mirror of
https://github.com/coredns/coredns.git
synced 2026-10-09 03:55:21 -04:00
plugin/k8s_external: Fixes a nil pointer dereference panic when upstream lookup returns no response (#8518)
* plugin/k8s_external: Fixes a nil pointer dereference panic when upstream lookup returns no response When a CNAME-hosted service is resolved, k8s_external performs internal upstream lookups for the target name. Upstream.Lookup can return a nil message with a nil error when the internal self-query's plugin chain returns a ClientWrite rcode without writing a response (for example acl's drop action), and the a/aaaa/srv handlers then dereference resp.Answer on a nil resp and panic. Guard all four lookups with err == nil && resp != nil, matching the nil checks already used in plugin/backend_lookup.go and the guard recently added to plugin/dns64 (#8511). Signed-off-by: zjncs <18910855655@163.com> * plugin/k8s_external: silence unused-parameter lint in nil upstream test The CI lint flagged the test handler's unused 'w' parameter. Rename it to '_' so golangci-lint (revive unused-parameter) passes. No behavior change. Signed-off-by: zjncs <18910855655@163.com> --------- Signed-off-by: zjncs <18910855655@163.com>
This commit is contained in:
@@ -4,9 +4,12 @@ import (
|
||||
"context"
|
||||
"testing"
|
||||
|
||||
"github.com/coredns/coredns/core/dnsserver"
|
||||
"github.com/coredns/coredns/plugin"
|
||||
"github.com/coredns/coredns/plugin/kubernetes"
|
||||
"github.com/coredns/coredns/plugin/kubernetes/object"
|
||||
"github.com/coredns/coredns/plugin/pkg/dnstest"
|
||||
"github.com/coredns/coredns/plugin/pkg/upstream"
|
||||
"github.com/coredns/coredns/plugin/test"
|
||||
"github.com/coredns/coredns/request"
|
||||
|
||||
@@ -55,6 +58,49 @@ func TestExternal(t *testing.T) {
|
||||
}
|
||||
}
|
||||
|
||||
// TestExternalCNAMENilUpstreamResponse checks that a CNAME-hosted service does not
|
||||
// panic when the internal upstream lookup returns no response, e.g. when a plugin
|
||||
// like acl's drop action returns success without writing.
|
||||
func TestExternalCNAMENilUpstreamResponse(t *testing.T) {
|
||||
k := kubernetes.New([]string{"cluster.local."})
|
||||
k.Namespaces = map[string]struct{}{"testns": {}}
|
||||
k.APIConn = &external{}
|
||||
|
||||
cfg := &dnsserver.Config{
|
||||
Zone: ".",
|
||||
Plugin: []plugin.Plugin{
|
||||
func(plugin.Handler) plugin.Handler {
|
||||
return plugin.HandlerFunc(func(_ context.Context, _ dns.ResponseWriter, _ *dns.Msg) (int, error) {
|
||||
return dns.RcodeSuccess, nil
|
||||
})
|
||||
},
|
||||
},
|
||||
}
|
||||
srv, err := dnsserver.NewServer("", []*dnsserver.Config{cfg})
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
ctx := context.WithValue(context.Background(), dnsserver.Key{}, srv)
|
||||
|
||||
e := New()
|
||||
e.Zones = []string{"example.com."}
|
||||
e.headless = true
|
||||
e.Next = test.NextHandler(dns.RcodeSuccess, nil)
|
||||
e.externalFunc = k.External
|
||||
e.externalAddrFunc = externalAddress
|
||||
e.externalSerialFunc = externalSerial
|
||||
e.upstream = upstream.New()
|
||||
|
||||
m := new(dns.Msg)
|
||||
m.SetQuestion("svc12.testns.example.com.", dns.TypeA)
|
||||
w := dnstest.NewRecorder(&test.ResponseWriter{})
|
||||
|
||||
_, err = e.ServeDNS(ctx, w, m)
|
||||
if err != nil {
|
||||
t.Fatalf("Expected no error, got %v", err)
|
||||
}
|
||||
}
|
||||
|
||||
var tests = []test.Case{
|
||||
// PTR reverse lookup
|
||||
{
|
||||
|
||||
Reference in New Issue
Block a user