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

(cherry picked from commit 05296a0ff615566d25c77c5e6619b08724d2eecb)
This commit is contained in:
Jake Freeland 2024-04-06 13:31:18 -05:00
parent 85a4df5f2a
commit fa92eaede4
6 changed files with 70 additions and 66 deletions

View file

@ -189,35 +189,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

@ -177,22 +177,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

@ -154,26 +154,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

@ -877,6 +877,8 @@ revert_f_setfl:
case F_KINFO:
#ifdef CAPABILITY_MODE
if (CAP_TRACING(td))
ktrcapfail(CAPFAIL_SYSCALL, &cmd);
if (IN_CAPABILITY_MODE(td)) {
error = ECAPMODE;
break;

View file

@ -2690,10 +2690,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

@ -120,10 +120,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