All of lore.kernel.org
 help / color / mirror / Atom feed
From: Bruce Ashfield <bruce.ashfield@gmail.com>
To: Hitendra Prajapati <hprajapati@mvista.com>
Cc: meta-virtualization@lists.yoctoproject.org
Subject: Re: [meta-virtualization][scarthgap][PATCH] docker-moby: fix CVE-2024-41110
Date: Thu, 18 Sep 2025 22:37:43 -0400	[thread overview]
Message-ID: <aMzB92SypOpZS4BI@gmail.com> (raw)
In-Reply-To: <20250910141357.267108-1-hprajapati@mvista.com>

In message: [meta-virtualization][scarthgap][PATCH] docker-moby: fix CVE-2024-41110
on 10/09/2025 Hitendra Prajapati wrote:

> Upstream-Status: Backport from https://github.com/moby/moby/commit/fc274cd2ff4cf3b48c91697fb327dd1fb95588fb && https://github.com/moby/moby/commit/a79fabbfe84117696a19671f4aa88b82d0f64fc1

It is much more useful to indicate which release those
commits are from.

I can't find a branch that contains them, so I'm not
inclined to take them. A quick check on the link shows
a message that agrees with my local git checks:

"This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository."

A backport implies it is part of a release .. this doesn't appear to be the case here.

Bruce

> 
> Signed-off-by: Hitendra Prajapati <hprajapati@mvista.com>
> ---
>  recipes-containers/docker/docker-moby_git.bb  |   2 +
>  .../docker/files/CVE-2024-41110-001.patch     | 173 ++++++++++++++++++
>  .../docker/files/CVE-2024-41110-002.patch     |  95 ++++++++++
>  3 files changed, 270 insertions(+)
>  create mode 100644 recipes-containers/docker/files/CVE-2024-41110-001.patch
>  create mode 100644 recipes-containers/docker/files/CVE-2024-41110-002.patch
> 
> diff --git a/recipes-containers/docker/docker-moby_git.bb b/recipes-containers/docker/docker-moby_git.bb
> index d274b002..565925e2 100644
> --- a/recipes-containers/docker/docker-moby_git.bb
> +++ b/recipes-containers/docker/docker-moby_git.bb
> @@ -58,6 +58,8 @@ SRC_URI = "\
>          file://0001-dynbinary-use-go-cross-compiler.patch;patchdir=src/import \
>          file://CVE-2024-36620.patch;patchdir=src/import \
>          file://CVE-2024-36621.patch;patchdir=src/import \
> +        file://CVE-2024-41110-001.patch;patchdir=src/import \
> +        file://CVE-2024-41110-002.patch;patchdir=src/import \
>  	"
>  
>  DOCKER_COMMIT = "${SRCREV_moby}"
> diff --git a/recipes-containers/docker/files/CVE-2024-41110-001.patch b/recipes-containers/docker/files/CVE-2024-41110-001.patch
> new file mode 100644
> index 00000000..ed7c4628
> --- /dev/null
> +++ b/recipes-containers/docker/files/CVE-2024-41110-001.patch
> @@ -0,0 +1,173 @@
> +From fc274cd2ff4cf3b48c91697fb327dd1fb95588fb Mon Sep 17 00:00:00 2001
> +From: Jameson Hyde <jameson.hyde@docker.com>
> +Date: Mon, 26 Nov 2018 14:15:22 -0500
> +Subject: [PATCH] Authz plugin security fixes for 0-length content and path
> + validation Signed-off-by: Jameson Hyde <jameson.hyde@docker.com>
> +
> +fix comments
> +
> +(cherry picked from commit 9659c3a52bac57e615b5fb49b0652baca448643e)
> +Signed-off-by: Sebastiaan van Stijn <github@gone.nl>
> +Signed-off-by: Eli Uriegas <eli.uriegas@docker.com>
> +
> +CVE: CVE-2024-41110
> +Upstream-Status: Backport [https://github.com/moby/moby/commit/fc274cd2ff4cf3b48c91697fb327dd1fb95588fb]
> +Signed-off-by: Hitendra Prajapati <hprajapati@mvista.com>
> +---
> + pkg/authorization/authz.go           | 38 ++++++++++++++++++---
> + pkg/authorization/authz_unix_test.go | 49 ++++++++++++++++++++++++++--
> + 2 files changed, 80 insertions(+), 7 deletions(-)
> +
> +diff --git a/pkg/authorization/authz.go b/pkg/authorization/authz.go
> +index 1eb44315dd..6450f504af 100644
> +--- a/pkg/authorization/authz.go
> ++++ b/pkg/authorization/authz.go
> +@@ -8,6 +8,8 @@ import (
> + 	"io"
> + 	"mime"
> + 	"net/http"
> ++	"net/url"
> ++	"regexp"
> + 	"strings"
> + 
> + 	"github.com/containerd/log"
> +@@ -53,10 +55,23 @@ type Ctx struct {
> + 	authReq *Request
> + }
> + 
> ++func isChunked(r *http.Request) bool {
> ++	//RFC 7230 specifies that content length is to be ignored if Transfer-Encoding is chunked
> ++	if strings.ToLower(r.Header.Get("Transfer-Encoding")) == "chunked" {
> ++		return true
> ++	}
> ++	for _, v := range r.TransferEncoding {
> ++		if 0 == strings.Compare(strings.ToLower(v), "chunked") {
> ++			return true
> ++		}
> ++	}
> ++	return false
> ++}
> ++
> + // AuthZRequest authorized the request to the docker daemon using authZ plugins
> + func (ctx *Ctx) AuthZRequest(w http.ResponseWriter, r *http.Request) error {
> + 	var body []byte
> +-	if sendBody(ctx.requestURI, r.Header) && r.ContentLength > 0 && r.ContentLength < maxBodySize {
> ++	if sendBody(ctx.requestURI, r.Header) && (r.ContentLength > 0 || isChunked(r)) && r.ContentLength < maxBodySize {
> + 		var err error
> + 		body, r.Body, err = drainBody(r.Body)
> + 		if err != nil {
> +@@ -109,7 +124,6 @@ func (ctx *Ctx) AuthZResponse(rm ResponseModifier, r *http.Request) error {
> + 	if sendBody(ctx.requestURI, rm.Header()) {
> + 		ctx.authReq.ResponseBody = rm.RawBody()
> + 	}
> +-
> + 	for _, plugin := range ctx.plugins {
> + 		log.G(context.TODO()).Debugf("AuthZ response using plugin %s", plugin.Name())
> + 
> +@@ -147,10 +161,26 @@ func drainBody(body io.ReadCloser) ([]byte, io.ReadCloser, error) {
> + 	return nil, newBody, err
> + }
> + 
> ++func isAuthEndpoint(urlPath string) (bool, error) {
> ++	// eg www.test.com/v1.24/auth/optional?optional1=something&optional2=something (version optional)
> ++	matched, err := regexp.MatchString(`^[^\/]+\/(v\d[\d\.]*\/)?auth.*`, urlPath)
> ++	if err != nil {
> ++		return false, err
> ++	}
> ++	return matched, nil
> ++}
> ++
> + // sendBody returns true when request/response body should be sent to AuthZPlugin
> +-func sendBody(url string, header http.Header) bool {
> ++func sendBody(inURL string, header http.Header) bool {
> ++	u, err := url.Parse(inURL)
> ++	// Assume no if the URL cannot be parsed - an empty request will still be forwarded to the plugin and should be rejected
> ++	if err != nil {
> ++		return false
> ++	}
> ++
> + 	// Skip body for auth endpoint
> +-	if strings.HasSuffix(url, "/auth") {
> ++	isAuth, err := isAuthEndpoint(u.Path)
> ++	if isAuth || err != nil {
> + 		return false
> + 	}
> + 
> +diff --git a/pkg/authorization/authz_unix_test.go b/pkg/authorization/authz_unix_test.go
> +index c9b18d96e9..275f1dd3d0 100644
> +--- a/pkg/authorization/authz_unix_test.go
> ++++ b/pkg/authorization/authz_unix_test.go
> +@@ -174,8 +174,8 @@ func TestDrainBody(t *testing.T) {
> + 
> + func TestSendBody(t *testing.T) {
> + 	var (
> +-		url       = "nothing.com"
> + 		testcases = []struct {
> ++			url         string
> + 			contentType string
> + 			expected    bool
> + 		}{
> +@@ -219,15 +219,58 @@ func TestSendBody(t *testing.T) {
> + 				contentType: "",
> + 				expected:    false,
> + 			},
> ++			{
> ++				url:         "nothing.com/auth",
> ++				contentType: "",
> ++				expected:    false,
> ++			},
> ++			{
> ++				url:         "nothing.com/auth",
> ++				contentType: "application/json;charset=UTF8",
> ++				expected:    false,
> ++			},
> ++			{
> ++				url:         "nothing.com/auth?p1=test",
> ++				contentType: "application/json;charset=UTF8",
> ++				expected:    false,
> ++			},
> ++			{
> ++				url:         "nothing.com/test?p1=/auth",
> ++				contentType: "application/json;charset=UTF8",
> ++				expected:    true,
> ++			},
> ++			{
> ++				url:         "nothing.com/something/auth",
> ++				contentType: "application/json;charset=UTF8",
> ++				expected:    true,
> ++			},
> ++			{
> ++				url:         "nothing.com/auth/test",
> ++				contentType: "application/json;charset=UTF8",
> ++				expected:    false,
> ++			},
> ++			{
> ++				url:         "nothing.com/v1.24/auth/test",
> ++				contentType: "application/json;charset=UTF8",
> ++				expected:    false,
> ++			},
> ++			{
> ++				url:         "nothing.com/v1/auth/test",
> ++				contentType: "application/json;charset=UTF8",
> ++				expected:    false,
> ++			},
> + 		}
> + 	)
> + 
> + 	for _, testcase := range testcases {
> + 		header := http.Header{}
> + 		header.Set("Content-Type", testcase.contentType)
> ++		if testcase.url == "" {
> ++			testcase.url = "nothing.com"
> ++		}
> + 
> +-		if b := sendBody(url, header); b != testcase.expected {
> +-			t.Fatalf("Unexpected Content-Type; Expected: %t, Actual: %t", testcase.expected, b)
> ++		if b := sendBody(testcase.url, header); b != testcase.expected {
> ++			t.Fatalf("sendBody failed: url: %s, content-type: %s; Expected: %t, Actual: %t", testcase.url, testcase.contentType, testcase.expected, b)
> + 		}
> + 	}
> + }
> +-- 
> +2.50.1
> +
> diff --git a/recipes-containers/docker/files/CVE-2024-41110-002.patch b/recipes-containers/docker/files/CVE-2024-41110-002.patch
> new file mode 100644
> index 00000000..7d8b572d
> --- /dev/null
> +++ b/recipes-containers/docker/files/CVE-2024-41110-002.patch
> @@ -0,0 +1,95 @@
> +From a79fabbfe84117696a19671f4aa88b82d0f64fc1 Mon Sep 17 00:00:00 2001
> +From: Jameson Hyde <jameson.hyde@docker.com>
> +Date: Sat, 1 Dec 2018 11:25:49 -0500
> +Subject: [PATCH] If url includes scheme, urlPath will drop hostname, which
> + would not match the auth check
> +
> +Signed-off-by: Jameson Hyde <jameson.hyde@docker.com>
> +(cherry picked from commit 754fb8d9d03895ae3ab60d2ad778152b0d835206)
> +Signed-off-by: Sebastiaan van Stijn <github@gone.nl>
> +Signed-off-by: Eli Uriegas <eli.uriegas@docker.com>
> +
> +CVE: CVE-2024-41110
> +Upstream-Status: Backport [https://github.com/moby/moby/commit/a79fabbfe84117696a19671f4aa88b82d0f64fc1]
> +Signed-off-by: Hitendra Prajapati <hprajapati@mvista.com>
> +---
> + pkg/authorization/authz.go           |  6 ++---
> + pkg/authorization/authz_unix_test.go | 35 ++++++++++++++++++++++++++++
> + 2 files changed, 38 insertions(+), 3 deletions(-)
> +
> +diff --git a/pkg/authorization/authz.go b/pkg/authorization/authz.go
> +index 6450f504af..012aa7e487 100644
> +--- a/pkg/authorization/authz.go
> ++++ b/pkg/authorization/authz.go
> +@@ -57,11 +57,11 @@ type Ctx struct {
> + 
> + func isChunked(r *http.Request) bool {
> + 	//RFC 7230 specifies that content length is to be ignored if Transfer-Encoding is chunked
> +-	if strings.ToLower(r.Header.Get("Transfer-Encoding")) == "chunked" {
> ++	if strings.EqualFold(r.Header.Get("Transfer-Encoding"), "chunked") {
> + 		return true
> + 	}
> + 	for _, v := range r.TransferEncoding {
> +-		if 0 == strings.Compare(strings.ToLower(v), "chunked") {
> ++		if strings.EqualFold(v, "chunked") {
> + 			return true
> + 		}
> + 	}
> +@@ -163,7 +163,7 @@ func drainBody(body io.ReadCloser) ([]byte, io.ReadCloser, error) {
> + 
> + func isAuthEndpoint(urlPath string) (bool, error) {
> + 	// eg www.test.com/v1.24/auth/optional?optional1=something&optional2=something (version optional)
> +-	matched, err := regexp.MatchString(`^[^\/]+\/(v\d[\d\.]*\/)?auth.*`, urlPath)
> ++	matched, err := regexp.MatchString(`^[^\/]*\/(v\d[\d\.]*\/)?auth.*`, urlPath)
> + 	if err != nil {
> + 		return false, err
> + 	}
> +diff --git a/pkg/authorization/authz_unix_test.go b/pkg/authorization/authz_unix_test.go
> +index 275f1dd3d0..66b4d20452 100644
> +--- a/pkg/authorization/authz_unix_test.go
> ++++ b/pkg/authorization/authz_unix_test.go
> +@@ -259,6 +259,41 @@ func TestSendBody(t *testing.T) {
> + 				contentType: "application/json;charset=UTF8",
> + 				expected:    false,
> + 			},
> ++			{
> ++				url:         "www.nothing.com/v1.24/auth/test",
> ++				contentType: "application/json;charset=UTF8",
> ++				expected:    false,
> ++			},
> ++			{
> ++				url:         "https://www.nothing.com/v1.24/auth/test",
> ++				contentType: "application/json;charset=UTF8",
> ++				expected:    false,
> ++			},
> ++			{
> ++				url:         "http://nothing.com/v1.24/auth/test",
> ++				contentType: "application/json;charset=UTF8",
> ++				expected:    false,
> ++			},
> ++			{
> ++				url:         "www.nothing.com/test?p1=/auth",
> ++				contentType: "application/json;charset=UTF8",
> ++				expected:    true,
> ++			},
> ++			{
> ++				url:         "http://www.nothing.com/test?p1=/auth",
> ++				contentType: "application/json;charset=UTF8",
> ++				expected:    true,
> ++			},
> ++			{
> ++				url:         "www.nothing.com/something/auth",
> ++				contentType: "application/json;charset=UTF8",
> ++				expected:    true,
> ++			},
> ++			{
> ++				url:         "https://www.nothing.com/something/auth",
> ++				contentType: "application/json;charset=UTF8",
> ++				expected:    true,
> ++			},
> + 		}
> + 	)
> + 
> +-- 
> +2.50.1
> +
> -- 
> 2.50.1
> 


      reply	other threads:[~2025-09-19  2:37 UTC|newest]

Thread overview: 2+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2025-09-10 14:13 [meta-virtualization][scarthgap][PATCH] docker-moby: fix CVE-2024-41110 Hitendra Prajapati
2025-09-19  2:37 ` Bruce Ashfield [this message]

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=aMzB92SypOpZS4BI@gmail.com \
    --to=bruce.ashfield@gmail.com \
    --cc=hprajapati@mvista.com \
    --cc=meta-virtualization@lists.yoctoproject.org \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
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.