From 3b9d49647afad0caaf0c162fa50da9fc1ff6b518 Mon Sep 17 00:00:00 2001 From: zhangxiaoyu Date: Tue, 4 Jul 2023 12:01:33 +0800 Subject: [PATCH] fix CVE-2022-3294 Signed-off-by: zhangxiaoyu (cherry picked from commit e484fb6520ede427eb0def6b34f9e130c9d02730) --- 0014-fix-node-address-validation.patch | 245 +++++++++++++++++++++++++ kubernetes.spec | 9 +- 2 files changed, 253 insertions(+), 1 deletion(-) create mode 100644 0014-fix-node-address-validation.patch diff --git a/0014-fix-node-address-validation.patch b/0014-fix-node-address-validation.patch new file mode 100644 index 0000000..06e4bb8 --- /dev/null +++ b/0014-fix-node-address-validation.patch @@ -0,0 +1,245 @@ +From 78d552efe620879599509ff0f9b04b8764e1878f Mon Sep 17 00:00:00 2001 +From: Andrew Sy Kim +Date: Mon, 7 Nov 2022 10:22:44 -0500 +Subject: [PATCH] fix node address validation + +Signed-off-by: Andrew Sy Kim +--- + .../core/node/storage/storage_test.go | 171 +++++++++++++++++- + pkg/registry/core/node/strategy.go | 8 +- + 2 files changed, 174 insertions(+), 5 deletions(-) + +diff --git a/pkg/registry/core/node/storage/storage_test.go b/pkg/registry/core/node/storage/storage_test.go +index af228b8a..89df2edf 100644 +--- a/pkg/registry/core/node/storage/storage_test.go ++++ b/pkg/registry/core/node/storage/storage_test.go +@@ -17,6 +17,7 @@ limitations under the License. + package storage + + import ( ++ "fmt" + "testing" + + "k8s.io/apimachinery/pkg/api/resource" +@@ -24,11 +25,14 @@ import ( + "k8s.io/apimachinery/pkg/fields" + "k8s.io/apimachinery/pkg/labels" + "k8s.io/apimachinery/pkg/runtime" ++ genericapirequest "k8s.io/apiserver/pkg/endpoints/request" + "k8s.io/apiserver/pkg/registry/generic" + genericregistrytest "k8s.io/apiserver/pkg/registry/generic/testing" ++ "k8s.io/apiserver/pkg/registry/rest" + etcd3testing "k8s.io/apiserver/pkg/storage/etcd3/testing" + api "k8s.io/kubernetes/pkg/apis/core" + kubeletclient "k8s.io/kubernetes/pkg/kubelet/client" ++ proxyutil "k8s.io/kubernetes/pkg/proxy/util" + "k8s.io/kubernetes/pkg/registry/registrytest" + ) + +@@ -40,7 +44,10 @@ func newStorage(t *testing.T) (*REST, *etcd3testing.EtcdTestServer) { + DeleteCollectionWorkers: 1, + ResourcePrefix: "nodes", + } +- storage, err := NewStorage(restOptions, kubeletclient.KubeletClientConfig{}, nil) ++ storage, err := NewStorage(restOptions, kubeletclient.KubeletClientConfig{ ++ Port: 10250, ++ PreferredAddressTypes: []string{string(api.NodeInternalIP)}, ++ }, nil) + if err != nil { + t.Fatal(err) + } +@@ -156,3 +163,165 @@ func TestShortNames(t *testing.T) { + expected := []string{"no"} + registrytest.AssertShortNames(t, storage, expected) + } ++ ++func TestResourceLocation(t *testing.T) { ++ testCases := []struct { ++ name string ++ node api.Node ++ query string ++ location string ++ err error ++ }{ ++ { ++ name: "proxyable hostname with default port", ++ node: api.Node{ ++ ObjectMeta: metav1.ObjectMeta{Name: "node0"}, ++ Status: api.NodeStatus{ ++ Addresses: []api.NodeAddress{ ++ { ++ Type: api.NodeInternalIP, ++ Address: "10.0.0.1", ++ }, ++ }, ++ }, ++ }, ++ query: "node0", ++ location: "10.0.0.1:10250", ++ err: nil, ++ }, ++ { ++ name: "proxyable hostname with kubelet port in query", ++ node: api.Node{ ++ ObjectMeta: metav1.ObjectMeta{Name: "node0"}, ++ Status: api.NodeStatus{ ++ Addresses: []api.NodeAddress{ ++ { ++ Type: api.NodeInternalIP, ++ Address: "10.0.0.1", ++ }, ++ }, ++ }, ++ }, ++ query: "node0:5000", ++ location: "10.0.0.1:5000", ++ err: nil, ++ }, ++ { ++ name: "proxyable hostname with kubelet port in status", ++ node: api.Node{ ++ ObjectMeta: metav1.ObjectMeta{Name: "node0"}, ++ Status: api.NodeStatus{ ++ Addresses: []api.NodeAddress{ ++ { ++ Type: api.NodeInternalIP, ++ Address: "10.0.0.1", ++ }, ++ }, ++ DaemonEndpoints: api.NodeDaemonEndpoints{ ++ KubeletEndpoint: api.DaemonEndpoint{ ++ Port: 5000, ++ }, ++ }, ++ }, ++ }, ++ query: "node0", ++ location: "10.0.0.1:5000", ++ err: nil, ++ }, ++ { ++ name: "non-proxyable hostname with default port", ++ node: api.Node{ ++ ObjectMeta: metav1.ObjectMeta{Name: "node0"}, ++ Status: api.NodeStatus{ ++ Addresses: []api.NodeAddress{ ++ { ++ Type: api.NodeInternalIP, ++ Address: "127.0.0.1", ++ }, ++ }, ++ }, ++ }, ++ query: "node0", ++ location: "", ++ err: proxyutil.ErrAddressNotAllowed, ++ }, ++ { ++ name: "non-proxyable hostname with kubelet port in query", ++ node: api.Node{ ++ ObjectMeta: metav1.ObjectMeta{Name: "node0"}, ++ Status: api.NodeStatus{ ++ Addresses: []api.NodeAddress{ ++ { ++ Type: api.NodeInternalIP, ++ Address: "127.0.0.1", ++ }, ++ }, ++ }, ++ }, ++ query: "node0:5000", ++ location: "", ++ err: proxyutil.ErrAddressNotAllowed, ++ }, ++ { ++ name: "non-proxyable hostname with kubelet port in status", ++ node: api.Node{ ++ ObjectMeta: metav1.ObjectMeta{Name: "node0"}, ++ Status: api.NodeStatus{ ++ Addresses: []api.NodeAddress{ ++ { ++ Type: api.NodeInternalIP, ++ Address: "127.0.0.1", ++ }, ++ }, ++ DaemonEndpoints: api.NodeDaemonEndpoints{ ++ KubeletEndpoint: api.DaemonEndpoint{ ++ Port: 443, ++ }, ++ }, ++ }, ++ }, ++ query: "node0", ++ location: "", ++ err: proxyutil.ErrAddressNotAllowed, ++ }, ++ } ++ ++ for _, testCase := range testCases { ++ t.Run(testCase.name, func(t *testing.T) { ++ storage, server := newStorage(t) ++ defer server.Terminate(t) ++ defer storage.Store.DestroyFunc() ++ ++ ctx := genericapirequest.WithNamespace(genericapirequest.NewDefaultContext(), fmt.Sprintf("namespace-%s", testCase.name)) ++ key, _ := storage.KeyFunc(ctx, testCase.node.Name) ++ if err := storage.Storage.Create(ctx, key, &testCase.node, nil, 0, false); err != nil { ++ t.Fatalf("unexpected error: %v", err) ++ } ++ ++ redirector := rest.Redirector(storage) ++ location, _, err := redirector.ResourceLocation(ctx, testCase.query) ++ ++ if err != nil && testCase.err != nil { ++ if err.Error() != testCase.err.Error() { ++ t.Fatalf("Unexpected error: %v, expected: %v", err, testCase.err) ++ } ++ ++ return ++ } ++ ++ if err != nil && testCase.err == nil { ++ t.Fatalf("Unexpected error: %v, expected: %v", err, testCase.err) ++ } else if err == nil && testCase.err != nil { ++ t.Fatalf("Expected error but got none, err: %v", testCase.err) ++ } ++ ++ if location == nil { ++ t.Errorf("Unexpected nil resource location: %v", location) ++ } ++ ++ if location.Host != testCase.location { ++ t.Errorf("Unexpected host: expected %v, but got %v", testCase.location, location.Host) ++ } ++ }) ++ } ++} +diff --git a/pkg/registry/core/node/strategy.go b/pkg/registry/core/node/strategy.go +index aaddb69e..59096e56 100644 +--- a/pkg/registry/core/node/strategy.go ++++ b/pkg/registry/core/node/strategy.go +@@ -242,6 +242,10 @@ func ResourceLocation(getter ResourceGetter, connection client.ConnectionInfoGet + return nil, nil, err + } + ++ if err := proxyutil.IsProxyableHostname(ctx, &net.Resolver{}, info.Hostname); err != nil { ++ return nil, nil, errors.NewBadRequest(err.Error()) ++ } ++ + // We check if we want to get a default Kubelet's transport. It happens if either: + // - no port is specified in request (Kubelet's port is default) + // - the requested port matches the kubelet port for this node +@@ -254,10 +258,6 @@ func ResourceLocation(getter ResourceGetter, connection client.ConnectionInfoGet + nil + } + +- if err := proxyutil.IsProxyableHostname(ctx, &net.Resolver{}, info.Hostname); err != nil { +- return nil, nil, errors.NewBadRequest(err.Error()) +- } +- + // Otherwise, return the requested scheme and port, and the proxy transport + return &url.URL{Scheme: schemeReq, Host: net.JoinHostPort(info.Hostname, portReq)}, proxyTransport, nil + } +-- +2.25.1 + diff --git a/kubernetes.spec b/kubernetes.spec index 497c65b..03f7e8b 100644 --- a/kubernetes.spec +++ b/kubernetes.spec @@ -3,7 +3,7 @@ Name: kubernetes Version: 1.20.2 -Release: 18 +Release: 19 Summary: Container cluster management License: ASL 2.0 URL: https://k8s.io/kubernetes @@ -37,6 +37,7 @@ Patch6009: 0010-Escape-terminal-special-characters-in-kubectl-112553.patch Patch6010: 0011-Remove-Endpoints-write-access-from-aggregated-edit-r.patch Patch6011: 0012-Return-error-for-localhost-seccomp-type-with-no-loca.patch Patch6012: 0013-Validate-etcd-paths.patch +Patch6013: 0014-fix-node-address-validation.patch %description Container cluster management. @@ -268,6 +269,12 @@ getent passwd kube >/dev/null || useradd -r -g kube -d / -s /sbin/nologin \ %systemd_postun kubelet kube-proxy %changelog +* Tue Jul 04 2023 zhangxiaoyu - 1.20.2-19 +- Type:bugfix +- CVE:NA +- SUG:NA +- DESC:fix CVE-2022-3294 + * Thu Jun 29 2023 zhangxiaoyu - 1.20.2-18 - Type:bugfix - CVE:NA -- Gitee