git: 05296a0ff615 - main - ktrace: Record syscall violations with KTR_CAPFAIL

From: Jake Freeland <jfree_at_FreeBSD.org>
Date: Sun, 07 Apr 2024 23:57:08 UTC
The branch main has been updated by jfree:

URL: https://cgit.FreeBSD.org/src/commit/?id=05296a0ff615566d25c77c5e6619b08724d2eecb

commit 05296a0ff615566d25c77c5e6619b08724d2eecb
Author:     Jake Freeland <jfree@FreeBSD.org>
AuthorDate: 2024-04-06 18:31:18 +0000
Commit:     Jake Freeland <jfree@FreeBSD.org>
CommitDate: 2024-04-07 23:52:51 +0000

    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
---
 sys/amd64/amd64/sys_machdep.c | 52 +++++++++++++++++++++----------------------
 sys/arm/arm/sys_machdep.c     | 27 ++++++++++------------
 sys/i386/i386/sys_machdep.c   | 34 +++++++++++++---------------
 sys/kern/kern_descrip.c       |  2 ++
 sys/kern/kern_sig.c           | 12 +++++++---
 sys/kern/subr_syscall.c       | 11 +++++----
 6 files changed, 71 insertions(+), 67 deletions(-)

diff --git a/sys/amd64/amd64/sys_machdep.c b/sys/amd64/amd64/sys_machdep.c
index dd4eef610147..b626925e1ea1 100644
--- a/sys/amd64/amd64/sys_machdep.c
+++ b/sys/amd64/amd64/sys_machdep.c
@@ -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
 
diff --git a/sys/arm/arm/sys_machdep.c b/sys/arm/arm/sys_machdep.c
index bf738ed77a67..50cdc4158517 100644
--- a/sys/arm/arm/sys_machdep.c
+++ b/sys/arm/arm/sys_machdep.c
@@ -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;
-
-		default:
-#ifdef KTRACE
-			if (KTRPOINT(td, KTR_CAPFAIL))
-				ktrcapfail(CAPFAIL_SYSCALL, NULL, NULL);
-#endif
+	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:
+		if (CAP_TRACING(td))
+			ktrcapfail(CAPFAIL_SYSCALL, &uap->op);
+		if (IN_CAPABILITY_MODE(td))
 			return (ECAPMODE);
-		}
 	}
 #endif
 
diff --git a/sys/i386/i386/sys_machdep.c b/sys/i386/i386/sys_machdep.c
index 2da60bd438d1..e29d98a61cb9 100644
--- a/sys/i386/i386/sys_machdep.c
+++ b/sys/i386/i386/sys_machdep.c
@@ -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
 
diff --git a/sys/kern/kern_descrip.c b/sys/kern/kern_descrip.c
index 7f9318a7ceda..f626f5a38ca8 100644
--- a/sys/kern/kern_descrip.c
+++ b/sys/kern/kern_descrip.c
@@ -875,6 +875,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;
diff --git a/sys/kern/kern_sig.c b/sys/kern/kern_sig.c
index a2ca74ac9183..8fa0942a5496 100644
--- a/sys/kern/kern_sig.c
+++ b/sys/kern/kern_sig.c
@@ -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
 
diff --git a/sys/kern/subr_syscall.c b/sys/kern/subr_syscall.c
index 8948cc0517a5..22bc35774e70 100644
--- a/sys/kern/subr_syscall.c
+++ b/sys/kern/subr_syscall.c
@@ -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