git: 85a4df5f2a6b - stable/14 - ktrace: Record cpuset violations with KTR_CAPFAIL

From: Jake Freeland <jfree_at_FreeBSD.org>
Date: Sun, 12 May 2024 00:08:27 UTC
The branch stable/14 has been updated by jfree:

URL: https://cgit.FreeBSD.org/src/commit/?id=85a4df5f2a6bae3e2ecdf311150f17f6063600d2

commit 85a4df5f2a6bae3e2ecdf311150f17f6063600d2
Author:     Jake Freeland <jfree@FreeBSD.org>
AuthorDate: 2024-04-06 18:31:14 +0000
Commit:     Jake Freeland <jfree@FreeBSD.org>
CommitDate: 2024-05-11 23:57:44 +0000

    ktrace: Record cpuset violations with KTR_CAPFAIL
    
    Report Capsicum violations in the cpuset namespace with CAPFAIL_CPUSET.
    
    Reviewed by:    markj
    Approved by:    markj (mentor)
    MFC after:      1 month
    Differential Revision:  https://reviews.freebsd.org/D40677
    
    (cherry picked from commit 96c8b3e509882e5a51a5ae58d366b812be4d2773)
---
 sys/kern/kern_cpuset.c | 40 ++++++++++++++++++++++++++++------------
 1 file changed, 28 insertions(+), 12 deletions(-)

diff --git a/sys/kern/kern_cpuset.c b/sys/kern/kern_cpuset.c
index 17176afa6ad3..5d9e2f2f326b 100644
--- a/sys/kern/kern_cpuset.c
+++ b/sys/kern/kern_cpuset.c
@@ -1762,22 +1762,38 @@ cpuset_setproc_update_set(struct proc *p, struct cpuset *set)
  * In Capability mode, the only accesses that are permitted are to the current
  * thread and process' CPU and domain sets.
  */
+static bool
+cpuset_capmode_allowed(struct thread *td, cpulevel_t level, cpuwhich_t which,
+    id_t id)
+{
+	if (level != CPU_LEVEL_WHICH)
+		return (false);
+	if (which != CPU_WHICH_TID && which != CPU_WHICH_PID &&
+	    which != CPU_WHICH_TIDPID)
+		return (false);
+	if (id != -1 && which == CPU_WHICH_TIDPID &&
+	    id != td->td_tid && id != td->td_proc->p_pid)
+		return (false);
+	if (id != -1 &&
+	    !(which == CPU_WHICH_TID && id == td->td_tid) &&
+	    !(which == CPU_WHICH_PID && id == td->td_proc->p_pid))
+		return (false);
+	return (true);
+}
+
+/*
+ * Check for capability violations and record them if ktrace(2) is active.
+ */
 static int
 cpuset_check_capabilities(struct thread *td, cpulevel_t level, cpuwhich_t which,
     id_t id)
 {
-	if (IN_CAPABILITY_MODE(td)) {
-		if (level != CPU_LEVEL_WHICH)
-			return (ECAPMODE);
-		if (which != CPU_WHICH_TID && which != CPU_WHICH_PID &&
-		    which != CPU_WHICH_TIDPID)
-			return (ECAPMODE);
-		if (id != -1 && which == CPU_WHICH_TIDPID &&
-		    id != td->td_tid && id != td->td_proc->p_pid)
-			return (ECAPMODE);
-		if (id != -1 &&
-		    !(which == CPU_WHICH_TID && id == td->td_tid) &&
-		    !(which == CPU_WHICH_PID && id == td->td_proc->p_pid))
+	if (IN_CAPABILITY_MODE(td) || CAP_TRACING(td)) {
+		if (cpuset_capmode_allowed(td, level, which, id))
+			return (0);
+		if (CAP_TRACING(td))
+			ktrcapfail(CAPFAIL_CPUSET, NULL);
+		if (IN_CAPABILITY_MODE(td))
 			return (ECAPMODE);
 	}
 	return (0);