]> git.ipfire.org Git - thirdparty/kernel/linux.git/commitdiff
pidfs: expose coredump signal
authorChristian Brauner <brauner@kernel.org>
Tue, 28 Oct 2025 08:45:53 +0000 (09:45 +0100)
committerChristian Brauner <brauner@kernel.org>
Thu, 30 Oct 2025 13:25:14 +0000 (14:25 +0100)
Userspace needs access to the signal that caused the coredump before the
coredumping process has been reaped. Expose it as part of the coredump
information in struct pidfd_info. After the process has been reaped that
info is also available as part of PIDFD_INFO_EXIT's exit_code field.

Link: https://patch.msgid.link/20251028-work-coredump-signal-v1-8-ca449b7b7aa0@kernel.org
Reviewed-by: Alexander Mikhalitsyn <aleksandr.mikhalitsyn@canonical.com>
Reviewed-by: Oleg Nesterov <oleg@redhat.com>
Signed-off-by: Christian Brauner <brauner@kernel.org>
fs/pidfs.c
include/uapi/linux/pidfd.h

index a3b80be3b98ba9dd2e0692cf4e97d28c839d77a3..354ceb2126e7c358b2b2721965b0bd8c26b58e2f 100644 (file)
@@ -41,6 +41,7 @@ void pidfs_get_root(struct path *path)
 
 enum pidfs_attr_mask_bits {
        PIDFS_ATTR_BIT_EXIT     = 0,
+       PIDFS_ATTR_BIT_COREDUMP = 1,
 };
 
 struct pidfs_attr {
@@ -51,6 +52,7 @@ struct pidfs_attr {
                __s32 exit_code;
        };
        __u32 coredump_mask;
+       __u32 coredump_signal;
 };
 
 static struct rb_root pidfs_ino_tree = RB_ROOT;
@@ -297,7 +299,8 @@ static __u32 pidfs_coredump_mask(unsigned long mm_flags)
                              PIDFD_INFO_CGROUPID | \
                              PIDFD_INFO_EXIT | \
                              PIDFD_INFO_COREDUMP | \
-                             PIDFD_INFO_SUPPORTED_MASK)
+                             PIDFD_INFO_SUPPORTED_MASK | \
+                             PIDFD_INFO_COREDUMP_SIGNAL)
 
 static long pidfd_info(struct file *file, unsigned int cmd, unsigned long arg)
 {
@@ -342,9 +345,12 @@ static long pidfd_info(struct file *file, unsigned int cmd, unsigned long arg)
        }
 
        if (mask & PIDFD_INFO_COREDUMP) {
-               kinfo.coredump_mask = READ_ONCE(attr->coredump_mask);
-               if (kinfo.coredump_mask)
-                       kinfo.mask |= PIDFD_INFO_COREDUMP;
+               if (test_bit(PIDFS_ATTR_BIT_COREDUMP, &attr->attr_mask)) {
+                       smp_rmb();
+                       kinfo.mask |= PIDFD_INFO_COREDUMP | PIDFD_INFO_COREDUMP_SIGNAL;
+                       kinfo.coredump_mask = attr->coredump_mask;
+                       kinfo.coredump_signal = attr->coredump_signal;
+               }
        }
 
        task = get_pid_task(pid, PIDTYPE_PID);
@@ -370,6 +376,7 @@ static long pidfd_info(struct file *file, unsigned int cmd, unsigned long arg)
 
                        kinfo.coredump_mask = pidfs_coredump_mask(flags);
                        kinfo.mask |= PIDFD_INFO_COREDUMP;
+                       /* No coredump actually took place, so no coredump signal. */
                }
        }
 
@@ -666,20 +673,21 @@ void pidfs_coredump(const struct coredump_params *cprm)
 {
        struct pid *pid = cprm->pid;
        struct pidfs_attr *attr;
-       __u32 coredump_mask = 0;
 
        attr = READ_ONCE(pid->attr);
 
        VFS_WARN_ON_ONCE(!attr);
        VFS_WARN_ON_ONCE(attr == PIDFS_PID_DEAD);
 
-       /* Note how we were coredumped. */
-       coredump_mask = pidfs_coredump_mask(cprm->mm_flags);
-       /* Note that we actually did coredump. */
-       coredump_mask |= PIDFD_COREDUMPED;
+       /* Note how we were coredumped and that we coredumped. */
+       attr->coredump_mask = pidfs_coredump_mask(cprm->mm_flags) |
+                             PIDFD_COREDUMPED;
        /* If coredumping is set to skip we should never end up here. */
-       VFS_WARN_ON_ONCE(coredump_mask & PIDFD_COREDUMP_SKIP);
-       smp_store_release(&attr->coredump_mask, coredump_mask);
+       VFS_WARN_ON_ONCE(attr->coredump_mask & PIDFD_COREDUMP_SKIP);
+       /* Expose the signal number that caused the coredump. */
+       attr->coredump_signal = cprm->siginfo->si_signo;
+       smp_wmb();
+       set_bit(PIDFS_ATTR_BIT_COREDUMP, &attr->attr_mask);
 }
 #endif
 
index e05caa0e00fe9b0b930666c47e137ae828f2db32..ea9a6811fc768d2b1b2f5137b37ea82d5dd62c42 100644 (file)
@@ -27,6 +27,7 @@
 #define PIDFD_INFO_EXIT                        (1UL << 3) /* Only returned if requested. */
 #define PIDFD_INFO_COREDUMP            (1UL << 4) /* Only returned if requested. */
 #define PIDFD_INFO_SUPPORTED_MASK      (1UL << 5) /* Want/got supported mask flags */
+#define PIDFD_INFO_COREDUMP_SIGNAL     (1UL << 6) /* Always returned if PIDFD_INFO_COREDUMP is requested. */
 
 #define PIDFD_INFO_SIZE_VER0           64 /* sizeof first published struct */
 #define PIDFD_INFO_SIZE_VER1           72 /* sizeof second published struct */
@@ -94,8 +95,10 @@ struct pidfd_info {
        __u32 fsuid;
        __u32 fsgid;
        __s32 exit_code;
-       __u32 coredump_mask;
-       __u32 __spare1;
+       struct /* coredump info */ {
+               __u32 coredump_mask;
+               __u32 coredump_signal;
+       };
        __u64 supported_mask;   /* Mask flags that this kernel supports */
 };