git: f9fa6cb391f8 - stable/14 - cred: Hide internal flag CRED_FLAG_CAPMODE

From: Olivier Certner <olce_at_FreeBSD.org>
Date: Tue, 08 Apr 2025 13:40:36 UTC
The branch stable/14 has been updated by olce:

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

commit f9fa6cb391f8811d12e566dbc91b34c8d6117d88
Author:     Olivier Certner <olce@FreeBSD.org>
AuthorDate: 2024-07-16 16:07:40 +0000
Commit:     Olivier Certner <olce@FreeBSD.org>
CommitDate: 2025-04-08 13:38:14 +0000

    cred: Hide internal flag CRED_FLAG_CAPMODE
    
    This flag is used in field 'cr_flags', which is never directly visible
    outside the kernel.  That field is however exported through 'struct
    kinfo_proc' objects (field 'ki_cr_flags'), either from the kernel via
    sysctls or from libkvm, and is supposed to contain exported flags
    prefixed with KI_CRF_ (currently, KI_CRF_CAPABILITY_MODE and
    KI_CRF_GRP_OVERFLOW, this second one being a purely userland one
    signaling overflow of 'ki_groups').
    
    Make sure that KI_CRF_CAPABILITY_MODE is the flag actually exported and
    tested by userland programs, and hide the internal CRED_FLAG_CAPMODE.
    As both flags are currently defined to the same value, this doesn't
    change the KBI, but of course does change the KPI.  A code search via
    GitHub and Google fortunately doesn't reveal any outside uses for
    CRED_FLAG_CAPMODE.
    
    While here, move assignment of 'ki_uid' to a more logical place in
    kvm_proclist(), and definition of XU_NGROUPS as well in 'sys/ucred.h'
    (no functional/interface changes intended).
    
    Reviewed by:    mhorne
    Approved by:    markj (mentor)
    MFC after:      2 weeks
    Sponsored by:   The FreeBSD Foundation
    Differential Revision:  https://reviews.freebsd.org/D46909
    
    (cherry picked from commit 09290c3a0c82524138973b14f393379edf733753)
    
    A ports exp-run (PR 283410) showed one port to be affected
    (sysutils/procs), which has been fixed upstream and in the ports tree.
    All additional indirect references to CRED_FLAG_CAPMODE we found after
    the code search mentioned in the original commit message are
    automatically generated from our headers by FFI mechanisms, so
    automatically disappear at recompilation (and the KBI is not changed, as
    explained above, so recompilation is not needed).
---
 bin/ps/print.c                   |  2 +-
 lib/libkvm/kvm_proc.c            |  6 ++++--
 sys/sys/ucred.h                  | 12 ++++++------
 usr.bin/procstat/procstat_cred.c |  2 +-
 4 files changed, 12 insertions(+), 10 deletions(-)

diff --git a/bin/ps/print.c b/bin/ps/print.c
index 30fbf8ed12de..8972cb14758b 100644
--- a/bin/ps/print.c
+++ b/bin/ps/print.c
@@ -275,7 +275,7 @@ state(KINFO *k, VARENT *ve __unused)
 		*cp++ = 'V';
 	if ((flag & P_SYSTEM) || k->ki_p->ki_lock > 0)
 		*cp++ = 'L';
-	if ((k->ki_p->ki_cr_flags & CRED_FLAG_CAPMODE) != 0)
+	if ((k->ki_p->ki_cr_flags & KI_CRF_CAPABILITY_MODE) != 0)
 		*cp++ = 'C';
 	if (k->ki_p->ki_kiflag & KI_SLEADER)
 		*cp++ = 's';
diff --git a/lib/libkvm/kvm_proc.c b/lib/libkvm/kvm_proc.c
index 0cd8d754eb04..6ad5d4a7cea6 100644
--- a/lib/libkvm/kvm_proc.c
+++ b/lib/libkvm/kvm_proc.c
@@ -144,11 +144,14 @@ kvm_proclist(kvm_t *kd, int what, int arg, struct proc *p,
 		if (proc.p_state == PRS_NEW)
 			continue;
 		if (KREAD(kd, (u_long)proc.p_ucred, &ucred) == 0) {
+			kp->ki_uid = ucred.cr_uid;
 			kp->ki_ruid = ucred.cr_ruid;
 			kp->ki_svuid = ucred.cr_svuid;
 			kp->ki_rgid = ucred.cr_rgid;
 			kp->ki_svgid = ucred.cr_svgid;
-			kp->ki_cr_flags = ucred.cr_flags;
+			kp->ki_cr_flags = 0;
+			if (ucred.cr_flags & CRED_FLAG_CAPMODE)
+				kp->ki_cr_flags |= KI_CRF_CAPABILITY_MODE;
 			if (ucred.cr_ngroups > KI_NGROUPS) {
 				kp->ki_ngroups = KI_NGROUPS;
 				kp->ki_cr_flags |= KI_CRF_GRP_OVERFLOW;
@@ -156,7 +159,6 @@ kvm_proclist(kvm_t *kd, int what, int arg, struct proc *p,
 				kp->ki_ngroups = ucred.cr_ngroups;
 			kvm_read(kd, (u_long)ucred.cr_groups, kp->ki_groups,
 			    kp->ki_ngroups * sizeof(gid_t));
-			kp->ki_uid = ucred.cr_uid;
 			if (ucred.cr_prison != NULL) {
 				if (KREAD(kd, (u_long)ucred.cr_prison, &pr)) {
 					_kvm_err(kd, kd->program,
diff --git a/sys/sys/ucred.h b/sys/sys/ucred.h
index 7df554884250..be7d5bab1d19 100644
--- a/sys/sys/ucred.h
+++ b/sys/sys/ucred.h
@@ -41,11 +41,14 @@
 #endif
 #include <bsm/audit.h>
 
+#if defined(_KERNEL) || defined(_WANT_UCRED)
 struct loginclass;
 
-#define	XU_NGROUPS	16
+/*
+ * Flags for cr_flags.
+ */
+#define	CRED_FLAG_CAPMODE	0x00000001	/* In capability mode. */
 
-#if defined(_KERNEL) || defined(_WANT_UCRED)
 /*
  * Number of groups inlined in 'struct ucred'.  It must stay reasonably low as
  * it is also used by some functions to allocate an array of this size on the
@@ -103,10 +106,7 @@ struct ucred {
 #define	FSCRED	((struct ucred *)-1)	/* filesystem credential */
 #endif /* _KERNEL || _WANT_UCRED */
 
-/*
- * Flags for cr_flags.
- */
-#define	CRED_FLAG_CAPMODE	0x00000001	/* In capability mode. */
+#define	XU_NGROUPS	16
 
 /*
  * This is the external representation of struct ucred.
diff --git a/usr.bin/procstat/procstat_cred.c b/usr.bin/procstat/procstat_cred.c
index f37a328e362f..9f6e6ae199c6 100644
--- a/usr.bin/procstat/procstat_cred.c
+++ b/usr.bin/procstat/procstat_cred.c
@@ -63,7 +63,7 @@ procstat_cred(struct procstat *procstat, struct kinfo_proc *kipp)
 	xo_emit("{:rgid/%5d} ", kipp->ki_rgid);
 	xo_emit("{:svgid/%5d} ", kipp->ki_svgid);
 	xo_emit("{:umask/%5s} ", get_umask(procstat, kipp));
-	xo_emit("{:cr_flags/%s}", kipp->ki_cr_flags & CRED_FLAG_CAPMODE ?
+	xo_emit("{:cr_flags/%s}", kipp->ki_cr_flags & KI_CRF_CAPABILITY_MODE ?
 	    "C" : "-");
 	xo_emit("{P:     }");