From 59b2a0550c079e2e28d82cd23998b998303eec7a Mon Sep 17 00:00:00 2001 From: wk333 <13474090681@163.com> Date: Fri, 16 Aug 2024 14:36:11 +0800 Subject: [PATCH] Add --bind-fd and --ro-bind-fd to let you bind a O_PATH fd for flatpak fix CVE-2024-42472 --- ...-bind-fd-to-let-you-bind-a-O_PATH-fd.patch | 117 ++++++++++++++++++ bubblewrap.spec | 6 +- 2 files changed, 122 insertions(+), 1 deletion(-) create mode 100644 backport-Add--bind-fd-and--ro-bind-fd-to-let-you-bind-a-O_PATH-fd.patch diff --git a/backport-Add--bind-fd-and--ro-bind-fd-to-let-you-bind-a-O_PATH-fd.patch b/backport-Add--bind-fd-and--ro-bind-fd-to-let-you-bind-a-O_PATH-fd.patch new file mode 100644 index 0000000..2ea1c0e --- /dev/null +++ b/backport-Add--bind-fd-and--ro-bind-fd-to-let-you-bind-a-O_PATH-fd.patch @@ -0,0 +1,117 @@ +From 68e75c3091c87583c28a439b45c45627a94d622c Mon Sep 17 00:00:00 2001 +From: Alexander Larsson +Date: Tue, 18 Jun 2024 10:20:36 +0200 +Subject: [PATCH] Add --bind-fd and --ro-bind-fd to let you bind a O_PATH fd. + +Origin: https://github.com/containers/bubblewrap/commit/68e75c3091c87583c28a439b45c45627a94d622c + +This is useful for example if you for some reason don't have the real +path. It is also a way to make bind-mounts race-free (i.e. to have the +mount actually be the thing you wanted to be mounted, avoiding issues +where some other process replaces the target in parallel with the bwrap +launch. + +Unfortunately due to some technical details we can't actually directly +mount the dirfd, as they come from different user namespace which is not +permitted, but at least we can delay resolving the fd to a path as much as +possible, and then validate after mount that we actually mounted the right +thing. + +Signed-off-by: Alexander Larsson +(cherry picked from commit a253257cd298892da43e15201d83f9a02c9b58b5) +[smcv: Backport to 0.6.x] +Signed-off-by: Simon McVittie +--- + bubblewrap.c | 50 +++++++++++++++++++++++++++++++++++++++++++++++ + tests/test-run.sh | 7 ++++++- + 2 files changed, 56 insertions(+), 1 deletion(-) + +diff --git a/bubblewrap.c b/bubblewrap.c +index b17ff990..1d2cc41c 100644 +--- a/bubblewrap.c ++++ b/bubblewrap.c +@@ -317,6 +317,8 @@ usage (int ecode, FILE *out) + " --dev-bind-try SRC DEST Equal to --dev-bind but ignores non-existent SRC\n" + " --ro-bind SRC DEST Bind mount the host path SRC readonly on DEST\n" + " --ro-bind-try SRC DEST Equal to --ro-bind but ignores non-existent SRC\n" ++ " --bind-fd FD DEST Bind open directory or path fd on DEST\n" ++ " --ro-bind-fd FD DEST Bind open directory or path fd read-only on DEST\n" + " --remount-ro DEST Remount DEST as readonly; does not recursively remount\n" + " --exec-label LABEL Exec label for the sandbox\n" + " --file-label LABEL File label for temporary sandbox content\n" +@@ -1198,6 +1200,30 @@ setup_newroot (bool unshare_pid, + (op->type == SETUP_RO_BIND_MOUNT ? BIND_READONLY : 0) | + (op->type == SETUP_DEV_BIND_MOUNT ? BIND_DEVICES : 0), + source, dest); ++ ++ if (op->fd >= 0) ++ { ++ struct stat fd_st, mount_st; ++ ++ /* When using bind-fd, there is a race condition between resolving the fd as a magic symlink ++ * and mounting it, where someone could replace what is at the symlink target. Ideally ++ * we would not even resolve the symlink and directly bind-mount from the fd, but unfortunately ++ * we can't do that, because its not permitted to bind mount a fd from another user namespace. ++ * So, we resolve, mount and then compare fstat+stat to detect the race. */ ++ ++ if (fstat(op->fd, &fd_st) != 0) ++ die_with_error("Can't stat fd %d", op->fd); ++ if (lstat(dest, &mount_st) != 0) ++ die_with_error("Can't stat mount at %s", dest); ++ ++ if (fd_st.st_ino != mount_st.st_ino || ++ fd_st.st_dev != mount_st.st_dev) ++ die_with_error("Race condition binding dirfd"); ++ ++ close(op->fd); ++ op->fd = -1; ++ } ++ + break; + + case SETUP_REMOUNT_RO_NO_RECURSIVE: +@@ -1819,6 +1845,30 @@ parse_args_recurse (int *argcp, + if (strcmp(arg, "--dev-bind-try") == 0) + op->flags = ALLOW_NOTEXIST; + ++ argv += 2; ++ argc -= 2; ++ } ++ else if (strcmp (arg, "--bind-fd") == 0 || ++ strcmp (arg, "--ro-bind-fd") == 0) ++ { ++ int src_fd; ++ char *endptr; ++ ++ if (argc < 3) ++ die ("--bind-fd takes two arguments"); ++ ++ src_fd = strtol (argv[1], &endptr, 10); ++ if (argv[1][0] == 0 || endptr[0] != 0 || src_fd < 0) ++ die ("Invalid fd: %s", argv[1]); ++ ++ if (strcmp(arg, "--ro-bind-fd") == 0) ++ op = setup_op_new (SETUP_RO_BIND_MOUNT); ++ else ++ op = setup_op_new (SETUP_BIND_MOUNT); ++ op->source = xasprintf ("/proc/self/fd/%d", src_fd); ++ op->fd = src_fd; ++ op->dest = argv[2]; ++ + argv += 2; + argc -= 2; + } +diff --git a/tests/test-run.sh b/tests/test-run.sh +index f25a9bc3..c5ce1866 100755 +--- a/tests/test-run.sh ++++ b/tests/test-run.sh +@@ -329,4 +329,9 @@ + fi + echo "ok - we can mount another directory inside /tmp" + ++echo "foobar" > file-data ++$RUN --proc /proc --dev /dev --bind / / --bind-fd 100 /tmp cat /tmp/file-data 100< . > stdout ++assert_file_has_content stdout foobar ++echo "ok - bind-fd" ++ + echo "ok - End of test" diff --git a/bubblewrap.spec b/bubblewrap.spec index 22af20a..36eab9d 100644 --- a/bubblewrap.spec +++ b/bubblewrap.spec @@ -1,10 +1,11 @@ Name: bubblewrap Version: 0.3.3 -Release: 1 +Release: 2 Summary: Core execution tool for unprivileged containers License: LGPLv2+ URL: https://github.com/projectatomic/bubblewrap Source0: https://github.com/containers/bubblewrap/archive/bubblewrap-%{version}.tar.xz +Patch0: backport-Add--bind-fd-and--ro-bind-fd-to-let-you-bind-a-O_PATH-fd.patch BuildRequires: autoconf automake libtool gcc libcap-devel BuildRequires: pkgconfig(libselinux) libxslt docbook-style-xsl @@ -39,5 +40,8 @@ if ! test -x configure; then NOCONFIGURE=1 ./autogen.sh; fi %{_mandir}/man1/* %changelog +* Fri Aug 16 2024 wangkai <13474090681@163.com> - 0.3.3-2 +- Add --bind-fd and --ro-bind-fd to let you bind a O_PATH fd for flatpak fix CVE-2024-42472 + * Mon Oct 21 2019 openEuler Buildteam - 0.3.3-1 - Package init -- Gitee