From f55af6f676e501070f42fb591950a1969426034c Mon Sep 17 00:00:00 2001 From: Cameron E Baird Date: Thu, 25 Apr 2024 08:23:07 -0700 Subject: [PATCH] Apply patches to fix CVE-2021-3602, CVE-2022-27651, CVE-2022-2995, CVE-2023-42821 (#8818) Co-authored-by: dallasd1 Co-authored-by: Dallas Delaney <106280731+dallasd1@users.noreply.github.com> Co-authored-by: Muhammad Falak R Wani Co-authored-by: jslobodzian --- SPECS/cri-o/CVE-2021-3602.patch | 119 ++++++++ SPECS/cri-o/CVE-2021-44716.patch | 45 +++ SPECS/cri-o/CVE-2022-21698.patch | 487 +++++++++++++++++++++++++++++++ SPECS/cri-o/CVE-2022-27651.patch | 50 ++++ SPECS/cri-o/CVE-2022-29526.patch | 25 ++ SPECS/cri-o/CVE-2022-2995.patch | 55 ++++ SPECS/cri-o/CVE-2023-42821.patch | 54 ++++ SPECS/cri-o/CVE-2023-44487.patch | 228 +++++++++++++++ SPECS/cri-o/CVE-2024-28180.patch | 88 ++++++ SPECS/cri-o/cri-o.spec | 17 +- 10 files changed, 1166 insertions(+), 2 deletions(-) create mode 100644 SPECS/cri-o/CVE-2021-3602.patch create mode 100644 SPECS/cri-o/CVE-2021-44716.patch create mode 100644 SPECS/cri-o/CVE-2022-21698.patch create mode 100644 SPECS/cri-o/CVE-2022-27651.patch create mode 100644 SPECS/cri-o/CVE-2022-29526.patch create mode 100644 SPECS/cri-o/CVE-2022-2995.patch create mode 100644 SPECS/cri-o/CVE-2023-42821.patch create mode 100644 SPECS/cri-o/CVE-2023-44487.patch create mode 100644 SPECS/cri-o/CVE-2024-28180.patch diff --git a/SPECS/cri-o/CVE-2021-3602.patch b/SPECS/cri-o/CVE-2021-3602.patch new file mode 100644 index 0000000000..5aa911ce0c --- /dev/null +++ b/SPECS/cri-o/CVE-2021-3602.patch @@ -0,0 +1,119 @@ +From 8716daa06e9eb421438b338f18b6b650b082b208 Mon Sep 17 00:00:00 2001 +From: Cameron Baird +Date: Tue, 16 Apr 2024 22:33:46 +0000 +Subject: [PATCH 4/4] CVE-2021-3602 + +--- + .../github.com/containers/buildah/chroot/run.go | 15 +++++---------- + .../podman/v3/pkg/specgen/generate/security.go | 7 +++++-- + 2 files changed, 10 insertions(+), 12 deletions(-) + +diff --git a/vendor/github.com/containers/buildah/chroot/run.go b/vendor/github.com/containers/buildah/chroot/run.go +index a93f97dcd..643f5c91d 100644 +--- a/vendor/github.com/containers/buildah/chroot/run.go ++++ b/vendor/github.com/containers/buildah/chroot/run.go +@@ -160,7 +160,7 @@ func RunUsingChroot(spec *specs.Spec, bundlePath, homeDir string, stdin io.Reade + cmd := unshare.Command(runUsingChrootCommand) + cmd.Stdin, cmd.Stdout, cmd.Stderr = stdin, stdout, stderr + cmd.Dir = "/" +- cmd.Env = append([]string{fmt.Sprintf("LOGLEVEL=%d", logrus.GetLevel())}, os.Environ()...) ++ cmd.Env = []string{fmt.Sprintf("LOGLEVEL=%d", logrus.GetLevel())} + + logrus.Debugf("Running %#v in %#v", cmd.Cmd, cmd) + confwg.Add(1) +@@ -206,7 +206,7 @@ func runUsingChrootMain() { + os.Exit(1) + } + +- if options.Spec == nil { ++ if options.Spec == nil || options.Spec.Process == nil { + fmt.Fprintf(os.Stderr, "invalid options spec in runUsingChrootMain\n") + os.Exit(1) + } +@@ -572,7 +572,7 @@ func runUsingChroot(spec *specs.Spec, bundlePath string, ctty *os.File, stdin io + cmd := unshare.Command(append([]string{runUsingChrootExecCommand}, spec.Process.Args...)...) + cmd.Stdin, cmd.Stdout, cmd.Stderr = stdin, stdout, stderr + cmd.Dir = "/" +- cmd.Env = append([]string{fmt.Sprintf("LOGLEVEL=%d", logrus.GetLevel())}, os.Environ()...) ++ cmd.Env = []string{fmt.Sprintf("LOGLEVEL=%d", logrus.GetLevel())} + cmd.UnshareFlags = syscall.CLONE_NEWUTS | syscall.CLONE_NEWNS + requestedUserNS := false + for _, ns := range spec.Linux.Namespaces { +@@ -662,7 +662,7 @@ func runUsingChrootExecMain() { + // Set the hostname. We're already in a distinct UTS namespace and are admins in the user + // namespace which created it, so we shouldn't get a permissions error, but seccomp policy + // might deny our attempt to call sethostname() anyway, so log a debug message for that. +- if options.Spec == nil { ++ if options.Spec == nil || options.Spec.Process == nil { + fmt.Fprintf(os.Stderr, "invalid options spec passed in\n") + os.Exit(1) + } +@@ -818,7 +818,6 @@ func runUsingChrootExecMain() { + // Output debug messages when that differs from what we're being asked to do. + func logNamespaceDiagnostics(spec *specs.Spec) { + sawMountNS := false +- sawUserNS := false + sawUTSNS := false + for _, ns := range spec.Linux.Namespaces { + switch ns.Type { +@@ -853,9 +852,8 @@ func logNamespaceDiagnostics(spec *specs.Spec) { + } + case specs.UserNamespace: + if ns.Path != "" { +- logrus.Debugf("unable to join user namespace %q, creating a new one", ns.Path) ++ logrus.Debugf("unable to join user namespace, sorry about that") + } +- sawUserNS = true + case specs.UTSNamespace: + if ns.Path != "" { + logrus.Debugf("unable to join UTS namespace %q, creating a new one", ns.Path) +@@ -866,9 +864,6 @@ func logNamespaceDiagnostics(spec *specs.Spec) { + if !sawMountNS { + logrus.Debugf("mount namespace not requested, but creating a new one anyway") + } +- if !sawUserNS { +- logrus.Debugf("user namespace not requested, but creating a new one anyway") +- } + if !sawUTSNS { + logrus.Debugf("UTS namespace not requested, but creating a new one anyway") + } +diff --git a/vendor/github.com/containers/podman/v3/pkg/specgen/generate/security.go b/vendor/github.com/containers/podman/v3/pkg/specgen/generate/security.go +index e0e4a47a4..3cda89a32 100644 +--- a/vendor/github.com/containers/podman/v3/pkg/specgen/generate/security.go ++++ b/vendor/github.com/containers/podman/v3/pkg/specgen/generate/security.go +@@ -146,6 +146,10 @@ func securityConfigureGenerator(s *specgen.SpecGenerator, g *generate.Generator, + + configSpec := g.Config + configSpec.Process.Capabilities.Ambient = []string{} ++ ++ // Always unset the inheritable capabilities similarly to what the Linux kernel does ++ // They are used only when using capabilities with uid != 0. ++ configSpec.Process.Capabilities.Inheritable = []string{} + configSpec.Process.Capabilities.Bounding = caplist + + user := strings.Split(s.User, ":")[0] +@@ -153,7 +157,6 @@ func securityConfigureGenerator(s *specgen.SpecGenerator, g *generate.Generator, + if (user == "" && s.UserNS.NSMode != specgen.KeepID) || user == "root" || user == "0" { + configSpec.Process.Capabilities.Effective = caplist + configSpec.Process.Capabilities.Permitted = caplist +- configSpec.Process.Capabilities.Inheritable = caplist + } else { + mergedCaps, err := capabilities.MergeCapabilities(nil, s.CapAdd, nil) + if err != nil { +@@ -175,12 +178,12 @@ func securityConfigureGenerator(s *specgen.SpecGenerator, g *generate.Generator, + } + configSpec.Process.Capabilities.Effective = userCaps + configSpec.Process.Capabilities.Permitted = userCaps +- configSpec.Process.Capabilities.Inheritable = userCaps + + // Ambient capabilities were added to Linux 4.3. Set ambient + // capabilities only when the kernel supports them. + if supportAmbientCapabilities() { + configSpec.Process.Capabilities.Ambient = userCaps ++ configSpec.Process.Capabilities.Inheritable = userCaps + } + } + +-- +2.33.8 + diff --git a/SPECS/cri-o/CVE-2021-44716.patch b/SPECS/cri-o/CVE-2021-44716.patch new file mode 100644 index 0000000000..294d0476e4 --- /dev/null +++ b/SPECS/cri-o/CVE-2021-44716.patch @@ -0,0 +1,45 @@ +From deb00def7d110f1b4edbe5d03044a9d9f2516151 Mon Sep 17 00:00:00 2001 +From: Cameron Baird +Date: Wed, 17 Apr 2024 20:57:05 +0000 +Subject: [PATCH 2/2] CVE-2021-44716 + +--- + vendor/golang.org/x/net/http2/server.go | 15 ++++++++++++--- + 1 file changed, 12 insertions(+), 3 deletions(-) + +diff --git a/vendor/golang.org/x/net/http2/server.go b/vendor/golang.org/x/net/http2/server.go +index e125bbd2a..5f417b444 100644 +--- a/vendor/golang.org/x/net/http2/server.go ++++ b/vendor/golang.org/x/net/http2/server.go +@@ -720,7 +720,15 @@ func (sc *serverConn) canonicalHeader(v string) string { + sc.canonHeader = make(map[string]string) + } + cv = http.CanonicalHeaderKey(v) +- sc.canonHeader[v] = cv ++ // maxCachedCanonicalHeaders is an arbitrarily-chosen limit on the number of ++ // entries in the canonHeader cache. This should be larger than the number ++ // of unique, uncommon header keys likely to be sent by the peer, while not ++ // so high as to permit unreaasonable memory usage if the peer sends an unbounded ++ // number of unique header keys. ++ const maxCachedCanonicalHeaders = 32 ++ if len(sc.canonHeader) < maxCachedCanonicalHeaders { ++ sc.canonHeader[v] = cv ++ } + return cv + } + +@@ -2530,8 +2538,9 @@ func (rws *responseWriterState) writeChunk(p []byte) (n int, err error) { + // prior to the headers being written. If the set of trailers is fixed + // or known before the header is written, the normal Go trailers mechanism + // is preferred: +-// https://golang.org/pkg/net/http/#ResponseWriter +-// https://golang.org/pkg/net/http/#example_ResponseWriter_trailers ++// ++// https://golang.org/pkg/net/http/#ResponseWriter ++// https://golang.org/pkg/net/http/#example_ResponseWriter_trailers + const TrailerPrefix = "Trailer:" + + // promoteUndeclaredTrailers permits http.Handlers to set trailers +-- +2.33.8 + diff --git a/SPECS/cri-o/CVE-2022-21698.patch b/SPECS/cri-o/CVE-2022-21698.patch new file mode 100644 index 0000000000..f995de0508 --- /dev/null +++ b/SPECS/cri-o/CVE-2022-21698.patch @@ -0,0 +1,487 @@ +From a7b977b81965244b750baee57181a0d7ba41ccd0 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 | 111 +++++++++++++---- + prometheus/promhttp/instrument_server_test.go | 116 ++++++++++++++++++ + prometheus/promhttp/option.go | 31 +++++ + prometheus/promhttp/option_test.go | 65 ++++++++++ + 5 files changed, 319 insertions(+), 32 deletions(-) + create mode 100644 prometheus/promhttp/option.go + create mode 100644 prometheus/promhttp/option_test.go + +diff --git a/vendor/github.com/prometheus/client_golang/prometheus/promhttp/instrument_client.go b/vendor/github.com/prometheus/client_golang/prometheus/promhttp/instrument_client.go +index 83c49b66a..861b4d21c 100644 +--- a/vendor/github.com/prometheus/client_golang/prometheus/promhttp/instrument_client.go ++++ b/vendor/github.com/prometheus/client_golang/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/vendor/github.com/prometheus/client_golang/prometheus/promhttp/instrument_server.go b/vendor/github.com/prometheus/client_golang/prometheus/promhttp/instrument_server.go +index ab037db86..a23f0edc6 100644 +--- a/vendor/github.com/prometheus/client_golang/prometheus/promhttp/instrument_server.go ++++ b/vendor/github.com/prometheus/client_golang/prometheus/promhttp/instrument_server.go +@@ -45,7 +45,10 @@ func InstrumentHandlerInFlight(g prometheus.Gauge, next http.Handler) http.Handl + // http.Handler to observe the request duration with the provided ObserverVec. + // The ObserverVec must have valid metric and label names and 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 ++// names are "code" and "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 +@@ -58,7 +61,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 +75,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()) + }) + } + +@@ -82,7 +90,10 @@ func InstrumentHandlerDuration(obs prometheus.ObserverVec, next http.Handler) ht + // to observe the request result with the provided CounterVec. The CounterVec + // must have valid metric and label names and 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 ++// "code" and "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. 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. +@@ -92,20 +103,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() + }) + } + +@@ -114,7 +130,10 @@ func InstrumentHandlerCounter(counter *prometheus.CounterVec, next http.Handler) + // until the response headers are written. The ObserverVec must have valid + // metric and label names and 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 in 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 unpartitioned observations, +@@ -128,13 +147,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) + }) +@@ -144,8 +168,11 @@ func InstrumentHandlerTimeToWriteHeader(obs prometheus.ObserverVec, next http.Ha + // http.Handler to observe the request size with the provided ObserverVec. The + // ObserverVec must have valid metric and label names and 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 in the ObserverVec is called with the request size in ++// are "code" and "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 size in + // bytes. Partitioning happens by HTTP status code and/or HTTP method if the + // respective instance label names are present in the ObserverVec. For + // unpartitioned observations, use an ObserverVec with zero labels. Note that +@@ -156,7 +183,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 { +@@ -164,14 +196,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)) + }) + } + +@@ -179,8 +211,11 @@ func InstrumentHandlerRequestSize(obs prometheus.ObserverVec, next http.Handler) + // http.Handler to observe the response size with the provided ObserverVec. The + // ObserverVec must have valid metric and label names and 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 in the ObserverVec is called with the response size in ++// are "code" and "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 response size in + // bytes. Partitioning happens by HTTP status code and/or HTTP method if the + // respective instance label names are present in the ObserverVec. For + // unpartitioned observations, use an ObserverVec with zero labels. Note that +@@ -191,12 +226,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())) + }) + } + +@@ -290,7 +331,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 + } +@@ -300,7 +341,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 +@@ -330,7 +371,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" +@@ -348,15 +394,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" +@@ -453,6 +509,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/vendor/github.com/prometheus/client_golang/prometheus/promhttp/option.go b/vendor/github.com/prometheus/client_golang/prometheus/promhttp/option.go +new file mode 100644 +index 000000000..35e41bd1e +--- /dev/null ++++ b/vendor/github.com/prometheus/client_golang/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 ++ } ++} +diff --git a/vendor/github.com/prometheus/client_golang/prometheus/promhttp/option_test.go b/vendor/github.com/prometheus/client_golang/prometheus/promhttp/option_test.go +new file mode 100644 +index 000000000..301fd0612 +--- /dev/null ++++ b/vendor/github.com/prometheus/client_golang/prometheus/promhttp/option_test.go +@@ -0,0 +1,65 @@ ++// 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 ++ ++import ( ++ "log" ++ "net/http" ++ ++ "github.com/prometheus/client_golang/prometheus" ++) ++ ++func ExampleInstrumentHandlerWithExtraMethods() { ++ counter := prometheus.NewCounterVec( ++ prometheus.CounterOpts{ ++ Name: "api_requests_total", ++ Help: "A counter for requests to the wrapped handler.", ++ }, ++ []string{"code", "method"}, ++ ) ++ ++ // duration is partitioned by the HTTP method and handler. It uses custom ++ // buckets based on the expected request duration. ++ duration := prometheus.NewHistogramVec( ++ prometheus.HistogramOpts{ ++ Name: "request_duration_seconds", ++ Help: "A histogram of latencies for requests.", ++ Buckets: []float64{.25, .5, 1, 2.5, 5, 10}, ++ }, ++ []string{"handler", "method"}, ++ ) ++ ++ // Create the handlers that will be wrapped by the middleware. ++ pullHandler := http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { ++ w.Write([]byte("Pull")) ++ }) ++ ++ // Specify additional HTTP methods to be added to the label allow list. ++ opts := WithExtraMethods("CUSTOM_METHOD") ++ ++ // Instrument the handlers with all the metrics, injecting the "handler" ++ // label by currying. ++ pullChain := ++ InstrumentHandlerDuration(duration.MustCurryWith(prometheus.Labels{"handler": "pull"}), ++ InstrumentHandlerCounter(counter, pullHandler, opts), ++ opts, ++ ) ++ ++ http.Handle("/metrics", Handler()) ++ http.Handle("/pull", pullChain) ++ ++ if err := http.ListenAndServe(":3000", nil); err != nil { ++ log.Fatal(err) ++ } ++} diff --git a/SPECS/cri-o/CVE-2022-27651.patch b/SPECS/cri-o/CVE-2022-27651.patch new file mode 100644 index 0000000000..bdccf8fc9f --- /dev/null +++ b/SPECS/cri-o/CVE-2022-27651.patch @@ -0,0 +1,50 @@ +From a3b181b667b8bd408c036e94f2b2f61295610ed6 Mon Sep 17 00:00:00 2001 +From: Cameron Baird +Date: Tue, 16 Apr 2024 22:27:00 +0000 +Subject: [PATCH 3/4] CVE-2022-27651 + +--- + vendor/github.com/containers/buildah/chroot/run.go | 2 +- + vendor/github.com/containers/buildah/run_linux.go | 6 ------ + 2 files changed, 1 insertion(+), 7 deletions(-) + +diff --git a/vendor/github.com/containers/buildah/chroot/run.go b/vendor/github.com/containers/buildah/chroot/run.go +index 39ad88b2b..a93f97dcd 100644 +--- a/vendor/github.com/containers/buildah/chroot/run.go ++++ b/vendor/github.com/containers/buildah/chroot/run.go +@@ -898,7 +898,7 @@ func setCapabilities(spec *specs.Spec, keepCaps ...string) error { + capMap := map[capability.CapType][]string{ + capability.BOUNDING: spec.Process.Capabilities.Bounding, + capability.EFFECTIVE: spec.Process.Capabilities.Effective, +- capability.INHERITABLE: spec.Process.Capabilities.Inheritable, ++ capability.INHERITABLE: []string{}, + capability.PERMITTED: spec.Process.Capabilities.Permitted, + capability.AMBIENT: spec.Process.Capabilities.Ambient, + } +diff --git a/vendor/github.com/containers/buildah/run_linux.go b/vendor/github.com/containers/buildah/run_linux.go +index ffbb36b7b..1d0646612 100644 +--- a/vendor/github.com/containers/buildah/run_linux.go ++++ b/vendor/github.com/containers/buildah/run_linux.go +@@ -1850,9 +1850,6 @@ func setupCapAdd(g *generate.Generator, caps ...string) error { + if err := g.AddProcessCapabilityEffective(cap); err != nil { + return errors.Wrapf(err, "error adding %q to the effective capability set", cap) + } +- if err := g.AddProcessCapabilityInheritable(cap); err != nil { +- return errors.Wrapf(err, "error adding %q to the inheritable capability set", cap) +- } + if err := g.AddProcessCapabilityPermitted(cap); err != nil { + return errors.Wrapf(err, "error adding %q to the permitted capability set", cap) + } +@@ -1871,9 +1868,6 @@ func setupCapDrop(g *generate.Generator, caps ...string) error { + if err := g.DropProcessCapabilityEffective(cap); err != nil { + return errors.Wrapf(err, "error removing %q from the effective capability set", cap) + } +- if err := g.DropProcessCapabilityInheritable(cap); err != nil { +- return errors.Wrapf(err, "error removing %q from the inheritable capability set", cap) +- } + if err := g.DropProcessCapabilityPermitted(cap); err != nil { + return errors.Wrapf(err, "error removing %q from the permitted capability set", cap) + } +-- +2.33.8 + diff --git a/SPECS/cri-o/CVE-2022-29526.patch b/SPECS/cri-o/CVE-2022-29526.patch new file mode 100644 index 0000000000..53c70bdc4f --- /dev/null +++ b/SPECS/cri-o/CVE-2022-29526.patch @@ -0,0 +1,25 @@ +From 3536be6d44bea94361fb9a993d4948cd378672d8 Mon Sep 17 00:00:00 2001 +From: Cameron Baird +Date: Wed, 17 Apr 2024 20:51:35 +0000 +Subject: [PATCH 1/2] CVE-2022-29526 + +--- + vendor/golang.org/x/sys/unix/syscall_linux.go | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/vendor/golang.org/x/sys/unix/syscall_linux.go b/vendor/golang.org/x/sys/unix/syscall_linux.go +index 2dd7c8e34..1a3ee718d 100644 +--- a/vendor/golang.org/x/sys/unix/syscall_linux.go ++++ b/vendor/golang.org/x/sys/unix/syscall_linux.go +@@ -2110,7 +2110,7 @@ func Faccessat(dirfd int, path string, mode uint32, flags int) (err error) { + gid = Getgid() + } + +- if uint32(gid) == st.Gid || isGroupMember(gid) { ++ if uint32(gid) == st.Gid || isGroupMember(int(st.Gid)) { + fmode = (st.Mode >> 3) & 7 + } else { + fmode = st.Mode & 7 +-- +2.33.8 + diff --git a/SPECS/cri-o/CVE-2022-2995.patch b/SPECS/cri-o/CVE-2022-2995.patch new file mode 100644 index 0000000000..f1364c41de --- /dev/null +++ b/SPECS/cri-o/CVE-2022-2995.patch @@ -0,0 +1,55 @@ +From 6c688b7d5bfd4609f08c052c6d843f0d6c541987 Mon Sep 17 00:00:00 2001 +From: Peter Hunt~ +Date: Mon, 22 Aug 2022 15:10:05 -0400 +Subject: [PATCH 2/4] server: add container GID to additional groups + +Signed-off-by: Peter Hunt~ +--- + server/container_create.go | 5 +++-- + test/ctr.bats | 12 ++++++++++++ + 2 files changed, 15 insertions(+), 2 deletions(-) + +diff --git a/server/container_create.go b/server/container_create.go +index 751b53738..9fae55d24 100644 +--- a/server/container_create.go ++++ b/server/container_create.go +@@ -250,10 +250,11 @@ func setupContainerUser(ctx context.Context, specgen *generate.Generator, rootfs + } + + specgen.SetProcessUID(uid) +- specgen.SetProcessGID(gid) + if sc.RunAsGroup != nil { +- specgen.SetProcessGID(uint32(sc.RunAsGroup.Value)) ++ gid = uint32(sc.RunAsGroup.Value) + } ++ specgen.SetProcessGID(gid) ++ specgen.AddProcessAdditionalGid(gid) + + for _, group := range addGroups { + specgen.AddProcessAdditionalGid(group) +diff --git a/test/ctr.bats b/test/ctr.bats +index a9f939372..21ba72531 100644 +--- a/test/ctr.bats ++++ b/test/ctr.bats +@@ -861,6 +861,18 @@ function check_oci_annotation() { + crictl exec --sync "$ctr_id" grep "CapEff:\s0000000000000000" /proc/1/status + } + ++@test "ctr has gid in supplimental groups" { ++ start_crio ++ ++ jq ' .linux.security_context.run_as_user.value = 1000 ++ | .linux.security_context.run_as_group.value = 1000' \ ++ "$TESTDATA"/container_redis.json > "$newconfig" ++ ++ ctr_id=$(crictl run "$newconfig" "$TESTDATA"/sandbox_config.json) ++ ++ crictl exec --sync "$ctr_id" grep Groups:.1000 /proc/1/status ++} ++ + @test "ctr with low memory configured should not be created" { + start_crio + pod_id=$(crictl runp "$TESTDATA"/sandbox_config.json) +-- +2.33.8 + diff --git a/SPECS/cri-o/CVE-2023-42821.patch b/SPECS/cri-o/CVE-2023-42821.patch new file mode 100644 index 0000000000..eec3b6d0aa --- /dev/null +++ b/SPECS/cri-o/CVE-2023-42821.patch @@ -0,0 +1,54 @@ +From 32ac20b93a622b6fb0d0ee22362c18c21e4f65c5 Mon Sep 17 00:00:00 2001 +From: Cameron Baird +Date: Tue, 16 Apr 2024 22:24:51 +0000 +Subject: [PATCH 1/4] CVE-2023-42821 + +--- + vendor/github.com/gomarkdown/markdown/parser/block.go | 7 ++++++- + vendor/github.com/gomarkdown/markdown/parser/citation.go | 5 +++++ + 2 files changed, 11 insertions(+), 1 deletion(-) + +diff --git a/vendor/github.com/gomarkdown/markdown/parser/block.go b/vendor/github.com/gomarkdown/markdown/parser/block.go +index a0b809915..54f6a237e 100644 +--- a/vendor/github.com/gomarkdown/markdown/parser/block.go ++++ b/vendor/github.com/gomarkdown/markdown/parser/block.go +@@ -172,6 +172,11 @@ func (p *Parser) block(data []byte) { + //
+ // ... + //
++ ++ if len(data) == 0 { ++ continue ++ } ++ + if data[0] == '<' { + if i := p.html(data, true); i > 0 { + data = data[i:] +@@ -376,7 +381,7 @@ func (p *Parser) addBlock(n ast.Node) ast.Node { + } + + func (p *Parser) isPrefixHeading(data []byte) bool { +- if data[0] != '#' { ++ if len(data) > 0 && data[0] != '#' { + return false + } + +diff --git a/vendor/github.com/gomarkdown/markdown/parser/citation.go b/vendor/github.com/gomarkdown/markdown/parser/citation.go +index 8ea1fbeee..217d4def0 100644 +--- a/vendor/github.com/gomarkdown/markdown/parser/citation.go ++++ b/vendor/github.com/gomarkdown/markdown/parser/citation.go +@@ -65,6 +65,11 @@ func citation(p *Parser, data []byte, offset int) (int, ast.Node) { + } + + citeType := ast.CitationTypeInformative ++ ++ if len(citation) < 2 { ++ continue ++ } ++ + j = 1 + switch citation[j] { + case '!': +-- +2.33.8 + diff --git a/SPECS/cri-o/CVE-2023-44487.patch b/SPECS/cri-o/CVE-2023-44487.patch new file mode 100644 index 0000000000..3d24ab0dd9 --- /dev/null +++ b/SPECS/cri-o/CVE-2023-44487.patch @@ -0,0 +1,228 @@ +From f2180b4d5403d2210b30b93098eb7da31c05c721 Mon Sep 17 00:00:00 2001 +From: Doug Fawley +Date: Tue, 10 Oct 2023 10:51:45 -0700 +Subject: [PATCH] server: prohibit more than MaxConcurrentStreams handlers from + running at once (#6703) + +--- + internal/transport/http2_server.go | 11 +-- + server.go | 47 +++++++++++++++++++++++-- + server_ext_test.go | 99 +++++++++++++++++++++++++ + 5 files changed, 210 insertions(+), 45 deletions(-) + create mode 100644 server_ext_test.go + +diff --git a/vendor/google.golang.org/grpc/vendor/google.golang.org/grpc/internal/transport/http2_server.go b/vendor/google.golang.org/grpc/internal/transport/http2_server.go +index 57475d27977..6fa1eb41992 100644 +--- a/vendor/google.golang.org/grpc/internal/transport/http2_server.go ++++ b/vendor/google.golang.org/grpc/internal/transport/http2_server.go +@@ -171,15 +171,10 @@ func NewServerTransport(conn net.Conn, config *ServerConfig) (_ ServerTransport, + ID: http2.SettingMaxFrameSize, + Val: http2MaxFrameLen, + }} +- // TODO(zhaoq): Have a better way to signal "no limit" because 0 is +- // permitted in the HTTP2 spec. +- maxStreams := config.MaxStreams +- if maxStreams == 0 { +- maxStreams = math.MaxUint32 +- } else { ++ if config.MaxStreams != math.MaxUint32 { + isettings = append(isettings, http2.Setting{ + ID: http2.SettingMaxConcurrentStreams, +- Val: maxStreams, ++ Val: config.MaxStreams, + }) + } + dynamicWindow := true +@@ -258,7 +253,7 @@ func NewServerTransport(conn net.Conn, config *ServerConfig) (_ ServerTransport, + framer: framer, + readerDone: make(chan struct{}), + writerDone: make(chan struct{}), +- maxStreams: maxStreams, ++ maxStreams: config.MaxStreams, + inTapHandle: config.InTapHandle, + fc: &trInFlow{limit: uint32(icwz)}, + state: reachable, +diff --git a/vendor/google.golang.org/grpc/server.go b/vendor/google.golang.org/grpc/server.go +index 0d75cb109..d795b5f73 100644 +--- a/vendor/google.golang.org/grpc/server.go ++++ b/vendor/google.golang.org/grpc/server.go +@@ -134,6 +134,7 @@ type serverOptions struct { + } + + var defaultServerOptions = serverOptions{ ++ maxConcurrentStreams: math.MaxUint32, + maxReceiveMessageSize: defaultServerMaxReceiveMessageSize, + maxSendMessageSize: defaultServerMaxSendMessageSize, + connectionTimeout: 120 * time.Second, +@@ -287,6 +288,9 @@ func MaxSendMsgSize(m int) ServerOption { + // MaxConcurrentStreams returns a ServerOption that will apply a limit on the number + // of concurrent streams to each ServerTransport. + func MaxConcurrentStreams(n uint32) ServerOption { ++ if n == 0 { ++ n = math.MaxUint32 ++ } + return newFuncServerOption(func(o *serverOptions) { + o.maxConcurrentStreams = n + }) +@@ -715,12 +719,18 @@ func (s *Server) newHTTP2Transport(c net.Conn, authInfo credentials.AuthInfo) tr + func (s *Server) serveStreams(st transport.ServerTransport) { + defer st.Close() + var wg sync.WaitGroup ++ streamQuota := newHandlerQuota(s.opts.maxConcurrentStreams) + st.HandleStreams(func(stream *transport.Stream) { + wg.Add(1) +- go func() { ++ ++ streamQuota.acquire() ++ f := func() { ++ defer streamQuota.release() + defer wg.Done() +- s.handleStream(st, stream, s.traceInfo(st, stream)) +- }() ++ s.handleStream(st, stream, s.traceInfo(st, stream)) ++ } ++ go f() ++ + }, func(ctx context.Context, method string) context.Context { + if !EnableTracing { + return ctx +@@ -1546,3 +1556,34 @@ type channelzServer struct { + func (c *channelzServer) ChannelzMetric() *channelz.ServerInternalMetric { + return c.s.channelzMetric() + } ++ ++// atomicSemaphore implements a blocking, counting semaphore. acquire should be ++// called synchronously; release may be called asynchronously. ++type atomicSemaphore struct { ++ n atomic.Int64 ++ wait chan struct{} ++} ++ ++func (q *atomicSemaphore) acquire() { ++ if q.n.Add(-1) < 0 { ++ // We ran out of quota. Block until a release happens. ++ <-q.wait ++ } ++} ++ ++func (q *atomicSemaphore) release() { ++ // N.B. the "<= 0" check below should allow for this to work with multiple ++ // concurrent calls to acquire, but also note that with synchronous calls to ++ // acquire, as our system does, n will never be less than -1. There are ++ // fairness issues (queuing) to consider if this was to be generalized. ++ if q.n.Add(1) <= 0 { ++ // An acquire was waiting on us. Unblock it. ++ q.wait <- struct{}{} ++ } ++} ++ ++func newHandlerQuota(n uint32) *atomicSemaphore { ++ a := &atomicSemaphore{wait: make(chan struct{}, 1)} ++ a.n.Store(int64(n)) ++ return a ++} +diff --git a/vendor/google.golang.org/grpc/vendor/google.golang.org/grpc/server_ext_test.go b/vendor/google.golang.org/grpc/server_ext_test.go +new file mode 100644 +index 00000000000..df79755f325 +--- /dev/null ++++ b/vendor/google.golang.org/grpc/server_ext_test.go +@@ -0,0 +1,99 @@ ++/* ++ * ++ * Copyright 2023 gRPC 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 grpc_test ++ ++import ( ++ "context" ++ "io" ++ "testing" ++ "time" ++ ++ "google.golang.org/grpc" ++ "google.golang.org/grpc/internal/grpcsync" ++ "google.golang.org/grpc/internal/stubserver" ++ ++ testgrpc "google.golang.org/grpc/interop/grpc_testing" ++) ++ ++// TestServer_MaxHandlers ensures that no more than MaxConcurrentStreams server ++// handlers are active at one time. ++func (s) TestServer_MaxHandlers(t *testing.T) { ++ started := make(chan struct{}) ++ blockCalls := grpcsync.NewEvent() ++ ++ // This stub server does not properly respect the stream context, so it will ++ // not exit when the context is canceled. ++ ss := stubserver.StubServer{ ++ FullDuplexCallF: func(stream testgrpc.TestService_FullDuplexCallServer) error { ++ started <- struct{}{} ++ <-blockCalls.Done() ++ return nil ++ }, ++ } ++ if err := ss.Start([]grpc.ServerOption{grpc.MaxConcurrentStreams(1)}); err != nil { ++ t.Fatal("Error starting server:", err) ++ } ++ defer ss.Stop() ++ ++ ctx, cancel := context.WithTimeout(context.Background(), defaultTestTimeout) ++ defer cancel() ++ ++ // Start one RPC to the server. ++ ctx1, cancel1 := context.WithCancel(ctx) ++ _, err := ss.Client.FullDuplexCall(ctx1) ++ if err != nil { ++ t.Fatal("Error staring call:", err) ++ } ++ ++ // Wait for the handler to be invoked. ++ select { ++ case <-started: ++ case <-ctx.Done(): ++ t.Fatalf("Timed out waiting for RPC to start on server.") ++ } ++ ++ // Cancel it on the client. The server handler will still be running. ++ cancel1() ++ ++ ctx2, cancel2 := context.WithCancel(ctx) ++ defer cancel2() ++ s, err := ss.Client.FullDuplexCall(ctx2) ++ if err != nil { ++ t.Fatal("Error staring call:", err) ++ } ++ ++ // After 100ms, allow the first call to unblock. That should allow the ++ // second RPC to run and finish. ++ select { ++ case <-started: ++ blockCalls.Fire() ++ t.Fatalf("RPC started unexpectedly.") ++ case <-time.After(100 * time.Millisecond): ++ blockCalls.Fire() ++ } ++ ++ select { ++ case <-started: ++ case <-ctx.Done(): ++ t.Fatalf("Timed out waiting for second RPC to start on server.") ++ } ++ if _, err := s.Recv(); err != io.EOF { ++ t.Fatal("Received unexpected RPC error:", err) ++ } ++} diff --git a/SPECS/cri-o/CVE-2024-28180.patch b/SPECS/cri-o/CVE-2024-28180.patch new file mode 100644 index 0000000000..c623c6a27d --- /dev/null +++ b/SPECS/cri-o/CVE-2024-28180.patch @@ -0,0 +1,88 @@ +From 95facc981124058b1e460216e84c678472223f4c Mon Sep 17 00:00:00 2001 +From: Jacob Hoffman-Andrews +Date: Thu, 7 Mar 2024 13:35:47 -0800 +Subject: [PATCH] v2: backport decompression limit fix + +Backport from #107. +--- + crypter.go | 6 ++++ + encoding.go | 21 +++++++++--- + 4 files changed, 141 insertions(+), 4 deletions(-) + + +diff --git a/vendor/gopkg.in/square/go-jose.v2/crypter.go b/vendor/gopkg.in/square/go-jose.v2/crypter.go +index 73aab0f..0ae2e5e 100644 +--- a/vendor/gopkg.in/square/go-jose.v2/crypter.go ++++ b/vendor/gopkg.in/square/go-jose.v2/crypter.go +@@ -406,6 +406,9 @@ func (ctx *genericEncrypter) Options() EncrypterOptions { + // Decrypt and validate the object and return the plaintext. Note that this + // function does not support multi-recipient, if you desire multi-recipient + // decryption use DecryptMulti instead. ++// ++// Automatically decompresses plaintext, but returns an error if the decompressed ++// data would be >250kB or >10x the size of the compressed data, whichever is larger. + func (obj JSONWebEncryption) Decrypt(decryptionKey interface{}) ([]byte, error) { + headers := obj.mergedHeaders(nil) + +@@ -470,6 +473,9 @@ func (obj JSONWebEncryption) Decrypt(decryptionKey interface{}) ([]byte, error) + // with support for multiple recipients. It returns the index of the recipient + // for which the decryption was successful, the merged headers for that recipient, + // and the plaintext. ++// ++// Automatically decompresses plaintext, but returns an error if the decompressed ++// data would be >250kB or >3x the size of the compressed data, whichever is larger. + func (obj JSONWebEncryption) DecryptMulti(decryptionKey interface{}) (int, Header, []byte, error) { + globalHeaders := obj.mergedHeaders(nil) + +diff --git a/vendor/gopkg.in/square/go-jose.v2/encoding.go b/vendor/gopkg.in/square/go-jose.v2/encoding.go +index 40b688b..636f6c8 100644 +--- a/vendor/gopkg.in/square/go-jose.v2/encoding.go ++++ b/vendor/gopkg.in/square/go-jose.v2/encoding.go +@@ -21,6 +21,7 @@ import ( + "compress/flate" + "encoding/base64" + "encoding/binary" ++ "fmt" + "io" + "math/big" + "strings" +@@ -85,7 +86,7 @@ func decompress(algorithm CompressionAlgorithm, input []byte) ([]byte, error) { + } + } + +-// Compress with DEFLATE ++// deflate compresses the input. + func deflate(input []byte) ([]byte, error) { + output := new(bytes.Buffer) + +@@ -97,15 +98,27 @@ func deflate(input []byte) ([]byte, error) { + return output.Bytes(), err + } + +-// Decompress with DEFLATE ++// inflate decompresses the input. ++// ++// Errors if the decompressed data would be >250kB or >10x the size of the ++// compressed data, whichever is larger. + func inflate(input []byte) ([]byte, error) { + output := new(bytes.Buffer) + reader := flate.NewReader(bytes.NewBuffer(input)) + +- _, err := io.Copy(output, reader) +- if err != nil { ++ maxCompressedSize := 10 * int64(len(input)) ++ if maxCompressedSize < 250000 { ++ maxCompressedSize = 250000 ++ } ++ ++ limit := maxCompressedSize + 1 ++ n, err := io.CopyN(output, reader, limit) ++ if err != nil && err != io.EOF { + return nil, err + } ++ if n == limit { ++ return nil, fmt.Errorf("uncompressed data would be too large (>%d bytes)", maxCompressedSize) ++ } + + err = reader.Close() + return output.Bytes(), err diff --git a/SPECS/cri-o/cri-o.spec b/SPECS/cri-o/cri-o.spec index ef2a0df9da..fd2b58e039 100644 --- a/SPECS/cri-o/cri-o.spec +++ b/SPECS/cri-o/cri-o.spec @@ -26,7 +26,7 @@ Summary: OCI-based implementation of Kubernetes Container Runtime Interfa # Define macros for further referenced sources Name: cri-o Version: 1.21.7 -Release: 1%{?dist} +Release: 2%{?dist} License: ASL 2.0 Vendor: Microsoft Corporation Distribution: Mariner @@ -53,6 +53,15 @@ Source4: crio.conf Source5: cri-o-rpmlintrc Source6: kubelet.env Patch0: CVE-2022-1708.patch +Patch1: CVE-2021-3602.patch +Patch2: CVE-2022-27651.patch +Patch3: CVE-2022-2995.patch +Patch4: CVE-2023-42821.patch +Patch5: CVE-2022-29526.patch +Patch6: CVE-2021-44716.patch +Patch7: CVE-2022-21698.patch +Patch8: CVE-2023-44487.patch +Patch9: CVE-2024-28180.patch BuildRequires: btrfs-progs-devel BuildRequires: device-mapper-devel BuildRequires: fdupes @@ -101,7 +110,7 @@ This package provides the CRI-O container runtime configuration for kubeadm %prep %setup -q tar -xf %{SOURCE1} --no-same-owner -%patch0 -p1 -b .files +%autopatch -p1 %build @@ -205,6 +214,10 @@ mkdir -p /opt/cni/bin %{_fillupdir}/sysconfig.kubelet %changelog +* Tue Apr 16 2024 Cameron Baird - 1.21.7-2 +- Apply patches to fix CVE-2021-3602, CVE-2022-27651, CVE-2022-2995, CVE-2023-42821 +- CVE-2021-44716, CVE-2022-29526, CVE-2022-21698, CVE-2023-44487, CVE-2024-28180 + * Tue Apr 09 2024 Adithya Jayachandran - 1.21.7-1 - Update to 1.21.7 to fix CVE-2022-0811 - Added sumsharma's backported patch for 1.21.7 to fix CVE-2022-1708