diff options
Diffstat (limited to 'kernel/pid.c')
-rw-r--r-- | kernel/pid.c | 69 |
1 files changed, 69 insertions, 0 deletions
diff --git a/kernel/pid.c b/kernel/pid.c index 6ce3a95968f7..8e6f50053364 100644 --- a/kernel/pid.c +++ b/kernel/pid.c | |||
@@ -37,6 +37,8 @@ | |||
37 | #include <linux/syscalls.h> | 37 | #include <linux/syscalls.h> |
38 | #include <linux/proc_ns.h> | 38 | #include <linux/proc_ns.h> |
39 | #include <linux/proc_fs.h> | 39 | #include <linux/proc_fs.h> |
40 | #include <linux/anon_inodes.h> | ||
41 | #include <linux/sched/signal.h> | ||
40 | #include <linux/sched/task.h> | 42 | #include <linux/sched/task.h> |
41 | #include <linux/idr.h> | 43 | #include <linux/idr.h> |
42 | 44 | ||
@@ -452,6 +454,73 @@ struct pid *find_ge_pid(int nr, struct pid_namespace *ns) | |||
452 | return idr_get_next(&ns->idr, &nr); | 454 | return idr_get_next(&ns->idr, &nr); |
453 | } | 455 | } |
454 | 456 | ||
457 | /** | ||
458 | * pidfd_create() - Create a new pid file descriptor. | ||
459 | * | ||
460 | * @pid: struct pid that the pidfd will reference | ||
461 | * | ||
462 | * This creates a new pid file descriptor with the O_CLOEXEC flag set. | ||
463 | * | ||
464 | * Note, that this function can only be called after the fd table has | ||
465 | * been unshared to avoid leaking the pidfd to the new process. | ||
466 | * | ||
467 | * Return: On success, a cloexec pidfd is returned. | ||
468 | * On error, a negative errno number will be returned. | ||
469 | */ | ||
470 | static int pidfd_create(struct pid *pid) | ||
471 | { | ||
472 | int fd; | ||
473 | |||
474 | fd = anon_inode_getfd("[pidfd]", &pidfd_fops, get_pid(pid), | ||
475 | O_RDWR | O_CLOEXEC); | ||
476 | if (fd < 0) | ||
477 | put_pid(pid); | ||
478 | |||
479 | return fd; | ||
480 | } | ||
481 | |||
482 | /** | ||
483 | * pidfd_open() - Open new pid file descriptor. | ||
484 | * | ||
485 | * @pid: pid for which to retrieve a pidfd | ||
486 | * @flags: flags to pass | ||
487 | * | ||
488 | * This creates a new pid file descriptor with the O_CLOEXEC flag set for | ||
489 | * the process identified by @pid. Currently, the process identified by | ||
490 | * @pid must be a thread-group leader. This restriction currently exists | ||
491 | * for all aspects of pidfds including pidfd creation (CLONE_PIDFD cannot | ||
492 | * be used with CLONE_THREAD) and pidfd polling (only supports thread group | ||
493 | * leaders). | ||
494 | * | ||
495 | * Return: On success, a cloexec pidfd is returned. | ||
496 | * On error, a negative errno number will be returned. | ||
497 | */ | ||
498 | SYSCALL_DEFINE2(pidfd_open, pid_t, pid, unsigned int, flags) | ||
499 | { | ||
500 | int fd, ret; | ||
501 | struct pid *p; | ||
502 | |||
503 | if (flags) | ||
504 | return -EINVAL; | ||
505 | |||
506 | if (pid <= 0) | ||
507 | return -EINVAL; | ||
508 | |||
509 | p = find_get_pid(pid); | ||
510 | if (!p) | ||
511 | return -ESRCH; | ||
512 | |||
513 | ret = 0; | ||
514 | rcu_read_lock(); | ||
515 | if (!pid_task(p, PIDTYPE_TGID)) | ||
516 | ret = -EINVAL; | ||
517 | rcu_read_unlock(); | ||
518 | |||
519 | fd = ret ?: pidfd_create(p); | ||
520 | put_pid(p); | ||
521 | return fd; | ||
522 | } | ||
523 | |||
455 | void __init pid_idr_init(void) | 524 | void __init pid_idr_init(void) |
456 | { | 525 | { |
457 | /* Verify no one has done anything silly: */ | 526 | /* Verify no one has done anything silly: */ |