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
1286112861 T: git git://git.kernel.org/pub/scm/linux/kernel/git/brauner/linux.git
1286212862 F: samples/pidfd/
1286312863 F: tools/testing/selftests/pidfd/
12864+F: tools/testing/selftests/clone3/
1286412865 K: (?i)pidfd
1286512866 K: (?i)clone3
1286612867 K: \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
8585
8686 extern void put_pid(struct pid *pid);
8787 extern struct task_struct *pid_task(struct pid *pid, enum pid_type);
88+static inline bool pid_has_task(struct pid *pid, enum pid_type type)
89+{
90+ return !hlist_empty(&pid->tasks[type]);
91+}
8892 extern struct task_struct *get_pid_task(struct pid *pid, enum pid_type);
8993
9094 extern 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
120124 extern struct pid *find_get_pid(int nr);
121125 extern struct pid *find_ge_pid(int nr, struct pid_namespace *);
122126
123−extern struct pid *alloc_pid(struct pid_namespace *ns);
127+extern struct pid *alloc_pid(struct pid_namespace *ns, pid_t *set_tid,
128+ size_t set_tid_size);
124129 extern void free_pid(struct pid *pid);
125130 extern void disable_pid_allocation(struct pid_namespace *ns);
126131
include/linux/pid_namespace.h+2−0
@@ -12,6 +12,8 @@ · 11 unmodified lines
1212 #include <linux/ns_common.h>
1313 #include <linux/idr.h>
1414
15+/* MAX_PID_NS_LEVEL is needed for limiting size of 'struct pid' */
16+#define MAX_PID_NS_LEVEL 32
1517
1618 struct fs_pin;
1719
include/linux/sched/task.h+3−0
@@ -26,6 +26,9 @@ struct kernel_clone_args { · 25 unmodified lines
2626 unsigned long stack;
2727 unsigned long stack_size;
2828 unsigned long tls;
29+ pid_t *set_tid;
30+ /* Number of elements in *set_tid */
31+ size_t set_tid_size;
2932 };
3033
3134 /*
include/uapi/linux/sched.h+42−22
@@ -33,31 +33,48 @@ · 32 unmodified lines
3333 #define CLONE_NEWNET 0x40000000 /* New network namespace */
3434 #define CLONE_IO 0x80000000 /* Clone io context */
3535
36+/* Flags for the clone3() syscall. */
37+#define CLONE_CLEAR_SIGHAND 0x100000000ULL /* Clear any signal handler and reset to SIG_DFL. */
38+
3639 #ifndef __ASSEMBLY__
3740 /**
3841 * struct clone_args - arguments for the clone3 syscall
39− * @flags: Flags for the new process as listed above.
40− * All flags are valid except for CSIGNAL and
41− * CLONE_DETACHED.
42− * @pidfd: If CLONE_PIDFD is set, a pidfd will be
43− * returned in this argument.
44− * @child_tid: If CLONE_CHILD_SETTID is set, the TID of the
45− * child process will be returned in the child's
46− * memory.
47− * @parent_tid: If CLONE_PARENT_SETTID is set, the TID of
48− * the child process will be returned in the
49− * parent's memory.
50− * @exit_signal: The exit_signal the parent process will be
51− * sent when the child exits.
52− * @stack: Specify the location of the stack for the
53− * child process.
54− * Note, @stack is expected to point to the
55− * lowest address. The stack direction will be
56− * determined by the kernel and set up
57− * appropriately based on @stack_size.
58− * @stack_size: The size of the stack for the child process.
59− * @tls: If CLONE_SETTLS is set, the tls descriptor
60− * is set to tls.
42+ * @flags: Flags for the new process as listed above.
43+ * All flags are valid except for CSIGNAL and
44+ * CLONE_DETACHED.
45+ * @pidfd: If CLONE_PIDFD is set, a pidfd will be
46+ * returned in this argument.
47+ * @child_tid: If CLONE_CHILD_SETTID is set, the TID of the
48+ * child process will be returned in the child's
49+ * memory.
50+ * @parent_tid: If CLONE_PARENT_SETTID is set, the TID of
51+ * the child process will be returned in the
52+ * parent's memory.
53+ * @exit_signal: The exit_signal the parent process will be
54+ * sent when the child exits.
55+ * @stack: Specify the location of the stack for the
56+ * child process.
57+ * Note, @stack is expected to point to the
58+ * lowest address. The stack direction will be
59+ * determined by the kernel and set up
60+ * appropriately based on @stack_size.
61+ * @stack_size: The size of the stack for the child process.
62+ * @tls: If CLONE_SETTLS is set, the tls descriptor
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.
6178 *
6279 * The structure is versioned by size and thus extensible.
6380 * New struct members must go at the end of the struct and
@@ -72,10 +89,13 @@ struct clone_args { · 8 unmodified lines
7289 __aligned_u64 stack;
7390 __aligned_u64 stack_size;
7491 __aligned_u64 tls;
92+ __aligned_u64 set_tid;
93+ __aligned_u64 set_tid_size;
7594 };
7695 #endif
7796
7897 #define CLONE_ARGS_SIZE_VER0 64 /* sizeof first published struct */
98+#define CLONE_ARGS_SIZE_VER1 80 /* sizeof second published struct */
7999
80100 /*
81101 * Scheduling policies
kernel/exit.c+1−1
@@ -1457,7 +1457,7 @@ repeat: · 1456 unmodified lines
14571457 */
14581458 wo->notask_error = -ECHILD;
14591459 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)))
14611461 goto notask;
14621462
14631463 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
15171517 spin_lock_irq(&current->sighand->siglock);
15181518 memcpy(sig->action, current->sighand->action, sizeof(sig->action));
15191519 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+
15201525 return 0;
15211526 }
15221527
@@ -1695,12 +1700,68 @@ static int pidfd_release(struct inode *inode, struct file *file) · 172 unmodified lines
16951700 }
16961701
16971702 #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+ */
16981738 static void pidfd_show_fdinfo(struct seq_file *m, struct file *f)
16991739 {
1700− struct pid_namespace *ns = proc_pid_ns(file_inode(m->file));
17011740 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;
17021755
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
17041765 seq_putc(m, '\n');
17051766 }
17061767 #endif
@@ -2026,7 +2087,8 @@ static __latent_entropy struct task_struct *copy_process( · 319 unmodified lines
20262087 stackleak_task_init(p);
20272088
20282089 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);
20302092 if (IS_ERR(pid)) {
20312093 retval = PTR_ERR(pid);
20322094 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
25292591 {
25302592 int err;
25312593 struct clone_args args;
2594+ pid_t *kset_tid = kargs->set_tid;
25322595
25332596 if (unlikely(usize > PAGE_SIZE))
25342597 return -E2BIG;
@@ -2539,6 +2602,15 @@ noinline static int copy_clone_args_from_user(struct kernel_clone_args *kargs, · 4 unmodified lines
25392602 if (err)
25402603 return err;
25412604
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+
25422614 /*
25432615 * Verify that higher 32bits of exit_signal are unset and that
25442616 * 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
25562628 .stack = args.stack,
25572629 .stack_size = args.stack_size,
25582630 .tls = args.tls,
2631+ .set_tid_size = args.set_tid_size,
25592632 };
25602633
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+
25612641 return 0;
25622642 }
25632643
@@ -2591,11 +2671,8 @@ static inline bool clone3_stack_valid(struct kernel_clone_args *kargs) · 27 unmodified lines
25912671
25922672 static bool clone3_args_valid(struct kernel_clone_args *kargs)
25932673 {
2594− /*
2595− * All lower bits of the flag word are taken.
2596− * Verify that no other unknown flags are passed along.
2597− */
2598− if (kargs->flags & ~CLONE_LEGACY_FLAGS)
2674+ /* Verify that no unknown flags are passed along. */
2675+ if (kargs->flags & ~(CLONE_LEGACY_FLAGS | CLONE_CLEAR_SIGHAND))
25992676 return false;
26002677
26012678 /*
@@ -2605,6 +2682,10 @@ static bool clone3_args_valid(struct kernel_clone_args *kargs) · 3 unmodified lines
26052682 if (kargs->flags & (CLONE_DETACHED | CSIGNAL))
26062683 return false;
26072684
2685+ if ((kargs->flags & (CLONE_SIGHAND | CLONE_CLEAR_SIGHAND)) ==
2686+ (CLONE_SIGHAND | CLONE_CLEAR_SIGHAND))
2687+ return false;
2688+
26082689 if ((kargs->flags & (CLONE_THREAD | CLONE_PARENT)) &&
26092690 kargs->exit_signal)
26102691 return false;
@@ -2631,6 +2712,9 @@ SYSCALL_DEFINE2(clone3, struct clone_args __user *, uargs, size_t, size) · 20 unmodified lines
26312712 int err;
26322713
26332714 struct kernel_clone_args kargs;
2715+ pid_t set_tid[MAX_PID_NS_LEVEL];
2716+
2717+ kargs.set_tid = set_tid;
26342718
26352719 err = copy_clone_args_from_user(&kargs, uargs, size);
26362720 if (err)
kernel/pid.c+63−23
@@ -157,7 +157,8 @@ void free_pid(struct pid *pid) · 156 unmodified lines
157157 call_rcu(&pid->rcu, delayed_put_pid);
158158 }
159159
160−struct pid *alloc_pid(struct pid_namespace *ns)
160+struct pid *alloc_pid(struct pid_namespace *ns, pid_t *set_tid,
161+ size_t set_tid_size)
161162 {
162163 struct pid *pid;
163164 enum pid_type type;
@@ -166,6 +167,17 @@ struct pid *alloc_pid(struct pid_namespace *ns) · 2 unmodified lines
166167 struct upid *upid;
167168 int retval = -ENOMEM;
168169
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+
169181 pid = kmem_cache_alloc(ns->pid_cachep, GFP_KERNEL);
170182 if (!pid)
171183 return ERR_PTR(retval);
@@ -174,24 +186,54 @@ struct pid *alloc_pid(struct pid_namespace *ns) · 2 unmodified lines
174186 pid->level = ns->level;
175187
176188 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+ }
178208
179209 idr_preload(GFP_KERNEL);
180210 spin_lock_irq(&pidmap_lock);
181211
182− /*
183− * init really needs pid 1, but after reaching the maximum
184− * wrap back to RESERVED_PIDS
185− */
186− if (idr_get_cursor(&tmp->idr) > RESERVED_PIDS)
187− pid_min = RESERVED_PIDS;
188−
189− /*
190− * Store a null pointer so find_pid_ns does not find
191− * a partially initialized PID (see below).
192− */
193− nr = idr_alloc_cyclic(&tmp->idr, NULL, pid_min,
194− pid_max, GFP_ATOMIC);
212+ if (tid) {
213+ nr = idr_alloc(&tmp->idr, NULL, tid,
214+ tid + 1, GFP_ATOMIC);
215+ /*
216+ * If ENOSPC is returned it means that the PID is
217+ * alreay in use. Return EEXIST in that case.
218+ */
219+ if (nr == -ENOSPC)
220+ nr = -EEXIST;
221+ } else {
222+ int pid_min = 1;
223+ /*
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+ }
195237 spin_unlock_irq(&pidmap_lock);
196238 idr_preload_end();
197239
@@ -299,7 +341,7 @@ static void __change_pid(struct task_struct *task, enum pid_type type, · 101 unmodified lines
299341 *pid_ptr = new;
300342
301343 for (tmp = PIDTYPE_MAX; --tmp >= 0; )
302− if (!hlist_empty(&pid->tasks[tmp]))
344+ if (pid_has_task(pid, tmp))
303345 return;
304346
305347 free_pid(pid);
@@ -497,7 +539,7 @@ static int pidfd_create(struct pid *pid) · 191 unmodified lines
497539 */
498540 SYSCALL_DEFINE2(pidfd_open, pid_t, pid, unsigned int, flags)
499541 {
500− int fd, ret;
542+ int fd;
501543 struct pid *p;
502544
503545 if (flags)
@@ -510,13 +552,11 @@ SYSCALL_DEFINE2(pidfd_open, pid_t, pid, unsigned int, flags) · 6 unmodified lines
510552 if (!p)
511553 return -ESRCH;
512554
513− ret = 0;
514− rcu_read_lock();
515− if (!pid_task(p, PIDTYPE_TGID))
516− ret = -EINVAL;
517− rcu_read_unlock();
555+ if (pid_has_task(p, PIDTYPE_TGID))
556+ fd = pidfd_create(p);
557+ else
558+ fd = -EINVAL;
518559
519− fd = ret ?: pidfd_create(p);
520560 put_pid(p);
521561 return fd;
522562 }
kernel/pid_namespace.c+0−2
@@ -26,8 +26,6 @@ · 25 unmodified lines
2626
2727 static DEFINE_MUTEX(pid_caches_mutex);
2828 static 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
3129 /* Write once array, filled from the beginning. */
3230 static struct kmem_cache *pid_cache[MAX_PID_NS_LEVEL];
3331
tools/testing/selftests/Makefile+1−0
@@ -5,6 +5,7 @@ TARGETS += bpf · 4 unmodified lines
55 TARGETS += breakpoints
66 TARGETS += capabilities
77 TARGETS += cgroup
8+TARGETS += clone3
89 TARGETS += cpufreq
910 TARGETS += cpu-hotplug
1011 TARGETS += drivers/dma-buf
tools/testing/selftests/clone3/.gitignore+3−0
@@ -0,0 +1,3 @@
1+clone3
2+clone3_clear_sighand
3+clone3_set_tid
tools/testing/selftests/clone3/Makefile+6−0
@@ -0,0 +1,6 @@
1+# SPDX-License-Identifier: GPL-2.0
2+CFLAGS += -g -I../../../../usr/include/
3+
4+TEST_GEN_PROGS := clone3 clone3_clear_sighand clone3_set_tid
5+
6+include ../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+
30+enum 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+
39+static 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+
107+static 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+
128+int 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+
23+static void nop_handler(int signo)
24+{
25+}
26+
27+static int wait_for_pid(pid_t pid)
28+{
29+ int status, ret;
30+
31+again:
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+
46+static 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+
119+int 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
16+struct 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+
30+static 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+
37+static 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+
30+static int pipe_1[2];
31+static int pipe_2[2];
32+
33+static void child_exit(int ret)
34+{
35+ fflush(stdout);
36+ fflush(stderr);
37+ _exit(ret);
38+}
39+
40+static 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+
119+static 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+}
145+int 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);
393+out:
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 @@
11 # SPDX-License-Identifier: GPL-2.0-only
22 CFLAGS += -g -I../../../../usr/include/ -pthread
33
4−TEST_GEN_PROGS := pidfd_test pidfd_open_test pidfd_poll_test pidfd_wait
4+TEST_GEN_PROGS := pidfd_test pidfd_fdinfo_test pidfd_open_test pidfd_poll_test pidfd_wait
55
66 include ../lib.mk
77
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+
19+struct error {
20+ int code;
21+ char msg[512];
22+};
23+
24+static 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+
41+static 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+
74+static 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+
83+struct child {
84+ pid_t pid;
85+ int fd;
86+};
87+
88+static 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+
116+static inline void child_close(struct child *child)
117+{
118+ close(child->fd);
119+}
120+
121+static 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+
135+static inline int child_join_close(struct child *child, struct error *err)
136+{
137+ child_close(child);
138+ return child_join(child, err);
139+}
140+
141+static inline void trim_newline(char *str)
142+{
143+ char *pos = strrchr(str, '\n');
144+
145+ if (pos)
146+ *pos = '\0';
147+}
148+
149+static 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+
201+static 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+
237+static 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+
270+static 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+
287+int 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+}