In preparation for performing actions during ptrace syscall exit, save
the syscall number during ptrace syscall entry. Some architectures do
no have the syscall number available during ptrace syscall exit.

Suggested-by: Thadeu Lima de Souza Cascardo <casca...@canonical.com>
Link: 
https://lore.kernel.org/linux-kselftest/20200911181012.171027-1-casca...@canonical.com/
Signed-off-by: Kees Cook <keesc...@chromium.org>
---
 tools/testing/selftests/seccomp/seccomp_bpf.c | 40 +++++++++++++------
 1 file changed, 27 insertions(+), 13 deletions(-)

diff --git a/tools/testing/selftests/seccomp/seccomp_bpf.c 
b/tools/testing/selftests/seccomp/seccomp_bpf.c
index bc0fb463c709..c0311b4c736b 100644
--- a/tools/testing/selftests/seccomp/seccomp_bpf.c
+++ b/tools/testing/selftests/seccomp/seccomp_bpf.c
@@ -1949,12 +1949,19 @@ void tracer_seccomp(struct __test_metadata *_metadata, 
pid_t tracee,
 
 }
 
+FIXTURE(TRACE_syscall) {
+       struct sock_fprog prog;
+       pid_t tracer, mytid, mypid, parent;
+       long syscall_nr;
+};
+
 void tracer_ptrace(struct __test_metadata *_metadata, pid_t tracee,
                   int status, void *args)
 {
-       int ret, nr;
+       int ret;
        unsigned long msg;
        static bool entry;
+       FIXTURE_DATA(TRACE_syscall) *self = args;
 
        /*
         * The traditional way to tell PTRACE_SYSCALL entry/exit
@@ -1968,24 +1975,31 @@ void tracer_ptrace(struct __test_metadata *_metadata, 
pid_t tracee,
        EXPECT_EQ(entry ? PTRACE_EVENTMSG_SYSCALL_ENTRY
                        : PTRACE_EVENTMSG_SYSCALL_EXIT, msg);
 
-       if (!entry)
+       /*
+        * Some architectures only support setting return values during
+        * syscall exit under ptrace, and on exit the syscall number may
+        * no longer be available. Therefore, save the initial sycall
+        * number here, so it can be examined during both entry and exit
+        * phases.
+        */
+       if (entry)
+               self->syscall_nr = get_syscall(_metadata, tracee);
+       else
                return;
 
-       nr = get_syscall(_metadata, tracee);
-
-       if (nr == __NR_getpid)
+       switch (self->syscall_nr) {
+       case __NR_getpid:
                change_syscall(_metadata, tracee, __NR_getppid, 0);
-       if (nr == __NR_gettid)
+               break;
+       case __NR_gettid:
                change_syscall(_metadata, tracee, -1, 45000);
-       if (nr == __NR_openat)
+               break;
+       case __NR_openat:
                change_syscall(_metadata, tracee, -1, -ESRCH);
+               break;
+       }
 }
 
-FIXTURE(TRACE_syscall) {
-       struct sock_fprog prog;
-       pid_t tracer, mytid, mypid, parent;
-};
-
 FIXTURE_VARIANT(TRACE_syscall) {
        /*
         * All of the SECCOMP_RET_TRACE behaviors can be tested with either
@@ -2044,7 +2058,7 @@ FIXTURE_SETUP(TRACE_syscall)
        self->tracer = setup_trace_fixture(_metadata,
                                           variant->use_ptrace ? tracer_ptrace
                                                               : tracer_seccomp,
-                                          NULL, variant->use_ptrace);
+                                          self, variant->use_ptrace);
 
        ret = prctl(PR_SET_NO_NEW_PRIVS, 1, 0, 0, 0);
        ASSERT_EQ(0, ret);
-- 
2.25.1

Reply via email to