diff --git a/lib/libc/sys/procctl.2 b/lib/libc/sys/procctl.2 index 432ed5919a8..ce7a2be5d5e 100644 --- a/lib/libc/sys/procctl.2 +++ b/lib/libc/sys/procctl.2 @@ -454,6 +454,16 @@ and the .Va si_code member is set to .Dv TRAP_CAP . +The system call number is stored in the +.Va si_syscall +field of the +.Fa siginfo +signal handler parameter. +The other system call parameters can be read from the +.Fa ucontext_t +but the system call number is typically stored in the register +that also contains the return value and so is unavailable in the +signal handler. .Pp See .Xr capsicum 4 diff --git a/share/man/man3/siginfo.3 b/share/man/man3/siginfo.3 index acc8785b2f0..7f8a809cdfa 100644 --- a/share/man/man3/siginfo.3 +++ b/share/man/man3/siginfo.3 @@ -85,6 +85,8 @@ timer overrun count .It Vt int Ta Va si_mqd Ta .Tn POSIX message queue ID +.It Vt int Ta Va si_syscall Ta +system-call number for system calls blocked by Capsicum .El .Pp The diff --git a/sys/amd64/amd64/trap.c b/sys/amd64/amd64/trap.c index 55649687ce5..b08495f3f13 100644 --- a/sys/amd64/amd64/trap.c +++ b/sys/amd64/amd64/trap.c @@ -1059,6 +1059,7 @@ cpu_fetch_syscall_args(struct thread *td) sa = &td->td_sa; sa->code = frame->tf_rax; + sa->original_code = sa->code; if (__predict_false(sa->code == SYS_syscall || sa->code == SYS___syscall || diff --git a/sys/amd64/cloudabi32/cloudabi32_sysvec.c b/sys/amd64/cloudabi32/cloudabi32_sysvec.c index 164f87e90e9..26924ed5a98 100644 --- a/sys/amd64/cloudabi32/cloudabi32_sysvec.c +++ b/sys/amd64/cloudabi32/cloudabi32_sysvec.c @@ -101,6 +101,7 @@ cloudabi32_fetch_syscall_args(struct thread *td) /* Obtain system call number. */ sa->code = frame->tf_rax; + sa->original_code = sa->code; if (sa->code >= CLOUDABI32_SYS_MAXSYSCALL) return (ENOSYS); sa->callp = &cloudabi32_sysent[sa->code]; diff --git a/sys/amd64/cloudabi64/cloudabi64_sysvec.c b/sys/amd64/cloudabi64/cloudabi64_sysvec.c index d3893902b08..c08d912e84d 100644 --- a/sys/amd64/cloudabi64/cloudabi64_sysvec.c +++ b/sys/amd64/cloudabi64/cloudabi64_sysvec.c @@ -98,6 +98,7 @@ cloudabi64_fetch_syscall_args(struct thread *td) /* Obtain system call number. */ sa->code = frame->tf_rax; + sa->original_code = sa->code; if (sa->code >= CLOUDABI64_SYS_MAXSYSCALL) return (ENOSYS); sa->callp = &cloudabi64_sysent[sa->code]; diff --git a/sys/amd64/ia32/ia32_syscall.c b/sys/amd64/ia32/ia32_syscall.c index 6c9399d1a52..9294ef8ce74 100644 --- a/sys/amd64/ia32/ia32_syscall.c +++ b/sys/amd64/ia32/ia32_syscall.c @@ -150,6 +150,7 @@ ia32_fetch_syscall_args(struct thread *td) params = (caddr_t)frame->tf_rsp + sizeof(u_int32_t); sa->code = frame->tf_rax; + sa->original_code = sa->code; /* * Need to check if this is a 32 bit or 64 bit syscall. diff --git a/sys/amd64/include/proc.h b/sys/amd64/include/proc.h index 59796e729ac..0f8cf50e326 100644 --- a/sys/amd64/include/proc.h +++ b/sys/amd64/include/proc.h @@ -92,6 +92,7 @@ struct mdproc { struct syscall_args { u_int code; + u_int original_code; struct sysent *callp; register_t args[8]; }; diff --git a/sys/amd64/linux/linux_sysvec.c b/sys/amd64/linux/linux_sysvec.c index c5538932b1e..566af6de29e 100644 --- a/sys/amd64/linux/linux_sysvec.c +++ b/sys/amd64/linux/linux_sysvec.c @@ -191,6 +191,7 @@ linux_fetch_syscall_args(struct thread *td) sa->args[4] = frame->tf_r8; sa->args[5] = frame->tf_r9; sa->code = frame->tf_rax; + sa->original_code = sa->code; if (sa->code >= p->p_sysent->sv_size) /* nosys */ diff --git a/sys/amd64/linux32/linux32_sysvec.c b/sys/amd64/linux32/linux32_sysvec.c index 504d57e418a..7dfd57a74a1 100644 --- a/sys/amd64/linux32/linux32_sysvec.c +++ b/sys/amd64/linux32/linux32_sysvec.c @@ -662,6 +662,7 @@ linux32_fetch_syscall_args(struct thread *td) sa->args[4] = frame->tf_rdi; sa->args[5] = frame->tf_rbp; /* Unconfirmed */ sa->code = frame->tf_rax; + sa->original_code = sa->code; if (sa->code >= p->p_sysent->sv_size) /* nosys */ diff --git a/sys/arm/arm/syscall.c b/sys/arm/arm/syscall.c index a851db6e455..a635de0ec71 100644 --- a/sys/arm/arm/syscall.c +++ b/sys/arm/arm/syscall.c @@ -108,6 +108,7 @@ cpu_fetch_syscall_args(struct thread *td) nap = 4; sa = &td->td_sa; sa->code = td->td_frame->tf_r7; + sa->original_code = sa->code; ap = &td->td_frame->tf_r0; if (sa->code == SYS_syscall) { sa->code = *ap++; diff --git a/sys/arm/cloudabi32/cloudabi32_sysvec.c b/sys/arm/cloudabi32/cloudabi32_sysvec.c index a8c5da47d26..4df57b22e13 100644 --- a/sys/arm/cloudabi32/cloudabi32_sysvec.c +++ b/sys/arm/cloudabi32/cloudabi32_sysvec.c @@ -78,6 +78,7 @@ cloudabi32_fetch_syscall_args(struct thread *td) /* Obtain system call number. */ sa->code = frame->tf_r12; + sa->original_code = sa->code; if (sa->code >= CLOUDABI32_SYS_MAXSYSCALL) return (ENOSYS); sa->callp = &cloudabi32_sysent[sa->code]; diff --git a/sys/arm/include/proc.h b/sys/arm/include/proc.h index a37ccd8f621..9566c264731 100644 --- a/sys/arm/include/proc.h +++ b/sys/arm/include/proc.h @@ -75,6 +75,7 @@ struct mdproc { */ struct syscall_args { u_int code; + u_int original_code; struct sysent *callp; register_t args[MAXARGS]; } __aligned(8); diff --git a/sys/arm64/arm64/elf32_machdep.c b/sys/arm64/arm64/elf32_machdep.c index 206413b4517..7cedbffc4d4 100644 --- a/sys/arm64/arm64/elf32_machdep.c +++ b/sys/arm64/arm64/elf32_machdep.c @@ -175,6 +175,7 @@ freebsd32_fetch_syscall_args(struct thread *td) /* r7 is the syscall id */ sa->code = td->td_frame->tf_x[7]; + sa->original_code = sa->code; if (sa->code == SYS_syscall) { sa->code = *ap++; diff --git a/sys/arm64/arm64/trap.c b/sys/arm64/arm64/trap.c index 744b646b31c..2b2d2e433ef 100644 --- a/sys/arm64/arm64/trap.c +++ b/sys/arm64/arm64/trap.c @@ -130,6 +130,7 @@ cpu_fetch_syscall_args(struct thread *td) dst_ap = &sa->args[0]; sa->code = td->td_frame->tf_x[8]; + sa->original_code = sa->code; if (__predict_false(sa->code == SYS_syscall || sa->code == SYS___syscall)) { sa->code = *ap++; diff --git a/sys/arm64/cloudabi32/cloudabi32_sysvec.c b/sys/arm64/cloudabi32/cloudabi32_sysvec.c index 889393560ed..b7be5cc0e5e 100644 --- a/sys/arm64/cloudabi32/cloudabi32_sysvec.c +++ b/sys/arm64/cloudabi32/cloudabi32_sysvec.c @@ -75,6 +75,7 @@ cloudabi32_fetch_syscall_args(struct thread *td) /* Obtain system call number. */ sa->code = frame->tf_x[0]; + sa->original_code = sa->code; if (sa->code >= CLOUDABI32_SYS_MAXSYSCALL) return (ENOSYS); sa->callp = &cloudabi32_sysent[sa->code]; diff --git a/sys/arm64/cloudabi64/cloudabi64_sysvec.c b/sys/arm64/cloudabi64/cloudabi64_sysvec.c index bdbd828b7b6..624d8669345 100644 --- a/sys/arm64/cloudabi64/cloudabi64_sysvec.c +++ b/sys/arm64/cloudabi64/cloudabi64_sysvec.c @@ -78,6 +78,7 @@ cloudabi64_fetch_syscall_args(struct thread *td) /* Obtain system call number. */ sa->code = frame->tf_x[8]; + sa->original_code = sa->code; if (sa->code >= CLOUDABI64_SYS_MAXSYSCALL) return (ENOSYS); sa->callp = &cloudabi64_sysent[sa->code]; diff --git a/sys/arm64/include/proc.h b/sys/arm64/include/proc.h index bb933dc9824..3800798d79b 100644 --- a/sys/arm64/include/proc.h +++ b/sys/arm64/include/proc.h @@ -49,6 +49,7 @@ struct mdproc { #define MAXARGS 8 struct syscall_args { u_int code; + u_int original_code; struct sysent *callp; register_t args[MAXARGS]; }; diff --git a/sys/arm64/linux/linux_sysvec.c b/sys/arm64/linux/linux_sysvec.c index e1d3708b70e..7749c1cd7fc 100644 --- a/sys/arm64/linux/linux_sysvec.c +++ b/sys/arm64/linux/linux_sysvec.c @@ -125,6 +125,7 @@ linux_fetch_syscall_args(struct thread *td) sa = &td->td_sa; sa->code = td->td_frame->tf_x[8]; + sa->original_code = sa->code; /* LINUXTODO: generic syscall? */ if (sa->code >= p->p_sysent->sv_size) sa->callp = &p->p_sysent->sv_table[0]; diff --git a/sys/i386/cloudabi32/cloudabi32_sysvec.c b/sys/i386/cloudabi32/cloudabi32_sysvec.c index 4f12d2b6cbc..e0a50f6697a 100644 --- a/sys/i386/cloudabi32/cloudabi32_sysvec.c +++ b/sys/i386/cloudabi32/cloudabi32_sysvec.c @@ -96,6 +96,7 @@ cloudabi32_fetch_syscall_args(struct thread *td) /* Obtain system call number. */ sa->code = frame->tf_eax; + sa->original_code = sa->code; if (sa->code >= CLOUDABI32_SYS_MAXSYSCALL) return (ENOSYS); sa->callp = &cloudabi32_sysent[sa->code]; diff --git a/sys/i386/i386/trap.c b/sys/i386/i386/trap.c index 045478149be..07abac23c9d 100644 --- a/sys/i386/i386/trap.c +++ b/sys/i386/i386/trap.c @@ -1052,6 +1052,7 @@ cpu_fetch_syscall_args(struct thread *td) #endif sa->code = frame->tf_eax; + sa->original_code = sa->code; params = (caddr_t)frame->tf_esp + sizeof(uint32_t); /* diff --git a/sys/i386/include/proc.h b/sys/i386/include/proc.h index 2950946ff15..76e1ac61147 100644 --- a/sys/i386/include/proc.h +++ b/sys/i386/include/proc.h @@ -64,6 +64,7 @@ struct mdproc { struct syscall_args { u_int code; + u_int original_code; struct sysent *callp; register_t args[8]; }; diff --git a/sys/i386/linux/linux_sysvec.c b/sys/i386/linux/linux_sysvec.c index adb70fded6d..a0959d55b58 100644 --- a/sys/i386/linux/linux_sysvec.c +++ b/sys/i386/linux/linux_sysvec.c @@ -756,6 +756,7 @@ linux_fetch_syscall_args(struct thread *td) sa = &td->td_sa; sa->code = frame->tf_eax; + sa->original_code = sa->code; sa->args[0] = frame->tf_ebx; sa->args[1] = frame->tf_ecx; sa->args[2] = frame->tf_edx; diff --git a/sys/kern/subr_syscall.c b/sys/kern/subr_syscall.c index 85a0814a212..2304e3e7f3f 100644 --- a/sys/kern/subr_syscall.c +++ b/sys/kern/subr_syscall.c @@ -230,6 +230,7 @@ syscallret(struct thread *td) ksi.ksi_signo = SIGTRAP; ksi.ksi_errno = td->td_errno; ksi.ksi_code = TRAP_CAP; + ksi.ksi_info.si_syscall = sa->original_code; trapsignal(td, &ksi); } } diff --git a/sys/mips/include/proc.h b/sys/mips/include/proc.h index 0cb1d433387..29d832a162e 100644 --- a/sys/mips/include/proc.h +++ b/sys/mips/include/proc.h @@ -84,6 +84,7 @@ struct mdproc { #define MAXARGS 8 struct syscall_args { u_int code; + u_int original_code; struct sysent *callp; register_t args[MAXARGS]; }; diff --git a/sys/mips/mips/trap.c b/sys/mips/mips/trap.c index 96a2de4ee81..9d7a0760637 100644 --- a/sys/mips/mips/trap.c +++ b/sys/mips/mips/trap.c @@ -355,6 +355,7 @@ cpu_fetch_syscall_args(struct thread *td) else locr0->pc += sizeof(int); sa->code = locr0->v0; + sa->original_code = sa->code; switch (sa->code) { case SYS___syscall: diff --git a/sys/powerpc/include/proc.h b/sys/powerpc/include/proc.h index d4df3ccfefe..aac4e66b39f 100644 --- a/sys/powerpc/include/proc.h +++ b/sys/powerpc/include/proc.h @@ -62,6 +62,7 @@ struct mdproc { #define MAXARGS 8 struct syscall_args { u_int code; + u_int original_code; struct sysent *callp; register_t args[MAXARGS]; }; diff --git a/sys/powerpc/powerpc/trap.c b/sys/powerpc/powerpc/trap.c index 3a1bdf7cde0..ab5189a0f41 100644 --- a/sys/powerpc/powerpc/trap.c +++ b/sys/powerpc/powerpc/trap.c @@ -667,6 +667,7 @@ cpu_fetch_syscall_args(struct thread *td) sa = &td->td_sa; sa->code = frame->fixreg[0]; + sa->original_code = sa->code; params = (caddr_t)(frame->fixreg + FIRSTARG); n = NARGREG; diff --git a/sys/riscv/include/proc.h b/sys/riscv/include/proc.h index 4b5ae9ebe3e..1c6c8d2919b 100644 --- a/sys/riscv/include/proc.h +++ b/sys/riscv/include/proc.h @@ -48,6 +48,7 @@ struct mdproc { #define MAXARGS 8 struct syscall_args { u_int code; + u_int original_code; struct sysent *callp; register_t args[MAXARGS]; }; diff --git a/sys/riscv/riscv/trap.c b/sys/riscv/riscv/trap.c index 07d7f84a94e..8844638c820 100644 --- a/sys/riscv/riscv/trap.c +++ b/sys/riscv/riscv/trap.c @@ -103,6 +103,7 @@ cpu_fetch_syscall_args(struct thread *td) dst_ap = &sa->args[0]; sa->code = td->td_frame->tf_t[0]; + sa->original_code = sa->code; if (__predict_false(sa->code == SYS_syscall || sa->code == SYS___syscall)) { sa->code = *ap++; diff --git a/sys/sys/signal.h b/sys/sys/signal.h index 8b45a521c3e..9dae3ce0474 100644 --- a/sys/sys/signal.h +++ b/sys/sys/signal.h @@ -255,6 +255,12 @@ typedef struct __siginfo { struct { long _band; /* band event for SIGPOLL */ } _poll; /* was this ever used ? */ + struct { + int _syscall; /* Syscall number for signals + * delivered as a result of + * system calls denied by + * Capsicum. */ + } _capsicum; struct { long __spare1__; int __spare2__[7]; @@ -267,6 +273,7 @@ typedef struct __siginfo { #define si_overrun _reason._timer._overrun #define si_mqd _reason._mesgq._mqd #define si_band _reason._poll._band +#define si_syscall _reason._capsicum._syscall #if defined(_WANT_LWPINFO32) || (defined(_KERNEL) && defined(__LP64__)) struct siginfo32 {