aboutsummaryrefslogtreecommitdiff
path: root/fs/pidfs.c
diff options
context:
space:
mode:
authorChristian Brauner <brauner@kernel.org>2025-10-28 09:45:53 +0100
committerChristian Brauner <brauner@kernel.org>2025-10-30 14:25:14 +0100
commit036375522be8425874e9e0f907c7127e315c7a52 (patch)
tree8718dcbc3446d6d6d360b15480c6c6ee136fe07c /fs/pidfs.c
parent90df6ff6853b5fc71c70cc8eebf1e49e29631ca2 (diff)
pidfs: expose coredump signal
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>
Diffstat (limited to 'fs/pidfs.c')
-rw-r--r--fs/pidfs.c30
1 files changed, 19 insertions, 11 deletions
diff --git a/fs/pidfs.c b/fs/pidfs.c
index a3b80be3b98b..354ceb2126e7 100644
--- a/fs/pidfs.c
+++ b/fs/pidfs.c
@@ -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