pidfs: record the coredump on the dumping thread's pid too

If a thread-group coredumps only the thread-group leader pidfd will
return coredump information. A pidfd for the thread that took the fatal
signal cannot be used to retrieve it.

Record both the thread-group leader and the specific thread that took
the signal and register both in pidfs. Mark both the thread-group leader
and the specific thread with the coredump information so retrieval works
for both pidfds.

Now that both SO_PEERPIDFD and SO_PEERPIDFD_THREAD are available it's
easy to get the coredump information for the specific thread.

Reviewed-by: Alexander Mikhalitsyn <aleksandr.mikhalitsyn@futurfusion.io>
Signed-off-by: Andrew Halaney <andrew@amutable.com>
Link: https://patch.msgid.link/20261005-work-unix-passpidfd-v4-9-350183b6e02a@amutable.com
Signed-off-by: Christian Brauner (Amutable) <brauner@kernel.org>
This commit is contained in:
Christian Brauner 2026-10-05 10:09:39 -05:00
parent 02e658dffe
commit 3209535cd3
No known key found for this signature in database
GPG Key ID: 91C61BC06578DCA2
3 changed files with 25 additions and 12 deletions

View File

@ -454,7 +454,7 @@ static bool coredump_parse(struct core_name *cn, struct coredump_params *cprm,
* leader we know that the thread-group leader
* cannot be reaped until @current has exited.
*/
cprm->pid = task_tgid(current);
task_pids(cprm->pid, current);
err = cn_printf(cn, "%d", COREDUMP_PIDFD_NUMBER);
break;
}
@ -626,13 +626,17 @@ static int umh_coredump_setup(struct subprocess_info *info, struct cred *new)
struct coredump_params *cp = (struct coredump_params *)info->data;
int err;
if (cp->pid) {
if (cp->pid[PIDTYPE_TGID]) {
struct file *pidfs_file __free(fput) = NULL;
pidfs_file = pidfs_alloc_file(cp->pid, 0);
pidfs_file = pidfs_alloc_file(cp->pid[PIDTYPE_TGID], 0);
if (IS_ERR(pidfs_file))
return PTR_ERR(pidfs_file);
err = pidfs_register_pids(cp->pid);
if (err)
return err;
pidfs_coredump(cp);
/*
@ -695,12 +699,12 @@ static bool coredump_sock_connect(struct core_name *cn, struct coredump_params *
return false;
/*
* Set the thread-group leader pid which is used for the peer
* credentials during connect() below. Then immediately register
* it in pidfs...
* Set the pids of the dumping thread and its thread-group leader
* which are used for the peer credentials during connect() below.
* Then immediately register them in pidfs...
*/
cprm->pid = task_tgid(current);
retval = pidfs_register_pid(cprm->pid);
task_pids(cprm->pid, current);
retval = pidfs_register_pids(cprm->pid);
if (retval)
return false;
@ -722,7 +726,7 @@ static bool coredump_sock_connect(struct core_name *cn, struct coredump_params *
}
/* ... and validate that @sk_peer_pid matches @cprm.pid. */
if (WARN_ON_ONCE(unix_peer(socket->sk)->sk_peer_pid[PIDTYPE_TGID] != cprm->pid))
if (WARN_ON_ONCE(!pids_equal(unix_peer(socket->sk)->sk_peer_pid, cprm->pid)))
return false;
cprm->limit = RLIM_INFINITY;

View File

@ -793,9 +793,9 @@ void pidfs_exit(struct task_struct *tsk)
}
#ifdef CONFIG_COREDUMP
void pidfs_coredump(const struct coredump_params *cprm)
static void pidfs_coredump_pid(struct pid *pid,
const struct coredump_params *cprm)
{
struct pid *pid = cprm->pid;
struct pidfs_attr *attr;
attr = READ_ONCE(pid->attr);
@ -814,6 +814,13 @@ void pidfs_coredump(const struct coredump_params *cprm)
smp_wmb();
set_bit(PIDFS_ATTR_BIT_COREDUMP, &attr->attr_mask);
}
void pidfs_coredump(const struct coredump_params *cprm)
{
/* The dumping thread's pidfd reports the coredump as well. */
for (enum pid_type type = PIDTYPE_PID; type <= pids_last(cprm->pid); type++)
pidfs_coredump_pid(cprm->pid[type], cprm);
}
#endif
static struct vfsmount *pidfs_mnt __ro_after_init;

View File

@ -5,6 +5,7 @@
#include <linux/types.h>
#include <linux/mm.h>
#include <linux/fs.h>
#include <linux/pid_types.h>
#include <linux/sched/coredump.h>
#include <asm/siginfo.h>
@ -32,7 +33,8 @@ struct coredump_params {
int vma_count;
size_t vma_data_size;
struct core_vma_metadata *vma_meta;
struct pid *pid;
/* Dumping thread and its thread-group leader by pid type. */
DECLARE_PIDS(pid, PIDTYPE_TGID);
};
extern unsigned int core_file_note_size_limit;