@@ -39,20 +39,20 @@ void pidfs_get_root(struct path *path)
3939 path_get (path );
4040}
4141
42- /*
43- * Stashes information that userspace needs to access even after the
44- * process has been reaped.
45- */
46- struct pidfs_exit_info {
47- __u64 cgroupid ;
48- __s32 exit_code ;
49- __u32 coredump_mask ;
42+ enum pidfs_attr_mask_bits {
43+ PIDFS_ATTR_BIT_EXIT = 0 ,
44+ PIDFS_ATTR_BIT_COREDUMP = 1 ,
5045};
5146
5247struct pidfs_attr {
48+ unsigned long attr_mask ;
5349 struct simple_xattrs * xattrs ;
54- struct pidfs_exit_info __pei ;
55- struct pidfs_exit_info * exit_info ;
50+ struct /* exit info */ {
51+ __u64 cgroupid ;
52+ __s32 exit_code ;
53+ };
54+ __u32 coredump_mask ;
55+ __u32 coredump_signal ;
5656};
5757
5858static struct rb_root pidfs_ino_tree = RB_ROOT ;
@@ -293,19 +293,29 @@ static __u32 pidfs_coredump_mask(unsigned long mm_flags)
293293 return 0 ;
294294}
295295
296+ /* This must be updated whenever a new flag is added */
297+ #define PIDFD_INFO_SUPPORTED (PIDFD_INFO_PID | \
298+ PIDFD_INFO_CREDS | \
299+ PIDFD_INFO_CGROUPID | \
300+ PIDFD_INFO_EXIT | \
301+ PIDFD_INFO_COREDUMP | \
302+ PIDFD_INFO_SUPPORTED_MASK | \
303+ PIDFD_INFO_COREDUMP_SIGNAL)
304+
296305static long pidfd_info (struct file * file , unsigned int cmd , unsigned long arg )
297306{
298307 struct pidfd_info __user * uinfo = (struct pidfd_info __user * )arg ;
299308 struct task_struct * task __free (put_task ) = NULL ;
300309 struct pid * pid = pidfd_pid (file );
301310 size_t usize = _IOC_SIZE (cmd );
302311 struct pidfd_info kinfo = {};
303- struct pidfs_exit_info * exit_info ;
304312 struct user_namespace * user_ns ;
305313 struct pidfs_attr * attr ;
306314 const struct cred * c ;
307315 __u64 mask ;
308316
317+ BUILD_BUG_ON (sizeof (struct pidfd_info ) != PIDFD_INFO_SIZE_VER2 );
318+
309319 if (!uinfo )
310320 return - EINVAL ;
311321 if (usize < PIDFD_INFO_SIZE_VER0 )
@@ -323,20 +333,24 @@ static long pidfd_info(struct file *file, unsigned int cmd, unsigned long arg)
323333
324334 attr = READ_ONCE (pid -> attr );
325335 if (mask & PIDFD_INFO_EXIT ) {
326- exit_info = READ_ONCE ( attr -> exit_info );
327- if ( exit_info ) {
336+ if ( test_bit ( PIDFS_ATTR_BIT_EXIT , & attr -> attr_mask )) {
337+ smp_rmb ();
328338 kinfo .mask |= PIDFD_INFO_EXIT ;
329339#ifdef CONFIG_CGROUPS
330- kinfo .cgroupid = exit_info -> cgroupid ;
340+ kinfo .cgroupid = attr -> cgroupid ;
331341 kinfo .mask |= PIDFD_INFO_CGROUPID ;
332342#endif
333- kinfo .exit_code = exit_info -> exit_code ;
343+ kinfo .exit_code = attr -> exit_code ;
334344 }
335345 }
336346
337347 if (mask & PIDFD_INFO_COREDUMP ) {
338- kinfo .mask |= PIDFD_INFO_COREDUMP ;
339- kinfo .coredump_mask = READ_ONCE (attr -> __pei .coredump_mask );
348+ if (test_bit (PIDFS_ATTR_BIT_COREDUMP , & attr -> attr_mask )) {
349+ smp_rmb ();
350+ kinfo .mask |= PIDFD_INFO_COREDUMP | PIDFD_INFO_COREDUMP_SIGNAL ;
351+ kinfo .coredump_mask = attr -> coredump_mask ;
352+ kinfo .coredump_signal = attr -> coredump_signal ;
353+ }
340354 }
341355
342356 task = get_pid_task (pid , PIDTYPE_PID );
@@ -355,14 +369,15 @@ static long pidfd_info(struct file *file, unsigned int cmd, unsigned long arg)
355369 if (!c )
356370 return - ESRCH ;
357371
358- if ((kinfo . mask & PIDFD_INFO_COREDUMP ) && !( kinfo .coredump_mask ) ) {
359- task_lock (task );
372+ if ((mask & PIDFD_INFO_COREDUMP ) && !kinfo .coredump_mask ) {
373+ guard ( task_lock ) (task );
360374 if (task -> mm ) {
361375 unsigned long flags = __mm_flags_get_dumpable (task -> mm );
362376
363377 kinfo .coredump_mask = pidfs_coredump_mask (flags );
378+ kinfo .mask |= PIDFD_INFO_COREDUMP ;
379+ /* No coredump actually took place, so no coredump signal. */
364380 }
365- task_unlock (task );
366381 }
367382
368383 /* Unconditionally return identifiers and credentials, the rest only on request */
@@ -409,6 +424,13 @@ static long pidfd_info(struct file *file, unsigned int cmd, unsigned long arg)
409424 return - ESRCH ;
410425
411426copy_out :
427+ if (mask & PIDFD_INFO_SUPPORTED_MASK ) {
428+ kinfo .mask |= PIDFD_INFO_SUPPORTED_MASK ;
429+ kinfo .supported_mask = PIDFD_INFO_SUPPORTED ;
430+ }
431+
432+ /* Are there bits in the return mask not present in PIDFD_INFO_SUPPORTED? */
433+ WARN_ON_ONCE (~PIDFD_INFO_SUPPORTED & kinfo .mask );
412434 /*
413435 * If userspace and the kernel have the same struct size it can just
414436 * be copied. If userspace provides an older struct, only the bits that
@@ -606,7 +628,6 @@ void pidfs_exit(struct task_struct *tsk)
606628{
607629 struct pid * pid = task_pid (tsk );
608630 struct pidfs_attr * attr ;
609- struct pidfs_exit_info * exit_info ;
610631#ifdef CONFIG_CGROUPS
611632 struct cgroup * cgrp ;
612633#endif
@@ -634,41 +655,39 @@ void pidfs_exit(struct task_struct *tsk)
634655 * is put
635656 */
636657
637- exit_info = & attr -> __pei ;
638-
639658#ifdef CONFIG_CGROUPS
640659 rcu_read_lock ();
641660 cgrp = task_dfl_cgroup (tsk );
642- exit_info -> cgroupid = cgroup_id (cgrp );
661+ attr -> cgroupid = cgroup_id (cgrp );
643662 rcu_read_unlock ();
644663#endif
645- exit_info -> exit_code = tsk -> exit_code ;
664+ attr -> exit_code = tsk -> exit_code ;
646665
647666 /* Ensure that PIDFD_GET_INFO sees either all or nothing. */
648- smp_store_release (& attr -> exit_info , & attr -> __pei );
667+ smp_wmb ();
668+ set_bit (PIDFS_ATTR_BIT_EXIT , & attr -> attr_mask );
649669}
650670
651671#ifdef CONFIG_COREDUMP
652672void pidfs_coredump (const struct coredump_params * cprm )
653673{
654674 struct pid * pid = cprm -> pid ;
655- struct pidfs_exit_info * exit_info ;
656675 struct pidfs_attr * attr ;
657- __u32 coredump_mask = 0 ;
658676
659677 attr = READ_ONCE (pid -> attr );
660678
661679 VFS_WARN_ON_ONCE (!attr );
662680 VFS_WARN_ON_ONCE (attr == PIDFS_PID_DEAD );
663681
664- exit_info = & attr -> __pei ;
665- /* Note how we were coredumped. */
666- coredump_mask = pidfs_coredump_mask (cprm -> mm_flags );
667- /* Note that we actually did coredump. */
668- coredump_mask |= PIDFD_COREDUMPED ;
682+ /* Note how we were coredumped and that we coredumped. */
683+ attr -> coredump_mask = pidfs_coredump_mask (cprm -> mm_flags ) |
684+ PIDFD_COREDUMPED ;
669685 /* If coredumping is set to skip we should never end up here. */
670- VFS_WARN_ON_ONCE (coredump_mask & PIDFD_COREDUMP_SKIP );
671- smp_store_release (& exit_info -> coredump_mask , coredump_mask );
686+ VFS_WARN_ON_ONCE (attr -> coredump_mask & PIDFD_COREDUMP_SKIP );
687+ /* Expose the signal number that caused the coredump. */
688+ attr -> coredump_signal = cprm -> siginfo -> si_signo ;
689+ smp_wmb ();
690+ set_bit (PIDFS_ATTR_BIT_COREDUMP , & attr -> attr_mask );
672691}
673692#endif
674693
0 commit comments