All of lore.kernel.org
 help / color / mirror / Atom feed
* Re: [meta-virtualization][zeus][PATCH] kubernetes: CVE-2020-8551 and CVE-2020-8552
       [not found] <20200512085232.72315-1-zhixiong.chi@windriver.com>
@ 2020-05-12 12:23 ` Bruce Ashfield
       [not found]   ` <8d477377-0ec5-8414-09ab-8b0541e340b2@windriver.com>
  0 siblings, 1 reply; 2+ messages in thread
From: Bruce Ashfield @ 2020-05-12 12:23 UTC (permalink / raw)
  To: Zhixiong Chi; +Cc: meta-virtualization

As mentioned previously (check the archives) I'm about to go to
1.18-release so I won't be backporting any k8s CVE patches.

If these are for a stable branch, indicate that clearly in the patch subject.

Bruce

On Tue, May 12, 2020 at 4:52 AM Zhixiong Chi <zhixiong.chi@windriver.com> wrote:
>
> Backport the CVE patches from the upstream:
> https://github.com/kubernetes/kubernetes.git
>
> Signed-off-by: Zhixiong Chi <zhixiong.chi@windriver.com>
> ---
>  .../kubernetes/kubernetes/CVE-2020-8551.patch | 303 ++++++++++++++++++
>  .../kubernetes/kubernetes/CVE-2020-8552.patch | 170 ++++++++++
>  .../kubernetes/kubernetes_git.bb              |   2 +
>  3 files changed, 475 insertions(+)
>  create mode 100644 recipes-containers/kubernetes/kubernetes/CVE-2020-8551.patch
>  create mode 100644 recipes-containers/kubernetes/kubernetes/CVE-2020-8552.patch
>
> diff --git a/recipes-containers/kubernetes/kubernetes/CVE-2020-8551.patch b/recipes-containers/kubernetes/kubernetes/CVE-2020-8551.patch
> new file mode 100644
> index 0000000..f1f87b0
> --- /dev/null
> +++ b/recipes-containers/kubernetes/kubernetes/CVE-2020-8551.patch
> @@ -0,0 +1,303 @@
> +From 9bae583cb0c46380866c3df5d7a6d26aac335818 Mon Sep 17 00:00:00 2001
> +From: Walter Fender <wfender@google.com>
> +Date: Thu, 6 Feb 2020 19:10:18 -0800
> +Subject: [PATCH] Add code to fix kubelet/metrics memory issue.
> +
> +Bucketing url paths based on concept/handling.
> +Bucketing code placed by handling code to encourage usage.
> +Added unit tests.
> +Fix format.
> +
> +CVE: CVE-2020-8551
> +Upstream-Status: Backport [https://github.com/kubernetes/kubernetes.git]
> +Signed-off-by: Zhixiong Chi <zhixiong.chi@windriver.com>
> +---
> + pkg/kubelet/server/server.go      | 56 ++++++++++++++++++++++++++++---
> + pkg/kubelet/server/server_test.go | 54 ++++++++++++++++++++++++++++-
> + 2 files changed, 105 insertions(+), 5 deletions(-)
> +
> +diff --git a/src/import/pkg/kubelet/server/server.go b/src/import/pkg/kubelet/server/server.go
> +index c1f1975fe43..f924304fc12 100644
> +--- a/src/import/pkg/kubelet/server/server.go
> ++++ b/src/import/pkg/kubelet/server/server.go
> +@@ -90,6 +90,7 @@ type Server struct {
> +       auth                       AuthInterface
> +       host                       HostInterface
> +       restfulCont                containerInterface
> ++      metricsBuckets             map[string]bool
> +       resourceAnalyzer           stats.ResourceAnalyzer
> +       redirectContainerStreaming bool
> + }
> +@@ -224,6 +225,7 @@ func NewServer(
> +               resourceAnalyzer:           resourceAnalyzer,
> +               auth:                       auth,
> +               restfulCont:                &filteringContainer{Container: restful.NewContainer()},
> ++              metricsBuckets:             make(map[string]bool),
> +               redirectContainerStreaming: redirectContainerStreaming,
> +       }
> +       if auth != nil {
> +@@ -279,14 +281,32 @@ func (s *Server) InstallAuthFilter() {
> +       })
> + }
> +
> ++// addMetricsBucketMatcher adds a regexp matcher and the relevant bucket to use when
> ++// it matches. Please be aware this is not thread safe and should not be used dynamically
> ++func (s *Server) addMetricsBucketMatcher(bucket string) {
> ++      s.metricsBuckets[bucket] = true
> ++}
> ++
> ++// getMetricBucket find the appropriate metrics reporting bucket for the given path
> ++func (s *Server) getMetricBucket(path string) string {
> ++      root := getURLRootPath(path)
> ++      if s.metricsBuckets[root] == true {
> ++              return root
> ++      }
> ++      return "Invalid path"
> ++}
> ++
> + // InstallDefaultHandlers registers the default set of supported HTTP request
> + // patterns with the restful Container.
> + func (s *Server) InstallDefaultHandlers(enableCAdvisorJSONEndpoints bool) {
> ++      s.addMetricsBucketMatcher("healthz")
> +       healthz.InstallHandler(s.restfulCont,
> +               healthz.PingHealthz,
> +               healthz.LogHealthz,
> +               healthz.NamedCheck("syncloop", s.syncLoopHealthCheck),
> +       )
> ++
> ++      s.addMetricsBucketMatcher("pods")
> +       ws := new(restful.WebService)
> +       ws.
> +               Path("/pods").
> +@@ -296,7 +316,14 @@ func (s *Server) InstallDefaultHandlers(enableCAdvisorJSONEndpoints bool) {
> +               Operation("getPods"))
> +       s.restfulCont.Add(ws)
> +
> ++      s.addMetricsBucketMatcher("stats")
> +       s.restfulCont.Add(stats.CreateHandlers(statsPath, s.host, s.resourceAnalyzer, enableCAdvisorJSONEndpoints))
> ++
> ++      s.addMetricsBucketMatcher("metrics")
> ++      s.addMetricsBucketMatcher("metrics/cadvisor")
> ++      s.addMetricsBucketMatcher("metrics/probes")
> ++      s.addMetricsBucketMatcher("metrics/resource/v1alpha1")
> ++      s.addMetricsBucketMatcher("metrics/resource")
> +       //lint:ignore SA1019 https://github.com/kubernetes/enhancements/issues/1206
> +       s.restfulCont.Handle(metricsPath, legacyregistry.Handler())
> +
> +@@ -316,6 +346,7 @@ func (s *Server) InstallDefaultHandlers(enableCAdvisorJSONEndpoints bool) {
> +               promhttp.HandlerFor(r, promhttp.HandlerOpts{ErrorHandling: promhttp.ContinueOnError}),
> +       )
> +
> ++      s.addMetricsBucketMatcher("metrics/resource/v1alpha1")
> +       v1alpha1ResourceRegistry := prometheus.NewRegistry()
> +       v1alpha1ResourceRegistry.MustRegister(stats.NewPrometheusResourceMetricCollector(s.resourceAnalyzer, v1alpha1.Config()))
> +       s.restfulCont.Handle(path.Join(resourceMetricsPathPrefix, v1alpha1.Version),
> +@@ -325,11 +357,14 @@ func (s *Server) InstallDefaultHandlers(enableCAdvisorJSONEndpoints bool) {
> +
> +       p := compbasemetrics.NewKubeRegistry()
> +       compbasemetrics.RegisterProcessStartTime(p.RawRegister)
> ++
> ++      s.addMetricsBucketMatcher("metrics/probes")
> +       p.MustRegister(prober.ProberResults)
> +       s.restfulCont.Handle(proberMetricsPath,
> +               promhttp.HandlerFor(p, promhttp.HandlerOpts{ErrorHandling: promhttp.ContinueOnError}),
> +       )
> +
> ++      s.addMetricsBucketMatcher("spec")
> +       if enableCAdvisorJSONEndpoints {
> +               ws := new(restful.WebService)
> +               ws.
> +@@ -349,6 +384,7 @@ const pprofBasePath = "/debug/pprof/"
> + func (s *Server) InstallDebuggingHandlers(criHandler http.Handler) {
> +       klog.Infof("Adding debug handlers to kubelet server.")
> +
> ++      s.addMetricsBucketMatcher("run")
> +       ws := new(restful.WebService)
> +       ws.
> +               Path("/run")
> +@@ -360,6 +396,7 @@ func (s *Server) InstallDebuggingHandlers(criHandler http.Handler) {
> +               Operation("getRun"))
> +       s.restfulCont.Add(ws)
> +
> ++      s.addMetricsBucketMatcher("exec")
> +       ws = new(restful.WebService)
> +       ws.
> +               Path("/exec")
> +@@ -377,6 +414,7 @@ func (s *Server) InstallDebuggingHandlers(criHandler http.Handler) {
> +               Operation("getExec"))
> +       s.restfulCont.Add(ws)
> +
> ++      s.addMetricsBucketMatcher("attach")
> +       ws = new(restful.WebService)
> +       ws.
> +               Path("/attach")
> +@@ -394,6 +432,7 @@ func (s *Server) InstallDebuggingHandlers(criHandler http.Handler) {
> +               Operation("getAttach"))
> +       s.restfulCont.Add(ws)
> +
> ++      s.addMetricsBucketMatcher("portForward")
> +       ws = new(restful.WebService)
> +       ws.
> +               Path("/portForward")
> +@@ -411,6 +450,7 @@ func (s *Server) InstallDebuggingHandlers(criHandler http.Handler) {
> +               Operation("getPortForward"))
> +       s.restfulCont.Add(ws)
> +
> ++      s.addMetricsBucketMatcher("logs")
> +       ws = new(restful.WebService)
> +       ws.
> +               Path(logsPath)
> +@@ -423,6 +463,7 @@ func (s *Server) InstallDebuggingHandlers(criHandler http.Handler) {
> +               Param(ws.PathParameter("logpath", "path to the log").DataType("string")))
> +       s.restfulCont.Add(ws)
> +
> ++      s.addMetricsBucketMatcher("containerLogs")
> +       ws = new(restful.WebService)
> +       ws.
> +               Path("/containerLogs")
> +@@ -431,8 +472,10 @@ func (s *Server) InstallDebuggingHandlers(criHandler http.Handler) {
> +               Operation("getContainerLogs"))
> +       s.restfulCont.Add(ws)
> +
> ++      s.addMetricsBucketMatcher("configz")
> +       configz.InstallHandler(s.restfulCont)
> +
> ++      s.addMetricsBucketMatcher("debug")
> +       handlePprofEndpoint := func(req *restful.Request, resp *restful.Response) {
> +               name := strings.TrimPrefix(req.Request.URL.Path, pprofBasePath)
> +               switch name {
> +@@ -448,7 +491,6 @@ func (s *Server) InstallDebuggingHandlers(criHandler http.Handler) {
> +                       pprof.Index(resp, req.Request)
> +               }
> +       }
> +-
> +       // Setup pprof handlers.
> +       ws = new(restful.WebService).Path(pprofBasePath)
> +       ws.Route(ws.GET("/{subpath:*}").To(func(req *restful.Request, resp *restful.Response) {
> +@@ -461,6 +503,7 @@ func (s *Server) InstallDebuggingHandlers(criHandler http.Handler) {
> +       s.restfulCont.Handle("/debug/flags/v", routes.StringFlagPutHandler(logs.GlogSetter))
> +
> +       // The /runningpods endpoint is used for testing only.
> ++      s.addMetricsBucketMatcher("runningpods")
> +       ws = new(restful.WebService)
> +       ws.
> +               Path("/runningpods/").
> +@@ -470,6 +513,7 @@ func (s *Server) InstallDebuggingHandlers(criHandler http.Handler) {
> +               Operation("getRunningPods"))
> +       s.restfulCont.Add(ws)
> +
> ++      s.addMetricsBucketMatcher("cri")
> +       if criHandler != nil {
> +               s.restfulCont.Handle("/cri/", criHandler)
> +       }
> +@@ -481,6 +525,14 @@ func (s *Server) InstallDebuggingDisabledHandlers() {
> +               http.Error(w, "Debug endpoints are disabled.", http.StatusMethodNotAllowed)
> +       })
> +
> ++      s.addMetricsBucketMatcher("run")
> ++      s.addMetricsBucketMatcher("exec")
> ++      s.addMetricsBucketMatcher("attach")
> ++      s.addMetricsBucketMatcher("portForward")
> ++      s.addMetricsBucketMatcher("containerLogs")
> ++      s.addMetricsBucketMatcher("runningpods")
> ++      s.addMetricsBucketMatcher("pprof")
> ++      s.addMetricsBucketMatcher("logs")
> +       paths := []string{
> +               "/run/", "/exec/", "/attach/", "/portForward/", "/containerLogs/",
> +               "/runningpods/", pprofBasePath, logsPath}
> +@@ -814,10 +849,10 @@ func (s *Server) getPortForward(request *restful.Request, response *restful.Resp
> +       proxyStream(response.ResponseWriter, request.Request, url)
> + }
> +
> +-// trimURLPath trims a URL path.
> ++// getURLRootPath trims a URL path.
> + // For paths in the format of "/metrics/xxx", "metrics/xxx" is returned;
> + // For all other paths, the first part of the path is returned.
> +-func trimURLPath(path string) string {
> ++func getURLRootPath(path string) string {
> +       parts := strings.SplitN(strings.TrimPrefix(path, "/"), "/", 3)
> +       if len(parts) == 0 {
> +               return path
> +@@ -865,7 +900,7 @@ func (s *Server) ServeHTTP(w http.ResponseWriter, req *http.Request) {
> +               serverType = "readwrite"
> +       }
> +
> +-      method, path := req.Method, trimURLPath(req.URL.Path)
> ++      method, path := req.Method, s.getMetricBucket(req.URL.Path)
> +
> +       longRunning := strconv.FormatBool(isLongRunningRequest(path))
> +
> +diff --git a/src/import/pkg/kubelet/server/server_test.go b/src/import/pkg/kubelet/server/server_test.go
> +index 4761d21afb7..a95e5d19f0b 100644
> +--- a/src/import/pkg/kubelet/server/server_test.go
> ++++ b/src/import/pkg/kubelet/server/server_test.go
> +@@ -1612,6 +1612,58 @@ func TestCRIHandler(t *testing.T) {
> +       assert.Equal(t, query, fw.criHandler.RequestReceived.URL.RawQuery)
> + }
> +
> ++func TestMetricBuckets(t *testing.T) {
> ++      tests := map[string]struct {
> ++              url    string
> ++              bucket string
> ++      }{
> ++              "healthz endpoint":                {url: "/healthz", bucket: "healthz"},
> ++              "attach":                          {url: "/attach/podNamespace/podID/containerName", bucket: "attach"},
> ++              "attach with uid":                 {url: "/attach/podNamespace/podID/uid/containerName", bucket: "attach"},
> ++              "configz":                         {url: "/configz", bucket: "configz"},
> ++              "containerLogs":                   {url: "/containerLogs/podNamespace/podID/containerName", bucket: "containerLogs"},
> ++              "cri":                             {url: "/cri/", bucket: "cri"},
> ++              "cri with sub":                    {url: "/cri/foo", bucket: "cri"},
> ++              "debug v flags":                   {url: "/debug/flags/v", bucket: "debug"},
> ++              "pprof with sub":                  {url: "/debug/pprof/subpath", bucket: "debug"},
> ++              "exec":                            {url: "/exec/podNamespace/podID/containerName", bucket: "exec"},
> ++              "exec with uid":                   {url: "/exec/podNamespace/podID/uid/containerName", bucket: "exec"},
> ++              "healthz":                         {url: "/healthz/", bucket: "healthz"},
> ++              "healthz log sub":                 {url: "/healthz/log", bucket: "healthz"},
> ++              "healthz ping":                    {url: "/healthz/ping", bucket: "healthz"},
> ++              "healthz sync loop":               {url: "/healthz/syncloop", bucket: "healthz"},
> ++              "logs":                            {url: "/logs/", bucket: "logs"},
> ++              "logs with path":                  {url: "/logs/logpath", bucket: "logs"},
> ++              "metrics":                         {url: "/metrics", bucket: "metrics"},
> ++              "metrics cadvisor sub":            {url: "/metrics/cadvisor", bucket: "metrics/cadvisor"},
> ++              "metrics probes sub":              {url: "/metrics/probes", bucket: "metrics/probes"},
> ++              "metrics resource v1alpha1":       {url: "/metrics/resource/v1alpha1", bucket: "metrics/resource"},
> ++              "metrics resource sub":            {url: "/metrics/resource", bucket: "metrics/resource"},
> ++              "pods":                            {url: "/pods/", bucket: "pods"},
> ++              "portForward":                     {url: "/portForward/podNamespace/podID", bucket: "portForward"},
> ++              "portForward with uid":            {url: "/portForward/podNamespace/podID/uid", bucket: "portForward"},
> ++              "run":                             {url: "/run/podNamespace/podID/containerName", bucket: "run"},
> ++              "run with uid":                    {url: "/run/podNamespace/podID/uid/containerName", bucket: "run"},
> ++              "runningpods":                     {url: "/runningpods/", bucket: "runningpods"},
> ++              "spec":                            {url: "/spec/", bucket: "spec"},
> ++              "stats":                           {url: "/stats/", bucket: "stats"},
> ++              "stats container sub":             {url: "/stats/container", bucket: "stats"},
> ++              "stats summary sub":               {url: "/stats/summary", bucket: "stats"},
> ++              "stats containerName with uid":    {url: "/stats/namespace/podName/uid/containerName", bucket: "stats"},
> ++              "stats containerName":             {url: "/stats/podName/containerName", bucket: "stats"},
> ++              "invalid path":                    {url: "/junk", bucket: "Invalid path"},
> ++              "invalid path starting with good": {url: "/healthzjunk", bucket: "Invalid path"},
> ++      }
> ++      fw := newServerTest()
> ++      defer fw.testHTTPServer.Close()
> ++
> ++      for _, test := range tests {
> ++              path := test.url
> ++              bucket := test.bucket
> ++              require.Equal(t, fw.serverUnderTest.getMetricBucket(path), bucket)
> ++      }
> ++}
> ++
> + func TestDebuggingDisabledHandlers(t *testing.T) {
> +       fw := newServerTestWithDebug(false, false, nil)
> +       defer fw.testHTTPServer.Close()
> +@@ -1685,6 +1737,6 @@ func TestTrimURLPath(t *testing.T) {
> +       }
> +
> +       for _, test := range tests {
> +-              assert.Equal(t, test.expected, trimURLPath(test.path), fmt.Sprintf("path is: %s", test.path))
> ++              assert.Equal(t, test.expected, getURLRootPath(test.path), fmt.Sprintf("path is: %s", test.path))
> +       }
> + }
> +--
> +2.17.0
> +
> diff --git a/recipes-containers/kubernetes/kubernetes/CVE-2020-8552.patch b/recipes-containers/kubernetes/kubernetes/CVE-2020-8552.patch
> new file mode 100644
> index 0000000..85d7fcb
> --- /dev/null
> +++ b/recipes-containers/kubernetes/kubernetes/CVE-2020-8552.patch
> @@ -0,0 +1,170 @@
> +From cc3190968b1f14ddf4067abef849fc41bd6068dc Mon Sep 17 00:00:00 2001
> +From: Han Kang <hankang@google.com>
> +Date: Wed, 29 Jan 2020 12:25:55 -0800
> +Subject: [PATCH] remove client label from apiserver request count metric since
> + it is unbounded
> +
> +Change-Id: I3a9eacebc9d9dc9ed6347260d9378cdcb5743431
> +
> +CVE: CVE-2020-8552
> +Upstream-Status: Backport [Cherry-picked from https://github.com/kubernetes/kubernetes.git tag:v1.18.0]
> +Signed-off-by: Zhixiong Chi <zhixiong.chi@windriver.com>
> +---
> + .../apiserver/pkg/endpoints/metrics/BUILD     |  8 ---
> + .../pkg/endpoints/metrics/metrics.go          | 21 ++------
> + .../pkg/endpoints/metrics/metrics_test.go     | 54 -------------------
> + 3 files changed, 3 insertions(+), 80 deletions(-)
> + delete mode 100644 staging/src/k8s.io/apiserver/pkg/endpoints/metrics/metrics_test.go
> +
> +diff --git a/src/import/staging/src/k8s.io/apiserver/pkg/endpoints/metrics/BUILD b/src/import/staging/src/k8s.io/apiserver/pkg/endpoints/metrics/BUILD
> +index 8d13a34eadc..8abb3d1a611 100644
> +--- a/src/import/staging/src/k8s.io/apiserver/pkg/endpoints/metrics/BUILD
> ++++ b/src/import/staging/src/k8s.io/apiserver/pkg/endpoints/metrics/BUILD
> +@@ -3,13 +3,6 @@ package(default_visibility = ["//visibility:public"])
> + load(
> +     "@io_bazel_rules_go//go:def.bzl",
> +     "go_library",
> +-    "go_test",
> +-)
> +-
> +-go_test(
> +-    name = "go_default_test",
> +-    srcs = ["metrics_test.go"],
> +-    embed = [":go_default_library"],
> + )
> +
> + go_library(
> +@@ -20,7 +13,6 @@ go_library(
> +     deps = [
> +         "//staging/src/k8s.io/apimachinery/pkg/apis/meta/v1/validation:go_default_library",
> +         "//staging/src/k8s.io/apimachinery/pkg/types:go_default_library",
> +-        "//staging/src/k8s.io/apimachinery/pkg/util/net:go_default_library",
> +         "//staging/src/k8s.io/apimachinery/pkg/util/sets:go_default_library",
> +         "//staging/src/k8s.io/apiserver/pkg/endpoints/request:go_default_library",
> +         "//staging/src/k8s.io/apiserver/pkg/features:go_default_library",
> +diff --git a/src/import/staging/src/k8s.io/apiserver/pkg/endpoints/metrics/metrics.go b/src/import/staging/src/k8s.io/apiserver/pkg/endpoints/metrics/metrics.go
> +index f4e02fbb6a8..c79efdef4e3 100644
> +--- a/src/import/staging/src/k8s.io/apiserver/pkg/endpoints/metrics/metrics.go
> ++++ b/src/import/staging/src/k8s.io/apiserver/pkg/endpoints/metrics/metrics.go
> +@@ -29,7 +29,6 @@ import (
> +
> +       "k8s.io/apimachinery/pkg/apis/meta/v1/validation"
> +       "k8s.io/apimachinery/pkg/types"
> +-      utilnet "k8s.io/apimachinery/pkg/util/net"
> +       utilsets "k8s.io/apimachinery/pkg/util/sets"
> +       "k8s.io/apiserver/pkg/endpoints/request"
> +       "k8s.io/apiserver/pkg/features"
> +@@ -66,14 +65,14 @@ var (
> +       requestCounter = compbasemetrics.NewCounterVec(
> +               &compbasemetrics.CounterOpts{
> +                       Name:           "apiserver_request_total",
> +-                      Help:           "Counter of apiserver requests broken out for each verb, dry run value, group, version, resource, scope, component, client, and HTTP response contentType and code.",
> ++                      Help:           "Counter of apiserver requests broken out for each verb, dry run value, group, version, resource, scope, component, and HTTP response contentType and code.",
> +                       StabilityLevel: compbasemetrics.ALPHA,
> +               },
> +               // The label_name contentType doesn't follow the label_name convention defined here:
> +               // https://github.com/kubernetes/community/blob/master/contributors/devel/sig-instrumentation/instrumentation.md
> +               // But changing it would break backwards compatibility. Future label_names
> +               // should be all lowercase and separated by underscores.
> +-              []string{"verb", "dry_run", "group", "version", "resource", "subresource", "scope", "component", "client", "contentType", "code"},
> ++              []string{"verb", "dry_run", "group", "version", "resource", "subresource", "scope", "component", "contentType", "code"},
> +       )
> +       deprecatedRequestCounter = compbasemetrics.NewCounterVec(
> +               &compbasemetrics.CounterOpts{
> +@@ -243,11 +242,10 @@ func RecordLongRunning(req *http.Request, requestInfo *request.RequestInfo, comp
> + func MonitorRequest(req *http.Request, verb, group, version, resource, subresource, scope, component, contentType string, httpCode, respSize int, elapsed time.Duration) {
> +       reportedVerb := cleanVerb(verb, req)
> +       dryRun := cleanDryRun(req.URL)
> +-      client := cleanUserAgent(utilnet.GetHTTPClient(req))
> +       elapsedMicroseconds := float64(elapsed / time.Microsecond)
> +       elapsedSeconds := elapsed.Seconds()
> +-      requestCounter.WithLabelValues(reportedVerb, dryRun, group, version, resource, subresource, scope, component, client, contentType, codeToString(httpCode)).Inc()
> +-      deprecatedRequestCounter.WithLabelValues(reportedVerb, group, version, resource, subresource, scope, component, client, contentType, codeToString(httpCode)).Inc()
> ++      requestCounter.WithLabelValues(reportedVerb, dryRun, group, version, resource, subresource, scope, component, contentType, codeToString(httpCode)).Inc()
> ++      deprecatedRequestCounter.WithLabelValues(reportedVerb, group, version, resource, subresource, scope, component, contentType, codeToString(httpCode)).Inc()
> +       requestLatencies.WithLabelValues(reportedVerb, dryRun, group, version, resource, subresource, scope, component).Observe(elapsedSeconds)
> +       deprecatedRequestLatencies.WithLabelValues(reportedVerb, group, version, resource, subresource, scope, component).Observe(elapsedMicroseconds)
> +       deprecatedRequestLatenciesSummary.WithLabelValues(reportedVerb, group, version, resource, subresource, scope, component).Observe(elapsedMicroseconds)
> +@@ -355,19 +353,6 @@ func cleanDryRun(u *url.URL) string {
> +       return strings.Join(utilsets.NewString(dryRun...).List(), ",")
> + }
> +
> +-func cleanUserAgent(ua string) string {
> +-      // We collapse all "web browser"-type user agents into one "browser" to reduce metric cardinality.
> +-      if strings.HasPrefix(ua, "Mozilla/") {
> +-              return "Browser"
> +-      }
> +-      // If an old "kubectl.exe" has passed us its full path, we discard the path portion.
> +-      if kubectlExeRegexp.MatchString(ua) {
> +-              // avoid an allocation
> +-              ua = kubectlExeRegexp.ReplaceAllString(ua, "$1")
> +-      }
> +-      return ua
> +-}
> +-
> + // ResponseWriterDelegator interface wraps http.ResponseWriter to additionally record content-length, status-code, etc.
> + type ResponseWriterDelegator struct {
> +       http.ResponseWriter
> +diff --git a/src/import/staging/src/k8s.io/apiserver/pkg/endpoints/metrics/metrics_test.go b/src/import/staging/src/k8s.io/apiserver/pkg/endpoints/metrics/metrics_test.go
> +deleted file mode 100644
> +index 4c0a8aa5d27..00000000000
> +--- a/src/import/staging/src/k8s.io/apiserver/pkg/endpoints/metrics/metrics_test.go
> ++++ /dev/null
> +@@ -1,54 +0,0 @@
> +-/*
> +-Copyright 2015 The Kubernetes Authors.
> +-
> +-Licensed under the Apache License, Version 2.0 (the "License");
> +-you may not use this file except in compliance with the License.
> +-You may obtain a copy of the License at
> +-
> +-    http://www.apache.org/licenses/LICENSE-2.0
> +-
> +-Unless required by applicable law or agreed to in writing, software
> +-distributed under the License is distributed on an "AS IS" BASIS,
> +-WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
> +-See the License for the specific language governing permissions and
> +-limitations under the License.
> +-*/
> +-
> +-package metrics
> +-
> +-import "testing"
> +-
> +-func TestCleanUserAgent(t *testing.T) {
> +-      panicBuf := []byte{198, 73, 129, 133, 90, 216, 104, 29, 13, 134, 209, 233, 30, 0, 22}
> +-
> +-      for _, tc := range []struct {
> +-              In  string
> +-              Out string
> +-      }{
> +-              {
> +-                      In:  "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_11_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/52.0.2743.116 Safari/537.36",
> +-                      Out: "Browser",
> +-              },
> +-              {
> +-                      In:  "kubectl/v1.2.4",
> +-                      Out: "kubectl/v1.2.4",
> +-              },
> +-              {
> +-                      In:  `C:\Users\Kubernetes\kubectl.exe/v1.5.4`,
> +-                      Out: "kubectl.exe/v1.5.4",
> +-              },
> +-              {
> +-                      In:  `C:\Program Files\kubectl.exe/v1.5.4`,
> +-                      Out: "kubectl.exe/v1.5.4",
> +-              },
> +-              {
> +-                      // This malicious input courtesy of enisoc.
> +-                      In:  string(panicBuf) + "kubectl.exe",
> +-                      Out: "kubectl.exe",
> +-              },
> +-      } {
> +-              if cleanUserAgent(tc.In) != tc.Out {
> +-                      t.Errorf("Failed to clean User-Agent: %s", tc.In)
> +-              }
> +-      }
> +-}
> +--
> +2.17.0
> +
> diff --git a/recipes-containers/kubernetes/kubernetes_git.bb b/recipes-containers/kubernetes/kubernetes_git.bb
> index fae554d..c378ccc 100644
> --- a/recipes-containers/kubernetes/kubernetes_git.bb
> +++ b/recipes-containers/kubernetes/kubernetes_git.bb
> @@ -12,6 +12,8 @@ SRC_URI = "git://github.com/kubernetes/kubernetes.git;branch=release-1.16;name=k
>             file://0001-hack-lib-golang.sh-use-CC-from-environment.patch \
>             file://0001-cross-don-t-build-tests-by-default.patch \
>             file://0001-fix-compiling-failure-execvp-bin-bash-Argument-list-.patch \
> +           file://CVE-2020-8551.patch \
> +           file://CVE-2020-8552.patch \
>            "
>
>  DEPENDS += "rsync-native \
> --
> 2.23.0
>


-- 
- Thou shalt not follow the NULL pointer, for chaos and madness await
thee at its end
- "Use the force Harry" - Gandalf, Star Trek II

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

* Re: [meta-virtualization][zeus][PATCH] kubernetes: CVE-2020-8551 and CVE-2020-8552
       [not found]   ` <8d477377-0ec5-8414-09ab-8b0541e340b2@windriver.com>
@ 2020-05-13  2:03     ` Bruce Ashfield
  0 siblings, 0 replies; 2+ messages in thread
From: Bruce Ashfield @ 2020-05-13  2:03 UTC (permalink / raw)
  To: Zhixiong Chi; +Cc: meta-virtualization

On Tue, May 12, 2020 at 10:00 PM Zhixiong Chi
<zhixiong.chi@windriver.com> wrote:
>
> Hi Bruce,
>
> The zeus branch will also be rebased to 1.18-release, right?
>

I was considering it.

but now that you've replied, I can see that you tagged this as Zeus
and gmail hid that from me in the original listing (since I get all
these mail twice on the new lists, it threaded them).

I can merge this to Zeus and will consider 1.18 after.

Bruce

> Thanks,
>
>
> On 2020年05月12日 20:23, Bruce Ashfield wrote:
> > As mentioned previously (check the archives) I'm about to go to
> > 1.18-release so I won't be backporting any k8s CVE patches.
> >
> > If these are for a stable branch, indicate that clearly in the patch subject.
> >
> > Bruce
> >
> > On Tue, May 12, 2020 at 4:52 AM Zhixiong Chi <zhixiong.chi@windriver.com> wrote:
> >> Backport the CVE patches from the upstream:
> >> https://github.com/kubernetes/kubernetes.git
> >>
> >> Signed-off-by: Zhixiong Chi <zhixiong.chi@windriver.com>
> >> ---
> >>   .../kubernetes/kubernetes/CVE-2020-8551.patch | 303 ++++++++++++++++++
> >>   .../kubernetes/kubernetes/CVE-2020-8552.patch | 170 ++++++++++
> >>   .../kubernetes/kubernetes_git.bb              |   2 +
> >>   3 files changed, 475 insertions(+)
> >>   create mode 100644 recipes-containers/kubernetes/kubernetes/CVE-2020-8551.patch
> >>   create mode 100644 recipes-containers/kubernetes/kubernetes/CVE-2020-8552.patch
> >>
> >> diff --git a/recipes-containers/kubernetes/kubernetes/CVE-2020-8551.patch b/recipes-containers/kubernetes/kubernetes/CVE-2020-8551.patch
> >> new file mode 100644
> >> index 0000000..f1f87b0
> >> --- /dev/null
> >> +++ b/recipes-containers/kubernetes/kubernetes/CVE-2020-8551.patch
> >> @@ -0,0 +1,303 @@
> >> +From 9bae583cb0c46380866c3df5d7a6d26aac335818 Mon Sep 17 00:00:00 2001
> >> +From: Walter Fender <wfender@google.com>
> >> +Date: Thu, 6 Feb 2020 19:10:18 -0800
> >> +Subject: [PATCH] Add code to fix kubelet/metrics memory issue.
> >> +
> >> +Bucketing url paths based on concept/handling.
> >> +Bucketing code placed by handling code to encourage usage.
> >> +Added unit tests.
> >> +Fix format.
> >> +
> >> +CVE: CVE-2020-8551
> >> +Upstream-Status: Backport [https://github.com/kubernetes/kubernetes.git]
> >> +Signed-off-by: Zhixiong Chi <zhixiong.chi@windriver.com>
> >> +---
> >> + pkg/kubelet/server/server.go      | 56 ++++++++++++++++++++++++++++---
> >> + pkg/kubelet/server/server_test.go | 54 ++++++++++++++++++++++++++++-
> >> + 2 files changed, 105 insertions(+), 5 deletions(-)
> >> +
> >> +diff --git a/src/import/pkg/kubelet/server/server.go b/src/import/pkg/kubelet/server/server.go
> >> +index c1f1975fe43..f924304fc12 100644
> >> +--- a/src/import/pkg/kubelet/server/server.go
> >> ++++ b/src/import/pkg/kubelet/server/server.go
> >> +@@ -90,6 +90,7 @@ type Server struct {
> >> +       auth                       AuthInterface
> >> +       host                       HostInterface
> >> +       restfulCont                containerInterface
> >> ++      metricsBuckets             map[string]bool
> >> +       resourceAnalyzer           stats.ResourceAnalyzer
> >> +       redirectContainerStreaming bool
> >> + }
> >> +@@ -224,6 +225,7 @@ func NewServer(
> >> +               resourceAnalyzer:           resourceAnalyzer,
> >> +               auth:                       auth,
> >> +               restfulCont:                &filteringContainer{Container: restful.NewContainer()},
> >> ++              metricsBuckets:             make(map[string]bool),
> >> +               redirectContainerStreaming: redirectContainerStreaming,
> >> +       }
> >> +       if auth != nil {
> >> +@@ -279,14 +281,32 @@ func (s *Server) InstallAuthFilter() {
> >> +       })
> >> + }
> >> +
> >> ++// addMetricsBucketMatcher adds a regexp matcher and the relevant bucket to use when
> >> ++// it matches. Please be aware this is not thread safe and should not be used dynamically
> >> ++func (s *Server) addMetricsBucketMatcher(bucket string) {
> >> ++      s.metricsBuckets[bucket] = true
> >> ++}
> >> ++
> >> ++// getMetricBucket find the appropriate metrics reporting bucket for the given path
> >> ++func (s *Server) getMetricBucket(path string) string {
> >> ++      root := getURLRootPath(path)
> >> ++      if s.metricsBuckets[root] == true {
> >> ++              return root
> >> ++      }
> >> ++      return "Invalid path"
> >> ++}
> >> ++
> >> + // InstallDefaultHandlers registers the default set of supported HTTP request
> >> + // patterns with the restful Container.
> >> + func (s *Server) InstallDefaultHandlers(enableCAdvisorJSONEndpoints bool) {
> >> ++      s.addMetricsBucketMatcher("healthz")
> >> +       healthz.InstallHandler(s.restfulCont,
> >> +               healthz.PingHealthz,
> >> +               healthz.LogHealthz,
> >> +               healthz.NamedCheck("syncloop", s.syncLoopHealthCheck),
> >> +       )
> >> ++
> >> ++      s.addMetricsBucketMatcher("pods")
> >> +       ws := new(restful.WebService)
> >> +       ws.
> >> +               Path("/pods").
> >> +@@ -296,7 +316,14 @@ func (s *Server) InstallDefaultHandlers(enableCAdvisorJSONEndpoints bool) {
> >> +               Operation("getPods"))
> >> +       s.restfulCont.Add(ws)
> >> +
> >> ++      s.addMetricsBucketMatcher("stats")
> >> +       s.restfulCont.Add(stats.CreateHandlers(statsPath, s.host, s.resourceAnalyzer, enableCAdvisorJSONEndpoints))
> >> ++
> >> ++      s.addMetricsBucketMatcher("metrics")
> >> ++      s.addMetricsBucketMatcher("metrics/cadvisor")
> >> ++      s.addMetricsBucketMatcher("metrics/probes")
> >> ++      s.addMetricsBucketMatcher("metrics/resource/v1alpha1")
> >> ++      s.addMetricsBucketMatcher("metrics/resource")
> >> +       //lint:ignore SA1019 https://github.com/kubernetes/enhancements/issues/1206
> >> +       s.restfulCont.Handle(metricsPath, legacyregistry.Handler())
> >> +
> >> +@@ -316,6 +346,7 @@ func (s *Server) InstallDefaultHandlers(enableCAdvisorJSONEndpoints bool) {
> >> +               promhttp.HandlerFor(r, promhttp.HandlerOpts{ErrorHandling: promhttp.ContinueOnError}),
> >> +       )
> >> +
> >> ++      s.addMetricsBucketMatcher("metrics/resource/v1alpha1")
> >> +       v1alpha1ResourceRegistry := prometheus.NewRegistry()
> >> +       v1alpha1ResourceRegistry.MustRegister(stats.NewPrometheusResourceMetricCollector(s.resourceAnalyzer, v1alpha1.Config()))
> >> +       s.restfulCont.Handle(path.Join(resourceMetricsPathPrefix, v1alpha1.Version),
> >> +@@ -325,11 +357,14 @@ func (s *Server) InstallDefaultHandlers(enableCAdvisorJSONEndpoints bool) {
> >> +
> >> +       p := compbasemetrics.NewKubeRegistry()
> >> +       compbasemetrics.RegisterProcessStartTime(p.RawRegister)
> >> ++
> >> ++      s.addMetricsBucketMatcher("metrics/probes")
> >> +       p.MustRegister(prober.ProberResults)
> >> +       s.restfulCont.Handle(proberMetricsPath,
> >> +               promhttp.HandlerFor(p, promhttp.HandlerOpts{ErrorHandling: promhttp.ContinueOnError}),
> >> +       )
> >> +
> >> ++      s.addMetricsBucketMatcher("spec")
> >> +       if enableCAdvisorJSONEndpoints {
> >> +               ws := new(restful.WebService)
> >> +               ws.
> >> +@@ -349,6 +384,7 @@ const pprofBasePath = "/debug/pprof/"
> >> + func (s *Server) InstallDebuggingHandlers(criHandler http.Handler) {
> >> +       klog.Infof("Adding debug handlers to kubelet server.")
> >> +
> >> ++      s.addMetricsBucketMatcher("run")
> >> +       ws := new(restful.WebService)
> >> +       ws.
> >> +               Path("/run")
> >> +@@ -360,6 +396,7 @@ func (s *Server) InstallDebuggingHandlers(criHandler http.Handler) {
> >> +               Operation("getRun"))
> >> +       s.restfulCont.Add(ws)
> >> +
> >> ++      s.addMetricsBucketMatcher("exec")
> >> +       ws = new(restful.WebService)
> >> +       ws.
> >> +               Path("/exec")
> >> +@@ -377,6 +414,7 @@ func (s *Server) InstallDebuggingHandlers(criHandler http.Handler) {
> >> +               Operation("getExec"))
> >> +       s.restfulCont.Add(ws)
> >> +
> >> ++      s.addMetricsBucketMatcher("attach")
> >> +       ws = new(restful.WebService)
> >> +       ws.
> >> +               Path("/attach")
> >> +@@ -394,6 +432,7 @@ func (s *Server) InstallDebuggingHandlers(criHandler http.Handler) {
> >> +               Operation("getAttach"))
> >> +       s.restfulCont.Add(ws)
> >> +
> >> ++      s.addMetricsBucketMatcher("portForward")
> >> +       ws = new(restful.WebService)
> >> +       ws.
> >> +               Path("/portForward")
> >> +@@ -411,6 +450,7 @@ func (s *Server) InstallDebuggingHandlers(criHandler http.Handler) {
> >> +               Operation("getPortForward"))
> >> +       s.restfulCont.Add(ws)
> >> +
> >> ++      s.addMetricsBucketMatcher("logs")
> >> +       ws = new(restful.WebService)
> >> +       ws.
> >> +               Path(logsPath)
> >> +@@ -423,6 +463,7 @@ func (s *Server) InstallDebuggingHandlers(criHandler http.Handler) {
> >> +               Param(ws.PathParameter("logpath", "path to the log").DataType("string")))
> >> +       s.restfulCont.Add(ws)
> >> +
> >> ++      s.addMetricsBucketMatcher("containerLogs")
> >> +       ws = new(restful.WebService)
> >> +       ws.
> >> +               Path("/containerLogs")
> >> +@@ -431,8 +472,10 @@ func (s *Server) InstallDebuggingHandlers(criHandler http.Handler) {
> >> +               Operation("getContainerLogs"))
> >> +       s.restfulCont.Add(ws)
> >> +
> >> ++      s.addMetricsBucketMatcher("configz")
> >> +       configz.InstallHandler(s.restfulCont)
> >> +
> >> ++      s.addMetricsBucketMatcher("debug")
> >> +       handlePprofEndpoint := func(req *restful.Request, resp *restful.Response) {
> >> +               name := strings.TrimPrefix(req.Request.URL.Path, pprofBasePath)
> >> +               switch name {
> >> +@@ -448,7 +491,6 @@ func (s *Server) InstallDebuggingHandlers(criHandler http.Handler) {
> >> +                       pprof.Index(resp, req.Request)
> >> +               }
> >> +       }
> >> +-
> >> +       // Setup pprof handlers.
> >> +       ws = new(restful.WebService).Path(pprofBasePath)
> >> +       ws.Route(ws.GET("/{subpath:*}").To(func(req *restful.Request, resp *restful.Response) {
> >> +@@ -461,6 +503,7 @@ func (s *Server) InstallDebuggingHandlers(criHandler http.Handler) {
> >> +       s.restfulCont.Handle("/debug/flags/v", routes.StringFlagPutHandler(logs.GlogSetter))
> >> +
> >> +       // The /runningpods endpoint is used for testing only.
> >> ++      s.addMetricsBucketMatcher("runningpods")
> >> +       ws = new(restful.WebService)
> >> +       ws.
> >> +               Path("/runningpods/").
> >> +@@ -470,6 +513,7 @@ func (s *Server) InstallDebuggingHandlers(criHandler http.Handler) {
> >> +               Operation("getRunningPods"))
> >> +       s.restfulCont.Add(ws)
> >> +
> >> ++      s.addMetricsBucketMatcher("cri")
> >> +       if criHandler != nil {
> >> +               s.restfulCont.Handle("/cri/", criHandler)
> >> +       }
> >> +@@ -481,6 +525,14 @@ func (s *Server) InstallDebuggingDisabledHandlers() {
> >> +               http.Error(w, "Debug endpoints are disabled.", http.StatusMethodNotAllowed)
> >> +       })
> >> +
> >> ++      s.addMetricsBucketMatcher("run")
> >> ++      s.addMetricsBucketMatcher("exec")
> >> ++      s.addMetricsBucketMatcher("attach")
> >> ++      s.addMetricsBucketMatcher("portForward")
> >> ++      s.addMetricsBucketMatcher("containerLogs")
> >> ++      s.addMetricsBucketMatcher("runningpods")
> >> ++      s.addMetricsBucketMatcher("pprof")
> >> ++      s.addMetricsBucketMatcher("logs")
> >> +       paths := []string{
> >> +               "/run/", "/exec/", "/attach/", "/portForward/", "/containerLogs/",
> >> +               "/runningpods/", pprofBasePath, logsPath}
> >> +@@ -814,10 +849,10 @@ func (s *Server) getPortForward(request *restful.Request, response *restful.Resp
> >> +       proxyStream(response.ResponseWriter, request.Request, url)
> >> + }
> >> +
> >> +-// trimURLPath trims a URL path.
> >> ++// getURLRootPath trims a URL path.
> >> + // For paths in the format of "/metrics/xxx", "metrics/xxx" is returned;
> >> + // For all other paths, the first part of the path is returned.
> >> +-func trimURLPath(path string) string {
> >> ++func getURLRootPath(path string) string {
> >> +       parts := strings.SplitN(strings.TrimPrefix(path, "/"), "/", 3)
> >> +       if len(parts) == 0 {
> >> +               return path
> >> +@@ -865,7 +900,7 @@ func (s *Server) ServeHTTP(w http.ResponseWriter, req *http.Request) {
> >> +               serverType = "readwrite"
> >> +       }
> >> +
> >> +-      method, path := req.Method, trimURLPath(req.URL.Path)
> >> ++      method, path := req.Method, s.getMetricBucket(req.URL.Path)
> >> +
> >> +       longRunning := strconv.FormatBool(isLongRunningRequest(path))
> >> +
> >> +diff --git a/src/import/pkg/kubelet/server/server_test.go b/src/import/pkg/kubelet/server/server_test.go
> >> +index 4761d21afb7..a95e5d19f0b 100644
> >> +--- a/src/import/pkg/kubelet/server/server_test.go
> >> ++++ b/src/import/pkg/kubelet/server/server_test.go
> >> +@@ -1612,6 +1612,58 @@ func TestCRIHandler(t *testing.T) {
> >> +       assert.Equal(t, query, fw.criHandler.RequestReceived.URL.RawQuery)
> >> + }
> >> +
> >> ++func TestMetricBuckets(t *testing.T) {
> >> ++      tests := map[string]struct {
> >> ++              url    string
> >> ++              bucket string
> >> ++      }{
> >> ++              "healthz endpoint":                {url: "/healthz", bucket: "healthz"},
> >> ++              "attach":                          {url: "/attach/podNamespace/podID/containerName", bucket: "attach"},
> >> ++              "attach with uid":                 {url: "/attach/podNamespace/podID/uid/containerName", bucket: "attach"},
> >> ++              "configz":                         {url: "/configz", bucket: "configz"},
> >> ++              "containerLogs":                   {url: "/containerLogs/podNamespace/podID/containerName", bucket: "containerLogs"},
> >> ++              "cri":                             {url: "/cri/", bucket: "cri"},
> >> ++              "cri with sub":                    {url: "/cri/foo", bucket: "cri"},
> >> ++              "debug v flags":                   {url: "/debug/flags/v", bucket: "debug"},
> >> ++              "pprof with sub":                  {url: "/debug/pprof/subpath", bucket: "debug"},
> >> ++              "exec":                            {url: "/exec/podNamespace/podID/containerName", bucket: "exec"},
> >> ++              "exec with uid":                   {url: "/exec/podNamespace/podID/uid/containerName", bucket: "exec"},
> >> ++              "healthz":                         {url: "/healthz/", bucket: "healthz"},
> >> ++              "healthz log sub":                 {url: "/healthz/log", bucket: "healthz"},
> >> ++              "healthz ping":                    {url: "/healthz/ping", bucket: "healthz"},
> >> ++              "healthz sync loop":               {url: "/healthz/syncloop", bucket: "healthz"},
> >> ++              "logs":                            {url: "/logs/", bucket: "logs"},
> >> ++              "logs with path":                  {url: "/logs/logpath", bucket: "logs"},
> >> ++              "metrics":                         {url: "/metrics", bucket: "metrics"},
> >> ++              "metrics cadvisor sub":            {url: "/metrics/cadvisor", bucket: "metrics/cadvisor"},
> >> ++              "metrics probes sub":              {url: "/metrics/probes", bucket: "metrics/probes"},
> >> ++              "metrics resource v1alpha1":       {url: "/metrics/resource/v1alpha1", bucket: "metrics/resource"},
> >> ++              "metrics resource sub":            {url: "/metrics/resource", bucket: "metrics/resource"},
> >> ++              "pods":                            {url: "/pods/", bucket: "pods"},
> >> ++              "portForward":                     {url: "/portForward/podNamespace/podID", bucket: "portForward"},
> >> ++              "portForward with uid":            {url: "/portForward/podNamespace/podID/uid", bucket: "portForward"},
> >> ++              "run":                             {url: "/run/podNamespace/podID/containerName", bucket: "run"},
> >> ++              "run with uid":                    {url: "/run/podNamespace/podID/uid/containerName", bucket: "run"},
> >> ++              "runningpods":                     {url: "/runningpods/", bucket: "runningpods"},
> >> ++              "spec":                            {url: "/spec/", bucket: "spec"},
> >> ++              "stats":                           {url: "/stats/", bucket: "stats"},
> >> ++              "stats container sub":             {url: "/stats/container", bucket: "stats"},
> >> ++              "stats summary sub":               {url: "/stats/summary", bucket: "stats"},
> >> ++              "stats containerName with uid":    {url: "/stats/namespace/podName/uid/containerName", bucket: "stats"},
> >> ++              "stats containerName":             {url: "/stats/podName/containerName", bucket: "stats"},
> >> ++              "invalid path":                    {url: "/junk", bucket: "Invalid path"},
> >> ++              "invalid path starting with good": {url: "/healthzjunk", bucket: "Invalid path"},
> >> ++      }
> >> ++      fw := newServerTest()
> >> ++      defer fw.testHTTPServer.Close()
> >> ++
> >> ++      for _, test := range tests {
> >> ++              path := test.url
> >> ++              bucket := test.bucket
> >> ++              require.Equal(t, fw.serverUnderTest.getMetricBucket(path), bucket)
> >> ++      }
> >> ++}
> >> ++
> >> + func TestDebuggingDisabledHandlers(t *testing.T) {
> >> +       fw := newServerTestWithDebug(false, false, nil)
> >> +       defer fw.testHTTPServer.Close()
> >> +@@ -1685,6 +1737,6 @@ func TestTrimURLPath(t *testing.T) {
> >> +       }
> >> +
> >> +       for _, test := range tests {
> >> +-              assert.Equal(t, test.expected, trimURLPath(test.path), fmt.Sprintf("path is: %s", test.path))
> >> ++              assert.Equal(t, test.expected, getURLRootPath(test.path), fmt.Sprintf("path is: %s", test.path))
> >> +       }
> >> + }
> >> +--
> >> +2.17.0
> >> +
> >> diff --git a/recipes-containers/kubernetes/kubernetes/CVE-2020-8552.patch b/recipes-containers/kubernetes/kubernetes/CVE-2020-8552.patch
> >> new file mode 100644
> >> index 0000000..85d7fcb
> >> --- /dev/null
> >> +++ b/recipes-containers/kubernetes/kubernetes/CVE-2020-8552.patch
> >> @@ -0,0 +1,170 @@
> >> +From cc3190968b1f14ddf4067abef849fc41bd6068dc Mon Sep 17 00:00:00 2001
> >> +From: Han Kang <hankang@google.com>
> >> +Date: Wed, 29 Jan 2020 12:25:55 -0800
> >> +Subject: [PATCH] remove client label from apiserver request count metric since
> >> + it is unbounded
> >> +
> >> +Change-Id: I3a9eacebc9d9dc9ed6347260d9378cdcb5743431
> >> +
> >> +CVE: CVE-2020-8552
> >> +Upstream-Status: Backport [Cherry-picked from https://github.com/kubernetes/kubernetes.git tag:v1.18.0]
> >> +Signed-off-by: Zhixiong Chi <zhixiong.chi@windriver.com>
> >> +---
> >> + .../apiserver/pkg/endpoints/metrics/BUILD     |  8 ---
> >> + .../pkg/endpoints/metrics/metrics.go          | 21 ++------
> >> + .../pkg/endpoints/metrics/metrics_test.go     | 54 -------------------
> >> + 3 files changed, 3 insertions(+), 80 deletions(-)
> >> + delete mode 100644 staging/src/k8s.io/apiserver/pkg/endpoints/metrics/metrics_test.go
> >> +
> >> +diff --git a/src/import/staging/src/k8s.io/apiserver/pkg/endpoints/metrics/BUILD b/src/import/staging/src/k8s.io/apiserver/pkg/endpoints/metrics/BUILD
> >> +index 8d13a34eadc..8abb3d1a611 100644
> >> +--- a/src/import/staging/src/k8s.io/apiserver/pkg/endpoints/metrics/BUILD
> >> ++++ b/src/import/staging/src/k8s.io/apiserver/pkg/endpoints/metrics/BUILD
> >> +@@ -3,13 +3,6 @@ package(default_visibility = ["//visibility:public"])
> >> + load(
> >> +     "@io_bazel_rules_go//go:def.bzl",
> >> +     "go_library",
> >> +-    "go_test",
> >> +-)
> >> +-
> >> +-go_test(
> >> +-    name = "go_default_test",
> >> +-    srcs = ["metrics_test.go"],
> >> +-    embed = [":go_default_library"],
> >> + )
> >> +
> >> + go_library(
> >> +@@ -20,7 +13,6 @@ go_library(
> >> +     deps = [
> >> +         "//staging/src/k8s.io/apimachinery/pkg/apis/meta/v1/validation:go_default_library",
> >> +         "//staging/src/k8s.io/apimachinery/pkg/types:go_default_library",
> >> +-        "//staging/src/k8s.io/apimachinery/pkg/util/net:go_default_library",
> >> +         "//staging/src/k8s.io/apimachinery/pkg/util/sets:go_default_library",
> >> +         "//staging/src/k8s.io/apiserver/pkg/endpoints/request:go_default_library",
> >> +         "//staging/src/k8s.io/apiserver/pkg/features:go_default_library",
> >> +diff --git a/src/import/staging/src/k8s.io/apiserver/pkg/endpoints/metrics/metrics.go b/src/import/staging/src/k8s.io/apiserver/pkg/endpoints/metrics/metrics.go
> >> +index f4e02fbb6a8..c79efdef4e3 100644
> >> +--- a/src/import/staging/src/k8s.io/apiserver/pkg/endpoints/metrics/metrics.go
> >> ++++ b/src/import/staging/src/k8s.io/apiserver/pkg/endpoints/metrics/metrics.go
> >> +@@ -29,7 +29,6 @@ import (
> >> +
> >> +       "k8s.io/apimachinery/pkg/apis/meta/v1/validation"
> >> +       "k8s.io/apimachinery/pkg/types"
> >> +-      utilnet "k8s.io/apimachinery/pkg/util/net"
> >> +       utilsets "k8s.io/apimachinery/pkg/util/sets"
> >> +       "k8s.io/apiserver/pkg/endpoints/request"
> >> +       "k8s.io/apiserver/pkg/features"
> >> +@@ -66,14 +65,14 @@ var (
> >> +       requestCounter = compbasemetrics.NewCounterVec(
> >> +               &compbasemetrics.CounterOpts{
> >> +                       Name:           "apiserver_request_total",
> >> +-                      Help:           "Counter of apiserver requests broken out for each verb, dry run value, group, version, resource, scope, component, client, and HTTP response contentType and code.",
> >> ++                      Help:           "Counter of apiserver requests broken out for each verb, dry run value, group, version, resource, scope, component, and HTTP response contentType and code.",
> >> +                       StabilityLevel: compbasemetrics.ALPHA,
> >> +               },
> >> +               // The label_name contentType doesn't follow the label_name convention defined here:
> >> +               // https://github.com/kubernetes/community/blob/master/contributors/devel/sig-instrumentation/instrumentation.md
> >> +               // But changing it would break backwards compatibility. Future label_names
> >> +               // should be all lowercase and separated by underscores.
> >> +-              []string{"verb", "dry_run", "group", "version", "resource", "subresource", "scope", "component", "client", "contentType", "code"},
> >> ++              []string{"verb", "dry_run", "group", "version", "resource", "subresource", "scope", "component", "contentType", "code"},
> >> +       )
> >> +       deprecatedRequestCounter = compbasemetrics.NewCounterVec(
> >> +               &compbasemetrics.CounterOpts{
> >> +@@ -243,11 +242,10 @@ func RecordLongRunning(req *http.Request, requestInfo *request.RequestInfo, comp
> >> + func MonitorRequest(req *http.Request, verb, group, version, resource, subresource, scope, component, contentType string, httpCode, respSize int, elapsed time.Duration) {
> >> +       reportedVerb := cleanVerb(verb, req)
> >> +       dryRun := cleanDryRun(req.URL)
> >> +-      client := cleanUserAgent(utilnet.GetHTTPClient(req))
> >> +       elapsedMicroseconds := float64(elapsed / time.Microsecond)
> >> +       elapsedSeconds := elapsed.Seconds()
> >> +-      requestCounter.WithLabelValues(reportedVerb, dryRun, group, version, resource, subresource, scope, component, client, contentType, codeToString(httpCode)).Inc()
> >> +-      deprecatedRequestCounter.WithLabelValues(reportedVerb, group, version, resource, subresource, scope, component, client, contentType, codeToString(httpCode)).Inc()
> >> ++      requestCounter.WithLabelValues(reportedVerb, dryRun, group, version, resource, subresource, scope, component, contentType, codeToString(httpCode)).Inc()
> >> ++      deprecatedRequestCounter.WithLabelValues(reportedVerb, group, version, resource, subresource, scope, component, contentType, codeToString(httpCode)).Inc()
> >> +       requestLatencies.WithLabelValues(reportedVerb, dryRun, group, version, resource, subresource, scope, component).Observe(elapsedSeconds)
> >> +       deprecatedRequestLatencies.WithLabelValues(reportedVerb, group, version, resource, subresource, scope, component).Observe(elapsedMicroseconds)
> >> +       deprecatedRequestLatenciesSummary.WithLabelValues(reportedVerb, group, version, resource, subresource, scope, component).Observe(elapsedMicroseconds)
> >> +@@ -355,19 +353,6 @@ func cleanDryRun(u *url.URL) string {
> >> +       return strings.Join(utilsets.NewString(dryRun...).List(), ",")
> >> + }
> >> +
> >> +-func cleanUserAgent(ua string) string {
> >> +-      // We collapse all "web browser"-type user agents into one "browser" to reduce metric cardinality.
> >> +-      if strings.HasPrefix(ua, "Mozilla/") {
> >> +-              return "Browser"
> >> +-      }
> >> +-      // If an old "kubectl.exe" has passed us its full path, we discard the path portion.
> >> +-      if kubectlExeRegexp.MatchString(ua) {
> >> +-              // avoid an allocation
> >> +-              ua = kubectlExeRegexp.ReplaceAllString(ua, "$1")
> >> +-      }
> >> +-      return ua
> >> +-}
> >> +-
> >> + // ResponseWriterDelegator interface wraps http.ResponseWriter to additionally record content-length, status-code, etc.
> >> + type ResponseWriterDelegator struct {
> >> +       http.ResponseWriter
> >> +diff --git a/src/import/staging/src/k8s.io/apiserver/pkg/endpoints/metrics/metrics_test.go b/src/import/staging/src/k8s.io/apiserver/pkg/endpoints/metrics/metrics_test.go
> >> +deleted file mode 100644
> >> +index 4c0a8aa5d27..00000000000
> >> +--- a/src/import/staging/src/k8s.io/apiserver/pkg/endpoints/metrics/metrics_test.go
> >> ++++ /dev/null
> >> +@@ -1,54 +0,0 @@
> >> +-/*
> >> +-Copyright 2015 The Kubernetes Authors.
> >> +-
> >> +-Licensed under the Apache License, Version 2.0 (the "License");
> >> +-you may not use this file except in compliance with the License.
> >> +-You may obtain a copy of the License at
> >> +-
> >> +-    http://www.apache.org/licenses/LICENSE-2.0
> >> +-
> >> +-Unless required by applicable law or agreed to in writing, software
> >> +-distributed under the License is distributed on an "AS IS" BASIS,
> >> +-WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
> >> +-See the License for the specific language governing permissions and
> >> +-limitations under the License.
> >> +-*/
> >> +-
> >> +-package metrics
> >> +-
> >> +-import "testing"
> >> +-
> >> +-func TestCleanUserAgent(t *testing.T) {
> >> +-      panicBuf := []byte{198, 73, 129, 133, 90, 216, 104, 29, 13, 134, 209, 233, 30, 0, 22}
> >> +-
> >> +-      for _, tc := range []struct {
> >> +-              In  string
> >> +-              Out string
> >> +-      }{
> >> +-              {
> >> +-                      In:  "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_11_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/52.0.2743.116 Safari/537.36",
> >> +-                      Out: "Browser",
> >> +-              },
> >> +-              {
> >> +-                      In:  "kubectl/v1.2.4",
> >> +-                      Out: "kubectl/v1.2.4",
> >> +-              },
> >> +-              {
> >> +-                      In:  `C:\Users\Kubernetes\kubectl.exe/v1.5.4`,
> >> +-                      Out: "kubectl.exe/v1.5.4",
> >> +-              },
> >> +-              {
> >> +-                      In:  `C:\Program Files\kubectl.exe/v1.5.4`,
> >> +-                      Out: "kubectl.exe/v1.5.4",
> >> +-              },
> >> +-              {
> >> +-                      // This malicious input courtesy of enisoc.
> >> +-                      In:  string(panicBuf) + "kubectl.exe",
> >> +-                      Out: "kubectl.exe",
> >> +-              },
> >> +-      } {
> >> +-              if cleanUserAgent(tc.In) != tc.Out {
> >> +-                      t.Errorf("Failed to clean User-Agent: %s", tc.In)
> >> +-              }
> >> +-      }
> >> +-}
> >> +--
> >> +2.17.0
> >> +
> >> diff --git a/recipes-containers/kubernetes/kubernetes_git.bb b/recipes-containers/kubernetes/kubernetes_git.bb
> >> index fae554d..c378ccc 100644
> >> --- a/recipes-containers/kubernetes/kubernetes_git.bb
> >> +++ b/recipes-containers/kubernetes/kubernetes_git.bb
> >> @@ -12,6 +12,8 @@ SRC_URI = "git://github.com/kubernetes/kubernetes.git;branch=release-1.16;name=k
> >>              file://0001-hack-lib-golang.sh-use-CC-from-environment.patch \
> >>              file://0001-cross-don-t-build-tests-by-default.patch \
> >>              file://0001-fix-compiling-failure-execvp-bin-bash-Argument-list-.patch \
> >> +           file://CVE-2020-8551.patch \
> >> +           file://CVE-2020-8552.patch \
> >>             "
> >>
> >>   DEPENDS += "rsync-native \
> >> --
> >> 2.23.0
> >>
> >
>
> --
> ---------------------
> Thanks,
> Zhixiong Chi
> Tel: +86-10-8477-7036
>


-- 
- Thou shalt not follow the NULL pointer, for chaos and madness await
thee at its end
- "Use the force Harry" - Gandalf, Star Trek II

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

end of thread, other threads:[~2020-05-13  2:04 UTC | newest]

Thread overview: 2+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
     [not found] <20200512085232.72315-1-zhixiong.chi@windriver.com>
2020-05-12 12:23 ` [meta-virtualization][zeus][PATCH] kubernetes: CVE-2020-8551 and CVE-2020-8552 Bruce Ashfield
     [not found]   ` <8d477377-0ec5-8414-09ab-8b0541e340b2@windriver.com>
2020-05-13  2:03     ` Bruce Ashfield

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.