]> git.ipfire.org Git - thirdparty/kernel/stable.git/commitdiff
coredump: split pipe coredumping into coredump_pipe()
authorChristian Brauner <brauner@kernel.org>
Thu, 12 Jun 2025 13:25:27 +0000 (15:25 +0200)
committerChristian Brauner <brauner@kernel.org>
Mon, 7 Jul 2025 10:24:49 +0000 (12:24 +0200)
* Move that whole mess into a separate helper instead of having all that
  hanging around in vfs_coredump() directly. Cleanup paths are already
  centralized.

Link: https://lore.kernel.org/20250612-work-coredump-massage-v1-13-315c0c34ba94@kernel.org
Signed-off-by: Christian Brauner <brauner@kernel.org>
fs/coredump.c

index c863e053b1f8ad515e285b5768aa88878a2b057d..f4f7f0a0ae40252a1efdac3f17703d71eebbbe0f 100644 (file)
@@ -970,6 +970,63 @@ static bool coredump_file(struct core_name *cn, struct coredump_params *cprm,
        return true;
 }
 
+static bool coredump_pipe(struct core_name *cn, struct coredump_params *cprm,
+                         size_t *argv, int argc)
+{
+       int argi;
+       char **helper_argv __free(kfree) = NULL;
+       struct subprocess_info *sub_info;
+
+       if (cprm->limit == 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
+                * cprm.limit of 1 here as a special value, this is a
+                * consistent way to catch recursive crashes.
+                * We can still crash if the core_pattern binary sets
+                * RLIM_CORE = !1, but it runs as root, and can do
+                * lots of stupid things.
+                *
+                * Note that we use task_tgid_vnr here to grab the pid
+                * of the process group leader.  That way we get the
+                * right pid if a thread in a multi-threaded
+                * core_pattern process dies.
+                */
+               coredump_report_failure("RLIMIT_CORE is set to 1, aborting core");
+               return false;
+       }
+       cprm->limit = RLIM_INFINITY;
+
+       cn->core_pipe_limit = atomic_inc_return(&core_pipe_count);
+       if (core_pipe_limit && (core_pipe_limit < cn->core_pipe_limit)) {
+               coredump_report_failure("over core_pipe_limit, skipping core dump");
+               return false;
+       }
+
+       helper_argv = kmalloc_array(argc + 1, sizeof(*helper_argv), GFP_KERNEL);
+       if (!helper_argv) {
+               coredump_report_failure("%s failed to allocate memory", __func__);
+               return false;
+       }
+       for (argi = 0; argi < argc; argi++)
+               helper_argv[argi] = cn->corename + argv[argi];
+       helper_argv[argi] = NULL;
+
+       sub_info = call_usermodehelper_setup(helper_argv[0], helper_argv, NULL,
+                                            GFP_KERNEL, umh_coredump_setup,
+                                            NULL, cprm);
+       if (!sub_info)
+               return false;
+
+       if (call_usermodehelper_exec(sub_info, UMH_WAIT_EXEC)) {
+               coredump_report_failure("|%s pipe failed", cn->corename);
+               return false;
+       }
+
+       return true;
+}
+
 void vfs_coredump(const kernel_siginfo_t *siginfo)
 {
        struct core_state core_state;
@@ -1031,63 +1088,10 @@ void vfs_coredump(const kernel_siginfo_t *siginfo)
                if (!coredump_file(&cn, &cprm, binfmt))
                        goto close_fail;
                break;
-       case COREDUMP_PIPE: {
-               int argi;
-               char **helper_argv;
-               struct subprocess_info *sub_info;
-
-               if (cprm.limit == 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
-                        * cprm.limit of 1 here as a special value, this is a
-                        * consistent way to catch recursive crashes.
-                        * We can still crash if the core_pattern binary sets
-                        * RLIM_CORE = !1, but it runs as root, and can do
-                        * lots of stupid things.
-                        *
-                        * Note that we use task_tgid_vnr here to grab the pid
-                        * of the process group leader.  That way we get the
-                        * right pid if a thread in a multi-threaded
-                        * core_pattern process dies.
-                        */
-                       coredump_report_failure("RLIMIT_CORE is set to 1, aborting core");
-                       goto close_fail;
-               }
-               cprm.limit = RLIM_INFINITY;
-
-               cn.core_pipe_limit = atomic_inc_return(&core_pipe_count);
-               if (core_pipe_limit && (core_pipe_limit < cn.core_pipe_limit)) {
-                       coredump_report_failure("over core_pipe_limit, skipping core dump");
+       case COREDUMP_PIPE:
+               if (!coredump_pipe(&cn, &cprm, argv, argc))
                        goto close_fail;
-               }
-
-               helper_argv = kmalloc_array(argc + 1, sizeof(*helper_argv),
-                                           GFP_KERNEL);
-               if (!helper_argv) {
-                       coredump_report_failure("%s failed to allocate memory", __func__);
-                       goto close_fail;
-               }
-               for (argi = 0; argi < argc; argi++)
-                       helper_argv[argi] = cn.corename + argv[argi];
-               helper_argv[argi] = NULL;
-
-               retval = -ENOMEM;
-               sub_info = call_usermodehelper_setup(helper_argv[0],
-                                               helper_argv, NULL, GFP_KERNEL,
-                                               umh_coredump_setup, NULL, &cprm);
-               if (sub_info)
-                       retval = call_usermodehelper_exec(sub_info,
-                                                         UMH_WAIT_EXEC);
-
-               kfree(helper_argv);
-               if (retval) {
-                       coredump_report_failure("|%s pipe failed", cn.corename);
-                       goto close_fail;
-               }
                break;
-       }
        case COREDUMP_SOCK_REQ:
                fallthrough;
        case COREDUMP_SOCK: