On Mon 27-03-23 20:22:51, Christian Brauner wrote: > Add a new helper that allows to reserve a pidfd and allocates a new > pidfd file that stashes the provided struct pid. This will allow us to > remove places that either open code this function or that call > pidfd_create() but then have to call close_fd() because there are still > failure points after pidfd_create() has been called. > > Signed-off-by: Christian Brauner <brauner@xxxxxxxxxx> Looks good to me. Feel free to add: Reviewed-by: Jan Kara <jack@xxxxxxx> Honza > --- > include/linux/pid.h | 1 + > kernel/pid.c | 69 +++++++++++++++++++++++++++++++++++++++++++---------- > 2 files changed, 58 insertions(+), 12 deletions(-) > > diff --git a/include/linux/pid.h b/include/linux/pid.h > index 343abf22092e..b75de288a8c2 100644 > --- a/include/linux/pid.h > +++ b/include/linux/pid.h > @@ -80,6 +80,7 @@ extern struct pid *pidfd_pid(const struct file *file); > struct pid *pidfd_get_pid(unsigned int fd, unsigned int *flags); > struct task_struct *pidfd_get_task(int pidfd, unsigned int *flags); > int pidfd_create(struct pid *pid, unsigned int flags); > +int pidfd_prepare(struct pid *pid, unsigned int flags, struct file **ret); > > static inline struct pid *get_pid(struct pid *pid) > { > diff --git a/kernel/pid.c b/kernel/pid.c > index 3fbc5e46b721..95e7e01574c8 100644 > --- a/kernel/pid.c > +++ b/kernel/pid.c > @@ -576,6 +576,56 @@ struct task_struct *pidfd_get_task(int pidfd, unsigned int *flags) > return task; > } > > +/** > + * pidfd_prepare - allocate a new pidfd_file and reserve a pidfd > + * @pid: the struct pid for which to create a pidfd > + * @flags: flags of the new @pidfd > + * @pidfd: the pidfd to return > + * > + * Allocate a new file that stashes @pid and reserve a new pidfd number in the > + * caller's file descriptor table. The pidfd is reserved but not installed yet. > + * > + * If this function returns successfully the caller is responsible to either > + * call fd_install() passing the returned pidfd and pidfd file as arguments in > + * order to install the pidfd into its file descriptor table or they must use > + * put_unused_fd() and fput() on the returned pidfd and pidfd file > + * respectively. > + * > + * This function is useful when a pidfd must already be reserved but there > + * might still be points of failure afterwards and the caller wants to ensure > + * that no pidfd is leaked into its file descriptor table. > + * > + * Return: On success, a reserved pidfd is returned from the function and a new > + * pidfd file is returned in the last argument to the function. On > + * error, a negative error code is returned from the function and the > + * last argument remains unchanged. > + */ > +int pidfd_prepare(struct pid *pid, unsigned int flags, struct file **ret) > +{ > + int pidfd; > + struct file *pidfd_file; > + > + if (!pid || !pid_has_task(pid, PIDTYPE_TGID)) > + return -EINVAL; > + > + if (flags & ~(O_NONBLOCK | O_RDWR | O_CLOEXEC)) > + return -EINVAL; > + > + pidfd = get_unused_fd_flags(O_RDWR | O_CLOEXEC); > + if (pidfd < 0) > + return pidfd; > + > + pidfd_file = anon_inode_getfile("[pidfd]", &pidfd_fops, pid, > + flags | O_RDWR | O_CLOEXEC); > + if (IS_ERR(pidfd_file)) { > + put_unused_fd(pidfd); > + return PTR_ERR(pidfd_file); > + } > + get_pid(pid); /* held by pidfd_file now */ > + *ret = pidfd_file; > + return pidfd; > +} > + > /** > * pidfd_create() - Create a new pid file descriptor. > * > @@ -594,20 +644,15 @@ struct task_struct *pidfd_get_task(int pidfd, unsigned int *flags) > */ > int pidfd_create(struct pid *pid, unsigned int flags) > { > - int fd; > + int pidfd; > + struct file *pidfd_file; > > - if (!pid || !pid_has_task(pid, PIDTYPE_TGID)) > - return -EINVAL; > - > - if (flags & ~(O_NONBLOCK | O_RDWR | O_CLOEXEC)) > - return -EINVAL; > - > - fd = anon_inode_getfd("[pidfd]", &pidfd_fops, get_pid(pid), > - flags | O_RDWR | O_CLOEXEC); > - if (fd < 0) > - put_pid(pid); > + pidfd = pidfd_prepare(pid, flags, &pidfd_file); > + if (pidfd < 0) > + return pidfd; > > - return fd; > + fd_install(pidfd, pidfd_file); > + return pidfd; > } > > /** > > -- > 2.34.1 > -- Jan Kara <jack@xxxxxxxx> SUSE Labs, CR