Page Menu
Home
FreeBSD
Search
Configure Global Search
Log In
Files
F169541782
D30130.id90518.diff
No One
Temporary
Actions
View File
Edit File
Delete File
View Transforms
Subscribe
Mute Notifications
Flag For Later
Award Token
Size
11 KB
Referenced Files
None
Subscribers
None
D30130.id90518.diff
View Options
Index: lib/libc/sys/procctl.2
===================================================================
--- lib/libc/sys/procctl.2
+++ lib/libc/sys/procctl.2
@@ -564,6 +564,30 @@
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 created by
+.Xr execve 2
+in the specified process or its 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 SETUID/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
.Sh x86 MACHINE-SPECIFIC REQUESTS
.Bl -tag -width PROC_KPTI_STATUS
Index: sys/compat/linux/linux_misc.c
===================================================================
--- sys/compat/linux/linux_misc.c
+++ sys/compat/linux/linux_misc.c
@@ -1968,7 +1968,7 @@
int
linux_prctl(struct thread *td, struct linux_prctl_args *args)
{
- int error = 0, max_size;
+ int error = 0, max_size, arg;
struct proc *p = td->td_proc;
char comm[LINUX_MAX_COMM_LEN];
int pdeath_signal, trace_state;
@@ -2099,8 +2099,10 @@
error = EINVAL;
break;
case LINUX_PR_SET_NO_NEW_PRIVS:
- linux_msg(td, "unsupported prctl PR_SET_NO_NEW_PRIVS");
- error = EINVAL;
+ arg = args->arg2 == 1 ?
+ PROC_NO_NEW_PRIVS_ENABLE : PROC_NO_NEW_PRIVS_DISABLE;
+ error = kern_procctl(td, P_PID, p->p_pid,
+ PROC_NO_NEW_PRIVS_CTL, &arg);
break;
case LINUX_PR_SET_PTRACER:
linux_msg(td, "unsupported prctl PR_SET_PTRACER");
Index: sys/kern/kern_exec.c
===================================================================
--- sys/kern/kern_exec.c
+++ sys/kern/kern_exec.c
@@ -782,6 +782,9 @@
!(*imgp->sysent->sv_setid_allowed)(td, imgp))
execve_nosetid(imgp);
+ if (p->p_flag2 & P2_NO_NEW_PRIVS)
+ execve_nosetid(imgp);
+
/*
* Implement image setuid/setgid installation.
*/
Index: sys/kern/kern_fork.c
===================================================================
--- sys/kern/kern_fork.c
+++ sys/kern/kern_fork.c
@@ -492,7 +492,7 @@
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);
Index: sys/kern/kern_procctl.c
===================================================================
--- sys/kern/kern_procctl.c
+++ sys/kern/kern_procctl.c
@@ -419,6 +419,31 @@
return (0);
}
+static int
+no_new_privs_ctl(struct thread *td, struct proc *p, int state)
+{
+
+ PROC_LOCK_ASSERT(p, MA_OWNED);
+
+ switch (state) {
+ case PROC_NO_NEW_PRIVS_ENABLE:
+ p->p_flag2 |= P2_NO_NEW_PRIVS;
+ break;
+ default:
+ return (EINVAL);
+ }
+ 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)
{
@@ -600,6 +625,7 @@
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);
@@ -631,6 +657,7 @@
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:
@@ -661,6 +688,7 @@
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;
@@ -710,6 +738,10 @@
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);
}
@@ -740,6 +772,8 @@
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);
}
@@ -772,6 +806,7 @@
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;
@@ -788,6 +823,7 @@
case PROC_STACKGAP_STATUS:
case PROC_TRACE_STATUS:
case PROC_TRAPCAP_STATUS:
+ case PROC_NO_NEW_PRIVS_STATUS:
tree_locked = false;
break;
default:
Index: sys/kern/vfs_syscalls.c
===================================================================
--- sys/kern/vfs_syscalls.c
+++ sys/kern/vfs_syscalls.c
@@ -955,6 +955,10 @@
return (0);
}
+static int unprivileged_chroot = 0;
+SYSCTL_INT(_security_bsd, OID_AUTO, unprivileged_chroot, CTLFLAG_RW,
+ &unprivileged_chroot, 0,
+ "Unprivileged processes can use chroot(2)");
/*
* Change notion of root (``/'') directory.
*/
@@ -967,11 +971,20 @@
sys_chroot(struct thread *td, struct chroot_args *uap)
{
struct nameidata nd;
+ struct proc *p;
int error;
error = priv_check(td, PRIV_VFS_CHROOT);
- if (error != 0)
- return (error);
+ if (error != 0) {
+ p = td->td_proc;
+ PROC_LOCK(p);
+ if (unprivileged_chroot == 0 ||
+ (p->p_flag2 & P2_NO_NEW_PRIVS) == 0) {
+ PROC_UNLOCK(p);
+ return (error);
+ }
+ PROC_UNLOCK(p);
+ }
NDINIT(&nd, LOOKUP, FOLLOW | LOCKSHARED | LOCKLEAF | AUDITVNODE1,
UIO_USERSPACE, uap->path, td);
error = namei(&nd);
Index: sys/sys/proc.h
===================================================================
--- sys/sys/proc.h
+++ sys/sys/proc.h
@@ -833,6 +833,7 @@
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 */
Index: sys/sys/procctl.h
===================================================================
--- sys/sys/procctl.h
+++ 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 @@
#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 *);
Index: usr.bin/proccontrol/proccontrol.1
===================================================================
--- usr.bin/proccontrol/proccontrol.1
+++ usr.bin/proccontrol/proccontrol.1
@@ -69,6 +69,9 @@
.It Ar protmax
Controls the implicit PROT_MAX application for
.Xr mmap 2 .
+.It Ar nonewprivs
+Controls disabling the setuid and sgid bits for
+.Xr execve 2 .
.It Ar kpti
Controls the KPTI enable, AMD64 only.
.It Ar la48
Index: usr.bin/proccontrol/proccontrol.c
===================================================================
--- usr.bin/proccontrol/proccontrol.c
+++ usr.bin/proccontrol/proccontrol.c
@@ -45,6 +45,7 @@
MODE_TRAPCAP,
MODE_PROTMAX,
MODE_STACKGAP,
+ MODE_NO_NEW_PRIVS,
#ifdef PROC_KPTI_CTL
MODE_KPTI,
#endif
@@ -84,7 +85,7 @@
{
fprintf(stderr, "Usage: proccontrol -m (aslr|protmax|trace|trapcap|"
- "stackgap"KPTI_USAGE LA_USAGE") [-q] "
+ "stackgap|nonewprivs"KPTI_USAGE LA_USAGE") [-q] "
"[-s (enable|disable)] [-p pid | command]\n");
exit(1);
}
@@ -113,6 +114,8 @@
mode = MODE_TRAPCAP;
else if (strcmp(optarg, "stackgap") == 0)
mode = MODE_STACKGAP;
+ else if (strcmp(optarg, "nonewprivs") == 0)
+ mode = MODE_NO_NEW_PRIVS;
#ifdef PROC_KPTI_CTL
else if (strcmp(optarg, "kpti") == 0)
mode = MODE_KPTI;
@@ -174,6 +177,9 @@
case MODE_STACKGAP:
error = procctl(P_PID, pid, PROC_STACKGAP_STATUS, &arg);
break;
+ case MODE_NO_NEW_PRIVS:
+ error = procctl(P_PID, pid, PROC_NO_NEW_PRIVS_STATUS, &arg);
+ break;
#ifdef PROC_KPTI_CTL
case MODE_KPTI:
error = procctl(P_PID, pid, PROC_KPTI_STATUS, &arg);
@@ -264,6 +270,16 @@
break;
}
break;
+ case MODE_NO_NEW_PRIVS:
+ switch (arg) {
+ case PROC_NO_NEW_PRIVS_ENABLE:
+ printf("enabled\n");
+ break;
+ case PROC_NO_NEW_PRIVS_DISABLE:
+ printf("disabled\n");
+ break;
+ }
+ break;
#ifdef PROC_KPTI_CTL
case MODE_KPTI:
switch (arg & ~PROC_KPTI_STATUS_ACTIVE) {
@@ -330,6 +346,11 @@
PROC_STACKGAP_DISABLE_EXEC);
error = procctl(P_PID, pid, PROC_STACKGAP_CTL, &arg);
break;
+ case MODE_NO_NEW_PRIVS:
+ arg = enable ? PROC_NO_NEW_PRIVS_ENABLE :
+ PROC_NO_NEW_PRIVS_DISABLE;
+ error = procctl(P_PID, pid, PROC_NO_NEW_PRIVS_CTL, &arg);
+ break;
#ifdef PROC_KPTI_CTL
case MODE_KPTI:
arg = enable ? PROC_KPTI_CTL_ENABLE_ON_EXEC :
Index: usr.sbin/chroot/chroot.8
===================================================================
--- usr.sbin/chroot/chroot.8
+++ usr.sbin/chroot/chroot.8
@@ -39,6 +39,7 @@
.Op Fl G Ar group Ns Op Cm \&, Ns Ar group ...
.Op Fl g Ar group
.Op Fl u Ar user
+.Op Fl n
.Ar newroot
.Op Ar command Op Ar arg ...
.Sh DESCRIPTION
@@ -61,6 +62,8 @@
.It Fl u Ar user
Run the command as the
.Ar user .
+.It Fl n
+Run in non-privileged mode.
.El
.Sh ENVIRONMENT
The following environment variable is referenced by
Index: usr.sbin/chroot/chroot.c
===================================================================
--- usr.sbin/chroot/chroot.c
+++ usr.sbin/chroot/chroot.c
@@ -44,6 +44,7 @@
__FBSDID("$FreeBSD$");
#include <sys/types.h>
+#include <sys/procctl.h>
#include <ctype.h>
#include <err.h>
@@ -51,6 +52,7 @@
#include <limits.h>
#include <paths.h>
#include <pwd.h>
+#include <stdbool.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
@@ -67,13 +69,15 @@
const char *shell;
gid_t gid, *gidlist;
uid_t uid;
- int ch, gids;
+ int arg, ch, error, gids;
long ngroups_max;
+ bool nonpriviledged;
gid = 0;
uid = 0;
user = group = grouplist = NULL;
- while ((ch = getopt(argc, argv, "G:g:u:")) != -1) {
+ nonpriviledged = false;
+ while ((ch = getopt(argc, argv, "G:g:u:n")) != -1) {
switch(ch) {
case 'u':
user = optarg;
@@ -90,6 +94,9 @@
if (*grouplist == '\0')
usage();
break;
+ case 'n':
+ nonpriviledged = true;
+ break;
case '?':
default:
usage();
@@ -153,6 +160,13 @@
}
}
+ if (nonpriviledged) {
+ arg = PROC_NO_NEW_PRIVS_ENABLE;
+ error = procctl(P_PID, getpid(), PROC_NO_NEW_PRIVS_CTL, &arg);
+ if (error != 0)
+ err(1, "procctl");
+ }
+
if (chdir(argv[0]) == -1 || chroot(".") == -1)
err(1, "%s", argv[0]);
@@ -179,6 +193,6 @@
usage(void)
{
(void)fprintf(stderr, "usage: chroot [-g group] [-G group,group,...] "
- "[-u user] newroot [command]\n");
+ "[-u user] [-n ] newroot [command]\n");
exit(1);
}
File Metadata
Details
Attached
Mime Type
text/plain
Expires
Wed, Sep 2, 9:07 PM (1 h, 47 m)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
38013224
Default Alt Text
D30130.id90518.diff (11 KB)
Attached To
Mode
D30130: Unprivileged chroot
Attached
Detach File
Event Timeline
Log In to Comment