From e90f75c9e91427aa6254a89a10c619a17e2be594 Mon Sep 17 00:00:00 2001
From: chenjiankun <chenjiankun1@huawei.com>
Date: Thu, 28 Mar 2024 17:16:11 +0800
Subject: [PATCH] docker: fix CVE-2024-29018

libnet: Don't forward to upstream resolvers on internal nw

Commit cbc2a71 makes `connect` syscall fail fast when a container is
only attached to an internal network. Thanks to that, if such a
container tries to resolve an "external" domain, the embedded resolver
returns an error immediately instead of waiting for a timeout.

This commit makes sure the embedded resolver doesn't even try to forward
to upstream servers.

Conflict:libnetwork/resolver.go,sandbox_dns_unix.go
Reference:https://github.com/moby/moby/commit/790c3039d0ca5ed86ecd099b4b571496607628bc
---
 .../vendor/github.com/docker/libnetwork/endpoint.go | 13 ++++++++++++-
 .../vendor/github.com/docker/libnetwork/resolver.go |  9 +++++++++
 .../docker/libnetwork/sandbox_dns_unix.go           |  6 +++++-
 3 files changed, 26 insertions(+), 2 deletions(-)

diff --git a/components/engine/vendor/github.com/docker/libnetwork/endpoint.go b/components/engine/vendor/github.com/docker/libnetwork/endpoint.go
index 822f88bd3..914169199 100644
--- a/components/engine/vendor/github.com/docker/libnetwork/endpoint.go
+++ b/components/engine/vendor/github.com/docker/libnetwork/endpoint.go
@@ -550,7 +550,13 @@ 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.
+	if sb.resolver != nil {
+		sb.resolver.SetForwardingPolicy(currentExtEp != nil)
+	}
+
+	moveExtConn := currentExtEp != extEp
 
 	if moveExtConn {
 		if extEp != nil {
@@ -786,6 +792,11 @@ 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.
+	if sb.resolver != nil {
+		sb.resolver.SetForwardingPolicy(extEp != nil)
+	}
+
 	if moveExtConn && extEp != nil {
 		logrus.Debugf("Programming external connectivity on endpoint %s (%s)", extEp.Name(), extEp.ID())
 		extN, err := extEp.getNetworkFromStore()
diff --git a/components/engine/vendor/github.com/docker/libnetwork/resolver.go b/components/engine/vendor/github.com/docker/libnetwork/resolver.go
index 04afe7a1d..0e44352d7 100644
--- a/components/engine/vendor/github.com/docker/libnetwork/resolver.go
+++ b/components/engine/vendor/github.com/docker/libnetwork/resolver.go
@@ -24,6 +24,9 @@ type Resolver interface {
 	// SetupFunc() provides the setup function that should be run
 	// in the container's network namespace.
 	SetupFunc(int) func()
+	// SetForwardingPolicy re-configures the embedded DNS resolver to either enable or disable forwarding DNS queries to
+	// external servers.
+	SetForwardingPolicy(bool)
 	// NameServer() returns the IP of the DNS resolver for the
 	// containers.
 	NameServer() string
@@ -196,6 +199,12 @@ 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) {
+	r.proxyDNS = policy
+}
+
 func (r *resolver) NameServer() string {
 	return r.listenAddress
 }
diff --git a/components/engine/vendor/github.com/docker/libnetwork/sandbox_dns_unix.go b/components/engine/vendor/github.com/docker/libnetwork/sandbox_dns_unix.go
index db1b66b19..484987a83 100644
--- a/components/engine/vendor/github.com/docker/libnetwork/sandbox_dns_unix.go
+++ b/components/engine/vendor/github.com/docker/libnetwork/sandbox_dns_unix.go
@@ -27,7 +27,11 @@ const (
 func (sb *sandbox) startResolver(restore bool) {
 	sb.resolverOnce.Do(func() {
 		var err error
-		sb.resolver = NewResolver(resolverIPSandbox, true, sb.Key(), sb)
+		// The resolver is started with proxyDNS=false if the sandbox does not currently
+		// have a gateway. So, if the Sandbox is only connected to an 'internal' network,
+		// it will not forward DNS requests to external resolvers. The resolver's
+		// proxyDNS setting is then updated as network Endpoints are added/removed.
+		sb.resolver = NewResolver(resolverIPSandbox, sb.getGatewayEndpoint() != nil, sb.Key(), sb)
 		defer func() {
 			if err != nil {
 				sb.resolver = nil
-- 
2.33.0

