summaryrefslogtreecommitdiff
path: root/fs/coredump.c
diff options
context:
space:
mode:
authorChristian Brauner <brauner@kernel.org>2025-05-16 13:25:32 +0200
committerChristian Brauner <brauner@kernel.org>2025-05-21 13:59:12 +0200
commit1d8db6fd698de1f73b1a7d72aea578fdd18d9a87 (patch)
tree8f8b4cfe32dbf117e61637df569ca3df7d737bf3 /fs/coredump.c
parenta9194f88782afa1386641451a6c76beaa60485a0 (diff)
pidfs, coredump: add PIDFD_INFO_COREDUMP
Extend the PIDFD_INFO_COREDUMP ioctl() with the new PIDFD_INFO_COREDUMP mask flag. This adds the @coredump_mask field to struct pidfd_info. When a task coredumps the kernel will provide the following information to userspace in @coredump_mask: * PIDFD_COREDUMPED is raised if the task did actually coredump. * PIDFD_COREDUMP_SKIP is raised if the task skipped coredumping (e.g., undumpable). * PIDFD_COREDUMP_USER is raised if this is a regular coredump and doesn't need special care by the coredump server. * PIDFD_COREDUMP_ROOT is raised if the generated coredump should be treated as sensitive and the coredump server should restrict to the generated coredump to sufficiently privileged users. The kernel guarantees that by the time the connection is made the all PIDFD_INFO_COREDUMP info is available. Link: https://lore.kernel.org/20250516-work-coredump-socket-v8-5-664f3caf2516@kernel.org Acked-by: Luca Boccassi <luca.boccassi@gmail.com> Reviewed-by: Alexander Mikhalitsyn <aleksandr.mikhalitsyn@canonical.com> Reviewed-by: Jann Horn <jannh@google.com> Signed-off-by: Christian Brauner <brauner@kernel.org>
Diffstat (limited to 'fs/coredump.c')
-rw-r--r--fs/coredump.c31
1 files changed, 31 insertions, 0 deletions
diff --git a/fs/coredump.c b/fs/coredump.c
index af4aa57353ba..b0ee99992ea5 100644
--- a/fs/coredump.c
+++ b/fs/coredump.c
@@ -46,7 +46,9 @@
#include <linux/pidfs.h>
#include <linux/net.h>
#include <linux/socket.h>
+#include <net/af_unix.h>
#include <net/net_namespace.h>
+#include <net/sock.h>
#include <uapi/linux/pidfd.h>
#include <uapi/linux/un.h>
@@ -599,6 +601,8 @@ static int umh_coredump_setup(struct subprocess_info *info, struct cred *new)
if (IS_ERR(pidfs_file))
return PTR_ERR(pidfs_file);
+ pidfs_coredump(cp);
+
/*
* Usermode helpers are childen of either
* system_unbound_wq or of kthreadd. So we know that
@@ -875,8 +879,31 @@ void do_coredump(const kernel_siginfo_t *siginfo)
if (IS_ERR(file))
goto close_fail;
+ /*
+ * Set the thread-group leader pid which is used for the
+ * peer credentials during connect() below. Then
+ * immediately register it in pidfs...
+ */
+ cprm.pid = task_tgid(current);
+ retval = pidfs_register_pid(cprm.pid);
+ if (retval)
+ goto close_fail;
+
+ /*
+ * ... and set the coredump information so userspace
+ * has it available after connect()...
+ */
+ pidfs_coredump(&cprm);
+
retval = kernel_connect(socket, (struct sockaddr *)(&addr),
addr_len, O_NONBLOCK | SOCK_COREDUMP);
+
+ /*
+ * ... Make sure to only put our reference after connect() took
+ * its own reference keeping the pidfs entry alive ...
+ */
+ pidfs_put_pid(cprm.pid);
+
if (retval) {
if (retval == -EAGAIN)
coredump_report_failure("Coredump socket %s receive queue full", addr.sun_path);
@@ -885,6 +912,10 @@ void do_coredump(const kernel_siginfo_t *siginfo)
goto close_fail;
}
+ /* ... and validate that @sk_peer_pid matches @cprm.pid. */
+ if (WARN_ON_ONCE(unix_peer(socket->sk)->sk_peer_pid != cprm.pid))
+ goto close_fail;
+
cprm.limit = RLIM_INFINITY;
cprm.file = no_free_ptr(file);
#else