From ldv at altlinux.org Sat Aug 1 12:29:23 2020 From: ldv at altlinux.org (Dmitry V. Levin) Date: Sat, 1 Aug 2020 15:29:23 +0300 Subject: [PATCH v4 1/7] PID namespace translation support In-Reply-To: References: <20200727185410.2503993-1-uzonyi.akos@gmail.com> <20200727185410.2503993-2-uzonyi.akos@gmail.com> <20200731184127.GA23929@altlinux.org> Message-ID: <20200801122923.GA2879@altlinux.org> On Fri, Jul 31, 2020 at 09:41:30PM +0200, ?kos Uzonyi wrote: > On Fri, 31 Jul 2020 at 20:41, Dmitry V. Levin wrote: > > On Mon, Jul 27, 2020 at 08:54:04PM +0200, ?kos Uzonyi wrote: > [...] > > > +static bool > > > +is_proc_ours(void) > > > +{ > > > + static int cached_val = -1; > > > + > > > + if (cached_val < 0) > > > + cached_val = get_id_list(0, NULL, PT_TID) == 1; > > > + > > > + return cached_val; > > > +} > > > + > > > +static uint64_t > > > +get_ns(struct tcb *tcp) > > > +{ > > > + if (!tcp->pid_ns_inited) { > > > + int proc_pid = 0; > > > + > > > + if (is_proc_ours()) > > > + proc_pid = tcp->pid; > > > + else > > > + translate_pid(NULL, tcp->pid, PT_TID, &proc_pid); > > > + > > > + if (proc_pid) > > > + get_ns_hierarchy(proc_pid, &tcp->pid_ns, 1); > > > + > > > + tcp->pid_ns_inited = true; > > > + } > > > + > > > + return tcp->pid_ns; > > > +} > > > + > > > +static uint64_t > > > +get_our_ns(void) > > > +{ > > > + static uint64_t our_ns = 0; > > > + static bool our_ns_initialised = false; > > > + > > > + if (!our_ns_initialised) { > > > + get_ns_hierarchy(0, &our_ns, 1); > > > + our_ns_initialised = true; > > > + } > > > + > > > + return our_ns; > > > +} > > > > Could you add some short comments describing the purpose of these > > functions, similar to other functions in this file, please? > > Ok, I'll add short documentations to these functions, and maybe some > other functions as well. It would be great if you could also add a comment about the choice of numeric constants passed as arguments to trie_create in pidns_init and put_proc_pid. -- ldv From ldv at altlinux.org Sat Aug 1 12:52:51 2020 From: ldv at altlinux.org (Dmitry V. Levin) Date: Sat, 1 Aug 2020 15:52:51 +0300 Subject: [PATCH v4 4/7] Add SYS_FUNC(tkill) In-Reply-To: <20200727185410.2503993-5-uzonyi.akos@gmail.com> References: <20200727185410.2503993-1-uzonyi.akos@gmail.com> <20200727185410.2503993-5-uzonyi.akos@gmail.com> Message-ID: <20200801125251.GA3038@altlinux.org> On Mon, Jul 27, 2020 at 08:54:07PM +0200, ?kos Uzonyi wrote: > syscallent*.h files are updated automatically by: > find linux -name syscallent*.h -exec \ > sed -i '/"tkill"/ s/SEN(kill)/SEN(tkill)/' {} + > > * signal.c (tkill): New syscall decoder. > * linux/32/syscallent.h: Use SEN(tkill) for "tkill" syscall. I think it would be better if this commit was split into two parts: the first one that introduces a tkill syscall decoder, and the second part that makes the tkill syscall decoder use printpid. The second part then should be merged into "Use printpid in decoders" commit that updates decoders of kill and tgkill syscalls. Does this make sense? -- ldv From uzonyi.akos at gmail.com Sat Aug 1 13:50:20 2020 From: uzonyi.akos at gmail.com (=?UTF-8?B?w4Frb3MgVXpvbnlp?=) Date: Sat, 1 Aug 2020 15:50:20 +0200 Subject: [PATCH v4 4/7] Add SYS_FUNC(tkill) In-Reply-To: <20200801125251.GA3038@altlinux.org> References: <20200727185410.2503993-1-uzonyi.akos@gmail.com> <20200727185410.2503993-5-uzonyi.akos@gmail.com> <20200801125251.GA3038@altlinux.org> Message-ID: On Sat, 1 Aug 2020 at 14:52, Dmitry V. Levin wrote: > On Mon, Jul 27, 2020 at 08:54:07PM +0200, ?kos Uzonyi wrote: > > syscallent*.h files are updated automatically by: > > find linux -name syscallent*.h -exec \ > > sed -i '/"tkill"/ s/SEN(kill)/SEN(tkill)/' {} + > > > > * signal.c (tkill): New syscall decoder. > > * linux/32/syscallent.h: Use SEN(tkill) for "tkill" syscall. > > I think it would be better if this commit was split into two parts: > the first one that introduces a tkill syscall decoder, and the second part > that makes the tkill syscall decoder use printpid. The second part then > should be merged into "Use printpid in decoders" commit that updates > decoders of kill and tgkill syscalls. > > Does this make sense? Yes, that makes sense, I will do it. Also I'm not sure if "Use printpid in decoders" and "Use printpid in print_sockaddr and printsiginfo" should be two different commits. I didn't squash them together, because the latter one adds a tcp parameter to a lot of functions so I thought it could be cleaner to keep them separate. But since logically these two commits should be one, I think I should squash them. Do you agree? From ldv at altlinux.org Sat Aug 1 13:51:29 2020 From: ldv at altlinux.org (Dmitry V. Levin) Date: Sat, 1 Aug 2020 16:51:29 +0300 Subject: [PATCH v4 1/7] PID namespace translation support In-Reply-To: <20200727185410.2503993-2-uzonyi.akos@gmail.com> References: <20200727185410.2503993-1-uzonyi.akos@gmail.com> <20200727185410.2503993-2-uzonyi.akos@gmail.com> Message-ID: <20200801135129.GA3674@altlinux.org> On Mon, Jul 27, 2020 at 08:54:04PM +0200, ?kos Uzonyi wrote: [...] > @@ -983,6 +1001,11 @@ print_local_array_ex(struct tcb *tcp, > extern kernel_ulong_t * > fetch_indirect_syscall_args(struct tcb *, kernel_ulong_t addr, unsigned int n_args); > > +extern void pidns_init(void); > + > +extern int translate_pid(struct tcb *tcp, int dest_id, enum pid_type type, > + int *proc_pid_ptr); > + > extern void > dumpiov_in_msghdr(struct tcb *, kernel_ulong_t addr, kernel_ulong_t data_size); > > @@ -1058,6 +1081,8 @@ printfd(struct tcb *tcp, int fd) > * of the tracee the descriptor tcp). This is a stub. > */ > extern void printfd_pid_tracee_ns(struct tcb *tcp, pid_t pid, int fd); > +extern void printpid(struct tcb *tcp, int pid, enum pid_type type); > +extern void printpid_translation(struct tcb *tcp, int pid, enum pid_type type); > extern void print_sockaddr(const void *sa, int len); > extern bool > print_inet_addr(int af, const void *addr, unsigned int len, const char *var_name); There is no strict rule, but in general we prefer "struct tcb *" to "struct tcb *tcp" in function declarations because the former is 3 symbols shorter and the latter does not add any more clarity. -- ldv From ldv at altlinux.org Sat Aug 1 13:57:11 2020 From: ldv at altlinux.org (Dmitry V. Levin) Date: Sat, 1 Aug 2020 16:57:11 +0300 Subject: [PATCH v4 4/7] Add SYS_FUNC(tkill) In-Reply-To: References: <20200727185410.2503993-1-uzonyi.akos@gmail.com> <20200727185410.2503993-5-uzonyi.akos@gmail.com> <20200801125251.GA3038@altlinux.org> Message-ID: <20200801135711.GB3674@altlinux.org> On Sat, Aug 01, 2020 at 03:50:20PM +0200, ?kos Uzonyi wrote: > On Sat, 1 Aug 2020 at 14:52, Dmitry V. Levin wrote: > > On Mon, Jul 27, 2020 at 08:54:07PM +0200, ?kos Uzonyi wrote: > > > syscallent*.h files are updated automatically by: > > > find linux -name syscallent*.h -exec \ > > > sed -i '/"tkill"/ s/SEN(kill)/SEN(tkill)/' {} + > > > > > > * signal.c (tkill): New syscall decoder. > > > * linux/32/syscallent.h: Use SEN(tkill) for "tkill" syscall. > > > > I think it would be better if this commit was split into two parts: > > the first one that introduces a tkill syscall decoder, and the second part > > that makes the tkill syscall decoder use printpid. The second part then > > should be merged into "Use printpid in decoders" commit that updates > > decoders of kill and tgkill syscalls. > > > > Does this make sense? > > Yes, that makes sense, I will do it. > > Also I'm not sure if "Use printpid in decoders" and "Use printpid in > print_sockaddr and printsiginfo" should be two different commits. I > didn't squash them together, because the latter one adds a tcp > parameter to a lot of functions so I thought it could be cleaner to > keep them separate. But since logically these two commits should be > one, I think I should squash them. Do you agree? I think those changes that just add "struct tcb *" argument here and there can now be moved to a separate commit (I'm currently testing this in ldv/next branch), and both "Use printpid" commits would indeed be better merged together. -- ldv From ldv at altlinux.org Sun Aug 2 12:08:27 2020 From: ldv at altlinux.org (Dmitry V. Levin) Date: Sun, 2 Aug 2020 15:08:27 +0300 Subject: [PATCH v4 4/7] Add SYS_FUNC(tkill) In-Reply-To: <20200801135711.GB3674@altlinux.org> References: <20200727185410.2503993-1-uzonyi.akos@gmail.com> <20200727185410.2503993-5-uzonyi.akos@gmail.com> <20200801125251.GA3038@altlinux.org> <20200801135711.GB3674@altlinux.org> Message-ID: <20200802120826.GA16944@altlinux.org> On Sat, Aug 01, 2020 at 04:57:11PM +0300, Dmitry V. Levin wrote: > On Sat, Aug 01, 2020 at 03:50:20PM +0200, ?kos Uzonyi wrote: > > On Sat, 1 Aug 2020 at 14:52, Dmitry V. Levin wrote: > > > On Mon, Jul 27, 2020 at 08:54:07PM +0200, ?kos Uzonyi wrote: > > > > syscallent*.h files are updated automatically by: > > > > find linux -name syscallent*.h -exec \ > > > > sed -i '/"tkill"/ s/SEN(kill)/SEN(tkill)/' {} + > > > > > > > > * signal.c (tkill): New syscall decoder. > > > > * linux/32/syscallent.h: Use SEN(tkill) for "tkill" syscall. > > > > > > I think it would be better if this commit was split into two parts: > > > the first one that introduces a tkill syscall decoder, and the second part > > > that makes the tkill syscall decoder use printpid. The second part then > > > should be merged into "Use printpid in decoders" commit that updates > > > decoders of kill and tgkill syscalls. > > > > > > Does this make sense? > > > > Yes, that makes sense, I will do it. > > > > Also I'm not sure if "Use printpid in decoders" and "Use printpid in > > print_sockaddr and printsiginfo" should be two different commits. I > > didn't squash them together, because the latter one adds a tcp > > parameter to a lot of functions so I thought it could be cleaner to > > keep them separate. But since logically these two commits should be > > one, I think I should squash them. Do you agree? > > I think those changes that just add "struct tcb *" argument here and > there can now be moved to a separate commit (I'm currently testing this > in ldv/next branch), and both "Use printpid" commits would indeed > be better merged together. OK, I've pushed these changes to master. When you rebase, there are going to be a few simple conflicts to resolve. -- ldv From uzonyi.akos at gmail.com Mon Aug 3 19:19:11 2020 From: uzonyi.akos at gmail.com (=?UTF-8?q?=C3=81kos=20Uzonyi?=) Date: Mon, 3 Aug 2020 21:19:11 +0200 Subject: [PATCH v5 0/5] [PIDNS] Final Message-ID: <20200803191916.94724-1-uzonyi.akos@gmail.com> From: Uzonyi ?kos Changes in v5: - Squash "Use printpid in *" commits - Makefile.am: move adding getpid.c to "Use printpid in decoders" - Remove pid_ns_inited field from struct tcb - strace.1.in: remove -Y flag - Use tprints instead of tprintf where possible - Make some global variables static - pidns_init: remove "inited" bool variable - Make printpid_translation static - tests/pidns.c: refactor a bit - check_ns_ioctl: fix error msg - defs.h: Move adding get_proc_pid to "PID namespace translation support" - Remove tcp paramter name from declarations - Update printfd_pid_tracee_ns documentation - Use named constants for trie_create arguments - Add documentation comments - Add printpid_tgid_pgid function - Delete get_pid_max function; use global variables instead - Refactor trie: - Move key_size argument - Remove support for TRIE_SET - Merge trie_create, trie_init, trie_check functions - trie_free_node: make static, fix "node" argument type - Add max_depth field - Reorder functions - Extract common parts of trie_get, trie_set Changes in v4: - Skip tests if NS_* ioctl commands are not supported - Improve documentation in pidns.h - Use pipe for init process termination (instead of SIGKILL) - Add PIDNS_TEST_INIT macro - Remove "ifdef __NR_gettid" - Fix fork--pidns-tranlsation.test: skip if unshare fails with EPERM - Use debug message instead of normal message in some cases - Rename some labels - Rewrite get_ns function - Remove O_NONBLOCK from open(/proc//ns/pid) Changes in v3: - Split accidentally sqashed last commit - Undo modification of tests/pidfd_send_signal.c - Rename kcmp-yY test to kcmp-y--pidns-translation - Skip tests if unshare fails with EPERM - Fix buffer size in pidns_pid2str - Use largefile_wrappers.h macros - Return early if from_ns or our_ns is 0 - Do not call ioctl(NS_GET_PARENT) again, if first failed with ENOTTY - Skip pidns tests if Linux kernel version < 4.9 - Use smaller trie nodes in pidns.c - Remove race condition from fork--pidns-translation test - Move "key_size" to center in trie description - Use PT_TID (not PT_TGID) when translating tcp->pid - Fix get_ns_hierarchy and get_id_list functions - Fix migrate_pages test if syscall succeds - Fix filtering in ioctl_block--pidns-translation.test - Fix -a flag value in xetpriority test Changes in v2: - Add missing header files to Makefile - Fix pointer-to-int-cast errors - Fix unused-result errors - Use perror_msg instead of perror_func_msg where appropriate - Remove tcb parameter of read_int_from_file - Use xsprintf instead of snprintf - Refactor get_pid_max, get_ns_hierarchy, get_id_list functions - Remove -Y flag - Improve documentation of trie - Fix printing of f_owner_ex struct - Use printpid for F_GETOWN, F_SETOWN fcntl command arguments - Use printpid for shmid_ds.shm_cpid, shmid_ds.shm_clid - Call pidns_init before parsing arguments ?kos Uzonyi (5): PID namespace translation support Use printpid in decoders Use get_proc_pid for /proc paths Implement testing framework for pidns Add tests for PID namespace translation Makefile.am | 4 + NEWS | 1 + affinity.c | 6 +- block.c | 2 +- bpf.c | 2 +- capability.c | 4 +- clone.c | 14 +- defs.h | 58 +- fcntl.c | 24 +- get_robust_list.c | 3 +- getpid.c | 46 ++ ioprio.c | 26 +- ipc_shmctl.c | 5 +- kcmp.c | 5 +- largefile_wrappers.h | 2 + linux/dummy.h | 8 +- mmap_cache.c | 2 +- msghdr.c | 2 +- net.c | 2 +- netlink.c | 5 +- numa.c | 6 +- pathtrace.c | 5 +- pidfd_open.c | 2 +- pidns.c | 597 ++++++++++++++++++ print_fields.h | 24 + printsiginfo.c | 2 +- process.c | 3 +- process_vm.c | 6 +- resource.c | 27 +- sched.c | 25 +- signal.c | 21 +- sockaddr.c | 2 +- strace.1.in | 4 + strace.c | 11 +- syscall.c | 15 + tests/.gitignore | 31 + tests/Makefile.am | 37 ++ tests/fcntl--pidns-translation.c | 2 + tests/fcntl-common.c | 82 ++- tests/fcntl.c | 1 + tests/fcntl64--pidns-translation.c | 2 + tests/fcntl64.c | 3 + tests/fork--pidns-translation.awk | 15 + tests/fork--pidns-translation.c | 69 ++ tests/fork--pidns-translation.test | 16 + tests/gen_tests.in | 30 +- tests/getpgrp--pidns-translation.c | 2 + tests/getpgrp.c | 8 +- tests/getpid--pidns-translation.c | 2 + tests/getpid.c | 8 +- tests/getsid--pidns-translation.c | 2 + tests/getsid.c | 9 +- tests/gettid--pidns-translation.c | 2 + tests/gettid.c | 8 +- tests/init.sh | 31 + tests/ioctl_block--pidns-translation.c | 2 + tests/ioctl_block--pidns-translation.test | 24 + tests/ioctl_block.c | 24 +- tests/ioprio--pidns-translation.c | 2 + tests/ioprio.c | 54 +- tests/kcmp-y--pidns-translation.c | 2 + tests/kcmp.c | 36 +- tests/kill--pidns-translation.c | 2 + tests/kill.c | 12 +- tests/migrate_pages--pidns-translation.c | 2 + tests/migrate_pages.c | 17 +- tests/move_pages--pidns-translation.c | 2 + tests/move_pages.c | 51 +- tests/net-sockaddr--pidns-translation.c | 2 + tests/net-sockaddr.c | 66 +- tests/netlink_audit--pidns-translation.c | 2 + tests/netlink_audit--pidns-translation.test | 13 + tests/netlink_audit.c | 11 +- tests/pidfd_open--pidns-translation.c | 2 + tests/pidfd_open.c | 21 +- tests/pidfd_send_signal--pidns-translation.c | 2 + tests/pidfd_send_signal.c | 13 +- tests/pidns.c | 214 +++++++ tests/pidns.h | 56 ++ tests/prlimit64--pidns-translation.c | 2 + tests/prlimit64.c | 17 +- tests/process_vm_readv--pidns-translation.c | 2 + tests/process_vm_readv_writev.c | 27 +- tests/process_vm_writev--pidns-translation.c | 2 + tests/rt_sigqueueinfo--pidns-translation.c | 2 + tests/rt_sigqueueinfo.c | 15 +- tests/rt_tgsigqueueinfo--pidns-translation.c | 2 + tests/rt_tgsigqueueinfo.c | 26 +- tests/sched_xetaffinity--pidns-translation.c | 2 + tests/sched_xetaffinity.c | 31 +- tests/sched_xetattr--pidns-translation.c | 2 + tests/sched_xetattr.c | 47 +- tests/sched_xetparam--pidns-translation.c | 2 + tests/sched_xetparam.c | 20 +- tests/sched_xetscheduler--pidns-translation.c | 2 + tests/sched_xetscheduler.c | 44 +- tests/signal_receive--pidns-translation.c | 2 + tests/signal_receive.c | 22 +- tests/so_peercred--pidns-translation.c | 2 + tests/so_peercred.c | 22 + tests/xet_robust_list--pidns-translation.c | 2 + tests/xet_robust_list.c | 18 +- tests/xetpgid--pidns-translation.c | 2 + tests/xetpgid.c | 21 +- tests/xetpriority--pidns-translation.c | 2 + tests/xetpriority.c | 20 +- trie.c | 250 ++++++++ trie.h | 89 +++ util.c | 27 +- wait.c | 36 +- 110 files changed, 2468 insertions(+), 255 deletions(-) create mode 100644 getpid.c create mode 100644 pidns.c create mode 100644 tests/fcntl--pidns-translation.c create mode 100644 tests/fcntl64--pidns-translation.c create mode 100644 tests/fork--pidns-translation.awk create mode 100644 tests/fork--pidns-translation.c create mode 100755 tests/fork--pidns-translation.test create mode 100644 tests/getpgrp--pidns-translation.c create mode 100644 tests/getpid--pidns-translation.c create mode 100644 tests/getsid--pidns-translation.c create mode 100644 tests/gettid--pidns-translation.c create mode 100644 tests/ioctl_block--pidns-translation.c create mode 100755 tests/ioctl_block--pidns-translation.test create mode 100644 tests/ioprio--pidns-translation.c create mode 100644 tests/kcmp-y--pidns-translation.c create mode 100644 tests/kill--pidns-translation.c create mode 100644 tests/migrate_pages--pidns-translation.c create mode 100644 tests/move_pages--pidns-translation.c create mode 100644 tests/net-sockaddr--pidns-translation.c create mode 100644 tests/netlink_audit--pidns-translation.c create mode 100755 tests/netlink_audit--pidns-translation.test create mode 100644 tests/pidfd_open--pidns-translation.c create mode 100644 tests/pidfd_send_signal--pidns-translation.c create mode 100644 tests/pidns.c create mode 100644 tests/pidns.h create mode 100644 tests/prlimit64--pidns-translation.c create mode 100644 tests/process_vm_readv--pidns-translation.c create mode 100644 tests/process_vm_writev--pidns-translation.c create mode 100644 tests/rt_sigqueueinfo--pidns-translation.c create mode 100644 tests/rt_tgsigqueueinfo--pidns-translation.c create mode 100644 tests/sched_xetaffinity--pidns-translation.c create mode 100644 tests/sched_xetattr--pidns-translation.c create mode 100644 tests/sched_xetparam--pidns-translation.c create mode 100644 tests/sched_xetscheduler--pidns-translation.c create mode 100644 tests/signal_receive--pidns-translation.c create mode 100644 tests/so_peercred--pidns-translation.c create mode 100644 tests/xet_robust_list--pidns-translation.c create mode 100644 tests/xetpgid--pidns-translation.c create mode 100644 tests/xetpriority--pidns-translation.c create mode 100644 trie.c create mode 100644 trie.h -- 2.27.0 From uzonyi.akos at gmail.com Mon Aug 3 19:19:12 2020 From: uzonyi.akos at gmail.com (=?UTF-8?q?=C3=81kos=20Uzonyi?=) Date: Mon, 3 Aug 2020 21:19:12 +0200 Subject: [PATCH v5 1/5] PID namespace translation support In-Reply-To: <20200803191916.94724-1-uzonyi.akos@gmail.com> References: <20200803191916.94724-1-uzonyi.akos@gmail.com> Message-ID: <20200803191916.94724-2-uzonyi.akos@gmail.com> * defs.h (pidns_translation): New variable. (tcb): Add pid_ns field. (RVAL_MASK): Change value from 013 to 017. (RVAL_TID, RVAL_SID, RVAL_TGID, RVAL_PGID): New definitions. (pid_type): New enum. (pidns_init, translate_pid, get_proc_pid, printpid, printpid_tgid_pgid): New function declarations. * largefile_wrappers.h (fstat_fd): New macro. * pidns.c: New file. * trie.c: New file. * trie.h: New file. * Makefile.am (libstrace_a_SOURCES): Add trie.c, trie.h, pidns.c. * strace.c (pidns_translation): New variable. (init): Add --pidns-translation option. * syscall.c (syscall_exiting_trace): Handle RVAL_* return values. * NEWS: Mention this. * strace.1.in: Add description for new option. Co-Authored-by: Eugene Syromyatnikov --- Makefile.am | 3 + NEWS | 1 + defs.h | 53 +++- largefile_wrappers.h | 2 + pidns.c | 597 +++++++++++++++++++++++++++++++++++++++++++ strace.1.in | 4 + strace.c | 9 + syscall.c | 15 ++ trie.c | 250 ++++++++++++++++++ trie.h | 89 +++++++ 10 files changed, 1022 insertions(+), 1 deletion(-) create mode 100644 pidns.c create mode 100644 trie.c create mode 100644 trie.h diff --git a/Makefile.am b/Makefile.am index f5447811..73c22035 100644 --- a/Makefile.am +++ b/Makefile.am @@ -233,6 +233,7 @@ libstrace_a_SOURCES = \ personality.c \ pidfd_getfd.c \ pidfd_open.c \ + pidns.c \ pkeys.c \ poll.c \ prctl.c \ @@ -344,6 +345,8 @@ libstrace_a_SOURCES = \ time.c \ times.c \ trace_event.h \ + trie.c \ + trie.h \ truncate.c \ ubi.c \ ucopy.c \ diff --git a/NEWS b/NEWS index b83f9e80..9086fde9 100644 --- a/NEWS +++ b/NEWS @@ -14,6 +14,7 @@ Noteworthy changes in release ?.? (????-??-??) KEYCTL_*, KVM_*, LOOP_*, NDA_*, RTC_*, TCA_*, STATX_*, and *_MAGIC constants. * Updated lists of ioctl commands from Linux 5.8. + * Added --pidns-translation opition for PID namespace translation. * Bug fixes * Added statx syscall to %fstat trace class. diff --git a/defs.h b/defs.h index f7ac54f3..c16feb3c 100644 --- a/defs.h +++ b/defs.h @@ -280,6 +280,13 @@ struct tcb { struct timespec etime; /* Syscall entry time (CLOCK_MONOTONIC) */ struct timespec delay_expiration_time; /* When does the delay end */ + /* + * The ID of the PID namespace of this process + * (inode number of /proc//ns/pid) + * (0: not initialized; -1ULL: initializtaion failed) + */ + uint64_t pid_ns; + struct mmap_cache_t *mmap_cache; /* @@ -413,7 +420,11 @@ extern const struct xlat whence_codes[]; # define RVAL_HEX 001 /* hex format */ # define RVAL_OCTAL 002 /* octal format */ # define RVAL_FD 010 /* file descriptor */ -# define RVAL_MASK 013 /* mask for these values */ +# define RVAL_TID 011 /* task ID */ +# define RVAL_SID 012 /* session ID */ +# define RVAL_TGID 013 /* thread group ID */ +# define RVAL_PGID 014 /* process group ID */ +# define RVAL_MASK 017 /* mask for these values */ # define RVAL_STR 020 /* Print `auxstr' field after return val */ # define RVAL_NONE 040 /* Print nothing */ @@ -428,6 +439,16 @@ extern const struct xlat whence_codes[]; # define indirect_ipccall(tcp) (tcp_sysent(tcp)->sys_flags & TRACE_INDIRECT_SUBCALL) +enum pid_type { + PT_TID, + PT_TGID, + PT_PGID, + PT_SID, + + PT_COUNT, + PT_NONE = -1 +}; + enum sock_proto { SOCK_PROTO_UNKNOWN, SOCK_PROTO_UNIX, @@ -469,6 +490,7 @@ extern int Tflag_scale; extern int Tflag_width; extern bool iflag; extern bool count_wallclock; +extern unsigned int pidns_translation; /* are we filtering traces based on paths? */ extern struct path_set { const char **paths_selected; @@ -983,6 +1005,27 @@ print_local_array_ex(struct tcb *tcp, extern kernel_ulong_t * fetch_indirect_syscall_args(struct tcb *, kernel_ulong_t addr, unsigned int n_args); +extern void pidns_init(void); + +/** + * Returns the pid of the tracee as present in /proc (can be different from + * tcp->pid if /proc and the tracee process are in different PID namespaces). + */ +extern int get_proc_pid(struct tcb *); + +/** + * Translates a pid from tracee's namespace to our namepace. + * + * @param tcp The tcb of the tracee + * (NULL: from_id is in strace's namespace. Useful for + * getting the proc PID of from_id) + * @param from_id The id to be translated + * @param type The PID type of from_id + * @param proc_pid_ptr If not NULL, writes the proc PID to this location + */ +extern int translate_pid(struct tcb *, int dest_id, enum pid_type type, + int *proc_pid_ptr); + extern void dumpiov_in_msghdr(struct tcb *, kernel_ulong_t addr, kernel_ulong_t data_size); @@ -1058,6 +1101,14 @@ printfd(struct tcb *tcp, int fd) * of the tracee the descriptor tcp). This is a stub. */ extern void printfd_pid_tracee_ns(struct tcb *tcp, pid_t pid, int fd); + +extern void printpid(struct tcb *, int pid, enum pid_type type); + +/** + * Prints pid as a TGID if positive, and PGID if negative + * (like the first argument of kill). + */ +extern void printpid_tgid_pgid(struct tcb *, int pid); extern void print_sockaddr(struct tcb *, const void *sa, int len); extern bool print_inet_addr(int af, const void *addr, unsigned int len, const char *var_name); diff --git a/largefile_wrappers.h b/largefile_wrappers.h index 116e7048..9d8f5c92 100644 --- a/largefile_wrappers.h +++ b/largefile_wrappers.h @@ -29,6 +29,7 @@ # else # define fcntl_fd fcntl # endif +# define fstat_fd fstat64 # define strace_stat_t struct stat64 # define stat_file stat64 # define struct_dirent struct dirent64 @@ -39,6 +40,7 @@ # define open_file open # define fopen_stream fopen # define fcntl_fd fcntl +# define fstat_fd fstat # define strace_stat_t struct stat # define stat_file stat # define struct_dirent struct dirent diff --git a/pidns.c b/pidns.c new file mode 100644 index 00000000..6d46cb11 --- /dev/null +++ b/pidns.c @@ -0,0 +1,597 @@ +/* + * Copyright (c) 2020 ?kos Uzonyi + * All rights reserved. + * + * SPDX-License-Identifier: LGPL-2.1-or-later + */ + +#include "defs.h" + + +#include +#include +#include +#include +#include + +#include + +#include +#include +#include +#include + +#include "largefile_wrappers.h" +#include "trie.h" +#include "nsfs.h" +#include "xmalloc.h" +#include "xstring.h" + +/** + * Key: PID NS ID + * Value: a btree: + * Key: a process PID in NS + * Value: the process's PID as present in /proc + */ +static struct trie *ns_pid_to_proc_pid[PT_COUNT]; + +/** + * Key: Proc PID + * Value: stuct proc_data + */ +static struct trie *proc_data_cache; + +static bool ns_get_parent_enotty = false; + +static const char tid_str[] = "NSpid:\t"; +static const char tgid_str[] = "NStgid:\t"; +static const char pgid_str[] = "NSpgid:\t"; +static const char sid_str[] = "NSsid:\t"; + +static const struct { + const char *str; + size_t size; +} id_strs[PT_COUNT] = { + [PT_TID] = { tid_str, sizeof(tid_str) - 1 }, + [PT_TGID] = { tgid_str, sizeof(tgid_str) - 1 }, + [PT_PGID] = { pgid_str, sizeof(pgid_str) - 1 }, + [PT_SID] = { sid_str, sizeof(sid_str) - 1 }, +}; + + +/** + * Limit on PID NS hierarchy depth, imposed since Linux 3.7. NS traversal + * is not possible before Linux 4.9, so we consider this limit pretty universal. + */ +#define MAX_NS_DEPTH 32 + +static const uint8_t ptr_sz_lg = (sizeof(uint64_t *) == 8 ? 6 : 5); + +static int pid_max; +static uint8_t pid_max_size, pid_max_size_lg; + +struct proc_data { + int proc_pid; + int ns_count; + uint64_t ns_hierarchy[MAX_NS_DEPTH]; + int id_count[PT_COUNT]; + int id_hierarchy[PT_COUNT][MAX_NS_DEPTH]; +}; + +void +pidns_init(void) +{ + if (proc_data_cache) + return; + + pid_max = INT_MAX; + if (read_int_from_file("/proc/sys/kernel/pid_max", &pid_max) < 0) + debug_func_perror_msg("reading /proc/sys/kernel/pid_max"); + pid_max_size = ilog2_32(pid_max - 1) + 1; + pid_max_size_lg = ilog2_32(pid_max_size - 1) + 1; + + for (int i = 0; i < PT_COUNT; i++) + ns_pid_to_proc_pid[i] = trie_create(64, ptr_sz_lg, 10, 10, 0); + + proc_data_cache = trie_create(pid_max_size, ptr_sz_lg, 10, 10, 0); +} + +static void +put_proc_pid(uint64_t ns, int ns_pid, enum pid_type type, int proc_pid) +{ + struct trie *b = (struct trie *) (uintptr_t) trie_get(ns_pid_to_proc_pid[type], ns); + if (!b) { + b = trie_create(pid_max_size, pid_max_size_lg, 10, 10, 0); + trie_set(ns_pid_to_proc_pid[type], ns, (uint64_t) (uintptr_t) b); + } + trie_set(b, ns_pid, proc_pid); +} + +static int +get_cached_proc_pid(uint64_t ns, int ns_pid, enum pid_type type) +{ + struct trie *b = (struct trie *) (uintptr_t) + trie_get(ns_pid_to_proc_pid[type], ns); + if (!b) + return 0; + + return trie_get(b, ns_pid); +} + +/** + * Helper function, converts pid to string, or to "self" for pid == 0. + * Uses static buffer for operation. + */ +static const char * +pid_to_str(pid_t pid) +{ + if (!pid) + return "self"; + + static char buf[sizeof("-2147483648")]; + xsprintf(buf, "%d", pid); + return buf; +} + +/** + * Returns a list of PID NS IDs for the specified PID. + * + * @param proc_pid PID (as present in /proc) to get information for. + * @param ns_buf Pointer to buffer that is able to contain at least + * ns_buf_size items. + * @return Amount of NS in list. 0 indicates error. + */ +static size_t +get_ns_hierarchy(int proc_pid, uint64_t *ns_buf, size_t ns_buf_size) +{ + char path[PATH_MAX + 1]; + xsprintf(path, "/proc/%s/ns/pid", pid_to_str(proc_pid)); + + int fd = open_file(path, O_RDONLY); + if (fd < 0) + return 0; + + size_t n = 0; + while (n < ns_buf_size) { + strace_stat_t st; + if (fstat_fd(fd, &st)) + break; + + ns_buf[n++] = st.st_ino; + if (n >= ns_buf_size) + break; + + if (ns_get_parent_enotty) + break; + + int parent_fd = ioctl(fd, NS_GET_PARENT); + if (parent_fd < 0) { + switch (errno) { + case EPERM: + break; + + case ENOTTY: + ns_get_parent_enotty = true; + error_msg("NS_* ioctl commands are not " + "supported by the kernel"); + break; + + default: + perror_func_msg("ioctl(NS_GET_PARENT)"); + break; + } + + break; + } + + close(fd); + fd = parent_fd; + } + + close(fd); + + return n; +} + +/** + * Get list of IDs present in NS* proc status record. IDs are placed as they are + * stored in /proc (from top to bottom of NS hierarchy). + * + * @param proc_pid PID (as present in /proc) to get information for. + * @param id_buf Pointer to buffer that is able to contain at least + * MAX_NS_DEPTH items. Can be NULL. + * @param type Type of ID requested. + * @return Number of items stored in id_list. 0 indicates error. + */ +static size_t +get_id_list(int proc_pid, int *id_buf, enum pid_type type) +{ + const char *ns_str = id_strs[type].str; + size_t ns_str_size = id_strs[type].size; + + size_t n = 0; + + char status_path[PATH_MAX + 1]; + xsprintf(status_path, "/proc/%s/status", pid_to_str(proc_pid)); + FILE *f = fopen_stream(status_path, "r"); + if (!f) + return 0; + + char *line = NULL; + size_t linesize = 0; + char *p = NULL; + + while (getline(&line, &linesize, f) > 0) { + if (strncmp(line, ns_str, ns_str_size) == 0) { + p = line + ns_str_size; + break; + } + } + + while (p) { + errno = 0; + long id = strtol(p, NULL, 10); + + if (errno || (id < 1) || (id > INT_MAX)) { + perror_func_msg("converting pid to int"); + break; + } + + if (id_buf) + id_buf[n] = (int) id; + + n++; + strsep(&p, "\t"); + } + + free(line); + fclose(f); + + return n; +} + +/** + * Returns whether the /proc filesystem's PID namespace is same as strace's. + */ +static bool +is_proc_ours(void) +{ + static int cached_val = -1; + + if (cached_val < 0) + cached_val = get_id_list(0, NULL, PT_TID) == 1; + + return cached_val; +} + +/** + * Returns the PID namespace of the tracee + */ +static uint64_t +get_ns(struct tcb *tcp) +{ + if (tcp->pid_ns == -1ULL) + return 0; + + if (tcp->pid_ns) + return tcp->pid_ns; + + int proc_pid = 0; + translate_pid(NULL, tcp->pid, PT_TID, &proc_pid); + + tcp->pid_ns = -1ULL; + if (proc_pid) + get_ns_hierarchy(proc_pid, &tcp->pid_ns, 1); + + return tcp->pid_ns; +} + +/** + * Returns the PID namespace of strace + */ +static uint64_t +get_our_ns(void) +{ + static uint64_t our_ns = 0; + static bool our_ns_initialised = false; + + if (!our_ns_initialised) { + get_ns_hierarchy(0, &our_ns, 1); + our_ns_initialised = true; + } + + return our_ns; +} + +/** + * Returns the cached proc_data struct associated with proc_pid. + * If none found, allocates a new proc_data. + */ +static struct proc_data * +get_or_create_proc_data(int proc_pid) +{ + struct proc_data *pd = (struct proc_data *) (uintptr_t) + trie_get(proc_data_cache, proc_pid); + + if (!pd) { + pd = calloc(1, sizeof(*pd)); + if (!pd) + return NULL; + + pd->proc_pid = proc_pid; + trie_set(proc_data_cache, proc_pid, (uint64_t) (uintptr_t) pd); + } + + return pd; +} + +/** + * Updates the proc_data from /proc + * If the process does not exists, returns false, and frees the proc_data + */ +static bool +update_proc_data(struct proc_data *pd, enum pid_type type) +{ + pd->ns_count = get_ns_hierarchy(pd->proc_pid, + pd->ns_hierarchy, MAX_NS_DEPTH); + if (!pd->ns_count) + goto fail; + + pd->id_count[type] = get_id_list(pd->proc_pid, + pd->id_hierarchy[type], type); + if (!pd->id_count[type]) + goto fail; + + return true; + +fail: + trie_set(proc_data_cache, pd->proc_pid, (uint64_t) (uintptr_t) NULL); + free(pd); + return false; +} + +/** + * Paramters for id translation + */ +struct translate_id_params { + /* The result (output) */ + int result_id; + /* The proc data of the process (output) */ + struct proc_data *pd; + + /* The namespace to be translated from */ + uint64_t from_ns; + /* The id to be translated */ + int from_id; + /* The type of the id */ + enum pid_type type; +}; + +/** + * Translates an id to our namespace, given the proc_pid of the process, + * by reading files in /proc. + * + * @param tip The parameters + * @param proc_pid The proc pid of the process. + * If 0, use the cached values in tip->pd. + */ +static void +translate_id_proc_pid(struct translate_id_params *tip, int proc_pid) +{ + struct proc_data *pd = proc_pid ? + get_or_create_proc_data(proc_pid) : + tip->pd; + + tip->result_id = 0; + tip->pd = NULL; + + if (!pd) + return; + + if (proc_pid && !update_proc_data(pd, tip->type)) + return; + + if (!pd->ns_count || (pd->id_count[tip->type] < pd->ns_count)) + return; + + int our_ns_id_idx = pd->id_count[tip->type] - pd->ns_count; + + for (int i = 0; i < pd->ns_count; i++) { + if (pd->ns_hierarchy[i] != tip->from_ns) + continue; + + int id_idx = pd->id_count[tip->type] - i - 1; + if (pd->id_hierarchy[tip->type][id_idx] != tip->from_id) + return; + + tip->result_id = pd->id_hierarchy[tip->type][our_ns_id_idx]; + tip->pd = pd; + return; + } +} + +/** + * Translates an id to our namespace, by reading all proc entries in dir. + * + * @param tip The parameters + * @param path The path of the dir to be read. + * @param read_task_dir Whether recurse to "task" subdirectory. + */ +static void +translate_id_dir(struct translate_id_params *tip, const char *path, + bool read_task_dir) +{ + DIR *dir = opendir(path); + if (!dir) { + debug_func_perror_msg("opening dir: %s", path); + return; + } + + while (!tip->result_id) { + errno = 0; + struct_dirent *entry = read_dir(dir); + if (!entry) { + if (errno) + perror_func_msg("readdir"); + + break; + } + + if (entry->d_type != DT_DIR) + continue; + + errno = 0; + long proc_pid = strtol(entry->d_name, NULL, 10); + if (errno) + continue; + if ((proc_pid < 1) || (proc_pid > INT_MAX)) + continue; + + if (read_task_dir) { + char task_dir_path[PATH_MAX + 1]; + xsprintf(task_dir_path, "/proc/%ld/task", proc_pid); + translate_id_dir(tip, task_dir_path, false); + } + + if (tip->result_id) + break; + + translate_id_proc_pid(tip, proc_pid); + } + + closedir(dir); +} + +/** + * Iterator function of the proc_data_cache for id translation. + * If the cache contains the id we are looking for, reads the corresponding + * directory in /proc, and if cache is valid, saves the result. + */ +static void +proc_data_cache_iterator_fn(void* fn_data, uint64_t key, uint64_t val) +{ + struct translate_id_params *tip = (struct translate_id_params *)fn_data; + struct proc_data *pd = (struct proc_data *) (uintptr_t) val; + + if (!pd) + return; + + /* Result already found in an earlier iteration */ + if (tip->result_id) + return; + + /* Translate from cache */ + tip->pd = pd; + translate_id_proc_pid(tip, 0); + if (!tip->result_id) + return; + + /* Now translate from actual data in /proc, to check cache validity */ + translate_id_proc_pid(tip, pd->proc_pid); +} + +int +translate_pid(struct tcb *tcp, int from_id, enum pid_type type, + int *proc_pid_ptr) +{ + if ((from_id <= 0) || (type < 0) || (type >= PT_COUNT)) + return 0; + + const uint64_t our_ns = get_our_ns(); + if (!our_ns) + return 0; + + struct translate_id_params tip = { + .result_id = 0, + .pd = NULL, + .from_ns = tcp ? get_ns(tcp) : our_ns, + .from_id = from_id, + .type = type, + }; + + if (!tip.from_ns) + return 0; + + /* If translation is trivial */ + if (tip.from_ns == our_ns && (is_proc_ours() || !proc_pid_ptr)) { + if (proc_pid_ptr) + *proc_pid_ptr = from_id; + + tip.result_id = tip.from_id; + goto exit; + } + + if (ns_get_parent_enotty) + return 0; + + /* Look for a cached proc_pid for this (from_ns, from_id) pair */ + int cached_proc_pid = get_cached_proc_pid(tip.from_ns, tip.from_id, + tip.type); + if (cached_proc_pid) { + translate_id_proc_pid(&tip, cached_proc_pid); + if (tip.result_id) + goto exit; + } + + /* Iterate through the cache, find potential proc_data */ + trie_iterate_keys(proc_data_cache, 0, pid_max, + proc_data_cache_iterator_fn, &tip); + /* (proc_data_cache_iterator_fn takes care about updating proc_data) */ + if (tip.result_id) + goto exit; + + /* No cache helped, read all entries in /proc */ + translate_id_dir(&tip, "/proc", true); + +exit: + if (tip.pd) { + if (tip.pd->proc_pid) + put_proc_pid(tip.from_ns, tip.from_id, tip.type, + tip.pd->proc_pid); + + if (proc_pid_ptr) + *proc_pid_ptr = tip.pd->proc_pid; + } + + return tip.result_id; +} + +int +get_proc_pid(struct tcb *tcp) +{ + if (!is_proc_ours()) { + int ret = 0; + translate_pid(NULL, tcp->pid, PT_TID, &ret); + return ret; + } + + return tcp->pid; +} + +static void +printpid_translation(struct tcb *tcp, int pid, enum pid_type type) +{ + if (!pidns_translation) + return; + + int strace_pid = translate_pid(tcp, pid, type, NULL); + if (strace_pid && strace_pid != pid) + tprintf_comment("%d in strace's PID NS", strace_pid); +} + +void +printpid(struct tcb *tcp, int pid, enum pid_type type) +{ + tprintf("%d", pid); + printpid_translation(tcp, pid, type); +} + +void +printpid_tgid_pgid(struct tcb *tcp, int pid) +{ + tprintf("%d", pid); + if (pid > 0) + printpid_translation(tcp, pid, PT_TGID); + else if (pid < -1) + printpid_translation(tcp, -pid, PT_PGID); +} diff --git a/strace.1.in b/strace.1.in index 3b21caec..adca194c 100644 --- a/strace.1.in +++ b/strace.1.in @@ -1075,6 +1075,10 @@ Print all available information associated with file descritors: protocol-specific information associated with socket file descriptors, block/character device number associated with device file descriptors, and PIDs asociated with pidfd file descriptors. +.TP +.B \-\-pidns\-translation +If strace and tracee are in different PID namespaces, print PIDs in +strace's namespace also. .SS Statistics .TP 12 .B \-c diff --git a/strace.c b/strace.c index 4c96a98b..249533ea 100644 --- a/strace.c +++ b/strace.c @@ -133,6 +133,8 @@ static unsigned int daemonized_tracer; static int post_attach_sigstop = TCB_IGNORE_ONE_SIGSTOP; #define use_seize (post_attach_sigstop == 0) +unsigned int pidns_translation; + static bool detach_on_execve; static int exit_code; @@ -1998,6 +2000,8 @@ init(int argc, char *argv[]) os_release = get_os_release(); + pidns_init(); + shared_log = stderr; set_sortby(DEFAULT_SORTBY); set_personality(DEFAULT_PERSONALITY); @@ -2022,6 +2026,7 @@ init(int argc, char *argv[]) GETOPT_FOLLOWFORKS, GETOPT_OUTPUT_SEPARATELY, GETOPT_TS, + GETOPT_PIDNS_TRANSLATION, GETOPT_QUAL_TRACE, GETOPT_QUAL_ABBREV, @@ -2072,6 +2077,7 @@ init(int argc, char *argv[]) { "summary-wall-clock", no_argument, 0, 'w' }, { "strings-in-hex", optional_argument, 0, GETOPT_HEX_STR }, { "const-print-style", required_argument, 0, 'X' }, + { "pidns-translation", no_argument , 0, GETOPT_PIDNS_TRANSLATION }, { "successful-only", no_argument, 0, 'z' }, { "failed-only", no_argument, 0, 'Z' }, { "failing-only", no_argument, 0, 'Z' }, @@ -2285,6 +2291,9 @@ init(int argc, char *argv[]) case 'y': yflag_short++; break; + case GETOPT_PIDNS_TRANSLATION: + pidns_translation++; + break; case 'z': clear_number_set_array(status_set, 1); add_number_to_set(STATUS_SUCCESSFUL, status_set); diff --git a/syscall.c b/syscall.c index bcc87025..0f4bab6d 100644 --- a/syscall.c +++ b/syscall.c @@ -937,6 +937,21 @@ syscall_exiting_trace(struct tcb *tcp, struct timespec *ts, int res) tprintf("= %" PRI_kld, tcp->u_rval); } break; + case RVAL_TID: + case RVAL_SID: + case RVAL_TGID: + case RVAL_PGID: { + #define _(_t) [RVAL_##_t - RVAL_TID] = PT_##_t + static const enum pid_type types[] = { + _(TID), _(SID), _(TGID), _(PGID), + }; + #undef _ + + tprints("= "); + printpid(tcp, tcp->u_rval, + types[(sys_res & RVAL_MASK) - RVAL_TID]); + break; + } default: error_msg("invalid rval format"); break; diff --git a/trie.c b/trie.c new file mode 100644 index 00000000..76cecc25 --- /dev/null +++ b/trie.c @@ -0,0 +1,250 @@ +/* + * Simple trie implementation for key-value mapping storage + * + * Copyright (c) 2020 ?kos Uzonyi + * All rights reserved. + * + * SPDX-License-Identifier: LGPL-2.1-or-later + */ + +#include "defs.h" + +#include +#include +#include +#include + +#include "trie.h" + +static const uint8_t ptr_sz_lg = (sizeof(uint64_t *) == 8 ? 6 : 5); + +/** + * Returns lg2 of node size for the specific level of the trie. If max_depth + * provided is less than zero, it is calculated via trie_get_depth call. + */ +static uint8_t +trie_get_node_size(struct trie *t, uint8_t depth) +{ + /* Last level contains data and we allow it having a different size */ + if (depth == t->max_depth) + return t->data_block_key_bits + t->item_size_lg; + /* Last level of the tree can be smaller */ + if (depth == t->max_depth - 1) + return (t->key_size - t->data_block_key_bits - 1) % + t->node_key_bits + 1 + ptr_sz_lg; + + return t->node_key_bits + ptr_sz_lg; +} + +/** + * Provides starting offset of bits in key corresponding to the node index + * at the specific level. + */ +static uint8_t +trie_get_node_bit_offs(struct trie *t, uint8_t depth) +{ + uint8_t offs; + + if (depth == t->max_depth) + return 0; + + offs = t->data_block_key_bits; + + if (depth == t->max_depth - 1) + return offs; + + /* data_block_size + remainder */ + offs += trie_get_node_size(t, t->max_depth - 1) - ptr_sz_lg; + offs += (t->max_depth - depth - 2) * t->node_key_bits; + + return offs; +} + +struct trie * +trie_create(uint8_t key_size, uint8_t item_size_lg, uint8_t node_key_bits, + uint8_t data_block_key_bits, uint64_t empty_value) +{ + if (item_size_lg > 6) + return NULL; + if (key_size > 64) + return NULL; + if (node_key_bits < 1) + return NULL; + if (data_block_key_bits < 1 || data_block_key_bits > key_size) + return NULL; + + struct trie *t = malloc(sizeof(*t)); + if (!t) + return NULL; + + t->empty_value = empty_value; + t->data = NULL; + t->item_size_lg = item_size_lg; + t->node_key_bits = node_key_bits; + t->data_block_key_bits = data_block_key_bits; + t->key_size = key_size; + t->max_depth = (key_size - data_block_key_bits + node_key_bits - 1) + / t->node_key_bits; + + return t; +} + +static uint64_t * +trie_get_node(struct trie *t, uint64_t key, bool auto_create) +{ + void **cur_node = &(t->data); + + if (t->key_size < 64 && key > (uint64_t) 1 << t->key_size) + return NULL; + + for (uint8_t cur_depth = 0; cur_depth <= t->max_depth; cur_depth++) { + uint8_t offs = trie_get_node_bit_offs(t, cur_depth); + uint8_t sz = trie_get_node_size(t, cur_depth); + + if (!*cur_node) { + if (!auto_create) + return NULL; + + *cur_node = xcalloc(1 << sz, 1); + } + + if (cur_depth >= t->max_depth) + break; + + size_t pos = (key >> offs) & ((1 << (sz - ptr_sz_lg)) - 1); + cur_node = (((void **) (*cur_node)) + pos); + } + + return (uint64_t *) (*cur_node); +} + +static void +trie_data_block_calc_pos(struct trie *t, uint64_t key, + uint64_t *pos, uint64_t *mask, uint64_t *offs) +{ + uint64_t key_mask; + + key_mask = (1 << t->data_block_key_bits) - 1; + *pos = (key & key_mask) >> (6 - t->item_size_lg); + + key_mask = (1 << (6 - t->item_size_lg)) - 1; + *offs = (key & key_mask) * (1 << t->item_size_lg); + + *mask = (((uint64_t) 1 << (1 << t->item_size_lg)) - 1) << *offs; +} + +bool +trie_set(struct trie *t, uint64_t key, uint64_t val) +{ + uint64_t *data = trie_get_node(t, key, true); + if (!data) + return false; + + uint64_t pos, mask, offs; + trie_data_block_calc_pos(t, key, &pos, &mask, &offs); + + data[pos] &= ~mask; + data[pos] |= (val << offs) & mask; + + return true; +} + +static uint64_t +trie_data_block_get(struct trie *t, uint64_t *data, uint64_t key) +{ + if (!data) + return t->empty_value; + + uint64_t pos, mask, offs; + trie_data_block_calc_pos(t, key, &pos, &mask, &offs); + + return (data[pos] & mask) >> offs; +} + +uint64_t +trie_get(struct trie *b, uint64_t key) +{ + return trie_data_block_get(b, trie_get_node(b, key, false), key); +} + +static uint64_t +trie_iterate_keys_node(struct trie *t, + trie_iterate_fn fn, void *fn_data, + void *node, uint64_t start, uint64_t end, + uint8_t depth) +{ + if (start > end || !node) + return 0; + + if (depth == t->max_depth) { + for (uint64_t i = start; i <= end; i++) + fn(fn_data, i, trie_data_block_get(t, + (uint64_t *) node, i)); + + return end - start + 1; //TODO: overflow + } + + uint8_t parent_node_bit_off = depth == 0 ? + t->key_size : + trie_get_node_bit_offs(t, depth - 1); + + uint64_t first_key_in_node = start & + (uint64_t) -1 << parent_node_bit_off; + + uint8_t node_bit_off = trie_get_node_bit_offs(t, depth); + uint8_t node_key_bits = parent_node_bit_off - node_bit_off; + uint64_t mask = ((uint64_t) 1 << (node_key_bits)) - 1; + uint64_t start_index = (start >> node_bit_off) & mask; + uint64_t end_index = (end >> node_bit_off) & mask; + uint64_t child_key_count = (uint64_t) 1 << node_bit_off; + + uint64_t count = 0; + + for (uint64_t i = start_index; i <= end_index; i++) { + uint64_t child_start = first_key_in_node + i * child_key_count; + uint64_t child_end = first_key_in_node + + (i + 1) * child_key_count - 1; + + if (child_start < start) + child_start = start; + if (child_end > end) + child_end = end; + + count += trie_iterate_keys_node(t, fn, fn_data, + ((void **) node)[i], child_start, child_end, + depth + 1); + } + + return count; +} + +uint64_t trie_iterate_keys(struct trie *t, uint64_t start, uint64_t end, + trie_iterate_fn fn, void *fn_data) +{ + return trie_iterate_keys_node(t, fn, fn_data, t->data, + start, end, 0); +} + +static void +trie_free_node(struct trie *t, void *node, uint8_t depth) +{ + if (!node) + return; + + if (depth >= t->max_depth) + goto free_node; + + size_t sz = 1 << (trie_get_node_size(t, depth) - ptr_sz_lg); + for (size_t i = 0; i < sz; i++) + trie_free_node(t, ((void **) node)[i], depth + 1); + +free_node: + free(node); +} + +void +trie_free(struct trie *t) +{ + trie_free_node(t, t->data, 0); + free(t); +} diff --git a/trie.h b/trie.h new file mode 100644 index 00000000..f7058c7e --- /dev/null +++ b/trie.h @@ -0,0 +1,89 @@ +/* + * Simple trie interface + * + * Copyright (c) 2020 ?kos Uzonyi + * All rights reserved. + * + * SPDX-License-Identifier: LGPL-2.1-or-later + */ + +#ifndef STRACE_TRIE_H +#define STRACE_TRIE_H + +/** + * Trie control structure. + * Trie implemented here has the following properties: + * * It allows storing values of the same size, the size can vary from 1 bit to + * 64 bit values (only power of 2 sizes are allowed). + * * The key can be up to 64 bits in size. + * * It has separate configuration for node size and data block size. + * + * How bits of key are used for different node levels: + * + * highest bits lowest bits + * | node_key_bits | node_key_bits | ... | | data_block_key_bits | + * \_________________________________________________________________________/ + * key_size + * + * So, the remainder is used on the lowest non-data node level. + * + * As of now, it doesn't implement any mechanisms for resizing/changing key + * size. De-fragmentation is also unsupported currently. + */ +struct trie { + /** Return value of trie_get if key is not found */ + uint64_t empty_value; + + /** Pointer to root node */ + void *data; + + /** Key size in bits (0..64). */ + uint8_t key_size; + + /** + * Size of the stored values in log2 bits (0..6). + * (6: 64 bit values, 5: 32 bit values, ...) + */ + uint8_t item_size_lg; + + /** + * Number of bits in key that makes a symbol for a node. + * (equals to log2 of the child count of the node) + */ + uint8_t node_key_bits; + + /** + * Number of bits in key that make a symbol for the data block (leaf). + * (equals to log2 of the value count stored in a data block) + */ + uint8_t data_block_key_bits; + + /** The depth of the data block. Caluclated from the values above */ + uint8_t max_depth; +}; + +struct trie* trie_create(uint8_t key_size, uint8_t item_size_lg, + uint8_t node_key_bits, uint8_t data_block_key_bits, + uint64_t empty_value); + +bool trie_set(struct trie *t, uint64_t key, uint64_t val); +uint64_t trie_get(struct trie *t, uint64_t key); + +typedef void (*trie_iterate_fn)(void *data, uint64_t key, uint64_t val); + +/** + * Calls trie_iterate_fn for each key-value pair where + * key is inside the [start, end] interval (inclusive). + * + * @param t The trie. + * @param start The start of the key interval (inclusive). + * @param end The end of the key interval (inclusive). + * @param fn The function to be called. + * @param fn_data The value to be passed to fn. + */ +uint64_t trie_iterate_keys(struct trie *t, uint64_t start, uint64_t end, + trie_iterate_fn fn, void *fn_data); + +void trie_free(struct trie *t); + +#endif /* !STRACE_TRIE_H */ -- 2.27.0 From uzonyi.akos at gmail.com Mon Aug 3 19:19:14 2020 From: uzonyi.akos at gmail.com (=?UTF-8?q?=C3=81kos=20Uzonyi?=) Date: Mon, 3 Aug 2020 21:19:14 +0200 Subject: [PATCH v5 3/5] Use get_proc_pid for /proc paths In-Reply-To: <20200803191916.94724-1-uzonyi.akos@gmail.com> References: <20200803191916.94724-1-uzonyi.akos@gmail.com> Message-ID: <20200803191916.94724-4-uzonyi.akos@gmail.com> * mmap_cache.c (mmap_cache_rebuild_if_invalid): Use proc pid instead of tcp->pid for /proc path. * util.c (getfdproto): Likewise. (pidfd_get_pid): Likewise. * pathtrace.c (getfdpath_pid): Likewise. * strace.c (attach_tcb): Likewise. --- mmap_cache.c | 2 +- pathtrace.c | 5 ++++- strace.c | 2 +- util.c | 7 +++++-- 4 files changed, 11 insertions(+), 5 deletions(-) diff --git a/mmap_cache.c b/mmap_cache.c index 89c62254..9825df26 100644 --- a/mmap_cache.c +++ b/mmap_cache.c @@ -84,7 +84,7 @@ mmap_cache_rebuild_if_invalid(struct tcb *tcp, const char *caller) return MMAP_CACHE_REBUILD_READY; char filename[sizeof("/proc/4294967296/maps")]; - xsprintf(filename, "/proc/%u/maps", tcp->pid); + xsprintf(filename, "/proc/%u/maps", get_proc_pid(tcp)); FILE *fp = fopen_stream(filename, "r"); if (!fp) { diff --git a/pathtrace.c b/pathtrace.c index 5b60762b..74717a8a 100644 --- a/pathtrace.c +++ b/pathtrace.c @@ -87,7 +87,10 @@ getfdpath_pid(pid_t pid, int fd, char *buf, unsigned bufsize) if (fd < 0) return -1; - xsprintf(linkpath, "/proc/%u/fd/%u", pid, fd); + int proc_pid = 0; + translate_pid(NULL, pid, PT_TID, &proc_pid); + + xsprintf(linkpath, "/proc/%u/fd/%u", proc_pid, fd); n = readlink(linkpath, buf, bufsize - 1); /* * NB: if buf is too small, readlink doesn't fail, diff --git a/strace.c b/strace.c index 249533ea..ef23f08f 100644 --- a/strace.c +++ b/strace.c @@ -1196,7 +1196,7 @@ attach_tcb(struct tcb *const tcp) unsigned int ntid = 0, nerr = 0; if (followfork && tcp->pid != strace_child && - xsprintf(procdir, task_path, tcp->pid) > 0 && + xsprintf(procdir, task_path, get_proc_pid(tcp)) > 0 && (dir = opendir(procdir)) != NULL) { struct_dirent *de; diff --git a/util.c b/util.c index 094e5818..d87d022e 100644 --- a/util.c +++ b/util.c @@ -501,7 +501,7 @@ getfdproto(struct tcb *tcp, int fd) if (fd < 0) return SOCK_PROTO_UNKNOWN; - xsprintf(path, "/proc/%u/fd/%u", tcp->pid, fd); + xsprintf(path, "/proc/%u/fd/%u", get_proc_pid(tcp), fd); r = getxattr(path, "system.sockprotoname", buf, bufsize - 1); if (r <= 0) return SOCK_PROTO_UNKNOWN; @@ -582,8 +582,11 @@ printdev(struct tcb *tcp, int fd, const char *path) pid_t pidfd_get_pid(pid_t pid_of_fd, int fd) { + int proc_pid = 0; + translate_pid(NULL, pid_of_fd, PT_TID, &proc_pid); + char fdi_path[sizeof("/proc/%u/fdinfo/%u") + 2 * sizeof(int) * 3]; - xsprintf(fdi_path, "/proc/%u/fdinfo/%u", pid_of_fd, fd); + xsprintf(fdi_path, "/proc/%u/fdinfo/%u", proc_pid, fd); FILE *f = fopen_stream(fdi_path, "r"); if (!f) -- 2.27.0 From uzonyi.akos at gmail.com Mon Aug 3 19:19:16 2020 From: uzonyi.akos at gmail.com (=?UTF-8?q?=C3=81kos=20Uzonyi?=) Date: Mon, 3 Aug 2020 21:19:16 +0200 Subject: [PATCH v5 5/5] Add tests for PID namespace translation In-Reply-To: <20200803191916.94724-1-uzonyi.akos@gmail.com> References: <20200803191916.94724-1-uzonyi.akos@gmail.com> Message-ID: <20200803191916.94724-6-uzonyi.akos@gmail.com> * tests/.gitignore: Add new test executables. * tests/Makefile.am (check_PROGRAMS): Add new test executables. (DECODER_TESTS) Add new test files. * tests/gen_tests.in: Add new tests. * tests/fcntl-Y.c: New file. * tests/fcntl64-Y.c: New file. * tests/fork-Y.awk: New file. * tests/fork-Y.c: New file. * tests/fork-Y.test: New file. * tests/getpgrp-Y.c: New file. * tests/getpid-Y.c: New file. * tests/getsid-Y.c: New file. * tests/gettid-Y.c: New file. * tests/ioctl_block-Y.c: New file. * tests/ioctl_block-Y.test: New file. * tests/ioprio-Y.c: New file. * tests/kill-Y.c: New file. * tests/migrate_pages-Y.c: New file. * tests/move_pages-Y.c: New file. * tests/net-sockaddr-Y.c: New file. * tests/netlink_audit-Y.c: New file. * tests/netlink_audit-Y.test: New file. * tests/pidfd_open-Y.c: New file. * tests/pidfd_send_signal-Y.c: New file. * tests/prlimit64-Y.c: New file. * tests/process_vm_readv-Y.c: New file. * tests/process_vm_writev-Y.c: New file. * tests/rt_sigqueueinfo-Y.c: New file. * tests/rt_tgsigqueueinfo-Y.c: New file. * tests/sched_xetaffinity-Y.c: New file. * tests/sched_xetattr-Y.c: New file. * tests/sched_xetparam-Y.c: New file. * tests/sched_xetscheduler-Y.c: New file. * tests/signal_receive-Y.c: New file. * tests/so_peercred-Y.c: New file. * tests/xet_robust_list-Y.c: New file. * tests/xetpgid-Y.c: New file. * tests/xetpriority-Y.c: New file. * tests/fcntl-common.c: Print PID translation string after PIDs. * tests/fcntl.c: Likewise. * tests/fcntl64.c: Likewise. * tests/getpgrp.c: Likewise. * tests/getpid.c: Likewise. * tests/getsid.c: Likewise. * tests/gettid.c: Likewise. * tests/ioctl_block.c: Likewise. * tests/ioprio.c: Likewise. * tests/kcmp.c: Likewise. * tests/kill.c: Likewise. * tests/migrate_pages.c: Likewise. * tests/move_pages.c: Likewise. * tests/net-sockaddr.c: Likewise. * tests/netlink_audit.c: Likewise. * tests/pidfd_open.c: Likewise. * tests/pidfd_send_signal.c: Likewise. * tests/prlimit64.c: Likewise. * tests/process_vm_readv_writev.c: Likewise. * tests/rt_sigqueueinfo.c: Likewise. * tests/rt_tgsigqueueinfo.c: Likewise. * tests/sched_xetaffinity.c: Likewise. * tests/sched_xetattr.c: Likewise. * tests/sched_xetparam.c: Likewise. * tests/sched_xetscheduler.c: Likewise. * tests/signal_receive.c: Likewise. * tests/so_peercred.c: Likewise. * tests/xet_robust_list.c: Likewise. * tests/xetpgid.c: Likewise. * tests/xetpriority.c: Likewise. --- tests/.gitignore | 31 +++++++ tests/Makefile.am | 35 ++++++++ tests/fcntl--pidns-translation.c | 2 + tests/fcntl-common.c | 82 ++++++++++++++----- tests/fcntl.c | 1 + tests/fcntl64--pidns-translation.c | 2 + tests/fcntl64.c | 3 + tests/fork--pidns-translation.awk | 15 ++++ tests/fork--pidns-translation.c | 69 ++++++++++++++++ tests/fork--pidns-translation.test | 16 ++++ tests/gen_tests.in | 30 ++++++- tests/getpgrp--pidns-translation.c | 2 + tests/getpgrp.c | 8 +- tests/getpid--pidns-translation.c | 2 + tests/getpid.c | 8 +- tests/getsid--pidns-translation.c | 2 + tests/getsid.c | 9 +- tests/gettid--pidns-translation.c | 2 + tests/gettid.c | 8 +- tests/ioctl_block--pidns-translation.c | 2 + tests/ioctl_block--pidns-translation.test | 24 ++++++ tests/ioctl_block.c | 24 +++++- tests/ioprio--pidns-translation.c | 2 + tests/ioprio.c | 54 ++++++++---- tests/kcmp-y--pidns-translation.c | 2 + tests/kcmp.c | 11 ++- tests/kill--pidns-translation.c | 2 + tests/kill.c | 12 ++- tests/migrate_pages--pidns-translation.c | 2 + tests/migrate_pages.c | 17 +++- tests/move_pages--pidns-translation.c | 2 + tests/move_pages.c | 51 +++++++----- tests/net-sockaddr--pidns-translation.c | 2 + tests/net-sockaddr.c | 66 +++++++++++++-- tests/netlink_audit--pidns-translation.c | 2 + tests/netlink_audit--pidns-translation.test | 13 +++ tests/netlink_audit.c | 11 ++- tests/pidfd_open--pidns-translation.c | 2 + tests/pidfd_open.c | 21 +++-- tests/pidfd_send_signal--pidns-translation.c | 2 + tests/pidfd_send_signal.c | 13 ++- tests/prlimit64--pidns-translation.c | 2 + tests/prlimit64.c | 17 +++- tests/process_vm_readv--pidns-translation.c | 2 + tests/process_vm_readv_writev.c | 27 +++--- tests/process_vm_writev--pidns-translation.c | 2 + tests/rt_sigqueueinfo--pidns-translation.c | 2 + tests/rt_sigqueueinfo.c | 15 +++- tests/rt_tgsigqueueinfo--pidns-translation.c | 2 + tests/rt_tgsigqueueinfo.c | 26 ++++-- tests/sched_xetaffinity--pidns-translation.c | 2 + tests/sched_xetaffinity.c | 31 ++++--- tests/sched_xetattr--pidns-translation.c | 2 + tests/sched_xetattr.c | 47 ++++++++++- tests/sched_xetparam--pidns-translation.c | 2 + tests/sched_xetparam.c | 20 +++-- tests/sched_xetscheduler--pidns-translation.c | 2 + tests/sched_xetscheduler.c | 44 ++++++---- tests/signal_receive--pidns-translation.c | 2 + tests/signal_receive.c | 22 +++-- tests/so_peercred--pidns-translation.c | 2 + tests/so_peercred.c | 22 +++++ tests/xet_robust_list--pidns-translation.c | 2 + tests/xet_robust_list.c | 18 +++- tests/xetpgid--pidns-translation.c | 2 + tests/xetpgid.c | 21 +++-- tests/xetpriority--pidns-translation.c | 2 + tests/xetpriority.c | 20 ++++- 68 files changed, 854 insertions(+), 168 deletions(-) create mode 100644 tests/fcntl--pidns-translation.c create mode 100644 tests/fcntl64--pidns-translation.c create mode 100644 tests/fork--pidns-translation.awk create mode 100644 tests/fork--pidns-translation.c create mode 100755 tests/fork--pidns-translation.test create mode 100644 tests/getpgrp--pidns-translation.c create mode 100644 tests/getpid--pidns-translation.c create mode 100644 tests/getsid--pidns-translation.c create mode 100644 tests/gettid--pidns-translation.c create mode 100644 tests/ioctl_block--pidns-translation.c create mode 100755 tests/ioctl_block--pidns-translation.test create mode 100644 tests/ioprio--pidns-translation.c create mode 100644 tests/kcmp-y--pidns-translation.c create mode 100644 tests/kill--pidns-translation.c create mode 100644 tests/migrate_pages--pidns-translation.c create mode 100644 tests/move_pages--pidns-translation.c create mode 100644 tests/net-sockaddr--pidns-translation.c create mode 100644 tests/netlink_audit--pidns-translation.c create mode 100755 tests/netlink_audit--pidns-translation.test create mode 100644 tests/pidfd_open--pidns-translation.c create mode 100644 tests/pidfd_send_signal--pidns-translation.c create mode 100644 tests/prlimit64--pidns-translation.c create mode 100644 tests/process_vm_readv--pidns-translation.c create mode 100644 tests/process_vm_writev--pidns-translation.c create mode 100644 tests/rt_sigqueueinfo--pidns-translation.c create mode 100644 tests/rt_tgsigqueueinfo--pidns-translation.c create mode 100644 tests/sched_xetaffinity--pidns-translation.c create mode 100644 tests/sched_xetattr--pidns-translation.c create mode 100644 tests/sched_xetparam--pidns-translation.c create mode 100644 tests/sched_xetscheduler--pidns-translation.c create mode 100644 tests/signal_receive--pidns-translation.c create mode 100644 tests/so_peercred--pidns-translation.c create mode 100644 tests/xet_robust_list--pidns-translation.c create mode 100644 tests/xetpgid--pidns-translation.c create mode 100644 tests/xetpriority--pidns-translation.c diff --git a/tests/.gitignore b/tests/.gitignore index 0031d04d..4d1153fc 100644 --- a/tests/.gitignore +++ b/tests/.gitignore @@ -116,7 +116,9 @@ fchown fchown32 fchownat fcntl +fcntl--pidns-translation fcntl64 +fcntl64--pidns-translation fdatasync fflush file_handle @@ -126,6 +128,7 @@ filter-unavailable finit_module flock fork-f +fork--pidns-translation fsconfig fsconfig-P fsmount @@ -168,7 +171,9 @@ getgroups getgroups32 getpeername getpgrp +getpgrp--pidns-translation getpid +getpid--pidns-translation getppid getrandom getresgid @@ -178,8 +183,10 @@ getresuid32 getrlimit getrusage getsid +getsid--pidns-translation getsockname gettid +gettid--pidns-translation getuid getuid32 getxgid @@ -200,6 +207,7 @@ io_uring_register io_uring_setup ioctl ioctl_block +ioctl_block--pidns-translation ioctl_dm ioctl_dm-v ioctl_evdev @@ -275,6 +283,7 @@ ioctl_watchdog ioperm iopl ioprio +ioprio--pidns-translation ioprio-Xabbrev ioprio-Xraw ioprio-Xverbose @@ -299,6 +308,7 @@ ipc_shm-Xverbose is_linux_mips_n64 kcmp kcmp-y +kcmp-y--pidns-translation kern_features kernel_version kernel_version-Xabbrev @@ -311,6 +321,7 @@ keyctl-Xabbrev keyctl-Xraw keyctl-Xverbose kill +kill--pidns-translation kill_child ksysent ksysent.h @@ -340,6 +351,7 @@ memfd_create-Xabbrev memfd_create-Xraw memfd_create-Xverbose migrate_pages +migrate_pages--pidns-translation mincore mkdir mkdirat @@ -371,6 +383,7 @@ move_pages move_pages-Xabbrev move_pages-Xraw move_pages-Xverbose +move_pages--pidns-translation mq mq_sendrecv mq_sendrecv-read @@ -391,6 +404,7 @@ net-packet_mreq-Xabbrev net-packet_mreq-Xraw net-packet_mreq-Xverbose net-sockaddr +net-sockaddr--pidns-translation net-tpacket_req net-tpacket_stats net-tpacket_stats-success @@ -400,6 +414,7 @@ net-yy-inet6 net-yy-netlink net-yy-unix netlink_audit +netlink_audit--pidns-translation netlink_crypto netlink_generic netlink_inet_diag @@ -507,7 +522,9 @@ pidfd_open--decode-fd-socket pidfd_open-P pidfd_open-y pidfd_open-yy +pidfd_open--pidns-translation pidfd_send_signal +pidfd_send_signal--pidns-translation pipe pipe2 pkey_alloc @@ -546,8 +563,11 @@ printstrn-umoven printstrn-umoven-peekdata printstrn-umoven-undumpable prlimit64 +prlimit64--pidns-translation process_vm_readv +process_vm_readv--pidns-translation process_vm_writev +process_vm_writev--pidns-translation pselect6 ptrace ptrace_syscall_info @@ -597,10 +617,12 @@ rt_sigaction rt_sigpending rt_sigprocmask rt_sigqueueinfo +rt_sigqueueinfo--pidns-translation rt_sigreturn rt_sigsuspend rt_sigtimedwait rt_tgsigqueueinfo +rt_tgsigqueueinfo--pidns-translation run_expect_termsig s390_guarded_storage s390_guarded_storage-v @@ -611,9 +633,13 @@ s390_sthyi-v sched_get_priority_mxx sched_rr_get_interval sched_xetaffinity +sched_xetaffinity--pidns-translation sched_xetattr +sched_xetattr--pidns-translation sched_xetparam +sched_xetparam--pidns-translation sched_xetscheduler +sched_xetscheduler--pidns-translation sched_yield scm_rights scno.h @@ -669,6 +695,7 @@ sigaltstack siginfo signal signal_receive +signal_receive--pidns-translation signalfd4 sigpending sigprocmask @@ -681,6 +708,7 @@ so_peercred so_peercred-Xabbrev so_peercred-Xraw so_peercred-Xverbose +so_peercred--pidns-translation sock_filter-v sock_filter-v-Xabbrev sock_filter-v-Xraw @@ -783,9 +811,12 @@ waitpid xattr xattr-strings xet_robust_list +xet_robust_list--pidns-translation xet_thread_area_x86 xetitimer xetpgid +xetpgid--pidns-translation xetpriority +xetpriority--pidns-translation xettimeofday zeroargc diff --git a/tests/Makefile.am b/tests/Makefile.am index 7a583a3a..05e350bd 100644 --- a/tests/Makefile.am +++ b/tests/Makefile.am @@ -109,17 +109,25 @@ check_PROGRAMS = $(PURE_EXECUTABLES) \ delay \ execve-v \ execveat-v \ + fcntl--pidns-translation \ + fcntl64--pidns-translation \ filter_seccomp-flag \ filter_seccomp-perf \ filter-unavailable \ fork-f \ + fork--pidns-translation \ fsync-y \ get_process_reaper \ + getpgrp--pidns-translation \ getpid \ + getpid--pidns-translation \ getppid \ + getsid--pidns-translation \ gettid \ + gettid--pidns-translation \ inject-nf \ int_0x80 \ + ioctl_block--pidns-translation \ ioctl_dm-v \ ioctl_evdev-success \ ioctl_evdev-success-Xabbrev \ @@ -150,18 +158,25 @@ check_PROGRAMS = $(PURE_EXECUTABLES) \ ioctl_v4l2-success-v-Xabbrev \ ioctl_v4l2-success-v-Xraw \ ioctl_v4l2-success-v-Xverbose \ + ioprio--pidns-translation \ is_linux_mips_n64 \ + kcmp-y--pidns-translation \ kill_child \ + kill--pidns-translation \ ksysent \ list_sigaction_signum \ localtime \ looping_threads \ + migrate_pages--pidns-translation \ mmsg-silent \ mmsg_name-v \ + move_pages--pidns-translation \ msg_control-v \ net-accept-connect \ + net-sockaddr--pidns-translation \ net-tpacket_stats-success \ nlattr_ifla_xdp-y \ + netlink_audit--pidns-translation \ netlink_inet_diag \ netlink_netlink_diag \ netlink_unix_diag \ @@ -173,14 +188,19 @@ check_PROGRAMS = $(PURE_EXECUTABLES) \ pc \ perf_event_open_nonverbose \ perf_event_open_unabbrev \ + pidfd_open--pidns-translation \ + pidfd_send_signal--pidns-translation \ poll-P \ ppoll-P \ ppoll-v \ + prlimit64--pidns-translation \ prctl-seccomp-filter-v \ prctl-seccomp-strict \ prctl-spec-inject \ print_maxfd \ print_ppid_tracerpid \ + process_vm_readv--pidns-translation \ + process_vm_writev--pidns-translation \ qual_fault \ qual_inject-error-signal \ qual_inject-retval \ @@ -194,7 +214,13 @@ check_PROGRAMS = $(PURE_EXECUTABLES) \ quotactl-xfs-v \ redirect-fds \ restart_syscall \ + rt_sigqueueinfo--pidns-translation \ + rt_tgsigqueueinfo--pidns-translation \ run_expect_termsig \ + sched_xetaffinity--pidns-translation \ + sched_xetattr--pidns-translation \ + sched_xetparam--pidns-translation \ + sched_xetscheduler--pidns-translation \ scm_rights \ seccomp-filter-v \ seccomp-strict \ @@ -204,12 +230,14 @@ check_PROGRAMS = $(PURE_EXECUTABLES) \ set_sigign \ setpgrp-exec \ signal_receive \ + signal_receive--pidns-translation \ sleep \ stack-fcall \ stack-fcall-attach \ stack-fcall-mangled \ status-none-threads \ status-unfinished-threads \ + so_peercred--pidns-translation \ syslog-success \ threads-execve \ threads-execve--quiet-thread-execve \ @@ -223,6 +251,9 @@ check_PROGRAMS = $(PURE_EXECUTABLES) \ vfork-f \ wait4-v \ waitid-v \ + xetpgid--pidns-translation \ + xetpriority--pidns-translation \ + xet_robust_list--pidns-translation \ zeroargc \ # end of check_PROGRAMS @@ -310,6 +341,7 @@ DECODER_TESTS = \ int_0x80.test \ inotify_init-y.test \ ioctl.test \ + ioctl_block--pidns-translation.test \ ioctl_evdev-success.test \ ipc_msgbuf.test \ kern_features-fault.test \ @@ -381,12 +413,14 @@ MISC_TESTS = \ filtering_fd-syntax.test \ filtering_syscall-syntax.test \ first_exec_failure.test \ + fork--pidns-translation.test \ get_regs.test \ inject-nf.test \ interactive_block.test \ kill_child.test \ localtime.test \ looping_threads.test \ + netlink_audit--pidns-translation.test \ opipe.test \ options-syntax.test \ pc.test \ @@ -467,6 +501,7 @@ EXTRA_DIST = \ filter_seccomp.in \ filter_seccomp.sh \ filter-unavailable.expected \ + fork--pidns-translation.awk \ fstatat.c \ fstatx.c \ gen_pure_executables.sh \ diff --git a/tests/fcntl--pidns-translation.c b/tests/fcntl--pidns-translation.c new file mode 100644 index 00000000..e249424a --- /dev/null +++ b/tests/fcntl--pidns-translation.c @@ -0,0 +1,2 @@ +#define PIDNS_TRANSLATION +#include "fcntl.c" diff --git a/tests/fcntl-common.c b/tests/fcntl-common.c index 27694326..d9e29939 100644 --- a/tests/fcntl-common.c +++ b/tests/fcntl-common.c @@ -13,6 +13,8 @@ #include #include #include "flock.h" +#include "pidns.h" +#include "scno.h" #define FILE_LEN 4096 @@ -48,12 +50,14 @@ test_flock_einval(const int cmd, const char *name) fl->l_len = (TYPEOF_FLOCK_OFF_T) 0xdefaced2cafef00dULL; invoke_test_syscall(0, cmd, fl); + pidns_print_leader(); printf("%s(0, %s, {l_type=F_RDLCK, l_whence=SEEK_SET" ", l_start=%jd, l_len=%jd}) = %s\n", TEST_SYSCALL_STR, name, (intmax_t) fl->l_start, (intmax_t) fl->l_len, errstr); void *const bad_addr = (void *) fl + 1; invoke_test_syscall(0, cmd, bad_addr); + pidns_print_leader(); printf("%s(0, %s, %p) = %s\n", TEST_SYSCALL_STR, name, bad_addr, errstr); } @@ -72,12 +76,14 @@ test_flock64_einval(const int cmd, const char *name) fl->l_len = (TYPEOF_FLOCK_OFF_T) 0xdefaced2cafef00dULL; invoke_test_syscall(0, cmd, fl); + pidns_print_leader(); printf("%s(0, %s, {l_type=F_RDLCK, l_whence=SEEK_SET" ", l_start=%jd, l_len=%jd}) = %s\n", TEST_SYSCALL_STR, name, (intmax_t) fl->l_start, (intmax_t) fl->l_len, errstr); void *const bad_addr = (void *) fl + 1; invoke_test_syscall(0, cmd, bad_addr); + pidns_print_leader(); printf("%s(0, %s, %p) = %s\n", TEST_SYSCALL_STR, name, bad_addr, errstr); } @@ -94,6 +100,7 @@ test_flock(void) fl->l_len = FILE_LEN; long rc = invoke_test_syscall(0, F_SETLK, fl); + pidns_print_leader(); printf("%s(0, F_SETLK, {l_type=F_RDLCK, l_whence=SEEK_SET" ", l_start=0, l_len=%d}) = %s\n", TEST_SYSCALL_STR, FILE_LEN, errstr); @@ -101,11 +108,13 @@ test_flock(void) return; invoke_test_syscall(0, F_GETLK, fl); + pidns_print_leader(); printf("%s(0, F_GETLK, {l_type=F_UNLCK, l_whence=SEEK_SET" ", l_start=0, l_len=%d, l_pid=0}) = 0\n", TEST_SYSCALL_STR, FILE_LEN); invoke_test_syscall(0, F_SETLKW, fl); + pidns_print_leader(); printf("%s(0, F_SETLKW, {l_type=F_UNLCK, l_whence=SEEK_SET" ", l_start=0, l_len=%d}) = 0\n", TEST_SYSCALL_STR, FILE_LEN); @@ -124,6 +133,7 @@ test_flock64_ofd(void) fl->l_len = FILE_LEN; long rc = invoke_test_syscall(0, F_OFD_SETLK, fl); + pidns_print_leader(); printf("%s(0, F_OFD_SETLK, {l_type=F_RDLCK, l_whence=SEEK_SET" ", l_start=0, l_len=%d}) = %s\n", TEST_SYSCALL_STR, FILE_LEN, errstr); @@ -131,11 +141,13 @@ test_flock64_ofd(void) return; invoke_test_syscall(0, F_OFD_GETLK, fl); + pidns_print_leader(); printf("%s(0, F_OFD_GETLK, {l_type=F_UNLCK, l_whence=SEEK_SET" ", l_start=0, l_len=%d, l_pid=0}) = 0\n", TEST_SYSCALL_STR, FILE_LEN); invoke_test_syscall(0, F_OFD_SETLKW, fl); + pidns_print_leader(); printf("%s(0, F_OFD_SETLKW, {l_type=F_UNLCK, l_whence=SEEK_SET" ", l_start=0, l_len=%d}) = 0\n", TEST_SYSCALL_STR, FILE_LEN); @@ -167,18 +179,21 @@ test_flock64(void) static long test_f_owner_ex_type_pid(const int cmd, const char *const cmd_name, const int type, const char *const type_name, - pid_t pid) + enum pid_type pid_type, pid_t pid) { TAIL_ALLOC_OBJECT_CONST_PTR(struct_kernel_f_owner_ex, fo); fo->type = type; fo->pid = pid; long rc = invoke_test_syscall(0, cmd, fo); - printf("%s(0, %s, {type=%s, pid=%d}) = %s\n", - TEST_SYSCALL_STR, cmd_name, type_name, fo->pid, errstr); + pidns_print_leader(); + printf("%s(0, %s, {type=%s, pid=%d%s}) = %s\n", + TEST_SYSCALL_STR, cmd_name, type_name, + fo->pid, pidns_pid2str(pid_type), errstr); void *bad_addr = (void *) fo + 1; invoke_test_syscall(0, cmd, bad_addr); + pidns_print_leader(); printf("%s(0, %s, %p) = %s\n", TEST_SYSCALL_STR, cmd_name, bad_addr, errstr); @@ -187,35 +202,39 @@ test_f_owner_ex_type_pid(const int cmd, const char *const cmd_name, static void test_f_owner_ex_umove_or_printaddr(const int type, const char *const type_name, - pid_t pid) + enum pid_type pid_type, pid_t pid) { long rc = test_f_owner_ex_type_pid(ARG_STR(F_SETOWN_EX), - type, type_name, pid); + type, type_name, pid_type, pid); if (!rc) test_f_owner_ex_type_pid(ARG_STR(F_GETOWN_EX), - type, type_name, pid); + type, type_name, pid_type, pid); } static void test_f_owner_ex(void) { - static const struct { + struct { int type; const char *type_name; - pid_t pid[2]; + enum pid_type pid_type; + pid_t pid; } a[] = { - { ARG_STR(F_OWNER_TID), { 1234567890, 20 } }, - { ARG_STR(F_OWNER_PID), { 1298126790, 30 } }, - { ARG_STR(F_OWNER_PGRP), { 1294567890, 40 } } + { ARG_STR(F_OWNER_TID), PT_NONE, 1234567890 }, + { ARG_STR(F_OWNER_PID), PT_NONE, 1234567890 }, + { ARG_STR(F_OWNER_PGRP), PT_NONE, 1234567890 }, + { ARG_STR(F_OWNER_TID), PT_TID, 0 }, + { ARG_STR(F_OWNER_PID), PT_TGID, 0 }, + { ARG_STR(F_OWNER_PGRP), PT_PGID, 0 }, }; - for (unsigned int i = 0; i < ARRAY_SIZE(a); i++) { - for (unsigned int j = 0; j < ARRAY_SIZE(a[0].pid); j++) { - test_f_owner_ex_umove_or_printaddr(a[i].type, - a[i].type_name, - a[i].pid[j]); - } - } + a[3].pid = syscall(__NR_gettid); + a[4].pid = getpid(); + a[5].pid = getpgid(0); + + for (unsigned int i = 0; i < ARRAY_SIZE(a); i++) + test_f_owner_ex_umove_or_printaddr(a[i].type, a[i].type_name, + a[i].pid_type, a[i].pid); } #endif /* TEST_F_OWNER_EX */ @@ -228,6 +247,23 @@ struct fcntl_cmd_check { void (*print_flags)(long rc); }; +static void +test_xetown(void) +{ + const int pid = getpid(); + const char *pid_str = pidns_pid2str(PT_TGID); + + invoke_test_syscall(0, F_SETOWN, (void *) (intptr_t) pid); + pidns_print_leader(); + printf("%s(0, F_SETOWN, %d%s) = %s\n", + TEST_SYSCALL_STR, pid, pid_str, errstr); + + invoke_test_syscall(0, F_GETOWN, NULL); + pidns_print_leader(); + printf("%s(0, F_GETOWN) = %d%s\n", + TEST_SYSCALL_STR, pid, pid_str); +} + static void print_retval_flags(const struct fcntl_cmd_check *check, long rc) { @@ -243,12 +279,14 @@ static void test_other_set_cmd(const struct fcntl_cmd_check *check) { invoke_test_syscall(check->fd, check->cmd, (void *) check->arg); + pidns_print_leader(); printf("%s(%d, %s, %s) = %s\n", TEST_SYSCALL_STR, check->fd, check->cmd_str, check->arg_str, errstr); /* bad file fd */ invoke_test_syscall(-1, check->cmd, (void *) check->arg); + pidns_print_leader(); printf("%s(-1, %s, %s) = %s\n", TEST_SYSCALL_STR, check->cmd_str, check->arg_str, errstr); @@ -258,12 +296,14 @@ static void test_other_get_cmd(const struct fcntl_cmd_check *check) { long rc = invoke_test_syscall(check->fd, check->cmd, NULL); + pidns_print_leader(); printf("%s(%d, %s) = ", TEST_SYSCALL_STR, check->fd, check->cmd_str); print_retval_flags(check, rc); /* bad file fd */ invoke_test_syscall(-1, check->cmd, NULL); + pidns_print_leader(); printf("%s(-1, %s) = %s\n", TEST_SYSCALL_STR, check->cmd_str, errstr); } @@ -315,7 +355,6 @@ test_fcntl_others(void) { static const struct fcntl_cmd_check set_checks[] = { { 0, ARG_STR(F_SETFD), ARG_STR(FD_CLOEXEC) }, - { 0, ARG_STR(F_SETOWN), ARG_STR(20) }, #ifdef F_SETPIPE_SZ { 0, ARG_STR(F_SETPIPE_SZ), ARG_STR(4097) }, #endif @@ -336,7 +375,6 @@ test_fcntl_others(void) static const struct fcntl_cmd_check get_checks[] = { { 0, ARG_STR(F_GETFD), .print_flags = print_flags_getfd }, { 1, ARG_STR(F_GETFD), .print_flags = print_flags_getfd }, - { 0, ARG_STR(F_GETOWN) }, #ifdef F_GETPIPE_SZ { 0, ARG_STR(F_GETPIPE_SZ) }, #endif @@ -360,6 +398,8 @@ create_sample(void) int main(void) { + PIDNS_TEST_INIT; + create_sample(); test_flock(); test_flock64(); @@ -367,7 +407,9 @@ main(void) test_f_owner_ex(); #endif test_fcntl_others(); + test_xetown(); + pidns_print_leader(); puts("+++ exited with 0 +++"); return 0; } diff --git a/tests/fcntl.c b/tests/fcntl.c index f38b8afb..673c06e4 100644 --- a/tests/fcntl.c +++ b/tests/fcntl.c @@ -24,6 +24,7 @@ test_flock64_undecoded(const int cmd, const char *name) .l_len = 0xdefaced2cafef00dULL }; invoke_test_syscall(0, cmd, &fl); + pidns_print_leader(); printf("%s(0, %s, %p) = %s\n", TEST_SYSCALL_STR, name, &fl, errstr); } diff --git a/tests/fcntl64--pidns-translation.c b/tests/fcntl64--pidns-translation.c new file mode 100644 index 00000000..c6fdadd1 --- /dev/null +++ b/tests/fcntl64--pidns-translation.c @@ -0,0 +1,2 @@ +#define PIDNS_TRANSLATION +#include "fcntl64.c" diff --git a/tests/fcntl64.c b/tests/fcntl64.c index 78e53b0d..f7b3f2fb 100644 --- a/tests/fcntl64.c +++ b/tests/fcntl64.c @@ -27,6 +27,7 @@ test_flock64_lk64(void) fl->l_len = FILE_LEN; long rc = invoke_test_syscall(0, F_SETLK64, fl); + pidns_print_leader(); printf("%s(0, F_SETLK64, {l_type=F_RDLCK, l_whence=SEEK_SET" ", l_start=0, l_len=%d}) = %s\n", TEST_SYSCALL_STR, FILE_LEN, errstr); @@ -35,11 +36,13 @@ test_flock64_lk64(void) return; invoke_test_syscall(0, F_GETLK64, fl); + pidns_print_leader(); printf("%s(0, F_GETLK64, {l_type=F_UNLCK, l_whence=SEEK_SET" ", l_start=0, l_len=%d, l_pid=0}) = 0\n", TEST_SYSCALL_STR, FILE_LEN); invoke_test_syscall(0, F_SETLKW64, fl); + pidns_print_leader(); printf("%s(0, F_SETLKW64, {l_type=F_UNLCK, l_whence=SEEK_SET" ", l_start=0, l_len=%d}) = 0\n", TEST_SYSCALL_STR, FILE_LEN); diff --git a/tests/fork--pidns-translation.awk b/tests/fork--pidns-translation.awk new file mode 100644 index 00000000..ef6858f4 --- /dev/null +++ b/tests/fork--pidns-translation.awk @@ -0,0 +1,15 @@ +/fork/ { + match($0, "([0-9]+) in strace\x27s PID NS", a); + if (a[1]) + fork_pid = a[1] +} + +/exited with 0/ { + if (!exit_pid) + exit_pid = $1 +} + +END { + if (!fork_pid || !exit_pid || fork_pid != exit_pid) + exit 1 +} diff --git a/tests/fork--pidns-translation.c b/tests/fork--pidns-translation.c new file mode 100644 index 00000000..73c39d5d --- /dev/null +++ b/tests/fork--pidns-translation.c @@ -0,0 +1,69 @@ +/* + * Test PID namespace translation + * + * Copyright (c) 2020 ?kos Uzonyi + * All rights reserved. + * + * SPDX-License-Identifier: LGPL-2.1-or-later + */ + +#include "tests.h" +#include "scno.h" +#include "pidns.h" + +#ifdef __NR_fork + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +static int +fork_chain(int depth) +{ + if (!depth) + return 0; + + int pid = syscall(__NR_fork); + if (pid < 0) + return errno; + + if (!pid) + _exit(fork_chain(depth - 1)); + + int status; + if (wait(&status) < 0) + return errno; + + if (!WIFEXITED(status)) + return -1; + + return WEXITSTATUS(status); +} + +int main(void) +{ + check_ns_ioctl(); + + if (unshare(CLONE_NEWPID | CLONE_NEWUSER) < 0) { + if (errno == EPERM) + perror_msg_and_skip("unshare"); + + perror_msg_and_fail("unshare"); + } + + errno = fork_chain(2); + if (errno) + perror("fork_chain"); +} + +#else + +SKIP_MAIN_UNDEFINED("__NR_fork") + +#endif diff --git a/tests/fork--pidns-translation.test b/tests/fork--pidns-translation.test new file mode 100755 index 00000000..fa7ecda5 --- /dev/null +++ b/tests/fork--pidns-translation.test @@ -0,0 +1,16 @@ +#!/bin/sh +# +# Check pidns translation of fork's return value. +# +# Copyright (c) 2020 The strace developers. +# All rights reserved. +# +# SPDX-License-Identifier: LGPL-2.1-or-later + +. "${srcdir=.}/init.sh" + +require_min_kernel_version_or_skip 4.9 + +run_prog +run_strace -a6 --pidns-translation -f -e trace=fork $args +match_awk diff --git a/tests/gen_tests.in b/tests/gen_tests.in index 6f8e1420..56e5b5e1 100644 --- a/tests/gen_tests.in +++ b/tests/gen_tests.in @@ -93,7 +93,9 @@ fchown -a16 fchown32 -a18 fchownat fcntl -a8 +fcntl--pidns-translation test_pidns -a8 -e trace=fcntl fcntl64 -a8 +fcntl64--pidns-translation test_pidns -a8 -e trace=fcntl64 fdatasync -a14 file_handle -e trace=name_to_handle_at,open_by_handle_at file_ioctl +ioctl.test @@ -147,7 +149,9 @@ getgroups -a17 getgroups32 -a19 getpeername -a27 getpgrp -a10 +getpgrp--pidns-translation test_pidns -e trace=getpgrp -a10 getpid -a9 +getpid--pidns-translation test_pidns -e trace=getpid -a9 getppid -a10 getrandom -a32 -s3 getresgid -a25 @@ -157,8 +161,10 @@ getresuid32 -a27 getrlimit -a27 getrusage -v getsid -a10 +getsid--pidns-translation test_pidns -e trace=getsid -a10 getsockname -a27 gettid -a9 +gettid--pidns-translation test_pidns -e trace=gettid -a9 getuid-creds +getuid.test getuid32 +getuid.test getuid32-creds +getuid.test @@ -250,6 +256,7 @@ ioctl_watchdog +ioctl.test ioperm -a27 iopl -a8 ioprio -a18 -e trace=ioprio_get,ioprio_set +ioprio--pidns-translation test_pidns -a18 -e trace=ioprio_get,ioprio_set ioprio-Xabbrev -a18 -e trace=ioprio_get,ioprio_set -Xabbrev ioprio-Xraw -a18 -e trace=ioprio_get,ioprio_set -Xraw ioprio-Xverbose -a18 -e trace=ioprio_get,ioprio_set -Xverbose @@ -272,6 +279,7 @@ ipc_shm-Xraw +ipc.sh -Xraw -a19 ipc_shm-Xverbose +ipc.sh -Xverbose -a34 kcmp -a22 kcmp-y -a22 -y -e trace=kcmp +kcmp-y--pidns-translation test_pidns -a22 -y -e trace=kcmp kern_features -a16 kernel_version -a16 -v -e trace=bpf kernel_version-Xabbrev -a16 -Xabbrev -v -e trace=bpf @@ -284,6 +292,7 @@ keyctl-Xabbrev -a31 -s10 -e trace=keyctl -Xabbrev keyctl-Xraw -a13 -s10 -e trace=keyctl -Xraw keyctl-Xverbose -a41 -s10 -e trace=keyctl -Xverbose kill -a12 -esignal=none +kill--pidns-translation test_pidns -a12 -e trace=kill -esignal=none ksysent ../$NAME lchown -a30 lchown32 -a32 @@ -305,6 +314,7 @@ memfd_create-Xabbrev -Xabbrev -e trace=memfd_create memfd_create-Xraw -a30 -Xraw -e trace=memfd_create memfd_create-Xverbose -Xverbose -e trace=memfd_create migrate_pages -a33 +migrate_pages--pidns-translation test_pidns -a33 -e trace=migrate_pages mincore -a22 mkdir -a20 mkdirat -a28 @@ -335,6 +345,7 @@ move_pages -s3 move_pages-Xabbrev -s3 -e trace=move_pages -Xabbrev move_pages-Xraw -s3 -a36 -e trace=move_pages -Xraw move_pages-Xverbose -s3 -e trace=move_pages -Xverbose +move_pages--pidns-translation test_pidns -s3 -e trace=move_pages mq -a32 -e trace=mq_getsetattr,mq_open,mq_unlink mq_sendrecv -a14 -e trace=mq_open,mq_notify,mq_timedsend,mq_timedreceive,mq_unlink mq_sendrecv-read -eread=0 -a14 -e trace=mq_open,mq_notify,mq_timedsend,mq_timedreceive,mq_unlink @@ -354,6 +365,7 @@ net-packet_mreq-Xabbrev -e trace=setsockopt -Xabbrev net-packet_mreq-Xraw -e trace=setsockopt -Xraw net-packet_mreq-Xverbose -e trace=setsockopt -Xverbose net-sockaddr -a24 -e trace=connect +net-sockaddr--pidns-translation test_pidns -a24 -e trace=connect net-tpacket_req -e trace=setsockopt net-tpacket_stats -e trace=getsockopt net-yy-inet6 +net-yy-inet.test @@ -457,7 +469,9 @@ pidfd_open--decode-fd-socket -a17 -e decode-fd=socket -e trace=pidfd_open pidfd_open-P -a17 -P /dev/full -e trace=pidfd_open pidfd_open-y -a17 -y -e trace=pidfd_open pidfd_open-yy -a17 -yy -e trace=pidfd_open +pidfd_open--pidns-translation test_pidns -a17 -e trace=pidfd_open pidfd_send_signal +pidfd_send_signal--pidns-translation test_pidns -e trace=pidfd_send_signal pipe2 -a15 pkey_alloc -a17 pkey_free -a13 @@ -480,8 +494,11 @@ printstrn-umoven -s4096 -e signal=none -e trace=add_key printstrn-umoven-peekdata -e signal=none -e trace=add_key printstrn-umoven-undumpable -e signal=none -e trace=add_key prlimit64 +prlimit64--pidns-translation test_pidns -e trace=prlimit64 process_vm_readv -s5 -a37 +process_vm_readv--pidns-translation test_pidns -s5 -a37 -e trace=process_vm_readv process_vm_writev -s5 -a38 +process_vm_writev--pidns-translation test_pidns -s5 -a38 -e trace=process_vm_writev pselect6 ptrace -a23 -e signal=none ptrace_syscall_info -a35 -e signal=none -e trace=ptrace @@ -518,10 +535,12 @@ rmdir -a22 rt_sigpending -a20 rt_sigprocmask rt_sigqueueinfo -esignal=none +rt_sigqueueinfo--pidns-translation test_pidns -esignal=none -e trace=rt_sigqueueinfo rt_sigreturn -esignal='!USR1' rt_sigsuspend -a20 -esignal=none rt_sigtimedwait -a38 rt_tgsigqueueinfo -esignal=none +rt_tgsigqueueinfo--pidns-translation test_pidns -esignal=none -e trace=rt_tgsigqueueinfo s390_guarded_storage -a32 s390_guarded_storage-v -e trace=s390_guarded_storage -a32 -v s390_pci_mmio_read_write -e trace=s390_pci_mmio_read,s390_pci_mmio_write -a30 @@ -532,9 +551,13 @@ sched test_trace_expr times -e/sched sched_get_priority_mxx -a33 -e trace=sched_get_priority_min,sched_get_priority_max sched_rr_get_interval -a31 sched_xetaffinity -a28 -e trace=sched_getaffinity,sched_setaffinity +sched_xetaffinity--pidns-translation test_pidns -a28 -e trace=sched_getaffinity,sched_setaffinity sched_xetattr -a29 -e trace=sched_getattr,sched_setattr +sched_xetattr--pidns-translation test_pidns -a29 -e trace=sched_getattr,sched_setattr sched_xetparam -a23 -e trace=sched_getparam,sched_setparam +sched_xetparam--pidns-translation test_pidns -a23 -e trace=sched_getparam,sched_setparam sched_xetscheduler -a22 -e trace=sched_getscheduler,sched_setscheduler +sched_xetscheduler--pidns-translation test_pidns -a22 -e trace=sched_getscheduler,sched_setscheduler sched_yield -a14 seccomp-filter -e trace=seccomp seccomp-filter-v -v -e trace=seccomp @@ -581,6 +604,7 @@ sigaction -a31 siginfo -e trace=none signal -a25 -e signal=none -e trace='/^signal$' signal_receive -a16 -e trace=kill +signal_receive--pidns-translation test_pidns -a16 -e trace=kill signalfd4 sigpending -a15 sigprocmask -a34 @@ -592,6 +616,7 @@ so_peercred -e trace=getsockopt so_peercred-Xabbrev -e trace=getsockopt -Xabbrev so_peercred-Xraw -e trace=getsockopt -Xraw -a39 so_peercred-Xverbose -e trace=getsockopt -Xverbose +so_peercred--pidns-translation test_pidns -e trace=getsockopt sock_filter-v -v -e trace=getsockopt,setsockopt sock_filter-v-Xabbrev -v -e trace=getsockopt,setsockopt -X abbrev sock_filter-v-Xraw -a 37 -v -e trace=getsockopt,setsockopt -X raw @@ -721,7 +746,10 @@ waitpid -a28 xattr -a22 -e trace=getxattr,fgetxattr,lgetxattr,setxattr,fsetxattr,lsetxattr,listxattr,flistxattr,llistxattr,removexattr,fremovexattr,lremovexattr xattr-strings -a22 -s 4 -e trace=fsetxattr xet_robust_list -a24 -e trace=get_robust_list,set_robust_list +xet_robust_list--pidns-translation test_pidns -a24 -e trace=get_robust_list,set_robust_list xetitimer -a29 -e trace=setitimer,getitimer xetpgid -a11 -e trace=getpgid,setpgid -xetpriority -a29 -e trace=getpriority,setpriority +xetpgid--pidns-translation test_pidns -a11 -e trace=getpgid,setpgid +xetpriority -a27 -e trace=getpriority,setpriority +xetpriority--pidns-translation test_pidns -a27 -e trace=getpriority,setpriority xettimeofday -a20 -e trace=gettimeofday,settimeofday diff --git a/tests/getpgrp--pidns-translation.c b/tests/getpgrp--pidns-translation.c new file mode 100644 index 00000000..de8ceb33 --- /dev/null +++ b/tests/getpgrp--pidns-translation.c @@ -0,0 +1,2 @@ +#define PIDNS_TRANSLATION +#include "getpgrp.c" diff --git a/tests/getpgrp.c b/tests/getpgrp.c index 104f4811..3f0b9dd1 100644 --- a/tests/getpgrp.c +++ b/tests/getpgrp.c @@ -7,6 +7,7 @@ #include "tests.h" #include "scno.h" +#include "pidns.h" #ifdef __NR_getpgrp @@ -16,8 +17,13 @@ int main(void) { - printf("getpgrp() = %ld\n", syscall(__NR_getpgrp)); + PIDNS_TEST_INIT; + pidns_print_leader(); + printf("getpgrp() = %d%s\n", (int) syscall(__NR_getpgrp), + pidns_pid2str(PT_PGID)); + + pidns_print_leader(); puts("+++ exited with 0 +++"); return 0; } diff --git a/tests/getpid--pidns-translation.c b/tests/getpid--pidns-translation.c new file mode 100644 index 00000000..94b12a1a --- /dev/null +++ b/tests/getpid--pidns-translation.c @@ -0,0 +1,2 @@ +#define PIDNS_TRANSLATION +#include "getpid.c" diff --git a/tests/getpid.c b/tests/getpid.c index 988f19d5..7ec4e6e8 100644 --- a/tests/getpid.c +++ b/tests/getpid.c @@ -7,6 +7,7 @@ #include "tests.h" #include "scno.h" +#include "pidns.h" #if defined __NR_getpid && (!defined __NR_getxpid || __NR_getxpid != __NR_getpid) @@ -16,7 +17,12 @@ int main(void) { - printf("getpid() = %ld\n", syscall(__NR_getpid)); + PIDNS_TEST_INIT; + + pidns_print_leader(); + printf("getpid() = %d%s\n", (int) syscall(__NR_getpid), + pidns_pid2str(PT_TGID)); + pidns_print_leader(); puts("+++ exited with 0 +++"); return 0; } diff --git a/tests/getsid--pidns-translation.c b/tests/getsid--pidns-translation.c new file mode 100644 index 00000000..7f983e87 --- /dev/null +++ b/tests/getsid--pidns-translation.c @@ -0,0 +1,2 @@ +#define PIDNS_TRANSLATION +#include "getsid.c" diff --git a/tests/getsid.c b/tests/getsid.c index 588ea4ab..3bf74734 100644 --- a/tests/getsid.c +++ b/tests/getsid.c @@ -6,15 +6,22 @@ */ #include "tests.h" +#include "pidns.h" + #include #include int main(void) { + PIDNS_TEST_INIT; + pid_t pid = getpid(); - printf("getsid(%d) = %d\n", pid, getsid(pid)); + pidns_print_leader(); + printf("getsid(%d%s) = %d%s\n", pid, pidns_pid2str(PT_TGID), + getsid(pid), pidns_pid2str(PT_SID)); + pidns_print_leader(); puts("+++ exited with 0 +++"); return 0; } diff --git a/tests/gettid--pidns-translation.c b/tests/gettid--pidns-translation.c new file mode 100644 index 00000000..500c3213 --- /dev/null +++ b/tests/gettid--pidns-translation.c @@ -0,0 +1,2 @@ +#define PIDNS_TRANSLATION +#include "gettid.c" diff --git a/tests/gettid.c b/tests/gettid.c index d38918dd..314d9c2c 100644 --- a/tests/gettid.c +++ b/tests/gettid.c @@ -9,11 +9,17 @@ #include #include #include "scno.h" +#include "pidns.h" int main(void) { - printf("gettid() = %ld\n", syscall(__NR_gettid)); + PIDNS_TEST_INIT; + + pidns_print_leader(); + printf("gettid() = %d%s\n", (int) syscall(__NR_gettid), + pidns_pid2str(PT_TID)); + pidns_print_leader(); puts("+++ exited with 0 +++"); return 0; } diff --git a/tests/ioctl_block--pidns-translation.c b/tests/ioctl_block--pidns-translation.c new file mode 100644 index 00000000..5eed6076 --- /dev/null +++ b/tests/ioctl_block--pidns-translation.c @@ -0,0 +1,2 @@ +#define PIDNS_TRANSLATION +#include "ioctl_block.c" diff --git a/tests/ioctl_block--pidns-translation.test b/tests/ioctl_block--pidns-translation.test new file mode 100755 index 00000000..bb45f695 --- /dev/null +++ b/tests/ioctl_block--pidns-translation.test @@ -0,0 +1,24 @@ +#!/bin/sh +# +# Check ioctl syscall decoding. +# +# Copyright (c) 2020 The strace developers. +# All rights reserved. +# +# SPDX-License-Identifier: LGPL-2.1-or-later + +. "${srcdir=.}/init.sh" + +require_min_kernel_version_or_skip 4.9 + +check_prog head +check_prog tail +check_prog cut +check_prog grep + +run_prog > /dev/null +run_strace --pidns-translation -f -a16 -e trace=ioctl $@ $args > "$EXP" +parent_pid="$(tail -n 2 $LOG | head -n 1 | cut -d' ' -f1)" +init_pid="$(tail -n 1 $LOG | cut -d' ' -f1)" +grep -E -v "^($parent_pid|$init_pid) |ioctl\([0123][,<]" "$LOG" > "$OUT" +match_diff "$OUT" "$EXP" diff --git a/tests/ioctl_block.c b/tests/ioctl_block.c index 67fee35c..64677e85 100644 --- a/tests/ioctl_block.c +++ b/tests/ioctl_block.c @@ -9,7 +9,9 @@ */ #include "tests.h" +#include "pidns.h" #include +#include #include #include #include @@ -41,12 +43,15 @@ static struct xlat_data block_argless[] = { #define TEST_NULL_ARG(cmd) \ do { \ ioctl(-1, cmd, 0); \ + pidns_print_leader(); \ printf("ioctl(-1, %s, NULL) = -1 EBADF (%m)\n", #cmd); \ } while (0) int main(void) { + PIDNS_TEST_INIT; + TEST_NULL_ARG(BLKBSZGET); TEST_NULL_ARG(BLKBSZSET); TEST_NULL_ARG(BLKFRAGET); @@ -91,18 +96,22 @@ main(void) #endif ioctl(-1, BLKRASET, lmagic); + pidns_print_leader(); printf("ioctl(-1, BLKRASET, %lu) = -1 EBADF (%m)\n", lmagic); ioctl(-1, BLKFRASET, lmagic); + pidns_print_leader(); printf("ioctl(-1, BLKFRASET, %lu) = -1 EBADF (%m)\n", lmagic); TAIL_ALLOC_OBJECT_CONST_PTR(int, val_int); *val_int = magic; ioctl(-1, BLKROSET, val_int); + pidns_print_leader(); printf("ioctl(-1, BLKROSET, [%d]) = -1 EBADF (%m)\n", *val_int); ioctl(-1, BLKBSZSET, val_int); + pidns_print_leader(); printf("ioctl(-1, BLKBSZSET, [%d]) = -1 EBADF (%m)\n", *val_int); uint64_t *pair_int64 = tail_alloc(sizeof(*pair_int64) * 2); @@ -111,18 +120,21 @@ main(void) #ifdef BLKDISCARD ioctl(-1, BLKDISCARD, pair_int64); + pidns_print_leader(); printf("ioctl(-1, BLKDISCARD, [%" PRIu64 ", %" PRIu64 "])" " = -1 EBADF (%m)\n", pair_int64[0], pair_int64[1]); #endif #ifdef BLKSECDISCARD ioctl(-1, BLKSECDISCARD, pair_int64); + pidns_print_leader(); printf("ioctl(-1, BLKSECDISCARD, [%" PRIu64 ", %" PRIu64 "])" " = -1 EBADF (%m)\n", pair_int64[0], pair_int64[1]); #endif #ifdef BLKZEROOUT ioctl(-1, BLKZEROOUT, pair_int64); + pidns_print_leader(); printf("ioctl(-1, BLKZEROOUT, [%" PRIu64 ", %" PRIu64 "])" " = -1 EBADF (%m)\n", pair_int64[0], pair_int64[1]); #endif @@ -134,6 +146,7 @@ main(void) blkpg->data = (void *) (unsigned long) 0xcafef00dfffffeedULL; ioctl(-1, BLKPG, blkpg); + pidns_print_leader(); printf("ioctl(-1, BLKPG, {op=%s, flags=%d, datalen=%d" ", data=%#lx}) = -1 EBADF (%m)\n", "BLKPG_RESIZE_PARTITION", blkpg->flags, blkpg->datalen, @@ -149,6 +162,7 @@ main(void) blkpg->data = bp; ioctl(-1, BLKPG, blkpg); + pidns_print_leader(); printf("ioctl(-1, BLKPG, {op=%s, flags=%d, datalen=%d" ", data={start=%lld, length=%lld, pno=%d" ", devname=\"%.*s\"..., volname=\"%.*s\"...}})" @@ -162,25 +176,31 @@ main(void) #if defined BLKTRACESETUP && defined HAVE_STRUCT_BLK_USER_TRACE_SETUP TAIL_ALLOC_OBJECT_CONST_PTR(struct blk_user_trace_setup, buts); fill_memory(buts, sizeof(*buts)); + buts->pid = getpid(); ioctl(-1, BLKTRACESETUP, buts); + pidns_print_leader(); printf("ioctl(-1, BLKTRACESETUP, {act_mask=%hu, buf_size=%u, buf_nr=%u" - ", start_lba=%" PRI__u64 ", end_lba=%" PRI__u64 ", pid=%d})" + ", start_lba=%" PRI__u64 ", end_lba=%" PRI__u64 ", pid=%d%s})" " = -1 EBADF (%m)\n", buts->act_mask, buts->buf_size, buts->buf_nr, - buts->start_lba, buts->end_lba, buts->pid); + buts->start_lba, buts->end_lba, buts->pid, + pidns_pid2str(PT_TGID)); #endif unsigned int i; for (i = 0; i < ARRAY_SIZE(block_argless); ++i) { ioctl(-1, (unsigned long) block_argless[i].val, lmagic); + pidns_print_leader(); printf("ioctl(-1, %s) = -1 EBADF (%m)\n", block_argless[i].str); } ioctl(-1, _IOC(_IOC_READ, 0x12, 0xfe, 0xff), lmagic); + pidns_print_leader(); printf("ioctl(-1, %s, %#lx) = -1 EBADF (%m)\n", "_IOC(_IOC_READ, 0x12, 0xfe, 0xff)", lmagic); + pidns_print_leader(); puts("+++ exited with 0 +++"); return 0; } diff --git a/tests/ioprio--pidns-translation.c b/tests/ioprio--pidns-translation.c new file mode 100644 index 00000000..bcb49a8b --- /dev/null +++ b/tests/ioprio--pidns-translation.c @@ -0,0 +1,2 @@ +#define PIDNS_TRANSLATION +#include "ioprio.c" diff --git a/tests/ioprio.c b/tests/ioprio.c index 5e1e1194..110df063 100644 --- a/tests/ioprio.c +++ b/tests/ioprio.c @@ -9,8 +9,8 @@ */ #include "tests.h" - #include "scno.h" +#include "pidns.h" #if defined(__NR_ioprio_get) && defined(__NR_ioprio_set) @@ -30,12 +30,18 @@ enum { int main(void) { + PIDNS_TEST_INIT; + static const kernel_ulong_t bogus_which = (kernel_ulong_t) 0xdeadfacefa57beefULL; static const kernel_ulong_t bogus_who = (kernel_ulong_t) 0xbadc0dedda7a1057ULL; static const kernel_ulong_t bogus_ioprio = (kernel_ulong_t) 0xdec0ded1facefeedULL; + + const int pid = getpid(); + const int pgid = getpgid(0); + # if !XLAT_RAW static const char * const bogus_ioprio_str = "IOPRIO_PRIO_VALUE(0x7d677 /* IOPRIO_CLASS_??? */, 7917)"; @@ -46,6 +52,7 @@ main(void) rc = syscall(__NR_ioprio_get, bogus_which, bogus_who); errstr = sprintrc(rc); + pidns_print_leader(); # if XLAT_RAW printf("ioprio_get(%#x, %d) = %s\n", (int) bogus_which, (int) bogus_who, errstr); @@ -54,42 +61,52 @@ main(void) (int) bogus_which, (int) bogus_who, errstr); # endif - rc = syscall(__NR_ioprio_get, 1, 0); + rc = syscall(__NR_ioprio_get, 1, pid); errstr = sprintrc(rc); + pidns_print_leader(); + printf("ioprio_get("); # if XLAT_RAW - printf("ioprio_get(0x1, 0) = %s\n", errstr); + printf("0x1, "); +# elif XLAT_VERBOSE + printf("0x1 /* IOPRIO_WHO_PROCESS */, "); # else /* XLAT_ABBREV */ -# if XLAT_VERBOSE - printf("ioprio_get(0x1 /* IOPRIO_WHO_PROCESS */, 0) = %s", errstr); -# else - printf("ioprio_get(IOPRIO_WHO_PROCESS, 0) = %s", errstr); -# endif + printf("IOPRIO_WHO_PROCESS, "); +# endif + printf("%d%s) = %s", pid, pidns_pid2str(PT_TGID), errstr); +# if !XLAT_RAW if (rc >= 0) { printf(" (IOPRIO_PRIO_VALUE("); printxval(ioprio_class, (unsigned int) rc >> 13, "IOPRIO_CLASS_???"); printf(", %u))", (unsigned int) rc & 0x1fff); } - puts(""); # endif + puts(""); - rc = syscall(__NR_ioprio_set, 2, 0, 8191); + rc = syscall(__NR_ioprio_set, 2, pgid, 8191); errstr = sprintrc(rc); + pidns_print_leader(); + printf("ioprio_set("); # if XLAT_RAW - printf("ioprio_set(%#x, 0, 8191) = %s\n", 2, errstr); + printf("%#x", 2); # elif XLAT_VERBOSE - printf("ioprio_set(%#x /* IOPRIO_WHO_PGRP */, 0, 8191" - " /* IOPRIO_PRIO_VALUE(0 /* IOPRIO_CLASS_NONE */, 8191) */)" - " = %s\n", - 2, errstr); + printf("%#x /* IOPRIO_WHO_PGRP */", 2); # else /* XLAT_ABBREV */ - printf("ioprio_set(IOPRIO_WHO_PGRP, 0" - ", IOPRIO_PRIO_VALUE(IOPRIO_CLASS_NONE, 8191)) = %s\n", - errstr); + printf("IOPRIO_WHO_PGRP"); +# endif + printf(", %d%s", pgid, pidns_pid2str(PT_PGID)); +# if XLAT_RAW + printf(", 8191)"); +# elif XLAT_VERBOSE + printf(", 8191 /* IOPRIO_PRIO_VALUE(0 /* IOPRIO_CLASS_NONE */, 8191) */)"); +# else /* XLAT_ABBREV */ + printf(", IOPRIO_PRIO_VALUE(IOPRIO_CLASS_NONE, 8191))"); # endif + printf(" = %s\n", errstr); rc = syscall(__NR_ioprio_set, bogus_which, bogus_who, bogus_ioprio); errstr = sprintrc(rc); + pidns_print_leader(); # if XLAT_RAW printf("ioprio_set(%#x, %d, %d) = %s\n", (int) bogus_which, (int) bogus_who, (int) bogus_ioprio, @@ -104,6 +121,7 @@ main(void) errstr); # endif + pidns_print_leader(); puts("+++ exited with 0 +++"); return 0; diff --git a/tests/kcmp-y--pidns-translation.c b/tests/kcmp-y--pidns-translation.c new file mode 100644 index 00000000..f54d94cc --- /dev/null +++ b/tests/kcmp-y--pidns-translation.c @@ -0,0 +1,2 @@ +#define PIDNS_TRANSLATION +#include "kcmp-y.c" diff --git a/tests/kcmp.c b/tests/kcmp.c index dc5ba9a4..ce705ad0 100644 --- a/tests/kcmp.c +++ b/tests/kcmp.c @@ -9,8 +9,8 @@ */ #include "tests.h" - #include "scno.h" +#include "pidns.h" #ifdef __NR_kcmp @@ -101,7 +101,11 @@ do_kcmp(kernel_ulong_t pid1, kernel_ulong_t pid2, kernel_ulong_t type, rc = syscall(__NR_kcmp, pid1, pid2, type, idx1, idx2); errstr = sprintrc(rc); - printf("kcmp(%d, %d, ", (int) pid1, (int) pid2); + const char *pid_str = pidns_pid2str(PT_TGID); + pidns_print_leader(); + printf("kcmp(%d%s, %d%s, ", + (int) pid1, (int) pid1 == getpid() ? pid_str : "", + (int) pid2, (int) pid2 == getpid() ? pid_str : ""); if (type_str) printf("%s", type_str); @@ -146,6 +150,8 @@ do_kcmp(kernel_ulong_t pid1, kernel_ulong_t pid2, kernel_ulong_t type, int main(void) { + PIDNS_TEST_INIT; + static const kernel_ulong_t bogus_pid1 = (kernel_ulong_t) 0xdeadca75face1057ULL; static const kernel_ulong_t bogus_pid2 = @@ -221,6 +227,7 @@ main(void) (uintptr_t) slot, 1); } + pidns_print_leader(); puts("+++ exited with 0 +++"); return 0; diff --git a/tests/kill--pidns-translation.c b/tests/kill--pidns-translation.c new file mode 100644 index 00000000..4736ca14 --- /dev/null +++ b/tests/kill--pidns-translation.c @@ -0,0 +1,2 @@ +#define PIDNS_TRANSLATION +#include "kill.c" diff --git a/tests/kill.c b/tests/kill.c index f7d9341e..17de35da 100644 --- a/tests/kill.c +++ b/tests/kill.c @@ -11,6 +11,7 @@ #include "tests.h" #include "scno.h" +#include "pidns.h" #ifdef __NR_kill @@ -26,6 +27,8 @@ handler(int sig) int main(void) { + PIDNS_TEST_INIT; + const struct sigaction act = { .sa_handler = handler }; if (sigaction(SIGALRM, &act, NULL)) perror_msg_and_fail("sigaction"); @@ -37,18 +40,23 @@ main(void) perror_msg_and_fail("sigprocmask"); const int pid = getpid(); + const char *pid_str = pidns_pid2str(PT_TGID); long rc = syscall(__NR_kill, pid, (long) 0xdefaced00000000ULL | SIGALRM); - printf("kill(%d, SIGALRM) = %ld\n", pid, rc); + pidns_print_leader(); + printf("kill(%d%s, SIGALRM) = %ld\n", pid, pid_str, rc); const long big_pid = (long) 0xfacefeedbadc0dedULL; const long big_sig = (long) 0xdeadbeefcafef00dULL; rc = syscall(__NR_kill, big_pid, big_sig); + pidns_print_leader(); printf("kill(%d, %d) = %ld %s (%m)\n", (int) big_pid, (int) big_sig, rc, errno2name()); rc = syscall(__NR_kill, (long) 0xdefaced00000000ULL | pid, 0); - printf("kill(%d, 0) = %ld\n", pid, rc); + pidns_print_leader(); + printf("kill(%d%s, 0) = %ld\n", pid, pid_str, rc); + pidns_print_leader(); puts("+++ exited with 0 +++"); return 0; } diff --git a/tests/migrate_pages--pidns-translation.c b/tests/migrate_pages--pidns-translation.c new file mode 100644 index 00000000..ec34938d --- /dev/null +++ b/tests/migrate_pages--pidns-translation.c @@ -0,0 +1,2 @@ +#define PIDNS_TRANSLATION +#include "migrate_pages.c" diff --git a/tests/migrate_pages.c b/tests/migrate_pages.c index 2dfba49c..390b490b 100644 --- a/tests/migrate_pages.c +++ b/tests/migrate_pages.c @@ -10,6 +10,7 @@ #include "tests.h" #include "scno.h" +#include "pidns.h" #ifdef __NR_migrate_pages @@ -19,11 +20,21 @@ int main(void) { - const long pid = (long) 0xfacefeedffffffffULL; + PIDNS_TEST_INIT; + + const long pid = (long) 0xfacefeed00000000ULL | getpid(); long rc = syscall(__NR_migrate_pages, pid, 0, 0, 0); - printf("migrate_pages(%d, 0, NULL, NULL) = %ld %s (%m)\n", - (int) pid, rc, errno2name()); + pidns_print_leader(); + printf("migrate_pages(%d%s, 0, NULL, NULL) = %ld", + (int) pid, pidns_pid2str(PT_TGID), rc); + + if (rc < 0) + printf(" %s (%m)\n", errno2name()); + else + printf("\n"); + + pidns_print_leader(); puts("+++ exited with 0 +++"); return 0; } diff --git a/tests/move_pages--pidns-translation.c b/tests/move_pages--pidns-translation.c new file mode 100644 index 00000000..8498e399 --- /dev/null +++ b/tests/move_pages--pidns-translation.c @@ -0,0 +1,2 @@ +#define PIDNS_TRANSLATION +#include "move_pages.c" diff --git a/tests/move_pages.c b/tests/move_pages.c index e00fd1ac..56843158 100644 --- a/tests/move_pages.c +++ b/tests/move_pages.c @@ -10,6 +10,7 @@ #include "tests.h" #include "scno.h" +#include "pidns.h" #ifdef __NR_move_pages @@ -122,15 +123,20 @@ print_status_array(const int *const status, const unsigned long count) } static void -print_stat_pages(const unsigned long pid, const unsigned long count, - const void **const pages, int *const status) +print_stat_pages(const unsigned long pid, + const char *pid_str, + const unsigned long count, + const void **const pages, + int *const status) { const unsigned long flags = (unsigned long) 0xfacefeed00000002ULL; long rc = syscall(__NR_move_pages, pid, count, pages, NULL, status, flags); const char *errstr = sprintrc(rc); - printf("move_pages(%d, %lu, ", (int) pid, count); + pidns_print_leader(); + printf("move_pages(%d%s, %lu, ", (int) pid, pid_str, + count); print_page_array(pages, count, 0); printf(", NULL, "); if (rc) { @@ -152,6 +158,7 @@ print_stat_pages(const unsigned long pid, const unsigned long count, static void print_move_pages(const unsigned long pid, + const char *pid_str, unsigned long count, const unsigned int offset, const void **const pages, @@ -164,7 +171,9 @@ print_move_pages(const unsigned long pid, long rc = syscall(__NR_move_pages, pid, count, pages, nodes, status, flags); const char *errstr = sprintrc(rc); - printf("move_pages(%d, %lu, ", (int) pid, count); + pidns_print_leader(); + printf("move_pages(%d%s, %lu, ", (int) pid, pid_str, + count); print_page_array(pages, count, offset); printf(", "); print_node_array(nodes, count, offset); @@ -185,8 +194,11 @@ print_move_pages(const unsigned long pid, int main(void) { + PIDNS_TEST_INIT; + const unsigned long pid = (unsigned long) 0xfacefeed00000000ULL | getpid(); + const char *pid_str = pidns_pid2str(PT_TGID); unsigned long count = 1; const unsigned page_size = get_page_size(); const void *const page = tail_alloc(page_size); @@ -195,40 +207,41 @@ main(void) TAIL_ALLOC_OBJECT_VAR_PTR(int, nodes); TAIL_ALLOC_OBJECT_VAR_PTR(int, status); - print_stat_pages(pid, 0, pages, status); - print_move_pages(pid, 0, 0, pages, nodes, status); - print_move_pages(pid, 0, 1, pages + 1, nodes + 1, status + 1); + print_stat_pages(pid, pid_str, 0, pages, status); + print_move_pages(pid, pid_str, 0, 0, pages, nodes, status); + print_move_pages(pid, pid_str, 0, 1, pages + 1, nodes + 1, status + 1); *pages = page; - print_stat_pages(pid, count, pages, status); + print_stat_pages(pid, pid_str, count, pages, status); *nodes = 0xdeadbee1; - print_move_pages(pid, count, 0, pages, nodes, status); - print_move_pages(pid, count, 1, pages, nodes, status); + print_move_pages(pid, pid_str, count, 0, pages, nodes, status); + print_move_pages(pid, pid_str, count, 1, pages, nodes, status); ++count; --status; *(--pages) = efault; - print_stat_pages(pid, count, pages, status); + print_stat_pages(pid, pid_str, count, pages, status); *(--nodes) = 0xdeadbee2; - print_move_pages(pid, count, 0, pages, nodes, status); - print_move_pages(pid, count, 1, pages, nodes, status); + print_move_pages(pid, pid_str, count, 0, pages, nodes, status); + print_move_pages(pid, pid_str, count, 1, pages, nodes, status); ++count; --status; *(--pages) = nodes; - print_stat_pages(pid, count, pages, status); + print_stat_pages(pid, pid_str, count, pages, status); *(--nodes) = 0xdeadbee3; - print_move_pages(pid, count, 0, pages, nodes, status); - print_move_pages(pid, count, 1, pages, nodes, status); + print_move_pages(pid, pid_str, count, 0, pages, nodes, status); + print_move_pages(pid, pid_str, count, 1, pages, nodes, status); ++count; --status; *(--pages) = status; - print_stat_pages(pid, count, pages, status); + print_stat_pages(pid, pid_str, count, pages, status); *(--nodes) = 0xdeadbee4; - print_move_pages(pid, count, 0, pages, nodes, status); - print_move_pages(pid, count, 1, pages, nodes, status); + print_move_pages(pid, pid_str, count, 0, pages, nodes, status); + print_move_pages(pid, pid_str, count, 1, pages, nodes, status); + pidns_print_leader(); puts("+++ exited with 0 +++"); return 0; } diff --git a/tests/net-sockaddr--pidns-translation.c b/tests/net-sockaddr--pidns-translation.c new file mode 100644 index 00000000..ff432bf4 --- /dev/null +++ b/tests/net-sockaddr--pidns-translation.c @@ -0,0 +1,2 @@ +#define PIDNS_TRANSLATION +#include "net-sockaddr.c" diff --git a/tests/net-sockaddr.c b/tests/net-sockaddr.c index 4fc9da6e..b9cd46fd 100644 --- a/tests/net-sockaddr.c +++ b/tests/net-sockaddr.c @@ -9,6 +9,7 @@ */ #include "tests.h" +#include "pidns.h" #include #include #include @@ -40,18 +41,21 @@ check_un(void) memset(un->sun_path, '0', sizeof(un->sun_path)); unsigned int len = sizeof(*un); int ret = connect(-1, (void *) un, len); + pidns_print_leader(); printf("connect(-1, {sa_family=AF_UNIX, sun_path=\"%.*u\"}" ", %u) = %d EBADF (%m)\n", (int) sizeof(un->sun_path), 0, len, ret); un->sun_path[1] = 0; ret = connect(-1, (void *) un, len); + pidns_print_leader(); printf("connect(-1, {sa_family=AF_UNIX, sun_path=\"%u\"}, %u)" " = %d EBADF (%m)\n", 0, len, ret); un->sun_path[0] = 0; un->sun_path[2] = 1; ret = connect(-1, (void *) un, len); + pidns_print_leader(); printf("connect(-1, {sa_family=AF_UNIX, sun_path=@\"\\0\\001%.*u\"}" ", %u) = %d EBADF (%m)\n", (int) sizeof(un->sun_path) - 3, 0, len, ret); @@ -61,12 +65,14 @@ check_un(void) memset(un->sun_path, '0', sizeof(un->sun_path)); len = sizeof(*un) + 2; ret = connect(-1, (void *) un, len); + pidns_print_leader(); printf("connect(-1, {sa_family=AF_UNIX, sun_path=\"%.*u\"}" ", %u) = %d EBADF (%m)\n", (int) sizeof(un->sun_path), 0, len, ret); un->sun_path[0] = 0; ret = connect(-1, (void *) un, len); + pidns_print_leader(); printf("connect(-1, {sa_family=AF_UNIX, sun_path=@\"%.*u\"}" ", %u) = %d EBADF (%m)\n", (int) sizeof(un->sun_path) - 1, 0, len, ret); @@ -75,18 +81,21 @@ check_un(void) un->sun_family = AF_UNIX; len = sizeof(*un) - 2; ret = connect(-1, (void *) un, len); + pidns_print_leader(); printf("connect(-1, {sa_family=AF_UNIX, sun_path=\"%.*u\"}" ", %u) = %d EBADF (%m)\n", (int) sizeof(un->sun_path) - 2, 0, len, ret); un->sun_path[0] = 0; ret = connect(-1, (void *) un, len); + pidns_print_leader(); printf("connect(-1, {sa_family=AF_UNIX, sun_path=@\"%.*u\"}" ", %u) = %d EBADF (%m)\n", (int) sizeof(un->sun_path) - 3, 0, len, ret); len = sizeof(*un); ret = connect(-1, (void *) un, len); + pidns_print_leader(); printf("connect(-1, %p, %u) = %d EBADF (%m)\n", un, len, ret); un = tail_alloc(sizeof(struct sockaddr_storage)); @@ -94,12 +103,14 @@ check_un(void) memset(un->sun_path, '0', sizeof(un->sun_path)); len = sizeof(struct sockaddr_storage) + 1; ret = connect(-1, (void *) un, len); + pidns_print_leader(); printf("connect(-1, {sa_family=AF_UNIX, sun_path=\"%.*u\"}" ", %u) = %d EBADF (%m)\n", (int) sizeof(un->sun_path), 0, len, ret); un->sun_path[0] = 0; ret = connect(-1, (void *) un, len); + pidns_print_leader(); printf("connect(-1, {sa_family=AF_UNIX, sun_path=@\"%.*u\"}" ", %u) = %d EBADF (%m)\n", (int) sizeof(un->sun_path) - 1, 0, len, ret); @@ -117,6 +128,7 @@ check_in(void) in->sin_addr.s_addr = inet_addr(h_addr); unsigned int len = sizeof(*in); int ret = connect(-1, (void *) in, len); + pidns_print_leader(); printf("connect(-1, {sa_family=AF_INET, sin_port=htons(%hu)" ", sin_addr=inet_addr(\"%s\")}, %u) = %d EBADF (%m)\n", h_port, h_addr, len, ret); @@ -127,6 +139,7 @@ check_in(void) in->sin_addr.s_addr = inet_addr(h_addr); len = sizeof(*in) + 4; ret = connect(-1, (void *) in, len); + pidns_print_leader(); printf("connect(-1, {sa_family=AF_INET, sin_port=htons(%hu)" ", sin_addr=inet_addr(\"%s\")}, %u) = %d EBADF (%m)\n", h_port, h_addr, len, ret); @@ -137,6 +150,7 @@ check_in(void) in->sin_addr.s_addr = 0; len = sizeof(*in) - 4; ret = connect(-1, (void *) in, len); + pidns_print_leader(); printf("connect(-1, {sa_family=AF_INET, sa_data=\"%s\"}, %u)" " = %d EBADF (%m)\n", "\\0\\0\\0\\0\\0\\0\\377\\377\\377\\377", @@ -144,6 +158,7 @@ check_in(void) len = sizeof(*in); ret = connect(-1, (void *) in, len); + pidns_print_leader(); printf("connect(-1, %p, %u) = %d EBADF (%m)\n", in, len, ret); } @@ -155,6 +170,7 @@ check_in6_linklocal(struct sockaddr_in6 *const in6, const char *const h_addr) in6->sin6_scope_id = 0xfacefeed; unsigned int len = sizeof(*in6); int ret = connect(-1, (void *) in6, len); + pidns_print_leader(); printf("connect(-1, {sa_family=AF_INET6, sin6_port=htons(%hu)" ", sin6_flowinfo=htonl(%u)" ", inet_pton(AF_INET6, \"%s\", &sin6_addr)" @@ -166,7 +182,8 @@ check_in6_linklocal(struct sockaddr_in6 *const in6, const char *const h_addr) in6->sin6_scope_id = ifindex_lo(); if (in6->sin6_scope_id) { ret = connect(-1, (void *) in6, len); - printf("connect(-1, {sa_family=AF_INET6, sin6_port=htons(%hu)" + pidns_print_leader(); + printf("connect(-1, {sa_family=AF_INET6, sin6_port=htons(%hu)" ", sin6_flowinfo=htonl(%u)" ", inet_pton(AF_INET6, \"%s\", &sin6_addr)" ", sin6_scope_id=%s}, %u)" @@ -191,6 +208,7 @@ check_in6(void) in6->sin6_scope_id = 0xfacefeed; unsigned int len = sizeof(*in6); int ret = connect(-1, (void *) in6, len); + pidns_print_leader(); printf("connect(-1, {sa_family=AF_INET6, sin6_port=htons(%hu)" ", sin6_flowinfo=htonl(%u)" ", inet_pton(AF_INET6, \"%s\", &sin6_addr)" @@ -209,6 +227,7 @@ check_in6(void) in6->sin6_scope_id = 0xfacefeed; len = sizeof(*in6) + 4; ret = connect(-1, (void *) in6, len); + pidns_print_leader(); printf("connect(-1, {sa_family=AF_INET6, sin6_port=htons(%hu)" ", sin6_flowinfo=htonl(%u)" ", inet_pton(AF_INET6, \"%s\", &sin6_addr)" @@ -223,6 +242,7 @@ check_in6(void) inet_pton(AF_INET6, h_addr, &in6->sin6_addr); len = sizeof(*in6) - sizeof(in6->sin6_scope_id); ret = connect(-1, (void *) in6, len); + pidns_print_leader(); printf("connect(-1, {sa_family=AF_INET6, sin6_port=htons(%hu)" ", sin6_flowinfo=htonl(%u)" ", inet_pton(AF_INET6, \"%s\", &sin6_addr)}, %u)" @@ -236,6 +256,7 @@ check_in6(void) memset(&in6->sin6_addr, '0', sizeof(in6->sin6_addr) - 4); len = sizeof(*in6) - sizeof(in6->sin6_scope_id) - 4; ret = connect(-1, (void *) in6, len); + pidns_print_leader(); printf("connect(-1, {sa_family=AF_INET6" ", sa_data=\"\\0\\0\\0\\0\\0\\000%.*u\"}, %u)" " = %d EBADF (%m)\n", @@ -244,6 +265,7 @@ check_in6(void) len = sizeof(*in6) - sizeof(in6->sin6_scope_id); ret = connect(-1, (void *) in6, len); + pidns_print_leader(); printf("connect(-1, %p, %u) = %d EBADF (%m)\n", in6, len, ret); } @@ -262,6 +284,7 @@ check_ipx(void) void *ipx = tail_memdup(&c_ipx, sizeof(c_ipx)); unsigned int len = sizeof(c_ipx); int ret = connect(-1, ipx, len); + pidns_print_leader(); printf("connect(-1, {sa_family=AF_IPX, sipx_port=htons(%u)" ", sipx_network=htonl(%#x)" ", sipx_node=[%#02x, %#02x, %#02x, %#02x, %#02x, %#02x]" @@ -316,18 +339,21 @@ check_ax25(void) fill_memory(sax, size); sax->fsa_ax25.sax25_family = AF_AX25; rc = connect(-1, sax_void, sizeof(struct sockaddr_ax25) - 1); + pidns_print_leader(); printf("connect(-1, {sa_family=AF_AX25, sa_data=\"\\202\\203\\204\\205" "\\206\\207\\210\\211\\212\\213\\214\\215\\216\"}, %zu) = %s\n", sizeof(struct sockaddr_ax25) - 1, sprintrc(rc)); memcpy(sax, &ax25, sizeof(ax25)); rc = connect(-1, sax_void, sizeof(struct sockaddr_ax25)); + pidns_print_leader(); printf("connect(-1, {sa_family=AF_AX25, fsa_ax25={sax25_call=VALID-13" ", sax25_ndigis=8}, fsa_digipeater=[/* ??? */]}, %zu) = %s\n", sizeof(struct sockaddr_ax25), sprintrc(rc)); sax->fsa_ax25.sax25_ndigis = 0; rc = connect(-1, sax_void, sizeof(struct sockaddr_ax25)); + pidns_print_leader(); printf("connect(-1, {sa_family=AF_AX25, sax25_call=VALID-13" ", sax25_ndigis=0}, %zu) = %s\n", sizeof(struct sockaddr_ax25), sprintrc(rc)); @@ -335,6 +361,7 @@ check_ax25(void) sax->fsa_ax25.sax25_ndigis = 8; size = sizeof(struct sockaddr_ax25) + sizeof(ax25_address) * 3 + 1; rc = connect(-1, sax_void, size); + pidns_print_leader(); printf("connect(-1, {sa_family=AF_AX25, fsa_ax25={sax25_call=VALID-13" ", sax25_ndigis=8}, fsa_digipeater" "=[{ax25_call=\"\\xa6\\xa0\\x82\\x40\\x86\\x8a\\x00\"" @@ -348,6 +375,7 @@ check_ax25(void) sax->fsa_digipeater[2].ax25_call[6] = 0x4; size = sizeof(struct sockaddr_ax25) + sizeof(ax25_address) * 4; rc = connect(-1, sax_void, size); + pidns_print_leader(); printf("connect(-1, {sa_family=AF_AX25, fsa_ax25={sax25_call=VALID-13" ", sax25_ndigis=8}, fsa_digipeater" "=[{ax25_call=\"\\xa6\\xa0\\x82\\x40\\x86\\x8a\\x00\"" @@ -365,7 +393,8 @@ check_ax25(void) for (size_t i = 0; i < 3; i++) { size = sizeof(ax25) + sizeof(ax25_address) * (i / 2); rc = connect(-1, sax_void, size); - printf("connect(-1, {sa_family=AF_AX25" + pidns_print_leader(); + printf("connect(-1, {sa_family=AF_AX25" ", fsa_ax25={sax25_call=VALID-13, sax25_ndigis=%d}" ", fsa_digipeater=[VALID2-7, OK-15, %s /* FINE-2 */" ", {ax25_call=\"\\xe6\\xda\\xc2\\xd8\\xd8\\xe6\\x12\"" @@ -427,13 +456,15 @@ check_x25(void) long rc; rc = connect(-1, x25_void, sizeof(c_x25) - 1); + pidns_print_leader(); printf("connect(-1, {sa_family=AF_X25" ", sa_data=\"0123456789abcde\"}, %zu) = %s\n", sizeof(c_x25) - 1, sprintrc(rc)); for (size_t i = 0; i < 2; i++) { rc = connect(-1, x25_void, sizeof(c_x25) + i); - printf("connect(-1, {sa_family=AF_X25" + pidns_print_leader(); + printf("connect(-1, {sa_family=AF_X25" ", sx25_addr={x25_addr=\"0123456789abcde\"...}" "}, %zu) = %s\n", sizeof(c_x25) + i, sprintrc(rc)); @@ -442,6 +473,7 @@ check_x25(void) struct sockaddr_x25 *const x25 = x25_void; x25->sx25_addr.x25_addr[10] = '\0'; rc = connect(-1, x25_void, sizeof(c_x25)); + pidns_print_leader(); printf("connect(-1, {sa_family=AF_X25" ", sx25_addr={x25_addr=\"0123456789\"}" "}, %zu) = %s\n", @@ -457,19 +489,21 @@ check_nl(void) nl->nl_groups = 0xfacefeed; unsigned int len = sizeof(*nl); int ret = connect(-1, (void *) nl, len); + pidns_print_leader(); printf("connect(-1, {sa_family=AF_NETLINK, nl_pid=%d" ", nl_groups=%#08x}, %u) = %d EBADF (%m)\n", nl->nl_pid, nl->nl_groups, len, ret); nl = ((void *) nl) - 4; nl->nl_family = AF_NETLINK; - nl->nl_pid = 1234567890; + nl->nl_pid = getpid(); nl->nl_groups = 0xfacefeed; len = sizeof(*nl) + 4; ret = connect(-1, (void *) nl, len); - printf("connect(-1, {sa_family=AF_NETLINK, nl_pid=%d" + pidns_print_leader(); + printf("connect(-1, {sa_family=AF_NETLINK, nl_pid=%d%s" ", nl_groups=%#08x}, %u) = %d EBADF (%m)\n", - nl->nl_pid, nl->nl_groups, len, ret); + nl->nl_pid, pidns_pid2str(PT_TGID), nl->nl_groups, len, ret); } static void @@ -487,6 +521,7 @@ check_ll(void) void *ll = tail_memdup(&c_ll, sizeof(c_ll)); unsigned int len = sizeof(c_ll); int ret = connect(-1, ll, len); + pidns_print_leader(); printf("connect(-1, {sa_family=AF_PACKET" ", sll_protocol=htons(ETH_P_ALL)" ", sll_ifindex=%u, sll_hatype=ARPHRD_ETHER" @@ -502,6 +537,7 @@ check_ll(void) ((struct sockaddr_ll *) ll)->sll_halen++; ret = connect(-1, ll, len); + pidns_print_leader(); printf("connect(-1, {sa_family=AF_PACKET" ", sll_protocol=htons(ETH_P_ALL)" ", sll_ifindex=%u, sll_hatype=ARPHRD_ETHER" @@ -517,6 +553,7 @@ check_ll(void) ((struct sockaddr_ll *) ll)->sll_halen = 0; ret = connect(-1, ll, len); + pidns_print_leader(); printf("connect(-1, {sa_family=AF_PACKET" ", sll_protocol=htons(ETH_P_ALL)" ", sll_ifindex=%u, sll_hatype=ARPHRD_ETHER" @@ -526,7 +563,8 @@ check_ll(void) ((struct sockaddr_ll *) ll)->sll_ifindex = ifindex_lo(); if (((struct sockaddr_ll *) ll)->sll_ifindex) { ret = connect(-1, ll, len); - printf("connect(-1, {sa_family=AF_PACKET" + pidns_print_leader(); + printf("connect(-1, {sa_family=AF_PACKET" ", sll_protocol=htons(ETH_P_ALL)" ", sll_ifindex=%s" ", sll_hatype=ARPHRD_ETHER" @@ -549,11 +587,13 @@ check_hci(void) unsigned int len = sizeof(*hci); int ret = connect(-1, (void *) hci, 4); + pidns_print_leader(); printf("connect(-1, {sa_family=AF_BLUETOOTH, hci_dev=htobs(%hu)" "}, 4) = %d EBADF (%m)\n", h_port, ret); ret = connect(-1, (void *) hci, len); + pidns_print_leader(); printf("connect(-1, {sa_family=AF_BLUETOOTH, hci_dev=htobs(%hu)" # ifdef HAVE_STRUCT_SOCKADDR_HCI_HCI_CHANNEL ", hci_channel=HCI_CHANNEL_RAW" @@ -572,6 +612,7 @@ check_sco(void) void *sco = tail_memdup(&c_sco, sizeof(c_sco)); unsigned int len = sizeof(c_sco); int ret = connect(-1, sco, len); + pidns_print_leader(); printf("connect(-1, {sa_family=AF_BLUETOOTH" ", sco_bdaddr=%02x:%02x:%02x:%02x:%02x:%02x" "}, %u) = %d EBADF (%m)\n", @@ -592,6 +633,7 @@ check_rc(void) void *rc = tail_memdup(&c_rc, sizeof(c_rc)); unsigned int len = sizeof(c_rc); int ret = connect(-1, rc, len); + pidns_print_leader(); printf("connect(-1, {sa_family=AF_BLUETOOTH" ", rc_bdaddr=%02x:%02x:%02x:%02x:%02x:%02x" ", rc_channel=%u}, %u) = %d EBADF (%m)\n", @@ -619,6 +661,7 @@ check_l2(void) unsigned int len = sizeof(c_l2); int ret = connect(-1, l2, len); + pidns_print_leader(); printf("connect(-1, {sa_family=AF_BLUETOOTH" ", l2_psm=htobs(L2CAP_PSM_DYN_START + %hu)" ", l2_bdaddr=%02x:%02x:%02x:%02x:%02x:%02x" @@ -640,6 +683,7 @@ check_l2(void) # endif memcpy(l2, &c_l2, sizeof(c_l2)); ret = connect(-1, l2, len); + pidns_print_leader(); printf("connect(-1, {sa_family=AF_BLUETOOTH" ", l2_psm=htobs(L2CAP_PSM_SDP)" ", l2_bdaddr=%02x:%02x:%02x:%02x:%02x:%02x" @@ -660,6 +704,7 @@ check_l2(void) # endif memcpy(l2, &c_l2, sizeof(c_l2)); ret = connect(-1, l2, len); + pidns_print_leader(); printf("connect(-1, {sa_family=AF_BLUETOOTH" ", l2_psm=htobs(0xbad /* L2CAP_PSM_??? */)" ", l2_bdaddr=%02x:%02x:%02x:%02x:%02x:%02x" @@ -677,6 +722,7 @@ check_l2(void) c_l2.l2_cid = htobs(0xffff); memcpy(l2, &c_l2, 12); ret = connect(-1, l2, 12); + pidns_print_leader(); printf("connect(-1, {sa_family=AF_BLUETOOTH" ", l2_psm=htobs(L2CAP_PSM_AUTO_END)" ", l2_bdaddr=%02x:%02x:%02x:%02x:%02x:%02x" @@ -700,6 +746,7 @@ check_raw(void) u.sa->sa_family = 0xff; unsigned int len = sizeof(*u.st) + 8; int ret = connect(-1, (void *) u.st, len); + pidns_print_leader(); printf("connect(-1, {sa_family=%#x /* AF_??? */, sa_data=\"%.*u\"}" ", %u) = %d EBADF (%m)\n", u.sa->sa_family, (int) (sizeof(*u.st) - sizeof(u.sa->sa_family)), 0, len, ret); @@ -707,11 +754,13 @@ check_raw(void) u.sa->sa_family = 0; len = sizeof(u.sa->sa_family) + 1; ret = connect(-1, (void *) u.st, len); + pidns_print_leader(); printf("connect(-1, {sa_family=AF_UNSPEC, sa_data=\"0\"}, %u)" " = %d EBADF (%m)\n", len, ret); u.sa->sa_family = AF_BLUETOOTH; ret = connect(-1, (void *) u.st, len); + pidns_print_leader(); printf("connect(-1, {sa_family=AF_BLUETOOTH, sa_data=\"0\"}, %u)" " = %d EBADF (%m)\n", len, ret); } @@ -719,6 +768,8 @@ check_raw(void) int main(void) { + PIDNS_TEST_INIT; + check_un(); check_in(); check_in6(); @@ -735,6 +786,7 @@ main(void) #endif check_raw(); + pidns_print_leader(); puts("+++ exited with 0 +++"); return 0; } diff --git a/tests/netlink_audit--pidns-translation.c b/tests/netlink_audit--pidns-translation.c new file mode 100644 index 00000000..e08f9168 --- /dev/null +++ b/tests/netlink_audit--pidns-translation.c @@ -0,0 +1,2 @@ +#define PIDNS_TRANSLATION +#include "netlink_audit.c" diff --git a/tests/netlink_audit--pidns-translation.test b/tests/netlink_audit--pidns-translation.test new file mode 100755 index 00000000..fbc32435 --- /dev/null +++ b/tests/netlink_audit--pidns-translation.test @@ -0,0 +1,13 @@ +#!/bin/sh +# +# Check decoding of NETLINK_SOCK_DIAG protocol +# +# Copyright (c) 2020 The strace developers. +# All rights reserved. +# +# SPDX-License-Identifier: LGPL-2.1-or-later + +. "${srcdir=.}/init.sh" + +run_prog ../netlink_netlink_diag +test_pidns -e trace=sendto "$@" diff --git a/tests/netlink_audit.c b/tests/netlink_audit.c index eba609a1..5dfcd786 100644 --- a/tests/netlink_audit.c +++ b/tests/netlink_audit.c @@ -7,6 +7,7 @@ */ #include "tests.h" +#include "pidns.h" #include #include #include @@ -17,18 +18,23 @@ static void test_nlmsg_type(const int fd) { + PIDNS_TEST_INIT; + long rc; struct nlmsghdr nlh = { .nlmsg_len = sizeof(nlh), .nlmsg_type = AUDIT_GET, .nlmsg_flags = NLM_F_REQUEST, + .nlmsg_pid = getpid(), }; rc = sendto(fd, &nlh, sizeof(nlh), MSG_DONTWAIT, NULL, 0); + pidns_print_leader(); printf("sendto(%d, {len=%u, type=AUDIT_GET" - ", flags=NLM_F_REQUEST, seq=0, pid=0}" + ", flags=NLM_F_REQUEST, seq=0, pid=%d%s}" ", %u, MSG_DONTWAIT, NULL, 0) = %s\n", - fd, nlh.nlmsg_len, (unsigned) sizeof(nlh), sprintrc(rc)); + fd, nlh.nlmsg_len, nlh.nlmsg_pid, pidns_pid2str(PT_TGID), + (unsigned) sizeof(nlh), sprintrc(rc)); } int main(void) @@ -39,6 +45,7 @@ int main(void) test_nlmsg_type(fd); + pidns_print_leader(); printf("+++ exited with 0 +++\n"); return 0; diff --git a/tests/pidfd_open--pidns-translation.c b/tests/pidfd_open--pidns-translation.c new file mode 100644 index 00000000..c38e37a8 --- /dev/null +++ b/tests/pidfd_open--pidns-translation.c @@ -0,0 +1,2 @@ +#define PIDNS_TRANSLATION +#include "pidfd_open.c" diff --git a/tests/pidfd_open.c b/tests/pidfd_open.c index 5860adde..e5d74a91 100644 --- a/tests/pidfd_open.c +++ b/tests/pidfd_open.c @@ -10,6 +10,7 @@ #include "tests.h" #include "scno.h" +#include "pidns.h" #ifdef __NR_pidfd_open @@ -37,6 +38,8 @@ k_pidfd_open(const unsigned int pid, const unsigned int flags) int main(void) { + PIDNS_TEST_INIT; + # if defined PATH_TRACING || defined PRINT_PATHS skip_if_unavailable("/proc/self/fd/"); # endif @@ -50,16 +53,19 @@ main(void) k_pidfd_open(0, 0); # ifndef PATH_TRACING + pidns_print_leader(); printf("pidfd_open(0, 0) = %s\n", errstr); # endif k_pidfd_open(-1U, 0); # ifndef PATH_TRACING + pidns_print_leader(); printf("pidfd_open(-1, 0) = %s\n", errstr); # endif k_pidfd_open(0, -1U); # ifndef PATH_TRACING + pidns_print_leader(); printf("pidfd_open(0, %#x) = %s\n", -1U, errstr); # endif @@ -68,7 +74,10 @@ main(void) k_pidfd_open(pid, flags); # ifndef PATH_TRACING - printf("pidfd_open(%d, %#x) = %s\n", pid, flags, errstr); + const char *pid_str = pidns_pid2str(PT_TGID); + pidns_print_leader(); + printf("pidfd_open(%d%s, %#x) = %s\n", + pid, pid_str, flags, errstr); # endif # ifdef PRINT_PATHS @@ -80,17 +89,19 @@ main(void) # endif # ifndef PATH_TRACING - printf("pidfd_open(%d, 0) = " + pidns_print_leader(); + printf("pidfd_open(%d%s, 0) = " # if defined PRINT_PIDFD - "%ld\n", pid, rc, pid + "%ld\n", pid, pid_str, rc, pid # elif defined PRINT_PATHS - "%ld\n", pid, rc + "%ld\n", pid, pid_str, rc # else - "%s\n", pid, errstr + "%s\n", pid, pid_str, errstr # endif ); # endif + pidns_print_leader(); puts("+++ exited with 0 +++"); return 0; } diff --git a/tests/pidfd_send_signal--pidns-translation.c b/tests/pidfd_send_signal--pidns-translation.c new file mode 100644 index 00000000..b04f10f5 --- /dev/null +++ b/tests/pidfd_send_signal--pidns-translation.c @@ -0,0 +1,2 @@ +#define PIDNS_TRANSLATION +#include "pidfd_send_signal.c" diff --git a/tests/pidfd_send_signal.c b/tests/pidfd_send_signal.c index 8537a497..3ce5024f 100644 --- a/tests/pidfd_send_signal.c +++ b/tests/pidfd_send_signal.c @@ -10,6 +10,7 @@ #include "tests.h" #include #include "scno.h" +#include "pidns.h" #ifdef __NR_pidfd_send_signal @@ -36,6 +37,8 @@ sys_pidfd_send_signal(int pidfd, int sig, const void *info, int flags) int main(void) { + PIDNS_TEST_INIT; + static const char null_path[] = "/dev/null"; int fd = open(null_path, O_RDONLY); @@ -46,19 +49,23 @@ main(void) const void *esi = (const void *) si + 1; sys_pidfd_send_signal(fd, SIGUSR1, esi, 0); + pidns_print_leader(); printf("pidfd_send_signal(%d, SIGUSR1, %p, 0) = %s\n", fd, esi, errstr); si->si_signo = SIGUSR1; si->si_code = SI_QUEUE; + si->si_pid = getpid(); sys_pidfd_send_signal(fd, SIGUSR2, si, -1); + pidns_print_leader(); printf("pidfd_send_signal(%d, SIGUSR2, {si_signo=SIGUSR1" - ", si_code=SI_QUEUE, si_errno=%u, si_pid=%d, si_uid=%d" + ", si_code=SI_QUEUE, si_errno=%u, si_pid=%d%s, si_uid=%d" ", si_value={int=%d, ptr=%p}}, %#x) = %s\n", - fd, si->si_errno, si->si_pid, si->si_uid, si->si_int, si->si_ptr, - -1U, errstr); + fd, si->si_errno, si->si_pid, pidns_pid2str(PT_TGID), si->si_uid, + si->si_int, si->si_ptr, -1U, errstr); + pidns_print_leader(); puts("+++ exited with 0 +++"); return 0; } diff --git a/tests/prlimit64--pidns-translation.c b/tests/prlimit64--pidns-translation.c new file mode 100644 index 00000000..3972de66 --- /dev/null +++ b/tests/prlimit64--pidns-translation.c @@ -0,0 +1,2 @@ +#define PIDNS_TRANSLATION +#include "prlimit64.c" diff --git a/tests/prlimit64.c b/tests/prlimit64.c index 34201a2b..bc1a80b3 100644 --- a/tests/prlimit64.c +++ b/tests/prlimit64.c @@ -19,6 +19,7 @@ # include # include +# include "pidns.h" # include "xlat.h" # include "xlat/resources.h" @@ -42,8 +43,11 @@ sprint_rlim(uint64_t lim) int main(void) { + PIDNS_TEST_INIT; + unsigned long pid = (unsigned long) 0xdefaced00000000ULL | (unsigned) getpid(); + const char *pid_str = pidns_pid2str(PT_TGID); uint64_t *const rlimit = tail_alloc(sizeof(*rlimit) * 2); const struct xlat_data *xlat; size_t i = 0; @@ -54,18 +58,23 @@ main(void) unsigned long res = 0xfacefeed00000000ULL | xlat->val; long rc = syscall(__NR_prlimit64, pid, res, 0, rlimit); + pidns_print_leader(); if (rc) - printf("prlimit64(%d, %s, NULL, %p) = %ld %s (%m)\n", - (unsigned) pid, xlat->str, rlimit, + printf("prlimit64(%d%s, %s, NULL, %p) =" + " %ld %s (%m)\n", + (unsigned) pid, pid_str, + xlat->str, rlimit, rc, errno2name()); else - printf("prlimit64(%d, %s, NULL" + printf("prlimit64(%d%s, %s, NULL" ", {rlim_cur=%s, rlim_max=%s}) = 0\n", - (unsigned) pid, xlat->str, + (unsigned) pid, pid_str, + xlat->str, sprint_rlim(rlimit[0]), sprint_rlim(rlimit[1])); } + pidns_print_leader(); puts("+++ exited with 0 +++"); return 0; } diff --git a/tests/process_vm_readv--pidns-translation.c b/tests/process_vm_readv--pidns-translation.c new file mode 100644 index 00000000..0db29ca2 --- /dev/null +++ b/tests/process_vm_readv--pidns-translation.c @@ -0,0 +1,2 @@ +#define PIDNS_TRANSLATION +#include "process_vm_readv.c" diff --git a/tests/process_vm_readv_writev.c b/tests/process_vm_readv_writev.c index 9309135a..44e511dd 100644 --- a/tests/process_vm_readv_writev.c +++ b/tests/process_vm_readv_writev.c @@ -12,6 +12,7 @@ #include #include #include +#include "pidns.h" #if OP_WR # define in_iovec rmt_iovec @@ -121,7 +122,7 @@ print_iov(const struct iovec *iov, const void *arg_ptr, long rc) } static void -do_call(kernel_ulong_t pid, +do_call(kernel_ulong_t pid, enum pid_type pid_type, kernel_ulong_t local_iov, const char *local_arg, kernel_ulong_t liovcnt, kernel_ulong_t remote_iov, const char *remote_arg, @@ -135,7 +136,8 @@ do_call(kernel_ulong_t pid, flags); errstr = sprintrc(rc); - printf("%s(%d, ", OP_STR, (int) pid); + pidns_print_leader(); + printf("%s(%d%s, ", OP_STR, (int) pid, pidns_pid2str(pid_type)); if (pr_iov) pr_iov((const struct iovec *) (uintptr_t) local_iov, local_arg, @@ -164,6 +166,8 @@ ptr_cast(void *ptr) int main(void) { + PIDNS_TEST_INIT; + enum { SIZE_11 = 2, SIZE_12 = 3, @@ -243,18 +247,18 @@ main(void) fill_memory_ex(data2_out, SIZE_2, SEGM2_BASE, SIZE_2); - do_call(bogus_pid, (kernel_ulong_t) (uintptr_t) ARG_STR(NULL), + do_call(bogus_pid, PT_NONE, (kernel_ulong_t) (uintptr_t) ARG_STR(NULL), bogus_iovcnt1, (kernel_ulong_t) (uintptr_t) ARG_STR(NULL), bogus_iovcnt2, bogus_flags, NULL); - do_call(my_pid, ptr_cast(bogus_iov + ARRAY_SIZE(bogus_iovec)), + do_call(my_pid, PT_TGID, ptr_cast(bogus_iov + ARRAY_SIZE(bogus_iovec)), "[]", 0, ptr_cast(in_iov + ARRAY_SIZE(in_iovec)), "[]", 0, 0, NULL); - do_call(my_pid, ptr_cast(bogus_iov + ARRAY_SIZE(bogus_iovec)), NULL, - bogus_iovcnt1, ptr_cast(in_iov + ARRAY_SIZE(in_iovec)), NULL, - bogus_iovcnt2, 0, print_iov); + do_call(my_pid, PT_TGID, ptr_cast(bogus_iov + ARRAY_SIZE(bogus_iovec)), + NULL, bogus_iovcnt1, ptr_cast(in_iov + ARRAY_SIZE(in_iovec)), + NULL, bogus_iovcnt2, 0, print_iov); - do_call(my_pid, ptr_cast(bogus_iov), (char *) &bogus_arg, + do_call(my_pid, PT_TGID, ptr_cast(bogus_iov), (char *) &bogus_arg, ARRAY_SIZE(bogus_iovec), ptr_cast(rmt_iov + 2), (char *) &rmt_arg_cut, ARRAY_SIZE(rmt_iovec) - 2, 0, print_iov); @@ -263,7 +267,7 @@ main(void) lcl_arg_cut.check_rc = 1; #endif - do_call(my_pid, ptr_cast(lcl_iov + 2), (char *) &lcl_arg_cut, + do_call(my_pid, PT_TGID, ptr_cast(lcl_iov + 2), (char *) &lcl_arg_cut, ARRAY_SIZE(lcl_iovec) - 1, ptr_cast(bogus_iov + 2), (char *) &bogus_arg_cut, ARRAY_SIZE(bogus_iovec) - 1, 0, print_iov); @@ -273,15 +277,16 @@ main(void) rmt_arg_cut.addr_term = 1; rmt_arg_cut.count = 5; - do_call(my_pid, ptr_cast(lcl_iov + 2), (char *) &lcl_arg_cut, + do_call(my_pid, PT_TGID, ptr_cast(lcl_iov + 2), (char *) &lcl_arg_cut, ARRAY_SIZE(lcl_iovec) - 2, ptr_cast(rmt_iov + 1), (char *) &rmt_arg_cut, ARRAY_SIZE(rmt_iovec), 0, print_iov); /* Correct call */ - do_call(my_pid, ptr_cast(lcl_iov), (char *) &lcl_arg, + do_call(my_pid, PT_TGID, ptr_cast(lcl_iov), (char *) &lcl_arg, ARRAY_SIZE(lcl_iovec), ptr_cast(rmt_iov), (char *) &rmt_arg, ARRAY_SIZE(rmt_iovec), 0, print_iov); + pidns_print_leader(); puts("+++ exited with 0 +++"); return 0; diff --git a/tests/process_vm_writev--pidns-translation.c b/tests/process_vm_writev--pidns-translation.c new file mode 100644 index 00000000..9ba6a39b --- /dev/null +++ b/tests/process_vm_writev--pidns-translation.c @@ -0,0 +1,2 @@ +#define PIDNS_TRANSLATION +#include "process_vm_writev.c" diff --git a/tests/rt_sigqueueinfo--pidns-translation.c b/tests/rt_sigqueueinfo--pidns-translation.c new file mode 100644 index 00000000..74bfb464 --- /dev/null +++ b/tests/rt_sigqueueinfo--pidns-translation.c @@ -0,0 +1,2 @@ +#define PIDNS_TRANSLATION +#include "rt_sigqueueinfo.c" diff --git a/tests/rt_sigqueueinfo.c b/tests/rt_sigqueueinfo.c index 3d3ae52c..7189ef14 100644 --- a/tests/rt_sigqueueinfo.c +++ b/tests/rt_sigqueueinfo.c @@ -7,6 +7,7 @@ */ #include "tests.h" +#include "pidns.h" #include #include #include @@ -15,6 +16,8 @@ int main(void) { + PIDNS_TEST_INIT; + struct sigaction sa = { .sa_handler = SIG_IGN }; @@ -22,15 +25,19 @@ main(void) .sival_ptr = (void *) (unsigned long) 0xdeadbeefbadc0dedULL }; pid_t pid = getpid(); + const char *pid_str = pidns_pid2str(PT_TGID); assert(sigaction(SIGUSR1, &sa, NULL) == 0); if (sigqueue(pid, SIGUSR1, value)) perror_msg_and_skip("sigqueue"); - printf("rt_sigqueueinfo(%u, SIGUSR1, {si_signo=SIGUSR1, " - "si_code=SI_QUEUE, si_pid=%d, si_uid=%d, " + pidns_print_leader(); + printf("rt_sigqueueinfo(%d%s, SIGUSR1, {si_signo=SIGUSR1, " + "si_code=SI_QUEUE, si_pid=%d%s, si_uid=%u, " "si_value={int=%d, ptr=%p}}) = 0\n", - pid, pid, getuid(), value.sival_int, value.sival_ptr); - printf("+++ exited with 0 +++\n"); + pid, pid_str, pid, pid_str, + getuid(), value.sival_int, value.sival_ptr); + pidns_print_leader(); + puts("+++ exited with 0 +++"); return 0; } diff --git a/tests/rt_tgsigqueueinfo--pidns-translation.c b/tests/rt_tgsigqueueinfo--pidns-translation.c new file mode 100644 index 00000000..94396f00 --- /dev/null +++ b/tests/rt_tgsigqueueinfo--pidns-translation.c @@ -0,0 +1,2 @@ +#define PIDNS_TRANSLATION +#include "rt_tgsigqueueinfo.c" diff --git a/tests/rt_tgsigqueueinfo.c b/tests/rt_tgsigqueueinfo.c index 918e41d0..dcd7b161 100644 --- a/tests/rt_tgsigqueueinfo.c +++ b/tests/rt_tgsigqueueinfo.c @@ -10,8 +10,9 @@ #include "tests.h" #include "scno.h" +#include "pidns.h" -#ifdef __NR_rt_tgsigqueueinfo +#if defined __NR_rt_tgsigqueueinfo && defined __NR_gettid # include # include @@ -20,11 +21,11 @@ # include static long -k_tgsigqueueinfo(const pid_t pid, const int sig, const void *const info) +k_tgsigqueueinfo(const pid_t tgid, const int tid, const int sig, const void *const info) { return syscall(__NR_rt_tgsigqueueinfo, - F8ILL_KULONG_MASK | pid, - F8ILL_KULONG_MASK | pid, + F8ILL_KULONG_MASK | tgid, + F8ILL_KULONG_MASK | tid, F8ILL_KULONG_MASK | sig, info); } @@ -32,6 +33,8 @@ k_tgsigqueueinfo(const pid_t pid, const int sig, const void *const info) int main(void) { + PIDNS_TEST_INIT; + const struct sigaction sa = { .sa_handler = SIG_IGN }; @@ -48,17 +51,22 @@ main(void) info->si_value.sival_ptr = (void *) (unsigned long) 0xdeadbeeffacefeedULL; - if (k_tgsigqueueinfo(info->si_pid, SIGUSR1, info)) + if (k_tgsigqueueinfo(getpid(), syscall(__NR_gettid), SIGUSR1, info)) (errno == ENOSYS ? perror_msg_and_skip : perror_msg_and_fail)( "rt_tgsigqueueinfo"); - printf("rt_tgsigqueueinfo(%u, %u, %s, {si_signo=%s" - ", si_code=SI_QUEUE, si_errno=ENOENT, si_pid=%d" + pidns_print_leader(); + printf("rt_tgsigqueueinfo(%d%s, %d%s, %s, {si_signo=%s" + ", si_code=SI_QUEUE, si_errno=ENOENT, si_pid=%d%s" ", si_uid=%d, si_value={int=%d, ptr=%p}}) = 0\n", - info->si_pid, info->si_pid, "SIGUSR1", "SIGUSR1", - info->si_pid, info->si_uid, info->si_value.sival_int, + info->si_pid, pidns_pid2str(PT_TGID), + info->si_pid, pidns_pid2str(PT_TID), + "SIGUSR1", "SIGUSR1", + info->si_pid, pidns_pid2str(PT_TGID), + info->si_uid, info->si_value.sival_int, info->si_value.sival_ptr); + pidns_print_leader(); puts("+++ exited with 0 +++"); return 0; } diff --git a/tests/sched_xetaffinity--pidns-translation.c b/tests/sched_xetaffinity--pidns-translation.c new file mode 100644 index 00000000..814e3989 --- /dev/null +++ b/tests/sched_xetaffinity--pidns-translation.c @@ -0,0 +1,2 @@ +#define PIDNS_TRANSLATION +#include "sched_xetaffinity.c" diff --git a/tests/sched_xetaffinity.c b/tests/sched_xetaffinity.c index cebff3ab..2e508ca3 100644 --- a/tests/sched_xetaffinity.c +++ b/tests/sched_xetaffinity.c @@ -10,6 +10,7 @@ #include "tests.h" #include "scno.h" +#include "pidns.h" #include #if defined __NR_sched_getaffinity && defined __NR_sched_setaffinity \ @@ -41,8 +42,11 @@ setaffinity(unsigned long pid, unsigned long size, void *set) int main(void) { + PIDNS_TEST_INIT; + unsigned int cpuset_size = 1; const pid_t pid = getpid(); + const char *pid_str = pidns_pid2str(PT_TGID); while (cpuset_size) { assert(getaffinity(pid, cpuset_size, NULL) == -1); @@ -50,18 +54,21 @@ main(void) break; if (EINVAL != errno) perror_msg_and_skip("sched_getaffinity"); - printf("sched_getaffinity(%d, %u, NULL) = %s\n", - pid, cpuset_size, errstr); + pidns_print_leader(); + printf("sched_getaffinity(%d%s, %u, NULL) = %s\n", + pid, pid_str, cpuset_size, errstr); cpuset_size <<= 1; } assert(cpuset_size); - printf("sched_getaffinity(%d, %u, NULL) = %s\n", - pid, cpuset_size, errstr); + pidns_print_leader(); + printf("sched_getaffinity(%d%s, %u, NULL) = %s\n", + pid, pid_str, cpuset_size, errstr); cpu_set_t *cpuset = tail_alloc(cpuset_size); getaffinity(pid, cpuset_size, cpuset + 1); - printf("sched_getaffinity(%d, %u, %p) = %s\n", - pid, cpuset_size, cpuset + 1, errstr); + pidns_print_leader(); + printf("sched_getaffinity(%d%s, %u, %p) = %s\n", + pid, pid_str, cpuset_size, cpuset + 1, errstr); int ret_size = getaffinity(pid, cpuset_size, cpuset); if (ret_size < 0) @@ -69,7 +76,8 @@ main(void) pid, (unsigned) cpuset_size, cpuset, errstr); assert(ret_size <= (int) cpuset_size); - printf("sched_getaffinity(%d, %u, [", pid, cpuset_size); + pidns_print_leader(); + printf("sched_getaffinity(%d%s, %u, [", pid, pid_str, cpuset_size); const char *sep; unsigned int i, cpu; for (i = 0, cpu = 0, sep = ""; i < (unsigned) ret_size * 8; ++i) { @@ -85,8 +93,9 @@ main(void) CPU_SET_S(cpu, cpuset_size, cpuset); if (setaffinity(pid, cpuset_size, cpuset)) perror_msg_and_skip("sched_setaffinity"); - printf("sched_setaffinity(%d, %u, [%u]) = 0\n", - pid, cpuset_size, cpu); + pidns_print_leader(); + printf("sched_setaffinity(%d%s, %u, [%u]) = 0\n", + pid, pid_str, cpuset_size, cpu); const unsigned int big_size = cpuset_size < 128 ? 128 : cpuset_size * 2; cpuset = tail_alloc(big_size); @@ -95,7 +104,8 @@ main(void) perror_msg_and_fail("sched_getaffinity(%d, %u, %p) = %s\n", pid, big_size, cpuset, errstr); assert(ret_size <= (int) big_size); - printf("sched_getaffinity(%d, %u, [", pid, big_size); + pidns_print_leader(); + printf("sched_getaffinity(%d%s, %u, [", pid, pid_str, big_size); for (i = 0, sep = ""; i < (unsigned) ret_size * 8; ++i) { if (CPU_ISSET_S(i, (unsigned) ret_size, cpuset)) { printf("%s%u", sep, i); @@ -104,6 +114,7 @@ main(void) } printf("]) = %s\n", errstr); + pidns_print_leader(); puts("+++ exited with 0 +++"); return 0; } diff --git a/tests/sched_xetattr--pidns-translation.c b/tests/sched_xetattr--pidns-translation.c new file mode 100644 index 00000000..c152023d --- /dev/null +++ b/tests/sched_xetattr--pidns-translation.c @@ -0,0 +1,2 @@ +#define PIDNS_TRANSLATION +#include "sched_xetattr.c" diff --git a/tests/sched_xetattr.c b/tests/sched_xetattr.c index c63d7a80..4a76b2d6 100644 --- a/tests/sched_xetattr.c +++ b/tests/sched_xetattr.c @@ -15,6 +15,7 @@ # include # include # include +# include "pidns.h" # include "sched_attr.h" # include "xlat.h" # include "xlat/schedulers.h" @@ -41,6 +42,8 @@ sys_sched_setattr(kernel_ulong_t pid, kernel_ulong_t attr, kernel_ulong_t flags) int main(void) { + PIDNS_TEST_INIT; + static const kernel_ulong_t bogus_pid = (kernel_ulong_t) 0xdefacedfacefeedULL; static const kernel_ulong_t bogus_size = @@ -48,20 +51,28 @@ main(void) static const kernel_ulong_t bogus_flags = (kernel_ulong_t) 0xdefaceddeadc0deULL; + const int pid = getpid(); + const char *pid_str = pidns_pid2str(PT_TGID); + TAIL_ALLOC_OBJECT_CONST_PTR(struct sched_attr, attr); TAIL_ALLOC_OBJECT_CONST_PTR(unsigned int, psize); void *const efault = attr + 1; - sys_sched_getattr(0, 0, 0, 0); - printf("sched_getattr(0, NULL, 0, 0) = %s\n", errstr); + sys_sched_getattr(pid, 0, 0, 0); + pidns_print_leader(); + printf("sched_getattr(%d%s, NULL, 0, 0) = %s\n", + pid, pid_str, errstr); sys_sched_getattr(0, (unsigned long) attr, 0, 0); + pidns_print_leader(); printf("sched_getattr(0, %p, 0, 0) = %s\n", attr, errstr); sys_sched_getattr(bogus_pid, 0, 0, 0); + pidns_print_leader(); printf("sched_getattr(%d, NULL, 0, 0) = %s\n", (int) bogus_pid, errstr); sys_sched_getattr(-1U, (unsigned long) attr, bogus_size, bogus_flags); + pidns_print_leader(); printf("sched_getattr(-1, %p, %s%u, %u) = %s\n", attr, # if defined __arm64__ || defined __aarch64__ @@ -72,11 +83,13 @@ main(void) (unsigned) bogus_size, (unsigned) bogus_flags, errstr); sys_sched_getattr(0, (unsigned long) efault, SCHED_ATTR_MIN_SIZE, 0); + pidns_print_leader(); printf("sched_getattr(0, %p, %u, 0) = %s\n", efault, (unsigned) SCHED_ATTR_MIN_SIZE, errstr); if (sys_sched_getattr(0, (unsigned long) attr, SCHED_ATTR_MIN_SIZE, 0)) perror_msg_and_skip("sched_getattr"); + pidns_print_leader(); printf("sched_getattr(0, {size=%u, sched_policy=", attr->size); printxval(schedulers, attr->sched_policy, NULL); printf(", sched_flags=%s, sched_nice=%d, sched_priority=%u" @@ -91,11 +104,13 @@ main(void) (unsigned) SCHED_ATTR_MIN_SIZE); sys_sched_getattr(0, (unsigned long) efault, sizeof(*attr), 0); + pidns_print_leader(); printf("sched_getattr(0, %p, %u, 0) = %s\n", efault, (unsigned) sizeof(*attr), errstr); if (sys_sched_getattr(0, (unsigned long) attr, sizeof(*attr), 0)) perror_msg_and_skip("sched_getattr"); + pidns_print_leader(); printf("sched_getattr(0, {size=%u, sched_policy=", attr->size); printxval(schedulers, attr->sched_policy, NULL); printf(", sched_flags=%s, sched_nice=%d, sched_priority=%u" @@ -121,11 +136,13 @@ main(void) F8ILL_KULONG_MASK | sizeof(*attr), F8ILL_KULONG_MASK); # if defined __arm64__ || defined __aarch64__ if (rc) { + pidns_print_leader(); printf("sched_getattr(0, %p, 0xffffffff<<32|%u, 0) = %s\n", attr, (unsigned) sizeof(*attr), errstr); } else # endif { + pidns_print_leader(); printf("sched_getattr(0, {size=%u, sched_policy=", attr->size); printxval(schedulers, attr->sched_policy, NULL); printf(", sched_flags=%s, sched_nice=%d, sched_priority=%u" @@ -146,13 +163,16 @@ main(void) } sys_sched_setattr(bogus_pid, 0, 0); + pidns_print_leader(); printf("sched_setattr(%d, NULL, 0) = %s\n", (int) bogus_pid, errstr); attr->sched_flags |= 1; - if (sys_sched_setattr(0, (unsigned long) attr, 0)) + if (sys_sched_setattr(pid, (unsigned long) attr, 0)) perror_msg_and_skip("sched_setattr"); - printf("sched_setattr(0, {size=%u, sched_policy=", attr->size); + pidns_print_leader(); + printf("sched_setattr(%d%s, {size=%u, sched_policy=", + pid, pid_str, attr->size); printxval(schedulers, attr->sched_policy, NULL); printf(", sched_flags=%s, sched_nice=%d, sched_priority=%u" ", sched_runtime=%" PRIu64 ", sched_deadline=%" PRIu64 @@ -172,6 +192,7 @@ main(void) sys_sched_setattr(F8ILL_KULONG_MASK, (unsigned long) attr, F8ILL_KULONG_MASK); + pidns_print_leader(); printf("sched_setattr(0, {size=%u, sched_policy=", attr->size); printxval(schedulers, attr->sched_policy, NULL); printf(", sched_flags=%s, sched_nice=%d, sched_priority=%u" @@ -193,11 +214,13 @@ main(void) *psize = attr->size; sys_sched_setattr(0, (unsigned long) psize, 0); + pidns_print_leader(); printf("sched_setattr(0, %p, 0) = %s\n", psize, errstr); attr->size = 0; sys_sched_setattr(0, (unsigned long) attr, 0); + pidns_print_leader(); printf("sched_setattr(0, {size=%u, sched_policy=", attr->size); printxval(schedulers, attr->sched_policy, NULL); printf(", sched_flags=%s, sched_nice=%d, sched_priority=%u" @@ -213,12 +236,14 @@ main(void) attr->size = 1; sys_sched_setattr(0, (unsigned long) attr, 0); + pidns_print_leader(); printf("sched_setattr(0, {size=%u} => {size=%u}, 0) = %s\n", 1, attr->size, errstr); attr->size = SCHED_ATTR_MIN_SIZE - 1; sys_sched_setattr(0, (unsigned long) attr, 0); + pidns_print_leader(); printf("sched_setattr(0, {size=%u} => {size=%u}, 0) = %s\n", SCHED_ATTR_MIN_SIZE - 1, attr->size, errstr); @@ -232,6 +257,7 @@ main(void) attr->sched_period = 0xded1ca7edda7aca7ULL; sys_sched_setattr(bogus_pid, (unsigned long) attr, bogus_flags); + pidns_print_leader(); printf("sched_setattr(%d, {size=%u, sched_policy=%#x /* SCHED_??? */, " "sched_flags=%#" PRIx64 " /* SCHED_FLAG_??? */, " "sched_nice=%d, sched_priority=%u, sched_runtime=%" PRIu64 ", " @@ -274,6 +300,7 @@ main(void) attr->sched_period = 0xded1ca7edda7aca7ULL; sys_sched_setattr(bogus_pid, (unsigned long) attr, bogus_flags); + pidns_print_leader(); printf("sched_setattr(%d, {size=%u, sched_policy=%#x /* SCHED_??? */, " "sched_flags=SCHED_FLAG_RESET_ON_FORK|SCHED_FLAG_RECLAIM|" "SCHED_FLAG_DL_OVERRUN|0x80, " @@ -296,11 +323,13 @@ main(void) const kernel_ulong_t ill = f8ill_ptr_to_kulong(attr); sys_sched_getattr(0, ill, sizeof(*attr), 0); + pidns_print_leader(); printf("sched_getattr(0, %#llx, %u, 0) = %s\n", (unsigned long long) ill, (unsigned) sizeof(*attr), errstr); sys_sched_setattr(0, ill, 0); + pidns_print_leader(); printf("sched_setattr(0, %#llx, 0) = %s\n", (unsigned long long) ill, errstr); } @@ -310,6 +339,7 @@ main(void) attr->sched_flags = 0x8fULL; sys_sched_setattr(bogus_pid, (unsigned long) attr, bogus_flags); + pidns_print_leader(); printf("sched_setattr(%d, {size=%u, " "sched_flags=SCHED_FLAG_RESET_ON_FORK|SCHED_FLAG_RECLAIM|" "SCHED_FLAG_DL_OVERRUN|SCHED_FLAG_KEEP_POLICY|0x80, " @@ -329,11 +359,13 @@ main(void) const kernel_ulong_t ill = f8ill_ptr_to_kulong(attr); sys_sched_getattr(0, ill, sizeof(*attr), 0); + pidns_print_leader(); printf("sched_getattr(0, %#llx, %u, 0) = %s\n", (unsigned long long) ill, (unsigned) sizeof(*attr), errstr); sys_sched_setattr(0, ill, 0); + pidns_print_leader(); printf("sched_setattr(0, %#llx, 0) = %s\n", (unsigned long long) ill, errstr); } @@ -342,6 +374,7 @@ main(void) attr->sched_flags = 0xe7ULL; sys_sched_setattr(bogus_pid, (unsigned long) attr, bogus_flags); + pidns_print_leader(); printf("sched_setattr(%d, {size=%u, sched_policy=%#x /* SCHED_??? */, " "sched_flags=SCHED_FLAG_RESET_ON_FORK|SCHED_FLAG_RECLAIM|" "SCHED_FLAG_DL_OVERRUN|SCHED_FLAG_UTIL_CLAMP_MIN" @@ -365,11 +398,13 @@ main(void) const kernel_ulong_t ill = f8ill_ptr_to_kulong(attr); sys_sched_getattr(0, ill, sizeof(*attr), 0); + pidns_print_leader(); printf("sched_getattr(0, %#llx, %u, 0) = %s\n", (unsigned long long) ill, (unsigned) sizeof(*attr), errstr); sys_sched_setattr(0, ill, 0); + pidns_print_leader(); printf("sched_setattr(0, %#llx, 0) = %s\n", (unsigned long long) ill, errstr); } @@ -377,6 +412,7 @@ main(void) attr->sched_flags = 0xcaffee90LL; sys_sched_setattr(bogus_pid, (unsigned long) attr, bogus_flags); + pidns_print_leader(); printf("sched_setattr(%d, {size=%u, sched_flags=SCHED_FLAG_KEEP_PARAMS" "|0xcaffee80, sched_util_min=%u, sched_util_max=%u}, %u) = %s\n", (int) bogus_pid, @@ -389,15 +425,18 @@ main(void) const kernel_ulong_t ill = f8ill_ptr_to_kulong(attr); sys_sched_getattr(0, ill, sizeof(*attr), 0); + pidns_print_leader(); printf("sched_getattr(0, %#llx, %u, 0) = %s\n", (unsigned long long) ill, (unsigned) sizeof(*attr), errstr); sys_sched_setattr(0, ill, 0); + pidns_print_leader(); printf("sched_setattr(0, %#llx, 0) = %s\n", (unsigned long long) ill, errstr); } + pidns_print_leader(); puts("+++ exited with 0 +++"); return 0; } diff --git a/tests/sched_xetparam--pidns-translation.c b/tests/sched_xetparam--pidns-translation.c new file mode 100644 index 00000000..9fb3e579 --- /dev/null +++ b/tests/sched_xetparam--pidns-translation.c @@ -0,0 +1,2 @@ +#define PIDNS_TRANSLATION +#include "sched_xetparam.c" diff --git a/tests/sched_xetparam.c b/tests/sched_xetparam.c index de3915b2..aa9c68cc 100644 --- a/tests/sched_xetparam.c +++ b/tests/sched_xetparam.c @@ -7,6 +7,7 @@ #include "tests.h" #include "scno.h" +# include "pidns.h" #if defined __NR_sched_getparam && defined __NR_sched_setparam @@ -17,18 +18,27 @@ int main(void) { + PIDNS_TEST_INIT; + struct sched_param *const param = tail_alloc(sizeof(struct sched_param)); - long rc = syscall(__NR_sched_getparam, 0, param); - printf("sched_getparam(0, [%d]) = %ld\n", - param->sched_priority, rc); + const int pid = getpid(); + const char *pid_str = pidns_pid2str(PT_TGID); + + long rc = syscall(__NR_sched_getparam, pid, param); + pidns_print_leader(); + printf("sched_getparam(%d%s, [%d]) = %ld\n", + pid, pid_str, param->sched_priority, rc); param->sched_priority = -1; - rc = syscall(__NR_sched_setparam, 0, param); - printf("sched_setparam(0, [%d]) = %ld %s (%m)\n", + rc = syscall(__NR_sched_setparam, pid, param); + pidns_print_leader(); + printf("sched_setparam(%d%s, [%d]) = %ld %s (%m)\n", + pid, pid_str, param->sched_priority, rc, errno2name()); + pidns_print_leader(); puts("+++ exited with 0 +++"); return 0; } diff --git a/tests/sched_xetscheduler--pidns-translation.c b/tests/sched_xetscheduler--pidns-translation.c new file mode 100644 index 00000000..78b794b2 --- /dev/null +++ b/tests/sched_xetscheduler--pidns-translation.c @@ -0,0 +1,2 @@ +#define PIDNS_TRANSLATION +#include "sched_xetscheduler.c" diff --git a/tests/sched_xetscheduler.c b/tests/sched_xetscheduler.c index 047e8676..91b5e32d 100644 --- a/tests/sched_xetscheduler.c +++ b/tests/sched_xetscheduler.c @@ -7,6 +7,7 @@ #include "tests.h" #include "scno.h" +#include "pidns.h" #if defined __NR_sched_getscheduler && defined __NR_sched_setscheduler @@ -17,8 +18,13 @@ int main(void) { + PIDNS_TEST_INIT; + TAIL_ALLOC_OBJECT_CONST_PTR(struct sched_param, param); - long rc = syscall(__NR_sched_getscheduler, 0); + const int pid = getpid(); + const char *pid_str = pidns_pid2str(PT_TGID); + + long rc = syscall(__NR_sched_getscheduler, pid); const char *scheduler; switch (rc) { case SCHED_FIFO: @@ -50,33 +56,43 @@ main(void) default: scheduler = "SCHED_OTHER"; } - printf("sched_getscheduler(0) = %ld (%s)\n", - rc, scheduler); + pidns_print_leader(); + printf("sched_getscheduler(%d%s) = %ld (%s)\n", + pid, pid_str, rc, scheduler); rc = syscall(__NR_sched_getscheduler, -1); + pidns_print_leader(); printf("sched_getscheduler(-1) = %s\n", sprintrc(rc)); param->sched_priority = -1; - rc = syscall(__NR_sched_setscheduler, 0, SCHED_FIFO, NULL); - printf("sched_setscheduler(0, SCHED_FIFO, NULL) = %s\n", sprintrc(rc)); + rc = syscall(__NR_sched_setscheduler, pid, SCHED_FIFO, NULL); + pidns_print_leader(); + printf("sched_setscheduler(%d%s, SCHED_FIFO, NULL) = %s\n", + pid, pid_str, sprintrc(rc)); - rc = syscall(__NR_sched_setscheduler, 0, SCHED_FIFO, param + 1); - printf("sched_setscheduler(0, SCHED_FIFO, %p) = %s\n", param + 1, - sprintrc(rc)); + rc = syscall(__NR_sched_setscheduler, pid, SCHED_FIFO, param + 1); + pidns_print_leader(); + printf("sched_setscheduler(%d%s, SCHED_FIFO, %p) = %s\n", + pid, pid_str, param + 1, sprintrc(rc)); - rc = syscall(__NR_sched_setscheduler, 0, 0xfaceda7a, param); - printf("sched_setscheduler(0, %#x /* SCHED_??? */, [%d]) = %s\n", - 0xfaceda7a, param->sched_priority, sprintrc(rc)); + rc = syscall(__NR_sched_setscheduler, pid, 0xfaceda7a, param); + pidns_print_leader(); + printf("sched_setscheduler(%d%s, %#x /* SCHED_??? */, [%d]) = %s\n", + pid, pid_str, 0xfaceda7a, + param->sched_priority, sprintrc(rc)); rc = syscall(__NR_sched_setscheduler, -1, SCHED_FIFO, param); + pidns_print_leader(); printf("sched_setscheduler(-1, SCHED_FIFO, [%d]) = %s\n", param->sched_priority, sprintrc(rc)); - rc = syscall(__NR_sched_setscheduler, 0, SCHED_FIFO, param); - printf("sched_setscheduler(0, SCHED_FIFO, [%d]) = %s\n", - param->sched_priority, sprintrc(rc)); + rc = syscall(__NR_sched_setscheduler, pid, SCHED_FIFO, param); + pidns_print_leader(); + printf("sched_setscheduler(%d%s, SCHED_FIFO, [%d]) = %s\n", + pid, pid_str, param->sched_priority, sprintrc(rc)); + pidns_print_leader(); puts("+++ exited with 0 +++"); return 0; } diff --git a/tests/signal_receive--pidns-translation.c b/tests/signal_receive--pidns-translation.c new file mode 100644 index 00000000..b4e3b2f8 --- /dev/null +++ b/tests/signal_receive--pidns-translation.c @@ -0,0 +1,2 @@ +#define PIDNS_TRANSLATION +#include "signal_receive.c" diff --git a/tests/signal_receive.c b/tests/signal_receive.c index ad3b4ebd..70441a9e 100644 --- a/tests/signal_receive.c +++ b/tests/signal_receive.c @@ -8,6 +8,7 @@ */ #include "tests.h" +#include "pidns.h" #include #include #include @@ -26,10 +27,13 @@ handler(int sig, siginfo_t *info, void *ucontext) int main(void) { + PIDNS_TEST_INIT; + static const char prefix[] = "KERNEL BUG"; int printed = 0; const int pid = getpid(); + const char *pid_str = pidns_pid2str(PT_TGID); const int uid = geteuid(); for (int sig = 1; sig <= 31; ++sig) { @@ -73,10 +77,13 @@ main(void) const int e_pid = s_pid; const int e_uid = s_uid; #endif - printf("kill(%d, %s) = 0\n", pid, signal2name(sig)); - printf("--- %s {si_signo=%s, si_code=SI_USER, si_pid=%d" + pidns_print_leader(); + printf("kill(%d%s, %s) = 0\n", pid, pid_str, signal2name(sig)); + pidns_print_leader(); + printf("--- %s {si_signo=%s, si_code=SI_USER, si_pid=%d%s" ", si_uid=%d} ---\n", - signal2name(sig), signal2name(e_sig), e_pid, e_uid); + signal2name(sig), signal2name(e_sig), + e_pid, pid_str, e_uid); if (s_code || sig != s_sig || pid != s_pid || uid != s_uid) { /* @@ -91,11 +98,11 @@ main(void) } fprintf(stderr, "%s: expected: si_signo=%d, si_code=%d" - ", si_pid=%d, si_uid=%d\n" + ", si_pid=%d%s, si_uid=%d\n" "%s: received: si_signo=%d, si_code=%d" - ", si_pid=%d, si_uid=%d\n", - prefix, sig, SI_USER, pid, uid, - prefix, sig, s_code, s_pid, s_uid); + ", si_pid=%d%s, si_uid=%d\n", + prefix, sig, SI_USER, pid, pid_str, uid, + prefix, sig, s_code, s_pid, pid_str, s_uid); } } @@ -104,6 +111,7 @@ main(void) "*** PLEASE FIX THE KERNEL ***\n", prefix); } + pidns_print_leader(); puts("+++ exited with 0 +++"); return 0; } diff --git a/tests/so_peercred--pidns-translation.c b/tests/so_peercred--pidns-translation.c new file mode 100644 index 00000000..402bbcfe --- /dev/null +++ b/tests/so_peercred--pidns-translation.c @@ -0,0 +1,2 @@ +#define PIDNS_TRANSLATION +#include "so_peercred.c" diff --git a/tests/so_peercred.c b/tests/so_peercred.c index 151bb175..20188bdb 100644 --- a/tests/so_peercred.c +++ b/tests/so_peercred.c @@ -9,6 +9,7 @@ */ #include "tests.h" +#include "pidns.h" #include #include @@ -53,6 +54,8 @@ so_str(void) int main(void) { + PIDNS_TEST_INIT; + TAIL_ALLOC_OBJECT_CONST_PTR(struct ucred, peercred); TAIL_ALLOC_OBJECT_CONST_PTR(socklen_t, len); @@ -75,6 +78,8 @@ main(void) struct ucred *const gid_truncated = tail_alloc(sizeof_gid_truncated); + const char *pid_str = pidns_pid2str(PT_TGID); + int sv[2]; if (socketpair(AF_UNIX, SOCK_STREAM, 0, sv)) perror_msg_and_skip("socketpair AF_UNIX SOCK_STREAM"); @@ -82,8 +87,10 @@ main(void) /* classic getsockopt */ *len = sizeof(*peercred); get_peercred(sv[0], peercred, len); + pidns_print_leader(); printf("getsockopt(%d, %s", sv[0], so_str()); PRINT_FIELD_D(", {", *peercred, pid); + printf("%s", pid_str); PRINT_FIELD_UID(", ", *peercred, uid); PRINT_FIELD_UID(", ", *peercred, gid); printf("}, [%d]) = %s\n", *len, errstr); @@ -91,14 +98,17 @@ main(void) /* getsockopt with zero optlen */ *len = 0; get_peercred(sv[0], peercred, len); + pidns_print_leader(); printf("getsockopt(%d, %s, %p, [0]) = %s\n", sv[0], so_str(), peercred, errstr); /* getsockopt with optlen larger than necessary - shortened */ *len = sizeof(*peercred) + 1; get_peercred(sv[0], peercred, len); + pidns_print_leader(); printf("getsockopt(%d, %s", sv[0], so_str()); PRINT_FIELD_D(", {", *peercred, pid); + printf("%s", pid_str); PRINT_FIELD_UID(", ", *peercred, uid); PRINT_FIELD_UID(", ", *peercred, gid); printf("}, [%u->%d]) = %s\n", @@ -110,6 +120,7 @@ main(void) */ *len = sizeof_pid_truncated; get_peercred(sv[0], pid_truncated, len); + pidns_print_leader(); printf("getsockopt(%d, %s, {pid=", sv[0], so_str()); print_quoted_hex(pid_truncated, *len); printf("}, [%d]) = %s\n", *len, errstr); @@ -120,8 +131,10 @@ main(void) */ *len = sizeof_pid; get_peercred(sv[0], pid, len); + pidns_print_leader(); printf("getsockopt(%d, %s", sv[0], so_str()); PRINT_FIELD_D(", {", *pid, pid); + printf("%s", pid_str); printf("}, [%d]) = %s\n", *len, errstr); /* @@ -136,8 +149,10 @@ main(void) * to struct ucred.pid field. */ memcpy(uid, uid_truncated, sizeof_uid_truncated); + pidns_print_leader(); printf("getsockopt(%d, %s", sv[0], so_str()); PRINT_FIELD_D(", {", *uid, pid); + printf("%s", pid_str); printf(", uid="); print_quoted_hex(&uid->uid, sizeof_uid_truncated - offsetof(struct ucred, uid)); @@ -149,8 +164,10 @@ main(void) */ *len = sizeof_uid; get_peercred(sv[0], uid, len); + pidns_print_leader(); printf("getsockopt(%d, %s", sv[0], so_str()); PRINT_FIELD_D(", {", *uid, pid); + printf("%s", pid_str); PRINT_FIELD_UID(", ", *uid, uid); printf("}, [%d]) = %s\n", *len, errstr); @@ -166,8 +183,10 @@ main(void) * to struct ucred.pid and struct ucred.uid fields. */ memcpy(peercred, gid_truncated, sizeof_gid_truncated); + pidns_print_leader(); printf("getsockopt(%d, %s", sv[0], so_str()); PRINT_FIELD_D(", {", *peercred, pid); + printf("%s", pid_str); PRINT_FIELD_UID(", ", *peercred, uid); printf(", gid="); print_quoted_hex(&peercred->gid, sizeof_gid_truncated - @@ -177,14 +196,17 @@ main(void) /* getsockopt optval EFAULT */ *len = sizeof(*peercred); get_peercred(sv[0], &peercred->uid, len); + pidns_print_leader(); printf("getsockopt(%d, %s, %p, [%d]) = %s\n", sv[0], so_str(), &peercred->uid, *len, errstr); /* getsockopt optlen EFAULT */ get_peercred(sv[0], peercred, len + 1); + pidns_print_leader(); printf("getsockopt(%d, %s, %p, %p) = %s\n", sv[0], so_str(), peercred, len + 1, errstr); + pidns_print_leader(); puts("+++ exited with 0 +++"); return 0; } diff --git a/tests/xet_robust_list--pidns-translation.c b/tests/xet_robust_list--pidns-translation.c new file mode 100644 index 00000000..e0477267 --- /dev/null +++ b/tests/xet_robust_list--pidns-translation.c @@ -0,0 +1,2 @@ +#define PIDNS_TRANSLATION +#include "xet_robust_list.c" diff --git a/tests/xet_robust_list.c b/tests/xet_robust_list.c index 43239c8b..b5751b0a 100644 --- a/tests/xet_robust_list.c +++ b/tests/xet_robust_list.c @@ -8,6 +8,7 @@ #include "tests.h" #include "scno.h" +#include "pidns.h" #if defined __NR_get_robust_list && defined __NR_set_robust_list @@ -30,27 +31,36 @@ sprintaddr(void *addr) int main(void) { + PIDNS_TEST_INIT; + const pid_t pid = getpid(); + const char *pid_str = pidns_pid2str(PT_TGID); const long long_pid = (unsigned long) (0xdeadbeef00000000LL | pid); TAIL_ALLOC_OBJECT_CONST_PTR(void *, p_head); TAIL_ALLOC_OBJECT_CONST_PTR(size_t, p_len); if (syscall(__NR_get_robust_list, long_pid, p_head, p_len)) perror_msg_and_skip("get_robust_list"); - printf("get_robust_list(%d, [%s], [%lu]) = 0\n", - (int) pid, sprintaddr(*p_head), (unsigned long) *p_len); + pidns_print_leader(); + printf("get_robust_list(%d%s, [%s], [%lu]) = 0\n", + pid, pid_str, sprintaddr(*p_head), + (unsigned long) *p_len); void *head = tail_alloc(*p_len); if (syscall(__NR_set_robust_list, head, *p_len)) perror_msg_and_skip("set_robust_list"); + pidns_print_leader(); printf("set_robust_list(%p, %lu) = 0\n", head, (unsigned long) *p_len); if (syscall(__NR_get_robust_list, long_pid, p_head, p_len)) perror_msg_and_skip("get_robust_list"); - printf("get_robust_list(%d, [%s], [%lu]) = 0\n", - (int) pid, sprintaddr(*p_head), (unsigned long) *p_len); + pidns_print_leader(); + printf("get_robust_list(%d%s, [%s], [%lu]) = 0\n", + pid, pid_str, sprintaddr(*p_head), + (unsigned long) *p_len); + pidns_print_leader(); puts("+++ exited with 0 +++"); return 0; } diff --git a/tests/xetpgid--pidns-translation.c b/tests/xetpgid--pidns-translation.c new file mode 100644 index 00000000..b6469628 --- /dev/null +++ b/tests/xetpgid--pidns-translation.c @@ -0,0 +1,2 @@ +#define PIDNS_TRANSLATION +#include "xetpgid.c" diff --git a/tests/xetpgid.c b/tests/xetpgid.c index 9b070af2..411edfc7 100644 --- a/tests/xetpgid.c +++ b/tests/xetpgid.c @@ -10,6 +10,7 @@ #include "tests.h" #include "scno.h" +#include "pidns.h" #if defined __NR_getpgid && defined __NR_setpgid @@ -19,13 +20,21 @@ int main(void) { - const int pid = getpid(); - long rc = syscall(__NR_getpgid, F8ILL_KULONG_MASK | pid); - printf("getpgid(%d) = %ld\n", pid, rc); - - rc = syscall(__NR_setpgid, F8ILL_KULONG_MASK, F8ILL_KULONG_MASK | pid); - printf("setpgid(0, %d) = %ld\n", pid, rc); + PIDNS_TEST_INIT; + const int pid = getpid(); + long pgid = syscall(__NR_getpgid, F8ILL_KULONG_MASK | pid); + pidns_print_leader(); + printf("getpgid(%d%s) = %ld%s\n", pid, pidns_pid2str(PT_TGID), + pgid, pidns_pid2str(PT_PGID)); + + long rc = syscall(__NR_setpgid, F8ILL_KULONG_MASK, + F8ILL_KULONG_MASK | pgid); + pidns_print_leader(); + printf("setpgid(0, %ld%s) = %s\n", pgid, pidns_pid2str(PT_PGID), + sprintrc(rc)); + + pidns_print_leader(); puts("+++ exited with 0 +++"); return 0; } diff --git a/tests/xetpriority--pidns-translation.c b/tests/xetpriority--pidns-translation.c new file mode 100644 index 00000000..c93669cb --- /dev/null +++ b/tests/xetpriority--pidns-translation.c @@ -0,0 +1,2 @@ +#define PIDNS_TRANSLATION +#include "xetpriority.c" diff --git a/tests/xetpriority.c b/tests/xetpriority.c index 2d61bd10..dd38217d 100644 --- a/tests/xetpriority.c +++ b/tests/xetpriority.c @@ -7,6 +7,7 @@ #include "tests.h" #include "scno.h" +#include "pidns.h" #if defined __NR_getpriority && defined __NR_setpriority @@ -17,15 +18,30 @@ int main(void) { + PIDNS_TEST_INIT; + const int pid = getpid(); + const int pgid = getpgid(0); + long rc = syscall(__NR_getpriority, PRIO_PROCESS, F8ILL_KULONG_MASK | pid); - printf("getpriority(PRIO_PROCESS, %d) = %ld\n", pid, rc); + pidns_print_leader(); + printf("getpriority(PRIO_PROCESS, %d%s) = %ld\n", + pid, pidns_pid2str(PT_TGID), rc); rc = syscall(__NR_setpriority, PRIO_PROCESS, F8ILL_KULONG_MASK | pid, F8ILL_KULONG_MASK); - printf("setpriority(PRIO_PROCESS, %d, 0) = %s\n", pid, sprintrc(rc)); + pidns_print_leader(); + printf("setpriority(PRIO_PROCESS, %d%s, 0) = %s\n", + pid, pidns_pid2str(PT_TGID), sprintrc(rc)); + + rc = syscall(__NR_getpriority, PRIO_PGRP, + F8ILL_KULONG_MASK | pgid); + pidns_print_leader(); + printf("getpriority(PRIO_PGRP, %d%s) = %ld\n", + pgid, pidns_pid2str(PT_PGID), rc); + pidns_print_leader(); puts("+++ exited with 0 +++"); return 0; } -- 2.27.0 From uzonyi.akos at gmail.com Mon Aug 3 19:19:15 2020 From: uzonyi.akos at gmail.com (=?UTF-8?q?=C3=81kos=20Uzonyi?=) Date: Mon, 3 Aug 2020 21:19:15 +0200 Subject: [PATCH v5 4/5] Implement testing framework for pidns In-Reply-To: <20200803191916.94724-1-uzonyi.akos@gmail.com> References: <20200803191916.94724-1-uzonyi.akos@gmail.com> Message-ID: <20200803191916.94724-5-uzonyi.akos@gmail.com> * tests/pidns.c: New file. * tests/pidns.h: New file. * tests/Makefile.am (libtests_a_SOURCES): Add pidns.c, pidns.h. * tests/init.sh (test_pidns, test_pidns_run_strace): New functions. --- tests/Makefile.am | 2 + tests/init.sh | 31 +++++++ tests/pidns.c | 214 ++++++++++++++++++++++++++++++++++++++++++++++ tests/pidns.h | 56 ++++++++++++ 4 files changed, 303 insertions(+) create mode 100644 tests/pidns.c create mode 100644 tests/pidns.h diff --git a/tests/Makefile.am b/tests/Makefile.am index 28d95e39..7a583a3a 100644 --- a/tests/Makefile.am +++ b/tests/Makefile.am @@ -44,6 +44,8 @@ libtests_a_SOURCES = \ libsocketcall.c \ lock_file.c \ overflowuid.c \ + pidns.c \ + pidns.h \ pipe_maxfd.c \ print_quoted_string.c \ print_time.c \ diff --git a/tests/init.sh b/tests/init.sh index d78e697b..7325fa4a 100644 --- a/tests/init.sh +++ b/tests/init.sh @@ -387,6 +387,37 @@ test_prog_set() test_pure_prog_set "$@" < "$srcdir/$NAME.in" } +test_pidns_run_strace() +{ + local parent_pid + + check_prog tail + check_prog cut + check_prog grep + + run_prog > /dev/null + run_strace --pidns-translation -f $@ $args > "$EXP" + + # filter out logs made by the parent or init process of the pidns test + parent_pid="$(tail -n 2 $LOG | head -n 1 | cut -d' ' -f1)" + init_pid="$(tail -n 1 $LOG | cut -d' ' -f1)" + grep -E -v "^($parent_pid|$init_pid) " "$LOG" > "$OUT" + match_diff "$OUT" "$EXP" +} + +test_pidns() +{ + # ioctl(NS_GET_PARENT) is added in Linux 4.9 + require_min_kernel_version_or_skip 4.9 + check_prog unshare + + test_pidns_run_strace "$@" + + # test PID translation when /proc is mounted from an other namespace + STRACE="unshare -Urpf $STRACE" + test_pidns_run_strace "$@" +} + check_prog cat check_prog rm diff --git a/tests/pidns.c b/tests/pidns.c new file mode 100644 index 00000000..f54af340 --- /dev/null +++ b/tests/pidns.c @@ -0,0 +1,214 @@ +/* + * Testing framework for PID namespace translation + * + * Copyright (c) 2020 ?kos Uzonyi + * All rights reserved. + * + * SPDX-License-Identifier: LGPL-2.1-or-later + */ +#include "tests.h" +#include "pidns.h" +#include "nsfs.h" + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +static bool pidns_translation = false; +static bool pidns_unshared = false; + +/* Our PIDs in strace's namespace */ +static pid_t pidns_strace_ids[PT_COUNT]; + +void +pidns_print_leader(void) +{ + if (pidns_translation) + printf("%-5d ", pidns_strace_ids[PT_TID]); +} + +const char * +pidns_pid2str(enum pid_type type) +{ + static const char format[] = " /* %d in strace's PID NS */"; + static char buf[PT_COUNT][sizeof(format) + sizeof(int) * 3]; + + if (type < 0 || type >= PT_COUNT) + return ""; + + if (!pidns_unshared || !pidns_strace_ids[type]) + return ""; + + snprintf(buf[type], sizeof(buf[type]), format, pidns_strace_ids[type]); + return buf[type]; +} + +/** + * This function is like fork, but does a few more things. It sets up the + * child's PGID and SID according to the parameters. Also it fills the + * pidns_strace_ids array in the child's memory with the PIDs of the child in + * parent's PID namespace. In the parent it waits for the child to terminate + * (but leaves the zombie to use it later as a process group). If the child + * terminates with nonzero exit status, the test is failed. + * + * @param pgid The process group the child should be moved to. It's expected + * to be a PID of a zombie process (will be reaped). If + * negative, leave the child in the process group of the parent. + * If 0, move the process to its own process group. + * @param new_sid Wheather child should be moved to a new session. + */ +static pid_t +pidns_fork(pid_t pgid, bool new_sid) +{ + int strace_ids_pipe[2]; + if (pipe(strace_ids_pipe) < 0) + perror_msg_and_fail("pipe"); + + fflush(stdout); + pid_t pid = fork(); + if (pid < 0) + perror_msg_and_fail("fork"); + + if (!pid) { + close(strace_ids_pipe[1]); + if (read(strace_ids_pipe[0], pidns_strace_ids, + sizeof(pidns_strace_ids)) < 0) + perror_msg_and_fail("read"); + close(strace_ids_pipe[0]); + + if (pidns_strace_ids[PT_SID]) + setsid(); + + return 0; + } + + pidns_strace_ids[PT_TID] = pid; + pidns_strace_ids[PT_TGID] = pid; + pidns_strace_ids[PT_PGID] = 0; + pidns_strace_ids[PT_SID] = 0; + + if (!pgid) + pgid = pid; + + if (pgid > 0) { + if (setpgid(pid, pgid) < 0) + perror_msg_and_fail("setpgid"); + + pidns_strace_ids[PT_PGID] = pgid; + } + + /* Reap group leader to test PGID decoding */ + if (pgid > 0 && pgid != pid) { + int ret = waitpid(pgid, NULL, WNOHANG); + if (ret < 0) + perror_msg_and_fail("wait"); + if (!ret) + error_msg_and_fail("could not reap group leader"); + } + + if (new_sid) { + pidns_strace_ids[PT_SID] = pid; + pidns_strace_ids[PT_PGID] = pid; + } + + if (write(strace_ids_pipe[1], pidns_strace_ids, + sizeof(pidns_strace_ids)) < 0) + perror_msg_and_fail("write"); + close(strace_ids_pipe[0]); + close(strace_ids_pipe[1]); + + /* WNOWAIT: leave the zombie, to be able to use it as a process group */ + siginfo_t siginfo; + if (waitid(P_PID, pid, &siginfo, WEXITED | WNOWAIT) < 0) + perror_msg_and_fail("wait"); + if (siginfo.si_code != CLD_EXITED || siginfo.si_status) + error_msg_and_fail("child terminated with nonzero exit status"); + + return pid; +} + +static void +create_init_process(void) +{ + int child_pipe[2]; + if (pipe(child_pipe) < 0) + perror_msg_and_fail("pipe"); + + pid_t pid = fork(); + if (pid < 0) + perror_msg_and_fail("fork"); + + if (!pid) { + close(child_pipe[1]); + _exit(read(child_pipe[0], &child_pipe[1], sizeof(int)) == 0); + } + + close(child_pipe[0]); +} + +void +check_ns_ioctl(void) +{ + int fd = open("/proc/self/ns/pid", O_RDONLY); + if (fd < 0) + perror_msg_and_fail("opening /proc/self/ns/pid"); + + int userns_fd = ioctl(fd, NS_GET_USERNS); + if (userns_fd < 0) { + if (errno == ENOTTY) + error_msg_and_skip("NS_* ioctl commands are not " + "supported by the kernel"); + else + perror_msg_and_fail("ioctl(NS_GET_USERNS)"); + } + + close(userns_fd); + close(fd); +} + +void +pidns_test_init(void) +{ + pidns_translation = true; + + check_ns_ioctl(); + + if (!pidns_fork(-1, false)) + return; + + /* Unshare user namespace too, so we do not need to be root */ + if (unshare(CLONE_NEWUSER | CLONE_NEWPID) < 0) { + if (errno == EPERM) + perror_msg_and_skip("unshare"); + + perror_msg_and_fail("unshare"); + } + + pidns_unshared = true; + + create_init_process(); + + if (!pidns_fork(-1, false)) + return; + + if (!pidns_fork(-1, true)) + return; + + pid_t pgid; + if (!(pgid = pidns_fork(0, false))) + return; + + if (!pidns_fork(pgid, false)) + return; + + exit(0); +} diff --git a/tests/pidns.h b/tests/pidns.h new file mode 100644 index 00000000..76963eb3 --- /dev/null +++ b/tests/pidns.h @@ -0,0 +1,56 @@ +/* + * Test PID namespace translation + * + * Copyright (c) 2020 ?kos Uzonyi + * All rights reserved. + * + * SPDX-License-Identifier: LGPL-2.1-or-later + */ +#ifndef STRACE_PIDNS_H +#define STRACE_PIDNS_H + +#ifdef PIDNS_TRANSLATION +# define PIDNS_TEST_INIT pidns_test_init() +#else +# define PIDNS_TEST_INIT +#endif + +#include + +enum pid_type { + PT_TID, + PT_TGID, + PT_PGID, + PT_SID, + + PT_COUNT, + PT_NONE = -1 +}; + +/* Prints leader (process tid) if pidns_test_init was called */ +void pidns_print_leader(void); + +/* + * Returns a static buffer containing the translation string of our PID. + */ +const char *pidns_pid2str(enum pid_type type); + +/** + * Skips the test if NS_* ioctl commands are not supported by the kernel. + */ +void check_ns_ioctl(void); + +/** + * Init pidns testing. + * + * Should be called at the beginning of the test's main function + * + * This function calls fork a couple of times, and returns in the child + * processes. These child processes are in a new PID namespace with different + * PID configurations (group leader, session leader, ...). If any child + * terminates with nonzero exit status the test is failed. Otherwise the test is + * succesful, and the parent process exits with 0. + */ +void pidns_test_init(void); + +#endif \ No newline at end of file -- 2.27.0 From uzonyi.akos at gmail.com Mon Aug 3 19:19:13 2020 From: uzonyi.akos at gmail.com (=?UTF-8?q?=C3=81kos=20Uzonyi?=) Date: Mon, 3 Aug 2020 21:19:13 +0200 Subject: [PATCH v5 2/5] Use printpid in decoders In-Reply-To: <20200803191916.94724-1-uzonyi.akos@gmail.com> References: <20200803191916.94724-1-uzonyi.akos@gmail.com> Message-ID: <20200803191916.94724-3-uzonyi.akos@gmail.com> * getpid.c: New file. * Makefile.am (libstrace_a_SOURCES): Add getpid.c. * linux/dummy.h (sys_getpid, sys_getppid, sys_gettid, sys_setpgid, sys_setpgrp): Remove. * util.c (printfd_pid_tracee_ns): Implement using translate_pid. * defs.h (printnum_pid): New function definition. (printfd_pid_tracee_ns): Update documentation * util.c: (printnum_pid): New function. * print_fields.h (PRINT_FIELD_TID): New macro. (PRINT_FIELD_TGID): Likewise. (PRINT_FIELD_PGID): Likewise. (PRINT_FIELD_SID): Likewise. * affinity.c: Print PIDs with printpid. * block.c: Likewise. * bpf.c: Likewise. * capability.c: Likewise. * clone.c: Likewise. * fcntl.c: Likewise. * get_robust_list.c: Likewise. * ioprio.c: Likewise. * kcmp.c: Likewise. * msghdr.c: Likewise. * net.c: Likewise. * netlink.c: Likewise. * numa.c: Likewise. * pidfd_open.c: Likewise. * printsiginfo.c: Likewise. * process.c: Likewise. * process_vm.c: Likewise. * resource.c: Likewise. * sched.c: Likewise. * signal.c: Likewise. * sockaddr.c: Likewise. * wait.c: Likewise. * kcmp.c (SYS_FUNC(kcmp)): Fix KCMP_FILE pid arguments. * tests/kcmp.c (printpidfd): Print path if VERBOSE_FD. (main): Use our real pid if real fds are used. --- Makefile.am | 1 + affinity.c | 6 ++++-- block.c | 2 +- bpf.c | 2 +- capability.c | 4 +++- clone.c | 14 +++++++------- defs.h | 5 ++++- fcntl.c | 24 ++++++++++++++++++++++-- get_robust_list.c | 3 ++- getpid.c | 46 ++++++++++++++++++++++++++++++++++++++++++++++ ioprio.c | 26 ++++++++++++++++++++++---- ipc_shmctl.c | 5 +++-- kcmp.c | 5 ++++- linux/dummy.h | 8 +------- msghdr.c | 2 +- net.c | 2 +- netlink.c | 5 +++-- numa.c | 6 ++++-- pidfd_open.c | 2 +- print_fields.h | 24 ++++++++++++++++++++++++ printsiginfo.c | 2 +- process.c | 3 ++- process_vm.c | 6 ++++-- resource.c | 27 ++++++++++++++++++++++++--- sched.c | 25 ++++++++++++++++--------- signal.c | 21 +++++++++++++++------ sockaddr.c | 2 +- tests/kcmp.c | 25 ++++++++++++++++++++++--- util.c | 20 ++++++++++++++------ wait.c | 36 ++++++++++++++++++++++++------------ 30 files changed, 278 insertions(+), 81 deletions(-) create mode 100644 getpid.c diff --git a/Makefile.am b/Makefile.am index 73c22035..15fcd9a6 100644 --- a/Makefile.am +++ b/Makefile.am @@ -135,6 +135,7 @@ libstrace_a_SOURCES = \ getcpu.c \ getcwd.c \ getpagesize.c \ + getpid.c \ getrandom.c \ hdio.c \ hostname.c \ diff --git a/affinity.c b/affinity.c index eb3158b7..f9893adb 100644 --- a/affinity.c +++ b/affinity.c @@ -82,7 +82,8 @@ SYS_FUNC(sched_setaffinity) const int pid = tcp->u_arg[0]; const unsigned int len = tcp->u_arg[1]; - tprintf("%d, %u, ", pid, len); + printpid(tcp, pid, PT_TGID); + tprintf(", %u, ", len); print_affinitylist(tcp, tcp->u_arg[2], len); return RVAL_DECODED; @@ -94,7 +95,8 @@ SYS_FUNC(sched_getaffinity) const unsigned int len = tcp->u_arg[1]; if (entering(tcp)) { - tprintf("%d, %u, ", pid, len); + printpid(tcp, pid, PT_TGID); + tprintf(", %u, ", len); } else { print_affinitylist(tcp, tcp->u_arg[2], tcp->u_rval); } diff --git a/block.c b/block.c index a2f41551..231fa56b 100644 --- a/block.c +++ b/block.c @@ -179,7 +179,7 @@ MPERS_PRINTER_DECL(int, block_ioctl, struct tcb *const tcp, PRINT_FIELD_U(", ", buts, buf_nr); PRINT_FIELD_U(", ", buts, start_lba); PRINT_FIELD_U(", ", buts, end_lba); - PRINT_FIELD_D(", ", buts, pid); + PRINT_FIELD_TGID(", ", buts, pid, tcp); return 0; } else { struct_blk_user_trace_setup buts; diff --git a/bpf.c b/bpf.c index af830053..0ec33ba4 100644 --- a/bpf.c +++ b/bpf.c @@ -927,7 +927,7 @@ BEGIN_BPF_CMD_DECODER(BPF_TASK_FD_QUERY) if (entering(tcp)) { set_tcb_priv_ulong(tcp, attr.buf_len); - PRINT_FIELD_D("{task_fd_query={", attr, pid); + PRINT_FIELD_TGID("{task_fd_query={", attr, pid, tcp); PRINT_FIELD_FD(", ", attr, fd, tcp); PRINT_FIELD_U(", ", attr, flags); PRINT_FIELD_U(", ", attr, buf_len); diff --git a/capability.c b/capability.c index 0e763ee1..812fb435 100644 --- a/capability.c +++ b/capability.c @@ -70,7 +70,9 @@ print_cap_header(struct tcb *const tcp, const kernel_ulong_t addr, tprints("{version="); printxval(cap_version, h->version, "_LINUX_CAPABILITY_VERSION_???"); - tprintf(", pid=%d}", h->pid); + tprints(", pid="); + printpid(tcp, h->pid, PT_TGID); + tprints("}"); } static void diff --git a/clone.c b/clone.c index 487c5c23..45f24065 100644 --- a/clone.c +++ b/clone.c @@ -114,14 +114,14 @@ SYS_FUNC(clone) */ if ((flags & (CLONE_PARENT_SETTID|CLONE_PIDFD|CLONE_CHILD_SETTID |CLONE_CHILD_CLEARTID|CLONE_SETTLS)) == 0) - return RVAL_DECODED; + return RVAL_DECODED | RVAL_TID; } else { if (flags & (CLONE_PARENT_SETTID|CLONE_PIDFD)) { kernel_ulong_t addr = tcp->u_arg[ARG_PTID]; tprints(", parent_tid="); if (flags & CLONE_PARENT_SETTID) - printnum_int(tcp, addr, "%u"); + printnum_pid(tcp, addr, PT_TID); else printnum_fd(tcp, addr); } @@ -134,7 +134,7 @@ SYS_FUNC(clone) printaddr(tcp->u_arg[ARG_CTID]); } } - return 0; + return RVAL_TID; } @@ -229,7 +229,7 @@ SYS_FUNC(clone3) if ((arg.flags & (CLONE_PIDFD | CLONE_PARENT_SETTID)) || (size > fetch_size)) - return 0; + return RVAL_TID; goto out; } @@ -256,7 +256,7 @@ SYS_FUNC(clone3) if (arg.flags & CLONE_PARENT_SETTID) { tprintf("%sparent_tid=", pfx); - printnum_int(tcp, arg.parent_tid, "%d"); /* TID */ + printnum_pid(tcp, arg.parent_tid, PT_TID); pfx = ", "; } @@ -279,7 +279,7 @@ SYS_FUNC(clone3) out: tprintf(", %" PRI_klu, size); - return RVAL_DECODED; + return RVAL_DECODED | RVAL_TID; } @@ -300,5 +300,5 @@ SYS_FUNC(unshare) SYS_FUNC(fork) { - return RVAL_DECODED; + return RVAL_DECODED | RVAL_TGID; } diff --git a/defs.h b/defs.h index c16feb3c..38f123ee 100644 --- a/defs.h +++ b/defs.h @@ -1098,7 +1098,7 @@ printfd(struct tcb *tcp, int fd) /** * Print file descriptor fd owned by process with ID pid (from the PID NS - * of the tracee the descriptor tcp). This is a stub. + * of the tracee). */ extern void printfd_pid_tracee_ns(struct tcb *tcp, pid_t pid, int fd); @@ -1558,6 +1558,9 @@ DECL_PRINTNUM_ADDR(int64); extern bool printnum_fd(struct tcb *, kernel_ulong_t addr); +extern bool +printnum_pid(struct tcb *const tcp, const kernel_ulong_t addr, enum pid_type type); + static inline bool printnum_slong(struct tcb *tcp, kernel_ulong_t addr) { diff --git a/fcntl.c b/fcntl.c index 345634c5..f4e69ea1 100644 --- a/fcntl.c +++ b/fcntl.c @@ -28,7 +28,7 @@ print_struct_flock64(struct tcb *const tcp, const struct_kernel_flock64 *fl, con PRINT_FIELD_D(", ", *fl, l_start); PRINT_FIELD_D(", ", *fl, l_len); if (getlk) - PRINT_FIELD_D(", ", *fl, l_pid); + PRINT_FIELD_TGID(", ", *fl, l_pid, tcp); tprints("}"); } @@ -59,7 +59,22 @@ print_f_owner_ex(struct tcb *const tcp, const kernel_ulong_t addr) return; PRINT_FIELD_XVAL("{", owner, type, f_owner_types, "F_OWNER_???"); - PRINT_FIELD_D(", ", owner, pid); + + enum pid_type pid_type = PT_NONE; + switch (owner.type) + { + case F_OWNER_TID: + pid_type = PT_TID; + break; + case F_OWNER_PID: + pid_type = PT_TGID; + break; + case F_OWNER_PGRP: + pid_type = PT_PGID; + break; + } + tprints(", pid="); + printpid(tcp, owner.pid, pid_type); tprints("}"); } @@ -74,6 +89,9 @@ print_fcntl(struct tcb *tcp) printflags(fdflags, tcp->u_arg[2], "FD_???"); break; case F_SETOWN: + tprints(", "); + printpid_tgid_pgid(tcp, tcp->u_arg[2]); + break; case F_SETPIPE_SZ: tprintf(", %" PRI_kld, tcp->u_arg[2]); break; @@ -116,6 +134,8 @@ print_fcntl(struct tcb *tcp) printsignal(tcp->u_arg[2]); break; case F_GETOWN: + return RVAL_DECODED | + ((int) tcp->u_rval < 0 ? RVAL_PGID : RVAL_TGID); case F_GETPIPE_SZ: break; case F_GETFD: diff --git a/get_robust_list.c b/get_robust_list.c index b5aebaff..4b771bac 100644 --- a/get_robust_list.c +++ b/get_robust_list.c @@ -10,7 +10,8 @@ SYS_FUNC(get_robust_list) { if (entering(tcp)) { - tprintf("%d, ", (int) tcp->u_arg[0]); + printpid(tcp, (int) tcp->u_arg[0], PT_TID); + tprints(", "); } else { printnum_ptr(tcp, tcp->u_arg[1]); tprints(", "); diff --git a/getpid.c b/getpid.c new file mode 100644 index 00000000..5e9a1a29 --- /dev/null +++ b/getpid.c @@ -0,0 +1,46 @@ +/* + * Copyright (c) 2020 ?kos Uzonyi + * All rights reserved. + * + * SPDX-License-Identifier: LGPL-2.1-or-later + */ + +#include "defs.h" + +SYS_FUNC(getpid) +{ + return RVAL_DECODED | RVAL_TGID; +} + +SYS_FUNC(gettid) +{ + return RVAL_DECODED | RVAL_TID; +} + +SYS_FUNC(getpgrp) +{ + return RVAL_DECODED | RVAL_PGID; +} + +SYS_FUNC(getpgid) +{ + printpid(tcp, tcp->u_arg[0], PT_TGID); + + return RVAL_DECODED | RVAL_PGID; +} + +SYS_FUNC(getsid) +{ + printpid(tcp, tcp->u_arg[0], PT_TGID); + + return RVAL_DECODED | RVAL_SID; +} + +SYS_FUNC(setpgid) +{ + printpid(tcp, tcp->u_arg[0], PT_TGID); + tprints(", "); + printpid(tcp, tcp->u_arg[1], PT_PGID); + + return RVAL_DECODED; +} diff --git a/ioprio.c b/ioprio.c index 873c8ce5..52144884 100644 --- a/ioprio.c +++ b/ioprio.c @@ -49,13 +49,30 @@ print_ioprio(unsigned int ioprio) ? tprints_comment : tprints)(str); } +static void +ioprio_print_who(struct tcb *tcp, int which, int who) +{ + switch (which) + { + case IOPRIO_WHO_PROCESS: + printpid(tcp, who, PT_TGID); + break; + case IOPRIO_WHO_PGRP: + printpid(tcp, who, PT_PGID); + break; + default: + tprintf("%d", who); + break; + } +} + SYS_FUNC(ioprio_get) { if (entering(tcp)) { /* int which */ printxval(ioprio_who, tcp->u_arg[0], "IOPRIO_WHO_???"); - /* int who */ - tprintf(", %d", (int) tcp->u_arg[1]); + tprints(", "); + ioprio_print_who(tcp, (int) tcp->u_arg[0], (int) tcp->u_arg[1]); return 0; } else { if (syserror(tcp)) @@ -72,8 +89,9 @@ SYS_FUNC(ioprio_set) { /* int which */ printxval(ioprio_who, tcp->u_arg[0], "IOPRIO_WHO_???"); - /* int who */ - tprintf(", %d, ", (int) tcp->u_arg[1]); + tprints(", "); + ioprio_print_who(tcp, (int) tcp->u_arg[0], (int) tcp->u_arg[1]); + tprints(", "); /* int ioprio */ if (xlat_verbose(xlat_verbosity) != XLAT_STYLE_ABBREV) tprintf("%d", (int) tcp->u_arg[2]); diff --git a/ipc_shmctl.c b/ipc_shmctl.c index 8c9e1e7a..71b41651 100644 --- a/ipc_shmctl.c +++ b/ipc_shmctl.c @@ -12,6 +12,7 @@ */ #include "defs.h" +#include "print_fields.h" #include DEF_MPERS_TYPE(shmid_ds_t) @@ -53,8 +54,8 @@ print_shmid_ds(struct tcb *const tcp, const kernel_ulong_t addr, int cmd) PRINT_FIELD_UID(", ", shmid_ds.shm_perm, cgid); tprints("}"); tprintf(", shm_segsz=%u", (unsigned) shmid_ds.shm_segsz); - PRINT_FIELD_D(", ", shmid_ds, shm_cpid); - PRINT_FIELD_D(", ", shmid_ds, shm_lpid); + PRINT_FIELD_TGID(", ", shmid_ds, shm_cpid, tcp); + PRINT_FIELD_TGID(", ", shmid_ds, shm_lpid, tcp); tprintf(", shm_nattch=%u", (unsigned) shmid_ds.shm_nattch); tprintf(", shm_atime=%u", (unsigned) shmid_ds.shm_atime); tprintf(", shm_dtime=%u", (unsigned) shmid_ds.shm_dtime); diff --git a/kcmp.c b/kcmp.c index 62115555..a5e1cdce 100644 --- a/kcmp.c +++ b/kcmp.c @@ -30,7 +30,10 @@ SYS_FUNC(kcmp) kernel_ulong_t idx1 = tcp->u_arg[3]; kernel_ulong_t idx2 = tcp->u_arg[4]; - tprintf("%d, %d, ", pid1, pid2); + printpid(tcp, pid1, PT_TGID); + tprints(", "); + printpid(tcp, pid2, PT_TGID); + tprints(", "); printxval(kcmp_types, type, "KCMP_???"); switch (type) { diff --git a/linux/dummy.h b/linux/dummy.h index 2f859a60..ca0d2f0c 100644 --- a/linux/dummy.h +++ b/linux/dummy.h @@ -53,6 +53,7 @@ # define sys_getgid sys_getuid # define sys_getgid16 sys_getuid16 # define sys_getpeername sys_getsockname +# define sys_getppid sys_getpid # define sys_getresgid sys_getresuid # define sys_getresgid16 sys_getresuid16 # define sys_lstat sys_stat @@ -87,10 +88,6 @@ # define sys_vfork sys_fork /* printargs does the right thing */ -# define sys_getpgrp printargs -# define sys_getpid printargs -# define sys_getppid printargs -# define sys_gettid printargs # define sys_idle printargs # define sys_munlockall printargs # define sys_pause printargs @@ -108,10 +105,7 @@ /* printargs_d does the right thing */ # define sys_exit printargs_d -# define sys_getpgid printargs_d -# define sys_getsid printargs_d # define sys_nice printargs_d -# define sys_setpgid printargs_d # define sys_setpgrp printargs_d # define sys_timer_delete printargs_d # define sys_timer_getoverrun printargs_d diff --git a/msghdr.c b/msghdr.c index ef6dc24b..170b8e51 100644 --- a/msghdr.c +++ b/msghdr.c @@ -69,7 +69,7 @@ print_scm_creds(struct tcb *tcp, const void *cmsg_data, { const struct ucred *uc = cmsg_data; - PRINT_FIELD_D("{", *uc, pid); + PRINT_FIELD_TGID("{", *uc, pid, tcp); PRINT_FIELD_UID(", ", *uc, uid); PRINT_FIELD_UID(", ", *uc, gid); tprints("}"); diff --git a/net.c b/net.c index 9ea34b22..6e899253 100644 --- a/net.c +++ b/net.c @@ -601,7 +601,7 @@ print_get_ucred(struct tcb *const tcp, const kernel_ulong_t addr, if (umoven_or_printaddr(tcp, addr, len, &uc)) return; - PRINT_FIELD_LEN("{", uc, pid, len, PRINT_FIELD_D); + PRINT_FIELD_LEN("{", uc, pid, len, PRINT_FIELD_TGID, tcp); PRINT_FIELD_LEN(", ", uc, uid, len, PRINT_FIELD_UID); PRINT_FIELD_LEN(", ", uc, gid, len, PRINT_FIELD_UID); tprints("}"); diff --git a/netlink.c b/netlink.c index 88d864a9..cb29033a 100644 --- a/netlink.c +++ b/netlink.c @@ -446,8 +446,9 @@ print_nlmsghdr(struct tcb *tcp, decode_nlmsg_flags(nlmsghdr->nlmsg_flags, nlmsghdr->nlmsg_type, family); - tprintf(", seq=%u, pid=%d}", nlmsghdr->nlmsg_seq, - nlmsghdr->nlmsg_pid); + tprintf(", seq=%u, pid=", nlmsghdr->nlmsg_seq); + printpid(tcp, nlmsghdr->nlmsg_pid, PT_TGID); + tprints("}"); } static bool diff --git a/numa.c b/numa.c index cc7a7cc6..37b95397 100644 --- a/numa.c +++ b/numa.c @@ -44,7 +44,8 @@ print_nodemask(struct tcb *const tcp, const kernel_ulong_t addr, SYS_FUNC(migrate_pages) { - tprintf("%d, %" PRI_klu ", ", (int) tcp->u_arg[0], tcp->u_arg[1]); + printpid(tcp, (int) tcp->u_arg[0], PT_TGID); + tprintf(", %" PRI_klu ", ", tcp->u_arg[1]); print_nodemask(tcp, tcp->u_arg[2], tcp->u_arg[1]); tprints(", "); print_nodemask(tcp, tcp->u_arg[3], tcp->u_arg[1]); @@ -170,7 +171,8 @@ SYS_FUNC(move_pages) kernel_ulong_t buf; if (entering(tcp)) { - tprintf("%d, %" PRI_klu ", ", (int) tcp->u_arg[0], npages); + printpid(tcp, (int) tcp->u_arg[0], PT_TGID); + tprintf(", %" PRI_klu ", ", npages); print_array(tcp, tcp->u_arg[2], npages, &buf, current_wordsize, tfetch_mem, print_addr, 0); tprints(", "); diff --git a/pidfd_open.c b/pidfd_open.c index bbc7f617..10b5003d 100644 --- a/pidfd_open.c +++ b/pidfd_open.c @@ -10,7 +10,7 @@ SYS_FUNC(pidfd_open) { /* pid_t pid */ - tprintf("%d", (int) tcp->u_arg[0]); + printpid(tcp, (int) tcp->u_arg[0], PT_TGID); /* unsigned int flags */ tprintf(", %#x", (unsigned int) tcp->u_arg[1]); diff --git a/print_fields.h b/print_fields.h index f9714115..33d4a458 100644 --- a/print_fields.h +++ b/print_fields.h @@ -263,6 +263,30 @@ printfd((tcp_), (where_).field_); \ } while (0) +# define PRINT_FIELD_TID(prefix_, where_, field_, tcp_) \ + do { \ + STRACE_PRINTF("%s%s=", (prefix_), #field_); \ + printpid((tcp_), (where_).field_, PT_TID); \ + } while (0) + +# define PRINT_FIELD_TGID(prefix_, where_, field_, tcp_) \ + do { \ + STRACE_PRINTF("%s%s=", (prefix_), #field_); \ + printpid((tcp_), (where_).field_, PT_TGID); \ + } while (0) + +# define PRINT_FIELD_PGID(prefix_, where_, field_, tcp_) \ + do { \ + STRACE_PRINTF("%s%s=", (prefix_), #field_); \ + printpid((tcp_), (where_).field_, PT_PGID); \ + } while (0) + +# define PRINT_FIELD_SID(prefix_, where_, field_, tcp_) \ + do { \ + STRACE_PRINTF("%s%s=", (prefix_), #field_); \ + printpid((tcp_), (where_).field_, PT_SID); \ + } while (0) + # define PRINT_FIELD_STRN(prefix_, where_, field_, len_, tcp_) \ do { \ STRACE_PRINTF("%s%s=", (prefix_), #field_); \ diff --git a/printsiginfo.c b/printsiginfo.c index 8ed1e7ba..cb4cde4a 100644 --- a/printsiginfo.c +++ b/printsiginfo.c @@ -58,7 +58,7 @@ static void printsigsource(struct tcb *tcp, const siginfo_t *sip) { - PRINT_FIELD_D(", ", *sip, si_pid); + PRINT_FIELD_TGID(", ", *sip, si_pid, tcp); PRINT_FIELD_UID(", ", *sip, si_uid); } diff --git a/process.c b/process.c index a98c304e..d6ff255d 100644 --- a/process.c +++ b/process.c @@ -92,7 +92,8 @@ SYS_FUNC(ptrace) } /* pid */ - tprintf(", %d", pid); + tprints(", "); + printpid(tcp, pid, PT_TGID); /* addr */ switch (request) { diff --git a/process_vm.c b/process_vm.c index abee1e68..50acb3fd 100644 --- a/process_vm.c +++ b/process_vm.c @@ -13,7 +13,8 @@ SYS_FUNC(process_vm_readv) { if (entering(tcp)) { /* arg 1: pid */ - tprintf("%d, ", (int) tcp->u_arg[0]); + printpid(tcp, (int) tcp->u_arg[0], PT_TGID); + tprints(", "); } else { kernel_ulong_t local_iovcnt = tcp->u_arg[2]; kernel_ulong_t remote_iovcnt = tcp->u_arg[4]; @@ -42,7 +43,8 @@ SYS_FUNC(process_vm_writev) kernel_ulong_t flags = tcp->u_arg[5]; /* arg 1: pid */ - tprintf("%d, ", (int) tcp->u_arg[0]); + printpid(tcp, (int) tcp->u_arg[0], PT_TGID); + tprints(", "); /* arg 2: local iov */ tprint_iov(tcp, local_iovcnt, tcp->u_arg[1], IOV_DECODE_STR); /* arg 3: local iovcnt */ diff --git a/resource.c b/resource.c index 53192ee9..bd21b748 100644 --- a/resource.c +++ b/resource.c @@ -142,7 +142,8 @@ SYS_FUNC(setrlimit) SYS_FUNC(prlimit64) { if (entering(tcp)) { - tprintf("%d, ", (int) tcp->u_arg[0]); + printpid(tcp, (int) tcp->u_arg[0], PT_TGID); + tprints(", "); printxval(resources, tcp->u_arg[1], "RLIMIT_???"); tprints(", "); print_rlimit64(tcp, tcp->u_arg[2]); @@ -179,10 +180,28 @@ SYS_FUNC(osf_getrusage) #include "xlat/priorities.h" +static void +priority_print_who(struct tcb *tcp, int which, int who) +{ + switch (which) + { + case PRIO_PROCESS: + printpid(tcp, who, PT_TGID); + break; + case PRIO_PGRP: + printpid(tcp, who, PT_PGID); + break; + default: + tprintf("%d", who); + break; + } +} + SYS_FUNC(getpriority) { printxval(priorities, tcp->u_arg[0], "PRIO_???"); - tprintf(", %d", (int) tcp->u_arg[1]); + tprints(", "); + priority_print_who(tcp, tcp->u_arg[0], tcp->u_arg[1]); return RVAL_DECODED; } @@ -190,7 +209,9 @@ SYS_FUNC(getpriority) SYS_FUNC(setpriority) { printxval(priorities, tcp->u_arg[0], "PRIO_???"); - tprintf(", %d, %d", (int) tcp->u_arg[1], (int) tcp->u_arg[2]); + tprints(", "); + priority_print_who(tcp, tcp->u_arg[0], tcp->u_arg[1]); + tprintf(", %d", (int) tcp->u_arg[2]); return RVAL_DECODED; } diff --git a/sched.c b/sched.c index 788ef39b..7ae5abe2 100644 --- a/sched.c +++ b/sched.c @@ -21,7 +21,7 @@ SYS_FUNC(sched_getscheduler) { if (entering(tcp)) { - tprintf("%d", (int) tcp->u_arg[0]); + printpid(tcp, (int) tcp->u_arg[0], PT_TGID); } else if (!syserror(tcp)) { tcp->auxstr = xlookup(schedulers, (kernel_ulong_t) tcp->u_rval); return RVAL_STR; @@ -31,7 +31,8 @@ SYS_FUNC(sched_getscheduler) SYS_FUNC(sched_setscheduler) { - tprintf("%d, ", (int) tcp->u_arg[0]); + printpid(tcp, (int) tcp->u_arg[0], PT_TGID); + tprints(", "); printxval(schedulers, tcp->u_arg[1], "SCHED_???"); tprints(", "); printnum_int(tcp, tcp->u_arg[2], "%d"); @@ -41,16 +42,19 @@ SYS_FUNC(sched_setscheduler) SYS_FUNC(sched_getparam) { - if (entering(tcp)) - tprintf("%d, ", (int) tcp->u_arg[0]); - else + if (entering(tcp)) { + printpid(tcp, (int) tcp->u_arg[0], PT_TGID); + tprints(", "); + } else { printnum_int(tcp, tcp->u_arg[1], "%d"); + } return 0; } SYS_FUNC(sched_setparam) { - tprintf("%d, ", (int) tcp->u_arg[0]); + printpid(tcp, (int) tcp->u_arg[0], PT_TGID); + tprints(", "); printnum_int(tcp, tcp->u_arg[1], "%d"); return RVAL_DECODED; @@ -68,7 +72,8 @@ do_sched_rr_get_interval(struct tcb *const tcp, const print_obj_by_addr_fn print_ts) { if (entering(tcp)) { - tprintf("%d, ", (int) tcp->u_arg[0]); + printpid(tcp, (int) tcp->u_arg[0], PT_TGID); + tprints(", "); } else { if (syserror(tcp)) printaddr(tcp->u_arg[1]); @@ -160,7 +165,8 @@ end: SYS_FUNC(sched_setattr) { if (entering(tcp)) { - tprintf("%d, ", (int) tcp->u_arg[0]); + printpid(tcp, (int) tcp->u_arg[0], PT_TGID); + tprints(", "); print_sched_attr(tcp, tcp->u_arg[1], 0); } else { struct sched_attr attr; @@ -179,7 +185,8 @@ SYS_FUNC(sched_setattr) SYS_FUNC(sched_getattr) { if (entering(tcp)) { - tprintf("%d, ", (int) tcp->u_arg[0]); + printpid(tcp, (int) tcp->u_arg[0], PT_TGID); + tprints(", "); } else { const unsigned int size = tcp->u_arg[2]; diff --git a/signal.c b/signal.c index 5f1acac6..50dd898c 100644 --- a/signal.c +++ b/signal.c @@ -439,7 +439,8 @@ SYS_FUNC(sigprocmask) SYS_FUNC(kill) { /* pid */ - tprintf("%d, ", (int) tcp->u_arg[0]); + printpid_tgid_pgid(tcp, tcp->u_arg[0]); + tprints(", "); /* signal */ printsignal(tcp->u_arg[1]); @@ -448,7 +449,7 @@ SYS_FUNC(kill) SYS_FUNC(tkill) { - tprintf("%d", (int) tcp->u_arg[0]); + printpid(tcp, (int) tcp->u_arg[0], PT_TID); tprints(", "); printsignal(tcp->u_arg[1]); @@ -457,8 +458,12 @@ SYS_FUNC(tkill) SYS_FUNC(tgkill) { - /* tgid, tid */ - tprintf("%d, %d, ", (int) tcp->u_arg[0], (int) tcp->u_arg[1]); + /* tgid */ + printpid(tcp, (int) tcp->u_arg[0], PT_TGID); + tprints(", "); + /* tid */ + printpid(tcp, (int) tcp->u_arg[1], PT_TID); + tprints(", "); /* signal */ printsignal(tcp->u_arg[2]); @@ -624,7 +629,8 @@ print_sigqueueinfo(struct tcb *const tcp, const int sig, SYS_FUNC(rt_sigqueueinfo) { - tprintf("%d, ", (int) tcp->u_arg[0]); + printpid(tcp, (int) tcp->u_arg[0], PT_TGID); + tprints(", "); print_sigqueueinfo(tcp, tcp->u_arg[1], tcp->u_arg[2]); return RVAL_DECODED; @@ -632,7 +638,10 @@ SYS_FUNC(rt_sigqueueinfo) SYS_FUNC(rt_tgsigqueueinfo) { - tprintf("%d, %d, ", (int) tcp->u_arg[0], (int) tcp->u_arg[1]); + printpid(tcp, (int) tcp->u_arg[0], PT_TGID); + tprints(", "); + printpid(tcp, (int) tcp->u_arg[1], PT_TID); + tprints(", "); print_sigqueueinfo(tcp, tcp->u_arg[2], tcp->u_arg[3]); return RVAL_DECODED; diff --git a/sockaddr.c b/sockaddr.c index b0046331..fb8887c2 100644 --- a/sockaddr.c +++ b/sockaddr.c @@ -416,7 +416,7 @@ print_sockaddr_data_nl(struct tcb *tcp, const void *const buf, const int addrlen { const struct sockaddr_nl *const sa_nl = buf; - PRINT_FIELD_D("", *sa_nl, nl_pid); + PRINT_FIELD_TGID("", *sa_nl, nl_pid, tcp); PRINT_FIELD_0X(", ", *sa_nl, nl_groups); } diff --git a/tests/kcmp.c b/tests/kcmp.c index a46da0ed..dc5ba9a4 100644 --- a/tests/kcmp.c +++ b/tests/kcmp.c @@ -64,7 +64,26 @@ static const char zero_path[] = "/dev/zero"; static void printpidfd(const char *prefix, pid_t pid, unsigned fd) { - printf("%s%d", prefix, fd); + const char *path = NULL; + +# if VERBOSE_FD + if (pid == getpid()) { + switch (fd) + { + case NULL_FD: + path = null_path; + break; + case ZERO_FD: + path = zero_path; + break; + } + } +# endif + + if (path) + printf("%s%d<%s>", prefix, fd, path); + else + printf("%s%d", prefix, fd); } /* @@ -179,7 +198,7 @@ main(void) /* KCMP_FILE is the only type which has additional args */ do_kcmp(3141592653U, 2718281828U, ARG_STR(KCMP_FILE), bogus_idx1, bogus_idx2); - do_kcmp(-1, -1, ARG_STR(KCMP_FILE), NULL_FD, ZERO_FD); + do_kcmp(getpid(), getpid(), ARG_STR(KCMP_FILE), NULL_FD, ZERO_FD); /* Types without additional args */ do_kcmp(-1, -1, ARG_STR(KCMP_VM), bogus_idx1, bogus_idx2); @@ -198,7 +217,7 @@ main(void) for (i = 0; i < ARRAY_SIZE(slot_data); i++) { memcpy(slot, slot_data + i, sizeof(*slot)); - do_kcmp(getpid(), getppid(), ARG_STR(KCMP_EPOLL_TFD), NULL_FD, + do_kcmp(getpid(), -1, ARG_STR(KCMP_EPOLL_TFD), NULL_FD, (uintptr_t) slot, 1); } diff --git a/util.c b/util.c index 286c6903..094e5818 100644 --- a/util.c +++ b/util.c @@ -392,6 +392,18 @@ printnum_fd(struct tcb *const tcp, const kernel_ulong_t addr) return true; } +bool +printnum_pid(struct tcb *const tcp, const kernel_ulong_t addr, enum pid_type type) +{ + int pid; + if (umove_or_printaddr(tcp, addr, &pid)) + return false; + tprints("["); + printpid(tcp, pid, type); + tprints("]"); + return true; +} + /** * Prints time to a (static internal) buffer and returns pointer to it. * Returns NULL if the provided time specification is not correct. @@ -641,12 +653,8 @@ printed: void printfd_pid_tracee_ns(struct tcb *tcp, pid_t pid, int fd) { - /* - * TODO: We want to have the same formatting as printfd here, - * but we should figure out first which process in strace's - * PID NS is referred to by pid in tracee's PID NS. - */ - tprintf("%d", fd); + int strace_pid = translate_pid(tcp, pid, PT_TGID, NULL); + printfd_pid(tcp, strace_pid, fd); } /* diff --git a/wait.c b/wait.c index 2b9f9807..997a711a 100644 --- a/wait.c +++ b/wait.c @@ -80,14 +80,8 @@ printwaitn(struct tcb *const tcp, void (*const print_rusage)(struct tcb *, kernel_ulong_t)) { if (entering(tcp)) { - /* On Linux, kernel-side pid_t is typedef'ed to int - * on all arches. Also, glibc-2.8 truncates wait3 and wait4 - * pid argument to int on 64bit arches, producing, - * for example, wait4(4294967295, ...) instead of -1 - * in strace. We have to use int here, not long. - */ - int pid = tcp->u_arg[0]; - tprintf("%d, ", pid); + printpid_tgid_pgid(tcp, tcp->u_arg[0]); + tprintf(", "); } else { int status; @@ -108,7 +102,7 @@ printwaitn(struct tcb *const tcp, printaddr(tcp->u_arg[3]); } } - return 0; + return RVAL_TGID; } SYS_FUNC(waitpid) @@ -134,10 +128,28 @@ SYS_FUNC(osf_wait4) SYS_FUNC(waitid) { + unsigned int idtype = (unsigned int) tcp->u_arg[0]; + int id = (int) tcp->u_arg[1]; + if (entering(tcp)) { - printxval(waitid_types, tcp->u_arg[0], "P_???"); - int pid = tcp->u_arg[1]; - tprintf(", %d, ", pid); + printxval(waitid_types, idtype, "P_???"); + tprints(", "); + switch (idtype) + { + case P_PID: + printpid(tcp, id, PT_TGID); + break; + case P_PIDFD: + printfd(tcp, id); + break; + case P_PGID: + printpid(tcp, id, PT_PGID); + break; + default: + tprintf("%d", id); + break; + } + tprints(", "); } else { /* siginfo */ printsiginfo_at(tcp, tcp->u_arg[2]); -- 2.27.0 From ldv at altlinux.org Mon Aug 3 21:43:27 2020 From: ldv at altlinux.org (Dmitry V. Levin) Date: Tue, 4 Aug 2020 00:43:27 +0300 Subject: [PATCH v5 1/5] PID namespace translation support In-Reply-To: <20200803191916.94724-2-uzonyi.akos@gmail.com> References: <20200803191916.94724-1-uzonyi.akos@gmail.com> <20200803191916.94724-2-uzonyi.akos@gmail.com> Message-ID: <20200803214326.GB7849@altlinux.org> On Mon, Aug 03, 2020 at 09:19:12PM +0200, ?kos Uzonyi wrote: [...] > +void > +pidns_init(void) > +{ > + if (proc_data_cache) > + return; > + > + pid_max = INT_MAX; > + if (read_int_from_file("/proc/sys/kernel/pid_max", &pid_max) < 0) > + debug_func_perror_msg("reading /proc/sys/kernel/pid_max"); > + pid_max_size = ilog2_32(pid_max - 1) + 1; > + pid_max_size_lg = ilog2_32(pid_max_size - 1) + 1; > + > + for (int i = 0; i < PT_COUNT; i++) > + ns_pid_to_proc_pid[i] = trie_create(64, ptr_sz_lg, 10, 10, 0); Has the numeric constant 64 been chosen because sizeof(struct tcb.pid_ns) * 8 == 64? > + > + proc_data_cache = trie_create(pid_max_size, ptr_sz_lg, 10, 10, 0); > +} > + > +static void > +put_proc_pid(uint64_t ns, int ns_pid, enum pid_type type, int proc_pid) > +{ > + struct trie *b = (struct trie *) (uintptr_t) trie_get(ns_pid_to_proc_pid[type], ns); > + if (!b) { > + b = trie_create(pid_max_size, pid_max_size_lg, 10, 10, 0); > + trie_set(ns_pid_to_proc_pid[type], ns, (uint64_t) (uintptr_t) b); > + } > + trie_set(b, ns_pid, proc_pid); > +} In all three cases trie_create is invoked with node_key_bits and data_block_key_bits arguments equal to 10. Could you shed some light on the choice of this numeric constant, please? -- ldv From jojokoo1111 at protonmail.com Tue Aug 4 05:13:17 2020 From: jojokoo1111 at protonmail.com (jojokoo1111) Date: Tue, 04 Aug 2020 05:13:17 +0000 Subject: How does strace distinguishes between syscall-exit-stop or syscall-enter-stop in ARM LINUX ? Message-ID: I didn't find the piece of code in strace that distinguishes when using PTRACE_SYSCALL if the state is syscall-exit-stop or syscall-enter-stop in ARM LINUX . If it is new kenel we can use PTRACE_GET_SYSCALL_INFO , but how does strace find that information out if it is older kernel? -------------- next part -------------- An HTML attachment was scrubbed... URL: From jojokoo1111 at protonmail.com Tue Aug 4 05:11:03 2020 From: jojokoo1111 at protonmail.com (jojokoo1111) Date: Tue, 04 Aug 2020 05:11:03 +0000 Subject: test Message-ID: sss -------------- next part -------------- An HTML attachment was scrubbed... URL: From uzonyi.akos at gmail.com Tue Aug 4 17:52:46 2020 From: uzonyi.akos at gmail.com (=?UTF-8?B?w4Frb3MgVXpvbnlp?=) Date: Tue, 4 Aug 2020 19:52:46 +0200 Subject: [PATCH v5 1/5] PID namespace translation support In-Reply-To: <20200803214326.GB7849@altlinux.org> References: <20200803191916.94724-1-uzonyi.akos@gmail.com> <20200803191916.94724-2-uzonyi.akos@gmail.com> <20200803214326.GB7849@altlinux.org> Message-ID: On Mon, 3 Aug 2020 at 23:43, Dmitry V. Levin wrote: > On Mon, Aug 03, 2020 at 09:19:12PM +0200, ?kos Uzonyi wrote: > [...] > > +void > > +pidns_init(void) > > +{ > > + if (proc_data_cache) > > + return; > > + > > + pid_max = INT_MAX; > > + if (read_int_from_file("/proc/sys/kernel/pid_max", &pid_max) < 0) > > + debug_func_perror_msg("reading /proc/sys/kernel/pid_max"); > > + pid_max_size = ilog2_32(pid_max - 1) + 1; > > + pid_max_size_lg = ilog2_32(pid_max_size - 1) + 1; > > + > > + for (int i = 0; i < PT_COUNT; i++) > > + ns_pid_to_proc_pid[i] = trie_create(64, ptr_sz_lg, 10, 10, 0); > > Has the numeric constant 64 been chosen because > sizeof(struct tcb.pid_ns) * 8 == 64? Yes. For making it clear in the code, which one would be preferred? - Using a named constant - Using the expression you wrote above - Adding a comment about it > > + > > + proc_data_cache = trie_create(pid_max_size, ptr_sz_lg, 10, 10, 0); > > +} > > + > > +static void > > +put_proc_pid(uint64_t ns, int ns_pid, enum pid_type type, int proc_pid) > > +{ > > + struct trie *b = (struct trie *) (uintptr_t) trie_get(ns_pid_to_proc_pid[type], ns); > > + if (!b) { > > + b = trie_create(pid_max_size, pid_max_size_lg, 10, 10, 0); > > + trie_set(ns_pid_to_proc_pid[type], ns, (uint64_t) (uintptr_t) b); > > + } > > + trie_set(b, ns_pid, proc_pid); > > +} > > In all three cases trie_create is invoked with node_key_bits > and data_block_key_bits arguments equal to 10. > > Could you shed some light on the choice of this numeric constant, please? Unfortunately, I have no strong reason why 10 was chosen. It's just a number that seemed to be ok. But thinking a bit more about it, I realized maybe a smaller number would be better. 10 means node size is 8KB (with 8 byte pointers), which seems to be a lot of memory usage, as PIDs are sparse. Maybe for example 4 could be a better choice, so nodes are small, and lookup times are still not that bad. But I'm still not sure what explanation could I write to the chosen constant. From ldv at altlinux.org Tue Aug 4 22:31:31 2020 From: ldv at altlinux.org (Dmitry V. Levin) Date: Wed, 5 Aug 2020 01:31:31 +0300 Subject: [PATCH v5 1/5] PID namespace translation support In-Reply-To: References: <20200803191916.94724-1-uzonyi.akos@gmail.com> <20200803191916.94724-2-uzonyi.akos@gmail.com> <20200803214326.GB7849@altlinux.org> Message-ID: <20200804223131.GA25142@altlinux.org> On Tue, Aug 04, 2020 at 07:52:46PM +0200, ?kos Uzonyi wrote: > On Mon, 3 Aug 2020 at 23:43, Dmitry V. Levin wrote: > > On Mon, Aug 03, 2020 at 09:19:12PM +0200, ?kos Uzonyi wrote: > > [...] > > > +void > > > +pidns_init(void) > > > +{ > > > + if (proc_data_cache) > > > + return; > > > + > > > + pid_max = INT_MAX; > > > + if (read_int_from_file("/proc/sys/kernel/pid_max", &pid_max) < 0) > > > + debug_func_perror_msg("reading /proc/sys/kernel/pid_max"); > > > + pid_max_size = ilog2_32(pid_max - 1) + 1; > > > + pid_max_size_lg = ilog2_32(pid_max_size - 1) + 1; > > > + > > > + for (int i = 0; i < PT_COUNT; i++) > > > + ns_pid_to_proc_pid[i] = trie_create(64, ptr_sz_lg, 10, 10, 0); > > > > Has the numeric constant 64 been chosen because > > sizeof(struct tcb.pid_ns) * 8 == 64? > > Yes. > For making it clear in the code, which one would be preferred? > - Using a named constant It's always nice to have a good name for a constant. > - Using the expression you wrote above Strictly speaking, that was not a valid C expression, but sizeof_field(struct tcb, pid_ns) * 8 is a valid one. > - Adding a comment about it > > > > + > > > + proc_data_cache = trie_create(pid_max_size, ptr_sz_lg, 10, 10, 0); > > > +} > > > + > > > +static void > > > +put_proc_pid(uint64_t ns, int ns_pid, enum pid_type type, int proc_pid) > > > +{ > > > + struct trie *b = (struct trie *) (uintptr_t) trie_get(ns_pid_to_proc_pid[type], ns); > > > + if (!b) { > > > + b = trie_create(pid_max_size, pid_max_size_lg, 10, 10, 0); > > > + trie_set(ns_pid_to_proc_pid[type], ns, (uint64_t) (uintptr_t) b); > > > + } > > > + trie_set(b, ns_pid, proc_pid); > > > +} > > > > In all three cases trie_create is invoked with node_key_bits > > and data_block_key_bits arguments equal to 10. > > > > Could you shed some light on the choice of this numeric constant, please? > > Unfortunately, I have no strong reason why 10 was chosen. It's just a > number that seemed to be ok. But thinking a bit more about it, I > realized maybe a smaller number would be better. 10 means node size is > 8KB (with 8 byte pointers), which seems to be a lot of memory usage, Should the number depend on the size of pointer then? Or should it depend on pid_max? > as PIDs are sparse. What do you mean by that? > Maybe for example 4 could be a better choice, so > nodes are small, and lookup times are still not that bad. But I'm > still not sure what explanation could I write to the chosen constant. Even if it just feels right, try to explain in the comment why it feels right. -- ldv From uzonyi.akos at gmail.com Tue Aug 4 23:53:37 2020 From: uzonyi.akos at gmail.com (=?UTF-8?B?w4Frb3MgVXpvbnlp?=) Date: Wed, 5 Aug 2020 01:53:37 +0200 Subject: [PATCH v5 1/5] PID namespace translation support In-Reply-To: <20200804223131.GA25142@altlinux.org> References: <20200803191916.94724-1-uzonyi.akos@gmail.com> <20200803191916.94724-2-uzonyi.akos@gmail.com> <20200803214326.GB7849@altlinux.org> <20200804223131.GA25142@altlinux.org> Message-ID: On Wed, 5 Aug 2020 at 00:31, Dmitry V. Levin wrote: > On Tue, Aug 04, 2020 at 07:52:46PM +0200, ?kos Uzonyi wrote: > > On Mon, 3 Aug 2020 at 23:43, Dmitry V. Levin wrote: > > > On Mon, Aug 03, 2020 at 09:19:12PM +0200, ?kos Uzonyi wrote: > > > [...] > > > > +void > > > > +pidns_init(void) > > > > +{ > > > > + if (proc_data_cache) > > > > + return; > > > > + > > > > + pid_max = INT_MAX; > > > > + if (read_int_from_file("/proc/sys/kernel/pid_max", &pid_max) < 0) > > > > + debug_func_perror_msg("reading /proc/sys/kernel/pid_max"); > > > > + pid_max_size = ilog2_32(pid_max - 1) + 1; > > > > + pid_max_size_lg = ilog2_32(pid_max_size - 1) + 1; > > > > + > > > > + for (int i = 0; i < PT_COUNT; i++) > > > > + ns_pid_to_proc_pid[i] = trie_create(64, ptr_sz_lg, 10, 10, 0); > > > > > > Has the numeric constant 64 been chosen because > > > sizeof(struct tcb.pid_ns) * 8 == 64? > > > > Yes. > > For making it clear in the code, which one would be preferred? > > - Using a named constant > > It's always nice to have a good name for a constant. > > > - Using the expression you wrote above > > Strictly speaking, that was not a valid C expression, but > sizeof_field(struct tcb, pid_ns) * 8 > is a valid one. As tcb.pid_ns is just one of the variables where ns ids are stored, I might prefer using sizeof(uint64_t): #define NS_ID_SIZE sizeof(uint64_t) or maybe just simply: #define NS_ID_SIZE 64 > > - Adding a comment about it > > > > > > + > > > > + proc_data_cache = trie_create(pid_max_size, ptr_sz_lg, 10, 10, 0); > > > > +} > > > > + > > > > +static void > > > > +put_proc_pid(uint64_t ns, int ns_pid, enum pid_type type, int proc_pid) > > > > +{ > > > > + struct trie *b = (struct trie *) (uintptr_t) trie_get(ns_pid_to_proc_pid[type], ns); > > > > + if (!b) { > > > > + b = trie_create(pid_max_size, pid_max_size_lg, 10, 10, 0); > > > > + trie_set(ns_pid_to_proc_pid[type], ns, (uint64_t) (uintptr_t) b); > > > > + } > > > > + trie_set(b, ns_pid, proc_pid); > > > > +} > > > > > > In all three cases trie_create is invoked with node_key_bits > > > and data_block_key_bits arguments equal to 10. > > > > > > Could you shed some light on the choice of this numeric constant, please? > > > > Unfortunately, I have no strong reason why 10 was chosen. It's just a > > number that seemed to be ok. But thinking a bit more about it, I > > realized maybe a smaller number would be better. 10 means node size is > > 8KB (with 8 byte pointers), which seems to be a lot of memory usage, > > Should the number depend on the size of pointer then? > Or should it depend on pid_max? I think it's easier to use a constant. > > as PIDs are sparse. > > What do you mean by that? I just meant that usually a few pids are distributed over a large interval, so it's a waste allocating large nodes, as usually only a few pointers will be used in them. > > Maybe for example 4 could be a better choice, so > > nodes are small, and lookup times are still not that bad. But I'm > > still not sure what explanation could I write to the chosen constant. > > Even if it just feels right, try to explain in the comment why it feels right. OK, I'll try to come up with something. From ldv at altlinux.org Wed Aug 5 00:02:58 2020 From: ldv at altlinux.org (Dmitry V. Levin) Date: Wed, 5 Aug 2020 03:02:58 +0300 Subject: [PATCH v5 1/5] PID namespace translation support In-Reply-To: References: <20200803191916.94724-1-uzonyi.akos@gmail.com> <20200803191916.94724-2-uzonyi.akos@gmail.com> <20200803214326.GB7849@altlinux.org> <20200804223131.GA25142@altlinux.org> Message-ID: <20200805000258.GA25963@altlinux.org> On Wed, Aug 05, 2020 at 01:53:37AM +0200, ?kos Uzonyi wrote: > On Wed, 5 Aug 2020 at 00:31, Dmitry V. Levin wrote: > > On Tue, Aug 04, 2020 at 07:52:46PM +0200, ?kos Uzonyi wrote: > > > On Mon, 3 Aug 2020 at 23:43, Dmitry V. Levin wrote: > > > > On Mon, Aug 03, 2020 at 09:19:12PM +0200, ?kos Uzonyi wrote: > > > > [...] > > > > > +void > > > > > +pidns_init(void) > > > > > +{ > > > > > + if (proc_data_cache) > > > > > + return; > > > > > + > > > > > + pid_max = INT_MAX; > > > > > + if (read_int_from_file("/proc/sys/kernel/pid_max", &pid_max) < 0) > > > > > + debug_func_perror_msg("reading /proc/sys/kernel/pid_max"); > > > > > + pid_max_size = ilog2_32(pid_max - 1) + 1; > > > > > + pid_max_size_lg = ilog2_32(pid_max_size - 1) + 1; > > > > > + > > > > > + for (int i = 0; i < PT_COUNT; i++) > > > > > + ns_pid_to_proc_pid[i] = trie_create(64, ptr_sz_lg, 10, 10, 0); > > > > > > > > Has the numeric constant 64 been chosen because > > > > sizeof(struct tcb.pid_ns) * 8 == 64? > > > > > > Yes. > > > For making it clear in the code, which one would be preferred? > > > - Using a named constant > > > > It's always nice to have a good name for a constant. > > > > > - Using the expression you wrote above > > > > Strictly speaking, that was not a valid C expression, but > > sizeof_field(struct tcb, pid_ns) * 8 > > is a valid one. > > As tcb.pid_ns is just one of the variables where ns ids are stored, I > might prefer using sizeof(uint64_t): > #define NS_ID_SIZE sizeof(uint64_t) > or maybe just simply: > #define NS_ID_SIZE 64 By the way, is it really 64? Yes, the type of struct tcb.pid_ns is 64-bit, but any valid pid_ns is 32-bit. -- ldv From uzonyi.akos at gmail.com Wed Aug 5 00:14:36 2020 From: uzonyi.akos at gmail.com (=?UTF-8?B?w4Frb3MgVXpvbnlp?=) Date: Wed, 5 Aug 2020 02:14:36 +0200 Subject: [PATCH v5 1/5] PID namespace translation support In-Reply-To: <20200805000258.GA25963@altlinux.org> References: <20200803191916.94724-1-uzonyi.akos@gmail.com> <20200803191916.94724-2-uzonyi.akos@gmail.com> <20200803214326.GB7849@altlinux.org> <20200804223131.GA25142@altlinux.org> <20200805000258.GA25963@altlinux.org> Message-ID: On Wed, 5 Aug 2020 at 02:02, Dmitry V. Levin wrote: > On Wed, Aug 05, 2020 at 01:53:37AM +0200, ?kos Uzonyi wrote: > > On Wed, 5 Aug 2020 at 00:31, Dmitry V. Levin wrote: > > > On Tue, Aug 04, 2020 at 07:52:46PM +0200, ?kos Uzonyi wrote: > > > > On Mon, 3 Aug 2020 at 23:43, Dmitry V. Levin wrote: > > > > > On Mon, Aug 03, 2020 at 09:19:12PM +0200, ?kos Uzonyi wrote: > > > > > [...] > > > > > > +void > > > > > > +pidns_init(void) > > > > > > +{ > > > > > > + if (proc_data_cache) > > > > > > + return; > > > > > > + > > > > > > + pid_max = INT_MAX; > > > > > > + if (read_int_from_file("/proc/sys/kernel/pid_max", &pid_max) < 0) > > > > > > + debug_func_perror_msg("reading /proc/sys/kernel/pid_max"); > > > > > > + pid_max_size = ilog2_32(pid_max - 1) + 1; > > > > > > + pid_max_size_lg = ilog2_32(pid_max_size - 1) + 1; > > > > > > + > > > > > > + for (int i = 0; i < PT_COUNT; i++) > > > > > > + ns_pid_to_proc_pid[i] = trie_create(64, ptr_sz_lg, 10, 10, 0); > > > > > > > > > > Has the numeric constant 64 been chosen because > > > > > sizeof(struct tcb.pid_ns) * 8 == 64? > > > > > > > > Yes. > > > > For making it clear in the code, which one would be preferred? > > > > - Using a named constant > > > > > > It's always nice to have a good name for a constant. > > > > > > > - Using the expression you wrote above > > > > > > Strictly speaking, that was not a valid C expression, but > > > sizeof_field(struct tcb, pid_ns) * 8 > > > is a valid one. > > > > As tcb.pid_ns is just one of the variables where ns ids are stored, I > > might prefer using sizeof(uint64_t): > > #define NS_ID_SIZE sizeof(uint64_t) > > or maybe just simply: > > #define NS_ID_SIZE 64 > > By the way, is it really 64? Yes, the type of struct tcb.pid_ns is 64-bit, > but any valid pid_ns is 32-bit. I think it was chosen to be 64 bit by Eugene, because it's not documented that it should fit into 32 bit. The documentation only says that it's derived from an inode number. Or is it guaranteed that inode numbers are maximum 32 bit? From ldv at altlinux.org Wed Aug 5 00:30:55 2020 From: ldv at altlinux.org (Dmitry V. Levin) Date: Wed, 5 Aug 2020 03:30:55 +0300 Subject: [PATCH v5 1/5] PID namespace translation support In-Reply-To: References: <20200803191916.94724-1-uzonyi.akos@gmail.com> <20200803191916.94724-2-uzonyi.akos@gmail.com> <20200803214326.GB7849@altlinux.org> <20200804223131.GA25142@altlinux.org> <20200805000258.GA25963@altlinux.org> Message-ID: <20200805003055.GA26447@altlinux.org> On Wed, Aug 05, 2020 at 02:14:36AM +0200, ?kos Uzonyi wrote: > On Wed, 5 Aug 2020 at 02:02, Dmitry V. Levin wrote: > > On Wed, Aug 05, 2020 at 01:53:37AM +0200, ?kos Uzonyi wrote: > > > On Wed, 5 Aug 2020 at 00:31, Dmitry V. Levin wrote: > > > > On Tue, Aug 04, 2020 at 07:52:46PM +0200, ?kos Uzonyi wrote: > > > > > On Mon, 3 Aug 2020 at 23:43, Dmitry V. Levin wrote: > > > > > > On Mon, Aug 03, 2020 at 09:19:12PM +0200, ?kos Uzonyi wrote: > > > > > > [...] > > > > > > > +void > > > > > > > +pidns_init(void) > > > > > > > +{ > > > > > > > + if (proc_data_cache) > > > > > > > + return; > > > > > > > + > > > > > > > + pid_max = INT_MAX; > > > > > > > + if (read_int_from_file("/proc/sys/kernel/pid_max", &pid_max) < 0) > > > > > > > + debug_func_perror_msg("reading /proc/sys/kernel/pid_max"); > > > > > > > + pid_max_size = ilog2_32(pid_max - 1) + 1; > > > > > > > + pid_max_size_lg = ilog2_32(pid_max_size - 1) + 1; > > > > > > > + > > > > > > > + for (int i = 0; i < PT_COUNT; i++) > > > > > > > + ns_pid_to_proc_pid[i] = trie_create(64, ptr_sz_lg, 10, 10, 0); > > > > > > > > > > > > Has the numeric constant 64 been chosen because > > > > > > sizeof(struct tcb.pid_ns) * 8 == 64? > > > > > > > > > > Yes. > > > > > For making it clear in the code, which one would be preferred? > > > > > - Using a named constant > > > > > > > > It's always nice to have a good name for a constant. > > > > > > > > > - Using the expression you wrote above > > > > > > > > Strictly speaking, that was not a valid C expression, but > > > > sizeof_field(struct tcb, pid_ns) * 8 > > > > is a valid one. > > > > > > As tcb.pid_ns is just one of the variables where ns ids are stored, I > > > might prefer using sizeof(uint64_t): > > > #define NS_ID_SIZE sizeof(uint64_t) > > > or maybe just simply: > > > #define NS_ID_SIZE 64 > > > > By the way, is it really 64? Yes, the type of struct tcb.pid_ns is 64-bit, > > but any valid pid_ns is 32-bit. > > I think it was chosen to be 64 bit by Eugene, because it's not > documented that it should fit into 32 bit. The documentation only says > that it's derived from an inode number. Or is it guaranteed that inode > numbers are maximum 32 bit? If I read the kernel correctly, pid_ns is assigned from struct ns_common.inum of type unsigned int. -- ldv From uzonyi.akos at gmail.com Wed Aug 5 08:45:28 2020 From: uzonyi.akos at gmail.com (=?UTF-8?B?w4Frb3MgVXpvbnlp?=) Date: Wed, 5 Aug 2020 10:45:28 +0200 Subject: [PATCH v5 1/5] PID namespace translation support In-Reply-To: <20200805003055.GA26447@altlinux.org> References: <20200803191916.94724-1-uzonyi.akos@gmail.com> <20200803191916.94724-2-uzonyi.akos@gmail.com> <20200803214326.GB7849@altlinux.org> <20200804223131.GA25142@altlinux.org> <20200805000258.GA25963@altlinux.org> <20200805003055.GA26447@altlinux.org> Message-ID: On Wed, 5 Aug 2020 at 02:30, Dmitry V. Levin wrote: > On Wed, Aug 05, 2020 at 02:14:36AM +0200, ?kos Uzonyi wrote: > > On Wed, 5 Aug 2020 at 02:02, Dmitry V. Levin wrote: > > > On Wed, Aug 05, 2020 at 01:53:37AM +0200, ?kos Uzonyi wrote: > > > > On Wed, 5 Aug 2020 at 00:31, Dmitry V. Levin wrote: > > > > > On Tue, Aug 04, 2020 at 07:52:46PM +0200, ?kos Uzonyi wrote: > > > > > > On Mon, 3 Aug 2020 at 23:43, Dmitry V. Levin wrote: > > > > > > > On Mon, Aug 03, 2020 at 09:19:12PM +0200, ?kos Uzonyi wrote: > > > > > > > [...] > > > > > > > > +void > > > > > > > > +pidns_init(void) > > > > > > > > +{ > > > > > > > > + if (proc_data_cache) > > > > > > > > + return; > > > > > > > > + > > > > > > > > + pid_max = INT_MAX; > > > > > > > > + if (read_int_from_file("/proc/sys/kernel/pid_max", &pid_max) < 0) > > > > > > > > + debug_func_perror_msg("reading /proc/sys/kernel/pid_max"); > > > > > > > > + pid_max_size = ilog2_32(pid_max - 1) + 1; > > > > > > > > + pid_max_size_lg = ilog2_32(pid_max_size - 1) + 1; > > > > > > > > + > > > > > > > > + for (int i = 0; i < PT_COUNT; i++) > > > > > > > > + ns_pid_to_proc_pid[i] = trie_create(64, ptr_sz_lg, 10, 10, 0); > > > > > > > > > > > > > > Has the numeric constant 64 been chosen because > > > > > > > sizeof(struct tcb.pid_ns) * 8 == 64? > > > > > > > > > > > > Yes. > > > > > > For making it clear in the code, which one would be preferred? > > > > > > - Using a named constant > > > > > > > > > > It's always nice to have a good name for a constant. > > > > > > > > > > > - Using the expression you wrote above > > > > > > > > > > Strictly speaking, that was not a valid C expression, but > > > > > sizeof_field(struct tcb, pid_ns) * 8 > > > > > is a valid one. > > > > > > > > As tcb.pid_ns is just one of the variables where ns ids are stored, I > > > > might prefer using sizeof(uint64_t): > > > > #define NS_ID_SIZE sizeof(uint64_t) > > > > or maybe just simply: > > > > #define NS_ID_SIZE 64 > > > > > > By the way, is it really 64? Yes, the type of struct tcb.pid_ns is 64-bit, > > > but any valid pid_ns is 32-bit. > > > > I think it was chosen to be 64 bit by Eugene, because it's not > > documented that it should fit into 32 bit. The documentation only says > > that it's derived from an inode number. Or is it guaranteed that inode > > numbers are maximum 32 bit? > > If I read the kernel correctly, pid_ns is assigned from struct ns_common.inum > of type unsigned int. Yes, I understand. However since it's not documented anywhere (AFAIK), it might change later, isn't it? But if you say it's highly unlikely to change, we can use unsigned int for ns id type. I think we should not use -1U then for indicating error in tcb.pid_ns, as it is a likely valid ns id. It's not a big problem however, as errors are unlikely, so there is an option to just leave tcb.pid_ns 0 on error. From ldv at altlinux.org Wed Aug 5 09:52:39 2020 From: ldv at altlinux.org (Dmitry V. Levin) Date: Wed, 5 Aug 2020 12:52:39 +0300 Subject: [PATCH v5 1/5] PID namespace translation support In-Reply-To: References: <20200803191916.94724-1-uzonyi.akos@gmail.com> <20200803191916.94724-2-uzonyi.akos@gmail.com> <20200803214326.GB7849@altlinux.org> <20200804223131.GA25142@altlinux.org> <20200805000258.GA25963@altlinux.org> <20200805003055.GA26447@altlinux.org> Message-ID: <20200805095239.GB27875@altlinux.org> On Wed, Aug 05, 2020 at 10:45:28AM +0200, ?kos Uzonyi wrote: > On Wed, 5 Aug 2020 at 02:30, Dmitry V. Levin wrote: > > On Wed, Aug 05, 2020 at 02:14:36AM +0200, ?kos Uzonyi wrote: > > > On Wed, 5 Aug 2020 at 02:02, Dmitry V. Levin wrote: > > > > On Wed, Aug 05, 2020 at 01:53:37AM +0200, ?kos Uzonyi wrote: > > > > > On Wed, 5 Aug 2020 at 00:31, Dmitry V. Levin wrote: > > > > > > On Tue, Aug 04, 2020 at 07:52:46PM +0200, ?kos Uzonyi wrote: > > > > > > > On Mon, 3 Aug 2020 at 23:43, Dmitry V. Levin wrote: > > > > > > > > On Mon, Aug 03, 2020 at 09:19:12PM +0200, ?kos Uzonyi wrote: > > > > > > > > [...] > > > > > > > > > +void > > > > > > > > > +pidns_init(void) > > > > > > > > > +{ > > > > > > > > > + if (proc_data_cache) > > > > > > > > > + return; > > > > > > > > > + > > > > > > > > > + pid_max = INT_MAX; > > > > > > > > > + if (read_int_from_file("/proc/sys/kernel/pid_max", &pid_max) < 0) > > > > > > > > > + debug_func_perror_msg("reading /proc/sys/kernel/pid_max"); > > > > > > > > > + pid_max_size = ilog2_32(pid_max - 1) + 1; > > > > > > > > > + pid_max_size_lg = ilog2_32(pid_max_size - 1) + 1; > > > > > > > > > + > > > > > > > > > + for (int i = 0; i < PT_COUNT; i++) > > > > > > > > > + ns_pid_to_proc_pid[i] = trie_create(64, ptr_sz_lg, 10, 10, 0); > > > > > > > > > > > > > > > > Has the numeric constant 64 been chosen because > > > > > > > > sizeof(struct tcb.pid_ns) * 8 == 64? > > > > > > > > > > > > > > Yes. > > > > > > > For making it clear in the code, which one would be preferred? > > > > > > > - Using a named constant > > > > > > > > > > > > It's always nice to have a good name for a constant. > > > > > > > > > > > > > - Using the expression you wrote above > > > > > > > > > > > > Strictly speaking, that was not a valid C expression, but > > > > > > sizeof_field(struct tcb, pid_ns) * 8 > > > > > > is a valid one. > > > > > > > > > > As tcb.pid_ns is just one of the variables where ns ids are stored, I > > > > > might prefer using sizeof(uint64_t): > > > > > #define NS_ID_SIZE sizeof(uint64_t) > > > > > or maybe just simply: > > > > > #define NS_ID_SIZE 64 > > > > > > > > By the way, is it really 64? Yes, the type of struct tcb.pid_ns is 64-bit, > > > > but any valid pid_ns is 32-bit. > > > > > > I think it was chosen to be 64 bit by Eugene, because it's not > > > documented that it should fit into 32 bit. The documentation only says > > > that it's derived from an inode number. Or is it guaranteed that inode > > > numbers are maximum 32 bit? > > > > If I read the kernel correctly, pid_ns is assigned from struct ns_common.inum > > of type unsigned int. > > Yes, I understand. However since it's not documented anywhere (AFAIK), > it might change later, isn't it? But if you say it's highly unlikely > to change, we can use unsigned int for ns id type. I think we should > not use -1U then for indicating error in tcb.pid_ns, as it is a likely > valid ns id. It's not a big problem however, as errors are unlikely, > so there is an option to just leave tcb.pid_ns 0 on error. Yes, I agree, -1U shouldn't be used as an error indicator. -- ldv From ldv at altlinux.org Thu Aug 6 18:29:30 2020 From: ldv at altlinux.org (Dmitry V. Levin) Date: Thu, 6 Aug 2020 21:29:30 +0300 Subject: strace 5.8 released Message-ID: <20200806182929.GA22121@altlinux.org> Starting with version 4.13, strace follows the schedule of linux kernel and new versions of strace are released along with new versions of linux kernel, so strace 5.8 is tagged and uploaded. $ git tag -v v5.8 2> /dev/null | sed -n '/^$/,$p' Noteworthy changes in strace 5.8 (2020-08-06) ============================================= * Changes in behaviour * Modified %process class to contain system calls associated with process lifecycle (creation, exec, termination): kill, tkill, tgkill, pidfd_send_signal and rt_sigqueueinfo are added, arch_prctl and unshare are removed. * Improvements * Implemented decoding of faccessat2 syscall. * Implemented decoding of LOOP_CONFIGURE ioctl command. * Updated decoding of io_uring_setup syscall to match Linux 5.8. * Updated lists of AUDIT_*, BPF_*, CAP_*, ETH_*, INET_DIAG_*, IORING_*, KEYCTL_*, KVM_*, LOOP_*, NDA_*, RTC_*, TCA_*, STATX_*, and *_MAGIC constants. * Updated lists of ioctl commands from Linux 5.8. * Bug fixes * Added statx syscall to %fstat trace class. Contributors ============ This release was made possible by the contributions of many people. The maintainers are grateful to everyone who has contributed changes or bug reports. These include: * Chris Packham * Dmitry V. Levin * Eugene Syromyatnikov * Gleb Fotengauer-Malinovskiy * Janosch Frank * Steve Langasek * Sven Schnelle * ?kos Uzonyi Please refer to the CREDITS file for the full list of strace contributors. -- ldv -------------- next part -------------- A non-text attachment was scrubbed... Name: signature.asc Type: application/pgp-signature Size: 801 bytes Desc: not available URL: From uzonyi.akos at gmail.com Thu Aug 6 19:02:06 2020 From: uzonyi.akos at gmail.com (=?UTF-8?q?=C3=81kos=20Uzonyi?=) Date: Thu, 6 Aug 2020 21:02:06 +0200 Subject: [PATCH v6 0/5] [PIDNS] Final Message-ID: <20200806190211.118721-1-uzonyi.akos@gmail.com> From: Uzonyi ?kos NS ID type is unsigned int now. -1U is no longer used as an error indicator, it just simply left 0 if initialization fails (but is's unlikely to happen). I added a new function for creating tries, with a documentation explaining the choice of using 4 for node_key_bits and data_block_key_bits. Changes in v6: - Add function with documentation for creating tries - Do not use -1ULL as error indicator in tcb.pid_ns - Use unsigned int (instead of uint64_t) for NS IDs - Add constant for NS ID size. - Modify get_proc_pid a bit - Die if trie creation fails Changes in v5: - Squash "Use printpid in *" commits - Makefile.am: move adding getpid.c to "Use printpid in decoders" - Remove pid_ns_inited field from struct tcb - strace.1.in: remove -Y flag - Use tprints instead of tprintf where possible - Make some global variables static - pidns_init: remove "inited" bool variable - Make printpid_translation static - tests/pidns.c: refactor a bit - check_ns_ioctl: fix error msg - defs.h: Move adding get_proc_pid to "PID namespace translation support" - Remove tcp paramter name from declarations - Update printfd_pid_tracee_ns documentation - Use named constants for trie_create arguments - Add documentation comments - Add printpid_tgid_pgid function - Delete get_pid_max function; use global variables instead - Refactor trie: - Move key_size argument - Remove support for TRIE_SET - Merge trie_create, trie_init, trie_check functions - trie_free_node: make static, fix "node" argument type - Add max_depth field - Reorder functions - Extract common parts of trie_get, trie_set Changes in v4: - Skip tests if NS_* ioctl commands are not supported - Improve documentation in pidns.h - Use pipe for init process termination (instead of SIGKILL) - Add PIDNS_TEST_INIT macro - Remove "ifdef __NR_gettid" - Fix fork--pidns-tranlsation.test: skip if unshare fails with EPERM - Use debug message instead of normal message in some cases - Rename some labels - Rewrite get_ns function - Remove O_NONBLOCK from open(/proc//ns/pid) Changes in v3: - Split accidentally sqashed last commit - Undo modification of tests/pidfd_send_signal.c - Rename kcmp-yY test to kcmp-y--pidns-translation - Skip tests if unshare fails with EPERM - Fix buffer size in pidns_pid2str - Use largefile_wrappers.h macros - Return early if from_ns or our_ns is 0 - Do not call ioctl(NS_GET_PARENT) again, if first failed with ENOTTY - Skip pidns tests if Linux kernel version < 4.9 - Use smaller trie nodes in pidns.c - Remove race condition from fork--pidns-translation test - Move "key_size" to center in trie description - Use PT_TID (not PT_TGID) when translating tcp->pid - Fix get_ns_hierarchy and get_id_list functions - Fix migrate_pages test if syscall succeds - Fix filtering in ioctl_block--pidns-translation.test - Fix -a flag value in xetpriority test Changes in v2: - Add missing header files to Makefile - Fix pointer-to-int-cast errors - Fix unused-result errors - Use perror_msg instead of perror_func_msg where appropriate - Remove tcb parameter of read_int_from_file - Use xsprintf instead of snprintf - Refactor get_pid_max, get_ns_hierarchy, get_id_list functions - Remove -Y flag - Improve documentation of trie - Fix printing of f_owner_ex struct - Use printpid for F_GETOWN, F_SETOWN fcntl command arguments - Use printpid for shmid_ds.shm_cpid, shmid_ds.shm_clid - Call pidns_init before parsing arguments ?kos Uzonyi (5): PID namespace translation support Use printpid in decoders Use get_proc_pid for /proc paths Implement testing framework for pidns Add tests for PID namespace translation Makefile.am | 4 + NEWS | 1 + affinity.c | 6 +- block.c | 2 +- bpf.c | 2 +- capability.c | 4 +- clone.c | 14 +- defs.h | 58 +- fcntl.c | 24 +- get_robust_list.c | 3 +- getpid.c | 46 ++ ioprio.c | 26 +- ipc_shmctl.c | 5 +- kcmp.c | 5 +- largefile_wrappers.h | 2 + linux/dummy.h | 8 +- mmap_cache.c | 2 +- msghdr.c | 2 +- net.c | 2 +- netlink.c | 5 +- numa.c | 6 +- pathtrace.c | 5 +- pidfd_open.c | 2 +- pidns.c | 613 ++++++++++++++++++ print_fields.h | 24 + printsiginfo.c | 2 +- process.c | 3 +- process_vm.c | 6 +- resource.c | 27 +- sched.c | 25 +- signal.c | 21 +- sockaddr.c | 2 +- strace.1.in | 4 + strace.c | 11 +- syscall.c | 15 + tests/.gitignore | 31 + tests/Makefile.am | 37 ++ tests/fcntl--pidns-translation.c | 2 + tests/fcntl-common.c | 82 ++- tests/fcntl.c | 1 + tests/fcntl64--pidns-translation.c | 2 + tests/fcntl64.c | 3 + tests/fork--pidns-translation.awk | 15 + tests/fork--pidns-translation.c | 69 ++ tests/fork--pidns-translation.test | 16 + tests/gen_tests.in | 30 +- tests/getpgrp--pidns-translation.c | 2 + tests/getpgrp.c | 8 +- tests/getpid--pidns-translation.c | 2 + tests/getpid.c | 8 +- tests/getsid--pidns-translation.c | 2 + tests/getsid.c | 9 +- tests/gettid--pidns-translation.c | 2 + tests/gettid.c | 8 +- tests/init.sh | 31 + tests/ioctl_block--pidns-translation.c | 2 + tests/ioctl_block--pidns-translation.test | 24 + tests/ioctl_block.c | 24 +- tests/ioprio--pidns-translation.c | 2 + tests/ioprio.c | 54 +- tests/kcmp-y--pidns-translation.c | 2 + tests/kcmp.c | 36 +- tests/kill--pidns-translation.c | 2 + tests/kill.c | 12 +- tests/migrate_pages--pidns-translation.c | 2 + tests/migrate_pages.c | 17 +- tests/move_pages--pidns-translation.c | 2 + tests/move_pages.c | 51 +- tests/net-sockaddr--pidns-translation.c | 2 + tests/net-sockaddr.c | 66 +- tests/netlink_audit--pidns-translation.c | 2 + tests/netlink_audit--pidns-translation.test | 13 + tests/netlink_audit.c | 11 +- tests/pidfd_open--pidns-translation.c | 2 + tests/pidfd_open.c | 21 +- tests/pidfd_send_signal--pidns-translation.c | 2 + tests/pidfd_send_signal.c | 13 +- tests/pidns.c | 214 ++++++ tests/pidns.h | 56 ++ tests/prlimit64--pidns-translation.c | 2 + tests/prlimit64.c | 17 +- tests/process_vm_readv--pidns-translation.c | 2 + tests/process_vm_readv_writev.c | 27 +- tests/process_vm_writev--pidns-translation.c | 2 + tests/rt_sigqueueinfo--pidns-translation.c | 2 + tests/rt_sigqueueinfo.c | 15 +- tests/rt_tgsigqueueinfo--pidns-translation.c | 2 + tests/rt_tgsigqueueinfo.c | 26 +- tests/sched_xetaffinity--pidns-translation.c | 2 + tests/sched_xetaffinity.c | 31 +- tests/sched_xetattr--pidns-translation.c | 2 + tests/sched_xetattr.c | 47 +- tests/sched_xetparam--pidns-translation.c | 2 + tests/sched_xetparam.c | 20 +- tests/sched_xetscheduler--pidns-translation.c | 2 + tests/sched_xetscheduler.c | 44 +- tests/signal_receive--pidns-translation.c | 2 + tests/signal_receive.c | 22 +- tests/so_peercred--pidns-translation.c | 2 + tests/so_peercred.c | 22 + tests/xet_robust_list--pidns-translation.c | 2 + tests/xet_robust_list.c | 18 +- tests/xetpgid--pidns-translation.c | 2 + tests/xetpgid.c | 21 +- tests/xetpriority--pidns-translation.c | 2 + tests/xetpriority.c | 20 +- trie.c | 250 +++++++ trie.h | 89 +++ util.c | 27 +- wait.c | 36 +- 110 files changed, 2484 insertions(+), 255 deletions(-) create mode 100644 getpid.c create mode 100644 pidns.c create mode 100644 tests/fcntl--pidns-translation.c create mode 100644 tests/fcntl64--pidns-translation.c create mode 100644 tests/fork--pidns-translation.awk create mode 100644 tests/fork--pidns-translation.c create mode 100755 tests/fork--pidns-translation.test create mode 100644 tests/getpgrp--pidns-translation.c create mode 100644 tests/getpid--pidns-translation.c create mode 100644 tests/getsid--pidns-translation.c create mode 100644 tests/gettid--pidns-translation.c create mode 100644 tests/ioctl_block--pidns-translation.c create mode 100755 tests/ioctl_block--pidns-translation.test create mode 100644 tests/ioprio--pidns-translation.c create mode 100644 tests/kcmp-y--pidns-translation.c create mode 100644 tests/kill--pidns-translation.c create mode 100644 tests/migrate_pages--pidns-translation.c create mode 100644 tests/move_pages--pidns-translation.c create mode 100644 tests/net-sockaddr--pidns-translation.c create mode 100644 tests/netlink_audit--pidns-translation.c create mode 100755 tests/netlink_audit--pidns-translation.test create mode 100644 tests/pidfd_open--pidns-translation.c create mode 100644 tests/pidfd_send_signal--pidns-translation.c create mode 100644 tests/pidns.c create mode 100644 tests/pidns.h create mode 100644 tests/prlimit64--pidns-translation.c create mode 100644 tests/process_vm_readv--pidns-translation.c create mode 100644 tests/process_vm_writev--pidns-translation.c create mode 100644 tests/rt_sigqueueinfo--pidns-translation.c create mode 100644 tests/rt_tgsigqueueinfo--pidns-translation.c create mode 100644 tests/sched_xetaffinity--pidns-translation.c create mode 100644 tests/sched_xetattr--pidns-translation.c create mode 100644 tests/sched_xetparam--pidns-translation.c create mode 100644 tests/sched_xetscheduler--pidns-translation.c create mode 100644 tests/signal_receive--pidns-translation.c create mode 100644 tests/so_peercred--pidns-translation.c create mode 100644 tests/xet_robust_list--pidns-translation.c create mode 100644 tests/xetpgid--pidns-translation.c create mode 100644 tests/xetpriority--pidns-translation.c create mode 100644 trie.c create mode 100644 trie.h -- 2.27.0 From uzonyi.akos at gmail.com Thu Aug 6 19:02:10 2020 From: uzonyi.akos at gmail.com (=?UTF-8?q?=C3=81kos=20Uzonyi?=) Date: Thu, 6 Aug 2020 21:02:10 +0200 Subject: [PATCH v6 4/5] Implement testing framework for pidns In-Reply-To: <20200806190211.118721-1-uzonyi.akos@gmail.com> References: <20200806190211.118721-1-uzonyi.akos@gmail.com> Message-ID: <20200806190211.118721-5-uzonyi.akos@gmail.com> * tests/pidns.c: New file. * tests/pidns.h: New file. * tests/Makefile.am (libtests_a_SOURCES): Add pidns.c, pidns.h. * tests/init.sh (test_pidns, test_pidns_run_strace): New functions. --- tests/Makefile.am | 2 + tests/init.sh | 31 +++++++ tests/pidns.c | 214 ++++++++++++++++++++++++++++++++++++++++++++++ tests/pidns.h | 56 ++++++++++++ 4 files changed, 303 insertions(+) create mode 100644 tests/pidns.c create mode 100644 tests/pidns.h diff --git a/tests/Makefile.am b/tests/Makefile.am index 28d95e39..7a583a3a 100644 --- a/tests/Makefile.am +++ b/tests/Makefile.am @@ -44,6 +44,8 @@ libtests_a_SOURCES = \ libsocketcall.c \ lock_file.c \ overflowuid.c \ + pidns.c \ + pidns.h \ pipe_maxfd.c \ print_quoted_string.c \ print_time.c \ diff --git a/tests/init.sh b/tests/init.sh index d78e697b..7325fa4a 100644 --- a/tests/init.sh +++ b/tests/init.sh @@ -387,6 +387,37 @@ test_prog_set() test_pure_prog_set "$@" < "$srcdir/$NAME.in" } +test_pidns_run_strace() +{ + local parent_pid + + check_prog tail + check_prog cut + check_prog grep + + run_prog > /dev/null + run_strace --pidns-translation -f $@ $args > "$EXP" + + # filter out logs made by the parent or init process of the pidns test + parent_pid="$(tail -n 2 $LOG | head -n 1 | cut -d' ' -f1)" + init_pid="$(tail -n 1 $LOG | cut -d' ' -f1)" + grep -E -v "^($parent_pid|$init_pid) " "$LOG" > "$OUT" + match_diff "$OUT" "$EXP" +} + +test_pidns() +{ + # ioctl(NS_GET_PARENT) is added in Linux 4.9 + require_min_kernel_version_or_skip 4.9 + check_prog unshare + + test_pidns_run_strace "$@" + + # test PID translation when /proc is mounted from an other namespace + STRACE="unshare -Urpf $STRACE" + test_pidns_run_strace "$@" +} + check_prog cat check_prog rm diff --git a/tests/pidns.c b/tests/pidns.c new file mode 100644 index 00000000..f54af340 --- /dev/null +++ b/tests/pidns.c @@ -0,0 +1,214 @@ +/* + * Testing framework for PID namespace translation + * + * Copyright (c) 2020 ?kos Uzonyi + * All rights reserved. + * + * SPDX-License-Identifier: LGPL-2.1-or-later + */ +#include "tests.h" +#include "pidns.h" +#include "nsfs.h" + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +static bool pidns_translation = false; +static bool pidns_unshared = false; + +/* Our PIDs in strace's namespace */ +static pid_t pidns_strace_ids[PT_COUNT]; + +void +pidns_print_leader(void) +{ + if (pidns_translation) + printf("%-5d ", pidns_strace_ids[PT_TID]); +} + +const char * +pidns_pid2str(enum pid_type type) +{ + static const char format[] = " /* %d in strace's PID NS */"; + static char buf[PT_COUNT][sizeof(format) + sizeof(int) * 3]; + + if (type < 0 || type >= PT_COUNT) + return ""; + + if (!pidns_unshared || !pidns_strace_ids[type]) + return ""; + + snprintf(buf[type], sizeof(buf[type]), format, pidns_strace_ids[type]); + return buf[type]; +} + +/** + * This function is like fork, but does a few more things. It sets up the + * child's PGID and SID according to the parameters. Also it fills the + * pidns_strace_ids array in the child's memory with the PIDs of the child in + * parent's PID namespace. In the parent it waits for the child to terminate + * (but leaves the zombie to use it later as a process group). If the child + * terminates with nonzero exit status, the test is failed. + * + * @param pgid The process group the child should be moved to. It's expected + * to be a PID of a zombie process (will be reaped). If + * negative, leave the child in the process group of the parent. + * If 0, move the process to its own process group. + * @param new_sid Wheather child should be moved to a new session. + */ +static pid_t +pidns_fork(pid_t pgid, bool new_sid) +{ + int strace_ids_pipe[2]; + if (pipe(strace_ids_pipe) < 0) + perror_msg_and_fail("pipe"); + + fflush(stdout); + pid_t pid = fork(); + if (pid < 0) + perror_msg_and_fail("fork"); + + if (!pid) { + close(strace_ids_pipe[1]); + if (read(strace_ids_pipe[0], pidns_strace_ids, + sizeof(pidns_strace_ids)) < 0) + perror_msg_and_fail("read"); + close(strace_ids_pipe[0]); + + if (pidns_strace_ids[PT_SID]) + setsid(); + + return 0; + } + + pidns_strace_ids[PT_TID] = pid; + pidns_strace_ids[PT_TGID] = pid; + pidns_strace_ids[PT_PGID] = 0; + pidns_strace_ids[PT_SID] = 0; + + if (!pgid) + pgid = pid; + + if (pgid > 0) { + if (setpgid(pid, pgid) < 0) + perror_msg_and_fail("setpgid"); + + pidns_strace_ids[PT_PGID] = pgid; + } + + /* Reap group leader to test PGID decoding */ + if (pgid > 0 && pgid != pid) { + int ret = waitpid(pgid, NULL, WNOHANG); + if (ret < 0) + perror_msg_and_fail("wait"); + if (!ret) + error_msg_and_fail("could not reap group leader"); + } + + if (new_sid) { + pidns_strace_ids[PT_SID] = pid; + pidns_strace_ids[PT_PGID] = pid; + } + + if (write(strace_ids_pipe[1], pidns_strace_ids, + sizeof(pidns_strace_ids)) < 0) + perror_msg_and_fail("write"); + close(strace_ids_pipe[0]); + close(strace_ids_pipe[1]); + + /* WNOWAIT: leave the zombie, to be able to use it as a process group */ + siginfo_t siginfo; + if (waitid(P_PID, pid, &siginfo, WEXITED | WNOWAIT) < 0) + perror_msg_and_fail("wait"); + if (siginfo.si_code != CLD_EXITED || siginfo.si_status) + error_msg_and_fail("child terminated with nonzero exit status"); + + return pid; +} + +static void +create_init_process(void) +{ + int child_pipe[2]; + if (pipe(child_pipe) < 0) + perror_msg_and_fail("pipe"); + + pid_t pid = fork(); + if (pid < 0) + perror_msg_and_fail("fork"); + + if (!pid) { + close(child_pipe[1]); + _exit(read(child_pipe[0], &child_pipe[1], sizeof(int)) == 0); + } + + close(child_pipe[0]); +} + +void +check_ns_ioctl(void) +{ + int fd = open("/proc/self/ns/pid", O_RDONLY); + if (fd < 0) + perror_msg_and_fail("opening /proc/self/ns/pid"); + + int userns_fd = ioctl(fd, NS_GET_USERNS); + if (userns_fd < 0) { + if (errno == ENOTTY) + error_msg_and_skip("NS_* ioctl commands are not " + "supported by the kernel"); + else + perror_msg_and_fail("ioctl(NS_GET_USERNS)"); + } + + close(userns_fd); + close(fd); +} + +void +pidns_test_init(void) +{ + pidns_translation = true; + + check_ns_ioctl(); + + if (!pidns_fork(-1, false)) + return; + + /* Unshare user namespace too, so we do not need to be root */ + if (unshare(CLONE_NEWUSER | CLONE_NEWPID) < 0) { + if (errno == EPERM) + perror_msg_and_skip("unshare"); + + perror_msg_and_fail("unshare"); + } + + pidns_unshared = true; + + create_init_process(); + + if (!pidns_fork(-1, false)) + return; + + if (!pidns_fork(-1, true)) + return; + + pid_t pgid; + if (!(pgid = pidns_fork(0, false))) + return; + + if (!pidns_fork(pgid, false)) + return; + + exit(0); +} diff --git a/tests/pidns.h b/tests/pidns.h new file mode 100644 index 00000000..76963eb3 --- /dev/null +++ b/tests/pidns.h @@ -0,0 +1,56 @@ +/* + * Test PID namespace translation + * + * Copyright (c) 2020 ?kos Uzonyi + * All rights reserved. + * + * SPDX-License-Identifier: LGPL-2.1-or-later + */ +#ifndef STRACE_PIDNS_H +#define STRACE_PIDNS_H + +#ifdef PIDNS_TRANSLATION +# define PIDNS_TEST_INIT pidns_test_init() +#else +# define PIDNS_TEST_INIT +#endif + +#include + +enum pid_type { + PT_TID, + PT_TGID, + PT_PGID, + PT_SID, + + PT_COUNT, + PT_NONE = -1 +}; + +/* Prints leader (process tid) if pidns_test_init was called */ +void pidns_print_leader(void); + +/* + * Returns a static buffer containing the translation string of our PID. + */ +const char *pidns_pid2str(enum pid_type type); + +/** + * Skips the test if NS_* ioctl commands are not supported by the kernel. + */ +void check_ns_ioctl(void); + +/** + * Init pidns testing. + * + * Should be called at the beginning of the test's main function + * + * This function calls fork a couple of times, and returns in the child + * processes. These child processes are in a new PID namespace with different + * PID configurations (group leader, session leader, ...). If any child + * terminates with nonzero exit status the test is failed. Otherwise the test is + * succesful, and the parent process exits with 0. + */ +void pidns_test_init(void); + +#endif \ No newline at end of file -- 2.27.0 From uzonyi.akos at gmail.com Thu Aug 6 19:02:08 2020 From: uzonyi.akos at gmail.com (=?UTF-8?q?=C3=81kos=20Uzonyi?=) Date: Thu, 6 Aug 2020 21:02:08 +0200 Subject: [PATCH v6 2/5] Use printpid in decoders In-Reply-To: <20200806190211.118721-1-uzonyi.akos@gmail.com> References: <20200806190211.118721-1-uzonyi.akos@gmail.com> Message-ID: <20200806190211.118721-3-uzonyi.akos@gmail.com> * getpid.c: New file. * Makefile.am (libstrace_a_SOURCES): Add getpid.c. * linux/dummy.h (sys_getpid, sys_getppid, sys_gettid, sys_setpgid, sys_setpgrp): Remove. * util.c (printfd_pid_tracee_ns): Implement using translate_pid. * defs.h (printnum_pid): New function definition. (printfd_pid_tracee_ns): Update documentation * util.c: (printnum_pid): New function. * print_fields.h (PRINT_FIELD_TID): New macro. (PRINT_FIELD_TGID): Likewise. (PRINT_FIELD_PGID): Likewise. (PRINT_FIELD_SID): Likewise. * affinity.c: Print PIDs with printpid. * block.c: Likewise. * bpf.c: Likewise. * capability.c: Likewise. * clone.c: Likewise. * fcntl.c: Likewise. * get_robust_list.c: Likewise. * ioprio.c: Likewise. * kcmp.c: Likewise. * msghdr.c: Likewise. * net.c: Likewise. * netlink.c: Likewise. * numa.c: Likewise. * pidfd_open.c: Likewise. * printsiginfo.c: Likewise. * process.c: Likewise. * process_vm.c: Likewise. * resource.c: Likewise. * sched.c: Likewise. * signal.c: Likewise. * sockaddr.c: Likewise. * wait.c: Likewise. * kcmp.c (SYS_FUNC(kcmp)): Fix KCMP_FILE pid arguments. * tests/kcmp.c (printpidfd): Print path if VERBOSE_FD. (main): Use our real pid if real fds are used. --- Makefile.am | 1 + affinity.c | 6 ++++-- block.c | 2 +- bpf.c | 2 +- capability.c | 4 +++- clone.c | 14 +++++++------- defs.h | 5 ++++- fcntl.c | 24 ++++++++++++++++++++++-- get_robust_list.c | 3 ++- getpid.c | 46 ++++++++++++++++++++++++++++++++++++++++++++++ ioprio.c | 26 ++++++++++++++++++++++---- ipc_shmctl.c | 5 +++-- kcmp.c | 5 ++++- linux/dummy.h | 8 +------- msghdr.c | 2 +- net.c | 2 +- netlink.c | 5 +++-- numa.c | 6 ++++-- pidfd_open.c | 2 +- print_fields.h | 24 ++++++++++++++++++++++++ printsiginfo.c | 2 +- process.c | 3 ++- process_vm.c | 6 ++++-- resource.c | 27 ++++++++++++++++++++++++--- sched.c | 25 ++++++++++++++++--------- signal.c | 21 +++++++++++++++------ sockaddr.c | 2 +- tests/kcmp.c | 25 ++++++++++++++++++++++--- util.c | 20 ++++++++++++++------ wait.c | 36 ++++++++++++++++++++++++------------ 30 files changed, 278 insertions(+), 81 deletions(-) create mode 100644 getpid.c diff --git a/Makefile.am b/Makefile.am index 73c22035..15fcd9a6 100644 --- a/Makefile.am +++ b/Makefile.am @@ -135,6 +135,7 @@ libstrace_a_SOURCES = \ getcpu.c \ getcwd.c \ getpagesize.c \ + getpid.c \ getrandom.c \ hdio.c \ hostname.c \ diff --git a/affinity.c b/affinity.c index eb3158b7..f9893adb 100644 --- a/affinity.c +++ b/affinity.c @@ -82,7 +82,8 @@ SYS_FUNC(sched_setaffinity) const int pid = tcp->u_arg[0]; const unsigned int len = tcp->u_arg[1]; - tprintf("%d, %u, ", pid, len); + printpid(tcp, pid, PT_TGID); + tprintf(", %u, ", len); print_affinitylist(tcp, tcp->u_arg[2], len); return RVAL_DECODED; @@ -94,7 +95,8 @@ SYS_FUNC(sched_getaffinity) const unsigned int len = tcp->u_arg[1]; if (entering(tcp)) { - tprintf("%d, %u, ", pid, len); + printpid(tcp, pid, PT_TGID); + tprintf(", %u, ", len); } else { print_affinitylist(tcp, tcp->u_arg[2], tcp->u_rval); } diff --git a/block.c b/block.c index b527ef43..783a4b5a 100644 --- a/block.c +++ b/block.c @@ -179,7 +179,7 @@ MPERS_PRINTER_DECL(int, block_ioctl, struct tcb *const tcp, PRINT_FIELD_U(", ", buts, buf_nr); PRINT_FIELD_U(", ", buts, start_lba); PRINT_FIELD_U(", ", buts, end_lba); - PRINT_FIELD_D(", ", buts, pid); + PRINT_FIELD_TGID(", ", buts, pid, tcp); return 0; } else { struct_blk_user_trace_setup buts; diff --git a/bpf.c b/bpf.c index af830053..0ec33ba4 100644 --- a/bpf.c +++ b/bpf.c @@ -927,7 +927,7 @@ BEGIN_BPF_CMD_DECODER(BPF_TASK_FD_QUERY) if (entering(tcp)) { set_tcb_priv_ulong(tcp, attr.buf_len); - PRINT_FIELD_D("{task_fd_query={", attr, pid); + PRINT_FIELD_TGID("{task_fd_query={", attr, pid, tcp); PRINT_FIELD_FD(", ", attr, fd, tcp); PRINT_FIELD_U(", ", attr, flags); PRINT_FIELD_U(", ", attr, buf_len); diff --git a/capability.c b/capability.c index 0e763ee1..812fb435 100644 --- a/capability.c +++ b/capability.c @@ -70,7 +70,9 @@ print_cap_header(struct tcb *const tcp, const kernel_ulong_t addr, tprints("{version="); printxval(cap_version, h->version, "_LINUX_CAPABILITY_VERSION_???"); - tprintf(", pid=%d}", h->pid); + tprints(", pid="); + printpid(tcp, h->pid, PT_TGID); + tprints("}"); } static void diff --git a/clone.c b/clone.c index 487c5c23..45f24065 100644 --- a/clone.c +++ b/clone.c @@ -114,14 +114,14 @@ SYS_FUNC(clone) */ if ((flags & (CLONE_PARENT_SETTID|CLONE_PIDFD|CLONE_CHILD_SETTID |CLONE_CHILD_CLEARTID|CLONE_SETTLS)) == 0) - return RVAL_DECODED; + return RVAL_DECODED | RVAL_TID; } else { if (flags & (CLONE_PARENT_SETTID|CLONE_PIDFD)) { kernel_ulong_t addr = tcp->u_arg[ARG_PTID]; tprints(", parent_tid="); if (flags & CLONE_PARENT_SETTID) - printnum_int(tcp, addr, "%u"); + printnum_pid(tcp, addr, PT_TID); else printnum_fd(tcp, addr); } @@ -134,7 +134,7 @@ SYS_FUNC(clone) printaddr(tcp->u_arg[ARG_CTID]); } } - return 0; + return RVAL_TID; } @@ -229,7 +229,7 @@ SYS_FUNC(clone3) if ((arg.flags & (CLONE_PIDFD | CLONE_PARENT_SETTID)) || (size > fetch_size)) - return 0; + return RVAL_TID; goto out; } @@ -256,7 +256,7 @@ SYS_FUNC(clone3) if (arg.flags & CLONE_PARENT_SETTID) { tprintf("%sparent_tid=", pfx); - printnum_int(tcp, arg.parent_tid, "%d"); /* TID */ + printnum_pid(tcp, arg.parent_tid, PT_TID); pfx = ", "; } @@ -279,7 +279,7 @@ SYS_FUNC(clone3) out: tprintf(", %" PRI_klu, size); - return RVAL_DECODED; + return RVAL_DECODED | RVAL_TID; } @@ -300,5 +300,5 @@ SYS_FUNC(unshare) SYS_FUNC(fork) { - return RVAL_DECODED; + return RVAL_DECODED | RVAL_TGID; } diff --git a/defs.h b/defs.h index 692fa0d3..f59da4ba 100644 --- a/defs.h +++ b/defs.h @@ -1098,7 +1098,7 @@ printfd(struct tcb *tcp, int fd) /** * Print file descriptor fd owned by process with ID pid (from the PID NS - * of the tracee the descriptor tcp). This is a stub. + * of the tracee). */ extern void printfd_pid_tracee_ns(struct tcb *tcp, pid_t pid, int fd); @@ -1558,6 +1558,9 @@ DECL_PRINTNUM_ADDR(int64); extern bool printnum_fd(struct tcb *, kernel_ulong_t addr); +extern bool +printnum_pid(struct tcb *const tcp, const kernel_ulong_t addr, enum pid_type type); + static inline bool printnum_slong(struct tcb *tcp, kernel_ulong_t addr) { diff --git a/fcntl.c b/fcntl.c index 6fcd5dac..5c630a06 100644 --- a/fcntl.c +++ b/fcntl.c @@ -28,7 +28,7 @@ print_struct_flock64(struct tcb *const tcp, const struct_kernel_flock64 *fl, con PRINT_FIELD_D(", ", *fl, l_start); PRINT_FIELD_D(", ", *fl, l_len); if (getlk) - PRINT_FIELD_D(", ", *fl, l_pid); + PRINT_FIELD_TGID(", ", *fl, l_pid, tcp); tprints("}"); } @@ -59,7 +59,22 @@ print_f_owner_ex(struct tcb *const tcp, const kernel_ulong_t addr) return; PRINT_FIELD_XVAL("{", owner, type, f_owner_types, "F_OWNER_???"); - PRINT_FIELD_D(", ", owner, pid); + + enum pid_type pid_type = PT_NONE; + switch (owner.type) + { + case F_OWNER_TID: + pid_type = PT_TID; + break; + case F_OWNER_PID: + pid_type = PT_TGID; + break; + case F_OWNER_PGRP: + pid_type = PT_PGID; + break; + } + tprints(", pid="); + printpid(tcp, owner.pid, pid_type); tprints("}"); } @@ -74,6 +89,9 @@ print_fcntl(struct tcb *tcp) printflags(fdflags, tcp->u_arg[2], "FD_???"); break; case F_SETOWN: + tprints(", "); + printpid_tgid_pgid(tcp, tcp->u_arg[2]); + break; case F_SETPIPE_SZ: tprintf(", %" PRI_kld, tcp->u_arg[2]); break; @@ -116,6 +134,8 @@ print_fcntl(struct tcb *tcp) printsignal(tcp->u_arg[2]); break; case F_GETOWN: + return RVAL_DECODED | + ((int) tcp->u_rval < 0 ? RVAL_PGID : RVAL_TGID); case F_GETPIPE_SZ: break; case F_GETFD: diff --git a/get_robust_list.c b/get_robust_list.c index b5aebaff..4b771bac 100644 --- a/get_robust_list.c +++ b/get_robust_list.c @@ -10,7 +10,8 @@ SYS_FUNC(get_robust_list) { if (entering(tcp)) { - tprintf("%d, ", (int) tcp->u_arg[0]); + printpid(tcp, (int) tcp->u_arg[0], PT_TID); + tprints(", "); } else { printnum_ptr(tcp, tcp->u_arg[1]); tprints(", "); diff --git a/getpid.c b/getpid.c new file mode 100644 index 00000000..5e9a1a29 --- /dev/null +++ b/getpid.c @@ -0,0 +1,46 @@ +/* + * Copyright (c) 2020 ?kos Uzonyi + * All rights reserved. + * + * SPDX-License-Identifier: LGPL-2.1-or-later + */ + +#include "defs.h" + +SYS_FUNC(getpid) +{ + return RVAL_DECODED | RVAL_TGID; +} + +SYS_FUNC(gettid) +{ + return RVAL_DECODED | RVAL_TID; +} + +SYS_FUNC(getpgrp) +{ + return RVAL_DECODED | RVAL_PGID; +} + +SYS_FUNC(getpgid) +{ + printpid(tcp, tcp->u_arg[0], PT_TGID); + + return RVAL_DECODED | RVAL_PGID; +} + +SYS_FUNC(getsid) +{ + printpid(tcp, tcp->u_arg[0], PT_TGID); + + return RVAL_DECODED | RVAL_SID; +} + +SYS_FUNC(setpgid) +{ + printpid(tcp, tcp->u_arg[0], PT_TGID); + tprints(", "); + printpid(tcp, tcp->u_arg[1], PT_PGID); + + return RVAL_DECODED; +} diff --git a/ioprio.c b/ioprio.c index 873c8ce5..52144884 100644 --- a/ioprio.c +++ b/ioprio.c @@ -49,13 +49,30 @@ print_ioprio(unsigned int ioprio) ? tprints_comment : tprints)(str); } +static void +ioprio_print_who(struct tcb *tcp, int which, int who) +{ + switch (which) + { + case IOPRIO_WHO_PROCESS: + printpid(tcp, who, PT_TGID); + break; + case IOPRIO_WHO_PGRP: + printpid(tcp, who, PT_PGID); + break; + default: + tprintf("%d", who); + break; + } +} + SYS_FUNC(ioprio_get) { if (entering(tcp)) { /* int which */ printxval(ioprio_who, tcp->u_arg[0], "IOPRIO_WHO_???"); - /* int who */ - tprintf(", %d", (int) tcp->u_arg[1]); + tprints(", "); + ioprio_print_who(tcp, (int) tcp->u_arg[0], (int) tcp->u_arg[1]); return 0; } else { if (syserror(tcp)) @@ -72,8 +89,9 @@ SYS_FUNC(ioprio_set) { /* int which */ printxval(ioprio_who, tcp->u_arg[0], "IOPRIO_WHO_???"); - /* int who */ - tprintf(", %d, ", (int) tcp->u_arg[1]); + tprints(", "); + ioprio_print_who(tcp, (int) tcp->u_arg[0], (int) tcp->u_arg[1]); + tprints(", "); /* int ioprio */ if (xlat_verbose(xlat_verbosity) != XLAT_STYLE_ABBREV) tprintf("%d", (int) tcp->u_arg[2]); diff --git a/ipc_shmctl.c b/ipc_shmctl.c index 8c9e1e7a..71b41651 100644 --- a/ipc_shmctl.c +++ b/ipc_shmctl.c @@ -12,6 +12,7 @@ */ #include "defs.h" +#include "print_fields.h" #include DEF_MPERS_TYPE(shmid_ds_t) @@ -53,8 +54,8 @@ print_shmid_ds(struct tcb *const tcp, const kernel_ulong_t addr, int cmd) PRINT_FIELD_UID(", ", shmid_ds.shm_perm, cgid); tprints("}"); tprintf(", shm_segsz=%u", (unsigned) shmid_ds.shm_segsz); - PRINT_FIELD_D(", ", shmid_ds, shm_cpid); - PRINT_FIELD_D(", ", shmid_ds, shm_lpid); + PRINT_FIELD_TGID(", ", shmid_ds, shm_cpid, tcp); + PRINT_FIELD_TGID(", ", shmid_ds, shm_lpid, tcp); tprintf(", shm_nattch=%u", (unsigned) shmid_ds.shm_nattch); tprintf(", shm_atime=%u", (unsigned) shmid_ds.shm_atime); tprintf(", shm_dtime=%u", (unsigned) shmid_ds.shm_dtime); diff --git a/kcmp.c b/kcmp.c index 62115555..a5e1cdce 100644 --- a/kcmp.c +++ b/kcmp.c @@ -30,7 +30,10 @@ SYS_FUNC(kcmp) kernel_ulong_t idx1 = tcp->u_arg[3]; kernel_ulong_t idx2 = tcp->u_arg[4]; - tprintf("%d, %d, ", pid1, pid2); + printpid(tcp, pid1, PT_TGID); + tprints(", "); + printpid(tcp, pid2, PT_TGID); + tprints(", "); printxval(kcmp_types, type, "KCMP_???"); switch (type) { diff --git a/linux/dummy.h b/linux/dummy.h index 2f859a60..ca0d2f0c 100644 --- a/linux/dummy.h +++ b/linux/dummy.h @@ -53,6 +53,7 @@ # define sys_getgid sys_getuid # define sys_getgid16 sys_getuid16 # define sys_getpeername sys_getsockname +# define sys_getppid sys_getpid # define sys_getresgid sys_getresuid # define sys_getresgid16 sys_getresuid16 # define sys_lstat sys_stat @@ -87,10 +88,6 @@ # define sys_vfork sys_fork /* printargs does the right thing */ -# define sys_getpgrp printargs -# define sys_getpid printargs -# define sys_getppid printargs -# define sys_gettid printargs # define sys_idle printargs # define sys_munlockall printargs # define sys_pause printargs @@ -108,10 +105,7 @@ /* printargs_d does the right thing */ # define sys_exit printargs_d -# define sys_getpgid printargs_d -# define sys_getsid printargs_d # define sys_nice printargs_d -# define sys_setpgid printargs_d # define sys_setpgrp printargs_d # define sys_timer_delete printargs_d # define sys_timer_getoverrun printargs_d diff --git a/msghdr.c b/msghdr.c index ef6dc24b..170b8e51 100644 --- a/msghdr.c +++ b/msghdr.c @@ -69,7 +69,7 @@ print_scm_creds(struct tcb *tcp, const void *cmsg_data, { const struct ucred *uc = cmsg_data; - PRINT_FIELD_D("{", *uc, pid); + PRINT_FIELD_TGID("{", *uc, pid, tcp); PRINT_FIELD_UID(", ", *uc, uid); PRINT_FIELD_UID(", ", *uc, gid); tprints("}"); diff --git a/net.c b/net.c index fa4638e7..2099f0ac 100644 --- a/net.c +++ b/net.c @@ -601,7 +601,7 @@ print_get_ucred(struct tcb *const tcp, const kernel_ulong_t addr, if (umoven_or_printaddr(tcp, addr, len, &uc)) return; - PRINT_FIELD_LEN("{", uc, pid, len, PRINT_FIELD_D); + PRINT_FIELD_LEN("{", uc, pid, len, PRINT_FIELD_TGID, tcp); PRINT_FIELD_LEN(", ", uc, uid, len, PRINT_FIELD_UID); PRINT_FIELD_LEN(", ", uc, gid, len, PRINT_FIELD_UID); tprints("}"); diff --git a/netlink.c b/netlink.c index 88d864a9..cb29033a 100644 --- a/netlink.c +++ b/netlink.c @@ -446,8 +446,9 @@ print_nlmsghdr(struct tcb *tcp, decode_nlmsg_flags(nlmsghdr->nlmsg_flags, nlmsghdr->nlmsg_type, family); - tprintf(", seq=%u, pid=%d}", nlmsghdr->nlmsg_seq, - nlmsghdr->nlmsg_pid); + tprintf(", seq=%u, pid=", nlmsghdr->nlmsg_seq); + printpid(tcp, nlmsghdr->nlmsg_pid, PT_TGID); + tprints("}"); } static bool diff --git a/numa.c b/numa.c index cc7a7cc6..37b95397 100644 --- a/numa.c +++ b/numa.c @@ -44,7 +44,8 @@ print_nodemask(struct tcb *const tcp, const kernel_ulong_t addr, SYS_FUNC(migrate_pages) { - tprintf("%d, %" PRI_klu ", ", (int) tcp->u_arg[0], tcp->u_arg[1]); + printpid(tcp, (int) tcp->u_arg[0], PT_TGID); + tprintf(", %" PRI_klu ", ", tcp->u_arg[1]); print_nodemask(tcp, tcp->u_arg[2], tcp->u_arg[1]); tprints(", "); print_nodemask(tcp, tcp->u_arg[3], tcp->u_arg[1]); @@ -170,7 +171,8 @@ SYS_FUNC(move_pages) kernel_ulong_t buf; if (entering(tcp)) { - tprintf("%d, %" PRI_klu ", ", (int) tcp->u_arg[0], npages); + printpid(tcp, (int) tcp->u_arg[0], PT_TGID); + tprintf(", %" PRI_klu ", ", npages); print_array(tcp, tcp->u_arg[2], npages, &buf, current_wordsize, tfetch_mem, print_addr, 0); tprints(", "); diff --git a/pidfd_open.c b/pidfd_open.c index bbc7f617..10b5003d 100644 --- a/pidfd_open.c +++ b/pidfd_open.c @@ -10,7 +10,7 @@ SYS_FUNC(pidfd_open) { /* pid_t pid */ - tprintf("%d", (int) tcp->u_arg[0]); + printpid(tcp, (int) tcp->u_arg[0], PT_TGID); /* unsigned int flags */ tprintf(", %#x", (unsigned int) tcp->u_arg[1]); diff --git a/print_fields.h b/print_fields.h index f9714115..33d4a458 100644 --- a/print_fields.h +++ b/print_fields.h @@ -263,6 +263,30 @@ printfd((tcp_), (where_).field_); \ } while (0) +# define PRINT_FIELD_TID(prefix_, where_, field_, tcp_) \ + do { \ + STRACE_PRINTF("%s%s=", (prefix_), #field_); \ + printpid((tcp_), (where_).field_, PT_TID); \ + } while (0) + +# define PRINT_FIELD_TGID(prefix_, where_, field_, tcp_) \ + do { \ + STRACE_PRINTF("%s%s=", (prefix_), #field_); \ + printpid((tcp_), (where_).field_, PT_TGID); \ + } while (0) + +# define PRINT_FIELD_PGID(prefix_, where_, field_, tcp_) \ + do { \ + STRACE_PRINTF("%s%s=", (prefix_), #field_); \ + printpid((tcp_), (where_).field_, PT_PGID); \ + } while (0) + +# define PRINT_FIELD_SID(prefix_, where_, field_, tcp_) \ + do { \ + STRACE_PRINTF("%s%s=", (prefix_), #field_); \ + printpid((tcp_), (where_).field_, PT_SID); \ + } while (0) + # define PRINT_FIELD_STRN(prefix_, where_, field_, len_, tcp_) \ do { \ STRACE_PRINTF("%s%s=", (prefix_), #field_); \ diff --git a/printsiginfo.c b/printsiginfo.c index 8ed1e7ba..cb4cde4a 100644 --- a/printsiginfo.c +++ b/printsiginfo.c @@ -58,7 +58,7 @@ static void printsigsource(struct tcb *tcp, const siginfo_t *sip) { - PRINT_FIELD_D(", ", *sip, si_pid); + PRINT_FIELD_TGID(", ", *sip, si_pid, tcp); PRINT_FIELD_UID(", ", *sip, si_uid); } diff --git a/process.c b/process.c index a98c304e..d6ff255d 100644 --- a/process.c +++ b/process.c @@ -92,7 +92,8 @@ SYS_FUNC(ptrace) } /* pid */ - tprintf(", %d", pid); + tprints(", "); + printpid(tcp, pid, PT_TGID); /* addr */ switch (request) { diff --git a/process_vm.c b/process_vm.c index abee1e68..50acb3fd 100644 --- a/process_vm.c +++ b/process_vm.c @@ -13,7 +13,8 @@ SYS_FUNC(process_vm_readv) { if (entering(tcp)) { /* arg 1: pid */ - tprintf("%d, ", (int) tcp->u_arg[0]); + printpid(tcp, (int) tcp->u_arg[0], PT_TGID); + tprints(", "); } else { kernel_ulong_t local_iovcnt = tcp->u_arg[2]; kernel_ulong_t remote_iovcnt = tcp->u_arg[4]; @@ -42,7 +43,8 @@ SYS_FUNC(process_vm_writev) kernel_ulong_t flags = tcp->u_arg[5]; /* arg 1: pid */ - tprintf("%d, ", (int) tcp->u_arg[0]); + printpid(tcp, (int) tcp->u_arg[0], PT_TGID); + tprints(", "); /* arg 2: local iov */ tprint_iov(tcp, local_iovcnt, tcp->u_arg[1], IOV_DECODE_STR); /* arg 3: local iovcnt */ diff --git a/resource.c b/resource.c index 53192ee9..bd21b748 100644 --- a/resource.c +++ b/resource.c @@ -142,7 +142,8 @@ SYS_FUNC(setrlimit) SYS_FUNC(prlimit64) { if (entering(tcp)) { - tprintf("%d, ", (int) tcp->u_arg[0]); + printpid(tcp, (int) tcp->u_arg[0], PT_TGID); + tprints(", "); printxval(resources, tcp->u_arg[1], "RLIMIT_???"); tprints(", "); print_rlimit64(tcp, tcp->u_arg[2]); @@ -179,10 +180,28 @@ SYS_FUNC(osf_getrusage) #include "xlat/priorities.h" +static void +priority_print_who(struct tcb *tcp, int which, int who) +{ + switch (which) + { + case PRIO_PROCESS: + printpid(tcp, who, PT_TGID); + break; + case PRIO_PGRP: + printpid(tcp, who, PT_PGID); + break; + default: + tprintf("%d", who); + break; + } +} + SYS_FUNC(getpriority) { printxval(priorities, tcp->u_arg[0], "PRIO_???"); - tprintf(", %d", (int) tcp->u_arg[1]); + tprints(", "); + priority_print_who(tcp, tcp->u_arg[0], tcp->u_arg[1]); return RVAL_DECODED; } @@ -190,7 +209,9 @@ SYS_FUNC(getpriority) SYS_FUNC(setpriority) { printxval(priorities, tcp->u_arg[0], "PRIO_???"); - tprintf(", %d, %d", (int) tcp->u_arg[1], (int) tcp->u_arg[2]); + tprints(", "); + priority_print_who(tcp, tcp->u_arg[0], tcp->u_arg[1]); + tprintf(", %d", (int) tcp->u_arg[2]); return RVAL_DECODED; } diff --git a/sched.c b/sched.c index 788ef39b..7ae5abe2 100644 --- a/sched.c +++ b/sched.c @@ -21,7 +21,7 @@ SYS_FUNC(sched_getscheduler) { if (entering(tcp)) { - tprintf("%d", (int) tcp->u_arg[0]); + printpid(tcp, (int) tcp->u_arg[0], PT_TGID); } else if (!syserror(tcp)) { tcp->auxstr = xlookup(schedulers, (kernel_ulong_t) tcp->u_rval); return RVAL_STR; @@ -31,7 +31,8 @@ SYS_FUNC(sched_getscheduler) SYS_FUNC(sched_setscheduler) { - tprintf("%d, ", (int) tcp->u_arg[0]); + printpid(tcp, (int) tcp->u_arg[0], PT_TGID); + tprints(", "); printxval(schedulers, tcp->u_arg[1], "SCHED_???"); tprints(", "); printnum_int(tcp, tcp->u_arg[2], "%d"); @@ -41,16 +42,19 @@ SYS_FUNC(sched_setscheduler) SYS_FUNC(sched_getparam) { - if (entering(tcp)) - tprintf("%d, ", (int) tcp->u_arg[0]); - else + if (entering(tcp)) { + printpid(tcp, (int) tcp->u_arg[0], PT_TGID); + tprints(", "); + } else { printnum_int(tcp, tcp->u_arg[1], "%d"); + } return 0; } SYS_FUNC(sched_setparam) { - tprintf("%d, ", (int) tcp->u_arg[0]); + printpid(tcp, (int) tcp->u_arg[0], PT_TGID); + tprints(", "); printnum_int(tcp, tcp->u_arg[1], "%d"); return RVAL_DECODED; @@ -68,7 +72,8 @@ do_sched_rr_get_interval(struct tcb *const tcp, const print_obj_by_addr_fn print_ts) { if (entering(tcp)) { - tprintf("%d, ", (int) tcp->u_arg[0]); + printpid(tcp, (int) tcp->u_arg[0], PT_TGID); + tprints(", "); } else { if (syserror(tcp)) printaddr(tcp->u_arg[1]); @@ -160,7 +165,8 @@ end: SYS_FUNC(sched_setattr) { if (entering(tcp)) { - tprintf("%d, ", (int) tcp->u_arg[0]); + printpid(tcp, (int) tcp->u_arg[0], PT_TGID); + tprints(", "); print_sched_attr(tcp, tcp->u_arg[1], 0); } else { struct sched_attr attr; @@ -179,7 +185,8 @@ SYS_FUNC(sched_setattr) SYS_FUNC(sched_getattr) { if (entering(tcp)) { - tprintf("%d, ", (int) tcp->u_arg[0]); + printpid(tcp, (int) tcp->u_arg[0], PT_TGID); + tprints(", "); } else { const unsigned int size = tcp->u_arg[2]; diff --git a/signal.c b/signal.c index d5d59105..510b8992 100644 --- a/signal.c +++ b/signal.c @@ -439,7 +439,8 @@ SYS_FUNC(sigprocmask) SYS_FUNC(kill) { /* pid */ - tprintf("%d, ", (int) tcp->u_arg[0]); + printpid_tgid_pgid(tcp, tcp->u_arg[0]); + tprints(", "); /* signal */ printsignal(tcp->u_arg[1]); @@ -448,7 +449,7 @@ SYS_FUNC(kill) SYS_FUNC(tkill) { - tprintf("%d", (int) tcp->u_arg[0]); + printpid(tcp, (int) tcp->u_arg[0], PT_TID); tprints(", "); printsignal(tcp->u_arg[1]); @@ -457,8 +458,12 @@ SYS_FUNC(tkill) SYS_FUNC(tgkill) { - /* tgid, tid */ - tprintf("%d, %d, ", (int) tcp->u_arg[0], (int) tcp->u_arg[1]); + /* tgid */ + printpid(tcp, (int) tcp->u_arg[0], PT_TGID); + tprints(", "); + /* tid */ + printpid(tcp, (int) tcp->u_arg[1], PT_TID); + tprints(", "); /* signal */ printsignal(tcp->u_arg[2]); @@ -624,7 +629,8 @@ print_sigqueueinfo(struct tcb *const tcp, const int sig, SYS_FUNC(rt_sigqueueinfo) { - tprintf("%d, ", (int) tcp->u_arg[0]); + printpid(tcp, (int) tcp->u_arg[0], PT_TGID); + tprints(", "); print_sigqueueinfo(tcp, tcp->u_arg[1], tcp->u_arg[2]); return RVAL_DECODED; @@ -632,7 +638,10 @@ SYS_FUNC(rt_sigqueueinfo) SYS_FUNC(rt_tgsigqueueinfo) { - tprintf("%d, %d, ", (int) tcp->u_arg[0], (int) tcp->u_arg[1]); + printpid(tcp, (int) tcp->u_arg[0], PT_TGID); + tprints(", "); + printpid(tcp, (int) tcp->u_arg[1], PT_TID); + tprints(", "); print_sigqueueinfo(tcp, tcp->u_arg[2], tcp->u_arg[3]); return RVAL_DECODED; diff --git a/sockaddr.c b/sockaddr.c index b0046331..fb8887c2 100644 --- a/sockaddr.c +++ b/sockaddr.c @@ -416,7 +416,7 @@ print_sockaddr_data_nl(struct tcb *tcp, const void *const buf, const int addrlen { const struct sockaddr_nl *const sa_nl = buf; - PRINT_FIELD_D("", *sa_nl, nl_pid); + PRINT_FIELD_TGID("", *sa_nl, nl_pid, tcp); PRINT_FIELD_0X(", ", *sa_nl, nl_groups); } diff --git a/tests/kcmp.c b/tests/kcmp.c index a46da0ed..dc5ba9a4 100644 --- a/tests/kcmp.c +++ b/tests/kcmp.c @@ -64,7 +64,26 @@ static const char zero_path[] = "/dev/zero"; static void printpidfd(const char *prefix, pid_t pid, unsigned fd) { - printf("%s%d", prefix, fd); + const char *path = NULL; + +# if VERBOSE_FD + if (pid == getpid()) { + switch (fd) + { + case NULL_FD: + path = null_path; + break; + case ZERO_FD: + path = zero_path; + break; + } + } +# endif + + if (path) + printf("%s%d<%s>", prefix, fd, path); + else + printf("%s%d", prefix, fd); } /* @@ -179,7 +198,7 @@ main(void) /* KCMP_FILE is the only type which has additional args */ do_kcmp(3141592653U, 2718281828U, ARG_STR(KCMP_FILE), bogus_idx1, bogus_idx2); - do_kcmp(-1, -1, ARG_STR(KCMP_FILE), NULL_FD, ZERO_FD); + do_kcmp(getpid(), getpid(), ARG_STR(KCMP_FILE), NULL_FD, ZERO_FD); /* Types without additional args */ do_kcmp(-1, -1, ARG_STR(KCMP_VM), bogus_idx1, bogus_idx2); @@ -198,7 +217,7 @@ main(void) for (i = 0; i < ARRAY_SIZE(slot_data); i++) { memcpy(slot, slot_data + i, sizeof(*slot)); - do_kcmp(getpid(), getppid(), ARG_STR(KCMP_EPOLL_TFD), NULL_FD, + do_kcmp(getpid(), -1, ARG_STR(KCMP_EPOLL_TFD), NULL_FD, (uintptr_t) slot, 1); } diff --git a/util.c b/util.c index 286c6903..094e5818 100644 --- a/util.c +++ b/util.c @@ -392,6 +392,18 @@ printnum_fd(struct tcb *const tcp, const kernel_ulong_t addr) return true; } +bool +printnum_pid(struct tcb *const tcp, const kernel_ulong_t addr, enum pid_type type) +{ + int pid; + if (umove_or_printaddr(tcp, addr, &pid)) + return false; + tprints("["); + printpid(tcp, pid, type); + tprints("]"); + return true; +} + /** * Prints time to a (static internal) buffer and returns pointer to it. * Returns NULL if the provided time specification is not correct. @@ -641,12 +653,8 @@ printed: void printfd_pid_tracee_ns(struct tcb *tcp, pid_t pid, int fd) { - /* - * TODO: We want to have the same formatting as printfd here, - * but we should figure out first which process in strace's - * PID NS is referred to by pid in tracee's PID NS. - */ - tprintf("%d", fd); + int strace_pid = translate_pid(tcp, pid, PT_TGID, NULL); + printfd_pid(tcp, strace_pid, fd); } /* diff --git a/wait.c b/wait.c index 2b9f9807..997a711a 100644 --- a/wait.c +++ b/wait.c @@ -80,14 +80,8 @@ printwaitn(struct tcb *const tcp, void (*const print_rusage)(struct tcb *, kernel_ulong_t)) { if (entering(tcp)) { - /* On Linux, kernel-side pid_t is typedef'ed to int - * on all arches. Also, glibc-2.8 truncates wait3 and wait4 - * pid argument to int on 64bit arches, producing, - * for example, wait4(4294967295, ...) instead of -1 - * in strace. We have to use int here, not long. - */ - int pid = tcp->u_arg[0]; - tprintf("%d, ", pid); + printpid_tgid_pgid(tcp, tcp->u_arg[0]); + tprintf(", "); } else { int status; @@ -108,7 +102,7 @@ printwaitn(struct tcb *const tcp, printaddr(tcp->u_arg[3]); } } - return 0; + return RVAL_TGID; } SYS_FUNC(waitpid) @@ -134,10 +128,28 @@ SYS_FUNC(osf_wait4) SYS_FUNC(waitid) { + unsigned int idtype = (unsigned int) tcp->u_arg[0]; + int id = (int) tcp->u_arg[1]; + if (entering(tcp)) { - printxval(waitid_types, tcp->u_arg[0], "P_???"); - int pid = tcp->u_arg[1]; - tprintf(", %d, ", pid); + printxval(waitid_types, idtype, "P_???"); + tprints(", "); + switch (idtype) + { + case P_PID: + printpid(tcp, id, PT_TGID); + break; + case P_PIDFD: + printfd(tcp, id); + break; + case P_PGID: + printpid(tcp, id, PT_PGID); + break; + default: + tprintf("%d", id); + break; + } + tprints(", "); } else { /* siginfo */ printsiginfo_at(tcp, tcp->u_arg[2]); -- 2.27.0 From uzonyi.akos at gmail.com Thu Aug 6 19:02:11 2020 From: uzonyi.akos at gmail.com (=?UTF-8?q?=C3=81kos=20Uzonyi?=) Date: Thu, 6 Aug 2020 21:02:11 +0200 Subject: [PATCH v6 5/5] Add tests for PID namespace translation In-Reply-To: <20200806190211.118721-1-uzonyi.akos@gmail.com> References: <20200806190211.118721-1-uzonyi.akos@gmail.com> Message-ID: <20200806190211.118721-6-uzonyi.akos@gmail.com> * tests/.gitignore: Add new test executables. * tests/Makefile.am (check_PROGRAMS): Add new test executables. (DECODER_TESTS) Add new test files. * tests/gen_tests.in: Add new tests. * tests/fcntl-Y.c: New file. * tests/fcntl64-Y.c: New file. * tests/fork-Y.awk: New file. * tests/fork-Y.c: New file. * tests/fork-Y.test: New file. * tests/getpgrp-Y.c: New file. * tests/getpid-Y.c: New file. * tests/getsid-Y.c: New file. * tests/gettid-Y.c: New file. * tests/ioctl_block-Y.c: New file. * tests/ioctl_block-Y.test: New file. * tests/ioprio-Y.c: New file. * tests/kill-Y.c: New file. * tests/migrate_pages-Y.c: New file. * tests/move_pages-Y.c: New file. * tests/net-sockaddr-Y.c: New file. * tests/netlink_audit-Y.c: New file. * tests/netlink_audit-Y.test: New file. * tests/pidfd_open-Y.c: New file. * tests/pidfd_send_signal-Y.c: New file. * tests/prlimit64-Y.c: New file. * tests/process_vm_readv-Y.c: New file. * tests/process_vm_writev-Y.c: New file. * tests/rt_sigqueueinfo-Y.c: New file. * tests/rt_tgsigqueueinfo-Y.c: New file. * tests/sched_xetaffinity-Y.c: New file. * tests/sched_xetattr-Y.c: New file. * tests/sched_xetparam-Y.c: New file. * tests/sched_xetscheduler-Y.c: New file. * tests/signal_receive-Y.c: New file. * tests/so_peercred-Y.c: New file. * tests/xet_robust_list-Y.c: New file. * tests/xetpgid-Y.c: New file. * tests/xetpriority-Y.c: New file. * tests/fcntl-common.c: Print PID translation string after PIDs. * tests/fcntl.c: Likewise. * tests/fcntl64.c: Likewise. * tests/getpgrp.c: Likewise. * tests/getpid.c: Likewise. * tests/getsid.c: Likewise. * tests/gettid.c: Likewise. * tests/ioctl_block.c: Likewise. * tests/ioprio.c: Likewise. * tests/kcmp.c: Likewise. * tests/kill.c: Likewise. * tests/migrate_pages.c: Likewise. * tests/move_pages.c: Likewise. * tests/net-sockaddr.c: Likewise. * tests/netlink_audit.c: Likewise. * tests/pidfd_open.c: Likewise. * tests/pidfd_send_signal.c: Likewise. * tests/prlimit64.c: Likewise. * tests/process_vm_readv_writev.c: Likewise. * tests/rt_sigqueueinfo.c: Likewise. * tests/rt_tgsigqueueinfo.c: Likewise. * tests/sched_xetaffinity.c: Likewise. * tests/sched_xetattr.c: Likewise. * tests/sched_xetparam.c: Likewise. * tests/sched_xetscheduler.c: Likewise. * tests/signal_receive.c: Likewise. * tests/so_peercred.c: Likewise. * tests/xet_robust_list.c: Likewise. * tests/xetpgid.c: Likewise. * tests/xetpriority.c: Likewise. --- tests/.gitignore | 31 +++++++ tests/Makefile.am | 35 ++++++++ tests/fcntl--pidns-translation.c | 2 + tests/fcntl-common.c | 82 ++++++++++++++----- tests/fcntl.c | 1 + tests/fcntl64--pidns-translation.c | 2 + tests/fcntl64.c | 3 + tests/fork--pidns-translation.awk | 15 ++++ tests/fork--pidns-translation.c | 69 ++++++++++++++++ tests/fork--pidns-translation.test | 16 ++++ tests/gen_tests.in | 30 ++++++- tests/getpgrp--pidns-translation.c | 2 + tests/getpgrp.c | 8 +- tests/getpid--pidns-translation.c | 2 + tests/getpid.c | 8 +- tests/getsid--pidns-translation.c | 2 + tests/getsid.c | 9 +- tests/gettid--pidns-translation.c | 2 + tests/gettid.c | 8 +- tests/ioctl_block--pidns-translation.c | 2 + tests/ioctl_block--pidns-translation.test | 24 ++++++ tests/ioctl_block.c | 24 +++++- tests/ioprio--pidns-translation.c | 2 + tests/ioprio.c | 54 ++++++++---- tests/kcmp-y--pidns-translation.c | 2 + tests/kcmp.c | 11 ++- tests/kill--pidns-translation.c | 2 + tests/kill.c | 12 ++- tests/migrate_pages--pidns-translation.c | 2 + tests/migrate_pages.c | 17 +++- tests/move_pages--pidns-translation.c | 2 + tests/move_pages.c | 51 +++++++----- tests/net-sockaddr--pidns-translation.c | 2 + tests/net-sockaddr.c | 66 +++++++++++++-- tests/netlink_audit--pidns-translation.c | 2 + tests/netlink_audit--pidns-translation.test | 13 +++ tests/netlink_audit.c | 11 ++- tests/pidfd_open--pidns-translation.c | 2 + tests/pidfd_open.c | 21 +++-- tests/pidfd_send_signal--pidns-translation.c | 2 + tests/pidfd_send_signal.c | 13 ++- tests/prlimit64--pidns-translation.c | 2 + tests/prlimit64.c | 17 +++- tests/process_vm_readv--pidns-translation.c | 2 + tests/process_vm_readv_writev.c | 27 +++--- tests/process_vm_writev--pidns-translation.c | 2 + tests/rt_sigqueueinfo--pidns-translation.c | 2 + tests/rt_sigqueueinfo.c | 15 +++- tests/rt_tgsigqueueinfo--pidns-translation.c | 2 + tests/rt_tgsigqueueinfo.c | 26 ++++-- tests/sched_xetaffinity--pidns-translation.c | 2 + tests/sched_xetaffinity.c | 31 ++++--- tests/sched_xetattr--pidns-translation.c | 2 + tests/sched_xetattr.c | 47 ++++++++++- tests/sched_xetparam--pidns-translation.c | 2 + tests/sched_xetparam.c | 20 +++-- tests/sched_xetscheduler--pidns-translation.c | 2 + tests/sched_xetscheduler.c | 44 ++++++---- tests/signal_receive--pidns-translation.c | 2 + tests/signal_receive.c | 22 +++-- tests/so_peercred--pidns-translation.c | 2 + tests/so_peercred.c | 22 +++++ tests/xet_robust_list--pidns-translation.c | 2 + tests/xet_robust_list.c | 18 +++- tests/xetpgid--pidns-translation.c | 2 + tests/xetpgid.c | 21 +++-- tests/xetpriority--pidns-translation.c | 2 + tests/xetpriority.c | 20 ++++- 68 files changed, 854 insertions(+), 168 deletions(-) create mode 100644 tests/fcntl--pidns-translation.c create mode 100644 tests/fcntl64--pidns-translation.c create mode 100644 tests/fork--pidns-translation.awk create mode 100644 tests/fork--pidns-translation.c create mode 100755 tests/fork--pidns-translation.test create mode 100644 tests/getpgrp--pidns-translation.c create mode 100644 tests/getpid--pidns-translation.c create mode 100644 tests/getsid--pidns-translation.c create mode 100644 tests/gettid--pidns-translation.c create mode 100644 tests/ioctl_block--pidns-translation.c create mode 100755 tests/ioctl_block--pidns-translation.test create mode 100644 tests/ioprio--pidns-translation.c create mode 100644 tests/kcmp-y--pidns-translation.c create mode 100644 tests/kill--pidns-translation.c create mode 100644 tests/migrate_pages--pidns-translation.c create mode 100644 tests/move_pages--pidns-translation.c create mode 100644 tests/net-sockaddr--pidns-translation.c create mode 100644 tests/netlink_audit--pidns-translation.c create mode 100755 tests/netlink_audit--pidns-translation.test create mode 100644 tests/pidfd_open--pidns-translation.c create mode 100644 tests/pidfd_send_signal--pidns-translation.c create mode 100644 tests/prlimit64--pidns-translation.c create mode 100644 tests/process_vm_readv--pidns-translation.c create mode 100644 tests/process_vm_writev--pidns-translation.c create mode 100644 tests/rt_sigqueueinfo--pidns-translation.c create mode 100644 tests/rt_tgsigqueueinfo--pidns-translation.c create mode 100644 tests/sched_xetaffinity--pidns-translation.c create mode 100644 tests/sched_xetattr--pidns-translation.c create mode 100644 tests/sched_xetparam--pidns-translation.c create mode 100644 tests/sched_xetscheduler--pidns-translation.c create mode 100644 tests/signal_receive--pidns-translation.c create mode 100644 tests/so_peercred--pidns-translation.c create mode 100644 tests/xet_robust_list--pidns-translation.c create mode 100644 tests/xetpgid--pidns-translation.c create mode 100644 tests/xetpriority--pidns-translation.c diff --git a/tests/.gitignore b/tests/.gitignore index 0031d04d..4d1153fc 100644 --- a/tests/.gitignore +++ b/tests/.gitignore @@ -116,7 +116,9 @@ fchown fchown32 fchownat fcntl +fcntl--pidns-translation fcntl64 +fcntl64--pidns-translation fdatasync fflush file_handle @@ -126,6 +128,7 @@ filter-unavailable finit_module flock fork-f +fork--pidns-translation fsconfig fsconfig-P fsmount @@ -168,7 +171,9 @@ getgroups getgroups32 getpeername getpgrp +getpgrp--pidns-translation getpid +getpid--pidns-translation getppid getrandom getresgid @@ -178,8 +183,10 @@ getresuid32 getrlimit getrusage getsid +getsid--pidns-translation getsockname gettid +gettid--pidns-translation getuid getuid32 getxgid @@ -200,6 +207,7 @@ io_uring_register io_uring_setup ioctl ioctl_block +ioctl_block--pidns-translation ioctl_dm ioctl_dm-v ioctl_evdev @@ -275,6 +283,7 @@ ioctl_watchdog ioperm iopl ioprio +ioprio--pidns-translation ioprio-Xabbrev ioprio-Xraw ioprio-Xverbose @@ -299,6 +308,7 @@ ipc_shm-Xverbose is_linux_mips_n64 kcmp kcmp-y +kcmp-y--pidns-translation kern_features kernel_version kernel_version-Xabbrev @@ -311,6 +321,7 @@ keyctl-Xabbrev keyctl-Xraw keyctl-Xverbose kill +kill--pidns-translation kill_child ksysent ksysent.h @@ -340,6 +351,7 @@ memfd_create-Xabbrev memfd_create-Xraw memfd_create-Xverbose migrate_pages +migrate_pages--pidns-translation mincore mkdir mkdirat @@ -371,6 +383,7 @@ move_pages move_pages-Xabbrev move_pages-Xraw move_pages-Xverbose +move_pages--pidns-translation mq mq_sendrecv mq_sendrecv-read @@ -391,6 +404,7 @@ net-packet_mreq-Xabbrev net-packet_mreq-Xraw net-packet_mreq-Xverbose net-sockaddr +net-sockaddr--pidns-translation net-tpacket_req net-tpacket_stats net-tpacket_stats-success @@ -400,6 +414,7 @@ net-yy-inet6 net-yy-netlink net-yy-unix netlink_audit +netlink_audit--pidns-translation netlink_crypto netlink_generic netlink_inet_diag @@ -507,7 +522,9 @@ pidfd_open--decode-fd-socket pidfd_open-P pidfd_open-y pidfd_open-yy +pidfd_open--pidns-translation pidfd_send_signal +pidfd_send_signal--pidns-translation pipe pipe2 pkey_alloc @@ -546,8 +563,11 @@ printstrn-umoven printstrn-umoven-peekdata printstrn-umoven-undumpable prlimit64 +prlimit64--pidns-translation process_vm_readv +process_vm_readv--pidns-translation process_vm_writev +process_vm_writev--pidns-translation pselect6 ptrace ptrace_syscall_info @@ -597,10 +617,12 @@ rt_sigaction rt_sigpending rt_sigprocmask rt_sigqueueinfo +rt_sigqueueinfo--pidns-translation rt_sigreturn rt_sigsuspend rt_sigtimedwait rt_tgsigqueueinfo +rt_tgsigqueueinfo--pidns-translation run_expect_termsig s390_guarded_storage s390_guarded_storage-v @@ -611,9 +633,13 @@ s390_sthyi-v sched_get_priority_mxx sched_rr_get_interval sched_xetaffinity +sched_xetaffinity--pidns-translation sched_xetattr +sched_xetattr--pidns-translation sched_xetparam +sched_xetparam--pidns-translation sched_xetscheduler +sched_xetscheduler--pidns-translation sched_yield scm_rights scno.h @@ -669,6 +695,7 @@ sigaltstack siginfo signal signal_receive +signal_receive--pidns-translation signalfd4 sigpending sigprocmask @@ -681,6 +708,7 @@ so_peercred so_peercred-Xabbrev so_peercred-Xraw so_peercred-Xverbose +so_peercred--pidns-translation sock_filter-v sock_filter-v-Xabbrev sock_filter-v-Xraw @@ -783,9 +811,12 @@ waitpid xattr xattr-strings xet_robust_list +xet_robust_list--pidns-translation xet_thread_area_x86 xetitimer xetpgid +xetpgid--pidns-translation xetpriority +xetpriority--pidns-translation xettimeofday zeroargc diff --git a/tests/Makefile.am b/tests/Makefile.am index 7a583a3a..05e350bd 100644 --- a/tests/Makefile.am +++ b/tests/Makefile.am @@ -109,17 +109,25 @@ check_PROGRAMS = $(PURE_EXECUTABLES) \ delay \ execve-v \ execveat-v \ + fcntl--pidns-translation \ + fcntl64--pidns-translation \ filter_seccomp-flag \ filter_seccomp-perf \ filter-unavailable \ fork-f \ + fork--pidns-translation \ fsync-y \ get_process_reaper \ + getpgrp--pidns-translation \ getpid \ + getpid--pidns-translation \ getppid \ + getsid--pidns-translation \ gettid \ + gettid--pidns-translation \ inject-nf \ int_0x80 \ + ioctl_block--pidns-translation \ ioctl_dm-v \ ioctl_evdev-success \ ioctl_evdev-success-Xabbrev \ @@ -150,18 +158,25 @@ check_PROGRAMS = $(PURE_EXECUTABLES) \ ioctl_v4l2-success-v-Xabbrev \ ioctl_v4l2-success-v-Xraw \ ioctl_v4l2-success-v-Xverbose \ + ioprio--pidns-translation \ is_linux_mips_n64 \ + kcmp-y--pidns-translation \ kill_child \ + kill--pidns-translation \ ksysent \ list_sigaction_signum \ localtime \ looping_threads \ + migrate_pages--pidns-translation \ mmsg-silent \ mmsg_name-v \ + move_pages--pidns-translation \ msg_control-v \ net-accept-connect \ + net-sockaddr--pidns-translation \ net-tpacket_stats-success \ nlattr_ifla_xdp-y \ + netlink_audit--pidns-translation \ netlink_inet_diag \ netlink_netlink_diag \ netlink_unix_diag \ @@ -173,14 +188,19 @@ check_PROGRAMS = $(PURE_EXECUTABLES) \ pc \ perf_event_open_nonverbose \ perf_event_open_unabbrev \ + pidfd_open--pidns-translation \ + pidfd_send_signal--pidns-translation \ poll-P \ ppoll-P \ ppoll-v \ + prlimit64--pidns-translation \ prctl-seccomp-filter-v \ prctl-seccomp-strict \ prctl-spec-inject \ print_maxfd \ print_ppid_tracerpid \ + process_vm_readv--pidns-translation \ + process_vm_writev--pidns-translation \ qual_fault \ qual_inject-error-signal \ qual_inject-retval \ @@ -194,7 +214,13 @@ check_PROGRAMS = $(PURE_EXECUTABLES) \ quotactl-xfs-v \ redirect-fds \ restart_syscall \ + rt_sigqueueinfo--pidns-translation \ + rt_tgsigqueueinfo--pidns-translation \ run_expect_termsig \ + sched_xetaffinity--pidns-translation \ + sched_xetattr--pidns-translation \ + sched_xetparam--pidns-translation \ + sched_xetscheduler--pidns-translation \ scm_rights \ seccomp-filter-v \ seccomp-strict \ @@ -204,12 +230,14 @@ check_PROGRAMS = $(PURE_EXECUTABLES) \ set_sigign \ setpgrp-exec \ signal_receive \ + signal_receive--pidns-translation \ sleep \ stack-fcall \ stack-fcall-attach \ stack-fcall-mangled \ status-none-threads \ status-unfinished-threads \ + so_peercred--pidns-translation \ syslog-success \ threads-execve \ threads-execve--quiet-thread-execve \ @@ -223,6 +251,9 @@ check_PROGRAMS = $(PURE_EXECUTABLES) \ vfork-f \ wait4-v \ waitid-v \ + xetpgid--pidns-translation \ + xetpriority--pidns-translation \ + xet_robust_list--pidns-translation \ zeroargc \ # end of check_PROGRAMS @@ -310,6 +341,7 @@ DECODER_TESTS = \ int_0x80.test \ inotify_init-y.test \ ioctl.test \ + ioctl_block--pidns-translation.test \ ioctl_evdev-success.test \ ipc_msgbuf.test \ kern_features-fault.test \ @@ -381,12 +413,14 @@ MISC_TESTS = \ filtering_fd-syntax.test \ filtering_syscall-syntax.test \ first_exec_failure.test \ + fork--pidns-translation.test \ get_regs.test \ inject-nf.test \ interactive_block.test \ kill_child.test \ localtime.test \ looping_threads.test \ + netlink_audit--pidns-translation.test \ opipe.test \ options-syntax.test \ pc.test \ @@ -467,6 +501,7 @@ EXTRA_DIST = \ filter_seccomp.in \ filter_seccomp.sh \ filter-unavailable.expected \ + fork--pidns-translation.awk \ fstatat.c \ fstatx.c \ gen_pure_executables.sh \ diff --git a/tests/fcntl--pidns-translation.c b/tests/fcntl--pidns-translation.c new file mode 100644 index 00000000..e249424a --- /dev/null +++ b/tests/fcntl--pidns-translation.c @@ -0,0 +1,2 @@ +#define PIDNS_TRANSLATION +#include "fcntl.c" diff --git a/tests/fcntl-common.c b/tests/fcntl-common.c index 27694326..d9e29939 100644 --- a/tests/fcntl-common.c +++ b/tests/fcntl-common.c @@ -13,6 +13,8 @@ #include #include #include "flock.h" +#include "pidns.h" +#include "scno.h" #define FILE_LEN 4096 @@ -48,12 +50,14 @@ test_flock_einval(const int cmd, const char *name) fl->l_len = (TYPEOF_FLOCK_OFF_T) 0xdefaced2cafef00dULL; invoke_test_syscall(0, cmd, fl); + pidns_print_leader(); printf("%s(0, %s, {l_type=F_RDLCK, l_whence=SEEK_SET" ", l_start=%jd, l_len=%jd}) = %s\n", TEST_SYSCALL_STR, name, (intmax_t) fl->l_start, (intmax_t) fl->l_len, errstr); void *const bad_addr = (void *) fl + 1; invoke_test_syscall(0, cmd, bad_addr); + pidns_print_leader(); printf("%s(0, %s, %p) = %s\n", TEST_SYSCALL_STR, name, bad_addr, errstr); } @@ -72,12 +76,14 @@ test_flock64_einval(const int cmd, const char *name) fl->l_len = (TYPEOF_FLOCK_OFF_T) 0xdefaced2cafef00dULL; invoke_test_syscall(0, cmd, fl); + pidns_print_leader(); printf("%s(0, %s, {l_type=F_RDLCK, l_whence=SEEK_SET" ", l_start=%jd, l_len=%jd}) = %s\n", TEST_SYSCALL_STR, name, (intmax_t) fl->l_start, (intmax_t) fl->l_len, errstr); void *const bad_addr = (void *) fl + 1; invoke_test_syscall(0, cmd, bad_addr); + pidns_print_leader(); printf("%s(0, %s, %p) = %s\n", TEST_SYSCALL_STR, name, bad_addr, errstr); } @@ -94,6 +100,7 @@ test_flock(void) fl->l_len = FILE_LEN; long rc = invoke_test_syscall(0, F_SETLK, fl); + pidns_print_leader(); printf("%s(0, F_SETLK, {l_type=F_RDLCK, l_whence=SEEK_SET" ", l_start=0, l_len=%d}) = %s\n", TEST_SYSCALL_STR, FILE_LEN, errstr); @@ -101,11 +108,13 @@ test_flock(void) return; invoke_test_syscall(0, F_GETLK, fl); + pidns_print_leader(); printf("%s(0, F_GETLK, {l_type=F_UNLCK, l_whence=SEEK_SET" ", l_start=0, l_len=%d, l_pid=0}) = 0\n", TEST_SYSCALL_STR, FILE_LEN); invoke_test_syscall(0, F_SETLKW, fl); + pidns_print_leader(); printf("%s(0, F_SETLKW, {l_type=F_UNLCK, l_whence=SEEK_SET" ", l_start=0, l_len=%d}) = 0\n", TEST_SYSCALL_STR, FILE_LEN); @@ -124,6 +133,7 @@ test_flock64_ofd(void) fl->l_len = FILE_LEN; long rc = invoke_test_syscall(0, F_OFD_SETLK, fl); + pidns_print_leader(); printf("%s(0, F_OFD_SETLK, {l_type=F_RDLCK, l_whence=SEEK_SET" ", l_start=0, l_len=%d}) = %s\n", TEST_SYSCALL_STR, FILE_LEN, errstr); @@ -131,11 +141,13 @@ test_flock64_ofd(void) return; invoke_test_syscall(0, F_OFD_GETLK, fl); + pidns_print_leader(); printf("%s(0, F_OFD_GETLK, {l_type=F_UNLCK, l_whence=SEEK_SET" ", l_start=0, l_len=%d, l_pid=0}) = 0\n", TEST_SYSCALL_STR, FILE_LEN); invoke_test_syscall(0, F_OFD_SETLKW, fl); + pidns_print_leader(); printf("%s(0, F_OFD_SETLKW, {l_type=F_UNLCK, l_whence=SEEK_SET" ", l_start=0, l_len=%d}) = 0\n", TEST_SYSCALL_STR, FILE_LEN); @@ -167,18 +179,21 @@ test_flock64(void) static long test_f_owner_ex_type_pid(const int cmd, const char *const cmd_name, const int type, const char *const type_name, - pid_t pid) + enum pid_type pid_type, pid_t pid) { TAIL_ALLOC_OBJECT_CONST_PTR(struct_kernel_f_owner_ex, fo); fo->type = type; fo->pid = pid; long rc = invoke_test_syscall(0, cmd, fo); - printf("%s(0, %s, {type=%s, pid=%d}) = %s\n", - TEST_SYSCALL_STR, cmd_name, type_name, fo->pid, errstr); + pidns_print_leader(); + printf("%s(0, %s, {type=%s, pid=%d%s}) = %s\n", + TEST_SYSCALL_STR, cmd_name, type_name, + fo->pid, pidns_pid2str(pid_type), errstr); void *bad_addr = (void *) fo + 1; invoke_test_syscall(0, cmd, bad_addr); + pidns_print_leader(); printf("%s(0, %s, %p) = %s\n", TEST_SYSCALL_STR, cmd_name, bad_addr, errstr); @@ -187,35 +202,39 @@ test_f_owner_ex_type_pid(const int cmd, const char *const cmd_name, static void test_f_owner_ex_umove_or_printaddr(const int type, const char *const type_name, - pid_t pid) + enum pid_type pid_type, pid_t pid) { long rc = test_f_owner_ex_type_pid(ARG_STR(F_SETOWN_EX), - type, type_name, pid); + type, type_name, pid_type, pid); if (!rc) test_f_owner_ex_type_pid(ARG_STR(F_GETOWN_EX), - type, type_name, pid); + type, type_name, pid_type, pid); } static void test_f_owner_ex(void) { - static const struct { + struct { int type; const char *type_name; - pid_t pid[2]; + enum pid_type pid_type; + pid_t pid; } a[] = { - { ARG_STR(F_OWNER_TID), { 1234567890, 20 } }, - { ARG_STR(F_OWNER_PID), { 1298126790, 30 } }, - { ARG_STR(F_OWNER_PGRP), { 1294567890, 40 } } + { ARG_STR(F_OWNER_TID), PT_NONE, 1234567890 }, + { ARG_STR(F_OWNER_PID), PT_NONE, 1234567890 }, + { ARG_STR(F_OWNER_PGRP), PT_NONE, 1234567890 }, + { ARG_STR(F_OWNER_TID), PT_TID, 0 }, + { ARG_STR(F_OWNER_PID), PT_TGID, 0 }, + { ARG_STR(F_OWNER_PGRP), PT_PGID, 0 }, }; - for (unsigned int i = 0; i < ARRAY_SIZE(a); i++) { - for (unsigned int j = 0; j < ARRAY_SIZE(a[0].pid); j++) { - test_f_owner_ex_umove_or_printaddr(a[i].type, - a[i].type_name, - a[i].pid[j]); - } - } + a[3].pid = syscall(__NR_gettid); + a[4].pid = getpid(); + a[5].pid = getpgid(0); + + for (unsigned int i = 0; i < ARRAY_SIZE(a); i++) + test_f_owner_ex_umove_or_printaddr(a[i].type, a[i].type_name, + a[i].pid_type, a[i].pid); } #endif /* TEST_F_OWNER_EX */ @@ -228,6 +247,23 @@ struct fcntl_cmd_check { void (*print_flags)(long rc); }; +static void +test_xetown(void) +{ + const int pid = getpid(); + const char *pid_str = pidns_pid2str(PT_TGID); + + invoke_test_syscall(0, F_SETOWN, (void *) (intptr_t) pid); + pidns_print_leader(); + printf("%s(0, F_SETOWN, %d%s) = %s\n", + TEST_SYSCALL_STR, pid, pid_str, errstr); + + invoke_test_syscall(0, F_GETOWN, NULL); + pidns_print_leader(); + printf("%s(0, F_GETOWN) = %d%s\n", + TEST_SYSCALL_STR, pid, pid_str); +} + static void print_retval_flags(const struct fcntl_cmd_check *check, long rc) { @@ -243,12 +279,14 @@ static void test_other_set_cmd(const struct fcntl_cmd_check *check) { invoke_test_syscall(check->fd, check->cmd, (void *) check->arg); + pidns_print_leader(); printf("%s(%d, %s, %s) = %s\n", TEST_SYSCALL_STR, check->fd, check->cmd_str, check->arg_str, errstr); /* bad file fd */ invoke_test_syscall(-1, check->cmd, (void *) check->arg); + pidns_print_leader(); printf("%s(-1, %s, %s) = %s\n", TEST_SYSCALL_STR, check->cmd_str, check->arg_str, errstr); @@ -258,12 +296,14 @@ static void test_other_get_cmd(const struct fcntl_cmd_check *check) { long rc = invoke_test_syscall(check->fd, check->cmd, NULL); + pidns_print_leader(); printf("%s(%d, %s) = ", TEST_SYSCALL_STR, check->fd, check->cmd_str); print_retval_flags(check, rc); /* bad file fd */ invoke_test_syscall(-1, check->cmd, NULL); + pidns_print_leader(); printf("%s(-1, %s) = %s\n", TEST_SYSCALL_STR, check->cmd_str, errstr); } @@ -315,7 +355,6 @@ test_fcntl_others(void) { static const struct fcntl_cmd_check set_checks[] = { { 0, ARG_STR(F_SETFD), ARG_STR(FD_CLOEXEC) }, - { 0, ARG_STR(F_SETOWN), ARG_STR(20) }, #ifdef F_SETPIPE_SZ { 0, ARG_STR(F_SETPIPE_SZ), ARG_STR(4097) }, #endif @@ -336,7 +375,6 @@ test_fcntl_others(void) static const struct fcntl_cmd_check get_checks[] = { { 0, ARG_STR(F_GETFD), .print_flags = print_flags_getfd }, { 1, ARG_STR(F_GETFD), .print_flags = print_flags_getfd }, - { 0, ARG_STR(F_GETOWN) }, #ifdef F_GETPIPE_SZ { 0, ARG_STR(F_GETPIPE_SZ) }, #endif @@ -360,6 +398,8 @@ create_sample(void) int main(void) { + PIDNS_TEST_INIT; + create_sample(); test_flock(); test_flock64(); @@ -367,7 +407,9 @@ main(void) test_f_owner_ex(); #endif test_fcntl_others(); + test_xetown(); + pidns_print_leader(); puts("+++ exited with 0 +++"); return 0; } diff --git a/tests/fcntl.c b/tests/fcntl.c index f38b8afb..673c06e4 100644 --- a/tests/fcntl.c +++ b/tests/fcntl.c @@ -24,6 +24,7 @@ test_flock64_undecoded(const int cmd, const char *name) .l_len = 0xdefaced2cafef00dULL }; invoke_test_syscall(0, cmd, &fl); + pidns_print_leader(); printf("%s(0, %s, %p) = %s\n", TEST_SYSCALL_STR, name, &fl, errstr); } diff --git a/tests/fcntl64--pidns-translation.c b/tests/fcntl64--pidns-translation.c new file mode 100644 index 00000000..c6fdadd1 --- /dev/null +++ b/tests/fcntl64--pidns-translation.c @@ -0,0 +1,2 @@ +#define PIDNS_TRANSLATION +#include "fcntl64.c" diff --git a/tests/fcntl64.c b/tests/fcntl64.c index 78e53b0d..f7b3f2fb 100644 --- a/tests/fcntl64.c +++ b/tests/fcntl64.c @@ -27,6 +27,7 @@ test_flock64_lk64(void) fl->l_len = FILE_LEN; long rc = invoke_test_syscall(0, F_SETLK64, fl); + pidns_print_leader(); printf("%s(0, F_SETLK64, {l_type=F_RDLCK, l_whence=SEEK_SET" ", l_start=0, l_len=%d}) = %s\n", TEST_SYSCALL_STR, FILE_LEN, errstr); @@ -35,11 +36,13 @@ test_flock64_lk64(void) return; invoke_test_syscall(0, F_GETLK64, fl); + pidns_print_leader(); printf("%s(0, F_GETLK64, {l_type=F_UNLCK, l_whence=SEEK_SET" ", l_start=0, l_len=%d, l_pid=0}) = 0\n", TEST_SYSCALL_STR, FILE_LEN); invoke_test_syscall(0, F_SETLKW64, fl); + pidns_print_leader(); printf("%s(0, F_SETLKW64, {l_type=F_UNLCK, l_whence=SEEK_SET" ", l_start=0, l_len=%d}) = 0\n", TEST_SYSCALL_STR, FILE_LEN); diff --git a/tests/fork--pidns-translation.awk b/tests/fork--pidns-translation.awk new file mode 100644 index 00000000..ef6858f4 --- /dev/null +++ b/tests/fork--pidns-translation.awk @@ -0,0 +1,15 @@ +/fork/ { + match($0, "([0-9]+) in strace\x27s PID NS", a); + if (a[1]) + fork_pid = a[1] +} + +/exited with 0/ { + if (!exit_pid) + exit_pid = $1 +} + +END { + if (!fork_pid || !exit_pid || fork_pid != exit_pid) + exit 1 +} diff --git a/tests/fork--pidns-translation.c b/tests/fork--pidns-translation.c new file mode 100644 index 00000000..73c39d5d --- /dev/null +++ b/tests/fork--pidns-translation.c @@ -0,0 +1,69 @@ +/* + * Test PID namespace translation + * + * Copyright (c) 2020 ?kos Uzonyi + * All rights reserved. + * + * SPDX-License-Identifier: LGPL-2.1-or-later + */ + +#include "tests.h" +#include "scno.h" +#include "pidns.h" + +#ifdef __NR_fork + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +static int +fork_chain(int depth) +{ + if (!depth) + return 0; + + int pid = syscall(__NR_fork); + if (pid < 0) + return errno; + + if (!pid) + _exit(fork_chain(depth - 1)); + + int status; + if (wait(&status) < 0) + return errno; + + if (!WIFEXITED(status)) + return -1; + + return WEXITSTATUS(status); +} + +int main(void) +{ + check_ns_ioctl(); + + if (unshare(CLONE_NEWPID | CLONE_NEWUSER) < 0) { + if (errno == EPERM) + perror_msg_and_skip("unshare"); + + perror_msg_and_fail("unshare"); + } + + errno = fork_chain(2); + if (errno) + perror("fork_chain"); +} + +#else + +SKIP_MAIN_UNDEFINED("__NR_fork") + +#endif diff --git a/tests/fork--pidns-translation.test b/tests/fork--pidns-translation.test new file mode 100755 index 00000000..fa7ecda5 --- /dev/null +++ b/tests/fork--pidns-translation.test @@ -0,0 +1,16 @@ +#!/bin/sh +# +# Check pidns translation of fork's return value. +# +# Copyright (c) 2020 The strace developers. +# All rights reserved. +# +# SPDX-License-Identifier: LGPL-2.1-or-later + +. "${srcdir=.}/init.sh" + +require_min_kernel_version_or_skip 4.9 + +run_prog +run_strace -a6 --pidns-translation -f -e trace=fork $args +match_awk diff --git a/tests/gen_tests.in b/tests/gen_tests.in index 6f8e1420..56e5b5e1 100644 --- a/tests/gen_tests.in +++ b/tests/gen_tests.in @@ -93,7 +93,9 @@ fchown -a16 fchown32 -a18 fchownat fcntl -a8 +fcntl--pidns-translation test_pidns -a8 -e trace=fcntl fcntl64 -a8 +fcntl64--pidns-translation test_pidns -a8 -e trace=fcntl64 fdatasync -a14 file_handle -e trace=name_to_handle_at,open_by_handle_at file_ioctl +ioctl.test @@ -147,7 +149,9 @@ getgroups -a17 getgroups32 -a19 getpeername -a27 getpgrp -a10 +getpgrp--pidns-translation test_pidns -e trace=getpgrp -a10 getpid -a9 +getpid--pidns-translation test_pidns -e trace=getpid -a9 getppid -a10 getrandom -a32 -s3 getresgid -a25 @@ -157,8 +161,10 @@ getresuid32 -a27 getrlimit -a27 getrusage -v getsid -a10 +getsid--pidns-translation test_pidns -e trace=getsid -a10 getsockname -a27 gettid -a9 +gettid--pidns-translation test_pidns -e trace=gettid -a9 getuid-creds +getuid.test getuid32 +getuid.test getuid32-creds +getuid.test @@ -250,6 +256,7 @@ ioctl_watchdog +ioctl.test ioperm -a27 iopl -a8 ioprio -a18 -e trace=ioprio_get,ioprio_set +ioprio--pidns-translation test_pidns -a18 -e trace=ioprio_get,ioprio_set ioprio-Xabbrev -a18 -e trace=ioprio_get,ioprio_set -Xabbrev ioprio-Xraw -a18 -e trace=ioprio_get,ioprio_set -Xraw ioprio-Xverbose -a18 -e trace=ioprio_get,ioprio_set -Xverbose @@ -272,6 +279,7 @@ ipc_shm-Xraw +ipc.sh -Xraw -a19 ipc_shm-Xverbose +ipc.sh -Xverbose -a34 kcmp -a22 kcmp-y -a22 -y -e trace=kcmp +kcmp-y--pidns-translation test_pidns -a22 -y -e trace=kcmp kern_features -a16 kernel_version -a16 -v -e trace=bpf kernel_version-Xabbrev -a16 -Xabbrev -v -e trace=bpf @@ -284,6 +292,7 @@ keyctl-Xabbrev -a31 -s10 -e trace=keyctl -Xabbrev keyctl-Xraw -a13 -s10 -e trace=keyctl -Xraw keyctl-Xverbose -a41 -s10 -e trace=keyctl -Xverbose kill -a12 -esignal=none +kill--pidns-translation test_pidns -a12 -e trace=kill -esignal=none ksysent ../$NAME lchown -a30 lchown32 -a32 @@ -305,6 +314,7 @@ memfd_create-Xabbrev -Xabbrev -e trace=memfd_create memfd_create-Xraw -a30 -Xraw -e trace=memfd_create memfd_create-Xverbose -Xverbose -e trace=memfd_create migrate_pages -a33 +migrate_pages--pidns-translation test_pidns -a33 -e trace=migrate_pages mincore -a22 mkdir -a20 mkdirat -a28 @@ -335,6 +345,7 @@ move_pages -s3 move_pages-Xabbrev -s3 -e trace=move_pages -Xabbrev move_pages-Xraw -s3 -a36 -e trace=move_pages -Xraw move_pages-Xverbose -s3 -e trace=move_pages -Xverbose +move_pages--pidns-translation test_pidns -s3 -e trace=move_pages mq -a32 -e trace=mq_getsetattr,mq_open,mq_unlink mq_sendrecv -a14 -e trace=mq_open,mq_notify,mq_timedsend,mq_timedreceive,mq_unlink mq_sendrecv-read -eread=0 -a14 -e trace=mq_open,mq_notify,mq_timedsend,mq_timedreceive,mq_unlink @@ -354,6 +365,7 @@ net-packet_mreq-Xabbrev -e trace=setsockopt -Xabbrev net-packet_mreq-Xraw -e trace=setsockopt -Xraw net-packet_mreq-Xverbose -e trace=setsockopt -Xverbose net-sockaddr -a24 -e trace=connect +net-sockaddr--pidns-translation test_pidns -a24 -e trace=connect net-tpacket_req -e trace=setsockopt net-tpacket_stats -e trace=getsockopt net-yy-inet6 +net-yy-inet.test @@ -457,7 +469,9 @@ pidfd_open--decode-fd-socket -a17 -e decode-fd=socket -e trace=pidfd_open pidfd_open-P -a17 -P /dev/full -e trace=pidfd_open pidfd_open-y -a17 -y -e trace=pidfd_open pidfd_open-yy -a17 -yy -e trace=pidfd_open +pidfd_open--pidns-translation test_pidns -a17 -e trace=pidfd_open pidfd_send_signal +pidfd_send_signal--pidns-translation test_pidns -e trace=pidfd_send_signal pipe2 -a15 pkey_alloc -a17 pkey_free -a13 @@ -480,8 +494,11 @@ printstrn-umoven -s4096 -e signal=none -e trace=add_key printstrn-umoven-peekdata -e signal=none -e trace=add_key printstrn-umoven-undumpable -e signal=none -e trace=add_key prlimit64 +prlimit64--pidns-translation test_pidns -e trace=prlimit64 process_vm_readv -s5 -a37 +process_vm_readv--pidns-translation test_pidns -s5 -a37 -e trace=process_vm_readv process_vm_writev -s5 -a38 +process_vm_writev--pidns-translation test_pidns -s5 -a38 -e trace=process_vm_writev pselect6 ptrace -a23 -e signal=none ptrace_syscall_info -a35 -e signal=none -e trace=ptrace @@ -518,10 +535,12 @@ rmdir -a22 rt_sigpending -a20 rt_sigprocmask rt_sigqueueinfo -esignal=none +rt_sigqueueinfo--pidns-translation test_pidns -esignal=none -e trace=rt_sigqueueinfo rt_sigreturn -esignal='!USR1' rt_sigsuspend -a20 -esignal=none rt_sigtimedwait -a38 rt_tgsigqueueinfo -esignal=none +rt_tgsigqueueinfo--pidns-translation test_pidns -esignal=none -e trace=rt_tgsigqueueinfo s390_guarded_storage -a32 s390_guarded_storage-v -e trace=s390_guarded_storage -a32 -v s390_pci_mmio_read_write -e trace=s390_pci_mmio_read,s390_pci_mmio_write -a30 @@ -532,9 +551,13 @@ sched test_trace_expr times -e/sched sched_get_priority_mxx -a33 -e trace=sched_get_priority_min,sched_get_priority_max sched_rr_get_interval -a31 sched_xetaffinity -a28 -e trace=sched_getaffinity,sched_setaffinity +sched_xetaffinity--pidns-translation test_pidns -a28 -e trace=sched_getaffinity,sched_setaffinity sched_xetattr -a29 -e trace=sched_getattr,sched_setattr +sched_xetattr--pidns-translation test_pidns -a29 -e trace=sched_getattr,sched_setattr sched_xetparam -a23 -e trace=sched_getparam,sched_setparam +sched_xetparam--pidns-translation test_pidns -a23 -e trace=sched_getparam,sched_setparam sched_xetscheduler -a22 -e trace=sched_getscheduler,sched_setscheduler +sched_xetscheduler--pidns-translation test_pidns -a22 -e trace=sched_getscheduler,sched_setscheduler sched_yield -a14 seccomp-filter -e trace=seccomp seccomp-filter-v -v -e trace=seccomp @@ -581,6 +604,7 @@ sigaction -a31 siginfo -e trace=none signal -a25 -e signal=none -e trace='/^signal$' signal_receive -a16 -e trace=kill +signal_receive--pidns-translation test_pidns -a16 -e trace=kill signalfd4 sigpending -a15 sigprocmask -a34 @@ -592,6 +616,7 @@ so_peercred -e trace=getsockopt so_peercred-Xabbrev -e trace=getsockopt -Xabbrev so_peercred-Xraw -e trace=getsockopt -Xraw -a39 so_peercred-Xverbose -e trace=getsockopt -Xverbose +so_peercred--pidns-translation test_pidns -e trace=getsockopt sock_filter-v -v -e trace=getsockopt,setsockopt sock_filter-v-Xabbrev -v -e trace=getsockopt,setsockopt -X abbrev sock_filter-v-Xraw -a 37 -v -e trace=getsockopt,setsockopt -X raw @@ -721,7 +746,10 @@ waitpid -a28 xattr -a22 -e trace=getxattr,fgetxattr,lgetxattr,setxattr,fsetxattr,lsetxattr,listxattr,flistxattr,llistxattr,removexattr,fremovexattr,lremovexattr xattr-strings -a22 -s 4 -e trace=fsetxattr xet_robust_list -a24 -e trace=get_robust_list,set_robust_list +xet_robust_list--pidns-translation test_pidns -a24 -e trace=get_robust_list,set_robust_list xetitimer -a29 -e trace=setitimer,getitimer xetpgid -a11 -e trace=getpgid,setpgid -xetpriority -a29 -e trace=getpriority,setpriority +xetpgid--pidns-translation test_pidns -a11 -e trace=getpgid,setpgid +xetpriority -a27 -e trace=getpriority,setpriority +xetpriority--pidns-translation test_pidns -a27 -e trace=getpriority,setpriority xettimeofday -a20 -e trace=gettimeofday,settimeofday diff --git a/tests/getpgrp--pidns-translation.c b/tests/getpgrp--pidns-translation.c new file mode 100644 index 00000000..de8ceb33 --- /dev/null +++ b/tests/getpgrp--pidns-translation.c @@ -0,0 +1,2 @@ +#define PIDNS_TRANSLATION +#include "getpgrp.c" diff --git a/tests/getpgrp.c b/tests/getpgrp.c index 104f4811..3f0b9dd1 100644 --- a/tests/getpgrp.c +++ b/tests/getpgrp.c @@ -7,6 +7,7 @@ #include "tests.h" #include "scno.h" +#include "pidns.h" #ifdef __NR_getpgrp @@ -16,8 +17,13 @@ int main(void) { - printf("getpgrp() = %ld\n", syscall(__NR_getpgrp)); + PIDNS_TEST_INIT; + pidns_print_leader(); + printf("getpgrp() = %d%s\n", (int) syscall(__NR_getpgrp), + pidns_pid2str(PT_PGID)); + + pidns_print_leader(); puts("+++ exited with 0 +++"); return 0; } diff --git a/tests/getpid--pidns-translation.c b/tests/getpid--pidns-translation.c new file mode 100644 index 00000000..94b12a1a --- /dev/null +++ b/tests/getpid--pidns-translation.c @@ -0,0 +1,2 @@ +#define PIDNS_TRANSLATION +#include "getpid.c" diff --git a/tests/getpid.c b/tests/getpid.c index 988f19d5..7ec4e6e8 100644 --- a/tests/getpid.c +++ b/tests/getpid.c @@ -7,6 +7,7 @@ #include "tests.h" #include "scno.h" +#include "pidns.h" #if defined __NR_getpid && (!defined __NR_getxpid || __NR_getxpid != __NR_getpid) @@ -16,7 +17,12 @@ int main(void) { - printf("getpid() = %ld\n", syscall(__NR_getpid)); + PIDNS_TEST_INIT; + + pidns_print_leader(); + printf("getpid() = %d%s\n", (int) syscall(__NR_getpid), + pidns_pid2str(PT_TGID)); + pidns_print_leader(); puts("+++ exited with 0 +++"); return 0; } diff --git a/tests/getsid--pidns-translation.c b/tests/getsid--pidns-translation.c new file mode 100644 index 00000000..7f983e87 --- /dev/null +++ b/tests/getsid--pidns-translation.c @@ -0,0 +1,2 @@ +#define PIDNS_TRANSLATION +#include "getsid.c" diff --git a/tests/getsid.c b/tests/getsid.c index 588ea4ab..3bf74734 100644 --- a/tests/getsid.c +++ b/tests/getsid.c @@ -6,15 +6,22 @@ */ #include "tests.h" +#include "pidns.h" + #include #include int main(void) { + PIDNS_TEST_INIT; + pid_t pid = getpid(); - printf("getsid(%d) = %d\n", pid, getsid(pid)); + pidns_print_leader(); + printf("getsid(%d%s) = %d%s\n", pid, pidns_pid2str(PT_TGID), + getsid(pid), pidns_pid2str(PT_SID)); + pidns_print_leader(); puts("+++ exited with 0 +++"); return 0; } diff --git a/tests/gettid--pidns-translation.c b/tests/gettid--pidns-translation.c new file mode 100644 index 00000000..500c3213 --- /dev/null +++ b/tests/gettid--pidns-translation.c @@ -0,0 +1,2 @@ +#define PIDNS_TRANSLATION +#include "gettid.c" diff --git a/tests/gettid.c b/tests/gettid.c index d38918dd..314d9c2c 100644 --- a/tests/gettid.c +++ b/tests/gettid.c @@ -9,11 +9,17 @@ #include #include #include "scno.h" +#include "pidns.h" int main(void) { - printf("gettid() = %ld\n", syscall(__NR_gettid)); + PIDNS_TEST_INIT; + + pidns_print_leader(); + printf("gettid() = %d%s\n", (int) syscall(__NR_gettid), + pidns_pid2str(PT_TID)); + pidns_print_leader(); puts("+++ exited with 0 +++"); return 0; } diff --git a/tests/ioctl_block--pidns-translation.c b/tests/ioctl_block--pidns-translation.c new file mode 100644 index 00000000..5eed6076 --- /dev/null +++ b/tests/ioctl_block--pidns-translation.c @@ -0,0 +1,2 @@ +#define PIDNS_TRANSLATION +#include "ioctl_block.c" diff --git a/tests/ioctl_block--pidns-translation.test b/tests/ioctl_block--pidns-translation.test new file mode 100755 index 00000000..bb45f695 --- /dev/null +++ b/tests/ioctl_block--pidns-translation.test @@ -0,0 +1,24 @@ +#!/bin/sh +# +# Check ioctl syscall decoding. +# +# Copyright (c) 2020 The strace developers. +# All rights reserved. +# +# SPDX-License-Identifier: LGPL-2.1-or-later + +. "${srcdir=.}/init.sh" + +require_min_kernel_version_or_skip 4.9 + +check_prog head +check_prog tail +check_prog cut +check_prog grep + +run_prog > /dev/null +run_strace --pidns-translation -f -a16 -e trace=ioctl $@ $args > "$EXP" +parent_pid="$(tail -n 2 $LOG | head -n 1 | cut -d' ' -f1)" +init_pid="$(tail -n 1 $LOG | cut -d' ' -f1)" +grep -E -v "^($parent_pid|$init_pid) |ioctl\([0123][,<]" "$LOG" > "$OUT" +match_diff "$OUT" "$EXP" diff --git a/tests/ioctl_block.c b/tests/ioctl_block.c index 0afe27f7..8a345f4e 100644 --- a/tests/ioctl_block.c +++ b/tests/ioctl_block.c @@ -9,7 +9,9 @@ */ #include "tests.h" +#include "pidns.h" #include +#include #include #include #include @@ -41,12 +43,15 @@ static struct xlat_data block_argless[] = { #define TEST_NULL_ARG(cmd) \ do { \ ioctl(-1, cmd, 0); \ + pidns_print_leader(); \ printf("ioctl(-1, %s, NULL) = -1 EBADF (%m)\n", #cmd); \ } while (0) int main(void) { + PIDNS_TEST_INIT; + TEST_NULL_ARG(BLKBSZGET); TEST_NULL_ARG(BLKBSZSET); TEST_NULL_ARG(BLKFRAGET); @@ -91,18 +96,22 @@ main(void) #endif ioctl(-1, BLKRASET, lmagic); + pidns_print_leader(); printf("ioctl(-1, BLKRASET, %lu) = -1 EBADF (%m)\n", lmagic); ioctl(-1, BLKFRASET, lmagic); + pidns_print_leader(); printf("ioctl(-1, BLKFRASET, %lu) = -1 EBADF (%m)\n", lmagic); TAIL_ALLOC_OBJECT_CONST_PTR(int, val_int); *val_int = magic; ioctl(-1, BLKROSET, val_int); + pidns_print_leader(); printf("ioctl(-1, BLKROSET, [%d]) = -1 EBADF (%m)\n", *val_int); ioctl(-1, BLKBSZSET, val_int); + pidns_print_leader(); printf("ioctl(-1, BLKBSZSET, [%d]) = -1 EBADF (%m)\n", *val_int); uint64_t *pair_int64 = tail_alloc(sizeof(*pair_int64) * 2); @@ -111,18 +120,21 @@ main(void) #ifdef BLKDISCARD ioctl(-1, BLKDISCARD, pair_int64); + pidns_print_leader(); printf("ioctl(-1, BLKDISCARD, [%" PRIu64 ", %" PRIu64 "])" " = -1 EBADF (%m)\n", pair_int64[0], pair_int64[1]); #endif #ifdef BLKSECDISCARD ioctl(-1, BLKSECDISCARD, pair_int64); + pidns_print_leader(); printf("ioctl(-1, BLKSECDISCARD, [%" PRIu64 ", %" PRIu64 "])" " = -1 EBADF (%m)\n", pair_int64[0], pair_int64[1]); #endif #ifdef BLKZEROOUT ioctl(-1, BLKZEROOUT, pair_int64); + pidns_print_leader(); printf("ioctl(-1, BLKZEROOUT, [%" PRIu64 ", %" PRIu64 "])" " = -1 EBADF (%m)\n", pair_int64[0], pair_int64[1]); #endif @@ -134,6 +146,7 @@ main(void) blkpg->data = (void *) (unsigned long) 0xcafef00dfffffeedULL; ioctl(-1, BLKPG, blkpg); + pidns_print_leader(); printf("ioctl(-1, BLKPG, {op=%s, flags=%d, datalen=%d" ", data=%#lx}) = -1 EBADF (%m)\n", "BLKPG_RESIZE_PARTITION", blkpg->flags, blkpg->datalen, @@ -149,6 +162,7 @@ main(void) blkpg->data = bp; ioctl(-1, BLKPG, blkpg); + pidns_print_leader(); printf("ioctl(-1, BLKPG, {op=%s, flags=%d, datalen=%d" ", data={start=%lld, length=%lld, pno=%d" ", devname=\"%.*s\"..., volname=\"%.*s\"...}})" @@ -162,25 +176,31 @@ main(void) #if defined BLKTRACESETUP && defined HAVE_STRUCT_BLK_USER_TRACE_SETUP TAIL_ALLOC_OBJECT_CONST_PTR(struct blk_user_trace_setup, buts); fill_memory(buts, sizeof(*buts)); + buts->pid = getpid(); ioctl(-1, BLKTRACESETUP, buts); + pidns_print_leader(); printf("ioctl(-1, BLKTRACESETUP, {act_mask=%hu, buf_size=%u, buf_nr=%u" - ", start_lba=%" PRI__u64 ", end_lba=%" PRI__u64 ", pid=%d})" + ", start_lba=%" PRI__u64 ", end_lba=%" PRI__u64 ", pid=%d%s})" " = -1 EBADF (%m)\n", buts->act_mask, buts->buf_size, buts->buf_nr, - buts->start_lba, buts->end_lba, buts->pid); + buts->start_lba, buts->end_lba, buts->pid, + pidns_pid2str(PT_TGID)); #endif unsigned int i; for (i = 0; i < ARRAY_SIZE(block_argless); ++i) { ioctl(-1, (unsigned long) block_argless[i].val, lmagic); + pidns_print_leader(); printf("ioctl(-1, %s) = -1 EBADF (%m)\n", block_argless[i].str); } ioctl(-1, _IOC(_IOC_READ, 0x12, 0xfe, 0xff), lmagic); + pidns_print_leader(); printf("ioctl(-1, %s, %#lx) = -1 EBADF (%m)\n", "_IOC(_IOC_READ, 0x12, 0xfe, 0xff)", lmagic); + pidns_print_leader(); puts("+++ exited with 0 +++"); return 0; } diff --git a/tests/ioprio--pidns-translation.c b/tests/ioprio--pidns-translation.c new file mode 100644 index 00000000..bcb49a8b --- /dev/null +++ b/tests/ioprio--pidns-translation.c @@ -0,0 +1,2 @@ +#define PIDNS_TRANSLATION +#include "ioprio.c" diff --git a/tests/ioprio.c b/tests/ioprio.c index 5e1e1194..110df063 100644 --- a/tests/ioprio.c +++ b/tests/ioprio.c @@ -9,8 +9,8 @@ */ #include "tests.h" - #include "scno.h" +#include "pidns.h" #if defined(__NR_ioprio_get) && defined(__NR_ioprio_set) @@ -30,12 +30,18 @@ enum { int main(void) { + PIDNS_TEST_INIT; + static const kernel_ulong_t bogus_which = (kernel_ulong_t) 0xdeadfacefa57beefULL; static const kernel_ulong_t bogus_who = (kernel_ulong_t) 0xbadc0dedda7a1057ULL; static const kernel_ulong_t bogus_ioprio = (kernel_ulong_t) 0xdec0ded1facefeedULL; + + const int pid = getpid(); + const int pgid = getpgid(0); + # if !XLAT_RAW static const char * const bogus_ioprio_str = "IOPRIO_PRIO_VALUE(0x7d677 /* IOPRIO_CLASS_??? */, 7917)"; @@ -46,6 +52,7 @@ main(void) rc = syscall(__NR_ioprio_get, bogus_which, bogus_who); errstr = sprintrc(rc); + pidns_print_leader(); # if XLAT_RAW printf("ioprio_get(%#x, %d) = %s\n", (int) bogus_which, (int) bogus_who, errstr); @@ -54,42 +61,52 @@ main(void) (int) bogus_which, (int) bogus_who, errstr); # endif - rc = syscall(__NR_ioprio_get, 1, 0); + rc = syscall(__NR_ioprio_get, 1, pid); errstr = sprintrc(rc); + pidns_print_leader(); + printf("ioprio_get("); # if XLAT_RAW - printf("ioprio_get(0x1, 0) = %s\n", errstr); + printf("0x1, "); +# elif XLAT_VERBOSE + printf("0x1 /* IOPRIO_WHO_PROCESS */, "); # else /* XLAT_ABBREV */ -# if XLAT_VERBOSE - printf("ioprio_get(0x1 /* IOPRIO_WHO_PROCESS */, 0) = %s", errstr); -# else - printf("ioprio_get(IOPRIO_WHO_PROCESS, 0) = %s", errstr); -# endif + printf("IOPRIO_WHO_PROCESS, "); +# endif + printf("%d%s) = %s", pid, pidns_pid2str(PT_TGID), errstr); +# if !XLAT_RAW if (rc >= 0) { printf(" (IOPRIO_PRIO_VALUE("); printxval(ioprio_class, (unsigned int) rc >> 13, "IOPRIO_CLASS_???"); printf(", %u))", (unsigned int) rc & 0x1fff); } - puts(""); # endif + puts(""); - rc = syscall(__NR_ioprio_set, 2, 0, 8191); + rc = syscall(__NR_ioprio_set, 2, pgid, 8191); errstr = sprintrc(rc); + pidns_print_leader(); + printf("ioprio_set("); # if XLAT_RAW - printf("ioprio_set(%#x, 0, 8191) = %s\n", 2, errstr); + printf("%#x", 2); # elif XLAT_VERBOSE - printf("ioprio_set(%#x /* IOPRIO_WHO_PGRP */, 0, 8191" - " /* IOPRIO_PRIO_VALUE(0 /* IOPRIO_CLASS_NONE */, 8191) */)" - " = %s\n", - 2, errstr); + printf("%#x /* IOPRIO_WHO_PGRP */", 2); # else /* XLAT_ABBREV */ - printf("ioprio_set(IOPRIO_WHO_PGRP, 0" - ", IOPRIO_PRIO_VALUE(IOPRIO_CLASS_NONE, 8191)) = %s\n", - errstr); + printf("IOPRIO_WHO_PGRP"); +# endif + printf(", %d%s", pgid, pidns_pid2str(PT_PGID)); +# if XLAT_RAW + printf(", 8191)"); +# elif XLAT_VERBOSE + printf(", 8191 /* IOPRIO_PRIO_VALUE(0 /* IOPRIO_CLASS_NONE */, 8191) */)"); +# else /* XLAT_ABBREV */ + printf(", IOPRIO_PRIO_VALUE(IOPRIO_CLASS_NONE, 8191))"); # endif + printf(" = %s\n", errstr); rc = syscall(__NR_ioprio_set, bogus_which, bogus_who, bogus_ioprio); errstr = sprintrc(rc); + pidns_print_leader(); # if XLAT_RAW printf("ioprio_set(%#x, %d, %d) = %s\n", (int) bogus_which, (int) bogus_who, (int) bogus_ioprio, @@ -104,6 +121,7 @@ main(void) errstr); # endif + pidns_print_leader(); puts("+++ exited with 0 +++"); return 0; diff --git a/tests/kcmp-y--pidns-translation.c b/tests/kcmp-y--pidns-translation.c new file mode 100644 index 00000000..f54d94cc --- /dev/null +++ b/tests/kcmp-y--pidns-translation.c @@ -0,0 +1,2 @@ +#define PIDNS_TRANSLATION +#include "kcmp-y.c" diff --git a/tests/kcmp.c b/tests/kcmp.c index dc5ba9a4..ce705ad0 100644 --- a/tests/kcmp.c +++ b/tests/kcmp.c @@ -9,8 +9,8 @@ */ #include "tests.h" - #include "scno.h" +#include "pidns.h" #ifdef __NR_kcmp @@ -101,7 +101,11 @@ do_kcmp(kernel_ulong_t pid1, kernel_ulong_t pid2, kernel_ulong_t type, rc = syscall(__NR_kcmp, pid1, pid2, type, idx1, idx2); errstr = sprintrc(rc); - printf("kcmp(%d, %d, ", (int) pid1, (int) pid2); + const char *pid_str = pidns_pid2str(PT_TGID); + pidns_print_leader(); + printf("kcmp(%d%s, %d%s, ", + (int) pid1, (int) pid1 == getpid() ? pid_str : "", + (int) pid2, (int) pid2 == getpid() ? pid_str : ""); if (type_str) printf("%s", type_str); @@ -146,6 +150,8 @@ do_kcmp(kernel_ulong_t pid1, kernel_ulong_t pid2, kernel_ulong_t type, int main(void) { + PIDNS_TEST_INIT; + static const kernel_ulong_t bogus_pid1 = (kernel_ulong_t) 0xdeadca75face1057ULL; static const kernel_ulong_t bogus_pid2 = @@ -221,6 +227,7 @@ main(void) (uintptr_t) slot, 1); } + pidns_print_leader(); puts("+++ exited with 0 +++"); return 0; diff --git a/tests/kill--pidns-translation.c b/tests/kill--pidns-translation.c new file mode 100644 index 00000000..4736ca14 --- /dev/null +++ b/tests/kill--pidns-translation.c @@ -0,0 +1,2 @@ +#define PIDNS_TRANSLATION +#include "kill.c" diff --git a/tests/kill.c b/tests/kill.c index f7d9341e..17de35da 100644 --- a/tests/kill.c +++ b/tests/kill.c @@ -11,6 +11,7 @@ #include "tests.h" #include "scno.h" +#include "pidns.h" #ifdef __NR_kill @@ -26,6 +27,8 @@ handler(int sig) int main(void) { + PIDNS_TEST_INIT; + const struct sigaction act = { .sa_handler = handler }; if (sigaction(SIGALRM, &act, NULL)) perror_msg_and_fail("sigaction"); @@ -37,18 +40,23 @@ main(void) perror_msg_and_fail("sigprocmask"); const int pid = getpid(); + const char *pid_str = pidns_pid2str(PT_TGID); long rc = syscall(__NR_kill, pid, (long) 0xdefaced00000000ULL | SIGALRM); - printf("kill(%d, SIGALRM) = %ld\n", pid, rc); + pidns_print_leader(); + printf("kill(%d%s, SIGALRM) = %ld\n", pid, pid_str, rc); const long big_pid = (long) 0xfacefeedbadc0dedULL; const long big_sig = (long) 0xdeadbeefcafef00dULL; rc = syscall(__NR_kill, big_pid, big_sig); + pidns_print_leader(); printf("kill(%d, %d) = %ld %s (%m)\n", (int) big_pid, (int) big_sig, rc, errno2name()); rc = syscall(__NR_kill, (long) 0xdefaced00000000ULL | pid, 0); - printf("kill(%d, 0) = %ld\n", pid, rc); + pidns_print_leader(); + printf("kill(%d%s, 0) = %ld\n", pid, pid_str, rc); + pidns_print_leader(); puts("+++ exited with 0 +++"); return 0; } diff --git a/tests/migrate_pages--pidns-translation.c b/tests/migrate_pages--pidns-translation.c new file mode 100644 index 00000000..ec34938d --- /dev/null +++ b/tests/migrate_pages--pidns-translation.c @@ -0,0 +1,2 @@ +#define PIDNS_TRANSLATION +#include "migrate_pages.c" diff --git a/tests/migrate_pages.c b/tests/migrate_pages.c index 2dfba49c..390b490b 100644 --- a/tests/migrate_pages.c +++ b/tests/migrate_pages.c @@ -10,6 +10,7 @@ #include "tests.h" #include "scno.h" +#include "pidns.h" #ifdef __NR_migrate_pages @@ -19,11 +20,21 @@ int main(void) { - const long pid = (long) 0xfacefeedffffffffULL; + PIDNS_TEST_INIT; + + const long pid = (long) 0xfacefeed00000000ULL | getpid(); long rc = syscall(__NR_migrate_pages, pid, 0, 0, 0); - printf("migrate_pages(%d, 0, NULL, NULL) = %ld %s (%m)\n", - (int) pid, rc, errno2name()); + pidns_print_leader(); + printf("migrate_pages(%d%s, 0, NULL, NULL) = %ld", + (int) pid, pidns_pid2str(PT_TGID), rc); + + if (rc < 0) + printf(" %s (%m)\n", errno2name()); + else + printf("\n"); + + pidns_print_leader(); puts("+++ exited with 0 +++"); return 0; } diff --git a/tests/move_pages--pidns-translation.c b/tests/move_pages--pidns-translation.c new file mode 100644 index 00000000..8498e399 --- /dev/null +++ b/tests/move_pages--pidns-translation.c @@ -0,0 +1,2 @@ +#define PIDNS_TRANSLATION +#include "move_pages.c" diff --git a/tests/move_pages.c b/tests/move_pages.c index e00fd1ac..56843158 100644 --- a/tests/move_pages.c +++ b/tests/move_pages.c @@ -10,6 +10,7 @@ #include "tests.h" #include "scno.h" +#include "pidns.h" #ifdef __NR_move_pages @@ -122,15 +123,20 @@ print_status_array(const int *const status, const unsigned long count) } static void -print_stat_pages(const unsigned long pid, const unsigned long count, - const void **const pages, int *const status) +print_stat_pages(const unsigned long pid, + const char *pid_str, + const unsigned long count, + const void **const pages, + int *const status) { const unsigned long flags = (unsigned long) 0xfacefeed00000002ULL; long rc = syscall(__NR_move_pages, pid, count, pages, NULL, status, flags); const char *errstr = sprintrc(rc); - printf("move_pages(%d, %lu, ", (int) pid, count); + pidns_print_leader(); + printf("move_pages(%d%s, %lu, ", (int) pid, pid_str, + count); print_page_array(pages, count, 0); printf(", NULL, "); if (rc) { @@ -152,6 +158,7 @@ print_stat_pages(const unsigned long pid, const unsigned long count, static void print_move_pages(const unsigned long pid, + const char *pid_str, unsigned long count, const unsigned int offset, const void **const pages, @@ -164,7 +171,9 @@ print_move_pages(const unsigned long pid, long rc = syscall(__NR_move_pages, pid, count, pages, nodes, status, flags); const char *errstr = sprintrc(rc); - printf("move_pages(%d, %lu, ", (int) pid, count); + pidns_print_leader(); + printf("move_pages(%d%s, %lu, ", (int) pid, pid_str, + count); print_page_array(pages, count, offset); printf(", "); print_node_array(nodes, count, offset); @@ -185,8 +194,11 @@ print_move_pages(const unsigned long pid, int main(void) { + PIDNS_TEST_INIT; + const unsigned long pid = (unsigned long) 0xfacefeed00000000ULL | getpid(); + const char *pid_str = pidns_pid2str(PT_TGID); unsigned long count = 1; const unsigned page_size = get_page_size(); const void *const page = tail_alloc(page_size); @@ -195,40 +207,41 @@ main(void) TAIL_ALLOC_OBJECT_VAR_PTR(int, nodes); TAIL_ALLOC_OBJECT_VAR_PTR(int, status); - print_stat_pages(pid, 0, pages, status); - print_move_pages(pid, 0, 0, pages, nodes, status); - print_move_pages(pid, 0, 1, pages + 1, nodes + 1, status + 1); + print_stat_pages(pid, pid_str, 0, pages, status); + print_move_pages(pid, pid_str, 0, 0, pages, nodes, status); + print_move_pages(pid, pid_str, 0, 1, pages + 1, nodes + 1, status + 1); *pages = page; - print_stat_pages(pid, count, pages, status); + print_stat_pages(pid, pid_str, count, pages, status); *nodes = 0xdeadbee1; - print_move_pages(pid, count, 0, pages, nodes, status); - print_move_pages(pid, count, 1, pages, nodes, status); + print_move_pages(pid, pid_str, count, 0, pages, nodes, status); + print_move_pages(pid, pid_str, count, 1, pages, nodes, status); ++count; --status; *(--pages) = efault; - print_stat_pages(pid, count, pages, status); + print_stat_pages(pid, pid_str, count, pages, status); *(--nodes) = 0xdeadbee2; - print_move_pages(pid, count, 0, pages, nodes, status); - print_move_pages(pid, count, 1, pages, nodes, status); + print_move_pages(pid, pid_str, count, 0, pages, nodes, status); + print_move_pages(pid, pid_str, count, 1, pages, nodes, status); ++count; --status; *(--pages) = nodes; - print_stat_pages(pid, count, pages, status); + print_stat_pages(pid, pid_str, count, pages, status); *(--nodes) = 0xdeadbee3; - print_move_pages(pid, count, 0, pages, nodes, status); - print_move_pages(pid, count, 1, pages, nodes, status); + print_move_pages(pid, pid_str, count, 0, pages, nodes, status); + print_move_pages(pid, pid_str, count, 1, pages, nodes, status); ++count; --status; *(--pages) = status; - print_stat_pages(pid, count, pages, status); + print_stat_pages(pid, pid_str, count, pages, status); *(--nodes) = 0xdeadbee4; - print_move_pages(pid, count, 0, pages, nodes, status); - print_move_pages(pid, count, 1, pages, nodes, status); + print_move_pages(pid, pid_str, count, 0, pages, nodes, status); + print_move_pages(pid, pid_str, count, 1, pages, nodes, status); + pidns_print_leader(); puts("+++ exited with 0 +++"); return 0; } diff --git a/tests/net-sockaddr--pidns-translation.c b/tests/net-sockaddr--pidns-translation.c new file mode 100644 index 00000000..ff432bf4 --- /dev/null +++ b/tests/net-sockaddr--pidns-translation.c @@ -0,0 +1,2 @@ +#define PIDNS_TRANSLATION +#include "net-sockaddr.c" diff --git a/tests/net-sockaddr.c b/tests/net-sockaddr.c index 4fc9da6e..b9cd46fd 100644 --- a/tests/net-sockaddr.c +++ b/tests/net-sockaddr.c @@ -9,6 +9,7 @@ */ #include "tests.h" +#include "pidns.h" #include #include #include @@ -40,18 +41,21 @@ check_un(void) memset(un->sun_path, '0', sizeof(un->sun_path)); unsigned int len = sizeof(*un); int ret = connect(-1, (void *) un, len); + pidns_print_leader(); printf("connect(-1, {sa_family=AF_UNIX, sun_path=\"%.*u\"}" ", %u) = %d EBADF (%m)\n", (int) sizeof(un->sun_path), 0, len, ret); un->sun_path[1] = 0; ret = connect(-1, (void *) un, len); + pidns_print_leader(); printf("connect(-1, {sa_family=AF_UNIX, sun_path=\"%u\"}, %u)" " = %d EBADF (%m)\n", 0, len, ret); un->sun_path[0] = 0; un->sun_path[2] = 1; ret = connect(-1, (void *) un, len); + pidns_print_leader(); printf("connect(-1, {sa_family=AF_UNIX, sun_path=@\"\\0\\001%.*u\"}" ", %u) = %d EBADF (%m)\n", (int) sizeof(un->sun_path) - 3, 0, len, ret); @@ -61,12 +65,14 @@ check_un(void) memset(un->sun_path, '0', sizeof(un->sun_path)); len = sizeof(*un) + 2; ret = connect(-1, (void *) un, len); + pidns_print_leader(); printf("connect(-1, {sa_family=AF_UNIX, sun_path=\"%.*u\"}" ", %u) = %d EBADF (%m)\n", (int) sizeof(un->sun_path), 0, len, ret); un->sun_path[0] = 0; ret = connect(-1, (void *) un, len); + pidns_print_leader(); printf("connect(-1, {sa_family=AF_UNIX, sun_path=@\"%.*u\"}" ", %u) = %d EBADF (%m)\n", (int) sizeof(un->sun_path) - 1, 0, len, ret); @@ -75,18 +81,21 @@ check_un(void) un->sun_family = AF_UNIX; len = sizeof(*un) - 2; ret = connect(-1, (void *) un, len); + pidns_print_leader(); printf("connect(-1, {sa_family=AF_UNIX, sun_path=\"%.*u\"}" ", %u) = %d EBADF (%m)\n", (int) sizeof(un->sun_path) - 2, 0, len, ret); un->sun_path[0] = 0; ret = connect(-1, (void *) un, len); + pidns_print_leader(); printf("connect(-1, {sa_family=AF_UNIX, sun_path=@\"%.*u\"}" ", %u) = %d EBADF (%m)\n", (int) sizeof(un->sun_path) - 3, 0, len, ret); len = sizeof(*un); ret = connect(-1, (void *) un, len); + pidns_print_leader(); printf("connect(-1, %p, %u) = %d EBADF (%m)\n", un, len, ret); un = tail_alloc(sizeof(struct sockaddr_storage)); @@ -94,12 +103,14 @@ check_un(void) memset(un->sun_path, '0', sizeof(un->sun_path)); len = sizeof(struct sockaddr_storage) + 1; ret = connect(-1, (void *) un, len); + pidns_print_leader(); printf("connect(-1, {sa_family=AF_UNIX, sun_path=\"%.*u\"}" ", %u) = %d EBADF (%m)\n", (int) sizeof(un->sun_path), 0, len, ret); un->sun_path[0] = 0; ret = connect(-1, (void *) un, len); + pidns_print_leader(); printf("connect(-1, {sa_family=AF_UNIX, sun_path=@\"%.*u\"}" ", %u) = %d EBADF (%m)\n", (int) sizeof(un->sun_path) - 1, 0, len, ret); @@ -117,6 +128,7 @@ check_in(void) in->sin_addr.s_addr = inet_addr(h_addr); unsigned int len = sizeof(*in); int ret = connect(-1, (void *) in, len); + pidns_print_leader(); printf("connect(-1, {sa_family=AF_INET, sin_port=htons(%hu)" ", sin_addr=inet_addr(\"%s\")}, %u) = %d EBADF (%m)\n", h_port, h_addr, len, ret); @@ -127,6 +139,7 @@ check_in(void) in->sin_addr.s_addr = inet_addr(h_addr); len = sizeof(*in) + 4; ret = connect(-1, (void *) in, len); + pidns_print_leader(); printf("connect(-1, {sa_family=AF_INET, sin_port=htons(%hu)" ", sin_addr=inet_addr(\"%s\")}, %u) = %d EBADF (%m)\n", h_port, h_addr, len, ret); @@ -137,6 +150,7 @@ check_in(void) in->sin_addr.s_addr = 0; len = sizeof(*in) - 4; ret = connect(-1, (void *) in, len); + pidns_print_leader(); printf("connect(-1, {sa_family=AF_INET, sa_data=\"%s\"}, %u)" " = %d EBADF (%m)\n", "\\0\\0\\0\\0\\0\\0\\377\\377\\377\\377", @@ -144,6 +158,7 @@ check_in(void) len = sizeof(*in); ret = connect(-1, (void *) in, len); + pidns_print_leader(); printf("connect(-1, %p, %u) = %d EBADF (%m)\n", in, len, ret); } @@ -155,6 +170,7 @@ check_in6_linklocal(struct sockaddr_in6 *const in6, const char *const h_addr) in6->sin6_scope_id = 0xfacefeed; unsigned int len = sizeof(*in6); int ret = connect(-1, (void *) in6, len); + pidns_print_leader(); printf("connect(-1, {sa_family=AF_INET6, sin6_port=htons(%hu)" ", sin6_flowinfo=htonl(%u)" ", inet_pton(AF_INET6, \"%s\", &sin6_addr)" @@ -166,7 +182,8 @@ check_in6_linklocal(struct sockaddr_in6 *const in6, const char *const h_addr) in6->sin6_scope_id = ifindex_lo(); if (in6->sin6_scope_id) { ret = connect(-1, (void *) in6, len); - printf("connect(-1, {sa_family=AF_INET6, sin6_port=htons(%hu)" + pidns_print_leader(); + printf("connect(-1, {sa_family=AF_INET6, sin6_port=htons(%hu)" ", sin6_flowinfo=htonl(%u)" ", inet_pton(AF_INET6, \"%s\", &sin6_addr)" ", sin6_scope_id=%s}, %u)" @@ -191,6 +208,7 @@ check_in6(void) in6->sin6_scope_id = 0xfacefeed; unsigned int len = sizeof(*in6); int ret = connect(-1, (void *) in6, len); + pidns_print_leader(); printf("connect(-1, {sa_family=AF_INET6, sin6_port=htons(%hu)" ", sin6_flowinfo=htonl(%u)" ", inet_pton(AF_INET6, \"%s\", &sin6_addr)" @@ -209,6 +227,7 @@ check_in6(void) in6->sin6_scope_id = 0xfacefeed; len = sizeof(*in6) + 4; ret = connect(-1, (void *) in6, len); + pidns_print_leader(); printf("connect(-1, {sa_family=AF_INET6, sin6_port=htons(%hu)" ", sin6_flowinfo=htonl(%u)" ", inet_pton(AF_INET6, \"%s\", &sin6_addr)" @@ -223,6 +242,7 @@ check_in6(void) inet_pton(AF_INET6, h_addr, &in6->sin6_addr); len = sizeof(*in6) - sizeof(in6->sin6_scope_id); ret = connect(-1, (void *) in6, len); + pidns_print_leader(); printf("connect(-1, {sa_family=AF_INET6, sin6_port=htons(%hu)" ", sin6_flowinfo=htonl(%u)" ", inet_pton(AF_INET6, \"%s\", &sin6_addr)}, %u)" @@ -236,6 +256,7 @@ check_in6(void) memset(&in6->sin6_addr, '0', sizeof(in6->sin6_addr) - 4); len = sizeof(*in6) - sizeof(in6->sin6_scope_id) - 4; ret = connect(-1, (void *) in6, len); + pidns_print_leader(); printf("connect(-1, {sa_family=AF_INET6" ", sa_data=\"\\0\\0\\0\\0\\0\\000%.*u\"}, %u)" " = %d EBADF (%m)\n", @@ -244,6 +265,7 @@ check_in6(void) len = sizeof(*in6) - sizeof(in6->sin6_scope_id); ret = connect(-1, (void *) in6, len); + pidns_print_leader(); printf("connect(-1, %p, %u) = %d EBADF (%m)\n", in6, len, ret); } @@ -262,6 +284,7 @@ check_ipx(void) void *ipx = tail_memdup(&c_ipx, sizeof(c_ipx)); unsigned int len = sizeof(c_ipx); int ret = connect(-1, ipx, len); + pidns_print_leader(); printf("connect(-1, {sa_family=AF_IPX, sipx_port=htons(%u)" ", sipx_network=htonl(%#x)" ", sipx_node=[%#02x, %#02x, %#02x, %#02x, %#02x, %#02x]" @@ -316,18 +339,21 @@ check_ax25(void) fill_memory(sax, size); sax->fsa_ax25.sax25_family = AF_AX25; rc = connect(-1, sax_void, sizeof(struct sockaddr_ax25) - 1); + pidns_print_leader(); printf("connect(-1, {sa_family=AF_AX25, sa_data=\"\\202\\203\\204\\205" "\\206\\207\\210\\211\\212\\213\\214\\215\\216\"}, %zu) = %s\n", sizeof(struct sockaddr_ax25) - 1, sprintrc(rc)); memcpy(sax, &ax25, sizeof(ax25)); rc = connect(-1, sax_void, sizeof(struct sockaddr_ax25)); + pidns_print_leader(); printf("connect(-1, {sa_family=AF_AX25, fsa_ax25={sax25_call=VALID-13" ", sax25_ndigis=8}, fsa_digipeater=[/* ??? */]}, %zu) = %s\n", sizeof(struct sockaddr_ax25), sprintrc(rc)); sax->fsa_ax25.sax25_ndigis = 0; rc = connect(-1, sax_void, sizeof(struct sockaddr_ax25)); + pidns_print_leader(); printf("connect(-1, {sa_family=AF_AX25, sax25_call=VALID-13" ", sax25_ndigis=0}, %zu) = %s\n", sizeof(struct sockaddr_ax25), sprintrc(rc)); @@ -335,6 +361,7 @@ check_ax25(void) sax->fsa_ax25.sax25_ndigis = 8; size = sizeof(struct sockaddr_ax25) + sizeof(ax25_address) * 3 + 1; rc = connect(-1, sax_void, size); + pidns_print_leader(); printf("connect(-1, {sa_family=AF_AX25, fsa_ax25={sax25_call=VALID-13" ", sax25_ndigis=8}, fsa_digipeater" "=[{ax25_call=\"\\xa6\\xa0\\x82\\x40\\x86\\x8a\\x00\"" @@ -348,6 +375,7 @@ check_ax25(void) sax->fsa_digipeater[2].ax25_call[6] = 0x4; size = sizeof(struct sockaddr_ax25) + sizeof(ax25_address) * 4; rc = connect(-1, sax_void, size); + pidns_print_leader(); printf("connect(-1, {sa_family=AF_AX25, fsa_ax25={sax25_call=VALID-13" ", sax25_ndigis=8}, fsa_digipeater" "=[{ax25_call=\"\\xa6\\xa0\\x82\\x40\\x86\\x8a\\x00\"" @@ -365,7 +393,8 @@ check_ax25(void) for (size_t i = 0; i < 3; i++) { size = sizeof(ax25) + sizeof(ax25_address) * (i / 2); rc = connect(-1, sax_void, size); - printf("connect(-1, {sa_family=AF_AX25" + pidns_print_leader(); + printf("connect(-1, {sa_family=AF_AX25" ", fsa_ax25={sax25_call=VALID-13, sax25_ndigis=%d}" ", fsa_digipeater=[VALID2-7, OK-15, %s /* FINE-2 */" ", {ax25_call=\"\\xe6\\xda\\xc2\\xd8\\xd8\\xe6\\x12\"" @@ -427,13 +456,15 @@ check_x25(void) long rc; rc = connect(-1, x25_void, sizeof(c_x25) - 1); + pidns_print_leader(); printf("connect(-1, {sa_family=AF_X25" ", sa_data=\"0123456789abcde\"}, %zu) = %s\n", sizeof(c_x25) - 1, sprintrc(rc)); for (size_t i = 0; i < 2; i++) { rc = connect(-1, x25_void, sizeof(c_x25) + i); - printf("connect(-1, {sa_family=AF_X25" + pidns_print_leader(); + printf("connect(-1, {sa_family=AF_X25" ", sx25_addr={x25_addr=\"0123456789abcde\"...}" "}, %zu) = %s\n", sizeof(c_x25) + i, sprintrc(rc)); @@ -442,6 +473,7 @@ check_x25(void) struct sockaddr_x25 *const x25 = x25_void; x25->sx25_addr.x25_addr[10] = '\0'; rc = connect(-1, x25_void, sizeof(c_x25)); + pidns_print_leader(); printf("connect(-1, {sa_family=AF_X25" ", sx25_addr={x25_addr=\"0123456789\"}" "}, %zu) = %s\n", @@ -457,19 +489,21 @@ check_nl(void) nl->nl_groups = 0xfacefeed; unsigned int len = sizeof(*nl); int ret = connect(-1, (void *) nl, len); + pidns_print_leader(); printf("connect(-1, {sa_family=AF_NETLINK, nl_pid=%d" ", nl_groups=%#08x}, %u) = %d EBADF (%m)\n", nl->nl_pid, nl->nl_groups, len, ret); nl = ((void *) nl) - 4; nl->nl_family = AF_NETLINK; - nl->nl_pid = 1234567890; + nl->nl_pid = getpid(); nl->nl_groups = 0xfacefeed; len = sizeof(*nl) + 4; ret = connect(-1, (void *) nl, len); - printf("connect(-1, {sa_family=AF_NETLINK, nl_pid=%d" + pidns_print_leader(); + printf("connect(-1, {sa_family=AF_NETLINK, nl_pid=%d%s" ", nl_groups=%#08x}, %u) = %d EBADF (%m)\n", - nl->nl_pid, nl->nl_groups, len, ret); + nl->nl_pid, pidns_pid2str(PT_TGID), nl->nl_groups, len, ret); } static void @@ -487,6 +521,7 @@ check_ll(void) void *ll = tail_memdup(&c_ll, sizeof(c_ll)); unsigned int len = sizeof(c_ll); int ret = connect(-1, ll, len); + pidns_print_leader(); printf("connect(-1, {sa_family=AF_PACKET" ", sll_protocol=htons(ETH_P_ALL)" ", sll_ifindex=%u, sll_hatype=ARPHRD_ETHER" @@ -502,6 +537,7 @@ check_ll(void) ((struct sockaddr_ll *) ll)->sll_halen++; ret = connect(-1, ll, len); + pidns_print_leader(); printf("connect(-1, {sa_family=AF_PACKET" ", sll_protocol=htons(ETH_P_ALL)" ", sll_ifindex=%u, sll_hatype=ARPHRD_ETHER" @@ -517,6 +553,7 @@ check_ll(void) ((struct sockaddr_ll *) ll)->sll_halen = 0; ret = connect(-1, ll, len); + pidns_print_leader(); printf("connect(-1, {sa_family=AF_PACKET" ", sll_protocol=htons(ETH_P_ALL)" ", sll_ifindex=%u, sll_hatype=ARPHRD_ETHER" @@ -526,7 +563,8 @@ check_ll(void) ((struct sockaddr_ll *) ll)->sll_ifindex = ifindex_lo(); if (((struct sockaddr_ll *) ll)->sll_ifindex) { ret = connect(-1, ll, len); - printf("connect(-1, {sa_family=AF_PACKET" + pidns_print_leader(); + printf("connect(-1, {sa_family=AF_PACKET" ", sll_protocol=htons(ETH_P_ALL)" ", sll_ifindex=%s" ", sll_hatype=ARPHRD_ETHER" @@ -549,11 +587,13 @@ check_hci(void) unsigned int len = sizeof(*hci); int ret = connect(-1, (void *) hci, 4); + pidns_print_leader(); printf("connect(-1, {sa_family=AF_BLUETOOTH, hci_dev=htobs(%hu)" "}, 4) = %d EBADF (%m)\n", h_port, ret); ret = connect(-1, (void *) hci, len); + pidns_print_leader(); printf("connect(-1, {sa_family=AF_BLUETOOTH, hci_dev=htobs(%hu)" # ifdef HAVE_STRUCT_SOCKADDR_HCI_HCI_CHANNEL ", hci_channel=HCI_CHANNEL_RAW" @@ -572,6 +612,7 @@ check_sco(void) void *sco = tail_memdup(&c_sco, sizeof(c_sco)); unsigned int len = sizeof(c_sco); int ret = connect(-1, sco, len); + pidns_print_leader(); printf("connect(-1, {sa_family=AF_BLUETOOTH" ", sco_bdaddr=%02x:%02x:%02x:%02x:%02x:%02x" "}, %u) = %d EBADF (%m)\n", @@ -592,6 +633,7 @@ check_rc(void) void *rc = tail_memdup(&c_rc, sizeof(c_rc)); unsigned int len = sizeof(c_rc); int ret = connect(-1, rc, len); + pidns_print_leader(); printf("connect(-1, {sa_family=AF_BLUETOOTH" ", rc_bdaddr=%02x:%02x:%02x:%02x:%02x:%02x" ", rc_channel=%u}, %u) = %d EBADF (%m)\n", @@ -619,6 +661,7 @@ check_l2(void) unsigned int len = sizeof(c_l2); int ret = connect(-1, l2, len); + pidns_print_leader(); printf("connect(-1, {sa_family=AF_BLUETOOTH" ", l2_psm=htobs(L2CAP_PSM_DYN_START + %hu)" ", l2_bdaddr=%02x:%02x:%02x:%02x:%02x:%02x" @@ -640,6 +683,7 @@ check_l2(void) # endif memcpy(l2, &c_l2, sizeof(c_l2)); ret = connect(-1, l2, len); + pidns_print_leader(); printf("connect(-1, {sa_family=AF_BLUETOOTH" ", l2_psm=htobs(L2CAP_PSM_SDP)" ", l2_bdaddr=%02x:%02x:%02x:%02x:%02x:%02x" @@ -660,6 +704,7 @@ check_l2(void) # endif memcpy(l2, &c_l2, sizeof(c_l2)); ret = connect(-1, l2, len); + pidns_print_leader(); printf("connect(-1, {sa_family=AF_BLUETOOTH" ", l2_psm=htobs(0xbad /* L2CAP_PSM_??? */)" ", l2_bdaddr=%02x:%02x:%02x:%02x:%02x:%02x" @@ -677,6 +722,7 @@ check_l2(void) c_l2.l2_cid = htobs(0xffff); memcpy(l2, &c_l2, 12); ret = connect(-1, l2, 12); + pidns_print_leader(); printf("connect(-1, {sa_family=AF_BLUETOOTH" ", l2_psm=htobs(L2CAP_PSM_AUTO_END)" ", l2_bdaddr=%02x:%02x:%02x:%02x:%02x:%02x" @@ -700,6 +746,7 @@ check_raw(void) u.sa->sa_family = 0xff; unsigned int len = sizeof(*u.st) + 8; int ret = connect(-1, (void *) u.st, len); + pidns_print_leader(); printf("connect(-1, {sa_family=%#x /* AF_??? */, sa_data=\"%.*u\"}" ", %u) = %d EBADF (%m)\n", u.sa->sa_family, (int) (sizeof(*u.st) - sizeof(u.sa->sa_family)), 0, len, ret); @@ -707,11 +754,13 @@ check_raw(void) u.sa->sa_family = 0; len = sizeof(u.sa->sa_family) + 1; ret = connect(-1, (void *) u.st, len); + pidns_print_leader(); printf("connect(-1, {sa_family=AF_UNSPEC, sa_data=\"0\"}, %u)" " = %d EBADF (%m)\n", len, ret); u.sa->sa_family = AF_BLUETOOTH; ret = connect(-1, (void *) u.st, len); + pidns_print_leader(); printf("connect(-1, {sa_family=AF_BLUETOOTH, sa_data=\"0\"}, %u)" " = %d EBADF (%m)\n", len, ret); } @@ -719,6 +768,8 @@ check_raw(void) int main(void) { + PIDNS_TEST_INIT; + check_un(); check_in(); check_in6(); @@ -735,6 +786,7 @@ main(void) #endif check_raw(); + pidns_print_leader(); puts("+++ exited with 0 +++"); return 0; } diff --git a/tests/netlink_audit--pidns-translation.c b/tests/netlink_audit--pidns-translation.c new file mode 100644 index 00000000..e08f9168 --- /dev/null +++ b/tests/netlink_audit--pidns-translation.c @@ -0,0 +1,2 @@ +#define PIDNS_TRANSLATION +#include "netlink_audit.c" diff --git a/tests/netlink_audit--pidns-translation.test b/tests/netlink_audit--pidns-translation.test new file mode 100755 index 00000000..fbc32435 --- /dev/null +++ b/tests/netlink_audit--pidns-translation.test @@ -0,0 +1,13 @@ +#!/bin/sh +# +# Check decoding of NETLINK_SOCK_DIAG protocol +# +# Copyright (c) 2020 The strace developers. +# All rights reserved. +# +# SPDX-License-Identifier: LGPL-2.1-or-later + +. "${srcdir=.}/init.sh" + +run_prog ../netlink_netlink_diag +test_pidns -e trace=sendto "$@" diff --git a/tests/netlink_audit.c b/tests/netlink_audit.c index eba609a1..5dfcd786 100644 --- a/tests/netlink_audit.c +++ b/tests/netlink_audit.c @@ -7,6 +7,7 @@ */ #include "tests.h" +#include "pidns.h" #include #include #include @@ -17,18 +18,23 @@ static void test_nlmsg_type(const int fd) { + PIDNS_TEST_INIT; + long rc; struct nlmsghdr nlh = { .nlmsg_len = sizeof(nlh), .nlmsg_type = AUDIT_GET, .nlmsg_flags = NLM_F_REQUEST, + .nlmsg_pid = getpid(), }; rc = sendto(fd, &nlh, sizeof(nlh), MSG_DONTWAIT, NULL, 0); + pidns_print_leader(); printf("sendto(%d, {len=%u, type=AUDIT_GET" - ", flags=NLM_F_REQUEST, seq=0, pid=0}" + ", flags=NLM_F_REQUEST, seq=0, pid=%d%s}" ", %u, MSG_DONTWAIT, NULL, 0) = %s\n", - fd, nlh.nlmsg_len, (unsigned) sizeof(nlh), sprintrc(rc)); + fd, nlh.nlmsg_len, nlh.nlmsg_pid, pidns_pid2str(PT_TGID), + (unsigned) sizeof(nlh), sprintrc(rc)); } int main(void) @@ -39,6 +45,7 @@ int main(void) test_nlmsg_type(fd); + pidns_print_leader(); printf("+++ exited with 0 +++\n"); return 0; diff --git a/tests/pidfd_open--pidns-translation.c b/tests/pidfd_open--pidns-translation.c new file mode 100644 index 00000000..c38e37a8 --- /dev/null +++ b/tests/pidfd_open--pidns-translation.c @@ -0,0 +1,2 @@ +#define PIDNS_TRANSLATION +#include "pidfd_open.c" diff --git a/tests/pidfd_open.c b/tests/pidfd_open.c index 5860adde..e5d74a91 100644 --- a/tests/pidfd_open.c +++ b/tests/pidfd_open.c @@ -10,6 +10,7 @@ #include "tests.h" #include "scno.h" +#include "pidns.h" #ifdef __NR_pidfd_open @@ -37,6 +38,8 @@ k_pidfd_open(const unsigned int pid, const unsigned int flags) int main(void) { + PIDNS_TEST_INIT; + # if defined PATH_TRACING || defined PRINT_PATHS skip_if_unavailable("/proc/self/fd/"); # endif @@ -50,16 +53,19 @@ main(void) k_pidfd_open(0, 0); # ifndef PATH_TRACING + pidns_print_leader(); printf("pidfd_open(0, 0) = %s\n", errstr); # endif k_pidfd_open(-1U, 0); # ifndef PATH_TRACING + pidns_print_leader(); printf("pidfd_open(-1, 0) = %s\n", errstr); # endif k_pidfd_open(0, -1U); # ifndef PATH_TRACING + pidns_print_leader(); printf("pidfd_open(0, %#x) = %s\n", -1U, errstr); # endif @@ -68,7 +74,10 @@ main(void) k_pidfd_open(pid, flags); # ifndef PATH_TRACING - printf("pidfd_open(%d, %#x) = %s\n", pid, flags, errstr); + const char *pid_str = pidns_pid2str(PT_TGID); + pidns_print_leader(); + printf("pidfd_open(%d%s, %#x) = %s\n", + pid, pid_str, flags, errstr); # endif # ifdef PRINT_PATHS @@ -80,17 +89,19 @@ main(void) # endif # ifndef PATH_TRACING - printf("pidfd_open(%d, 0) = " + pidns_print_leader(); + printf("pidfd_open(%d%s, 0) = " # if defined PRINT_PIDFD - "%ld\n", pid, rc, pid + "%ld\n", pid, pid_str, rc, pid # elif defined PRINT_PATHS - "%ld\n", pid, rc + "%ld\n", pid, pid_str, rc # else - "%s\n", pid, errstr + "%s\n", pid, pid_str, errstr # endif ); # endif + pidns_print_leader(); puts("+++ exited with 0 +++"); return 0; } diff --git a/tests/pidfd_send_signal--pidns-translation.c b/tests/pidfd_send_signal--pidns-translation.c new file mode 100644 index 00000000..b04f10f5 --- /dev/null +++ b/tests/pidfd_send_signal--pidns-translation.c @@ -0,0 +1,2 @@ +#define PIDNS_TRANSLATION +#include "pidfd_send_signal.c" diff --git a/tests/pidfd_send_signal.c b/tests/pidfd_send_signal.c index 38b5bda1..a6b2d28c 100644 --- a/tests/pidfd_send_signal.c +++ b/tests/pidfd_send_signal.c @@ -10,6 +10,7 @@ #include "tests.h" #include #include "scno.h" +#include "pidns.h" #ifdef __NR_pidfd_send_signal @@ -36,6 +37,8 @@ sys_pidfd_send_signal(int pidfd, int sig, const void *info, int flags) int main(void) { + PIDNS_TEST_INIT; + static const char null_path[] = "/dev/null"; int fd = open(null_path, O_RDONLY); @@ -46,19 +49,23 @@ main(void) const void *esi = (const void *) si + 1; sys_pidfd_send_signal(fd, SIGUSR1, esi, 0); + pidns_print_leader(); printf("pidfd_send_signal(%d, SIGUSR1, %p, 0) = %s\n", fd, esi, errstr); si->si_signo = SIGUSR1; si->si_code = SI_QUEUE; + si->si_pid = getpid(); sys_pidfd_send_signal(fd, SIGUSR2, si, -1); + pidns_print_leader(); printf("pidfd_send_signal(%d, SIGUSR2, {si_signo=SIGUSR1" - ", si_code=SI_QUEUE, si_errno=%u, si_pid=%d, si_uid=%d" + ", si_code=SI_QUEUE, si_errno=%u, si_pid=%d%s, si_uid=%d" ", si_value={int=%d, ptr=%p}}, %#x) = %s\n", - fd, si->si_errno, si->si_pid, si->si_uid, si->si_int, si->si_ptr, - -1U, errstr); + fd, si->si_errno, si->si_pid, pidns_pid2str(PT_TGID), si->si_uid, + si->si_int, si->si_ptr, -1U, errstr); + pidns_print_leader(); puts("+++ exited with 0 +++"); return 0; } diff --git a/tests/prlimit64--pidns-translation.c b/tests/prlimit64--pidns-translation.c new file mode 100644 index 00000000..3972de66 --- /dev/null +++ b/tests/prlimit64--pidns-translation.c @@ -0,0 +1,2 @@ +#define PIDNS_TRANSLATION +#include "prlimit64.c" diff --git a/tests/prlimit64.c b/tests/prlimit64.c index 34201a2b..bc1a80b3 100644 --- a/tests/prlimit64.c +++ b/tests/prlimit64.c @@ -19,6 +19,7 @@ # include # include +# include "pidns.h" # include "xlat.h" # include "xlat/resources.h" @@ -42,8 +43,11 @@ sprint_rlim(uint64_t lim) int main(void) { + PIDNS_TEST_INIT; + unsigned long pid = (unsigned long) 0xdefaced00000000ULL | (unsigned) getpid(); + const char *pid_str = pidns_pid2str(PT_TGID); uint64_t *const rlimit = tail_alloc(sizeof(*rlimit) * 2); const struct xlat_data *xlat; size_t i = 0; @@ -54,18 +58,23 @@ main(void) unsigned long res = 0xfacefeed00000000ULL | xlat->val; long rc = syscall(__NR_prlimit64, pid, res, 0, rlimit); + pidns_print_leader(); if (rc) - printf("prlimit64(%d, %s, NULL, %p) = %ld %s (%m)\n", - (unsigned) pid, xlat->str, rlimit, + printf("prlimit64(%d%s, %s, NULL, %p) =" + " %ld %s (%m)\n", + (unsigned) pid, pid_str, + xlat->str, rlimit, rc, errno2name()); else - printf("prlimit64(%d, %s, NULL" + printf("prlimit64(%d%s, %s, NULL" ", {rlim_cur=%s, rlim_max=%s}) = 0\n", - (unsigned) pid, xlat->str, + (unsigned) pid, pid_str, + xlat->str, sprint_rlim(rlimit[0]), sprint_rlim(rlimit[1])); } + pidns_print_leader(); puts("+++ exited with 0 +++"); return 0; } diff --git a/tests/process_vm_readv--pidns-translation.c b/tests/process_vm_readv--pidns-translation.c new file mode 100644 index 00000000..0db29ca2 --- /dev/null +++ b/tests/process_vm_readv--pidns-translation.c @@ -0,0 +1,2 @@ +#define PIDNS_TRANSLATION +#include "process_vm_readv.c" diff --git a/tests/process_vm_readv_writev.c b/tests/process_vm_readv_writev.c index 9309135a..44e511dd 100644 --- a/tests/process_vm_readv_writev.c +++ b/tests/process_vm_readv_writev.c @@ -12,6 +12,7 @@ #include #include #include +#include "pidns.h" #if OP_WR # define in_iovec rmt_iovec @@ -121,7 +122,7 @@ print_iov(const struct iovec *iov, const void *arg_ptr, long rc) } static void -do_call(kernel_ulong_t pid, +do_call(kernel_ulong_t pid, enum pid_type pid_type, kernel_ulong_t local_iov, const char *local_arg, kernel_ulong_t liovcnt, kernel_ulong_t remote_iov, const char *remote_arg, @@ -135,7 +136,8 @@ do_call(kernel_ulong_t pid, flags); errstr = sprintrc(rc); - printf("%s(%d, ", OP_STR, (int) pid); + pidns_print_leader(); + printf("%s(%d%s, ", OP_STR, (int) pid, pidns_pid2str(pid_type)); if (pr_iov) pr_iov((const struct iovec *) (uintptr_t) local_iov, local_arg, @@ -164,6 +166,8 @@ ptr_cast(void *ptr) int main(void) { + PIDNS_TEST_INIT; + enum { SIZE_11 = 2, SIZE_12 = 3, @@ -243,18 +247,18 @@ main(void) fill_memory_ex(data2_out, SIZE_2, SEGM2_BASE, SIZE_2); - do_call(bogus_pid, (kernel_ulong_t) (uintptr_t) ARG_STR(NULL), + do_call(bogus_pid, PT_NONE, (kernel_ulong_t) (uintptr_t) ARG_STR(NULL), bogus_iovcnt1, (kernel_ulong_t) (uintptr_t) ARG_STR(NULL), bogus_iovcnt2, bogus_flags, NULL); - do_call(my_pid, ptr_cast(bogus_iov + ARRAY_SIZE(bogus_iovec)), + do_call(my_pid, PT_TGID, ptr_cast(bogus_iov + ARRAY_SIZE(bogus_iovec)), "[]", 0, ptr_cast(in_iov + ARRAY_SIZE(in_iovec)), "[]", 0, 0, NULL); - do_call(my_pid, ptr_cast(bogus_iov + ARRAY_SIZE(bogus_iovec)), NULL, - bogus_iovcnt1, ptr_cast(in_iov + ARRAY_SIZE(in_iovec)), NULL, - bogus_iovcnt2, 0, print_iov); + do_call(my_pid, PT_TGID, ptr_cast(bogus_iov + ARRAY_SIZE(bogus_iovec)), + NULL, bogus_iovcnt1, ptr_cast(in_iov + ARRAY_SIZE(in_iovec)), + NULL, bogus_iovcnt2, 0, print_iov); - do_call(my_pid, ptr_cast(bogus_iov), (char *) &bogus_arg, + do_call(my_pid, PT_TGID, ptr_cast(bogus_iov), (char *) &bogus_arg, ARRAY_SIZE(bogus_iovec), ptr_cast(rmt_iov + 2), (char *) &rmt_arg_cut, ARRAY_SIZE(rmt_iovec) - 2, 0, print_iov); @@ -263,7 +267,7 @@ main(void) lcl_arg_cut.check_rc = 1; #endif - do_call(my_pid, ptr_cast(lcl_iov + 2), (char *) &lcl_arg_cut, + do_call(my_pid, PT_TGID, ptr_cast(lcl_iov + 2), (char *) &lcl_arg_cut, ARRAY_SIZE(lcl_iovec) - 1, ptr_cast(bogus_iov + 2), (char *) &bogus_arg_cut, ARRAY_SIZE(bogus_iovec) - 1, 0, print_iov); @@ -273,15 +277,16 @@ main(void) rmt_arg_cut.addr_term = 1; rmt_arg_cut.count = 5; - do_call(my_pid, ptr_cast(lcl_iov + 2), (char *) &lcl_arg_cut, + do_call(my_pid, PT_TGID, ptr_cast(lcl_iov + 2), (char *) &lcl_arg_cut, ARRAY_SIZE(lcl_iovec) - 2, ptr_cast(rmt_iov + 1), (char *) &rmt_arg_cut, ARRAY_SIZE(rmt_iovec), 0, print_iov); /* Correct call */ - do_call(my_pid, ptr_cast(lcl_iov), (char *) &lcl_arg, + do_call(my_pid, PT_TGID, ptr_cast(lcl_iov), (char *) &lcl_arg, ARRAY_SIZE(lcl_iovec), ptr_cast(rmt_iov), (char *) &rmt_arg, ARRAY_SIZE(rmt_iovec), 0, print_iov); + pidns_print_leader(); puts("+++ exited with 0 +++"); return 0; diff --git a/tests/process_vm_writev--pidns-translation.c b/tests/process_vm_writev--pidns-translation.c new file mode 100644 index 00000000..9ba6a39b --- /dev/null +++ b/tests/process_vm_writev--pidns-translation.c @@ -0,0 +1,2 @@ +#define PIDNS_TRANSLATION +#include "process_vm_writev.c" diff --git a/tests/rt_sigqueueinfo--pidns-translation.c b/tests/rt_sigqueueinfo--pidns-translation.c new file mode 100644 index 00000000..74bfb464 --- /dev/null +++ b/tests/rt_sigqueueinfo--pidns-translation.c @@ -0,0 +1,2 @@ +#define PIDNS_TRANSLATION +#include "rt_sigqueueinfo.c" diff --git a/tests/rt_sigqueueinfo.c b/tests/rt_sigqueueinfo.c index c1693873..e22e4640 100644 --- a/tests/rt_sigqueueinfo.c +++ b/tests/rt_sigqueueinfo.c @@ -7,6 +7,7 @@ */ #include "tests.h" +#include "pidns.h" #include #include #include @@ -15,6 +16,8 @@ int main(void) { + PIDNS_TEST_INIT; + struct sigaction sa = { .sa_handler = SIG_IGN }; @@ -22,15 +25,19 @@ main(void) .sival_ptr = (void *) (unsigned long) 0xdeadbeefbadc0dedULL }; pid_t pid = getpid(); + const char *pid_str = pidns_pid2str(PT_TGID); assert(sigaction(SIGUSR1, &sa, NULL) == 0); if (sigqueue(pid, SIGUSR1, value)) perror_msg_and_skip("sigqueue"); - printf("rt_sigqueueinfo(%u, SIGUSR1, {si_signo=SIGUSR1, " - "si_code=SI_QUEUE, si_pid=%d, si_uid=%d, " + pidns_print_leader(); + printf("rt_sigqueueinfo(%d%s, SIGUSR1, {si_signo=SIGUSR1, " + "si_code=SI_QUEUE, si_pid=%d%s, si_uid=%u, " "si_value={int=%d, ptr=%p}}) = 0\n", - pid, pid, getuid(), value.sival_int, value.sival_ptr); - printf("+++ exited with 0 +++\n"); + pid, pid_str, pid, pid_str, + getuid(), value.sival_int, value.sival_ptr); + pidns_print_leader(); + puts("+++ exited with 0 +++"); return 0; } diff --git a/tests/rt_tgsigqueueinfo--pidns-translation.c b/tests/rt_tgsigqueueinfo--pidns-translation.c new file mode 100644 index 00000000..94396f00 --- /dev/null +++ b/tests/rt_tgsigqueueinfo--pidns-translation.c @@ -0,0 +1,2 @@ +#define PIDNS_TRANSLATION +#include "rt_tgsigqueueinfo.c" diff --git a/tests/rt_tgsigqueueinfo.c b/tests/rt_tgsigqueueinfo.c index 865c21f6..21d01cbb 100644 --- a/tests/rt_tgsigqueueinfo.c +++ b/tests/rt_tgsigqueueinfo.c @@ -10,8 +10,9 @@ #include "tests.h" #include "scno.h" +#include "pidns.h" -#ifdef __NR_rt_tgsigqueueinfo +#if defined __NR_rt_tgsigqueueinfo && defined __NR_gettid # include # include @@ -20,11 +21,11 @@ # include static long -k_tgsigqueueinfo(const pid_t pid, const int sig, const void *const info) +k_tgsigqueueinfo(const pid_t tgid, const int tid, const int sig, const void *const info) { return syscall(__NR_rt_tgsigqueueinfo, - F8ILL_KULONG_MASK | pid, - F8ILL_KULONG_MASK | pid, + F8ILL_KULONG_MASK | tgid, + F8ILL_KULONG_MASK | tid, F8ILL_KULONG_MASK | sig, info); } @@ -32,6 +33,8 @@ k_tgsigqueueinfo(const pid_t pid, const int sig, const void *const info) int main(void) { + PIDNS_TEST_INIT; + const struct sigaction sa = { .sa_handler = SIG_IGN }; @@ -48,17 +51,22 @@ main(void) info->si_value.sival_ptr = (void *) (unsigned long) 0xdeadbeeffacefeedULL; - if (k_tgsigqueueinfo(info->si_pid, SIGUSR1, info)) + if (k_tgsigqueueinfo(getpid(), syscall(__NR_gettid), SIGUSR1, info)) (errno == ENOSYS ? perror_msg_and_skip : perror_msg_and_fail)( "rt_tgsigqueueinfo"); - printf("rt_tgsigqueueinfo(%u, %u, %s, {si_signo=%s" - ", si_code=SI_QUEUE, si_errno=ENOENT, si_pid=%d" + pidns_print_leader(); + printf("rt_tgsigqueueinfo(%d%s, %d%s, %s, {si_signo=%s" + ", si_code=SI_QUEUE, si_errno=ENOENT, si_pid=%d%s" ", si_uid=%d, si_value={int=%d, ptr=%p}}) = 0\n", - info->si_pid, info->si_pid, "SIGUSR1", "SIGUSR1", - info->si_pid, info->si_uid, info->si_value.sival_int, + info->si_pid, pidns_pid2str(PT_TGID), + info->si_pid, pidns_pid2str(PT_TID), + "SIGUSR1", "SIGUSR1", + info->si_pid, pidns_pid2str(PT_TGID), + info->si_uid, info->si_value.sival_int, info->si_value.sival_ptr); + pidns_print_leader(); puts("+++ exited with 0 +++"); return 0; } diff --git a/tests/sched_xetaffinity--pidns-translation.c b/tests/sched_xetaffinity--pidns-translation.c new file mode 100644 index 00000000..814e3989 --- /dev/null +++ b/tests/sched_xetaffinity--pidns-translation.c @@ -0,0 +1,2 @@ +#define PIDNS_TRANSLATION +#include "sched_xetaffinity.c" diff --git a/tests/sched_xetaffinity.c b/tests/sched_xetaffinity.c index cebff3ab..2e508ca3 100644 --- a/tests/sched_xetaffinity.c +++ b/tests/sched_xetaffinity.c @@ -10,6 +10,7 @@ #include "tests.h" #include "scno.h" +#include "pidns.h" #include #if defined __NR_sched_getaffinity && defined __NR_sched_setaffinity \ @@ -41,8 +42,11 @@ setaffinity(unsigned long pid, unsigned long size, void *set) int main(void) { + PIDNS_TEST_INIT; + unsigned int cpuset_size = 1; const pid_t pid = getpid(); + const char *pid_str = pidns_pid2str(PT_TGID); while (cpuset_size) { assert(getaffinity(pid, cpuset_size, NULL) == -1); @@ -50,18 +54,21 @@ main(void) break; if (EINVAL != errno) perror_msg_and_skip("sched_getaffinity"); - printf("sched_getaffinity(%d, %u, NULL) = %s\n", - pid, cpuset_size, errstr); + pidns_print_leader(); + printf("sched_getaffinity(%d%s, %u, NULL) = %s\n", + pid, pid_str, cpuset_size, errstr); cpuset_size <<= 1; } assert(cpuset_size); - printf("sched_getaffinity(%d, %u, NULL) = %s\n", - pid, cpuset_size, errstr); + pidns_print_leader(); + printf("sched_getaffinity(%d%s, %u, NULL) = %s\n", + pid, pid_str, cpuset_size, errstr); cpu_set_t *cpuset = tail_alloc(cpuset_size); getaffinity(pid, cpuset_size, cpuset + 1); - printf("sched_getaffinity(%d, %u, %p) = %s\n", - pid, cpuset_size, cpuset + 1, errstr); + pidns_print_leader(); + printf("sched_getaffinity(%d%s, %u, %p) = %s\n", + pid, pid_str, cpuset_size, cpuset + 1, errstr); int ret_size = getaffinity(pid, cpuset_size, cpuset); if (ret_size < 0) @@ -69,7 +76,8 @@ main(void) pid, (unsigned) cpuset_size, cpuset, errstr); assert(ret_size <= (int) cpuset_size); - printf("sched_getaffinity(%d, %u, [", pid, cpuset_size); + pidns_print_leader(); + printf("sched_getaffinity(%d%s, %u, [", pid, pid_str, cpuset_size); const char *sep; unsigned int i, cpu; for (i = 0, cpu = 0, sep = ""; i < (unsigned) ret_size * 8; ++i) { @@ -85,8 +93,9 @@ main(void) CPU_SET_S(cpu, cpuset_size, cpuset); if (setaffinity(pid, cpuset_size, cpuset)) perror_msg_and_skip("sched_setaffinity"); - printf("sched_setaffinity(%d, %u, [%u]) = 0\n", - pid, cpuset_size, cpu); + pidns_print_leader(); + printf("sched_setaffinity(%d%s, %u, [%u]) = 0\n", + pid, pid_str, cpuset_size, cpu); const unsigned int big_size = cpuset_size < 128 ? 128 : cpuset_size * 2; cpuset = tail_alloc(big_size); @@ -95,7 +104,8 @@ main(void) perror_msg_and_fail("sched_getaffinity(%d, %u, %p) = %s\n", pid, big_size, cpuset, errstr); assert(ret_size <= (int) big_size); - printf("sched_getaffinity(%d, %u, [", pid, big_size); + pidns_print_leader(); + printf("sched_getaffinity(%d%s, %u, [", pid, pid_str, big_size); for (i = 0, sep = ""; i < (unsigned) ret_size * 8; ++i) { if (CPU_ISSET_S(i, (unsigned) ret_size, cpuset)) { printf("%s%u", sep, i); @@ -104,6 +114,7 @@ main(void) } printf("]) = %s\n", errstr); + pidns_print_leader(); puts("+++ exited with 0 +++"); return 0; } diff --git a/tests/sched_xetattr--pidns-translation.c b/tests/sched_xetattr--pidns-translation.c new file mode 100644 index 00000000..c152023d --- /dev/null +++ b/tests/sched_xetattr--pidns-translation.c @@ -0,0 +1,2 @@ +#define PIDNS_TRANSLATION +#include "sched_xetattr.c" diff --git a/tests/sched_xetattr.c b/tests/sched_xetattr.c index c63d7a80..4a76b2d6 100644 --- a/tests/sched_xetattr.c +++ b/tests/sched_xetattr.c @@ -15,6 +15,7 @@ # include # include # include +# include "pidns.h" # include "sched_attr.h" # include "xlat.h" # include "xlat/schedulers.h" @@ -41,6 +42,8 @@ sys_sched_setattr(kernel_ulong_t pid, kernel_ulong_t attr, kernel_ulong_t flags) int main(void) { + PIDNS_TEST_INIT; + static const kernel_ulong_t bogus_pid = (kernel_ulong_t) 0xdefacedfacefeedULL; static const kernel_ulong_t bogus_size = @@ -48,20 +51,28 @@ main(void) static const kernel_ulong_t bogus_flags = (kernel_ulong_t) 0xdefaceddeadc0deULL; + const int pid = getpid(); + const char *pid_str = pidns_pid2str(PT_TGID); + TAIL_ALLOC_OBJECT_CONST_PTR(struct sched_attr, attr); TAIL_ALLOC_OBJECT_CONST_PTR(unsigned int, psize); void *const efault = attr + 1; - sys_sched_getattr(0, 0, 0, 0); - printf("sched_getattr(0, NULL, 0, 0) = %s\n", errstr); + sys_sched_getattr(pid, 0, 0, 0); + pidns_print_leader(); + printf("sched_getattr(%d%s, NULL, 0, 0) = %s\n", + pid, pid_str, errstr); sys_sched_getattr(0, (unsigned long) attr, 0, 0); + pidns_print_leader(); printf("sched_getattr(0, %p, 0, 0) = %s\n", attr, errstr); sys_sched_getattr(bogus_pid, 0, 0, 0); + pidns_print_leader(); printf("sched_getattr(%d, NULL, 0, 0) = %s\n", (int) bogus_pid, errstr); sys_sched_getattr(-1U, (unsigned long) attr, bogus_size, bogus_flags); + pidns_print_leader(); printf("sched_getattr(-1, %p, %s%u, %u) = %s\n", attr, # if defined __arm64__ || defined __aarch64__ @@ -72,11 +83,13 @@ main(void) (unsigned) bogus_size, (unsigned) bogus_flags, errstr); sys_sched_getattr(0, (unsigned long) efault, SCHED_ATTR_MIN_SIZE, 0); + pidns_print_leader(); printf("sched_getattr(0, %p, %u, 0) = %s\n", efault, (unsigned) SCHED_ATTR_MIN_SIZE, errstr); if (sys_sched_getattr(0, (unsigned long) attr, SCHED_ATTR_MIN_SIZE, 0)) perror_msg_and_skip("sched_getattr"); + pidns_print_leader(); printf("sched_getattr(0, {size=%u, sched_policy=", attr->size); printxval(schedulers, attr->sched_policy, NULL); printf(", sched_flags=%s, sched_nice=%d, sched_priority=%u" @@ -91,11 +104,13 @@ main(void) (unsigned) SCHED_ATTR_MIN_SIZE); sys_sched_getattr(0, (unsigned long) efault, sizeof(*attr), 0); + pidns_print_leader(); printf("sched_getattr(0, %p, %u, 0) = %s\n", efault, (unsigned) sizeof(*attr), errstr); if (sys_sched_getattr(0, (unsigned long) attr, sizeof(*attr), 0)) perror_msg_and_skip("sched_getattr"); + pidns_print_leader(); printf("sched_getattr(0, {size=%u, sched_policy=", attr->size); printxval(schedulers, attr->sched_policy, NULL); printf(", sched_flags=%s, sched_nice=%d, sched_priority=%u" @@ -121,11 +136,13 @@ main(void) F8ILL_KULONG_MASK | sizeof(*attr), F8ILL_KULONG_MASK); # if defined __arm64__ || defined __aarch64__ if (rc) { + pidns_print_leader(); printf("sched_getattr(0, %p, 0xffffffff<<32|%u, 0) = %s\n", attr, (unsigned) sizeof(*attr), errstr); } else # endif { + pidns_print_leader(); printf("sched_getattr(0, {size=%u, sched_policy=", attr->size); printxval(schedulers, attr->sched_policy, NULL); printf(", sched_flags=%s, sched_nice=%d, sched_priority=%u" @@ -146,13 +163,16 @@ main(void) } sys_sched_setattr(bogus_pid, 0, 0); + pidns_print_leader(); printf("sched_setattr(%d, NULL, 0) = %s\n", (int) bogus_pid, errstr); attr->sched_flags |= 1; - if (sys_sched_setattr(0, (unsigned long) attr, 0)) + if (sys_sched_setattr(pid, (unsigned long) attr, 0)) perror_msg_and_skip("sched_setattr"); - printf("sched_setattr(0, {size=%u, sched_policy=", attr->size); + pidns_print_leader(); + printf("sched_setattr(%d%s, {size=%u, sched_policy=", + pid, pid_str, attr->size); printxval(schedulers, attr->sched_policy, NULL); printf(", sched_flags=%s, sched_nice=%d, sched_priority=%u" ", sched_runtime=%" PRIu64 ", sched_deadline=%" PRIu64 @@ -172,6 +192,7 @@ main(void) sys_sched_setattr(F8ILL_KULONG_MASK, (unsigned long) attr, F8ILL_KULONG_MASK); + pidns_print_leader(); printf("sched_setattr(0, {size=%u, sched_policy=", attr->size); printxval(schedulers, attr->sched_policy, NULL); printf(", sched_flags=%s, sched_nice=%d, sched_priority=%u" @@ -193,11 +214,13 @@ main(void) *psize = attr->size; sys_sched_setattr(0, (unsigned long) psize, 0); + pidns_print_leader(); printf("sched_setattr(0, %p, 0) = %s\n", psize, errstr); attr->size = 0; sys_sched_setattr(0, (unsigned long) attr, 0); + pidns_print_leader(); printf("sched_setattr(0, {size=%u, sched_policy=", attr->size); printxval(schedulers, attr->sched_policy, NULL); printf(", sched_flags=%s, sched_nice=%d, sched_priority=%u" @@ -213,12 +236,14 @@ main(void) attr->size = 1; sys_sched_setattr(0, (unsigned long) attr, 0); + pidns_print_leader(); printf("sched_setattr(0, {size=%u} => {size=%u}, 0) = %s\n", 1, attr->size, errstr); attr->size = SCHED_ATTR_MIN_SIZE - 1; sys_sched_setattr(0, (unsigned long) attr, 0); + pidns_print_leader(); printf("sched_setattr(0, {size=%u} => {size=%u}, 0) = %s\n", SCHED_ATTR_MIN_SIZE - 1, attr->size, errstr); @@ -232,6 +257,7 @@ main(void) attr->sched_period = 0xded1ca7edda7aca7ULL; sys_sched_setattr(bogus_pid, (unsigned long) attr, bogus_flags); + pidns_print_leader(); printf("sched_setattr(%d, {size=%u, sched_policy=%#x /* SCHED_??? */, " "sched_flags=%#" PRIx64 " /* SCHED_FLAG_??? */, " "sched_nice=%d, sched_priority=%u, sched_runtime=%" PRIu64 ", " @@ -274,6 +300,7 @@ main(void) attr->sched_period = 0xded1ca7edda7aca7ULL; sys_sched_setattr(bogus_pid, (unsigned long) attr, bogus_flags); + pidns_print_leader(); printf("sched_setattr(%d, {size=%u, sched_policy=%#x /* SCHED_??? */, " "sched_flags=SCHED_FLAG_RESET_ON_FORK|SCHED_FLAG_RECLAIM|" "SCHED_FLAG_DL_OVERRUN|0x80, " @@ -296,11 +323,13 @@ main(void) const kernel_ulong_t ill = f8ill_ptr_to_kulong(attr); sys_sched_getattr(0, ill, sizeof(*attr), 0); + pidns_print_leader(); printf("sched_getattr(0, %#llx, %u, 0) = %s\n", (unsigned long long) ill, (unsigned) sizeof(*attr), errstr); sys_sched_setattr(0, ill, 0); + pidns_print_leader(); printf("sched_setattr(0, %#llx, 0) = %s\n", (unsigned long long) ill, errstr); } @@ -310,6 +339,7 @@ main(void) attr->sched_flags = 0x8fULL; sys_sched_setattr(bogus_pid, (unsigned long) attr, bogus_flags); + pidns_print_leader(); printf("sched_setattr(%d, {size=%u, " "sched_flags=SCHED_FLAG_RESET_ON_FORK|SCHED_FLAG_RECLAIM|" "SCHED_FLAG_DL_OVERRUN|SCHED_FLAG_KEEP_POLICY|0x80, " @@ -329,11 +359,13 @@ main(void) const kernel_ulong_t ill = f8ill_ptr_to_kulong(attr); sys_sched_getattr(0, ill, sizeof(*attr), 0); + pidns_print_leader(); printf("sched_getattr(0, %#llx, %u, 0) = %s\n", (unsigned long long) ill, (unsigned) sizeof(*attr), errstr); sys_sched_setattr(0, ill, 0); + pidns_print_leader(); printf("sched_setattr(0, %#llx, 0) = %s\n", (unsigned long long) ill, errstr); } @@ -342,6 +374,7 @@ main(void) attr->sched_flags = 0xe7ULL; sys_sched_setattr(bogus_pid, (unsigned long) attr, bogus_flags); + pidns_print_leader(); printf("sched_setattr(%d, {size=%u, sched_policy=%#x /* SCHED_??? */, " "sched_flags=SCHED_FLAG_RESET_ON_FORK|SCHED_FLAG_RECLAIM|" "SCHED_FLAG_DL_OVERRUN|SCHED_FLAG_UTIL_CLAMP_MIN" @@ -365,11 +398,13 @@ main(void) const kernel_ulong_t ill = f8ill_ptr_to_kulong(attr); sys_sched_getattr(0, ill, sizeof(*attr), 0); + pidns_print_leader(); printf("sched_getattr(0, %#llx, %u, 0) = %s\n", (unsigned long long) ill, (unsigned) sizeof(*attr), errstr); sys_sched_setattr(0, ill, 0); + pidns_print_leader(); printf("sched_setattr(0, %#llx, 0) = %s\n", (unsigned long long) ill, errstr); } @@ -377,6 +412,7 @@ main(void) attr->sched_flags = 0xcaffee90LL; sys_sched_setattr(bogus_pid, (unsigned long) attr, bogus_flags); + pidns_print_leader(); printf("sched_setattr(%d, {size=%u, sched_flags=SCHED_FLAG_KEEP_PARAMS" "|0xcaffee80, sched_util_min=%u, sched_util_max=%u}, %u) = %s\n", (int) bogus_pid, @@ -389,15 +425,18 @@ main(void) const kernel_ulong_t ill = f8ill_ptr_to_kulong(attr); sys_sched_getattr(0, ill, sizeof(*attr), 0); + pidns_print_leader(); printf("sched_getattr(0, %#llx, %u, 0) = %s\n", (unsigned long long) ill, (unsigned) sizeof(*attr), errstr); sys_sched_setattr(0, ill, 0); + pidns_print_leader(); printf("sched_setattr(0, %#llx, 0) = %s\n", (unsigned long long) ill, errstr); } + pidns_print_leader(); puts("+++ exited with 0 +++"); return 0; } diff --git a/tests/sched_xetparam--pidns-translation.c b/tests/sched_xetparam--pidns-translation.c new file mode 100644 index 00000000..9fb3e579 --- /dev/null +++ b/tests/sched_xetparam--pidns-translation.c @@ -0,0 +1,2 @@ +#define PIDNS_TRANSLATION +#include "sched_xetparam.c" diff --git a/tests/sched_xetparam.c b/tests/sched_xetparam.c index de3915b2..aa9c68cc 100644 --- a/tests/sched_xetparam.c +++ b/tests/sched_xetparam.c @@ -7,6 +7,7 @@ #include "tests.h" #include "scno.h" +# include "pidns.h" #if defined __NR_sched_getparam && defined __NR_sched_setparam @@ -17,18 +18,27 @@ int main(void) { + PIDNS_TEST_INIT; + struct sched_param *const param = tail_alloc(sizeof(struct sched_param)); - long rc = syscall(__NR_sched_getparam, 0, param); - printf("sched_getparam(0, [%d]) = %ld\n", - param->sched_priority, rc); + const int pid = getpid(); + const char *pid_str = pidns_pid2str(PT_TGID); + + long rc = syscall(__NR_sched_getparam, pid, param); + pidns_print_leader(); + printf("sched_getparam(%d%s, [%d]) = %ld\n", + pid, pid_str, param->sched_priority, rc); param->sched_priority = -1; - rc = syscall(__NR_sched_setparam, 0, param); - printf("sched_setparam(0, [%d]) = %ld %s (%m)\n", + rc = syscall(__NR_sched_setparam, pid, param); + pidns_print_leader(); + printf("sched_setparam(%d%s, [%d]) = %ld %s (%m)\n", + pid, pid_str, param->sched_priority, rc, errno2name()); + pidns_print_leader(); puts("+++ exited with 0 +++"); return 0; } diff --git a/tests/sched_xetscheduler--pidns-translation.c b/tests/sched_xetscheduler--pidns-translation.c new file mode 100644 index 00000000..78b794b2 --- /dev/null +++ b/tests/sched_xetscheduler--pidns-translation.c @@ -0,0 +1,2 @@ +#define PIDNS_TRANSLATION +#include "sched_xetscheduler.c" diff --git a/tests/sched_xetscheduler.c b/tests/sched_xetscheduler.c index 047e8676..91b5e32d 100644 --- a/tests/sched_xetscheduler.c +++ b/tests/sched_xetscheduler.c @@ -7,6 +7,7 @@ #include "tests.h" #include "scno.h" +#include "pidns.h" #if defined __NR_sched_getscheduler && defined __NR_sched_setscheduler @@ -17,8 +18,13 @@ int main(void) { + PIDNS_TEST_INIT; + TAIL_ALLOC_OBJECT_CONST_PTR(struct sched_param, param); - long rc = syscall(__NR_sched_getscheduler, 0); + const int pid = getpid(); + const char *pid_str = pidns_pid2str(PT_TGID); + + long rc = syscall(__NR_sched_getscheduler, pid); const char *scheduler; switch (rc) { case SCHED_FIFO: @@ -50,33 +56,43 @@ main(void) default: scheduler = "SCHED_OTHER"; } - printf("sched_getscheduler(0) = %ld (%s)\n", - rc, scheduler); + pidns_print_leader(); + printf("sched_getscheduler(%d%s) = %ld (%s)\n", + pid, pid_str, rc, scheduler); rc = syscall(__NR_sched_getscheduler, -1); + pidns_print_leader(); printf("sched_getscheduler(-1) = %s\n", sprintrc(rc)); param->sched_priority = -1; - rc = syscall(__NR_sched_setscheduler, 0, SCHED_FIFO, NULL); - printf("sched_setscheduler(0, SCHED_FIFO, NULL) = %s\n", sprintrc(rc)); + rc = syscall(__NR_sched_setscheduler, pid, SCHED_FIFO, NULL); + pidns_print_leader(); + printf("sched_setscheduler(%d%s, SCHED_FIFO, NULL) = %s\n", + pid, pid_str, sprintrc(rc)); - rc = syscall(__NR_sched_setscheduler, 0, SCHED_FIFO, param + 1); - printf("sched_setscheduler(0, SCHED_FIFO, %p) = %s\n", param + 1, - sprintrc(rc)); + rc = syscall(__NR_sched_setscheduler, pid, SCHED_FIFO, param + 1); + pidns_print_leader(); + printf("sched_setscheduler(%d%s, SCHED_FIFO, %p) = %s\n", + pid, pid_str, param + 1, sprintrc(rc)); - rc = syscall(__NR_sched_setscheduler, 0, 0xfaceda7a, param); - printf("sched_setscheduler(0, %#x /* SCHED_??? */, [%d]) = %s\n", - 0xfaceda7a, param->sched_priority, sprintrc(rc)); + rc = syscall(__NR_sched_setscheduler, pid, 0xfaceda7a, param); + pidns_print_leader(); + printf("sched_setscheduler(%d%s, %#x /* SCHED_??? */, [%d]) = %s\n", + pid, pid_str, 0xfaceda7a, + param->sched_priority, sprintrc(rc)); rc = syscall(__NR_sched_setscheduler, -1, SCHED_FIFO, param); + pidns_print_leader(); printf("sched_setscheduler(-1, SCHED_FIFO, [%d]) = %s\n", param->sched_priority, sprintrc(rc)); - rc = syscall(__NR_sched_setscheduler, 0, SCHED_FIFO, param); - printf("sched_setscheduler(0, SCHED_FIFO, [%d]) = %s\n", - param->sched_priority, sprintrc(rc)); + rc = syscall(__NR_sched_setscheduler, pid, SCHED_FIFO, param); + pidns_print_leader(); + printf("sched_setscheduler(%d%s, SCHED_FIFO, [%d]) = %s\n", + pid, pid_str, param->sched_priority, sprintrc(rc)); + pidns_print_leader(); puts("+++ exited with 0 +++"); return 0; } diff --git a/tests/signal_receive--pidns-translation.c b/tests/signal_receive--pidns-translation.c new file mode 100644 index 00000000..b4e3b2f8 --- /dev/null +++ b/tests/signal_receive--pidns-translation.c @@ -0,0 +1,2 @@ +#define PIDNS_TRANSLATION +#include "signal_receive.c" diff --git a/tests/signal_receive.c b/tests/signal_receive.c index ad3b4ebd..70441a9e 100644 --- a/tests/signal_receive.c +++ b/tests/signal_receive.c @@ -8,6 +8,7 @@ */ #include "tests.h" +#include "pidns.h" #include #include #include @@ -26,10 +27,13 @@ handler(int sig, siginfo_t *info, void *ucontext) int main(void) { + PIDNS_TEST_INIT; + static const char prefix[] = "KERNEL BUG"; int printed = 0; const int pid = getpid(); + const char *pid_str = pidns_pid2str(PT_TGID); const int uid = geteuid(); for (int sig = 1; sig <= 31; ++sig) { @@ -73,10 +77,13 @@ main(void) const int e_pid = s_pid; const int e_uid = s_uid; #endif - printf("kill(%d, %s) = 0\n", pid, signal2name(sig)); - printf("--- %s {si_signo=%s, si_code=SI_USER, si_pid=%d" + pidns_print_leader(); + printf("kill(%d%s, %s) = 0\n", pid, pid_str, signal2name(sig)); + pidns_print_leader(); + printf("--- %s {si_signo=%s, si_code=SI_USER, si_pid=%d%s" ", si_uid=%d} ---\n", - signal2name(sig), signal2name(e_sig), e_pid, e_uid); + signal2name(sig), signal2name(e_sig), + e_pid, pid_str, e_uid); if (s_code || sig != s_sig || pid != s_pid || uid != s_uid) { /* @@ -91,11 +98,11 @@ main(void) } fprintf(stderr, "%s: expected: si_signo=%d, si_code=%d" - ", si_pid=%d, si_uid=%d\n" + ", si_pid=%d%s, si_uid=%d\n" "%s: received: si_signo=%d, si_code=%d" - ", si_pid=%d, si_uid=%d\n", - prefix, sig, SI_USER, pid, uid, - prefix, sig, s_code, s_pid, s_uid); + ", si_pid=%d%s, si_uid=%d\n", + prefix, sig, SI_USER, pid, pid_str, uid, + prefix, sig, s_code, s_pid, pid_str, s_uid); } } @@ -104,6 +111,7 @@ main(void) "*** PLEASE FIX THE KERNEL ***\n", prefix); } + pidns_print_leader(); puts("+++ exited with 0 +++"); return 0; } diff --git a/tests/so_peercred--pidns-translation.c b/tests/so_peercred--pidns-translation.c new file mode 100644 index 00000000..402bbcfe --- /dev/null +++ b/tests/so_peercred--pidns-translation.c @@ -0,0 +1,2 @@ +#define PIDNS_TRANSLATION +#include "so_peercred.c" diff --git a/tests/so_peercred.c b/tests/so_peercred.c index 151bb175..20188bdb 100644 --- a/tests/so_peercred.c +++ b/tests/so_peercred.c @@ -9,6 +9,7 @@ */ #include "tests.h" +#include "pidns.h" #include #include @@ -53,6 +54,8 @@ so_str(void) int main(void) { + PIDNS_TEST_INIT; + TAIL_ALLOC_OBJECT_CONST_PTR(struct ucred, peercred); TAIL_ALLOC_OBJECT_CONST_PTR(socklen_t, len); @@ -75,6 +78,8 @@ main(void) struct ucred *const gid_truncated = tail_alloc(sizeof_gid_truncated); + const char *pid_str = pidns_pid2str(PT_TGID); + int sv[2]; if (socketpair(AF_UNIX, SOCK_STREAM, 0, sv)) perror_msg_and_skip("socketpair AF_UNIX SOCK_STREAM"); @@ -82,8 +87,10 @@ main(void) /* classic getsockopt */ *len = sizeof(*peercred); get_peercred(sv[0], peercred, len); + pidns_print_leader(); printf("getsockopt(%d, %s", sv[0], so_str()); PRINT_FIELD_D(", {", *peercred, pid); + printf("%s", pid_str); PRINT_FIELD_UID(", ", *peercred, uid); PRINT_FIELD_UID(", ", *peercred, gid); printf("}, [%d]) = %s\n", *len, errstr); @@ -91,14 +98,17 @@ main(void) /* getsockopt with zero optlen */ *len = 0; get_peercred(sv[0], peercred, len); + pidns_print_leader(); printf("getsockopt(%d, %s, %p, [0]) = %s\n", sv[0], so_str(), peercred, errstr); /* getsockopt with optlen larger than necessary - shortened */ *len = sizeof(*peercred) + 1; get_peercred(sv[0], peercred, len); + pidns_print_leader(); printf("getsockopt(%d, %s", sv[0], so_str()); PRINT_FIELD_D(", {", *peercred, pid); + printf("%s", pid_str); PRINT_FIELD_UID(", ", *peercred, uid); PRINT_FIELD_UID(", ", *peercred, gid); printf("}, [%u->%d]) = %s\n", @@ -110,6 +120,7 @@ main(void) */ *len = sizeof_pid_truncated; get_peercred(sv[0], pid_truncated, len); + pidns_print_leader(); printf("getsockopt(%d, %s, {pid=", sv[0], so_str()); print_quoted_hex(pid_truncated, *len); printf("}, [%d]) = %s\n", *len, errstr); @@ -120,8 +131,10 @@ main(void) */ *len = sizeof_pid; get_peercred(sv[0], pid, len); + pidns_print_leader(); printf("getsockopt(%d, %s", sv[0], so_str()); PRINT_FIELD_D(", {", *pid, pid); + printf("%s", pid_str); printf("}, [%d]) = %s\n", *len, errstr); /* @@ -136,8 +149,10 @@ main(void) * to struct ucred.pid field. */ memcpy(uid, uid_truncated, sizeof_uid_truncated); + pidns_print_leader(); printf("getsockopt(%d, %s", sv[0], so_str()); PRINT_FIELD_D(", {", *uid, pid); + printf("%s", pid_str); printf(", uid="); print_quoted_hex(&uid->uid, sizeof_uid_truncated - offsetof(struct ucred, uid)); @@ -149,8 +164,10 @@ main(void) */ *len = sizeof_uid; get_peercred(sv[0], uid, len); + pidns_print_leader(); printf("getsockopt(%d, %s", sv[0], so_str()); PRINT_FIELD_D(", {", *uid, pid); + printf("%s", pid_str); PRINT_FIELD_UID(", ", *uid, uid); printf("}, [%d]) = %s\n", *len, errstr); @@ -166,8 +183,10 @@ main(void) * to struct ucred.pid and struct ucred.uid fields. */ memcpy(peercred, gid_truncated, sizeof_gid_truncated); + pidns_print_leader(); printf("getsockopt(%d, %s", sv[0], so_str()); PRINT_FIELD_D(", {", *peercred, pid); + printf("%s", pid_str); PRINT_FIELD_UID(", ", *peercred, uid); printf(", gid="); print_quoted_hex(&peercred->gid, sizeof_gid_truncated - @@ -177,14 +196,17 @@ main(void) /* getsockopt optval EFAULT */ *len = sizeof(*peercred); get_peercred(sv[0], &peercred->uid, len); + pidns_print_leader(); printf("getsockopt(%d, %s, %p, [%d]) = %s\n", sv[0], so_str(), &peercred->uid, *len, errstr); /* getsockopt optlen EFAULT */ get_peercred(sv[0], peercred, len + 1); + pidns_print_leader(); printf("getsockopt(%d, %s, %p, %p) = %s\n", sv[0], so_str(), peercred, len + 1, errstr); + pidns_print_leader(); puts("+++ exited with 0 +++"); return 0; } diff --git a/tests/xet_robust_list--pidns-translation.c b/tests/xet_robust_list--pidns-translation.c new file mode 100644 index 00000000..e0477267 --- /dev/null +++ b/tests/xet_robust_list--pidns-translation.c @@ -0,0 +1,2 @@ +#define PIDNS_TRANSLATION +#include "xet_robust_list.c" diff --git a/tests/xet_robust_list.c b/tests/xet_robust_list.c index 43239c8b..b5751b0a 100644 --- a/tests/xet_robust_list.c +++ b/tests/xet_robust_list.c @@ -8,6 +8,7 @@ #include "tests.h" #include "scno.h" +#include "pidns.h" #if defined __NR_get_robust_list && defined __NR_set_robust_list @@ -30,27 +31,36 @@ sprintaddr(void *addr) int main(void) { + PIDNS_TEST_INIT; + const pid_t pid = getpid(); + const char *pid_str = pidns_pid2str(PT_TGID); const long long_pid = (unsigned long) (0xdeadbeef00000000LL | pid); TAIL_ALLOC_OBJECT_CONST_PTR(void *, p_head); TAIL_ALLOC_OBJECT_CONST_PTR(size_t, p_len); if (syscall(__NR_get_robust_list, long_pid, p_head, p_len)) perror_msg_and_skip("get_robust_list"); - printf("get_robust_list(%d, [%s], [%lu]) = 0\n", - (int) pid, sprintaddr(*p_head), (unsigned long) *p_len); + pidns_print_leader(); + printf("get_robust_list(%d%s, [%s], [%lu]) = 0\n", + pid, pid_str, sprintaddr(*p_head), + (unsigned long) *p_len); void *head = tail_alloc(*p_len); if (syscall(__NR_set_robust_list, head, *p_len)) perror_msg_and_skip("set_robust_list"); + pidns_print_leader(); printf("set_robust_list(%p, %lu) = 0\n", head, (unsigned long) *p_len); if (syscall(__NR_get_robust_list, long_pid, p_head, p_len)) perror_msg_and_skip("get_robust_list"); - printf("get_robust_list(%d, [%s], [%lu]) = 0\n", - (int) pid, sprintaddr(*p_head), (unsigned long) *p_len); + pidns_print_leader(); + printf("get_robust_list(%d%s, [%s], [%lu]) = 0\n", + pid, pid_str, sprintaddr(*p_head), + (unsigned long) *p_len); + pidns_print_leader(); puts("+++ exited with 0 +++"); return 0; } diff --git a/tests/xetpgid--pidns-translation.c b/tests/xetpgid--pidns-translation.c new file mode 100644 index 00000000..b6469628 --- /dev/null +++ b/tests/xetpgid--pidns-translation.c @@ -0,0 +1,2 @@ +#define PIDNS_TRANSLATION +#include "xetpgid.c" diff --git a/tests/xetpgid.c b/tests/xetpgid.c index 9b070af2..411edfc7 100644 --- a/tests/xetpgid.c +++ b/tests/xetpgid.c @@ -10,6 +10,7 @@ #include "tests.h" #include "scno.h" +#include "pidns.h" #if defined __NR_getpgid && defined __NR_setpgid @@ -19,13 +20,21 @@ int main(void) { - const int pid = getpid(); - long rc = syscall(__NR_getpgid, F8ILL_KULONG_MASK | pid); - printf("getpgid(%d) = %ld\n", pid, rc); - - rc = syscall(__NR_setpgid, F8ILL_KULONG_MASK, F8ILL_KULONG_MASK | pid); - printf("setpgid(0, %d) = %ld\n", pid, rc); + PIDNS_TEST_INIT; + const int pid = getpid(); + long pgid = syscall(__NR_getpgid, F8ILL_KULONG_MASK | pid); + pidns_print_leader(); + printf("getpgid(%d%s) = %ld%s\n", pid, pidns_pid2str(PT_TGID), + pgid, pidns_pid2str(PT_PGID)); + + long rc = syscall(__NR_setpgid, F8ILL_KULONG_MASK, + F8ILL_KULONG_MASK | pgid); + pidns_print_leader(); + printf("setpgid(0, %ld%s) = %s\n", pgid, pidns_pid2str(PT_PGID), + sprintrc(rc)); + + pidns_print_leader(); puts("+++ exited with 0 +++"); return 0; } diff --git a/tests/xetpriority--pidns-translation.c b/tests/xetpriority--pidns-translation.c new file mode 100644 index 00000000..c93669cb --- /dev/null +++ b/tests/xetpriority--pidns-translation.c @@ -0,0 +1,2 @@ +#define PIDNS_TRANSLATION +#include "xetpriority.c" diff --git a/tests/xetpriority.c b/tests/xetpriority.c index 2d61bd10..dd38217d 100644 --- a/tests/xetpriority.c +++ b/tests/xetpriority.c @@ -7,6 +7,7 @@ #include "tests.h" #include "scno.h" +#include "pidns.h" #if defined __NR_getpriority && defined __NR_setpriority @@ -17,15 +18,30 @@ int main(void) { + PIDNS_TEST_INIT; + const int pid = getpid(); + const int pgid = getpgid(0); + long rc = syscall(__NR_getpriority, PRIO_PROCESS, F8ILL_KULONG_MASK | pid); - printf("getpriority(PRIO_PROCESS, %d) = %ld\n", pid, rc); + pidns_print_leader(); + printf("getpriority(PRIO_PROCESS, %d%s) = %ld\n", + pid, pidns_pid2str(PT_TGID), rc); rc = syscall(__NR_setpriority, PRIO_PROCESS, F8ILL_KULONG_MASK | pid, F8ILL_KULONG_MASK); - printf("setpriority(PRIO_PROCESS, %d, 0) = %s\n", pid, sprintrc(rc)); + pidns_print_leader(); + printf("setpriority(PRIO_PROCESS, %d%s, 0) = %s\n", + pid, pidns_pid2str(PT_TGID), sprintrc(rc)); + + rc = syscall(__NR_getpriority, PRIO_PGRP, + F8ILL_KULONG_MASK | pgid); + pidns_print_leader(); + printf("getpriority(PRIO_PGRP, %d%s) = %ld\n", + pgid, pidns_pid2str(PT_PGID), rc); + pidns_print_leader(); puts("+++ exited with 0 +++"); return 0; } -- 2.27.0 From uzonyi.akos at gmail.com Thu Aug 6 19:02:09 2020 From: uzonyi.akos at gmail.com (=?UTF-8?q?=C3=81kos=20Uzonyi?=) Date: Thu, 6 Aug 2020 21:02:09 +0200 Subject: [PATCH v6 3/5] Use get_proc_pid for /proc paths In-Reply-To: <20200806190211.118721-1-uzonyi.akos@gmail.com> References: <20200806190211.118721-1-uzonyi.akos@gmail.com> Message-ID: <20200806190211.118721-4-uzonyi.akos@gmail.com> * mmap_cache.c (mmap_cache_rebuild_if_invalid): Use proc pid instead of tcp->pid for /proc path. * util.c (getfdproto): Likewise. (pidfd_get_pid): Likewise. * pathtrace.c (getfdpath_pid): Likewise. * strace.c (attach_tcb): Likewise. --- mmap_cache.c | 2 +- pathtrace.c | 5 ++++- strace.c | 2 +- util.c | 7 +++++-- 4 files changed, 11 insertions(+), 5 deletions(-) diff --git a/mmap_cache.c b/mmap_cache.c index 89c62254..9825df26 100644 --- a/mmap_cache.c +++ b/mmap_cache.c @@ -84,7 +84,7 @@ mmap_cache_rebuild_if_invalid(struct tcb *tcp, const char *caller) return MMAP_CACHE_REBUILD_READY; char filename[sizeof("/proc/4294967296/maps")]; - xsprintf(filename, "/proc/%u/maps", tcp->pid); + xsprintf(filename, "/proc/%u/maps", get_proc_pid(tcp)); FILE *fp = fopen_stream(filename, "r"); if (!fp) { diff --git a/pathtrace.c b/pathtrace.c index 5b60762b..74717a8a 100644 --- a/pathtrace.c +++ b/pathtrace.c @@ -87,7 +87,10 @@ getfdpath_pid(pid_t pid, int fd, char *buf, unsigned bufsize) if (fd < 0) return -1; - xsprintf(linkpath, "/proc/%u/fd/%u", pid, fd); + int proc_pid = 0; + translate_pid(NULL, pid, PT_TID, &proc_pid); + + xsprintf(linkpath, "/proc/%u/fd/%u", proc_pid, fd); n = readlink(linkpath, buf, bufsize - 1); /* * NB: if buf is too small, readlink doesn't fail, diff --git a/strace.c b/strace.c index 249533ea..ef23f08f 100644 --- a/strace.c +++ b/strace.c @@ -1196,7 +1196,7 @@ attach_tcb(struct tcb *const tcp) unsigned int ntid = 0, nerr = 0; if (followfork && tcp->pid != strace_child && - xsprintf(procdir, task_path, tcp->pid) > 0 && + xsprintf(procdir, task_path, get_proc_pid(tcp)) > 0 && (dir = opendir(procdir)) != NULL) { struct_dirent *de; diff --git a/util.c b/util.c index 094e5818..d87d022e 100644 --- a/util.c +++ b/util.c @@ -501,7 +501,7 @@ getfdproto(struct tcb *tcp, int fd) if (fd < 0) return SOCK_PROTO_UNKNOWN; - xsprintf(path, "/proc/%u/fd/%u", tcp->pid, fd); + xsprintf(path, "/proc/%u/fd/%u", get_proc_pid(tcp), fd); r = getxattr(path, "system.sockprotoname", buf, bufsize - 1); if (r <= 0) return SOCK_PROTO_UNKNOWN; @@ -582,8 +582,11 @@ printdev(struct tcb *tcp, int fd, const char *path) pid_t pidfd_get_pid(pid_t pid_of_fd, int fd) { + int proc_pid = 0; + translate_pid(NULL, pid_of_fd, PT_TID, &proc_pid); + char fdi_path[sizeof("/proc/%u/fdinfo/%u") + 2 * sizeof(int) * 3]; - xsprintf(fdi_path, "/proc/%u/fdinfo/%u", pid_of_fd, fd); + xsprintf(fdi_path, "/proc/%u/fdinfo/%u", proc_pid, fd); FILE *f = fopen_stream(fdi_path, "r"); if (!f) -- 2.27.0 From uzonyi.akos at gmail.com Thu Aug 6 19:02:07 2020 From: uzonyi.akos at gmail.com (=?UTF-8?q?=C3=81kos=20Uzonyi?=) Date: Thu, 6 Aug 2020 21:02:07 +0200 Subject: [PATCH v6 1/5] PID namespace translation support In-Reply-To: <20200806190211.118721-1-uzonyi.akos@gmail.com> References: <20200806190211.118721-1-uzonyi.akos@gmail.com> Message-ID: <20200806190211.118721-2-uzonyi.akos@gmail.com> * defs.h (pidns_translation): New variable. (tcb): Add pid_ns field. (RVAL_MASK): Change value from 013 to 017. (RVAL_TID, RVAL_SID, RVAL_TGID, RVAL_PGID): New definitions. (pid_type): New enum. (pidns_init, translate_pid, get_proc_pid, printpid, printpid_tgid_pgid): New function declarations. * largefile_wrappers.h (fstat_fd): New macro. * pidns.c: New file. * trie.c: New file. * trie.h: New file. * Makefile.am (libstrace_a_SOURCES): Add trie.c, trie.h, pidns.c. * strace.c (pidns_translation): New variable. (init): Add --pidns-translation option. * syscall.c (syscall_exiting_trace): Handle RVAL_* return values. * NEWS: Mention this. * strace.1.in: Add description for new option. Co-Authored-by: Eugene Syromyatnikov --- Makefile.am | 3 + NEWS | 1 + defs.h | 53 +++- largefile_wrappers.h | 2 + pidns.c | 613 +++++++++++++++++++++++++++++++++++++++++++ strace.1.in | 4 + strace.c | 9 + syscall.c | 15 ++ trie.c | 250 ++++++++++++++++++ trie.h | 89 +++++++ 10 files changed, 1038 insertions(+), 1 deletion(-) create mode 100644 pidns.c create mode 100644 trie.c create mode 100644 trie.h diff --git a/Makefile.am b/Makefile.am index f5447811..73c22035 100644 --- a/Makefile.am +++ b/Makefile.am @@ -233,6 +233,7 @@ libstrace_a_SOURCES = \ personality.c \ pidfd_getfd.c \ pidfd_open.c \ + pidns.c \ pkeys.c \ poll.c \ prctl.c \ @@ -344,6 +345,8 @@ libstrace_a_SOURCES = \ time.c \ times.c \ trace_event.h \ + trie.c \ + trie.h \ truncate.c \ ubi.c \ ucopy.c \ diff --git a/NEWS b/NEWS index b83f9e80..9086fde9 100644 --- a/NEWS +++ b/NEWS @@ -14,6 +14,7 @@ Noteworthy changes in release ?.? (????-??-??) KEYCTL_*, KVM_*, LOOP_*, NDA_*, RTC_*, TCA_*, STATX_*, and *_MAGIC constants. * Updated lists of ioctl commands from Linux 5.8. + * Added --pidns-translation opition for PID namespace translation. * Bug fixes * Added statx syscall to %fstat trace class. diff --git a/defs.h b/defs.h index f7ac54f3..692fa0d3 100644 --- a/defs.h +++ b/defs.h @@ -280,6 +280,13 @@ struct tcb { struct timespec etime; /* Syscall entry time (CLOCK_MONOTONIC) */ struct timespec delay_expiration_time; /* When does the delay end */ + /* + * The ID of the PID namespace of this process + * (inode number of /proc//ns/pid) + * (0: not initialized) + */ + unsigned int pid_ns; + struct mmap_cache_t *mmap_cache; /* @@ -413,7 +420,11 @@ extern const struct xlat whence_codes[]; # define RVAL_HEX 001 /* hex format */ # define RVAL_OCTAL 002 /* octal format */ # define RVAL_FD 010 /* file descriptor */ -# define RVAL_MASK 013 /* mask for these values */ +# define RVAL_TID 011 /* task ID */ +# define RVAL_SID 012 /* session ID */ +# define RVAL_TGID 013 /* thread group ID */ +# define RVAL_PGID 014 /* process group ID */ +# define RVAL_MASK 017 /* mask for these values */ # define RVAL_STR 020 /* Print `auxstr' field after return val */ # define RVAL_NONE 040 /* Print nothing */ @@ -428,6 +439,16 @@ extern const struct xlat whence_codes[]; # define indirect_ipccall(tcp) (tcp_sysent(tcp)->sys_flags & TRACE_INDIRECT_SUBCALL) +enum pid_type { + PT_TID, + PT_TGID, + PT_PGID, + PT_SID, + + PT_COUNT, + PT_NONE = -1 +}; + enum sock_proto { SOCK_PROTO_UNKNOWN, SOCK_PROTO_UNIX, @@ -469,6 +490,7 @@ extern int Tflag_scale; extern int Tflag_width; extern bool iflag; extern bool count_wallclock; +extern unsigned int pidns_translation; /* are we filtering traces based on paths? */ extern struct path_set { const char **paths_selected; @@ -983,6 +1005,27 @@ print_local_array_ex(struct tcb *tcp, extern kernel_ulong_t * fetch_indirect_syscall_args(struct tcb *, kernel_ulong_t addr, unsigned int n_args); +extern void pidns_init(void); + +/** + * Returns the pid of the tracee as present in /proc (can be different from + * tcp->pid if /proc and the tracee process are in different PID namespaces). + */ +extern int get_proc_pid(struct tcb *); + +/** + * Translates a pid from tracee's namespace to our namepace. + * + * @param tcp The tcb of the tracee + * (NULL: from_id is in strace's namespace. Useful for + * getting the proc PID of from_id) + * @param from_id The id to be translated + * @param type The PID type of from_id + * @param proc_pid_ptr If not NULL, writes the proc PID to this location + */ +extern int translate_pid(struct tcb *, int dest_id, enum pid_type type, + int *proc_pid_ptr); + extern void dumpiov_in_msghdr(struct tcb *, kernel_ulong_t addr, kernel_ulong_t data_size); @@ -1058,6 +1101,14 @@ printfd(struct tcb *tcp, int fd) * of the tracee the descriptor tcp). This is a stub. */ extern void printfd_pid_tracee_ns(struct tcb *tcp, pid_t pid, int fd); + +extern void printpid(struct tcb *, int pid, enum pid_type type); + +/** + * Prints pid as a TGID if positive, and PGID if negative + * (like the first argument of kill). + */ +extern void printpid_tgid_pgid(struct tcb *, int pid); extern void print_sockaddr(struct tcb *, const void *sa, int len); extern bool print_inet_addr(int af, const void *addr, unsigned int len, const char *var_name); diff --git a/largefile_wrappers.h b/largefile_wrappers.h index 116e7048..9d8f5c92 100644 --- a/largefile_wrappers.h +++ b/largefile_wrappers.h @@ -29,6 +29,7 @@ # else # define fcntl_fd fcntl # endif +# define fstat_fd fstat64 # define strace_stat_t struct stat64 # define stat_file stat64 # define struct_dirent struct dirent64 @@ -39,6 +40,7 @@ # define open_file open # define fopen_stream fopen # define fcntl_fd fcntl +# define fstat_fd fstat # define strace_stat_t struct stat # define stat_file stat # define struct_dirent struct dirent diff --git a/pidns.c b/pidns.c new file mode 100644 index 00000000..6a99fbb4 --- /dev/null +++ b/pidns.c @@ -0,0 +1,613 @@ +/* + * Copyright (c) 2020 ?kos Uzonyi + * All rights reserved. + * + * SPDX-License-Identifier: LGPL-2.1-or-later + */ + +#include "defs.h" + + +#include +#include +#include +#include +#include + +#include + +#include +#include +#include +#include + +#include "largefile_wrappers.h" +#include "trie.h" +#include "nsfs.h" +#include "xmalloc.h" +#include "xstring.h" + +/** + * Key: PID NS ID + * Value: a btree: + * Key: a process PID in NS + * Value: the process's PID as present in /proc + */ +static struct trie *ns_pid_to_proc_pid[PT_COUNT]; + +/** + * Key: Proc PID + * Value: stuct proc_data + */ +static struct trie *proc_data_cache; + +static bool ns_get_parent_enotty = false; + +static const char tid_str[] = "NSpid:\t"; +static const char tgid_str[] = "NStgid:\t"; +static const char pgid_str[] = "NSpgid:\t"; +static const char sid_str[] = "NSsid:\t"; + +static const struct { + const char *str; + size_t size; +} id_strs[PT_COUNT] = { + [PT_TID] = { tid_str, sizeof(tid_str) - 1 }, + [PT_TGID] = { tgid_str, sizeof(tgid_str) - 1 }, + [PT_PGID] = { pgid_str, sizeof(pgid_str) - 1 }, + [PT_SID] = { sid_str, sizeof(sid_str) - 1 }, +}; + + +/** + * Limit on PID NS hierarchy depth, imposed since Linux 3.7. NS traversal + * is not possible before Linux 4.9, so we consider this limit pretty universal. + */ +#define MAX_NS_DEPTH 32 + +static const size_t ns_id_size = sizeof(unsigned int); +static const uint8_t ptr_sz_lg = (sizeof(void *) == 8 ? 6 : 5); + +static int pid_max; +static uint8_t pid_max_size, pid_max_size_lg; + +struct proc_data { + int proc_pid; + int ns_count; + unsigned int ns_hierarchy[MAX_NS_DEPTH]; + int id_count[PT_COUNT]; + int id_hierarchy[PT_COUNT][MAX_NS_DEPTH]; +}; + +/** + * Helper function for creating a trie. + * + * For node_key_bits and data_block_key_bits 4 is used (so trie height is 32 / 4 + * = 8, and node sizes are 8 byte * 2^4 = 128 bytes), which seems to be a good + * tradeoff between between memory usage and lookup time. It should not be too + * large, since there can be large holes between PIDs, and it would be just a + * waste of memory having large nodes with lot of NULL pointers in them. + */ +static struct trie * +create_trie_4(uint8_t key_size, uint8_t item_size_lg, uint64_t empty_value) +{ + struct trie *t = trie_create(key_size, item_size_lg, 4, 4, empty_value); + if (!t) + error_msg_and_die("creating trie failed"); + + return t; +} + +void +pidns_init(void) +{ + if (proc_data_cache) + return; + + pid_max = INT_MAX; + if (read_int_from_file("/proc/sys/kernel/pid_max", &pid_max) < 0) + debug_func_perror_msg("reading /proc/sys/kernel/pid_max"); + pid_max_size = ilog2_32(pid_max - 1) + 1; + pid_max_size_lg = ilog2_32(pid_max_size - 1) + 1; + + for (int i = 0; i < PT_COUNT; i++) + ns_pid_to_proc_pid[i] = create_trie_4(ns_id_size, ptr_sz_lg, 0); + + proc_data_cache = create_trie_4(pid_max_size, ptr_sz_lg, 0); +} + +static void +put_proc_pid(unsigned int ns, int ns_pid, enum pid_type type, int proc_pid) +{ + struct trie *b = (struct trie *) (uintptr_t) trie_get(ns_pid_to_proc_pid[type], ns); + if (!b) { + b = create_trie_4(pid_max_size, pid_max_size_lg, 0); + trie_set(ns_pid_to_proc_pid[type], ns, (uint64_t) (uintptr_t) b); + } + trie_set(b, ns_pid, proc_pid); +} + +static int +get_cached_proc_pid(unsigned int ns, int ns_pid, enum pid_type type) +{ + struct trie *b = (struct trie *) (uintptr_t) + trie_get(ns_pid_to_proc_pid[type], ns); + if (!b) + return 0; + + return trie_get(b, ns_pid); +} + +/** + * Helper function, converts pid to string, or to "self" for pid == 0. + * Uses static buffer for operation. + */ +static const char * +pid_to_str(pid_t pid) +{ + if (!pid) + return "self"; + + static char buf[sizeof("-2147483648")]; + xsprintf(buf, "%d", pid); + return buf; +} + +/** + * Returns a list of PID NS IDs for the specified PID. + * + * @param proc_pid PID (as present in /proc) to get information for. + * @param ns_buf Pointer to buffer that is able to contain at least + * ns_buf_size items. + * @return Amount of NS in list. 0 indicates error. + */ +static size_t +get_ns_hierarchy(int proc_pid, unsigned int *ns_buf, size_t ns_buf_size) +{ + char path[PATH_MAX + 1]; + xsprintf(path, "/proc/%s/ns/pid", pid_to_str(proc_pid)); + + int fd = open_file(path, O_RDONLY); + if (fd < 0) + return 0; + + size_t n = 0; + while (n < ns_buf_size) { + strace_stat_t st; + if (fstat_fd(fd, &st)) + break; + + ns_buf[n++] = st.st_ino; + if (n >= ns_buf_size) + break; + + if (ns_get_parent_enotty) + break; + + int parent_fd = ioctl(fd, NS_GET_PARENT); + if (parent_fd < 0) { + switch (errno) { + case EPERM: + break; + + case ENOTTY: + ns_get_parent_enotty = true; + error_msg("NS_* ioctl commands are not " + "supported by the kernel"); + break; + + default: + perror_func_msg("ioctl(NS_GET_PARENT)"); + break; + } + + break; + } + + close(fd); + fd = parent_fd; + } + + close(fd); + + return n; +} + +/** + * Get list of IDs present in NS* proc status record. IDs are placed as they are + * stored in /proc (from top to bottom of NS hierarchy). + * + * @param proc_pid PID (as present in /proc) to get information for. + * @param id_buf Pointer to buffer that is able to contain at least + * MAX_NS_DEPTH items. Can be NULL. + * @param type Type of ID requested. + * @return Number of items stored in id_list. 0 indicates error. + */ +static size_t +get_id_list(int proc_pid, int *id_buf, enum pid_type type) +{ + const char *ns_str = id_strs[type].str; + size_t ns_str_size = id_strs[type].size; + + size_t n = 0; + + char status_path[PATH_MAX + 1]; + xsprintf(status_path, "/proc/%s/status", pid_to_str(proc_pid)); + FILE *f = fopen_stream(status_path, "r"); + if (!f) + return 0; + + char *line = NULL; + size_t linesize = 0; + char *p = NULL; + + while (getline(&line, &linesize, f) > 0) { + if (strncmp(line, ns_str, ns_str_size) == 0) { + p = line + ns_str_size; + break; + } + } + + while (p) { + errno = 0; + long id = strtol(p, NULL, 10); + + if (errno || (id < 1) || (id > INT_MAX)) { + perror_func_msg("converting pid to int"); + break; + } + + if (id_buf) + id_buf[n] = (int) id; + + n++; + strsep(&p, "\t"); + } + + free(line); + fclose(f); + + return n; +} + +/** + * Returns whether the /proc filesystem's PID namespace is same as strace's. + */ +static bool +is_proc_ours(void) +{ + static int cached_val = -1; + + if (cached_val < 0) + cached_val = get_id_list(0, NULL, PT_TID) == 1; + + return cached_val; +} + +/** + * Returns the PID namespace of the tracee + */ +static unsigned int +get_ns(struct tcb *tcp) +{ + if (!tcp->pid_ns) { + int proc_pid = 0; + translate_pid(NULL, tcp->pid, PT_TID, &proc_pid); + + if (proc_pid) + get_ns_hierarchy(proc_pid, &tcp->pid_ns, 1); + } + + return tcp->pid_ns; +} + +/** + * Returns the PID namespace of strace + */ +static unsigned int +get_our_ns(void) +{ + static unsigned int our_ns = 0; + static bool our_ns_initialised = false; + + if (!our_ns_initialised) { + get_ns_hierarchy(0, &our_ns, 1); + our_ns_initialised = true; + } + + return our_ns; +} + +/** + * Returns the cached proc_data struct associated with proc_pid. + * If none found, allocates a new proc_data. + */ +static struct proc_data * +get_or_create_proc_data(int proc_pid) +{ + struct proc_data *pd = (struct proc_data *) (uintptr_t) + trie_get(proc_data_cache, proc_pid); + + if (!pd) { + pd = calloc(1, sizeof(*pd)); + if (!pd) + return NULL; + + pd->proc_pid = proc_pid; + trie_set(proc_data_cache, proc_pid, (uint64_t) (uintptr_t) pd); + } + + return pd; +} + +/** + * Updates the proc_data from /proc + * If the process does not exists, returns false, and frees the proc_data + */ +static bool +update_proc_data(struct proc_data *pd, enum pid_type type) +{ + pd->ns_count = get_ns_hierarchy(pd->proc_pid, + pd->ns_hierarchy, MAX_NS_DEPTH); + if (!pd->ns_count) + goto fail; + + pd->id_count[type] = get_id_list(pd->proc_pid, + pd->id_hierarchy[type], type); + if (!pd->id_count[type]) + goto fail; + + return true; + +fail: + trie_set(proc_data_cache, pd->proc_pid, (uint64_t) (uintptr_t) NULL); + free(pd); + return false; +} + +/** + * Paramters for id translation + */ +struct translate_id_params { + /* The result (output) */ + int result_id; + /* The proc data of the process (output) */ + struct proc_data *pd; + + /* The namespace to be translated from */ + unsigned int from_ns; + /* The id to be translated */ + int from_id; + /* The type of the id */ + enum pid_type type; +}; + +/** + * Translates an id to our namespace, given the proc_pid of the process, + * by reading files in /proc. + * + * @param tip The parameters + * @param proc_pid The proc pid of the process. + * If 0, use the cached values in tip->pd. + */ +static void +translate_id_proc_pid(struct translate_id_params *tip, int proc_pid) +{ + struct proc_data *pd = proc_pid ? + get_or_create_proc_data(proc_pid) : + tip->pd; + + tip->result_id = 0; + tip->pd = NULL; + + if (!pd) + return; + + if (proc_pid && !update_proc_data(pd, tip->type)) + return; + + if (!pd->ns_count || (pd->id_count[tip->type] < pd->ns_count)) + return; + + int our_ns_id_idx = pd->id_count[tip->type] - pd->ns_count; + + for (int i = 0; i < pd->ns_count; i++) { + if (pd->ns_hierarchy[i] != tip->from_ns) + continue; + + int id_idx = pd->id_count[tip->type] - i - 1; + if (pd->id_hierarchy[tip->type][id_idx] != tip->from_id) + return; + + tip->result_id = pd->id_hierarchy[tip->type][our_ns_id_idx]; + tip->pd = pd; + return; + } +} + +/** + * Translates an id to our namespace, by reading all proc entries in dir. + * + * @param tip The parameters + * @param path The path of the dir to be read. + * @param read_task_dir Whether recurse to "task" subdirectory. + */ +static void +translate_id_dir(struct translate_id_params *tip, const char *path, + bool read_task_dir) +{ + DIR *dir = opendir(path); + if (!dir) { + debug_func_perror_msg("opening dir: %s", path); + return; + } + + while (!tip->result_id) { + errno = 0; + struct_dirent *entry = read_dir(dir); + if (!entry) { + if (errno) + perror_func_msg("readdir"); + + break; + } + + if (entry->d_type != DT_DIR) + continue; + + errno = 0; + long proc_pid = strtol(entry->d_name, NULL, 10); + if (errno) + continue; + if ((proc_pid < 1) || (proc_pid > INT_MAX)) + continue; + + if (read_task_dir) { + char task_dir_path[PATH_MAX + 1]; + xsprintf(task_dir_path, "/proc/%ld/task", proc_pid); + translate_id_dir(tip, task_dir_path, false); + } + + if (tip->result_id) + break; + + translate_id_proc_pid(tip, proc_pid); + } + + closedir(dir); +} + +/** + * Iterator function of the proc_data_cache for id translation. + * If the cache contains the id we are looking for, reads the corresponding + * directory in /proc, and if cache is valid, saves the result. + */ +static void +proc_data_cache_iterator_fn(void* fn_data, uint64_t key, uint64_t val) +{ + struct translate_id_params *tip = (struct translate_id_params *)fn_data; + struct proc_data *pd = (struct proc_data *) (uintptr_t) val; + + if (!pd) + return; + + /* Result already found in an earlier iteration */ + if (tip->result_id) + return; + + /* Translate from cache */ + tip->pd = pd; + translate_id_proc_pid(tip, 0); + if (!tip->result_id) + return; + + /* Now translate from actual data in /proc, to check cache validity */ + translate_id_proc_pid(tip, pd->proc_pid); +} + +int +translate_pid(struct tcb *tcp, int from_id, enum pid_type type, + int *proc_pid_ptr) +{ + if ((from_id <= 0) || (type < 0) || (type >= PT_COUNT)) + return 0; + + const unsigned int our_ns = get_our_ns(); + if (!our_ns) + return 0; + + struct translate_id_params tip = { + .result_id = 0, + .pd = NULL, + .from_ns = tcp ? get_ns(tcp) : our_ns, + .from_id = from_id, + .type = type, + }; + + if (!tip.from_ns) + return 0; + + /* If translation is trivial */ + if (tip.from_ns == our_ns && (is_proc_ours() || !proc_pid_ptr)) { + if (proc_pid_ptr) + *proc_pid_ptr = from_id; + + tip.result_id = tip.from_id; + goto exit; + } + + if (ns_get_parent_enotty) + return 0; + + /* Look for a cached proc_pid for this (from_ns, from_id) pair */ + int cached_proc_pid = get_cached_proc_pid(tip.from_ns, tip.from_id, + tip.type); + if (cached_proc_pid) { + translate_id_proc_pid(&tip, cached_proc_pid); + if (tip.result_id) + goto exit; + } + + /* Iterate through the cache, find potential proc_data */ + trie_iterate_keys(proc_data_cache, 0, pid_max, + proc_data_cache_iterator_fn, &tip); + /* (proc_data_cache_iterator_fn takes care about updating proc_data) */ + if (tip.result_id) + goto exit; + + /* No cache helped, read all entries in /proc */ + translate_id_dir(&tip, "/proc", true); + +exit: + if (tip.pd) { + if (tip.pd->proc_pid) + put_proc_pid(tip.from_ns, tip.from_id, tip.type, + tip.pd->proc_pid); + + if (proc_pid_ptr) + *proc_pid_ptr = tip.pd->proc_pid; + } + + return tip.result_id; +} + +int +get_proc_pid(struct tcb *tcp) +{ + int ret = 0; + + if (is_proc_ours()) + ret = tcp->pid; + else + translate_pid(NULL, tcp->pid, PT_TID, &ret); + + return ret; +} + +static void +printpid_translation(struct tcb *tcp, int pid, enum pid_type type) +{ + if (!pidns_translation) + return; + + int strace_pid = translate_pid(tcp, pid, type, NULL); + if (strace_pid && strace_pid != pid) + tprintf_comment("%d in strace's PID NS", strace_pid); +} + +void +printpid(struct tcb *tcp, int pid, enum pid_type type) +{ + tprintf("%d", pid); + printpid_translation(tcp, pid, type); +} + +void +printpid_tgid_pgid(struct tcb *tcp, int pid) +{ + tprintf("%d", pid); + if (pid > 0) + printpid_translation(tcp, pid, PT_TGID); + else if (pid < -1) + printpid_translation(tcp, -pid, PT_PGID); +} diff --git a/strace.1.in b/strace.1.in index 3b21caec..adca194c 100644 --- a/strace.1.in +++ b/strace.1.in @@ -1075,6 +1075,10 @@ Print all available information associated with file descritors: protocol-specific information associated with socket file descriptors, block/character device number associated with device file descriptors, and PIDs asociated with pidfd file descriptors. +.TP +.B \-\-pidns\-translation +If strace and tracee are in different PID namespaces, print PIDs in +strace's namespace also. .SS Statistics .TP 12 .B \-c diff --git a/strace.c b/strace.c index 4c96a98b..249533ea 100644 --- a/strace.c +++ b/strace.c @@ -133,6 +133,8 @@ static unsigned int daemonized_tracer; static int post_attach_sigstop = TCB_IGNORE_ONE_SIGSTOP; #define use_seize (post_attach_sigstop == 0) +unsigned int pidns_translation; + static bool detach_on_execve; static int exit_code; @@ -1998,6 +2000,8 @@ init(int argc, char *argv[]) os_release = get_os_release(); + pidns_init(); + shared_log = stderr; set_sortby(DEFAULT_SORTBY); set_personality(DEFAULT_PERSONALITY); @@ -2022,6 +2026,7 @@ init(int argc, char *argv[]) GETOPT_FOLLOWFORKS, GETOPT_OUTPUT_SEPARATELY, GETOPT_TS, + GETOPT_PIDNS_TRANSLATION, GETOPT_QUAL_TRACE, GETOPT_QUAL_ABBREV, @@ -2072,6 +2077,7 @@ init(int argc, char *argv[]) { "summary-wall-clock", no_argument, 0, 'w' }, { "strings-in-hex", optional_argument, 0, GETOPT_HEX_STR }, { "const-print-style", required_argument, 0, 'X' }, + { "pidns-translation", no_argument , 0, GETOPT_PIDNS_TRANSLATION }, { "successful-only", no_argument, 0, 'z' }, { "failed-only", no_argument, 0, 'Z' }, { "failing-only", no_argument, 0, 'Z' }, @@ -2285,6 +2291,9 @@ init(int argc, char *argv[]) case 'y': yflag_short++; break; + case GETOPT_PIDNS_TRANSLATION: + pidns_translation++; + break; case 'z': clear_number_set_array(status_set, 1); add_number_to_set(STATUS_SUCCESSFUL, status_set); diff --git a/syscall.c b/syscall.c index bcc87025..0f4bab6d 100644 --- a/syscall.c +++ b/syscall.c @@ -937,6 +937,21 @@ syscall_exiting_trace(struct tcb *tcp, struct timespec *ts, int res) tprintf("= %" PRI_kld, tcp->u_rval); } break; + case RVAL_TID: + case RVAL_SID: + case RVAL_TGID: + case RVAL_PGID: { + #define _(_t) [RVAL_##_t - RVAL_TID] = PT_##_t + static const enum pid_type types[] = { + _(TID), _(SID), _(TGID), _(PGID), + }; + #undef _ + + tprints("= "); + printpid(tcp, tcp->u_rval, + types[(sys_res & RVAL_MASK) - RVAL_TID]); + break; + } default: error_msg("invalid rval format"); break; diff --git a/trie.c b/trie.c new file mode 100644 index 00000000..76cecc25 --- /dev/null +++ b/trie.c @@ -0,0 +1,250 @@ +/* + * Simple trie implementation for key-value mapping storage + * + * Copyright (c) 2020 ?kos Uzonyi + * All rights reserved. + * + * SPDX-License-Identifier: LGPL-2.1-or-later + */ + +#include "defs.h" + +#include +#include +#include +#include + +#include "trie.h" + +static const uint8_t ptr_sz_lg = (sizeof(uint64_t *) == 8 ? 6 : 5); + +/** + * Returns lg2 of node size for the specific level of the trie. If max_depth + * provided is less than zero, it is calculated via trie_get_depth call. + */ +static uint8_t +trie_get_node_size(struct trie *t, uint8_t depth) +{ + /* Last level contains data and we allow it having a different size */ + if (depth == t->max_depth) + return t->data_block_key_bits + t->item_size_lg; + /* Last level of the tree can be smaller */ + if (depth == t->max_depth - 1) + return (t->key_size - t->data_block_key_bits - 1) % + t->node_key_bits + 1 + ptr_sz_lg; + + return t->node_key_bits + ptr_sz_lg; +} + +/** + * Provides starting offset of bits in key corresponding to the node index + * at the specific level. + */ +static uint8_t +trie_get_node_bit_offs(struct trie *t, uint8_t depth) +{ + uint8_t offs; + + if (depth == t->max_depth) + return 0; + + offs = t->data_block_key_bits; + + if (depth == t->max_depth - 1) + return offs; + + /* data_block_size + remainder */ + offs += trie_get_node_size(t, t->max_depth - 1) - ptr_sz_lg; + offs += (t->max_depth - depth - 2) * t->node_key_bits; + + return offs; +} + +struct trie * +trie_create(uint8_t key_size, uint8_t item_size_lg, uint8_t node_key_bits, + uint8_t data_block_key_bits, uint64_t empty_value) +{ + if (item_size_lg > 6) + return NULL; + if (key_size > 64) + return NULL; + if (node_key_bits < 1) + return NULL; + if (data_block_key_bits < 1 || data_block_key_bits > key_size) + return NULL; + + struct trie *t = malloc(sizeof(*t)); + if (!t) + return NULL; + + t->empty_value = empty_value; + t->data = NULL; + t->item_size_lg = item_size_lg; + t->node_key_bits = node_key_bits; + t->data_block_key_bits = data_block_key_bits; + t->key_size = key_size; + t->max_depth = (key_size - data_block_key_bits + node_key_bits - 1) + / t->node_key_bits; + + return t; +} + +static uint64_t * +trie_get_node(struct trie *t, uint64_t key, bool auto_create) +{ + void **cur_node = &(t->data); + + if (t->key_size < 64 && key > (uint64_t) 1 << t->key_size) + return NULL; + + for (uint8_t cur_depth = 0; cur_depth <= t->max_depth; cur_depth++) { + uint8_t offs = trie_get_node_bit_offs(t, cur_depth); + uint8_t sz = trie_get_node_size(t, cur_depth); + + if (!*cur_node) { + if (!auto_create) + return NULL; + + *cur_node = xcalloc(1 << sz, 1); + } + + if (cur_depth >= t->max_depth) + break; + + size_t pos = (key >> offs) & ((1 << (sz - ptr_sz_lg)) - 1); + cur_node = (((void **) (*cur_node)) + pos); + } + + return (uint64_t *) (*cur_node); +} + +static void +trie_data_block_calc_pos(struct trie *t, uint64_t key, + uint64_t *pos, uint64_t *mask, uint64_t *offs) +{ + uint64_t key_mask; + + key_mask = (1 << t->data_block_key_bits) - 1; + *pos = (key & key_mask) >> (6 - t->item_size_lg); + + key_mask = (1 << (6 - t->item_size_lg)) - 1; + *offs = (key & key_mask) * (1 << t->item_size_lg); + + *mask = (((uint64_t) 1 << (1 << t->item_size_lg)) - 1) << *offs; +} + +bool +trie_set(struct trie *t, uint64_t key, uint64_t val) +{ + uint64_t *data = trie_get_node(t, key, true); + if (!data) + return false; + + uint64_t pos, mask, offs; + trie_data_block_calc_pos(t, key, &pos, &mask, &offs); + + data[pos] &= ~mask; + data[pos] |= (val << offs) & mask; + + return true; +} + +static uint64_t +trie_data_block_get(struct trie *t, uint64_t *data, uint64_t key) +{ + if (!data) + return t->empty_value; + + uint64_t pos, mask, offs; + trie_data_block_calc_pos(t, key, &pos, &mask, &offs); + + return (data[pos] & mask) >> offs; +} + +uint64_t +trie_get(struct trie *b, uint64_t key) +{ + return trie_data_block_get(b, trie_get_node(b, key, false), key); +} + +static uint64_t +trie_iterate_keys_node(struct trie *t, + trie_iterate_fn fn, void *fn_data, + void *node, uint64_t start, uint64_t end, + uint8_t depth) +{ + if (start > end || !node) + return 0; + + if (depth == t->max_depth) { + for (uint64_t i = start; i <= end; i++) + fn(fn_data, i, trie_data_block_get(t, + (uint64_t *) node, i)); + + return end - start + 1; //TODO: overflow + } + + uint8_t parent_node_bit_off = depth == 0 ? + t->key_size : + trie_get_node_bit_offs(t, depth - 1); + + uint64_t first_key_in_node = start & + (uint64_t) -1 << parent_node_bit_off; + + uint8_t node_bit_off = trie_get_node_bit_offs(t, depth); + uint8_t node_key_bits = parent_node_bit_off - node_bit_off; + uint64_t mask = ((uint64_t) 1 << (node_key_bits)) - 1; + uint64_t start_index = (start >> node_bit_off) & mask; + uint64_t end_index = (end >> node_bit_off) & mask; + uint64_t child_key_count = (uint64_t) 1 << node_bit_off; + + uint64_t count = 0; + + for (uint64_t i = start_index; i <= end_index; i++) { + uint64_t child_start = first_key_in_node + i * child_key_count; + uint64_t child_end = first_key_in_node + + (i + 1) * child_key_count - 1; + + if (child_start < start) + child_start = start; + if (child_end > end) + child_end = end; + + count += trie_iterate_keys_node(t, fn, fn_data, + ((void **) node)[i], child_start, child_end, + depth + 1); + } + + return count; +} + +uint64_t trie_iterate_keys(struct trie *t, uint64_t start, uint64_t end, + trie_iterate_fn fn, void *fn_data) +{ + return trie_iterate_keys_node(t, fn, fn_data, t->data, + start, end, 0); +} + +static void +trie_free_node(struct trie *t, void *node, uint8_t depth) +{ + if (!node) + return; + + if (depth >= t->max_depth) + goto free_node; + + size_t sz = 1 << (trie_get_node_size(t, depth) - ptr_sz_lg); + for (size_t i = 0; i < sz; i++) + trie_free_node(t, ((void **) node)[i], depth + 1); + +free_node: + free(node); +} + +void +trie_free(struct trie *t) +{ + trie_free_node(t, t->data, 0); + free(t); +} diff --git a/trie.h b/trie.h new file mode 100644 index 00000000..f7058c7e --- /dev/null +++ b/trie.h @@ -0,0 +1,89 @@ +/* + * Simple trie interface + * + * Copyright (c) 2020 ?kos Uzonyi + * All rights reserved. + * + * SPDX-License-Identifier: LGPL-2.1-or-later + */ + +#ifndef STRACE_TRIE_H +#define STRACE_TRIE_H + +/** + * Trie control structure. + * Trie implemented here has the following properties: + * * It allows storing values of the same size, the size can vary from 1 bit to + * 64 bit values (only power of 2 sizes are allowed). + * * The key can be up to 64 bits in size. + * * It has separate configuration for node size and data block size. + * + * How bits of key are used for different node levels: + * + * highest bits lowest bits + * | node_key_bits | node_key_bits | ... | | data_block_key_bits | + * \_________________________________________________________________________/ + * key_size + * + * So, the remainder is used on the lowest non-data node level. + * + * As of now, it doesn't implement any mechanisms for resizing/changing key + * size. De-fragmentation is also unsupported currently. + */ +struct trie { + /** Return value of trie_get if key is not found */ + uint64_t empty_value; + + /** Pointer to root node */ + void *data; + + /** Key size in bits (0..64). */ + uint8_t key_size; + + /** + * Size of the stored values in log2 bits (0..6). + * (6: 64 bit values, 5: 32 bit values, ...) + */ + uint8_t item_size_lg; + + /** + * Number of bits in key that makes a symbol for a node. + * (equals to log2 of the child count of the node) + */ + uint8_t node_key_bits; + + /** + * Number of bits in key that make a symbol for the data block (leaf). + * (equals to log2 of the value count stored in a data block) + */ + uint8_t data_block_key_bits; + + /** The depth of the data block. Caluclated from the values above */ + uint8_t max_depth; +}; + +struct trie* trie_create(uint8_t key_size, uint8_t item_size_lg, + uint8_t node_key_bits, uint8_t data_block_key_bits, + uint64_t empty_value); + +bool trie_set(struct trie *t, uint64_t key, uint64_t val); +uint64_t trie_get(struct trie *t, uint64_t key); + +typedef void (*trie_iterate_fn)(void *data, uint64_t key, uint64_t val); + +/** + * Calls trie_iterate_fn for each key-value pair where + * key is inside the [start, end] interval (inclusive). + * + * @param t The trie. + * @param start The start of the key interval (inclusive). + * @param end The end of the key interval (inclusive). + * @param fn The function to be called. + * @param fn_data The value to be passed to fn. + */ +uint64_t trie_iterate_keys(struct trie *t, uint64_t start, uint64_t end, + trie_iterate_fn fn, void *fn_data); + +void trie_free(struct trie *t); + +#endif /* !STRACE_TRIE_H */ -- 2.27.0 From ldv at altlinux.org Fri Aug 7 18:23:18 2020 From: ldv at altlinux.org (Dmitry V. Levin) Date: Fri, 7 Aug 2020 21:23:18 +0300 Subject: [PATCH v6 1/5] PID namespace translation support In-Reply-To: <20200806190211.118721-2-uzonyi.akos@gmail.com> References: <20200806190211.118721-1-uzonyi.akos@gmail.com> <20200806190211.118721-2-uzonyi.akos@gmail.com> Message-ID: <20200807182318.GA5985@altlinux.org> On Thu, Aug 06, 2020 at 09:02:07PM +0200, ?kos Uzonyi wrote: [...] > diff --git a/NEWS b/NEWS > index b83f9e80..9086fde9 100644 > --- a/NEWS > +++ b/NEWS > @@ -14,6 +14,7 @@ Noteworthy changes in release ?.? (????-??-??) > KEYCTL_*, KVM_*, LOOP_*, NDA_*, RTC_*, TCA_*, STATX_*, and *_MAGIC > constants. > * Updated lists of ioctl commands from Linux 5.8. > + * Added --pidns-translation opition for PID namespace translation. Typo? > @@ -983,6 +1005,27 @@ print_local_array_ex(struct tcb *tcp, > extern kernel_ulong_t * > fetch_indirect_syscall_args(struct tcb *, kernel_ulong_t addr, unsigned int n_args); > > +extern void pidns_init(void); > + > +/** > + * Returns the pid of the tracee as present in /proc (can be different from > + * tcp->pid if /proc and the tracee process are in different PID namespaces). > + */ > +extern int get_proc_pid(struct tcb *); I'm still puzzled what /proc are you talking about, the tracer's /proc or the tracee's /proc. > @@ -1058,6 +1101,14 @@ printfd(struct tcb *tcp, int fd) > * of the tracee the descriptor tcp). This is a stub. > */ > extern void printfd_pid_tracee_ns(struct tcb *tcp, pid_t pid, int fd); > + > +extern void printpid(struct tcb *, int pid, enum pid_type type); Although this might look obvious, I suggest adding a short comment for printpid, too, to make it clear that printpid prints the pid given in the tracee's pid namespace. > +/** > + * Key: Proc PID > + * Value: stuct proc_data Typo? > +/** > + * Helper function for creating a trie. > + * > + * For node_key_bits and data_block_key_bits 4 is used (so trie height is 32 / 4 > + * = 8, and node sizes are 8 byte * 2^4 = 128 bytes), which seems to be a good > + * tradeoff between between memory usage and lookup time. It should not be too Typo? > + * large, since there can be large holes between PIDs, and it would be just a > + * waste of memory having large nodes with lot of NULL pointers in them. > + */ > +static struct trie * > +create_trie_4(uint8_t key_size, uint8_t item_size_lg, uint64_t empty_value) > +{ > + struct trie *t = trie_create(key_size, item_size_lg, 4, 4, empty_value); > + if (!t) > + error_msg_and_die("creating trie failed"); > + > + return t; > +} I believe empty_value is always 0, so why bother with the argument? > + while (p) { > + errno = 0; > + long id = strtol(p, NULL, 10); > + > + if (errno || (id < 1) || (id > INT_MAX)) { I don't think these extra brackets increase readability. > + perror_func_msg("converting pid to int"); > + break; > + } I suggest also printing the value of p in this unlikely case. > +/** > + * Returns whether the /proc filesystem's PID namespace is same as strace's. Grammar: is the same. > diff --git a/strace.1.in b/strace.1.in > index 3b21caec..adca194c 100644 > --- a/strace.1.in > +++ b/strace.1.in > @@ -1075,6 +1075,10 @@ Print all available information associated with file descritors: > protocol-specific information associated with socket file descriptors, > block/character device number associated with device file descriptors, > and PIDs asociated with pidfd file descriptors. > +.TP > +.B \-\-pidns\-translation > +If strace and tracee are in different PID namespaces, print PIDs in > +strace's namespace also. Changing "print PIDs in strace's namespace also" to either "print PIDs also in strace's namespace" or "print PIDs in strace's namespace, too" would likely result to a more grammatically correct sentence. > diff --git a/trie.c b/trie.c > new file mode 100644 > index 00000000..76cecc25 > --- /dev/null > +++ b/trie.c > @@ -0,0 +1,250 @@ > +/* > + * Simple trie implementation for key-value mapping storage > + * > + * Copyright (c) 2020 ?kos Uzonyi > + * All rights reserved. > + * > + * SPDX-License-Identifier: LGPL-2.1-or-later > + */ > + > +#include "defs.h" > + > +#include Does this code use assert? > +#include > +#include > +#include > + > +#include "trie.h" > + > +static const uint8_t ptr_sz_lg = (sizeof(uint64_t *) == 8 ? 6 : 5); Hmm, pidns.c uses a slightly different (although essentially the same) definition of ptr_sz_lg. > + > +/** > + * Returns lg2 of node size for the specific level of the trie. If max_depth > + * provided is less than zero, it is calculated via trie_get_depth call. > + */ > +static uint8_t > +trie_get_node_size(struct trie *t, uint8_t depth) What do you mean by "If max_depth provided"? > +struct trie * > +trie_create(uint8_t key_size, uint8_t item_size_lg, uint8_t node_key_bits, > + uint8_t data_block_key_bits, uint64_t empty_value) > +{ > + if (item_size_lg > 6) > + return NULL; > + if (key_size > 64) > + return NULL; > + if (node_key_bits < 1) > + return NULL; > + if (data_block_key_bits < 1 || data_block_key_bits > key_size) > + return NULL; Should there be a check that node_key_bits isn't too big, for consistency? > +static uint64_t > +trie_iterate_keys_node(struct trie *t, > + trie_iterate_fn fn, void *fn_data, > + void *node, uint64_t start, uint64_t end, > + uint8_t depth) > +{ > + if (start > end || !node) > + return 0; > + > + if (depth == t->max_depth) { > + for (uint64_t i = start; i <= end; i++) > + fn(fn_data, i, trie_data_block_get(t, > + (uint64_t *) node, i)); > + > + return end - start + 1; //TODO: overflow Overflow? > + /** > + * Number of bits in key that makes a symbol for a node. > + * (equals to log2 of the child count of the node) > + */ > + uint8_t node_key_bits; > + > + /** > + * Number of bits in key that make a symbol for the data block (leaf). Typo? > + * (equals to log2 of the value count stored in a data block) > + */ > + uint8_t data_block_key_bits; > + > + /** The depth of the data block. Caluclated from the values above */ Typo? -- ldv From ldv at altlinux.org Fri Aug 7 18:53:54 2020 From: ldv at altlinux.org (Dmitry V. Levin) Date: Fri, 7 Aug 2020 21:53:54 +0300 Subject: [PATCH v6 3/5] Use get_proc_pid for /proc paths In-Reply-To: <20200806190211.118721-4-uzonyi.akos@gmail.com> References: <20200806190211.118721-1-uzonyi.akos@gmail.com> <20200806190211.118721-4-uzonyi.akos@gmail.com> Message-ID: <20200807185354.GB5985@altlinux.org> On Thu, Aug 06, 2020 at 09:02:09PM +0200, ?kos Uzonyi wrote: > * mmap_cache.c (mmap_cache_rebuild_if_invalid): Use proc pid instead of > tcp->pid for /proc path. > * util.c (getfdproto): Likewise. > (pidfd_get_pid): Likewise. > * pathtrace.c (getfdpath_pid): Likewise. > * strace.c (attach_tcb): Likewise. > --- > mmap_cache.c | 2 +- > pathtrace.c | 5 ++++- > strace.c | 2 +- > util.c | 7 +++++-- > 4 files changed, 11 insertions(+), 5 deletions(-) > > diff --git a/mmap_cache.c b/mmap_cache.c > index 89c62254..9825df26 100644 > --- a/mmap_cache.c > +++ b/mmap_cache.c > @@ -84,7 +84,7 @@ mmap_cache_rebuild_if_invalid(struct tcb *tcp, const char *caller) > return MMAP_CACHE_REBUILD_READY; > > char filename[sizeof("/proc/4294967296/maps")]; > - xsprintf(filename, "/proc/%u/maps", tcp->pid); > + xsprintf(filename, "/proc/%u/maps", get_proc_pid(tcp)); > > FILE *fp = fopen_stream(filename, "r"); > if (!fp) { > diff --git a/pathtrace.c b/pathtrace.c > index 5b60762b..74717a8a 100644 > --- a/pathtrace.c > +++ b/pathtrace.c > @@ -87,7 +87,10 @@ getfdpath_pid(pid_t pid, int fd, char *buf, unsigned bufsize) > if (fd < 0) > return -1; > > - xsprintf(linkpath, "/proc/%u/fd/%u", pid, fd); > + int proc_pid = 0; > + translate_pid(NULL, pid, PT_TID, &proc_pid); > + > + xsprintf(linkpath, "/proc/%u/fd/%u", proc_pid, fd); This looks like an emulation of get_proc_pid(tcp) for the case when we have no tcp. Fortunately, we have a tcp argument, it's in function getfdpath. Since there are no users of getfdpath_pid that couldn't use getfdpath instead, I suggest removing getfdpath_pid and defining just getfdpath, this would make the code clearer. > n = readlink(linkpath, buf, bufsize - 1); > /* > * NB: if buf is too small, readlink doesn't fail, > diff --git a/util.c b/util.c > index 094e5818..d87d022e 100644 > --- a/util.c > +++ b/util.c > @@ -582,8 +582,11 @@ printdev(struct tcb *tcp, int fd, const char *path) > pid_t > pidfd_get_pid(pid_t pid_of_fd, int fd) > { > + int proc_pid = 0; > + translate_pid(NULL, pid_of_fd, PT_TID, &proc_pid); > + > char fdi_path[sizeof("/proc/%u/fdinfo/%u") + 2 * sizeof(int) * 3]; > - xsprintf(fdi_path, "/proc/%u/fdinfo/%u", pid_of_fd, fd); > + xsprintf(fdi_path, "/proc/%u/fdinfo/%u", proc_pid, fd); > > FILE *f = fopen_stream(fdi_path, "r"); > if (!f) Likewise, this would invoke the whole translate_pid machinery even for the case when is_proc_ours() returns true. Could something be done about it? The idea is not to bring all these heavy translation mechanisms up unnecessarily, that is, unless /proc is messed up or --pidns-translation is specified. -- ldv From ldv at altlinux.org Fri Aug 7 19:04:04 2020 From: ldv at altlinux.org (Dmitry V. Levin) Date: Fri, 7 Aug 2020 22:04:04 +0300 Subject: [PATCH v6 1/5] PID namespace translation support In-Reply-To: <20200806190211.118721-2-uzonyi.akos@gmail.com> References: <20200806190211.118721-1-uzonyi.akos@gmail.com> <20200806190211.118721-2-uzonyi.akos@gmail.com> Message-ID: <20200807190404.GC5985@altlinux.org> On Thu, Aug 06, 2020 at 09:02:07PM +0200, ?kos Uzonyi wrote: > * pidns.c: New file. > * trie.c: New file. > * trie.h: New file. Sorry, these files are really hard to review, especially trie.c: when I read it for about five minutes my mind blows up. So I'll be reviewing these products of a superiour mind in five minute chunks, sorry. -- ldv From ldv at altlinux.org Fri Aug 7 19:09:25 2020 From: ldv at altlinux.org (Dmitry V. Levin) Date: Fri, 7 Aug 2020 22:09:25 +0300 Subject: [PATCH v6 5/5] Add tests for PID namespace translation In-Reply-To: <20200806190211.118721-6-uzonyi.akos@gmail.com> References: <20200806190211.118721-1-uzonyi.akos@gmail.com> <20200806190211.118721-6-uzonyi.akos@gmail.com> Message-ID: <20200807190925.GD5985@altlinux.org> On Thu, Aug 06, 2020 at 09:02:11PM +0200, ?kos Uzonyi wrote: > tests/gettid--pidns-translation.c | 2 + Note that this test is constantly failing one of github ci tests, see e.g. https://github.com/strace/strace/runs/959422499 Could you have a look, please? -- ldv From uzonyi.akos at gmail.com Fri Aug 7 19:12:05 2020 From: uzonyi.akos at gmail.com (=?UTF-8?B?w4Frb3MgVXpvbnlp?=) Date: Fri, 7 Aug 2020 21:12:05 +0200 Subject: [PATCH v6 3/5] Use get_proc_pid for /proc paths In-Reply-To: <20200807185354.GB5985@altlinux.org> References: <20200806190211.118721-1-uzonyi.akos@gmail.com> <20200806190211.118721-4-uzonyi.akos@gmail.com> <20200807185354.GB5985@altlinux.org> Message-ID: On Fri, 7 Aug 2020 at 20:53, Dmitry V. Levin wrote: > On Thu, Aug 06, 2020 at 09:02:09PM +0200, ?kos Uzonyi wrote: > > * mmap_cache.c (mmap_cache_rebuild_if_invalid): Use proc pid instead of > > tcp->pid for /proc path. > > * util.c (getfdproto): Likewise. > > (pidfd_get_pid): Likewise. > > * pathtrace.c (getfdpath_pid): Likewise. > > * strace.c (attach_tcb): Likewise. > > --- > > mmap_cache.c | 2 +- > > pathtrace.c | 5 ++++- > > strace.c | 2 +- > > util.c | 7 +++++-- > > 4 files changed, 11 insertions(+), 5 deletions(-) > > > > diff --git a/mmap_cache.c b/mmap_cache.c > > index 89c62254..9825df26 100644 > > --- a/mmap_cache.c > > +++ b/mmap_cache.c > > @@ -84,7 +84,7 @@ mmap_cache_rebuild_if_invalid(struct tcb *tcp, const char *caller) > > return MMAP_CACHE_REBUILD_READY; > > > > char filename[sizeof("/proc/4294967296/maps")]; > > - xsprintf(filename, "/proc/%u/maps", tcp->pid); > > + xsprintf(filename, "/proc/%u/maps", get_proc_pid(tcp)); > > > > FILE *fp = fopen_stream(filename, "r"); > > if (!fp) { > > diff --git a/pathtrace.c b/pathtrace.c > > index 5b60762b..74717a8a 100644 > > --- a/pathtrace.c > > +++ b/pathtrace.c > > @@ -87,7 +87,10 @@ getfdpath_pid(pid_t pid, int fd, char *buf, unsigned bufsize) > > if (fd < 0) > > return -1; > > > > - xsprintf(linkpath, "/proc/%u/fd/%u", pid, fd); > > + int proc_pid = 0; > > + translate_pid(NULL, pid, PT_TID, &proc_pid); > > + > > + xsprintf(linkpath, "/proc/%u/fd/%u", proc_pid, fd); > > This looks like an emulation of get_proc_pid(tcp) for the case > when we have no tcp. > > Fortunately, we have a tcp argument, it's in function getfdpath. > Since there are no users of getfdpath_pid that couldn't use getfdpath > instead, I suggest removing getfdpath_pid and defining just getfdpath, > this would make the code clearer. getfdpath_pid was introduced by me recently. It's used in printfd_pid (util.c), and it cannot be replaced by getfdpath. getfdpath_pid is necessary for decoding a fd of another process (not the tracee), which is the case in kcmp. > > n = readlink(linkpath, buf, bufsize - 1); > > /* > > * NB: if buf is too small, readlink doesn't fail, > > diff --git a/util.c b/util.c > > index 094e5818..d87d022e 100644 > > --- a/util.c > > +++ b/util.c > > @@ -582,8 +582,11 @@ printdev(struct tcb *tcp, int fd, const char *path) > > pid_t > > pidfd_get_pid(pid_t pid_of_fd, int fd) > > { > > + int proc_pid = 0; > > + translate_pid(NULL, pid_of_fd, PT_TID, &proc_pid); > > + > > char fdi_path[sizeof("/proc/%u/fdinfo/%u") + 2 * sizeof(int) * 3]; > > - xsprintf(fdi_path, "/proc/%u/fdinfo/%u", pid_of_fd, fd); > > + xsprintf(fdi_path, "/proc/%u/fdinfo/%u", proc_pid, fd); > > > > FILE *f = fopen_stream(fdi_path, "r"); > > if (!f) > > Likewise, this would invoke the whole translate_pid machinery even for the > case when is_proc_ours() returns true. Could something be done about it? > > The idea is not to bring all these heavy translation mechanisms up > unnecessarily, that is, unless /proc is messed up or --pidns-translation > is specified. Actually, translation happens very fast in that case, as the following condition will be true (in translate_pid): /* If translation is trivial */ if (tip.from_ns == our_ns && (is_proc_ours() || !proc_pid_ptr)) { So we could even remove the "if (is_proc_ours())" optimization from get_proc_pid, as it is already done in translate_pid. From ldv at altlinux.org Fri Aug 7 19:29:38 2020 From: ldv at altlinux.org (Dmitry V. Levin) Date: Fri, 7 Aug 2020 22:29:38 +0300 Subject: [PATCH v6 3/5] Use get_proc_pid for /proc paths In-Reply-To: References: <20200806190211.118721-1-uzonyi.akos@gmail.com> <20200806190211.118721-4-uzonyi.akos@gmail.com> <20200807185354.GB5985@altlinux.org> Message-ID: <20200807192938.GE5985@altlinux.org> On Fri, Aug 07, 2020 at 09:12:05PM +0200, ?kos Uzonyi wrote: > On Fri, 7 Aug 2020 at 20:53, Dmitry V. Levin wrote: > > On Thu, Aug 06, 2020 at 09:02:09PM +0200, ?kos Uzonyi wrote: > > > * mmap_cache.c (mmap_cache_rebuild_if_invalid): Use proc pid instead of > > > tcp->pid for /proc path. > > > * util.c (getfdproto): Likewise. > > > (pidfd_get_pid): Likewise. > > > * pathtrace.c (getfdpath_pid): Likewise. > > > * strace.c (attach_tcb): Likewise. > > > --- > > > mmap_cache.c | 2 +- > > > pathtrace.c | 5 ++++- > > > strace.c | 2 +- > > > util.c | 7 +++++-- > > > 4 files changed, 11 insertions(+), 5 deletions(-) > > > > > > diff --git a/mmap_cache.c b/mmap_cache.c > > > index 89c62254..9825df26 100644 > > > --- a/mmap_cache.c > > > +++ b/mmap_cache.c > > > @@ -84,7 +84,7 @@ mmap_cache_rebuild_if_invalid(struct tcb *tcp, const char *caller) > > > return MMAP_CACHE_REBUILD_READY; > > > > > > char filename[sizeof("/proc/4294967296/maps")]; > > > - xsprintf(filename, "/proc/%u/maps", tcp->pid); > > > + xsprintf(filename, "/proc/%u/maps", get_proc_pid(tcp)); > > > > > > FILE *fp = fopen_stream(filename, "r"); > > > if (!fp) { > > > diff --git a/pathtrace.c b/pathtrace.c > > > index 5b60762b..74717a8a 100644 > > > --- a/pathtrace.c > > > +++ b/pathtrace.c > > > @@ -87,7 +87,10 @@ getfdpath_pid(pid_t pid, int fd, char *buf, unsigned bufsize) > > > if (fd < 0) > > > return -1; > > > > > > - xsprintf(linkpath, "/proc/%u/fd/%u", pid, fd); > > > + int proc_pid = 0; > > > + translate_pid(NULL, pid, PT_TID, &proc_pid); > > > + > > > + xsprintf(linkpath, "/proc/%u/fd/%u", proc_pid, fd); > > > > This looks like an emulation of get_proc_pid(tcp) for the case > > when we have no tcp. > > > > Fortunately, we have a tcp argument, it's in function getfdpath. > > Since there are no users of getfdpath_pid that couldn't use getfdpath > > instead, I suggest removing getfdpath_pid and defining just getfdpath, > > this would make the code clearer. > > getfdpath_pid was introduced by me recently. It's used in printfd_pid > (util.c), and it cannot be replaced by getfdpath. getfdpath_pid is > necessary for decoding a fd of another process (not the tracee), which > is the case in kcmp. Indeed, I used to remember that, but it has eventually slipped my mind. > > > > n = readlink(linkpath, buf, bufsize - 1); > > > /* > > > * NB: if buf is too small, readlink doesn't fail, > > > diff --git a/util.c b/util.c > > > index 094e5818..d87d022e 100644 > > > --- a/util.c > > > +++ b/util.c > > > @@ -582,8 +582,11 @@ printdev(struct tcb *tcp, int fd, const char *path) > > > pid_t > > > pidfd_get_pid(pid_t pid_of_fd, int fd) > > > { > > > + int proc_pid = 0; > > > + translate_pid(NULL, pid_of_fd, PT_TID, &proc_pid); > > > + > > > char fdi_path[sizeof("/proc/%u/fdinfo/%u") + 2 * sizeof(int) * 3]; > > > - xsprintf(fdi_path, "/proc/%u/fdinfo/%u", pid_of_fd, fd); > > > + xsprintf(fdi_path, "/proc/%u/fdinfo/%u", proc_pid, fd); > > > > > > FILE *f = fopen_stream(fdi_path, "r"); > > > if (!f) > > > > Likewise, this would invoke the whole translate_pid machinery even for the > > case when is_proc_ours() returns true. Could something be done about it? > > > > The idea is not to bring all these heavy translation mechanisms up > > unnecessarily, that is, unless /proc is messed up or --pidns-translation > > is specified. > > Actually, translation happens very fast in that case, as the following > condition will be true (in translate_pid): > > /* If translation is trivial */ > if (tip.from_ns == our_ns && (is_proc_ours() || !proc_pid_ptr)) { > > So we could even remove the "if (is_proc_ours())" optimization from > get_proc_pid, as it is already done in translate_pid. Sorry, I don't follow: translate_pid(NULL) calls both get_our_ns() and is_proc_ours(), but I don't understand why it has to call get_our_ns() if the result is essentially ignored anyway. -- ldv From uzonyi.akos at gmail.com Fri Aug 7 19:34:22 2020 From: uzonyi.akos at gmail.com (=?UTF-8?B?w4Frb3MgVXpvbnlp?=) Date: Fri, 7 Aug 2020 21:34:22 +0200 Subject: [PATCH v6 1/5] PID namespace translation support In-Reply-To: <20200807182318.GA5985@altlinux.org> References: <20200806190211.118721-1-uzonyi.akos@gmail.com> <20200806190211.118721-2-uzonyi.akos@gmail.com> <20200807182318.GA5985@altlinux.org> Message-ID: On Fri, 7 Aug 2020 at 20:23, Dmitry V. Levin wrote: > On Thu, Aug 06, 2020 at 09:02:07PM +0200, ?kos Uzonyi wrote: > [...] > > diff --git a/NEWS b/NEWS > > index b83f9e80..9086fde9 100644 > > --- a/NEWS > > +++ b/NEWS > > @@ -14,6 +14,7 @@ Noteworthy changes in release ?.? (????-??-??) > > KEYCTL_*, KVM_*, LOOP_*, NDA_*, RTC_*, TCA_*, STATX_*, and *_MAGIC > > constants. > > * Updated lists of ioctl commands from Linux 5.8. > > + * Added --pidns-translation opition for PID namespace translation. > > Typo? > > > @@ -983,6 +1005,27 @@ print_local_array_ex(struct tcb *tcp, > > extern kernel_ulong_t * > > fetch_indirect_syscall_args(struct tcb *, kernel_ulong_t addr, unsigned int n_args); > > > > +extern void pidns_init(void); > > + > > +/** > > + * Returns the pid of the tracee as present in /proc (can be different from > > + * tcp->pid if /proc and the tracee process are in different PID namespaces). > > + */ > > +extern int get_proc_pid(struct tcb *); > > I'm still puzzled what /proc are you talking about, the tracer's /proc or > the tracee's /proc. It's the tracer's /proc. I will clarify it. > > @@ -1058,6 +1101,14 @@ printfd(struct tcb *tcp, int fd) > > * of the tracee the descriptor tcp). This is a stub. > > */ > > extern void printfd_pid_tracee_ns(struct tcb *tcp, pid_t pid, int fd); > > + > > +extern void printpid(struct tcb *, int pid, enum pid_type type); > > Although this might look obvious, I suggest adding a short comment for > printpid, too, to make it clear that printpid prints the pid given > in the tracee's pid namespace. Ok, I'll add a short comment. > > +/** > > + * Key: Proc PID > > + * Value: stuct proc_data > > Typo? > > > +/** > > + * Helper function for creating a trie. > > + * > > + * For node_key_bits and data_block_key_bits 4 is used (so trie height is 32 / 4 > > + * = 8, and node sizes are 8 byte * 2^4 = 128 bytes), which seems to be a good > > + * tradeoff between between memory usage and lookup time. It should not be too > > Typo? > > > + * large, since there can be large holes between PIDs, and it would be just a > > + * waste of memory having large nodes with lot of NULL pointers in them. > > + */ > > +static struct trie * > > +create_trie_4(uint8_t key_size, uint8_t item_size_lg, uint64_t empty_value) > > +{ > > + struct trie *t = trie_create(key_size, item_size_lg, 4, 4, empty_value); > > + if (!t) > > + error_msg_and_die("creating trie failed"); > > + > > + return t; > > +} > > I believe empty_value is always 0, so why bother with the argument? I'm working on a performance improvement: translating pids by unix sockets. In that code I use a trie where empty_value is -1 (keys are file descriptors), so I would like to keep that argument. > > + while (p) { > > + errno = 0; > > + long id = strtol(p, NULL, 10); > > + > > + if (errno || (id < 1) || (id > INT_MAX)) { > > I don't think these extra brackets increase readability. Agree. > > + perror_func_msg("converting pid to int"); > > + break; > > + } > > I suggest also printing the value of p in this unlikely case. OK. > > +/** > > + * Returns whether the /proc filesystem's PID namespace is same as strace's. > > Grammar: is the same. > > > diff --git a/strace.1.in b/strace.1.in > > index 3b21caec..adca194c 100644 > > --- a/strace.1.in > > +++ b/strace.1.in > > @@ -1075,6 +1075,10 @@ Print all available information associated with file descritors: > > protocol-specific information associated with socket file descriptors, > > block/character device number associated with device file descriptors, > > and PIDs asociated with pidfd file descriptors. > > +.TP > > +.B \-\-pidns\-translation > > +If strace and tracee are in different PID namespaces, print PIDs in > > +strace's namespace also. > > Changing "print PIDs in strace's namespace also" to either > "print PIDs also in strace's namespace" or > "print PIDs in strace's namespace, too" would likely result > to a more grammatically correct sentence. > > > diff --git a/trie.c b/trie.c > > new file mode 100644 > > index 00000000..76cecc25 > > --- /dev/null > > +++ b/trie.c > > @@ -0,0 +1,250 @@ > > +/* > > + * Simple trie implementation for key-value mapping storage > > + * > > + * Copyright (c) 2020 ?kos Uzonyi > > + * All rights reserved. > > + * > > + * SPDX-License-Identifier: LGPL-2.1-or-later > > + */ > > + > > +#include "defs.h" > > + > > +#include > > Does this code use assert? Indeed, it's not necessary anymore. > > +#include > > +#include > > +#include > > + > > +#include "trie.h" > > + > > +static const uint8_t ptr_sz_lg = (sizeof(uint64_t *) == 8 ? 6 : 5); > > Hmm, pidns.c uses a slightly different (although essentially the same) > definition of ptr_sz_lg. Oh thanks, I modified the one in pidns.c recently, and forgot to update this one. > > + > > +/** > > + * Returns lg2 of node size for the specific level of the trie. If max_depth > > + * provided is less than zero, it is calculated via trie_get_depth call. > > + */ > > +static uint8_t > > +trie_get_node_size(struct trie *t, uint8_t depth) > > What do you mean by "If max_depth provided"? Sorry, I forgot to update the documentation when I removed the "max_depth" argument. > > +struct trie * > > +trie_create(uint8_t key_size, uint8_t item_size_lg, uint8_t node_key_bits, > > + uint8_t data_block_key_bits, uint64_t empty_value) > > +{ > > + if (item_size_lg > 6) > > + return NULL; > > + if (key_size > 64) > > + return NULL; > > + if (node_key_bits < 1) > > + return NULL; > > + if (data_block_key_bits < 1 || data_block_key_bits > key_size) > > + return NULL; > > Should there be a check that node_key_bits isn't too big, for consistency? Actually it's not a problem if node_key_bits is big. If node_key_bits is larger than key_size, then all the key bits (except the bits for the data block) are part of the "" node level. > > +static uint64_t > > +trie_iterate_keys_node(struct trie *t, > > + trie_iterate_fn fn, void *fn_data, > > + void *node, uint64_t start, uint64_t end, > > + uint8_t depth) > > +{ > > + if (start > end || !node) > > + return 0; > > + > > + if (depth == t->max_depth) { > > + for (uint64_t i = start; i <= end; i++) > > + fn(fn_data, i, trie_data_block_get(t, > > + (uint64_t *) node, i)); > > + > > + return end - start + 1; //TODO: overflow > > Overflow? The function returns the number of values iterated. In case the trie contains 2^64 values, the above expression will overflow to 0. But since it's not possible to have so many values in the trie, I agree that this comment should be removed. :) > > + /** > > + * Number of bits in key that makes a symbol for a node. > > + * (equals to log2 of the child count of the node) > > + */ > > + uint8_t node_key_bits; > > + > > + /** > > + * Number of bits in key that make a symbol for the data block (leaf). > > Typo? Sorry I can't find the typo you are referring to. > > + * (equals to log2 of the value count stored in a data block) > > + */ > > + uint8_t data_block_key_bits; > > + > > + /** The depth of the data block. Caluclated from the values above */ > > Typo? Thanks, I'll fix all the typos you found. I think I should have run a spell checker on the comments, sorry. From ldv at altlinux.org Fri Aug 7 19:43:24 2020 From: ldv at altlinux.org (Dmitry V. Levin) Date: Fri, 7 Aug 2020 22:43:24 +0300 Subject: [PATCH v6 2/5] Use printpid in decoders In-Reply-To: <20200806190211.118721-3-uzonyi.akos@gmail.com> References: <20200806190211.118721-1-uzonyi.akos@gmail.com> <20200806190211.118721-3-uzonyi.akos@gmail.com> Message-ID: <20200807194324.GA7365@altlinux.org> On Thu, Aug 06, 2020 at 09:02:08PM +0200, ?kos Uzonyi wrote: > * getpid.c: New file. > * Makefile.am (libstrace_a_SOURCES): Add getpid.c. By the way, you can use a simpler form "Add it" instead of "Add getpid.c". > diff --git a/get_robust_list.c b/get_robust_list.c > index b5aebaff..4b771bac 100644 > --- a/get_robust_list.c > +++ b/get_robust_list.c > @@ -10,7 +10,8 @@ > SYS_FUNC(get_robust_list) > { > if (entering(tcp)) { > - tprintf("%d, ", (int) tcp->u_arg[0]); > + printpid(tcp, (int) tcp->u_arg[0], PT_TID); > + tprints(", "); The explicit cast used to be need for tprintf, but I don't think it's still useful in printpid calls like this one. > diff --git a/ioprio.c b/ioprio.c > index 873c8ce5..52144884 100644 > --- a/ioprio.c > +++ b/ioprio.c > @@ -49,13 +49,30 @@ print_ioprio(unsigned int ioprio) > ? tprints_comment : tprints)(str); > } > > +static void > +ioprio_print_who(struct tcb *tcp, int which, int who) > +{ > + switch (which) > + { > + case IOPRIO_WHO_PROCESS: > + printpid(tcp, who, PT_TGID); > + break; > + case IOPRIO_WHO_PGRP: > + printpid(tcp, who, PT_PGID); > + break; > + default: > + tprintf("%d", who); > + break; > + } > +} > + > SYS_FUNC(ioprio_get) > { > if (entering(tcp)) { > /* int which */ > printxval(ioprio_who, tcp->u_arg[0], "IOPRIO_WHO_???"); > - /* int who */ > - tprintf(", %d", (int) tcp->u_arg[1]); > + tprints(", "); > + ioprio_print_who(tcp, (int) tcp->u_arg[0], (int) tcp->u_arg[1]); Likewise, I don't think these explicit casts increase readability. > return 0; > } else { > if (syserror(tcp)) > @@ -72,8 +89,9 @@ SYS_FUNC(ioprio_set) > { > /* int which */ > printxval(ioprio_who, tcp->u_arg[0], "IOPRIO_WHO_???"); > - /* int who */ > - tprintf(", %d, ", (int) tcp->u_arg[1]); > + tprints(", "); > + ioprio_print_who(tcp, (int) tcp->u_arg[0], (int) tcp->u_arg[1]); > + tprints(", "); Likewise. > diff --git a/ipc_shmctl.c b/ipc_shmctl.c > index 8c9e1e7a..71b41651 100644 > --- a/ipc_shmctl.c > +++ b/ipc_shmctl.c > @@ -12,6 +12,7 @@ > */ > > #include "defs.h" > +#include "print_fields.h" > > #include DEF_MPERS_TYPE(shmid_ds_t) > > @@ -53,8 +54,8 @@ print_shmid_ds(struct tcb *const tcp, const kernel_ulong_t addr, int cmd) > PRINT_FIELD_UID(", ", shmid_ds.shm_perm, cgid); > tprints("}"); > tprintf(", shm_segsz=%u", (unsigned) shmid_ds.shm_segsz); > - PRINT_FIELD_D(", ", shmid_ds, shm_cpid); > - PRINT_FIELD_D(", ", shmid_ds, shm_lpid); > + PRINT_FIELD_TGID(", ", shmid_ds, shm_cpid, tcp); > + PRINT_FIELD_TGID(", ", shmid_ds, shm_lpid, tcp); > tprintf(", shm_nattch=%u", (unsigned) shmid_ds.shm_nattch); > tprintf(", shm_atime=%u", (unsigned) shmid_ds.shm_atime); > tprintf(", shm_dtime=%u", (unsigned) shmid_ds.shm_dtime); The #include "print_fields.h" added here is probably a leftover from an early edition. > diff --git a/numa.c b/numa.c > index cc7a7cc6..37b95397 100644 > --- a/numa.c > +++ b/numa.c > @@ -44,7 +44,8 @@ print_nodemask(struct tcb *const tcp, const kernel_ulong_t addr, > > SYS_FUNC(migrate_pages) > { > - tprintf("%d, %" PRI_klu ", ", (int) tcp->u_arg[0], tcp->u_arg[1]); > + printpid(tcp, (int) tcp->u_arg[0], PT_TGID); > + tprintf(", %" PRI_klu ", ", tcp->u_arg[1]); Likewise, I don't think this explicit cast increases readability. > print_nodemask(tcp, tcp->u_arg[2], tcp->u_arg[1]); > tprints(", "); > print_nodemask(tcp, tcp->u_arg[3], tcp->u_arg[1]); > @@ -170,7 +171,8 @@ SYS_FUNC(move_pages) > kernel_ulong_t buf; > > if (entering(tcp)) { > - tprintf("%d, %" PRI_klu ", ", (int) tcp->u_arg[0], npages); > + printpid(tcp, (int) tcp->u_arg[0], PT_TGID); > + tprintf(", %" PRI_klu ", ", npages); Likewise. > diff --git a/pidfd_open.c b/pidfd_open.c > index bbc7f617..10b5003d 100644 > --- a/pidfd_open.c > +++ b/pidfd_open.c > @@ -10,7 +10,7 @@ > SYS_FUNC(pidfd_open) > { > /* pid_t pid */ > - tprintf("%d", (int) tcp->u_arg[0]); > + printpid(tcp, (int) tcp->u_arg[0], PT_TGID); Likewise. > diff --git a/process_vm.c b/process_vm.c > index abee1e68..50acb3fd 100644 > --- a/process_vm.c > +++ b/process_vm.c > @@ -13,7 +13,8 @@ SYS_FUNC(process_vm_readv) > { > if (entering(tcp)) { > /* arg 1: pid */ > - tprintf("%d, ", (int) tcp->u_arg[0]); > + printpid(tcp, (int) tcp->u_arg[0], PT_TGID); > + tprints(", "); Likewise. > } else { > kernel_ulong_t local_iovcnt = tcp->u_arg[2]; > kernel_ulong_t remote_iovcnt = tcp->u_arg[4]; > @@ -42,7 +43,8 @@ SYS_FUNC(process_vm_writev) > kernel_ulong_t flags = tcp->u_arg[5]; > > /* arg 1: pid */ > - tprintf("%d, ", (int) tcp->u_arg[0]); > + printpid(tcp, (int) tcp->u_arg[0], PT_TGID); > + tprints(", "); Likewise. > diff --git a/resource.c b/resource.c > index 53192ee9..bd21b748 100644 > --- a/resource.c > +++ b/resource.c > @@ -142,7 +142,8 @@ SYS_FUNC(setrlimit) > SYS_FUNC(prlimit64) > { > if (entering(tcp)) { > - tprintf("%d, ", (int) tcp->u_arg[0]); > + printpid(tcp, (int) tcp->u_arg[0], PT_TGID); > + tprints(", "); Likewise. > diff --git a/sched.c b/sched.c > index 788ef39b..7ae5abe2 100644 > --- a/sched.c > +++ b/sched.c > @@ -21,7 +21,7 @@ > SYS_FUNC(sched_getscheduler) > { > if (entering(tcp)) { > - tprintf("%d", (int) tcp->u_arg[0]); > + printpid(tcp, (int) tcp->u_arg[0], PT_TGID); Likewise. > } else if (!syserror(tcp)) { > tcp->auxstr = xlookup(schedulers, (kernel_ulong_t) tcp->u_rval); > return RVAL_STR; > @@ -31,7 +31,8 @@ SYS_FUNC(sched_getscheduler) > > SYS_FUNC(sched_setscheduler) > { > - tprintf("%d, ", (int) tcp->u_arg[0]); > + printpid(tcp, (int) tcp->u_arg[0], PT_TGID); > + tprints(", "); Likewise. > printxval(schedulers, tcp->u_arg[1], "SCHED_???"); > tprints(", "); > printnum_int(tcp, tcp->u_arg[2], "%d"); > @@ -41,16 +42,19 @@ SYS_FUNC(sched_setscheduler) > > SYS_FUNC(sched_getparam) > { > - if (entering(tcp)) > - tprintf("%d, ", (int) tcp->u_arg[0]); > - else > + if (entering(tcp)) { > + printpid(tcp, (int) tcp->u_arg[0], PT_TGID); > + tprints(", "); > + } else { Likewise. > printnum_int(tcp, tcp->u_arg[1], "%d"); > + } > return 0; > } > > SYS_FUNC(sched_setparam) > { > - tprintf("%d, ", (int) tcp->u_arg[0]); > + printpid(tcp, (int) tcp->u_arg[0], PT_TGID); > + tprints(", "); Likewise. > printnum_int(tcp, tcp->u_arg[1], "%d"); > > return RVAL_DECODED; > @@ -68,7 +72,8 @@ do_sched_rr_get_interval(struct tcb *const tcp, > const print_obj_by_addr_fn print_ts) > { > if (entering(tcp)) { > - tprintf("%d, ", (int) tcp->u_arg[0]); > + printpid(tcp, (int) tcp->u_arg[0], PT_TGID); > + tprints(", "); Likewise. > } else { > if (syserror(tcp)) > printaddr(tcp->u_arg[1]); > @@ -160,7 +165,8 @@ end: > SYS_FUNC(sched_setattr) > { > if (entering(tcp)) { > - tprintf("%d, ", (int) tcp->u_arg[0]); > + printpid(tcp, (int) tcp->u_arg[0], PT_TGID); > + tprints(", "); Likewise. > print_sched_attr(tcp, tcp->u_arg[1], 0); > } else { > struct sched_attr attr; > @@ -179,7 +185,8 @@ SYS_FUNC(sched_setattr) > SYS_FUNC(sched_getattr) > { > if (entering(tcp)) { > - tprintf("%d, ", (int) tcp->u_arg[0]); > + printpid(tcp, (int) tcp->u_arg[0], PT_TGID); Likewise. > @@ -448,7 +449,7 @@ SYS_FUNC(kill) > > SYS_FUNC(tkill) > { > - tprintf("%d", (int) tcp->u_arg[0]); > + printpid(tcp, (int) tcp->u_arg[0], PT_TID); Likewise. > tprints(", "); > printsignal(tcp->u_arg[1]); > > @@ -457,8 +458,12 @@ SYS_FUNC(tkill) > > SYS_FUNC(tgkill) > { > - /* tgid, tid */ > - tprintf("%d, %d, ", (int) tcp->u_arg[0], (int) tcp->u_arg[1]); > + /* tgid */ > + printpid(tcp, (int) tcp->u_arg[0], PT_TGID); > + tprints(", "); > + /* tid */ > + printpid(tcp, (int) tcp->u_arg[1], PT_TID); > + tprints(", "); Likewise. > /* signal */ > printsignal(tcp->u_arg[2]); > > @@ -624,7 +629,8 @@ print_sigqueueinfo(struct tcb *const tcp, const int sig, > > SYS_FUNC(rt_sigqueueinfo) > { > - tprintf("%d, ", (int) tcp->u_arg[0]); > + printpid(tcp, (int) tcp->u_arg[0], PT_TGID); > + tprints(", "); Likewise. > print_sigqueueinfo(tcp, tcp->u_arg[1], tcp->u_arg[2]); > > return RVAL_DECODED; > @@ -632,7 +638,10 @@ SYS_FUNC(rt_sigqueueinfo) > > SYS_FUNC(rt_tgsigqueueinfo) > { > - tprintf("%d, %d, ", (int) tcp->u_arg[0], (int) tcp->u_arg[1]); > + printpid(tcp, (int) tcp->u_arg[0], PT_TGID); > + tprints(", "); > + printpid(tcp, (int) tcp->u_arg[1], PT_TID); > + tprints(", "); Likewise. -- ldv From ldv at altlinux.org Fri Aug 7 19:53:36 2020 From: ldv at altlinux.org (Dmitry V. Levin) Date: Fri, 7 Aug 2020 22:53:36 +0300 Subject: [PATCH v6 1/5] PID namespace translation support In-Reply-To: References: <20200806190211.118721-1-uzonyi.akos@gmail.com> <20200806190211.118721-2-uzonyi.akos@gmail.com> <20200807182318.GA5985@altlinux.org> Message-ID: <20200807195336.GB7365@altlinux.org> On Fri, Aug 07, 2020 at 09:34:22PM +0200, ?kos Uzonyi wrote: > On Fri, 7 Aug 2020 at 20:23, Dmitry V. Levin wrote: > > On Thu, Aug 06, 2020 at 09:02:07PM +0200, ?kos Uzonyi wrote: [...] > > > + * large, since there can be large holes between PIDs, and it would be just a > > > + * waste of memory having large nodes with lot of NULL pointers in them. > > > + */ > > > +static struct trie * > > > +create_trie_4(uint8_t key_size, uint8_t item_size_lg, uint64_t empty_value) > > > +{ > > > + struct trie *t = trie_create(key_size, item_size_lg, 4, 4, empty_value); > > > + if (!t) > > > + error_msg_and_die("creating trie failed"); > > > + > > > + return t; > > > +} > > > > I believe empty_value is always 0, so why bother with the argument? > > I'm working on a performance improvement: translating pids by unix > sockets. In that code I use a trie where empty_value is -1 (keys are > file descriptors), so I would like to keep that argument. OK [...] > > > +struct trie * > > > +trie_create(uint8_t key_size, uint8_t item_size_lg, uint8_t node_key_bits, > > > + uint8_t data_block_key_bits, uint64_t empty_value) > > > +{ > > > + if (item_size_lg > 6) > > > + return NULL; > > > + if (key_size > 64) > > > + return NULL; > > > + if (node_key_bits < 1) > > > + return NULL; > > > + if (data_block_key_bits < 1 || data_block_key_bits > key_size) > > > + return NULL; > > > > Should there be a check that node_key_bits isn't too big, for consistency? > > Actually it's not a problem if node_key_bits is big. If node_key_bits > is larger than key_size, then all the key bits (except the bits for > the data block) are part of the "" node level. Unless we care about integer overflows due to node_key_bits being too large. Well, this definitely can wait as we are not going to have such large node_key_bits any time soon. [...] > > > + /** > > > + * Number of bits in key that makes a symbol for a node. > > > + * (equals to log2 of the child count of the node) > > > + */ > > > + uint8_t node_key_bits; > > > + > > > + /** > > > + * Number of bits in key that make a symbol for the data block (leaf). > > > > Typo? > > Sorry I can't find the typo you are referring to. It's grammar than. :) The first comments says: Number of bits in key that makes. The second comments says: Number of bits in key that make. By the way, it should be "in the key" in both cases. -- ldv From uzonyi.akos at gmail.com Fri Aug 7 21:11:22 2020 From: uzonyi.akos at gmail.com (=?UTF-8?B?w4Frb3MgVXpvbnlp?=) Date: Fri, 7 Aug 2020 23:11:22 +0200 Subject: [PATCH v6 3/5] Use get_proc_pid for /proc paths In-Reply-To: <20200807192938.GE5985@altlinux.org> References: <20200806190211.118721-1-uzonyi.akos@gmail.com> <20200806190211.118721-4-uzonyi.akos@gmail.com> <20200807185354.GB5985@altlinux.org> <20200807192938.GE5985@altlinux.org> Message-ID: On Fri, 7 Aug 2020 at 21:29, Dmitry V. Levin wrote: > On Fri, Aug 07, 2020 at 09:12:05PM +0200, ?kos Uzonyi wrote: > > On Fri, 7 Aug 2020 at 20:53, Dmitry V. Levin wrote: > > > On Thu, Aug 06, 2020 at 09:02:09PM +0200, ?kos Uzonyi wrote: [...] > > > > diff --git a/util.c b/util.c > > > > index 094e5818..d87d022e 100644 > > > > --- a/util.c > > > > +++ b/util.c > > > > @@ -582,8 +582,11 @@ printdev(struct tcb *tcp, int fd, const char *path) > > > > pid_t > > > > pidfd_get_pid(pid_t pid_of_fd, int fd) > > > > { > > > > + int proc_pid = 0; > > > > + translate_pid(NULL, pid_of_fd, PT_TID, &proc_pid); > > > > + > > > > char fdi_path[sizeof("/proc/%u/fdinfo/%u") + 2 * sizeof(int) * 3]; > > > > - xsprintf(fdi_path, "/proc/%u/fdinfo/%u", pid_of_fd, fd); > > > > + xsprintf(fdi_path, "/proc/%u/fdinfo/%u", proc_pid, fd); > > > > > > > > FILE *f = fopen_stream(fdi_path, "r"); > > > > if (!f) > > > > > > Likewise, this would invoke the whole translate_pid machinery even for the > > > case when is_proc_ours() returns true. Could something be done about it? > > > > > > The idea is not to bring all these heavy translation mechanisms up > > > unnecessarily, that is, unless /proc is messed up or --pidns-translation > > > is specified. > > > > Actually, translation happens very fast in that case, as the following > > condition will be true (in translate_pid): > > > > /* If translation is trivial */ > > if (tip.from_ns == our_ns && (is_proc_ours() || !proc_pid_ptr)) { > > > > So we could even remove the "if (is_proc_ours())" optimization from > > get_proc_pid, as it is already done in translate_pid. > > Sorry, I don't follow: translate_pid(NULL) calls both get_our_ns() > and is_proc_ours(), but I don't understand why it has to call > get_our_ns() if the result is essentially ignored anyway. Indeed, it calls get_our_ns, which is not needed if tcp is NULL. It's not a very big performance problem however, as get_our_ns return value is cached. But I'll modify translate_pid a bit, so get_our_ns is only called if really needed. From uzonyi.akos at gmail.com Sat Aug 8 13:33:06 2020 From: uzonyi.akos at gmail.com (=?UTF-8?B?w4Frb3MgVXpvbnlp?=) Date: Sat, 8 Aug 2020 15:33:06 +0200 Subject: [PATCH v6 5/5] Add tests for PID namespace translation In-Reply-To: <20200807190925.GD5985@altlinux.org> References: <20200806190211.118721-1-uzonyi.akos@gmail.com> <20200806190211.118721-6-uzonyi.akos@gmail.com> <20200807190925.GD5985@altlinux.org> Message-ID: On Fri, 7 Aug 2020 at 21:09, Dmitry V. Levin wrote: > On Thu, Aug 06, 2020 at 09:02:11PM +0200, ?kos Uzonyi wrote: > > tests/gettid--pidns-translation.c | 2 + > > Note that this test is constantly failing one of github ci tests, > see e.g. https://github.com/strace/strace/runs/959422499 > > Could you have a look, please? Unfortunately musl calls gettid in the child after fork. I think some kind of hack has to be done here, like running uniq on the output. From uzonyi.akos at gmail.com Sat Aug 8 21:14:32 2020 From: uzonyi.akos at gmail.com (=?UTF-8?q?=C3=81kos=20Uzonyi?=) Date: Sat, 8 Aug 2020 23:14:32 +0200 Subject: [PATCH v7 0/5] [PIDNS] Final Message-ID: <20200808211437.469898-1-uzonyi.akos@gmail.com> From: Uzonyi ?kos In gettid--pidns-translation test I used uniq to filter out gettid calls made by musl. Changes in v7: - Run uniq on gettid--pidns-translation test output - Add comment to printpid - translate_id: do not call get_our_ns if not necessary - Remove unnecessary parentheses - Fix commit message of last commit (s/-Y/--pidns-translation/) - get_proc_pid: remove unnecessary optimization - trie.c: remove #include - Add clarification to get_proc_pid's comment - Fix typos - trie.c: ptr_sz_lg use void* in sizeof - trie_get_node_size: fix comment - trie.c: remove "TODO: overflow" - ipc_shmctl.c: remove duplicate #include "print_field.h" Changes in v6: - Add function with documentation for creating tries - Do not use -1ULL as error indicator in tcb.pid_ns - Use unsigned int (instead of uint64_t) for NS IDs - Add constant for NS ID size. - Modify get_proc_pid a bit - Die if trie creation fails Changes in v5: - Squash "Use printpid in *" commits - Makefile.am: move adding getpid.c to "Use printpid in decoders" - Remove pid_ns_inited field from struct tcb - strace.1.in: remove -Y flag - Use tprints instead of tprintf where possible - Make some global variables static - pidns_init: remove "inited" bool variable - Make printpid_translation static - tests/pidns.c: refactor a bit - check_ns_ioctl: fix error msg - defs.h: Move adding get_proc_pid to "PID namespace translation support" - Remove tcp paramter name from declarations - Update printfd_pid_tracee_ns documentation - Use named constants for trie_create arguments - Add documentation comments - Add printpid_tgid_pgid function - Delete get_pid_max function; use global variables instead - Refactor trie: - Move key_size argument - Remove support for TRIE_SET - Merge trie_create, trie_init, trie_check functions - trie_free_node: make static, fix "node" argument type - Add max_depth field - Reorder functions - Extract common parts of trie_get, trie_set Changes in v4: - Skip tests if NS_* ioctl commands are not supported - Improve documentation in pidns.h - Use pipe for init process termination (instead of SIGKILL) - Add PIDNS_TEST_INIT macro - Remove "ifdef __NR_gettid" - Fix fork--pidns-tranlsation.test: skip if unshare fails with EPERM - Use debug message instead of normal message in some cases - Rename some labels - Rewrite get_ns function - Remove O_NONBLOCK from open(/proc//ns/pid) Changes in v3: - Split accidentally sqashed last commit - Undo modification of tests/pidfd_send_signal.c - Rename kcmp-yY test to kcmp-y--pidns-translation - Skip tests if unshare fails with EPERM - Fix buffer size in pidns_pid2str - Use largefile_wrappers.h macros - Return early if from_ns or our_ns is 0 - Do not call ioctl(NS_GET_PARENT) again, if first failed with ENOTTY - Skip pidns tests if Linux kernel version < 4.9 - Use smaller trie nodes in pidns.c - Remove race condition from fork--pidns-translation test - Move "key_size" to center in trie description - Use PT_TID (not PT_TGID) when translating tcp->pid - Fix get_ns_hierarchy and get_id_list functions - Fix migrate_pages test if syscall succeds - Fix filtering in ioctl_block--pidns-translation.test - Fix -a flag value in xetpriority test Changes in v2: - Add missing header files to Makefile - Fix pointer-to-int-cast errors - Fix unused-result errors - Use perror_msg instead of perror_func_msg where appropriate - Remove tcb parameter of read_int_from_file - Use xsprintf instead of snprintf - Refactor get_pid_max, get_ns_hierarchy, get_id_list functions - Remove -Y flag - Improve documentation of trie - Fix printing of f_owner_ex struct - Use printpid for F_GETOWN, F_SETOWN fcntl command arguments - Use printpid for shmid_ds.shm_cpid, shmid_ds.shm_clid - Call pidns_init before parsing arguments ?kos Uzonyi (5): PID namespace translation support Use printpid in decoders Use get_proc_pid for /proc paths Implement testing framework for pidns Add tests for PID namespace translation Makefile.am | 4 + NEWS | 1 + affinity.c | 6 +- block.c | 2 +- bpf.c | 2 +- capability.c | 4 +- clone.c | 14 +- defs.h | 60 +- fcntl.c | 24 +- get_robust_list.c | 3 +- getpid.c | 46 ++ ioprio.c | 26 +- ipc_shmctl.c | 4 +- kcmp.c | 5 +- largefile_wrappers.h | 2 + linux/dummy.h | 8 +- mmap_cache.c | 2 +- msghdr.c | 2 +- net.c | 2 +- netlink.c | 5 +- numa.c | 6 +- pathtrace.c | 5 +- pidfd_open.c | 2 +- pidns.c | 604 ++++++++++++++++++ print_fields.h | 24 + printsiginfo.c | 2 +- process.c | 3 +- process_vm.c | 6 +- resource.c | 27 +- sched.c | 25 +- signal.c | 21 +- sockaddr.c | 2 +- strace.1.in | 4 + strace.c | 11 +- syscall.c | 15 + tests/.gitignore | 31 + tests/Makefile.am | 38 ++ tests/fcntl--pidns-translation.c | 2 + tests/fcntl-common.c | 82 ++- tests/fcntl.c | 1 + tests/fcntl64--pidns-translation.c | 2 + tests/fcntl64.c | 3 + tests/fork--pidns-translation.awk | 15 + tests/fork--pidns-translation.c | 69 ++ tests/fork--pidns-translation.test | 16 + tests/gen_tests.in | 29 +- tests/getpgrp--pidns-translation.c | 2 + tests/getpgrp.c | 8 +- tests/getpid--pidns-translation.c | 2 + tests/getpid.c | 8 +- tests/getsid--pidns-translation.c | 2 + tests/getsid.c | 9 +- tests/gettid--pidns-translation.c | 2 + tests/gettid--pidns-translation.test | 19 + tests/gettid.c | 8 +- tests/init.sh | 31 + tests/ioctl_block--pidns-translation.c | 2 + tests/ioctl_block--pidns-translation.test | 24 + tests/ioctl_block.c | 24 +- tests/ioprio--pidns-translation.c | 2 + tests/ioprio.c | 54 +- tests/kcmp-y--pidns-translation.c | 2 + tests/kcmp.c | 36 +- tests/kill--pidns-translation.c | 2 + tests/kill.c | 12 +- tests/migrate_pages--pidns-translation.c | 2 + tests/migrate_pages.c | 17 +- tests/move_pages--pidns-translation.c | 2 + tests/move_pages.c | 51 +- tests/net-sockaddr--pidns-translation.c | 2 + tests/net-sockaddr.c | 66 +- tests/netlink_audit--pidns-translation.c | 2 + tests/netlink_audit--pidns-translation.test | 13 + tests/netlink_audit.c | 11 +- tests/pidfd_open--pidns-translation.c | 2 + tests/pidfd_open.c | 21 +- tests/pidfd_send_signal--pidns-translation.c | 2 + tests/pidfd_send_signal.c | 13 +- tests/pidns.c | 214 +++++++ tests/pidns.h | 56 ++ tests/prlimit64--pidns-translation.c | 2 + tests/prlimit64.c | 17 +- tests/process_vm_readv--pidns-translation.c | 2 + tests/process_vm_readv_writev.c | 27 +- tests/process_vm_writev--pidns-translation.c | 2 + tests/rt_sigqueueinfo--pidns-translation.c | 2 + tests/rt_sigqueueinfo.c | 15 +- tests/rt_tgsigqueueinfo--pidns-translation.c | 2 + tests/rt_tgsigqueueinfo.c | 26 +- tests/sched_xetaffinity--pidns-translation.c | 2 + tests/sched_xetaffinity.c | 31 +- tests/sched_xetattr--pidns-translation.c | 2 + tests/sched_xetattr.c | 47 +- tests/sched_xetparam--pidns-translation.c | 2 + tests/sched_xetparam.c | 20 +- tests/sched_xetscheduler--pidns-translation.c | 2 + tests/sched_xetscheduler.c | 44 +- tests/signal_receive--pidns-translation.c | 2 + tests/signal_receive.c | 22 +- tests/so_peercred--pidns-translation.c | 2 + tests/so_peercred.c | 22 + tests/xet_robust_list--pidns-translation.c | 2 + tests/xet_robust_list.c | 18 +- tests/xetpgid--pidns-translation.c | 2 + tests/xetpgid.c | 21 +- tests/xetpriority--pidns-translation.c | 2 + tests/xetpriority.c | 20 +- trie.c | 248 +++++++ trie.h | 89 +++ util.c | 27 +- wait.c | 36 +- 111 files changed, 2493 insertions(+), 255 deletions(-) create mode 100644 getpid.c create mode 100644 pidns.c create mode 100644 tests/fcntl--pidns-translation.c create mode 100644 tests/fcntl64--pidns-translation.c create mode 100644 tests/fork--pidns-translation.awk create mode 100644 tests/fork--pidns-translation.c create mode 100755 tests/fork--pidns-translation.test create mode 100644 tests/getpgrp--pidns-translation.c create mode 100644 tests/getpid--pidns-translation.c create mode 100644 tests/getsid--pidns-translation.c create mode 100644 tests/gettid--pidns-translation.c create mode 100755 tests/gettid--pidns-translation.test create mode 100644 tests/ioctl_block--pidns-translation.c create mode 100755 tests/ioctl_block--pidns-translation.test create mode 100644 tests/ioprio--pidns-translation.c create mode 100644 tests/kcmp-y--pidns-translation.c create mode 100644 tests/kill--pidns-translation.c create mode 100644 tests/migrate_pages--pidns-translation.c create mode 100644 tests/move_pages--pidns-translation.c create mode 100644 tests/net-sockaddr--pidns-translation.c create mode 100644 tests/netlink_audit--pidns-translation.c create mode 100755 tests/netlink_audit--pidns-translation.test create mode 100644 tests/pidfd_open--pidns-translation.c create mode 100644 tests/pidfd_send_signal--pidns-translation.c create mode 100644 tests/pidns.c create mode 100644 tests/pidns.h create mode 100644 tests/prlimit64--pidns-translation.c create mode 100644 tests/process_vm_readv--pidns-translation.c create mode 100644 tests/process_vm_writev--pidns-translation.c create mode 100644 tests/rt_sigqueueinfo--pidns-translation.c create mode 100644 tests/rt_tgsigqueueinfo--pidns-translation.c create mode 100644 tests/sched_xetaffinity--pidns-translation.c create mode 100644 tests/sched_xetattr--pidns-translation.c create mode 100644 tests/sched_xetparam--pidns-translation.c create mode 100644 tests/sched_xetscheduler--pidns-translation.c create mode 100644 tests/signal_receive--pidns-translation.c create mode 100644 tests/so_peercred--pidns-translation.c create mode 100644 tests/xet_robust_list--pidns-translation.c create mode 100644 tests/xetpgid--pidns-translation.c create mode 100644 tests/xetpriority--pidns-translation.c create mode 100644 trie.c create mode 100644 trie.h -- 2.27.0 From uzonyi.akos at gmail.com Sat Aug 8 21:14:33 2020 From: uzonyi.akos at gmail.com (=?UTF-8?q?=C3=81kos=20Uzonyi?=) Date: Sat, 8 Aug 2020 23:14:33 +0200 Subject: [PATCH v7 1/5] PID namespace translation support In-Reply-To: <20200808211437.469898-1-uzonyi.akos@gmail.com> References: <20200808211437.469898-1-uzonyi.akos@gmail.com> Message-ID: <20200808211437.469898-2-uzonyi.akos@gmail.com> * defs.h (pidns_translation): New variable. (tcb): Add pid_ns field. (RVAL_MASK): Change value from 013 to 017. (RVAL_TID, RVAL_SID, RVAL_TGID, RVAL_PGID): New definitions. (pid_type): New enum. (pidns_init, translate_pid, get_proc_pid, printpid, printpid_tgid_pgid): New function declarations. * largefile_wrappers.h (fstat_fd): New macro. * pidns.c: New file. * trie.c: New file. * trie.h: New file. * Makefile.am (libstrace_a_SOURCES): Add trie.c, trie.h, pidns.c. * strace.c (pidns_translation): New variable. (init): Add --pidns-translation option. * syscall.c (syscall_exiting_trace): Handle RVAL_* return values. * NEWS: Mention this. * strace.1.in: Add description for new option. Co-Authored-by: Eugene Syromyatnikov --- Makefile.am | 3 + NEWS | 1 + defs.h | 55 +++- largefile_wrappers.h | 2 + pidns.c | 604 +++++++++++++++++++++++++++++++++++++++++++ strace.1.in | 4 + strace.c | 9 + syscall.c | 15 ++ trie.c | 248 ++++++++++++++++++ trie.h | 89 +++++++ 10 files changed, 1029 insertions(+), 1 deletion(-) create mode 100644 pidns.c create mode 100644 trie.c create mode 100644 trie.h diff --git a/Makefile.am b/Makefile.am index f5447811..73c22035 100644 --- a/Makefile.am +++ b/Makefile.am @@ -233,6 +233,7 @@ libstrace_a_SOURCES = \ personality.c \ pidfd_getfd.c \ pidfd_open.c \ + pidns.c \ pkeys.c \ poll.c \ prctl.c \ @@ -344,6 +345,8 @@ libstrace_a_SOURCES = \ time.c \ times.c \ trace_event.h \ + trie.c \ + trie.h \ truncate.c \ ubi.c \ ucopy.c \ diff --git a/NEWS b/NEWS index 10039ceb..2ebe45c1 100644 --- a/NEWS +++ b/NEWS @@ -22,6 +22,7 @@ Noteworthy changes in release 5.8 (2020-08-06) KEYCTL_*, KVM_*, LOOP_*, NDA_*, RTC_*, TCA_*, STATX_*, and *_MAGIC constants. * Updated lists of ioctl commands from Linux 5.8. + * Added --pidns-translation option for PID namespace translation. * Bug fixes * Added statx syscall to %fstat trace class. diff --git a/defs.h b/defs.h index f7ac54f3..ea77f1ff 100644 --- a/defs.h +++ b/defs.h @@ -280,6 +280,13 @@ struct tcb { struct timespec etime; /* Syscall entry time (CLOCK_MONOTONIC) */ struct timespec delay_expiration_time; /* When does the delay end */ + /* + * The ID of the PID namespace of this process + * (inode number of /proc//ns/pid) + * (0: not initialized) + */ + unsigned int pid_ns; + struct mmap_cache_t *mmap_cache; /* @@ -413,7 +420,11 @@ extern const struct xlat whence_codes[]; # define RVAL_HEX 001 /* hex format */ # define RVAL_OCTAL 002 /* octal format */ # define RVAL_FD 010 /* file descriptor */ -# define RVAL_MASK 013 /* mask for these values */ +# define RVAL_TID 011 /* task ID */ +# define RVAL_SID 012 /* session ID */ +# define RVAL_TGID 013 /* thread group ID */ +# define RVAL_PGID 014 /* process group ID */ +# define RVAL_MASK 017 /* mask for these values */ # define RVAL_STR 020 /* Print `auxstr' field after return val */ # define RVAL_NONE 040 /* Print nothing */ @@ -428,6 +439,16 @@ extern const struct xlat whence_codes[]; # define indirect_ipccall(tcp) (tcp_sysent(tcp)->sys_flags & TRACE_INDIRECT_SUBCALL) +enum pid_type { + PT_TID, + PT_TGID, + PT_PGID, + PT_SID, + + PT_COUNT, + PT_NONE = -1 +}; + enum sock_proto { SOCK_PROTO_UNKNOWN, SOCK_PROTO_UNIX, @@ -469,6 +490,7 @@ extern int Tflag_scale; extern int Tflag_width; extern bool iflag; extern bool count_wallclock; +extern unsigned int pidns_translation; /* are we filtering traces based on paths? */ extern struct path_set { const char **paths_selected; @@ -983,6 +1005,28 @@ print_local_array_ex(struct tcb *tcp, extern kernel_ulong_t * fetch_indirect_syscall_args(struct tcb *, kernel_ulong_t addr, unsigned int n_args); +extern void pidns_init(void); + +/** + * Returns the pid of the tracee as present in /proc of the tracer (can be + * different from tcp->pid if /proc and the tracee process are in different PID + * namespaces). + */ +extern int get_proc_pid(struct tcb *); + +/** + * Translates a pid from tracee's namespace to our namepace. + * + * @param tcp The tcb of the tracee + * (NULL: from_id is in strace's namespace. Useful for + * getting the proc PID of from_id) + * @param from_id The id to be translated + * @param type The PID type of from_id + * @param proc_pid_ptr If not NULL, writes the proc PID to this location + */ +extern int translate_pid(struct tcb *, int dest_id, enum pid_type type, + int *proc_pid_ptr); + extern void dumpiov_in_msghdr(struct tcb *, kernel_ulong_t addr, kernel_ulong_t data_size); @@ -1058,6 +1102,15 @@ printfd(struct tcb *tcp, int fd) * of the tracee the descriptor tcp). This is a stub. */ extern void printfd_pid_tracee_ns(struct tcb *tcp, pid_t pid, int fd); + +/** Prints a PID in the tracee's PID namespace */ +extern void printpid(struct tcb *, int pid, enum pid_type type); + +/** + * Prints pid as a TGID if positive, and PGID if negative + * (like the first argument of kill). + */ +extern void printpid_tgid_pgid(struct tcb *, int pid); extern void print_sockaddr(struct tcb *, const void *sa, int len); extern bool print_inet_addr(int af, const void *addr, unsigned int len, const char *var_name); diff --git a/largefile_wrappers.h b/largefile_wrappers.h index 116e7048..9d8f5c92 100644 --- a/largefile_wrappers.h +++ b/largefile_wrappers.h @@ -29,6 +29,7 @@ # else # define fcntl_fd fcntl # endif +# define fstat_fd fstat64 # define strace_stat_t struct stat64 # define stat_file stat64 # define struct_dirent struct dirent64 @@ -39,6 +40,7 @@ # define open_file open # define fopen_stream fopen # define fcntl_fd fcntl +# define fstat_fd fstat # define strace_stat_t struct stat # define stat_file stat # define struct_dirent struct dirent diff --git a/pidns.c b/pidns.c new file mode 100644 index 00000000..2f43838d --- /dev/null +++ b/pidns.c @@ -0,0 +1,604 @@ +/* + * Copyright (c) 2020 ?kos Uzonyi + * All rights reserved. + * + * SPDX-License-Identifier: LGPL-2.1-or-later + */ + +#include "defs.h" + + +#include +#include +#include +#include +#include + +#include + +#include +#include +#include +#include + +#include "largefile_wrappers.h" +#include "trie.h" +#include "nsfs.h" +#include "xmalloc.h" +#include "xstring.h" + +/** + * Key: PID NS ID + * Value: a btree: + * Key: a process PID in NS + * Value: the process's PID as present in /proc + */ +static struct trie *ns_pid_to_proc_pid[PT_COUNT]; + +/** + * Key: Proc PID + * Value: struct proc_data + */ +static struct trie *proc_data_cache; + +static bool ns_get_parent_enotty = false; + +static const char tid_str[] = "NSpid:\t"; +static const char tgid_str[] = "NStgid:\t"; +static const char pgid_str[] = "NSpgid:\t"; +static const char sid_str[] = "NSsid:\t"; + +static const struct { + const char *str; + size_t size; +} id_strs[PT_COUNT] = { + [PT_TID] = { tid_str, sizeof(tid_str) - 1 }, + [PT_TGID] = { tgid_str, sizeof(tgid_str) - 1 }, + [PT_PGID] = { pgid_str, sizeof(pgid_str) - 1 }, + [PT_SID] = { sid_str, sizeof(sid_str) - 1 }, +}; + + +/** + * Limit on PID NS hierarchy depth, imposed since Linux 3.7. NS traversal + * is not possible before Linux 4.9, so we consider this limit pretty universal. + */ +#define MAX_NS_DEPTH 32 + +static const size_t ns_id_size = sizeof(unsigned int); +static const uint8_t ptr_sz_lg = (sizeof(void *) == 8 ? 6 : 5); + +static int pid_max; +static uint8_t pid_max_size, pid_max_size_lg; + +struct proc_data { + int proc_pid; + int ns_count; + unsigned int ns_hierarchy[MAX_NS_DEPTH]; + int id_count[PT_COUNT]; + int id_hierarchy[PT_COUNT][MAX_NS_DEPTH]; +}; + +/** + * Helper function for creating a trie. + * + * For node_key_bits and data_block_key_bits 4 is used (so trie height is 32 / 4 + * = 8, and node sizes are 8 byte * 2^4 = 128 bytes), which seems to be a good + * tradeoff between memory usage and lookup time. It should not be too large, + * since there can be large holes between PIDs, and it would be just a waste of + * memory having large nodes with lot of NULL pointers in them. + */ +static struct trie * +create_trie_4(uint8_t key_size, uint8_t item_size_lg, uint64_t empty_value) +{ + struct trie *t = trie_create(key_size, item_size_lg, 4, 4, empty_value); + if (!t) + error_msg_and_die("creating trie failed"); + + return t; +} + +void +pidns_init(void) +{ + if (proc_data_cache) + return; + + pid_max = INT_MAX; + if (read_int_from_file("/proc/sys/kernel/pid_max", &pid_max) < 0) + debug_func_perror_msg("reading /proc/sys/kernel/pid_max"); + pid_max_size = ilog2_32(pid_max - 1) + 1; + pid_max_size_lg = ilog2_32(pid_max_size - 1) + 1; + + for (int i = 0; i < PT_COUNT; i++) + ns_pid_to_proc_pid[i] = create_trie_4(ns_id_size, ptr_sz_lg, 0); + + proc_data_cache = create_trie_4(pid_max_size, ptr_sz_lg, 0); +} + +static void +put_proc_pid(unsigned int ns, int ns_pid, enum pid_type type, int proc_pid) +{ + struct trie *b = (struct trie *) (uintptr_t) trie_get(ns_pid_to_proc_pid[type], ns); + if (!b) { + b = create_trie_4(pid_max_size, pid_max_size_lg, 0); + trie_set(ns_pid_to_proc_pid[type], ns, (uint64_t) (uintptr_t) b); + } + trie_set(b, ns_pid, proc_pid); +} + +static int +get_cached_proc_pid(unsigned int ns, int ns_pid, enum pid_type type) +{ + struct trie *b = (struct trie *) (uintptr_t) + trie_get(ns_pid_to_proc_pid[type], ns); + if (!b) + return 0; + + return trie_get(b, ns_pid); +} + +/** + * Helper function, converts pid to string, or to "self" for pid == 0. + * Uses static buffer for operation. + */ +static const char * +pid_to_str(pid_t pid) +{ + if (!pid) + return "self"; + + static char buf[sizeof("-2147483648")]; + xsprintf(buf, "%d", pid); + return buf; +} + +/** + * Returns a list of PID NS IDs for the specified PID. + * + * @param proc_pid PID (as present in /proc) to get information for. + * @param ns_buf Pointer to buffer that is able to contain at least + * ns_buf_size items. + * @return Amount of NS in list. 0 indicates error. + */ +static size_t +get_ns_hierarchy(int proc_pid, unsigned int *ns_buf, size_t ns_buf_size) +{ + char path[PATH_MAX + 1]; + xsprintf(path, "/proc/%s/ns/pid", pid_to_str(proc_pid)); + + int fd = open_file(path, O_RDONLY); + if (fd < 0) + return 0; + + size_t n = 0; + while (n < ns_buf_size) { + strace_stat_t st; + if (fstat_fd(fd, &st)) + break; + + ns_buf[n++] = st.st_ino; + if (n >= ns_buf_size) + break; + + if (ns_get_parent_enotty) + break; + + int parent_fd = ioctl(fd, NS_GET_PARENT); + if (parent_fd < 0) { + switch (errno) { + case EPERM: + break; + + case ENOTTY: + ns_get_parent_enotty = true; + error_msg("NS_* ioctl commands are not " + "supported by the kernel"); + break; + + default: + perror_func_msg("ioctl(NS_GET_PARENT)"); + break; + } + + break; + } + + close(fd); + fd = parent_fd; + } + + close(fd); + + return n; +} + +/** + * Get list of IDs present in NS* proc status record. IDs are placed as they are + * stored in /proc (from top to bottom of NS hierarchy). + * + * @param proc_pid PID (as present in /proc) to get information for. + * @param id_buf Pointer to buffer that is able to contain at least + * MAX_NS_DEPTH items. Can be NULL. + * @param type Type of ID requested. + * @return Number of items stored in id_list. 0 indicates error. + */ +static size_t +get_id_list(int proc_pid, int *id_buf, enum pid_type type) +{ + const char *ns_str = id_strs[type].str; + size_t ns_str_size = id_strs[type].size; + + size_t n = 0; + + char status_path[PATH_MAX + 1]; + xsprintf(status_path, "/proc/%s/status", pid_to_str(proc_pid)); + FILE *f = fopen_stream(status_path, "r"); + if (!f) + return 0; + + char *line = NULL; + size_t linesize = 0; + char *p = NULL; + + while (getline(&line, &linesize, f) > 0) { + if (strncmp(line, ns_str, ns_str_size) == 0) { + p = line + ns_str_size; + break; + } + } + + while (p) { + errno = 0; + long id = strtol(p, NULL, 10); + + if (errno || id < 1 || id > INT_MAX) { + perror_func_msg("converting pid (%ld) to int", id); + break; + } + + if (id_buf) + id_buf[n] = (int) id; + + n++; + strsep(&p, "\t"); + } + + free(line); + fclose(f); + + return n; +} + +/** + * Returns whether the /proc filesystem's PID namespace is the same as strace's. + */ +static bool +is_proc_ours(void) +{ + static int cached_val = -1; + + if (cached_val < 0) + cached_val = get_id_list(0, NULL, PT_TID) == 1; + + return cached_val; +} + +/** + * Returns the PID namespace of the tracee + */ +static unsigned int +get_ns(struct tcb *tcp) +{ + if (!tcp->pid_ns) { + int proc_pid = 0; + translate_pid(NULL, tcp->pid, PT_TID, &proc_pid); + + if (proc_pid) + get_ns_hierarchy(proc_pid, &tcp->pid_ns, 1); + } + + return tcp->pid_ns; +} + +/** + * Returns the PID namespace of strace + */ +static unsigned int +get_our_ns(void) +{ + static unsigned int our_ns = 0; + static bool our_ns_initialised = false; + + if (!our_ns_initialised) { + get_ns_hierarchy(0, &our_ns, 1); + our_ns_initialised = true; + } + + return our_ns; +} + +/** + * Returns the cached proc_data struct associated with proc_pid. + * If none found, allocates a new proc_data. + */ +static struct proc_data * +get_or_create_proc_data(int proc_pid) +{ + struct proc_data *pd = (struct proc_data *) (uintptr_t) + trie_get(proc_data_cache, proc_pid); + + if (!pd) { + pd = calloc(1, sizeof(*pd)); + if (!pd) + return NULL; + + pd->proc_pid = proc_pid; + trie_set(proc_data_cache, proc_pid, (uint64_t) (uintptr_t) pd); + } + + return pd; +} + +/** + * Updates the proc_data from /proc + * If the process does not exists, returns false, and frees the proc_data + */ +static bool +update_proc_data(struct proc_data *pd, enum pid_type type) +{ + pd->ns_count = get_ns_hierarchy(pd->proc_pid, + pd->ns_hierarchy, MAX_NS_DEPTH); + if (!pd->ns_count) + goto fail; + + pd->id_count[type] = get_id_list(pd->proc_pid, + pd->id_hierarchy[type], type); + if (!pd->id_count[type]) + goto fail; + + return true; + +fail: + trie_set(proc_data_cache, pd->proc_pid, (uint64_t) (uintptr_t) NULL); + free(pd); + return false; +} + +/** + * Paramters for id translation + */ +struct translate_id_params { + /* The result (output) */ + int result_id; + /* The proc data of the process (output) */ + struct proc_data *pd; + + /* The namespace to be translated from */ + unsigned int from_ns; + /* The id to be translated */ + int from_id; + /* The type of the id */ + enum pid_type type; +}; + +/** + * Translates an id to our namespace, given the proc_pid of the process, + * by reading files in /proc. + * + * @param tip The parameters + * @param proc_pid The proc pid of the process. + * If 0, use the cached values in tip->pd. + */ +static void +translate_id_proc_pid(struct translate_id_params *tip, int proc_pid) +{ + struct proc_data *pd = proc_pid ? + get_or_create_proc_data(proc_pid) : + tip->pd; + + tip->result_id = 0; + tip->pd = NULL; + + if (!pd) + return; + + if (proc_pid && !update_proc_data(pd, tip->type)) + return; + + if (!pd->ns_count || pd->id_count[tip->type] < pd->ns_count) + return; + + int our_ns_id_idx = pd->id_count[tip->type] - pd->ns_count; + + for (int i = 0; i < pd->ns_count; i++) { + if (pd->ns_hierarchy[i] != tip->from_ns) + continue; + + int id_idx = pd->id_count[tip->type] - i - 1; + if (pd->id_hierarchy[tip->type][id_idx] != tip->from_id) + return; + + tip->result_id = pd->id_hierarchy[tip->type][our_ns_id_idx]; + tip->pd = pd; + return; + } +} + +/** + * Translates an id to our namespace, by reading all proc entries in dir. + * + * @param tip The parameters + * @param path The path of the dir to be read. + * @param read_task_dir Whether recurse to "task" subdirectory. + */ +static void +translate_id_dir(struct translate_id_params *tip, const char *path, + bool read_task_dir) +{ + DIR *dir = opendir(path); + if (!dir) { + debug_func_perror_msg("opening dir: %s", path); + return; + } + + while (!tip->result_id) { + errno = 0; + struct_dirent *entry = read_dir(dir); + if (!entry) { + if (errno) + perror_func_msg("readdir"); + + break; + } + + if (entry->d_type != DT_DIR) + continue; + + errno = 0; + long proc_pid = strtol(entry->d_name, NULL, 10); + if (errno) + continue; + if (proc_pid < 1 || proc_pid > INT_MAX) + continue; + + if (read_task_dir) { + char task_dir_path[PATH_MAX + 1]; + xsprintf(task_dir_path, "/proc/%ld/task", proc_pid); + translate_id_dir(tip, task_dir_path, false); + } + + if (tip->result_id) + break; + + translate_id_proc_pid(tip, proc_pid); + } + + closedir(dir); +} + +/** + * Iterator function of the proc_data_cache for id translation. + * If the cache contains the id we are looking for, reads the corresponding + * directory in /proc, and if cache is valid, saves the result. + */ +static void +proc_data_cache_iterator_fn(void* fn_data, uint64_t key, uint64_t val) +{ + struct translate_id_params *tip = (struct translate_id_params *)fn_data; + struct proc_data *pd = (struct proc_data *) (uintptr_t) val; + + if (!pd) + return; + + /* Result already found in an earlier iteration */ + if (tip->result_id) + return; + + /* Translate from cache */ + tip->pd = pd; + translate_id_proc_pid(tip, 0); + if (!tip->result_id) + return; + + /* Now translate from actual data in /proc, to check cache validity */ + translate_id_proc_pid(tip, pd->proc_pid); +} + +int +translate_pid(struct tcb *tcp, int from_id, enum pid_type type, + int *proc_pid_ptr) +{ + if (from_id <= 0 || type < 0 || type >= PT_COUNT) + return 0; + + /* If translation is trivial */ + if ((!tcp || get_ns(tcp) == get_our_ns()) && + (is_proc_ours() || !proc_pid_ptr)) { + if (proc_pid_ptr) + *proc_pid_ptr = from_id; + + return from_id; + } + + struct translate_id_params tip = { + .result_id = 0, + .pd = NULL, + .from_ns = tcp ? get_ns(tcp) : get_our_ns(), + .from_id = from_id, + .type = type, + }; + + if (!tip.from_ns) + return 0; + + if (ns_get_parent_enotty) + return 0; + + /* Look for a cached proc_pid for this (from_ns, from_id) pair */ + int cached_proc_pid = get_cached_proc_pid(tip.from_ns, tip.from_id, + tip.type); + if (cached_proc_pid) { + translate_id_proc_pid(&tip, cached_proc_pid); + if (tip.result_id) + goto exit; + } + + /* Iterate through the cache, find potential proc_data */ + trie_iterate_keys(proc_data_cache, 0, pid_max, + proc_data_cache_iterator_fn, &tip); + /* (proc_data_cache_iterator_fn takes care about updating proc_data) */ + if (tip.result_id) + goto exit; + + /* No cache helped, read all entries in /proc */ + translate_id_dir(&tip, "/proc", true); + +exit: + if (tip.pd) { + if (tip.pd->proc_pid) + put_proc_pid(tip.from_ns, tip.from_id, tip.type, + tip.pd->proc_pid); + + if (proc_pid_ptr) + *proc_pid_ptr = tip.pd->proc_pid; + } + + return tip.result_id; +} + +int +get_proc_pid(struct tcb *tcp) +{ + int proc_pid = 0; + translate_pid(NULL, tcp->pid, PT_TID, &proc_pid); + return proc_pid; +} + +static void +printpid_translation(struct tcb *tcp, int pid, enum pid_type type) +{ + if (!pidns_translation) + return; + + int strace_pid = translate_pid(tcp, pid, type, NULL); + if (strace_pid && strace_pid != pid) + tprintf_comment("%d in strace's PID NS", strace_pid); +} + +void +printpid(struct tcb *tcp, int pid, enum pid_type type) +{ + tprintf("%d", pid); + printpid_translation(tcp, pid, type); +} + +void +printpid_tgid_pgid(struct tcb *tcp, int pid) +{ + tprintf("%d", pid); + if (pid > 0) + printpid_translation(tcp, pid, PT_TGID); + else if (pid < -1) + printpid_translation(tcp, -pid, PT_PGID); +} diff --git a/strace.1.in b/strace.1.in index 3b21caec..83776e88 100644 --- a/strace.1.in +++ b/strace.1.in @@ -1075,6 +1075,10 @@ Print all available information associated with file descritors: protocol-specific information associated with socket file descriptors, block/character device number associated with device file descriptors, and PIDs asociated with pidfd file descriptors. +.TP +.B \-\-pidns\-translation +If strace and tracee are in different PID namespaces, print PIDs in +strace's namespace, too. .SS Statistics .TP 12 .B \-c diff --git a/strace.c b/strace.c index 4c96a98b..249533ea 100644 --- a/strace.c +++ b/strace.c @@ -133,6 +133,8 @@ static unsigned int daemonized_tracer; static int post_attach_sigstop = TCB_IGNORE_ONE_SIGSTOP; #define use_seize (post_attach_sigstop == 0) +unsigned int pidns_translation; + static bool detach_on_execve; static int exit_code; @@ -1998,6 +2000,8 @@ init(int argc, char *argv[]) os_release = get_os_release(); + pidns_init(); + shared_log = stderr; set_sortby(DEFAULT_SORTBY); set_personality(DEFAULT_PERSONALITY); @@ -2022,6 +2026,7 @@ init(int argc, char *argv[]) GETOPT_FOLLOWFORKS, GETOPT_OUTPUT_SEPARATELY, GETOPT_TS, + GETOPT_PIDNS_TRANSLATION, GETOPT_QUAL_TRACE, GETOPT_QUAL_ABBREV, @@ -2072,6 +2077,7 @@ init(int argc, char *argv[]) { "summary-wall-clock", no_argument, 0, 'w' }, { "strings-in-hex", optional_argument, 0, GETOPT_HEX_STR }, { "const-print-style", required_argument, 0, 'X' }, + { "pidns-translation", no_argument , 0, GETOPT_PIDNS_TRANSLATION }, { "successful-only", no_argument, 0, 'z' }, { "failed-only", no_argument, 0, 'Z' }, { "failing-only", no_argument, 0, 'Z' }, @@ -2285,6 +2291,9 @@ init(int argc, char *argv[]) case 'y': yflag_short++; break; + case GETOPT_PIDNS_TRANSLATION: + pidns_translation++; + break; case 'z': clear_number_set_array(status_set, 1); add_number_to_set(STATUS_SUCCESSFUL, status_set); diff --git a/syscall.c b/syscall.c index bcc87025..0f4bab6d 100644 --- a/syscall.c +++ b/syscall.c @@ -937,6 +937,21 @@ syscall_exiting_trace(struct tcb *tcp, struct timespec *ts, int res) tprintf("= %" PRI_kld, tcp->u_rval); } break; + case RVAL_TID: + case RVAL_SID: + case RVAL_TGID: + case RVAL_PGID: { + #define _(_t) [RVAL_##_t - RVAL_TID] = PT_##_t + static const enum pid_type types[] = { + _(TID), _(SID), _(TGID), _(PGID), + }; + #undef _ + + tprints("= "); + printpid(tcp, tcp->u_rval, + types[(sys_res & RVAL_MASK) - RVAL_TID]); + break; + } default: error_msg("invalid rval format"); break; diff --git a/trie.c b/trie.c new file mode 100644 index 00000000..b7d56ed5 --- /dev/null +++ b/trie.c @@ -0,0 +1,248 @@ +/* + * Simple trie implementation for key-value mapping storage + * + * Copyright (c) 2020 ?kos Uzonyi + * All rights reserved. + * + * SPDX-License-Identifier: LGPL-2.1-or-later + */ + +#include "defs.h" + +#include +#include +#include + +#include "trie.h" + +static const uint8_t ptr_sz_lg = (sizeof(void *) == 8 ? 6 : 5); + +/** + * Returns lg2 of node size in bits for the specific level of the trie. + */ +static uint8_t +trie_get_node_size(struct trie *t, uint8_t depth) +{ + /* Last level contains data and we allow it having a different size */ + if (depth == t->max_depth) + return t->data_block_key_bits + t->item_size_lg; + /* Last level of the tree can be smaller */ + if (depth == t->max_depth - 1) + return (t->key_size - t->data_block_key_bits - 1) % + t->node_key_bits + 1 + ptr_sz_lg; + + return t->node_key_bits + ptr_sz_lg; +} + +/** + * Provides starting offset of bits in key corresponding to the node index + * at the specific level. + */ +static uint8_t +trie_get_node_bit_offs(struct trie *t, uint8_t depth) +{ + uint8_t offs; + + if (depth == t->max_depth) + return 0; + + offs = t->data_block_key_bits; + + if (depth == t->max_depth - 1) + return offs; + + /* data_block_size + remainder */ + offs += trie_get_node_size(t, t->max_depth - 1) - ptr_sz_lg; + offs += (t->max_depth - depth - 2) * t->node_key_bits; + + return offs; +} + +struct trie * +trie_create(uint8_t key_size, uint8_t item_size_lg, uint8_t node_key_bits, + uint8_t data_block_key_bits, uint64_t empty_value) +{ + if (item_size_lg > 6) + return NULL; + if (key_size > 64) + return NULL; + if (node_key_bits < 1) + return NULL; + if (data_block_key_bits < 1 || data_block_key_bits > key_size) + return NULL; + + struct trie *t = malloc(sizeof(*t)); + if (!t) + return NULL; + + t->empty_value = empty_value; + t->data = NULL; + t->item_size_lg = item_size_lg; + t->node_key_bits = node_key_bits; + t->data_block_key_bits = data_block_key_bits; + t->key_size = key_size; + t->max_depth = (key_size - data_block_key_bits + node_key_bits - 1) + / t->node_key_bits; + + return t; +} + +static uint64_t * +trie_get_node(struct trie *t, uint64_t key, bool auto_create) +{ + void **cur_node = &(t->data); + + if (t->key_size < 64 && key > (uint64_t) 1 << t->key_size) + return NULL; + + for (uint8_t cur_depth = 0; cur_depth <= t->max_depth; cur_depth++) { + uint8_t offs = trie_get_node_bit_offs(t, cur_depth); + uint8_t sz = trie_get_node_size(t, cur_depth); + + if (!*cur_node) { + if (!auto_create) + return NULL; + + *cur_node = xcalloc(1 << sz, 1); + } + + if (cur_depth >= t->max_depth) + break; + + size_t pos = (key >> offs) & ((1 << (sz - ptr_sz_lg)) - 1); + cur_node = (((void **) (*cur_node)) + pos); + } + + return (uint64_t *) (*cur_node); +} + +static void +trie_data_block_calc_pos(struct trie *t, uint64_t key, + uint64_t *pos, uint64_t *mask, uint64_t *offs) +{ + uint64_t key_mask; + + key_mask = (1 << t->data_block_key_bits) - 1; + *pos = (key & key_mask) >> (6 - t->item_size_lg); + + key_mask = (1 << (6 - t->item_size_lg)) - 1; + *offs = (key & key_mask) * (1 << t->item_size_lg); + + *mask = (((uint64_t) 1 << (1 << t->item_size_lg)) - 1) << *offs; +} + +bool +trie_set(struct trie *t, uint64_t key, uint64_t val) +{ + uint64_t *data = trie_get_node(t, key, true); + if (!data) + return false; + + uint64_t pos, mask, offs; + trie_data_block_calc_pos(t, key, &pos, &mask, &offs); + + data[pos] &= ~mask; + data[pos] |= (val << offs) & mask; + + return true; +} + +static uint64_t +trie_data_block_get(struct trie *t, uint64_t *data, uint64_t key) +{ + if (!data) + return t->empty_value; + + uint64_t pos, mask, offs; + trie_data_block_calc_pos(t, key, &pos, &mask, &offs); + + return (data[pos] & mask) >> offs; +} + +uint64_t +trie_get(struct trie *b, uint64_t key) +{ + return trie_data_block_get(b, trie_get_node(b, key, false), key); +} + +static uint64_t +trie_iterate_keys_node(struct trie *t, + trie_iterate_fn fn, void *fn_data, + void *node, uint64_t start, uint64_t end, + uint8_t depth) +{ + if (start > end || !node) + return 0; + + if (depth == t->max_depth) { + for (uint64_t i = start; i <= end; i++) + fn(fn_data, i, trie_data_block_get(t, + (uint64_t *) node, i)); + + return end - start + 1; + } + + uint8_t parent_node_bit_off = depth == 0 ? + t->key_size : + trie_get_node_bit_offs(t, depth - 1); + + uint64_t first_key_in_node = start & + (uint64_t) -1 << parent_node_bit_off; + + uint8_t node_bit_off = trie_get_node_bit_offs(t, depth); + uint8_t node_key_bits = parent_node_bit_off - node_bit_off; + uint64_t mask = ((uint64_t) 1 << (node_key_bits)) - 1; + uint64_t start_index = (start >> node_bit_off) & mask; + uint64_t end_index = (end >> node_bit_off) & mask; + uint64_t child_key_count = (uint64_t) 1 << node_bit_off; + + uint64_t count = 0; + + for (uint64_t i = start_index; i <= end_index; i++) { + uint64_t child_start = first_key_in_node + i * child_key_count; + uint64_t child_end = first_key_in_node + + (i + 1) * child_key_count - 1; + + if (child_start < start) + child_start = start; + if (child_end > end) + child_end = end; + + count += trie_iterate_keys_node(t, fn, fn_data, + ((void **) node)[i], child_start, child_end, + depth + 1); + } + + return count; +} + +uint64_t trie_iterate_keys(struct trie *t, uint64_t start, uint64_t end, + trie_iterate_fn fn, void *fn_data) +{ + return trie_iterate_keys_node(t, fn, fn_data, t->data, + start, end, 0); +} + +static void +trie_free_node(struct trie *t, void *node, uint8_t depth) +{ + if (!node) + return; + + if (depth >= t->max_depth) + goto free_node; + + size_t sz = 1 << (trie_get_node_size(t, depth) - ptr_sz_lg); + for (size_t i = 0; i < sz; i++) + trie_free_node(t, ((void **) node)[i], depth + 1); + +free_node: + free(node); +} + +void +trie_free(struct trie *t) +{ + trie_free_node(t, t->data, 0); + free(t); +} diff --git a/trie.h b/trie.h new file mode 100644 index 00000000..1ff31397 --- /dev/null +++ b/trie.h @@ -0,0 +1,89 @@ +/* + * Simple trie interface + * + * Copyright (c) 2020 ?kos Uzonyi + * All rights reserved. + * + * SPDX-License-Identifier: LGPL-2.1-or-later + */ + +#ifndef STRACE_TRIE_H +#define STRACE_TRIE_H + +/** + * Trie control structure. + * Trie implemented here has the following properties: + * * It allows storing values of the same size, the size can vary from 1 bit to + * 64 bit values (only power of 2 sizes are allowed). + * * The key can be up to 64 bits in size. + * * It has separate configuration for node size and data block size. + * + * How bits of key are used for different node levels: + * + * highest bits lowest bits + * | node_key_bits | node_key_bits | ... | | data_block_key_bits | + * \_________________________________________________________________________/ + * key_size + * + * So, the remainder is used on the lowest non-data node level. + * + * As of now, it doesn't implement any mechanisms for resizing/changing key + * size. De-fragmentation is also unsupported currently. + */ +struct trie { + /** Return value of trie_get if key is not found */ + uint64_t empty_value; + + /** Pointer to root node */ + void *data; + + /** Key size in bits (0..64). */ + uint8_t key_size; + + /** + * Size of the stored values in log2 bits (0..6). + * (6: 64 bit values, 5: 32 bit values, ...) + */ + uint8_t item_size_lg; + + /** + * Number of bits in the key that make a symbol for a node. + * (equals to log2 of the child count of the node) + */ + uint8_t node_key_bits; + + /** + * Number of bits in the key that make a symbol for the data block (leaf). + * (equals to log2 of the value count stored in a data block) + */ + uint8_t data_block_key_bits; + + /** The depth of the data block. Calculated from the values above */ + uint8_t max_depth; +}; + +struct trie* trie_create(uint8_t key_size, uint8_t item_size_lg, + uint8_t node_key_bits, uint8_t data_block_key_bits, + uint64_t empty_value); + +bool trie_set(struct trie *t, uint64_t key, uint64_t val); +uint64_t trie_get(struct trie *t, uint64_t key); + +typedef void (*trie_iterate_fn)(void *data, uint64_t key, uint64_t val); + +/** + * Calls trie_iterate_fn for each key-value pair where + * key is inside the [start, end] interval (inclusive). + * + * @param t The trie. + * @param start The start of the key interval (inclusive). + * @param end The end of the key interval (inclusive). + * @param fn The function to be called. + * @param fn_data The value to be passed to fn. + */ +uint64_t trie_iterate_keys(struct trie *t, uint64_t start, uint64_t end, + trie_iterate_fn fn, void *fn_data); + +void trie_free(struct trie *t); + +#endif /* !STRACE_TRIE_H */ -- 2.27.0 From uzonyi.akos at gmail.com Sat Aug 8 21:14:34 2020 From: uzonyi.akos at gmail.com (=?UTF-8?q?=C3=81kos=20Uzonyi?=) Date: Sat, 8 Aug 2020 23:14:34 +0200 Subject: [PATCH v7 2/5] Use printpid in decoders In-Reply-To: <20200808211437.469898-1-uzonyi.akos@gmail.com> References: <20200808211437.469898-1-uzonyi.akos@gmail.com> Message-ID: <20200808211437.469898-3-uzonyi.akos@gmail.com> * getpid.c: New file. * Makefile.am (libstrace_a_SOURCES): Add it. * linux/dummy.h (sys_getpid, sys_getppid, sys_gettid, sys_setpgid, sys_setpgrp): Remove. * util.c (printfd_pid_tracee_ns): Implement using translate_pid. * defs.h (printnum_pid): New function definition. (printfd_pid_tracee_ns): Update documentation * util.c: (printnum_pid): New function. * print_fields.h (PRINT_FIELD_TID): New macro. (PRINT_FIELD_TGID): Likewise. (PRINT_FIELD_PGID): Likewise. (PRINT_FIELD_SID): Likewise. * affinity.c: Print PIDs with printpid. * block.c: Likewise. * bpf.c: Likewise. * capability.c: Likewise. * clone.c: Likewise. * fcntl.c: Likewise. * get_robust_list.c: Likewise. * ioprio.c: Likewise. * kcmp.c: Likewise. * msghdr.c: Likewise. * net.c: Likewise. * netlink.c: Likewise. * numa.c: Likewise. * pidfd_open.c: Likewise. * printsiginfo.c: Likewise. * process.c: Likewise. * process_vm.c: Likewise. * resource.c: Likewise. * sched.c: Likewise. * signal.c: Likewise. * sockaddr.c: Likewise. * wait.c: Likewise. * kcmp.c (SYS_FUNC(kcmp)): Fix KCMP_FILE pid arguments. * tests/kcmp.c (printpidfd): Print path if VERBOSE_FD. (main): Use our real pid if real fds are used. --- Makefile.am | 1 + affinity.c | 6 ++++-- block.c | 2 +- bpf.c | 2 +- capability.c | 4 +++- clone.c | 14 +++++++------- defs.h | 5 ++++- fcntl.c | 24 ++++++++++++++++++++++-- get_robust_list.c | 3 ++- getpid.c | 46 ++++++++++++++++++++++++++++++++++++++++++++++ ioprio.c | 26 ++++++++++++++++++++++---- ipc_shmctl.c | 4 ++-- kcmp.c | 5 ++++- linux/dummy.h | 8 +------- msghdr.c | 2 +- net.c | 2 +- netlink.c | 5 +++-- numa.c | 6 ++++-- pidfd_open.c | 2 +- print_fields.h | 24 ++++++++++++++++++++++++ printsiginfo.c | 2 +- process.c | 3 ++- process_vm.c | 6 ++++-- resource.c | 27 ++++++++++++++++++++++++--- sched.c | 25 ++++++++++++++++--------- signal.c | 21 +++++++++++++++------ sockaddr.c | 2 +- tests/kcmp.c | 25 ++++++++++++++++++++++--- util.c | 20 ++++++++++++++------ wait.c | 36 ++++++++++++++++++++++++------------ 30 files changed, 277 insertions(+), 81 deletions(-) create mode 100644 getpid.c diff --git a/Makefile.am b/Makefile.am index 73c22035..15fcd9a6 100644 --- a/Makefile.am +++ b/Makefile.am @@ -135,6 +135,7 @@ libstrace_a_SOURCES = \ getcpu.c \ getcwd.c \ getpagesize.c \ + getpid.c \ getrandom.c \ hdio.c \ hostname.c \ diff --git a/affinity.c b/affinity.c index eb3158b7..f9893adb 100644 --- a/affinity.c +++ b/affinity.c @@ -82,7 +82,8 @@ SYS_FUNC(sched_setaffinity) const int pid = tcp->u_arg[0]; const unsigned int len = tcp->u_arg[1]; - tprintf("%d, %u, ", pid, len); + printpid(tcp, pid, PT_TGID); + tprintf(", %u, ", len); print_affinitylist(tcp, tcp->u_arg[2], len); return RVAL_DECODED; @@ -94,7 +95,8 @@ SYS_FUNC(sched_getaffinity) const unsigned int len = tcp->u_arg[1]; if (entering(tcp)) { - tprintf("%d, %u, ", pid, len); + printpid(tcp, pid, PT_TGID); + tprintf(", %u, ", len); } else { print_affinitylist(tcp, tcp->u_arg[2], tcp->u_rval); } diff --git a/block.c b/block.c index b527ef43..783a4b5a 100644 --- a/block.c +++ b/block.c @@ -179,7 +179,7 @@ MPERS_PRINTER_DECL(int, block_ioctl, struct tcb *const tcp, PRINT_FIELD_U(", ", buts, buf_nr); PRINT_FIELD_U(", ", buts, start_lba); PRINT_FIELD_U(", ", buts, end_lba); - PRINT_FIELD_D(", ", buts, pid); + PRINT_FIELD_TGID(", ", buts, pid, tcp); return 0; } else { struct_blk_user_trace_setup buts; diff --git a/bpf.c b/bpf.c index af830053..0ec33ba4 100644 --- a/bpf.c +++ b/bpf.c @@ -927,7 +927,7 @@ BEGIN_BPF_CMD_DECODER(BPF_TASK_FD_QUERY) if (entering(tcp)) { set_tcb_priv_ulong(tcp, attr.buf_len); - PRINT_FIELD_D("{task_fd_query={", attr, pid); + PRINT_FIELD_TGID("{task_fd_query={", attr, pid, tcp); PRINT_FIELD_FD(", ", attr, fd, tcp); PRINT_FIELD_U(", ", attr, flags); PRINT_FIELD_U(", ", attr, buf_len); diff --git a/capability.c b/capability.c index 0e763ee1..812fb435 100644 --- a/capability.c +++ b/capability.c @@ -70,7 +70,9 @@ print_cap_header(struct tcb *const tcp, const kernel_ulong_t addr, tprints("{version="); printxval(cap_version, h->version, "_LINUX_CAPABILITY_VERSION_???"); - tprintf(", pid=%d}", h->pid); + tprints(", pid="); + printpid(tcp, h->pid, PT_TGID); + tprints("}"); } static void diff --git a/clone.c b/clone.c index 487c5c23..45f24065 100644 --- a/clone.c +++ b/clone.c @@ -114,14 +114,14 @@ SYS_FUNC(clone) */ if ((flags & (CLONE_PARENT_SETTID|CLONE_PIDFD|CLONE_CHILD_SETTID |CLONE_CHILD_CLEARTID|CLONE_SETTLS)) == 0) - return RVAL_DECODED; + return RVAL_DECODED | RVAL_TID; } else { if (flags & (CLONE_PARENT_SETTID|CLONE_PIDFD)) { kernel_ulong_t addr = tcp->u_arg[ARG_PTID]; tprints(", parent_tid="); if (flags & CLONE_PARENT_SETTID) - printnum_int(tcp, addr, "%u"); + printnum_pid(tcp, addr, PT_TID); else printnum_fd(tcp, addr); } @@ -134,7 +134,7 @@ SYS_FUNC(clone) printaddr(tcp->u_arg[ARG_CTID]); } } - return 0; + return RVAL_TID; } @@ -229,7 +229,7 @@ SYS_FUNC(clone3) if ((arg.flags & (CLONE_PIDFD | CLONE_PARENT_SETTID)) || (size > fetch_size)) - return 0; + return RVAL_TID; goto out; } @@ -256,7 +256,7 @@ SYS_FUNC(clone3) if (arg.flags & CLONE_PARENT_SETTID) { tprintf("%sparent_tid=", pfx); - printnum_int(tcp, arg.parent_tid, "%d"); /* TID */ + printnum_pid(tcp, arg.parent_tid, PT_TID); pfx = ", "; } @@ -279,7 +279,7 @@ SYS_FUNC(clone3) out: tprintf(", %" PRI_klu, size); - return RVAL_DECODED; + return RVAL_DECODED | RVAL_TID; } @@ -300,5 +300,5 @@ SYS_FUNC(unshare) SYS_FUNC(fork) { - return RVAL_DECODED; + return RVAL_DECODED | RVAL_TGID; } diff --git a/defs.h b/defs.h index ea77f1ff..f7a0a01d 100644 --- a/defs.h +++ b/defs.h @@ -1099,7 +1099,7 @@ printfd(struct tcb *tcp, int fd) /** * Print file descriptor fd owned by process with ID pid (from the PID NS - * of the tracee the descriptor tcp). This is a stub. + * of the tracee). */ extern void printfd_pid_tracee_ns(struct tcb *tcp, pid_t pid, int fd); @@ -1560,6 +1560,9 @@ DECL_PRINTNUM_ADDR(int64); extern bool printnum_fd(struct tcb *, kernel_ulong_t addr); +extern bool +printnum_pid(struct tcb *const tcp, const kernel_ulong_t addr, enum pid_type type); + static inline bool printnum_slong(struct tcb *tcp, kernel_ulong_t addr) { diff --git a/fcntl.c b/fcntl.c index 6fcd5dac..5c630a06 100644 --- a/fcntl.c +++ b/fcntl.c @@ -28,7 +28,7 @@ print_struct_flock64(struct tcb *const tcp, const struct_kernel_flock64 *fl, con PRINT_FIELD_D(", ", *fl, l_start); PRINT_FIELD_D(", ", *fl, l_len); if (getlk) - PRINT_FIELD_D(", ", *fl, l_pid); + PRINT_FIELD_TGID(", ", *fl, l_pid, tcp); tprints("}"); } @@ -59,7 +59,22 @@ print_f_owner_ex(struct tcb *const tcp, const kernel_ulong_t addr) return; PRINT_FIELD_XVAL("{", owner, type, f_owner_types, "F_OWNER_???"); - PRINT_FIELD_D(", ", owner, pid); + + enum pid_type pid_type = PT_NONE; + switch (owner.type) + { + case F_OWNER_TID: + pid_type = PT_TID; + break; + case F_OWNER_PID: + pid_type = PT_TGID; + break; + case F_OWNER_PGRP: + pid_type = PT_PGID; + break; + } + tprints(", pid="); + printpid(tcp, owner.pid, pid_type); tprints("}"); } @@ -74,6 +89,9 @@ print_fcntl(struct tcb *tcp) printflags(fdflags, tcp->u_arg[2], "FD_???"); break; case F_SETOWN: + tprints(", "); + printpid_tgid_pgid(tcp, tcp->u_arg[2]); + break; case F_SETPIPE_SZ: tprintf(", %" PRI_kld, tcp->u_arg[2]); break; @@ -116,6 +134,8 @@ print_fcntl(struct tcb *tcp) printsignal(tcp->u_arg[2]); break; case F_GETOWN: + return RVAL_DECODED | + ((int) tcp->u_rval < 0 ? RVAL_PGID : RVAL_TGID); case F_GETPIPE_SZ: break; case F_GETFD: diff --git a/get_robust_list.c b/get_robust_list.c index b5aebaff..81aba2dd 100644 --- a/get_robust_list.c +++ b/get_robust_list.c @@ -10,7 +10,8 @@ SYS_FUNC(get_robust_list) { if (entering(tcp)) { - tprintf("%d, ", (int) tcp->u_arg[0]); + printpid(tcp, tcp->u_arg[0], PT_TID); + tprints(", "); } else { printnum_ptr(tcp, tcp->u_arg[1]); tprints(", "); diff --git a/getpid.c b/getpid.c new file mode 100644 index 00000000..5e9a1a29 --- /dev/null +++ b/getpid.c @@ -0,0 +1,46 @@ +/* + * Copyright (c) 2020 ?kos Uzonyi + * All rights reserved. + * + * SPDX-License-Identifier: LGPL-2.1-or-later + */ + +#include "defs.h" + +SYS_FUNC(getpid) +{ + return RVAL_DECODED | RVAL_TGID; +} + +SYS_FUNC(gettid) +{ + return RVAL_DECODED | RVAL_TID; +} + +SYS_FUNC(getpgrp) +{ + return RVAL_DECODED | RVAL_PGID; +} + +SYS_FUNC(getpgid) +{ + printpid(tcp, tcp->u_arg[0], PT_TGID); + + return RVAL_DECODED | RVAL_PGID; +} + +SYS_FUNC(getsid) +{ + printpid(tcp, tcp->u_arg[0], PT_TGID); + + return RVAL_DECODED | RVAL_SID; +} + +SYS_FUNC(setpgid) +{ + printpid(tcp, tcp->u_arg[0], PT_TGID); + tprints(", "); + printpid(tcp, tcp->u_arg[1], PT_PGID); + + return RVAL_DECODED; +} diff --git a/ioprio.c b/ioprio.c index 873c8ce5..149ef3fd 100644 --- a/ioprio.c +++ b/ioprio.c @@ -49,13 +49,30 @@ print_ioprio(unsigned int ioprio) ? tprints_comment : tprints)(str); } +static void +ioprio_print_who(struct tcb *tcp, int which, int who) +{ + switch (which) + { + case IOPRIO_WHO_PROCESS: + printpid(tcp, who, PT_TGID); + break; + case IOPRIO_WHO_PGRP: + printpid(tcp, who, PT_PGID); + break; + default: + tprintf("%d", who); + break; + } +} + SYS_FUNC(ioprio_get) { if (entering(tcp)) { /* int which */ printxval(ioprio_who, tcp->u_arg[0], "IOPRIO_WHO_???"); - /* int who */ - tprintf(", %d", (int) tcp->u_arg[1]); + tprints(", "); + ioprio_print_who(tcp, tcp->u_arg[0], tcp->u_arg[1]); return 0; } else { if (syserror(tcp)) @@ -72,8 +89,9 @@ SYS_FUNC(ioprio_set) { /* int which */ printxval(ioprio_who, tcp->u_arg[0], "IOPRIO_WHO_???"); - /* int who */ - tprintf(", %d, ", (int) tcp->u_arg[1]); + tprints(", "); + ioprio_print_who(tcp, tcp->u_arg[0], tcp->u_arg[1]); + tprints(", "); /* int ioprio */ if (xlat_verbose(xlat_verbosity) != XLAT_STYLE_ABBREV) tprintf("%d", (int) tcp->u_arg[2]); diff --git a/ipc_shmctl.c b/ipc_shmctl.c index 8c9e1e7a..1f99f02a 100644 --- a/ipc_shmctl.c +++ b/ipc_shmctl.c @@ -53,8 +53,8 @@ print_shmid_ds(struct tcb *const tcp, const kernel_ulong_t addr, int cmd) PRINT_FIELD_UID(", ", shmid_ds.shm_perm, cgid); tprints("}"); tprintf(", shm_segsz=%u", (unsigned) shmid_ds.shm_segsz); - PRINT_FIELD_D(", ", shmid_ds, shm_cpid); - PRINT_FIELD_D(", ", shmid_ds, shm_lpid); + PRINT_FIELD_TGID(", ", shmid_ds, shm_cpid, tcp); + PRINT_FIELD_TGID(", ", shmid_ds, shm_lpid, tcp); tprintf(", shm_nattch=%u", (unsigned) shmid_ds.shm_nattch); tprintf(", shm_atime=%u", (unsigned) shmid_ds.shm_atime); tprintf(", shm_dtime=%u", (unsigned) shmid_ds.shm_dtime); diff --git a/kcmp.c b/kcmp.c index 62115555..a5e1cdce 100644 --- a/kcmp.c +++ b/kcmp.c @@ -30,7 +30,10 @@ SYS_FUNC(kcmp) kernel_ulong_t idx1 = tcp->u_arg[3]; kernel_ulong_t idx2 = tcp->u_arg[4]; - tprintf("%d, %d, ", pid1, pid2); + printpid(tcp, pid1, PT_TGID); + tprints(", "); + printpid(tcp, pid2, PT_TGID); + tprints(", "); printxval(kcmp_types, type, "KCMP_???"); switch (type) { diff --git a/linux/dummy.h b/linux/dummy.h index 2f859a60..ca0d2f0c 100644 --- a/linux/dummy.h +++ b/linux/dummy.h @@ -53,6 +53,7 @@ # define sys_getgid sys_getuid # define sys_getgid16 sys_getuid16 # define sys_getpeername sys_getsockname +# define sys_getppid sys_getpid # define sys_getresgid sys_getresuid # define sys_getresgid16 sys_getresuid16 # define sys_lstat sys_stat @@ -87,10 +88,6 @@ # define sys_vfork sys_fork /* printargs does the right thing */ -# define sys_getpgrp printargs -# define sys_getpid printargs -# define sys_getppid printargs -# define sys_gettid printargs # define sys_idle printargs # define sys_munlockall printargs # define sys_pause printargs @@ -108,10 +105,7 @@ /* printargs_d does the right thing */ # define sys_exit printargs_d -# define sys_getpgid printargs_d -# define sys_getsid printargs_d # define sys_nice printargs_d -# define sys_setpgid printargs_d # define sys_setpgrp printargs_d # define sys_timer_delete printargs_d # define sys_timer_getoverrun printargs_d diff --git a/msghdr.c b/msghdr.c index ef6dc24b..170b8e51 100644 --- a/msghdr.c +++ b/msghdr.c @@ -69,7 +69,7 @@ print_scm_creds(struct tcb *tcp, const void *cmsg_data, { const struct ucred *uc = cmsg_data; - PRINT_FIELD_D("{", *uc, pid); + PRINT_FIELD_TGID("{", *uc, pid, tcp); PRINT_FIELD_UID(", ", *uc, uid); PRINT_FIELD_UID(", ", *uc, gid); tprints("}"); diff --git a/net.c b/net.c index fa4638e7..2099f0ac 100644 --- a/net.c +++ b/net.c @@ -601,7 +601,7 @@ print_get_ucred(struct tcb *const tcp, const kernel_ulong_t addr, if (umoven_or_printaddr(tcp, addr, len, &uc)) return; - PRINT_FIELD_LEN("{", uc, pid, len, PRINT_FIELD_D); + PRINT_FIELD_LEN("{", uc, pid, len, PRINT_FIELD_TGID, tcp); PRINT_FIELD_LEN(", ", uc, uid, len, PRINT_FIELD_UID); PRINT_FIELD_LEN(", ", uc, gid, len, PRINT_FIELD_UID); tprints("}"); diff --git a/netlink.c b/netlink.c index 88d864a9..cb29033a 100644 --- a/netlink.c +++ b/netlink.c @@ -446,8 +446,9 @@ print_nlmsghdr(struct tcb *tcp, decode_nlmsg_flags(nlmsghdr->nlmsg_flags, nlmsghdr->nlmsg_type, family); - tprintf(", seq=%u, pid=%d}", nlmsghdr->nlmsg_seq, - nlmsghdr->nlmsg_pid); + tprintf(", seq=%u, pid=", nlmsghdr->nlmsg_seq); + printpid(tcp, nlmsghdr->nlmsg_pid, PT_TGID); + tprints("}"); } static bool diff --git a/numa.c b/numa.c index cc7a7cc6..f7a58266 100644 --- a/numa.c +++ b/numa.c @@ -44,7 +44,8 @@ print_nodemask(struct tcb *const tcp, const kernel_ulong_t addr, SYS_FUNC(migrate_pages) { - tprintf("%d, %" PRI_klu ", ", (int) tcp->u_arg[0], tcp->u_arg[1]); + printpid(tcp, tcp->u_arg[0], PT_TGID); + tprintf(", %" PRI_klu ", ", tcp->u_arg[1]); print_nodemask(tcp, tcp->u_arg[2], tcp->u_arg[1]); tprints(", "); print_nodemask(tcp, tcp->u_arg[3], tcp->u_arg[1]); @@ -170,7 +171,8 @@ SYS_FUNC(move_pages) kernel_ulong_t buf; if (entering(tcp)) { - tprintf("%d, %" PRI_klu ", ", (int) tcp->u_arg[0], npages); + printpid(tcp, tcp->u_arg[0], PT_TGID); + tprintf(", %" PRI_klu ", ", npages); print_array(tcp, tcp->u_arg[2], npages, &buf, current_wordsize, tfetch_mem, print_addr, 0); tprints(", "); diff --git a/pidfd_open.c b/pidfd_open.c index bbc7f617..cf05a110 100644 --- a/pidfd_open.c +++ b/pidfd_open.c @@ -10,7 +10,7 @@ SYS_FUNC(pidfd_open) { /* pid_t pid */ - tprintf("%d", (int) tcp->u_arg[0]); + printpid(tcp, tcp->u_arg[0], PT_TGID); /* unsigned int flags */ tprintf(", %#x", (unsigned int) tcp->u_arg[1]); diff --git a/print_fields.h b/print_fields.h index f9714115..33d4a458 100644 --- a/print_fields.h +++ b/print_fields.h @@ -263,6 +263,30 @@ printfd((tcp_), (where_).field_); \ } while (0) +# define PRINT_FIELD_TID(prefix_, where_, field_, tcp_) \ + do { \ + STRACE_PRINTF("%s%s=", (prefix_), #field_); \ + printpid((tcp_), (where_).field_, PT_TID); \ + } while (0) + +# define PRINT_FIELD_TGID(prefix_, where_, field_, tcp_) \ + do { \ + STRACE_PRINTF("%s%s=", (prefix_), #field_); \ + printpid((tcp_), (where_).field_, PT_TGID); \ + } while (0) + +# define PRINT_FIELD_PGID(prefix_, where_, field_, tcp_) \ + do { \ + STRACE_PRINTF("%s%s=", (prefix_), #field_); \ + printpid((tcp_), (where_).field_, PT_PGID); \ + } while (0) + +# define PRINT_FIELD_SID(prefix_, where_, field_, tcp_) \ + do { \ + STRACE_PRINTF("%s%s=", (prefix_), #field_); \ + printpid((tcp_), (where_).field_, PT_SID); \ + } while (0) + # define PRINT_FIELD_STRN(prefix_, where_, field_, len_, tcp_) \ do { \ STRACE_PRINTF("%s%s=", (prefix_), #field_); \ diff --git a/printsiginfo.c b/printsiginfo.c index 8ed1e7ba..cb4cde4a 100644 --- a/printsiginfo.c +++ b/printsiginfo.c @@ -58,7 +58,7 @@ static void printsigsource(struct tcb *tcp, const siginfo_t *sip) { - PRINT_FIELD_D(", ", *sip, si_pid); + PRINT_FIELD_TGID(", ", *sip, si_pid, tcp); PRINT_FIELD_UID(", ", *sip, si_uid); } diff --git a/process.c b/process.c index a98c304e..d6ff255d 100644 --- a/process.c +++ b/process.c @@ -92,7 +92,8 @@ SYS_FUNC(ptrace) } /* pid */ - tprintf(", %d", pid); + tprints(", "); + printpid(tcp, pid, PT_TGID); /* addr */ switch (request) { diff --git a/process_vm.c b/process_vm.c index abee1e68..81d9b0f4 100644 --- a/process_vm.c +++ b/process_vm.c @@ -13,7 +13,8 @@ SYS_FUNC(process_vm_readv) { if (entering(tcp)) { /* arg 1: pid */ - tprintf("%d, ", (int) tcp->u_arg[0]); + printpid(tcp, tcp->u_arg[0], PT_TGID); + tprints(", "); } else { kernel_ulong_t local_iovcnt = tcp->u_arg[2]; kernel_ulong_t remote_iovcnt = tcp->u_arg[4]; @@ -42,7 +43,8 @@ SYS_FUNC(process_vm_writev) kernel_ulong_t flags = tcp->u_arg[5]; /* arg 1: pid */ - tprintf("%d, ", (int) tcp->u_arg[0]); + printpid(tcp, tcp->u_arg[0], PT_TGID); + tprints(", "); /* arg 2: local iov */ tprint_iov(tcp, local_iovcnt, tcp->u_arg[1], IOV_DECODE_STR); /* arg 3: local iovcnt */ diff --git a/resource.c b/resource.c index 53192ee9..070f4740 100644 --- a/resource.c +++ b/resource.c @@ -142,7 +142,8 @@ SYS_FUNC(setrlimit) SYS_FUNC(prlimit64) { if (entering(tcp)) { - tprintf("%d, ", (int) tcp->u_arg[0]); + printpid(tcp, tcp->u_arg[0], PT_TGID); + tprints(", "); printxval(resources, tcp->u_arg[1], "RLIMIT_???"); tprints(", "); print_rlimit64(tcp, tcp->u_arg[2]); @@ -179,10 +180,28 @@ SYS_FUNC(osf_getrusage) #include "xlat/priorities.h" +static void +priority_print_who(struct tcb *tcp, int which, int who) +{ + switch (which) + { + case PRIO_PROCESS: + printpid(tcp, who, PT_TGID); + break; + case PRIO_PGRP: + printpid(tcp, who, PT_PGID); + break; + default: + tprintf("%d", who); + break; + } +} + SYS_FUNC(getpriority) { printxval(priorities, tcp->u_arg[0], "PRIO_???"); - tprintf(", %d", (int) tcp->u_arg[1]); + tprints(", "); + priority_print_who(tcp, tcp->u_arg[0], tcp->u_arg[1]); return RVAL_DECODED; } @@ -190,7 +209,9 @@ SYS_FUNC(getpriority) SYS_FUNC(setpriority) { printxval(priorities, tcp->u_arg[0], "PRIO_???"); - tprintf(", %d, %d", (int) tcp->u_arg[1], (int) tcp->u_arg[2]); + tprints(", "); + priority_print_who(tcp, tcp->u_arg[0], tcp->u_arg[1]); + tprintf(", %d", (int) tcp->u_arg[2]); return RVAL_DECODED; } diff --git a/sched.c b/sched.c index 788ef39b..ff427e48 100644 --- a/sched.c +++ b/sched.c @@ -21,7 +21,7 @@ SYS_FUNC(sched_getscheduler) { if (entering(tcp)) { - tprintf("%d", (int) tcp->u_arg[0]); + printpid(tcp, tcp->u_arg[0], PT_TGID); } else if (!syserror(tcp)) { tcp->auxstr = xlookup(schedulers, (kernel_ulong_t) tcp->u_rval); return RVAL_STR; @@ -31,7 +31,8 @@ SYS_FUNC(sched_getscheduler) SYS_FUNC(sched_setscheduler) { - tprintf("%d, ", (int) tcp->u_arg[0]); + printpid(tcp, tcp->u_arg[0], PT_TGID); + tprints(", "); printxval(schedulers, tcp->u_arg[1], "SCHED_???"); tprints(", "); printnum_int(tcp, tcp->u_arg[2], "%d"); @@ -41,16 +42,19 @@ SYS_FUNC(sched_setscheduler) SYS_FUNC(sched_getparam) { - if (entering(tcp)) - tprintf("%d, ", (int) tcp->u_arg[0]); - else + if (entering(tcp)) { + printpid(tcp, tcp->u_arg[0], PT_TGID); + tprints(", "); + } else { printnum_int(tcp, tcp->u_arg[1], "%d"); + } return 0; } SYS_FUNC(sched_setparam) { - tprintf("%d, ", (int) tcp->u_arg[0]); + printpid(tcp, tcp->u_arg[0], PT_TGID); + tprints(", "); printnum_int(tcp, tcp->u_arg[1], "%d"); return RVAL_DECODED; @@ -68,7 +72,8 @@ do_sched_rr_get_interval(struct tcb *const tcp, const print_obj_by_addr_fn print_ts) { if (entering(tcp)) { - tprintf("%d, ", (int) tcp->u_arg[0]); + printpid(tcp, tcp->u_arg[0], PT_TGID); + tprints(", "); } else { if (syserror(tcp)) printaddr(tcp->u_arg[1]); @@ -160,7 +165,8 @@ end: SYS_FUNC(sched_setattr) { if (entering(tcp)) { - tprintf("%d, ", (int) tcp->u_arg[0]); + printpid(tcp, tcp->u_arg[0], PT_TGID); + tprints(", "); print_sched_attr(tcp, tcp->u_arg[1], 0); } else { struct sched_attr attr; @@ -179,7 +185,8 @@ SYS_FUNC(sched_setattr) SYS_FUNC(sched_getattr) { if (entering(tcp)) { - tprintf("%d, ", (int) tcp->u_arg[0]); + printpid(tcp, tcp->u_arg[0], PT_TGID); + tprints(", "); } else { const unsigned int size = tcp->u_arg[2]; diff --git a/signal.c b/signal.c index d5d59105..49b4ebd5 100644 --- a/signal.c +++ b/signal.c @@ -439,7 +439,8 @@ SYS_FUNC(sigprocmask) SYS_FUNC(kill) { /* pid */ - tprintf("%d, ", (int) tcp->u_arg[0]); + printpid_tgid_pgid(tcp, tcp->u_arg[0]); + tprints(", "); /* signal */ printsignal(tcp->u_arg[1]); @@ -448,7 +449,7 @@ SYS_FUNC(kill) SYS_FUNC(tkill) { - tprintf("%d", (int) tcp->u_arg[0]); + printpid(tcp, tcp->u_arg[0], PT_TID); tprints(", "); printsignal(tcp->u_arg[1]); @@ -457,8 +458,12 @@ SYS_FUNC(tkill) SYS_FUNC(tgkill) { - /* tgid, tid */ - tprintf("%d, %d, ", (int) tcp->u_arg[0], (int) tcp->u_arg[1]); + /* tgid */ + printpid(tcp, tcp->u_arg[0], PT_TGID); + tprints(", "); + /* tid */ + printpid(tcp, tcp->u_arg[1], PT_TID); + tprints(", "); /* signal */ printsignal(tcp->u_arg[2]); @@ -624,7 +629,8 @@ print_sigqueueinfo(struct tcb *const tcp, const int sig, SYS_FUNC(rt_sigqueueinfo) { - tprintf("%d, ", (int) tcp->u_arg[0]); + printpid(tcp, tcp->u_arg[0], PT_TGID); + tprints(", "); print_sigqueueinfo(tcp, tcp->u_arg[1], tcp->u_arg[2]); return RVAL_DECODED; @@ -632,7 +638,10 @@ SYS_FUNC(rt_sigqueueinfo) SYS_FUNC(rt_tgsigqueueinfo) { - tprintf("%d, %d, ", (int) tcp->u_arg[0], (int) tcp->u_arg[1]); + printpid(tcp, tcp->u_arg[0], PT_TGID); + tprints(", "); + printpid(tcp, tcp->u_arg[1], PT_TID); + tprints(", "); print_sigqueueinfo(tcp, tcp->u_arg[2], tcp->u_arg[3]); return RVAL_DECODED; diff --git a/sockaddr.c b/sockaddr.c index b0046331..fb8887c2 100644 --- a/sockaddr.c +++ b/sockaddr.c @@ -416,7 +416,7 @@ print_sockaddr_data_nl(struct tcb *tcp, const void *const buf, const int addrlen { const struct sockaddr_nl *const sa_nl = buf; - PRINT_FIELD_D("", *sa_nl, nl_pid); + PRINT_FIELD_TGID("", *sa_nl, nl_pid, tcp); PRINT_FIELD_0X(", ", *sa_nl, nl_groups); } diff --git a/tests/kcmp.c b/tests/kcmp.c index a46da0ed..dc5ba9a4 100644 --- a/tests/kcmp.c +++ b/tests/kcmp.c @@ -64,7 +64,26 @@ static const char zero_path[] = "/dev/zero"; static void printpidfd(const char *prefix, pid_t pid, unsigned fd) { - printf("%s%d", prefix, fd); + const char *path = NULL; + +# if VERBOSE_FD + if (pid == getpid()) { + switch (fd) + { + case NULL_FD: + path = null_path; + break; + case ZERO_FD: + path = zero_path; + break; + } + } +# endif + + if (path) + printf("%s%d<%s>", prefix, fd, path); + else + printf("%s%d", prefix, fd); } /* @@ -179,7 +198,7 @@ main(void) /* KCMP_FILE is the only type which has additional args */ do_kcmp(3141592653U, 2718281828U, ARG_STR(KCMP_FILE), bogus_idx1, bogus_idx2); - do_kcmp(-1, -1, ARG_STR(KCMP_FILE), NULL_FD, ZERO_FD); + do_kcmp(getpid(), getpid(), ARG_STR(KCMP_FILE), NULL_FD, ZERO_FD); /* Types without additional args */ do_kcmp(-1, -1, ARG_STR(KCMP_VM), bogus_idx1, bogus_idx2); @@ -198,7 +217,7 @@ main(void) for (i = 0; i < ARRAY_SIZE(slot_data); i++) { memcpy(slot, slot_data + i, sizeof(*slot)); - do_kcmp(getpid(), getppid(), ARG_STR(KCMP_EPOLL_TFD), NULL_FD, + do_kcmp(getpid(), -1, ARG_STR(KCMP_EPOLL_TFD), NULL_FD, (uintptr_t) slot, 1); } diff --git a/util.c b/util.c index 286c6903..094e5818 100644 --- a/util.c +++ b/util.c @@ -392,6 +392,18 @@ printnum_fd(struct tcb *const tcp, const kernel_ulong_t addr) return true; } +bool +printnum_pid(struct tcb *const tcp, const kernel_ulong_t addr, enum pid_type type) +{ + int pid; + if (umove_or_printaddr(tcp, addr, &pid)) + return false; + tprints("["); + printpid(tcp, pid, type); + tprints("]"); + return true; +} + /** * Prints time to a (static internal) buffer and returns pointer to it. * Returns NULL if the provided time specification is not correct. @@ -641,12 +653,8 @@ printed: void printfd_pid_tracee_ns(struct tcb *tcp, pid_t pid, int fd) { - /* - * TODO: We want to have the same formatting as printfd here, - * but we should figure out first which process in strace's - * PID NS is referred to by pid in tracee's PID NS. - */ - tprintf("%d", fd); + int strace_pid = translate_pid(tcp, pid, PT_TGID, NULL); + printfd_pid(tcp, strace_pid, fd); } /* diff --git a/wait.c b/wait.c index 2b9f9807..177427c8 100644 --- a/wait.c +++ b/wait.c @@ -80,14 +80,8 @@ printwaitn(struct tcb *const tcp, void (*const print_rusage)(struct tcb *, kernel_ulong_t)) { if (entering(tcp)) { - /* On Linux, kernel-side pid_t is typedef'ed to int - * on all arches. Also, glibc-2.8 truncates wait3 and wait4 - * pid argument to int on 64bit arches, producing, - * for example, wait4(4294967295, ...) instead of -1 - * in strace. We have to use int here, not long. - */ - int pid = tcp->u_arg[0]; - tprintf("%d, ", pid); + printpid_tgid_pgid(tcp, tcp->u_arg[0]); + tprintf(", "); } else { int status; @@ -108,7 +102,7 @@ printwaitn(struct tcb *const tcp, printaddr(tcp->u_arg[3]); } } - return 0; + return RVAL_TGID; } SYS_FUNC(waitpid) @@ -134,10 +128,28 @@ SYS_FUNC(osf_wait4) SYS_FUNC(waitid) { + unsigned int idtype = (unsigned int) tcp->u_arg[0]; + int id = tcp->u_arg[1]; + if (entering(tcp)) { - printxval(waitid_types, tcp->u_arg[0], "P_???"); - int pid = tcp->u_arg[1]; - tprintf(", %d, ", pid); + printxval(waitid_types, idtype, "P_???"); + tprints(", "); + switch (idtype) + { + case P_PID: + printpid(tcp, id, PT_TGID); + break; + case P_PIDFD: + printfd(tcp, id); + break; + case P_PGID: + printpid(tcp, id, PT_PGID); + break; + default: + tprintf("%d", id); + break; + } + tprints(", "); } else { /* siginfo */ printsiginfo_at(tcp, tcp->u_arg[2]); -- 2.27.0 From uzonyi.akos at gmail.com Sat Aug 8 21:14:36 2020 From: uzonyi.akos at gmail.com (=?UTF-8?q?=C3=81kos=20Uzonyi?=) Date: Sat, 8 Aug 2020 23:14:36 +0200 Subject: [PATCH v7 4/5] Implement testing framework for pidns In-Reply-To: <20200808211437.469898-1-uzonyi.akos@gmail.com> References: <20200808211437.469898-1-uzonyi.akos@gmail.com> Message-ID: <20200808211437.469898-5-uzonyi.akos@gmail.com> * tests/pidns.c: New file. * tests/pidns.h: New file. * tests/Makefile.am (libtests_a_SOURCES): Add pidns.c, pidns.h. * tests/init.sh (test_pidns, test_pidns_run_strace): New functions. --- tests/Makefile.am | 2 + tests/init.sh | 31 +++++++ tests/pidns.c | 214 ++++++++++++++++++++++++++++++++++++++++++++++ tests/pidns.h | 56 ++++++++++++ 4 files changed, 303 insertions(+) create mode 100644 tests/pidns.c create mode 100644 tests/pidns.h diff --git a/tests/Makefile.am b/tests/Makefile.am index 28d95e39..7a583a3a 100644 --- a/tests/Makefile.am +++ b/tests/Makefile.am @@ -44,6 +44,8 @@ libtests_a_SOURCES = \ libsocketcall.c \ lock_file.c \ overflowuid.c \ + pidns.c \ + pidns.h \ pipe_maxfd.c \ print_quoted_string.c \ print_time.c \ diff --git a/tests/init.sh b/tests/init.sh index d78e697b..7325fa4a 100644 --- a/tests/init.sh +++ b/tests/init.sh @@ -387,6 +387,37 @@ test_prog_set() test_pure_prog_set "$@" < "$srcdir/$NAME.in" } +test_pidns_run_strace() +{ + local parent_pid + + check_prog tail + check_prog cut + check_prog grep + + run_prog > /dev/null + run_strace --pidns-translation -f $@ $args > "$EXP" + + # filter out logs made by the parent or init process of the pidns test + parent_pid="$(tail -n 2 $LOG | head -n 1 | cut -d' ' -f1)" + init_pid="$(tail -n 1 $LOG | cut -d' ' -f1)" + grep -E -v "^($parent_pid|$init_pid) " "$LOG" > "$OUT" + match_diff "$OUT" "$EXP" +} + +test_pidns() +{ + # ioctl(NS_GET_PARENT) is added in Linux 4.9 + require_min_kernel_version_or_skip 4.9 + check_prog unshare + + test_pidns_run_strace "$@" + + # test PID translation when /proc is mounted from an other namespace + STRACE="unshare -Urpf $STRACE" + test_pidns_run_strace "$@" +} + check_prog cat check_prog rm diff --git a/tests/pidns.c b/tests/pidns.c new file mode 100644 index 00000000..f54af340 --- /dev/null +++ b/tests/pidns.c @@ -0,0 +1,214 @@ +/* + * Testing framework for PID namespace translation + * + * Copyright (c) 2020 ?kos Uzonyi + * All rights reserved. + * + * SPDX-License-Identifier: LGPL-2.1-or-later + */ +#include "tests.h" +#include "pidns.h" +#include "nsfs.h" + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +static bool pidns_translation = false; +static bool pidns_unshared = false; + +/* Our PIDs in strace's namespace */ +static pid_t pidns_strace_ids[PT_COUNT]; + +void +pidns_print_leader(void) +{ + if (pidns_translation) + printf("%-5d ", pidns_strace_ids[PT_TID]); +} + +const char * +pidns_pid2str(enum pid_type type) +{ + static const char format[] = " /* %d in strace's PID NS */"; + static char buf[PT_COUNT][sizeof(format) + sizeof(int) * 3]; + + if (type < 0 || type >= PT_COUNT) + return ""; + + if (!pidns_unshared || !pidns_strace_ids[type]) + return ""; + + snprintf(buf[type], sizeof(buf[type]), format, pidns_strace_ids[type]); + return buf[type]; +} + +/** + * This function is like fork, but does a few more things. It sets up the + * child's PGID and SID according to the parameters. Also it fills the + * pidns_strace_ids array in the child's memory with the PIDs of the child in + * parent's PID namespace. In the parent it waits for the child to terminate + * (but leaves the zombie to use it later as a process group). If the child + * terminates with nonzero exit status, the test is failed. + * + * @param pgid The process group the child should be moved to. It's expected + * to be a PID of a zombie process (will be reaped). If + * negative, leave the child in the process group of the parent. + * If 0, move the process to its own process group. + * @param new_sid Wheather child should be moved to a new session. + */ +static pid_t +pidns_fork(pid_t pgid, bool new_sid) +{ + int strace_ids_pipe[2]; + if (pipe(strace_ids_pipe) < 0) + perror_msg_and_fail("pipe"); + + fflush(stdout); + pid_t pid = fork(); + if (pid < 0) + perror_msg_and_fail("fork"); + + if (!pid) { + close(strace_ids_pipe[1]); + if (read(strace_ids_pipe[0], pidns_strace_ids, + sizeof(pidns_strace_ids)) < 0) + perror_msg_and_fail("read"); + close(strace_ids_pipe[0]); + + if (pidns_strace_ids[PT_SID]) + setsid(); + + return 0; + } + + pidns_strace_ids[PT_TID] = pid; + pidns_strace_ids[PT_TGID] = pid; + pidns_strace_ids[PT_PGID] = 0; + pidns_strace_ids[PT_SID] = 0; + + if (!pgid) + pgid = pid; + + if (pgid > 0) { + if (setpgid(pid, pgid) < 0) + perror_msg_and_fail("setpgid"); + + pidns_strace_ids[PT_PGID] = pgid; + } + + /* Reap group leader to test PGID decoding */ + if (pgid > 0 && pgid != pid) { + int ret = waitpid(pgid, NULL, WNOHANG); + if (ret < 0) + perror_msg_and_fail("wait"); + if (!ret) + error_msg_and_fail("could not reap group leader"); + } + + if (new_sid) { + pidns_strace_ids[PT_SID] = pid; + pidns_strace_ids[PT_PGID] = pid; + } + + if (write(strace_ids_pipe[1], pidns_strace_ids, + sizeof(pidns_strace_ids)) < 0) + perror_msg_and_fail("write"); + close(strace_ids_pipe[0]); + close(strace_ids_pipe[1]); + + /* WNOWAIT: leave the zombie, to be able to use it as a process group */ + siginfo_t siginfo; + if (waitid(P_PID, pid, &siginfo, WEXITED | WNOWAIT) < 0) + perror_msg_and_fail("wait"); + if (siginfo.si_code != CLD_EXITED || siginfo.si_status) + error_msg_and_fail("child terminated with nonzero exit status"); + + return pid; +} + +static void +create_init_process(void) +{ + int child_pipe[2]; + if (pipe(child_pipe) < 0) + perror_msg_and_fail("pipe"); + + pid_t pid = fork(); + if (pid < 0) + perror_msg_and_fail("fork"); + + if (!pid) { + close(child_pipe[1]); + _exit(read(child_pipe[0], &child_pipe[1], sizeof(int)) == 0); + } + + close(child_pipe[0]); +} + +void +check_ns_ioctl(void) +{ + int fd = open("/proc/self/ns/pid", O_RDONLY); + if (fd < 0) + perror_msg_and_fail("opening /proc/self/ns/pid"); + + int userns_fd = ioctl(fd, NS_GET_USERNS); + if (userns_fd < 0) { + if (errno == ENOTTY) + error_msg_and_skip("NS_* ioctl commands are not " + "supported by the kernel"); + else + perror_msg_and_fail("ioctl(NS_GET_USERNS)"); + } + + close(userns_fd); + close(fd); +} + +void +pidns_test_init(void) +{ + pidns_translation = true; + + check_ns_ioctl(); + + if (!pidns_fork(-1, false)) + return; + + /* Unshare user namespace too, so we do not need to be root */ + if (unshare(CLONE_NEWUSER | CLONE_NEWPID) < 0) { + if (errno == EPERM) + perror_msg_and_skip("unshare"); + + perror_msg_and_fail("unshare"); + } + + pidns_unshared = true; + + create_init_process(); + + if (!pidns_fork(-1, false)) + return; + + if (!pidns_fork(-1, true)) + return; + + pid_t pgid; + if (!(pgid = pidns_fork(0, false))) + return; + + if (!pidns_fork(pgid, false)) + return; + + exit(0); +} diff --git a/tests/pidns.h b/tests/pidns.h new file mode 100644 index 00000000..76963eb3 --- /dev/null +++ b/tests/pidns.h @@ -0,0 +1,56 @@ +/* + * Test PID namespace translation + * + * Copyright (c) 2020 ?kos Uzonyi + * All rights reserved. + * + * SPDX-License-Identifier: LGPL-2.1-or-later + */ +#ifndef STRACE_PIDNS_H +#define STRACE_PIDNS_H + +#ifdef PIDNS_TRANSLATION +# define PIDNS_TEST_INIT pidns_test_init() +#else +# define PIDNS_TEST_INIT +#endif + +#include + +enum pid_type { + PT_TID, + PT_TGID, + PT_PGID, + PT_SID, + + PT_COUNT, + PT_NONE = -1 +}; + +/* Prints leader (process tid) if pidns_test_init was called */ +void pidns_print_leader(void); + +/* + * Returns a static buffer containing the translation string of our PID. + */ +const char *pidns_pid2str(enum pid_type type); + +/** + * Skips the test if NS_* ioctl commands are not supported by the kernel. + */ +void check_ns_ioctl(void); + +/** + * Init pidns testing. + * + * Should be called at the beginning of the test's main function + * + * This function calls fork a couple of times, and returns in the child + * processes. These child processes are in a new PID namespace with different + * PID configurations (group leader, session leader, ...). If any child + * terminates with nonzero exit status the test is failed. Otherwise the test is + * succesful, and the parent process exits with 0. + */ +void pidns_test_init(void); + +#endif \ No newline at end of file -- 2.27.0 From uzonyi.akos at gmail.com Sat Aug 8 21:14:35 2020 From: uzonyi.akos at gmail.com (=?UTF-8?q?=C3=81kos=20Uzonyi?=) Date: Sat, 8 Aug 2020 23:14:35 +0200 Subject: [PATCH v7 3/5] Use get_proc_pid for /proc paths In-Reply-To: <20200808211437.469898-1-uzonyi.akos@gmail.com> References: <20200808211437.469898-1-uzonyi.akos@gmail.com> Message-ID: <20200808211437.469898-4-uzonyi.akos@gmail.com> * mmap_cache.c (mmap_cache_rebuild_if_invalid): Use proc pid instead of tcp->pid for /proc path. * util.c (getfdproto): Likewise. (pidfd_get_pid): Likewise. * pathtrace.c (getfdpath_pid): Likewise. * strace.c (attach_tcb): Likewise. --- mmap_cache.c | 2 +- pathtrace.c | 5 ++++- strace.c | 2 +- util.c | 7 +++++-- 4 files changed, 11 insertions(+), 5 deletions(-) diff --git a/mmap_cache.c b/mmap_cache.c index 89c62254..9825df26 100644 --- a/mmap_cache.c +++ b/mmap_cache.c @@ -84,7 +84,7 @@ mmap_cache_rebuild_if_invalid(struct tcb *tcp, const char *caller) return MMAP_CACHE_REBUILD_READY; char filename[sizeof("/proc/4294967296/maps")]; - xsprintf(filename, "/proc/%u/maps", tcp->pid); + xsprintf(filename, "/proc/%u/maps", get_proc_pid(tcp)); FILE *fp = fopen_stream(filename, "r"); if (!fp) { diff --git a/pathtrace.c b/pathtrace.c index 5b60762b..74717a8a 100644 --- a/pathtrace.c +++ b/pathtrace.c @@ -87,7 +87,10 @@ getfdpath_pid(pid_t pid, int fd, char *buf, unsigned bufsize) if (fd < 0) return -1; - xsprintf(linkpath, "/proc/%u/fd/%u", pid, fd); + int proc_pid = 0; + translate_pid(NULL, pid, PT_TID, &proc_pid); + + xsprintf(linkpath, "/proc/%u/fd/%u", proc_pid, fd); n = readlink(linkpath, buf, bufsize - 1); /* * NB: if buf is too small, readlink doesn't fail, diff --git a/strace.c b/strace.c index 249533ea..ef23f08f 100644 --- a/strace.c +++ b/strace.c @@ -1196,7 +1196,7 @@ attach_tcb(struct tcb *const tcp) unsigned int ntid = 0, nerr = 0; if (followfork && tcp->pid != strace_child && - xsprintf(procdir, task_path, tcp->pid) > 0 && + xsprintf(procdir, task_path, get_proc_pid(tcp)) > 0 && (dir = opendir(procdir)) != NULL) { struct_dirent *de; diff --git a/util.c b/util.c index 094e5818..d87d022e 100644 --- a/util.c +++ b/util.c @@ -501,7 +501,7 @@ getfdproto(struct tcb *tcp, int fd) if (fd < 0) return SOCK_PROTO_UNKNOWN; - xsprintf(path, "/proc/%u/fd/%u", tcp->pid, fd); + xsprintf(path, "/proc/%u/fd/%u", get_proc_pid(tcp), fd); r = getxattr(path, "system.sockprotoname", buf, bufsize - 1); if (r <= 0) return SOCK_PROTO_UNKNOWN; @@ -582,8 +582,11 @@ printdev(struct tcb *tcp, int fd, const char *path) pid_t pidfd_get_pid(pid_t pid_of_fd, int fd) { + int proc_pid = 0; + translate_pid(NULL, pid_of_fd, PT_TID, &proc_pid); + char fdi_path[sizeof("/proc/%u/fdinfo/%u") + 2 * sizeof(int) * 3]; - xsprintf(fdi_path, "/proc/%u/fdinfo/%u", pid_of_fd, fd); + xsprintf(fdi_path, "/proc/%u/fdinfo/%u", proc_pid, fd); FILE *f = fopen_stream(fdi_path, "r"); if (!f) -- 2.27.0 From uzonyi.akos at gmail.com Sat Aug 8 21:14:37 2020 From: uzonyi.akos at gmail.com (=?UTF-8?q?=C3=81kos=20Uzonyi?=) Date: Sat, 8 Aug 2020 23:14:37 +0200 Subject: [PATCH v7 5/5] Add tests for PID namespace translation In-Reply-To: <20200808211437.469898-1-uzonyi.akos@gmail.com> References: <20200808211437.469898-1-uzonyi.akos@gmail.com> Message-ID: <20200808211437.469898-6-uzonyi.akos@gmail.com> * tests/.gitignore: Add new test executables. * tests/Makefile.am (check_PROGRAMS): Add new test executables. (DECODER_TESTS) Add new test files. * tests/gen_tests.in: Add new tests. * tests/fcntl--pidns-translation.c: New file. * tests/fcntl64--pidns-translation.c: New file. * tests/fork--pidns-translation.awk: New file. * tests/fork--pidns-translation.c: New file. * tests/fork--pidns-translation.test: New file. * tests/getpgrp--pidns-translation.c: New file. * tests/getpid--pidns-translation.c: New file. * tests/getsid--pidns-translation.c: New file. * tests/gettid--pidns-translation.c: New file. * tests/gettid--pidns-translation.test: New file. * tests/ioctl_block--pidns-translation.c: New file. * tests/ioctl_block--pidns-translation.test: New file. * tests/ioprio--pidns-translation.c: New file. * tests/kill--pidns-translation.c: New file. * tests/migrate_pages--pidns-translation.c: New file. * tests/move_pages--pidns-translation.c: New file. * tests/net-sockaddr--pidns-translation.c: New file. * tests/netlink_audit--pidns-translation.c: New file. * tests/netlink_audit--pidns-translation.test: New file. * tests/pidfd_open--pidns-translation.c: New file. * tests/pidfd_send_signal--pidns-translation.c: New file. * tests/prlimit64--pidns-translation.c: New file. * tests/process_vm_readv--pidns-translation.c: New file. * tests/process_vm_writev--pidns-translation.c: New file. * tests/rt_sigqueueinfo--pidns-translation.c: New file. * tests/rt_tgsigqueueinfo--pidns-translation.c: New file. * tests/sched_xetaffinity--pidns-translation.c: New file. * tests/sched_xetattr--pidns-translation.c: New file. * tests/sched_xetparam--pidns-translation.c: New file. * tests/sched_xetscheduler--pidns-translation.c: New file. * tests/signal_receive--pidns-translation.c: New file. * tests/so_peercred--pidns-translation.c: New file. * tests/xet_robust_list--pidns-translation.c: New file. * tests/xetpgid--pidns-translation.c: New file. * tests/xetpriority--pidns-translation.c: New file. * tests/fcntl-common.c: Print PID translation string after PIDs. * tests/fcntl.c: Likewise. * tests/fcntl64.c: Likewise. * tests/getpgrp.c: Likewise. * tests/getpid.c: Likewise. * tests/getsid.c: Likewise. * tests/gettid.c: Likewise. * tests/ioctl_block.c: Likewise. * tests/ioprio.c: Likewise. * tests/kcmp.c: Likewise. * tests/kill.c: Likewise. * tests/migrate_pages.c: Likewise. * tests/move_pages.c: Likewise. * tests/net-sockaddr.c: Likewise. * tests/netlink_audit.c: Likewise. * tests/pidfd_open.c: Likewise. * tests/pidfd_send_signal.c: Likewise. * tests/prlimit64.c: Likewise. * tests/process_vm_readv_writev.c: Likewise. * tests/rt_sigqueueinfo.c: Likewise. * tests/rt_tgsigqueueinfo.c: Likewise. * tests/sched_xetaffinity.c: Likewise. * tests/sched_xetattr.c: Likewise. * tests/sched_xetparam.c: Likewise. * tests/sched_xetscheduler.c: Likewise. * tests/signal_receive.c: Likewise. * tests/so_peercred.c: Likewise. * tests/xet_robust_list.c: Likewise. * tests/xetpgid.c: Likewise. * tests/xetpriority.c: Likewise. --- tests/.gitignore | 31 +++++++ tests/Makefile.am | 36 ++++++++ tests/fcntl--pidns-translation.c | 2 + tests/fcntl-common.c | 82 ++++++++++++++----- tests/fcntl.c | 1 + tests/fcntl64--pidns-translation.c | 2 + tests/fcntl64.c | 3 + tests/fork--pidns-translation.awk | 15 ++++ tests/fork--pidns-translation.c | 69 ++++++++++++++++ tests/fork--pidns-translation.test | 16 ++++ tests/gen_tests.in | 29 ++++++- tests/getpgrp--pidns-translation.c | 2 + tests/getpgrp.c | 8 +- tests/getpid--pidns-translation.c | 2 + tests/getpid.c | 8 +- tests/getsid--pidns-translation.c | 2 + tests/getsid.c | 9 +- tests/gettid--pidns-translation.c | 2 + tests/gettid--pidns-translation.test | 19 +++++ tests/gettid.c | 8 +- tests/ioctl_block--pidns-translation.c | 2 + tests/ioctl_block--pidns-translation.test | 24 ++++++ tests/ioctl_block.c | 24 +++++- tests/ioprio--pidns-translation.c | 2 + tests/ioprio.c | 54 ++++++++---- tests/kcmp-y--pidns-translation.c | 2 + tests/kcmp.c | 11 ++- tests/kill--pidns-translation.c | 2 + tests/kill.c | 12 ++- tests/migrate_pages--pidns-translation.c | 2 + tests/migrate_pages.c | 17 +++- tests/move_pages--pidns-translation.c | 2 + tests/move_pages.c | 51 +++++++----- tests/net-sockaddr--pidns-translation.c | 2 + tests/net-sockaddr.c | 66 +++++++++++++-- tests/netlink_audit--pidns-translation.c | 2 + tests/netlink_audit--pidns-translation.test | 13 +++ tests/netlink_audit.c | 11 ++- tests/pidfd_open--pidns-translation.c | 2 + tests/pidfd_open.c | 21 +++-- tests/pidfd_send_signal--pidns-translation.c | 2 + tests/pidfd_send_signal.c | 13 ++- tests/prlimit64--pidns-translation.c | 2 + tests/prlimit64.c | 17 +++- tests/process_vm_readv--pidns-translation.c | 2 + tests/process_vm_readv_writev.c | 27 +++--- tests/process_vm_writev--pidns-translation.c | 2 + tests/rt_sigqueueinfo--pidns-translation.c | 2 + tests/rt_sigqueueinfo.c | 15 +++- tests/rt_tgsigqueueinfo--pidns-translation.c | 2 + tests/rt_tgsigqueueinfo.c | 26 ++++-- tests/sched_xetaffinity--pidns-translation.c | 2 + tests/sched_xetaffinity.c | 31 ++++--- tests/sched_xetattr--pidns-translation.c | 2 + tests/sched_xetattr.c | 47 ++++++++++- tests/sched_xetparam--pidns-translation.c | 2 + tests/sched_xetparam.c | 20 +++-- tests/sched_xetscheduler--pidns-translation.c | 2 + tests/sched_xetscheduler.c | 44 ++++++---- tests/signal_receive--pidns-translation.c | 2 + tests/signal_receive.c | 22 +++-- tests/so_peercred--pidns-translation.c | 2 + tests/so_peercred.c | 22 +++++ tests/xet_robust_list--pidns-translation.c | 2 + tests/xet_robust_list.c | 18 +++- tests/xetpgid--pidns-translation.c | 2 + tests/xetpgid.c | 21 +++-- tests/xetpriority--pidns-translation.c | 2 + tests/xetpriority.c | 20 ++++- 69 files changed, 873 insertions(+), 168 deletions(-) create mode 100644 tests/fcntl--pidns-translation.c create mode 100644 tests/fcntl64--pidns-translation.c create mode 100644 tests/fork--pidns-translation.awk create mode 100644 tests/fork--pidns-translation.c create mode 100755 tests/fork--pidns-translation.test create mode 100644 tests/getpgrp--pidns-translation.c create mode 100644 tests/getpid--pidns-translation.c create mode 100644 tests/getsid--pidns-translation.c create mode 100644 tests/gettid--pidns-translation.c create mode 100755 tests/gettid--pidns-translation.test create mode 100644 tests/ioctl_block--pidns-translation.c create mode 100755 tests/ioctl_block--pidns-translation.test create mode 100644 tests/ioprio--pidns-translation.c create mode 100644 tests/kcmp-y--pidns-translation.c create mode 100644 tests/kill--pidns-translation.c create mode 100644 tests/migrate_pages--pidns-translation.c create mode 100644 tests/move_pages--pidns-translation.c create mode 100644 tests/net-sockaddr--pidns-translation.c create mode 100644 tests/netlink_audit--pidns-translation.c create mode 100755 tests/netlink_audit--pidns-translation.test create mode 100644 tests/pidfd_open--pidns-translation.c create mode 100644 tests/pidfd_send_signal--pidns-translation.c create mode 100644 tests/prlimit64--pidns-translation.c create mode 100644 tests/process_vm_readv--pidns-translation.c create mode 100644 tests/process_vm_writev--pidns-translation.c create mode 100644 tests/rt_sigqueueinfo--pidns-translation.c create mode 100644 tests/rt_tgsigqueueinfo--pidns-translation.c create mode 100644 tests/sched_xetaffinity--pidns-translation.c create mode 100644 tests/sched_xetattr--pidns-translation.c create mode 100644 tests/sched_xetparam--pidns-translation.c create mode 100644 tests/sched_xetscheduler--pidns-translation.c create mode 100644 tests/signal_receive--pidns-translation.c create mode 100644 tests/so_peercred--pidns-translation.c create mode 100644 tests/xet_robust_list--pidns-translation.c create mode 100644 tests/xetpgid--pidns-translation.c create mode 100644 tests/xetpriority--pidns-translation.c diff --git a/tests/.gitignore b/tests/.gitignore index 0031d04d..4d1153fc 100644 --- a/tests/.gitignore +++ b/tests/.gitignore @@ -116,7 +116,9 @@ fchown fchown32 fchownat fcntl +fcntl--pidns-translation fcntl64 +fcntl64--pidns-translation fdatasync fflush file_handle @@ -126,6 +128,7 @@ filter-unavailable finit_module flock fork-f +fork--pidns-translation fsconfig fsconfig-P fsmount @@ -168,7 +171,9 @@ getgroups getgroups32 getpeername getpgrp +getpgrp--pidns-translation getpid +getpid--pidns-translation getppid getrandom getresgid @@ -178,8 +183,10 @@ getresuid32 getrlimit getrusage getsid +getsid--pidns-translation getsockname gettid +gettid--pidns-translation getuid getuid32 getxgid @@ -200,6 +207,7 @@ io_uring_register io_uring_setup ioctl ioctl_block +ioctl_block--pidns-translation ioctl_dm ioctl_dm-v ioctl_evdev @@ -275,6 +283,7 @@ ioctl_watchdog ioperm iopl ioprio +ioprio--pidns-translation ioprio-Xabbrev ioprio-Xraw ioprio-Xverbose @@ -299,6 +308,7 @@ ipc_shm-Xverbose is_linux_mips_n64 kcmp kcmp-y +kcmp-y--pidns-translation kern_features kernel_version kernel_version-Xabbrev @@ -311,6 +321,7 @@ keyctl-Xabbrev keyctl-Xraw keyctl-Xverbose kill +kill--pidns-translation kill_child ksysent ksysent.h @@ -340,6 +351,7 @@ memfd_create-Xabbrev memfd_create-Xraw memfd_create-Xverbose migrate_pages +migrate_pages--pidns-translation mincore mkdir mkdirat @@ -371,6 +383,7 @@ move_pages move_pages-Xabbrev move_pages-Xraw move_pages-Xverbose +move_pages--pidns-translation mq mq_sendrecv mq_sendrecv-read @@ -391,6 +404,7 @@ net-packet_mreq-Xabbrev net-packet_mreq-Xraw net-packet_mreq-Xverbose net-sockaddr +net-sockaddr--pidns-translation net-tpacket_req net-tpacket_stats net-tpacket_stats-success @@ -400,6 +414,7 @@ net-yy-inet6 net-yy-netlink net-yy-unix netlink_audit +netlink_audit--pidns-translation netlink_crypto netlink_generic netlink_inet_diag @@ -507,7 +522,9 @@ pidfd_open--decode-fd-socket pidfd_open-P pidfd_open-y pidfd_open-yy +pidfd_open--pidns-translation pidfd_send_signal +pidfd_send_signal--pidns-translation pipe pipe2 pkey_alloc @@ -546,8 +563,11 @@ printstrn-umoven printstrn-umoven-peekdata printstrn-umoven-undumpable prlimit64 +prlimit64--pidns-translation process_vm_readv +process_vm_readv--pidns-translation process_vm_writev +process_vm_writev--pidns-translation pselect6 ptrace ptrace_syscall_info @@ -597,10 +617,12 @@ rt_sigaction rt_sigpending rt_sigprocmask rt_sigqueueinfo +rt_sigqueueinfo--pidns-translation rt_sigreturn rt_sigsuspend rt_sigtimedwait rt_tgsigqueueinfo +rt_tgsigqueueinfo--pidns-translation run_expect_termsig s390_guarded_storage s390_guarded_storage-v @@ -611,9 +633,13 @@ s390_sthyi-v sched_get_priority_mxx sched_rr_get_interval sched_xetaffinity +sched_xetaffinity--pidns-translation sched_xetattr +sched_xetattr--pidns-translation sched_xetparam +sched_xetparam--pidns-translation sched_xetscheduler +sched_xetscheduler--pidns-translation sched_yield scm_rights scno.h @@ -669,6 +695,7 @@ sigaltstack siginfo signal signal_receive +signal_receive--pidns-translation signalfd4 sigpending sigprocmask @@ -681,6 +708,7 @@ so_peercred so_peercred-Xabbrev so_peercred-Xraw so_peercred-Xverbose +so_peercred--pidns-translation sock_filter-v sock_filter-v-Xabbrev sock_filter-v-Xraw @@ -783,9 +811,12 @@ waitpid xattr xattr-strings xet_robust_list +xet_robust_list--pidns-translation xet_thread_area_x86 xetitimer xetpgid +xetpgid--pidns-translation xetpriority +xetpriority--pidns-translation xettimeofday zeroargc diff --git a/tests/Makefile.am b/tests/Makefile.am index 7a583a3a..f2c5da83 100644 --- a/tests/Makefile.am +++ b/tests/Makefile.am @@ -109,17 +109,25 @@ check_PROGRAMS = $(PURE_EXECUTABLES) \ delay \ execve-v \ execveat-v \ + fcntl--pidns-translation \ + fcntl64--pidns-translation \ filter_seccomp-flag \ filter_seccomp-perf \ filter-unavailable \ fork-f \ + fork--pidns-translation \ fsync-y \ get_process_reaper \ + getpgrp--pidns-translation \ getpid \ + getpid--pidns-translation \ getppid \ + getsid--pidns-translation \ gettid \ + gettid--pidns-translation \ inject-nf \ int_0x80 \ + ioctl_block--pidns-translation \ ioctl_dm-v \ ioctl_evdev-success \ ioctl_evdev-success-Xabbrev \ @@ -150,18 +158,25 @@ check_PROGRAMS = $(PURE_EXECUTABLES) \ ioctl_v4l2-success-v-Xabbrev \ ioctl_v4l2-success-v-Xraw \ ioctl_v4l2-success-v-Xverbose \ + ioprio--pidns-translation \ is_linux_mips_n64 \ + kcmp-y--pidns-translation \ kill_child \ + kill--pidns-translation \ ksysent \ list_sigaction_signum \ localtime \ looping_threads \ + migrate_pages--pidns-translation \ mmsg-silent \ mmsg_name-v \ + move_pages--pidns-translation \ msg_control-v \ net-accept-connect \ + net-sockaddr--pidns-translation \ net-tpacket_stats-success \ nlattr_ifla_xdp-y \ + netlink_audit--pidns-translation \ netlink_inet_diag \ netlink_netlink_diag \ netlink_unix_diag \ @@ -173,14 +188,19 @@ check_PROGRAMS = $(PURE_EXECUTABLES) \ pc \ perf_event_open_nonverbose \ perf_event_open_unabbrev \ + pidfd_open--pidns-translation \ + pidfd_send_signal--pidns-translation \ poll-P \ ppoll-P \ ppoll-v \ + prlimit64--pidns-translation \ prctl-seccomp-filter-v \ prctl-seccomp-strict \ prctl-spec-inject \ print_maxfd \ print_ppid_tracerpid \ + process_vm_readv--pidns-translation \ + process_vm_writev--pidns-translation \ qual_fault \ qual_inject-error-signal \ qual_inject-retval \ @@ -194,7 +214,13 @@ check_PROGRAMS = $(PURE_EXECUTABLES) \ quotactl-xfs-v \ redirect-fds \ restart_syscall \ + rt_sigqueueinfo--pidns-translation \ + rt_tgsigqueueinfo--pidns-translation \ run_expect_termsig \ + sched_xetaffinity--pidns-translation \ + sched_xetattr--pidns-translation \ + sched_xetparam--pidns-translation \ + sched_xetscheduler--pidns-translation \ scm_rights \ seccomp-filter-v \ seccomp-strict \ @@ -204,12 +230,14 @@ check_PROGRAMS = $(PURE_EXECUTABLES) \ set_sigign \ setpgrp-exec \ signal_receive \ + signal_receive--pidns-translation \ sleep \ stack-fcall \ stack-fcall-attach \ stack-fcall-mangled \ status-none-threads \ status-unfinished-threads \ + so_peercred--pidns-translation \ syslog-success \ threads-execve \ threads-execve--quiet-thread-execve \ @@ -223,6 +251,9 @@ check_PROGRAMS = $(PURE_EXECUTABLES) \ vfork-f \ wait4-v \ waitid-v \ + xetpgid--pidns-translation \ + xetpriority--pidns-translation \ + xet_robust_list--pidns-translation \ zeroargc \ # end of check_PROGRAMS @@ -310,6 +341,7 @@ DECODER_TESTS = \ int_0x80.test \ inotify_init-y.test \ ioctl.test \ + ioctl_block--pidns-translation.test \ ioctl_evdev-success.test \ ipc_msgbuf.test \ kern_features-fault.test \ @@ -381,12 +413,15 @@ MISC_TESTS = \ filtering_fd-syntax.test \ filtering_syscall-syntax.test \ first_exec_failure.test \ + fork--pidns-translation.test \ get_regs.test \ + gettid--pidns-translation.test \ inject-nf.test \ interactive_block.test \ kill_child.test \ localtime.test \ looping_threads.test \ + netlink_audit--pidns-translation.test \ opipe.test \ options-syntax.test \ pc.test \ @@ -467,6 +502,7 @@ EXTRA_DIST = \ filter_seccomp.in \ filter_seccomp.sh \ filter-unavailable.expected \ + fork--pidns-translation.awk \ fstatat.c \ fstatx.c \ gen_pure_executables.sh \ diff --git a/tests/fcntl--pidns-translation.c b/tests/fcntl--pidns-translation.c new file mode 100644 index 00000000..e249424a --- /dev/null +++ b/tests/fcntl--pidns-translation.c @@ -0,0 +1,2 @@ +#define PIDNS_TRANSLATION +#include "fcntl.c" diff --git a/tests/fcntl-common.c b/tests/fcntl-common.c index 27694326..d9e29939 100644 --- a/tests/fcntl-common.c +++ b/tests/fcntl-common.c @@ -13,6 +13,8 @@ #include #include #include "flock.h" +#include "pidns.h" +#include "scno.h" #define FILE_LEN 4096 @@ -48,12 +50,14 @@ test_flock_einval(const int cmd, const char *name) fl->l_len = (TYPEOF_FLOCK_OFF_T) 0xdefaced2cafef00dULL; invoke_test_syscall(0, cmd, fl); + pidns_print_leader(); printf("%s(0, %s, {l_type=F_RDLCK, l_whence=SEEK_SET" ", l_start=%jd, l_len=%jd}) = %s\n", TEST_SYSCALL_STR, name, (intmax_t) fl->l_start, (intmax_t) fl->l_len, errstr); void *const bad_addr = (void *) fl + 1; invoke_test_syscall(0, cmd, bad_addr); + pidns_print_leader(); printf("%s(0, %s, %p) = %s\n", TEST_SYSCALL_STR, name, bad_addr, errstr); } @@ -72,12 +76,14 @@ test_flock64_einval(const int cmd, const char *name) fl->l_len = (TYPEOF_FLOCK_OFF_T) 0xdefaced2cafef00dULL; invoke_test_syscall(0, cmd, fl); + pidns_print_leader(); printf("%s(0, %s, {l_type=F_RDLCK, l_whence=SEEK_SET" ", l_start=%jd, l_len=%jd}) = %s\n", TEST_SYSCALL_STR, name, (intmax_t) fl->l_start, (intmax_t) fl->l_len, errstr); void *const bad_addr = (void *) fl + 1; invoke_test_syscall(0, cmd, bad_addr); + pidns_print_leader(); printf("%s(0, %s, %p) = %s\n", TEST_SYSCALL_STR, name, bad_addr, errstr); } @@ -94,6 +100,7 @@ test_flock(void) fl->l_len = FILE_LEN; long rc = invoke_test_syscall(0, F_SETLK, fl); + pidns_print_leader(); printf("%s(0, F_SETLK, {l_type=F_RDLCK, l_whence=SEEK_SET" ", l_start=0, l_len=%d}) = %s\n", TEST_SYSCALL_STR, FILE_LEN, errstr); @@ -101,11 +108,13 @@ test_flock(void) return; invoke_test_syscall(0, F_GETLK, fl); + pidns_print_leader(); printf("%s(0, F_GETLK, {l_type=F_UNLCK, l_whence=SEEK_SET" ", l_start=0, l_len=%d, l_pid=0}) = 0\n", TEST_SYSCALL_STR, FILE_LEN); invoke_test_syscall(0, F_SETLKW, fl); + pidns_print_leader(); printf("%s(0, F_SETLKW, {l_type=F_UNLCK, l_whence=SEEK_SET" ", l_start=0, l_len=%d}) = 0\n", TEST_SYSCALL_STR, FILE_LEN); @@ -124,6 +133,7 @@ test_flock64_ofd(void) fl->l_len = FILE_LEN; long rc = invoke_test_syscall(0, F_OFD_SETLK, fl); + pidns_print_leader(); printf("%s(0, F_OFD_SETLK, {l_type=F_RDLCK, l_whence=SEEK_SET" ", l_start=0, l_len=%d}) = %s\n", TEST_SYSCALL_STR, FILE_LEN, errstr); @@ -131,11 +141,13 @@ test_flock64_ofd(void) return; invoke_test_syscall(0, F_OFD_GETLK, fl); + pidns_print_leader(); printf("%s(0, F_OFD_GETLK, {l_type=F_UNLCK, l_whence=SEEK_SET" ", l_start=0, l_len=%d, l_pid=0}) = 0\n", TEST_SYSCALL_STR, FILE_LEN); invoke_test_syscall(0, F_OFD_SETLKW, fl); + pidns_print_leader(); printf("%s(0, F_OFD_SETLKW, {l_type=F_UNLCK, l_whence=SEEK_SET" ", l_start=0, l_len=%d}) = 0\n", TEST_SYSCALL_STR, FILE_LEN); @@ -167,18 +179,21 @@ test_flock64(void) static long test_f_owner_ex_type_pid(const int cmd, const char *const cmd_name, const int type, const char *const type_name, - pid_t pid) + enum pid_type pid_type, pid_t pid) { TAIL_ALLOC_OBJECT_CONST_PTR(struct_kernel_f_owner_ex, fo); fo->type = type; fo->pid = pid; long rc = invoke_test_syscall(0, cmd, fo); - printf("%s(0, %s, {type=%s, pid=%d}) = %s\n", - TEST_SYSCALL_STR, cmd_name, type_name, fo->pid, errstr); + pidns_print_leader(); + printf("%s(0, %s, {type=%s, pid=%d%s}) = %s\n", + TEST_SYSCALL_STR, cmd_name, type_name, + fo->pid, pidns_pid2str(pid_type), errstr); void *bad_addr = (void *) fo + 1; invoke_test_syscall(0, cmd, bad_addr); + pidns_print_leader(); printf("%s(0, %s, %p) = %s\n", TEST_SYSCALL_STR, cmd_name, bad_addr, errstr); @@ -187,35 +202,39 @@ test_f_owner_ex_type_pid(const int cmd, const char *const cmd_name, static void test_f_owner_ex_umove_or_printaddr(const int type, const char *const type_name, - pid_t pid) + enum pid_type pid_type, pid_t pid) { long rc = test_f_owner_ex_type_pid(ARG_STR(F_SETOWN_EX), - type, type_name, pid); + type, type_name, pid_type, pid); if (!rc) test_f_owner_ex_type_pid(ARG_STR(F_GETOWN_EX), - type, type_name, pid); + type, type_name, pid_type, pid); } static void test_f_owner_ex(void) { - static const struct { + struct { int type; const char *type_name; - pid_t pid[2]; + enum pid_type pid_type; + pid_t pid; } a[] = { - { ARG_STR(F_OWNER_TID), { 1234567890, 20 } }, - { ARG_STR(F_OWNER_PID), { 1298126790, 30 } }, - { ARG_STR(F_OWNER_PGRP), { 1294567890, 40 } } + { ARG_STR(F_OWNER_TID), PT_NONE, 1234567890 }, + { ARG_STR(F_OWNER_PID), PT_NONE, 1234567890 }, + { ARG_STR(F_OWNER_PGRP), PT_NONE, 1234567890 }, + { ARG_STR(F_OWNER_TID), PT_TID, 0 }, + { ARG_STR(F_OWNER_PID), PT_TGID, 0 }, + { ARG_STR(F_OWNER_PGRP), PT_PGID, 0 }, }; - for (unsigned int i = 0; i < ARRAY_SIZE(a); i++) { - for (unsigned int j = 0; j < ARRAY_SIZE(a[0].pid); j++) { - test_f_owner_ex_umove_or_printaddr(a[i].type, - a[i].type_name, - a[i].pid[j]); - } - } + a[3].pid = syscall(__NR_gettid); + a[4].pid = getpid(); + a[5].pid = getpgid(0); + + for (unsigned int i = 0; i < ARRAY_SIZE(a); i++) + test_f_owner_ex_umove_or_printaddr(a[i].type, a[i].type_name, + a[i].pid_type, a[i].pid); } #endif /* TEST_F_OWNER_EX */ @@ -228,6 +247,23 @@ struct fcntl_cmd_check { void (*print_flags)(long rc); }; +static void +test_xetown(void) +{ + const int pid = getpid(); + const char *pid_str = pidns_pid2str(PT_TGID); + + invoke_test_syscall(0, F_SETOWN, (void *) (intptr_t) pid); + pidns_print_leader(); + printf("%s(0, F_SETOWN, %d%s) = %s\n", + TEST_SYSCALL_STR, pid, pid_str, errstr); + + invoke_test_syscall(0, F_GETOWN, NULL); + pidns_print_leader(); + printf("%s(0, F_GETOWN) = %d%s\n", + TEST_SYSCALL_STR, pid, pid_str); +} + static void print_retval_flags(const struct fcntl_cmd_check *check, long rc) { @@ -243,12 +279,14 @@ static void test_other_set_cmd(const struct fcntl_cmd_check *check) { invoke_test_syscall(check->fd, check->cmd, (void *) check->arg); + pidns_print_leader(); printf("%s(%d, %s, %s) = %s\n", TEST_SYSCALL_STR, check->fd, check->cmd_str, check->arg_str, errstr); /* bad file fd */ invoke_test_syscall(-1, check->cmd, (void *) check->arg); + pidns_print_leader(); printf("%s(-1, %s, %s) = %s\n", TEST_SYSCALL_STR, check->cmd_str, check->arg_str, errstr); @@ -258,12 +296,14 @@ static void test_other_get_cmd(const struct fcntl_cmd_check *check) { long rc = invoke_test_syscall(check->fd, check->cmd, NULL); + pidns_print_leader(); printf("%s(%d, %s) = ", TEST_SYSCALL_STR, check->fd, check->cmd_str); print_retval_flags(check, rc); /* bad file fd */ invoke_test_syscall(-1, check->cmd, NULL); + pidns_print_leader(); printf("%s(-1, %s) = %s\n", TEST_SYSCALL_STR, check->cmd_str, errstr); } @@ -315,7 +355,6 @@ test_fcntl_others(void) { static const struct fcntl_cmd_check set_checks[] = { { 0, ARG_STR(F_SETFD), ARG_STR(FD_CLOEXEC) }, - { 0, ARG_STR(F_SETOWN), ARG_STR(20) }, #ifdef F_SETPIPE_SZ { 0, ARG_STR(F_SETPIPE_SZ), ARG_STR(4097) }, #endif @@ -336,7 +375,6 @@ test_fcntl_others(void) static const struct fcntl_cmd_check get_checks[] = { { 0, ARG_STR(F_GETFD), .print_flags = print_flags_getfd }, { 1, ARG_STR(F_GETFD), .print_flags = print_flags_getfd }, - { 0, ARG_STR(F_GETOWN) }, #ifdef F_GETPIPE_SZ { 0, ARG_STR(F_GETPIPE_SZ) }, #endif @@ -360,6 +398,8 @@ create_sample(void) int main(void) { + PIDNS_TEST_INIT; + create_sample(); test_flock(); test_flock64(); @@ -367,7 +407,9 @@ main(void) test_f_owner_ex(); #endif test_fcntl_others(); + test_xetown(); + pidns_print_leader(); puts("+++ exited with 0 +++"); return 0; } diff --git a/tests/fcntl.c b/tests/fcntl.c index f38b8afb..673c06e4 100644 --- a/tests/fcntl.c +++ b/tests/fcntl.c @@ -24,6 +24,7 @@ test_flock64_undecoded(const int cmd, const char *name) .l_len = 0xdefaced2cafef00dULL }; invoke_test_syscall(0, cmd, &fl); + pidns_print_leader(); printf("%s(0, %s, %p) = %s\n", TEST_SYSCALL_STR, name, &fl, errstr); } diff --git a/tests/fcntl64--pidns-translation.c b/tests/fcntl64--pidns-translation.c new file mode 100644 index 00000000..c6fdadd1 --- /dev/null +++ b/tests/fcntl64--pidns-translation.c @@ -0,0 +1,2 @@ +#define PIDNS_TRANSLATION +#include "fcntl64.c" diff --git a/tests/fcntl64.c b/tests/fcntl64.c index 78e53b0d..f7b3f2fb 100644 --- a/tests/fcntl64.c +++ b/tests/fcntl64.c @@ -27,6 +27,7 @@ test_flock64_lk64(void) fl->l_len = FILE_LEN; long rc = invoke_test_syscall(0, F_SETLK64, fl); + pidns_print_leader(); printf("%s(0, F_SETLK64, {l_type=F_RDLCK, l_whence=SEEK_SET" ", l_start=0, l_len=%d}) = %s\n", TEST_SYSCALL_STR, FILE_LEN, errstr); @@ -35,11 +36,13 @@ test_flock64_lk64(void) return; invoke_test_syscall(0, F_GETLK64, fl); + pidns_print_leader(); printf("%s(0, F_GETLK64, {l_type=F_UNLCK, l_whence=SEEK_SET" ", l_start=0, l_len=%d, l_pid=0}) = 0\n", TEST_SYSCALL_STR, FILE_LEN); invoke_test_syscall(0, F_SETLKW64, fl); + pidns_print_leader(); printf("%s(0, F_SETLKW64, {l_type=F_UNLCK, l_whence=SEEK_SET" ", l_start=0, l_len=%d}) = 0\n", TEST_SYSCALL_STR, FILE_LEN); diff --git a/tests/fork--pidns-translation.awk b/tests/fork--pidns-translation.awk new file mode 100644 index 00000000..ef6858f4 --- /dev/null +++ b/tests/fork--pidns-translation.awk @@ -0,0 +1,15 @@ +/fork/ { + match($0, "([0-9]+) in strace\x27s PID NS", a); + if (a[1]) + fork_pid = a[1] +} + +/exited with 0/ { + if (!exit_pid) + exit_pid = $1 +} + +END { + if (!fork_pid || !exit_pid || fork_pid != exit_pid) + exit 1 +} diff --git a/tests/fork--pidns-translation.c b/tests/fork--pidns-translation.c new file mode 100644 index 00000000..73c39d5d --- /dev/null +++ b/tests/fork--pidns-translation.c @@ -0,0 +1,69 @@ +/* + * Test PID namespace translation + * + * Copyright (c) 2020 ?kos Uzonyi + * All rights reserved. + * + * SPDX-License-Identifier: LGPL-2.1-or-later + */ + +#include "tests.h" +#include "scno.h" +#include "pidns.h" + +#ifdef __NR_fork + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +static int +fork_chain(int depth) +{ + if (!depth) + return 0; + + int pid = syscall(__NR_fork); + if (pid < 0) + return errno; + + if (!pid) + _exit(fork_chain(depth - 1)); + + int status; + if (wait(&status) < 0) + return errno; + + if (!WIFEXITED(status)) + return -1; + + return WEXITSTATUS(status); +} + +int main(void) +{ + check_ns_ioctl(); + + if (unshare(CLONE_NEWPID | CLONE_NEWUSER) < 0) { + if (errno == EPERM) + perror_msg_and_skip("unshare"); + + perror_msg_and_fail("unshare"); + } + + errno = fork_chain(2); + if (errno) + perror("fork_chain"); +} + +#else + +SKIP_MAIN_UNDEFINED("__NR_fork") + +#endif diff --git a/tests/fork--pidns-translation.test b/tests/fork--pidns-translation.test new file mode 100755 index 00000000..fa7ecda5 --- /dev/null +++ b/tests/fork--pidns-translation.test @@ -0,0 +1,16 @@ +#!/bin/sh +# +# Check pidns translation of fork's return value. +# +# Copyright (c) 2020 The strace developers. +# All rights reserved. +# +# SPDX-License-Identifier: LGPL-2.1-or-later + +. "${srcdir=.}/init.sh" + +require_min_kernel_version_or_skip 4.9 + +run_prog +run_strace -a6 --pidns-translation -f -e trace=fork $args +match_awk diff --git a/tests/gen_tests.in b/tests/gen_tests.in index 6f8e1420..10374a9e 100644 --- a/tests/gen_tests.in +++ b/tests/gen_tests.in @@ -93,7 +93,9 @@ fchown -a16 fchown32 -a18 fchownat fcntl -a8 +fcntl--pidns-translation test_pidns -a8 -e trace=fcntl fcntl64 -a8 +fcntl64--pidns-translation test_pidns -a8 -e trace=fcntl64 fdatasync -a14 file_handle -e trace=name_to_handle_at,open_by_handle_at file_ioctl +ioctl.test @@ -147,7 +149,9 @@ getgroups -a17 getgroups32 -a19 getpeername -a27 getpgrp -a10 +getpgrp--pidns-translation test_pidns -e trace=getpgrp -a10 getpid -a9 +getpid--pidns-translation test_pidns -e trace=getpid -a9 getppid -a10 getrandom -a32 -s3 getresgid -a25 @@ -157,6 +161,7 @@ getresuid32 -a27 getrlimit -a27 getrusage -v getsid -a10 +getsid--pidns-translation test_pidns -e trace=getsid -a10 getsockname -a27 gettid -a9 getuid-creds +getuid.test @@ -250,6 +255,7 @@ ioctl_watchdog +ioctl.test ioperm -a27 iopl -a8 ioprio -a18 -e trace=ioprio_get,ioprio_set +ioprio--pidns-translation test_pidns -a18 -e trace=ioprio_get,ioprio_set ioprio-Xabbrev -a18 -e trace=ioprio_get,ioprio_set -Xabbrev ioprio-Xraw -a18 -e trace=ioprio_get,ioprio_set -Xraw ioprio-Xverbose -a18 -e trace=ioprio_get,ioprio_set -Xverbose @@ -272,6 +278,7 @@ ipc_shm-Xraw +ipc.sh -Xraw -a19 ipc_shm-Xverbose +ipc.sh -Xverbose -a34 kcmp -a22 kcmp-y -a22 -y -e trace=kcmp +kcmp-y--pidns-translation test_pidns -a22 -y -e trace=kcmp kern_features -a16 kernel_version -a16 -v -e trace=bpf kernel_version-Xabbrev -a16 -Xabbrev -v -e trace=bpf @@ -284,6 +291,7 @@ keyctl-Xabbrev -a31 -s10 -e trace=keyctl -Xabbrev keyctl-Xraw -a13 -s10 -e trace=keyctl -Xraw keyctl-Xverbose -a41 -s10 -e trace=keyctl -Xverbose kill -a12 -esignal=none +kill--pidns-translation test_pidns -a12 -e trace=kill -esignal=none ksysent ../$NAME lchown -a30 lchown32 -a32 @@ -305,6 +313,7 @@ memfd_create-Xabbrev -Xabbrev -e trace=memfd_create memfd_create-Xraw -a30 -Xraw -e trace=memfd_create memfd_create-Xverbose -Xverbose -e trace=memfd_create migrate_pages -a33 +migrate_pages--pidns-translation test_pidns -a33 -e trace=migrate_pages mincore -a22 mkdir -a20 mkdirat -a28 @@ -335,6 +344,7 @@ move_pages -s3 move_pages-Xabbrev -s3 -e trace=move_pages -Xabbrev move_pages-Xraw -s3 -a36 -e trace=move_pages -Xraw move_pages-Xverbose -s3 -e trace=move_pages -Xverbose +move_pages--pidns-translation test_pidns -s3 -e trace=move_pages mq -a32 -e trace=mq_getsetattr,mq_open,mq_unlink mq_sendrecv -a14 -e trace=mq_open,mq_notify,mq_timedsend,mq_timedreceive,mq_unlink mq_sendrecv-read -eread=0 -a14 -e trace=mq_open,mq_notify,mq_timedsend,mq_timedreceive,mq_unlink @@ -354,6 +364,7 @@ net-packet_mreq-Xabbrev -e trace=setsockopt -Xabbrev net-packet_mreq-Xraw -e trace=setsockopt -Xraw net-packet_mreq-Xverbose -e trace=setsockopt -Xverbose net-sockaddr -a24 -e trace=connect +net-sockaddr--pidns-translation test_pidns -a24 -e trace=connect net-tpacket_req -e trace=setsockopt net-tpacket_stats -e trace=getsockopt net-yy-inet6 +net-yy-inet.test @@ -457,7 +468,9 @@ pidfd_open--decode-fd-socket -a17 -e decode-fd=socket -e trace=pidfd_open pidfd_open-P -a17 -P /dev/full -e trace=pidfd_open pidfd_open-y -a17 -y -e trace=pidfd_open pidfd_open-yy -a17 -yy -e trace=pidfd_open +pidfd_open--pidns-translation test_pidns -a17 -e trace=pidfd_open pidfd_send_signal +pidfd_send_signal--pidns-translation test_pidns -e trace=pidfd_send_signal pipe2 -a15 pkey_alloc -a17 pkey_free -a13 @@ -480,8 +493,11 @@ printstrn-umoven -s4096 -e signal=none -e trace=add_key printstrn-umoven-peekdata -e signal=none -e trace=add_key printstrn-umoven-undumpable -e signal=none -e trace=add_key prlimit64 +prlimit64--pidns-translation test_pidns -e trace=prlimit64 process_vm_readv -s5 -a37 +process_vm_readv--pidns-translation test_pidns -s5 -a37 -e trace=process_vm_readv process_vm_writev -s5 -a38 +process_vm_writev--pidns-translation test_pidns -s5 -a38 -e trace=process_vm_writev pselect6 ptrace -a23 -e signal=none ptrace_syscall_info -a35 -e signal=none -e trace=ptrace @@ -518,10 +534,12 @@ rmdir -a22 rt_sigpending -a20 rt_sigprocmask rt_sigqueueinfo -esignal=none +rt_sigqueueinfo--pidns-translation test_pidns -esignal=none -e trace=rt_sigqueueinfo rt_sigreturn -esignal='!USR1' rt_sigsuspend -a20 -esignal=none rt_sigtimedwait -a38 rt_tgsigqueueinfo -esignal=none +rt_tgsigqueueinfo--pidns-translation test_pidns -esignal=none -e trace=rt_tgsigqueueinfo s390_guarded_storage -a32 s390_guarded_storage-v -e trace=s390_guarded_storage -a32 -v s390_pci_mmio_read_write -e trace=s390_pci_mmio_read,s390_pci_mmio_write -a30 @@ -532,9 +550,13 @@ sched test_trace_expr times -e/sched sched_get_priority_mxx -a33 -e trace=sched_get_priority_min,sched_get_priority_max sched_rr_get_interval -a31 sched_xetaffinity -a28 -e trace=sched_getaffinity,sched_setaffinity +sched_xetaffinity--pidns-translation test_pidns -a28 -e trace=sched_getaffinity,sched_setaffinity sched_xetattr -a29 -e trace=sched_getattr,sched_setattr +sched_xetattr--pidns-translation test_pidns -a29 -e trace=sched_getattr,sched_setattr sched_xetparam -a23 -e trace=sched_getparam,sched_setparam +sched_xetparam--pidns-translation test_pidns -a23 -e trace=sched_getparam,sched_setparam sched_xetscheduler -a22 -e trace=sched_getscheduler,sched_setscheduler +sched_xetscheduler--pidns-translation test_pidns -a22 -e trace=sched_getscheduler,sched_setscheduler sched_yield -a14 seccomp-filter -e trace=seccomp seccomp-filter-v -v -e trace=seccomp @@ -581,6 +603,7 @@ sigaction -a31 siginfo -e trace=none signal -a25 -e signal=none -e trace='/^signal$' signal_receive -a16 -e trace=kill +signal_receive--pidns-translation test_pidns -a16 -e trace=kill signalfd4 sigpending -a15 sigprocmask -a34 @@ -592,6 +615,7 @@ so_peercred -e trace=getsockopt so_peercred-Xabbrev -e trace=getsockopt -Xabbrev so_peercred-Xraw -e trace=getsockopt -Xraw -a39 so_peercred-Xverbose -e trace=getsockopt -Xverbose +so_peercred--pidns-translation test_pidns -e trace=getsockopt sock_filter-v -v -e trace=getsockopt,setsockopt sock_filter-v-Xabbrev -v -e trace=getsockopt,setsockopt -X abbrev sock_filter-v-Xraw -a 37 -v -e trace=getsockopt,setsockopt -X raw @@ -721,7 +745,10 @@ waitpid -a28 xattr -a22 -e trace=getxattr,fgetxattr,lgetxattr,setxattr,fsetxattr,lsetxattr,listxattr,flistxattr,llistxattr,removexattr,fremovexattr,lremovexattr xattr-strings -a22 -s 4 -e trace=fsetxattr xet_robust_list -a24 -e trace=get_robust_list,set_robust_list +xet_robust_list--pidns-translation test_pidns -a24 -e trace=get_robust_list,set_robust_list xetitimer -a29 -e trace=setitimer,getitimer xetpgid -a11 -e trace=getpgid,setpgid -xetpriority -a29 -e trace=getpriority,setpriority +xetpgid--pidns-translation test_pidns -a11 -e trace=getpgid,setpgid +xetpriority -a27 -e trace=getpriority,setpriority +xetpriority--pidns-translation test_pidns -a27 -e trace=getpriority,setpriority xettimeofday -a20 -e trace=gettimeofday,settimeofday diff --git a/tests/getpgrp--pidns-translation.c b/tests/getpgrp--pidns-translation.c new file mode 100644 index 00000000..de8ceb33 --- /dev/null +++ b/tests/getpgrp--pidns-translation.c @@ -0,0 +1,2 @@ +#define PIDNS_TRANSLATION +#include "getpgrp.c" diff --git a/tests/getpgrp.c b/tests/getpgrp.c index 104f4811..3f0b9dd1 100644 --- a/tests/getpgrp.c +++ b/tests/getpgrp.c @@ -7,6 +7,7 @@ #include "tests.h" #include "scno.h" +#include "pidns.h" #ifdef __NR_getpgrp @@ -16,8 +17,13 @@ int main(void) { - printf("getpgrp() = %ld\n", syscall(__NR_getpgrp)); + PIDNS_TEST_INIT; + pidns_print_leader(); + printf("getpgrp() = %d%s\n", (int) syscall(__NR_getpgrp), + pidns_pid2str(PT_PGID)); + + pidns_print_leader(); puts("+++ exited with 0 +++"); return 0; } diff --git a/tests/getpid--pidns-translation.c b/tests/getpid--pidns-translation.c new file mode 100644 index 00000000..94b12a1a --- /dev/null +++ b/tests/getpid--pidns-translation.c @@ -0,0 +1,2 @@ +#define PIDNS_TRANSLATION +#include "getpid.c" diff --git a/tests/getpid.c b/tests/getpid.c index 988f19d5..7ec4e6e8 100644 --- a/tests/getpid.c +++ b/tests/getpid.c @@ -7,6 +7,7 @@ #include "tests.h" #include "scno.h" +#include "pidns.h" #if defined __NR_getpid && (!defined __NR_getxpid || __NR_getxpid != __NR_getpid) @@ -16,7 +17,12 @@ int main(void) { - printf("getpid() = %ld\n", syscall(__NR_getpid)); + PIDNS_TEST_INIT; + + pidns_print_leader(); + printf("getpid() = %d%s\n", (int) syscall(__NR_getpid), + pidns_pid2str(PT_TGID)); + pidns_print_leader(); puts("+++ exited with 0 +++"); return 0; } diff --git a/tests/getsid--pidns-translation.c b/tests/getsid--pidns-translation.c new file mode 100644 index 00000000..7f983e87 --- /dev/null +++ b/tests/getsid--pidns-translation.c @@ -0,0 +1,2 @@ +#define PIDNS_TRANSLATION +#include "getsid.c" diff --git a/tests/getsid.c b/tests/getsid.c index 588ea4ab..3bf74734 100644 --- a/tests/getsid.c +++ b/tests/getsid.c @@ -6,15 +6,22 @@ */ #include "tests.h" +#include "pidns.h" + #include #include int main(void) { + PIDNS_TEST_INIT; + pid_t pid = getpid(); - printf("getsid(%d) = %d\n", pid, getsid(pid)); + pidns_print_leader(); + printf("getsid(%d%s) = %d%s\n", pid, pidns_pid2str(PT_TGID), + getsid(pid), pidns_pid2str(PT_SID)); + pidns_print_leader(); puts("+++ exited with 0 +++"); return 0; } diff --git a/tests/gettid--pidns-translation.c b/tests/gettid--pidns-translation.c new file mode 100644 index 00000000..500c3213 --- /dev/null +++ b/tests/gettid--pidns-translation.c @@ -0,0 +1,2 @@ +#define PIDNS_TRANSLATION +#include "gettid.c" diff --git a/tests/gettid--pidns-translation.test b/tests/gettid--pidns-translation.test new file mode 100755 index 00000000..b9773e04 --- /dev/null +++ b/tests/gettid--pidns-translation.test @@ -0,0 +1,19 @@ +#!/bin/sh +# +# Check pidns translation of gettid's return value. +# +# Copyright (c) 2020 The strace developers. +# All rights reserved. +# +# SPDX-License-Identifier: LGPL-2.1-or-later + +. "${srcdir=.}/init.sh" + +require_min_kernel_version_or_skip 4.9 + +run_prog > /dev/null +run_strace -a9 --pidns-translation -f -e trace=gettid $args > "$EXP" +parent_pid="$(tail -n 2 $LOG | head -n 1 | cut -d' ' -f1)" +init_pid="$(tail -n 1 $LOG | cut -d' ' -f1)" +grep -E -v "^($parent_pid|$init_pid) " "$LOG" | uniq > "$OUT" +match_diff "$OUT" "$EXP" diff --git a/tests/gettid.c b/tests/gettid.c index d38918dd..314d9c2c 100644 --- a/tests/gettid.c +++ b/tests/gettid.c @@ -9,11 +9,17 @@ #include #include #include "scno.h" +#include "pidns.h" int main(void) { - printf("gettid() = %ld\n", syscall(__NR_gettid)); + PIDNS_TEST_INIT; + + pidns_print_leader(); + printf("gettid() = %d%s\n", (int) syscall(__NR_gettid), + pidns_pid2str(PT_TID)); + pidns_print_leader(); puts("+++ exited with 0 +++"); return 0; } diff --git a/tests/ioctl_block--pidns-translation.c b/tests/ioctl_block--pidns-translation.c new file mode 100644 index 00000000..5eed6076 --- /dev/null +++ b/tests/ioctl_block--pidns-translation.c @@ -0,0 +1,2 @@ +#define PIDNS_TRANSLATION +#include "ioctl_block.c" diff --git a/tests/ioctl_block--pidns-translation.test b/tests/ioctl_block--pidns-translation.test new file mode 100755 index 00000000..bb45f695 --- /dev/null +++ b/tests/ioctl_block--pidns-translation.test @@ -0,0 +1,24 @@ +#!/bin/sh +# +# Check ioctl syscall decoding. +# +# Copyright (c) 2020 The strace developers. +# All rights reserved. +# +# SPDX-License-Identifier: LGPL-2.1-or-later + +. "${srcdir=.}/init.sh" + +require_min_kernel_version_or_skip 4.9 + +check_prog head +check_prog tail +check_prog cut +check_prog grep + +run_prog > /dev/null +run_strace --pidns-translation -f -a16 -e trace=ioctl $@ $args > "$EXP" +parent_pid="$(tail -n 2 $LOG | head -n 1 | cut -d' ' -f1)" +init_pid="$(tail -n 1 $LOG | cut -d' ' -f1)" +grep -E -v "^($parent_pid|$init_pid) |ioctl\([0123][,<]" "$LOG" > "$OUT" +match_diff "$OUT" "$EXP" diff --git a/tests/ioctl_block.c b/tests/ioctl_block.c index 0afe27f7..8a345f4e 100644 --- a/tests/ioctl_block.c +++ b/tests/ioctl_block.c @@ -9,7 +9,9 @@ */ #include "tests.h" +#include "pidns.h" #include +#include #include #include #include @@ -41,12 +43,15 @@ static struct xlat_data block_argless[] = { #define TEST_NULL_ARG(cmd) \ do { \ ioctl(-1, cmd, 0); \ + pidns_print_leader(); \ printf("ioctl(-1, %s, NULL) = -1 EBADF (%m)\n", #cmd); \ } while (0) int main(void) { + PIDNS_TEST_INIT; + TEST_NULL_ARG(BLKBSZGET); TEST_NULL_ARG(BLKBSZSET); TEST_NULL_ARG(BLKFRAGET); @@ -91,18 +96,22 @@ main(void) #endif ioctl(-1, BLKRASET, lmagic); + pidns_print_leader(); printf("ioctl(-1, BLKRASET, %lu) = -1 EBADF (%m)\n", lmagic); ioctl(-1, BLKFRASET, lmagic); + pidns_print_leader(); printf("ioctl(-1, BLKFRASET, %lu) = -1 EBADF (%m)\n", lmagic); TAIL_ALLOC_OBJECT_CONST_PTR(int, val_int); *val_int = magic; ioctl(-1, BLKROSET, val_int); + pidns_print_leader(); printf("ioctl(-1, BLKROSET, [%d]) = -1 EBADF (%m)\n", *val_int); ioctl(-1, BLKBSZSET, val_int); + pidns_print_leader(); printf("ioctl(-1, BLKBSZSET, [%d]) = -1 EBADF (%m)\n", *val_int); uint64_t *pair_int64 = tail_alloc(sizeof(*pair_int64) * 2); @@ -111,18 +120,21 @@ main(void) #ifdef BLKDISCARD ioctl(-1, BLKDISCARD, pair_int64); + pidns_print_leader(); printf("ioctl(-1, BLKDISCARD, [%" PRIu64 ", %" PRIu64 "])" " = -1 EBADF (%m)\n", pair_int64[0], pair_int64[1]); #endif #ifdef BLKSECDISCARD ioctl(-1, BLKSECDISCARD, pair_int64); + pidns_print_leader(); printf("ioctl(-1, BLKSECDISCARD, [%" PRIu64 ", %" PRIu64 "])" " = -1 EBADF (%m)\n", pair_int64[0], pair_int64[1]); #endif #ifdef BLKZEROOUT ioctl(-1, BLKZEROOUT, pair_int64); + pidns_print_leader(); printf("ioctl(-1, BLKZEROOUT, [%" PRIu64 ", %" PRIu64 "])" " = -1 EBADF (%m)\n", pair_int64[0], pair_int64[1]); #endif @@ -134,6 +146,7 @@ main(void) blkpg->data = (void *) (unsigned long) 0xcafef00dfffffeedULL; ioctl(-1, BLKPG, blkpg); + pidns_print_leader(); printf("ioctl(-1, BLKPG, {op=%s, flags=%d, datalen=%d" ", data=%#lx}) = -1 EBADF (%m)\n", "BLKPG_RESIZE_PARTITION", blkpg->flags, blkpg->datalen, @@ -149,6 +162,7 @@ main(void) blkpg->data = bp; ioctl(-1, BLKPG, blkpg); + pidns_print_leader(); printf("ioctl(-1, BLKPG, {op=%s, flags=%d, datalen=%d" ", data={start=%lld, length=%lld, pno=%d" ", devname=\"%.*s\"..., volname=\"%.*s\"...}})" @@ -162,25 +176,31 @@ main(void) #if defined BLKTRACESETUP && defined HAVE_STRUCT_BLK_USER_TRACE_SETUP TAIL_ALLOC_OBJECT_CONST_PTR(struct blk_user_trace_setup, buts); fill_memory(buts, sizeof(*buts)); + buts->pid = getpid(); ioctl(-1, BLKTRACESETUP, buts); + pidns_print_leader(); printf("ioctl(-1, BLKTRACESETUP, {act_mask=%hu, buf_size=%u, buf_nr=%u" - ", start_lba=%" PRI__u64 ", end_lba=%" PRI__u64 ", pid=%d})" + ", start_lba=%" PRI__u64 ", end_lba=%" PRI__u64 ", pid=%d%s})" " = -1 EBADF (%m)\n", buts->act_mask, buts->buf_size, buts->buf_nr, - buts->start_lba, buts->end_lba, buts->pid); + buts->start_lba, buts->end_lba, buts->pid, + pidns_pid2str(PT_TGID)); #endif unsigned int i; for (i = 0; i < ARRAY_SIZE(block_argless); ++i) { ioctl(-1, (unsigned long) block_argless[i].val, lmagic); + pidns_print_leader(); printf("ioctl(-1, %s) = -1 EBADF (%m)\n", block_argless[i].str); } ioctl(-1, _IOC(_IOC_READ, 0x12, 0xfe, 0xff), lmagic); + pidns_print_leader(); printf("ioctl(-1, %s, %#lx) = -1 EBADF (%m)\n", "_IOC(_IOC_READ, 0x12, 0xfe, 0xff)", lmagic); + pidns_print_leader(); puts("+++ exited with 0 +++"); return 0; } diff --git a/tests/ioprio--pidns-translation.c b/tests/ioprio--pidns-translation.c new file mode 100644 index 00000000..bcb49a8b --- /dev/null +++ b/tests/ioprio--pidns-translation.c @@ -0,0 +1,2 @@ +#define PIDNS_TRANSLATION +#include "ioprio.c" diff --git a/tests/ioprio.c b/tests/ioprio.c index 5e1e1194..110df063 100644 --- a/tests/ioprio.c +++ b/tests/ioprio.c @@ -9,8 +9,8 @@ */ #include "tests.h" - #include "scno.h" +#include "pidns.h" #if defined(__NR_ioprio_get) && defined(__NR_ioprio_set) @@ -30,12 +30,18 @@ enum { int main(void) { + PIDNS_TEST_INIT; + static const kernel_ulong_t bogus_which = (kernel_ulong_t) 0xdeadfacefa57beefULL; static const kernel_ulong_t bogus_who = (kernel_ulong_t) 0xbadc0dedda7a1057ULL; static const kernel_ulong_t bogus_ioprio = (kernel_ulong_t) 0xdec0ded1facefeedULL; + + const int pid = getpid(); + const int pgid = getpgid(0); + # if !XLAT_RAW static const char * const bogus_ioprio_str = "IOPRIO_PRIO_VALUE(0x7d677 /* IOPRIO_CLASS_??? */, 7917)"; @@ -46,6 +52,7 @@ main(void) rc = syscall(__NR_ioprio_get, bogus_which, bogus_who); errstr = sprintrc(rc); + pidns_print_leader(); # if XLAT_RAW printf("ioprio_get(%#x, %d) = %s\n", (int) bogus_which, (int) bogus_who, errstr); @@ -54,42 +61,52 @@ main(void) (int) bogus_which, (int) bogus_who, errstr); # endif - rc = syscall(__NR_ioprio_get, 1, 0); + rc = syscall(__NR_ioprio_get, 1, pid); errstr = sprintrc(rc); + pidns_print_leader(); + printf("ioprio_get("); # if XLAT_RAW - printf("ioprio_get(0x1, 0) = %s\n", errstr); + printf("0x1, "); +# elif XLAT_VERBOSE + printf("0x1 /* IOPRIO_WHO_PROCESS */, "); # else /* XLAT_ABBREV */ -# if XLAT_VERBOSE - printf("ioprio_get(0x1 /* IOPRIO_WHO_PROCESS */, 0) = %s", errstr); -# else - printf("ioprio_get(IOPRIO_WHO_PROCESS, 0) = %s", errstr); -# endif + printf("IOPRIO_WHO_PROCESS, "); +# endif + printf("%d%s) = %s", pid, pidns_pid2str(PT_TGID), errstr); +# if !XLAT_RAW if (rc >= 0) { printf(" (IOPRIO_PRIO_VALUE("); printxval(ioprio_class, (unsigned int) rc >> 13, "IOPRIO_CLASS_???"); printf(", %u))", (unsigned int) rc & 0x1fff); } - puts(""); # endif + puts(""); - rc = syscall(__NR_ioprio_set, 2, 0, 8191); + rc = syscall(__NR_ioprio_set, 2, pgid, 8191); errstr = sprintrc(rc); + pidns_print_leader(); + printf("ioprio_set("); # if XLAT_RAW - printf("ioprio_set(%#x, 0, 8191) = %s\n", 2, errstr); + printf("%#x", 2); # elif XLAT_VERBOSE - printf("ioprio_set(%#x /* IOPRIO_WHO_PGRP */, 0, 8191" - " /* IOPRIO_PRIO_VALUE(0 /* IOPRIO_CLASS_NONE */, 8191) */)" - " = %s\n", - 2, errstr); + printf("%#x /* IOPRIO_WHO_PGRP */", 2); # else /* XLAT_ABBREV */ - printf("ioprio_set(IOPRIO_WHO_PGRP, 0" - ", IOPRIO_PRIO_VALUE(IOPRIO_CLASS_NONE, 8191)) = %s\n", - errstr); + printf("IOPRIO_WHO_PGRP"); +# endif + printf(", %d%s", pgid, pidns_pid2str(PT_PGID)); +# if XLAT_RAW + printf(", 8191)"); +# elif XLAT_VERBOSE + printf(", 8191 /* IOPRIO_PRIO_VALUE(0 /* IOPRIO_CLASS_NONE */, 8191) */)"); +# else /* XLAT_ABBREV */ + printf(", IOPRIO_PRIO_VALUE(IOPRIO_CLASS_NONE, 8191))"); # endif + printf(" = %s\n", errstr); rc = syscall(__NR_ioprio_set, bogus_which, bogus_who, bogus_ioprio); errstr = sprintrc(rc); + pidns_print_leader(); # if XLAT_RAW printf("ioprio_set(%#x, %d, %d) = %s\n", (int) bogus_which, (int) bogus_who, (int) bogus_ioprio, @@ -104,6 +121,7 @@ main(void) errstr); # endif + pidns_print_leader(); puts("+++ exited with 0 +++"); return 0; diff --git a/tests/kcmp-y--pidns-translation.c b/tests/kcmp-y--pidns-translation.c new file mode 100644 index 00000000..f54d94cc --- /dev/null +++ b/tests/kcmp-y--pidns-translation.c @@ -0,0 +1,2 @@ +#define PIDNS_TRANSLATION +#include "kcmp-y.c" diff --git a/tests/kcmp.c b/tests/kcmp.c index dc5ba9a4..ce705ad0 100644 --- a/tests/kcmp.c +++ b/tests/kcmp.c @@ -9,8 +9,8 @@ */ #include "tests.h" - #include "scno.h" +#include "pidns.h" #ifdef __NR_kcmp @@ -101,7 +101,11 @@ do_kcmp(kernel_ulong_t pid1, kernel_ulong_t pid2, kernel_ulong_t type, rc = syscall(__NR_kcmp, pid1, pid2, type, idx1, idx2); errstr = sprintrc(rc); - printf("kcmp(%d, %d, ", (int) pid1, (int) pid2); + const char *pid_str = pidns_pid2str(PT_TGID); + pidns_print_leader(); + printf("kcmp(%d%s, %d%s, ", + (int) pid1, (int) pid1 == getpid() ? pid_str : "", + (int) pid2, (int) pid2 == getpid() ? pid_str : ""); if (type_str) printf("%s", type_str); @@ -146,6 +150,8 @@ do_kcmp(kernel_ulong_t pid1, kernel_ulong_t pid2, kernel_ulong_t type, int main(void) { + PIDNS_TEST_INIT; + static const kernel_ulong_t bogus_pid1 = (kernel_ulong_t) 0xdeadca75face1057ULL; static const kernel_ulong_t bogus_pid2 = @@ -221,6 +227,7 @@ main(void) (uintptr_t) slot, 1); } + pidns_print_leader(); puts("+++ exited with 0 +++"); return 0; diff --git a/tests/kill--pidns-translation.c b/tests/kill--pidns-translation.c new file mode 100644 index 00000000..4736ca14 --- /dev/null +++ b/tests/kill--pidns-translation.c @@ -0,0 +1,2 @@ +#define PIDNS_TRANSLATION +#include "kill.c" diff --git a/tests/kill.c b/tests/kill.c index f7d9341e..17de35da 100644 --- a/tests/kill.c +++ b/tests/kill.c @@ -11,6 +11,7 @@ #include "tests.h" #include "scno.h" +#include "pidns.h" #ifdef __NR_kill @@ -26,6 +27,8 @@ handler(int sig) int main(void) { + PIDNS_TEST_INIT; + const struct sigaction act = { .sa_handler = handler }; if (sigaction(SIGALRM, &act, NULL)) perror_msg_and_fail("sigaction"); @@ -37,18 +40,23 @@ main(void) perror_msg_and_fail("sigprocmask"); const int pid = getpid(); + const char *pid_str = pidns_pid2str(PT_TGID); long rc = syscall(__NR_kill, pid, (long) 0xdefaced00000000ULL | SIGALRM); - printf("kill(%d, SIGALRM) = %ld\n", pid, rc); + pidns_print_leader(); + printf("kill(%d%s, SIGALRM) = %ld\n", pid, pid_str, rc); const long big_pid = (long) 0xfacefeedbadc0dedULL; const long big_sig = (long) 0xdeadbeefcafef00dULL; rc = syscall(__NR_kill, big_pid, big_sig); + pidns_print_leader(); printf("kill(%d, %d) = %ld %s (%m)\n", (int) big_pid, (int) big_sig, rc, errno2name()); rc = syscall(__NR_kill, (long) 0xdefaced00000000ULL | pid, 0); - printf("kill(%d, 0) = %ld\n", pid, rc); + pidns_print_leader(); + printf("kill(%d%s, 0) = %ld\n", pid, pid_str, rc); + pidns_print_leader(); puts("+++ exited with 0 +++"); return 0; } diff --git a/tests/migrate_pages--pidns-translation.c b/tests/migrate_pages--pidns-translation.c new file mode 100644 index 00000000..ec34938d --- /dev/null +++ b/tests/migrate_pages--pidns-translation.c @@ -0,0 +1,2 @@ +#define PIDNS_TRANSLATION +#include "migrate_pages.c" diff --git a/tests/migrate_pages.c b/tests/migrate_pages.c index 2dfba49c..390b490b 100644 --- a/tests/migrate_pages.c +++ b/tests/migrate_pages.c @@ -10,6 +10,7 @@ #include "tests.h" #include "scno.h" +#include "pidns.h" #ifdef __NR_migrate_pages @@ -19,11 +20,21 @@ int main(void) { - const long pid = (long) 0xfacefeedffffffffULL; + PIDNS_TEST_INIT; + + const long pid = (long) 0xfacefeed00000000ULL | getpid(); long rc = syscall(__NR_migrate_pages, pid, 0, 0, 0); - printf("migrate_pages(%d, 0, NULL, NULL) = %ld %s (%m)\n", - (int) pid, rc, errno2name()); + pidns_print_leader(); + printf("migrate_pages(%d%s, 0, NULL, NULL) = %ld", + (int) pid, pidns_pid2str(PT_TGID), rc); + + if (rc < 0) + printf(" %s (%m)\n", errno2name()); + else + printf("\n"); + + pidns_print_leader(); puts("+++ exited with 0 +++"); return 0; } diff --git a/tests/move_pages--pidns-translation.c b/tests/move_pages--pidns-translation.c new file mode 100644 index 00000000..8498e399 --- /dev/null +++ b/tests/move_pages--pidns-translation.c @@ -0,0 +1,2 @@ +#define PIDNS_TRANSLATION +#include "move_pages.c" diff --git a/tests/move_pages.c b/tests/move_pages.c index e00fd1ac..56843158 100644 --- a/tests/move_pages.c +++ b/tests/move_pages.c @@ -10,6 +10,7 @@ #include "tests.h" #include "scno.h" +#include "pidns.h" #ifdef __NR_move_pages @@ -122,15 +123,20 @@ print_status_array(const int *const status, const unsigned long count) } static void -print_stat_pages(const unsigned long pid, const unsigned long count, - const void **const pages, int *const status) +print_stat_pages(const unsigned long pid, + const char *pid_str, + const unsigned long count, + const void **const pages, + int *const status) { const unsigned long flags = (unsigned long) 0xfacefeed00000002ULL; long rc = syscall(__NR_move_pages, pid, count, pages, NULL, status, flags); const char *errstr = sprintrc(rc); - printf("move_pages(%d, %lu, ", (int) pid, count); + pidns_print_leader(); + printf("move_pages(%d%s, %lu, ", (int) pid, pid_str, + count); print_page_array(pages, count, 0); printf(", NULL, "); if (rc) { @@ -152,6 +158,7 @@ print_stat_pages(const unsigned long pid, const unsigned long count, static void print_move_pages(const unsigned long pid, + const char *pid_str, unsigned long count, const unsigned int offset, const void **const pages, @@ -164,7 +171,9 @@ print_move_pages(const unsigned long pid, long rc = syscall(__NR_move_pages, pid, count, pages, nodes, status, flags); const char *errstr = sprintrc(rc); - printf("move_pages(%d, %lu, ", (int) pid, count); + pidns_print_leader(); + printf("move_pages(%d%s, %lu, ", (int) pid, pid_str, + count); print_page_array(pages, count, offset); printf(", "); print_node_array(nodes, count, offset); @@ -185,8 +194,11 @@ print_move_pages(const unsigned long pid, int main(void) { + PIDNS_TEST_INIT; + const unsigned long pid = (unsigned long) 0xfacefeed00000000ULL | getpid(); + const char *pid_str = pidns_pid2str(PT_TGID); unsigned long count = 1; const unsigned page_size = get_page_size(); const void *const page = tail_alloc(page_size); @@ -195,40 +207,41 @@ main(void) TAIL_ALLOC_OBJECT_VAR_PTR(int, nodes); TAIL_ALLOC_OBJECT_VAR_PTR(int, status); - print_stat_pages(pid, 0, pages, status); - print_move_pages(pid, 0, 0, pages, nodes, status); - print_move_pages(pid, 0, 1, pages + 1, nodes + 1, status + 1); + print_stat_pages(pid, pid_str, 0, pages, status); + print_move_pages(pid, pid_str, 0, 0, pages, nodes, status); + print_move_pages(pid, pid_str, 0, 1, pages + 1, nodes + 1, status + 1); *pages = page; - print_stat_pages(pid, count, pages, status); + print_stat_pages(pid, pid_str, count, pages, status); *nodes = 0xdeadbee1; - print_move_pages(pid, count, 0, pages, nodes, status); - print_move_pages(pid, count, 1, pages, nodes, status); + print_move_pages(pid, pid_str, count, 0, pages, nodes, status); + print_move_pages(pid, pid_str, count, 1, pages, nodes, status); ++count; --status; *(--pages) = efault; - print_stat_pages(pid, count, pages, status); + print_stat_pages(pid, pid_str, count, pages, status); *(--nodes) = 0xdeadbee2; - print_move_pages(pid, count, 0, pages, nodes, status); - print_move_pages(pid, count, 1, pages, nodes, status); + print_move_pages(pid, pid_str, count, 0, pages, nodes, status); + print_move_pages(pid, pid_str, count, 1, pages, nodes, status); ++count; --status; *(--pages) = nodes; - print_stat_pages(pid, count, pages, status); + print_stat_pages(pid, pid_str, count, pages, status); *(--nodes) = 0xdeadbee3; - print_move_pages(pid, count, 0, pages, nodes, status); - print_move_pages(pid, count, 1, pages, nodes, status); + print_move_pages(pid, pid_str, count, 0, pages, nodes, status); + print_move_pages(pid, pid_str, count, 1, pages, nodes, status); ++count; --status; *(--pages) = status; - print_stat_pages(pid, count, pages, status); + print_stat_pages(pid, pid_str, count, pages, status); *(--nodes) = 0xdeadbee4; - print_move_pages(pid, count, 0, pages, nodes, status); - print_move_pages(pid, count, 1, pages, nodes, status); + print_move_pages(pid, pid_str, count, 0, pages, nodes, status); + print_move_pages(pid, pid_str, count, 1, pages, nodes, status); + pidns_print_leader(); puts("+++ exited with 0 +++"); return 0; } diff --git a/tests/net-sockaddr--pidns-translation.c b/tests/net-sockaddr--pidns-translation.c new file mode 100644 index 00000000..ff432bf4 --- /dev/null +++ b/tests/net-sockaddr--pidns-translation.c @@ -0,0 +1,2 @@ +#define PIDNS_TRANSLATION +#include "net-sockaddr.c" diff --git a/tests/net-sockaddr.c b/tests/net-sockaddr.c index 4fc9da6e..b9cd46fd 100644 --- a/tests/net-sockaddr.c +++ b/tests/net-sockaddr.c @@ -9,6 +9,7 @@ */ #include "tests.h" +#include "pidns.h" #include #include #include @@ -40,18 +41,21 @@ check_un(void) memset(un->sun_path, '0', sizeof(un->sun_path)); unsigned int len = sizeof(*un); int ret = connect(-1, (void *) un, len); + pidns_print_leader(); printf("connect(-1, {sa_family=AF_UNIX, sun_path=\"%.*u\"}" ", %u) = %d EBADF (%m)\n", (int) sizeof(un->sun_path), 0, len, ret); un->sun_path[1] = 0; ret = connect(-1, (void *) un, len); + pidns_print_leader(); printf("connect(-1, {sa_family=AF_UNIX, sun_path=\"%u\"}, %u)" " = %d EBADF (%m)\n", 0, len, ret); un->sun_path[0] = 0; un->sun_path[2] = 1; ret = connect(-1, (void *) un, len); + pidns_print_leader(); printf("connect(-1, {sa_family=AF_UNIX, sun_path=@\"\\0\\001%.*u\"}" ", %u) = %d EBADF (%m)\n", (int) sizeof(un->sun_path) - 3, 0, len, ret); @@ -61,12 +65,14 @@ check_un(void) memset(un->sun_path, '0', sizeof(un->sun_path)); len = sizeof(*un) + 2; ret = connect(-1, (void *) un, len); + pidns_print_leader(); printf("connect(-1, {sa_family=AF_UNIX, sun_path=\"%.*u\"}" ", %u) = %d EBADF (%m)\n", (int) sizeof(un->sun_path), 0, len, ret); un->sun_path[0] = 0; ret = connect(-1, (void *) un, len); + pidns_print_leader(); printf("connect(-1, {sa_family=AF_UNIX, sun_path=@\"%.*u\"}" ", %u) = %d EBADF (%m)\n", (int) sizeof(un->sun_path) - 1, 0, len, ret); @@ -75,18 +81,21 @@ check_un(void) un->sun_family = AF_UNIX; len = sizeof(*un) - 2; ret = connect(-1, (void *) un, len); + pidns_print_leader(); printf("connect(-1, {sa_family=AF_UNIX, sun_path=\"%.*u\"}" ", %u) = %d EBADF (%m)\n", (int) sizeof(un->sun_path) - 2, 0, len, ret); un->sun_path[0] = 0; ret = connect(-1, (void *) un, len); + pidns_print_leader(); printf("connect(-1, {sa_family=AF_UNIX, sun_path=@\"%.*u\"}" ", %u) = %d EBADF (%m)\n", (int) sizeof(un->sun_path) - 3, 0, len, ret); len = sizeof(*un); ret = connect(-1, (void *) un, len); + pidns_print_leader(); printf("connect(-1, %p, %u) = %d EBADF (%m)\n", un, len, ret); un = tail_alloc(sizeof(struct sockaddr_storage)); @@ -94,12 +103,14 @@ check_un(void) memset(un->sun_path, '0', sizeof(un->sun_path)); len = sizeof(struct sockaddr_storage) + 1; ret = connect(-1, (void *) un, len); + pidns_print_leader(); printf("connect(-1, {sa_family=AF_UNIX, sun_path=\"%.*u\"}" ", %u) = %d EBADF (%m)\n", (int) sizeof(un->sun_path), 0, len, ret); un->sun_path[0] = 0; ret = connect(-1, (void *) un, len); + pidns_print_leader(); printf("connect(-1, {sa_family=AF_UNIX, sun_path=@\"%.*u\"}" ", %u) = %d EBADF (%m)\n", (int) sizeof(un->sun_path) - 1, 0, len, ret); @@ -117,6 +128,7 @@ check_in(void) in->sin_addr.s_addr = inet_addr(h_addr); unsigned int len = sizeof(*in); int ret = connect(-1, (void *) in, len); + pidns_print_leader(); printf("connect(-1, {sa_family=AF_INET, sin_port=htons(%hu)" ", sin_addr=inet_addr(\"%s\")}, %u) = %d EBADF (%m)\n", h_port, h_addr, len, ret); @@ -127,6 +139,7 @@ check_in(void) in->sin_addr.s_addr = inet_addr(h_addr); len = sizeof(*in) + 4; ret = connect(-1, (void *) in, len); + pidns_print_leader(); printf("connect(-1, {sa_family=AF_INET, sin_port=htons(%hu)" ", sin_addr=inet_addr(\"%s\")}, %u) = %d EBADF (%m)\n", h_port, h_addr, len, ret); @@ -137,6 +150,7 @@ check_in(void) in->sin_addr.s_addr = 0; len = sizeof(*in) - 4; ret = connect(-1, (void *) in, len); + pidns_print_leader(); printf("connect(-1, {sa_family=AF_INET, sa_data=\"%s\"}, %u)" " = %d EBADF (%m)\n", "\\0\\0\\0\\0\\0\\0\\377\\377\\377\\377", @@ -144,6 +158,7 @@ check_in(void) len = sizeof(*in); ret = connect(-1, (void *) in, len); + pidns_print_leader(); printf("connect(-1, %p, %u) = %d EBADF (%m)\n", in, len, ret); } @@ -155,6 +170,7 @@ check_in6_linklocal(struct sockaddr_in6 *const in6, const char *const h_addr) in6->sin6_scope_id = 0xfacefeed; unsigned int len = sizeof(*in6); int ret = connect(-1, (void *) in6, len); + pidns_print_leader(); printf("connect(-1, {sa_family=AF_INET6, sin6_port=htons(%hu)" ", sin6_flowinfo=htonl(%u)" ", inet_pton(AF_INET6, \"%s\", &sin6_addr)" @@ -166,7 +182,8 @@ check_in6_linklocal(struct sockaddr_in6 *const in6, const char *const h_addr) in6->sin6_scope_id = ifindex_lo(); if (in6->sin6_scope_id) { ret = connect(-1, (void *) in6, len); - printf("connect(-1, {sa_family=AF_INET6, sin6_port=htons(%hu)" + pidns_print_leader(); + printf("connect(-1, {sa_family=AF_INET6, sin6_port=htons(%hu)" ", sin6_flowinfo=htonl(%u)" ", inet_pton(AF_INET6, \"%s\", &sin6_addr)" ", sin6_scope_id=%s}, %u)" @@ -191,6 +208,7 @@ check_in6(void) in6->sin6_scope_id = 0xfacefeed; unsigned int len = sizeof(*in6); int ret = connect(-1, (void *) in6, len); + pidns_print_leader(); printf("connect(-1, {sa_family=AF_INET6, sin6_port=htons(%hu)" ", sin6_flowinfo=htonl(%u)" ", inet_pton(AF_INET6, \"%s\", &sin6_addr)" @@ -209,6 +227,7 @@ check_in6(void) in6->sin6_scope_id = 0xfacefeed; len = sizeof(*in6) + 4; ret = connect(-1, (void *) in6, len); + pidns_print_leader(); printf("connect(-1, {sa_family=AF_INET6, sin6_port=htons(%hu)" ", sin6_flowinfo=htonl(%u)" ", inet_pton(AF_INET6, \"%s\", &sin6_addr)" @@ -223,6 +242,7 @@ check_in6(void) inet_pton(AF_INET6, h_addr, &in6->sin6_addr); len = sizeof(*in6) - sizeof(in6->sin6_scope_id); ret = connect(-1, (void *) in6, len); + pidns_print_leader(); printf("connect(-1, {sa_family=AF_INET6, sin6_port=htons(%hu)" ", sin6_flowinfo=htonl(%u)" ", inet_pton(AF_INET6, \"%s\", &sin6_addr)}, %u)" @@ -236,6 +256,7 @@ check_in6(void) memset(&in6->sin6_addr, '0', sizeof(in6->sin6_addr) - 4); len = sizeof(*in6) - sizeof(in6->sin6_scope_id) - 4; ret = connect(-1, (void *) in6, len); + pidns_print_leader(); printf("connect(-1, {sa_family=AF_INET6" ", sa_data=\"\\0\\0\\0\\0\\0\\000%.*u\"}, %u)" " = %d EBADF (%m)\n", @@ -244,6 +265,7 @@ check_in6(void) len = sizeof(*in6) - sizeof(in6->sin6_scope_id); ret = connect(-1, (void *) in6, len); + pidns_print_leader(); printf("connect(-1, %p, %u) = %d EBADF (%m)\n", in6, len, ret); } @@ -262,6 +284,7 @@ check_ipx(void) void *ipx = tail_memdup(&c_ipx, sizeof(c_ipx)); unsigned int len = sizeof(c_ipx); int ret = connect(-1, ipx, len); + pidns_print_leader(); printf("connect(-1, {sa_family=AF_IPX, sipx_port=htons(%u)" ", sipx_network=htonl(%#x)" ", sipx_node=[%#02x, %#02x, %#02x, %#02x, %#02x, %#02x]" @@ -316,18 +339,21 @@ check_ax25(void) fill_memory(sax, size); sax->fsa_ax25.sax25_family = AF_AX25; rc = connect(-1, sax_void, sizeof(struct sockaddr_ax25) - 1); + pidns_print_leader(); printf("connect(-1, {sa_family=AF_AX25, sa_data=\"\\202\\203\\204\\205" "\\206\\207\\210\\211\\212\\213\\214\\215\\216\"}, %zu) = %s\n", sizeof(struct sockaddr_ax25) - 1, sprintrc(rc)); memcpy(sax, &ax25, sizeof(ax25)); rc = connect(-1, sax_void, sizeof(struct sockaddr_ax25)); + pidns_print_leader(); printf("connect(-1, {sa_family=AF_AX25, fsa_ax25={sax25_call=VALID-13" ", sax25_ndigis=8}, fsa_digipeater=[/* ??? */]}, %zu) = %s\n", sizeof(struct sockaddr_ax25), sprintrc(rc)); sax->fsa_ax25.sax25_ndigis = 0; rc = connect(-1, sax_void, sizeof(struct sockaddr_ax25)); + pidns_print_leader(); printf("connect(-1, {sa_family=AF_AX25, sax25_call=VALID-13" ", sax25_ndigis=0}, %zu) = %s\n", sizeof(struct sockaddr_ax25), sprintrc(rc)); @@ -335,6 +361,7 @@ check_ax25(void) sax->fsa_ax25.sax25_ndigis = 8; size = sizeof(struct sockaddr_ax25) + sizeof(ax25_address) * 3 + 1; rc = connect(-1, sax_void, size); + pidns_print_leader(); printf("connect(-1, {sa_family=AF_AX25, fsa_ax25={sax25_call=VALID-13" ", sax25_ndigis=8}, fsa_digipeater" "=[{ax25_call=\"\\xa6\\xa0\\x82\\x40\\x86\\x8a\\x00\"" @@ -348,6 +375,7 @@ check_ax25(void) sax->fsa_digipeater[2].ax25_call[6] = 0x4; size = sizeof(struct sockaddr_ax25) + sizeof(ax25_address) * 4; rc = connect(-1, sax_void, size); + pidns_print_leader(); printf("connect(-1, {sa_family=AF_AX25, fsa_ax25={sax25_call=VALID-13" ", sax25_ndigis=8}, fsa_digipeater" "=[{ax25_call=\"\\xa6\\xa0\\x82\\x40\\x86\\x8a\\x00\"" @@ -365,7 +393,8 @@ check_ax25(void) for (size_t i = 0; i < 3; i++) { size = sizeof(ax25) + sizeof(ax25_address) * (i / 2); rc = connect(-1, sax_void, size); - printf("connect(-1, {sa_family=AF_AX25" + pidns_print_leader(); + printf("connect(-1, {sa_family=AF_AX25" ", fsa_ax25={sax25_call=VALID-13, sax25_ndigis=%d}" ", fsa_digipeater=[VALID2-7, OK-15, %s /* FINE-2 */" ", {ax25_call=\"\\xe6\\xda\\xc2\\xd8\\xd8\\xe6\\x12\"" @@ -427,13 +456,15 @@ check_x25(void) long rc; rc = connect(-1, x25_void, sizeof(c_x25) - 1); + pidns_print_leader(); printf("connect(-1, {sa_family=AF_X25" ", sa_data=\"0123456789abcde\"}, %zu) = %s\n", sizeof(c_x25) - 1, sprintrc(rc)); for (size_t i = 0; i < 2; i++) { rc = connect(-1, x25_void, sizeof(c_x25) + i); - printf("connect(-1, {sa_family=AF_X25" + pidns_print_leader(); + printf("connect(-1, {sa_family=AF_X25" ", sx25_addr={x25_addr=\"0123456789abcde\"...}" "}, %zu) = %s\n", sizeof(c_x25) + i, sprintrc(rc)); @@ -442,6 +473,7 @@ check_x25(void) struct sockaddr_x25 *const x25 = x25_void; x25->sx25_addr.x25_addr[10] = '\0'; rc = connect(-1, x25_void, sizeof(c_x25)); + pidns_print_leader(); printf("connect(-1, {sa_family=AF_X25" ", sx25_addr={x25_addr=\"0123456789\"}" "}, %zu) = %s\n", @@ -457,19 +489,21 @@ check_nl(void) nl->nl_groups = 0xfacefeed; unsigned int len = sizeof(*nl); int ret = connect(-1, (void *) nl, len); + pidns_print_leader(); printf("connect(-1, {sa_family=AF_NETLINK, nl_pid=%d" ", nl_groups=%#08x}, %u) = %d EBADF (%m)\n", nl->nl_pid, nl->nl_groups, len, ret); nl = ((void *) nl) - 4; nl->nl_family = AF_NETLINK; - nl->nl_pid = 1234567890; + nl->nl_pid = getpid(); nl->nl_groups = 0xfacefeed; len = sizeof(*nl) + 4; ret = connect(-1, (void *) nl, len); - printf("connect(-1, {sa_family=AF_NETLINK, nl_pid=%d" + pidns_print_leader(); + printf("connect(-1, {sa_family=AF_NETLINK, nl_pid=%d%s" ", nl_groups=%#08x}, %u) = %d EBADF (%m)\n", - nl->nl_pid, nl->nl_groups, len, ret); + nl->nl_pid, pidns_pid2str(PT_TGID), nl->nl_groups, len, ret); } static void @@ -487,6 +521,7 @@ check_ll(void) void *ll = tail_memdup(&c_ll, sizeof(c_ll)); unsigned int len = sizeof(c_ll); int ret = connect(-1, ll, len); + pidns_print_leader(); printf("connect(-1, {sa_family=AF_PACKET" ", sll_protocol=htons(ETH_P_ALL)" ", sll_ifindex=%u, sll_hatype=ARPHRD_ETHER" @@ -502,6 +537,7 @@ check_ll(void) ((struct sockaddr_ll *) ll)->sll_halen++; ret = connect(-1, ll, len); + pidns_print_leader(); printf("connect(-1, {sa_family=AF_PACKET" ", sll_protocol=htons(ETH_P_ALL)" ", sll_ifindex=%u, sll_hatype=ARPHRD_ETHER" @@ -517,6 +553,7 @@ check_ll(void) ((struct sockaddr_ll *) ll)->sll_halen = 0; ret = connect(-1, ll, len); + pidns_print_leader(); printf("connect(-1, {sa_family=AF_PACKET" ", sll_protocol=htons(ETH_P_ALL)" ", sll_ifindex=%u, sll_hatype=ARPHRD_ETHER" @@ -526,7 +563,8 @@ check_ll(void) ((struct sockaddr_ll *) ll)->sll_ifindex = ifindex_lo(); if (((struct sockaddr_ll *) ll)->sll_ifindex) { ret = connect(-1, ll, len); - printf("connect(-1, {sa_family=AF_PACKET" + pidns_print_leader(); + printf("connect(-1, {sa_family=AF_PACKET" ", sll_protocol=htons(ETH_P_ALL)" ", sll_ifindex=%s" ", sll_hatype=ARPHRD_ETHER" @@ -549,11 +587,13 @@ check_hci(void) unsigned int len = sizeof(*hci); int ret = connect(-1, (void *) hci, 4); + pidns_print_leader(); printf("connect(-1, {sa_family=AF_BLUETOOTH, hci_dev=htobs(%hu)" "}, 4) = %d EBADF (%m)\n", h_port, ret); ret = connect(-1, (void *) hci, len); + pidns_print_leader(); printf("connect(-1, {sa_family=AF_BLUETOOTH, hci_dev=htobs(%hu)" # ifdef HAVE_STRUCT_SOCKADDR_HCI_HCI_CHANNEL ", hci_channel=HCI_CHANNEL_RAW" @@ -572,6 +612,7 @@ check_sco(void) void *sco = tail_memdup(&c_sco, sizeof(c_sco)); unsigned int len = sizeof(c_sco); int ret = connect(-1, sco, len); + pidns_print_leader(); printf("connect(-1, {sa_family=AF_BLUETOOTH" ", sco_bdaddr=%02x:%02x:%02x:%02x:%02x:%02x" "}, %u) = %d EBADF (%m)\n", @@ -592,6 +633,7 @@ check_rc(void) void *rc = tail_memdup(&c_rc, sizeof(c_rc)); unsigned int len = sizeof(c_rc); int ret = connect(-1, rc, len); + pidns_print_leader(); printf("connect(-1, {sa_family=AF_BLUETOOTH" ", rc_bdaddr=%02x:%02x:%02x:%02x:%02x:%02x" ", rc_channel=%u}, %u) = %d EBADF (%m)\n", @@ -619,6 +661,7 @@ check_l2(void) unsigned int len = sizeof(c_l2); int ret = connect(-1, l2, len); + pidns_print_leader(); printf("connect(-1, {sa_family=AF_BLUETOOTH" ", l2_psm=htobs(L2CAP_PSM_DYN_START + %hu)" ", l2_bdaddr=%02x:%02x:%02x:%02x:%02x:%02x" @@ -640,6 +683,7 @@ check_l2(void) # endif memcpy(l2, &c_l2, sizeof(c_l2)); ret = connect(-1, l2, len); + pidns_print_leader(); printf("connect(-1, {sa_family=AF_BLUETOOTH" ", l2_psm=htobs(L2CAP_PSM_SDP)" ", l2_bdaddr=%02x:%02x:%02x:%02x:%02x:%02x" @@ -660,6 +704,7 @@ check_l2(void) # endif memcpy(l2, &c_l2, sizeof(c_l2)); ret = connect(-1, l2, len); + pidns_print_leader(); printf("connect(-1, {sa_family=AF_BLUETOOTH" ", l2_psm=htobs(0xbad /* L2CAP_PSM_??? */)" ", l2_bdaddr=%02x:%02x:%02x:%02x:%02x:%02x" @@ -677,6 +722,7 @@ check_l2(void) c_l2.l2_cid = htobs(0xffff); memcpy(l2, &c_l2, 12); ret = connect(-1, l2, 12); + pidns_print_leader(); printf("connect(-1, {sa_family=AF_BLUETOOTH" ", l2_psm=htobs(L2CAP_PSM_AUTO_END)" ", l2_bdaddr=%02x:%02x:%02x:%02x:%02x:%02x" @@ -700,6 +746,7 @@ check_raw(void) u.sa->sa_family = 0xff; unsigned int len = sizeof(*u.st) + 8; int ret = connect(-1, (void *) u.st, len); + pidns_print_leader(); printf("connect(-1, {sa_family=%#x /* AF_??? */, sa_data=\"%.*u\"}" ", %u) = %d EBADF (%m)\n", u.sa->sa_family, (int) (sizeof(*u.st) - sizeof(u.sa->sa_family)), 0, len, ret); @@ -707,11 +754,13 @@ check_raw(void) u.sa->sa_family = 0; len = sizeof(u.sa->sa_family) + 1; ret = connect(-1, (void *) u.st, len); + pidns_print_leader(); printf("connect(-1, {sa_family=AF_UNSPEC, sa_data=\"0\"}, %u)" " = %d EBADF (%m)\n", len, ret); u.sa->sa_family = AF_BLUETOOTH; ret = connect(-1, (void *) u.st, len); + pidns_print_leader(); printf("connect(-1, {sa_family=AF_BLUETOOTH, sa_data=\"0\"}, %u)" " = %d EBADF (%m)\n", len, ret); } @@ -719,6 +768,8 @@ check_raw(void) int main(void) { + PIDNS_TEST_INIT; + check_un(); check_in(); check_in6(); @@ -735,6 +786,7 @@ main(void) #endif check_raw(); + pidns_print_leader(); puts("+++ exited with 0 +++"); return 0; } diff --git a/tests/netlink_audit--pidns-translation.c b/tests/netlink_audit--pidns-translation.c new file mode 100644 index 00000000..e08f9168 --- /dev/null +++ b/tests/netlink_audit--pidns-translation.c @@ -0,0 +1,2 @@ +#define PIDNS_TRANSLATION +#include "netlink_audit.c" diff --git a/tests/netlink_audit--pidns-translation.test b/tests/netlink_audit--pidns-translation.test new file mode 100755 index 00000000..fbc32435 --- /dev/null +++ b/tests/netlink_audit--pidns-translation.test @@ -0,0 +1,13 @@ +#!/bin/sh +# +# Check decoding of NETLINK_SOCK_DIAG protocol +# +# Copyright (c) 2020 The strace developers. +# All rights reserved. +# +# SPDX-License-Identifier: LGPL-2.1-or-later + +. "${srcdir=.}/init.sh" + +run_prog ../netlink_netlink_diag +test_pidns -e trace=sendto "$@" diff --git a/tests/netlink_audit.c b/tests/netlink_audit.c index eba609a1..5dfcd786 100644 --- a/tests/netlink_audit.c +++ b/tests/netlink_audit.c @@ -7,6 +7,7 @@ */ #include "tests.h" +#include "pidns.h" #include #include #include @@ -17,18 +18,23 @@ static void test_nlmsg_type(const int fd) { + PIDNS_TEST_INIT; + long rc; struct nlmsghdr nlh = { .nlmsg_len = sizeof(nlh), .nlmsg_type = AUDIT_GET, .nlmsg_flags = NLM_F_REQUEST, + .nlmsg_pid = getpid(), }; rc = sendto(fd, &nlh, sizeof(nlh), MSG_DONTWAIT, NULL, 0); + pidns_print_leader(); printf("sendto(%d, {len=%u, type=AUDIT_GET" - ", flags=NLM_F_REQUEST, seq=0, pid=0}" + ", flags=NLM_F_REQUEST, seq=0, pid=%d%s}" ", %u, MSG_DONTWAIT, NULL, 0) = %s\n", - fd, nlh.nlmsg_len, (unsigned) sizeof(nlh), sprintrc(rc)); + fd, nlh.nlmsg_len, nlh.nlmsg_pid, pidns_pid2str(PT_TGID), + (unsigned) sizeof(nlh), sprintrc(rc)); } int main(void) @@ -39,6 +45,7 @@ int main(void) test_nlmsg_type(fd); + pidns_print_leader(); printf("+++ exited with 0 +++\n"); return 0; diff --git a/tests/pidfd_open--pidns-translation.c b/tests/pidfd_open--pidns-translation.c new file mode 100644 index 00000000..c38e37a8 --- /dev/null +++ b/tests/pidfd_open--pidns-translation.c @@ -0,0 +1,2 @@ +#define PIDNS_TRANSLATION +#include "pidfd_open.c" diff --git a/tests/pidfd_open.c b/tests/pidfd_open.c index 5860adde..e5d74a91 100644 --- a/tests/pidfd_open.c +++ b/tests/pidfd_open.c @@ -10,6 +10,7 @@ #include "tests.h" #include "scno.h" +#include "pidns.h" #ifdef __NR_pidfd_open @@ -37,6 +38,8 @@ k_pidfd_open(const unsigned int pid, const unsigned int flags) int main(void) { + PIDNS_TEST_INIT; + # if defined PATH_TRACING || defined PRINT_PATHS skip_if_unavailable("/proc/self/fd/"); # endif @@ -50,16 +53,19 @@ main(void) k_pidfd_open(0, 0); # ifndef PATH_TRACING + pidns_print_leader(); printf("pidfd_open(0, 0) = %s\n", errstr); # endif k_pidfd_open(-1U, 0); # ifndef PATH_TRACING + pidns_print_leader(); printf("pidfd_open(-1, 0) = %s\n", errstr); # endif k_pidfd_open(0, -1U); # ifndef PATH_TRACING + pidns_print_leader(); printf("pidfd_open(0, %#x) = %s\n", -1U, errstr); # endif @@ -68,7 +74,10 @@ main(void) k_pidfd_open(pid, flags); # ifndef PATH_TRACING - printf("pidfd_open(%d, %#x) = %s\n", pid, flags, errstr); + const char *pid_str = pidns_pid2str(PT_TGID); + pidns_print_leader(); + printf("pidfd_open(%d%s, %#x) = %s\n", + pid, pid_str, flags, errstr); # endif # ifdef PRINT_PATHS @@ -80,17 +89,19 @@ main(void) # endif # ifndef PATH_TRACING - printf("pidfd_open(%d, 0) = " + pidns_print_leader(); + printf("pidfd_open(%d%s, 0) = " # if defined PRINT_PIDFD - "%ld\n", pid, rc, pid + "%ld\n", pid, pid_str, rc, pid # elif defined PRINT_PATHS - "%ld\n", pid, rc + "%ld\n", pid, pid_str, rc # else - "%s\n", pid, errstr + "%s\n", pid, pid_str, errstr # endif ); # endif + pidns_print_leader(); puts("+++ exited with 0 +++"); return 0; } diff --git a/tests/pidfd_send_signal--pidns-translation.c b/tests/pidfd_send_signal--pidns-translation.c new file mode 100644 index 00000000..b04f10f5 --- /dev/null +++ b/tests/pidfd_send_signal--pidns-translation.c @@ -0,0 +1,2 @@ +#define PIDNS_TRANSLATION +#include "pidfd_send_signal.c" diff --git a/tests/pidfd_send_signal.c b/tests/pidfd_send_signal.c index 38b5bda1..a6b2d28c 100644 --- a/tests/pidfd_send_signal.c +++ b/tests/pidfd_send_signal.c @@ -10,6 +10,7 @@ #include "tests.h" #include #include "scno.h" +#include "pidns.h" #ifdef __NR_pidfd_send_signal @@ -36,6 +37,8 @@ sys_pidfd_send_signal(int pidfd, int sig, const void *info, int flags) int main(void) { + PIDNS_TEST_INIT; + static const char null_path[] = "/dev/null"; int fd = open(null_path, O_RDONLY); @@ -46,19 +49,23 @@ main(void) const void *esi = (const void *) si + 1; sys_pidfd_send_signal(fd, SIGUSR1, esi, 0); + pidns_print_leader(); printf("pidfd_send_signal(%d, SIGUSR1, %p, 0) = %s\n", fd, esi, errstr); si->si_signo = SIGUSR1; si->si_code = SI_QUEUE; + si->si_pid = getpid(); sys_pidfd_send_signal(fd, SIGUSR2, si, -1); + pidns_print_leader(); printf("pidfd_send_signal(%d, SIGUSR2, {si_signo=SIGUSR1" - ", si_code=SI_QUEUE, si_errno=%u, si_pid=%d, si_uid=%d" + ", si_code=SI_QUEUE, si_errno=%u, si_pid=%d%s, si_uid=%d" ", si_value={int=%d, ptr=%p}}, %#x) = %s\n", - fd, si->si_errno, si->si_pid, si->si_uid, si->si_int, si->si_ptr, - -1U, errstr); + fd, si->si_errno, si->si_pid, pidns_pid2str(PT_TGID), si->si_uid, + si->si_int, si->si_ptr, -1U, errstr); + pidns_print_leader(); puts("+++ exited with 0 +++"); return 0; } diff --git a/tests/prlimit64--pidns-translation.c b/tests/prlimit64--pidns-translation.c new file mode 100644 index 00000000..3972de66 --- /dev/null +++ b/tests/prlimit64--pidns-translation.c @@ -0,0 +1,2 @@ +#define PIDNS_TRANSLATION +#include "prlimit64.c" diff --git a/tests/prlimit64.c b/tests/prlimit64.c index 34201a2b..bc1a80b3 100644 --- a/tests/prlimit64.c +++ b/tests/prlimit64.c @@ -19,6 +19,7 @@ # include # include +# include "pidns.h" # include "xlat.h" # include "xlat/resources.h" @@ -42,8 +43,11 @@ sprint_rlim(uint64_t lim) int main(void) { + PIDNS_TEST_INIT; + unsigned long pid = (unsigned long) 0xdefaced00000000ULL | (unsigned) getpid(); + const char *pid_str = pidns_pid2str(PT_TGID); uint64_t *const rlimit = tail_alloc(sizeof(*rlimit) * 2); const struct xlat_data *xlat; size_t i = 0; @@ -54,18 +58,23 @@ main(void) unsigned long res = 0xfacefeed00000000ULL | xlat->val; long rc = syscall(__NR_prlimit64, pid, res, 0, rlimit); + pidns_print_leader(); if (rc) - printf("prlimit64(%d, %s, NULL, %p) = %ld %s (%m)\n", - (unsigned) pid, xlat->str, rlimit, + printf("prlimit64(%d%s, %s, NULL, %p) =" + " %ld %s (%m)\n", + (unsigned) pid, pid_str, + xlat->str, rlimit, rc, errno2name()); else - printf("prlimit64(%d, %s, NULL" + printf("prlimit64(%d%s, %s, NULL" ", {rlim_cur=%s, rlim_max=%s}) = 0\n", - (unsigned) pid, xlat->str, + (unsigned) pid, pid_str, + xlat->str, sprint_rlim(rlimit[0]), sprint_rlim(rlimit[1])); } + pidns_print_leader(); puts("+++ exited with 0 +++"); return 0; } diff --git a/tests/process_vm_readv--pidns-translation.c b/tests/process_vm_readv--pidns-translation.c new file mode 100644 index 00000000..0db29ca2 --- /dev/null +++ b/tests/process_vm_readv--pidns-translation.c @@ -0,0 +1,2 @@ +#define PIDNS_TRANSLATION +#include "process_vm_readv.c" diff --git a/tests/process_vm_readv_writev.c b/tests/process_vm_readv_writev.c index 9309135a..44e511dd 100644 --- a/tests/process_vm_readv_writev.c +++ b/tests/process_vm_readv_writev.c @@ -12,6 +12,7 @@ #include #include #include +#include "pidns.h" #if OP_WR # define in_iovec rmt_iovec @@ -121,7 +122,7 @@ print_iov(const struct iovec *iov, const void *arg_ptr, long rc) } static void -do_call(kernel_ulong_t pid, +do_call(kernel_ulong_t pid, enum pid_type pid_type, kernel_ulong_t local_iov, const char *local_arg, kernel_ulong_t liovcnt, kernel_ulong_t remote_iov, const char *remote_arg, @@ -135,7 +136,8 @@ do_call(kernel_ulong_t pid, flags); errstr = sprintrc(rc); - printf("%s(%d, ", OP_STR, (int) pid); + pidns_print_leader(); + printf("%s(%d%s, ", OP_STR, (int) pid, pidns_pid2str(pid_type)); if (pr_iov) pr_iov((const struct iovec *) (uintptr_t) local_iov, local_arg, @@ -164,6 +166,8 @@ ptr_cast(void *ptr) int main(void) { + PIDNS_TEST_INIT; + enum { SIZE_11 = 2, SIZE_12 = 3, @@ -243,18 +247,18 @@ main(void) fill_memory_ex(data2_out, SIZE_2, SEGM2_BASE, SIZE_2); - do_call(bogus_pid, (kernel_ulong_t) (uintptr_t) ARG_STR(NULL), + do_call(bogus_pid, PT_NONE, (kernel_ulong_t) (uintptr_t) ARG_STR(NULL), bogus_iovcnt1, (kernel_ulong_t) (uintptr_t) ARG_STR(NULL), bogus_iovcnt2, bogus_flags, NULL); - do_call(my_pid, ptr_cast(bogus_iov + ARRAY_SIZE(bogus_iovec)), + do_call(my_pid, PT_TGID, ptr_cast(bogus_iov + ARRAY_SIZE(bogus_iovec)), "[]", 0, ptr_cast(in_iov + ARRAY_SIZE(in_iovec)), "[]", 0, 0, NULL); - do_call(my_pid, ptr_cast(bogus_iov + ARRAY_SIZE(bogus_iovec)), NULL, - bogus_iovcnt1, ptr_cast(in_iov + ARRAY_SIZE(in_iovec)), NULL, - bogus_iovcnt2, 0, print_iov); + do_call(my_pid, PT_TGID, ptr_cast(bogus_iov + ARRAY_SIZE(bogus_iovec)), + NULL, bogus_iovcnt1, ptr_cast(in_iov + ARRAY_SIZE(in_iovec)), + NULL, bogus_iovcnt2, 0, print_iov); - do_call(my_pid, ptr_cast(bogus_iov), (char *) &bogus_arg, + do_call(my_pid, PT_TGID, ptr_cast(bogus_iov), (char *) &bogus_arg, ARRAY_SIZE(bogus_iovec), ptr_cast(rmt_iov + 2), (char *) &rmt_arg_cut, ARRAY_SIZE(rmt_iovec) - 2, 0, print_iov); @@ -263,7 +267,7 @@ main(void) lcl_arg_cut.check_rc = 1; #endif - do_call(my_pid, ptr_cast(lcl_iov + 2), (char *) &lcl_arg_cut, + do_call(my_pid, PT_TGID, ptr_cast(lcl_iov + 2), (char *) &lcl_arg_cut, ARRAY_SIZE(lcl_iovec) - 1, ptr_cast(bogus_iov + 2), (char *) &bogus_arg_cut, ARRAY_SIZE(bogus_iovec) - 1, 0, print_iov); @@ -273,15 +277,16 @@ main(void) rmt_arg_cut.addr_term = 1; rmt_arg_cut.count = 5; - do_call(my_pid, ptr_cast(lcl_iov + 2), (char *) &lcl_arg_cut, + do_call(my_pid, PT_TGID, ptr_cast(lcl_iov + 2), (char *) &lcl_arg_cut, ARRAY_SIZE(lcl_iovec) - 2, ptr_cast(rmt_iov + 1), (char *) &rmt_arg_cut, ARRAY_SIZE(rmt_iovec), 0, print_iov); /* Correct call */ - do_call(my_pid, ptr_cast(lcl_iov), (char *) &lcl_arg, + do_call(my_pid, PT_TGID, ptr_cast(lcl_iov), (char *) &lcl_arg, ARRAY_SIZE(lcl_iovec), ptr_cast(rmt_iov), (char *) &rmt_arg, ARRAY_SIZE(rmt_iovec), 0, print_iov); + pidns_print_leader(); puts("+++ exited with 0 +++"); return 0; diff --git a/tests/process_vm_writev--pidns-translation.c b/tests/process_vm_writev--pidns-translation.c new file mode 100644 index 00000000..9ba6a39b --- /dev/null +++ b/tests/process_vm_writev--pidns-translation.c @@ -0,0 +1,2 @@ +#define PIDNS_TRANSLATION +#include "process_vm_writev.c" diff --git a/tests/rt_sigqueueinfo--pidns-translation.c b/tests/rt_sigqueueinfo--pidns-translation.c new file mode 100644 index 00000000..74bfb464 --- /dev/null +++ b/tests/rt_sigqueueinfo--pidns-translation.c @@ -0,0 +1,2 @@ +#define PIDNS_TRANSLATION +#include "rt_sigqueueinfo.c" diff --git a/tests/rt_sigqueueinfo.c b/tests/rt_sigqueueinfo.c index c1693873..e22e4640 100644 --- a/tests/rt_sigqueueinfo.c +++ b/tests/rt_sigqueueinfo.c @@ -7,6 +7,7 @@ */ #include "tests.h" +#include "pidns.h" #include #include #include @@ -15,6 +16,8 @@ int main(void) { + PIDNS_TEST_INIT; + struct sigaction sa = { .sa_handler = SIG_IGN }; @@ -22,15 +25,19 @@ main(void) .sival_ptr = (void *) (unsigned long) 0xdeadbeefbadc0dedULL }; pid_t pid = getpid(); + const char *pid_str = pidns_pid2str(PT_TGID); assert(sigaction(SIGUSR1, &sa, NULL) == 0); if (sigqueue(pid, SIGUSR1, value)) perror_msg_and_skip("sigqueue"); - printf("rt_sigqueueinfo(%u, SIGUSR1, {si_signo=SIGUSR1, " - "si_code=SI_QUEUE, si_pid=%d, si_uid=%d, " + pidns_print_leader(); + printf("rt_sigqueueinfo(%d%s, SIGUSR1, {si_signo=SIGUSR1, " + "si_code=SI_QUEUE, si_pid=%d%s, si_uid=%u, " "si_value={int=%d, ptr=%p}}) = 0\n", - pid, pid, getuid(), value.sival_int, value.sival_ptr); - printf("+++ exited with 0 +++\n"); + pid, pid_str, pid, pid_str, + getuid(), value.sival_int, value.sival_ptr); + pidns_print_leader(); + puts("+++ exited with 0 +++"); return 0; } diff --git a/tests/rt_tgsigqueueinfo--pidns-translation.c b/tests/rt_tgsigqueueinfo--pidns-translation.c new file mode 100644 index 00000000..94396f00 --- /dev/null +++ b/tests/rt_tgsigqueueinfo--pidns-translation.c @@ -0,0 +1,2 @@ +#define PIDNS_TRANSLATION +#include "rt_tgsigqueueinfo.c" diff --git a/tests/rt_tgsigqueueinfo.c b/tests/rt_tgsigqueueinfo.c index 865c21f6..21d01cbb 100644 --- a/tests/rt_tgsigqueueinfo.c +++ b/tests/rt_tgsigqueueinfo.c @@ -10,8 +10,9 @@ #include "tests.h" #include "scno.h" +#include "pidns.h" -#ifdef __NR_rt_tgsigqueueinfo +#if defined __NR_rt_tgsigqueueinfo && defined __NR_gettid # include # include @@ -20,11 +21,11 @@ # include static long -k_tgsigqueueinfo(const pid_t pid, const int sig, const void *const info) +k_tgsigqueueinfo(const pid_t tgid, const int tid, const int sig, const void *const info) { return syscall(__NR_rt_tgsigqueueinfo, - F8ILL_KULONG_MASK | pid, - F8ILL_KULONG_MASK | pid, + F8ILL_KULONG_MASK | tgid, + F8ILL_KULONG_MASK | tid, F8ILL_KULONG_MASK | sig, info); } @@ -32,6 +33,8 @@ k_tgsigqueueinfo(const pid_t pid, const int sig, const void *const info) int main(void) { + PIDNS_TEST_INIT; + const struct sigaction sa = { .sa_handler = SIG_IGN }; @@ -48,17 +51,22 @@ main(void) info->si_value.sival_ptr = (void *) (unsigned long) 0xdeadbeeffacefeedULL; - if (k_tgsigqueueinfo(info->si_pid, SIGUSR1, info)) + if (k_tgsigqueueinfo(getpid(), syscall(__NR_gettid), SIGUSR1, info)) (errno == ENOSYS ? perror_msg_and_skip : perror_msg_and_fail)( "rt_tgsigqueueinfo"); - printf("rt_tgsigqueueinfo(%u, %u, %s, {si_signo=%s" - ", si_code=SI_QUEUE, si_errno=ENOENT, si_pid=%d" + pidns_print_leader(); + printf("rt_tgsigqueueinfo(%d%s, %d%s, %s, {si_signo=%s" + ", si_code=SI_QUEUE, si_errno=ENOENT, si_pid=%d%s" ", si_uid=%d, si_value={int=%d, ptr=%p}}) = 0\n", - info->si_pid, info->si_pid, "SIGUSR1", "SIGUSR1", - info->si_pid, info->si_uid, info->si_value.sival_int, + info->si_pid, pidns_pid2str(PT_TGID), + info->si_pid, pidns_pid2str(PT_TID), + "SIGUSR1", "SIGUSR1", + info->si_pid, pidns_pid2str(PT_TGID), + info->si_uid, info->si_value.sival_int, info->si_value.sival_ptr); + pidns_print_leader(); puts("+++ exited with 0 +++"); return 0; } diff --git a/tests/sched_xetaffinity--pidns-translation.c b/tests/sched_xetaffinity--pidns-translation.c new file mode 100644 index 00000000..814e3989 --- /dev/null +++ b/tests/sched_xetaffinity--pidns-translation.c @@ -0,0 +1,2 @@ +#define PIDNS_TRANSLATION +#include "sched_xetaffinity.c" diff --git a/tests/sched_xetaffinity.c b/tests/sched_xetaffinity.c index cebff3ab..2e508ca3 100644 --- a/tests/sched_xetaffinity.c +++ b/tests/sched_xetaffinity.c @@ -10,6 +10,7 @@ #include "tests.h" #include "scno.h" +#include "pidns.h" #include #if defined __NR_sched_getaffinity && defined __NR_sched_setaffinity \ @@ -41,8 +42,11 @@ setaffinity(unsigned long pid, unsigned long size, void *set) int main(void) { + PIDNS_TEST_INIT; + unsigned int cpuset_size = 1; const pid_t pid = getpid(); + const char *pid_str = pidns_pid2str(PT_TGID); while (cpuset_size) { assert(getaffinity(pid, cpuset_size, NULL) == -1); @@ -50,18 +54,21 @@ main(void) break; if (EINVAL != errno) perror_msg_and_skip("sched_getaffinity"); - printf("sched_getaffinity(%d, %u, NULL) = %s\n", - pid, cpuset_size, errstr); + pidns_print_leader(); + printf("sched_getaffinity(%d%s, %u, NULL) = %s\n", + pid, pid_str, cpuset_size, errstr); cpuset_size <<= 1; } assert(cpuset_size); - printf("sched_getaffinity(%d, %u, NULL) = %s\n", - pid, cpuset_size, errstr); + pidns_print_leader(); + printf("sched_getaffinity(%d%s, %u, NULL) = %s\n", + pid, pid_str, cpuset_size, errstr); cpu_set_t *cpuset = tail_alloc(cpuset_size); getaffinity(pid, cpuset_size, cpuset + 1); - printf("sched_getaffinity(%d, %u, %p) = %s\n", - pid, cpuset_size, cpuset + 1, errstr); + pidns_print_leader(); + printf("sched_getaffinity(%d%s, %u, %p) = %s\n", + pid, pid_str, cpuset_size, cpuset + 1, errstr); int ret_size = getaffinity(pid, cpuset_size, cpuset); if (ret_size < 0) @@ -69,7 +76,8 @@ main(void) pid, (unsigned) cpuset_size, cpuset, errstr); assert(ret_size <= (int) cpuset_size); - printf("sched_getaffinity(%d, %u, [", pid, cpuset_size); + pidns_print_leader(); + printf("sched_getaffinity(%d%s, %u, [", pid, pid_str, cpuset_size); const char *sep; unsigned int i, cpu; for (i = 0, cpu = 0, sep = ""; i < (unsigned) ret_size * 8; ++i) { @@ -85,8 +93,9 @@ main(void) CPU_SET_S(cpu, cpuset_size, cpuset); if (setaffinity(pid, cpuset_size, cpuset)) perror_msg_and_skip("sched_setaffinity"); - printf("sched_setaffinity(%d, %u, [%u]) = 0\n", - pid, cpuset_size, cpu); + pidns_print_leader(); + printf("sched_setaffinity(%d%s, %u, [%u]) = 0\n", + pid, pid_str, cpuset_size, cpu); const unsigned int big_size = cpuset_size < 128 ? 128 : cpuset_size * 2; cpuset = tail_alloc(big_size); @@ -95,7 +104,8 @@ main(void) perror_msg_and_fail("sched_getaffinity(%d, %u, %p) = %s\n", pid, big_size, cpuset, errstr); assert(ret_size <= (int) big_size); - printf("sched_getaffinity(%d, %u, [", pid, big_size); + pidns_print_leader(); + printf("sched_getaffinity(%d%s, %u, [", pid, pid_str, big_size); for (i = 0, sep = ""; i < (unsigned) ret_size * 8; ++i) { if (CPU_ISSET_S(i, (unsigned) ret_size, cpuset)) { printf("%s%u", sep, i); @@ -104,6 +114,7 @@ main(void) } printf("]) = %s\n", errstr); + pidns_print_leader(); puts("+++ exited with 0 +++"); return 0; } diff --git a/tests/sched_xetattr--pidns-translation.c b/tests/sched_xetattr--pidns-translation.c new file mode 100644 index 00000000..c152023d --- /dev/null +++ b/tests/sched_xetattr--pidns-translation.c @@ -0,0 +1,2 @@ +#define PIDNS_TRANSLATION +#include "sched_xetattr.c" diff --git a/tests/sched_xetattr.c b/tests/sched_xetattr.c index c63d7a80..4a76b2d6 100644 --- a/tests/sched_xetattr.c +++ b/tests/sched_xetattr.c @@ -15,6 +15,7 @@ # include # include # include +# include "pidns.h" # include "sched_attr.h" # include "xlat.h" # include "xlat/schedulers.h" @@ -41,6 +42,8 @@ sys_sched_setattr(kernel_ulong_t pid, kernel_ulong_t attr, kernel_ulong_t flags) int main(void) { + PIDNS_TEST_INIT; + static const kernel_ulong_t bogus_pid = (kernel_ulong_t) 0xdefacedfacefeedULL; static const kernel_ulong_t bogus_size = @@ -48,20 +51,28 @@ main(void) static const kernel_ulong_t bogus_flags = (kernel_ulong_t) 0xdefaceddeadc0deULL; + const int pid = getpid(); + const char *pid_str = pidns_pid2str(PT_TGID); + TAIL_ALLOC_OBJECT_CONST_PTR(struct sched_attr, attr); TAIL_ALLOC_OBJECT_CONST_PTR(unsigned int, psize); void *const efault = attr + 1; - sys_sched_getattr(0, 0, 0, 0); - printf("sched_getattr(0, NULL, 0, 0) = %s\n", errstr); + sys_sched_getattr(pid, 0, 0, 0); + pidns_print_leader(); + printf("sched_getattr(%d%s, NULL, 0, 0) = %s\n", + pid, pid_str, errstr); sys_sched_getattr(0, (unsigned long) attr, 0, 0); + pidns_print_leader(); printf("sched_getattr(0, %p, 0, 0) = %s\n", attr, errstr); sys_sched_getattr(bogus_pid, 0, 0, 0); + pidns_print_leader(); printf("sched_getattr(%d, NULL, 0, 0) = %s\n", (int) bogus_pid, errstr); sys_sched_getattr(-1U, (unsigned long) attr, bogus_size, bogus_flags); + pidns_print_leader(); printf("sched_getattr(-1, %p, %s%u, %u) = %s\n", attr, # if defined __arm64__ || defined __aarch64__ @@ -72,11 +83,13 @@ main(void) (unsigned) bogus_size, (unsigned) bogus_flags, errstr); sys_sched_getattr(0, (unsigned long) efault, SCHED_ATTR_MIN_SIZE, 0); + pidns_print_leader(); printf("sched_getattr(0, %p, %u, 0) = %s\n", efault, (unsigned) SCHED_ATTR_MIN_SIZE, errstr); if (sys_sched_getattr(0, (unsigned long) attr, SCHED_ATTR_MIN_SIZE, 0)) perror_msg_and_skip("sched_getattr"); + pidns_print_leader(); printf("sched_getattr(0, {size=%u, sched_policy=", attr->size); printxval(schedulers, attr->sched_policy, NULL); printf(", sched_flags=%s, sched_nice=%d, sched_priority=%u" @@ -91,11 +104,13 @@ main(void) (unsigned) SCHED_ATTR_MIN_SIZE); sys_sched_getattr(0, (unsigned long) efault, sizeof(*attr), 0); + pidns_print_leader(); printf("sched_getattr(0, %p, %u, 0) = %s\n", efault, (unsigned) sizeof(*attr), errstr); if (sys_sched_getattr(0, (unsigned long) attr, sizeof(*attr), 0)) perror_msg_and_skip("sched_getattr"); + pidns_print_leader(); printf("sched_getattr(0, {size=%u, sched_policy=", attr->size); printxval(schedulers, attr->sched_policy, NULL); printf(", sched_flags=%s, sched_nice=%d, sched_priority=%u" @@ -121,11 +136,13 @@ main(void) F8ILL_KULONG_MASK | sizeof(*attr), F8ILL_KULONG_MASK); # if defined __arm64__ || defined __aarch64__ if (rc) { + pidns_print_leader(); printf("sched_getattr(0, %p, 0xffffffff<<32|%u, 0) = %s\n", attr, (unsigned) sizeof(*attr), errstr); } else # endif { + pidns_print_leader(); printf("sched_getattr(0, {size=%u, sched_policy=", attr->size); printxval(schedulers, attr->sched_policy, NULL); printf(", sched_flags=%s, sched_nice=%d, sched_priority=%u" @@ -146,13 +163,16 @@ main(void) } sys_sched_setattr(bogus_pid, 0, 0); + pidns_print_leader(); printf("sched_setattr(%d, NULL, 0) = %s\n", (int) bogus_pid, errstr); attr->sched_flags |= 1; - if (sys_sched_setattr(0, (unsigned long) attr, 0)) + if (sys_sched_setattr(pid, (unsigned long) attr, 0)) perror_msg_and_skip("sched_setattr"); - printf("sched_setattr(0, {size=%u, sched_policy=", attr->size); + pidns_print_leader(); + printf("sched_setattr(%d%s, {size=%u, sched_policy=", + pid, pid_str, attr->size); printxval(schedulers, attr->sched_policy, NULL); printf(", sched_flags=%s, sched_nice=%d, sched_priority=%u" ", sched_runtime=%" PRIu64 ", sched_deadline=%" PRIu64 @@ -172,6 +192,7 @@ main(void) sys_sched_setattr(F8ILL_KULONG_MASK, (unsigned long) attr, F8ILL_KULONG_MASK); + pidns_print_leader(); printf("sched_setattr(0, {size=%u, sched_policy=", attr->size); printxval(schedulers, attr->sched_policy, NULL); printf(", sched_flags=%s, sched_nice=%d, sched_priority=%u" @@ -193,11 +214,13 @@ main(void) *psize = attr->size; sys_sched_setattr(0, (unsigned long) psize, 0); + pidns_print_leader(); printf("sched_setattr(0, %p, 0) = %s\n", psize, errstr); attr->size = 0; sys_sched_setattr(0, (unsigned long) attr, 0); + pidns_print_leader(); printf("sched_setattr(0, {size=%u, sched_policy=", attr->size); printxval(schedulers, attr->sched_policy, NULL); printf(", sched_flags=%s, sched_nice=%d, sched_priority=%u" @@ -213,12 +236,14 @@ main(void) attr->size = 1; sys_sched_setattr(0, (unsigned long) attr, 0); + pidns_print_leader(); printf("sched_setattr(0, {size=%u} => {size=%u}, 0) = %s\n", 1, attr->size, errstr); attr->size = SCHED_ATTR_MIN_SIZE - 1; sys_sched_setattr(0, (unsigned long) attr, 0); + pidns_print_leader(); printf("sched_setattr(0, {size=%u} => {size=%u}, 0) = %s\n", SCHED_ATTR_MIN_SIZE - 1, attr->size, errstr); @@ -232,6 +257,7 @@ main(void) attr->sched_period = 0xded1ca7edda7aca7ULL; sys_sched_setattr(bogus_pid, (unsigned long) attr, bogus_flags); + pidns_print_leader(); printf("sched_setattr(%d, {size=%u, sched_policy=%#x /* SCHED_??? */, " "sched_flags=%#" PRIx64 " /* SCHED_FLAG_??? */, " "sched_nice=%d, sched_priority=%u, sched_runtime=%" PRIu64 ", " @@ -274,6 +300,7 @@ main(void) attr->sched_period = 0xded1ca7edda7aca7ULL; sys_sched_setattr(bogus_pid, (unsigned long) attr, bogus_flags); + pidns_print_leader(); printf("sched_setattr(%d, {size=%u, sched_policy=%#x /* SCHED_??? */, " "sched_flags=SCHED_FLAG_RESET_ON_FORK|SCHED_FLAG_RECLAIM|" "SCHED_FLAG_DL_OVERRUN|0x80, " @@ -296,11 +323,13 @@ main(void) const kernel_ulong_t ill = f8ill_ptr_to_kulong(attr); sys_sched_getattr(0, ill, sizeof(*attr), 0); + pidns_print_leader(); printf("sched_getattr(0, %#llx, %u, 0) = %s\n", (unsigned long long) ill, (unsigned) sizeof(*attr), errstr); sys_sched_setattr(0, ill, 0); + pidns_print_leader(); printf("sched_setattr(0, %#llx, 0) = %s\n", (unsigned long long) ill, errstr); } @@ -310,6 +339,7 @@ main(void) attr->sched_flags = 0x8fULL; sys_sched_setattr(bogus_pid, (unsigned long) attr, bogus_flags); + pidns_print_leader(); printf("sched_setattr(%d, {size=%u, " "sched_flags=SCHED_FLAG_RESET_ON_FORK|SCHED_FLAG_RECLAIM|" "SCHED_FLAG_DL_OVERRUN|SCHED_FLAG_KEEP_POLICY|0x80, " @@ -329,11 +359,13 @@ main(void) const kernel_ulong_t ill = f8ill_ptr_to_kulong(attr); sys_sched_getattr(0, ill, sizeof(*attr), 0); + pidns_print_leader(); printf("sched_getattr(0, %#llx, %u, 0) = %s\n", (unsigned long long) ill, (unsigned) sizeof(*attr), errstr); sys_sched_setattr(0, ill, 0); + pidns_print_leader(); printf("sched_setattr(0, %#llx, 0) = %s\n", (unsigned long long) ill, errstr); } @@ -342,6 +374,7 @@ main(void) attr->sched_flags = 0xe7ULL; sys_sched_setattr(bogus_pid, (unsigned long) attr, bogus_flags); + pidns_print_leader(); printf("sched_setattr(%d, {size=%u, sched_policy=%#x /* SCHED_??? */, " "sched_flags=SCHED_FLAG_RESET_ON_FORK|SCHED_FLAG_RECLAIM|" "SCHED_FLAG_DL_OVERRUN|SCHED_FLAG_UTIL_CLAMP_MIN" @@ -365,11 +398,13 @@ main(void) const kernel_ulong_t ill = f8ill_ptr_to_kulong(attr); sys_sched_getattr(0, ill, sizeof(*attr), 0); + pidns_print_leader(); printf("sched_getattr(0, %#llx, %u, 0) = %s\n", (unsigned long long) ill, (unsigned) sizeof(*attr), errstr); sys_sched_setattr(0, ill, 0); + pidns_print_leader(); printf("sched_setattr(0, %#llx, 0) = %s\n", (unsigned long long) ill, errstr); } @@ -377,6 +412,7 @@ main(void) attr->sched_flags = 0xcaffee90LL; sys_sched_setattr(bogus_pid, (unsigned long) attr, bogus_flags); + pidns_print_leader(); printf("sched_setattr(%d, {size=%u, sched_flags=SCHED_FLAG_KEEP_PARAMS" "|0xcaffee80, sched_util_min=%u, sched_util_max=%u}, %u) = %s\n", (int) bogus_pid, @@ -389,15 +425,18 @@ main(void) const kernel_ulong_t ill = f8ill_ptr_to_kulong(attr); sys_sched_getattr(0, ill, sizeof(*attr), 0); + pidns_print_leader(); printf("sched_getattr(0, %#llx, %u, 0) = %s\n", (unsigned long long) ill, (unsigned) sizeof(*attr), errstr); sys_sched_setattr(0, ill, 0); + pidns_print_leader(); printf("sched_setattr(0, %#llx, 0) = %s\n", (unsigned long long) ill, errstr); } + pidns_print_leader(); puts("+++ exited with 0 +++"); return 0; } diff --git a/tests/sched_xetparam--pidns-translation.c b/tests/sched_xetparam--pidns-translation.c new file mode 100644 index 00000000..9fb3e579 --- /dev/null +++ b/tests/sched_xetparam--pidns-translation.c @@ -0,0 +1,2 @@ +#define PIDNS_TRANSLATION +#include "sched_xetparam.c" diff --git a/tests/sched_xetparam.c b/tests/sched_xetparam.c index de3915b2..aa9c68cc 100644 --- a/tests/sched_xetparam.c +++ b/tests/sched_xetparam.c @@ -7,6 +7,7 @@ #include "tests.h" #include "scno.h" +# include "pidns.h" #if defined __NR_sched_getparam && defined __NR_sched_setparam @@ -17,18 +18,27 @@ int main(void) { + PIDNS_TEST_INIT; + struct sched_param *const param = tail_alloc(sizeof(struct sched_param)); - long rc = syscall(__NR_sched_getparam, 0, param); - printf("sched_getparam(0, [%d]) = %ld\n", - param->sched_priority, rc); + const int pid = getpid(); + const char *pid_str = pidns_pid2str(PT_TGID); + + long rc = syscall(__NR_sched_getparam, pid, param); + pidns_print_leader(); + printf("sched_getparam(%d%s, [%d]) = %ld\n", + pid, pid_str, param->sched_priority, rc); param->sched_priority = -1; - rc = syscall(__NR_sched_setparam, 0, param); - printf("sched_setparam(0, [%d]) = %ld %s (%m)\n", + rc = syscall(__NR_sched_setparam, pid, param); + pidns_print_leader(); + printf("sched_setparam(%d%s, [%d]) = %ld %s (%m)\n", + pid, pid_str, param->sched_priority, rc, errno2name()); + pidns_print_leader(); puts("+++ exited with 0 +++"); return 0; } diff --git a/tests/sched_xetscheduler--pidns-translation.c b/tests/sched_xetscheduler--pidns-translation.c new file mode 100644 index 00000000..78b794b2 --- /dev/null +++ b/tests/sched_xetscheduler--pidns-translation.c @@ -0,0 +1,2 @@ +#define PIDNS_TRANSLATION +#include "sched_xetscheduler.c" diff --git a/tests/sched_xetscheduler.c b/tests/sched_xetscheduler.c index 047e8676..91b5e32d 100644 --- a/tests/sched_xetscheduler.c +++ b/tests/sched_xetscheduler.c @@ -7,6 +7,7 @@ #include "tests.h" #include "scno.h" +#include "pidns.h" #if defined __NR_sched_getscheduler && defined __NR_sched_setscheduler @@ -17,8 +18,13 @@ int main(void) { + PIDNS_TEST_INIT; + TAIL_ALLOC_OBJECT_CONST_PTR(struct sched_param, param); - long rc = syscall(__NR_sched_getscheduler, 0); + const int pid = getpid(); + const char *pid_str = pidns_pid2str(PT_TGID); + + long rc = syscall(__NR_sched_getscheduler, pid); const char *scheduler; switch (rc) { case SCHED_FIFO: @@ -50,33 +56,43 @@ main(void) default: scheduler = "SCHED_OTHER"; } - printf("sched_getscheduler(0) = %ld (%s)\n", - rc, scheduler); + pidns_print_leader(); + printf("sched_getscheduler(%d%s) = %ld (%s)\n", + pid, pid_str, rc, scheduler); rc = syscall(__NR_sched_getscheduler, -1); + pidns_print_leader(); printf("sched_getscheduler(-1) = %s\n", sprintrc(rc)); param->sched_priority = -1; - rc = syscall(__NR_sched_setscheduler, 0, SCHED_FIFO, NULL); - printf("sched_setscheduler(0, SCHED_FIFO, NULL) = %s\n", sprintrc(rc)); + rc = syscall(__NR_sched_setscheduler, pid, SCHED_FIFO, NULL); + pidns_print_leader(); + printf("sched_setscheduler(%d%s, SCHED_FIFO, NULL) = %s\n", + pid, pid_str, sprintrc(rc)); - rc = syscall(__NR_sched_setscheduler, 0, SCHED_FIFO, param + 1); - printf("sched_setscheduler(0, SCHED_FIFO, %p) = %s\n", param + 1, - sprintrc(rc)); + rc = syscall(__NR_sched_setscheduler, pid, SCHED_FIFO, param + 1); + pidns_print_leader(); + printf("sched_setscheduler(%d%s, SCHED_FIFO, %p) = %s\n", + pid, pid_str, param + 1, sprintrc(rc)); - rc = syscall(__NR_sched_setscheduler, 0, 0xfaceda7a, param); - printf("sched_setscheduler(0, %#x /* SCHED_??? */, [%d]) = %s\n", - 0xfaceda7a, param->sched_priority, sprintrc(rc)); + rc = syscall(__NR_sched_setscheduler, pid, 0xfaceda7a, param); + pidns_print_leader(); + printf("sched_setscheduler(%d%s, %#x /* SCHED_??? */, [%d]) = %s\n", + pid, pid_str, 0xfaceda7a, + param->sched_priority, sprintrc(rc)); rc = syscall(__NR_sched_setscheduler, -1, SCHED_FIFO, param); + pidns_print_leader(); printf("sched_setscheduler(-1, SCHED_FIFO, [%d]) = %s\n", param->sched_priority, sprintrc(rc)); - rc = syscall(__NR_sched_setscheduler, 0, SCHED_FIFO, param); - printf("sched_setscheduler(0, SCHED_FIFO, [%d]) = %s\n", - param->sched_priority, sprintrc(rc)); + rc = syscall(__NR_sched_setscheduler, pid, SCHED_FIFO, param); + pidns_print_leader(); + printf("sched_setscheduler(%d%s, SCHED_FIFO, [%d]) = %s\n", + pid, pid_str, param->sched_priority, sprintrc(rc)); + pidns_print_leader(); puts("+++ exited with 0 +++"); return 0; } diff --git a/tests/signal_receive--pidns-translation.c b/tests/signal_receive--pidns-translation.c new file mode 100644 index 00000000..b4e3b2f8 --- /dev/null +++ b/tests/signal_receive--pidns-translation.c @@ -0,0 +1,2 @@ +#define PIDNS_TRANSLATION +#include "signal_receive.c" diff --git a/tests/signal_receive.c b/tests/signal_receive.c index ad3b4ebd..70441a9e 100644 --- a/tests/signal_receive.c +++ b/tests/signal_receive.c @@ -8,6 +8,7 @@ */ #include "tests.h" +#include "pidns.h" #include #include #include @@ -26,10 +27,13 @@ handler(int sig, siginfo_t *info, void *ucontext) int main(void) { + PIDNS_TEST_INIT; + static const char prefix[] = "KERNEL BUG"; int printed = 0; const int pid = getpid(); + const char *pid_str = pidns_pid2str(PT_TGID); const int uid = geteuid(); for (int sig = 1; sig <= 31; ++sig) { @@ -73,10 +77,13 @@ main(void) const int e_pid = s_pid; const int e_uid = s_uid; #endif - printf("kill(%d, %s) = 0\n", pid, signal2name(sig)); - printf("--- %s {si_signo=%s, si_code=SI_USER, si_pid=%d" + pidns_print_leader(); + printf("kill(%d%s, %s) = 0\n", pid, pid_str, signal2name(sig)); + pidns_print_leader(); + printf("--- %s {si_signo=%s, si_code=SI_USER, si_pid=%d%s" ", si_uid=%d} ---\n", - signal2name(sig), signal2name(e_sig), e_pid, e_uid); + signal2name(sig), signal2name(e_sig), + e_pid, pid_str, e_uid); if (s_code || sig != s_sig || pid != s_pid || uid != s_uid) { /* @@ -91,11 +98,11 @@ main(void) } fprintf(stderr, "%s: expected: si_signo=%d, si_code=%d" - ", si_pid=%d, si_uid=%d\n" + ", si_pid=%d%s, si_uid=%d\n" "%s: received: si_signo=%d, si_code=%d" - ", si_pid=%d, si_uid=%d\n", - prefix, sig, SI_USER, pid, uid, - prefix, sig, s_code, s_pid, s_uid); + ", si_pid=%d%s, si_uid=%d\n", + prefix, sig, SI_USER, pid, pid_str, uid, + prefix, sig, s_code, s_pid, pid_str, s_uid); } } @@ -104,6 +111,7 @@ main(void) "*** PLEASE FIX THE KERNEL ***\n", prefix); } + pidns_print_leader(); puts("+++ exited with 0 +++"); return 0; } diff --git a/tests/so_peercred--pidns-translation.c b/tests/so_peercred--pidns-translation.c new file mode 100644 index 00000000..402bbcfe --- /dev/null +++ b/tests/so_peercred--pidns-translation.c @@ -0,0 +1,2 @@ +#define PIDNS_TRANSLATION +#include "so_peercred.c" diff --git a/tests/so_peercred.c b/tests/so_peercred.c index 151bb175..20188bdb 100644 --- a/tests/so_peercred.c +++ b/tests/so_peercred.c @@ -9,6 +9,7 @@ */ #include "tests.h" +#include "pidns.h" #include #include @@ -53,6 +54,8 @@ so_str(void) int main(void) { + PIDNS_TEST_INIT; + TAIL_ALLOC_OBJECT_CONST_PTR(struct ucred, peercred); TAIL_ALLOC_OBJECT_CONST_PTR(socklen_t, len); @@ -75,6 +78,8 @@ main(void) struct ucred *const gid_truncated = tail_alloc(sizeof_gid_truncated); + const char *pid_str = pidns_pid2str(PT_TGID); + int sv[2]; if (socketpair(AF_UNIX, SOCK_STREAM, 0, sv)) perror_msg_and_skip("socketpair AF_UNIX SOCK_STREAM"); @@ -82,8 +87,10 @@ main(void) /* classic getsockopt */ *len = sizeof(*peercred); get_peercred(sv[0], peercred, len); + pidns_print_leader(); printf("getsockopt(%d, %s", sv[0], so_str()); PRINT_FIELD_D(", {", *peercred, pid); + printf("%s", pid_str); PRINT_FIELD_UID(", ", *peercred, uid); PRINT_FIELD_UID(", ", *peercred, gid); printf("}, [%d]) = %s\n", *len, errstr); @@ -91,14 +98,17 @@ main(void) /* getsockopt with zero optlen */ *len = 0; get_peercred(sv[0], peercred, len); + pidns_print_leader(); printf("getsockopt(%d, %s, %p, [0]) = %s\n", sv[0], so_str(), peercred, errstr); /* getsockopt with optlen larger than necessary - shortened */ *len = sizeof(*peercred) + 1; get_peercred(sv[0], peercred, len); + pidns_print_leader(); printf("getsockopt(%d, %s", sv[0], so_str()); PRINT_FIELD_D(", {", *peercred, pid); + printf("%s", pid_str); PRINT_FIELD_UID(", ", *peercred, uid); PRINT_FIELD_UID(", ", *peercred, gid); printf("}, [%u->%d]) = %s\n", @@ -110,6 +120,7 @@ main(void) */ *len = sizeof_pid_truncated; get_peercred(sv[0], pid_truncated, len); + pidns_print_leader(); printf("getsockopt(%d, %s, {pid=", sv[0], so_str()); print_quoted_hex(pid_truncated, *len); printf("}, [%d]) = %s\n", *len, errstr); @@ -120,8 +131,10 @@ main(void) */ *len = sizeof_pid; get_peercred(sv[0], pid, len); + pidns_print_leader(); printf("getsockopt(%d, %s", sv[0], so_str()); PRINT_FIELD_D(", {", *pid, pid); + printf("%s", pid_str); printf("}, [%d]) = %s\n", *len, errstr); /* @@ -136,8 +149,10 @@ main(void) * to struct ucred.pid field. */ memcpy(uid, uid_truncated, sizeof_uid_truncated); + pidns_print_leader(); printf("getsockopt(%d, %s", sv[0], so_str()); PRINT_FIELD_D(", {", *uid, pid); + printf("%s", pid_str); printf(", uid="); print_quoted_hex(&uid->uid, sizeof_uid_truncated - offsetof(struct ucred, uid)); @@ -149,8 +164,10 @@ main(void) */ *len = sizeof_uid; get_peercred(sv[0], uid, len); + pidns_print_leader(); printf("getsockopt(%d, %s", sv[0], so_str()); PRINT_FIELD_D(", {", *uid, pid); + printf("%s", pid_str); PRINT_FIELD_UID(", ", *uid, uid); printf("}, [%d]) = %s\n", *len, errstr); @@ -166,8 +183,10 @@ main(void) * to struct ucred.pid and struct ucred.uid fields. */ memcpy(peercred, gid_truncated, sizeof_gid_truncated); + pidns_print_leader(); printf("getsockopt(%d, %s", sv[0], so_str()); PRINT_FIELD_D(", {", *peercred, pid); + printf("%s", pid_str); PRINT_FIELD_UID(", ", *peercred, uid); printf(", gid="); print_quoted_hex(&peercred->gid, sizeof_gid_truncated - @@ -177,14 +196,17 @@ main(void) /* getsockopt optval EFAULT */ *len = sizeof(*peercred); get_peercred(sv[0], &peercred->uid, len); + pidns_print_leader(); printf("getsockopt(%d, %s, %p, [%d]) = %s\n", sv[0], so_str(), &peercred->uid, *len, errstr); /* getsockopt optlen EFAULT */ get_peercred(sv[0], peercred, len + 1); + pidns_print_leader(); printf("getsockopt(%d, %s, %p, %p) = %s\n", sv[0], so_str(), peercred, len + 1, errstr); + pidns_print_leader(); puts("+++ exited with 0 +++"); return 0; } diff --git a/tests/xet_robust_list--pidns-translation.c b/tests/xet_robust_list--pidns-translation.c new file mode 100644 index 00000000..e0477267 --- /dev/null +++ b/tests/xet_robust_list--pidns-translation.c @@ -0,0 +1,2 @@ +#define PIDNS_TRANSLATION +#include "xet_robust_list.c" diff --git a/tests/xet_robust_list.c b/tests/xet_robust_list.c index 43239c8b..b5751b0a 100644 --- a/tests/xet_robust_list.c +++ b/tests/xet_robust_list.c @@ -8,6 +8,7 @@ #include "tests.h" #include "scno.h" +#include "pidns.h" #if defined __NR_get_robust_list && defined __NR_set_robust_list @@ -30,27 +31,36 @@ sprintaddr(void *addr) int main(void) { + PIDNS_TEST_INIT; + const pid_t pid = getpid(); + const char *pid_str = pidns_pid2str(PT_TGID); const long long_pid = (unsigned long) (0xdeadbeef00000000LL | pid); TAIL_ALLOC_OBJECT_CONST_PTR(void *, p_head); TAIL_ALLOC_OBJECT_CONST_PTR(size_t, p_len); if (syscall(__NR_get_robust_list, long_pid, p_head, p_len)) perror_msg_and_skip("get_robust_list"); - printf("get_robust_list(%d, [%s], [%lu]) = 0\n", - (int) pid, sprintaddr(*p_head), (unsigned long) *p_len); + pidns_print_leader(); + printf("get_robust_list(%d%s, [%s], [%lu]) = 0\n", + pid, pid_str, sprintaddr(*p_head), + (unsigned long) *p_len); void *head = tail_alloc(*p_len); if (syscall(__NR_set_robust_list, head, *p_len)) perror_msg_and_skip("set_robust_list"); + pidns_print_leader(); printf("set_robust_list(%p, %lu) = 0\n", head, (unsigned long) *p_len); if (syscall(__NR_get_robust_list, long_pid, p_head, p_len)) perror_msg_and_skip("get_robust_list"); - printf("get_robust_list(%d, [%s], [%lu]) = 0\n", - (int) pid, sprintaddr(*p_head), (unsigned long) *p_len); + pidns_print_leader(); + printf("get_robust_list(%d%s, [%s], [%lu]) = 0\n", + pid, pid_str, sprintaddr(*p_head), + (unsigned long) *p_len); + pidns_print_leader(); puts("+++ exited with 0 +++"); return 0; } diff --git a/tests/xetpgid--pidns-translation.c b/tests/xetpgid--pidns-translation.c new file mode 100644 index 00000000..b6469628 --- /dev/null +++ b/tests/xetpgid--pidns-translation.c @@ -0,0 +1,2 @@ +#define PIDNS_TRANSLATION +#include "xetpgid.c" diff --git a/tests/xetpgid.c b/tests/xetpgid.c index 9b070af2..411edfc7 100644 --- a/tests/xetpgid.c +++ b/tests/xetpgid.c @@ -10,6 +10,7 @@ #include "tests.h" #include "scno.h" +#include "pidns.h" #if defined __NR_getpgid && defined __NR_setpgid @@ -19,13 +20,21 @@ int main(void) { - const int pid = getpid(); - long rc = syscall(__NR_getpgid, F8ILL_KULONG_MASK | pid); - printf("getpgid(%d) = %ld\n", pid, rc); - - rc = syscall(__NR_setpgid, F8ILL_KULONG_MASK, F8ILL_KULONG_MASK | pid); - printf("setpgid(0, %d) = %ld\n", pid, rc); + PIDNS_TEST_INIT; + const int pid = getpid(); + long pgid = syscall(__NR_getpgid, F8ILL_KULONG_MASK | pid); + pidns_print_leader(); + printf("getpgid(%d%s) = %ld%s\n", pid, pidns_pid2str(PT_TGID), + pgid, pidns_pid2str(PT_PGID)); + + long rc = syscall(__NR_setpgid, F8ILL_KULONG_MASK, + F8ILL_KULONG_MASK | pgid); + pidns_print_leader(); + printf("setpgid(0, %ld%s) = %s\n", pgid, pidns_pid2str(PT_PGID), + sprintrc(rc)); + + pidns_print_leader(); puts("+++ exited with 0 +++"); return 0; } diff --git a/tests/xetpriority--pidns-translation.c b/tests/xetpriority--pidns-translation.c new file mode 100644 index 00000000..c93669cb --- /dev/null +++ b/tests/xetpriority--pidns-translation.c @@ -0,0 +1,2 @@ +#define PIDNS_TRANSLATION +#include "xetpriority.c" diff --git a/tests/xetpriority.c b/tests/xetpriority.c index 2d61bd10..dd38217d 100644 --- a/tests/xetpriority.c +++ b/tests/xetpriority.c @@ -7,6 +7,7 @@ #include "tests.h" #include "scno.h" +#include "pidns.h" #if defined __NR_getpriority && defined __NR_setpriority @@ -17,15 +18,30 @@ int main(void) { + PIDNS_TEST_INIT; + const int pid = getpid(); + const int pgid = getpgid(0); + long rc = syscall(__NR_getpriority, PRIO_PROCESS, F8ILL_KULONG_MASK | pid); - printf("getpriority(PRIO_PROCESS, %d) = %ld\n", pid, rc); + pidns_print_leader(); + printf("getpriority(PRIO_PROCESS, %d%s) = %ld\n", + pid, pidns_pid2str(PT_TGID), rc); rc = syscall(__NR_setpriority, PRIO_PROCESS, F8ILL_KULONG_MASK | pid, F8ILL_KULONG_MASK); - printf("setpriority(PRIO_PROCESS, %d, 0) = %s\n", pid, sprintrc(rc)); + pidns_print_leader(); + printf("setpriority(PRIO_PROCESS, %d%s, 0) = %s\n", + pid, pidns_pid2str(PT_TGID), sprintrc(rc)); + + rc = syscall(__NR_getpriority, PRIO_PGRP, + F8ILL_KULONG_MASK | pgid); + pidns_print_leader(); + printf("getpriority(PRIO_PGRP, %d%s) = %ld\n", + pgid, pidns_pid2str(PT_PGID), rc); + pidns_print_leader(); puts("+++ exited with 0 +++"); return 0; } -- 2.27.0 From ldv at altlinux.org Sat Aug 8 22:07:56 2020 From: ldv at altlinux.org (Dmitry V. Levin) Date: Sun, 9 Aug 2020 01:07:56 +0300 Subject: [PATCH v7 1/5] PID namespace translation support In-Reply-To: <20200808211437.469898-2-uzonyi.akos@gmail.com> References: <20200808211437.469898-1-uzonyi.akos@gmail.com> <20200808211437.469898-2-uzonyi.akos@gmail.com> Message-ID: <20200808220756.GA23517@altlinux.org> On Sat, Aug 08, 2020 at 11:14:33PM +0200, ?kos Uzonyi wrote: [...] > --- a/NEWS > +++ b/NEWS > @@ -22,6 +22,7 @@ Noteworthy changes in release 5.8 (2020-08-06) > KEYCTL_*, KVM_*, LOOP_*, NDA_*, RTC_*, TCA_*, STATX_*, and *_MAGIC > constants. > * Updated lists of ioctl commands from Linux 5.8. > + * Added --pidns-translation option for PID namespace translation. > > * Bug fixes > * Added statx syscall to %fstat trace class. This went to the old section of the NEWS. > --- a/defs.h > +++ b/defs.h > @@ -983,6 +1005,28 @@ print_local_array_ex(struct tcb *tcp, > extern kernel_ulong_t * > fetch_indirect_syscall_args(struct tcb *, kernel_ulong_t addr, unsigned int n_args); > > +extern void pidns_init(void); > + > +/** > + * Returns the pid of the tracee as present in /proc of the tracer (can be > + * different from tcp->pid if /proc and the tracee process are in different PID > + * namespaces). > + */ > +extern int get_proc_pid(struct tcb *); I though it can be different only if /proc and the _tracer_ are in different PID namespaces. > + > +/** > + * Translates a pid from tracee's namespace to our namepace. > + * > + * @param tcp The tcb of the tracee > + * (NULL: from_id is in strace's namespace. Useful for > + * getting the proc PID of from_id) > + * @param from_id The id to be translated > + * @param type The PID type of from_id > + * @param proc_pid_ptr If not NULL, writes the proc PID to this location > + */ > +extern int translate_pid(struct tcb *, int dest_id, enum pid_type type, > + int *proc_pid_ptr); Sometimes this function returns the translated pid, sometimes it doesn't. Could you document the return value, please? Also, could you check whether all users of this function do proper error handling, please? I'm afraid sometimes they just go on with 0 instead of translated pid. > @@ -1058,6 +1102,15 @@ printfd(struct tcb *tcp, int fd) > * of the tracee the descriptor tcp). This is a stub. > */ > extern void printfd_pid_tracee_ns(struct tcb *tcp, pid_t pid, int fd); > + > +/** Prints a PID in the tracee's PID namespace */ > +extern void printpid(struct tcb *, int pid, enum pid_type type); This is slightly ambiguous. One might think it translates a pid into the tracee's PID namespace and prints it, which is certainly not the case. I think this function prints a pid which is specified in the tracee's PID namespace. [...] > +int > +translate_pid(struct tcb *tcp, int from_id, enum pid_type type, > + int *proc_pid_ptr) > +{ > + if (from_id <= 0 || type < 0 || type >= PT_COUNT) > + return 0; > + > + /* If translation is trivial */ > + if ((!tcp || get_ns(tcp) == get_our_ns()) && > + (is_proc_ours() || !proc_pid_ptr)) { I suggest checking for !proc_pid_ptr first because its very cheap. -- ldv From uzonyi.akos at gmail.com Sun Aug 9 14:13:01 2020 From: uzonyi.akos at gmail.com (=?UTF-8?q?=C3=81kos=20Uzonyi?=) Date: Sun, 9 Aug 2020 16:13:01 +0200 Subject: [PATCH v8 0/5] [PIDNS] Final Message-ID: <20200809141306.477539-1-uzonyi.akos@gmail.com> From: Uzonyi ?kos Changes in v8: - translate_pid: document return value; check !proc_pid first - NEWS: move to new section - get_proc_pid, printpid: fix comment - Check if translation failed Changes in v7: - Run uniq on gettid--pidns-translation test output - Add comment to printpid - translate_id: do not call get_our_ns if not necessary - Remove unnecessary parentheses - Fix commit message of last commit (s/-Y/--pidns-translation/) - get_proc_pid: remove unnecessary optimization - trie.c: remove #include - Add clarification to get_proc_pid's comment - Fix typos - trie.c: ptr_sz_lg use void* in sizeof - trie_get_node_size: fix comment - trie.c: remove "TODO: overflow" - ipc_shmctl.c: remove duplicate #include "print_field.h" Changes in v6: - Add function with documentation for creating tries - Do not use -1ULL as error indicator in tcb.pid_ns - Use unsigned int (instead of uint64_t) for NS IDs - Add constant for NS ID size. - Modify get_proc_pid a bit - Die if trie creation fails Changes in v5: - Squash "Use printpid in *" commits - Makefile.am: move adding getpid.c to "Use printpid in decoders" - Remove pid_ns_inited field from struct tcb - strace.1.in: remove -Y flag - Use tprints instead of tprintf where possible - Make some global variables static - pidns_init: remove "inited" bool variable - Make printpid_translation static - tests/pidns.c: refactor a bit - check_ns_ioctl: fix error msg - defs.h: Move adding get_proc_pid to "PID namespace translation support" - Remove tcp paramter name from declarations - Update printfd_pid_tracee_ns documentation - Use named constants for trie_create arguments - Add documentation comments - Add printpid_tgid_pgid function - Delete get_pid_max function; use global variables instead - Refactor trie: - Move key_size argument - Remove support for TRIE_SET - Merge trie_create, trie_init, trie_check functions - trie_free_node: make static, fix "node" argument type - Add max_depth field - Reorder functions - Extract common parts of trie_get, trie_set Changes in v4: - Skip tests if NS_* ioctl commands are not supported - Improve documentation in pidns.h - Use pipe for init process termination (instead of SIGKILL) - Add PIDNS_TEST_INIT macro - Remove "ifdef __NR_gettid" - Fix fork--pidns-tranlsation.test: skip if unshare fails with EPERM - Use debug message instead of normal message in some cases - Rename some labels - Rewrite get_ns function - Remove O_NONBLOCK from open(/proc//ns/pid) Changes in v3: - Split accidentally sqashed last commit - Undo modification of tests/pidfd_send_signal.c - Rename kcmp-yY test to kcmp-y--pidns-translation - Skip tests if unshare fails with EPERM - Fix buffer size in pidns_pid2str - Use largefile_wrappers.h macros - Return early if from_ns or our_ns is 0 - Do not call ioctl(NS_GET_PARENT) again, if first failed with ENOTTY - Skip pidns tests if Linux kernel version < 4.9 - Use smaller trie nodes in pidns.c - Remove race condition from fork--pidns-translation test - Move "key_size" to center in trie description - Use PT_TID (not PT_TGID) when translating tcp->pid - Fix get_ns_hierarchy and get_id_list functions - Fix migrate_pages test if syscall succeds - Fix filtering in ioctl_block--pidns-translation.test - Fix -a flag value in xetpriority test Changes in v2: - Add missing header files to Makefile - Fix pointer-to-int-cast errors - Fix unused-result errors - Use perror_msg instead of perror_func_msg where appropriate - Remove tcb parameter of read_int_from_file - Use xsprintf instead of snprintf - Refactor get_pid_max, get_ns_hierarchy, get_id_list functions - Remove -Y flag - Improve documentation of trie - Fix printing of f_owner_ex struct - Use printpid for F_GETOWN, F_SETOWN fcntl command arguments - Use printpid for shmid_ds.shm_cpid, shmid_ds.shm_clid - Call pidns_init before parsing arguments ?kos Uzonyi (5): PID namespace translation support Use printpid in decoders Use get_proc_pid for /proc paths Implement testing framework for pidns Add tests for PID namespace translation Makefile.am | 4 + NEWS | 1 + affinity.c | 6 +- block.c | 2 +- bpf.c | 2 +- capability.c | 4 +- clone.c | 14 +- defs.h | 61 +- fcntl.c | 24 +- get_robust_list.c | 3 +- getpid.c | 46 ++ ioprio.c | 26 +- ipc_shmctl.c | 4 +- kcmp.c | 5 +- largefile_wrappers.h | 2 + linux/dummy.h | 8 +- mmap_cache.c | 2 +- msghdr.c | 2 +- net.c | 2 +- netlink.c | 5 +- numa.c | 6 +- pathtrace.c | 7 +- pidfd_open.c | 2 +- pidns.c | 604 ++++++++++++++++++ print_fields.h | 24 + printsiginfo.c | 2 +- process.c | 3 +- process_vm.c | 6 +- resource.c | 27 +- sched.c | 25 +- signal.c | 21 +- sockaddr.c | 2 +- strace.1.in | 4 + strace.c | 11 +- syscall.c | 15 + tests/.gitignore | 31 + tests/Makefile.am | 38 ++ tests/fcntl--pidns-translation.c | 2 + tests/fcntl-common.c | 82 ++- tests/fcntl.c | 1 + tests/fcntl64--pidns-translation.c | 2 + tests/fcntl64.c | 3 + tests/fork--pidns-translation.awk | 15 + tests/fork--pidns-translation.c | 69 ++ tests/fork--pidns-translation.test | 16 + tests/gen_tests.in | 29 +- tests/getpgrp--pidns-translation.c | 2 + tests/getpgrp.c | 8 +- tests/getpid--pidns-translation.c | 2 + tests/getpid.c | 8 +- tests/getsid--pidns-translation.c | 2 + tests/getsid.c | 9 +- tests/gettid--pidns-translation.c | 2 + tests/gettid--pidns-translation.test | 20 + tests/gettid.c | 8 +- tests/init.sh | 31 + tests/ioctl_block--pidns-translation.c | 2 + tests/ioctl_block--pidns-translation.test | 24 + tests/ioctl_block.c | 24 +- tests/ioprio--pidns-translation.c | 2 + tests/ioprio.c | 54 +- tests/kcmp-y--pidns-translation.c | 2 + tests/kcmp.c | 36 +- tests/kill--pidns-translation.c | 2 + tests/kill.c | 12 +- tests/migrate_pages--pidns-translation.c | 2 + tests/migrate_pages.c | 17 +- tests/move_pages--pidns-translation.c | 2 + tests/move_pages.c | 51 +- tests/net-sockaddr--pidns-translation.c | 2 + tests/net-sockaddr.c | 66 +- tests/netlink_audit--pidns-translation.c | 2 + tests/netlink_audit--pidns-translation.test | 13 + tests/netlink_audit.c | 11 +- tests/pidfd_open--pidns-translation.c | 2 + tests/pidfd_open.c | 21 +- tests/pidfd_send_signal--pidns-translation.c | 2 + tests/pidfd_send_signal.c | 13 +- tests/pidns.c | 214 +++++++ tests/pidns.h | 56 ++ tests/prlimit64--pidns-translation.c | 2 + tests/prlimit64.c | 17 +- tests/process_vm_readv--pidns-translation.c | 2 + tests/process_vm_readv_writev.c | 27 +- tests/process_vm_writev--pidns-translation.c | 2 + tests/rt_sigqueueinfo--pidns-translation.c | 2 + tests/rt_sigqueueinfo.c | 15 +- tests/rt_tgsigqueueinfo--pidns-translation.c | 2 + tests/rt_tgsigqueueinfo.c | 26 +- tests/sched_xetaffinity--pidns-translation.c | 2 + tests/sched_xetaffinity.c | 31 +- tests/sched_xetattr--pidns-translation.c | 2 + tests/sched_xetattr.c | 47 +- tests/sched_xetparam--pidns-translation.c | 2 + tests/sched_xetparam.c | 20 +- tests/sched_xetscheduler--pidns-translation.c | 2 + tests/sched_xetscheduler.c | 44 +- tests/signal_receive--pidns-translation.c | 2 + tests/signal_receive.c | 22 +- tests/so_peercred--pidns-translation.c | 2 + tests/so_peercred.c | 22 + tests/xet_robust_list--pidns-translation.c | 2 + tests/xet_robust_list.c | 18 +- tests/xetpgid--pidns-translation.c | 2 + tests/xetpgid.c | 21 +- tests/xetpriority--pidns-translation.c | 2 + tests/xetpriority.c | 20 +- trie.c | 248 +++++++ trie.h | 89 +++ util.c | 31 +- wait.c | 36 +- 111 files changed, 2500 insertions(+), 256 deletions(-) create mode 100644 getpid.c create mode 100644 pidns.c create mode 100644 tests/fcntl--pidns-translation.c create mode 100644 tests/fcntl64--pidns-translation.c create mode 100644 tests/fork--pidns-translation.awk create mode 100644 tests/fork--pidns-translation.c create mode 100755 tests/fork--pidns-translation.test create mode 100644 tests/getpgrp--pidns-translation.c create mode 100644 tests/getpid--pidns-translation.c create mode 100644 tests/getsid--pidns-translation.c create mode 100644 tests/gettid--pidns-translation.c create mode 100755 tests/gettid--pidns-translation.test create mode 100644 tests/ioctl_block--pidns-translation.c create mode 100755 tests/ioctl_block--pidns-translation.test create mode 100644 tests/ioprio--pidns-translation.c create mode 100644 tests/kcmp-y--pidns-translation.c create mode 100644 tests/kill--pidns-translation.c create mode 100644 tests/migrate_pages--pidns-translation.c create mode 100644 tests/move_pages--pidns-translation.c create mode 100644 tests/net-sockaddr--pidns-translation.c create mode 100644 tests/netlink_audit--pidns-translation.c create mode 100755 tests/netlink_audit--pidns-translation.test create mode 100644 tests/pidfd_open--pidns-translation.c create mode 100644 tests/pidfd_send_signal--pidns-translation.c create mode 100644 tests/pidns.c create mode 100644 tests/pidns.h create mode 100644 tests/prlimit64--pidns-translation.c create mode 100644 tests/process_vm_readv--pidns-translation.c create mode 100644 tests/process_vm_writev--pidns-translation.c create mode 100644 tests/rt_sigqueueinfo--pidns-translation.c create mode 100644 tests/rt_tgsigqueueinfo--pidns-translation.c create mode 100644 tests/sched_xetaffinity--pidns-translation.c create mode 100644 tests/sched_xetattr--pidns-translation.c create mode 100644 tests/sched_xetparam--pidns-translation.c create mode 100644 tests/sched_xetscheduler--pidns-translation.c create mode 100644 tests/signal_receive--pidns-translation.c create mode 100644 tests/so_peercred--pidns-translation.c create mode 100644 tests/xet_robust_list--pidns-translation.c create mode 100644 tests/xetpgid--pidns-translation.c create mode 100644 tests/xetpriority--pidns-translation.c create mode 100644 trie.c create mode 100644 trie.h -- 2.27.0 From uzonyi.akos at gmail.com Sun Aug 9 14:13:02 2020 From: uzonyi.akos at gmail.com (=?UTF-8?q?=C3=81kos=20Uzonyi?=) Date: Sun, 9 Aug 2020 16:13:02 +0200 Subject: [PATCH v8 1/5] PID namespace translation support In-Reply-To: <20200809141306.477539-1-uzonyi.akos@gmail.com> References: <20200809141306.477539-1-uzonyi.akos@gmail.com> Message-ID: <20200809141306.477539-2-uzonyi.akos@gmail.com> * defs.h (pidns_translation): New variable. (tcb): Add pid_ns field. (RVAL_MASK): Change value from 013 to 017. (RVAL_TID, RVAL_SID, RVAL_TGID, RVAL_PGID): New definitions. (pid_type): New enum. (pidns_init, translate_pid, get_proc_pid, printpid, printpid_tgid_pgid): New function declarations. * largefile_wrappers.h (fstat_fd): New macro. * pidns.c: New file. * trie.c: New file. * trie.h: New file. * Makefile.am (libstrace_a_SOURCES): Add trie.c, trie.h, pidns.c. * strace.c (pidns_translation): New variable. (init): Add --pidns-translation option. * syscall.c (syscall_exiting_trace): Handle RVAL_* return values. * NEWS: Mention this. * strace.1.in: Add description for new option. Co-Authored-by: Eugene Syromyatnikov --- Makefile.am | 3 + NEWS | 1 + defs.h | 56 +++- largefile_wrappers.h | 2 + pidns.c | 604 +++++++++++++++++++++++++++++++++++++++++++ strace.1.in | 4 + strace.c | 9 + syscall.c | 15 ++ trie.c | 248 ++++++++++++++++++ trie.h | 89 +++++++ 10 files changed, 1030 insertions(+), 1 deletion(-) create mode 100644 pidns.c create mode 100644 trie.c create mode 100644 trie.h diff --git a/Makefile.am b/Makefile.am index f5447811..73c22035 100644 --- a/Makefile.am +++ b/Makefile.am @@ -233,6 +233,7 @@ libstrace_a_SOURCES = \ personality.c \ pidfd_getfd.c \ pidfd_open.c \ + pidns.c \ pkeys.c \ poll.c \ prctl.c \ @@ -344,6 +345,8 @@ libstrace_a_SOURCES = \ time.c \ times.c \ trace_event.h \ + trie.c \ + trie.h \ truncate.c \ ubi.c \ ucopy.c \ diff --git a/NEWS b/NEWS index 10039ceb..c3c5c162 100644 --- a/NEWS +++ b/NEWS @@ -2,6 +2,7 @@ Noteworthy changes in release ?.? (????-??-??) ============================================== * Improvements + * Added --pidns-translation option for PID namespace translation. * Bug fixes diff --git a/defs.h b/defs.h index f7ac54f3..511a92a2 100644 --- a/defs.h +++ b/defs.h @@ -280,6 +280,13 @@ struct tcb { struct timespec etime; /* Syscall entry time (CLOCK_MONOTONIC) */ struct timespec delay_expiration_time; /* When does the delay end */ + /* + * The ID of the PID namespace of this process + * (inode number of /proc//ns/pid) + * (0: not initialized) + */ + unsigned int pid_ns; + struct mmap_cache_t *mmap_cache; /* @@ -413,7 +420,11 @@ extern const struct xlat whence_codes[]; # define RVAL_HEX 001 /* hex format */ # define RVAL_OCTAL 002 /* octal format */ # define RVAL_FD 010 /* file descriptor */ -# define RVAL_MASK 013 /* mask for these values */ +# define RVAL_TID 011 /* task ID */ +# define RVAL_SID 012 /* session ID */ +# define RVAL_TGID 013 /* thread group ID */ +# define RVAL_PGID 014 /* process group ID */ +# define RVAL_MASK 017 /* mask for these values */ # define RVAL_STR 020 /* Print `auxstr' field after return val */ # define RVAL_NONE 040 /* Print nothing */ @@ -428,6 +439,16 @@ extern const struct xlat whence_codes[]; # define indirect_ipccall(tcp) (tcp_sysent(tcp)->sys_flags & TRACE_INDIRECT_SUBCALL) +enum pid_type { + PT_TID, + PT_TGID, + PT_PGID, + PT_SID, + + PT_COUNT, + PT_NONE = -1 +}; + enum sock_proto { SOCK_PROTO_UNKNOWN, SOCK_PROTO_UNIX, @@ -469,6 +490,7 @@ extern int Tflag_scale; extern int Tflag_width; extern bool iflag; extern bool count_wallclock; +extern unsigned int pidns_translation; /* are we filtering traces based on paths? */ extern struct path_set { const char **paths_selected; @@ -983,6 +1005,29 @@ print_local_array_ex(struct tcb *tcp, extern kernel_ulong_t * fetch_indirect_syscall_args(struct tcb *, kernel_ulong_t addr, unsigned int n_args); +extern void pidns_init(void); + +/** + * Returns the pid of the tracee as present in /proc of the tracer (can be + * different from tcp->pid if /proc and the tracer process are in different PID + * namespaces). + */ +extern int get_proc_pid(struct tcb *); + +/** + * Translates a pid from tracee's namespace to our namepace. + * + * @param tcp The tcb of the tracee + * (NULL: from_id is in strace's namespace. Useful for + * getting the proc PID of from_id) + * @param from_id The id to be translated + * @param type The PID type of from_id + * @param proc_pid_ptr If not NULL, writes the proc PID to this location + * @return The translated id, or 0 if translation fails. + */ +extern int translate_pid(struct tcb *, int dest_id, enum pid_type type, + int *proc_pid_ptr); + extern void dumpiov_in_msghdr(struct tcb *, kernel_ulong_t addr, kernel_ulong_t data_size); @@ -1058,6 +1103,15 @@ printfd(struct tcb *tcp, int fd) * of the tracee the descriptor tcp). This is a stub. */ extern void printfd_pid_tracee_ns(struct tcb *tcp, pid_t pid, int fd); + +/** Prints a PID specified in the tracee's PID namespace */ +extern void printpid(struct tcb *, int pid, enum pid_type type); + +/** + * Prints pid as a TGID if positive, and PGID if negative + * (like the first argument of kill). + */ +extern void printpid_tgid_pgid(struct tcb *, int pid); extern void print_sockaddr(struct tcb *, const void *sa, int len); extern bool print_inet_addr(int af, const void *addr, unsigned int len, const char *var_name); diff --git a/largefile_wrappers.h b/largefile_wrappers.h index 116e7048..9d8f5c92 100644 --- a/largefile_wrappers.h +++ b/largefile_wrappers.h @@ -29,6 +29,7 @@ # else # define fcntl_fd fcntl # endif +# define fstat_fd fstat64 # define strace_stat_t struct stat64 # define stat_file stat64 # define struct_dirent struct dirent64 @@ -39,6 +40,7 @@ # define open_file open # define fopen_stream fopen # define fcntl_fd fcntl +# define fstat_fd fstat # define strace_stat_t struct stat # define stat_file stat # define struct_dirent struct dirent diff --git a/pidns.c b/pidns.c new file mode 100644 index 00000000..edab73f8 --- /dev/null +++ b/pidns.c @@ -0,0 +1,604 @@ +/* + * Copyright (c) 2020 ?kos Uzonyi + * All rights reserved. + * + * SPDX-License-Identifier: LGPL-2.1-or-later + */ + +#include "defs.h" + + +#include +#include +#include +#include +#include + +#include + +#include +#include +#include +#include + +#include "largefile_wrappers.h" +#include "trie.h" +#include "nsfs.h" +#include "xmalloc.h" +#include "xstring.h" + +/** + * Key: PID NS ID + * Value: a btree: + * Key: a process PID in NS + * Value: the process's PID as present in /proc + */ +static struct trie *ns_pid_to_proc_pid[PT_COUNT]; + +/** + * Key: Proc PID + * Value: struct proc_data + */ +static struct trie *proc_data_cache; + +static bool ns_get_parent_enotty = false; + +static const char tid_str[] = "NSpid:\t"; +static const char tgid_str[] = "NStgid:\t"; +static const char pgid_str[] = "NSpgid:\t"; +static const char sid_str[] = "NSsid:\t"; + +static const struct { + const char *str; + size_t size; +} id_strs[PT_COUNT] = { + [PT_TID] = { tid_str, sizeof(tid_str) - 1 }, + [PT_TGID] = { tgid_str, sizeof(tgid_str) - 1 }, + [PT_PGID] = { pgid_str, sizeof(pgid_str) - 1 }, + [PT_SID] = { sid_str, sizeof(sid_str) - 1 }, +}; + + +/** + * Limit on PID NS hierarchy depth, imposed since Linux 3.7. NS traversal + * is not possible before Linux 4.9, so we consider this limit pretty universal. + */ +#define MAX_NS_DEPTH 32 + +static const size_t ns_id_size = sizeof(unsigned int); +static const uint8_t ptr_sz_lg = (sizeof(void *) == 8 ? 6 : 5); + +static int pid_max; +static uint8_t pid_max_size, pid_max_size_lg; + +struct proc_data { + int proc_pid; + int ns_count; + unsigned int ns_hierarchy[MAX_NS_DEPTH]; + int id_count[PT_COUNT]; + int id_hierarchy[PT_COUNT][MAX_NS_DEPTH]; +}; + +/** + * Helper function for creating a trie. + * + * For node_key_bits and data_block_key_bits 4 is used (so trie height is 32 / 4 + * = 8, and node sizes are 8 byte * 2^4 = 128 bytes), which seems to be a good + * tradeoff between memory usage and lookup time. It should not be too large, + * since there can be large holes between PIDs, and it would be just a waste of + * memory having large nodes with lot of NULL pointers in them. + */ +static struct trie * +create_trie_4(uint8_t key_size, uint8_t item_size_lg, uint64_t empty_value) +{ + struct trie *t = trie_create(key_size, item_size_lg, 4, 4, empty_value); + if (!t) + error_msg_and_die("creating trie failed"); + + return t; +} + +void +pidns_init(void) +{ + if (proc_data_cache) + return; + + pid_max = INT_MAX; + if (read_int_from_file("/proc/sys/kernel/pid_max", &pid_max) < 0) + debug_func_perror_msg("reading /proc/sys/kernel/pid_max"); + pid_max_size = ilog2_32(pid_max - 1) + 1; + pid_max_size_lg = ilog2_32(pid_max_size - 1) + 1; + + for (int i = 0; i < PT_COUNT; i++) + ns_pid_to_proc_pid[i] = create_trie_4(ns_id_size, ptr_sz_lg, 0); + + proc_data_cache = create_trie_4(pid_max_size, ptr_sz_lg, 0); +} + +static void +put_proc_pid(unsigned int ns, int ns_pid, enum pid_type type, int proc_pid) +{ + struct trie *b = (struct trie *) (uintptr_t) trie_get(ns_pid_to_proc_pid[type], ns); + if (!b) { + b = create_trie_4(pid_max_size, pid_max_size_lg, 0); + trie_set(ns_pid_to_proc_pid[type], ns, (uint64_t) (uintptr_t) b); + } + trie_set(b, ns_pid, proc_pid); +} + +static int +get_cached_proc_pid(unsigned int ns, int ns_pid, enum pid_type type) +{ + struct trie *b = (struct trie *) (uintptr_t) + trie_get(ns_pid_to_proc_pid[type], ns); + if (!b) + return 0; + + return trie_get(b, ns_pid); +} + +/** + * Helper function, converts pid to string, or to "self" for pid == 0. + * Uses static buffer for operation. + */ +static const char * +pid_to_str(pid_t pid) +{ + if (!pid) + return "self"; + + static char buf[sizeof("-2147483648")]; + xsprintf(buf, "%d", pid); + return buf; +} + +/** + * Returns a list of PID NS IDs for the specified PID. + * + * @param proc_pid PID (as present in /proc) to get information for. + * @param ns_buf Pointer to buffer that is able to contain at least + * ns_buf_size items. + * @return Amount of NS in list. 0 indicates error. + */ +static size_t +get_ns_hierarchy(int proc_pid, unsigned int *ns_buf, size_t ns_buf_size) +{ + char path[PATH_MAX + 1]; + xsprintf(path, "/proc/%s/ns/pid", pid_to_str(proc_pid)); + + int fd = open_file(path, O_RDONLY); + if (fd < 0) + return 0; + + size_t n = 0; + while (n < ns_buf_size) { + strace_stat_t st; + if (fstat_fd(fd, &st)) + break; + + ns_buf[n++] = st.st_ino; + if (n >= ns_buf_size) + break; + + if (ns_get_parent_enotty) + break; + + int parent_fd = ioctl(fd, NS_GET_PARENT); + if (parent_fd < 0) { + switch (errno) { + case EPERM: + break; + + case ENOTTY: + ns_get_parent_enotty = true; + error_msg("NS_* ioctl commands are not " + "supported by the kernel"); + break; + + default: + perror_func_msg("ioctl(NS_GET_PARENT)"); + break; + } + + break; + } + + close(fd); + fd = parent_fd; + } + + close(fd); + + return n; +} + +/** + * Get list of IDs present in NS* proc status record. IDs are placed as they are + * stored in /proc (from top to bottom of NS hierarchy). + * + * @param proc_pid PID (as present in /proc) to get information for. + * @param id_buf Pointer to buffer that is able to contain at least + * MAX_NS_DEPTH items. Can be NULL. + * @param type Type of ID requested. + * @return Number of items stored in id_list. 0 indicates error. + */ +static size_t +get_id_list(int proc_pid, int *id_buf, enum pid_type type) +{ + const char *ns_str = id_strs[type].str; + size_t ns_str_size = id_strs[type].size; + + size_t n = 0; + + char status_path[PATH_MAX + 1]; + xsprintf(status_path, "/proc/%s/status", pid_to_str(proc_pid)); + FILE *f = fopen_stream(status_path, "r"); + if (!f) + return 0; + + char *line = NULL; + size_t linesize = 0; + char *p = NULL; + + while (getline(&line, &linesize, f) > 0) { + if (strncmp(line, ns_str, ns_str_size) == 0) { + p = line + ns_str_size; + break; + } + } + + while (p) { + errno = 0; + long id = strtol(p, NULL, 10); + + if (errno || id < 1 || id > INT_MAX) { + perror_func_msg("converting pid (%ld) to int", id); + break; + } + + if (id_buf) + id_buf[n] = (int) id; + + n++; + strsep(&p, "\t"); + } + + free(line); + fclose(f); + + return n; +} + +/** + * Returns whether the /proc filesystem's PID namespace is the same as strace's. + */ +static bool +is_proc_ours(void) +{ + static int cached_val = -1; + + if (cached_val < 0) + cached_val = get_id_list(0, NULL, PT_TID) == 1; + + return cached_val; +} + +/** + * Returns the PID namespace of the tracee + */ +static unsigned int +get_ns(struct tcb *tcp) +{ + if (!tcp->pid_ns) { + int proc_pid = 0; + translate_pid(NULL, tcp->pid, PT_TID, &proc_pid); + + if (proc_pid) + get_ns_hierarchy(proc_pid, &tcp->pid_ns, 1); + } + + return tcp->pid_ns; +} + +/** + * Returns the PID namespace of strace + */ +static unsigned int +get_our_ns(void) +{ + static unsigned int our_ns = 0; + static bool our_ns_initialised = false; + + if (!our_ns_initialised) { + get_ns_hierarchy(0, &our_ns, 1); + our_ns_initialised = true; + } + + return our_ns; +} + +/** + * Returns the cached proc_data struct associated with proc_pid. + * If none found, allocates a new proc_data. + */ +static struct proc_data * +get_or_create_proc_data(int proc_pid) +{ + struct proc_data *pd = (struct proc_data *) (uintptr_t) + trie_get(proc_data_cache, proc_pid); + + if (!pd) { + pd = calloc(1, sizeof(*pd)); + if (!pd) + return NULL; + + pd->proc_pid = proc_pid; + trie_set(proc_data_cache, proc_pid, (uint64_t) (uintptr_t) pd); + } + + return pd; +} + +/** + * Updates the proc_data from /proc + * If the process does not exists, returns false, and frees the proc_data + */ +static bool +update_proc_data(struct proc_data *pd, enum pid_type type) +{ + pd->ns_count = get_ns_hierarchy(pd->proc_pid, + pd->ns_hierarchy, MAX_NS_DEPTH); + if (!pd->ns_count) + goto fail; + + pd->id_count[type] = get_id_list(pd->proc_pid, + pd->id_hierarchy[type], type); + if (!pd->id_count[type]) + goto fail; + + return true; + +fail: + trie_set(proc_data_cache, pd->proc_pid, (uint64_t) (uintptr_t) NULL); + free(pd); + return false; +} + +/** + * Paramters for id translation + */ +struct translate_id_params { + /* The result (output) */ + int result_id; + /* The proc data of the process (output) */ + struct proc_data *pd; + + /* The namespace to be translated from */ + unsigned int from_ns; + /* The id to be translated */ + int from_id; + /* The type of the id */ + enum pid_type type; +}; + +/** + * Translates an id to our namespace, given the proc_pid of the process, + * by reading files in /proc. + * + * @param tip The parameters + * @param proc_pid The proc pid of the process. + * If 0, use the cached values in tip->pd. + */ +static void +translate_id_proc_pid(struct translate_id_params *tip, int proc_pid) +{ + struct proc_data *pd = proc_pid ? + get_or_create_proc_data(proc_pid) : + tip->pd; + + tip->result_id = 0; + tip->pd = NULL; + + if (!pd) + return; + + if (proc_pid && !update_proc_data(pd, tip->type)) + return; + + if (!pd->ns_count || pd->id_count[tip->type] < pd->ns_count) + return; + + int our_ns_id_idx = pd->id_count[tip->type] - pd->ns_count; + + for (int i = 0; i < pd->ns_count; i++) { + if (pd->ns_hierarchy[i] != tip->from_ns) + continue; + + int id_idx = pd->id_count[tip->type] - i - 1; + if (pd->id_hierarchy[tip->type][id_idx] != tip->from_id) + return; + + tip->result_id = pd->id_hierarchy[tip->type][our_ns_id_idx]; + tip->pd = pd; + return; + } +} + +/** + * Translates an id to our namespace, by reading all proc entries in dir. + * + * @param tip The parameters + * @param path The path of the dir to be read. + * @param read_task_dir Whether recurse to "task" subdirectory. + */ +static void +translate_id_dir(struct translate_id_params *tip, const char *path, + bool read_task_dir) +{ + DIR *dir = opendir(path); + if (!dir) { + debug_func_perror_msg("opening dir: %s", path); + return; + } + + while (!tip->result_id) { + errno = 0; + struct_dirent *entry = read_dir(dir); + if (!entry) { + if (errno) + perror_func_msg("readdir"); + + break; + } + + if (entry->d_type != DT_DIR) + continue; + + errno = 0; + long proc_pid = strtol(entry->d_name, NULL, 10); + if (errno) + continue; + if (proc_pid < 1 || proc_pid > INT_MAX) + continue; + + if (read_task_dir) { + char task_dir_path[PATH_MAX + 1]; + xsprintf(task_dir_path, "/proc/%ld/task", proc_pid); + translate_id_dir(tip, task_dir_path, false); + } + + if (tip->result_id) + break; + + translate_id_proc_pid(tip, proc_pid); + } + + closedir(dir); +} + +/** + * Iterator function of the proc_data_cache for id translation. + * If the cache contains the id we are looking for, reads the corresponding + * directory in /proc, and if cache is valid, saves the result. + */ +static void +proc_data_cache_iterator_fn(void* fn_data, uint64_t key, uint64_t val) +{ + struct translate_id_params *tip = (struct translate_id_params *)fn_data; + struct proc_data *pd = (struct proc_data *) (uintptr_t) val; + + if (!pd) + return; + + /* Result already found in an earlier iteration */ + if (tip->result_id) + return; + + /* Translate from cache */ + tip->pd = pd; + translate_id_proc_pid(tip, 0); + if (!tip->result_id) + return; + + /* Now translate from actual data in /proc, to check cache validity */ + translate_id_proc_pid(tip, pd->proc_pid); +} + +int +translate_pid(struct tcb *tcp, int from_id, enum pid_type type, + int *proc_pid_ptr) +{ + if (from_id <= 0 || type < 0 || type >= PT_COUNT) + return 0; + + /* If translation is trivial */ + if ((!tcp || get_ns(tcp) == get_our_ns()) && + (!proc_pid_ptr || is_proc_ours())) { + if (proc_pid_ptr) + *proc_pid_ptr = from_id; + + return from_id; + } + + struct translate_id_params tip = { + .result_id = 0, + .pd = NULL, + .from_ns = tcp ? get_ns(tcp) : get_our_ns(), + .from_id = from_id, + .type = type, + }; + + if (!tip.from_ns) + return 0; + + if (ns_get_parent_enotty) + return 0; + + /* Look for a cached proc_pid for this (from_ns, from_id) pair */ + int cached_proc_pid = get_cached_proc_pid(tip.from_ns, tip.from_id, + tip.type); + if (cached_proc_pid) { + translate_id_proc_pid(&tip, cached_proc_pid); + if (tip.result_id) + goto exit; + } + + /* Iterate through the cache, find potential proc_data */ + trie_iterate_keys(proc_data_cache, 0, pid_max, + proc_data_cache_iterator_fn, &tip); + /* (proc_data_cache_iterator_fn takes care about updating proc_data) */ + if (tip.result_id) + goto exit; + + /* No cache helped, read all entries in /proc */ + translate_id_dir(&tip, "/proc", true); + +exit: + if (tip.pd) { + if (tip.pd->proc_pid) + put_proc_pid(tip.from_ns, tip.from_id, tip.type, + tip.pd->proc_pid); + + if (proc_pid_ptr) + *proc_pid_ptr = tip.pd->proc_pid; + } + + return tip.result_id; +} + +int +get_proc_pid(struct tcb *tcp) +{ + int proc_pid = 0; + translate_pid(NULL, tcp->pid, PT_TID, &proc_pid); + return proc_pid; +} + +static void +printpid_translation(struct tcb *tcp, int pid, enum pid_type type) +{ + if (!pidns_translation) + return; + + int strace_pid = translate_pid(tcp, pid, type, NULL); + if (strace_pid && strace_pid != pid) + tprintf_comment("%d in strace's PID NS", strace_pid); +} + +void +printpid(struct tcb *tcp, int pid, enum pid_type type) +{ + tprintf("%d", pid); + printpid_translation(tcp, pid, type); +} + +void +printpid_tgid_pgid(struct tcb *tcp, int pid) +{ + tprintf("%d", pid); + if (pid > 0) + printpid_translation(tcp, pid, PT_TGID); + else if (pid < -1) + printpid_translation(tcp, -pid, PT_PGID); +} diff --git a/strace.1.in b/strace.1.in index 3b21caec..83776e88 100644 --- a/strace.1.in +++ b/strace.1.in @@ -1075,6 +1075,10 @@ Print all available information associated with file descritors: protocol-specific information associated with socket file descriptors, block/character device number associated with device file descriptors, and PIDs asociated with pidfd file descriptors. +.TP +.B \-\-pidns\-translation +If strace and tracee are in different PID namespaces, print PIDs in +strace's namespace, too. .SS Statistics .TP 12 .B \-c diff --git a/strace.c b/strace.c index 4c96a98b..249533ea 100644 --- a/strace.c +++ b/strace.c @@ -133,6 +133,8 @@ static unsigned int daemonized_tracer; static int post_attach_sigstop = TCB_IGNORE_ONE_SIGSTOP; #define use_seize (post_attach_sigstop == 0) +unsigned int pidns_translation; + static bool detach_on_execve; static int exit_code; @@ -1998,6 +2000,8 @@ init(int argc, char *argv[]) os_release = get_os_release(); + pidns_init(); + shared_log = stderr; set_sortby(DEFAULT_SORTBY); set_personality(DEFAULT_PERSONALITY); @@ -2022,6 +2026,7 @@ init(int argc, char *argv[]) GETOPT_FOLLOWFORKS, GETOPT_OUTPUT_SEPARATELY, GETOPT_TS, + GETOPT_PIDNS_TRANSLATION, GETOPT_QUAL_TRACE, GETOPT_QUAL_ABBREV, @@ -2072,6 +2077,7 @@ init(int argc, char *argv[]) { "summary-wall-clock", no_argument, 0, 'w' }, { "strings-in-hex", optional_argument, 0, GETOPT_HEX_STR }, { "const-print-style", required_argument, 0, 'X' }, + { "pidns-translation", no_argument , 0, GETOPT_PIDNS_TRANSLATION }, { "successful-only", no_argument, 0, 'z' }, { "failed-only", no_argument, 0, 'Z' }, { "failing-only", no_argument, 0, 'Z' }, @@ -2285,6 +2291,9 @@ init(int argc, char *argv[]) case 'y': yflag_short++; break; + case GETOPT_PIDNS_TRANSLATION: + pidns_translation++; + break; case 'z': clear_number_set_array(status_set, 1); add_number_to_set(STATUS_SUCCESSFUL, status_set); diff --git a/syscall.c b/syscall.c index bcc87025..0f4bab6d 100644 --- a/syscall.c +++ b/syscall.c @@ -937,6 +937,21 @@ syscall_exiting_trace(struct tcb *tcp, struct timespec *ts, int res) tprintf("= %" PRI_kld, tcp->u_rval); } break; + case RVAL_TID: + case RVAL_SID: + case RVAL_TGID: + case RVAL_PGID: { + #define _(_t) [RVAL_##_t - RVAL_TID] = PT_##_t + static const enum pid_type types[] = { + _(TID), _(SID), _(TGID), _(PGID), + }; + #undef _ + + tprints("= "); + printpid(tcp, tcp->u_rval, + types[(sys_res & RVAL_MASK) - RVAL_TID]); + break; + } default: error_msg("invalid rval format"); break; diff --git a/trie.c b/trie.c new file mode 100644 index 00000000..b7d56ed5 --- /dev/null +++ b/trie.c @@ -0,0 +1,248 @@ +/* + * Simple trie implementation for key-value mapping storage + * + * Copyright (c) 2020 ?kos Uzonyi + * All rights reserved. + * + * SPDX-License-Identifier: LGPL-2.1-or-later + */ + +#include "defs.h" + +#include +#include +#include + +#include "trie.h" + +static const uint8_t ptr_sz_lg = (sizeof(void *) == 8 ? 6 : 5); + +/** + * Returns lg2 of node size in bits for the specific level of the trie. + */ +static uint8_t +trie_get_node_size(struct trie *t, uint8_t depth) +{ + /* Last level contains data and we allow it having a different size */ + if (depth == t->max_depth) + return t->data_block_key_bits + t->item_size_lg; + /* Last level of the tree can be smaller */ + if (depth == t->max_depth - 1) + return (t->key_size - t->data_block_key_bits - 1) % + t->node_key_bits + 1 + ptr_sz_lg; + + return t->node_key_bits + ptr_sz_lg; +} + +/** + * Provides starting offset of bits in key corresponding to the node index + * at the specific level. + */ +static uint8_t +trie_get_node_bit_offs(struct trie *t, uint8_t depth) +{ + uint8_t offs; + + if (depth == t->max_depth) + return 0; + + offs = t->data_block_key_bits; + + if (depth == t->max_depth - 1) + return offs; + + /* data_block_size + remainder */ + offs += trie_get_node_size(t, t->max_depth - 1) - ptr_sz_lg; + offs += (t->max_depth - depth - 2) * t->node_key_bits; + + return offs; +} + +struct trie * +trie_create(uint8_t key_size, uint8_t item_size_lg, uint8_t node_key_bits, + uint8_t data_block_key_bits, uint64_t empty_value) +{ + if (item_size_lg > 6) + return NULL; + if (key_size > 64) + return NULL; + if (node_key_bits < 1) + return NULL; + if (data_block_key_bits < 1 || data_block_key_bits > key_size) + return NULL; + + struct trie *t = malloc(sizeof(*t)); + if (!t) + return NULL; + + t->empty_value = empty_value; + t->data = NULL; + t->item_size_lg = item_size_lg; + t->node_key_bits = node_key_bits; + t->data_block_key_bits = data_block_key_bits; + t->key_size = key_size; + t->max_depth = (key_size - data_block_key_bits + node_key_bits - 1) + / t->node_key_bits; + + return t; +} + +static uint64_t * +trie_get_node(struct trie *t, uint64_t key, bool auto_create) +{ + void **cur_node = &(t->data); + + if (t->key_size < 64 && key > (uint64_t) 1 << t->key_size) + return NULL; + + for (uint8_t cur_depth = 0; cur_depth <= t->max_depth; cur_depth++) { + uint8_t offs = trie_get_node_bit_offs(t, cur_depth); + uint8_t sz = trie_get_node_size(t, cur_depth); + + if (!*cur_node) { + if (!auto_create) + return NULL; + + *cur_node = xcalloc(1 << sz, 1); + } + + if (cur_depth >= t->max_depth) + break; + + size_t pos = (key >> offs) & ((1 << (sz - ptr_sz_lg)) - 1); + cur_node = (((void **) (*cur_node)) + pos); + } + + return (uint64_t *) (*cur_node); +} + +static void +trie_data_block_calc_pos(struct trie *t, uint64_t key, + uint64_t *pos, uint64_t *mask, uint64_t *offs) +{ + uint64_t key_mask; + + key_mask = (1 << t->data_block_key_bits) - 1; + *pos = (key & key_mask) >> (6 - t->item_size_lg); + + key_mask = (1 << (6 - t->item_size_lg)) - 1; + *offs = (key & key_mask) * (1 << t->item_size_lg); + + *mask = (((uint64_t) 1 << (1 << t->item_size_lg)) - 1) << *offs; +} + +bool +trie_set(struct trie *t, uint64_t key, uint64_t val) +{ + uint64_t *data = trie_get_node(t, key, true); + if (!data) + return false; + + uint64_t pos, mask, offs; + trie_data_block_calc_pos(t, key, &pos, &mask, &offs); + + data[pos] &= ~mask; + data[pos] |= (val << offs) & mask; + + return true; +} + +static uint64_t +trie_data_block_get(struct trie *t, uint64_t *data, uint64_t key) +{ + if (!data) + return t->empty_value; + + uint64_t pos, mask, offs; + trie_data_block_calc_pos(t, key, &pos, &mask, &offs); + + return (data[pos] & mask) >> offs; +} + +uint64_t +trie_get(struct trie *b, uint64_t key) +{ + return trie_data_block_get(b, trie_get_node(b, key, false), key); +} + +static uint64_t +trie_iterate_keys_node(struct trie *t, + trie_iterate_fn fn, void *fn_data, + void *node, uint64_t start, uint64_t end, + uint8_t depth) +{ + if (start > end || !node) + return 0; + + if (depth == t->max_depth) { + for (uint64_t i = start; i <= end; i++) + fn(fn_data, i, trie_data_block_get(t, + (uint64_t *) node, i)); + + return end - start + 1; + } + + uint8_t parent_node_bit_off = depth == 0 ? + t->key_size : + trie_get_node_bit_offs(t, depth - 1); + + uint64_t first_key_in_node = start & + (uint64_t) -1 << parent_node_bit_off; + + uint8_t node_bit_off = trie_get_node_bit_offs(t, depth); + uint8_t node_key_bits = parent_node_bit_off - node_bit_off; + uint64_t mask = ((uint64_t) 1 << (node_key_bits)) - 1; + uint64_t start_index = (start >> node_bit_off) & mask; + uint64_t end_index = (end >> node_bit_off) & mask; + uint64_t child_key_count = (uint64_t) 1 << node_bit_off; + + uint64_t count = 0; + + for (uint64_t i = start_index; i <= end_index; i++) { + uint64_t child_start = first_key_in_node + i * child_key_count; + uint64_t child_end = first_key_in_node + + (i + 1) * child_key_count - 1; + + if (child_start < start) + child_start = start; + if (child_end > end) + child_end = end; + + count += trie_iterate_keys_node(t, fn, fn_data, + ((void **) node)[i], child_start, child_end, + depth + 1); + } + + return count; +} + +uint64_t trie_iterate_keys(struct trie *t, uint64_t start, uint64_t end, + trie_iterate_fn fn, void *fn_data) +{ + return trie_iterate_keys_node(t, fn, fn_data, t->data, + start, end, 0); +} + +static void +trie_free_node(struct trie *t, void *node, uint8_t depth) +{ + if (!node) + return; + + if (depth >= t->max_depth) + goto free_node; + + size_t sz = 1 << (trie_get_node_size(t, depth) - ptr_sz_lg); + for (size_t i = 0; i < sz; i++) + trie_free_node(t, ((void **) node)[i], depth + 1); + +free_node: + free(node); +} + +void +trie_free(struct trie *t) +{ + trie_free_node(t, t->data, 0); + free(t); +} diff --git a/trie.h b/trie.h new file mode 100644 index 00000000..1ff31397 --- /dev/null +++ b/trie.h @@ -0,0 +1,89 @@ +/* + * Simple trie interface + * + * Copyright (c) 2020 ?kos Uzonyi + * All rights reserved. + * + * SPDX-License-Identifier: LGPL-2.1-or-later + */ + +#ifndef STRACE_TRIE_H +#define STRACE_TRIE_H + +/** + * Trie control structure. + * Trie implemented here has the following properties: + * * It allows storing values of the same size, the size can vary from 1 bit to + * 64 bit values (only power of 2 sizes are allowed). + * * The key can be up to 64 bits in size. + * * It has separate configuration for node size and data block size. + * + * How bits of key are used for different node levels: + * + * highest bits lowest bits + * | node_key_bits | node_key_bits | ... | | data_block_key_bits | + * \_________________________________________________________________________/ + * key_size + * + * So, the remainder is used on the lowest non-data node level. + * + * As of now, it doesn't implement any mechanisms for resizing/changing key + * size. De-fragmentation is also unsupported currently. + */ +struct trie { + /** Return value of trie_get if key is not found */ + uint64_t empty_value; + + /** Pointer to root node */ + void *data; + + /** Key size in bits (0..64). */ + uint8_t key_size; + + /** + * Size of the stored values in log2 bits (0..6). + * (6: 64 bit values, 5: 32 bit values, ...) + */ + uint8_t item_size_lg; + + /** + * Number of bits in the key that make a symbol for a node. + * (equals to log2 of the child count of the node) + */ + uint8_t node_key_bits; + + /** + * Number of bits in the key that make a symbol for the data block (leaf). + * (equals to log2 of the value count stored in a data block) + */ + uint8_t data_block_key_bits; + + /** The depth of the data block. Calculated from the values above */ + uint8_t max_depth; +}; + +struct trie* trie_create(uint8_t key_size, uint8_t item_size_lg, + uint8_t node_key_bits, uint8_t data_block_key_bits, + uint64_t empty_value); + +bool trie_set(struct trie *t, uint64_t key, uint64_t val); +uint64_t trie_get(struct trie *t, uint64_t key); + +typedef void (*trie_iterate_fn)(void *data, uint64_t key, uint64_t val); + +/** + * Calls trie_iterate_fn for each key-value pair where + * key is inside the [start, end] interval (inclusive). + * + * @param t The trie. + * @param start The start of the key interval (inclusive). + * @param end The end of the key interval (inclusive). + * @param fn The function to be called. + * @param fn_data The value to be passed to fn. + */ +uint64_t trie_iterate_keys(struct trie *t, uint64_t start, uint64_t end, + trie_iterate_fn fn, void *fn_data); + +void trie_free(struct trie *t); + +#endif /* !STRACE_TRIE_H */ -- 2.27.0 From uzonyi.akos at gmail.com Sun Aug 9 14:13:04 2020 From: uzonyi.akos at gmail.com (=?UTF-8?q?=C3=81kos=20Uzonyi?=) Date: Sun, 9 Aug 2020 16:13:04 +0200 Subject: [PATCH v8 3/5] Use get_proc_pid for /proc paths In-Reply-To: <20200809141306.477539-1-uzonyi.akos@gmail.com> References: <20200809141306.477539-1-uzonyi.akos@gmail.com> Message-ID: <20200809141306.477539-4-uzonyi.akos@gmail.com> * mmap_cache.c (mmap_cache_rebuild_if_invalid): Use proc pid instead of tcp->pid for /proc path. * util.c (getfdproto): Likewise. (pidfd_get_pid): Likewise. * pathtrace.c (getfdpath_pid): Likewise. * strace.c (attach_tcb): Likewise. --- mmap_cache.c | 2 +- pathtrace.c | 7 ++++++- strace.c | 2 +- util.c | 9 +++++++-- 4 files changed, 15 insertions(+), 5 deletions(-) diff --git a/mmap_cache.c b/mmap_cache.c index 89c62254..9825df26 100644 --- a/mmap_cache.c +++ b/mmap_cache.c @@ -84,7 +84,7 @@ mmap_cache_rebuild_if_invalid(struct tcb *tcp, const char *caller) return MMAP_CACHE_REBUILD_READY; char filename[sizeof("/proc/4294967296/maps")]; - xsprintf(filename, "/proc/%u/maps", tcp->pid); + xsprintf(filename, "/proc/%u/maps", get_proc_pid(tcp)); FILE *fp = fopen_stream(filename, "r"); if (!fp) { diff --git a/pathtrace.c b/pathtrace.c index 5b60762b..afed770a 100644 --- a/pathtrace.c +++ b/pathtrace.c @@ -87,7 +87,12 @@ getfdpath_pid(pid_t pid, int fd, char *buf, unsigned bufsize) if (fd < 0) return -1; - xsprintf(linkpath, "/proc/%u/fd/%u", pid, fd); + int proc_pid = 0; + translate_pid(NULL, pid, PT_TID, &proc_pid); + if (!proc_pid) + return -1; + + xsprintf(linkpath, "/proc/%u/fd/%u", proc_pid, fd); n = readlink(linkpath, buf, bufsize - 1); /* * NB: if buf is too small, readlink doesn't fail, diff --git a/strace.c b/strace.c index 249533ea..ef23f08f 100644 --- a/strace.c +++ b/strace.c @@ -1196,7 +1196,7 @@ attach_tcb(struct tcb *const tcp) unsigned int ntid = 0, nerr = 0; if (followfork && tcp->pid != strace_child && - xsprintf(procdir, task_path, tcp->pid) > 0 && + xsprintf(procdir, task_path, get_proc_pid(tcp)) > 0 && (dir = opendir(procdir)) != NULL) { struct_dirent *de; diff --git a/util.c b/util.c index 2568021e..481144bf 100644 --- a/util.c +++ b/util.c @@ -501,7 +501,7 @@ getfdproto(struct tcb *tcp, int fd) if (fd < 0) return SOCK_PROTO_UNKNOWN; - xsprintf(path, "/proc/%u/fd/%u", tcp->pid, fd); + xsprintf(path, "/proc/%u/fd/%u", get_proc_pid(tcp), fd); r = getxattr(path, "system.sockprotoname", buf, bufsize - 1); if (r <= 0) return SOCK_PROTO_UNKNOWN; @@ -582,8 +582,13 @@ printdev(struct tcb *tcp, int fd, const char *path) pid_t pidfd_get_pid(pid_t pid_of_fd, int fd) { + int proc_pid = 0; + translate_pid(NULL, pid_of_fd, PT_TID, &proc_pid); + if (!proc_pid) + return -1; + char fdi_path[sizeof("/proc/%u/fdinfo/%u") + 2 * sizeof(int) * 3]; - xsprintf(fdi_path, "/proc/%u/fdinfo/%u", pid_of_fd, fd); + xsprintf(fdi_path, "/proc/%u/fdinfo/%u", proc_pid, fd); FILE *f = fopen_stream(fdi_path, "r"); if (!f) -- 2.27.0 From uzonyi.akos at gmail.com Sun Aug 9 14:13:03 2020 From: uzonyi.akos at gmail.com (=?UTF-8?q?=C3=81kos=20Uzonyi?=) Date: Sun, 9 Aug 2020 16:13:03 +0200 Subject: [PATCH v8 2/5] Use printpid in decoders In-Reply-To: <20200809141306.477539-1-uzonyi.akos@gmail.com> References: <20200809141306.477539-1-uzonyi.akos@gmail.com> Message-ID: <20200809141306.477539-3-uzonyi.akos@gmail.com> * getpid.c: New file. * Makefile.am (libstrace_a_SOURCES): Add it. * linux/dummy.h (sys_getpid, sys_getppid, sys_gettid, sys_setpgid, sys_setpgrp): Remove. * util.c (printfd_pid_tracee_ns): Implement using translate_pid. * defs.h (printnum_pid): New function definition. (printfd_pid_tracee_ns): Update documentation * util.c: (printnum_pid): New function. * print_fields.h (PRINT_FIELD_TID): New macro. (PRINT_FIELD_TGID): Likewise. (PRINT_FIELD_PGID): Likewise. (PRINT_FIELD_SID): Likewise. * affinity.c: Print PIDs with printpid. * block.c: Likewise. * bpf.c: Likewise. * capability.c: Likewise. * clone.c: Likewise. * fcntl.c: Likewise. * get_robust_list.c: Likewise. * ioprio.c: Likewise. * kcmp.c: Likewise. * msghdr.c: Likewise. * net.c: Likewise. * netlink.c: Likewise. * numa.c: Likewise. * pidfd_open.c: Likewise. * printsiginfo.c: Likewise. * process.c: Likewise. * process_vm.c: Likewise. * resource.c: Likewise. * sched.c: Likewise. * signal.c: Likewise. * sockaddr.c: Likewise. * wait.c: Likewise. * kcmp.c (SYS_FUNC(kcmp)): Fix KCMP_FILE pid arguments. * tests/kcmp.c (printpidfd): Print path if VERBOSE_FD. (main): Use our real pid if real fds are used. --- Makefile.am | 1 + affinity.c | 6 ++++-- block.c | 2 +- bpf.c | 2 +- capability.c | 4 +++- clone.c | 14 +++++++------- defs.h | 5 ++++- fcntl.c | 24 ++++++++++++++++++++++-- get_robust_list.c | 3 ++- getpid.c | 46 ++++++++++++++++++++++++++++++++++++++++++++++ ioprio.c | 26 ++++++++++++++++++++++---- ipc_shmctl.c | 4 ++-- kcmp.c | 5 ++++- linux/dummy.h | 8 +------- msghdr.c | 2 +- net.c | 2 +- netlink.c | 5 +++-- numa.c | 6 ++++-- pidfd_open.c | 2 +- print_fields.h | 24 ++++++++++++++++++++++++ printsiginfo.c | 2 +- process.c | 3 ++- process_vm.c | 6 ++++-- resource.c | 27 ++++++++++++++++++++++++--- sched.c | 25 ++++++++++++++++--------- signal.c | 21 +++++++++++++++------ sockaddr.c | 2 +- tests/kcmp.c | 25 ++++++++++++++++++++++--- util.c | 22 +++++++++++++++------- wait.c | 36 ++++++++++++++++++++++++------------ 30 files changed, 278 insertions(+), 82 deletions(-) create mode 100644 getpid.c diff --git a/Makefile.am b/Makefile.am index 73c22035..15fcd9a6 100644 --- a/Makefile.am +++ b/Makefile.am @@ -135,6 +135,7 @@ libstrace_a_SOURCES = \ getcpu.c \ getcwd.c \ getpagesize.c \ + getpid.c \ getrandom.c \ hdio.c \ hostname.c \ diff --git a/affinity.c b/affinity.c index eb3158b7..f9893adb 100644 --- a/affinity.c +++ b/affinity.c @@ -82,7 +82,8 @@ SYS_FUNC(sched_setaffinity) const int pid = tcp->u_arg[0]; const unsigned int len = tcp->u_arg[1]; - tprintf("%d, %u, ", pid, len); + printpid(tcp, pid, PT_TGID); + tprintf(", %u, ", len); print_affinitylist(tcp, tcp->u_arg[2], len); return RVAL_DECODED; @@ -94,7 +95,8 @@ SYS_FUNC(sched_getaffinity) const unsigned int len = tcp->u_arg[1]; if (entering(tcp)) { - tprintf("%d, %u, ", pid, len); + printpid(tcp, pid, PT_TGID); + tprintf(", %u, ", len); } else { print_affinitylist(tcp, tcp->u_arg[2], tcp->u_rval); } diff --git a/block.c b/block.c index b527ef43..783a4b5a 100644 --- a/block.c +++ b/block.c @@ -179,7 +179,7 @@ MPERS_PRINTER_DECL(int, block_ioctl, struct tcb *const tcp, PRINT_FIELD_U(", ", buts, buf_nr); PRINT_FIELD_U(", ", buts, start_lba); PRINT_FIELD_U(", ", buts, end_lba); - PRINT_FIELD_D(", ", buts, pid); + PRINT_FIELD_TGID(", ", buts, pid, tcp); return 0; } else { struct_blk_user_trace_setup buts; diff --git a/bpf.c b/bpf.c index af830053..0ec33ba4 100644 --- a/bpf.c +++ b/bpf.c @@ -927,7 +927,7 @@ BEGIN_BPF_CMD_DECODER(BPF_TASK_FD_QUERY) if (entering(tcp)) { set_tcb_priv_ulong(tcp, attr.buf_len); - PRINT_FIELD_D("{task_fd_query={", attr, pid); + PRINT_FIELD_TGID("{task_fd_query={", attr, pid, tcp); PRINT_FIELD_FD(", ", attr, fd, tcp); PRINT_FIELD_U(", ", attr, flags); PRINT_FIELD_U(", ", attr, buf_len); diff --git a/capability.c b/capability.c index 0e763ee1..812fb435 100644 --- a/capability.c +++ b/capability.c @@ -70,7 +70,9 @@ print_cap_header(struct tcb *const tcp, const kernel_ulong_t addr, tprints("{version="); printxval(cap_version, h->version, "_LINUX_CAPABILITY_VERSION_???"); - tprintf(", pid=%d}", h->pid); + tprints(", pid="); + printpid(tcp, h->pid, PT_TGID); + tprints("}"); } static void diff --git a/clone.c b/clone.c index 487c5c23..45f24065 100644 --- a/clone.c +++ b/clone.c @@ -114,14 +114,14 @@ SYS_FUNC(clone) */ if ((flags & (CLONE_PARENT_SETTID|CLONE_PIDFD|CLONE_CHILD_SETTID |CLONE_CHILD_CLEARTID|CLONE_SETTLS)) == 0) - return RVAL_DECODED; + return RVAL_DECODED | RVAL_TID; } else { if (flags & (CLONE_PARENT_SETTID|CLONE_PIDFD)) { kernel_ulong_t addr = tcp->u_arg[ARG_PTID]; tprints(", parent_tid="); if (flags & CLONE_PARENT_SETTID) - printnum_int(tcp, addr, "%u"); + printnum_pid(tcp, addr, PT_TID); else printnum_fd(tcp, addr); } @@ -134,7 +134,7 @@ SYS_FUNC(clone) printaddr(tcp->u_arg[ARG_CTID]); } } - return 0; + return RVAL_TID; } @@ -229,7 +229,7 @@ SYS_FUNC(clone3) if ((arg.flags & (CLONE_PIDFD | CLONE_PARENT_SETTID)) || (size > fetch_size)) - return 0; + return RVAL_TID; goto out; } @@ -256,7 +256,7 @@ SYS_FUNC(clone3) if (arg.flags & CLONE_PARENT_SETTID) { tprintf("%sparent_tid=", pfx); - printnum_int(tcp, arg.parent_tid, "%d"); /* TID */ + printnum_pid(tcp, arg.parent_tid, PT_TID); pfx = ", "; } @@ -279,7 +279,7 @@ SYS_FUNC(clone3) out: tprintf(", %" PRI_klu, size); - return RVAL_DECODED; + return RVAL_DECODED | RVAL_TID; } @@ -300,5 +300,5 @@ SYS_FUNC(unshare) SYS_FUNC(fork) { - return RVAL_DECODED; + return RVAL_DECODED | RVAL_TGID; } diff --git a/defs.h b/defs.h index 511a92a2..328c1940 100644 --- a/defs.h +++ b/defs.h @@ -1100,7 +1100,7 @@ printfd(struct tcb *tcp, int fd) /** * Print file descriptor fd owned by process with ID pid (from the PID NS - * of the tracee the descriptor tcp). This is a stub. + * of the tracee). */ extern void printfd_pid_tracee_ns(struct tcb *tcp, pid_t pid, int fd); @@ -1561,6 +1561,9 @@ DECL_PRINTNUM_ADDR(int64); extern bool printnum_fd(struct tcb *, kernel_ulong_t addr); +extern bool +printnum_pid(struct tcb *const tcp, const kernel_ulong_t addr, enum pid_type type); + static inline bool printnum_slong(struct tcb *tcp, kernel_ulong_t addr) { diff --git a/fcntl.c b/fcntl.c index 6fcd5dac..5c630a06 100644 --- a/fcntl.c +++ b/fcntl.c @@ -28,7 +28,7 @@ print_struct_flock64(struct tcb *const tcp, const struct_kernel_flock64 *fl, con PRINT_FIELD_D(", ", *fl, l_start); PRINT_FIELD_D(", ", *fl, l_len); if (getlk) - PRINT_FIELD_D(", ", *fl, l_pid); + PRINT_FIELD_TGID(", ", *fl, l_pid, tcp); tprints("}"); } @@ -59,7 +59,22 @@ print_f_owner_ex(struct tcb *const tcp, const kernel_ulong_t addr) return; PRINT_FIELD_XVAL("{", owner, type, f_owner_types, "F_OWNER_???"); - PRINT_FIELD_D(", ", owner, pid); + + enum pid_type pid_type = PT_NONE; + switch (owner.type) + { + case F_OWNER_TID: + pid_type = PT_TID; + break; + case F_OWNER_PID: + pid_type = PT_TGID; + break; + case F_OWNER_PGRP: + pid_type = PT_PGID; + break; + } + tprints(", pid="); + printpid(tcp, owner.pid, pid_type); tprints("}"); } @@ -74,6 +89,9 @@ print_fcntl(struct tcb *tcp) printflags(fdflags, tcp->u_arg[2], "FD_???"); break; case F_SETOWN: + tprints(", "); + printpid_tgid_pgid(tcp, tcp->u_arg[2]); + break; case F_SETPIPE_SZ: tprintf(", %" PRI_kld, tcp->u_arg[2]); break; @@ -116,6 +134,8 @@ print_fcntl(struct tcb *tcp) printsignal(tcp->u_arg[2]); break; case F_GETOWN: + return RVAL_DECODED | + ((int) tcp->u_rval < 0 ? RVAL_PGID : RVAL_TGID); case F_GETPIPE_SZ: break; case F_GETFD: diff --git a/get_robust_list.c b/get_robust_list.c index b5aebaff..81aba2dd 100644 --- a/get_robust_list.c +++ b/get_robust_list.c @@ -10,7 +10,8 @@ SYS_FUNC(get_robust_list) { if (entering(tcp)) { - tprintf("%d, ", (int) tcp->u_arg[0]); + printpid(tcp, tcp->u_arg[0], PT_TID); + tprints(", "); } else { printnum_ptr(tcp, tcp->u_arg[1]); tprints(", "); diff --git a/getpid.c b/getpid.c new file mode 100644 index 00000000..5e9a1a29 --- /dev/null +++ b/getpid.c @@ -0,0 +1,46 @@ +/* + * Copyright (c) 2020 ?kos Uzonyi + * All rights reserved. + * + * SPDX-License-Identifier: LGPL-2.1-or-later + */ + +#include "defs.h" + +SYS_FUNC(getpid) +{ + return RVAL_DECODED | RVAL_TGID; +} + +SYS_FUNC(gettid) +{ + return RVAL_DECODED | RVAL_TID; +} + +SYS_FUNC(getpgrp) +{ + return RVAL_DECODED | RVAL_PGID; +} + +SYS_FUNC(getpgid) +{ + printpid(tcp, tcp->u_arg[0], PT_TGID); + + return RVAL_DECODED | RVAL_PGID; +} + +SYS_FUNC(getsid) +{ + printpid(tcp, tcp->u_arg[0], PT_TGID); + + return RVAL_DECODED | RVAL_SID; +} + +SYS_FUNC(setpgid) +{ + printpid(tcp, tcp->u_arg[0], PT_TGID); + tprints(", "); + printpid(tcp, tcp->u_arg[1], PT_PGID); + + return RVAL_DECODED; +} diff --git a/ioprio.c b/ioprio.c index 873c8ce5..149ef3fd 100644 --- a/ioprio.c +++ b/ioprio.c @@ -49,13 +49,30 @@ print_ioprio(unsigned int ioprio) ? tprints_comment : tprints)(str); } +static void +ioprio_print_who(struct tcb *tcp, int which, int who) +{ + switch (which) + { + case IOPRIO_WHO_PROCESS: + printpid(tcp, who, PT_TGID); + break; + case IOPRIO_WHO_PGRP: + printpid(tcp, who, PT_PGID); + break; + default: + tprintf("%d", who); + break; + } +} + SYS_FUNC(ioprio_get) { if (entering(tcp)) { /* int which */ printxval(ioprio_who, tcp->u_arg[0], "IOPRIO_WHO_???"); - /* int who */ - tprintf(", %d", (int) tcp->u_arg[1]); + tprints(", "); + ioprio_print_who(tcp, tcp->u_arg[0], tcp->u_arg[1]); return 0; } else { if (syserror(tcp)) @@ -72,8 +89,9 @@ SYS_FUNC(ioprio_set) { /* int which */ printxval(ioprio_who, tcp->u_arg[0], "IOPRIO_WHO_???"); - /* int who */ - tprintf(", %d, ", (int) tcp->u_arg[1]); + tprints(", "); + ioprio_print_who(tcp, tcp->u_arg[0], tcp->u_arg[1]); + tprints(", "); /* int ioprio */ if (xlat_verbose(xlat_verbosity) != XLAT_STYLE_ABBREV) tprintf("%d", (int) tcp->u_arg[2]); diff --git a/ipc_shmctl.c b/ipc_shmctl.c index 8c9e1e7a..1f99f02a 100644 --- a/ipc_shmctl.c +++ b/ipc_shmctl.c @@ -53,8 +53,8 @@ print_shmid_ds(struct tcb *const tcp, const kernel_ulong_t addr, int cmd) PRINT_FIELD_UID(", ", shmid_ds.shm_perm, cgid); tprints("}"); tprintf(", shm_segsz=%u", (unsigned) shmid_ds.shm_segsz); - PRINT_FIELD_D(", ", shmid_ds, shm_cpid); - PRINT_FIELD_D(", ", shmid_ds, shm_lpid); + PRINT_FIELD_TGID(", ", shmid_ds, shm_cpid, tcp); + PRINT_FIELD_TGID(", ", shmid_ds, shm_lpid, tcp); tprintf(", shm_nattch=%u", (unsigned) shmid_ds.shm_nattch); tprintf(", shm_atime=%u", (unsigned) shmid_ds.shm_atime); tprintf(", shm_dtime=%u", (unsigned) shmid_ds.shm_dtime); diff --git a/kcmp.c b/kcmp.c index 62115555..a5e1cdce 100644 --- a/kcmp.c +++ b/kcmp.c @@ -30,7 +30,10 @@ SYS_FUNC(kcmp) kernel_ulong_t idx1 = tcp->u_arg[3]; kernel_ulong_t idx2 = tcp->u_arg[4]; - tprintf("%d, %d, ", pid1, pid2); + printpid(tcp, pid1, PT_TGID); + tprints(", "); + printpid(tcp, pid2, PT_TGID); + tprints(", "); printxval(kcmp_types, type, "KCMP_???"); switch (type) { diff --git a/linux/dummy.h b/linux/dummy.h index 2f859a60..ca0d2f0c 100644 --- a/linux/dummy.h +++ b/linux/dummy.h @@ -53,6 +53,7 @@ # define sys_getgid sys_getuid # define sys_getgid16 sys_getuid16 # define sys_getpeername sys_getsockname +# define sys_getppid sys_getpid # define sys_getresgid sys_getresuid # define sys_getresgid16 sys_getresuid16 # define sys_lstat sys_stat @@ -87,10 +88,6 @@ # define sys_vfork sys_fork /* printargs does the right thing */ -# define sys_getpgrp printargs -# define sys_getpid printargs -# define sys_getppid printargs -# define sys_gettid printargs # define sys_idle printargs # define sys_munlockall printargs # define sys_pause printargs @@ -108,10 +105,7 @@ /* printargs_d does the right thing */ # define sys_exit printargs_d -# define sys_getpgid printargs_d -# define sys_getsid printargs_d # define sys_nice printargs_d -# define sys_setpgid printargs_d # define sys_setpgrp printargs_d # define sys_timer_delete printargs_d # define sys_timer_getoverrun printargs_d diff --git a/msghdr.c b/msghdr.c index ef6dc24b..170b8e51 100644 --- a/msghdr.c +++ b/msghdr.c @@ -69,7 +69,7 @@ print_scm_creds(struct tcb *tcp, const void *cmsg_data, { const struct ucred *uc = cmsg_data; - PRINT_FIELD_D("{", *uc, pid); + PRINT_FIELD_TGID("{", *uc, pid, tcp); PRINT_FIELD_UID(", ", *uc, uid); PRINT_FIELD_UID(", ", *uc, gid); tprints("}"); diff --git a/net.c b/net.c index fa4638e7..2099f0ac 100644 --- a/net.c +++ b/net.c @@ -601,7 +601,7 @@ print_get_ucred(struct tcb *const tcp, const kernel_ulong_t addr, if (umoven_or_printaddr(tcp, addr, len, &uc)) return; - PRINT_FIELD_LEN("{", uc, pid, len, PRINT_FIELD_D); + PRINT_FIELD_LEN("{", uc, pid, len, PRINT_FIELD_TGID, tcp); PRINT_FIELD_LEN(", ", uc, uid, len, PRINT_FIELD_UID); PRINT_FIELD_LEN(", ", uc, gid, len, PRINT_FIELD_UID); tprints("}"); diff --git a/netlink.c b/netlink.c index 88d864a9..cb29033a 100644 --- a/netlink.c +++ b/netlink.c @@ -446,8 +446,9 @@ print_nlmsghdr(struct tcb *tcp, decode_nlmsg_flags(nlmsghdr->nlmsg_flags, nlmsghdr->nlmsg_type, family); - tprintf(", seq=%u, pid=%d}", nlmsghdr->nlmsg_seq, - nlmsghdr->nlmsg_pid); + tprintf(", seq=%u, pid=", nlmsghdr->nlmsg_seq); + printpid(tcp, nlmsghdr->nlmsg_pid, PT_TGID); + tprints("}"); } static bool diff --git a/numa.c b/numa.c index cc7a7cc6..f7a58266 100644 --- a/numa.c +++ b/numa.c @@ -44,7 +44,8 @@ print_nodemask(struct tcb *const tcp, const kernel_ulong_t addr, SYS_FUNC(migrate_pages) { - tprintf("%d, %" PRI_klu ", ", (int) tcp->u_arg[0], tcp->u_arg[1]); + printpid(tcp, tcp->u_arg[0], PT_TGID); + tprintf(", %" PRI_klu ", ", tcp->u_arg[1]); print_nodemask(tcp, tcp->u_arg[2], tcp->u_arg[1]); tprints(", "); print_nodemask(tcp, tcp->u_arg[3], tcp->u_arg[1]); @@ -170,7 +171,8 @@ SYS_FUNC(move_pages) kernel_ulong_t buf; if (entering(tcp)) { - tprintf("%d, %" PRI_klu ", ", (int) tcp->u_arg[0], npages); + printpid(tcp, tcp->u_arg[0], PT_TGID); + tprintf(", %" PRI_klu ", ", npages); print_array(tcp, tcp->u_arg[2], npages, &buf, current_wordsize, tfetch_mem, print_addr, 0); tprints(", "); diff --git a/pidfd_open.c b/pidfd_open.c index bbc7f617..cf05a110 100644 --- a/pidfd_open.c +++ b/pidfd_open.c @@ -10,7 +10,7 @@ SYS_FUNC(pidfd_open) { /* pid_t pid */ - tprintf("%d", (int) tcp->u_arg[0]); + printpid(tcp, tcp->u_arg[0], PT_TGID); /* unsigned int flags */ tprintf(", %#x", (unsigned int) tcp->u_arg[1]); diff --git a/print_fields.h b/print_fields.h index f9714115..33d4a458 100644 --- a/print_fields.h +++ b/print_fields.h @@ -263,6 +263,30 @@ printfd((tcp_), (where_).field_); \ } while (0) +# define PRINT_FIELD_TID(prefix_, where_, field_, tcp_) \ + do { \ + STRACE_PRINTF("%s%s=", (prefix_), #field_); \ + printpid((tcp_), (where_).field_, PT_TID); \ + } while (0) + +# define PRINT_FIELD_TGID(prefix_, where_, field_, tcp_) \ + do { \ + STRACE_PRINTF("%s%s=", (prefix_), #field_); \ + printpid((tcp_), (where_).field_, PT_TGID); \ + } while (0) + +# define PRINT_FIELD_PGID(prefix_, where_, field_, tcp_) \ + do { \ + STRACE_PRINTF("%s%s=", (prefix_), #field_); \ + printpid((tcp_), (where_).field_, PT_PGID); \ + } while (0) + +# define PRINT_FIELD_SID(prefix_, where_, field_, tcp_) \ + do { \ + STRACE_PRINTF("%s%s=", (prefix_), #field_); \ + printpid((tcp_), (where_).field_, PT_SID); \ + } while (0) + # define PRINT_FIELD_STRN(prefix_, where_, field_, len_, tcp_) \ do { \ STRACE_PRINTF("%s%s=", (prefix_), #field_); \ diff --git a/printsiginfo.c b/printsiginfo.c index 8ed1e7ba..cb4cde4a 100644 --- a/printsiginfo.c +++ b/printsiginfo.c @@ -58,7 +58,7 @@ static void printsigsource(struct tcb *tcp, const siginfo_t *sip) { - PRINT_FIELD_D(", ", *sip, si_pid); + PRINT_FIELD_TGID(", ", *sip, si_pid, tcp); PRINT_FIELD_UID(", ", *sip, si_uid); } diff --git a/process.c b/process.c index a98c304e..d6ff255d 100644 --- a/process.c +++ b/process.c @@ -92,7 +92,8 @@ SYS_FUNC(ptrace) } /* pid */ - tprintf(", %d", pid); + tprints(", "); + printpid(tcp, pid, PT_TGID); /* addr */ switch (request) { diff --git a/process_vm.c b/process_vm.c index abee1e68..81d9b0f4 100644 --- a/process_vm.c +++ b/process_vm.c @@ -13,7 +13,8 @@ SYS_FUNC(process_vm_readv) { if (entering(tcp)) { /* arg 1: pid */ - tprintf("%d, ", (int) tcp->u_arg[0]); + printpid(tcp, tcp->u_arg[0], PT_TGID); + tprints(", "); } else { kernel_ulong_t local_iovcnt = tcp->u_arg[2]; kernel_ulong_t remote_iovcnt = tcp->u_arg[4]; @@ -42,7 +43,8 @@ SYS_FUNC(process_vm_writev) kernel_ulong_t flags = tcp->u_arg[5]; /* arg 1: pid */ - tprintf("%d, ", (int) tcp->u_arg[0]); + printpid(tcp, tcp->u_arg[0], PT_TGID); + tprints(", "); /* arg 2: local iov */ tprint_iov(tcp, local_iovcnt, tcp->u_arg[1], IOV_DECODE_STR); /* arg 3: local iovcnt */ diff --git a/resource.c b/resource.c index 53192ee9..070f4740 100644 --- a/resource.c +++ b/resource.c @@ -142,7 +142,8 @@ SYS_FUNC(setrlimit) SYS_FUNC(prlimit64) { if (entering(tcp)) { - tprintf("%d, ", (int) tcp->u_arg[0]); + printpid(tcp, tcp->u_arg[0], PT_TGID); + tprints(", "); printxval(resources, tcp->u_arg[1], "RLIMIT_???"); tprints(", "); print_rlimit64(tcp, tcp->u_arg[2]); @@ -179,10 +180,28 @@ SYS_FUNC(osf_getrusage) #include "xlat/priorities.h" +static void +priority_print_who(struct tcb *tcp, int which, int who) +{ + switch (which) + { + case PRIO_PROCESS: + printpid(tcp, who, PT_TGID); + break; + case PRIO_PGRP: + printpid(tcp, who, PT_PGID); + break; + default: + tprintf("%d", who); + break; + } +} + SYS_FUNC(getpriority) { printxval(priorities, tcp->u_arg[0], "PRIO_???"); - tprintf(", %d", (int) tcp->u_arg[1]); + tprints(", "); + priority_print_who(tcp, tcp->u_arg[0], tcp->u_arg[1]); return RVAL_DECODED; } @@ -190,7 +209,9 @@ SYS_FUNC(getpriority) SYS_FUNC(setpriority) { printxval(priorities, tcp->u_arg[0], "PRIO_???"); - tprintf(", %d, %d", (int) tcp->u_arg[1], (int) tcp->u_arg[2]); + tprints(", "); + priority_print_who(tcp, tcp->u_arg[0], tcp->u_arg[1]); + tprintf(", %d", (int) tcp->u_arg[2]); return RVAL_DECODED; } diff --git a/sched.c b/sched.c index 788ef39b..ff427e48 100644 --- a/sched.c +++ b/sched.c @@ -21,7 +21,7 @@ SYS_FUNC(sched_getscheduler) { if (entering(tcp)) { - tprintf("%d", (int) tcp->u_arg[0]); + printpid(tcp, tcp->u_arg[0], PT_TGID); } else if (!syserror(tcp)) { tcp->auxstr = xlookup(schedulers, (kernel_ulong_t) tcp->u_rval); return RVAL_STR; @@ -31,7 +31,8 @@ SYS_FUNC(sched_getscheduler) SYS_FUNC(sched_setscheduler) { - tprintf("%d, ", (int) tcp->u_arg[0]); + printpid(tcp, tcp->u_arg[0], PT_TGID); + tprints(", "); printxval(schedulers, tcp->u_arg[1], "SCHED_???"); tprints(", "); printnum_int(tcp, tcp->u_arg[2], "%d"); @@ -41,16 +42,19 @@ SYS_FUNC(sched_setscheduler) SYS_FUNC(sched_getparam) { - if (entering(tcp)) - tprintf("%d, ", (int) tcp->u_arg[0]); - else + if (entering(tcp)) { + printpid(tcp, tcp->u_arg[0], PT_TGID); + tprints(", "); + } else { printnum_int(tcp, tcp->u_arg[1], "%d"); + } return 0; } SYS_FUNC(sched_setparam) { - tprintf("%d, ", (int) tcp->u_arg[0]); + printpid(tcp, tcp->u_arg[0], PT_TGID); + tprints(", "); printnum_int(tcp, tcp->u_arg[1], "%d"); return RVAL_DECODED; @@ -68,7 +72,8 @@ do_sched_rr_get_interval(struct tcb *const tcp, const print_obj_by_addr_fn print_ts) { if (entering(tcp)) { - tprintf("%d, ", (int) tcp->u_arg[0]); + printpid(tcp, tcp->u_arg[0], PT_TGID); + tprints(", "); } else { if (syserror(tcp)) printaddr(tcp->u_arg[1]); @@ -160,7 +165,8 @@ end: SYS_FUNC(sched_setattr) { if (entering(tcp)) { - tprintf("%d, ", (int) tcp->u_arg[0]); + printpid(tcp, tcp->u_arg[0], PT_TGID); + tprints(", "); print_sched_attr(tcp, tcp->u_arg[1], 0); } else { struct sched_attr attr; @@ -179,7 +185,8 @@ SYS_FUNC(sched_setattr) SYS_FUNC(sched_getattr) { if (entering(tcp)) { - tprintf("%d, ", (int) tcp->u_arg[0]); + printpid(tcp, tcp->u_arg[0], PT_TGID); + tprints(", "); } else { const unsigned int size = tcp->u_arg[2]; diff --git a/signal.c b/signal.c index d5d59105..49b4ebd5 100644 --- a/signal.c +++ b/signal.c @@ -439,7 +439,8 @@ SYS_FUNC(sigprocmask) SYS_FUNC(kill) { /* pid */ - tprintf("%d, ", (int) tcp->u_arg[0]); + printpid_tgid_pgid(tcp, tcp->u_arg[0]); + tprints(", "); /* signal */ printsignal(tcp->u_arg[1]); @@ -448,7 +449,7 @@ SYS_FUNC(kill) SYS_FUNC(tkill) { - tprintf("%d", (int) tcp->u_arg[0]); + printpid(tcp, tcp->u_arg[0], PT_TID); tprints(", "); printsignal(tcp->u_arg[1]); @@ -457,8 +458,12 @@ SYS_FUNC(tkill) SYS_FUNC(tgkill) { - /* tgid, tid */ - tprintf("%d, %d, ", (int) tcp->u_arg[0], (int) tcp->u_arg[1]); + /* tgid */ + printpid(tcp, tcp->u_arg[0], PT_TGID); + tprints(", "); + /* tid */ + printpid(tcp, tcp->u_arg[1], PT_TID); + tprints(", "); /* signal */ printsignal(tcp->u_arg[2]); @@ -624,7 +629,8 @@ print_sigqueueinfo(struct tcb *const tcp, const int sig, SYS_FUNC(rt_sigqueueinfo) { - tprintf("%d, ", (int) tcp->u_arg[0]); + printpid(tcp, tcp->u_arg[0], PT_TGID); + tprints(", "); print_sigqueueinfo(tcp, tcp->u_arg[1], tcp->u_arg[2]); return RVAL_DECODED; @@ -632,7 +638,10 @@ SYS_FUNC(rt_sigqueueinfo) SYS_FUNC(rt_tgsigqueueinfo) { - tprintf("%d, %d, ", (int) tcp->u_arg[0], (int) tcp->u_arg[1]); + printpid(tcp, tcp->u_arg[0], PT_TGID); + tprints(", "); + printpid(tcp, tcp->u_arg[1], PT_TID); + tprints(", "); print_sigqueueinfo(tcp, tcp->u_arg[2], tcp->u_arg[3]); return RVAL_DECODED; diff --git a/sockaddr.c b/sockaddr.c index b0046331..fb8887c2 100644 --- a/sockaddr.c +++ b/sockaddr.c @@ -416,7 +416,7 @@ print_sockaddr_data_nl(struct tcb *tcp, const void *const buf, const int addrlen { const struct sockaddr_nl *const sa_nl = buf; - PRINT_FIELD_D("", *sa_nl, nl_pid); + PRINT_FIELD_TGID("", *sa_nl, nl_pid, tcp); PRINT_FIELD_0X(", ", *sa_nl, nl_groups); } diff --git a/tests/kcmp.c b/tests/kcmp.c index a46da0ed..dc5ba9a4 100644 --- a/tests/kcmp.c +++ b/tests/kcmp.c @@ -64,7 +64,26 @@ static const char zero_path[] = "/dev/zero"; static void printpidfd(const char *prefix, pid_t pid, unsigned fd) { - printf("%s%d", prefix, fd); + const char *path = NULL; + +# if VERBOSE_FD + if (pid == getpid()) { + switch (fd) + { + case NULL_FD: + path = null_path; + break; + case ZERO_FD: + path = zero_path; + break; + } + } +# endif + + if (path) + printf("%s%d<%s>", prefix, fd, path); + else + printf("%s%d", prefix, fd); } /* @@ -179,7 +198,7 @@ main(void) /* KCMP_FILE is the only type which has additional args */ do_kcmp(3141592653U, 2718281828U, ARG_STR(KCMP_FILE), bogus_idx1, bogus_idx2); - do_kcmp(-1, -1, ARG_STR(KCMP_FILE), NULL_FD, ZERO_FD); + do_kcmp(getpid(), getpid(), ARG_STR(KCMP_FILE), NULL_FD, ZERO_FD); /* Types without additional args */ do_kcmp(-1, -1, ARG_STR(KCMP_VM), bogus_idx1, bogus_idx2); @@ -198,7 +217,7 @@ main(void) for (i = 0; i < ARRAY_SIZE(slot_data); i++) { memcpy(slot, slot_data + i, sizeof(*slot)); - do_kcmp(getpid(), getppid(), ARG_STR(KCMP_EPOLL_TFD), NULL_FD, + do_kcmp(getpid(), -1, ARG_STR(KCMP_EPOLL_TFD), NULL_FD, (uintptr_t) slot, 1); } diff --git a/util.c b/util.c index 286c6903..2568021e 100644 --- a/util.c +++ b/util.c @@ -392,6 +392,18 @@ printnum_fd(struct tcb *const tcp, const kernel_ulong_t addr) return true; } +bool +printnum_pid(struct tcb *const tcp, const kernel_ulong_t addr, enum pid_type type) +{ + int pid; + if (umove_or_printaddr(tcp, addr, &pid)) + return false; + tprints("["); + printpid(tcp, pid, type); + tprints("]"); + return true; +} + /** * Prints time to a (static internal) buffer and returns pointer to it. * Returns NULL if the provided time specification is not correct. @@ -616,7 +628,7 @@ void printfd_pid(struct tcb *tcp, pid_t pid, int fd) { char path[PATH_MAX + 1]; - if (!number_set_array_is_empty(decode_fd_set, 0) + if (pid > 0 && !number_set_array_is_empty(decode_fd_set, 0) && getfdpath_pid(pid, fd, path, sizeof(path)) >= 0) { tprintf("%d<", (int) fd); if (is_number_in_set(DECODE_FD_SOCKET, decode_fd_set) && @@ -641,12 +653,8 @@ printed: void printfd_pid_tracee_ns(struct tcb *tcp, pid_t pid, int fd) { - /* - * TODO: We want to have the same formatting as printfd here, - * but we should figure out first which process in strace's - * PID NS is referred to by pid in tracee's PID NS. - */ - tprintf("%d", fd); + int strace_pid = translate_pid(tcp, pid, PT_TGID, NULL); + printfd_pid(tcp, strace_pid, fd); } /* diff --git a/wait.c b/wait.c index 2b9f9807..177427c8 100644 --- a/wait.c +++ b/wait.c @@ -80,14 +80,8 @@ printwaitn(struct tcb *const tcp, void (*const print_rusage)(struct tcb *, kernel_ulong_t)) { if (entering(tcp)) { - /* On Linux, kernel-side pid_t is typedef'ed to int - * on all arches. Also, glibc-2.8 truncates wait3 and wait4 - * pid argument to int on 64bit arches, producing, - * for example, wait4(4294967295, ...) instead of -1 - * in strace. We have to use int here, not long. - */ - int pid = tcp->u_arg[0]; - tprintf("%d, ", pid); + printpid_tgid_pgid(tcp, tcp->u_arg[0]); + tprintf(", "); } else { int status; @@ -108,7 +102,7 @@ printwaitn(struct tcb *const tcp, printaddr(tcp->u_arg[3]); } } - return 0; + return RVAL_TGID; } SYS_FUNC(waitpid) @@ -134,10 +128,28 @@ SYS_FUNC(osf_wait4) SYS_FUNC(waitid) { + unsigned int idtype = (unsigned int) tcp->u_arg[0]; + int id = tcp->u_arg[1]; + if (entering(tcp)) { - printxval(waitid_types, tcp->u_arg[0], "P_???"); - int pid = tcp->u_arg[1]; - tprintf(", %d, ", pid); + printxval(waitid_types, idtype, "P_???"); + tprints(", "); + switch (idtype) + { + case P_PID: + printpid(tcp, id, PT_TGID); + break; + case P_PIDFD: + printfd(tcp, id); + break; + case P_PGID: + printpid(tcp, id, PT_PGID); + break; + default: + tprintf("%d", id); + break; + } + tprints(", "); } else { /* siginfo */ printsiginfo_at(tcp, tcp->u_arg[2]); -- 2.27.0 From uzonyi.akos at gmail.com Sun Aug 9 14:13:05 2020 From: uzonyi.akos at gmail.com (=?UTF-8?q?=C3=81kos=20Uzonyi?=) Date: Sun, 9 Aug 2020 16:13:05 +0200 Subject: [PATCH v8 4/5] Implement testing framework for pidns In-Reply-To: <20200809141306.477539-1-uzonyi.akos@gmail.com> References: <20200809141306.477539-1-uzonyi.akos@gmail.com> Message-ID: <20200809141306.477539-5-uzonyi.akos@gmail.com> * tests/pidns.c: New file. * tests/pidns.h: New file. * tests/Makefile.am (libtests_a_SOURCES): Add pidns.c, pidns.h. * tests/init.sh (test_pidns, test_pidns_run_strace): New functions. --- tests/Makefile.am | 2 + tests/init.sh | 31 +++++++ tests/pidns.c | 214 ++++++++++++++++++++++++++++++++++++++++++++++ tests/pidns.h | 56 ++++++++++++ 4 files changed, 303 insertions(+) create mode 100644 tests/pidns.c create mode 100644 tests/pidns.h diff --git a/tests/Makefile.am b/tests/Makefile.am index 28d95e39..7a583a3a 100644 --- a/tests/Makefile.am +++ b/tests/Makefile.am @@ -44,6 +44,8 @@ libtests_a_SOURCES = \ libsocketcall.c \ lock_file.c \ overflowuid.c \ + pidns.c \ + pidns.h \ pipe_maxfd.c \ print_quoted_string.c \ print_time.c \ diff --git a/tests/init.sh b/tests/init.sh index d78e697b..7325fa4a 100644 --- a/tests/init.sh +++ b/tests/init.sh @@ -387,6 +387,37 @@ test_prog_set() test_pure_prog_set "$@" < "$srcdir/$NAME.in" } +test_pidns_run_strace() +{ + local parent_pid + + check_prog tail + check_prog cut + check_prog grep + + run_prog > /dev/null + run_strace --pidns-translation -f $@ $args > "$EXP" + + # filter out logs made by the parent or init process of the pidns test + parent_pid="$(tail -n 2 $LOG | head -n 1 | cut -d' ' -f1)" + init_pid="$(tail -n 1 $LOG | cut -d' ' -f1)" + grep -E -v "^($parent_pid|$init_pid) " "$LOG" > "$OUT" + match_diff "$OUT" "$EXP" +} + +test_pidns() +{ + # ioctl(NS_GET_PARENT) is added in Linux 4.9 + require_min_kernel_version_or_skip 4.9 + check_prog unshare + + test_pidns_run_strace "$@" + + # test PID translation when /proc is mounted from an other namespace + STRACE="unshare -Urpf $STRACE" + test_pidns_run_strace "$@" +} + check_prog cat check_prog rm diff --git a/tests/pidns.c b/tests/pidns.c new file mode 100644 index 00000000..f54af340 --- /dev/null +++ b/tests/pidns.c @@ -0,0 +1,214 @@ +/* + * Testing framework for PID namespace translation + * + * Copyright (c) 2020 ?kos Uzonyi + * All rights reserved. + * + * SPDX-License-Identifier: LGPL-2.1-or-later + */ +#include "tests.h" +#include "pidns.h" +#include "nsfs.h" + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +static bool pidns_translation = false; +static bool pidns_unshared = false; + +/* Our PIDs in strace's namespace */ +static pid_t pidns_strace_ids[PT_COUNT]; + +void +pidns_print_leader(void) +{ + if (pidns_translation) + printf("%-5d ", pidns_strace_ids[PT_TID]); +} + +const char * +pidns_pid2str(enum pid_type type) +{ + static const char format[] = " /* %d in strace's PID NS */"; + static char buf[PT_COUNT][sizeof(format) + sizeof(int) * 3]; + + if (type < 0 || type >= PT_COUNT) + return ""; + + if (!pidns_unshared || !pidns_strace_ids[type]) + return ""; + + snprintf(buf[type], sizeof(buf[type]), format, pidns_strace_ids[type]); + return buf[type]; +} + +/** + * This function is like fork, but does a few more things. It sets up the + * child's PGID and SID according to the parameters. Also it fills the + * pidns_strace_ids array in the child's memory with the PIDs of the child in + * parent's PID namespace. In the parent it waits for the child to terminate + * (but leaves the zombie to use it later as a process group). If the child + * terminates with nonzero exit status, the test is failed. + * + * @param pgid The process group the child should be moved to. It's expected + * to be a PID of a zombie process (will be reaped). If + * negative, leave the child in the process group of the parent. + * If 0, move the process to its own process group. + * @param new_sid Wheather child should be moved to a new session. + */ +static pid_t +pidns_fork(pid_t pgid, bool new_sid) +{ + int strace_ids_pipe[2]; + if (pipe(strace_ids_pipe) < 0) + perror_msg_and_fail("pipe"); + + fflush(stdout); + pid_t pid = fork(); + if (pid < 0) + perror_msg_and_fail("fork"); + + if (!pid) { + close(strace_ids_pipe[1]); + if (read(strace_ids_pipe[0], pidns_strace_ids, + sizeof(pidns_strace_ids)) < 0) + perror_msg_and_fail("read"); + close(strace_ids_pipe[0]); + + if (pidns_strace_ids[PT_SID]) + setsid(); + + return 0; + } + + pidns_strace_ids[PT_TID] = pid; + pidns_strace_ids[PT_TGID] = pid; + pidns_strace_ids[PT_PGID] = 0; + pidns_strace_ids[PT_SID] = 0; + + if (!pgid) + pgid = pid; + + if (pgid > 0) { + if (setpgid(pid, pgid) < 0) + perror_msg_and_fail("setpgid"); + + pidns_strace_ids[PT_PGID] = pgid; + } + + /* Reap group leader to test PGID decoding */ + if (pgid > 0 && pgid != pid) { + int ret = waitpid(pgid, NULL, WNOHANG); + if (ret < 0) + perror_msg_and_fail("wait"); + if (!ret) + error_msg_and_fail("could not reap group leader"); + } + + if (new_sid) { + pidns_strace_ids[PT_SID] = pid; + pidns_strace_ids[PT_PGID] = pid; + } + + if (write(strace_ids_pipe[1], pidns_strace_ids, + sizeof(pidns_strace_ids)) < 0) + perror_msg_and_fail("write"); + close(strace_ids_pipe[0]); + close(strace_ids_pipe[1]); + + /* WNOWAIT: leave the zombie, to be able to use it as a process group */ + siginfo_t siginfo; + if (waitid(P_PID, pid, &siginfo, WEXITED | WNOWAIT) < 0) + perror_msg_and_fail("wait"); + if (siginfo.si_code != CLD_EXITED || siginfo.si_status) + error_msg_and_fail("child terminated with nonzero exit status"); + + return pid; +} + +static void +create_init_process(void) +{ + int child_pipe[2]; + if (pipe(child_pipe) < 0) + perror_msg_and_fail("pipe"); + + pid_t pid = fork(); + if (pid < 0) + perror_msg_and_fail("fork"); + + if (!pid) { + close(child_pipe[1]); + _exit(read(child_pipe[0], &child_pipe[1], sizeof(int)) == 0); + } + + close(child_pipe[0]); +} + +void +check_ns_ioctl(void) +{ + int fd = open("/proc/self/ns/pid", O_RDONLY); + if (fd < 0) + perror_msg_and_fail("opening /proc/self/ns/pid"); + + int userns_fd = ioctl(fd, NS_GET_USERNS); + if (userns_fd < 0) { + if (errno == ENOTTY) + error_msg_and_skip("NS_* ioctl commands are not " + "supported by the kernel"); + else + perror_msg_and_fail("ioctl(NS_GET_USERNS)"); + } + + close(userns_fd); + close(fd); +} + +void +pidns_test_init(void) +{ + pidns_translation = true; + + check_ns_ioctl(); + + if (!pidns_fork(-1, false)) + return; + + /* Unshare user namespace too, so we do not need to be root */ + if (unshare(CLONE_NEWUSER | CLONE_NEWPID) < 0) { + if (errno == EPERM) + perror_msg_and_skip("unshare"); + + perror_msg_and_fail("unshare"); + } + + pidns_unshared = true; + + create_init_process(); + + if (!pidns_fork(-1, false)) + return; + + if (!pidns_fork(-1, true)) + return; + + pid_t pgid; + if (!(pgid = pidns_fork(0, false))) + return; + + if (!pidns_fork(pgid, false)) + return; + + exit(0); +} diff --git a/tests/pidns.h b/tests/pidns.h new file mode 100644 index 00000000..76963eb3 --- /dev/null +++ b/tests/pidns.h @@ -0,0 +1,56 @@ +/* + * Test PID namespace translation + * + * Copyright (c) 2020 ?kos Uzonyi + * All rights reserved. + * + * SPDX-License-Identifier: LGPL-2.1-or-later + */ +#ifndef STRACE_PIDNS_H +#define STRACE_PIDNS_H + +#ifdef PIDNS_TRANSLATION +# define PIDNS_TEST_INIT pidns_test_init() +#else +# define PIDNS_TEST_INIT +#endif + +#include + +enum pid_type { + PT_TID, + PT_TGID, + PT_PGID, + PT_SID, + + PT_COUNT, + PT_NONE = -1 +}; + +/* Prints leader (process tid) if pidns_test_init was called */ +void pidns_print_leader(void); + +/* + * Returns a static buffer containing the translation string of our PID. + */ +const char *pidns_pid2str(enum pid_type type); + +/** + * Skips the test if NS_* ioctl commands are not supported by the kernel. + */ +void check_ns_ioctl(void); + +/** + * Init pidns testing. + * + * Should be called at the beginning of the test's main function + * + * This function calls fork a couple of times, and returns in the child + * processes. These child processes are in a new PID namespace with different + * PID configurations (group leader, session leader, ...). If any child + * terminates with nonzero exit status the test is failed. Otherwise the test is + * succesful, and the parent process exits with 0. + */ +void pidns_test_init(void); + +#endif \ No newline at end of file -- 2.27.0 From uzonyi.akos at gmail.com Sun Aug 9 14:13:06 2020 From: uzonyi.akos at gmail.com (=?UTF-8?q?=C3=81kos=20Uzonyi?=) Date: Sun, 9 Aug 2020 16:13:06 +0200 Subject: [PATCH v8 5/5] Add tests for PID namespace translation In-Reply-To: <20200809141306.477539-1-uzonyi.akos@gmail.com> References: <20200809141306.477539-1-uzonyi.akos@gmail.com> Message-ID: <20200809141306.477539-6-uzonyi.akos@gmail.com> * tests/.gitignore: Add new test executables. * tests/Makefile.am (check_PROGRAMS): Add new test executables. (DECODER_TESTS) Add new test files. * tests/gen_tests.in: Add new tests. * tests/fcntl--pidns-translation.c: New file. * tests/fcntl64--pidns-translation.c: New file. * tests/fork--pidns-translation.awk: New file. * tests/fork--pidns-translation.c: New file. * tests/fork--pidns-translation.test: New file. * tests/getpgrp--pidns-translation.c: New file. * tests/getpid--pidns-translation.c: New file. * tests/getsid--pidns-translation.c: New file. * tests/gettid--pidns-translation.c: New file. * tests/gettid--pidns-translation.test: New file. * tests/ioctl_block--pidns-translation.c: New file. * tests/ioctl_block--pidns-translation.test: New file. * tests/ioprio--pidns-translation.c: New file. * tests/kill--pidns-translation.c: New file. * tests/migrate_pages--pidns-translation.c: New file. * tests/move_pages--pidns-translation.c: New file. * tests/net-sockaddr--pidns-translation.c: New file. * tests/netlink_audit--pidns-translation.c: New file. * tests/netlink_audit--pidns-translation.test: New file. * tests/pidfd_open--pidns-translation.c: New file. * tests/pidfd_send_signal--pidns-translation.c: New file. * tests/prlimit64--pidns-translation.c: New file. * tests/process_vm_readv--pidns-translation.c: New file. * tests/process_vm_writev--pidns-translation.c: New file. * tests/rt_sigqueueinfo--pidns-translation.c: New file. * tests/rt_tgsigqueueinfo--pidns-translation.c: New file. * tests/sched_xetaffinity--pidns-translation.c: New file. * tests/sched_xetattr--pidns-translation.c: New file. * tests/sched_xetparam--pidns-translation.c: New file. * tests/sched_xetscheduler--pidns-translation.c: New file. * tests/signal_receive--pidns-translation.c: New file. * tests/so_peercred--pidns-translation.c: New file. * tests/xet_robust_list--pidns-translation.c: New file. * tests/xetpgid--pidns-translation.c: New file. * tests/xetpriority--pidns-translation.c: New file. * tests/fcntl-common.c: Print PID translation string after PIDs. * tests/fcntl.c: Likewise. * tests/fcntl64.c: Likewise. * tests/getpgrp.c: Likewise. * tests/getpid.c: Likewise. * tests/getsid.c: Likewise. * tests/gettid.c: Likewise. * tests/ioctl_block.c: Likewise. * tests/ioprio.c: Likewise. * tests/kcmp.c: Likewise. * tests/kill.c: Likewise. * tests/migrate_pages.c: Likewise. * tests/move_pages.c: Likewise. * tests/net-sockaddr.c: Likewise. * tests/netlink_audit.c: Likewise. * tests/pidfd_open.c: Likewise. * tests/pidfd_send_signal.c: Likewise. * tests/prlimit64.c: Likewise. * tests/process_vm_readv_writev.c: Likewise. * tests/rt_sigqueueinfo.c: Likewise. * tests/rt_tgsigqueueinfo.c: Likewise. * tests/sched_xetaffinity.c: Likewise. * tests/sched_xetattr.c: Likewise. * tests/sched_xetparam.c: Likewise. * tests/sched_xetscheduler.c: Likewise. * tests/signal_receive.c: Likewise. * tests/so_peercred.c: Likewise. * tests/xet_robust_list.c: Likewise. * tests/xetpgid.c: Likewise. * tests/xetpriority.c: Likewise. --- tests/.gitignore | 31 +++++++ tests/Makefile.am | 36 ++++++++ tests/fcntl--pidns-translation.c | 2 + tests/fcntl-common.c | 82 ++++++++++++++----- tests/fcntl.c | 1 + tests/fcntl64--pidns-translation.c | 2 + tests/fcntl64.c | 3 + tests/fork--pidns-translation.awk | 15 ++++ tests/fork--pidns-translation.c | 69 ++++++++++++++++ tests/fork--pidns-translation.test | 16 ++++ tests/gen_tests.in | 29 ++++++- tests/getpgrp--pidns-translation.c | 2 + tests/getpgrp.c | 8 +- tests/getpid--pidns-translation.c | 2 + tests/getpid.c | 8 +- tests/getsid--pidns-translation.c | 2 + tests/getsid.c | 9 +- tests/gettid--pidns-translation.c | 2 + tests/gettid--pidns-translation.test | 20 +++++ tests/gettid.c | 8 +- tests/ioctl_block--pidns-translation.c | 2 + tests/ioctl_block--pidns-translation.test | 24 ++++++ tests/ioctl_block.c | 24 +++++- tests/ioprio--pidns-translation.c | 2 + tests/ioprio.c | 54 ++++++++---- tests/kcmp-y--pidns-translation.c | 2 + tests/kcmp.c | 11 ++- tests/kill--pidns-translation.c | 2 + tests/kill.c | 12 ++- tests/migrate_pages--pidns-translation.c | 2 + tests/migrate_pages.c | 17 +++- tests/move_pages--pidns-translation.c | 2 + tests/move_pages.c | 51 +++++++----- tests/net-sockaddr--pidns-translation.c | 2 + tests/net-sockaddr.c | 66 +++++++++++++-- tests/netlink_audit--pidns-translation.c | 2 + tests/netlink_audit--pidns-translation.test | 13 +++ tests/netlink_audit.c | 11 ++- tests/pidfd_open--pidns-translation.c | 2 + tests/pidfd_open.c | 21 +++-- tests/pidfd_send_signal--pidns-translation.c | 2 + tests/pidfd_send_signal.c | 13 ++- tests/prlimit64--pidns-translation.c | 2 + tests/prlimit64.c | 17 +++- tests/process_vm_readv--pidns-translation.c | 2 + tests/process_vm_readv_writev.c | 27 +++--- tests/process_vm_writev--pidns-translation.c | 2 + tests/rt_sigqueueinfo--pidns-translation.c | 2 + tests/rt_sigqueueinfo.c | 15 +++- tests/rt_tgsigqueueinfo--pidns-translation.c | 2 + tests/rt_tgsigqueueinfo.c | 26 ++++-- tests/sched_xetaffinity--pidns-translation.c | 2 + tests/sched_xetaffinity.c | 31 ++++--- tests/sched_xetattr--pidns-translation.c | 2 + tests/sched_xetattr.c | 47 ++++++++++- tests/sched_xetparam--pidns-translation.c | 2 + tests/sched_xetparam.c | 20 +++-- tests/sched_xetscheduler--pidns-translation.c | 2 + tests/sched_xetscheduler.c | 44 ++++++---- tests/signal_receive--pidns-translation.c | 2 + tests/signal_receive.c | 22 +++-- tests/so_peercred--pidns-translation.c | 2 + tests/so_peercred.c | 22 +++++ tests/xet_robust_list--pidns-translation.c | 2 + tests/xet_robust_list.c | 18 +++- tests/xetpgid--pidns-translation.c | 2 + tests/xetpgid.c | 21 +++-- tests/xetpriority--pidns-translation.c | 2 + tests/xetpriority.c | 20 ++++- 69 files changed, 874 insertions(+), 168 deletions(-) create mode 100644 tests/fcntl--pidns-translation.c create mode 100644 tests/fcntl64--pidns-translation.c create mode 100644 tests/fork--pidns-translation.awk create mode 100644 tests/fork--pidns-translation.c create mode 100755 tests/fork--pidns-translation.test create mode 100644 tests/getpgrp--pidns-translation.c create mode 100644 tests/getpid--pidns-translation.c create mode 100644 tests/getsid--pidns-translation.c create mode 100644 tests/gettid--pidns-translation.c create mode 100755 tests/gettid--pidns-translation.test create mode 100644 tests/ioctl_block--pidns-translation.c create mode 100755 tests/ioctl_block--pidns-translation.test create mode 100644 tests/ioprio--pidns-translation.c create mode 100644 tests/kcmp-y--pidns-translation.c create mode 100644 tests/kill--pidns-translation.c create mode 100644 tests/migrate_pages--pidns-translation.c create mode 100644 tests/move_pages--pidns-translation.c create mode 100644 tests/net-sockaddr--pidns-translation.c create mode 100644 tests/netlink_audit--pidns-translation.c create mode 100755 tests/netlink_audit--pidns-translation.test create mode 100644 tests/pidfd_open--pidns-translation.c create mode 100644 tests/pidfd_send_signal--pidns-translation.c create mode 100644 tests/prlimit64--pidns-translation.c create mode 100644 tests/process_vm_readv--pidns-translation.c create mode 100644 tests/process_vm_writev--pidns-translation.c create mode 100644 tests/rt_sigqueueinfo--pidns-translation.c create mode 100644 tests/rt_tgsigqueueinfo--pidns-translation.c create mode 100644 tests/sched_xetaffinity--pidns-translation.c create mode 100644 tests/sched_xetattr--pidns-translation.c create mode 100644 tests/sched_xetparam--pidns-translation.c create mode 100644 tests/sched_xetscheduler--pidns-translation.c create mode 100644 tests/signal_receive--pidns-translation.c create mode 100644 tests/so_peercred--pidns-translation.c create mode 100644 tests/xet_robust_list--pidns-translation.c create mode 100644 tests/xetpgid--pidns-translation.c create mode 100644 tests/xetpriority--pidns-translation.c diff --git a/tests/.gitignore b/tests/.gitignore index 0031d04d..4d1153fc 100644 --- a/tests/.gitignore +++ b/tests/.gitignore @@ -116,7 +116,9 @@ fchown fchown32 fchownat fcntl +fcntl--pidns-translation fcntl64 +fcntl64--pidns-translation fdatasync fflush file_handle @@ -126,6 +128,7 @@ filter-unavailable finit_module flock fork-f +fork--pidns-translation fsconfig fsconfig-P fsmount @@ -168,7 +171,9 @@ getgroups getgroups32 getpeername getpgrp +getpgrp--pidns-translation getpid +getpid--pidns-translation getppid getrandom getresgid @@ -178,8 +183,10 @@ getresuid32 getrlimit getrusage getsid +getsid--pidns-translation getsockname gettid +gettid--pidns-translation getuid getuid32 getxgid @@ -200,6 +207,7 @@ io_uring_register io_uring_setup ioctl ioctl_block +ioctl_block--pidns-translation ioctl_dm ioctl_dm-v ioctl_evdev @@ -275,6 +283,7 @@ ioctl_watchdog ioperm iopl ioprio +ioprio--pidns-translation ioprio-Xabbrev ioprio-Xraw ioprio-Xverbose @@ -299,6 +308,7 @@ ipc_shm-Xverbose is_linux_mips_n64 kcmp kcmp-y +kcmp-y--pidns-translation kern_features kernel_version kernel_version-Xabbrev @@ -311,6 +321,7 @@ keyctl-Xabbrev keyctl-Xraw keyctl-Xverbose kill +kill--pidns-translation kill_child ksysent ksysent.h @@ -340,6 +351,7 @@ memfd_create-Xabbrev memfd_create-Xraw memfd_create-Xverbose migrate_pages +migrate_pages--pidns-translation mincore mkdir mkdirat @@ -371,6 +383,7 @@ move_pages move_pages-Xabbrev move_pages-Xraw move_pages-Xverbose +move_pages--pidns-translation mq mq_sendrecv mq_sendrecv-read @@ -391,6 +404,7 @@ net-packet_mreq-Xabbrev net-packet_mreq-Xraw net-packet_mreq-Xverbose net-sockaddr +net-sockaddr--pidns-translation net-tpacket_req net-tpacket_stats net-tpacket_stats-success @@ -400,6 +414,7 @@ net-yy-inet6 net-yy-netlink net-yy-unix netlink_audit +netlink_audit--pidns-translation netlink_crypto netlink_generic netlink_inet_diag @@ -507,7 +522,9 @@ pidfd_open--decode-fd-socket pidfd_open-P pidfd_open-y pidfd_open-yy +pidfd_open--pidns-translation pidfd_send_signal +pidfd_send_signal--pidns-translation pipe pipe2 pkey_alloc @@ -546,8 +563,11 @@ printstrn-umoven printstrn-umoven-peekdata printstrn-umoven-undumpable prlimit64 +prlimit64--pidns-translation process_vm_readv +process_vm_readv--pidns-translation process_vm_writev +process_vm_writev--pidns-translation pselect6 ptrace ptrace_syscall_info @@ -597,10 +617,12 @@ rt_sigaction rt_sigpending rt_sigprocmask rt_sigqueueinfo +rt_sigqueueinfo--pidns-translation rt_sigreturn rt_sigsuspend rt_sigtimedwait rt_tgsigqueueinfo +rt_tgsigqueueinfo--pidns-translation run_expect_termsig s390_guarded_storage s390_guarded_storage-v @@ -611,9 +633,13 @@ s390_sthyi-v sched_get_priority_mxx sched_rr_get_interval sched_xetaffinity +sched_xetaffinity--pidns-translation sched_xetattr +sched_xetattr--pidns-translation sched_xetparam +sched_xetparam--pidns-translation sched_xetscheduler +sched_xetscheduler--pidns-translation sched_yield scm_rights scno.h @@ -669,6 +695,7 @@ sigaltstack siginfo signal signal_receive +signal_receive--pidns-translation signalfd4 sigpending sigprocmask @@ -681,6 +708,7 @@ so_peercred so_peercred-Xabbrev so_peercred-Xraw so_peercred-Xverbose +so_peercred--pidns-translation sock_filter-v sock_filter-v-Xabbrev sock_filter-v-Xraw @@ -783,9 +811,12 @@ waitpid xattr xattr-strings xet_robust_list +xet_robust_list--pidns-translation xet_thread_area_x86 xetitimer xetpgid +xetpgid--pidns-translation xetpriority +xetpriority--pidns-translation xettimeofday zeroargc diff --git a/tests/Makefile.am b/tests/Makefile.am index 7a583a3a..f2c5da83 100644 --- a/tests/Makefile.am +++ b/tests/Makefile.am @@ -109,17 +109,25 @@ check_PROGRAMS = $(PURE_EXECUTABLES) \ delay \ execve-v \ execveat-v \ + fcntl--pidns-translation \ + fcntl64--pidns-translation \ filter_seccomp-flag \ filter_seccomp-perf \ filter-unavailable \ fork-f \ + fork--pidns-translation \ fsync-y \ get_process_reaper \ + getpgrp--pidns-translation \ getpid \ + getpid--pidns-translation \ getppid \ + getsid--pidns-translation \ gettid \ + gettid--pidns-translation \ inject-nf \ int_0x80 \ + ioctl_block--pidns-translation \ ioctl_dm-v \ ioctl_evdev-success \ ioctl_evdev-success-Xabbrev \ @@ -150,18 +158,25 @@ check_PROGRAMS = $(PURE_EXECUTABLES) \ ioctl_v4l2-success-v-Xabbrev \ ioctl_v4l2-success-v-Xraw \ ioctl_v4l2-success-v-Xverbose \ + ioprio--pidns-translation \ is_linux_mips_n64 \ + kcmp-y--pidns-translation \ kill_child \ + kill--pidns-translation \ ksysent \ list_sigaction_signum \ localtime \ looping_threads \ + migrate_pages--pidns-translation \ mmsg-silent \ mmsg_name-v \ + move_pages--pidns-translation \ msg_control-v \ net-accept-connect \ + net-sockaddr--pidns-translation \ net-tpacket_stats-success \ nlattr_ifla_xdp-y \ + netlink_audit--pidns-translation \ netlink_inet_diag \ netlink_netlink_diag \ netlink_unix_diag \ @@ -173,14 +188,19 @@ check_PROGRAMS = $(PURE_EXECUTABLES) \ pc \ perf_event_open_nonverbose \ perf_event_open_unabbrev \ + pidfd_open--pidns-translation \ + pidfd_send_signal--pidns-translation \ poll-P \ ppoll-P \ ppoll-v \ + prlimit64--pidns-translation \ prctl-seccomp-filter-v \ prctl-seccomp-strict \ prctl-spec-inject \ print_maxfd \ print_ppid_tracerpid \ + process_vm_readv--pidns-translation \ + process_vm_writev--pidns-translation \ qual_fault \ qual_inject-error-signal \ qual_inject-retval \ @@ -194,7 +214,13 @@ check_PROGRAMS = $(PURE_EXECUTABLES) \ quotactl-xfs-v \ redirect-fds \ restart_syscall \ + rt_sigqueueinfo--pidns-translation \ + rt_tgsigqueueinfo--pidns-translation \ run_expect_termsig \ + sched_xetaffinity--pidns-translation \ + sched_xetattr--pidns-translation \ + sched_xetparam--pidns-translation \ + sched_xetscheduler--pidns-translation \ scm_rights \ seccomp-filter-v \ seccomp-strict \ @@ -204,12 +230,14 @@ check_PROGRAMS = $(PURE_EXECUTABLES) \ set_sigign \ setpgrp-exec \ signal_receive \ + signal_receive--pidns-translation \ sleep \ stack-fcall \ stack-fcall-attach \ stack-fcall-mangled \ status-none-threads \ status-unfinished-threads \ + so_peercred--pidns-translation \ syslog-success \ threads-execve \ threads-execve--quiet-thread-execve \ @@ -223,6 +251,9 @@ check_PROGRAMS = $(PURE_EXECUTABLES) \ vfork-f \ wait4-v \ waitid-v \ + xetpgid--pidns-translation \ + xetpriority--pidns-translation \ + xet_robust_list--pidns-translation \ zeroargc \ # end of check_PROGRAMS @@ -310,6 +341,7 @@ DECODER_TESTS = \ int_0x80.test \ inotify_init-y.test \ ioctl.test \ + ioctl_block--pidns-translation.test \ ioctl_evdev-success.test \ ipc_msgbuf.test \ kern_features-fault.test \ @@ -381,12 +413,15 @@ MISC_TESTS = \ filtering_fd-syntax.test \ filtering_syscall-syntax.test \ first_exec_failure.test \ + fork--pidns-translation.test \ get_regs.test \ + gettid--pidns-translation.test \ inject-nf.test \ interactive_block.test \ kill_child.test \ localtime.test \ looping_threads.test \ + netlink_audit--pidns-translation.test \ opipe.test \ options-syntax.test \ pc.test \ @@ -467,6 +502,7 @@ EXTRA_DIST = \ filter_seccomp.in \ filter_seccomp.sh \ filter-unavailable.expected \ + fork--pidns-translation.awk \ fstatat.c \ fstatx.c \ gen_pure_executables.sh \ diff --git a/tests/fcntl--pidns-translation.c b/tests/fcntl--pidns-translation.c new file mode 100644 index 00000000..e249424a --- /dev/null +++ b/tests/fcntl--pidns-translation.c @@ -0,0 +1,2 @@ +#define PIDNS_TRANSLATION +#include "fcntl.c" diff --git a/tests/fcntl-common.c b/tests/fcntl-common.c index 27694326..d9e29939 100644 --- a/tests/fcntl-common.c +++ b/tests/fcntl-common.c @@ -13,6 +13,8 @@ #include #include #include "flock.h" +#include "pidns.h" +#include "scno.h" #define FILE_LEN 4096 @@ -48,12 +50,14 @@ test_flock_einval(const int cmd, const char *name) fl->l_len = (TYPEOF_FLOCK_OFF_T) 0xdefaced2cafef00dULL; invoke_test_syscall(0, cmd, fl); + pidns_print_leader(); printf("%s(0, %s, {l_type=F_RDLCK, l_whence=SEEK_SET" ", l_start=%jd, l_len=%jd}) = %s\n", TEST_SYSCALL_STR, name, (intmax_t) fl->l_start, (intmax_t) fl->l_len, errstr); void *const bad_addr = (void *) fl + 1; invoke_test_syscall(0, cmd, bad_addr); + pidns_print_leader(); printf("%s(0, %s, %p) = %s\n", TEST_SYSCALL_STR, name, bad_addr, errstr); } @@ -72,12 +76,14 @@ test_flock64_einval(const int cmd, const char *name) fl->l_len = (TYPEOF_FLOCK_OFF_T) 0xdefaced2cafef00dULL; invoke_test_syscall(0, cmd, fl); + pidns_print_leader(); printf("%s(0, %s, {l_type=F_RDLCK, l_whence=SEEK_SET" ", l_start=%jd, l_len=%jd}) = %s\n", TEST_SYSCALL_STR, name, (intmax_t) fl->l_start, (intmax_t) fl->l_len, errstr); void *const bad_addr = (void *) fl + 1; invoke_test_syscall(0, cmd, bad_addr); + pidns_print_leader(); printf("%s(0, %s, %p) = %s\n", TEST_SYSCALL_STR, name, bad_addr, errstr); } @@ -94,6 +100,7 @@ test_flock(void) fl->l_len = FILE_LEN; long rc = invoke_test_syscall(0, F_SETLK, fl); + pidns_print_leader(); printf("%s(0, F_SETLK, {l_type=F_RDLCK, l_whence=SEEK_SET" ", l_start=0, l_len=%d}) = %s\n", TEST_SYSCALL_STR, FILE_LEN, errstr); @@ -101,11 +108,13 @@ test_flock(void) return; invoke_test_syscall(0, F_GETLK, fl); + pidns_print_leader(); printf("%s(0, F_GETLK, {l_type=F_UNLCK, l_whence=SEEK_SET" ", l_start=0, l_len=%d, l_pid=0}) = 0\n", TEST_SYSCALL_STR, FILE_LEN); invoke_test_syscall(0, F_SETLKW, fl); + pidns_print_leader(); printf("%s(0, F_SETLKW, {l_type=F_UNLCK, l_whence=SEEK_SET" ", l_start=0, l_len=%d}) = 0\n", TEST_SYSCALL_STR, FILE_LEN); @@ -124,6 +133,7 @@ test_flock64_ofd(void) fl->l_len = FILE_LEN; long rc = invoke_test_syscall(0, F_OFD_SETLK, fl); + pidns_print_leader(); printf("%s(0, F_OFD_SETLK, {l_type=F_RDLCK, l_whence=SEEK_SET" ", l_start=0, l_len=%d}) = %s\n", TEST_SYSCALL_STR, FILE_LEN, errstr); @@ -131,11 +141,13 @@ test_flock64_ofd(void) return; invoke_test_syscall(0, F_OFD_GETLK, fl); + pidns_print_leader(); printf("%s(0, F_OFD_GETLK, {l_type=F_UNLCK, l_whence=SEEK_SET" ", l_start=0, l_len=%d, l_pid=0}) = 0\n", TEST_SYSCALL_STR, FILE_LEN); invoke_test_syscall(0, F_OFD_SETLKW, fl); + pidns_print_leader(); printf("%s(0, F_OFD_SETLKW, {l_type=F_UNLCK, l_whence=SEEK_SET" ", l_start=0, l_len=%d}) = 0\n", TEST_SYSCALL_STR, FILE_LEN); @@ -167,18 +179,21 @@ test_flock64(void) static long test_f_owner_ex_type_pid(const int cmd, const char *const cmd_name, const int type, const char *const type_name, - pid_t pid) + enum pid_type pid_type, pid_t pid) { TAIL_ALLOC_OBJECT_CONST_PTR(struct_kernel_f_owner_ex, fo); fo->type = type; fo->pid = pid; long rc = invoke_test_syscall(0, cmd, fo); - printf("%s(0, %s, {type=%s, pid=%d}) = %s\n", - TEST_SYSCALL_STR, cmd_name, type_name, fo->pid, errstr); + pidns_print_leader(); + printf("%s(0, %s, {type=%s, pid=%d%s}) = %s\n", + TEST_SYSCALL_STR, cmd_name, type_name, + fo->pid, pidns_pid2str(pid_type), errstr); void *bad_addr = (void *) fo + 1; invoke_test_syscall(0, cmd, bad_addr); + pidns_print_leader(); printf("%s(0, %s, %p) = %s\n", TEST_SYSCALL_STR, cmd_name, bad_addr, errstr); @@ -187,35 +202,39 @@ test_f_owner_ex_type_pid(const int cmd, const char *const cmd_name, static void test_f_owner_ex_umove_or_printaddr(const int type, const char *const type_name, - pid_t pid) + enum pid_type pid_type, pid_t pid) { long rc = test_f_owner_ex_type_pid(ARG_STR(F_SETOWN_EX), - type, type_name, pid); + type, type_name, pid_type, pid); if (!rc) test_f_owner_ex_type_pid(ARG_STR(F_GETOWN_EX), - type, type_name, pid); + type, type_name, pid_type, pid); } static void test_f_owner_ex(void) { - static const struct { + struct { int type; const char *type_name; - pid_t pid[2]; + enum pid_type pid_type; + pid_t pid; } a[] = { - { ARG_STR(F_OWNER_TID), { 1234567890, 20 } }, - { ARG_STR(F_OWNER_PID), { 1298126790, 30 } }, - { ARG_STR(F_OWNER_PGRP), { 1294567890, 40 } } + { ARG_STR(F_OWNER_TID), PT_NONE, 1234567890 }, + { ARG_STR(F_OWNER_PID), PT_NONE, 1234567890 }, + { ARG_STR(F_OWNER_PGRP), PT_NONE, 1234567890 }, + { ARG_STR(F_OWNER_TID), PT_TID, 0 }, + { ARG_STR(F_OWNER_PID), PT_TGID, 0 }, + { ARG_STR(F_OWNER_PGRP), PT_PGID, 0 }, }; - for (unsigned int i = 0; i < ARRAY_SIZE(a); i++) { - for (unsigned int j = 0; j < ARRAY_SIZE(a[0].pid); j++) { - test_f_owner_ex_umove_or_printaddr(a[i].type, - a[i].type_name, - a[i].pid[j]); - } - } + a[3].pid = syscall(__NR_gettid); + a[4].pid = getpid(); + a[5].pid = getpgid(0); + + for (unsigned int i = 0; i < ARRAY_SIZE(a); i++) + test_f_owner_ex_umove_or_printaddr(a[i].type, a[i].type_name, + a[i].pid_type, a[i].pid); } #endif /* TEST_F_OWNER_EX */ @@ -228,6 +247,23 @@ struct fcntl_cmd_check { void (*print_flags)(long rc); }; +static void +test_xetown(void) +{ + const int pid = getpid(); + const char *pid_str = pidns_pid2str(PT_TGID); + + invoke_test_syscall(0, F_SETOWN, (void *) (intptr_t) pid); + pidns_print_leader(); + printf("%s(0, F_SETOWN, %d%s) = %s\n", + TEST_SYSCALL_STR, pid, pid_str, errstr); + + invoke_test_syscall(0, F_GETOWN, NULL); + pidns_print_leader(); + printf("%s(0, F_GETOWN) = %d%s\n", + TEST_SYSCALL_STR, pid, pid_str); +} + static void print_retval_flags(const struct fcntl_cmd_check *check, long rc) { @@ -243,12 +279,14 @@ static void test_other_set_cmd(const struct fcntl_cmd_check *check) { invoke_test_syscall(check->fd, check->cmd, (void *) check->arg); + pidns_print_leader(); printf("%s(%d, %s, %s) = %s\n", TEST_SYSCALL_STR, check->fd, check->cmd_str, check->arg_str, errstr); /* bad file fd */ invoke_test_syscall(-1, check->cmd, (void *) check->arg); + pidns_print_leader(); printf("%s(-1, %s, %s) = %s\n", TEST_SYSCALL_STR, check->cmd_str, check->arg_str, errstr); @@ -258,12 +296,14 @@ static void test_other_get_cmd(const struct fcntl_cmd_check *check) { long rc = invoke_test_syscall(check->fd, check->cmd, NULL); + pidns_print_leader(); printf("%s(%d, %s) = ", TEST_SYSCALL_STR, check->fd, check->cmd_str); print_retval_flags(check, rc); /* bad file fd */ invoke_test_syscall(-1, check->cmd, NULL); + pidns_print_leader(); printf("%s(-1, %s) = %s\n", TEST_SYSCALL_STR, check->cmd_str, errstr); } @@ -315,7 +355,6 @@ test_fcntl_others(void) { static const struct fcntl_cmd_check set_checks[] = { { 0, ARG_STR(F_SETFD), ARG_STR(FD_CLOEXEC) }, - { 0, ARG_STR(F_SETOWN), ARG_STR(20) }, #ifdef F_SETPIPE_SZ { 0, ARG_STR(F_SETPIPE_SZ), ARG_STR(4097) }, #endif @@ -336,7 +375,6 @@ test_fcntl_others(void) static const struct fcntl_cmd_check get_checks[] = { { 0, ARG_STR(F_GETFD), .print_flags = print_flags_getfd }, { 1, ARG_STR(F_GETFD), .print_flags = print_flags_getfd }, - { 0, ARG_STR(F_GETOWN) }, #ifdef F_GETPIPE_SZ { 0, ARG_STR(F_GETPIPE_SZ) }, #endif @@ -360,6 +398,8 @@ create_sample(void) int main(void) { + PIDNS_TEST_INIT; + create_sample(); test_flock(); test_flock64(); @@ -367,7 +407,9 @@ main(void) test_f_owner_ex(); #endif test_fcntl_others(); + test_xetown(); + pidns_print_leader(); puts("+++ exited with 0 +++"); return 0; } diff --git a/tests/fcntl.c b/tests/fcntl.c index f38b8afb..673c06e4 100644 --- a/tests/fcntl.c +++ b/tests/fcntl.c @@ -24,6 +24,7 @@ test_flock64_undecoded(const int cmd, const char *name) .l_len = 0xdefaced2cafef00dULL }; invoke_test_syscall(0, cmd, &fl); + pidns_print_leader(); printf("%s(0, %s, %p) = %s\n", TEST_SYSCALL_STR, name, &fl, errstr); } diff --git a/tests/fcntl64--pidns-translation.c b/tests/fcntl64--pidns-translation.c new file mode 100644 index 00000000..c6fdadd1 --- /dev/null +++ b/tests/fcntl64--pidns-translation.c @@ -0,0 +1,2 @@ +#define PIDNS_TRANSLATION +#include "fcntl64.c" diff --git a/tests/fcntl64.c b/tests/fcntl64.c index 78e53b0d..f7b3f2fb 100644 --- a/tests/fcntl64.c +++ b/tests/fcntl64.c @@ -27,6 +27,7 @@ test_flock64_lk64(void) fl->l_len = FILE_LEN; long rc = invoke_test_syscall(0, F_SETLK64, fl); + pidns_print_leader(); printf("%s(0, F_SETLK64, {l_type=F_RDLCK, l_whence=SEEK_SET" ", l_start=0, l_len=%d}) = %s\n", TEST_SYSCALL_STR, FILE_LEN, errstr); @@ -35,11 +36,13 @@ test_flock64_lk64(void) return; invoke_test_syscall(0, F_GETLK64, fl); + pidns_print_leader(); printf("%s(0, F_GETLK64, {l_type=F_UNLCK, l_whence=SEEK_SET" ", l_start=0, l_len=%d, l_pid=0}) = 0\n", TEST_SYSCALL_STR, FILE_LEN); invoke_test_syscall(0, F_SETLKW64, fl); + pidns_print_leader(); printf("%s(0, F_SETLKW64, {l_type=F_UNLCK, l_whence=SEEK_SET" ", l_start=0, l_len=%d}) = 0\n", TEST_SYSCALL_STR, FILE_LEN); diff --git a/tests/fork--pidns-translation.awk b/tests/fork--pidns-translation.awk new file mode 100644 index 00000000..ef6858f4 --- /dev/null +++ b/tests/fork--pidns-translation.awk @@ -0,0 +1,15 @@ +/fork/ { + match($0, "([0-9]+) in strace\x27s PID NS", a); + if (a[1]) + fork_pid = a[1] +} + +/exited with 0/ { + if (!exit_pid) + exit_pid = $1 +} + +END { + if (!fork_pid || !exit_pid || fork_pid != exit_pid) + exit 1 +} diff --git a/tests/fork--pidns-translation.c b/tests/fork--pidns-translation.c new file mode 100644 index 00000000..73c39d5d --- /dev/null +++ b/tests/fork--pidns-translation.c @@ -0,0 +1,69 @@ +/* + * Test PID namespace translation + * + * Copyright (c) 2020 ?kos Uzonyi + * All rights reserved. + * + * SPDX-License-Identifier: LGPL-2.1-or-later + */ + +#include "tests.h" +#include "scno.h" +#include "pidns.h" + +#ifdef __NR_fork + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +static int +fork_chain(int depth) +{ + if (!depth) + return 0; + + int pid = syscall(__NR_fork); + if (pid < 0) + return errno; + + if (!pid) + _exit(fork_chain(depth - 1)); + + int status; + if (wait(&status) < 0) + return errno; + + if (!WIFEXITED(status)) + return -1; + + return WEXITSTATUS(status); +} + +int main(void) +{ + check_ns_ioctl(); + + if (unshare(CLONE_NEWPID | CLONE_NEWUSER) < 0) { + if (errno == EPERM) + perror_msg_and_skip("unshare"); + + perror_msg_and_fail("unshare"); + } + + errno = fork_chain(2); + if (errno) + perror("fork_chain"); +} + +#else + +SKIP_MAIN_UNDEFINED("__NR_fork") + +#endif diff --git a/tests/fork--pidns-translation.test b/tests/fork--pidns-translation.test new file mode 100755 index 00000000..fa7ecda5 --- /dev/null +++ b/tests/fork--pidns-translation.test @@ -0,0 +1,16 @@ +#!/bin/sh +# +# Check pidns translation of fork's return value. +# +# Copyright (c) 2020 The strace developers. +# All rights reserved. +# +# SPDX-License-Identifier: LGPL-2.1-or-later + +. "${srcdir=.}/init.sh" + +require_min_kernel_version_or_skip 4.9 + +run_prog +run_strace -a6 --pidns-translation -f -e trace=fork $args +match_awk diff --git a/tests/gen_tests.in b/tests/gen_tests.in index 6f8e1420..10374a9e 100644 --- a/tests/gen_tests.in +++ b/tests/gen_tests.in @@ -93,7 +93,9 @@ fchown -a16 fchown32 -a18 fchownat fcntl -a8 +fcntl--pidns-translation test_pidns -a8 -e trace=fcntl fcntl64 -a8 +fcntl64--pidns-translation test_pidns -a8 -e trace=fcntl64 fdatasync -a14 file_handle -e trace=name_to_handle_at,open_by_handle_at file_ioctl +ioctl.test @@ -147,7 +149,9 @@ getgroups -a17 getgroups32 -a19 getpeername -a27 getpgrp -a10 +getpgrp--pidns-translation test_pidns -e trace=getpgrp -a10 getpid -a9 +getpid--pidns-translation test_pidns -e trace=getpid -a9 getppid -a10 getrandom -a32 -s3 getresgid -a25 @@ -157,6 +161,7 @@ getresuid32 -a27 getrlimit -a27 getrusage -v getsid -a10 +getsid--pidns-translation test_pidns -e trace=getsid -a10 getsockname -a27 gettid -a9 getuid-creds +getuid.test @@ -250,6 +255,7 @@ ioctl_watchdog +ioctl.test ioperm -a27 iopl -a8 ioprio -a18 -e trace=ioprio_get,ioprio_set +ioprio--pidns-translation test_pidns -a18 -e trace=ioprio_get,ioprio_set ioprio-Xabbrev -a18 -e trace=ioprio_get,ioprio_set -Xabbrev ioprio-Xraw -a18 -e trace=ioprio_get,ioprio_set -Xraw ioprio-Xverbose -a18 -e trace=ioprio_get,ioprio_set -Xverbose @@ -272,6 +278,7 @@ ipc_shm-Xraw +ipc.sh -Xraw -a19 ipc_shm-Xverbose +ipc.sh -Xverbose -a34 kcmp -a22 kcmp-y -a22 -y -e trace=kcmp +kcmp-y--pidns-translation test_pidns -a22 -y -e trace=kcmp kern_features -a16 kernel_version -a16 -v -e trace=bpf kernel_version-Xabbrev -a16 -Xabbrev -v -e trace=bpf @@ -284,6 +291,7 @@ keyctl-Xabbrev -a31 -s10 -e trace=keyctl -Xabbrev keyctl-Xraw -a13 -s10 -e trace=keyctl -Xraw keyctl-Xverbose -a41 -s10 -e trace=keyctl -Xverbose kill -a12 -esignal=none +kill--pidns-translation test_pidns -a12 -e trace=kill -esignal=none ksysent ../$NAME lchown -a30 lchown32 -a32 @@ -305,6 +313,7 @@ memfd_create-Xabbrev -Xabbrev -e trace=memfd_create memfd_create-Xraw -a30 -Xraw -e trace=memfd_create memfd_create-Xverbose -Xverbose -e trace=memfd_create migrate_pages -a33 +migrate_pages--pidns-translation test_pidns -a33 -e trace=migrate_pages mincore -a22 mkdir -a20 mkdirat -a28 @@ -335,6 +344,7 @@ move_pages -s3 move_pages-Xabbrev -s3 -e trace=move_pages -Xabbrev move_pages-Xraw -s3 -a36 -e trace=move_pages -Xraw move_pages-Xverbose -s3 -e trace=move_pages -Xverbose +move_pages--pidns-translation test_pidns -s3 -e trace=move_pages mq -a32 -e trace=mq_getsetattr,mq_open,mq_unlink mq_sendrecv -a14 -e trace=mq_open,mq_notify,mq_timedsend,mq_timedreceive,mq_unlink mq_sendrecv-read -eread=0 -a14 -e trace=mq_open,mq_notify,mq_timedsend,mq_timedreceive,mq_unlink @@ -354,6 +364,7 @@ net-packet_mreq-Xabbrev -e trace=setsockopt -Xabbrev net-packet_mreq-Xraw -e trace=setsockopt -Xraw net-packet_mreq-Xverbose -e trace=setsockopt -Xverbose net-sockaddr -a24 -e trace=connect +net-sockaddr--pidns-translation test_pidns -a24 -e trace=connect net-tpacket_req -e trace=setsockopt net-tpacket_stats -e trace=getsockopt net-yy-inet6 +net-yy-inet.test @@ -457,7 +468,9 @@ pidfd_open--decode-fd-socket -a17 -e decode-fd=socket -e trace=pidfd_open pidfd_open-P -a17 -P /dev/full -e trace=pidfd_open pidfd_open-y -a17 -y -e trace=pidfd_open pidfd_open-yy -a17 -yy -e trace=pidfd_open +pidfd_open--pidns-translation test_pidns -a17 -e trace=pidfd_open pidfd_send_signal +pidfd_send_signal--pidns-translation test_pidns -e trace=pidfd_send_signal pipe2 -a15 pkey_alloc -a17 pkey_free -a13 @@ -480,8 +493,11 @@ printstrn-umoven -s4096 -e signal=none -e trace=add_key printstrn-umoven-peekdata -e signal=none -e trace=add_key printstrn-umoven-undumpable -e signal=none -e trace=add_key prlimit64 +prlimit64--pidns-translation test_pidns -e trace=prlimit64 process_vm_readv -s5 -a37 +process_vm_readv--pidns-translation test_pidns -s5 -a37 -e trace=process_vm_readv process_vm_writev -s5 -a38 +process_vm_writev--pidns-translation test_pidns -s5 -a38 -e trace=process_vm_writev pselect6 ptrace -a23 -e signal=none ptrace_syscall_info -a35 -e signal=none -e trace=ptrace @@ -518,10 +534,12 @@ rmdir -a22 rt_sigpending -a20 rt_sigprocmask rt_sigqueueinfo -esignal=none +rt_sigqueueinfo--pidns-translation test_pidns -esignal=none -e trace=rt_sigqueueinfo rt_sigreturn -esignal='!USR1' rt_sigsuspend -a20 -esignal=none rt_sigtimedwait -a38 rt_tgsigqueueinfo -esignal=none +rt_tgsigqueueinfo--pidns-translation test_pidns -esignal=none -e trace=rt_tgsigqueueinfo s390_guarded_storage -a32 s390_guarded_storage-v -e trace=s390_guarded_storage -a32 -v s390_pci_mmio_read_write -e trace=s390_pci_mmio_read,s390_pci_mmio_write -a30 @@ -532,9 +550,13 @@ sched test_trace_expr times -e/sched sched_get_priority_mxx -a33 -e trace=sched_get_priority_min,sched_get_priority_max sched_rr_get_interval -a31 sched_xetaffinity -a28 -e trace=sched_getaffinity,sched_setaffinity +sched_xetaffinity--pidns-translation test_pidns -a28 -e trace=sched_getaffinity,sched_setaffinity sched_xetattr -a29 -e trace=sched_getattr,sched_setattr +sched_xetattr--pidns-translation test_pidns -a29 -e trace=sched_getattr,sched_setattr sched_xetparam -a23 -e trace=sched_getparam,sched_setparam +sched_xetparam--pidns-translation test_pidns -a23 -e trace=sched_getparam,sched_setparam sched_xetscheduler -a22 -e trace=sched_getscheduler,sched_setscheduler +sched_xetscheduler--pidns-translation test_pidns -a22 -e trace=sched_getscheduler,sched_setscheduler sched_yield -a14 seccomp-filter -e trace=seccomp seccomp-filter-v -v -e trace=seccomp @@ -581,6 +603,7 @@ sigaction -a31 siginfo -e trace=none signal -a25 -e signal=none -e trace='/^signal$' signal_receive -a16 -e trace=kill +signal_receive--pidns-translation test_pidns -a16 -e trace=kill signalfd4 sigpending -a15 sigprocmask -a34 @@ -592,6 +615,7 @@ so_peercred -e trace=getsockopt so_peercred-Xabbrev -e trace=getsockopt -Xabbrev so_peercred-Xraw -e trace=getsockopt -Xraw -a39 so_peercred-Xverbose -e trace=getsockopt -Xverbose +so_peercred--pidns-translation test_pidns -e trace=getsockopt sock_filter-v -v -e trace=getsockopt,setsockopt sock_filter-v-Xabbrev -v -e trace=getsockopt,setsockopt -X abbrev sock_filter-v-Xraw -a 37 -v -e trace=getsockopt,setsockopt -X raw @@ -721,7 +745,10 @@ waitpid -a28 xattr -a22 -e trace=getxattr,fgetxattr,lgetxattr,setxattr,fsetxattr,lsetxattr,listxattr,flistxattr,llistxattr,removexattr,fremovexattr,lremovexattr xattr-strings -a22 -s 4 -e trace=fsetxattr xet_robust_list -a24 -e trace=get_robust_list,set_robust_list +xet_robust_list--pidns-translation test_pidns -a24 -e trace=get_robust_list,set_robust_list xetitimer -a29 -e trace=setitimer,getitimer xetpgid -a11 -e trace=getpgid,setpgid -xetpriority -a29 -e trace=getpriority,setpriority +xetpgid--pidns-translation test_pidns -a11 -e trace=getpgid,setpgid +xetpriority -a27 -e trace=getpriority,setpriority +xetpriority--pidns-translation test_pidns -a27 -e trace=getpriority,setpriority xettimeofday -a20 -e trace=gettimeofday,settimeofday diff --git a/tests/getpgrp--pidns-translation.c b/tests/getpgrp--pidns-translation.c new file mode 100644 index 00000000..de8ceb33 --- /dev/null +++ b/tests/getpgrp--pidns-translation.c @@ -0,0 +1,2 @@ +#define PIDNS_TRANSLATION +#include "getpgrp.c" diff --git a/tests/getpgrp.c b/tests/getpgrp.c index 104f4811..3f0b9dd1 100644 --- a/tests/getpgrp.c +++ b/tests/getpgrp.c @@ -7,6 +7,7 @@ #include "tests.h" #include "scno.h" +#include "pidns.h" #ifdef __NR_getpgrp @@ -16,8 +17,13 @@ int main(void) { - printf("getpgrp() = %ld\n", syscall(__NR_getpgrp)); + PIDNS_TEST_INIT; + pidns_print_leader(); + printf("getpgrp() = %d%s\n", (int) syscall(__NR_getpgrp), + pidns_pid2str(PT_PGID)); + + pidns_print_leader(); puts("+++ exited with 0 +++"); return 0; } diff --git a/tests/getpid--pidns-translation.c b/tests/getpid--pidns-translation.c new file mode 100644 index 00000000..94b12a1a --- /dev/null +++ b/tests/getpid--pidns-translation.c @@ -0,0 +1,2 @@ +#define PIDNS_TRANSLATION +#include "getpid.c" diff --git a/tests/getpid.c b/tests/getpid.c index 988f19d5..7ec4e6e8 100644 --- a/tests/getpid.c +++ b/tests/getpid.c @@ -7,6 +7,7 @@ #include "tests.h" #include "scno.h" +#include "pidns.h" #if defined __NR_getpid && (!defined __NR_getxpid || __NR_getxpid != __NR_getpid) @@ -16,7 +17,12 @@ int main(void) { - printf("getpid() = %ld\n", syscall(__NR_getpid)); + PIDNS_TEST_INIT; + + pidns_print_leader(); + printf("getpid() = %d%s\n", (int) syscall(__NR_getpid), + pidns_pid2str(PT_TGID)); + pidns_print_leader(); puts("+++ exited with 0 +++"); return 0; } diff --git a/tests/getsid--pidns-translation.c b/tests/getsid--pidns-translation.c new file mode 100644 index 00000000..7f983e87 --- /dev/null +++ b/tests/getsid--pidns-translation.c @@ -0,0 +1,2 @@ +#define PIDNS_TRANSLATION +#include "getsid.c" diff --git a/tests/getsid.c b/tests/getsid.c index 588ea4ab..3bf74734 100644 --- a/tests/getsid.c +++ b/tests/getsid.c @@ -6,15 +6,22 @@ */ #include "tests.h" +#include "pidns.h" + #include #include int main(void) { + PIDNS_TEST_INIT; + pid_t pid = getpid(); - printf("getsid(%d) = %d\n", pid, getsid(pid)); + pidns_print_leader(); + printf("getsid(%d%s) = %d%s\n", pid, pidns_pid2str(PT_TGID), + getsid(pid), pidns_pid2str(PT_SID)); + pidns_print_leader(); puts("+++ exited with 0 +++"); return 0; } diff --git a/tests/gettid--pidns-translation.c b/tests/gettid--pidns-translation.c new file mode 100644 index 00000000..500c3213 --- /dev/null +++ b/tests/gettid--pidns-translation.c @@ -0,0 +1,2 @@ +#define PIDNS_TRANSLATION +#include "gettid.c" diff --git a/tests/gettid--pidns-translation.test b/tests/gettid--pidns-translation.test new file mode 100755 index 00000000..0c7736fa --- /dev/null +++ b/tests/gettid--pidns-translation.test @@ -0,0 +1,20 @@ +#!/bin/sh +# +# Check pidns translation of gettid's return value. +# +# Copyright (c) 2020 The strace developers. +# All rights reserved. +# +# SPDX-License-Identifier: LGPL-2.1-or-later + +. "${srcdir=.}/init.sh" + +require_min_kernel_version_or_skip 4.9 + +run_prog > /dev/null +run_strace -a9 --pidns-translation -f -e trace=gettid $args > "$EXP" +parent_pid="$(tail -n 2 $LOG | head -n 1 | cut -d' ' -f1)" +init_pid="$(tail -n 1 $LOG | cut -d' ' -f1)" +# uniq: filter out extra gettid calls made by musl libc +grep -E -v "^($parent_pid|$init_pid) " "$LOG" | uniq > "$OUT" +match_diff "$OUT" "$EXP" diff --git a/tests/gettid.c b/tests/gettid.c index d38918dd..314d9c2c 100644 --- a/tests/gettid.c +++ b/tests/gettid.c @@ -9,11 +9,17 @@ #include #include #include "scno.h" +#include "pidns.h" int main(void) { - printf("gettid() = %ld\n", syscall(__NR_gettid)); + PIDNS_TEST_INIT; + + pidns_print_leader(); + printf("gettid() = %d%s\n", (int) syscall(__NR_gettid), + pidns_pid2str(PT_TID)); + pidns_print_leader(); puts("+++ exited with 0 +++"); return 0; } diff --git a/tests/ioctl_block--pidns-translation.c b/tests/ioctl_block--pidns-translation.c new file mode 100644 index 00000000..5eed6076 --- /dev/null +++ b/tests/ioctl_block--pidns-translation.c @@ -0,0 +1,2 @@ +#define PIDNS_TRANSLATION +#include "ioctl_block.c" diff --git a/tests/ioctl_block--pidns-translation.test b/tests/ioctl_block--pidns-translation.test new file mode 100755 index 00000000..bb45f695 --- /dev/null +++ b/tests/ioctl_block--pidns-translation.test @@ -0,0 +1,24 @@ +#!/bin/sh +# +# Check ioctl syscall decoding. +# +# Copyright (c) 2020 The strace developers. +# All rights reserved. +# +# SPDX-License-Identifier: LGPL-2.1-or-later + +. "${srcdir=.}/init.sh" + +require_min_kernel_version_or_skip 4.9 + +check_prog head +check_prog tail +check_prog cut +check_prog grep + +run_prog > /dev/null +run_strace --pidns-translation -f -a16 -e trace=ioctl $@ $args > "$EXP" +parent_pid="$(tail -n 2 $LOG | head -n 1 | cut -d' ' -f1)" +init_pid="$(tail -n 1 $LOG | cut -d' ' -f1)" +grep -E -v "^($parent_pid|$init_pid) |ioctl\([0123][,<]" "$LOG" > "$OUT" +match_diff "$OUT" "$EXP" diff --git a/tests/ioctl_block.c b/tests/ioctl_block.c index 0afe27f7..8a345f4e 100644 --- a/tests/ioctl_block.c +++ b/tests/ioctl_block.c @@ -9,7 +9,9 @@ */ #include "tests.h" +#include "pidns.h" #include +#include #include #include #include @@ -41,12 +43,15 @@ static struct xlat_data block_argless[] = { #define TEST_NULL_ARG(cmd) \ do { \ ioctl(-1, cmd, 0); \ + pidns_print_leader(); \ printf("ioctl(-1, %s, NULL) = -1 EBADF (%m)\n", #cmd); \ } while (0) int main(void) { + PIDNS_TEST_INIT; + TEST_NULL_ARG(BLKBSZGET); TEST_NULL_ARG(BLKBSZSET); TEST_NULL_ARG(BLKFRAGET); @@ -91,18 +96,22 @@ main(void) #endif ioctl(-1, BLKRASET, lmagic); + pidns_print_leader(); printf("ioctl(-1, BLKRASET, %lu) = -1 EBADF (%m)\n", lmagic); ioctl(-1, BLKFRASET, lmagic); + pidns_print_leader(); printf("ioctl(-1, BLKFRASET, %lu) = -1 EBADF (%m)\n", lmagic); TAIL_ALLOC_OBJECT_CONST_PTR(int, val_int); *val_int = magic; ioctl(-1, BLKROSET, val_int); + pidns_print_leader(); printf("ioctl(-1, BLKROSET, [%d]) = -1 EBADF (%m)\n", *val_int); ioctl(-1, BLKBSZSET, val_int); + pidns_print_leader(); printf("ioctl(-1, BLKBSZSET, [%d]) = -1 EBADF (%m)\n", *val_int); uint64_t *pair_int64 = tail_alloc(sizeof(*pair_int64) * 2); @@ -111,18 +120,21 @@ main(void) #ifdef BLKDISCARD ioctl(-1, BLKDISCARD, pair_int64); + pidns_print_leader(); printf("ioctl(-1, BLKDISCARD, [%" PRIu64 ", %" PRIu64 "])" " = -1 EBADF (%m)\n", pair_int64[0], pair_int64[1]); #endif #ifdef BLKSECDISCARD ioctl(-1, BLKSECDISCARD, pair_int64); + pidns_print_leader(); printf("ioctl(-1, BLKSECDISCARD, [%" PRIu64 ", %" PRIu64 "])" " = -1 EBADF (%m)\n", pair_int64[0], pair_int64[1]); #endif #ifdef BLKZEROOUT ioctl(-1, BLKZEROOUT, pair_int64); + pidns_print_leader(); printf("ioctl(-1, BLKZEROOUT, [%" PRIu64 ", %" PRIu64 "])" " = -1 EBADF (%m)\n", pair_int64[0], pair_int64[1]); #endif @@ -134,6 +146,7 @@ main(void) blkpg->data = (void *) (unsigned long) 0xcafef00dfffffeedULL; ioctl(-1, BLKPG, blkpg); + pidns_print_leader(); printf("ioctl(-1, BLKPG, {op=%s, flags=%d, datalen=%d" ", data=%#lx}) = -1 EBADF (%m)\n", "BLKPG_RESIZE_PARTITION", blkpg->flags, blkpg->datalen, @@ -149,6 +162,7 @@ main(void) blkpg->data = bp; ioctl(-1, BLKPG, blkpg); + pidns_print_leader(); printf("ioctl(-1, BLKPG, {op=%s, flags=%d, datalen=%d" ", data={start=%lld, length=%lld, pno=%d" ", devname=\"%.*s\"..., volname=\"%.*s\"...}})" @@ -162,25 +176,31 @@ main(void) #if defined BLKTRACESETUP && defined HAVE_STRUCT_BLK_USER_TRACE_SETUP TAIL_ALLOC_OBJECT_CONST_PTR(struct blk_user_trace_setup, buts); fill_memory(buts, sizeof(*buts)); + buts->pid = getpid(); ioctl(-1, BLKTRACESETUP, buts); + pidns_print_leader(); printf("ioctl(-1, BLKTRACESETUP, {act_mask=%hu, buf_size=%u, buf_nr=%u" - ", start_lba=%" PRI__u64 ", end_lba=%" PRI__u64 ", pid=%d})" + ", start_lba=%" PRI__u64 ", end_lba=%" PRI__u64 ", pid=%d%s})" " = -1 EBADF (%m)\n", buts->act_mask, buts->buf_size, buts->buf_nr, - buts->start_lba, buts->end_lba, buts->pid); + buts->start_lba, buts->end_lba, buts->pid, + pidns_pid2str(PT_TGID)); #endif unsigned int i; for (i = 0; i < ARRAY_SIZE(block_argless); ++i) { ioctl(-1, (unsigned long) block_argless[i].val, lmagic); + pidns_print_leader(); printf("ioctl(-1, %s) = -1 EBADF (%m)\n", block_argless[i].str); } ioctl(-1, _IOC(_IOC_READ, 0x12, 0xfe, 0xff), lmagic); + pidns_print_leader(); printf("ioctl(-1, %s, %#lx) = -1 EBADF (%m)\n", "_IOC(_IOC_READ, 0x12, 0xfe, 0xff)", lmagic); + pidns_print_leader(); puts("+++ exited with 0 +++"); return 0; } diff --git a/tests/ioprio--pidns-translation.c b/tests/ioprio--pidns-translation.c new file mode 100644 index 00000000..bcb49a8b --- /dev/null +++ b/tests/ioprio--pidns-translation.c @@ -0,0 +1,2 @@ +#define PIDNS_TRANSLATION +#include "ioprio.c" diff --git a/tests/ioprio.c b/tests/ioprio.c index 5e1e1194..110df063 100644 --- a/tests/ioprio.c +++ b/tests/ioprio.c @@ -9,8 +9,8 @@ */ #include "tests.h" - #include "scno.h" +#include "pidns.h" #if defined(__NR_ioprio_get) && defined(__NR_ioprio_set) @@ -30,12 +30,18 @@ enum { int main(void) { + PIDNS_TEST_INIT; + static const kernel_ulong_t bogus_which = (kernel_ulong_t) 0xdeadfacefa57beefULL; static const kernel_ulong_t bogus_who = (kernel_ulong_t) 0xbadc0dedda7a1057ULL; static const kernel_ulong_t bogus_ioprio = (kernel_ulong_t) 0xdec0ded1facefeedULL; + + const int pid = getpid(); + const int pgid = getpgid(0); + # if !XLAT_RAW static const char * const bogus_ioprio_str = "IOPRIO_PRIO_VALUE(0x7d677 /* IOPRIO_CLASS_??? */, 7917)"; @@ -46,6 +52,7 @@ main(void) rc = syscall(__NR_ioprio_get, bogus_which, bogus_who); errstr = sprintrc(rc); + pidns_print_leader(); # if XLAT_RAW printf("ioprio_get(%#x, %d) = %s\n", (int) bogus_which, (int) bogus_who, errstr); @@ -54,42 +61,52 @@ main(void) (int) bogus_which, (int) bogus_who, errstr); # endif - rc = syscall(__NR_ioprio_get, 1, 0); + rc = syscall(__NR_ioprio_get, 1, pid); errstr = sprintrc(rc); + pidns_print_leader(); + printf("ioprio_get("); # if XLAT_RAW - printf("ioprio_get(0x1, 0) = %s\n", errstr); + printf("0x1, "); +# elif XLAT_VERBOSE + printf("0x1 /* IOPRIO_WHO_PROCESS */, "); # else /* XLAT_ABBREV */ -# if XLAT_VERBOSE - printf("ioprio_get(0x1 /* IOPRIO_WHO_PROCESS */, 0) = %s", errstr); -# else - printf("ioprio_get(IOPRIO_WHO_PROCESS, 0) = %s", errstr); -# endif + printf("IOPRIO_WHO_PROCESS, "); +# endif + printf("%d%s) = %s", pid, pidns_pid2str(PT_TGID), errstr); +# if !XLAT_RAW if (rc >= 0) { printf(" (IOPRIO_PRIO_VALUE("); printxval(ioprio_class, (unsigned int) rc >> 13, "IOPRIO_CLASS_???"); printf(", %u))", (unsigned int) rc & 0x1fff); } - puts(""); # endif + puts(""); - rc = syscall(__NR_ioprio_set, 2, 0, 8191); + rc = syscall(__NR_ioprio_set, 2, pgid, 8191); errstr = sprintrc(rc); + pidns_print_leader(); + printf("ioprio_set("); # if XLAT_RAW - printf("ioprio_set(%#x, 0, 8191) = %s\n", 2, errstr); + printf("%#x", 2); # elif XLAT_VERBOSE - printf("ioprio_set(%#x /* IOPRIO_WHO_PGRP */, 0, 8191" - " /* IOPRIO_PRIO_VALUE(0 /* IOPRIO_CLASS_NONE */, 8191) */)" - " = %s\n", - 2, errstr); + printf("%#x /* IOPRIO_WHO_PGRP */", 2); # else /* XLAT_ABBREV */ - printf("ioprio_set(IOPRIO_WHO_PGRP, 0" - ", IOPRIO_PRIO_VALUE(IOPRIO_CLASS_NONE, 8191)) = %s\n", - errstr); + printf("IOPRIO_WHO_PGRP"); +# endif + printf(", %d%s", pgid, pidns_pid2str(PT_PGID)); +# if XLAT_RAW + printf(", 8191)"); +# elif XLAT_VERBOSE + printf(", 8191 /* IOPRIO_PRIO_VALUE(0 /* IOPRIO_CLASS_NONE */, 8191) */)"); +# else /* XLAT_ABBREV */ + printf(", IOPRIO_PRIO_VALUE(IOPRIO_CLASS_NONE, 8191))"); # endif + printf(" = %s\n", errstr); rc = syscall(__NR_ioprio_set, bogus_which, bogus_who, bogus_ioprio); errstr = sprintrc(rc); + pidns_print_leader(); # if XLAT_RAW printf("ioprio_set(%#x, %d, %d) = %s\n", (int) bogus_which, (int) bogus_who, (int) bogus_ioprio, @@ -104,6 +121,7 @@ main(void) errstr); # endif + pidns_print_leader(); puts("+++ exited with 0 +++"); return 0; diff --git a/tests/kcmp-y--pidns-translation.c b/tests/kcmp-y--pidns-translation.c new file mode 100644 index 00000000..f54d94cc --- /dev/null +++ b/tests/kcmp-y--pidns-translation.c @@ -0,0 +1,2 @@ +#define PIDNS_TRANSLATION +#include "kcmp-y.c" diff --git a/tests/kcmp.c b/tests/kcmp.c index dc5ba9a4..ce705ad0 100644 --- a/tests/kcmp.c +++ b/tests/kcmp.c @@ -9,8 +9,8 @@ */ #include "tests.h" - #include "scno.h" +#include "pidns.h" #ifdef __NR_kcmp @@ -101,7 +101,11 @@ do_kcmp(kernel_ulong_t pid1, kernel_ulong_t pid2, kernel_ulong_t type, rc = syscall(__NR_kcmp, pid1, pid2, type, idx1, idx2); errstr = sprintrc(rc); - printf("kcmp(%d, %d, ", (int) pid1, (int) pid2); + const char *pid_str = pidns_pid2str(PT_TGID); + pidns_print_leader(); + printf("kcmp(%d%s, %d%s, ", + (int) pid1, (int) pid1 == getpid() ? pid_str : "", + (int) pid2, (int) pid2 == getpid() ? pid_str : ""); if (type_str) printf("%s", type_str); @@ -146,6 +150,8 @@ do_kcmp(kernel_ulong_t pid1, kernel_ulong_t pid2, kernel_ulong_t type, int main(void) { + PIDNS_TEST_INIT; + static const kernel_ulong_t bogus_pid1 = (kernel_ulong_t) 0xdeadca75face1057ULL; static const kernel_ulong_t bogus_pid2 = @@ -221,6 +227,7 @@ main(void) (uintptr_t) slot, 1); } + pidns_print_leader(); puts("+++ exited with 0 +++"); return 0; diff --git a/tests/kill--pidns-translation.c b/tests/kill--pidns-translation.c new file mode 100644 index 00000000..4736ca14 --- /dev/null +++ b/tests/kill--pidns-translation.c @@ -0,0 +1,2 @@ +#define PIDNS_TRANSLATION +#include "kill.c" diff --git a/tests/kill.c b/tests/kill.c index f7d9341e..17de35da 100644 --- a/tests/kill.c +++ b/tests/kill.c @@ -11,6 +11,7 @@ #include "tests.h" #include "scno.h" +#include "pidns.h" #ifdef __NR_kill @@ -26,6 +27,8 @@ handler(int sig) int main(void) { + PIDNS_TEST_INIT; + const struct sigaction act = { .sa_handler = handler }; if (sigaction(SIGALRM, &act, NULL)) perror_msg_and_fail("sigaction"); @@ -37,18 +40,23 @@ main(void) perror_msg_and_fail("sigprocmask"); const int pid = getpid(); + const char *pid_str = pidns_pid2str(PT_TGID); long rc = syscall(__NR_kill, pid, (long) 0xdefaced00000000ULL | SIGALRM); - printf("kill(%d, SIGALRM) = %ld\n", pid, rc); + pidns_print_leader(); + printf("kill(%d%s, SIGALRM) = %ld\n", pid, pid_str, rc); const long big_pid = (long) 0xfacefeedbadc0dedULL; const long big_sig = (long) 0xdeadbeefcafef00dULL; rc = syscall(__NR_kill, big_pid, big_sig); + pidns_print_leader(); printf("kill(%d, %d) = %ld %s (%m)\n", (int) big_pid, (int) big_sig, rc, errno2name()); rc = syscall(__NR_kill, (long) 0xdefaced00000000ULL | pid, 0); - printf("kill(%d, 0) = %ld\n", pid, rc); + pidns_print_leader(); + printf("kill(%d%s, 0) = %ld\n", pid, pid_str, rc); + pidns_print_leader(); puts("+++ exited with 0 +++"); return 0; } diff --git a/tests/migrate_pages--pidns-translation.c b/tests/migrate_pages--pidns-translation.c new file mode 100644 index 00000000..ec34938d --- /dev/null +++ b/tests/migrate_pages--pidns-translation.c @@ -0,0 +1,2 @@ +#define PIDNS_TRANSLATION +#include "migrate_pages.c" diff --git a/tests/migrate_pages.c b/tests/migrate_pages.c index 2dfba49c..390b490b 100644 --- a/tests/migrate_pages.c +++ b/tests/migrate_pages.c @@ -10,6 +10,7 @@ #include "tests.h" #include "scno.h" +#include "pidns.h" #ifdef __NR_migrate_pages @@ -19,11 +20,21 @@ int main(void) { - const long pid = (long) 0xfacefeedffffffffULL; + PIDNS_TEST_INIT; + + const long pid = (long) 0xfacefeed00000000ULL | getpid(); long rc = syscall(__NR_migrate_pages, pid, 0, 0, 0); - printf("migrate_pages(%d, 0, NULL, NULL) = %ld %s (%m)\n", - (int) pid, rc, errno2name()); + pidns_print_leader(); + printf("migrate_pages(%d%s, 0, NULL, NULL) = %ld", + (int) pid, pidns_pid2str(PT_TGID), rc); + + if (rc < 0) + printf(" %s (%m)\n", errno2name()); + else + printf("\n"); + + pidns_print_leader(); puts("+++ exited with 0 +++"); return 0; } diff --git a/tests/move_pages--pidns-translation.c b/tests/move_pages--pidns-translation.c new file mode 100644 index 00000000..8498e399 --- /dev/null +++ b/tests/move_pages--pidns-translation.c @@ -0,0 +1,2 @@ +#define PIDNS_TRANSLATION +#include "move_pages.c" diff --git a/tests/move_pages.c b/tests/move_pages.c index e00fd1ac..56843158 100644 --- a/tests/move_pages.c +++ b/tests/move_pages.c @@ -10,6 +10,7 @@ #include "tests.h" #include "scno.h" +#include "pidns.h" #ifdef __NR_move_pages @@ -122,15 +123,20 @@ print_status_array(const int *const status, const unsigned long count) } static void -print_stat_pages(const unsigned long pid, const unsigned long count, - const void **const pages, int *const status) +print_stat_pages(const unsigned long pid, + const char *pid_str, + const unsigned long count, + const void **const pages, + int *const status) { const unsigned long flags = (unsigned long) 0xfacefeed00000002ULL; long rc = syscall(__NR_move_pages, pid, count, pages, NULL, status, flags); const char *errstr = sprintrc(rc); - printf("move_pages(%d, %lu, ", (int) pid, count); + pidns_print_leader(); + printf("move_pages(%d%s, %lu, ", (int) pid, pid_str, + count); print_page_array(pages, count, 0); printf(", NULL, "); if (rc) { @@ -152,6 +158,7 @@ print_stat_pages(const unsigned long pid, const unsigned long count, static void print_move_pages(const unsigned long pid, + const char *pid_str, unsigned long count, const unsigned int offset, const void **const pages, @@ -164,7 +171,9 @@ print_move_pages(const unsigned long pid, long rc = syscall(__NR_move_pages, pid, count, pages, nodes, status, flags); const char *errstr = sprintrc(rc); - printf("move_pages(%d, %lu, ", (int) pid, count); + pidns_print_leader(); + printf("move_pages(%d%s, %lu, ", (int) pid, pid_str, + count); print_page_array(pages, count, offset); printf(", "); print_node_array(nodes, count, offset); @@ -185,8 +194,11 @@ print_move_pages(const unsigned long pid, int main(void) { + PIDNS_TEST_INIT; + const unsigned long pid = (unsigned long) 0xfacefeed00000000ULL | getpid(); + const char *pid_str = pidns_pid2str(PT_TGID); unsigned long count = 1; const unsigned page_size = get_page_size(); const void *const page = tail_alloc(page_size); @@ -195,40 +207,41 @@ main(void) TAIL_ALLOC_OBJECT_VAR_PTR(int, nodes); TAIL_ALLOC_OBJECT_VAR_PTR(int, status); - print_stat_pages(pid, 0, pages, status); - print_move_pages(pid, 0, 0, pages, nodes, status); - print_move_pages(pid, 0, 1, pages + 1, nodes + 1, status + 1); + print_stat_pages(pid, pid_str, 0, pages, status); + print_move_pages(pid, pid_str, 0, 0, pages, nodes, status); + print_move_pages(pid, pid_str, 0, 1, pages + 1, nodes + 1, status + 1); *pages = page; - print_stat_pages(pid, count, pages, status); + print_stat_pages(pid, pid_str, count, pages, status); *nodes = 0xdeadbee1; - print_move_pages(pid, count, 0, pages, nodes, status); - print_move_pages(pid, count, 1, pages, nodes, status); + print_move_pages(pid, pid_str, count, 0, pages, nodes, status); + print_move_pages(pid, pid_str, count, 1, pages, nodes, status); ++count; --status; *(--pages) = efault; - print_stat_pages(pid, count, pages, status); + print_stat_pages(pid, pid_str, count, pages, status); *(--nodes) = 0xdeadbee2; - print_move_pages(pid, count, 0, pages, nodes, status); - print_move_pages(pid, count, 1, pages, nodes, status); + print_move_pages(pid, pid_str, count, 0, pages, nodes, status); + print_move_pages(pid, pid_str, count, 1, pages, nodes, status); ++count; --status; *(--pages) = nodes; - print_stat_pages(pid, count, pages, status); + print_stat_pages(pid, pid_str, count, pages, status); *(--nodes) = 0xdeadbee3; - print_move_pages(pid, count, 0, pages, nodes, status); - print_move_pages(pid, count, 1, pages, nodes, status); + print_move_pages(pid, pid_str, count, 0, pages, nodes, status); + print_move_pages(pid, pid_str, count, 1, pages, nodes, status); ++count; --status; *(--pages) = status; - print_stat_pages(pid, count, pages, status); + print_stat_pages(pid, pid_str, count, pages, status); *(--nodes) = 0xdeadbee4; - print_move_pages(pid, count, 0, pages, nodes, status); - print_move_pages(pid, count, 1, pages, nodes, status); + print_move_pages(pid, pid_str, count, 0, pages, nodes, status); + print_move_pages(pid, pid_str, count, 1, pages, nodes, status); + pidns_print_leader(); puts("+++ exited with 0 +++"); return 0; } diff --git a/tests/net-sockaddr--pidns-translation.c b/tests/net-sockaddr--pidns-translation.c new file mode 100644 index 00000000..ff432bf4 --- /dev/null +++ b/tests/net-sockaddr--pidns-translation.c @@ -0,0 +1,2 @@ +#define PIDNS_TRANSLATION +#include "net-sockaddr.c" diff --git a/tests/net-sockaddr.c b/tests/net-sockaddr.c index 4fc9da6e..b9cd46fd 100644 --- a/tests/net-sockaddr.c +++ b/tests/net-sockaddr.c @@ -9,6 +9,7 @@ */ #include "tests.h" +#include "pidns.h" #include #include #include @@ -40,18 +41,21 @@ check_un(void) memset(un->sun_path, '0', sizeof(un->sun_path)); unsigned int len = sizeof(*un); int ret = connect(-1, (void *) un, len); + pidns_print_leader(); printf("connect(-1, {sa_family=AF_UNIX, sun_path=\"%.*u\"}" ", %u) = %d EBADF (%m)\n", (int) sizeof(un->sun_path), 0, len, ret); un->sun_path[1] = 0; ret = connect(-1, (void *) un, len); + pidns_print_leader(); printf("connect(-1, {sa_family=AF_UNIX, sun_path=\"%u\"}, %u)" " = %d EBADF (%m)\n", 0, len, ret); un->sun_path[0] = 0; un->sun_path[2] = 1; ret = connect(-1, (void *) un, len); + pidns_print_leader(); printf("connect(-1, {sa_family=AF_UNIX, sun_path=@\"\\0\\001%.*u\"}" ", %u) = %d EBADF (%m)\n", (int) sizeof(un->sun_path) - 3, 0, len, ret); @@ -61,12 +65,14 @@ check_un(void) memset(un->sun_path, '0', sizeof(un->sun_path)); len = sizeof(*un) + 2; ret = connect(-1, (void *) un, len); + pidns_print_leader(); printf("connect(-1, {sa_family=AF_UNIX, sun_path=\"%.*u\"}" ", %u) = %d EBADF (%m)\n", (int) sizeof(un->sun_path), 0, len, ret); un->sun_path[0] = 0; ret = connect(-1, (void *) un, len); + pidns_print_leader(); printf("connect(-1, {sa_family=AF_UNIX, sun_path=@\"%.*u\"}" ", %u) = %d EBADF (%m)\n", (int) sizeof(un->sun_path) - 1, 0, len, ret); @@ -75,18 +81,21 @@ check_un(void) un->sun_family = AF_UNIX; len = sizeof(*un) - 2; ret = connect(-1, (void *) un, len); + pidns_print_leader(); printf("connect(-1, {sa_family=AF_UNIX, sun_path=\"%.*u\"}" ", %u) = %d EBADF (%m)\n", (int) sizeof(un->sun_path) - 2, 0, len, ret); un->sun_path[0] = 0; ret = connect(-1, (void *) un, len); + pidns_print_leader(); printf("connect(-1, {sa_family=AF_UNIX, sun_path=@\"%.*u\"}" ", %u) = %d EBADF (%m)\n", (int) sizeof(un->sun_path) - 3, 0, len, ret); len = sizeof(*un); ret = connect(-1, (void *) un, len); + pidns_print_leader(); printf("connect(-1, %p, %u) = %d EBADF (%m)\n", un, len, ret); un = tail_alloc(sizeof(struct sockaddr_storage)); @@ -94,12 +103,14 @@ check_un(void) memset(un->sun_path, '0', sizeof(un->sun_path)); len = sizeof(struct sockaddr_storage) + 1; ret = connect(-1, (void *) un, len); + pidns_print_leader(); printf("connect(-1, {sa_family=AF_UNIX, sun_path=\"%.*u\"}" ", %u) = %d EBADF (%m)\n", (int) sizeof(un->sun_path), 0, len, ret); un->sun_path[0] = 0; ret = connect(-1, (void *) un, len); + pidns_print_leader(); printf("connect(-1, {sa_family=AF_UNIX, sun_path=@\"%.*u\"}" ", %u) = %d EBADF (%m)\n", (int) sizeof(un->sun_path) - 1, 0, len, ret); @@ -117,6 +128,7 @@ check_in(void) in->sin_addr.s_addr = inet_addr(h_addr); unsigned int len = sizeof(*in); int ret = connect(-1, (void *) in, len); + pidns_print_leader(); printf("connect(-1, {sa_family=AF_INET, sin_port=htons(%hu)" ", sin_addr=inet_addr(\"%s\")}, %u) = %d EBADF (%m)\n", h_port, h_addr, len, ret); @@ -127,6 +139,7 @@ check_in(void) in->sin_addr.s_addr = inet_addr(h_addr); len = sizeof(*in) + 4; ret = connect(-1, (void *) in, len); + pidns_print_leader(); printf("connect(-1, {sa_family=AF_INET, sin_port=htons(%hu)" ", sin_addr=inet_addr(\"%s\")}, %u) = %d EBADF (%m)\n", h_port, h_addr, len, ret); @@ -137,6 +150,7 @@ check_in(void) in->sin_addr.s_addr = 0; len = sizeof(*in) - 4; ret = connect(-1, (void *) in, len); + pidns_print_leader(); printf("connect(-1, {sa_family=AF_INET, sa_data=\"%s\"}, %u)" " = %d EBADF (%m)\n", "\\0\\0\\0\\0\\0\\0\\377\\377\\377\\377", @@ -144,6 +158,7 @@ check_in(void) len = sizeof(*in); ret = connect(-1, (void *) in, len); + pidns_print_leader(); printf("connect(-1, %p, %u) = %d EBADF (%m)\n", in, len, ret); } @@ -155,6 +170,7 @@ check_in6_linklocal(struct sockaddr_in6 *const in6, const char *const h_addr) in6->sin6_scope_id = 0xfacefeed; unsigned int len = sizeof(*in6); int ret = connect(-1, (void *) in6, len); + pidns_print_leader(); printf("connect(-1, {sa_family=AF_INET6, sin6_port=htons(%hu)" ", sin6_flowinfo=htonl(%u)" ", inet_pton(AF_INET6, \"%s\", &sin6_addr)" @@ -166,7 +182,8 @@ check_in6_linklocal(struct sockaddr_in6 *const in6, const char *const h_addr) in6->sin6_scope_id = ifindex_lo(); if (in6->sin6_scope_id) { ret = connect(-1, (void *) in6, len); - printf("connect(-1, {sa_family=AF_INET6, sin6_port=htons(%hu)" + pidns_print_leader(); + printf("connect(-1, {sa_family=AF_INET6, sin6_port=htons(%hu)" ", sin6_flowinfo=htonl(%u)" ", inet_pton(AF_INET6, \"%s\", &sin6_addr)" ", sin6_scope_id=%s}, %u)" @@ -191,6 +208,7 @@ check_in6(void) in6->sin6_scope_id = 0xfacefeed; unsigned int len = sizeof(*in6); int ret = connect(-1, (void *) in6, len); + pidns_print_leader(); printf("connect(-1, {sa_family=AF_INET6, sin6_port=htons(%hu)" ", sin6_flowinfo=htonl(%u)" ", inet_pton(AF_INET6, \"%s\", &sin6_addr)" @@ -209,6 +227,7 @@ check_in6(void) in6->sin6_scope_id = 0xfacefeed; len = sizeof(*in6) + 4; ret = connect(-1, (void *) in6, len); + pidns_print_leader(); printf("connect(-1, {sa_family=AF_INET6, sin6_port=htons(%hu)" ", sin6_flowinfo=htonl(%u)" ", inet_pton(AF_INET6, \"%s\", &sin6_addr)" @@ -223,6 +242,7 @@ check_in6(void) inet_pton(AF_INET6, h_addr, &in6->sin6_addr); len = sizeof(*in6) - sizeof(in6->sin6_scope_id); ret = connect(-1, (void *) in6, len); + pidns_print_leader(); printf("connect(-1, {sa_family=AF_INET6, sin6_port=htons(%hu)" ", sin6_flowinfo=htonl(%u)" ", inet_pton(AF_INET6, \"%s\", &sin6_addr)}, %u)" @@ -236,6 +256,7 @@ check_in6(void) memset(&in6->sin6_addr, '0', sizeof(in6->sin6_addr) - 4); len = sizeof(*in6) - sizeof(in6->sin6_scope_id) - 4; ret = connect(-1, (void *) in6, len); + pidns_print_leader(); printf("connect(-1, {sa_family=AF_INET6" ", sa_data=\"\\0\\0\\0\\0\\0\\000%.*u\"}, %u)" " = %d EBADF (%m)\n", @@ -244,6 +265,7 @@ check_in6(void) len = sizeof(*in6) - sizeof(in6->sin6_scope_id); ret = connect(-1, (void *) in6, len); + pidns_print_leader(); printf("connect(-1, %p, %u) = %d EBADF (%m)\n", in6, len, ret); } @@ -262,6 +284,7 @@ check_ipx(void) void *ipx = tail_memdup(&c_ipx, sizeof(c_ipx)); unsigned int len = sizeof(c_ipx); int ret = connect(-1, ipx, len); + pidns_print_leader(); printf("connect(-1, {sa_family=AF_IPX, sipx_port=htons(%u)" ", sipx_network=htonl(%#x)" ", sipx_node=[%#02x, %#02x, %#02x, %#02x, %#02x, %#02x]" @@ -316,18 +339,21 @@ check_ax25(void) fill_memory(sax, size); sax->fsa_ax25.sax25_family = AF_AX25; rc = connect(-1, sax_void, sizeof(struct sockaddr_ax25) - 1); + pidns_print_leader(); printf("connect(-1, {sa_family=AF_AX25, sa_data=\"\\202\\203\\204\\205" "\\206\\207\\210\\211\\212\\213\\214\\215\\216\"}, %zu) = %s\n", sizeof(struct sockaddr_ax25) - 1, sprintrc(rc)); memcpy(sax, &ax25, sizeof(ax25)); rc = connect(-1, sax_void, sizeof(struct sockaddr_ax25)); + pidns_print_leader(); printf("connect(-1, {sa_family=AF_AX25, fsa_ax25={sax25_call=VALID-13" ", sax25_ndigis=8}, fsa_digipeater=[/* ??? */]}, %zu) = %s\n", sizeof(struct sockaddr_ax25), sprintrc(rc)); sax->fsa_ax25.sax25_ndigis = 0; rc = connect(-1, sax_void, sizeof(struct sockaddr_ax25)); + pidns_print_leader(); printf("connect(-1, {sa_family=AF_AX25, sax25_call=VALID-13" ", sax25_ndigis=0}, %zu) = %s\n", sizeof(struct sockaddr_ax25), sprintrc(rc)); @@ -335,6 +361,7 @@ check_ax25(void) sax->fsa_ax25.sax25_ndigis = 8; size = sizeof(struct sockaddr_ax25) + sizeof(ax25_address) * 3 + 1; rc = connect(-1, sax_void, size); + pidns_print_leader(); printf("connect(-1, {sa_family=AF_AX25, fsa_ax25={sax25_call=VALID-13" ", sax25_ndigis=8}, fsa_digipeater" "=[{ax25_call=\"\\xa6\\xa0\\x82\\x40\\x86\\x8a\\x00\"" @@ -348,6 +375,7 @@ check_ax25(void) sax->fsa_digipeater[2].ax25_call[6] = 0x4; size = sizeof(struct sockaddr_ax25) + sizeof(ax25_address) * 4; rc = connect(-1, sax_void, size); + pidns_print_leader(); printf("connect(-1, {sa_family=AF_AX25, fsa_ax25={sax25_call=VALID-13" ", sax25_ndigis=8}, fsa_digipeater" "=[{ax25_call=\"\\xa6\\xa0\\x82\\x40\\x86\\x8a\\x00\"" @@ -365,7 +393,8 @@ check_ax25(void) for (size_t i = 0; i < 3; i++) { size = sizeof(ax25) + sizeof(ax25_address) * (i / 2); rc = connect(-1, sax_void, size); - printf("connect(-1, {sa_family=AF_AX25" + pidns_print_leader(); + printf("connect(-1, {sa_family=AF_AX25" ", fsa_ax25={sax25_call=VALID-13, sax25_ndigis=%d}" ", fsa_digipeater=[VALID2-7, OK-15, %s /* FINE-2 */" ", {ax25_call=\"\\xe6\\xda\\xc2\\xd8\\xd8\\xe6\\x12\"" @@ -427,13 +456,15 @@ check_x25(void) long rc; rc = connect(-1, x25_void, sizeof(c_x25) - 1); + pidns_print_leader(); printf("connect(-1, {sa_family=AF_X25" ", sa_data=\"0123456789abcde\"}, %zu) = %s\n", sizeof(c_x25) - 1, sprintrc(rc)); for (size_t i = 0; i < 2; i++) { rc = connect(-1, x25_void, sizeof(c_x25) + i); - printf("connect(-1, {sa_family=AF_X25" + pidns_print_leader(); + printf("connect(-1, {sa_family=AF_X25" ", sx25_addr={x25_addr=\"0123456789abcde\"...}" "}, %zu) = %s\n", sizeof(c_x25) + i, sprintrc(rc)); @@ -442,6 +473,7 @@ check_x25(void) struct sockaddr_x25 *const x25 = x25_void; x25->sx25_addr.x25_addr[10] = '\0'; rc = connect(-1, x25_void, sizeof(c_x25)); + pidns_print_leader(); printf("connect(-1, {sa_family=AF_X25" ", sx25_addr={x25_addr=\"0123456789\"}" "}, %zu) = %s\n", @@ -457,19 +489,21 @@ check_nl(void) nl->nl_groups = 0xfacefeed; unsigned int len = sizeof(*nl); int ret = connect(-1, (void *) nl, len); + pidns_print_leader(); printf("connect(-1, {sa_family=AF_NETLINK, nl_pid=%d" ", nl_groups=%#08x}, %u) = %d EBADF (%m)\n", nl->nl_pid, nl->nl_groups, len, ret); nl = ((void *) nl) - 4; nl->nl_family = AF_NETLINK; - nl->nl_pid = 1234567890; + nl->nl_pid = getpid(); nl->nl_groups = 0xfacefeed; len = sizeof(*nl) + 4; ret = connect(-1, (void *) nl, len); - printf("connect(-1, {sa_family=AF_NETLINK, nl_pid=%d" + pidns_print_leader(); + printf("connect(-1, {sa_family=AF_NETLINK, nl_pid=%d%s" ", nl_groups=%#08x}, %u) = %d EBADF (%m)\n", - nl->nl_pid, nl->nl_groups, len, ret); + nl->nl_pid, pidns_pid2str(PT_TGID), nl->nl_groups, len, ret); } static void @@ -487,6 +521,7 @@ check_ll(void) void *ll = tail_memdup(&c_ll, sizeof(c_ll)); unsigned int len = sizeof(c_ll); int ret = connect(-1, ll, len); + pidns_print_leader(); printf("connect(-1, {sa_family=AF_PACKET" ", sll_protocol=htons(ETH_P_ALL)" ", sll_ifindex=%u, sll_hatype=ARPHRD_ETHER" @@ -502,6 +537,7 @@ check_ll(void) ((struct sockaddr_ll *) ll)->sll_halen++; ret = connect(-1, ll, len); + pidns_print_leader(); printf("connect(-1, {sa_family=AF_PACKET" ", sll_protocol=htons(ETH_P_ALL)" ", sll_ifindex=%u, sll_hatype=ARPHRD_ETHER" @@ -517,6 +553,7 @@ check_ll(void) ((struct sockaddr_ll *) ll)->sll_halen = 0; ret = connect(-1, ll, len); + pidns_print_leader(); printf("connect(-1, {sa_family=AF_PACKET" ", sll_protocol=htons(ETH_P_ALL)" ", sll_ifindex=%u, sll_hatype=ARPHRD_ETHER" @@ -526,7 +563,8 @@ check_ll(void) ((struct sockaddr_ll *) ll)->sll_ifindex = ifindex_lo(); if (((struct sockaddr_ll *) ll)->sll_ifindex) { ret = connect(-1, ll, len); - printf("connect(-1, {sa_family=AF_PACKET" + pidns_print_leader(); + printf("connect(-1, {sa_family=AF_PACKET" ", sll_protocol=htons(ETH_P_ALL)" ", sll_ifindex=%s" ", sll_hatype=ARPHRD_ETHER" @@ -549,11 +587,13 @@ check_hci(void) unsigned int len = sizeof(*hci); int ret = connect(-1, (void *) hci, 4); + pidns_print_leader(); printf("connect(-1, {sa_family=AF_BLUETOOTH, hci_dev=htobs(%hu)" "}, 4) = %d EBADF (%m)\n", h_port, ret); ret = connect(-1, (void *) hci, len); + pidns_print_leader(); printf("connect(-1, {sa_family=AF_BLUETOOTH, hci_dev=htobs(%hu)" # ifdef HAVE_STRUCT_SOCKADDR_HCI_HCI_CHANNEL ", hci_channel=HCI_CHANNEL_RAW" @@ -572,6 +612,7 @@ check_sco(void) void *sco = tail_memdup(&c_sco, sizeof(c_sco)); unsigned int len = sizeof(c_sco); int ret = connect(-1, sco, len); + pidns_print_leader(); printf("connect(-1, {sa_family=AF_BLUETOOTH" ", sco_bdaddr=%02x:%02x:%02x:%02x:%02x:%02x" "}, %u) = %d EBADF (%m)\n", @@ -592,6 +633,7 @@ check_rc(void) void *rc = tail_memdup(&c_rc, sizeof(c_rc)); unsigned int len = sizeof(c_rc); int ret = connect(-1, rc, len); + pidns_print_leader(); printf("connect(-1, {sa_family=AF_BLUETOOTH" ", rc_bdaddr=%02x:%02x:%02x:%02x:%02x:%02x" ", rc_channel=%u}, %u) = %d EBADF (%m)\n", @@ -619,6 +661,7 @@ check_l2(void) unsigned int len = sizeof(c_l2); int ret = connect(-1, l2, len); + pidns_print_leader(); printf("connect(-1, {sa_family=AF_BLUETOOTH" ", l2_psm=htobs(L2CAP_PSM_DYN_START + %hu)" ", l2_bdaddr=%02x:%02x:%02x:%02x:%02x:%02x" @@ -640,6 +683,7 @@ check_l2(void) # endif memcpy(l2, &c_l2, sizeof(c_l2)); ret = connect(-1, l2, len); + pidns_print_leader(); printf("connect(-1, {sa_family=AF_BLUETOOTH" ", l2_psm=htobs(L2CAP_PSM_SDP)" ", l2_bdaddr=%02x:%02x:%02x:%02x:%02x:%02x" @@ -660,6 +704,7 @@ check_l2(void) # endif memcpy(l2, &c_l2, sizeof(c_l2)); ret = connect(-1, l2, len); + pidns_print_leader(); printf("connect(-1, {sa_family=AF_BLUETOOTH" ", l2_psm=htobs(0xbad /* L2CAP_PSM_??? */)" ", l2_bdaddr=%02x:%02x:%02x:%02x:%02x:%02x" @@ -677,6 +722,7 @@ check_l2(void) c_l2.l2_cid = htobs(0xffff); memcpy(l2, &c_l2, 12); ret = connect(-1, l2, 12); + pidns_print_leader(); printf("connect(-1, {sa_family=AF_BLUETOOTH" ", l2_psm=htobs(L2CAP_PSM_AUTO_END)" ", l2_bdaddr=%02x:%02x:%02x:%02x:%02x:%02x" @@ -700,6 +746,7 @@ check_raw(void) u.sa->sa_family = 0xff; unsigned int len = sizeof(*u.st) + 8; int ret = connect(-1, (void *) u.st, len); + pidns_print_leader(); printf("connect(-1, {sa_family=%#x /* AF_??? */, sa_data=\"%.*u\"}" ", %u) = %d EBADF (%m)\n", u.sa->sa_family, (int) (sizeof(*u.st) - sizeof(u.sa->sa_family)), 0, len, ret); @@ -707,11 +754,13 @@ check_raw(void) u.sa->sa_family = 0; len = sizeof(u.sa->sa_family) + 1; ret = connect(-1, (void *) u.st, len); + pidns_print_leader(); printf("connect(-1, {sa_family=AF_UNSPEC, sa_data=\"0\"}, %u)" " = %d EBADF (%m)\n", len, ret); u.sa->sa_family = AF_BLUETOOTH; ret = connect(-1, (void *) u.st, len); + pidns_print_leader(); printf("connect(-1, {sa_family=AF_BLUETOOTH, sa_data=\"0\"}, %u)" " = %d EBADF (%m)\n", len, ret); } @@ -719,6 +768,8 @@ check_raw(void) int main(void) { + PIDNS_TEST_INIT; + check_un(); check_in(); check_in6(); @@ -735,6 +786,7 @@ main(void) #endif check_raw(); + pidns_print_leader(); puts("+++ exited with 0 +++"); return 0; } diff --git a/tests/netlink_audit--pidns-translation.c b/tests/netlink_audit--pidns-translation.c new file mode 100644 index 00000000..e08f9168 --- /dev/null +++ b/tests/netlink_audit--pidns-translation.c @@ -0,0 +1,2 @@ +#define PIDNS_TRANSLATION +#include "netlink_audit.c" diff --git a/tests/netlink_audit--pidns-translation.test b/tests/netlink_audit--pidns-translation.test new file mode 100755 index 00000000..fbc32435 --- /dev/null +++ b/tests/netlink_audit--pidns-translation.test @@ -0,0 +1,13 @@ +#!/bin/sh +# +# Check decoding of NETLINK_SOCK_DIAG protocol +# +# Copyright (c) 2020 The strace developers. +# All rights reserved. +# +# SPDX-License-Identifier: LGPL-2.1-or-later + +. "${srcdir=.}/init.sh" + +run_prog ../netlink_netlink_diag +test_pidns -e trace=sendto "$@" diff --git a/tests/netlink_audit.c b/tests/netlink_audit.c index eba609a1..5dfcd786 100644 --- a/tests/netlink_audit.c +++ b/tests/netlink_audit.c @@ -7,6 +7,7 @@ */ #include "tests.h" +#include "pidns.h" #include #include #include @@ -17,18 +18,23 @@ static void test_nlmsg_type(const int fd) { + PIDNS_TEST_INIT; + long rc; struct nlmsghdr nlh = { .nlmsg_len = sizeof(nlh), .nlmsg_type = AUDIT_GET, .nlmsg_flags = NLM_F_REQUEST, + .nlmsg_pid = getpid(), }; rc = sendto(fd, &nlh, sizeof(nlh), MSG_DONTWAIT, NULL, 0); + pidns_print_leader(); printf("sendto(%d, {len=%u, type=AUDIT_GET" - ", flags=NLM_F_REQUEST, seq=0, pid=0}" + ", flags=NLM_F_REQUEST, seq=0, pid=%d%s}" ", %u, MSG_DONTWAIT, NULL, 0) = %s\n", - fd, nlh.nlmsg_len, (unsigned) sizeof(nlh), sprintrc(rc)); + fd, nlh.nlmsg_len, nlh.nlmsg_pid, pidns_pid2str(PT_TGID), + (unsigned) sizeof(nlh), sprintrc(rc)); } int main(void) @@ -39,6 +45,7 @@ int main(void) test_nlmsg_type(fd); + pidns_print_leader(); printf("+++ exited with 0 +++\n"); return 0; diff --git a/tests/pidfd_open--pidns-translation.c b/tests/pidfd_open--pidns-translation.c new file mode 100644 index 00000000..c38e37a8 --- /dev/null +++ b/tests/pidfd_open--pidns-translation.c @@ -0,0 +1,2 @@ +#define PIDNS_TRANSLATION +#include "pidfd_open.c" diff --git a/tests/pidfd_open.c b/tests/pidfd_open.c index 5860adde..e5d74a91 100644 --- a/tests/pidfd_open.c +++ b/tests/pidfd_open.c @@ -10,6 +10,7 @@ #include "tests.h" #include "scno.h" +#include "pidns.h" #ifdef __NR_pidfd_open @@ -37,6 +38,8 @@ k_pidfd_open(const unsigned int pid, const unsigned int flags) int main(void) { + PIDNS_TEST_INIT; + # if defined PATH_TRACING || defined PRINT_PATHS skip_if_unavailable("/proc/self/fd/"); # endif @@ -50,16 +53,19 @@ main(void) k_pidfd_open(0, 0); # ifndef PATH_TRACING + pidns_print_leader(); printf("pidfd_open(0, 0) = %s\n", errstr); # endif k_pidfd_open(-1U, 0); # ifndef PATH_TRACING + pidns_print_leader(); printf("pidfd_open(-1, 0) = %s\n", errstr); # endif k_pidfd_open(0, -1U); # ifndef PATH_TRACING + pidns_print_leader(); printf("pidfd_open(0, %#x) = %s\n", -1U, errstr); # endif @@ -68,7 +74,10 @@ main(void) k_pidfd_open(pid, flags); # ifndef PATH_TRACING - printf("pidfd_open(%d, %#x) = %s\n", pid, flags, errstr); + const char *pid_str = pidns_pid2str(PT_TGID); + pidns_print_leader(); + printf("pidfd_open(%d%s, %#x) = %s\n", + pid, pid_str, flags, errstr); # endif # ifdef PRINT_PATHS @@ -80,17 +89,19 @@ main(void) # endif # ifndef PATH_TRACING - printf("pidfd_open(%d, 0) = " + pidns_print_leader(); + printf("pidfd_open(%d%s, 0) = " # if defined PRINT_PIDFD - "%ld\n", pid, rc, pid + "%ld\n", pid, pid_str, rc, pid # elif defined PRINT_PATHS - "%ld\n", pid, rc + "%ld\n", pid, pid_str, rc # else - "%s\n", pid, errstr + "%s\n", pid, pid_str, errstr # endif ); # endif + pidns_print_leader(); puts("+++ exited with 0 +++"); return 0; } diff --git a/tests/pidfd_send_signal--pidns-translation.c b/tests/pidfd_send_signal--pidns-translation.c new file mode 100644 index 00000000..b04f10f5 --- /dev/null +++ b/tests/pidfd_send_signal--pidns-translation.c @@ -0,0 +1,2 @@ +#define PIDNS_TRANSLATION +#include "pidfd_send_signal.c" diff --git a/tests/pidfd_send_signal.c b/tests/pidfd_send_signal.c index 38b5bda1..a6b2d28c 100644 --- a/tests/pidfd_send_signal.c +++ b/tests/pidfd_send_signal.c @@ -10,6 +10,7 @@ #include "tests.h" #include #include "scno.h" +#include "pidns.h" #ifdef __NR_pidfd_send_signal @@ -36,6 +37,8 @@ sys_pidfd_send_signal(int pidfd, int sig, const void *info, int flags) int main(void) { + PIDNS_TEST_INIT; + static const char null_path[] = "/dev/null"; int fd = open(null_path, O_RDONLY); @@ -46,19 +49,23 @@ main(void) const void *esi = (const void *) si + 1; sys_pidfd_send_signal(fd, SIGUSR1, esi, 0); + pidns_print_leader(); printf("pidfd_send_signal(%d, SIGUSR1, %p, 0) = %s\n", fd, esi, errstr); si->si_signo = SIGUSR1; si->si_code = SI_QUEUE; + si->si_pid = getpid(); sys_pidfd_send_signal(fd, SIGUSR2, si, -1); + pidns_print_leader(); printf("pidfd_send_signal(%d, SIGUSR2, {si_signo=SIGUSR1" - ", si_code=SI_QUEUE, si_errno=%u, si_pid=%d, si_uid=%d" + ", si_code=SI_QUEUE, si_errno=%u, si_pid=%d%s, si_uid=%d" ", si_value={int=%d, ptr=%p}}, %#x) = %s\n", - fd, si->si_errno, si->si_pid, si->si_uid, si->si_int, si->si_ptr, - -1U, errstr); + fd, si->si_errno, si->si_pid, pidns_pid2str(PT_TGID), si->si_uid, + si->si_int, si->si_ptr, -1U, errstr); + pidns_print_leader(); puts("+++ exited with 0 +++"); return 0; } diff --git a/tests/prlimit64--pidns-translation.c b/tests/prlimit64--pidns-translation.c new file mode 100644 index 00000000..3972de66 --- /dev/null +++ b/tests/prlimit64--pidns-translation.c @@ -0,0 +1,2 @@ +#define PIDNS_TRANSLATION +#include "prlimit64.c" diff --git a/tests/prlimit64.c b/tests/prlimit64.c index 34201a2b..bc1a80b3 100644 --- a/tests/prlimit64.c +++ b/tests/prlimit64.c @@ -19,6 +19,7 @@ # include # include +# include "pidns.h" # include "xlat.h" # include "xlat/resources.h" @@ -42,8 +43,11 @@ sprint_rlim(uint64_t lim) int main(void) { + PIDNS_TEST_INIT; + unsigned long pid = (unsigned long) 0xdefaced00000000ULL | (unsigned) getpid(); + const char *pid_str = pidns_pid2str(PT_TGID); uint64_t *const rlimit = tail_alloc(sizeof(*rlimit) * 2); const struct xlat_data *xlat; size_t i = 0; @@ -54,18 +58,23 @@ main(void) unsigned long res = 0xfacefeed00000000ULL | xlat->val; long rc = syscall(__NR_prlimit64, pid, res, 0, rlimit); + pidns_print_leader(); if (rc) - printf("prlimit64(%d, %s, NULL, %p) = %ld %s (%m)\n", - (unsigned) pid, xlat->str, rlimit, + printf("prlimit64(%d%s, %s, NULL, %p) =" + " %ld %s (%m)\n", + (unsigned) pid, pid_str, + xlat->str, rlimit, rc, errno2name()); else - printf("prlimit64(%d, %s, NULL" + printf("prlimit64(%d%s, %s, NULL" ", {rlim_cur=%s, rlim_max=%s}) = 0\n", - (unsigned) pid, xlat->str, + (unsigned) pid, pid_str, + xlat->str, sprint_rlim(rlimit[0]), sprint_rlim(rlimit[1])); } + pidns_print_leader(); puts("+++ exited with 0 +++"); return 0; } diff --git a/tests/process_vm_readv--pidns-translation.c b/tests/process_vm_readv--pidns-translation.c new file mode 100644 index 00000000..0db29ca2 --- /dev/null +++ b/tests/process_vm_readv--pidns-translation.c @@ -0,0 +1,2 @@ +#define PIDNS_TRANSLATION +#include "process_vm_readv.c" diff --git a/tests/process_vm_readv_writev.c b/tests/process_vm_readv_writev.c index 9309135a..44e511dd 100644 --- a/tests/process_vm_readv_writev.c +++ b/tests/process_vm_readv_writev.c @@ -12,6 +12,7 @@ #include #include #include +#include "pidns.h" #if OP_WR # define in_iovec rmt_iovec @@ -121,7 +122,7 @@ print_iov(const struct iovec *iov, const void *arg_ptr, long rc) } static void -do_call(kernel_ulong_t pid, +do_call(kernel_ulong_t pid, enum pid_type pid_type, kernel_ulong_t local_iov, const char *local_arg, kernel_ulong_t liovcnt, kernel_ulong_t remote_iov, const char *remote_arg, @@ -135,7 +136,8 @@ do_call(kernel_ulong_t pid, flags); errstr = sprintrc(rc); - printf("%s(%d, ", OP_STR, (int) pid); + pidns_print_leader(); + printf("%s(%d%s, ", OP_STR, (int) pid, pidns_pid2str(pid_type)); if (pr_iov) pr_iov((const struct iovec *) (uintptr_t) local_iov, local_arg, @@ -164,6 +166,8 @@ ptr_cast(void *ptr) int main(void) { + PIDNS_TEST_INIT; + enum { SIZE_11 = 2, SIZE_12 = 3, @@ -243,18 +247,18 @@ main(void) fill_memory_ex(data2_out, SIZE_2, SEGM2_BASE, SIZE_2); - do_call(bogus_pid, (kernel_ulong_t) (uintptr_t) ARG_STR(NULL), + do_call(bogus_pid, PT_NONE, (kernel_ulong_t) (uintptr_t) ARG_STR(NULL), bogus_iovcnt1, (kernel_ulong_t) (uintptr_t) ARG_STR(NULL), bogus_iovcnt2, bogus_flags, NULL); - do_call(my_pid, ptr_cast(bogus_iov + ARRAY_SIZE(bogus_iovec)), + do_call(my_pid, PT_TGID, ptr_cast(bogus_iov + ARRAY_SIZE(bogus_iovec)), "[]", 0, ptr_cast(in_iov + ARRAY_SIZE(in_iovec)), "[]", 0, 0, NULL); - do_call(my_pid, ptr_cast(bogus_iov + ARRAY_SIZE(bogus_iovec)), NULL, - bogus_iovcnt1, ptr_cast(in_iov + ARRAY_SIZE(in_iovec)), NULL, - bogus_iovcnt2, 0, print_iov); + do_call(my_pid, PT_TGID, ptr_cast(bogus_iov + ARRAY_SIZE(bogus_iovec)), + NULL, bogus_iovcnt1, ptr_cast(in_iov + ARRAY_SIZE(in_iovec)), + NULL, bogus_iovcnt2, 0, print_iov); - do_call(my_pid, ptr_cast(bogus_iov), (char *) &bogus_arg, + do_call(my_pid, PT_TGID, ptr_cast(bogus_iov), (char *) &bogus_arg, ARRAY_SIZE(bogus_iovec), ptr_cast(rmt_iov + 2), (char *) &rmt_arg_cut, ARRAY_SIZE(rmt_iovec) - 2, 0, print_iov); @@ -263,7 +267,7 @@ main(void) lcl_arg_cut.check_rc = 1; #endif - do_call(my_pid, ptr_cast(lcl_iov + 2), (char *) &lcl_arg_cut, + do_call(my_pid, PT_TGID, ptr_cast(lcl_iov + 2), (char *) &lcl_arg_cut, ARRAY_SIZE(lcl_iovec) - 1, ptr_cast(bogus_iov + 2), (char *) &bogus_arg_cut, ARRAY_SIZE(bogus_iovec) - 1, 0, print_iov); @@ -273,15 +277,16 @@ main(void) rmt_arg_cut.addr_term = 1; rmt_arg_cut.count = 5; - do_call(my_pid, ptr_cast(lcl_iov + 2), (char *) &lcl_arg_cut, + do_call(my_pid, PT_TGID, ptr_cast(lcl_iov + 2), (char *) &lcl_arg_cut, ARRAY_SIZE(lcl_iovec) - 2, ptr_cast(rmt_iov + 1), (char *) &rmt_arg_cut, ARRAY_SIZE(rmt_iovec), 0, print_iov); /* Correct call */ - do_call(my_pid, ptr_cast(lcl_iov), (char *) &lcl_arg, + do_call(my_pid, PT_TGID, ptr_cast(lcl_iov), (char *) &lcl_arg, ARRAY_SIZE(lcl_iovec), ptr_cast(rmt_iov), (char *) &rmt_arg, ARRAY_SIZE(rmt_iovec), 0, print_iov); + pidns_print_leader(); puts("+++ exited with 0 +++"); return 0; diff --git a/tests/process_vm_writev--pidns-translation.c b/tests/process_vm_writev--pidns-translation.c new file mode 100644 index 00000000..9ba6a39b --- /dev/null +++ b/tests/process_vm_writev--pidns-translation.c @@ -0,0 +1,2 @@ +#define PIDNS_TRANSLATION +#include "process_vm_writev.c" diff --git a/tests/rt_sigqueueinfo--pidns-translation.c b/tests/rt_sigqueueinfo--pidns-translation.c new file mode 100644 index 00000000..74bfb464 --- /dev/null +++ b/tests/rt_sigqueueinfo--pidns-translation.c @@ -0,0 +1,2 @@ +#define PIDNS_TRANSLATION +#include "rt_sigqueueinfo.c" diff --git a/tests/rt_sigqueueinfo.c b/tests/rt_sigqueueinfo.c index c1693873..e22e4640 100644 --- a/tests/rt_sigqueueinfo.c +++ b/tests/rt_sigqueueinfo.c @@ -7,6 +7,7 @@ */ #include "tests.h" +#include "pidns.h" #include #include #include @@ -15,6 +16,8 @@ int main(void) { + PIDNS_TEST_INIT; + struct sigaction sa = { .sa_handler = SIG_IGN }; @@ -22,15 +25,19 @@ main(void) .sival_ptr = (void *) (unsigned long) 0xdeadbeefbadc0dedULL }; pid_t pid = getpid(); + const char *pid_str = pidns_pid2str(PT_TGID); assert(sigaction(SIGUSR1, &sa, NULL) == 0); if (sigqueue(pid, SIGUSR1, value)) perror_msg_and_skip("sigqueue"); - printf("rt_sigqueueinfo(%u, SIGUSR1, {si_signo=SIGUSR1, " - "si_code=SI_QUEUE, si_pid=%d, si_uid=%d, " + pidns_print_leader(); + printf("rt_sigqueueinfo(%d%s, SIGUSR1, {si_signo=SIGUSR1, " + "si_code=SI_QUEUE, si_pid=%d%s, si_uid=%u, " "si_value={int=%d, ptr=%p}}) = 0\n", - pid, pid, getuid(), value.sival_int, value.sival_ptr); - printf("+++ exited with 0 +++\n"); + pid, pid_str, pid, pid_str, + getuid(), value.sival_int, value.sival_ptr); + pidns_print_leader(); + puts("+++ exited with 0 +++"); return 0; } diff --git a/tests/rt_tgsigqueueinfo--pidns-translation.c b/tests/rt_tgsigqueueinfo--pidns-translation.c new file mode 100644 index 00000000..94396f00 --- /dev/null +++ b/tests/rt_tgsigqueueinfo--pidns-translation.c @@ -0,0 +1,2 @@ +#define PIDNS_TRANSLATION +#include "rt_tgsigqueueinfo.c" diff --git a/tests/rt_tgsigqueueinfo.c b/tests/rt_tgsigqueueinfo.c index 865c21f6..21d01cbb 100644 --- a/tests/rt_tgsigqueueinfo.c +++ b/tests/rt_tgsigqueueinfo.c @@ -10,8 +10,9 @@ #include "tests.h" #include "scno.h" +#include "pidns.h" -#ifdef __NR_rt_tgsigqueueinfo +#if defined __NR_rt_tgsigqueueinfo && defined __NR_gettid # include # include @@ -20,11 +21,11 @@ # include static long -k_tgsigqueueinfo(const pid_t pid, const int sig, const void *const info) +k_tgsigqueueinfo(const pid_t tgid, const int tid, const int sig, const void *const info) { return syscall(__NR_rt_tgsigqueueinfo, - F8ILL_KULONG_MASK | pid, - F8ILL_KULONG_MASK | pid, + F8ILL_KULONG_MASK | tgid, + F8ILL_KULONG_MASK | tid, F8ILL_KULONG_MASK | sig, info); } @@ -32,6 +33,8 @@ k_tgsigqueueinfo(const pid_t pid, const int sig, const void *const info) int main(void) { + PIDNS_TEST_INIT; + const struct sigaction sa = { .sa_handler = SIG_IGN }; @@ -48,17 +51,22 @@ main(void) info->si_value.sival_ptr = (void *) (unsigned long) 0xdeadbeeffacefeedULL; - if (k_tgsigqueueinfo(info->si_pid, SIGUSR1, info)) + if (k_tgsigqueueinfo(getpid(), syscall(__NR_gettid), SIGUSR1, info)) (errno == ENOSYS ? perror_msg_and_skip : perror_msg_and_fail)( "rt_tgsigqueueinfo"); - printf("rt_tgsigqueueinfo(%u, %u, %s, {si_signo=%s" - ", si_code=SI_QUEUE, si_errno=ENOENT, si_pid=%d" + pidns_print_leader(); + printf("rt_tgsigqueueinfo(%d%s, %d%s, %s, {si_signo=%s" + ", si_code=SI_QUEUE, si_errno=ENOENT, si_pid=%d%s" ", si_uid=%d, si_value={int=%d, ptr=%p}}) = 0\n", - info->si_pid, info->si_pid, "SIGUSR1", "SIGUSR1", - info->si_pid, info->si_uid, info->si_value.sival_int, + info->si_pid, pidns_pid2str(PT_TGID), + info->si_pid, pidns_pid2str(PT_TID), + "SIGUSR1", "SIGUSR1", + info->si_pid, pidns_pid2str(PT_TGID), + info->si_uid, info->si_value.sival_int, info->si_value.sival_ptr); + pidns_print_leader(); puts("+++ exited with 0 +++"); return 0; } diff --git a/tests/sched_xetaffinity--pidns-translation.c b/tests/sched_xetaffinity--pidns-translation.c new file mode 100644 index 00000000..814e3989 --- /dev/null +++ b/tests/sched_xetaffinity--pidns-translation.c @@ -0,0 +1,2 @@ +#define PIDNS_TRANSLATION +#include "sched_xetaffinity.c" diff --git a/tests/sched_xetaffinity.c b/tests/sched_xetaffinity.c index cebff3ab..2e508ca3 100644 --- a/tests/sched_xetaffinity.c +++ b/tests/sched_xetaffinity.c @@ -10,6 +10,7 @@ #include "tests.h" #include "scno.h" +#include "pidns.h" #include #if defined __NR_sched_getaffinity && defined __NR_sched_setaffinity \ @@ -41,8 +42,11 @@ setaffinity(unsigned long pid, unsigned long size, void *set) int main(void) { + PIDNS_TEST_INIT; + unsigned int cpuset_size = 1; const pid_t pid = getpid(); + const char *pid_str = pidns_pid2str(PT_TGID); while (cpuset_size) { assert(getaffinity(pid, cpuset_size, NULL) == -1); @@ -50,18 +54,21 @@ main(void) break; if (EINVAL != errno) perror_msg_and_skip("sched_getaffinity"); - printf("sched_getaffinity(%d, %u, NULL) = %s\n", - pid, cpuset_size, errstr); + pidns_print_leader(); + printf("sched_getaffinity(%d%s, %u, NULL) = %s\n", + pid, pid_str, cpuset_size, errstr); cpuset_size <<= 1; } assert(cpuset_size); - printf("sched_getaffinity(%d, %u, NULL) = %s\n", - pid, cpuset_size, errstr); + pidns_print_leader(); + printf("sched_getaffinity(%d%s, %u, NULL) = %s\n", + pid, pid_str, cpuset_size, errstr); cpu_set_t *cpuset = tail_alloc(cpuset_size); getaffinity(pid, cpuset_size, cpuset + 1); - printf("sched_getaffinity(%d, %u, %p) = %s\n", - pid, cpuset_size, cpuset + 1, errstr); + pidns_print_leader(); + printf("sched_getaffinity(%d%s, %u, %p) = %s\n", + pid, pid_str, cpuset_size, cpuset + 1, errstr); int ret_size = getaffinity(pid, cpuset_size, cpuset); if (ret_size < 0) @@ -69,7 +76,8 @@ main(void) pid, (unsigned) cpuset_size, cpuset, errstr); assert(ret_size <= (int) cpuset_size); - printf("sched_getaffinity(%d, %u, [", pid, cpuset_size); + pidns_print_leader(); + printf("sched_getaffinity(%d%s, %u, [", pid, pid_str, cpuset_size); const char *sep; unsigned int i, cpu; for (i = 0, cpu = 0, sep = ""; i < (unsigned) ret_size * 8; ++i) { @@ -85,8 +93,9 @@ main(void) CPU_SET_S(cpu, cpuset_size, cpuset); if (setaffinity(pid, cpuset_size, cpuset)) perror_msg_and_skip("sched_setaffinity"); - printf("sched_setaffinity(%d, %u, [%u]) = 0\n", - pid, cpuset_size, cpu); + pidns_print_leader(); + printf("sched_setaffinity(%d%s, %u, [%u]) = 0\n", + pid, pid_str, cpuset_size, cpu); const unsigned int big_size = cpuset_size < 128 ? 128 : cpuset_size * 2; cpuset = tail_alloc(big_size); @@ -95,7 +104,8 @@ main(void) perror_msg_and_fail("sched_getaffinity(%d, %u, %p) = %s\n", pid, big_size, cpuset, errstr); assert(ret_size <= (int) big_size); - printf("sched_getaffinity(%d, %u, [", pid, big_size); + pidns_print_leader(); + printf("sched_getaffinity(%d%s, %u, [", pid, pid_str, big_size); for (i = 0, sep = ""; i < (unsigned) ret_size * 8; ++i) { if (CPU_ISSET_S(i, (unsigned) ret_size, cpuset)) { printf("%s%u", sep, i); @@ -104,6 +114,7 @@ main(void) } printf("]) = %s\n", errstr); + pidns_print_leader(); puts("+++ exited with 0 +++"); return 0; } diff --git a/tests/sched_xetattr--pidns-translation.c b/tests/sched_xetattr--pidns-translation.c new file mode 100644 index 00000000..c152023d --- /dev/null +++ b/tests/sched_xetattr--pidns-translation.c @@ -0,0 +1,2 @@ +#define PIDNS_TRANSLATION +#include "sched_xetattr.c" diff --git a/tests/sched_xetattr.c b/tests/sched_xetattr.c index c63d7a80..4a76b2d6 100644 --- a/tests/sched_xetattr.c +++ b/tests/sched_xetattr.c @@ -15,6 +15,7 @@ # include # include # include +# include "pidns.h" # include "sched_attr.h" # include "xlat.h" # include "xlat/schedulers.h" @@ -41,6 +42,8 @@ sys_sched_setattr(kernel_ulong_t pid, kernel_ulong_t attr, kernel_ulong_t flags) int main(void) { + PIDNS_TEST_INIT; + static const kernel_ulong_t bogus_pid = (kernel_ulong_t) 0xdefacedfacefeedULL; static const kernel_ulong_t bogus_size = @@ -48,20 +51,28 @@ main(void) static const kernel_ulong_t bogus_flags = (kernel_ulong_t) 0xdefaceddeadc0deULL; + const int pid = getpid(); + const char *pid_str = pidns_pid2str(PT_TGID); + TAIL_ALLOC_OBJECT_CONST_PTR(struct sched_attr, attr); TAIL_ALLOC_OBJECT_CONST_PTR(unsigned int, psize); void *const efault = attr + 1; - sys_sched_getattr(0, 0, 0, 0); - printf("sched_getattr(0, NULL, 0, 0) = %s\n", errstr); + sys_sched_getattr(pid, 0, 0, 0); + pidns_print_leader(); + printf("sched_getattr(%d%s, NULL, 0, 0) = %s\n", + pid, pid_str, errstr); sys_sched_getattr(0, (unsigned long) attr, 0, 0); + pidns_print_leader(); printf("sched_getattr(0, %p, 0, 0) = %s\n", attr, errstr); sys_sched_getattr(bogus_pid, 0, 0, 0); + pidns_print_leader(); printf("sched_getattr(%d, NULL, 0, 0) = %s\n", (int) bogus_pid, errstr); sys_sched_getattr(-1U, (unsigned long) attr, bogus_size, bogus_flags); + pidns_print_leader(); printf("sched_getattr(-1, %p, %s%u, %u) = %s\n", attr, # if defined __arm64__ || defined __aarch64__ @@ -72,11 +83,13 @@ main(void) (unsigned) bogus_size, (unsigned) bogus_flags, errstr); sys_sched_getattr(0, (unsigned long) efault, SCHED_ATTR_MIN_SIZE, 0); + pidns_print_leader(); printf("sched_getattr(0, %p, %u, 0) = %s\n", efault, (unsigned) SCHED_ATTR_MIN_SIZE, errstr); if (sys_sched_getattr(0, (unsigned long) attr, SCHED_ATTR_MIN_SIZE, 0)) perror_msg_and_skip("sched_getattr"); + pidns_print_leader(); printf("sched_getattr(0, {size=%u, sched_policy=", attr->size); printxval(schedulers, attr->sched_policy, NULL); printf(", sched_flags=%s, sched_nice=%d, sched_priority=%u" @@ -91,11 +104,13 @@ main(void) (unsigned) SCHED_ATTR_MIN_SIZE); sys_sched_getattr(0, (unsigned long) efault, sizeof(*attr), 0); + pidns_print_leader(); printf("sched_getattr(0, %p, %u, 0) = %s\n", efault, (unsigned) sizeof(*attr), errstr); if (sys_sched_getattr(0, (unsigned long) attr, sizeof(*attr), 0)) perror_msg_and_skip("sched_getattr"); + pidns_print_leader(); printf("sched_getattr(0, {size=%u, sched_policy=", attr->size); printxval(schedulers, attr->sched_policy, NULL); printf(", sched_flags=%s, sched_nice=%d, sched_priority=%u" @@ -121,11 +136,13 @@ main(void) F8ILL_KULONG_MASK | sizeof(*attr), F8ILL_KULONG_MASK); # if defined __arm64__ || defined __aarch64__ if (rc) { + pidns_print_leader(); printf("sched_getattr(0, %p, 0xffffffff<<32|%u, 0) = %s\n", attr, (unsigned) sizeof(*attr), errstr); } else # endif { + pidns_print_leader(); printf("sched_getattr(0, {size=%u, sched_policy=", attr->size); printxval(schedulers, attr->sched_policy, NULL); printf(", sched_flags=%s, sched_nice=%d, sched_priority=%u" @@ -146,13 +163,16 @@ main(void) } sys_sched_setattr(bogus_pid, 0, 0); + pidns_print_leader(); printf("sched_setattr(%d, NULL, 0) = %s\n", (int) bogus_pid, errstr); attr->sched_flags |= 1; - if (sys_sched_setattr(0, (unsigned long) attr, 0)) + if (sys_sched_setattr(pid, (unsigned long) attr, 0)) perror_msg_and_skip("sched_setattr"); - printf("sched_setattr(0, {size=%u, sched_policy=", attr->size); + pidns_print_leader(); + printf("sched_setattr(%d%s, {size=%u, sched_policy=", + pid, pid_str, attr->size); printxval(schedulers, attr->sched_policy, NULL); printf(", sched_flags=%s, sched_nice=%d, sched_priority=%u" ", sched_runtime=%" PRIu64 ", sched_deadline=%" PRIu64 @@ -172,6 +192,7 @@ main(void) sys_sched_setattr(F8ILL_KULONG_MASK, (unsigned long) attr, F8ILL_KULONG_MASK); + pidns_print_leader(); printf("sched_setattr(0, {size=%u, sched_policy=", attr->size); printxval(schedulers, attr->sched_policy, NULL); printf(", sched_flags=%s, sched_nice=%d, sched_priority=%u" @@ -193,11 +214,13 @@ main(void) *psize = attr->size; sys_sched_setattr(0, (unsigned long) psize, 0); + pidns_print_leader(); printf("sched_setattr(0, %p, 0) = %s\n", psize, errstr); attr->size = 0; sys_sched_setattr(0, (unsigned long) attr, 0); + pidns_print_leader(); printf("sched_setattr(0, {size=%u, sched_policy=", attr->size); printxval(schedulers, attr->sched_policy, NULL); printf(", sched_flags=%s, sched_nice=%d, sched_priority=%u" @@ -213,12 +236,14 @@ main(void) attr->size = 1; sys_sched_setattr(0, (unsigned long) attr, 0); + pidns_print_leader(); printf("sched_setattr(0, {size=%u} => {size=%u}, 0) = %s\n", 1, attr->size, errstr); attr->size = SCHED_ATTR_MIN_SIZE - 1; sys_sched_setattr(0, (unsigned long) attr, 0); + pidns_print_leader(); printf("sched_setattr(0, {size=%u} => {size=%u}, 0) = %s\n", SCHED_ATTR_MIN_SIZE - 1, attr->size, errstr); @@ -232,6 +257,7 @@ main(void) attr->sched_period = 0xded1ca7edda7aca7ULL; sys_sched_setattr(bogus_pid, (unsigned long) attr, bogus_flags); + pidns_print_leader(); printf("sched_setattr(%d, {size=%u, sched_policy=%#x /* SCHED_??? */, " "sched_flags=%#" PRIx64 " /* SCHED_FLAG_??? */, " "sched_nice=%d, sched_priority=%u, sched_runtime=%" PRIu64 ", " @@ -274,6 +300,7 @@ main(void) attr->sched_period = 0xded1ca7edda7aca7ULL; sys_sched_setattr(bogus_pid, (unsigned long) attr, bogus_flags); + pidns_print_leader(); printf("sched_setattr(%d, {size=%u, sched_policy=%#x /* SCHED_??? */, " "sched_flags=SCHED_FLAG_RESET_ON_FORK|SCHED_FLAG_RECLAIM|" "SCHED_FLAG_DL_OVERRUN|0x80, " @@ -296,11 +323,13 @@ main(void) const kernel_ulong_t ill = f8ill_ptr_to_kulong(attr); sys_sched_getattr(0, ill, sizeof(*attr), 0); + pidns_print_leader(); printf("sched_getattr(0, %#llx, %u, 0) = %s\n", (unsigned long long) ill, (unsigned) sizeof(*attr), errstr); sys_sched_setattr(0, ill, 0); + pidns_print_leader(); printf("sched_setattr(0, %#llx, 0) = %s\n", (unsigned long long) ill, errstr); } @@ -310,6 +339,7 @@ main(void) attr->sched_flags = 0x8fULL; sys_sched_setattr(bogus_pid, (unsigned long) attr, bogus_flags); + pidns_print_leader(); printf("sched_setattr(%d, {size=%u, " "sched_flags=SCHED_FLAG_RESET_ON_FORK|SCHED_FLAG_RECLAIM|" "SCHED_FLAG_DL_OVERRUN|SCHED_FLAG_KEEP_POLICY|0x80, " @@ -329,11 +359,13 @@ main(void) const kernel_ulong_t ill = f8ill_ptr_to_kulong(attr); sys_sched_getattr(0, ill, sizeof(*attr), 0); + pidns_print_leader(); printf("sched_getattr(0, %#llx, %u, 0) = %s\n", (unsigned long long) ill, (unsigned) sizeof(*attr), errstr); sys_sched_setattr(0, ill, 0); + pidns_print_leader(); printf("sched_setattr(0, %#llx, 0) = %s\n", (unsigned long long) ill, errstr); } @@ -342,6 +374,7 @@ main(void) attr->sched_flags = 0xe7ULL; sys_sched_setattr(bogus_pid, (unsigned long) attr, bogus_flags); + pidns_print_leader(); printf("sched_setattr(%d, {size=%u, sched_policy=%#x /* SCHED_??? */, " "sched_flags=SCHED_FLAG_RESET_ON_FORK|SCHED_FLAG_RECLAIM|" "SCHED_FLAG_DL_OVERRUN|SCHED_FLAG_UTIL_CLAMP_MIN" @@ -365,11 +398,13 @@ main(void) const kernel_ulong_t ill = f8ill_ptr_to_kulong(attr); sys_sched_getattr(0, ill, sizeof(*attr), 0); + pidns_print_leader(); printf("sched_getattr(0, %#llx, %u, 0) = %s\n", (unsigned long long) ill, (unsigned) sizeof(*attr), errstr); sys_sched_setattr(0, ill, 0); + pidns_print_leader(); printf("sched_setattr(0, %#llx, 0) = %s\n", (unsigned long long) ill, errstr); } @@ -377,6 +412,7 @@ main(void) attr->sched_flags = 0xcaffee90LL; sys_sched_setattr(bogus_pid, (unsigned long) attr, bogus_flags); + pidns_print_leader(); printf("sched_setattr(%d, {size=%u, sched_flags=SCHED_FLAG_KEEP_PARAMS" "|0xcaffee80, sched_util_min=%u, sched_util_max=%u}, %u) = %s\n", (int) bogus_pid, @@ -389,15 +425,18 @@ main(void) const kernel_ulong_t ill = f8ill_ptr_to_kulong(attr); sys_sched_getattr(0, ill, sizeof(*attr), 0); + pidns_print_leader(); printf("sched_getattr(0, %#llx, %u, 0) = %s\n", (unsigned long long) ill, (unsigned) sizeof(*attr), errstr); sys_sched_setattr(0, ill, 0); + pidns_print_leader(); printf("sched_setattr(0, %#llx, 0) = %s\n", (unsigned long long) ill, errstr); } + pidns_print_leader(); puts("+++ exited with 0 +++"); return 0; } diff --git a/tests/sched_xetparam--pidns-translation.c b/tests/sched_xetparam--pidns-translation.c new file mode 100644 index 00000000..9fb3e579 --- /dev/null +++ b/tests/sched_xetparam--pidns-translation.c @@ -0,0 +1,2 @@ +#define PIDNS_TRANSLATION +#include "sched_xetparam.c" diff --git a/tests/sched_xetparam.c b/tests/sched_xetparam.c index de3915b2..aa9c68cc 100644 --- a/tests/sched_xetparam.c +++ b/tests/sched_xetparam.c @@ -7,6 +7,7 @@ #include "tests.h" #include "scno.h" +# include "pidns.h" #if defined __NR_sched_getparam && defined __NR_sched_setparam @@ -17,18 +18,27 @@ int main(void) { + PIDNS_TEST_INIT; + struct sched_param *const param = tail_alloc(sizeof(struct sched_param)); - long rc = syscall(__NR_sched_getparam, 0, param); - printf("sched_getparam(0, [%d]) = %ld\n", - param->sched_priority, rc); + const int pid = getpid(); + const char *pid_str = pidns_pid2str(PT_TGID); + + long rc = syscall(__NR_sched_getparam, pid, param); + pidns_print_leader(); + printf("sched_getparam(%d%s, [%d]) = %ld\n", + pid, pid_str, param->sched_priority, rc); param->sched_priority = -1; - rc = syscall(__NR_sched_setparam, 0, param); - printf("sched_setparam(0, [%d]) = %ld %s (%m)\n", + rc = syscall(__NR_sched_setparam, pid, param); + pidns_print_leader(); + printf("sched_setparam(%d%s, [%d]) = %ld %s (%m)\n", + pid, pid_str, param->sched_priority, rc, errno2name()); + pidns_print_leader(); puts("+++ exited with 0 +++"); return 0; } diff --git a/tests/sched_xetscheduler--pidns-translation.c b/tests/sched_xetscheduler--pidns-translation.c new file mode 100644 index 00000000..78b794b2 --- /dev/null +++ b/tests/sched_xetscheduler--pidns-translation.c @@ -0,0 +1,2 @@ +#define PIDNS_TRANSLATION +#include "sched_xetscheduler.c" diff --git a/tests/sched_xetscheduler.c b/tests/sched_xetscheduler.c index 047e8676..91b5e32d 100644 --- a/tests/sched_xetscheduler.c +++ b/tests/sched_xetscheduler.c @@ -7,6 +7,7 @@ #include "tests.h" #include "scno.h" +#include "pidns.h" #if defined __NR_sched_getscheduler && defined __NR_sched_setscheduler @@ -17,8 +18,13 @@ int main(void) { + PIDNS_TEST_INIT; + TAIL_ALLOC_OBJECT_CONST_PTR(struct sched_param, param); - long rc = syscall(__NR_sched_getscheduler, 0); + const int pid = getpid(); + const char *pid_str = pidns_pid2str(PT_TGID); + + long rc = syscall(__NR_sched_getscheduler, pid); const char *scheduler; switch (rc) { case SCHED_FIFO: @@ -50,33 +56,43 @@ main(void) default: scheduler = "SCHED_OTHER"; } - printf("sched_getscheduler(0) = %ld (%s)\n", - rc, scheduler); + pidns_print_leader(); + printf("sched_getscheduler(%d%s) = %ld (%s)\n", + pid, pid_str, rc, scheduler); rc = syscall(__NR_sched_getscheduler, -1); + pidns_print_leader(); printf("sched_getscheduler(-1) = %s\n", sprintrc(rc)); param->sched_priority = -1; - rc = syscall(__NR_sched_setscheduler, 0, SCHED_FIFO, NULL); - printf("sched_setscheduler(0, SCHED_FIFO, NULL) = %s\n", sprintrc(rc)); + rc = syscall(__NR_sched_setscheduler, pid, SCHED_FIFO, NULL); + pidns_print_leader(); + printf("sched_setscheduler(%d%s, SCHED_FIFO, NULL) = %s\n", + pid, pid_str, sprintrc(rc)); - rc = syscall(__NR_sched_setscheduler, 0, SCHED_FIFO, param + 1); - printf("sched_setscheduler(0, SCHED_FIFO, %p) = %s\n", param + 1, - sprintrc(rc)); + rc = syscall(__NR_sched_setscheduler, pid, SCHED_FIFO, param + 1); + pidns_print_leader(); + printf("sched_setscheduler(%d%s, SCHED_FIFO, %p) = %s\n", + pid, pid_str, param + 1, sprintrc(rc)); - rc = syscall(__NR_sched_setscheduler, 0, 0xfaceda7a, param); - printf("sched_setscheduler(0, %#x /* SCHED_??? */, [%d]) = %s\n", - 0xfaceda7a, param->sched_priority, sprintrc(rc)); + rc = syscall(__NR_sched_setscheduler, pid, 0xfaceda7a, param); + pidns_print_leader(); + printf("sched_setscheduler(%d%s, %#x /* SCHED_??? */, [%d]) = %s\n", + pid, pid_str, 0xfaceda7a, + param->sched_priority, sprintrc(rc)); rc = syscall(__NR_sched_setscheduler, -1, SCHED_FIFO, param); + pidns_print_leader(); printf("sched_setscheduler(-1, SCHED_FIFO, [%d]) = %s\n", param->sched_priority, sprintrc(rc)); - rc = syscall(__NR_sched_setscheduler, 0, SCHED_FIFO, param); - printf("sched_setscheduler(0, SCHED_FIFO, [%d]) = %s\n", - param->sched_priority, sprintrc(rc)); + rc = syscall(__NR_sched_setscheduler, pid, SCHED_FIFO, param); + pidns_print_leader(); + printf("sched_setscheduler(%d%s, SCHED_FIFO, [%d]) = %s\n", + pid, pid_str, param->sched_priority, sprintrc(rc)); + pidns_print_leader(); puts("+++ exited with 0 +++"); return 0; } diff --git a/tests/signal_receive--pidns-translation.c b/tests/signal_receive--pidns-translation.c new file mode 100644 index 00000000..b4e3b2f8 --- /dev/null +++ b/tests/signal_receive--pidns-translation.c @@ -0,0 +1,2 @@ +#define PIDNS_TRANSLATION +#include "signal_receive.c" diff --git a/tests/signal_receive.c b/tests/signal_receive.c index ad3b4ebd..70441a9e 100644 --- a/tests/signal_receive.c +++ b/tests/signal_receive.c @@ -8,6 +8,7 @@ */ #include "tests.h" +#include "pidns.h" #include #include #include @@ -26,10 +27,13 @@ handler(int sig, siginfo_t *info, void *ucontext) int main(void) { + PIDNS_TEST_INIT; + static const char prefix[] = "KERNEL BUG"; int printed = 0; const int pid = getpid(); + const char *pid_str = pidns_pid2str(PT_TGID); const int uid = geteuid(); for (int sig = 1; sig <= 31; ++sig) { @@ -73,10 +77,13 @@ main(void) const int e_pid = s_pid; const int e_uid = s_uid; #endif - printf("kill(%d, %s) = 0\n", pid, signal2name(sig)); - printf("--- %s {si_signo=%s, si_code=SI_USER, si_pid=%d" + pidns_print_leader(); + printf("kill(%d%s, %s) = 0\n", pid, pid_str, signal2name(sig)); + pidns_print_leader(); + printf("--- %s {si_signo=%s, si_code=SI_USER, si_pid=%d%s" ", si_uid=%d} ---\n", - signal2name(sig), signal2name(e_sig), e_pid, e_uid); + signal2name(sig), signal2name(e_sig), + e_pid, pid_str, e_uid); if (s_code || sig != s_sig || pid != s_pid || uid != s_uid) { /* @@ -91,11 +98,11 @@ main(void) } fprintf(stderr, "%s: expected: si_signo=%d, si_code=%d" - ", si_pid=%d, si_uid=%d\n" + ", si_pid=%d%s, si_uid=%d\n" "%s: received: si_signo=%d, si_code=%d" - ", si_pid=%d, si_uid=%d\n", - prefix, sig, SI_USER, pid, uid, - prefix, sig, s_code, s_pid, s_uid); + ", si_pid=%d%s, si_uid=%d\n", + prefix, sig, SI_USER, pid, pid_str, uid, + prefix, sig, s_code, s_pid, pid_str, s_uid); } } @@ -104,6 +111,7 @@ main(void) "*** PLEASE FIX THE KERNEL ***\n", prefix); } + pidns_print_leader(); puts("+++ exited with 0 +++"); return 0; } diff --git a/tests/so_peercred--pidns-translation.c b/tests/so_peercred--pidns-translation.c new file mode 100644 index 00000000..402bbcfe --- /dev/null +++ b/tests/so_peercred--pidns-translation.c @@ -0,0 +1,2 @@ +#define PIDNS_TRANSLATION +#include "so_peercred.c" diff --git a/tests/so_peercred.c b/tests/so_peercred.c index 151bb175..20188bdb 100644 --- a/tests/so_peercred.c +++ b/tests/so_peercred.c @@ -9,6 +9,7 @@ */ #include "tests.h" +#include "pidns.h" #include #include @@ -53,6 +54,8 @@ so_str(void) int main(void) { + PIDNS_TEST_INIT; + TAIL_ALLOC_OBJECT_CONST_PTR(struct ucred, peercred); TAIL_ALLOC_OBJECT_CONST_PTR(socklen_t, len); @@ -75,6 +78,8 @@ main(void) struct ucred *const gid_truncated = tail_alloc(sizeof_gid_truncated); + const char *pid_str = pidns_pid2str(PT_TGID); + int sv[2]; if (socketpair(AF_UNIX, SOCK_STREAM, 0, sv)) perror_msg_and_skip("socketpair AF_UNIX SOCK_STREAM"); @@ -82,8 +87,10 @@ main(void) /* classic getsockopt */ *len = sizeof(*peercred); get_peercred(sv[0], peercred, len); + pidns_print_leader(); printf("getsockopt(%d, %s", sv[0], so_str()); PRINT_FIELD_D(", {", *peercred, pid); + printf("%s", pid_str); PRINT_FIELD_UID(", ", *peercred, uid); PRINT_FIELD_UID(", ", *peercred, gid); printf("}, [%d]) = %s\n", *len, errstr); @@ -91,14 +98,17 @@ main(void) /* getsockopt with zero optlen */ *len = 0; get_peercred(sv[0], peercred, len); + pidns_print_leader(); printf("getsockopt(%d, %s, %p, [0]) = %s\n", sv[0], so_str(), peercred, errstr); /* getsockopt with optlen larger than necessary - shortened */ *len = sizeof(*peercred) + 1; get_peercred(sv[0], peercred, len); + pidns_print_leader(); printf("getsockopt(%d, %s", sv[0], so_str()); PRINT_FIELD_D(", {", *peercred, pid); + printf("%s", pid_str); PRINT_FIELD_UID(", ", *peercred, uid); PRINT_FIELD_UID(", ", *peercred, gid); printf("}, [%u->%d]) = %s\n", @@ -110,6 +120,7 @@ main(void) */ *len = sizeof_pid_truncated; get_peercred(sv[0], pid_truncated, len); + pidns_print_leader(); printf("getsockopt(%d, %s, {pid=", sv[0], so_str()); print_quoted_hex(pid_truncated, *len); printf("}, [%d]) = %s\n", *len, errstr); @@ -120,8 +131,10 @@ main(void) */ *len = sizeof_pid; get_peercred(sv[0], pid, len); + pidns_print_leader(); printf("getsockopt(%d, %s", sv[0], so_str()); PRINT_FIELD_D(", {", *pid, pid); + printf("%s", pid_str); printf("}, [%d]) = %s\n", *len, errstr); /* @@ -136,8 +149,10 @@ main(void) * to struct ucred.pid field. */ memcpy(uid, uid_truncated, sizeof_uid_truncated); + pidns_print_leader(); printf("getsockopt(%d, %s", sv[0], so_str()); PRINT_FIELD_D(", {", *uid, pid); + printf("%s", pid_str); printf(", uid="); print_quoted_hex(&uid->uid, sizeof_uid_truncated - offsetof(struct ucred, uid)); @@ -149,8 +164,10 @@ main(void) */ *len = sizeof_uid; get_peercred(sv[0], uid, len); + pidns_print_leader(); printf("getsockopt(%d, %s", sv[0], so_str()); PRINT_FIELD_D(", {", *uid, pid); + printf("%s", pid_str); PRINT_FIELD_UID(", ", *uid, uid); printf("}, [%d]) = %s\n", *len, errstr); @@ -166,8 +183,10 @@ main(void) * to struct ucred.pid and struct ucred.uid fields. */ memcpy(peercred, gid_truncated, sizeof_gid_truncated); + pidns_print_leader(); printf("getsockopt(%d, %s", sv[0], so_str()); PRINT_FIELD_D(", {", *peercred, pid); + printf("%s", pid_str); PRINT_FIELD_UID(", ", *peercred, uid); printf(", gid="); print_quoted_hex(&peercred->gid, sizeof_gid_truncated - @@ -177,14 +196,17 @@ main(void) /* getsockopt optval EFAULT */ *len = sizeof(*peercred); get_peercred(sv[0], &peercred->uid, len); + pidns_print_leader(); printf("getsockopt(%d, %s, %p, [%d]) = %s\n", sv[0], so_str(), &peercred->uid, *len, errstr); /* getsockopt optlen EFAULT */ get_peercred(sv[0], peercred, len + 1); + pidns_print_leader(); printf("getsockopt(%d, %s, %p, %p) = %s\n", sv[0], so_str(), peercred, len + 1, errstr); + pidns_print_leader(); puts("+++ exited with 0 +++"); return 0; } diff --git a/tests/xet_robust_list--pidns-translation.c b/tests/xet_robust_list--pidns-translation.c new file mode 100644 index 00000000..e0477267 --- /dev/null +++ b/tests/xet_robust_list--pidns-translation.c @@ -0,0 +1,2 @@ +#define PIDNS_TRANSLATION +#include "xet_robust_list.c" diff --git a/tests/xet_robust_list.c b/tests/xet_robust_list.c index 43239c8b..b5751b0a 100644 --- a/tests/xet_robust_list.c +++ b/tests/xet_robust_list.c @@ -8,6 +8,7 @@ #include "tests.h" #include "scno.h" +#include "pidns.h" #if defined __NR_get_robust_list && defined __NR_set_robust_list @@ -30,27 +31,36 @@ sprintaddr(void *addr) int main(void) { + PIDNS_TEST_INIT; + const pid_t pid = getpid(); + const char *pid_str = pidns_pid2str(PT_TGID); const long long_pid = (unsigned long) (0xdeadbeef00000000LL | pid); TAIL_ALLOC_OBJECT_CONST_PTR(void *, p_head); TAIL_ALLOC_OBJECT_CONST_PTR(size_t, p_len); if (syscall(__NR_get_robust_list, long_pid, p_head, p_len)) perror_msg_and_skip("get_robust_list"); - printf("get_robust_list(%d, [%s], [%lu]) = 0\n", - (int) pid, sprintaddr(*p_head), (unsigned long) *p_len); + pidns_print_leader(); + printf("get_robust_list(%d%s, [%s], [%lu]) = 0\n", + pid, pid_str, sprintaddr(*p_head), + (unsigned long) *p_len); void *head = tail_alloc(*p_len); if (syscall(__NR_set_robust_list, head, *p_len)) perror_msg_and_skip("set_robust_list"); + pidns_print_leader(); printf("set_robust_list(%p, %lu) = 0\n", head, (unsigned long) *p_len); if (syscall(__NR_get_robust_list, long_pid, p_head, p_len)) perror_msg_and_skip("get_robust_list"); - printf("get_robust_list(%d, [%s], [%lu]) = 0\n", - (int) pid, sprintaddr(*p_head), (unsigned long) *p_len); + pidns_print_leader(); + printf("get_robust_list(%d%s, [%s], [%lu]) = 0\n", + pid, pid_str, sprintaddr(*p_head), + (unsigned long) *p_len); + pidns_print_leader(); puts("+++ exited with 0 +++"); return 0; } diff --git a/tests/xetpgid--pidns-translation.c b/tests/xetpgid--pidns-translation.c new file mode 100644 index 00000000..b6469628 --- /dev/null +++ b/tests/xetpgid--pidns-translation.c @@ -0,0 +1,2 @@ +#define PIDNS_TRANSLATION +#include "xetpgid.c" diff --git a/tests/xetpgid.c b/tests/xetpgid.c index 9b070af2..411edfc7 100644 --- a/tests/xetpgid.c +++ b/tests/xetpgid.c @@ -10,6 +10,7 @@ #include "tests.h" #include "scno.h" +#include "pidns.h" #if defined __NR_getpgid && defined __NR_setpgid @@ -19,13 +20,21 @@ int main(void) { - const int pid = getpid(); - long rc = syscall(__NR_getpgid, F8ILL_KULONG_MASK | pid); - printf("getpgid(%d) = %ld\n", pid, rc); - - rc = syscall(__NR_setpgid, F8ILL_KULONG_MASK, F8ILL_KULONG_MASK | pid); - printf("setpgid(0, %d) = %ld\n", pid, rc); + PIDNS_TEST_INIT; + const int pid = getpid(); + long pgid = syscall(__NR_getpgid, F8ILL_KULONG_MASK | pid); + pidns_print_leader(); + printf("getpgid(%d%s) = %ld%s\n", pid, pidns_pid2str(PT_TGID), + pgid, pidns_pid2str(PT_PGID)); + + long rc = syscall(__NR_setpgid, F8ILL_KULONG_MASK, + F8ILL_KULONG_MASK | pgid); + pidns_print_leader(); + printf("setpgid(0, %ld%s) = %s\n", pgid, pidns_pid2str(PT_PGID), + sprintrc(rc)); + + pidns_print_leader(); puts("+++ exited with 0 +++"); return 0; } diff --git a/tests/xetpriority--pidns-translation.c b/tests/xetpriority--pidns-translation.c new file mode 100644 index 00000000..c93669cb --- /dev/null +++ b/tests/xetpriority--pidns-translation.c @@ -0,0 +1,2 @@ +#define PIDNS_TRANSLATION +#include "xetpriority.c" diff --git a/tests/xetpriority.c b/tests/xetpriority.c index 2d61bd10..dd38217d 100644 --- a/tests/xetpriority.c +++ b/tests/xetpriority.c @@ -7,6 +7,7 @@ #include "tests.h" #include "scno.h" +#include "pidns.h" #if defined __NR_getpriority && defined __NR_setpriority @@ -17,15 +18,30 @@ int main(void) { + PIDNS_TEST_INIT; + const int pid = getpid(); + const int pgid = getpgid(0); + long rc = syscall(__NR_getpriority, PRIO_PROCESS, F8ILL_KULONG_MASK | pid); - printf("getpriority(PRIO_PROCESS, %d) = %ld\n", pid, rc); + pidns_print_leader(); + printf("getpriority(PRIO_PROCESS, %d%s) = %ld\n", + pid, pidns_pid2str(PT_TGID), rc); rc = syscall(__NR_setpriority, PRIO_PROCESS, F8ILL_KULONG_MASK | pid, F8ILL_KULONG_MASK); - printf("setpriority(PRIO_PROCESS, %d, 0) = %s\n", pid, sprintrc(rc)); + pidns_print_leader(); + printf("setpriority(PRIO_PROCESS, %d%s, 0) = %s\n", + pid, pidns_pid2str(PT_TGID), sprintrc(rc)); + + rc = syscall(__NR_getpriority, PRIO_PGRP, + F8ILL_KULONG_MASK | pgid); + pidns_print_leader(); + printf("getpriority(PRIO_PGRP, %d%s) = %ld\n", + pgid, pidns_pid2str(PT_PGID), rc); + pidns_print_leader(); puts("+++ exited with 0 +++"); return 0; } -- 2.27.0 From uzonyi.akos at gmail.com Thu Aug 13 15:32:38 2020 From: uzonyi.akos at gmail.com (=?UTF-8?q?=C3=81kos=20Uzonyi?=) Date: Thu, 13 Aug 2020 17:32:38 +0200 Subject: [RFC PATCH 0/4] [PIDNS] Trie and pidns-cache tests Message-ID: <20200813153242.94742-1-uzonyi.akos@gmail.com> From: Uzonyi ?kos In the last series, while refactoring trie I introduced a bug (tries with 64 bits key were returning 0 always), which caused pidns cache not working. The first patch in this series fixes it. Also ns_id_size was wrong, which is fixed by the second patch. The last two patches add tests, so these bugs are caught by the test suite. The first one checks whether pidns tranlsation is fast enough (executes 200 getpid calls, and expects it to complete under 1s). The second one (which is not yet complete) check whether trie_get is returning the expected value. The reason I'm sending it is to have some feedback whether you like the approach to these (little bit odd) tests. In the first one, I'm not sure if it's OK to use 200 for SYSCALL_COUNT, which is based on my system's performance. In the second one is it's OK to add ../trie.c ../trie.h to libtests_a_SOURCES? ?kos Uzonyi (4): Fix trie Fix ns_id_size Test pidns translation cache Add test for trie pidns.c | 2 +- tests/.gitignore | 2 ++ tests/Makefile.am | 5 ++++ tests/pidns-cache.c | 29 +++++++++++++++++++++ tests/pidns-cache.test | 23 +++++++++++++++++ tests/trie.c | 57 ++++++++++++++++++++++++++++++++++++++++++ tests/trie.test | 12 +++++++++ trie.c | 10 +++++--- 8 files changed, 136 insertions(+), 4 deletions(-) create mode 100644 tests/pidns-cache.c create mode 100755 tests/pidns-cache.test create mode 100644 tests/trie.c create mode 100755 tests/trie.test -- 2.28.0 From uzonyi.akos at gmail.com Thu Aug 13 15:32:39 2020 From: uzonyi.akos at gmail.com (=?UTF-8?q?=C3=81kos=20Uzonyi?=) Date: Thu, 13 Aug 2020 17:32:39 +0200 Subject: [RFC PATCH 1/4] Fix trie In-Reply-To: <20200813153242.94742-1-uzonyi.akos@gmail.com> References: <20200813153242.94742-1-uzonyi.akos@gmail.com> Message-ID: <20200813153242.94742-2-uzonyi.akos@gmail.com> --- trie.c | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/trie.c b/trie.c index b7d56ed5..b2d421cd 100644 --- a/trie.c +++ b/trie.c @@ -125,6 +125,12 @@ trie_data_block_calc_pos(struct trie *t, uint64_t key, key_mask = (1 << t->data_block_key_bits) - 1; *pos = (key & key_mask) >> (6 - t->item_size_lg); + if (t->item_size_lg == 6) { + *offs = 0; + *mask = -1; + return; + } + key_mask = (1 << (6 - t->item_size_lg)) - 1; *offs = (key & key_mask) * (1 << t->item_size_lg); -- 2.28.0 From uzonyi.akos at gmail.com Thu Aug 13 15:32:40 2020 From: uzonyi.akos at gmail.com (=?UTF-8?q?=C3=81kos=20Uzonyi?=) Date: Thu, 13 Aug 2020 17:32:40 +0200 Subject: [RFC PATCH 2/4] Fix ns_id_size In-Reply-To: <20200813153242.94742-1-uzonyi.akos@gmail.com> References: <20200813153242.94742-1-uzonyi.akos@gmail.com> Message-ID: <20200813153242.94742-3-uzonyi.akos@gmail.com> --- pidns.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pidns.c b/pidns.c index edab73f8..9d8695da 100644 --- a/pidns.c +++ b/pidns.c @@ -65,7 +65,7 @@ static const struct { */ #define MAX_NS_DEPTH 32 -static const size_t ns_id_size = sizeof(unsigned int); +static const size_t ns_id_size = sizeof(unsigned int) * 8; static const uint8_t ptr_sz_lg = (sizeof(void *) == 8 ? 6 : 5); static int pid_max; -- 2.28.0 From uzonyi.akos at gmail.com Thu Aug 13 15:32:41 2020 From: uzonyi.akos at gmail.com (=?UTF-8?q?=C3=81kos=20Uzonyi?=) Date: Thu, 13 Aug 2020 17:32:41 +0200 Subject: [RFC PATCH 3/4] Test pidns translation cache In-Reply-To: <20200813153242.94742-1-uzonyi.akos@gmail.com> References: <20200813153242.94742-1-uzonyi.akos@gmail.com> Message-ID: <20200813153242.94742-4-uzonyi.akos@gmail.com> --- tests/.gitignore | 1 + tests/Makefile.am | 2 ++ tests/pidns-cache.c | 29 +++++++++++++++++++++++++++++ tests/pidns-cache.test | 23 +++++++++++++++++++++++ 4 files changed, 55 insertions(+) create mode 100644 tests/pidns-cache.c create mode 100755 tests/pidns-cache.test diff --git a/tests/.gitignore b/tests/.gitignore index 4d1153fc..fc512ad2 100644 --- a/tests/.gitignore +++ b/tests/.gitignore @@ -525,6 +525,7 @@ pidfd_open-yy pidfd_open--pidns-translation pidfd_send_signal pidfd_send_signal--pidns-translation +pidns-performance pipe pipe2 pkey_alloc diff --git a/tests/Makefile.am b/tests/Makefile.am index f2c5da83..8aaa0cae 100644 --- a/tests/Makefile.am +++ b/tests/Makefile.am @@ -190,6 +190,7 @@ check_PROGRAMS = $(PURE_EXECUTABLES) \ perf_event_open_unabbrev \ pidfd_open--pidns-translation \ pidfd_send_signal--pidns-translation \ + pidns-cache \ poll-P \ ppoll-P \ ppoll-v \ @@ -425,6 +426,7 @@ MISC_TESTS = \ opipe.test \ options-syntax.test \ pc.test \ + pidns-cache.test \ printpath-umovestr-legacy.test \ printstrn-umoven-legacy.test \ qual_fault-syntax.test \ diff --git a/tests/pidns-cache.c b/tests/pidns-cache.c new file mode 100644 index 00000000..989f7db3 --- /dev/null +++ b/tests/pidns-cache.c @@ -0,0 +1,29 @@ +/* + * Copyright (c) 2020 The strace developers. + * All rights reserved. + * + * SPDX-License-Identifier: GPL-2.0-or-later + */ + +#include "tests.h" +#include "pidns.h" + +#include +#include + +/** + * There is a 1 sec timeout for this test. With pidns caching more than 1000 + * syscalls can be executed, without caching only a few tens. + */ +#define SYSCALL_COUNT 200 + +int +main(void) +{ + pidns_test_init(); + + for (int i = 0; i < SYSCALL_COUNT; i++) + getpid(); + + return 0; +} diff --git a/tests/pidns-cache.test b/tests/pidns-cache.test new file mode 100755 index 00000000..8c126f91 --- /dev/null +++ b/tests/pidns-cache.test @@ -0,0 +1,23 @@ +#!/bin/sh +# +# Test pidns translation cache. +# +# Copyright (c) 2020 The strace developers. +# All rights reserved. +# +# SPDX-License-Identifier: GPL-2.0-or-later + +. "${srcdir=.}/init.sh" + +require_min_kernel_version_or_skip 4.9 +check_prog timeout + +run_prog > /dev/null +timeout 1 $STRACE -o /dev/null --pidns-translation -f -e trace=getpid $args || { + rc=$? + if [ $rc -eq 124 ]; then + fail_ "pidns translation took too long" + else + fail_ "$args failed with code $rc" + fi +} -- 2.28.0 From uzonyi.akos at gmail.com Thu Aug 13 15:32:42 2020 From: uzonyi.akos at gmail.com (=?UTF-8?q?=C3=81kos=20Uzonyi?=) Date: Thu, 13 Aug 2020 17:32:42 +0200 Subject: [RFC PATCH 4/4] Add test for trie In-Reply-To: <20200813153242.94742-1-uzonyi.akos@gmail.com> References: <20200813153242.94742-1-uzonyi.akos@gmail.com> Message-ID: <20200813153242.94742-5-uzonyi.akos@gmail.com> --- tests/.gitignore | 1 + tests/Makefile.am | 3 +++ tests/trie.c | 57 +++++++++++++++++++++++++++++++++++++++++++++++ tests/trie.test | 12 ++++++++++ trie.c | 4 +--- 5 files changed, 74 insertions(+), 3 deletions(-) create mode 100644 tests/trie.c create mode 100755 tests/trie.test diff --git a/tests/.gitignore b/tests/.gitignore index fc512ad2..34268a05 100644 --- a/tests/.gitignore +++ b/tests/.gitignore @@ -772,6 +772,7 @@ times times-fail tkill tracer_ppid_pgid_sid +trie truncate truncate64 ugetrlimit diff --git a/tests/Makefile.am b/tests/Makefile.am index 8aaa0cae..d1f1a98d 100644 --- a/tests/Makefile.am +++ b/tests/Makefile.am @@ -29,6 +29,7 @@ AM_CPPFLAGS = $(ARCH_MFLAGS) \ AM_LDFLAGS = $(ARCH_MFLAGS) libtests_a_SOURCES = \ + ../trie.c ../trie.h \ create_nl_socket.c \ create_tmpfile.c \ errno2name.c \ @@ -246,6 +247,7 @@ check_PROGRAMS = $(PURE_EXECUTABLES) \ threads-execve-qq \ threads-execve-qqq \ tracer_ppid_pgid_sid \ + trie \ unblock_reset_raise \ unix-pair-send-recv \ unix-pair-sendto-recvfrom \ @@ -467,6 +469,7 @@ MISC_TESTS = \ strace-tt.test \ strace-ttt.test \ termsig.test \ + trie.test \ threads-execve.test \ umovestr_cached.test \ # end of MISC_TESTS diff --git a/tests/trie.c b/tests/trie.c new file mode 100644 index 00000000..26118c14 --- /dev/null +++ b/tests/trie.c @@ -0,0 +1,57 @@ +/* + * Copyright (c) 2017-2019 The strace developers. + * All rights reserved. + * + * SPDX-License-Identifier: GPL-2.0-or-later + */ + +#include "tests.h" +#include "trie.h" + +#include + +static void +assert_equals(const char *msg, uint64_t expected, uint64_t actual) { + if (actual != expected) + error_msg_and_fail("%s: expected: %ld, actual: %ld", msg, expected, actual); +} + +int +main(void) +{ + static const struct { + uint8_t key_size; + uint8_t item_size_lg; + uint8_t node_key_bits; + uint8_t data_block_key_bits; + uint64_t empty_value; + + struct { + uint64_t key, value, expected_value; + } key_value_pairs[3]; + } params[] = { + {64, 6, 10, 10, 0, {{2, 42, 42}, {0, 1, 1}, {2, 43, 43}}}, + }; + + for (size_t i = 0; i < ARRAY_SIZE(params); i++) { + struct trie *t = trie_create(params[i].key_size, + params[i].item_size_lg, + params[i].node_key_bits, + params[i].data_block_key_bits, + params[i].empty_value); + + for (size_t j = 0; j < ARRAY_SIZE(params[i].key_value_pairs); j++) { + uint64_t key, value, expected; + key = params[i].key_value_pairs[j].key; + value = params[i].key_value_pairs[j].value; + expected = params[i].key_value_pairs[j].expected_value; + + trie_set(t, key, value); + assert_equals("trie_get", expected, trie_get(t, key)); + } + + trie_free(t); + } + + return 0; +} diff --git a/tests/trie.test b/tests/trie.test new file mode 100755 index 00000000..f5a5bf68 --- /dev/null +++ b/tests/trie.test @@ -0,0 +1,12 @@ +#!/bin/sh +# +# Test trie. +# +# Copyright (c) 2020 The strace developers. +# All rights reserved. +# +# SPDX-License-Identifier: LGPL-2.1-or-later + +. "${srcdir=.}/init.sh" + +run_prog diff --git a/trie.c b/trie.c index b2d421cd..e55c5027 100644 --- a/trie.c +++ b/trie.c @@ -7,8 +7,6 @@ * SPDX-License-Identifier: LGPL-2.1-or-later */ -#include "defs.h" - #include #include #include @@ -103,7 +101,7 @@ trie_get_node(struct trie *t, uint64_t key, bool auto_create) if (!auto_create) return NULL; - *cur_node = xcalloc(1 << sz, 1); + *cur_node = calloc(1 << sz, 1); } if (cur_depth >= t->max_depth) -- 2.28.0 From ldv at altlinux.org Sat Aug 15 12:37:42 2020 From: ldv at altlinux.org (Dmitry V. Levin) Date: Sat, 15 Aug 2020 15:37:42 +0300 Subject: [RFC PATCH 3/4] Test pidns translation cache In-Reply-To: <20200813153242.94742-4-uzonyi.akos@gmail.com> References: <20200813153242.94742-1-uzonyi.akos@gmail.com> <20200813153242.94742-4-uzonyi.akos@gmail.com> Message-ID: <20200815123742.GA30941@altlinux.org> On Thu, Aug 13, 2020 at 05:32:41PM +0200, ?kos Uzonyi wrote: [...] > +/** > + * There is a 1 sec timeout for this test. With pidns caching more than 1000 > + * syscalls can be executed, without caching only a few tens. > + */ > +#define SYSCALL_COUNT 200 > + > +int > +main(void) > +{ > + pidns_test_init(); > + > + for (int i = 0; i < SYSCALL_COUNT; i++) > + getpid(); > + > + return 0; > +} As getpid can be easily cached by libc, this has to be a syscall(). With regards to the number of syscalls, some hosts could be very slow, so I suggest to count the number of syscalls without any pid translation and use it as a baseline. -- ldv From ldv at altlinux.org Sat Aug 15 12:41:29 2020 From: ldv at altlinux.org (Dmitry V. Levin) Date: Sat, 15 Aug 2020 15:41:29 +0300 Subject: [RFC PATCH 0/4] [PIDNS] Trie and pidns-cache tests In-Reply-To: <20200813153242.94742-1-uzonyi.akos@gmail.com> References: <20200813153242.94742-1-uzonyi.akos@gmail.com> Message-ID: <20200815124129.GB30941@altlinux.org> On Thu, Aug 13, 2020 at 05:32:38PM +0200, ?kos Uzonyi wrote: > is it's OK to add ../trie.c ../trie.h to libtests_a_SOURCES? I suppose automake should be fine with it. What's your concern? -- ldv From ldv at altlinux.org Sat Aug 15 15:18:26 2020 From: ldv at altlinux.org (Dmitry V. Levin) Date: Sat, 15 Aug 2020 18:18:26 +0300 Subject: [RFC PATCH 4/4] Add test for trie In-Reply-To: <20200813153242.94742-5-uzonyi.akos@gmail.com> References: <20200813153242.94742-1-uzonyi.akos@gmail.com> <20200813153242.94742-5-uzonyi.akos@gmail.com> Message-ID: <20200815151826.GA376@altlinux.org> On Thu, Aug 13, 2020 at 05:32:42PM +0200, ?kos Uzonyi wrote: [...] > --- a/tests/Makefile.am > +++ b/tests/Makefile.am > @@ -29,6 +29,7 @@ AM_CPPFLAGS = $(ARCH_MFLAGS) \ > AM_LDFLAGS = $(ARCH_MFLAGS) > > libtests_a_SOURCES = \ > + ../trie.c ../trie.h \ There is no need to include the header. By the way, the code linked into the test is not going to be shown in the test coverage. > --- /dev/null > +++ b/tests/trie.test > @@ -0,0 +1,12 @@ > +#!/bin/sh > +# > +# Test trie. > +# > +# Copyright (c) 2020 The strace developers. > +# All rights reserved. > +# > +# SPDX-License-Identifier: LGPL-2.1-or-later > + > +. "${srcdir=.}/init.sh" > + > +run_prog I suppose you can add something like trie . "${srcdir=.}/init.sh"; run_prog to tests/gen_tests.in with the same effect. > diff --git a/trie.c b/trie.c > index b2d421cd..e55c5027 100644 > --- a/trie.c > +++ b/trie.c > @@ -7,8 +7,6 @@ > * SPDX-License-Identifier: LGPL-2.1-or-later > */ > > -#include "defs.h" > - > #include > #include > #include This is not correct unless you prepend it with #ifdef HAVE_CONFIG_H # include "config.h" #endif Also, consider moving #include #include to trie.h > @@ -103,7 +101,7 @@ trie_get_node(struct trie *t, uint64_t key, bool auto_create) > if (!auto_create) > return NULL; > > - *cur_node = xcalloc(1 << sz, 1); > + *cur_node = calloc(1 << sz, 1); > } > > if (cur_depth >= t->max_depth) This doesn't look correct either: the return value check is lost. -- ldv From uzonyi.akos at gmail.com Sat Aug 15 16:23:26 2020 From: uzonyi.akos at gmail.com (=?UTF-8?B?w4Frb3MgVXpvbnlp?=) Date: Sat, 15 Aug 2020 18:23:26 +0200 Subject: [RFC PATCH 0/4] [PIDNS] Trie and pidns-cache tests In-Reply-To: <20200815124129.GB30941@altlinux.org> References: <20200813153242.94742-1-uzonyi.akos@gmail.com> <20200815124129.GB30941@altlinux.org> Message-ID: On Sat, 15 Aug 2020 at 14:41, Dmitry V. Levin wrote: > On Thu, Aug 13, 2020 at 05:32:38PM +0200, ?kos Uzonyi wrote: > > is it's OK to add ../trie.c ../trie.h to libtests_a_SOURCES? > > I suppose automake should be fine with it. What's your concern? Technically there is no problem, I just worried about including a file not in tests directory, as it hasn't been done before. But if you say it's OK, then everything is fine :). From ldv at altlinux.org Sat Aug 15 16:27:10 2020 From: ldv at altlinux.org (Dmitry V. Levin) Date: Sat, 15 Aug 2020 19:27:10 +0300 Subject: [RFC PATCH 0/4] [PIDNS] Trie and pidns-cache tests In-Reply-To: References: <20200813153242.94742-1-uzonyi.akos@gmail.com> <20200815124129.GB30941@altlinux.org> Message-ID: <20200815162710.GD376@altlinux.org> On Sat, Aug 15, 2020 at 06:23:26PM +0200, ?kos Uzonyi wrote: > On Sat, 15 Aug 2020 at 14:41, Dmitry V. Levin wrote: > > On Thu, Aug 13, 2020 at 05:32:38PM +0200, ?kos Uzonyi wrote: > > > is it's OK to add ../trie.c ../trie.h to libtests_a_SOURCES? > > > > I suppose automake should be fine with it. What's your concern? > > Technically there is no problem, I just worried about including a file > not in tests directory, as it hasn't been done before. But if you say > it's OK, then everything is fine :). The only problem is that it won't be built with coverage support, so it won't be shown in coverage reports. -- ldv From uzonyi.akos at gmail.com Sat Aug 15 20:21:49 2020 From: uzonyi.akos at gmail.com (=?UTF-8?B?w4Frb3MgVXpvbnlp?=) Date: Sat, 15 Aug 2020 22:21:49 +0200 Subject: [RFC PATCH 3/4] Test pidns translation cache In-Reply-To: <20200815123742.GA30941@altlinux.org> References: <20200813153242.94742-1-uzonyi.akos@gmail.com> <20200813153242.94742-4-uzonyi.akos@gmail.com> <20200815123742.GA30941@altlinux.org> Message-ID: On Sat, 15 Aug 2020 at 14:37, Dmitry V. Levin wrote: > On Thu, Aug 13, 2020 at 05:32:41PM +0200, ?kos Uzonyi wrote: > [...] > > +/** > > + * There is a 1 sec timeout for this test. With pidns caching more than 1000 > > + * syscalls can be executed, without caching only a few tens. > > + */ > > +#define SYSCALL_COUNT 200 > > + > > +int > > +main(void) > > +{ > > + pidns_test_init(); > > + > > + for (int i = 0; i < SYSCALL_COUNT; i++) > > + getpid(); > > + > > + return 0; > > +} > > As getpid can be easily cached by libc, this has to be a syscall(). > > With regards to the number of syscalls, some hosts could be very slow, so > I suggest to count the number of syscalls without any pid translation and > use it as a baseline. Good idea, thanks. From ldv at altlinux.org Sat Aug 15 20:27:26 2020 From: ldv at altlinux.org (Dmitry V. Levin) Date: Sat, 15 Aug 2020 23:27:26 +0300 Subject: [PATCH v8 4/5] Implement testing framework for pidns In-Reply-To: <20200809141306.477539-5-uzonyi.akos@gmail.com> References: <20200809141306.477539-1-uzonyi.akos@gmail.com> <20200809141306.477539-5-uzonyi.akos@gmail.com> Message-ID: <20200815202725.GA3099@altlinux.org> On Sun, Aug 09, 2020 at 04:13:05PM +0200, ?kos Uzonyi wrote: [...] > --- a/tests/init.sh > +++ b/tests/init.sh > @@ -387,6 +387,37 @@ test_prog_set() > test_pure_prog_set "$@" < "$srcdir/$NAME.in" > } > > +test_pidns_run_strace() > +{ > + local parent_pid > + > + check_prog tail > + check_prog cut > + check_prog grep > + > + run_prog > /dev/null > + run_strace --pidns-translation -f $@ $args > "$EXP" > + > + # filter out logs made by the parent or init process of the pidns test > + parent_pid="$(tail -n 2 $LOG | head -n 1 | cut -d' ' -f1)" > + init_pid="$(tail -n 1 $LOG | cut -d' ' -f1)" > + grep -E -v "^($parent_pid|$init_pid) " "$LOG" > "$OUT" > + match_diff "$OUT" "$EXP" > +} init_pid also has to be declared as local here. > + > +test_pidns() > +{ > + # ioctl(NS_GET_PARENT) is added in Linux 4.9 > + require_min_kernel_version_or_skip 4.9 Is this check still needed given that check_ns_ioctl() already performs a runtime check? [...] > + if (read(strace_ids_pipe[0], pidns_strace_ids, > + sizeof(pidns_strace_ids)) < 0) > + perror_msg_and_fail("read"); If this read call is expected to return sizeof(pidns_strace_ids), should the return value be tested against that instead? [...] > + if (write(strace_ids_pipe[1], pidns_strace_ids, > + sizeof(pidns_strace_ids)) < 0) > + perror_msg_and_fail("write"); Likewise, if this write call is expected to return sizeof(pidns_strace_ids), should the return value be tested against that instead? > +static void > +create_init_process(void) > +{ > + int child_pipe[2]; > + if (pipe(child_pipe) < 0) > + perror_msg_and_fail("pipe"); > + > + pid_t pid = fork(); > + if (pid < 0) > + perror_msg_and_fail("fork"); > + > + if (!pid) { > + close(child_pipe[1]); > + _exit(read(child_pipe[0], &child_pipe[1], sizeof(int)) == 0); > + } > + > + close(child_pipe[0]); > +} If nothing is going to be written to child_pipe[1], then this read call is expected to return 0, followed by _exit(1). The choice of exit code seems strange to me. > + > +void > +check_ns_ioctl(void) > +{ > + int fd = open("/proc/self/ns/pid", O_RDONLY); > + if (fd < 0) > + perror_msg_and_fail("opening /proc/self/ns/pid"); What if /proc/self/ns/pid is not available, e.g. /proc is not mounted or the kernel doesn't implement it? I suggest to do perror_msg_and_skip instead, at least in case of ENOENT. -- ldv From ldv at altlinux.org Sat Aug 15 20:35:25 2020 From: ldv at altlinux.org (Dmitry V. Levin) Date: Sat, 15 Aug 2020 23:35:25 +0300 Subject: [RFC PATCH 3/4] Test pidns translation cache In-Reply-To: References: <20200813153242.94742-1-uzonyi.akos@gmail.com> <20200813153242.94742-4-uzonyi.akos@gmail.com> <20200815123742.GA30941@altlinux.org> Message-ID: <20200815203525.GB3099@altlinux.org> On Sat, Aug 15, 2020 at 10:21:49PM +0200, ?kos Uzonyi wrote: > On Sat, 15 Aug 2020 at 14:37, Dmitry V. Levin wrote: > > On Thu, Aug 13, 2020 at 05:32:41PM +0200, ?kos Uzonyi wrote: > > [...] > > > +/** > > > + * There is a 1 sec timeout for this test. With pidns caching more than 1000 > > > + * syscalls can be executed, without caching only a few tens. > > > + */ > > > +#define SYSCALL_COUNT 200 > > > + > > > +int > > > +main(void) > > > +{ > > > + pidns_test_init(); > > > + > > > + for (int i = 0; i < SYSCALL_COUNT; i++) > > > + getpid(); > > > + > > > + return 0; > > > +} > > > > As getpid can be easily cached by libc, this has to be a syscall(). > > > > With regards to the number of syscalls, some hosts could be very slow, so > > I suggest to count the number of syscalls without any pid translation and > > use it as a baseline. > > Good idea, thanks. We employ a similar technique in filter_seccomp-perf.test where the test counts the number of chdir syscalls invoked in a loop for one second. -- ldv From uzonyi.akos at gmail.com Sat Aug 15 20:54:46 2020 From: uzonyi.akos at gmail.com (=?UTF-8?B?w4Frb3MgVXpvbnlp?=) Date: Sat, 15 Aug 2020 22:54:46 +0200 Subject: [RFC PATCH 3/4] Test pidns translation cache In-Reply-To: <20200815203525.GB3099@altlinux.org> References: <20200813153242.94742-1-uzonyi.akos@gmail.com> <20200813153242.94742-4-uzonyi.akos@gmail.com> <20200815123742.GA30941@altlinux.org> <20200815203525.GB3099@altlinux.org> Message-ID: On Sat, 15 Aug 2020 at 22:35, Dmitry V. Levin wrote: > On Sat, Aug 15, 2020 at 10:21:49PM +0200, ?kos Uzonyi wrote: > > On Sat, 15 Aug 2020 at 14:37, Dmitry V. Levin wrote: > > > On Thu, Aug 13, 2020 at 05:32:41PM +0200, ?kos Uzonyi wrote: > > > [...] > > > > +/** > > > > + * There is a 1 sec timeout for this test. With pidns caching more than 1000 > > > > + * syscalls can be executed, without caching only a few tens. > > > > + */ > > > > +#define SYSCALL_COUNT 200 > > > > + > > > > +int > > > > +main(void) > > > > +{ > > > > + pidns_test_init(); > > > > + > > > > + for (int i = 0; i < SYSCALL_COUNT; i++) > > > > + getpid(); > > > > + > > > > + return 0; > > > > +} > > > > > > As getpid can be easily cached by libc, this has to be a syscall(). > > > > > > With regards to the number of syscalls, some hosts could be very slow, so > > > I suggest to count the number of syscalls without any pid translation and > > > use it as a baseline. > > > > Good idea, thanks. > > We employ a similar technique in filter_seccomp-perf.test where the test > counts the number of chdir syscalls invoked in a loop for one second. Thanks for pointing that out. But I already started to implement a little bit different kind of test: the syscall count is constant, I measure the time with and without pidns translation, and the difference should be below some threshold. From ldv at altlinux.org Sat Aug 15 21:00:00 2020 From: ldv at altlinux.org (Dmitry V. Levin) Date: Sun, 16 Aug 2020 00:00:00 +0300 Subject: [RFC PATCH 3/4] Test pidns translation cache In-Reply-To: References: <20200813153242.94742-1-uzonyi.akos@gmail.com> <20200813153242.94742-4-uzonyi.akos@gmail.com> <20200815123742.GA30941@altlinux.org> <20200815203525.GB3099@altlinux.org> Message-ID: <20200815210000.GA3699@altlinux.org> On Sat, Aug 15, 2020 at 10:54:46PM +0200, ?kos Uzonyi wrote: > On Sat, 15 Aug 2020 at 22:35, Dmitry V. Levin wrote: > > On Sat, Aug 15, 2020 at 10:21:49PM +0200, ?kos Uzonyi wrote: > > > On Sat, 15 Aug 2020 at 14:37, Dmitry V. Levin wrote: > > > > On Thu, Aug 13, 2020 at 05:32:41PM +0200, ?kos Uzonyi wrote: > > > > [...] > > > > > +/** > > > > > + * There is a 1 sec timeout for this test. With pidns caching more than 1000 > > > > > + * syscalls can be executed, without caching only a few tens. > > > > > + */ > > > > > +#define SYSCALL_COUNT 200 > > > > > + > > > > > +int > > > > > +main(void) > > > > > +{ > > > > > + pidns_test_init(); > > > > > + > > > > > + for (int i = 0; i < SYSCALL_COUNT; i++) > > > > > + getpid(); > > > > > + > > > > > + return 0; > > > > > +} > > > > > > > > As getpid can be easily cached by libc, this has to be a syscall(). > > > > > > > > With regards to the number of syscalls, some hosts could be very slow, so > > > > I suggest to count the number of syscalls without any pid translation and > > > > use it as a baseline. > > > > > > Good idea, thanks. > > > > We employ a similar technique in filter_seccomp-perf.test where the test > > counts the number of chdir syscalls invoked in a loop for one second. > > Thanks for pointing that out. But I already started to implement a > little bit different kind of test: the syscall count is constant, I > measure the time with and without pidns translation, and the > difference should be below some threshold. Let's see which one results in less code then. ;) -- ldv From ldv at altlinux.org Sat Aug 15 21:02:48 2020 From: ldv at altlinux.org (Dmitry V. Levin) Date: Sun, 16 Aug 2020 00:02:48 +0300 Subject: [RFC PATCH 4/4] Add test for trie In-Reply-To: <20200815151826.GA376@altlinux.org> References: <20200813153242.94742-1-uzonyi.akos@gmail.com> <20200813153242.94742-5-uzonyi.akos@gmail.com> <20200815151826.GA376@altlinux.org> Message-ID: <20200815210248.GB3699@altlinux.org> On Sat, Aug 15, 2020 at 06:18:26PM +0300, Dmitry V. Levin wrote: > On Thu, Aug 13, 2020 at 05:32:42PM +0200, ?kos Uzonyi wrote: [...] > > --- /dev/null > > +++ b/tests/trie.test > > @@ -0,0 +1,12 @@ > > +#!/bin/sh > > +# > > +# Test trie. > > +# > > +# Copyright (c) 2020 The strace developers. > > +# All rights reserved. > > +# > > +# SPDX-License-Identifier: LGPL-2.1-or-later > > + > > +. "${srcdir=.}/init.sh" > > + > > +run_prog > > I suppose you can add something like > > trie . "${srcdir=.}/init.sh"; run_prog > > to tests/gen_tests.in with the same effect. Or maybe just a simple line trie run_prog would be sufficient. -- ldv From ldv at altlinux.org Sat Aug 15 21:19:41 2020 From: ldv at altlinux.org (Dmitry V. Levin) Date: Sun, 16 Aug 2020 00:19:41 +0300 Subject: [PATCH v8 5/5] Add tests for PID namespace translation In-Reply-To: <20200809141306.477539-6-uzonyi.akos@gmail.com> References: <20200809141306.477539-1-uzonyi.akos@gmail.com> <20200809141306.477539-6-uzonyi.akos@gmail.com> Message-ID: <20200815211941.GA3650@altlinux.org> On Sun, Aug 09, 2020 at 04:13:06PM +0200, ?kos Uzonyi wrote: [...] > * tests/kill--pidns-translation.c: New file. Tests for tkill and tgkill syscalls were added recently, could you extend them too, please? [...] > static void > test_f_owner_ex(void) > { > - static const struct { > + struct { > int type; > const char *type_name; > - pid_t pid[2]; > + enum pid_type pid_type; > + pid_t pid; > } a[] = { > - { ARG_STR(F_OWNER_TID), { 1234567890, 20 } }, > - { ARG_STR(F_OWNER_PID), { 1298126790, 30 } }, > - { ARG_STR(F_OWNER_PGRP), { 1294567890, 40 } } > + { ARG_STR(F_OWNER_TID), PT_NONE, 1234567890 }, > + { ARG_STR(F_OWNER_PID), PT_NONE, 1234567890 }, > + { ARG_STR(F_OWNER_PGRP), PT_NONE, 1234567890 }, > + { ARG_STR(F_OWNER_TID), PT_TID, 0 }, > + { ARG_STR(F_OWNER_PID), PT_TGID, 0 }, > + { ARG_STR(F_OWNER_PGRP), PT_PGID, 0 }, > }; > > - for (unsigned int i = 0; i < ARRAY_SIZE(a); i++) { > - for (unsigned int j = 0; j < ARRAY_SIZE(a[0].pid); j++) { > - test_f_owner_ex_umove_or_printaddr(a[i].type, > - a[i].type_name, > - a[i].pid[j]); > - } > - } > + a[3].pid = syscall(__NR_gettid); > + a[4].pid = getpid(); > + a[5].pid = getpgid(0); > + > + for (unsigned int i = 0; i < ARRAY_SIZE(a); i++) > + test_f_owner_ex_umove_or_printaddr(a[i].type, a[i].type_name, > + a[i].pid_type, a[i].pid); > } Let's initialize the array during the definition. If it's no longer static, function calls are allowed in the definition. [...] > --- /dev/null > +++ b/tests/ioctl_block--pidns-translation.test > @@ -0,0 +1,24 @@ > +#!/bin/sh > +# > +# Check ioctl syscall decoding. This is primarily not a generic check of ioctl syscall decoding. [...] > @@ -365,7 +393,8 @@ check_ax25(void) > for (size_t i = 0; i < 3; i++) { > size = sizeof(ax25) + sizeof(ax25_address) * (i / 2); > rc = connect(-1, sax_void, size); > - printf("connect(-1, {sa_family=AF_AX25" > + pidns_print_leader(); > + printf("connect(-1, {sa_family=AF_AX25" > ", fsa_ax25={sax25_call=VALID-13, sax25_ndigis=%d}" > ", fsa_digipeater=[VALID2-7, OK-15, %s /* FINE-2 */" > ", {ax25_call=\"\\xe6\\xda\\xc2\\xd8\\xd8\\xe6\\x12\"" Something went wrong with the indentation here, > @@ -427,13 +456,15 @@ check_x25(void) > long rc; > > rc = connect(-1, x25_void, sizeof(c_x25) - 1); > + pidns_print_leader(); > printf("connect(-1, {sa_family=AF_X25" > ", sa_data=\"0123456789abcde\"}, %zu) = %s\n", > sizeof(c_x25) - 1, sprintrc(rc)); > > for (size_t i = 0; i < 2; i++) { > rc = connect(-1, x25_void, sizeof(c_x25) + i); > - printf("connect(-1, {sa_family=AF_X25" > + pidns_print_leader(); > + printf("connect(-1, {sa_family=AF_X25" > ", sx25_addr={x25_addr=\"0123456789abcde\"...}" > "}, %zu) = %s\n", > sizeof(c_x25) + i, sprintrc(rc)); here, > @@ -526,7 +563,8 @@ check_ll(void) > ((struct sockaddr_ll *) ll)->sll_ifindex = ifindex_lo(); > if (((struct sockaddr_ll *) ll)->sll_ifindex) { > ret = connect(-1, ll, len); > - printf("connect(-1, {sa_family=AF_PACKET" > + pidns_print_leader(); > + printf("connect(-1, {sa_family=AF_PACKET" > ", sll_protocol=htons(ETH_P_ALL)" > ", sll_ifindex=%s" > ", sll_hatype=ARPHRD_ETHER" and here. [...] > --- /dev/null > +++ b/tests/netlink_audit--pidns-translation.test > @@ -0,0 +1,13 @@ > +#!/bin/sh > +# > +# Check decoding of NETLINK_SOCK_DIAG protocol This is primarily not a generic check of NETLINK_SOCK_DIAG protocol decoding. -- ldv From uzonyi.akos at gmail.com Sat Aug 15 23:00:16 2020 From: uzonyi.akos at gmail.com (=?UTF-8?B?w4Frb3MgVXpvbnlp?=) Date: Sun, 16 Aug 2020 01:00:16 +0200 Subject: [RFC PATCH 4/4] Add test for trie In-Reply-To: <20200815210248.GB3699@altlinux.org> References: <20200813153242.94742-1-uzonyi.akos@gmail.com> <20200813153242.94742-5-uzonyi.akos@gmail.com> <20200815151826.GA376@altlinux.org> <20200815210248.GB3699@altlinux.org> Message-ID: On Sat, 15 Aug 2020 at 23:02, Dmitry V. Levin wrote: > On Sat, Aug 15, 2020 at 06:18:26PM +0300, Dmitry V. Levin wrote: > > On Thu, Aug 13, 2020 at 05:32:42PM +0200, ?kos Uzonyi wrote: > [...] > > > --- /dev/null > > > +++ b/tests/trie.test > > > @@ -0,0 +1,12 @@ > > > +#!/bin/sh > > > +# > > > +# Test trie. > > > +# > > > +# Copyright (c) 2020 The strace developers. > > > +# All rights reserved. > > > +# > > > +# SPDX-License-Identifier: LGPL-2.1-or-later > > > + > > > +. "${srcdir=.}/init.sh" > > > + > > > +run_prog > > > > I suppose you can add something like > > > > trie . "${srcdir=.}/init.sh"; run_prog > > > > to tests/gen_tests.in with the same effect. > > Or maybe just a simple line > > trie run_prog > > would be sufficient. Yes, the first one doesn't even work ;). From uzonyi.akos at gmail.com Sat Aug 15 23:29:00 2020 From: uzonyi.akos at gmail.com (=?UTF-8?B?w4Frb3MgVXpvbnlp?=) Date: Sun, 16 Aug 2020 01:29:00 +0200 Subject: [PATCH v8 4/5] Implement testing framework for pidns In-Reply-To: <20200815202725.GA3099@altlinux.org> References: <20200809141306.477539-1-uzonyi.akos@gmail.com> <20200809141306.477539-5-uzonyi.akos@gmail.com> <20200815202725.GA3099@altlinux.org> Message-ID: On Sat, 15 Aug 2020 at 22:27, Dmitry V. Levin wrote: > On Sun, Aug 09, 2020 at 04:13:05PM +0200, ?kos Uzonyi wrote: > [...] > > --- a/tests/init.sh > > +++ b/tests/init.sh > > @@ -387,6 +387,37 @@ test_prog_set() > > test_pure_prog_set "$@" < "$srcdir/$NAME.in" > > } > > > > +test_pidns_run_strace() > > +{ > > + local parent_pid > > + > > + check_prog tail > > + check_prog cut > > + check_prog grep > > + > > + run_prog > /dev/null > > + run_strace --pidns-translation -f $@ $args > "$EXP" > > + > > + # filter out logs made by the parent or init process of the pidns test > > + parent_pid="$(tail -n 2 $LOG | head -n 1 | cut -d' ' -f1)" > > + init_pid="$(tail -n 1 $LOG | cut -d' ' -f1)" > > + grep -E -v "^($parent_pid|$init_pid) " "$LOG" > "$OUT" > > + match_diff "$OUT" "$EXP" > > +} > > init_pid also has to be declared as local here. RIght, thanks. > > + > > +test_pidns() > > +{ > > + # ioctl(NS_GET_PARENT) is added in Linux 4.9 > > + require_min_kernel_version_or_skip 4.9 > > Is this check still needed given that check_ns_ioctl() already performs > a runtime check? I think I left this check because the runtime check seemed to be just a temporary solution (until the kernel is fixed). But since it's not expected to happen very soon, I agree that this check should be removed. > > [...] > > + if (read(strace_ids_pipe[0], pidns_strace_ids, > > + sizeof(pidns_strace_ids)) < 0) > > + perror_msg_and_fail("read"); > > If this read call is expected to return sizeof(pidns_strace_ids), > should the return value be tested against that instead? > > [...] > > + if (write(strace_ids_pipe[1], pidns_strace_ids, > > + sizeof(pidns_strace_ids)) < 0) > > + perror_msg_and_fail("write"); > > Likewise, if this write call is expected to return sizeof(pidns_strace_ids), > should the return value be tested against that instead? That makes sense. I'll test against sizeof(pidns_strace_ids). > > +static void > > +create_init_process(void) > > +{ > > + int child_pipe[2]; > > + if (pipe(child_pipe) < 0) > > + perror_msg_and_fail("pipe"); > > + > > + pid_t pid = fork(); > > + if (pid < 0) > > + perror_msg_and_fail("fork"); > > + > > + if (!pid) { > > + close(child_pipe[1]); > > + _exit(read(child_pipe[0], &child_pipe[1], sizeof(int)) == 0); > > + } > > + > > + close(child_pipe[0]); > > +} > > If nothing is going to be written to child_pipe[1], then this read call is > expected to return 0, followed by _exit(1). The choice of exit code seems > strange to me. Oh yes, this is a mistake, I should have written "!=" instead of "==". I think I'll use an if, that's more readable. > > + > > +void > > +check_ns_ioctl(void) > > +{ > > + int fd = open("/proc/self/ns/pid", O_RDONLY); > > + if (fd < 0) > > + perror_msg_and_fail("opening /proc/self/ns/pid"); > > What if /proc/self/ns/pid is not available, e.g. /proc is not mounted > or the kernel doesn't implement it? > I suggest to do perror_msg_and_skip instead, at least in case of ENOENT. OK, I'll check for ENOENT From uzonyi.akos at gmail.com Sun Aug 16 17:08:48 2020 From: uzonyi.akos at gmail.com (=?UTF-8?B?w4Frb3MgVXpvbnlp?=) Date: Sun, 16 Aug 2020 19:08:48 +0200 Subject: [PATCH v8 4/5] Implement testing framework for pidns In-Reply-To: References: <20200809141306.477539-1-uzonyi.akos@gmail.com> <20200809141306.477539-5-uzonyi.akos@gmail.com> <20200815202725.GA3099@altlinux.org> Message-ID: On Sun, 16 Aug 2020 at 01:29, ?kos Uzonyi wrote: > On Sat, 15 Aug 2020 at 22:27, Dmitry V. Levin wrote: > > On Sun, Aug 09, 2020 at 04:13:05PM +0200, ?kos Uzonyi wrote: [...] > > > +static void > > > +create_init_process(void) > > > +{ > > > + int child_pipe[2]; > > > + if (pipe(child_pipe) < 0) > > > + perror_msg_and_fail("pipe"); > > > + > > > + pid_t pid = fork(); > > > + if (pid < 0) > > > + perror_msg_and_fail("fork"); > > > + > > > + if (!pid) { > > > + close(child_pipe[1]); > > > + _exit(read(child_pipe[0], &child_pipe[1], sizeof(int)) == 0); > > > + } > > > + > > > + close(child_pipe[0]); > > > +} > > > > If nothing is going to be written to child_pipe[1], then this read call is > > expected to return 0, followed by _exit(1). The choice of exit code seems > > strange to me. > > Oh yes, this is a mistake, I should have written "!=" instead of "==". > I think I'll use an if, that's more readable. Actually, we do not really care about exit code, so I think I will just use _exit(0), regardless of the return value of read. From ldv at altlinux.org Sun Aug 16 17:16:05 2020 From: ldv at altlinux.org (Dmitry V. Levin) Date: Sun, 16 Aug 2020 20:16:05 +0300 Subject: [PATCH v8 4/5] Implement testing framework for pidns In-Reply-To: References: <20200809141306.477539-1-uzonyi.akos@gmail.com> <20200809141306.477539-5-uzonyi.akos@gmail.com> <20200815202725.GA3099@altlinux.org> Message-ID: <20200816171603.GA16560@altlinux.org> On Sun, Aug 16, 2020 at 07:08:48PM +0200, ?kos Uzonyi wrote: > On Sun, 16 Aug 2020 at 01:29, ?kos Uzonyi wrote: > > On Sat, 15 Aug 2020 at 22:27, Dmitry V. Levin wrote: > > > On Sun, Aug 09, 2020 at 04:13:05PM +0200, ?kos Uzonyi wrote: > [...] > > > > +static void > > > > +create_init_process(void) > > > > +{ > > > > + int child_pipe[2]; > > > > + if (pipe(child_pipe) < 0) > > > > + perror_msg_and_fail("pipe"); > > > > + > > > > + pid_t pid = fork(); > > > > + if (pid < 0) > > > > + perror_msg_and_fail("fork"); > > > > + > > > > + if (!pid) { > > > > + close(child_pipe[1]); > > > > + _exit(read(child_pipe[0], &child_pipe[1], sizeof(int)) == 0); > > > > + } > > > > + > > > > + close(child_pipe[0]); > > > > +} > > > > > > If nothing is going to be written to child_pipe[1], then this read call is > > > expected to return 0, followed by _exit(1). The choice of exit code seems > > > strange to me. > > > > Oh yes, this is a mistake, I should have written "!=" instead of "==". > > I think I'll use an if, that's more readable. > > Actually, we do not really care about exit code, so I think I will > just use _exit(0), regardless of the return value of read. Ignoring the return value of read syscall might be tricky. -- ldv From uzonyi.akos at gmail.com Sun Aug 16 20:19:48 2020 From: uzonyi.akos at gmail.com (=?UTF-8?B?w4Frb3MgVXpvbnlp?=) Date: Sun, 16 Aug 2020 22:19:48 +0200 Subject: [PATCH v8 4/5] Implement testing framework for pidns In-Reply-To: <20200816171603.GA16560@altlinux.org> References: <20200809141306.477539-1-uzonyi.akos@gmail.com> <20200809141306.477539-5-uzonyi.akos@gmail.com> <20200815202725.GA3099@altlinux.org> <20200816171603.GA16560@altlinux.org> Message-ID: On Sun, 16 Aug 2020 at 19:16, Dmitry V. Levin wrote: > On Sun, Aug 16, 2020 at 07:08:48PM +0200, ?kos Uzonyi wrote: > > On Sun, 16 Aug 2020 at 01:29, ?kos Uzonyi wrote: > > > On Sat, 15 Aug 2020 at 22:27, Dmitry V. Levin wrote: > > > > On Sun, Aug 09, 2020 at 04:13:05PM +0200, ?kos Uzonyi wrote: > > [...] > > > > > +static void > > > > > +create_init_process(void) > > > > > +{ > > > > > + int child_pipe[2]; > > > > > + if (pipe(child_pipe) < 0) > > > > > + perror_msg_and_fail("pipe"); > > > > > + > > > > > + pid_t pid = fork(); > > > > > + if (pid < 0) > > > > > + perror_msg_and_fail("fork"); > > > > > + > > > > > + if (!pid) { > > > > > + close(child_pipe[1]); > > > > > + _exit(read(child_pipe[0], &child_pipe[1], sizeof(int)) == 0); > > > > > + } > > > > > + > > > > > + close(child_pipe[0]); > > > > > +} > > > > > > > > If nothing is going to be written to child_pipe[1], then this read call is > > > > expected to return 0, followed by _exit(1). The choice of exit code seems > > > > strange to me. > > > > > > Oh yes, this is a mistake, I should have written "!=" instead of "==". > > > I think I'll use an if, that's more readable. > > > > Actually, we do not really care about exit code, so I think I will > > just use _exit(0), regardless of the return value of read. > > Ignoring the return value of read syscall might be tricky. Oh, that's true. Then I'll go with the if version. From uzonyi.akos at gmail.com Sun Aug 16 22:18:43 2020 From: uzonyi.akos at gmail.com (=?UTF-8?q?=C3=81kos=20Uzonyi?=) Date: Mon, 17 Aug 2020 00:18:43 +0200 Subject: [RFC PATCH v9 0/8] [PIDNS] Final Message-ID: <20200816221851.200031-1-uzonyi.akos@gmail.com> From: Uzonyi ?kos I made the requested changes, added more test cases to trie test, and fixed some trie bugs. The travis build [1] unfortunately shows some errors. On ppc mknod test fails, but I have no idea why. Mknod is unrelated to my code. Do you have any idea? Also, pidns-cache fails on one arm build. I tried to increase the time available for translation, but it didn't help. Maybe pidns-cache test should be removed, it's not very important. [1] https://travis-ci.org/github/AkosUzonyi/strace/builds/718435900 Changes in v9: - Add test for trie - Fix ns_id_size - Add tests for pidns cache - Skip pidns tests if /proc/self/ns/pid is not found - init.sh: add init_pid as a local variable - Remove kernel version checks (4.9) in pidns tests - tests/pidns.c: fix exit code of init process - tests/fcntl-common.c: initialize array during definition - tests/net-sockaddr.c: fix indentation - Fix description of some test scripts - Add tests for tkill, tgkill - Fix trie bugs: - When creating a data block, fill it with empty_value - Check calloc return value - Include config.h - Move some include from trie.c to trie.h - Fix trie_data_block_calc_pos when item_size_lg == 6 - Mask empty_value to fit item_size Changes in v8: - translate_pid: document return value; check !proc_pid first - NEWS: move to new section - get_proc_pid, printpid: fix comment - Check if translation failed Changes in v7: - Run uniq on gettid--pidns-translation test output - Add comment to printpid - translate_id: do not call get_our_ns if not necessary - Remove unnecessary parentheses - Fix commit message of last commit (s/-Y/--pidns-translation/) - get_proc_pid: remove unnecessary optimization - trie.c: remove #include - Add clarification to get_proc_pid's comment - Fix typos - trie.c: ptr_sz_lg use void* in sizeof - trie_get_node_size: fix comment - trie.c: remove "TODO: overflow" - ipc_shmctl.c: remove duplicate #include "print_field.h" Changes in v6: - Add function with documentation for creating tries - Do not use -1ULL as error indicator in tcb.pid_ns - Use unsigned int (instead of uint64_t) for NS IDs - Add constant for NS ID size. - Modify get_proc_pid a bit - Die if trie creation fails Changes in v5: - Squash "Use printpid in *" commits - Makefile.am: move adding getpid.c to "Use printpid in decoders" - Remove pid_ns_inited field from struct tcb - strace.1.in: remove -Y flag - Use tprints instead of tprintf where possible - Make some global variables static - pidns_init: remove "inited" bool variable - Make printpid_translation static - tests/pidns.c: refactor a bit - check_ns_ioctl: fix error msg - defs.h: Move adding get_proc_pid to "PID namespace translation support" - Remove tcp paramter name from declarations - Update printfd_pid_tracee_ns documentation - Use named constants for trie_create arguments - Add documentation comments - Add printpid_tgid_pgid function - Delete get_pid_max function; use global variables instead - Refactor trie: - Move key_size argument - Remove support for TRIE_SET - Merge trie_create, trie_init, trie_check functions - trie_free_node: make static, fix "node" argument type - Add max_depth field - Reorder functions - Extract common parts of trie_get, trie_set Changes in v4: - Skip tests if NS_* ioctl commands are not supported - Improve documentation in pidns.h - Use pipe for init process termination (instead of SIGKILL) - Add PIDNS_TEST_INIT macro - Remove "ifdef __NR_gettid" - Fix fork--pidns-tranlsation.test: skip if unshare fails with EPERM - Use debug message instead of normal message in some cases - Rename some labels - Rewrite get_ns function - Remove O_NONBLOCK from open(/proc//ns/pid) Changes in v3: - Split accidentally sqashed last commit - Undo modification of tests/pidfd_send_signal.c - Rename kcmp-yY test to kcmp-y--pidns-translation - Skip tests if unshare fails with EPERM - Fix buffer size in pidns_pid2str - Use largefile_wrappers.h macros - Return early if from_ns or our_ns is 0 - Do not call ioctl(NS_GET_PARENT) again, if first failed with ENOTTY - Skip pidns tests if Linux kernel version < 4.9 - Use smaller trie nodes in pidns.c - Remove race condition from fork--pidns-translation test - Move "key_size" to center in trie description - Use PT_TID (not PT_TGID) when translating tcp->pid - Fix get_ns_hierarchy and get_id_list functions - Fix migrate_pages test if syscall succeds - Fix filtering in ioctl_block--pidns-translation.test - Fix -a flag value in xetpriority test Changes in v2: - Add missing header files to Makefile - Fix pointer-to-int-cast errors - Fix unused-result errors - Use perror_msg instead of perror_func_msg where appropriate - Remove tcb parameter of read_int_from_file - Use xsprintf instead of snprintf - Refactor get_pid_max, get_ns_hierarchy, get_id_list functions - Remove -Y flag - Improve documentation of trie - Fix printing of f_owner_ex struct - Use printpid for F_GETOWN, F_SETOWN fcntl command arguments - Use printpid for shmid_ds.shm_cpid, shmid_ds.shm_clid - Call pidns_init before parsing arguments ?kos Uzonyi (8): PID namespace translation support Use printpid in decoders Use get_proc_pid for /proc paths Implement testing framework for pidns Add tests for PID namespace translation [squash] Test pidns translation cache [squash] Add test for trie [squash] Add tests for tkill, tgkill Makefile.am | 4 + NEWS | 1 + affinity.c | 6 +- block.c | 2 +- bpf.c | 2 +- capability.c | 4 +- clone.c | 14 +- defs.h | 61 +- fcntl.c | 24 +- get_robust_list.c | 3 +- getpid.c | 46 ++ ioprio.c | 26 +- ipc_shmctl.c | 4 +- kcmp.c | 5 +- largefile_wrappers.h | 2 + linux/dummy.h | 8 +- mmap_cache.c | 2 +- msghdr.c | 2 +- net.c | 2 +- netlink.c | 5 +- numa.c | 6 +- pathtrace.c | 7 +- pidfd_open.c | 2 +- pidns.c | 604 ++++++++++++++++++ print_fields.h | 24 + printsiginfo.c | 2 +- process.c | 3 +- process_vm.c | 6 +- resource.c | 27 +- sched.c | 25 +- signal.c | 21 +- sockaddr.c | 2 +- strace.1.in | 4 + strace.c | 11 +- syscall.c | 15 + tests/.gitignore | 35 + tests/Makefile.am | 44 ++ tests/fcntl--pidns-translation.c | 2 + tests/fcntl-common.c | 78 ++- tests/fcntl.c | 1 + tests/fcntl64--pidns-translation.c | 2 + tests/fcntl64.c | 3 + tests/fork--pidns-translation.awk | 15 + tests/fork--pidns-translation.c | 69 ++ tests/fork--pidns-translation.test | 14 + tests/gen_tests.in | 32 +- tests/getpgrp--pidns-translation.c | 2 + tests/getpgrp.c | 8 +- tests/getpid--pidns-translation.c | 2 + tests/getpid.c | 8 +- tests/getsid--pidns-translation.c | 2 + tests/getsid.c | 9 +- tests/gettid--pidns-translation.c | 2 + tests/gettid--pidns-translation.test | 18 + tests/gettid.c | 8 +- tests/init.sh | 29 + tests/ioctl_block--pidns-translation.c | 2 + tests/ioctl_block--pidns-translation.test | 22 + tests/ioctl_block.c | 24 +- tests/ioprio--pidns-translation.c | 2 + tests/ioprio.c | 54 +- tests/kcmp-y--pidns-translation.c | 2 + tests/kcmp.c | 36 +- tests/kill--pidns-translation.c | 2 + tests/kill.c | 12 +- tests/migrate_pages--pidns-translation.c | 2 + tests/migrate_pages.c | 17 +- tests/move_pages--pidns-translation.c | 2 + tests/move_pages.c | 51 +- tests/net-sockaddr--pidns-translation.c | 2 + tests/net-sockaddr.c | 60 +- tests/netlink_audit--pidns-translation.c | 2 + tests/netlink_audit--pidns-translation.test | 13 + tests/netlink_audit.c | 11 +- tests/pidfd_open--pidns-translation.c | 2 + tests/pidfd_open.c | 21 +- tests/pidfd_send_signal--pidns-translation.c | 2 + tests/pidfd_send_signal.c | 13 +- tests/pidns-cache.c | 62 ++ tests/pidns-cache.test | 16 + tests/pidns.c | 229 +++++++ tests/pidns.h | 56 ++ tests/prlimit64--pidns-translation.c | 2 + tests/prlimit64.c | 17 +- tests/process_vm_readv--pidns-translation.c | 2 + tests/process_vm_readv_writev.c | 27 +- tests/process_vm_writev--pidns-translation.c | 2 + tests/rt_sigqueueinfo--pidns-translation.c | 2 + tests/rt_sigqueueinfo.c | 15 +- tests/rt_tgsigqueueinfo--pidns-translation.c | 2 + tests/rt_tgsigqueueinfo.c | 26 +- tests/sched_xetaffinity--pidns-translation.c | 2 + tests/sched_xetaffinity.c | 31 +- tests/sched_xetattr--pidns-translation.c | 2 + tests/sched_xetattr.c | 47 +- tests/sched_xetparam--pidns-translation.c | 2 + tests/sched_xetparam.c | 20 +- tests/sched_xetscheduler--pidns-translation.c | 2 + tests/sched_xetscheduler.c | 44 +- tests/signal_receive--pidns-translation.c | 2 + tests/signal_receive.c | 22 +- tests/so_peercred--pidns-translation.c | 2 + tests/so_peercred.c | 22 + tests/tgkill--pidns-translation.c | 2 + tests/tgkill.c | 51 +- tests/tkill--pidns-translation.c | 2 + tests/tkill.c | 19 +- tests/trie.c | 77 +++ tests/xet_robust_list--pidns-translation.c | 2 + tests/xet_robust_list.c | 18 +- tests/xetpgid--pidns-translation.c | 2 + tests/xetpgid.c | 21 +- tests/xetpriority--pidns-translation.c | 2 + tests/xetpriority.c | 20 +- trie.c | 290 +++++++++ trie.h | 92 +++ util.c | 31 +- wait.c | 36 +- 118 files changed, 2766 insertions(+), 274 deletions(-) create mode 100644 getpid.c create mode 100644 pidns.c create mode 100644 tests/fcntl--pidns-translation.c create mode 100644 tests/fcntl64--pidns-translation.c create mode 100644 tests/fork--pidns-translation.awk create mode 100644 tests/fork--pidns-translation.c create mode 100755 tests/fork--pidns-translation.test create mode 100644 tests/getpgrp--pidns-translation.c create mode 100644 tests/getpid--pidns-translation.c create mode 100644 tests/getsid--pidns-translation.c create mode 100644 tests/gettid--pidns-translation.c create mode 100755 tests/gettid--pidns-translation.test create mode 100644 tests/ioctl_block--pidns-translation.c create mode 100755 tests/ioctl_block--pidns-translation.test create mode 100644 tests/ioprio--pidns-translation.c create mode 100644 tests/kcmp-y--pidns-translation.c create mode 100644 tests/kill--pidns-translation.c create mode 100644 tests/migrate_pages--pidns-translation.c create mode 100644 tests/move_pages--pidns-translation.c create mode 100644 tests/net-sockaddr--pidns-translation.c create mode 100644 tests/netlink_audit--pidns-translation.c create mode 100755 tests/netlink_audit--pidns-translation.test create mode 100644 tests/pidfd_open--pidns-translation.c create mode 100644 tests/pidfd_send_signal--pidns-translation.c create mode 100644 tests/pidns-cache.c create mode 100755 tests/pidns-cache.test create mode 100644 tests/pidns.c create mode 100644 tests/pidns.h create mode 100644 tests/prlimit64--pidns-translation.c create mode 100644 tests/process_vm_readv--pidns-translation.c create mode 100644 tests/process_vm_writev--pidns-translation.c create mode 100644 tests/rt_sigqueueinfo--pidns-translation.c create mode 100644 tests/rt_tgsigqueueinfo--pidns-translation.c create mode 100644 tests/sched_xetaffinity--pidns-translation.c create mode 100644 tests/sched_xetattr--pidns-translation.c create mode 100644 tests/sched_xetparam--pidns-translation.c create mode 100644 tests/sched_xetscheduler--pidns-translation.c create mode 100644 tests/signal_receive--pidns-translation.c create mode 100644 tests/so_peercred--pidns-translation.c create mode 100644 tests/tgkill--pidns-translation.c create mode 100644 tests/tkill--pidns-translation.c create mode 100644 tests/trie.c create mode 100644 tests/xet_robust_list--pidns-translation.c create mode 100644 tests/xetpgid--pidns-translation.c create mode 100644 tests/xetpriority--pidns-translation.c create mode 100644 trie.c create mode 100644 trie.h -- 2.28.0 From uzonyi.akos at gmail.com Sun Aug 16 22:18:44 2020 From: uzonyi.akos at gmail.com (=?UTF-8?q?=C3=81kos=20Uzonyi?=) Date: Mon, 17 Aug 2020 00:18:44 +0200 Subject: [RFC PATCH v9 1/8] PID namespace translation support In-Reply-To: <20200816221851.200031-1-uzonyi.akos@gmail.com> References: <20200816221851.200031-1-uzonyi.akos@gmail.com> Message-ID: <20200816221851.200031-2-uzonyi.akos@gmail.com> * defs.h (pidns_translation): New variable. (tcb): Add pid_ns field. (RVAL_MASK): Change value from 013 to 017. (RVAL_TID, RVAL_SID, RVAL_TGID, RVAL_PGID): New definitions. (pid_type): New enum. (pidns_init, translate_pid, get_proc_pid, printpid, printpid_tgid_pgid): New function declarations. * largefile_wrappers.h (fstat_fd): New macro. * pidns.c: New file. * trie.c: New file. * trie.h: New file. * Makefile.am (libstrace_a_SOURCES): Add trie.c, trie.h, pidns.c. * strace.c (pidns_translation): New variable. (init): Add --pidns-translation option. * syscall.c (syscall_exiting_trace): Handle RVAL_* return values. * NEWS: Mention this. * strace.1.in: Add description for new option. Co-Authored-by: Eugene Syromyatnikov --- Makefile.am | 3 + NEWS | 1 + defs.h | 56 +++- largefile_wrappers.h | 2 + pidns.c | 604 +++++++++++++++++++++++++++++++++++++++++++ strace.1.in | 4 + strace.c | 9 + syscall.c | 15 ++ trie.c | 290 +++++++++++++++++++++ trie.h | 92 +++++++ 10 files changed, 1075 insertions(+), 1 deletion(-) create mode 100644 pidns.c create mode 100644 trie.c create mode 100644 trie.h diff --git a/Makefile.am b/Makefile.am index f5447811..73c22035 100644 --- a/Makefile.am +++ b/Makefile.am @@ -233,6 +233,7 @@ libstrace_a_SOURCES = \ personality.c \ pidfd_getfd.c \ pidfd_open.c \ + pidns.c \ pkeys.c \ poll.c \ prctl.c \ @@ -344,6 +345,8 @@ libstrace_a_SOURCES = \ time.c \ times.c \ trace_event.h \ + trie.c \ + trie.h \ truncate.c \ ubi.c \ ucopy.c \ diff --git a/NEWS b/NEWS index 10039ceb..c3c5c162 100644 --- a/NEWS +++ b/NEWS @@ -2,6 +2,7 @@ Noteworthy changes in release ?.? (????-??-??) ============================================== * Improvements + * Added --pidns-translation option for PID namespace translation. * Bug fixes diff --git a/defs.h b/defs.h index f7ac54f3..511a92a2 100644 --- a/defs.h +++ b/defs.h @@ -280,6 +280,13 @@ struct tcb { struct timespec etime; /* Syscall entry time (CLOCK_MONOTONIC) */ struct timespec delay_expiration_time; /* When does the delay end */ + /* + * The ID of the PID namespace of this process + * (inode number of /proc//ns/pid) + * (0: not initialized) + */ + unsigned int pid_ns; + struct mmap_cache_t *mmap_cache; /* @@ -413,7 +420,11 @@ extern const struct xlat whence_codes[]; # define RVAL_HEX 001 /* hex format */ # define RVAL_OCTAL 002 /* octal format */ # define RVAL_FD 010 /* file descriptor */ -# define RVAL_MASK 013 /* mask for these values */ +# define RVAL_TID 011 /* task ID */ +# define RVAL_SID 012 /* session ID */ +# define RVAL_TGID 013 /* thread group ID */ +# define RVAL_PGID 014 /* process group ID */ +# define RVAL_MASK 017 /* mask for these values */ # define RVAL_STR 020 /* Print `auxstr' field after return val */ # define RVAL_NONE 040 /* Print nothing */ @@ -428,6 +439,16 @@ extern const struct xlat whence_codes[]; # define indirect_ipccall(tcp) (tcp_sysent(tcp)->sys_flags & TRACE_INDIRECT_SUBCALL) +enum pid_type { + PT_TID, + PT_TGID, + PT_PGID, + PT_SID, + + PT_COUNT, + PT_NONE = -1 +}; + enum sock_proto { SOCK_PROTO_UNKNOWN, SOCK_PROTO_UNIX, @@ -469,6 +490,7 @@ extern int Tflag_scale; extern int Tflag_width; extern bool iflag; extern bool count_wallclock; +extern unsigned int pidns_translation; /* are we filtering traces based on paths? */ extern struct path_set { const char **paths_selected; @@ -983,6 +1005,29 @@ print_local_array_ex(struct tcb *tcp, extern kernel_ulong_t * fetch_indirect_syscall_args(struct tcb *, kernel_ulong_t addr, unsigned int n_args); +extern void pidns_init(void); + +/** + * Returns the pid of the tracee as present in /proc of the tracer (can be + * different from tcp->pid if /proc and the tracer process are in different PID + * namespaces). + */ +extern int get_proc_pid(struct tcb *); + +/** + * Translates a pid from tracee's namespace to our namepace. + * + * @param tcp The tcb of the tracee + * (NULL: from_id is in strace's namespace. Useful for + * getting the proc PID of from_id) + * @param from_id The id to be translated + * @param type The PID type of from_id + * @param proc_pid_ptr If not NULL, writes the proc PID to this location + * @return The translated id, or 0 if translation fails. + */ +extern int translate_pid(struct tcb *, int dest_id, enum pid_type type, + int *proc_pid_ptr); + extern void dumpiov_in_msghdr(struct tcb *, kernel_ulong_t addr, kernel_ulong_t data_size); @@ -1058,6 +1103,15 @@ printfd(struct tcb *tcp, int fd) * of the tracee the descriptor tcp). This is a stub. */ extern void printfd_pid_tracee_ns(struct tcb *tcp, pid_t pid, int fd); + +/** Prints a PID specified in the tracee's PID namespace */ +extern void printpid(struct tcb *, int pid, enum pid_type type); + +/** + * Prints pid as a TGID if positive, and PGID if negative + * (like the first argument of kill). + */ +extern void printpid_tgid_pgid(struct tcb *, int pid); extern void print_sockaddr(struct tcb *, const void *sa, int len); extern bool print_inet_addr(int af, const void *addr, unsigned int len, const char *var_name); diff --git a/largefile_wrappers.h b/largefile_wrappers.h index 116e7048..9d8f5c92 100644 --- a/largefile_wrappers.h +++ b/largefile_wrappers.h @@ -29,6 +29,7 @@ # else # define fcntl_fd fcntl # endif +# define fstat_fd fstat64 # define strace_stat_t struct stat64 # define stat_file stat64 # define struct_dirent struct dirent64 @@ -39,6 +40,7 @@ # define open_file open # define fopen_stream fopen # define fcntl_fd fcntl +# define fstat_fd fstat # define strace_stat_t struct stat # define stat_file stat # define struct_dirent struct dirent diff --git a/pidns.c b/pidns.c new file mode 100644 index 00000000..9d8695da --- /dev/null +++ b/pidns.c @@ -0,0 +1,604 @@ +/* + * Copyright (c) 2020 ?kos Uzonyi + * All rights reserved. + * + * SPDX-License-Identifier: LGPL-2.1-or-later + */ + +#include "defs.h" + + +#include +#include +#include +#include +#include + +#include + +#include +#include +#include +#include + +#include "largefile_wrappers.h" +#include "trie.h" +#include "nsfs.h" +#include "xmalloc.h" +#include "xstring.h" + +/** + * Key: PID NS ID + * Value: a btree: + * Key: a process PID in NS + * Value: the process's PID as present in /proc + */ +static struct trie *ns_pid_to_proc_pid[PT_COUNT]; + +/** + * Key: Proc PID + * Value: struct proc_data + */ +static struct trie *proc_data_cache; + +static bool ns_get_parent_enotty = false; + +static const char tid_str[] = "NSpid:\t"; +static const char tgid_str[] = "NStgid:\t"; +static const char pgid_str[] = "NSpgid:\t"; +static const char sid_str[] = "NSsid:\t"; + +static const struct { + const char *str; + size_t size; +} id_strs[PT_COUNT] = { + [PT_TID] = { tid_str, sizeof(tid_str) - 1 }, + [PT_TGID] = { tgid_str, sizeof(tgid_str) - 1 }, + [PT_PGID] = { pgid_str, sizeof(pgid_str) - 1 }, + [PT_SID] = { sid_str, sizeof(sid_str) - 1 }, +}; + + +/** + * Limit on PID NS hierarchy depth, imposed since Linux 3.7. NS traversal + * is not possible before Linux 4.9, so we consider this limit pretty universal. + */ +#define MAX_NS_DEPTH 32 + +static const size_t ns_id_size = sizeof(unsigned int) * 8; +static const uint8_t ptr_sz_lg = (sizeof(void *) == 8 ? 6 : 5); + +static int pid_max; +static uint8_t pid_max_size, pid_max_size_lg; + +struct proc_data { + int proc_pid; + int ns_count; + unsigned int ns_hierarchy[MAX_NS_DEPTH]; + int id_count[PT_COUNT]; + int id_hierarchy[PT_COUNT][MAX_NS_DEPTH]; +}; + +/** + * Helper function for creating a trie. + * + * For node_key_bits and data_block_key_bits 4 is used (so trie height is 32 / 4 + * = 8, and node sizes are 8 byte * 2^4 = 128 bytes), which seems to be a good + * tradeoff between memory usage and lookup time. It should not be too large, + * since there can be large holes between PIDs, and it would be just a waste of + * memory having large nodes with lot of NULL pointers in them. + */ +static struct trie * +create_trie_4(uint8_t key_size, uint8_t item_size_lg, uint64_t empty_value) +{ + struct trie *t = trie_create(key_size, item_size_lg, 4, 4, empty_value); + if (!t) + error_msg_and_die("creating trie failed"); + + return t; +} + +void +pidns_init(void) +{ + if (proc_data_cache) + return; + + pid_max = INT_MAX; + if (read_int_from_file("/proc/sys/kernel/pid_max", &pid_max) < 0) + debug_func_perror_msg("reading /proc/sys/kernel/pid_max"); + pid_max_size = ilog2_32(pid_max - 1) + 1; + pid_max_size_lg = ilog2_32(pid_max_size - 1) + 1; + + for (int i = 0; i < PT_COUNT; i++) + ns_pid_to_proc_pid[i] = create_trie_4(ns_id_size, ptr_sz_lg, 0); + + proc_data_cache = create_trie_4(pid_max_size, ptr_sz_lg, 0); +} + +static void +put_proc_pid(unsigned int ns, int ns_pid, enum pid_type type, int proc_pid) +{ + struct trie *b = (struct trie *) (uintptr_t) trie_get(ns_pid_to_proc_pid[type], ns); + if (!b) { + b = create_trie_4(pid_max_size, pid_max_size_lg, 0); + trie_set(ns_pid_to_proc_pid[type], ns, (uint64_t) (uintptr_t) b); + } + trie_set(b, ns_pid, proc_pid); +} + +static int +get_cached_proc_pid(unsigned int ns, int ns_pid, enum pid_type type) +{ + struct trie *b = (struct trie *) (uintptr_t) + trie_get(ns_pid_to_proc_pid[type], ns); + if (!b) + return 0; + + return trie_get(b, ns_pid); +} + +/** + * Helper function, converts pid to string, or to "self" for pid == 0. + * Uses static buffer for operation. + */ +static const char * +pid_to_str(pid_t pid) +{ + if (!pid) + return "self"; + + static char buf[sizeof("-2147483648")]; + xsprintf(buf, "%d", pid); + return buf; +} + +/** + * Returns a list of PID NS IDs for the specified PID. + * + * @param proc_pid PID (as present in /proc) to get information for. + * @param ns_buf Pointer to buffer that is able to contain at least + * ns_buf_size items. + * @return Amount of NS in list. 0 indicates error. + */ +static size_t +get_ns_hierarchy(int proc_pid, unsigned int *ns_buf, size_t ns_buf_size) +{ + char path[PATH_MAX + 1]; + xsprintf(path, "/proc/%s/ns/pid", pid_to_str(proc_pid)); + + int fd = open_file(path, O_RDONLY); + if (fd < 0) + return 0; + + size_t n = 0; + while (n < ns_buf_size) { + strace_stat_t st; + if (fstat_fd(fd, &st)) + break; + + ns_buf[n++] = st.st_ino; + if (n >= ns_buf_size) + break; + + if (ns_get_parent_enotty) + break; + + int parent_fd = ioctl(fd, NS_GET_PARENT); + if (parent_fd < 0) { + switch (errno) { + case EPERM: + break; + + case ENOTTY: + ns_get_parent_enotty = true; + error_msg("NS_* ioctl commands are not " + "supported by the kernel"); + break; + + default: + perror_func_msg("ioctl(NS_GET_PARENT)"); + break; + } + + break; + } + + close(fd); + fd = parent_fd; + } + + close(fd); + + return n; +} + +/** + * Get list of IDs present in NS* proc status record. IDs are placed as they are + * stored in /proc (from top to bottom of NS hierarchy). + * + * @param proc_pid PID (as present in /proc) to get information for. + * @param id_buf Pointer to buffer that is able to contain at least + * MAX_NS_DEPTH items. Can be NULL. + * @param type Type of ID requested. + * @return Number of items stored in id_list. 0 indicates error. + */ +static size_t +get_id_list(int proc_pid, int *id_buf, enum pid_type type) +{ + const char *ns_str = id_strs[type].str; + size_t ns_str_size = id_strs[type].size; + + size_t n = 0; + + char status_path[PATH_MAX + 1]; + xsprintf(status_path, "/proc/%s/status", pid_to_str(proc_pid)); + FILE *f = fopen_stream(status_path, "r"); + if (!f) + return 0; + + char *line = NULL; + size_t linesize = 0; + char *p = NULL; + + while (getline(&line, &linesize, f) > 0) { + if (strncmp(line, ns_str, ns_str_size) == 0) { + p = line + ns_str_size; + break; + } + } + + while (p) { + errno = 0; + long id = strtol(p, NULL, 10); + + if (errno || id < 1 || id > INT_MAX) { + perror_func_msg("converting pid (%ld) to int", id); + break; + } + + if (id_buf) + id_buf[n] = (int) id; + + n++; + strsep(&p, "\t"); + } + + free(line); + fclose(f); + + return n; +} + +/** + * Returns whether the /proc filesystem's PID namespace is the same as strace's. + */ +static bool +is_proc_ours(void) +{ + static int cached_val = -1; + + if (cached_val < 0) + cached_val = get_id_list(0, NULL, PT_TID) == 1; + + return cached_val; +} + +/** + * Returns the PID namespace of the tracee + */ +static unsigned int +get_ns(struct tcb *tcp) +{ + if (!tcp->pid_ns) { + int proc_pid = 0; + translate_pid(NULL, tcp->pid, PT_TID, &proc_pid); + + if (proc_pid) + get_ns_hierarchy(proc_pid, &tcp->pid_ns, 1); + } + + return tcp->pid_ns; +} + +/** + * Returns the PID namespace of strace + */ +static unsigned int +get_our_ns(void) +{ + static unsigned int our_ns = 0; + static bool our_ns_initialised = false; + + if (!our_ns_initialised) { + get_ns_hierarchy(0, &our_ns, 1); + our_ns_initialised = true; + } + + return our_ns; +} + +/** + * Returns the cached proc_data struct associated with proc_pid. + * If none found, allocates a new proc_data. + */ +static struct proc_data * +get_or_create_proc_data(int proc_pid) +{ + struct proc_data *pd = (struct proc_data *) (uintptr_t) + trie_get(proc_data_cache, proc_pid); + + if (!pd) { + pd = calloc(1, sizeof(*pd)); + if (!pd) + return NULL; + + pd->proc_pid = proc_pid; + trie_set(proc_data_cache, proc_pid, (uint64_t) (uintptr_t) pd); + } + + return pd; +} + +/** + * Updates the proc_data from /proc + * If the process does not exists, returns false, and frees the proc_data + */ +static bool +update_proc_data(struct proc_data *pd, enum pid_type type) +{ + pd->ns_count = get_ns_hierarchy(pd->proc_pid, + pd->ns_hierarchy, MAX_NS_DEPTH); + if (!pd->ns_count) + goto fail; + + pd->id_count[type] = get_id_list(pd->proc_pid, + pd->id_hierarchy[type], type); + if (!pd->id_count[type]) + goto fail; + + return true; + +fail: + trie_set(proc_data_cache, pd->proc_pid, (uint64_t) (uintptr_t) NULL); + free(pd); + return false; +} + +/** + * Paramters for id translation + */ +struct translate_id_params { + /* The result (output) */ + int result_id; + /* The proc data of the process (output) */ + struct proc_data *pd; + + /* The namespace to be translated from */ + unsigned int from_ns; + /* The id to be translated */ + int from_id; + /* The type of the id */ + enum pid_type type; +}; + +/** + * Translates an id to our namespace, given the proc_pid of the process, + * by reading files in /proc. + * + * @param tip The parameters + * @param proc_pid The proc pid of the process. + * If 0, use the cached values in tip->pd. + */ +static void +translate_id_proc_pid(struct translate_id_params *tip, int proc_pid) +{ + struct proc_data *pd = proc_pid ? + get_or_create_proc_data(proc_pid) : + tip->pd; + + tip->result_id = 0; + tip->pd = NULL; + + if (!pd) + return; + + if (proc_pid && !update_proc_data(pd, tip->type)) + return; + + if (!pd->ns_count || pd->id_count[tip->type] < pd->ns_count) + return; + + int our_ns_id_idx = pd->id_count[tip->type] - pd->ns_count; + + for (int i = 0; i < pd->ns_count; i++) { + if (pd->ns_hierarchy[i] != tip->from_ns) + continue; + + int id_idx = pd->id_count[tip->type] - i - 1; + if (pd->id_hierarchy[tip->type][id_idx] != tip->from_id) + return; + + tip->result_id = pd->id_hierarchy[tip->type][our_ns_id_idx]; + tip->pd = pd; + return; + } +} + +/** + * Translates an id to our namespace, by reading all proc entries in dir. + * + * @param tip The parameters + * @param path The path of the dir to be read. + * @param read_task_dir Whether recurse to "task" subdirectory. + */ +static void +translate_id_dir(struct translate_id_params *tip, const char *path, + bool read_task_dir) +{ + DIR *dir = opendir(path); + if (!dir) { + debug_func_perror_msg("opening dir: %s", path); + return; + } + + while (!tip->result_id) { + errno = 0; + struct_dirent *entry = read_dir(dir); + if (!entry) { + if (errno) + perror_func_msg("readdir"); + + break; + } + + if (entry->d_type != DT_DIR) + continue; + + errno = 0; + long proc_pid = strtol(entry->d_name, NULL, 10); + if (errno) + continue; + if (proc_pid < 1 || proc_pid > INT_MAX) + continue; + + if (read_task_dir) { + char task_dir_path[PATH_MAX + 1]; + xsprintf(task_dir_path, "/proc/%ld/task", proc_pid); + translate_id_dir(tip, task_dir_path, false); + } + + if (tip->result_id) + break; + + translate_id_proc_pid(tip, proc_pid); + } + + closedir(dir); +} + +/** + * Iterator function of the proc_data_cache for id translation. + * If the cache contains the id we are looking for, reads the corresponding + * directory in /proc, and if cache is valid, saves the result. + */ +static void +proc_data_cache_iterator_fn(void* fn_data, uint64_t key, uint64_t val) +{ + struct translate_id_params *tip = (struct translate_id_params *)fn_data; + struct proc_data *pd = (struct proc_data *) (uintptr_t) val; + + if (!pd) + return; + + /* Result already found in an earlier iteration */ + if (tip->result_id) + return; + + /* Translate from cache */ + tip->pd = pd; + translate_id_proc_pid(tip, 0); + if (!tip->result_id) + return; + + /* Now translate from actual data in /proc, to check cache validity */ + translate_id_proc_pid(tip, pd->proc_pid); +} + +int +translate_pid(struct tcb *tcp, int from_id, enum pid_type type, + int *proc_pid_ptr) +{ + if (from_id <= 0 || type < 0 || type >= PT_COUNT) + return 0; + + /* If translation is trivial */ + if ((!tcp || get_ns(tcp) == get_our_ns()) && + (!proc_pid_ptr || is_proc_ours())) { + if (proc_pid_ptr) + *proc_pid_ptr = from_id; + + return from_id; + } + + struct translate_id_params tip = { + .result_id = 0, + .pd = NULL, + .from_ns = tcp ? get_ns(tcp) : get_our_ns(), + .from_id = from_id, + .type = type, + }; + + if (!tip.from_ns) + return 0; + + if (ns_get_parent_enotty) + return 0; + + /* Look for a cached proc_pid for this (from_ns, from_id) pair */ + int cached_proc_pid = get_cached_proc_pid(tip.from_ns, tip.from_id, + tip.type); + if (cached_proc_pid) { + translate_id_proc_pid(&tip, cached_proc_pid); + if (tip.result_id) + goto exit; + } + + /* Iterate through the cache, find potential proc_data */ + trie_iterate_keys(proc_data_cache, 0, pid_max, + proc_data_cache_iterator_fn, &tip); + /* (proc_data_cache_iterator_fn takes care about updating proc_data) */ + if (tip.result_id) + goto exit; + + /* No cache helped, read all entries in /proc */ + translate_id_dir(&tip, "/proc", true); + +exit: + if (tip.pd) { + if (tip.pd->proc_pid) + put_proc_pid(tip.from_ns, tip.from_id, tip.type, + tip.pd->proc_pid); + + if (proc_pid_ptr) + *proc_pid_ptr = tip.pd->proc_pid; + } + + return tip.result_id; +} + +int +get_proc_pid(struct tcb *tcp) +{ + int proc_pid = 0; + translate_pid(NULL, tcp->pid, PT_TID, &proc_pid); + return proc_pid; +} + +static void +printpid_translation(struct tcb *tcp, int pid, enum pid_type type) +{ + if (!pidns_translation) + return; + + int strace_pid = translate_pid(tcp, pid, type, NULL); + if (strace_pid && strace_pid != pid) + tprintf_comment("%d in strace's PID NS", strace_pid); +} + +void +printpid(struct tcb *tcp, int pid, enum pid_type type) +{ + tprintf("%d", pid); + printpid_translation(tcp, pid, type); +} + +void +printpid_tgid_pgid(struct tcb *tcp, int pid) +{ + tprintf("%d", pid); + if (pid > 0) + printpid_translation(tcp, pid, PT_TGID); + else if (pid < -1) + printpid_translation(tcp, -pid, PT_PGID); +} diff --git a/strace.1.in b/strace.1.in index 3b21caec..83776e88 100644 --- a/strace.1.in +++ b/strace.1.in @@ -1075,6 +1075,10 @@ Print all available information associated with file descritors: protocol-specific information associated with socket file descriptors, block/character device number associated with device file descriptors, and PIDs asociated with pidfd file descriptors. +.TP +.B \-\-pidns\-translation +If strace and tracee are in different PID namespaces, print PIDs in +strace's namespace, too. .SS Statistics .TP 12 .B \-c diff --git a/strace.c b/strace.c index 4c96a98b..249533ea 100644 --- a/strace.c +++ b/strace.c @@ -133,6 +133,8 @@ static unsigned int daemonized_tracer; static int post_attach_sigstop = TCB_IGNORE_ONE_SIGSTOP; #define use_seize (post_attach_sigstop == 0) +unsigned int pidns_translation; + static bool detach_on_execve; static int exit_code; @@ -1998,6 +2000,8 @@ init(int argc, char *argv[]) os_release = get_os_release(); + pidns_init(); + shared_log = stderr; set_sortby(DEFAULT_SORTBY); set_personality(DEFAULT_PERSONALITY); @@ -2022,6 +2026,7 @@ init(int argc, char *argv[]) GETOPT_FOLLOWFORKS, GETOPT_OUTPUT_SEPARATELY, GETOPT_TS, + GETOPT_PIDNS_TRANSLATION, GETOPT_QUAL_TRACE, GETOPT_QUAL_ABBREV, @@ -2072,6 +2077,7 @@ init(int argc, char *argv[]) { "summary-wall-clock", no_argument, 0, 'w' }, { "strings-in-hex", optional_argument, 0, GETOPT_HEX_STR }, { "const-print-style", required_argument, 0, 'X' }, + { "pidns-translation", no_argument , 0, GETOPT_PIDNS_TRANSLATION }, { "successful-only", no_argument, 0, 'z' }, { "failed-only", no_argument, 0, 'Z' }, { "failing-only", no_argument, 0, 'Z' }, @@ -2285,6 +2291,9 @@ init(int argc, char *argv[]) case 'y': yflag_short++; break; + case GETOPT_PIDNS_TRANSLATION: + pidns_translation++; + break; case 'z': clear_number_set_array(status_set, 1); add_number_to_set(STATUS_SUCCESSFUL, status_set); diff --git a/syscall.c b/syscall.c index bcc87025..0f4bab6d 100644 --- a/syscall.c +++ b/syscall.c @@ -937,6 +937,21 @@ syscall_exiting_trace(struct tcb *tcp, struct timespec *ts, int res) tprintf("= %" PRI_kld, tcp->u_rval); } break; + case RVAL_TID: + case RVAL_SID: + case RVAL_TGID: + case RVAL_PGID: { + #define _(_t) [RVAL_##_t - RVAL_TID] = PT_##_t + static const enum pid_type types[] = { + _(TID), _(SID), _(TGID), _(PGID), + }; + #undef _ + + tprints("= "); + printpid(tcp, tcp->u_rval, + types[(sys_res & RVAL_MASK) - RVAL_TID]); + break; + } default: error_msg("invalid rval format"); break; diff --git a/trie.c b/trie.c new file mode 100644 index 00000000..bcb0d791 --- /dev/null +++ b/trie.c @@ -0,0 +1,290 @@ +/* + * Simple trie implementation for key-value mapping storage + * + * Copyright (c) 2020 ?kos Uzonyi + * All rights reserved. + * + * SPDX-License-Identifier: LGPL-2.1-or-later + */ + +#ifdef HAVE_CONFIG_H +# include "config.h" +#endif + +#include +#include + +#include "trie.h" + +static const uint8_t ptr_sz_lg = (sizeof(void *) == 8 ? 6 : 5); + +/** + * Returns lg2 of node size in bits for the specific level of the trie. + */ +static uint8_t +trie_get_node_size(struct trie *t, uint8_t depth) +{ + /* Last level contains data and we allow it having a different size */ + if (depth == t->max_depth) + return t->data_block_key_bits + t->item_size_lg; + /* Last level of the tree can be smaller */ + if (depth == t->max_depth - 1) + return (t->key_size - t->data_block_key_bits - 1) % + t->node_key_bits + 1 + ptr_sz_lg; + + return t->node_key_bits + ptr_sz_lg; +} + +/** + * Provides starting offset of bits in key corresponding to the node index + * at the specific level. + */ +static uint8_t +trie_get_node_bit_offs(struct trie *t, uint8_t depth) +{ + uint8_t offs; + + if (depth == t->max_depth) + return 0; + + offs = t->data_block_key_bits; + + if (depth == t->max_depth - 1) + return offs; + + /* data_block_size + remainder */ + offs += trie_get_node_size(t, t->max_depth - 1) - ptr_sz_lg; + offs += (t->max_depth - depth - 2) * t->node_key_bits; + + return offs; +} + +struct trie * +trie_create(uint8_t key_size, uint8_t item_size_lg, uint8_t node_key_bits, + uint8_t data_block_key_bits, uint64_t empty_value) +{ + if (item_size_lg > 6) + return NULL; + if (key_size > 64) + return NULL; + if (node_key_bits < 1) + return NULL; + if (data_block_key_bits < 1 || data_block_key_bits > key_size) + return NULL; + + struct trie *t = malloc(sizeof(*t)); + if (!t) + return NULL; + + t->empty_value = empty_value; + t->data = NULL; + t->item_size_lg = item_size_lg; + t->node_key_bits = node_key_bits; + t->data_block_key_bits = data_block_key_bits; + t->key_size = key_size; + t->max_depth = (key_size - data_block_key_bits + node_key_bits - 1) + / t->node_key_bits; + + if (item_size_lg != 6) + t->empty_value &= (((uint64_t) 1 << (1 << t->item_size_lg)) - 1); + + return t; +} + +static void * +trie_create_data_block(struct trie *t) +{ + uint64_t fill_value = t->empty_value; + for (int i = 1; i < 1 << (6 - t->item_size_lg); i++) { + fill_value <<= (1 << t->item_size_lg); + fill_value |= t->empty_value; + } + + uint8_t sz = t->data_block_key_bits + t->item_size_lg; + if (sz < 6) + sz = 6; + + size_t count = 1 << (sz - 6); + uint64_t *data_block = calloc(count, 8); + if (!data_block) + return NULL; + + for (size_t i = 0; i < count; i++) + data_block[i] = fill_value; + + return data_block; +} + +static uint64_t * +trie_get_node(struct trie *t, uint64_t key, bool auto_create) +{ + void **cur_node = &(t->data); + + if (t->key_size < 64 && key > (uint64_t) 1 << t->key_size) + return NULL; + + for (uint8_t cur_depth = 0; cur_depth <= t->max_depth; cur_depth++) { + uint8_t offs = trie_get_node_bit_offs(t, cur_depth); + uint8_t sz = trie_get_node_size(t, cur_depth); + + if (!*cur_node) { + if (!auto_create) + return NULL; + + if (cur_depth == t->max_depth) + *cur_node = trie_create_data_block(t); + else + *cur_node = calloc(1 << sz, 1); + + if (!*cur_node) { + fprintf(stderr, "Out of memory"); + exit(1); + } + } + + if (cur_depth == t->max_depth) + break; + + size_t pos = (key >> offs) & ((1 << (sz - ptr_sz_lg)) - 1); + cur_node = (((void **) (*cur_node)) + pos); + } + + return (uint64_t *) (*cur_node); +} + +static void +trie_data_block_calc_pos(struct trie *t, uint64_t key, + uint64_t *pos, uint64_t *mask, uint64_t *offs) +{ + uint64_t key_mask; + + key_mask = (1 << t->data_block_key_bits) - 1; + *pos = (key & key_mask) >> (6 - t->item_size_lg); + + if (t->item_size_lg == 6) { + *offs = 0; + *mask = -1; + return; + } + + key_mask = (1 << (6 - t->item_size_lg)) - 1; + *offs = (key & key_mask) * (1 << t->item_size_lg); + + *mask = (((uint64_t) 1 << (1 << t->item_size_lg)) - 1) << *offs; +} + +bool +trie_set(struct trie *t, uint64_t key, uint64_t val) +{ + uint64_t *data = trie_get_node(t, key, true); + if (!data) + return false; + + uint64_t pos, mask, offs; + trie_data_block_calc_pos(t, key, &pos, &mask, &offs); + + data[pos] &= ~mask; + data[pos] |= (val << offs) & mask; + + return true; +} + +static uint64_t +trie_data_block_get(struct trie *t, uint64_t *data, uint64_t key) +{ + if (!data) + return t->empty_value; + + uint64_t pos, mask, offs; + trie_data_block_calc_pos(t, key, &pos, &mask, &offs); + + return (data[pos] & mask) >> offs; +} + +uint64_t +trie_get(struct trie *b, uint64_t key) +{ + return trie_data_block_get(b, trie_get_node(b, key, false), key); +} + +static uint64_t +trie_iterate_keys_node(struct trie *t, + trie_iterate_fn fn, void *fn_data, + void *node, uint64_t start, uint64_t end, + uint8_t depth) +{ + if (start > end || !node) + return 0; + + if (depth == t->max_depth) { + for (uint64_t i = start; i <= end; i++) + fn(fn_data, i, trie_data_block_get(t, + (uint64_t *) node, i)); + + return end - start + 1; + } + + uint8_t parent_node_bit_off = depth == 0 ? + t->key_size : + trie_get_node_bit_offs(t, depth - 1); + + uint64_t first_key_in_node = start & + (uint64_t) -1 << parent_node_bit_off; + + uint8_t node_bit_off = trie_get_node_bit_offs(t, depth); + uint8_t node_key_bits = parent_node_bit_off - node_bit_off; + uint64_t mask = ((uint64_t) 1 << (node_key_bits)) - 1; + uint64_t start_index = (start >> node_bit_off) & mask; + uint64_t end_index = (end >> node_bit_off) & mask; + uint64_t child_key_count = (uint64_t) 1 << node_bit_off; + + uint64_t count = 0; + + for (uint64_t i = start_index; i <= end_index; i++) { + uint64_t child_start = first_key_in_node + i * child_key_count; + uint64_t child_end = first_key_in_node + + (i + 1) * child_key_count - 1; + + if (child_start < start) + child_start = start; + if (child_end > end) + child_end = end; + + count += trie_iterate_keys_node(t, fn, fn_data, + ((void **) node)[i], child_start, child_end, + depth + 1); + } + + return count; +} + +uint64_t trie_iterate_keys(struct trie *t, uint64_t start, uint64_t end, + trie_iterate_fn fn, void *fn_data) +{ + return trie_iterate_keys_node(t, fn, fn_data, t->data, + start, end, 0); +} + +static void +trie_free_node(struct trie *t, void *node, uint8_t depth) +{ + if (!node) + return; + + if (depth >= t->max_depth) + goto free_node; + + size_t sz = 1 << (trie_get_node_size(t, depth) - ptr_sz_lg); + for (size_t i = 0; i < sz; i++) + trie_free_node(t, ((void **) node)[i], depth + 1); + +free_node: + free(node); +} + +void +trie_free(struct trie *t) +{ + trie_free_node(t, t->data, 0); + free(t); +} diff --git a/trie.h b/trie.h new file mode 100644 index 00000000..deb87a54 --- /dev/null +++ b/trie.h @@ -0,0 +1,92 @@ +/* + * Simple trie interface + * + * Copyright (c) 2020 ?kos Uzonyi + * All rights reserved. + * + * SPDX-License-Identifier: LGPL-2.1-or-later + */ + +#ifndef STRACE_TRIE_H +#define STRACE_TRIE_H + +#include +#include + +/** + * Trie control structure. + * Trie implemented here has the following properties: + * * It allows storing values of the same size, the size can vary from 1 bit to + * 64 bit values (only power of 2 sizes are allowed). + * * The key can be up to 64 bits in size. + * * It has separate configuration for node size and data block size. + * + * How bits of key are used for different node levels: + * + * highest bits lowest bits + * | node_key_bits | node_key_bits | ... | | data_block_key_bits | + * \_________________________________________________________________________/ + * key_size + * + * So, the remainder is used on the lowest non-data node level. + * + * As of now, it doesn't implement any mechanisms for resizing/changing key + * size. De-fragmentation is also unsupported currently. + */ +struct trie { + /** Return value of trie_get if key is not found */ + uint64_t empty_value; + + /** Pointer to root node */ + void *data; + + /** Key size in bits (0..64). */ + uint8_t key_size; + + /** + * Size of the stored values in log2 bits (0..6). + * (6: 64 bit values, 5: 32 bit values, ...) + */ + uint8_t item_size_lg; + + /** + * Number of bits in the key that make a symbol for a node. + * (equals to log2 of the child count of the node) + */ + uint8_t node_key_bits; + + /** + * Number of bits in the key that make a symbol for the data block (leaf). + * (equals to log2 of the value count stored in a data block) + */ + uint8_t data_block_key_bits; + + /** The depth of the data block. Calculated from the values above */ + uint8_t max_depth; +}; + +struct trie* trie_create(uint8_t key_size, uint8_t item_size_lg, + uint8_t node_key_bits, uint8_t data_block_key_bits, + uint64_t empty_value); + +bool trie_set(struct trie *t, uint64_t key, uint64_t val); +uint64_t trie_get(struct trie *t, uint64_t key); + +typedef void (*trie_iterate_fn)(void *data, uint64_t key, uint64_t val); + +/** + * Calls trie_iterate_fn for each key-value pair where + * key is inside the [start, end] interval (inclusive). + * + * @param t The trie. + * @param start The start of the key interval (inclusive). + * @param end The end of the key interval (inclusive). + * @param fn The function to be called. + * @param fn_data The value to be passed to fn. + */ +uint64_t trie_iterate_keys(struct trie *t, uint64_t start, uint64_t end, + trie_iterate_fn fn, void *fn_data); + +void trie_free(struct trie *t); + +#endif /* !STRACE_TRIE_H */ -- 2.28.0 From uzonyi.akos at gmail.com Sun Aug 16 22:18:46 2020 From: uzonyi.akos at gmail.com (=?UTF-8?q?=C3=81kos=20Uzonyi?=) Date: Mon, 17 Aug 2020 00:18:46 +0200 Subject: [RFC PATCH v9 3/8] Use get_proc_pid for /proc paths In-Reply-To: <20200816221851.200031-1-uzonyi.akos@gmail.com> References: <20200816221851.200031-1-uzonyi.akos@gmail.com> Message-ID: <20200816221851.200031-4-uzonyi.akos@gmail.com> * mmap_cache.c (mmap_cache_rebuild_if_invalid): Use proc pid instead of tcp->pid for /proc path. * util.c (getfdproto): Likewise. (pidfd_get_pid): Likewise. * pathtrace.c (getfdpath_pid): Likewise. * strace.c (attach_tcb): Likewise. --- mmap_cache.c | 2 +- pathtrace.c | 7 ++++++- strace.c | 2 +- util.c | 9 +++++++-- 4 files changed, 15 insertions(+), 5 deletions(-) diff --git a/mmap_cache.c b/mmap_cache.c index 89c62254..9825df26 100644 --- a/mmap_cache.c +++ b/mmap_cache.c @@ -84,7 +84,7 @@ mmap_cache_rebuild_if_invalid(struct tcb *tcp, const char *caller) return MMAP_CACHE_REBUILD_READY; char filename[sizeof("/proc/4294967296/maps")]; - xsprintf(filename, "/proc/%u/maps", tcp->pid); + xsprintf(filename, "/proc/%u/maps", get_proc_pid(tcp)); FILE *fp = fopen_stream(filename, "r"); if (!fp) { diff --git a/pathtrace.c b/pathtrace.c index 5b60762b..afed770a 100644 --- a/pathtrace.c +++ b/pathtrace.c @@ -87,7 +87,12 @@ getfdpath_pid(pid_t pid, int fd, char *buf, unsigned bufsize) if (fd < 0) return -1; - xsprintf(linkpath, "/proc/%u/fd/%u", pid, fd); + int proc_pid = 0; + translate_pid(NULL, pid, PT_TID, &proc_pid); + if (!proc_pid) + return -1; + + xsprintf(linkpath, "/proc/%u/fd/%u", proc_pid, fd); n = readlink(linkpath, buf, bufsize - 1); /* * NB: if buf is too small, readlink doesn't fail, diff --git a/strace.c b/strace.c index 249533ea..ef23f08f 100644 --- a/strace.c +++ b/strace.c @@ -1196,7 +1196,7 @@ attach_tcb(struct tcb *const tcp) unsigned int ntid = 0, nerr = 0; if (followfork && tcp->pid != strace_child && - xsprintf(procdir, task_path, tcp->pid) > 0 && + xsprintf(procdir, task_path, get_proc_pid(tcp)) > 0 && (dir = opendir(procdir)) != NULL) { struct_dirent *de; diff --git a/util.c b/util.c index 2568021e..481144bf 100644 --- a/util.c +++ b/util.c @@ -501,7 +501,7 @@ getfdproto(struct tcb *tcp, int fd) if (fd < 0) return SOCK_PROTO_UNKNOWN; - xsprintf(path, "/proc/%u/fd/%u", tcp->pid, fd); + xsprintf(path, "/proc/%u/fd/%u", get_proc_pid(tcp), fd); r = getxattr(path, "system.sockprotoname", buf, bufsize - 1); if (r <= 0) return SOCK_PROTO_UNKNOWN; @@ -582,8 +582,13 @@ printdev(struct tcb *tcp, int fd, const char *path) pid_t pidfd_get_pid(pid_t pid_of_fd, int fd) { + int proc_pid = 0; + translate_pid(NULL, pid_of_fd, PT_TID, &proc_pid); + if (!proc_pid) + return -1; + char fdi_path[sizeof("/proc/%u/fdinfo/%u") + 2 * sizeof(int) * 3]; - xsprintf(fdi_path, "/proc/%u/fdinfo/%u", pid_of_fd, fd); + xsprintf(fdi_path, "/proc/%u/fdinfo/%u", proc_pid, fd); FILE *f = fopen_stream(fdi_path, "r"); if (!f) -- 2.28.0 From uzonyi.akos at gmail.com Sun Aug 16 22:18:45 2020 From: uzonyi.akos at gmail.com (=?UTF-8?q?=C3=81kos=20Uzonyi?=) Date: Mon, 17 Aug 2020 00:18:45 +0200 Subject: [RFC PATCH v9 2/8] Use printpid in decoders In-Reply-To: <20200816221851.200031-1-uzonyi.akos@gmail.com> References: <20200816221851.200031-1-uzonyi.akos@gmail.com> Message-ID: <20200816221851.200031-3-uzonyi.akos@gmail.com> * getpid.c: New file. * Makefile.am (libstrace_a_SOURCES): Add it. * linux/dummy.h (sys_getpid, sys_getppid, sys_gettid, sys_setpgid, sys_setpgrp): Remove. * util.c (printfd_pid_tracee_ns): Implement using translate_pid. * defs.h (printnum_pid): New function definition. (printfd_pid_tracee_ns): Update documentation * util.c: (printnum_pid): New function. * print_fields.h (PRINT_FIELD_TID): New macro. (PRINT_FIELD_TGID): Likewise. (PRINT_FIELD_PGID): Likewise. (PRINT_FIELD_SID): Likewise. * affinity.c: Print PIDs with printpid. * block.c: Likewise. * bpf.c: Likewise. * capability.c: Likewise. * clone.c: Likewise. * fcntl.c: Likewise. * get_robust_list.c: Likewise. * ioprio.c: Likewise. * kcmp.c: Likewise. * msghdr.c: Likewise. * net.c: Likewise. * netlink.c: Likewise. * numa.c: Likewise. * pidfd_open.c: Likewise. * printsiginfo.c: Likewise. * process.c: Likewise. * process_vm.c: Likewise. * resource.c: Likewise. * sched.c: Likewise. * signal.c: Likewise. * sockaddr.c: Likewise. * wait.c: Likewise. * kcmp.c (SYS_FUNC(kcmp)): Fix KCMP_FILE pid arguments. * tests/kcmp.c (printpidfd): Print path if VERBOSE_FD. (main): Use our real pid if real fds are used. --- Makefile.am | 1 + affinity.c | 6 ++++-- block.c | 2 +- bpf.c | 2 +- capability.c | 4 +++- clone.c | 14 +++++++------- defs.h | 5 ++++- fcntl.c | 24 ++++++++++++++++++++++-- get_robust_list.c | 3 ++- getpid.c | 46 ++++++++++++++++++++++++++++++++++++++++++++++ ioprio.c | 26 ++++++++++++++++++++++---- ipc_shmctl.c | 4 ++-- kcmp.c | 5 ++++- linux/dummy.h | 8 +------- msghdr.c | 2 +- net.c | 2 +- netlink.c | 5 +++-- numa.c | 6 ++++-- pidfd_open.c | 2 +- print_fields.h | 24 ++++++++++++++++++++++++ printsiginfo.c | 2 +- process.c | 3 ++- process_vm.c | 6 ++++-- resource.c | 27 ++++++++++++++++++++++++--- sched.c | 25 ++++++++++++++++--------- signal.c | 21 +++++++++++++++------ sockaddr.c | 2 +- tests/kcmp.c | 25 ++++++++++++++++++++++--- util.c | 22 +++++++++++++++------- wait.c | 36 ++++++++++++++++++++++++------------ 30 files changed, 278 insertions(+), 82 deletions(-) create mode 100644 getpid.c diff --git a/Makefile.am b/Makefile.am index 73c22035..15fcd9a6 100644 --- a/Makefile.am +++ b/Makefile.am @@ -135,6 +135,7 @@ libstrace_a_SOURCES = \ getcpu.c \ getcwd.c \ getpagesize.c \ + getpid.c \ getrandom.c \ hdio.c \ hostname.c \ diff --git a/affinity.c b/affinity.c index eb3158b7..f9893adb 100644 --- a/affinity.c +++ b/affinity.c @@ -82,7 +82,8 @@ SYS_FUNC(sched_setaffinity) const int pid = tcp->u_arg[0]; const unsigned int len = tcp->u_arg[1]; - tprintf("%d, %u, ", pid, len); + printpid(tcp, pid, PT_TGID); + tprintf(", %u, ", len); print_affinitylist(tcp, tcp->u_arg[2], len); return RVAL_DECODED; @@ -94,7 +95,8 @@ SYS_FUNC(sched_getaffinity) const unsigned int len = tcp->u_arg[1]; if (entering(tcp)) { - tprintf("%d, %u, ", pid, len); + printpid(tcp, pid, PT_TGID); + tprintf(", %u, ", len); } else { print_affinitylist(tcp, tcp->u_arg[2], tcp->u_rval); } diff --git a/block.c b/block.c index b527ef43..783a4b5a 100644 --- a/block.c +++ b/block.c @@ -179,7 +179,7 @@ MPERS_PRINTER_DECL(int, block_ioctl, struct tcb *const tcp, PRINT_FIELD_U(", ", buts, buf_nr); PRINT_FIELD_U(", ", buts, start_lba); PRINT_FIELD_U(", ", buts, end_lba); - PRINT_FIELD_D(", ", buts, pid); + PRINT_FIELD_TGID(", ", buts, pid, tcp); return 0; } else { struct_blk_user_trace_setup buts; diff --git a/bpf.c b/bpf.c index af830053..0ec33ba4 100644 --- a/bpf.c +++ b/bpf.c @@ -927,7 +927,7 @@ BEGIN_BPF_CMD_DECODER(BPF_TASK_FD_QUERY) if (entering(tcp)) { set_tcb_priv_ulong(tcp, attr.buf_len); - PRINT_FIELD_D("{task_fd_query={", attr, pid); + PRINT_FIELD_TGID("{task_fd_query={", attr, pid, tcp); PRINT_FIELD_FD(", ", attr, fd, tcp); PRINT_FIELD_U(", ", attr, flags); PRINT_FIELD_U(", ", attr, buf_len); diff --git a/capability.c b/capability.c index 0e763ee1..812fb435 100644 --- a/capability.c +++ b/capability.c @@ -70,7 +70,9 @@ print_cap_header(struct tcb *const tcp, const kernel_ulong_t addr, tprints("{version="); printxval(cap_version, h->version, "_LINUX_CAPABILITY_VERSION_???"); - tprintf(", pid=%d}", h->pid); + tprints(", pid="); + printpid(tcp, h->pid, PT_TGID); + tprints("}"); } static void diff --git a/clone.c b/clone.c index 487c5c23..45f24065 100644 --- a/clone.c +++ b/clone.c @@ -114,14 +114,14 @@ SYS_FUNC(clone) */ if ((flags & (CLONE_PARENT_SETTID|CLONE_PIDFD|CLONE_CHILD_SETTID |CLONE_CHILD_CLEARTID|CLONE_SETTLS)) == 0) - return RVAL_DECODED; + return RVAL_DECODED | RVAL_TID; } else { if (flags & (CLONE_PARENT_SETTID|CLONE_PIDFD)) { kernel_ulong_t addr = tcp->u_arg[ARG_PTID]; tprints(", parent_tid="); if (flags & CLONE_PARENT_SETTID) - printnum_int(tcp, addr, "%u"); + printnum_pid(tcp, addr, PT_TID); else printnum_fd(tcp, addr); } @@ -134,7 +134,7 @@ SYS_FUNC(clone) printaddr(tcp->u_arg[ARG_CTID]); } } - return 0; + return RVAL_TID; } @@ -229,7 +229,7 @@ SYS_FUNC(clone3) if ((arg.flags & (CLONE_PIDFD | CLONE_PARENT_SETTID)) || (size > fetch_size)) - return 0; + return RVAL_TID; goto out; } @@ -256,7 +256,7 @@ SYS_FUNC(clone3) if (arg.flags & CLONE_PARENT_SETTID) { tprintf("%sparent_tid=", pfx); - printnum_int(tcp, arg.parent_tid, "%d"); /* TID */ + printnum_pid(tcp, arg.parent_tid, PT_TID); pfx = ", "; } @@ -279,7 +279,7 @@ SYS_FUNC(clone3) out: tprintf(", %" PRI_klu, size); - return RVAL_DECODED; + return RVAL_DECODED | RVAL_TID; } @@ -300,5 +300,5 @@ SYS_FUNC(unshare) SYS_FUNC(fork) { - return RVAL_DECODED; + return RVAL_DECODED | RVAL_TGID; } diff --git a/defs.h b/defs.h index 511a92a2..328c1940 100644 --- a/defs.h +++ b/defs.h @@ -1100,7 +1100,7 @@ printfd(struct tcb *tcp, int fd) /** * Print file descriptor fd owned by process with ID pid (from the PID NS - * of the tracee the descriptor tcp). This is a stub. + * of the tracee). */ extern void printfd_pid_tracee_ns(struct tcb *tcp, pid_t pid, int fd); @@ -1561,6 +1561,9 @@ DECL_PRINTNUM_ADDR(int64); extern bool printnum_fd(struct tcb *, kernel_ulong_t addr); +extern bool +printnum_pid(struct tcb *const tcp, const kernel_ulong_t addr, enum pid_type type); + static inline bool printnum_slong(struct tcb *tcp, kernel_ulong_t addr) { diff --git a/fcntl.c b/fcntl.c index 6fcd5dac..5c630a06 100644 --- a/fcntl.c +++ b/fcntl.c @@ -28,7 +28,7 @@ print_struct_flock64(struct tcb *const tcp, const struct_kernel_flock64 *fl, con PRINT_FIELD_D(", ", *fl, l_start); PRINT_FIELD_D(", ", *fl, l_len); if (getlk) - PRINT_FIELD_D(", ", *fl, l_pid); + PRINT_FIELD_TGID(", ", *fl, l_pid, tcp); tprints("}"); } @@ -59,7 +59,22 @@ print_f_owner_ex(struct tcb *const tcp, const kernel_ulong_t addr) return; PRINT_FIELD_XVAL("{", owner, type, f_owner_types, "F_OWNER_???"); - PRINT_FIELD_D(", ", owner, pid); + + enum pid_type pid_type = PT_NONE; + switch (owner.type) + { + case F_OWNER_TID: + pid_type = PT_TID; + break; + case F_OWNER_PID: + pid_type = PT_TGID; + break; + case F_OWNER_PGRP: + pid_type = PT_PGID; + break; + } + tprints(", pid="); + printpid(tcp, owner.pid, pid_type); tprints("}"); } @@ -74,6 +89,9 @@ print_fcntl(struct tcb *tcp) printflags(fdflags, tcp->u_arg[2], "FD_???"); break; case F_SETOWN: + tprints(", "); + printpid_tgid_pgid(tcp, tcp->u_arg[2]); + break; case F_SETPIPE_SZ: tprintf(", %" PRI_kld, tcp->u_arg[2]); break; @@ -116,6 +134,8 @@ print_fcntl(struct tcb *tcp) printsignal(tcp->u_arg[2]); break; case F_GETOWN: + return RVAL_DECODED | + ((int) tcp->u_rval < 0 ? RVAL_PGID : RVAL_TGID); case F_GETPIPE_SZ: break; case F_GETFD: diff --git a/get_robust_list.c b/get_robust_list.c index b5aebaff..81aba2dd 100644 --- a/get_robust_list.c +++ b/get_robust_list.c @@ -10,7 +10,8 @@ SYS_FUNC(get_robust_list) { if (entering(tcp)) { - tprintf("%d, ", (int) tcp->u_arg[0]); + printpid(tcp, tcp->u_arg[0], PT_TID); + tprints(", "); } else { printnum_ptr(tcp, tcp->u_arg[1]); tprints(", "); diff --git a/getpid.c b/getpid.c new file mode 100644 index 00000000..5e9a1a29 --- /dev/null +++ b/getpid.c @@ -0,0 +1,46 @@ +/* + * Copyright (c) 2020 ?kos Uzonyi + * All rights reserved. + * + * SPDX-License-Identifier: LGPL-2.1-or-later + */ + +#include "defs.h" + +SYS_FUNC(getpid) +{ + return RVAL_DECODED | RVAL_TGID; +} + +SYS_FUNC(gettid) +{ + return RVAL_DECODED | RVAL_TID; +} + +SYS_FUNC(getpgrp) +{ + return RVAL_DECODED | RVAL_PGID; +} + +SYS_FUNC(getpgid) +{ + printpid(tcp, tcp->u_arg[0], PT_TGID); + + return RVAL_DECODED | RVAL_PGID; +} + +SYS_FUNC(getsid) +{ + printpid(tcp, tcp->u_arg[0], PT_TGID); + + return RVAL_DECODED | RVAL_SID; +} + +SYS_FUNC(setpgid) +{ + printpid(tcp, tcp->u_arg[0], PT_TGID); + tprints(", "); + printpid(tcp, tcp->u_arg[1], PT_PGID); + + return RVAL_DECODED; +} diff --git a/ioprio.c b/ioprio.c index 873c8ce5..149ef3fd 100644 --- a/ioprio.c +++ b/ioprio.c @@ -49,13 +49,30 @@ print_ioprio(unsigned int ioprio) ? tprints_comment : tprints)(str); } +static void +ioprio_print_who(struct tcb *tcp, int which, int who) +{ + switch (which) + { + case IOPRIO_WHO_PROCESS: + printpid(tcp, who, PT_TGID); + break; + case IOPRIO_WHO_PGRP: + printpid(tcp, who, PT_PGID); + break; + default: + tprintf("%d", who); + break; + } +} + SYS_FUNC(ioprio_get) { if (entering(tcp)) { /* int which */ printxval(ioprio_who, tcp->u_arg[0], "IOPRIO_WHO_???"); - /* int who */ - tprintf(", %d", (int) tcp->u_arg[1]); + tprints(", "); + ioprio_print_who(tcp, tcp->u_arg[0], tcp->u_arg[1]); return 0; } else { if (syserror(tcp)) @@ -72,8 +89,9 @@ SYS_FUNC(ioprio_set) { /* int which */ printxval(ioprio_who, tcp->u_arg[0], "IOPRIO_WHO_???"); - /* int who */ - tprintf(", %d, ", (int) tcp->u_arg[1]); + tprints(", "); + ioprio_print_who(tcp, tcp->u_arg[0], tcp->u_arg[1]); + tprints(", "); /* int ioprio */ if (xlat_verbose(xlat_verbosity) != XLAT_STYLE_ABBREV) tprintf("%d", (int) tcp->u_arg[2]); diff --git a/ipc_shmctl.c b/ipc_shmctl.c index 8c9e1e7a..1f99f02a 100644 --- a/ipc_shmctl.c +++ b/ipc_shmctl.c @@ -53,8 +53,8 @@ print_shmid_ds(struct tcb *const tcp, const kernel_ulong_t addr, int cmd) PRINT_FIELD_UID(", ", shmid_ds.shm_perm, cgid); tprints("}"); tprintf(", shm_segsz=%u", (unsigned) shmid_ds.shm_segsz); - PRINT_FIELD_D(", ", shmid_ds, shm_cpid); - PRINT_FIELD_D(", ", shmid_ds, shm_lpid); + PRINT_FIELD_TGID(", ", shmid_ds, shm_cpid, tcp); + PRINT_FIELD_TGID(", ", shmid_ds, shm_lpid, tcp); tprintf(", shm_nattch=%u", (unsigned) shmid_ds.shm_nattch); tprintf(", shm_atime=%u", (unsigned) shmid_ds.shm_atime); tprintf(", shm_dtime=%u", (unsigned) shmid_ds.shm_dtime); diff --git a/kcmp.c b/kcmp.c index 62115555..a5e1cdce 100644 --- a/kcmp.c +++ b/kcmp.c @@ -30,7 +30,10 @@ SYS_FUNC(kcmp) kernel_ulong_t idx1 = tcp->u_arg[3]; kernel_ulong_t idx2 = tcp->u_arg[4]; - tprintf("%d, %d, ", pid1, pid2); + printpid(tcp, pid1, PT_TGID); + tprints(", "); + printpid(tcp, pid2, PT_TGID); + tprints(", "); printxval(kcmp_types, type, "KCMP_???"); switch (type) { diff --git a/linux/dummy.h b/linux/dummy.h index 2f859a60..ca0d2f0c 100644 --- a/linux/dummy.h +++ b/linux/dummy.h @@ -53,6 +53,7 @@ # define sys_getgid sys_getuid # define sys_getgid16 sys_getuid16 # define sys_getpeername sys_getsockname +# define sys_getppid sys_getpid # define sys_getresgid sys_getresuid # define sys_getresgid16 sys_getresuid16 # define sys_lstat sys_stat @@ -87,10 +88,6 @@ # define sys_vfork sys_fork /* printargs does the right thing */ -# define sys_getpgrp printargs -# define sys_getpid printargs -# define sys_getppid printargs -# define sys_gettid printargs # define sys_idle printargs # define sys_munlockall printargs # define sys_pause printargs @@ -108,10 +105,7 @@ /* printargs_d does the right thing */ # define sys_exit printargs_d -# define sys_getpgid printargs_d -# define sys_getsid printargs_d # define sys_nice printargs_d -# define sys_setpgid printargs_d # define sys_setpgrp printargs_d # define sys_timer_delete printargs_d # define sys_timer_getoverrun printargs_d diff --git a/msghdr.c b/msghdr.c index ef6dc24b..170b8e51 100644 --- a/msghdr.c +++ b/msghdr.c @@ -69,7 +69,7 @@ print_scm_creds(struct tcb *tcp, const void *cmsg_data, { const struct ucred *uc = cmsg_data; - PRINT_FIELD_D("{", *uc, pid); + PRINT_FIELD_TGID("{", *uc, pid, tcp); PRINT_FIELD_UID(", ", *uc, uid); PRINT_FIELD_UID(", ", *uc, gid); tprints("}"); diff --git a/net.c b/net.c index fa4638e7..2099f0ac 100644 --- a/net.c +++ b/net.c @@ -601,7 +601,7 @@ print_get_ucred(struct tcb *const tcp, const kernel_ulong_t addr, if (umoven_or_printaddr(tcp, addr, len, &uc)) return; - PRINT_FIELD_LEN("{", uc, pid, len, PRINT_FIELD_D); + PRINT_FIELD_LEN("{", uc, pid, len, PRINT_FIELD_TGID, tcp); PRINT_FIELD_LEN(", ", uc, uid, len, PRINT_FIELD_UID); PRINT_FIELD_LEN(", ", uc, gid, len, PRINT_FIELD_UID); tprints("}"); diff --git a/netlink.c b/netlink.c index 88d864a9..cb29033a 100644 --- a/netlink.c +++ b/netlink.c @@ -446,8 +446,9 @@ print_nlmsghdr(struct tcb *tcp, decode_nlmsg_flags(nlmsghdr->nlmsg_flags, nlmsghdr->nlmsg_type, family); - tprintf(", seq=%u, pid=%d}", nlmsghdr->nlmsg_seq, - nlmsghdr->nlmsg_pid); + tprintf(", seq=%u, pid=", nlmsghdr->nlmsg_seq); + printpid(tcp, nlmsghdr->nlmsg_pid, PT_TGID); + tprints("}"); } static bool diff --git a/numa.c b/numa.c index cc7a7cc6..f7a58266 100644 --- a/numa.c +++ b/numa.c @@ -44,7 +44,8 @@ print_nodemask(struct tcb *const tcp, const kernel_ulong_t addr, SYS_FUNC(migrate_pages) { - tprintf("%d, %" PRI_klu ", ", (int) tcp->u_arg[0], tcp->u_arg[1]); + printpid(tcp, tcp->u_arg[0], PT_TGID); + tprintf(", %" PRI_klu ", ", tcp->u_arg[1]); print_nodemask(tcp, tcp->u_arg[2], tcp->u_arg[1]); tprints(", "); print_nodemask(tcp, tcp->u_arg[3], tcp->u_arg[1]); @@ -170,7 +171,8 @@ SYS_FUNC(move_pages) kernel_ulong_t buf; if (entering(tcp)) { - tprintf("%d, %" PRI_klu ", ", (int) tcp->u_arg[0], npages); + printpid(tcp, tcp->u_arg[0], PT_TGID); + tprintf(", %" PRI_klu ", ", npages); print_array(tcp, tcp->u_arg[2], npages, &buf, current_wordsize, tfetch_mem, print_addr, 0); tprints(", "); diff --git a/pidfd_open.c b/pidfd_open.c index bbc7f617..cf05a110 100644 --- a/pidfd_open.c +++ b/pidfd_open.c @@ -10,7 +10,7 @@ SYS_FUNC(pidfd_open) { /* pid_t pid */ - tprintf("%d", (int) tcp->u_arg[0]); + printpid(tcp, tcp->u_arg[0], PT_TGID); /* unsigned int flags */ tprintf(", %#x", (unsigned int) tcp->u_arg[1]); diff --git a/print_fields.h b/print_fields.h index f9714115..33d4a458 100644 --- a/print_fields.h +++ b/print_fields.h @@ -263,6 +263,30 @@ printfd((tcp_), (where_).field_); \ } while (0) +# define PRINT_FIELD_TID(prefix_, where_, field_, tcp_) \ + do { \ + STRACE_PRINTF("%s%s=", (prefix_), #field_); \ + printpid((tcp_), (where_).field_, PT_TID); \ + } while (0) + +# define PRINT_FIELD_TGID(prefix_, where_, field_, tcp_) \ + do { \ + STRACE_PRINTF("%s%s=", (prefix_), #field_); \ + printpid((tcp_), (where_).field_, PT_TGID); \ + } while (0) + +# define PRINT_FIELD_PGID(prefix_, where_, field_, tcp_) \ + do { \ + STRACE_PRINTF("%s%s=", (prefix_), #field_); \ + printpid((tcp_), (where_).field_, PT_PGID); \ + } while (0) + +# define PRINT_FIELD_SID(prefix_, where_, field_, tcp_) \ + do { \ + STRACE_PRINTF("%s%s=", (prefix_), #field_); \ + printpid((tcp_), (where_).field_, PT_SID); \ + } while (0) + # define PRINT_FIELD_STRN(prefix_, where_, field_, len_, tcp_) \ do { \ STRACE_PRINTF("%s%s=", (prefix_), #field_); \ diff --git a/printsiginfo.c b/printsiginfo.c index 8ed1e7ba..cb4cde4a 100644 --- a/printsiginfo.c +++ b/printsiginfo.c @@ -58,7 +58,7 @@ static void printsigsource(struct tcb *tcp, const siginfo_t *sip) { - PRINT_FIELD_D(", ", *sip, si_pid); + PRINT_FIELD_TGID(", ", *sip, si_pid, tcp); PRINT_FIELD_UID(", ", *sip, si_uid); } diff --git a/process.c b/process.c index a98c304e..d6ff255d 100644 --- a/process.c +++ b/process.c @@ -92,7 +92,8 @@ SYS_FUNC(ptrace) } /* pid */ - tprintf(", %d", pid); + tprints(", "); + printpid(tcp, pid, PT_TGID); /* addr */ switch (request) { diff --git a/process_vm.c b/process_vm.c index abee1e68..81d9b0f4 100644 --- a/process_vm.c +++ b/process_vm.c @@ -13,7 +13,8 @@ SYS_FUNC(process_vm_readv) { if (entering(tcp)) { /* arg 1: pid */ - tprintf("%d, ", (int) tcp->u_arg[0]); + printpid(tcp, tcp->u_arg[0], PT_TGID); + tprints(", "); } else { kernel_ulong_t local_iovcnt = tcp->u_arg[2]; kernel_ulong_t remote_iovcnt = tcp->u_arg[4]; @@ -42,7 +43,8 @@ SYS_FUNC(process_vm_writev) kernel_ulong_t flags = tcp->u_arg[5]; /* arg 1: pid */ - tprintf("%d, ", (int) tcp->u_arg[0]); + printpid(tcp, tcp->u_arg[0], PT_TGID); + tprints(", "); /* arg 2: local iov */ tprint_iov(tcp, local_iovcnt, tcp->u_arg[1], IOV_DECODE_STR); /* arg 3: local iovcnt */ diff --git a/resource.c b/resource.c index 53192ee9..070f4740 100644 --- a/resource.c +++ b/resource.c @@ -142,7 +142,8 @@ SYS_FUNC(setrlimit) SYS_FUNC(prlimit64) { if (entering(tcp)) { - tprintf("%d, ", (int) tcp->u_arg[0]); + printpid(tcp, tcp->u_arg[0], PT_TGID); + tprints(", "); printxval(resources, tcp->u_arg[1], "RLIMIT_???"); tprints(", "); print_rlimit64(tcp, tcp->u_arg[2]); @@ -179,10 +180,28 @@ SYS_FUNC(osf_getrusage) #include "xlat/priorities.h" +static void +priority_print_who(struct tcb *tcp, int which, int who) +{ + switch (which) + { + case PRIO_PROCESS: + printpid(tcp, who, PT_TGID); + break; + case PRIO_PGRP: + printpid(tcp, who, PT_PGID); + break; + default: + tprintf("%d", who); + break; + } +} + SYS_FUNC(getpriority) { printxval(priorities, tcp->u_arg[0], "PRIO_???"); - tprintf(", %d", (int) tcp->u_arg[1]); + tprints(", "); + priority_print_who(tcp, tcp->u_arg[0], tcp->u_arg[1]); return RVAL_DECODED; } @@ -190,7 +209,9 @@ SYS_FUNC(getpriority) SYS_FUNC(setpriority) { printxval(priorities, tcp->u_arg[0], "PRIO_???"); - tprintf(", %d, %d", (int) tcp->u_arg[1], (int) tcp->u_arg[2]); + tprints(", "); + priority_print_who(tcp, tcp->u_arg[0], tcp->u_arg[1]); + tprintf(", %d", (int) tcp->u_arg[2]); return RVAL_DECODED; } diff --git a/sched.c b/sched.c index 788ef39b..ff427e48 100644 --- a/sched.c +++ b/sched.c @@ -21,7 +21,7 @@ SYS_FUNC(sched_getscheduler) { if (entering(tcp)) { - tprintf("%d", (int) tcp->u_arg[0]); + printpid(tcp, tcp->u_arg[0], PT_TGID); } else if (!syserror(tcp)) { tcp->auxstr = xlookup(schedulers, (kernel_ulong_t) tcp->u_rval); return RVAL_STR; @@ -31,7 +31,8 @@ SYS_FUNC(sched_getscheduler) SYS_FUNC(sched_setscheduler) { - tprintf("%d, ", (int) tcp->u_arg[0]); + printpid(tcp, tcp->u_arg[0], PT_TGID); + tprints(", "); printxval(schedulers, tcp->u_arg[1], "SCHED_???"); tprints(", "); printnum_int(tcp, tcp->u_arg[2], "%d"); @@ -41,16 +42,19 @@ SYS_FUNC(sched_setscheduler) SYS_FUNC(sched_getparam) { - if (entering(tcp)) - tprintf("%d, ", (int) tcp->u_arg[0]); - else + if (entering(tcp)) { + printpid(tcp, tcp->u_arg[0], PT_TGID); + tprints(", "); + } else { printnum_int(tcp, tcp->u_arg[1], "%d"); + } return 0; } SYS_FUNC(sched_setparam) { - tprintf("%d, ", (int) tcp->u_arg[0]); + printpid(tcp, tcp->u_arg[0], PT_TGID); + tprints(", "); printnum_int(tcp, tcp->u_arg[1], "%d"); return RVAL_DECODED; @@ -68,7 +72,8 @@ do_sched_rr_get_interval(struct tcb *const tcp, const print_obj_by_addr_fn print_ts) { if (entering(tcp)) { - tprintf("%d, ", (int) tcp->u_arg[0]); + printpid(tcp, tcp->u_arg[0], PT_TGID); + tprints(", "); } else { if (syserror(tcp)) printaddr(tcp->u_arg[1]); @@ -160,7 +165,8 @@ end: SYS_FUNC(sched_setattr) { if (entering(tcp)) { - tprintf("%d, ", (int) tcp->u_arg[0]); + printpid(tcp, tcp->u_arg[0], PT_TGID); + tprints(", "); print_sched_attr(tcp, tcp->u_arg[1], 0); } else { struct sched_attr attr; @@ -179,7 +185,8 @@ SYS_FUNC(sched_setattr) SYS_FUNC(sched_getattr) { if (entering(tcp)) { - tprintf("%d, ", (int) tcp->u_arg[0]); + printpid(tcp, tcp->u_arg[0], PT_TGID); + tprints(", "); } else { const unsigned int size = tcp->u_arg[2]; diff --git a/signal.c b/signal.c index d5d59105..49b4ebd5 100644 --- a/signal.c +++ b/signal.c @@ -439,7 +439,8 @@ SYS_FUNC(sigprocmask) SYS_FUNC(kill) { /* pid */ - tprintf("%d, ", (int) tcp->u_arg[0]); + printpid_tgid_pgid(tcp, tcp->u_arg[0]); + tprints(", "); /* signal */ printsignal(tcp->u_arg[1]); @@ -448,7 +449,7 @@ SYS_FUNC(kill) SYS_FUNC(tkill) { - tprintf("%d", (int) tcp->u_arg[0]); + printpid(tcp, tcp->u_arg[0], PT_TID); tprints(", "); printsignal(tcp->u_arg[1]); @@ -457,8 +458,12 @@ SYS_FUNC(tkill) SYS_FUNC(tgkill) { - /* tgid, tid */ - tprintf("%d, %d, ", (int) tcp->u_arg[0], (int) tcp->u_arg[1]); + /* tgid */ + printpid(tcp, tcp->u_arg[0], PT_TGID); + tprints(", "); + /* tid */ + printpid(tcp, tcp->u_arg[1], PT_TID); + tprints(", "); /* signal */ printsignal(tcp->u_arg[2]); @@ -624,7 +629,8 @@ print_sigqueueinfo(struct tcb *const tcp, const int sig, SYS_FUNC(rt_sigqueueinfo) { - tprintf("%d, ", (int) tcp->u_arg[0]); + printpid(tcp, tcp->u_arg[0], PT_TGID); + tprints(", "); print_sigqueueinfo(tcp, tcp->u_arg[1], tcp->u_arg[2]); return RVAL_DECODED; @@ -632,7 +638,10 @@ SYS_FUNC(rt_sigqueueinfo) SYS_FUNC(rt_tgsigqueueinfo) { - tprintf("%d, %d, ", (int) tcp->u_arg[0], (int) tcp->u_arg[1]); + printpid(tcp, tcp->u_arg[0], PT_TGID); + tprints(", "); + printpid(tcp, tcp->u_arg[1], PT_TID); + tprints(", "); print_sigqueueinfo(tcp, tcp->u_arg[2], tcp->u_arg[3]); return RVAL_DECODED; diff --git a/sockaddr.c b/sockaddr.c index b0046331..fb8887c2 100644 --- a/sockaddr.c +++ b/sockaddr.c @@ -416,7 +416,7 @@ print_sockaddr_data_nl(struct tcb *tcp, const void *const buf, const int addrlen { const struct sockaddr_nl *const sa_nl = buf; - PRINT_FIELD_D("", *sa_nl, nl_pid); + PRINT_FIELD_TGID("", *sa_nl, nl_pid, tcp); PRINT_FIELD_0X(", ", *sa_nl, nl_groups); } diff --git a/tests/kcmp.c b/tests/kcmp.c index a46da0ed..dc5ba9a4 100644 --- a/tests/kcmp.c +++ b/tests/kcmp.c @@ -64,7 +64,26 @@ static const char zero_path[] = "/dev/zero"; static void printpidfd(const char *prefix, pid_t pid, unsigned fd) { - printf("%s%d", prefix, fd); + const char *path = NULL; + +# if VERBOSE_FD + if (pid == getpid()) { + switch (fd) + { + case NULL_FD: + path = null_path; + break; + case ZERO_FD: + path = zero_path; + break; + } + } +# endif + + if (path) + printf("%s%d<%s>", prefix, fd, path); + else + printf("%s%d", prefix, fd); } /* @@ -179,7 +198,7 @@ main(void) /* KCMP_FILE is the only type which has additional args */ do_kcmp(3141592653U, 2718281828U, ARG_STR(KCMP_FILE), bogus_idx1, bogus_idx2); - do_kcmp(-1, -1, ARG_STR(KCMP_FILE), NULL_FD, ZERO_FD); + do_kcmp(getpid(), getpid(), ARG_STR(KCMP_FILE), NULL_FD, ZERO_FD); /* Types without additional args */ do_kcmp(-1, -1, ARG_STR(KCMP_VM), bogus_idx1, bogus_idx2); @@ -198,7 +217,7 @@ main(void) for (i = 0; i < ARRAY_SIZE(slot_data); i++) { memcpy(slot, slot_data + i, sizeof(*slot)); - do_kcmp(getpid(), getppid(), ARG_STR(KCMP_EPOLL_TFD), NULL_FD, + do_kcmp(getpid(), -1, ARG_STR(KCMP_EPOLL_TFD), NULL_FD, (uintptr_t) slot, 1); } diff --git a/util.c b/util.c index 286c6903..2568021e 100644 --- a/util.c +++ b/util.c @@ -392,6 +392,18 @@ printnum_fd(struct tcb *const tcp, const kernel_ulong_t addr) return true; } +bool +printnum_pid(struct tcb *const tcp, const kernel_ulong_t addr, enum pid_type type) +{ + int pid; + if (umove_or_printaddr(tcp, addr, &pid)) + return false; + tprints("["); + printpid(tcp, pid, type); + tprints("]"); + return true; +} + /** * Prints time to a (static internal) buffer and returns pointer to it. * Returns NULL if the provided time specification is not correct. @@ -616,7 +628,7 @@ void printfd_pid(struct tcb *tcp, pid_t pid, int fd) { char path[PATH_MAX + 1]; - if (!number_set_array_is_empty(decode_fd_set, 0) + if (pid > 0 && !number_set_array_is_empty(decode_fd_set, 0) && getfdpath_pid(pid, fd, path, sizeof(path)) >= 0) { tprintf("%d<", (int) fd); if (is_number_in_set(DECODE_FD_SOCKET, decode_fd_set) && @@ -641,12 +653,8 @@ printed: void printfd_pid_tracee_ns(struct tcb *tcp, pid_t pid, int fd) { - /* - * TODO: We want to have the same formatting as printfd here, - * but we should figure out first which process in strace's - * PID NS is referred to by pid in tracee's PID NS. - */ - tprintf("%d", fd); + int strace_pid = translate_pid(tcp, pid, PT_TGID, NULL); + printfd_pid(tcp, strace_pid, fd); } /* diff --git a/wait.c b/wait.c index 2b9f9807..177427c8 100644 --- a/wait.c +++ b/wait.c @@ -80,14 +80,8 @@ printwaitn(struct tcb *const tcp, void (*const print_rusage)(struct tcb *, kernel_ulong_t)) { if (entering(tcp)) { - /* On Linux, kernel-side pid_t is typedef'ed to int - * on all arches. Also, glibc-2.8 truncates wait3 and wait4 - * pid argument to int on 64bit arches, producing, - * for example, wait4(4294967295, ...) instead of -1 - * in strace. We have to use int here, not long. - */ - int pid = tcp->u_arg[0]; - tprintf("%d, ", pid); + printpid_tgid_pgid(tcp, tcp->u_arg[0]); + tprintf(", "); } else { int status; @@ -108,7 +102,7 @@ printwaitn(struct tcb *const tcp, printaddr(tcp->u_arg[3]); } } - return 0; + return RVAL_TGID; } SYS_FUNC(waitpid) @@ -134,10 +128,28 @@ SYS_FUNC(osf_wait4) SYS_FUNC(waitid) { + unsigned int idtype = (unsigned int) tcp->u_arg[0]; + int id = tcp->u_arg[1]; + if (entering(tcp)) { - printxval(waitid_types, tcp->u_arg[0], "P_???"); - int pid = tcp->u_arg[1]; - tprintf(", %d, ", pid); + printxval(waitid_types, idtype, "P_???"); + tprints(", "); + switch (idtype) + { + case P_PID: + printpid(tcp, id, PT_TGID); + break; + case P_PIDFD: + printfd(tcp, id); + break; + case P_PGID: + printpid(tcp, id, PT_PGID); + break; + default: + tprintf("%d", id); + break; + } + tprints(", "); } else { /* siginfo */ printsiginfo_at(tcp, tcp->u_arg[2]); -- 2.28.0 From uzonyi.akos at gmail.com Sun Aug 16 22:18:47 2020 From: uzonyi.akos at gmail.com (=?UTF-8?q?=C3=81kos=20Uzonyi?=) Date: Mon, 17 Aug 2020 00:18:47 +0200 Subject: [RFC PATCH v9 4/8] Implement testing framework for pidns In-Reply-To: <20200816221851.200031-1-uzonyi.akos@gmail.com> References: <20200816221851.200031-1-uzonyi.akos@gmail.com> Message-ID: <20200816221851.200031-5-uzonyi.akos@gmail.com> * tests/pidns.c: New file. * tests/pidns.h: New file. * tests/Makefile.am (libtests_a_SOURCES): Add pidns.c, pidns.h. * tests/init.sh (test_pidns, test_pidns_run_strace): New functions. --- tests/Makefile.am | 2 + tests/init.sh | 29 ++++++ tests/pidns.c | 229 ++++++++++++++++++++++++++++++++++++++++++++++ tests/pidns.h | 56 ++++++++++++ 4 files changed, 316 insertions(+) create mode 100644 tests/pidns.c create mode 100644 tests/pidns.h diff --git a/tests/Makefile.am b/tests/Makefile.am index 28d95e39..7a583a3a 100644 --- a/tests/Makefile.am +++ b/tests/Makefile.am @@ -44,6 +44,8 @@ libtests_a_SOURCES = \ libsocketcall.c \ lock_file.c \ overflowuid.c \ + pidns.c \ + pidns.h \ pipe_maxfd.c \ print_quoted_string.c \ print_time.c \ diff --git a/tests/init.sh b/tests/init.sh index d78e697b..5c9b8260 100644 --- a/tests/init.sh +++ b/tests/init.sh @@ -387,6 +387,35 @@ test_prog_set() test_pure_prog_set "$@" < "$srcdir/$NAME.in" } +test_pidns_run_strace() +{ + local parent_pid init_pid + + check_prog tail + check_prog cut + check_prog grep + + run_prog > /dev/null + run_strace --pidns-translation -f $@ $args > "$EXP" + + # filter out logs made by the parent or init process of the pidns test + parent_pid="$(tail -n 2 $LOG | head -n 1 | cut -d' ' -f1)" + init_pid="$(tail -n 1 $LOG | cut -d' ' -f1)" + grep -E -v "^($parent_pid|$init_pid) " "$LOG" > "$OUT" + match_diff "$OUT" "$EXP" +} + +test_pidns() +{ + check_prog unshare + + test_pidns_run_strace "$@" + + # test PID translation when /proc is mounted from an other namespace + STRACE="unshare -Urpf $STRACE" + test_pidns_run_strace "$@" +} + check_prog cat check_prog rm diff --git a/tests/pidns.c b/tests/pidns.c new file mode 100644 index 00000000..294650f8 --- /dev/null +++ b/tests/pidns.c @@ -0,0 +1,229 @@ +/* + * Testing framework for PID namespace translation + * + * Copyright (c) 2020 ?kos Uzonyi + * All rights reserved. + * + * SPDX-License-Identifier: LGPL-2.1-or-later + */ +#include "tests.h" +#include "pidns.h" +#include "nsfs.h" + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +static bool pidns_translation = false; +static bool pidns_unshared = false; + +/* Our PIDs in strace's namespace */ +static pid_t pidns_strace_ids[PT_COUNT]; + +void +pidns_print_leader(void) +{ + if (pidns_translation) + printf("%-5d ", pidns_strace_ids[PT_TID]); +} + +const char * +pidns_pid2str(enum pid_type type) +{ + static const char format[] = " /* %d in strace's PID NS */"; + static char buf[PT_COUNT][sizeof(format) + sizeof(int) * 3]; + + if (type < 0 || type >= PT_COUNT) + return ""; + + if (!pidns_unshared || !pidns_strace_ids[type]) + return ""; + + snprintf(buf[type], sizeof(buf[type]), format, pidns_strace_ids[type]); + return buf[type]; +} + +/** + * This function is like fork, but does a few more things. It sets up the + * child's PGID and SID according to the parameters. Also it fills the + * pidns_strace_ids array in the child's memory with the PIDs of the child in + * parent's PID namespace. In the parent it waits for the child to terminate + * (but leaves the zombie to use it later as a process group). If the child + * terminates with nonzero exit status, the test is failed. + * + * @param pgid The process group the child should be moved to. It's expected + * to be a PID of a zombie process (will be reaped). If + * negative, leave the child in the process group of the parent. + * If 0, move the process to its own process group. + * @param new_sid Wheather child should be moved to a new session. + */ +static pid_t +pidns_fork(pid_t pgid, bool new_sid) +{ + int strace_ids_pipe[2]; + if (pipe(strace_ids_pipe) < 0) + perror_msg_and_fail("pipe"); + + fflush(stdout); + pid_t pid = fork(); + if (pid < 0) + perror_msg_and_fail("fork"); + + if (!pid) { + close(strace_ids_pipe[1]); + + ssize_t len = read(strace_ids_pipe[0], pidns_strace_ids, + sizeof(pidns_strace_ids)); + if (len < 0) + perror_msg_and_fail("read"); + if (len != sizeof(pidns_strace_ids)) + error_msg_and_fail("read returned < sizeof(pidns_strace_ids)"); + + close(strace_ids_pipe[0]); + + if (pidns_strace_ids[PT_SID]) + setsid(); + + return 0; + } + + pidns_strace_ids[PT_TID] = pid; + pidns_strace_ids[PT_TGID] = pid; + pidns_strace_ids[PT_PGID] = 0; + pidns_strace_ids[PT_SID] = 0; + + if (!pgid) + pgid = pid; + + if (pgid > 0) { + if (setpgid(pid, pgid) < 0) + perror_msg_and_fail("setpgid"); + + pidns_strace_ids[PT_PGID] = pgid; + } + + /* Reap group leader to test PGID decoding */ + if (pgid > 0 && pgid != pid) { + int ret = waitpid(pgid, NULL, WNOHANG); + if (ret < 0) + perror_msg_and_fail("wait"); + if (!ret) + error_msg_and_fail("could not reap group leader"); + } + + if (new_sid) { + pidns_strace_ids[PT_SID] = pid; + pidns_strace_ids[PT_PGID] = pid; + } + + ssize_t len = write(strace_ids_pipe[1], pidns_strace_ids, + sizeof(pidns_strace_ids)); + if (len < 0) + perror_msg_and_fail("write"); + if (len != sizeof(pidns_strace_ids)) + error_msg_and_fail("write returned < sizeof(pidns_strace_ids)"); + + close(strace_ids_pipe[0]); + close(strace_ids_pipe[1]); + + /* WNOWAIT: leave the zombie, to be able to use it as a process group */ + siginfo_t siginfo; + if (waitid(P_PID, pid, &siginfo, WEXITED | WNOWAIT) < 0) + perror_msg_and_fail("wait"); + if (siginfo.si_code != CLD_EXITED || siginfo.si_status) + error_msg_and_fail("child terminated with nonzero exit status"); + + return pid; +} + +static void +create_init_process(void) +{ + int child_pipe[2]; + if (pipe(child_pipe) < 0) + perror_msg_and_fail("pipe"); + + pid_t pid = fork(); + if (pid < 0) + perror_msg_and_fail("fork"); + + if (!pid) { + close(child_pipe[1]); + if (read(child_pipe[0], &child_pipe[1], sizeof(int)) != 0) + _exit(1); + _exit(0); + } + + close(child_pipe[0]); +} + +void +check_ns_ioctl(void) +{ + int fd = open("/proc/self/ns/pid", O_RDONLY); + if (fd < 0) { + if (errno == ENOENT) + perror_msg_and_skip("opening /proc/self/ns/pid"); + else + perror_msg_and_fail("opening /proc/self/ns/pid"); + } + + int userns_fd = ioctl(fd, NS_GET_USERNS); + if (userns_fd < 0) { + if (errno == ENOTTY) + error_msg_and_skip("NS_* ioctl commands are not " + "supported by the kernel"); + else + perror_msg_and_fail("ioctl(NS_GET_USERNS)"); + } + + close(userns_fd); + close(fd); +} + +void +pidns_test_init(void) +{ + pidns_translation = true; + + check_ns_ioctl(); + + if (!pidns_fork(-1, false)) + return; + + /* Unshare user namespace too, so we do not need to be root */ + if (unshare(CLONE_NEWUSER | CLONE_NEWPID) < 0) { + if (errno == EPERM) + perror_msg_and_skip("unshare"); + + perror_msg_and_fail("unshare"); + } + + pidns_unshared = true; + + create_init_process(); + + if (!pidns_fork(-1, false)) + return; + + if (!pidns_fork(-1, true)) + return; + + pid_t pgid; + if (!(pgid = pidns_fork(0, false))) + return; + + if (!pidns_fork(pgid, false)) + return; + + exit(0); +} diff --git a/tests/pidns.h b/tests/pidns.h new file mode 100644 index 00000000..76963eb3 --- /dev/null +++ b/tests/pidns.h @@ -0,0 +1,56 @@ +/* + * Test PID namespace translation + * + * Copyright (c) 2020 ?kos Uzonyi + * All rights reserved. + * + * SPDX-License-Identifier: LGPL-2.1-or-later + */ +#ifndef STRACE_PIDNS_H +#define STRACE_PIDNS_H + +#ifdef PIDNS_TRANSLATION +# define PIDNS_TEST_INIT pidns_test_init() +#else +# define PIDNS_TEST_INIT +#endif + +#include + +enum pid_type { + PT_TID, + PT_TGID, + PT_PGID, + PT_SID, + + PT_COUNT, + PT_NONE = -1 +}; + +/* Prints leader (process tid) if pidns_test_init was called */ +void pidns_print_leader(void); + +/* + * Returns a static buffer containing the translation string of our PID. + */ +const char *pidns_pid2str(enum pid_type type); + +/** + * Skips the test if NS_* ioctl commands are not supported by the kernel. + */ +void check_ns_ioctl(void); + +/** + * Init pidns testing. + * + * Should be called at the beginning of the test's main function + * + * This function calls fork a couple of times, and returns in the child + * processes. These child processes are in a new PID namespace with different + * PID configurations (group leader, session leader, ...). If any child + * terminates with nonzero exit status the test is failed. Otherwise the test is + * succesful, and the parent process exits with 0. + */ +void pidns_test_init(void); + +#endif \ No newline at end of file -- 2.28.0 From uzonyi.akos at gmail.com Sun Aug 16 22:18:51 2020 From: uzonyi.akos at gmail.com (=?UTF-8?q?=C3=81kos=20Uzonyi?=) Date: Mon, 17 Aug 2020 00:18:51 +0200 Subject: [RFC PATCH v9 8/8] [squash] Add tests for tkill, tgkill In-Reply-To: <20200816221851.200031-1-uzonyi.akos@gmail.com> References: <20200816221851.200031-1-uzonyi.akos@gmail.com> Message-ID: <20200816221851.200031-9-uzonyi.akos@gmail.com> --- tests/.gitignore | 2 ++ tests/Makefile.am | 2 ++ tests/gen_tests.in | 2 ++ tests/tgkill--pidns-translation.c | 2 ++ tests/tgkill.c | 51 +++++++++++++++++++++---------- tests/tkill--pidns-translation.c | 2 ++ tests/tkill.c | 19 +++++++++--- 7 files changed, 59 insertions(+), 21 deletions(-) create mode 100644 tests/tgkill--pidns-translation.c create mode 100644 tests/tkill--pidns-translation.c diff --git a/tests/.gitignore b/tests/.gitignore index 237d2d03..a75b3deb 100644 --- a/tests/.gitignore +++ b/tests/.gitignore @@ -759,6 +759,7 @@ syslog syslog-success tee tgkill +tgkill--pidns-translation threads-execve threads-execve--quiet-thread-execve threads-execve-q @@ -771,6 +772,7 @@ timerfd_xettime times times-fail tkill +tkill--pidns-translation tracer_ppid_pgid_sid trie truncate diff --git a/tests/Makefile.am b/tests/Makefile.am index 8ed6933f..379b9851 100644 --- a/tests/Makefile.am +++ b/tests/Makefile.am @@ -241,11 +241,13 @@ check_PROGRAMS = $(PURE_EXECUTABLES) \ status-unfinished-threads \ so_peercred--pidns-translation \ syslog-success \ + tgkill--pidns-translation \ threads-execve \ threads-execve--quiet-thread-execve \ threads-execve-q \ threads-execve-qq \ threads-execve-qqq \ + tkill--pidns-translation \ tracer_ppid_pgid_sid \ trie \ unblock_reset_raise \ diff --git a/tests/gen_tests.in b/tests/gen_tests.in index 1138c6af..d272031e 100644 --- a/tests/gen_tests.in +++ b/tests/gen_tests.in @@ -688,6 +688,7 @@ sysinfo -a14 syslog -a35 tee tgkill -a15 --signal='!cont' +tgkill--pidns-translation test_pidns -a15 --signal='!cont' -e trace=tgkill threads-execve--quiet-thread-execve +threads-execve.test -s40 --quiet=personality,thread-execve threads-execve-q +threads-execve.test -q threads-execve-qq +threads-execve.test -qq @@ -699,6 +700,7 @@ timerfd_xettime -e trace=timerfd_create,timerfd_settime,timerfd_gettime times -esignal=none times-fail -a12 -e trace=times tkill -a12 --signal='!cont' +tkill--pidns-translation test_pidns --signal='!cont' -a12 -e trace=tkill trace_clock test_trace_expr 'clock_nanosleep|times' -e%clock trace_creds test_trace_expr '([gs]et[^p]*([gu]id|groups)|caps|prctl|[fl]?chown|print(path-umovestr|strn-umoven)-undumpable|ptrace|quotactl|rt_sigtimedwait|rt_(tg)?sigqueueinfo).*' -e%creds trace_fstat test_trace_expr '' -e%fstat -v -P stat.sample -P /dev/full diff --git a/tests/tgkill--pidns-translation.c b/tests/tgkill--pidns-translation.c new file mode 100644 index 00000000..c3ac2d0a --- /dev/null +++ b/tests/tgkill--pidns-translation.c @@ -0,0 +1,2 @@ +#define PIDNS_TRANSLATION +#include "tgkill.c" diff --git a/tests/tgkill.c b/tests/tgkill.c index 901be376..10816a61 100644 --- a/tests/tgkill.c +++ b/tests/tgkill.c @@ -9,6 +9,7 @@ #include "tests.h" #include "scno.h" +#include "pidns.h" #ifdef __NR_tgkill @@ -36,28 +37,46 @@ k_tgkill(const unsigned int tgid, int main(void) { + PIDNS_TEST_INIT; + const int pid = getpid(); + const char *pid_str = pidns_pid2str(PT_TGID); + const int tid = syscall(__NR_gettid); + const char *tid_str = pidns_pid2str(PT_TID); const int bad_pid = -1; const int bad_sig = 0xface; - k_tgkill(pid, pid, 0); - printf("tgkill(%d, %d, 0) = %s\n", pid, pid, errstr); + k_tgkill(pid, tid, 0); + pidns_print_leader(); + printf("tgkill(%d%s, %d%s, 0) = %s\n", + pid, pid_str, tid, tid_str, errstr); k_tgkill(pid, bad_pid, 0); - printf("tgkill(%d, %d, 0) = %s\n", pid, bad_pid, errstr); - - k_tgkill(bad_pid, pid, 0); - printf("tgkill(%d, %d, 0) = %s\n", bad_pid, pid, errstr); - - k_tgkill(pid, pid, SIGCONT); - printf("tgkill(%d, %d, SIGCONT) = %s\n", pid, pid, errstr); - - k_tgkill(pid, pid, bad_sig); - printf("tgkill(%d, %d, %d) = %s\n", pid, pid, bad_sig, errstr); - - k_tgkill(pid, pid, -bad_sig); - printf("tgkill(%d, %d, %d) = %s\n", pid, pid, -bad_sig, errstr); - + pidns_print_leader(); + printf("tgkill(%d%s, %d, 0) = %s\n", + pid, pid_str, bad_pid, errstr); + + k_tgkill(bad_pid, tid, 0); + pidns_print_leader(); + printf("tgkill(%d, %d%s, 0) = %s\n", + bad_pid, tid, tid_str, errstr); + + k_tgkill(pid, tid, SIGCONT); + pidns_print_leader(); + printf("tgkill(%d%s, %d%s, SIGCONT) = %s\n", + pid, pid_str, tid, tid_str, errstr); + + k_tgkill(pid, tid, bad_sig); + pidns_print_leader(); + printf("tgkill(%d%s, %d%s, %d) = %s\n", + pid, pid_str, tid, tid_str, bad_sig, errstr); + + k_tgkill(pid, tid, -bad_sig); + pidns_print_leader(); + printf("tgkill(%d%s, %d%s, %d) = %s\n", + pid, pid_str, tid, tid_str, -bad_sig, errstr); + + pidns_print_leader(); puts("+++ exited with 0 +++"); return 0; } diff --git a/tests/tkill--pidns-translation.c b/tests/tkill--pidns-translation.c new file mode 100644 index 00000000..70a64f57 --- /dev/null +++ b/tests/tkill--pidns-translation.c @@ -0,0 +1,2 @@ +#define PIDNS_TRANSLATION +#include "tkill.c" diff --git a/tests/tkill.c b/tests/tkill.c index 5f67c9f5..89466e1a 100644 --- a/tests/tkill.c +++ b/tests/tkill.c @@ -9,6 +9,7 @@ #include "tests.h" #include "scno.h" +#include "pidns.h" #ifdef __NR_tkill @@ -33,22 +34,30 @@ k_tkill(const unsigned int tid, const unsigned int sig) int main(void) { - const int pid = getpid(); + PIDNS_TEST_INIT; + + const int tid = syscall(__NR_gettid); + const char *tid_str = pidns_pid2str(PT_TID); const int bad_pid = -1; const int bad_sig = 0xface; - k_tkill(pid, 0); - printf("tkill(%d, 0) = %s\n", pid, errstr); + k_tkill(tid, 0); + pidns_print_leader(); + printf("tkill(%d%s, 0) = %s\n", tid, tid_str, errstr); - k_tkill(pid, SIGCONT); - printf("tkill(%d, SIGCONT) = %s\n", pid, errstr); + k_tkill(tid, SIGCONT); + pidns_print_leader(); + printf("tkill(%d%s, SIGCONT) = %s\n", tid, tid_str, errstr); k_tkill(bad_pid, bad_sig); + pidns_print_leader(); printf("tkill(%d, %d) = %s\n", bad_pid, bad_sig, errstr); k_tkill(bad_pid, -bad_sig); + pidns_print_leader(); printf("tkill(%d, %d) = %s\n", bad_pid, -bad_sig, errstr); + pidns_print_leader(); puts("+++ exited with 0 +++"); return 0; } -- 2.28.0 From uzonyi.akos at gmail.com Sun Aug 16 22:18:50 2020 From: uzonyi.akos at gmail.com (=?UTF-8?q?=C3=81kos=20Uzonyi?=) Date: Mon, 17 Aug 2020 00:18:50 +0200 Subject: [RFC PATCH v9 7/8] [squash] Add test for trie In-Reply-To: <20200816221851.200031-1-uzonyi.akos@gmail.com> References: <20200816221851.200031-1-uzonyi.akos@gmail.com> Message-ID: <20200816221851.200031-8-uzonyi.akos@gmail.com> --- tests/.gitignore | 1 + tests/Makefile.am | 2 ++ tests/gen_tests.in | 1 + tests/trie.c | 77 ++++++++++++++++++++++++++++++++++++++++++++++ 4 files changed, 81 insertions(+) create mode 100644 tests/trie.c diff --git a/tests/.gitignore b/tests/.gitignore index c824ca5e..237d2d03 100644 --- a/tests/.gitignore +++ b/tests/.gitignore @@ -772,6 +772,7 @@ times times-fail tkill tracer_ppid_pgid_sid +trie truncate truncate64 ugetrlimit diff --git a/tests/Makefile.am b/tests/Makefile.am index 8aaa0cae..8ed6933f 100644 --- a/tests/Makefile.am +++ b/tests/Makefile.am @@ -66,6 +66,7 @@ libtests_a_SOURCES = \ test_ucopy.h \ tests.h \ tprintf.c \ + ../trie.c \ # end of libtests_a_SOURCES libtests_a_CPPFLAGS = $(AM_CPPFLAGS) -D_FILE_OFFSET_BITS=64 check_LIBRARIES = libtests.a @@ -246,6 +247,7 @@ check_PROGRAMS = $(PURE_EXECUTABLES) \ threads-execve-qq \ threads-execve-qqq \ tracer_ppid_pgid_sid \ + trie \ unblock_reset_raise \ unix-pair-send-recv \ unix-pair-sendto-recvfrom \ diff --git a/tests/gen_tests.in b/tests/gen_tests.in index 10374a9e..1138c6af 100644 --- a/tests/gen_tests.in +++ b/tests/gen_tests.in @@ -715,6 +715,7 @@ trace_stat test_trace_expr '' -e%stat -v -P stat.sample -P /dev/full trace_stat_like test_trace_expr '' -e%%stat -v -P stat.sample -P /dev/full trace_statfs test_trace_expr '' -e%statfs trace_statfs_like test_trace_expr '' -e%%statfs +trie run_prog truncate truncate64 ugetrlimit -a28 diff --git a/tests/trie.c b/tests/trie.c new file mode 100644 index 00000000..bc54a888 --- /dev/null +++ b/tests/trie.c @@ -0,0 +1,77 @@ +/* + * Copyright (c) 2017-2019 The strace developers. + * All rights reserved. + * + * SPDX-License-Identifier: GPL-2.0-or-later + */ + +#include "tests.h" +#include "trie.h" + +#include +#include + +static void +assert_equals(const char *msg, uint64_t expected, uint64_t actual) { + if (actual != expected) + error_msg_and_fail("%s: expected: %" PRIu64 + ", actual: %" PRIu64, msg, expected, actual); +} + +struct key_value_pair { + uint64_t key, value; +}; + +int +main(void) +{ + static const struct { + uint8_t key_size; + uint8_t item_size_lg; + uint8_t node_key_bits; + uint8_t data_block_key_bits; + uint64_t empty_value; + + struct key_value_pair set_values[3], get_values[3]; + } params[] = { + {64, 6, 10, 10, 0, + {{300, 1}, {0xfacefeed, 0xabcdef123456}, {-1ULL, -1ULL}}, + {{301, 0}, {0xfacefeed, 0xabcdef123456}, {-1ULL, -1ULL}}}, + {8, 2, 4, 4, 10, + {{0xab, 0xcd}, {0xface, 2}, {0, 3}}, + {{0xab, 0xd}, {0xface, 10}, {0, 3}}}, + {30, 0, 6, 3, -1, + {{0xaaaa, 127}, {0xface, 0}, {0, 0}}, + {{0xaaaa, 1}, {0xface, 0}, {1, 1}}}, + {16, 4, 5, 11, 0xffffff, + {{0xabcdef, 42}, {0xabcd, 42}, {0xffff, 0}}, + {{0xabcdef, 0xffff}, {0xabcd, 42}, {0xffff, 0}}}, + {41, 5, 1, 1, -1, + {{0xabcdef01, 0x22222222}, {-1, 0x33333333}, {10, 10}}, + {{0xabcdef01, 0x22222222}, {-1, 0xffffffff}, {10, 10}}}, + }; + + for (size_t i = 0; i < ARRAY_SIZE(params); i++) { + struct trie *t = trie_create(params[i].key_size, + params[i].item_size_lg, + params[i].node_key_bits, + params[i].data_block_key_bits, + params[i].empty_value); + + if (!t) + error_msg_and_fail("trie creation failed"); + + for (size_t j = 0; j < ARRAY_SIZE(params[i].set_values); j++) { + struct key_value_pair kv = params[i].set_values[j]; + trie_set(t, kv.key, kv.value); + } + for (size_t j = 0; j < ARRAY_SIZE(params[i].get_values); j++) { + struct key_value_pair kv = params[i].get_values[j]; + assert_equals("trie_get", kv.value, trie_get(t, kv.key)); + } + + trie_free(t); + } + + return 0; +} -- 2.28.0 From uzonyi.akos at gmail.com Sun Aug 16 22:18:49 2020 From: uzonyi.akos at gmail.com (=?UTF-8?q?=C3=81kos=20Uzonyi?=) Date: Mon, 17 Aug 2020 00:18:49 +0200 Subject: [RFC PATCH v9 6/8] [squash] Test pidns translation cache In-Reply-To: <20200816221851.200031-1-uzonyi.akos@gmail.com> References: <20200816221851.200031-1-uzonyi.akos@gmail.com> Message-ID: <20200816221851.200031-7-uzonyi.akos@gmail.com> --- tests/.gitignore | 1 + tests/Makefile.am | 2 ++ tests/pidns-cache.c | 62 ++++++++++++++++++++++++++++++++++++++++++ tests/pidns-cache.test | 16 +++++++++++ 4 files changed, 81 insertions(+) create mode 100644 tests/pidns-cache.c create mode 100755 tests/pidns-cache.test diff --git a/tests/.gitignore b/tests/.gitignore index 4d1153fc..c824ca5e 100644 --- a/tests/.gitignore +++ b/tests/.gitignore @@ -525,6 +525,7 @@ pidfd_open-yy pidfd_open--pidns-translation pidfd_send_signal pidfd_send_signal--pidns-translation +pidns-cache pipe pipe2 pkey_alloc diff --git a/tests/Makefile.am b/tests/Makefile.am index f2c5da83..8aaa0cae 100644 --- a/tests/Makefile.am +++ b/tests/Makefile.am @@ -190,6 +190,7 @@ check_PROGRAMS = $(PURE_EXECUTABLES) \ perf_event_open_unabbrev \ pidfd_open--pidns-translation \ pidfd_send_signal--pidns-translation \ + pidns-cache \ poll-P \ ppoll-P \ ppoll-v \ @@ -425,6 +426,7 @@ MISC_TESTS = \ opipe.test \ options-syntax.test \ pc.test \ + pidns-cache.test \ printpath-umovestr-legacy.test \ printstrn-umoven-legacy.test \ qual_fault-syntax.test \ diff --git a/tests/pidns-cache.c b/tests/pidns-cache.c new file mode 100644 index 00000000..5996abc1 --- /dev/null +++ b/tests/pidns-cache.c @@ -0,0 +1,62 @@ +/* + * Copyright (c) 2020 The strace developers. + * All rights reserved. + * + * SPDX-License-Identifier: GPL-2.0-or-later + */ + +#include "tests.h" +#include "scno.h" +#include "pidns.h" + +#if defined __NR_getpid && (!defined __NR_getxpid || __NR_getxpid != __NR_getpid) + +# include +# include +# include + +# define SYSCALL_COUNT 50 + +/** + * Max us per syscall that translation should take. 1 ms is plenty enough time + * for the cache, and very short for translating without the cache. + */ +# define MAX_TRANSLATION_US_PER_SYSCALL 1000 + +static long +execute_syscalls(void) +{ + /* Load our PID in the cache */ + syscall(__NR_getpid); + + struct timeval stop, start; + gettimeofday(&start, NULL); + + for (int i = 0; i < SYSCALL_COUNT; i++) + syscall(__NR_getpid); + + gettimeofday(&stop, NULL); + + return (stop.tv_usec - start.tv_usec) + + (stop.tv_sec - start.tv_sec) * 1000000; +} + +int +main(void) +{ + long max_us = execute_syscalls() + + SYSCALL_COUNT * MAX_TRANSLATION_US_PER_SYSCALL; + + pidns_test_init(); + + if (execute_syscalls() > max_us) + error_msg_and_fail("pidns translation took too long"); + + return 0; +} + +#else + +SKIP_MAIN_UNDEFINED("__NR_getpid") + +#endif diff --git a/tests/pidns-cache.test b/tests/pidns-cache.test new file mode 100755 index 00000000..fa98ed8c --- /dev/null +++ b/tests/pidns-cache.test @@ -0,0 +1,16 @@ +#!/bin/sh +# +# Test pidns translation cache. +# +# Copyright (c) 2020 The strace developers. +# All rights reserved. +# +# SPDX-License-Identifier: GPL-2.0-or-later + +. "${srcdir=.}/init.sh" + +require_min_kernel_version_or_skip 4.9 +check_prog timeout + +run_prog > /dev/null +run_strace --pidns-translation -f -e trace=getpid $args -- 2.28.0 From uzonyi.akos at gmail.com Sun Aug 16 22:18:48 2020 From: uzonyi.akos at gmail.com (=?UTF-8?q?=C3=81kos=20Uzonyi?=) Date: Mon, 17 Aug 2020 00:18:48 +0200 Subject: [RFC PATCH v9 5/8] Add tests for PID namespace translation In-Reply-To: <20200816221851.200031-1-uzonyi.akos@gmail.com> References: <20200816221851.200031-1-uzonyi.akos@gmail.com> Message-ID: <20200816221851.200031-6-uzonyi.akos@gmail.com> * tests/.gitignore: Add new test executables. * tests/Makefile.am (check_PROGRAMS): Add new test executables. (DECODER_TESTS) Add new test files. * tests/gen_tests.in: Add new tests. * tests/fcntl--pidns-translation.c: New file. * tests/fcntl64--pidns-translation.c: New file. * tests/fork--pidns-translation.awk: New file. * tests/fork--pidns-translation.c: New file. * tests/fork--pidns-translation.test: New file. * tests/getpgrp--pidns-translation.c: New file. * tests/getpid--pidns-translation.c: New file. * tests/getsid--pidns-translation.c: New file. * tests/gettid--pidns-translation.c: New file. * tests/gettid--pidns-translation.test: New file. * tests/ioctl_block--pidns-translation.c: New file. * tests/ioctl_block--pidns-translation.test: New file. * tests/ioprio--pidns-translation.c: New file. * tests/kill--pidns-translation.c: New file. * tests/migrate_pages--pidns-translation.c: New file. * tests/move_pages--pidns-translation.c: New file. * tests/net-sockaddr--pidns-translation.c: New file. * tests/netlink_audit--pidns-translation.c: New file. * tests/netlink_audit--pidns-translation.test: New file. * tests/pidfd_open--pidns-translation.c: New file. * tests/pidfd_send_signal--pidns-translation.c: New file. * tests/prlimit64--pidns-translation.c: New file. * tests/process_vm_readv--pidns-translation.c: New file. * tests/process_vm_writev--pidns-translation.c: New file. * tests/rt_sigqueueinfo--pidns-translation.c: New file. * tests/rt_tgsigqueueinfo--pidns-translation.c: New file. * tests/sched_xetaffinity--pidns-translation.c: New file. * tests/sched_xetattr--pidns-translation.c: New file. * tests/sched_xetparam--pidns-translation.c: New file. * tests/sched_xetscheduler--pidns-translation.c: New file. * tests/signal_receive--pidns-translation.c: New file. * tests/so_peercred--pidns-translation.c: New file. * tests/xet_robust_list--pidns-translation.c: New file. * tests/xetpgid--pidns-translation.c: New file. * tests/xetpriority--pidns-translation.c: New file. * tests/fcntl-common.c: Print PID translation string after PIDs. * tests/fcntl.c: Likewise. * tests/fcntl64.c: Likewise. * tests/getpgrp.c: Likewise. * tests/getpid.c: Likewise. * tests/getsid.c: Likewise. * tests/gettid.c: Likewise. * tests/ioctl_block.c: Likewise. * tests/ioprio.c: Likewise. * tests/kcmp.c: Likewise. * tests/kill.c: Likewise. * tests/migrate_pages.c: Likewise. * tests/move_pages.c: Likewise. * tests/net-sockaddr.c: Likewise. * tests/netlink_audit.c: Likewise. * tests/pidfd_open.c: Likewise. * tests/pidfd_send_signal.c: Likewise. * tests/prlimit64.c: Likewise. * tests/process_vm_readv_writev.c: Likewise. * tests/rt_sigqueueinfo.c: Likewise. * tests/rt_tgsigqueueinfo.c: Likewise. * tests/sched_xetaffinity.c: Likewise. * tests/sched_xetattr.c: Likewise. * tests/sched_xetparam.c: Likewise. * tests/sched_xetscheduler.c: Likewise. * tests/signal_receive.c: Likewise. * tests/so_peercred.c: Likewise. * tests/xet_robust_list.c: Likewise. * tests/xetpgid.c: Likewise. * tests/xetpriority.c: Likewise. --- tests/.gitignore | 31 ++++++++ tests/Makefile.am | 36 +++++++++ tests/fcntl--pidns-translation.c | 2 + tests/fcntl-common.c | 78 ++++++++++++++----- tests/fcntl.c | 1 + tests/fcntl64--pidns-translation.c | 2 + tests/fcntl64.c | 3 + tests/fork--pidns-translation.awk | 15 ++++ tests/fork--pidns-translation.c | 69 ++++++++++++++++ tests/fork--pidns-translation.test | 14 ++++ tests/gen_tests.in | 29 ++++++- tests/getpgrp--pidns-translation.c | 2 + tests/getpgrp.c | 8 +- tests/getpid--pidns-translation.c | 2 + tests/getpid.c | 8 +- tests/getsid--pidns-translation.c | 2 + tests/getsid.c | 9 ++- tests/gettid--pidns-translation.c | 2 + tests/gettid--pidns-translation.test | 18 +++++ tests/gettid.c | 8 +- tests/ioctl_block--pidns-translation.c | 2 + tests/ioctl_block--pidns-translation.test | 22 ++++++ tests/ioctl_block.c | 24 +++++- tests/ioprio--pidns-translation.c | 2 + tests/ioprio.c | 54 ++++++++----- tests/kcmp-y--pidns-translation.c | 2 + tests/kcmp.c | 11 ++- tests/kill--pidns-translation.c | 2 + tests/kill.c | 12 ++- tests/migrate_pages--pidns-translation.c | 2 + tests/migrate_pages.c | 17 +++- tests/move_pages--pidns-translation.c | 2 + tests/move_pages.c | 51 +++++++----- tests/net-sockaddr--pidns-translation.c | 2 + tests/net-sockaddr.c | 60 +++++++++++++- tests/netlink_audit--pidns-translation.c | 2 + tests/netlink_audit--pidns-translation.test | 13 ++++ tests/netlink_audit.c | 11 ++- tests/pidfd_open--pidns-translation.c | 2 + tests/pidfd_open.c | 21 +++-- tests/pidfd_send_signal--pidns-translation.c | 2 + tests/pidfd_send_signal.c | 13 +++- tests/prlimit64--pidns-translation.c | 2 + tests/prlimit64.c | 17 +++- tests/process_vm_readv--pidns-translation.c | 2 + tests/process_vm_readv_writev.c | 27 ++++--- tests/process_vm_writev--pidns-translation.c | 2 + tests/rt_sigqueueinfo--pidns-translation.c | 2 + tests/rt_sigqueueinfo.c | 15 +++- tests/rt_tgsigqueueinfo--pidns-translation.c | 2 + tests/rt_tgsigqueueinfo.c | 26 ++++--- tests/sched_xetaffinity--pidns-translation.c | 2 + tests/sched_xetaffinity.c | 31 +++++--- tests/sched_xetattr--pidns-translation.c | 2 + tests/sched_xetattr.c | 47 ++++++++++- tests/sched_xetparam--pidns-translation.c | 2 + tests/sched_xetparam.c | 20 +++-- tests/sched_xetscheduler--pidns-translation.c | 2 + tests/sched_xetscheduler.c | 44 +++++++---- tests/signal_receive--pidns-translation.c | 2 + tests/signal_receive.c | 22 ++++-- tests/so_peercred--pidns-translation.c | 2 + tests/so_peercred.c | 22 ++++++ tests/xet_robust_list--pidns-translation.c | 2 + tests/xet_robust_list.c | 18 ++++- tests/xetpgid--pidns-translation.c | 2 + tests/xetpgid.c | 21 +++-- tests/xetpriority--pidns-translation.c | 2 + tests/xetpriority.c | 20 ++++- 69 files changed, 861 insertions(+), 165 deletions(-) create mode 100644 tests/fcntl--pidns-translation.c create mode 100644 tests/fcntl64--pidns-translation.c create mode 100644 tests/fork--pidns-translation.awk create mode 100644 tests/fork--pidns-translation.c create mode 100755 tests/fork--pidns-translation.test create mode 100644 tests/getpgrp--pidns-translation.c create mode 100644 tests/getpid--pidns-translation.c create mode 100644 tests/getsid--pidns-translation.c create mode 100644 tests/gettid--pidns-translation.c create mode 100755 tests/gettid--pidns-translation.test create mode 100644 tests/ioctl_block--pidns-translation.c create mode 100755 tests/ioctl_block--pidns-translation.test create mode 100644 tests/ioprio--pidns-translation.c create mode 100644 tests/kcmp-y--pidns-translation.c create mode 100644 tests/kill--pidns-translation.c create mode 100644 tests/migrate_pages--pidns-translation.c create mode 100644 tests/move_pages--pidns-translation.c create mode 100644 tests/net-sockaddr--pidns-translation.c create mode 100644 tests/netlink_audit--pidns-translation.c create mode 100755 tests/netlink_audit--pidns-translation.test create mode 100644 tests/pidfd_open--pidns-translation.c create mode 100644 tests/pidfd_send_signal--pidns-translation.c create mode 100644 tests/prlimit64--pidns-translation.c create mode 100644 tests/process_vm_readv--pidns-translation.c create mode 100644 tests/process_vm_writev--pidns-translation.c create mode 100644 tests/rt_sigqueueinfo--pidns-translation.c create mode 100644 tests/rt_tgsigqueueinfo--pidns-translation.c create mode 100644 tests/sched_xetaffinity--pidns-translation.c create mode 100644 tests/sched_xetattr--pidns-translation.c create mode 100644 tests/sched_xetparam--pidns-translation.c create mode 100644 tests/sched_xetscheduler--pidns-translation.c create mode 100644 tests/signal_receive--pidns-translation.c create mode 100644 tests/so_peercred--pidns-translation.c create mode 100644 tests/xet_robust_list--pidns-translation.c create mode 100644 tests/xetpgid--pidns-translation.c create mode 100644 tests/xetpriority--pidns-translation.c diff --git a/tests/.gitignore b/tests/.gitignore index 0031d04d..4d1153fc 100644 --- a/tests/.gitignore +++ b/tests/.gitignore @@ -116,7 +116,9 @@ fchown fchown32 fchownat fcntl +fcntl--pidns-translation fcntl64 +fcntl64--pidns-translation fdatasync fflush file_handle @@ -126,6 +128,7 @@ filter-unavailable finit_module flock fork-f +fork--pidns-translation fsconfig fsconfig-P fsmount @@ -168,7 +171,9 @@ getgroups getgroups32 getpeername getpgrp +getpgrp--pidns-translation getpid +getpid--pidns-translation getppid getrandom getresgid @@ -178,8 +183,10 @@ getresuid32 getrlimit getrusage getsid +getsid--pidns-translation getsockname gettid +gettid--pidns-translation getuid getuid32 getxgid @@ -200,6 +207,7 @@ io_uring_register io_uring_setup ioctl ioctl_block +ioctl_block--pidns-translation ioctl_dm ioctl_dm-v ioctl_evdev @@ -275,6 +283,7 @@ ioctl_watchdog ioperm iopl ioprio +ioprio--pidns-translation ioprio-Xabbrev ioprio-Xraw ioprio-Xverbose @@ -299,6 +308,7 @@ ipc_shm-Xverbose is_linux_mips_n64 kcmp kcmp-y +kcmp-y--pidns-translation kern_features kernel_version kernel_version-Xabbrev @@ -311,6 +321,7 @@ keyctl-Xabbrev keyctl-Xraw keyctl-Xverbose kill +kill--pidns-translation kill_child ksysent ksysent.h @@ -340,6 +351,7 @@ memfd_create-Xabbrev memfd_create-Xraw memfd_create-Xverbose migrate_pages +migrate_pages--pidns-translation mincore mkdir mkdirat @@ -371,6 +383,7 @@ move_pages move_pages-Xabbrev move_pages-Xraw move_pages-Xverbose +move_pages--pidns-translation mq mq_sendrecv mq_sendrecv-read @@ -391,6 +404,7 @@ net-packet_mreq-Xabbrev net-packet_mreq-Xraw net-packet_mreq-Xverbose net-sockaddr +net-sockaddr--pidns-translation net-tpacket_req net-tpacket_stats net-tpacket_stats-success @@ -400,6 +414,7 @@ net-yy-inet6 net-yy-netlink net-yy-unix netlink_audit +netlink_audit--pidns-translation netlink_crypto netlink_generic netlink_inet_diag @@ -507,7 +522,9 @@ pidfd_open--decode-fd-socket pidfd_open-P pidfd_open-y pidfd_open-yy +pidfd_open--pidns-translation pidfd_send_signal +pidfd_send_signal--pidns-translation pipe pipe2 pkey_alloc @@ -546,8 +563,11 @@ printstrn-umoven printstrn-umoven-peekdata printstrn-umoven-undumpable prlimit64 +prlimit64--pidns-translation process_vm_readv +process_vm_readv--pidns-translation process_vm_writev +process_vm_writev--pidns-translation pselect6 ptrace ptrace_syscall_info @@ -597,10 +617,12 @@ rt_sigaction rt_sigpending rt_sigprocmask rt_sigqueueinfo +rt_sigqueueinfo--pidns-translation rt_sigreturn rt_sigsuspend rt_sigtimedwait rt_tgsigqueueinfo +rt_tgsigqueueinfo--pidns-translation run_expect_termsig s390_guarded_storage s390_guarded_storage-v @@ -611,9 +633,13 @@ s390_sthyi-v sched_get_priority_mxx sched_rr_get_interval sched_xetaffinity +sched_xetaffinity--pidns-translation sched_xetattr +sched_xetattr--pidns-translation sched_xetparam +sched_xetparam--pidns-translation sched_xetscheduler +sched_xetscheduler--pidns-translation sched_yield scm_rights scno.h @@ -669,6 +695,7 @@ sigaltstack siginfo signal signal_receive +signal_receive--pidns-translation signalfd4 sigpending sigprocmask @@ -681,6 +708,7 @@ so_peercred so_peercred-Xabbrev so_peercred-Xraw so_peercred-Xverbose +so_peercred--pidns-translation sock_filter-v sock_filter-v-Xabbrev sock_filter-v-Xraw @@ -783,9 +811,12 @@ waitpid xattr xattr-strings xet_robust_list +xet_robust_list--pidns-translation xet_thread_area_x86 xetitimer xetpgid +xetpgid--pidns-translation xetpriority +xetpriority--pidns-translation xettimeofday zeroargc diff --git a/tests/Makefile.am b/tests/Makefile.am index 7a583a3a..f2c5da83 100644 --- a/tests/Makefile.am +++ b/tests/Makefile.am @@ -109,17 +109,25 @@ check_PROGRAMS = $(PURE_EXECUTABLES) \ delay \ execve-v \ execveat-v \ + fcntl--pidns-translation \ + fcntl64--pidns-translation \ filter_seccomp-flag \ filter_seccomp-perf \ filter-unavailable \ fork-f \ + fork--pidns-translation \ fsync-y \ get_process_reaper \ + getpgrp--pidns-translation \ getpid \ + getpid--pidns-translation \ getppid \ + getsid--pidns-translation \ gettid \ + gettid--pidns-translation \ inject-nf \ int_0x80 \ + ioctl_block--pidns-translation \ ioctl_dm-v \ ioctl_evdev-success \ ioctl_evdev-success-Xabbrev \ @@ -150,18 +158,25 @@ check_PROGRAMS = $(PURE_EXECUTABLES) \ ioctl_v4l2-success-v-Xabbrev \ ioctl_v4l2-success-v-Xraw \ ioctl_v4l2-success-v-Xverbose \ + ioprio--pidns-translation \ is_linux_mips_n64 \ + kcmp-y--pidns-translation \ kill_child \ + kill--pidns-translation \ ksysent \ list_sigaction_signum \ localtime \ looping_threads \ + migrate_pages--pidns-translation \ mmsg-silent \ mmsg_name-v \ + move_pages--pidns-translation \ msg_control-v \ net-accept-connect \ + net-sockaddr--pidns-translation \ net-tpacket_stats-success \ nlattr_ifla_xdp-y \ + netlink_audit--pidns-translation \ netlink_inet_diag \ netlink_netlink_diag \ netlink_unix_diag \ @@ -173,14 +188,19 @@ check_PROGRAMS = $(PURE_EXECUTABLES) \ pc \ perf_event_open_nonverbose \ perf_event_open_unabbrev \ + pidfd_open--pidns-translation \ + pidfd_send_signal--pidns-translation \ poll-P \ ppoll-P \ ppoll-v \ + prlimit64--pidns-translation \ prctl-seccomp-filter-v \ prctl-seccomp-strict \ prctl-spec-inject \ print_maxfd \ print_ppid_tracerpid \ + process_vm_readv--pidns-translation \ + process_vm_writev--pidns-translation \ qual_fault \ qual_inject-error-signal \ qual_inject-retval \ @@ -194,7 +214,13 @@ check_PROGRAMS = $(PURE_EXECUTABLES) \ quotactl-xfs-v \ redirect-fds \ restart_syscall \ + rt_sigqueueinfo--pidns-translation \ + rt_tgsigqueueinfo--pidns-translation \ run_expect_termsig \ + sched_xetaffinity--pidns-translation \ + sched_xetattr--pidns-translation \ + sched_xetparam--pidns-translation \ + sched_xetscheduler--pidns-translation \ scm_rights \ seccomp-filter-v \ seccomp-strict \ @@ -204,12 +230,14 @@ check_PROGRAMS = $(PURE_EXECUTABLES) \ set_sigign \ setpgrp-exec \ signal_receive \ + signal_receive--pidns-translation \ sleep \ stack-fcall \ stack-fcall-attach \ stack-fcall-mangled \ status-none-threads \ status-unfinished-threads \ + so_peercred--pidns-translation \ syslog-success \ threads-execve \ threads-execve--quiet-thread-execve \ @@ -223,6 +251,9 @@ check_PROGRAMS = $(PURE_EXECUTABLES) \ vfork-f \ wait4-v \ waitid-v \ + xetpgid--pidns-translation \ + xetpriority--pidns-translation \ + xet_robust_list--pidns-translation \ zeroargc \ # end of check_PROGRAMS @@ -310,6 +341,7 @@ DECODER_TESTS = \ int_0x80.test \ inotify_init-y.test \ ioctl.test \ + ioctl_block--pidns-translation.test \ ioctl_evdev-success.test \ ipc_msgbuf.test \ kern_features-fault.test \ @@ -381,12 +413,15 @@ MISC_TESTS = \ filtering_fd-syntax.test \ filtering_syscall-syntax.test \ first_exec_failure.test \ + fork--pidns-translation.test \ get_regs.test \ + gettid--pidns-translation.test \ inject-nf.test \ interactive_block.test \ kill_child.test \ localtime.test \ looping_threads.test \ + netlink_audit--pidns-translation.test \ opipe.test \ options-syntax.test \ pc.test \ @@ -467,6 +502,7 @@ EXTRA_DIST = \ filter_seccomp.in \ filter_seccomp.sh \ filter-unavailable.expected \ + fork--pidns-translation.awk \ fstatat.c \ fstatx.c \ gen_pure_executables.sh \ diff --git a/tests/fcntl--pidns-translation.c b/tests/fcntl--pidns-translation.c new file mode 100644 index 00000000..e249424a --- /dev/null +++ b/tests/fcntl--pidns-translation.c @@ -0,0 +1,2 @@ +#define PIDNS_TRANSLATION +#include "fcntl.c" diff --git a/tests/fcntl-common.c b/tests/fcntl-common.c index 27694326..ec18aa79 100644 --- a/tests/fcntl-common.c +++ b/tests/fcntl-common.c @@ -13,6 +13,8 @@ #include #include #include "flock.h" +#include "pidns.h" +#include "scno.h" #define FILE_LEN 4096 @@ -48,12 +50,14 @@ test_flock_einval(const int cmd, const char *name) fl->l_len = (TYPEOF_FLOCK_OFF_T) 0xdefaced2cafef00dULL; invoke_test_syscall(0, cmd, fl); + pidns_print_leader(); printf("%s(0, %s, {l_type=F_RDLCK, l_whence=SEEK_SET" ", l_start=%jd, l_len=%jd}) = %s\n", TEST_SYSCALL_STR, name, (intmax_t) fl->l_start, (intmax_t) fl->l_len, errstr); void *const bad_addr = (void *) fl + 1; invoke_test_syscall(0, cmd, bad_addr); + pidns_print_leader(); printf("%s(0, %s, %p) = %s\n", TEST_SYSCALL_STR, name, bad_addr, errstr); } @@ -72,12 +76,14 @@ test_flock64_einval(const int cmd, const char *name) fl->l_len = (TYPEOF_FLOCK_OFF_T) 0xdefaced2cafef00dULL; invoke_test_syscall(0, cmd, fl); + pidns_print_leader(); printf("%s(0, %s, {l_type=F_RDLCK, l_whence=SEEK_SET" ", l_start=%jd, l_len=%jd}) = %s\n", TEST_SYSCALL_STR, name, (intmax_t) fl->l_start, (intmax_t) fl->l_len, errstr); void *const bad_addr = (void *) fl + 1; invoke_test_syscall(0, cmd, bad_addr); + pidns_print_leader(); printf("%s(0, %s, %p) = %s\n", TEST_SYSCALL_STR, name, bad_addr, errstr); } @@ -94,6 +100,7 @@ test_flock(void) fl->l_len = FILE_LEN; long rc = invoke_test_syscall(0, F_SETLK, fl); + pidns_print_leader(); printf("%s(0, F_SETLK, {l_type=F_RDLCK, l_whence=SEEK_SET" ", l_start=0, l_len=%d}) = %s\n", TEST_SYSCALL_STR, FILE_LEN, errstr); @@ -101,11 +108,13 @@ test_flock(void) return; invoke_test_syscall(0, F_GETLK, fl); + pidns_print_leader(); printf("%s(0, F_GETLK, {l_type=F_UNLCK, l_whence=SEEK_SET" ", l_start=0, l_len=%d, l_pid=0}) = 0\n", TEST_SYSCALL_STR, FILE_LEN); invoke_test_syscall(0, F_SETLKW, fl); + pidns_print_leader(); printf("%s(0, F_SETLKW, {l_type=F_UNLCK, l_whence=SEEK_SET" ", l_start=0, l_len=%d}) = 0\n", TEST_SYSCALL_STR, FILE_LEN); @@ -124,6 +133,7 @@ test_flock64_ofd(void) fl->l_len = FILE_LEN; long rc = invoke_test_syscall(0, F_OFD_SETLK, fl); + pidns_print_leader(); printf("%s(0, F_OFD_SETLK, {l_type=F_RDLCK, l_whence=SEEK_SET" ", l_start=0, l_len=%d}) = %s\n", TEST_SYSCALL_STR, FILE_LEN, errstr); @@ -131,11 +141,13 @@ test_flock64_ofd(void) return; invoke_test_syscall(0, F_OFD_GETLK, fl); + pidns_print_leader(); printf("%s(0, F_OFD_GETLK, {l_type=F_UNLCK, l_whence=SEEK_SET" ", l_start=0, l_len=%d, l_pid=0}) = 0\n", TEST_SYSCALL_STR, FILE_LEN); invoke_test_syscall(0, F_OFD_SETLKW, fl); + pidns_print_leader(); printf("%s(0, F_OFD_SETLKW, {l_type=F_UNLCK, l_whence=SEEK_SET" ", l_start=0, l_len=%d}) = 0\n", TEST_SYSCALL_STR, FILE_LEN); @@ -167,18 +179,21 @@ test_flock64(void) static long test_f_owner_ex_type_pid(const int cmd, const char *const cmd_name, const int type, const char *const type_name, - pid_t pid) + enum pid_type pid_type, pid_t pid) { TAIL_ALLOC_OBJECT_CONST_PTR(struct_kernel_f_owner_ex, fo); fo->type = type; fo->pid = pid; long rc = invoke_test_syscall(0, cmd, fo); - printf("%s(0, %s, {type=%s, pid=%d}) = %s\n", - TEST_SYSCALL_STR, cmd_name, type_name, fo->pid, errstr); + pidns_print_leader(); + printf("%s(0, %s, {type=%s, pid=%d%s}) = %s\n", + TEST_SYSCALL_STR, cmd_name, type_name, + fo->pid, pidns_pid2str(pid_type), errstr); void *bad_addr = (void *) fo + 1; invoke_test_syscall(0, cmd, bad_addr); + pidns_print_leader(); printf("%s(0, %s, %p) = %s\n", TEST_SYSCALL_STR, cmd_name, bad_addr, errstr); @@ -187,35 +202,35 @@ test_f_owner_ex_type_pid(const int cmd, const char *const cmd_name, static void test_f_owner_ex_umove_or_printaddr(const int type, const char *const type_name, - pid_t pid) + enum pid_type pid_type, pid_t pid) { long rc = test_f_owner_ex_type_pid(ARG_STR(F_SETOWN_EX), - type, type_name, pid); + type, type_name, pid_type, pid); if (!rc) test_f_owner_ex_type_pid(ARG_STR(F_GETOWN_EX), - type, type_name, pid); + type, type_name, pid_type, pid); } static void test_f_owner_ex(void) { - static const struct { + struct { int type; const char *type_name; - pid_t pid[2]; + enum pid_type pid_type; + pid_t pid; } a[] = { - { ARG_STR(F_OWNER_TID), { 1234567890, 20 } }, - { ARG_STR(F_OWNER_PID), { 1298126790, 30 } }, - { ARG_STR(F_OWNER_PGRP), { 1294567890, 40 } } + { ARG_STR(F_OWNER_TID), PT_NONE, 1234567890 }, + { ARG_STR(F_OWNER_PID), PT_NONE, 1234567890 }, + { ARG_STR(F_OWNER_PGRP), PT_NONE, 1234567890 }, + { ARG_STR(F_OWNER_TID), PT_TID, syscall(__NR_gettid) }, + { ARG_STR(F_OWNER_PID), PT_TGID, getpid() }, + { ARG_STR(F_OWNER_PGRP), PT_PGID, getpgid(0) }, }; - for (unsigned int i = 0; i < ARRAY_SIZE(a); i++) { - for (unsigned int j = 0; j < ARRAY_SIZE(a[0].pid); j++) { - test_f_owner_ex_umove_or_printaddr(a[i].type, - a[i].type_name, - a[i].pid[j]); - } - } + for (unsigned int i = 0; i < ARRAY_SIZE(a); i++) + test_f_owner_ex_umove_or_printaddr(a[i].type, a[i].type_name, + a[i].pid_type, a[i].pid); } #endif /* TEST_F_OWNER_EX */ @@ -228,6 +243,23 @@ struct fcntl_cmd_check { void (*print_flags)(long rc); }; +static void +test_xetown(void) +{ + const int pid = getpid(); + const char *pid_str = pidns_pid2str(PT_TGID); + + invoke_test_syscall(0, F_SETOWN, (void *) (intptr_t) pid); + pidns_print_leader(); + printf("%s(0, F_SETOWN, %d%s) = %s\n", + TEST_SYSCALL_STR, pid, pid_str, errstr); + + invoke_test_syscall(0, F_GETOWN, NULL); + pidns_print_leader(); + printf("%s(0, F_GETOWN) = %d%s\n", + TEST_SYSCALL_STR, pid, pid_str); +} + static void print_retval_flags(const struct fcntl_cmd_check *check, long rc) { @@ -243,12 +275,14 @@ static void test_other_set_cmd(const struct fcntl_cmd_check *check) { invoke_test_syscall(check->fd, check->cmd, (void *) check->arg); + pidns_print_leader(); printf("%s(%d, %s, %s) = %s\n", TEST_SYSCALL_STR, check->fd, check->cmd_str, check->arg_str, errstr); /* bad file fd */ invoke_test_syscall(-1, check->cmd, (void *) check->arg); + pidns_print_leader(); printf("%s(-1, %s, %s) = %s\n", TEST_SYSCALL_STR, check->cmd_str, check->arg_str, errstr); @@ -258,12 +292,14 @@ static void test_other_get_cmd(const struct fcntl_cmd_check *check) { long rc = invoke_test_syscall(check->fd, check->cmd, NULL); + pidns_print_leader(); printf("%s(%d, %s) = ", TEST_SYSCALL_STR, check->fd, check->cmd_str); print_retval_flags(check, rc); /* bad file fd */ invoke_test_syscall(-1, check->cmd, NULL); + pidns_print_leader(); printf("%s(-1, %s) = %s\n", TEST_SYSCALL_STR, check->cmd_str, errstr); } @@ -315,7 +351,6 @@ test_fcntl_others(void) { static const struct fcntl_cmd_check set_checks[] = { { 0, ARG_STR(F_SETFD), ARG_STR(FD_CLOEXEC) }, - { 0, ARG_STR(F_SETOWN), ARG_STR(20) }, #ifdef F_SETPIPE_SZ { 0, ARG_STR(F_SETPIPE_SZ), ARG_STR(4097) }, #endif @@ -336,7 +371,6 @@ test_fcntl_others(void) static const struct fcntl_cmd_check get_checks[] = { { 0, ARG_STR(F_GETFD), .print_flags = print_flags_getfd }, { 1, ARG_STR(F_GETFD), .print_flags = print_flags_getfd }, - { 0, ARG_STR(F_GETOWN) }, #ifdef F_GETPIPE_SZ { 0, ARG_STR(F_GETPIPE_SZ) }, #endif @@ -360,6 +394,8 @@ create_sample(void) int main(void) { + PIDNS_TEST_INIT; + create_sample(); test_flock(); test_flock64(); @@ -367,7 +403,9 @@ main(void) test_f_owner_ex(); #endif test_fcntl_others(); + test_xetown(); + pidns_print_leader(); puts("+++ exited with 0 +++"); return 0; } diff --git a/tests/fcntl.c b/tests/fcntl.c index f38b8afb..673c06e4 100644 --- a/tests/fcntl.c +++ b/tests/fcntl.c @@ -24,6 +24,7 @@ test_flock64_undecoded(const int cmd, const char *name) .l_len = 0xdefaced2cafef00dULL }; invoke_test_syscall(0, cmd, &fl); + pidns_print_leader(); printf("%s(0, %s, %p) = %s\n", TEST_SYSCALL_STR, name, &fl, errstr); } diff --git a/tests/fcntl64--pidns-translation.c b/tests/fcntl64--pidns-translation.c new file mode 100644 index 00000000..c6fdadd1 --- /dev/null +++ b/tests/fcntl64--pidns-translation.c @@ -0,0 +1,2 @@ +#define PIDNS_TRANSLATION +#include "fcntl64.c" diff --git a/tests/fcntl64.c b/tests/fcntl64.c index 78e53b0d..f7b3f2fb 100644 --- a/tests/fcntl64.c +++ b/tests/fcntl64.c @@ -27,6 +27,7 @@ test_flock64_lk64(void) fl->l_len = FILE_LEN; long rc = invoke_test_syscall(0, F_SETLK64, fl); + pidns_print_leader(); printf("%s(0, F_SETLK64, {l_type=F_RDLCK, l_whence=SEEK_SET" ", l_start=0, l_len=%d}) = %s\n", TEST_SYSCALL_STR, FILE_LEN, errstr); @@ -35,11 +36,13 @@ test_flock64_lk64(void) return; invoke_test_syscall(0, F_GETLK64, fl); + pidns_print_leader(); printf("%s(0, F_GETLK64, {l_type=F_UNLCK, l_whence=SEEK_SET" ", l_start=0, l_len=%d, l_pid=0}) = 0\n", TEST_SYSCALL_STR, FILE_LEN); invoke_test_syscall(0, F_SETLKW64, fl); + pidns_print_leader(); printf("%s(0, F_SETLKW64, {l_type=F_UNLCK, l_whence=SEEK_SET" ", l_start=0, l_len=%d}) = 0\n", TEST_SYSCALL_STR, FILE_LEN); diff --git a/tests/fork--pidns-translation.awk b/tests/fork--pidns-translation.awk new file mode 100644 index 00000000..ef6858f4 --- /dev/null +++ b/tests/fork--pidns-translation.awk @@ -0,0 +1,15 @@ +/fork/ { + match($0, "([0-9]+) in strace\x27s PID NS", a); + if (a[1]) + fork_pid = a[1] +} + +/exited with 0/ { + if (!exit_pid) + exit_pid = $1 +} + +END { + if (!fork_pid || !exit_pid || fork_pid != exit_pid) + exit 1 +} diff --git a/tests/fork--pidns-translation.c b/tests/fork--pidns-translation.c new file mode 100644 index 00000000..73c39d5d --- /dev/null +++ b/tests/fork--pidns-translation.c @@ -0,0 +1,69 @@ +/* + * Test PID namespace translation + * + * Copyright (c) 2020 ?kos Uzonyi + * All rights reserved. + * + * SPDX-License-Identifier: LGPL-2.1-or-later + */ + +#include "tests.h" +#include "scno.h" +#include "pidns.h" + +#ifdef __NR_fork + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +static int +fork_chain(int depth) +{ + if (!depth) + return 0; + + int pid = syscall(__NR_fork); + if (pid < 0) + return errno; + + if (!pid) + _exit(fork_chain(depth - 1)); + + int status; + if (wait(&status) < 0) + return errno; + + if (!WIFEXITED(status)) + return -1; + + return WEXITSTATUS(status); +} + +int main(void) +{ + check_ns_ioctl(); + + if (unshare(CLONE_NEWPID | CLONE_NEWUSER) < 0) { + if (errno == EPERM) + perror_msg_and_skip("unshare"); + + perror_msg_and_fail("unshare"); + } + + errno = fork_chain(2); + if (errno) + perror("fork_chain"); +} + +#else + +SKIP_MAIN_UNDEFINED("__NR_fork") + +#endif diff --git a/tests/fork--pidns-translation.test b/tests/fork--pidns-translation.test new file mode 100755 index 00000000..24cc5930 --- /dev/null +++ b/tests/fork--pidns-translation.test @@ -0,0 +1,14 @@ +#!/bin/sh +# +# Check pidns translation of fork's return value. +# +# Copyright (c) 2020 The strace developers. +# All rights reserved. +# +# SPDX-License-Identifier: LGPL-2.1-or-later + +. "${srcdir=.}/init.sh" + +run_prog +run_strace -a6 --pidns-translation -f -e trace=fork $args +match_awk diff --git a/tests/gen_tests.in b/tests/gen_tests.in index 6f8e1420..10374a9e 100644 --- a/tests/gen_tests.in +++ b/tests/gen_tests.in @@ -93,7 +93,9 @@ fchown -a16 fchown32 -a18 fchownat fcntl -a8 +fcntl--pidns-translation test_pidns -a8 -e trace=fcntl fcntl64 -a8 +fcntl64--pidns-translation test_pidns -a8 -e trace=fcntl64 fdatasync -a14 file_handle -e trace=name_to_handle_at,open_by_handle_at file_ioctl +ioctl.test @@ -147,7 +149,9 @@ getgroups -a17 getgroups32 -a19 getpeername -a27 getpgrp -a10 +getpgrp--pidns-translation test_pidns -e trace=getpgrp -a10 getpid -a9 +getpid--pidns-translation test_pidns -e trace=getpid -a9 getppid -a10 getrandom -a32 -s3 getresgid -a25 @@ -157,6 +161,7 @@ getresuid32 -a27 getrlimit -a27 getrusage -v getsid -a10 +getsid--pidns-translation test_pidns -e trace=getsid -a10 getsockname -a27 gettid -a9 getuid-creds +getuid.test @@ -250,6 +255,7 @@ ioctl_watchdog +ioctl.test ioperm -a27 iopl -a8 ioprio -a18 -e trace=ioprio_get,ioprio_set +ioprio--pidns-translation test_pidns -a18 -e trace=ioprio_get,ioprio_set ioprio-Xabbrev -a18 -e trace=ioprio_get,ioprio_set -Xabbrev ioprio-Xraw -a18 -e trace=ioprio_get,ioprio_set -Xraw ioprio-Xverbose -a18 -e trace=ioprio_get,ioprio_set -Xverbose @@ -272,6 +278,7 @@ ipc_shm-Xraw +ipc.sh -Xraw -a19 ipc_shm-Xverbose +ipc.sh -Xverbose -a34 kcmp -a22 kcmp-y -a22 -y -e trace=kcmp +kcmp-y--pidns-translation test_pidns -a22 -y -e trace=kcmp kern_features -a16 kernel_version -a16 -v -e trace=bpf kernel_version-Xabbrev -a16 -Xabbrev -v -e trace=bpf @@ -284,6 +291,7 @@ keyctl-Xabbrev -a31 -s10 -e trace=keyctl -Xabbrev keyctl-Xraw -a13 -s10 -e trace=keyctl -Xraw keyctl-Xverbose -a41 -s10 -e trace=keyctl -Xverbose kill -a12 -esignal=none +kill--pidns-translation test_pidns -a12 -e trace=kill -esignal=none ksysent ../$NAME lchown -a30 lchown32 -a32 @@ -305,6 +313,7 @@ memfd_create-Xabbrev -Xabbrev -e trace=memfd_create memfd_create-Xraw -a30 -Xraw -e trace=memfd_create memfd_create-Xverbose -Xverbose -e trace=memfd_create migrate_pages -a33 +migrate_pages--pidns-translation test_pidns -a33 -e trace=migrate_pages mincore -a22 mkdir -a20 mkdirat -a28 @@ -335,6 +344,7 @@ move_pages -s3 move_pages-Xabbrev -s3 -e trace=move_pages -Xabbrev move_pages-Xraw -s3 -a36 -e trace=move_pages -Xraw move_pages-Xverbose -s3 -e trace=move_pages -Xverbose +move_pages--pidns-translation test_pidns -s3 -e trace=move_pages mq -a32 -e trace=mq_getsetattr,mq_open,mq_unlink mq_sendrecv -a14 -e trace=mq_open,mq_notify,mq_timedsend,mq_timedreceive,mq_unlink mq_sendrecv-read -eread=0 -a14 -e trace=mq_open,mq_notify,mq_timedsend,mq_timedreceive,mq_unlink @@ -354,6 +364,7 @@ net-packet_mreq-Xabbrev -e trace=setsockopt -Xabbrev net-packet_mreq-Xraw -e trace=setsockopt -Xraw net-packet_mreq-Xverbose -e trace=setsockopt -Xverbose net-sockaddr -a24 -e trace=connect +net-sockaddr--pidns-translation test_pidns -a24 -e trace=connect net-tpacket_req -e trace=setsockopt net-tpacket_stats -e trace=getsockopt net-yy-inet6 +net-yy-inet.test @@ -457,7 +468,9 @@ pidfd_open--decode-fd-socket -a17 -e decode-fd=socket -e trace=pidfd_open pidfd_open-P -a17 -P /dev/full -e trace=pidfd_open pidfd_open-y -a17 -y -e trace=pidfd_open pidfd_open-yy -a17 -yy -e trace=pidfd_open +pidfd_open--pidns-translation test_pidns -a17 -e trace=pidfd_open pidfd_send_signal +pidfd_send_signal--pidns-translation test_pidns -e trace=pidfd_send_signal pipe2 -a15 pkey_alloc -a17 pkey_free -a13 @@ -480,8 +493,11 @@ printstrn-umoven -s4096 -e signal=none -e trace=add_key printstrn-umoven-peekdata -e signal=none -e trace=add_key printstrn-umoven-undumpable -e signal=none -e trace=add_key prlimit64 +prlimit64--pidns-translation test_pidns -e trace=prlimit64 process_vm_readv -s5 -a37 +process_vm_readv--pidns-translation test_pidns -s5 -a37 -e trace=process_vm_readv process_vm_writev -s5 -a38 +process_vm_writev--pidns-translation test_pidns -s5 -a38 -e trace=process_vm_writev pselect6 ptrace -a23 -e signal=none ptrace_syscall_info -a35 -e signal=none -e trace=ptrace @@ -518,10 +534,12 @@ rmdir -a22 rt_sigpending -a20 rt_sigprocmask rt_sigqueueinfo -esignal=none +rt_sigqueueinfo--pidns-translation test_pidns -esignal=none -e trace=rt_sigqueueinfo rt_sigreturn -esignal='!USR1' rt_sigsuspend -a20 -esignal=none rt_sigtimedwait -a38 rt_tgsigqueueinfo -esignal=none +rt_tgsigqueueinfo--pidns-translation test_pidns -esignal=none -e trace=rt_tgsigqueueinfo s390_guarded_storage -a32 s390_guarded_storage-v -e trace=s390_guarded_storage -a32 -v s390_pci_mmio_read_write -e trace=s390_pci_mmio_read,s390_pci_mmio_write -a30 @@ -532,9 +550,13 @@ sched test_trace_expr times -e/sched sched_get_priority_mxx -a33 -e trace=sched_get_priority_min,sched_get_priority_max sched_rr_get_interval -a31 sched_xetaffinity -a28 -e trace=sched_getaffinity,sched_setaffinity +sched_xetaffinity--pidns-translation test_pidns -a28 -e trace=sched_getaffinity,sched_setaffinity sched_xetattr -a29 -e trace=sched_getattr,sched_setattr +sched_xetattr--pidns-translation test_pidns -a29 -e trace=sched_getattr,sched_setattr sched_xetparam -a23 -e trace=sched_getparam,sched_setparam +sched_xetparam--pidns-translation test_pidns -a23 -e trace=sched_getparam,sched_setparam sched_xetscheduler -a22 -e trace=sched_getscheduler,sched_setscheduler +sched_xetscheduler--pidns-translation test_pidns -a22 -e trace=sched_getscheduler,sched_setscheduler sched_yield -a14 seccomp-filter -e trace=seccomp seccomp-filter-v -v -e trace=seccomp @@ -581,6 +603,7 @@ sigaction -a31 siginfo -e trace=none signal -a25 -e signal=none -e trace='/^signal$' signal_receive -a16 -e trace=kill +signal_receive--pidns-translation test_pidns -a16 -e trace=kill signalfd4 sigpending -a15 sigprocmask -a34 @@ -592,6 +615,7 @@ so_peercred -e trace=getsockopt so_peercred-Xabbrev -e trace=getsockopt -Xabbrev so_peercred-Xraw -e trace=getsockopt -Xraw -a39 so_peercred-Xverbose -e trace=getsockopt -Xverbose +so_peercred--pidns-translation test_pidns -e trace=getsockopt sock_filter-v -v -e trace=getsockopt,setsockopt sock_filter-v-Xabbrev -v -e trace=getsockopt,setsockopt -X abbrev sock_filter-v-Xraw -a 37 -v -e trace=getsockopt,setsockopt -X raw @@ -721,7 +745,10 @@ waitpid -a28 xattr -a22 -e trace=getxattr,fgetxattr,lgetxattr,setxattr,fsetxattr,lsetxattr,listxattr,flistxattr,llistxattr,removexattr,fremovexattr,lremovexattr xattr-strings -a22 -s 4 -e trace=fsetxattr xet_robust_list -a24 -e trace=get_robust_list,set_robust_list +xet_robust_list--pidns-translation test_pidns -a24 -e trace=get_robust_list,set_robust_list xetitimer -a29 -e trace=setitimer,getitimer xetpgid -a11 -e trace=getpgid,setpgid -xetpriority -a29 -e trace=getpriority,setpriority +xetpgid--pidns-translation test_pidns -a11 -e trace=getpgid,setpgid +xetpriority -a27 -e trace=getpriority,setpriority +xetpriority--pidns-translation test_pidns -a27 -e trace=getpriority,setpriority xettimeofday -a20 -e trace=gettimeofday,settimeofday diff --git a/tests/getpgrp--pidns-translation.c b/tests/getpgrp--pidns-translation.c new file mode 100644 index 00000000..de8ceb33 --- /dev/null +++ b/tests/getpgrp--pidns-translation.c @@ -0,0 +1,2 @@ +#define PIDNS_TRANSLATION +#include "getpgrp.c" diff --git a/tests/getpgrp.c b/tests/getpgrp.c index 104f4811..3f0b9dd1 100644 --- a/tests/getpgrp.c +++ b/tests/getpgrp.c @@ -7,6 +7,7 @@ #include "tests.h" #include "scno.h" +#include "pidns.h" #ifdef __NR_getpgrp @@ -16,8 +17,13 @@ int main(void) { - printf("getpgrp() = %ld\n", syscall(__NR_getpgrp)); + PIDNS_TEST_INIT; + pidns_print_leader(); + printf("getpgrp() = %d%s\n", (int) syscall(__NR_getpgrp), + pidns_pid2str(PT_PGID)); + + pidns_print_leader(); puts("+++ exited with 0 +++"); return 0; } diff --git a/tests/getpid--pidns-translation.c b/tests/getpid--pidns-translation.c new file mode 100644 index 00000000..94b12a1a --- /dev/null +++ b/tests/getpid--pidns-translation.c @@ -0,0 +1,2 @@ +#define PIDNS_TRANSLATION +#include "getpid.c" diff --git a/tests/getpid.c b/tests/getpid.c index 988f19d5..7ec4e6e8 100644 --- a/tests/getpid.c +++ b/tests/getpid.c @@ -7,6 +7,7 @@ #include "tests.h" #include "scno.h" +#include "pidns.h" #if defined __NR_getpid && (!defined __NR_getxpid || __NR_getxpid != __NR_getpid) @@ -16,7 +17,12 @@ int main(void) { - printf("getpid() = %ld\n", syscall(__NR_getpid)); + PIDNS_TEST_INIT; + + pidns_print_leader(); + printf("getpid() = %d%s\n", (int) syscall(__NR_getpid), + pidns_pid2str(PT_TGID)); + pidns_print_leader(); puts("+++ exited with 0 +++"); return 0; } diff --git a/tests/getsid--pidns-translation.c b/tests/getsid--pidns-translation.c new file mode 100644 index 00000000..7f983e87 --- /dev/null +++ b/tests/getsid--pidns-translation.c @@ -0,0 +1,2 @@ +#define PIDNS_TRANSLATION +#include "getsid.c" diff --git a/tests/getsid.c b/tests/getsid.c index 588ea4ab..3bf74734 100644 --- a/tests/getsid.c +++ b/tests/getsid.c @@ -6,15 +6,22 @@ */ #include "tests.h" +#include "pidns.h" + #include #include int main(void) { + PIDNS_TEST_INIT; + pid_t pid = getpid(); - printf("getsid(%d) = %d\n", pid, getsid(pid)); + pidns_print_leader(); + printf("getsid(%d%s) = %d%s\n", pid, pidns_pid2str(PT_TGID), + getsid(pid), pidns_pid2str(PT_SID)); + pidns_print_leader(); puts("+++ exited with 0 +++"); return 0; } diff --git a/tests/gettid--pidns-translation.c b/tests/gettid--pidns-translation.c new file mode 100644 index 00000000..500c3213 --- /dev/null +++ b/tests/gettid--pidns-translation.c @@ -0,0 +1,2 @@ +#define PIDNS_TRANSLATION +#include "gettid.c" diff --git a/tests/gettid--pidns-translation.test b/tests/gettid--pidns-translation.test new file mode 100755 index 00000000..5797cf28 --- /dev/null +++ b/tests/gettid--pidns-translation.test @@ -0,0 +1,18 @@ +#!/bin/sh +# +# Check pidns translation of gettid's return value. +# +# Copyright (c) 2020 The strace developers. +# All rights reserved. +# +# SPDX-License-Identifier: LGPL-2.1-or-later + +. "${srcdir=.}/init.sh" + +run_prog > /dev/null +run_strace -a9 --pidns-translation -f -e trace=gettid $args > "$EXP" +parent_pid="$(tail -n 2 $LOG | head -n 1 | cut -d' ' -f1)" +init_pid="$(tail -n 1 $LOG | cut -d' ' -f1)" +# uniq: filter out extra gettid calls made by musl libc +grep -E -v "^($parent_pid|$init_pid) " "$LOG" | uniq > "$OUT" +match_diff "$OUT" "$EXP" diff --git a/tests/gettid.c b/tests/gettid.c index d38918dd..314d9c2c 100644 --- a/tests/gettid.c +++ b/tests/gettid.c @@ -9,11 +9,17 @@ #include #include #include "scno.h" +#include "pidns.h" int main(void) { - printf("gettid() = %ld\n", syscall(__NR_gettid)); + PIDNS_TEST_INIT; + + pidns_print_leader(); + printf("gettid() = %d%s\n", (int) syscall(__NR_gettid), + pidns_pid2str(PT_TID)); + pidns_print_leader(); puts("+++ exited with 0 +++"); return 0; } diff --git a/tests/ioctl_block--pidns-translation.c b/tests/ioctl_block--pidns-translation.c new file mode 100644 index 00000000..5eed6076 --- /dev/null +++ b/tests/ioctl_block--pidns-translation.c @@ -0,0 +1,2 @@ +#define PIDNS_TRANSLATION +#include "ioctl_block.c" diff --git a/tests/ioctl_block--pidns-translation.test b/tests/ioctl_block--pidns-translation.test new file mode 100755 index 00000000..d06855f9 --- /dev/null +++ b/tests/ioctl_block--pidns-translation.test @@ -0,0 +1,22 @@ +#!/bin/sh +# +# Check pidns translation of ioctl(BLK*) syscall decoding. +# +# Copyright (c) 2020 The strace developers. +# All rights reserved. +# +# SPDX-License-Identifier: LGPL-2.1-or-later + +. "${srcdir=.}/init.sh" + +check_prog head +check_prog tail +check_prog cut +check_prog grep + +run_prog > /dev/null +run_strace --pidns-translation -f -a16 -e trace=ioctl $@ $args > "$EXP" +parent_pid="$(tail -n 2 $LOG | head -n 1 | cut -d' ' -f1)" +init_pid="$(tail -n 1 $LOG | cut -d' ' -f1)" +grep -E -v "^($parent_pid|$init_pid) |ioctl\([0123][,<]" "$LOG" > "$OUT" +match_diff "$OUT" "$EXP" diff --git a/tests/ioctl_block.c b/tests/ioctl_block.c index 0afe27f7..8a345f4e 100644 --- a/tests/ioctl_block.c +++ b/tests/ioctl_block.c @@ -9,7 +9,9 @@ */ #include "tests.h" +#include "pidns.h" #include +#include #include #include #include @@ -41,12 +43,15 @@ static struct xlat_data block_argless[] = { #define TEST_NULL_ARG(cmd) \ do { \ ioctl(-1, cmd, 0); \ + pidns_print_leader(); \ printf("ioctl(-1, %s, NULL) = -1 EBADF (%m)\n", #cmd); \ } while (0) int main(void) { + PIDNS_TEST_INIT; + TEST_NULL_ARG(BLKBSZGET); TEST_NULL_ARG(BLKBSZSET); TEST_NULL_ARG(BLKFRAGET); @@ -91,18 +96,22 @@ main(void) #endif ioctl(-1, BLKRASET, lmagic); + pidns_print_leader(); printf("ioctl(-1, BLKRASET, %lu) = -1 EBADF (%m)\n", lmagic); ioctl(-1, BLKFRASET, lmagic); + pidns_print_leader(); printf("ioctl(-1, BLKFRASET, %lu) = -1 EBADF (%m)\n", lmagic); TAIL_ALLOC_OBJECT_CONST_PTR(int, val_int); *val_int = magic; ioctl(-1, BLKROSET, val_int); + pidns_print_leader(); printf("ioctl(-1, BLKROSET, [%d]) = -1 EBADF (%m)\n", *val_int); ioctl(-1, BLKBSZSET, val_int); + pidns_print_leader(); printf("ioctl(-1, BLKBSZSET, [%d]) = -1 EBADF (%m)\n", *val_int); uint64_t *pair_int64 = tail_alloc(sizeof(*pair_int64) * 2); @@ -111,18 +120,21 @@ main(void) #ifdef BLKDISCARD ioctl(-1, BLKDISCARD, pair_int64); + pidns_print_leader(); printf("ioctl(-1, BLKDISCARD, [%" PRIu64 ", %" PRIu64 "])" " = -1 EBADF (%m)\n", pair_int64[0], pair_int64[1]); #endif #ifdef BLKSECDISCARD ioctl(-1, BLKSECDISCARD, pair_int64); + pidns_print_leader(); printf("ioctl(-1, BLKSECDISCARD, [%" PRIu64 ", %" PRIu64 "])" " = -1 EBADF (%m)\n", pair_int64[0], pair_int64[1]); #endif #ifdef BLKZEROOUT ioctl(-1, BLKZEROOUT, pair_int64); + pidns_print_leader(); printf("ioctl(-1, BLKZEROOUT, [%" PRIu64 ", %" PRIu64 "])" " = -1 EBADF (%m)\n", pair_int64[0], pair_int64[1]); #endif @@ -134,6 +146,7 @@ main(void) blkpg->data = (void *) (unsigned long) 0xcafef00dfffffeedULL; ioctl(-1, BLKPG, blkpg); + pidns_print_leader(); printf("ioctl(-1, BLKPG, {op=%s, flags=%d, datalen=%d" ", data=%#lx}) = -1 EBADF (%m)\n", "BLKPG_RESIZE_PARTITION", blkpg->flags, blkpg->datalen, @@ -149,6 +162,7 @@ main(void) blkpg->data = bp; ioctl(-1, BLKPG, blkpg); + pidns_print_leader(); printf("ioctl(-1, BLKPG, {op=%s, flags=%d, datalen=%d" ", data={start=%lld, length=%lld, pno=%d" ", devname=\"%.*s\"..., volname=\"%.*s\"...}})" @@ -162,25 +176,31 @@ main(void) #if defined BLKTRACESETUP && defined HAVE_STRUCT_BLK_USER_TRACE_SETUP TAIL_ALLOC_OBJECT_CONST_PTR(struct blk_user_trace_setup, buts); fill_memory(buts, sizeof(*buts)); + buts->pid = getpid(); ioctl(-1, BLKTRACESETUP, buts); + pidns_print_leader(); printf("ioctl(-1, BLKTRACESETUP, {act_mask=%hu, buf_size=%u, buf_nr=%u" - ", start_lba=%" PRI__u64 ", end_lba=%" PRI__u64 ", pid=%d})" + ", start_lba=%" PRI__u64 ", end_lba=%" PRI__u64 ", pid=%d%s})" " = -1 EBADF (%m)\n", buts->act_mask, buts->buf_size, buts->buf_nr, - buts->start_lba, buts->end_lba, buts->pid); + buts->start_lba, buts->end_lba, buts->pid, + pidns_pid2str(PT_TGID)); #endif unsigned int i; for (i = 0; i < ARRAY_SIZE(block_argless); ++i) { ioctl(-1, (unsigned long) block_argless[i].val, lmagic); + pidns_print_leader(); printf("ioctl(-1, %s) = -1 EBADF (%m)\n", block_argless[i].str); } ioctl(-1, _IOC(_IOC_READ, 0x12, 0xfe, 0xff), lmagic); + pidns_print_leader(); printf("ioctl(-1, %s, %#lx) = -1 EBADF (%m)\n", "_IOC(_IOC_READ, 0x12, 0xfe, 0xff)", lmagic); + pidns_print_leader(); puts("+++ exited with 0 +++"); return 0; } diff --git a/tests/ioprio--pidns-translation.c b/tests/ioprio--pidns-translation.c new file mode 100644 index 00000000..bcb49a8b --- /dev/null +++ b/tests/ioprio--pidns-translation.c @@ -0,0 +1,2 @@ +#define PIDNS_TRANSLATION +#include "ioprio.c" diff --git a/tests/ioprio.c b/tests/ioprio.c index 5e1e1194..110df063 100644 --- a/tests/ioprio.c +++ b/tests/ioprio.c @@ -9,8 +9,8 @@ */ #include "tests.h" - #include "scno.h" +#include "pidns.h" #if defined(__NR_ioprio_get) && defined(__NR_ioprio_set) @@ -30,12 +30,18 @@ enum { int main(void) { + PIDNS_TEST_INIT; + static const kernel_ulong_t bogus_which = (kernel_ulong_t) 0xdeadfacefa57beefULL; static const kernel_ulong_t bogus_who = (kernel_ulong_t) 0xbadc0dedda7a1057ULL; static const kernel_ulong_t bogus_ioprio = (kernel_ulong_t) 0xdec0ded1facefeedULL; + + const int pid = getpid(); + const int pgid = getpgid(0); + # if !XLAT_RAW static const char * const bogus_ioprio_str = "IOPRIO_PRIO_VALUE(0x7d677 /* IOPRIO_CLASS_??? */, 7917)"; @@ -46,6 +52,7 @@ main(void) rc = syscall(__NR_ioprio_get, bogus_which, bogus_who); errstr = sprintrc(rc); + pidns_print_leader(); # if XLAT_RAW printf("ioprio_get(%#x, %d) = %s\n", (int) bogus_which, (int) bogus_who, errstr); @@ -54,42 +61,52 @@ main(void) (int) bogus_which, (int) bogus_who, errstr); # endif - rc = syscall(__NR_ioprio_get, 1, 0); + rc = syscall(__NR_ioprio_get, 1, pid); errstr = sprintrc(rc); + pidns_print_leader(); + printf("ioprio_get("); # if XLAT_RAW - printf("ioprio_get(0x1, 0) = %s\n", errstr); + printf("0x1, "); +# elif XLAT_VERBOSE + printf("0x1 /* IOPRIO_WHO_PROCESS */, "); # else /* XLAT_ABBREV */ -# if XLAT_VERBOSE - printf("ioprio_get(0x1 /* IOPRIO_WHO_PROCESS */, 0) = %s", errstr); -# else - printf("ioprio_get(IOPRIO_WHO_PROCESS, 0) = %s", errstr); -# endif + printf("IOPRIO_WHO_PROCESS, "); +# endif + printf("%d%s) = %s", pid, pidns_pid2str(PT_TGID), errstr); +# if !XLAT_RAW if (rc >= 0) { printf(" (IOPRIO_PRIO_VALUE("); printxval(ioprio_class, (unsigned int) rc >> 13, "IOPRIO_CLASS_???"); printf(", %u))", (unsigned int) rc & 0x1fff); } - puts(""); # endif + puts(""); - rc = syscall(__NR_ioprio_set, 2, 0, 8191); + rc = syscall(__NR_ioprio_set, 2, pgid, 8191); errstr = sprintrc(rc); + pidns_print_leader(); + printf("ioprio_set("); # if XLAT_RAW - printf("ioprio_set(%#x, 0, 8191) = %s\n", 2, errstr); + printf("%#x", 2); # elif XLAT_VERBOSE - printf("ioprio_set(%#x /* IOPRIO_WHO_PGRP */, 0, 8191" - " /* IOPRIO_PRIO_VALUE(0 /* IOPRIO_CLASS_NONE */, 8191) */)" - " = %s\n", - 2, errstr); + printf("%#x /* IOPRIO_WHO_PGRP */", 2); # else /* XLAT_ABBREV */ - printf("ioprio_set(IOPRIO_WHO_PGRP, 0" - ", IOPRIO_PRIO_VALUE(IOPRIO_CLASS_NONE, 8191)) = %s\n", - errstr); + printf("IOPRIO_WHO_PGRP"); +# endif + printf(", %d%s", pgid, pidns_pid2str(PT_PGID)); +# if XLAT_RAW + printf(", 8191)"); +# elif XLAT_VERBOSE + printf(", 8191 /* IOPRIO_PRIO_VALUE(0 /* IOPRIO_CLASS_NONE */, 8191) */)"); +# else /* XLAT_ABBREV */ + printf(", IOPRIO_PRIO_VALUE(IOPRIO_CLASS_NONE, 8191))"); # endif + printf(" = %s\n", errstr); rc = syscall(__NR_ioprio_set, bogus_which, bogus_who, bogus_ioprio); errstr = sprintrc(rc); + pidns_print_leader(); # if XLAT_RAW printf("ioprio_set(%#x, %d, %d) = %s\n", (int) bogus_which, (int) bogus_who, (int) bogus_ioprio, @@ -104,6 +121,7 @@ main(void) errstr); # endif + pidns_print_leader(); puts("+++ exited with 0 +++"); return 0; diff --git a/tests/kcmp-y--pidns-translation.c b/tests/kcmp-y--pidns-translation.c new file mode 100644 index 00000000..f54d94cc --- /dev/null +++ b/tests/kcmp-y--pidns-translation.c @@ -0,0 +1,2 @@ +#define PIDNS_TRANSLATION +#include "kcmp-y.c" diff --git a/tests/kcmp.c b/tests/kcmp.c index dc5ba9a4..ce705ad0 100644 --- a/tests/kcmp.c +++ b/tests/kcmp.c @@ -9,8 +9,8 @@ */ #include "tests.h" - #include "scno.h" +#include "pidns.h" #ifdef __NR_kcmp @@ -101,7 +101,11 @@ do_kcmp(kernel_ulong_t pid1, kernel_ulong_t pid2, kernel_ulong_t type, rc = syscall(__NR_kcmp, pid1, pid2, type, idx1, idx2); errstr = sprintrc(rc); - printf("kcmp(%d, %d, ", (int) pid1, (int) pid2); + const char *pid_str = pidns_pid2str(PT_TGID); + pidns_print_leader(); + printf("kcmp(%d%s, %d%s, ", + (int) pid1, (int) pid1 == getpid() ? pid_str : "", + (int) pid2, (int) pid2 == getpid() ? pid_str : ""); if (type_str) printf("%s", type_str); @@ -146,6 +150,8 @@ do_kcmp(kernel_ulong_t pid1, kernel_ulong_t pid2, kernel_ulong_t type, int main(void) { + PIDNS_TEST_INIT; + static const kernel_ulong_t bogus_pid1 = (kernel_ulong_t) 0xdeadca75face1057ULL; static const kernel_ulong_t bogus_pid2 = @@ -221,6 +227,7 @@ main(void) (uintptr_t) slot, 1); } + pidns_print_leader(); puts("+++ exited with 0 +++"); return 0; diff --git a/tests/kill--pidns-translation.c b/tests/kill--pidns-translation.c new file mode 100644 index 00000000..4736ca14 --- /dev/null +++ b/tests/kill--pidns-translation.c @@ -0,0 +1,2 @@ +#define PIDNS_TRANSLATION +#include "kill.c" diff --git a/tests/kill.c b/tests/kill.c index f7d9341e..17de35da 100644 --- a/tests/kill.c +++ b/tests/kill.c @@ -11,6 +11,7 @@ #include "tests.h" #include "scno.h" +#include "pidns.h" #ifdef __NR_kill @@ -26,6 +27,8 @@ handler(int sig) int main(void) { + PIDNS_TEST_INIT; + const struct sigaction act = { .sa_handler = handler }; if (sigaction(SIGALRM, &act, NULL)) perror_msg_and_fail("sigaction"); @@ -37,18 +40,23 @@ main(void) perror_msg_and_fail("sigprocmask"); const int pid = getpid(); + const char *pid_str = pidns_pid2str(PT_TGID); long rc = syscall(__NR_kill, pid, (long) 0xdefaced00000000ULL | SIGALRM); - printf("kill(%d, SIGALRM) = %ld\n", pid, rc); + pidns_print_leader(); + printf("kill(%d%s, SIGALRM) = %ld\n", pid, pid_str, rc); const long big_pid = (long) 0xfacefeedbadc0dedULL; const long big_sig = (long) 0xdeadbeefcafef00dULL; rc = syscall(__NR_kill, big_pid, big_sig); + pidns_print_leader(); printf("kill(%d, %d) = %ld %s (%m)\n", (int) big_pid, (int) big_sig, rc, errno2name()); rc = syscall(__NR_kill, (long) 0xdefaced00000000ULL | pid, 0); - printf("kill(%d, 0) = %ld\n", pid, rc); + pidns_print_leader(); + printf("kill(%d%s, 0) = %ld\n", pid, pid_str, rc); + pidns_print_leader(); puts("+++ exited with 0 +++"); return 0; } diff --git a/tests/migrate_pages--pidns-translation.c b/tests/migrate_pages--pidns-translation.c new file mode 100644 index 00000000..ec34938d --- /dev/null +++ b/tests/migrate_pages--pidns-translation.c @@ -0,0 +1,2 @@ +#define PIDNS_TRANSLATION +#include "migrate_pages.c" diff --git a/tests/migrate_pages.c b/tests/migrate_pages.c index 2dfba49c..390b490b 100644 --- a/tests/migrate_pages.c +++ b/tests/migrate_pages.c @@ -10,6 +10,7 @@ #include "tests.h" #include "scno.h" +#include "pidns.h" #ifdef __NR_migrate_pages @@ -19,11 +20,21 @@ int main(void) { - const long pid = (long) 0xfacefeedffffffffULL; + PIDNS_TEST_INIT; + + const long pid = (long) 0xfacefeed00000000ULL | getpid(); long rc = syscall(__NR_migrate_pages, pid, 0, 0, 0); - printf("migrate_pages(%d, 0, NULL, NULL) = %ld %s (%m)\n", - (int) pid, rc, errno2name()); + pidns_print_leader(); + printf("migrate_pages(%d%s, 0, NULL, NULL) = %ld", + (int) pid, pidns_pid2str(PT_TGID), rc); + + if (rc < 0) + printf(" %s (%m)\n", errno2name()); + else + printf("\n"); + + pidns_print_leader(); puts("+++ exited with 0 +++"); return 0; } diff --git a/tests/move_pages--pidns-translation.c b/tests/move_pages--pidns-translation.c new file mode 100644 index 00000000..8498e399 --- /dev/null +++ b/tests/move_pages--pidns-translation.c @@ -0,0 +1,2 @@ +#define PIDNS_TRANSLATION +#include "move_pages.c" diff --git a/tests/move_pages.c b/tests/move_pages.c index e00fd1ac..56843158 100644 --- a/tests/move_pages.c +++ b/tests/move_pages.c @@ -10,6 +10,7 @@ #include "tests.h" #include "scno.h" +#include "pidns.h" #ifdef __NR_move_pages @@ -122,15 +123,20 @@ print_status_array(const int *const status, const unsigned long count) } static void -print_stat_pages(const unsigned long pid, const unsigned long count, - const void **const pages, int *const status) +print_stat_pages(const unsigned long pid, + const char *pid_str, + const unsigned long count, + const void **const pages, + int *const status) { const unsigned long flags = (unsigned long) 0xfacefeed00000002ULL; long rc = syscall(__NR_move_pages, pid, count, pages, NULL, status, flags); const char *errstr = sprintrc(rc); - printf("move_pages(%d, %lu, ", (int) pid, count); + pidns_print_leader(); + printf("move_pages(%d%s, %lu, ", (int) pid, pid_str, + count); print_page_array(pages, count, 0); printf(", NULL, "); if (rc) { @@ -152,6 +158,7 @@ print_stat_pages(const unsigned long pid, const unsigned long count, static void print_move_pages(const unsigned long pid, + const char *pid_str, unsigned long count, const unsigned int offset, const void **const pages, @@ -164,7 +171,9 @@ print_move_pages(const unsigned long pid, long rc = syscall(__NR_move_pages, pid, count, pages, nodes, status, flags); const char *errstr = sprintrc(rc); - printf("move_pages(%d, %lu, ", (int) pid, count); + pidns_print_leader(); + printf("move_pages(%d%s, %lu, ", (int) pid, pid_str, + count); print_page_array(pages, count, offset); printf(", "); print_node_array(nodes, count, offset); @@ -185,8 +194,11 @@ print_move_pages(const unsigned long pid, int main(void) { + PIDNS_TEST_INIT; + const unsigned long pid = (unsigned long) 0xfacefeed00000000ULL | getpid(); + const char *pid_str = pidns_pid2str(PT_TGID); unsigned long count = 1; const unsigned page_size = get_page_size(); const void *const page = tail_alloc(page_size); @@ -195,40 +207,41 @@ main(void) TAIL_ALLOC_OBJECT_VAR_PTR(int, nodes); TAIL_ALLOC_OBJECT_VAR_PTR(int, status); - print_stat_pages(pid, 0, pages, status); - print_move_pages(pid, 0, 0, pages, nodes, status); - print_move_pages(pid, 0, 1, pages + 1, nodes + 1, status + 1); + print_stat_pages(pid, pid_str, 0, pages, status); + print_move_pages(pid, pid_str, 0, 0, pages, nodes, status); + print_move_pages(pid, pid_str, 0, 1, pages + 1, nodes + 1, status + 1); *pages = page; - print_stat_pages(pid, count, pages, status); + print_stat_pages(pid, pid_str, count, pages, status); *nodes = 0xdeadbee1; - print_move_pages(pid, count, 0, pages, nodes, status); - print_move_pages(pid, count, 1, pages, nodes, status); + print_move_pages(pid, pid_str, count, 0, pages, nodes, status); + print_move_pages(pid, pid_str, count, 1, pages, nodes, status); ++count; --status; *(--pages) = efault; - print_stat_pages(pid, count, pages, status); + print_stat_pages(pid, pid_str, count, pages, status); *(--nodes) = 0xdeadbee2; - print_move_pages(pid, count, 0, pages, nodes, status); - print_move_pages(pid, count, 1, pages, nodes, status); + print_move_pages(pid, pid_str, count, 0, pages, nodes, status); + print_move_pages(pid, pid_str, count, 1, pages, nodes, status); ++count; --status; *(--pages) = nodes; - print_stat_pages(pid, count, pages, status); + print_stat_pages(pid, pid_str, count, pages, status); *(--nodes) = 0xdeadbee3; - print_move_pages(pid, count, 0, pages, nodes, status); - print_move_pages(pid, count, 1, pages, nodes, status); + print_move_pages(pid, pid_str, count, 0, pages, nodes, status); + print_move_pages(pid, pid_str, count, 1, pages, nodes, status); ++count; --status; *(--pages) = status; - print_stat_pages(pid, count, pages, status); + print_stat_pages(pid, pid_str, count, pages, status); *(--nodes) = 0xdeadbee4; - print_move_pages(pid, count, 0, pages, nodes, status); - print_move_pages(pid, count, 1, pages, nodes, status); + print_move_pages(pid, pid_str, count, 0, pages, nodes, status); + print_move_pages(pid, pid_str, count, 1, pages, nodes, status); + pidns_print_leader(); puts("+++ exited with 0 +++"); return 0; } diff --git a/tests/net-sockaddr--pidns-translation.c b/tests/net-sockaddr--pidns-translation.c new file mode 100644 index 00000000..ff432bf4 --- /dev/null +++ b/tests/net-sockaddr--pidns-translation.c @@ -0,0 +1,2 @@ +#define PIDNS_TRANSLATION +#include "net-sockaddr.c" diff --git a/tests/net-sockaddr.c b/tests/net-sockaddr.c index 4fc9da6e..c7e9bde7 100644 --- a/tests/net-sockaddr.c +++ b/tests/net-sockaddr.c @@ -9,6 +9,7 @@ */ #include "tests.h" +#include "pidns.h" #include #include #include @@ -40,18 +41,21 @@ check_un(void) memset(un->sun_path, '0', sizeof(un->sun_path)); unsigned int len = sizeof(*un); int ret = connect(-1, (void *) un, len); + pidns_print_leader(); printf("connect(-1, {sa_family=AF_UNIX, sun_path=\"%.*u\"}" ", %u) = %d EBADF (%m)\n", (int) sizeof(un->sun_path), 0, len, ret); un->sun_path[1] = 0; ret = connect(-1, (void *) un, len); + pidns_print_leader(); printf("connect(-1, {sa_family=AF_UNIX, sun_path=\"%u\"}, %u)" " = %d EBADF (%m)\n", 0, len, ret); un->sun_path[0] = 0; un->sun_path[2] = 1; ret = connect(-1, (void *) un, len); + pidns_print_leader(); printf("connect(-1, {sa_family=AF_UNIX, sun_path=@\"\\0\\001%.*u\"}" ", %u) = %d EBADF (%m)\n", (int) sizeof(un->sun_path) - 3, 0, len, ret); @@ -61,12 +65,14 @@ check_un(void) memset(un->sun_path, '0', sizeof(un->sun_path)); len = sizeof(*un) + 2; ret = connect(-1, (void *) un, len); + pidns_print_leader(); printf("connect(-1, {sa_family=AF_UNIX, sun_path=\"%.*u\"}" ", %u) = %d EBADF (%m)\n", (int) sizeof(un->sun_path), 0, len, ret); un->sun_path[0] = 0; ret = connect(-1, (void *) un, len); + pidns_print_leader(); printf("connect(-1, {sa_family=AF_UNIX, sun_path=@\"%.*u\"}" ", %u) = %d EBADF (%m)\n", (int) sizeof(un->sun_path) - 1, 0, len, ret); @@ -75,18 +81,21 @@ check_un(void) un->sun_family = AF_UNIX; len = sizeof(*un) - 2; ret = connect(-1, (void *) un, len); + pidns_print_leader(); printf("connect(-1, {sa_family=AF_UNIX, sun_path=\"%.*u\"}" ", %u) = %d EBADF (%m)\n", (int) sizeof(un->sun_path) - 2, 0, len, ret); un->sun_path[0] = 0; ret = connect(-1, (void *) un, len); + pidns_print_leader(); printf("connect(-1, {sa_family=AF_UNIX, sun_path=@\"%.*u\"}" ", %u) = %d EBADF (%m)\n", (int) sizeof(un->sun_path) - 3, 0, len, ret); len = sizeof(*un); ret = connect(-1, (void *) un, len); + pidns_print_leader(); printf("connect(-1, %p, %u) = %d EBADF (%m)\n", un, len, ret); un = tail_alloc(sizeof(struct sockaddr_storage)); @@ -94,12 +103,14 @@ check_un(void) memset(un->sun_path, '0', sizeof(un->sun_path)); len = sizeof(struct sockaddr_storage) + 1; ret = connect(-1, (void *) un, len); + pidns_print_leader(); printf("connect(-1, {sa_family=AF_UNIX, sun_path=\"%.*u\"}" ", %u) = %d EBADF (%m)\n", (int) sizeof(un->sun_path), 0, len, ret); un->sun_path[0] = 0; ret = connect(-1, (void *) un, len); + pidns_print_leader(); printf("connect(-1, {sa_family=AF_UNIX, sun_path=@\"%.*u\"}" ", %u) = %d EBADF (%m)\n", (int) sizeof(un->sun_path) - 1, 0, len, ret); @@ -117,6 +128,7 @@ check_in(void) in->sin_addr.s_addr = inet_addr(h_addr); unsigned int len = sizeof(*in); int ret = connect(-1, (void *) in, len); + pidns_print_leader(); printf("connect(-1, {sa_family=AF_INET, sin_port=htons(%hu)" ", sin_addr=inet_addr(\"%s\")}, %u) = %d EBADF (%m)\n", h_port, h_addr, len, ret); @@ -127,6 +139,7 @@ check_in(void) in->sin_addr.s_addr = inet_addr(h_addr); len = sizeof(*in) + 4; ret = connect(-1, (void *) in, len); + pidns_print_leader(); printf("connect(-1, {sa_family=AF_INET, sin_port=htons(%hu)" ", sin_addr=inet_addr(\"%s\")}, %u) = %d EBADF (%m)\n", h_port, h_addr, len, ret); @@ -137,6 +150,7 @@ check_in(void) in->sin_addr.s_addr = 0; len = sizeof(*in) - 4; ret = connect(-1, (void *) in, len); + pidns_print_leader(); printf("connect(-1, {sa_family=AF_INET, sa_data=\"%s\"}, %u)" " = %d EBADF (%m)\n", "\\0\\0\\0\\0\\0\\0\\377\\377\\377\\377", @@ -144,6 +158,7 @@ check_in(void) len = sizeof(*in); ret = connect(-1, (void *) in, len); + pidns_print_leader(); printf("connect(-1, %p, %u) = %d EBADF (%m)\n", in, len, ret); } @@ -155,6 +170,7 @@ check_in6_linklocal(struct sockaddr_in6 *const in6, const char *const h_addr) in6->sin6_scope_id = 0xfacefeed; unsigned int len = sizeof(*in6); int ret = connect(-1, (void *) in6, len); + pidns_print_leader(); printf("connect(-1, {sa_family=AF_INET6, sin6_port=htons(%hu)" ", sin6_flowinfo=htonl(%u)" ", inet_pton(AF_INET6, \"%s\", &sin6_addr)" @@ -166,7 +182,8 @@ check_in6_linklocal(struct sockaddr_in6 *const in6, const char *const h_addr) in6->sin6_scope_id = ifindex_lo(); if (in6->sin6_scope_id) { ret = connect(-1, (void *) in6, len); - printf("connect(-1, {sa_family=AF_INET6, sin6_port=htons(%hu)" + pidns_print_leader(); + printf("connect(-1, {sa_family=AF_INET6, sin6_port=htons(%hu)" ", sin6_flowinfo=htonl(%u)" ", inet_pton(AF_INET6, \"%s\", &sin6_addr)" ", sin6_scope_id=%s}, %u)" @@ -191,6 +208,7 @@ check_in6(void) in6->sin6_scope_id = 0xfacefeed; unsigned int len = sizeof(*in6); int ret = connect(-1, (void *) in6, len); + pidns_print_leader(); printf("connect(-1, {sa_family=AF_INET6, sin6_port=htons(%hu)" ", sin6_flowinfo=htonl(%u)" ", inet_pton(AF_INET6, \"%s\", &sin6_addr)" @@ -209,6 +227,7 @@ check_in6(void) in6->sin6_scope_id = 0xfacefeed; len = sizeof(*in6) + 4; ret = connect(-1, (void *) in6, len); + pidns_print_leader(); printf("connect(-1, {sa_family=AF_INET6, sin6_port=htons(%hu)" ", sin6_flowinfo=htonl(%u)" ", inet_pton(AF_INET6, \"%s\", &sin6_addr)" @@ -223,6 +242,7 @@ check_in6(void) inet_pton(AF_INET6, h_addr, &in6->sin6_addr); len = sizeof(*in6) - sizeof(in6->sin6_scope_id); ret = connect(-1, (void *) in6, len); + pidns_print_leader(); printf("connect(-1, {sa_family=AF_INET6, sin6_port=htons(%hu)" ", sin6_flowinfo=htonl(%u)" ", inet_pton(AF_INET6, \"%s\", &sin6_addr)}, %u)" @@ -236,6 +256,7 @@ check_in6(void) memset(&in6->sin6_addr, '0', sizeof(in6->sin6_addr) - 4); len = sizeof(*in6) - sizeof(in6->sin6_scope_id) - 4; ret = connect(-1, (void *) in6, len); + pidns_print_leader(); printf("connect(-1, {sa_family=AF_INET6" ", sa_data=\"\\0\\0\\0\\0\\0\\000%.*u\"}, %u)" " = %d EBADF (%m)\n", @@ -244,6 +265,7 @@ check_in6(void) len = sizeof(*in6) - sizeof(in6->sin6_scope_id); ret = connect(-1, (void *) in6, len); + pidns_print_leader(); printf("connect(-1, %p, %u) = %d EBADF (%m)\n", in6, len, ret); } @@ -262,6 +284,7 @@ check_ipx(void) void *ipx = tail_memdup(&c_ipx, sizeof(c_ipx)); unsigned int len = sizeof(c_ipx); int ret = connect(-1, ipx, len); + pidns_print_leader(); printf("connect(-1, {sa_family=AF_IPX, sipx_port=htons(%u)" ", sipx_network=htonl(%#x)" ", sipx_node=[%#02x, %#02x, %#02x, %#02x, %#02x, %#02x]" @@ -316,18 +339,21 @@ check_ax25(void) fill_memory(sax, size); sax->fsa_ax25.sax25_family = AF_AX25; rc = connect(-1, sax_void, sizeof(struct sockaddr_ax25) - 1); + pidns_print_leader(); printf("connect(-1, {sa_family=AF_AX25, sa_data=\"\\202\\203\\204\\205" "\\206\\207\\210\\211\\212\\213\\214\\215\\216\"}, %zu) = %s\n", sizeof(struct sockaddr_ax25) - 1, sprintrc(rc)); memcpy(sax, &ax25, sizeof(ax25)); rc = connect(-1, sax_void, sizeof(struct sockaddr_ax25)); + pidns_print_leader(); printf("connect(-1, {sa_family=AF_AX25, fsa_ax25={sax25_call=VALID-13" ", sax25_ndigis=8}, fsa_digipeater=[/* ??? */]}, %zu) = %s\n", sizeof(struct sockaddr_ax25), sprintrc(rc)); sax->fsa_ax25.sax25_ndigis = 0; rc = connect(-1, sax_void, sizeof(struct sockaddr_ax25)); + pidns_print_leader(); printf("connect(-1, {sa_family=AF_AX25, sax25_call=VALID-13" ", sax25_ndigis=0}, %zu) = %s\n", sizeof(struct sockaddr_ax25), sprintrc(rc)); @@ -335,6 +361,7 @@ check_ax25(void) sax->fsa_ax25.sax25_ndigis = 8; size = sizeof(struct sockaddr_ax25) + sizeof(ax25_address) * 3 + 1; rc = connect(-1, sax_void, size); + pidns_print_leader(); printf("connect(-1, {sa_family=AF_AX25, fsa_ax25={sax25_call=VALID-13" ", sax25_ndigis=8}, fsa_digipeater" "=[{ax25_call=\"\\xa6\\xa0\\x82\\x40\\x86\\x8a\\x00\"" @@ -348,6 +375,7 @@ check_ax25(void) sax->fsa_digipeater[2].ax25_call[6] = 0x4; size = sizeof(struct sockaddr_ax25) + sizeof(ax25_address) * 4; rc = connect(-1, sax_void, size); + pidns_print_leader(); printf("connect(-1, {sa_family=AF_AX25, fsa_ax25={sax25_call=VALID-13" ", sax25_ndigis=8}, fsa_digipeater" "=[{ax25_call=\"\\xa6\\xa0\\x82\\x40\\x86\\x8a\\x00\"" @@ -365,6 +393,7 @@ check_ax25(void) for (size_t i = 0; i < 3; i++) { size = sizeof(ax25) + sizeof(ax25_address) * (i / 2); rc = connect(-1, sax_void, size); + pidns_print_leader(); printf("connect(-1, {sa_family=AF_AX25" ", fsa_ax25={sax25_call=VALID-13, sax25_ndigis=%d}" ", fsa_digipeater=[VALID2-7, OK-15, %s /* FINE-2 */" @@ -427,12 +456,14 @@ check_x25(void) long rc; rc = connect(-1, x25_void, sizeof(c_x25) - 1); + pidns_print_leader(); printf("connect(-1, {sa_family=AF_X25" ", sa_data=\"0123456789abcde\"}, %zu) = %s\n", sizeof(c_x25) - 1, sprintrc(rc)); for (size_t i = 0; i < 2; i++) { rc = connect(-1, x25_void, sizeof(c_x25) + i); + pidns_print_leader(); printf("connect(-1, {sa_family=AF_X25" ", sx25_addr={x25_addr=\"0123456789abcde\"...}" "}, %zu) = %s\n", @@ -442,6 +473,7 @@ check_x25(void) struct sockaddr_x25 *const x25 = x25_void; x25->sx25_addr.x25_addr[10] = '\0'; rc = connect(-1, x25_void, sizeof(c_x25)); + pidns_print_leader(); printf("connect(-1, {sa_family=AF_X25" ", sx25_addr={x25_addr=\"0123456789\"}" "}, %zu) = %s\n", @@ -457,19 +489,21 @@ check_nl(void) nl->nl_groups = 0xfacefeed; unsigned int len = sizeof(*nl); int ret = connect(-1, (void *) nl, len); + pidns_print_leader(); printf("connect(-1, {sa_family=AF_NETLINK, nl_pid=%d" ", nl_groups=%#08x}, %u) = %d EBADF (%m)\n", nl->nl_pid, nl->nl_groups, len, ret); nl = ((void *) nl) - 4; nl->nl_family = AF_NETLINK; - nl->nl_pid = 1234567890; + nl->nl_pid = getpid(); nl->nl_groups = 0xfacefeed; len = sizeof(*nl) + 4; ret = connect(-1, (void *) nl, len); - printf("connect(-1, {sa_family=AF_NETLINK, nl_pid=%d" + pidns_print_leader(); + printf("connect(-1, {sa_family=AF_NETLINK, nl_pid=%d%s" ", nl_groups=%#08x}, %u) = %d EBADF (%m)\n", - nl->nl_pid, nl->nl_groups, len, ret); + nl->nl_pid, pidns_pid2str(PT_TGID), nl->nl_groups, len, ret); } static void @@ -487,6 +521,7 @@ check_ll(void) void *ll = tail_memdup(&c_ll, sizeof(c_ll)); unsigned int len = sizeof(c_ll); int ret = connect(-1, ll, len); + pidns_print_leader(); printf("connect(-1, {sa_family=AF_PACKET" ", sll_protocol=htons(ETH_P_ALL)" ", sll_ifindex=%u, sll_hatype=ARPHRD_ETHER" @@ -502,6 +537,7 @@ check_ll(void) ((struct sockaddr_ll *) ll)->sll_halen++; ret = connect(-1, ll, len); + pidns_print_leader(); printf("connect(-1, {sa_family=AF_PACKET" ", sll_protocol=htons(ETH_P_ALL)" ", sll_ifindex=%u, sll_hatype=ARPHRD_ETHER" @@ -517,6 +553,7 @@ check_ll(void) ((struct sockaddr_ll *) ll)->sll_halen = 0; ret = connect(-1, ll, len); + pidns_print_leader(); printf("connect(-1, {sa_family=AF_PACKET" ", sll_protocol=htons(ETH_P_ALL)" ", sll_ifindex=%u, sll_hatype=ARPHRD_ETHER" @@ -526,6 +563,7 @@ check_ll(void) ((struct sockaddr_ll *) ll)->sll_ifindex = ifindex_lo(); if (((struct sockaddr_ll *) ll)->sll_ifindex) { ret = connect(-1, ll, len); + pidns_print_leader(); printf("connect(-1, {sa_family=AF_PACKET" ", sll_protocol=htons(ETH_P_ALL)" ", sll_ifindex=%s" @@ -549,11 +587,13 @@ check_hci(void) unsigned int len = sizeof(*hci); int ret = connect(-1, (void *) hci, 4); + pidns_print_leader(); printf("connect(-1, {sa_family=AF_BLUETOOTH, hci_dev=htobs(%hu)" "}, 4) = %d EBADF (%m)\n", h_port, ret); ret = connect(-1, (void *) hci, len); + pidns_print_leader(); printf("connect(-1, {sa_family=AF_BLUETOOTH, hci_dev=htobs(%hu)" # ifdef HAVE_STRUCT_SOCKADDR_HCI_HCI_CHANNEL ", hci_channel=HCI_CHANNEL_RAW" @@ -572,6 +612,7 @@ check_sco(void) void *sco = tail_memdup(&c_sco, sizeof(c_sco)); unsigned int len = sizeof(c_sco); int ret = connect(-1, sco, len); + pidns_print_leader(); printf("connect(-1, {sa_family=AF_BLUETOOTH" ", sco_bdaddr=%02x:%02x:%02x:%02x:%02x:%02x" "}, %u) = %d EBADF (%m)\n", @@ -592,6 +633,7 @@ check_rc(void) void *rc = tail_memdup(&c_rc, sizeof(c_rc)); unsigned int len = sizeof(c_rc); int ret = connect(-1, rc, len); + pidns_print_leader(); printf("connect(-1, {sa_family=AF_BLUETOOTH" ", rc_bdaddr=%02x:%02x:%02x:%02x:%02x:%02x" ", rc_channel=%u}, %u) = %d EBADF (%m)\n", @@ -619,6 +661,7 @@ check_l2(void) unsigned int len = sizeof(c_l2); int ret = connect(-1, l2, len); + pidns_print_leader(); printf("connect(-1, {sa_family=AF_BLUETOOTH" ", l2_psm=htobs(L2CAP_PSM_DYN_START + %hu)" ", l2_bdaddr=%02x:%02x:%02x:%02x:%02x:%02x" @@ -640,6 +683,7 @@ check_l2(void) # endif memcpy(l2, &c_l2, sizeof(c_l2)); ret = connect(-1, l2, len); + pidns_print_leader(); printf("connect(-1, {sa_family=AF_BLUETOOTH" ", l2_psm=htobs(L2CAP_PSM_SDP)" ", l2_bdaddr=%02x:%02x:%02x:%02x:%02x:%02x" @@ -660,6 +704,7 @@ check_l2(void) # endif memcpy(l2, &c_l2, sizeof(c_l2)); ret = connect(-1, l2, len); + pidns_print_leader(); printf("connect(-1, {sa_family=AF_BLUETOOTH" ", l2_psm=htobs(0xbad /* L2CAP_PSM_??? */)" ", l2_bdaddr=%02x:%02x:%02x:%02x:%02x:%02x" @@ -677,6 +722,7 @@ check_l2(void) c_l2.l2_cid = htobs(0xffff); memcpy(l2, &c_l2, 12); ret = connect(-1, l2, 12); + pidns_print_leader(); printf("connect(-1, {sa_family=AF_BLUETOOTH" ", l2_psm=htobs(L2CAP_PSM_AUTO_END)" ", l2_bdaddr=%02x:%02x:%02x:%02x:%02x:%02x" @@ -700,6 +746,7 @@ check_raw(void) u.sa->sa_family = 0xff; unsigned int len = sizeof(*u.st) + 8; int ret = connect(-1, (void *) u.st, len); + pidns_print_leader(); printf("connect(-1, {sa_family=%#x /* AF_??? */, sa_data=\"%.*u\"}" ", %u) = %d EBADF (%m)\n", u.sa->sa_family, (int) (sizeof(*u.st) - sizeof(u.sa->sa_family)), 0, len, ret); @@ -707,11 +754,13 @@ check_raw(void) u.sa->sa_family = 0; len = sizeof(u.sa->sa_family) + 1; ret = connect(-1, (void *) u.st, len); + pidns_print_leader(); printf("connect(-1, {sa_family=AF_UNSPEC, sa_data=\"0\"}, %u)" " = %d EBADF (%m)\n", len, ret); u.sa->sa_family = AF_BLUETOOTH; ret = connect(-1, (void *) u.st, len); + pidns_print_leader(); printf("connect(-1, {sa_family=AF_BLUETOOTH, sa_data=\"0\"}, %u)" " = %d EBADF (%m)\n", len, ret); } @@ -719,6 +768,8 @@ check_raw(void) int main(void) { + PIDNS_TEST_INIT; + check_un(); check_in(); check_in6(); @@ -735,6 +786,7 @@ main(void) #endif check_raw(); + pidns_print_leader(); puts("+++ exited with 0 +++"); return 0; } diff --git a/tests/netlink_audit--pidns-translation.c b/tests/netlink_audit--pidns-translation.c new file mode 100644 index 00000000..e08f9168 --- /dev/null +++ b/tests/netlink_audit--pidns-translation.c @@ -0,0 +1,2 @@ +#define PIDNS_TRANSLATION +#include "netlink_audit.c" diff --git a/tests/netlink_audit--pidns-translation.test b/tests/netlink_audit--pidns-translation.test new file mode 100755 index 00000000..1a39eadd --- /dev/null +++ b/tests/netlink_audit--pidns-translation.test @@ -0,0 +1,13 @@ +#!/bin/sh +# +# Check pidns translation of NETLINK_SOCK_DIAG protocol decoding +# +# Copyright (c) 2020 The strace developers. +# All rights reserved. +# +# SPDX-License-Identifier: LGPL-2.1-or-later + +. "${srcdir=.}/init.sh" + +run_prog ../netlink_netlink_diag +test_pidns -e trace=sendto "$@" diff --git a/tests/netlink_audit.c b/tests/netlink_audit.c index eba609a1..5dfcd786 100644 --- a/tests/netlink_audit.c +++ b/tests/netlink_audit.c @@ -7,6 +7,7 @@ */ #include "tests.h" +#include "pidns.h" #include #include #include @@ -17,18 +18,23 @@ static void test_nlmsg_type(const int fd) { + PIDNS_TEST_INIT; + long rc; struct nlmsghdr nlh = { .nlmsg_len = sizeof(nlh), .nlmsg_type = AUDIT_GET, .nlmsg_flags = NLM_F_REQUEST, + .nlmsg_pid = getpid(), }; rc = sendto(fd, &nlh, sizeof(nlh), MSG_DONTWAIT, NULL, 0); + pidns_print_leader(); printf("sendto(%d, {len=%u, type=AUDIT_GET" - ", flags=NLM_F_REQUEST, seq=0, pid=0}" + ", flags=NLM_F_REQUEST, seq=0, pid=%d%s}" ", %u, MSG_DONTWAIT, NULL, 0) = %s\n", - fd, nlh.nlmsg_len, (unsigned) sizeof(nlh), sprintrc(rc)); + fd, nlh.nlmsg_len, nlh.nlmsg_pid, pidns_pid2str(PT_TGID), + (unsigned) sizeof(nlh), sprintrc(rc)); } int main(void) @@ -39,6 +45,7 @@ int main(void) test_nlmsg_type(fd); + pidns_print_leader(); printf("+++ exited with 0 +++\n"); return 0; diff --git a/tests/pidfd_open--pidns-translation.c b/tests/pidfd_open--pidns-translation.c new file mode 100644 index 00000000..c38e37a8 --- /dev/null +++ b/tests/pidfd_open--pidns-translation.c @@ -0,0 +1,2 @@ +#define PIDNS_TRANSLATION +#include "pidfd_open.c" diff --git a/tests/pidfd_open.c b/tests/pidfd_open.c index 5860adde..e5d74a91 100644 --- a/tests/pidfd_open.c +++ b/tests/pidfd_open.c @@ -10,6 +10,7 @@ #include "tests.h" #include "scno.h" +#include "pidns.h" #ifdef __NR_pidfd_open @@ -37,6 +38,8 @@ k_pidfd_open(const unsigned int pid, const unsigned int flags) int main(void) { + PIDNS_TEST_INIT; + # if defined PATH_TRACING || defined PRINT_PATHS skip_if_unavailable("/proc/self/fd/"); # endif @@ -50,16 +53,19 @@ main(void) k_pidfd_open(0, 0); # ifndef PATH_TRACING + pidns_print_leader(); printf("pidfd_open(0, 0) = %s\n", errstr); # endif k_pidfd_open(-1U, 0); # ifndef PATH_TRACING + pidns_print_leader(); printf("pidfd_open(-1, 0) = %s\n", errstr); # endif k_pidfd_open(0, -1U); # ifndef PATH_TRACING + pidns_print_leader(); printf("pidfd_open(0, %#x) = %s\n", -1U, errstr); # endif @@ -68,7 +74,10 @@ main(void) k_pidfd_open(pid, flags); # ifndef PATH_TRACING - printf("pidfd_open(%d, %#x) = %s\n", pid, flags, errstr); + const char *pid_str = pidns_pid2str(PT_TGID); + pidns_print_leader(); + printf("pidfd_open(%d%s, %#x) = %s\n", + pid, pid_str, flags, errstr); # endif # ifdef PRINT_PATHS @@ -80,17 +89,19 @@ main(void) # endif # ifndef PATH_TRACING - printf("pidfd_open(%d, 0) = " + pidns_print_leader(); + printf("pidfd_open(%d%s, 0) = " # if defined PRINT_PIDFD - "%ld\n", pid, rc, pid + "%ld\n", pid, pid_str, rc, pid # elif defined PRINT_PATHS - "%ld\n", pid, rc + "%ld\n", pid, pid_str, rc # else - "%s\n", pid, errstr + "%s\n", pid, pid_str, errstr # endif ); # endif + pidns_print_leader(); puts("+++ exited with 0 +++"); return 0; } diff --git a/tests/pidfd_send_signal--pidns-translation.c b/tests/pidfd_send_signal--pidns-translation.c new file mode 100644 index 00000000..b04f10f5 --- /dev/null +++ b/tests/pidfd_send_signal--pidns-translation.c @@ -0,0 +1,2 @@ +#define PIDNS_TRANSLATION +#include "pidfd_send_signal.c" diff --git a/tests/pidfd_send_signal.c b/tests/pidfd_send_signal.c index 38b5bda1..a6b2d28c 100644 --- a/tests/pidfd_send_signal.c +++ b/tests/pidfd_send_signal.c @@ -10,6 +10,7 @@ #include "tests.h" #include #include "scno.h" +#include "pidns.h" #ifdef __NR_pidfd_send_signal @@ -36,6 +37,8 @@ sys_pidfd_send_signal(int pidfd, int sig, const void *info, int flags) int main(void) { + PIDNS_TEST_INIT; + static const char null_path[] = "/dev/null"; int fd = open(null_path, O_RDONLY); @@ -46,19 +49,23 @@ main(void) const void *esi = (const void *) si + 1; sys_pidfd_send_signal(fd, SIGUSR1, esi, 0); + pidns_print_leader(); printf("pidfd_send_signal(%d, SIGUSR1, %p, 0) = %s\n", fd, esi, errstr); si->si_signo = SIGUSR1; si->si_code = SI_QUEUE; + si->si_pid = getpid(); sys_pidfd_send_signal(fd, SIGUSR2, si, -1); + pidns_print_leader(); printf("pidfd_send_signal(%d, SIGUSR2, {si_signo=SIGUSR1" - ", si_code=SI_QUEUE, si_errno=%u, si_pid=%d, si_uid=%d" + ", si_code=SI_QUEUE, si_errno=%u, si_pid=%d%s, si_uid=%d" ", si_value={int=%d, ptr=%p}}, %#x) = %s\n", - fd, si->si_errno, si->si_pid, si->si_uid, si->si_int, si->si_ptr, - -1U, errstr); + fd, si->si_errno, si->si_pid, pidns_pid2str(PT_TGID), si->si_uid, + si->si_int, si->si_ptr, -1U, errstr); + pidns_print_leader(); puts("+++ exited with 0 +++"); return 0; } diff --git a/tests/prlimit64--pidns-translation.c b/tests/prlimit64--pidns-translation.c new file mode 100644 index 00000000..3972de66 --- /dev/null +++ b/tests/prlimit64--pidns-translation.c @@ -0,0 +1,2 @@ +#define PIDNS_TRANSLATION +#include "prlimit64.c" diff --git a/tests/prlimit64.c b/tests/prlimit64.c index 34201a2b..bc1a80b3 100644 --- a/tests/prlimit64.c +++ b/tests/prlimit64.c @@ -19,6 +19,7 @@ # include # include +# include "pidns.h" # include "xlat.h" # include "xlat/resources.h" @@ -42,8 +43,11 @@ sprint_rlim(uint64_t lim) int main(void) { + PIDNS_TEST_INIT; + unsigned long pid = (unsigned long) 0xdefaced00000000ULL | (unsigned) getpid(); + const char *pid_str = pidns_pid2str(PT_TGID); uint64_t *const rlimit = tail_alloc(sizeof(*rlimit) * 2); const struct xlat_data *xlat; size_t i = 0; @@ -54,18 +58,23 @@ main(void) unsigned long res = 0xfacefeed00000000ULL | xlat->val; long rc = syscall(__NR_prlimit64, pid, res, 0, rlimit); + pidns_print_leader(); if (rc) - printf("prlimit64(%d, %s, NULL, %p) = %ld %s (%m)\n", - (unsigned) pid, xlat->str, rlimit, + printf("prlimit64(%d%s, %s, NULL, %p) =" + " %ld %s (%m)\n", + (unsigned) pid, pid_str, + xlat->str, rlimit, rc, errno2name()); else - printf("prlimit64(%d, %s, NULL" + printf("prlimit64(%d%s, %s, NULL" ", {rlim_cur=%s, rlim_max=%s}) = 0\n", - (unsigned) pid, xlat->str, + (unsigned) pid, pid_str, + xlat->str, sprint_rlim(rlimit[0]), sprint_rlim(rlimit[1])); } + pidns_print_leader(); puts("+++ exited with 0 +++"); return 0; } diff --git a/tests/process_vm_readv--pidns-translation.c b/tests/process_vm_readv--pidns-translation.c new file mode 100644 index 00000000..0db29ca2 --- /dev/null +++ b/tests/process_vm_readv--pidns-translation.c @@ -0,0 +1,2 @@ +#define PIDNS_TRANSLATION +#include "process_vm_readv.c" diff --git a/tests/process_vm_readv_writev.c b/tests/process_vm_readv_writev.c index 9309135a..44e511dd 100644 --- a/tests/process_vm_readv_writev.c +++ b/tests/process_vm_readv_writev.c @@ -12,6 +12,7 @@ #include #include #include +#include "pidns.h" #if OP_WR # define in_iovec rmt_iovec @@ -121,7 +122,7 @@ print_iov(const struct iovec *iov, const void *arg_ptr, long rc) } static void -do_call(kernel_ulong_t pid, +do_call(kernel_ulong_t pid, enum pid_type pid_type, kernel_ulong_t local_iov, const char *local_arg, kernel_ulong_t liovcnt, kernel_ulong_t remote_iov, const char *remote_arg, @@ -135,7 +136,8 @@ do_call(kernel_ulong_t pid, flags); errstr = sprintrc(rc); - printf("%s(%d, ", OP_STR, (int) pid); + pidns_print_leader(); + printf("%s(%d%s, ", OP_STR, (int) pid, pidns_pid2str(pid_type)); if (pr_iov) pr_iov((const struct iovec *) (uintptr_t) local_iov, local_arg, @@ -164,6 +166,8 @@ ptr_cast(void *ptr) int main(void) { + PIDNS_TEST_INIT; + enum { SIZE_11 = 2, SIZE_12 = 3, @@ -243,18 +247,18 @@ main(void) fill_memory_ex(data2_out, SIZE_2, SEGM2_BASE, SIZE_2); - do_call(bogus_pid, (kernel_ulong_t) (uintptr_t) ARG_STR(NULL), + do_call(bogus_pid, PT_NONE, (kernel_ulong_t) (uintptr_t) ARG_STR(NULL), bogus_iovcnt1, (kernel_ulong_t) (uintptr_t) ARG_STR(NULL), bogus_iovcnt2, bogus_flags, NULL); - do_call(my_pid, ptr_cast(bogus_iov + ARRAY_SIZE(bogus_iovec)), + do_call(my_pid, PT_TGID, ptr_cast(bogus_iov + ARRAY_SIZE(bogus_iovec)), "[]", 0, ptr_cast(in_iov + ARRAY_SIZE(in_iovec)), "[]", 0, 0, NULL); - do_call(my_pid, ptr_cast(bogus_iov + ARRAY_SIZE(bogus_iovec)), NULL, - bogus_iovcnt1, ptr_cast(in_iov + ARRAY_SIZE(in_iovec)), NULL, - bogus_iovcnt2, 0, print_iov); + do_call(my_pid, PT_TGID, ptr_cast(bogus_iov + ARRAY_SIZE(bogus_iovec)), + NULL, bogus_iovcnt1, ptr_cast(in_iov + ARRAY_SIZE(in_iovec)), + NULL, bogus_iovcnt2, 0, print_iov); - do_call(my_pid, ptr_cast(bogus_iov), (char *) &bogus_arg, + do_call(my_pid, PT_TGID, ptr_cast(bogus_iov), (char *) &bogus_arg, ARRAY_SIZE(bogus_iovec), ptr_cast(rmt_iov + 2), (char *) &rmt_arg_cut, ARRAY_SIZE(rmt_iovec) - 2, 0, print_iov); @@ -263,7 +267,7 @@ main(void) lcl_arg_cut.check_rc = 1; #endif - do_call(my_pid, ptr_cast(lcl_iov + 2), (char *) &lcl_arg_cut, + do_call(my_pid, PT_TGID, ptr_cast(lcl_iov + 2), (char *) &lcl_arg_cut, ARRAY_SIZE(lcl_iovec) - 1, ptr_cast(bogus_iov + 2), (char *) &bogus_arg_cut, ARRAY_SIZE(bogus_iovec) - 1, 0, print_iov); @@ -273,15 +277,16 @@ main(void) rmt_arg_cut.addr_term = 1; rmt_arg_cut.count = 5; - do_call(my_pid, ptr_cast(lcl_iov + 2), (char *) &lcl_arg_cut, + do_call(my_pid, PT_TGID, ptr_cast(lcl_iov + 2), (char *) &lcl_arg_cut, ARRAY_SIZE(lcl_iovec) - 2, ptr_cast(rmt_iov + 1), (char *) &rmt_arg_cut, ARRAY_SIZE(rmt_iovec), 0, print_iov); /* Correct call */ - do_call(my_pid, ptr_cast(lcl_iov), (char *) &lcl_arg, + do_call(my_pid, PT_TGID, ptr_cast(lcl_iov), (char *) &lcl_arg, ARRAY_SIZE(lcl_iovec), ptr_cast(rmt_iov), (char *) &rmt_arg, ARRAY_SIZE(rmt_iovec), 0, print_iov); + pidns_print_leader(); puts("+++ exited with 0 +++"); return 0; diff --git a/tests/process_vm_writev--pidns-translation.c b/tests/process_vm_writev--pidns-translation.c new file mode 100644 index 00000000..9ba6a39b --- /dev/null +++ b/tests/process_vm_writev--pidns-translation.c @@ -0,0 +1,2 @@ +#define PIDNS_TRANSLATION +#include "process_vm_writev.c" diff --git a/tests/rt_sigqueueinfo--pidns-translation.c b/tests/rt_sigqueueinfo--pidns-translation.c new file mode 100644 index 00000000..74bfb464 --- /dev/null +++ b/tests/rt_sigqueueinfo--pidns-translation.c @@ -0,0 +1,2 @@ +#define PIDNS_TRANSLATION +#include "rt_sigqueueinfo.c" diff --git a/tests/rt_sigqueueinfo.c b/tests/rt_sigqueueinfo.c index c1693873..e22e4640 100644 --- a/tests/rt_sigqueueinfo.c +++ b/tests/rt_sigqueueinfo.c @@ -7,6 +7,7 @@ */ #include "tests.h" +#include "pidns.h" #include #include #include @@ -15,6 +16,8 @@ int main(void) { + PIDNS_TEST_INIT; + struct sigaction sa = { .sa_handler = SIG_IGN }; @@ -22,15 +25,19 @@ main(void) .sival_ptr = (void *) (unsigned long) 0xdeadbeefbadc0dedULL }; pid_t pid = getpid(); + const char *pid_str = pidns_pid2str(PT_TGID); assert(sigaction(SIGUSR1, &sa, NULL) == 0); if (sigqueue(pid, SIGUSR1, value)) perror_msg_and_skip("sigqueue"); - printf("rt_sigqueueinfo(%u, SIGUSR1, {si_signo=SIGUSR1, " - "si_code=SI_QUEUE, si_pid=%d, si_uid=%d, " + pidns_print_leader(); + printf("rt_sigqueueinfo(%d%s, SIGUSR1, {si_signo=SIGUSR1, " + "si_code=SI_QUEUE, si_pid=%d%s, si_uid=%u, " "si_value={int=%d, ptr=%p}}) = 0\n", - pid, pid, getuid(), value.sival_int, value.sival_ptr); - printf("+++ exited with 0 +++\n"); + pid, pid_str, pid, pid_str, + getuid(), value.sival_int, value.sival_ptr); + pidns_print_leader(); + puts("+++ exited with 0 +++"); return 0; } diff --git a/tests/rt_tgsigqueueinfo--pidns-translation.c b/tests/rt_tgsigqueueinfo--pidns-translation.c new file mode 100644 index 00000000..94396f00 --- /dev/null +++ b/tests/rt_tgsigqueueinfo--pidns-translation.c @@ -0,0 +1,2 @@ +#define PIDNS_TRANSLATION +#include "rt_tgsigqueueinfo.c" diff --git a/tests/rt_tgsigqueueinfo.c b/tests/rt_tgsigqueueinfo.c index 865c21f6..21d01cbb 100644 --- a/tests/rt_tgsigqueueinfo.c +++ b/tests/rt_tgsigqueueinfo.c @@ -10,8 +10,9 @@ #include "tests.h" #include "scno.h" +#include "pidns.h" -#ifdef __NR_rt_tgsigqueueinfo +#if defined __NR_rt_tgsigqueueinfo && defined __NR_gettid # include # include @@ -20,11 +21,11 @@ # include static long -k_tgsigqueueinfo(const pid_t pid, const int sig, const void *const info) +k_tgsigqueueinfo(const pid_t tgid, const int tid, const int sig, const void *const info) { return syscall(__NR_rt_tgsigqueueinfo, - F8ILL_KULONG_MASK | pid, - F8ILL_KULONG_MASK | pid, + F8ILL_KULONG_MASK | tgid, + F8ILL_KULONG_MASK | tid, F8ILL_KULONG_MASK | sig, info); } @@ -32,6 +33,8 @@ k_tgsigqueueinfo(const pid_t pid, const int sig, const void *const info) int main(void) { + PIDNS_TEST_INIT; + const struct sigaction sa = { .sa_handler = SIG_IGN }; @@ -48,17 +51,22 @@ main(void) info->si_value.sival_ptr = (void *) (unsigned long) 0xdeadbeeffacefeedULL; - if (k_tgsigqueueinfo(info->si_pid, SIGUSR1, info)) + if (k_tgsigqueueinfo(getpid(), syscall(__NR_gettid), SIGUSR1, info)) (errno == ENOSYS ? perror_msg_and_skip : perror_msg_and_fail)( "rt_tgsigqueueinfo"); - printf("rt_tgsigqueueinfo(%u, %u, %s, {si_signo=%s" - ", si_code=SI_QUEUE, si_errno=ENOENT, si_pid=%d" + pidns_print_leader(); + printf("rt_tgsigqueueinfo(%d%s, %d%s, %s, {si_signo=%s" + ", si_code=SI_QUEUE, si_errno=ENOENT, si_pid=%d%s" ", si_uid=%d, si_value={int=%d, ptr=%p}}) = 0\n", - info->si_pid, info->si_pid, "SIGUSR1", "SIGUSR1", - info->si_pid, info->si_uid, info->si_value.sival_int, + info->si_pid, pidns_pid2str(PT_TGID), + info->si_pid, pidns_pid2str(PT_TID), + "SIGUSR1", "SIGUSR1", + info->si_pid, pidns_pid2str(PT_TGID), + info->si_uid, info->si_value.sival_int, info->si_value.sival_ptr); + pidns_print_leader(); puts("+++ exited with 0 +++"); return 0; } diff --git a/tests/sched_xetaffinity--pidns-translation.c b/tests/sched_xetaffinity--pidns-translation.c new file mode 100644 index 00000000..814e3989 --- /dev/null +++ b/tests/sched_xetaffinity--pidns-translation.c @@ -0,0 +1,2 @@ +#define PIDNS_TRANSLATION +#include "sched_xetaffinity.c" diff --git a/tests/sched_xetaffinity.c b/tests/sched_xetaffinity.c index cebff3ab..2e508ca3 100644 --- a/tests/sched_xetaffinity.c +++ b/tests/sched_xetaffinity.c @@ -10,6 +10,7 @@ #include "tests.h" #include "scno.h" +#include "pidns.h" #include #if defined __NR_sched_getaffinity && defined __NR_sched_setaffinity \ @@ -41,8 +42,11 @@ setaffinity(unsigned long pid, unsigned long size, void *set) int main(void) { + PIDNS_TEST_INIT; + unsigned int cpuset_size = 1; const pid_t pid = getpid(); + const char *pid_str = pidns_pid2str(PT_TGID); while (cpuset_size) { assert(getaffinity(pid, cpuset_size, NULL) == -1); @@ -50,18 +54,21 @@ main(void) break; if (EINVAL != errno) perror_msg_and_skip("sched_getaffinity"); - printf("sched_getaffinity(%d, %u, NULL) = %s\n", - pid, cpuset_size, errstr); + pidns_print_leader(); + printf("sched_getaffinity(%d%s, %u, NULL) = %s\n", + pid, pid_str, cpuset_size, errstr); cpuset_size <<= 1; } assert(cpuset_size); - printf("sched_getaffinity(%d, %u, NULL) = %s\n", - pid, cpuset_size, errstr); + pidns_print_leader(); + printf("sched_getaffinity(%d%s, %u, NULL) = %s\n", + pid, pid_str, cpuset_size, errstr); cpu_set_t *cpuset = tail_alloc(cpuset_size); getaffinity(pid, cpuset_size, cpuset + 1); - printf("sched_getaffinity(%d, %u, %p) = %s\n", - pid, cpuset_size, cpuset + 1, errstr); + pidns_print_leader(); + printf("sched_getaffinity(%d%s, %u, %p) = %s\n", + pid, pid_str, cpuset_size, cpuset + 1, errstr); int ret_size = getaffinity(pid, cpuset_size, cpuset); if (ret_size < 0) @@ -69,7 +76,8 @@ main(void) pid, (unsigned) cpuset_size, cpuset, errstr); assert(ret_size <= (int) cpuset_size); - printf("sched_getaffinity(%d, %u, [", pid, cpuset_size); + pidns_print_leader(); + printf("sched_getaffinity(%d%s, %u, [", pid, pid_str, cpuset_size); const char *sep; unsigned int i, cpu; for (i = 0, cpu = 0, sep = ""; i < (unsigned) ret_size * 8; ++i) { @@ -85,8 +93,9 @@ main(void) CPU_SET_S(cpu, cpuset_size, cpuset); if (setaffinity(pid, cpuset_size, cpuset)) perror_msg_and_skip("sched_setaffinity"); - printf("sched_setaffinity(%d, %u, [%u]) = 0\n", - pid, cpuset_size, cpu); + pidns_print_leader(); + printf("sched_setaffinity(%d%s, %u, [%u]) = 0\n", + pid, pid_str, cpuset_size, cpu); const unsigned int big_size = cpuset_size < 128 ? 128 : cpuset_size * 2; cpuset = tail_alloc(big_size); @@ -95,7 +104,8 @@ main(void) perror_msg_and_fail("sched_getaffinity(%d, %u, %p) = %s\n", pid, big_size, cpuset, errstr); assert(ret_size <= (int) big_size); - printf("sched_getaffinity(%d, %u, [", pid, big_size); + pidns_print_leader(); + printf("sched_getaffinity(%d%s, %u, [", pid, pid_str, big_size); for (i = 0, sep = ""; i < (unsigned) ret_size * 8; ++i) { if (CPU_ISSET_S(i, (unsigned) ret_size, cpuset)) { printf("%s%u", sep, i); @@ -104,6 +114,7 @@ main(void) } printf("]) = %s\n", errstr); + pidns_print_leader(); puts("+++ exited with 0 +++"); return 0; } diff --git a/tests/sched_xetattr--pidns-translation.c b/tests/sched_xetattr--pidns-translation.c new file mode 100644 index 00000000..c152023d --- /dev/null +++ b/tests/sched_xetattr--pidns-translation.c @@ -0,0 +1,2 @@ +#define PIDNS_TRANSLATION +#include "sched_xetattr.c" diff --git a/tests/sched_xetattr.c b/tests/sched_xetattr.c index c63d7a80..4a76b2d6 100644 --- a/tests/sched_xetattr.c +++ b/tests/sched_xetattr.c @@ -15,6 +15,7 @@ # include # include # include +# include "pidns.h" # include "sched_attr.h" # include "xlat.h" # include "xlat/schedulers.h" @@ -41,6 +42,8 @@ sys_sched_setattr(kernel_ulong_t pid, kernel_ulong_t attr, kernel_ulong_t flags) int main(void) { + PIDNS_TEST_INIT; + static const kernel_ulong_t bogus_pid = (kernel_ulong_t) 0xdefacedfacefeedULL; static const kernel_ulong_t bogus_size = @@ -48,20 +51,28 @@ main(void) static const kernel_ulong_t bogus_flags = (kernel_ulong_t) 0xdefaceddeadc0deULL; + const int pid = getpid(); + const char *pid_str = pidns_pid2str(PT_TGID); + TAIL_ALLOC_OBJECT_CONST_PTR(struct sched_attr, attr); TAIL_ALLOC_OBJECT_CONST_PTR(unsigned int, psize); void *const efault = attr + 1; - sys_sched_getattr(0, 0, 0, 0); - printf("sched_getattr(0, NULL, 0, 0) = %s\n", errstr); + sys_sched_getattr(pid, 0, 0, 0); + pidns_print_leader(); + printf("sched_getattr(%d%s, NULL, 0, 0) = %s\n", + pid, pid_str, errstr); sys_sched_getattr(0, (unsigned long) attr, 0, 0); + pidns_print_leader(); printf("sched_getattr(0, %p, 0, 0) = %s\n", attr, errstr); sys_sched_getattr(bogus_pid, 0, 0, 0); + pidns_print_leader(); printf("sched_getattr(%d, NULL, 0, 0) = %s\n", (int) bogus_pid, errstr); sys_sched_getattr(-1U, (unsigned long) attr, bogus_size, bogus_flags); + pidns_print_leader(); printf("sched_getattr(-1, %p, %s%u, %u) = %s\n", attr, # if defined __arm64__ || defined __aarch64__ @@ -72,11 +83,13 @@ main(void) (unsigned) bogus_size, (unsigned) bogus_flags, errstr); sys_sched_getattr(0, (unsigned long) efault, SCHED_ATTR_MIN_SIZE, 0); + pidns_print_leader(); printf("sched_getattr(0, %p, %u, 0) = %s\n", efault, (unsigned) SCHED_ATTR_MIN_SIZE, errstr); if (sys_sched_getattr(0, (unsigned long) attr, SCHED_ATTR_MIN_SIZE, 0)) perror_msg_and_skip("sched_getattr"); + pidns_print_leader(); printf("sched_getattr(0, {size=%u, sched_policy=", attr->size); printxval(schedulers, attr->sched_policy, NULL); printf(", sched_flags=%s, sched_nice=%d, sched_priority=%u" @@ -91,11 +104,13 @@ main(void) (unsigned) SCHED_ATTR_MIN_SIZE); sys_sched_getattr(0, (unsigned long) efault, sizeof(*attr), 0); + pidns_print_leader(); printf("sched_getattr(0, %p, %u, 0) = %s\n", efault, (unsigned) sizeof(*attr), errstr); if (sys_sched_getattr(0, (unsigned long) attr, sizeof(*attr), 0)) perror_msg_and_skip("sched_getattr"); + pidns_print_leader(); printf("sched_getattr(0, {size=%u, sched_policy=", attr->size); printxval(schedulers, attr->sched_policy, NULL); printf(", sched_flags=%s, sched_nice=%d, sched_priority=%u" @@ -121,11 +136,13 @@ main(void) F8ILL_KULONG_MASK | sizeof(*attr), F8ILL_KULONG_MASK); # if defined __arm64__ || defined __aarch64__ if (rc) { + pidns_print_leader(); printf("sched_getattr(0, %p, 0xffffffff<<32|%u, 0) = %s\n", attr, (unsigned) sizeof(*attr), errstr); } else # endif { + pidns_print_leader(); printf("sched_getattr(0, {size=%u, sched_policy=", attr->size); printxval(schedulers, attr->sched_policy, NULL); printf(", sched_flags=%s, sched_nice=%d, sched_priority=%u" @@ -146,13 +163,16 @@ main(void) } sys_sched_setattr(bogus_pid, 0, 0); + pidns_print_leader(); printf("sched_setattr(%d, NULL, 0) = %s\n", (int) bogus_pid, errstr); attr->sched_flags |= 1; - if (sys_sched_setattr(0, (unsigned long) attr, 0)) + if (sys_sched_setattr(pid, (unsigned long) attr, 0)) perror_msg_and_skip("sched_setattr"); - printf("sched_setattr(0, {size=%u, sched_policy=", attr->size); + pidns_print_leader(); + printf("sched_setattr(%d%s, {size=%u, sched_policy=", + pid, pid_str, attr->size); printxval(schedulers, attr->sched_policy, NULL); printf(", sched_flags=%s, sched_nice=%d, sched_priority=%u" ", sched_runtime=%" PRIu64 ", sched_deadline=%" PRIu64 @@ -172,6 +192,7 @@ main(void) sys_sched_setattr(F8ILL_KULONG_MASK, (unsigned long) attr, F8ILL_KULONG_MASK); + pidns_print_leader(); printf("sched_setattr(0, {size=%u, sched_policy=", attr->size); printxval(schedulers, attr->sched_policy, NULL); printf(", sched_flags=%s, sched_nice=%d, sched_priority=%u" @@ -193,11 +214,13 @@ main(void) *psize = attr->size; sys_sched_setattr(0, (unsigned long) psize, 0); + pidns_print_leader(); printf("sched_setattr(0, %p, 0) = %s\n", psize, errstr); attr->size = 0; sys_sched_setattr(0, (unsigned long) attr, 0); + pidns_print_leader(); printf("sched_setattr(0, {size=%u, sched_policy=", attr->size); printxval(schedulers, attr->sched_policy, NULL); printf(", sched_flags=%s, sched_nice=%d, sched_priority=%u" @@ -213,12 +236,14 @@ main(void) attr->size = 1; sys_sched_setattr(0, (unsigned long) attr, 0); + pidns_print_leader(); printf("sched_setattr(0, {size=%u} => {size=%u}, 0) = %s\n", 1, attr->size, errstr); attr->size = SCHED_ATTR_MIN_SIZE - 1; sys_sched_setattr(0, (unsigned long) attr, 0); + pidns_print_leader(); printf("sched_setattr(0, {size=%u} => {size=%u}, 0) = %s\n", SCHED_ATTR_MIN_SIZE - 1, attr->size, errstr); @@ -232,6 +257,7 @@ main(void) attr->sched_period = 0xded1ca7edda7aca7ULL; sys_sched_setattr(bogus_pid, (unsigned long) attr, bogus_flags); + pidns_print_leader(); printf("sched_setattr(%d, {size=%u, sched_policy=%#x /* SCHED_??? */, " "sched_flags=%#" PRIx64 " /* SCHED_FLAG_??? */, " "sched_nice=%d, sched_priority=%u, sched_runtime=%" PRIu64 ", " @@ -274,6 +300,7 @@ main(void) attr->sched_period = 0xded1ca7edda7aca7ULL; sys_sched_setattr(bogus_pid, (unsigned long) attr, bogus_flags); + pidns_print_leader(); printf("sched_setattr(%d, {size=%u, sched_policy=%#x /* SCHED_??? */, " "sched_flags=SCHED_FLAG_RESET_ON_FORK|SCHED_FLAG_RECLAIM|" "SCHED_FLAG_DL_OVERRUN|0x80, " @@ -296,11 +323,13 @@ main(void) const kernel_ulong_t ill = f8ill_ptr_to_kulong(attr); sys_sched_getattr(0, ill, sizeof(*attr), 0); + pidns_print_leader(); printf("sched_getattr(0, %#llx, %u, 0) = %s\n", (unsigned long long) ill, (unsigned) sizeof(*attr), errstr); sys_sched_setattr(0, ill, 0); + pidns_print_leader(); printf("sched_setattr(0, %#llx, 0) = %s\n", (unsigned long long) ill, errstr); } @@ -310,6 +339,7 @@ main(void) attr->sched_flags = 0x8fULL; sys_sched_setattr(bogus_pid, (unsigned long) attr, bogus_flags); + pidns_print_leader(); printf("sched_setattr(%d, {size=%u, " "sched_flags=SCHED_FLAG_RESET_ON_FORK|SCHED_FLAG_RECLAIM|" "SCHED_FLAG_DL_OVERRUN|SCHED_FLAG_KEEP_POLICY|0x80, " @@ -329,11 +359,13 @@ main(void) const kernel_ulong_t ill = f8ill_ptr_to_kulong(attr); sys_sched_getattr(0, ill, sizeof(*attr), 0); + pidns_print_leader(); printf("sched_getattr(0, %#llx, %u, 0) = %s\n", (unsigned long long) ill, (unsigned) sizeof(*attr), errstr); sys_sched_setattr(0, ill, 0); + pidns_print_leader(); printf("sched_setattr(0, %#llx, 0) = %s\n", (unsigned long long) ill, errstr); } @@ -342,6 +374,7 @@ main(void) attr->sched_flags = 0xe7ULL; sys_sched_setattr(bogus_pid, (unsigned long) attr, bogus_flags); + pidns_print_leader(); printf("sched_setattr(%d, {size=%u, sched_policy=%#x /* SCHED_??? */, " "sched_flags=SCHED_FLAG_RESET_ON_FORK|SCHED_FLAG_RECLAIM|" "SCHED_FLAG_DL_OVERRUN|SCHED_FLAG_UTIL_CLAMP_MIN" @@ -365,11 +398,13 @@ main(void) const kernel_ulong_t ill = f8ill_ptr_to_kulong(attr); sys_sched_getattr(0, ill, sizeof(*attr), 0); + pidns_print_leader(); printf("sched_getattr(0, %#llx, %u, 0) = %s\n", (unsigned long long) ill, (unsigned) sizeof(*attr), errstr); sys_sched_setattr(0, ill, 0); + pidns_print_leader(); printf("sched_setattr(0, %#llx, 0) = %s\n", (unsigned long long) ill, errstr); } @@ -377,6 +412,7 @@ main(void) attr->sched_flags = 0xcaffee90LL; sys_sched_setattr(bogus_pid, (unsigned long) attr, bogus_flags); + pidns_print_leader(); printf("sched_setattr(%d, {size=%u, sched_flags=SCHED_FLAG_KEEP_PARAMS" "|0xcaffee80, sched_util_min=%u, sched_util_max=%u}, %u) = %s\n", (int) bogus_pid, @@ -389,15 +425,18 @@ main(void) const kernel_ulong_t ill = f8ill_ptr_to_kulong(attr); sys_sched_getattr(0, ill, sizeof(*attr), 0); + pidns_print_leader(); printf("sched_getattr(0, %#llx, %u, 0) = %s\n", (unsigned long long) ill, (unsigned) sizeof(*attr), errstr); sys_sched_setattr(0, ill, 0); + pidns_print_leader(); printf("sched_setattr(0, %#llx, 0) = %s\n", (unsigned long long) ill, errstr); } + pidns_print_leader(); puts("+++ exited with 0 +++"); return 0; } diff --git a/tests/sched_xetparam--pidns-translation.c b/tests/sched_xetparam--pidns-translation.c new file mode 100644 index 00000000..9fb3e579 --- /dev/null +++ b/tests/sched_xetparam--pidns-translation.c @@ -0,0 +1,2 @@ +#define PIDNS_TRANSLATION +#include "sched_xetparam.c" diff --git a/tests/sched_xetparam.c b/tests/sched_xetparam.c index de3915b2..aa9c68cc 100644 --- a/tests/sched_xetparam.c +++ b/tests/sched_xetparam.c @@ -7,6 +7,7 @@ #include "tests.h" #include "scno.h" +# include "pidns.h" #if defined __NR_sched_getparam && defined __NR_sched_setparam @@ -17,18 +18,27 @@ int main(void) { + PIDNS_TEST_INIT; + struct sched_param *const param = tail_alloc(sizeof(struct sched_param)); - long rc = syscall(__NR_sched_getparam, 0, param); - printf("sched_getparam(0, [%d]) = %ld\n", - param->sched_priority, rc); + const int pid = getpid(); + const char *pid_str = pidns_pid2str(PT_TGID); + + long rc = syscall(__NR_sched_getparam, pid, param); + pidns_print_leader(); + printf("sched_getparam(%d%s, [%d]) = %ld\n", + pid, pid_str, param->sched_priority, rc); param->sched_priority = -1; - rc = syscall(__NR_sched_setparam, 0, param); - printf("sched_setparam(0, [%d]) = %ld %s (%m)\n", + rc = syscall(__NR_sched_setparam, pid, param); + pidns_print_leader(); + printf("sched_setparam(%d%s, [%d]) = %ld %s (%m)\n", + pid, pid_str, param->sched_priority, rc, errno2name()); + pidns_print_leader(); puts("+++ exited with 0 +++"); return 0; } diff --git a/tests/sched_xetscheduler--pidns-translation.c b/tests/sched_xetscheduler--pidns-translation.c new file mode 100644 index 00000000..78b794b2 --- /dev/null +++ b/tests/sched_xetscheduler--pidns-translation.c @@ -0,0 +1,2 @@ +#define PIDNS_TRANSLATION +#include "sched_xetscheduler.c" diff --git a/tests/sched_xetscheduler.c b/tests/sched_xetscheduler.c index 047e8676..91b5e32d 100644 --- a/tests/sched_xetscheduler.c +++ b/tests/sched_xetscheduler.c @@ -7,6 +7,7 @@ #include "tests.h" #include "scno.h" +#include "pidns.h" #if defined __NR_sched_getscheduler && defined __NR_sched_setscheduler @@ -17,8 +18,13 @@ int main(void) { + PIDNS_TEST_INIT; + TAIL_ALLOC_OBJECT_CONST_PTR(struct sched_param, param); - long rc = syscall(__NR_sched_getscheduler, 0); + const int pid = getpid(); + const char *pid_str = pidns_pid2str(PT_TGID); + + long rc = syscall(__NR_sched_getscheduler, pid); const char *scheduler; switch (rc) { case SCHED_FIFO: @@ -50,33 +56,43 @@ main(void) default: scheduler = "SCHED_OTHER"; } - printf("sched_getscheduler(0) = %ld (%s)\n", - rc, scheduler); + pidns_print_leader(); + printf("sched_getscheduler(%d%s) = %ld (%s)\n", + pid, pid_str, rc, scheduler); rc = syscall(__NR_sched_getscheduler, -1); + pidns_print_leader(); printf("sched_getscheduler(-1) = %s\n", sprintrc(rc)); param->sched_priority = -1; - rc = syscall(__NR_sched_setscheduler, 0, SCHED_FIFO, NULL); - printf("sched_setscheduler(0, SCHED_FIFO, NULL) = %s\n", sprintrc(rc)); + rc = syscall(__NR_sched_setscheduler, pid, SCHED_FIFO, NULL); + pidns_print_leader(); + printf("sched_setscheduler(%d%s, SCHED_FIFO, NULL) = %s\n", + pid, pid_str, sprintrc(rc)); - rc = syscall(__NR_sched_setscheduler, 0, SCHED_FIFO, param + 1); - printf("sched_setscheduler(0, SCHED_FIFO, %p) = %s\n", param + 1, - sprintrc(rc)); + rc = syscall(__NR_sched_setscheduler, pid, SCHED_FIFO, param + 1); + pidns_print_leader(); + printf("sched_setscheduler(%d%s, SCHED_FIFO, %p) = %s\n", + pid, pid_str, param + 1, sprintrc(rc)); - rc = syscall(__NR_sched_setscheduler, 0, 0xfaceda7a, param); - printf("sched_setscheduler(0, %#x /* SCHED_??? */, [%d]) = %s\n", - 0xfaceda7a, param->sched_priority, sprintrc(rc)); + rc = syscall(__NR_sched_setscheduler, pid, 0xfaceda7a, param); + pidns_print_leader(); + printf("sched_setscheduler(%d%s, %#x /* SCHED_??? */, [%d]) = %s\n", + pid, pid_str, 0xfaceda7a, + param->sched_priority, sprintrc(rc)); rc = syscall(__NR_sched_setscheduler, -1, SCHED_FIFO, param); + pidns_print_leader(); printf("sched_setscheduler(-1, SCHED_FIFO, [%d]) = %s\n", param->sched_priority, sprintrc(rc)); - rc = syscall(__NR_sched_setscheduler, 0, SCHED_FIFO, param); - printf("sched_setscheduler(0, SCHED_FIFO, [%d]) = %s\n", - param->sched_priority, sprintrc(rc)); + rc = syscall(__NR_sched_setscheduler, pid, SCHED_FIFO, param); + pidns_print_leader(); + printf("sched_setscheduler(%d%s, SCHED_FIFO, [%d]) = %s\n", + pid, pid_str, param->sched_priority, sprintrc(rc)); + pidns_print_leader(); puts("+++ exited with 0 +++"); return 0; } diff --git a/tests/signal_receive--pidns-translation.c b/tests/signal_receive--pidns-translation.c new file mode 100644 index 00000000..b4e3b2f8 --- /dev/null +++ b/tests/signal_receive--pidns-translation.c @@ -0,0 +1,2 @@ +#define PIDNS_TRANSLATION +#include "signal_receive.c" diff --git a/tests/signal_receive.c b/tests/signal_receive.c index ad3b4ebd..70441a9e 100644 --- a/tests/signal_receive.c +++ b/tests/signal_receive.c @@ -8,6 +8,7 @@ */ #include "tests.h" +#include "pidns.h" #include #include #include @@ -26,10 +27,13 @@ handler(int sig, siginfo_t *info, void *ucontext) int main(void) { + PIDNS_TEST_INIT; + static const char prefix[] = "KERNEL BUG"; int printed = 0; const int pid = getpid(); + const char *pid_str = pidns_pid2str(PT_TGID); const int uid = geteuid(); for (int sig = 1; sig <= 31; ++sig) { @@ -73,10 +77,13 @@ main(void) const int e_pid = s_pid; const int e_uid = s_uid; #endif - printf("kill(%d, %s) = 0\n", pid, signal2name(sig)); - printf("--- %s {si_signo=%s, si_code=SI_USER, si_pid=%d" + pidns_print_leader(); + printf("kill(%d%s, %s) = 0\n", pid, pid_str, signal2name(sig)); + pidns_print_leader(); + printf("--- %s {si_signo=%s, si_code=SI_USER, si_pid=%d%s" ", si_uid=%d} ---\n", - signal2name(sig), signal2name(e_sig), e_pid, e_uid); + signal2name(sig), signal2name(e_sig), + e_pid, pid_str, e_uid); if (s_code || sig != s_sig || pid != s_pid || uid != s_uid) { /* @@ -91,11 +98,11 @@ main(void) } fprintf(stderr, "%s: expected: si_signo=%d, si_code=%d" - ", si_pid=%d, si_uid=%d\n" + ", si_pid=%d%s, si_uid=%d\n" "%s: received: si_signo=%d, si_code=%d" - ", si_pid=%d, si_uid=%d\n", - prefix, sig, SI_USER, pid, uid, - prefix, sig, s_code, s_pid, s_uid); + ", si_pid=%d%s, si_uid=%d\n", + prefix, sig, SI_USER, pid, pid_str, uid, + prefix, sig, s_code, s_pid, pid_str, s_uid); } } @@ -104,6 +111,7 @@ main(void) "*** PLEASE FIX THE KERNEL ***\n", prefix); } + pidns_print_leader(); puts("+++ exited with 0 +++"); return 0; } diff --git a/tests/so_peercred--pidns-translation.c b/tests/so_peercred--pidns-translation.c new file mode 100644 index 00000000..402bbcfe --- /dev/null +++ b/tests/so_peercred--pidns-translation.c @@ -0,0 +1,2 @@ +#define PIDNS_TRANSLATION +#include "so_peercred.c" diff --git a/tests/so_peercred.c b/tests/so_peercred.c index 151bb175..20188bdb 100644 --- a/tests/so_peercred.c +++ b/tests/so_peercred.c @@ -9,6 +9,7 @@ */ #include "tests.h" +#include "pidns.h" #include #include @@ -53,6 +54,8 @@ so_str(void) int main(void) { + PIDNS_TEST_INIT; + TAIL_ALLOC_OBJECT_CONST_PTR(struct ucred, peercred); TAIL_ALLOC_OBJECT_CONST_PTR(socklen_t, len); @@ -75,6 +78,8 @@ main(void) struct ucred *const gid_truncated = tail_alloc(sizeof_gid_truncated); + const char *pid_str = pidns_pid2str(PT_TGID); + int sv[2]; if (socketpair(AF_UNIX, SOCK_STREAM, 0, sv)) perror_msg_and_skip("socketpair AF_UNIX SOCK_STREAM"); @@ -82,8 +87,10 @@ main(void) /* classic getsockopt */ *len = sizeof(*peercred); get_peercred(sv[0], peercred, len); + pidns_print_leader(); printf("getsockopt(%d, %s", sv[0], so_str()); PRINT_FIELD_D(", {", *peercred, pid); + printf("%s", pid_str); PRINT_FIELD_UID(", ", *peercred, uid); PRINT_FIELD_UID(", ", *peercred, gid); printf("}, [%d]) = %s\n", *len, errstr); @@ -91,14 +98,17 @@ main(void) /* getsockopt with zero optlen */ *len = 0; get_peercred(sv[0], peercred, len); + pidns_print_leader(); printf("getsockopt(%d, %s, %p, [0]) = %s\n", sv[0], so_str(), peercred, errstr); /* getsockopt with optlen larger than necessary - shortened */ *len = sizeof(*peercred) + 1; get_peercred(sv[0], peercred, len); + pidns_print_leader(); printf("getsockopt(%d, %s", sv[0], so_str()); PRINT_FIELD_D(", {", *peercred, pid); + printf("%s", pid_str); PRINT_FIELD_UID(", ", *peercred, uid); PRINT_FIELD_UID(", ", *peercred, gid); printf("}, [%u->%d]) = %s\n", @@ -110,6 +120,7 @@ main(void) */ *len = sizeof_pid_truncated; get_peercred(sv[0], pid_truncated, len); + pidns_print_leader(); printf("getsockopt(%d, %s, {pid=", sv[0], so_str()); print_quoted_hex(pid_truncated, *len); printf("}, [%d]) = %s\n", *len, errstr); @@ -120,8 +131,10 @@ main(void) */ *len = sizeof_pid; get_peercred(sv[0], pid, len); + pidns_print_leader(); printf("getsockopt(%d, %s", sv[0], so_str()); PRINT_FIELD_D(", {", *pid, pid); + printf("%s", pid_str); printf("}, [%d]) = %s\n", *len, errstr); /* @@ -136,8 +149,10 @@ main(void) * to struct ucred.pid field. */ memcpy(uid, uid_truncated, sizeof_uid_truncated); + pidns_print_leader(); printf("getsockopt(%d, %s", sv[0], so_str()); PRINT_FIELD_D(", {", *uid, pid); + printf("%s", pid_str); printf(", uid="); print_quoted_hex(&uid->uid, sizeof_uid_truncated - offsetof(struct ucred, uid)); @@ -149,8 +164,10 @@ main(void) */ *len = sizeof_uid; get_peercred(sv[0], uid, len); + pidns_print_leader(); printf("getsockopt(%d, %s", sv[0], so_str()); PRINT_FIELD_D(", {", *uid, pid); + printf("%s", pid_str); PRINT_FIELD_UID(", ", *uid, uid); printf("}, [%d]) = %s\n", *len, errstr); @@ -166,8 +183,10 @@ main(void) * to struct ucred.pid and struct ucred.uid fields. */ memcpy(peercred, gid_truncated, sizeof_gid_truncated); + pidns_print_leader(); printf("getsockopt(%d, %s", sv[0], so_str()); PRINT_FIELD_D(", {", *peercred, pid); + printf("%s", pid_str); PRINT_FIELD_UID(", ", *peercred, uid); printf(", gid="); print_quoted_hex(&peercred->gid, sizeof_gid_truncated - @@ -177,14 +196,17 @@ main(void) /* getsockopt optval EFAULT */ *len = sizeof(*peercred); get_peercred(sv[0], &peercred->uid, len); + pidns_print_leader(); printf("getsockopt(%d, %s, %p, [%d]) = %s\n", sv[0], so_str(), &peercred->uid, *len, errstr); /* getsockopt optlen EFAULT */ get_peercred(sv[0], peercred, len + 1); + pidns_print_leader(); printf("getsockopt(%d, %s, %p, %p) = %s\n", sv[0], so_str(), peercred, len + 1, errstr); + pidns_print_leader(); puts("+++ exited with 0 +++"); return 0; } diff --git a/tests/xet_robust_list--pidns-translation.c b/tests/xet_robust_list--pidns-translation.c new file mode 100644 index 00000000..e0477267 --- /dev/null +++ b/tests/xet_robust_list--pidns-translation.c @@ -0,0 +1,2 @@ +#define PIDNS_TRANSLATION +#include "xet_robust_list.c" diff --git a/tests/xet_robust_list.c b/tests/xet_robust_list.c index 43239c8b..b5751b0a 100644 --- a/tests/xet_robust_list.c +++ b/tests/xet_robust_list.c @@ -8,6 +8,7 @@ #include "tests.h" #include "scno.h" +#include "pidns.h" #if defined __NR_get_robust_list && defined __NR_set_robust_list @@ -30,27 +31,36 @@ sprintaddr(void *addr) int main(void) { + PIDNS_TEST_INIT; + const pid_t pid = getpid(); + const char *pid_str = pidns_pid2str(PT_TGID); const long long_pid = (unsigned long) (0xdeadbeef00000000LL | pid); TAIL_ALLOC_OBJECT_CONST_PTR(void *, p_head); TAIL_ALLOC_OBJECT_CONST_PTR(size_t, p_len); if (syscall(__NR_get_robust_list, long_pid, p_head, p_len)) perror_msg_and_skip("get_robust_list"); - printf("get_robust_list(%d, [%s], [%lu]) = 0\n", - (int) pid, sprintaddr(*p_head), (unsigned long) *p_len); + pidns_print_leader(); + printf("get_robust_list(%d%s, [%s], [%lu]) = 0\n", + pid, pid_str, sprintaddr(*p_head), + (unsigned long) *p_len); void *head = tail_alloc(*p_len); if (syscall(__NR_set_robust_list, head, *p_len)) perror_msg_and_skip("set_robust_list"); + pidns_print_leader(); printf("set_robust_list(%p, %lu) = 0\n", head, (unsigned long) *p_len); if (syscall(__NR_get_robust_list, long_pid, p_head, p_len)) perror_msg_and_skip("get_robust_list"); - printf("get_robust_list(%d, [%s], [%lu]) = 0\n", - (int) pid, sprintaddr(*p_head), (unsigned long) *p_len); + pidns_print_leader(); + printf("get_robust_list(%d%s, [%s], [%lu]) = 0\n", + pid, pid_str, sprintaddr(*p_head), + (unsigned long) *p_len); + pidns_print_leader(); puts("+++ exited with 0 +++"); return 0; } diff --git a/tests/xetpgid--pidns-translation.c b/tests/xetpgid--pidns-translation.c new file mode 100644 index 00000000..b6469628 --- /dev/null +++ b/tests/xetpgid--pidns-translation.c @@ -0,0 +1,2 @@ +#define PIDNS_TRANSLATION +#include "xetpgid.c" diff --git a/tests/xetpgid.c b/tests/xetpgid.c index 9b070af2..411edfc7 100644 --- a/tests/xetpgid.c +++ b/tests/xetpgid.c @@ -10,6 +10,7 @@ #include "tests.h" #include "scno.h" +#include "pidns.h" #if defined __NR_getpgid && defined __NR_setpgid @@ -19,13 +20,21 @@ int main(void) { - const int pid = getpid(); - long rc = syscall(__NR_getpgid, F8ILL_KULONG_MASK | pid); - printf("getpgid(%d) = %ld\n", pid, rc); - - rc = syscall(__NR_setpgid, F8ILL_KULONG_MASK, F8ILL_KULONG_MASK | pid); - printf("setpgid(0, %d) = %ld\n", pid, rc); + PIDNS_TEST_INIT; + const int pid = getpid(); + long pgid = syscall(__NR_getpgid, F8ILL_KULONG_MASK | pid); + pidns_print_leader(); + printf("getpgid(%d%s) = %ld%s\n", pid, pidns_pid2str(PT_TGID), + pgid, pidns_pid2str(PT_PGID)); + + long rc = syscall(__NR_setpgid, F8ILL_KULONG_MASK, + F8ILL_KULONG_MASK | pgid); + pidns_print_leader(); + printf("setpgid(0, %ld%s) = %s\n", pgid, pidns_pid2str(PT_PGID), + sprintrc(rc)); + + pidns_print_leader(); puts("+++ exited with 0 +++"); return 0; } diff --git a/tests/xetpriority--pidns-translation.c b/tests/xetpriority--pidns-translation.c new file mode 100644 index 00000000..c93669cb --- /dev/null +++ b/tests/xetpriority--pidns-translation.c @@ -0,0 +1,2 @@ +#define PIDNS_TRANSLATION +#include "xetpriority.c" diff --git a/tests/xetpriority.c b/tests/xetpriority.c index 2d61bd10..dd38217d 100644 --- a/tests/xetpriority.c +++ b/tests/xetpriority.c @@ -7,6 +7,7 @@ #include "tests.h" #include "scno.h" +#include "pidns.h" #if defined __NR_getpriority && defined __NR_setpriority @@ -17,15 +18,30 @@ int main(void) { + PIDNS_TEST_INIT; + const int pid = getpid(); + const int pgid = getpgid(0); + long rc = syscall(__NR_getpriority, PRIO_PROCESS, F8ILL_KULONG_MASK | pid); - printf("getpriority(PRIO_PROCESS, %d) = %ld\n", pid, rc); + pidns_print_leader(); + printf("getpriority(PRIO_PROCESS, %d%s) = %ld\n", + pid, pidns_pid2str(PT_TGID), rc); rc = syscall(__NR_setpriority, PRIO_PROCESS, F8ILL_KULONG_MASK | pid, F8ILL_KULONG_MASK); - printf("setpriority(PRIO_PROCESS, %d, 0) = %s\n", pid, sprintrc(rc)); + pidns_print_leader(); + printf("setpriority(PRIO_PROCESS, %d%s, 0) = %s\n", + pid, pidns_pid2str(PT_TGID), sprintrc(rc)); + + rc = syscall(__NR_getpriority, PRIO_PGRP, + F8ILL_KULONG_MASK | pgid); + pidns_print_leader(); + printf("getpriority(PRIO_PGRP, %d%s) = %ld\n", + pgid, pidns_pid2str(PT_PGID), rc); + pidns_print_leader(); puts("+++ exited with 0 +++"); return 0; } -- 2.28.0 From uzonyi.akos at gmail.com Mon Aug 17 22:12:17 2020 From: uzonyi.akos at gmail.com (=?UTF-8?B?w4Frb3MgVXpvbnlp?=) Date: Tue, 18 Aug 2020 00:12:17 +0200 Subject: [RFC PATCH 0/4] [PIDNS] Trie and pidns-cache tests In-Reply-To: <20200815162710.GD376@altlinux.org> References: <20200813153242.94742-1-uzonyi.akos@gmail.com> <20200815124129.GB30941@altlinux.org> <20200815162710.GD376@altlinux.org> Message-ID: On Sat, 15 Aug 2020 at 18:27, Dmitry V. Levin wrote: > On Sat, Aug 15, 2020 at 06:23:26PM +0200, ?kos Uzonyi wrote: > > On Sat, 15 Aug 2020 at 14:41, Dmitry V. Levin wrote: > > > On Thu, Aug 13, 2020 at 05:32:38PM +0200, ?kos Uzonyi wrote: > > > > is it's OK to add ../trie.c ../trie.h to libtests_a_SOURCES? > > > > > > I suppose automake should be fine with it. What's your concern? > > > > Technically there is no problem, I just worried about including a file > > not in tests directory, as it hasn't been done before. But if you say > > it's OK, then everything is fine :). > > The only problem is that it won't be built with coverage support, > so it won't be shown in coverage reports. I found an another problem, github CI errors with: /usr/bin/ld: i386:x86-64 architecture of input file `libtests.a(libtests_a-trie.o)' is incompatible with i386 output I think we could add a symlink in tests/ directory pointing to trie.c, and use that. It would solve both problems if I'm not mistaken. From ldv at altlinux.org Mon Aug 17 23:12:49 2020 From: ldv at altlinux.org (Dmitry V. Levin) Date: Tue, 18 Aug 2020 02:12:49 +0300 Subject: [RFC PATCH 0/4] [PIDNS] Trie and pidns-cache tests In-Reply-To: References: <20200813153242.94742-1-uzonyi.akos@gmail.com> <20200815124129.GB30941@altlinux.org> <20200815162710.GD376@altlinux.org> Message-ID: <20200817231248.GA5522@altlinux.org> On Tue, Aug 18, 2020 at 12:12:17AM +0200, ?kos Uzonyi wrote: > On Sat, 15 Aug 2020 at 18:27, Dmitry V. Levin wrote: > > On Sat, Aug 15, 2020 at 06:23:26PM +0200, ?kos Uzonyi wrote: > > > On Sat, 15 Aug 2020 at 14:41, Dmitry V. Levin wrote: > > > > On Thu, Aug 13, 2020 at 05:32:38PM +0200, ?kos Uzonyi wrote: > > > > > is it's OK to add ../trie.c ../trie.h to libtests_a_SOURCES? > > > > > > > > I suppose automake should be fine with it. What's your concern? > > > > > > Technically there is no problem, I just worried about including a file > > > not in tests directory, as it hasn't been done before. But if you say > > > it's OK, then everything is fine :). > > > > The only problem is that it won't be built with coverage support, > > so it won't be shown in coverage reports. > > I found an another problem, github CI errors with: > > /usr/bin/ld: i386:x86-64 architecture of input file > `libtests.a(libtests_a-trie.o)' is incompatible with i386 output Interesting. Could you give a link to the full log? However, we are probably not interested in running this test for compat personalities. There is a loop in ./bootstrap that creates tests-m32 and tests-mx32 directories, we could do something there to filter it out. -- ldv From ldv at altlinux.org Mon Aug 17 23:14:21 2020 From: ldv at altlinux.org (Dmitry V. Levin) Date: Tue, 18 Aug 2020 02:14:21 +0300 Subject: [RFC PATCH v9 8/8] [squash] Add tests for tkill, tgkill In-Reply-To: <20200816221851.200031-9-uzonyi.akos@gmail.com> References: <20200816221851.200031-1-uzonyi.akos@gmail.com> <20200816221851.200031-9-uzonyi.akos@gmail.com> Message-ID: <20200817231421.GB5522@altlinux.org> On Mon, Aug 17, 2020 at 12:18:51AM +0200, ?kos Uzonyi wrote: > --- > tests/.gitignore | 2 ++ > tests/Makefile.am | 2 ++ > tests/gen_tests.in | 2 ++ > tests/tgkill--pidns-translation.c | 2 ++ > tests/tgkill.c | 51 +++++++++++++++++++++---------- > tests/tkill--pidns-translation.c | 2 ++ > tests/tkill.c | 19 +++++++++--- > 7 files changed, 59 insertions(+), 21 deletions(-) > create mode 100644 tests/tgkill--pidns-translation.c > create mode 100644 tests/tkill--pidns-translation.c This looks good, thanks. -- ldv From uzonyi.akos at gmail.com Mon Aug 17 23:21:18 2020 From: uzonyi.akos at gmail.com (=?UTF-8?B?w4Frb3MgVXpvbnlp?=) Date: Tue, 18 Aug 2020 01:21:18 +0200 Subject: [RFC PATCH 0/4] [PIDNS] Trie and pidns-cache tests In-Reply-To: <20200817231248.GA5522@altlinux.org> References: <20200813153242.94742-1-uzonyi.akos@gmail.com> <20200815124129.GB30941@altlinux.org> <20200815162710.GD376@altlinux.org> <20200817231248.GA5522@altlinux.org> Message-ID: On Tue, 18 Aug 2020 at 01:12, Dmitry V. Levin wrote: > On Tue, Aug 18, 2020 at 12:12:17AM +0200, ?kos Uzonyi wrote: > > On Sat, 15 Aug 2020 at 18:27, Dmitry V. Levin wrote: > > > On Sat, Aug 15, 2020 at 06:23:26PM +0200, ?kos Uzonyi wrote: > > > > On Sat, 15 Aug 2020 at 14:41, Dmitry V. Levin wrote: > > > > > On Thu, Aug 13, 2020 at 05:32:38PM +0200, ?kos Uzonyi wrote: > > > > > > is it's OK to add ../trie.c ../trie.h to libtests_a_SOURCES? > > > > > > > > > > I suppose automake should be fine with it. What's your concern? > > > > > > > > Technically there is no problem, I just worried about including a file > > > > not in tests directory, as it hasn't been done before. But if you say > > > > it's OK, then everything is fine :). > > > > > > The only problem is that it won't be built with coverage support, > > > so it won't be shown in coverage reports. > > > > I found an another problem, github CI errors with: > > > > /usr/bin/ld: i386:x86-64 architecture of input file > > `libtests.a(libtests_a-trie.o)' is incompatible with i386 output > > Interesting. Could you give a link to the full log? https://github.com/AkosUzonyi/strace/runs/994567416 > However, we are probably not interested in running this test for compat > personalities. There is a loop in ./bootstrap that creates tests-m32 and > tests-mx32 directories, we could do something there to filter it out. Yes, I was also thinking about doing something in bootstrap. But I think it's easier to add a symlink, and it also solves the coverage support problem. From ldv at altlinux.org Mon Aug 17 23:38:50 2020 From: ldv at altlinux.org (Dmitry V. Levin) Date: Tue, 18 Aug 2020 02:38:50 +0300 Subject: [RFC PATCH v9 0/8] [PIDNS] Final In-Reply-To: <20200816221851.200031-1-uzonyi.akos@gmail.com> References: <20200816221851.200031-1-uzonyi.akos@gmail.com> Message-ID: <20200817233850.GC5522@altlinux.org> On Mon, Aug 17, 2020 at 12:18:43AM +0200, ?kos Uzonyi wrote: > From: Uzonyi ?kos > > I made the requested changes, added more test cases to trie test, and fixed some > trie bugs. > > The travis build [1] unfortunately shows some errors. On ppc mknod test fails, > but I have no idea why. Mknod is unrelated to my code. Do you have any idea? Something is broken in their ppc system: apparently, they allow the mknod syscall to exit without an error in cases where is must fail with EEXIST because the target file already exists. This violates the contract: "If pathname already exists, or is a symbolic link, this call fails with an EEXIST error." I suppose they use some kind of mknod interception, and it doesn't implement the expected semantics. We can either come up with a workaround or report a bug and let them fix it. > Also, pidns-cache fails on one arm build. I tried to increase the time > available for translation, but it didn't help. Could you add some diagnostics to the test, e.g. how much time did it take in the first and in the second case? This way we could see what's going on. > Maybe pidns-cache test > should be removed, it's not very important. I'd rather keep the test to be sure the pidns cache is actually tested. -- ldv From ldv at altlinux.org Mon Aug 17 23:44:48 2020 From: ldv at altlinux.org (Dmitry V. Levin) Date: Tue, 18 Aug 2020 02:44:48 +0300 Subject: [RFC PATCH 0/4] [PIDNS] Trie and pidns-cache tests In-Reply-To: References: <20200813153242.94742-1-uzonyi.akos@gmail.com> <20200815124129.GB30941@altlinux.org> <20200815162710.GD376@altlinux.org> <20200817231248.GA5522@altlinux.org> Message-ID: <20200817234448.GD5522@altlinux.org> On Tue, Aug 18, 2020 at 01:21:18AM +0200, ?kos Uzonyi wrote: > On Tue, 18 Aug 2020 at 01:12, Dmitry V. Levin wrote: > > On Tue, Aug 18, 2020 at 12:12:17AM +0200, ?kos Uzonyi wrote: > > > On Sat, 15 Aug 2020 at 18:27, Dmitry V. Levin wrote: > > > > On Sat, Aug 15, 2020 at 06:23:26PM +0200, ?kos Uzonyi wrote: > > > > > On Sat, 15 Aug 2020 at 14:41, Dmitry V. Levin wrote: > > > > > > On Thu, Aug 13, 2020 at 05:32:38PM +0200, ?kos Uzonyi wrote: > > > > > > > is it's OK to add ../trie.c ../trie.h to libtests_a_SOURCES? > > > > > > > > > > > > I suppose automake should be fine with it. What's your concern? > > > > > > > > > > Technically there is no problem, I just worried about including a file > > > > > not in tests directory, as it hasn't been done before. But if you say > > > > > it's OK, then everything is fine :). > > > > > > > > The only problem is that it won't be built with coverage support, > > > > so it won't be shown in coverage reports. > > > > > > I found an another problem, github CI errors with: > > > > > > /usr/bin/ld: i386:x86-64 architecture of input file > > > `libtests.a(libtests_a-trie.o)' is incompatible with i386 output > > > > Interesting. Could you give a link to the full log? > > https://github.com/AkosUzonyi/strace/runs/994567416 I see, it just built ../libtests_a-trie.o once and used it several times. > > However, we are probably not interested in running this test for compat > > personalities. There is a loop in ./bootstrap that creates tests-m32 and > > tests-mx32 directories, we could do something there to filter it out. > > Yes, I was also thinking about doing something in bootstrap. But I > think it's easier to add a symlink, and it also solves the coverage > support problem. I agree adding a symlink is much easier way to fix the build, but I don't see how it solves the coverage support problem. -- ldv From uzonyi.akos at gmail.com Tue Aug 18 12:19:50 2020 From: uzonyi.akos at gmail.com (=?UTF-8?B?w4Frb3MgVXpvbnlp?=) Date: Tue, 18 Aug 2020 14:19:50 +0200 Subject: [RFC PATCH 0/4] [PIDNS] Trie and pidns-cache tests In-Reply-To: <20200817234448.GD5522@altlinux.org> References: <20200813153242.94742-1-uzonyi.akos@gmail.com> <20200815124129.GB30941@altlinux.org> <20200815162710.GD376@altlinux.org> <20200817231248.GA5522@altlinux.org> <20200817234448.GD5522@altlinux.org> Message-ID: On Tue, 18 Aug 2020 at 01:44, Dmitry V. Levin wrote: > On Tue, Aug 18, 2020 at 01:21:18AM +0200, ?kos Uzonyi wrote: > > On Tue, 18 Aug 2020 at 01:12, Dmitry V. Levin wrote: > > > On Tue, Aug 18, 2020 at 12:12:17AM +0200, ?kos Uzonyi wrote: > > > > On Sat, 15 Aug 2020 at 18:27, Dmitry V. Levin wrote: > > > > > On Sat, Aug 15, 2020 at 06:23:26PM +0200, ?kos Uzonyi wrote: > > > > > > On Sat, 15 Aug 2020 at 14:41, Dmitry V. Levin wrote: > > > > > > > On Thu, Aug 13, 2020 at 05:32:38PM +0200, ?kos Uzonyi wrote: > > > > > > > > is it's OK to add ../trie.c ../trie.h to libtests_a_SOURCES? > > > > > > > > > > > > > > I suppose automake should be fine with it. What's your concern? > > > > > > > > > > > > Technically there is no problem, I just worried about including a file > > > > > > not in tests directory, as it hasn't been done before. But if you say > > > > > > it's OK, then everything is fine :). > > > > > > > > > > The only problem is that it won't be built with coverage support, > > > > > so it won't be shown in coverage reports. > > > > > > > > I found an another problem, github CI errors with: > > > > > > > > /usr/bin/ld: i386:x86-64 architecture of input file > > > > `libtests.a(libtests_a-trie.o)' is incompatible with i386 output > > > > > > Interesting. Could you give a link to the full log? > > > > https://github.com/AkosUzonyi/strace/runs/994567416 > > I see, it just built ../libtests_a-trie.o once and used it several times. > > > > However, we are probably not interested in running this test for compat > > > personalities. There is a loop in ./bootstrap that creates tests-m32 and > > > tests-mx32 directories, we could do something there to filter it out. > > > > Yes, I was also thinking about doing something in bootstrap. But I > > think it's easier to add a symlink, and it also solves the coverage > > support problem. > > I agree adding a symlink is much easier way to fix the build, but I don't > see how it solves the coverage support problem. Sorry, I was wrong about this coverage thing. However pidns tests already cover nearly all the lines of trie.c (except trie_free), so trie test's goal is not to add line coverage, but to test edge cases of trie. From uzonyi.akos at gmail.com Tue Aug 18 22:37:14 2020 From: uzonyi.akos at gmail.com (=?UTF-8?B?w4Frb3MgVXpvbnlp?=) Date: Wed, 19 Aug 2020 00:37:14 +0200 Subject: [RFC PATCH v9 0/8] [PIDNS] Final In-Reply-To: <20200817233850.GC5522@altlinux.org> References: <20200816221851.200031-1-uzonyi.akos@gmail.com> <20200817233850.GC5522@altlinux.org> Message-ID: On Tue, 18 Aug 2020 at 01:38, Dmitry V. Levin wrote: > On Mon, Aug 17, 2020 at 12:18:43AM +0200, ?kos Uzonyi wrote: > > From: Uzonyi ?kos > > > > I made the requested changes, added more test cases to trie test, and fixed some > > trie bugs. > > > > The travis build [1] unfortunately shows some errors. On ppc mknod test fails, > > but I have no idea why. Mknod is unrelated to my code. Do you have any idea? > > Something is broken in their ppc system: apparently, they allow the mknod > syscall to exit without an error in cases where is must fail with EEXIST > because the target file already exists. This violates the contract: > "If pathname already exists, or is a symbolic link, this call fails with > an EEXIST error." I suppose they use some kind of mknod interception, > and it doesn't implement the expected semantics. > > We can either come up with a workaround or report a bug and let them fix it. What seems really strange is that only the last two mknod does not fail with EEXIST. > > Also, pidns-cache fails on one arm build. I tried to increase the time > > available for translation, but it didn't help. > > Could you add some diagnostics to the test, e.g. how much time did it take > in the first and in the second case? This way we could see what's going > on. Here are the results: (no translation | translation with cache | translation without cache) the 3 arm builds: 17846us 76435us 3676880us 141378us 496301us 3379754us 8699us 134754us 2974909us on my system: 948us 9358us 916094us s390x: 303us 2167us 110213us The numbers seem pretty chaotic on arm. Unfortunately I can't see a way how we could make this test work on these arm builds too. From ldv at altlinux.org Tue Aug 18 23:00:24 2020 From: ldv at altlinux.org (Dmitry V. Levin) Date: Wed, 19 Aug 2020 02:00:24 +0300 Subject: [RFC PATCH v9 0/8] [PIDNS] Final In-Reply-To: References: <20200816221851.200031-1-uzonyi.akos@gmail.com> <20200817233850.GC5522@altlinux.org> Message-ID: <20200818230024.GA21969@altlinux.org> On Wed, Aug 19, 2020 at 12:37:14AM +0200, ?kos Uzonyi wrote: > On Tue, 18 Aug 2020 at 01:38, Dmitry V. Levin wrote: > > On Mon, Aug 17, 2020 at 12:18:43AM +0200, ?kos Uzonyi wrote: > > > From: Uzonyi ?kos > > > > > > I made the requested changes, added more test cases to trie test, and fixed some > > > trie bugs. > > > > > > The travis build [1] unfortunately shows some errors. On ppc mknod test fails, > > > but I have no idea why. Mknod is unrelated to my code. Do you have any idea? > > > > Something is broken in their ppc system: apparently, they allow the mknod > > syscall to exit without an error in cases where is must fail with EEXIST > > because the target file already exists. This violates the contract: > > "If pathname already exists, or is a symbolic link, this call fails with > > an EEXIST error." I suppose they use some kind of mknod interception, > > and it doesn't implement the expected semantics. > > > > We can either come up with a workaround or report a bug and let them fix it. > > What seems really strange is that only the last two mknod does not > fail with EEXIST. Only the last two mknod calls are trying to create devices, all the rest aren't. This looks like an error in some seccomp filter. > > > Also, pidns-cache fails on one arm build. I tried to increase the time > > > available for translation, but it didn't help. > > > > Could you add some diagnostics to the test, e.g. how much time did it take > > in the first and in the second case? This way we could see what's going > > on. > > Here are the results: > (no translation | translation with cache | translation without cache) > > the 3 arm builds: > 17846us 76435us 3676880us > 141378us 496301us 3379754us > 8699us 134754us 2974909us > > on my system: > 948us 9358us 916094us I wonder why the cached translation takes that long on your system: 9358 / 948 ? 10 Would it make sense to increase SYSCALL_COUNT so that cache effect would become more visible compared to the translation without cache? -- ldv From ldv at altlinux.org Wed Aug 19 15:26:44 2020 From: ldv at altlinux.org (Dmitry V. Levin) Date: Wed, 19 Aug 2020 18:26:44 +0300 Subject: [RFC PATCH v9 0/8] [PIDNS] Final In-Reply-To: <20200818230024.GA21969@altlinux.org> References: <20200816221851.200031-1-uzonyi.akos@gmail.com> <20200817233850.GC5522@altlinux.org> <20200818230024.GA21969@altlinux.org> Message-ID: <20200819152643.GA1481@altlinux.org> On Wed, Aug 19, 2020 at 02:00:24AM +0300, Dmitry V. Levin wrote: > On Wed, Aug 19, 2020 at 12:37:14AM +0200, ?kos Uzonyi wrote: > > On Tue, 18 Aug 2020 at 01:38, Dmitry V. Levin wrote: > > > On Mon, Aug 17, 2020 at 12:18:43AM +0200, ?kos Uzonyi wrote: > > > > From: Uzonyi ?kos > > > > > > > > I made the requested changes, added more test cases to trie test, and fixed some > > > > trie bugs. > > > > > > > > The travis build [1] unfortunately shows some errors. On ppc mknod test fails, > > > > but I have no idea why. Mknod is unrelated to my code. Do you have any idea? > > > > > > Something is broken in their ppc system: apparently, they allow the mknod > > > syscall to exit without an error in cases where is must fail with EEXIST > > > because the target file already exists. This violates the contract: > > > "If pathname already exists, or is a symbolic link, this call fails with > > > an EEXIST error." I suppose they use some kind of mknod interception, > > > and it doesn't implement the expected semantics. > > > > > > We can either come up with a workaround or report a bug and let them fix it. > > > > What seems really strange is that only the last two mknod does not > > fail with EEXIST. > > Only the last two mknod calls are trying to create devices, > all the rest aren't. This looks like an error in some seccomp filter. > > > > > Also, pidns-cache fails on one arm build. I tried to increase the time > > > > available for translation, but it didn't help. > > > > > > Could you add some diagnostics to the test, e.g. how much time did it take > > > in the first and in the second case? This way we could see what's going > > > on. > > > > Here are the results: > > (no translation | translation with cache | translation without cache) > > > > the 3 arm builds: > > 17846us 76435us 3676880us > > 141378us 496301us 3379754us > > 8699us 134754us 2974909us > > > > on my system: > > 948us 9358us 916094us > > I wonder why the cached translation takes that long on your system: > 9358 / 948 ? 10 > > Would it make sense to increase SYSCALL_COUNT so that cache effect would > become more visible compared to the translation without cache? Also, if the first syscall takes more time to complete because it's not cached yet, would it help if it was excluded from the time measurement? -- ldv From uzonyi.akos at gmail.com Wed Aug 19 15:45:48 2020 From: uzonyi.akos at gmail.com (=?UTF-8?B?w4Frb3MgVXpvbnlp?=) Date: Wed, 19 Aug 2020 17:45:48 +0200 Subject: [RFC PATCH v9 0/8] [PIDNS] Final In-Reply-To: <20200819152643.GA1481@altlinux.org> References: <20200816221851.200031-1-uzonyi.akos@gmail.com> <20200817233850.GC5522@altlinux.org> <20200818230024.GA21969@altlinux.org> <20200819152643.GA1481@altlinux.org> Message-ID: On Wed, 19 Aug 2020 at 17:26, Dmitry V. Levin wrote: > On Wed, Aug 19, 2020 at 02:00:24AM +0300, Dmitry V. Levin wrote: > > On Wed, Aug 19, 2020 at 12:37:14AM +0200, ?kos Uzonyi wrote: > > > On Tue, 18 Aug 2020 at 01:38, Dmitry V. Levin wrote: > > > > On Mon, Aug 17, 2020 at 12:18:43AM +0200, ?kos Uzonyi wrote: > > > > > Also, pidns-cache fails on one arm build. I tried to increase the time > > > > > available for translation, but it didn't help. > > > > > > > > Could you add some diagnostics to the test, e.g. how much time did it take > > > > in the first and in the second case? This way we could see what's going > > > > on. > > > > > > Here are the results: > > > (no translation | translation with cache | translation without cache) > > > > > > the 3 arm builds: > > > 17846us 76435us 3676880us > > > 141378us 496301us 3379754us > > > 8699us 134754us 2974909us > > > > > > on my system: > > > 948us 9358us 916094us > > > > I wonder why the cached translation takes that long on your system: > > 9358 / 948 ? 10 Note that cached translation still requires a few syscalls, as we have to check if cache is still valid. > > Would it make sense to increase SYSCALL_COUNT so that cache effect would > > become more visible compared to the translation without cache? Using 1000 for SYSCALL_COUNT: arm: 113807us 613880us 66353us 274007us 71271us 146847us my system: 23076us 53473us s390x: 10762us 42090us These numbers seem less chaotic now :). Maybe we could try using 20 as the maximum ratio (it could be less, but I think it's better to have some false negatives, than false positives). What do you think? > Also, if the first syscall takes more time to complete because it's not > cached yet, would it help if it was excluded from the time measurement? It's already done: static long execute_syscalls(void) { /* Load our PID in the cache */ syscall(__NR_getpid); ... From ldv at altlinux.org Wed Aug 19 15:55:24 2020 From: ldv at altlinux.org (Dmitry V. Levin) Date: Wed, 19 Aug 2020 18:55:24 +0300 Subject: [RFC PATCH v9 0/8] [PIDNS] Final In-Reply-To: References: <20200816221851.200031-1-uzonyi.akos@gmail.com> <20200817233850.GC5522@altlinux.org> <20200818230024.GA21969@altlinux.org> <20200819152643.GA1481@altlinux.org> Message-ID: <20200819155523.GA1613@altlinux.org> On Wed, Aug 19, 2020 at 05:45:48PM +0200, ?kos Uzonyi wrote: > On Wed, 19 Aug 2020 at 17:26, Dmitry V. Levin wrote: > > On Wed, Aug 19, 2020 at 02:00:24AM +0300, Dmitry V. Levin wrote: > > > On Wed, Aug 19, 2020 at 12:37:14AM +0200, ?kos Uzonyi wrote: > > > > On Tue, 18 Aug 2020 at 01:38, Dmitry V. Levin wrote: > > > > > On Mon, Aug 17, 2020 at 12:18:43AM +0200, ?kos Uzonyi wrote: > > > > > > Also, pidns-cache fails on one arm build. I tried to increase the time > > > > > > available for translation, but it didn't help. > > > > > > > > > > Could you add some diagnostics to the test, e.g. how much time did it take > > > > > in the first and in the second case? This way we could see what's going > > > > > on. > > > > > > > > Here are the results: > > > > (no translation | translation with cache | translation without cache) > > > > > > > > the 3 arm builds: > > > > 17846us 76435us 3676880us > > > > 141378us 496301us 3379754us > > > > 8699us 134754us 2974909us > > > > > > > > on my system: > > > > 948us 9358us 916094us > > > > > > I wonder why the cached translation takes that long on your system: > > > 9358 / 948 ? 10 > > Note that cached translation still requires a few syscalls, as we have > to check if cache is still valid. What a pity! :) > > > Would it make sense to increase SYSCALL_COUNT so that cache effect would > > > become more visible compared to the translation without cache? > > Using 1000 for SYSCALL_COUNT: > arm: > 113807us 613880us > 66353us 274007us > 71271us 146847us > my system: > 23076us 53473us > s390x: > 10762us 42090us > > These numbers seem less chaotic now :). > > Maybe we could try using 20 as the maximum ratio (it could be less, > but I think it's better to have some false negatives, than false > positives). What do you think? Yes, I agree, let's try using 20. > > Also, if the first syscall takes more time to complete because it's not > > cached yet, would it help if it was excluded from the time measurement? > > It's already done: > > static long > execute_syscalls(void) > { > /* Load our PID in the cache */ > syscall(__NR_getpid); Indeed. -- ldv From uzonyi.akos at gmail.com Wed Aug 19 18:16:32 2020 From: uzonyi.akos at gmail.com (=?UTF-8?q?=C3=81kos=20Uzonyi?=) Date: Wed, 19 Aug 2020 20:16:32 +0200 Subject: [PATCH v10 0/5] [PIDNS] Final Message-ID: <20200819181637.1096507-1-uzonyi.akos@gmail.com> From: Uzonyi ?kos The SYSCALL_COUNT in pidns-cache test is 1000, and the max time ratio is 20. Now all tests pass in travis (except mknod on the buggy ppc). I renamed tests/trie.c to tests/trie_test.c, and added a symlink: tests/trie.c -> ../trie.c. In gettid test the gettid syscalls made by musl are sometimes unfinished/resumed, which is not filtered by uniq. So I filtered these out by grep. Changes in v10: - Use symlink for trie.c - Rename tests/trie.c -> tests/trie_test.c - pidns-cache test: use 20 as max ratio for execution times - Increase SYSCALL_COUNT to 1000 - Filter unfinished/resumed syscalls in gettid test. Changes in v9: - Add test for trie - Fix ns_id_size - Add tests for pidns cache - Skip pidns tests if /proc/self/ns/pid is not found - init.sh: add init_pid as a local variable - Remove kernel version checks (4.9) in pidns tests - tests/pidns.c: fix exit code of init process - tests/fcntl-common.c: initialize array during definition - tests/net-sockaddr.c: fix indentation - Fix description of some test scripts - Add tests for tkill, tgkill - Fix trie bugs: - When creating a data block, fill it with empty_value - Check calloc return value - Include config.h - Move some include from trie.c to trie.h - Fix trie_data_block_calc_pos when item_size_lg == 6 - Mask empty_value to fit item_size Changes in v8: - translate_pid: document return value; check !proc_pid first - NEWS: move to new section - get_proc_pid, printpid: fix comment - Check if translation failed Changes in v7: - Run uniq on gettid--pidns-translation test output - Add comment to printpid - translate_id: do not call get_our_ns if not necessary - Remove unnecessary parentheses - Fix commit message of last commit (s/-Y/--pidns-translation/) - get_proc_pid: remove unnecessary optimization - trie.c: remove #include - Add clarification to get_proc_pid's comment - Fix typos - trie.c: ptr_sz_lg use void* in sizeof - trie_get_node_size: fix comment - trie.c: remove "TODO: overflow" - ipc_shmctl.c: remove duplicate #include "print_field.h" Changes in v6: - Add function with documentation for creating tries - Do not use -1ULL as error indicator in tcb.pid_ns - Use unsigned int (instead of uint64_t) for NS IDs - Add constant for NS ID size. - Modify get_proc_pid a bit - Die if trie creation fails Changes in v5: - Squash "Use printpid in *" commits - Makefile.am: move adding getpid.c to "Use printpid in decoders" - Remove pid_ns_inited field from struct tcb - strace.1.in: remove -Y flag - Use tprints instead of tprintf where possible - Make some global variables static - pidns_init: remove "inited" bool variable - Make printpid_translation static - tests/pidns.c: refactor a bit - check_ns_ioctl: fix error msg - defs.h: Move adding get_proc_pid to "PID namespace translation support" - Remove tcp paramter name from declarations - Update printfd_pid_tracee_ns documentation - Use named constants for trie_create arguments - Add documentation comments - Add printpid_tgid_pgid function - Delete get_pid_max function; use global variables instead - Refactor trie: - Move key_size argument - Remove support for TRIE_SET - Merge trie_create, trie_init, trie_check functions - trie_free_node: make static, fix "node" argument type - Add max_depth field - Reorder functions - Extract common parts of trie_get, trie_set Changes in v4: - Skip tests if NS_* ioctl commands are not supported - Improve documentation in pidns.h - Use pipe for init process termination (instead of SIGKILL) - Add PIDNS_TEST_INIT macro - Remove "ifdef __NR_gettid" - Fix fork--pidns-tranlsation.test: skip if unshare fails with EPERM - Use debug message instead of normal message in some cases - Rename some labels - Rewrite get_ns function - Remove O_NONBLOCK from open(/proc//ns/pid) Changes in v3: - Split accidentally sqashed last commit - Undo modification of tests/pidfd_send_signal.c - Rename kcmp-yY test to kcmp-y--pidns-translation - Skip tests if unshare fails with EPERM - Fix buffer size in pidns_pid2str - Use largefile_wrappers.h macros - Return early if from_ns or our_ns is 0 - Do not call ioctl(NS_GET_PARENT) again, if first failed with ENOTTY - Skip pidns tests if Linux kernel version < 4.9 - Use smaller trie nodes in pidns.c - Remove race condition from fork--pidns-translation test - Move "key_size" to center in trie description - Use PT_TID (not PT_TGID) when translating tcp->pid - Fix get_ns_hierarchy and get_id_list functions - Fix migrate_pages test if syscall succeds - Fix filtering in ioctl_block--pidns-translation.test - Fix -a flag value in xetpriority test Changes in v2: - Add missing header files to Makefile - Fix pointer-to-int-cast errors - Fix unused-result errors - Use perror_msg instead of perror_func_msg where appropriate - Remove tcb parameter of read_int_from_file - Use xsprintf instead of snprintf - Refactor get_pid_max, get_ns_hierarchy, get_id_list functions - Remove -Y flag - Improve documentation of trie - Fix printing of f_owner_ex struct - Use printpid for F_GETOWN, F_SETOWN fcntl command arguments - Use printpid for shmid_ds.shm_cpid, shmid_ds.shm_clid - Call pidns_init before parsing arguments ?kos Uzonyi (5): PID namespace translation support Use printpid in decoders Use get_proc_pid for /proc paths Implement testing framework for pidns Add tests for PID namespace translation Makefile.am | 4 + NEWS | 1 + affinity.c | 6 +- block.c | 2 +- bpf.c | 2 +- capability.c | 4 +- clone.c | 14 +- defs.h | 61 +- fcntl.c | 24 +- get_robust_list.c | 3 +- getpid.c | 46 ++ ioprio.c | 26 +- ipc_shmctl.c | 4 +- kcmp.c | 5 +- largefile_wrappers.h | 2 + linux/dummy.h | 8 +- mmap_cache.c | 2 +- msghdr.c | 2 +- net.c | 2 +- netlink.c | 5 +- numa.c | 6 +- pathtrace.c | 7 +- pidfd_open.c | 2 +- pidns.c | 604 ++++++++++++++++++ print_fields.h | 24 + printsiginfo.c | 2 +- process.c | 3 +- process_vm.c | 6 +- resource.c | 27 +- sched.c | 25 +- signal.c | 21 +- sockaddr.c | 2 +- strace.1.in | 4 + strace.c | 11 +- syscall.c | 15 + tests/.gitignore | 35 + tests/Makefile.am | 44 ++ tests/fcntl--pidns-translation.c | 2 + tests/fcntl-common.c | 78 ++- tests/fcntl.c | 1 + tests/fcntl64--pidns-translation.c | 2 + tests/fcntl64.c | 3 + tests/fork--pidns-translation.awk | 15 + tests/fork--pidns-translation.c | 69 ++ tests/fork--pidns-translation.test | 14 + tests/gen_tests.in | 32 +- tests/getpgrp--pidns-translation.c | 2 + tests/getpgrp.c | 8 +- tests/getpid--pidns-translation.c | 2 + tests/getpid.c | 8 +- tests/getsid--pidns-translation.c | 2 + tests/getsid.c | 9 +- tests/gettid--pidns-translation.c | 2 + tests/gettid--pidns-translation.test | 18 + tests/gettid.c | 8 +- tests/init.sh | 29 + tests/ioctl_block--pidns-translation.c | 2 + tests/ioctl_block--pidns-translation.test | 22 + tests/ioctl_block.c | 24 +- tests/ioprio--pidns-translation.c | 2 + tests/ioprio.c | 54 +- tests/kcmp-y--pidns-translation.c | 2 + tests/kcmp.c | 36 +- tests/kill--pidns-translation.c | 2 + tests/kill.c | 12 +- tests/migrate_pages--pidns-translation.c | 2 + tests/migrate_pages.c | 17 +- tests/move_pages--pidns-translation.c | 2 + tests/move_pages.c | 51 +- tests/net-sockaddr--pidns-translation.c | 2 + tests/net-sockaddr.c | 60 +- tests/netlink_audit--pidns-translation.c | 2 + tests/netlink_audit--pidns-translation.test | 13 + tests/netlink_audit.c | 11 +- tests/pidfd_open--pidns-translation.c | 2 + tests/pidfd_open.c | 21 +- tests/pidfd_send_signal--pidns-translation.c | 2 + tests/pidfd_send_signal.c | 13 +- tests/pidns-cache.c | 62 ++ tests/pidns-cache.test | 16 + tests/pidns.c | 229 +++++++ tests/pidns.h | 56 ++ tests/prlimit64--pidns-translation.c | 2 + tests/prlimit64.c | 17 +- tests/process_vm_readv--pidns-translation.c | 2 + tests/process_vm_readv_writev.c | 27 +- tests/process_vm_writev--pidns-translation.c | 2 + tests/rt_sigqueueinfo--pidns-translation.c | 2 + tests/rt_sigqueueinfo.c | 15 +- tests/rt_tgsigqueueinfo--pidns-translation.c | 2 + tests/rt_tgsigqueueinfo.c | 26 +- tests/sched_xetaffinity--pidns-translation.c | 2 + tests/sched_xetaffinity.c | 31 +- tests/sched_xetattr--pidns-translation.c | 2 + tests/sched_xetattr.c | 47 +- tests/sched_xetparam--pidns-translation.c | 2 + tests/sched_xetparam.c | 20 +- tests/sched_xetscheduler--pidns-translation.c | 2 + tests/sched_xetscheduler.c | 44 +- tests/signal_receive--pidns-translation.c | 2 + tests/signal_receive.c | 22 +- tests/so_peercred--pidns-translation.c | 2 + tests/so_peercred.c | 22 + tests/tgkill--pidns-translation.c | 2 + tests/tgkill.c | 51 +- tests/tkill--pidns-translation.c | 2 + tests/tkill.c | 19 +- tests/trie.c | 1 + tests/trie_test.c | 77 +++ tests/xet_robust_list--pidns-translation.c | 2 + tests/xet_robust_list.c | 18 +- tests/xetpgid--pidns-translation.c | 2 + tests/xetpgid.c | 21 +- tests/xetpriority--pidns-translation.c | 2 + tests/xetpriority.c | 20 +- trie.c | 290 +++++++++ trie.h | 92 +++ util.c | 31 +- wait.c | 36 +- 119 files changed, 2767 insertions(+), 274 deletions(-) create mode 100644 getpid.c create mode 100644 pidns.c create mode 100644 tests/fcntl--pidns-translation.c create mode 100644 tests/fcntl64--pidns-translation.c create mode 100644 tests/fork--pidns-translation.awk create mode 100644 tests/fork--pidns-translation.c create mode 100755 tests/fork--pidns-translation.test create mode 100644 tests/getpgrp--pidns-translation.c create mode 100644 tests/getpid--pidns-translation.c create mode 100644 tests/getsid--pidns-translation.c create mode 100644 tests/gettid--pidns-translation.c create mode 100755 tests/gettid--pidns-translation.test create mode 100644 tests/ioctl_block--pidns-translation.c create mode 100755 tests/ioctl_block--pidns-translation.test create mode 100644 tests/ioprio--pidns-translation.c create mode 100644 tests/kcmp-y--pidns-translation.c create mode 100644 tests/kill--pidns-translation.c create mode 100644 tests/migrate_pages--pidns-translation.c create mode 100644 tests/move_pages--pidns-translation.c create mode 100644 tests/net-sockaddr--pidns-translation.c create mode 100644 tests/netlink_audit--pidns-translation.c create mode 100755 tests/netlink_audit--pidns-translation.test create mode 100644 tests/pidfd_open--pidns-translation.c create mode 100644 tests/pidfd_send_signal--pidns-translation.c create mode 100644 tests/pidns-cache.c create mode 100755 tests/pidns-cache.test create mode 100644 tests/pidns.c create mode 100644 tests/pidns.h create mode 100644 tests/prlimit64--pidns-translation.c create mode 100644 tests/process_vm_readv--pidns-translation.c create mode 100644 tests/process_vm_writev--pidns-translation.c create mode 100644 tests/rt_sigqueueinfo--pidns-translation.c create mode 100644 tests/rt_tgsigqueueinfo--pidns-translation.c create mode 100644 tests/sched_xetaffinity--pidns-translation.c create mode 100644 tests/sched_xetattr--pidns-translation.c create mode 100644 tests/sched_xetparam--pidns-translation.c create mode 100644 tests/sched_xetscheduler--pidns-translation.c create mode 100644 tests/signal_receive--pidns-translation.c create mode 100644 tests/so_peercred--pidns-translation.c create mode 100644 tests/tgkill--pidns-translation.c create mode 100644 tests/tkill--pidns-translation.c create mode 120000 tests/trie.c create mode 100644 tests/trie_test.c create mode 100644 tests/xet_robust_list--pidns-translation.c create mode 100644 tests/xetpgid--pidns-translation.c create mode 100644 tests/xetpriority--pidns-translation.c create mode 100644 trie.c create mode 100644 trie.h -- 2.28.0 From uzonyi.akos at gmail.com Wed Aug 19 18:16:34 2020 From: uzonyi.akos at gmail.com (=?UTF-8?q?=C3=81kos=20Uzonyi?=) Date: Wed, 19 Aug 2020 20:16:34 +0200 Subject: [PATCH v10 2/5] Use printpid in decoders In-Reply-To: <20200819181637.1096507-1-uzonyi.akos@gmail.com> References: <20200819181637.1096507-1-uzonyi.akos@gmail.com> Message-ID: <20200819181637.1096507-3-uzonyi.akos@gmail.com> * getpid.c: New file. * Makefile.am (libstrace_a_SOURCES): Add it. * linux/dummy.h (sys_getpid, sys_getppid, sys_gettid, sys_setpgid, sys_setpgrp): Remove. * util.c (printfd_pid_tracee_ns): Implement using translate_pid. * defs.h (printnum_pid): New function definition. (printfd_pid_tracee_ns): Update documentation * util.c: (printnum_pid): New function. * print_fields.h (PRINT_FIELD_TID): New macro. (PRINT_FIELD_TGID): Likewise. (PRINT_FIELD_PGID): Likewise. (PRINT_FIELD_SID): Likewise. * affinity.c: Print PIDs with printpid. * block.c: Likewise. * bpf.c: Likewise. * capability.c: Likewise. * clone.c: Likewise. * fcntl.c: Likewise. * get_robust_list.c: Likewise. * ioprio.c: Likewise. * kcmp.c: Likewise. * msghdr.c: Likewise. * net.c: Likewise. * netlink.c: Likewise. * numa.c: Likewise. * pidfd_open.c: Likewise. * printsiginfo.c: Likewise. * process.c: Likewise. * process_vm.c: Likewise. * resource.c: Likewise. * sched.c: Likewise. * signal.c: Likewise. * sockaddr.c: Likewise. * wait.c: Likewise. * kcmp.c (SYS_FUNC(kcmp)): Fix KCMP_FILE pid arguments. * tests/kcmp.c (printpidfd): Print path if VERBOSE_FD. (main): Use our real pid if real fds are used. --- Makefile.am | 1 + affinity.c | 6 ++++-- block.c | 2 +- bpf.c | 2 +- capability.c | 4 +++- clone.c | 14 +++++++------- defs.h | 5 ++++- fcntl.c | 24 ++++++++++++++++++++++-- get_robust_list.c | 3 ++- getpid.c | 46 ++++++++++++++++++++++++++++++++++++++++++++++ ioprio.c | 26 ++++++++++++++++++++++---- ipc_shmctl.c | 4 ++-- kcmp.c | 5 ++++- linux/dummy.h | 8 +------- msghdr.c | 2 +- net.c | 2 +- netlink.c | 5 +++-- numa.c | 6 ++++-- pidfd_open.c | 2 +- print_fields.h | 24 ++++++++++++++++++++++++ printsiginfo.c | 2 +- process.c | 3 ++- process_vm.c | 6 ++++-- resource.c | 27 ++++++++++++++++++++++++--- sched.c | 25 ++++++++++++++++--------- signal.c | 21 +++++++++++++++------ sockaddr.c | 2 +- tests/kcmp.c | 25 ++++++++++++++++++++++--- util.c | 22 +++++++++++++++------- wait.c | 36 ++++++++++++++++++++++++------------ 30 files changed, 278 insertions(+), 82 deletions(-) create mode 100644 getpid.c diff --git a/Makefile.am b/Makefile.am index 73c22035..15fcd9a6 100644 --- a/Makefile.am +++ b/Makefile.am @@ -135,6 +135,7 @@ libstrace_a_SOURCES = \ getcpu.c \ getcwd.c \ getpagesize.c \ + getpid.c \ getrandom.c \ hdio.c \ hostname.c \ diff --git a/affinity.c b/affinity.c index eb3158b7..f9893adb 100644 --- a/affinity.c +++ b/affinity.c @@ -82,7 +82,8 @@ SYS_FUNC(sched_setaffinity) const int pid = tcp->u_arg[0]; const unsigned int len = tcp->u_arg[1]; - tprintf("%d, %u, ", pid, len); + printpid(tcp, pid, PT_TGID); + tprintf(", %u, ", len); print_affinitylist(tcp, tcp->u_arg[2], len); return RVAL_DECODED; @@ -94,7 +95,8 @@ SYS_FUNC(sched_getaffinity) const unsigned int len = tcp->u_arg[1]; if (entering(tcp)) { - tprintf("%d, %u, ", pid, len); + printpid(tcp, pid, PT_TGID); + tprintf(", %u, ", len); } else { print_affinitylist(tcp, tcp->u_arg[2], tcp->u_rval); } diff --git a/block.c b/block.c index b527ef43..783a4b5a 100644 --- a/block.c +++ b/block.c @@ -179,7 +179,7 @@ MPERS_PRINTER_DECL(int, block_ioctl, struct tcb *const tcp, PRINT_FIELD_U(", ", buts, buf_nr); PRINT_FIELD_U(", ", buts, start_lba); PRINT_FIELD_U(", ", buts, end_lba); - PRINT_FIELD_D(", ", buts, pid); + PRINT_FIELD_TGID(", ", buts, pid, tcp); return 0; } else { struct_blk_user_trace_setup buts; diff --git a/bpf.c b/bpf.c index af830053..0ec33ba4 100644 --- a/bpf.c +++ b/bpf.c @@ -927,7 +927,7 @@ BEGIN_BPF_CMD_DECODER(BPF_TASK_FD_QUERY) if (entering(tcp)) { set_tcb_priv_ulong(tcp, attr.buf_len); - PRINT_FIELD_D("{task_fd_query={", attr, pid); + PRINT_FIELD_TGID("{task_fd_query={", attr, pid, tcp); PRINT_FIELD_FD(", ", attr, fd, tcp); PRINT_FIELD_U(", ", attr, flags); PRINT_FIELD_U(", ", attr, buf_len); diff --git a/capability.c b/capability.c index 0e763ee1..812fb435 100644 --- a/capability.c +++ b/capability.c @@ -70,7 +70,9 @@ print_cap_header(struct tcb *const tcp, const kernel_ulong_t addr, tprints("{version="); printxval(cap_version, h->version, "_LINUX_CAPABILITY_VERSION_???"); - tprintf(", pid=%d}", h->pid); + tprints(", pid="); + printpid(tcp, h->pid, PT_TGID); + tprints("}"); } static void diff --git a/clone.c b/clone.c index 487c5c23..45f24065 100644 --- a/clone.c +++ b/clone.c @@ -114,14 +114,14 @@ SYS_FUNC(clone) */ if ((flags & (CLONE_PARENT_SETTID|CLONE_PIDFD|CLONE_CHILD_SETTID |CLONE_CHILD_CLEARTID|CLONE_SETTLS)) == 0) - return RVAL_DECODED; + return RVAL_DECODED | RVAL_TID; } else { if (flags & (CLONE_PARENT_SETTID|CLONE_PIDFD)) { kernel_ulong_t addr = tcp->u_arg[ARG_PTID]; tprints(", parent_tid="); if (flags & CLONE_PARENT_SETTID) - printnum_int(tcp, addr, "%u"); + printnum_pid(tcp, addr, PT_TID); else printnum_fd(tcp, addr); } @@ -134,7 +134,7 @@ SYS_FUNC(clone) printaddr(tcp->u_arg[ARG_CTID]); } } - return 0; + return RVAL_TID; } @@ -229,7 +229,7 @@ SYS_FUNC(clone3) if ((arg.flags & (CLONE_PIDFD | CLONE_PARENT_SETTID)) || (size > fetch_size)) - return 0; + return RVAL_TID; goto out; } @@ -256,7 +256,7 @@ SYS_FUNC(clone3) if (arg.flags & CLONE_PARENT_SETTID) { tprintf("%sparent_tid=", pfx); - printnum_int(tcp, arg.parent_tid, "%d"); /* TID */ + printnum_pid(tcp, arg.parent_tid, PT_TID); pfx = ", "; } @@ -279,7 +279,7 @@ SYS_FUNC(clone3) out: tprintf(", %" PRI_klu, size); - return RVAL_DECODED; + return RVAL_DECODED | RVAL_TID; } @@ -300,5 +300,5 @@ SYS_FUNC(unshare) SYS_FUNC(fork) { - return RVAL_DECODED; + return RVAL_DECODED | RVAL_TGID; } diff --git a/defs.h b/defs.h index 511a92a2..328c1940 100644 --- a/defs.h +++ b/defs.h @@ -1100,7 +1100,7 @@ printfd(struct tcb *tcp, int fd) /** * Print file descriptor fd owned by process with ID pid (from the PID NS - * of the tracee the descriptor tcp). This is a stub. + * of the tracee). */ extern void printfd_pid_tracee_ns(struct tcb *tcp, pid_t pid, int fd); @@ -1561,6 +1561,9 @@ DECL_PRINTNUM_ADDR(int64); extern bool printnum_fd(struct tcb *, kernel_ulong_t addr); +extern bool +printnum_pid(struct tcb *const tcp, const kernel_ulong_t addr, enum pid_type type); + static inline bool printnum_slong(struct tcb *tcp, kernel_ulong_t addr) { diff --git a/fcntl.c b/fcntl.c index 6fcd5dac..5c630a06 100644 --- a/fcntl.c +++ b/fcntl.c @@ -28,7 +28,7 @@ print_struct_flock64(struct tcb *const tcp, const struct_kernel_flock64 *fl, con PRINT_FIELD_D(", ", *fl, l_start); PRINT_FIELD_D(", ", *fl, l_len); if (getlk) - PRINT_FIELD_D(", ", *fl, l_pid); + PRINT_FIELD_TGID(", ", *fl, l_pid, tcp); tprints("}"); } @@ -59,7 +59,22 @@ print_f_owner_ex(struct tcb *const tcp, const kernel_ulong_t addr) return; PRINT_FIELD_XVAL("{", owner, type, f_owner_types, "F_OWNER_???"); - PRINT_FIELD_D(", ", owner, pid); + + enum pid_type pid_type = PT_NONE; + switch (owner.type) + { + case F_OWNER_TID: + pid_type = PT_TID; + break; + case F_OWNER_PID: + pid_type = PT_TGID; + break; + case F_OWNER_PGRP: + pid_type = PT_PGID; + break; + } + tprints(", pid="); + printpid(tcp, owner.pid, pid_type); tprints("}"); } @@ -74,6 +89,9 @@ print_fcntl(struct tcb *tcp) printflags(fdflags, tcp->u_arg[2], "FD_???"); break; case F_SETOWN: + tprints(", "); + printpid_tgid_pgid(tcp, tcp->u_arg[2]); + break; case F_SETPIPE_SZ: tprintf(", %" PRI_kld, tcp->u_arg[2]); break; @@ -116,6 +134,8 @@ print_fcntl(struct tcb *tcp) printsignal(tcp->u_arg[2]); break; case F_GETOWN: + return RVAL_DECODED | + ((int) tcp->u_rval < 0 ? RVAL_PGID : RVAL_TGID); case F_GETPIPE_SZ: break; case F_GETFD: diff --git a/get_robust_list.c b/get_robust_list.c index b5aebaff..81aba2dd 100644 --- a/get_robust_list.c +++ b/get_robust_list.c @@ -10,7 +10,8 @@ SYS_FUNC(get_robust_list) { if (entering(tcp)) { - tprintf("%d, ", (int) tcp->u_arg[0]); + printpid(tcp, tcp->u_arg[0], PT_TID); + tprints(", "); } else { printnum_ptr(tcp, tcp->u_arg[1]); tprints(", "); diff --git a/getpid.c b/getpid.c new file mode 100644 index 00000000..5e9a1a29 --- /dev/null +++ b/getpid.c @@ -0,0 +1,46 @@ +/* + * Copyright (c) 2020 ?kos Uzonyi + * All rights reserved. + * + * SPDX-License-Identifier: LGPL-2.1-or-later + */ + +#include "defs.h" + +SYS_FUNC(getpid) +{ + return RVAL_DECODED | RVAL_TGID; +} + +SYS_FUNC(gettid) +{ + return RVAL_DECODED | RVAL_TID; +} + +SYS_FUNC(getpgrp) +{ + return RVAL_DECODED | RVAL_PGID; +} + +SYS_FUNC(getpgid) +{ + printpid(tcp, tcp->u_arg[0], PT_TGID); + + return RVAL_DECODED | RVAL_PGID; +} + +SYS_FUNC(getsid) +{ + printpid(tcp, tcp->u_arg[0], PT_TGID); + + return RVAL_DECODED | RVAL_SID; +} + +SYS_FUNC(setpgid) +{ + printpid(tcp, tcp->u_arg[0], PT_TGID); + tprints(", "); + printpid(tcp, tcp->u_arg[1], PT_PGID); + + return RVAL_DECODED; +} diff --git a/ioprio.c b/ioprio.c index 873c8ce5..149ef3fd 100644 --- a/ioprio.c +++ b/ioprio.c @@ -49,13 +49,30 @@ print_ioprio(unsigned int ioprio) ? tprints_comment : tprints)(str); } +static void +ioprio_print_who(struct tcb *tcp, int which, int who) +{ + switch (which) + { + case IOPRIO_WHO_PROCESS: + printpid(tcp, who, PT_TGID); + break; + case IOPRIO_WHO_PGRP: + printpid(tcp, who, PT_PGID); + break; + default: + tprintf("%d", who); + break; + } +} + SYS_FUNC(ioprio_get) { if (entering(tcp)) { /* int which */ printxval(ioprio_who, tcp->u_arg[0], "IOPRIO_WHO_???"); - /* int who */ - tprintf(", %d", (int) tcp->u_arg[1]); + tprints(", "); + ioprio_print_who(tcp, tcp->u_arg[0], tcp->u_arg[1]); return 0; } else { if (syserror(tcp)) @@ -72,8 +89,9 @@ SYS_FUNC(ioprio_set) { /* int which */ printxval(ioprio_who, tcp->u_arg[0], "IOPRIO_WHO_???"); - /* int who */ - tprintf(", %d, ", (int) tcp->u_arg[1]); + tprints(", "); + ioprio_print_who(tcp, tcp->u_arg[0], tcp->u_arg[1]); + tprints(", "); /* int ioprio */ if (xlat_verbose(xlat_verbosity) != XLAT_STYLE_ABBREV) tprintf("%d", (int) tcp->u_arg[2]); diff --git a/ipc_shmctl.c b/ipc_shmctl.c index 8c9e1e7a..1f99f02a 100644 --- a/ipc_shmctl.c +++ b/ipc_shmctl.c @@ -53,8 +53,8 @@ print_shmid_ds(struct tcb *const tcp, const kernel_ulong_t addr, int cmd) PRINT_FIELD_UID(", ", shmid_ds.shm_perm, cgid); tprints("}"); tprintf(", shm_segsz=%u", (unsigned) shmid_ds.shm_segsz); - PRINT_FIELD_D(", ", shmid_ds, shm_cpid); - PRINT_FIELD_D(", ", shmid_ds, shm_lpid); + PRINT_FIELD_TGID(", ", shmid_ds, shm_cpid, tcp); + PRINT_FIELD_TGID(", ", shmid_ds, shm_lpid, tcp); tprintf(", shm_nattch=%u", (unsigned) shmid_ds.shm_nattch); tprintf(", shm_atime=%u", (unsigned) shmid_ds.shm_atime); tprintf(", shm_dtime=%u", (unsigned) shmid_ds.shm_dtime); diff --git a/kcmp.c b/kcmp.c index 62115555..a5e1cdce 100644 --- a/kcmp.c +++ b/kcmp.c @@ -30,7 +30,10 @@ SYS_FUNC(kcmp) kernel_ulong_t idx1 = tcp->u_arg[3]; kernel_ulong_t idx2 = tcp->u_arg[4]; - tprintf("%d, %d, ", pid1, pid2); + printpid(tcp, pid1, PT_TGID); + tprints(", "); + printpid(tcp, pid2, PT_TGID); + tprints(", "); printxval(kcmp_types, type, "KCMP_???"); switch (type) { diff --git a/linux/dummy.h b/linux/dummy.h index 2f859a60..ca0d2f0c 100644 --- a/linux/dummy.h +++ b/linux/dummy.h @@ -53,6 +53,7 @@ # define sys_getgid sys_getuid # define sys_getgid16 sys_getuid16 # define sys_getpeername sys_getsockname +# define sys_getppid sys_getpid # define sys_getresgid sys_getresuid # define sys_getresgid16 sys_getresuid16 # define sys_lstat sys_stat @@ -87,10 +88,6 @@ # define sys_vfork sys_fork /* printargs does the right thing */ -# define sys_getpgrp printargs -# define sys_getpid printargs -# define sys_getppid printargs -# define sys_gettid printargs # define sys_idle printargs # define sys_munlockall printargs # define sys_pause printargs @@ -108,10 +105,7 @@ /* printargs_d does the right thing */ # define sys_exit printargs_d -# define sys_getpgid printargs_d -# define sys_getsid printargs_d # define sys_nice printargs_d -# define sys_setpgid printargs_d # define sys_setpgrp printargs_d # define sys_timer_delete printargs_d # define sys_timer_getoverrun printargs_d diff --git a/msghdr.c b/msghdr.c index ef6dc24b..170b8e51 100644 --- a/msghdr.c +++ b/msghdr.c @@ -69,7 +69,7 @@ print_scm_creds(struct tcb *tcp, const void *cmsg_data, { const struct ucred *uc = cmsg_data; - PRINT_FIELD_D("{", *uc, pid); + PRINT_FIELD_TGID("{", *uc, pid, tcp); PRINT_FIELD_UID(", ", *uc, uid); PRINT_FIELD_UID(", ", *uc, gid); tprints("}"); diff --git a/net.c b/net.c index fa4638e7..2099f0ac 100644 --- a/net.c +++ b/net.c @@ -601,7 +601,7 @@ print_get_ucred(struct tcb *const tcp, const kernel_ulong_t addr, if (umoven_or_printaddr(tcp, addr, len, &uc)) return; - PRINT_FIELD_LEN("{", uc, pid, len, PRINT_FIELD_D); + PRINT_FIELD_LEN("{", uc, pid, len, PRINT_FIELD_TGID, tcp); PRINT_FIELD_LEN(", ", uc, uid, len, PRINT_FIELD_UID); PRINT_FIELD_LEN(", ", uc, gid, len, PRINT_FIELD_UID); tprints("}"); diff --git a/netlink.c b/netlink.c index 88d864a9..cb29033a 100644 --- a/netlink.c +++ b/netlink.c @@ -446,8 +446,9 @@ print_nlmsghdr(struct tcb *tcp, decode_nlmsg_flags(nlmsghdr->nlmsg_flags, nlmsghdr->nlmsg_type, family); - tprintf(", seq=%u, pid=%d}", nlmsghdr->nlmsg_seq, - nlmsghdr->nlmsg_pid); + tprintf(", seq=%u, pid=", nlmsghdr->nlmsg_seq); + printpid(tcp, nlmsghdr->nlmsg_pid, PT_TGID); + tprints("}"); } static bool diff --git a/numa.c b/numa.c index cc7a7cc6..f7a58266 100644 --- a/numa.c +++ b/numa.c @@ -44,7 +44,8 @@ print_nodemask(struct tcb *const tcp, const kernel_ulong_t addr, SYS_FUNC(migrate_pages) { - tprintf("%d, %" PRI_klu ", ", (int) tcp->u_arg[0], tcp->u_arg[1]); + printpid(tcp, tcp->u_arg[0], PT_TGID); + tprintf(", %" PRI_klu ", ", tcp->u_arg[1]); print_nodemask(tcp, tcp->u_arg[2], tcp->u_arg[1]); tprints(", "); print_nodemask(tcp, tcp->u_arg[3], tcp->u_arg[1]); @@ -170,7 +171,8 @@ SYS_FUNC(move_pages) kernel_ulong_t buf; if (entering(tcp)) { - tprintf("%d, %" PRI_klu ", ", (int) tcp->u_arg[0], npages); + printpid(tcp, tcp->u_arg[0], PT_TGID); + tprintf(", %" PRI_klu ", ", npages); print_array(tcp, tcp->u_arg[2], npages, &buf, current_wordsize, tfetch_mem, print_addr, 0); tprints(", "); diff --git a/pidfd_open.c b/pidfd_open.c index bbc7f617..cf05a110 100644 --- a/pidfd_open.c +++ b/pidfd_open.c @@ -10,7 +10,7 @@ SYS_FUNC(pidfd_open) { /* pid_t pid */ - tprintf("%d", (int) tcp->u_arg[0]); + printpid(tcp, tcp->u_arg[0], PT_TGID); /* unsigned int flags */ tprintf(", %#x", (unsigned int) tcp->u_arg[1]); diff --git a/print_fields.h b/print_fields.h index f9714115..33d4a458 100644 --- a/print_fields.h +++ b/print_fields.h @@ -263,6 +263,30 @@ printfd((tcp_), (where_).field_); \ } while (0) +# define PRINT_FIELD_TID(prefix_, where_, field_, tcp_) \ + do { \ + STRACE_PRINTF("%s%s=", (prefix_), #field_); \ + printpid((tcp_), (where_).field_, PT_TID); \ + } while (0) + +# define PRINT_FIELD_TGID(prefix_, where_, field_, tcp_) \ + do { \ + STRACE_PRINTF("%s%s=", (prefix_), #field_); \ + printpid((tcp_), (where_).field_, PT_TGID); \ + } while (0) + +# define PRINT_FIELD_PGID(prefix_, where_, field_, tcp_) \ + do { \ + STRACE_PRINTF("%s%s=", (prefix_), #field_); \ + printpid((tcp_), (where_).field_, PT_PGID); \ + } while (0) + +# define PRINT_FIELD_SID(prefix_, where_, field_, tcp_) \ + do { \ + STRACE_PRINTF("%s%s=", (prefix_), #field_); \ + printpid((tcp_), (where_).field_, PT_SID); \ + } while (0) + # define PRINT_FIELD_STRN(prefix_, where_, field_, len_, tcp_) \ do { \ STRACE_PRINTF("%s%s=", (prefix_), #field_); \ diff --git a/printsiginfo.c b/printsiginfo.c index 8ed1e7ba..cb4cde4a 100644 --- a/printsiginfo.c +++ b/printsiginfo.c @@ -58,7 +58,7 @@ static void printsigsource(struct tcb *tcp, const siginfo_t *sip) { - PRINT_FIELD_D(", ", *sip, si_pid); + PRINT_FIELD_TGID(", ", *sip, si_pid, tcp); PRINT_FIELD_UID(", ", *sip, si_uid); } diff --git a/process.c b/process.c index a98c304e..d6ff255d 100644 --- a/process.c +++ b/process.c @@ -92,7 +92,8 @@ SYS_FUNC(ptrace) } /* pid */ - tprintf(", %d", pid); + tprints(", "); + printpid(tcp, pid, PT_TGID); /* addr */ switch (request) { diff --git a/process_vm.c b/process_vm.c index abee1e68..81d9b0f4 100644 --- a/process_vm.c +++ b/process_vm.c @@ -13,7 +13,8 @@ SYS_FUNC(process_vm_readv) { if (entering(tcp)) { /* arg 1: pid */ - tprintf("%d, ", (int) tcp->u_arg[0]); + printpid(tcp, tcp->u_arg[0], PT_TGID); + tprints(", "); } else { kernel_ulong_t local_iovcnt = tcp->u_arg[2]; kernel_ulong_t remote_iovcnt = tcp->u_arg[4]; @@ -42,7 +43,8 @@ SYS_FUNC(process_vm_writev) kernel_ulong_t flags = tcp->u_arg[5]; /* arg 1: pid */ - tprintf("%d, ", (int) tcp->u_arg[0]); + printpid(tcp, tcp->u_arg[0], PT_TGID); + tprints(", "); /* arg 2: local iov */ tprint_iov(tcp, local_iovcnt, tcp->u_arg[1], IOV_DECODE_STR); /* arg 3: local iovcnt */ diff --git a/resource.c b/resource.c index 53192ee9..070f4740 100644 --- a/resource.c +++ b/resource.c @@ -142,7 +142,8 @@ SYS_FUNC(setrlimit) SYS_FUNC(prlimit64) { if (entering(tcp)) { - tprintf("%d, ", (int) tcp->u_arg[0]); + printpid(tcp, tcp->u_arg[0], PT_TGID); + tprints(", "); printxval(resources, tcp->u_arg[1], "RLIMIT_???"); tprints(", "); print_rlimit64(tcp, tcp->u_arg[2]); @@ -179,10 +180,28 @@ SYS_FUNC(osf_getrusage) #include "xlat/priorities.h" +static void +priority_print_who(struct tcb *tcp, int which, int who) +{ + switch (which) + { + case PRIO_PROCESS: + printpid(tcp, who, PT_TGID); + break; + case PRIO_PGRP: + printpid(tcp, who, PT_PGID); + break; + default: + tprintf("%d", who); + break; + } +} + SYS_FUNC(getpriority) { printxval(priorities, tcp->u_arg[0], "PRIO_???"); - tprintf(", %d", (int) tcp->u_arg[1]); + tprints(", "); + priority_print_who(tcp, tcp->u_arg[0], tcp->u_arg[1]); return RVAL_DECODED; } @@ -190,7 +209,9 @@ SYS_FUNC(getpriority) SYS_FUNC(setpriority) { printxval(priorities, tcp->u_arg[0], "PRIO_???"); - tprintf(", %d, %d", (int) tcp->u_arg[1], (int) tcp->u_arg[2]); + tprints(", "); + priority_print_who(tcp, tcp->u_arg[0], tcp->u_arg[1]); + tprintf(", %d", (int) tcp->u_arg[2]); return RVAL_DECODED; } diff --git a/sched.c b/sched.c index 788ef39b..ff427e48 100644 --- a/sched.c +++ b/sched.c @@ -21,7 +21,7 @@ SYS_FUNC(sched_getscheduler) { if (entering(tcp)) { - tprintf("%d", (int) tcp->u_arg[0]); + printpid(tcp, tcp->u_arg[0], PT_TGID); } else if (!syserror(tcp)) { tcp->auxstr = xlookup(schedulers, (kernel_ulong_t) tcp->u_rval); return RVAL_STR; @@ -31,7 +31,8 @@ SYS_FUNC(sched_getscheduler) SYS_FUNC(sched_setscheduler) { - tprintf("%d, ", (int) tcp->u_arg[0]); + printpid(tcp, tcp->u_arg[0], PT_TGID); + tprints(", "); printxval(schedulers, tcp->u_arg[1], "SCHED_???"); tprints(", "); printnum_int(tcp, tcp->u_arg[2], "%d"); @@ -41,16 +42,19 @@ SYS_FUNC(sched_setscheduler) SYS_FUNC(sched_getparam) { - if (entering(tcp)) - tprintf("%d, ", (int) tcp->u_arg[0]); - else + if (entering(tcp)) { + printpid(tcp, tcp->u_arg[0], PT_TGID); + tprints(", "); + } else { printnum_int(tcp, tcp->u_arg[1], "%d"); + } return 0; } SYS_FUNC(sched_setparam) { - tprintf("%d, ", (int) tcp->u_arg[0]); + printpid(tcp, tcp->u_arg[0], PT_TGID); + tprints(", "); printnum_int(tcp, tcp->u_arg[1], "%d"); return RVAL_DECODED; @@ -68,7 +72,8 @@ do_sched_rr_get_interval(struct tcb *const tcp, const print_obj_by_addr_fn print_ts) { if (entering(tcp)) { - tprintf("%d, ", (int) tcp->u_arg[0]); + printpid(tcp, tcp->u_arg[0], PT_TGID); + tprints(", "); } else { if (syserror(tcp)) printaddr(tcp->u_arg[1]); @@ -160,7 +165,8 @@ end: SYS_FUNC(sched_setattr) { if (entering(tcp)) { - tprintf("%d, ", (int) tcp->u_arg[0]); + printpid(tcp, tcp->u_arg[0], PT_TGID); + tprints(", "); print_sched_attr(tcp, tcp->u_arg[1], 0); } else { struct sched_attr attr; @@ -179,7 +185,8 @@ SYS_FUNC(sched_setattr) SYS_FUNC(sched_getattr) { if (entering(tcp)) { - tprintf("%d, ", (int) tcp->u_arg[0]); + printpid(tcp, tcp->u_arg[0], PT_TGID); + tprints(", "); } else { const unsigned int size = tcp->u_arg[2]; diff --git a/signal.c b/signal.c index d5d59105..49b4ebd5 100644 --- a/signal.c +++ b/signal.c @@ -439,7 +439,8 @@ SYS_FUNC(sigprocmask) SYS_FUNC(kill) { /* pid */ - tprintf("%d, ", (int) tcp->u_arg[0]); + printpid_tgid_pgid(tcp, tcp->u_arg[0]); + tprints(", "); /* signal */ printsignal(tcp->u_arg[1]); @@ -448,7 +449,7 @@ SYS_FUNC(kill) SYS_FUNC(tkill) { - tprintf("%d", (int) tcp->u_arg[0]); + printpid(tcp, tcp->u_arg[0], PT_TID); tprints(", "); printsignal(tcp->u_arg[1]); @@ -457,8 +458,12 @@ SYS_FUNC(tkill) SYS_FUNC(tgkill) { - /* tgid, tid */ - tprintf("%d, %d, ", (int) tcp->u_arg[0], (int) tcp->u_arg[1]); + /* tgid */ + printpid(tcp, tcp->u_arg[0], PT_TGID); + tprints(", "); + /* tid */ + printpid(tcp, tcp->u_arg[1], PT_TID); + tprints(", "); /* signal */ printsignal(tcp->u_arg[2]); @@ -624,7 +629,8 @@ print_sigqueueinfo(struct tcb *const tcp, const int sig, SYS_FUNC(rt_sigqueueinfo) { - tprintf("%d, ", (int) tcp->u_arg[0]); + printpid(tcp, tcp->u_arg[0], PT_TGID); + tprints(", "); print_sigqueueinfo(tcp, tcp->u_arg[1], tcp->u_arg[2]); return RVAL_DECODED; @@ -632,7 +638,10 @@ SYS_FUNC(rt_sigqueueinfo) SYS_FUNC(rt_tgsigqueueinfo) { - tprintf("%d, %d, ", (int) tcp->u_arg[0], (int) tcp->u_arg[1]); + printpid(tcp, tcp->u_arg[0], PT_TGID); + tprints(", "); + printpid(tcp, tcp->u_arg[1], PT_TID); + tprints(", "); print_sigqueueinfo(tcp, tcp->u_arg[2], tcp->u_arg[3]); return RVAL_DECODED; diff --git a/sockaddr.c b/sockaddr.c index b0046331..fb8887c2 100644 --- a/sockaddr.c +++ b/sockaddr.c @@ -416,7 +416,7 @@ print_sockaddr_data_nl(struct tcb *tcp, const void *const buf, const int addrlen { const struct sockaddr_nl *const sa_nl = buf; - PRINT_FIELD_D("", *sa_nl, nl_pid); + PRINT_FIELD_TGID("", *sa_nl, nl_pid, tcp); PRINT_FIELD_0X(", ", *sa_nl, nl_groups); } diff --git a/tests/kcmp.c b/tests/kcmp.c index a46da0ed..dc5ba9a4 100644 --- a/tests/kcmp.c +++ b/tests/kcmp.c @@ -64,7 +64,26 @@ static const char zero_path[] = "/dev/zero"; static void printpidfd(const char *prefix, pid_t pid, unsigned fd) { - printf("%s%d", prefix, fd); + const char *path = NULL; + +# if VERBOSE_FD + if (pid == getpid()) { + switch (fd) + { + case NULL_FD: + path = null_path; + break; + case ZERO_FD: + path = zero_path; + break; + } + } +# endif + + if (path) + printf("%s%d<%s>", prefix, fd, path); + else + printf("%s%d", prefix, fd); } /* @@ -179,7 +198,7 @@ main(void) /* KCMP_FILE is the only type which has additional args */ do_kcmp(3141592653U, 2718281828U, ARG_STR(KCMP_FILE), bogus_idx1, bogus_idx2); - do_kcmp(-1, -1, ARG_STR(KCMP_FILE), NULL_FD, ZERO_FD); + do_kcmp(getpid(), getpid(), ARG_STR(KCMP_FILE), NULL_FD, ZERO_FD); /* Types without additional args */ do_kcmp(-1, -1, ARG_STR(KCMP_VM), bogus_idx1, bogus_idx2); @@ -198,7 +217,7 @@ main(void) for (i = 0; i < ARRAY_SIZE(slot_data); i++) { memcpy(slot, slot_data + i, sizeof(*slot)); - do_kcmp(getpid(), getppid(), ARG_STR(KCMP_EPOLL_TFD), NULL_FD, + do_kcmp(getpid(), -1, ARG_STR(KCMP_EPOLL_TFD), NULL_FD, (uintptr_t) slot, 1); } diff --git a/util.c b/util.c index 286c6903..2568021e 100644 --- a/util.c +++ b/util.c @@ -392,6 +392,18 @@ printnum_fd(struct tcb *const tcp, const kernel_ulong_t addr) return true; } +bool +printnum_pid(struct tcb *const tcp, const kernel_ulong_t addr, enum pid_type type) +{ + int pid; + if (umove_or_printaddr(tcp, addr, &pid)) + return false; + tprints("["); + printpid(tcp, pid, type); + tprints("]"); + return true; +} + /** * Prints time to a (static internal) buffer and returns pointer to it. * Returns NULL if the provided time specification is not correct. @@ -616,7 +628,7 @@ void printfd_pid(struct tcb *tcp, pid_t pid, int fd) { char path[PATH_MAX + 1]; - if (!number_set_array_is_empty(decode_fd_set, 0) + if (pid > 0 && !number_set_array_is_empty(decode_fd_set, 0) && getfdpath_pid(pid, fd, path, sizeof(path)) >= 0) { tprintf("%d<", (int) fd); if (is_number_in_set(DECODE_FD_SOCKET, decode_fd_set) && @@ -641,12 +653,8 @@ printed: void printfd_pid_tracee_ns(struct tcb *tcp, pid_t pid, int fd) { - /* - * TODO: We want to have the same formatting as printfd here, - * but we should figure out first which process in strace's - * PID NS is referred to by pid in tracee's PID NS. - */ - tprintf("%d", fd); + int strace_pid = translate_pid(tcp, pid, PT_TGID, NULL); + printfd_pid(tcp, strace_pid, fd); } /* diff --git a/wait.c b/wait.c index 2b9f9807..177427c8 100644 --- a/wait.c +++ b/wait.c @@ -80,14 +80,8 @@ printwaitn(struct tcb *const tcp, void (*const print_rusage)(struct tcb *, kernel_ulong_t)) { if (entering(tcp)) { - /* On Linux, kernel-side pid_t is typedef'ed to int - * on all arches. Also, glibc-2.8 truncates wait3 and wait4 - * pid argument to int on 64bit arches, producing, - * for example, wait4(4294967295, ...) instead of -1 - * in strace. We have to use int here, not long. - */ - int pid = tcp->u_arg[0]; - tprintf("%d, ", pid); + printpid_tgid_pgid(tcp, tcp->u_arg[0]); + tprintf(", "); } else { int status; @@ -108,7 +102,7 @@ printwaitn(struct tcb *const tcp, printaddr(tcp->u_arg[3]); } } - return 0; + return RVAL_TGID; } SYS_FUNC(waitpid) @@ -134,10 +128,28 @@ SYS_FUNC(osf_wait4) SYS_FUNC(waitid) { + unsigned int idtype = (unsigned int) tcp->u_arg[0]; + int id = tcp->u_arg[1]; + if (entering(tcp)) { - printxval(waitid_types, tcp->u_arg[0], "P_???"); - int pid = tcp->u_arg[1]; - tprintf(", %d, ", pid); + printxval(waitid_types, idtype, "P_???"); + tprints(", "); + switch (idtype) + { + case P_PID: + printpid(tcp, id, PT_TGID); + break; + case P_PIDFD: + printfd(tcp, id); + break; + case P_PGID: + printpid(tcp, id, PT_PGID); + break; + default: + tprintf("%d", id); + break; + } + tprints(", "); } else { /* siginfo */ printsiginfo_at(tcp, tcp->u_arg[2]); -- 2.28.0 From uzonyi.akos at gmail.com Wed Aug 19 18:16:35 2020 From: uzonyi.akos at gmail.com (=?UTF-8?q?=C3=81kos=20Uzonyi?=) Date: Wed, 19 Aug 2020 20:16:35 +0200 Subject: [PATCH v10 3/5] Use get_proc_pid for /proc paths In-Reply-To: <20200819181637.1096507-1-uzonyi.akos@gmail.com> References: <20200819181637.1096507-1-uzonyi.akos@gmail.com> Message-ID: <20200819181637.1096507-4-uzonyi.akos@gmail.com> * mmap_cache.c (mmap_cache_rebuild_if_invalid): Use proc pid instead of tcp->pid for /proc path. * util.c (getfdproto): Likewise. (pidfd_get_pid): Likewise. * pathtrace.c (getfdpath_pid): Likewise. * strace.c (attach_tcb): Likewise. --- mmap_cache.c | 2 +- pathtrace.c | 7 ++++++- strace.c | 2 +- util.c | 9 +++++++-- 4 files changed, 15 insertions(+), 5 deletions(-) diff --git a/mmap_cache.c b/mmap_cache.c index 89c62254..9825df26 100644 --- a/mmap_cache.c +++ b/mmap_cache.c @@ -84,7 +84,7 @@ mmap_cache_rebuild_if_invalid(struct tcb *tcp, const char *caller) return MMAP_CACHE_REBUILD_READY; char filename[sizeof("/proc/4294967296/maps")]; - xsprintf(filename, "/proc/%u/maps", tcp->pid); + xsprintf(filename, "/proc/%u/maps", get_proc_pid(tcp)); FILE *fp = fopen_stream(filename, "r"); if (!fp) { diff --git a/pathtrace.c b/pathtrace.c index 5b60762b..afed770a 100644 --- a/pathtrace.c +++ b/pathtrace.c @@ -87,7 +87,12 @@ getfdpath_pid(pid_t pid, int fd, char *buf, unsigned bufsize) if (fd < 0) return -1; - xsprintf(linkpath, "/proc/%u/fd/%u", pid, fd); + int proc_pid = 0; + translate_pid(NULL, pid, PT_TID, &proc_pid); + if (!proc_pid) + return -1; + + xsprintf(linkpath, "/proc/%u/fd/%u", proc_pid, fd); n = readlink(linkpath, buf, bufsize - 1); /* * NB: if buf is too small, readlink doesn't fail, diff --git a/strace.c b/strace.c index 249533ea..ef23f08f 100644 --- a/strace.c +++ b/strace.c @@ -1196,7 +1196,7 @@ attach_tcb(struct tcb *const tcp) unsigned int ntid = 0, nerr = 0; if (followfork && tcp->pid != strace_child && - xsprintf(procdir, task_path, tcp->pid) > 0 && + xsprintf(procdir, task_path, get_proc_pid(tcp)) > 0 && (dir = opendir(procdir)) != NULL) { struct_dirent *de; diff --git a/util.c b/util.c index 2568021e..481144bf 100644 --- a/util.c +++ b/util.c @@ -501,7 +501,7 @@ getfdproto(struct tcb *tcp, int fd) if (fd < 0) return SOCK_PROTO_UNKNOWN; - xsprintf(path, "/proc/%u/fd/%u", tcp->pid, fd); + xsprintf(path, "/proc/%u/fd/%u", get_proc_pid(tcp), fd); r = getxattr(path, "system.sockprotoname", buf, bufsize - 1); if (r <= 0) return SOCK_PROTO_UNKNOWN; @@ -582,8 +582,13 @@ printdev(struct tcb *tcp, int fd, const char *path) pid_t pidfd_get_pid(pid_t pid_of_fd, int fd) { + int proc_pid = 0; + translate_pid(NULL, pid_of_fd, PT_TID, &proc_pid); + if (!proc_pid) + return -1; + char fdi_path[sizeof("/proc/%u/fdinfo/%u") + 2 * sizeof(int) * 3]; - xsprintf(fdi_path, "/proc/%u/fdinfo/%u", pid_of_fd, fd); + xsprintf(fdi_path, "/proc/%u/fdinfo/%u", proc_pid, fd); FILE *f = fopen_stream(fdi_path, "r"); if (!f) -- 2.28.0 From uzonyi.akos at gmail.com Wed Aug 19 18:16:36 2020 From: uzonyi.akos at gmail.com (=?UTF-8?q?=C3=81kos=20Uzonyi?=) Date: Wed, 19 Aug 2020 20:16:36 +0200 Subject: [PATCH v10 4/5] Implement testing framework for pidns In-Reply-To: <20200819181637.1096507-1-uzonyi.akos@gmail.com> References: <20200819181637.1096507-1-uzonyi.akos@gmail.com> Message-ID: <20200819181637.1096507-5-uzonyi.akos@gmail.com> * tests/pidns.c: New file. * tests/pidns.h: New file. * tests/Makefile.am (libtests_a_SOURCES): Add pidns.c, pidns.h. * tests/init.sh (test_pidns, test_pidns_run_strace): New functions. --- tests/Makefile.am | 2 + tests/init.sh | 29 ++++++ tests/pidns.c | 229 ++++++++++++++++++++++++++++++++++++++++++++++ tests/pidns.h | 56 ++++++++++++ 4 files changed, 316 insertions(+) create mode 100644 tests/pidns.c create mode 100644 tests/pidns.h diff --git a/tests/Makefile.am b/tests/Makefile.am index 28d95e39..7a583a3a 100644 --- a/tests/Makefile.am +++ b/tests/Makefile.am @@ -44,6 +44,8 @@ libtests_a_SOURCES = \ libsocketcall.c \ lock_file.c \ overflowuid.c \ + pidns.c \ + pidns.h \ pipe_maxfd.c \ print_quoted_string.c \ print_time.c \ diff --git a/tests/init.sh b/tests/init.sh index d78e697b..5c9b8260 100644 --- a/tests/init.sh +++ b/tests/init.sh @@ -387,6 +387,35 @@ test_prog_set() test_pure_prog_set "$@" < "$srcdir/$NAME.in" } +test_pidns_run_strace() +{ + local parent_pid init_pid + + check_prog tail + check_prog cut + check_prog grep + + run_prog > /dev/null + run_strace --pidns-translation -f $@ $args > "$EXP" + + # filter out logs made by the parent or init process of the pidns test + parent_pid="$(tail -n 2 $LOG | head -n 1 | cut -d' ' -f1)" + init_pid="$(tail -n 1 $LOG | cut -d' ' -f1)" + grep -E -v "^($parent_pid|$init_pid) " "$LOG" > "$OUT" + match_diff "$OUT" "$EXP" +} + +test_pidns() +{ + check_prog unshare + + test_pidns_run_strace "$@" + + # test PID translation when /proc is mounted from an other namespace + STRACE="unshare -Urpf $STRACE" + test_pidns_run_strace "$@" +} + check_prog cat check_prog rm diff --git a/tests/pidns.c b/tests/pidns.c new file mode 100644 index 00000000..294650f8 --- /dev/null +++ b/tests/pidns.c @@ -0,0 +1,229 @@ +/* + * Testing framework for PID namespace translation + * + * Copyright (c) 2020 ?kos Uzonyi + * All rights reserved. + * + * SPDX-License-Identifier: LGPL-2.1-or-later + */ +#include "tests.h" +#include "pidns.h" +#include "nsfs.h" + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +static bool pidns_translation = false; +static bool pidns_unshared = false; + +/* Our PIDs in strace's namespace */ +static pid_t pidns_strace_ids[PT_COUNT]; + +void +pidns_print_leader(void) +{ + if (pidns_translation) + printf("%-5d ", pidns_strace_ids[PT_TID]); +} + +const char * +pidns_pid2str(enum pid_type type) +{ + static const char format[] = " /* %d in strace's PID NS */"; + static char buf[PT_COUNT][sizeof(format) + sizeof(int) * 3]; + + if (type < 0 || type >= PT_COUNT) + return ""; + + if (!pidns_unshared || !pidns_strace_ids[type]) + return ""; + + snprintf(buf[type], sizeof(buf[type]), format, pidns_strace_ids[type]); + return buf[type]; +} + +/** + * This function is like fork, but does a few more things. It sets up the + * child's PGID and SID according to the parameters. Also it fills the + * pidns_strace_ids array in the child's memory with the PIDs of the child in + * parent's PID namespace. In the parent it waits for the child to terminate + * (but leaves the zombie to use it later as a process group). If the child + * terminates with nonzero exit status, the test is failed. + * + * @param pgid The process group the child should be moved to. It's expected + * to be a PID of a zombie process (will be reaped). If + * negative, leave the child in the process group of the parent. + * If 0, move the process to its own process group. + * @param new_sid Wheather child should be moved to a new session. + */ +static pid_t +pidns_fork(pid_t pgid, bool new_sid) +{ + int strace_ids_pipe[2]; + if (pipe(strace_ids_pipe) < 0) + perror_msg_and_fail("pipe"); + + fflush(stdout); + pid_t pid = fork(); + if (pid < 0) + perror_msg_and_fail("fork"); + + if (!pid) { + close(strace_ids_pipe[1]); + + ssize_t len = read(strace_ids_pipe[0], pidns_strace_ids, + sizeof(pidns_strace_ids)); + if (len < 0) + perror_msg_and_fail("read"); + if (len != sizeof(pidns_strace_ids)) + error_msg_and_fail("read returned < sizeof(pidns_strace_ids)"); + + close(strace_ids_pipe[0]); + + if (pidns_strace_ids[PT_SID]) + setsid(); + + return 0; + } + + pidns_strace_ids[PT_TID] = pid; + pidns_strace_ids[PT_TGID] = pid; + pidns_strace_ids[PT_PGID] = 0; + pidns_strace_ids[PT_SID] = 0; + + if (!pgid) + pgid = pid; + + if (pgid > 0) { + if (setpgid(pid, pgid) < 0) + perror_msg_and_fail("setpgid"); + + pidns_strace_ids[PT_PGID] = pgid; + } + + /* Reap group leader to test PGID decoding */ + if (pgid > 0 && pgid != pid) { + int ret = waitpid(pgid, NULL, WNOHANG); + if (ret < 0) + perror_msg_and_fail("wait"); + if (!ret) + error_msg_and_fail("could not reap group leader"); + } + + if (new_sid) { + pidns_strace_ids[PT_SID] = pid; + pidns_strace_ids[PT_PGID] = pid; + } + + ssize_t len = write(strace_ids_pipe[1], pidns_strace_ids, + sizeof(pidns_strace_ids)); + if (len < 0) + perror_msg_and_fail("write"); + if (len != sizeof(pidns_strace_ids)) + error_msg_and_fail("write returned < sizeof(pidns_strace_ids)"); + + close(strace_ids_pipe[0]); + close(strace_ids_pipe[1]); + + /* WNOWAIT: leave the zombie, to be able to use it as a process group */ + siginfo_t siginfo; + if (waitid(P_PID, pid, &siginfo, WEXITED | WNOWAIT) < 0) + perror_msg_and_fail("wait"); + if (siginfo.si_code != CLD_EXITED || siginfo.si_status) + error_msg_and_fail("child terminated with nonzero exit status"); + + return pid; +} + +static void +create_init_process(void) +{ + int child_pipe[2]; + if (pipe(child_pipe) < 0) + perror_msg_and_fail("pipe"); + + pid_t pid = fork(); + if (pid < 0) + perror_msg_and_fail("fork"); + + if (!pid) { + close(child_pipe[1]); + if (read(child_pipe[0], &child_pipe[1], sizeof(int)) != 0) + _exit(1); + _exit(0); + } + + close(child_pipe[0]); +} + +void +check_ns_ioctl(void) +{ + int fd = open("/proc/self/ns/pid", O_RDONLY); + if (fd < 0) { + if (errno == ENOENT) + perror_msg_and_skip("opening /proc/self/ns/pid"); + else + perror_msg_and_fail("opening /proc/self/ns/pid"); + } + + int userns_fd = ioctl(fd, NS_GET_USERNS); + if (userns_fd < 0) { + if (errno == ENOTTY) + error_msg_and_skip("NS_* ioctl commands are not " + "supported by the kernel"); + else + perror_msg_and_fail("ioctl(NS_GET_USERNS)"); + } + + close(userns_fd); + close(fd); +} + +void +pidns_test_init(void) +{ + pidns_translation = true; + + check_ns_ioctl(); + + if (!pidns_fork(-1, false)) + return; + + /* Unshare user namespace too, so we do not need to be root */ + if (unshare(CLONE_NEWUSER | CLONE_NEWPID) < 0) { + if (errno == EPERM) + perror_msg_and_skip("unshare"); + + perror_msg_and_fail("unshare"); + } + + pidns_unshared = true; + + create_init_process(); + + if (!pidns_fork(-1, false)) + return; + + if (!pidns_fork(-1, true)) + return; + + pid_t pgid; + if (!(pgid = pidns_fork(0, false))) + return; + + if (!pidns_fork(pgid, false)) + return; + + exit(0); +} diff --git a/tests/pidns.h b/tests/pidns.h new file mode 100644 index 00000000..76963eb3 --- /dev/null +++ b/tests/pidns.h @@ -0,0 +1,56 @@ +/* + * Test PID namespace translation + * + * Copyright (c) 2020 ?kos Uzonyi + * All rights reserved. + * + * SPDX-License-Identifier: LGPL-2.1-or-later + */ +#ifndef STRACE_PIDNS_H +#define STRACE_PIDNS_H + +#ifdef PIDNS_TRANSLATION +# define PIDNS_TEST_INIT pidns_test_init() +#else +# define PIDNS_TEST_INIT +#endif + +#include + +enum pid_type { + PT_TID, + PT_TGID, + PT_PGID, + PT_SID, + + PT_COUNT, + PT_NONE = -1 +}; + +/* Prints leader (process tid) if pidns_test_init was called */ +void pidns_print_leader(void); + +/* + * Returns a static buffer containing the translation string of our PID. + */ +const char *pidns_pid2str(enum pid_type type); + +/** + * Skips the test if NS_* ioctl commands are not supported by the kernel. + */ +void check_ns_ioctl(void); + +/** + * Init pidns testing. + * + * Should be called at the beginning of the test's main function + * + * This function calls fork a couple of times, and returns in the child + * processes. These child processes are in a new PID namespace with different + * PID configurations (group leader, session leader, ...). If any child + * terminates with nonzero exit status the test is failed. Otherwise the test is + * succesful, and the parent process exits with 0. + */ +void pidns_test_init(void); + +#endif \ No newline at end of file -- 2.28.0 From uzonyi.akos at gmail.com Wed Aug 19 18:16:33 2020 From: uzonyi.akos at gmail.com (=?UTF-8?q?=C3=81kos=20Uzonyi?=) Date: Wed, 19 Aug 2020 20:16:33 +0200 Subject: [PATCH v10 1/5] PID namespace translation support In-Reply-To: <20200819181637.1096507-1-uzonyi.akos@gmail.com> References: <20200819181637.1096507-1-uzonyi.akos@gmail.com> Message-ID: <20200819181637.1096507-2-uzonyi.akos@gmail.com> * defs.h (pidns_translation): New variable. (tcb): Add pid_ns field. (RVAL_MASK): Change value from 013 to 017. (RVAL_TID, RVAL_SID, RVAL_TGID, RVAL_PGID): New definitions. (pid_type): New enum. (pidns_init, translate_pid, get_proc_pid, printpid, printpid_tgid_pgid): New function declarations. * largefile_wrappers.h (fstat_fd): New macro. * pidns.c: New file. * trie.c: New file. * trie.h: New file. * Makefile.am (libstrace_a_SOURCES): Add trie.c, trie.h, pidns.c. * strace.c (pidns_translation): New variable. (init): Add --pidns-translation option. * syscall.c (syscall_exiting_trace): Handle RVAL_* return values. * NEWS: Mention this. * strace.1.in: Add description for new option. Co-Authored-by: Eugene Syromyatnikov --- Makefile.am | 3 + NEWS | 1 + defs.h | 56 +++- largefile_wrappers.h | 2 + pidns.c | 604 +++++++++++++++++++++++++++++++++++++++++++ strace.1.in | 4 + strace.c | 9 + syscall.c | 15 ++ trie.c | 290 +++++++++++++++++++++ trie.h | 92 +++++++ 10 files changed, 1075 insertions(+), 1 deletion(-) create mode 100644 pidns.c create mode 100644 trie.c create mode 100644 trie.h diff --git a/Makefile.am b/Makefile.am index f5447811..73c22035 100644 --- a/Makefile.am +++ b/Makefile.am @@ -233,6 +233,7 @@ libstrace_a_SOURCES = \ personality.c \ pidfd_getfd.c \ pidfd_open.c \ + pidns.c \ pkeys.c \ poll.c \ prctl.c \ @@ -344,6 +345,8 @@ libstrace_a_SOURCES = \ time.c \ times.c \ trace_event.h \ + trie.c \ + trie.h \ truncate.c \ ubi.c \ ucopy.c \ diff --git a/NEWS b/NEWS index 10039ceb..c3c5c162 100644 --- a/NEWS +++ b/NEWS @@ -2,6 +2,7 @@ Noteworthy changes in release ?.? (????-??-??) ============================================== * Improvements + * Added --pidns-translation option for PID namespace translation. * Bug fixes diff --git a/defs.h b/defs.h index f7ac54f3..511a92a2 100644 --- a/defs.h +++ b/defs.h @@ -280,6 +280,13 @@ struct tcb { struct timespec etime; /* Syscall entry time (CLOCK_MONOTONIC) */ struct timespec delay_expiration_time; /* When does the delay end */ + /* + * The ID of the PID namespace of this process + * (inode number of /proc//ns/pid) + * (0: not initialized) + */ + unsigned int pid_ns; + struct mmap_cache_t *mmap_cache; /* @@ -413,7 +420,11 @@ extern const struct xlat whence_codes[]; # define RVAL_HEX 001 /* hex format */ # define RVAL_OCTAL 002 /* octal format */ # define RVAL_FD 010 /* file descriptor */ -# define RVAL_MASK 013 /* mask for these values */ +# define RVAL_TID 011 /* task ID */ +# define RVAL_SID 012 /* session ID */ +# define RVAL_TGID 013 /* thread group ID */ +# define RVAL_PGID 014 /* process group ID */ +# define RVAL_MASK 017 /* mask for these values */ # define RVAL_STR 020 /* Print `auxstr' field after return val */ # define RVAL_NONE 040 /* Print nothing */ @@ -428,6 +439,16 @@ extern const struct xlat whence_codes[]; # define indirect_ipccall(tcp) (tcp_sysent(tcp)->sys_flags & TRACE_INDIRECT_SUBCALL) +enum pid_type { + PT_TID, + PT_TGID, + PT_PGID, + PT_SID, + + PT_COUNT, + PT_NONE = -1 +}; + enum sock_proto { SOCK_PROTO_UNKNOWN, SOCK_PROTO_UNIX, @@ -469,6 +490,7 @@ extern int Tflag_scale; extern int Tflag_width; extern bool iflag; extern bool count_wallclock; +extern unsigned int pidns_translation; /* are we filtering traces based on paths? */ extern struct path_set { const char **paths_selected; @@ -983,6 +1005,29 @@ print_local_array_ex(struct tcb *tcp, extern kernel_ulong_t * fetch_indirect_syscall_args(struct tcb *, kernel_ulong_t addr, unsigned int n_args); +extern void pidns_init(void); + +/** + * Returns the pid of the tracee as present in /proc of the tracer (can be + * different from tcp->pid if /proc and the tracer process are in different PID + * namespaces). + */ +extern int get_proc_pid(struct tcb *); + +/** + * Translates a pid from tracee's namespace to our namepace. + * + * @param tcp The tcb of the tracee + * (NULL: from_id is in strace's namespace. Useful for + * getting the proc PID of from_id) + * @param from_id The id to be translated + * @param type The PID type of from_id + * @param proc_pid_ptr If not NULL, writes the proc PID to this location + * @return The translated id, or 0 if translation fails. + */ +extern int translate_pid(struct tcb *, int dest_id, enum pid_type type, + int *proc_pid_ptr); + extern void dumpiov_in_msghdr(struct tcb *, kernel_ulong_t addr, kernel_ulong_t data_size); @@ -1058,6 +1103,15 @@ printfd(struct tcb *tcp, int fd) * of the tracee the descriptor tcp). This is a stub. */ extern void printfd_pid_tracee_ns(struct tcb *tcp, pid_t pid, int fd); + +/** Prints a PID specified in the tracee's PID namespace */ +extern void printpid(struct tcb *, int pid, enum pid_type type); + +/** + * Prints pid as a TGID if positive, and PGID if negative + * (like the first argument of kill). + */ +extern void printpid_tgid_pgid(struct tcb *, int pid); extern void print_sockaddr(struct tcb *, const void *sa, int len); extern bool print_inet_addr(int af, const void *addr, unsigned int len, const char *var_name); diff --git a/largefile_wrappers.h b/largefile_wrappers.h index 116e7048..9d8f5c92 100644 --- a/largefile_wrappers.h +++ b/largefile_wrappers.h @@ -29,6 +29,7 @@ # else # define fcntl_fd fcntl # endif +# define fstat_fd fstat64 # define strace_stat_t struct stat64 # define stat_file stat64 # define struct_dirent struct dirent64 @@ -39,6 +40,7 @@ # define open_file open # define fopen_stream fopen # define fcntl_fd fcntl +# define fstat_fd fstat # define strace_stat_t struct stat # define stat_file stat # define struct_dirent struct dirent diff --git a/pidns.c b/pidns.c new file mode 100644 index 00000000..9d8695da --- /dev/null +++ b/pidns.c @@ -0,0 +1,604 @@ +/* + * Copyright (c) 2020 ?kos Uzonyi + * All rights reserved. + * + * SPDX-License-Identifier: LGPL-2.1-or-later + */ + +#include "defs.h" + + +#include +#include +#include +#include +#include + +#include + +#include +#include +#include +#include + +#include "largefile_wrappers.h" +#include "trie.h" +#include "nsfs.h" +#include "xmalloc.h" +#include "xstring.h" + +/** + * Key: PID NS ID + * Value: a btree: + * Key: a process PID in NS + * Value: the process's PID as present in /proc + */ +static struct trie *ns_pid_to_proc_pid[PT_COUNT]; + +/** + * Key: Proc PID + * Value: struct proc_data + */ +static struct trie *proc_data_cache; + +static bool ns_get_parent_enotty = false; + +static const char tid_str[] = "NSpid:\t"; +static const char tgid_str[] = "NStgid:\t"; +static const char pgid_str[] = "NSpgid:\t"; +static const char sid_str[] = "NSsid:\t"; + +static const struct { + const char *str; + size_t size; +} id_strs[PT_COUNT] = { + [PT_TID] = { tid_str, sizeof(tid_str) - 1 }, + [PT_TGID] = { tgid_str, sizeof(tgid_str) - 1 }, + [PT_PGID] = { pgid_str, sizeof(pgid_str) - 1 }, + [PT_SID] = { sid_str, sizeof(sid_str) - 1 }, +}; + + +/** + * Limit on PID NS hierarchy depth, imposed since Linux 3.7. NS traversal + * is not possible before Linux 4.9, so we consider this limit pretty universal. + */ +#define MAX_NS_DEPTH 32 + +static const size_t ns_id_size = sizeof(unsigned int) * 8; +static const uint8_t ptr_sz_lg = (sizeof(void *) == 8 ? 6 : 5); + +static int pid_max; +static uint8_t pid_max_size, pid_max_size_lg; + +struct proc_data { + int proc_pid; + int ns_count; + unsigned int ns_hierarchy[MAX_NS_DEPTH]; + int id_count[PT_COUNT]; + int id_hierarchy[PT_COUNT][MAX_NS_DEPTH]; +}; + +/** + * Helper function for creating a trie. + * + * For node_key_bits and data_block_key_bits 4 is used (so trie height is 32 / 4 + * = 8, and node sizes are 8 byte * 2^4 = 128 bytes), which seems to be a good + * tradeoff between memory usage and lookup time. It should not be too large, + * since there can be large holes between PIDs, and it would be just a waste of + * memory having large nodes with lot of NULL pointers in them. + */ +static struct trie * +create_trie_4(uint8_t key_size, uint8_t item_size_lg, uint64_t empty_value) +{ + struct trie *t = trie_create(key_size, item_size_lg, 4, 4, empty_value); + if (!t) + error_msg_and_die("creating trie failed"); + + return t; +} + +void +pidns_init(void) +{ + if (proc_data_cache) + return; + + pid_max = INT_MAX; + if (read_int_from_file("/proc/sys/kernel/pid_max", &pid_max) < 0) + debug_func_perror_msg("reading /proc/sys/kernel/pid_max"); + pid_max_size = ilog2_32(pid_max - 1) + 1; + pid_max_size_lg = ilog2_32(pid_max_size - 1) + 1; + + for (int i = 0; i < PT_COUNT; i++) + ns_pid_to_proc_pid[i] = create_trie_4(ns_id_size, ptr_sz_lg, 0); + + proc_data_cache = create_trie_4(pid_max_size, ptr_sz_lg, 0); +} + +static void +put_proc_pid(unsigned int ns, int ns_pid, enum pid_type type, int proc_pid) +{ + struct trie *b = (struct trie *) (uintptr_t) trie_get(ns_pid_to_proc_pid[type], ns); + if (!b) { + b = create_trie_4(pid_max_size, pid_max_size_lg, 0); + trie_set(ns_pid_to_proc_pid[type], ns, (uint64_t) (uintptr_t) b); + } + trie_set(b, ns_pid, proc_pid); +} + +static int +get_cached_proc_pid(unsigned int ns, int ns_pid, enum pid_type type) +{ + struct trie *b = (struct trie *) (uintptr_t) + trie_get(ns_pid_to_proc_pid[type], ns); + if (!b) + return 0; + + return trie_get(b, ns_pid); +} + +/** + * Helper function, converts pid to string, or to "self" for pid == 0. + * Uses static buffer for operation. + */ +static const char * +pid_to_str(pid_t pid) +{ + if (!pid) + return "self"; + + static char buf[sizeof("-2147483648")]; + xsprintf(buf, "%d", pid); + return buf; +} + +/** + * Returns a list of PID NS IDs for the specified PID. + * + * @param proc_pid PID (as present in /proc) to get information for. + * @param ns_buf Pointer to buffer that is able to contain at least + * ns_buf_size items. + * @return Amount of NS in list. 0 indicates error. + */ +static size_t +get_ns_hierarchy(int proc_pid, unsigned int *ns_buf, size_t ns_buf_size) +{ + char path[PATH_MAX + 1]; + xsprintf(path, "/proc/%s/ns/pid", pid_to_str(proc_pid)); + + int fd = open_file(path, O_RDONLY); + if (fd < 0) + return 0; + + size_t n = 0; + while (n < ns_buf_size) { + strace_stat_t st; + if (fstat_fd(fd, &st)) + break; + + ns_buf[n++] = st.st_ino; + if (n >= ns_buf_size) + break; + + if (ns_get_parent_enotty) + break; + + int parent_fd = ioctl(fd, NS_GET_PARENT); + if (parent_fd < 0) { + switch (errno) { + case EPERM: + break; + + case ENOTTY: + ns_get_parent_enotty = true; + error_msg("NS_* ioctl commands are not " + "supported by the kernel"); + break; + + default: + perror_func_msg("ioctl(NS_GET_PARENT)"); + break; + } + + break; + } + + close(fd); + fd = parent_fd; + } + + close(fd); + + return n; +} + +/** + * Get list of IDs present in NS* proc status record. IDs are placed as they are + * stored in /proc (from top to bottom of NS hierarchy). + * + * @param proc_pid PID (as present in /proc) to get information for. + * @param id_buf Pointer to buffer that is able to contain at least + * MAX_NS_DEPTH items. Can be NULL. + * @param type Type of ID requested. + * @return Number of items stored in id_list. 0 indicates error. + */ +static size_t +get_id_list(int proc_pid, int *id_buf, enum pid_type type) +{ + const char *ns_str = id_strs[type].str; + size_t ns_str_size = id_strs[type].size; + + size_t n = 0; + + char status_path[PATH_MAX + 1]; + xsprintf(status_path, "/proc/%s/status", pid_to_str(proc_pid)); + FILE *f = fopen_stream(status_path, "r"); + if (!f) + return 0; + + char *line = NULL; + size_t linesize = 0; + char *p = NULL; + + while (getline(&line, &linesize, f) > 0) { + if (strncmp(line, ns_str, ns_str_size) == 0) { + p = line + ns_str_size; + break; + } + } + + while (p) { + errno = 0; + long id = strtol(p, NULL, 10); + + if (errno || id < 1 || id > INT_MAX) { + perror_func_msg("converting pid (%ld) to int", id); + break; + } + + if (id_buf) + id_buf[n] = (int) id; + + n++; + strsep(&p, "\t"); + } + + free(line); + fclose(f); + + return n; +} + +/** + * Returns whether the /proc filesystem's PID namespace is the same as strace's. + */ +static bool +is_proc_ours(void) +{ + static int cached_val = -1; + + if (cached_val < 0) + cached_val = get_id_list(0, NULL, PT_TID) == 1; + + return cached_val; +} + +/** + * Returns the PID namespace of the tracee + */ +static unsigned int +get_ns(struct tcb *tcp) +{ + if (!tcp->pid_ns) { + int proc_pid = 0; + translate_pid(NULL, tcp->pid, PT_TID, &proc_pid); + + if (proc_pid) + get_ns_hierarchy(proc_pid, &tcp->pid_ns, 1); + } + + return tcp->pid_ns; +} + +/** + * Returns the PID namespace of strace + */ +static unsigned int +get_our_ns(void) +{ + static unsigned int our_ns = 0; + static bool our_ns_initialised = false; + + if (!our_ns_initialised) { + get_ns_hierarchy(0, &our_ns, 1); + our_ns_initialised = true; + } + + return our_ns; +} + +/** + * Returns the cached proc_data struct associated with proc_pid. + * If none found, allocates a new proc_data. + */ +static struct proc_data * +get_or_create_proc_data(int proc_pid) +{ + struct proc_data *pd = (struct proc_data *) (uintptr_t) + trie_get(proc_data_cache, proc_pid); + + if (!pd) { + pd = calloc(1, sizeof(*pd)); + if (!pd) + return NULL; + + pd->proc_pid = proc_pid; + trie_set(proc_data_cache, proc_pid, (uint64_t) (uintptr_t) pd); + } + + return pd; +} + +/** + * Updates the proc_data from /proc + * If the process does not exists, returns false, and frees the proc_data + */ +static bool +update_proc_data(struct proc_data *pd, enum pid_type type) +{ + pd->ns_count = get_ns_hierarchy(pd->proc_pid, + pd->ns_hierarchy, MAX_NS_DEPTH); + if (!pd->ns_count) + goto fail; + + pd->id_count[type] = get_id_list(pd->proc_pid, + pd->id_hierarchy[type], type); + if (!pd->id_count[type]) + goto fail; + + return true; + +fail: + trie_set(proc_data_cache, pd->proc_pid, (uint64_t) (uintptr_t) NULL); + free(pd); + return false; +} + +/** + * Paramters for id translation + */ +struct translate_id_params { + /* The result (output) */ + int result_id; + /* The proc data of the process (output) */ + struct proc_data *pd; + + /* The namespace to be translated from */ + unsigned int from_ns; + /* The id to be translated */ + int from_id; + /* The type of the id */ + enum pid_type type; +}; + +/** + * Translates an id to our namespace, given the proc_pid of the process, + * by reading files in /proc. + * + * @param tip The parameters + * @param proc_pid The proc pid of the process. + * If 0, use the cached values in tip->pd. + */ +static void +translate_id_proc_pid(struct translate_id_params *tip, int proc_pid) +{ + struct proc_data *pd = proc_pid ? + get_or_create_proc_data(proc_pid) : + tip->pd; + + tip->result_id = 0; + tip->pd = NULL; + + if (!pd) + return; + + if (proc_pid && !update_proc_data(pd, tip->type)) + return; + + if (!pd->ns_count || pd->id_count[tip->type] < pd->ns_count) + return; + + int our_ns_id_idx = pd->id_count[tip->type] - pd->ns_count; + + for (int i = 0; i < pd->ns_count; i++) { + if (pd->ns_hierarchy[i] != tip->from_ns) + continue; + + int id_idx = pd->id_count[tip->type] - i - 1; + if (pd->id_hierarchy[tip->type][id_idx] != tip->from_id) + return; + + tip->result_id = pd->id_hierarchy[tip->type][our_ns_id_idx]; + tip->pd = pd; + return; + } +} + +/** + * Translates an id to our namespace, by reading all proc entries in dir. + * + * @param tip The parameters + * @param path The path of the dir to be read. + * @param read_task_dir Whether recurse to "task" subdirectory. + */ +static void +translate_id_dir(struct translate_id_params *tip, const char *path, + bool read_task_dir) +{ + DIR *dir = opendir(path); + if (!dir) { + debug_func_perror_msg("opening dir: %s", path); + return; + } + + while (!tip->result_id) { + errno = 0; + struct_dirent *entry = read_dir(dir); + if (!entry) { + if (errno) + perror_func_msg("readdir"); + + break; + } + + if (entry->d_type != DT_DIR) + continue; + + errno = 0; + long proc_pid = strtol(entry->d_name, NULL, 10); + if (errno) + continue; + if (proc_pid < 1 || proc_pid > INT_MAX) + continue; + + if (read_task_dir) { + char task_dir_path[PATH_MAX + 1]; + xsprintf(task_dir_path, "/proc/%ld/task", proc_pid); + translate_id_dir(tip, task_dir_path, false); + } + + if (tip->result_id) + break; + + translate_id_proc_pid(tip, proc_pid); + } + + closedir(dir); +} + +/** + * Iterator function of the proc_data_cache for id translation. + * If the cache contains the id we are looking for, reads the corresponding + * directory in /proc, and if cache is valid, saves the result. + */ +static void +proc_data_cache_iterator_fn(void* fn_data, uint64_t key, uint64_t val) +{ + struct translate_id_params *tip = (struct translate_id_params *)fn_data; + struct proc_data *pd = (struct proc_data *) (uintptr_t) val; + + if (!pd) + return; + + /* Result already found in an earlier iteration */ + if (tip->result_id) + return; + + /* Translate from cache */ + tip->pd = pd; + translate_id_proc_pid(tip, 0); + if (!tip->result_id) + return; + + /* Now translate from actual data in /proc, to check cache validity */ + translate_id_proc_pid(tip, pd->proc_pid); +} + +int +translate_pid(struct tcb *tcp, int from_id, enum pid_type type, + int *proc_pid_ptr) +{ + if (from_id <= 0 || type < 0 || type >= PT_COUNT) + return 0; + + /* If translation is trivial */ + if ((!tcp || get_ns(tcp) == get_our_ns()) && + (!proc_pid_ptr || is_proc_ours())) { + if (proc_pid_ptr) + *proc_pid_ptr = from_id; + + return from_id; + } + + struct translate_id_params tip = { + .result_id = 0, + .pd = NULL, + .from_ns = tcp ? get_ns(tcp) : get_our_ns(), + .from_id = from_id, + .type = type, + }; + + if (!tip.from_ns) + return 0; + + if (ns_get_parent_enotty) + return 0; + + /* Look for a cached proc_pid for this (from_ns, from_id) pair */ + int cached_proc_pid = get_cached_proc_pid(tip.from_ns, tip.from_id, + tip.type); + if (cached_proc_pid) { + translate_id_proc_pid(&tip, cached_proc_pid); + if (tip.result_id) + goto exit; + } + + /* Iterate through the cache, find potential proc_data */ + trie_iterate_keys(proc_data_cache, 0, pid_max, + proc_data_cache_iterator_fn, &tip); + /* (proc_data_cache_iterator_fn takes care about updating proc_data) */ + if (tip.result_id) + goto exit; + + /* No cache helped, read all entries in /proc */ + translate_id_dir(&tip, "/proc", true); + +exit: + if (tip.pd) { + if (tip.pd->proc_pid) + put_proc_pid(tip.from_ns, tip.from_id, tip.type, + tip.pd->proc_pid); + + if (proc_pid_ptr) + *proc_pid_ptr = tip.pd->proc_pid; + } + + return tip.result_id; +} + +int +get_proc_pid(struct tcb *tcp) +{ + int proc_pid = 0; + translate_pid(NULL, tcp->pid, PT_TID, &proc_pid); + return proc_pid; +} + +static void +printpid_translation(struct tcb *tcp, int pid, enum pid_type type) +{ + if (!pidns_translation) + return; + + int strace_pid = translate_pid(tcp, pid, type, NULL); + if (strace_pid && strace_pid != pid) + tprintf_comment("%d in strace's PID NS", strace_pid); +} + +void +printpid(struct tcb *tcp, int pid, enum pid_type type) +{ + tprintf("%d", pid); + printpid_translation(tcp, pid, type); +} + +void +printpid_tgid_pgid(struct tcb *tcp, int pid) +{ + tprintf("%d", pid); + if (pid > 0) + printpid_translation(tcp, pid, PT_TGID); + else if (pid < -1) + printpid_translation(tcp, -pid, PT_PGID); +} diff --git a/strace.1.in b/strace.1.in index 3b21caec..83776e88 100644 --- a/strace.1.in +++ b/strace.1.in @@ -1075,6 +1075,10 @@ Print all available information associated with file descritors: protocol-specific information associated with socket file descriptors, block/character device number associated with device file descriptors, and PIDs asociated with pidfd file descriptors. +.TP +.B \-\-pidns\-translation +If strace and tracee are in different PID namespaces, print PIDs in +strace's namespace, too. .SS Statistics .TP 12 .B \-c diff --git a/strace.c b/strace.c index 4c96a98b..249533ea 100644 --- a/strace.c +++ b/strace.c @@ -133,6 +133,8 @@ static unsigned int daemonized_tracer; static int post_attach_sigstop = TCB_IGNORE_ONE_SIGSTOP; #define use_seize (post_attach_sigstop == 0) +unsigned int pidns_translation; + static bool detach_on_execve; static int exit_code; @@ -1998,6 +2000,8 @@ init(int argc, char *argv[]) os_release = get_os_release(); + pidns_init(); + shared_log = stderr; set_sortby(DEFAULT_SORTBY); set_personality(DEFAULT_PERSONALITY); @@ -2022,6 +2026,7 @@ init(int argc, char *argv[]) GETOPT_FOLLOWFORKS, GETOPT_OUTPUT_SEPARATELY, GETOPT_TS, + GETOPT_PIDNS_TRANSLATION, GETOPT_QUAL_TRACE, GETOPT_QUAL_ABBREV, @@ -2072,6 +2077,7 @@ init(int argc, char *argv[]) { "summary-wall-clock", no_argument, 0, 'w' }, { "strings-in-hex", optional_argument, 0, GETOPT_HEX_STR }, { "const-print-style", required_argument, 0, 'X' }, + { "pidns-translation", no_argument , 0, GETOPT_PIDNS_TRANSLATION }, { "successful-only", no_argument, 0, 'z' }, { "failed-only", no_argument, 0, 'Z' }, { "failing-only", no_argument, 0, 'Z' }, @@ -2285,6 +2291,9 @@ init(int argc, char *argv[]) case 'y': yflag_short++; break; + case GETOPT_PIDNS_TRANSLATION: + pidns_translation++; + break; case 'z': clear_number_set_array(status_set, 1); add_number_to_set(STATUS_SUCCESSFUL, status_set); diff --git a/syscall.c b/syscall.c index bcc87025..0f4bab6d 100644 --- a/syscall.c +++ b/syscall.c @@ -937,6 +937,21 @@ syscall_exiting_trace(struct tcb *tcp, struct timespec *ts, int res) tprintf("= %" PRI_kld, tcp->u_rval); } break; + case RVAL_TID: + case RVAL_SID: + case RVAL_TGID: + case RVAL_PGID: { + #define _(_t) [RVAL_##_t - RVAL_TID] = PT_##_t + static const enum pid_type types[] = { + _(TID), _(SID), _(TGID), _(PGID), + }; + #undef _ + + tprints("= "); + printpid(tcp, tcp->u_rval, + types[(sys_res & RVAL_MASK) - RVAL_TID]); + break; + } default: error_msg("invalid rval format"); break; diff --git a/trie.c b/trie.c new file mode 100644 index 00000000..bcb0d791 --- /dev/null +++ b/trie.c @@ -0,0 +1,290 @@ +/* + * Simple trie implementation for key-value mapping storage + * + * Copyright (c) 2020 ?kos Uzonyi + * All rights reserved. + * + * SPDX-License-Identifier: LGPL-2.1-or-later + */ + +#ifdef HAVE_CONFIG_H +# include "config.h" +#endif + +#include +#include + +#include "trie.h" + +static const uint8_t ptr_sz_lg = (sizeof(void *) == 8 ? 6 : 5); + +/** + * Returns lg2 of node size in bits for the specific level of the trie. + */ +static uint8_t +trie_get_node_size(struct trie *t, uint8_t depth) +{ + /* Last level contains data and we allow it having a different size */ + if (depth == t->max_depth) + return t->data_block_key_bits + t->item_size_lg; + /* Last level of the tree can be smaller */ + if (depth == t->max_depth - 1) + return (t->key_size - t->data_block_key_bits - 1) % + t->node_key_bits + 1 + ptr_sz_lg; + + return t->node_key_bits + ptr_sz_lg; +} + +/** + * Provides starting offset of bits in key corresponding to the node index + * at the specific level. + */ +static uint8_t +trie_get_node_bit_offs(struct trie *t, uint8_t depth) +{ + uint8_t offs; + + if (depth == t->max_depth) + return 0; + + offs = t->data_block_key_bits; + + if (depth == t->max_depth - 1) + return offs; + + /* data_block_size + remainder */ + offs += trie_get_node_size(t, t->max_depth - 1) - ptr_sz_lg; + offs += (t->max_depth - depth - 2) * t->node_key_bits; + + return offs; +} + +struct trie * +trie_create(uint8_t key_size, uint8_t item_size_lg, uint8_t node_key_bits, + uint8_t data_block_key_bits, uint64_t empty_value) +{ + if (item_size_lg > 6) + return NULL; + if (key_size > 64) + return NULL; + if (node_key_bits < 1) + return NULL; + if (data_block_key_bits < 1 || data_block_key_bits > key_size) + return NULL; + + struct trie *t = malloc(sizeof(*t)); + if (!t) + return NULL; + + t->empty_value = empty_value; + t->data = NULL; + t->item_size_lg = item_size_lg; + t->node_key_bits = node_key_bits; + t->data_block_key_bits = data_block_key_bits; + t->key_size = key_size; + t->max_depth = (key_size - data_block_key_bits + node_key_bits - 1) + / t->node_key_bits; + + if (item_size_lg != 6) + t->empty_value &= (((uint64_t) 1 << (1 << t->item_size_lg)) - 1); + + return t; +} + +static void * +trie_create_data_block(struct trie *t) +{ + uint64_t fill_value = t->empty_value; + for (int i = 1; i < 1 << (6 - t->item_size_lg); i++) { + fill_value <<= (1 << t->item_size_lg); + fill_value |= t->empty_value; + } + + uint8_t sz = t->data_block_key_bits + t->item_size_lg; + if (sz < 6) + sz = 6; + + size_t count = 1 << (sz - 6); + uint64_t *data_block = calloc(count, 8); + if (!data_block) + return NULL; + + for (size_t i = 0; i < count; i++) + data_block[i] = fill_value; + + return data_block; +} + +static uint64_t * +trie_get_node(struct trie *t, uint64_t key, bool auto_create) +{ + void **cur_node = &(t->data); + + if (t->key_size < 64 && key > (uint64_t) 1 << t->key_size) + return NULL; + + for (uint8_t cur_depth = 0; cur_depth <= t->max_depth; cur_depth++) { + uint8_t offs = trie_get_node_bit_offs(t, cur_depth); + uint8_t sz = trie_get_node_size(t, cur_depth); + + if (!*cur_node) { + if (!auto_create) + return NULL; + + if (cur_depth == t->max_depth) + *cur_node = trie_create_data_block(t); + else + *cur_node = calloc(1 << sz, 1); + + if (!*cur_node) { + fprintf(stderr, "Out of memory"); + exit(1); + } + } + + if (cur_depth == t->max_depth) + break; + + size_t pos = (key >> offs) & ((1 << (sz - ptr_sz_lg)) - 1); + cur_node = (((void **) (*cur_node)) + pos); + } + + return (uint64_t *) (*cur_node); +} + +static void +trie_data_block_calc_pos(struct trie *t, uint64_t key, + uint64_t *pos, uint64_t *mask, uint64_t *offs) +{ + uint64_t key_mask; + + key_mask = (1 << t->data_block_key_bits) - 1; + *pos = (key & key_mask) >> (6 - t->item_size_lg); + + if (t->item_size_lg == 6) { + *offs = 0; + *mask = -1; + return; + } + + key_mask = (1 << (6 - t->item_size_lg)) - 1; + *offs = (key & key_mask) * (1 << t->item_size_lg); + + *mask = (((uint64_t) 1 << (1 << t->item_size_lg)) - 1) << *offs; +} + +bool +trie_set(struct trie *t, uint64_t key, uint64_t val) +{ + uint64_t *data = trie_get_node(t, key, true); + if (!data) + return false; + + uint64_t pos, mask, offs; + trie_data_block_calc_pos(t, key, &pos, &mask, &offs); + + data[pos] &= ~mask; + data[pos] |= (val << offs) & mask; + + return true; +} + +static uint64_t +trie_data_block_get(struct trie *t, uint64_t *data, uint64_t key) +{ + if (!data) + return t->empty_value; + + uint64_t pos, mask, offs; + trie_data_block_calc_pos(t, key, &pos, &mask, &offs); + + return (data[pos] & mask) >> offs; +} + +uint64_t +trie_get(struct trie *b, uint64_t key) +{ + return trie_data_block_get(b, trie_get_node(b, key, false), key); +} + +static uint64_t +trie_iterate_keys_node(struct trie *t, + trie_iterate_fn fn, void *fn_data, + void *node, uint64_t start, uint64_t end, + uint8_t depth) +{ + if (start > end || !node) + return 0; + + if (depth == t->max_depth) { + for (uint64_t i = start; i <= end; i++) + fn(fn_data, i, trie_data_block_get(t, + (uint64_t *) node, i)); + + return end - start + 1; + } + + uint8_t parent_node_bit_off = depth == 0 ? + t->key_size : + trie_get_node_bit_offs(t, depth - 1); + + uint64_t first_key_in_node = start & + (uint64_t) -1 << parent_node_bit_off; + + uint8_t node_bit_off = trie_get_node_bit_offs(t, depth); + uint8_t node_key_bits = parent_node_bit_off - node_bit_off; + uint64_t mask = ((uint64_t) 1 << (node_key_bits)) - 1; + uint64_t start_index = (start >> node_bit_off) & mask; + uint64_t end_index = (end >> node_bit_off) & mask; + uint64_t child_key_count = (uint64_t) 1 << node_bit_off; + + uint64_t count = 0; + + for (uint64_t i = start_index; i <= end_index; i++) { + uint64_t child_start = first_key_in_node + i * child_key_count; + uint64_t child_end = first_key_in_node + + (i + 1) * child_key_count - 1; + + if (child_start < start) + child_start = start; + if (child_end > end) + child_end = end; + + count += trie_iterate_keys_node(t, fn, fn_data, + ((void **) node)[i], child_start, child_end, + depth + 1); + } + + return count; +} + +uint64_t trie_iterate_keys(struct trie *t, uint64_t start, uint64_t end, + trie_iterate_fn fn, void *fn_data) +{ + return trie_iterate_keys_node(t, fn, fn_data, t->data, + start, end, 0); +} + +static void +trie_free_node(struct trie *t, void *node, uint8_t depth) +{ + if (!node) + return; + + if (depth >= t->max_depth) + goto free_node; + + size_t sz = 1 << (trie_get_node_size(t, depth) - ptr_sz_lg); + for (size_t i = 0; i < sz; i++) + trie_free_node(t, ((void **) node)[i], depth + 1); + +free_node: + free(node); +} + +void +trie_free(struct trie *t) +{ + trie_free_node(t, t->data, 0); + free(t); +} diff --git a/trie.h b/trie.h new file mode 100644 index 00000000..deb87a54 --- /dev/null +++ b/trie.h @@ -0,0 +1,92 @@ +/* + * Simple trie interface + * + * Copyright (c) 2020 ?kos Uzonyi + * All rights reserved. + * + * SPDX-License-Identifier: LGPL-2.1-or-later + */ + +#ifndef STRACE_TRIE_H +#define STRACE_TRIE_H + +#include +#include + +/** + * Trie control structure. + * Trie implemented here has the following properties: + * * It allows storing values of the same size, the size can vary from 1 bit to + * 64 bit values (only power of 2 sizes are allowed). + * * The key can be up to 64 bits in size. + * * It has separate configuration for node size and data block size. + * + * How bits of key are used for different node levels: + * + * highest bits lowest bits + * | node_key_bits | node_key_bits | ... | | data_block_key_bits | + * \_________________________________________________________________________/ + * key_size + * + * So, the remainder is used on the lowest non-data node level. + * + * As of now, it doesn't implement any mechanisms for resizing/changing key + * size. De-fragmentation is also unsupported currently. + */ +struct trie { + /** Return value of trie_get if key is not found */ + uint64_t empty_value; + + /** Pointer to root node */ + void *data; + + /** Key size in bits (0..64). */ + uint8_t key_size; + + /** + * Size of the stored values in log2 bits (0..6). + * (6: 64 bit values, 5: 32 bit values, ...) + */ + uint8_t item_size_lg; + + /** + * Number of bits in the key that make a symbol for a node. + * (equals to log2 of the child count of the node) + */ + uint8_t node_key_bits; + + /** + * Number of bits in the key that make a symbol for the data block (leaf). + * (equals to log2 of the value count stored in a data block) + */ + uint8_t data_block_key_bits; + + /** The depth of the data block. Calculated from the values above */ + uint8_t max_depth; +}; + +struct trie* trie_create(uint8_t key_size, uint8_t item_size_lg, + uint8_t node_key_bits, uint8_t data_block_key_bits, + uint64_t empty_value); + +bool trie_set(struct trie *t, uint64_t key, uint64_t val); +uint64_t trie_get(struct trie *t, uint64_t key); + +typedef void (*trie_iterate_fn)(void *data, uint64_t key, uint64_t val); + +/** + * Calls trie_iterate_fn for each key-value pair where + * key is inside the [start, end] interval (inclusive). + * + * @param t The trie. + * @param start The start of the key interval (inclusive). + * @param end The end of the key interval (inclusive). + * @param fn The function to be called. + * @param fn_data The value to be passed to fn. + */ +uint64_t trie_iterate_keys(struct trie *t, uint64_t start, uint64_t end, + trie_iterate_fn fn, void *fn_data); + +void trie_free(struct trie *t); + +#endif /* !STRACE_TRIE_H */ -- 2.28.0 From uzonyi.akos at gmail.com Wed Aug 19 18:16:37 2020 From: uzonyi.akos at gmail.com (=?UTF-8?q?=C3=81kos=20Uzonyi?=) Date: Wed, 19 Aug 2020 20:16:37 +0200 Subject: [PATCH v10 5/5] Add tests for PID namespace translation In-Reply-To: <20200819181637.1096507-1-uzonyi.akos@gmail.com> References: <20200819181637.1096507-1-uzonyi.akos@gmail.com> Message-ID: <20200819181637.1096507-6-uzonyi.akos@gmail.com> * tests/.gitignore: Add new test executables. * tests/Makefile.am (check_PROGRAMS): Add new test executables. (DECODER_TESTS) Add new test files. * tests/gen_tests.in: Add new tests. * tests/trie.c: New symbolic link to ../trie. * tests/trie_test.c: New file. * tests/pidns-cache.c: New file. * tests/pidns-cache.test: New file. * tests/fcntl--pidns-translation.c: New file. * tests/fcntl64--pidns-translation.c: New file. * tests/fork--pidns-translation.awk: New file. * tests/fork--pidns-translation.c: New file. * tests/fork--pidns-translation.test: New file. * tests/getpgrp--pidns-translation.c: New file. * tests/getpid--pidns-translation.c: New file. * tests/getsid--pidns-translation.c: New file. * tests/gettid--pidns-translation.c: New file. * tests/gettid--pidns-translation.test: New file. * tests/ioctl_block--pidns-translation.c: New file. * tests/ioctl_block--pidns-translation.test: New file. * tests/ioprio--pidns-translation.c: New file. * tests/kill--pidns-translation.c: New file. * tests/migrate_pages--pidns-translation.c: New file. * tests/move_pages--pidns-translation.c: New file. * tests/net-sockaddr--pidns-translation.c: New file. * tests/netlink_audit--pidns-translation.c: New file. * tests/netlink_audit--pidns-translation.test: New file. * tests/pidfd_open--pidns-translation.c: New file. * tests/pidfd_send_signal--pidns-translation.c: New file. * tests/prlimit64--pidns-translation.c: New file. * tests/process_vm_readv--pidns-translation.c: New file. * tests/process_vm_writev--pidns-translation.c: New file. * tests/rt_sigqueueinfo--pidns-translation.c: New file. * tests/rt_tgsigqueueinfo--pidns-translation.c: New file. * tests/sched_xetaffinity--pidns-translation.c: New file. * tests/sched_xetattr--pidns-translation.c: New file. * tests/sched_xetparam--pidns-translation.c: New file. * tests/sched_xetscheduler--pidns-translation.c: New file. * tests/signal_receive--pidns-translation.c: New file. * tests/so_peercred--pidns-translation.c: New file. * tests/tkill--pidns-translation.c: New file. * tests/tgkill--pidns-translation.c: New file. * tests/xet_robust_list--pidns-translation.c: New file. * tests/xetpgid--pidns-translation.c: New file. * tests/xetpriority--pidns-translation.c: New file. * tests/fcntl-common.c: Print PID translation string after PIDs. * tests/fcntl.c: Likewise. * tests/fcntl64.c: Likewise. * tests/getpgrp.c: Likewise. * tests/getpid.c: Likewise. * tests/getsid.c: Likewise. * tests/gettid.c: Likewise. * tests/ioctl_block.c: Likewise. * tests/ioprio.c: Likewise. * tests/kcmp.c: Likewise. * tests/kill.c: Likewise. * tests/migrate_pages.c: Likewise. * tests/move_pages.c: Likewise. * tests/net-sockaddr.c: Likewise. * tests/netlink_audit.c: Likewise. * tests/pidfd_open.c: Likewise. * tests/pidfd_send_signal.c: Likewise. * tests/prlimit64.c: Likewise. * tests/process_vm_readv_writev.c: Likewise. * tests/rt_sigqueueinfo.c: Likewise. * tests/rt_tgsigqueueinfo.c: Likewise. * tests/sched_xetaffinity.c: Likewise. * tests/sched_xetattr.c: Likewise. * tests/sched_xetparam.c: Likewise. * tests/sched_xetscheduler.c: Likewise. * tests/signal_receive.c: Likewise. * tests/so_peercred.c: Likewise. * tests/tgkill.c: Likewise. * tests/tkill.c: Likewise. * tests/xet_robust_list.c: Likewise. * tests/xetpgid.c: Likewise. * tests/xetpriority.c: Likewise. --- tests/.gitignore | 35 +++++++++ tests/Makefile.am | 42 ++++++++++ tests/fcntl--pidns-translation.c | 2 + tests/fcntl-common.c | 78 ++++++++++++++----- tests/fcntl.c | 1 + tests/fcntl64--pidns-translation.c | 2 + tests/fcntl64.c | 3 + tests/fork--pidns-translation.awk | 15 ++++ tests/fork--pidns-translation.c | 69 ++++++++++++++++ tests/fork--pidns-translation.test | 14 ++++ tests/gen_tests.in | 32 +++++++- tests/getpgrp--pidns-translation.c | 2 + tests/getpgrp.c | 8 +- tests/getpid--pidns-translation.c | 2 + tests/getpid.c | 8 +- tests/getsid--pidns-translation.c | 2 + tests/getsid.c | 9 ++- tests/gettid--pidns-translation.c | 2 + tests/gettid--pidns-translation.test | 18 +++++ tests/gettid.c | 8 +- tests/ioctl_block--pidns-translation.c | 2 + tests/ioctl_block--pidns-translation.test | 22 ++++++ tests/ioctl_block.c | 24 +++++- tests/ioprio--pidns-translation.c | 2 + tests/ioprio.c | 54 ++++++++----- tests/kcmp-y--pidns-translation.c | 2 + tests/kcmp.c | 11 ++- tests/kill--pidns-translation.c | 2 + tests/kill.c | 12 ++- tests/migrate_pages--pidns-translation.c | 2 + tests/migrate_pages.c | 17 +++- tests/move_pages--pidns-translation.c | 2 + tests/move_pages.c | 51 +++++++----- tests/net-sockaddr--pidns-translation.c | 2 + tests/net-sockaddr.c | 60 +++++++++++++- tests/netlink_audit--pidns-translation.c | 2 + tests/netlink_audit--pidns-translation.test | 13 ++++ tests/netlink_audit.c | 11 ++- tests/pidfd_open--pidns-translation.c | 2 + tests/pidfd_open.c | 21 +++-- tests/pidfd_send_signal--pidns-translation.c | 2 + tests/pidfd_send_signal.c | 13 +++- tests/pidns-cache.c | 62 +++++++++++++++ tests/pidns-cache.test | 16 ++++ tests/prlimit64--pidns-translation.c | 2 + tests/prlimit64.c | 17 +++- tests/process_vm_readv--pidns-translation.c | 2 + tests/process_vm_readv_writev.c | 27 ++++--- tests/process_vm_writev--pidns-translation.c | 2 + tests/rt_sigqueueinfo--pidns-translation.c | 2 + tests/rt_sigqueueinfo.c | 15 +++- tests/rt_tgsigqueueinfo--pidns-translation.c | 2 + tests/rt_tgsigqueueinfo.c | 26 ++++--- tests/sched_xetaffinity--pidns-translation.c | 2 + tests/sched_xetaffinity.c | 31 +++++--- tests/sched_xetattr--pidns-translation.c | 2 + tests/sched_xetattr.c | 47 ++++++++++- tests/sched_xetparam--pidns-translation.c | 2 + tests/sched_xetparam.c | 20 +++-- tests/sched_xetscheduler--pidns-translation.c | 2 + tests/sched_xetscheduler.c | 44 +++++++---- tests/signal_receive--pidns-translation.c | 2 + tests/signal_receive.c | 22 ++++-- tests/so_peercred--pidns-translation.c | 2 + tests/so_peercred.c | 22 ++++++ tests/tgkill--pidns-translation.c | 2 + tests/tgkill.c | 51 ++++++++---- tests/tkill--pidns-translation.c | 2 + tests/tkill.c | 19 +++-- tests/trie.c | 1 + tests/trie_test.c | 77 ++++++++++++++++++ tests/xet_robust_list--pidns-translation.c | 2 + tests/xet_robust_list.c | 18 ++++- tests/xetpgid--pidns-translation.c | 2 + tests/xetpgid.c | 21 +++-- tests/xetpriority--pidns-translation.c | 2 + tests/xetpriority.c | 20 ++++- 77 files changed, 1083 insertions(+), 186 deletions(-) create mode 100644 tests/fcntl--pidns-translation.c create mode 100644 tests/fcntl64--pidns-translation.c create mode 100644 tests/fork--pidns-translation.awk create mode 100644 tests/fork--pidns-translation.c create mode 100755 tests/fork--pidns-translation.test create mode 100644 tests/getpgrp--pidns-translation.c create mode 100644 tests/getpid--pidns-translation.c create mode 100644 tests/getsid--pidns-translation.c create mode 100644 tests/gettid--pidns-translation.c create mode 100755 tests/gettid--pidns-translation.test create mode 100644 tests/ioctl_block--pidns-translation.c create mode 100755 tests/ioctl_block--pidns-translation.test create mode 100644 tests/ioprio--pidns-translation.c create mode 100644 tests/kcmp-y--pidns-translation.c create mode 100644 tests/kill--pidns-translation.c create mode 100644 tests/migrate_pages--pidns-translation.c create mode 100644 tests/move_pages--pidns-translation.c create mode 100644 tests/net-sockaddr--pidns-translation.c create mode 100644 tests/netlink_audit--pidns-translation.c create mode 100755 tests/netlink_audit--pidns-translation.test create mode 100644 tests/pidfd_open--pidns-translation.c create mode 100644 tests/pidfd_send_signal--pidns-translation.c create mode 100644 tests/pidns-cache.c create mode 100755 tests/pidns-cache.test create mode 100644 tests/prlimit64--pidns-translation.c create mode 100644 tests/process_vm_readv--pidns-translation.c create mode 100644 tests/process_vm_writev--pidns-translation.c create mode 100644 tests/rt_sigqueueinfo--pidns-translation.c create mode 100644 tests/rt_tgsigqueueinfo--pidns-translation.c create mode 100644 tests/sched_xetaffinity--pidns-translation.c create mode 100644 tests/sched_xetattr--pidns-translation.c create mode 100644 tests/sched_xetparam--pidns-translation.c create mode 100644 tests/sched_xetscheduler--pidns-translation.c create mode 100644 tests/signal_receive--pidns-translation.c create mode 100644 tests/so_peercred--pidns-translation.c create mode 100644 tests/tgkill--pidns-translation.c create mode 100644 tests/tkill--pidns-translation.c create mode 120000 tests/trie.c create mode 100644 tests/trie_test.c create mode 100644 tests/xet_robust_list--pidns-translation.c create mode 100644 tests/xetpgid--pidns-translation.c create mode 100644 tests/xetpriority--pidns-translation.c diff --git a/tests/.gitignore b/tests/.gitignore index 0031d04d..f95fc37c 100644 --- a/tests/.gitignore +++ b/tests/.gitignore @@ -116,7 +116,9 @@ fchown fchown32 fchownat fcntl +fcntl--pidns-translation fcntl64 +fcntl64--pidns-translation fdatasync fflush file_handle @@ -126,6 +128,7 @@ filter-unavailable finit_module flock fork-f +fork--pidns-translation fsconfig fsconfig-P fsmount @@ -168,7 +171,9 @@ getgroups getgroups32 getpeername getpgrp +getpgrp--pidns-translation getpid +getpid--pidns-translation getppid getrandom getresgid @@ -178,8 +183,10 @@ getresuid32 getrlimit getrusage getsid +getsid--pidns-translation getsockname gettid +gettid--pidns-translation getuid getuid32 getxgid @@ -200,6 +207,7 @@ io_uring_register io_uring_setup ioctl ioctl_block +ioctl_block--pidns-translation ioctl_dm ioctl_dm-v ioctl_evdev @@ -275,6 +283,7 @@ ioctl_watchdog ioperm iopl ioprio +ioprio--pidns-translation ioprio-Xabbrev ioprio-Xraw ioprio-Xverbose @@ -299,6 +308,7 @@ ipc_shm-Xverbose is_linux_mips_n64 kcmp kcmp-y +kcmp-y--pidns-translation kern_features kernel_version kernel_version-Xabbrev @@ -311,6 +321,7 @@ keyctl-Xabbrev keyctl-Xraw keyctl-Xverbose kill +kill--pidns-translation kill_child ksysent ksysent.h @@ -340,6 +351,7 @@ memfd_create-Xabbrev memfd_create-Xraw memfd_create-Xverbose migrate_pages +migrate_pages--pidns-translation mincore mkdir mkdirat @@ -371,6 +383,7 @@ move_pages move_pages-Xabbrev move_pages-Xraw move_pages-Xverbose +move_pages--pidns-translation mq mq_sendrecv mq_sendrecv-read @@ -391,6 +404,7 @@ net-packet_mreq-Xabbrev net-packet_mreq-Xraw net-packet_mreq-Xverbose net-sockaddr +net-sockaddr--pidns-translation net-tpacket_req net-tpacket_stats net-tpacket_stats-success @@ -400,6 +414,7 @@ net-yy-inet6 net-yy-netlink net-yy-unix netlink_audit +netlink_audit--pidns-translation netlink_crypto netlink_generic netlink_inet_diag @@ -507,7 +522,10 @@ pidfd_open--decode-fd-socket pidfd_open-P pidfd_open-y pidfd_open-yy +pidfd_open--pidns-translation pidfd_send_signal +pidfd_send_signal--pidns-translation +pidns-cache pipe pipe2 pkey_alloc @@ -546,8 +564,11 @@ printstrn-umoven printstrn-umoven-peekdata printstrn-umoven-undumpable prlimit64 +prlimit64--pidns-translation process_vm_readv +process_vm_readv--pidns-translation process_vm_writev +process_vm_writev--pidns-translation pselect6 ptrace ptrace_syscall_info @@ -597,10 +618,12 @@ rt_sigaction rt_sigpending rt_sigprocmask rt_sigqueueinfo +rt_sigqueueinfo--pidns-translation rt_sigreturn rt_sigsuspend rt_sigtimedwait rt_tgsigqueueinfo +rt_tgsigqueueinfo--pidns-translation run_expect_termsig s390_guarded_storage s390_guarded_storage-v @@ -611,9 +634,13 @@ s390_sthyi-v sched_get_priority_mxx sched_rr_get_interval sched_xetaffinity +sched_xetaffinity--pidns-translation sched_xetattr +sched_xetattr--pidns-translation sched_xetparam +sched_xetparam--pidns-translation sched_xetscheduler +sched_xetscheduler--pidns-translation sched_yield scm_rights scno.h @@ -669,6 +696,7 @@ sigaltstack siginfo signal signal_receive +signal_receive--pidns-translation signalfd4 sigpending sigprocmask @@ -681,6 +709,7 @@ so_peercred so_peercred-Xabbrev so_peercred-Xraw so_peercred-Xverbose +so_peercred--pidns-translation sock_filter-v sock_filter-v-Xabbrev sock_filter-v-Xraw @@ -730,6 +759,7 @@ syslog syslog-success tee tgkill +tgkill--pidns-translation threads-execve threads-execve--quiet-thread-execve threads-execve-q @@ -742,7 +772,9 @@ timerfd_xettime times times-fail tkill +tkill--pidns-translation tracer_ppid_pgid_sid +trie_test truncate truncate64 ugetrlimit @@ -783,9 +815,12 @@ waitpid xattr xattr-strings xet_robust_list +xet_robust_list--pidns-translation xet_thread_area_x86 xetitimer xetpgid +xetpgid--pidns-translation xetpriority +xetpriority--pidns-translation xettimeofday zeroargc diff --git a/tests/Makefile.am b/tests/Makefile.am index 7a583a3a..39d948cf 100644 --- a/tests/Makefile.am +++ b/tests/Makefile.am @@ -66,6 +66,7 @@ libtests_a_SOURCES = \ test_ucopy.h \ tests.h \ tprintf.c \ + trie.c \ # end of libtests_a_SOURCES libtests_a_CPPFLAGS = $(AM_CPPFLAGS) -D_FILE_OFFSET_BITS=64 check_LIBRARIES = libtests.a @@ -109,17 +110,25 @@ check_PROGRAMS = $(PURE_EXECUTABLES) \ delay \ execve-v \ execveat-v \ + fcntl--pidns-translation \ + fcntl64--pidns-translation \ filter_seccomp-flag \ filter_seccomp-perf \ filter-unavailable \ fork-f \ + fork--pidns-translation \ fsync-y \ get_process_reaper \ + getpgrp--pidns-translation \ getpid \ + getpid--pidns-translation \ getppid \ + getsid--pidns-translation \ gettid \ + gettid--pidns-translation \ inject-nf \ int_0x80 \ + ioctl_block--pidns-translation \ ioctl_dm-v \ ioctl_evdev-success \ ioctl_evdev-success-Xabbrev \ @@ -150,18 +159,25 @@ check_PROGRAMS = $(PURE_EXECUTABLES) \ ioctl_v4l2-success-v-Xabbrev \ ioctl_v4l2-success-v-Xraw \ ioctl_v4l2-success-v-Xverbose \ + ioprio--pidns-translation \ is_linux_mips_n64 \ + kcmp-y--pidns-translation \ kill_child \ + kill--pidns-translation \ ksysent \ list_sigaction_signum \ localtime \ looping_threads \ + migrate_pages--pidns-translation \ mmsg-silent \ mmsg_name-v \ + move_pages--pidns-translation \ msg_control-v \ net-accept-connect \ + net-sockaddr--pidns-translation \ net-tpacket_stats-success \ nlattr_ifla_xdp-y \ + netlink_audit--pidns-translation \ netlink_inet_diag \ netlink_netlink_diag \ netlink_unix_diag \ @@ -173,14 +189,20 @@ check_PROGRAMS = $(PURE_EXECUTABLES) \ pc \ perf_event_open_nonverbose \ perf_event_open_unabbrev \ + pidfd_open--pidns-translation \ + pidfd_send_signal--pidns-translation \ + pidns-cache \ poll-P \ ppoll-P \ ppoll-v \ + prlimit64--pidns-translation \ prctl-seccomp-filter-v \ prctl-seccomp-strict \ prctl-spec-inject \ print_maxfd \ print_ppid_tracerpid \ + process_vm_readv--pidns-translation \ + process_vm_writev--pidns-translation \ qual_fault \ qual_inject-error-signal \ qual_inject-retval \ @@ -194,7 +216,13 @@ check_PROGRAMS = $(PURE_EXECUTABLES) \ quotactl-xfs-v \ redirect-fds \ restart_syscall \ + rt_sigqueueinfo--pidns-translation \ + rt_tgsigqueueinfo--pidns-translation \ run_expect_termsig \ + sched_xetaffinity--pidns-translation \ + sched_xetattr--pidns-translation \ + sched_xetparam--pidns-translation \ + sched_xetscheduler--pidns-translation \ scm_rights \ seccomp-filter-v \ seccomp-strict \ @@ -204,25 +232,33 @@ check_PROGRAMS = $(PURE_EXECUTABLES) \ set_sigign \ setpgrp-exec \ signal_receive \ + signal_receive--pidns-translation \ sleep \ stack-fcall \ stack-fcall-attach \ stack-fcall-mangled \ status-none-threads \ status-unfinished-threads \ + so_peercred--pidns-translation \ syslog-success \ + tgkill--pidns-translation \ threads-execve \ threads-execve--quiet-thread-execve \ threads-execve-q \ threads-execve-qq \ threads-execve-qqq \ + tkill--pidns-translation \ tracer_ppid_pgid_sid \ + trie_test \ unblock_reset_raise \ unix-pair-send-recv \ unix-pair-sendto-recvfrom \ vfork-f \ wait4-v \ waitid-v \ + xetpgid--pidns-translation \ + xetpriority--pidns-translation \ + xet_robust_list--pidns-translation \ zeroargc \ # end of check_PROGRAMS @@ -310,6 +346,7 @@ DECODER_TESTS = \ int_0x80.test \ inotify_init-y.test \ ioctl.test \ + ioctl_block--pidns-translation.test \ ioctl_evdev-success.test \ ipc_msgbuf.test \ kern_features-fault.test \ @@ -381,15 +418,19 @@ MISC_TESTS = \ filtering_fd-syntax.test \ filtering_syscall-syntax.test \ first_exec_failure.test \ + fork--pidns-translation.test \ get_regs.test \ + gettid--pidns-translation.test \ inject-nf.test \ interactive_block.test \ kill_child.test \ localtime.test \ looping_threads.test \ + netlink_audit--pidns-translation.test \ opipe.test \ options-syntax.test \ pc.test \ + pidns-cache.test \ printpath-umovestr-legacy.test \ printstrn-umoven-legacy.test \ qual_fault-syntax.test \ @@ -467,6 +508,7 @@ EXTRA_DIST = \ filter_seccomp.in \ filter_seccomp.sh \ filter-unavailable.expected \ + fork--pidns-translation.awk \ fstatat.c \ fstatx.c \ gen_pure_executables.sh \ diff --git a/tests/fcntl--pidns-translation.c b/tests/fcntl--pidns-translation.c new file mode 100644 index 00000000..e249424a --- /dev/null +++ b/tests/fcntl--pidns-translation.c @@ -0,0 +1,2 @@ +#define PIDNS_TRANSLATION +#include "fcntl.c" diff --git a/tests/fcntl-common.c b/tests/fcntl-common.c index 27694326..ec18aa79 100644 --- a/tests/fcntl-common.c +++ b/tests/fcntl-common.c @@ -13,6 +13,8 @@ #include #include #include "flock.h" +#include "pidns.h" +#include "scno.h" #define FILE_LEN 4096 @@ -48,12 +50,14 @@ test_flock_einval(const int cmd, const char *name) fl->l_len = (TYPEOF_FLOCK_OFF_T) 0xdefaced2cafef00dULL; invoke_test_syscall(0, cmd, fl); + pidns_print_leader(); printf("%s(0, %s, {l_type=F_RDLCK, l_whence=SEEK_SET" ", l_start=%jd, l_len=%jd}) = %s\n", TEST_SYSCALL_STR, name, (intmax_t) fl->l_start, (intmax_t) fl->l_len, errstr); void *const bad_addr = (void *) fl + 1; invoke_test_syscall(0, cmd, bad_addr); + pidns_print_leader(); printf("%s(0, %s, %p) = %s\n", TEST_SYSCALL_STR, name, bad_addr, errstr); } @@ -72,12 +76,14 @@ test_flock64_einval(const int cmd, const char *name) fl->l_len = (TYPEOF_FLOCK_OFF_T) 0xdefaced2cafef00dULL; invoke_test_syscall(0, cmd, fl); + pidns_print_leader(); printf("%s(0, %s, {l_type=F_RDLCK, l_whence=SEEK_SET" ", l_start=%jd, l_len=%jd}) = %s\n", TEST_SYSCALL_STR, name, (intmax_t) fl->l_start, (intmax_t) fl->l_len, errstr); void *const bad_addr = (void *) fl + 1; invoke_test_syscall(0, cmd, bad_addr); + pidns_print_leader(); printf("%s(0, %s, %p) = %s\n", TEST_SYSCALL_STR, name, bad_addr, errstr); } @@ -94,6 +100,7 @@ test_flock(void) fl->l_len = FILE_LEN; long rc = invoke_test_syscall(0, F_SETLK, fl); + pidns_print_leader(); printf("%s(0, F_SETLK, {l_type=F_RDLCK, l_whence=SEEK_SET" ", l_start=0, l_len=%d}) = %s\n", TEST_SYSCALL_STR, FILE_LEN, errstr); @@ -101,11 +108,13 @@ test_flock(void) return; invoke_test_syscall(0, F_GETLK, fl); + pidns_print_leader(); printf("%s(0, F_GETLK, {l_type=F_UNLCK, l_whence=SEEK_SET" ", l_start=0, l_len=%d, l_pid=0}) = 0\n", TEST_SYSCALL_STR, FILE_LEN); invoke_test_syscall(0, F_SETLKW, fl); + pidns_print_leader(); printf("%s(0, F_SETLKW, {l_type=F_UNLCK, l_whence=SEEK_SET" ", l_start=0, l_len=%d}) = 0\n", TEST_SYSCALL_STR, FILE_LEN); @@ -124,6 +133,7 @@ test_flock64_ofd(void) fl->l_len = FILE_LEN; long rc = invoke_test_syscall(0, F_OFD_SETLK, fl); + pidns_print_leader(); printf("%s(0, F_OFD_SETLK, {l_type=F_RDLCK, l_whence=SEEK_SET" ", l_start=0, l_len=%d}) = %s\n", TEST_SYSCALL_STR, FILE_LEN, errstr); @@ -131,11 +141,13 @@ test_flock64_ofd(void) return; invoke_test_syscall(0, F_OFD_GETLK, fl); + pidns_print_leader(); printf("%s(0, F_OFD_GETLK, {l_type=F_UNLCK, l_whence=SEEK_SET" ", l_start=0, l_len=%d, l_pid=0}) = 0\n", TEST_SYSCALL_STR, FILE_LEN); invoke_test_syscall(0, F_OFD_SETLKW, fl); + pidns_print_leader(); printf("%s(0, F_OFD_SETLKW, {l_type=F_UNLCK, l_whence=SEEK_SET" ", l_start=0, l_len=%d}) = 0\n", TEST_SYSCALL_STR, FILE_LEN); @@ -167,18 +179,21 @@ test_flock64(void) static long test_f_owner_ex_type_pid(const int cmd, const char *const cmd_name, const int type, const char *const type_name, - pid_t pid) + enum pid_type pid_type, pid_t pid) { TAIL_ALLOC_OBJECT_CONST_PTR(struct_kernel_f_owner_ex, fo); fo->type = type; fo->pid = pid; long rc = invoke_test_syscall(0, cmd, fo); - printf("%s(0, %s, {type=%s, pid=%d}) = %s\n", - TEST_SYSCALL_STR, cmd_name, type_name, fo->pid, errstr); + pidns_print_leader(); + printf("%s(0, %s, {type=%s, pid=%d%s}) = %s\n", + TEST_SYSCALL_STR, cmd_name, type_name, + fo->pid, pidns_pid2str(pid_type), errstr); void *bad_addr = (void *) fo + 1; invoke_test_syscall(0, cmd, bad_addr); + pidns_print_leader(); printf("%s(0, %s, %p) = %s\n", TEST_SYSCALL_STR, cmd_name, bad_addr, errstr); @@ -187,35 +202,35 @@ test_f_owner_ex_type_pid(const int cmd, const char *const cmd_name, static void test_f_owner_ex_umove_or_printaddr(const int type, const char *const type_name, - pid_t pid) + enum pid_type pid_type, pid_t pid) { long rc = test_f_owner_ex_type_pid(ARG_STR(F_SETOWN_EX), - type, type_name, pid); + type, type_name, pid_type, pid); if (!rc) test_f_owner_ex_type_pid(ARG_STR(F_GETOWN_EX), - type, type_name, pid); + type, type_name, pid_type, pid); } static void test_f_owner_ex(void) { - static const struct { + struct { int type; const char *type_name; - pid_t pid[2]; + enum pid_type pid_type; + pid_t pid; } a[] = { - { ARG_STR(F_OWNER_TID), { 1234567890, 20 } }, - { ARG_STR(F_OWNER_PID), { 1298126790, 30 } }, - { ARG_STR(F_OWNER_PGRP), { 1294567890, 40 } } + { ARG_STR(F_OWNER_TID), PT_NONE, 1234567890 }, + { ARG_STR(F_OWNER_PID), PT_NONE, 1234567890 }, + { ARG_STR(F_OWNER_PGRP), PT_NONE, 1234567890 }, + { ARG_STR(F_OWNER_TID), PT_TID, syscall(__NR_gettid) }, + { ARG_STR(F_OWNER_PID), PT_TGID, getpid() }, + { ARG_STR(F_OWNER_PGRP), PT_PGID, getpgid(0) }, }; - for (unsigned int i = 0; i < ARRAY_SIZE(a); i++) { - for (unsigned int j = 0; j < ARRAY_SIZE(a[0].pid); j++) { - test_f_owner_ex_umove_or_printaddr(a[i].type, - a[i].type_name, - a[i].pid[j]); - } - } + for (unsigned int i = 0; i < ARRAY_SIZE(a); i++) + test_f_owner_ex_umove_or_printaddr(a[i].type, a[i].type_name, + a[i].pid_type, a[i].pid); } #endif /* TEST_F_OWNER_EX */ @@ -228,6 +243,23 @@ struct fcntl_cmd_check { void (*print_flags)(long rc); }; +static void +test_xetown(void) +{ + const int pid = getpid(); + const char *pid_str = pidns_pid2str(PT_TGID); + + invoke_test_syscall(0, F_SETOWN, (void *) (intptr_t) pid); + pidns_print_leader(); + printf("%s(0, F_SETOWN, %d%s) = %s\n", + TEST_SYSCALL_STR, pid, pid_str, errstr); + + invoke_test_syscall(0, F_GETOWN, NULL); + pidns_print_leader(); + printf("%s(0, F_GETOWN) = %d%s\n", + TEST_SYSCALL_STR, pid, pid_str); +} + static void print_retval_flags(const struct fcntl_cmd_check *check, long rc) { @@ -243,12 +275,14 @@ static void test_other_set_cmd(const struct fcntl_cmd_check *check) { invoke_test_syscall(check->fd, check->cmd, (void *) check->arg); + pidns_print_leader(); printf("%s(%d, %s, %s) = %s\n", TEST_SYSCALL_STR, check->fd, check->cmd_str, check->arg_str, errstr); /* bad file fd */ invoke_test_syscall(-1, check->cmd, (void *) check->arg); + pidns_print_leader(); printf("%s(-1, %s, %s) = %s\n", TEST_SYSCALL_STR, check->cmd_str, check->arg_str, errstr); @@ -258,12 +292,14 @@ static void test_other_get_cmd(const struct fcntl_cmd_check *check) { long rc = invoke_test_syscall(check->fd, check->cmd, NULL); + pidns_print_leader(); printf("%s(%d, %s) = ", TEST_SYSCALL_STR, check->fd, check->cmd_str); print_retval_flags(check, rc); /* bad file fd */ invoke_test_syscall(-1, check->cmd, NULL); + pidns_print_leader(); printf("%s(-1, %s) = %s\n", TEST_SYSCALL_STR, check->cmd_str, errstr); } @@ -315,7 +351,6 @@ test_fcntl_others(void) { static const struct fcntl_cmd_check set_checks[] = { { 0, ARG_STR(F_SETFD), ARG_STR(FD_CLOEXEC) }, - { 0, ARG_STR(F_SETOWN), ARG_STR(20) }, #ifdef F_SETPIPE_SZ { 0, ARG_STR(F_SETPIPE_SZ), ARG_STR(4097) }, #endif @@ -336,7 +371,6 @@ test_fcntl_others(void) static const struct fcntl_cmd_check get_checks[] = { { 0, ARG_STR(F_GETFD), .print_flags = print_flags_getfd }, { 1, ARG_STR(F_GETFD), .print_flags = print_flags_getfd }, - { 0, ARG_STR(F_GETOWN) }, #ifdef F_GETPIPE_SZ { 0, ARG_STR(F_GETPIPE_SZ) }, #endif @@ -360,6 +394,8 @@ create_sample(void) int main(void) { + PIDNS_TEST_INIT; + create_sample(); test_flock(); test_flock64(); @@ -367,7 +403,9 @@ main(void) test_f_owner_ex(); #endif test_fcntl_others(); + test_xetown(); + pidns_print_leader(); puts("+++ exited with 0 +++"); return 0; } diff --git a/tests/fcntl.c b/tests/fcntl.c index f38b8afb..673c06e4 100644 --- a/tests/fcntl.c +++ b/tests/fcntl.c @@ -24,6 +24,7 @@ test_flock64_undecoded(const int cmd, const char *name) .l_len = 0xdefaced2cafef00dULL }; invoke_test_syscall(0, cmd, &fl); + pidns_print_leader(); printf("%s(0, %s, %p) = %s\n", TEST_SYSCALL_STR, name, &fl, errstr); } diff --git a/tests/fcntl64--pidns-translation.c b/tests/fcntl64--pidns-translation.c new file mode 100644 index 00000000..c6fdadd1 --- /dev/null +++ b/tests/fcntl64--pidns-translation.c @@ -0,0 +1,2 @@ +#define PIDNS_TRANSLATION +#include "fcntl64.c" diff --git a/tests/fcntl64.c b/tests/fcntl64.c index 78e53b0d..f7b3f2fb 100644 --- a/tests/fcntl64.c +++ b/tests/fcntl64.c @@ -27,6 +27,7 @@ test_flock64_lk64(void) fl->l_len = FILE_LEN; long rc = invoke_test_syscall(0, F_SETLK64, fl); + pidns_print_leader(); printf("%s(0, F_SETLK64, {l_type=F_RDLCK, l_whence=SEEK_SET" ", l_start=0, l_len=%d}) = %s\n", TEST_SYSCALL_STR, FILE_LEN, errstr); @@ -35,11 +36,13 @@ test_flock64_lk64(void) return; invoke_test_syscall(0, F_GETLK64, fl); + pidns_print_leader(); printf("%s(0, F_GETLK64, {l_type=F_UNLCK, l_whence=SEEK_SET" ", l_start=0, l_len=%d, l_pid=0}) = 0\n", TEST_SYSCALL_STR, FILE_LEN); invoke_test_syscall(0, F_SETLKW64, fl); + pidns_print_leader(); printf("%s(0, F_SETLKW64, {l_type=F_UNLCK, l_whence=SEEK_SET" ", l_start=0, l_len=%d}) = 0\n", TEST_SYSCALL_STR, FILE_LEN); diff --git a/tests/fork--pidns-translation.awk b/tests/fork--pidns-translation.awk new file mode 100644 index 00000000..ef6858f4 --- /dev/null +++ b/tests/fork--pidns-translation.awk @@ -0,0 +1,15 @@ +/fork/ { + match($0, "([0-9]+) in strace\x27s PID NS", a); + if (a[1]) + fork_pid = a[1] +} + +/exited with 0/ { + if (!exit_pid) + exit_pid = $1 +} + +END { + if (!fork_pid || !exit_pid || fork_pid != exit_pid) + exit 1 +} diff --git a/tests/fork--pidns-translation.c b/tests/fork--pidns-translation.c new file mode 100644 index 00000000..73c39d5d --- /dev/null +++ b/tests/fork--pidns-translation.c @@ -0,0 +1,69 @@ +/* + * Test PID namespace translation + * + * Copyright (c) 2020 ?kos Uzonyi + * All rights reserved. + * + * SPDX-License-Identifier: LGPL-2.1-or-later + */ + +#include "tests.h" +#include "scno.h" +#include "pidns.h" + +#ifdef __NR_fork + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +static int +fork_chain(int depth) +{ + if (!depth) + return 0; + + int pid = syscall(__NR_fork); + if (pid < 0) + return errno; + + if (!pid) + _exit(fork_chain(depth - 1)); + + int status; + if (wait(&status) < 0) + return errno; + + if (!WIFEXITED(status)) + return -1; + + return WEXITSTATUS(status); +} + +int main(void) +{ + check_ns_ioctl(); + + if (unshare(CLONE_NEWPID | CLONE_NEWUSER) < 0) { + if (errno == EPERM) + perror_msg_and_skip("unshare"); + + perror_msg_and_fail("unshare"); + } + + errno = fork_chain(2); + if (errno) + perror("fork_chain"); +} + +#else + +SKIP_MAIN_UNDEFINED("__NR_fork") + +#endif diff --git a/tests/fork--pidns-translation.test b/tests/fork--pidns-translation.test new file mode 100755 index 00000000..24cc5930 --- /dev/null +++ b/tests/fork--pidns-translation.test @@ -0,0 +1,14 @@ +#!/bin/sh +# +# Check pidns translation of fork's return value. +# +# Copyright (c) 2020 The strace developers. +# All rights reserved. +# +# SPDX-License-Identifier: LGPL-2.1-or-later + +. "${srcdir=.}/init.sh" + +run_prog +run_strace -a6 --pidns-translation -f -e trace=fork $args +match_awk diff --git a/tests/gen_tests.in b/tests/gen_tests.in index 6f8e1420..e59a2f7f 100644 --- a/tests/gen_tests.in +++ b/tests/gen_tests.in @@ -93,7 +93,9 @@ fchown -a16 fchown32 -a18 fchownat fcntl -a8 +fcntl--pidns-translation test_pidns -a8 -e trace=fcntl fcntl64 -a8 +fcntl64--pidns-translation test_pidns -a8 -e trace=fcntl64 fdatasync -a14 file_handle -e trace=name_to_handle_at,open_by_handle_at file_ioctl +ioctl.test @@ -147,7 +149,9 @@ getgroups -a17 getgroups32 -a19 getpeername -a27 getpgrp -a10 +getpgrp--pidns-translation test_pidns -e trace=getpgrp -a10 getpid -a9 +getpid--pidns-translation test_pidns -e trace=getpid -a9 getppid -a10 getrandom -a32 -s3 getresgid -a25 @@ -157,6 +161,7 @@ getresuid32 -a27 getrlimit -a27 getrusage -v getsid -a10 +getsid--pidns-translation test_pidns -e trace=getsid -a10 getsockname -a27 gettid -a9 getuid-creds +getuid.test @@ -250,6 +255,7 @@ ioctl_watchdog +ioctl.test ioperm -a27 iopl -a8 ioprio -a18 -e trace=ioprio_get,ioprio_set +ioprio--pidns-translation test_pidns -a18 -e trace=ioprio_get,ioprio_set ioprio-Xabbrev -a18 -e trace=ioprio_get,ioprio_set -Xabbrev ioprio-Xraw -a18 -e trace=ioprio_get,ioprio_set -Xraw ioprio-Xverbose -a18 -e trace=ioprio_get,ioprio_set -Xverbose @@ -272,6 +278,7 @@ ipc_shm-Xraw +ipc.sh -Xraw -a19 ipc_shm-Xverbose +ipc.sh -Xverbose -a34 kcmp -a22 kcmp-y -a22 -y -e trace=kcmp +kcmp-y--pidns-translation test_pidns -a22 -y -e trace=kcmp kern_features -a16 kernel_version -a16 -v -e trace=bpf kernel_version-Xabbrev -a16 -Xabbrev -v -e trace=bpf @@ -284,6 +291,7 @@ keyctl-Xabbrev -a31 -s10 -e trace=keyctl -Xabbrev keyctl-Xraw -a13 -s10 -e trace=keyctl -Xraw keyctl-Xverbose -a41 -s10 -e trace=keyctl -Xverbose kill -a12 -esignal=none +kill--pidns-translation test_pidns -a12 -e trace=kill -esignal=none ksysent ../$NAME lchown -a30 lchown32 -a32 @@ -305,6 +313,7 @@ memfd_create-Xabbrev -Xabbrev -e trace=memfd_create memfd_create-Xraw -a30 -Xraw -e trace=memfd_create memfd_create-Xverbose -Xverbose -e trace=memfd_create migrate_pages -a33 +migrate_pages--pidns-translation test_pidns -a33 -e trace=migrate_pages mincore -a22 mkdir -a20 mkdirat -a28 @@ -335,6 +344,7 @@ move_pages -s3 move_pages-Xabbrev -s3 -e trace=move_pages -Xabbrev move_pages-Xraw -s3 -a36 -e trace=move_pages -Xraw move_pages-Xverbose -s3 -e trace=move_pages -Xverbose +move_pages--pidns-translation test_pidns -s3 -e trace=move_pages mq -a32 -e trace=mq_getsetattr,mq_open,mq_unlink mq_sendrecv -a14 -e trace=mq_open,mq_notify,mq_timedsend,mq_timedreceive,mq_unlink mq_sendrecv-read -eread=0 -a14 -e trace=mq_open,mq_notify,mq_timedsend,mq_timedreceive,mq_unlink @@ -354,6 +364,7 @@ net-packet_mreq-Xabbrev -e trace=setsockopt -Xabbrev net-packet_mreq-Xraw -e trace=setsockopt -Xraw net-packet_mreq-Xverbose -e trace=setsockopt -Xverbose net-sockaddr -a24 -e trace=connect +net-sockaddr--pidns-translation test_pidns -a24 -e trace=connect net-tpacket_req -e trace=setsockopt net-tpacket_stats -e trace=getsockopt net-yy-inet6 +net-yy-inet.test @@ -457,7 +468,9 @@ pidfd_open--decode-fd-socket -a17 -e decode-fd=socket -e trace=pidfd_open pidfd_open-P -a17 -P /dev/full -e trace=pidfd_open pidfd_open-y -a17 -y -e trace=pidfd_open pidfd_open-yy -a17 -yy -e trace=pidfd_open +pidfd_open--pidns-translation test_pidns -a17 -e trace=pidfd_open pidfd_send_signal +pidfd_send_signal--pidns-translation test_pidns -e trace=pidfd_send_signal pipe2 -a15 pkey_alloc -a17 pkey_free -a13 @@ -480,8 +493,11 @@ printstrn-umoven -s4096 -e signal=none -e trace=add_key printstrn-umoven-peekdata -e signal=none -e trace=add_key printstrn-umoven-undumpable -e signal=none -e trace=add_key prlimit64 +prlimit64--pidns-translation test_pidns -e trace=prlimit64 process_vm_readv -s5 -a37 +process_vm_readv--pidns-translation test_pidns -s5 -a37 -e trace=process_vm_readv process_vm_writev -s5 -a38 +process_vm_writev--pidns-translation test_pidns -s5 -a38 -e trace=process_vm_writev pselect6 ptrace -a23 -e signal=none ptrace_syscall_info -a35 -e signal=none -e trace=ptrace @@ -518,10 +534,12 @@ rmdir -a22 rt_sigpending -a20 rt_sigprocmask rt_sigqueueinfo -esignal=none +rt_sigqueueinfo--pidns-translation test_pidns -esignal=none -e trace=rt_sigqueueinfo rt_sigreturn -esignal='!USR1' rt_sigsuspend -a20 -esignal=none rt_sigtimedwait -a38 rt_tgsigqueueinfo -esignal=none +rt_tgsigqueueinfo--pidns-translation test_pidns -esignal=none -e trace=rt_tgsigqueueinfo s390_guarded_storage -a32 s390_guarded_storage-v -e trace=s390_guarded_storage -a32 -v s390_pci_mmio_read_write -e trace=s390_pci_mmio_read,s390_pci_mmio_write -a30 @@ -532,9 +550,13 @@ sched test_trace_expr times -e/sched sched_get_priority_mxx -a33 -e trace=sched_get_priority_min,sched_get_priority_max sched_rr_get_interval -a31 sched_xetaffinity -a28 -e trace=sched_getaffinity,sched_setaffinity +sched_xetaffinity--pidns-translation test_pidns -a28 -e trace=sched_getaffinity,sched_setaffinity sched_xetattr -a29 -e trace=sched_getattr,sched_setattr +sched_xetattr--pidns-translation test_pidns -a29 -e trace=sched_getattr,sched_setattr sched_xetparam -a23 -e trace=sched_getparam,sched_setparam +sched_xetparam--pidns-translation test_pidns -a23 -e trace=sched_getparam,sched_setparam sched_xetscheduler -a22 -e trace=sched_getscheduler,sched_setscheduler +sched_xetscheduler--pidns-translation test_pidns -a22 -e trace=sched_getscheduler,sched_setscheduler sched_yield -a14 seccomp-filter -e trace=seccomp seccomp-filter-v -v -e trace=seccomp @@ -581,6 +603,7 @@ sigaction -a31 siginfo -e trace=none signal -a25 -e signal=none -e trace='/^signal$' signal_receive -a16 -e trace=kill +signal_receive--pidns-translation test_pidns -a16 -e trace=kill signalfd4 sigpending -a15 sigprocmask -a34 @@ -592,6 +615,7 @@ so_peercred -e trace=getsockopt so_peercred-Xabbrev -e trace=getsockopt -Xabbrev so_peercred-Xraw -e trace=getsockopt -Xraw -a39 so_peercred-Xverbose -e trace=getsockopt -Xverbose +so_peercred--pidns-translation test_pidns -e trace=getsockopt sock_filter-v -v -e trace=getsockopt,setsockopt sock_filter-v-Xabbrev -v -e trace=getsockopt,setsockopt -X abbrev sock_filter-v-Xraw -a 37 -v -e trace=getsockopt,setsockopt -X raw @@ -664,6 +688,7 @@ sysinfo -a14 syslog -a35 tee tgkill -a15 --signal='!cont' +tgkill--pidns-translation test_pidns -a15 --signal='!cont' -e trace=tgkill threads-execve--quiet-thread-execve +threads-execve.test -s40 --quiet=personality,thread-execve threads-execve-q +threads-execve.test -q threads-execve-qq +threads-execve.test -qq @@ -675,6 +700,7 @@ timerfd_xettime -e trace=timerfd_create,timerfd_settime,timerfd_gettime times -esignal=none times-fail -a12 -e trace=times tkill -a12 --signal='!cont' +tkill--pidns-translation test_pidns --signal='!cont' -a12 -e trace=tkill trace_clock test_trace_expr 'clock_nanosleep|times' -e%clock trace_creds test_trace_expr '([gs]et[^p]*([gu]id|groups)|caps|prctl|[fl]?chown|print(path-umovestr|strn-umoven)-undumpable|ptrace|quotactl|rt_sigtimedwait|rt_(tg)?sigqueueinfo).*' -e%creds trace_fstat test_trace_expr '' -e%fstat -v -P stat.sample -P /dev/full @@ -691,6 +717,7 @@ trace_stat test_trace_expr '' -e%stat -v -P stat.sample -P /dev/full trace_stat_like test_trace_expr '' -e%%stat -v -P stat.sample -P /dev/full trace_statfs test_trace_expr '' -e%statfs trace_statfs_like test_trace_expr '' -e%%statfs +trie_test run_prog truncate truncate64 ugetrlimit -a28 @@ -721,7 +748,10 @@ waitpid -a28 xattr -a22 -e trace=getxattr,fgetxattr,lgetxattr,setxattr,fsetxattr,lsetxattr,listxattr,flistxattr,llistxattr,removexattr,fremovexattr,lremovexattr xattr-strings -a22 -s 4 -e trace=fsetxattr xet_robust_list -a24 -e trace=get_robust_list,set_robust_list +xet_robust_list--pidns-translation test_pidns -a24 -e trace=get_robust_list,set_robust_list xetitimer -a29 -e trace=setitimer,getitimer xetpgid -a11 -e trace=getpgid,setpgid -xetpriority -a29 -e trace=getpriority,setpriority +xetpgid--pidns-translation test_pidns -a11 -e trace=getpgid,setpgid +xetpriority -a27 -e trace=getpriority,setpriority +xetpriority--pidns-translation test_pidns -a27 -e trace=getpriority,setpriority xettimeofday -a20 -e trace=gettimeofday,settimeofday diff --git a/tests/getpgrp--pidns-translation.c b/tests/getpgrp--pidns-translation.c new file mode 100644 index 00000000..de8ceb33 --- /dev/null +++ b/tests/getpgrp--pidns-translation.c @@ -0,0 +1,2 @@ +#define PIDNS_TRANSLATION +#include "getpgrp.c" diff --git a/tests/getpgrp.c b/tests/getpgrp.c index 104f4811..3f0b9dd1 100644 --- a/tests/getpgrp.c +++ b/tests/getpgrp.c @@ -7,6 +7,7 @@ #include "tests.h" #include "scno.h" +#include "pidns.h" #ifdef __NR_getpgrp @@ -16,8 +17,13 @@ int main(void) { - printf("getpgrp() = %ld\n", syscall(__NR_getpgrp)); + PIDNS_TEST_INIT; + pidns_print_leader(); + printf("getpgrp() = %d%s\n", (int) syscall(__NR_getpgrp), + pidns_pid2str(PT_PGID)); + + pidns_print_leader(); puts("+++ exited with 0 +++"); return 0; } diff --git a/tests/getpid--pidns-translation.c b/tests/getpid--pidns-translation.c new file mode 100644 index 00000000..94b12a1a --- /dev/null +++ b/tests/getpid--pidns-translation.c @@ -0,0 +1,2 @@ +#define PIDNS_TRANSLATION +#include "getpid.c" diff --git a/tests/getpid.c b/tests/getpid.c index 988f19d5..7ec4e6e8 100644 --- a/tests/getpid.c +++ b/tests/getpid.c @@ -7,6 +7,7 @@ #include "tests.h" #include "scno.h" +#include "pidns.h" #if defined __NR_getpid && (!defined __NR_getxpid || __NR_getxpid != __NR_getpid) @@ -16,7 +17,12 @@ int main(void) { - printf("getpid() = %ld\n", syscall(__NR_getpid)); + PIDNS_TEST_INIT; + + pidns_print_leader(); + printf("getpid() = %d%s\n", (int) syscall(__NR_getpid), + pidns_pid2str(PT_TGID)); + pidns_print_leader(); puts("+++ exited with 0 +++"); return 0; } diff --git a/tests/getsid--pidns-translation.c b/tests/getsid--pidns-translation.c new file mode 100644 index 00000000..7f983e87 --- /dev/null +++ b/tests/getsid--pidns-translation.c @@ -0,0 +1,2 @@ +#define PIDNS_TRANSLATION +#include "getsid.c" diff --git a/tests/getsid.c b/tests/getsid.c index 588ea4ab..3bf74734 100644 --- a/tests/getsid.c +++ b/tests/getsid.c @@ -6,15 +6,22 @@ */ #include "tests.h" +#include "pidns.h" + #include #include int main(void) { + PIDNS_TEST_INIT; + pid_t pid = getpid(); - printf("getsid(%d) = %d\n", pid, getsid(pid)); + pidns_print_leader(); + printf("getsid(%d%s) = %d%s\n", pid, pidns_pid2str(PT_TGID), + getsid(pid), pidns_pid2str(PT_SID)); + pidns_print_leader(); puts("+++ exited with 0 +++"); return 0; } diff --git a/tests/gettid--pidns-translation.c b/tests/gettid--pidns-translation.c new file mode 100644 index 00000000..500c3213 --- /dev/null +++ b/tests/gettid--pidns-translation.c @@ -0,0 +1,2 @@ +#define PIDNS_TRANSLATION +#include "gettid.c" diff --git a/tests/gettid--pidns-translation.test b/tests/gettid--pidns-translation.test new file mode 100755 index 00000000..9624129e --- /dev/null +++ b/tests/gettid--pidns-translation.test @@ -0,0 +1,18 @@ +#!/bin/sh +# +# Check pidns translation of gettid's return value. +# +# Copyright (c) 2020 The strace developers. +# All rights reserved. +# +# SPDX-License-Identifier: LGPL-2.1-or-later + +. "${srcdir=.}/init.sh" + +run_prog > /dev/null +run_strace -a9 --pidns-translation -f -e trace=gettid $args > "$EXP" +parent_pid="$(tail -n 2 $LOG | head -n 1 | cut -d' ' -f1)" +init_pid="$(tail -n 1 $LOG | cut -d' ' -f1)" +# uniq: filter out extra gettid calls made by musl libc +grep -E -v "^($parent_pid|$init_pid) |unfinished|resumed" "$LOG" | uniq > "$OUT" +match_diff "$OUT" "$EXP" diff --git a/tests/gettid.c b/tests/gettid.c index d38918dd..314d9c2c 100644 --- a/tests/gettid.c +++ b/tests/gettid.c @@ -9,11 +9,17 @@ #include #include #include "scno.h" +#include "pidns.h" int main(void) { - printf("gettid() = %ld\n", syscall(__NR_gettid)); + PIDNS_TEST_INIT; + + pidns_print_leader(); + printf("gettid() = %d%s\n", (int) syscall(__NR_gettid), + pidns_pid2str(PT_TID)); + pidns_print_leader(); puts("+++ exited with 0 +++"); return 0; } diff --git a/tests/ioctl_block--pidns-translation.c b/tests/ioctl_block--pidns-translation.c new file mode 100644 index 00000000..5eed6076 --- /dev/null +++ b/tests/ioctl_block--pidns-translation.c @@ -0,0 +1,2 @@ +#define PIDNS_TRANSLATION +#include "ioctl_block.c" diff --git a/tests/ioctl_block--pidns-translation.test b/tests/ioctl_block--pidns-translation.test new file mode 100755 index 00000000..d06855f9 --- /dev/null +++ b/tests/ioctl_block--pidns-translation.test @@ -0,0 +1,22 @@ +#!/bin/sh +# +# Check pidns translation of ioctl(BLK*) syscall decoding. +# +# Copyright (c) 2020 The strace developers. +# All rights reserved. +# +# SPDX-License-Identifier: LGPL-2.1-or-later + +. "${srcdir=.}/init.sh" + +check_prog head +check_prog tail +check_prog cut +check_prog grep + +run_prog > /dev/null +run_strace --pidns-translation -f -a16 -e trace=ioctl $@ $args > "$EXP" +parent_pid="$(tail -n 2 $LOG | head -n 1 | cut -d' ' -f1)" +init_pid="$(tail -n 1 $LOG | cut -d' ' -f1)" +grep -E -v "^($parent_pid|$init_pid) |ioctl\([0123][,<]" "$LOG" > "$OUT" +match_diff "$OUT" "$EXP" diff --git a/tests/ioctl_block.c b/tests/ioctl_block.c index 0afe27f7..8a345f4e 100644 --- a/tests/ioctl_block.c +++ b/tests/ioctl_block.c @@ -9,7 +9,9 @@ */ #include "tests.h" +#include "pidns.h" #include +#include #include #include #include @@ -41,12 +43,15 @@ static struct xlat_data block_argless[] = { #define TEST_NULL_ARG(cmd) \ do { \ ioctl(-1, cmd, 0); \ + pidns_print_leader(); \ printf("ioctl(-1, %s, NULL) = -1 EBADF (%m)\n", #cmd); \ } while (0) int main(void) { + PIDNS_TEST_INIT; + TEST_NULL_ARG(BLKBSZGET); TEST_NULL_ARG(BLKBSZSET); TEST_NULL_ARG(BLKFRAGET); @@ -91,18 +96,22 @@ main(void) #endif ioctl(-1, BLKRASET, lmagic); + pidns_print_leader(); printf("ioctl(-1, BLKRASET, %lu) = -1 EBADF (%m)\n", lmagic); ioctl(-1, BLKFRASET, lmagic); + pidns_print_leader(); printf("ioctl(-1, BLKFRASET, %lu) = -1 EBADF (%m)\n", lmagic); TAIL_ALLOC_OBJECT_CONST_PTR(int, val_int); *val_int = magic; ioctl(-1, BLKROSET, val_int); + pidns_print_leader(); printf("ioctl(-1, BLKROSET, [%d]) = -1 EBADF (%m)\n", *val_int); ioctl(-1, BLKBSZSET, val_int); + pidns_print_leader(); printf("ioctl(-1, BLKBSZSET, [%d]) = -1 EBADF (%m)\n", *val_int); uint64_t *pair_int64 = tail_alloc(sizeof(*pair_int64) * 2); @@ -111,18 +120,21 @@ main(void) #ifdef BLKDISCARD ioctl(-1, BLKDISCARD, pair_int64); + pidns_print_leader(); printf("ioctl(-1, BLKDISCARD, [%" PRIu64 ", %" PRIu64 "])" " = -1 EBADF (%m)\n", pair_int64[0], pair_int64[1]); #endif #ifdef BLKSECDISCARD ioctl(-1, BLKSECDISCARD, pair_int64); + pidns_print_leader(); printf("ioctl(-1, BLKSECDISCARD, [%" PRIu64 ", %" PRIu64 "])" " = -1 EBADF (%m)\n", pair_int64[0], pair_int64[1]); #endif #ifdef BLKZEROOUT ioctl(-1, BLKZEROOUT, pair_int64); + pidns_print_leader(); printf("ioctl(-1, BLKZEROOUT, [%" PRIu64 ", %" PRIu64 "])" " = -1 EBADF (%m)\n", pair_int64[0], pair_int64[1]); #endif @@ -134,6 +146,7 @@ main(void) blkpg->data = (void *) (unsigned long) 0xcafef00dfffffeedULL; ioctl(-1, BLKPG, blkpg); + pidns_print_leader(); printf("ioctl(-1, BLKPG, {op=%s, flags=%d, datalen=%d" ", data=%#lx}) = -1 EBADF (%m)\n", "BLKPG_RESIZE_PARTITION", blkpg->flags, blkpg->datalen, @@ -149,6 +162,7 @@ main(void) blkpg->data = bp; ioctl(-1, BLKPG, blkpg); + pidns_print_leader(); printf("ioctl(-1, BLKPG, {op=%s, flags=%d, datalen=%d" ", data={start=%lld, length=%lld, pno=%d" ", devname=\"%.*s\"..., volname=\"%.*s\"...}})" @@ -162,25 +176,31 @@ main(void) #if defined BLKTRACESETUP && defined HAVE_STRUCT_BLK_USER_TRACE_SETUP TAIL_ALLOC_OBJECT_CONST_PTR(struct blk_user_trace_setup, buts); fill_memory(buts, sizeof(*buts)); + buts->pid = getpid(); ioctl(-1, BLKTRACESETUP, buts); + pidns_print_leader(); printf("ioctl(-1, BLKTRACESETUP, {act_mask=%hu, buf_size=%u, buf_nr=%u" - ", start_lba=%" PRI__u64 ", end_lba=%" PRI__u64 ", pid=%d})" + ", start_lba=%" PRI__u64 ", end_lba=%" PRI__u64 ", pid=%d%s})" " = -1 EBADF (%m)\n", buts->act_mask, buts->buf_size, buts->buf_nr, - buts->start_lba, buts->end_lba, buts->pid); + buts->start_lba, buts->end_lba, buts->pid, + pidns_pid2str(PT_TGID)); #endif unsigned int i; for (i = 0; i < ARRAY_SIZE(block_argless); ++i) { ioctl(-1, (unsigned long) block_argless[i].val, lmagic); + pidns_print_leader(); printf("ioctl(-1, %s) = -1 EBADF (%m)\n", block_argless[i].str); } ioctl(-1, _IOC(_IOC_READ, 0x12, 0xfe, 0xff), lmagic); + pidns_print_leader(); printf("ioctl(-1, %s, %#lx) = -1 EBADF (%m)\n", "_IOC(_IOC_READ, 0x12, 0xfe, 0xff)", lmagic); + pidns_print_leader(); puts("+++ exited with 0 +++"); return 0; } diff --git a/tests/ioprio--pidns-translation.c b/tests/ioprio--pidns-translation.c new file mode 100644 index 00000000..bcb49a8b --- /dev/null +++ b/tests/ioprio--pidns-translation.c @@ -0,0 +1,2 @@ +#define PIDNS_TRANSLATION +#include "ioprio.c" diff --git a/tests/ioprio.c b/tests/ioprio.c index 5e1e1194..110df063 100644 --- a/tests/ioprio.c +++ b/tests/ioprio.c @@ -9,8 +9,8 @@ */ #include "tests.h" - #include "scno.h" +#include "pidns.h" #if defined(__NR_ioprio_get) && defined(__NR_ioprio_set) @@ -30,12 +30,18 @@ enum { int main(void) { + PIDNS_TEST_INIT; + static const kernel_ulong_t bogus_which = (kernel_ulong_t) 0xdeadfacefa57beefULL; static const kernel_ulong_t bogus_who = (kernel_ulong_t) 0xbadc0dedda7a1057ULL; static const kernel_ulong_t bogus_ioprio = (kernel_ulong_t) 0xdec0ded1facefeedULL; + + const int pid = getpid(); + const int pgid = getpgid(0); + # if !XLAT_RAW static const char * const bogus_ioprio_str = "IOPRIO_PRIO_VALUE(0x7d677 /* IOPRIO_CLASS_??? */, 7917)"; @@ -46,6 +52,7 @@ main(void) rc = syscall(__NR_ioprio_get, bogus_which, bogus_who); errstr = sprintrc(rc); + pidns_print_leader(); # if XLAT_RAW printf("ioprio_get(%#x, %d) = %s\n", (int) bogus_which, (int) bogus_who, errstr); @@ -54,42 +61,52 @@ main(void) (int) bogus_which, (int) bogus_who, errstr); # endif - rc = syscall(__NR_ioprio_get, 1, 0); + rc = syscall(__NR_ioprio_get, 1, pid); errstr = sprintrc(rc); + pidns_print_leader(); + printf("ioprio_get("); # if XLAT_RAW - printf("ioprio_get(0x1, 0) = %s\n", errstr); + printf("0x1, "); +# elif XLAT_VERBOSE + printf("0x1 /* IOPRIO_WHO_PROCESS */, "); # else /* XLAT_ABBREV */ -# if XLAT_VERBOSE - printf("ioprio_get(0x1 /* IOPRIO_WHO_PROCESS */, 0) = %s", errstr); -# else - printf("ioprio_get(IOPRIO_WHO_PROCESS, 0) = %s", errstr); -# endif + printf("IOPRIO_WHO_PROCESS, "); +# endif + printf("%d%s) = %s", pid, pidns_pid2str(PT_TGID), errstr); +# if !XLAT_RAW if (rc >= 0) { printf(" (IOPRIO_PRIO_VALUE("); printxval(ioprio_class, (unsigned int) rc >> 13, "IOPRIO_CLASS_???"); printf(", %u))", (unsigned int) rc & 0x1fff); } - puts(""); # endif + puts(""); - rc = syscall(__NR_ioprio_set, 2, 0, 8191); + rc = syscall(__NR_ioprio_set, 2, pgid, 8191); errstr = sprintrc(rc); + pidns_print_leader(); + printf("ioprio_set("); # if XLAT_RAW - printf("ioprio_set(%#x, 0, 8191) = %s\n", 2, errstr); + printf("%#x", 2); # elif XLAT_VERBOSE - printf("ioprio_set(%#x /* IOPRIO_WHO_PGRP */, 0, 8191" - " /* IOPRIO_PRIO_VALUE(0 /* IOPRIO_CLASS_NONE */, 8191) */)" - " = %s\n", - 2, errstr); + printf("%#x /* IOPRIO_WHO_PGRP */", 2); # else /* XLAT_ABBREV */ - printf("ioprio_set(IOPRIO_WHO_PGRP, 0" - ", IOPRIO_PRIO_VALUE(IOPRIO_CLASS_NONE, 8191)) = %s\n", - errstr); + printf("IOPRIO_WHO_PGRP"); +# endif + printf(", %d%s", pgid, pidns_pid2str(PT_PGID)); +# if XLAT_RAW + printf(", 8191)"); +# elif XLAT_VERBOSE + printf(", 8191 /* IOPRIO_PRIO_VALUE(0 /* IOPRIO_CLASS_NONE */, 8191) */)"); +# else /* XLAT_ABBREV */ + printf(", IOPRIO_PRIO_VALUE(IOPRIO_CLASS_NONE, 8191))"); # endif + printf(" = %s\n", errstr); rc = syscall(__NR_ioprio_set, bogus_which, bogus_who, bogus_ioprio); errstr = sprintrc(rc); + pidns_print_leader(); # if XLAT_RAW printf("ioprio_set(%#x, %d, %d) = %s\n", (int) bogus_which, (int) bogus_who, (int) bogus_ioprio, @@ -104,6 +121,7 @@ main(void) errstr); # endif + pidns_print_leader(); puts("+++ exited with 0 +++"); return 0; diff --git a/tests/kcmp-y--pidns-translation.c b/tests/kcmp-y--pidns-translation.c new file mode 100644 index 00000000..f54d94cc --- /dev/null +++ b/tests/kcmp-y--pidns-translation.c @@ -0,0 +1,2 @@ +#define PIDNS_TRANSLATION +#include "kcmp-y.c" diff --git a/tests/kcmp.c b/tests/kcmp.c index dc5ba9a4..ce705ad0 100644 --- a/tests/kcmp.c +++ b/tests/kcmp.c @@ -9,8 +9,8 @@ */ #include "tests.h" - #include "scno.h" +#include "pidns.h" #ifdef __NR_kcmp @@ -101,7 +101,11 @@ do_kcmp(kernel_ulong_t pid1, kernel_ulong_t pid2, kernel_ulong_t type, rc = syscall(__NR_kcmp, pid1, pid2, type, idx1, idx2); errstr = sprintrc(rc); - printf("kcmp(%d, %d, ", (int) pid1, (int) pid2); + const char *pid_str = pidns_pid2str(PT_TGID); + pidns_print_leader(); + printf("kcmp(%d%s, %d%s, ", + (int) pid1, (int) pid1 == getpid() ? pid_str : "", + (int) pid2, (int) pid2 == getpid() ? pid_str : ""); if (type_str) printf("%s", type_str); @@ -146,6 +150,8 @@ do_kcmp(kernel_ulong_t pid1, kernel_ulong_t pid2, kernel_ulong_t type, int main(void) { + PIDNS_TEST_INIT; + static const kernel_ulong_t bogus_pid1 = (kernel_ulong_t) 0xdeadca75face1057ULL; static const kernel_ulong_t bogus_pid2 = @@ -221,6 +227,7 @@ main(void) (uintptr_t) slot, 1); } + pidns_print_leader(); puts("+++ exited with 0 +++"); return 0; diff --git a/tests/kill--pidns-translation.c b/tests/kill--pidns-translation.c new file mode 100644 index 00000000..4736ca14 --- /dev/null +++ b/tests/kill--pidns-translation.c @@ -0,0 +1,2 @@ +#define PIDNS_TRANSLATION +#include "kill.c" diff --git a/tests/kill.c b/tests/kill.c index f7d9341e..17de35da 100644 --- a/tests/kill.c +++ b/tests/kill.c @@ -11,6 +11,7 @@ #include "tests.h" #include "scno.h" +#include "pidns.h" #ifdef __NR_kill @@ -26,6 +27,8 @@ handler(int sig) int main(void) { + PIDNS_TEST_INIT; + const struct sigaction act = { .sa_handler = handler }; if (sigaction(SIGALRM, &act, NULL)) perror_msg_and_fail("sigaction"); @@ -37,18 +40,23 @@ main(void) perror_msg_and_fail("sigprocmask"); const int pid = getpid(); + const char *pid_str = pidns_pid2str(PT_TGID); long rc = syscall(__NR_kill, pid, (long) 0xdefaced00000000ULL | SIGALRM); - printf("kill(%d, SIGALRM) = %ld\n", pid, rc); + pidns_print_leader(); + printf("kill(%d%s, SIGALRM) = %ld\n", pid, pid_str, rc); const long big_pid = (long) 0xfacefeedbadc0dedULL; const long big_sig = (long) 0xdeadbeefcafef00dULL; rc = syscall(__NR_kill, big_pid, big_sig); + pidns_print_leader(); printf("kill(%d, %d) = %ld %s (%m)\n", (int) big_pid, (int) big_sig, rc, errno2name()); rc = syscall(__NR_kill, (long) 0xdefaced00000000ULL | pid, 0); - printf("kill(%d, 0) = %ld\n", pid, rc); + pidns_print_leader(); + printf("kill(%d%s, 0) = %ld\n", pid, pid_str, rc); + pidns_print_leader(); puts("+++ exited with 0 +++"); return 0; } diff --git a/tests/migrate_pages--pidns-translation.c b/tests/migrate_pages--pidns-translation.c new file mode 100644 index 00000000..ec34938d --- /dev/null +++ b/tests/migrate_pages--pidns-translation.c @@ -0,0 +1,2 @@ +#define PIDNS_TRANSLATION +#include "migrate_pages.c" diff --git a/tests/migrate_pages.c b/tests/migrate_pages.c index 2dfba49c..390b490b 100644 --- a/tests/migrate_pages.c +++ b/tests/migrate_pages.c @@ -10,6 +10,7 @@ #include "tests.h" #include "scno.h" +#include "pidns.h" #ifdef __NR_migrate_pages @@ -19,11 +20,21 @@ int main(void) { - const long pid = (long) 0xfacefeedffffffffULL; + PIDNS_TEST_INIT; + + const long pid = (long) 0xfacefeed00000000ULL | getpid(); long rc = syscall(__NR_migrate_pages, pid, 0, 0, 0); - printf("migrate_pages(%d, 0, NULL, NULL) = %ld %s (%m)\n", - (int) pid, rc, errno2name()); + pidns_print_leader(); + printf("migrate_pages(%d%s, 0, NULL, NULL) = %ld", + (int) pid, pidns_pid2str(PT_TGID), rc); + + if (rc < 0) + printf(" %s (%m)\n", errno2name()); + else + printf("\n"); + + pidns_print_leader(); puts("+++ exited with 0 +++"); return 0; } diff --git a/tests/move_pages--pidns-translation.c b/tests/move_pages--pidns-translation.c new file mode 100644 index 00000000..8498e399 --- /dev/null +++ b/tests/move_pages--pidns-translation.c @@ -0,0 +1,2 @@ +#define PIDNS_TRANSLATION +#include "move_pages.c" diff --git a/tests/move_pages.c b/tests/move_pages.c index e00fd1ac..56843158 100644 --- a/tests/move_pages.c +++ b/tests/move_pages.c @@ -10,6 +10,7 @@ #include "tests.h" #include "scno.h" +#include "pidns.h" #ifdef __NR_move_pages @@ -122,15 +123,20 @@ print_status_array(const int *const status, const unsigned long count) } static void -print_stat_pages(const unsigned long pid, const unsigned long count, - const void **const pages, int *const status) +print_stat_pages(const unsigned long pid, + const char *pid_str, + const unsigned long count, + const void **const pages, + int *const status) { const unsigned long flags = (unsigned long) 0xfacefeed00000002ULL; long rc = syscall(__NR_move_pages, pid, count, pages, NULL, status, flags); const char *errstr = sprintrc(rc); - printf("move_pages(%d, %lu, ", (int) pid, count); + pidns_print_leader(); + printf("move_pages(%d%s, %lu, ", (int) pid, pid_str, + count); print_page_array(pages, count, 0); printf(", NULL, "); if (rc) { @@ -152,6 +158,7 @@ print_stat_pages(const unsigned long pid, const unsigned long count, static void print_move_pages(const unsigned long pid, + const char *pid_str, unsigned long count, const unsigned int offset, const void **const pages, @@ -164,7 +171,9 @@ print_move_pages(const unsigned long pid, long rc = syscall(__NR_move_pages, pid, count, pages, nodes, status, flags); const char *errstr = sprintrc(rc); - printf("move_pages(%d, %lu, ", (int) pid, count); + pidns_print_leader(); + printf("move_pages(%d%s, %lu, ", (int) pid, pid_str, + count); print_page_array(pages, count, offset); printf(", "); print_node_array(nodes, count, offset); @@ -185,8 +194,11 @@ print_move_pages(const unsigned long pid, int main(void) { + PIDNS_TEST_INIT; + const unsigned long pid = (unsigned long) 0xfacefeed00000000ULL | getpid(); + const char *pid_str = pidns_pid2str(PT_TGID); unsigned long count = 1; const unsigned page_size = get_page_size(); const void *const page = tail_alloc(page_size); @@ -195,40 +207,41 @@ main(void) TAIL_ALLOC_OBJECT_VAR_PTR(int, nodes); TAIL_ALLOC_OBJECT_VAR_PTR(int, status); - print_stat_pages(pid, 0, pages, status); - print_move_pages(pid, 0, 0, pages, nodes, status); - print_move_pages(pid, 0, 1, pages + 1, nodes + 1, status + 1); + print_stat_pages(pid, pid_str, 0, pages, status); + print_move_pages(pid, pid_str, 0, 0, pages, nodes, status); + print_move_pages(pid, pid_str, 0, 1, pages + 1, nodes + 1, status + 1); *pages = page; - print_stat_pages(pid, count, pages, status); + print_stat_pages(pid, pid_str, count, pages, status); *nodes = 0xdeadbee1; - print_move_pages(pid, count, 0, pages, nodes, status); - print_move_pages(pid, count, 1, pages, nodes, status); + print_move_pages(pid, pid_str, count, 0, pages, nodes, status); + print_move_pages(pid, pid_str, count, 1, pages, nodes, status); ++count; --status; *(--pages) = efault; - print_stat_pages(pid, count, pages, status); + print_stat_pages(pid, pid_str, count, pages, status); *(--nodes) = 0xdeadbee2; - print_move_pages(pid, count, 0, pages, nodes, status); - print_move_pages(pid, count, 1, pages, nodes, status); + print_move_pages(pid, pid_str, count, 0, pages, nodes, status); + print_move_pages(pid, pid_str, count, 1, pages, nodes, status); ++count; --status; *(--pages) = nodes; - print_stat_pages(pid, count, pages, status); + print_stat_pages(pid, pid_str, count, pages, status); *(--nodes) = 0xdeadbee3; - print_move_pages(pid, count, 0, pages, nodes, status); - print_move_pages(pid, count, 1, pages, nodes, status); + print_move_pages(pid, pid_str, count, 0, pages, nodes, status); + print_move_pages(pid, pid_str, count, 1, pages, nodes, status); ++count; --status; *(--pages) = status; - print_stat_pages(pid, count, pages, status); + print_stat_pages(pid, pid_str, count, pages, status); *(--nodes) = 0xdeadbee4; - print_move_pages(pid, count, 0, pages, nodes, status); - print_move_pages(pid, count, 1, pages, nodes, status); + print_move_pages(pid, pid_str, count, 0, pages, nodes, status); + print_move_pages(pid, pid_str, count, 1, pages, nodes, status); + pidns_print_leader(); puts("+++ exited with 0 +++"); return 0; } diff --git a/tests/net-sockaddr--pidns-translation.c b/tests/net-sockaddr--pidns-translation.c new file mode 100644 index 00000000..ff432bf4 --- /dev/null +++ b/tests/net-sockaddr--pidns-translation.c @@ -0,0 +1,2 @@ +#define PIDNS_TRANSLATION +#include "net-sockaddr.c" diff --git a/tests/net-sockaddr.c b/tests/net-sockaddr.c index 4fc9da6e..c7e9bde7 100644 --- a/tests/net-sockaddr.c +++ b/tests/net-sockaddr.c @@ -9,6 +9,7 @@ */ #include "tests.h" +#include "pidns.h" #include #include #include @@ -40,18 +41,21 @@ check_un(void) memset(un->sun_path, '0', sizeof(un->sun_path)); unsigned int len = sizeof(*un); int ret = connect(-1, (void *) un, len); + pidns_print_leader(); printf("connect(-1, {sa_family=AF_UNIX, sun_path=\"%.*u\"}" ", %u) = %d EBADF (%m)\n", (int) sizeof(un->sun_path), 0, len, ret); un->sun_path[1] = 0; ret = connect(-1, (void *) un, len); + pidns_print_leader(); printf("connect(-1, {sa_family=AF_UNIX, sun_path=\"%u\"}, %u)" " = %d EBADF (%m)\n", 0, len, ret); un->sun_path[0] = 0; un->sun_path[2] = 1; ret = connect(-1, (void *) un, len); + pidns_print_leader(); printf("connect(-1, {sa_family=AF_UNIX, sun_path=@\"\\0\\001%.*u\"}" ", %u) = %d EBADF (%m)\n", (int) sizeof(un->sun_path) - 3, 0, len, ret); @@ -61,12 +65,14 @@ check_un(void) memset(un->sun_path, '0', sizeof(un->sun_path)); len = sizeof(*un) + 2; ret = connect(-1, (void *) un, len); + pidns_print_leader(); printf("connect(-1, {sa_family=AF_UNIX, sun_path=\"%.*u\"}" ", %u) = %d EBADF (%m)\n", (int) sizeof(un->sun_path), 0, len, ret); un->sun_path[0] = 0; ret = connect(-1, (void *) un, len); + pidns_print_leader(); printf("connect(-1, {sa_family=AF_UNIX, sun_path=@\"%.*u\"}" ", %u) = %d EBADF (%m)\n", (int) sizeof(un->sun_path) - 1, 0, len, ret); @@ -75,18 +81,21 @@ check_un(void) un->sun_family = AF_UNIX; len = sizeof(*un) - 2; ret = connect(-1, (void *) un, len); + pidns_print_leader(); printf("connect(-1, {sa_family=AF_UNIX, sun_path=\"%.*u\"}" ", %u) = %d EBADF (%m)\n", (int) sizeof(un->sun_path) - 2, 0, len, ret); un->sun_path[0] = 0; ret = connect(-1, (void *) un, len); + pidns_print_leader(); printf("connect(-1, {sa_family=AF_UNIX, sun_path=@\"%.*u\"}" ", %u) = %d EBADF (%m)\n", (int) sizeof(un->sun_path) - 3, 0, len, ret); len = sizeof(*un); ret = connect(-1, (void *) un, len); + pidns_print_leader(); printf("connect(-1, %p, %u) = %d EBADF (%m)\n", un, len, ret); un = tail_alloc(sizeof(struct sockaddr_storage)); @@ -94,12 +103,14 @@ check_un(void) memset(un->sun_path, '0', sizeof(un->sun_path)); len = sizeof(struct sockaddr_storage) + 1; ret = connect(-1, (void *) un, len); + pidns_print_leader(); printf("connect(-1, {sa_family=AF_UNIX, sun_path=\"%.*u\"}" ", %u) = %d EBADF (%m)\n", (int) sizeof(un->sun_path), 0, len, ret); un->sun_path[0] = 0; ret = connect(-1, (void *) un, len); + pidns_print_leader(); printf("connect(-1, {sa_family=AF_UNIX, sun_path=@\"%.*u\"}" ", %u) = %d EBADF (%m)\n", (int) sizeof(un->sun_path) - 1, 0, len, ret); @@ -117,6 +128,7 @@ check_in(void) in->sin_addr.s_addr = inet_addr(h_addr); unsigned int len = sizeof(*in); int ret = connect(-1, (void *) in, len); + pidns_print_leader(); printf("connect(-1, {sa_family=AF_INET, sin_port=htons(%hu)" ", sin_addr=inet_addr(\"%s\")}, %u) = %d EBADF (%m)\n", h_port, h_addr, len, ret); @@ -127,6 +139,7 @@ check_in(void) in->sin_addr.s_addr = inet_addr(h_addr); len = sizeof(*in) + 4; ret = connect(-1, (void *) in, len); + pidns_print_leader(); printf("connect(-1, {sa_family=AF_INET, sin_port=htons(%hu)" ", sin_addr=inet_addr(\"%s\")}, %u) = %d EBADF (%m)\n", h_port, h_addr, len, ret); @@ -137,6 +150,7 @@ check_in(void) in->sin_addr.s_addr = 0; len = sizeof(*in) - 4; ret = connect(-1, (void *) in, len); + pidns_print_leader(); printf("connect(-1, {sa_family=AF_INET, sa_data=\"%s\"}, %u)" " = %d EBADF (%m)\n", "\\0\\0\\0\\0\\0\\0\\377\\377\\377\\377", @@ -144,6 +158,7 @@ check_in(void) len = sizeof(*in); ret = connect(-1, (void *) in, len); + pidns_print_leader(); printf("connect(-1, %p, %u) = %d EBADF (%m)\n", in, len, ret); } @@ -155,6 +170,7 @@ check_in6_linklocal(struct sockaddr_in6 *const in6, const char *const h_addr) in6->sin6_scope_id = 0xfacefeed; unsigned int len = sizeof(*in6); int ret = connect(-1, (void *) in6, len); + pidns_print_leader(); printf("connect(-1, {sa_family=AF_INET6, sin6_port=htons(%hu)" ", sin6_flowinfo=htonl(%u)" ", inet_pton(AF_INET6, \"%s\", &sin6_addr)" @@ -166,7 +182,8 @@ check_in6_linklocal(struct sockaddr_in6 *const in6, const char *const h_addr) in6->sin6_scope_id = ifindex_lo(); if (in6->sin6_scope_id) { ret = connect(-1, (void *) in6, len); - printf("connect(-1, {sa_family=AF_INET6, sin6_port=htons(%hu)" + pidns_print_leader(); + printf("connect(-1, {sa_family=AF_INET6, sin6_port=htons(%hu)" ", sin6_flowinfo=htonl(%u)" ", inet_pton(AF_INET6, \"%s\", &sin6_addr)" ", sin6_scope_id=%s}, %u)" @@ -191,6 +208,7 @@ check_in6(void) in6->sin6_scope_id = 0xfacefeed; unsigned int len = sizeof(*in6); int ret = connect(-1, (void *) in6, len); + pidns_print_leader(); printf("connect(-1, {sa_family=AF_INET6, sin6_port=htons(%hu)" ", sin6_flowinfo=htonl(%u)" ", inet_pton(AF_INET6, \"%s\", &sin6_addr)" @@ -209,6 +227,7 @@ check_in6(void) in6->sin6_scope_id = 0xfacefeed; len = sizeof(*in6) + 4; ret = connect(-1, (void *) in6, len); + pidns_print_leader(); printf("connect(-1, {sa_family=AF_INET6, sin6_port=htons(%hu)" ", sin6_flowinfo=htonl(%u)" ", inet_pton(AF_INET6, \"%s\", &sin6_addr)" @@ -223,6 +242,7 @@ check_in6(void) inet_pton(AF_INET6, h_addr, &in6->sin6_addr); len = sizeof(*in6) - sizeof(in6->sin6_scope_id); ret = connect(-1, (void *) in6, len); + pidns_print_leader(); printf("connect(-1, {sa_family=AF_INET6, sin6_port=htons(%hu)" ", sin6_flowinfo=htonl(%u)" ", inet_pton(AF_INET6, \"%s\", &sin6_addr)}, %u)" @@ -236,6 +256,7 @@ check_in6(void) memset(&in6->sin6_addr, '0', sizeof(in6->sin6_addr) - 4); len = sizeof(*in6) - sizeof(in6->sin6_scope_id) - 4; ret = connect(-1, (void *) in6, len); + pidns_print_leader(); printf("connect(-1, {sa_family=AF_INET6" ", sa_data=\"\\0\\0\\0\\0\\0\\000%.*u\"}, %u)" " = %d EBADF (%m)\n", @@ -244,6 +265,7 @@ check_in6(void) len = sizeof(*in6) - sizeof(in6->sin6_scope_id); ret = connect(-1, (void *) in6, len); + pidns_print_leader(); printf("connect(-1, %p, %u) = %d EBADF (%m)\n", in6, len, ret); } @@ -262,6 +284,7 @@ check_ipx(void) void *ipx = tail_memdup(&c_ipx, sizeof(c_ipx)); unsigned int len = sizeof(c_ipx); int ret = connect(-1, ipx, len); + pidns_print_leader(); printf("connect(-1, {sa_family=AF_IPX, sipx_port=htons(%u)" ", sipx_network=htonl(%#x)" ", sipx_node=[%#02x, %#02x, %#02x, %#02x, %#02x, %#02x]" @@ -316,18 +339,21 @@ check_ax25(void) fill_memory(sax, size); sax->fsa_ax25.sax25_family = AF_AX25; rc = connect(-1, sax_void, sizeof(struct sockaddr_ax25) - 1); + pidns_print_leader(); printf("connect(-1, {sa_family=AF_AX25, sa_data=\"\\202\\203\\204\\205" "\\206\\207\\210\\211\\212\\213\\214\\215\\216\"}, %zu) = %s\n", sizeof(struct sockaddr_ax25) - 1, sprintrc(rc)); memcpy(sax, &ax25, sizeof(ax25)); rc = connect(-1, sax_void, sizeof(struct sockaddr_ax25)); + pidns_print_leader(); printf("connect(-1, {sa_family=AF_AX25, fsa_ax25={sax25_call=VALID-13" ", sax25_ndigis=8}, fsa_digipeater=[/* ??? */]}, %zu) = %s\n", sizeof(struct sockaddr_ax25), sprintrc(rc)); sax->fsa_ax25.sax25_ndigis = 0; rc = connect(-1, sax_void, sizeof(struct sockaddr_ax25)); + pidns_print_leader(); printf("connect(-1, {sa_family=AF_AX25, sax25_call=VALID-13" ", sax25_ndigis=0}, %zu) = %s\n", sizeof(struct sockaddr_ax25), sprintrc(rc)); @@ -335,6 +361,7 @@ check_ax25(void) sax->fsa_ax25.sax25_ndigis = 8; size = sizeof(struct sockaddr_ax25) + sizeof(ax25_address) * 3 + 1; rc = connect(-1, sax_void, size); + pidns_print_leader(); printf("connect(-1, {sa_family=AF_AX25, fsa_ax25={sax25_call=VALID-13" ", sax25_ndigis=8}, fsa_digipeater" "=[{ax25_call=\"\\xa6\\xa0\\x82\\x40\\x86\\x8a\\x00\"" @@ -348,6 +375,7 @@ check_ax25(void) sax->fsa_digipeater[2].ax25_call[6] = 0x4; size = sizeof(struct sockaddr_ax25) + sizeof(ax25_address) * 4; rc = connect(-1, sax_void, size); + pidns_print_leader(); printf("connect(-1, {sa_family=AF_AX25, fsa_ax25={sax25_call=VALID-13" ", sax25_ndigis=8}, fsa_digipeater" "=[{ax25_call=\"\\xa6\\xa0\\x82\\x40\\x86\\x8a\\x00\"" @@ -365,6 +393,7 @@ check_ax25(void) for (size_t i = 0; i < 3; i++) { size = sizeof(ax25) + sizeof(ax25_address) * (i / 2); rc = connect(-1, sax_void, size); + pidns_print_leader(); printf("connect(-1, {sa_family=AF_AX25" ", fsa_ax25={sax25_call=VALID-13, sax25_ndigis=%d}" ", fsa_digipeater=[VALID2-7, OK-15, %s /* FINE-2 */" @@ -427,12 +456,14 @@ check_x25(void) long rc; rc = connect(-1, x25_void, sizeof(c_x25) - 1); + pidns_print_leader(); printf("connect(-1, {sa_family=AF_X25" ", sa_data=\"0123456789abcde\"}, %zu) = %s\n", sizeof(c_x25) - 1, sprintrc(rc)); for (size_t i = 0; i < 2; i++) { rc = connect(-1, x25_void, sizeof(c_x25) + i); + pidns_print_leader(); printf("connect(-1, {sa_family=AF_X25" ", sx25_addr={x25_addr=\"0123456789abcde\"...}" "}, %zu) = %s\n", @@ -442,6 +473,7 @@ check_x25(void) struct sockaddr_x25 *const x25 = x25_void; x25->sx25_addr.x25_addr[10] = '\0'; rc = connect(-1, x25_void, sizeof(c_x25)); + pidns_print_leader(); printf("connect(-1, {sa_family=AF_X25" ", sx25_addr={x25_addr=\"0123456789\"}" "}, %zu) = %s\n", @@ -457,19 +489,21 @@ check_nl(void) nl->nl_groups = 0xfacefeed; unsigned int len = sizeof(*nl); int ret = connect(-1, (void *) nl, len); + pidns_print_leader(); printf("connect(-1, {sa_family=AF_NETLINK, nl_pid=%d" ", nl_groups=%#08x}, %u) = %d EBADF (%m)\n", nl->nl_pid, nl->nl_groups, len, ret); nl = ((void *) nl) - 4; nl->nl_family = AF_NETLINK; - nl->nl_pid = 1234567890; + nl->nl_pid = getpid(); nl->nl_groups = 0xfacefeed; len = sizeof(*nl) + 4; ret = connect(-1, (void *) nl, len); - printf("connect(-1, {sa_family=AF_NETLINK, nl_pid=%d" + pidns_print_leader(); + printf("connect(-1, {sa_family=AF_NETLINK, nl_pid=%d%s" ", nl_groups=%#08x}, %u) = %d EBADF (%m)\n", - nl->nl_pid, nl->nl_groups, len, ret); + nl->nl_pid, pidns_pid2str(PT_TGID), nl->nl_groups, len, ret); } static void @@ -487,6 +521,7 @@ check_ll(void) void *ll = tail_memdup(&c_ll, sizeof(c_ll)); unsigned int len = sizeof(c_ll); int ret = connect(-1, ll, len); + pidns_print_leader(); printf("connect(-1, {sa_family=AF_PACKET" ", sll_protocol=htons(ETH_P_ALL)" ", sll_ifindex=%u, sll_hatype=ARPHRD_ETHER" @@ -502,6 +537,7 @@ check_ll(void) ((struct sockaddr_ll *) ll)->sll_halen++; ret = connect(-1, ll, len); + pidns_print_leader(); printf("connect(-1, {sa_family=AF_PACKET" ", sll_protocol=htons(ETH_P_ALL)" ", sll_ifindex=%u, sll_hatype=ARPHRD_ETHER" @@ -517,6 +553,7 @@ check_ll(void) ((struct sockaddr_ll *) ll)->sll_halen = 0; ret = connect(-1, ll, len); + pidns_print_leader(); printf("connect(-1, {sa_family=AF_PACKET" ", sll_protocol=htons(ETH_P_ALL)" ", sll_ifindex=%u, sll_hatype=ARPHRD_ETHER" @@ -526,6 +563,7 @@ check_ll(void) ((struct sockaddr_ll *) ll)->sll_ifindex = ifindex_lo(); if (((struct sockaddr_ll *) ll)->sll_ifindex) { ret = connect(-1, ll, len); + pidns_print_leader(); printf("connect(-1, {sa_family=AF_PACKET" ", sll_protocol=htons(ETH_P_ALL)" ", sll_ifindex=%s" @@ -549,11 +587,13 @@ check_hci(void) unsigned int len = sizeof(*hci); int ret = connect(-1, (void *) hci, 4); + pidns_print_leader(); printf("connect(-1, {sa_family=AF_BLUETOOTH, hci_dev=htobs(%hu)" "}, 4) = %d EBADF (%m)\n", h_port, ret); ret = connect(-1, (void *) hci, len); + pidns_print_leader(); printf("connect(-1, {sa_family=AF_BLUETOOTH, hci_dev=htobs(%hu)" # ifdef HAVE_STRUCT_SOCKADDR_HCI_HCI_CHANNEL ", hci_channel=HCI_CHANNEL_RAW" @@ -572,6 +612,7 @@ check_sco(void) void *sco = tail_memdup(&c_sco, sizeof(c_sco)); unsigned int len = sizeof(c_sco); int ret = connect(-1, sco, len); + pidns_print_leader(); printf("connect(-1, {sa_family=AF_BLUETOOTH" ", sco_bdaddr=%02x:%02x:%02x:%02x:%02x:%02x" "}, %u) = %d EBADF (%m)\n", @@ -592,6 +633,7 @@ check_rc(void) void *rc = tail_memdup(&c_rc, sizeof(c_rc)); unsigned int len = sizeof(c_rc); int ret = connect(-1, rc, len); + pidns_print_leader(); printf("connect(-1, {sa_family=AF_BLUETOOTH" ", rc_bdaddr=%02x:%02x:%02x:%02x:%02x:%02x" ", rc_channel=%u}, %u) = %d EBADF (%m)\n", @@ -619,6 +661,7 @@ check_l2(void) unsigned int len = sizeof(c_l2); int ret = connect(-1, l2, len); + pidns_print_leader(); printf("connect(-1, {sa_family=AF_BLUETOOTH" ", l2_psm=htobs(L2CAP_PSM_DYN_START + %hu)" ", l2_bdaddr=%02x:%02x:%02x:%02x:%02x:%02x" @@ -640,6 +683,7 @@ check_l2(void) # endif memcpy(l2, &c_l2, sizeof(c_l2)); ret = connect(-1, l2, len); + pidns_print_leader(); printf("connect(-1, {sa_family=AF_BLUETOOTH" ", l2_psm=htobs(L2CAP_PSM_SDP)" ", l2_bdaddr=%02x:%02x:%02x:%02x:%02x:%02x" @@ -660,6 +704,7 @@ check_l2(void) # endif memcpy(l2, &c_l2, sizeof(c_l2)); ret = connect(-1, l2, len); + pidns_print_leader(); printf("connect(-1, {sa_family=AF_BLUETOOTH" ", l2_psm=htobs(0xbad /* L2CAP_PSM_??? */)" ", l2_bdaddr=%02x:%02x:%02x:%02x:%02x:%02x" @@ -677,6 +722,7 @@ check_l2(void) c_l2.l2_cid = htobs(0xffff); memcpy(l2, &c_l2, 12); ret = connect(-1, l2, 12); + pidns_print_leader(); printf("connect(-1, {sa_family=AF_BLUETOOTH" ", l2_psm=htobs(L2CAP_PSM_AUTO_END)" ", l2_bdaddr=%02x:%02x:%02x:%02x:%02x:%02x" @@ -700,6 +746,7 @@ check_raw(void) u.sa->sa_family = 0xff; unsigned int len = sizeof(*u.st) + 8; int ret = connect(-1, (void *) u.st, len); + pidns_print_leader(); printf("connect(-1, {sa_family=%#x /* AF_??? */, sa_data=\"%.*u\"}" ", %u) = %d EBADF (%m)\n", u.sa->sa_family, (int) (sizeof(*u.st) - sizeof(u.sa->sa_family)), 0, len, ret); @@ -707,11 +754,13 @@ check_raw(void) u.sa->sa_family = 0; len = sizeof(u.sa->sa_family) + 1; ret = connect(-1, (void *) u.st, len); + pidns_print_leader(); printf("connect(-1, {sa_family=AF_UNSPEC, sa_data=\"0\"}, %u)" " = %d EBADF (%m)\n", len, ret); u.sa->sa_family = AF_BLUETOOTH; ret = connect(-1, (void *) u.st, len); + pidns_print_leader(); printf("connect(-1, {sa_family=AF_BLUETOOTH, sa_data=\"0\"}, %u)" " = %d EBADF (%m)\n", len, ret); } @@ -719,6 +768,8 @@ check_raw(void) int main(void) { + PIDNS_TEST_INIT; + check_un(); check_in(); check_in6(); @@ -735,6 +786,7 @@ main(void) #endif check_raw(); + pidns_print_leader(); puts("+++ exited with 0 +++"); return 0; } diff --git a/tests/netlink_audit--pidns-translation.c b/tests/netlink_audit--pidns-translation.c new file mode 100644 index 00000000..e08f9168 --- /dev/null +++ b/tests/netlink_audit--pidns-translation.c @@ -0,0 +1,2 @@ +#define PIDNS_TRANSLATION +#include "netlink_audit.c" diff --git a/tests/netlink_audit--pidns-translation.test b/tests/netlink_audit--pidns-translation.test new file mode 100755 index 00000000..1a39eadd --- /dev/null +++ b/tests/netlink_audit--pidns-translation.test @@ -0,0 +1,13 @@ +#!/bin/sh +# +# Check pidns translation of NETLINK_SOCK_DIAG protocol decoding +# +# Copyright (c) 2020 The strace developers. +# All rights reserved. +# +# SPDX-License-Identifier: LGPL-2.1-or-later + +. "${srcdir=.}/init.sh" + +run_prog ../netlink_netlink_diag +test_pidns -e trace=sendto "$@" diff --git a/tests/netlink_audit.c b/tests/netlink_audit.c index eba609a1..5dfcd786 100644 --- a/tests/netlink_audit.c +++ b/tests/netlink_audit.c @@ -7,6 +7,7 @@ */ #include "tests.h" +#include "pidns.h" #include #include #include @@ -17,18 +18,23 @@ static void test_nlmsg_type(const int fd) { + PIDNS_TEST_INIT; + long rc; struct nlmsghdr nlh = { .nlmsg_len = sizeof(nlh), .nlmsg_type = AUDIT_GET, .nlmsg_flags = NLM_F_REQUEST, + .nlmsg_pid = getpid(), }; rc = sendto(fd, &nlh, sizeof(nlh), MSG_DONTWAIT, NULL, 0); + pidns_print_leader(); printf("sendto(%d, {len=%u, type=AUDIT_GET" - ", flags=NLM_F_REQUEST, seq=0, pid=0}" + ", flags=NLM_F_REQUEST, seq=0, pid=%d%s}" ", %u, MSG_DONTWAIT, NULL, 0) = %s\n", - fd, nlh.nlmsg_len, (unsigned) sizeof(nlh), sprintrc(rc)); + fd, nlh.nlmsg_len, nlh.nlmsg_pid, pidns_pid2str(PT_TGID), + (unsigned) sizeof(nlh), sprintrc(rc)); } int main(void) @@ -39,6 +45,7 @@ int main(void) test_nlmsg_type(fd); + pidns_print_leader(); printf("+++ exited with 0 +++\n"); return 0; diff --git a/tests/pidfd_open--pidns-translation.c b/tests/pidfd_open--pidns-translation.c new file mode 100644 index 00000000..c38e37a8 --- /dev/null +++ b/tests/pidfd_open--pidns-translation.c @@ -0,0 +1,2 @@ +#define PIDNS_TRANSLATION +#include "pidfd_open.c" diff --git a/tests/pidfd_open.c b/tests/pidfd_open.c index 5860adde..e5d74a91 100644 --- a/tests/pidfd_open.c +++ b/tests/pidfd_open.c @@ -10,6 +10,7 @@ #include "tests.h" #include "scno.h" +#include "pidns.h" #ifdef __NR_pidfd_open @@ -37,6 +38,8 @@ k_pidfd_open(const unsigned int pid, const unsigned int flags) int main(void) { + PIDNS_TEST_INIT; + # if defined PATH_TRACING || defined PRINT_PATHS skip_if_unavailable("/proc/self/fd/"); # endif @@ -50,16 +53,19 @@ main(void) k_pidfd_open(0, 0); # ifndef PATH_TRACING + pidns_print_leader(); printf("pidfd_open(0, 0) = %s\n", errstr); # endif k_pidfd_open(-1U, 0); # ifndef PATH_TRACING + pidns_print_leader(); printf("pidfd_open(-1, 0) = %s\n", errstr); # endif k_pidfd_open(0, -1U); # ifndef PATH_TRACING + pidns_print_leader(); printf("pidfd_open(0, %#x) = %s\n", -1U, errstr); # endif @@ -68,7 +74,10 @@ main(void) k_pidfd_open(pid, flags); # ifndef PATH_TRACING - printf("pidfd_open(%d, %#x) = %s\n", pid, flags, errstr); + const char *pid_str = pidns_pid2str(PT_TGID); + pidns_print_leader(); + printf("pidfd_open(%d%s, %#x) = %s\n", + pid, pid_str, flags, errstr); # endif # ifdef PRINT_PATHS @@ -80,17 +89,19 @@ main(void) # endif # ifndef PATH_TRACING - printf("pidfd_open(%d, 0) = " + pidns_print_leader(); + printf("pidfd_open(%d%s, 0) = " # if defined PRINT_PIDFD - "%ld\n", pid, rc, pid + "%ld\n", pid, pid_str, rc, pid # elif defined PRINT_PATHS - "%ld\n", pid, rc + "%ld\n", pid, pid_str, rc # else - "%s\n", pid, errstr + "%s\n", pid, pid_str, errstr # endif ); # endif + pidns_print_leader(); puts("+++ exited with 0 +++"); return 0; } diff --git a/tests/pidfd_send_signal--pidns-translation.c b/tests/pidfd_send_signal--pidns-translation.c new file mode 100644 index 00000000..b04f10f5 --- /dev/null +++ b/tests/pidfd_send_signal--pidns-translation.c @@ -0,0 +1,2 @@ +#define PIDNS_TRANSLATION +#include "pidfd_send_signal.c" diff --git a/tests/pidfd_send_signal.c b/tests/pidfd_send_signal.c index 38b5bda1..a6b2d28c 100644 --- a/tests/pidfd_send_signal.c +++ b/tests/pidfd_send_signal.c @@ -10,6 +10,7 @@ #include "tests.h" #include #include "scno.h" +#include "pidns.h" #ifdef __NR_pidfd_send_signal @@ -36,6 +37,8 @@ sys_pidfd_send_signal(int pidfd, int sig, const void *info, int flags) int main(void) { + PIDNS_TEST_INIT; + static const char null_path[] = "/dev/null"; int fd = open(null_path, O_RDONLY); @@ -46,19 +49,23 @@ main(void) const void *esi = (const void *) si + 1; sys_pidfd_send_signal(fd, SIGUSR1, esi, 0); + pidns_print_leader(); printf("pidfd_send_signal(%d, SIGUSR1, %p, 0) = %s\n", fd, esi, errstr); si->si_signo = SIGUSR1; si->si_code = SI_QUEUE; + si->si_pid = getpid(); sys_pidfd_send_signal(fd, SIGUSR2, si, -1); + pidns_print_leader(); printf("pidfd_send_signal(%d, SIGUSR2, {si_signo=SIGUSR1" - ", si_code=SI_QUEUE, si_errno=%u, si_pid=%d, si_uid=%d" + ", si_code=SI_QUEUE, si_errno=%u, si_pid=%d%s, si_uid=%d" ", si_value={int=%d, ptr=%p}}, %#x) = %s\n", - fd, si->si_errno, si->si_pid, si->si_uid, si->si_int, si->si_ptr, - -1U, errstr); + fd, si->si_errno, si->si_pid, pidns_pid2str(PT_TGID), si->si_uid, + si->si_int, si->si_ptr, -1U, errstr); + pidns_print_leader(); puts("+++ exited with 0 +++"); return 0; } diff --git a/tests/pidns-cache.c b/tests/pidns-cache.c new file mode 100644 index 00000000..6319a7fd --- /dev/null +++ b/tests/pidns-cache.c @@ -0,0 +1,62 @@ +/* + * Copyright (c) 2020 The strace developers. + * All rights reserved. + * + * SPDX-License-Identifier: GPL-2.0-or-later + */ + +#include "tests.h" +#include "scno.h" +#include "pidns.h" + +#if defined __NR_getpid && (!defined __NR_getxpid || __NR_getxpid != __NR_getpid) + +# include +# include +# include + +# define SYSCALL_COUNT 1000 + +/** + * Max ratio of the execution time with and without pidns translation. + */ +# define MAX_TIME_RATIO 20 + +static long +execute_syscalls(void) +{ + /* Load our PID in the cache */ + syscall(__NR_getpid); + + struct timeval stop, start; + gettimeofday(&start, NULL); + + for (int i = 0; i < SYSCALL_COUNT; i++) + syscall(__NR_getpid); + + gettimeofday(&stop, NULL); + + return (stop.tv_usec - start.tv_usec) + + (stop.tv_sec - start.tv_sec) * 1000000; +} + +int +main(void) +{ + long max_us = execute_syscalls() * MAX_TIME_RATIO; + + pidns_test_init(); + + long us = execute_syscalls(); + if (us > max_us) + error_msg_and_fail("pidns translation took too long: %ld us " + "(max: %ld us)", us, max_us); + + return 0; +} + +#else + +SKIP_MAIN_UNDEFINED("__NR_getpid") + +#endif diff --git a/tests/pidns-cache.test b/tests/pidns-cache.test new file mode 100755 index 00000000..fa98ed8c --- /dev/null +++ b/tests/pidns-cache.test @@ -0,0 +1,16 @@ +#!/bin/sh +# +# Test pidns translation cache. +# +# Copyright (c) 2020 The strace developers. +# All rights reserved. +# +# SPDX-License-Identifier: GPL-2.0-or-later + +. "${srcdir=.}/init.sh" + +require_min_kernel_version_or_skip 4.9 +check_prog timeout + +run_prog > /dev/null +run_strace --pidns-translation -f -e trace=getpid $args diff --git a/tests/prlimit64--pidns-translation.c b/tests/prlimit64--pidns-translation.c new file mode 100644 index 00000000..3972de66 --- /dev/null +++ b/tests/prlimit64--pidns-translation.c @@ -0,0 +1,2 @@ +#define PIDNS_TRANSLATION +#include "prlimit64.c" diff --git a/tests/prlimit64.c b/tests/prlimit64.c index 34201a2b..bc1a80b3 100644 --- a/tests/prlimit64.c +++ b/tests/prlimit64.c @@ -19,6 +19,7 @@ # include # include +# include "pidns.h" # include "xlat.h" # include "xlat/resources.h" @@ -42,8 +43,11 @@ sprint_rlim(uint64_t lim) int main(void) { + PIDNS_TEST_INIT; + unsigned long pid = (unsigned long) 0xdefaced00000000ULL | (unsigned) getpid(); + const char *pid_str = pidns_pid2str(PT_TGID); uint64_t *const rlimit = tail_alloc(sizeof(*rlimit) * 2); const struct xlat_data *xlat; size_t i = 0; @@ -54,18 +58,23 @@ main(void) unsigned long res = 0xfacefeed00000000ULL | xlat->val; long rc = syscall(__NR_prlimit64, pid, res, 0, rlimit); + pidns_print_leader(); if (rc) - printf("prlimit64(%d, %s, NULL, %p) = %ld %s (%m)\n", - (unsigned) pid, xlat->str, rlimit, + printf("prlimit64(%d%s, %s, NULL, %p) =" + " %ld %s (%m)\n", + (unsigned) pid, pid_str, + xlat->str, rlimit, rc, errno2name()); else - printf("prlimit64(%d, %s, NULL" + printf("prlimit64(%d%s, %s, NULL" ", {rlim_cur=%s, rlim_max=%s}) = 0\n", - (unsigned) pid, xlat->str, + (unsigned) pid, pid_str, + xlat->str, sprint_rlim(rlimit[0]), sprint_rlim(rlimit[1])); } + pidns_print_leader(); puts("+++ exited with 0 +++"); return 0; } diff --git a/tests/process_vm_readv--pidns-translation.c b/tests/process_vm_readv--pidns-translation.c new file mode 100644 index 00000000..0db29ca2 --- /dev/null +++ b/tests/process_vm_readv--pidns-translation.c @@ -0,0 +1,2 @@ +#define PIDNS_TRANSLATION +#include "process_vm_readv.c" diff --git a/tests/process_vm_readv_writev.c b/tests/process_vm_readv_writev.c index 9309135a..44e511dd 100644 --- a/tests/process_vm_readv_writev.c +++ b/tests/process_vm_readv_writev.c @@ -12,6 +12,7 @@ #include #include #include +#include "pidns.h" #if OP_WR # define in_iovec rmt_iovec @@ -121,7 +122,7 @@ print_iov(const struct iovec *iov, const void *arg_ptr, long rc) } static void -do_call(kernel_ulong_t pid, +do_call(kernel_ulong_t pid, enum pid_type pid_type, kernel_ulong_t local_iov, const char *local_arg, kernel_ulong_t liovcnt, kernel_ulong_t remote_iov, const char *remote_arg, @@ -135,7 +136,8 @@ do_call(kernel_ulong_t pid, flags); errstr = sprintrc(rc); - printf("%s(%d, ", OP_STR, (int) pid); + pidns_print_leader(); + printf("%s(%d%s, ", OP_STR, (int) pid, pidns_pid2str(pid_type)); if (pr_iov) pr_iov((const struct iovec *) (uintptr_t) local_iov, local_arg, @@ -164,6 +166,8 @@ ptr_cast(void *ptr) int main(void) { + PIDNS_TEST_INIT; + enum { SIZE_11 = 2, SIZE_12 = 3, @@ -243,18 +247,18 @@ main(void) fill_memory_ex(data2_out, SIZE_2, SEGM2_BASE, SIZE_2); - do_call(bogus_pid, (kernel_ulong_t) (uintptr_t) ARG_STR(NULL), + do_call(bogus_pid, PT_NONE, (kernel_ulong_t) (uintptr_t) ARG_STR(NULL), bogus_iovcnt1, (kernel_ulong_t) (uintptr_t) ARG_STR(NULL), bogus_iovcnt2, bogus_flags, NULL); - do_call(my_pid, ptr_cast(bogus_iov + ARRAY_SIZE(bogus_iovec)), + do_call(my_pid, PT_TGID, ptr_cast(bogus_iov + ARRAY_SIZE(bogus_iovec)), "[]", 0, ptr_cast(in_iov + ARRAY_SIZE(in_iovec)), "[]", 0, 0, NULL); - do_call(my_pid, ptr_cast(bogus_iov + ARRAY_SIZE(bogus_iovec)), NULL, - bogus_iovcnt1, ptr_cast(in_iov + ARRAY_SIZE(in_iovec)), NULL, - bogus_iovcnt2, 0, print_iov); + do_call(my_pid, PT_TGID, ptr_cast(bogus_iov + ARRAY_SIZE(bogus_iovec)), + NULL, bogus_iovcnt1, ptr_cast(in_iov + ARRAY_SIZE(in_iovec)), + NULL, bogus_iovcnt2, 0, print_iov); - do_call(my_pid, ptr_cast(bogus_iov), (char *) &bogus_arg, + do_call(my_pid, PT_TGID, ptr_cast(bogus_iov), (char *) &bogus_arg, ARRAY_SIZE(bogus_iovec), ptr_cast(rmt_iov + 2), (char *) &rmt_arg_cut, ARRAY_SIZE(rmt_iovec) - 2, 0, print_iov); @@ -263,7 +267,7 @@ main(void) lcl_arg_cut.check_rc = 1; #endif - do_call(my_pid, ptr_cast(lcl_iov + 2), (char *) &lcl_arg_cut, + do_call(my_pid, PT_TGID, ptr_cast(lcl_iov + 2), (char *) &lcl_arg_cut, ARRAY_SIZE(lcl_iovec) - 1, ptr_cast(bogus_iov + 2), (char *) &bogus_arg_cut, ARRAY_SIZE(bogus_iovec) - 1, 0, print_iov); @@ -273,15 +277,16 @@ main(void) rmt_arg_cut.addr_term = 1; rmt_arg_cut.count = 5; - do_call(my_pid, ptr_cast(lcl_iov + 2), (char *) &lcl_arg_cut, + do_call(my_pid, PT_TGID, ptr_cast(lcl_iov + 2), (char *) &lcl_arg_cut, ARRAY_SIZE(lcl_iovec) - 2, ptr_cast(rmt_iov + 1), (char *) &rmt_arg_cut, ARRAY_SIZE(rmt_iovec), 0, print_iov); /* Correct call */ - do_call(my_pid, ptr_cast(lcl_iov), (char *) &lcl_arg, + do_call(my_pid, PT_TGID, ptr_cast(lcl_iov), (char *) &lcl_arg, ARRAY_SIZE(lcl_iovec), ptr_cast(rmt_iov), (char *) &rmt_arg, ARRAY_SIZE(rmt_iovec), 0, print_iov); + pidns_print_leader(); puts("+++ exited with 0 +++"); return 0; diff --git a/tests/process_vm_writev--pidns-translation.c b/tests/process_vm_writev--pidns-translation.c new file mode 100644 index 00000000..9ba6a39b --- /dev/null +++ b/tests/process_vm_writev--pidns-translation.c @@ -0,0 +1,2 @@ +#define PIDNS_TRANSLATION +#include "process_vm_writev.c" diff --git a/tests/rt_sigqueueinfo--pidns-translation.c b/tests/rt_sigqueueinfo--pidns-translation.c new file mode 100644 index 00000000..74bfb464 --- /dev/null +++ b/tests/rt_sigqueueinfo--pidns-translation.c @@ -0,0 +1,2 @@ +#define PIDNS_TRANSLATION +#include "rt_sigqueueinfo.c" diff --git a/tests/rt_sigqueueinfo.c b/tests/rt_sigqueueinfo.c index c1693873..e22e4640 100644 --- a/tests/rt_sigqueueinfo.c +++ b/tests/rt_sigqueueinfo.c @@ -7,6 +7,7 @@ */ #include "tests.h" +#include "pidns.h" #include #include #include @@ -15,6 +16,8 @@ int main(void) { + PIDNS_TEST_INIT; + struct sigaction sa = { .sa_handler = SIG_IGN }; @@ -22,15 +25,19 @@ main(void) .sival_ptr = (void *) (unsigned long) 0xdeadbeefbadc0dedULL }; pid_t pid = getpid(); + const char *pid_str = pidns_pid2str(PT_TGID); assert(sigaction(SIGUSR1, &sa, NULL) == 0); if (sigqueue(pid, SIGUSR1, value)) perror_msg_and_skip("sigqueue"); - printf("rt_sigqueueinfo(%u, SIGUSR1, {si_signo=SIGUSR1, " - "si_code=SI_QUEUE, si_pid=%d, si_uid=%d, " + pidns_print_leader(); + printf("rt_sigqueueinfo(%d%s, SIGUSR1, {si_signo=SIGUSR1, " + "si_code=SI_QUEUE, si_pid=%d%s, si_uid=%u, " "si_value={int=%d, ptr=%p}}) = 0\n", - pid, pid, getuid(), value.sival_int, value.sival_ptr); - printf("+++ exited with 0 +++\n"); + pid, pid_str, pid, pid_str, + getuid(), value.sival_int, value.sival_ptr); + pidns_print_leader(); + puts("+++ exited with 0 +++"); return 0; } diff --git a/tests/rt_tgsigqueueinfo--pidns-translation.c b/tests/rt_tgsigqueueinfo--pidns-translation.c new file mode 100644 index 00000000..94396f00 --- /dev/null +++ b/tests/rt_tgsigqueueinfo--pidns-translation.c @@ -0,0 +1,2 @@ +#define PIDNS_TRANSLATION +#include "rt_tgsigqueueinfo.c" diff --git a/tests/rt_tgsigqueueinfo.c b/tests/rt_tgsigqueueinfo.c index 865c21f6..21d01cbb 100644 --- a/tests/rt_tgsigqueueinfo.c +++ b/tests/rt_tgsigqueueinfo.c @@ -10,8 +10,9 @@ #include "tests.h" #include "scno.h" +#include "pidns.h" -#ifdef __NR_rt_tgsigqueueinfo +#if defined __NR_rt_tgsigqueueinfo && defined __NR_gettid # include # include @@ -20,11 +21,11 @@ # include static long -k_tgsigqueueinfo(const pid_t pid, const int sig, const void *const info) +k_tgsigqueueinfo(const pid_t tgid, const int tid, const int sig, const void *const info) { return syscall(__NR_rt_tgsigqueueinfo, - F8ILL_KULONG_MASK | pid, - F8ILL_KULONG_MASK | pid, + F8ILL_KULONG_MASK | tgid, + F8ILL_KULONG_MASK | tid, F8ILL_KULONG_MASK | sig, info); } @@ -32,6 +33,8 @@ k_tgsigqueueinfo(const pid_t pid, const int sig, const void *const info) int main(void) { + PIDNS_TEST_INIT; + const struct sigaction sa = { .sa_handler = SIG_IGN }; @@ -48,17 +51,22 @@ main(void) info->si_value.sival_ptr = (void *) (unsigned long) 0xdeadbeeffacefeedULL; - if (k_tgsigqueueinfo(info->si_pid, SIGUSR1, info)) + if (k_tgsigqueueinfo(getpid(), syscall(__NR_gettid), SIGUSR1, info)) (errno == ENOSYS ? perror_msg_and_skip : perror_msg_and_fail)( "rt_tgsigqueueinfo"); - printf("rt_tgsigqueueinfo(%u, %u, %s, {si_signo=%s" - ", si_code=SI_QUEUE, si_errno=ENOENT, si_pid=%d" + pidns_print_leader(); + printf("rt_tgsigqueueinfo(%d%s, %d%s, %s, {si_signo=%s" + ", si_code=SI_QUEUE, si_errno=ENOENT, si_pid=%d%s" ", si_uid=%d, si_value={int=%d, ptr=%p}}) = 0\n", - info->si_pid, info->si_pid, "SIGUSR1", "SIGUSR1", - info->si_pid, info->si_uid, info->si_value.sival_int, + info->si_pid, pidns_pid2str(PT_TGID), + info->si_pid, pidns_pid2str(PT_TID), + "SIGUSR1", "SIGUSR1", + info->si_pid, pidns_pid2str(PT_TGID), + info->si_uid, info->si_value.sival_int, info->si_value.sival_ptr); + pidns_print_leader(); puts("+++ exited with 0 +++"); return 0; } diff --git a/tests/sched_xetaffinity--pidns-translation.c b/tests/sched_xetaffinity--pidns-translation.c new file mode 100644 index 00000000..814e3989 --- /dev/null +++ b/tests/sched_xetaffinity--pidns-translation.c @@ -0,0 +1,2 @@ +#define PIDNS_TRANSLATION +#include "sched_xetaffinity.c" diff --git a/tests/sched_xetaffinity.c b/tests/sched_xetaffinity.c index cebff3ab..2e508ca3 100644 --- a/tests/sched_xetaffinity.c +++ b/tests/sched_xetaffinity.c @@ -10,6 +10,7 @@ #include "tests.h" #include "scno.h" +#include "pidns.h" #include #if defined __NR_sched_getaffinity && defined __NR_sched_setaffinity \ @@ -41,8 +42,11 @@ setaffinity(unsigned long pid, unsigned long size, void *set) int main(void) { + PIDNS_TEST_INIT; + unsigned int cpuset_size = 1; const pid_t pid = getpid(); + const char *pid_str = pidns_pid2str(PT_TGID); while (cpuset_size) { assert(getaffinity(pid, cpuset_size, NULL) == -1); @@ -50,18 +54,21 @@ main(void) break; if (EINVAL != errno) perror_msg_and_skip("sched_getaffinity"); - printf("sched_getaffinity(%d, %u, NULL) = %s\n", - pid, cpuset_size, errstr); + pidns_print_leader(); + printf("sched_getaffinity(%d%s, %u, NULL) = %s\n", + pid, pid_str, cpuset_size, errstr); cpuset_size <<= 1; } assert(cpuset_size); - printf("sched_getaffinity(%d, %u, NULL) = %s\n", - pid, cpuset_size, errstr); + pidns_print_leader(); + printf("sched_getaffinity(%d%s, %u, NULL) = %s\n", + pid, pid_str, cpuset_size, errstr); cpu_set_t *cpuset = tail_alloc(cpuset_size); getaffinity(pid, cpuset_size, cpuset + 1); - printf("sched_getaffinity(%d, %u, %p) = %s\n", - pid, cpuset_size, cpuset + 1, errstr); + pidns_print_leader(); + printf("sched_getaffinity(%d%s, %u, %p) = %s\n", + pid, pid_str, cpuset_size, cpuset + 1, errstr); int ret_size = getaffinity(pid, cpuset_size, cpuset); if (ret_size < 0) @@ -69,7 +76,8 @@ main(void) pid, (unsigned) cpuset_size, cpuset, errstr); assert(ret_size <= (int) cpuset_size); - printf("sched_getaffinity(%d, %u, [", pid, cpuset_size); + pidns_print_leader(); + printf("sched_getaffinity(%d%s, %u, [", pid, pid_str, cpuset_size); const char *sep; unsigned int i, cpu; for (i = 0, cpu = 0, sep = ""; i < (unsigned) ret_size * 8; ++i) { @@ -85,8 +93,9 @@ main(void) CPU_SET_S(cpu, cpuset_size, cpuset); if (setaffinity(pid, cpuset_size, cpuset)) perror_msg_and_skip("sched_setaffinity"); - printf("sched_setaffinity(%d, %u, [%u]) = 0\n", - pid, cpuset_size, cpu); + pidns_print_leader(); + printf("sched_setaffinity(%d%s, %u, [%u]) = 0\n", + pid, pid_str, cpuset_size, cpu); const unsigned int big_size = cpuset_size < 128 ? 128 : cpuset_size * 2; cpuset = tail_alloc(big_size); @@ -95,7 +104,8 @@ main(void) perror_msg_and_fail("sched_getaffinity(%d, %u, %p) = %s\n", pid, big_size, cpuset, errstr); assert(ret_size <= (int) big_size); - printf("sched_getaffinity(%d, %u, [", pid, big_size); + pidns_print_leader(); + printf("sched_getaffinity(%d%s, %u, [", pid, pid_str, big_size); for (i = 0, sep = ""; i < (unsigned) ret_size * 8; ++i) { if (CPU_ISSET_S(i, (unsigned) ret_size, cpuset)) { printf("%s%u", sep, i); @@ -104,6 +114,7 @@ main(void) } printf("]) = %s\n", errstr); + pidns_print_leader(); puts("+++ exited with 0 +++"); return 0; } diff --git a/tests/sched_xetattr--pidns-translation.c b/tests/sched_xetattr--pidns-translation.c new file mode 100644 index 00000000..c152023d --- /dev/null +++ b/tests/sched_xetattr--pidns-translation.c @@ -0,0 +1,2 @@ +#define PIDNS_TRANSLATION +#include "sched_xetattr.c" diff --git a/tests/sched_xetattr.c b/tests/sched_xetattr.c index c63d7a80..4a76b2d6 100644 --- a/tests/sched_xetattr.c +++ b/tests/sched_xetattr.c @@ -15,6 +15,7 @@ # include # include # include +# include "pidns.h" # include "sched_attr.h" # include "xlat.h" # include "xlat/schedulers.h" @@ -41,6 +42,8 @@ sys_sched_setattr(kernel_ulong_t pid, kernel_ulong_t attr, kernel_ulong_t flags) int main(void) { + PIDNS_TEST_INIT; + static const kernel_ulong_t bogus_pid = (kernel_ulong_t) 0xdefacedfacefeedULL; static const kernel_ulong_t bogus_size = @@ -48,20 +51,28 @@ main(void) static const kernel_ulong_t bogus_flags = (kernel_ulong_t) 0xdefaceddeadc0deULL; + const int pid = getpid(); + const char *pid_str = pidns_pid2str(PT_TGID); + TAIL_ALLOC_OBJECT_CONST_PTR(struct sched_attr, attr); TAIL_ALLOC_OBJECT_CONST_PTR(unsigned int, psize); void *const efault = attr + 1; - sys_sched_getattr(0, 0, 0, 0); - printf("sched_getattr(0, NULL, 0, 0) = %s\n", errstr); + sys_sched_getattr(pid, 0, 0, 0); + pidns_print_leader(); + printf("sched_getattr(%d%s, NULL, 0, 0) = %s\n", + pid, pid_str, errstr); sys_sched_getattr(0, (unsigned long) attr, 0, 0); + pidns_print_leader(); printf("sched_getattr(0, %p, 0, 0) = %s\n", attr, errstr); sys_sched_getattr(bogus_pid, 0, 0, 0); + pidns_print_leader(); printf("sched_getattr(%d, NULL, 0, 0) = %s\n", (int) bogus_pid, errstr); sys_sched_getattr(-1U, (unsigned long) attr, bogus_size, bogus_flags); + pidns_print_leader(); printf("sched_getattr(-1, %p, %s%u, %u) = %s\n", attr, # if defined __arm64__ || defined __aarch64__ @@ -72,11 +83,13 @@ main(void) (unsigned) bogus_size, (unsigned) bogus_flags, errstr); sys_sched_getattr(0, (unsigned long) efault, SCHED_ATTR_MIN_SIZE, 0); + pidns_print_leader(); printf("sched_getattr(0, %p, %u, 0) = %s\n", efault, (unsigned) SCHED_ATTR_MIN_SIZE, errstr); if (sys_sched_getattr(0, (unsigned long) attr, SCHED_ATTR_MIN_SIZE, 0)) perror_msg_and_skip("sched_getattr"); + pidns_print_leader(); printf("sched_getattr(0, {size=%u, sched_policy=", attr->size); printxval(schedulers, attr->sched_policy, NULL); printf(", sched_flags=%s, sched_nice=%d, sched_priority=%u" @@ -91,11 +104,13 @@ main(void) (unsigned) SCHED_ATTR_MIN_SIZE); sys_sched_getattr(0, (unsigned long) efault, sizeof(*attr), 0); + pidns_print_leader(); printf("sched_getattr(0, %p, %u, 0) = %s\n", efault, (unsigned) sizeof(*attr), errstr); if (sys_sched_getattr(0, (unsigned long) attr, sizeof(*attr), 0)) perror_msg_and_skip("sched_getattr"); + pidns_print_leader(); printf("sched_getattr(0, {size=%u, sched_policy=", attr->size); printxval(schedulers, attr->sched_policy, NULL); printf(", sched_flags=%s, sched_nice=%d, sched_priority=%u" @@ -121,11 +136,13 @@ main(void) F8ILL_KULONG_MASK | sizeof(*attr), F8ILL_KULONG_MASK); # if defined __arm64__ || defined __aarch64__ if (rc) { + pidns_print_leader(); printf("sched_getattr(0, %p, 0xffffffff<<32|%u, 0) = %s\n", attr, (unsigned) sizeof(*attr), errstr); } else # endif { + pidns_print_leader(); printf("sched_getattr(0, {size=%u, sched_policy=", attr->size); printxval(schedulers, attr->sched_policy, NULL); printf(", sched_flags=%s, sched_nice=%d, sched_priority=%u" @@ -146,13 +163,16 @@ main(void) } sys_sched_setattr(bogus_pid, 0, 0); + pidns_print_leader(); printf("sched_setattr(%d, NULL, 0) = %s\n", (int) bogus_pid, errstr); attr->sched_flags |= 1; - if (sys_sched_setattr(0, (unsigned long) attr, 0)) + if (sys_sched_setattr(pid, (unsigned long) attr, 0)) perror_msg_and_skip("sched_setattr"); - printf("sched_setattr(0, {size=%u, sched_policy=", attr->size); + pidns_print_leader(); + printf("sched_setattr(%d%s, {size=%u, sched_policy=", + pid, pid_str, attr->size); printxval(schedulers, attr->sched_policy, NULL); printf(", sched_flags=%s, sched_nice=%d, sched_priority=%u" ", sched_runtime=%" PRIu64 ", sched_deadline=%" PRIu64 @@ -172,6 +192,7 @@ main(void) sys_sched_setattr(F8ILL_KULONG_MASK, (unsigned long) attr, F8ILL_KULONG_MASK); + pidns_print_leader(); printf("sched_setattr(0, {size=%u, sched_policy=", attr->size); printxval(schedulers, attr->sched_policy, NULL); printf(", sched_flags=%s, sched_nice=%d, sched_priority=%u" @@ -193,11 +214,13 @@ main(void) *psize = attr->size; sys_sched_setattr(0, (unsigned long) psize, 0); + pidns_print_leader(); printf("sched_setattr(0, %p, 0) = %s\n", psize, errstr); attr->size = 0; sys_sched_setattr(0, (unsigned long) attr, 0); + pidns_print_leader(); printf("sched_setattr(0, {size=%u, sched_policy=", attr->size); printxval(schedulers, attr->sched_policy, NULL); printf(", sched_flags=%s, sched_nice=%d, sched_priority=%u" @@ -213,12 +236,14 @@ main(void) attr->size = 1; sys_sched_setattr(0, (unsigned long) attr, 0); + pidns_print_leader(); printf("sched_setattr(0, {size=%u} => {size=%u}, 0) = %s\n", 1, attr->size, errstr); attr->size = SCHED_ATTR_MIN_SIZE - 1; sys_sched_setattr(0, (unsigned long) attr, 0); + pidns_print_leader(); printf("sched_setattr(0, {size=%u} => {size=%u}, 0) = %s\n", SCHED_ATTR_MIN_SIZE - 1, attr->size, errstr); @@ -232,6 +257,7 @@ main(void) attr->sched_period = 0xded1ca7edda7aca7ULL; sys_sched_setattr(bogus_pid, (unsigned long) attr, bogus_flags); + pidns_print_leader(); printf("sched_setattr(%d, {size=%u, sched_policy=%#x /* SCHED_??? */, " "sched_flags=%#" PRIx64 " /* SCHED_FLAG_??? */, " "sched_nice=%d, sched_priority=%u, sched_runtime=%" PRIu64 ", " @@ -274,6 +300,7 @@ main(void) attr->sched_period = 0xded1ca7edda7aca7ULL; sys_sched_setattr(bogus_pid, (unsigned long) attr, bogus_flags); + pidns_print_leader(); printf("sched_setattr(%d, {size=%u, sched_policy=%#x /* SCHED_??? */, " "sched_flags=SCHED_FLAG_RESET_ON_FORK|SCHED_FLAG_RECLAIM|" "SCHED_FLAG_DL_OVERRUN|0x80, " @@ -296,11 +323,13 @@ main(void) const kernel_ulong_t ill = f8ill_ptr_to_kulong(attr); sys_sched_getattr(0, ill, sizeof(*attr), 0); + pidns_print_leader(); printf("sched_getattr(0, %#llx, %u, 0) = %s\n", (unsigned long long) ill, (unsigned) sizeof(*attr), errstr); sys_sched_setattr(0, ill, 0); + pidns_print_leader(); printf("sched_setattr(0, %#llx, 0) = %s\n", (unsigned long long) ill, errstr); } @@ -310,6 +339,7 @@ main(void) attr->sched_flags = 0x8fULL; sys_sched_setattr(bogus_pid, (unsigned long) attr, bogus_flags); + pidns_print_leader(); printf("sched_setattr(%d, {size=%u, " "sched_flags=SCHED_FLAG_RESET_ON_FORK|SCHED_FLAG_RECLAIM|" "SCHED_FLAG_DL_OVERRUN|SCHED_FLAG_KEEP_POLICY|0x80, " @@ -329,11 +359,13 @@ main(void) const kernel_ulong_t ill = f8ill_ptr_to_kulong(attr); sys_sched_getattr(0, ill, sizeof(*attr), 0); + pidns_print_leader(); printf("sched_getattr(0, %#llx, %u, 0) = %s\n", (unsigned long long) ill, (unsigned) sizeof(*attr), errstr); sys_sched_setattr(0, ill, 0); + pidns_print_leader(); printf("sched_setattr(0, %#llx, 0) = %s\n", (unsigned long long) ill, errstr); } @@ -342,6 +374,7 @@ main(void) attr->sched_flags = 0xe7ULL; sys_sched_setattr(bogus_pid, (unsigned long) attr, bogus_flags); + pidns_print_leader(); printf("sched_setattr(%d, {size=%u, sched_policy=%#x /* SCHED_??? */, " "sched_flags=SCHED_FLAG_RESET_ON_FORK|SCHED_FLAG_RECLAIM|" "SCHED_FLAG_DL_OVERRUN|SCHED_FLAG_UTIL_CLAMP_MIN" @@ -365,11 +398,13 @@ main(void) const kernel_ulong_t ill = f8ill_ptr_to_kulong(attr); sys_sched_getattr(0, ill, sizeof(*attr), 0); + pidns_print_leader(); printf("sched_getattr(0, %#llx, %u, 0) = %s\n", (unsigned long long) ill, (unsigned) sizeof(*attr), errstr); sys_sched_setattr(0, ill, 0); + pidns_print_leader(); printf("sched_setattr(0, %#llx, 0) = %s\n", (unsigned long long) ill, errstr); } @@ -377,6 +412,7 @@ main(void) attr->sched_flags = 0xcaffee90LL; sys_sched_setattr(bogus_pid, (unsigned long) attr, bogus_flags); + pidns_print_leader(); printf("sched_setattr(%d, {size=%u, sched_flags=SCHED_FLAG_KEEP_PARAMS" "|0xcaffee80, sched_util_min=%u, sched_util_max=%u}, %u) = %s\n", (int) bogus_pid, @@ -389,15 +425,18 @@ main(void) const kernel_ulong_t ill = f8ill_ptr_to_kulong(attr); sys_sched_getattr(0, ill, sizeof(*attr), 0); + pidns_print_leader(); printf("sched_getattr(0, %#llx, %u, 0) = %s\n", (unsigned long long) ill, (unsigned) sizeof(*attr), errstr); sys_sched_setattr(0, ill, 0); + pidns_print_leader(); printf("sched_setattr(0, %#llx, 0) = %s\n", (unsigned long long) ill, errstr); } + pidns_print_leader(); puts("+++ exited with 0 +++"); return 0; } diff --git a/tests/sched_xetparam--pidns-translation.c b/tests/sched_xetparam--pidns-translation.c new file mode 100644 index 00000000..9fb3e579 --- /dev/null +++ b/tests/sched_xetparam--pidns-translation.c @@ -0,0 +1,2 @@ +#define PIDNS_TRANSLATION +#include "sched_xetparam.c" diff --git a/tests/sched_xetparam.c b/tests/sched_xetparam.c index de3915b2..aa9c68cc 100644 --- a/tests/sched_xetparam.c +++ b/tests/sched_xetparam.c @@ -7,6 +7,7 @@ #include "tests.h" #include "scno.h" +# include "pidns.h" #if defined __NR_sched_getparam && defined __NR_sched_setparam @@ -17,18 +18,27 @@ int main(void) { + PIDNS_TEST_INIT; + struct sched_param *const param = tail_alloc(sizeof(struct sched_param)); - long rc = syscall(__NR_sched_getparam, 0, param); - printf("sched_getparam(0, [%d]) = %ld\n", - param->sched_priority, rc); + const int pid = getpid(); + const char *pid_str = pidns_pid2str(PT_TGID); + + long rc = syscall(__NR_sched_getparam, pid, param); + pidns_print_leader(); + printf("sched_getparam(%d%s, [%d]) = %ld\n", + pid, pid_str, param->sched_priority, rc); param->sched_priority = -1; - rc = syscall(__NR_sched_setparam, 0, param); - printf("sched_setparam(0, [%d]) = %ld %s (%m)\n", + rc = syscall(__NR_sched_setparam, pid, param); + pidns_print_leader(); + printf("sched_setparam(%d%s, [%d]) = %ld %s (%m)\n", + pid, pid_str, param->sched_priority, rc, errno2name()); + pidns_print_leader(); puts("+++ exited with 0 +++"); return 0; } diff --git a/tests/sched_xetscheduler--pidns-translation.c b/tests/sched_xetscheduler--pidns-translation.c new file mode 100644 index 00000000..78b794b2 --- /dev/null +++ b/tests/sched_xetscheduler--pidns-translation.c @@ -0,0 +1,2 @@ +#define PIDNS_TRANSLATION +#include "sched_xetscheduler.c" diff --git a/tests/sched_xetscheduler.c b/tests/sched_xetscheduler.c index 047e8676..91b5e32d 100644 --- a/tests/sched_xetscheduler.c +++ b/tests/sched_xetscheduler.c @@ -7,6 +7,7 @@ #include "tests.h" #include "scno.h" +#include "pidns.h" #if defined __NR_sched_getscheduler && defined __NR_sched_setscheduler @@ -17,8 +18,13 @@ int main(void) { + PIDNS_TEST_INIT; + TAIL_ALLOC_OBJECT_CONST_PTR(struct sched_param, param); - long rc = syscall(__NR_sched_getscheduler, 0); + const int pid = getpid(); + const char *pid_str = pidns_pid2str(PT_TGID); + + long rc = syscall(__NR_sched_getscheduler, pid); const char *scheduler; switch (rc) { case SCHED_FIFO: @@ -50,33 +56,43 @@ main(void) default: scheduler = "SCHED_OTHER"; } - printf("sched_getscheduler(0) = %ld (%s)\n", - rc, scheduler); + pidns_print_leader(); + printf("sched_getscheduler(%d%s) = %ld (%s)\n", + pid, pid_str, rc, scheduler); rc = syscall(__NR_sched_getscheduler, -1); + pidns_print_leader(); printf("sched_getscheduler(-1) = %s\n", sprintrc(rc)); param->sched_priority = -1; - rc = syscall(__NR_sched_setscheduler, 0, SCHED_FIFO, NULL); - printf("sched_setscheduler(0, SCHED_FIFO, NULL) = %s\n", sprintrc(rc)); + rc = syscall(__NR_sched_setscheduler, pid, SCHED_FIFO, NULL); + pidns_print_leader(); + printf("sched_setscheduler(%d%s, SCHED_FIFO, NULL) = %s\n", + pid, pid_str, sprintrc(rc)); - rc = syscall(__NR_sched_setscheduler, 0, SCHED_FIFO, param + 1); - printf("sched_setscheduler(0, SCHED_FIFO, %p) = %s\n", param + 1, - sprintrc(rc)); + rc = syscall(__NR_sched_setscheduler, pid, SCHED_FIFO, param + 1); + pidns_print_leader(); + printf("sched_setscheduler(%d%s, SCHED_FIFO, %p) = %s\n", + pid, pid_str, param + 1, sprintrc(rc)); - rc = syscall(__NR_sched_setscheduler, 0, 0xfaceda7a, param); - printf("sched_setscheduler(0, %#x /* SCHED_??? */, [%d]) = %s\n", - 0xfaceda7a, param->sched_priority, sprintrc(rc)); + rc = syscall(__NR_sched_setscheduler, pid, 0xfaceda7a, param); + pidns_print_leader(); + printf("sched_setscheduler(%d%s, %#x /* SCHED_??? */, [%d]) = %s\n", + pid, pid_str, 0xfaceda7a, + param->sched_priority, sprintrc(rc)); rc = syscall(__NR_sched_setscheduler, -1, SCHED_FIFO, param); + pidns_print_leader(); printf("sched_setscheduler(-1, SCHED_FIFO, [%d]) = %s\n", param->sched_priority, sprintrc(rc)); - rc = syscall(__NR_sched_setscheduler, 0, SCHED_FIFO, param); - printf("sched_setscheduler(0, SCHED_FIFO, [%d]) = %s\n", - param->sched_priority, sprintrc(rc)); + rc = syscall(__NR_sched_setscheduler, pid, SCHED_FIFO, param); + pidns_print_leader(); + printf("sched_setscheduler(%d%s, SCHED_FIFO, [%d]) = %s\n", + pid, pid_str, param->sched_priority, sprintrc(rc)); + pidns_print_leader(); puts("+++ exited with 0 +++"); return 0; } diff --git a/tests/signal_receive--pidns-translation.c b/tests/signal_receive--pidns-translation.c new file mode 100644 index 00000000..b4e3b2f8 --- /dev/null +++ b/tests/signal_receive--pidns-translation.c @@ -0,0 +1,2 @@ +#define PIDNS_TRANSLATION +#include "signal_receive.c" diff --git a/tests/signal_receive.c b/tests/signal_receive.c index ad3b4ebd..70441a9e 100644 --- a/tests/signal_receive.c +++ b/tests/signal_receive.c @@ -8,6 +8,7 @@ */ #include "tests.h" +#include "pidns.h" #include #include #include @@ -26,10 +27,13 @@ handler(int sig, siginfo_t *info, void *ucontext) int main(void) { + PIDNS_TEST_INIT; + static const char prefix[] = "KERNEL BUG"; int printed = 0; const int pid = getpid(); + const char *pid_str = pidns_pid2str(PT_TGID); const int uid = geteuid(); for (int sig = 1; sig <= 31; ++sig) { @@ -73,10 +77,13 @@ main(void) const int e_pid = s_pid; const int e_uid = s_uid; #endif - printf("kill(%d, %s) = 0\n", pid, signal2name(sig)); - printf("--- %s {si_signo=%s, si_code=SI_USER, si_pid=%d" + pidns_print_leader(); + printf("kill(%d%s, %s) = 0\n", pid, pid_str, signal2name(sig)); + pidns_print_leader(); + printf("--- %s {si_signo=%s, si_code=SI_USER, si_pid=%d%s" ", si_uid=%d} ---\n", - signal2name(sig), signal2name(e_sig), e_pid, e_uid); + signal2name(sig), signal2name(e_sig), + e_pid, pid_str, e_uid); if (s_code || sig != s_sig || pid != s_pid || uid != s_uid) { /* @@ -91,11 +98,11 @@ main(void) } fprintf(stderr, "%s: expected: si_signo=%d, si_code=%d" - ", si_pid=%d, si_uid=%d\n" + ", si_pid=%d%s, si_uid=%d\n" "%s: received: si_signo=%d, si_code=%d" - ", si_pid=%d, si_uid=%d\n", - prefix, sig, SI_USER, pid, uid, - prefix, sig, s_code, s_pid, s_uid); + ", si_pid=%d%s, si_uid=%d\n", + prefix, sig, SI_USER, pid, pid_str, uid, + prefix, sig, s_code, s_pid, pid_str, s_uid); } } @@ -104,6 +111,7 @@ main(void) "*** PLEASE FIX THE KERNEL ***\n", prefix); } + pidns_print_leader(); puts("+++ exited with 0 +++"); return 0; } diff --git a/tests/so_peercred--pidns-translation.c b/tests/so_peercred--pidns-translation.c new file mode 100644 index 00000000..402bbcfe --- /dev/null +++ b/tests/so_peercred--pidns-translation.c @@ -0,0 +1,2 @@ +#define PIDNS_TRANSLATION +#include "so_peercred.c" diff --git a/tests/so_peercred.c b/tests/so_peercred.c index 151bb175..20188bdb 100644 --- a/tests/so_peercred.c +++ b/tests/so_peercred.c @@ -9,6 +9,7 @@ */ #include "tests.h" +#include "pidns.h" #include #include @@ -53,6 +54,8 @@ so_str(void) int main(void) { + PIDNS_TEST_INIT; + TAIL_ALLOC_OBJECT_CONST_PTR(struct ucred, peercred); TAIL_ALLOC_OBJECT_CONST_PTR(socklen_t, len); @@ -75,6 +78,8 @@ main(void) struct ucred *const gid_truncated = tail_alloc(sizeof_gid_truncated); + const char *pid_str = pidns_pid2str(PT_TGID); + int sv[2]; if (socketpair(AF_UNIX, SOCK_STREAM, 0, sv)) perror_msg_and_skip("socketpair AF_UNIX SOCK_STREAM"); @@ -82,8 +87,10 @@ main(void) /* classic getsockopt */ *len = sizeof(*peercred); get_peercred(sv[0], peercred, len); + pidns_print_leader(); printf("getsockopt(%d, %s", sv[0], so_str()); PRINT_FIELD_D(", {", *peercred, pid); + printf("%s", pid_str); PRINT_FIELD_UID(", ", *peercred, uid); PRINT_FIELD_UID(", ", *peercred, gid); printf("}, [%d]) = %s\n", *len, errstr); @@ -91,14 +98,17 @@ main(void) /* getsockopt with zero optlen */ *len = 0; get_peercred(sv[0], peercred, len); + pidns_print_leader(); printf("getsockopt(%d, %s, %p, [0]) = %s\n", sv[0], so_str(), peercred, errstr); /* getsockopt with optlen larger than necessary - shortened */ *len = sizeof(*peercred) + 1; get_peercred(sv[0], peercred, len); + pidns_print_leader(); printf("getsockopt(%d, %s", sv[0], so_str()); PRINT_FIELD_D(", {", *peercred, pid); + printf("%s", pid_str); PRINT_FIELD_UID(", ", *peercred, uid); PRINT_FIELD_UID(", ", *peercred, gid); printf("}, [%u->%d]) = %s\n", @@ -110,6 +120,7 @@ main(void) */ *len = sizeof_pid_truncated; get_peercred(sv[0], pid_truncated, len); + pidns_print_leader(); printf("getsockopt(%d, %s, {pid=", sv[0], so_str()); print_quoted_hex(pid_truncated, *len); printf("}, [%d]) = %s\n", *len, errstr); @@ -120,8 +131,10 @@ main(void) */ *len = sizeof_pid; get_peercred(sv[0], pid, len); + pidns_print_leader(); printf("getsockopt(%d, %s", sv[0], so_str()); PRINT_FIELD_D(", {", *pid, pid); + printf("%s", pid_str); printf("}, [%d]) = %s\n", *len, errstr); /* @@ -136,8 +149,10 @@ main(void) * to struct ucred.pid field. */ memcpy(uid, uid_truncated, sizeof_uid_truncated); + pidns_print_leader(); printf("getsockopt(%d, %s", sv[0], so_str()); PRINT_FIELD_D(", {", *uid, pid); + printf("%s", pid_str); printf(", uid="); print_quoted_hex(&uid->uid, sizeof_uid_truncated - offsetof(struct ucred, uid)); @@ -149,8 +164,10 @@ main(void) */ *len = sizeof_uid; get_peercred(sv[0], uid, len); + pidns_print_leader(); printf("getsockopt(%d, %s", sv[0], so_str()); PRINT_FIELD_D(", {", *uid, pid); + printf("%s", pid_str); PRINT_FIELD_UID(", ", *uid, uid); printf("}, [%d]) = %s\n", *len, errstr); @@ -166,8 +183,10 @@ main(void) * to struct ucred.pid and struct ucred.uid fields. */ memcpy(peercred, gid_truncated, sizeof_gid_truncated); + pidns_print_leader(); printf("getsockopt(%d, %s", sv[0], so_str()); PRINT_FIELD_D(", {", *peercred, pid); + printf("%s", pid_str); PRINT_FIELD_UID(", ", *peercred, uid); printf(", gid="); print_quoted_hex(&peercred->gid, sizeof_gid_truncated - @@ -177,14 +196,17 @@ main(void) /* getsockopt optval EFAULT */ *len = sizeof(*peercred); get_peercred(sv[0], &peercred->uid, len); + pidns_print_leader(); printf("getsockopt(%d, %s, %p, [%d]) = %s\n", sv[0], so_str(), &peercred->uid, *len, errstr); /* getsockopt optlen EFAULT */ get_peercred(sv[0], peercred, len + 1); + pidns_print_leader(); printf("getsockopt(%d, %s, %p, %p) = %s\n", sv[0], so_str(), peercred, len + 1, errstr); + pidns_print_leader(); puts("+++ exited with 0 +++"); return 0; } diff --git a/tests/tgkill--pidns-translation.c b/tests/tgkill--pidns-translation.c new file mode 100644 index 00000000..c3ac2d0a --- /dev/null +++ b/tests/tgkill--pidns-translation.c @@ -0,0 +1,2 @@ +#define PIDNS_TRANSLATION +#include "tgkill.c" diff --git a/tests/tgkill.c b/tests/tgkill.c index 901be376..10816a61 100644 --- a/tests/tgkill.c +++ b/tests/tgkill.c @@ -9,6 +9,7 @@ #include "tests.h" #include "scno.h" +#include "pidns.h" #ifdef __NR_tgkill @@ -36,28 +37,46 @@ k_tgkill(const unsigned int tgid, int main(void) { + PIDNS_TEST_INIT; + const int pid = getpid(); + const char *pid_str = pidns_pid2str(PT_TGID); + const int tid = syscall(__NR_gettid); + const char *tid_str = pidns_pid2str(PT_TID); const int bad_pid = -1; const int bad_sig = 0xface; - k_tgkill(pid, pid, 0); - printf("tgkill(%d, %d, 0) = %s\n", pid, pid, errstr); + k_tgkill(pid, tid, 0); + pidns_print_leader(); + printf("tgkill(%d%s, %d%s, 0) = %s\n", + pid, pid_str, tid, tid_str, errstr); k_tgkill(pid, bad_pid, 0); - printf("tgkill(%d, %d, 0) = %s\n", pid, bad_pid, errstr); - - k_tgkill(bad_pid, pid, 0); - printf("tgkill(%d, %d, 0) = %s\n", bad_pid, pid, errstr); - - k_tgkill(pid, pid, SIGCONT); - printf("tgkill(%d, %d, SIGCONT) = %s\n", pid, pid, errstr); - - k_tgkill(pid, pid, bad_sig); - printf("tgkill(%d, %d, %d) = %s\n", pid, pid, bad_sig, errstr); - - k_tgkill(pid, pid, -bad_sig); - printf("tgkill(%d, %d, %d) = %s\n", pid, pid, -bad_sig, errstr); - + pidns_print_leader(); + printf("tgkill(%d%s, %d, 0) = %s\n", + pid, pid_str, bad_pid, errstr); + + k_tgkill(bad_pid, tid, 0); + pidns_print_leader(); + printf("tgkill(%d, %d%s, 0) = %s\n", + bad_pid, tid, tid_str, errstr); + + k_tgkill(pid, tid, SIGCONT); + pidns_print_leader(); + printf("tgkill(%d%s, %d%s, SIGCONT) = %s\n", + pid, pid_str, tid, tid_str, errstr); + + k_tgkill(pid, tid, bad_sig); + pidns_print_leader(); + printf("tgkill(%d%s, %d%s, %d) = %s\n", + pid, pid_str, tid, tid_str, bad_sig, errstr); + + k_tgkill(pid, tid, -bad_sig); + pidns_print_leader(); + printf("tgkill(%d%s, %d%s, %d) = %s\n", + pid, pid_str, tid, tid_str, -bad_sig, errstr); + + pidns_print_leader(); puts("+++ exited with 0 +++"); return 0; } diff --git a/tests/tkill--pidns-translation.c b/tests/tkill--pidns-translation.c new file mode 100644 index 00000000..70a64f57 --- /dev/null +++ b/tests/tkill--pidns-translation.c @@ -0,0 +1,2 @@ +#define PIDNS_TRANSLATION +#include "tkill.c" diff --git a/tests/tkill.c b/tests/tkill.c index 5f67c9f5..89466e1a 100644 --- a/tests/tkill.c +++ b/tests/tkill.c @@ -9,6 +9,7 @@ #include "tests.h" #include "scno.h" +#include "pidns.h" #ifdef __NR_tkill @@ -33,22 +34,30 @@ k_tkill(const unsigned int tid, const unsigned int sig) int main(void) { - const int pid = getpid(); + PIDNS_TEST_INIT; + + const int tid = syscall(__NR_gettid); + const char *tid_str = pidns_pid2str(PT_TID); const int bad_pid = -1; const int bad_sig = 0xface; - k_tkill(pid, 0); - printf("tkill(%d, 0) = %s\n", pid, errstr); + k_tkill(tid, 0); + pidns_print_leader(); + printf("tkill(%d%s, 0) = %s\n", tid, tid_str, errstr); - k_tkill(pid, SIGCONT); - printf("tkill(%d, SIGCONT) = %s\n", pid, errstr); + k_tkill(tid, SIGCONT); + pidns_print_leader(); + printf("tkill(%d%s, SIGCONT) = %s\n", tid, tid_str, errstr); k_tkill(bad_pid, bad_sig); + pidns_print_leader(); printf("tkill(%d, %d) = %s\n", bad_pid, bad_sig, errstr); k_tkill(bad_pid, -bad_sig); + pidns_print_leader(); printf("tkill(%d, %d) = %s\n", bad_pid, -bad_sig, errstr); + pidns_print_leader(); puts("+++ exited with 0 +++"); return 0; } diff --git a/tests/trie.c b/tests/trie.c new file mode 120000 index 00000000..0dd9cab4 --- /dev/null +++ b/tests/trie.c @@ -0,0 +1 @@ +../trie.c \ No newline at end of file diff --git a/tests/trie_test.c b/tests/trie_test.c new file mode 100644 index 00000000..bc54a888 --- /dev/null +++ b/tests/trie_test.c @@ -0,0 +1,77 @@ +/* + * Copyright (c) 2017-2019 The strace developers. + * All rights reserved. + * + * SPDX-License-Identifier: GPL-2.0-or-later + */ + +#include "tests.h" +#include "trie.h" + +#include +#include + +static void +assert_equals(const char *msg, uint64_t expected, uint64_t actual) { + if (actual != expected) + error_msg_and_fail("%s: expected: %" PRIu64 + ", actual: %" PRIu64, msg, expected, actual); +} + +struct key_value_pair { + uint64_t key, value; +}; + +int +main(void) +{ + static const struct { + uint8_t key_size; + uint8_t item_size_lg; + uint8_t node_key_bits; + uint8_t data_block_key_bits; + uint64_t empty_value; + + struct key_value_pair set_values[3], get_values[3]; + } params[] = { + {64, 6, 10, 10, 0, + {{300, 1}, {0xfacefeed, 0xabcdef123456}, {-1ULL, -1ULL}}, + {{301, 0}, {0xfacefeed, 0xabcdef123456}, {-1ULL, -1ULL}}}, + {8, 2, 4, 4, 10, + {{0xab, 0xcd}, {0xface, 2}, {0, 3}}, + {{0xab, 0xd}, {0xface, 10}, {0, 3}}}, + {30, 0, 6, 3, -1, + {{0xaaaa, 127}, {0xface, 0}, {0, 0}}, + {{0xaaaa, 1}, {0xface, 0}, {1, 1}}}, + {16, 4, 5, 11, 0xffffff, + {{0xabcdef, 42}, {0xabcd, 42}, {0xffff, 0}}, + {{0xabcdef, 0xffff}, {0xabcd, 42}, {0xffff, 0}}}, + {41, 5, 1, 1, -1, + {{0xabcdef01, 0x22222222}, {-1, 0x33333333}, {10, 10}}, + {{0xabcdef01, 0x22222222}, {-1, 0xffffffff}, {10, 10}}}, + }; + + for (size_t i = 0; i < ARRAY_SIZE(params); i++) { + struct trie *t = trie_create(params[i].key_size, + params[i].item_size_lg, + params[i].node_key_bits, + params[i].data_block_key_bits, + params[i].empty_value); + + if (!t) + error_msg_and_fail("trie creation failed"); + + for (size_t j = 0; j < ARRAY_SIZE(params[i].set_values); j++) { + struct key_value_pair kv = params[i].set_values[j]; + trie_set(t, kv.key, kv.value); + } + for (size_t j = 0; j < ARRAY_SIZE(params[i].get_values); j++) { + struct key_value_pair kv = params[i].get_values[j]; + assert_equals("trie_get", kv.value, trie_get(t, kv.key)); + } + + trie_free(t); + } + + return 0; +} diff --git a/tests/xet_robust_list--pidns-translation.c b/tests/xet_robust_list--pidns-translation.c new file mode 100644 index 00000000..e0477267 --- /dev/null +++ b/tests/xet_robust_list--pidns-translation.c @@ -0,0 +1,2 @@ +#define PIDNS_TRANSLATION +#include "xet_robust_list.c" diff --git a/tests/xet_robust_list.c b/tests/xet_robust_list.c index 43239c8b..b5751b0a 100644 --- a/tests/xet_robust_list.c +++ b/tests/xet_robust_list.c @@ -8,6 +8,7 @@ #include "tests.h" #include "scno.h" +#include "pidns.h" #if defined __NR_get_robust_list && defined __NR_set_robust_list @@ -30,27 +31,36 @@ sprintaddr(void *addr) int main(void) { + PIDNS_TEST_INIT; + const pid_t pid = getpid(); + const char *pid_str = pidns_pid2str(PT_TGID); const long long_pid = (unsigned long) (0xdeadbeef00000000LL | pid); TAIL_ALLOC_OBJECT_CONST_PTR(void *, p_head); TAIL_ALLOC_OBJECT_CONST_PTR(size_t, p_len); if (syscall(__NR_get_robust_list, long_pid, p_head, p_len)) perror_msg_and_skip("get_robust_list"); - printf("get_robust_list(%d, [%s], [%lu]) = 0\n", - (int) pid, sprintaddr(*p_head), (unsigned long) *p_len); + pidns_print_leader(); + printf("get_robust_list(%d%s, [%s], [%lu]) = 0\n", + pid, pid_str, sprintaddr(*p_head), + (unsigned long) *p_len); void *head = tail_alloc(*p_len); if (syscall(__NR_set_robust_list, head, *p_len)) perror_msg_and_skip("set_robust_list"); + pidns_print_leader(); printf("set_robust_list(%p, %lu) = 0\n", head, (unsigned long) *p_len); if (syscall(__NR_get_robust_list, long_pid, p_head, p_len)) perror_msg_and_skip("get_robust_list"); - printf("get_robust_list(%d, [%s], [%lu]) = 0\n", - (int) pid, sprintaddr(*p_head), (unsigned long) *p_len); + pidns_print_leader(); + printf("get_robust_list(%d%s, [%s], [%lu]) = 0\n", + pid, pid_str, sprintaddr(*p_head), + (unsigned long) *p_len); + pidns_print_leader(); puts("+++ exited with 0 +++"); return 0; } diff --git a/tests/xetpgid--pidns-translation.c b/tests/xetpgid--pidns-translation.c new file mode 100644 index 00000000..b6469628 --- /dev/null +++ b/tests/xetpgid--pidns-translation.c @@ -0,0 +1,2 @@ +#define PIDNS_TRANSLATION +#include "xetpgid.c" diff --git a/tests/xetpgid.c b/tests/xetpgid.c index 9b070af2..411edfc7 100644 --- a/tests/xetpgid.c +++ b/tests/xetpgid.c @@ -10,6 +10,7 @@ #include "tests.h" #include "scno.h" +#include "pidns.h" #if defined __NR_getpgid && defined __NR_setpgid @@ -19,13 +20,21 @@ int main(void) { - const int pid = getpid(); - long rc = syscall(__NR_getpgid, F8ILL_KULONG_MASK | pid); - printf("getpgid(%d) = %ld\n", pid, rc); - - rc = syscall(__NR_setpgid, F8ILL_KULONG_MASK, F8ILL_KULONG_MASK | pid); - printf("setpgid(0, %d) = %ld\n", pid, rc); + PIDNS_TEST_INIT; + const int pid = getpid(); + long pgid = syscall(__NR_getpgid, F8ILL_KULONG_MASK | pid); + pidns_print_leader(); + printf("getpgid(%d%s) = %ld%s\n", pid, pidns_pid2str(PT_TGID), + pgid, pidns_pid2str(PT_PGID)); + + long rc = syscall(__NR_setpgid, F8ILL_KULONG_MASK, + F8ILL_KULONG_MASK | pgid); + pidns_print_leader(); + printf("setpgid(0, %ld%s) = %s\n", pgid, pidns_pid2str(PT_PGID), + sprintrc(rc)); + + pidns_print_leader(); puts("+++ exited with 0 +++"); return 0; } diff --git a/tests/xetpriority--pidns-translation.c b/tests/xetpriority--pidns-translation.c new file mode 100644 index 00000000..c93669cb --- /dev/null +++ b/tests/xetpriority--pidns-translation.c @@ -0,0 +1,2 @@ +#define PIDNS_TRANSLATION +#include "xetpriority.c" diff --git a/tests/xetpriority.c b/tests/xetpriority.c index 2d61bd10..dd38217d 100644 --- a/tests/xetpriority.c +++ b/tests/xetpriority.c @@ -7,6 +7,7 @@ #include "tests.h" #include "scno.h" +#include "pidns.h" #if defined __NR_getpriority && defined __NR_setpriority @@ -17,15 +18,30 @@ int main(void) { + PIDNS_TEST_INIT; + const int pid = getpid(); + const int pgid = getpgid(0); + long rc = syscall(__NR_getpriority, PRIO_PROCESS, F8ILL_KULONG_MASK | pid); - printf("getpriority(PRIO_PROCESS, %d) = %ld\n", pid, rc); + pidns_print_leader(); + printf("getpriority(PRIO_PROCESS, %d%s) = %ld\n", + pid, pidns_pid2str(PT_TGID), rc); rc = syscall(__NR_setpriority, PRIO_PROCESS, F8ILL_KULONG_MASK | pid, F8ILL_KULONG_MASK); - printf("setpriority(PRIO_PROCESS, %d, 0) = %s\n", pid, sprintrc(rc)); + pidns_print_leader(); + printf("setpriority(PRIO_PROCESS, %d%s, 0) = %s\n", + pid, pidns_pid2str(PT_TGID), sprintrc(rc)); + + rc = syscall(__NR_getpriority, PRIO_PGRP, + F8ILL_KULONG_MASK | pgid); + pidns_print_leader(); + printf("getpriority(PRIO_PGRP, %d%s) = %ld\n", + pgid, pidns_pid2str(PT_PGID), rc); + pidns_print_leader(); puts("+++ exited with 0 +++"); return 0; } -- 2.28.0 From ldv at altlinux.org Thu Aug 20 09:34:03 2020 From: ldv at altlinux.org (Dmitry V. Levin) Date: Thu, 20 Aug 2020 12:34:03 +0300 Subject: [PATCH v10 0/5] [PIDNS] Final In-Reply-To: <20200819181637.1096507-1-uzonyi.akos@gmail.com> References: <20200819181637.1096507-1-uzonyi.akos@gmail.com> Message-ID: <20200820093403.GA13651@altlinux.org> Hi, When I tried this patchset on various systems, on those where NS_* ioctl commands are not supported by the kernel, a lot of tests start failing with similar diagnostics. For example: FAIL: dup-y.gen =============== + ../strace -V + TIMEOUT='timeout -k 5 -s XCPU 2100' + timeout -k 5 -s XCPU 2100 true + '[' 1 -eq 0 ']' + exec timeout -k 5 -s XCPU 2100 ./dup-y.gen.test + run_strace_match_diff -a8 --trace=dup -y + args='-a8 --trace=dup -y' + '[' -n '-a8 --trace=dup -y' -a '(' -z '-a8 --trace=dup -y' -o -z '' ')' ']' + run_prog + '[' 0 -eq 0 ']' + set -- ../dup-y + args=../dup-y + ../dup-y + run_strace -a8 --trace=dup -y ../dup-y + args='-a8 --trace=dup -y ../dup-y' + ../../strace -o log -a8 --trace=dup -y ../dup-y ../../strace: NS_* ioctl commands are not supported by the kernel + match_diff log exp + local output expected error + '[' 2 -eq 0 ']' + output=log + shift + '[' 1 -eq 0 ']' + expected=exp + shift + '[' 0 -eq 0 ']' + error='../../strace -a8 --trace=dup -y ../dup-y output mismatch' + check_prog diff + type diff + diff -u -- exp log --- exp 2020-08-20 00:53:31.868741256 +0000 +++ log 2020-08-20 00:53:31.868741256 +0000 @@ -1,5 +1,5 @@ dup(-1) = -1 EBADF (Bad file descriptor) -dup(0) = 3 -dup(3) = 4 -dup(9) = 5 +dup(0) = 3 +dup(3) = 4 +dup(9) = 5 +++ exited with 0 +++ + fail_ '../../strace -a8 --trace=dup -y ../dup-y output mismatch' + warn_ 'dup-y.gen.test: failed test: ../../strace -a8 --trace=dup -y ../dup-y output mismatch' + printf '%s\n' 'dup-y.gen.test: failed test: ../../strace -a8 --trace=dup -y ../dup-y output mismatch' dup-y.gen.test: failed test: ../../strace -a8 --trace=dup -y ../dup-y output mismatch + exit 1 FAIL dup-y.gen.test (exit status: 1) -- ldv From uzonyi.akos at gmail.com Thu Aug 20 11:38:34 2020 From: uzonyi.akos at gmail.com (=?UTF-8?B?w4Frb3MgVXpvbnlp?=) Date: Thu, 20 Aug 2020 13:38:34 +0200 Subject: [PATCH v10 0/5] [PIDNS] Final In-Reply-To: <20200820093403.GA13651@altlinux.org> References: <20200819181637.1096507-1-uzonyi.akos@gmail.com> <20200820093403.GA13651@altlinux.org> Message-ID: On Thu, 20 Aug 2020 at 11:34, Dmitry V. Levin wrote: > Hi, > > When I tried this patchset on various systems, on those where NS_* ioctl > commands are not supported by the kernel, a lot of tests start failing with > similar diagnostics. For example: > > FAIL: dup-y.gen > =============== > > + ../strace -V > + TIMEOUT='timeout -k 5 -s XCPU 2100' > + timeout -k 5 -s XCPU 2100 true > + '[' 1 -eq 0 ']' > + exec timeout -k 5 -s XCPU 2100 ./dup-y.gen.test > + run_strace_match_diff -a8 --trace=dup -y > + args='-a8 --trace=dup -y' > + '[' -n '-a8 --trace=dup -y' -a '(' -z '-a8 --trace=dup -y' -o -z '' ')' ']' > + run_prog > + '[' 0 -eq 0 ']' > + set -- ../dup-y > + args=../dup-y > + ../dup-y > + run_strace -a8 --trace=dup -y ../dup-y > + args='-a8 --trace=dup -y ../dup-y' > + ../../strace -o log -a8 --trace=dup -y ../dup-y > ../../strace: NS_* ioctl commands are not supported by the kernel > + match_diff log exp > + local output expected error > + '[' 2 -eq 0 ']' > + output=log > + shift > + '[' 1 -eq 0 ']' > + expected=exp > + shift > + '[' 0 -eq 0 ']' > + error='../../strace -a8 --trace=dup -y ../dup-y output mismatch' > + check_prog diff > + type diff > + diff -u -- exp log > --- exp 2020-08-20 00:53:31.868741256 +0000 > +++ log 2020-08-20 00:53:31.868741256 +0000 > @@ -1,5 +1,5 @@ > dup(-1) = -1 EBADF (Bad file descriptor) > -dup(0) = 3 > -dup(3) = 4 > -dup(9) = 5 > +dup(0) = 3 > +dup(3) = 4 > +dup(9) = 5 > +++ exited with 0 +++ > + fail_ '../../strace -a8 --trace=dup -y ../dup-y output mismatch' > + warn_ 'dup-y.gen.test: failed test: ../../strace -a8 --trace=dup -y ../dup-y output mismatch' > + printf '%s\n' 'dup-y.gen.test: failed test: ../../strace -a8 --trace=dup -y ../dup-y output mismatch' > dup-y.gen.test: failed test: ../../strace -a8 --trace=dup -y ../dup-y output mismatch > + exit 1 > FAIL dup-y.gen.test (exit status: 1) Interesting. On travis we have some systems where NS_* ioctl commands are not supported, and all tests pass. I think the problem is caused by is_proc_ours returning false (otherwise translation should be trivial, and no NS_ ioctl commands would be needed). First I thought that /proc is not mounted on that system, but dup-y is skipped if /proc/self/fd is not available (anyway we should check if /proc is mounted and return 0 in translate_pid if not). Also I think we could print error messages if /proc/%s/ns/pid or /proc/%s/status is not available. Is it possible that these are not available on this system? From ldv at altlinux.org Thu Aug 20 11:44:01 2020 From: ldv at altlinux.org (Dmitry V. Levin) Date: Thu, 20 Aug 2020 14:44:01 +0300 Subject: [PATCH v10 0/5] [PIDNS] Final In-Reply-To: References: <20200819181637.1096507-1-uzonyi.akos@gmail.com> <20200820093403.GA13651@altlinux.org> Message-ID: <20200820114401.GB15515@altlinux.org> On Thu, Aug 20, 2020 at 01:38:34PM +0200, ?kos Uzonyi wrote: > On Thu, 20 Aug 2020 at 11:34, Dmitry V. Levin wrote: > > Hi, > > > > When I tried this patchset on various systems, on those where NS_* ioctl > > commands are not supported by the kernel, a lot of tests start failing with > > similar diagnostics. For example: > > > > FAIL: dup-y.gen > > =============== > > > > + ../strace -V > > + TIMEOUT='timeout -k 5 -s XCPU 2100' > > + timeout -k 5 -s XCPU 2100 true > > + '[' 1 -eq 0 ']' > > + exec timeout -k 5 -s XCPU 2100 ./dup-y.gen.test > > + run_strace_match_diff -a8 --trace=dup -y > > + args='-a8 --trace=dup -y' > > + '[' -n '-a8 --trace=dup -y' -a '(' -z '-a8 --trace=dup -y' -o -z '' ')' ']' > > + run_prog > > + '[' 0 -eq 0 ']' > > + set -- ../dup-y > > + args=../dup-y > > + ../dup-y > > + run_strace -a8 --trace=dup -y ../dup-y > > + args='-a8 --trace=dup -y ../dup-y' > > + ../../strace -o log -a8 --trace=dup -y ../dup-y > > ../../strace: NS_* ioctl commands are not supported by the kernel > > + match_diff log exp > > + local output expected error > > + '[' 2 -eq 0 ']' > > + output=log > > + shift > > + '[' 1 -eq 0 ']' > > + expected=exp > > + shift > > + '[' 0 -eq 0 ']' > > + error='../../strace -a8 --trace=dup -y ../dup-y output mismatch' > > + check_prog diff > > + type diff > > + diff -u -- exp log > > --- exp 2020-08-20 00:53:31.868741256 +0000 > > +++ log 2020-08-20 00:53:31.868741256 +0000 > > @@ -1,5 +1,5 @@ > > dup(-1) = -1 EBADF (Bad file descriptor) > > -dup(0) = 3 > > -dup(3) = 4 > > -dup(9) = 5 > > +dup(0) = 3 > > +dup(3) = 4 > > +dup(9) = 5 > > +++ exited with 0 +++ > > + fail_ '../../strace -a8 --trace=dup -y ../dup-y output mismatch' > > + warn_ 'dup-y.gen.test: failed test: ../../strace -a8 --trace=dup -y ../dup-y output mismatch' > > + printf '%s\n' 'dup-y.gen.test: failed test: ../../strace -a8 --trace=dup -y ../dup-y output mismatch' > > dup-y.gen.test: failed test: ../../strace -a8 --trace=dup -y ../dup-y output mismatch > > + exit 1 > > FAIL dup-y.gen.test (exit status: 1) > > Interesting. On travis we have some systems where NS_* ioctl commands > are not supported, and all tests pass. I think the problem is caused > by is_proc_ours returning false (otherwise translation should be > trivial, and no NS_ ioctl commands would be needed). First I thought > that /proc is not mounted on that system, but dup-y is skipped if > /proc/self/fd is not available (anyway we should check if /proc is > mounted and return 0 in translate_pid if not). Also I think we could > print error messages if /proc/%s/ns/pid or /proc/%s/status is not > available. Is it possible that these are not available on this system? No, both /proc/self/status and /proc/self/ns/pid are available, and $ readlink /proc/self/ns/pid pid:[4026532619] they look plausible. FWiW, the host where I first seen this is Linux el7-test.fedorainfracloud.org 3.10.0-957.1.3.el7.x86_64 #1 SMP Thu Nov 29 14:49:43 UTC 2018 x86_64 x86_64 x86_64 GNU/Linux -- ldv From uzonyi.akos at gmail.com Thu Aug 20 13:11:23 2020 From: uzonyi.akos at gmail.com (=?UTF-8?B?w4Frb3MgVXpvbnlp?=) Date: Thu, 20 Aug 2020 15:11:23 +0200 Subject: [PATCH v10 0/5] [PIDNS] Final In-Reply-To: <20200820114401.GB15515@altlinux.org> References: <20200819181637.1096507-1-uzonyi.akos@gmail.com> <20200820093403.GA13651@altlinux.org> <20200820114401.GB15515@altlinux.org> Message-ID: On Thu, 20 Aug 2020 at 13:44, Dmitry V. Levin wrote: > On Thu, Aug 20, 2020 at 01:38:34PM +0200, ?kos Uzonyi wrote: > > On Thu, 20 Aug 2020 at 11:34, Dmitry V. Levin wrote: > > > Hi, > > > > > > When I tried this patchset on various systems, on those where NS_* ioctl > > > commands are not supported by the kernel, a lot of tests start failing with > > > similar diagnostics. For example: > > > > > > FAIL: dup-y.gen > > > =============== > > > > > > + ../strace -V > > > + TIMEOUT='timeout -k 5 -s XCPU 2100' > > > + timeout -k 5 -s XCPU 2100 true > > > + '[' 1 -eq 0 ']' > > > + exec timeout -k 5 -s XCPU 2100 ./dup-y.gen.test > > > + run_strace_match_diff -a8 --trace=dup -y > > > + args='-a8 --trace=dup -y' > > > + '[' -n '-a8 --trace=dup -y' -a '(' -z '-a8 --trace=dup -y' -o -z '' ')' ']' > > > + run_prog > > > + '[' 0 -eq 0 ']' > > > + set -- ../dup-y > > > + args=../dup-y > > > + ../dup-y > > > + run_strace -a8 --trace=dup -y ../dup-y > > > + args='-a8 --trace=dup -y ../dup-y' > > > + ../../strace -o log -a8 --trace=dup -y ../dup-y > > > ../../strace: NS_* ioctl commands are not supported by the kernel > > > + match_diff log exp > > > + local output expected error > > > + '[' 2 -eq 0 ']' > > > + output=log > > > + shift > > > + '[' 1 -eq 0 ']' > > > + expected=exp > > > + shift > > > + '[' 0 -eq 0 ']' > > > + error='../../strace -a8 --trace=dup -y ../dup-y output mismatch' > > > + check_prog diff > > > + type diff > > > + diff -u -- exp log > > > --- exp 2020-08-20 00:53:31.868741256 +0000 > > > +++ log 2020-08-20 00:53:31.868741256 +0000 > > > @@ -1,5 +1,5 @@ > > > dup(-1) = -1 EBADF (Bad file descriptor) > > > -dup(0) = 3 > > > -dup(3) = 4 > > > -dup(9) = 5 > > > +dup(0) = 3 > > > +dup(3) = 4 > > > +dup(9) = 5 > > > +++ exited with 0 +++ > > > + fail_ '../../strace -a8 --trace=dup -y ../dup-y output mismatch' > > > + warn_ 'dup-y.gen.test: failed test: ../../strace -a8 --trace=dup -y ../dup-y output mismatch' > > > + printf '%s\n' 'dup-y.gen.test: failed test: ../../strace -a8 --trace=dup -y ../dup-y output mismatch' > > > dup-y.gen.test: failed test: ../../strace -a8 --trace=dup -y ../dup-y output mismatch > > > + exit 1 > > > FAIL dup-y.gen.test (exit status: 1) > > > > Interesting. On travis we have some systems where NS_* ioctl commands > > are not supported, and all tests pass. I think the problem is caused > > by is_proc_ours returning false (otherwise translation should be > > trivial, and no NS_ ioctl commands would be needed). First I thought > > that /proc is not mounted on that system, but dup-y is skipped if > > /proc/self/fd is not available (anyway we should check if /proc is > > mounted and return 0 in translate_pid if not). Also I think we could > > print error messages if /proc/%s/ns/pid or /proc/%s/status is not > > available. Is it possible that these are not available on this system? > > No, both /proc/self/status and /proc/self/ns/pid are available, and > $ readlink /proc/self/ns/pid > pid:[4026532619] > they look plausible. > > FWiW, the host where I first seen this is > Linux el7-test.fedorainfracloud.org 3.10.0-957.1.3.el7.x86_64 #1 SMP Thu Nov 29 14:49:43 UTC 2018 x86_64 x86_64 x86_64 GNU/Linux Interesting, the kernel version is 3.10.0, the test should have been skipped by check_ns_ioctl. Or is it possible somehow that NS_GET_USERNS is available and NS_GET_PARENT is not? From ldv at altlinux.org Thu Aug 20 13:19:25 2020 From: ldv at altlinux.org (Dmitry V. Levin) Date: Thu, 20 Aug 2020 16:19:25 +0300 Subject: [PATCH v10 0/5] [PIDNS] Final In-Reply-To: References: <20200819181637.1096507-1-uzonyi.akos@gmail.com> <20200820093403.GA13651@altlinux.org> <20200820114401.GB15515@altlinux.org> Message-ID: <20200820131925.GA17385@altlinux.org> On Thu, Aug 20, 2020 at 03:11:23PM +0200, ?kos Uzonyi wrote: > On Thu, 20 Aug 2020 at 13:44, Dmitry V. Levin wrote: > > On Thu, Aug 20, 2020 at 01:38:34PM +0200, ?kos Uzonyi wrote: > > > On Thu, 20 Aug 2020 at 11:34, Dmitry V. Levin wrote: > > > > Hi, > > > > > > > > When I tried this patchset on various systems, on those where NS_* ioctl > > > > commands are not supported by the kernel, a lot of tests start failing with > > > > similar diagnostics. For example: > > > > > > > > FAIL: dup-y.gen > > > > =============== > > > > > > > > + ../strace -V > > > > + TIMEOUT='timeout -k 5 -s XCPU 2100' > > > > + timeout -k 5 -s XCPU 2100 true > > > > + '[' 1 -eq 0 ']' > > > > + exec timeout -k 5 -s XCPU 2100 ./dup-y.gen.test > > > > + run_strace_match_diff -a8 --trace=dup -y > > > > + args='-a8 --trace=dup -y' > > > > + '[' -n '-a8 --trace=dup -y' -a '(' -z '-a8 --trace=dup -y' -o -z '' ')' ']' > > > > + run_prog > > > > + '[' 0 -eq 0 ']' > > > > + set -- ../dup-y > > > > + args=../dup-y > > > > + ../dup-y > > > > + run_strace -a8 --trace=dup -y ../dup-y > > > > + args='-a8 --trace=dup -y ../dup-y' > > > > + ../../strace -o log -a8 --trace=dup -y ../dup-y > > > > ../../strace: NS_* ioctl commands are not supported by the kernel > > > > + match_diff log exp > > > > + local output expected error > > > > + '[' 2 -eq 0 ']' > > > > + output=log > > > > + shift > > > > + '[' 1 -eq 0 ']' > > > > + expected=exp > > > > + shift > > > > + '[' 0 -eq 0 ']' > > > > + error='../../strace -a8 --trace=dup -y ../dup-y output mismatch' > > > > + check_prog diff > > > > + type diff > > > > + diff -u -- exp log > > > > --- exp 2020-08-20 00:53:31.868741256 +0000 > > > > +++ log 2020-08-20 00:53:31.868741256 +0000 > > > > @@ -1,5 +1,5 @@ > > > > dup(-1) = -1 EBADF (Bad file descriptor) > > > > -dup(0) = 3 > > > > -dup(3) = 4 > > > > -dup(9) = 5 > > > > +dup(0) = 3 > > > > +dup(3) = 4 > > > > +dup(9) = 5 > > > > +++ exited with 0 +++ > > > > + fail_ '../../strace -a8 --trace=dup -y ../dup-y output mismatch' > > > > + warn_ 'dup-y.gen.test: failed test: ../../strace -a8 --trace=dup -y ../dup-y output mismatch' > > > > + printf '%s\n' 'dup-y.gen.test: failed test: ../../strace -a8 --trace=dup -y ../dup-y output mismatch' > > > > dup-y.gen.test: failed test: ../../strace -a8 --trace=dup -y ../dup-y output mismatch > > > > + exit 1 > > > > FAIL dup-y.gen.test (exit status: 1) > > > > > > Interesting. On travis we have some systems where NS_* ioctl commands > > > are not supported, and all tests pass. I think the problem is caused > > > by is_proc_ours returning false (otherwise translation should be > > > trivial, and no NS_ ioctl commands would be needed). First I thought > > > that /proc is not mounted on that system, but dup-y is skipped if > > > /proc/self/fd is not available (anyway we should check if /proc is > > > mounted and return 0 in translate_pid if not). Also I think we could > > > print error messages if /proc/%s/ns/pid or /proc/%s/status is not > > > available. Is it possible that these are not available on this system? > > > > No, both /proc/self/status and /proc/self/ns/pid are available, and > > $ readlink /proc/self/ns/pid > > pid:[4026532619] > > they look plausible. > > > > FWiW, the host where I first seen this is > > Linux el7-test.fedorainfracloud.org 3.10.0-957.1.3.el7.x86_64 #1 SMP Thu Nov 29 14:49:43 UTC 2018 x86_64 x86_64 x86_64 GNU/Linux > > Interesting, the kernel version is 3.10.0, the test should have been > skipped by check_ns_ioctl. Or is it possible somehow that > NS_GET_USERNS is available and NS_GET_PARENT is not? As that is a vendor kernel, everything is possible. I can check this. -- ldv From ldv at altlinux.org Thu Aug 20 15:56:36 2020 From: ldv at altlinux.org (Dmitry V. Levin) Date: Thu, 20 Aug 2020 18:56:36 +0300 Subject: [PATCH v10 0/5] [PIDNS] Final In-Reply-To: <20200820131925.GA17385@altlinux.org> References: <20200819181637.1096507-1-uzonyi.akos@gmail.com> <20200820093403.GA13651@altlinux.org> <20200820114401.GB15515@altlinux.org> <20200820131925.GA17385@altlinux.org> Message-ID: <20200820155635.GA19109@altlinux.org> On Thu, Aug 20, 2020 at 04:19:25PM +0300, Dmitry V. Levin wrote: > On Thu, Aug 20, 2020 at 03:11:23PM +0200, ?kos Uzonyi wrote: > > On Thu, 20 Aug 2020 at 13:44, Dmitry V. Levin wrote: > > > On Thu, Aug 20, 2020 at 01:38:34PM +0200, ?kos Uzonyi wrote: > > > > On Thu, 20 Aug 2020 at 11:34, Dmitry V. Levin wrote: > > > > > Hi, > > > > > > > > > > When I tried this patchset on various systems, on those where NS_* ioctl > > > > > commands are not supported by the kernel, a lot of tests start failing with > > > > > similar diagnostics. For example: > > > > > > > > > > FAIL: dup-y.gen > > > > > =============== > > > > > > > > > > + ../strace -V > > > > > + TIMEOUT='timeout -k 5 -s XCPU 2100' > > > > > + timeout -k 5 -s XCPU 2100 true > > > > > + '[' 1 -eq 0 ']' > > > > > + exec timeout -k 5 -s XCPU 2100 ./dup-y.gen.test > > > > > + run_strace_match_diff -a8 --trace=dup -y > > > > > + args='-a8 --trace=dup -y' > > > > > + '[' -n '-a8 --trace=dup -y' -a '(' -z '-a8 --trace=dup -y' -o -z '' ')' ']' > > > > > + run_prog > > > > > + '[' 0 -eq 0 ']' > > > > > + set -- ../dup-y > > > > > + args=../dup-y > > > > > + ../dup-y > > > > > + run_strace -a8 --trace=dup -y ../dup-y > > > > > + args='-a8 --trace=dup -y ../dup-y' > > > > > + ../../strace -o log -a8 --trace=dup -y ../dup-y > > > > > ../../strace: NS_* ioctl commands are not supported by the kernel > > > > > + match_diff log exp > > > > > + local output expected error > > > > > + '[' 2 -eq 0 ']' > > > > > + output=log > > > > > + shift > > > > > + '[' 1 -eq 0 ']' > > > > > + expected=exp > > > > > + shift > > > > > + '[' 0 -eq 0 ']' > > > > > + error='../../strace -a8 --trace=dup -y ../dup-y output mismatch' > > > > > + check_prog diff > > > > > + type diff > > > > > + diff -u -- exp log > > > > > --- exp 2020-08-20 00:53:31.868741256 +0000 > > > > > +++ log 2020-08-20 00:53:31.868741256 +0000 > > > > > @@ -1,5 +1,5 @@ > > > > > dup(-1) = -1 EBADF (Bad file descriptor) > > > > > -dup(0) = 3 > > > > > -dup(3) = 4 > > > > > -dup(9) = 5 > > > > > +dup(0) = 3 > > > > > +dup(3) = 4 > > > > > +dup(9) = 5 > > > > > +++ exited with 0 +++ > > > > > + fail_ '../../strace -a8 --trace=dup -y ../dup-y output mismatch' > > > > > + warn_ 'dup-y.gen.test: failed test: ../../strace -a8 --trace=dup -y ../dup-y output mismatch' > > > > > + printf '%s\n' 'dup-y.gen.test: failed test: ../../strace -a8 --trace=dup -y ../dup-y output mismatch' > > > > > dup-y.gen.test: failed test: ../../strace -a8 --trace=dup -y ../dup-y output mismatch > > > > > + exit 1 > > > > > FAIL dup-y.gen.test (exit status: 1) > > > > > > > > Interesting. On travis we have some systems where NS_* ioctl commands > > > > are not supported, and all tests pass. I think the problem is caused > > > > by is_proc_ours returning false (otherwise translation should be > > > > trivial, and no NS_ ioctl commands would be needed). First I thought > > > > that /proc is not mounted on that system, but dup-y is skipped if > > > > /proc/self/fd is not available (anyway we should check if /proc is > > > > mounted and return 0 in translate_pid if not). Also I think we could > > > > print error messages if /proc/%s/ns/pid or /proc/%s/status is not > > > > available. Is it possible that these are not available on this system? > > > > > > No, both /proc/self/status and /proc/self/ns/pid are available, and > > > $ readlink /proc/self/ns/pid > > > pid:[4026532619] > > > they look plausible. > > > > > > FWiW, the host where I first seen this is > > > Linux el7-test.fedorainfracloud.org 3.10.0-957.1.3.el7.x86_64 #1 SMP Thu Nov 29 14:49:43 UTC 2018 x86_64 x86_64 x86_64 GNU/Linux > > > > Interesting, the kernel version is 3.10.0, the test should have been > > skipped by check_ns_ioctl. Or is it possible somehow that > > NS_GET_USERNS is available and NS_GET_PARENT is not? > > As that is a vendor kernel, everything is possible. > I can check this. No, in that system NS_GET_USERNS fails with ENOTTY: open("/proc/self/ns/pid", O_RDONLY) = 3 ioctl(3, NS_GET_USERNS) = -1 ENOTTY (Inappropriate ioctl for device) -- ldv From uzonyi.akos at gmail.com Thu Aug 20 16:38:26 2020 From: uzonyi.akos at gmail.com (=?UTF-8?B?w4Frb3MgVXpvbnlp?=) Date: Thu, 20 Aug 2020 18:38:26 +0200 Subject: [PATCH v10 0/5] [PIDNS] Final In-Reply-To: <20200820155635.GA19109@altlinux.org> References: <20200819181637.1096507-1-uzonyi.akos@gmail.com> <20200820093403.GA13651@altlinux.org> <20200820114401.GB15515@altlinux.org> <20200820131925.GA17385@altlinux.org> <20200820155635.GA19109@altlinux.org> Message-ID: On Thu, 20 Aug 2020 at 17:56, Dmitry V. Levin wrote: > On Thu, Aug 20, 2020 at 04:19:25PM +0300, Dmitry V. Levin wrote: > > On Thu, Aug 20, 2020 at 03:11:23PM +0200, ?kos Uzonyi wrote: > > > On Thu, 20 Aug 2020 at 13:44, Dmitry V. Levin wrote: > > > > On Thu, Aug 20, 2020 at 01:38:34PM +0200, ?kos Uzonyi wrote: > > > > > On Thu, 20 Aug 2020 at 11:34, Dmitry V. Levin wrote: > > > > > > Hi, > > > > > > > > > > > > When I tried this patchset on various systems, on those where NS_* ioctl > > > > > > commands are not supported by the kernel, a lot of tests start failing with > > > > > > similar diagnostics. For example: > > > > > > > > > > > > FAIL: dup-y.gen > > > > > > =============== > > > > > > > > > > > > + ../strace -V > > > > > > + TIMEOUT='timeout -k 5 -s XCPU 2100' > > > > > > + timeout -k 5 -s XCPU 2100 true > > > > > > + '[' 1 -eq 0 ']' > > > > > > + exec timeout -k 5 -s XCPU 2100 ./dup-y.gen.test > > > > > > + run_strace_match_diff -a8 --trace=dup -y > > > > > > + args='-a8 --trace=dup -y' > > > > > > + '[' -n '-a8 --trace=dup -y' -a '(' -z '-a8 --trace=dup -y' -o -z '' ')' ']' > > > > > > + run_prog > > > > > > + '[' 0 -eq 0 ']' > > > > > > + set -- ../dup-y > > > > > > + args=../dup-y > > > > > > + ../dup-y > > > > > > + run_strace -a8 --trace=dup -y ../dup-y > > > > > > + args='-a8 --trace=dup -y ../dup-y' > > > > > > + ../../strace -o log -a8 --trace=dup -y ../dup-y > > > > > > ../../strace: NS_* ioctl commands are not supported by the kernel > > > > > > + match_diff log exp > > > > > > + local output expected error > > > > > > + '[' 2 -eq 0 ']' > > > > > > + output=log > > > > > > + shift > > > > > > + '[' 1 -eq 0 ']' > > > > > > + expected=exp > > > > > > + shift > > > > > > + '[' 0 -eq 0 ']' > > > > > > + error='../../strace -a8 --trace=dup -y ../dup-y output mismatch' > > > > > > + check_prog diff > > > > > > + type diff > > > > > > + diff -u -- exp log > > > > > > --- exp 2020-08-20 00:53:31.868741256 +0000 > > > > > > +++ log 2020-08-20 00:53:31.868741256 +0000 > > > > > > @@ -1,5 +1,5 @@ > > > > > > dup(-1) = -1 EBADF (Bad file descriptor) > > > > > > -dup(0) = 3 > > > > > > -dup(3) = 4 > > > > > > -dup(9) = 5 > > > > > > +dup(0) = 3 > > > > > > +dup(3) = 4 > > > > > > +dup(9) = 5 > > > > > > +++ exited with 0 +++ > > > > > > + fail_ '../../strace -a8 --trace=dup -y ../dup-y output mismatch' > > > > > > + warn_ 'dup-y.gen.test: failed test: ../../strace -a8 --trace=dup -y ../dup-y output mismatch' > > > > > > + printf '%s\n' 'dup-y.gen.test: failed test: ../../strace -a8 --trace=dup -y ../dup-y output mismatch' > > > > > > dup-y.gen.test: failed test: ../../strace -a8 --trace=dup -y ../dup-y output mismatch > > > > > > + exit 1 > > > > > > FAIL dup-y.gen.test (exit status: 1) > > > > > > > > > > Interesting. On travis we have some systems where NS_* ioctl commands > > > > > are not supported, and all tests pass. I think the problem is caused > > > > > by is_proc_ours returning false (otherwise translation should be > > > > > trivial, and no NS_ ioctl commands would be needed). First I thought > > > > > that /proc is not mounted on that system, but dup-y is skipped if > > > > > /proc/self/fd is not available (anyway we should check if /proc is > > > > > mounted and return 0 in translate_pid if not). Also I think we could > > > > > print error messages if /proc/%s/ns/pid or /proc/%s/status is not > > > > > available. Is it possible that these are not available on this system? > > > > > > > > No, both /proc/self/status and /proc/self/ns/pid are available, and > > > > $ readlink /proc/self/ns/pid > > > > pid:[4026532619] > > > > they look plausible. > > > > > > > > FWiW, the host where I first seen this is > > > > Linux el7-test.fedorainfracloud.org 3.10.0-957.1.3.el7.x86_64 #1 SMP Thu Nov 29 14:49:43 UTC 2018 x86_64 x86_64 x86_64 GNU/Linux > > > > > > Interesting, the kernel version is 3.10.0, the test should have been > > > skipped by check_ns_ioctl. Or is it possible somehow that > > > NS_GET_USERNS is available and NS_GET_PARENT is not? > > > > As that is a vendor kernel, everything is possible. > > I can check this. > > No, in that system NS_GET_USERNS fails with ENOTTY: > > open("/proc/self/ns/pid", O_RDONLY) = 3 > ioctl(3, NS_GET_USERNS) = -1 ENOTTY (Inappropriate ioctl for device) Thanks for checking it. I realized I was wrong, as check_ns_ioctl is not called in dup-y test (it's not a pidns test). I think get_proc_pid returns false for some reason, and that causes this problem. I'll send a patch that adds more error messages, could you please run the test again with that patch applied? From uzonyi.akos at gmail.com Thu Aug 20 16:39:30 2020 From: uzonyi.akos at gmail.com (=?UTF-8?q?=C3=81kos=20Uzonyi?=) Date: Thu, 20 Aug 2020 18:39:30 +0200 Subject: [PATCH] Print more error messages Message-ID: <20200820163930.1103778-1-uzonyi.akos@gmail.com> --- Could you please run the dup-y test again with this patch applied? Hopefully we'll see where the problem comes from. pidns.c | 15 ++++++++++++--- 1 file changed, 12 insertions(+), 3 deletions(-) diff --git a/pidns.c b/pidns.c index 9d8695da..7e7d8212 100644 --- a/pidns.c +++ b/pidns.c @@ -168,14 +168,18 @@ get_ns_hierarchy(int proc_pid, unsigned int *ns_buf, size_t ns_buf_size) xsprintf(path, "/proc/%s/ns/pid", pid_to_str(proc_pid)); int fd = open_file(path, O_RDONLY); - if (fd < 0) + if (fd < 0) { + perror_func_msg("opening %s", path); return 0; + } size_t n = 0; while (n < ns_buf_size) { strace_stat_t st; - if (fstat_fd(fd, &st)) + if (fstat_fd(fd, &st)) { + perror_func_msg("fstat_fd"); break; + } ns_buf[n++] = st.st_ino; if (n >= ns_buf_size) @@ -234,8 +238,10 @@ get_id_list(int proc_pid, int *id_buf, enum pid_type type) char status_path[PATH_MAX + 1]; xsprintf(status_path, "/proc/%s/status", pid_to_str(proc_pid)); FILE *f = fopen_stream(status_path, "r"); - if (!f) + if (!f) { + error_func_msg("opening %s", status_path); return 0; + } char *line = NULL; size_t linesize = 0; @@ -248,6 +254,9 @@ get_id_list(int proc_pid, int *id_buf, enum pid_type type) } } + if (!p) + error_func_msg("no line found starting with %s", ns_str); + while (p) { errno = 0; long id = strtol(p, NULL, 10); -- 2.28.0 From ldv at altlinux.org Thu Aug 20 16:46:36 2020 From: ldv at altlinux.org (Dmitry V. Levin) Date: Thu, 20 Aug 2020 19:46:36 +0300 Subject: [PATCH v10 0/5] [PIDNS] Final In-Reply-To: References: <20200819181637.1096507-1-uzonyi.akos@gmail.com> <20200820093403.GA13651@altlinux.org> <20200820114401.GB15515@altlinux.org> <20200820131925.GA17385@altlinux.org> <20200820155635.GA19109@altlinux.org> Message-ID: <20200820164636.GB19738@altlinux.org> On Thu, Aug 20, 2020 at 06:38:26PM +0200, ?kos Uzonyi wrote: > On Thu, 20 Aug 2020 at 17:56, Dmitry V. Levin wrote: > > On Thu, Aug 20, 2020 at 04:19:25PM +0300, Dmitry V. Levin wrote: > > > On Thu, Aug 20, 2020 at 03:11:23PM +0200, ?kos Uzonyi wrote: > > > > On Thu, 20 Aug 2020 at 13:44, Dmitry V. Levin wrote: > > > > > On Thu, Aug 20, 2020 at 01:38:34PM +0200, ?kos Uzonyi wrote: > > > > > > On Thu, 20 Aug 2020 at 11:34, Dmitry V. Levin wrote: > > > > > > > Hi, > > > > > > > > > > > > > > When I tried this patchset on various systems, on those where NS_* ioctl > > > > > > > commands are not supported by the kernel, a lot of tests start failing with > > > > > > > similar diagnostics. For example: > > > > > > > > > > > > > > FAIL: dup-y.gen > > > > > > > =============== > > > > > > > > > > > > > > + ../strace -V > > > > > > > + TIMEOUT='timeout -k 5 -s XCPU 2100' > > > > > > > + timeout -k 5 -s XCPU 2100 true > > > > > > > + '[' 1 -eq 0 ']' > > > > > > > + exec timeout -k 5 -s XCPU 2100 ./dup-y.gen.test > > > > > > > + run_strace_match_diff -a8 --trace=dup -y > > > > > > > + args='-a8 --trace=dup -y' > > > > > > > + '[' -n '-a8 --trace=dup -y' -a '(' -z '-a8 --trace=dup -y' -o -z '' ')' ']' > > > > > > > + run_prog > > > > > > > + '[' 0 -eq 0 ']' > > > > > > > + set -- ../dup-y > > > > > > > + args=../dup-y > > > > > > > + ../dup-y > > > > > > > + run_strace -a8 --trace=dup -y ../dup-y > > > > > > > + args='-a8 --trace=dup -y ../dup-y' > > > > > > > + ../../strace -o log -a8 --trace=dup -y ../dup-y > > > > > > > ../../strace: NS_* ioctl commands are not supported by the kernel > > > > > > > + match_diff log exp > > > > > > > + local output expected error > > > > > > > + '[' 2 -eq 0 ']' > > > > > > > + output=log > > > > > > > + shift > > > > > > > + '[' 1 -eq 0 ']' > > > > > > > + expected=exp > > > > > > > + shift > > > > > > > + '[' 0 -eq 0 ']' > > > > > > > + error='../../strace -a8 --trace=dup -y ../dup-y output mismatch' > > > > > > > + check_prog diff > > > > > > > + type diff > > > > > > > + diff -u -- exp log > > > > > > > --- exp 2020-08-20 00:53:31.868741256 +0000 > > > > > > > +++ log 2020-08-20 00:53:31.868741256 +0000 > > > > > > > @@ -1,5 +1,5 @@ > > > > > > > dup(-1) = -1 EBADF (Bad file descriptor) > > > > > > > -dup(0) = 3 > > > > > > > -dup(3) = 4 > > > > > > > -dup(9) = 5 > > > > > > > +dup(0) = 3 > > > > > > > +dup(3) = 4 > > > > > > > +dup(9) = 5 > > > > > > > +++ exited with 0 +++ > > > > > > > + fail_ '../../strace -a8 --trace=dup -y ../dup-y output mismatch' > > > > > > > + warn_ 'dup-y.gen.test: failed test: ../../strace -a8 --trace=dup -y ../dup-y output mismatch' > > > > > > > + printf '%s\n' 'dup-y.gen.test: failed test: ../../strace -a8 --trace=dup -y ../dup-y output mismatch' > > > > > > > dup-y.gen.test: failed test: ../../strace -a8 --trace=dup -y ../dup-y output mismatch > > > > > > > + exit 1 > > > > > > > FAIL dup-y.gen.test (exit status: 1) > > > > > > > > > > > > Interesting. On travis we have some systems where NS_* ioctl commands > > > > > > are not supported, and all tests pass. I think the problem is caused > > > > > > by is_proc_ours returning false (otherwise translation should be > > > > > > trivial, and no NS_ ioctl commands would be needed). First I thought > > > > > > that /proc is not mounted on that system, but dup-y is skipped if > > > > > > /proc/self/fd is not available (anyway we should check if /proc is > > > > > > mounted and return 0 in translate_pid if not). Also I think we could > > > > > > print error messages if /proc/%s/ns/pid or /proc/%s/status is not > > > > > > available. Is it possible that these are not available on this system? > > > > > > > > > > No, both /proc/self/status and /proc/self/ns/pid are available, and > > > > > $ readlink /proc/self/ns/pid > > > > > pid:[4026532619] > > > > > they look plausible. > > > > > > > > > > FWiW, the host where I first seen this is > > > > > Linux el7-test.fedorainfracloud.org 3.10.0-957.1.3.el7.x86_64 #1 SMP Thu Nov 29 14:49:43 UTC 2018 x86_64 x86_64 x86_64 GNU/Linux > > > > > > > > Interesting, the kernel version is 3.10.0, the test should have been > > > > skipped by check_ns_ioctl. Or is it possible somehow that > > > > NS_GET_USERNS is available and NS_GET_PARENT is not? > > > > > > As that is a vendor kernel, everything is possible. > > > I can check this. > > > > No, in that system NS_GET_USERNS fails with ENOTTY: > > > > open("/proc/self/ns/pid", O_RDONLY) = 3 > > ioctl(3, NS_GET_USERNS) = -1 ENOTTY (Inappropriate ioctl for device) > > Thanks for checking it. > > I realized I was wrong, as check_ns_ioctl is not called in dup-y test > (it's not a pidns test). I think get_proc_pid returns false for some > reason, and that causes this problem. I'll send a patch that adds more > error messages, could you please run the test again with that patch > applied? Yes, sure. -- ldv From ldv at altlinux.org Thu Aug 20 16:57:13 2020 From: ldv at altlinux.org (Dmitry V. Levin) Date: Thu, 20 Aug 2020 19:57:13 +0300 Subject: [PATCH] Print more error messages In-Reply-To: <20200820163930.1103778-1-uzonyi.akos@gmail.com> References: <20200820163930.1103778-1-uzonyi.akos@gmail.com> Message-ID: <20200820165713.GC19738@altlinux.org> On Thu, Aug 20, 2020 at 06:39:30PM +0200, ?kos Uzonyi wrote: > --- > > Could you please run the dup-y test again with this patch applied? > Hopefully we'll see where the problem comes from. > > pidns.c | 15 ++++++++++++--- > 1 file changed, 12 insertions(+), 3 deletions(-) > > diff --git a/pidns.c b/pidns.c > index 9d8695da..7e7d8212 100644 > --- a/pidns.c > +++ b/pidns.c > @@ -168,14 +168,18 @@ get_ns_hierarchy(int proc_pid, unsigned int *ns_buf, size_t ns_buf_size) > xsprintf(path, "/proc/%s/ns/pid", pid_to_str(proc_pid)); > > int fd = open_file(path, O_RDONLY); > - if (fd < 0) > + if (fd < 0) { > + perror_func_msg("opening %s", path); > return 0; > + } There are quite a few of these, e.g. get_ns_hierarchy: opening /proc/1/ns/pid: Permission denied but they are harmless. > @@ -248,6 +254,9 @@ get_id_list(int proc_pid, int *id_buf, enum pid_type type) > } > } > > + if (!p) > + error_func_msg("no line found starting with %s", ns_str); Yes, that was it, it prints "no line found starting with NSpid:". On that system I also see the following: $ grep -c ^NS /proc/self/status 0 -- ldv From ldv at altlinux.org Thu Aug 20 17:41:13 2020 From: ldv at altlinux.org (Dmitry V. Levin) Date: Thu, 20 Aug 2020 20:41:13 +0300 Subject: [PATCH v10 4/5] Implement testing framework for pidns In-Reply-To: <20200819181637.1096507-5-uzonyi.akos@gmail.com> References: <20200819181637.1096507-1-uzonyi.akos@gmail.com> <20200819181637.1096507-5-uzonyi.akos@gmail.com> Message-ID: <20200820174113.GA20582@altlinux.org> On Wed, Aug 19, 2020 at 08:16:36PM +0200, ?kos Uzonyi wrote: [...] > +test_pidns() > +{ > + check_prog unshare > + > + test_pidns_run_strace "$@" > + > + # test PID translation when /proc is mounted from an other namespace > + STRACE="unshare -Urpf $STRACE" > + test_pidns_run_strace "$@" > +} Apparently, a check for simple presence of unshare is not enough, there are systems where unshare doesn't work as expected, see e.g. https://build.opensuse.org/package/live_build_log/home:ldv_alt/strace/RHEL_7/x86_6 I suggest to framework_skip_ if "unshare -Urpf true" doesn't exit successfully. -- ldv From uzonyi.akos at gmail.com Thu Aug 20 17:48:57 2020 From: uzonyi.akos at gmail.com (=?UTF-8?B?w4Frb3MgVXpvbnlp?=) Date: Thu, 20 Aug 2020 19:48:57 +0200 Subject: [PATCH v10 4/5] Implement testing framework for pidns In-Reply-To: <20200820174113.GA20582@altlinux.org> References: <20200819181637.1096507-1-uzonyi.akos@gmail.com> <20200819181637.1096507-5-uzonyi.akos@gmail.com> <20200820174113.GA20582@altlinux.org> Message-ID: On Thu, 20 Aug 2020 at 19:41, Dmitry V. Levin wrote: > On Wed, Aug 19, 2020 at 08:16:36PM +0200, ?kos Uzonyi wrote: > [...] > > +test_pidns() > > +{ > > + check_prog unshare > > + > > + test_pidns_run_strace "$@" > > + > > + # test PID translation when /proc is mounted from an other namespace > > + STRACE="unshare -Urpf $STRACE" > > + test_pidns_run_strace "$@" > > +} > > Apparently, a check for simple presence of unshare is not enough, > there are systems where unshare doesn't work as expected, see e.g. > https://build.opensuse.org/package/live_build_log/home:ldv_alt/strace/RHEL_7/x86_6 > > I suggest to framework_skip_ if "unshare -Urpf true" doesn't exit > successfully. Thanks, I'll add this check. From ldv at altlinux.org Thu Aug 20 17:51:10 2020 From: ldv at altlinux.org (Dmitry V. Levin) Date: Thu, 20 Aug 2020 20:51:10 +0300 Subject: [PATCH v10 4/5] Implement testing framework for pidns In-Reply-To: <20200819181637.1096507-5-uzonyi.akos@gmail.com> References: <20200819181637.1096507-1-uzonyi.akos@gmail.com> <20200819181637.1096507-5-uzonyi.akos@gmail.com> Message-ID: <20200820175110.GB20582@altlinux.org> On Wed, Aug 19, 2020 at 08:16:36PM +0200, ?kos Uzonyi wrote: [...] > +void > +pidns_test_init(void) > +{ > + pidns_translation = true; > + > + check_ns_ioctl(); > + > + if (!pidns_fork(-1, false)) > + return; > + > + /* Unshare user namespace too, so we do not need to be root */ > + if (unshare(CLONE_NEWUSER | CLONE_NEWPID) < 0) { > + if (errno == EPERM) > + perror_msg_and_skip("unshare"); > + > + perror_msg_and_fail("unshare"); > + } This code fails to compile on the following system: https://build.opensuse.org/package/live_build_log/home:ldv_alt/strace/RedHat_RHEL-5/x86_64 pidns.c: In function 'pidns_test_init': pidns.c:204: error: 'CLONE_NEWUSER' undeclared (first use in this function) pidns.c:204: error: (Each undeclared identifier is reported only once pidns.c:204: error: for each function it appears in.) pidns.c:204: error: 'CLONE_NEWPID' undeclared (first use in this function) A similar compilation issue exists in fork--pidns-translation.c, too. -- ldv From uzonyi.akos at gmail.com Thu Aug 20 17:54:34 2020 From: uzonyi.akos at gmail.com (=?UTF-8?B?w4Frb3MgVXpvbnlp?=) Date: Thu, 20 Aug 2020 19:54:34 +0200 Subject: [PATCH] Print more error messages In-Reply-To: <20200820165713.GC19738@altlinux.org> References: <20200820163930.1103778-1-uzonyi.akos@gmail.com> <20200820165713.GC19738@altlinux.org> Message-ID: On Thu, 20 Aug 2020 at 18:57, Dmitry V. Levin wrote: > On Thu, Aug 20, 2020 at 06:39:30PM +0200, ?kos Uzonyi wrote: > > --- > > > > Could you please run the dup-y test again with this patch applied? > > Hopefully we'll see where the problem comes from. > > > > pidns.c | 15 ++++++++++++--- > > 1 file changed, 12 insertions(+), 3 deletions(-) > > > > diff --git a/pidns.c b/pidns.c > > index 9d8695da..7e7d8212 100644 > > --- a/pidns.c > > +++ b/pidns.c > > @@ -168,14 +168,18 @@ get_ns_hierarchy(int proc_pid, unsigned int *ns_buf, size_t ns_buf_size) > > xsprintf(path, "/proc/%s/ns/pid", pid_to_str(proc_pid)); > > > > int fd = open_file(path, O_RDONLY); > > - if (fd < 0) > > + if (fd < 0) { > > + perror_func_msg("opening %s", path); > > return 0; > > + } > > There are quite a few of these, e.g. > get_ns_hierarchy: opening /proc/1/ns/pid: Permission denied > but they are harmless. I was thinking about keeping these messages in the final version, but I think we don't need these permission denied errors, so it seems better not to keep them. > > @@ -248,6 +254,9 @@ get_id_list(int proc_pid, int *id_buf, enum pid_type type) > > } > > } > > > > + if (!p) > > + error_func_msg("no line found starting with %s", ns_str); > > Yes, that was it, it prints "no line found starting with NSpid:". > On that system I also see the following: > $ grep -c ^NS /proc/self/status > 0 Nice, thanks. Then I think we should modify this line a bit in is_proc_ours: - cached_val = get_id_list(0, NULL, PT_TID) == 1; + cached_val = get_id_list(0, NULL, PT_TID) <= 1; So in case get_id_list returns 0, we consider /proc to be ours, as this most probably means there is no PID namespace support in the kernel. From uzonyi.akos at gmail.com Thu Aug 20 18:07:53 2020 From: uzonyi.akos at gmail.com (=?UTF-8?B?w4Frb3MgVXpvbnlp?=) Date: Thu, 20 Aug 2020 20:07:53 +0200 Subject: [PATCH v10 4/5] Implement testing framework for pidns In-Reply-To: <20200820175110.GB20582@altlinux.org> References: <20200819181637.1096507-1-uzonyi.akos@gmail.com> <20200819181637.1096507-5-uzonyi.akos@gmail.com> <20200820175110.GB20582@altlinux.org> Message-ID: On Thu, 20 Aug 2020 at 19:51, Dmitry V. Levin wrote: > On Wed, Aug 19, 2020 at 08:16:36PM +0200, ?kos Uzonyi wrote: > [...] > > +void > > +pidns_test_init(void) > > +{ > > + pidns_translation = true; > > + > > + check_ns_ioctl(); > > + > > + if (!pidns_fork(-1, false)) > > + return; > > + > > + /* Unshare user namespace too, so we do not need to be root */ > > + if (unshare(CLONE_NEWUSER | CLONE_NEWPID) < 0) { > > + if (errno == EPERM) > > + perror_msg_and_skip("unshare"); > > + > > + perror_msg_and_fail("unshare"); > > + } > > This code fails to compile on the following system: > https://build.opensuse.org/package/live_build_log/home:ldv_alt/strace/RedHat_RHEL-5/x86_64 > > pidns.c: In function 'pidns_test_init': > pidns.c:204: error: 'CLONE_NEWUSER' undeclared (first use in this function) > pidns.c:204: error: (Each undeclared identifier is reported only once > pidns.c:204: error: for each function it appears in.) > pidns.c:204: error: 'CLONE_NEWPID' undeclared (first use in this function) > > A similar compilation issue exists in fork--pidns-translation.c, too. I think "#define _GNU_SOURCE" should be added to the beginning of the file. I'll add it, hopefully it solves the problem. From ldv at altlinux.org Thu Aug 20 18:10:38 2020 From: ldv at altlinux.org (Dmitry V. Levin) Date: Thu, 20 Aug 2020 21:10:38 +0300 Subject: [PATCH v10 4/5] Implement testing framework for pidns In-Reply-To: References: <20200819181637.1096507-1-uzonyi.akos@gmail.com> <20200819181637.1096507-5-uzonyi.akos@gmail.com> <20200820175110.GB20582@altlinux.org> Message-ID: <20200820181038.GC20582@altlinux.org> On Thu, Aug 20, 2020 at 08:07:53PM +0200, ?kos Uzonyi wrote: > On Thu, 20 Aug 2020 at 19:51, Dmitry V. Levin wrote: > > On Wed, Aug 19, 2020 at 08:16:36PM +0200, ?kos Uzonyi wrote: > > [...] > > > +void > > > +pidns_test_init(void) > > > +{ > > > + pidns_translation = true; > > > + > > > + check_ns_ioctl(); > > > + > > > + if (!pidns_fork(-1, false)) > > > + return; > > > + > > > + /* Unshare user namespace too, so we do not need to be root */ > > > + if (unshare(CLONE_NEWUSER | CLONE_NEWPID) < 0) { > > > + if (errno == EPERM) > > > + perror_msg_and_skip("unshare"); > > > + > > > + perror_msg_and_fail("unshare"); > > > + } > > > > This code fails to compile on the following system: > > https://build.opensuse.org/package/live_build_log/home:ldv_alt/strace/RedHat_RHEL-5/x86_64 > > > > pidns.c: In function 'pidns_test_init': > > pidns.c:204: error: 'CLONE_NEWUSER' undeclared (first use in this function) > > pidns.c:204: error: (Each undeclared identifier is reported only once > > pidns.c:204: error: for each function it appears in.) > > pidns.c:204: error: 'CLONE_NEWPID' undeclared (first use in this function) > > > > A similar compilation issue exists in fork--pidns-translation.c, too. > > I think "#define _GNU_SOURCE" should be added to the beginning of the > file. I'll add it, hopefully it solves the problem. No, it's already there due to config.h, I think some ifdefs like in tests/ioctl_nsfs.c might be useful. -- ldv From ldv at altlinux.org Thu Aug 20 18:12:27 2020 From: ldv at altlinux.org (Dmitry V. Levin) Date: Thu, 20 Aug 2020 21:12:27 +0300 Subject: [PATCH] Print more error messages In-Reply-To: References: <20200820163930.1103778-1-uzonyi.akos@gmail.com> <20200820165713.GC19738@altlinux.org> Message-ID: <20200820181227.GD20582@altlinux.org> On Thu, Aug 20, 2020 at 07:54:34PM +0200, ?kos Uzonyi wrote: > On Thu, 20 Aug 2020 at 18:57, Dmitry V. Levin wrote: > > On Thu, Aug 20, 2020 at 06:39:30PM +0200, ?kos Uzonyi wrote: [...] > > > @@ -248,6 +254,9 @@ get_id_list(int proc_pid, int *id_buf, enum pid_type type) > > > } > > > } > > > > > > + if (!p) > > > + error_func_msg("no line found starting with %s", ns_str); > > > > Yes, that was it, it prints "no line found starting with NSpid:". > > On that system I also see the following: > > $ grep -c ^NS /proc/self/status > > 0 > > Nice, thanks. > > Then I think we should modify this line a bit in is_proc_ours: > > - cached_val = get_id_list(0, NULL, PT_TID) == 1; > + cached_val = get_id_list(0, NULL, PT_TID) <= 1; > > So in case get_id_list returns 0, we consider /proc to be ours, as > this most probably means there is no PID namespace support in the > kernel. Yes, makes sense. -- ldv From uzonyi.akos at gmail.com Thu Aug 20 18:22:41 2020 From: uzonyi.akos at gmail.com (=?UTF-8?B?w4Frb3MgVXpvbnlp?=) Date: Thu, 20 Aug 2020 20:22:41 +0200 Subject: [PATCH v10 4/5] Implement testing framework for pidns In-Reply-To: <20200820181038.GC20582@altlinux.org> References: <20200819181637.1096507-1-uzonyi.akos@gmail.com> <20200819181637.1096507-5-uzonyi.akos@gmail.com> <20200820175110.GB20582@altlinux.org> <20200820181038.GC20582@altlinux.org> Message-ID: On Thu, 20 Aug 2020 at 20:10, Dmitry V. Levin wrote: > On Thu, Aug 20, 2020 at 08:07:53PM +0200, ?kos Uzonyi wrote: > > On Thu, 20 Aug 2020 at 19:51, Dmitry V. Levin wrote: > > > On Wed, Aug 19, 2020 at 08:16:36PM +0200, ?kos Uzonyi wrote: > > > [...] > > > > +void > > > > +pidns_test_init(void) > > > > +{ > > > > + pidns_translation = true; > > > > + > > > > + check_ns_ioctl(); > > > > + > > > > + if (!pidns_fork(-1, false)) > > > > + return; > > > > + > > > > + /* Unshare user namespace too, so we do not need to be root */ > > > > + if (unshare(CLONE_NEWUSER | CLONE_NEWPID) < 0) { > > > > + if (errno == EPERM) > > > > + perror_msg_and_skip("unshare"); > > > > + > > > > + perror_msg_and_fail("unshare"); > > > > + } > > > > > > This code fails to compile on the following system: > > > https://build.opensuse.org/package/live_build_log/home:ldv_alt/strace/RedHat_RHEL-5/x86_64 > > > > > > pidns.c: In function 'pidns_test_init': > > > pidns.c:204: error: 'CLONE_NEWUSER' undeclared (first use in this function) > > > pidns.c:204: error: (Each undeclared identifier is reported only once > > > pidns.c:204: error: for each function it appears in.) > > > pidns.c:204: error: 'CLONE_NEWPID' undeclared (first use in this function) > > > > > > A similar compilation issue exists in fork--pidns-translation.c, too. > > > > I think "#define _GNU_SOURCE" should be added to the beginning of the > > file. I'll add it, hopefully it solves the problem. > > No, it's already there due to config.h, I think some ifdefs like > in tests/ioctl_nsfs.c might be useful. Oh, OK thanks. And also I'll include "nsfs.h". From ldv at altlinux.org Thu Aug 20 19:17:01 2020 From: ldv at altlinux.org (Dmitry V. Levin) Date: Thu, 20 Aug 2020 22:17:01 +0300 Subject: [PATCH v10 5/5] Add tests for PID namespace translation In-Reply-To: <20200819181637.1096507-6-uzonyi.akos@gmail.com> References: <20200819181637.1096507-1-uzonyi.akos@gmail.com> <20200819181637.1096507-6-uzonyi.akos@gmail.com> Message-ID: <20200820191701.GA21914@altlinux.org> On Wed, Aug 19, 2020 at 08:16:37PM +0200, ?kos Uzonyi wrote: [...] > new file mode 100755 > index 00000000..fa98ed8c > --- /dev/null > +++ b/tests/pidns-cache.test > @@ -0,0 +1,16 @@ > +#!/bin/sh > +# > +# Test pidns translation cache. > +# > +# Copyright (c) 2020 The strace developers. > +# All rights reserved. > +# > +# SPDX-License-Identifier: GPL-2.0-or-later > + > +. "${srcdir=.}/init.sh" > + > +require_min_kernel_version_or_skip 4.9 > +check_prog timeout > + > +run_prog > /dev/null > +run_strace --pidns-translation -f -e trace=getpid $args Do we really need this require_min_kernel_version_or_skip here? -- ldv From uzonyi.akos at gmail.com Thu Aug 20 20:24:23 2020 From: uzonyi.akos at gmail.com (=?UTF-8?B?w4Frb3MgVXpvbnlp?=) Date: Thu, 20 Aug 2020 22:24:23 +0200 Subject: [PATCH v10 5/5] Add tests for PID namespace translation In-Reply-To: <20200820191701.GA21914@altlinux.org> References: <20200819181637.1096507-1-uzonyi.akos@gmail.com> <20200819181637.1096507-6-uzonyi.akos@gmail.com> <20200820191701.GA21914@altlinux.org> Message-ID: On Thu, 20 Aug 2020 at 21:17, Dmitry V. Levin wrote: > On Wed, Aug 19, 2020 at 08:16:37PM +0200, ?kos Uzonyi wrote: > [...] > > new file mode 100755 > > index 00000000..fa98ed8c > > --- /dev/null > > +++ b/tests/pidns-cache.test > > @@ -0,0 +1,16 @@ > > +#!/bin/sh > > +# > > +# Test pidns translation cache. > > +# > > +# Copyright (c) 2020 The strace developers. > > +# All rights reserved. > > +# > > +# SPDX-License-Identifier: GPL-2.0-or-later > > + > > +. "${srcdir=.}/init.sh" > > + > > +require_min_kernel_version_or_skip 4.9 > > +check_prog timeout > > + > > +run_prog > /dev/null > > +run_strace --pidns-translation -f -e trace=getpid $args > > Do we really need this require_min_kernel_version_or_skip here? No, we don't, it was just a mistake. From ldv at altlinux.org Thu Aug 20 22:47:21 2020 From: ldv at altlinux.org (Dmitry V. Levin) Date: Fri, 21 Aug 2020 01:47:21 +0300 Subject: [PATCH v10 4/5] Implement testing framework for pidns In-Reply-To: References: <20200819181637.1096507-1-uzonyi.akos@gmail.com> <20200819181637.1096507-5-uzonyi.akos@gmail.com> <20200820175110.GB20582@altlinux.org> <20200820181038.GC20582@altlinux.org> Message-ID: <20200820224721.GA23894@altlinux.org> On Thu, Aug 20, 2020 at 08:22:41PM +0200, ?kos Uzonyi wrote: > On Thu, 20 Aug 2020 at 20:10, Dmitry V. Levin wrote: [...] > > No, it's already there due to config.h, I think some ifdefs like > > in tests/ioctl_nsfs.c might be useful. > > Oh, OK thanks. And also I'll include "nsfs.h". Some of them already include "nsfs.h": $ git -P grep -F -n '"nsfs.h"' nsfs.c:12:#include "nsfs.h" pidns.c:26:#include "nsfs.h" tests/ioctl_nsfs.c:20:#include "nsfs.h" tests/pidns.c:11:#include "nsfs.h" -- ldv From uzonyi.akos at gmail.com Fri Aug 21 07:45:04 2020 From: uzonyi.akos at gmail.com (=?UTF-8?B?w4Frb3MgVXpvbnlp?=) Date: Fri, 21 Aug 2020 09:45:04 +0200 Subject: [PATCH v10 4/5] Implement testing framework for pidns In-Reply-To: <20200820224721.GA23894@altlinux.org> References: <20200819181637.1096507-1-uzonyi.akos@gmail.com> <20200819181637.1096507-5-uzonyi.akos@gmail.com> <20200820175110.GB20582@altlinux.org> <20200820181038.GC20582@altlinux.org> <20200820224721.GA23894@altlinux.org> Message-ID: On Fri, 21 Aug 2020 at 00:47, Dmitry V. Levin wrote: > On Thu, Aug 20, 2020 at 08:22:41PM +0200, ?kos Uzonyi wrote: > > On Thu, 20 Aug 2020 at 20:10, Dmitry V. Levin wrote: > [...] > > > No, it's already there due to config.h, I think some ifdefs like > > > in tests/ioctl_nsfs.c might be useful. > > > > Oh, OK thanks. And also I'll include "nsfs.h". > > Some of them already include "nsfs.h": > > $ git -P grep -F -n '"nsfs.h"' > nsfs.c:12:#include "nsfs.h" > pidns.c:26:#include "nsfs.h" > tests/ioctl_nsfs.c:20:#include "nsfs.h" > tests/pidns.c:11:#include "nsfs.h" Thanks, then it was only missing from tests/fork--pidns-translation.c. From notifications at github.com Thu Aug 20 16:08:44 2020 From: notifications at github.com (Dmitry V. Levin) Date: Thu, 20 Aug 2020 09:08:44 -0700 Subject: [strace/strace] Add -n/--syscall-number option (#149) In-Reply-To: References: Message-ID: @ldv-alt commented on this pull request. > print_kernel_version.c \ + print_syscall_number.c \ print_mac.c \ Please keep this list sorted. -- You are receiving this because you are subscribed to this thread. Reply to this email directly or view it on GitHub: https://github.com/strace/strace/pull/149#pullrequestreview-471769749 -------------- next part -------------- An HTML attachment was scrubbed... URL: From notifications at github.com Fri Aug 21 05:34:21 2020 From: notifications at github.com (Elvira Khabirova) Date: Thu, 20 Aug 2020 22:34:21 -0700 Subject: [strace/strace] Add -n/--syscall-number option (#149) In-Reply-To: References: Message-ID: Should shuffle_scno be skipped as well? -- You are receiving this because you are subscribed to this thread. Reply to this email directly or view it on GitHub: https://github.com/strace/strace/pull/149#issuecomment-678048055 -------------- next part -------------- An HTML attachment was scrubbed... URL: From notifications at github.com Fri Aug 21 09:14:54 2020 From: notifications at github.com (esyr) Date: Fri, 21 Aug 2020 02:14:54 -0700 Subject: [strace/strace] Add -n/--syscall-number option (#149) In-Reply-To: References: Message-ID: > Should shuffle_scno be skipped as well? Yes, it is used for making meaningful scno space less sparse. It is involutory, however. -- You are receiving this because you are subscribed to this thread. Reply to this email directly or view it on GitHub: https://github.com/strace/strace/pull/149#issuecomment-678134644 -------------- next part -------------- An HTML attachment was scrubbed... URL: From notifications at github.com Fri Aug 21 09:15:26 2020 From: notifications at github.com (esyr) Date: Fri, 21 Aug 2020 02:15:26 -0700 Subject: [strace/strace] Add -n/--syscall-number option (#149) In-Reply-To: References: Message-ID: A change to `strace.1.in` is missing. -- You are receiving this because you are subscribed to this thread. Reply to this email directly or view it on GitHub: https://github.com/strace/strace/pull/149#issuecomment-678134905 -------------- next part -------------- An HTML attachment was scrubbed... URL: From notifications at github.com Fri Aug 21 09:52:29 2020 From: notifications at github.com (Elvira Khabirova) Date: Fri, 21 Aug 2020 02:52:29 -0700 Subject: [strace/strace] Add -n/--syscall-number option (#149) In-Reply-To: References: Message-ID: Should syscall() be printed honestly too? That one isn't reversible, and as i see requires another struct tcb field. -- You are receiving this because you are subscribed to this thread. Reply to this email directly or view it on GitHub: https://github.com/strace/strace/pull/149#issuecomment-678150765 -------------- next part -------------- An HTML attachment was scrubbed... URL: From notifications at github.com Fri Aug 21 10:19:18 2020 From: notifications at github.com (Dmitry V. Levin) Date: Fri, 21 Aug 2020 03:19:18 -0700 Subject: [strace/strace] Add -n/--syscall-number option (#149) In-Reply-To: References: Message-ID: On Fri, Aug 21, 2020 at 02:52:26AM -0700, Elvira Khabirova wrote: > Should syscall() be printed honestly too? That one isn't reversible, and as i see requires another struct tcb field. Since syscall() is a mips-o32-only thing, I wouldn't bother. -- You are receiving this because you are subscribed to this thread. Reply to this email directly or view it on GitHub: https://github.com/strace/strace/pull/149#issuecomment-678186733 -------------- next part -------------- An HTML attachment was scrubbed... URL: From notifications at github.com Fri Aug 21 14:53:56 2020 From: notifications at github.com (Elvira Khabirova) Date: Fri, 21 Aug 2020 07:53:56 -0700 Subject: [strace/strace] Add -n/--syscall-number option (#149) In-Reply-To: References: Message-ID: @parport0 commented on this pull request. > + const long args[] = { 0, 0 }; + syscall(__NR_socketcall, SC_listen, args); + printf("[%4u] listen(0, 0) = -1 ENOTSOCK (%m)\n", SYS_socket_subcall + SC_listen); Those __NR_* numbers would have to depend on the personality, wouldn't they? -- You are receiving this because you are subscribed to this thread. Reply to this email directly or view it on GitHub: https://github.com/strace/strace/pull/149#discussion_r474749243 -------------- next part -------------- An HTML attachment was scrubbed... URL: From notifications at github.com Fri Aug 21 15:04:45 2020 From: notifications at github.com (Dmitry V. Levin) Date: Fri, 21 Aug 2020 08:04:45 -0700 Subject: [strace/strace] Add -n/--syscall-number option (#149) In-Reply-To: References: Message-ID: @ldv-alt commented on this pull request. > + const long args[] = { 0, 0 }; + syscall(__NR_socketcall, SC_listen, args); + printf("[%4u] listen(0, 0) = -1 ENOTSOCK (%m)\n", SYS_socket_subcall + SC_listen); There is only one personality in the test. In the tracer it would be easier just to save the original scno. -- You are receiving this because you are subscribed to this thread. Reply to this email directly or view it on GitHub: https://github.com/strace/strace/pull/149#discussion_r474756197 -------------- next part -------------- An HTML attachment was scrubbed... URL: From notifications at github.com Fri Aug 21 15:06:54 2020 From: notifications at github.com (Elvira Khabirova) Date: Fri, 21 Aug 2020 08:06:54 -0700 Subject: [strace/strace] Add -n/--syscall-number option (#149) In-Reply-To: References: Message-ID: @parport0 commented on this pull request. > + const long args[] = { 0, 0 }; + syscall(__NR_socketcall, SC_listen, args); + printf("[%4u] listen(0, 0) = -1 ENOTSOCK (%m)\n", SYS_socket_subcall + SC_listen); Is that a green light to add a field to struct tcb and not *unmince the meat back*? -- You are receiving this because you are subscribed to this thread. Reply to this email directly or view it on GitHub: https://github.com/strace/strace/pull/149#discussion_r474757462 -------------- next part -------------- An HTML attachment was scrubbed... URL: From notifications at github.com Fri Aug 21 15:19:52 2020 From: notifications at github.com (Dmitry V. Levin) Date: Fri, 21 Aug 2020 08:19:52 -0700 Subject: [strace/strace] Add -n/--syscall-number option (#149) In-Reply-To: References: Message-ID: @ldv-alt commented on this pull request. > + const long args[] = { 0, 0 }; + syscall(__NR_socketcall, SC_listen, args); + printf("[%4u] listen(0, 0) = -1 ENOTSOCK (%m)\n", SYS_socket_subcall + SC_listen); Yes, the light couldn't have been any greener. -- You are receiving this because you are subscribed to this thread. Reply to this email directly or view it on GitHub: https://github.com/strace/strace/pull/149#discussion_r474765075 -------------- next part -------------- An HTML attachment was scrubbed... URL: From notifications at github.com Fri Aug 21 15:24:13 2020 From: notifications at github.com (Elvira Khabirova) Date: Fri, 21 Aug 2020 08:24:13 -0700 Subject: [strace/strace] Add -n/--syscall-number option (#149) In-Reply-To: References: Message-ID: I believe i've addressed everything. -- You are receiving this because you are subscribed to this thread. Reply to this email directly or view it on GitHub: https://github.com/strace/strace/pull/149#issuecomment-678349198 -------------- next part -------------- An HTML attachment was scrubbed... URL: From notifications at github.com Fri Aug 21 15:26:09 2020 From: notifications at github.com (Dmitry V. Levin) Date: Fri, 21 Aug 2020 08:26:09 -0700 Subject: [strace/strace] Add -n/--syscall-number option (#149) In-Reply-To: References: Message-ID: @ldv-alt commented on this pull request. > @@ -0,0 +1,42 @@ +/* + * Test strace's -n option. + * + * Copyright (c) 2020 The strace developers. + * All rights reserved. + * + * SPDX-License-Identifier: GPL-2.0-or-later + */ + +#include "tests.h" +#include "scno.h" + +#if defined __NR_socketcall && defined __NR_listen && defined __i386__ Assuming that every architecture has at least one of ```__NR_listen``` or ```__NR_socketcall``` defined, it seems to me now that the test would make sense for any architecture. -- You are receiving this because you are subscribed to this thread. Reply to this email directly or view it on GitHub: https://github.com/strace/strace/pull/149#discussion_r474768972 -------------- next part -------------- An HTML attachment was scrubbed... URL: From notifications at github.com Fri Aug 21 15:31:41 2020 From: notifications at github.com (Elvira Khabirova) Date: Fri, 21 Aug 2020 08:31:41 -0700 Subject: [strace/strace] Add -n/--syscall-number option (#149) In-Reply-To: References: Message-ID: @parport0 commented on this pull request. > @@ -0,0 +1,42 @@ +/* + * Test strace's -n option. + * + * Copyright (c) 2020 The strace developers. + * All rights reserved. + * + * SPDX-License-Identifier: GPL-2.0-or-later + */ + +#include "tests.h" +#include "scno.h" + +#if defined __NR_socketcall && defined __NR_listen && defined __i386__ When !__NR_socketcall it hardly tests anything. Not saying it can't be run anyway. -- You are receiving this because you are subscribed to this thread. Reply to this email directly or view it on GitHub: https://github.com/strace/strace/pull/149#discussion_r474772379 -------------- next part -------------- An HTML attachment was scrubbed... URL: From notifications at github.com Fri Aug 21 15:34:03 2020 From: notifications at github.com (Dmitry V. Levin) Date: Fri, 21 Aug 2020 08:34:03 -0700 Subject: [strace/strace] Add -n/--syscall-number option (#149) In-Reply-To: References: Message-ID: @ldv-alt commented on this pull request. > @@ -0,0 +1,42 @@ +/* + * Test strace's -n option. + * + * Copyright (c) 2020 The strace developers. + * All rights reserved. + * + * SPDX-License-Identifier: GPL-2.0-or-later + */ + +#include "tests.h" +#include "scno.h" + +#if defined __NR_socketcall && defined __NR_listen && defined __i386__ At least it would test print_syscall_number, it's better than testing nothing. -- You are receiving this because you are subscribed to this thread. Reply to this email directly or view it on GitHub: https://github.com/strace/strace/pull/149#discussion_r474773661 -------------- next part -------------- An HTML attachment was scrubbed... URL: From notifications at github.com Fri Aug 21 15:36:35 2020 From: notifications at github.com (Dmitry V. Levin) Date: Fri, 21 Aug 2020 08:36:35 -0700 Subject: [strace/strace] Add -n/--syscall-number option (#149) In-Reply-To: References: Message-ID: It would be great if you could add a NEWS entry for this change. -- You are receiving this because you are subscribed to this thread. Reply to this email directly or view it on GitHub: https://github.com/strace/strace/pull/149#issuecomment-678355021 -------------- next part -------------- An HTML attachment was scrubbed... URL: From notifications at github.com Fri Aug 21 16:23:05 2020 From: notifications at github.com (Dmitry V. Levin) Date: Fri, 21 Aug 2020 09:23:05 -0700 Subject: [strace/strace] Add -n/--syscall-number option (#149) In-Reply-To: References: Message-ID: [Commenting commit messages in not something github is designed for.] > * print_syscall_number.c: New file. > * Makefile.am (libstrace_a_SOURCES): Add print_syscall_number.c. A simple "Add it." would suffice. > * defs.h: Add print_syscall_number. Please elaborate, e.g. * defs.h (struct tcb): Add true_scno field. (print_syscall_number): New function declaration. > * strace.c: Add -n/--syscall-number option. > (printleader): Call print_syscall_number. Please mention other changes, e.g. * syscall.c (get_scno): Assign tcp->true_scno. * strace.1.in: Document new option. -- You are receiving this because you are subscribed to this thread. Reply to this email directly or view it on GitHub: https://github.com/strace/strace/pull/149#issuecomment-678376562 -------------- next part -------------- An HTML attachment was scrubbed... URL: From notifications at github.com Fri Aug 21 17:15:58 2020 From: notifications at github.com (Dmitry V. Levin) Date: Fri, 21 Aug 2020 10:15:58 -0700 Subject: [strace/strace] Add -n/--syscall-number option (#149) In-Reply-To: References: Message-ID: ``` $ env -i ./strace -n -v -e/execve,/exit tests-m32/strace-n > /dev/null [ 59] execve("tests-m32/strace-n", ["tests-m32/strace-n"], []) = 0 [ 59] [ Process PID=12345 runs in 32 bit mode. ] [ 252] exit_group(0) = ? [ 252] +++ exited with 0 +++ ``` Is this behaviour of the new -n option expected? -- You are receiving this because you are subscribed to this thread. Reply to this email directly or view it on GitHub: https://github.com/strace/strace/pull/149#issuecomment-678398567 -------------- next part -------------- An HTML attachment was scrubbed... URL: From notifications at github.com Fri Aug 21 17:19:00 2020 From: notifications at github.com (Elvira Khabirova) Date: Fri, 21 Aug 2020 10:19:00 -0700 Subject: [strace/strace] Add -n/--syscall-number option (#149) In-Reply-To: References: Message-ID: It's expected as in i'm aware of it and am not against it. -- You are receiving this because you are subscribed to this thread. Reply to this email directly or view it on GitHub: https://github.com/strace/strace/pull/149#issuecomment-678399735 -------------- next part -------------- An HTML attachment was scrubbed... URL: From ldv at altlinux.org Sat Aug 22 17:52:27 2020 From: ldv at altlinux.org (Dmitry V. Levin) Date: Sat, 22 Aug 2020 20:52:27 +0300 Subject: [PATCH v10 1/5] PID namespace translation support In-Reply-To: <20200819181637.1096507-2-uzonyi.akos@gmail.com> References: <20200819181637.1096507-1-uzonyi.akos@gmail.com> <20200819181637.1096507-2-uzonyi.akos@gmail.com> Message-ID: <20200822175227.GA20831@altlinux.org> On Wed, Aug 19, 2020 at 08:16:33PM +0200, ?kos Uzonyi wrote: [...] > +static uint64_t * > +trie_get_node(struct trie *t, uint64_t key, bool auto_create) > +{ > + void **cur_node = &(t->data); > + > + if (t->key_size < 64 && key > (uint64_t) 1 << t->key_size) > + return NULL; > + > + for (uint8_t cur_depth = 0; cur_depth <= t->max_depth; cur_depth++) { > + uint8_t offs = trie_get_node_bit_offs(t, cur_depth); > + uint8_t sz = trie_get_node_size(t, cur_depth); > + > + if (!*cur_node) { > + if (!auto_create) > + return NULL; > + > + if (cur_depth == t->max_depth) > + *cur_node = trie_create_data_block(t); > + else > + *cur_node = calloc(1 << sz, 1); > + > + if (!*cur_node) { > + fprintf(stderr, "Out of memory"); > + exit(1); > + } This should rather be error_msg_and_die("Out of memory"); Or better use xcalloc instead of calloc here and in trie_create_data_block. -- ldv From ldv at altlinux.org Sat Aug 22 19:07:27 2020 From: ldv at altlinux.org (Dmitry V. Levin) Date: Sat, 22 Aug 2020 22:07:27 +0300 Subject: [PATCH v10 1/5] PID namespace translation support In-Reply-To: <20200819181637.1096507-2-uzonyi.akos@gmail.com> References: <20200819181637.1096507-1-uzonyi.akos@gmail.com> <20200819181637.1096507-2-uzonyi.akos@gmail.com> Message-ID: <20200822190726.GA21479@altlinux.org> On Wed, Aug 19, 2020 at 08:16:33PM +0200, ?kos Uzonyi wrote: [...] > + errno = 0; > + long id = strtol(p, NULL, 10); > + > + if (errno || id < 1 || id > INT_MAX) { > + perror_func_msg("converting pid (%ld) to int", id); > + break; > + } I generally prefer to check local variables ("id" in this case) prior to global ("errno") in this case. [...] > + errno = 0; > + long proc_pid = strtol(entry->d_name, NULL, 10); > + if (errno) > + continue; > + if (proc_pid < 1 || proc_pid > INT_MAX) > + continue; Likewise. By the way, could you merge checks for proc_pid and errno into a single condition, please? > +/** > + * Iterator function of the proc_data_cache for id translation. > + * If the cache contains the id we are looking for, reads the corresponding > + * directory in /proc, and if cache is valid, saves the result. > + */ > +static void > +proc_data_cache_iterator_fn(void* fn_data, uint64_t key, uint64_t val) > +{ > + struct translate_id_params *tip = (struct translate_id_params *)fn_data; > + struct proc_data *pd = (struct proc_data *) (uintptr_t) val; > + > + if (!pd) > + return; > + > + /* Result already found in an earlier iteration */ > + if (tip->result_id) > + return; > + > + /* Translate from cache */ > + tip->pd = pd; > + translate_id_proc_pid(tip, 0); > + if (!tip->result_id) > + return; > + > + /* Now translate from actual data in /proc, to check cache validity */ > + translate_id_proc_pid(tip, pd->proc_pid); > +} According to the coverage report [1], the last translate_id_proc_pid call is not covered by tests as if tip->result_id was always equal to 0. Do you have any ideas why? [...] > + /* Iterate through the cache, find potential proc_data */ > + trie_iterate_keys(proc_data_cache, 0, pid_max, > + proc_data_cache_iterator_fn, &tip); > + /* (proc_data_cache_iterator_fn takes care about updating proc_data) */ > + if (tip.result_id) > + goto exit; > + > + /* No cache helped, read all entries in /proc */ > + translate_id_dir(&tip, "/proc", true); > + > +exit: Likewise, according to [1], this "goto exit" is somehow not covered by tests as if translate_id_dir was always called. [1] https://codecov.io/gh/strace/strace/src/a5f58ab7ded18c14dd055e38a0b4899c948bdb59/pidns.c -- ldv From uzonyi.akos at gmail.com Sat Aug 22 19:37:55 2020 From: uzonyi.akos at gmail.com (=?UTF-8?B?w4Frb3MgVXpvbnlp?=) Date: Sat, 22 Aug 2020 21:37:55 +0200 Subject: [PATCH v10 1/5] PID namespace translation support In-Reply-To: <20200822175227.GA20831@altlinux.org> References: <20200819181637.1096507-1-uzonyi.akos@gmail.com> <20200819181637.1096507-2-uzonyi.akos@gmail.com> <20200822175227.GA20831@altlinux.org> Message-ID: On Sat, 22 Aug 2020 at 19:52, Dmitry V. Levin wrote: > On Wed, Aug 19, 2020 at 08:16:33PM +0200, ?kos Uzonyi wrote: > [...] > > +static uint64_t * > > +trie_get_node(struct trie *t, uint64_t key, bool auto_create) > > +{ > > + void **cur_node = &(t->data); > > + > > + if (t->key_size < 64 && key > (uint64_t) 1 << t->key_size) > > + return NULL; > > + > > + for (uint8_t cur_depth = 0; cur_depth <= t->max_depth; cur_depth++) { > > + uint8_t offs = trie_get_node_bit_offs(t, cur_depth); > > + uint8_t sz = trie_get_node_size(t, cur_depth); > > + > > + if (!*cur_node) { > > + if (!auto_create) > > + return NULL; > > + > > + if (cur_depth == t->max_depth) > > + *cur_node = trie_create_data_block(t); > > + else > > + *cur_node = calloc(1 << sz, 1); > > + > > + if (!*cur_node) { > > + fprintf(stderr, "Out of memory"); > > + exit(1); > > + } > > This should rather be error_msg_and_die("Out of memory"); > > Or better use xcalloc instead of calloc here and in > trie_create_data_block. The problem is, trie.c is linked to the strace code and to the test suite code too, so we can't use these functions (they do not exist in the test environment). Originally xcalloc was used here, but when I created the trie test, I replaced it with the code above. fprintf(sterr); exit(1) seems to be fine, as this is used in error_msg_and_die, and error_msg_and fail too. From ldv at altlinux.org Sat Aug 22 19:50:45 2020 From: ldv at altlinux.org (Dmitry V. Levin) Date: Sat, 22 Aug 2020 22:50:45 +0300 Subject: [PATCH v10 1/5] PID namespace translation support In-Reply-To: References: <20200819181637.1096507-1-uzonyi.akos@gmail.com> <20200819181637.1096507-2-uzonyi.akos@gmail.com> <20200822175227.GA20831@altlinux.org> Message-ID: <20200822195045.GA22035@altlinux.org> On Sat, Aug 22, 2020 at 09:37:55PM +0200, ?kos Uzonyi wrote: > On Sat, 22 Aug 2020 at 19:52, Dmitry V. Levin wrote: > > On Wed, Aug 19, 2020 at 08:16:33PM +0200, ?kos Uzonyi wrote: > > [...] > > > +static uint64_t * > > > +trie_get_node(struct trie *t, uint64_t key, bool auto_create) > > > +{ > > > + void **cur_node = &(t->data); > > > + > > > + if (t->key_size < 64 && key > (uint64_t) 1 << t->key_size) > > > + return NULL; > > > + > > > + for (uint8_t cur_depth = 0; cur_depth <= t->max_depth; cur_depth++) { > > > + uint8_t offs = trie_get_node_bit_offs(t, cur_depth); > > > + uint8_t sz = trie_get_node_size(t, cur_depth); > > > + > > > + if (!*cur_node) { > > > + if (!auto_create) > > > + return NULL; > > > + > > > + if (cur_depth == t->max_depth) > > > + *cur_node = trie_create_data_block(t); > > > + else > > > + *cur_node = calloc(1 << sz, 1); > > > + > > > + if (!*cur_node) { > > > + fprintf(stderr, "Out of memory"); > > > + exit(1); > > > + } > > > > This should rather be error_msg_and_die("Out of memory"); > > > > Or better use xcalloc instead of calloc here and in > > trie_create_data_block. > > The problem is, trie.c is linked to the strace code and to the test > suite code too, so we can't use these functions (they do not exist in > the test environment). Originally xcalloc was used here, but when I > created the trie test, I replaced it with the code above. > fprintf(sterr); exit(1) seems to be fine, as this is used in > error_msg_and_die, and error_msg_and fail too. First of all, I don't like the very idea of a mere test affecting the way how the main code is implemented. If xcalloc is needed in a test, why not add it to the test? With regards to error_msg_and_die(), it also prints program_invocation_name and calls die() which in turn calls cleanup(). -- ldv From uzonyi.akos at gmail.com Sat Aug 22 20:56:05 2020 From: uzonyi.akos at gmail.com (=?UTF-8?B?w4Frb3MgVXpvbnlp?=) Date: Sat, 22 Aug 2020 22:56:05 +0200 Subject: [PATCH v10 1/5] PID namespace translation support In-Reply-To: <20200822195045.GA22035@altlinux.org> References: <20200819181637.1096507-1-uzonyi.akos@gmail.com> <20200819181637.1096507-2-uzonyi.akos@gmail.com> <20200822175227.GA20831@altlinux.org> <20200822195045.GA22035@altlinux.org> Message-ID: On Sat, 22 Aug 2020 at 21:50, Dmitry V. Levin wrote: > On Sat, Aug 22, 2020 at 09:37:55PM +0200, ?kos Uzonyi wrote: > > On Sat, 22 Aug 2020 at 19:52, Dmitry V. Levin wrote: > > > On Wed, Aug 19, 2020 at 08:16:33PM +0200, ?kos Uzonyi wrote: > > > [...] > > > > +static uint64_t * > > > > +trie_get_node(struct trie *t, uint64_t key, bool auto_create) > > > > +{ > > > > + void **cur_node = &(t->data); > > > > + > > > > + if (t->key_size < 64 && key > (uint64_t) 1 << t->key_size) > > > > + return NULL; > > > > + > > > > + for (uint8_t cur_depth = 0; cur_depth <= t->max_depth; cur_depth++) { > > > > + uint8_t offs = trie_get_node_bit_offs(t, cur_depth); > > > > + uint8_t sz = trie_get_node_size(t, cur_depth); > > > > + > > > > + if (!*cur_node) { > > > > + if (!auto_create) > > > > + return NULL; > > > > + > > > > + if (cur_depth == t->max_depth) > > > > + *cur_node = trie_create_data_block(t); > > > > + else > > > > + *cur_node = calloc(1 << sz, 1); > > > > + > > > > + if (!*cur_node) { > > > > + fprintf(stderr, "Out of memory"); > > > > + exit(1); > > > > + } > > > > > > This should rather be error_msg_and_die("Out of memory"); > > > > > > Or better use xcalloc instead of calloc here and in > > > trie_create_data_block. > > > > The problem is, trie.c is linked to the strace code and to the test > > suite code too, so we can't use these functions (they do not exist in > > the test environment). Originally xcalloc was used here, but when I > > created the trie test, I replaced it with the code above. > > fprintf(sterr); exit(1) seems to be fine, as this is used in > > error_msg_and_die, and error_msg_and fail too. > > First of all, I don't like the very idea of a mere test affecting the way > how the main code is implemented. Yes, I agree, it was an ugly hack from me to replace xcalloc this way. > If xcalloc is needed in a test, why not add it to the test? OK, I'll add it. Is it OK if I copy xmalloc.c and xmalloc.h to tests/ (with necessary modifications like replacing error_msg_and_die with error_msg_and_fail), and add them to libtests_a_SOURCES? From ldv at altlinux.org Sat Aug 22 21:06:26 2020 From: ldv at altlinux.org (Dmitry V. Levin) Date: Sun, 23 Aug 2020 00:06:26 +0300 Subject: [PATCH v10 1/5] PID namespace translation support In-Reply-To: References: <20200819181637.1096507-1-uzonyi.akos@gmail.com> <20200819181637.1096507-2-uzonyi.akos@gmail.com> <20200822175227.GA20831@altlinux.org> <20200822195045.GA22035@altlinux.org> Message-ID: <20200822210626.GA22745@altlinux.org> On Sat, Aug 22, 2020 at 10:56:05PM +0200, ?kos Uzonyi wrote: > On Sat, 22 Aug 2020 at 21:50, Dmitry V. Levin wrote: > > On Sat, Aug 22, 2020 at 09:37:55PM +0200, ?kos Uzonyi wrote: > > > On Sat, 22 Aug 2020 at 19:52, Dmitry V. Levin wrote: > > > > On Wed, Aug 19, 2020 at 08:16:33PM +0200, ?kos Uzonyi wrote: > > > > [...] > > > > > +static uint64_t * > > > > > +trie_get_node(struct trie *t, uint64_t key, bool auto_create) > > > > > +{ > > > > > + void **cur_node = &(t->data); > > > > > + > > > > > + if (t->key_size < 64 && key > (uint64_t) 1 << t->key_size) > > > > > + return NULL; > > > > > + > > > > > + for (uint8_t cur_depth = 0; cur_depth <= t->max_depth; cur_depth++) { > > > > > + uint8_t offs = trie_get_node_bit_offs(t, cur_depth); > > > > > + uint8_t sz = trie_get_node_size(t, cur_depth); > > > > > + > > > > > + if (!*cur_node) { > > > > > + if (!auto_create) > > > > > + return NULL; > > > > > + > > > > > + if (cur_depth == t->max_depth) > > > > > + *cur_node = trie_create_data_block(t); > > > > > + else > > > > > + *cur_node = calloc(1 << sz, 1); > > > > > + > > > > > + if (!*cur_node) { > > > > > + fprintf(stderr, "Out of memory"); > > > > > + exit(1); > > > > > + } > > > > > > > > This should rather be error_msg_and_die("Out of memory"); > > > > > > > > Or better use xcalloc instead of calloc here and in > > > > trie_create_data_block. > > > > > > The problem is, trie.c is linked to the strace code and to the test > > > suite code too, so we can't use these functions (they do not exist in > > > the test environment). Originally xcalloc was used here, but when I > > > created the trie test, I replaced it with the code above. > > > fprintf(sterr); exit(1) seems to be fine, as this is used in > > > error_msg_and_die, and error_msg_and fail too. > > > > First of all, I don't like the very idea of a mere test affecting the way > > how the main code is implemented. > > Yes, I agree, it was an ugly hack from me to replace xcalloc this way. > > > If xcalloc is needed in a test, why not add it to the test? > > OK, I'll add it. Is it OK if I copy xmalloc.c and xmalloc.h to tests/ > (with necessary modifications like replacing > error_msg_and_die with error_msg_and_fail), and add them to libtests_a_SOURCES? There is no need to do anything with xmalloc.h as its directory is already in the search path of header files for tests. With regards to xmalloc.c, I suppose you can create e.g. tests/xmalloc_for_tests.c containing #define error_msg_and_die error_msg_and_fail #include "xmalloc.c" -- ldv From ldv at altlinux.org Sat Aug 22 22:36:15 2020 From: ldv at altlinux.org (Dmitry V. Levin) Date: Sun, 23 Aug 2020 01:36:15 +0300 Subject: [RFC PATCH 0/4] [PIDNS] Trie and pidns-cache tests In-Reply-To: References: <20200813153242.94742-1-uzonyi.akos@gmail.com> <20200815124129.GB30941@altlinux.org> <20200815162710.GD376@altlinux.org> <20200817231248.GA5522@altlinux.org> <20200817234448.GD5522@altlinux.org> Message-ID: <20200822223615.GB23834@altlinux.org> On Tue, Aug 18, 2020 at 02:19:50PM +0200, ?kos Uzonyi wrote: > On Tue, 18 Aug 2020 at 01:44, Dmitry V. Levin wrote: > > On Tue, Aug 18, 2020 at 01:21:18AM +0200, ?kos Uzonyi wrote: > > > On Tue, 18 Aug 2020 at 01:12, Dmitry V. Levin wrote: > > > > On Tue, Aug 18, 2020 at 12:12:17AM +0200, ?kos Uzonyi wrote: > > > > > On Sat, 15 Aug 2020 at 18:27, Dmitry V. Levin wrote: > > > > > > On Sat, Aug 15, 2020 at 06:23:26PM +0200, ?kos Uzonyi wrote: > > > > > > > On Sat, 15 Aug 2020 at 14:41, Dmitry V. Levin wrote: > > > > > > > > On Thu, Aug 13, 2020 at 05:32:38PM +0200, ?kos Uzonyi wrote: > > > > > > > > > is it's OK to add ../trie.c ../trie.h to libtests_a_SOURCES? > > > > > > > > > > > > > > > > I suppose automake should be fine with it. What's your concern? > > > > > > > > > > > > > > Technically there is no problem, I just worried about including a file > > > > > > > not in tests directory, as it hasn't been done before. But if you say > > > > > > > it's OK, then everything is fine :). > > > > > > > > > > > > The only problem is that it won't be built with coverage support, > > > > > > so it won't be shown in coverage reports. > > > > > > > > > > I found an another problem, github CI errors with: > > > > > > > > > > /usr/bin/ld: i386:x86-64 architecture of input file > > > > > `libtests.a(libtests_a-trie.o)' is incompatible with i386 output > > > > > > > > Interesting. Could you give a link to the full log? > > > > > > https://github.com/AkosUzonyi/strace/runs/994567416 > > > > I see, it just built ../libtests_a-trie.o once and used it several times. > > > > > > However, we are probably not interested in running this test for compat > > > > personalities. There is a loop in ./bootstrap that creates tests-m32 and > > > > tests-mx32 directories, we could do something there to filter it out. > > > > > > Yes, I was also thinking about doing something in bootstrap. But I > > > think it's easier to add a symlink, and it also solves the coverage > > > support problem. > > > > I agree adding a symlink is much easier way to fix the build, but I don't > > see how it solves the coverage support problem. > > Sorry, I was wrong about this coverage thing. However pidns tests > already cover nearly all the lines of trie.c (except trie_free), so > trie test's goal is not to add line coverage, but to test edge cases > of trie. OK, I've found a way to work this around and squeeze some coverage out of the test, feel free to squash it in: diff --git a/Makefile.am b/Makefile.am index f4bd0e0d9..f79d93437 100644 --- a/Makefile.am +++ b/Makefile.am @@ -409,7 +409,7 @@ endif CODE_COVERAGE_BRANCH_COVERAGE = 1 CODE_COVERAGE_GENHTML_OPTIONS = $(CODE_COVERAGE_GENHTML_OPTIONS_DEFAULT) \ --prefix $(shell cd $(abs_top_srcdir)/.. && pwd || echo .) -CODE_COVERAGE_IGNORE_PATTERN = '/usr/include/*' +CODE_COVERAGE_IGNORE_PATTERN = '/usr/include/*' '*/tests/*' '*/tests-m32/*' '*/tests-mx32/*' strace_CPPFLAGS += $(CODE_COVERAGE_CPPFLAGS) strace_CFLAGS += $(CODE_COVERAGE_CFLAGS) strace_LDADD += $(CODE_COVERAGE_LIBS) diff --git a/tests/Makefile.am b/tests/Makefile.am index 39d948cf4..56e0e8eea 100644 --- a/tests/Makefile.am +++ b/tests/Makefile.am @@ -66,7 +66,6 @@ libtests_a_SOURCES = \ test_ucopy.h \ tests.h \ tprintf.c \ - trie.c \ # end of libtests_a_SOURCES libtests_a_CPPFLAGS = $(AM_CPPFLAGS) -D_FILE_OFFSET_BITS=64 check_LIBRARIES = libtests.a @@ -308,6 +307,11 @@ stack_fcall_mangled_SOURCES = stack-fcall-mangled.c \ stack-fcall-mangled-0.c stack-fcall-mangled-1.c \ stack-fcall-mangled-2.c stack-fcall-mangled-3.c +trie_test_SOURCES = trie_test.c trie_for_tests.c +trie_test_CPPFLAGS = $(AM_CPPFLAGS) $(CODE_COVERAGE_CPPFLAGS) +trie_test_CFLAGS = $(AM_CFLAGS) $(CODE_COVERAGE_CFLAGS) +trie_test_LDADD = $(LDADD) $(CODE_COVERAGE_LIBS) + include gen_tests.am if ENABLE_STACKTRACE diff --git a/tests/trie.c b/tests/trie.c deleted file mode 120000 index 0dd9cab45..000000000 --- a/tests/trie.c +++ /dev/null @@ -1 +0,0 @@ -../trie.c \ No newline at end of file diff --git a/tests/trie_for_tests.c b/tests/trie_for_tests.c new file mode 100644 index 000000000..13e564c4f --- /dev/null +++ b/tests/trie_for_tests.c @@ -0,0 +1 @@ +#include "trie.c" -- ldv From notifications at github.com Sun Aug 23 18:18:52 2020 From: notifications at github.com (Dmitry V. Levin) Date: Sun, 23 Aug 2020 11:18:52 -0700 Subject: [strace/strace] Add -n/--syscall-number option (#149) In-Reply-To: References: Message-ID: Merged #149 into master. -- You are receiving this because you are subscribed to this thread. Reply to this email directly or view it on GitHub: https://github.com/strace/strace/pull/149#event-3683031423 -------------- next part -------------- An HTML attachment was scrubbed... URL: From notifications at github.com Sun Aug 23 18:18:52 2020 From: notifications at github.com (Dmitry V. Levin) Date: Sun, 23 Aug 2020 11:18:52 -0700 Subject: [strace/strace] No way to distinguish SYS_socketcall from broken-down socket syscalls (#146) In-Reply-To: References: Message-ID: Closed #146 via #149. -- You are receiving this because you are subscribed to this thread. Reply to this email directly or view it on GitHub: https://github.com/strace/strace/issues/146#event-3683031426 -------------- next part -------------- An HTML attachment was scrubbed... URL: From uzonyi.akos at gmail.com Sun Aug 23 21:03:38 2020 From: uzonyi.akos at gmail.com (=?UTF-8?B?w4Frb3MgVXpvbnlp?=) Date: Sun, 23 Aug 2020 23:03:38 +0200 Subject: [PATCH v10 1/5] PID namespace translation support In-Reply-To: <20200822190726.GA21479@altlinux.org> References: <20200819181637.1096507-1-uzonyi.akos@gmail.com> <20200819181637.1096507-2-uzonyi.akos@gmail.com> <20200822190726.GA21479@altlinux.org> Message-ID: On Sat, 22 Aug 2020 at 21:07, Dmitry V. Levin wrote: > On Wed, Aug 19, 2020 at 08:16:33PM +0200, ?kos Uzonyi wrote: [...] > > +/** > > + * Iterator function of the proc_data_cache for id translation. > > + * If the cache contains the id we are looking for, reads the corresponding > > + * directory in /proc, and if cache is valid, saves the result. > > + */ > > +static void > > +proc_data_cache_iterator_fn(void* fn_data, uint64_t key, uint64_t val) > > +{ > > + struct translate_id_params *tip = (struct translate_id_params *)fn_data; > > + struct proc_data *pd = (struct proc_data *) (uintptr_t) val; > > + > > + if (!pd) > > + return; > > + > > + /* Result already found in an earlier iteration */ > > + if (tip->result_id) > > + return; > > + > > + /* Translate from cache */ > > + tip->pd = pd; > > + translate_id_proc_pid(tip, 0); > > + if (!tip->result_id) > > + return; > > + > > + /* Now translate from actual data in /proc, to check cache validity */ > > + translate_id_proc_pid(tip, pd->proc_pid); > > +} > > According to the coverage report [1], the last translate_id_proc_pid call > is not covered by tests as if tip->result_id was always equal to 0. > Do you have any ideas why? It took a bit of time to figure it out, but I found the reason for it. It was caused by a bug, so it's very useful you pointed this out. The bug was in trie_iterate_keys_node: it didn't work correctly if "end" was larger than the maximum allowed key. And in pidns.c "pid_max" was passed as "end" where "pid_max - 1" should have been (this was also a little bug, but trie should have been able to handle it). I fixed both bugs, now the line is covered. And also, I extended trie_test to test trie_iterate_keys_node. > [...] > > + /* Iterate through the cache, find potential proc_data */ > > + trie_iterate_keys(proc_data_cache, 0, pid_max, > > + proc_data_cache_iterator_fn, &tip); > > + /* (proc_data_cache_iterator_fn takes care about updating proc_data) */ > > + if (tip.result_id) > > + goto exit; > > + > > + /* No cache helped, read all entries in /proc */ > > + translate_id_dir(&tip, "/proc", true); > > + > > +exit: > > Likewise, according to [1], this "goto exit" is somehow not covered by tests > as if translate_id_dir was always called. This is just the symptom of the previous problem (by the way, translate_id_dir was not always called, as there are other "goto exit" and return statements before). From uzonyi.akos at gmail.com Sun Aug 23 21:30:37 2020 From: uzonyi.akos at gmail.com (=?UTF-8?B?w4Frb3MgVXpvbnlp?=) Date: Sun, 23 Aug 2020 23:30:37 +0200 Subject: [RFC PATCH 0/4] [PIDNS] Trie and pidns-cache tests In-Reply-To: <20200822223615.GB23834@altlinux.org> References: <20200813153242.94742-1-uzonyi.akos@gmail.com> <20200815124129.GB30941@altlinux.org> <20200815162710.GD376@altlinux.org> <20200817231248.GA5522@altlinux.org> <20200817234448.GD5522@altlinux.org> <20200822223615.GB23834@altlinux.org> Message-ID: On Sun, 23 Aug 2020 at 00:36, Dmitry V. Levin wrote: > OK, I've found a way to work this around and squeeze some coverage > out of the test, feel free to squash it in: > > diff --git a/Makefile.am b/Makefile.am > index f4bd0e0d9..f79d93437 100644 > --- a/Makefile.am > +++ b/Makefile.am > @@ -409,7 +409,7 @@ endif > CODE_COVERAGE_BRANCH_COVERAGE = 1 > CODE_COVERAGE_GENHTML_OPTIONS = $(CODE_COVERAGE_GENHTML_OPTIONS_DEFAULT) \ > --prefix $(shell cd $(abs_top_srcdir)/.. && pwd || echo .) > -CODE_COVERAGE_IGNORE_PATTERN = '/usr/include/*' > +CODE_COVERAGE_IGNORE_PATTERN = '/usr/include/*' '*/tests/*' '*/tests-m32/*' '*/tests-mx32/*' > strace_CPPFLAGS += $(CODE_COVERAGE_CPPFLAGS) > strace_CFLAGS += $(CODE_COVERAGE_CFLAGS) > strace_LDADD += $(CODE_COVERAGE_LIBS) > diff --git a/tests/Makefile.am b/tests/Makefile.am > index 39d948cf4..56e0e8eea 100644 > --- a/tests/Makefile.am > +++ b/tests/Makefile.am > @@ -66,7 +66,6 @@ libtests_a_SOURCES = \ > test_ucopy.h \ > tests.h \ > tprintf.c \ > - trie.c \ > # end of libtests_a_SOURCES > libtests_a_CPPFLAGS = $(AM_CPPFLAGS) -D_FILE_OFFSET_BITS=64 > check_LIBRARIES = libtests.a > @@ -308,6 +307,11 @@ stack_fcall_mangled_SOURCES = stack-fcall-mangled.c \ > stack-fcall-mangled-0.c stack-fcall-mangled-1.c \ > stack-fcall-mangled-2.c stack-fcall-mangled-3.c > > +trie_test_SOURCES = trie_test.c trie_for_tests.c > +trie_test_CPPFLAGS = $(AM_CPPFLAGS) $(CODE_COVERAGE_CPPFLAGS) > +trie_test_CFLAGS = $(AM_CFLAGS) $(CODE_COVERAGE_CFLAGS) > +trie_test_LDADD = $(LDADD) $(CODE_COVERAGE_LIBS) > + > include gen_tests.am > > if ENABLE_STACKTRACE > diff --git a/tests/trie.c b/tests/trie.c > deleted file mode 120000 > index 0dd9cab45..000000000 > --- a/tests/trie.c > +++ /dev/null > @@ -1 +0,0 @@ > -../trie.c > \ No newline at end of file > diff --git a/tests/trie_for_tests.c b/tests/trie_for_tests.c > new file mode 100644 > index 000000000..13e564c4f > --- /dev/null > +++ b/tests/trie_for_tests.c > @@ -0,0 +1 @@ > +#include "trie.c" I didn't know very well how this code coverage is configured, so thank you for helping with this. Applied, thanks :). From ldv at altlinux.org Sun Aug 23 21:55:13 2020 From: ldv at altlinux.org (Dmitry V. Levin) Date: Mon, 24 Aug 2020 00:55:13 +0300 Subject: [RFC PATCH 0/4] [PIDNS] Trie and pidns-cache tests In-Reply-To: References: <20200815124129.GB30941@altlinux.org> <20200815162710.GD376@altlinux.org> <20200817231248.GA5522@altlinux.org> <20200817234448.GD5522@altlinux.org> <20200822223615.GB23834@altlinux.org> Message-ID: <20200823215513.GA6213@altlinux.org> On Sun, Aug 23, 2020 at 11:30:37PM +0200, ?kos Uzonyi wrote: > On Sun, 23 Aug 2020 at 00:36, Dmitry V. Levin wrote: > > OK, I've found a way to work this around and squeeze some coverage > > out of the test, feel free to squash it in: > > > > diff --git a/Makefile.am b/Makefile.am > > index f4bd0e0d9..f79d93437 100644 > > --- a/Makefile.am > > +++ b/Makefile.am > > @@ -409,7 +409,7 @@ endif > > CODE_COVERAGE_BRANCH_COVERAGE = 1 > > CODE_COVERAGE_GENHTML_OPTIONS = $(CODE_COVERAGE_GENHTML_OPTIONS_DEFAULT) \ > > --prefix $(shell cd $(abs_top_srcdir)/.. && pwd || echo .) > > -CODE_COVERAGE_IGNORE_PATTERN = '/usr/include/*' > > +CODE_COVERAGE_IGNORE_PATTERN = '/usr/include/*' '*/tests/*' '*/tests-m32/*' '*/tests-mx32/*' > > strace_CPPFLAGS += $(CODE_COVERAGE_CPPFLAGS) > > strace_CFLAGS += $(CODE_COVERAGE_CFLAGS) > > strace_LDADD += $(CODE_COVERAGE_LIBS) > > diff --git a/tests/Makefile.am b/tests/Makefile.am > > index 39d948cf4..56e0e8eea 100644 > > --- a/tests/Makefile.am > > +++ b/tests/Makefile.am > > @@ -66,7 +66,6 @@ libtests_a_SOURCES = \ > > test_ucopy.h \ > > tests.h \ > > tprintf.c \ > > - trie.c \ > > # end of libtests_a_SOURCES > > libtests_a_CPPFLAGS = $(AM_CPPFLAGS) -D_FILE_OFFSET_BITS=64 > > check_LIBRARIES = libtests.a > > @@ -308,6 +307,11 @@ stack_fcall_mangled_SOURCES = stack-fcall-mangled.c \ > > stack-fcall-mangled-0.c stack-fcall-mangled-1.c \ > > stack-fcall-mangled-2.c stack-fcall-mangled-3.c > > > > +trie_test_SOURCES = trie_test.c trie_for_tests.c > > +trie_test_CPPFLAGS = $(AM_CPPFLAGS) $(CODE_COVERAGE_CPPFLAGS) > > +trie_test_CFLAGS = $(AM_CFLAGS) $(CODE_COVERAGE_CFLAGS) > > +trie_test_LDADD = $(LDADD) $(CODE_COVERAGE_LIBS) > > + > > include gen_tests.am > > > > if ENABLE_STACKTRACE > > diff --git a/tests/trie.c b/tests/trie.c > > deleted file mode 120000 > > index 0dd9cab45..000000000 > > --- a/tests/trie.c > > +++ /dev/null > > @@ -1 +0,0 @@ > > -../trie.c > > \ No newline at end of file > > diff --git a/tests/trie_for_tests.c b/tests/trie_for_tests.c > > new file mode 100644 > > index 000000000..13e564c4f > > --- /dev/null > > +++ b/tests/trie_for_tests.c > > @@ -0,0 +1 @@ > > +#include "trie.c" > > I didn't know very well how this code coverage is configured, so thank > you for helping with this. The idea was to compile tests/trie_for_tests.c (which is trie.c) along with the test with coverage options. For this reason I had to take tests/trie_for_tests.c out of libtests_a_SOURCES and convert it from a symlink into a real file so that the original trie.c is covered instead of a symlinked file. -- ldv From uzonyi.akos at gmail.com Sun Aug 23 22:25:50 2020 From: uzonyi.akos at gmail.com (=?UTF-8?q?=C3=81kos=20Uzonyi?=) Date: Mon, 24 Aug 2020 00:25:50 +0200 Subject: [PATCH v11 0/5] [PIDNS] Final Message-ID: <20200823222555.1224386-1-uzonyi.akos@gmail.com> From: Uzonyi ?kos Changes in v11: - trie_iterate_keys: handle if "end" is larger than max key - pidns.c: fix end argument of trie_iterate_keys - trie_test: test trie_iterate_keys too - Do not print error message if 0 found in id list - is_proc_ours: return true if id count is 0 - Use xcalloc in trie.c - Add coverage support for trie.c when tested by trie_test - Add check if unshare -Urpf true works - define CLONE_NEW* macros, if not defined - tests/fork--pidns-translation.c: include "nsfs.h" - tests/pidns-cache.test: remove require_min_kernel_version_or_skip - Reorder some or conditions - translate_id_proc_pid: make the code a little bit cleaner - pidns.c: Improve some comments a bit Changes in v10: - Use symlink for trie.c - Rename tests/trie.c -> tests/trie_test.c - pidns-cache test: use 20 as max ratio for execution times - Increase SYSCALL_COUNT to 1000 - Filter unfinished/resumed syscalls in gettid test. Changes in v9: - Add test for trie - Fix ns_id_size - Add tests for pidns cache - Skip pidns tests if /proc/self/ns/pid is not found - init.sh: add init_pid as a local variable - Remove kernel version checks (4.9) in pidns tests - tests/pidns.c: fix exit code of init process - tests/fcntl-common.c: initialize array during definition - tests/net-sockaddr.c: fix indentation - Fix description of some test scripts - Add tests for tkill, tgkill - Fix trie bugs: - When creating a data block, fill it with empty_value - Check calloc return value - Include config.h - Move some include from trie.c to trie.h - Fix trie_data_block_calc_pos when item_size_lg == 6 - Mask empty_value to fit item_size Changes in v8: - translate_pid: document return value; check !proc_pid first - NEWS: move to new section - get_proc_pid, printpid: fix comment - Check if translation failed Changes in v7: - Run uniq on gettid--pidns-translation test output - Add comment to printpid - translate_id: do not call get_our_ns if not necessary - Remove unnecessary parentheses - Fix commit message of last commit (s/-Y/--pidns-translation/) - get_proc_pid: remove unnecessary optimization - trie.c: remove #include - Add clarification to get_proc_pid's comment - Fix typos - trie.c: ptr_sz_lg use void* in sizeof - trie_get_node_size: fix comment - trie.c: remove "TODO: overflow" - ipc_shmctl.c: remove duplicate #include "print_field.h" Changes in v6: - Add function with documentation for creating tries - Do not use -1ULL as error indicator in tcb.pid_ns - Use unsigned int (instead of uint64_t) for NS IDs - Add constant for NS ID size. - Modify get_proc_pid a bit - Die if trie creation fails Changes in v5: - Squash "Use printpid in *" commits - Makefile.am: move adding getpid.c to "Use printpid in decoders" - Remove pid_ns_inited field from struct tcb - strace.1.in: remove -Y flag - Use tprints instead of tprintf where possible - Make some global variables static - pidns_init: remove "inited" bool variable - Make printpid_translation static - tests/pidns.c: refactor a bit - check_ns_ioctl: fix error msg - defs.h: Move adding get_proc_pid to "PID namespace translation support" - Remove tcp paramter name from declarations - Update printfd_pid_tracee_ns documentation - Use named constants for trie_create arguments - Add documentation comments - Add printpid_tgid_pgid function - Delete get_pid_max function; use global variables instead - Refactor trie: - Move key_size argument - Remove support for TRIE_SET - Merge trie_create, trie_init, trie_check functions - trie_free_node: make static, fix "node" argument type - Add max_depth field - Reorder functions - Extract common parts of trie_get, trie_set Changes in v4: - Skip tests if NS_* ioctl commands are not supported - Improve documentation in pidns.h - Use pipe for init process termination (instead of SIGKILL) - Add PIDNS_TEST_INIT macro - Remove "ifdef __NR_gettid" - Fix fork--pidns-tranlsation.test: skip if unshare fails with EPERM - Use debug message instead of normal message in some cases - Rename some labels - Rewrite get_ns function - Remove O_NONBLOCK from open(/proc//ns/pid) Changes in v3: - Split accidentally sqashed last commit - Undo modification of tests/pidfd_send_signal.c - Rename kcmp-yY test to kcmp-y--pidns-translation - Skip tests if unshare fails with EPERM - Fix buffer size in pidns_pid2str - Use largefile_wrappers.h macros - Return early if from_ns or our_ns is 0 - Do not call ioctl(NS_GET_PARENT) again, if first failed with ENOTTY - Skip pidns tests if Linux kernel version < 4.9 - Use smaller trie nodes in pidns.c - Remove race condition from fork--pidns-translation test - Move "key_size" to center in trie description - Use PT_TID (not PT_TGID) when translating tcp->pid - Fix get_ns_hierarchy and get_id_list functions - Fix migrate_pages test if syscall succeds - Fix filtering in ioctl_block--pidns-translation.test - Fix -a flag value in xetpriority test Changes in v2: - Add missing header files to Makefile - Fix pointer-to-int-cast errors - Fix unused-result errors - Use perror_msg instead of perror_func_msg where appropriate - Remove tcb parameter of read_int_from_file - Use xsprintf instead of snprintf - Refactor get_pid_max, get_ns_hierarchy, get_id_list functions - Remove -Y flag - Improve documentation of trie - Fix printing of f_owner_ex struct - Use printpid for F_GETOWN, F_SETOWN fcntl command arguments - Use printpid for shmid_ds.shm_cpid, shmid_ds.shm_clid - Call pidns_init before parsing arguments ?kos Uzonyi (5): PID namespace translation support Use printpid in decoders Use get_proc_pid for /proc paths Implement testing framework for pidns Add tests for PID namespace translation Makefile.am | 6 +- NEWS | 1 + affinity.c | 6 +- block.c | 2 +- bpf.c | 2 +- capability.c | 4 +- clone.c | 14 +- defs.h | 61 +- fcntl.c | 24 +- get_robust_list.c | 3 +- getpid.c | 46 ++ ioprio.c | 26 +- ipc_shmctl.c | 4 +- kcmp.c | 5 +- largefile_wrappers.h | 2 + linux/dummy.h | 8 +- mmap_cache.c | 2 +- msghdr.c | 2 +- net.c | 2 +- netlink.c | 5 +- numa.c | 6 +- pathtrace.c | 7 +- pidfd_open.c | 2 +- pidns.c | 608 ++++++++++++++++++ print_fields.h | 24 + printsiginfo.c | 2 +- process.c | 3 +- process_vm.c | 6 +- resource.c | 27 +- sched.c | 25 +- signal.c | 21 +- sockaddr.c | 2 +- strace.1.in | 4 + strace.c | 11 +- syscall.c | 15 + tests/.gitignore | 35 + tests/Makefile.am | 50 ++ tests/fcntl--pidns-translation.c | 2 + tests/fcntl-common.c | 78 ++- tests/fcntl.c | 1 + tests/fcntl64--pidns-translation.c | 2 + tests/fcntl64.c | 3 + tests/fork--pidns-translation.awk | 15 + tests/fork--pidns-translation.c | 78 +++ tests/fork--pidns-translation.test | 14 + tests/gen_tests.in | 32 +- tests/getpgrp--pidns-translation.c | 2 + tests/getpgrp.c | 8 +- tests/getpid--pidns-translation.c | 2 + tests/getpid.c | 8 +- tests/getsid--pidns-translation.c | 2 + tests/getsid.c | 9 +- tests/gettid--pidns-translation.c | 2 + tests/gettid--pidns-translation.test | 18 + tests/gettid.c | 8 +- tests/init.sh | 30 + tests/ioctl_block--pidns-translation.c | 2 + tests/ioctl_block--pidns-translation.test | 22 + tests/ioctl_block.c | 24 +- tests/ioprio--pidns-translation.c | 2 + tests/ioprio.c | 54 +- tests/kcmp-y--pidns-translation.c | 2 + tests/kcmp.c | 36 +- tests/kill--pidns-translation.c | 2 + tests/kill.c | 12 +- tests/migrate_pages--pidns-translation.c | 2 + tests/migrate_pages.c | 17 +- tests/move_pages--pidns-translation.c | 2 + tests/move_pages.c | 51 +- tests/net-sockaddr--pidns-translation.c | 2 + tests/net-sockaddr.c | 60 +- tests/netlink_audit--pidns-translation.c | 2 + tests/netlink_audit--pidns-translation.test | 13 + tests/netlink_audit.c | 11 +- tests/pidfd_open--pidns-translation.c | 2 + tests/pidfd_open.c | 21 +- tests/pidfd_send_signal--pidns-translation.c | 2 + tests/pidfd_send_signal.c | 13 +- tests/pidns-cache.c | 62 ++ tests/pidns-cache.test | 15 + tests/pidns.c | 237 +++++++ tests/pidns.h | 56 ++ tests/prlimit64--pidns-translation.c | 2 + tests/prlimit64.c | 17 +- tests/process_vm_readv--pidns-translation.c | 2 + tests/process_vm_readv_writev.c | 27 +- tests/process_vm_writev--pidns-translation.c | 2 + tests/rt_sigqueueinfo--pidns-translation.c | 2 + tests/rt_sigqueueinfo.c | 15 +- tests/rt_tgsigqueueinfo--pidns-translation.c | 2 + tests/rt_tgsigqueueinfo.c | 26 +- tests/sched_xetaffinity--pidns-translation.c | 2 + tests/sched_xetaffinity.c | 31 +- tests/sched_xetattr--pidns-translation.c | 2 + tests/sched_xetattr.c | 47 +- tests/sched_xetparam--pidns-translation.c | 2 + tests/sched_xetparam.c | 20 +- tests/sched_xetscheduler--pidns-translation.c | 2 + tests/sched_xetscheduler.c | 44 +- tests/signal_receive--pidns-translation.c | 2 + tests/signal_receive.c | 22 +- tests/so_peercred--pidns-translation.c | 2 + tests/so_peercred.c | 22 + tests/tgkill--pidns-translation.c | 2 + tests/tgkill.c | 51 +- tests/tkill--pidns-translation.c | 2 + tests/tkill.c | 19 +- tests/trie_for_tests.c | 1 + tests/trie_test.c | 121 ++++ tests/xet_robust_list--pidns-translation.c | 2 + tests/xet_robust_list.c | 18 +- tests/xetpgid--pidns-translation.c | 2 + tests/xetpgid.c | 21 +- tests/xetpriority--pidns-translation.c | 2 + tests/xetpriority.c | 20 +- tests/xmalloc_for_tests.c | 2 + trie.c | 290 +++++++++ trie.h | 92 +++ util.c | 31 +- wait.c | 36 +- 120 files changed, 2841 insertions(+), 275 deletions(-) create mode 100644 getpid.c create mode 100644 pidns.c create mode 100644 tests/fcntl--pidns-translation.c create mode 100644 tests/fcntl64--pidns-translation.c create mode 100644 tests/fork--pidns-translation.awk create mode 100644 tests/fork--pidns-translation.c create mode 100755 tests/fork--pidns-translation.test create mode 100644 tests/getpgrp--pidns-translation.c create mode 100644 tests/getpid--pidns-translation.c create mode 100644 tests/getsid--pidns-translation.c create mode 100644 tests/gettid--pidns-translation.c create mode 100755 tests/gettid--pidns-translation.test create mode 100644 tests/ioctl_block--pidns-translation.c create mode 100755 tests/ioctl_block--pidns-translation.test create mode 100644 tests/ioprio--pidns-translation.c create mode 100644 tests/kcmp-y--pidns-translation.c create mode 100644 tests/kill--pidns-translation.c create mode 100644 tests/migrate_pages--pidns-translation.c create mode 100644 tests/move_pages--pidns-translation.c create mode 100644 tests/net-sockaddr--pidns-translation.c create mode 100644 tests/netlink_audit--pidns-translation.c create mode 100755 tests/netlink_audit--pidns-translation.test create mode 100644 tests/pidfd_open--pidns-translation.c create mode 100644 tests/pidfd_send_signal--pidns-translation.c create mode 100644 tests/pidns-cache.c create mode 100755 tests/pidns-cache.test create mode 100644 tests/pidns.c create mode 100644 tests/pidns.h create mode 100644 tests/prlimit64--pidns-translation.c create mode 100644 tests/process_vm_readv--pidns-translation.c create mode 100644 tests/process_vm_writev--pidns-translation.c create mode 100644 tests/rt_sigqueueinfo--pidns-translation.c create mode 100644 tests/rt_tgsigqueueinfo--pidns-translation.c create mode 100644 tests/sched_xetaffinity--pidns-translation.c create mode 100644 tests/sched_xetattr--pidns-translation.c create mode 100644 tests/sched_xetparam--pidns-translation.c create mode 100644 tests/sched_xetscheduler--pidns-translation.c create mode 100644 tests/signal_receive--pidns-translation.c create mode 100644 tests/so_peercred--pidns-translation.c create mode 100644 tests/tgkill--pidns-translation.c create mode 100644 tests/tkill--pidns-translation.c create mode 100644 tests/trie_for_tests.c create mode 100644 tests/trie_test.c create mode 100644 tests/xet_robust_list--pidns-translation.c create mode 100644 tests/xetpgid--pidns-translation.c create mode 100644 tests/xetpriority--pidns-translation.c create mode 100644 tests/xmalloc_for_tests.c create mode 100644 trie.c create mode 100644 trie.h -- 2.28.0 From uzonyi.akos at gmail.com Sun Aug 23 22:25:51 2020 From: uzonyi.akos at gmail.com (=?UTF-8?q?=C3=81kos=20Uzonyi?=) Date: Mon, 24 Aug 2020 00:25:51 +0200 Subject: [PATCH v11 1/5] PID namespace translation support In-Reply-To: <20200823222555.1224386-1-uzonyi.akos@gmail.com> References: <20200823222555.1224386-1-uzonyi.akos@gmail.com> Message-ID: <20200823222555.1224386-2-uzonyi.akos@gmail.com> * defs.h (pidns_translation): New variable. (tcb): Add pid_ns field. (RVAL_MASK): Change value from 013 to 017. (RVAL_TID, RVAL_SID, RVAL_TGID, RVAL_PGID): New definitions. (pid_type): New enum. (pidns_init, translate_pid, get_proc_pid, printpid, printpid_tgid_pgid): New function declarations. * largefile_wrappers.h (fstat_fd): New macro. * pidns.c: New file. * trie.c: New file. * trie.h: New file. * Makefile.am (libstrace_a_SOURCES): Add trie.c, trie.h, pidns.c. * strace.c (pidns_translation): New variable. (init): Add --pidns-translation option. * syscall.c (syscall_exiting_trace): Handle RVAL_* return values. * NEWS: Mention this. * strace.1.in: Add description for new option. Co-Authored-by: Eugene Syromyatnikov --- Makefile.am | 3 + NEWS | 1 + defs.h | 56 +++- largefile_wrappers.h | 2 + pidns.c | 608 +++++++++++++++++++++++++++++++++++++++++++ strace.1.in | 4 + strace.c | 9 + syscall.c | 15 ++ trie.c | 290 +++++++++++++++++++++ trie.h | 92 +++++++ 10 files changed, 1079 insertions(+), 1 deletion(-) create mode 100644 pidns.c create mode 100644 trie.c create mode 100644 trie.h diff --git a/Makefile.am b/Makefile.am index f5447811..73c22035 100644 --- a/Makefile.am +++ b/Makefile.am @@ -233,6 +233,7 @@ libstrace_a_SOURCES = \ personality.c \ pidfd_getfd.c \ pidfd_open.c \ + pidns.c \ pkeys.c \ poll.c \ prctl.c \ @@ -344,6 +345,8 @@ libstrace_a_SOURCES = \ time.c \ times.c \ trace_event.h \ + trie.c \ + trie.h \ truncate.c \ ubi.c \ ucopy.c \ diff --git a/NEWS b/NEWS index 10039ceb..c3c5c162 100644 --- a/NEWS +++ b/NEWS @@ -2,6 +2,7 @@ Noteworthy changes in release ?.? (????-??-??) ============================================== * Improvements + * Added --pidns-translation option for PID namespace translation. * Bug fixes diff --git a/defs.h b/defs.h index f7ac54f3..511a92a2 100644 --- a/defs.h +++ b/defs.h @@ -280,6 +280,13 @@ struct tcb { struct timespec etime; /* Syscall entry time (CLOCK_MONOTONIC) */ struct timespec delay_expiration_time; /* When does the delay end */ + /* + * The ID of the PID namespace of this process + * (inode number of /proc//ns/pid) + * (0: not initialized) + */ + unsigned int pid_ns; + struct mmap_cache_t *mmap_cache; /* @@ -413,7 +420,11 @@ extern const struct xlat whence_codes[]; # define RVAL_HEX 001 /* hex format */ # define RVAL_OCTAL 002 /* octal format */ # define RVAL_FD 010 /* file descriptor */ -# define RVAL_MASK 013 /* mask for these values */ +# define RVAL_TID 011 /* task ID */ +# define RVAL_SID 012 /* session ID */ +# define RVAL_TGID 013 /* thread group ID */ +# define RVAL_PGID 014 /* process group ID */ +# define RVAL_MASK 017 /* mask for these values */ # define RVAL_STR 020 /* Print `auxstr' field after return val */ # define RVAL_NONE 040 /* Print nothing */ @@ -428,6 +439,16 @@ extern const struct xlat whence_codes[]; # define indirect_ipccall(tcp) (tcp_sysent(tcp)->sys_flags & TRACE_INDIRECT_SUBCALL) +enum pid_type { + PT_TID, + PT_TGID, + PT_PGID, + PT_SID, + + PT_COUNT, + PT_NONE = -1 +}; + enum sock_proto { SOCK_PROTO_UNKNOWN, SOCK_PROTO_UNIX, @@ -469,6 +490,7 @@ extern int Tflag_scale; extern int Tflag_width; extern bool iflag; extern bool count_wallclock; +extern unsigned int pidns_translation; /* are we filtering traces based on paths? */ extern struct path_set { const char **paths_selected; @@ -983,6 +1005,29 @@ print_local_array_ex(struct tcb *tcp, extern kernel_ulong_t * fetch_indirect_syscall_args(struct tcb *, kernel_ulong_t addr, unsigned int n_args); +extern void pidns_init(void); + +/** + * Returns the pid of the tracee as present in /proc of the tracer (can be + * different from tcp->pid if /proc and the tracer process are in different PID + * namespaces). + */ +extern int get_proc_pid(struct tcb *); + +/** + * Translates a pid from tracee's namespace to our namepace. + * + * @param tcp The tcb of the tracee + * (NULL: from_id is in strace's namespace. Useful for + * getting the proc PID of from_id) + * @param from_id The id to be translated + * @param type The PID type of from_id + * @param proc_pid_ptr If not NULL, writes the proc PID to this location + * @return The translated id, or 0 if translation fails. + */ +extern int translate_pid(struct tcb *, int dest_id, enum pid_type type, + int *proc_pid_ptr); + extern void dumpiov_in_msghdr(struct tcb *, kernel_ulong_t addr, kernel_ulong_t data_size); @@ -1058,6 +1103,15 @@ printfd(struct tcb *tcp, int fd) * of the tracee the descriptor tcp). This is a stub. */ extern void printfd_pid_tracee_ns(struct tcb *tcp, pid_t pid, int fd); + +/** Prints a PID specified in the tracee's PID namespace */ +extern void printpid(struct tcb *, int pid, enum pid_type type); + +/** + * Prints pid as a TGID if positive, and PGID if negative + * (like the first argument of kill). + */ +extern void printpid_tgid_pgid(struct tcb *, int pid); extern void print_sockaddr(struct tcb *, const void *sa, int len); extern bool print_inet_addr(int af, const void *addr, unsigned int len, const char *var_name); diff --git a/largefile_wrappers.h b/largefile_wrappers.h index 116e7048..9d8f5c92 100644 --- a/largefile_wrappers.h +++ b/largefile_wrappers.h @@ -29,6 +29,7 @@ # else # define fcntl_fd fcntl # endif +# define fstat_fd fstat64 # define strace_stat_t struct stat64 # define stat_file stat64 # define struct_dirent struct dirent64 @@ -39,6 +40,7 @@ # define open_file open # define fopen_stream fopen # define fcntl_fd fcntl +# define fstat_fd fstat # define strace_stat_t struct stat # define stat_file stat # define struct_dirent struct dirent diff --git a/pidns.c b/pidns.c new file mode 100644 index 00000000..94b16fa9 --- /dev/null +++ b/pidns.c @@ -0,0 +1,608 @@ +/* + * Copyright (c) 2020 ?kos Uzonyi + * All rights reserved. + * + * SPDX-License-Identifier: LGPL-2.1-or-later + */ + +#include "defs.h" + + +#include +#include +#include +#include +#include + +#include + +#include +#include +#include +#include + +#include "largefile_wrappers.h" +#include "trie.h" +#include "nsfs.h" +#include "xmalloc.h" +#include "xstring.h" + +/** + * Key: PID NS ID + * Value: a btree: + * Key: a process PID in NS + * Value: the process's PID as present in /proc + */ +static struct trie *ns_pid_to_proc_pid[PT_COUNT]; + +/** + * Key: Proc PID + * Value: struct proc_data + */ +static struct trie *proc_data_cache; + +static bool ns_get_parent_enotty = false; + +static const char tid_str[] = "NSpid:\t"; +static const char tgid_str[] = "NStgid:\t"; +static const char pgid_str[] = "NSpgid:\t"; +static const char sid_str[] = "NSsid:\t"; + +static const struct { + const char *str; + size_t size; +} id_strs[PT_COUNT] = { + [PT_TID] = { tid_str, sizeof(tid_str) - 1 }, + [PT_TGID] = { tgid_str, sizeof(tgid_str) - 1 }, + [PT_PGID] = { pgid_str, sizeof(pgid_str) - 1 }, + [PT_SID] = { sid_str, sizeof(sid_str) - 1 }, +}; + + +/** + * Limit on PID NS hierarchy depth, imposed since Linux 3.7. NS traversal + * is not possible before Linux 4.9, so we consider this limit pretty universal. + */ +#define MAX_NS_DEPTH 32 + +static const size_t ns_id_size = sizeof(unsigned int) * 8; +static const uint8_t ptr_sz_lg = (sizeof(void *) == 8 ? 6 : 5); + +static int pid_max; +static uint8_t pid_max_size, pid_max_size_lg; + +struct proc_data { + int proc_pid; + int ns_count; + unsigned int ns_hierarchy[MAX_NS_DEPTH]; + int id_count[PT_COUNT]; + int id_hierarchy[PT_COUNT][MAX_NS_DEPTH]; +}; + +/** + * Helper function for creating a trie. + * + * For node_key_bits and data_block_key_bits 4 is used (so trie height is 32 / 4 + * = 8, and node sizes are 8 byte * 2^4 = 128 bytes), which seems to be a good + * tradeoff between memory usage and lookup time. It should not be too large, + * since there can be large holes between PIDs, and it would be just a waste of + * memory having large nodes with lot of NULL pointers in them. + */ +static struct trie * +create_trie_4(uint8_t key_size, uint8_t item_size_lg, uint64_t empty_value) +{ + struct trie *t = trie_create(key_size, item_size_lg, 4, 4, empty_value); + if (!t) + error_msg_and_die("creating trie failed"); + + return t; +} + +void +pidns_init(void) +{ + if (proc_data_cache) + return; + + pid_max = INT_MAX; + if (read_int_from_file("/proc/sys/kernel/pid_max", &pid_max) < 0) + debug_func_perror_msg("reading /proc/sys/kernel/pid_max"); + pid_max_size = ilog2_32(pid_max - 1) + 1; + pid_max_size_lg = ilog2_32(pid_max_size - 1) + 1; + + for (int i = 0; i < PT_COUNT; i++) + ns_pid_to_proc_pid[i] = create_trie_4(ns_id_size, ptr_sz_lg, 0); + + proc_data_cache = create_trie_4(pid_max_size, ptr_sz_lg, 0); +} + +static void +put_proc_pid(unsigned int ns, int ns_pid, enum pid_type type, int proc_pid) +{ + struct trie *b = (struct trie *) (uintptr_t) trie_get(ns_pid_to_proc_pid[type], ns); + if (!b) { + b = create_trie_4(pid_max_size, pid_max_size_lg, 0); + trie_set(ns_pid_to_proc_pid[type], ns, (uint64_t) (uintptr_t) b); + } + trie_set(b, ns_pid, proc_pid); +} + +static int +get_cached_proc_pid(unsigned int ns, int ns_pid, enum pid_type type) +{ + struct trie *b = (struct trie *) (uintptr_t) + trie_get(ns_pid_to_proc_pid[type], ns); + if (!b) + return 0; + + return trie_get(b, ns_pid); +} + +/** + * Helper function, converts pid to string, or to "self" for pid == 0. + * Uses static buffer for operation. + */ +static const char * +pid_to_str(pid_t pid) +{ + if (!pid) + return "self"; + + static char buf[sizeof("-2147483648")]; + xsprintf(buf, "%d", pid); + return buf; +} + +/** + * Returns a list of PID NS IDs for the specified PID. + * + * @param proc_pid PID (as present in /proc) to get information for. + * @param ns_buf Pointer to buffer that is able to contain at least + * ns_buf_size items. + * @return Amount of NS in list. 0 indicates error. + */ +static size_t +get_ns_hierarchy(int proc_pid, unsigned int *ns_buf, size_t ns_buf_size) +{ + char path[PATH_MAX + 1]; + xsprintf(path, "/proc/%s/ns/pid", pid_to_str(proc_pid)); + + int fd = open_file(path, O_RDONLY); + if (fd < 0) + return 0; + + size_t n = 0; + while (n < ns_buf_size) { + strace_stat_t st; + if (fstat_fd(fd, &st)) + break; + + ns_buf[n++] = st.st_ino; + if (n >= ns_buf_size) + break; + + if (ns_get_parent_enotty) + break; + + int parent_fd = ioctl(fd, NS_GET_PARENT); + if (parent_fd < 0) { + switch (errno) { + case EPERM: + break; + + case ENOTTY: + ns_get_parent_enotty = true; + error_msg("NS_* ioctl commands are not " + "supported by the kernel"); + break; + + default: + perror_func_msg("ioctl(NS_GET_PARENT)"); + break; + } + + break; + } + + close(fd); + fd = parent_fd; + } + + close(fd); + + return n; +} + +/** + * Get list of IDs present in NS* proc status record. IDs are placed as they are + * stored in /proc (from top to bottom of NS hierarchy). + * + * @param proc_pid PID (as present in /proc) to get information for. + * @param id_buf Pointer to buffer that is able to contain at least + * MAX_NS_DEPTH items. Can be NULL. + * @param type Type of ID requested. + * @return Number of items stored in id_list. 0 indicates error. + */ +static size_t +get_id_list(int proc_pid, int *id_buf, enum pid_type type) +{ + const char *ns_str = id_strs[type].str; + size_t ns_str_size = id_strs[type].size; + + size_t n = 0; + + char status_path[PATH_MAX + 1]; + xsprintf(status_path, "/proc/%s/status", pid_to_str(proc_pid)); + FILE *f = fopen_stream(status_path, "r"); + if (!f) + return 0; + + char *line = NULL; + size_t linesize = 0; + char *p = NULL; + + while (getline(&line, &linesize, f) > 0) { + if (strncmp(line, ns_str, ns_str_size) == 0) { + p = line + ns_str_size; + break; + } + } + + while (p) { + errno = 0; + long id = strtol(p, NULL, 10); + + if (id < 0 || id > INT_MAX || errno) { + perror_func_msg("converting pid (%ld) to int", id); + break; + } + + if (id_buf) + id_buf[n] = (int) id; + + n++; + strsep(&p, "\t"); + } + + free(line); + fclose(f); + + return n; +} + +/** + * Returns whether the /proc filesystem's PID namespace is the same as strace's. + */ +static bool +is_proc_ours(void) +{ + static int cached_val = -1; + + if (cached_val < 0) + cached_val = get_id_list(0, NULL, PT_TID) <= 1; + + return cached_val; +} + +/** + * Returns the PID namespace of the tracee + */ +static unsigned int +get_ns(struct tcb *tcp) +{ + if (!tcp->pid_ns) { + int proc_pid = 0; + translate_pid(NULL, tcp->pid, PT_TID, &proc_pid); + + if (proc_pid) + get_ns_hierarchy(proc_pid, &tcp->pid_ns, 1); + } + + return tcp->pid_ns; +} + +/** + * Returns the PID namespace of strace + */ +static unsigned int +get_our_ns(void) +{ + static unsigned int our_ns = 0; + static bool our_ns_initialised = false; + + if (!our_ns_initialised) { + get_ns_hierarchy(0, &our_ns, 1); + our_ns_initialised = true; + } + + return our_ns; +} + +/** + * Returns the cached proc_data struct associated with proc_pid. + * If none found, allocates a new proc_data. + */ +static struct proc_data * +get_or_create_proc_data(int proc_pid) +{ + struct proc_data *pd = (struct proc_data *) (uintptr_t) + trie_get(proc_data_cache, proc_pid); + + if (!pd) { + pd = calloc(1, sizeof(*pd)); + if (!pd) + return NULL; + + pd->proc_pid = proc_pid; + trie_set(proc_data_cache, proc_pid, (uint64_t) (uintptr_t) pd); + } + + return pd; +} + +/** + * Updates the proc_data from /proc + * If the process does not exists, returns false, and frees the proc_data + */ +static bool +update_proc_data(struct proc_data *pd, enum pid_type type) +{ + pd->ns_count = get_ns_hierarchy(pd->proc_pid, + pd->ns_hierarchy, MAX_NS_DEPTH); + if (!pd->ns_count) + goto fail; + + pd->id_count[type] = get_id_list(pd->proc_pid, + pd->id_hierarchy[type], type); + if (!pd->id_count[type]) + goto fail; + + return true; + +fail: + trie_set(proc_data_cache, pd->proc_pid, (uint64_t) (uintptr_t) NULL); + free(pd); + return false; +} + +/** + * Paramters for id translation + */ +struct translate_id_params { + /* The result (output) */ + int result_id; + /* The proc data of the process (output) */ + struct proc_data *pd; + + /* The namespace to be translated from */ + unsigned int from_ns; + /* The id to be translated */ + int from_id; + /* The type of the id */ + enum pid_type type; +}; + +/** + * Translates an id to our namespace, given the proc_pid of the process, + * by reading files in /proc. + * + * @param tip The parameters + * @param proc_pid The proc pid of the process. + * If 0, use the cached values in tip->pd. + */ +static void +translate_id_proc_pid(struct translate_id_params *tip, int proc_pid) +{ + struct proc_data *pd = proc_pid ? + get_or_create_proc_data(proc_pid) : + tip->pd; + + tip->result_id = 0; + tip->pd = NULL; + + if (!pd) + return; + + if (proc_pid && !update_proc_data(pd, tip->type)) + return; + + if (!pd->ns_count || pd->id_count[tip->type] < pd->ns_count) + return; + + int *id_hierarchy = pd->id_hierarchy[tip->type]; + int id_count = pd->id_count[tip->type]; + + for (int i = 0; i < pd->ns_count; i++) { + unsigned int ns = pd->ns_hierarchy[i]; + int ns_id = id_hierarchy[id_count - i - 1]; + int our_id = id_hierarchy[id_count - pd->ns_count]; + + if (ns != tip->from_ns) + continue; + + if (ns_id != tip->from_id) + return; + + tip->result_id = our_id; + tip->pd = pd; + return; + } +} + +/** + * Translates an id to our namespace by reading all proc entries in a directory. + * The directory is either /proc or /proc//task. + * + * + * @param tip The parameters + * @param path The path of the directory to be read. + * @param read_task_dir Whether recurse to "task" subdirectory. + */ +static void +translate_id_dir(struct translate_id_params *tip, const char *path, + bool read_task_dir) +{ + DIR *dir = opendir(path); + if (!dir) { + debug_func_perror_msg("opening dir: %s", path); + return; + } + + while (!tip->result_id) { + errno = 0; + struct_dirent *entry = read_dir(dir); + if (!entry) { + if (errno) + perror_func_msg("readdir"); + + break; + } + + if (entry->d_type != DT_DIR) + continue; + + errno = 0; + long proc_pid = strtol(entry->d_name, NULL, 10); + if (proc_pid < 1 || proc_pid > INT_MAX || errno) + continue; + + if (read_task_dir) { + char task_dir_path[PATH_MAX + 1]; + xsprintf(task_dir_path, "/proc/%ld/task", proc_pid); + translate_id_dir(tip, task_dir_path, false); + } + + if (tip->result_id) + break; + + translate_id_proc_pid(tip, proc_pid); + } + + closedir(dir); +} + +/** + * Iterator function of the proc_data_cache for id translation. + * If the cache contains the id we are looking for, reads the corresponding + * directory in /proc, and if cache is valid, saves the result. + */ +static void +proc_data_cache_iterator_fn(void* fn_data, uint64_t key, uint64_t val) +{ + struct translate_id_params *tip = (struct translate_id_params *)fn_data; + struct proc_data *pd = (struct proc_data *) (uintptr_t) val; + + if (!pd) + return; + + /* Result already found in an earlier iteration */ + if (tip->result_id) + return; + + /* Translate from cache */ + tip->pd = pd; + translate_id_proc_pid(tip, 0); + if (!tip->result_id) + return; + + /* Now translate from actual data in /proc, to check cache validity */ + translate_id_proc_pid(tip, pd->proc_pid); +} + +int +translate_pid(struct tcb *tcp, int from_id, enum pid_type type, + int *proc_pid_ptr) +{ + if (from_id <= 0 || type < 0 || type >= PT_COUNT) + return 0; + + /* If translation is trivial */ + if ((!tcp || get_ns(tcp) == get_our_ns()) && + (!proc_pid_ptr || is_proc_ours())) { + if (proc_pid_ptr) + *proc_pid_ptr = from_id; + + return from_id; + } + + struct translate_id_params tip = { + .result_id = 0, + .pd = NULL, + .from_ns = tcp ? get_ns(tcp) : get_our_ns(), + .from_id = from_id, + .type = type, + }; + + if (!tip.from_ns) + return 0; + + if (ns_get_parent_enotty) + return 0; + + /* Look for a cached proc_pid for this (from_ns, from_id) pair */ + int cached_proc_pid = get_cached_proc_pid(tip.from_ns, tip.from_id, + tip.type); + if (cached_proc_pid) { + translate_id_proc_pid(&tip, cached_proc_pid); + if (tip.result_id) + goto exit; + } + + /* Iterate through the cache, find potential proc_data */ + trie_iterate_keys(proc_data_cache, 0, pid_max - 1, + proc_data_cache_iterator_fn, &tip); + /* (proc_data_cache_iterator_fn takes care about updating proc_data) */ + if (tip.result_id) + goto exit; + + /* No cache helped, read all entries in /proc */ + translate_id_dir(&tip, "/proc", true); + +exit: + if (tip.pd) { + if (tip.pd->proc_pid) + put_proc_pid(tip.from_ns, tip.from_id, tip.type, + tip.pd->proc_pid); + + if (proc_pid_ptr) + *proc_pid_ptr = tip.pd->proc_pid; + } + + return tip.result_id; +} + +int +get_proc_pid(struct tcb *tcp) +{ + int proc_pid = 0; + translate_pid(NULL, tcp->pid, PT_TID, &proc_pid); + return proc_pid; +} + +static void +printpid_translation(struct tcb *tcp, int pid, enum pid_type type) +{ + if (!pidns_translation) + return; + + int strace_pid = translate_pid(tcp, pid, type, NULL); + if (strace_pid && strace_pid != pid) + tprintf_comment("%d in strace's PID NS", strace_pid); +} + +void +printpid(struct tcb *tcp, int pid, enum pid_type type) +{ + tprintf("%d", pid); + printpid_translation(tcp, pid, type); +} + +void +printpid_tgid_pgid(struct tcb *tcp, int pid) +{ + tprintf("%d", pid); + if (pid > 0) + printpid_translation(tcp, pid, PT_TGID); + else if (pid < -1) + printpid_translation(tcp, -pid, PT_PGID); +} diff --git a/strace.1.in b/strace.1.in index 3b21caec..83776e88 100644 --- a/strace.1.in +++ b/strace.1.in @@ -1075,6 +1075,10 @@ Print all available information associated with file descritors: protocol-specific information associated with socket file descriptors, block/character device number associated with device file descriptors, and PIDs asociated with pidfd file descriptors. +.TP +.B \-\-pidns\-translation +If strace and tracee are in different PID namespaces, print PIDs in +strace's namespace, too. .SS Statistics .TP 12 .B \-c diff --git a/strace.c b/strace.c index 4c96a98b..249533ea 100644 --- a/strace.c +++ b/strace.c @@ -133,6 +133,8 @@ static unsigned int daemonized_tracer; static int post_attach_sigstop = TCB_IGNORE_ONE_SIGSTOP; #define use_seize (post_attach_sigstop == 0) +unsigned int pidns_translation; + static bool detach_on_execve; static int exit_code; @@ -1998,6 +2000,8 @@ init(int argc, char *argv[]) os_release = get_os_release(); + pidns_init(); + shared_log = stderr; set_sortby(DEFAULT_SORTBY); set_personality(DEFAULT_PERSONALITY); @@ -2022,6 +2026,7 @@ init(int argc, char *argv[]) GETOPT_FOLLOWFORKS, GETOPT_OUTPUT_SEPARATELY, GETOPT_TS, + GETOPT_PIDNS_TRANSLATION, GETOPT_QUAL_TRACE, GETOPT_QUAL_ABBREV, @@ -2072,6 +2077,7 @@ init(int argc, char *argv[]) { "summary-wall-clock", no_argument, 0, 'w' }, { "strings-in-hex", optional_argument, 0, GETOPT_HEX_STR }, { "const-print-style", required_argument, 0, 'X' }, + { "pidns-translation", no_argument , 0, GETOPT_PIDNS_TRANSLATION }, { "successful-only", no_argument, 0, 'z' }, { "failed-only", no_argument, 0, 'Z' }, { "failing-only", no_argument, 0, 'Z' }, @@ -2285,6 +2291,9 @@ init(int argc, char *argv[]) case 'y': yflag_short++; break; + case GETOPT_PIDNS_TRANSLATION: + pidns_translation++; + break; case 'z': clear_number_set_array(status_set, 1); add_number_to_set(STATUS_SUCCESSFUL, status_set); diff --git a/syscall.c b/syscall.c index bcc87025..0f4bab6d 100644 --- a/syscall.c +++ b/syscall.c @@ -937,6 +937,21 @@ syscall_exiting_trace(struct tcb *tcp, struct timespec *ts, int res) tprintf("= %" PRI_kld, tcp->u_rval); } break; + case RVAL_TID: + case RVAL_SID: + case RVAL_TGID: + case RVAL_PGID: { + #define _(_t) [RVAL_##_t - RVAL_TID] = PT_##_t + static const enum pid_type types[] = { + _(TID), _(SID), _(TGID), _(PGID), + }; + #undef _ + + tprints("= "); + printpid(tcp, tcp->u_rval, + types[(sys_res & RVAL_MASK) - RVAL_TID]); + break; + } default: error_msg("invalid rval format"); break; diff --git a/trie.c b/trie.c new file mode 100644 index 00000000..c26368ed --- /dev/null +++ b/trie.c @@ -0,0 +1,290 @@ +/* + * Simple trie implementation for key-value mapping storage + * + * Copyright (c) 2020 ?kos Uzonyi + * All rights reserved. + * + * SPDX-License-Identifier: LGPL-2.1-or-later + */ + +#ifdef HAVE_CONFIG_H +# include "config.h" +#endif + +#include +#include + +#include "trie.h" +#include "xmalloc.h" + +static const uint8_t ptr_sz_lg = (sizeof(void *) == 8 ? 6 : 5); + +/** + * Returns lg2 of node size in bits for the specific level of the trie. + */ +static uint8_t +trie_get_node_size(struct trie *t, uint8_t depth) +{ + /* Last level contains data and we allow it having a different size */ + if (depth == t->max_depth) + return t->data_block_key_bits + t->item_size_lg; + /* Last level of the tree can be smaller */ + if (depth == t->max_depth - 1) + return (t->key_size - t->data_block_key_bits - 1) % + t->node_key_bits + 1 + ptr_sz_lg; + + return t->node_key_bits + ptr_sz_lg; +} + +/** + * Provides starting offset of bits in key corresponding to the node index + * at the specific level. + */ +static uint8_t +trie_get_node_bit_offs(struct trie *t, uint8_t depth) +{ + uint8_t offs; + + if (depth == t->max_depth) + return 0; + + offs = t->data_block_key_bits; + + if (depth == t->max_depth - 1) + return offs; + + /* data_block_size + remainder */ + offs += trie_get_node_size(t, t->max_depth - 1) - ptr_sz_lg; + offs += (t->max_depth - depth - 2) * t->node_key_bits; + + return offs; +} + +struct trie * +trie_create(uint8_t key_size, uint8_t item_size_lg, uint8_t node_key_bits, + uint8_t data_block_key_bits, uint64_t empty_value) +{ + if (item_size_lg > 6) + return NULL; + if (key_size > 64) + return NULL; + if (node_key_bits < 1) + return NULL; + if (data_block_key_bits < 1 || data_block_key_bits > key_size) + return NULL; + + struct trie *t = malloc(sizeof(*t)); + if (!t) + return NULL; + + t->empty_value = empty_value; + t->data = NULL; + t->item_size_lg = item_size_lg; + t->node_key_bits = node_key_bits; + t->data_block_key_bits = data_block_key_bits; + t->key_size = key_size; + t->max_depth = (key_size - data_block_key_bits + node_key_bits - 1) + / t->node_key_bits; + + if (item_size_lg != 6) + t->empty_value &= (((uint64_t) 1 << (1 << t->item_size_lg)) - 1); + + return t; +} + +static void * +trie_create_data_block(struct trie *t) +{ + uint64_t fill_value = t->empty_value; + for (int i = 1; i < 1 << (6 - t->item_size_lg); i++) { + fill_value <<= (1 << t->item_size_lg); + fill_value |= t->empty_value; + } + + uint8_t sz = t->data_block_key_bits + t->item_size_lg; + if (sz < 6) + sz = 6; + + size_t count = 1 << (sz - 6); + uint64_t *data_block = xcalloc(count, 8); + + for (size_t i = 0; i < count; i++) + data_block[i] = fill_value; + + return data_block; +} + +static uint64_t * +trie_get_node(struct trie *t, uint64_t key, bool auto_create) +{ + void **cur_node = &(t->data); + + if (t->key_size < 64 && key > (uint64_t) 1 << t->key_size) + return NULL; + + for (uint8_t cur_depth = 0; cur_depth <= t->max_depth; cur_depth++) { + uint8_t offs = trie_get_node_bit_offs(t, cur_depth); + uint8_t sz = trie_get_node_size(t, cur_depth); + + if (!*cur_node) { + if (!auto_create) + return NULL; + + if (cur_depth == t->max_depth) + *cur_node = trie_create_data_block(t); + else + *cur_node = xcalloc(1 << sz, 1); + } + + if (cur_depth == t->max_depth) + break; + + size_t pos = (key >> offs) & ((1 << (sz - ptr_sz_lg)) - 1); + cur_node = (((void **) (*cur_node)) + pos); + } + + return (uint64_t *) (*cur_node); +} + +static void +trie_data_block_calc_pos(struct trie *t, uint64_t key, + uint64_t *pos, uint64_t *mask, uint64_t *offs) +{ + uint64_t key_mask; + + key_mask = (1 << t->data_block_key_bits) - 1; + *pos = (key & key_mask) >> (6 - t->item_size_lg); + + if (t->item_size_lg == 6) { + *offs = 0; + *mask = -1; + return; + } + + key_mask = (1 << (6 - t->item_size_lg)) - 1; + *offs = (key & key_mask) * (1 << t->item_size_lg); + + *mask = (((uint64_t) 1 << (1 << t->item_size_lg)) - 1) << *offs; +} + +bool +trie_set(struct trie *t, uint64_t key, uint64_t val) +{ + uint64_t *data = trie_get_node(t, key, true); + if (!data) + return false; + + uint64_t pos, mask, offs; + trie_data_block_calc_pos(t, key, &pos, &mask, &offs); + + data[pos] &= ~mask; + data[pos] |= (val << offs) & mask; + + return true; +} + +static uint64_t +trie_data_block_get(struct trie *t, uint64_t *data, uint64_t key) +{ + if (!data) + return t->empty_value; + + uint64_t pos, mask, offs; + trie_data_block_calc_pos(t, key, &pos, &mask, &offs); + + return (data[pos] & mask) >> offs; +} + +uint64_t +trie_get(struct trie *b, uint64_t key) +{ + return trie_data_block_get(b, trie_get_node(b, key, false), key); +} + +static uint64_t +trie_iterate_keys_node(struct trie *t, + trie_iterate_fn fn, void *fn_data, + void *node, uint64_t start, uint64_t end, + uint8_t depth) +{ + if (start > end || !node) + return 0; + + if (t->key_size < 64) { + uint64_t key_max = ((uint64_t) 1 << t->key_size) - 1; + if (end > key_max) + end = key_max; + } + + if (depth == t->max_depth) { + for (uint64_t i = start; i <= end; i++) + fn(fn_data, i, trie_data_block_get(t, + (uint64_t *) node, i)); + + return end - start + 1; + } + + uint8_t parent_node_bit_off = depth == 0 ? + t->key_size : + trie_get_node_bit_offs(t, depth - 1); + + uint64_t first_key_in_node = start & + (uint64_t) -1 << parent_node_bit_off; + + uint8_t node_bit_off = trie_get_node_bit_offs(t, depth); + uint8_t node_key_bits = parent_node_bit_off - node_bit_off; + uint64_t mask = ((uint64_t) 1 << (node_key_bits)) - 1; + uint64_t start_index = (start >> node_bit_off) & mask; + uint64_t end_index = (end >> node_bit_off) & mask; + uint64_t child_key_count = (uint64_t) 1 << node_bit_off; + + uint64_t count = 0; + + for (uint64_t i = start_index; i <= end_index; i++) { + uint64_t child_start = first_key_in_node + i * child_key_count; + uint64_t child_end = first_key_in_node + + (i + 1) * child_key_count - 1; + + if (child_start < start) + child_start = start; + if (child_end > end) + child_end = end; + + count += trie_iterate_keys_node(t, fn, fn_data, + ((void **) node)[i], child_start, child_end, + depth + 1); + } + + return count; +} + +uint64_t trie_iterate_keys(struct trie *t, uint64_t start, uint64_t end, + trie_iterate_fn fn, void *fn_data) +{ + return trie_iterate_keys_node(t, fn, fn_data, t->data, + start, end, 0); +} + +static void +trie_free_node(struct trie *t, void *node, uint8_t depth) +{ + if (!node) + return; + + if (depth >= t->max_depth) + goto free_node; + + size_t sz = 1 << (trie_get_node_size(t, depth) - ptr_sz_lg); + for (size_t i = 0; i < sz; i++) + trie_free_node(t, ((void **) node)[i], depth + 1); + +free_node: + free(node); +} + +void +trie_free(struct trie *t) +{ + trie_free_node(t, t->data, 0); + free(t); +} diff --git a/trie.h b/trie.h new file mode 100644 index 00000000..deb87a54 --- /dev/null +++ b/trie.h @@ -0,0 +1,92 @@ +/* + * Simple trie interface + * + * Copyright (c) 2020 ?kos Uzonyi + * All rights reserved. + * + * SPDX-License-Identifier: LGPL-2.1-or-later + */ + +#ifndef STRACE_TRIE_H +#define STRACE_TRIE_H + +#include +#include + +/** + * Trie control structure. + * Trie implemented here has the following properties: + * * It allows storing values of the same size, the size can vary from 1 bit to + * 64 bit values (only power of 2 sizes are allowed). + * * The key can be up to 64 bits in size. + * * It has separate configuration for node size and data block size. + * + * How bits of key are used for different node levels: + * + * highest bits lowest bits + * | node_key_bits | node_key_bits | ... | | data_block_key_bits | + * \_________________________________________________________________________/ + * key_size + * + * So, the remainder is used on the lowest non-data node level. + * + * As of now, it doesn't implement any mechanisms for resizing/changing key + * size. De-fragmentation is also unsupported currently. + */ +struct trie { + /** Return value of trie_get if key is not found */ + uint64_t empty_value; + + /** Pointer to root node */ + void *data; + + /** Key size in bits (0..64). */ + uint8_t key_size; + + /** + * Size of the stored values in log2 bits (0..6). + * (6: 64 bit values, 5: 32 bit values, ...) + */ + uint8_t item_size_lg; + + /** + * Number of bits in the key that make a symbol for a node. + * (equals to log2 of the child count of the node) + */ + uint8_t node_key_bits; + + /** + * Number of bits in the key that make a symbol for the data block (leaf). + * (equals to log2 of the value count stored in a data block) + */ + uint8_t data_block_key_bits; + + /** The depth of the data block. Calculated from the values above */ + uint8_t max_depth; +}; + +struct trie* trie_create(uint8_t key_size, uint8_t item_size_lg, + uint8_t node_key_bits, uint8_t data_block_key_bits, + uint64_t empty_value); + +bool trie_set(struct trie *t, uint64_t key, uint64_t val); +uint64_t trie_get(struct trie *t, uint64_t key); + +typedef void (*trie_iterate_fn)(void *data, uint64_t key, uint64_t val); + +/** + * Calls trie_iterate_fn for each key-value pair where + * key is inside the [start, end] interval (inclusive). + * + * @param t The trie. + * @param start The start of the key interval (inclusive). + * @param end The end of the key interval (inclusive). + * @param fn The function to be called. + * @param fn_data The value to be passed to fn. + */ +uint64_t trie_iterate_keys(struct trie *t, uint64_t start, uint64_t end, + trie_iterate_fn fn, void *fn_data); + +void trie_free(struct trie *t); + +#endif /* !STRACE_TRIE_H */ -- 2.28.0 From uzonyi.akos at gmail.com Sun Aug 23 22:25:52 2020 From: uzonyi.akos at gmail.com (=?UTF-8?q?=C3=81kos=20Uzonyi?=) Date: Mon, 24 Aug 2020 00:25:52 +0200 Subject: [PATCH v11 2/5] Use printpid in decoders In-Reply-To: <20200823222555.1224386-1-uzonyi.akos@gmail.com> References: <20200823222555.1224386-1-uzonyi.akos@gmail.com> Message-ID: <20200823222555.1224386-3-uzonyi.akos@gmail.com> * getpid.c: New file. * Makefile.am (libstrace_a_SOURCES): Add it. * linux/dummy.h (sys_getpid, sys_getppid, sys_gettid, sys_setpgid, sys_setpgrp): Remove. * util.c (printfd_pid_tracee_ns): Implement using translate_pid. * defs.h (printnum_pid): New function definition. (printfd_pid_tracee_ns): Update documentation * util.c: (printnum_pid): New function. * print_fields.h (PRINT_FIELD_TID): New macro. (PRINT_FIELD_TGID): Likewise. (PRINT_FIELD_PGID): Likewise. (PRINT_FIELD_SID): Likewise. * affinity.c: Print PIDs with printpid. * block.c: Likewise. * bpf.c: Likewise. * capability.c: Likewise. * clone.c: Likewise. * fcntl.c: Likewise. * get_robust_list.c: Likewise. * ioprio.c: Likewise. * kcmp.c: Likewise. * msghdr.c: Likewise. * net.c: Likewise. * netlink.c: Likewise. * numa.c: Likewise. * pidfd_open.c: Likewise. * printsiginfo.c: Likewise. * process.c: Likewise. * process_vm.c: Likewise. * resource.c: Likewise. * sched.c: Likewise. * signal.c: Likewise. * sockaddr.c: Likewise. * wait.c: Likewise. * kcmp.c (SYS_FUNC(kcmp)): Fix KCMP_FILE pid arguments. * tests/kcmp.c (printpidfd): Print path if VERBOSE_FD. (main): Use our real pid if real fds are used. --- Makefile.am | 1 + affinity.c | 6 ++++-- block.c | 2 +- bpf.c | 2 +- capability.c | 4 +++- clone.c | 14 +++++++------- defs.h | 5 ++++- fcntl.c | 24 ++++++++++++++++++++++-- get_robust_list.c | 3 ++- getpid.c | 46 ++++++++++++++++++++++++++++++++++++++++++++++ ioprio.c | 26 ++++++++++++++++++++++---- ipc_shmctl.c | 4 ++-- kcmp.c | 5 ++++- linux/dummy.h | 8 +------- msghdr.c | 2 +- net.c | 2 +- netlink.c | 5 +++-- numa.c | 6 ++++-- pidfd_open.c | 2 +- print_fields.h | 24 ++++++++++++++++++++++++ printsiginfo.c | 2 +- process.c | 3 ++- process_vm.c | 6 ++++-- resource.c | 27 ++++++++++++++++++++++++--- sched.c | 25 ++++++++++++++++--------- signal.c | 21 +++++++++++++++------ sockaddr.c | 2 +- tests/kcmp.c | 25 ++++++++++++++++++++++--- util.c | 22 +++++++++++++++------- wait.c | 36 ++++++++++++++++++++++++------------ 30 files changed, 278 insertions(+), 82 deletions(-) create mode 100644 getpid.c diff --git a/Makefile.am b/Makefile.am index 73c22035..15fcd9a6 100644 --- a/Makefile.am +++ b/Makefile.am @@ -135,6 +135,7 @@ libstrace_a_SOURCES = \ getcpu.c \ getcwd.c \ getpagesize.c \ + getpid.c \ getrandom.c \ hdio.c \ hostname.c \ diff --git a/affinity.c b/affinity.c index eb3158b7..f9893adb 100644 --- a/affinity.c +++ b/affinity.c @@ -82,7 +82,8 @@ SYS_FUNC(sched_setaffinity) const int pid = tcp->u_arg[0]; const unsigned int len = tcp->u_arg[1]; - tprintf("%d, %u, ", pid, len); + printpid(tcp, pid, PT_TGID); + tprintf(", %u, ", len); print_affinitylist(tcp, tcp->u_arg[2], len); return RVAL_DECODED; @@ -94,7 +95,8 @@ SYS_FUNC(sched_getaffinity) const unsigned int len = tcp->u_arg[1]; if (entering(tcp)) { - tprintf("%d, %u, ", pid, len); + printpid(tcp, pid, PT_TGID); + tprintf(", %u, ", len); } else { print_affinitylist(tcp, tcp->u_arg[2], tcp->u_rval); } diff --git a/block.c b/block.c index b527ef43..783a4b5a 100644 --- a/block.c +++ b/block.c @@ -179,7 +179,7 @@ MPERS_PRINTER_DECL(int, block_ioctl, struct tcb *const tcp, PRINT_FIELD_U(", ", buts, buf_nr); PRINT_FIELD_U(", ", buts, start_lba); PRINT_FIELD_U(", ", buts, end_lba); - PRINT_FIELD_D(", ", buts, pid); + PRINT_FIELD_TGID(", ", buts, pid, tcp); return 0; } else { struct_blk_user_trace_setup buts; diff --git a/bpf.c b/bpf.c index af830053..0ec33ba4 100644 --- a/bpf.c +++ b/bpf.c @@ -927,7 +927,7 @@ BEGIN_BPF_CMD_DECODER(BPF_TASK_FD_QUERY) if (entering(tcp)) { set_tcb_priv_ulong(tcp, attr.buf_len); - PRINT_FIELD_D("{task_fd_query={", attr, pid); + PRINT_FIELD_TGID("{task_fd_query={", attr, pid, tcp); PRINT_FIELD_FD(", ", attr, fd, tcp); PRINT_FIELD_U(", ", attr, flags); PRINT_FIELD_U(", ", attr, buf_len); diff --git a/capability.c b/capability.c index 0e763ee1..812fb435 100644 --- a/capability.c +++ b/capability.c @@ -70,7 +70,9 @@ print_cap_header(struct tcb *const tcp, const kernel_ulong_t addr, tprints("{version="); printxval(cap_version, h->version, "_LINUX_CAPABILITY_VERSION_???"); - tprintf(", pid=%d}", h->pid); + tprints(", pid="); + printpid(tcp, h->pid, PT_TGID); + tprints("}"); } static void diff --git a/clone.c b/clone.c index 487c5c23..45f24065 100644 --- a/clone.c +++ b/clone.c @@ -114,14 +114,14 @@ SYS_FUNC(clone) */ if ((flags & (CLONE_PARENT_SETTID|CLONE_PIDFD|CLONE_CHILD_SETTID |CLONE_CHILD_CLEARTID|CLONE_SETTLS)) == 0) - return RVAL_DECODED; + return RVAL_DECODED | RVAL_TID; } else { if (flags & (CLONE_PARENT_SETTID|CLONE_PIDFD)) { kernel_ulong_t addr = tcp->u_arg[ARG_PTID]; tprints(", parent_tid="); if (flags & CLONE_PARENT_SETTID) - printnum_int(tcp, addr, "%u"); + printnum_pid(tcp, addr, PT_TID); else printnum_fd(tcp, addr); } @@ -134,7 +134,7 @@ SYS_FUNC(clone) printaddr(tcp->u_arg[ARG_CTID]); } } - return 0; + return RVAL_TID; } @@ -229,7 +229,7 @@ SYS_FUNC(clone3) if ((arg.flags & (CLONE_PIDFD | CLONE_PARENT_SETTID)) || (size > fetch_size)) - return 0; + return RVAL_TID; goto out; } @@ -256,7 +256,7 @@ SYS_FUNC(clone3) if (arg.flags & CLONE_PARENT_SETTID) { tprintf("%sparent_tid=", pfx); - printnum_int(tcp, arg.parent_tid, "%d"); /* TID */ + printnum_pid(tcp, arg.parent_tid, PT_TID); pfx = ", "; } @@ -279,7 +279,7 @@ SYS_FUNC(clone3) out: tprintf(", %" PRI_klu, size); - return RVAL_DECODED; + return RVAL_DECODED | RVAL_TID; } @@ -300,5 +300,5 @@ SYS_FUNC(unshare) SYS_FUNC(fork) { - return RVAL_DECODED; + return RVAL_DECODED | RVAL_TGID; } diff --git a/defs.h b/defs.h index 511a92a2..328c1940 100644 --- a/defs.h +++ b/defs.h @@ -1100,7 +1100,7 @@ printfd(struct tcb *tcp, int fd) /** * Print file descriptor fd owned by process with ID pid (from the PID NS - * of the tracee the descriptor tcp). This is a stub. + * of the tracee). */ extern void printfd_pid_tracee_ns(struct tcb *tcp, pid_t pid, int fd); @@ -1561,6 +1561,9 @@ DECL_PRINTNUM_ADDR(int64); extern bool printnum_fd(struct tcb *, kernel_ulong_t addr); +extern bool +printnum_pid(struct tcb *const tcp, const kernel_ulong_t addr, enum pid_type type); + static inline bool printnum_slong(struct tcb *tcp, kernel_ulong_t addr) { diff --git a/fcntl.c b/fcntl.c index 6fcd5dac..5c630a06 100644 --- a/fcntl.c +++ b/fcntl.c @@ -28,7 +28,7 @@ print_struct_flock64(struct tcb *const tcp, const struct_kernel_flock64 *fl, con PRINT_FIELD_D(", ", *fl, l_start); PRINT_FIELD_D(", ", *fl, l_len); if (getlk) - PRINT_FIELD_D(", ", *fl, l_pid); + PRINT_FIELD_TGID(", ", *fl, l_pid, tcp); tprints("}"); } @@ -59,7 +59,22 @@ print_f_owner_ex(struct tcb *const tcp, const kernel_ulong_t addr) return; PRINT_FIELD_XVAL("{", owner, type, f_owner_types, "F_OWNER_???"); - PRINT_FIELD_D(", ", owner, pid); + + enum pid_type pid_type = PT_NONE; + switch (owner.type) + { + case F_OWNER_TID: + pid_type = PT_TID; + break; + case F_OWNER_PID: + pid_type = PT_TGID; + break; + case F_OWNER_PGRP: + pid_type = PT_PGID; + break; + } + tprints(", pid="); + printpid(tcp, owner.pid, pid_type); tprints("}"); } @@ -74,6 +89,9 @@ print_fcntl(struct tcb *tcp) printflags(fdflags, tcp->u_arg[2], "FD_???"); break; case F_SETOWN: + tprints(", "); + printpid_tgid_pgid(tcp, tcp->u_arg[2]); + break; case F_SETPIPE_SZ: tprintf(", %" PRI_kld, tcp->u_arg[2]); break; @@ -116,6 +134,8 @@ print_fcntl(struct tcb *tcp) printsignal(tcp->u_arg[2]); break; case F_GETOWN: + return RVAL_DECODED | + ((int) tcp->u_rval < 0 ? RVAL_PGID : RVAL_TGID); case F_GETPIPE_SZ: break; case F_GETFD: diff --git a/get_robust_list.c b/get_robust_list.c index b5aebaff..81aba2dd 100644 --- a/get_robust_list.c +++ b/get_robust_list.c @@ -10,7 +10,8 @@ SYS_FUNC(get_robust_list) { if (entering(tcp)) { - tprintf("%d, ", (int) tcp->u_arg[0]); + printpid(tcp, tcp->u_arg[0], PT_TID); + tprints(", "); } else { printnum_ptr(tcp, tcp->u_arg[1]); tprints(", "); diff --git a/getpid.c b/getpid.c new file mode 100644 index 00000000..5e9a1a29 --- /dev/null +++ b/getpid.c @@ -0,0 +1,46 @@ +/* + * Copyright (c) 2020 ?kos Uzonyi + * All rights reserved. + * + * SPDX-License-Identifier: LGPL-2.1-or-later + */ + +#include "defs.h" + +SYS_FUNC(getpid) +{ + return RVAL_DECODED | RVAL_TGID; +} + +SYS_FUNC(gettid) +{ + return RVAL_DECODED | RVAL_TID; +} + +SYS_FUNC(getpgrp) +{ + return RVAL_DECODED | RVAL_PGID; +} + +SYS_FUNC(getpgid) +{ + printpid(tcp, tcp->u_arg[0], PT_TGID); + + return RVAL_DECODED | RVAL_PGID; +} + +SYS_FUNC(getsid) +{ + printpid(tcp, tcp->u_arg[0], PT_TGID); + + return RVAL_DECODED | RVAL_SID; +} + +SYS_FUNC(setpgid) +{ + printpid(tcp, tcp->u_arg[0], PT_TGID); + tprints(", "); + printpid(tcp, tcp->u_arg[1], PT_PGID); + + return RVAL_DECODED; +} diff --git a/ioprio.c b/ioprio.c index 873c8ce5..149ef3fd 100644 --- a/ioprio.c +++ b/ioprio.c @@ -49,13 +49,30 @@ print_ioprio(unsigned int ioprio) ? tprints_comment : tprints)(str); } +static void +ioprio_print_who(struct tcb *tcp, int which, int who) +{ + switch (which) + { + case IOPRIO_WHO_PROCESS: + printpid(tcp, who, PT_TGID); + break; + case IOPRIO_WHO_PGRP: + printpid(tcp, who, PT_PGID); + break; + default: + tprintf("%d", who); + break; + } +} + SYS_FUNC(ioprio_get) { if (entering(tcp)) { /* int which */ printxval(ioprio_who, tcp->u_arg[0], "IOPRIO_WHO_???"); - /* int who */ - tprintf(", %d", (int) tcp->u_arg[1]); + tprints(", "); + ioprio_print_who(tcp, tcp->u_arg[0], tcp->u_arg[1]); return 0; } else { if (syserror(tcp)) @@ -72,8 +89,9 @@ SYS_FUNC(ioprio_set) { /* int which */ printxval(ioprio_who, tcp->u_arg[0], "IOPRIO_WHO_???"); - /* int who */ - tprintf(", %d, ", (int) tcp->u_arg[1]); + tprints(", "); + ioprio_print_who(tcp, tcp->u_arg[0], tcp->u_arg[1]); + tprints(", "); /* int ioprio */ if (xlat_verbose(xlat_verbosity) != XLAT_STYLE_ABBREV) tprintf("%d", (int) tcp->u_arg[2]); diff --git a/ipc_shmctl.c b/ipc_shmctl.c index 8c9e1e7a..1f99f02a 100644 --- a/ipc_shmctl.c +++ b/ipc_shmctl.c @@ -53,8 +53,8 @@ print_shmid_ds(struct tcb *const tcp, const kernel_ulong_t addr, int cmd) PRINT_FIELD_UID(", ", shmid_ds.shm_perm, cgid); tprints("}"); tprintf(", shm_segsz=%u", (unsigned) shmid_ds.shm_segsz); - PRINT_FIELD_D(", ", shmid_ds, shm_cpid); - PRINT_FIELD_D(", ", shmid_ds, shm_lpid); + PRINT_FIELD_TGID(", ", shmid_ds, shm_cpid, tcp); + PRINT_FIELD_TGID(", ", shmid_ds, shm_lpid, tcp); tprintf(", shm_nattch=%u", (unsigned) shmid_ds.shm_nattch); tprintf(", shm_atime=%u", (unsigned) shmid_ds.shm_atime); tprintf(", shm_dtime=%u", (unsigned) shmid_ds.shm_dtime); diff --git a/kcmp.c b/kcmp.c index 62115555..a5e1cdce 100644 --- a/kcmp.c +++ b/kcmp.c @@ -30,7 +30,10 @@ SYS_FUNC(kcmp) kernel_ulong_t idx1 = tcp->u_arg[3]; kernel_ulong_t idx2 = tcp->u_arg[4]; - tprintf("%d, %d, ", pid1, pid2); + printpid(tcp, pid1, PT_TGID); + tprints(", "); + printpid(tcp, pid2, PT_TGID); + tprints(", "); printxval(kcmp_types, type, "KCMP_???"); switch (type) { diff --git a/linux/dummy.h b/linux/dummy.h index 2f859a60..ca0d2f0c 100644 --- a/linux/dummy.h +++ b/linux/dummy.h @@ -53,6 +53,7 @@ # define sys_getgid sys_getuid # define sys_getgid16 sys_getuid16 # define sys_getpeername sys_getsockname +# define sys_getppid sys_getpid # define sys_getresgid sys_getresuid # define sys_getresgid16 sys_getresuid16 # define sys_lstat sys_stat @@ -87,10 +88,6 @@ # define sys_vfork sys_fork /* printargs does the right thing */ -# define sys_getpgrp printargs -# define sys_getpid printargs -# define sys_getppid printargs -# define sys_gettid printargs # define sys_idle printargs # define sys_munlockall printargs # define sys_pause printargs @@ -108,10 +105,7 @@ /* printargs_d does the right thing */ # define sys_exit printargs_d -# define sys_getpgid printargs_d -# define sys_getsid printargs_d # define sys_nice printargs_d -# define sys_setpgid printargs_d # define sys_setpgrp printargs_d # define sys_timer_delete printargs_d # define sys_timer_getoverrun printargs_d diff --git a/msghdr.c b/msghdr.c index ef6dc24b..170b8e51 100644 --- a/msghdr.c +++ b/msghdr.c @@ -69,7 +69,7 @@ print_scm_creds(struct tcb *tcp, const void *cmsg_data, { const struct ucred *uc = cmsg_data; - PRINT_FIELD_D("{", *uc, pid); + PRINT_FIELD_TGID("{", *uc, pid, tcp); PRINT_FIELD_UID(", ", *uc, uid); PRINT_FIELD_UID(", ", *uc, gid); tprints("}"); diff --git a/net.c b/net.c index fa4638e7..2099f0ac 100644 --- a/net.c +++ b/net.c @@ -601,7 +601,7 @@ print_get_ucred(struct tcb *const tcp, const kernel_ulong_t addr, if (umoven_or_printaddr(tcp, addr, len, &uc)) return; - PRINT_FIELD_LEN("{", uc, pid, len, PRINT_FIELD_D); + PRINT_FIELD_LEN("{", uc, pid, len, PRINT_FIELD_TGID, tcp); PRINT_FIELD_LEN(", ", uc, uid, len, PRINT_FIELD_UID); PRINT_FIELD_LEN(", ", uc, gid, len, PRINT_FIELD_UID); tprints("}"); diff --git a/netlink.c b/netlink.c index 88d864a9..cb29033a 100644 --- a/netlink.c +++ b/netlink.c @@ -446,8 +446,9 @@ print_nlmsghdr(struct tcb *tcp, decode_nlmsg_flags(nlmsghdr->nlmsg_flags, nlmsghdr->nlmsg_type, family); - tprintf(", seq=%u, pid=%d}", nlmsghdr->nlmsg_seq, - nlmsghdr->nlmsg_pid); + tprintf(", seq=%u, pid=", nlmsghdr->nlmsg_seq); + printpid(tcp, nlmsghdr->nlmsg_pid, PT_TGID); + tprints("}"); } static bool diff --git a/numa.c b/numa.c index cc7a7cc6..f7a58266 100644 --- a/numa.c +++ b/numa.c @@ -44,7 +44,8 @@ print_nodemask(struct tcb *const tcp, const kernel_ulong_t addr, SYS_FUNC(migrate_pages) { - tprintf("%d, %" PRI_klu ", ", (int) tcp->u_arg[0], tcp->u_arg[1]); + printpid(tcp, tcp->u_arg[0], PT_TGID); + tprintf(", %" PRI_klu ", ", tcp->u_arg[1]); print_nodemask(tcp, tcp->u_arg[2], tcp->u_arg[1]); tprints(", "); print_nodemask(tcp, tcp->u_arg[3], tcp->u_arg[1]); @@ -170,7 +171,8 @@ SYS_FUNC(move_pages) kernel_ulong_t buf; if (entering(tcp)) { - tprintf("%d, %" PRI_klu ", ", (int) tcp->u_arg[0], npages); + printpid(tcp, tcp->u_arg[0], PT_TGID); + tprintf(", %" PRI_klu ", ", npages); print_array(tcp, tcp->u_arg[2], npages, &buf, current_wordsize, tfetch_mem, print_addr, 0); tprints(", "); diff --git a/pidfd_open.c b/pidfd_open.c index bbc7f617..cf05a110 100644 --- a/pidfd_open.c +++ b/pidfd_open.c @@ -10,7 +10,7 @@ SYS_FUNC(pidfd_open) { /* pid_t pid */ - tprintf("%d", (int) tcp->u_arg[0]); + printpid(tcp, tcp->u_arg[0], PT_TGID); /* unsigned int flags */ tprintf(", %#x", (unsigned int) tcp->u_arg[1]); diff --git a/print_fields.h b/print_fields.h index f9714115..33d4a458 100644 --- a/print_fields.h +++ b/print_fields.h @@ -263,6 +263,30 @@ printfd((tcp_), (where_).field_); \ } while (0) +# define PRINT_FIELD_TID(prefix_, where_, field_, tcp_) \ + do { \ + STRACE_PRINTF("%s%s=", (prefix_), #field_); \ + printpid((tcp_), (where_).field_, PT_TID); \ + } while (0) + +# define PRINT_FIELD_TGID(prefix_, where_, field_, tcp_) \ + do { \ + STRACE_PRINTF("%s%s=", (prefix_), #field_); \ + printpid((tcp_), (where_).field_, PT_TGID); \ + } while (0) + +# define PRINT_FIELD_PGID(prefix_, where_, field_, tcp_) \ + do { \ + STRACE_PRINTF("%s%s=", (prefix_), #field_); \ + printpid((tcp_), (where_).field_, PT_PGID); \ + } while (0) + +# define PRINT_FIELD_SID(prefix_, where_, field_, tcp_) \ + do { \ + STRACE_PRINTF("%s%s=", (prefix_), #field_); \ + printpid((tcp_), (where_).field_, PT_SID); \ + } while (0) + # define PRINT_FIELD_STRN(prefix_, where_, field_, len_, tcp_) \ do { \ STRACE_PRINTF("%s%s=", (prefix_), #field_); \ diff --git a/printsiginfo.c b/printsiginfo.c index 8ed1e7ba..cb4cde4a 100644 --- a/printsiginfo.c +++ b/printsiginfo.c @@ -58,7 +58,7 @@ static void printsigsource(struct tcb *tcp, const siginfo_t *sip) { - PRINT_FIELD_D(", ", *sip, si_pid); + PRINT_FIELD_TGID(", ", *sip, si_pid, tcp); PRINT_FIELD_UID(", ", *sip, si_uid); } diff --git a/process.c b/process.c index a98c304e..d6ff255d 100644 --- a/process.c +++ b/process.c @@ -92,7 +92,8 @@ SYS_FUNC(ptrace) } /* pid */ - tprintf(", %d", pid); + tprints(", "); + printpid(tcp, pid, PT_TGID); /* addr */ switch (request) { diff --git a/process_vm.c b/process_vm.c index abee1e68..81d9b0f4 100644 --- a/process_vm.c +++ b/process_vm.c @@ -13,7 +13,8 @@ SYS_FUNC(process_vm_readv) { if (entering(tcp)) { /* arg 1: pid */ - tprintf("%d, ", (int) tcp->u_arg[0]); + printpid(tcp, tcp->u_arg[0], PT_TGID); + tprints(", "); } else { kernel_ulong_t local_iovcnt = tcp->u_arg[2]; kernel_ulong_t remote_iovcnt = tcp->u_arg[4]; @@ -42,7 +43,8 @@ SYS_FUNC(process_vm_writev) kernel_ulong_t flags = tcp->u_arg[5]; /* arg 1: pid */ - tprintf("%d, ", (int) tcp->u_arg[0]); + printpid(tcp, tcp->u_arg[0], PT_TGID); + tprints(", "); /* arg 2: local iov */ tprint_iov(tcp, local_iovcnt, tcp->u_arg[1], IOV_DECODE_STR); /* arg 3: local iovcnt */ diff --git a/resource.c b/resource.c index 53192ee9..070f4740 100644 --- a/resource.c +++ b/resource.c @@ -142,7 +142,8 @@ SYS_FUNC(setrlimit) SYS_FUNC(prlimit64) { if (entering(tcp)) { - tprintf("%d, ", (int) tcp->u_arg[0]); + printpid(tcp, tcp->u_arg[0], PT_TGID); + tprints(", "); printxval(resources, tcp->u_arg[1], "RLIMIT_???"); tprints(", "); print_rlimit64(tcp, tcp->u_arg[2]); @@ -179,10 +180,28 @@ SYS_FUNC(osf_getrusage) #include "xlat/priorities.h" +static void +priority_print_who(struct tcb *tcp, int which, int who) +{ + switch (which) + { + case PRIO_PROCESS: + printpid(tcp, who, PT_TGID); + break; + case PRIO_PGRP: + printpid(tcp, who, PT_PGID); + break; + default: + tprintf("%d", who); + break; + } +} + SYS_FUNC(getpriority) { printxval(priorities, tcp->u_arg[0], "PRIO_???"); - tprintf(", %d", (int) tcp->u_arg[1]); + tprints(", "); + priority_print_who(tcp, tcp->u_arg[0], tcp->u_arg[1]); return RVAL_DECODED; } @@ -190,7 +209,9 @@ SYS_FUNC(getpriority) SYS_FUNC(setpriority) { printxval(priorities, tcp->u_arg[0], "PRIO_???"); - tprintf(", %d, %d", (int) tcp->u_arg[1], (int) tcp->u_arg[2]); + tprints(", "); + priority_print_who(tcp, tcp->u_arg[0], tcp->u_arg[1]); + tprintf(", %d", (int) tcp->u_arg[2]); return RVAL_DECODED; } diff --git a/sched.c b/sched.c index 788ef39b..ff427e48 100644 --- a/sched.c +++ b/sched.c @@ -21,7 +21,7 @@ SYS_FUNC(sched_getscheduler) { if (entering(tcp)) { - tprintf("%d", (int) tcp->u_arg[0]); + printpid(tcp, tcp->u_arg[0], PT_TGID); } else if (!syserror(tcp)) { tcp->auxstr = xlookup(schedulers, (kernel_ulong_t) tcp->u_rval); return RVAL_STR; @@ -31,7 +31,8 @@ SYS_FUNC(sched_getscheduler) SYS_FUNC(sched_setscheduler) { - tprintf("%d, ", (int) tcp->u_arg[0]); + printpid(tcp, tcp->u_arg[0], PT_TGID); + tprints(", "); printxval(schedulers, tcp->u_arg[1], "SCHED_???"); tprints(", "); printnum_int(tcp, tcp->u_arg[2], "%d"); @@ -41,16 +42,19 @@ SYS_FUNC(sched_setscheduler) SYS_FUNC(sched_getparam) { - if (entering(tcp)) - tprintf("%d, ", (int) tcp->u_arg[0]); - else + if (entering(tcp)) { + printpid(tcp, tcp->u_arg[0], PT_TGID); + tprints(", "); + } else { printnum_int(tcp, tcp->u_arg[1], "%d"); + } return 0; } SYS_FUNC(sched_setparam) { - tprintf("%d, ", (int) tcp->u_arg[0]); + printpid(tcp, tcp->u_arg[0], PT_TGID); + tprints(", "); printnum_int(tcp, tcp->u_arg[1], "%d"); return RVAL_DECODED; @@ -68,7 +72,8 @@ do_sched_rr_get_interval(struct tcb *const tcp, const print_obj_by_addr_fn print_ts) { if (entering(tcp)) { - tprintf("%d, ", (int) tcp->u_arg[0]); + printpid(tcp, tcp->u_arg[0], PT_TGID); + tprints(", "); } else { if (syserror(tcp)) printaddr(tcp->u_arg[1]); @@ -160,7 +165,8 @@ end: SYS_FUNC(sched_setattr) { if (entering(tcp)) { - tprintf("%d, ", (int) tcp->u_arg[0]); + printpid(tcp, tcp->u_arg[0], PT_TGID); + tprints(", "); print_sched_attr(tcp, tcp->u_arg[1], 0); } else { struct sched_attr attr; @@ -179,7 +185,8 @@ SYS_FUNC(sched_setattr) SYS_FUNC(sched_getattr) { if (entering(tcp)) { - tprintf("%d, ", (int) tcp->u_arg[0]); + printpid(tcp, tcp->u_arg[0], PT_TGID); + tprints(", "); } else { const unsigned int size = tcp->u_arg[2]; diff --git a/signal.c b/signal.c index d5d59105..49b4ebd5 100644 --- a/signal.c +++ b/signal.c @@ -439,7 +439,8 @@ SYS_FUNC(sigprocmask) SYS_FUNC(kill) { /* pid */ - tprintf("%d, ", (int) tcp->u_arg[0]); + printpid_tgid_pgid(tcp, tcp->u_arg[0]); + tprints(", "); /* signal */ printsignal(tcp->u_arg[1]); @@ -448,7 +449,7 @@ SYS_FUNC(kill) SYS_FUNC(tkill) { - tprintf("%d", (int) tcp->u_arg[0]); + printpid(tcp, tcp->u_arg[0], PT_TID); tprints(", "); printsignal(tcp->u_arg[1]); @@ -457,8 +458,12 @@ SYS_FUNC(tkill) SYS_FUNC(tgkill) { - /* tgid, tid */ - tprintf("%d, %d, ", (int) tcp->u_arg[0], (int) tcp->u_arg[1]); + /* tgid */ + printpid(tcp, tcp->u_arg[0], PT_TGID); + tprints(", "); + /* tid */ + printpid(tcp, tcp->u_arg[1], PT_TID); + tprints(", "); /* signal */ printsignal(tcp->u_arg[2]); @@ -624,7 +629,8 @@ print_sigqueueinfo(struct tcb *const tcp, const int sig, SYS_FUNC(rt_sigqueueinfo) { - tprintf("%d, ", (int) tcp->u_arg[0]); + printpid(tcp, tcp->u_arg[0], PT_TGID); + tprints(", "); print_sigqueueinfo(tcp, tcp->u_arg[1], tcp->u_arg[2]); return RVAL_DECODED; @@ -632,7 +638,10 @@ SYS_FUNC(rt_sigqueueinfo) SYS_FUNC(rt_tgsigqueueinfo) { - tprintf("%d, %d, ", (int) tcp->u_arg[0], (int) tcp->u_arg[1]); + printpid(tcp, tcp->u_arg[0], PT_TGID); + tprints(", "); + printpid(tcp, tcp->u_arg[1], PT_TID); + tprints(", "); print_sigqueueinfo(tcp, tcp->u_arg[2], tcp->u_arg[3]); return RVAL_DECODED; diff --git a/sockaddr.c b/sockaddr.c index b0046331..fb8887c2 100644 --- a/sockaddr.c +++ b/sockaddr.c @@ -416,7 +416,7 @@ print_sockaddr_data_nl(struct tcb *tcp, const void *const buf, const int addrlen { const struct sockaddr_nl *const sa_nl = buf; - PRINT_FIELD_D("", *sa_nl, nl_pid); + PRINT_FIELD_TGID("", *sa_nl, nl_pid, tcp); PRINT_FIELD_0X(", ", *sa_nl, nl_groups); } diff --git a/tests/kcmp.c b/tests/kcmp.c index a46da0ed..dc5ba9a4 100644 --- a/tests/kcmp.c +++ b/tests/kcmp.c @@ -64,7 +64,26 @@ static const char zero_path[] = "/dev/zero"; static void printpidfd(const char *prefix, pid_t pid, unsigned fd) { - printf("%s%d", prefix, fd); + const char *path = NULL; + +# if VERBOSE_FD + if (pid == getpid()) { + switch (fd) + { + case NULL_FD: + path = null_path; + break; + case ZERO_FD: + path = zero_path; + break; + } + } +# endif + + if (path) + printf("%s%d<%s>", prefix, fd, path); + else + printf("%s%d", prefix, fd); } /* @@ -179,7 +198,7 @@ main(void) /* KCMP_FILE is the only type which has additional args */ do_kcmp(3141592653U, 2718281828U, ARG_STR(KCMP_FILE), bogus_idx1, bogus_idx2); - do_kcmp(-1, -1, ARG_STR(KCMP_FILE), NULL_FD, ZERO_FD); + do_kcmp(getpid(), getpid(), ARG_STR(KCMP_FILE), NULL_FD, ZERO_FD); /* Types without additional args */ do_kcmp(-1, -1, ARG_STR(KCMP_VM), bogus_idx1, bogus_idx2); @@ -198,7 +217,7 @@ main(void) for (i = 0; i < ARRAY_SIZE(slot_data); i++) { memcpy(slot, slot_data + i, sizeof(*slot)); - do_kcmp(getpid(), getppid(), ARG_STR(KCMP_EPOLL_TFD), NULL_FD, + do_kcmp(getpid(), -1, ARG_STR(KCMP_EPOLL_TFD), NULL_FD, (uintptr_t) slot, 1); } diff --git a/util.c b/util.c index 286c6903..2568021e 100644 --- a/util.c +++ b/util.c @@ -392,6 +392,18 @@ printnum_fd(struct tcb *const tcp, const kernel_ulong_t addr) return true; } +bool +printnum_pid(struct tcb *const tcp, const kernel_ulong_t addr, enum pid_type type) +{ + int pid; + if (umove_or_printaddr(tcp, addr, &pid)) + return false; + tprints("["); + printpid(tcp, pid, type); + tprints("]"); + return true; +} + /** * Prints time to a (static internal) buffer and returns pointer to it. * Returns NULL if the provided time specification is not correct. @@ -616,7 +628,7 @@ void printfd_pid(struct tcb *tcp, pid_t pid, int fd) { char path[PATH_MAX + 1]; - if (!number_set_array_is_empty(decode_fd_set, 0) + if (pid > 0 && !number_set_array_is_empty(decode_fd_set, 0) && getfdpath_pid(pid, fd, path, sizeof(path)) >= 0) { tprintf("%d<", (int) fd); if (is_number_in_set(DECODE_FD_SOCKET, decode_fd_set) && @@ -641,12 +653,8 @@ printed: void printfd_pid_tracee_ns(struct tcb *tcp, pid_t pid, int fd) { - /* - * TODO: We want to have the same formatting as printfd here, - * but we should figure out first which process in strace's - * PID NS is referred to by pid in tracee's PID NS. - */ - tprintf("%d", fd); + int strace_pid = translate_pid(tcp, pid, PT_TGID, NULL); + printfd_pid(tcp, strace_pid, fd); } /* diff --git a/wait.c b/wait.c index 2b9f9807..177427c8 100644 --- a/wait.c +++ b/wait.c @@ -80,14 +80,8 @@ printwaitn(struct tcb *const tcp, void (*const print_rusage)(struct tcb *, kernel_ulong_t)) { if (entering(tcp)) { - /* On Linux, kernel-side pid_t is typedef'ed to int - * on all arches. Also, glibc-2.8 truncates wait3 and wait4 - * pid argument to int on 64bit arches, producing, - * for example, wait4(4294967295, ...) instead of -1 - * in strace. We have to use int here, not long. - */ - int pid = tcp->u_arg[0]; - tprintf("%d, ", pid); + printpid_tgid_pgid(tcp, tcp->u_arg[0]); + tprintf(", "); } else { int status; @@ -108,7 +102,7 @@ printwaitn(struct tcb *const tcp, printaddr(tcp->u_arg[3]); } } - return 0; + return RVAL_TGID; } SYS_FUNC(waitpid) @@ -134,10 +128,28 @@ SYS_FUNC(osf_wait4) SYS_FUNC(waitid) { + unsigned int idtype = (unsigned int) tcp->u_arg[0]; + int id = tcp->u_arg[1]; + if (entering(tcp)) { - printxval(waitid_types, tcp->u_arg[0], "P_???"); - int pid = tcp->u_arg[1]; - tprintf(", %d, ", pid); + printxval(waitid_types, idtype, "P_???"); + tprints(", "); + switch (idtype) + { + case P_PID: + printpid(tcp, id, PT_TGID); + break; + case P_PIDFD: + printfd(tcp, id); + break; + case P_PGID: + printpid(tcp, id, PT_PGID); + break; + default: + tprintf("%d", id); + break; + } + tprints(", "); } else { /* siginfo */ printsiginfo_at(tcp, tcp->u_arg[2]); -- 2.28.0 From uzonyi.akos at gmail.com Sun Aug 23 22:25:53 2020 From: uzonyi.akos at gmail.com (=?UTF-8?q?=C3=81kos=20Uzonyi?=) Date: Mon, 24 Aug 2020 00:25:53 +0200 Subject: [PATCH v11 3/5] Use get_proc_pid for /proc paths In-Reply-To: <20200823222555.1224386-1-uzonyi.akos@gmail.com> References: <20200823222555.1224386-1-uzonyi.akos@gmail.com> Message-ID: <20200823222555.1224386-4-uzonyi.akos@gmail.com> * mmap_cache.c (mmap_cache_rebuild_if_invalid): Use proc pid instead of tcp->pid for /proc path. * util.c (getfdproto): Likewise. (pidfd_get_pid): Likewise. * pathtrace.c (getfdpath_pid): Likewise. * strace.c (attach_tcb): Likewise. --- mmap_cache.c | 2 +- pathtrace.c | 7 ++++++- strace.c | 2 +- util.c | 9 +++++++-- 4 files changed, 15 insertions(+), 5 deletions(-) diff --git a/mmap_cache.c b/mmap_cache.c index 89c62254..9825df26 100644 --- a/mmap_cache.c +++ b/mmap_cache.c @@ -84,7 +84,7 @@ mmap_cache_rebuild_if_invalid(struct tcb *tcp, const char *caller) return MMAP_CACHE_REBUILD_READY; char filename[sizeof("/proc/4294967296/maps")]; - xsprintf(filename, "/proc/%u/maps", tcp->pid); + xsprintf(filename, "/proc/%u/maps", get_proc_pid(tcp)); FILE *fp = fopen_stream(filename, "r"); if (!fp) { diff --git a/pathtrace.c b/pathtrace.c index 5b60762b..afed770a 100644 --- a/pathtrace.c +++ b/pathtrace.c @@ -87,7 +87,12 @@ getfdpath_pid(pid_t pid, int fd, char *buf, unsigned bufsize) if (fd < 0) return -1; - xsprintf(linkpath, "/proc/%u/fd/%u", pid, fd); + int proc_pid = 0; + translate_pid(NULL, pid, PT_TID, &proc_pid); + if (!proc_pid) + return -1; + + xsprintf(linkpath, "/proc/%u/fd/%u", proc_pid, fd); n = readlink(linkpath, buf, bufsize - 1); /* * NB: if buf is too small, readlink doesn't fail, diff --git a/strace.c b/strace.c index 249533ea..ef23f08f 100644 --- a/strace.c +++ b/strace.c @@ -1196,7 +1196,7 @@ attach_tcb(struct tcb *const tcp) unsigned int ntid = 0, nerr = 0; if (followfork && tcp->pid != strace_child && - xsprintf(procdir, task_path, tcp->pid) > 0 && + xsprintf(procdir, task_path, get_proc_pid(tcp)) > 0 && (dir = opendir(procdir)) != NULL) { struct_dirent *de; diff --git a/util.c b/util.c index 2568021e..481144bf 100644 --- a/util.c +++ b/util.c @@ -501,7 +501,7 @@ getfdproto(struct tcb *tcp, int fd) if (fd < 0) return SOCK_PROTO_UNKNOWN; - xsprintf(path, "/proc/%u/fd/%u", tcp->pid, fd); + xsprintf(path, "/proc/%u/fd/%u", get_proc_pid(tcp), fd); r = getxattr(path, "system.sockprotoname", buf, bufsize - 1); if (r <= 0) return SOCK_PROTO_UNKNOWN; @@ -582,8 +582,13 @@ printdev(struct tcb *tcp, int fd, const char *path) pid_t pidfd_get_pid(pid_t pid_of_fd, int fd) { + int proc_pid = 0; + translate_pid(NULL, pid_of_fd, PT_TID, &proc_pid); + if (!proc_pid) + return -1; + char fdi_path[sizeof("/proc/%u/fdinfo/%u") + 2 * sizeof(int) * 3]; - xsprintf(fdi_path, "/proc/%u/fdinfo/%u", pid_of_fd, fd); + xsprintf(fdi_path, "/proc/%u/fdinfo/%u", proc_pid, fd); FILE *f = fopen_stream(fdi_path, "r"); if (!f) -- 2.28.0 From uzonyi.akos at gmail.com Sun Aug 23 22:25:54 2020 From: uzonyi.akos at gmail.com (=?UTF-8?q?=C3=81kos=20Uzonyi?=) Date: Mon, 24 Aug 2020 00:25:54 +0200 Subject: [PATCH v11 4/5] Implement testing framework for pidns In-Reply-To: <20200823222555.1224386-1-uzonyi.akos@gmail.com> References: <20200823222555.1224386-1-uzonyi.akos@gmail.com> Message-ID: <20200823222555.1224386-5-uzonyi.akos@gmail.com> * tests/pidns.c: New file. * tests/pidns.h: New file. * tests/Makefile.am (libtests_a_SOURCES): Add pidns.c, pidns.h. * tests/init.sh (test_pidns, test_pidns_run_strace): New functions. --- tests/Makefile.am | 2 + tests/init.sh | 30 ++++++ tests/pidns.c | 237 ++++++++++++++++++++++++++++++++++++++++++++++ tests/pidns.h | 56 +++++++++++ 4 files changed, 325 insertions(+) create mode 100644 tests/pidns.c create mode 100644 tests/pidns.h diff --git a/tests/Makefile.am b/tests/Makefile.am index 28d95e39..7a583a3a 100644 --- a/tests/Makefile.am +++ b/tests/Makefile.am @@ -44,6 +44,8 @@ libtests_a_SOURCES = \ libsocketcall.c \ lock_file.c \ overflowuid.c \ + pidns.c \ + pidns.h \ pipe_maxfd.c \ print_quoted_string.c \ print_time.c \ diff --git a/tests/init.sh b/tests/init.sh index d78e697b..52417051 100644 --- a/tests/init.sh +++ b/tests/init.sh @@ -387,6 +387,36 @@ test_prog_set() test_pure_prog_set "$@" < "$srcdir/$NAME.in" } +test_pidns_run_strace() +{ + local parent_pid init_pid + + check_prog tail + check_prog cut + check_prog grep + + run_prog > /dev/null + run_strace --pidns-translation -f $@ $args > "$EXP" + + # filter out logs made by the parent or init process of the pidns test + parent_pid="$(tail -n 2 $LOG | head -n 1 | cut -d' ' -f1)" + init_pid="$(tail -n 1 $LOG | cut -d' ' -f1)" + grep -E -v "^($parent_pid|$init_pid) " "$LOG" > "$OUT" + match_diff "$OUT" "$EXP" +} + +test_pidns() +{ + check_prog unshare + unshare -Urpf true || framework_skip_ "unshare -Urpf true failed" + + test_pidns_run_strace "$@" + + # test PID translation when /proc is mounted from an other namespace + STRACE="unshare -Urpf $STRACE" + test_pidns_run_strace "$@" +} + check_prog cat check_prog rm diff --git a/tests/pidns.c b/tests/pidns.c new file mode 100644 index 00000000..4fe5b223 --- /dev/null +++ b/tests/pidns.c @@ -0,0 +1,237 @@ +/* + * Testing framework for PID namespace translation + * + * Copyright (c) 2020 ?kos Uzonyi + * All rights reserved. + * + * SPDX-License-Identifier: LGPL-2.1-or-later + */ +#include "tests.h" +#include "pidns.h" +#include "nsfs.h" + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#ifndef CLONE_NEWUSER +# define CLONE_NEWUSER 0x10000000 +#endif + +#ifndef CLONE_NEWPID +# define CLONE_NEWPID 0x20000000 +#endif + +static bool pidns_translation = false; +static bool pidns_unshared = false; + +/* Our PIDs in strace's namespace */ +static pid_t pidns_strace_ids[PT_COUNT]; + +void +pidns_print_leader(void) +{ + if (pidns_translation) + printf("%-5d ", pidns_strace_ids[PT_TID]); +} + +const char * +pidns_pid2str(enum pid_type type) +{ + static const char format[] = " /* %d in strace's PID NS */"; + static char buf[PT_COUNT][sizeof(format) + sizeof(int) * 3]; + + if (type < 0 || type >= PT_COUNT) + return ""; + + if (!pidns_unshared || !pidns_strace_ids[type]) + return ""; + + snprintf(buf[type], sizeof(buf[type]), format, pidns_strace_ids[type]); + return buf[type]; +} + +/** + * This function is like fork, but does a few more things. It sets up the + * child's PGID and SID according to the parameters. Also it fills the + * pidns_strace_ids array in the child's memory with the PIDs of the child in + * parent's PID namespace. In the parent it waits for the child to terminate + * (but leaves the zombie to use it later as a process group). If the child + * terminates with nonzero exit status, the test is failed. + * + * @param pgid The process group the child should be moved to. It's expected + * to be a PID of a zombie process (will be reaped). If + * negative, leave the child in the process group of the parent. + * If 0, move the process to its own process group. + * @param new_sid Wheather child should be moved to a new session. + */ +static pid_t +pidns_fork(pid_t pgid, bool new_sid) +{ + int strace_ids_pipe[2]; + if (pipe(strace_ids_pipe) < 0) + perror_msg_and_fail("pipe"); + + fflush(stdout); + pid_t pid = fork(); + if (pid < 0) + perror_msg_and_fail("fork"); + + if (!pid) { + close(strace_ids_pipe[1]); + + ssize_t len = read(strace_ids_pipe[0], pidns_strace_ids, + sizeof(pidns_strace_ids)); + if (len < 0) + perror_msg_and_fail("read"); + if (len != sizeof(pidns_strace_ids)) + error_msg_and_fail("read returned < sizeof(pidns_strace_ids)"); + + close(strace_ids_pipe[0]); + + if (pidns_strace_ids[PT_SID]) + setsid(); + + return 0; + } + + pidns_strace_ids[PT_TID] = pid; + pidns_strace_ids[PT_TGID] = pid; + pidns_strace_ids[PT_PGID] = 0; + pidns_strace_ids[PT_SID] = 0; + + if (!pgid) + pgid = pid; + + if (pgid > 0) { + if (setpgid(pid, pgid) < 0) + perror_msg_and_fail("setpgid"); + + pidns_strace_ids[PT_PGID] = pgid; + } + + /* Reap group leader to test PGID decoding */ + if (pgid > 0 && pgid != pid) { + int ret = waitpid(pgid, NULL, WNOHANG); + if (ret < 0) + perror_msg_and_fail("wait"); + if (!ret) + error_msg_and_fail("could not reap group leader"); + } + + if (new_sid) { + pidns_strace_ids[PT_SID] = pid; + pidns_strace_ids[PT_PGID] = pid; + } + + ssize_t len = write(strace_ids_pipe[1], pidns_strace_ids, + sizeof(pidns_strace_ids)); + if (len < 0) + perror_msg_and_fail("write"); + if (len != sizeof(pidns_strace_ids)) + error_msg_and_fail("write returned < sizeof(pidns_strace_ids)"); + + close(strace_ids_pipe[0]); + close(strace_ids_pipe[1]); + + /* WNOWAIT: leave the zombie, to be able to use it as a process group */ + siginfo_t siginfo; + if (waitid(P_PID, pid, &siginfo, WEXITED | WNOWAIT) < 0) + perror_msg_and_fail("wait"); + if (siginfo.si_code != CLD_EXITED || siginfo.si_status) + error_msg_and_fail("child terminated with nonzero exit status"); + + return pid; +} + +static void +create_init_process(void) +{ + int child_pipe[2]; + if (pipe(child_pipe) < 0) + perror_msg_and_fail("pipe"); + + pid_t pid = fork(); + if (pid < 0) + perror_msg_and_fail("fork"); + + if (!pid) { + close(child_pipe[1]); + if (read(child_pipe[0], &child_pipe[1], sizeof(int)) != 0) + _exit(1); + _exit(0); + } + + close(child_pipe[0]); +} + +void +check_ns_ioctl(void) +{ + int fd = open("/proc/self/ns/pid", O_RDONLY); + if (fd < 0) { + if (errno == ENOENT) + perror_msg_and_skip("opening /proc/self/ns/pid"); + else + perror_msg_and_fail("opening /proc/self/ns/pid"); + } + + int userns_fd = ioctl(fd, NS_GET_USERNS); + if (userns_fd < 0) { + if (errno == ENOTTY) + error_msg_and_skip("NS_* ioctl commands are not " + "supported by the kernel"); + else + perror_msg_and_fail("ioctl(NS_GET_USERNS)"); + } + + close(userns_fd); + close(fd); +} + +void +pidns_test_init(void) +{ + pidns_translation = true; + + check_ns_ioctl(); + + if (!pidns_fork(-1, false)) + return; + + /* Unshare user namespace too, so we do not need to be root */ + if (unshare(CLONE_NEWUSER | CLONE_NEWPID) < 0) { + if (errno == EPERM) + perror_msg_and_skip("unshare"); + + perror_msg_and_fail("unshare"); + } + + pidns_unshared = true; + + create_init_process(); + + if (!pidns_fork(-1, false)) + return; + + if (!pidns_fork(-1, true)) + return; + + pid_t pgid; + if (!(pgid = pidns_fork(0, false))) + return; + + if (!pidns_fork(pgid, false)) + return; + + exit(0); +} diff --git a/tests/pidns.h b/tests/pidns.h new file mode 100644 index 00000000..76963eb3 --- /dev/null +++ b/tests/pidns.h @@ -0,0 +1,56 @@ +/* + * Test PID namespace translation + * + * Copyright (c) 2020 ?kos Uzonyi + * All rights reserved. + * + * SPDX-License-Identifier: LGPL-2.1-or-later + */ +#ifndef STRACE_PIDNS_H +#define STRACE_PIDNS_H + +#ifdef PIDNS_TRANSLATION +# define PIDNS_TEST_INIT pidns_test_init() +#else +# define PIDNS_TEST_INIT +#endif + +#include + +enum pid_type { + PT_TID, + PT_TGID, + PT_PGID, + PT_SID, + + PT_COUNT, + PT_NONE = -1 +}; + +/* Prints leader (process tid) if pidns_test_init was called */ +void pidns_print_leader(void); + +/* + * Returns a static buffer containing the translation string of our PID. + */ +const char *pidns_pid2str(enum pid_type type); + +/** + * Skips the test if NS_* ioctl commands are not supported by the kernel. + */ +void check_ns_ioctl(void); + +/** + * Init pidns testing. + * + * Should be called at the beginning of the test's main function + * + * This function calls fork a couple of times, and returns in the child + * processes. These child processes are in a new PID namespace with different + * PID configurations (group leader, session leader, ...). If any child + * terminates with nonzero exit status the test is failed. Otherwise the test is + * succesful, and the parent process exits with 0. + */ +void pidns_test_init(void); + +#endif \ No newline at end of file -- 2.28.0 From uzonyi.akos at gmail.com Sun Aug 23 22:25:55 2020 From: uzonyi.akos at gmail.com (=?UTF-8?q?=C3=81kos=20Uzonyi?=) Date: Mon, 24 Aug 2020 00:25:55 +0200 Subject: [PATCH v11 5/5] Add tests for PID namespace translation In-Reply-To: <20200823222555.1224386-1-uzonyi.akos@gmail.com> References: <20200823222555.1224386-1-uzonyi.akos@gmail.com> Message-ID: <20200823222555.1224386-6-uzonyi.akos@gmail.com> * Makefile.am (CODE_COVERAGE_IGNORE_PATTERN): Add test directories. * tests/.gitignore: Add new test executables. * tests/Makefile.am (check_PROGRAMS): Add new test executables. (DECODER_TESTS) Add new test files. (libtests_a_SOURCES): Add trie_for_tests.c, xmalloc_for_tests.c. * tests/gen_tests.in: Add new tests. * tests/trie_test.c: New file. * tests/trie_for_tests.c: New file. * tests/xmalloc_for_tests.c: New file. * tests/pidns-cache.c: New file. * tests/pidns-cache.test: New file. * tests/fcntl--pidns-translation.c: New file. * tests/fcntl64--pidns-translation.c: New file. * tests/fork--pidns-translation.awk: New file. * tests/fork--pidns-translation.c: New file. * tests/fork--pidns-translation.test: New file. * tests/getpgrp--pidns-translation.c: New file. * tests/getpid--pidns-translation.c: New file. * tests/getsid--pidns-translation.c: New file. * tests/gettid--pidns-translation.c: New file. * tests/gettid--pidns-translation.test: New file. * tests/ioctl_block--pidns-translation.c: New file. * tests/ioctl_block--pidns-translation.test: New file. * tests/ioprio--pidns-translation.c: New file. * tests/kill--pidns-translation.c: New file. * tests/migrate_pages--pidns-translation.c: New file. * tests/move_pages--pidns-translation.c: New file. * tests/net-sockaddr--pidns-translation.c: New file. * tests/netlink_audit--pidns-translation.c: New file. * tests/netlink_audit--pidns-translation.test: New file. * tests/pidfd_open--pidns-translation.c: New file. * tests/pidfd_send_signal--pidns-translation.c: New file. * tests/prlimit64--pidns-translation.c: New file. * tests/process_vm_readv--pidns-translation.c: New file. * tests/process_vm_writev--pidns-translation.c: New file. * tests/rt_sigqueueinfo--pidns-translation.c: New file. * tests/rt_tgsigqueueinfo--pidns-translation.c: New file. * tests/sched_xetaffinity--pidns-translation.c: New file. * tests/sched_xetattr--pidns-translation.c: New file. * tests/sched_xetparam--pidns-translation.c: New file. * tests/sched_xetscheduler--pidns-translation.c: New file. * tests/signal_receive--pidns-translation.c: New file. * tests/so_peercred--pidns-translation.c: New file. * tests/tkill--pidns-translation.c: New file. * tests/tgkill--pidns-translation.c: New file. * tests/xet_robust_list--pidns-translation.c: New file. * tests/xetpgid--pidns-translation.c: New file. * tests/xetpriority--pidns-translation.c: New file. * tests/fcntl-common.c: Print PID translation string after PIDs. * tests/fcntl.c: Likewise. * tests/fcntl64.c: Likewise. * tests/getpgrp.c: Likewise. * tests/getpid.c: Likewise. * tests/getsid.c: Likewise. * tests/gettid.c: Likewise. * tests/ioctl_block.c: Likewise. * tests/ioprio.c: Likewise. * tests/kcmp.c: Likewise. * tests/kill.c: Likewise. * tests/migrate_pages.c: Likewise. * tests/move_pages.c: Likewise. * tests/net-sockaddr.c: Likewise. * tests/netlink_audit.c: Likewise. * tests/pidfd_open.c: Likewise. * tests/pidfd_send_signal.c: Likewise. * tests/prlimit64.c: Likewise. * tests/process_vm_readv_writev.c: Likewise. * tests/rt_sigqueueinfo.c: Likewise. * tests/rt_tgsigqueueinfo.c: Likewise. * tests/sched_xetaffinity.c: Likewise. * tests/sched_xetattr.c: Likewise. * tests/sched_xetparam.c: Likewise. * tests/sched_xetscheduler.c: Likewise. * tests/signal_receive.c: Likewise. * tests/so_peercred.c: Likewise. * tests/tgkill.c: Likewise. * tests/tkill.c: Likewise. * tests/xet_robust_list.c: Likewise. * tests/xetpgid.c: Likewise. * tests/xetpriority.c: Likewise. --- Makefile.am | 2 +- tests/.gitignore | 35 +++++ tests/Makefile.am | 48 +++++++ tests/fcntl--pidns-translation.c | 2 + tests/fcntl-common.c | 78 ++++++++--- tests/fcntl.c | 1 + tests/fcntl64--pidns-translation.c | 2 + tests/fcntl64.c | 3 + tests/fork--pidns-translation.awk | 15 +++ tests/fork--pidns-translation.c | 78 +++++++++++ tests/fork--pidns-translation.test | 14 ++ tests/gen_tests.in | 32 ++++- tests/getpgrp--pidns-translation.c | 2 + tests/getpgrp.c | 8 +- tests/getpid--pidns-translation.c | 2 + tests/getpid.c | 8 +- tests/getsid--pidns-translation.c | 2 + tests/getsid.c | 9 +- tests/gettid--pidns-translation.c | 2 + tests/gettid--pidns-translation.test | 18 +++ tests/gettid.c | 8 +- tests/ioctl_block--pidns-translation.c | 2 + tests/ioctl_block--pidns-translation.test | 22 ++++ tests/ioctl_block.c | 24 +++- tests/ioprio--pidns-translation.c | 2 + tests/ioprio.c | 54 +++++--- tests/kcmp-y--pidns-translation.c | 2 + tests/kcmp.c | 11 +- tests/kill--pidns-translation.c | 2 + tests/kill.c | 12 +- tests/migrate_pages--pidns-translation.c | 2 + tests/migrate_pages.c | 17 ++- tests/move_pages--pidns-translation.c | 2 + tests/move_pages.c | 51 +++++--- tests/net-sockaddr--pidns-translation.c | 2 + tests/net-sockaddr.c | 60 ++++++++- tests/netlink_audit--pidns-translation.c | 2 + tests/netlink_audit--pidns-translation.test | 13 ++ tests/netlink_audit.c | 11 +- tests/pidfd_open--pidns-translation.c | 2 + tests/pidfd_open.c | 21 ++- tests/pidfd_send_signal--pidns-translation.c | 2 + tests/pidfd_send_signal.c | 13 +- tests/pidns-cache.c | 62 +++++++++ tests/pidns-cache.test | 15 +++ tests/prlimit64--pidns-translation.c | 2 + tests/prlimit64.c | 17 ++- tests/process_vm_readv--pidns-translation.c | 2 + tests/process_vm_readv_writev.c | 27 ++-- tests/process_vm_writev--pidns-translation.c | 2 + tests/rt_sigqueueinfo--pidns-translation.c | 2 + tests/rt_sigqueueinfo.c | 15 ++- tests/rt_tgsigqueueinfo--pidns-translation.c | 2 + tests/rt_tgsigqueueinfo.c | 26 ++-- tests/sched_xetaffinity--pidns-translation.c | 2 + tests/sched_xetaffinity.c | 31 +++-- tests/sched_xetattr--pidns-translation.c | 2 + tests/sched_xetattr.c | 47 ++++++- tests/sched_xetparam--pidns-translation.c | 2 + tests/sched_xetparam.c | 20 ++- tests/sched_xetscheduler--pidns-translation.c | 2 + tests/sched_xetscheduler.c | 44 +++++-- tests/signal_receive--pidns-translation.c | 2 + tests/signal_receive.c | 22 +++- tests/so_peercred--pidns-translation.c | 2 + tests/so_peercred.c | 22 ++++ tests/tgkill--pidns-translation.c | 2 + tests/tgkill.c | 51 +++++--- tests/tkill--pidns-translation.c | 2 + tests/tkill.c | 19 ++- tests/trie_for_tests.c | 1 + tests/trie_test.c | 121 ++++++++++++++++++ tests/xet_robust_list--pidns-translation.c | 2 + tests/xet_robust_list.c | 18 ++- tests/xetpgid--pidns-translation.c | 2 + tests/xetpgid.c | 21 ++- tests/xetpriority--pidns-translation.c | 2 + tests/xetpriority.c | 20 ++- tests/xmalloc_for_tests.c | 2 + 79 files changed, 1144 insertions(+), 187 deletions(-) create mode 100644 tests/fcntl--pidns-translation.c create mode 100644 tests/fcntl64--pidns-translation.c create mode 100644 tests/fork--pidns-translation.awk create mode 100644 tests/fork--pidns-translation.c create mode 100755 tests/fork--pidns-translation.test create mode 100644 tests/getpgrp--pidns-translation.c create mode 100644 tests/getpid--pidns-translation.c create mode 100644 tests/getsid--pidns-translation.c create mode 100644 tests/gettid--pidns-translation.c create mode 100755 tests/gettid--pidns-translation.test create mode 100644 tests/ioctl_block--pidns-translation.c create mode 100755 tests/ioctl_block--pidns-translation.test create mode 100644 tests/ioprio--pidns-translation.c create mode 100644 tests/kcmp-y--pidns-translation.c create mode 100644 tests/kill--pidns-translation.c create mode 100644 tests/migrate_pages--pidns-translation.c create mode 100644 tests/move_pages--pidns-translation.c create mode 100644 tests/net-sockaddr--pidns-translation.c create mode 100644 tests/netlink_audit--pidns-translation.c create mode 100755 tests/netlink_audit--pidns-translation.test create mode 100644 tests/pidfd_open--pidns-translation.c create mode 100644 tests/pidfd_send_signal--pidns-translation.c create mode 100644 tests/pidns-cache.c create mode 100755 tests/pidns-cache.test create mode 100644 tests/prlimit64--pidns-translation.c create mode 100644 tests/process_vm_readv--pidns-translation.c create mode 100644 tests/process_vm_writev--pidns-translation.c create mode 100644 tests/rt_sigqueueinfo--pidns-translation.c create mode 100644 tests/rt_tgsigqueueinfo--pidns-translation.c create mode 100644 tests/sched_xetaffinity--pidns-translation.c create mode 100644 tests/sched_xetattr--pidns-translation.c create mode 100644 tests/sched_xetparam--pidns-translation.c create mode 100644 tests/sched_xetscheduler--pidns-translation.c create mode 100644 tests/signal_receive--pidns-translation.c create mode 100644 tests/so_peercred--pidns-translation.c create mode 100644 tests/tgkill--pidns-translation.c create mode 100644 tests/tkill--pidns-translation.c create mode 100644 tests/trie_for_tests.c create mode 100644 tests/trie_test.c create mode 100644 tests/xet_robust_list--pidns-translation.c create mode 100644 tests/xetpgid--pidns-translation.c create mode 100644 tests/xetpriority--pidns-translation.c create mode 100644 tests/xmalloc_for_tests.c diff --git a/Makefile.am b/Makefile.am index 15fcd9a6..88874d6b 100644 --- a/Makefile.am +++ b/Makefile.am @@ -408,7 +408,7 @@ endif CODE_COVERAGE_BRANCH_COVERAGE = 1 CODE_COVERAGE_GENHTML_OPTIONS = $(CODE_COVERAGE_GENHTML_OPTIONS_DEFAULT) \ --prefix $(shell cd $(abs_top_srcdir)/.. && pwd || echo .) -CODE_COVERAGE_IGNORE_PATTERN = '/usr/include/*' +CODE_COVERAGE_IGNORE_PATTERN = '/usr/include/*' '*/tests/*' '*/tests-m32/*' '*/tests-mx32/*' strace_CPPFLAGS += $(CODE_COVERAGE_CPPFLAGS) strace_CFLAGS += $(CODE_COVERAGE_CFLAGS) strace_LDADD += $(CODE_COVERAGE_LIBS) diff --git a/tests/.gitignore b/tests/.gitignore index 0031d04d..f95fc37c 100644 --- a/tests/.gitignore +++ b/tests/.gitignore @@ -116,7 +116,9 @@ fchown fchown32 fchownat fcntl +fcntl--pidns-translation fcntl64 +fcntl64--pidns-translation fdatasync fflush file_handle @@ -126,6 +128,7 @@ filter-unavailable finit_module flock fork-f +fork--pidns-translation fsconfig fsconfig-P fsmount @@ -168,7 +171,9 @@ getgroups getgroups32 getpeername getpgrp +getpgrp--pidns-translation getpid +getpid--pidns-translation getppid getrandom getresgid @@ -178,8 +183,10 @@ getresuid32 getrlimit getrusage getsid +getsid--pidns-translation getsockname gettid +gettid--pidns-translation getuid getuid32 getxgid @@ -200,6 +207,7 @@ io_uring_register io_uring_setup ioctl ioctl_block +ioctl_block--pidns-translation ioctl_dm ioctl_dm-v ioctl_evdev @@ -275,6 +283,7 @@ ioctl_watchdog ioperm iopl ioprio +ioprio--pidns-translation ioprio-Xabbrev ioprio-Xraw ioprio-Xverbose @@ -299,6 +308,7 @@ ipc_shm-Xverbose is_linux_mips_n64 kcmp kcmp-y +kcmp-y--pidns-translation kern_features kernel_version kernel_version-Xabbrev @@ -311,6 +321,7 @@ keyctl-Xabbrev keyctl-Xraw keyctl-Xverbose kill +kill--pidns-translation kill_child ksysent ksysent.h @@ -340,6 +351,7 @@ memfd_create-Xabbrev memfd_create-Xraw memfd_create-Xverbose migrate_pages +migrate_pages--pidns-translation mincore mkdir mkdirat @@ -371,6 +383,7 @@ move_pages move_pages-Xabbrev move_pages-Xraw move_pages-Xverbose +move_pages--pidns-translation mq mq_sendrecv mq_sendrecv-read @@ -391,6 +404,7 @@ net-packet_mreq-Xabbrev net-packet_mreq-Xraw net-packet_mreq-Xverbose net-sockaddr +net-sockaddr--pidns-translation net-tpacket_req net-tpacket_stats net-tpacket_stats-success @@ -400,6 +414,7 @@ net-yy-inet6 net-yy-netlink net-yy-unix netlink_audit +netlink_audit--pidns-translation netlink_crypto netlink_generic netlink_inet_diag @@ -507,7 +522,10 @@ pidfd_open--decode-fd-socket pidfd_open-P pidfd_open-y pidfd_open-yy +pidfd_open--pidns-translation pidfd_send_signal +pidfd_send_signal--pidns-translation +pidns-cache pipe pipe2 pkey_alloc @@ -546,8 +564,11 @@ printstrn-umoven printstrn-umoven-peekdata printstrn-umoven-undumpable prlimit64 +prlimit64--pidns-translation process_vm_readv +process_vm_readv--pidns-translation process_vm_writev +process_vm_writev--pidns-translation pselect6 ptrace ptrace_syscall_info @@ -597,10 +618,12 @@ rt_sigaction rt_sigpending rt_sigprocmask rt_sigqueueinfo +rt_sigqueueinfo--pidns-translation rt_sigreturn rt_sigsuspend rt_sigtimedwait rt_tgsigqueueinfo +rt_tgsigqueueinfo--pidns-translation run_expect_termsig s390_guarded_storage s390_guarded_storage-v @@ -611,9 +634,13 @@ s390_sthyi-v sched_get_priority_mxx sched_rr_get_interval sched_xetaffinity +sched_xetaffinity--pidns-translation sched_xetattr +sched_xetattr--pidns-translation sched_xetparam +sched_xetparam--pidns-translation sched_xetscheduler +sched_xetscheduler--pidns-translation sched_yield scm_rights scno.h @@ -669,6 +696,7 @@ sigaltstack siginfo signal signal_receive +signal_receive--pidns-translation signalfd4 sigpending sigprocmask @@ -681,6 +709,7 @@ so_peercred so_peercred-Xabbrev so_peercred-Xraw so_peercred-Xverbose +so_peercred--pidns-translation sock_filter-v sock_filter-v-Xabbrev sock_filter-v-Xraw @@ -730,6 +759,7 @@ syslog syslog-success tee tgkill +tgkill--pidns-translation threads-execve threads-execve--quiet-thread-execve threads-execve-q @@ -742,7 +772,9 @@ timerfd_xettime times times-fail tkill +tkill--pidns-translation tracer_ppid_pgid_sid +trie_test truncate truncate64 ugetrlimit @@ -783,9 +815,12 @@ waitpid xattr xattr-strings xet_robust_list +xet_robust_list--pidns-translation xet_thread_area_x86 xetitimer xetpgid +xetpgid--pidns-translation xetpriority +xetpriority--pidns-translation xettimeofday zeroargc diff --git a/tests/Makefile.am b/tests/Makefile.am index 7a583a3a..5dc9f561 100644 --- a/tests/Makefile.am +++ b/tests/Makefile.am @@ -66,6 +66,8 @@ libtests_a_SOURCES = \ test_ucopy.h \ tests.h \ tprintf.c \ + trie_for_tests.c \ + xmalloc_for_tests.c \ # end of libtests_a_SOURCES libtests_a_CPPFLAGS = $(AM_CPPFLAGS) -D_FILE_OFFSET_BITS=64 check_LIBRARIES = libtests.a @@ -109,17 +111,25 @@ check_PROGRAMS = $(PURE_EXECUTABLES) \ delay \ execve-v \ execveat-v \ + fcntl--pidns-translation \ + fcntl64--pidns-translation \ filter_seccomp-flag \ filter_seccomp-perf \ filter-unavailable \ fork-f \ + fork--pidns-translation \ fsync-y \ get_process_reaper \ + getpgrp--pidns-translation \ getpid \ + getpid--pidns-translation \ getppid \ + getsid--pidns-translation \ gettid \ + gettid--pidns-translation \ inject-nf \ int_0x80 \ + ioctl_block--pidns-translation \ ioctl_dm-v \ ioctl_evdev-success \ ioctl_evdev-success-Xabbrev \ @@ -150,18 +160,25 @@ check_PROGRAMS = $(PURE_EXECUTABLES) \ ioctl_v4l2-success-v-Xabbrev \ ioctl_v4l2-success-v-Xraw \ ioctl_v4l2-success-v-Xverbose \ + ioprio--pidns-translation \ is_linux_mips_n64 \ + kcmp-y--pidns-translation \ kill_child \ + kill--pidns-translation \ ksysent \ list_sigaction_signum \ localtime \ looping_threads \ + migrate_pages--pidns-translation \ mmsg-silent \ mmsg_name-v \ + move_pages--pidns-translation \ msg_control-v \ net-accept-connect \ + net-sockaddr--pidns-translation \ net-tpacket_stats-success \ nlattr_ifla_xdp-y \ + netlink_audit--pidns-translation \ netlink_inet_diag \ netlink_netlink_diag \ netlink_unix_diag \ @@ -173,14 +190,20 @@ check_PROGRAMS = $(PURE_EXECUTABLES) \ pc \ perf_event_open_nonverbose \ perf_event_open_unabbrev \ + pidfd_open--pidns-translation \ + pidfd_send_signal--pidns-translation \ + pidns-cache \ poll-P \ ppoll-P \ ppoll-v \ + prlimit64--pidns-translation \ prctl-seccomp-filter-v \ prctl-seccomp-strict \ prctl-spec-inject \ print_maxfd \ print_ppid_tracerpid \ + process_vm_readv--pidns-translation \ + process_vm_writev--pidns-translation \ qual_fault \ qual_inject-error-signal \ qual_inject-retval \ @@ -194,7 +217,13 @@ check_PROGRAMS = $(PURE_EXECUTABLES) \ quotactl-xfs-v \ redirect-fds \ restart_syscall \ + rt_sigqueueinfo--pidns-translation \ + rt_tgsigqueueinfo--pidns-translation \ run_expect_termsig \ + sched_xetaffinity--pidns-translation \ + sched_xetattr--pidns-translation \ + sched_xetparam--pidns-translation \ + sched_xetscheduler--pidns-translation \ scm_rights \ seccomp-filter-v \ seccomp-strict \ @@ -204,25 +233,33 @@ check_PROGRAMS = $(PURE_EXECUTABLES) \ set_sigign \ setpgrp-exec \ signal_receive \ + signal_receive--pidns-translation \ sleep \ stack-fcall \ stack-fcall-attach \ stack-fcall-mangled \ status-none-threads \ status-unfinished-threads \ + so_peercred--pidns-translation \ syslog-success \ + tgkill--pidns-translation \ threads-execve \ threads-execve--quiet-thread-execve \ threads-execve-q \ threads-execve-qq \ threads-execve-qqq \ + tkill--pidns-translation \ tracer_ppid_pgid_sid \ + trie_test \ unblock_reset_raise \ unix-pair-send-recv \ unix-pair-sendto-recvfrom \ vfork-f \ wait4-v \ waitid-v \ + xetpgid--pidns-translation \ + xetpriority--pidns-translation \ + xet_robust_list--pidns-translation \ zeroargc \ # end of check_PROGRAMS @@ -272,6 +309,11 @@ stack_fcall_mangled_SOURCES = stack-fcall-mangled.c \ stack-fcall-mangled-0.c stack-fcall-mangled-1.c \ stack-fcall-mangled-2.c stack-fcall-mangled-3.c +trie_test_SOURCES = trie_test.c trie_for_tests.c +trie_test_CPPFLAGS = $(AM_CPPFLAGS) $(CODE_COVERAGE_CPPFLAGS) +trie_test_CFLAGS = $(AM_CFLAGS) $(CODE_COVERAGE_CFLAGS) +trie_test_LDADD = $(LDADD) $(CODE_COVERAGE_LIBS) + include gen_tests.am if ENABLE_STACKTRACE @@ -310,6 +352,7 @@ DECODER_TESTS = \ int_0x80.test \ inotify_init-y.test \ ioctl.test \ + ioctl_block--pidns-translation.test \ ioctl_evdev-success.test \ ipc_msgbuf.test \ kern_features-fault.test \ @@ -381,15 +424,19 @@ MISC_TESTS = \ filtering_fd-syntax.test \ filtering_syscall-syntax.test \ first_exec_failure.test \ + fork--pidns-translation.test \ get_regs.test \ + gettid--pidns-translation.test \ inject-nf.test \ interactive_block.test \ kill_child.test \ localtime.test \ looping_threads.test \ + netlink_audit--pidns-translation.test \ opipe.test \ options-syntax.test \ pc.test \ + pidns-cache.test \ printpath-umovestr-legacy.test \ printstrn-umoven-legacy.test \ qual_fault-syntax.test \ @@ -467,6 +514,7 @@ EXTRA_DIST = \ filter_seccomp.in \ filter_seccomp.sh \ filter-unavailable.expected \ + fork--pidns-translation.awk \ fstatat.c \ fstatx.c \ gen_pure_executables.sh \ diff --git a/tests/fcntl--pidns-translation.c b/tests/fcntl--pidns-translation.c new file mode 100644 index 00000000..e249424a --- /dev/null +++ b/tests/fcntl--pidns-translation.c @@ -0,0 +1,2 @@ +#define PIDNS_TRANSLATION +#include "fcntl.c" diff --git a/tests/fcntl-common.c b/tests/fcntl-common.c index 27694326..ec18aa79 100644 --- a/tests/fcntl-common.c +++ b/tests/fcntl-common.c @@ -13,6 +13,8 @@ #include #include #include "flock.h" +#include "pidns.h" +#include "scno.h" #define FILE_LEN 4096 @@ -48,12 +50,14 @@ test_flock_einval(const int cmd, const char *name) fl->l_len = (TYPEOF_FLOCK_OFF_T) 0xdefaced2cafef00dULL; invoke_test_syscall(0, cmd, fl); + pidns_print_leader(); printf("%s(0, %s, {l_type=F_RDLCK, l_whence=SEEK_SET" ", l_start=%jd, l_len=%jd}) = %s\n", TEST_SYSCALL_STR, name, (intmax_t) fl->l_start, (intmax_t) fl->l_len, errstr); void *const bad_addr = (void *) fl + 1; invoke_test_syscall(0, cmd, bad_addr); + pidns_print_leader(); printf("%s(0, %s, %p) = %s\n", TEST_SYSCALL_STR, name, bad_addr, errstr); } @@ -72,12 +76,14 @@ test_flock64_einval(const int cmd, const char *name) fl->l_len = (TYPEOF_FLOCK_OFF_T) 0xdefaced2cafef00dULL; invoke_test_syscall(0, cmd, fl); + pidns_print_leader(); printf("%s(0, %s, {l_type=F_RDLCK, l_whence=SEEK_SET" ", l_start=%jd, l_len=%jd}) = %s\n", TEST_SYSCALL_STR, name, (intmax_t) fl->l_start, (intmax_t) fl->l_len, errstr); void *const bad_addr = (void *) fl + 1; invoke_test_syscall(0, cmd, bad_addr); + pidns_print_leader(); printf("%s(0, %s, %p) = %s\n", TEST_SYSCALL_STR, name, bad_addr, errstr); } @@ -94,6 +100,7 @@ test_flock(void) fl->l_len = FILE_LEN; long rc = invoke_test_syscall(0, F_SETLK, fl); + pidns_print_leader(); printf("%s(0, F_SETLK, {l_type=F_RDLCK, l_whence=SEEK_SET" ", l_start=0, l_len=%d}) = %s\n", TEST_SYSCALL_STR, FILE_LEN, errstr); @@ -101,11 +108,13 @@ test_flock(void) return; invoke_test_syscall(0, F_GETLK, fl); + pidns_print_leader(); printf("%s(0, F_GETLK, {l_type=F_UNLCK, l_whence=SEEK_SET" ", l_start=0, l_len=%d, l_pid=0}) = 0\n", TEST_SYSCALL_STR, FILE_LEN); invoke_test_syscall(0, F_SETLKW, fl); + pidns_print_leader(); printf("%s(0, F_SETLKW, {l_type=F_UNLCK, l_whence=SEEK_SET" ", l_start=0, l_len=%d}) = 0\n", TEST_SYSCALL_STR, FILE_LEN); @@ -124,6 +133,7 @@ test_flock64_ofd(void) fl->l_len = FILE_LEN; long rc = invoke_test_syscall(0, F_OFD_SETLK, fl); + pidns_print_leader(); printf("%s(0, F_OFD_SETLK, {l_type=F_RDLCK, l_whence=SEEK_SET" ", l_start=0, l_len=%d}) = %s\n", TEST_SYSCALL_STR, FILE_LEN, errstr); @@ -131,11 +141,13 @@ test_flock64_ofd(void) return; invoke_test_syscall(0, F_OFD_GETLK, fl); + pidns_print_leader(); printf("%s(0, F_OFD_GETLK, {l_type=F_UNLCK, l_whence=SEEK_SET" ", l_start=0, l_len=%d, l_pid=0}) = 0\n", TEST_SYSCALL_STR, FILE_LEN); invoke_test_syscall(0, F_OFD_SETLKW, fl); + pidns_print_leader(); printf("%s(0, F_OFD_SETLKW, {l_type=F_UNLCK, l_whence=SEEK_SET" ", l_start=0, l_len=%d}) = 0\n", TEST_SYSCALL_STR, FILE_LEN); @@ -167,18 +179,21 @@ test_flock64(void) static long test_f_owner_ex_type_pid(const int cmd, const char *const cmd_name, const int type, const char *const type_name, - pid_t pid) + enum pid_type pid_type, pid_t pid) { TAIL_ALLOC_OBJECT_CONST_PTR(struct_kernel_f_owner_ex, fo); fo->type = type; fo->pid = pid; long rc = invoke_test_syscall(0, cmd, fo); - printf("%s(0, %s, {type=%s, pid=%d}) = %s\n", - TEST_SYSCALL_STR, cmd_name, type_name, fo->pid, errstr); + pidns_print_leader(); + printf("%s(0, %s, {type=%s, pid=%d%s}) = %s\n", + TEST_SYSCALL_STR, cmd_name, type_name, + fo->pid, pidns_pid2str(pid_type), errstr); void *bad_addr = (void *) fo + 1; invoke_test_syscall(0, cmd, bad_addr); + pidns_print_leader(); printf("%s(0, %s, %p) = %s\n", TEST_SYSCALL_STR, cmd_name, bad_addr, errstr); @@ -187,35 +202,35 @@ test_f_owner_ex_type_pid(const int cmd, const char *const cmd_name, static void test_f_owner_ex_umove_or_printaddr(const int type, const char *const type_name, - pid_t pid) + enum pid_type pid_type, pid_t pid) { long rc = test_f_owner_ex_type_pid(ARG_STR(F_SETOWN_EX), - type, type_name, pid); + type, type_name, pid_type, pid); if (!rc) test_f_owner_ex_type_pid(ARG_STR(F_GETOWN_EX), - type, type_name, pid); + type, type_name, pid_type, pid); } static void test_f_owner_ex(void) { - static const struct { + struct { int type; const char *type_name; - pid_t pid[2]; + enum pid_type pid_type; + pid_t pid; } a[] = { - { ARG_STR(F_OWNER_TID), { 1234567890, 20 } }, - { ARG_STR(F_OWNER_PID), { 1298126790, 30 } }, - { ARG_STR(F_OWNER_PGRP), { 1294567890, 40 } } + { ARG_STR(F_OWNER_TID), PT_NONE, 1234567890 }, + { ARG_STR(F_OWNER_PID), PT_NONE, 1234567890 }, + { ARG_STR(F_OWNER_PGRP), PT_NONE, 1234567890 }, + { ARG_STR(F_OWNER_TID), PT_TID, syscall(__NR_gettid) }, + { ARG_STR(F_OWNER_PID), PT_TGID, getpid() }, + { ARG_STR(F_OWNER_PGRP), PT_PGID, getpgid(0) }, }; - for (unsigned int i = 0; i < ARRAY_SIZE(a); i++) { - for (unsigned int j = 0; j < ARRAY_SIZE(a[0].pid); j++) { - test_f_owner_ex_umove_or_printaddr(a[i].type, - a[i].type_name, - a[i].pid[j]); - } - } + for (unsigned int i = 0; i < ARRAY_SIZE(a); i++) + test_f_owner_ex_umove_or_printaddr(a[i].type, a[i].type_name, + a[i].pid_type, a[i].pid); } #endif /* TEST_F_OWNER_EX */ @@ -228,6 +243,23 @@ struct fcntl_cmd_check { void (*print_flags)(long rc); }; +static void +test_xetown(void) +{ + const int pid = getpid(); + const char *pid_str = pidns_pid2str(PT_TGID); + + invoke_test_syscall(0, F_SETOWN, (void *) (intptr_t) pid); + pidns_print_leader(); + printf("%s(0, F_SETOWN, %d%s) = %s\n", + TEST_SYSCALL_STR, pid, pid_str, errstr); + + invoke_test_syscall(0, F_GETOWN, NULL); + pidns_print_leader(); + printf("%s(0, F_GETOWN) = %d%s\n", + TEST_SYSCALL_STR, pid, pid_str); +} + static void print_retval_flags(const struct fcntl_cmd_check *check, long rc) { @@ -243,12 +275,14 @@ static void test_other_set_cmd(const struct fcntl_cmd_check *check) { invoke_test_syscall(check->fd, check->cmd, (void *) check->arg); + pidns_print_leader(); printf("%s(%d, %s, %s) = %s\n", TEST_SYSCALL_STR, check->fd, check->cmd_str, check->arg_str, errstr); /* bad file fd */ invoke_test_syscall(-1, check->cmd, (void *) check->arg); + pidns_print_leader(); printf("%s(-1, %s, %s) = %s\n", TEST_SYSCALL_STR, check->cmd_str, check->arg_str, errstr); @@ -258,12 +292,14 @@ static void test_other_get_cmd(const struct fcntl_cmd_check *check) { long rc = invoke_test_syscall(check->fd, check->cmd, NULL); + pidns_print_leader(); printf("%s(%d, %s) = ", TEST_SYSCALL_STR, check->fd, check->cmd_str); print_retval_flags(check, rc); /* bad file fd */ invoke_test_syscall(-1, check->cmd, NULL); + pidns_print_leader(); printf("%s(-1, %s) = %s\n", TEST_SYSCALL_STR, check->cmd_str, errstr); } @@ -315,7 +351,6 @@ test_fcntl_others(void) { static const struct fcntl_cmd_check set_checks[] = { { 0, ARG_STR(F_SETFD), ARG_STR(FD_CLOEXEC) }, - { 0, ARG_STR(F_SETOWN), ARG_STR(20) }, #ifdef F_SETPIPE_SZ { 0, ARG_STR(F_SETPIPE_SZ), ARG_STR(4097) }, #endif @@ -336,7 +371,6 @@ test_fcntl_others(void) static const struct fcntl_cmd_check get_checks[] = { { 0, ARG_STR(F_GETFD), .print_flags = print_flags_getfd }, { 1, ARG_STR(F_GETFD), .print_flags = print_flags_getfd }, - { 0, ARG_STR(F_GETOWN) }, #ifdef F_GETPIPE_SZ { 0, ARG_STR(F_GETPIPE_SZ) }, #endif @@ -360,6 +394,8 @@ create_sample(void) int main(void) { + PIDNS_TEST_INIT; + create_sample(); test_flock(); test_flock64(); @@ -367,7 +403,9 @@ main(void) test_f_owner_ex(); #endif test_fcntl_others(); + test_xetown(); + pidns_print_leader(); puts("+++ exited with 0 +++"); return 0; } diff --git a/tests/fcntl.c b/tests/fcntl.c index f38b8afb..673c06e4 100644 --- a/tests/fcntl.c +++ b/tests/fcntl.c @@ -24,6 +24,7 @@ test_flock64_undecoded(const int cmd, const char *name) .l_len = 0xdefaced2cafef00dULL }; invoke_test_syscall(0, cmd, &fl); + pidns_print_leader(); printf("%s(0, %s, %p) = %s\n", TEST_SYSCALL_STR, name, &fl, errstr); } diff --git a/tests/fcntl64--pidns-translation.c b/tests/fcntl64--pidns-translation.c new file mode 100644 index 00000000..c6fdadd1 --- /dev/null +++ b/tests/fcntl64--pidns-translation.c @@ -0,0 +1,2 @@ +#define PIDNS_TRANSLATION +#include "fcntl64.c" diff --git a/tests/fcntl64.c b/tests/fcntl64.c index 78e53b0d..f7b3f2fb 100644 --- a/tests/fcntl64.c +++ b/tests/fcntl64.c @@ -27,6 +27,7 @@ test_flock64_lk64(void) fl->l_len = FILE_LEN; long rc = invoke_test_syscall(0, F_SETLK64, fl); + pidns_print_leader(); printf("%s(0, F_SETLK64, {l_type=F_RDLCK, l_whence=SEEK_SET" ", l_start=0, l_len=%d}) = %s\n", TEST_SYSCALL_STR, FILE_LEN, errstr); @@ -35,11 +36,13 @@ test_flock64_lk64(void) return; invoke_test_syscall(0, F_GETLK64, fl); + pidns_print_leader(); printf("%s(0, F_GETLK64, {l_type=F_UNLCK, l_whence=SEEK_SET" ", l_start=0, l_len=%d, l_pid=0}) = 0\n", TEST_SYSCALL_STR, FILE_LEN); invoke_test_syscall(0, F_SETLKW64, fl); + pidns_print_leader(); printf("%s(0, F_SETLKW64, {l_type=F_UNLCK, l_whence=SEEK_SET" ", l_start=0, l_len=%d}) = 0\n", TEST_SYSCALL_STR, FILE_LEN); diff --git a/tests/fork--pidns-translation.awk b/tests/fork--pidns-translation.awk new file mode 100644 index 00000000..ef6858f4 --- /dev/null +++ b/tests/fork--pidns-translation.awk @@ -0,0 +1,15 @@ +/fork/ { + match($0, "([0-9]+) in strace\x27s PID NS", a); + if (a[1]) + fork_pid = a[1] +} + +/exited with 0/ { + if (!exit_pid) + exit_pid = $1 +} + +END { + if (!fork_pid || !exit_pid || fork_pid != exit_pid) + exit 1 +} diff --git a/tests/fork--pidns-translation.c b/tests/fork--pidns-translation.c new file mode 100644 index 00000000..1499a603 --- /dev/null +++ b/tests/fork--pidns-translation.c @@ -0,0 +1,78 @@ +/* + * Test PID namespace translation + * + * Copyright (c) 2020 ?kos Uzonyi + * All rights reserved. + * + * SPDX-License-Identifier: LGPL-2.1-or-later + */ + +#include "tests.h" +#include "scno.h" +#include "pidns.h" + +#ifdef __NR_fork + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "nsfs.h" + +#ifndef CLONE_NEWUSER +# define CLONE_NEWUSER 0x10000000 +#endif + +#ifndef CLONE_NEWPID +# define CLONE_NEWPID 0x20000000 +#endif + +static int +fork_chain(int depth) +{ + if (!depth) + return 0; + + int pid = syscall(__NR_fork); + if (pid < 0) + return errno; + + if (!pid) + _exit(fork_chain(depth - 1)); + + int status; + if (wait(&status) < 0) + return errno; + + if (!WIFEXITED(status)) + return -1; + + return WEXITSTATUS(status); +} + +int main(void) +{ + check_ns_ioctl(); + + if (unshare(CLONE_NEWPID | CLONE_NEWUSER) < 0) { + if (errno == EPERM) + perror_msg_and_skip("unshare"); + + perror_msg_and_fail("unshare"); + } + + errno = fork_chain(2); + if (errno) + perror("fork_chain"); +} + +#else + +SKIP_MAIN_UNDEFINED("__NR_fork") + +#endif diff --git a/tests/fork--pidns-translation.test b/tests/fork--pidns-translation.test new file mode 100755 index 00000000..24cc5930 --- /dev/null +++ b/tests/fork--pidns-translation.test @@ -0,0 +1,14 @@ +#!/bin/sh +# +# Check pidns translation of fork's return value. +# +# Copyright (c) 2020 The strace developers. +# All rights reserved. +# +# SPDX-License-Identifier: LGPL-2.1-or-later + +. "${srcdir=.}/init.sh" + +run_prog +run_strace -a6 --pidns-translation -f -e trace=fork $args +match_awk diff --git a/tests/gen_tests.in b/tests/gen_tests.in index 6f8e1420..e59a2f7f 100644 --- a/tests/gen_tests.in +++ b/tests/gen_tests.in @@ -93,7 +93,9 @@ fchown -a16 fchown32 -a18 fchownat fcntl -a8 +fcntl--pidns-translation test_pidns -a8 -e trace=fcntl fcntl64 -a8 +fcntl64--pidns-translation test_pidns -a8 -e trace=fcntl64 fdatasync -a14 file_handle -e trace=name_to_handle_at,open_by_handle_at file_ioctl +ioctl.test @@ -147,7 +149,9 @@ getgroups -a17 getgroups32 -a19 getpeername -a27 getpgrp -a10 +getpgrp--pidns-translation test_pidns -e trace=getpgrp -a10 getpid -a9 +getpid--pidns-translation test_pidns -e trace=getpid -a9 getppid -a10 getrandom -a32 -s3 getresgid -a25 @@ -157,6 +161,7 @@ getresuid32 -a27 getrlimit -a27 getrusage -v getsid -a10 +getsid--pidns-translation test_pidns -e trace=getsid -a10 getsockname -a27 gettid -a9 getuid-creds +getuid.test @@ -250,6 +255,7 @@ ioctl_watchdog +ioctl.test ioperm -a27 iopl -a8 ioprio -a18 -e trace=ioprio_get,ioprio_set +ioprio--pidns-translation test_pidns -a18 -e trace=ioprio_get,ioprio_set ioprio-Xabbrev -a18 -e trace=ioprio_get,ioprio_set -Xabbrev ioprio-Xraw -a18 -e trace=ioprio_get,ioprio_set -Xraw ioprio-Xverbose -a18 -e trace=ioprio_get,ioprio_set -Xverbose @@ -272,6 +278,7 @@ ipc_shm-Xraw +ipc.sh -Xraw -a19 ipc_shm-Xverbose +ipc.sh -Xverbose -a34 kcmp -a22 kcmp-y -a22 -y -e trace=kcmp +kcmp-y--pidns-translation test_pidns -a22 -y -e trace=kcmp kern_features -a16 kernel_version -a16 -v -e trace=bpf kernel_version-Xabbrev -a16 -Xabbrev -v -e trace=bpf @@ -284,6 +291,7 @@ keyctl-Xabbrev -a31 -s10 -e trace=keyctl -Xabbrev keyctl-Xraw -a13 -s10 -e trace=keyctl -Xraw keyctl-Xverbose -a41 -s10 -e trace=keyctl -Xverbose kill -a12 -esignal=none +kill--pidns-translation test_pidns -a12 -e trace=kill -esignal=none ksysent ../$NAME lchown -a30 lchown32 -a32 @@ -305,6 +313,7 @@ memfd_create-Xabbrev -Xabbrev -e trace=memfd_create memfd_create-Xraw -a30 -Xraw -e trace=memfd_create memfd_create-Xverbose -Xverbose -e trace=memfd_create migrate_pages -a33 +migrate_pages--pidns-translation test_pidns -a33 -e trace=migrate_pages mincore -a22 mkdir -a20 mkdirat -a28 @@ -335,6 +344,7 @@ move_pages -s3 move_pages-Xabbrev -s3 -e trace=move_pages -Xabbrev move_pages-Xraw -s3 -a36 -e trace=move_pages -Xraw move_pages-Xverbose -s3 -e trace=move_pages -Xverbose +move_pages--pidns-translation test_pidns -s3 -e trace=move_pages mq -a32 -e trace=mq_getsetattr,mq_open,mq_unlink mq_sendrecv -a14 -e trace=mq_open,mq_notify,mq_timedsend,mq_timedreceive,mq_unlink mq_sendrecv-read -eread=0 -a14 -e trace=mq_open,mq_notify,mq_timedsend,mq_timedreceive,mq_unlink @@ -354,6 +364,7 @@ net-packet_mreq-Xabbrev -e trace=setsockopt -Xabbrev net-packet_mreq-Xraw -e trace=setsockopt -Xraw net-packet_mreq-Xverbose -e trace=setsockopt -Xverbose net-sockaddr -a24 -e trace=connect +net-sockaddr--pidns-translation test_pidns -a24 -e trace=connect net-tpacket_req -e trace=setsockopt net-tpacket_stats -e trace=getsockopt net-yy-inet6 +net-yy-inet.test @@ -457,7 +468,9 @@ pidfd_open--decode-fd-socket -a17 -e decode-fd=socket -e trace=pidfd_open pidfd_open-P -a17 -P /dev/full -e trace=pidfd_open pidfd_open-y -a17 -y -e trace=pidfd_open pidfd_open-yy -a17 -yy -e trace=pidfd_open +pidfd_open--pidns-translation test_pidns -a17 -e trace=pidfd_open pidfd_send_signal +pidfd_send_signal--pidns-translation test_pidns -e trace=pidfd_send_signal pipe2 -a15 pkey_alloc -a17 pkey_free -a13 @@ -480,8 +493,11 @@ printstrn-umoven -s4096 -e signal=none -e trace=add_key printstrn-umoven-peekdata -e signal=none -e trace=add_key printstrn-umoven-undumpable -e signal=none -e trace=add_key prlimit64 +prlimit64--pidns-translation test_pidns -e trace=prlimit64 process_vm_readv -s5 -a37 +process_vm_readv--pidns-translation test_pidns -s5 -a37 -e trace=process_vm_readv process_vm_writev -s5 -a38 +process_vm_writev--pidns-translation test_pidns -s5 -a38 -e trace=process_vm_writev pselect6 ptrace -a23 -e signal=none ptrace_syscall_info -a35 -e signal=none -e trace=ptrace @@ -518,10 +534,12 @@ rmdir -a22 rt_sigpending -a20 rt_sigprocmask rt_sigqueueinfo -esignal=none +rt_sigqueueinfo--pidns-translation test_pidns -esignal=none -e trace=rt_sigqueueinfo rt_sigreturn -esignal='!USR1' rt_sigsuspend -a20 -esignal=none rt_sigtimedwait -a38 rt_tgsigqueueinfo -esignal=none +rt_tgsigqueueinfo--pidns-translation test_pidns -esignal=none -e trace=rt_tgsigqueueinfo s390_guarded_storage -a32 s390_guarded_storage-v -e trace=s390_guarded_storage -a32 -v s390_pci_mmio_read_write -e trace=s390_pci_mmio_read,s390_pci_mmio_write -a30 @@ -532,9 +550,13 @@ sched test_trace_expr times -e/sched sched_get_priority_mxx -a33 -e trace=sched_get_priority_min,sched_get_priority_max sched_rr_get_interval -a31 sched_xetaffinity -a28 -e trace=sched_getaffinity,sched_setaffinity +sched_xetaffinity--pidns-translation test_pidns -a28 -e trace=sched_getaffinity,sched_setaffinity sched_xetattr -a29 -e trace=sched_getattr,sched_setattr +sched_xetattr--pidns-translation test_pidns -a29 -e trace=sched_getattr,sched_setattr sched_xetparam -a23 -e trace=sched_getparam,sched_setparam +sched_xetparam--pidns-translation test_pidns -a23 -e trace=sched_getparam,sched_setparam sched_xetscheduler -a22 -e trace=sched_getscheduler,sched_setscheduler +sched_xetscheduler--pidns-translation test_pidns -a22 -e trace=sched_getscheduler,sched_setscheduler sched_yield -a14 seccomp-filter -e trace=seccomp seccomp-filter-v -v -e trace=seccomp @@ -581,6 +603,7 @@ sigaction -a31 siginfo -e trace=none signal -a25 -e signal=none -e trace='/^signal$' signal_receive -a16 -e trace=kill +signal_receive--pidns-translation test_pidns -a16 -e trace=kill signalfd4 sigpending -a15 sigprocmask -a34 @@ -592,6 +615,7 @@ so_peercred -e trace=getsockopt so_peercred-Xabbrev -e trace=getsockopt -Xabbrev so_peercred-Xraw -e trace=getsockopt -Xraw -a39 so_peercred-Xverbose -e trace=getsockopt -Xverbose +so_peercred--pidns-translation test_pidns -e trace=getsockopt sock_filter-v -v -e trace=getsockopt,setsockopt sock_filter-v-Xabbrev -v -e trace=getsockopt,setsockopt -X abbrev sock_filter-v-Xraw -a 37 -v -e trace=getsockopt,setsockopt -X raw @@ -664,6 +688,7 @@ sysinfo -a14 syslog -a35 tee tgkill -a15 --signal='!cont' +tgkill--pidns-translation test_pidns -a15 --signal='!cont' -e trace=tgkill threads-execve--quiet-thread-execve +threads-execve.test -s40 --quiet=personality,thread-execve threads-execve-q +threads-execve.test -q threads-execve-qq +threads-execve.test -qq @@ -675,6 +700,7 @@ timerfd_xettime -e trace=timerfd_create,timerfd_settime,timerfd_gettime times -esignal=none times-fail -a12 -e trace=times tkill -a12 --signal='!cont' +tkill--pidns-translation test_pidns --signal='!cont' -a12 -e trace=tkill trace_clock test_trace_expr 'clock_nanosleep|times' -e%clock trace_creds test_trace_expr '([gs]et[^p]*([gu]id|groups)|caps|prctl|[fl]?chown|print(path-umovestr|strn-umoven)-undumpable|ptrace|quotactl|rt_sigtimedwait|rt_(tg)?sigqueueinfo).*' -e%creds trace_fstat test_trace_expr '' -e%fstat -v -P stat.sample -P /dev/full @@ -691,6 +717,7 @@ trace_stat test_trace_expr '' -e%stat -v -P stat.sample -P /dev/full trace_stat_like test_trace_expr '' -e%%stat -v -P stat.sample -P /dev/full trace_statfs test_trace_expr '' -e%statfs trace_statfs_like test_trace_expr '' -e%%statfs +trie_test run_prog truncate truncate64 ugetrlimit -a28 @@ -721,7 +748,10 @@ waitpid -a28 xattr -a22 -e trace=getxattr,fgetxattr,lgetxattr,setxattr,fsetxattr,lsetxattr,listxattr,flistxattr,llistxattr,removexattr,fremovexattr,lremovexattr xattr-strings -a22 -s 4 -e trace=fsetxattr xet_robust_list -a24 -e trace=get_robust_list,set_robust_list +xet_robust_list--pidns-translation test_pidns -a24 -e trace=get_robust_list,set_robust_list xetitimer -a29 -e trace=setitimer,getitimer xetpgid -a11 -e trace=getpgid,setpgid -xetpriority -a29 -e trace=getpriority,setpriority +xetpgid--pidns-translation test_pidns -a11 -e trace=getpgid,setpgid +xetpriority -a27 -e trace=getpriority,setpriority +xetpriority--pidns-translation test_pidns -a27 -e trace=getpriority,setpriority xettimeofday -a20 -e trace=gettimeofday,settimeofday diff --git a/tests/getpgrp--pidns-translation.c b/tests/getpgrp--pidns-translation.c new file mode 100644 index 00000000..de8ceb33 --- /dev/null +++ b/tests/getpgrp--pidns-translation.c @@ -0,0 +1,2 @@ +#define PIDNS_TRANSLATION +#include "getpgrp.c" diff --git a/tests/getpgrp.c b/tests/getpgrp.c index 104f4811..3f0b9dd1 100644 --- a/tests/getpgrp.c +++ b/tests/getpgrp.c @@ -7,6 +7,7 @@ #include "tests.h" #include "scno.h" +#include "pidns.h" #ifdef __NR_getpgrp @@ -16,8 +17,13 @@ int main(void) { - printf("getpgrp() = %ld\n", syscall(__NR_getpgrp)); + PIDNS_TEST_INIT; + pidns_print_leader(); + printf("getpgrp() = %d%s\n", (int) syscall(__NR_getpgrp), + pidns_pid2str(PT_PGID)); + + pidns_print_leader(); puts("+++ exited with 0 +++"); return 0; } diff --git a/tests/getpid--pidns-translation.c b/tests/getpid--pidns-translation.c new file mode 100644 index 00000000..94b12a1a --- /dev/null +++ b/tests/getpid--pidns-translation.c @@ -0,0 +1,2 @@ +#define PIDNS_TRANSLATION +#include "getpid.c" diff --git a/tests/getpid.c b/tests/getpid.c index 988f19d5..7ec4e6e8 100644 --- a/tests/getpid.c +++ b/tests/getpid.c @@ -7,6 +7,7 @@ #include "tests.h" #include "scno.h" +#include "pidns.h" #if defined __NR_getpid && (!defined __NR_getxpid || __NR_getxpid != __NR_getpid) @@ -16,7 +17,12 @@ int main(void) { - printf("getpid() = %ld\n", syscall(__NR_getpid)); + PIDNS_TEST_INIT; + + pidns_print_leader(); + printf("getpid() = %d%s\n", (int) syscall(__NR_getpid), + pidns_pid2str(PT_TGID)); + pidns_print_leader(); puts("+++ exited with 0 +++"); return 0; } diff --git a/tests/getsid--pidns-translation.c b/tests/getsid--pidns-translation.c new file mode 100644 index 00000000..7f983e87 --- /dev/null +++ b/tests/getsid--pidns-translation.c @@ -0,0 +1,2 @@ +#define PIDNS_TRANSLATION +#include "getsid.c" diff --git a/tests/getsid.c b/tests/getsid.c index 588ea4ab..3bf74734 100644 --- a/tests/getsid.c +++ b/tests/getsid.c @@ -6,15 +6,22 @@ */ #include "tests.h" +#include "pidns.h" + #include #include int main(void) { + PIDNS_TEST_INIT; + pid_t pid = getpid(); - printf("getsid(%d) = %d\n", pid, getsid(pid)); + pidns_print_leader(); + printf("getsid(%d%s) = %d%s\n", pid, pidns_pid2str(PT_TGID), + getsid(pid), pidns_pid2str(PT_SID)); + pidns_print_leader(); puts("+++ exited with 0 +++"); return 0; } diff --git a/tests/gettid--pidns-translation.c b/tests/gettid--pidns-translation.c new file mode 100644 index 00000000..500c3213 --- /dev/null +++ b/tests/gettid--pidns-translation.c @@ -0,0 +1,2 @@ +#define PIDNS_TRANSLATION +#include "gettid.c" diff --git a/tests/gettid--pidns-translation.test b/tests/gettid--pidns-translation.test new file mode 100755 index 00000000..9624129e --- /dev/null +++ b/tests/gettid--pidns-translation.test @@ -0,0 +1,18 @@ +#!/bin/sh +# +# Check pidns translation of gettid's return value. +# +# Copyright (c) 2020 The strace developers. +# All rights reserved. +# +# SPDX-License-Identifier: LGPL-2.1-or-later + +. "${srcdir=.}/init.sh" + +run_prog > /dev/null +run_strace -a9 --pidns-translation -f -e trace=gettid $args > "$EXP" +parent_pid="$(tail -n 2 $LOG | head -n 1 | cut -d' ' -f1)" +init_pid="$(tail -n 1 $LOG | cut -d' ' -f1)" +# uniq: filter out extra gettid calls made by musl libc +grep -E -v "^($parent_pid|$init_pid) |unfinished|resumed" "$LOG" | uniq > "$OUT" +match_diff "$OUT" "$EXP" diff --git a/tests/gettid.c b/tests/gettid.c index d38918dd..314d9c2c 100644 --- a/tests/gettid.c +++ b/tests/gettid.c @@ -9,11 +9,17 @@ #include #include #include "scno.h" +#include "pidns.h" int main(void) { - printf("gettid() = %ld\n", syscall(__NR_gettid)); + PIDNS_TEST_INIT; + + pidns_print_leader(); + printf("gettid() = %d%s\n", (int) syscall(__NR_gettid), + pidns_pid2str(PT_TID)); + pidns_print_leader(); puts("+++ exited with 0 +++"); return 0; } diff --git a/tests/ioctl_block--pidns-translation.c b/tests/ioctl_block--pidns-translation.c new file mode 100644 index 00000000..5eed6076 --- /dev/null +++ b/tests/ioctl_block--pidns-translation.c @@ -0,0 +1,2 @@ +#define PIDNS_TRANSLATION +#include "ioctl_block.c" diff --git a/tests/ioctl_block--pidns-translation.test b/tests/ioctl_block--pidns-translation.test new file mode 100755 index 00000000..d06855f9 --- /dev/null +++ b/tests/ioctl_block--pidns-translation.test @@ -0,0 +1,22 @@ +#!/bin/sh +# +# Check pidns translation of ioctl(BLK*) syscall decoding. +# +# Copyright (c) 2020 The strace developers. +# All rights reserved. +# +# SPDX-License-Identifier: LGPL-2.1-or-later + +. "${srcdir=.}/init.sh" + +check_prog head +check_prog tail +check_prog cut +check_prog grep + +run_prog > /dev/null +run_strace --pidns-translation -f -a16 -e trace=ioctl $@ $args > "$EXP" +parent_pid="$(tail -n 2 $LOG | head -n 1 | cut -d' ' -f1)" +init_pid="$(tail -n 1 $LOG | cut -d' ' -f1)" +grep -E -v "^($parent_pid|$init_pid) |ioctl\([0123][,<]" "$LOG" > "$OUT" +match_diff "$OUT" "$EXP" diff --git a/tests/ioctl_block.c b/tests/ioctl_block.c index 0afe27f7..8a345f4e 100644 --- a/tests/ioctl_block.c +++ b/tests/ioctl_block.c @@ -9,7 +9,9 @@ */ #include "tests.h" +#include "pidns.h" #include +#include #include #include #include @@ -41,12 +43,15 @@ static struct xlat_data block_argless[] = { #define TEST_NULL_ARG(cmd) \ do { \ ioctl(-1, cmd, 0); \ + pidns_print_leader(); \ printf("ioctl(-1, %s, NULL) = -1 EBADF (%m)\n", #cmd); \ } while (0) int main(void) { + PIDNS_TEST_INIT; + TEST_NULL_ARG(BLKBSZGET); TEST_NULL_ARG(BLKBSZSET); TEST_NULL_ARG(BLKFRAGET); @@ -91,18 +96,22 @@ main(void) #endif ioctl(-1, BLKRASET, lmagic); + pidns_print_leader(); printf("ioctl(-1, BLKRASET, %lu) = -1 EBADF (%m)\n", lmagic); ioctl(-1, BLKFRASET, lmagic); + pidns_print_leader(); printf("ioctl(-1, BLKFRASET, %lu) = -1 EBADF (%m)\n", lmagic); TAIL_ALLOC_OBJECT_CONST_PTR(int, val_int); *val_int = magic; ioctl(-1, BLKROSET, val_int); + pidns_print_leader(); printf("ioctl(-1, BLKROSET, [%d]) = -1 EBADF (%m)\n", *val_int); ioctl(-1, BLKBSZSET, val_int); + pidns_print_leader(); printf("ioctl(-1, BLKBSZSET, [%d]) = -1 EBADF (%m)\n", *val_int); uint64_t *pair_int64 = tail_alloc(sizeof(*pair_int64) * 2); @@ -111,18 +120,21 @@ main(void) #ifdef BLKDISCARD ioctl(-1, BLKDISCARD, pair_int64); + pidns_print_leader(); printf("ioctl(-1, BLKDISCARD, [%" PRIu64 ", %" PRIu64 "])" " = -1 EBADF (%m)\n", pair_int64[0], pair_int64[1]); #endif #ifdef BLKSECDISCARD ioctl(-1, BLKSECDISCARD, pair_int64); + pidns_print_leader(); printf("ioctl(-1, BLKSECDISCARD, [%" PRIu64 ", %" PRIu64 "])" " = -1 EBADF (%m)\n", pair_int64[0], pair_int64[1]); #endif #ifdef BLKZEROOUT ioctl(-1, BLKZEROOUT, pair_int64); + pidns_print_leader(); printf("ioctl(-1, BLKZEROOUT, [%" PRIu64 ", %" PRIu64 "])" " = -1 EBADF (%m)\n", pair_int64[0], pair_int64[1]); #endif @@ -134,6 +146,7 @@ main(void) blkpg->data = (void *) (unsigned long) 0xcafef00dfffffeedULL; ioctl(-1, BLKPG, blkpg); + pidns_print_leader(); printf("ioctl(-1, BLKPG, {op=%s, flags=%d, datalen=%d" ", data=%#lx}) = -1 EBADF (%m)\n", "BLKPG_RESIZE_PARTITION", blkpg->flags, blkpg->datalen, @@ -149,6 +162,7 @@ main(void) blkpg->data = bp; ioctl(-1, BLKPG, blkpg); + pidns_print_leader(); printf("ioctl(-1, BLKPG, {op=%s, flags=%d, datalen=%d" ", data={start=%lld, length=%lld, pno=%d" ", devname=\"%.*s\"..., volname=\"%.*s\"...}})" @@ -162,25 +176,31 @@ main(void) #if defined BLKTRACESETUP && defined HAVE_STRUCT_BLK_USER_TRACE_SETUP TAIL_ALLOC_OBJECT_CONST_PTR(struct blk_user_trace_setup, buts); fill_memory(buts, sizeof(*buts)); + buts->pid = getpid(); ioctl(-1, BLKTRACESETUP, buts); + pidns_print_leader(); printf("ioctl(-1, BLKTRACESETUP, {act_mask=%hu, buf_size=%u, buf_nr=%u" - ", start_lba=%" PRI__u64 ", end_lba=%" PRI__u64 ", pid=%d})" + ", start_lba=%" PRI__u64 ", end_lba=%" PRI__u64 ", pid=%d%s})" " = -1 EBADF (%m)\n", buts->act_mask, buts->buf_size, buts->buf_nr, - buts->start_lba, buts->end_lba, buts->pid); + buts->start_lba, buts->end_lba, buts->pid, + pidns_pid2str(PT_TGID)); #endif unsigned int i; for (i = 0; i < ARRAY_SIZE(block_argless); ++i) { ioctl(-1, (unsigned long) block_argless[i].val, lmagic); + pidns_print_leader(); printf("ioctl(-1, %s) = -1 EBADF (%m)\n", block_argless[i].str); } ioctl(-1, _IOC(_IOC_READ, 0x12, 0xfe, 0xff), lmagic); + pidns_print_leader(); printf("ioctl(-1, %s, %#lx) = -1 EBADF (%m)\n", "_IOC(_IOC_READ, 0x12, 0xfe, 0xff)", lmagic); + pidns_print_leader(); puts("+++ exited with 0 +++"); return 0; } diff --git a/tests/ioprio--pidns-translation.c b/tests/ioprio--pidns-translation.c new file mode 100644 index 00000000..bcb49a8b --- /dev/null +++ b/tests/ioprio--pidns-translation.c @@ -0,0 +1,2 @@ +#define PIDNS_TRANSLATION +#include "ioprio.c" diff --git a/tests/ioprio.c b/tests/ioprio.c index 5e1e1194..110df063 100644 --- a/tests/ioprio.c +++ b/tests/ioprio.c @@ -9,8 +9,8 @@ */ #include "tests.h" - #include "scno.h" +#include "pidns.h" #if defined(__NR_ioprio_get) && defined(__NR_ioprio_set) @@ -30,12 +30,18 @@ enum { int main(void) { + PIDNS_TEST_INIT; + static const kernel_ulong_t bogus_which = (kernel_ulong_t) 0xdeadfacefa57beefULL; static const kernel_ulong_t bogus_who = (kernel_ulong_t) 0xbadc0dedda7a1057ULL; static const kernel_ulong_t bogus_ioprio = (kernel_ulong_t) 0xdec0ded1facefeedULL; + + const int pid = getpid(); + const int pgid = getpgid(0); + # if !XLAT_RAW static const char * const bogus_ioprio_str = "IOPRIO_PRIO_VALUE(0x7d677 /* IOPRIO_CLASS_??? */, 7917)"; @@ -46,6 +52,7 @@ main(void) rc = syscall(__NR_ioprio_get, bogus_which, bogus_who); errstr = sprintrc(rc); + pidns_print_leader(); # if XLAT_RAW printf("ioprio_get(%#x, %d) = %s\n", (int) bogus_which, (int) bogus_who, errstr); @@ -54,42 +61,52 @@ main(void) (int) bogus_which, (int) bogus_who, errstr); # endif - rc = syscall(__NR_ioprio_get, 1, 0); + rc = syscall(__NR_ioprio_get, 1, pid); errstr = sprintrc(rc); + pidns_print_leader(); + printf("ioprio_get("); # if XLAT_RAW - printf("ioprio_get(0x1, 0) = %s\n", errstr); + printf("0x1, "); +# elif XLAT_VERBOSE + printf("0x1 /* IOPRIO_WHO_PROCESS */, "); # else /* XLAT_ABBREV */ -# if XLAT_VERBOSE - printf("ioprio_get(0x1 /* IOPRIO_WHO_PROCESS */, 0) = %s", errstr); -# else - printf("ioprio_get(IOPRIO_WHO_PROCESS, 0) = %s", errstr); -# endif + printf("IOPRIO_WHO_PROCESS, "); +# endif + printf("%d%s) = %s", pid, pidns_pid2str(PT_TGID), errstr); +# if !XLAT_RAW if (rc >= 0) { printf(" (IOPRIO_PRIO_VALUE("); printxval(ioprio_class, (unsigned int) rc >> 13, "IOPRIO_CLASS_???"); printf(", %u))", (unsigned int) rc & 0x1fff); } - puts(""); # endif + puts(""); - rc = syscall(__NR_ioprio_set, 2, 0, 8191); + rc = syscall(__NR_ioprio_set, 2, pgid, 8191); errstr = sprintrc(rc); + pidns_print_leader(); + printf("ioprio_set("); # if XLAT_RAW - printf("ioprio_set(%#x, 0, 8191) = %s\n", 2, errstr); + printf("%#x", 2); # elif XLAT_VERBOSE - printf("ioprio_set(%#x /* IOPRIO_WHO_PGRP */, 0, 8191" - " /* IOPRIO_PRIO_VALUE(0 /* IOPRIO_CLASS_NONE */, 8191) */)" - " = %s\n", - 2, errstr); + printf("%#x /* IOPRIO_WHO_PGRP */", 2); # else /* XLAT_ABBREV */ - printf("ioprio_set(IOPRIO_WHO_PGRP, 0" - ", IOPRIO_PRIO_VALUE(IOPRIO_CLASS_NONE, 8191)) = %s\n", - errstr); + printf("IOPRIO_WHO_PGRP"); +# endif + printf(", %d%s", pgid, pidns_pid2str(PT_PGID)); +# if XLAT_RAW + printf(", 8191)"); +# elif XLAT_VERBOSE + printf(", 8191 /* IOPRIO_PRIO_VALUE(0 /* IOPRIO_CLASS_NONE */, 8191) */)"); +# else /* XLAT_ABBREV */ + printf(", IOPRIO_PRIO_VALUE(IOPRIO_CLASS_NONE, 8191))"); # endif + printf(" = %s\n", errstr); rc = syscall(__NR_ioprio_set, bogus_which, bogus_who, bogus_ioprio); errstr = sprintrc(rc); + pidns_print_leader(); # if XLAT_RAW printf("ioprio_set(%#x, %d, %d) = %s\n", (int) bogus_which, (int) bogus_who, (int) bogus_ioprio, @@ -104,6 +121,7 @@ main(void) errstr); # endif + pidns_print_leader(); puts("+++ exited with 0 +++"); return 0; diff --git a/tests/kcmp-y--pidns-translation.c b/tests/kcmp-y--pidns-translation.c new file mode 100644 index 00000000..f54d94cc --- /dev/null +++ b/tests/kcmp-y--pidns-translation.c @@ -0,0 +1,2 @@ +#define PIDNS_TRANSLATION +#include "kcmp-y.c" diff --git a/tests/kcmp.c b/tests/kcmp.c index dc5ba9a4..ce705ad0 100644 --- a/tests/kcmp.c +++ b/tests/kcmp.c @@ -9,8 +9,8 @@ */ #include "tests.h" - #include "scno.h" +#include "pidns.h" #ifdef __NR_kcmp @@ -101,7 +101,11 @@ do_kcmp(kernel_ulong_t pid1, kernel_ulong_t pid2, kernel_ulong_t type, rc = syscall(__NR_kcmp, pid1, pid2, type, idx1, idx2); errstr = sprintrc(rc); - printf("kcmp(%d, %d, ", (int) pid1, (int) pid2); + const char *pid_str = pidns_pid2str(PT_TGID); + pidns_print_leader(); + printf("kcmp(%d%s, %d%s, ", + (int) pid1, (int) pid1 == getpid() ? pid_str : "", + (int) pid2, (int) pid2 == getpid() ? pid_str : ""); if (type_str) printf("%s", type_str); @@ -146,6 +150,8 @@ do_kcmp(kernel_ulong_t pid1, kernel_ulong_t pid2, kernel_ulong_t type, int main(void) { + PIDNS_TEST_INIT; + static const kernel_ulong_t bogus_pid1 = (kernel_ulong_t) 0xdeadca75face1057ULL; static const kernel_ulong_t bogus_pid2 = @@ -221,6 +227,7 @@ main(void) (uintptr_t) slot, 1); } + pidns_print_leader(); puts("+++ exited with 0 +++"); return 0; diff --git a/tests/kill--pidns-translation.c b/tests/kill--pidns-translation.c new file mode 100644 index 00000000..4736ca14 --- /dev/null +++ b/tests/kill--pidns-translation.c @@ -0,0 +1,2 @@ +#define PIDNS_TRANSLATION +#include "kill.c" diff --git a/tests/kill.c b/tests/kill.c index f7d9341e..17de35da 100644 --- a/tests/kill.c +++ b/tests/kill.c @@ -11,6 +11,7 @@ #include "tests.h" #include "scno.h" +#include "pidns.h" #ifdef __NR_kill @@ -26,6 +27,8 @@ handler(int sig) int main(void) { + PIDNS_TEST_INIT; + const struct sigaction act = { .sa_handler = handler }; if (sigaction(SIGALRM, &act, NULL)) perror_msg_and_fail("sigaction"); @@ -37,18 +40,23 @@ main(void) perror_msg_and_fail("sigprocmask"); const int pid = getpid(); + const char *pid_str = pidns_pid2str(PT_TGID); long rc = syscall(__NR_kill, pid, (long) 0xdefaced00000000ULL | SIGALRM); - printf("kill(%d, SIGALRM) = %ld\n", pid, rc); + pidns_print_leader(); + printf("kill(%d%s, SIGALRM) = %ld\n", pid, pid_str, rc); const long big_pid = (long) 0xfacefeedbadc0dedULL; const long big_sig = (long) 0xdeadbeefcafef00dULL; rc = syscall(__NR_kill, big_pid, big_sig); + pidns_print_leader(); printf("kill(%d, %d) = %ld %s (%m)\n", (int) big_pid, (int) big_sig, rc, errno2name()); rc = syscall(__NR_kill, (long) 0xdefaced00000000ULL | pid, 0); - printf("kill(%d, 0) = %ld\n", pid, rc); + pidns_print_leader(); + printf("kill(%d%s, 0) = %ld\n", pid, pid_str, rc); + pidns_print_leader(); puts("+++ exited with 0 +++"); return 0; } diff --git a/tests/migrate_pages--pidns-translation.c b/tests/migrate_pages--pidns-translation.c new file mode 100644 index 00000000..ec34938d --- /dev/null +++ b/tests/migrate_pages--pidns-translation.c @@ -0,0 +1,2 @@ +#define PIDNS_TRANSLATION +#include "migrate_pages.c" diff --git a/tests/migrate_pages.c b/tests/migrate_pages.c index 2dfba49c..390b490b 100644 --- a/tests/migrate_pages.c +++ b/tests/migrate_pages.c @@ -10,6 +10,7 @@ #include "tests.h" #include "scno.h" +#include "pidns.h" #ifdef __NR_migrate_pages @@ -19,11 +20,21 @@ int main(void) { - const long pid = (long) 0xfacefeedffffffffULL; + PIDNS_TEST_INIT; + + const long pid = (long) 0xfacefeed00000000ULL | getpid(); long rc = syscall(__NR_migrate_pages, pid, 0, 0, 0); - printf("migrate_pages(%d, 0, NULL, NULL) = %ld %s (%m)\n", - (int) pid, rc, errno2name()); + pidns_print_leader(); + printf("migrate_pages(%d%s, 0, NULL, NULL) = %ld", + (int) pid, pidns_pid2str(PT_TGID), rc); + + if (rc < 0) + printf(" %s (%m)\n", errno2name()); + else + printf("\n"); + + pidns_print_leader(); puts("+++ exited with 0 +++"); return 0; } diff --git a/tests/move_pages--pidns-translation.c b/tests/move_pages--pidns-translation.c new file mode 100644 index 00000000..8498e399 --- /dev/null +++ b/tests/move_pages--pidns-translation.c @@ -0,0 +1,2 @@ +#define PIDNS_TRANSLATION +#include "move_pages.c" diff --git a/tests/move_pages.c b/tests/move_pages.c index e00fd1ac..56843158 100644 --- a/tests/move_pages.c +++ b/tests/move_pages.c @@ -10,6 +10,7 @@ #include "tests.h" #include "scno.h" +#include "pidns.h" #ifdef __NR_move_pages @@ -122,15 +123,20 @@ print_status_array(const int *const status, const unsigned long count) } static void -print_stat_pages(const unsigned long pid, const unsigned long count, - const void **const pages, int *const status) +print_stat_pages(const unsigned long pid, + const char *pid_str, + const unsigned long count, + const void **const pages, + int *const status) { const unsigned long flags = (unsigned long) 0xfacefeed00000002ULL; long rc = syscall(__NR_move_pages, pid, count, pages, NULL, status, flags); const char *errstr = sprintrc(rc); - printf("move_pages(%d, %lu, ", (int) pid, count); + pidns_print_leader(); + printf("move_pages(%d%s, %lu, ", (int) pid, pid_str, + count); print_page_array(pages, count, 0); printf(", NULL, "); if (rc) { @@ -152,6 +158,7 @@ print_stat_pages(const unsigned long pid, const unsigned long count, static void print_move_pages(const unsigned long pid, + const char *pid_str, unsigned long count, const unsigned int offset, const void **const pages, @@ -164,7 +171,9 @@ print_move_pages(const unsigned long pid, long rc = syscall(__NR_move_pages, pid, count, pages, nodes, status, flags); const char *errstr = sprintrc(rc); - printf("move_pages(%d, %lu, ", (int) pid, count); + pidns_print_leader(); + printf("move_pages(%d%s, %lu, ", (int) pid, pid_str, + count); print_page_array(pages, count, offset); printf(", "); print_node_array(nodes, count, offset); @@ -185,8 +194,11 @@ print_move_pages(const unsigned long pid, int main(void) { + PIDNS_TEST_INIT; + const unsigned long pid = (unsigned long) 0xfacefeed00000000ULL | getpid(); + const char *pid_str = pidns_pid2str(PT_TGID); unsigned long count = 1; const unsigned page_size = get_page_size(); const void *const page = tail_alloc(page_size); @@ -195,40 +207,41 @@ main(void) TAIL_ALLOC_OBJECT_VAR_PTR(int, nodes); TAIL_ALLOC_OBJECT_VAR_PTR(int, status); - print_stat_pages(pid, 0, pages, status); - print_move_pages(pid, 0, 0, pages, nodes, status); - print_move_pages(pid, 0, 1, pages + 1, nodes + 1, status + 1); + print_stat_pages(pid, pid_str, 0, pages, status); + print_move_pages(pid, pid_str, 0, 0, pages, nodes, status); + print_move_pages(pid, pid_str, 0, 1, pages + 1, nodes + 1, status + 1); *pages = page; - print_stat_pages(pid, count, pages, status); + print_stat_pages(pid, pid_str, count, pages, status); *nodes = 0xdeadbee1; - print_move_pages(pid, count, 0, pages, nodes, status); - print_move_pages(pid, count, 1, pages, nodes, status); + print_move_pages(pid, pid_str, count, 0, pages, nodes, status); + print_move_pages(pid, pid_str, count, 1, pages, nodes, status); ++count; --status; *(--pages) = efault; - print_stat_pages(pid, count, pages, status); + print_stat_pages(pid, pid_str, count, pages, status); *(--nodes) = 0xdeadbee2; - print_move_pages(pid, count, 0, pages, nodes, status); - print_move_pages(pid, count, 1, pages, nodes, status); + print_move_pages(pid, pid_str, count, 0, pages, nodes, status); + print_move_pages(pid, pid_str, count, 1, pages, nodes, status); ++count; --status; *(--pages) = nodes; - print_stat_pages(pid, count, pages, status); + print_stat_pages(pid, pid_str, count, pages, status); *(--nodes) = 0xdeadbee3; - print_move_pages(pid, count, 0, pages, nodes, status); - print_move_pages(pid, count, 1, pages, nodes, status); + print_move_pages(pid, pid_str, count, 0, pages, nodes, status); + print_move_pages(pid, pid_str, count, 1, pages, nodes, status); ++count; --status; *(--pages) = status; - print_stat_pages(pid, count, pages, status); + print_stat_pages(pid, pid_str, count, pages, status); *(--nodes) = 0xdeadbee4; - print_move_pages(pid, count, 0, pages, nodes, status); - print_move_pages(pid, count, 1, pages, nodes, status); + print_move_pages(pid, pid_str, count, 0, pages, nodes, status); + print_move_pages(pid, pid_str, count, 1, pages, nodes, status); + pidns_print_leader(); puts("+++ exited with 0 +++"); return 0; } diff --git a/tests/net-sockaddr--pidns-translation.c b/tests/net-sockaddr--pidns-translation.c new file mode 100644 index 00000000..ff432bf4 --- /dev/null +++ b/tests/net-sockaddr--pidns-translation.c @@ -0,0 +1,2 @@ +#define PIDNS_TRANSLATION +#include "net-sockaddr.c" diff --git a/tests/net-sockaddr.c b/tests/net-sockaddr.c index 4fc9da6e..c7e9bde7 100644 --- a/tests/net-sockaddr.c +++ b/tests/net-sockaddr.c @@ -9,6 +9,7 @@ */ #include "tests.h" +#include "pidns.h" #include #include #include @@ -40,18 +41,21 @@ check_un(void) memset(un->sun_path, '0', sizeof(un->sun_path)); unsigned int len = sizeof(*un); int ret = connect(-1, (void *) un, len); + pidns_print_leader(); printf("connect(-1, {sa_family=AF_UNIX, sun_path=\"%.*u\"}" ", %u) = %d EBADF (%m)\n", (int) sizeof(un->sun_path), 0, len, ret); un->sun_path[1] = 0; ret = connect(-1, (void *) un, len); + pidns_print_leader(); printf("connect(-1, {sa_family=AF_UNIX, sun_path=\"%u\"}, %u)" " = %d EBADF (%m)\n", 0, len, ret); un->sun_path[0] = 0; un->sun_path[2] = 1; ret = connect(-1, (void *) un, len); + pidns_print_leader(); printf("connect(-1, {sa_family=AF_UNIX, sun_path=@\"\\0\\001%.*u\"}" ", %u) = %d EBADF (%m)\n", (int) sizeof(un->sun_path) - 3, 0, len, ret); @@ -61,12 +65,14 @@ check_un(void) memset(un->sun_path, '0', sizeof(un->sun_path)); len = sizeof(*un) + 2; ret = connect(-1, (void *) un, len); + pidns_print_leader(); printf("connect(-1, {sa_family=AF_UNIX, sun_path=\"%.*u\"}" ", %u) = %d EBADF (%m)\n", (int) sizeof(un->sun_path), 0, len, ret); un->sun_path[0] = 0; ret = connect(-1, (void *) un, len); + pidns_print_leader(); printf("connect(-1, {sa_family=AF_UNIX, sun_path=@\"%.*u\"}" ", %u) = %d EBADF (%m)\n", (int) sizeof(un->sun_path) - 1, 0, len, ret); @@ -75,18 +81,21 @@ check_un(void) un->sun_family = AF_UNIX; len = sizeof(*un) - 2; ret = connect(-1, (void *) un, len); + pidns_print_leader(); printf("connect(-1, {sa_family=AF_UNIX, sun_path=\"%.*u\"}" ", %u) = %d EBADF (%m)\n", (int) sizeof(un->sun_path) - 2, 0, len, ret); un->sun_path[0] = 0; ret = connect(-1, (void *) un, len); + pidns_print_leader(); printf("connect(-1, {sa_family=AF_UNIX, sun_path=@\"%.*u\"}" ", %u) = %d EBADF (%m)\n", (int) sizeof(un->sun_path) - 3, 0, len, ret); len = sizeof(*un); ret = connect(-1, (void *) un, len); + pidns_print_leader(); printf("connect(-1, %p, %u) = %d EBADF (%m)\n", un, len, ret); un = tail_alloc(sizeof(struct sockaddr_storage)); @@ -94,12 +103,14 @@ check_un(void) memset(un->sun_path, '0', sizeof(un->sun_path)); len = sizeof(struct sockaddr_storage) + 1; ret = connect(-1, (void *) un, len); + pidns_print_leader(); printf("connect(-1, {sa_family=AF_UNIX, sun_path=\"%.*u\"}" ", %u) = %d EBADF (%m)\n", (int) sizeof(un->sun_path), 0, len, ret); un->sun_path[0] = 0; ret = connect(-1, (void *) un, len); + pidns_print_leader(); printf("connect(-1, {sa_family=AF_UNIX, sun_path=@\"%.*u\"}" ", %u) = %d EBADF (%m)\n", (int) sizeof(un->sun_path) - 1, 0, len, ret); @@ -117,6 +128,7 @@ check_in(void) in->sin_addr.s_addr = inet_addr(h_addr); unsigned int len = sizeof(*in); int ret = connect(-1, (void *) in, len); + pidns_print_leader(); printf("connect(-1, {sa_family=AF_INET, sin_port=htons(%hu)" ", sin_addr=inet_addr(\"%s\")}, %u) = %d EBADF (%m)\n", h_port, h_addr, len, ret); @@ -127,6 +139,7 @@ check_in(void) in->sin_addr.s_addr = inet_addr(h_addr); len = sizeof(*in) + 4; ret = connect(-1, (void *) in, len); + pidns_print_leader(); printf("connect(-1, {sa_family=AF_INET, sin_port=htons(%hu)" ", sin_addr=inet_addr(\"%s\")}, %u) = %d EBADF (%m)\n", h_port, h_addr, len, ret); @@ -137,6 +150,7 @@ check_in(void) in->sin_addr.s_addr = 0; len = sizeof(*in) - 4; ret = connect(-1, (void *) in, len); + pidns_print_leader(); printf("connect(-1, {sa_family=AF_INET, sa_data=\"%s\"}, %u)" " = %d EBADF (%m)\n", "\\0\\0\\0\\0\\0\\0\\377\\377\\377\\377", @@ -144,6 +158,7 @@ check_in(void) len = sizeof(*in); ret = connect(-1, (void *) in, len); + pidns_print_leader(); printf("connect(-1, %p, %u) = %d EBADF (%m)\n", in, len, ret); } @@ -155,6 +170,7 @@ check_in6_linklocal(struct sockaddr_in6 *const in6, const char *const h_addr) in6->sin6_scope_id = 0xfacefeed; unsigned int len = sizeof(*in6); int ret = connect(-1, (void *) in6, len); + pidns_print_leader(); printf("connect(-1, {sa_family=AF_INET6, sin6_port=htons(%hu)" ", sin6_flowinfo=htonl(%u)" ", inet_pton(AF_INET6, \"%s\", &sin6_addr)" @@ -166,7 +182,8 @@ check_in6_linklocal(struct sockaddr_in6 *const in6, const char *const h_addr) in6->sin6_scope_id = ifindex_lo(); if (in6->sin6_scope_id) { ret = connect(-1, (void *) in6, len); - printf("connect(-1, {sa_family=AF_INET6, sin6_port=htons(%hu)" + pidns_print_leader(); + printf("connect(-1, {sa_family=AF_INET6, sin6_port=htons(%hu)" ", sin6_flowinfo=htonl(%u)" ", inet_pton(AF_INET6, \"%s\", &sin6_addr)" ", sin6_scope_id=%s}, %u)" @@ -191,6 +208,7 @@ check_in6(void) in6->sin6_scope_id = 0xfacefeed; unsigned int len = sizeof(*in6); int ret = connect(-1, (void *) in6, len); + pidns_print_leader(); printf("connect(-1, {sa_family=AF_INET6, sin6_port=htons(%hu)" ", sin6_flowinfo=htonl(%u)" ", inet_pton(AF_INET6, \"%s\", &sin6_addr)" @@ -209,6 +227,7 @@ check_in6(void) in6->sin6_scope_id = 0xfacefeed; len = sizeof(*in6) + 4; ret = connect(-1, (void *) in6, len); + pidns_print_leader(); printf("connect(-1, {sa_family=AF_INET6, sin6_port=htons(%hu)" ", sin6_flowinfo=htonl(%u)" ", inet_pton(AF_INET6, \"%s\", &sin6_addr)" @@ -223,6 +242,7 @@ check_in6(void) inet_pton(AF_INET6, h_addr, &in6->sin6_addr); len = sizeof(*in6) - sizeof(in6->sin6_scope_id); ret = connect(-1, (void *) in6, len); + pidns_print_leader(); printf("connect(-1, {sa_family=AF_INET6, sin6_port=htons(%hu)" ", sin6_flowinfo=htonl(%u)" ", inet_pton(AF_INET6, \"%s\", &sin6_addr)}, %u)" @@ -236,6 +256,7 @@ check_in6(void) memset(&in6->sin6_addr, '0', sizeof(in6->sin6_addr) - 4); len = sizeof(*in6) - sizeof(in6->sin6_scope_id) - 4; ret = connect(-1, (void *) in6, len); + pidns_print_leader(); printf("connect(-1, {sa_family=AF_INET6" ", sa_data=\"\\0\\0\\0\\0\\0\\000%.*u\"}, %u)" " = %d EBADF (%m)\n", @@ -244,6 +265,7 @@ check_in6(void) len = sizeof(*in6) - sizeof(in6->sin6_scope_id); ret = connect(-1, (void *) in6, len); + pidns_print_leader(); printf("connect(-1, %p, %u) = %d EBADF (%m)\n", in6, len, ret); } @@ -262,6 +284,7 @@ check_ipx(void) void *ipx = tail_memdup(&c_ipx, sizeof(c_ipx)); unsigned int len = sizeof(c_ipx); int ret = connect(-1, ipx, len); + pidns_print_leader(); printf("connect(-1, {sa_family=AF_IPX, sipx_port=htons(%u)" ", sipx_network=htonl(%#x)" ", sipx_node=[%#02x, %#02x, %#02x, %#02x, %#02x, %#02x]" @@ -316,18 +339,21 @@ check_ax25(void) fill_memory(sax, size); sax->fsa_ax25.sax25_family = AF_AX25; rc = connect(-1, sax_void, sizeof(struct sockaddr_ax25) - 1); + pidns_print_leader(); printf("connect(-1, {sa_family=AF_AX25, sa_data=\"\\202\\203\\204\\205" "\\206\\207\\210\\211\\212\\213\\214\\215\\216\"}, %zu) = %s\n", sizeof(struct sockaddr_ax25) - 1, sprintrc(rc)); memcpy(sax, &ax25, sizeof(ax25)); rc = connect(-1, sax_void, sizeof(struct sockaddr_ax25)); + pidns_print_leader(); printf("connect(-1, {sa_family=AF_AX25, fsa_ax25={sax25_call=VALID-13" ", sax25_ndigis=8}, fsa_digipeater=[/* ??? */]}, %zu) = %s\n", sizeof(struct sockaddr_ax25), sprintrc(rc)); sax->fsa_ax25.sax25_ndigis = 0; rc = connect(-1, sax_void, sizeof(struct sockaddr_ax25)); + pidns_print_leader(); printf("connect(-1, {sa_family=AF_AX25, sax25_call=VALID-13" ", sax25_ndigis=0}, %zu) = %s\n", sizeof(struct sockaddr_ax25), sprintrc(rc)); @@ -335,6 +361,7 @@ check_ax25(void) sax->fsa_ax25.sax25_ndigis = 8; size = sizeof(struct sockaddr_ax25) + sizeof(ax25_address) * 3 + 1; rc = connect(-1, sax_void, size); + pidns_print_leader(); printf("connect(-1, {sa_family=AF_AX25, fsa_ax25={sax25_call=VALID-13" ", sax25_ndigis=8}, fsa_digipeater" "=[{ax25_call=\"\\xa6\\xa0\\x82\\x40\\x86\\x8a\\x00\"" @@ -348,6 +375,7 @@ check_ax25(void) sax->fsa_digipeater[2].ax25_call[6] = 0x4; size = sizeof(struct sockaddr_ax25) + sizeof(ax25_address) * 4; rc = connect(-1, sax_void, size); + pidns_print_leader(); printf("connect(-1, {sa_family=AF_AX25, fsa_ax25={sax25_call=VALID-13" ", sax25_ndigis=8}, fsa_digipeater" "=[{ax25_call=\"\\xa6\\xa0\\x82\\x40\\x86\\x8a\\x00\"" @@ -365,6 +393,7 @@ check_ax25(void) for (size_t i = 0; i < 3; i++) { size = sizeof(ax25) + sizeof(ax25_address) * (i / 2); rc = connect(-1, sax_void, size); + pidns_print_leader(); printf("connect(-1, {sa_family=AF_AX25" ", fsa_ax25={sax25_call=VALID-13, sax25_ndigis=%d}" ", fsa_digipeater=[VALID2-7, OK-15, %s /* FINE-2 */" @@ -427,12 +456,14 @@ check_x25(void) long rc; rc = connect(-1, x25_void, sizeof(c_x25) - 1); + pidns_print_leader(); printf("connect(-1, {sa_family=AF_X25" ", sa_data=\"0123456789abcde\"}, %zu) = %s\n", sizeof(c_x25) - 1, sprintrc(rc)); for (size_t i = 0; i < 2; i++) { rc = connect(-1, x25_void, sizeof(c_x25) + i); + pidns_print_leader(); printf("connect(-1, {sa_family=AF_X25" ", sx25_addr={x25_addr=\"0123456789abcde\"...}" "}, %zu) = %s\n", @@ -442,6 +473,7 @@ check_x25(void) struct sockaddr_x25 *const x25 = x25_void; x25->sx25_addr.x25_addr[10] = '\0'; rc = connect(-1, x25_void, sizeof(c_x25)); + pidns_print_leader(); printf("connect(-1, {sa_family=AF_X25" ", sx25_addr={x25_addr=\"0123456789\"}" "}, %zu) = %s\n", @@ -457,19 +489,21 @@ check_nl(void) nl->nl_groups = 0xfacefeed; unsigned int len = sizeof(*nl); int ret = connect(-1, (void *) nl, len); + pidns_print_leader(); printf("connect(-1, {sa_family=AF_NETLINK, nl_pid=%d" ", nl_groups=%#08x}, %u) = %d EBADF (%m)\n", nl->nl_pid, nl->nl_groups, len, ret); nl = ((void *) nl) - 4; nl->nl_family = AF_NETLINK; - nl->nl_pid = 1234567890; + nl->nl_pid = getpid(); nl->nl_groups = 0xfacefeed; len = sizeof(*nl) + 4; ret = connect(-1, (void *) nl, len); - printf("connect(-1, {sa_family=AF_NETLINK, nl_pid=%d" + pidns_print_leader(); + printf("connect(-1, {sa_family=AF_NETLINK, nl_pid=%d%s" ", nl_groups=%#08x}, %u) = %d EBADF (%m)\n", - nl->nl_pid, nl->nl_groups, len, ret); + nl->nl_pid, pidns_pid2str(PT_TGID), nl->nl_groups, len, ret); } static void @@ -487,6 +521,7 @@ check_ll(void) void *ll = tail_memdup(&c_ll, sizeof(c_ll)); unsigned int len = sizeof(c_ll); int ret = connect(-1, ll, len); + pidns_print_leader(); printf("connect(-1, {sa_family=AF_PACKET" ", sll_protocol=htons(ETH_P_ALL)" ", sll_ifindex=%u, sll_hatype=ARPHRD_ETHER" @@ -502,6 +537,7 @@ check_ll(void) ((struct sockaddr_ll *) ll)->sll_halen++; ret = connect(-1, ll, len); + pidns_print_leader(); printf("connect(-1, {sa_family=AF_PACKET" ", sll_protocol=htons(ETH_P_ALL)" ", sll_ifindex=%u, sll_hatype=ARPHRD_ETHER" @@ -517,6 +553,7 @@ check_ll(void) ((struct sockaddr_ll *) ll)->sll_halen = 0; ret = connect(-1, ll, len); + pidns_print_leader(); printf("connect(-1, {sa_family=AF_PACKET" ", sll_protocol=htons(ETH_P_ALL)" ", sll_ifindex=%u, sll_hatype=ARPHRD_ETHER" @@ -526,6 +563,7 @@ check_ll(void) ((struct sockaddr_ll *) ll)->sll_ifindex = ifindex_lo(); if (((struct sockaddr_ll *) ll)->sll_ifindex) { ret = connect(-1, ll, len); + pidns_print_leader(); printf("connect(-1, {sa_family=AF_PACKET" ", sll_protocol=htons(ETH_P_ALL)" ", sll_ifindex=%s" @@ -549,11 +587,13 @@ check_hci(void) unsigned int len = sizeof(*hci); int ret = connect(-1, (void *) hci, 4); + pidns_print_leader(); printf("connect(-1, {sa_family=AF_BLUETOOTH, hci_dev=htobs(%hu)" "}, 4) = %d EBADF (%m)\n", h_port, ret); ret = connect(-1, (void *) hci, len); + pidns_print_leader(); printf("connect(-1, {sa_family=AF_BLUETOOTH, hci_dev=htobs(%hu)" # ifdef HAVE_STRUCT_SOCKADDR_HCI_HCI_CHANNEL ", hci_channel=HCI_CHANNEL_RAW" @@ -572,6 +612,7 @@ check_sco(void) void *sco = tail_memdup(&c_sco, sizeof(c_sco)); unsigned int len = sizeof(c_sco); int ret = connect(-1, sco, len); + pidns_print_leader(); printf("connect(-1, {sa_family=AF_BLUETOOTH" ", sco_bdaddr=%02x:%02x:%02x:%02x:%02x:%02x" "}, %u) = %d EBADF (%m)\n", @@ -592,6 +633,7 @@ check_rc(void) void *rc = tail_memdup(&c_rc, sizeof(c_rc)); unsigned int len = sizeof(c_rc); int ret = connect(-1, rc, len); + pidns_print_leader(); printf("connect(-1, {sa_family=AF_BLUETOOTH" ", rc_bdaddr=%02x:%02x:%02x:%02x:%02x:%02x" ", rc_channel=%u}, %u) = %d EBADF (%m)\n", @@ -619,6 +661,7 @@ check_l2(void) unsigned int len = sizeof(c_l2); int ret = connect(-1, l2, len); + pidns_print_leader(); printf("connect(-1, {sa_family=AF_BLUETOOTH" ", l2_psm=htobs(L2CAP_PSM_DYN_START + %hu)" ", l2_bdaddr=%02x:%02x:%02x:%02x:%02x:%02x" @@ -640,6 +683,7 @@ check_l2(void) # endif memcpy(l2, &c_l2, sizeof(c_l2)); ret = connect(-1, l2, len); + pidns_print_leader(); printf("connect(-1, {sa_family=AF_BLUETOOTH" ", l2_psm=htobs(L2CAP_PSM_SDP)" ", l2_bdaddr=%02x:%02x:%02x:%02x:%02x:%02x" @@ -660,6 +704,7 @@ check_l2(void) # endif memcpy(l2, &c_l2, sizeof(c_l2)); ret = connect(-1, l2, len); + pidns_print_leader(); printf("connect(-1, {sa_family=AF_BLUETOOTH" ", l2_psm=htobs(0xbad /* L2CAP_PSM_??? */)" ", l2_bdaddr=%02x:%02x:%02x:%02x:%02x:%02x" @@ -677,6 +722,7 @@ check_l2(void) c_l2.l2_cid = htobs(0xffff); memcpy(l2, &c_l2, 12); ret = connect(-1, l2, 12); + pidns_print_leader(); printf("connect(-1, {sa_family=AF_BLUETOOTH" ", l2_psm=htobs(L2CAP_PSM_AUTO_END)" ", l2_bdaddr=%02x:%02x:%02x:%02x:%02x:%02x" @@ -700,6 +746,7 @@ check_raw(void) u.sa->sa_family = 0xff; unsigned int len = sizeof(*u.st) + 8; int ret = connect(-1, (void *) u.st, len); + pidns_print_leader(); printf("connect(-1, {sa_family=%#x /* AF_??? */, sa_data=\"%.*u\"}" ", %u) = %d EBADF (%m)\n", u.sa->sa_family, (int) (sizeof(*u.st) - sizeof(u.sa->sa_family)), 0, len, ret); @@ -707,11 +754,13 @@ check_raw(void) u.sa->sa_family = 0; len = sizeof(u.sa->sa_family) + 1; ret = connect(-1, (void *) u.st, len); + pidns_print_leader(); printf("connect(-1, {sa_family=AF_UNSPEC, sa_data=\"0\"}, %u)" " = %d EBADF (%m)\n", len, ret); u.sa->sa_family = AF_BLUETOOTH; ret = connect(-1, (void *) u.st, len); + pidns_print_leader(); printf("connect(-1, {sa_family=AF_BLUETOOTH, sa_data=\"0\"}, %u)" " = %d EBADF (%m)\n", len, ret); } @@ -719,6 +768,8 @@ check_raw(void) int main(void) { + PIDNS_TEST_INIT; + check_un(); check_in(); check_in6(); @@ -735,6 +786,7 @@ main(void) #endif check_raw(); + pidns_print_leader(); puts("+++ exited with 0 +++"); return 0; } diff --git a/tests/netlink_audit--pidns-translation.c b/tests/netlink_audit--pidns-translation.c new file mode 100644 index 00000000..e08f9168 --- /dev/null +++ b/tests/netlink_audit--pidns-translation.c @@ -0,0 +1,2 @@ +#define PIDNS_TRANSLATION +#include "netlink_audit.c" diff --git a/tests/netlink_audit--pidns-translation.test b/tests/netlink_audit--pidns-translation.test new file mode 100755 index 00000000..1a39eadd --- /dev/null +++ b/tests/netlink_audit--pidns-translation.test @@ -0,0 +1,13 @@ +#!/bin/sh +# +# Check pidns translation of NETLINK_SOCK_DIAG protocol decoding +# +# Copyright (c) 2020 The strace developers. +# All rights reserved. +# +# SPDX-License-Identifier: LGPL-2.1-or-later + +. "${srcdir=.}/init.sh" + +run_prog ../netlink_netlink_diag +test_pidns -e trace=sendto "$@" diff --git a/tests/netlink_audit.c b/tests/netlink_audit.c index eba609a1..5dfcd786 100644 --- a/tests/netlink_audit.c +++ b/tests/netlink_audit.c @@ -7,6 +7,7 @@ */ #include "tests.h" +#include "pidns.h" #include #include #include @@ -17,18 +18,23 @@ static void test_nlmsg_type(const int fd) { + PIDNS_TEST_INIT; + long rc; struct nlmsghdr nlh = { .nlmsg_len = sizeof(nlh), .nlmsg_type = AUDIT_GET, .nlmsg_flags = NLM_F_REQUEST, + .nlmsg_pid = getpid(), }; rc = sendto(fd, &nlh, sizeof(nlh), MSG_DONTWAIT, NULL, 0); + pidns_print_leader(); printf("sendto(%d, {len=%u, type=AUDIT_GET" - ", flags=NLM_F_REQUEST, seq=0, pid=0}" + ", flags=NLM_F_REQUEST, seq=0, pid=%d%s}" ", %u, MSG_DONTWAIT, NULL, 0) = %s\n", - fd, nlh.nlmsg_len, (unsigned) sizeof(nlh), sprintrc(rc)); + fd, nlh.nlmsg_len, nlh.nlmsg_pid, pidns_pid2str(PT_TGID), + (unsigned) sizeof(nlh), sprintrc(rc)); } int main(void) @@ -39,6 +45,7 @@ int main(void) test_nlmsg_type(fd); + pidns_print_leader(); printf("+++ exited with 0 +++\n"); return 0; diff --git a/tests/pidfd_open--pidns-translation.c b/tests/pidfd_open--pidns-translation.c new file mode 100644 index 00000000..c38e37a8 --- /dev/null +++ b/tests/pidfd_open--pidns-translation.c @@ -0,0 +1,2 @@ +#define PIDNS_TRANSLATION +#include "pidfd_open.c" diff --git a/tests/pidfd_open.c b/tests/pidfd_open.c index 5860adde..e5d74a91 100644 --- a/tests/pidfd_open.c +++ b/tests/pidfd_open.c @@ -10,6 +10,7 @@ #include "tests.h" #include "scno.h" +#include "pidns.h" #ifdef __NR_pidfd_open @@ -37,6 +38,8 @@ k_pidfd_open(const unsigned int pid, const unsigned int flags) int main(void) { + PIDNS_TEST_INIT; + # if defined PATH_TRACING || defined PRINT_PATHS skip_if_unavailable("/proc/self/fd/"); # endif @@ -50,16 +53,19 @@ main(void) k_pidfd_open(0, 0); # ifndef PATH_TRACING + pidns_print_leader(); printf("pidfd_open(0, 0) = %s\n", errstr); # endif k_pidfd_open(-1U, 0); # ifndef PATH_TRACING + pidns_print_leader(); printf("pidfd_open(-1, 0) = %s\n", errstr); # endif k_pidfd_open(0, -1U); # ifndef PATH_TRACING + pidns_print_leader(); printf("pidfd_open(0, %#x) = %s\n", -1U, errstr); # endif @@ -68,7 +74,10 @@ main(void) k_pidfd_open(pid, flags); # ifndef PATH_TRACING - printf("pidfd_open(%d, %#x) = %s\n", pid, flags, errstr); + const char *pid_str = pidns_pid2str(PT_TGID); + pidns_print_leader(); + printf("pidfd_open(%d%s, %#x) = %s\n", + pid, pid_str, flags, errstr); # endif # ifdef PRINT_PATHS @@ -80,17 +89,19 @@ main(void) # endif # ifndef PATH_TRACING - printf("pidfd_open(%d, 0) = " + pidns_print_leader(); + printf("pidfd_open(%d%s, 0) = " # if defined PRINT_PIDFD - "%ld\n", pid, rc, pid + "%ld\n", pid, pid_str, rc, pid # elif defined PRINT_PATHS - "%ld\n", pid, rc + "%ld\n", pid, pid_str, rc # else - "%s\n", pid, errstr + "%s\n", pid, pid_str, errstr # endif ); # endif + pidns_print_leader(); puts("+++ exited with 0 +++"); return 0; } diff --git a/tests/pidfd_send_signal--pidns-translation.c b/tests/pidfd_send_signal--pidns-translation.c new file mode 100644 index 00000000..b04f10f5 --- /dev/null +++ b/tests/pidfd_send_signal--pidns-translation.c @@ -0,0 +1,2 @@ +#define PIDNS_TRANSLATION +#include "pidfd_send_signal.c" diff --git a/tests/pidfd_send_signal.c b/tests/pidfd_send_signal.c index 38b5bda1..a6b2d28c 100644 --- a/tests/pidfd_send_signal.c +++ b/tests/pidfd_send_signal.c @@ -10,6 +10,7 @@ #include "tests.h" #include #include "scno.h" +#include "pidns.h" #ifdef __NR_pidfd_send_signal @@ -36,6 +37,8 @@ sys_pidfd_send_signal(int pidfd, int sig, const void *info, int flags) int main(void) { + PIDNS_TEST_INIT; + static const char null_path[] = "/dev/null"; int fd = open(null_path, O_RDONLY); @@ -46,19 +49,23 @@ main(void) const void *esi = (const void *) si + 1; sys_pidfd_send_signal(fd, SIGUSR1, esi, 0); + pidns_print_leader(); printf("pidfd_send_signal(%d, SIGUSR1, %p, 0) = %s\n", fd, esi, errstr); si->si_signo = SIGUSR1; si->si_code = SI_QUEUE; + si->si_pid = getpid(); sys_pidfd_send_signal(fd, SIGUSR2, si, -1); + pidns_print_leader(); printf("pidfd_send_signal(%d, SIGUSR2, {si_signo=SIGUSR1" - ", si_code=SI_QUEUE, si_errno=%u, si_pid=%d, si_uid=%d" + ", si_code=SI_QUEUE, si_errno=%u, si_pid=%d%s, si_uid=%d" ", si_value={int=%d, ptr=%p}}, %#x) = %s\n", - fd, si->si_errno, si->si_pid, si->si_uid, si->si_int, si->si_ptr, - -1U, errstr); + fd, si->si_errno, si->si_pid, pidns_pid2str(PT_TGID), si->si_uid, + si->si_int, si->si_ptr, -1U, errstr); + pidns_print_leader(); puts("+++ exited with 0 +++"); return 0; } diff --git a/tests/pidns-cache.c b/tests/pidns-cache.c new file mode 100644 index 00000000..6319a7fd --- /dev/null +++ b/tests/pidns-cache.c @@ -0,0 +1,62 @@ +/* + * Copyright (c) 2020 The strace developers. + * All rights reserved. + * + * SPDX-License-Identifier: GPL-2.0-or-later + */ + +#include "tests.h" +#include "scno.h" +#include "pidns.h" + +#if defined __NR_getpid && (!defined __NR_getxpid || __NR_getxpid != __NR_getpid) + +# include +# include +# include + +# define SYSCALL_COUNT 1000 + +/** + * Max ratio of the execution time with and without pidns translation. + */ +# define MAX_TIME_RATIO 20 + +static long +execute_syscalls(void) +{ + /* Load our PID in the cache */ + syscall(__NR_getpid); + + struct timeval stop, start; + gettimeofday(&start, NULL); + + for (int i = 0; i < SYSCALL_COUNT; i++) + syscall(__NR_getpid); + + gettimeofday(&stop, NULL); + + return (stop.tv_usec - start.tv_usec) + + (stop.tv_sec - start.tv_sec) * 1000000; +} + +int +main(void) +{ + long max_us = execute_syscalls() * MAX_TIME_RATIO; + + pidns_test_init(); + + long us = execute_syscalls(); + if (us > max_us) + error_msg_and_fail("pidns translation took too long: %ld us " + "(max: %ld us)", us, max_us); + + return 0; +} + +#else + +SKIP_MAIN_UNDEFINED("__NR_getpid") + +#endif diff --git a/tests/pidns-cache.test b/tests/pidns-cache.test new file mode 100755 index 00000000..e4df0821 --- /dev/null +++ b/tests/pidns-cache.test @@ -0,0 +1,15 @@ +#!/bin/sh +# +# Test pidns translation cache. +# +# Copyright (c) 2020 The strace developers. +# All rights reserved. +# +# SPDX-License-Identifier: GPL-2.0-or-later + +. "${srcdir=.}/init.sh" + +check_prog timeout + +run_prog > /dev/null +run_strace --pidns-translation -f -e trace=getpid $args diff --git a/tests/prlimit64--pidns-translation.c b/tests/prlimit64--pidns-translation.c new file mode 100644 index 00000000..3972de66 --- /dev/null +++ b/tests/prlimit64--pidns-translation.c @@ -0,0 +1,2 @@ +#define PIDNS_TRANSLATION +#include "prlimit64.c" diff --git a/tests/prlimit64.c b/tests/prlimit64.c index 34201a2b..bc1a80b3 100644 --- a/tests/prlimit64.c +++ b/tests/prlimit64.c @@ -19,6 +19,7 @@ # include # include +# include "pidns.h" # include "xlat.h" # include "xlat/resources.h" @@ -42,8 +43,11 @@ sprint_rlim(uint64_t lim) int main(void) { + PIDNS_TEST_INIT; + unsigned long pid = (unsigned long) 0xdefaced00000000ULL | (unsigned) getpid(); + const char *pid_str = pidns_pid2str(PT_TGID); uint64_t *const rlimit = tail_alloc(sizeof(*rlimit) * 2); const struct xlat_data *xlat; size_t i = 0; @@ -54,18 +58,23 @@ main(void) unsigned long res = 0xfacefeed00000000ULL | xlat->val; long rc = syscall(__NR_prlimit64, pid, res, 0, rlimit); + pidns_print_leader(); if (rc) - printf("prlimit64(%d, %s, NULL, %p) = %ld %s (%m)\n", - (unsigned) pid, xlat->str, rlimit, + printf("prlimit64(%d%s, %s, NULL, %p) =" + " %ld %s (%m)\n", + (unsigned) pid, pid_str, + xlat->str, rlimit, rc, errno2name()); else - printf("prlimit64(%d, %s, NULL" + printf("prlimit64(%d%s, %s, NULL" ", {rlim_cur=%s, rlim_max=%s}) = 0\n", - (unsigned) pid, xlat->str, + (unsigned) pid, pid_str, + xlat->str, sprint_rlim(rlimit[0]), sprint_rlim(rlimit[1])); } + pidns_print_leader(); puts("+++ exited with 0 +++"); return 0; } diff --git a/tests/process_vm_readv--pidns-translation.c b/tests/process_vm_readv--pidns-translation.c new file mode 100644 index 00000000..0db29ca2 --- /dev/null +++ b/tests/process_vm_readv--pidns-translation.c @@ -0,0 +1,2 @@ +#define PIDNS_TRANSLATION +#include "process_vm_readv.c" diff --git a/tests/process_vm_readv_writev.c b/tests/process_vm_readv_writev.c index 9309135a..44e511dd 100644 --- a/tests/process_vm_readv_writev.c +++ b/tests/process_vm_readv_writev.c @@ -12,6 +12,7 @@ #include #include #include +#include "pidns.h" #if OP_WR # define in_iovec rmt_iovec @@ -121,7 +122,7 @@ print_iov(const struct iovec *iov, const void *arg_ptr, long rc) } static void -do_call(kernel_ulong_t pid, +do_call(kernel_ulong_t pid, enum pid_type pid_type, kernel_ulong_t local_iov, const char *local_arg, kernel_ulong_t liovcnt, kernel_ulong_t remote_iov, const char *remote_arg, @@ -135,7 +136,8 @@ do_call(kernel_ulong_t pid, flags); errstr = sprintrc(rc); - printf("%s(%d, ", OP_STR, (int) pid); + pidns_print_leader(); + printf("%s(%d%s, ", OP_STR, (int) pid, pidns_pid2str(pid_type)); if (pr_iov) pr_iov((const struct iovec *) (uintptr_t) local_iov, local_arg, @@ -164,6 +166,8 @@ ptr_cast(void *ptr) int main(void) { + PIDNS_TEST_INIT; + enum { SIZE_11 = 2, SIZE_12 = 3, @@ -243,18 +247,18 @@ main(void) fill_memory_ex(data2_out, SIZE_2, SEGM2_BASE, SIZE_2); - do_call(bogus_pid, (kernel_ulong_t) (uintptr_t) ARG_STR(NULL), + do_call(bogus_pid, PT_NONE, (kernel_ulong_t) (uintptr_t) ARG_STR(NULL), bogus_iovcnt1, (kernel_ulong_t) (uintptr_t) ARG_STR(NULL), bogus_iovcnt2, bogus_flags, NULL); - do_call(my_pid, ptr_cast(bogus_iov + ARRAY_SIZE(bogus_iovec)), + do_call(my_pid, PT_TGID, ptr_cast(bogus_iov + ARRAY_SIZE(bogus_iovec)), "[]", 0, ptr_cast(in_iov + ARRAY_SIZE(in_iovec)), "[]", 0, 0, NULL); - do_call(my_pid, ptr_cast(bogus_iov + ARRAY_SIZE(bogus_iovec)), NULL, - bogus_iovcnt1, ptr_cast(in_iov + ARRAY_SIZE(in_iovec)), NULL, - bogus_iovcnt2, 0, print_iov); + do_call(my_pid, PT_TGID, ptr_cast(bogus_iov + ARRAY_SIZE(bogus_iovec)), + NULL, bogus_iovcnt1, ptr_cast(in_iov + ARRAY_SIZE(in_iovec)), + NULL, bogus_iovcnt2, 0, print_iov); - do_call(my_pid, ptr_cast(bogus_iov), (char *) &bogus_arg, + do_call(my_pid, PT_TGID, ptr_cast(bogus_iov), (char *) &bogus_arg, ARRAY_SIZE(bogus_iovec), ptr_cast(rmt_iov + 2), (char *) &rmt_arg_cut, ARRAY_SIZE(rmt_iovec) - 2, 0, print_iov); @@ -263,7 +267,7 @@ main(void) lcl_arg_cut.check_rc = 1; #endif - do_call(my_pid, ptr_cast(lcl_iov + 2), (char *) &lcl_arg_cut, + do_call(my_pid, PT_TGID, ptr_cast(lcl_iov + 2), (char *) &lcl_arg_cut, ARRAY_SIZE(lcl_iovec) - 1, ptr_cast(bogus_iov + 2), (char *) &bogus_arg_cut, ARRAY_SIZE(bogus_iovec) - 1, 0, print_iov); @@ -273,15 +277,16 @@ main(void) rmt_arg_cut.addr_term = 1; rmt_arg_cut.count = 5; - do_call(my_pid, ptr_cast(lcl_iov + 2), (char *) &lcl_arg_cut, + do_call(my_pid, PT_TGID, ptr_cast(lcl_iov + 2), (char *) &lcl_arg_cut, ARRAY_SIZE(lcl_iovec) - 2, ptr_cast(rmt_iov + 1), (char *) &rmt_arg_cut, ARRAY_SIZE(rmt_iovec), 0, print_iov); /* Correct call */ - do_call(my_pid, ptr_cast(lcl_iov), (char *) &lcl_arg, + do_call(my_pid, PT_TGID, ptr_cast(lcl_iov), (char *) &lcl_arg, ARRAY_SIZE(lcl_iovec), ptr_cast(rmt_iov), (char *) &rmt_arg, ARRAY_SIZE(rmt_iovec), 0, print_iov); + pidns_print_leader(); puts("+++ exited with 0 +++"); return 0; diff --git a/tests/process_vm_writev--pidns-translation.c b/tests/process_vm_writev--pidns-translation.c new file mode 100644 index 00000000..9ba6a39b --- /dev/null +++ b/tests/process_vm_writev--pidns-translation.c @@ -0,0 +1,2 @@ +#define PIDNS_TRANSLATION +#include "process_vm_writev.c" diff --git a/tests/rt_sigqueueinfo--pidns-translation.c b/tests/rt_sigqueueinfo--pidns-translation.c new file mode 100644 index 00000000..74bfb464 --- /dev/null +++ b/tests/rt_sigqueueinfo--pidns-translation.c @@ -0,0 +1,2 @@ +#define PIDNS_TRANSLATION +#include "rt_sigqueueinfo.c" diff --git a/tests/rt_sigqueueinfo.c b/tests/rt_sigqueueinfo.c index c1693873..e22e4640 100644 --- a/tests/rt_sigqueueinfo.c +++ b/tests/rt_sigqueueinfo.c @@ -7,6 +7,7 @@ */ #include "tests.h" +#include "pidns.h" #include #include #include @@ -15,6 +16,8 @@ int main(void) { + PIDNS_TEST_INIT; + struct sigaction sa = { .sa_handler = SIG_IGN }; @@ -22,15 +25,19 @@ main(void) .sival_ptr = (void *) (unsigned long) 0xdeadbeefbadc0dedULL }; pid_t pid = getpid(); + const char *pid_str = pidns_pid2str(PT_TGID); assert(sigaction(SIGUSR1, &sa, NULL) == 0); if (sigqueue(pid, SIGUSR1, value)) perror_msg_and_skip("sigqueue"); - printf("rt_sigqueueinfo(%u, SIGUSR1, {si_signo=SIGUSR1, " - "si_code=SI_QUEUE, si_pid=%d, si_uid=%d, " + pidns_print_leader(); + printf("rt_sigqueueinfo(%d%s, SIGUSR1, {si_signo=SIGUSR1, " + "si_code=SI_QUEUE, si_pid=%d%s, si_uid=%u, " "si_value={int=%d, ptr=%p}}) = 0\n", - pid, pid, getuid(), value.sival_int, value.sival_ptr); - printf("+++ exited with 0 +++\n"); + pid, pid_str, pid, pid_str, + getuid(), value.sival_int, value.sival_ptr); + pidns_print_leader(); + puts("+++ exited with 0 +++"); return 0; } diff --git a/tests/rt_tgsigqueueinfo--pidns-translation.c b/tests/rt_tgsigqueueinfo--pidns-translation.c new file mode 100644 index 00000000..94396f00 --- /dev/null +++ b/tests/rt_tgsigqueueinfo--pidns-translation.c @@ -0,0 +1,2 @@ +#define PIDNS_TRANSLATION +#include "rt_tgsigqueueinfo.c" diff --git a/tests/rt_tgsigqueueinfo.c b/tests/rt_tgsigqueueinfo.c index 865c21f6..21d01cbb 100644 --- a/tests/rt_tgsigqueueinfo.c +++ b/tests/rt_tgsigqueueinfo.c @@ -10,8 +10,9 @@ #include "tests.h" #include "scno.h" +#include "pidns.h" -#ifdef __NR_rt_tgsigqueueinfo +#if defined __NR_rt_tgsigqueueinfo && defined __NR_gettid # include # include @@ -20,11 +21,11 @@ # include static long -k_tgsigqueueinfo(const pid_t pid, const int sig, const void *const info) +k_tgsigqueueinfo(const pid_t tgid, const int tid, const int sig, const void *const info) { return syscall(__NR_rt_tgsigqueueinfo, - F8ILL_KULONG_MASK | pid, - F8ILL_KULONG_MASK | pid, + F8ILL_KULONG_MASK | tgid, + F8ILL_KULONG_MASK | tid, F8ILL_KULONG_MASK | sig, info); } @@ -32,6 +33,8 @@ k_tgsigqueueinfo(const pid_t pid, const int sig, const void *const info) int main(void) { + PIDNS_TEST_INIT; + const struct sigaction sa = { .sa_handler = SIG_IGN }; @@ -48,17 +51,22 @@ main(void) info->si_value.sival_ptr = (void *) (unsigned long) 0xdeadbeeffacefeedULL; - if (k_tgsigqueueinfo(info->si_pid, SIGUSR1, info)) + if (k_tgsigqueueinfo(getpid(), syscall(__NR_gettid), SIGUSR1, info)) (errno == ENOSYS ? perror_msg_and_skip : perror_msg_and_fail)( "rt_tgsigqueueinfo"); - printf("rt_tgsigqueueinfo(%u, %u, %s, {si_signo=%s" - ", si_code=SI_QUEUE, si_errno=ENOENT, si_pid=%d" + pidns_print_leader(); + printf("rt_tgsigqueueinfo(%d%s, %d%s, %s, {si_signo=%s" + ", si_code=SI_QUEUE, si_errno=ENOENT, si_pid=%d%s" ", si_uid=%d, si_value={int=%d, ptr=%p}}) = 0\n", - info->si_pid, info->si_pid, "SIGUSR1", "SIGUSR1", - info->si_pid, info->si_uid, info->si_value.sival_int, + info->si_pid, pidns_pid2str(PT_TGID), + info->si_pid, pidns_pid2str(PT_TID), + "SIGUSR1", "SIGUSR1", + info->si_pid, pidns_pid2str(PT_TGID), + info->si_uid, info->si_value.sival_int, info->si_value.sival_ptr); + pidns_print_leader(); puts("+++ exited with 0 +++"); return 0; } diff --git a/tests/sched_xetaffinity--pidns-translation.c b/tests/sched_xetaffinity--pidns-translation.c new file mode 100644 index 00000000..814e3989 --- /dev/null +++ b/tests/sched_xetaffinity--pidns-translation.c @@ -0,0 +1,2 @@ +#define PIDNS_TRANSLATION +#include "sched_xetaffinity.c" diff --git a/tests/sched_xetaffinity.c b/tests/sched_xetaffinity.c index cebff3ab..2e508ca3 100644 --- a/tests/sched_xetaffinity.c +++ b/tests/sched_xetaffinity.c @@ -10,6 +10,7 @@ #include "tests.h" #include "scno.h" +#include "pidns.h" #include #if defined __NR_sched_getaffinity && defined __NR_sched_setaffinity \ @@ -41,8 +42,11 @@ setaffinity(unsigned long pid, unsigned long size, void *set) int main(void) { + PIDNS_TEST_INIT; + unsigned int cpuset_size = 1; const pid_t pid = getpid(); + const char *pid_str = pidns_pid2str(PT_TGID); while (cpuset_size) { assert(getaffinity(pid, cpuset_size, NULL) == -1); @@ -50,18 +54,21 @@ main(void) break; if (EINVAL != errno) perror_msg_and_skip("sched_getaffinity"); - printf("sched_getaffinity(%d, %u, NULL) = %s\n", - pid, cpuset_size, errstr); + pidns_print_leader(); + printf("sched_getaffinity(%d%s, %u, NULL) = %s\n", + pid, pid_str, cpuset_size, errstr); cpuset_size <<= 1; } assert(cpuset_size); - printf("sched_getaffinity(%d, %u, NULL) = %s\n", - pid, cpuset_size, errstr); + pidns_print_leader(); + printf("sched_getaffinity(%d%s, %u, NULL) = %s\n", + pid, pid_str, cpuset_size, errstr); cpu_set_t *cpuset = tail_alloc(cpuset_size); getaffinity(pid, cpuset_size, cpuset + 1); - printf("sched_getaffinity(%d, %u, %p) = %s\n", - pid, cpuset_size, cpuset + 1, errstr); + pidns_print_leader(); + printf("sched_getaffinity(%d%s, %u, %p) = %s\n", + pid, pid_str, cpuset_size, cpuset + 1, errstr); int ret_size = getaffinity(pid, cpuset_size, cpuset); if (ret_size < 0) @@ -69,7 +76,8 @@ main(void) pid, (unsigned) cpuset_size, cpuset, errstr); assert(ret_size <= (int) cpuset_size); - printf("sched_getaffinity(%d, %u, [", pid, cpuset_size); + pidns_print_leader(); + printf("sched_getaffinity(%d%s, %u, [", pid, pid_str, cpuset_size); const char *sep; unsigned int i, cpu; for (i = 0, cpu = 0, sep = ""; i < (unsigned) ret_size * 8; ++i) { @@ -85,8 +93,9 @@ main(void) CPU_SET_S(cpu, cpuset_size, cpuset); if (setaffinity(pid, cpuset_size, cpuset)) perror_msg_and_skip("sched_setaffinity"); - printf("sched_setaffinity(%d, %u, [%u]) = 0\n", - pid, cpuset_size, cpu); + pidns_print_leader(); + printf("sched_setaffinity(%d%s, %u, [%u]) = 0\n", + pid, pid_str, cpuset_size, cpu); const unsigned int big_size = cpuset_size < 128 ? 128 : cpuset_size * 2; cpuset = tail_alloc(big_size); @@ -95,7 +104,8 @@ main(void) perror_msg_and_fail("sched_getaffinity(%d, %u, %p) = %s\n", pid, big_size, cpuset, errstr); assert(ret_size <= (int) big_size); - printf("sched_getaffinity(%d, %u, [", pid, big_size); + pidns_print_leader(); + printf("sched_getaffinity(%d%s, %u, [", pid, pid_str, big_size); for (i = 0, sep = ""; i < (unsigned) ret_size * 8; ++i) { if (CPU_ISSET_S(i, (unsigned) ret_size, cpuset)) { printf("%s%u", sep, i); @@ -104,6 +114,7 @@ main(void) } printf("]) = %s\n", errstr); + pidns_print_leader(); puts("+++ exited with 0 +++"); return 0; } diff --git a/tests/sched_xetattr--pidns-translation.c b/tests/sched_xetattr--pidns-translation.c new file mode 100644 index 00000000..c152023d --- /dev/null +++ b/tests/sched_xetattr--pidns-translation.c @@ -0,0 +1,2 @@ +#define PIDNS_TRANSLATION +#include "sched_xetattr.c" diff --git a/tests/sched_xetattr.c b/tests/sched_xetattr.c index c63d7a80..4a76b2d6 100644 --- a/tests/sched_xetattr.c +++ b/tests/sched_xetattr.c @@ -15,6 +15,7 @@ # include # include # include +# include "pidns.h" # include "sched_attr.h" # include "xlat.h" # include "xlat/schedulers.h" @@ -41,6 +42,8 @@ sys_sched_setattr(kernel_ulong_t pid, kernel_ulong_t attr, kernel_ulong_t flags) int main(void) { + PIDNS_TEST_INIT; + static const kernel_ulong_t bogus_pid = (kernel_ulong_t) 0xdefacedfacefeedULL; static const kernel_ulong_t bogus_size = @@ -48,20 +51,28 @@ main(void) static const kernel_ulong_t bogus_flags = (kernel_ulong_t) 0xdefaceddeadc0deULL; + const int pid = getpid(); + const char *pid_str = pidns_pid2str(PT_TGID); + TAIL_ALLOC_OBJECT_CONST_PTR(struct sched_attr, attr); TAIL_ALLOC_OBJECT_CONST_PTR(unsigned int, psize); void *const efault = attr + 1; - sys_sched_getattr(0, 0, 0, 0); - printf("sched_getattr(0, NULL, 0, 0) = %s\n", errstr); + sys_sched_getattr(pid, 0, 0, 0); + pidns_print_leader(); + printf("sched_getattr(%d%s, NULL, 0, 0) = %s\n", + pid, pid_str, errstr); sys_sched_getattr(0, (unsigned long) attr, 0, 0); + pidns_print_leader(); printf("sched_getattr(0, %p, 0, 0) = %s\n", attr, errstr); sys_sched_getattr(bogus_pid, 0, 0, 0); + pidns_print_leader(); printf("sched_getattr(%d, NULL, 0, 0) = %s\n", (int) bogus_pid, errstr); sys_sched_getattr(-1U, (unsigned long) attr, bogus_size, bogus_flags); + pidns_print_leader(); printf("sched_getattr(-1, %p, %s%u, %u) = %s\n", attr, # if defined __arm64__ || defined __aarch64__ @@ -72,11 +83,13 @@ main(void) (unsigned) bogus_size, (unsigned) bogus_flags, errstr); sys_sched_getattr(0, (unsigned long) efault, SCHED_ATTR_MIN_SIZE, 0); + pidns_print_leader(); printf("sched_getattr(0, %p, %u, 0) = %s\n", efault, (unsigned) SCHED_ATTR_MIN_SIZE, errstr); if (sys_sched_getattr(0, (unsigned long) attr, SCHED_ATTR_MIN_SIZE, 0)) perror_msg_and_skip("sched_getattr"); + pidns_print_leader(); printf("sched_getattr(0, {size=%u, sched_policy=", attr->size); printxval(schedulers, attr->sched_policy, NULL); printf(", sched_flags=%s, sched_nice=%d, sched_priority=%u" @@ -91,11 +104,13 @@ main(void) (unsigned) SCHED_ATTR_MIN_SIZE); sys_sched_getattr(0, (unsigned long) efault, sizeof(*attr), 0); + pidns_print_leader(); printf("sched_getattr(0, %p, %u, 0) = %s\n", efault, (unsigned) sizeof(*attr), errstr); if (sys_sched_getattr(0, (unsigned long) attr, sizeof(*attr), 0)) perror_msg_and_skip("sched_getattr"); + pidns_print_leader(); printf("sched_getattr(0, {size=%u, sched_policy=", attr->size); printxval(schedulers, attr->sched_policy, NULL); printf(", sched_flags=%s, sched_nice=%d, sched_priority=%u" @@ -121,11 +136,13 @@ main(void) F8ILL_KULONG_MASK | sizeof(*attr), F8ILL_KULONG_MASK); # if defined __arm64__ || defined __aarch64__ if (rc) { + pidns_print_leader(); printf("sched_getattr(0, %p, 0xffffffff<<32|%u, 0) = %s\n", attr, (unsigned) sizeof(*attr), errstr); } else # endif { + pidns_print_leader(); printf("sched_getattr(0, {size=%u, sched_policy=", attr->size); printxval(schedulers, attr->sched_policy, NULL); printf(", sched_flags=%s, sched_nice=%d, sched_priority=%u" @@ -146,13 +163,16 @@ main(void) } sys_sched_setattr(bogus_pid, 0, 0); + pidns_print_leader(); printf("sched_setattr(%d, NULL, 0) = %s\n", (int) bogus_pid, errstr); attr->sched_flags |= 1; - if (sys_sched_setattr(0, (unsigned long) attr, 0)) + if (sys_sched_setattr(pid, (unsigned long) attr, 0)) perror_msg_and_skip("sched_setattr"); - printf("sched_setattr(0, {size=%u, sched_policy=", attr->size); + pidns_print_leader(); + printf("sched_setattr(%d%s, {size=%u, sched_policy=", + pid, pid_str, attr->size); printxval(schedulers, attr->sched_policy, NULL); printf(", sched_flags=%s, sched_nice=%d, sched_priority=%u" ", sched_runtime=%" PRIu64 ", sched_deadline=%" PRIu64 @@ -172,6 +192,7 @@ main(void) sys_sched_setattr(F8ILL_KULONG_MASK, (unsigned long) attr, F8ILL_KULONG_MASK); + pidns_print_leader(); printf("sched_setattr(0, {size=%u, sched_policy=", attr->size); printxval(schedulers, attr->sched_policy, NULL); printf(", sched_flags=%s, sched_nice=%d, sched_priority=%u" @@ -193,11 +214,13 @@ main(void) *psize = attr->size; sys_sched_setattr(0, (unsigned long) psize, 0); + pidns_print_leader(); printf("sched_setattr(0, %p, 0) = %s\n", psize, errstr); attr->size = 0; sys_sched_setattr(0, (unsigned long) attr, 0); + pidns_print_leader(); printf("sched_setattr(0, {size=%u, sched_policy=", attr->size); printxval(schedulers, attr->sched_policy, NULL); printf(", sched_flags=%s, sched_nice=%d, sched_priority=%u" @@ -213,12 +236,14 @@ main(void) attr->size = 1; sys_sched_setattr(0, (unsigned long) attr, 0); + pidns_print_leader(); printf("sched_setattr(0, {size=%u} => {size=%u}, 0) = %s\n", 1, attr->size, errstr); attr->size = SCHED_ATTR_MIN_SIZE - 1; sys_sched_setattr(0, (unsigned long) attr, 0); + pidns_print_leader(); printf("sched_setattr(0, {size=%u} => {size=%u}, 0) = %s\n", SCHED_ATTR_MIN_SIZE - 1, attr->size, errstr); @@ -232,6 +257,7 @@ main(void) attr->sched_period = 0xded1ca7edda7aca7ULL; sys_sched_setattr(bogus_pid, (unsigned long) attr, bogus_flags); + pidns_print_leader(); printf("sched_setattr(%d, {size=%u, sched_policy=%#x /* SCHED_??? */, " "sched_flags=%#" PRIx64 " /* SCHED_FLAG_??? */, " "sched_nice=%d, sched_priority=%u, sched_runtime=%" PRIu64 ", " @@ -274,6 +300,7 @@ main(void) attr->sched_period = 0xded1ca7edda7aca7ULL; sys_sched_setattr(bogus_pid, (unsigned long) attr, bogus_flags); + pidns_print_leader(); printf("sched_setattr(%d, {size=%u, sched_policy=%#x /* SCHED_??? */, " "sched_flags=SCHED_FLAG_RESET_ON_FORK|SCHED_FLAG_RECLAIM|" "SCHED_FLAG_DL_OVERRUN|0x80, " @@ -296,11 +323,13 @@ main(void) const kernel_ulong_t ill = f8ill_ptr_to_kulong(attr); sys_sched_getattr(0, ill, sizeof(*attr), 0); + pidns_print_leader(); printf("sched_getattr(0, %#llx, %u, 0) = %s\n", (unsigned long long) ill, (unsigned) sizeof(*attr), errstr); sys_sched_setattr(0, ill, 0); + pidns_print_leader(); printf("sched_setattr(0, %#llx, 0) = %s\n", (unsigned long long) ill, errstr); } @@ -310,6 +339,7 @@ main(void) attr->sched_flags = 0x8fULL; sys_sched_setattr(bogus_pid, (unsigned long) attr, bogus_flags); + pidns_print_leader(); printf("sched_setattr(%d, {size=%u, " "sched_flags=SCHED_FLAG_RESET_ON_FORK|SCHED_FLAG_RECLAIM|" "SCHED_FLAG_DL_OVERRUN|SCHED_FLAG_KEEP_POLICY|0x80, " @@ -329,11 +359,13 @@ main(void) const kernel_ulong_t ill = f8ill_ptr_to_kulong(attr); sys_sched_getattr(0, ill, sizeof(*attr), 0); + pidns_print_leader(); printf("sched_getattr(0, %#llx, %u, 0) = %s\n", (unsigned long long) ill, (unsigned) sizeof(*attr), errstr); sys_sched_setattr(0, ill, 0); + pidns_print_leader(); printf("sched_setattr(0, %#llx, 0) = %s\n", (unsigned long long) ill, errstr); } @@ -342,6 +374,7 @@ main(void) attr->sched_flags = 0xe7ULL; sys_sched_setattr(bogus_pid, (unsigned long) attr, bogus_flags); + pidns_print_leader(); printf("sched_setattr(%d, {size=%u, sched_policy=%#x /* SCHED_??? */, " "sched_flags=SCHED_FLAG_RESET_ON_FORK|SCHED_FLAG_RECLAIM|" "SCHED_FLAG_DL_OVERRUN|SCHED_FLAG_UTIL_CLAMP_MIN" @@ -365,11 +398,13 @@ main(void) const kernel_ulong_t ill = f8ill_ptr_to_kulong(attr); sys_sched_getattr(0, ill, sizeof(*attr), 0); + pidns_print_leader(); printf("sched_getattr(0, %#llx, %u, 0) = %s\n", (unsigned long long) ill, (unsigned) sizeof(*attr), errstr); sys_sched_setattr(0, ill, 0); + pidns_print_leader(); printf("sched_setattr(0, %#llx, 0) = %s\n", (unsigned long long) ill, errstr); } @@ -377,6 +412,7 @@ main(void) attr->sched_flags = 0xcaffee90LL; sys_sched_setattr(bogus_pid, (unsigned long) attr, bogus_flags); + pidns_print_leader(); printf("sched_setattr(%d, {size=%u, sched_flags=SCHED_FLAG_KEEP_PARAMS" "|0xcaffee80, sched_util_min=%u, sched_util_max=%u}, %u) = %s\n", (int) bogus_pid, @@ -389,15 +425,18 @@ main(void) const kernel_ulong_t ill = f8ill_ptr_to_kulong(attr); sys_sched_getattr(0, ill, sizeof(*attr), 0); + pidns_print_leader(); printf("sched_getattr(0, %#llx, %u, 0) = %s\n", (unsigned long long) ill, (unsigned) sizeof(*attr), errstr); sys_sched_setattr(0, ill, 0); + pidns_print_leader(); printf("sched_setattr(0, %#llx, 0) = %s\n", (unsigned long long) ill, errstr); } + pidns_print_leader(); puts("+++ exited with 0 +++"); return 0; } diff --git a/tests/sched_xetparam--pidns-translation.c b/tests/sched_xetparam--pidns-translation.c new file mode 100644 index 00000000..9fb3e579 --- /dev/null +++ b/tests/sched_xetparam--pidns-translation.c @@ -0,0 +1,2 @@ +#define PIDNS_TRANSLATION +#include "sched_xetparam.c" diff --git a/tests/sched_xetparam.c b/tests/sched_xetparam.c index de3915b2..aa9c68cc 100644 --- a/tests/sched_xetparam.c +++ b/tests/sched_xetparam.c @@ -7,6 +7,7 @@ #include "tests.h" #include "scno.h" +# include "pidns.h" #if defined __NR_sched_getparam && defined __NR_sched_setparam @@ -17,18 +18,27 @@ int main(void) { + PIDNS_TEST_INIT; + struct sched_param *const param = tail_alloc(sizeof(struct sched_param)); - long rc = syscall(__NR_sched_getparam, 0, param); - printf("sched_getparam(0, [%d]) = %ld\n", - param->sched_priority, rc); + const int pid = getpid(); + const char *pid_str = pidns_pid2str(PT_TGID); + + long rc = syscall(__NR_sched_getparam, pid, param); + pidns_print_leader(); + printf("sched_getparam(%d%s, [%d]) = %ld\n", + pid, pid_str, param->sched_priority, rc); param->sched_priority = -1; - rc = syscall(__NR_sched_setparam, 0, param); - printf("sched_setparam(0, [%d]) = %ld %s (%m)\n", + rc = syscall(__NR_sched_setparam, pid, param); + pidns_print_leader(); + printf("sched_setparam(%d%s, [%d]) = %ld %s (%m)\n", + pid, pid_str, param->sched_priority, rc, errno2name()); + pidns_print_leader(); puts("+++ exited with 0 +++"); return 0; } diff --git a/tests/sched_xetscheduler--pidns-translation.c b/tests/sched_xetscheduler--pidns-translation.c new file mode 100644 index 00000000..78b794b2 --- /dev/null +++ b/tests/sched_xetscheduler--pidns-translation.c @@ -0,0 +1,2 @@ +#define PIDNS_TRANSLATION +#include "sched_xetscheduler.c" diff --git a/tests/sched_xetscheduler.c b/tests/sched_xetscheduler.c index 047e8676..91b5e32d 100644 --- a/tests/sched_xetscheduler.c +++ b/tests/sched_xetscheduler.c @@ -7,6 +7,7 @@ #include "tests.h" #include "scno.h" +#include "pidns.h" #if defined __NR_sched_getscheduler && defined __NR_sched_setscheduler @@ -17,8 +18,13 @@ int main(void) { + PIDNS_TEST_INIT; + TAIL_ALLOC_OBJECT_CONST_PTR(struct sched_param, param); - long rc = syscall(__NR_sched_getscheduler, 0); + const int pid = getpid(); + const char *pid_str = pidns_pid2str(PT_TGID); + + long rc = syscall(__NR_sched_getscheduler, pid); const char *scheduler; switch (rc) { case SCHED_FIFO: @@ -50,33 +56,43 @@ main(void) default: scheduler = "SCHED_OTHER"; } - printf("sched_getscheduler(0) = %ld (%s)\n", - rc, scheduler); + pidns_print_leader(); + printf("sched_getscheduler(%d%s) = %ld (%s)\n", + pid, pid_str, rc, scheduler); rc = syscall(__NR_sched_getscheduler, -1); + pidns_print_leader(); printf("sched_getscheduler(-1) = %s\n", sprintrc(rc)); param->sched_priority = -1; - rc = syscall(__NR_sched_setscheduler, 0, SCHED_FIFO, NULL); - printf("sched_setscheduler(0, SCHED_FIFO, NULL) = %s\n", sprintrc(rc)); + rc = syscall(__NR_sched_setscheduler, pid, SCHED_FIFO, NULL); + pidns_print_leader(); + printf("sched_setscheduler(%d%s, SCHED_FIFO, NULL) = %s\n", + pid, pid_str, sprintrc(rc)); - rc = syscall(__NR_sched_setscheduler, 0, SCHED_FIFO, param + 1); - printf("sched_setscheduler(0, SCHED_FIFO, %p) = %s\n", param + 1, - sprintrc(rc)); + rc = syscall(__NR_sched_setscheduler, pid, SCHED_FIFO, param + 1); + pidns_print_leader(); + printf("sched_setscheduler(%d%s, SCHED_FIFO, %p) = %s\n", + pid, pid_str, param + 1, sprintrc(rc)); - rc = syscall(__NR_sched_setscheduler, 0, 0xfaceda7a, param); - printf("sched_setscheduler(0, %#x /* SCHED_??? */, [%d]) = %s\n", - 0xfaceda7a, param->sched_priority, sprintrc(rc)); + rc = syscall(__NR_sched_setscheduler, pid, 0xfaceda7a, param); + pidns_print_leader(); + printf("sched_setscheduler(%d%s, %#x /* SCHED_??? */, [%d]) = %s\n", + pid, pid_str, 0xfaceda7a, + param->sched_priority, sprintrc(rc)); rc = syscall(__NR_sched_setscheduler, -1, SCHED_FIFO, param); + pidns_print_leader(); printf("sched_setscheduler(-1, SCHED_FIFO, [%d]) = %s\n", param->sched_priority, sprintrc(rc)); - rc = syscall(__NR_sched_setscheduler, 0, SCHED_FIFO, param); - printf("sched_setscheduler(0, SCHED_FIFO, [%d]) = %s\n", - param->sched_priority, sprintrc(rc)); + rc = syscall(__NR_sched_setscheduler, pid, SCHED_FIFO, param); + pidns_print_leader(); + printf("sched_setscheduler(%d%s, SCHED_FIFO, [%d]) = %s\n", + pid, pid_str, param->sched_priority, sprintrc(rc)); + pidns_print_leader(); puts("+++ exited with 0 +++"); return 0; } diff --git a/tests/signal_receive--pidns-translation.c b/tests/signal_receive--pidns-translation.c new file mode 100644 index 00000000..b4e3b2f8 --- /dev/null +++ b/tests/signal_receive--pidns-translation.c @@ -0,0 +1,2 @@ +#define PIDNS_TRANSLATION +#include "signal_receive.c" diff --git a/tests/signal_receive.c b/tests/signal_receive.c index ad3b4ebd..70441a9e 100644 --- a/tests/signal_receive.c +++ b/tests/signal_receive.c @@ -8,6 +8,7 @@ */ #include "tests.h" +#include "pidns.h" #include #include #include @@ -26,10 +27,13 @@ handler(int sig, siginfo_t *info, void *ucontext) int main(void) { + PIDNS_TEST_INIT; + static const char prefix[] = "KERNEL BUG"; int printed = 0; const int pid = getpid(); + const char *pid_str = pidns_pid2str(PT_TGID); const int uid = geteuid(); for (int sig = 1; sig <= 31; ++sig) { @@ -73,10 +77,13 @@ main(void) const int e_pid = s_pid; const int e_uid = s_uid; #endif - printf("kill(%d, %s) = 0\n", pid, signal2name(sig)); - printf("--- %s {si_signo=%s, si_code=SI_USER, si_pid=%d" + pidns_print_leader(); + printf("kill(%d%s, %s) = 0\n", pid, pid_str, signal2name(sig)); + pidns_print_leader(); + printf("--- %s {si_signo=%s, si_code=SI_USER, si_pid=%d%s" ", si_uid=%d} ---\n", - signal2name(sig), signal2name(e_sig), e_pid, e_uid); + signal2name(sig), signal2name(e_sig), + e_pid, pid_str, e_uid); if (s_code || sig != s_sig || pid != s_pid || uid != s_uid) { /* @@ -91,11 +98,11 @@ main(void) } fprintf(stderr, "%s: expected: si_signo=%d, si_code=%d" - ", si_pid=%d, si_uid=%d\n" + ", si_pid=%d%s, si_uid=%d\n" "%s: received: si_signo=%d, si_code=%d" - ", si_pid=%d, si_uid=%d\n", - prefix, sig, SI_USER, pid, uid, - prefix, sig, s_code, s_pid, s_uid); + ", si_pid=%d%s, si_uid=%d\n", + prefix, sig, SI_USER, pid, pid_str, uid, + prefix, sig, s_code, s_pid, pid_str, s_uid); } } @@ -104,6 +111,7 @@ main(void) "*** PLEASE FIX THE KERNEL ***\n", prefix); } + pidns_print_leader(); puts("+++ exited with 0 +++"); return 0; } diff --git a/tests/so_peercred--pidns-translation.c b/tests/so_peercred--pidns-translation.c new file mode 100644 index 00000000..402bbcfe --- /dev/null +++ b/tests/so_peercred--pidns-translation.c @@ -0,0 +1,2 @@ +#define PIDNS_TRANSLATION +#include "so_peercred.c" diff --git a/tests/so_peercred.c b/tests/so_peercred.c index 151bb175..20188bdb 100644 --- a/tests/so_peercred.c +++ b/tests/so_peercred.c @@ -9,6 +9,7 @@ */ #include "tests.h" +#include "pidns.h" #include #include @@ -53,6 +54,8 @@ so_str(void) int main(void) { + PIDNS_TEST_INIT; + TAIL_ALLOC_OBJECT_CONST_PTR(struct ucred, peercred); TAIL_ALLOC_OBJECT_CONST_PTR(socklen_t, len); @@ -75,6 +78,8 @@ main(void) struct ucred *const gid_truncated = tail_alloc(sizeof_gid_truncated); + const char *pid_str = pidns_pid2str(PT_TGID); + int sv[2]; if (socketpair(AF_UNIX, SOCK_STREAM, 0, sv)) perror_msg_and_skip("socketpair AF_UNIX SOCK_STREAM"); @@ -82,8 +87,10 @@ main(void) /* classic getsockopt */ *len = sizeof(*peercred); get_peercred(sv[0], peercred, len); + pidns_print_leader(); printf("getsockopt(%d, %s", sv[0], so_str()); PRINT_FIELD_D(", {", *peercred, pid); + printf("%s", pid_str); PRINT_FIELD_UID(", ", *peercred, uid); PRINT_FIELD_UID(", ", *peercred, gid); printf("}, [%d]) = %s\n", *len, errstr); @@ -91,14 +98,17 @@ main(void) /* getsockopt with zero optlen */ *len = 0; get_peercred(sv[0], peercred, len); + pidns_print_leader(); printf("getsockopt(%d, %s, %p, [0]) = %s\n", sv[0], so_str(), peercred, errstr); /* getsockopt with optlen larger than necessary - shortened */ *len = sizeof(*peercred) + 1; get_peercred(sv[0], peercred, len); + pidns_print_leader(); printf("getsockopt(%d, %s", sv[0], so_str()); PRINT_FIELD_D(", {", *peercred, pid); + printf("%s", pid_str); PRINT_FIELD_UID(", ", *peercred, uid); PRINT_FIELD_UID(", ", *peercred, gid); printf("}, [%u->%d]) = %s\n", @@ -110,6 +120,7 @@ main(void) */ *len = sizeof_pid_truncated; get_peercred(sv[0], pid_truncated, len); + pidns_print_leader(); printf("getsockopt(%d, %s, {pid=", sv[0], so_str()); print_quoted_hex(pid_truncated, *len); printf("}, [%d]) = %s\n", *len, errstr); @@ -120,8 +131,10 @@ main(void) */ *len = sizeof_pid; get_peercred(sv[0], pid, len); + pidns_print_leader(); printf("getsockopt(%d, %s", sv[0], so_str()); PRINT_FIELD_D(", {", *pid, pid); + printf("%s", pid_str); printf("}, [%d]) = %s\n", *len, errstr); /* @@ -136,8 +149,10 @@ main(void) * to struct ucred.pid field. */ memcpy(uid, uid_truncated, sizeof_uid_truncated); + pidns_print_leader(); printf("getsockopt(%d, %s", sv[0], so_str()); PRINT_FIELD_D(", {", *uid, pid); + printf("%s", pid_str); printf(", uid="); print_quoted_hex(&uid->uid, sizeof_uid_truncated - offsetof(struct ucred, uid)); @@ -149,8 +164,10 @@ main(void) */ *len = sizeof_uid; get_peercred(sv[0], uid, len); + pidns_print_leader(); printf("getsockopt(%d, %s", sv[0], so_str()); PRINT_FIELD_D(", {", *uid, pid); + printf("%s", pid_str); PRINT_FIELD_UID(", ", *uid, uid); printf("}, [%d]) = %s\n", *len, errstr); @@ -166,8 +183,10 @@ main(void) * to struct ucred.pid and struct ucred.uid fields. */ memcpy(peercred, gid_truncated, sizeof_gid_truncated); + pidns_print_leader(); printf("getsockopt(%d, %s", sv[0], so_str()); PRINT_FIELD_D(", {", *peercred, pid); + printf("%s", pid_str); PRINT_FIELD_UID(", ", *peercred, uid); printf(", gid="); print_quoted_hex(&peercred->gid, sizeof_gid_truncated - @@ -177,14 +196,17 @@ main(void) /* getsockopt optval EFAULT */ *len = sizeof(*peercred); get_peercred(sv[0], &peercred->uid, len); + pidns_print_leader(); printf("getsockopt(%d, %s, %p, [%d]) = %s\n", sv[0], so_str(), &peercred->uid, *len, errstr); /* getsockopt optlen EFAULT */ get_peercred(sv[0], peercred, len + 1); + pidns_print_leader(); printf("getsockopt(%d, %s, %p, %p) = %s\n", sv[0], so_str(), peercred, len + 1, errstr); + pidns_print_leader(); puts("+++ exited with 0 +++"); return 0; } diff --git a/tests/tgkill--pidns-translation.c b/tests/tgkill--pidns-translation.c new file mode 100644 index 00000000..c3ac2d0a --- /dev/null +++ b/tests/tgkill--pidns-translation.c @@ -0,0 +1,2 @@ +#define PIDNS_TRANSLATION +#include "tgkill.c" diff --git a/tests/tgkill.c b/tests/tgkill.c index 901be376..10816a61 100644 --- a/tests/tgkill.c +++ b/tests/tgkill.c @@ -9,6 +9,7 @@ #include "tests.h" #include "scno.h" +#include "pidns.h" #ifdef __NR_tgkill @@ -36,28 +37,46 @@ k_tgkill(const unsigned int tgid, int main(void) { + PIDNS_TEST_INIT; + const int pid = getpid(); + const char *pid_str = pidns_pid2str(PT_TGID); + const int tid = syscall(__NR_gettid); + const char *tid_str = pidns_pid2str(PT_TID); const int bad_pid = -1; const int bad_sig = 0xface; - k_tgkill(pid, pid, 0); - printf("tgkill(%d, %d, 0) = %s\n", pid, pid, errstr); + k_tgkill(pid, tid, 0); + pidns_print_leader(); + printf("tgkill(%d%s, %d%s, 0) = %s\n", + pid, pid_str, tid, tid_str, errstr); k_tgkill(pid, bad_pid, 0); - printf("tgkill(%d, %d, 0) = %s\n", pid, bad_pid, errstr); - - k_tgkill(bad_pid, pid, 0); - printf("tgkill(%d, %d, 0) = %s\n", bad_pid, pid, errstr); - - k_tgkill(pid, pid, SIGCONT); - printf("tgkill(%d, %d, SIGCONT) = %s\n", pid, pid, errstr); - - k_tgkill(pid, pid, bad_sig); - printf("tgkill(%d, %d, %d) = %s\n", pid, pid, bad_sig, errstr); - - k_tgkill(pid, pid, -bad_sig); - printf("tgkill(%d, %d, %d) = %s\n", pid, pid, -bad_sig, errstr); - + pidns_print_leader(); + printf("tgkill(%d%s, %d, 0) = %s\n", + pid, pid_str, bad_pid, errstr); + + k_tgkill(bad_pid, tid, 0); + pidns_print_leader(); + printf("tgkill(%d, %d%s, 0) = %s\n", + bad_pid, tid, tid_str, errstr); + + k_tgkill(pid, tid, SIGCONT); + pidns_print_leader(); + printf("tgkill(%d%s, %d%s, SIGCONT) = %s\n", + pid, pid_str, tid, tid_str, errstr); + + k_tgkill(pid, tid, bad_sig); + pidns_print_leader(); + printf("tgkill(%d%s, %d%s, %d) = %s\n", + pid, pid_str, tid, tid_str, bad_sig, errstr); + + k_tgkill(pid, tid, -bad_sig); + pidns_print_leader(); + printf("tgkill(%d%s, %d%s, %d) = %s\n", + pid, pid_str, tid, tid_str, -bad_sig, errstr); + + pidns_print_leader(); puts("+++ exited with 0 +++"); return 0; } diff --git a/tests/tkill--pidns-translation.c b/tests/tkill--pidns-translation.c new file mode 100644 index 00000000..70a64f57 --- /dev/null +++ b/tests/tkill--pidns-translation.c @@ -0,0 +1,2 @@ +#define PIDNS_TRANSLATION +#include "tkill.c" diff --git a/tests/tkill.c b/tests/tkill.c index 5f67c9f5..89466e1a 100644 --- a/tests/tkill.c +++ b/tests/tkill.c @@ -9,6 +9,7 @@ #include "tests.h" #include "scno.h" +#include "pidns.h" #ifdef __NR_tkill @@ -33,22 +34,30 @@ k_tkill(const unsigned int tid, const unsigned int sig) int main(void) { - const int pid = getpid(); + PIDNS_TEST_INIT; + + const int tid = syscall(__NR_gettid); + const char *tid_str = pidns_pid2str(PT_TID); const int bad_pid = -1; const int bad_sig = 0xface; - k_tkill(pid, 0); - printf("tkill(%d, 0) = %s\n", pid, errstr); + k_tkill(tid, 0); + pidns_print_leader(); + printf("tkill(%d%s, 0) = %s\n", tid, tid_str, errstr); - k_tkill(pid, SIGCONT); - printf("tkill(%d, SIGCONT) = %s\n", pid, errstr); + k_tkill(tid, SIGCONT); + pidns_print_leader(); + printf("tkill(%d%s, SIGCONT) = %s\n", tid, tid_str, errstr); k_tkill(bad_pid, bad_sig); + pidns_print_leader(); printf("tkill(%d, %d) = %s\n", bad_pid, bad_sig, errstr); k_tkill(bad_pid, -bad_sig); + pidns_print_leader(); printf("tkill(%d, %d) = %s\n", bad_pid, -bad_sig, errstr); + pidns_print_leader(); puts("+++ exited with 0 +++"); return 0; } diff --git a/tests/trie_for_tests.c b/tests/trie_for_tests.c new file mode 100644 index 00000000..13e564c4 --- /dev/null +++ b/tests/trie_for_tests.c @@ -0,0 +1 @@ +#include "trie.c" diff --git a/tests/trie_test.c b/tests/trie_test.c new file mode 100644 index 00000000..21c9c11b --- /dev/null +++ b/tests/trie_test.c @@ -0,0 +1,121 @@ +/* + * Copyright (c) 2017-2019 The strace developers. + * All rights reserved. + * + * SPDX-License-Identifier: GPL-2.0-or-later + */ + +#include "tests.h" +#include "trie.h" + +#include +#include + +static void +assert_equals(const char *msg, uint64_t expected, uint64_t actual) { + if (actual != expected) + error_msg_and_fail("%s: expected: %" PRIu64 + ", actual: %" PRIu64, msg, expected, actual); +} + +static void +iterate_fn(void *data, uint64_t key, uint64_t value) +{ + uint64_t expected = key < 256 && key % 10 == 0 ? key + 42 : -1ULL; + assert_equals("iterate_fn", expected, value); + + int *count = (int *) data; + if (value != -1ULL) + (*count)++; +} + +static void +test_trie_iterate_fn(void) +{ + struct trie *t = trie_create(8, 6, 3, 3, -1); + for (int i = 0; i < 26; i++) + trie_set(t, i * 10, i * 10 + 42); + + static const struct { + uint64_t start; + uint64_t end; + int expected_count; + } iterate_params[] = { + {0, 256, 26}, + {0, UINT64_MAX, 26}, + {20, 90, 8}, + {99, 999, 16}, + {10000, 100000, 0}, + {200, 100, 0}, + }; + + for (size_t i = 0; i < ARRAY_SIZE(iterate_params); i++) { + int count = 0; + trie_iterate_keys(t, iterate_params[i].start, iterate_params[i].end, iterate_fn, &count); + assert_equals("iteration count", iterate_params[i].expected_count, count); + } +} + +struct key_value_pair { + uint64_t key, value; +}; + +static void +test_trie_get(void) +{ + static const struct { + uint8_t key_size; + uint8_t item_size_lg; + uint8_t node_key_bits; + uint8_t data_block_key_bits; + uint64_t empty_value; + + struct key_value_pair set_values[3], get_values[3]; + } params[] = { + {64, 6, 10, 10, 0, + {{300, 1}, {0xfacefeed, 0xabcdef123456}, {-1ULL, -1ULL}}, + {{301, 0}, {0xfacefeed, 0xabcdef123456}, {-1ULL, -1ULL}}}, + {8, 2, 4, 4, 10, + {{0xab, 0xcd}, {0xface, 2}, {0, 3}}, + {{0xab, 0xd}, {0xface, 10}, {0, 3}}}, + {30, 0, 6, 3, -1, + {{0xaaaa, 127}, {0xface, 0}, {0, 0}}, + {{0xaaaa, 1}, {0xface, 0}, {1, 1}}}, + {16, 4, 5, 11, 0xffffff, + {{0xabcdef, 42}, {0xabcd, 42}, {0xffff, 0}}, + {{0xabcdef, 0xffff}, {0xabcd, 42}, {0xffff, 0}}}, + {41, 5, 1, 1, -1, + {{0xabcdef01, 0x22222222}, {-1, 0x33333333}, {10, 10}}, + {{0xabcdef01, 0x22222222}, {-1, 0xffffffff}, {10, 10}}}, + }; + + for (size_t i = 0; i < ARRAY_SIZE(params); i++) { + struct trie *t = trie_create(params[i].key_size, + params[i].item_size_lg, + params[i].node_key_bits, + params[i].data_block_key_bits, + params[i].empty_value); + + if (!t) + error_msg_and_fail("trie creation failed"); + + for (size_t j = 0; j < ARRAY_SIZE(params[i].set_values); j++) { + struct key_value_pair kv = params[i].set_values[j]; + trie_set(t, kv.key, kv.value); + } + for (size_t j = 0; j < ARRAY_SIZE(params[i].get_values); j++) { + struct key_value_pair kv = params[i].get_values[j]; + assert_equals("trie_get", kv.value, trie_get(t, kv.key)); + } + + trie_free(t); + } +} + +int +main(void) +{ + test_trie_get(); + test_trie_iterate_fn(); + return 0; +} diff --git a/tests/xet_robust_list--pidns-translation.c b/tests/xet_robust_list--pidns-translation.c new file mode 100644 index 00000000..e0477267 --- /dev/null +++ b/tests/xet_robust_list--pidns-translation.c @@ -0,0 +1,2 @@ +#define PIDNS_TRANSLATION +#include "xet_robust_list.c" diff --git a/tests/xet_robust_list.c b/tests/xet_robust_list.c index 43239c8b..b5751b0a 100644 --- a/tests/xet_robust_list.c +++ b/tests/xet_robust_list.c @@ -8,6 +8,7 @@ #include "tests.h" #include "scno.h" +#include "pidns.h" #if defined __NR_get_robust_list && defined __NR_set_robust_list @@ -30,27 +31,36 @@ sprintaddr(void *addr) int main(void) { + PIDNS_TEST_INIT; + const pid_t pid = getpid(); + const char *pid_str = pidns_pid2str(PT_TGID); const long long_pid = (unsigned long) (0xdeadbeef00000000LL | pid); TAIL_ALLOC_OBJECT_CONST_PTR(void *, p_head); TAIL_ALLOC_OBJECT_CONST_PTR(size_t, p_len); if (syscall(__NR_get_robust_list, long_pid, p_head, p_len)) perror_msg_and_skip("get_robust_list"); - printf("get_robust_list(%d, [%s], [%lu]) = 0\n", - (int) pid, sprintaddr(*p_head), (unsigned long) *p_len); + pidns_print_leader(); + printf("get_robust_list(%d%s, [%s], [%lu]) = 0\n", + pid, pid_str, sprintaddr(*p_head), + (unsigned long) *p_len); void *head = tail_alloc(*p_len); if (syscall(__NR_set_robust_list, head, *p_len)) perror_msg_and_skip("set_robust_list"); + pidns_print_leader(); printf("set_robust_list(%p, %lu) = 0\n", head, (unsigned long) *p_len); if (syscall(__NR_get_robust_list, long_pid, p_head, p_len)) perror_msg_and_skip("get_robust_list"); - printf("get_robust_list(%d, [%s], [%lu]) = 0\n", - (int) pid, sprintaddr(*p_head), (unsigned long) *p_len); + pidns_print_leader(); + printf("get_robust_list(%d%s, [%s], [%lu]) = 0\n", + pid, pid_str, sprintaddr(*p_head), + (unsigned long) *p_len); + pidns_print_leader(); puts("+++ exited with 0 +++"); return 0; } diff --git a/tests/xetpgid--pidns-translation.c b/tests/xetpgid--pidns-translation.c new file mode 100644 index 00000000..b6469628 --- /dev/null +++ b/tests/xetpgid--pidns-translation.c @@ -0,0 +1,2 @@ +#define PIDNS_TRANSLATION +#include "xetpgid.c" diff --git a/tests/xetpgid.c b/tests/xetpgid.c index 9b070af2..411edfc7 100644 --- a/tests/xetpgid.c +++ b/tests/xetpgid.c @@ -10,6 +10,7 @@ #include "tests.h" #include "scno.h" +#include "pidns.h" #if defined __NR_getpgid && defined __NR_setpgid @@ -19,13 +20,21 @@ int main(void) { - const int pid = getpid(); - long rc = syscall(__NR_getpgid, F8ILL_KULONG_MASK | pid); - printf("getpgid(%d) = %ld\n", pid, rc); - - rc = syscall(__NR_setpgid, F8ILL_KULONG_MASK, F8ILL_KULONG_MASK | pid); - printf("setpgid(0, %d) = %ld\n", pid, rc); + PIDNS_TEST_INIT; + const int pid = getpid(); + long pgid = syscall(__NR_getpgid, F8ILL_KULONG_MASK | pid); + pidns_print_leader(); + printf("getpgid(%d%s) = %ld%s\n", pid, pidns_pid2str(PT_TGID), + pgid, pidns_pid2str(PT_PGID)); + + long rc = syscall(__NR_setpgid, F8ILL_KULONG_MASK, + F8ILL_KULONG_MASK | pgid); + pidns_print_leader(); + printf("setpgid(0, %ld%s) = %s\n", pgid, pidns_pid2str(PT_PGID), + sprintrc(rc)); + + pidns_print_leader(); puts("+++ exited with 0 +++"); return 0; } diff --git a/tests/xetpriority--pidns-translation.c b/tests/xetpriority--pidns-translation.c new file mode 100644 index 00000000..c93669cb --- /dev/null +++ b/tests/xetpriority--pidns-translation.c @@ -0,0 +1,2 @@ +#define PIDNS_TRANSLATION +#include "xetpriority.c" diff --git a/tests/xetpriority.c b/tests/xetpriority.c index 2d61bd10..dd38217d 100644 --- a/tests/xetpriority.c +++ b/tests/xetpriority.c @@ -7,6 +7,7 @@ #include "tests.h" #include "scno.h" +#include "pidns.h" #if defined __NR_getpriority && defined __NR_setpriority @@ -17,15 +18,30 @@ int main(void) { + PIDNS_TEST_INIT; + const int pid = getpid(); + const int pgid = getpgid(0); + long rc = syscall(__NR_getpriority, PRIO_PROCESS, F8ILL_KULONG_MASK | pid); - printf("getpriority(PRIO_PROCESS, %d) = %ld\n", pid, rc); + pidns_print_leader(); + printf("getpriority(PRIO_PROCESS, %d%s) = %ld\n", + pid, pidns_pid2str(PT_TGID), rc); rc = syscall(__NR_setpriority, PRIO_PROCESS, F8ILL_KULONG_MASK | pid, F8ILL_KULONG_MASK); - printf("setpriority(PRIO_PROCESS, %d, 0) = %s\n", pid, sprintrc(rc)); + pidns_print_leader(); + printf("setpriority(PRIO_PROCESS, %d%s, 0) = %s\n", + pid, pidns_pid2str(PT_TGID), sprintrc(rc)); + + rc = syscall(__NR_getpriority, PRIO_PGRP, + F8ILL_KULONG_MASK | pgid); + pidns_print_leader(); + printf("getpriority(PRIO_PGRP, %d%s) = %ld\n", + pgid, pidns_pid2str(PT_PGID), rc); + pidns_print_leader(); puts("+++ exited with 0 +++"); return 0; } diff --git a/tests/xmalloc_for_tests.c b/tests/xmalloc_for_tests.c new file mode 100644 index 00000000..5c496adb --- /dev/null +++ b/tests/xmalloc_for_tests.c @@ -0,0 +1,2 @@ +#define error_msg_and_die error_msg_and_fail +#include "xmalloc.c" -- 2.28.0 From ldv at altlinux.org Sun Aug 23 22:36:09 2020 From: ldv at altlinux.org (Dmitry V. Levin) Date: Mon, 24 Aug 2020 01:36:09 +0300 Subject: [PATCH v11 5/5] Add tests for PID namespace translation In-Reply-To: <20200823222555.1224386-6-uzonyi.akos@gmail.com> References: <20200823222555.1224386-1-uzonyi.akos@gmail.com> <20200823222555.1224386-6-uzonyi.akos@gmail.com> Message-ID: <20200823223609.GC6850@altlinux.org> On Mon, Aug 24, 2020 at 12:25:55AM +0200, ?kos Uzonyi wrote: [...] > --- a/tests/Makefile.am > +++ b/tests/Makefile.am > @@ -66,6 +66,8 @@ libtests_a_SOURCES = \ > test_ucopy.h \ > tests.h \ > tprintf.c \ > + trie_for_tests.c \ > + xmalloc_for_tests.c \ > # end of libtests_a_SOURCES > libtests_a_CPPFLAGS = $(AM_CPPFLAGS) -D_FILE_OFFSET_BITS=64 > check_LIBRARIES = libtests.a Why are you adding trie_for_tests.c to libtests_a_SOURCES? If I understand correctly, ... > +trie_test_SOURCES = trie_test.c trie_for_tests.c > +trie_test_CPPFLAGS = $(AM_CPPFLAGS) $(CODE_COVERAGE_CPPFLAGS) > +trie_test_CFLAGS = $(AM_CFLAGS) $(CODE_COVERAGE_CFLAGS) > +trie_test_LDADD = $(LDADD) $(CODE_COVERAGE_LIBS) ... trie_for_tests.c is needed only in trie_test_SOURCES. -- ldv From uzonyi.akos at gmail.com Mon Aug 24 07:31:53 2020 From: uzonyi.akos at gmail.com (=?UTF-8?B?w4Frb3MgVXpvbnlp?=) Date: Mon, 24 Aug 2020 09:31:53 +0200 Subject: [PATCH v11 5/5] Add tests for PID namespace translation In-Reply-To: <20200823223609.GC6850@altlinux.org> References: <20200823222555.1224386-1-uzonyi.akos@gmail.com> <20200823222555.1224386-6-uzonyi.akos@gmail.com> <20200823223609.GC6850@altlinux.org> Message-ID: On Mon, 24 Aug 2020 at 00:36, Dmitry V. Levin wrote: > On Mon, Aug 24, 2020 at 12:25:55AM +0200, ?kos Uzonyi wrote: > [...] > > --- a/tests/Makefile.am > > +++ b/tests/Makefile.am > > @@ -66,6 +66,8 @@ libtests_a_SOURCES = \ > > test_ucopy.h \ > > tests.h \ > > tprintf.c \ > > + trie_for_tests.c \ > > + xmalloc_for_tests.c \ > > # end of libtests_a_SOURCES > > libtests_a_CPPFLAGS = $(AM_CPPFLAGS) -D_FILE_OFFSET_BITS=64 > > check_LIBRARIES = libtests.a > > Why are you adding trie_for_tests.c to libtests_a_SOURCES? > If I understand correctly, ... > > > +trie_test_SOURCES = trie_test.c trie_for_tests.c > > +trie_test_CPPFLAGS = $(AM_CPPFLAGS) $(CODE_COVERAGE_CPPFLAGS) > > +trie_test_CFLAGS = $(AM_CFLAGS) $(CODE_COVERAGE_CFLAGS) > > +trie_test_LDADD = $(LDADD) $(CODE_COVERAGE_LIBS) > > ... trie_for_tests.c is needed only in trie_test_SOURCES. Yes, it shouldn't be added to libtests_a_SOURCES, I overlooked this fact during conflict resolution. From uzonyi.akos at gmail.com Mon Aug 24 17:26:40 2020 From: uzonyi.akos at gmail.com (=?UTF-8?B?w4Frb3MgVXpvbnlp?=) Date: Mon, 24 Aug 2020 19:26:40 +0200 Subject: [GSoC] Final evaluation URL Message-ID: Hi, I'll submit the following URL for the final evaluation: https://akosuzonyi.github.io/strace/ Please have a look at this page, and if you have any comments, let me know. Thanks, ?kos From ldv at altlinux.org Mon Aug 24 17:39:59 2020 From: ldv at altlinux.org (Dmitry V. Levin) Date: Mon, 24 Aug 2020 20:39:59 +0300 Subject: [PATCH v11 0/5] [PIDNS] Final In-Reply-To: <20200823222555.1224386-1-uzonyi.akos@gmail.com> References: <20200823222555.1224386-1-uzonyi.akos@gmail.com> Message-ID: <20200824173959.GR18193@altlinux.org> On Mon, Aug 24, 2020 at 12:25:50AM +0200, ?kos Uzonyi wrote: > From: Uzonyi ?kos > > Changes in v11: > - trie_iterate_keys: handle if "end" is larger than max key > - pidns.c: fix end argument of trie_iterate_keys > - trie_test: test trie_iterate_keys too > - Do not print error message if 0 found in id list > - is_proc_ours: return true if id count is 0 > - Use xcalloc in trie.c > - Add coverage support for trie.c when tested by trie_test > - Add check if unshare -Urpf true works > - define CLONE_NEW* macros, if not defined > - tests/fork--pidns-translation.c: include "nsfs.h" > - tests/pidns-cache.test: remove require_min_kernel_version_or_skip > - Reorder some or conditions > - translate_id_proc_pid: make the code a little bit cleaner > - pidns.c: Improve some comments a bit Thanks. As far as I can tell, there are no build regressions anymore. If anybody else has any comments about this patchset, it's perhaps the last moment to make them known before the series is merged. -- ldv From uzonyi.akos at gmail.com Mon Aug 24 18:00:27 2020 From: uzonyi.akos at gmail.com (=?UTF-8?B?w4Frb3MgVXpvbnlp?=) Date: Mon, 24 Aug 2020 20:00:27 +0200 Subject: [RFC PATCH 0/4] [PIDNS] Trie and pidns-cache tests In-Reply-To: <20200823215513.GA6213@altlinux.org> References: <20200815124129.GB30941@altlinux.org> <20200815162710.GD376@altlinux.org> <20200817231248.GA5522@altlinux.org> <20200817234448.GD5522@altlinux.org> <20200822223615.GB23834@altlinux.org> <20200823215513.GA6213@altlinux.org> Message-ID: On Sun, 23 Aug 2020 at 23:55, Dmitry V. Levin wrote: > On Sun, Aug 23, 2020 at 11:30:37PM +0200, ?kos Uzonyi wrote: > > On Sun, 23 Aug 2020 at 00:36, Dmitry V. Levin wrote: > > > OK, I've found a way to work this around and squeeze some coverage > > > out of the test, feel free to squash it in: > > > > > > diff --git a/Makefile.am b/Makefile.am > > > index f4bd0e0d9..f79d93437 100644 > > > --- a/Makefile.am > > > +++ b/Makefile.am > > > @@ -409,7 +409,7 @@ endif > > > CODE_COVERAGE_BRANCH_COVERAGE = 1 > > > CODE_COVERAGE_GENHTML_OPTIONS = $(CODE_COVERAGE_GENHTML_OPTIONS_DEFAULT) \ > > > --prefix $(shell cd $(abs_top_srcdir)/.. && pwd || echo .) > > > -CODE_COVERAGE_IGNORE_PATTERN = '/usr/include/*' > > > +CODE_COVERAGE_IGNORE_PATTERN = '/usr/include/*' '*/tests/*' '*/tests-m32/*' '*/tests-mx32/*' > > > strace_CPPFLAGS += $(CODE_COVERAGE_CPPFLAGS) > > > strace_CFLAGS += $(CODE_COVERAGE_CFLAGS) > > > strace_LDADD += $(CODE_COVERAGE_LIBS) > > > diff --git a/tests/Makefile.am b/tests/Makefile.am > > > index 39d948cf4..56e0e8eea 100644 > > > --- a/tests/Makefile.am > > > +++ b/tests/Makefile.am > > > @@ -66,7 +66,6 @@ libtests_a_SOURCES = \ > > > test_ucopy.h \ > > > tests.h \ > > > tprintf.c \ > > > - trie.c \ > > > # end of libtests_a_SOURCES > > > libtests_a_CPPFLAGS = $(AM_CPPFLAGS) -D_FILE_OFFSET_BITS=64 > > > check_LIBRARIES = libtests.a > > > @@ -308,6 +307,11 @@ stack_fcall_mangled_SOURCES = stack-fcall-mangled.c \ > > > stack-fcall-mangled-0.c stack-fcall-mangled-1.c \ > > > stack-fcall-mangled-2.c stack-fcall-mangled-3.c > > > > > > +trie_test_SOURCES = trie_test.c trie_for_tests.c > > > +trie_test_CPPFLAGS = $(AM_CPPFLAGS) $(CODE_COVERAGE_CPPFLAGS) > > > +trie_test_CFLAGS = $(AM_CFLAGS) $(CODE_COVERAGE_CFLAGS) > > > +trie_test_LDADD = $(LDADD) $(CODE_COVERAGE_LIBS) > > > + > > > include gen_tests.am > > > > > > if ENABLE_STACKTRACE > > > diff --git a/tests/trie.c b/tests/trie.c > > > deleted file mode 120000 > > > index 0dd9cab45..000000000 > > > --- a/tests/trie.c > > > +++ /dev/null > > > @@ -1 +0,0 @@ > > > -../trie.c > > > \ No newline at end of file > > > diff --git a/tests/trie_for_tests.c b/tests/trie_for_tests.c > > > new file mode 100644 > > > index 000000000..13e564c4f > > > --- /dev/null > > > +++ b/tests/trie_for_tests.c > > > @@ -0,0 +1 @@ > > > +#include "trie.c" > > > > I didn't know very well how this code coverage is configured, so thank > > you for helping with this. > > The idea was to compile tests/trie_for_tests.c (which is trie.c) along > with the test with coverage options. For this reason I had to take > tests/trie_for_tests.c out of libtests_a_SOURCES and convert it from a > symlink into a real file so that the original trie.c is covered instead of > a symlinked file. Yes, after reading the patch, I understood the main concept, but it would have taken a lot of time to come up with this myself :). However the codecov result [1] of my last commit (which includes the patch above) still shows that trie_free is not covered. I'm not sure what's causing this, as trie_free is called in trie_test. [1] https://codecov.io/gh/AkosUzonyi/strace/src/6b0f5cf5aa6ac8473e64a1f9d7f9430a8356e410/trie.c From ldv at altlinux.org Mon Aug 24 18:07:20 2020 From: ldv at altlinux.org (Dmitry V. Levin) Date: Mon, 24 Aug 2020 21:07:20 +0300 Subject: [RFC PATCH 0/4] [PIDNS] Trie and pidns-cache tests In-Reply-To: References: <20200815162710.GD376@altlinux.org> <20200817231248.GA5522@altlinux.org> <20200817234448.GD5522@altlinux.org> <20200822223615.GB23834@altlinux.org> <20200823215513.GA6213@altlinux.org> Message-ID: <20200824180720.GT18193@altlinux.org> On Mon, Aug 24, 2020 at 08:00:27PM +0200, ?kos Uzonyi wrote: > On Sun, 23 Aug 2020 at 23:55, Dmitry V. Levin wrote: > > On Sun, Aug 23, 2020 at 11:30:37PM +0200, ?kos Uzonyi wrote: > > > On Sun, 23 Aug 2020 at 00:36, Dmitry V. Levin wrote: > > > > OK, I've found a way to work this around and squeeze some coverage > > > > out of the test, feel free to squash it in: > > > > > > > > diff --git a/Makefile.am b/Makefile.am > > > > index f4bd0e0d9..f79d93437 100644 > > > > --- a/Makefile.am > > > > +++ b/Makefile.am > > > > @@ -409,7 +409,7 @@ endif > > > > CODE_COVERAGE_BRANCH_COVERAGE = 1 > > > > CODE_COVERAGE_GENHTML_OPTIONS = $(CODE_COVERAGE_GENHTML_OPTIONS_DEFAULT) \ > > > > --prefix $(shell cd $(abs_top_srcdir)/.. && pwd || echo .) > > > > -CODE_COVERAGE_IGNORE_PATTERN = '/usr/include/*' > > > > +CODE_COVERAGE_IGNORE_PATTERN = '/usr/include/*' '*/tests/*' '*/tests-m32/*' '*/tests-mx32/*' > > > > strace_CPPFLAGS += $(CODE_COVERAGE_CPPFLAGS) > > > > strace_CFLAGS += $(CODE_COVERAGE_CFLAGS) > > > > strace_LDADD += $(CODE_COVERAGE_LIBS) > > > > diff --git a/tests/Makefile.am b/tests/Makefile.am > > > > index 39d948cf4..56e0e8eea 100644 > > > > --- a/tests/Makefile.am > > > > +++ b/tests/Makefile.am > > > > @@ -66,7 +66,6 @@ libtests_a_SOURCES = \ > > > > test_ucopy.h \ > > > > tests.h \ > > > > tprintf.c \ > > > > - trie.c \ > > > > # end of libtests_a_SOURCES > > > > libtests_a_CPPFLAGS = $(AM_CPPFLAGS) -D_FILE_OFFSET_BITS=64 > > > > check_LIBRARIES = libtests.a > > > > @@ -308,6 +307,11 @@ stack_fcall_mangled_SOURCES = stack-fcall-mangled.c \ > > > > stack-fcall-mangled-0.c stack-fcall-mangled-1.c \ > > > > stack-fcall-mangled-2.c stack-fcall-mangled-3.c > > > > > > > > +trie_test_SOURCES = trie_test.c trie_for_tests.c > > > > +trie_test_CPPFLAGS = $(AM_CPPFLAGS) $(CODE_COVERAGE_CPPFLAGS) > > > > +trie_test_CFLAGS = $(AM_CFLAGS) $(CODE_COVERAGE_CFLAGS) > > > > +trie_test_LDADD = $(LDADD) $(CODE_COVERAGE_LIBS) > > > > + > > > > include gen_tests.am > > > > > > > > if ENABLE_STACKTRACE > > > > diff --git a/tests/trie.c b/tests/trie.c > > > > deleted file mode 120000 > > > > index 0dd9cab45..000000000 > > > > --- a/tests/trie.c > > > > +++ /dev/null > > > > @@ -1 +0,0 @@ > > > > -../trie.c > > > > \ No newline at end of file > > > > diff --git a/tests/trie_for_tests.c b/tests/trie_for_tests.c > > > > new file mode 100644 > > > > index 000000000..13e564c4f > > > > --- /dev/null > > > > +++ b/tests/trie_for_tests.c > > > > @@ -0,0 +1 @@ > > > > +#include "trie.c" > > > > > > I didn't know very well how this code coverage is configured, so thank > > > you for helping with this. > > > > The idea was to compile tests/trie_for_tests.c (which is trie.c) along > > with the test with coverage options. For this reason I had to take > > tests/trie_for_tests.c out of libtests_a_SOURCES and convert it from a > > symlink into a real file so that the original trie.c is covered instead of > > a symlinked file. > > Yes, after reading the patch, I understood the main concept, but it > would have taken a lot of time to come up with this myself :). > > However the codecov result [1] of my last commit (which includes the > patch above) still shows that trie_free is not covered. I'm not sure > what's causing this, as trie_free is called in trie_test. > > [1] https://codecov.io/gh/AkosUzonyi/strace/src/6b0f5cf5aa6ac8473e64a1f9d7f9430a8356e410/trie.c Hmm, locally lcov says that 100% of trie.c is covered now. -- ldv From uzonyi.akos at gmail.com Mon Aug 24 18:52:01 2020 From: uzonyi.akos at gmail.com (=?UTF-8?B?w4Frb3MgVXpvbnlp?=) Date: Mon, 24 Aug 2020 20:52:01 +0200 Subject: [RFC PATCH 0/4] [PIDNS] Trie and pidns-cache tests In-Reply-To: <20200824180720.GT18193@altlinux.org> References: <20200815162710.GD376@altlinux.org> <20200817231248.GA5522@altlinux.org> <20200817234448.GD5522@altlinux.org> <20200822223615.GB23834@altlinux.org> <20200823215513.GA6213@altlinux.org> <20200824180720.GT18193@altlinux.org> Message-ID: On Mon, 24 Aug 2020 at 20:07, Dmitry V. Levin wrote: > On Mon, Aug 24, 2020 at 08:00:27PM +0200, ?kos Uzonyi wrote: > > On Sun, 23 Aug 2020 at 23:55, Dmitry V. Levin wrote: > > > On Sun, Aug 23, 2020 at 11:30:37PM +0200, ?kos Uzonyi wrote: > > > > On Sun, 23 Aug 2020 at 00:36, Dmitry V. Levin wrote: > > > > > OK, I've found a way to work this around and squeeze some coverage > > > > > out of the test, feel free to squash it in: > > > > > > > > > > diff --git a/Makefile.am b/Makefile.am > > > > > index f4bd0e0d9..f79d93437 100644 > > > > > --- a/Makefile.am > > > > > +++ b/Makefile.am > > > > > @@ -409,7 +409,7 @@ endif > > > > > CODE_COVERAGE_BRANCH_COVERAGE = 1 > > > > > CODE_COVERAGE_GENHTML_OPTIONS = $(CODE_COVERAGE_GENHTML_OPTIONS_DEFAULT) \ > > > > > --prefix $(shell cd $(abs_top_srcdir)/.. && pwd || echo .) > > > > > -CODE_COVERAGE_IGNORE_PATTERN = '/usr/include/*' > > > > > +CODE_COVERAGE_IGNORE_PATTERN = '/usr/include/*' '*/tests/*' '*/tests-m32/*' '*/tests-mx32/*' > > > > > strace_CPPFLAGS += $(CODE_COVERAGE_CPPFLAGS) > > > > > strace_CFLAGS += $(CODE_COVERAGE_CFLAGS) > > > > > strace_LDADD += $(CODE_COVERAGE_LIBS) > > > > > diff --git a/tests/Makefile.am b/tests/Makefile.am > > > > > index 39d948cf4..56e0e8eea 100644 > > > > > --- a/tests/Makefile.am > > > > > +++ b/tests/Makefile.am > > > > > @@ -66,7 +66,6 @@ libtests_a_SOURCES = \ > > > > > test_ucopy.h \ > > > > > tests.h \ > > > > > tprintf.c \ > > > > > - trie.c \ > > > > > # end of libtests_a_SOURCES > > > > > libtests_a_CPPFLAGS = $(AM_CPPFLAGS) -D_FILE_OFFSET_BITS=64 > > > > > check_LIBRARIES = libtests.a > > > > > @@ -308,6 +307,11 @@ stack_fcall_mangled_SOURCES = stack-fcall-mangled.c \ > > > > > stack-fcall-mangled-0.c stack-fcall-mangled-1.c \ > > > > > stack-fcall-mangled-2.c stack-fcall-mangled-3.c > > > > > > > > > > +trie_test_SOURCES = trie_test.c trie_for_tests.c > > > > > +trie_test_CPPFLAGS = $(AM_CPPFLAGS) $(CODE_COVERAGE_CPPFLAGS) > > > > > +trie_test_CFLAGS = $(AM_CFLAGS) $(CODE_COVERAGE_CFLAGS) > > > > > +trie_test_LDADD = $(LDADD) $(CODE_COVERAGE_LIBS) > > > > > + > > > > > include gen_tests.am > > > > > > > > > > if ENABLE_STACKTRACE > > > > > diff --git a/tests/trie.c b/tests/trie.c > > > > > deleted file mode 120000 > > > > > index 0dd9cab45..000000000 > > > > > --- a/tests/trie.c > > > > > +++ /dev/null > > > > > @@ -1 +0,0 @@ > > > > > -../trie.c > > > > > \ No newline at end of file > > > > > diff --git a/tests/trie_for_tests.c b/tests/trie_for_tests.c > > > > > new file mode 100644 > > > > > index 000000000..13e564c4f > > > > > --- /dev/null > > > > > +++ b/tests/trie_for_tests.c > > > > > @@ -0,0 +1 @@ > > > > > +#include "trie.c" > > > > > > > > I didn't know very well how this code coverage is configured, so thank > > > > you for helping with this. > > > > > > The idea was to compile tests/trie_for_tests.c (which is trie.c) along > > > with the test with coverage options. For this reason I had to take > > > tests/trie_for_tests.c out of libtests_a_SOURCES and convert it from a > > > symlink into a real file so that the original trie.c is covered instead of > > > a symlinked file. > > > > Yes, after reading the patch, I understood the main concept, but it > > would have taken a lot of time to come up with this myself :). > > > > However the codecov result [1] of my last commit (which includes the > > patch above) still shows that trie_free is not covered. I'm not sure > > what's causing this, as trie_free is called in trie_test. > > > > [1] https://codecov.io/gh/AkosUzonyi/strace/src/6b0f5cf5aa6ac8473e64a1f9d7f9430a8356e410/trie.c > > Hmm, locally lcov says that 100% of trie.c is covered now. OK, fine, then it's just some problem in codecov. From uzonyi.akos at gmail.com Mon Aug 24 20:36:44 2020 From: uzonyi.akos at gmail.com (=?UTF-8?B?w4Frb3MgVXpvbnlp?=) Date: Mon, 24 Aug 2020 22:36:44 +0200 Subject: [RFC PATCH v9 0/8] [PIDNS] Final In-Reply-To: <20200817233850.GC5522@altlinux.org> References: <20200816221851.200031-1-uzonyi.akos@gmail.com> <20200817233850.GC5522@altlinux.org> Message-ID: On Tue, 18 Aug 2020 at 01:38, Dmitry V. Levin wrote: > On Mon, Aug 17, 2020 at 12:18:43AM +0200, ?kos Uzonyi wrote: > > The travis build [1] unfortunately shows some errors. On ppc mknod test fails, > > but I have no idea why. Mknod is unrelated to my code. Do you have any idea? > > Something is broken in their ppc system: apparently, they allow the mknod > syscall to exit without an error in cases where is must fail with EEXIST > because the target file already exists. This violates the contract: > "If pathname already exists, or is a symbolic link, this call fails with > an EEXIST error." I suppose they use some kind of mknod interception, > and it doesn't implement the expected semantics. > > We can either come up with a workaround or report a bug and let them fix it. I reported this bug on Travis CI Community Forums [1]. [1] https://travis-ci.community/t/syscall-mknod-is-incorrectly-successful-on-ppc-systems/9713 From uzonyi.akos at gmail.com Tue Aug 25 12:54:13 2020 From: uzonyi.akos at gmail.com (=?UTF-8?q?=C3=81kos=20Uzonyi?=) Date: Tue, 25 Aug 2020 14:54:13 +0200 Subject: [PATCH] tests/mknod.c: add workaround for ppc bug in travis Message-ID: <20200825125413.1282325-1-uzonyi.akos@gmail.com> On ppc travis builds syscall(mknod) sometimes does not fail with EEXISTS as expected, but returns successfully. A new print_errno function is added, which handles the case when errno is 0. * tests/errno2name.c (print_errno): New function. * tests/defs.h (errno2name.c): New function declaration. * tests/mknod.c (call_mknod): set errno to 0 before syscall. (main): Use print_errno for printing errno. --- tests/errno2name.c | 9 +++++++++ tests/mknod.c | 42 ++++++++++++++++++++++++++---------------- tests/tests.h | 8 ++++++++ 3 files changed, 43 insertions(+), 16 deletions(-) diff --git a/tests/errno2name.c b/tests/errno2name.c index 56340d75..103ea08d 100644 --- a/tests/errno2name.c +++ b/tests/errno2name.c @@ -8,6 +8,15 @@ #include "tests.h" #include +#include + +void +print_errno(void) +{ + if (errno) + printf(" %s (%m)", errno2name()); + puts(""); +} #define CASE(x) case x: return #x diff --git a/tests/mknod.c b/tests/mknod.c index 44c6f028..03cb8ef2 100644 --- a/tests/mknod.c +++ b/tests/mknod.c @@ -10,6 +10,7 @@ #ifdef __NR_mknod +# include # include # include # include @@ -20,6 +21,7 @@ static const char *sample; static long call_mknod(unsigned short mode, unsigned long dev) { + errno = 0; unsigned long lmode = (unsigned long) 0xffffffffffff0000ULL | mode; return syscall(__NR_mknod, sample, lmode, dev); } @@ -31,44 +33,52 @@ main(int ac, char **av) sample = av[0]; long rc = call_mknod(0, dev); - printf("mknod(\"%s\", 000) = %ld %s (%m)\n", - sample, rc, errno2name()); + printf("mknod(\"%s\", 000) = %ld", + sample, rc); + print_errno(); rc = call_mknod(0xffff, dev); - printf("mknod(\"%s\", %#03ho) = %ld %s (%m)\n", - sample, (unsigned short) -1, rc, errno2name()); + printf("mknod(\"%s\", %#03ho) = %ld", + sample, (unsigned short) -1, rc); + print_errno(); rc = call_mknod(S_IFREG, 0); - printf("mknod(\"%s\", S_IFREG|000) = %ld %s (%m)\n", - sample, rc, errno2name()); + printf("mknod(\"%s\", S_IFREG|000) = %ld", + sample, rc); + print_errno(); rc = call_mknod(S_IFDIR | 06, 0); - printf("mknod(\"%s\", S_IFDIR|006) = %ld %s (%m)\n", - sample, rc, errno2name()); + printf("mknod(\"%s\", S_IFDIR|006) = %ld", + sample, rc); + print_errno(); rc = call_mknod(S_IFLNK | 060, 0); - printf("mknod(\"%s\", S_IFLNK|060) = %ld %s (%m)\n", - sample, rc, errno2name()); + printf("mknod(\"%s\", S_IFLNK|060) = %ld", + sample, rc); + print_errno(); rc = call_mknod(S_IFIFO | 0600, 0); - printf("mknod(\"%s\", S_IFIFO|0600) = %ld %s (%m)\n", - sample, rc, errno2name()); + printf("mknod(\"%s\", S_IFIFO|0600) = %ld", + sample, rc); + print_errno(); dev = (unsigned long) 0xdeadbeef00000000ULL | makedev(1, 7); rc = call_mknod(S_IFCHR | 024, dev); - printf("mknod(\"%s\", S_IFCHR|024, makedev(0x1, 0x7)) = %ld %s (%m)\n", - sample, rc, errno2name()); + printf("mknod(\"%s\", S_IFCHR|024, makedev(0x1, 0x7)) = %ld", + sample, rc); + print_errno(); const unsigned short mode = (0xffff & ~S_IFMT) | S_IFBLK; dev = (unsigned long) 0xdeadbeefbadc0dedULL; rc = call_mknod(mode, dev); printf("mknod(\"%s\", S_IFBLK|S_ISUID|S_ISGID|S_ISVTX|%#03ho" - ", makedev(%#x, %#x)) = %ld %s (%m)\n", + ", makedev(%#x, %#x)) = %ld", sample, (short) (mode & ~(S_IFMT|S_ISUID|S_ISGID|S_ISVTX)), major((unsigned) dev), minor((unsigned) dev), - rc, errno2name()); + rc); + print_errno(); puts("+++ exited with 0 +++"); return 0; diff --git a/tests/tests.h b/tests/tests.h index 66c7f0e6..ad7abec3 100644 --- a/tests/tests.h +++ b/tests/tests.h @@ -267,6 +267,14 @@ void check_overflowgid(const int); /* Translate errno to its name. */ const char *errno2name(void); +/** + * Prints errno name and description with a leading space + * and a trailing newline. + * + * (using the format string: " %s (%m)\n") + */ +void print_errno(void); + /* Translate signal number to its name. */ const char *signal2name(int); -- 2.28.0 From ldv at altlinux.org Tue Aug 25 13:00:14 2020 From: ldv at altlinux.org (Dmitry V. Levin) Date: Tue, 25 Aug 2020 16:00:14 +0300 Subject: [PATCH] tests/mknod.c: add workaround for ppc bug in travis In-Reply-To: <20200825125413.1282325-1-uzonyi.akos@gmail.com> References: <20200825125413.1282325-1-uzonyi.akos@gmail.com> Message-ID: <20200825130014.GA1490@altlinux.org> On Tue, Aug 25, 2020 at 02:54:13PM +0200, ?kos Uzonyi wrote: > On ppc travis builds syscall(mknod) sometimes does not fail with EEXISTS > as expected, but returns successfully. > > A new print_errno function is added, which handles the case when errno > is 0. > > * tests/errno2name.c (print_errno): New function. > * tests/defs.h (errno2name.c): New function declaration. > * tests/mknod.c (call_mknod): set errno to 0 before syscall. > (main): Use print_errno for printing errno. > --- > tests/errno2name.c | 9 +++++++++ > tests/mknod.c | 42 ++++++++++++++++++++++++++---------------- > tests/tests.h | 8 ++++++++ > 3 files changed, 43 insertions(+), 16 deletions(-) > > diff --git a/tests/errno2name.c b/tests/errno2name.c > index 56340d75..103ea08d 100644 > --- a/tests/errno2name.c > +++ b/tests/errno2name.c > @@ -8,6 +8,15 @@ > > #include "tests.h" > #include > +#include > + > +void > +print_errno(void) > +{ > + if (errno) > + printf(" %s (%m)", errno2name()); > + puts(""); > +} > > #define CASE(x) case x: return #x > > diff --git a/tests/mknod.c b/tests/mknod.c > index 44c6f028..03cb8ef2 100644 > --- a/tests/mknod.c > +++ b/tests/mknod.c > @@ -10,6 +10,7 @@ > > #ifdef __NR_mknod > > +# include > # include > # include > # include > @@ -20,6 +21,7 @@ static const char *sample; > static long > call_mknod(unsigned short mode, unsigned long dev) > { > + errno = 0; > unsigned long lmode = (unsigned long) 0xffffffffffff0000ULL | mode; > return syscall(__NR_mknod, sample, lmode, dev); > } > @@ -31,44 +33,52 @@ main(int ac, char **av) > sample = av[0]; > > long rc = call_mknod(0, dev); > - printf("mknod(\"%s\", 000) = %ld %s (%m)\n", > - sample, rc, errno2name()); > + printf("mknod(\"%s\", 000) = %ld", > + sample, rc); > + print_errno(); > > rc = call_mknod(0xffff, dev); > - printf("mknod(\"%s\", %#03ho) = %ld %s (%m)\n", > - sample, (unsigned short) -1, rc, errno2name()); > + printf("mknod(\"%s\", %#03ho) = %ld", > + sample, (unsigned short) -1, rc); > + print_errno(); > > rc = call_mknod(S_IFREG, 0); > - printf("mknod(\"%s\", S_IFREG|000) = %ld %s (%m)\n", > - sample, rc, errno2name()); > + printf("mknod(\"%s\", S_IFREG|000) = %ld", > + sample, rc); > + print_errno(); > > rc = call_mknod(S_IFDIR | 06, 0); > - printf("mknod(\"%s\", S_IFDIR|006) = %ld %s (%m)\n", > - sample, rc, errno2name()); > + printf("mknod(\"%s\", S_IFDIR|006) = %ld", > + sample, rc); > + print_errno(); > > rc = call_mknod(S_IFLNK | 060, 0); > - printf("mknod(\"%s\", S_IFLNK|060) = %ld %s (%m)\n", > - sample, rc, errno2name()); > + printf("mknod(\"%s\", S_IFLNK|060) = %ld", > + sample, rc); > + print_errno(); > > rc = call_mknod(S_IFIFO | 0600, 0); > - printf("mknod(\"%s\", S_IFIFO|0600) = %ld %s (%m)\n", > - sample, rc, errno2name()); > + printf("mknod(\"%s\", S_IFIFO|0600) = %ld", > + sample, rc); > + print_errno(); > > dev = (unsigned long) 0xdeadbeef00000000ULL | makedev(1, 7); > > rc = call_mknod(S_IFCHR | 024, dev); > - printf("mknod(\"%s\", S_IFCHR|024, makedev(0x1, 0x7)) = %ld %s (%m)\n", > - sample, rc, errno2name()); > + printf("mknod(\"%s\", S_IFCHR|024, makedev(0x1, 0x7)) = %ld", > + sample, rc); > + print_errno(); > > const unsigned short mode = (0xffff & ~S_IFMT) | S_IFBLK; > dev = (unsigned long) 0xdeadbeefbadc0dedULL; > > rc = call_mknod(mode, dev); > printf("mknod(\"%s\", S_IFBLK|S_ISUID|S_ISGID|S_ISVTX|%#03ho" > - ", makedev(%#x, %#x)) = %ld %s (%m)\n", > + ", makedev(%#x, %#x)) = %ld", > sample, (short) (mode & ~(S_IFMT|S_ISUID|S_ISGID|S_ISVTX)), > major((unsigned) dev), minor((unsigned) dev), > - rc, errno2name()); > + rc); > + print_errno(); > > puts("+++ exited with 0 +++"); > return 0; We already have (and use) sprintrc, could it be useful here, too? -- ldv From uzonyi.akos at gmail.com Tue Aug 25 13:36:23 2020 From: uzonyi.akos at gmail.com (=?UTF-8?B?w4Frb3MgVXpvbnlp?=) Date: Tue, 25 Aug 2020 15:36:23 +0200 Subject: [PATCH] tests/mknod.c: add workaround for ppc bug in travis In-Reply-To: <20200825130014.GA1490@altlinux.org> References: <20200825125413.1282325-1-uzonyi.akos@gmail.com> <20200825130014.GA1490@altlinux.org> Message-ID: On Tue, 25 Aug 2020 at 15:00, Dmitry V. Levin wrote: > On Tue, Aug 25, 2020 at 02:54:13PM +0200, ?kos Uzonyi wrote: > > On ppc travis builds syscall(mknod) sometimes does not fail with EEXISTS > > as expected, but returns successfully. > > > > A new print_errno function is added, which handles the case when errno > > is 0. > > > > * tests/errno2name.c (print_errno): New function. > > * tests/defs.h (errno2name.c): New function declaration. > > * tests/mknod.c (call_mknod): set errno to 0 before syscall. > > (main): Use print_errno for printing errno. > > --- > > tests/errno2name.c | 9 +++++++++ > > tests/mknod.c | 42 ++++++++++++++++++++++++++---------------- > > tests/tests.h | 8 ++++++++ > > 3 files changed, 43 insertions(+), 16 deletions(-) > > > > diff --git a/tests/errno2name.c b/tests/errno2name.c > > index 56340d75..103ea08d 100644 > > --- a/tests/errno2name.c > > +++ b/tests/errno2name.c > > @@ -8,6 +8,15 @@ > > > > #include "tests.h" > > #include > > +#include > > + > > +void > > +print_errno(void) > > +{ > > + if (errno) > > + printf(" %s (%m)", errno2name()); > > + puts(""); > > +} > > > > #define CASE(x) case x: return #x > > > > diff --git a/tests/mknod.c b/tests/mknod.c > > index 44c6f028..03cb8ef2 100644 > > --- a/tests/mknod.c > > +++ b/tests/mknod.c > > @@ -10,6 +10,7 @@ > > > > #ifdef __NR_mknod > > > > +# include > > # include > > # include > > # include > > @@ -20,6 +21,7 @@ static const char *sample; > > static long > > call_mknod(unsigned short mode, unsigned long dev) > > { > > + errno = 0; > > unsigned long lmode = (unsigned long) 0xffffffffffff0000ULL | mode; > > return syscall(__NR_mknod, sample, lmode, dev); > > } > > @@ -31,44 +33,52 @@ main(int ac, char **av) > > sample = av[0]; > > > > long rc = call_mknod(0, dev); > > - printf("mknod(\"%s\", 000) = %ld %s (%m)\n", > > - sample, rc, errno2name()); > > + printf("mknod(\"%s\", 000) = %ld", > > + sample, rc); > > + print_errno(); > > > > rc = call_mknod(0xffff, dev); > > - printf("mknod(\"%s\", %#03ho) = %ld %s (%m)\n", > > - sample, (unsigned short) -1, rc, errno2name()); > > + printf("mknod(\"%s\", %#03ho) = %ld", > > + sample, (unsigned short) -1, rc); > > + print_errno(); > > > > rc = call_mknod(S_IFREG, 0); > > - printf("mknod(\"%s\", S_IFREG|000) = %ld %s (%m)\n", > > - sample, rc, errno2name()); > > + printf("mknod(\"%s\", S_IFREG|000) = %ld", > > + sample, rc); > > + print_errno(); > > > > rc = call_mknod(S_IFDIR | 06, 0); > > - printf("mknod(\"%s\", S_IFDIR|006) = %ld %s (%m)\n", > > - sample, rc, errno2name()); > > + printf("mknod(\"%s\", S_IFDIR|006) = %ld", > > + sample, rc); > > + print_errno(); > > > > rc = call_mknod(S_IFLNK | 060, 0); > > - printf("mknod(\"%s\", S_IFLNK|060) = %ld %s (%m)\n", > > - sample, rc, errno2name()); > > + printf("mknod(\"%s\", S_IFLNK|060) = %ld", > > + sample, rc); > > + print_errno(); > > > > rc = call_mknod(S_IFIFO | 0600, 0); > > - printf("mknod(\"%s\", S_IFIFO|0600) = %ld %s (%m)\n", > > - sample, rc, errno2name()); > > + printf("mknod(\"%s\", S_IFIFO|0600) = %ld", > > + sample, rc); > > + print_errno(); > > > > dev = (unsigned long) 0xdeadbeef00000000ULL | makedev(1, 7); > > > > rc = call_mknod(S_IFCHR | 024, dev); > > - printf("mknod(\"%s\", S_IFCHR|024, makedev(0x1, 0x7)) = %ld %s (%m)\n", > > - sample, rc, errno2name()); > > + printf("mknod(\"%s\", S_IFCHR|024, makedev(0x1, 0x7)) = %ld", > > + sample, rc); > > + print_errno(); > > > > const unsigned short mode = (0xffff & ~S_IFMT) | S_IFBLK; > > dev = (unsigned long) 0xdeadbeefbadc0dedULL; > > > > rc = call_mknod(mode, dev); > > printf("mknod(\"%s\", S_IFBLK|S_ISUID|S_ISGID|S_ISVTX|%#03ho" > > - ", makedev(%#x, %#x)) = %ld %s (%m)\n", > > + ", makedev(%#x, %#x)) = %ld", > > sample, (short) (mode & ~(S_IFMT|S_ISUID|S_ISGID|S_ISVTX)), > > major((unsigned) dev), minor((unsigned) dev), > > - rc, errno2name()); > > + rc); > > + print_errno(); > > > > puts("+++ exited with 0 +++"); > > return 0; > > We already have (and use) sprintrc, could it be useful here, too? Thanks, that's exactly what we need here. I remember seeing sprintc in the past, but I forgot about it. I'm sending a v2 with sprintrc... From uzonyi.akos at gmail.com Tue Aug 25 13:39:24 2020 From: uzonyi.akos at gmail.com (=?UTF-8?q?=C3=81kos=20Uzonyi?=) Date: Tue, 25 Aug 2020 15:39:24 +0200 Subject: [PATCH] tests/mknod.c: add workaround for ppc bug in travis Message-ID: <20200825133924.1303362-1-uzonyi.akos@gmail.com> On ppc travis builds syscall(mknod) sometimes does not fail with EEXISTS as expected, but returns successfully. This commit uses sprintrc for errno printing, which handles successful return values too. * tests/mknod.c (call_mknod): set errno to 0 before syscall. (main): Use sprintrc for printing errno. --- tests/mknod.c | 34 ++++++++++++++++++---------------- 1 file changed, 18 insertions(+), 16 deletions(-) diff --git a/tests/mknod.c b/tests/mknod.c index 44c6f028..2570b523 100644 --- a/tests/mknod.c +++ b/tests/mknod.c @@ -10,6 +10,7 @@ #ifdef __NR_mknod +# include # include # include # include @@ -20,6 +21,7 @@ static const char *sample; static long call_mknod(unsigned short mode, unsigned long dev) { + errno = 0; unsigned long lmode = (unsigned long) 0xffffffffffff0000ULL | mode; return syscall(__NR_mknod, sample, lmode, dev); } @@ -31,44 +33,44 @@ main(int ac, char **av) sample = av[0]; long rc = call_mknod(0, dev); - printf("mknod(\"%s\", 000) = %ld %s (%m)\n", - sample, rc, errno2name()); + printf("mknod(\"%s\", 000) = %s\n", + sample, sprintrc(rc)); rc = call_mknod(0xffff, dev); - printf("mknod(\"%s\", %#03ho) = %ld %s (%m)\n", - sample, (unsigned short) -1, rc, errno2name()); + printf("mknod(\"%s\", %#03ho) = %s\n", + sample, (unsigned short) -1, sprintrc(rc)); rc = call_mknod(S_IFREG, 0); - printf("mknod(\"%s\", S_IFREG|000) = %ld %s (%m)\n", - sample, rc, errno2name()); + printf("mknod(\"%s\", S_IFREG|000) = %s\n", + sample, sprintrc(rc)); rc = call_mknod(S_IFDIR | 06, 0); - printf("mknod(\"%s\", S_IFDIR|006) = %ld %s (%m)\n", - sample, rc, errno2name()); + printf("mknod(\"%s\", S_IFDIR|006) = %s\n", + sample, sprintrc(rc)); rc = call_mknod(S_IFLNK | 060, 0); - printf("mknod(\"%s\", S_IFLNK|060) = %ld %s (%m)\n", - sample, rc, errno2name()); + printf("mknod(\"%s\", S_IFLNK|060) = %s\n", + sample, sprintrc(rc)); rc = call_mknod(S_IFIFO | 0600, 0); - printf("mknod(\"%s\", S_IFIFO|0600) = %ld %s (%m)\n", - sample, rc, errno2name()); + printf("mknod(\"%s\", S_IFIFO|0600) = %s\n", + sample, sprintrc(rc)); dev = (unsigned long) 0xdeadbeef00000000ULL | makedev(1, 7); rc = call_mknod(S_IFCHR | 024, dev); - printf("mknod(\"%s\", S_IFCHR|024, makedev(0x1, 0x7)) = %ld %s (%m)\n", - sample, rc, errno2name()); + printf("mknod(\"%s\", S_IFCHR|024, makedev(0x1, 0x7)) = %s\n", + sample, sprintrc(rc)); const unsigned short mode = (0xffff & ~S_IFMT) | S_IFBLK; dev = (unsigned long) 0xdeadbeefbadc0dedULL; rc = call_mknod(mode, dev); printf("mknod(\"%s\", S_IFBLK|S_ISUID|S_ISGID|S_ISVTX|%#03ho" - ", makedev(%#x, %#x)) = %ld %s (%m)\n", + ", makedev(%#x, %#x)) = %s\n", sample, (short) (mode & ~(S_IFMT|S_ISUID|S_ISGID|S_ISVTX)), major((unsigned) dev), minor((unsigned) dev), - rc, errno2name()); + sprintrc(rc)); puts("+++ exited with 0 +++"); return 0; -- 2.28.0 From ldv at altlinux.org Tue Aug 25 14:02:23 2020 From: ldv at altlinux.org (Dmitry V. Levin) Date: Tue, 25 Aug 2020 17:02:23 +0300 Subject: [PATCH v2] tests/mknod.c: add workaround for ppc bug in travis In-Reply-To: <20200825133924.1303362-1-uzonyi.akos@gmail.com> References: <20200825133924.1303362-1-uzonyi.akos@gmail.com> Message-ID: <20200825140223.GB2249@altlinux.org> On Tue, Aug 25, 2020 at 03:39:24PM +0200, ?kos Uzonyi wrote: > On ppc travis builds syscall(mknod) sometimes does not fail with EEXISTS > as expected, but returns successfully. This commit uses sprintrc for > errno printing, which handles successful return values too. > > * tests/mknod.c (call_mknod): set errno to 0 before syscall. > (main): Use sprintrc for printing errno. > --- > tests/mknod.c | 34 ++++++++++++++++++---------------- > 1 file changed, 18 insertions(+), 16 deletions(-) > > diff --git a/tests/mknod.c b/tests/mknod.c > index 44c6f028..2570b523 100644 > --- a/tests/mknod.c > +++ b/tests/mknod.c > @@ -10,6 +10,7 @@ > > #ifdef __NR_mknod > > +# include > # include > # include > # include > @@ -20,6 +21,7 @@ static const char *sample; > static long > call_mknod(unsigned short mode, unsigned long dev) > { > + errno = 0; > unsigned long lmode = (unsigned long) 0xffffffffffff0000ULL | mode; > return syscall(__NR_mknod, sample, lmode, dev); > } I don't see why you might need to change this part. Besides that, LGTM. -- ldv From ldv at altlinux.org Tue Aug 25 14:19:42 2020 From: ldv at altlinux.org (Dmitry V. Levin) Date: Tue, 25 Aug 2020 17:19:42 +0300 Subject: [GSoC] Final evaluation URL In-Reply-To: References: Message-ID: <20200825141942.GA2848@altlinux.org> Hi, On Mon, Aug 24, 2020 at 07:26:40PM +0200, ?kos Uzonyi wrote: > Hi, > > I'll submit the following URL for the final evaluation: > > https://akosuzonyi.github.io/strace/ > > Please have a look at this page, and if you have any comments, let me know. You are saying there at the bottom of the page that "All commits listed here are made during GSoC 2020, although not all of them is related to the main project". I think all those commits are related to the main project, although not all of them are related directly. -- ldv From uzonyi.akos at gmail.com Tue Aug 25 14:20:20 2020 From: uzonyi.akos at gmail.com (=?UTF-8?B?w4Frb3MgVXpvbnlp?=) Date: Tue, 25 Aug 2020 16:20:20 +0200 Subject: [PATCH v2] tests/mknod.c: add workaround for ppc bug in travis In-Reply-To: <20200825140223.GB2249@altlinux.org> References: <20200825133924.1303362-1-uzonyi.akos@gmail.com> <20200825140223.GB2249@altlinux.org> Message-ID: On Tue, 25 Aug 2020 at 16:02, Dmitry V. Levin wrote: > On Tue, Aug 25, 2020 at 03:39:24PM +0200, ?kos Uzonyi wrote: > > On ppc travis builds syscall(mknod) sometimes does not fail with EEXISTS > > as expected, but returns successfully. This commit uses sprintrc for > > errno printing, which handles successful return values too. > > > > * tests/mknod.c (call_mknod): set errno to 0 before syscall. > > (main): Use sprintrc for printing errno. > > --- > > tests/mknod.c | 34 ++++++++++++++++++---------------- > > 1 file changed, 18 insertions(+), 16 deletions(-) > > > > diff --git a/tests/mknod.c b/tests/mknod.c > > index 44c6f028..2570b523 100644 > > --- a/tests/mknod.c > > +++ b/tests/mknod.c > > @@ -10,6 +10,7 @@ > > > > #ifdef __NR_mknod > > > > +# include > > # include > > # include > > # include > > @@ -20,6 +21,7 @@ static const char *sample; > > static long > > call_mknod(unsigned short mode, unsigned long dev) > > { > > + errno = 0; > > unsigned long lmode = (unsigned long) 0xffffffffffff0000ULL | mode; > > return syscall(__NR_mknod, sample, lmode, dev); > > } > > I don't see why you might need to change this part. > Besides that, LGTM. Oh yes, this is not needed anymore, as sprintc checks whether the return value is -1. Should I resend? From ldv at altlinux.org Tue Aug 25 14:27:10 2020 From: ldv at altlinux.org (Dmitry V. Levin) Date: Tue, 25 Aug 2020 17:27:10 +0300 Subject: [PATCH v2] tests/mknod.c: add workaround for ppc bug in travis In-Reply-To: References: <20200825133924.1303362-1-uzonyi.akos@gmail.com> <20200825140223.GB2249@altlinux.org> Message-ID: <20200825142710.GC2895@altlinux.org> On Tue, Aug 25, 2020 at 04:20:20PM +0200, ?kos Uzonyi wrote: > On Tue, 25 Aug 2020 at 16:02, Dmitry V. Levin wrote: > > On Tue, Aug 25, 2020 at 03:39:24PM +0200, ?kos Uzonyi wrote: > > > On ppc travis builds syscall(mknod) sometimes does not fail with EEXISTS > > > as expected, but returns successfully. This commit uses sprintrc for > > > errno printing, which handles successful return values too. > > > > > > * tests/mknod.c (call_mknod): set errno to 0 before syscall. > > > (main): Use sprintrc for printing errno. > > > --- > > > tests/mknod.c | 34 ++++++++++++++++++---------------- > > > 1 file changed, 18 insertions(+), 16 deletions(-) > > > > > > diff --git a/tests/mknod.c b/tests/mknod.c > > > index 44c6f028..2570b523 100644 > > > --- a/tests/mknod.c > > > +++ b/tests/mknod.c > > > @@ -10,6 +10,7 @@ > > > > > > #ifdef __NR_mknod > > > > > > +# include > > > # include > > > # include > > > # include > > > @@ -20,6 +21,7 @@ static const char *sample; > > > static long > > > call_mknod(unsigned short mode, unsigned long dev) > > > { > > > + errno = 0; > > > unsigned long lmode = (unsigned long) 0xffffffffffff0000ULL | mode; > > > return syscall(__NR_mknod, sample, lmode, dev); > > > } > > > > I don't see why you might need to change this part. > > Besides that, LGTM. > > Oh yes, this is not needed anymore, as sprintc checks whether the > return value is -1. > > Should I resend? Yes, please, if you don't mind. -- ldv From uzonyi.akos at gmail.com Tue Aug 25 14:29:30 2020 From: uzonyi.akos at gmail.com (=?UTF-8?q?=C3=81kos=20Uzonyi?=) Date: Tue, 25 Aug 2020 16:29:30 +0200 Subject: [PATCH v3] tests/mknod.c: add workaround for ppc bug in travis Message-ID: <20200825142930.1304593-1-uzonyi.akos@gmail.com> On ppc travis builds syscall(mknod) sometimes does not fail with EEXISTS as expected, but returns successfully. This commit uses sprintrc for errno printing, which handles successful return values too. * tests/mknod.c (main): Use sprintrc for printing errno. --- tests/mknod.c | 32 ++++++++++++++++---------------- 1 file changed, 16 insertions(+), 16 deletions(-) diff --git a/tests/mknod.c b/tests/mknod.c index 44c6f028..7fbe693c 100644 --- a/tests/mknod.c +++ b/tests/mknod.c @@ -31,44 +31,44 @@ main(int ac, char **av) sample = av[0]; long rc = call_mknod(0, dev); - printf("mknod(\"%s\", 000) = %ld %s (%m)\n", - sample, rc, errno2name()); + printf("mknod(\"%s\", 000) = %s\n", + sample, sprintrc(rc)); rc = call_mknod(0xffff, dev); - printf("mknod(\"%s\", %#03ho) = %ld %s (%m)\n", - sample, (unsigned short) -1, rc, errno2name()); + printf("mknod(\"%s\", %#03ho) = %s\n", + sample, (unsigned short) -1, sprintrc(rc)); rc = call_mknod(S_IFREG, 0); - printf("mknod(\"%s\", S_IFREG|000) = %ld %s (%m)\n", - sample, rc, errno2name()); + printf("mknod(\"%s\", S_IFREG|000) = %s\n", + sample, sprintrc(rc)); rc = call_mknod(S_IFDIR | 06, 0); - printf("mknod(\"%s\", S_IFDIR|006) = %ld %s (%m)\n", - sample, rc, errno2name()); + printf("mknod(\"%s\", S_IFDIR|006) = %s\n", + sample, sprintrc(rc)); rc = call_mknod(S_IFLNK | 060, 0); - printf("mknod(\"%s\", S_IFLNK|060) = %ld %s (%m)\n", - sample, rc, errno2name()); + printf("mknod(\"%s\", S_IFLNK|060) = %s\n", + sample, sprintrc(rc)); rc = call_mknod(S_IFIFO | 0600, 0); - printf("mknod(\"%s\", S_IFIFO|0600) = %ld %s (%m)\n", - sample, rc, errno2name()); + printf("mknod(\"%s\", S_IFIFO|0600) = %s\n", + sample, sprintrc(rc)); dev = (unsigned long) 0xdeadbeef00000000ULL | makedev(1, 7); rc = call_mknod(S_IFCHR | 024, dev); - printf("mknod(\"%s\", S_IFCHR|024, makedev(0x1, 0x7)) = %ld %s (%m)\n", - sample, rc, errno2name()); + printf("mknod(\"%s\", S_IFCHR|024, makedev(0x1, 0x7)) = %s\n", + sample, sprintrc(rc)); const unsigned short mode = (0xffff & ~S_IFMT) | S_IFBLK; dev = (unsigned long) 0xdeadbeefbadc0dedULL; rc = call_mknod(mode, dev); printf("mknod(\"%s\", S_IFBLK|S_ISUID|S_ISGID|S_ISVTX|%#03ho" - ", makedev(%#x, %#x)) = %ld %s (%m)\n", + ", makedev(%#x, %#x)) = %s\n", sample, (short) (mode & ~(S_IFMT|S_ISUID|S_ISGID|S_ISVTX)), major((unsigned) dev), minor((unsigned) dev), - rc, errno2name()); + sprintrc(rc)); puts("+++ exited with 0 +++"); return 0; -- 2.28.0 From uzonyi.akos at gmail.com Tue Aug 25 14:31:08 2020 From: uzonyi.akos at gmail.com (=?UTF-8?B?w4Frb3MgVXpvbnlp?=) Date: Tue, 25 Aug 2020 16:31:08 +0200 Subject: [GSoC] Final evaluation URL In-Reply-To: <20200825141942.GA2848@altlinux.org> References: <20200825141942.GA2848@altlinux.org> Message-ID: On Tue, 25 Aug 2020 at 16:19, Dmitry V. Levin wrote: > Hi, > > On Mon, Aug 24, 2020 at 07:26:40PM +0200, ?kos Uzonyi wrote: > > Hi, > > > > I'll submit the following URL for the final evaluation: > > > > https://akosuzonyi.github.io/strace/ > > > > Please have a look at this page, and if you have any comments, let me know. > > You are saying there at the bottom of the page that > "All commits listed here are made during GSoC 2020, > although not all of them is related to the main project". > > I think all those commits are related to the main project, > although not all of them are related directly. I think the first 10 commits for example are not related to the main project (my microproject, and a pidfd_getfd decoder bugfix). From hauke at hauke-m.de Sat Aug 29 19:42:33 2020 From: hauke at hauke-m.de (Hauke Mehrtens) Date: Sat, 29 Aug 2020 21:42:33 +0200 Subject: [PATCH] v4l2: Fix compile of mpers-m32 API Message-ID: <20200829194233.6505-1-hauke@hauke-m.de> In the mpers-m32 API the value64 member of the struct_v4l2_ext_control structure is of type int32_t. This causes the following compile error: v4l2.c: In function 'print_v4l2_ext_control': v4l2.c:915:11: error: format '%ld' expects argument of type 'long int', but argument 3 has type 'int32_t' {aka 'const int'} [-Werror=format=] tprintf(", value=%d, value64=%" PRId64, p->value, p->value64); ^~~~~~~~~~~~~~~~~~~~~~~ ~~~~~~~~~~ Fix this by adding the explicit cast again which was removed in strace version 5.6. Fixes: 7e7669ec899e ("v4l2: always decode VIDIOC_*_EXT_CTRLS ioctl commands") --- v4l2.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/v4l2.c b/v4l2.c index 3a1c49d2..93466c4d 100644 --- a/v4l2.c +++ b/v4l2.c @@ -912,7 +912,7 @@ print_v4l2_ext_control(struct tcb *tcp, void *elem_buf, size_t elem_size, void * tprints(", string="); printstrn(tcp, ptr_to_kulong(p->string), p->size); } else { - tprintf(", value=%d, value64=%" PRId64, p->value, p->value64); + tprintf(", value=%d, value64=%" PRId64, p->value, (int64_t) p->value64); } tprints("}"); -- 2.20.1 From evgsyr at gmail.com Sun Aug 30 10:54:49 2020 From: evgsyr at gmail.com (Eugene Syromyatnikov) Date: Sun, 30 Aug 2020 12:54:49 +0200 Subject: [PATCH] v4l2: Fix compile of mpers-m32 API In-Reply-To: <20200829194233.6505-1-hauke@hauke-m.de> References: <20200829194233.6505-1-hauke@hauke-m.de> Message-ID: On Sun, Aug 30, 2020 at 12:10 PM Hauke Mehrtens wrote: > > In the mpers-m32 API the value64 member of the struct_v4l2_ext_control > structure is of type int32_t. mpers headers are generated, and the fact that int64_t[1] is 32-bit wide when -m32 compiler option is used is rather a bug on libc's part. See also [2]. [1] https://gitlab.com/strace/strace/-/blob/v5.8/types/v4l2.h#L175 [2] https://github.com/strace/musl/commit/6a63dbca01b26dd68483429746ec90e34551ace4 -- Eugene Syromyatnikov mailto:evgsyr at gmail.com xmpp:esyr at jabber.{ru|org} From hauke at hauke-m.de Sun Aug 30 12:07:34 2020 From: hauke at hauke-m.de (Hauke Mehrtens) Date: Sun, 30 Aug 2020 14:07:34 +0200 Subject: [PATCH] v4l2: Fix compile of mpers-m32 API In-Reply-To: References: <20200829194233.6505-1-hauke@hauke-m.de> Message-ID: <619f56a0-de27-c14f-4f3d-8747d0004a4c@hauke-m.de> On 8/30/20 12:54 PM, Eugene Syromyatnikov wrote: > On Sun, Aug 30, 2020 at 12:10 PM Hauke Mehrtens wrote: >> >> In the mpers-m32 API the value64 member of the struct_v4l2_ext_control >> structure is of type int32_t. > > mpers headers are generated, and the fact that int64_t[1] is 32-bit > wide when -m32 compiler option is used is rather a bug on libc's part. > See also [2]. > > [1] https://gitlab.com/strace/strace/-/blob/v5.8/types/v4l2.h#L175 > [2] https://github.com/strace/musl/commit/6a63dbca01b26dd68483429746ec90e34551ace4 > Hi Eugene, I did this build in OpenWrt with musl libc 1.1.24 + gcc 8.4.0 for x86_64. The file mpers-mx32/struct_v4l2_ext_control.h looks like this: ----------------------------------------------------------- .... int32_t value; int32_t value64; .... } ; } ATTRIBUTE_PACKED mx32_struct_v4l2_ext_control; #define MPERS_mx32_struct_v4l2_ext_control mx32_struct_v4l2_ext_control ----------------------------------------------------------- The mpers-m32/struct_v4l2_ext_control.h file looks similar. When I compile this on my Debian with glibc and gcc 8.3.0 the value64 is of type int64_t. Where are these structures in mpers-m32 and mpers-mx32 generated? It looks like some script which generates them converts the int64_t into a int32_t under some conditions. I see that Apline just deactivated mpers support, I think that is also ok for OpenWrt: https://git.alpinelinux.org/aports/commit/main/strace/APKBUILD?id=69d6896b7d57d5e7dc9596fd3b4721205cb7bca8 Hauke -------------- next part -------------- A non-text attachment was scrubbed... Name: signature.asc Type: application/pgp-signature Size: 488 bytes Desc: OpenPGP digital signature URL: From ldv at altlinux.org Sun Aug 30 22:24:21 2020 From: ldv at altlinux.org (Dmitry V. Levin) Date: Mon, 31 Aug 2020 01:24:21 +0300 Subject: [PATCH] v4l2: Fix compile of mpers-m32 API In-Reply-To: <619f56a0-de27-c14f-4f3d-8747d0004a4c@hauke-m.de> References: <20200829194233.6505-1-hauke@hauke-m.de> <619f56a0-de27-c14f-4f3d-8747d0004a4c@hauke-m.de> Message-ID: <20200830222421.GA21814@altlinux.org> On Sun, Aug 30, 2020 at 02:07:34PM +0200, Hauke Mehrtens wrote: > On 8/30/20 12:54 PM, Eugene Syromyatnikov wrote: > > On Sun, Aug 30, 2020 at 12:10 PM Hauke Mehrtens wrote: > >> > >> In the mpers-m32 API the value64 member of the struct_v4l2_ext_control > >> structure is of type int32_t. > > > > mpers headers are generated, and the fact that int64_t[1] is 32-bit > > wide when -m32 compiler option is used is rather a bug on libc's part. > > See also [2]. > > > > [1] https://gitlab.com/strace/strace/-/blob/v5.8/types/v4l2.h#L175 > > [2] https://github.com/strace/musl/commit/6a63dbca01b26dd68483429746ec90e34551ace4 > > > > Hi Eugene, > > I did this build in OpenWrt with musl libc 1.1.24 + gcc 8.4.0 for x86_64. > > The file mpers-mx32/struct_v4l2_ext_control.h looks like this: > ----------------------------------------------------------- > .... > int32_t value; > int32_t value64; > .... > } ; > } ATTRIBUTE_PACKED mx32_struct_v4l2_ext_control; > #define MPERS_mx32_struct_v4l2_ext_control mx32_struct_v4l2_ext_control > ----------------------------------------------------------- > The mpers-m32/struct_v4l2_ext_control.h file looks similar. > > When I compile this on my Debian with glibc and gcc 8.3.0 the value64 is > of type int64_t. That's because gcc -m32 is not supported by your musl libc. We have to patch musl [2] to workaround this musl bug. > Where are these structures in mpers-m32 and mpers-mx32 generated? It > looks like some script which generates them converts the int64_t into a > int32_t under some conditions. Yes, all these structures are generated at build time using gcc -m32 and gcc -mx32, respectively. > I see that Apline just deactivated mpers support, I think that is also > ok for OpenWrt: > https://git.alpinelinux.org/aports/commit/main/strace/APKBUILD?id=69d6896b7d57d5e7dc9596fd3b4721205cb7bca8 If your x86_64 kernel is configured with either CONFIG_IA32_EMULATION or CONFIG_X86_X32 enabled, then you shouldn't deactivate mpers support, otherwise you're building a strace that won't be able to handle compat syscalls on x86_64 properly. -- ldv