summaryrefslogtreecommitdiffstats
path: root/sys/kern
diff options
context:
space:
mode:
authorrwatson <rwatson@FreeBSD.org>2006-11-06 13:42:10 +0000
committerrwatson <rwatson@FreeBSD.org>2006-11-06 13:42:10 +0000
commit10d0d9cf473dc5f0ce1bf263ead445ffe7819154 (patch)
treeb9dd284620eeaddbff089cef10e4b1afb7918279 /sys/kern
parent7288104e2094825a9c98b9923f039817a76e2983 (diff)
downloadFreeBSD-src-10d0d9cf473dc5f0ce1bf263ead445ffe7819154.zip
FreeBSD-src-10d0d9cf473dc5f0ce1bf263ead445ffe7819154.tar.gz
Sweep kernel replacing suser(9) calls with priv(9) calls, assigning
specific privilege names to a broad range of privileges. These may require some future tweaking. Sponsored by: nCircle Network Security, Inc. Obtained from: TrustedBSD Project Discussed on: arch@ Reviewed (at least in part) by: mlaier, jmg, pjd, bde, ceri, Alex Lyashkov <umka at sevcity dot net>, Skip Ford <skip dot ford at verizon dot net>, Antoine Brodin <antoine dot brodin at laposte dot net>
Diffstat (limited to 'sys/kern')
-rw-r--r--sys/kern/kern_acct.c4
-rw-r--r--sys/kern/kern_descrip.c3
-rw-r--r--sys/kern/kern_environment.c14
-rw-r--r--sys/kern/kern_exec.c6
-rw-r--r--sys/kern/kern_fork.c8
-rw-r--r--sys/kern/kern_ktrace.c6
-rw-r--r--sys/kern/kern_linker.c5
-rw-r--r--sys/kern/kern_ntptime.c5
-rw-r--r--sys/kern/kern_resource.c8
-rw-r--r--sys/kern/kern_shutdown.c3
-rw-r--r--sys/kern/kern_sysctl.c11
-rw-r--r--sys/kern/kern_thr.c3
-rw-r--r--sys/kern/kern_time.c5
-rw-r--r--sys/kern/kern_umtx.c5
-rw-r--r--sys/kern/kern_xxx.c10
-rw-r--r--sys/kern/p1003_1b.c8
-rw-r--r--sys/kern/subr_acl_posix1e.c91
-rw-r--r--sys/kern/subr_firmware.c4
-rw-r--r--sys/kern/subr_prf.c3
-rw-r--r--sys/kern/subr_witness.c6
-rw-r--r--sys/kern/sysv_ipc.c104
-rw-r--r--sys/kern/sysv_msg.c3
-rw-r--r--sys/kern/tty.c14
-rw-r--r--sys/kern/tty_cons.c3
-rw-r--r--sys/kern/tty_pts.c7
-rw-r--r--sys/kern/tty_pty.c7
-rw-r--r--sys/kern/uipc_mqueue.c20
-rw-r--r--sys/kern/uipc_sem.c17
-rw-r--r--sys/kern/vfs_extattr.c68
-rw-r--r--sys/kern/vfs_mount.c30
-rw-r--r--sys/kern/vfs_subr.c63
-rw-r--r--sys/kern/vfs_syscalls.c68
-rw-r--r--sys/kern/vfs_vnops.c3
33 files changed, 367 insertions, 248 deletions
diff --git a/sys/kern/kern_acct.c b/sys/kern/kern_acct.c
index ec7289f..e3b108c 100644
--- a/sys/kern/kern_acct.c
+++ b/sys/kern/kern_acct.c
@@ -56,6 +56,7 @@ __FBSDID("$FreeBSD$");
#include <sys/mount.h>
#include <sys/mutex.h>
#include <sys/namei.h>
+#include <sys/priv.h>
#include <sys/proc.h>
#include <sys/resourcevar.h>
#include <sys/sched.h>
@@ -166,8 +167,7 @@ acct(struct thread *td, struct acct_args *uap)
struct nameidata nd;
int error, flags, vfslocked;
- /* Make sure that the caller is root. */
- error = suser(td);
+ error = priv_check(td, PRIV_ACCT);
if (error)
return (error);
diff --git a/sys/kern/kern_descrip.c b/sys/kern/kern_descrip.c
index b62c977..685222c 100644
--- a/sys/kern/kern_descrip.c
+++ b/sys/kern/kern_descrip.c
@@ -57,6 +57,7 @@ __FBSDID("$FreeBSD$");
#include <sys/mqueue.h>
#include <sys/mutex.h>
#include <sys/namei.h>
+#include <sys/priv.h>
#include <sys/proc.h>
#include <sys/resourcevar.h>
#include <sys/signalvar.h>
@@ -1351,7 +1352,7 @@ falloc(struct thread *td, struct file **resultfp, int *resultfd)
sx_xlock(&filelist_lock);
if ((openfiles >= maxuserfiles &&
- suser_cred(td->td_ucred, SUSER_RUID) != 0) ||
+ priv_check_cred(td->td_ucred, PRIV_MAXFILES, SUSER_RUID) != 0) ||
openfiles >= maxfiles) {
if (ppsratecheck(&lastfail, &curfail, 1)) {
printf("kern.maxfiles limit exceeded by uid %i, please see tuning(7).\n",
diff --git a/sys/kern/kern_environment.c b/sys/kern/kern_environment.c
index ff26529..1d33626 100644
--- a/sys/kern/kern_environment.c
+++ b/sys/kern/kern_environment.c
@@ -46,6 +46,7 @@ __FBSDID("$FreeBSD$");
#include <sys/lock.h>
#include <sys/malloc.h>
#include <sys/mutex.h>
+#include <sys/priv.h>
#include <sys/kernel.h>
#include <sys/systm.h>
#include <sys/sysent.h>
@@ -125,11 +126,18 @@ kenv(td, uap)
return (error);
}
- if ((uap->what == KENV_SET) ||
- (uap->what == KENV_UNSET)) {
- error = suser(td);
+ switch (uap->what) {
+ case KENV_SET:
+ error = priv_check(td, PRIV_KENV_SET);
+ if (error)
+ return (error);
+ break;
+
+ case KENV_UNSET:
+ error = priv_check(td, PRIV_KENV_UNSET);
if (error)
return (error);
+ break;
}
name = malloc(KENV_MNAMELEN, M_TEMP, M_WAITOK);
diff --git a/sys/kern/kern_exec.c b/sys/kern/kern_exec.c
index e513908..75843eb 100644
--- a/sys/kern/kern_exec.c
+++ b/sys/kern/kern_exec.c
@@ -48,6 +48,7 @@ __FBSDID("$FreeBSD$");
#include <sys/imgact_elf.h>
#include <sys/wait.h>
#include <sys/malloc.h>
+#include <sys/priv.h>
#include <sys/proc.h>
#include <sys/pioctl.h>
#include <sys/namei.h>
@@ -571,8 +572,11 @@ interpret:
* we do not regain any tracing during a possible block.
*/
setsugid(p);
+
#ifdef KTRACE
- if (p->p_tracevp != NULL && suser_cred(oldcred, SUSER_ALLOWJAIL)) {
+ if (p->p_tracevp != NULL &&
+ priv_check_cred(oldcred, PRIV_DEBUG_DIFFCRED,
+ SUSER_ALLOWJAIL)) {
mtx_lock(&ktrace_mtx);
p->p_traceflag = 0;
tracevp = p->p_tracevp;
diff --git a/sys/kern/kern_fork.c b/sys/kern/kern_fork.c
index e92720b..9c5597e 100644
--- a/sys/kern/kern_fork.c
+++ b/sys/kern/kern_fork.c
@@ -51,6 +51,7 @@ __FBSDID("$FreeBSD$");
#include <sys/lock.h>
#include <sys/malloc.h>
#include <sys/mutex.h>
+#include <sys/priv.h>
#include <sys/proc.h>
#include <sys/pioctl.h>
#include <sys/resourcevar.h>
@@ -310,7 +311,7 @@ fork1(td, flags, pages, procp)
*/
sx_xlock(&allproc_lock);
if ((nprocs >= maxproc - 10 &&
- suser_cred(td->td_ucred, SUSER_RUID) != 0) ||
+ priv_check_cred(td->td_ucred, PRIV_MAXPROC, SUSER_RUID) != 0) ||
nprocs >= maxproc) {
error = EAGAIN;
goto fail;
@@ -319,8 +320,11 @@ fork1(td, flags, pages, procp)
/*
* Increment the count of procs running with this uid. Don't allow
* a nonprivileged user to exceed their current limit.
+ *
+ * XXXRW: Can we avoid privilege here if it's not needed?
*/
- error = suser_cred(td->td_ucred, SUSER_RUID | SUSER_ALLOWJAIL);
+ error = priv_check_cred(td->td_ucred, PRIV_PROC_LIMIT, SUSER_RUID |
+ SUSER_ALLOWJAIL);
if (error == 0)
ok = chgproccnt(td->td_ucred->cr_ruidinfo, 1, 0);
else {
diff --git a/sys/kern/kern_ktrace.c b/sys/kern/kern_ktrace.c
index e79fa7c..b5a4456 100644
--- a/sys/kern/kern_ktrace.c
+++ b/sys/kern/kern_ktrace.c
@@ -47,6 +47,7 @@ __FBSDID("$FreeBSD$");
#include <sys/malloc.h>
#include <sys/mount.h>
#include <sys/namei.h>
+#include <sys/priv.h>
#include <sys/proc.h>
#include <sys/unistd.h>
#include <sys/vnode.h>
@@ -807,7 +808,8 @@ ktrops(td, p, ops, facs, vp)
p->p_tracecred = crhold(td->td_ucred);
}
p->p_traceflag |= facs;
- if (suser_cred(td->td_ucred, SUSER_ALLOWJAIL) == 0)
+ if (priv_check_cred(td->td_ucred, PRIV_KTRACE,
+ SUSER_ALLOWJAIL) == 0)
p->p_traceflag |= KTRFAC_ROOT;
} else {
/* KTROP_CLEAR */
@@ -1013,7 +1015,7 @@ ktrcanset(td, targetp)
PROC_LOCK_ASSERT(targetp, MA_OWNED);
if (targetp->p_traceflag & KTRFAC_ROOT &&
- suser_cred(td->td_ucred, SUSER_ALLOWJAIL))
+ priv_check_cred(td->td_ucred, PRIV_KTRACE, SUSER_ALLOWJAIL))
return (0);
if (p_candebug(td, targetp) != 0)
diff --git a/sys/kern/kern_linker.c b/sys/kern/kern_linker.c
index 0bdd9f8..6d0dd0f 100644
--- a/sys/kern/kern_linker.c
+++ b/sys/kern/kern_linker.c
@@ -37,6 +37,7 @@ __FBSDID("$FreeBSD$");
#include <sys/malloc.h>
#include <sys/sysproto.h>
#include <sys/sysent.h>
+#include <sys/priv.h>
#include <sys/proc.h>
#include <sys/lock.h>
#include <sys/mutex.h>
@@ -854,7 +855,7 @@ kern_kldload(struct thread *td, const char *file, int *fileid)
if ((error = securelevel_gt(td->td_ucred, 0)) != 0)
return (error);
- if ((error = suser(td)) != 0)
+ if ((error = priv_check(td, PRIV_KLD_LOAD)) != 0)
return (error);
/*
@@ -921,7 +922,7 @@ kern_kldunload(struct thread *td, int fileid, int flags)
if ((error = securelevel_gt(td->td_ucred, 0)) != 0)
return (error);
- if ((error = suser(td)) != 0)
+ if ((error = priv_check(td, PRIV_KLD_UNLOAD)) != 0)
return (error);
KLD_LOCK();
diff --git a/sys/kern/kern_ntptime.c b/sys/kern/kern_ntptime.c
index 53deb9f..87d10d7 100644
--- a/sys/kern/kern_ntptime.c
+++ b/sys/kern/kern_ntptime.c
@@ -39,6 +39,7 @@ __FBSDID("$FreeBSD$");
#include <sys/systm.h>
#include <sys/sysproto.h>
#include <sys/kernel.h>
+#include <sys/priv.h>
#include <sys/proc.h>
#include <sys/lock.h>
#include <sys/mutex.h>
@@ -333,7 +334,7 @@ ntp_adjtime(struct thread *td, struct ntp_adjtime_args *uap)
mtx_lock(&Giant);
modes = ntv.modes;
if (modes)
- error = suser(td);
+ error = priv_check(td, PRIV_NTP_ADJTIME);
if (error)
goto done2;
s = splclock();
@@ -954,7 +955,7 @@ kern_adjtime(struct thread *td, struct timeval *delta, struct timeval *olddelta)
struct timeval atv;
int error;
- if ((error = suser(td)))
+ if ((error = priv_check(td, PRIV_ADJTIME)))
return (error);
mtx_lock(&Giant);
diff --git a/sys/kern/kern_resource.c b/sys/kern/kern_resource.c
index 524631f..3ba110f 100644
--- a/sys/kern/kern_resource.c
+++ b/sys/kern/kern_resource.c
@@ -47,6 +47,7 @@ __FBSDID("$FreeBSD$");
#include <sys/lock.h>
#include <sys/malloc.h>
#include <sys/mutex.h>
+#include <sys/priv.h>
#include <sys/proc.h>
#include <sys/refcount.h>
#include <sys/resourcevar.h>
@@ -264,7 +265,7 @@ donice(struct thread *td, struct proc *p, int n)
n = PRIO_MAX;
if (n < PRIO_MIN)
n = PRIO_MIN;
- if (n < p->p_nice && suser(td) != 0)
+ if (n < p->p_nice && priv_check(td, PRIV_SCHED_SETPRIORITY) != 0)
return (EACCES);
mtx_lock_spin(&sched_lock);
sched_nice(p, n);
@@ -468,7 +469,7 @@ rtprio(td, uap)
break;
/* Disallow setting rtprio in most cases if not superuser. */
- if (suser(td) != 0) {
+ if (priv_check(td, PRIV_SCHED_RTPRIO) != 0) {
/* can't set someone else's */
if (uap->pid) {
error = EPERM;
@@ -754,7 +755,8 @@ kern_setrlimit(td, which, limp)
alimp = &oldlim->pl_rlimit[which];
if (limp->rlim_cur > alimp->rlim_max ||
limp->rlim_max > alimp->rlim_max)
- if ((error = suser_cred(td->td_ucred, SUSER_ALLOWJAIL))) {
+ if ((error = priv_check_cred(td->td_ucred,
+ PRIV_PROC_SETRLIMIT, SUSER_ALLOWJAIL))) {
PROC_UNLOCK(p);
lim_free(newlim);
return (error);
diff --git a/sys/kern/kern_shutdown.c b/sys/kern/kern_shutdown.c
index a5bcfa8..a20daa7 100644
--- a/sys/kern/kern_shutdown.c
+++ b/sys/kern/kern_shutdown.c
@@ -55,6 +55,7 @@ __FBSDID("$FreeBSD$");
#include <sys/kthread.h>
#include <sys/malloc.h>
#include <sys/mount.h>
+#include <sys/priv.h>
#include <sys/proc.h>
#include <sys/reboot.h>
#include <sys/resourcevar.h>
@@ -164,7 +165,7 @@ reboot(struct thread *td, struct reboot_args *uap)
error = mac_check_system_reboot(td->td_ucred, uap->opt);
#endif
if (error == 0)
- error = suser(td);
+ error = priv_check(td, PRIV_REBOOT);
if (error == 0) {
mtx_lock(&Giant);
boot(uap->opt);
diff --git a/sys/kern/kern_sysctl.c b/sys/kern/kern_sysctl.c
index a929291..6015551 100644
--- a/sys/kern/kern_sysctl.c
+++ b/sys/kern/kern_sysctl.c
@@ -46,6 +46,7 @@ __FBSDID("$FreeBSD$");
#include <sys/kernel.h>
#include <sys/sysctl.h>
#include <sys/malloc.h>
+#include <sys/priv.h>
#include <sys/proc.h>
#include <sys/lock.h>
#include <sys/mutex.h>
@@ -512,7 +513,7 @@ sysctl_sysctl_debug(SYSCTL_HANDLER_ARGS)
{
int error;
- error = suser(req->td);
+ error = priv_check(req->td, PRIV_SYSCTL_DEBUG);
if (error)
return (error);
sysctl_sysctl_debug_dump_node(&sysctl__children, 0);
@@ -1253,13 +1254,11 @@ sysctl_root(SYSCTL_HANDLER_ARGS)
/* Is this sysctl writable by only privileged users? */
if (req->newptr && !(oid->oid_kind & CTLFLAG_ANYBODY)) {
- int flags;
-
if (oid->oid_kind & CTLFLAG_PRISON)
- flags = SUSER_ALLOWJAIL;
+ error = priv_check_cred(req->td->td_ucred,
+ PRIV_SYSCTL_WRITEJAIL, SUSER_ALLOWJAIL);
else
- flags = 0;
- error = suser_cred(req->td->td_ucred, flags);
+ error = priv_check(req->td, PRIV_SYSCTL_WRITE);
if (error)
return (error);
}
diff --git a/sys/kern/kern_thr.c b/sys/kern/kern_thr.c
index bfa1e2b..72798ac 100644
--- a/sys/kern/kern_thr.c
+++ b/sys/kern/kern_thr.c
@@ -33,6 +33,7 @@ __FBSDID("$FreeBSD$");
#include <sys/kernel.h>
#include <sys/lock.h>
#include <sys/mutex.h>
+#include <sys/priv.h>
#include <sys/proc.h>
#include <sys/resourcevar.h>
#include <sys/sched.h>
@@ -164,7 +165,7 @@ create_thread(struct thread *td, mcontext_t *ctx,
case RTP_PRIO_REALTIME:
case RTP_PRIO_FIFO:
/* Only root can set scheduler policy */
- if (suser(td) != 0)
+ if (priv_check(td, PRIV_SCHED_SETPOLICY) != 0)
return (EPERM);
if (rtp->prio > RTP_PRIO_MAX)
return (EINVAL);
diff --git a/sys/kern/kern_time.c b/sys/kern/kern_time.c
index 479348e..53ce9e4 100644
--- a/sys/kern/kern_time.c
+++ b/sys/kern/kern_time.c
@@ -48,6 +48,7 @@ __FBSDID("$FreeBSD$");
#include <sys/syscallsubr.h>
#include <sys/sysctl.h>
#include <sys/sysent.h>
+#include <sys/priv.h>
#include <sys/proc.h>
#include <sys/time.h>
#include <sys/timers.h>
@@ -286,7 +287,7 @@ kern_clock_settime(struct thread *td, clockid_t clock_id, struct timespec *ats)
if (error)
return (error);
#endif
- if ((error = suser(td)) != 0)
+ if ((error = priv_check(td, PRIV_CLOCK_SETTIME)) != 0)
return (error);
if (clock_id != CLOCK_REALTIME)
return (EINVAL);
@@ -504,7 +505,7 @@ kern_settimeofday(struct thread *td, struct timeval *tv, struct timezone *tzp)
if (error)
return (error);
#endif
- error = suser(td);
+ error = priv_check(td, PRIV_SETTIMEOFDAY);
if (error)
return (error);
/* Verify all parameters before changing time. */
diff --git a/sys/kern/kern_umtx.c b/sys/kern/kern_umtx.c
index d6c8c2d..e9513c8 100644
--- a/sys/kern/kern_umtx.c
+++ b/sys/kern/kern_umtx.c
@@ -35,6 +35,7 @@ __FBSDID("$FreeBSD$");
#include <sys/lock.h>
#include <sys/malloc.h>
#include <sys/mutex.h>
+#include <sys/priv.h>
#include <sys/proc.h>
#include <sys/sched.h>
#include <sys/sysctl.h>
@@ -1813,7 +1814,7 @@ _do_lock_pp(struct thread *td, struct umutex *m, uint32_t flags, int timo,
if ((error = umtx_key_get(m, TYPE_PP_UMUTEX, GET_SHARE(flags),
&uq->uq_key)) != 0)
return (error);
- su = (suser(td) == 0);
+ su = (priv_check(td, PRIV_SCHED_RTPRIO) == 0);
for (;;) {
old_inherited_pri = uq->uq_inherited_pri;
umtxq_lock(&uq->uq_key);
@@ -1934,7 +1935,7 @@ do_unlock_pp(struct thread *td, struct umutex *m, uint32_t flags)
id = td->td_tid;
uq = td->td_umtxq;
- su = (suser(td) == 0);
+ su = (priv_check(td, PRIV_SCHED_RTPRIO) == 0);
/*
* Make sure we own this mtx.
diff --git a/sys/kern/kern_xxx.c b/sys/kern/kern_xxx.c
index d93ba37..81c2df4 100644
--- a/sys/kern/kern_xxx.c
+++ b/sys/kern/kern_xxx.c
@@ -38,6 +38,7 @@ __FBSDID("$FreeBSD$");
#include <sys/systm.h>
#include <sys/sysproto.h>
#include <sys/kernel.h>
+#include <sys/priv.h>
#include <sys/proc.h>
#include <sys/lock.h>
#include <sys/mutex.h>
@@ -139,7 +140,8 @@ osethostid(td, uap)
{
int error;
- if ((error = suser(td)))
+ error = priv_check(td, PRIV_SETHOSTID);
+ if (error)
return (error);
mtx_lock(&Giant);
hostid = uap->hostid;
@@ -295,9 +297,10 @@ setdomainname(td, uap)
{
int error, domainnamelen;
+ error = priv_check(td, PRIV_SETDOMAINNAME);
+ if (error)
+ return (error);
mtx_lock(&Giant);
- if ((error = suser(td)))
- goto done2;
if ((u_int)uap->len > sizeof (domainname) - 1) {
error = EINVAL;
goto done2;
@@ -309,4 +312,3 @@ done2:
mtx_unlock(&Giant);
return (error);
}
-
diff --git a/sys/kern/p1003_1b.c b/sys/kern/p1003_1b.c
index 189f593..8ed0de5 100644
--- a/sys/kern/p1003_1b.c
+++ b/sys/kern/p1003_1b.c
@@ -44,6 +44,7 @@ __FBSDID("$FreeBSD$");
#include <sys/lock.h>
#include <sys/module.h>
#include <sys/mutex.h>
+#include <sys/priv.h>
#include <sys/proc.h>
#include <sys/syscallsubr.h>
#include <sys/sysctl.h>
@@ -186,9 +187,10 @@ sched_setscheduler(struct thread *td, struct sched_setscheduler_args *uap)
struct thread *targettd;
struct proc *targetp;
- /* Don't allow non root user to set a scheduler policy */
- if (suser(td) != 0)
- return (EPERM);
+ /* Don't allow non root user to set a scheduler policy. */
+ e = priv_check(td, PRIV_SCHED_SET);
+ if (e)
+ return (e);
e = copyin(uap->param, &sched_param, sizeof(sched_param));
if (e)
diff --git a/sys/kern/subr_acl_posix1e.c b/sys/kern/subr_acl_posix1e.c
index a3ea703..94c612f 100644
--- a/sys/kern/subr_acl_posix1e.c
+++ b/sys/kern/subr_acl_posix1e.c
@@ -39,6 +39,7 @@ __FBSDID("$FreeBSD$");
#include <sys/param.h>
#include <sys/systm.h>
#include <sys/mount.h>
+#include <sys/priv.h>
#include <sys/vnode.h>
#include <sys/errno.h>
#include <sys/stat.h>
@@ -46,9 +47,9 @@ __FBSDID("$FreeBSD$");
/*
* Implement a version of vaccess() that understands POSIX.1e ACL semantics;
- * the access ACL has already been prepared for evaluation by the file
- * system and is passed via 'uid', 'gid', and 'acl'. Return 0 on success,
- * else an errno value.
+ * the access ACL has already been prepared for evaluation by the file system
+ * and is passed via 'uid', 'gid', and 'acl'. Return 0 on success, else an
+ * errno value.
*/
int
vaccess_acl_posix1e(enum vtype type, uid_t file_uid, gid_t file_gid,
@@ -56,14 +57,14 @@ vaccess_acl_posix1e(enum vtype type, uid_t file_uid, gid_t file_gid,
{
struct acl_entry *acl_other, *acl_mask;
mode_t dac_granted;
- mode_t cap_granted;
+ mode_t priv_granted;
mode_t acl_mask_granted;
int group_matched, i;
/*
* Look for a normal, non-privileged way to access the file/directory
* as requested. If it exists, go with that. Otherwise, attempt to
- * use privileges granted via cap_granted. In some cases, which
+ * use privileges granted via priv_granted. In some cases, which
* privileges to use may be ambiguous due to "best match", in which
* case fall back on first match for the time being.
*/
@@ -72,40 +73,34 @@ vaccess_acl_posix1e(enum vtype type, uid_t file_uid, gid_t file_gid,
/*
* Determine privileges now, but don't apply until we've found a DAC
- * entry that matches but has failed to allow access. POSIX.1e
- * capabilities are not implemented, but we document how they would
- * behave here if implemented.
+ * entry that matches but has failed to allow access.
+ *
+ * XXXRW: Ideally, we'd determine the privileges required before
+ * asking for them.
*/
-#ifndef CAPABILITIES
- if (suser_cred(cred, SUSER_ALLOWJAIL) == 0)
- cap_granted = VALLPERM;
- else
- cap_granted = 0;
-#else
- cap_granted = 0;
+ priv_granted = 0;
if (type == VDIR) {
- if ((acc_mode & VEXEC) && !cap_check(cred, NULL,
- CAP_DAC_READ_SEARCH, SUSER_ALLOWJAIL))
- cap_granted |= VEXEC;
+ if ((acc_mode & VEXEC) && !priv_check_cred(cred,
+ PRIV_VFS_LOOKUP, SUSER_ALLOWJAIL))
+ priv_granted |= VEXEC;
} else {
- if ((acc_mode & VEXEC) && !cap_check(cred, NULL,
- CAP_DAC_EXECUTE, SUSER_ALLOWJAIL))
- cap_granted |= VEXEC;
+ if ((acc_mode & VEXEC) && !priv_check_cred(cred,
+ PRIV_VFS_EXEC, SUSER_ALLOWJAIL))
+ priv_granted |= VEXEC;
}
- if ((acc_mode & VREAD) && !cap_check(cred, NULL, CAP_DAC_READ_SEARCH,
+ if ((acc_mode & VREAD) && !priv_check_cred(cred, PRIV_VFS_READ,
SUSER_ALLOWJAIL))
- cap_granted |= VREAD;
+ priv_granted |= VREAD;
if (((acc_mode & VWRITE) || (acc_mode & VAPPEND)) &&
- !cap_check(cred, NULL, CAP_DAC_WRITE, SUSER_ALLOWJAIL))
- cap_granted |= (VWRITE | VAPPEND);
+ !priv_check_cred(cred, PRIV_VFS_WRITE, SUSER_ALLOWJAIL))
+ priv_granted |= (VWRITE | VAPPEND);
- if ((acc_mode & VADMIN) && !cap_check(cred, NULL, CAP_FOWNER,
+ if ((acc_mode & VADMIN) && !priv_check_cred(cred, PRIV_VFS_ADMIN,
SUSER_ALLOWJAIL))
- cap_granted |= VADMIN;
-#endif /* CAPABILITIES */
+ priv_granted |= VADMIN;
/*
* The owner matches if the effective uid associated with the
@@ -129,7 +124,11 @@ vaccess_acl_posix1e(enum vtype type, uid_t file_uid, gid_t file_gid,
dac_granted |= (VWRITE | VAPPEND);
if ((acc_mode & dac_granted) == acc_mode)
return (0);
- if ((acc_mode & (dac_granted | cap_granted)) ==
+
+ /*
+ * XXXRW: Do privilege lookup here.
+ */
+ if ((acc_mode & (dac_granted | priv_granted)) ==
acc_mode) {
if (privused != NULL)
*privused = 1;
@@ -183,13 +182,9 @@ vaccess_acl_posix1e(enum vtype type, uid_t file_uid, gid_t file_gid,
acl_mask_granted = VEXEC | VREAD | VWRITE | VAPPEND;
/*
- * Iterate through user ACL entries. Do checks twice, first without
- * privilege, and then if a match is found but failed, a second time
- * with privilege.
- */
-
- /*
- * Check ACL_USER ACL entries.
+ * Check ACL_USER ACL entries. There will either be one or no
+ * matches; if there is one, we accept or rejected based on the
+ * match; otherwise, we continue on to groups.
*/
for (i = 0; i < acl->acl_cnt; i++) {
switch (acl->acl_entry[i].ae_tag) {
@@ -206,7 +201,10 @@ vaccess_acl_posix1e(enum vtype type, uid_t file_uid, gid_t file_gid,
dac_granted &= acl_mask_granted;
if ((acc_mode & dac_granted) == acc_mode)
return (0);
- if ((acc_mode & (dac_granted | cap_granted)) !=
+ /*
+ * XXXRW: Do privilege lookup here.
+ */
+ if ((acc_mode & (dac_granted | priv_granted)) !=
acc_mode)
goto error;
@@ -286,8 +284,11 @@ vaccess_acl_posix1e(enum vtype type, uid_t file_uid, gid_t file_gid,
dac_granted |= (VWRITE | VAPPEND);
dac_granted &= acl_mask_granted;
- if ((acc_mode & (dac_granted | cap_granted)) !=
- acc_mode)
+ /*
+ * XXXRW: Do privilege lookup here.
+ */
+ if ((acc_mode & (dac_granted | priv_granted))
+ != acc_mode)
break;
if (privused != NULL)
@@ -307,8 +308,11 @@ vaccess_acl_posix1e(enum vtype type, uid_t file_uid, gid_t file_gid,
dac_granted |= (VWRITE | VAPPEND);
dac_granted &= acl_mask_granted;
- if ((acc_mode & (dac_granted | cap_granted)) !=
- acc_mode)
+ /*
+ * XXXRW: Do privilege lookup here.
+ */
+ if ((acc_mode & (dac_granted | priv_granted))
+ != acc_mode)
break;
if (privused != NULL)
@@ -339,7 +343,10 @@ vaccess_acl_posix1e(enum vtype type, uid_t file_uid, gid_t file_gid,
if ((acc_mode & dac_granted) == acc_mode)
return (0);
- if ((acc_mode & (dac_granted | cap_granted)) == acc_mode) {
+ /*
+ * XXXRW: Do privilege lookup here.
+ */
+ if ((acc_mode & (dac_granted | priv_granted)) == acc_mode) {
if (privused != NULL)
*privused = 1;
return (0);
diff --git a/sys/kern/subr_firmware.c b/sys/kern/subr_firmware.c
index 6de4fa4..a83e567 100644
--- a/sys/kern/subr_firmware.c
+++ b/sys/kern/subr_firmware.c
@@ -38,6 +38,7 @@ __FBSDID("$FreeBSD$");
#include <sys/errno.h>
#include <sys/linker.h>
#include <sys/firmware.h>
+#include <sys/priv.h>
#include <sys/proc.h>
#include <sys/module.h>
@@ -190,7 +191,8 @@ again:
return NULL;
}
td = curthread;
- if (suser(td) != 0 || securelevel_gt(td->td_ucred, 0) != 0) {
+ if (priv_check(td, PRIV_FIRMWARE_LOAD) != 0 ||
+ securelevel_gt(td->td_ucred, 0) != 0) {
printf("%s: insufficient privileges to "
"load firmware image %s\n", __func__, imagename);
return NULL;
diff --git a/sys/kern/subr_prf.c b/sys/kern/subr_prf.c
index b6ffc91..c53bf98 100644
--- a/sys/kern/subr_prf.c
+++ b/sys/kern/subr_prf.c
@@ -48,6 +48,7 @@ __FBSDID("$FreeBSD$");
#include <sys/kernel.h>
#include <sys/msgbuf.h>
#include <sys/malloc.h>
+#include <sys/priv.h>
#include <sys/proc.h>
#include <sys/stddef.h>
#include <sys/sysctl.h>
@@ -925,7 +926,7 @@ sysctl_kern_msgbuf(SYSCTL_HANDLER_ARGS)
int error, len;
if (!unprivileged_read_msgbuf) {
- error = suser(req->td);
+ error = priv_check(req->td, PRIV_MSGBUF);
if (error)
return (error);
}
diff --git a/sys/kern/subr_witness.c b/sys/kern/subr_witness.c
index 4018d3f..a99172e 100644
--- a/sys/kern/subr_witness.c
+++ b/sys/kern/subr_witness.c
@@ -95,6 +95,7 @@ __FBSDID("$FreeBSD$");
#include <sys/lock.h>
#include <sys/malloc.h>
#include <sys/mutex.h>
+#include <sys/priv.h>
#include <sys/proc.h>
#include <sys/sysctl.h>
#include <sys/systm.h>
@@ -533,7 +534,10 @@ sysctl_debug_witness_watch(SYSCTL_HANDLER_ARGS)
error = sysctl_handle_int(oidp, &value, 0, req);
if (error != 0 || req->newptr == NULL)
return (error);
- error = suser(req->td);
+ /*
+ * XXXRW: Why a priv check here?
+ */
+ error = priv_check(req->td, PRIV_WITNESS);
if (error != 0)
return (error);
if (value == witness_watch)
diff --git a/sys/kern/sysv_ipc.c b/sys/kern/sysv_ipc.c
index 8fec1da..0cbb4bb 100644
--- a/sys/kern/sysv_ipc.c
+++ b/sys/kern/sysv_ipc.c
@@ -1,8 +1,12 @@
/* $NetBSD: sysv_ipc.c,v 1.7 1994/06/29 06:33:11 cgd Exp $ */
/*-
* Copyright (c) 1994 Herb Peyerl <hpeyerl@novatel.ca>
+ * Copyright (c) 2006 nCircle Network Security, Inc.
* All rights reserved.
*
+ * This software was developed by Robert N. M. Watson for the TrustedBSD
+ * Project under contract to nCircle Network Security, Inc.
+ *
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
@@ -39,6 +43,7 @@ __FBSDID("$FreeBSD$");
#include <sys/sem.h>
#include <sys/shm.h>
#include <sys/ipc.h>
+#include <sys/priv.h>
#include <sys/proc.h>
#include <sys/ucred.h>
@@ -72,50 +77,73 @@ shmexit(struct vmspace *vm)
* Note: The MAC Framework does not require any modifications to the
* ipcperm() function, as access control checks are performed throughout the
* implementation of each primitive. Those entry point calls complement the
- * ipcperm() discertionary checks.
+ * ipcperm() discertionary checks. Unlike file system discretionary access
+ * control, the original create of an object is given the same rights as the
+ * current owner.
*/
int
-ipcperm(td, perm, mode)
- struct thread *td;
- struct ipc_perm *perm;
- int mode;
+ipcperm(struct thread *td, struct ipc_perm *perm, int acc_mode)
{
struct ucred *cred = td->td_ucred;
- int error;
-
- if (cred->cr_uid != perm->cuid && cred->cr_uid != perm->uid) {
- /*
- * For a non-create/owner, we require privilege to
- * modify the object protections. Note: some other
- * implementations permit IPC_M to be delegated to
- * unprivileged non-creator/owner uids/gids.
- */
- if (mode & IPC_M) {
- error = suser(td);
- if (error)
- return (error);
- }
- /*
- * Try to match against creator/owner group; if not, fall
- * back on other.
- */
- mode >>= 3;
- if (!groupmember(perm->gid, cred) &&
- !groupmember(perm->cgid, cred))
- mode >>= 3;
+ int error, obj_mode, dac_granted, priv_granted;
+
+ dac_granted = 0;
+ if (cred->cr_uid == perm->cuid || cred->cr_uid == perm->uid) {
+ obj_mode = perm->mode;
+ dac_granted |= IPC_M;
+ } else if (groupmember(perm->gid, cred) ||
+ groupmember(perm->cgid, cred)) {
+ obj_mode = perm->mode;
+ obj_mode <<= 3;
} else {
- /*
- * Always permit the creator/owner to update the object
- * protections regardless of whether the object mode
- * permits it.
- */
- if (mode & IPC_M)
- return (0);
+ obj_mode = perm->mode;
+ obj_mode <<= 6;
}
- if ((mode & perm->mode) != mode) {
- if (suser(td) != 0)
- return (EACCES);
+ /*
+ * While the System V IPC permission model allows IPC_M to be
+ * granted, as part of the mode, our implementation requires
+ * privilege to adminster the object if not the owner or creator.
+ */
+#if 0
+ if (obj_mode & IPC_M)
+ dac_granted |= IPC_M;
+#endif
+ if (obj_mode & IPC_R)
+ dac_granted |= IPC_R;
+ if (obj_mode & IPC_W)
+ dac_granted |= IPC_W;
+
+ /*
+ * Simple case: all required rights are granted by DAC.
+ */
+ if ((dac_granted & acc_mode) == acc_mode)
+ return (0);
+
+ /*
+ * Privilege is required to satisfy the request.
+ */
+ priv_granted = 0;
+ if ((acc_mode & IPC_M) && !(dac_granted & IPC_M)) {
+ error = priv_check(td, PRIV_IPC_ADMIN);
+ if (error == 0)
+ priv_granted |= IPC_M;
}
- return (0);
+
+ if ((acc_mode & IPC_R) && !(dac_granted & IPC_R)) {
+ error = priv_check(td, PRIV_IPC_READ);
+ if (error == 0)
+ priv_granted |= IPC_R;
+ }
+
+ if ((acc_mode & IPC_W) && !(dac_granted & IPC_W)) {
+ error = priv_check(td, PRIV_IPC_WRITE);
+ if (error == 0)
+ priv_granted |= IPC_W;
+ }
+
+ if (((dac_granted | priv_granted) & acc_mode) == acc_mode)
+ return (0);
+ else
+ return (EACCES);
}
diff --git a/sys/kern/sysv_msg.c b/sys/kern/sysv_msg.c
index 464a7e5..a3db14c 100644
--- a/sys/kern/sysv_msg.c
+++ b/sys/kern/sysv_msg.c
@@ -57,6 +57,7 @@ __FBSDID("$FreeBSD$");
#include <sys/systm.h>
#include <sys/sysproto.h>
#include <sys/kernel.h>
+#include <sys/priv.h>
#include <sys/proc.h>
#include <sys/lock.h>
#include <sys/mutex.h>
@@ -507,7 +508,7 @@ kern_msgctl(td, msqid, cmd, msqbuf)
if ((error = ipcperm(td, &msqkptr->u.msg_perm, IPC_M)))
goto done2;
if (msqbuf->msg_qbytes > msqkptr->u.msg_qbytes) {
- error = suser(td);
+ error = priv_check(td, PRIV_IPC_MSGSIZE);
if (error)
goto done2;
}
diff --git a/sys/kern/tty.c b/sys/kern/tty.c
index 29ddde3..17205f2 100644
--- a/sys/kern/tty.c
+++ b/sys/kern/tty.c
@@ -86,6 +86,7 @@ __FBSDID("$FreeBSD$");
#if defined(COMPAT_43TTY)
#include <sys/ioctl_compat.h>
#endif
+#include <sys/priv.h>
#include <sys/proc.h>
#define TTYDEFCHARS
#include <sys/tty.h>
@@ -1020,7 +1021,7 @@ ttioctl(struct tty *tp, u_long cmd, void *data, int flag)
break;
case TIOCMSDTRWAIT:
/* must be root since the wait applies to following logins */
- error = suser(td);
+ error = priv_check(td, PRIV_TTY_DTRWAIT);
if (error)
return (error);
tp->t_dtr_wait = *(int *)data * hz / 100;
@@ -1169,9 +1170,9 @@ ttioctl(struct tty *tp, u_long cmd, void *data, int flag)
splx(s);
break;
case TIOCSTI: /* simulate terminal input */
- if ((flag & FREAD) == 0 && suser(td))
+ if ((flag & FREAD) == 0 && priv_check(td, PRIV_TTY_STI))
return (EPERM);
- if (!isctty(p, tp) && suser(td))
+ if (!isctty(p, tp) && priv_check(td, PRIV_TTY_STI))
return (EACCES);
s = spltty();
ttyld_rint(tp, *(u_char *)data);
@@ -1244,7 +1245,7 @@ ttioctl(struct tty *tp, u_long cmd, void *data, int flag)
}
break;
case TIOCSDRAINWAIT:
- error = suser(td);
+ error = priv_check(td, PRIV_TTY_DRAINWAIT);
if (error)
return (error);
tp->t_timeout = *(int *)data * hz;
@@ -3114,7 +3115,8 @@ open_top:
goto out;
goto open_top;
}
- if (tp->t_state & TS_XCLUDE && suser(td))
+ if (tp->t_state & TS_XCLUDE && priv_check(td,
+ PRIV_TTY_EXCLUSIVE))
return (EBUSY);
} else {
/*
@@ -3340,7 +3342,7 @@ ttysioctl(struct cdev *dev, u_long cmd, caddr_t data, int flag, struct thread *t
ct = dev->si_drv2;
switch (cmd) {
case TIOCSETA:
- error = suser(td);
+ error = priv_check(td, PRIV_TTY_SETA);
if (error != 0)
return (error);
*ct = *(struct termios *)data;
diff --git a/sys/kern/tty_cons.c b/sys/kern/tty_cons.c
index 4472470..8e9e2a5 100644
--- a/sys/kern/tty_cons.c
+++ b/sys/kern/tty_cons.c
@@ -51,6 +51,7 @@ __FBSDID("$FreeBSD$");
#include <sys/malloc.h>
#include <sys/msgbuf.h>
#include <sys/namei.h>
+#include <sys/priv.h>
#include <sys/proc.h>
#include <sys/queue.h>
#include <sys/reboot.h>
@@ -510,7 +511,7 @@ cnioctl(struct cdev *dev, u_long cmd, caddr_t data, int flag, struct thread *td)
* output from the "virtual" console.
*/
if (cmd == TIOCCONS && constty) {
- error = suser(td);
+ error = priv_check(td, PRIV_TTY_CONSOLE);
if (error)
return (error);
constty = NULL;
diff --git a/sys/kern/tty_pts.c b/sys/kern/tty_pts.c
index d5880a2..205cf57 100644
--- a/sys/kern/tty_pts.c
+++ b/sys/kern/tty_pts.c
@@ -56,6 +56,7 @@ __FBSDID("$FreeBSD$");
#if defined(COMPAT_43TTY)
#include <sys/ioctl_compat.h>
#endif
+#include <sys/priv.h>
#include <sys/proc.h>
#include <sys/queue.h>
#include <sys/tty.h>
@@ -268,9 +269,11 @@ ptsopen(struct cdev *dev, int flag, int devtype, struct thread *td)
tp = dev->si_tty;
if ((tp->t_state & TS_ISOPEN) == 0)
ttyinitmode(tp, 1, 0);
- else if (tp->t_state & TS_XCLUDE && suser(td)) {
+ else if (tp->t_state & TS_XCLUDE && priv_check(td,
+ PRIV_TTY_EXCLUSIVE)) {
return (EBUSY);
- } else if (pt->pt_prison != td->td_ucred->cr_prison && suser(td)) {
+ } else if (pt->pt_prison != td->td_ucred->cr_prison &&
+ priv_check(td, PRIV_TTY_PRISON)) {
return (EBUSY);
}
if (tp->t_oproc) /* Ctrlr still around. */
diff --git a/sys/kern/tty_pty.c b/sys/kern/tty_pty.c
index a973f6a..a59430f 100644
--- a/sys/kern/tty_pty.c
+++ b/sys/kern/tty_pty.c
@@ -46,6 +46,7 @@ __FBSDID("$FreeBSD$");
#if defined(COMPAT_43TTY)
#include <sys/ioctl_compat.h>
#endif
+#include <sys/priv.h>
#include <sys/proc.h>
#include <sys/tty.h>
#include <sys/conf.h>
@@ -207,9 +208,11 @@ ptsopen(struct cdev *dev, int flag, int devtype, struct thread *td)
if ((tp->t_state & TS_ISOPEN) == 0) {
ttyinitmode(tp, 1, 0);
- } else if (tp->t_state & TS_XCLUDE && suser(td))
+ } else if (tp->t_state & TS_XCLUDE && priv_check(td,
+ PRIV_TTY_EXCLUSIVE))
return (EBUSY);
- else if (pt->pt_prison != td->td_ucred->cr_prison && suser(td))
+ else if (pt->pt_prison != td->td_ucred->cr_prison &&
+ priv_check(td, PRIV_TTY_PRISON))
return (EBUSY);
if (tp->t_oproc) /* Ctrlr still around. */
(void)ttyld_modem(tp, 1);
diff --git a/sys/kern/uipc_mqueue.c b/sys/kern/uipc_mqueue.c
index d6cf2e5..9185c0e 100644
--- a/sys/kern/uipc_mqueue.c
+++ b/sys/kern/uipc_mqueue.c
@@ -65,6 +65,7 @@ __FBSDID("$FreeBSD$");
#include <sys/mutex.h>
#include <sys/namei.h>
#include <sys/poll.h>
+#include <sys/priv.h>
#include <sys/proc.h>
#include <sys/queue.h>
#include <sys/sysproto.h>
@@ -955,8 +956,12 @@ int do_unlink(struct mqfs_node *pn, struct ucred *ucred)
sx_assert(&pn->mn_info->mi_lock, SX_LOCKED);
+ /*
+ * XXXRW: Other instances of the message queue primitive are
+ * allowed in jail?
+ */
if (ucred->cr_uid != pn->mn_uid &&
- (error = suser_cred(ucred, 0)) != 0)
+ (error = priv_check_cred(ucred, PRIV_MQ_ADMIN, 0)) != 0)
error = EACCES;
else if (!pn->mn_deleted) {
parent = pn->mn_parent;
@@ -1207,10 +1212,16 @@ mqfs_setattr(struct vop_setattr_args *ap)
*/
if ((error = VOP_ACCESS(vp, VADMIN, ap->a_cred, ap->a_td)))
return (error);
+
+ /*
+ * XXXRW: Why is there a privilege check here: shouldn't the
+ * check in VOP_ACCESS() be enough? Also, are the group bits
+ * below definitely right?
+ */
if (((ap->a_cred->cr_uid != pn->mn_uid) || uid != pn->mn_uid ||
(gid != pn->mn_gid && !groupmember(gid, ap->a_cred))) &&
- (error = suser_cred(ap->a_td->td_ucred, SUSER_ALLOWJAIL))
- != 0)
+ (error = priv_check_cred(ap->a_td->td_ucred,
+ PRIV_MQ_ADMIN, SUSER_ALLOWJAIL)) != 0)
return (error);
pn->mn_uid = uid;
pn->mn_gid = gid;
@@ -1219,7 +1230,8 @@ mqfs_setattr(struct vop_setattr_args *ap)
if (vap->va_mode != (mode_t)VNOVAL) {
if ((ap->a_cred->cr_uid != pn->mn_uid) &&
- (error = suser_cred(ap->a_td->td_ucred, SUSER_ALLOWJAIL)))
+ (error = priv_check_cred(ap->a_td->td_ucred,
+ PRIV_MQ_ADMIN, SUSER_ALLOWJAIL)))
return (error);
pn->mn_mode = vap->va_mode;
c = 1;
diff --git a/sys/kern/uipc_sem.c b/sys/kern/uipc_sem.c
index 8de7d8f..340c1a6 100644
--- a/sys/kern/uipc_sem.c
+++ b/sys/kern/uipc_sem.c
@@ -42,6 +42,7 @@ __FBSDID("$FreeBSD$");
#include <sys/sysproto.h>
#include <sys/eventhandler.h>
#include <sys/kernel.h>
+#include <sys/priv.h>
#include <sys/proc.h>
#include <sys/lock.h>
#include <sys/mutex.h>
@@ -419,15 +420,23 @@ sem_perm(struct thread *td, struct ksem *ks)
{
struct ucred *uc;
+ /*
+ * XXXRW: This permission routine appears to be incorrect. If the
+ * user matches, we shouldn't go on to the group if the user
+ * permissions don't allow the action? Not changed for now. To fix,
+ * change from a series of if (); if (); to if () else if () else...
+ */
uc = td->td_ucred;
DP(("sem_perm: uc(%d,%d) ks(%d,%d,%o)\n",
uc->cr_uid, uc->cr_gid,
ks->ks_uid, ks->ks_gid, ks->ks_mode));
- if ((uc->cr_uid == ks->ks_uid && (ks->ks_mode & S_IWUSR) != 0) ||
- (uc->cr_gid == ks->ks_gid && (ks->ks_mode & S_IWGRP) != 0) ||
- (ks->ks_mode & S_IWOTH) != 0 || suser(td) == 0)
+ if ((uc->cr_uid == ks->ks_uid) && (ks->ks_mode & S_IWUSR) != 0)
+ return (0);
+ if ((uc->cr_gid == ks->ks_gid) && (ks->ks_mode & S_IWGRP) != 0)
+ return (0);
+ if ((ks->ks_mode & S_IWOTH) != 0)
return (0);
- return (EPERM);
+ return (priv_check(td, PRIV_SEM_WRITE));
}
static void
diff --git a/sys/kern/vfs_extattr.c b/sys/kern/vfs_extattr.c
index 8a57786..bb51d01 100644
--- a/sys/kern/vfs_extattr.c
+++ b/sys/kern/vfs_extattr.c
@@ -60,6 +60,7 @@ __FBSDID("$FreeBSD$");
#include <sys/sx.h>
#include <sys/unistd.h>
#include <sys/vnode.h>
+#include <sys/priv.h>
#include <sys/proc.h>
#include <sys/dirent.h>
#include <sys/extattr.h>
@@ -272,7 +273,7 @@ kern_statfs(struct thread *td, char *path, enum uio_seg pathseg,
error = VFS_STATFS(mp, sp, td);
if (error)
goto out;
- if (suser(td)) {
+ if (priv_check(td, PRIV_VFS_GENERATION)) {
bcopy(sp, &sb, sizeof(sb));
sb.f_fsid.val[0] = sb.f_fsid.val[1] = 0;
prison_enforce_statfs(td->td_ucred, mp, &sb);
@@ -357,7 +358,7 @@ kern_fstatfs(struct thread *td, int fd, struct statfs *buf)
error = VFS_STATFS(mp, sp, td);
if (error)
goto out;
- if (suser(td)) {
+ if (priv_check(td, PRIV_VFS_GENERATION)) {
bcopy(sp, &sb, sizeof(sb));
sb.f_fsid.val[0] = sb.f_fsid.val[1] = 0;
prison_enforce_statfs(td->td_ucred, mp, &sb);
@@ -468,7 +469,7 @@ kern_getfsstat(struct thread *td, struct statfs **buf, size_t bufsize,
vfs_unbusy(mp, td);
continue;
}
- if (suser(td)) {
+ if (priv_check(td, PRIV_VFS_GENERATION)) {
bcopy(sp, &sb, sizeof(sb));
sb.f_fsid.val[0] = sb.f_fsid.val[1] = 0;
prison_enforce_statfs(td->td_ucred, mp, &sb);
@@ -842,7 +843,8 @@ chroot(td, uap)
struct nameidata nd;
int vfslocked;
- error = suser_cred(td->td_ucred, SUSER_ALLOWJAIL);
+ error = priv_check_cred(td->td_ucred, PRIV_VFS_CHROOT,
+ SUSER_ALLOWJAIL);
if (error)
return (error);
NDINIT(&nd, LOOKUP, FOLLOW | LOCKLEAF | MPSAFE | AUDITVNODE1,
@@ -896,8 +898,8 @@ change_dir(vp, td)
/*
* Common routine for kern_chroot() and jail_attach(). The caller is
- * responsible for invoking suser() and mac_check_chroot() to authorize this
- * operation.
+ * responsible for invoking priv_check() and mac_check_chroot() to authorize
+ * this operation.
*/
int
change_root(vp, td)
@@ -1186,10 +1188,16 @@ kern_mknod(struct thread *td, char *path, enum uio_seg pathseg, int mode,
switch (mode & S_IFMT) {
case S_IFCHR:
case S_IFBLK:
- error = suser(td);
+ error = priv_check(td, PRIV_VFS_MKNOD_DEV);
+ break;
+ case S_IFMT:
+ error = priv_check(td, PRIV_VFS_MKNOD_BAD);
+ break;
+ case S_IFWHT:
+ error = priv_check(td, PRIV_VFS_MKNOD_WHT);
break;
default:
- error = suser_cred(td->td_ucred, SUSER_ALLOWJAIL);
+ error = EINVAL;
break;
}
if (error)
@@ -1234,8 +1242,7 @@ restart:
whiteout = 1;
break;
default:
- error = EINVAL;
- break;
+ panic("kern_mknod: invalid mode");
}
}
if (vn_start_write(nd.ni_dvp, &mp, V_NOWAIT) != 0) {
@@ -1390,9 +1397,6 @@ can_hardlink(struct vnode *vp, struct thread *td, struct ucred *cred)
struct vattr va;
int error;
- if (suser_cred(cred, SUSER_ALLOWJAIL) == 0)
- return (0);
-
if (!hardlink_check_uid && !hardlink_check_gid)
return (0);
@@ -1400,14 +1404,18 @@ can_hardlink(struct vnode *vp, struct thread *td, struct ucred *cred)
if (error != 0)
return (error);
- if (hardlink_check_uid) {
- if (cred->cr_uid != va.va_uid)
- return (EPERM);
+ if (hardlink_check_uid && cred->cr_uid != va.va_uid) {
+ error = priv_check_cred(cred, PRIV_VFS_LINK,
+ SUSER_ALLOWJAIL);
+ if (error)
+ return (error);
}
- if (hardlink_check_gid) {
- if (!groupmember(va.va_gid, cred))
- return (EPERM);
+ if (hardlink_check_gid && !groupmember(va.va_gid, cred)) {
+ error = priv_check_cred(cred, PRIV_VFS_LINK,
+ SUSER_ALLOWJAIL);
+ if (error)
+ return (error);
}
return (0);
@@ -2361,7 +2369,8 @@ setfflags(td, vp, flags)
* chown can't fail when done as root.
*/
if (vp->v_type == VCHR || vp->v_type == VBLK) {
- error = suser_cred(td->td_ucred, SUSER_ALLOWJAIL);
+ error = priv_check_cred(td->td_ucred, PRIV_VFS_CHFLAGS_DEV,
+ SUSER_ALLOWJAIL);
if (error)
return (error);
}
@@ -3894,7 +3903,8 @@ revoke(td, uap)
if (error)
goto out;
if (td->td_ucred->cr_uid != vattr.va_uid) {
- error = suser_cred(td->td_ucred, SUSER_ALLOWJAIL);
+ error = priv_check_cred(td->td_ucred, PRIV_VFS_ADMIN,
+ SUSER_ALLOWJAIL);
if (error)
goto out;
}
@@ -3960,7 +3970,7 @@ lgetfh(td, uap)
int vfslocked;
int error;
- error = suser(td);
+ error = priv_check(td, PRIV_VFS_GETFH);
if (error)
return (error);
NDINIT(&nd, LOOKUP, NOFOLLOW | LOCKLEAF | MPSAFE | AUDITVNODE1,
@@ -3999,7 +4009,7 @@ getfh(td, uap)
int vfslocked;
int error;
- error = suser(td);
+ error = priv_check(td, PRIV_VFS_GETFH);
if (error)
return (error);
NDINIT(&nd, LOOKUP, FOLLOW | LOCKLEAF | MPSAFE | AUDITVNODE1,
@@ -4022,10 +4032,10 @@ getfh(td, uap)
}
/*
- * syscall for the rpc.lockd to use to translate a NFS file handle into
- * an open descriptor.
+ * syscall for the rpc.lockd to use to translate a NFS file handle into an
+ * open descriptor.
*
- * warning: do not remove the suser() call or this becomes one giant
+ * warning: do not remove the priv_check() call or this becomes one giant
* security hole.
*
* MP SAFE
@@ -4058,7 +4068,7 @@ fhopen(td, uap)
int vfslocked;
int indx;
- error = suser(td);
+ error = priv_check(td, PRIV_VFS_FHOPEN);
if (error)
return (error);
fmode = FFLAGS(uap->flags);
@@ -4242,7 +4252,7 @@ fhstat(td, uap)
int vfslocked;
int error;
- error = suser(td);
+ error = priv_check(td, PRIV_VFS_FHSTAT);
if (error)
return (error);
error = copyin(uap->u_fhp, &fh, sizeof(fhandle_t));
@@ -4307,7 +4317,7 @@ kern_fhstatfs(struct thread *td, fhandle_t fh, struct statfs *buf)
int vfslocked;
int error;
- error = suser(td);
+ error = priv_check(td, PRIV_VFS_FHSTATFS);
if (error)
return (error);
if ((mp = vfs_getvfs(&fh.fh_fsid)) == NULL)
diff --git a/sys/kern/vfs_mount.c b/sys/kern/vfs_mount.c
index af07f44..ef757b8 100644
--- a/sys/kern/vfs_mount.c
+++ b/sys/kern/vfs_mount.c
@@ -47,6 +47,7 @@ __FBSDID("$FreeBSD$");
#include <sys/mount.h>
#include <sys/mutex.h>
#include <sys/namei.h>
+#include <sys/priv.h>
#include <sys/proc.h>
#include <sys/filedesc.h>
#include <sys/reboot.h>
@@ -808,23 +809,31 @@ vfs_domount(
if (jailed(td->td_ucred))
return (EPERM);
if (usermount == 0) {
- if ((error = suser(td)) != 0)
+ if ((error = priv_check(td, PRIV_VFS_MOUNT)) != 0)
return (error);
}
/*
* Do not allow NFS export or MNT_SUIDDIR by unprivileged users.
*/
- if (fsflags & (MNT_EXPORTED | MNT_SUIDDIR)) {
- if ((error = suser(td)) != 0)
+ if (fsflags & MNT_EXPORTED) {
+ error = priv_check(td, PRIV_VFS_MOUNT_EXPORTED);
+ if (error)
return (error);
}
+ if (fsflags & MNT_SUIDDIR) {
+ error = priv_check(td, PRIV_VFS_MOUNT_SUIDDIR);
+ if (error)
+ return (error);
+
+ }
/*
- * Silently enforce MNT_NOSUID and MNT_USER for
- * unprivileged users.
+ * Silently enforce MNT_NOSUID and MNT_USER for unprivileged users.
*/
- if (suser(td) != 0)
- fsflags |= MNT_NOSUID | MNT_USER;
+ if ((fsflags & (MNT_NOSUID | MNT_USER)) != (MNT_NOSUID | MNT_USER)) {
+ if (priv_check(td, PRIV_VFS_MOUNT_NONUSER) != 0)
+ fsflags |= MNT_NOSUID | MNT_USER;
+ }
/* Load KLDs before we lock the covered vnode to avoid reversals. */
vfsp = NULL;
@@ -906,7 +915,9 @@ vfs_domount(
return (error);
}
if (va.va_uid != td->td_ucred->cr_uid) {
- if ((error = suser(td)) != 0) {
+ error = priv_check_cred(td->td_ucred, PRIV_VFS_ADMIN,
+ SUSER_ALLOWJAIL);
+ if (error) {
vput(vp);
return (error);
}
@@ -1078,7 +1089,8 @@ unmount(td, uap)
if (jailed(td->td_ucred))
return (EPERM);
if (usermount == 0) {
- if ((error = suser(td)) != 0)
+ error = priv_check(td, PRIV_VFS_UNMOUNT);
+ if (error)
return (error);
}
diff --git a/sys/kern/vfs_subr.c b/sys/kern/vfs_subr.c
index 46ffd8f..d584606 100644
--- a/sys/kern/vfs_subr.c
+++ b/sys/kern/vfs_subr.c
@@ -61,6 +61,7 @@ __FBSDID("$FreeBSD$");
#include <sys/malloc.h>
#include <sys/mount.h>
#include <sys/namei.h>
+#include <sys/priv.h>
#include <sys/reboot.h>
#include <sys/sleepqueue.h>
#include <sys/stat.h>
@@ -412,7 +413,7 @@ vfs_suser(struct mount *mp, struct thread *td)
if ((mp->mnt_flag & MNT_USER) == 0 ||
mp->mnt_cred->cr_uid != td->td_ucred->cr_uid) {
- if ((error = suser(td)) != 0)
+ if ((error = priv_check(td, PRIV_VFS_MOUNT_OWNER)) != 0)
return (error);
}
return (0);
@@ -3178,9 +3179,7 @@ vaccess(enum vtype type, mode_t file_mode, uid_t file_uid, gid_t file_gid,
mode_t acc_mode, struct ucred *cred, int *privused)
{
mode_t dac_granted;
-#ifdef CAPABILITIES
- mode_t cap_granted;
-#endif
+ mode_t priv_granted;
/*
* Look for a normal, non-privileged way to access the file/directory
@@ -3234,59 +3233,46 @@ vaccess(enum vtype type, mode_t file_mode, uid_t file_uid, gid_t file_gid,
return (0);
privcheck:
- if (!suser_cred(cred, SUSER_ALLOWJAIL)) {
- /* XXX audit: privilege used */
- if (privused != NULL)
- *privused = 1;
- return (0);
- }
-
-#ifdef CAPABILITIES
/*
- * Build a capability mask to determine if the set of capabilities
+ * Build a privilege mask to determine if the set of privileges
* satisfies the requirements when combined with the granted mask
- * from above. For each capability, if the capability is required,
- * bitwise or the request type onto the cap_granted mask.
- *
- * Note: This is never actually used, but is here for reference
- * purposes.
+ * from above. For each privilege, if the privilege is required,
+ * bitwise or the request type onto the priv_granted mask.
*/
- cap_granted = 0;
+ priv_granted = 0;
if (type == VDIR) {
/*
- * For directories, use CAP_DAC_READ_SEARCH to satisfy
- * VEXEC requests, instead of CAP_DAC_EXECUTE.
+ * For directories, use PRIV_VFS_LOOKUP to satisfy VEXEC
+ * requests, instead of PRIV_VFS_EXEC.
*/
if ((acc_mode & VEXEC) && ((dac_granted & VEXEC) == 0) &&
- !cap_check(cred, NULL, CAP_DAC_READ_SEARCH,
- SUSER_ALLOWJAIL))
- cap_granted |= VEXEC;
+ !priv_check_cred(cred, PRIV_VFS_LOOKUP, SUSER_ALLOWJAIL))
+ priv_granted |= VEXEC;
} else {
if ((acc_mode & VEXEC) && ((dac_granted & VEXEC) == 0) &&
- !cap_check(cred, NULL, CAP_DAC_EXECUTE, SUSER_ALLOWJAIL))
- cap_granted |= VEXEC;
+ !priv_check_cred(cred, PRIV_VFS_EXEC, SUSER_ALLOWJAIL))
+ priv_granted |= VEXEC;
}
if ((acc_mode & VREAD) && ((dac_granted & VREAD) == 0) &&
- !cap_check(cred, NULL, CAP_DAC_READ_SEARCH, SUSER_ALLOWJAIL))
- cap_granted |= VREAD;
+ !priv_check_cred(cred, PRIV_VFS_READ, SUSER_ALLOWJAIL))
+ priv_granted |= VREAD;
if ((acc_mode & VWRITE) && ((dac_granted & VWRITE) == 0) &&
- !cap_check(cred, NULL, CAP_DAC_WRITE, SUSER_ALLOWJAIL))
- cap_granted |= (VWRITE | VAPPEND);
+ !priv_check_cred(cred, PRIV_VFS_WRITE, SUSER_ALLOWJAIL))
+ priv_granted |= (VWRITE | VAPPEND);
if ((acc_mode & VADMIN) && ((dac_granted & VADMIN) == 0) &&
- !cap_check(cred, NULL, CAP_FOWNER, SUSER_ALLOWJAIL))
- cap_granted |= VADMIN;
+ !priv_check_cred(cred, PRIV_VFS_ADMIN, SUSER_ALLOWJAIL))
+ priv_granted |= VADMIN;
- if ((acc_mode & (cap_granted | dac_granted)) == acc_mode) {
+ if ((acc_mode & (priv_granted | dac_granted)) == acc_mode) {
/* XXX audit: privilege used */
if (privused != NULL)
*privused = 1;
return (0);
}
-#endif
return ((acc_mode & VADMIN) ? EPERM : EACCES);
}
@@ -3307,16 +3293,13 @@ extattr_check_cred(struct vnode *vp, int attrnamespace, struct ucred *cred,
return (0);
/*
- * Do not allow privileged processes in jail to directly
- * manipulate system attributes.
- *
- * XXX What capability should apply here?
- * Probably CAP_SYS_SETFFLAG.
+ * Do not allow privileged processes in jail to directly manipulate
+ * system attributes.
*/
switch (attrnamespace) {
case EXTATTR_NAMESPACE_SYSTEM:
/* Potentially should be: return (EPERM); */
- return (suser_cred(cred, 0));
+ return (priv_check_cred(cred, PRIV_VFS_EXTATTR_SYSTEM, 0));
case EXTATTR_NAMESPACE_USER:
return (VOP_ACCESS(vp, access, cred, td));
default:
diff --git a/sys/kern/vfs_syscalls.c b/sys/kern/vfs_syscalls.c
index 8a57786..bb51d01 100644
--- a/sys/kern/vfs_syscalls.c
+++ b/sys/kern/vfs_syscalls.c
@@ -60,6 +60,7 @@ __FBSDID("$FreeBSD$");
#include <sys/sx.h>
#include <sys/unistd.h>
#include <sys/vnode.h>
+#include <sys/priv.h>
#include <sys/proc.h>
#include <sys/dirent.h>
#include <sys/extattr.h>
@@ -272,7 +273,7 @@ kern_statfs(struct thread *td, char *path, enum uio_seg pathseg,
error = VFS_STATFS(mp, sp, td);
if (error)
goto out;
- if (suser(td)) {
+ if (priv_check(td, PRIV_VFS_GENERATION)) {
bcopy(sp, &sb, sizeof(sb));
sb.f_fsid.val[0] = sb.f_fsid.val[1] = 0;
prison_enforce_statfs(td->td_ucred, mp, &sb);
@@ -357,7 +358,7 @@ kern_fstatfs(struct thread *td, int fd, struct statfs *buf)
error = VFS_STATFS(mp, sp, td);
if (error)
goto out;
- if (suser(td)) {
+ if (priv_check(td, PRIV_VFS_GENERATION)) {
bcopy(sp, &sb, sizeof(sb));
sb.f_fsid.val[0] = sb.f_fsid.val[1] = 0;
prison_enforce_statfs(td->td_ucred, mp, &sb);
@@ -468,7 +469,7 @@ kern_getfsstat(struct thread *td, struct statfs **buf, size_t bufsize,
vfs_unbusy(mp, td);
continue;
}
- if (suser(td)) {
+ if (priv_check(td, PRIV_VFS_GENERATION)) {
bcopy(sp, &sb, sizeof(sb));
sb.f_fsid.val[0] = sb.f_fsid.val[1] = 0;
prison_enforce_statfs(td->td_ucred, mp, &sb);
@@ -842,7 +843,8 @@ chroot(td, uap)
struct nameidata nd;
int vfslocked;
- error = suser_cred(td->td_ucred, SUSER_ALLOWJAIL);
+ error = priv_check_cred(td->td_ucred, PRIV_VFS_CHROOT,
+ SUSER_ALLOWJAIL);
if (error)
return (error);
NDINIT(&nd, LOOKUP, FOLLOW | LOCKLEAF | MPSAFE | AUDITVNODE1,
@@ -896,8 +898,8 @@ change_dir(vp, td)
/*
* Common routine for kern_chroot() and jail_attach(). The caller is
- * responsible for invoking suser() and mac_check_chroot() to authorize this
- * operation.
+ * responsible for invoking priv_check() and mac_check_chroot() to authorize
+ * this operation.
*/
int
change_root(vp, td)
@@ -1186,10 +1188,16 @@ kern_mknod(struct thread *td, char *path, enum uio_seg pathseg, int mode,
switch (mode & S_IFMT) {
case S_IFCHR:
case S_IFBLK:
- error = suser(td);
+ error = priv_check(td, PRIV_VFS_MKNOD_DEV);
+ break;
+ case S_IFMT:
+ error = priv_check(td, PRIV_VFS_MKNOD_BAD);
+ break;
+ case S_IFWHT:
+ error = priv_check(td, PRIV_VFS_MKNOD_WHT);
break;
default:
- error = suser_cred(td->td_ucred, SUSER_ALLOWJAIL);
+ error = EINVAL;
break;
}
if (error)
@@ -1234,8 +1242,7 @@ restart:
whiteout = 1;
break;
default:
- error = EINVAL;
- break;
+ panic("kern_mknod: invalid mode");
}
}
if (vn_start_write(nd.ni_dvp, &mp, V_NOWAIT) != 0) {
@@ -1390,9 +1397,6 @@ can_hardlink(struct vnode *vp, struct thread *td, struct ucred *cred)
struct vattr va;
int error;
- if (suser_cred(cred, SUSER_ALLOWJAIL) == 0)
- return (0);
-
if (!hardlink_check_uid && !hardlink_check_gid)
return (0);
@@ -1400,14 +1404,18 @@ can_hardlink(struct vnode *vp, struct thread *td, struct ucred *cred)
if (error != 0)
return (error);
- if (hardlink_check_uid) {
- if (cred->cr_uid != va.va_uid)
- return (EPERM);
+ if (hardlink_check_uid && cred->cr_uid != va.va_uid) {
+ error = priv_check_cred(cred, PRIV_VFS_LINK,
+ SUSER_ALLOWJAIL);
+ if (error)
+ return (error);
}
- if (hardlink_check_gid) {
- if (!groupmember(va.va_gid, cred))
- return (EPERM);
+ if (hardlink_check_gid && !groupmember(va.va_gid, cred)) {
+ error = priv_check_cred(cred, PRIV_VFS_LINK,
+ SUSER_ALLOWJAIL);
+ if (error)
+ return (error);
}
return (0);
@@ -2361,7 +2369,8 @@ setfflags(td, vp, flags)
* chown can't fail when done as root.
*/
if (vp->v_type == VCHR || vp->v_type == VBLK) {
- error = suser_cred(td->td_ucred, SUSER_ALLOWJAIL);
+ error = priv_check_cred(td->td_ucred, PRIV_VFS_CHFLAGS_DEV,
+ SUSER_ALLOWJAIL);
if (error)
return (error);
}
@@ -3894,7 +3903,8 @@ revoke(td, uap)
if (error)
goto out;
if (td->td_ucred->cr_uid != vattr.va_uid) {
- error = suser_cred(td->td_ucred, SUSER_ALLOWJAIL);
+ error = priv_check_cred(td->td_ucred, PRIV_VFS_ADMIN,
+ SUSER_ALLOWJAIL);
if (error)
goto out;
}
@@ -3960,7 +3970,7 @@ lgetfh(td, uap)
int vfslocked;
int error;
- error = suser(td);
+ error = priv_check(td, PRIV_VFS_GETFH);
if (error)
return (error);
NDINIT(&nd, LOOKUP, NOFOLLOW | LOCKLEAF | MPSAFE | AUDITVNODE1,
@@ -3999,7 +4009,7 @@ getfh(td, uap)
int vfslocked;
int error;
- error = suser(td);
+ error = priv_check(td, PRIV_VFS_GETFH);
if (error)
return (error);
NDINIT(&nd, LOOKUP, FOLLOW | LOCKLEAF | MPSAFE | AUDITVNODE1,
@@ -4022,10 +4032,10 @@ getfh(td, uap)
}
/*
- * syscall for the rpc.lockd to use to translate a NFS file handle into
- * an open descriptor.
+ * syscall for the rpc.lockd to use to translate a NFS file handle into an
+ * open descriptor.
*
- * warning: do not remove the suser() call or this becomes one giant
+ * warning: do not remove the priv_check() call or this becomes one giant
* security hole.
*
* MP SAFE
@@ -4058,7 +4068,7 @@ fhopen(td, uap)
int vfslocked;
int indx;
- error = suser(td);
+ error = priv_check(td, PRIV_VFS_FHOPEN);
if (error)
return (error);
fmode = FFLAGS(uap->flags);
@@ -4242,7 +4252,7 @@ fhstat(td, uap)
int vfslocked;
int error;
- error = suser(td);
+ error = priv_check(td, PRIV_VFS_FHSTAT);
if (error)
return (error);
error = copyin(uap->u_fhp, &fh, sizeof(fhandle_t));
@@ -4307,7 +4317,7 @@ kern_fhstatfs(struct thread *td, fhandle_t fh, struct statfs *buf)
int vfslocked;
int error;
- error = suser(td);
+ error = priv_check(td, PRIV_VFS_FHSTATFS);
if (error)
return (error);
if ((mp = vfs_getvfs(&fh.fh_fsid)) == NULL)
diff --git a/sys/kern/vfs_vnops.c b/sys/kern/vfs_vnops.c
index 4a516a7..3511044 100644
--- a/sys/kern/vfs_vnops.c
+++ b/sys/kern/vfs_vnops.c
@@ -45,6 +45,7 @@ __FBSDID("$FreeBSD$");
#include <sys/file.h>
#include <sys/kdb.h>
#include <sys/stat.h>
+#include <sys/priv.h>
#include <sys/proc.h>
#include <sys/limits.h>
#include <sys/lock.h>
@@ -709,7 +710,7 @@ vn_stat(vp, sb, active_cred, file_cred, td)
sb->st_blksize = PAGE_SIZE;
sb->st_flags = vap->va_flags;
- if (suser(td))
+ if (priv_check(td, PRIV_VFS_GENERATION))
sb->st_gen = 0;
else
sb->st_gen = vap->va_gen;
OpenPOWER on IntegriCloud