diff --git a/Bugfix-for-CVE-2024-42472.patch b/Bugfix-for-CVE-2024-42472.patch new file mode 100644 index 0000000000000000000000000000000000000000..de162c7d8c0d5c9c341f01a45a56cc92da3ca06f --- /dev/null +++ b/Bugfix-for-CVE-2024-42472.patch @@ -0,0 +1,270 @@ +diff -Naur a/bubblewrap/bubblewrap.c b/bubblewrap/bubblewrap.c +--- a/bubblewrap/bubblewrap.c 2019-09-19 21:04:06.000000000 +0800 ++++ b/bubblewrap/bubblewrap.c 2024-09-23 17:34:00.152028658 +0800 +@@ -209,6 +209,8 @@ + " --bind SRC DEST Bind mount the host path SRC on DEST\n" + " --dev-bind SRC DEST Bind mount the host path SRC on DEST, allowing device access\n" + " --ro-bind SRC DEST Bind mount the host path SRC readonly on DEST\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" +@@ -995,6 +997,30 @@ + (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: +@@ -1519,6 +1545,30 @@ + op->dest = argv[2]; + + 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; + } + else if (strcmp (arg, "--proc") == 0) +diff -Naur a/common/flatpak-context.c b/common/flatpak-context.c +--- a/common/flatpak-context.c 2024-09-23 17:28:14.553986528 +0800 ++++ b/common/flatpak-context.c 2024-09-23 17:34:00.148028494 +0800 +@@ -2110,6 +2110,90 @@ + return flags; + } + ++/* This creates zero or more directories unders base_fd+basedir, each ++ * being guaranteed to either exist and be a directory (no symlinks) ++ * or be created as a directory. The last directory is opened ++ * and the fd is returned. ++ */ ++static gboolean ++mkdir_p_open_nofollow_at (int base_fd, ++ const char *basedir, ++ int mode, ++ const char *subdir, ++ int *out_fd, ++ GError **error) ++{ ++ glnx_autofd int parent_fd = -1; ++ ++ if (g_path_is_absolute (subdir)) ++ { ++ const char *skipped_prefix = subdir; ++ ++ while (*skipped_prefix == '/') ++ skipped_prefix++; ++ ++ g_warning ("--persist=\"%s\" is deprecated, treating it as --persist=\"%s\"", subdir, skipped_prefix); ++ subdir = skipped_prefix; ++ } ++ ++ g_autofree char *subdir_dirname = g_path_get_dirname (subdir); ++ ++ if (strcmp (subdir_dirname, ".") == 0) ++ { ++ /* It is ok to open basedir with follow=true */ ++ if (!glnx_opendirat (base_fd, basedir, TRUE, &parent_fd, error)) ++ return FALSE; ++ } ++ else if (strcmp (subdir_dirname, "..") == 0) ++ { ++ return glnx_throw (error, "'..' not supported in --persist paths"); ++ } ++ else ++ { ++ if (!mkdir_p_open_nofollow_at (base_fd, basedir, mode, ++ subdir_dirname, &parent_fd, error)) ++ return FALSE; ++ } ++ ++ g_autofree char *subdir_basename = g_path_get_basename (subdir); ++ ++ if (strcmp (subdir_basename, ".") == 0) ++ { ++ *out_fd = glnx_steal_fd (&parent_fd); ++ return TRUE; ++ } ++ else if (strcmp (subdir_basename, "..") == 0) ++ { ++ return glnx_throw (error, "'..' not supported in --persist paths"); ++ } ++ ++ if (!glnx_shutil_mkdir_p_at (parent_fd, subdir_basename, mode, NULL, error)) ++ return FALSE; ++ ++ int fd = openat (parent_fd, subdir_basename, O_PATH | O_NONBLOCK | O_DIRECTORY | O_CLOEXEC | O_NOCTTY | O_NOFOLLOW); ++ if (fd == -1) ++ { ++ int saved_errno = errno; ++ struct stat stat_buf; ++ ++ /* If it's a symbolic link, that could be a user trying to offload ++ * large data to another filesystem, but it could equally well be ++ * a malicious or compromised app trying to exploit GHSA-7hgv-f2j8-xw87. ++ * Produce a clearer error message in this case. ++ * Unfortunately the errno we get in this case is ENOTDIR, so we have ++ * to ask again to find out whether it's really a symlink. */ ++ if (saved_errno == ENOTDIR && ++ fstatat (parent_fd, subdir_basename, &stat_buf, AT_SYMLINK_NOFOLLOW) == 0 && ++ S_ISLNK (stat_buf.st_mode)) ++ return glnx_throw (error, "Symbolic link \"%s\" not allowed to avoid sandbox escape", subdir_basename); ++ ++ return glnx_throw_errno_prefix (error, "openat(%s)", subdir_basename); ++ } ++ ++ *out_fd = fd; ++ return TRUE; ++} ++ + void + flatpak_context_append_bwrap_filesystem (FlatpakContext *context, + FlatpakBwrap *bwrap, +@@ -2136,12 +2220,30 @@ + while (g_hash_table_iter_next (&iter, &key, NULL)) + { + const char *persist = key; +- g_autofree char *src = g_build_filename (g_get_home_dir (), ".var/app", app_id, persist, NULL); ++ g_autofree char *appdir = g_build_filename (g_get_home_dir (), ".var/app", app_id, NULL); + g_autofree char *dest = g_build_filename (g_get_home_dir (), persist, NULL); ++ g_autoptr(GError) local_error = NULL; ++ ++ if (g_mkdir_with_parents (appdir, 0755) != 0) ++ { ++ g_warning ("Unable to create directory %s", appdir); ++ continue; ++ } ++ ++ /* Don't follow symlinks from the persist directory, as it is under user control */ ++ glnx_autofd int src_fd = -1; ++ if (!mkdir_p_open_nofollow_at (AT_FDCWD, appdir, 0755, ++ persist, &src_fd, ++ &local_error)) ++ { ++ g_warning ("Failed to create persist path %s: %s", persist, local_error->message); ++ continue; ++ } + +- g_mkdir_with_parents (src, 0755); ++ g_autofree char *src_via_proc = g_strdup_printf ("%d", src_fd); + +- flatpak_bwrap_add_bind_arg (bwrap, "--bind", src, dest); ++ flatpak_bwrap_add_fd (bwrap, glnx_steal_fd (&src_fd)); ++ flatpak_bwrap_add_bind_arg (bwrap, "--bind-fd", src_via_proc, dest); + } + } + +diff -Naur a/configure.ac b/configure.ac +--- a/configure.ac 2019-09-19 21:03:47.000000000 +0800 ++++ b/configure.ac 2024-09-23 17:34:00.144028329 +0800 +@@ -156,6 +156,9 @@ + BWRAP_VERSION=`$BWRAP --version | sed 's,.*\ \([0-9]*\.[0-9]*\.[0-9]*\)$,\1,'` + AX_COMPARE_VERSION([$SYSTEM_BWRAP_REQS],[gt],[$BWRAP_VERSION], + [AC_MSG_ERROR([You need at least version $SYSTEM_BWRAP_REQS of bubblewrap to use the system installed version])]) ++ AS_IF([$BWRAP --help | grep '@<:@-@:>@-bind-fd' >/dev/null], ++ [:], ++ [AC_MSG_ERROR([$BWRAP does not list required option --bind-fd in its --help])]) + AM_CONDITIONAL([WITH_SYSTEM_BWRAP], [true]) + else + AC_CHECK_LIB(cap, cap_from_text, CAP_LIB=-lcap) +diff -Naur a/tests/test-run.sh b/tests/test-run.sh +--- a/tests/test-run.sh 2024-09-23 17:28:14.573987340 +0800 ++++ b/tests/test-run.sh 2024-09-23 17:34:00.144028329 +0800 +@@ -23,7 +23,7 @@ + + skip_without_bwrap + +-echo "1..13" ++echo "1..14" + + setup_repo + install_repo +@@ -378,3 +378,42 @@ + assert_file_has_content err2.txt [Ii]nvalid + + echo "ok no setuid" ++ ++rm -fr "$HOME/.var/app/org.test.Hello" ++mkdir -p "$HOME/.var/app/org.test.Hello" ++run --command=sh --persist=.persist org.test.Hello -c 'echo can-persist > .persist/rc' ++sed -e 's,^,#--persist=.persist# ,g' < "$HOME/.var/app/org.test.Hello/.persist/rc" >&2 ++assert_file_has_content "$HOME/.var/app/org.test.Hello/.persist/rc" "can-persist" ++ ++echo "ok --persist=.persist persists a directory" ++ ++rm -fr "$HOME/.var/app/org.test.Hello" ++mkdir -p "$HOME/.var/app/org.test.Hello" ++# G_DEBUG= to avoid the deprecation warning being fatal ++G_DEBUG= run --command=sh --persist=/.persist org.test.Hello -c 'echo can-persist > .persist/rc' ++sed -e 's,^,#--persist=/.persist# ,g' < "$HOME/.var/app/org.test.Hello/.persist/rc" >&2 ++assert_file_has_content "$HOME/.var/app/org.test.Hello/.persist/rc" "can-persist" ++ ++echo "ok --persist=/.persist is a deprecated form of --persist=.persist" ++ ++rm -fr "$HOME/.var/app/org.test.Hello" ++mkdir -p "$HOME/.var/app/org.test.Hello" ++run --command=sh --persist=. org.test.Hello -c 'echo can-persist > .persistrc' ++sed -e 's,^,#--persist=.# ,g' < "$HOME/.var/app/org.test.Hello/.persistrc" >&2 ++assert_file_has_content "$HOME/.var/app/org.test.Hello/.persistrc" "can-persist" ++ ++echo "ok --persist=. persists all files" ++ ++mkdir "${TEST_DATA_DIR}/inaccessible" ++echo FOO > ${TEST_DATA_DIR}/inaccessible/secret-file ++rm -fr "$HOME/.var/app/org.test.Hello" ++mkdir -p "$HOME/.var/app/org.test.Hello" ++ln -fns "${TEST_DATA_DIR}/inaccessible" "$HOME/.var/app/org.test.Hello/persist" ++# G_DEBUG= to avoid the warnings being fatal when we reject a --persist option. ++# LC_ALL=C so we get the expected non-localized string. ++LC_ALL=C G_DEBUG= run --command=ls --persist=persist --persist=relative/../escape org.test.Hello -la ~/persist &> hello_out || true ++sed -e 's,^,#--persist=symlink# ,g' < hello_out >&2 ++assert_file_has_content hello_out "not allowed to avoid sandbox escape" ++assert_not_file_has_content hello_out "secret-file" ++ ++echo "ok --persist doesn't allow sandbox escape via a symlink (CVE-2024-42472)" diff --git a/flatpak.spec b/flatpak.spec index 85d1ece2da5e51336af1b96d433ffc374027fa91..81081ae5a20249ced4aee9ffaceee866420e4a66 100644 --- a/flatpak.spec +++ b/flatpak.spec @@ -1,10 +1,11 @@ +%define anolis_release .0.1 %global flatpak_version 1.0.9 %global flatpak_builder_version 1.0.0 %global ostree_version 2018.8 Name: flatpak Version: %{flatpak_version} -Release: 13%{?dist} +Release: 13%{anolis_release}%{?dist} Summary: Application deployment framework for desktop apps License: LGPLv2+ @@ -31,6 +32,9 @@ Patch6: flatpak-1.0.9-fix-CVE-2021-21381.patch Patch7: flatpak-1.0.9-fix-CVE-2021-41133.patch # Backported CVE-2024-32462 fix from upstream Patch8: flatpak-CVE-2024-32462.patch +#add by uos +Patch9: Bugfix-for-CVE-2024-42472.patch +#end BuildRequires: pkgconfig(appstream-glib) BuildRequires: pkgconfig(fuse) @@ -148,7 +152,7 @@ This package contains libflatpak. %patch6 -p1 %patch7 -p1 %patch8 -p1 - +%patch9 -p1 %build cd libostree-%{ostree_version} @@ -304,6 +308,9 @@ flatpak remote-list --system &> /dev/null || : %changelog +* Tue Sep 3 2024 zhuhongbo - 1.0.9-13.0.1 +- cve:fix Fix CVE-2024-42472 + * Fri Jun 07 2024 Kalev Lember - 1.0.9-13 - Fix CVE-2024-32462