git: e79a18dadf83 - stable/13 - procctl(2): add PROC_NO_NEW_PRIVS_CTL, PROC_NO_NEW_PRIVS_STATUS

Konstantin Belousov kib at FreeBSD.org
Fri Sep 24 00:40:03 UTC 2021


The branch stable/13 has been updated by kib:

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

commit e79a18dadf83b7bdcab1c2ba8b43b9a508810d22
Author:     Edward Tomasz Napierala <trasz at FreeBSD.org>
AuthorDate: 2021-07-01 08:11:11 +0000
Commit:     Konstantin Belousov <kib at FreeBSD.org>
CommitDate: 2021-09-24 00:26:59 +0000

    procctl(2): add PROC_NO_NEW_PRIVS_CTL, PROC_NO_NEW_PRIVS_STATUS
    
    (cherry picked from commit db8d680ebe9b12c7d9e0eb8bf9940fcef709f5ec)
---
 lib/libc/sys/procctl.2                | 27 ++++++++++++++++++++++++++-
 sys/compat/freebsd32/freebsd32_misc.c |  3 +++
 sys/kern/kern_exec.c                  |  5 +++--
 sys/kern/kern_fork.c                  |  2 +-
 sys/kern/kern_procctl.c               | 32 ++++++++++++++++++++++++++++++++
 sys/sys/proc.h                        |  1 +
 sys/sys/procctl.h                     |  5 +++++
 7 files changed, 71 insertions(+), 4 deletions(-)

diff --git a/lib/libc/sys/procctl.2 b/lib/libc/sys/procctl.2
index f85825d8cc6f..432ed5919a81 100644
--- a/lib/libc/sys/procctl.2
+++ b/lib/libc/sys/procctl.2
@@ -29,7 +29,7 @@
 .\"
 .\" $FreeBSD$
 .\"
-.Dd June 13, 2020
+.Dd July 1, 2021
 .Dt PROCCTL 2
 .Os
 .Sh NAME
@@ -564,6 +564,31 @@ Stack gaps are enabled in the process after
 Stack gaps are disabled in the process after
 .Xr execve 2 .
 .El
+.It Dv PROC_NO_NEW_PRIVS_CTL
+Allows one to ignore the SUID and SGID bits on the program
+images activated by
+.Xr execve 2
+in the specified process and its future descendants.
+The
+.Fa data
+parameter must point to the integer variable holding the following
+value:
+.Bl -tag -width PROC_NO_NEW_PRIVS_ENABLE
+.It Dv PROC_NO_NEW_PRIVS_ENABLE
+Request SUID and SGID bits to be ignored.
+.El
+.Pp
+It is not possible to disable it once it has been enabled.
+.It Dv PROC_NO_NEW_PRIVS_STATUS
+Returns the current status of SUID/SGID enablement for the target process.
+The
+.Fa data
+parameter must point to the integer variable, where one of the
+following values is written:
+.Bl -tag -width PROC_NO_NEW_PRIVS_DISABLE
+.It Dv PROC_NO_NEW_PRIVS_ENABLE
+.It Dv PROC_NO_NEW_PRIVS_DISABLE
+.El
 .El
 .Sh x86 MACHINE-SPECIFIC REQUESTS
 .Bl -tag -width PROC_KPTI_STATUS
diff --git a/sys/compat/freebsd32/freebsd32_misc.c b/sys/compat/freebsd32/freebsd32_misc.c
index d258afa2352d..cefae53b69df 100644
--- a/sys/compat/freebsd32/freebsd32_misc.c
+++ b/sys/compat/freebsd32/freebsd32_misc.c
@@ -3631,6 +3631,7 @@ freebsd32_procctl(struct thread *td, struct freebsd32_procctl_args *uap)
 	case PROC_STACKGAP_CTL:
 	case PROC_TRACE_CTL:
 	case PROC_TRAPCAP_CTL:
+	case PROC_NO_NEW_PRIVS_CTL:
 		error = copyin(PTRIN(uap->data), &flags, sizeof(flags));
 		if (error != 0)
 			return (error);
@@ -3664,6 +3665,7 @@ freebsd32_procctl(struct thread *td, struct freebsd32_procctl_args *uap)
 	case PROC_STACKGAP_STATUS:
 	case PROC_TRACE_STATUS:
 	case PROC_TRAPCAP_STATUS:
+	case PROC_NO_NEW_PRIVS_STATUS:
 		data = &flags;
 		break;
 	case PROC_PDEATHSIG_CTL:
@@ -3695,6 +3697,7 @@ freebsd32_procctl(struct thread *td, struct freebsd32_procctl_args *uap)
 	case PROC_STACKGAP_STATUS:
 	case PROC_TRACE_STATUS:
 	case PROC_TRAPCAP_STATUS:
+	case PROC_NO_NEW_PRIVS_STATUS:
 		if (error == 0)
 			error = copyout(&flags, uap->data, sizeof(flags));
 		break;
diff --git a/sys/kern/kern_exec.c b/sys/kern/kern_exec.c
index 491e5332c834..0611eedcec73 100644
--- a/sys/kern/kern_exec.c
+++ b/sys/kern/kern_exec.c
@@ -776,8 +776,9 @@ interpret:
 		signotify(td);
 	}
 
-	if (imgp->sysent->sv_setid_allowed != NULL &&
-	    !(*imgp->sysent->sv_setid_allowed)(td, imgp))
+	if ((imgp->sysent->sv_setid_allowed != NULL &&
+	    !(*imgp->sysent->sv_setid_allowed)(td, imgp)) ||
+	    (p->p_flag2 & P2_NO_NEW_PRIVS) != 0)
 		execve_nosetid(imgp);
 
 	/*
diff --git a/sys/kern/kern_fork.c b/sys/kern/kern_fork.c
index 0d0659b432fe..7a80f7de85d8 100644
--- a/sys/kern/kern_fork.c
+++ b/sys/kern/kern_fork.c
@@ -492,7 +492,7 @@ do_fork(struct thread *td, struct fork_req *fr, struct proc *p2, struct thread *
 	p2->p_flag2 = p1->p_flag2 & (P2_ASLR_DISABLE | P2_ASLR_ENABLE |
 	    P2_ASLR_IGNSTART | P2_NOTRACE | P2_NOTRACE_EXEC |
 	    P2_PROTMAX_ENABLE | P2_PROTMAX_DISABLE | P2_TRAPCAP |
-	    P2_STKGAP_DISABLE | P2_STKGAP_DISABLE_EXEC);
+	    P2_STKGAP_DISABLE | P2_STKGAP_DISABLE_EXEC | P2_NO_NEW_PRIVS);
 	p2->p_swtick = ticks;
 	if (p1->p_flag & P_PROFIL)
 		startprofclock(p2);
diff --git a/sys/kern/kern_procctl.c b/sys/kern/kern_procctl.c
index b2694fd0c32c..68fa4bc0c3ac 100644
--- a/sys/kern/kern_procctl.c
+++ b/sys/kern/kern_procctl.c
@@ -419,6 +419,27 @@ trapcap_status(struct thread *td, struct proc *p, int *data)
 	return (0);
 }
 
+static int
+no_new_privs_ctl(struct thread *td, struct proc *p, int state)
+{
+
+	PROC_LOCK_ASSERT(p, MA_OWNED);
+
+	if (state != PROC_NO_NEW_PRIVS_ENABLE)
+		return (EINVAL);
+	p->p_flag2 |= P2_NO_NEW_PRIVS;
+	return (0);
+}
+
+static int
+no_new_privs_status(struct thread *td, struct proc *p, int *data)
+{
+
+	*data = (p->p_flag2 & P2_NO_NEW_PRIVS) != 0 ?
+	    PROC_NO_NEW_PRIVS_ENABLE : PROC_NO_NEW_PRIVS_DISABLE;
+	return (0);
+}
+
 static int
 protmax_ctl(struct thread *td, struct proc *p, int state)
 {
@@ -601,6 +622,7 @@ sys_procctl(struct thread *td, struct procctl_args *uap)
 	case PROC_STACKGAP_CTL:
 	case PROC_TRACE_CTL:
 	case PROC_TRAPCAP_CTL:
+	case PROC_NO_NEW_PRIVS_CTL:
 		error = copyin(uap->data, &flags, sizeof(flags));
 		if (error != 0)
 			return (error);
@@ -632,6 +654,7 @@ sys_procctl(struct thread *td, struct procctl_args *uap)
 	case PROC_STACKGAP_STATUS:
 	case PROC_TRACE_STATUS:
 	case PROC_TRAPCAP_STATUS:
+	case PROC_NO_NEW_PRIVS_STATUS:
 		data = &flags;
 		break;
 	case PROC_PDEATHSIG_CTL:
@@ -662,6 +685,7 @@ sys_procctl(struct thread *td, struct procctl_args *uap)
 	case PROC_STACKGAP_STATUS:
 	case PROC_TRACE_STATUS:
 	case PROC_TRAPCAP_STATUS:
+	case PROC_NO_NEW_PRIVS_STATUS:
 		if (error == 0)
 			error = copyout(&flags, uap->data, sizeof(flags));
 		break;
@@ -711,6 +735,10 @@ kern_procctl_single(struct thread *td, struct proc *p, int com, void *data)
 		return (trapcap_ctl(td, p, *(int *)data));
 	case PROC_TRAPCAP_STATUS:
 		return (trapcap_status(td, p, data));
+	case PROC_NO_NEW_PRIVS_CTL:
+		return (no_new_privs_ctl(td, p, *(int *)data));
+	case PROC_NO_NEW_PRIVS_STATUS:
+		return (no_new_privs_status(td, p, data));
 	default:
 		return (EINVAL);
 	}
@@ -741,6 +769,8 @@ kern_procctl(struct thread *td, idtype_t idtype, id_t id, int com, void *data)
 	case PROC_TRAPCAP_STATUS:
 	case PROC_PDEATHSIG_CTL:
 	case PROC_PDEATHSIG_STATUS:
+	case PROC_NO_NEW_PRIVS_CTL:
+	case PROC_NO_NEW_PRIVS_STATUS:
 		if (idtype != P_PID)
 			return (EINVAL);
 	}
@@ -773,6 +803,7 @@ kern_procctl(struct thread *td, idtype_t idtype, id_t id, int com, void *data)
 	case PROC_REAP_KILL:
 	case PROC_TRACE_CTL:
 	case PROC_TRAPCAP_CTL:
+	case PROC_NO_NEW_PRIVS_CTL:
 		sx_slock(&proctree_lock);
 		tree_locked = true;
 		break;
@@ -789,6 +820,7 @@ kern_procctl(struct thread *td, idtype_t idtype, id_t id, int com, void *data)
 	case PROC_STACKGAP_STATUS:
 	case PROC_TRACE_STATUS:
 	case PROC_TRAPCAP_STATUS:
+	case PROC_NO_NEW_PRIVS_STATUS:
 		tree_locked = false;
 		break;
 	default:
diff --git a/sys/sys/proc.h b/sys/sys/proc.h
index 138e763f2f11..15e175bf5aad 100644
--- a/sys/sys/proc.h
+++ b/sys/sys/proc.h
@@ -824,6 +824,7 @@ struct proc {
 						   after exec */
 #define	P2_ITSTOPPED		0x00002000
 #define	P2_PTRACEREQ		0x00004000	/* Active ptrace req */
+#define	P2_NO_NEW_PRIVS		0x00008000	/* Ignore setuid */
 
 /* Flags protected by proctree_lock, kept in p_treeflags. */
 #define	P_TREE_ORPHANED		0x00000001	/* Reparented, on orphan list */
diff --git a/sys/sys/procctl.h b/sys/sys/procctl.h
index 90fb149830dc..cc0279fb0d08 100644
--- a/sys/sys/procctl.h
+++ b/sys/sys/procctl.h
@@ -63,6 +63,8 @@
 #define	PROC_PROTMAX_STATUS	16	/* query implicit PROT_MAX status */
 #define	PROC_STACKGAP_CTL	17	/* en/dis stack gap on MAP_STACK */
 #define	PROC_STACKGAP_STATUS	18	/* query stack gap */
+#define	PROC_NO_NEW_PRIVS_CTL	19	/* disable setuid/setgid */
+#define	PROC_NO_NEW_PRIVS_STATUS 20	/* query suid/sgid disabled status */
 
 /* Operations for PROC_SPROTECT (passed in integer arg). */
 #define	PPROT_OP(x)	((x) & 0xf)
@@ -141,6 +143,9 @@ struct procctl_reaper_kill {
 #define	PROC_STACKGAP_ENABLE_EXEC	0x0004
 #define	PROC_STACKGAP_DISABLE_EXEC	0x0008
 
+#define	PROC_NO_NEW_PRIVS_ENABLE	1
+#define	PROC_NO_NEW_PRIVS_DISABLE	2
+
 #ifndef _KERNEL
 __BEGIN_DECLS
 int	procctl(idtype_t, id_t, int, void *);


More information about the dev-commits-src-branches mailing list