Page MenuHomeFreeBSD

D30635.1777694978.diff
No OneTemporary

Size
9 KB
Referenced Files
None
Subscribers
None

D30635.1777694978.diff

diff --git a/lib/libc/sys/procctl.2 b/lib/libc/sys/procctl.2
--- a/lib/libc/sys/procctl.2
+++ b/lib/libc/sys/procctl.2
@@ -413,6 +413,16 @@
.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
--- a/share/man/man3/siginfo.3
+++ b/share/man/man3/siginfo.3
@@ -85,6 +85,8 @@
.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
--- a/sys/amd64/amd64/trap.c
+++ b/sys/amd64/amd64/trap.c
@@ -995,6 +995,7 @@
regcnt = NARGREGS;
sa->code = frame->tf_rax;
+ td->original_code = sa->code;
if (sa->code == SYS_syscall || sa->code == SYS___syscall) {
sa->code = frame->tf_rdi;
@@ -1040,6 +1041,7 @@
sa = &td->td_sa;
sa->code = frame->tf_rax;
+ td->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
--- a/sys/amd64/cloudabi32/cloudabi32_sysvec.c
+++ b/sys/amd64/cloudabi32/cloudabi32_sysvec.c
@@ -101,6 +101,7 @@
/* Obtain system call number. */
sa->code = frame->tf_rax;
+ td->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
--- a/sys/amd64/cloudabi64/cloudabi64_sysvec.c
+++ b/sys/amd64/cloudabi64/cloudabi64_sysvec.c
@@ -97,6 +97,7 @@
/* Obtain system call number. */
sa->code = frame->tf_rax;
+ td->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
--- a/sys/amd64/ia32/ia32_syscall.c
+++ b/sys/amd64/ia32/ia32_syscall.c
@@ -151,6 +151,7 @@
params = (caddr_t)frame->tf_rsp + sizeof(u_int32_t);
sa->code = frame->tf_rax;
+ td->original_code = sa->code;
/*
* Need to check if this is a 32 bit or 64 bit syscall.
diff --git a/sys/amd64/linux/linux_sysvec.c b/sys/amd64/linux/linux_sysvec.c
--- a/sys/amd64/linux/linux_sysvec.c
+++ b/sys/amd64/linux/linux_sysvec.c
@@ -191,6 +191,7 @@
sa->args[4] = frame->tf_r8;
sa->args[5] = frame->tf_r9;
sa->code = frame->tf_rax;
+ td->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
--- a/sys/amd64/linux32/linux32_sysvec.c
+++ b/sys/amd64/linux32/linux32_sysvec.c
@@ -657,6 +657,7 @@
sa->args[4] = frame->tf_rdi;
sa->args[5] = frame->tf_rbp; /* Unconfirmed */
sa->code = frame->tf_rax;
+ td->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
--- a/sys/arm/arm/syscall.c
+++ b/sys/arm/arm/syscall.c
@@ -108,6 +108,7 @@
sa = &td->td_sa;
sa->code = td->td_frame->tf_r7;
+ td->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
--- a/sys/arm/cloudabi32/cloudabi32_sysvec.c
+++ b/sys/arm/cloudabi32/cloudabi32_sysvec.c
@@ -78,6 +78,7 @@
/* Obtain system call number. */
sa->code = frame->tf_r12;
+ td->original_code = sa->code;
if (sa->code >= CLOUDABI32_SYS_MAXSYSCALL)
return (ENOSYS);
sa->callp = &cloudabi32_sysent[sa->code];
diff --git a/sys/arm64/arm64/trap.c b/sys/arm64/arm64/trap.c
--- a/sys/arm64/arm64/trap.c
+++ b/sys/arm64/arm64/trap.c
@@ -109,6 +109,7 @@
sa = &td->td_sa;
sa->code = td->td_frame->tf_x[8];
+ td->original_code = sa->code;
if (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
--- a/sys/arm64/cloudabi32/cloudabi32_sysvec.c
+++ b/sys/arm64/cloudabi32/cloudabi32_sysvec.c
@@ -75,6 +75,7 @@
/* Obtain system call number. */
sa->code = frame->tf_x[0];
+ td->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
--- a/sys/arm64/cloudabi64/cloudabi64_sysvec.c
+++ b/sys/arm64/cloudabi64/cloudabi64_sysvec.c
@@ -78,6 +78,7 @@
/* Obtain system call number. */
sa->code = frame->tf_x[8];
+ td->original_code = sa->code;
if (sa->code >= CLOUDABI64_SYS_MAXSYSCALL)
return (ENOSYS);
sa->callp = &cloudabi64_sysent[sa->code];
diff --git a/sys/arm64/linux/linux_sysvec.c b/sys/arm64/linux/linux_sysvec.c
--- a/sys/arm64/linux/linux_sysvec.c
+++ b/sys/arm64/linux/linux_sysvec.c
@@ -118,6 +118,7 @@
sa = &td->td_sa;
sa->code = td->td_frame->tf_x[8];
+ td->original_code = sa->code;
/* LINUXTODO: generic syscall? */
if (p->p_sysent->sv_mask)
sa->code &= p->p_sysent->sv_mask;
diff --git a/sys/i386/cloudabi32/cloudabi32_sysvec.c b/sys/i386/cloudabi32/cloudabi32_sysvec.c
--- a/sys/i386/cloudabi32/cloudabi32_sysvec.c
+++ b/sys/i386/cloudabi32/cloudabi32_sysvec.c
@@ -96,6 +96,7 @@
/* Obtain system call number. */
sa->code = frame->tf_eax;
+ td->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
--- a/sys/i386/i386/trap.c
+++ b/sys/i386/i386/trap.c
@@ -1064,6 +1064,7 @@
#endif
sa->code = frame->tf_eax;
+ td->original_code = sa->code;
params = (caddr_t)frame->tf_esp + sizeof(uint32_t);
/*
diff --git a/sys/i386/linux/linux_sysvec.c b/sys/i386/linux/linux_sysvec.c
--- a/sys/i386/linux/linux_sysvec.c
+++ b/sys/i386/linux/linux_sysvec.c
@@ -739,6 +739,7 @@
sa = &td->td_sa;
sa->code = frame->tf_eax;
+ td->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/kern_fork.c b/sys/kern/kern_fork.c
--- a/sys/kern/kern_fork.c
+++ b/sys/kern/kern_fork.c
@@ -505,6 +505,19 @@
td2->td_vnet_lpush = NULL;
#endif
+ /*
+ * Propagate the system call number to the new thread. This should never
+ * be needed because if a system call was not blocked by Capsicum then this
+ * field will not be read. We never deliver a signal in the child if a
+ * system call is blocked in the parent.
+ *
+ * This is set anyway so that a future use of this field will have the same
+ * behaviour in the stable back-port branches as in 14-CURRENT (where this
+ * value is part of the system-call arguments structure and not the thread
+ * structure).
+ */
+ td2->original_code = td->original_code;
+
/*
* Allow the scheduler to initialize the child.
*/
diff --git a/sys/kern/subr_syscall.c b/sys/kern/subr_syscall.c
--- a/sys/kern/subr_syscall.c
+++ b/sys/kern/subr_syscall.c
@@ -199,6 +199,7 @@
ksi.ksi_signo = SIGTRAP;
ksi.ksi_errno = td->td_errno;
ksi.ksi_code = TRAP_CAP;
+ ksi.ksi_info.si_syscall = td->original_code;
trapsignal(td, &ksi);
}
}
diff --git a/sys/mips/mips/trap.c b/sys/mips/mips/trap.c
--- a/sys/mips/mips/trap.c
+++ b/sys/mips/mips/trap.c
@@ -355,6 +355,7 @@
else
locr0->pc += sizeof(int);
sa->code = locr0->v0;
+ td->original_code = sa->code;
switch (sa->code) {
case SYS___syscall:
diff --git a/sys/powerpc/powerpc/trap.c b/sys/powerpc/powerpc/trap.c
--- a/sys/powerpc/powerpc/trap.c
+++ b/sys/powerpc/powerpc/trap.c
@@ -582,6 +582,7 @@
sa = &td->td_sa;
sa->code = frame->fixreg[0];
+ td->original_code = sa->code;
params = (caddr_t)(frame->fixreg + FIRSTARG);
n = NARGREG;
diff --git a/sys/riscv/riscv/trap.c b/sys/riscv/riscv/trap.c
--- a/sys/riscv/riscv/trap.c
+++ b/sys/riscv/riscv/trap.c
@@ -105,6 +105,7 @@
ap = &td->td_frame->tf_a[0];
sa->code = td->td_frame->tf_t[0];
+ td->original_code = sa->code;
if (sa->code == SYS_syscall || sa->code == SYS___syscall) {
sa->code = *ap++;
diff --git a/sys/sys/proc.h b/sys/sys/proc.h
--- a/sys/sys/proc.h
+++ b/sys/sys/proc.h
@@ -372,6 +372,8 @@
struct mdthread td_md; /* (k) Any machine-dependent fields. */
#endif
int td_pflags2; /* (k) Private thread (TDP2_*) flags. */
+ int original_code; /* System call number. Undefined when
+ not in a syscall. */
};
struct thread0_storage {
diff --git a/sys/sys/signal.h b/sys/sys/signal.h
--- a/sys/sys/signal.h
+++ b/sys/sys/signal.h
@@ -255,6 +255,12 @@
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 @@
#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 {

File Metadata

Mime Type
text/plain
Expires
Sat, May 2, 4:09 AM (21 h, 2 m)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
28529966
Default Alt Text
D30635.1777694978.diff (9 KB)

Event Timeline