Skip to content

Commit 10f3280

Browse files
author
CKI KWF Bot
committed
Merge: Backport pidfd/pidfs commits to enabling passing pidfd to coredump usermode helper
MR: https://gitlab.com/redhat/centos-stream/src/kernel/centos-stream-9/-/merge_requests/7270 JIRA: https://issues.redhat.com/browse/RHEL-107520 CVE: CVE-2024-46801 CVE: CVE-2025-38306 MR: https://gitlab.com/redhat/centos-stream/src/kernel/centos-stream-9/-/merge_requests/7270 Omitted-fix: fed307b ("kthread: update comment for __to_kthread") Omitted-fix: bb58559 ("fhandle: use more consistent rules for decoding file handle from userns") The goal of this MR is to backport enough upstream pidfd/pidfs related commits to enable systemd to pass pidfd to coredump usermode helper for fixing CVE-2025-4598. Note that the last netfilter selftest patch was added to fix a false positive CKI netfilter selftest failure. Signed-off-by: Waiman Long <longman@redhat.com> Approved-by: Rafael Aquini <raquini@redhat.com> Approved-by: Phil Auld <pauld@redhat.com> Approved-by: Guillaume Nault <gnault@redhat.com> Approved-by: CKI KWF Bot <cki-ci-bot+kwf-gitlab-com@redhat.com> Merged-by: CKI GitLab Kmaint Pipeline Bot <26919896-cki-kmaint-pipeline-bot@users.noreply.gitlab.com>
2 parents 2b0ec56 + 9ab3676 commit 10f3280

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

68 files changed

+2291
-560
lines changed

Documentation/admin-guide/sysctl/kernel.rst

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -169,6 +169,8 @@ core_pattern
169169
%f executable filename
170170
%E executable path
171171
%c maximum size of core file by resource limit RLIMIT_CORE
172+
%C CPU the task ran on
173+
%F pidfd number
172174
%<OTHER> both are dropped
173175
======== ==========================================
174176

drivers/dma-buf/dma-buf.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -77,7 +77,7 @@ static char *dmabuffs_dname(struct dentry *dentry, char *buffer, int buflen)
7777
ret = strscpy(name, dmabuf->name, sizeof(name));
7878
spin_unlock(&dmabuf->name_lock);
7979

80-
return dynamic_dname(dentry, buffer, buflen, "/%s:%s",
80+
return dynamic_dname(buffer, buflen, "/%s:%s",
8181
dentry->d_name.name, ret > 0 ? name : "");
8282
}
8383

fs/Makefile

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,7 @@ obj-y := open.o read_write.o file_table.o super.o \
1616
pnode.o splice.o sync.o utimes.o d_path.o \
1717
stack.o fs_struct.o statfs.o fs_pin.o nsfs.o \
1818
fs_types.o fs_context.o fs_parser.o fsopen.o init.o \
19-
kernel_read_file.o mnt_idmapping.o remap_range.o
19+
kernel_read_file.o mnt_idmapping.o remap_range.o pidfs.o
2020

2121
obj-$(CONFIG_BUFFER_HEAD) += buffer.o mpage.o
2222
obj-$(CONFIG_PROC_FS) += proc_namespace.o

fs/anon_inodes.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -32,7 +32,7 @@ static struct inode *anon_inode_inode;
3232
*/
3333
static char *anon_inodefs_dname(struct dentry *dentry, char *buffer, int buflen)
3434
{
35-
return dynamic_dname(dentry, buffer, buflen, "anon_inode:%s",
35+
return dynamic_dname(buffer, buflen, "anon_inode:%s",
3636
dentry->d_name.name);
3737
}
3838

fs/attr.c

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -308,9 +308,9 @@ void setattr_copy(struct mnt_idmap *idmap, struct inode *inode,
308308
i_uid_update(idmap, attr, inode);
309309
i_gid_update(idmap, attr, inode);
310310
if (ia_valid & ATTR_ATIME)
311-
inode->i_atime = attr->ia_atime;
311+
inode_set_atime_to_ts(inode, attr->ia_atime);
312312
if (ia_valid & ATTR_MTIME)
313-
inode->i_mtime = attr->ia_mtime;
313+
inode_set_mtime_to_ts(inode, attr->ia_mtime);
314314
if (ia_valid & ATTR_CTIME)
315315
inode_set_ctime_to_ts(inode, attr->ia_ctime);
316316
if (ia_valid & ATTR_MODE) {

fs/bad_inode.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -209,7 +209,7 @@ void make_bad_inode(struct inode *inode)
209209
remove_inode_hash(inode);
210210

211211
inode->i_mode = S_IFREG;
212-
inode->i_atime = inode->i_mtime = inode_set_ctime_current(inode);
212+
simple_inode_init_ts(inode);
213213
inode->i_op = &bad_inode_ops;
214214
inode->i_opflags &= ~IOP_XATTR;
215215
inode->i_fop = &bad_file_ops;

fs/binfmt_misc.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -547,7 +547,7 @@ static struct inode *bm_get_inode(struct super_block *sb, int mode)
547547
if (inode) {
548548
inode->i_ino = get_next_ino();
549549
inode->i_mode = mode;
550-
inode->i_atime = inode->i_mtime = inode_set_ctime_current(inode);
550+
simple_inode_init_ts(inode);
551551
}
552552
return inode;
553553
}

fs/configfs/dir.c

Lines changed: 2 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1624,12 +1624,6 @@ static int configfs_dir_close(struct inode *inode, struct file *file)
16241624
return 0;
16251625
}
16261626

1627-
/* Relationship between s_mode and the DT_xxx types */
1628-
static inline unsigned char dt_type(struct configfs_dirent *sd)
1629-
{
1630-
return (sd->s_mode >> 12) & 15;
1631-
}
1632-
16331627
static int configfs_readdir(struct file *file, struct dir_context *ctx)
16341628
{
16351629
struct dentry *dentry = file->f_path.dentry;
@@ -1679,7 +1673,8 @@ static int configfs_readdir(struct file *file, struct dir_context *ctx)
16791673
name = configfs_get_name(next);
16801674
len = strlen(name);
16811675

1682-
if (!dir_emit(ctx, name, len, ino, dt_type(next)))
1676+
if (!dir_emit(ctx, name, len, ino,
1677+
fs_umode_to_dtype(next->s_mode)))
16831678
return 0;
16841679

16851680
spin_lock(&configfs_dirent_lock);

fs/coredump.c

Lines changed: 65 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -43,6 +43,8 @@
4343
#include <linux/timekeeping.h>
4444
#include <linux/sysctl.h>
4545
#include <linux/elf.h>
46+
#include <linux/pidfs.h>
47+
#include <uapi/linux/pidfd.h>
4648

4749
#include <linux/uaccess.h>
4850
#include <asm/mmu_context.h>
@@ -56,6 +58,12 @@
5658

5759
static bool dump_vma_snapshot(struct coredump_params *cprm);
5860
static void free_vma_snapshot(struct coredump_params *cprm);
61+
/*
62+
* File descriptor number for the pidfd for the thread-group leader of
63+
* the coredumping task installed into the usermode helper's file
64+
* descriptor table.
65+
*/
66+
#define COREDUMP_PIDFD_NUMBER 3
5967

6068
static int core_uses_pid;
6169
static unsigned int core_pipe_limit;
@@ -329,6 +337,31 @@ static int format_corename(struct core_name *cn, struct coredump_params *cprm,
329337
err = cn_printf(cn, "%lu",
330338
rlimit(RLIMIT_CORE));
331339
break;
340+
/* CPU the task ran on */
341+
case 'C':
342+
err = cn_printf(cn, "%d", cprm->cpu);
343+
break;
344+
/* pidfd number */
345+
case 'F': {
346+
/*
347+
* Installing a pidfd only makes sense if
348+
* we actually spawn a usermode helper.
349+
*/
350+
if (!ispipe)
351+
break;
352+
353+
/*
354+
* Note that we'll install a pidfd for the
355+
* thread-group leader. We know that task
356+
* linkage hasn't been removed yet and even if
357+
* this @current isn't the actual thread-group
358+
* leader we know that the thread-group leader
359+
* cannot be reaped until @current has exited.
360+
*/
361+
cprm->pid = task_tgid(current);
362+
err = cn_printf(cn, "%d", COREDUMP_PIDFD_NUMBER);
363+
break;
364+
}
332365
default:
333366
break;
334367
}
@@ -358,7 +391,7 @@ static int zap_process(struct task_struct *start, int exit_code)
358391
struct task_struct *t;
359392
int nr = 0;
360393

361-
/* ignore all signals except SIGKILL, see prepare_signal() */
394+
/* Allow SIGKILL, see prepare_signal() */
362395
start->signal->flags = SIGNAL_GROUP_EXIT;
363396
start->signal->group_exit_code = exit_code;
364397
start->signal->group_stop_count = 0;
@@ -483,7 +516,7 @@ static void wait_for_dump_helpers(struct file *file)
483516
}
484517

485518
/*
486-
* umh_pipe_setup
519+
* umh_coredump_setup
487520
* helper function to customize the process used
488521
* to collect the core in userspace. Specifically
489522
* it sets up a pipe and installs it as fd 0 (stdin)
@@ -493,22 +526,46 @@ static void wait_for_dump_helpers(struct file *file)
493526
* is a special value that we use to trap recursive
494527
* core dumps
495528
*/
496-
static int umh_pipe_setup(struct subprocess_info *info, struct cred *new)
529+
static int umh_coredump_setup(struct subprocess_info *info, struct cred *new)
497530
{
498531
struct file *files[2];
499532
struct coredump_params *cp = (struct coredump_params *)info->data;
500-
int err = create_pipe_files(files, 0);
533+
int err;
534+
535+
if (cp->pid) {
536+
struct file *pidfs_file __free(fput) = NULL;
537+
538+
pidfs_file = pidfs_alloc_file(cp->pid, 0);
539+
if (IS_ERR(pidfs_file))
540+
return PTR_ERR(pidfs_file);
541+
542+
/*
543+
* Usermode helpers are childen of either
544+
* system_unbound_wq or of kthreadd. So we know that
545+
* we're starting off with a clean file descriptor
546+
* table. So we should always be able to use
547+
* COREDUMP_PIDFD_NUMBER as our file descriptor value.
548+
*/
549+
err = replace_fd(COREDUMP_PIDFD_NUMBER, pidfs_file, 0);
550+
if (err < 0)
551+
return err;
552+
}
553+
554+
err = create_pipe_files(files, 0);
501555
if (err)
502556
return err;
503557

504558
cp->file = files[1];
505559

506560
err = replace_fd(0, files[0], 0);
507561
fput(files[0]);
562+
if (err < 0)
563+
return err;
564+
508565
/* and disallow core files too */
509566
current->signal->rlim[RLIMIT_CORE] = (struct rlimit){1, 1};
510567

511-
return err;
568+
return 0;
512569
}
513570

514571
void do_coredump(const kernel_siginfo_t *siginfo)
@@ -538,6 +595,7 @@ void do_coredump(const kernel_siginfo_t *siginfo)
538595
*/
539596
.mm_flags = mm->flags,
540597
.vma_meta = NULL,
598+
.cpu = raw_smp_processor_id(),
541599
};
542600

543601
audit_core_dumps(siginfo->si_signo);
@@ -584,7 +642,7 @@ void do_coredump(const kernel_siginfo_t *siginfo)
584642
}
585643

586644
if (cprm.limit == 1) {
587-
/* See umh_pipe_setup() which sets RLIMIT_CORE = 1.
645+
/* See umh_coredump_setup() which sets RLIMIT_CORE = 1.
588646
*
589647
* Normally core limits are irrelevant to pipes, since
590648
* we're not writing to the file system, but we use
@@ -629,7 +687,7 @@ void do_coredump(const kernel_siginfo_t *siginfo)
629687
retval = -ENOMEM;
630688
sub_info = call_usermodehelper_setup(helper_argv[0],
631689
helper_argv, NULL, GFP_KERNEL,
632-
umh_pipe_setup, NULL, &cprm);
690+
umh_coredump_setup, NULL, &cprm);
633691
if (sub_info)
634692
retval = call_usermodehelper_exec(sub_info,
635693
UMH_WAIT_EXEC);

fs/d_path.c

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -266,8 +266,7 @@ EXPORT_SYMBOL(d_path);
266266
/*
267267
* Helper function for dentry_operations.d_dname() members
268268
*/
269-
char *dynamic_dname(struct dentry *dentry, char *buffer, int buflen,
270-
const char *fmt, ...)
269+
char *dynamic_dname(char *buffer, int buflen, const char *fmt, ...)
271270
{
272271
va_list args;
273272
char temp[64];

0 commit comments

Comments
 (0)