Package: strace Version: 4.15-2 Severity: normal Dear Maintainer,
On armhf, when the known system call triggers a SECCOMP rule that raises SIGSYS strace starts interpreting system calls entries as exits, and exits as entries. After another SIGSYS correct behavour is restored. For example: $ strace -o /dev/fd/1 ./a.out 3 2>/dev/null ... read(72, <unfinished ...> --- SIGSYS {si_signo=SIGSYS, si_code=SYS_SECCOMP, si_call_addr=0x7f57e5d0, si_syscall=__NR_read, si_arch=AUDIT_ARCH_ARM} --- <... read resumed> "3\0KDE_MULTIHEAD=false\0GS_LIB=/h", 0) = 31 read(72, "3\0", 0) = 2 write(1, "H", 1) = 101 --- SIGSYS {si_signo=SIGSYS, si_code=SYS_SECCOMP, si_call_addr=0x7f57e5d0, si_syscall=__NR_read, si_arch=AUDIT_ARCH_ARM} --- sigreturn({mask=[]}) = 101 write(2, "e", 1) = 1 read(108, <unfinished ...> --- SIGSYS {si_signo=SIGSYS, si_code=SYS_SECCOMP, si_call_addr=0x7f57e5d0, si_syscall=__NR_read, si_arch=AUDIT_ARCH_ARM} --- <... read resumed> "ello World\n\0\0\0\0d\376\377\177\1\0\0\0\0\0\0\0\0\0\0\0", 1) = 31 read(108, "el", 1) = 2 write(1, "l", 1) = 108 --- SIGSYS {si_signo=SIGSYS, si_code=SYS_SECCOMP, si_call_addr=0x7f57e5d0, si_syscall=__NR_read, si_arch=AUDIT_ARCH_ARM} --- sigreturn({mask=[]}) = 108 With an invalid system call number it works properly: $ strace -o /dev/fd/1 ./a.out 1000 2>/dev/null ... syscall_1000(0x48, 0xbede5373, 0, 0, 0x7f61778c, 0x3e8 <unfinished ...> --- SIGSYS {si_signo=SIGSYS, si_code=SYS_SECCOMP, si_call_addr=0x7f6175d0, si_syscall=1000, si_arch=AUDIT_ARCH_ARM} --- <... syscall_1000 resumed> ) = 0x1f write(2, "H", 1) = 1 syscall_1000(0x65, 0x7f61778c, 0x1, 0, 0x7f61778d, 0x3e8 <unfinished ...> --- SIGSYS {si_signo=SIGSYS, si_code=SYS_SECCOMP, si_call_addr=0x7f6175d0, si_syscall=1000, si_arch=AUDIT_ARCH_ARM} --- <... syscall_1000 resumed> ) = 0x1f write(2, "e", 1) = 1 syscall_1000(0x6c, 0x7f61778d, 0x1, 0, 0x7f61778e, 0x3e8 <unfinished ...> --- SIGSYS {si_signo=SIGSYS, si_code=SYS_SECCOMP, si_call_addr=0x7f6175d0, si_syscall=1000, si_arch=AUDIT_ARCH_ARM} --- <... syscall_1000 resumed> ) = 0x1f write(2, "l", 1) = 1 syscall_1000(0x6c, 0x7f61778e, 0x1, 0, 0x7f61778f, 0x3e8 <unfinished ...> --- SIGSYS {si_signo=SIGSYS, si_code=SYS_SECCOMP, si_call_addr=0x7f6175d0, si_syscall=1000, si_arch=AUDIT_ARCH_ARM} --- Attached test case requires -marm or -O2 gcc options to compile. -- System Information: Debian Release: 9.0 APT prefers testing APT policy: (990, 'testing'), (500, 'unstable') Architecture: armhf (armv7l) Kernel: Linux 4.9.9-teb2+ (SMP w/4 CPU cores) Locale: LANG=en_GB.UTF-8, LC_CTYPE=en_GB.UTF-8 (charmap=UTF-8) Shell: /bin/sh linked to /bin/dash Init: systemd (via /run/systemd/system) Versions of packages strace depends on: ii libc6 2.24-9 strace recommends no packages. strace suggests no packages. -- no debconf information
#define _GNU_SOURCE #include <linux/filter.h> #include <linux/seccomp.h> #include <signal.h> #include <stddef.h> #include <stdint.h> #include <stdlib.h> #include <sys/prctl.h> #include <unistd.h> void ignore(int s) { } extern char syscall_instruction[]; int main(int argc, char **argv) { struct sock_filter filter[] = { // Load PC BPF_STMT(BPF_LD | BPF_W | BPF_ABS, offsetof(struct seccomp_data, instruction_pointer)), // Trap test instruction BPF_JUMP(BPF_JMP | BPF_JEQ | BPF_K, (uintptr_t)syscall_instruction, 0, 1), // Raise signal. BPF_STMT(BPF_RET | BPF_K, SECCOMP_RET_TRAP), // Continue as Linux system call. BPF_STMT(BPF_RET | BPF_K, SECCOMP_RET_ALLOW), }; struct sock_fprog fprog = { .len = sizeof(filter) / sizeof(filter[0]), .filter = filter }; prctl(PR_SET_NO_NEW_PRIVS, 1, 0, 0, 0); prctl(PR_SET_SECCOMP, SECCOMP_MODE_FILTER, (uintptr_t)&fprog, 0, 0); signal(SIGSYS, ignore); int syscall = 4; if (argc > 1) syscall = atoi(argv[1]); const char *c = "Hello World\n"; while (*c) { #ifdef __arm__ register int r0 asm("r0") = *c; register int r7 asm("r7") = syscall; asm volatile ("svc 0\n\tsyscall_instruction:" : "+r"(r0), "+r"(r7) :: "memory"); #else int s = syscall; asm volatile ("int $0x80\n\tsyscall_instruction:" : "+a"(s): "b"(*c) : "memory"); #endif write(2, c, 1); ++c; } }