From 59f0ffc77571ea11f44de14a74fb7cca268e586b Mon Sep 17 00:00:00 2001 From: lvxiangcong Date: Mon, 22 Apr 2024 14:55:45 +0800 Subject: [PATCH] fix CVE-2024-32473 (cherry picked from commit 8b5f202b7d73b9cfbf374e171fc33f47c4c6eae0) --- 0002-fix-cve-2024-32473.patch | 185 ++++++++++++++++++++++++++++++++++ moby.spec | 8 +- 2 files changed, 191 insertions(+), 2 deletions(-) create mode 100644 0002-fix-cve-2024-32473.patch diff --git a/0002-fix-cve-2024-32473.patch b/0002-fix-cve-2024-32473.patch new file mode 100644 index 0000000..0499aba --- /dev/null +++ b/0002-fix-cve-2024-32473.patch @@ -0,0 +1,185 @@ +From ed2e2bd1cb6491cc76e6681db122844400762a2e Mon Sep 17 00:00:00 2001 +From: lvxiangcong +Date: Mon, 22 Apr 2024 10:59:42 +0800 +Subject: [PATCH] fix cve-2024-32473 + +--- + integration/network/ipvlan/ipvlan_test.go | 25 +++++++++++++++ + integration/network/macvlan/macvlan_test.go | 29 +++++++++++++++++ + integration/networking/bridge_test.go | 35 +++++++++++++++++++++ + libnetwork/osl/interface_linux.go | 21 ++++++++----- + 4 files changed, 103 insertions(+), 7 deletions(-) + +diff --git a/integration/network/ipvlan/ipvlan_test.go b/integration/network/ipvlan/ipvlan_test.go +index 130b60d..adb42cd 100644 +--- a/integration/network/ipvlan/ipvlan_test.go ++++ b/integration/network/ipvlan/ipvlan_test.go +@@ -87,6 +87,9 @@ func TestDockerNetworkIpvlan(t *testing.T) { + }, { + name: "Addressing", + test: testIpvlanAddressing, ++ }, { ++ name: "NoIPv6", ++ test: testIpvlanNoIPv6, + }, + } { + +@@ -438,3 +441,25 @@ func ipvlanKernelSupport(t *testing.T) bool { + + return ipvlanSupported + } ++ ++// Check that an ipvlan interface with '--ipv6=false' doesn't get kernel-assigned ++// IPv6 addresses, but the loopback interface does still have an IPv6 address ('::1'). ++func testIpvlanNoIPv6(t *testing.T, ctx context.Context, client dclient.APIClient) { ++ const netName = "ipvlannet" ++ net.CreateNoError(ctx, t, client, netName, net.WithIPvlan("", "l3")) ++ assert.Check(t, n.IsNetworkAvailable(ctx, client, netName)) ++ ++ id := container.Run(ctx, t, client, container.WithNetworkMode(netName)) ++ ++ loRes := container.ExecT(ctx, t, client, id, []string{"ip", "a", "show", "dev", "lo"}) ++ assert.Check(t, is.Contains(loRes.Combined(), " inet ")) ++ assert.Check(t, is.Contains(loRes.Combined(), " inet6 ")) ++ ++ eth0Res := container.ExecT(ctx, t, client, id, []string{"ip", "a", "show", "dev", "eth0"}) ++ assert.Check(t, is.Contains(eth0Res.Combined(), " inet ")) ++ assert.Check(t, !strings.Contains(eth0Res.Combined(), " inet6 "), ++ "result.Combined(): %s", eth0Res.Combined()) ++ ++ sysctlRes := container.ExecT(ctx, t, client, id, []string{"sysctl", "-n", "net.ipv6.conf.eth0.disable_ipv6"}) ++ assert.Check(t, is.Equal(strings.TrimSpace(sysctlRes.Combined()), "1")) ++} +diff --git a/integration/network/macvlan/macvlan_test.go b/integration/network/macvlan/macvlan_test.go +index c41373c..c907ffb 100644 +--- a/integration/network/macvlan/macvlan_test.go ++++ b/integration/network/macvlan/macvlan_test.go +@@ -71,6 +71,9 @@ func TestDockerNetworkMacvlan(t *testing.T) { + }, { + name: "Addressing", + test: testMacvlanAddressing, ++ }, { ++ name: "NoIPv6", ++ test: testMacvlanNoIPv6, + }, + } { + tc := tc +@@ -275,3 +278,29 @@ func testMacvlanAddressing(ctx context.Context, client client.APIClient) func(*t + assert.Check(t, strings.Contains(result.Combined(), "default via 2001:db8:abca::254 dev eth0")) + } + } ++ ++// Check that a macvlan interface with '--ipv6=false' doesn't get kernel-assigned ++// IPv6 addresses, but the loopback interface does still have an IPv6 address ('::1'). ++func testMacvlanNoIPv6(t *testing.T, ctx context.Context, client client.APIClient) { ++ const netName = "macvlannet" ++ ++ net.CreateNoError(ctx, t, client, netName, ++ net.WithMacvlan(""), ++ net.WithOption("macvlan_mode", "bridge"), ++ ) ++ assert.Check(t, n.IsNetworkAvailable(ctx, client, netName)) ++ ++ id := container.Run(ctx, t, client, container.WithNetworkMode(netName)) ++ ++ loRes := container.ExecT(ctx, t, client, id, []string{"ip", "a", "show", "dev", "lo"}) ++ assert.Check(t, is.Contains(loRes.Combined(), " inet ")) ++ assert.Check(t, is.Contains(loRes.Combined(), " inet6 ")) ++ ++ eth0Res := container.ExecT(ctx, t, client, id, []string{"ip", "a", "show", "dev", "eth0"}) ++ assert.Check(t, is.Contains(eth0Res.Combined(), " inet ")) ++ assert.Check(t, !strings.Contains(eth0Res.Combined(), " inet6 "), ++ "result.Combined(): %s", eth0Res.Combined()) ++ ++ sysctlRes := container.ExecT(ctx, t, client, id, []string{"sysctl", "-n", "net.ipv6.conf.eth0.disable_ipv6"}) ++ assert.Check(t, is.Equal(strings.TrimSpace(sysctlRes.Combined()), "1")) ++} +diff --git a/integration/networking/bridge_test.go b/integration/networking/bridge_test.go +index e3d1fe2..7dfcd28 100644 +--- a/integration/networking/bridge_test.go ++++ b/integration/networking/bridge_test.go +@@ -3,6 +3,7 @@ package networking + import ( + "context" + "fmt" ++ "strings" + "testing" + "time" + +@@ -477,3 +478,37 @@ func TestDefaultBridgeAddresses(t *testing.T) { + }) + } + } ++ ++// Check that an interface to an '--ipv6=false' network has no IPv6 ++// address - either IPAM assigned, or kernel-assigned LL, but the loopback ++// interface does still have an IPv6 address ('::1'). ++func TestNonIPv6Network(t *testing.T) { ++ skip.If(t, testEnv.DaemonInfo.OSType == "windows") ++ ++ ctx := setupTest(t) ++ d := daemon.New(t) ++ d.StartWithBusybox(ctx, t) ++ defer d.Stop(t) ++ ++ c := d.NewClientT(t) ++ defer c.Close() ++ ++ const netName = "testnet" ++ network.CreateNoError(ctx, t, c, netName) ++ defer network.RemoveNoError(ctx, t, c, netName) ++ ++ id := container.Run(ctx, t, c, container.WithNetworkMode(netName)) ++ defer c.ContainerRemove(ctx, id, containertypes.RemoveOptions{Force: true}) ++ ++ loRes := container.ExecT(ctx, t, c, id, []string{"ip", "a", "show", "dev", "lo"}) ++ assert.Check(t, is.Contains(loRes.Combined(), " inet ")) ++ assert.Check(t, is.Contains(loRes.Combined(), " inet6 ")) ++ ++ eth0Res := container.ExecT(ctx, t, c, id, []string{"ip", "a", "show", "dev", "eth0"}) ++ assert.Check(t, is.Contains(eth0Res.Combined(), " inet ")) ++ assert.Check(t, !strings.Contains(eth0Res.Combined(), " inet6 "), ++ "result.Combined(): %s", eth0Res.Combined()) ++ ++ sysctlRes := container.ExecT(ctx, t, c, id, []string{"sysctl", "-n", "net.ipv6.conf.eth0.disable_ipv6"}) ++ assert.Check(t, is.Equal(strings.TrimSpace(sysctlRes.Combined()), "1")) ++} +diff --git a/libnetwork/osl/interface_linux.go b/libnetwork/osl/interface_linux.go +index 27e079d..e559ab9 100644 +--- a/libnetwork/osl/interface_linux.go ++++ b/libnetwork/osl/interface_linux.go +@@ -367,17 +367,24 @@ func setInterfaceIP(nlh *netlink.Handle, iface netlink.Link, i *Interface) error + } + + func setInterfaceIPv6(nlh *netlink.Handle, iface netlink.Link, i *Interface) error { +- if i.AddressIPv6() == nil { ++ addr := i.AddressIPv6() ++ // IPv6 must be enabled on the interface if and only if the network is ++ // IPv6-enabled. For an interface on an IPv4-only network, if IPv6 isn't ++ // disabled, the interface will be put into IPv6 multicast groups making ++ // it unexpectedly susceptible to NDP cache poisoning, route injection, etc. ++ // (At present, there will always be a pre-configured IPv6 address if the ++ // network is IPv6-enabled.) ++ if err := setIPv6(i.ns.path, i.DstName(), addr != nil); err != nil { ++ return fmt.Errorf("failed to configure ipv6: %v", err) ++ } ++ if addr == nil { + return nil + } +- if err := checkRouteConflict(nlh, i.AddressIPv6(), netlink.FAMILY_V6); err != nil { ++ if err := checkRouteConflict(nlh, addr, netlink.FAMILY_V6); err != nil { + return err + } +- if err := setIPv6(i.ns.path, i.DstName(), true); err != nil { +- return fmt.Errorf("failed to enable ipv6: %v", err) +- } +- ipAddr := &netlink.Addr{IPNet: i.AddressIPv6(), Label: "", Flags: syscall.IFA_F_NODAD} +- return nlh.AddrAdd(iface, ipAddr) ++ nlAddr := &netlink.Addr{IPNet: addr, Label: "", Flags: syscall.IFA_F_NODAD} ++ return nlh.AddrAdd(iface, nlAddr) + } + + func setInterfaceLinkLocalIPs(nlh *netlink.Handle, iface netlink.Link, i *Interface) error { +-- +2.25.1 + diff --git a/moby.spec b/moby.spec index f7e0e33..ea0399d 100644 --- a/moby.spec +++ b/moby.spec @@ -7,7 +7,7 @@ Name: moby Version: 25.0.3 -Release: 2 +Release: 3 Summary: The open-source application container engine License: ASL 2.0 URL: https://www.docker.com @@ -21,6 +21,7 @@ Source3: docker.service Source4: docker.socket Source5: docker.sysconfig Patch0000: 0001-fix-cve-2024-29018.patch +Patch0001: 0002-fix-cve-2024-32473.patch Requires: %{name}-engine = %{version}-%{release} @@ -92,7 +93,7 @@ Docker client binary and related utilities %setup -q -n %{_source_client} %setup -q -T -n %{_source_engine} -b 1 %patch0000 -p1 - +%patch0001 -p1 %setup -q -T -n %{_source_docker_init} -b 2 %build @@ -194,6 +195,9 @@ fi %systemd_postun_with_restart docker.service %changelog +* Mon Apr 22 2024 lvxiangcong - 25.0.3-3 +- DESC:fix cve-2024-32473 + * Wed Apr 17 2024 lvxiangcong - 25.0.3-2 - DESC:fix cve-2024-29018 -- Gitee