ktrace: Record syscall violations with KTR_CAPFAIL

Report syscalls that are not allowed in capability mode with
CAPFAIL_SYSCALL.

Reviewed by:	markj
Approved by:	markj (mentor)
MFC after:	1 month
Differential Revision:	https://reviews.freebsd.org/D40678
This commit is contained in:
Jake Freeland 2024-04-06 13:31:18 -05:00
parent 96c8b3e509
commit 05296a0ff6
6 changed files with 70 additions and 66 deletions

View file

@ -187,35 +187,33 @@ sysarch(struct thread *td, struct sysarch_args *uap)
* explicitly indicate whether or not the operation is safe to
* perform in capability mode.
*/
if (IN_CAPABILITY_MODE(td)) {
switch (uap->op) {
case I386_GET_LDT:
case I386_SET_LDT:
case I386_GET_IOPERM:
case I386_GET_FSBASE:
case I386_SET_FSBASE:
case I386_GET_GSBASE:
case I386_SET_GSBASE:
case I386_GET_XFPUSTATE:
case I386_SET_PKRU:
case I386_CLEAR_PKRU:
case AMD64_GET_FSBASE:
case AMD64_SET_FSBASE:
case AMD64_GET_GSBASE:
case AMD64_SET_GSBASE:
case AMD64_GET_XFPUSTATE:
case AMD64_SET_PKRU:
case AMD64_CLEAR_PKRU:
break;
switch (uap->op) {
case I386_GET_LDT:
case I386_SET_LDT:
case I386_GET_IOPERM:
case I386_GET_FSBASE:
case I386_SET_FSBASE:
case I386_GET_GSBASE:
case I386_SET_GSBASE:
case I386_GET_XFPUSTATE:
case I386_SET_PKRU:
case I386_CLEAR_PKRU:
case AMD64_GET_FSBASE:
case AMD64_SET_FSBASE:
case AMD64_GET_GSBASE:
case AMD64_SET_GSBASE:
case AMD64_GET_XFPUSTATE:
case AMD64_SET_PKRU:
case AMD64_CLEAR_PKRU:
break;
case I386_SET_IOPERM:
default:
#ifdef KTRACE
if (KTRPOINT(td, KTR_CAPFAIL))
ktrcapfail(CAPFAIL_SYSCALL, NULL, NULL);
#endif
case I386_SET_IOPERM:
default:
if (CAP_TRACING(td))
ktrcapfail(CAPFAIL_SYSCALL, &uap->op);
if (IN_CAPABILITY_MODE(td))
return (ECAPMODE);
}
break;
}
#endif

View file

@ -175,22 +175,19 @@ sysarch(struct thread *td, struct sysarch_args *uap)
* explicitly indicate whether or not the operation is safe to
* perform in capability mode.
*/
if (IN_CAPABILITY_MODE(td)) {
switch (uap->op) {
case ARM_SYNC_ICACHE:
case ARM_DRAIN_WRITEBUF:
case ARM_SET_TP:
case ARM_GET_TP:
case ARM_GET_VFPSTATE:
break;
switch (uap->op) {
case ARM_SYNC_ICACHE:
case ARM_DRAIN_WRITEBUF:
case ARM_SET_TP:
case ARM_GET_TP:
case ARM_GET_VFPSTATE:
break;
default:
#ifdef KTRACE
if (KTRPOINT(td, KTR_CAPFAIL))
ktrcapfail(CAPFAIL_SYSCALL, NULL, NULL);
#endif
default:
if (CAP_TRACING(td))
ktrcapfail(CAPFAIL_SYSCALL, &uap->op);
if (IN_CAPABILITY_MODE(td))
return (ECAPMODE);
}
}
#endif

View file

@ -152,26 +152,24 @@ sysarch(struct thread *td, struct sysarch_args *uap)
* explicitly indicate whether or not the operation is safe to
* perform in capability mode.
*/
if (IN_CAPABILITY_MODE(td)) {
switch (uap->op) {
case I386_GET_LDT:
case I386_SET_LDT:
case I386_GET_IOPERM:
case I386_GET_FSBASE:
case I386_SET_FSBASE:
case I386_GET_GSBASE:
case I386_SET_GSBASE:
case I386_GET_XFPUSTATE:
break;
switch (uap->op) {
case I386_GET_LDT:
case I386_SET_LDT:
case I386_GET_IOPERM:
case I386_GET_FSBASE:
case I386_SET_FSBASE:
case I386_GET_GSBASE:
case I386_SET_GSBASE:
case I386_GET_XFPUSTATE:
break;
case I386_SET_IOPERM:
default:
#ifdef KTRACE
if (KTRPOINT(td, KTR_CAPFAIL))
ktrcapfail(CAPFAIL_SYSCALL, NULL, NULL);
#endif
case I386_SET_IOPERM:
default:
if (CAP_TRACING(td))
ktrcapfail(CAPFAIL_SYSCALL, &uap->op);
if (IN_CAPABILITY_MODE(td))
return (ECAPMODE);
}
break;
}
#endif

View file

@ -875,6 +875,8 @@ kern_fcntl(struct thread *td, int fd, int cmd, intptr_t arg)
case F_KINFO:
#ifdef CAPABILITY_MODE
if (CAP_TRACING(td))
ktrcapfail(CAPFAIL_SYSCALL, &cmd);
if (IN_CAPABILITY_MODE(td)) {
error = ECAPMODE;
break;

View file

@ -2677,10 +2677,16 @@ ptrace_syscallreq(struct thread *td, struct proc *p,
&td->td_proc->p_cowgen)))
thread_cow_update(td);
td->td_sa = tsr->ts_sa;
#ifdef CAPABILITY_MODE
if (IN_CAPABILITY_MODE(td) && (se->sy_flags & SYF_CAPENABLED) == 0) {
tsr->ts_ret.sr_error = ECAPMODE;
return;
if ((se->sy_flags & SYF_CAPENABLED) == 0) {
if (CAP_TRACING(td))
ktrcapfail(CAPFAIL_SYSCALL, NULL);
if (IN_CAPABILITY_MODE(td)) {
tsr->ts_ret.sr_error = ECAPMODE;
return;
}
}
#endif

View file

@ -118,10 +118,13 @@ syscallenter(struct thread *td)
* In capability mode, we only allow access to system calls
* flagged with SYF_CAPENABLED.
*/
if (__predict_false(IN_CAPABILITY_MODE(td) &&
(se->sy_flags & SYF_CAPENABLED) == 0)) {
td->td_errno = error = ECAPMODE;
goto retval;
if ((se->sy_flags & SYF_CAPENABLED) == 0) {
if (CAP_TRACING(td))
ktrcapfail(CAPFAIL_SYSCALL, NULL);
if (IN_CAPABILITY_MODE(td)) {
td->td_errno = error = ECAPMODE;
goto retval;
}
}
#endif