diff options
| author | Christian Brauner <brauner@kernel.org> | 2025-05-16 13:25:32 +0200 |
|---|---|---|
| committer | Christian Brauner <brauner@kernel.org> | 2025-05-21 13:59:12 +0200 |
| commit | 1d8db6fd698de1f73b1a7d72aea578fdd18d9a87 (patch) | |
| tree | 8f8b4cfe32dbf117e61637df569ca3df7d737bf3 /fs/coredump.c | |
| parent | a9194f88782afa1386641451a6c76beaa60485a0 (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.c | 31 |
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 |
