From: Greg Kroah-Hartman Date: Mon, 2 Jun 2025 12:46:40 +0000 (+0200) Subject: 6.1-stable patches X-Git-Tag: v5.4.294~17 X-Git-Url: http://git.ipfire.org/?a=commitdiff_plain;h=35c0a2386859e5d88495dbae5fa6eebd2f30b3ed;p=thirdparty%2Fkernel%2Fstable-queue.git 6.1-stable patches added patches: coredump-fix-error-handling-for-replace_fd.patch coredump-hand-a-pidfd-to-the-usermode-coredump-helper.patch fork-use-pidfd_prepare.patch pid-add-pidfd_prepare.patch --- diff --git a/queue-6.1/coredump-fix-error-handling-for-replace_fd.patch b/queue-6.1/coredump-fix-error-handling-for-replace_fd.patch new file mode 100644 index 0000000000..f6e8bb31fe --- /dev/null +++ b/queue-6.1/coredump-fix-error-handling-for-replace_fd.patch @@ -0,0 +1,52 @@ +From cfdc0503a546064a0762a53194b09885ab3c8267 Mon Sep 17 00:00:00 2001 +From: Christian Brauner +Date: Mon, 14 Apr 2025 15:55:06 +0200 +Subject: coredump: fix error handling for replace_fd() + +From: Christian Brauner + +commit 95c5f43181fe9c1b5e5a4bd3281c857a5259991f upstream. + +The replace_fd() helper returns the file descriptor number on success +and a negative error code on failure. The current error handling in +umh_pipe_setup() only works because the file descriptor that is replaced +is zero but that's pretty volatile. Explicitly check for a negative +error code. + +Link: https://lore.kernel.org/20250414-work-coredump-v2-2-685bf231f828@kernel.org +Tested-by: Luca Boccassi +Reviewed-by: Oleg Nesterov +Signed-off-by: Christian Brauner +Signed-off-by: Greg Kroah-Hartman +--- + fs/coredump.c | 9 +++++++-- + 1 file changed, 7 insertions(+), 2 deletions(-) + +--- a/fs/coredump.c ++++ b/fs/coredump.c +@@ -493,7 +493,9 @@ static int umh_pipe_setup(struct subproc + { + struct file *files[2]; + struct coredump_params *cp = (struct coredump_params *)info->data; +- int err = create_pipe_files(files, 0); ++ int err; ++ ++ err = create_pipe_files(files, 0); + if (err) + return err; + +@@ -501,10 +503,13 @@ static int umh_pipe_setup(struct subproc + + err = replace_fd(0, files[0], 0); + fput(files[0]); ++ if (err < 0) ++ return err; ++ + /* and disallow core files too */ + current->signal->rlim[RLIMIT_CORE] = (struct rlimit){1, 1}; + +- return err; ++ return 0; + } + + void do_coredump(const kernel_siginfo_t *siginfo) diff --git a/queue-6.1/coredump-hand-a-pidfd-to-the-usermode-coredump-helper.patch b/queue-6.1/coredump-hand-a-pidfd-to-the-usermode-coredump-helper.patch new file mode 100644 index 0000000000..d992ef0196 --- /dev/null +++ b/queue-6.1/coredump-hand-a-pidfd-to-the-usermode-coredump-helper.patch @@ -0,0 +1,202 @@ +From 9c3383683cf521ac19f2d6a1f0001020cbdef5ea Mon Sep 17 00:00:00 2001 +From: Christian Brauner +Date: Mon, 14 Apr 2025 15:55:07 +0200 +Subject: coredump: hand a pidfd to the usermode coredump helper + +From: Christian Brauner + +commit b5325b2a270fcaf7b2a9a0f23d422ca8a5a8bdea upstream. + +Give userspace a way to instruct the kernel to install a pidfd into the +usermode helper process. This makes coredump handling a lot more +reliable for userspace. In parallel with this commit we already have +systemd adding support for this in [1]. + +We create a pidfs file for the coredumping process when we process the +corename pattern. When the usermode helper process is forked we then +install the pidfs file as file descriptor three into the usermode +helpers file descriptor table so it's available to the exec'd program. + +Since usermode helpers are either children of the system_unbound_wq +workqueue or kthreadd we know that the file descriptor table is empty +and can thus always use three as the file descriptor number. + +Note, that we'll install a pidfd for the thread-group leader even if a +subthread is calling do_coredump(). We know that task linkage hasn't +been removed due to delay_group_leader() and even if this @current isn't +the actual thread-group leader we know that the thread-group leader +cannot be reaped until @current has exited. + +[brauner: This is a backport for the v6.1 series. Upstream has +significantly changed and backporting all that infra is a non-starter. +So simply backport the pidfd_prepare() helper and waste the file +descriptor we allocated. Then we minimally massage the umh coredump +setup code.] + +Link: https://github.com/systemd/systemd/pull/37125 [1] +Link: https://lore.kernel.org/20250414-work-coredump-v2-3-685bf231f828@kernel.org +Tested-by: Luca Boccassi +Reviewed-by: Oleg Nesterov +Signed-off-by: Christian Brauner +Signed-off-by: Greg Kroah-Hartman +--- + fs/coredump.c | 78 ++++++++++++++++++++++++++++++++++++++++++----- + include/linux/coredump.h | 1 + 2 files changed, 72 insertions(+), 7 deletions(-) + +--- a/fs/coredump.c ++++ b/fs/coredump.c +@@ -42,6 +42,7 @@ + #include + #include + #include ++#include + + #include + #include +@@ -56,6 +57,13 @@ + static bool dump_vma_snapshot(struct coredump_params *cprm); + static void free_vma_snapshot(struct coredump_params *cprm); + ++/* ++ * File descriptor number for the pidfd for the thread-group leader of ++ * the coredumping task installed into the usermode helper's file ++ * descriptor table. ++ */ ++#define COREDUMP_PIDFD_NUMBER 3 ++ + static int core_uses_pid; + static unsigned int core_pipe_limit; + static char core_pattern[CORENAME_MAX_SIZE] = "core"; +@@ -325,6 +333,27 @@ static int format_corename(struct core_n + err = cn_printf(cn, "%lu", + rlimit(RLIMIT_CORE)); + break; ++ /* pidfd number */ ++ case 'F': { ++ /* ++ * Installing a pidfd only makes sense if ++ * we actually spawn a usermode helper. ++ */ ++ if (!ispipe) ++ break; ++ ++ /* ++ * Note that we'll install a pidfd for the ++ * thread-group leader. We know that task ++ * linkage hasn't been removed yet and even if ++ * this @current isn't the actual thread-group ++ * leader we know that the thread-group leader ++ * cannot be reaped until @current has exited. ++ */ ++ cprm->pid = task_tgid(current); ++ err = cn_printf(cn, "%d", COREDUMP_PIDFD_NUMBER); ++ break; ++ } + default: + break; + } +@@ -479,7 +508,7 @@ static void wait_for_dump_helpers(struct + } + + /* +- * umh_pipe_setup ++ * umh_coredump_setup + * helper function to customize the process used + * to collect the core in userspace. Specifically + * it sets up a pipe and installs it as fd 0 (stdin) +@@ -489,27 +518,62 @@ static void wait_for_dump_helpers(struct + * is a special value that we use to trap recursive + * core dumps + */ +-static int umh_pipe_setup(struct subprocess_info *info, struct cred *new) ++static int umh_coredump_setup(struct subprocess_info *info, struct cred *new) + { + struct file *files[2]; ++ struct file *pidfs_file = NULL; + struct coredump_params *cp = (struct coredump_params *)info->data; + int err; + ++ if (cp->pid) { ++ int fd; ++ ++ fd = pidfd_prepare(cp->pid, 0, &pidfs_file); ++ if (fd < 0) ++ return fd; ++ ++ /* ++ * We don't care about the fd. We also cannot simply ++ * replace it below because dup2() will refuse to close ++ * this file descriptor if its in a larval state. So ++ * close it! ++ */ ++ put_unused_fd(fd); ++ ++ /* ++ * Usermode helpers are childen of either ++ * system_unbound_wq or of kthreadd. So we know that ++ * we're starting off with a clean file descriptor ++ * table. So we should always be able to use ++ * COREDUMP_PIDFD_NUMBER as our file descriptor value. ++ */ ++ err = replace_fd(COREDUMP_PIDFD_NUMBER, pidfs_file, 0); ++ if (err < 0) ++ goto out_fail; ++ ++ pidfs_file = NULL; ++ } ++ + err = create_pipe_files(files, 0); + if (err) +- return err; ++ goto out_fail; + + cp->file = files[1]; + + err = replace_fd(0, files[0], 0); + fput(files[0]); + if (err < 0) +- return err; ++ goto out_fail; + + /* and disallow core files too */ + current->signal->rlim[RLIMIT_CORE] = (struct rlimit){1, 1}; + +- return 0; ++ err = 0; ++ ++out_fail: ++ if (pidfs_file) ++ fput(pidfs_file); ++ return err; + } + + void do_coredump(const kernel_siginfo_t *siginfo) +@@ -585,7 +649,7 @@ void do_coredump(const kernel_siginfo_t + } + + if (cprm.limit == 1) { +- /* See umh_pipe_setup() which sets RLIMIT_CORE = 1. ++ /* See umh_coredump_setup() which sets RLIMIT_CORE = 1. + * + * Normally core limits are irrelevant to pipes, since + * we're not writing to the file system, but we use +@@ -630,7 +694,7 @@ void do_coredump(const kernel_siginfo_t + retval = -ENOMEM; + sub_info = call_usermodehelper_setup(helper_argv[0], + helper_argv, NULL, GFP_KERNEL, +- umh_pipe_setup, NULL, &cprm); ++ umh_coredump_setup, NULL, &cprm); + if (sub_info) + retval = call_usermodehelper_exec(sub_info, + UMH_WAIT_EXEC); +--- a/include/linux/coredump.h ++++ b/include/linux/coredump.h +@@ -28,6 +28,7 @@ struct coredump_params { + int vma_count; + size_t vma_data_size; + struct core_vma_metadata *vma_meta; ++ struct pid *pid; + }; + + /* diff --git a/queue-6.1/fork-use-pidfd_prepare.patch b/queue-6.1/fork-use-pidfd_prepare.patch new file mode 100644 index 0000000000..cb1e2f9395 --- /dev/null +++ b/queue-6.1/fork-use-pidfd_prepare.patch @@ -0,0 +1,46 @@ +From 9d8ad5d4fe33fc9c63d0bb7f8d7b8fdc0d36ec2a Mon Sep 17 00:00:00 2001 +From: Christian Brauner +Date: Mon, 27 Mar 2023 20:22:52 +0200 +Subject: fork: use pidfd_prepare() + +From: Christian Brauner + +commit ca7707f5430ad6b1c9cb7cee0a7f67d69328bb2d upstream. + +Stop open-coding get_unused_fd_flags() and anon_inode_getfile(). That's +brittle just for keeping the flags between both calls in sync. Use the +dedicated helper. + +Message-Id: <20230327-pidfd-file-api-v1-2-5c0e9a3158e4@kernel.org> +Signed-off-by: Christian Brauner +Signed-off-by: Greg Kroah-Hartman +--- + kernel/fork.c | 13 ++----------- + 1 file changed, 2 insertions(+), 11 deletions(-) + +--- a/kernel/fork.c ++++ b/kernel/fork.c +@@ -2378,21 +2378,12 @@ static __latent_entropy struct task_stru + * if the fd table isn't shared). + */ + if (clone_flags & CLONE_PIDFD) { +- retval = get_unused_fd_flags(O_RDWR | O_CLOEXEC); ++ /* Note that no task has been attached to @pid yet. */ ++ retval = __pidfd_prepare(pid, O_RDWR | O_CLOEXEC, &pidfile); + if (retval < 0) + goto bad_fork_free_pid; +- + pidfd = retval; + +- pidfile = anon_inode_getfile("[pidfd]", &pidfd_fops, pid, +- O_RDWR | O_CLOEXEC); +- if (IS_ERR(pidfile)) { +- put_unused_fd(pidfd); +- retval = PTR_ERR(pidfile); +- goto bad_fork_free_pid; +- } +- get_pid(pid); /* held by pidfile now */ +- + retval = put_user(pidfd, args->pidfd); + if (retval) + goto bad_fork_put_pidfd; diff --git a/queue-6.1/pid-add-pidfd_prepare.patch b/queue-6.1/pid-add-pidfd_prepare.patch new file mode 100644 index 0000000000..3e6a7867e2 --- /dev/null +++ b/queue-6.1/pid-add-pidfd_prepare.patch @@ -0,0 +1,159 @@ +From bfc6a7e6e3ce7ba21ea1e182c1d9f7f6fc72bbe9 Mon Sep 17 00:00:00 2001 +From: Christian Brauner +Date: Mon, 27 Mar 2023 20:22:51 +0200 +Subject: pid: add pidfd_prepare() + +From: Christian Brauner + +commit 6ae930d9dbf2d093157be33428538c91966d8a9f upstream. + +Add a new helper that allows to reserve a pidfd and allocates a new +pidfd file that stashes the provided struct pid. This will allow us to +remove places that either open code this function or that call +pidfd_create() but then have to call close_fd() because there are still +failure points after pidfd_create() has been called. + +Reviewed-by: Jan Kara +Message-Id: <20230327-pidfd-file-api-v1-1-5c0e9a3158e4@kernel.org> +Signed-off-by: Christian Brauner +Signed-off-by: Greg Kroah-Hartman +--- + include/linux/pid.h | 1 + kernel/fork.c | 85 ++++++++++++++++++++++++++++++++++++++++++++++++++++ + kernel/pid.c | 19 ++++------- + 3 files changed, 93 insertions(+), 12 deletions(-) + +--- a/include/linux/pid.h ++++ b/include/linux/pid.h +@@ -80,6 +80,7 @@ extern struct pid *pidfd_pid(const struc + struct pid *pidfd_get_pid(unsigned int fd, unsigned int *flags); + struct task_struct *pidfd_get_task(int pidfd, unsigned int *flags); + int pidfd_create(struct pid *pid, unsigned int flags); ++int pidfd_prepare(struct pid *pid, unsigned int flags, struct file **ret); + + static inline struct pid *get_pid(struct pid *pid) + { +--- a/kernel/fork.c ++++ b/kernel/fork.c +@@ -1943,6 +1943,91 @@ const struct file_operations pidfd_fops + #endif + }; + ++/** ++ * __pidfd_prepare - allocate a new pidfd_file and reserve a pidfd ++ * @pid: the struct pid for which to create a pidfd ++ * @flags: flags of the new @pidfd ++ * @pidfd: the pidfd to return ++ * ++ * Allocate a new file that stashes @pid and reserve a new pidfd number in the ++ * caller's file descriptor table. The pidfd is reserved but not installed yet. ++ ++ * The helper doesn't perform checks on @pid which makes it useful for pidfds ++ * created via CLONE_PIDFD where @pid has no task attached when the pidfd and ++ * pidfd file are prepared. ++ * ++ * If this function returns successfully the caller is responsible to either ++ * call fd_install() passing the returned pidfd and pidfd file as arguments in ++ * order to install the pidfd into its file descriptor table or they must use ++ * put_unused_fd() and fput() on the returned pidfd and pidfd file ++ * respectively. ++ * ++ * This function is useful when a pidfd must already be reserved but there ++ * might still be points of failure afterwards and the caller wants to ensure ++ * that no pidfd is leaked into its file descriptor table. ++ * ++ * Return: On success, a reserved pidfd is returned from the function and a new ++ * pidfd file is returned in the last argument to the function. On ++ * error, a negative error code is returned from the function and the ++ * last argument remains unchanged. ++ */ ++static int __pidfd_prepare(struct pid *pid, unsigned int flags, struct file **ret) ++{ ++ int pidfd; ++ struct file *pidfd_file; ++ ++ if (flags & ~(O_NONBLOCK | O_RDWR | O_CLOEXEC)) ++ return -EINVAL; ++ ++ pidfd = get_unused_fd_flags(O_RDWR | O_CLOEXEC); ++ if (pidfd < 0) ++ return pidfd; ++ ++ pidfd_file = anon_inode_getfile("[pidfd]", &pidfd_fops, pid, ++ flags | O_RDWR | O_CLOEXEC); ++ if (IS_ERR(pidfd_file)) { ++ put_unused_fd(pidfd); ++ return PTR_ERR(pidfd_file); ++ } ++ get_pid(pid); /* held by pidfd_file now */ ++ *ret = pidfd_file; ++ return pidfd; ++} ++ ++/** ++ * pidfd_prepare - allocate a new pidfd_file and reserve a pidfd ++ * @pid: the struct pid for which to create a pidfd ++ * @flags: flags of the new @pidfd ++ * @pidfd: the pidfd to return ++ * ++ * Allocate a new file that stashes @pid and reserve a new pidfd number in the ++ * caller's file descriptor table. The pidfd is reserved but not installed yet. ++ * ++ * The helper verifies that @pid is used as a thread group leader. ++ * ++ * If this function returns successfully the caller is responsible to either ++ * call fd_install() passing the returned pidfd and pidfd file as arguments in ++ * order to install the pidfd into its file descriptor table or they must use ++ * put_unused_fd() and fput() on the returned pidfd and pidfd file ++ * respectively. ++ * ++ * This function is useful when a pidfd must already be reserved but there ++ * might still be points of failure afterwards and the caller wants to ensure ++ * that no pidfd is leaked into its file descriptor table. ++ * ++ * Return: On success, a reserved pidfd is returned from the function and a new ++ * pidfd file is returned in the last argument to the function. On ++ * error, a negative error code is returned from the function and the ++ * last argument remains unchanged. ++ */ ++int pidfd_prepare(struct pid *pid, unsigned int flags, struct file **ret) ++{ ++ if (!pid || !pid_has_task(pid, PIDTYPE_TGID)) ++ return -EINVAL; ++ ++ return __pidfd_prepare(pid, flags, ret); ++} ++ + static void __delayed_free_task(struct rcu_head *rhp) + { + struct task_struct *tsk = container_of(rhp, struct task_struct, rcu); +--- a/kernel/pid.c ++++ b/kernel/pid.c +@@ -594,20 +594,15 @@ struct task_struct *pidfd_get_task(int p + */ + int pidfd_create(struct pid *pid, unsigned int flags) + { +- int fd; ++ int pidfd; ++ struct file *pidfd_file; + +- if (!pid || !pid_has_task(pid, PIDTYPE_TGID)) +- return -EINVAL; ++ pidfd = pidfd_prepare(pid, flags, &pidfd_file); ++ if (pidfd < 0) ++ return pidfd; + +- if (flags & ~(O_NONBLOCK | O_RDWR | O_CLOEXEC)) +- return -EINVAL; +- +- fd = anon_inode_getfd("[pidfd]", &pidfd_fops, get_pid(pid), +- flags | O_RDWR | O_CLOEXEC); +- if (fd < 0) +- put_pid(pid); +- +- return fd; ++ fd_install(pidfd, pidfd_file); ++ return pidfd; + } + + /** diff --git a/queue-6.1/series b/queue-6.1/series index 3ac71630a9..11ca4ef9c5 100644 --- a/queue-6.1/series +++ b/queue-6.1/series @@ -309,3 +309,7 @@ arm64-dts-qcom-sm8350-fix-typo-in-pil_camera_mem-node.patch net_sched-hfsc-address-reentrant-enqueue-adding-class-to-eltree-twice.patch perf-arm-cmn-fix-req2-snp2-mixup.patch perf-arm-cmn-initialise-cmn-cpu-earlier.patch +coredump-fix-error-handling-for-replace_fd.patch +pid-add-pidfd_prepare.patch +fork-use-pidfd_prepare.patch +coredump-hand-a-pidfd-to-the-usermode-coredump-helper.patch