Message ID | 20191017101832.5985-1-christian.brauner@ubuntu.com (mailing list archive) |
---|---|
State | Mainlined |
Commit | 3d6d8da48d0b214d65ea0227d47228abc75d7c88 |
Headers | show |
Series | [v3,1/5] pidfd: check pid has attached task in fdinfo | expand |
On Thu, Oct 17, 2019 at 12:18:28PM +0200, Christian Brauner wrote: > Currently, when a task is dead we still print the pid it used to use in > the fdinfo files of its pidfds. This doesn't make much sense since the > pid may have already been reused. So verify that the task is still alive > by introducing the pid_has_task() helper which will be used by other > callers in follow-up patches. > If the task is not alive anymore, we will print -1. This allows us to > differentiate between a task not being present in a given pid namespace > - in which case we already print 0 - and a task having been reaped. > > Note that this uses PIDTYPE_PID for the check. Technically, we could've > checked PIDTYPE_TGID since pidfds currently only refer to thread-group > leaders but if they won't anymore in the future then this check becomes > problematic without it being immediately obvious to non-experts imho. If > a thread is created via clone(CLONE_THREAD) than struct pid has a single > non-empty list pid->tasks[PIDTYPE_PID] and this pid can't be used as a > PIDTYPE_TGID meaning pid->tasks[PIDTYPE_TGID] will return NULL even > though the thread-group leader might still be very much alive. So > checking PIDTYPE_PID is fine and is easier to maintain should we ever > allow pidfds to refer to threads. > > Cc: Jann Horn <jannh@google.com> > Cc: Christian Kellner <christian@kellner.me> > Cc: linux-api@vger.kernel.org > Signed-off-by: Christian Brauner <christian.brauner@ubuntu.com> > Reviewed-by: Oleg Nesterov <oleg@redhat.com> Applied this series to: https://git.kernel.org/pub/scm/linux/kernel/git/brauner/linux.git/log/?h=pidfd Thanks! Christian
diff --git a/include/linux/pid.h b/include/linux/pid.h index 9645b1194c98..034e3cd60dc0 100644 --- a/include/linux/pid.h +++ b/include/linux/pid.h @@ -85,6 +85,10 @@ static inline struct pid *get_pid(struct pid *pid) extern void put_pid(struct pid *pid); extern struct task_struct *pid_task(struct pid *pid, enum pid_type); +static inline bool pid_has_task(struct pid *pid, enum pid_type type) +{ + return !hlist_empty(&pid->tasks[type]); +} extern struct task_struct *get_pid_task(struct pid *pid, enum pid_type); extern struct pid *get_task_pid(struct task_struct *task, enum pid_type type); diff --git a/kernel/fork.c b/kernel/fork.c index 782986962d47..ffa314838b43 100644 --- a/kernel/fork.c +++ b/kernel/fork.c @@ -1732,15 +1732,20 @@ static int pidfd_release(struct inode *inode, struct file *file) */ static void pidfd_show_fdinfo(struct seq_file *m, struct file *f) { - struct pid_namespace *ns = proc_pid_ns(file_inode(m->file)); struct pid *pid = f->private_data; - pid_t nr = pid_nr_ns(pid, ns); + struct pid_namespace *ns; + pid_t nr = -1; - seq_put_decimal_ull(m, "Pid:\t", nr); + if (likely(pid_has_task(pid, PIDTYPE_PID))) { + ns = proc_pid_ns(file_inode(m->file)); + nr = pid_nr_ns(pid, ns); + } + + seq_put_decimal_ll(m, "Pid:\t", nr); #ifdef CONFIG_PID_NS - seq_put_decimal_ull(m, "\nNSpid:\t", nr); - if (nr) { + seq_put_decimal_ll(m, "\nNSpid:\t", nr); + if (nr > 0) { int i; /* If nr is non-zero it means that 'pid' is valid and that @@ -1749,7 +1754,7 @@ static void pidfd_show_fdinfo(struct seq_file *m, struct file *f) * Start at one below the already printed level. */ for (i = ns->level + 1; i <= pid->level; i++) - seq_put_decimal_ull(m, "\t", pid->numbers[i].nr); + seq_put_decimal_ll(m, "\t", pid->numbers[i].nr); } #endif seq_putc(m, '\n');