History

Merge tag 'threads-v5.5' of git://git.kernel.org/pub/scm/linux/kernel/git/brauner/linux

Pull thread management updates from Christian Brauner: - A pidfd's fdinfo file currently contains the field "Pid:\t<pid>" where <pid> is the pid of the process in the pid namespace of the procfs instance the fdinfo file for the pidfd was opened in. The fdinfo file has now gained a new "NSpid:\t<ns-pid1>[\t<ns-pid2>[...]]" field which lists the pids of the process in all child pid namespaces provided the pid namespace of the procfs instance it is looked up under has an ancestoral relationship with the pid namespace of the process. If it does not 0 will be shown and no further pid namespaces will be listed. Tests included. (Christian Kellner) - If the process the pidfd references has already exited, print -1 for the Pid and NSpid fields in the pidfd's fdinfo file. Tests included. (me) - Add CLONE_CLEAR_SIGHAND. This lets callers clear all signal handler that are not SIG_DFL or SIG_IGN at process creation time. This originated as a feature request from glibc to improve performance and elimate races in their posix_spawn() implementation. Tests included. (me) - Add support for choosing a specific pid for a process with clone3(). This is the feature which was part of the thread update for v5.4 but after a discussion at LPC in Lisbon we decided to delay it for one more cycle in order to make the interface more generic. This has now done. It is now possible to choose a specific pid in a whole pid namespaces (sub)hierarchy instead of just one pid namespace. In order to choose a specific pid the caller must have CAP_SYS_ADMIN in all owning user namespaces of the target pid namespaces. Tests included. (Adrian Reber) - Test improvements and extensions. (Andrei Vagin, me) * tag 'threads-v5.5' of git://git.kernel.org/pub/scm/linux/kernel/git/brauner/linux: selftests/clone3: skip if clone3() is ENOSYS selftests/clone3: check that all pids are released on error paths selftests/clone3: report a correct number of fails selftests/clone3: flush stdout and stderr before clone3() and _exit() selftests: add tests for clone3() with *set_tid fork: extend clone3() to support setting a PID selftests: add tests for clone3() tests: test CLONE_CLEAR_SIGHAND clone3: add CLONE_CLEAR_SIGHAND pid: use pid_has_task() in pidfd_open() exit: use pid_has_task() in do_wait() pid: use pid_has_task() in __change_pid() test: verify fdinfo for pidfd of reaped process pidfd: check pid has attached task in fdinfo pidfd: add tests for NSpid info in fdinfo pidfd: add NSpid entries to fdinfo

Linus Torvalds committed 6 years ago

Commit 0acefef2 parents 9c91e6a 11fde1618 files · +1308 −58Browse files

Unified · Split

18 files
  1. MAINTAINERS +1 −0
  2. include/linux/pid.h +6 −1
  3. include/linux/pid_namespace.h +2 −0
  4. include/linux/sched/task.h +3 −0
  5. include/uapi/linux/sched.h +42 −22
  6. kernel/exit.c +1 −1
  7. kernel/fork.c +92 −8
  8. kernel/pid.c +63 −23
  9. kernel/pid_namespace.c +0 −2
  10. tools/testing/selftests/Makefile +1 −0
  11. tools/testing/selftests/clone3/.gitignore +3 −0
  12. tools/testing/selftests/clone3/Makefile +6 −0
  13. tools/testing/selftests/clone3/clone3.c +202 −0
  14. tools/testing/selftests/clone3/clone3_clear_sighand.c +129 −0
  15. tools/testing/selftests/clone3/clone3_selftests.h +63 −0
  16. tools/testing/selftests/clone3/clone3_set_tid.c +397 −0
  17. tools/testing/selftests/pidfd/Makefile +1 −1
  18. tools/testing/selftests/pidfd/pidfd_fdinfo_test.c +296 −0
MAINTAINERS+1−0
@@ -12861,6 +12861,7 @@ S: Maintained · 12860 unmodified lines
12861T: git git://git.kernel.org/pub/scm/linux/kernel/git/brauner/linux.git12861T: git git://git.kernel.org/pub/scm/linux/kernel/git/brauner/linux.git
12862F: samples/pidfd/12862F: samples/pidfd/
12863F: tools/testing/selftests/pidfd/12863F: tools/testing/selftests/pidfd/
12864F: tools/testing/selftests/clone3/
12864K: (?i)pidfd12865K: (?i)pidfd
12865K: (?i)clone312866K: (?i)clone3
12866K: \b(clone_args|kernel_clone_args)\b12867K: \b(clone_args|kernel_clone_args)\b
include/linux/pid.h+6−1
@@ -85,6 +85,10 @@ static inline struct pid *get_pid(struct pid *pid) · 84 unmodified lines
85 85
86extern void put_pid(struct pid *pid);86extern void put_pid(struct pid *pid);
87extern struct task_struct *pid_task(struct pid *pid, enum pid_type);87extern struct task_struct *pid_task(struct pid *pid, enum pid_type);
88static inline bool pid_has_task(struct pid *pid, enum pid_type type)
89{
90 return !hlist_empty(&pid->tasks[type]);
91}
88extern struct task_struct *get_pid_task(struct pid *pid, enum pid_type);92extern struct task_struct *get_pid_task(struct pid *pid, enum pid_type);
89 93
90extern struct pid *get_task_pid(struct task_struct *task, enum pid_type type);94extern struct pid *get_task_pid(struct task_struct *task, enum pid_type type);
@@ -120,7 +124,8 @@ extern struct pid *find_vpid(int nr); · 29 unmodified lines
120extern struct pid *find_get_pid(int nr);124extern struct pid *find_get_pid(int nr);
121extern struct pid *find_ge_pid(int nr, struct pid_namespace *);125extern struct pid *find_ge_pid(int nr, struct pid_namespace *);
122 126
123extern struct pid *alloc_pid(struct pid_namespace *ns);127extern struct pid *alloc_pid(struct pid_namespace *ns, pid_t *set_tid,
128 size_t set_tid_size);
124extern void free_pid(struct pid *pid);129extern void free_pid(struct pid *pid);
125extern void disable_pid_allocation(struct pid_namespace *ns);130extern void disable_pid_allocation(struct pid_namespace *ns);
126 131
include/linux/pid_namespace.h+2−0
@@ -12,6 +12,8 @@ · 11 unmodified lines
12#include <linux/ns_common.h>12#include <linux/ns_common.h>
13#include <linux/idr.h>13#include <linux/idr.h>
14 14
15/* MAX_PID_NS_LEVEL is needed for limiting size of 'struct pid' */
16#define MAX_PID_NS_LEVEL 32
15 17
16struct fs_pin;18struct fs_pin;
17 19
include/linux/sched/task.h+3−0
@@ -26,6 +26,9 @@ struct kernel_clone_args { · 25 unmodified lines
26 unsigned long stack;26 unsigned long stack;
27 unsigned long stack_size;27 unsigned long stack_size;
28 unsigned long tls;28 unsigned long tls;
29 pid_t *set_tid;
30 /* Number of elements in *set_tid */
31 size_t set_tid_size;
29};32};
30 33
31/*34/*
include/uapi/linux/sched.h+42−22
@@ -33,31 +33,48 @@ · 32 unmodified lines
33#define CLONE_NEWNET 0x40000000 /* New network namespace */33#define CLONE_NEWNET 0x40000000 /* New network namespace */
34#define CLONE_IO 0x80000000 /* Clone io context */34#define CLONE_IO 0x80000000 /* Clone io context */
35 35
36/* Flags for the clone3() syscall. */
37#define CLONE_CLEAR_SIGHAND 0x100000000ULL /* Clear any signal handler and reset to SIG_DFL. */
38
36#ifndef __ASSEMBLY__39#ifndef __ASSEMBLY__
37/**40/**
38 * struct clone_args - arguments for the clone3 syscall41 * struct clone_args - arguments for the clone3 syscall
39 * @flags: Flags for the new process as listed above.42 * @flags: Flags for the new process as listed above.
40 * All flags are valid except for CSIGNAL and43 * All flags are valid except for CSIGNAL and
41 * CLONE_DETACHED.44 * CLONE_DETACHED.
42 * @pidfd: If CLONE_PIDFD is set, a pidfd will be45 * @pidfd: If CLONE_PIDFD is set, a pidfd will be
43 * returned in this argument.46 * returned in this argument.
44 * @child_tid: If CLONE_CHILD_SETTID is set, the TID of the47 * @child_tid: If CLONE_CHILD_SETTID is set, the TID of the
45 * child process will be returned in the child's48 * child process will be returned in the child's
46 * memory.49 * memory.
47 * @parent_tid: If CLONE_PARENT_SETTID is set, the TID of50 * @parent_tid: If CLONE_PARENT_SETTID is set, the TID of
48 * the child process will be returned in the51 * the child process will be returned in the
49 * parent's memory.52 * parent's memory.
50 * @exit_signal: The exit_signal the parent process will be53 * @exit_signal: The exit_signal the parent process will be
51 * sent when the child exits.54 * sent when the child exits.
52 * @stack: Specify the location of the stack for the55 * @stack: Specify the location of the stack for the
53 * child process.56 * child process.
54 * Note, @stack is expected to point to the57 * Note, @stack is expected to point to the
55 * lowest address. The stack direction will be58 * lowest address. The stack direction will be
56 * determined by the kernel and set up59 * determined by the kernel and set up
57 * appropriately based on @stack_size.60 * appropriately based on @stack_size.
58 * @stack_size: The size of the stack for the child process.61 * @stack_size: The size of the stack for the child process.
59 * @tls: If CLONE_SETTLS is set, the tls descriptor62 * @tls: If CLONE_SETTLS is set, the tls descriptor
60 * is set to tls.63 * is set to tls.
64 * @set_tid: Pointer to an array of type *pid_t. The size
65 * of the array is defined using @set_tid_size.
66 * This array is used to select PIDs/TIDs for
67 * newly created processes. The first element in
68 * this defines the PID in the most nested PID
69 * namespace. Each additional element in the array
70 * defines the PID in the parent PID namespace of
71 * the original PID namespace. If the array has
72 * less entries than the number of currently
73 * nested PID namespaces only the PIDs in the
74 * corresponding namespaces are set.
75 * @set_tid_size: This defines the size of the array referenced
76 * in @set_tid. This cannot be larger than the
77 * kernel's limit of nested PID namespaces.
61 *78 *
62 * The structure is versioned by size and thus extensible.79 * The structure is versioned by size and thus extensible.
63 * New struct members must go at the end of the struct and80 * New struct members must go at the end of the struct and
@@ -72,10 +89,13 @@ struct clone_args { · 8 unmodified lines
72 __aligned_u64 stack;89 __aligned_u64 stack;
73 __aligned_u64 stack_size;90 __aligned_u64 stack_size;
74 __aligned_u64 tls;91 __aligned_u64 tls;
92 __aligned_u64 set_tid;
93 __aligned_u64 set_tid_size;
75};94};
76#endif95#endif
77 96
78#define CLONE_ARGS_SIZE_VER0 64 /* sizeof first published struct */97#define CLONE_ARGS_SIZE_VER0 64 /* sizeof first published struct */
98#define CLONE_ARGS_SIZE_VER1 80 /* sizeof second published struct */
79 99
80/*100/*
81 * Scheduling policies101 * Scheduling policies
kernel/exit.c+1−1
@@ -1457,7 +1457,7 @@ repeat: · 1456 unmodified lines
1457 */1457 */
1458 wo->notask_error = -ECHILD;1458 wo->notask_error = -ECHILD;
1459 if ((wo->wo_type < PIDTYPE_MAX) &&1459 if ((wo->wo_type < PIDTYPE_MAX) &&
1460 (!wo->wo_pid || hlist_empty(&wo->wo_pid->tasks[wo->wo_type])))1460 (!wo->wo_pid || !pid_has_task(wo->wo_pid, wo->wo_type)))
1461 goto notask;1461 goto notask;
1462 1462
1463 set_current_state(TASK_INTERRUPTIBLE);1463 set_current_state(TASK_INTERRUPTIBLE);
kernel/fork.c+92−8
@@ -1517,6 +1517,11 @@ static int copy_sighand(unsigned long clone_flags, struct task_struct *tsk) · 1516 unmodified lines
1517 spin_lock_irq(&current->sighand->siglock);1517 spin_lock_irq(&current->sighand->siglock);
1518 memcpy(sig->action, current->sighand->action, sizeof(sig->action));1518 memcpy(sig->action, current->sighand->action, sizeof(sig->action));
1519 spin_unlock_irq(&current->sighand->siglock);1519 spin_unlock_irq(&current->sighand->siglock);
1520
1521 /* Reset all signal handler not set to SIG_IGN to SIG_DFL. */
1522 if (clone_flags & CLONE_CLEAR_SIGHAND)
1523 flush_signal_handlers(tsk, 0);
1524
1520 return 0;1525 return 0;
1521}1526}
1522 1527
@@ -1695,12 +1700,68 @@ static int pidfd_release(struct inode *inode, struct file *file) · 172 unmodified lines
1695}1700}
1696 1701
1697#ifdef CONFIG_PROC_FS1702#ifdef CONFIG_PROC_FS
1703/**
1704 * pidfd_show_fdinfo - print information about a pidfd
1705 * @m: proc fdinfo file
1706 * @f: file referencing a pidfd
1707 *
1708 * Pid:
1709 * This function will print the pid that a given pidfd refers to in the
1710 * pid namespace of the procfs instance.
1711 * If the pid namespace of the process is not a descendant of the pid
1712 * namespace of the procfs instance 0 will be shown as its pid. This is
1713 * similar to calling getppid() on a process whose parent is outside of
1714 * its pid namespace.
1715 *
1716 * NSpid:
1717 * If pid namespaces are supported then this function will also print
1718 * the pid of a given pidfd refers to for all descendant pid namespaces
1719 * starting from the current pid namespace of the instance, i.e. the
1720 * Pid field and the first entry in the NSpid field will be identical.
1721 * If the pid namespace of the process is not a descendant of the pid
1722 * namespace of the procfs instance 0 will be shown as its first NSpid
1723 * entry and no others will be shown.
1724 * Note that this differs from the Pid and NSpid fields in
1725 * /proc/<pid>/status where Pid and NSpid are always shown relative to
1726 * the pid namespace of the procfs instance. The difference becomes
1727 * obvious when sending around a pidfd between pid namespaces from a
1728 * different branch of the tree, i.e. where no ancestoral relation is
1729 * present between the pid namespaces:
1730 * - create two new pid namespaces ns1 and ns2 in the initial pid
1731 * namespace (also take care to create new mount namespaces in the
1732 * new pid namespace and mount procfs)
1733 * - create a process with a pidfd in ns1
1734 * - send pidfd from ns1 to ns2
1735 * - read /proc/self/fdinfo/<pidfd> and observe that both Pid and NSpid
1736 * have exactly one entry, which is 0
1737 */
1698static void pidfd_show_fdinfo(struct seq_file *m, struct file *f)1738static void pidfd_show_fdinfo(struct seq_file *m, struct file *f)
1699{1739{
1700 struct pid_namespace *ns = proc_pid_ns(file_inode(m->file));
1701 struct pid *pid = f->private_data;1740 struct pid *pid = f->private_data;
1741 struct pid_namespace *ns;
1742 pid_t nr = -1;
1743
1744 if (likely(pid_has_task(pid, PIDTYPE_PID))) {
1745 ns = proc_pid_ns(file_inode(m->file));
1746 nr = pid_nr_ns(pid, ns);
1747 }
1748
1749 seq_put_decimal_ll(m, "Pid:\t", nr);
1750
1751#ifdef CONFIG_PID_NS
1752 seq_put_decimal_ll(m, "\nNSpid:\t", nr);
1753 if (nr > 0) {
1754 int i;
1702 1755
1703 seq_put_decimal_ull(m, "Pid:\t", pid_nr_ns(pid, ns));1756 /* If nr is non-zero it means that 'pid' is valid and that
1757 * ns, i.e. the pid namespace associated with the procfs
1758 * instance, is in the pid namespace hierarchy of pid.
1759 * Start at one below the already printed level.
1760 */
1761 for (i = ns->level + 1; i <= pid->level; i++)
1762 seq_put_decimal_ll(m, "\t", pid->numbers[i].nr);
1763 }
1764#endif
1704 seq_putc(m, '\n');1765 seq_putc(m, '\n');
1705}1766}
1706#endif1767#endif
@@ -2026,7 +2087,8 @@ static __latent_entropy struct task_struct *copy_process( · 319 unmodified lines
2026 stackleak_task_init(p);2087 stackleak_task_init(p);
2027 2088
2028 if (pid != &init_struct_pid) {2089 if (pid != &init_struct_pid) {
2029 pid = alloc_pid(p->nsproxy->pid_ns_for_children);2090 pid = alloc_pid(p->nsproxy->pid_ns_for_children, args->set_tid,
2091 args->set_tid_size);
2030 if (IS_ERR(pid)) {2092 if (IS_ERR(pid)) {
2031 retval = PTR_ERR(pid);2093 retval = PTR_ERR(pid);
2032 goto bad_fork_cleanup_thread;2094 goto bad_fork_cleanup_thread;
@@ -2529,6 +2591,7 @@ noinline static int copy_clone_args_from_user(struct kernel_clone_args *kargs, · 496 unmodified lines
2529{2591{
2530 int err;2592 int err;
2531 struct clone_args args;2593 struct clone_args args;
2594 pid_t *kset_tid = kargs->set_tid;
2532 2595
2533 if (unlikely(usize > PAGE_SIZE))2596 if (unlikely(usize > PAGE_SIZE))
2534 return -E2BIG;2597 return -E2BIG;
@@ -2539,6 +2602,15 @@ noinline static int copy_clone_args_from_user(struct kernel_clone_args *kargs, · 4 unmodified lines
2539 if (err)2602 if (err)
2540 return err;2603 return err;
2541 2604
2605 if (unlikely(args.set_tid_size > MAX_PID_NS_LEVEL))
2606 return -EINVAL;
2607
2608 if (unlikely(!args.set_tid && args.set_tid_size > 0))
2609 return -EINVAL;
2610
2611 if (unlikely(args.set_tid && args.set_tid_size == 0))
2612 return -EINVAL;
2613
2542 /*2614 /*
2543 * Verify that higher 32bits of exit_signal are unset and that2615 * Verify that higher 32bits of exit_signal are unset and that
2544 * it is a valid signal2616 * it is a valid signal
@@ -2556,8 +2628,16 @@ noinline static int copy_clone_args_from_user(struct kernel_clone_args *kargs, · 11 unmodified lines
2556 .stack = args.stack,2628 .stack = args.stack,
2557 .stack_size = args.stack_size,2629 .stack_size = args.stack_size,
2558 .tls = args.tls,2630 .tls = args.tls,
2631 .set_tid_size = args.set_tid_size,
2559 };2632 };
2560 2633
2634 if (args.set_tid &&
2635 copy_from_user(kset_tid, u64_to_user_ptr(args.set_tid),
2636 (kargs->set_tid_size * sizeof(pid_t))))
2637 return -EFAULT;
2638
2639 kargs->set_tid = kset_tid;
2640
2561 return 0;2641 return 0;
2562}2642}
2563 2643
@@ -2591,11 +2671,8 @@ static inline bool clone3_stack_valid(struct kernel_clone_args *kargs) · 27 unmodified lines
2591 2671
2592static bool clone3_args_valid(struct kernel_clone_args *kargs)2672static bool clone3_args_valid(struct kernel_clone_args *kargs)
2593{2673{
2594 /*2674 /* Verify that no unknown flags are passed along. */
2595 * All lower bits of the flag word are taken.2675 if (kargs->flags & ~(CLONE_LEGACY_FLAGS | CLONE_CLEAR_SIGHAND))
2596 * Verify that no other unknown flags are passed along.
2597 */
2598 if (kargs->flags & ~CLONE_LEGACY_FLAGS)
2599 return false;2676 return false;
2600 2677
2601 /*2678 /*
@@ -2605,6 +2682,10 @@ static bool clone3_args_valid(struct kernel_clone_args *kargs) · 3 unmodified lines
2605 if (kargs->flags & (CLONE_DETACHED | CSIGNAL))2682 if (kargs->flags & (CLONE_DETACHED | CSIGNAL))
2606 return false;2683 return false;
2607 2684
2685 if ((kargs->flags & (CLONE_SIGHAND | CLONE_CLEAR_SIGHAND)) ==
2686 (CLONE_SIGHAND | CLONE_CLEAR_SIGHAND))
2687 return false;
2688
2608 if ((kargs->flags & (CLONE_THREAD | CLONE_PARENT)) &&2689 if ((kargs->flags & (CLONE_THREAD | CLONE_PARENT)) &&
2609 kargs->exit_signal)2690 kargs->exit_signal)
2610 return false;2691 return false;
@@ -2631,6 +2712,9 @@ SYSCALL_DEFINE2(clone3, struct clone_args __user *, uargs, size_t, size) · 20 unmodified lines
2631 int err;2712 int err;
2632 2713
2633 struct kernel_clone_args kargs;2714 struct kernel_clone_args kargs;
2715 pid_t set_tid[MAX_PID_NS_LEVEL];
2716
2717 kargs.set_tid = set_tid;
2634 2718
2635 err = copy_clone_args_from_user(&kargs, uargs, size);2719 err = copy_clone_args_from_user(&kargs, uargs, size);
2636 if (err)2720 if (err)
kernel/pid.c+63−23
@@ -157,7 +157,8 @@ void free_pid(struct pid *pid) · 156 unmodified lines
157 call_rcu(&pid->rcu, delayed_put_pid);157 call_rcu(&pid->rcu, delayed_put_pid);
158}158}
159 159
160struct pid *alloc_pid(struct pid_namespace *ns)160struct pid *alloc_pid(struct pid_namespace *ns, pid_t *set_tid,
161 size_t set_tid_size)
161{162{
162 struct pid *pid;163 struct pid *pid;
163 enum pid_type type;164 enum pid_type type;
@@ -166,6 +167,17 @@ struct pid *alloc_pid(struct pid_namespace *ns) · 2 unmodified lines
166 struct upid *upid;167 struct upid *upid;
167 int retval = -ENOMEM;168 int retval = -ENOMEM;
168 169
170 /*
171 * set_tid_size contains the size of the set_tid array. Starting at
172 * the most nested currently active PID namespace it tells alloc_pid()
173 * which PID to set for a process in that most nested PID namespace
174 * up to set_tid_size PID namespaces. It does not have to set the PID
175 * for a process in all nested PID namespaces but set_tid_size must
176 * never be greater than the current ns->level + 1.
177 */
178 if (set_tid_size > ns->level + 1)
179 return ERR_PTR(-EINVAL);
180
169 pid = kmem_cache_alloc(ns->pid_cachep, GFP_KERNEL);181 pid = kmem_cache_alloc(ns->pid_cachep, GFP_KERNEL);
170 if (!pid)182 if (!pid)
171 return ERR_PTR(retval);183 return ERR_PTR(retval);
@@ -174,24 +186,54 @@ struct pid *alloc_pid(struct pid_namespace *ns) · 2 unmodified lines
174 pid->level = ns->level;186 pid->level = ns->level;
175 187
176 for (i = ns->level; i >= 0; i--) {188 for (i = ns->level; i >= 0; i--) {
177 int pid_min = 1;189 int tid = 0;
190
191 if (set_tid_size) {
192 tid = set_tid[ns->level - i];
193
194 retval = -EINVAL;
195 if (tid < 1 || tid >= pid_max)
196 goto out_free;
197 /*
198 * Also fail if a PID != 1 is requested and
199 * no PID 1 exists.
200 */
201 if (tid != 1 && !tmp->child_reaper)
202 goto out_free;
203 retval = -EPERM;
204 if (!ns_capable(tmp->user_ns, CAP_SYS_ADMIN))
205 goto out_free;
206 set_tid_size--;
207 }
178 208
179 idr_preload(GFP_KERNEL);209 idr_preload(GFP_KERNEL);
180 spin_lock_irq(&pidmap_lock);210 spin_lock_irq(&pidmap_lock);
181 211
182 /*212 if (tid) {
183 * init really needs pid 1, but after reaching the maximum213 nr = idr_alloc(&tmp->idr, NULL, tid,
184 * wrap back to RESERVED_PIDS214 tid + 1, GFP_ATOMIC);
185 */215 /*
186 if (idr_get_cursor(&tmp->idr) > RESERVED_PIDS)216 * If ENOSPC is returned it means that the PID is
187 pid_min = RESERVED_PIDS;217 * alreay in use. Return EEXIST in that case.
188 218 */
189 /*219 if (nr == -ENOSPC)
190 * Store a null pointer so find_pid_ns does not find220 nr = -EEXIST;
191 * a partially initialized PID (see below).221 } else {
192 */222 int pid_min = 1;
193 nr = idr_alloc_cyclic(&tmp->idr, NULL, pid_min,223 /*
194 pid_max, GFP_ATOMIC);224 * init really needs pid 1, but after reaching the
225 * maximum wrap back to RESERVED_PIDS
226 */
227 if (idr_get_cursor(&tmp->idr) > RESERVED_PIDS)
228 pid_min = RESERVED_PIDS;
229
230 /*
231 * Store a null pointer so find_pid_ns does not find
232 * a partially initialized PID (see below).
233 */
234 nr = idr_alloc_cyclic(&tmp->idr, NULL, pid_min,
235 pid_max, GFP_ATOMIC);
236 }
195 spin_unlock_irq(&pidmap_lock);237 spin_unlock_irq(&pidmap_lock);
196 idr_preload_end();238 idr_preload_end();
197 239
@@ -299,7 +341,7 @@ static void __change_pid(struct task_struct *task, enum pid_type type, · 101 unmodified lines
299 *pid_ptr = new;341 *pid_ptr = new;
300 342
301 for (tmp = PIDTYPE_MAX; --tmp >= 0; )343 for (tmp = PIDTYPE_MAX; --tmp >= 0; )
302 if (!hlist_empty(&pid->tasks[tmp]))344 if (pid_has_task(pid, tmp))
303 return;345 return;
304 346
305 free_pid(pid);347 free_pid(pid);
@@ -497,7 +539,7 @@ static int pidfd_create(struct pid *pid) · 191 unmodified lines
497 */539 */
498SYSCALL_DEFINE2(pidfd_open, pid_t, pid, unsigned int, flags)540SYSCALL_DEFINE2(pidfd_open, pid_t, pid, unsigned int, flags)
499{541{
500 int fd, ret;542 int fd;
501 struct pid *p;543 struct pid *p;
502 544
503 if (flags)545 if (flags)
@@ -510,13 +552,11 @@ SYSCALL_DEFINE2(pidfd_open, pid_t, pid, unsigned int, flags) · 6 unmodified lines
510 if (!p)552 if (!p)
511 return -ESRCH;553 return -ESRCH;
512 554
513 ret = 0;555 if (pid_has_task(p, PIDTYPE_TGID))
514 rcu_read_lock();556 fd = pidfd_create(p);
515 if (!pid_task(p, PIDTYPE_TGID))557 else
516 ret = -EINVAL;558 fd = -EINVAL;
517 rcu_read_unlock();
518 559
519 fd = ret ?: pidfd_create(p);
520 put_pid(p);560 put_pid(p);
521 return fd;561 return fd;
522}562}
kernel/pid_namespace.c+0−2
@@ -26,8 +26,6 @@ · 25 unmodified lines
26 26
27static DEFINE_MUTEX(pid_caches_mutex);27static DEFINE_MUTEX(pid_caches_mutex);
28static struct kmem_cache *pid_ns_cachep;28static struct kmem_cache *pid_ns_cachep;
29/* MAX_PID_NS_LEVEL is needed for limiting size of 'struct pid' */
30#define MAX_PID_NS_LEVEL 32
31/* Write once array, filled from the beginning. */29/* Write once array, filled from the beginning. */
32static struct kmem_cache *pid_cache[MAX_PID_NS_LEVEL];30static struct kmem_cache *pid_cache[MAX_PID_NS_LEVEL];
33 31
tools/testing/selftests/Makefile+1−0
@@ -5,6 +5,7 @@ TARGETS += bpf · 4 unmodified lines
5TARGETS += breakpoints5TARGETS += breakpoints
6TARGETS += capabilities6TARGETS += capabilities
7TARGETS += cgroup7TARGETS += cgroup
8TARGETS += clone3
8TARGETS += cpufreq9TARGETS += cpufreq
9TARGETS += cpu-hotplug10TARGETS += cpu-hotplug
10TARGETS += drivers/dma-buf11TARGETS += drivers/dma-buf
tools/testing/selftests/clone3/.gitignore+3−0
@@ -0,0 +1,3 @@
1clone3
2clone3_clear_sighand
3clone3_set_tid
tools/testing/selftests/clone3/Makefile+6−0
@@ -0,0 +1,6 @@
1# SPDX-License-Identifier: GPL-2.0
2CFLAGS += -g -I../../../../usr/include/
3
4TEST_GEN_PROGS := clone3 clone3_clear_sighand clone3_set_tid
5
6include ../lib.mk
tools/testing/selftests/clone3/clone3.c+202−0
@@ -0,0 +1,202 @@
1// SPDX-License-Identifier: GPL-2.0
2
3/* Based on Christian Brauner's clone3() example */
4
5#define _GNU_SOURCE
6#include <errno.h>
7#include <inttypes.h>
8#include <linux/types.h>
9#include <linux/sched.h>
10#include <stdint.h>
11#include <stdio.h>
12#include <stdlib.h>
13#include <sys/syscall.h>
14#include <sys/types.h>
15#include <sys/un.h>
16#include <sys/wait.h>
17#include <unistd.h>
18#include <sched.h>
19
20#include "../kselftest.h"
21#include "clone3_selftests.h"
22
23/*
24 * Different sizes of struct clone_args
25 */
26#ifndef CLONE3_ARGS_SIZE_V0
27#define CLONE3_ARGS_SIZE_V0 64
28#endif
29
30enum test_mode {
31 CLONE3_ARGS_NO_TEST,
32 CLONE3_ARGS_ALL_0,
33 CLONE3_ARGS_INVAL_EXIT_SIGNAL_BIG,
34 CLONE3_ARGS_INVAL_EXIT_SIGNAL_NEG,
35 CLONE3_ARGS_INVAL_EXIT_SIGNAL_CSIG,
36 CLONE3_ARGS_INVAL_EXIT_SIGNAL_NSIG,
37};
38
39static int call_clone3(uint64_t flags, size_t size, enum test_mode test_mode)
40{
41 struct clone_args args = {
42 .flags = flags,
43 .exit_signal = SIGCHLD,
44 };
45
46 struct clone_args_extended {
47 struct clone_args args;
48 __aligned_u64 excess_space[2];
49 } args_ext;
50
51 pid_t pid = -1;
52 int status;
53
54 memset(&args_ext, 0, sizeof(args_ext));
55 if (size > sizeof(struct clone_args))
56 args_ext.excess_space[1] = 1;
57
58 if (size == 0)
59 size = sizeof(struct clone_args);
60
61 switch (test_mode) {
62 case CLONE3_ARGS_ALL_0:
63 args.flags = 0;
64 args.exit_signal = 0;
65 break;
66 case CLONE3_ARGS_INVAL_EXIT_SIGNAL_BIG:
67 args.exit_signal = 0xbadc0ded00000000ULL;
68 break;
69 case CLONE3_ARGS_INVAL_EXIT_SIGNAL_NEG:
70 args.exit_signal = 0x0000000080000000ULL;
71 break;
72 case CLONE3_ARGS_INVAL_EXIT_SIGNAL_CSIG:
73 args.exit_signal = 0x0000000000000100ULL;
74 break;
75 case CLONE3_ARGS_INVAL_EXIT_SIGNAL_NSIG:
76 args.exit_signal = 0x00000000000000f0ULL;
77 break;
78 }
79
80 memcpy(&args_ext.args, &args, sizeof(struct clone_args));
81
82 pid = sys_clone3((struct clone_args *)&args_ext, size);
83 if (pid < 0) {
84 ksft_print_msg("%s - Failed to create new process\n",
85 strerror(errno));
86 return -errno;
87 }
88
89 if (pid == 0) {
90 ksft_print_msg("I am the child, my PID is %d\n", getpid());
91 _exit(EXIT_SUCCESS);
92 }
93
94 ksft_print_msg("I am the parent (%d). My child's pid is %d\n",
95 getpid(), pid);
96
97 if (waitpid(-1, &status, __WALL) < 0) {
98 ksft_print_msg("Child returned %s\n", strerror(errno));
99 return -errno;
100 }
101 if (WEXITSTATUS(status))
102 return WEXITSTATUS(status);
103
104 return 0;
105}
106
107static void test_clone3(uint64_t flags, size_t size, int expected,
108 enum test_mode test_mode)
109{
110 int ret;
111
112 ksft_print_msg(
113 "[%d] Trying clone3() with flags %#" PRIx64 " (size %zu)\n",
114 getpid(), flags, size);
115 ret = call_clone3(flags, size, test_mode);
116 ksft_print_msg("[%d] clone3() with flags says: %d expected %d\n",
117 getpid(), ret, expected);
118 if (ret != expected)
119 ksft_test_result_fail(
120 "[%d] Result (%d) is different than expected (%d)\n",
121 getpid(), ret, expected);
122 else
123 ksft_test_result_pass(
124 "[%d] Result (%d) matches expectation (%d)\n",
125 getpid(), ret, expected);
126}
127
128int main(int argc, char *argv[])
129{
130 pid_t pid;
131
132 uid_t uid = getuid();
133
134 test_clone3_supported();
135 ksft_print_header();
136 ksft_set_plan(17);
137
138 /* Just a simple clone3() should return 0.*/
139 test_clone3(0, 0, 0, CLONE3_ARGS_NO_TEST);
140
141 /* Do a clone3() in a new PID NS.*/
142 if (uid == 0)
143 test_clone3(CLONE_NEWPID, 0, 0, CLONE3_ARGS_NO_TEST);
144 else
145 ksft_test_result_skip("Skipping clone3() with CLONE_NEWPID\n");
146
147 /* Do a clone3() with CLONE3_ARGS_SIZE_V0. */
148 test_clone3(0, CLONE3_ARGS_SIZE_V0, 0, CLONE3_ARGS_NO_TEST);
149
150 /* Do a clone3() with CLONE3_ARGS_SIZE_V0 - 8 */
151 test_clone3(0, CLONE3_ARGS_SIZE_V0 - 8, -EINVAL, CLONE3_ARGS_NO_TEST);
152
153 /* Do a clone3() with sizeof(struct clone_args) + 8 */
154 test_clone3(0, sizeof(struct clone_args) + 8, 0, CLONE3_ARGS_NO_TEST);
155
156 /* Do a clone3() with exit_signal having highest 32 bits non-zero */
157 test_clone3(0, 0, -EINVAL, CLONE3_ARGS_INVAL_EXIT_SIGNAL_BIG);
158
159 /* Do a clone3() with negative 32-bit exit_signal */
160 test_clone3(0, 0, -EINVAL, CLONE3_ARGS_INVAL_EXIT_SIGNAL_NEG);
161
162 /* Do a clone3() with exit_signal not fitting into CSIGNAL mask */
163 test_clone3(0, 0, -EINVAL, CLONE3_ARGS_INVAL_EXIT_SIGNAL_CSIG);
164
165 /* Do a clone3() with NSIG < exit_signal < CSIG */
166 test_clone3(0, 0, -EINVAL, CLONE3_ARGS_INVAL_EXIT_SIGNAL_NSIG);
167
168 test_clone3(0, sizeof(struct clone_args) + 8, 0, CLONE3_ARGS_ALL_0);
169
170 test_clone3(0, sizeof(struct clone_args) + 16, -E2BIG,
171 CLONE3_ARGS_ALL_0);
172
173 test_clone3(0, sizeof(struct clone_args) * 2, -E2BIG,
174 CLONE3_ARGS_ALL_0);
175
176 /* Do a clone3() with > page size */
177 test_clone3(0, getpagesize() + 8, -E2BIG, CLONE3_ARGS_NO_TEST);
178
179 /* Do a clone3() with CLONE3_ARGS_SIZE_V0 in a new PID NS. */
180 if (uid == 0)
181 test_clone3(CLONE_NEWPID, CLONE3_ARGS_SIZE_V0, 0,
182 CLONE3_ARGS_NO_TEST);
183 else
184 ksft_test_result_skip("Skipping clone3() with CLONE_NEWPID\n");
185
186 /* Do a clone3() with CLONE3_ARGS_SIZE_V0 - 8 in a new PID NS */
187 test_clone3(CLONE_NEWPID, CLONE3_ARGS_SIZE_V0 - 8, -EINVAL,
188 CLONE3_ARGS_NO_TEST);
189
190 /* Do a clone3() with sizeof(struct clone_args) + 8 in a new PID NS */
191 if (uid == 0)
192 test_clone3(CLONE_NEWPID, sizeof(struct clone_args) + 8, 0,
193 CLONE3_ARGS_NO_TEST);
194 else
195 ksft_test_result_skip("Skipping clone3() with CLONE_NEWPID\n");
196
197 /* Do a clone3() with > page size in a new PID NS */
198 test_clone3(CLONE_NEWPID, getpagesize() + 8, -E2BIG,
199 CLONE3_ARGS_NO_TEST);
200
201 return !ksft_get_fail_cnt() ? ksft_exit_pass() : ksft_exit_fail();
202}
tools/testing/selftests/clone3/clone3_clear_sighand.c+129−0
@@ -0,0 +1,129 @@
1/* SPDX-License-Identifier: GPL-2.0 */
2
3#define _GNU_SOURCE
4#include <errno.h>
5#include <sched.h>
6#include <signal.h>
7#include <stdio.h>
8#include <stdlib.h>
9#include <string.h>
10#include <unistd.h>
11#include <linux/sched.h>
12#include <linux/types.h>
13#include <sys/syscall.h>
14#include <sys/wait.h>
15
16#include "../kselftest.h"
17#include "clone3_selftests.h"
18
19#ifndef CLONE_CLEAR_SIGHAND
20#define CLONE_CLEAR_SIGHAND 0x100000000ULL
21#endif
22
23static void nop_handler(int signo)
24{
25}
26
27static int wait_for_pid(pid_t pid)
28{
29 int status, ret;
30
31again:
32 ret = waitpid(pid, &status, 0);
33 if (ret == -1) {
34 if (errno == EINTR)
35 goto again;
36
37 return -1;
38 }
39
40 if (!WIFEXITED(status))
41 return -1;
42
43 return WEXITSTATUS(status);
44}
45
46static void test_clone3_clear_sighand(void)
47{
48 int ret;
49 pid_t pid;
50 struct clone_args args = {};
51 struct sigaction act;
52
53 /*
54 * Check that CLONE_CLEAR_SIGHAND and CLONE_SIGHAND are mutually
55 * exclusive.
56 */
57 args.flags |= CLONE_CLEAR_SIGHAND | CLONE_SIGHAND;
58 args.exit_signal = SIGCHLD;
59 pid = sys_clone3(&args, sizeof(args));
60 if (pid > 0)
61 ksft_exit_fail_msg(
62 "clone3(CLONE_CLEAR_SIGHAND | CLONE_SIGHAND) succeeded\n");
63
64 act.sa_handler = nop_handler;
65 ret = sigemptyset(&act.sa_mask);
66 if (ret < 0)
67 ksft_exit_fail_msg("%s - sigemptyset() failed\n",
68 strerror(errno));
69
70 act.sa_flags = 0;
71
72 /* Register signal handler for SIGUSR1 */
73 ret = sigaction(SIGUSR1, &act, NULL);
74 if (ret < 0)
75 ksft_exit_fail_msg(
76 "%s - sigaction(SIGUSR1, &act, NULL) failed\n",
77 strerror(errno));
78
79 /* Register signal handler for SIGUSR2 */
80 ret = sigaction(SIGUSR2, &act, NULL);
81 if (ret < 0)
82 ksft_exit_fail_msg(
83 "%s - sigaction(SIGUSR2, &act, NULL) failed\n",
84 strerror(errno));
85
86 /* Check that CLONE_CLEAR_SIGHAND works. */
87 args.flags = CLONE_CLEAR_SIGHAND;
88 pid = sys_clone3(&args, sizeof(args));
89 if (pid < 0)
90 ksft_exit_fail_msg("%s - clone3(CLONE_CLEAR_SIGHAND) failed\n",
91 strerror(errno));
92
93 if (pid == 0) {
94 ret = sigaction(SIGUSR1, NULL, &act);
95 if (ret < 0)
96 exit(EXIT_FAILURE);
97
98 if (act.sa_handler != SIG_DFL)
99 exit(EXIT_FAILURE);
100
101 ret = sigaction(SIGUSR2, NULL, &act);
102 if (ret < 0)
103 exit(EXIT_FAILURE);
104
105 if (act.sa_handler != SIG_DFL)
106 exit(EXIT_FAILURE);
107
108 exit(EXIT_SUCCESS);
109 }
110
111 ret = wait_for_pid(pid);
112 if (ret)
113 ksft_exit_fail_msg(
114 "Failed to clear signal handler for child process\n");
115
116 ksft_test_result_pass("Cleared signal handlers for child process\n");
117}
118
119int main(int argc, char **argv)
120{
121 ksft_print_header();
122 test_clone3_supported();
123
124 ksft_set_plan(1);
125
126 test_clone3_clear_sighand();
127
128 return ksft_exit_pass();
129}
tools/testing/selftests/clone3/clone3_selftests.h+63−0
@@ -0,0 +1,63 @@
1/* SPDX-License-Identifier: GPL-2.0 */
2
3#ifndef _CLONE3_SELFTESTS_H
4#define _CLONE3_SELFTESTS_H
5
6#define _GNU_SOURCE
7#include <sched.h>
8#include <stdint.h>
9#include <syscall.h>
10#include <linux/types.h>
11
12#define ptr_to_u64(ptr) ((__u64)((uintptr_t)(ptr)))
13
14#ifndef __NR_clone3
15#define __NR_clone3 -1
16struct clone_args {
17 __aligned_u64 flags;
18 __aligned_u64 pidfd;
19 __aligned_u64 child_tid;
20 __aligned_u64 parent_tid;
21 __aligned_u64 exit_signal;
22 __aligned_u64 stack;
23 __aligned_u64 stack_size;
24 __aligned_u64 tls;
25 __aligned_u64 set_tid;
26 __aligned_u64 set_tid_size;
27};
28#endif
29
30static pid_t sys_clone3(struct clone_args *args, size_t size)
31{
32 fflush(stdout);
33 fflush(stderr);
34 return syscall(__NR_clone3, args, size);
35}
36
37static inline void test_clone3_supported(void)
38{
39 pid_t pid;
40 struct clone_args args = {};
41
42 if (__NR_clone3 < 0)
43 ksft_exit_skip("clone3() syscall is not supported\n");
44
45 /* Set to something that will always cause EINVAL. */
46 args.exit_signal = -1;
47 pid = sys_clone3(&args, sizeof(args));
48 if (!pid)
49 exit(EXIT_SUCCESS);
50
51 if (pid > 0) {
52 wait(NULL);
53 ksft_exit_fail_msg(
54 "Managed to create child process with invalid exit_signal\n");
55 }
56
57 if (errno == ENOSYS)
58 ksft_exit_skip("clone3() syscall is not supported\n");
59
60 ksft_print_msg("clone3() syscall supported\n");
61}
62
63#endif /* _CLONE3_SELFTESTS_H */
tools/testing/selftests/clone3/clone3_set_tid.c+397−0
@@ -0,0 +1,397 @@
1// SPDX-License-Identifier: GPL-2.0
2
3/*
4 * Based on Christian Brauner's clone3() example.
5 * These tests are assuming to be running in the host's
6 * PID namespace.
7 */
8
9#define _GNU_SOURCE
10#include <errno.h>
11#include <linux/types.h>
12#include <linux/sched.h>
13#include <stdio.h>
14#include <stdlib.h>
15#include <stdbool.h>
16#include <sys/syscall.h>
17#include <sys/types.h>
18#include <sys/un.h>
19#include <sys/wait.h>
20#include <unistd.h>
21#include <sched.h>
22
23#include "../kselftest.h"
24#include "clone3_selftests.h"
25
26#ifndef MAX_PID_NS_LEVEL
27#define MAX_PID_NS_LEVEL 32
28#endif
29
30static int pipe_1[2];
31static int pipe_2[2];
32
33static void child_exit(int ret)
34{
35 fflush(stdout);
36 fflush(stderr);
37 _exit(ret);
38}
39
40static int call_clone3_set_tid(pid_t *set_tid,
41 size_t set_tid_size,
42 int flags,
43 int expected_pid,
44 bool wait_for_it)
45{
46 int status;
47 pid_t pid = -1;
48
49 struct clone_args args = {
50 .flags = flags,
51 .exit_signal = SIGCHLD,
52 .set_tid = ptr_to_u64(set_tid),
53 .set_tid_size = set_tid_size,
54 };
55
56 pid = sys_clone3(&args, sizeof(struct clone_args));
57 if (pid < 0) {
58 ksft_print_msg("%s - Failed to create new process\n",
59 strerror(errno));
60 return -errno;
61 }
62
63 if (pid == 0) {
64 int ret;
65 char tmp = 0;
66 int exit_code = EXIT_SUCCESS;
67
68 ksft_print_msg("I am the child, my PID is %d (expected %d)\n",
69 getpid(), set_tid[0]);
70 if (wait_for_it) {
71 ksft_print_msg("[%d] Child is ready and waiting\n",
72 getpid());
73
74 /* Signal the parent that the child is ready */
75 close(pipe_1[0]);
76 ret = write(pipe_1[1], &tmp, 1);
77 if (ret != 1) {
78 ksft_print_msg(
79 "Writing to pipe returned %d", ret);
80 exit_code = EXIT_FAILURE;
81 }
82 close(pipe_1[1]);
83 close(pipe_2[1]);
84 ret = read(pipe_2[0], &tmp, 1);
85 if (ret != 1) {
86 ksft_print_msg(
87 "Reading from pipe returned %d", ret);
88 exit_code = EXIT_FAILURE;
89 }
90 close(pipe_2[0]);
91 }
92
93 if (set_tid[0] != getpid())
94 child_exit(EXIT_FAILURE);
95 child_exit(exit_code);
96 }
97
98 if (expected_pid == 0 || expected_pid == pid) {
99 ksft_print_msg("I am the parent (%d). My child's pid is %d\n",
100 getpid(), pid);
101 } else {
102 ksft_print_msg(
103 "Expected child pid %d does not match actual pid %d\n",
104 expected_pid, pid);
105 return -1;
106 }
107
108 if (waitpid(pid, &status, 0) < 0) {
109 ksft_print_msg("Child returned %s\n", strerror(errno));
110 return -errno;
111 }
112
113 if (!WIFEXITED(status))
114 return -1;
115
116 return WEXITSTATUS(status);
117}
118
119static void test_clone3_set_tid(pid_t *set_tid,
120 size_t set_tid_size,
121 int flags,
122 int expected,
123 int expected_pid,
124 bool wait_for_it)
125{
126 int ret;
127
128 ksft_print_msg(
129 "[%d] Trying clone3() with CLONE_SET_TID to %d and 0x%x\n",
130 getpid(), set_tid[0], flags);
131 ret = call_clone3_set_tid(set_tid, set_tid_size, flags, expected_pid,
132 wait_for_it);
133 ksft_print_msg(
134 "[%d] clone3() with CLONE_SET_TID %d says :%d - expected %d\n",
135 getpid(), set_tid[0], ret, expected);
136 if (ret != expected)
137 ksft_test_result_fail(
138 "[%d] Result (%d) is different than expected (%d)\n",
139 getpid(), ret, expected);
140 else
141 ksft_test_result_pass(
142 "[%d] Result (%d) matches expectation (%d)\n",
143 getpid(), ret, expected);
144}
145int main(int argc, char *argv[])
146{
147 FILE *f;
148 char buf;
149 char *line;
150 int status;
151 int ret = -1;
152 size_t len = 0;
153 int pid_max = 0;
154 uid_t uid = getuid();
155 char proc_path[100] = {0};
156 pid_t pid, ns1, ns2, ns3, ns_pid;
157 pid_t set_tid[MAX_PID_NS_LEVEL * 2];
158
159 ksft_print_header();
160 test_clone3_supported();
161 ksft_set_plan(29);
162
163 if (pipe(pipe_1) < 0 || pipe(pipe_2) < 0)
164 ksft_exit_fail_msg("pipe() failed\n");
165
166 f = fopen("/proc/sys/kernel/pid_max", "r");
167 if (f == NULL)
168 ksft_exit_fail_msg(
169 "%s - Could not open /proc/sys/kernel/pid_max\n",
170 strerror(errno));
171 fscanf(f, "%d", &pid_max);
172 fclose(f);
173 ksft_print_msg("/proc/sys/kernel/pid_max %d\n", pid_max);
174
175 /* Try invalid settings */
176 memset(&set_tid, 0, sizeof(set_tid));
177 test_clone3_set_tid(set_tid, MAX_PID_NS_LEVEL + 1, 0, -EINVAL, 0, 0);
178
179 test_clone3_set_tid(set_tid, MAX_PID_NS_LEVEL * 2, 0, -EINVAL, 0, 0);
180
181 test_clone3_set_tid(set_tid, MAX_PID_NS_LEVEL * 2 + 1, 0,
182 -EINVAL, 0, 0);
183
184 test_clone3_set_tid(set_tid, MAX_PID_NS_LEVEL * 42, 0, -EINVAL, 0, 0);
185
186 /*
187 * This can actually work if this test running in a MAX_PID_NS_LEVEL - 1
188 * nested PID namespace.
189 */
190 test_clone3_set_tid(set_tid, MAX_PID_NS_LEVEL - 1, 0, -EINVAL, 0, 0);
191
192 memset(&set_tid, 0xff, sizeof(set_tid));
193 test_clone3_set_tid(set_tid, MAX_PID_NS_LEVEL + 1, 0, -EINVAL, 0, 0);
194
195 test_clone3_set_tid(set_tid, MAX_PID_NS_LEVEL * 2, 0, -EINVAL, 0, 0);
196
197 test_clone3_set_tid(set_tid, MAX_PID_NS_LEVEL * 2 + 1, 0,
198 -EINVAL, 0, 0);
199
200 test_clone3_set_tid(set_tid, MAX_PID_NS_LEVEL * 42, 0, -EINVAL, 0, 0);
201
202 /*
203 * This can actually work if this test running in a MAX_PID_NS_LEVEL - 1
204 * nested PID namespace.
205 */
206 test_clone3_set_tid(set_tid, MAX_PID_NS_LEVEL - 1, 0, -EINVAL, 0, 0);
207
208 memset(&set_tid, 0, sizeof(set_tid));
209 /* Try with an invalid PID */
210 set_tid[0] = 0;
211 test_clone3_set_tid(set_tid, 1, 0, -EINVAL, 0, 0);
212
213 set_tid[0] = -1;
214 test_clone3_set_tid(set_tid, 1, 0, -EINVAL, 0, 0);
215
216 /* Claim that the set_tid array actually contains 2 elements. */
217 test_clone3_set_tid(set_tid, 2, 0, -EINVAL, 0, 0);
218
219 /* Try it in a new PID namespace */
220 if (uid == 0)
221 test_clone3_set_tid(set_tid, 1, CLONE_NEWPID, -EINVAL, 0, 0);
222 else
223 ksft_test_result_skip("Clone3() with set_tid requires root\n");
224
225 /* Try with a valid PID (1) this should return -EEXIST. */
226 set_tid[0] = 1;
227 if (uid == 0)
228 test_clone3_set_tid(set_tid, 1, 0, -EEXIST, 0, 0);
229 else
230 ksft_test_result_skip("Clone3() with set_tid requires root\n");
231
232 /* Try it in a new PID namespace */
233 if (uid == 0)
234 test_clone3_set_tid(set_tid, 1, CLONE_NEWPID, 0, 0, 0);
235 else
236 ksft_test_result_skip("Clone3() with set_tid requires root\n");
237
238 /* pid_max should fail everywhere */
239 set_tid[0] = pid_max;
240 test_clone3_set_tid(set_tid, 1, 0, -EINVAL, 0, 0);
241
242 if (uid == 0)
243 test_clone3_set_tid(set_tid, 1, CLONE_NEWPID, -EINVAL, 0, 0);
244 else
245 ksft_test_result_skip("Clone3() with set_tid requires root\n");
246
247 if (uid != 0) {
248 /*
249 * All remaining tests require root. Tell the framework
250 * that all those tests are skipped as non-root.
251 */
252 ksft_cnt.ksft_xskip += ksft_plan - ksft_test_num();
253 goto out;
254 }
255
256 /* Find the current active PID */
257 pid = fork();
258 if (pid == 0) {
259 ksft_print_msg("Child has PID %d\n", getpid());
260 child_exit(EXIT_SUCCESS);
261 }
262 if (waitpid(pid, &status, 0) < 0)
263 ksft_exit_fail_msg("Waiting for child %d failed", pid);
264
265 /* After the child has finished, its PID should be free. */
266 set_tid[0] = pid;
267 test_clone3_set_tid(set_tid, 1, 0, 0, 0, 0);
268
269 /* This should fail as there is no PID 1 in that namespace */
270 test_clone3_set_tid(set_tid, 1, CLONE_NEWPID, -EINVAL, 0, 0);
271
272 /*
273 * Creating a process with PID 1 in the newly created most nested
274 * PID namespace and PID 'pid' in the parent PID namespace. This
275 * needs to work.
276 */
277 set_tid[0] = 1;
278 set_tid[1] = pid;
279 test_clone3_set_tid(set_tid, 2, CLONE_NEWPID, 0, pid, 0);
280
281 ksft_print_msg("unshare PID namespace\n");
282 if (unshare(CLONE_NEWPID) == -1)
283 ksft_exit_fail_msg("unshare(CLONE_NEWPID) failed: %s\n",
284 strerror(errno));
285
286 set_tid[0] = pid;
287
288 /* This should fail as there is no PID 1 in that namespace */
289 test_clone3_set_tid(set_tid, 1, 0, -EINVAL, 0, 0);
290
291 /* Let's create a PID 1 */
292 ns_pid = fork();
293 if (ns_pid == 0) {
294 /*
295 * This and the next test cases check that all pid-s are
296 * released on error paths.
297 */
298 set_tid[0] = 43;
299 set_tid[1] = -1;
300 test_clone3_set_tid(set_tid, 2, 0, -EINVAL, 0, 0);
301
302 set_tid[0] = 43;
303 set_tid[1] = pid;
304 test_clone3_set_tid(set_tid, 2, 0, 0, 43, 0);
305
306 ksft_print_msg("Child in PID namespace has PID %d\n", getpid());
307 set_tid[0] = 2;
308 test_clone3_set_tid(set_tid, 1, 0, 0, 2, 0);
309
310 set_tid[0] = 1;
311 set_tid[1] = -1;
312 set_tid[2] = pid;
313 /* This should fail as there is invalid PID at level '1'. */
314 test_clone3_set_tid(set_tid, 3, CLONE_NEWPID, -EINVAL, 0, 0);
315
316 set_tid[0] = 1;
317 set_tid[1] = 42;
318 set_tid[2] = pid;
319 /*
320 * This should fail as there are not enough active PID
321 * namespaces. Again assuming this is running in the host's
322 * PID namespace. Not yet nested.
323 */
324 test_clone3_set_tid(set_tid, 4, CLONE_NEWPID, -EINVAL, 0, 0);
325
326 /*
327 * This should work and from the parent we should see
328 * something like 'NSpid: pid 42 1'.
329 */
330 test_clone3_set_tid(set_tid, 3, CLONE_NEWPID, 0, 42, true);
331
332 child_exit(ksft_cnt.ksft_fail);
333 }
334
335 close(pipe_1[1]);
336 close(pipe_2[0]);
337 while (read(pipe_1[0], &buf, 1) > 0) {
338 ksft_print_msg("[%d] Child is ready and waiting\n", getpid());
339 break;
340 }
341
342 snprintf(proc_path, sizeof(proc_path), "/proc/%d/status", pid);
343 f = fopen(proc_path, "r");
344 if (f == NULL)
345 ksft_exit_fail_msg(
346 "%s - Could not open %s\n",
347 strerror(errno), proc_path);
348
349 while (getline(&line, &len, f) != -1) {
350 if (strstr(line, "NSpid")) {
351 int i;
352
353 /* Verify that all generated PIDs are as expected. */
354 i = sscanf(line, "NSpid:\t%d\t%d\t%d",
355 &ns3, &ns2, &ns1);
356 if (i != 3) {
357 ksft_print_msg(
358 "Unexpected 'NSPid:' entry: %s",
359 line);
360 ns1 = ns2 = ns3 = 0;
361 }
362 break;
363 }
364 }
365 fclose(f);
366 free(line);
367 close(pipe_2[0]);
368
369 /* Tell the clone3()'d child to finish. */
370 write(pipe_2[1], &buf, 1);
371 close(pipe_2[1]);
372
373 if (waitpid(ns_pid, &status, 0) < 0) {
374 ksft_print_msg("Child returned %s\n", strerror(errno));
375 ret = -errno;
376 goto out;
377 }
378
379 if (!WIFEXITED(status))
380 ksft_test_result_fail("Child error\n");
381
382 ksft_cnt.ksft_pass += 6 - (ksft_cnt.ksft_fail - WEXITSTATUS(status));
383 ksft_cnt.ksft_fail = WEXITSTATUS(status);
384
385 if (ns3 == pid && ns2 == 42 && ns1 == 1)
386 ksft_test_result_pass(
387 "PIDs in all namespaces as expected (%d,%d,%d)\n",
388 ns3, ns2, ns1);
389 else
390 ksft_test_result_fail(
391 "PIDs in all namespaces not as expected (%d,%d,%d)\n",
392 ns3, ns2, ns1);
393out:
394 ret = 0;
395
396 return !ret ? ksft_exit_pass() : ksft_exit_fail();
397}
tools/testing/selftests/pidfd/Makefile+1−1
@@ -1,7 +1,7 @@
1# SPDX-License-Identifier: GPL-2.0-only1# SPDX-License-Identifier: GPL-2.0-only
2CFLAGS += -g -I../../../../usr/include/ -pthread2CFLAGS += -g -I../../../../usr/include/ -pthread
3 3
4TEST_GEN_PROGS := pidfd_test pidfd_open_test pidfd_poll_test pidfd_wait4TEST_GEN_PROGS := pidfd_test pidfd_fdinfo_test pidfd_open_test pidfd_poll_test pidfd_wait
5 5
6include ../lib.mk6include ../lib.mk
7 7
tools/testing/selftests/pidfd/pidfd_fdinfo_test.c+296−0
@@ -0,0 +1,296 @@
1// SPDX-License-Identifier: GPL-2.0
2
3#define _GNU_SOURCE
4#include <assert.h>
5#include <errno.h>
6#include <fcntl.h>
7#include <linux/types.h>
8#include <sched.h>
9#include <signal.h>
10#include <stdio.h>
11#include <stdlib.h>
12#include <string.h>
13#include <syscall.h>
14#include <sys/wait.h>
15
16#include "pidfd.h"
17#include "../kselftest.h"
18
19struct error {
20 int code;
21 char msg[512];
22};
23
24static int error_set(struct error *err, int code, const char *fmt, ...)
25{
26 va_list args;
27 int r;
28
29 if (code == PIDFD_PASS || !err || err->code != PIDFD_PASS)
30 return code;
31
32 err->code = code;
33 va_start(args, fmt);
34 r = vsnprintf(err->msg, sizeof(err->msg), fmt, args);
35 assert((size_t)r < sizeof(err->msg));
36 va_end(args);
37
38 return code;
39}
40
41static void error_report(struct error *err, const char *test_name)
42{
43 switch (err->code) {
44 case PIDFD_ERROR:
45 ksft_exit_fail_msg("%s test: Fatal: %s\n", test_name, err->msg);
46 break;
47
48 case PIDFD_FAIL:
49 /* will be: not ok %d # error %s test: %s */
50 ksft_test_result_error("%s test: %s\n", test_name, err->msg);
51 break;
52
53 case PIDFD_SKIP:
54 /* will be: not ok %d # SKIP %s test: %s */
55 ksft_test_result_skip("%s test: %s\n", test_name, err->msg);
56 break;
57
58 case PIDFD_XFAIL:
59 ksft_test_result_pass("%s test: Expected failure: %s\n",
60 test_name, err->msg);
61 break;
62
63 case PIDFD_PASS:
64 ksft_test_result_pass("%s test: Passed\n");
65 break;
66
67 default:
68 ksft_exit_fail_msg("%s test: Unknown code: %d %s\n",
69 test_name, err->code, err->msg);
70 break;
71 }
72}
73
74static inline int error_check(struct error *err, const char *test_name)
75{
76 /* In case of error we bail out and terminate the test program */
77 if (err->code == PIDFD_ERROR)
78 error_report(err, test_name);
79
80 return err->code;
81}
82
83struct child {
84 pid_t pid;
85 int fd;
86};
87
88static struct child clone_newns(int (*fn)(void *), void *args,
89 struct error *err)
90{
91 static int flags = CLONE_PIDFD | CLONE_NEWPID | CLONE_NEWNS | SIGCHLD;
92 size_t stack_size = 1024;
93 char *stack[1024] = { 0 };
94 struct child ret;
95
96 if (!(flags & CLONE_NEWUSER) && geteuid() != 0)
97 flags |= CLONE_NEWUSER;
98
99#ifdef __ia64__
100 ret.pid = __clone2(fn, stack, stack_size, flags, args, &ret.fd);
101#else
102 ret.pid = clone(fn, stack + stack_size, flags, args, &ret.fd);
103#endif
104
105 if (ret.pid < 0) {
106 error_set(err, PIDFD_ERROR, "clone failed (ret %d, errno %d)",
107 ret.fd, errno);
108 return ret;
109 }
110
111 ksft_print_msg("New child: %d, fd: %d\n", ret.pid, ret.fd);
112
113 return ret;
114}
115
116static inline void child_close(struct child *child)
117{
118 close(child->fd);
119}
120
121static inline int child_join(struct child *child, struct error *err)
122{
123 int r;
124
125 r = wait_for_pid(child->pid);
126 if (r < 0)
127 error_set(err, PIDFD_ERROR, "waitpid failed (ret %d, errno %d)",
128 r, errno);
129 else if (r > 0)
130 error_set(err, r, "child %d reported: %d", child->pid, r);
131
132 return r;
133}
134
135static inline int child_join_close(struct child *child, struct error *err)
136{
137 child_close(child);
138 return child_join(child, err);
139}
140
141static inline void trim_newline(char *str)
142{
143 char *pos = strrchr(str, '\n');
144
145 if (pos)
146 *pos = '\0';
147}
148
149static int verify_fdinfo(int pidfd, struct error *err, const char *prefix,
150 size_t prefix_len, const char *expect, ...)
151{
152 char buffer[512] = {0, };
153 char path[512] = {0, };
154 va_list args;
155 FILE *f;
156 char *line = NULL;
157 size_t n = 0;
158 int found = 0;
159 int r;
160
161 va_start(args, expect);
162 r = vsnprintf(buffer, sizeof(buffer), expect, args);
163 assert((size_t)r < sizeof(buffer));
164 va_end(args);
165
166 snprintf(path, sizeof(path), "/proc/self/fdinfo/%d", pidfd);
167 f = fopen(path, "re");
168 if (!f)
169 return error_set(err, PIDFD_ERROR, "fdinfo open failed for %d",
170 pidfd);
171
172 while (getline(&line, &n, f) != -1) {
173 char *val;
174
175 if (strncmp(line, prefix, prefix_len))
176 continue;
177
178 found = 1;
179
180 val = line + prefix_len;
181 r = strcmp(val, buffer);
182 if (r != 0) {
183 trim_newline(line);
184 trim_newline(buffer);
185 error_set(err, PIDFD_FAIL, "%s '%s' != '%s'",
186 prefix, val, buffer);
187 }
188 break;
189 }
190
191 free(line);
192 fclose(f);
193
194 if (found == 0)
195 return error_set(err, PIDFD_FAIL, "%s not found for fd %d",
196 prefix, pidfd);
197
198 return PIDFD_PASS;
199}
200
201static int child_fdinfo_nspid_test(void *args)
202{
203 struct error err;
204 int pidfd;
205 int r;
206
207 /* if we got no fd for the sibling, we are done */
208 if (!args)
209 return PIDFD_PASS;
210
211 /* verify that we can not resolve the pidfd for a process
212 * in a sibling pid namespace, i.e. a pid namespace it is
213 * not in our or a descended namespace
214 */
215 r = mount(NULL, "/", NULL, MS_REC | MS_PRIVATE, 0);
216 if (r < 0) {
217 ksft_print_msg("Failed to remount / private\n");
218 return PIDFD_ERROR;
219 }
220
221 (void)umount2("/proc", MNT_DETACH);
222 r = mount("proc", "/proc", "proc", 0, NULL);
223 if (r < 0) {
224 ksft_print_msg("Failed to remount /proc\n");
225 return PIDFD_ERROR;
226 }
227
228 pidfd = *(int *)args;
229 r = verify_fdinfo(pidfd, &err, "NSpid:", 6, "\t0\n");
230
231 if (r != PIDFD_PASS)
232 ksft_print_msg("NSpid fdinfo check failed: %s\n", err.msg);
233
234 return r;
235}
236
237static void test_pidfd_fdinfo_nspid(void)
238{
239 struct child a, b;
240 struct error err = {0, };
241 const char *test_name = "pidfd check for NSpid in fdinfo";
242
243 /* Create a new child in a new pid and mount namespace */
244 a = clone_newns(child_fdinfo_nspid_test, NULL, &err);
245 error_check(&err, test_name);
246
247 /* Pass the pidfd representing the first child to the
248 * second child, which will be in a sibling pid namespace,
249 * which means that the fdinfo NSpid entry for the pidfd
250 * should only contain '0'.
251 */
252 b = clone_newns(child_fdinfo_nspid_test, &a.fd, &err);
253 error_check(&err, test_name);
254
255 /* The children will have pid 1 in the new pid namespace,
256 * so the line must be 'NSPid:\t<pid>\t1'.
257 */
258 verify_fdinfo(a.fd, &err, "NSpid:", 6, "\t%d\t%d\n", a.pid, 1);
259 verify_fdinfo(b.fd, &err, "NSpid:", 6, "\t%d\t%d\n", b.pid, 1);
260
261 /* wait for the process, check the exit status and set
262 * 'err' accordingly, if it is not already set.
263 */
264 child_join_close(&a, &err);
265 child_join_close(&b, &err);
266
267 error_report(&err, test_name);
268}
269
270static void test_pidfd_dead_fdinfo(void)
271{
272 struct child a;
273 struct error err = {0, };
274 const char *test_name = "pidfd check fdinfo for dead process";
275
276 /* Create a new child in a new pid and mount namespace */
277 a = clone_newns(child_fdinfo_nspid_test, NULL, &err);
278 error_check(&err, test_name);
279 child_join(&a, &err);
280
281 verify_fdinfo(a.fd, &err, "Pid:", 4, "\t-1\n");
282 verify_fdinfo(a.fd, &err, "NSpid:", 6, "\t-1\n");
283 child_close(&a);
284 error_report(&err, test_name);
285}
286
287int main(int argc, char **argv)
288{
289 ksft_print_header();
290 ksft_set_plan(2);
291
292 test_pidfd_fdinfo_nspid();
293 test_pidfd_dead_fdinfo();
294
295 return ksft_exit_pass();
296}