Patch moby-engine to address CVE-2023-44487 (#9276)
This commit is contained in:
Родитель
a6539502f3
Коммит
a264db1f75
|
@ -0,0 +1,200 @@
|
||||||
|
From acdb7b9731b3d1eb14352328d2976d4b7baaafea Mon Sep 17 00:00:00 2001
|
||||||
|
From: Mitch Zhu <mitchzhu@microsoft.com>
|
||||||
|
Date: Fri, 31 May 2024 17:00:00 +0000
|
||||||
|
Subject: [PATCH] Address CVE-2023-44487
|
||||||
|
|
||||||
|
---
|
||||||
|
.../grpc/internal/transport/http2_server.go | 11 +--
|
||||||
|
vendor/google.golang.org/grpc/server.go | 77 +++++++++++++------
|
||||||
|
2 files changed, 57 insertions(+), 31 deletions(-)
|
||||||
|
|
||||||
|
diff --git a/vendor/google.golang.org/grpc/internal/transport/http2_server.go b/vendor/google.golang.org/grpc/internal/transport/http2_server.go
|
||||||
|
index 3dd1564..9d9a3fd 100644
|
||||||
|
--- a/vendor/google.golang.org/grpc/internal/transport/http2_server.go
|
||||||
|
+++ b/vendor/google.golang.org/grpc/internal/transport/http2_server.go
|
||||||
|
@@ -165,15 +165,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
|
||||||
|
@@ -252,7 +247,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 f4dde72..17d39cf 100644
|
||||||
|
--- a/vendor/google.golang.org/grpc/server.go
|
||||||
|
+++ b/vendor/google.golang.org/grpc/server.go
|
||||||
|
@@ -115,12 +115,6 @@ type serviceInfo struct {
|
||||||
|
mdata interface{}
|
||||||
|
}
|
||||||
|
|
||||||
|
-type serverWorkerData struct {
|
||||||
|
- st transport.ServerTransport
|
||||||
|
- wg *sync.WaitGroup
|
||||||
|
- stream *transport.Stream
|
||||||
|
-}
|
||||||
|
-
|
||||||
|
// Server is a gRPC server to serve RPC requests.
|
||||||
|
type Server struct {
|
||||||
|
opts serverOptions
|
||||||
|
@@ -145,7 +139,7 @@ type Server struct {
|
||||||
|
channelzID *channelz.Identifier
|
||||||
|
czData *channelzData
|
||||||
|
|
||||||
|
- serverWorkerChannels []chan *serverWorkerData
|
||||||
|
+ serverWorkerChannel chan func()
|
||||||
|
}
|
||||||
|
|
||||||
|
type serverOptions struct {
|
||||||
|
@@ -177,6 +171,7 @@ type serverOptions struct {
|
||||||
|
}
|
||||||
|
|
||||||
|
var defaultServerOptions = serverOptions{
|
||||||
|
+ maxConcurrentStreams: math.MaxUint32,
|
||||||
|
maxReceiveMessageSize: defaultServerMaxReceiveMessageSize,
|
||||||
|
maxSendMessageSize: defaultServerMaxSendMessageSize,
|
||||||
|
connectionTimeout: 120 * time.Second,
|
||||||
|
@@ -387,6 +382,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
|
||||||
|
})
|
||||||
|
@@ -565,35 +563,31 @@ const serverWorkerResetThreshold = 1 << 16
|
||||||
|
// re-allocations (see the runtime.morestack problem [1]).
|
||||||
|
//
|
||||||
|
// [1] https://github.com/golang/go/issues/18138
|
||||||
|
-func (s *Server) serverWorker(ch chan *serverWorkerData) {
|
||||||
|
+func (s *Server) serverWorker() {
|
||||||
|
// To make sure all server workers don't reset at the same time, choose a
|
||||||
|
// random number of iterations before resetting.
|
||||||
|
threshold := serverWorkerResetThreshold + grpcrand.Intn(serverWorkerResetThreshold)
|
||||||
|
for completed := 0; completed < threshold; completed++ {
|
||||||
|
- data, ok := <-ch
|
||||||
|
+ f, ok := <-s.serverWorkerChannel
|
||||||
|
if !ok {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
- s.handleStream(data.st, data.stream, s.traceInfo(data.st, data.stream))
|
||||||
|
- data.wg.Done()
|
||||||
|
+ f()
|
||||||
|
}
|
||||||
|
- go s.serverWorker(ch)
|
||||||
|
+ go s.serverWorker()
|
||||||
|
}
|
||||||
|
|
||||||
|
// initServerWorkers creates worker goroutines and channels to process incoming
|
||||||
|
// connections to reduce the time spent overall on runtime.morestack.
|
||||||
|
func (s *Server) initServerWorkers() {
|
||||||
|
- s.serverWorkerChannels = make([]chan *serverWorkerData, s.opts.numServerWorkers)
|
||||||
|
+ s.serverWorkerChannel = make(chan func())
|
||||||
|
for i := uint32(0); i < s.opts.numServerWorkers; i++ {
|
||||||
|
- s.serverWorkerChannels[i] = make(chan *serverWorkerData)
|
||||||
|
- go s.serverWorker(s.serverWorkerChannels[i])
|
||||||
|
+ go s.serverWorker()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (s *Server) stopServerWorkers() {
|
||||||
|
- for i := uint32(0); i < s.opts.numServerWorkers; i++ {
|
||||||
|
- close(s.serverWorkerChannels[i])
|
||||||
|
- }
|
||||||
|
+ close(s.serverWorkerChannel)
|
||||||
|
}
|
||||||
|
|
||||||
|
// NewServer creates a gRPC server which has no service registered and has not
|
||||||
|
@@ -945,13 +939,20 @@ func (s *Server) serveStreams(st transport.ServerTransport) {
|
||||||
|
defer st.Close()
|
||||||
|
var wg sync.WaitGroup
|
||||||
|
|
||||||
|
- var roundRobinCounter uint32
|
||||||
|
+ streamQuota := newHandlerQuota(s.opts.maxConcurrentStreams)
|
||||||
|
st.HandleStreams(func(stream *transport.Stream) {
|
||||||
|
wg.Add(1)
|
||||||
|
+
|
||||||
|
+ streamQuota.acquire()
|
||||||
|
+ f := func() {
|
||||||
|
+ defer streamQuota.release()
|
||||||
|
+ defer wg.Done()
|
||||||
|
+ s.handleStream(st, stream, s.traceInfo(st, stream))
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
if s.opts.numServerWorkers > 0 {
|
||||||
|
- data := &serverWorkerData{st: st, wg: &wg, stream: stream}
|
||||||
|
select {
|
||||||
|
- case s.serverWorkerChannels[atomic.AddUint32(&roundRobinCounter, 1)%s.opts.numServerWorkers] <- data:
|
||||||
|
+ case s.serverWorkerChannel <- f:
|
||||||
|
default:
|
||||||
|
// If all stream workers are busy, fallback to the default code path.
|
||||||
|
go func() {
|
||||||
|
@@ -961,8 +962,7 @@ func (s *Server) serveStreams(st transport.ServerTransport) {
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
go func() {
|
||||||
|
- defer wg.Done()
|
||||||
|
- s.handleStream(st, stream, s.traceInfo(st, stream))
|
||||||
|
+ go f()
|
||||||
|
}()
|
||||||
|
}
|
||||||
|
}, func(ctx context.Context, method string) context.Context {
|
||||||
|
@@ -1978,3 +1978,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
|
||||||
|
+}
|
||||||
|
--
|
||||||
|
2.34.1
|
||||||
|
|
|
@ -3,7 +3,7 @@
|
||||||
Summary: The open-source application container engine
|
Summary: The open-source application container engine
|
||||||
Name: moby-engine
|
Name: moby-engine
|
||||||
Version: 24.0.9
|
Version: 24.0.9
|
||||||
Release: 3%{?dist}
|
Release: 4%{?dist}
|
||||||
License: ASL 2.0
|
License: ASL 2.0
|
||||||
Group: Tools/Container
|
Group: Tools/Container
|
||||||
URL: https://mobyproject.org
|
URL: https://mobyproject.org
|
||||||
|
@ -21,6 +21,7 @@ Patch1: CVE-2024-23651.patch
|
||||||
# Remove once we upgrade this package at least to version 25.0+.
|
# Remove once we upgrade this package at least to version 25.0+.
|
||||||
Patch2: CVE-2024-23652.patch
|
Patch2: CVE-2024-23652.patch
|
||||||
Patch3: CVE-2023-45288.patch
|
Patch3: CVE-2023-45288.patch
|
||||||
|
Patch4: CVE-2023-44487.patch
|
||||||
|
|
||||||
%{?systemd_requires}
|
%{?systemd_requires}
|
||||||
|
|
||||||
|
@ -126,6 +127,9 @@ fi
|
||||||
%{_unitdir}/*
|
%{_unitdir}/*
|
||||||
|
|
||||||
%changelog
|
%changelog
|
||||||
|
* Fri May 31 2024 Mitch Zhu <mitchzhu@microsoft.com> - 24.0.9-4
|
||||||
|
- Fix for CVE-2023-44487
|
||||||
|
|
||||||
* Fri May 03 2024 Chris Gunn <chrisgun@microsoft.com> - 24.0.9-3
|
* Fri May 03 2024 Chris Gunn <chrisgun@microsoft.com> - 24.0.9-3
|
||||||
- Fix for CVE-2023-45288
|
- Fix for CVE-2023-45288
|
||||||
|
|
||||||
|
|
Загрузка…
Ссылка в новой задаче