Skip to content

Commit 6752de1

Browse files
committed
Merge tag 'pidfd.v5.16' of git://git.kernel.org/pub/scm/linux/kernel/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
2 parents 8810075 + ee9955d commit 6752de1

File tree

4 files changed

+43
-24
lines changed

4 files changed

+43
-24
lines changed

include/linux/pid.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -78,6 +78,7 @@ struct file;
7878

7979
extern struct pid *pidfd_pid(const struct file *file);
8080
struct pid *pidfd_get_pid(unsigned int fd, unsigned int *flags);
81+
struct task_struct *pidfd_get_task(int pidfd, unsigned int *flags);
8182
int pidfd_create(struct pid *pid, unsigned int flags);
8283

8384
static inline struct pid *get_pid(struct pid *pid)

kernel/pid.c

Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -539,6 +539,42 @@ struct pid *pidfd_get_pid(unsigned int fd, unsigned int *flags)
539539
return pid;
540540
}
541541

542+
/**
543+
* pidfd_get_task() - Get the task associated with a pidfd
544+
*
545+
* @pidfd: pidfd for which to get the task
546+
* @flags: flags associated with this pidfd
547+
*
548+
* Return the task associated with @pidfd. The function takes a reference on
549+
* the returned task. The caller is responsible for releasing that reference.
550+
*
551+
* Currently, the process identified by @pidfd is always a thread-group leader.
552+
* This restriction currently exists for all aspects of pidfds including pidfd
553+
* creation (CLONE_PIDFD cannot be used with CLONE_THREAD) and pidfd polling
554+
* (only supports thread group leaders).
555+
*
556+
* Return: On success, the task_struct associated with the pidfd.
557+
* On error, a negative errno number will be returned.
558+
*/
559+
struct task_struct *pidfd_get_task(int pidfd, unsigned int *flags)
560+
{
561+
unsigned int f_flags;
562+
struct pid *pid;
563+
struct task_struct *task;
564+
565+
pid = pidfd_get_pid(pidfd, &f_flags);
566+
if (IS_ERR(pid))
567+
return ERR_CAST(pid);
568+
569+
task = get_pid_task(pid, PIDTYPE_TGID);
570+
put_pid(pid);
571+
if (!task)
572+
return ERR_PTR(-ESRCH);
573+
574+
*flags = f_flags;
575+
return task;
576+
}
577+
542578
/**
543579
* pidfd_create() - Create a new pid file descriptor.
544580
*

mm/madvise.c

Lines changed: 3 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -1235,7 +1235,6 @@ SYSCALL_DEFINE5(process_madvise, int, pidfd, const struct iovec __user *, vec,
12351235
struct iovec iovstack[UIO_FASTIOV], iovec;
12361236
struct iovec *iov = iovstack;
12371237
struct iov_iter iter;
1238-
struct pid *pid;
12391238
struct task_struct *task;
12401239
struct mm_struct *mm;
12411240
size_t total_len;
@@ -1250,18 +1249,12 @@ SYSCALL_DEFINE5(process_madvise, int, pidfd, const struct iovec __user *, vec,
12501249
if (ret < 0)
12511250
goto out;
12521251

1253-
pid = pidfd_get_pid(pidfd, &f_flags);
1254-
if (IS_ERR(pid)) {
1255-
ret = PTR_ERR(pid);
1252+
task = pidfd_get_task(pidfd, &f_flags);
1253+
if (IS_ERR(task)) {
1254+
ret = PTR_ERR(task);
12561255
goto free_iov;
12571256
}
12581257

1259-
task = get_pid_task(pid, PIDTYPE_PID);
1260-
if (!task) {
1261-
ret = -ESRCH;
1262-
goto put_pid;
1263-
}
1264-
12651258
if (!process_madvise_behavior_valid(behavior)) {
12661259
ret = -EINVAL;
12671260
goto release_task;
@@ -1301,8 +1294,6 @@ SYSCALL_DEFINE5(process_madvise, int, pidfd, const struct iovec __user *, vec,
13011294
mmput(mm);
13021295
release_task:
13031296
put_task_struct(task);
1304-
put_pid:
1305-
put_pid(pid);
13061297
free_iov:
13071298
kfree(iov);
13081299
out:

mm/oom_kill.c

Lines changed: 3 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -1150,21 +1150,14 @@ SYSCALL_DEFINE2(process_mrelease, int, pidfd, unsigned int, flags)
11501150
struct task_struct *p;
11511151
unsigned int f_flags;
11521152
bool reap = false;
1153-
struct pid *pid;
11541153
long ret = 0;
11551154

11561155
if (flags)
11571156
return -EINVAL;
11581157

1159-
pid = pidfd_get_pid(pidfd, &f_flags);
1160-
if (IS_ERR(pid))
1161-
return PTR_ERR(pid);
1162-
1163-
task = get_pid_task(pid, PIDTYPE_TGID);
1164-
if (!task) {
1165-
ret = -ESRCH;
1166-
goto put_pid;
1167-
}
1158+
task = pidfd_get_task(pidfd, &f_flags);
1159+
if (IS_ERR(task))
1160+
return PTR_ERR(task);
11681161

11691162
/*
11701163
* Make sure to choose a thread which still has a reference to mm
@@ -1204,8 +1197,6 @@ SYSCALL_DEFINE2(process_mrelease, int, pidfd, unsigned int, flags)
12041197
mmput(mm);
12051198
put_task:
12061199
put_task_struct(task);
1207-
put_pid:
1208-
put_pid(pid);
12091200
return ret;
12101201
#else
12111202
return -ENOSYS;

0 commit comments

Comments
 (0)