213 lines
7.1 KiB
Diff
213 lines
7.1 KiB
Diff
From a9b119d4858a40936583262cb8d878036a0171dd Mon Sep 17 00:00:00 2001
|
|
From: root <root@localhost.localdomain>
|
|
Date: Sun, 14 Apr 2024 19:46:56 +0800
|
|
Subject: [PATCH] fix cve-2024-29018
|
|
|
|
---
|
|
integration/networking/bridge_test.go | 20 +++++++++++++++-----
|
|
libnetwork/endpoint.go | 8 +++++++-
|
|
libnetwork/resolver.go | 21 +++++++++++++++++----
|
|
libnetwork/sandbox_dns_unix.go | 5 +----
|
|
4 files changed, 40 insertions(+), 14 deletions(-)
|
|
|
|
diff --git a/integration/networking/bridge_test.go b/integration/networking/bridge_test.go
|
|
index e3d1fe2..4be3e55 100644
|
|
--- a/integration/networking/bridge_test.go
|
|
+++ b/integration/networking/bridge_test.go
|
|
@@ -36,7 +36,8 @@ func TestBridgeICC(t *testing.T) {
|
|
name string
|
|
bridgeOpts []func(*types.NetworkCreate)
|
|
ctr1MacAddress string
|
|
- linkLocal bool
|
|
+ isIPv6 bool
|
|
+ isLinkLocal bool
|
|
pingHost string
|
|
}{
|
|
{
|
|
@@ -55,6 +56,7 @@ func TestBridgeICC(t *testing.T) {
|
|
network.WithIPv6(),
|
|
network.WithIPAM("fdf1:a844:380c:b200::/64", "fdf1:a844:380c:b200::1"),
|
|
},
|
|
+ isIPv6: true,
|
|
},
|
|
{
|
|
name: "IPv6 ULA on internal network",
|
|
@@ -74,7 +76,8 @@ func TestBridgeICC(t *testing.T) {
|
|
// 2. the one dynamically assigned by the IPAM driver.
|
|
network.WithIPAM("fe80::/64", "fe80::1"),
|
|
},
|
|
- linkLocal: true,
|
|
+ isLinkLocal: true,
|
|
+ isIPv6: true,
|
|
},
|
|
{
|
|
name: "IPv6 link-local address on internal network",
|
|
@@ -84,7 +87,8 @@ func TestBridgeICC(t *testing.T) {
|
|
// See the note above about link-local addresses.
|
|
network.WithIPAM("fe80::/64", "fe80::1"),
|
|
},
|
|
- linkLocal: true,
|
|
+ isLinkLocal: true,
|
|
+ isIPv6: true,
|
|
},
|
|
{
|
|
// As for 'LL non-internal', but ping the container by name instead of by address
|
|
@@ -122,6 +126,7 @@ func TestBridgeICC(t *testing.T) {
|
|
// specify one here to hardcode the SLAAC LL address below.
|
|
ctr1MacAddress: "02:42:ac:11:00:02",
|
|
pingHost: "fe80::42:acff:fe11:2%eth0",
|
|
+ isIPv6: true,
|
|
},
|
|
{
|
|
name: "IPv6 internal network with SLAAC LL address",
|
|
@@ -133,6 +138,7 @@ func TestBridgeICC(t *testing.T) {
|
|
// specify one here to hardcode the SLAAC LL address below.
|
|
ctr1MacAddress: "02:42:ac:11:00:02",
|
|
pingHost: "fe80::42:acff:fe11:2%eth0",
|
|
+ isIPv6: true,
|
|
},
|
|
}
|
|
|
|
@@ -162,7 +168,7 @@ func TestBridgeICC(t *testing.T) {
|
|
|
|
pingHost := tc.pingHost
|
|
if pingHost == "" {
|
|
- if tc.linkLocal {
|
|
+ if tc.isLinkLocal {
|
|
inspect := container.Inspect(ctx, t, c, id1)
|
|
pingHost = inspect.NetworkSettings.Networks[bridgeName].GlobalIPv6Address + "%eth0"
|
|
} else {
|
|
@@ -170,7 +176,11 @@ func TestBridgeICC(t *testing.T) {
|
|
}
|
|
}
|
|
|
|
- pingCmd := []string{"ping", "-c1", "-W3", pingHost}
|
|
+ pingCmd := []string{"ping", "-c1", "-W3"}
|
|
+ if tc.isIPv6 {
|
|
+ pingCmd = append(pingCmd, "-6")
|
|
+ }
|
|
+ pingCmd = append(pingCmd, pingHost)
|
|
|
|
ctr2Name := fmt.Sprintf("ctr-icc-%d-2", tcID)
|
|
attachCtx, cancel := context.WithTimeout(ctx, 5*time.Second)
|
|
diff --git a/libnetwork/endpoint.go b/libnetwork/endpoint.go
|
|
index d9c257d..93ddbc9 100644
|
|
--- a/libnetwork/endpoint.go
|
|
+++ b/libnetwork/endpoint.go
|
|
@@ -538,8 +538,11 @@ func (ep *Endpoint) sbJoin(sb *Sandbox, options ...EndpointOption) (err error) {
|
|
return sb.setupDefaultGW()
|
|
}
|
|
|
|
- moveExtConn := sb.getGatewayEndpoint() != extEp
|
|
+ currentExtEp := sb.getGatewayEndpoint()
|
|
+ // Enable upstream forwarding if the sandbox gained external connectivity.
|
|
+ sb.resolver.SetForwardingPolicy(currentExtEp != nil)
|
|
|
|
+ moveExtConn := currentExtEp != extEp
|
|
if moveExtConn {
|
|
if extEp != nil {
|
|
log.G(context.TODO()).Debugf("Revoking external connectivity on endpoint %s (%s)", extEp.Name(), extEp.ID())
|
|
@@ -735,6 +738,9 @@ func (ep *Endpoint) sbLeave(sb *Sandbox, force bool, options ...EndpointOption)
|
|
|
|
// New endpoint providing external connectivity for the sandbox
|
|
extEp = sb.getGatewayEndpoint()
|
|
+ // Disable upstream forwarding if the sandbox lost external connectivity.
|
|
+ sb.resolver.SetForwardingPolicy(extEp != nil)
|
|
+
|
|
if moveExtConn && extEp != nil {
|
|
log.G(context.TODO()).Debugf("Programming external connectivity on endpoint %s (%s)", extEp.Name(), extEp.ID())
|
|
extN, err := extEp.getNetworkFromStore()
|
|
diff --git a/libnetwork/resolver.go b/libnetwork/resolver.go
|
|
index 9df2154..6da595c 100644
|
|
--- a/libnetwork/resolver.go
|
|
+++ b/libnetwork/resolver.go
|
|
@@ -9,6 +9,7 @@ import (
|
|
"strconv"
|
|
"strings"
|
|
"sync"
|
|
+ "sync/atomic"
|
|
"time"
|
|
|
|
"github.com/containerd/log"
|
|
@@ -75,7 +76,7 @@ type Resolver struct {
|
|
tcpListen *net.TCPListener
|
|
err error
|
|
listenAddress string
|
|
- proxyDNS bool
|
|
+ proxyDNS atomic.Bool
|
|
startCh chan struct{}
|
|
logger *log.Entry
|
|
|
|
@@ -85,15 +86,17 @@ type Resolver struct {
|
|
|
|
// NewResolver creates a new instance of the Resolver
|
|
func NewResolver(address string, proxyDNS bool, backend DNSBackend) *Resolver {
|
|
- return &Resolver{
|
|
+ r := &Resolver{
|
|
backend: backend,
|
|
- proxyDNS: proxyDNS,
|
|
listenAddress: address,
|
|
err: fmt.Errorf("setup not done yet"),
|
|
startCh: make(chan struct{}, 1),
|
|
fwdSem: semaphore.NewWeighted(maxConcurrent),
|
|
logInverval: rate.Sometimes{Interval: logInterval},
|
|
}
|
|
+ r.proxyDNS.Store(proxyDNS)
|
|
+
|
|
+ return r
|
|
}
|
|
|
|
func (r *Resolver) log(ctx context.Context) *log.Entry {
|
|
@@ -103,6 +106,8 @@ func (r *Resolver) log(ctx context.Context) *log.Entry {
|
|
return r.logger
|
|
}
|
|
|
|
+
|
|
+
|
|
// SetupFunc returns the setup function that should be run in the container's
|
|
// network namespace.
|
|
func (r *Resolver) SetupFunc(port int) func() {
|
|
@@ -194,6 +199,14 @@ func (r *Resolver) SetExtServers(extDNS []extDNSEntry) {
|
|
}
|
|
}
|
|
|
|
+// SetForwardingPolicy re-configures the embedded DNS resolver to either enable or disable forwarding DNS queries to
|
|
+// external servers.
|
|
+func (r *Resolver) SetForwardingPolicy(policy bool) {
|
|
+ if r != nil {
|
|
+ r.proxyDNS.Store(policy)
|
|
+ }
|
|
+}
|
|
+
|
|
// NameServer returns the IP of the DNS resolver for the containers.
|
|
func (r *Resolver) NameServer() string {
|
|
return r.listenAddress
|
|
@@ -421,7 +434,7 @@ func (r *Resolver) serveDNS(w dns.ResponseWriter, query *dns.Msg) {
|
|
return
|
|
}
|
|
|
|
- if r.proxyDNS {
|
|
+ if r.proxyDNS.Load(){
|
|
// If the user sets ndots > 0 explicitly and the query is
|
|
// in the root domain don't forward it out. We will return
|
|
// failure and let the client retry with the search domain
|
|
diff --git a/libnetwork/sandbox_dns_unix.go b/libnetwork/sandbox_dns_unix.go
|
|
index e30f394..505c5f5 100644
|
|
--- a/libnetwork/sandbox_dns_unix.go
|
|
+++ b/libnetwork/sandbox_dns_unix.go
|
|
@@ -30,10 +30,7 @@ const (
|
|
func (sb *Sandbox) startResolver(restore bool) {
|
|
sb.resolverOnce.Do(func() {
|
|
var err error
|
|
- // The embedded resolver is always started with proxyDNS set as true, even when the sandbox is only attached to
|
|
- // an internal network. This way, it's the driver responsibility to make sure `connect` syscall fails fast when
|
|
- // no external connectivity is available (eg. by not setting a default gateway).
|
|
- sb.resolver = NewResolver(resolverIPSandbox, true, sb)
|
|
+ sb.resolver = NewResolver(resolverIPSandbox, sb.getGatewayEndpoint() != nil, sb)
|
|
defer func() {
|
|
if err != nil {
|
|
sb.resolver = nil
|
|
--
|
|
2.27.0
|
|
|