Skip to content

Commit

Permalink
Merge tag 'pidfd.v5.16' of git://git.kernel.org/pub/scm/linux/kernel/…
Browse files Browse the repository at this point in the history
…git/brauner/linux

Pull pidfd updates from Christian Brauner:
 "Various places in the kernel have picked up pidfds.

  The two most recent additions have probably been the ability to use
  pidfds in bpf maps and the usage of pidfds in mm-based syscalls such
  as process_mrelease() and process_madvise().

  The same pattern to turn a pidfd into a struct task exists in two
  places. One of those places used PIDTYPE_TGID while the other one used
  PIDTYPE_PID even though it is clearly documented in all pidfd-helpers
  that pidfds __currently__ only refer to thread-group leaders (subject
  to change in the future if need be).

  This isn't a bug per se but has the potential to be one if we allow
  pidfds to refer to individual threads. If that happens we want to
  audit all codepaths that make use of them to ensure they can deal with
  pidfds refering to individual threads.

  This adds a simple helper to turn a pidfd into a struct task making it
  easy to grep for such places. Plus, it gets rid of code-duplication"

* tag 'pidfd.v5.16' of git://git.kernel.org/pub/scm/linux/kernel/git/brauner/linux:
  mm: use pidfd_get_task()
  pid: add pidfd_get_task() helper
  • Loading branch information
torvalds committed Nov 11, 2021
2 parents 8810075 + ee9955d commit 6752de1
Show file tree
Hide file tree
Showing 4 changed files with 43 additions and 24 deletions.
1 change: 1 addition & 0 deletions include/linux/pid.h
Original file line number Diff line number Diff line change
Expand Up @@ -78,6 +78,7 @@ struct file;

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);

static inline struct pid *get_pid(struct pid *pid)
Expand Down
36 changes: 36 additions & 0 deletions kernel/pid.c
Original file line number Diff line number Diff line change
Expand Up @@ -539,6 +539,42 @@ struct pid *pidfd_get_pid(unsigned int fd, unsigned int *flags)
return pid;
}

/**
* pidfd_get_task() - Get the task associated with a pidfd
*
* @pidfd: pidfd for which to get the task
* @flags: flags associated with this pidfd
*
* Return the task associated with @pidfd. The function takes a reference on
* the returned task. The caller is responsible for releasing that reference.
*
* Currently, the process identified by @pidfd is always a thread-group leader.
* This restriction currently exists for all aspects of pidfds including pidfd
* creation (CLONE_PIDFD cannot be used with CLONE_THREAD) and pidfd polling
* (only supports thread group leaders).
*
* Return: On success, the task_struct associated with the pidfd.
* On error, a negative errno number will be returned.
*/
struct task_struct *pidfd_get_task(int pidfd, unsigned int *flags)
{
unsigned int f_flags;
struct pid *pid;
struct task_struct *task;

pid = pidfd_get_pid(pidfd, &f_flags);
if (IS_ERR(pid))
return ERR_CAST(pid);

task = get_pid_task(pid, PIDTYPE_TGID);
put_pid(pid);
if (!task)
return ERR_PTR(-ESRCH);

*flags = f_flags;
return task;
}

/**
* pidfd_create() - Create a new pid file descriptor.
*
Expand Down
15 changes: 3 additions & 12 deletions mm/madvise.c
Original file line number Diff line number Diff line change
Expand Up @@ -1235,7 +1235,6 @@ SYSCALL_DEFINE5(process_madvise, int, pidfd, const struct iovec __user *, vec,
struct iovec iovstack[UIO_FASTIOV], iovec;
struct iovec *iov = iovstack;
struct iov_iter iter;
struct pid *pid;
struct task_struct *task;
struct mm_struct *mm;
size_t total_len;
Expand All @@ -1250,18 +1249,12 @@ SYSCALL_DEFINE5(process_madvise, int, pidfd, const struct iovec __user *, vec,
if (ret < 0)
goto out;

pid = pidfd_get_pid(pidfd, &f_flags);
if (IS_ERR(pid)) {
ret = PTR_ERR(pid);
task = pidfd_get_task(pidfd, &f_flags);
if (IS_ERR(task)) {
ret = PTR_ERR(task);
goto free_iov;
}

task = get_pid_task(pid, PIDTYPE_PID);
if (!task) {
ret = -ESRCH;
goto put_pid;
}

if (!process_madvise_behavior_valid(behavior)) {
ret = -EINVAL;
goto release_task;
Expand Down Expand Up @@ -1301,8 +1294,6 @@ SYSCALL_DEFINE5(process_madvise, int, pidfd, const struct iovec __user *, vec,
mmput(mm);
release_task:
put_task_struct(task);
put_pid:
put_pid(pid);
free_iov:
kfree(iov);
out:
Expand Down
15 changes: 3 additions & 12 deletions mm/oom_kill.c
Original file line number Diff line number Diff line change
Expand Up @@ -1150,21 +1150,14 @@ SYSCALL_DEFINE2(process_mrelease, int, pidfd, unsigned int, flags)
struct task_struct *p;
unsigned int f_flags;
bool reap = false;
struct pid *pid;
long ret = 0;

if (flags)
return -EINVAL;

pid = pidfd_get_pid(pidfd, &f_flags);
if (IS_ERR(pid))
return PTR_ERR(pid);

task = get_pid_task(pid, PIDTYPE_TGID);
if (!task) {
ret = -ESRCH;
goto put_pid;
}
task = pidfd_get_task(pidfd, &f_flags);
if (IS_ERR(task))
return PTR_ERR(task);

/*
* Make sure to choose a thread which still has a reference to mm
Expand Down Expand Up @@ -1204,8 +1197,6 @@ SYSCALL_DEFINE2(process_mrelease, int, pidfd, unsigned int, flags)
mmput(mm);
put_task:
put_task_struct(task);
put_pid:
put_pid(pid);
return ret;
#else
return -ENOSYS;
Expand Down

0 comments on commit 6752de1

Please sign in to comment.