From e9fea0b72cb7e7dc92c712461c03c3d0cd894ce6 Mon Sep 17 00:00:00 2001 From: CBL-Mariner-Bot <75509084+CBL-Mariner-Bot@users.noreply.github.com> Date: Thu, 1 Feb 2024 15:39:42 -0800 Subject: [PATCH] [AUTO-CHERRYPICK] fix cve-2022-21698 in local-path-provisioner - branch main (#7626) Fixes CVE-2022-21698 for local-path-provisioner. The vulnerability is in the client_golang go module, which is vendored in this package. Fix is to apply a (modified) patch to the vendored code. Co-authored-by: Tobias Brick <39196763+tobiasb-ms@users.noreply.github.com> --- .../CVE-2022-21698.patch | 364 ++++++++++++++++++ .../local-path-provisioner.spec | 8 +- 2 files changed, 371 insertions(+), 1 deletion(-) create mode 100644 SPECS/local-path-provisioner/CVE-2022-21698.patch diff --git a/SPECS/local-path-provisioner/CVE-2022-21698.patch b/SPECS/local-path-provisioner/CVE-2022-21698.patch new file mode 100644 index 0000000000..d182f16619 --- /dev/null +++ b/SPECS/local-path-provisioner/CVE-2022-21698.patch @@ -0,0 +1,364 @@ +From 253029f7ffbade99588df59a8b89a35d99197fe0 Mon Sep 17 00:00:00 2001 +From: Tobias Brick +Date: Tue, 18 Jan 2022 10:19:28 +0100 +Subject: [PATCH] Port upstream patch + https://github.com/prometheus/client_golang/commit/9075cdf61646b5adf54d3ba77a0e4f6c65cb4fd7 + +Differences: +- Removed tests +- Removed some comments that don't merge +- Line numbers and such + +Based on: + +From 9075cdf61646b5adf54d3ba77a0e4f6c65cb4fd7 Mon Sep 17 00:00:00 2001 +From: Kemal Akkoyun +Date: Tue, 18 Jan 2022 10:19:28 +0100 +Subject: [PATCH] promhttp: Check validity of method and code label values + (#962) + +* Check validity of method and code label values + +Signed-off-by: Kemal Akkoyun + +* Use more flexibly functional option pattern for configuration + +Signed-off-by: Kemal Akkoyun + +* Update documentation + +Signed-off-by: Kemal Akkoyun + +* Simplify + +Signed-off-by: Kemal Akkoyun + +* Fix inconsistent method naming + +Signed-off-by: Kemal Akkoyun +--- + prometheus/promhttp/instrument_client.go | 28 ++++++-- + prometheus/promhttp/instrument_server.go | 82 ++++++++++++++++++------ + prometheus/promhttp/option.go | 31 +++++++++ + 3 files changed, 116 insertions(+), 25 deletions(-) + create mode 100644 prometheus/promhttp/option.go + +diff --git a/prometheus/promhttp/instrument_client.go b/prometheus/promhttp/instrument_client.go +index 83c49b6..861b4d2 100644 +--- a/prometheus/promhttp/instrument_client.go ++++ b/prometheus/promhttp/instrument_client.go +@@ -49,7 +49,10 @@ func InstrumentRoundTripperInFlight(gauge prometheus.Gauge, next http.RoundTripp + // http.RoundTripper to observe the request result with the provided CounterVec. + // The CounterVec must have zero, one, or two non-const non-curried labels. For + // those, the only allowed label names are "code" and "method". The function +-// panics otherwise. Partitioning of the CounterVec happens by HTTP status code ++// panics otherwise. For the "method" label a predefined default label value set ++// is used to filter given values. Values besides predefined values will count ++// as `unknown` method.`WithExtraMethods` can be used to add more ++// methods to the set. Partitioning of the CounterVec happens by HTTP status code + // and/or HTTP method if the respective instance label names are present in the + // CounterVec. For unpartitioned counting, use a CounterVec with zero labels. + // +@@ -57,13 +60,18 @@ func InstrumentRoundTripperInFlight(gauge prometheus.Gauge, next http.RoundTripp + // is not incremented. + // + // See the example for ExampleInstrumentRoundTripperDuration for example usage. +-func InstrumentRoundTripperCounter(counter *prometheus.CounterVec, next http.RoundTripper) RoundTripperFunc { ++func InstrumentRoundTripperCounter(counter *prometheus.CounterVec, next http.RoundTripper, opts ...Option) RoundTripperFunc { ++ rtOpts := &option{} ++ for _, o := range opts { ++ o(rtOpts) ++ } ++ + code, method := checkLabels(counter) + + return RoundTripperFunc(func(r *http.Request) (*http.Response, error) { + resp, err := next.RoundTrip(r) + if err == nil { +- counter.With(labels(code, method, r.Method, resp.StatusCode)).Inc() ++ counter.With(labels(code, method, r.Method, resp.StatusCode, rtOpts.extraMethods...)).Inc() + } + return resp, err + }) +@@ -73,7 +81,10 @@ func InstrumentRoundTripperCounter(counter *prometheus.CounterVec, next http.Rou + // http.RoundTripper to observe the request duration with the provided + // ObserverVec. The ObserverVec must have zero, one, or two non-const + // non-curried labels. For those, the only allowed label names are "code" and +-// "method". The function panics otherwise. The Observe method of the Observer ++// "method". The function panics otherwise. For the "method" label a predefined ++// default label value set is used to filter given values. Values besides ++// predefined values will count as `unknown` method. `WithExtraMethods` ++// can be used to add more methods to the set. The Observe method of the Observer + // in the ObserverVec is called with the request duration in + // seconds. Partitioning happens by HTTP status code and/or HTTP method if the + // respective instance label names are present in the ObserverVec. For +@@ -85,14 +96,19 @@ func InstrumentRoundTripperCounter(counter *prometheus.CounterVec, next http.Rou + // + // Note that this method is only guaranteed to never observe negative durations + // if used with Go1.9+. +-func InstrumentRoundTripperDuration(obs prometheus.ObserverVec, next http.RoundTripper) RoundTripperFunc { ++func InstrumentRoundTripperDuration(obs prometheus.ObserverVec, next http.RoundTripper, opts ...Option) RoundTripperFunc { ++ rtOpts := &option{} ++ for _, o := range opts { ++ o(rtOpts) ++ } ++ + code, method := checkLabels(obs) + + return RoundTripperFunc(func(r *http.Request) (*http.Response, error) { + start := time.Now() + resp, err := next.RoundTrip(r) + if err == nil { +- obs.With(labels(code, method, r.Method, resp.StatusCode)).Observe(time.Since(start).Seconds()) ++ obs.With(labels(code, method, r.Method, resp.StatusCode, rtOpts.extraMethods...)).Observe(time.Since(start).Seconds()) + } + return resp, err + }) +diff --git a/prometheus/promhttp/instrument_server.go b/prometheus/promhttp/instrument_server.go +index 9db2438..91802f8 100644 +--- a/prometheus/promhttp/instrument_server.go ++++ b/prometheus/promhttp/instrument_server.go +@@ -58,7 +58,12 @@ func InstrumentHandlerInFlight(g prometheus.Gauge, next http.Handler) http.Handl + // + // Note that this method is only guaranteed to never observe negative durations + // if used with Go1.9+. +-func InstrumentHandlerDuration(obs prometheus.ObserverVec, next http.Handler) http.HandlerFunc { ++func InstrumentHandlerDuration(obs prometheus.ObserverVec, next http.Handler, opts ...Option) http.HandlerFunc { ++ mwOpts := &option{} ++ for _, o := range opts { ++ o(mwOpts) ++ } ++ + code, method := checkLabels(obs) + + if code { +@@ -67,14 +72,14 @@ func InstrumentHandlerDuration(obs prometheus.ObserverVec, next http.Handler) ht + d := newDelegator(w, nil) + next.ServeHTTP(d, r) + +- obs.With(labels(code, method, r.Method, d.Status())).Observe(time.Since(now).Seconds()) ++ obs.With(labels(code, method, r.Method, d.Status(), mwOpts.extraMethods...)).Observe(time.Since(now).Seconds()) + }) + } + + return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { + now := time.Now() + next.ServeHTTP(w, r) +- obs.With(labels(code, method, r.Method, 0)).Observe(time.Since(now).Seconds()) ++ obs.With(labels(code, method, r.Method, 0, mwOpts.extraMethods...)).Observe(time.Since(now).Seconds()) + }) + } + +@@ -91,20 +96,25 @@ func InstrumentHandlerDuration(obs prometheus.ObserverVec, next http.Handler) ht + // If the wrapped Handler panics, the Counter is not incremented. + // + // See the example for InstrumentHandlerDuration for example usage. +-func InstrumentHandlerCounter(counter *prometheus.CounterVec, next http.Handler) http.HandlerFunc { ++func InstrumentHandlerCounter(counter *prometheus.CounterVec, next http.Handler, opts ...Option) http.HandlerFunc { ++ mwOpts := &option{} ++ for _, o := range opts { ++ o(mwOpts) ++ } ++ + code, method := checkLabels(counter) + + if code { + return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { + d := newDelegator(w, nil) + next.ServeHTTP(d, r) +- counter.With(labels(code, method, r.Method, d.Status())).Inc() ++ counter.With(labels(code, method, r.Method, d.Status(), mwOpts.extraMethods...)).Inc() + }) + } + + return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { + next.ServeHTTP(w, r) +- counter.With(labels(code, method, r.Method, 0)).Inc() ++ counter.With(labels(code, method, r.Method, 0, mwOpts.extraMethods...)).Inc() + }) + } + +@@ -126,13 +136,18 @@ func InstrumentHandlerCounter(counter *prometheus.CounterVec, next http.Handler) + // if used with Go1.9+. + // + // See the example for InstrumentHandlerDuration for example usage. +-func InstrumentHandlerTimeToWriteHeader(obs prometheus.ObserverVec, next http.Handler) http.HandlerFunc { ++func InstrumentHandlerTimeToWriteHeader(obs prometheus.ObserverVec, next http.Handler, opts ...Option) http.HandlerFunc { ++ mwOpts := &option{} ++ for _, o := range opts { ++ o(mwOpts) ++ } ++ + code, method := checkLabels(obs) + + return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { + now := time.Now() + d := newDelegator(w, func(status int) { +- obs.With(labels(code, method, r.Method, status)).Observe(time.Since(now).Seconds()) ++ obs.With(labels(code, method, r.Method, status, mwOpts.extraMethods...)).Observe(time.Since(now).Seconds()) + }) + next.ServeHTTP(d, r) + }) +@@ -154,7 +169,12 @@ func InstrumentHandlerTimeToWriteHeader(obs prometheus.ObserverVec, next http.Ha + // If the wrapped Handler panics, no values are reported. + // + // See the example for InstrumentHandlerDuration for example usage. +-func InstrumentHandlerRequestSize(obs prometheus.ObserverVec, next http.Handler) http.HandlerFunc { ++func InstrumentHandlerRequestSize(obs prometheus.ObserverVec, next http.Handler, opts ...Option) http.HandlerFunc { ++ mwOpts := &option{} ++ for _, o := range opts { ++ o(mwOpts) ++ } ++ + code, method := checkLabels(obs) + + if code { +@@ -162,14 +182,14 @@ func InstrumentHandlerRequestSize(obs prometheus.ObserverVec, next http.Handler) + d := newDelegator(w, nil) + next.ServeHTTP(d, r) + size := computeApproximateRequestSize(r) +- obs.With(labels(code, method, r.Method, d.Status())).Observe(float64(size)) ++ obs.With(labels(code, method, r.Method, d.Status(), mwOpts.extraMethods...)).Observe(float64(size)) + }) + } + + return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { + next.ServeHTTP(w, r) + size := computeApproximateRequestSize(r) +- obs.With(labels(code, method, r.Method, 0)).Observe(float64(size)) ++ obs.With(labels(code, method, r.Method, 0, mwOpts.extraMethods...)).Observe(float64(size)) + }) + } + +@@ -189,12 +209,18 @@ func InstrumentHandlerRequestSize(obs prometheus.ObserverVec, next http.Handler) + // If the wrapped Handler panics, no values are reported. + // + // See the example for InstrumentHandlerDuration for example usage. +-func InstrumentHandlerResponseSize(obs prometheus.ObserverVec, next http.Handler) http.Handler { ++func InstrumentHandlerResponseSize(obs prometheus.ObserverVec, next http.Handler, opts ...Option) http.Handler { ++ mwOpts := &option{} ++ for _, o := range opts { ++ o(mwOpts) ++ } ++ + code, method := checkLabels(obs) ++ + return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { + d := newDelegator(w, nil) + next.ServeHTTP(d, r) +- obs.With(labels(code, method, r.Method, d.Status())).Observe(float64(d.Written())) ++ obs.With(labels(code, method, r.Method, d.Status(), mwOpts.extraMethods...)).Observe(float64(d.Written())) + }) + } + +@@ -279,7 +305,7 @@ func isLabelCurried(c prometheus.Collector, label string) bool { + // unnecessary allocations on each request. + var emptyLabels = prometheus.Labels{} + +-func labels(code, method bool, reqMethod string, status int) prometheus.Labels { ++func labels(code, method bool, reqMethod string, status int, extraMethods ...string) prometheus.Labels { + if !(code || method) { + return emptyLabels + } +@@ -289,7 +315,7 @@ func labels(code, method bool, reqMethod string, status int) prometheus.Labels { + labels["code"] = sanitizeCode(status) + } + if method { +- labels["method"] = sanitizeMethod(reqMethod) ++ labels["method"] = sanitizeMethod(reqMethod, extraMethods...) + } + + return labels +@@ -319,7 +345,12 @@ func computeApproximateRequestSize(r *http.Request) int { + return s + } + +-func sanitizeMethod(m string) string { ++// If the wrapped http.Handler has a known method, it will be sanitized and returned. ++// Otherwise, "unknown" will be returned. The known method list can be extended ++// as needed by using extraMethods parameter. ++func sanitizeMethod(m string, extraMethods ...string) string { ++ // See https://developer.mozilla.org/en-US/docs/Web/HTTP/Methods for ++ // the methods chosen as default. + switch m { + case "GET", "get": + return "get" +@@ -337,15 +368,25 @@ func sanitizeMethod(m string) string { + return "options" + case "NOTIFY", "notify": + return "notify" ++ case "TRACE", "trace": ++ return "trace" ++ case "PATCH", "patch": ++ return "patch" + default: +- return strings.ToLower(m) ++ for _, method := range extraMethods { ++ if strings.EqualFold(m, method) { ++ return strings.ToLower(m) ++ } ++ } ++ return "unknown" + } + } + + // If the wrapped http.Handler has not set a status code, i.e. the value is +-// currently 0, santizeCode will return 200, for consistency with behavior in ++// currently 0, sanitizeCode will return 200, for consistency with behavior in + // the stdlib. + func sanitizeCode(s int) string { ++ // See for accepted codes https://www.iana.org/assignments/http-status-codes/http-status-codes.xhtml + switch s { + case 100: + return "100" +@@ -442,6 +483,9 @@ func sanitizeCode(s int) string { + return "511" + + default: +- return strconv.Itoa(s) ++ if s >= 100 && s <= 599 { ++ return strconv.Itoa(s) ++ } ++ return "unknown" + } + } +diff --git a/prometheus/promhttp/option.go b/prometheus/promhttp/option.go +new file mode 100644 +index 0000000..35e41bd +--- /dev/null ++++ b/prometheus/promhttp/option.go +@@ -0,0 +1,31 @@ ++// Copyright 2022 The Prometheus 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 promhttp ++ ++// Option are used to configure a middleware or round tripper.. ++type Option func(*option) ++ ++type option struct { ++ extraMethods []string ++} ++ ++// WithExtraMethods adds additional HTTP methods to the list of allowed methods. ++// See https://developer.mozilla.org/en-US/docs/Web/HTTP/Methods for the default list. ++// ++// See the example for ExampleInstrumentHandlerWithExtraMethods for example usage. ++func WithExtraMethods(methods ...string) Option { ++ return func(o *option) { ++ o.extraMethods = methods ++ } ++} +-- +2.33.8 + diff --git a/SPECS/local-path-provisioner/local-path-provisioner.spec b/SPECS/local-path-provisioner/local-path-provisioner.spec index a106b0a32b..8b59d743ca 100644 --- a/SPECS/local-path-provisioner/local-path-provisioner.spec +++ b/SPECS/local-path-provisioner/local-path-provisioner.spec @@ -1,7 +1,7 @@ Summary: Provides a way for the Kubernetes users to utilize the local storage in each node Name: local-path-provisioner Version: 0.0.21 -Release: 13%{?dist} +Release: 14%{?dist} License: ASL 2.0 URL: https://github.com/rancher/local-path-provisioner Group: Applications/Text @@ -9,6 +9,8 @@ Vendor: Microsoft Distribution: Mariner Source0: https://github.com/rancher/%{name}/archive/refs/tags/v%{version}.tar.gz#/%{name}-%{version}.tar.gz #Note that the source file should be renamed to the format {name}-%{version}.tar.gz +# Fixed in upstream 0.0.24, so we can remove this patch when we upgrade to that version +Patch0: CVE-2022-21698.patch BuildRequires: golang @@ -17,6 +19,7 @@ Provides a way for the Kubernetes users to utilize the local storage in each nod %prep %setup -q +%patch 0 -p1 -d vendor/github.com/prometheus/client_golang %build export CGO_ENABLED=0 @@ -30,6 +33,9 @@ install local-path-provisioner %{buildroot}%{_bindir}/local-path-provisioner %{_bindir}/local-path-provisioner %changelog +* Wed Jan 31 2024 Tobias Brick - 0.0.21-14 +- Fix CVE-2022-21698 + * Mon Oct 16 2023 CBL-Mariner Servicing Account - 0.0.21-13 - Bump release to rebuild with go 1.20.9