All of lore.kernel.org
 help / color / mirror / Atom feed
* Re: [meta-virtualization][zeus][PATCH] kubernetes: fix three CVE issues
       [not found] <16267A948D96B982.15129@lists.yoctoproject.org>
@ 2020-07-30  8:35 ` Zhixiong Chi
  2020-07-30 19:54   ` Bruce Ashfield
  0 siblings, 1 reply; 4+ messages in thread
From: Zhixiong Chi @ 2020-07-30  8:35 UTC (permalink / raw)
  To: bruce.ashfield, meta-virtualization

[-- Attachment #1: Type: text/plain, Size: 22892 bytes --]

Hi Bruce,

After the last CVE-1019-11254 patch merged, this patch can be applied
successfully.

Thanks.

On 2020/7/30 下午4:30, Zhixiong Chi wrote:
> Backport the patches from the upstream:
> https://github.com/kubernetes/kubernetes.git  [branch: release-1.16]
> ba3ca4929ed3887c95f94fcf97610f3449446804
> 68750fefd3df76b7b008ef7b18e8acd18d5c2f2e
> d22a61e21d677f7527bc8a4aeb3288c5e11dd49b
>
> Signed-off-by: Zhixiong Chi <zhixiong.chi@windriver.com>
> ---
>  .../kubernetes/kubernetes/CVE-2020-8557.patch | 179 ++++++++++++++++++
>  .../kubernetes/kubernetes/CVE-2020-8558.patch |  51 +++++
>  .../kubernetes/kubernetes/CVE-2020-8559.patch | 148 +++++++++++++++
>  .../kubernetes/kubernetes_git.bb              |   3 +
>  4 files changed, 381 insertions(+)
>  create mode 100644 recipes-containers/kubernetes/kubernetes/CVE-2020-8557.patch
>  create mode 100644 recipes-containers/kubernetes/kubernetes/CVE-2020-8558.patch
>  create mode 100644 recipes-containers/kubernetes/kubernetes/CVE-2020-8559.patch
>
> diff --git a/recipes-containers/kubernetes/kubernetes/CVE-2020-8557.patch b/recipes-containers/kubernetes/kubernetes/CVE-2020-8557.patch
> new file mode 100644
> index 0000000..dd70627
> --- /dev/null
> +++ b/recipes-containers/kubernetes/kubernetes/CVE-2020-8557.patch
> @@ -0,0 +1,179 @@
> +From 68750fefd3df76b7b008ef7b18e8acd18d5c2f2e Mon Sep 17 00:00:00 2001
> +From: Joel Smith <joesmith@redhat.com>
> +Date: Thu, 14 May 2020 20:09:58 -0600
> +Subject: [PATCH] Include pod /etc/hosts in ephemeral storage calculation for
> + eviction
> +
> +CVE: CVE-2020-8557
> +Upstream-Status: Backport [https://github.com/kubernetes/kubernetes.git branch:release-1.16]
> +Signed-off-by: Zhixiong Chi <zhixiong.chi@windriver.com>
> +---
> + src/import/pkg/kubelet/eviction/BUILD               | 1 +
> + src/import/pkg/kubelet/eviction/eviction_manager.go | 7 ++++++-
> + src/import/pkg/kubelet/eviction/helpers.go          | 9 ++++++++-
> + src/import/pkg/kubelet/kubelet.go                   | 3 ++-
> + src/import/pkg/kubelet/kubelet_pods.go              | 7 ++++++-
> + src/import/pkg/kubelet/kubelet_test.go              | 3 ++-
> + src/import/pkg/kubelet/runonce_test.go              | 3 ++-
> + 7 files changed, 27 insertions(+), 6 deletions(-)
> +
> +diff --git a/src/import/pkg/kubelet/eviction/BUILD b/src/import/pkg/kubelet/eviction/BUILD
> +index 2209b26d7d4..e8c2241e075 100644
> +--- a/src/import/pkg/kubelet/eviction/BUILD
> ++++ b/src/import/pkg/kubelet/eviction/BUILD
> +@@ -66,6 +66,7 @@ go_library(
> +         "//staging/src/k8s.io/api/core/v1:go_default_library",
> +         "//staging/src/k8s.io/apimachinery/pkg/api/resource:go_default_library",
> +         "//staging/src/k8s.io/apimachinery/pkg/apis/meta/v1:go_default_library",
> ++        "//staging/src/k8s.io/apimachinery/pkg/types:go_default_library",
> +         "//staging/src/k8s.io/apimachinery/pkg/util/clock:go_default_library",
> +         "//staging/src/k8s.io/apiserver/pkg/util/feature:go_default_library",
> +         "//staging/src/k8s.io/client-go/tools/record:go_default_library",
> +diff --git a/src/import/pkg/kubelet/eviction/eviction_manager.go b/src/import/pkg/kubelet/eviction/eviction_manager.go
> +index 4ef2a89dce6..ca218cb942f 100644
> +--- a/src/import/pkg/kubelet/eviction/eviction_manager.go
> ++++ b/src/import/pkg/kubelet/eviction/eviction_manager.go
> +@@ -26,6 +26,7 @@ import (
> + 
> + 	v1 "k8s.io/api/core/v1"
> + 	"k8s.io/apimachinery/pkg/api/resource"
> ++	"k8s.io/apimachinery/pkg/types"
> + 	"k8s.io/apimachinery/pkg/util/clock"
> + 	utilfeature "k8s.io/apiserver/pkg/util/feature"
> + 	"k8s.io/client-go/tools/record"
> +@@ -90,6 +91,8 @@ type managerImpl struct {
> + 	thresholdNotifiers []ThresholdNotifier
> + 	// thresholdsLastUpdated is the last time the thresholdNotifiers were updated.
> + 	thresholdsLastUpdated time.Time
> ++	// etcHostsPath is a function that will get the etc-hosts file's path for a pod given its UID
> ++	etcHostsPath func(podUID types.UID) string
> + }
> + 
> + // ensure it implements the required interface
> +@@ -106,6 +109,7 @@ func NewManager(
> + 	recorder record.EventRecorder,
> + 	nodeRef *v1.ObjectReference,
> + 	clock clock.Clock,
> ++	etcHostsPath func(types.UID) string,
> + ) (Manager, lifecycle.PodAdmitHandler) {
> + 	manager := &managerImpl{
> + 		clock:                        clock,
> +@@ -121,6 +125,7 @@ func NewManager(
> + 		thresholdsFirstObservedAt:    thresholdsObservedAt{},
> + 		dedicatedImageFs:             nil,
> + 		thresholdNotifiers:           []ThresholdNotifier{},
> ++		etcHostsPath:                 etcHostsPath,
> + 	}
> + 	return manager, manager
> + }
> +@@ -503,7 +508,7 @@ func (m *managerImpl) podEphemeralStorageLimitEviction(podStats statsapi.PodStat
> + 	} else {
> + 		fsStatsSet = []fsStatsType{fsStatsRoot, fsStatsLogs, fsStatsLocalVolumeSource}
> + 	}
> +-	podEphemeralUsage, err := podLocalEphemeralStorageUsage(podStats, pod, fsStatsSet)
> ++	podEphemeralUsage, err := podLocalEphemeralStorageUsage(podStats, pod, fsStatsSet, m.etcHostsPath(pod.UID))
> + 	if err != nil {
> + 		klog.Errorf("eviction manager: error getting pod disk usage %v", err)
> + 		return false
> +diff --git a/src/import/pkg/kubelet/eviction/helpers.go b/src/import/pkg/kubelet/eviction/helpers.go
> +index dfdb8ce3b60..41c55855aad 100644
> +--- a/src/import/pkg/kubelet/eviction/helpers.go
> ++++ b/src/import/pkg/kubelet/eviction/helpers.go
> +@@ -18,6 +18,7 @@ package eviction
> + 
> + import (
> + 	"fmt"
> ++	"os"
> + 	"sort"
> + 	"strconv"
> + 	"strings"
> +@@ -415,7 +416,7 @@ func localEphemeralVolumeNames(pod *v1.Pod) []string {
> + }
> + 
> + // podLocalEphemeralStorageUsage aggregates pod local ephemeral storage usage and inode consumption for the specified stats to measure.
> +-func podLocalEphemeralStorageUsage(podStats statsapi.PodStats, pod *v1.Pod, statsToMeasure []fsStatsType) (v1.ResourceList, error) {
> ++func podLocalEphemeralStorageUsage(podStats statsapi.PodStats, pod *v1.Pod, statsToMeasure []fsStatsType, etcHostsPath string) (v1.ResourceList, error) {
> + 	disk := resource.Quantity{Format: resource.BinarySI}
> + 	inodes := resource.Quantity{Format: resource.DecimalSI}
> + 
> +@@ -429,6 +430,12 @@ func podLocalEphemeralStorageUsage(podStats statsapi.PodStats, pod *v1.Pod, stat
> + 		disk.Add(podLocalVolumeUsageList[v1.ResourceEphemeralStorage])
> + 		inodes.Add(podLocalVolumeUsageList[resourceInodes])
> + 	}
> ++	if len(etcHostsPath) > 0 {
> ++		if stat, err := os.Stat(etcHostsPath); err == nil {
> ++			disk.Add(*resource.NewQuantity(int64(stat.Size()), resource.BinarySI))
> ++			inodes.Add(*resource.NewQuantity(int64(1), resource.DecimalSI))
> ++		}
> ++	}
> + 	return v1.ResourceList{
> + 		v1.ResourceEphemeralStorage: disk,
> + 		resourceInodes:              inodes,
> +diff --git a/src/import/pkg/kubelet/kubelet.go b/src/import/pkg/kubelet/kubelet.go
> +index c2acd358e59..8da5d0f2e92 100644
> +--- a/src/import/pkg/kubelet/kubelet.go
> ++++ b/src/import/pkg/kubelet/kubelet.go
> +@@ -831,8 +831,9 @@ func NewMainKubelet(kubeCfg *kubeletconfiginternal.KubeletConfiguration,
> + 	klet.backOff = flowcontrol.NewBackOff(backOffPeriod, MaxContainerBackOff)
> + 	klet.podKillingCh = make(chan *kubecontainer.PodPair, podKillingChannelCapacity)
> + 
> ++	etcHostsPathFunc := func(podUID types.UID) string { return getEtcHostsPath(klet.getPodDir(podUID)) }
> + 	// setup eviction manager
> +-	evictionManager, evictionAdmitHandler := eviction.NewManager(klet.resourceAnalyzer, evictionConfig, killPodNow(klet.podWorkers, kubeDeps.Recorder), klet.podManager.GetMirrorPodByPod, klet.imageManager, klet.containerGC, kubeDeps.Recorder, nodeRef, klet.clock)
> ++	evictionManager, evictionAdmitHandler := eviction.NewManager(klet.resourceAnalyzer, evictionConfig, killPodNow(klet.podWorkers, kubeDeps.Recorder), klet.podManager.GetMirrorPodByPod, klet.imageManager, klet.containerGC, kubeDeps.Recorder, nodeRef, klet.clock, etcHostsPathFunc)
> + 
> + 	klet.evictionManager = evictionManager
> + 	klet.admitHandlers.AddPodAdmitHandler(evictionAdmitHandler)
> +diff --git a/src/import/pkg/kubelet/kubelet_pods.go b/src/import/pkg/kubelet/kubelet_pods.go
> +index 013d0f55aea..02857d4b5b3 100644
> +--- a/src/import/pkg/kubelet/kubelet_pods.go
> ++++ b/src/import/pkg/kubelet/kubelet_pods.go
> +@@ -291,10 +291,15 @@ func translateMountPropagation(mountMode *v1.MountPropagationMode) (runtimeapi.M
> + 	}
> + }
> + 
> ++// getEtcHostsPath returns the full host-side path to a pod's generated /etc/hosts file
> ++func getEtcHostsPath(podDir string) string {
> ++	return path.Join(podDir, "etc-hosts")
> ++}
> ++
> + // makeHostsMount makes the mountpoint for the hosts file that the containers
> + // in a pod are injected with.
> + func makeHostsMount(podDir, podIP, hostName, hostDomainName string, hostAliases []v1.HostAlias, useHostNetwork bool) (*kubecontainer.Mount, error) {
> +-	hostsFilePath := path.Join(podDir, "etc-hosts")
> ++	hostsFilePath := getEtcHostsPath(podDir)
> + 	if err := ensureHostsFile(hostsFilePath, podIP, hostName, hostDomainName, hostAliases, useHostNetwork); err != nil {
> + 		return nil, err
> + 	}
> +diff --git a/src/import/pkg/kubelet/kubelet_test.go b/src/import/pkg/kubelet/kubelet_test.go
> +index 80c6dcb73b6..9fb417fbb9d 100644
> +--- a/src/import/pkg/kubelet/kubelet_test.go
> ++++ b/src/import/pkg/kubelet/kubelet_test.go
> +@@ -291,8 +291,9 @@ func newTestKubeletWithImageList(
> + 		UID:       types.UID(kubelet.nodeName),
> + 		Namespace: "",
> + 	}
> ++	etcHostsPathFunc := func(podUID types.UID) string { return getEtcHostsPath(kubelet.getPodDir(podUID)) }
> + 	// setup eviction manager
> +-	evictionManager, evictionAdmitHandler := eviction.NewManager(kubelet.resourceAnalyzer, eviction.Config{}, killPodNow(kubelet.podWorkers, fakeRecorder), kubelet.podManager.GetMirrorPodByPod, kubelet.imageManager, kubelet.containerGC, fakeRecorder, nodeRef, kubelet.clock)
> ++	evictionManager, evictionAdmitHandler := eviction.NewManager(kubelet.resourceAnalyzer, eviction.Config{}, killPodNow(kubelet.podWorkers, fakeRecorder), kubelet.podManager.GetMirrorPodByPod, kubelet.imageManager, kubelet.containerGC, fakeRecorder, nodeRef, kubelet.clock, etcHostsPathFunc)
> + 
> + 	kubelet.evictionManager = evictionManager
> + 	kubelet.admitHandlers.AddPodAdmitHandler(evictionAdmitHandler)
> +diff --git a/src/import/pkg/kubelet/runonce_test.go b/src/import/pkg/kubelet/runonce_test.go
> +index 7239133e481..9b162c11702 100644
> +--- a/src/import/pkg/kubelet/runonce_test.go
> ++++ b/src/import/pkg/kubelet/runonce_test.go
> +@@ -125,7 +125,8 @@ func TestRunOnce(t *testing.T) {
> + 		return nil
> + 	}
> + 	fakeMirrodPodFunc := func(*v1.Pod) (*v1.Pod, bool) { return nil, false }
> +-	evictionManager, evictionAdmitHandler := eviction.NewManager(kb.resourceAnalyzer, eviction.Config{}, fakeKillPodFunc, fakeMirrodPodFunc, nil, nil, kb.recorder, nodeRef, kb.clock)
> ++	etcHostsPathFunc := func(podUID types.UID) string { return getEtcHostsPath(kb.getPodDir(podUID)) }
> ++	evictionManager, evictionAdmitHandler := eviction.NewManager(kb.resourceAnalyzer, eviction.Config{}, fakeKillPodFunc, fakeMirrodPodFunc, nil, nil, kb.recorder, nodeRef, kb.clock, etcHostsPathFunc)
> + 
> + 	kb.evictionManager = evictionManager
> + 	kb.admitHandlers.AddPodAdmitHandler(evictionAdmitHandler)
> +-- 
> +2.17.0
> +
> diff --git a/recipes-containers/kubernetes/kubernetes/CVE-2020-8558.patch b/recipes-containers/kubernetes/kubernetes/CVE-2020-8558.patch
> new file mode 100644
> index 0000000..9eeed26
> --- /dev/null
> +++ b/recipes-containers/kubernetes/kubernetes/CVE-2020-8558.patch
> @@ -0,0 +1,51 @@
> +From d22a61e21d677f7527bc8a4aeb3288c5e11dd49b Mon Sep 17 00:00:00 2001
> +From: Casey Callendrello <cdc@redhat.com>
> +Date: Fri, 29 May 2020 13:03:37 +0200
> +Subject: [PATCH] kubelet: block non-forwarded packets from crossing the
> + localhost boundary
> +
> +We set route_localnet so that host-network processes can connect to
> +<127.0.0.1:NodePort> and it still works. This, however, is too
> +permissive.
> +
> +So, block martians that are not already in conntrack.
> +
> +See: #90259
> +Signed-off-by: Casey Callendrello <cdc@redhat.com>
> +CVE: CVE-2020-8558
> +Upstream-Status: Backport [https://github.com/kubernetes/kubernetes.git branch:release-1.16]
> +Signed-off-by: Zhixiong Chi <zhixiong.chi@windriver.com>
> +---
> + src/import/pkg/kubelet/kubelet_network_linux.go | 16 ++++++++++++++++
> + 1 file changed, 16 insertions(+)
> +
> +diff --git a/src/import/pkg/kubelet/kubelet_network_linux.go b/src/import/pkg/kubelet/kubelet_network_linux.go
> +index 1c9ad46b989..d18ab75a053 100644
> +--- a/src/import/pkg/kubelet/kubelet_network_linux.go
> ++++ b/src/import/pkg/kubelet/kubelet_network_linux.go
> +@@ -68,6 +68,22 @@ func (kl *Kubelet) syncNetworkUtil() {
> + 		klog.Errorf("Failed to ensure rule to drop packet marked by %v in %v chain %v: %v", KubeMarkDropChain, utiliptables.TableFilter, KubeFirewallChain, err)
> + 		return
> + 	}
> ++
> ++	// drop all non-local packets to localhost if they're not part of an existing
> ++	// forwarded connection. See #90259
> ++	if !kl.iptClient.IsIpv6() { // ipv6 doesn't have this issue
> ++		if _, err := kl.iptClient.EnsureRule(utiliptables.Append, utiliptables.TableFilter, KubeFirewallChain,
> ++			"-m", "comment", "--comment", "block incoming localnet connections",
> ++			"--dst", "127.0.0.0/8",
> ++			"!", "--src", "127.0.0.0/8",
> ++			"-m", "conntrack",
> ++			"!", "--ctstate", "RELATED,ESTABLISHED,DNAT",
> ++			"-j", "DROP"); err != nil {
> ++			klog.Errorf("Failed to ensure rule to drop invalid localhost packets in %v chain %v: %v", utiliptables.TableFilter, KubeFirewallChain, err)
> ++			return
> ++		}
> ++	}
> ++
> + 	if _, err := kl.iptClient.EnsureRule(utiliptables.Prepend, utiliptables.TableFilter, utiliptables.ChainOutput, "-j", string(KubeFirewallChain)); err != nil {
> + 		klog.Errorf("Failed to ensure that %s chain %s jumps to %s: %v", utiliptables.TableFilter, utiliptables.ChainOutput, KubeFirewallChain, err)
> + 		return
> +-- 
> +2.17.0
> +
> diff --git a/recipes-containers/kubernetes/kubernetes/CVE-2020-8559.patch b/recipes-containers/kubernetes/kubernetes/CVE-2020-8559.patch
> new file mode 100644
> index 0000000..f47826d
> --- /dev/null
> +++ b/recipes-containers/kubernetes/kubernetes/CVE-2020-8559.patch
> @@ -0,0 +1,148 @@
> +From ba3ca4929ed3887c95f94fcf97610f3449446804 Mon Sep 17 00:00:00 2001
> +From: Tim Allclair <tallclair@google.com>
> +Date: Wed, 17 Jun 2020 11:09:02 -0700
> +Subject: [PATCH] Don't return proxied redirects to the client
> +
> +CVE: CVE-2020-8559
> +Upstream-Status: Backport [https://github.com/kubernetes/kubernetes.git branch:release-1.16]
> +Signed-off-by: Zhixiong Chi <zhixiong.chi@windriver.com>
> +---
> + .../k8s.io/apimachinery/pkg/util/net/http.go  |  2 +-
> + .../apimachinery/pkg/util/net/http_test.go    | 12 ++---
> + .../pkg/util/proxy/upgradeaware.go            | 10 ++++
> + .../pkg/util/proxy/upgradeaware_test.go       | 47 ++++++++++++++++++-
> + 4 files changed, 62 insertions(+), 9 deletions(-)
> +
> +diff --git a/src/import/staging/src/k8s.io/apimachinery/pkg/util/net/http.go b/src/import/staging/src/k8s.io/apimachinery/pkg/util/net/http.go
> +index bd79d6c4a09..c24fbc6921c 100644
> +--- a/src/import/staging/src/k8s.io/apimachinery/pkg/util/net/http.go
> ++++ b/src/import/staging/src/k8s.io/apimachinery/pkg/util/net/http.go
> +@@ -431,7 +431,7 @@ redirectLoop:
> + 
> + 		// Only follow redirects to the same host. Otherwise, propagate the redirect response back.
> + 		if requireSameHostRedirects && location.Hostname() != originalLocation.Hostname() {
> +-			break redirectLoop
> ++			return nil, nil, fmt.Errorf("hostname mismatch: expected %s, found %s", originalLocation.Hostname(), location.Hostname())
> + 		}
> + 
> + 		// Reset the connection.
> +diff --git a/src/import/staging/src/k8s.io/apimachinery/pkg/util/net/http_test.go b/src/import/staging/src/k8s.io/apimachinery/pkg/util/net/http_test.go
> +index 4e4e317b9a4..142b80f1a84 100644
> +--- a/src/import/staging/src/k8s.io/apimachinery/pkg/util/net/http_test.go
> ++++ b/src/import/staging/src/k8s.io/apimachinery/pkg/util/net/http_test.go
> +@@ -330,13 +330,13 @@ func TestConnectWithRedirects(t *testing.T) {
> + 		redirects:   []string{"/1", "/2", "/3", "/4", "/5", "/6", "/7", "/8", "/9", "/10"},
> + 		expectError: true,
> + 	}, {
> +-		desc:              "redirect to different host are prevented",
> +-		redirects:         []string{"http://example.com/foo"},
> +-		expectedRedirects: 0,
> ++		desc:        "redirect to different host are prevented",
> ++		redirects:   []string{"http://example.com/foo"},
> ++		expectError: true,
> + 	}, {
> +-		desc:              "multiple redirect to different host forbidden",
> +-		redirects:         []string{"/1", "/2", "/3", "http://example.com/foo"},
> +-		expectedRedirects: 3,
> ++		desc:        "multiple redirect to different host forbidden",
> ++		redirects:   []string{"/1", "/2", "/3", "http://example.com/foo"},
> ++		expectError: true,
> + 	}, {
> + 		desc:              "redirect to different port is allowed",
> + 		redirects:         []string{"http://HOST/foo"},
> +diff --git a/src/import/staging/src/k8s.io/apimachinery/pkg/util/proxy/upgradeaware.go b/src/import/staging/src/k8s.io/apimachinery/pkg/util/proxy/upgradeaware.go
> +index fcdc76a0529..3a02919d135 100644
> +--- a/src/import/staging/src/k8s.io/apimachinery/pkg/util/proxy/upgradeaware.go
> ++++ b/src/import/staging/src/k8s.io/apimachinery/pkg/util/proxy/upgradeaware.go
> +@@ -298,6 +298,16 @@ func (h *UpgradeAwareHandler) tryUpgrade(w http.ResponseWriter, req *http.Reques
> + 		rawResponse = headerBytes
> + 	}
> + 
> ++	// If the backend did not upgrade the request, return an error to the client. If the response was
> ++	// an error, the error is forwarded directly after the connection is hijacked. Otherwise, just
> ++	// return a generic error here.
> ++	if backendHTTPResponse.StatusCode != http.StatusSwitchingProtocols && backendHTTPResponse.StatusCode < 400 {
> ++		err := fmt.Errorf("invalid upgrade response: status code %d", backendHTTPResponse.StatusCode)
> ++		klog.Errorf("Proxy upgrade error: %v", err)
> ++		h.Responder.Error(w, req, err)
> ++		return true
> ++	}
> ++
> + 	// Once the connection is hijacked, the ErrorResponder will no longer work, so
> + 	// hijacking should be the last step in the upgrade.
> + 	requestHijacker, ok := w.(http.Hijacker)
> +diff --git a/src/import/staging/src/k8s.io/apimachinery/pkg/util/proxy/upgradeaware_test.go b/src/import/staging/src/k8s.io/apimachinery/pkg/util/proxy/upgradeaware_test.go
> +index 7d14f6534a8..236362373cd 100644
> +--- a/src/import/staging/src/k8s.io/apimachinery/pkg/util/proxy/upgradeaware_test.go
> ++++ b/src/import/staging/src/k8s.io/apimachinery/pkg/util/proxy/upgradeaware_test.go
> +@@ -493,7 +493,7 @@ func (r *noErrorsAllowed) Error(w http.ResponseWriter, req *http.Request, err er
> + 	r.t.Error(err)
> + }
> + 
> +-func TestProxyUpgradeErrorResponse(t *testing.T) {
> ++func TestProxyUpgradeConnectionErrorResponse(t *testing.T) {
> + 	var (
> + 		responder   *fakeResponder
> + 		expectedErr = errors.New("EXPECTED")
> +@@ -541,7 +541,7 @@ func TestProxyUpgradeErrorResponse(t *testing.T) {
> + 
> + func TestProxyUpgradeErrorResponseTerminates(t *testing.T) {
> + 	for _, intercept := range []bool{true, false} {
> +-		for _, code := range []int{200, 400, 500} {
> ++		for _, code := range []int{400, 500} {
> + 			t.Run(fmt.Sprintf("intercept=%v,code=%v", intercept, code), func(t *testing.T) {
> + 				// Set up a backend server
> + 				backend := http.NewServeMux()
> +@@ -601,6 +601,49 @@ func TestProxyUpgradeErrorResponseTerminates(t *testing.T) {
> + 	}
> + }
> + 
> ++func TestProxyUpgradeErrorResponse(t *testing.T) {
> ++	for _, intercept := range []bool{true, false} {
> ++		for _, code := range []int{200, 300, 302, 307} {
> ++			t.Run(fmt.Sprintf("intercept=%v,code=%v", intercept, code), func(t *testing.T) {
> ++				// Set up a backend server
> ++				backend := http.NewServeMux()
> ++				backend.Handle("/hello", http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
> ++					http.Redirect(w, r, "https://example.com/there", code)
> ++				}))
> ++				backendServer := httptest.NewServer(backend)
> ++				defer backendServer.Close()
> ++				backendServerURL, _ := url.Parse(backendServer.URL)
> ++				backendServerURL.Path = "/hello"
> ++
> ++				// Set up a proxy pointing to a specific path on the backend
> ++				proxyHandler := NewUpgradeAwareHandler(backendServerURL, nil, false, false, &fakeResponder{t: t})
> ++				proxyHandler.InterceptRedirects = intercept
> ++				proxyHandler.RequireSameHostRedirects = true
> ++				proxy := httptest.NewServer(proxyHandler)
> ++				defer proxy.Close()
> ++				proxyURL, _ := url.Parse(proxy.URL)
> ++
> ++				conn, err := net.Dial("tcp", proxyURL.Host)
> ++				require.NoError(t, err)
> ++				bufferedReader := bufio.NewReader(conn)
> ++
> ++				// Send upgrade request resulting in a non-101 response from the backend
> ++				req, _ := http.NewRequest("GET", "/", nil)
> ++				req.Header.Set(httpstream.HeaderConnection, httpstream.HeaderUpgrade)
> ++				require.NoError(t, req.Write(conn))
> ++				// Verify we get the correct response and full message body content
> ++				resp, err := http.ReadResponse(bufferedReader, nil)
> ++				require.NoError(t, err)
> ++				assert.Equal(t, fakeStatusCode, resp.StatusCode)
> ++				resp.Body.Close()
> ++
> ++				// clean up
> ++				conn.Close()
> ++			})
> ++		}
> ++	}
> ++}
> ++
> + func TestDefaultProxyTransport(t *testing.T) {
> + 	tests := []struct {
> + 		name,
> +-- 
> +2.17.0
> +
> diff --git a/recipes-containers/kubernetes/kubernetes_git.bb b/recipes-containers/kubernetes/kubernetes_git.bb
> index 941e0ca..fbe2dd8 100644
> --- a/recipes-containers/kubernetes/kubernetes_git.bb
> +++ b/recipes-containers/kubernetes/kubernetes_git.bb
> @@ -16,6 +16,9 @@ SRC_URI = "git://github.com/kubernetes/kubernetes.git;branch=release-1.16;name=k
>             file://CVE-2020-8552.patch \
>             file://CVE-2020-8555.patch \
>             file://CVE-2019-11254.patch \
> +           file://CVE-2020-8557.patch \
> +           file://CVE-2020-8558.patch \
> +           file://CVE-2020-8559.patch \
>            "
>
>  DEPENDS += "rsync-native \
>
> 

-- 
---------------------
Thanks,
Zhixiong Chi
Tel: +86-10-8477-7036


[-- Attachment #2: Type: text/html, Size: 25598 bytes --]

^ permalink raw reply	[flat|nested] 4+ messages in thread

* Re: [meta-virtualization][zeus][PATCH] kubernetes: fix three CVE issues
  2020-07-30  8:35 ` [meta-virtualization][zeus][PATCH] kubernetes: fix three CVE issues Zhixiong Chi
@ 2020-07-30 19:54   ` Bruce Ashfield
  2020-07-31  3:11     ` Zhixiong Chi
  0 siblings, 1 reply; 4+ messages in thread
From: Bruce Ashfield @ 2020-07-30 19:54 UTC (permalink / raw)
  To: Zhixiong Chi; +Cc: meta-virtualization


merged (and yes, I went back and picked up the older CVE patch as well).

But remember, when submitting these to an older branch, we should also
be summarizing if other branches are vulenerable.

In master, we'll update the version to pick up the change, but it is still
useful to know if it is fixed in the k8s release branch.

And in particular, I need the following answered: does dunfell need these
patches as well ?

Bruce

In message: Re: [meta-virtualization][zeus][PATCH] kubernetes: fix three CVE issues
on 30/07/2020 Zhixiong Chi wrote:

> Hi Bruce,
> 
> After the last CVE-1019-11254 patch merged, this patch can be applied
> successfully.
> 
> Thanks.
> 
> On 2020/7/30 下午4:30, Zhixiong Chi wrote:
> 
>     Backport the patches from the upstream:
>     https://github.com/kubernetes/kubernetes.git  [branch: release-1.16]
>     ba3ca4929ed3887c95f94fcf97610f3449446804
>     68750fefd3df76b7b008ef7b18e8acd18d5c2f2e
>     d22a61e21d677f7527bc8a4aeb3288c5e11dd49b
> 
>     Signed-off-by: Zhixiong Chi <zhixiong.chi@windriver.com>
>     ---
>      .../kubernetes/kubernetes/CVE-2020-8557.patch | 179 ++++++++++++++++++
>      .../kubernetes/kubernetes/CVE-2020-8558.patch |  51 +++++
>      .../kubernetes/kubernetes/CVE-2020-8559.patch | 148 +++++++++++++++
>      .../kubernetes/kubernetes_git.bb              |   3 +
>      4 files changed, 381 insertions(+)
>      create mode 100644 recipes-containers/kubernetes/kubernetes/CVE-2020-8557.patch
>      create mode 100644 recipes-containers/kubernetes/kubernetes/CVE-2020-8558.patch
>      create mode 100644 recipes-containers/kubernetes/kubernetes/CVE-2020-8559.patch
> 
>     diff --git a/recipes-containers/kubernetes/kubernetes/CVE-2020-8557.patch b/recipes-containers/kubernetes/kubernetes/CVE-2020-8557.patch
>     new file mode 100644
>     index 0000000..dd70627
>     --- /dev/null
>     +++ b/recipes-containers/kubernetes/kubernetes/CVE-2020-8557.patch
>     @@ -0,0 +1,179 @@
>     +From 68750fefd3df76b7b008ef7b18e8acd18d5c2f2e Mon Sep 17 00:00:00 2001
>     +From: Joel Smith <joesmith@redhat.com>
>     +Date: Thu, 14 May 2020 20:09:58 -0600
>     +Subject: [PATCH] Include pod /etc/hosts in ephemeral storage calculation for
>     + eviction
>     +
>     +CVE: CVE-2020-8557
>     +Upstream-Status: Backport [https://github.com/kubernetes/kubernetes.git branch:release-1.16]
>     +Signed-off-by: Zhixiong Chi <zhixiong.chi@windriver.com>
>     +---
>     + src/import/pkg/kubelet/eviction/BUILD               | 1 +
>     + src/import/pkg/kubelet/eviction/eviction_manager.go | 7 ++++++-
>     + src/import/pkg/kubelet/eviction/helpers.go          | 9 ++++++++-
>     + src/import/pkg/kubelet/kubelet.go                   | 3 ++-
>     + src/import/pkg/kubelet/kubelet_pods.go              | 7 ++++++-
>     + src/import/pkg/kubelet/kubelet_test.go              | 3 ++-
>     + src/import/pkg/kubelet/runonce_test.go              | 3 ++-
>     + 7 files changed, 27 insertions(+), 6 deletions(-)
>     +
>     +diff --git a/src/import/pkg/kubelet/eviction/BUILD b/src/import/pkg/kubelet/eviction/BUILD
>     +index 2209b26d7d4..e8c2241e075 100644
>     +--- a/src/import/pkg/kubelet/eviction/BUILD
>     ++++ b/src/import/pkg/kubelet/eviction/BUILD
>     +@@ -66,6 +66,7 @@ go_library(
>     +         "//staging/src/k8s.io/api/core/v1:go_default_library",
>     +         "//staging/src/k8s.io/apimachinery/pkg/api/resource:go_default_library",
>     +         "//staging/src/k8s.io/apimachinery/pkg/apis/meta/v1:go_default_library",
>     ++        "//staging/src/k8s.io/apimachinery/pkg/types:go_default_library",
>     +         "//staging/src/k8s.io/apimachinery/pkg/util/clock:go_default_library",
>     +         "//staging/src/k8s.io/apiserver/pkg/util/feature:go_default_library",
>     +         "//staging/src/k8s.io/client-go/tools/record:go_default_library",
>     +diff --git a/src/import/pkg/kubelet/eviction/eviction_manager.go b/src/import/pkg/kubelet/eviction/eviction_manager.go
>     +index 4ef2a89dce6..ca218cb942f 100644
>     +--- a/src/import/pkg/kubelet/eviction/eviction_manager.go
>     ++++ b/src/import/pkg/kubelet/eviction/eviction_manager.go
>     +@@ -26,6 +26,7 @@ import (
>     +
>     +       v1 "k8s.io/api/core/v1"
>     +       "k8s.io/apimachinery/pkg/api/resource"
>     ++      "k8s.io/apimachinery/pkg/types"
>     +       "k8s.io/apimachinery/pkg/util/clock"
>     +       utilfeature "k8s.io/apiserver/pkg/util/feature"
>     +       "k8s.io/client-go/tools/record"
>     +@@ -90,6 +91,8 @@ type managerImpl struct {
>     +       thresholdNotifiers []ThresholdNotifier
>     +       // thresholdsLastUpdated is the last time the thresholdNotifiers were updated.
>     +       thresholdsLastUpdated time.Time
>     ++      // etcHostsPath is a function that will get the etc-hosts file's path for a pod given its UID
>     ++      etcHostsPath func(podUID types.UID) string
>     + }
>     + 
>     + // ensure it implements the required interface
>     +@@ -106,6 +109,7 @@ func NewManager(
>     +       recorder record.EventRecorder,
>     +       nodeRef *v1.ObjectReference,
>     +       clock clock.Clock,
>     ++      etcHostsPath func(types.UID) string,
>     + ) (Manager, lifecycle.PodAdmitHandler) {
>     +       manager := &managerImpl{
>     +               clock:                        clock,
>     +@@ -121,6 +125,7 @@ func NewManager(
>     +               thresholdsFirstObservedAt:    thresholdsObservedAt{},
>     +               dedicatedImageFs:             nil,
>     +               thresholdNotifiers:           []ThresholdNotifier{},
>     ++              etcHostsPath:                 etcHostsPath,
>     +       }
>     +       return manager, manager
>     + }
>     +@@ -503,7 +508,7 @@ func (m *managerImpl) podEphemeralStorageLimitEviction(podStats statsapi.PodStat
>     +       } else {
>     +               fsStatsSet = []fsStatsType{fsStatsRoot, fsStatsLogs, fsStatsLocalVolumeSource}
>     +       }
>     +-      podEphemeralUsage, err := podLocalEphemeralStorageUsage(podStats, pod, fsStatsSet)
>     ++      podEphemeralUsage, err := podLocalEphemeralStorageUsage(podStats, pod, fsStatsSet, m.etcHostsPath(pod.UID))
>     +       if err != nil {
>     +               klog.Errorf("eviction manager: error getting pod disk usage %v", err)
>     +               return false
>     +diff --git a/src/import/pkg/kubelet/eviction/helpers.go b/src/import/pkg/kubelet/eviction/helpers.go
>     +index dfdb8ce3b60..41c55855aad 100644
>     +--- a/src/import/pkg/kubelet/eviction/helpers.go
>     ++++ b/src/import/pkg/kubelet/eviction/helpers.go
>     +@@ -18,6 +18,7 @@ package eviction
>     +
>     + import (
>     +       "fmt"
>     ++      "os"
>     +       "sort"
>     +       "strconv"
>     +       "strings"
>     +@@ -415,7 +416,7 @@ func localEphemeralVolumeNames(pod *v1.Pod) []string {
>     + }
>     +
>     + // podLocalEphemeralStorageUsage aggregates pod local ephemeral storage usage and inode consumption for the specified stats to measure.
>     +-func podLocalEphemeralStorageUsage(podStats statsapi.PodStats, pod *v1.Pod, statsToMeasure []fsStatsType) (v1.ResourceList, error) {
>     ++func podLocalEphemeralStorageUsage(podStats statsapi.PodStats, pod *v1.Pod, statsToMeasure []fsStatsType, etcHostsPath string) (v1.ResourceList, error) {
>     +       disk := resource.Quantity{Format: resource.BinarySI}
>     +       inodes := resource.Quantity{Format: resource.DecimalSI}
>     +
>     +@@ -429,6 +430,12 @@ func podLocalEphemeralStorageUsage(podStats statsapi.PodStats, pod *v1.Pod, stat
>     +               disk.Add(podLocalVolumeUsageList[v1.ResourceEphemeralStorage])
>     +               inodes.Add(podLocalVolumeUsageList[resourceInodes])
>     +       }
>     ++      if len(etcHostsPath) > 0 {
>     ++              if stat, err := os.Stat(etcHostsPath); err == nil {
>     ++                      disk.Add(*resource.NewQuantity(int64(stat.Size()), resource.BinarySI))
>     ++                      inodes.Add(*resource.NewQuantity(int64(1), resource.DecimalSI))
>     ++              }
>     ++      }
>     +       return v1.ResourceList{
>     +               v1.ResourceEphemeralStorage: disk,
>     +               resourceInodes:              inodes,
>     +diff --git a/src/import/pkg/kubelet/kubelet.go b/src/import/pkg/kubelet/kubelet.go
>     +index c2acd358e59..8da5d0f2e92 100644
>     +--- a/src/import/pkg/kubelet/kubelet.go
>     ++++ b/src/import/pkg/kubelet/kubelet.go
>     +@@ -831,8 +831,9 @@ func NewMainKubelet(kubeCfg *kubeletconfiginternal.KubeletConfiguration,
>     +       klet.backOff = flowcontrol.NewBackOff(backOffPeriod, MaxContainerBackOff)
>     +       klet.podKillingCh = make(chan *kubecontainer.PodPair, podKillingChannelCapacity)
>     +
>     ++      etcHostsPathFunc := func(podUID types.UID) string { return getEtcHostsPath(klet.getPodDir(podUID)) }
>     +       // setup eviction manager
>     +-      evictionManager, evictionAdmitHandler := eviction.NewManager(klet.resourceAnalyzer, evictionConfig, killPodNow(klet.podWorkers, kubeDeps.Recorder), klet.podManager.GetMirrorPodByPod, klet.imageManager, klet.containerGC, kubeDeps.Recorder, nodeRef, klet.clock)
>     ++      evictionManager, evictionAdmitHandler := eviction.NewManager(klet.resourceAnalyzer, evictionConfig, killPodNow(klet.podWorkers, kubeDeps.Recorder), klet.podManager.GetMirrorPodByPod, klet.imageManager, klet.containerGC, kubeDeps.Recorder, nodeRef, klet.clock, etcHostsPathFunc)
>     +
>     +       klet.evictionManager = evictionManager
>     +       klet.admitHandlers.AddPodAdmitHandler(evictionAdmitHandler)
>     +diff --git a/src/import/pkg/kubelet/kubelet_pods.go b/src/import/pkg/kubelet/kubelet_pods.go
>     +index 013d0f55aea..02857d4b5b3 100644
>     +--- a/src/import/pkg/kubelet/kubelet_pods.go
>     ++++ b/src/import/pkg/kubelet/kubelet_pods.go
>     +@@ -291,10 +291,15 @@ func translateMountPropagation(mountMode *v1.MountPropagationMode) (runtimeapi.M
>     +       }
>     + }
>     +
>     ++// getEtcHostsPath returns the full host-side path to a pod's generated /etc/hosts file
>     ++func getEtcHostsPath(podDir string) string {
>     ++      return path.Join(podDir, "etc-hosts")
>     ++}
>     ++
>     + // makeHostsMount makes the mountpoint for the hosts file that the containers
>     + // in a pod are injected with.
>     + func makeHostsMount(podDir, podIP, hostName, hostDomainName string, hostAliases []v1.HostAlias, useHostNetwork bool) (*kubecontainer.Mount, error) {
>     +-      hostsFilePath := path.Join(podDir, "etc-hosts")
>     ++      hostsFilePath := getEtcHostsPath(podDir)
>     +       if err := ensureHostsFile(hostsFilePath, podIP, hostName, hostDomainName, hostAliases, useHostNetwork); err != nil {
>     +               return nil, err
>     +       }
>     +diff --git a/src/import/pkg/kubelet/kubelet_test.go b/src/import/pkg/kubelet/kubelet_test.go
>     +index 80c6dcb73b6..9fb417fbb9d 100644
>     +--- a/src/import/pkg/kubelet/kubelet_test.go
>     ++++ b/src/import/pkg/kubelet/kubelet_test.go
>     +@@ -291,8 +291,9 @@ func newTestKubeletWithImageList(
>     +               UID:       types.UID(kubelet.nodeName),
>     +               Namespace: "",
>     +       }
>     ++      etcHostsPathFunc := func(podUID types.UID) string { return getEtcHostsPath(kubelet.getPodDir(podUID)) }
>     +       // setup eviction manager
>     +-      evictionManager, evictionAdmitHandler := eviction.NewManager(kubelet.resourceAnalyzer, eviction.Config{}, killPodNow(kubelet.podWorkers, fakeRecorder), kubelet.podManager.GetMirrorPodByPod, kubelet.imageManager, kubelet.containerGC, fakeRecorder, nodeRef, kubelet.clock)
>     ++      evictionManager, evictionAdmitHandler := eviction.NewManager(kubelet.resourceAnalyzer, eviction.Config{}, killPodNow(kubelet.podWorkers, fakeRecorder), kubelet.podManager.GetMirrorPodByPod, kubelet.imageManager, kubelet.containerGC, fakeRecorder, nodeRef, kubelet.clock, etcHostsPathFunc)
>     +
>     +       kubelet.evictionManager = evictionManager
>     +       kubelet.admitHandlers.AddPodAdmitHandler(evictionAdmitHandler)
>     +diff --git a/src/import/pkg/kubelet/runonce_test.go b/src/import/pkg/kubelet/runonce_test.go
>     +index 7239133e481..9b162c11702 100644
>     +--- a/src/import/pkg/kubelet/runonce_test.go
>     ++++ b/src/import/pkg/kubelet/runonce_test.go
>     +@@ -125,7 +125,8 @@ func TestRunOnce(t *testing.T) {
>     +               return nil
>     +       }
>     +       fakeMirrodPodFunc := func(*v1.Pod) (*v1.Pod, bool) { return nil, false }
>     +-      evictionManager, evictionAdmitHandler := eviction.NewManager(kb.resourceAnalyzer, eviction.Config{}, fakeKillPodFunc, fakeMirrodPodFunc, nil, nil, kb.recorder, nodeRef, kb.clock)
>     ++      etcHostsPathFunc := func(podUID types.UID) string { return getEtcHostsPath(kb.getPodDir(podUID)) }
>     ++      evictionManager, evictionAdmitHandler := eviction.NewManager(kb.resourceAnalyzer, eviction.Config{}, fakeKillPodFunc, fakeMirrodPodFunc, nil, nil, kb.recorder, nodeRef, kb.clock, etcHostsPathFunc)
>     +
>     +       kb.evictionManager = evictionManager
>     +       kb.admitHandlers.AddPodAdmitHandler(evictionAdmitHandler)
>     +--
>     +2.17.0
>     +
>     diff --git a/recipes-containers/kubernetes/kubernetes/CVE-2020-8558.patch b/recipes-containers/kubernetes/kubernetes/CVE-2020-8558.patch
>     new file mode 100644
>     index 0000000..9eeed26
>     --- /dev/null
>     +++ b/recipes-containers/kubernetes/kubernetes/CVE-2020-8558.patch
>     @@ -0,0 +1,51 @@
>     +From d22a61e21d677f7527bc8a4aeb3288c5e11dd49b Mon Sep 17 00:00:00 2001
>     +From: Casey Callendrello <cdc@redhat.com>
>     +Date: Fri, 29 May 2020 13:03:37 +0200
>     +Subject: [PATCH] kubelet: block non-forwarded packets from crossing the
>     + localhost boundary
>     +
>     +We set route_localnet so that host-network processes can connect to
>     +<127.0.0.1:NodePort> and it still works. This, however, is too
>     +permissive.
>     +
>     +So, block martians that are not already in conntrack.
>     +
>     +See: #90259
>     +Signed-off-by: Casey Callendrello <cdc@redhat.com>
>     +CVE: CVE-2020-8558
>     +Upstream-Status: Backport [https://github.com/kubernetes/kubernetes.git branch:release-1.16]
>     +Signed-off-by: Zhixiong Chi <zhixiong.chi@windriver.com>
>     +---
>     + src/import/pkg/kubelet/kubelet_network_linux.go | 16 ++++++++++++++++
>     + 1 file changed, 16 insertions(+)
>     +
>     +diff --git a/src/import/pkg/kubelet/kubelet_network_linux.go b/src/import/pkg/kubelet/kubelet_network_linux.go
>     +index 1c9ad46b989..d18ab75a053 100644
>     +--- a/src/import/pkg/kubelet/kubelet_network_linux.go
>     ++++ b/src/import/pkg/kubelet/kubelet_network_linux.go
>     +@@ -68,6 +68,22 @@ func (kl *Kubelet) syncNetworkUtil() {
>     +               klog.Errorf("Failed to ensure rule to drop packet marked by %v in %v chain %v: %v", KubeMarkDropChain, utiliptables.TableFilter, KubeFirewallChain, err)
>     +               return
>     +       }
>     ++
>     ++      // drop all non-local packets to localhost if they're not part of an existing
>     ++      // forwarded connection. See #90259
>     ++      if !kl.iptClient.IsIpv6() { // ipv6 doesn't have this issue
>     ++              if _, err := kl.iptClient.EnsureRule(utiliptables.Append, utiliptables.TableFilter, KubeFirewallChain,
>     ++                      "-m", "comment", "--comment", "block incoming localnet connections",
>     ++                      "--dst", "127.0.0.0/8",
>     ++                      "!", "--src", "127.0.0.0/8",
>     ++                      "-m", "conntrack",
>     ++                      "!", "--ctstate", "RELATED,ESTABLISHED,DNAT",
>     ++                      "-j", "DROP"); err != nil {
>     ++                      klog.Errorf("Failed to ensure rule to drop invalid localhost packets in %v chain %v: %v", utiliptables.TableFilter, KubeFirewallChain, err)
>     ++                      return
>     ++              }
>     ++      }
>     ++
>     +       if _, err := kl.iptClient.EnsureRule(utiliptables.Prepend, utiliptables.TableFilter, utiliptables.ChainOutput, "-j", string(KubeFirewallChain)); err != nil {
>     +               klog.Errorf("Failed to ensure that %s chain %s jumps to %s: %v", utiliptables.TableFilter, utiliptables.ChainOutput, KubeFirewallChain, err)
>     +               return
>     +--
>     +2.17.0
>     +
>     diff --git a/recipes-containers/kubernetes/kubernetes/CVE-2020-8559.patch b/recipes-containers/kubernetes/kubernetes/CVE-2020-8559.patch
>     new file mode 100644
>     index 0000000..f47826d
>     --- /dev/null
>     +++ b/recipes-containers/kubernetes/kubernetes/CVE-2020-8559.patch
>     @@ -0,0 +1,148 @@
>     +From ba3ca4929ed3887c95f94fcf97610f3449446804 Mon Sep 17 00:00:00 2001
>     +From: Tim Allclair <tallclair@google.com>
>     +Date: Wed, 17 Jun 2020 11:09:02 -0700
>     +Subject: [PATCH] Don't return proxied redirects to the client
>     +
>     +CVE: CVE-2020-8559
>     +Upstream-Status: Backport [https://github.com/kubernetes/kubernetes.git branch:release-1.16]
>     +Signed-off-by: Zhixiong Chi <zhixiong.chi@windriver.com>
>     +---
>     + .../k8s.io/apimachinery/pkg/util/net/http.go  |  2 +-
>     + .../apimachinery/pkg/util/net/http_test.go    | 12 ++---
>     + .../pkg/util/proxy/upgradeaware.go            | 10 ++++
>     + .../pkg/util/proxy/upgradeaware_test.go       | 47 ++++++++++++++++++-
>     + 4 files changed, 62 insertions(+), 9 deletions(-)
>     +
>     +diff --git a/src/import/staging/src/k8s.io/apimachinery/pkg/util/net/http.go b/src/import/staging/src/k8s.io/apimachinery/pkg/util/net/http.go
>     +index bd79d6c4a09..c24fbc6921c 100644
>     +--- a/src/import/staging/src/k8s.io/apimachinery/pkg/util/net/http.go
>     ++++ b/src/import/staging/src/k8s.io/apimachinery/pkg/util/net/http.go
>     +@@ -431,7 +431,7 @@ redirectLoop:
>     +
>     +               // Only follow redirects to the same host. Otherwise, propagate the redirect response back.
>     +               if requireSameHostRedirects && location.Hostname() != originalLocation.Hostname() {
>     +-                      break redirectLoop
>     ++                      return nil, nil, fmt.Errorf("hostname mismatch: expected %s, found %s", originalLocation.Hostname(), location.Hostname())
>     +               }
>     +
>     +               // Reset the connection.
>     +diff --git a/src/import/staging/src/k8s.io/apimachinery/pkg/util/net/http_test.go b/src/import/staging/src/k8s.io/apimachinery/pkg/util/net/http_test.go
>     +index 4e4e317b9a4..142b80f1a84 100644
>     +--- a/src/import/staging/src/k8s.io/apimachinery/pkg/util/net/http_test.go
>     ++++ b/src/import/staging/src/k8s.io/apimachinery/pkg/util/net/http_test.go
>     +@@ -330,13 +330,13 @@ func TestConnectWithRedirects(t *testing.T) {
>     +               redirects:   []string{"/1", "/2", "/3", "/4", "/5", "/6", "/7", "/8", "/9", "/10"},
>     +               expectError: true,
>     +       }, {
>     +-              desc:              "redirect to different host are prevented",
>     +-              redirects:         []string{"http://example.com/foo"},
>     +-              expectedRedirects: 0,
>     ++              desc:        "redirect to different host are prevented",
>     ++              redirects:   []string{"http://example.com/foo"},
>     ++              expectError: true,
>     +       }, {
>     +-              desc:              "multiple redirect to different host forbidden",
>     +-              redirects:         []string{"/1", "/2", "/3", "http://example.com/foo"},
>     +-              expectedRedirects: 3,
>     ++              desc:        "multiple redirect to different host forbidden",
>     ++              redirects:   []string{"/1", "/2", "/3", "http://example.com/foo"},
>     ++              expectError: true,
>     +       }, {
>     +               desc:              "redirect to different port is allowed",
>     +               redirects:         []string{"http://HOST/foo"},
>     +diff --git a/src/import/staging/src/k8s.io/apimachinery/pkg/util/proxy/upgradeaware.go b/src/import/staging/src/k8s.io/apimachinery/pkg/util/proxy/upgradeaware.go
>     +index fcdc76a0529..3a02919d135 100644
>     +--- a/src/import/staging/src/k8s.io/apimachinery/pkg/util/proxy/upgradeaware.go
>     ++++ b/src/import/staging/src/k8s.io/apimachinery/pkg/util/proxy/upgradeaware.go
>     +@@ -298,6 +298,16 @@ func (h *UpgradeAwareHandler) tryUpgrade(w http.ResponseWriter, req *http.Reques
>     +               rawResponse = headerBytes
>     +       }
>     +
>     ++      // If the backend did not upgrade the request, return an error to the client. If the response was
>     ++      // an error, the error is forwarded directly after the connection is hijacked. Otherwise, just
>     ++      // return a generic error here.
>     ++      if backendHTTPResponse.StatusCode != http.StatusSwitchingProtocols && backendHTTPResponse.StatusCode < 400 {
>     ++              err := fmt.Errorf("invalid upgrade response: status code %d", backendHTTPResponse.StatusCode)
>     ++              klog.Errorf("Proxy upgrade error: %v", err)
>     ++              h.Responder.Error(w, req, err)
>     ++              return true
>     ++      }
>     ++
>     +       // Once the connection is hijacked, the ErrorResponder will no longer work, so
>     +       // hijacking should be the last step in the upgrade.
>     +       requestHijacker, ok := w.(http.Hijacker)
>     +diff --git a/src/import/staging/src/k8s.io/apimachinery/pkg/util/proxy/upgradeaware_test.go b/src/import/staging/src/k8s.io/apimachinery/pkg/util/proxy/upgradeaware_test.go
>     +index 7d14f6534a8..236362373cd 100644
>     +--- a/src/import/staging/src/k8s.io/apimachinery/pkg/util/proxy/upgradeaware_test.go
>     ++++ b/src/import/staging/src/k8s.io/apimachinery/pkg/util/proxy/upgradeaware_test.go
>     +@@ -493,7 +493,7 @@ func (r *noErrorsAllowed) Error(w http.ResponseWriter, req *http.Request, err er
>     +       r.t.Error(err)
>     + }
>     +
>     +-func TestProxyUpgradeErrorResponse(t *testing.T) {
>     ++func TestProxyUpgradeConnectionErrorResponse(t *testing.T) {
>     +       var (
>     +               responder   *fakeResponder
>     +               expectedErr = errors.New("EXPECTED")
>     +@@ -541,7 +541,7 @@ func TestProxyUpgradeErrorResponse(t *testing.T) {
>     + 
>     + func TestProxyUpgradeErrorResponseTerminates(t *testing.T) {
>     +       for _, intercept := range []bool{true, false} {
>     +-              for _, code := range []int{200, 400, 500} {
>     ++              for _, code := range []int{400, 500} {
>     +                       t.Run(fmt.Sprintf("intercept=%v,code=%v", intercept, code), func(t *testing.T) {
>     +                               // Set up a backend server
>     +                               backend := http.NewServeMux()
>     +@@ -601,6 +601,49 @@ func TestProxyUpgradeErrorResponseTerminates(t *testing.T) {
>     +       }
>     + }
>     +
>     ++func TestProxyUpgradeErrorResponse(t *testing.T) {
>     ++      for _, intercept := range []bool{true, false} {
>     ++              for _, code := range []int{200, 300, 302, 307} {
>     ++                      t.Run(fmt.Sprintf("intercept=%v,code=%v", intercept, code), func(t *testing.T) {
>     ++                              // Set up a backend server
>     ++                              backend := http.NewServeMux()
>     ++                              backend.Handle("/hello", http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
>     ++                                      http.Redirect(w, r, "https://example.com/there", code)
>     ++                              }))
>     ++                              backendServer := httptest.NewServer(backend)
>     ++                              defer backendServer.Close()
>     ++                              backendServerURL, _ := url.Parse(backendServer.URL)
>     ++                              backendServerURL.Path = "/hello"
>     ++
>     ++                              // Set up a proxy pointing to a specific path on the backend
>     ++                              proxyHandler := NewUpgradeAwareHandler(backendServerURL, nil, false, false, &fakeResponder{t: t})
>     ++                              proxyHandler.InterceptRedirects = intercept
>     ++                              proxyHandler.RequireSameHostRedirects = true
>     ++                              proxy := httptest.NewServer(proxyHandler)
>     ++                              defer proxy.Close()
>     ++                              proxyURL, _ := url.Parse(proxy.URL)
>     ++
>     ++                              conn, err := net.Dial("tcp", proxyURL.Host)
>     ++                              require.NoError(t, err)
>     ++                              bufferedReader := bufio.NewReader(conn)
>     ++
>     ++                              // Send upgrade request resulting in a non-101 response from the backend
>     ++                              req, _ := http.NewRequest("GET", "/", nil)
>     ++                              req.Header.Set(httpstream.HeaderConnection, httpstream.HeaderUpgrade)
>     ++                              require.NoError(t, req.Write(conn))
>     ++                              // Verify we get the correct response and full message body content
>     ++                              resp, err := http.ReadResponse(bufferedReader, nil)
>     ++                              require.NoError(t, err)
>     ++                              assert.Equal(t, fakeStatusCode, resp.StatusCode)
>     ++                              resp.Body.Close()
>     ++
>     ++                              // clean up
>     ++                              conn.Close()
>     ++                      })
>     ++              }
>     ++      }
>     ++}
>     ++
>     + func TestDefaultProxyTransport(t *testing.T) {
>     +       tests := []struct {
>     +               name,
>     +--
>     +2.17.0
>     +
>     diff --git a/recipes-containers/kubernetes/kubernetes_git.bb b/recipes-containers/kubernetes/kubernetes_git.bb
>     index 941e0ca..fbe2dd8 100644
>     --- a/recipes-containers/kubernetes/kubernetes_git.bb
>     +++ b/recipes-containers/kubernetes/kubernetes_git.bb
>     @@ -16,6 +16,9 @@ SRC_URI = "git://github.com/kubernetes/kubernetes.git;branch=release-1.16;name=k
>                 file://CVE-2020-8552.patch \
>                 file://CVE-2020-8555.patch \
>                 file://CVE-2019-11254.patch \
>     +           file://CVE-2020-8557.patch \
>     +           file://CVE-2020-8558.patch \
>     +           file://CVE-2020-8559.patch \
>                "
> 
>      DEPENDS += "rsync-native \
> 
> 
>     
> 
> --
> ---------------------
> Thanks,
> Zhixiong Chi
> Tel: +86-10-8477-7036
> 

^ permalink raw reply	[flat|nested] 4+ messages in thread

* Re: [meta-virtualization][zeus][PATCH] kubernetes: fix three CVE issues
  2020-07-30 19:54   ` Bruce Ashfield
@ 2020-07-31  3:11     ` Zhixiong Chi
  0 siblings, 0 replies; 4+ messages in thread
From: Zhixiong Chi @ 2020-07-31  3:11 UTC (permalink / raw)
  To: Bruce Ashfield; +Cc: meta-virtualization


On 2020/7/31 上午3:54, Bruce Ashfield wrote:
> merged (and yes, I went back and picked up the older CVE patch as well).
>
> But remember, when submitting these to an older branch, we should also
> be summarizing if other branches are vulenerable.
>
> In master, we'll update the version to pick up the change, but it is still
> useful to know if it is fixed in the k8s release branch.
>
> And in particular, I need the following answered: does dunfell need these
> patches as well ?

Hi Bruce,

OK, I will handle the dunfell branch together next time.

Thanks.


> Bruce
>
> In message: Re: [meta-virtualization][zeus][PATCH] kubernetes: fix three CVE issues
> on 30/07/2020 Zhixiong Chi wrote:
>
>> Hi Bruce,
>>
>> After the last CVE-1019-11254 patch merged, this patch can be applied
>> successfully.
>>
>> Thanks.
>>
>> On 2020/7/30 下午4:30, Zhixiong Chi wrote:
>>
>>     Backport the patches from the upstream:
>>     https://github.com/kubernetes/kubernetes.git  [branch: release-1.16]
>>     ba3ca4929ed3887c95f94fcf97610f3449446804
>>     68750fefd3df76b7b008ef7b18e8acd18d5c2f2e
>>     d22a61e21d677f7527bc8a4aeb3288c5e11dd49b
>>
>>     Signed-off-by: Zhixiong Chi <zhixiong.chi@windriver.com>
>>     ---
>>      .../kubernetes/kubernetes/CVE-2020-8557.patch | 179 ++++++++++++++++++
>>      .../kubernetes/kubernetes/CVE-2020-8558.patch |  51 +++++
>>      .../kubernetes/kubernetes/CVE-2020-8559.patch | 148 +++++++++++++++
>>      .../kubernetes/kubernetes_git.bb              |   3 +
>>      4 files changed, 381 insertions(+)
>>      create mode 100644 recipes-containers/kubernetes/kubernetes/CVE-2020-8557.patch
>>      create mode 100644 recipes-containers/kubernetes/kubernetes/CVE-2020-8558.patch
>>      create mode 100644 recipes-containers/kubernetes/kubernetes/CVE-2020-8559.patch
>>
>>     diff --git a/recipes-containers/kubernetes/kubernetes/CVE-2020-8557.patch b/recipes-containers/kubernetes/kubernetes/CVE-2020-8557.patch
>>     new file mode 100644
>>     index 0000000..dd70627
>>     --- /dev/null
>>     +++ b/recipes-containers/kubernetes/kubernetes/CVE-2020-8557.patch
>>     @@ -0,0 +1,179 @@
>>     +From 68750fefd3df76b7b008ef7b18e8acd18d5c2f2e Mon Sep 17 00:00:00 2001
>>     +From: Joel Smith <joesmith@redhat.com>
>>     +Date: Thu, 14 May 2020 20:09:58 -0600
>>     +Subject: [PATCH] Include pod /etc/hosts in ephemeral storage calculation for
>>     + eviction
>>     +
>>     +CVE: CVE-2020-8557
>>     +Upstream-Status: Backport [https://github.com/kubernetes/kubernetes.git branch:release-1.16]
>>     +Signed-off-by: Zhixiong Chi <zhixiong.chi@windriver.com>
>>     +---
>>     + src/import/pkg/kubelet/eviction/BUILD               | 1 +
>>     + src/import/pkg/kubelet/eviction/eviction_manager.go | 7 ++++++-
>>     + src/import/pkg/kubelet/eviction/helpers.go          | 9 ++++++++-
>>     + src/import/pkg/kubelet/kubelet.go                   | 3 ++-
>>     + src/import/pkg/kubelet/kubelet_pods.go              | 7 ++++++-
>>     + src/import/pkg/kubelet/kubelet_test.go              | 3 ++-
>>     + src/import/pkg/kubelet/runonce_test.go              | 3 ++-
>>     + 7 files changed, 27 insertions(+), 6 deletions(-)
>>     +
>>     +diff --git a/src/import/pkg/kubelet/eviction/BUILD b/src/import/pkg/kubelet/eviction/BUILD
>>     +index 2209b26d7d4..e8c2241e075 100644
>>     +--- a/src/import/pkg/kubelet/eviction/BUILD
>>     ++++ b/src/import/pkg/kubelet/eviction/BUILD
>>     +@@ -66,6 +66,7 @@ go_library(
>>     +         "//staging/src/k8s.io/api/core/v1:go_default_library",
>>     +         "//staging/src/k8s.io/apimachinery/pkg/api/resource:go_default_library",
>>     +         "//staging/src/k8s.io/apimachinery/pkg/apis/meta/v1:go_default_library",
>>     ++        "//staging/src/k8s.io/apimachinery/pkg/types:go_default_library",
>>     +         "//staging/src/k8s.io/apimachinery/pkg/util/clock:go_default_library",
>>     +         "//staging/src/k8s.io/apiserver/pkg/util/feature:go_default_library",
>>     +         "//staging/src/k8s.io/client-go/tools/record:go_default_library",
>>     +diff --git a/src/import/pkg/kubelet/eviction/eviction_manager.go b/src/import/pkg/kubelet/eviction/eviction_manager.go
>>     +index 4ef2a89dce6..ca218cb942f 100644
>>     +--- a/src/import/pkg/kubelet/eviction/eviction_manager.go
>>     ++++ b/src/import/pkg/kubelet/eviction/eviction_manager.go
>>     +@@ -26,6 +26,7 @@ import (
>>     +
>>     +       v1 "k8s.io/api/core/v1"
>>     +       "k8s.io/apimachinery/pkg/api/resource"
>>     ++      "k8s.io/apimachinery/pkg/types"
>>     +       "k8s.io/apimachinery/pkg/util/clock"
>>     +       utilfeature "k8s.io/apiserver/pkg/util/feature"
>>     +       "k8s.io/client-go/tools/record"
>>     +@@ -90,6 +91,8 @@ type managerImpl struct {
>>     +       thresholdNotifiers []ThresholdNotifier
>>     +       // thresholdsLastUpdated is the last time the thresholdNotifiers were updated.
>>     +       thresholdsLastUpdated time.Time
>>     ++      // etcHostsPath is a function that will get the etc-hosts file's path for a pod given its UID
>>     ++      etcHostsPath func(podUID types.UID) string
>>     + }
>>     + 
>>     + // ensure it implements the required interface
>>     +@@ -106,6 +109,7 @@ func NewManager(
>>     +       recorder record.EventRecorder,
>>     +       nodeRef *v1.ObjectReference,
>>     +       clock clock.Clock,
>>     ++      etcHostsPath func(types.UID) string,
>>     + ) (Manager, lifecycle.PodAdmitHandler) {
>>     +       manager := &managerImpl{
>>     +               clock:                        clock,
>>     +@@ -121,6 +125,7 @@ func NewManager(
>>     +               thresholdsFirstObservedAt:    thresholdsObservedAt{},
>>     +               dedicatedImageFs:             nil,
>>     +               thresholdNotifiers:           []ThresholdNotifier{},
>>     ++              etcHostsPath:                 etcHostsPath,
>>     +       }
>>     +       return manager, manager
>>     + }
>>     +@@ -503,7 +508,7 @@ func (m *managerImpl) podEphemeralStorageLimitEviction(podStats statsapi.PodStat
>>     +       } else {
>>     +               fsStatsSet = []fsStatsType{fsStatsRoot, fsStatsLogs, fsStatsLocalVolumeSource}
>>     +       }
>>     +-      podEphemeralUsage, err := podLocalEphemeralStorageUsage(podStats, pod, fsStatsSet)
>>     ++      podEphemeralUsage, err := podLocalEphemeralStorageUsage(podStats, pod, fsStatsSet, m.etcHostsPath(pod.UID))
>>     +       if err != nil {
>>     +               klog.Errorf("eviction manager: error getting pod disk usage %v", err)
>>     +               return false
>>     +diff --git a/src/import/pkg/kubelet/eviction/helpers.go b/src/import/pkg/kubelet/eviction/helpers.go
>>     +index dfdb8ce3b60..41c55855aad 100644
>>     +--- a/src/import/pkg/kubelet/eviction/helpers.go
>>     ++++ b/src/import/pkg/kubelet/eviction/helpers.go
>>     +@@ -18,6 +18,7 @@ package eviction
>>     +
>>     + import (
>>     +       "fmt"
>>     ++      "os"
>>     +       "sort"
>>     +       "strconv"
>>     +       "strings"
>>     +@@ -415,7 +416,7 @@ func localEphemeralVolumeNames(pod *v1.Pod) []string {
>>     + }
>>     +
>>     + // podLocalEphemeralStorageUsage aggregates pod local ephemeral storage usage and inode consumption for the specified stats to measure.
>>     +-func podLocalEphemeralStorageUsage(podStats statsapi.PodStats, pod *v1.Pod, statsToMeasure []fsStatsType) (v1.ResourceList, error) {
>>     ++func podLocalEphemeralStorageUsage(podStats statsapi.PodStats, pod *v1.Pod, statsToMeasure []fsStatsType, etcHostsPath string) (v1.ResourceList, error) {
>>     +       disk := resource.Quantity{Format: resource.BinarySI}
>>     +       inodes := resource.Quantity{Format: resource.DecimalSI}
>>     +
>>     +@@ -429,6 +430,12 @@ func podLocalEphemeralStorageUsage(podStats statsapi.PodStats, pod *v1.Pod, stat
>>     +               disk.Add(podLocalVolumeUsageList[v1.ResourceEphemeralStorage])
>>     +               inodes.Add(podLocalVolumeUsageList[resourceInodes])
>>     +       }
>>     ++      if len(etcHostsPath) > 0 {
>>     ++              if stat, err := os.Stat(etcHostsPath); err == nil {
>>     ++                      disk.Add(*resource.NewQuantity(int64(stat.Size()), resource.BinarySI))
>>     ++                      inodes.Add(*resource.NewQuantity(int64(1), resource.DecimalSI))
>>     ++              }
>>     ++      }
>>     +       return v1.ResourceList{
>>     +               v1.ResourceEphemeralStorage: disk,
>>     +               resourceInodes:              inodes,
>>     +diff --git a/src/import/pkg/kubelet/kubelet.go b/src/import/pkg/kubelet/kubelet.go
>>     +index c2acd358e59..8da5d0f2e92 100644
>>     +--- a/src/import/pkg/kubelet/kubelet.go
>>     ++++ b/src/import/pkg/kubelet/kubelet.go
>>     +@@ -831,8 +831,9 @@ func NewMainKubelet(kubeCfg *kubeletconfiginternal.KubeletConfiguration,
>>     +       klet.backOff = flowcontrol.NewBackOff(backOffPeriod, MaxContainerBackOff)
>>     +       klet.podKillingCh = make(chan *kubecontainer.PodPair, podKillingChannelCapacity)
>>     +
>>     ++      etcHostsPathFunc := func(podUID types.UID) string { return getEtcHostsPath(klet.getPodDir(podUID)) }
>>     +       // setup eviction manager
>>     +-      evictionManager, evictionAdmitHandler := eviction.NewManager(klet.resourceAnalyzer, evictionConfig, killPodNow(klet.podWorkers, kubeDeps.Recorder), klet.podManager.GetMirrorPodByPod, klet.imageManager, klet.containerGC, kubeDeps.Recorder, nodeRef, klet.clock)
>>     ++      evictionManager, evictionAdmitHandler := eviction.NewManager(klet.resourceAnalyzer, evictionConfig, killPodNow(klet.podWorkers, kubeDeps.Recorder), klet.podManager.GetMirrorPodByPod, klet.imageManager, klet.containerGC, kubeDeps.Recorder, nodeRef, klet.clock, etcHostsPathFunc)
>>     +
>>     +       klet.evictionManager = evictionManager
>>     +       klet.admitHandlers.AddPodAdmitHandler(evictionAdmitHandler)
>>     +diff --git a/src/import/pkg/kubelet/kubelet_pods.go b/src/import/pkg/kubelet/kubelet_pods.go
>>     +index 013d0f55aea..02857d4b5b3 100644
>>     +--- a/src/import/pkg/kubelet/kubelet_pods.go
>>     ++++ b/src/import/pkg/kubelet/kubelet_pods.go
>>     +@@ -291,10 +291,15 @@ func translateMountPropagation(mountMode *v1.MountPropagationMode) (runtimeapi.M
>>     +       }
>>     + }
>>     +
>>     ++// getEtcHostsPath returns the full host-side path to a pod's generated /etc/hosts file
>>     ++func getEtcHostsPath(podDir string) string {
>>     ++      return path.Join(podDir, "etc-hosts")
>>     ++}
>>     ++
>>     + // makeHostsMount makes the mountpoint for the hosts file that the containers
>>     + // in a pod are injected with.
>>     + func makeHostsMount(podDir, podIP, hostName, hostDomainName string, hostAliases []v1.HostAlias, useHostNetwork bool) (*kubecontainer.Mount, error) {
>>     +-      hostsFilePath := path.Join(podDir, "etc-hosts")
>>     ++      hostsFilePath := getEtcHostsPath(podDir)
>>     +       if err := ensureHostsFile(hostsFilePath, podIP, hostName, hostDomainName, hostAliases, useHostNetwork); err != nil {
>>     +               return nil, err
>>     +       }
>>     +diff --git a/src/import/pkg/kubelet/kubelet_test.go b/src/import/pkg/kubelet/kubelet_test.go
>>     +index 80c6dcb73b6..9fb417fbb9d 100644
>>     +--- a/src/import/pkg/kubelet/kubelet_test.go
>>     ++++ b/src/import/pkg/kubelet/kubelet_test.go
>>     +@@ -291,8 +291,9 @@ func newTestKubeletWithImageList(
>>     +               UID:       types.UID(kubelet.nodeName),
>>     +               Namespace: "",
>>     +       }
>>     ++      etcHostsPathFunc := func(podUID types.UID) string { return getEtcHostsPath(kubelet.getPodDir(podUID)) }
>>     +       // setup eviction manager
>>     +-      evictionManager, evictionAdmitHandler := eviction.NewManager(kubelet.resourceAnalyzer, eviction.Config{}, killPodNow(kubelet.podWorkers, fakeRecorder), kubelet.podManager.GetMirrorPodByPod, kubelet.imageManager, kubelet.containerGC, fakeRecorder, nodeRef, kubelet.clock)
>>     ++      evictionManager, evictionAdmitHandler := eviction.NewManager(kubelet.resourceAnalyzer, eviction.Config{}, killPodNow(kubelet.podWorkers, fakeRecorder), kubelet.podManager.GetMirrorPodByPod, kubelet.imageManager, kubelet.containerGC, fakeRecorder, nodeRef, kubelet.clock, etcHostsPathFunc)
>>     +
>>     +       kubelet.evictionManager = evictionManager
>>     +       kubelet.admitHandlers.AddPodAdmitHandler(evictionAdmitHandler)
>>     +diff --git a/src/import/pkg/kubelet/runonce_test.go b/src/import/pkg/kubelet/runonce_test.go
>>     +index 7239133e481..9b162c11702 100644
>>     +--- a/src/import/pkg/kubelet/runonce_test.go
>>     ++++ b/src/import/pkg/kubelet/runonce_test.go
>>     +@@ -125,7 +125,8 @@ func TestRunOnce(t *testing.T) {
>>     +               return nil
>>     +       }
>>     +       fakeMirrodPodFunc := func(*v1.Pod) (*v1.Pod, bool) { return nil, false }
>>     +-      evictionManager, evictionAdmitHandler := eviction.NewManager(kb.resourceAnalyzer, eviction.Config{}, fakeKillPodFunc, fakeMirrodPodFunc, nil, nil, kb.recorder, nodeRef, kb.clock)
>>     ++      etcHostsPathFunc := func(podUID types.UID) string { return getEtcHostsPath(kb.getPodDir(podUID)) }
>>     ++      evictionManager, evictionAdmitHandler := eviction.NewManager(kb.resourceAnalyzer, eviction.Config{}, fakeKillPodFunc, fakeMirrodPodFunc, nil, nil, kb.recorder, nodeRef, kb.clock, etcHostsPathFunc)
>>     +
>>     +       kb.evictionManager = evictionManager
>>     +       kb.admitHandlers.AddPodAdmitHandler(evictionAdmitHandler)
>>     +--
>>     +2.17.0
>>     +
>>     diff --git a/recipes-containers/kubernetes/kubernetes/CVE-2020-8558.patch b/recipes-containers/kubernetes/kubernetes/CVE-2020-8558.patch
>>     new file mode 100644
>>     index 0000000..9eeed26
>>     --- /dev/null
>>     +++ b/recipes-containers/kubernetes/kubernetes/CVE-2020-8558.patch
>>     @@ -0,0 +1,51 @@
>>     +From d22a61e21d677f7527bc8a4aeb3288c5e11dd49b Mon Sep 17 00:00:00 2001
>>     +From: Casey Callendrello <cdc@redhat.com>
>>     +Date: Fri, 29 May 2020 13:03:37 +0200
>>     +Subject: [PATCH] kubelet: block non-forwarded packets from crossing the
>>     + localhost boundary
>>     +
>>     +We set route_localnet so that host-network processes can connect to
>>     +<127.0.0.1:NodePort> and it still works. This, however, is too
>>     +permissive.
>>     +
>>     +So, block martians that are not already in conntrack.
>>     +
>>     +See: #90259
>>     +Signed-off-by: Casey Callendrello <cdc@redhat.com>
>>     +CVE: CVE-2020-8558
>>     +Upstream-Status: Backport [https://github.com/kubernetes/kubernetes.git branch:release-1.16]
>>     +Signed-off-by: Zhixiong Chi <zhixiong.chi@windriver.com>
>>     +---
>>     + src/import/pkg/kubelet/kubelet_network_linux.go | 16 ++++++++++++++++
>>     + 1 file changed, 16 insertions(+)
>>     +
>>     +diff --git a/src/import/pkg/kubelet/kubelet_network_linux.go b/src/import/pkg/kubelet/kubelet_network_linux.go
>>     +index 1c9ad46b989..d18ab75a053 100644
>>     +--- a/src/import/pkg/kubelet/kubelet_network_linux.go
>>     ++++ b/src/import/pkg/kubelet/kubelet_network_linux.go
>>     +@@ -68,6 +68,22 @@ func (kl *Kubelet) syncNetworkUtil() {
>>     +               klog.Errorf("Failed to ensure rule to drop packet marked by %v in %v chain %v: %v", KubeMarkDropChain, utiliptables.TableFilter, KubeFirewallChain, err)
>>     +               return
>>     +       }
>>     ++
>>     ++      // drop all non-local packets to localhost if they're not part of an existing
>>     ++      // forwarded connection. See #90259
>>     ++      if !kl.iptClient.IsIpv6() { // ipv6 doesn't have this issue
>>     ++              if _, err := kl.iptClient.EnsureRule(utiliptables.Append, utiliptables.TableFilter, KubeFirewallChain,
>>     ++                      "-m", "comment", "--comment", "block incoming localnet connections",
>>     ++                      "--dst", "127.0.0.0/8",
>>     ++                      "!", "--src", "127.0.0.0/8",
>>     ++                      "-m", "conntrack",
>>     ++                      "!", "--ctstate", "RELATED,ESTABLISHED,DNAT",
>>     ++                      "-j", "DROP"); err != nil {
>>     ++                      klog.Errorf("Failed to ensure rule to drop invalid localhost packets in %v chain %v: %v", utiliptables.TableFilter, KubeFirewallChain, err)
>>     ++                      return
>>     ++              }
>>     ++      }
>>     ++
>>     +       if _, err := kl.iptClient.EnsureRule(utiliptables.Prepend, utiliptables.TableFilter, utiliptables.ChainOutput, "-j", string(KubeFirewallChain)); err != nil {
>>     +               klog.Errorf("Failed to ensure that %s chain %s jumps to %s: %v", utiliptables.TableFilter, utiliptables.ChainOutput, KubeFirewallChain, err)
>>     +               return
>>     +--
>>     +2.17.0
>>     +
>>     diff --git a/recipes-containers/kubernetes/kubernetes/CVE-2020-8559.patch b/recipes-containers/kubernetes/kubernetes/CVE-2020-8559.patch
>>     new file mode 100644
>>     index 0000000..f47826d
>>     --- /dev/null
>>     +++ b/recipes-containers/kubernetes/kubernetes/CVE-2020-8559.patch
>>     @@ -0,0 +1,148 @@
>>     +From ba3ca4929ed3887c95f94fcf97610f3449446804 Mon Sep 17 00:00:00 2001
>>     +From: Tim Allclair <tallclair@google.com>
>>     +Date: Wed, 17 Jun 2020 11:09:02 -0700
>>     +Subject: [PATCH] Don't return proxied redirects to the client
>>     +
>>     +CVE: CVE-2020-8559
>>     +Upstream-Status: Backport [https://github.com/kubernetes/kubernetes.git branch:release-1.16]
>>     +Signed-off-by: Zhixiong Chi <zhixiong.chi@windriver.com>
>>     +---
>>     + .../k8s.io/apimachinery/pkg/util/net/http.go  |  2 +-
>>     + .../apimachinery/pkg/util/net/http_test.go    | 12 ++---
>>     + .../pkg/util/proxy/upgradeaware.go            | 10 ++++
>>     + .../pkg/util/proxy/upgradeaware_test.go       | 47 ++++++++++++++++++-
>>     + 4 files changed, 62 insertions(+), 9 deletions(-)
>>     +
>>     +diff --git a/src/import/staging/src/k8s.io/apimachinery/pkg/util/net/http.go b/src/import/staging/src/k8s.io/apimachinery/pkg/util/net/http.go
>>     +index bd79d6c4a09..c24fbc6921c 100644
>>     +--- a/src/import/staging/src/k8s.io/apimachinery/pkg/util/net/http.go
>>     ++++ b/src/import/staging/src/k8s.io/apimachinery/pkg/util/net/http.go
>>     +@@ -431,7 +431,7 @@ redirectLoop:
>>     +
>>     +               // Only follow redirects to the same host. Otherwise, propagate the redirect response back.
>>     +               if requireSameHostRedirects && location.Hostname() != originalLocation.Hostname() {
>>     +-                      break redirectLoop
>>     ++                      return nil, nil, fmt.Errorf("hostname mismatch: expected %s, found %s", originalLocation.Hostname(), location.Hostname())
>>     +               }
>>     +
>>     +               // Reset the connection.
>>     +diff --git a/src/import/staging/src/k8s.io/apimachinery/pkg/util/net/http_test.go b/src/import/staging/src/k8s.io/apimachinery/pkg/util/net/http_test.go
>>     +index 4e4e317b9a4..142b80f1a84 100644
>>     +--- a/src/import/staging/src/k8s.io/apimachinery/pkg/util/net/http_test.go
>>     ++++ b/src/import/staging/src/k8s.io/apimachinery/pkg/util/net/http_test.go
>>     +@@ -330,13 +330,13 @@ func TestConnectWithRedirects(t *testing.T) {
>>     +               redirects:   []string{"/1", "/2", "/3", "/4", "/5", "/6", "/7", "/8", "/9", "/10"},
>>     +               expectError: true,
>>     +       }, {
>>     +-              desc:              "redirect to different host are prevented",
>>     +-              redirects:         []string{"http://example.com/foo"},
>>     +-              expectedRedirects: 0,
>>     ++              desc:        "redirect to different host are prevented",
>>     ++              redirects:   []string{"http://example.com/foo"},
>>     ++              expectError: true,
>>     +       }, {
>>     +-              desc:              "multiple redirect to different host forbidden",
>>     +-              redirects:         []string{"/1", "/2", "/3", "http://example.com/foo"},
>>     +-              expectedRedirects: 3,
>>     ++              desc:        "multiple redirect to different host forbidden",
>>     ++              redirects:   []string{"/1", "/2", "/3", "http://example.com/foo"},
>>     ++              expectError: true,
>>     +       }, {
>>     +               desc:              "redirect to different port is allowed",
>>     +               redirects:         []string{"http://HOST/foo"},
>>     +diff --git a/src/import/staging/src/k8s.io/apimachinery/pkg/util/proxy/upgradeaware.go b/src/import/staging/src/k8s.io/apimachinery/pkg/util/proxy/upgradeaware.go
>>     +index fcdc76a0529..3a02919d135 100644
>>     +--- a/src/import/staging/src/k8s.io/apimachinery/pkg/util/proxy/upgradeaware.go
>>     ++++ b/src/import/staging/src/k8s.io/apimachinery/pkg/util/proxy/upgradeaware.go
>>     +@@ -298,6 +298,16 @@ func (h *UpgradeAwareHandler) tryUpgrade(w http.ResponseWriter, req *http.Reques
>>     +               rawResponse = headerBytes
>>     +       }
>>     +
>>     ++      // If the backend did not upgrade the request, return an error to the client. If the response was
>>     ++      // an error, the error is forwarded directly after the connection is hijacked. Otherwise, just
>>     ++      // return a generic error here.
>>     ++      if backendHTTPResponse.StatusCode != http.StatusSwitchingProtocols && backendHTTPResponse.StatusCode < 400 {
>>     ++              err := fmt.Errorf("invalid upgrade response: status code %d", backendHTTPResponse.StatusCode)
>>     ++              klog.Errorf("Proxy upgrade error: %v", err)
>>     ++              h.Responder.Error(w, req, err)
>>     ++              return true
>>     ++      }
>>     ++
>>     +       // Once the connection is hijacked, the ErrorResponder will no longer work, so
>>     +       // hijacking should be the last step in the upgrade.
>>     +       requestHijacker, ok := w.(http.Hijacker)
>>     +diff --git a/src/import/staging/src/k8s.io/apimachinery/pkg/util/proxy/upgradeaware_test.go b/src/import/staging/src/k8s.io/apimachinery/pkg/util/proxy/upgradeaware_test.go
>>     +index 7d14f6534a8..236362373cd 100644
>>     +--- a/src/import/staging/src/k8s.io/apimachinery/pkg/util/proxy/upgradeaware_test.go
>>     ++++ b/src/import/staging/src/k8s.io/apimachinery/pkg/util/proxy/upgradeaware_test.go
>>     +@@ -493,7 +493,7 @@ func (r *noErrorsAllowed) Error(w http.ResponseWriter, req *http.Request, err er
>>     +       r.t.Error(err)
>>     + }
>>     +
>>     +-func TestProxyUpgradeErrorResponse(t *testing.T) {
>>     ++func TestProxyUpgradeConnectionErrorResponse(t *testing.T) {
>>     +       var (
>>     +               responder   *fakeResponder
>>     +               expectedErr = errors.New("EXPECTED")
>>     +@@ -541,7 +541,7 @@ func TestProxyUpgradeErrorResponse(t *testing.T) {
>>     + 
>>     + func TestProxyUpgradeErrorResponseTerminates(t *testing.T) {
>>     +       for _, intercept := range []bool{true, false} {
>>     +-              for _, code := range []int{200, 400, 500} {
>>     ++              for _, code := range []int{400, 500} {
>>     +                       t.Run(fmt.Sprintf("intercept=%v,code=%v", intercept, code), func(t *testing.T) {
>>     +                               // Set up a backend server
>>     +                               backend := http.NewServeMux()
>>     +@@ -601,6 +601,49 @@ func TestProxyUpgradeErrorResponseTerminates(t *testing.T) {
>>     +       }
>>     + }
>>     +
>>     ++func TestProxyUpgradeErrorResponse(t *testing.T) {
>>     ++      for _, intercept := range []bool{true, false} {
>>     ++              for _, code := range []int{200, 300, 302, 307} {
>>     ++                      t.Run(fmt.Sprintf("intercept=%v,code=%v", intercept, code), func(t *testing.T) {
>>     ++                              // Set up a backend server
>>     ++                              backend := http.NewServeMux()
>>     ++                              backend.Handle("/hello", http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
>>     ++                                      http.Redirect(w, r, "https://example.com/there", code)
>>     ++                              }))
>>     ++                              backendServer := httptest.NewServer(backend)
>>     ++                              defer backendServer.Close()
>>     ++                              backendServerURL, _ := url.Parse(backendServer.URL)
>>     ++                              backendServerURL.Path = "/hello"
>>     ++
>>     ++                              // Set up a proxy pointing to a specific path on the backend
>>     ++                              proxyHandler := NewUpgradeAwareHandler(backendServerURL, nil, false, false, &fakeResponder{t: t})
>>     ++                              proxyHandler.InterceptRedirects = intercept
>>     ++                              proxyHandler.RequireSameHostRedirects = true
>>     ++                              proxy := httptest.NewServer(proxyHandler)
>>     ++                              defer proxy.Close()
>>     ++                              proxyURL, _ := url.Parse(proxy.URL)
>>     ++
>>     ++                              conn, err := net.Dial("tcp", proxyURL.Host)
>>     ++                              require.NoError(t, err)
>>     ++                              bufferedReader := bufio.NewReader(conn)
>>     ++
>>     ++                              // Send upgrade request resulting in a non-101 response from the backend
>>     ++                              req, _ := http.NewRequest("GET", "/", nil)
>>     ++                              req.Header.Set(httpstream.HeaderConnection, httpstream.HeaderUpgrade)
>>     ++                              require.NoError(t, req.Write(conn))
>>     ++                              // Verify we get the correct response and full message body content
>>     ++                              resp, err := http.ReadResponse(bufferedReader, nil)
>>     ++                              require.NoError(t, err)
>>     ++                              assert.Equal(t, fakeStatusCode, resp.StatusCode)
>>     ++                              resp.Body.Close()
>>     ++
>>     ++                              // clean up
>>     ++                              conn.Close()
>>     ++                      })
>>     ++              }
>>     ++      }
>>     ++}
>>     ++
>>     + func TestDefaultProxyTransport(t *testing.T) {
>>     +       tests := []struct {
>>     +               name,
>>     +--
>>     +2.17.0
>>     +
>>     diff --git a/recipes-containers/kubernetes/kubernetes_git.bb b/recipes-containers/kubernetes/kubernetes_git.bb
>>     index 941e0ca..fbe2dd8 100644
>>     --- a/recipes-containers/kubernetes/kubernetes_git.bb
>>     +++ b/recipes-containers/kubernetes/kubernetes_git.bb
>>     @@ -16,6 +16,9 @@ SRC_URI = "git://github.com/kubernetes/kubernetes.git;branch=release-1.16;name=k
>>                 file://CVE-2020-8552.patch \
>>                 file://CVE-2020-8555.patch \
>>                 file://CVE-2019-11254.patch \
>>     +           file://CVE-2020-8557.patch \
>>     +           file://CVE-2020-8558.patch \
>>     +           file://CVE-2020-8559.patch \
>>                "
>>
>>      DEPENDS += "rsync-native \
>>
>>
>>     
>>
>> --
>> ---------------------
>> Thanks,
>> Zhixiong Chi
>> Tel: +86-10-8477-7036
>>
-- 
---------------------
Thanks,
Zhixiong Chi
Tel: +86-10-8477-7036


^ permalink raw reply	[flat|nested] 4+ messages in thread

* [meta-virtualization][zeus][PATCH] kubernetes: fix three CVE issues
@ 2020-07-30  8:30 Zhixiong Chi
  0 siblings, 0 replies; 4+ messages in thread
From: Zhixiong Chi @ 2020-07-30  8:30 UTC (permalink / raw)
  To: bruce.ashfield, meta-virtualization

Backport the patches from the upstream:
https://github.com/kubernetes/kubernetes.git  [branch: release-1.16]
ba3ca4929ed3887c95f94fcf97610f3449446804
68750fefd3df76b7b008ef7b18e8acd18d5c2f2e
d22a61e21d677f7527bc8a4aeb3288c5e11dd49b

Signed-off-by: Zhixiong Chi <zhixiong.chi@windriver.com>
---
 .../kubernetes/kubernetes/CVE-2020-8557.patch | 179 ++++++++++++++++++
 .../kubernetes/kubernetes/CVE-2020-8558.patch |  51 +++++
 .../kubernetes/kubernetes/CVE-2020-8559.patch | 148 +++++++++++++++
 .../kubernetes/kubernetes_git.bb              |   3 +
 4 files changed, 381 insertions(+)
 create mode 100644 recipes-containers/kubernetes/kubernetes/CVE-2020-8557.patch
 create mode 100644 recipes-containers/kubernetes/kubernetes/CVE-2020-8558.patch
 create mode 100644 recipes-containers/kubernetes/kubernetes/CVE-2020-8559.patch

diff --git a/recipes-containers/kubernetes/kubernetes/CVE-2020-8557.patch b/recipes-containers/kubernetes/kubernetes/CVE-2020-8557.patch
new file mode 100644
index 0000000..dd70627
--- /dev/null
+++ b/recipes-containers/kubernetes/kubernetes/CVE-2020-8557.patch
@@ -0,0 +1,179 @@
+From 68750fefd3df76b7b008ef7b18e8acd18d5c2f2e Mon Sep 17 00:00:00 2001
+From: Joel Smith <joesmith@redhat.com>
+Date: Thu, 14 May 2020 20:09:58 -0600
+Subject: [PATCH] Include pod /etc/hosts in ephemeral storage calculation for
+ eviction
+
+CVE: CVE-2020-8557
+Upstream-Status: Backport [https://github.com/kubernetes/kubernetes.git branch:release-1.16]
+Signed-off-by: Zhixiong Chi <zhixiong.chi@windriver.com>
+---
+ src/import/pkg/kubelet/eviction/BUILD               | 1 +
+ src/import/pkg/kubelet/eviction/eviction_manager.go | 7 ++++++-
+ src/import/pkg/kubelet/eviction/helpers.go          | 9 ++++++++-
+ src/import/pkg/kubelet/kubelet.go                   | 3 ++-
+ src/import/pkg/kubelet/kubelet_pods.go              | 7 ++++++-
+ src/import/pkg/kubelet/kubelet_test.go              | 3 ++-
+ src/import/pkg/kubelet/runonce_test.go              | 3 ++-
+ 7 files changed, 27 insertions(+), 6 deletions(-)
+
+diff --git a/src/import/pkg/kubelet/eviction/BUILD b/src/import/pkg/kubelet/eviction/BUILD
+index 2209b26d7d4..e8c2241e075 100644
+--- a/src/import/pkg/kubelet/eviction/BUILD
++++ b/src/import/pkg/kubelet/eviction/BUILD
+@@ -66,6 +66,7 @@ go_library(
+         "//staging/src/k8s.io/api/core/v1:go_default_library",
+         "//staging/src/k8s.io/apimachinery/pkg/api/resource:go_default_library",
+         "//staging/src/k8s.io/apimachinery/pkg/apis/meta/v1:go_default_library",
++        "//staging/src/k8s.io/apimachinery/pkg/types:go_default_library",
+         "//staging/src/k8s.io/apimachinery/pkg/util/clock:go_default_library",
+         "//staging/src/k8s.io/apiserver/pkg/util/feature:go_default_library",
+         "//staging/src/k8s.io/client-go/tools/record:go_default_library",
+diff --git a/src/import/pkg/kubelet/eviction/eviction_manager.go b/src/import/pkg/kubelet/eviction/eviction_manager.go
+index 4ef2a89dce6..ca218cb942f 100644
+--- a/src/import/pkg/kubelet/eviction/eviction_manager.go
++++ b/src/import/pkg/kubelet/eviction/eviction_manager.go
+@@ -26,6 +26,7 @@ import (
+ 
+ 	v1 "k8s.io/api/core/v1"
+ 	"k8s.io/apimachinery/pkg/api/resource"
++	"k8s.io/apimachinery/pkg/types"
+ 	"k8s.io/apimachinery/pkg/util/clock"
+ 	utilfeature "k8s.io/apiserver/pkg/util/feature"
+ 	"k8s.io/client-go/tools/record"
+@@ -90,6 +91,8 @@ type managerImpl struct {
+ 	thresholdNotifiers []ThresholdNotifier
+ 	// thresholdsLastUpdated is the last time the thresholdNotifiers were updated.
+ 	thresholdsLastUpdated time.Time
++	// etcHostsPath is a function that will get the etc-hosts file's path for a pod given its UID
++	etcHostsPath func(podUID types.UID) string
+ }
+ 
+ // ensure it implements the required interface
+@@ -106,6 +109,7 @@ func NewManager(
+ 	recorder record.EventRecorder,
+ 	nodeRef *v1.ObjectReference,
+ 	clock clock.Clock,
++	etcHostsPath func(types.UID) string,
+ ) (Manager, lifecycle.PodAdmitHandler) {
+ 	manager := &managerImpl{
+ 		clock:                        clock,
+@@ -121,6 +125,7 @@ func NewManager(
+ 		thresholdsFirstObservedAt:    thresholdsObservedAt{},
+ 		dedicatedImageFs:             nil,
+ 		thresholdNotifiers:           []ThresholdNotifier{},
++		etcHostsPath:                 etcHostsPath,
+ 	}
+ 	return manager, manager
+ }
+@@ -503,7 +508,7 @@ func (m *managerImpl) podEphemeralStorageLimitEviction(podStats statsapi.PodStat
+ 	} else {
+ 		fsStatsSet = []fsStatsType{fsStatsRoot, fsStatsLogs, fsStatsLocalVolumeSource}
+ 	}
+-	podEphemeralUsage, err := podLocalEphemeralStorageUsage(podStats, pod, fsStatsSet)
++	podEphemeralUsage, err := podLocalEphemeralStorageUsage(podStats, pod, fsStatsSet, m.etcHostsPath(pod.UID))
+ 	if err != nil {
+ 		klog.Errorf("eviction manager: error getting pod disk usage %v", err)
+ 		return false
+diff --git a/src/import/pkg/kubelet/eviction/helpers.go b/src/import/pkg/kubelet/eviction/helpers.go
+index dfdb8ce3b60..41c55855aad 100644
+--- a/src/import/pkg/kubelet/eviction/helpers.go
++++ b/src/import/pkg/kubelet/eviction/helpers.go
+@@ -18,6 +18,7 @@ package eviction
+ 
+ import (
+ 	"fmt"
++	"os"
+ 	"sort"
+ 	"strconv"
+ 	"strings"
+@@ -415,7 +416,7 @@ func localEphemeralVolumeNames(pod *v1.Pod) []string {
+ }
+ 
+ // podLocalEphemeralStorageUsage aggregates pod local ephemeral storage usage and inode consumption for the specified stats to measure.
+-func podLocalEphemeralStorageUsage(podStats statsapi.PodStats, pod *v1.Pod, statsToMeasure []fsStatsType) (v1.ResourceList, error) {
++func podLocalEphemeralStorageUsage(podStats statsapi.PodStats, pod *v1.Pod, statsToMeasure []fsStatsType, etcHostsPath string) (v1.ResourceList, error) {
+ 	disk := resource.Quantity{Format: resource.BinarySI}
+ 	inodes := resource.Quantity{Format: resource.DecimalSI}
+ 
+@@ -429,6 +430,12 @@ func podLocalEphemeralStorageUsage(podStats statsapi.PodStats, pod *v1.Pod, stat
+ 		disk.Add(podLocalVolumeUsageList[v1.ResourceEphemeralStorage])
+ 		inodes.Add(podLocalVolumeUsageList[resourceInodes])
+ 	}
++	if len(etcHostsPath) > 0 {
++		if stat, err := os.Stat(etcHostsPath); err == nil {
++			disk.Add(*resource.NewQuantity(int64(stat.Size()), resource.BinarySI))
++			inodes.Add(*resource.NewQuantity(int64(1), resource.DecimalSI))
++		}
++	}
+ 	return v1.ResourceList{
+ 		v1.ResourceEphemeralStorage: disk,
+ 		resourceInodes:              inodes,
+diff --git a/src/import/pkg/kubelet/kubelet.go b/src/import/pkg/kubelet/kubelet.go
+index c2acd358e59..8da5d0f2e92 100644
+--- a/src/import/pkg/kubelet/kubelet.go
++++ b/src/import/pkg/kubelet/kubelet.go
+@@ -831,8 +831,9 @@ func NewMainKubelet(kubeCfg *kubeletconfiginternal.KubeletConfiguration,
+ 	klet.backOff = flowcontrol.NewBackOff(backOffPeriod, MaxContainerBackOff)
+ 	klet.podKillingCh = make(chan *kubecontainer.PodPair, podKillingChannelCapacity)
+ 
++	etcHostsPathFunc := func(podUID types.UID) string { return getEtcHostsPath(klet.getPodDir(podUID)) }
+ 	// setup eviction manager
+-	evictionManager, evictionAdmitHandler := eviction.NewManager(klet.resourceAnalyzer, evictionConfig, killPodNow(klet.podWorkers, kubeDeps.Recorder), klet.podManager.GetMirrorPodByPod, klet.imageManager, klet.containerGC, kubeDeps.Recorder, nodeRef, klet.clock)
++	evictionManager, evictionAdmitHandler := eviction.NewManager(klet.resourceAnalyzer, evictionConfig, killPodNow(klet.podWorkers, kubeDeps.Recorder), klet.podManager.GetMirrorPodByPod, klet.imageManager, klet.containerGC, kubeDeps.Recorder, nodeRef, klet.clock, etcHostsPathFunc)
+ 
+ 	klet.evictionManager = evictionManager
+ 	klet.admitHandlers.AddPodAdmitHandler(evictionAdmitHandler)
+diff --git a/src/import/pkg/kubelet/kubelet_pods.go b/src/import/pkg/kubelet/kubelet_pods.go
+index 013d0f55aea..02857d4b5b3 100644
+--- a/src/import/pkg/kubelet/kubelet_pods.go
++++ b/src/import/pkg/kubelet/kubelet_pods.go
+@@ -291,10 +291,15 @@ func translateMountPropagation(mountMode *v1.MountPropagationMode) (runtimeapi.M
+ 	}
+ }
+ 
++// getEtcHostsPath returns the full host-side path to a pod's generated /etc/hosts file
++func getEtcHostsPath(podDir string) string {
++	return path.Join(podDir, "etc-hosts")
++}
++
+ // makeHostsMount makes the mountpoint for the hosts file that the containers
+ // in a pod are injected with.
+ func makeHostsMount(podDir, podIP, hostName, hostDomainName string, hostAliases []v1.HostAlias, useHostNetwork bool) (*kubecontainer.Mount, error) {
+-	hostsFilePath := path.Join(podDir, "etc-hosts")
++	hostsFilePath := getEtcHostsPath(podDir)
+ 	if err := ensureHostsFile(hostsFilePath, podIP, hostName, hostDomainName, hostAliases, useHostNetwork); err != nil {
+ 		return nil, err
+ 	}
+diff --git a/src/import/pkg/kubelet/kubelet_test.go b/src/import/pkg/kubelet/kubelet_test.go
+index 80c6dcb73b6..9fb417fbb9d 100644
+--- a/src/import/pkg/kubelet/kubelet_test.go
++++ b/src/import/pkg/kubelet/kubelet_test.go
+@@ -291,8 +291,9 @@ func newTestKubeletWithImageList(
+ 		UID:       types.UID(kubelet.nodeName),
+ 		Namespace: "",
+ 	}
++	etcHostsPathFunc := func(podUID types.UID) string { return getEtcHostsPath(kubelet.getPodDir(podUID)) }
+ 	// setup eviction manager
+-	evictionManager, evictionAdmitHandler := eviction.NewManager(kubelet.resourceAnalyzer, eviction.Config{}, killPodNow(kubelet.podWorkers, fakeRecorder), kubelet.podManager.GetMirrorPodByPod, kubelet.imageManager, kubelet.containerGC, fakeRecorder, nodeRef, kubelet.clock)
++	evictionManager, evictionAdmitHandler := eviction.NewManager(kubelet.resourceAnalyzer, eviction.Config{}, killPodNow(kubelet.podWorkers, fakeRecorder), kubelet.podManager.GetMirrorPodByPod, kubelet.imageManager, kubelet.containerGC, fakeRecorder, nodeRef, kubelet.clock, etcHostsPathFunc)
+ 
+ 	kubelet.evictionManager = evictionManager
+ 	kubelet.admitHandlers.AddPodAdmitHandler(evictionAdmitHandler)
+diff --git a/src/import/pkg/kubelet/runonce_test.go b/src/import/pkg/kubelet/runonce_test.go
+index 7239133e481..9b162c11702 100644
+--- a/src/import/pkg/kubelet/runonce_test.go
++++ b/src/import/pkg/kubelet/runonce_test.go
+@@ -125,7 +125,8 @@ func TestRunOnce(t *testing.T) {
+ 		return nil
+ 	}
+ 	fakeMirrodPodFunc := func(*v1.Pod) (*v1.Pod, bool) { return nil, false }
+-	evictionManager, evictionAdmitHandler := eviction.NewManager(kb.resourceAnalyzer, eviction.Config{}, fakeKillPodFunc, fakeMirrodPodFunc, nil, nil, kb.recorder, nodeRef, kb.clock)
++	etcHostsPathFunc := func(podUID types.UID) string { return getEtcHostsPath(kb.getPodDir(podUID)) }
++	evictionManager, evictionAdmitHandler := eviction.NewManager(kb.resourceAnalyzer, eviction.Config{}, fakeKillPodFunc, fakeMirrodPodFunc, nil, nil, kb.recorder, nodeRef, kb.clock, etcHostsPathFunc)
+ 
+ 	kb.evictionManager = evictionManager
+ 	kb.admitHandlers.AddPodAdmitHandler(evictionAdmitHandler)
+-- 
+2.17.0
+
diff --git a/recipes-containers/kubernetes/kubernetes/CVE-2020-8558.patch b/recipes-containers/kubernetes/kubernetes/CVE-2020-8558.patch
new file mode 100644
index 0000000..9eeed26
--- /dev/null
+++ b/recipes-containers/kubernetes/kubernetes/CVE-2020-8558.patch
@@ -0,0 +1,51 @@
+From d22a61e21d677f7527bc8a4aeb3288c5e11dd49b Mon Sep 17 00:00:00 2001
+From: Casey Callendrello <cdc@redhat.com>
+Date: Fri, 29 May 2020 13:03:37 +0200
+Subject: [PATCH] kubelet: block non-forwarded packets from crossing the
+ localhost boundary
+
+We set route_localnet so that host-network processes can connect to
+<127.0.0.1:NodePort> and it still works. This, however, is too
+permissive.
+
+So, block martians that are not already in conntrack.
+
+See: #90259
+Signed-off-by: Casey Callendrello <cdc@redhat.com>
+CVE: CVE-2020-8558
+Upstream-Status: Backport [https://github.com/kubernetes/kubernetes.git branch:release-1.16]
+Signed-off-by: Zhixiong Chi <zhixiong.chi@windriver.com>
+---
+ src/import/pkg/kubelet/kubelet_network_linux.go | 16 ++++++++++++++++
+ 1 file changed, 16 insertions(+)
+
+diff --git a/src/import/pkg/kubelet/kubelet_network_linux.go b/src/import/pkg/kubelet/kubelet_network_linux.go
+index 1c9ad46b989..d18ab75a053 100644
+--- a/src/import/pkg/kubelet/kubelet_network_linux.go
++++ b/src/import/pkg/kubelet/kubelet_network_linux.go
+@@ -68,6 +68,22 @@ func (kl *Kubelet) syncNetworkUtil() {
+ 		klog.Errorf("Failed to ensure rule to drop packet marked by %v in %v chain %v: %v", KubeMarkDropChain, utiliptables.TableFilter, KubeFirewallChain, err)
+ 		return
+ 	}
++
++	// drop all non-local packets to localhost if they're not part of an existing
++	// forwarded connection. See #90259
++	if !kl.iptClient.IsIpv6() { // ipv6 doesn't have this issue
++		if _, err := kl.iptClient.EnsureRule(utiliptables.Append, utiliptables.TableFilter, KubeFirewallChain,
++			"-m", "comment", "--comment", "block incoming localnet connections",
++			"--dst", "127.0.0.0/8",
++			"!", "--src", "127.0.0.0/8",
++			"-m", "conntrack",
++			"!", "--ctstate", "RELATED,ESTABLISHED,DNAT",
++			"-j", "DROP"); err != nil {
++			klog.Errorf("Failed to ensure rule to drop invalid localhost packets in %v chain %v: %v", utiliptables.TableFilter, KubeFirewallChain, err)
++			return
++		}
++	}
++
+ 	if _, err := kl.iptClient.EnsureRule(utiliptables.Prepend, utiliptables.TableFilter, utiliptables.ChainOutput, "-j", string(KubeFirewallChain)); err != nil {
+ 		klog.Errorf("Failed to ensure that %s chain %s jumps to %s: %v", utiliptables.TableFilter, utiliptables.ChainOutput, KubeFirewallChain, err)
+ 		return
+-- 
+2.17.0
+
diff --git a/recipes-containers/kubernetes/kubernetes/CVE-2020-8559.patch b/recipes-containers/kubernetes/kubernetes/CVE-2020-8559.patch
new file mode 100644
index 0000000..f47826d
--- /dev/null
+++ b/recipes-containers/kubernetes/kubernetes/CVE-2020-8559.patch
@@ -0,0 +1,148 @@
+From ba3ca4929ed3887c95f94fcf97610f3449446804 Mon Sep 17 00:00:00 2001
+From: Tim Allclair <tallclair@google.com>
+Date: Wed, 17 Jun 2020 11:09:02 -0700
+Subject: [PATCH] Don't return proxied redirects to the client
+
+CVE: CVE-2020-8559
+Upstream-Status: Backport [https://github.com/kubernetes/kubernetes.git branch:release-1.16]
+Signed-off-by: Zhixiong Chi <zhixiong.chi@windriver.com>
+---
+ .../k8s.io/apimachinery/pkg/util/net/http.go  |  2 +-
+ .../apimachinery/pkg/util/net/http_test.go    | 12 ++---
+ .../pkg/util/proxy/upgradeaware.go            | 10 ++++
+ .../pkg/util/proxy/upgradeaware_test.go       | 47 ++++++++++++++++++-
+ 4 files changed, 62 insertions(+), 9 deletions(-)
+
+diff --git a/src/import/staging/src/k8s.io/apimachinery/pkg/util/net/http.go b/src/import/staging/src/k8s.io/apimachinery/pkg/util/net/http.go
+index bd79d6c4a09..c24fbc6921c 100644
+--- a/src/import/staging/src/k8s.io/apimachinery/pkg/util/net/http.go
++++ b/src/import/staging/src/k8s.io/apimachinery/pkg/util/net/http.go
+@@ -431,7 +431,7 @@ redirectLoop:
+ 
+ 		// Only follow redirects to the same host. Otherwise, propagate the redirect response back.
+ 		if requireSameHostRedirects && location.Hostname() != originalLocation.Hostname() {
+-			break redirectLoop
++			return nil, nil, fmt.Errorf("hostname mismatch: expected %s, found %s", originalLocation.Hostname(), location.Hostname())
+ 		}
+ 
+ 		// Reset the connection.
+diff --git a/src/import/staging/src/k8s.io/apimachinery/pkg/util/net/http_test.go b/src/import/staging/src/k8s.io/apimachinery/pkg/util/net/http_test.go
+index 4e4e317b9a4..142b80f1a84 100644
+--- a/src/import/staging/src/k8s.io/apimachinery/pkg/util/net/http_test.go
++++ b/src/import/staging/src/k8s.io/apimachinery/pkg/util/net/http_test.go
+@@ -330,13 +330,13 @@ func TestConnectWithRedirects(t *testing.T) {
+ 		redirects:   []string{"/1", "/2", "/3", "/4", "/5", "/6", "/7", "/8", "/9", "/10"},
+ 		expectError: true,
+ 	}, {
+-		desc:              "redirect to different host are prevented",
+-		redirects:         []string{"http://example.com/foo"},
+-		expectedRedirects: 0,
++		desc:        "redirect to different host are prevented",
++		redirects:   []string{"http://example.com/foo"},
++		expectError: true,
+ 	}, {
+-		desc:              "multiple redirect to different host forbidden",
+-		redirects:         []string{"/1", "/2", "/3", "http://example.com/foo"},
+-		expectedRedirects: 3,
++		desc:        "multiple redirect to different host forbidden",
++		redirects:   []string{"/1", "/2", "/3", "http://example.com/foo"},
++		expectError: true,
+ 	}, {
+ 		desc:              "redirect to different port is allowed",
+ 		redirects:         []string{"http://HOST/foo"},
+diff --git a/src/import/staging/src/k8s.io/apimachinery/pkg/util/proxy/upgradeaware.go b/src/import/staging/src/k8s.io/apimachinery/pkg/util/proxy/upgradeaware.go
+index fcdc76a0529..3a02919d135 100644
+--- a/src/import/staging/src/k8s.io/apimachinery/pkg/util/proxy/upgradeaware.go
++++ b/src/import/staging/src/k8s.io/apimachinery/pkg/util/proxy/upgradeaware.go
+@@ -298,6 +298,16 @@ func (h *UpgradeAwareHandler) tryUpgrade(w http.ResponseWriter, req *http.Reques
+ 		rawResponse = headerBytes
+ 	}
+ 
++	// If the backend did not upgrade the request, return an error to the client. If the response was
++	// an error, the error is forwarded directly after the connection is hijacked. Otherwise, just
++	// return a generic error here.
++	if backendHTTPResponse.StatusCode != http.StatusSwitchingProtocols && backendHTTPResponse.StatusCode < 400 {
++		err := fmt.Errorf("invalid upgrade response: status code %d", backendHTTPResponse.StatusCode)
++		klog.Errorf("Proxy upgrade error: %v", err)
++		h.Responder.Error(w, req, err)
++		return true
++	}
++
+ 	// Once the connection is hijacked, the ErrorResponder will no longer work, so
+ 	// hijacking should be the last step in the upgrade.
+ 	requestHijacker, ok := w.(http.Hijacker)
+diff --git a/src/import/staging/src/k8s.io/apimachinery/pkg/util/proxy/upgradeaware_test.go b/src/import/staging/src/k8s.io/apimachinery/pkg/util/proxy/upgradeaware_test.go
+index 7d14f6534a8..236362373cd 100644
+--- a/src/import/staging/src/k8s.io/apimachinery/pkg/util/proxy/upgradeaware_test.go
++++ b/src/import/staging/src/k8s.io/apimachinery/pkg/util/proxy/upgradeaware_test.go
+@@ -493,7 +493,7 @@ func (r *noErrorsAllowed) Error(w http.ResponseWriter, req *http.Request, err er
+ 	r.t.Error(err)
+ }
+ 
+-func TestProxyUpgradeErrorResponse(t *testing.T) {
++func TestProxyUpgradeConnectionErrorResponse(t *testing.T) {
+ 	var (
+ 		responder   *fakeResponder
+ 		expectedErr = errors.New("EXPECTED")
+@@ -541,7 +541,7 @@ func TestProxyUpgradeErrorResponse(t *testing.T) {
+ 
+ func TestProxyUpgradeErrorResponseTerminates(t *testing.T) {
+ 	for _, intercept := range []bool{true, false} {
+-		for _, code := range []int{200, 400, 500} {
++		for _, code := range []int{400, 500} {
+ 			t.Run(fmt.Sprintf("intercept=%v,code=%v", intercept, code), func(t *testing.T) {
+ 				// Set up a backend server
+ 				backend := http.NewServeMux()
+@@ -601,6 +601,49 @@ func TestProxyUpgradeErrorResponseTerminates(t *testing.T) {
+ 	}
+ }
+ 
++func TestProxyUpgradeErrorResponse(t *testing.T) {
++	for _, intercept := range []bool{true, false} {
++		for _, code := range []int{200, 300, 302, 307} {
++			t.Run(fmt.Sprintf("intercept=%v,code=%v", intercept, code), func(t *testing.T) {
++				// Set up a backend server
++				backend := http.NewServeMux()
++				backend.Handle("/hello", http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
++					http.Redirect(w, r, "https://example.com/there", code)
++				}))
++				backendServer := httptest.NewServer(backend)
++				defer backendServer.Close()
++				backendServerURL, _ := url.Parse(backendServer.URL)
++				backendServerURL.Path = "/hello"
++
++				// Set up a proxy pointing to a specific path on the backend
++				proxyHandler := NewUpgradeAwareHandler(backendServerURL, nil, false, false, &fakeResponder{t: t})
++				proxyHandler.InterceptRedirects = intercept
++				proxyHandler.RequireSameHostRedirects = true
++				proxy := httptest.NewServer(proxyHandler)
++				defer proxy.Close()
++				proxyURL, _ := url.Parse(proxy.URL)
++
++				conn, err := net.Dial("tcp", proxyURL.Host)
++				require.NoError(t, err)
++				bufferedReader := bufio.NewReader(conn)
++
++				// Send upgrade request resulting in a non-101 response from the backend
++				req, _ := http.NewRequest("GET", "/", nil)
++				req.Header.Set(httpstream.HeaderConnection, httpstream.HeaderUpgrade)
++				require.NoError(t, req.Write(conn))
++				// Verify we get the correct response and full message body content
++				resp, err := http.ReadResponse(bufferedReader, nil)
++				require.NoError(t, err)
++				assert.Equal(t, fakeStatusCode, resp.StatusCode)
++				resp.Body.Close()
++
++				// clean up
++				conn.Close()
++			})
++		}
++	}
++}
++
+ func TestDefaultProxyTransport(t *testing.T) {
+ 	tests := []struct {
+ 		name,
+-- 
+2.17.0
+
diff --git a/recipes-containers/kubernetes/kubernetes_git.bb b/recipes-containers/kubernetes/kubernetes_git.bb
index 941e0ca..fbe2dd8 100644
--- a/recipes-containers/kubernetes/kubernetes_git.bb
+++ b/recipes-containers/kubernetes/kubernetes_git.bb
@@ -16,6 +16,9 @@ SRC_URI = "git://github.com/kubernetes/kubernetes.git;branch=release-1.16;name=k
            file://CVE-2020-8552.patch \
            file://CVE-2020-8555.patch \
            file://CVE-2019-11254.patch \
+           file://CVE-2020-8557.patch \
+           file://CVE-2020-8558.patch \
+           file://CVE-2020-8559.patch \
           "
 
 DEPENDS += "rsync-native \
-- 
2.17.1


^ permalink raw reply related	[flat|nested] 4+ messages in thread

end of thread, other threads:[~2020-07-31  3:11 UTC | newest]

Thread overview: 4+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
     [not found] <16267A948D96B982.15129@lists.yoctoproject.org>
2020-07-30  8:35 ` [meta-virtualization][zeus][PATCH] kubernetes: fix three CVE issues Zhixiong Chi
2020-07-30 19:54   ` Bruce Ashfield
2020-07-31  3:11     ` Zhixiong Chi
2020-07-30  8:30 Zhixiong Chi

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.