Index: share/man/man9/Makefile
===================================================================
RCS file: /home/ncvs/src/share/man/man9/Makefile,v
retrieving revision 1.277
diff -u -r1.277 Makefile
--- share/man/man9/Makefile	12 Jul 2006 19:12:16 -0000	1.277
+++ share/man/man9/Makefile	13 Sep 2006 09:02:40 -0000
@@ -185,6 +185,7 @@
 	pmap_zero_page.9 \
 	printf.9 \
 	prison_check.9 \
+	priv.9 \
 	pseudofs.9 \
 	psignal.9 \
 	random.9 \
Index: share/man/man9/priv.9
===================================================================
RCS file: share/man/man9/priv.9
diff -N share/man/man9/priv.9
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ share/man/man9/priv.9	13 Sep 2006 09:02:29 -0000
@@ -0,0 +1,112 @@
+.\"-
+.\" 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:
+.\" 1. Redistributions of source code must retain the above copyright
+.\"    notice, this list of conditions and the following disclaimer.
+.\" 2. Redistributions in binary form must reproduce the above copyright
+.\"    notice, this list of conditions and the following disclaimer in the
+.\"    documentation and/or other materials provided with the distribution.
+.\"
+.\" THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+.\" ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR, NCIRCLE NETWORK SECURITY,
+.\" INC., OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+.\" SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
+.\" TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+.\" PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
+.\" LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+.\" NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+.\" SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+.\"
+.\" $FreeBSD$
+.\"
+.Dd August 30, 2007
+.Dt priv 9
+.Os
+.Sh NAME
+.Nm priv
+.Nd kernel privilege checking API
+.Sh SYNOPSIS
+.In sys/priv.h
+.Vt enum priv {};
+.Ft int
+.Fn priv_check "struct thread *td" "enum priv priv"
+.Ft int
+.Fn priv_check_cred "struct ucred *cred" "enum priv priv" "int flags"
+.Sh DESCRIPTION
+The
+.Xr priv 9
+interfaces check to see if specific system privileges are granted to the
+passed thread,
+.Va td ,
+or credential,
+.Va cred.
+Privileges typically represent rights in one of two categories: the right to
+manage a particular component of the system, or an exemption to a specific
+policy or access control list.
+The caller identifies the desired privilege via the
+.Fa priv
+argument.
+Additional access control context may also be passed using the
+.Va flags .
+.Ss Privilege Policies
+Privileges are typically granted based on one of two base system policies:
+the superuser policy, which grants privilege based on the effective (or
+sometimes real) uid having a value of 0, and the
+.Xr jail 2
+policy, which permits only certain privileges to be granted to processes in a
+jail.
+The set of available privileges may also be influenced by the TrustedBSD MAC
+Framework, described in
+.Xr mac 9 .
+.Sh IMPLEMENTATION NOTES
+When adding a new privilege check to a code path, first check the complete
+list of current privileges in
+.Pa sys/priv.h
+to see if one already exists for the class of privilege required.
+Only if there is not an exact match should a new privilege be added to the
+privilege list.
+As the privilege number becomes encoded in the kernel module ABI, privileges
+should only be appended to the list, not inserted in the list, and the list
+sort order should not be changed.
+.Pp
+Certain catch-all privileges exist, such as
+.Dv PRIV_DRIVER ,
+intended to be used by device drivers, rather than adding a new
+driver-specific privilege.
+.Sh RETURN VALUES
+Typically, 0 will be returned for success, and
+.Dv EPERM
+will be returned on failure.
+Most consumers of
+.Xr priv 9
+will wish to directly return the error code from a failed privilege check to
+user space; a small number will wish to translate it to another error code
+appropriate to a specific context.
+.Pp
+When designing new APIs, it is preferable to return explicit errors from a
+call if privilege is not granted rather than changing the semantics of the
+call but returning success.
+For example, the behavior exhibited by
+.Xr stat 2 ,
+in which the generation field is optionally zero'd out when insufficient
+privilege is not present is highly undesirable, as it results in frequent
+privilege checks, and the caller is unable to tell if an access control
+failure occured.
+.Sh SEE ALSO
+.Xr jail 2 ,
+.Xr mac 9 ,
+.Xr ucred 9
+.Sh AUTHORS
+The
+.Xr priv 9
+API and implementation were created by Robert Watson under contract to
+nCircle Network Security, Inc.
Index: sys/amd64/amd64/io.c
===================================================================
RCS file: /home/ncvs/src/sys/amd64/amd64/io.c,v
retrieving revision 1.1
diff -u -r1.1 io.c
--- sys/amd64/amd64/io.c	1 Aug 2004 11:40:50 -0000	1.1
+++ sys/amd64/amd64/io.c	13 Sep 2006 08:56:13 -0000
@@ -33,6 +33,7 @@
 #include <sys/lock.h>
 #include <sys/malloc.h>
 #include <sys/mutex.h>
+#include <sys/priv.h>
 #include <sys/proc.h>
 #include <sys/signalvar.h>
 #include <sys/systm.h>
@@ -54,7 +55,7 @@
 {
 	int error;
 
-	error = suser(td);
+	error = priv_check(td, PRIV_IO);
 	if (error != 0)
 		return (error);
 	error = securelevel_gt(td->td_ucred, 0);
Index: sys/compat/linux/linux_misc.c
===================================================================
RCS file: /home/ncvs/src/sys/compat/linux/linux_misc.c,v
retrieving revision 1.186
diff -u -r1.186 linux_misc.c
--- sys/compat/linux/linux_misc.c	25 Aug 2006 11:02:42 -0000	1.186
+++ sys/compat/linux/linux_misc.c	13 Sep 2006 08:56:13 -0000
@@ -49,6 +49,7 @@
 #include <sys/mount.h>
 #include <sys/mutex.h>
 #include <sys/namei.h>
+#include <sys/priv.h>
 #include <sys/proc.h>
 #include <sys/reboot.h>
 #include <sys/resourcevar.h>
@@ -1011,7 +1012,8 @@
 	 * Keep cr_groups[0] unchanged to prevent that.
 	 */
 
-	if ((error = suser_cred(oldcred, SUSER_ALLOWJAIL)) != 0) {
+	if ((error = priv_check_cred(oldcred, PRIV_CRED_SETGROUPS,
+	    SUSER_ALLOWJAIL)) != 0) {
 		PROC_UNLOCK(p);
 		crfree(newcred);
 		return (error);
Index: sys/compat/linux/linux_uid16.c
===================================================================
RCS file: /home/ncvs/src/sys/compat/linux/linux_uid16.c,v
retrieving revision 1.19
diff -u -r1.19 linux_uid16.c
--- sys/compat/linux/linux_uid16.c	19 Mar 2006 11:10:33 -0000	1.19
+++ sys/compat/linux/linux_uid16.c	13 Sep 2006 08:56:13 -0000
@@ -33,6 +33,7 @@
 #include <sys/lock.h>
 #include <sys/malloc.h>
 #include <sys/mutex.h>
+#include <sys/priv.h>
 #include <sys/proc.h>
 #include <sys/syscallsubr.h>
 #include <sys/sysproto.h>
@@ -123,7 +124,8 @@
 	 * Keep cr_groups[0] unchanged to prevent that.
 	 */
 
-	if ((error = suser_cred(oldcred, SUSER_ALLOWJAIL)) != 0) {
+	if ((error = priv_check_cred(oldcred, PRIV_CRED_SETGROUPS,
+	    SUSER_ALLOWJAIL)) != 0) {
 		PROC_UNLOCK(p);
 		crfree(newcred);
 		return (error);
Index: sys/compat/svr4/svr4_fcntl.c
===================================================================
RCS file: /home/ncvs/src/sys/compat/svr4/svr4_fcntl.c,v
retrieving revision 1.37
diff -u -r1.37 svr4_fcntl.c
--- sys/compat/svr4/svr4_fcntl.c	28 Sep 2005 07:03:02 -0000	1.37
+++ sys/compat/svr4/svr4_fcntl.c	13 Sep 2006 08:56:13 -0000
@@ -45,6 +45,7 @@
 #include <sys/mount.h>
 #include <sys/mutex.h>
 #include <sys/namei.h>
+#include <sys/priv.h>
 #include <sys/proc.h>
 #include <sys/stat.h>
 #include <sys/syscallsubr.h>
@@ -279,7 +280,8 @@
 		goto out;
 
 	if (td->td_ucred->cr_uid != vattr.va_uid &&
-	    (error = suser(td)) != 0)
+	    (error = priv_check_cred(td->td_ucred, PRIV_VFS_ADMIN,
+	    SUSER_ALLOWJAIL)) != 0)
 		goto out;
 
 	if ((error = vn_start_write(vp, &mp, V_WAIT | PCATCH)) != 0)
Index: sys/compat/svr4/svr4_misc.c
===================================================================
RCS file: /home/ncvs/src/sys/compat/svr4/svr4_misc.c,v
retrieving revision 1.89
diff -u -r1.89 svr4_misc.c
--- sys/compat/svr4/svr4_misc.c	21 Jul 2006 20:28:56 -0000	1.89
+++ sys/compat/svr4/svr4_misc.c	13 Sep 2006 08:56:13 -0000
@@ -53,6 +53,7 @@
 #include <sys/msg.h>
 #include <sys/mutex.h>
 #include <sys/namei.h>
+#include <sys/priv.h>
 #include <sys/proc.h>
 #include <sys/ptrace.h>
 #include <sys/resource.h>
@@ -610,7 +611,8 @@
 	struct file	*fp;
 	int		 error, vfslocked;
 
-	if ((error = suser(td)) != 0)
+	if ((error = priv_check_cred(td->td_ucred, PRIV_VFS_FCHROOT,
+	    SUSER_ALLOWJAIL)) != 0)
 		return error;
 	if ((error = getvnode(fdp, uap->fd, &fp)) != 0)
 		return error;
Index: sys/conf/NOTES
===================================================================
RCS file: /home/ncvs/src/sys/conf/NOTES,v
retrieving revision 1.1380
diff -u -r1.1380 NOTES
--- sys/conf/NOTES	27 Aug 2006 12:57:37 -0000	1.1380
+++ sys/conf/NOTES	13 Sep 2006 08:56:13 -0000
@@ -1001,6 +1001,7 @@
 options 	MAC_NONE
 options 	MAC_PARTITION
 options 	MAC_PORTACL
+options 	MAC_PRIVS
 options 	MAC_SEEOTHERUIDS
 options 	MAC_STUB
 options 	MAC_TEST
Index: sys/conf/files
===================================================================
RCS file: /home/ncvs/src/sys/conf/files,v
retrieving revision 1.1140
diff -u -r1.1140 files
--- sys/conf/files	14 Aug 2006 21:09:37 -0000	1.1140
+++ sys/conf/files	13 Sep 2006 08:56:13 -0000
@@ -1335,6 +1335,7 @@
 kern/kern_physio.c		standard
 kern/kern_pmc.c			standard
 kern/kern_poll.c		optional device_polling
+kern/kern_priv.c		standard
 kern/kern_proc.c		standard
 kern/kern_prot.c		standard
 kern/kern_resource.c		standard
@@ -1911,6 +1912,7 @@
 security/mac/mac_net.c		optional mac
 security/mac/mac_pipe.c		optional mac
 security/mac/mac_posix_sem.c	optional mac
+security/mac/mac_priv.c		optional mac
 security/mac/mac_process.c	optional mac
 security/mac/mac_socket.c	optional mac
 security/mac/mac_system.c	optional mac
@@ -1926,6 +1928,7 @@
 security/mac_none/mac_none.c	optional mac_none
 security/mac_partition/mac_partition.c optional mac_partition
 security/mac_portacl/mac_portacl.c optional mac_portacl
+security/mac_privs/mac_privs.c	optional mac_privs
 security/mac_seeotheruids/mac_seeotheruids.c optional mac_seeotheruids
 security/mac_stub/mac_stub.c	optional mac_stub
 security/mac_test/mac_test.c	optional mac_test
Index: sys/conf/options
===================================================================
RCS file: /home/ncvs/src/sys/conf/options,v
retrieving revision 1.557
diff -u -r1.557 options
--- sys/conf/options	17 Aug 2006 00:37:03 -0000	1.557
+++ sys/conf/options	13 Sep 2006 08:56:13 -0000
@@ -110,6 +110,7 @@
 MAC_NONE	opt_dontuse.h
 MAC_PARTITION	opt_dontuse.h
 MAC_PORTACL	opt_dontuse.h
+MAC_PRIVS	opt_dontuse.h
 MAC_SEEOTHERUIDS	opt_dontuse.h
 MAC_STATIC	opt_mac.h
 MAC_STUB	opt_dontuse.h
Index: sys/contrib/altq/altq/altq_cbq.c
===================================================================
RCS file: /home/ncvs/src/sys/contrib/altq/altq/altq_cbq.c,v
retrieving revision 1.3
diff -u -r1.3 altq_cbq.c
--- sys/contrib/altq/altq/altq_cbq.c	9 Aug 2005 10:19:41 -0000	1.3
+++ sys/contrib/altq/altq/altq_cbq.c	13 Sep 2006 08:56:13 -0000
@@ -1062,7 +1062,9 @@
 		/* currently only command that an ordinary user can call */
 		break;
 	default:
-#if (__FreeBSD_version > 400000)
+#if (__FreeBSD_version > 700000)
+		error = priv_check(p, PRIV_ALTQ_MANAGE);
+#elsif (__FreeBSD_version > 400000)
 		error = suser(p);
 #else
 		error = suser(p->p_ucred, &p->p_acflag);
Index: sys/contrib/altq/altq/altq_cdnr.c
===================================================================
RCS file: /home/ncvs/src/sys/contrib/altq/altq/altq_cdnr.c,v
retrieving revision 1.2
diff -u -r1.2 altq_cdnr.c
--- sys/contrib/altq/altq/altq_cdnr.c	12 Jun 2004 00:57:20 -0000	1.2
+++ sys/contrib/altq/altq/altq_cdnr.c	13 Sep 2006 08:56:13 -0000
@@ -1262,7 +1262,9 @@
 	case CDNR_GETSTATS:
 		break;
 	default:
-#if (__FreeBSD_version > 400000)
+#if (__FreeBSD_versoin > 700000)
+		if ((error = priv_check(p, PRIV_ALTQ_MANAGE)) != 0)
+#elsif (__FreeBSD_version > 400000)
 		if ((error = suser(p)) != 0)
 #else
 		if ((error = suser(p->p_ucred, &p->p_acflag)) != 0)
Index: sys/contrib/altq/altq/altq_hfsc.c
===================================================================
RCS file: /home/ncvs/src/sys/contrib/altq/altq/altq_hfsc.c,v
retrieving revision 1.2
diff -u -r1.2 altq_hfsc.c
--- sys/contrib/altq/altq/altq_hfsc.c	12 Jun 2004 00:57:20 -0000	1.2
+++ sys/contrib/altq/altq/altq_hfsc.c	13 Sep 2006 08:56:13 -0000
@@ -1975,7 +1975,10 @@
 	case HFSC_GETSTATS:
 		break;
 	default:
-#if (__FreeBSD_version > 400000)
+#if (__FreeBSD_version > 700000)
+		if ((error = priv_check(p, PRIV_ALTQ_MANAGE)) != 0)
+			return (error);
+#elsif (__FreeBSD_version > 400000)
 		if ((error = suser(p)) != 0)
 			return (error);
 #else
Index: sys/contrib/altq/altq/altq_priq.c
===================================================================
RCS file: /home/ncvs/src/sys/contrib/altq/altq/altq_priq.c,v
retrieving revision 1.2
diff -u -r1.2 altq_priq.c
--- sys/contrib/altq/altq/altq_priq.c	12 Jun 2004 00:57:20 -0000	1.2
+++ sys/contrib/altq/altq/altq_priq.c	13 Sep 2006 08:56:13 -0000
@@ -772,7 +772,10 @@
 	case PRIQ_GETSTATS:
 		break;
 	default:
-#if (__FreeBSD_version > 400000)
+#if (__FreeBSD_version > 700000)
+		if ((error = priv_check(p, PRIV_ALTQ_MANAGE)) != 0)
+			return (error);
+#elsif (__FreeBSD_version > 400000)
 		if ((error = suser(p)) != 0)
 			return (error);
 #else
Index: sys/contrib/altq/altq/altq_red.c
===================================================================
RCS file: /home/ncvs/src/sys/contrib/altq/altq/altq_red.c,v
retrieving revision 1.2
diff -u -r1.2 altq_red.c
--- sys/contrib/altq/altq/altq_red.c	12 Jun 2004 00:57:20 -0000	1.2
+++ sys/contrib/altq/altq/altq_red.c	13 Sep 2006 08:56:13 -0000
@@ -781,7 +781,9 @@
 	case RED_GETSTATS:
 		break;
 	default:
-#if (__FreeBSD_version > 400000)
+#if (__FreeBSD_version > 700000)
+		if ((error = priv_check(p, PRIV_ALTQ_MANAGE)) != 0)
+#elsif (__FreeBSD_version > 400000)
 		if ((error = suser(p)) != 0)
 #else
 		if ((error = suser(p->p_ucred, &p->p_acflag)) != 0)
Index: sys/contrib/altq/altq/altq_rio.c
===================================================================
RCS file: /home/ncvs/src/sys/contrib/altq/altq/altq_rio.c,v
retrieving revision 1.3
diff -u -r1.3 altq_rio.c
--- sys/contrib/altq/altq/altq_rio.c	10 Jun 2005 16:49:03 -0000	1.3
+++ sys/contrib/altq/altq/altq_rio.c	13 Sep 2006 08:56:13 -0000
@@ -531,7 +531,10 @@
 	case RIO_GETSTATS:
 		break;
 	default:
-#if (__FreeBSD_version > 400000)
+#if (__FreeBSD_versoin > 700000)
+		if ((error = priv_check(p, PRIV_ALTQ_MANAGE)) != 0)
+			return (error);
+#elsif (__FreeBSD_version > 400000)
 		if ((error = suser(p)) != 0)
 			return (error);
 #else
Index: sys/contrib/pf/net/if_pfsync.c
===================================================================
RCS file: /home/ncvs/src/sys/contrib/pf/net/if_pfsync.c,v
retrieving revision 1.30
diff -u -r1.30 if_pfsync.c
--- sys/contrib/pf/net/if_pfsync.c	9 Jul 2006 06:04:01 -0000	1.30
+++ sys/contrib/pf/net/if_pfsync.c	13 Sep 2006 08:56:13 -0000
@@ -54,6 +54,9 @@
 #endif
 
 #include <sys/param.h>
+#ifdef __FreeBSD__
+#include <sys/priv.h>
+#endif
 #include <sys/proc.h>
 #include <sys/systm.h>
 #include <sys/time.h>
@@ -1057,7 +1060,7 @@
 		break;
 	case SIOCSETPFSYNC:
 #ifdef __FreeBSD__
-		if ((error = suser(curthread)) != 0)
+		if ((error = priv_check(curthread, PRIV_NETINET_PF)) != 0)
 #else
 		if ((error = suser(p, p->p_acflag)) != 0)
 #endif
Index: sys/dev/an/if_an.c
===================================================================
RCS file: /home/ncvs/src/sys/dev/an/if_an.c,v
retrieving revision 1.79
diff -u -r1.79 if_an.c
--- sys/dev/an/if_an.c	16 May 2006 14:36:22 -0000	1.79
+++ sys/dev/an/if_an.c	13 Sep 2006 08:56:13 -0000
@@ -92,6 +92,7 @@
 #include <sys/systm.h>
 #include <sys/sockio.h>
 #include <sys/mbuf.h>
+#include <sys/priv.h>
 #include <sys/proc.h>
 #include <sys/kernel.h>
 #include <sys/socket.h>
@@ -1920,7 +1921,7 @@
 			break;
 #ifdef ANCACHE
 		if (sc->areq.an_type == AN_RID_ZERO_CACHE) {
-			error = suser(td);
+			error = priv_check(td, PRIV_DRIVER);
 			if (error)
 				break;
 			sc->an_sigitems = sc->an_nextitem = 0;
@@ -1944,7 +1945,7 @@
 		error = copyout(&sc->areq, ifr->ifr_data, sizeof(sc->areq));
 		break;
 	case SIOCSAIRONET:
-		if ((error = suser(td)))
+		if ((error = priv_check(td, PRIV_DRIVER)))
 			goto out;
 		error = copyin(ifr->ifr_data, &sc->areq, sizeof(sc->areq));
 		if (error != 0)
@@ -1952,7 +1953,7 @@
 		an_setdef(sc, &sc->areq);
 		break;
 	case SIOCGPRIVATE_0:              /* used by Cisco client utility */
-		if ((error = suser(td)))
+		if ((error = priv_check(td, PRIV_DRIVER)))
 			goto out;
 		error = copyin(ifr->ifr_data, &l_ioctl, sizeof(l_ioctl));
 		if (error)
@@ -1974,7 +1975,7 @@
 		}
 		break;
 	case SIOCGPRIVATE_1:              /* used by Cisco client utility */
-		if ((error = suser(td)))
+		if ((error = priv_check(td, PRIV_DRIVER)))
 			goto out;
 		error = copyin(ifr->ifr_data, &l_ioctl, sizeof(l_ioctl));
 		if (error)
@@ -2226,7 +2227,7 @@
 		}
 		break;
 	case SIOCS80211:
-		if ((error = suser(td)))
+		if ((error = priv_check(td, PRIV_NET80211_MANAGE)))
 			goto out;
 		sc->areq.an_len = sizeof(sc->areq);
 		/*
Index: sys/dev/arl/if_arl.c
===================================================================
RCS file: /home/ncvs/src/sys/dev/arl/if_arl.c,v
retrieving revision 1.13
diff -u -r1.13 if_arl.c
--- sys/dev/arl/if_arl.c	16 May 2006 14:36:23 -0000	1.13
+++ sys/dev/arl/if_arl.c	13 Sep 2006 08:56:13 -0000
@@ -43,6 +43,7 @@
 #include <sys/mbuf.h>
 #include <sys/socket.h>
 #include <sys/sockio.h>
+#include <sys/priv.h>
 #include <sys/proc.h>
 #include <sys/conf.h>
 
@@ -504,7 +505,7 @@
 		break;
 
 	case SIOCS80211:
-		if ((error = suser(td)))
+		if ((error = priv_check(td, PRIV_NET80211_MANAGE)))
 			break;
 		switch (ireq->i_type) {
 		case IEEE80211_IOC_SSID:
@@ -577,7 +578,7 @@
 	}
 	case SIOCGARLALL:
 		bzero(&arlan_io, sizeof(arlan_io));
-		if (!suser(td)) {
+		if (!priv_check(td, PRIV_DRIVER)) {
 			bcopy(ar->systemId, arlan_io.cfg.sid, 4);
 		}
 
@@ -616,7 +617,7 @@
 	} while (0)
 
 	case SIOCSARLALL:
-		if (suser(td))
+		if (priv_check(td, PRIV_DRIVER))
 			break;
 
 		user = (void *)ifr->ifr_data;
Index: sys/dev/asr/asr.c
===================================================================
RCS file: /home/ncvs/src/sys/dev/asr/asr.c,v
retrieving revision 1.78
diff -u -r1.78 asr.c
--- sys/dev/asr/asr.c	12 May 2006 05:04:40 -0000	1.78
+++ sys/dev/asr/asr.c	13 Sep 2006 08:56:13 -0000
@@ -117,6 +117,7 @@
 #include <sys/malloc.h>
 #include <sys/conf.h>
 #include <sys/ioccom.h>
+#include <sys/priv.h>
 #include <sys/proc.h>
 #include <sys/bus.h>
 #include <machine/resource.h>
@@ -3114,7 +3115,7 @@
 	s = splcam ();
 	if (ASR_ctlr_held) {
 		error = EBUSY;
-	} else if ((error = suser(td)) == 0) {
+	} else if ((error = priv_check(td, PRIV_DRIVER)) == 0) {
 		++ASR_ctlr_held;
 	}
 	splx(s);
Index: sys/dev/ata/atapi-cd.c
===================================================================
RCS file: /home/ncvs/src/sys/dev/ata/atapi-cd.c,v
retrieving revision 1.189
diff -u -r1.189 atapi-cd.c
--- sys/dev/ata/atapi-cd.c	28 Jun 2006 15:04:10 -0000	1.189
+++ sys/dev/ata/atapi-cd.c	13 Sep 2006 08:56:13 -0000
@@ -34,6 +34,7 @@
 #include <sys/kernel.h>
 #include <sys/module.h>
 #include <sys/malloc.h>
+#include <sys/priv.h>
 #include <sys/proc.h>
 #include <sys/bio.h>
 #include <sys/bus.h>
@@ -257,8 +258,11 @@
 	cdp->flags |= F_LOCKED;
 	break;
 
+    /*
+     * XXXRW: Why does this require privilege?
+     */
     case CDIOCRESET:
-	error = suser(td);
+	error = priv_check(td, PRIV_DRIVER);
 	if (error)
 	    break;
 	error = acd_test_ready(dev);
Index: sys/dev/ce/if_ce.c
===================================================================
RCS file: /home/ncvs/src/sys/dev/ce/if_ce.c,v
retrieving revision 1.3
diff -u -r1.3 if_ce.c
--- sys/dev/ce/if_ce.c	3 Feb 2006 20:55:30 -0000	1.3
+++ sys/dev/ce/if_ce.c	13 Sep 2006 08:56:13 -0000
@@ -29,6 +29,7 @@
 #if NPCI > 0
 
 #include <sys/ucred.h>
+#include <sys/priv.h>
 #include <sys/proc.h>
 #include <sys/systm.h>
 #include <sys/mbuf.h>
@@ -1341,9 +1342,11 @@
 		/* Only for superuser! */
 #if __FreeBSD_version < 500000
 		error = suser (p);
-#else /* __FreeBSD_version >= 500000 */
+#elsif __FreeBSD_version < 700000
 		error = suser (td);
-#endif /* __FreeBSD_version >= 500000 */
+#else
+		error = priv_check (td, PRIV_DRIVER);
+#endif
 		if (error)
 			return error;
 #if __FreeBSD_version >= 600034
@@ -1380,8 +1383,10 @@
 		/* Only for superuser! */
 #if __FreeBSD_version < 500000
 		error = suser (p);
-#else
+#elsif __FreeBSD_version < 700000
 		error = suser (td);
+#else
+		error = priv_check (td, PRIV_DRIVER);
 #endif
 		if (error)
 			return error;
@@ -1408,8 +1413,10 @@
 		/* Only for superuser! */
 #if __FreeBSD_version < 500000
 		error = suser (p);
-#else
+#elsif __FreeBSD_version < 700000
 		error = suser (td);
+#else
+		error = priv_check (td, PRIV_DRIVER);
 #endif
 		if (error)
 			return error;
@@ -1426,8 +1433,10 @@
 		CE_DEBUG2 (d, ("ioctl: setcfg\n"));
 #if __FreeBSD_version < 500000
 		error = suser (p);
-#else
+#elsif __FreeBSD_version < 700000
 		error = suser (td);
+#else
+		error = priv_check (td, PRIV_DRIVER);
 #endif
 		if (error)
 			return error;
@@ -1526,8 +1535,10 @@
 		/* Only for superuser! */
 #if __FreeBSD_version < 500000
 		error = suser (p);
-#else
+#elsif __FreeBSD_version < 700000
 		error = suser (td);
+#else
+		error = priv_check (td, PRIV_DRIVER);
 #endif
 		if (error)
 			return error;
@@ -1560,8 +1571,10 @@
 		/* Only for superuser! */
 #if __FreeBSD_version < 500000
 		error = suser (p);
-#else
+#elsif __FreeBSD_version < 700000
 		error = suser (td);
+#else
+		error = priv_check (td, PRIV_DRIVER);
 #endif
 		if (error)
 			return error;
@@ -1586,8 +1599,10 @@
 		/* Only for superuser! */
 #if __FreeBSD_version < 500000
 		error = suser (p);
-#else
+#elsif __FreeBSD_version < 700000
 		error = suser (td);
+#else
+		error = priv_check (td, PRIV_DRIVER);
 #endif
 		if (error)
 			return error;
@@ -1608,8 +1623,10 @@
 		/* Only for superuser! */
 #if __FreeBSD_version < 500000
 		error = suser (p);
-#else
+#elsif __FreeBSD_version < 700000
 		error = suser (td);
+#else
+		error = priv_check (td, PRIV_DRIVER);
 #endif
 		if (error)
 			return error;
@@ -1634,8 +1651,10 @@
 		/* Only for superuser! */
 #if __FreeBSD_version < 500000
 		error = suser (p);
-#else
+#elsif __FreeBSD_version < 700000
 		error = suser (td);
+#else
+		error = priv_check (td, PRIV_DRIVER);
 #endif
 		if (error)
 			return error;
@@ -1658,8 +1677,10 @@
 		/* Only for superuser! */
 #if __FreeBSD_version < 500000
 		error = suser (p);
-#else
+#elsif __FreeBSD_version < 700000
 		error = suser (td);
+#else
+		error = priv_check (td, PRIV_DRIVER);
 #endif
 		if (error)
 			return error;
@@ -1686,8 +1707,10 @@
 		/* Only for superuser! */
 #if __FreeBSD_version < 500000
 		error = suser (p);
-#else
+#elsif __FreeBSD_version < 700000
 		error = suser (td);
+#else
+		error = priv_check (td, PRIV_DRIVER);
 #endif
 		if (error)
 			return error;
@@ -1708,8 +1731,10 @@
 		/* Only for superuser! */
 #if __FreeBSD_version < 500000
 		error = suser (p);
-#else
+#elsif __FreeBSD_version < 700000
 		error = suser (td);
+#else
+		error = priv_check (td, PRIV_DRIVER);
 #endif
 		if (error)
 			return error;
@@ -1734,8 +1759,10 @@
 		/* Only for superuser! */
 #if __FreeBSD_version < 500000
 		error = suser (p);
-#else
+#elsif __FreeBSD_version < 700000
 		error = suser (td);
+#else
+		error = priv_check (td, PRIV_DRIVER);
 #endif
 		if (error)
 			return error;
@@ -1758,8 +1785,10 @@
 		/* Only for superuser! */
 #if __FreeBSD_version < 500000
 		error = suser (p);
-#else
+#elsif __FreeBSD_version < 700000
 		error = suser (td);
+#else
+		error = priv_check (td, PRIV_DRIVER);
 #endif
 		if (error)
 			return error;
@@ -1784,8 +1813,10 @@
 		/* Only for superuser! */
 #if __FreeBSD_version < 500000
 		error = suser (p);
-#else
+#elsif __FreeBSD_version < 700000
 		error = suser (td);
+#else
+		error = priv_check (td, PRIV_DRIVER);
 #endif
 		if (error)
 			return error;
@@ -1810,8 +1841,10 @@
 		/* Only for superuser! */
 #if __FreeBSD_version < 500000
 		error = suser (p);
-#else
+#elsif __FreeBSD_version < 700000
 		error = suser (td);
+#else
+		error = priv_check (td, PRIV_DRIVER);
 #endif
 		if (error)
 			return error;
@@ -1836,8 +1869,10 @@
 		/* Only for superuser! */
 #if __FreeBSD_version < 500000
 		error = suser (p);
-#else
+#elsif __FreeBSD_version < 700000
 		error = suser (td);
+#else
+		error = priv_check (td, PRIV_DRIVER);
 #endif
 		if (error)
 			return error;
@@ -1867,8 +1902,10 @@
 		/* Only for superuser! */
 #if __FreeBSD_version < 500000
 		error = suser (p);
-#else
+#elsif __FreeBSD_version < 700000
 		error = suser (td);
+#else
+		error = priv_check (td, PRIV_DRIVER);
 #endif
 		if (error)
 			return error;
@@ -1892,8 +1929,10 @@
 		/* Only for superuser! */
 #if __FreeBSD_version < 500000
 		error = suser (p);
-#else
+#elsif __FreeBSD_version < 700000
 		error = suser (td);
+#else
+		error = priv_check (td, PRIV_DRIVER);
 #endif
 		if (error)
 			return error;
@@ -1909,8 +1948,10 @@
 		/* Only for superuser! */
 #if __FreeBSD_version < 500000
 		error = suser (p);
-#else
+#elsif __FreeBSD_version < 700000
 		error = suser (td);
+#else
+		error = priv_check (td, PRIV_DRIVER);
 #endif
 		if (error)
 			return error;
@@ -1945,8 +1986,10 @@
 		/* Only for superuser! */
 #if __FreeBSD_version < 500000
 		error = suser (p);
-#else
+#elsif __FreeBSD_version < 700000
 		error = suser (td);
+#else
+		error = priv_check (td, PRIV_DRIVER);
 #endif
 		if (error)
 			return error;
Index: sys/dev/cp/if_cp.c
===================================================================
RCS file: /home/ncvs/src/sys/dev/cp/if_cp.c,v
retrieving revision 1.29
diff -u -r1.29 if_cp.c
--- sys/dev/cp/if_cp.c	27 Sep 2005 16:57:44 -0000	1.29
+++ sys/dev/cp/if_cp.c	13 Sep 2006 08:56:13 -0000
@@ -33,6 +33,7 @@
 #include <sys/module.h>
 #include <sys/conf.h>
 #include <sys/malloc.h>
+#include <sys/priv.h>
 #include <sys/socket.h>
 #include <sys/sockio.h>
 #include <sys/sysctl.h>
@@ -1071,7 +1072,7 @@
 	case SERIAL_SETPROTO:
 		CP_DEBUG2 (d, ("ioctl: setproto\n"));
 		/* Only for superuser! */
-		error = suser (td);
+		error = priv_check (td, PRIV_DRIVER);
 		if (error)
 			return error;
 		if (d->ifp->if_drv_flags & IFF_DRV_RUNNING)
@@ -1102,7 +1103,7 @@
 	case SERIAL_SETKEEPALIVE:
 		CP_DEBUG2 (d, ("ioctl: setkeepalive\n"));
 		/* Only for superuser! */
-		error = suser (td);
+		error = priv_check (td, PRIV_DRIVER);
 		if (error)
 			return error;
 		if ((IFP2SP(d->ifp)->pp_flags & PP_FR) ||
@@ -1126,7 +1127,7 @@
 
 	case SERIAL_SETMODE:
 		/* Only for superuser! */
-		error = suser (td);
+		error = priv_check (td, PRIV_DRIVER);
 		if (error)
 			return error;
 		if (*(int*)data != SERIAL_HDLC)
@@ -1142,7 +1143,7 @@
 
 	case SERIAL_SETCFG:
 		CP_DEBUG2 (d, ("ioctl: setcfg\n"));
-		error = suser (td);
+		error = priv_check (td, PRIV_DRIVER);
 		if (error)
 			return error;
 		if (c->type != T_E1)
@@ -1239,7 +1240,7 @@
 	case SERIAL_CLRSTAT:
 		CP_DEBUG2 (d, ("ioctl: clrstat\n"));
 		/* Only for superuser! */
-		error = suser (td);
+		error = priv_check (td, PRIV_DRIVER);
 		if (error)
 			return error;
 		c->rintr    = 0;
@@ -1268,7 +1269,7 @@
 	case SERIAL_SETBAUD:
 		CP_DEBUG2 (d, ("ioctl: setbaud\n"));
 		/* Only for superuser! */
-		error = suser (td);
+		error = priv_check (td, PRIV_DRIVER);
 		if (error)
 			return error;
 		s = splimp ();
@@ -1286,7 +1287,7 @@
 	case SERIAL_SETLOOP:
 		CP_DEBUG2 (d, ("ioctl: setloop\n"));
 		/* Only for superuser! */
-		error = suser (td);
+		error = priv_check (td, PRIV_DRIVER);
 		if (error)
 			return error;
 		s = splimp ();
@@ -1306,7 +1307,7 @@
 	case SERIAL_SETDPLL:
 		CP_DEBUG2 (d, ("ioctl: setdpll\n"));
 		/* Only for superuser! */
-		error = suser (td);
+		error = priv_check (td, PRIV_DRIVER);
 		if (error)
 			return error;
 		if (c->type != T_SERIAL)
@@ -1328,7 +1329,7 @@
 	case SERIAL_SETNRZI:
 		CP_DEBUG2 (d, ("ioctl: setnrzi\n"));
 		/* Only for superuser! */
-		error = suser (td);
+		error = priv_check (td, PRIV_DRIVER);
 		if (error)
 			return error;
 		if (c->type != T_SERIAL)
@@ -1348,7 +1349,7 @@
 	case SERIAL_SETDEBUG:
 		CP_DEBUG2 (d, ("ioctl: setdebug\n"));
 		/* Only for superuser! */
-		error = suser (td);
+		error = priv_check (td, PRIV_DRIVER);
 		if (error)
 			return error;
 		d->chan->debug = *(int*)data;
@@ -1370,7 +1371,7 @@
 	case SERIAL_SETHIGAIN:
 		CP_DEBUG2 (d, ("ioctl: sethigain\n"));
 		/* Only for superuser! */
-		error = suser (td);
+		error = priv_check (td, PRIV_DRIVER);
 		if (error)
 			return error;
 		if (c->type != T_E1)
@@ -1392,7 +1393,7 @@
 	case SERIAL_SETPHONY:
 		CP_DEBUG2 (d, ("ioctl: setphony\n"));
 		/* Only for superuser! */
-		error = suser (td);
+		error = priv_check (td, PRIV_DRIVER);
 		if (error)
 			return error;
 		if (c->type != T_E1)
@@ -1414,7 +1415,7 @@
 	case SERIAL_SETUNFRAM:
 		CP_DEBUG2 (d, ("ioctl: setunfram\n"));
 		/* Only for superuser! */
-		error = suser (td);
+		error = priv_check (td, PRIV_DRIVER);
 		if (error)
 			return error;
 		if (c->type != T_E1)
@@ -1436,7 +1437,7 @@
 	case SERIAL_SETSCRAMBLER:
 		CP_DEBUG2 (d, ("ioctl: setscrambler\n"));
 		/* Only for superuser! */
-		error = suser (td);
+		error = priv_check (td, PRIV_DRIVER);
 		if (error)
 			return error;
 		if (c->type != T_G703 && !c->unfram)
@@ -1461,7 +1462,7 @@
 	case SERIAL_SETMONITOR:
 		CP_DEBUG2 (d, ("ioctl: setmonitor\n"));
 		/* Only for superuser! */
-		error = suser (td);
+		error = priv_check (td, PRIV_DRIVER);
 		if (error)
 			return error;
 		if (c->type != T_E1)
@@ -1483,7 +1484,7 @@
 	case SERIAL_SETUSE16:
 		CP_DEBUG2 (d, ("ioctl: setuse16\n"));
 		/* Only for superuser! */
-		error = suser (td);
+		error = priv_check (td, PRIV_DRIVER);
 		if (error)
 			return error;
 		if (c->type != T_E1)
@@ -1505,7 +1506,7 @@
 	case SERIAL_SETCRC4:
 		CP_DEBUG2 (d, ("ioctl: setcrc4\n"));
 		/* Only for superuser! */
-		error = suser (td);
+		error = priv_check (td, PRIV_DRIVER);
 		if (error)
 			return error;
 		if (c->type != T_E1)
@@ -1538,7 +1539,7 @@
 	case SERIAL_SETCLK:
 		CP_DEBUG2 (d, ("ioctl: setclk\n"));
 		/* Only for superuser! */
-		error = suser (td);
+		error = priv_check (td, PRIV_DRIVER);
 		if (error)
 			return error;
 		if (c->type != T_E1 &&
@@ -1571,7 +1572,7 @@
 	case SERIAL_SETTIMESLOTS:
 		CP_DEBUG2 (d, ("ioctl: settimeslots\n"));
 		/* Only for superuser! */
-		error = suser (td);
+		error = priv_check (td, PRIV_DRIVER);
 		if (error)
 			return error;
 		if ((c->type != T_E1 || c->unfram) && c->type != T_DATA)
@@ -1597,7 +1598,7 @@
 	case SERIAL_SETINVCLK:
 		CP_DEBUG2 (d, ("ioctl: setinvclk\n"));
 		/* Only for superuser! */
-		error = suser (td);
+		error = priv_check (td, PRIV_DRIVER);
 		if (error)
 			return error;
 		if (c->type != T_SERIAL)
@@ -1620,7 +1621,7 @@
 	case SERIAL_SETINVTCLK:
 		CP_DEBUG2 (d, ("ioctl: setinvtclk\n"));
 		/* Only for superuser! */
-		error = suser (td);
+		error = priv_check (td, PRIV_DRIVER);
 		if (error)
 			return error;
 		if (c->type != T_SERIAL)
@@ -1642,7 +1643,7 @@
 	case SERIAL_SETINVRCLK:
 		CP_DEBUG2 (d, ("ioctl: setinvrclk\n"));
 		/* Only for superuser! */
-		error = suser (td);
+		error = priv_check (td, PRIV_DRIVER);
 		if (error)
 			return error;
 		if (c->type != T_SERIAL)
@@ -1669,7 +1670,7 @@
 	case SERIAL_RESET:
 		CP_DEBUG2 (d, ("ioctl: reset\n"));
 		/* Only for superuser! */
-		error = suser (td);
+		error = priv_check (td, PRIV_DRIVER);
 		if (error)
 			return error;
 		s = splimp ();
@@ -1682,7 +1683,7 @@
 	case SERIAL_HARDRESET:
 		CP_DEBUG2 (d, ("ioctl: hardreset\n"));
 		/* Only for superuser! */
-		error = suser (td);
+		error = priv_check (td, PRIV_DRIVER);
 		if (error)
 			return error;
 		s = splimp ();
@@ -1714,7 +1715,7 @@
 	case SERIAL_SETDIR:
 		CP_DEBUG2 (d, ("ioctl: setdir\n"));
 		/* Only for superuser! */
-		error = suser (td);
+		error = priv_check (td, PRIV_DRIVER);
 		if (error)
 			return error;
 		s = splimp ();
@@ -1739,7 +1740,7 @@
 		if (c->type != T_E3 && c->type != T_T3 && c->type != T_STS1)
 			return EINVAL;
 		/* Only for superuser! */
-		error = suser (td);
+		error = priv_check (td, PRIV_DRIVER);
 		if (error)
 			return error;
 		s = splimp ();
@@ -1761,7 +1762,7 @@
 		if (c->type != T_T3 && c->type != T_STS1)
 			return EINVAL;
 		/* Only for superuser! */
-		error = suser (td);
+		error = priv_check (td, PRIV_DRIVER);
 		if (error)
 			return error;
 		s = splimp ();
Index: sys/dev/ctau/if_ct.c
===================================================================
RCS file: /home/ncvs/src/sys/dev/ctau/if_ct.c,v
retrieving revision 1.29
diff -u -r1.29 if_ct.c
--- sys/dev/ctau/if_ct.c	16 May 2006 14:36:24 -0000	1.29
+++ sys/dev/ctau/if_ct.c	13 Sep 2006 08:56:13 -0000
@@ -32,6 +32,7 @@
 #include <sys/mbuf.h>
 #include <sys/sockio.h>
 #include <sys/malloc.h>
+#include <sys/priv.h>
 #include <sys/socket.h>
 #include <sys/sysctl.h>
 #include <sys/conf.h>
@@ -1300,7 +1301,7 @@
 
 	case SERIAL_SETPROTO:
 		/* Only for superuser! */
-		error = suser (td);
+		error = priv_check (td, PRIV_DRIVER);
 		if (error)
 			return error;
 		if (d->ifp->if_drv_flags & IFF_DRV_RUNNING)
@@ -1328,7 +1329,7 @@
 
 	case SERIAL_SETKEEPALIVE:
 		/* Only for superuser! */
-		error = suser (td);
+		error = priv_check (td, PRIV_DRIVER);
 		if (error)
 			return error;
 		if ((IFP2SP(d->ifp)->pp_flags & PP_FR) ||
@@ -1357,7 +1358,7 @@
 
 	case SERIAL_SETCFG:
 		/* Only for superuser! */
-		error = suser (td);
+		error = priv_check (td, PRIV_DRIVER);
 		if (error)
 			return error;
 		if (c->mode == M_HDLC)
@@ -1435,7 +1436,7 @@
 
 	case SERIAL_CLRSTAT:
 		/* Only for superuser! */
-		error = suser (td);
+		error = priv_check (td, PRIV_DRIVER);
 		if (error)
 			return error;
 		c->rintr = 0;
@@ -1458,7 +1459,7 @@
 
 	case SERIAL_SETBAUD:
 		/* Only for superuser! */
-		error = suser (td);
+		error = priv_check (td, PRIV_DRIVER);
 		if (error)
 			return error;
 		s = splimp ();
@@ -1474,7 +1475,7 @@
 
 	case SERIAL_SETLOOP:
 		/* Only for superuser! */
-		error = suser (td);
+		error = priv_check (td, PRIV_DRIVER);
 		if (error)
 			return error;
 		s = splimp ();
@@ -1492,7 +1493,7 @@
 
 	case SERIAL_SETDPLL:
 		/* Only for superuser! */
-		error = suser (td);
+		error = priv_check (td, PRIV_DRIVER);
 		if (error)
 			return error;
 		if (c->mode == M_E1 || c->mode == M_G703)
@@ -1512,7 +1513,7 @@
 
 	case SERIAL_SETNRZI:
 		/* Only for superuser! */
-		error = suser (td);
+		error = priv_check (td, PRIV_DRIVER);
 		if (error)
 			return error;
 		if (c->mode == M_E1 || c->mode == M_G703)
@@ -1530,7 +1531,7 @@
 
 	case SERIAL_SETDEBUG:
 		/* Only for superuser! */
-		error = suser (td);
+		error = priv_check (td, PRIV_DRIVER);
 		if (error)
 			return error;
 		c->debug = *(int*)data;
@@ -1550,7 +1551,7 @@
 
 	case SERIAL_SETHIGAIN:
 		/* Only for superuser! */
-		error = suser (td);
+		error = priv_check (td, PRIV_DRIVER);
 		if (error)
 			return error;
 		s = splimp ();
@@ -1572,7 +1573,7 @@
 		if (c->mode != M_E1)
 			return EINVAL;
 		/* Only for superuser! */
-		error = suser (td);
+		error = priv_check (td, PRIV_DRIVER);
 		if (error)
 			return error;
 		s = splimp ();
@@ -1595,7 +1596,7 @@
 
 	case SERIAL_SETCLK:
 		/* Only for superuser! */
-		error = suser (td);
+		error = priv_check (td, PRIV_DRIVER);
 		if (error)
 			return error;
 		s = splimp ();
@@ -1619,7 +1620,7 @@
 
 	case SERIAL_SETTIMESLOTS:
 		/* Only for superuser! */
-		error = suser (td);
+		error = priv_check (td, PRIV_DRIVER);
 		if (error)
 			return error;
 		s = splimp ();
@@ -1637,7 +1638,7 @@
 
 	case SERIAL_SETSUBCHAN:
 		/* Only for superuser! */
-		error = suser (td);
+		error = priv_check (td, PRIV_DRIVER);
 		if (error)
 			return error;
 		s = splimp ();
@@ -1663,7 +1664,7 @@
 	case SERIAL_SETINVCLK:
 	case SERIAL_SETINVTCLK:
 		/* Only for superuser! */
-		error = suser (td);
+		error = priv_check (td, PRIV_DRIVER);
 		if (error)
 			return error;
 		if (c->mode == M_E1 || c->mode == M_G703)
@@ -1677,7 +1678,7 @@
 
 	case SERIAL_SETINVRCLK:
 		/* Only for superuser! */
-		error = suser (td);
+		error = priv_check (td, PRIV_DRIVER);
 		if (error)
 			return error;
 		if (c->mode == M_E1 || c->mode == M_G703)
Index: sys/dev/cx/if_cx.c
===================================================================
RCS file: /home/ncvs/src/sys/dev/cx/if_cx.c,v
retrieving revision 1.52
diff -u -r1.52 if_cx.c
--- sys/dev/cx/if_cx.c	16 May 2006 14:36:24 -0000	1.52
+++ sys/dev/cx/if_cx.c	13 Sep 2006 08:56:13 -0000
@@ -30,6 +30,7 @@
 #include <sys/systm.h>
 #include <sys/kernel.h>
 #include <sys/module.h>
+#include <sys/priv.h>
 #include <sys/proc.h>
 #include <sys/mbuf.h>
 #include <sys/sockio.h>
@@ -1632,7 +1633,7 @@
 	case SERIAL_SETPORT:
 		CX_DEBUG2 (d, ("ioctl: setproto\n"));
 		/* Only for superuser! */
-		error = suser (td);
+		error = priv_check (td, PRIV_DRIVER);
 		if (error)
 			return error;
 
@@ -1658,7 +1659,7 @@
 	case SERIAL_SETPROTO:
 		CX_DEBUG2 (d, ("ioctl: setproto\n"));
 		/* Only for superuser! */
-		error = suser (td);
+		error = priv_check (td, PRIV_DRIVER);
 		if (error)
 			return error;
 		if (c->mode == M_ASYNC)
@@ -1695,7 +1696,7 @@
 	case SERIAL_SETKEEPALIVE:
 		CX_DEBUG2 (d, ("ioctl: setkeepalive\n"));
 		/* Only for superuser! */
-		error = suser (td);
+		error = priv_check (td, PRIV_DRIVER);
 		if (error)
 			return error;
 		if ((IFP2SP(d->ifp)->pp_flags & PP_FR) ||
@@ -1725,7 +1726,7 @@
 	case SERIAL_SETMODE:
 		CX_DEBUG2 (d, ("ioctl: setmode\n"));
 		/* Only for superuser! */
-		error = suser (td);
+		error = priv_check (td, PRIV_DRIVER);
 		if (error)
 			return error;
 
@@ -1778,7 +1779,7 @@
 	case SERIAL_CLRSTAT:
 		CX_DEBUG2 (d, ("ioctl: clrstat\n"));
 		/* Only for superuser! */
-		error = suser (td);
+		error = priv_check (td, PRIV_DRIVER);
 		if (error)
 			return error;
 		s = splhigh ();
@@ -1810,7 +1811,7 @@
 	case SERIAL_SETBAUD:
 		CX_DEBUG2 (d, ("ioctl: setbaud\n"));
 		/* Only for superuser! */
-		error = suser (td);
+		error = priv_check (td, PRIV_DRIVER);
 		if (error)
 			return error;
 		if (c->mode == M_ASYNC)
@@ -1836,7 +1837,7 @@
 	case SERIAL_SETLOOP:
 		CX_DEBUG2 (d, ("ioctl: setloop\n"));
 		/* Only for superuser! */
-		error = suser (td);
+		error = priv_check (td, PRIV_DRIVER);
 		if (error)
 			return error;
 		if (c->mode == M_ASYNC)
@@ -1862,7 +1863,7 @@
 	case SERIAL_SETDPLL:
 		CX_DEBUG2 (d, ("ioctl: setdpll\n"));
 		/* Only for superuser! */
-		error = suser (td);
+		error = priv_check (td, PRIV_DRIVER);
 		if (error)
 			return error;
 		if (c->mode == M_ASYNC)
@@ -1888,7 +1889,7 @@
 	case SERIAL_SETNRZI:
 		CX_DEBUG2 (d, ("ioctl: setnrzi\n"));
 		/* Only for superuser! */
-		error = suser (td);
+		error = priv_check (td, PRIV_DRIVER);
 		if (error)
 			return error;
 		if (c->mode == M_ASYNC)
@@ -1912,7 +1913,7 @@
 	case SERIAL_SETDEBUG:
 		CX_DEBUG2 (d, ("ioctl: setdebug\n"));
 		/* Only for superuser! */
-		error = suser (td);
+		error = priv_check (td, PRIV_DRIVER);
 		if (error)
 			return error;
 		s = splhigh ();
Index: sys/dev/dcons/dcons_os.c
===================================================================
RCS file: /home/ncvs/src/sys/dev/dcons/dcons_os.c,v
retrieving revision 1.11
diff -u -r1.11 dcons_os.c
--- sys/dev/dcons/dcons_os.c	26 May 2006 13:51:38 -0000	1.11
+++ sys/dev/dcons/dcons_os.c	13 Sep 2006 08:56:13 -0000
@@ -48,6 +48,7 @@
 #include <sys/consio.h>
 #include <sys/tty.h>
 #include <sys/malloc.h>
+#include <sys/priv.h>
 #include <sys/proc.h>
 #include <sys/ucred.h>
 
@@ -293,7 +294,8 @@
 	if ((tp->t_state & TS_ISOPEN) == 0) {
 		tp->t_state |= TS_CARR_ON;
 		ttyconsolemode(tp, 0);
-	} else if ((tp->t_state & TS_XCLUDE) && suser(td)) {
+	} else if ((tp->t_state & TS_XCLUDE) &&
+	    priv_check(td, PRIV_TTY_EXCLUSIVE)) {
 		splx(s);
 		return (EBUSY);
 	}
Index: sys/dev/drm/drmP.h
===================================================================
RCS file: /home/ncvs/src/sys/dev/drm/drmP.h,v
retrieving revision 1.17
diff -u -r1.17 drmP.h
--- sys/dev/drm/drmP.h	7 Sep 2006 23:04:47 -0000	1.17
+++ sys/dev/drm/drmP.h	13 Sep 2006 08:56:13 -0000
@@ -50,6 +50,9 @@
 #include <sys/systm.h>
 #include <sys/conf.h>
 #include <sys/stat.h>
+#if __FreeBSD_version >= 700000
+#include <sys/priv.h>
+#endif
 #include <sys/proc.h>
 #include <sys/lock.h>
 #include <sys/fcntl.h>
@@ -233,7 +236,11 @@
 
 #define PAGE_ALIGN(addr) round_page(addr)
 /* DRM_SUSER returns true if the user is superuser */
+#if __FreeBSD_version >= 700000
+#define	DRM_SUSER(p)		(priv_check(p, PRIV_DRIVER) == 0)
+#else
 #define DRM_SUSER(p)		(suser(p) == 0)
+#endif
 #define DRM_AGP_FIND_DEVICE()	agp_find_device()
 #define DRM_MTRR_WC		MDF_WRITECOMBINE
 #define jiffies			ticks
Index: sys/dev/fdc/fdc.c
===================================================================
RCS file: /home/ncvs/src/sys/dev/fdc/fdc.c,v
retrieving revision 1.313
diff -u -r1.313 fdc.c
--- sys/dev/fdc/fdc.c	8 Sep 2006 21:46:00 -0000	1.313
+++ sys/dev/fdc/fdc.c	13 Sep 2006 08:56:13 -0000
@@ -69,6 +69,7 @@
 #include <sys/malloc.h>
 #include <sys/module.h>
 #include <sys/mutex.h>
+#include <sys/priv.h>
 #include <sys/proc.h>
 #include <sys/rman.h>
 #include <sys/sysctl.h>
@@ -1489,8 +1490,9 @@
 		return (0);
 
 	case FD_CLRERR:
-		if (suser(td) != 0)
-			return (EPERM);
+		error = priv_check(td, PRIV_DRIVER);
+		if (error)
+			return (error);
 		fd->fdc->fdc_errs = 0;
 		return (0);
 
Index: sys/dev/hwpmc/hwpmc_mod.c
===================================================================
RCS file: /home/ncvs/src/sys/dev/hwpmc/hwpmc_mod.c,v
retrieving revision 1.24
diff -u -r1.24 hwpmc_mod.c
--- sys/dev/hwpmc/hwpmc_mod.c	17 Apr 2006 18:20:37 -0000	1.24
+++ sys/dev/hwpmc/hwpmc_mod.c	13 Sep 2006 08:56:13 -0000
@@ -41,6 +41,7 @@
 #include <sys/pmc.h>
 #include <sys/pmckern.h>
 #include <sys/pmclog.h>
+#include <sys/priv.h>
 #include <sys/proc.h>
 #include <sys/queue.h>
 #include <sys/resourcevar.h>
@@ -252,8 +253,6 @@
  * per-process measurements.  This feature is turned off by default.
  */
 
-SYSCTL_DECL(_security_bsd);
-
 static int pmc_unprivileged_syspmcs = 0;
 TUNABLE_INT("security.bsd.unprivileged_syspmcs", &pmc_unprivileged_syspmcs);
 SYSCTL_INT(_security_bsd, OID_AUTO, unprivileged_syspmcs, CTLFLAG_RW,
@@ -2784,10 +2783,9 @@
 		KASSERT(td == curthread,
 		    ("[pmc,%d] td != curthread", __LINE__));
 
-		if (suser(td) || jailed(td->td_ucred)) {
-			error =  EPERM;
+		error = priv_check(td, PRIV_PMC_MANAGE);
+		if (error)
 			break;
-		}
 
 		if ((error = copyin(arg, &pma, sizeof(pma))) != 0)
 			break;
@@ -2920,11 +2918,16 @@
 		 */
 
 		if (PMC_IS_SYSTEM_MODE(mode)) {
-			if (jailed(curthread->td_ucred))
-				error = EPERM;
-			else if (suser(curthread) &&
-			    (pmc_unprivileged_syspmcs == 0))
+			if (jailed(curthread->td_ucred)) {
 				error = EPERM;
+				break;
+			}
+			if (!pmc_unprivileged_syspmcs) {
+				error = priv_check(curthread,
+				    PRIV_PMC_SYSTEM);
+				if (error)
+					break;
+			}
 		}
 
 		if (error)
Index: sys/dev/if_ndis/if_ndis.c
===================================================================
RCS file: /home/ncvs/src/sys/dev/if_ndis/if_ndis.c,v
retrieving revision 1.117
diff -u -r1.117 if_ndis.c
--- sys/dev/if_ndis/if_ndis.c	4 Feb 2006 19:42:49 -0000	1.117
+++ sys/dev/if_ndis/if_ndis.c	13 Sep 2006 08:56:13 -0000
@@ -41,6 +41,7 @@
 #include <sys/sockio.h>
 #include <sys/mbuf.h>
 #include <sys/malloc.h>
+#include <sys/priv.h>
 #include <sys/kernel.h>
 #include <sys/socket.h>
 #include <sys/queue.h>
@@ -2836,7 +2837,7 @@
 			error = ENOTTY;
 		break;
 	case SIOCGDRVSPEC:
-		if ((error = suser(curthread)))
+		if ((error = priv_check(curthread, PRIV_DRIVER)))
 			break;
 		error =  copyin(ifr->ifr_data, &oid, sizeof(oid));
 		if (error)
@@ -2865,7 +2866,7 @@
 		free(oidbuf, M_TEMP);
 		break;
 	case SIOCSDRVSPEC:
-		if ((error = suser(curthread)))
+		if ((error = priv_check(curthread, PRIV_DRIVER)))
 			break;
 		error =  copyin(ifr->ifr_data, &oid, sizeof(oid));
 		if (error)
@@ -2894,7 +2895,7 @@
 		free(oidbuf, M_TEMP);
 		break;
 	case SIOCGPRIVATE_0:
-		if ((error = suser(curthread)))
+		if ((error = priv_check(curthread, PRIV_DRIVER)))
 			break;
 		NDIS_LOCK(sc);
 		if (sc->ndis_evt[sc->ndis_evtcidx].ne_sts == 0) {
@@ -3062,7 +3063,7 @@
 	uint32_t		foo;
 	int			error, len;
 
-	error = suser(curthread);
+	error = priv_check(curthread, PRIV_DRIVER);
 	if (error)
 		return (error);
 
@@ -3370,7 +3371,7 @@
 		break;
 #endif
 	case IEEE80211_IOC_STATIONNAME:
-		error = suser(curthread);
+		error = priv_check(curthread, PRIV_NET80211_MANAGE);
 		if (error)
 			break;
 		if (ireq->i_val != 0 ||
Index: sys/dev/kbd/kbd.c
===================================================================
RCS file: /home/ncvs/src/sys/dev/kbd/kbd.c,v
retrieving revision 1.45
diff -u -r1.45 kbd.c
--- sys/dev/kbd/kbd.c	28 Feb 2006 23:46:23 -0000	1.45
+++ sys/dev/kbd/kbd.c	13 Sep 2006 08:56:13 -0000
@@ -38,6 +38,7 @@
 #include <sys/fcntl.h>
 #include <sys/tty.h>
 #include <sys/poll.h>
+#include <sys/priv.h>
 #include <sys/proc.h>
 #include <sys/sysctl.h>
 #include <sys/uio.h>
@@ -972,11 +973,11 @@
 	if (keymap_restrict_change >= 2) {
 		for (i = 0; i < NUM_STATES; i++)
 			if (oldkey->map[i] != newkey->map[i])
-				return suser(td);
+				return priv_check(td, PRIV_KEYBOARD);
 		if (oldkey->spcl != newkey->spcl)
-			return suser(td);
+			return priv_check(td, PRIV_KEYBOARD);
 		if (oldkey->flgs != newkey->flgs)
-			return suser(td);
+			return priv_check(td, PRIV_KEYBOARD);
 		return (0);
 	}
 
@@ -991,7 +992,7 @@
 		if ((oldkey->spcl & (0x80 >> i)) == (newkey->spcl & (0x80 >> i))
 		    && oldkey->map[i] == newkey->map[i])
 			continue;
-		return suser(td);
+		return priv_check(td, PRIV_KEYBOARD);
 	}
 
 	return (0);
@@ -1020,20 +1021,20 @@
 		return (0);
 
 	if (oldmap->n_accs != newmap->n_accs)
-		return suser(td);
+		return priv_check(td, PRIV_KEYBOARD);
 
 	for (accent = 0; accent < oldmap->n_accs; accent++) {
 		oldacc = &oldmap->acc[accent];
 		newacc = &newmap->acc[accent];
 		if (oldacc->accchar != newacc->accchar)
-			return suser(td);
+			return priv_check(td, PRIV_KEYBOARD);
 		for (i = 0; i < NUM_ACCENTCHARS; ++i) {
 			if (oldacc->map[i][0] != newacc->map[i][0])
-				return suser(td);
+				return priv_check(td, PRIV_KEYBOARD);
 			if (oldacc->map[i][0] == 0)	/* end of table */
 				break;
 			if (oldacc->map[i][1] != newacc->map[i][1])
-				return suser(td);
+				return priv_check(td, PRIV_KEYBOARD);
 		}
 	}
 
@@ -1048,7 +1049,7 @@
 
 	if (oldkey->len != newkey->flen ||
 	    bcmp(oldkey->str, newkey->keydef, oldkey->len) != 0)
-		return suser(td);
+		return priv_check(td, PRIV_KEYBOARD);
 
 	return (0);
 }
Index: sys/dev/lmc/if_lmc.c
===================================================================
RCS file: /home/ncvs/src/sys/dev/lmc/if_lmc.c,v
retrieving revision 1.29
diff -u -r1.29 if_lmc.c
--- sys/dev/lmc/if_lmc.c	15 Jul 2006 02:07:38 -0000	1.29
+++ sys/dev/lmc/if_lmc.c	13 Sep 2006 08:56:13 -0000
@@ -113,6 +113,9 @@
 # include <sys/rman.h>
 # include <vm/vm.h>
 # include <vm/pmap.h>
+# if (__FreeBSD_version >= 700000)
+#  include <sys/priv.h>
+# endif
 # if (__FreeBSD_version >= 500000)
 #  include <sys/mutex.h>
 #  include <dev/pci/pcivar.h>
Index: sys/dev/lmc/if_lmc.h
===================================================================
RCS file: /home/ncvs/src/sys/dev/lmc/if_lmc.h,v
retrieving revision 1.4
diff -u -r1.4 if_lmc.h
--- sys/dev/lmc/if_lmc.h	21 Jul 2006 08:45:00 -0000	1.4
+++ sys/dev/lmc/if_lmc.h	13 Sep 2006 08:56:13 -0000
@@ -1223,7 +1223,11 @@
 #  define TOP_UNLOCK		mtx_unlock (&sc->top_mtx)
 #  define BOTTOM_TRYLOCK	mtx_trylock(&sc->bottom_mtx)
 #  define BOTTOM_UNLOCK		mtx_unlock (&sc->bottom_mtx)
-#  define CHECK_CAP		suser(curthread)
+#  if (__FreeBSD_version >= 700000)
+#   define CHECK_CAP		priv_check(curthread, PRIV_DRIVER)
+#  else
+#   define CHECK_CAP		suser(curthread)
+#  endif
 # else /* FreeBSD-4 */
 #  define TOP_TRYLOCK		(sc->top_spl = splimp())
 #  define TOP_UNLOCK		splx(sc->top_spl)
Index: sys/dev/nmdm/nmdm.c
===================================================================
RCS file: /home/ncvs/src/sys/dev/nmdm/nmdm.c,v
retrieving revision 1.37
diff -u -r1.37 nmdm.c
--- sys/dev/nmdm/nmdm.c	4 Jan 2006 08:34:23 -0000	1.37
+++ sys/dev/nmdm/nmdm.c	13 Sep 2006 08:56:13 -0000
@@ -41,6 +41,7 @@
 
 #include <sys/param.h>
 #include <sys/systm.h>
+#include <sys/priv.h>
 #include <sys/proc.h>
 #include <sys/tty.h>
 #include <sys/conf.h>
@@ -286,7 +287,8 @@
 	if ((tp->t_state & TS_ISOPEN) == 0) {
 		ttyinitmode(tp, 0, 0);
 		ttsetwater(tp); /* XXX ? */
-	} else if (tp->t_state & TS_XCLUDE && suser(td)) {
+	} else if (tp->t_state & TS_XCLUDE &&
+	    priv_check(td, PRIV_TTY_EXCLUSIVE)) {
 		return (EBUSY);
 	}
 
Index: sys/dev/null/null.c
===================================================================
RCS file: /home/ncvs/src/sys/dev/null/null.c,v
retrieving revision 1.31
diff -u -r1.31 null.c
--- sys/dev/null/null.c	27 Feb 2005 22:00:45 -0000	1.31
+++ sys/dev/null/null.c	13 Sep 2006 08:56:13 -0000
@@ -36,6 +36,7 @@
 #include <sys/kernel.h>
 #include <sys/malloc.h>
 #include <sys/module.h>
+#include <sys/priv.h>
 #include <sys/disk.h>
 #include <sys/bus.h>
 #include <machine/bus.h>
@@ -87,7 +88,7 @@
 
 	if (cmd != DIOCSKERNELDUMP)
 		return (ENOIOCTL);
-	error = suser(td);
+	error = priv_check(td, PRIV_SETDUMPER);
 	if (error)
 		return (error);
 	return (set_dumper(NULL));
Index: sys/dev/ofw/ofw_console.c
===================================================================
RCS file: /home/ncvs/src/sys/dev/ofw/ofw_console.c,v
retrieving revision 1.34
diff -u -r1.34 ofw_console.c
--- sys/dev/ofw/ofw_console.c	30 May 2006 07:56:57 -0000	1.34
+++ sys/dev/ofw/ofw_console.c	13 Sep 2006 08:56:13 -0000
@@ -140,7 +140,8 @@
 		ttyconsolemode(tp, 0);
 
 		setuptimeout = 1;
-	} else if ((tp->t_state & TS_XCLUDE) && suser(td)) {
+	} else if ((tp->t_state & TS_XCLUDE) &&
+	    priv_check(td, PRIV_TTY_EXCLUSIVE)) {
 		return (EBUSY);
 	}
 
Index: sys/dev/random/randomdev.c
===================================================================
RCS file: /home/ncvs/src/sys/dev/random/randomdev.c,v
retrieving revision 1.60
diff -u -r1.60 randomdev.c
--- sys/dev/random/randomdev.c	20 Dec 2005 21:41:52 -0000	1.60
+++ sys/dev/random/randomdev.c	13 Sep 2006 08:56:13 -0000
@@ -41,6 +41,7 @@
 #include <sys/module.h>
 #include <sys/mutex.h>
 #include <sys/poll.h>
+#include <sys/priv.h>
 #include <sys/proc.h>
 #include <sys/selinfo.h>
 #include <sys/uio.h>
@@ -85,7 +86,7 @@
 random_close(struct cdev *dev __unused, int flags, int fmt __unused,
     struct thread *td)
 {
-	if ((flags & FWRITE) && (suser(td) == 0)
+	if ((flags & FWRITE) && (priv_check(td, PRIV_RANDOM_RESEED) == 0)
 	    && (securelevel_gt(td->td_ucred, 0) == 0)) {
 		(*random_systat.reseed)();
 		random_systat.seeded = 1;
Index: sys/dev/sbni/if_sbni.c
===================================================================
RCS file: /home/ncvs/src/sys/dev/sbni/if_sbni.c,v
retrieving revision 1.22
diff -u -r1.22 if_sbni.c
--- sys/dev/sbni/if_sbni.c	11 Nov 2005 16:04:54 -0000	1.22
+++ sys/dev/sbni/if_sbni.c	13 Sep 2006 08:56:13 -0000
@@ -67,6 +67,7 @@
 #include <sys/sockio.h>
 #include <sys/mbuf.h>
 #include <sys/kernel.h>
+#include <sys/priv.h>
 #include <sys/proc.h>
 #include <sys/callout.h>
 #include <sys/syslog.h>
@@ -1110,7 +1111,7 @@
 
 	case SIOCSHWFLAGS:	/* set flags */
 		/* root only */
-		error = suser(td);
+		error = priv_check(td, PRIV_DRIVER);
 		if (error)
 			break;
 		flags = *(struct sbni_flags*)&ifr->ifr_data;
@@ -1132,7 +1133,7 @@
 		break;
 
 	case SIOCRINSTATS:
-		if (!(error = suser(td)))	/* root only */
+		if (!(error = priv_check(td, PRIV_DRIVER)))	/* root only */
 			bzero(&sc->in_stats, sizeof(struct sbni_in_stats));
 		break;
 
Index: sys/dev/sbsh/if_sbsh.c
===================================================================
RCS file: /home/ncvs/src/sys/dev/sbsh/if_sbsh.c,v
retrieving revision 1.16
diff -u -r1.16 if_sbsh.c
--- sys/dev/sbsh/if_sbsh.c	16 May 2006 14:36:31 -0000	1.16
+++ sys/dev/sbsh/if_sbsh.c	13 Sep 2006 08:56:13 -0000
@@ -34,6 +34,7 @@
 #include <sys/malloc.h>
 #include <sys/kernel.h>
 #include <sys/module.h>
+#include <sys/priv.h>
 #include <sys/proc.h>
 #include <sys/socket.h>
 #include <sys/random.h>
@@ -424,7 +425,7 @@
 
 	switch(cmd) {
 	case SIOCLOADFIRMW:
-		if ((error = suser(curthread)) != 0)
+		if ((error = priv_check(curthread, PRIV_DRIVER)) != 0)
 			break;
 		if (ifp->if_flags & IFF_UP)
 			error = EBUSY;
@@ -444,7 +445,7 @@
 		break;
 
 	case  SIOCGETSTATS :
-		if ((error = suser(curthread)) != 0)
+		if ((error = priv_check(curthread, PRIV_DRIVER)) != 0)
 			break;
 
 		t = 0;
@@ -478,7 +479,7 @@
 		break;
 
 	case  SIOCCLRSTATS :
-		if (!(error = suser(curthread))) {
+		if (!(error = priv_check(curthread, PRIV_DRIVER))) {
 			bzero(&sc->in_stats, sizeof(struct sbni16_stats));
 			t = 2;
 			if (issue_cx28975_cmd(sc, _DSL_CLEAR_ERROR_CTRS, &t, 1))
Index: sys/dev/si/si.c
===================================================================
RCS file: /home/ncvs/src/sys/dev/si/si.c,v
retrieving revision 1.137
diff -u -r1.137 si.c
--- sys/dev/si/si.c	6 Jan 2006 19:56:12 -0000	1.137
+++ sys/dev/si/si.c	13 Sep 2006 08:56:13 -0000
@@ -53,6 +53,7 @@
 #include <sys/fcntl.h>
 #include <sys/kernel.h>
 #include <sys/malloc.h>
+#include <sys/priv.h>
 #include <sys/sysctl.h>
 #include <sys/bus.h>
 #include <machine/bus.h>
@@ -650,7 +651,7 @@
 
 	ip = (int *)data;
 
-#define SUCHECK if ((error = suser(td))) goto out
+#define SUCHECK if ((error = priv_check(td, PRIV_DRIVER))) goto out
 
 	switch (cmd) {
 	case TCSIPORTS:
Index: sys/dev/syscons/syscons.c
===================================================================
RCS file: /home/ncvs/src/sys/dev/syscons/syscons.c,v
retrieving revision 1.445
diff -u -r1.445 syscons.c
--- sys/dev/syscons/syscons.c	26 May 2006 13:52:44 -0000	1.445
+++ sys/dev/syscons/syscons.c	13 Sep 2006 08:56:13 -0000
@@ -49,6 +49,7 @@
 #include <sys/lock.h>
 #include <sys/malloc.h>
 #include <sys/mutex.h>
+#include <sys/priv.h>
 #include <sys/proc.h>
 #include <sys/random.h>
 #include <sys/reboot.h>
@@ -516,7 +517,7 @@
 	ttyld_modem(tp, 1);
     }
     else
-	if (tp->t_state & TS_XCLUDE && suser(td))
+	if (tp->t_state & TS_XCLUDE && priv_check(td, PRIV_TTY_EXCLUSIVE))
 	    return(EBUSY);
 
     error = ttyld_open(tp, dev);
@@ -1066,7 +1067,7 @@
 	return 0;
 
     case KDENABIO:      	/* allow io operations */
-	error = suser(td);
+	error = priv_check(td, PRIV_IO);
 	if (error != 0)
 	    return error;
 	error = securelevel_gt(td->td_ucred, 0);
Index: sys/dev/syscons/sysmouse.c
===================================================================
RCS file: /home/ncvs/src/sys/dev/syscons/sysmouse.c,v
retrieving revision 1.28
diff -u -r1.28 sysmouse.c
--- sys/dev/syscons/sysmouse.c	4 Dec 2005 02:12:42 -0000	1.28
+++ sys/dev/syscons/sysmouse.c	13 Sep 2006 08:56:13 -0000
@@ -33,6 +33,7 @@
 #include <sys/param.h>
 #include <sys/systm.h>
 #include <sys/conf.h>
+#include <sys/priv.h>
 #include <sys/tty.h>
 #include <sys/kernel.h>
 #include <sys/consio.h>
@@ -83,7 +84,8 @@
 		ttyinitmode(tp, 0, 0);
 		smparam(tp, &tp->t_termios);
 		ttyld_modem(tp, 1);
-	} else if (tp->t_state & TS_XCLUDE && suser(td)) {
+	} else if (tp->t_state & TS_XCLUDE &&
+	    priv_check(td, PRIV_TTY_EXCLUSIVE)) {
 		return EBUSY;
 	}
 
Index: sys/dev/wi/if_wi.c
===================================================================
RCS file: /home/ncvs/src/sys/dev/wi/if_wi.c,v
retrieving revision 1.199
diff -u -r1.199 if_wi.c
--- sys/dev/wi/if_wi.c	5 Aug 2006 04:58:25 -0000	1.199
+++ sys/dev/wi/if_wi.c	13 Sep 2006 08:56:13 -0000
@@ -76,6 +76,7 @@
 #endif
 #include <sys/sockio.h>
 #include <sys/mbuf.h>
+#include <sys/priv.h>
 #include <sys/proc.h>
 #include <sys/kernel.h>
 #include <sys/socket.h>
@@ -1273,7 +1274,7 @@
 		WI_UNLOCK(sc);
 		break;
 	case SIOCSIFGENERIC:
-		error = suser(td);
+		error = priv_check(td, PRIV_DRIVER);
 		if (error == 0)
 			error = wi_set_cfg(ifp, cmd, data);
 		break;
@@ -1291,7 +1292,7 @@
 			error = copyout(&wreq, ifr->ifr_data, sizeof(wreq));
 		break;
 	case SIOCSPRISM2DEBUG:
-		if ((error = suser(td)))
+		if ((error = priv_check(td, PRIV_DRIVER)))
 			return (error);
 		error = copyin(ifr->ifr_data, &wreq, sizeof(wreq));
 		if (error)
@@ -1312,7 +1313,7 @@
 	case SIOCS80211:
 		ireq = (struct ieee80211req *) data;
 		if (ireq->i_type == IEEE80211_IOC_STATIONNAME) {
-			error = suser(td);
+			error = priv_check(td, PRIV_NET80211_MANAGE);
 			if (error)
 				break;
 			if (ireq->i_val != 0 ||
Index: sys/dev/wl/if_wl.c
===================================================================
RCS file: /home/ncvs/src/sys/dev/wl/if_wl.c,v
retrieving revision 1.73
diff -u -r1.73 if_wl.c
--- sys/dev/wl/if_wl.c	19 Jun 2006 11:30:36 -0000	1.73
+++ sys/dev/wl/if_wl.c	13 Sep 2006 08:56:13 -0000
@@ -197,6 +197,7 @@
 #include <sys/module.h>
 #include <sys/sockio.h>
 #include <sys/mbuf.h>
+#include <sys/priv.h>
 #include <sys/socket.h>
 #include <sys/syslog.h>
 #include <machine/bus.h>
@@ -1310,7 +1311,7 @@
 	/* pointer to buffer in user space */
 	up = (void *)ifr->ifr_data;
 	/* work out if they're root */
-	isroot = (suser(td) == 0);
+	isroot = (priv_check(td, PRIV_NET80211_GETKEY) == 0);
 	
 	for (i = 0; i < 0x40; i++) {
 	    /* don't hand the DES key out to non-root users */
@@ -1327,7 +1328,7 @@
 	/* copy the PSA in from the caller; we only copy _some_ values */
     case SIOCSWLPSA:
 	/* root only */
-	if ((error = suser(td)))
+	if ((error = priv_check(td, PRIV_DRIVER)))
 	    break;
 	error = EINVAL;	/* assume the worst */
 	/* pointer to buffer in user space containing data */
@@ -1383,7 +1384,7 @@
 	 */
     case SIOCSWLCNWID:
 	/* root only */
-	if ((error = suser(td)))
+	if ((error = priv_check(td, PRIV_DRIVER)))
 	    break;
 	if (!(ifp->if_flags & IFF_UP)) {
 	    error = EIO;	/* only allowed while up */
@@ -1401,7 +1402,7 @@
 	/* copy the EEPROM in 2.4 Gz WaveMODEM  out to the caller */
     case SIOCGWLEEPROM:
 	/* root only */
-	if ((error = suser(td)))
+	if ((error = priv_check(td, PRIV_DRIVER)))
 	    break;
 	/* pointer to buffer in user space */
 	up = (void *)ifr->ifr_data;
@@ -1428,7 +1429,7 @@
 	/* zero (Delete) the wl cache */
     case SIOCDWLCACHE:
 	/* root only */
-	if ((error = suser(td)))
+	if ((error = priv_check(td, PRIV_DRIVER)))
 	    break;
 	wl_cache_zero(sc);
 	break;
Index: sys/dev/zs/zs.c
===================================================================
RCS file: /home/ncvs/src/sys/dev/zs/zs.c,v
retrieving revision 1.35
diff -u -r1.35 zs.c
--- sys/dev/zs/zs.c	26 May 2006 18:25:34 -0000	1.35
+++ sys/dev/zs/zs.c	13 Sep 2006 08:56:13 -0000
@@ -453,7 +453,7 @@
 
 	if ((tp->t_state & TS_ISOPEN) != 0 &&
 	    (tp->t_state & TS_XCLUDE) != 0 &&
-	    suser(td) != 0)
+	    priv_check(td, PRIV_TTY_EXCLUSIVE) != 0)
 		return (EBUSY);
 
 	if ((tp->t_state & TS_ISOPEN) == 0) {
Index: sys/fs/devfs/devfs_rule.c
===================================================================
RCS file: /home/ncvs/src/sys/fs/devfs/devfs_rule.c,v
retrieving revision 1.22
diff -u -r1.22 devfs_rule.c
--- sys/fs/devfs/devfs_rule.c	17 Jul 2006 09:07:01 -0000	1.22
+++ sys/fs/devfs/devfs_rule.c	13 Sep 2006 08:56:13 -0000
@@ -67,6 +67,7 @@
 #include <sys/conf.h>
 #include <sys/kernel.h>
 #include <sys/malloc.h>
+#include <sys/priv.h>
 #include <sys/dirent.h>
 #include <sys/ioccom.h>
 #include <sys/lock.h>
@@ -164,11 +165,13 @@
 	sx_assert(&dm->dm_lock, SX_XLOCKED);
 
 	/*
-	 * XXX: This returns an error regardless of whether we
-	 * actually support the cmd or not.
+	 * XXX: This returns an error regardless of whether we actually
+	 * support the cmd or not.
+	 *
+	 * XXXRW: We could make this privileges finer grained if desired.
 	 */
-	error = suser(td);
-	if (error != 0)
+	error = priv_check(td, PRIV_DEVFS_RULE);
+	if (error)
 		return (error);
 
 	sx_xlock(&sx_rules);
Index: sys/fs/devfs/devfs_vnops.c
===================================================================
RCS file: /home/ncvs/src/sys/fs/devfs/devfs_vnops.c,v
retrieving revision 1.133
diff -u -r1.133 devfs_vnops.c
--- sys/fs/devfs/devfs_vnops.c	17 Jul 2006 09:07:01 -0000	1.133
+++ sys/fs/devfs/devfs_vnops.c	13 Sep 2006 08:56:13 -0000
@@ -56,6 +56,7 @@
 #include <sys/malloc.h>
 #include <sys/mount.h>
 #include <sys/namei.h>
+#include <sys/priv.h>
 #include <sys/proc.h>
 #include <sys/stat.h>
 #include <sys/sx.h>
@@ -1023,19 +1024,25 @@
 	else
 		gid = vap->va_gid;
 	if (uid != de->de_uid || gid != de->de_gid) {
-		if (((ap->a_cred->cr_uid != de->de_uid) || uid != de->de_uid ||
-		    (gid != de->de_gid && !groupmember(gid, ap->a_cred))) &&
-		    (error = suser_cred(ap->a_td->td_ucred, SUSER_ALLOWJAIL)) != 0)
-			return (error);
+		if ((ap->a_cred->cr_uid != de->de_uid) || uid != de->de_uid ||
+		    (gid != de->de_gid && !groupmember(gid, ap->a_cred))) {
+			error = priv_check_cred(ap->a_td->td_ucred,
+			    PRIV_VFS_CHOWN, SUSER_ALLOWJAIL);
+			if (error)
+				return (error);
+		}
 		de->de_uid = uid;
 		de->de_gid = gid;
 		c = 1;
 	}
 
 	if (vap->va_mode != (mode_t)VNOVAL) {
-		if ((ap->a_cred->cr_uid != de->de_uid) &&
-		    (error = suser_cred(ap->a_td->td_ucred, SUSER_ALLOWJAIL)))
-			return (error);
+		if (ap->a_cred->cr_uid != de->de_uid) {
+			error = priv_check_cred(ap->a_td->td_ucred,
+			    PRIV_VFS_ADMIN, SUSER_ALLOWJAIL);
+			if (error)
+				return (error);
+		}
 		de->de_mode = vap->va_mode;
 		c = 1;
 	}
@@ -1105,7 +1112,8 @@
 
 	td = ap->a_cnp->cn_thread;
 	KASSERT(td == curthread, ("devfs_symlink: td != curthread"));
-	error = suser(td);
+
+	error = priv_check(td, PRIV_DEVFS_SYMLINK);
 	if (error)
 		return(error);
 	dmp = VFSTODEVFS(ap->a_dvp->v_mount);
Index: sys/fs/hpfs/hpfs_vnops.c
===================================================================
RCS file: /home/ncvs/src/sys/fs/hpfs/hpfs_vnops.c,v
retrieving revision 1.68
diff -u -r1.68 hpfs_vnops.c
--- sys/fs/hpfs/hpfs_vnops.c	17 Jan 2006 17:29:01 -0000	1.68
+++ sys/fs/hpfs/hpfs_vnops.c	13 Sep 2006 08:56:13 -0000
@@ -501,6 +501,10 @@
 	if (vap->va_atime.tv_sec != VNOVAL || vap->va_mtime.tv_sec != VNOVAL) {
 		if (vp->v_mount->mnt_flag & MNT_RDONLY)
 			return (EROFS);
+		/*
+		 * XXXRW: Why not just rely on the VOP_ACCESS() check here
+		 * instead of calling suser()?
+		 */
 		if (cred->cr_uid != hp->h_uid &&
 		    (error = suser_cred(cred, SUSER_ALLOWJAIL)) &&
 		    ((vap->va_vaflags & VA_UTIMES_NULL) == 0 ||
Index: sys/fs/msdosfs/msdosfs_vfsops.c
===================================================================
RCS file: /home/ncvs/src/sys/fs/msdosfs/msdosfs_vfsops.c,v
retrieving revision 1.152
diff -u -r1.152 msdosfs_vfsops.c
--- sys/fs/msdosfs/msdosfs_vfsops.c	3 Aug 2006 03:55:52 -0000	1.152
+++ sys/fs/msdosfs/msdosfs_vfsops.c	13 Sep 2006 08:56:13 -0000
@@ -52,6 +52,7 @@
 #include <sys/systm.h>
 #include <sys/conf.h>
 #include <sys/namei.h>
+#include <sys/priv.h>
 #include <sys/proc.h>
 #include <sys/kernel.h>
 #include <sys/vnode.h>
@@ -293,17 +294,17 @@
 			 * If upgrade to read-write by non-root, then verify
 			 * that user has necessary permissions on the device.
 			 */
-			if (suser(td)) {
-				devvp = pmp->pm_devvp;
-				vn_lock(devvp, LK_EXCLUSIVE | LK_RETRY, td);
-				error = VOP_ACCESS(devvp, VREAD | VWRITE,
-						   td->td_ucred, td);
-				if (error) {
-					VOP_UNLOCK(devvp, 0, td);
-					return (error);
-				}
+			devvp = pmp->pm_devvp;
+			vn_lock(devvp, LK_EXCLUSIVE | LK_RETRY, td);
+			error = VOP_ACCESS(devvp, VREAD | VWRITE,
+			   td->td_ucred, td);
+			if (error)
+				error = priv_check(td, PRIV_VFS_MOUNT_PERM);
+			if (error) {
 				VOP_UNLOCK(devvp, 0, td);
+				return (error);
 			}
+			VOP_UNLOCK(devvp, 0, td);
 			DROP_GIANT();
 			g_topology_lock();
 			error = g_access(pmp->pm_cp, 0, 1, 0);
@@ -353,15 +354,15 @@
 	 * If mount by non-root, then verify that user has necessary
 	 * permissions on the device.
 	 */
-	if (suser(td)) {
-		accessmode = VREAD;
-		if ((mp->mnt_flag & MNT_RDONLY) == 0)
-			accessmode |= VWRITE;
-		error = VOP_ACCESS(devvp, accessmode, td->td_ucred, td);
-		if (error) {
-			vput(devvp);
-			return (error);
-		}
+	accessmode = VREAD;
+	if ((mp->mnt_flag & MNT_RDONLY) == 0)
+		accessmode |= VWRITE;
+	error = VOP_ACCESS(devvp, accessmode, td->td_ucred, td);
+	if (error)
+		error = priv_check(td, PRIV_VFS_MOUNT_PERM);
+	if (error) {
+		vput(devvp);
+		return (error);
 	}
 	if ((mp->mnt_flag & MNT_UPDATE) == 0) {
 		error = mountmsdosfs(devvp, mp, td);
Index: sys/fs/msdosfs/msdosfs_vnops.c
===================================================================
RCS file: /home/ncvs/src/sys/fs/msdosfs/msdosfs_vnops.c,v
retrieving revision 1.163
diff -u -r1.163 msdosfs_vnops.c
--- sys/fs/msdosfs/msdosfs_vnops.c	1 Feb 2006 00:25:25 -0000	1.163
+++ sys/fs/msdosfs/msdosfs_vnops.c	13 Sep 2006 08:56:13 -0000
@@ -58,6 +58,7 @@
 #include <sys/bio.h>
 #include <sys/conf.h>
 #include <sys/buf.h>
+#include <sys/priv.h>
 #include <sys/proc.h>
 #include <sys/mount.h>
 #include <sys/unistd.h>
@@ -402,9 +403,12 @@
 	if (vap->va_flags != VNOVAL) {
 		if (vp->v_mount->mnt_flag & MNT_RDONLY)
 			return (EROFS);
-		if (cred->cr_uid != pmp->pm_uid &&
-		    (error = suser_cred(cred, SUSER_ALLOWJAIL)))
-			return (error);
+		if (cred->cr_uid != pmp->pm_uid) {
+			error = priv_check_cred(cred, PRIV_VFS_ADMIN,
+			    SUSER_ALLOWJAIL);
+			if (error)
+				return (error);
+		}
 		/*
 		 * We are very inconsistent about handling unsupported
 		 * attributes.  We ignored the access time and the
@@ -417,9 +421,11 @@
 		 * set ATTR_ARCHIVE for directories `cp -pr' from a more
 		 * sensible filesystem attempts it a lot.
 		 */
-		if (suser_cred(cred, SUSER_ALLOWJAIL)) {
-			if (vap->va_flags & SF_SETTABLE)
-				return EPERM;
+		if (vap->va_flags & SF_SETTABLE) {
+			error = priv_check_cred(cred, PRIV_VFS_SYSFLAGS,
+			    SUSER_ALLOWJAIL);
+			if (error)
+				return (error);
 		}
 		if (vap->va_flags & ~SF_ARCHIVED)
 			return EOPNOTSUPP;
@@ -442,10 +448,13 @@
 		gid = vap->va_gid;
 		if (gid == (gid_t)VNOVAL)
 			gid = pmp->pm_gid;
-		if ((cred->cr_uid != pmp->pm_uid || uid != pmp->pm_uid ||
-		    (gid != pmp->pm_gid && !groupmember(gid, cred))) &&
-		    (error = suser_cred(cred, SUSER_ALLOWJAIL)))
-			return error;
+		if (cred->cr_uid != pmp->pm_uid || uid != pmp->pm_uid ||
+		    (gid != pmp->pm_gid && !groupmember(gid, cred))) {
+			error = priv_check_cred(cred, PRIV_VFS_CHOWN,
+			    SUSER_ALLOWJAIL);
+			if (error)
+				return (error);
+		}
 		if (uid != pmp->pm_uid || gid != pmp->pm_gid)
 			return EINVAL;
 	}
@@ -475,6 +484,10 @@
 	if (vap->va_atime.tv_sec != VNOVAL || vap->va_mtime.tv_sec != VNOVAL) {
 		if (vp->v_mount->mnt_flag & MNT_RDONLY)
 			return (EROFS);
+		/*
+		 * XXXRW: Isn't VOP_ACCESS() enough here?  Why is suser()
+		 * required?
+		 */
 		if (cred->cr_uid != pmp->pm_uid &&
 		    (error = suser_cred(cred, SUSER_ALLOWJAIL)) &&
 		    ((vap->va_vaflags & VA_UTIMES_NULL) == 0 ||
@@ -504,9 +517,12 @@
 	if (vap->va_mode != (mode_t)VNOVAL) {
 		if (vp->v_mount->mnt_flag & MNT_RDONLY)
 			return (EROFS);
-		if (cred->cr_uid != pmp->pm_uid &&
-		    (error = suser_cred(cred, SUSER_ALLOWJAIL)))
-			return (error);
+		if (cred->cr_uid != pmp->pm_uid) {
+			error = priv_check_cred(cred, PRIV_VFS_ADMIN,
+			    SUSER_ALLOWJAIL);
+			if (error)
+				return (error);
+		}
 		if (vp->v_type != VDIR) {
 			/* We ignore the read and execute bits. */
 			if (vap->va_mode & VWRITE)
Index: sys/fs/procfs/procfs_ioctl.c
===================================================================
RCS file: /home/ncvs/src/sys/fs/procfs/procfs_ioctl.c,v
retrieving revision 1.12
diff -u -r1.12 procfs_ioctl.c
--- sys/fs/procfs/procfs_ioctl.c	30 Jun 2005 07:49:21 -0000	1.12
+++ sys/fs/procfs/procfs_ioctl.c	13 Sep 2006 08:56:13 -0000
@@ -34,6 +34,7 @@
 #include <sys/lock.h>
 #include <sys/mutex.h>
 #include <sys/pioctl.h>
+#include <sys/priv.h>
 #include <sys/proc.h>
 #include <sys/signalvar.h>
 #include <sys/systm.h>
@@ -86,8 +87,19 @@
 #endif
 	case PIOCSFL:
 		flags = *(uintptr_t *)data;
-		if (flags & PF_ISUGID && (error = suser(td)) != 0)
-			break;
+		if (flags & PF_ISUGID) {
+			/*
+			 * XXXRW: Is this specific check required here, as
+			 * p_candebug() should implement it, or other checks
+			 * are missing.
+			 *
+			 * XXXRW: Other debugging privileges are granted in
+			 * jail, why isn't this?
+			 */
+			error = priv_check(td, PRIV_DEBUG_SUGID);
+			if (error)
+				break;
+		}
 		p->p_pfsflags = flags;
 		break;
 	case PIOCGFL:
Index: sys/fs/smbfs/smbfs_vnops.c
===================================================================
RCS file: /home/ncvs/src/sys/fs/smbfs/smbfs_vnops.c,v
retrieving revision 1.62
diff -u -r1.62 smbfs_vnops.c
--- sys/fs/smbfs/smbfs_vnops.c	31 May 2006 22:31:08 -0000	1.62
+++ sys/fs/smbfs/smbfs_vnops.c	13 Sep 2006 08:56:13 -0000
@@ -352,6 +352,9 @@
 	if (vap->va_atime.tv_sec != VNOVAL)
 		atime = &vap->va_atime;
 	if (mtime != atime) {
+		/*
+		 * XXXRW: Isn't VOP_ACCESS() here sufficient?  Why suser()?
+		 */
 		if (ap->a_cred->cr_uid != VTOSMBFS(vp)->sm_uid &&
 		    (error = suser_cred(ap->a_cred, SUSER_ALLOWJAIL)) &&
 		    ((vap->va_vaflags & VA_UTIMES_NULL) == 0 ||
Index: sys/fs/udf/udf_vfsops.c
===================================================================
RCS file: /home/ncvs/src/sys/fs/udf/udf_vfsops.c,v
retrieving revision 1.43
diff -u -r1.43 udf_vfsops.c
--- sys/fs/udf/udf_vfsops.c	25 Jul 2006 14:15:50 -0000	1.43
+++ sys/fs/udf/udf_vfsops.c	13 Sep 2006 08:56:13 -0000
@@ -84,6 +84,7 @@
 #include <sys/malloc.h>
 #include <sys/mount.h>
 #include <sys/namei.h>
+#include <sys/priv.h>
 #include <sys/proc.h>
 #include <sys/queue.h>
 #include <sys/vnode.h>
@@ -236,7 +237,7 @@
 	/* Check the access rights on the mount device */
 	error = VOP_ACCESS(devvp, VREAD, td->td_ucred, td);
 	if (error)
-		error = suser(td);
+		error = priv_check(td, PRIV_VFS_MOUNT_PERM);
 	if (error) {
 		vput(devvp);
 		return (error);
Index: sys/fs/umapfs/umap_vfsops.c
===================================================================
RCS file: /home/ncvs/src/sys/fs/umapfs/umap_vfsops.c,v
retrieving revision 1.64
diff -u -r1.64 umap_vfsops.c
--- sys/fs/umapfs/umap_vfsops.c	31 Oct 2005 15:41:21 -0000	1.64
+++ sys/fs/umapfs/umap_vfsops.c	13 Sep 2006 08:56:13 -0000
@@ -88,8 +88,9 @@
 	/*
 	 * Only for root
 	 */
-	if ((error = suser(td)) != 0)
-		return (error);
+	error = priv_check(td, PRIV_VFS_MOUNT);
+	if (error)
+		return (ERROR);
 
 #ifdef DEBUG
 	printf("umapfs_mount(mp = %p)\n", (void *)mp);
Index: sys/gnu/fs/ext2fs/ext2_vfsops.c
===================================================================
RCS file: /home/ncvs/src/sys/gnu/fs/ext2fs/ext2_vfsops.c,v
retrieving revision 1.157
diff -u -r1.157 ext2_vfsops.c
--- sys/gnu/fs/ext2fs/ext2_vfsops.c	26 May 2006 00:32:20 -0000	1.157
+++ sys/gnu/fs/ext2fs/ext2_vfsops.c	13 Sep 2006 08:56:13 -0000
@@ -57,6 +57,7 @@
 #include <sys/param.h>
 #include <sys/systm.h>
 #include <sys/namei.h>
+#include <sys/priv.h>
 #include <sys/proc.h>
 #include <sys/kernel.h>
 #include <sys/vnode.h>
@@ -197,15 +198,16 @@
 			 * If upgrade to read-write by non-root, then verify
 			 * that user has necessary permissions on the device.
 			 */
-			if (suser(td)) {
-				vn_lock(devvp, LK_EXCLUSIVE | LK_RETRY, td);
-				if ((error = VOP_ACCESS(devvp, VREAD | VWRITE,
-				    td->td_ucred, td)) != 0) {
-					VOP_UNLOCK(devvp, 0, td);
-					return (error);
-				}
+			vn_lock(devvp, LK_EXCLUSIVE | LK_RETRY, td);
+			error = VOP_ACCESS(devvp, VREAD | VWRITE,
+			    td->td_ucred, td);
+			if (error)
+				error = priv_check(td, PRIV_VFS_MOUNT_PERM);
+			if (error) {
 				VOP_UNLOCK(devvp, 0, td);
+				return (error);
 			}
+			VOP_UNLOCK(devvp, 0, td);
 			DROP_GIANT();
 			g_topology_lock();
 			error = g_access(ump->um_cp, 0, 1, 0);
@@ -257,15 +259,18 @@
 	/*
 	 * If mount by non-root, then verify that user has necessary
 	 * permissions on the device.
+	 *
+	 * XXXRW: VOP_ACCESS() enough?
 	 */
-	if (suser(td)) {
-		accessmode = VREAD;
-		if ((mp->mnt_flag & MNT_RDONLY) == 0)
-			accessmode |= VWRITE;
-		if ((error = VOP_ACCESS(devvp, accessmode, td->td_ucred, td)) != 0) {
-			vput(devvp);
-			return (error);
-		}
+	accessmode = VREAD;
+	if ((mp->mnt_flag & MNT_RDONLY) == 0)
+		accessmode |= VWRITE;
+	error = VOP_ACCESS(devvp, accessmode, td->td_ucred, td);
+	if (error)
+		error = priv_check(td, PRIV_VFS_MOUNT_PERM);
+	if (error) {
+		vput(devvp);
+		return (error);
 	}
 
 	if ((mp->mnt_flag & MNT_UPDATE) == 0) {
Index: sys/gnu/fs/ext2fs/ext2_vnops.c
===================================================================
RCS file: /home/ncvs/src/sys/gnu/fs/ext2fs/ext2_vnops.c,v
retrieving revision 1.105
diff -u -r1.105 ext2_vnops.c
--- sys/gnu/fs/ext2fs/ext2_vnops.c	29 Dec 2005 21:34:49 -0000	1.105
+++ sys/gnu/fs/ext2fs/ext2_vnops.c	13 Sep 2006 08:56:13 -0000
@@ -52,6 +52,7 @@
 #include <sys/stat.h>
 #include <sys/bio.h>
 #include <sys/buf.h>
+#include <sys/priv.h>
 #include <sys/proc.h>
 #include <sys/mount.h>
 #include <sys/unistd.h>
@@ -411,7 +412,8 @@
 		 * Privileged non-jail processes may not modify system flags
 		 * if securelevel > 0 and any existing system flags are set.
 		 */
-		if (!suser_cred(cred, SUSER_ALLOWJAIL)) {
+		if (!priv_check_cred(cred, PRIV_VFS_SYSFLAGS,
+		    SUSER_ALLOWJAIL)) {
 			if (ip->i_flags
 			    & (SF_NOUNLINK | SF_IMMUTABLE | SF_APPEND)) {
 				error = securelevel_gt(cred, 0);
@@ -529,11 +531,17 @@
 	 * as well as set the setgid bit on a file with a group that the
 	 * process is not a member of.
 	 */
-	if (suser_cred(cred, SUSER_ALLOWJAIL)) {
-		if (vp->v_type != VDIR && (mode & S_ISTXT))
+	if (vp->v_type != VDIR && (mode & S_ISTXT)) {
+		error = priv_check_cred(cred, PRIV_VFS_STICKYFILE,
+		    SUSER_ALLOWJAIL);
+		if (error)
 			return (EFTYPE);
-		if (!groupmember(ip->i_gid, cred) && (mode & ISGID))
-			return (EPERM);
+	}
+	if (!groupmember(ip->i_gid, cred) && (mode & ISGID)) {
+		error = priv_check_cred(cred, PRIV_VFS_SETGID,
+		    SUSER_ALLOWJAIL);
+		if (error)
+			return (error);
 	}
 	ip->i_mode &= ~ALLPERMS;
 	ip->i_mode |= (mode & ALLPERMS);
@@ -573,17 +581,23 @@
 	 * to a group of which we are not a member, the caller must
 	 * have privilege.
 	 */
-	if ((uid != ip->i_uid || 
-	    (gid != ip->i_gid && !groupmember(gid, cred))) &&
-	    (error = suser_cred(cred, SUSER_ALLOWJAIL)))
-		return (error);
+	if (uid != ip->i_uid || (gid != ip->i_gid &&
+	    !groupmember(gid, cred))) {
+		error = priv_check_cred(cred, PRIV_VFS_CHOWN,
+		    SUSER_ALLOWJAIL);
+		if (error)
+			return (error);
+	}
 	ogid = ip->i_gid;
 	ouid = ip->i_uid;
 	ip->i_gid = gid;
 	ip->i_uid = uid;
 	ip->i_flag |= IN_CHANGE;
-	if (suser_cred(cred, SUSER_ALLOWJAIL) && (ouid != uid || ogid != gid))
-		ip->i_mode &= ~(ISUID | ISGID);
+	if (ouid != uid || ogid != gid) {
+		if (priv_check_cred(cred, PRIV_VFS_CLEARSUGID,
+		    SUSER_ALLOWJAIL) != 0)
+			ip->i_mode &= ~(ISUID | ISGID);
+	}
 	return (0);
 }
 
@@ -1608,9 +1622,11 @@
 	ip->i_mode = mode;
 	tvp->v_type = IFTOVT(mode);	/* Rest init'd in getnewvnode(). */
 	ip->i_nlink = 1;
-	if ((ip->i_mode & ISGID) && !groupmember(ip->i_gid, cnp->cn_cred) &&
-	    suser_cred(cnp->cn_cred, SUSER_ALLOWJAIL))
-		ip->i_mode &= ~ISGID;
+	if ((ip->i_mode & ISGID) && !groupmember(ip->i_gid, cnp->cn_cred)) {
+		if (priv_check_cred(cnp->cn_cred, PRIV_VFS_CLEARSUGID,
+		    SUSER_ALLOWJAIL))
+			ip->i_mode &= ~ISGID;
+	}
 
 	if (cnp->cn_flags & ISWHITEOUT)
 		ip->i_flags |= UF_OPAQUE;
Index: sys/gnu/fs/reiserfs/reiserfs_fs.h
===================================================================
RCS file: /home/ncvs/src/sys/gnu/fs/reiserfs/reiserfs_fs.h,v
retrieving revision 1.4
diff -u -r1.4 reiserfs_fs.h
--- sys/gnu/fs/reiserfs/reiserfs_fs.h	4 Dec 2005 09:57:09 -0000	1.4
+++ sys/gnu/fs/reiserfs/reiserfs_fs.h	13 Sep 2006 08:56:13 -0000
@@ -18,6 +18,7 @@
 #include <sys/kernel.h>
 #include <sys/mount.h>
 #include <sys/namei.h>
+#include <sys/priv.h>
 #include <sys/proc.h>
 #include <sys/vnode.h>
 #include <sys/unistd.h>
Index: sys/gnu/fs/reiserfs/reiserfs_vfsops.c
===================================================================
RCS file: /home/ncvs/src/sys/gnu/fs/reiserfs/reiserfs_vfsops.c,v
retrieving revision 1.5
diff -u -r1.5 reiserfs_vfsops.c
--- sys/gnu/fs/reiserfs/reiserfs_vfsops.c	26 May 2006 11:58:30 -0000	1.5
+++ sys/gnu/fs/reiserfs/reiserfs_vfsops.c	13 Sep 2006 08:56:13 -0000
@@ -125,15 +125,15 @@
 
 	/* If mount by non-root, then verify that user has necessary
 	 * permissions on the device. */
-	if (suser(td)) {
-		accessmode = VREAD;
-		if ((mp->mnt_flag & MNT_RDONLY) == 0)
-			accessmode |= VWRITE;
-		if ((error = VOP_ACCESS(devvp,
-		    accessmode, td->td_ucred, td)) != 0) {
-			vput(devvp);
-			return (error);
-		}
+	accessmode = VREAD;
+	if ((mp->mnt_flag & MNT_RDONLY) == 0)
+		accessmode |= VWRITE;
+	error = VOP_ACCESS(devvp, accessmode, td->td_ucred, td);
+	if (error)
+		error = priv_check(td, PRIV_VFS_MOUNT_PERM);
+	if (error) {
+		vput(devvp);
+		return (error);
 	}
 
 	if ((mp->mnt_flag & MNT_UPDATE) == 0) {
Index: sys/gnu/fs/xfs/FreeBSD/xfs_super.c
===================================================================
RCS file: /home/ncvs/src/sys/gnu/fs/xfs/FreeBSD/xfs_super.c,v
retrieving revision 1.4
diff -u -r1.4 xfs_super.c
--- sys/gnu/fs/xfs/FreeBSD/xfs_super.c	10 Jun 2006 19:02:13 -0000	1.4
+++ sys/gnu/fs/xfs/FreeBSD/xfs_super.c	13 Sep 2006 08:56:13 -0000
@@ -53,6 +53,8 @@
 #include "xfs_version.h"
 #include "xfs_buf.h"
 
+#include <sys/priv.h>
+
 #include <geom/geom.h>
 #include <geom/geom_vfs.h>
 
@@ -149,14 +151,15 @@
 	vn_lock(devvp, LK_EXCLUSIVE | LK_RETRY, td);
 
 	ronly = ((XFS_MTOVFS(mp)->vfs_flag & VFS_RDONLY) != 0);
-	if (suser(td)) {
-		accessmode = VREAD;
-		if (!ronly)
-			accessmode |= VWRITE;
-		if ((error = VOP_ACCESS(devvp, accessmode, td->td_ucred, td))!= 0){
-			vput(devvp);
-			return (error);
-		}
+	accessmode = VREAD;
+	if (!ronly)
+		accessmode |= VWRITE;
+	error = VOP_ACCESS(devvp, accessmode, td->td_ucred, td);
+	if (error)
+		error = priv_check(td, PRIV_VFS_MOUNT_PERM);
+	if (error) {
+		vput(devvp);
+		return (error);
 	}
 
 	DROP_GIANT();
Index: sys/i386/i386/io.c
===================================================================
RCS file: /home/ncvs/src/sys/i386/i386/io.c,v
retrieving revision 1.1
diff -u -r1.1 io.c
--- sys/i386/i386/io.c	1 Aug 2004 11:40:52 -0000	1.1
+++ sys/i386/i386/io.c	13 Sep 2006 08:56:13 -0000
@@ -33,6 +33,7 @@
 #include <sys/lock.h>
 #include <sys/malloc.h>
 #include <sys/mutex.h>
+#include <sys/priv.h>
 #include <sys/proc.h>
 #include <sys/signalvar.h>
 #include <sys/systm.h>
@@ -54,7 +55,7 @@
 {
 	int error;
 
-	error = suser(td);
+	error = priv_check(td, PRIV_IO);
 	if (error != 0)
 		return (error);
 	error = securelevel_gt(td->td_ucred, 0);
Index: sys/i386/i386/sys_machdep.c
===================================================================
RCS file: /home/ncvs/src/sys/i386/i386/sys_machdep.c,v
retrieving revision 1.105
diff -u -r1.105 sys_machdep.c
--- sys/i386/i386/sys_machdep.c	9 Sep 2006 10:20:31 -0000	1.105
+++ sys/i386/i386/sys_machdep.c	13 Sep 2006 08:56:13 -0000
@@ -41,6 +41,7 @@
 #include <sys/mac.h>
 #include <sys/malloc.h>
 #include <sys/mutex.h>
+#include <sys/priv.h>
 #include <sys/proc.h>
 #include <sys/smp.h>
 #include <sys/sysproto.h>
@@ -292,7 +293,7 @@
 	if ((error = mac_check_sysarch_ioperm(td->td_ucred)) != 0)
 		return (error);
 #endif
-	if ((error = suser(td)) != 0)
+	if ((error = priv_check(td, PRIV_IO)) != 0)
 		return (error);
 	if ((error = securelevel_gt(td->td_ucred, 0)) != 0)
 		return (error);
Index: sys/i386/i386/vm86.c
===================================================================
RCS file: /home/ncvs/src/sys/i386/i386/vm86.c,v
retrieving revision 1.59
diff -u -r1.59 vm86.c
--- sys/i386/i386/vm86.c	28 Sep 2005 07:03:03 -0000	1.59
+++ sys/i386/i386/vm86.c	13 Sep 2006 08:56:13 -0000
@@ -29,6 +29,7 @@
 
 #include <sys/param.h>
 #include <sys/systm.h>
+#include <sys/priv.h>
 #include <sys/proc.h>
 #include <sys/lock.h>
 #include <sys/malloc.h>
@@ -724,7 +725,7 @@
 	case VM86_INTCALL: {
 		struct vm86_intcall_args sa;
 
-		if ((error = suser(td)))
+		if ((error = priv_check(td, PRIV_VM86_INTCALL)))
 			return (error);
 		if ((error = copyin(ua.sub_args, &sa, sizeof(sa))))
 			return (error);
Index: sys/i386/ibcs2/ibcs2_misc.c
===================================================================
RCS file: /home/ncvs/src/sys/i386/ibcs2/ibcs2_misc.c,v
retrieving revision 1.64
diff -u -r1.64 ibcs2_misc.c
--- sys/i386/ibcs2/ibcs2_misc.c	11 Jul 2006 20:52:08 -0000	1.64
+++ sys/i386/ibcs2/ibcs2_misc.c	13 Sep 2006 08:56:14 -0000
@@ -69,6 +69,7 @@
 #include <sys/malloc.h>
 #include <sys/file.h>			/* Must come after sys/malloc.h */
 #include <sys/mutex.h>
+#include <sys/priv.h>
 #include <sys/reboot.h>
 #include <sys/resourcevar.h>
 #include <sys/stat.h>
@@ -1007,14 +1008,22 @@
 #define IBCS2_DATALOCK	4
 
 	
-        if ((error = suser(td)) != 0)
-                return EPERM;
 	switch(uap->cmd) {
 	case IBCS2_UNLOCK:
+        	error = priv_check(td, PRIV_VM_MUNLOCK);
+		if (error)
+			return (error);
+		/* XXX - TODO */
+		return (0);
+
 	case IBCS2_PROCLOCK:
 	case IBCS2_TEXTLOCK:
 	case IBCS2_DATALOCK:
-		return 0;	/* XXX - TODO */
+        	error = priv_check(td, PRIV_VM_MLOCK);
+		if (error)
+			return (error);
+		/* XXX - TODO */
+		return 0;
 	}
 	return EINVAL;
 }
@@ -1042,9 +1051,6 @@
 #define SCO_AD_GETBMAJ      0
 #define SCO_AD_GETCMAJ      1
 
-        if (suser(td))
-                return EPERM;
-
 	switch(uap->cmd) {
 	case SCO_A_REBOOT:
 	case SCO_A_SHUTDOWN:
@@ -1054,11 +1060,11 @@
 		case SCO_AD_PWRDOWN:
 		case SCO_AD_PWRNAP:
 			r.opt = RB_HALT;
-			reboot(td, &r);
+			return (reboot(td, &r));
 		case SCO_AD_BOOT:
 		case SCO_AD_IBOOT:
 			r.opt = RB_AUTOBOOT;
-			reboot(td, &r);
+			return (reboot(td, &r));
 		}
 		return EINVAL;
 	case SCO_A_REMOUNT:
Index: sys/i386/ibcs2/ibcs2_socksys.c
===================================================================
RCS file: /home/ncvs/src/sys/i386/ibcs2/ibcs2_socksys.c,v
retrieving revision 1.21
diff -u -r1.21 ibcs2_socksys.c
--- sys/i386/ibcs2/ibcs2_socksys.c	6 Jan 2005 23:22:04 -0000	1.21
+++ sys/i386/ibcs2/ibcs2_socksys.c	13 Sep 2006 08:56:14 -0000
@@ -174,9 +174,6 @@
 	char hname[MAXHOSTNAMELEN], *ptr;
 	int error, sctl[2], hlen;
 
-	if ((error = suser(td)))
-		return (error);
-
 	/* W/out a hostname a domain-name is nonsense */
 	if ( strlen(hostname) == 0 )
 		return EINVAL;
Index: sys/i386/ibcs2/ibcs2_sysi86.c
===================================================================
RCS file: /home/ncvs/src/sys/i386/ibcs2/ibcs2_sysi86.c,v
retrieving revision 1.22
diff -u -r1.22 ibcs2_sysi86.c
--- sys/i386/ibcs2/ibcs2_sysi86.c	7 Jul 2005 19:30:30 -0000	1.22
+++ sys/i386/ibcs2/ibcs2_sysi86.c	13 Sep 2006 08:56:14 -0000
@@ -76,8 +76,6 @@
 	        int name[2];
 	        int error;
 
-		if ((error = suser(td)))
-		  return (error);
 		name[0] = CTL_KERN;
 		name[1] = KERN_HOSTNAME;
 		mtx_lock(&Giant);
Index: sys/i386/linux/linux_machdep.c
===================================================================
RCS file: /home/ncvs/src/sys/i386/linux/linux_machdep.c,v
retrieving revision 1.55
diff -u -r1.55 linux_machdep.c
--- sys/i386/linux/linux_machdep.c	27 Aug 2006 18:51:32 -0000	1.55
+++ sys/i386/linux/linux_machdep.c	13 Sep 2006 08:56:14 -0000
@@ -37,6 +37,7 @@
 #include <sys/mman.h>
 #include <sys/mutex.h>
 #include <sys/sx.h>
+#include <sys/priv.h>
 #include <sys/proc.h>
 #include <sys/queue.h>
 #include <sys/resource.h>
@@ -756,7 +757,7 @@
 
 	if (args->level < 0 || args->level > 3)
 		return (EINVAL);
-	if ((error = suser(td)) != 0)
+	if ((error = priv_check(td, PRIV_IO)) != 0)
 		return (error);
 	if ((error = securelevel_gt(td->td_ucred, 0)) != 0)
 		return (error);
Index: sys/i4b/driver/i4b_ipr.c
===================================================================
RCS file: /home/ncvs/src/sys/i4b/driver/i4b_ipr.c,v
retrieving revision 1.35
diff -u -r1.35 i4b_ipr.c
--- sys/i4b/driver/i4b_ipr.c	9 Aug 2005 10:19:57 -0000	1.35
+++ sys/i4b/driver/i4b_ipr.c	13 Sep 2006 08:56:14 -0000
@@ -490,7 +490,7 @@
 			{
 			struct thread *td = curthread;	/* XXX */
 
-			if((error = suser(td)))
+			if((error = priv_check(td, PRIV_DRIVER)))
 				return (error);
 		        sl_compress_setup(sc->sc_compr, *(int *)data);
 			}
Index: sys/ia64/ia64/ssc.c
===================================================================
RCS file: /home/ncvs/src/sys/ia64/ia64/ssc.c,v
retrieving revision 1.28
diff -u -r1.28 ssc.c
--- sys/ia64/ia64/ssc.c	27 May 2006 17:52:08 -0000	1.28
+++ sys/ia64/ia64/ssc.c	13 Sep 2006 08:56:14 -0000
@@ -147,7 +147,8 @@
 		ttyconsolemode(tp, 0);
 
 		setuptimeout = 1;
-	} else if ((tp->t_state & TS_XCLUDE) && suser(td)) {
+	} else if ((tp->t_state & TS_XCLUDE) &&
+	    priv_check(td, PRIV_TTY_EXCLUSIVE)) {
 		splx(s);
 		return EBUSY;
 	}
Index: sys/isofs/cd9660/cd9660_vfsops.c
===================================================================
RCS file: /home/ncvs/src/sys/isofs/cd9660/cd9660_vfsops.c,v
retrieving revision 1.145
diff -u -r1.145 cd9660_vfsops.c
--- sys/isofs/cd9660/cd9660_vfsops.c	26 May 2006 00:32:20 -0000	1.145
+++ sys/isofs/cd9660/cd9660_vfsops.c	13 Sep 2006 08:56:14 -0000
@@ -40,6 +40,7 @@
 #include <sys/param.h>
 #include <sys/systm.h>
 #include <sys/namei.h>
+#include <sys/priv.h>
 #include <sys/proc.h>
 #include <sys/kernel.h>
 #include <sys/vnode.h>
@@ -172,7 +173,7 @@
 	vn_lock(devvp, LK_EXCLUSIVE | LK_RETRY, td);
 	error = VOP_ACCESS(devvp, accessmode, td->td_ucred, td);
 	if (error)
-		error = suser(td);
+		error = priv_check(td, PRIV_VFS_MOUNT_PERM);
 	if (error) {
 		vput(devvp);
 		return (error);
Index: sys/kern/kern_acct.c
===================================================================
RCS file: /home/ncvs/src/sys/kern/kern_acct.c,v
retrieving revision 1.82
diff -u -r1.82 kern_acct.c
--- sys/kern/kern_acct.c	5 Jun 2006 13:02:34 -0000	1.82
+++ sys/kern/kern_acct.c	13 Sep 2006 08:56:14 -0000
@@ -57,6 +57,7 @@
 #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>
@@ -94,6 +95,7 @@
  * acct_sx protects against changes to the active vnode and credentials
  * while accounting records are being committed to disk.
  */
+static int		 acct_configured;
 static int		 acct_suspended;
 static struct vnode	*acct_vp;
 static struct ucred	*acct_cred;
@@ -146,6 +148,9 @@
     &acctchkfreq, 0, sysctl_acct_chkfreq, "I",
     "frequency for checking the free space");
 
+SYSCTL_INT(_kern, OID_AUTO, acct_configured, CTLFLAG_RD, &acct_configured, 0,
+	"Accounting configured or not");
+
 SYSCTL_INT(_kern, OID_AUTO, acct_suspended, CTLFLAG_RD, &acct_suspended, 0,
 	"Accounting suspended or not");
 
@@ -161,8 +166,7 @@
 	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);
 
@@ -252,6 +256,7 @@
 			(void) vn_close(acct_vp, acct_flags, acct_cred, td);
 			VFS_UNLOCK_GIANT(vfslocked);
 			crfree(acct_cred);
+			acct_configured = 0;
 			acct_vp = NULL;
 			acct_cred = NULL;
 			acct_flags = 0;
@@ -260,6 +265,7 @@
 			return (error);
 		}
 	}
+	acct_configured = 1;
 	sx_xunlock(&acct_sx);
 	log(LOG_NOTICE, "Accounting enabled\n");
 	return (error);
@@ -277,6 +283,7 @@
 	sx_assert(&acct_sx, SX_XLOCKED);
 	error = vn_close(acct_vp, acct_flags, acct_cred, td);
 	crfree(acct_cred);
+	acct_configured = 0;
 	acct_vp = NULL;
 	acct_cred = NULL;
 	acct_flags = 0;
Index: sys/kern/kern_descrip.c
===================================================================
RCS file: /home/ncvs/src/sys/kern/kern_descrip.c,v
retrieving revision 1.297
diff -u -r1.297 kern_descrip.c
--- sys/kern/kern_descrip.c	21 Jul 2006 20:24:00 -0000	1.297
+++ sys/kern/kern_descrip.c	13 Sep 2006 08:56:14 -0000
@@ -57,6 +57,7 @@
 #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,8 +1352,8 @@
 	sx_xlock(&filelist_lock);
 
 	if ((openfiles >= maxuserfiles &&
-	     suser_cred(td->td_ucred, SUSER_RUID) != 0) ||
-	    openfiles >= maxfiles) {
+	     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",
 				td->td_ucred->cr_ruid);
Index: sys/kern/kern_environment.c
===================================================================
RCS file: /home/ncvs/src/sys/kern/kern_environment.c,v
retrieving revision 1.44
diff -u -r1.44 kern_environment.c
--- sys/kern/kern_environment.c	9 Jul 2006 21:42:58 -0000	1.44
+++ sys/kern/kern_environment.c	13 Sep 2006 08:56:14 -0000
@@ -47,6 +47,7 @@
 #include <sys/mac.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>
@@ -124,11 +125,18 @@
 		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);
Index: sys/kern/kern_exec.c
===================================================================
RCS file: /home/ncvs/src/sys/kern/kern_exec.c,v
retrieving revision 1.295
diff -u -r1.295 kern_exec.c
--- sys/kern/kern_exec.c	1 Sep 2006 11:45:39 -0000	1.295
+++ sys/kern/kern_exec.c	13 Sep 2006 08:56:14 -0000
@@ -49,6 +49,7 @@
 #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,14 @@
 		 * we do not regain any tracing during a possible block.
 		 */
 		setsugid(p);
+
+		/*
+		 * XXXRW: Make sure that this priv is the right one.
+		 */
 #ifdef KTRACE
-		if (p->p_tracevp != NULL && suser_cred(oldcred, SUSER_ALLOWJAIL)) {
+		if (p->p_tracevp != NULL &&
+		    priv_check_cred(oldcred, PRIV_DEBUG_SUGID,
+		    SUSER_ALLOWJAIL)) {
 			mtx_lock(&ktrace_mtx);
 			p->p_traceflag = 0;
 			tracevp = p->p_tracevp;
Index: sys/kern/kern_fork.c
===================================================================
RCS file: /home/ncvs/src/sys/kern/kern_fork.c,v
retrieving revision 1.261
diff -u -r1.261 kern_fork.c
--- sys/kern/kern_fork.c	15 Aug 2006 12:10:57 -0000	1.261
+++ sys/kern/kern_fork.c	13 Sep 2006 08:56:14 -0000
@@ -51,6 +51,7 @@
 #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>
@@ -308,7 +309,7 @@
 	 */
 	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;
@@ -317,8 +318,11 @@
 	/*
 	 * 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 {
Index: sys/kern/kern_jail.c
===================================================================
RCS file: /home/ncvs/src/sys/kern/kern_jail.c,v
retrieving revision 1.51
diff -u -r1.51 kern_jail.c
--- sys/kern/kern_jail.c	28 Sep 2005 00:30:56 -0000	1.51
+++ sys/kern/kern_jail.c	13 Sep 2006 08:56:14 -0000
@@ -20,6 +20,7 @@
 #include <sys/sysproto.h>
 #include <sys/mac.h>
 #include <sys/malloc.h>
+#include <sys/priv.h>
 #include <sys/proc.h>
 #include <sys/taskqueue.h>
 #include <sys/jail.h>
@@ -37,7 +38,6 @@
 
 MALLOC_DEFINE(M_PRISON, "prison", "Prison structures");
 
-SYSCTL_DECL(_security);
 SYSCTL_NODE(_security, OID_AUTO, jail, CTLFLAG_RW, 0,
     "Jail rules");
 
@@ -205,7 +205,7 @@
 	 * a process root from one prison, but attached to the jail
 	 * of another.
 	 */
-	error = suser(td);
+	error = priv_check(td, PRIV_JAIL_ATTACH);
 	if (error)
 		return (error);
 
@@ -523,6 +523,210 @@
 	}
 }
 
+/*
+ * Check with permission for a specific privilege is granted within jail.  We
+ * have a specific list of accepted privileges; the rest are denied.
+ */
+int
+prison_priv_check(struct ucred *cred, enum priv priv)
+{
+
+	if (!(jailed(cred)))
+		return (0);
+
+	switch (priv) {
+	/* case PRIV_ROOT: */
+	/* case PRIV_ACCT: */
+	/* case PRIV_MAXFILES: */
+	/* case PRIV_MAXPROC: */
+	case PRIV_KTRACE:
+	/* case PRIV_SETDUMPER: */
+	/* case PRIV_NFSD: */
+	/* case PRIV_REBOOT: */
+	/* case PRIV_SWAPON: */
+	/* case PRIV_SWAPOFF: */
+	/* case PRIV_MSGBUF: */
+	/* case PRIV_WITNESS: */
+	/* case PRIV_IO: */
+	/* case PRIV_KEYBOARD: */
+	/* case PRIV_DRIVER: */
+	/* case PRIV_ADJTIME: */
+	/* case PRIV_NTP_ADJTIME: */
+	/* case PRIV_CLOCK_SETTIME: */
+	/* case PRIV_SETTIMEOFDAY: */
+	/* case PRIV_SETHOSTID: */
+	/* case PRIV_SETDOMAINNAME: */
+	/* case PRIV_AUDIT_CONTROL: */
+	/* case PRIV_AUDIT_FAILSTOP: */
+	case PRIV_AUDIT_GETAUDIT:
+	case PRIV_AUDIT_SETAUDIT:
+	case PRIV_AUDIT_SUBMIT:
+	case PRIV_CRED_SETUID:
+	case PRIV_CRED_SETEUID:
+	case PRIV_CRED_SETGID:
+	case PRIV_CRED_SETEGID:
+	case PRIV_CRED_SETGROUPS:
+	case PRIV_CRED_SETREUID:
+	case PRIV_CRED_SETREGID:
+	case PRIV_CRED_SETRESUID:
+	case PRIV_CRED_SETRESGID:
+	case PRIV_SEEOTHERGIDS:
+	case PRIV_SEEOTHERUIDS:
+	case PRIV_DEBUG_DIFFCRED:
+	case PRIV_DEBUG_SUGID:
+	case PRIV_DEBUG_UNPRIV:
+	/* case PRIV_FIRMWARE_LOAD: */
+	/* case PRIV_JAIL_ATTACH: */
+	/* case PRIV_KENV_SET: */
+	/* case PRIV_KENV_UNSET: */
+	/* case PRIV_KLD_LOAD: */
+	/* case PRIV_KLD_UNLOAD: */
+	/* case PRIV_MAC_PARTITION: */
+	case PRIV_PROC_LIMIT:
+	case PRIV_PROC_SETLOGIN:
+	case PRIV_PROC_SETRLIMIT:
+
+	/* XXXRW: Not yet. */
+	/* case PRIV_IPC_READ: */
+	/* case PRIV_IPC_WRITE: */
+	/* case PRIV_IPC_EXEC: */
+	/* case PRIV_IPC_ADMIN: */
+	/* case PRIV_IPC_MSGSIZE: */
+	/* case PRIV_MQ_ADMIN: */
+	/* case PRIV_PMC_MANAGE: */
+	/* case PRIV_PMC_SYSTEM: */
+	case PRIV_SCHED_DIFFCRED:
+	/* case PRIV_SCHED_SETPRIORITY: */
+	/* case PRIV_SCHED_RTPRIO: */
+	/* case PRIV_SCHED_SETPOLICY: */
+	/* case PRIV_SCHED_SET: */
+	/* case PRIV_SCHED_SETPARAM: */
+	/* case PRIV_SEM_WRITE: */
+	case PRIV_SIGNAL_DIFFCRED:
+	case PRIV_SIGNAL_SUGID:
+	/* case PRIV_SYSCTL_DEBUG: */
+	/* case PRIV_SYSCTL_WRITE: */
+	case PRIV_SYSCTL_WRITEJAIL:
+	/* case PRIV_TTY_CONSOLE: */
+	/* case PRIV_TTY_DRAINWAIT: */
+	/* case PRIV_TTY_DTRWAIT: */
+	/* case PRIV_TTY_EXCLUSIVE: */
+	/* case PRIV_TTY_PRISON: */
+	/* case PRIV_TTY_STI: */
+	/* case PRIV_TTY_SETA: */
+	/* case PRIV_UFS_EXTATTRCTL: */
+	case PRIV_UFS_GETQUOTA:
+	case PRIV_UFS_QUOTAOFF:		/* XXXRW: Slightly surprising. */
+	case PRIV_UFS_QUOTAON:		/* XXXRW: Slightly surprising. */
+	case PRIV_UFS_SETQUOTA:
+	case PRIV_UFS_SETUSE:		/* XXXRW: Slightly surprising. */
+	/* case PRIV_UFS_EXCEEDQUOTA: */
+	case PRIV_VFS_READ:
+	case PRIV_VFS_WRITE:
+	case PRIV_VFS_ADMIN:
+	case PRIV_VFS_EXEC:
+	case PRIV_VFS_LOOKUP:
+	case PRIV_VFS_BLOCKRESERVE:	/* XXXRW: Slightly surprising. */
+	case PRIV_VFS_CHFLAGS_DEV:
+	case PRIV_VFS_CHOWN:
+	case PRIV_VFS_CHROOT:
+	case PRIV_VFS_CLEARSUGID:
+	/* case PRIV_VFS_EXTATTR_SYSTEM: */
+	case PRIV_VFS_FCHROOT:
+	/* case PRIV_VFS_FHOPEN: */
+	/* case PRIV_VFS_FHSTAT: */
+	/* case PRIV_VFS_FHSTATFS: */
+	/* case PRIV_VFS_GENERATION: */
+	/* case PRIV_VFS_GETFH: */
+	case PRIV_VFS_LINK:
+	/* case PRIV_VFS_MKNOD_DEV: */
+	/* case PRIV_VFS_MOUNT: */
+	/* case PRIV_VFS_MOUNT_OWNER: */
+	/* case PRIV_VFS_MOUNT_EXPORTED: */
+	/* case PRIV_VFS_MOUNT_PERM: */
+	/* case PRIV_VFS_MOUNT_SUIDDIR: */
+	case PRIV_VFS_SETGID:
+	case PRIV_VFS_STICKYFILE:
+		return (0);
+
+	case PRIV_VFS_SYSFLAGS:
+		if (jail_chflags_allowed)
+			return (0);
+		else
+			return (EPERM);
+
+	/* case PRIV_VFS_UNMOUNT: */
+	/* case PRIV_VM_MADV_PROTECT: */
+	/* case PRIV_VM_MLOCK: */
+	/* case PRIV_VM_MUNLOCK: */
+	/* case PRIV_DEVFS_RULE: */
+	/* case PRIV_DEVFS_SYMLINK: */
+	/* case PRIV_RANDOM_RESEED: */
+	/* case PRIV_NET_BRIDGE: */
+	/* case PRIV_NET_GRE: */
+	/* case PRIV_NET_PPP: */
+	/* case PRIV_NET_SLIP: */
+	/* case PRIV_NET_BPF: */
+	/* case PRIV_NET_RAW: */
+	/* case PRIV_NET_ROUTE: */
+	/* case PRIV_NET_TAP: */
+	/* case PRIV_NET_SETIFMTU: */
+	/* case PRIV_NET_SETIFFLAGS: */
+	/* case PRIV_NET_SETIFCAP: */
+	/* case PRIV_NET_SETIFNAME: */
+	/* case PRIV_NET_SETIFMETRIC: */
+	/* case PRIV_NET_SETIFPHYS: */
+	/* case PRIV_NET_SETIFMAC: */
+	/* case PRIV_NET_ADDMULTI: */
+	/* case PRIV_NET_DELMULTI: */
+	/* case PRIV_NET_HWIOCTL: */
+	/* case PRIV_NET_SETLLADDR: */
+	/* case PRIV_NET_ADDIFGROUP: */
+	/* case PRIV_NET_DELIFGROUP: */
+	/* case PRIV_NET_IFCREATE: */
+	/* case PRIV_NET_IFDESTROY: */
+	/* case PRIV_NET80211_GETKEY: */
+	/* case PRIV_NET80211_MANAGE: */
+	/* case PRIV_NETATALK_RESERVEDPORT: */
+	/* case PRIV_NETATM_CFG: */
+	/* case PRIV_NETATM_ADD: */
+	/* case PRIV_NETATM_DEL: */
+	/* case PRIV_NETATM_SET: */
+	/* case PRIV_NETGRAPH_CONTROL: */
+	/* case PRIV_NETGRAPH_TTY: */
+	case PRIV_NETINET_RESERVEDPORT:
+		return (0);
+	/* case PRIV_NETINET_IPFW: */
+	/* case PRIV_NETINET_DIVERT: */
+	/* case PRIV_NETINET_PF: */
+	/* case PRIV_NETINET_DUMMYNET: */
+	/* case PRIV_NETINET_CARP: */
+	/* case PRIV_NETINET_MROUTE: */
+	case PRIV_NETINET_RAW:
+		if (jail_allow_raw_sockets)
+			return (0);
+		else
+			return (EPERM);
+	case PRIV_NETINET_GETCRED:
+	/* case PRIV_NETINET_ADDRCTRL6: */
+	/* case PRIV_NETINET_ND6: */
+	/* case PRIV_NETINET_SCOPE6: */
+	/* case PRIV_NETINET_ALIFETIME6: */
+	/* case PRIV_NETINET_IPSEC: */
+	/* case PRIV_NETIPX_RESERVEDPORT: */
+	/* case PRIV_NETIPX_RAW: */
+	/* case PRIV_NETNCP: */
+	/* case PRIV_NETSMB: */
+	/* case PRIV_VM86_INTCALL: */
+
+	default:
+		/*
+		 * In all remaining cases, deny the privilege request.
+		 */
+		return (EPERM);
+	}
+}
+
 static int
 sysctl_jail_list(SYSCTL_HANDLER_ARGS)
 {
Index: sys/kern/kern_ktrace.c
===================================================================
RCS file: /home/ncvs/src/sys/kern/kern_ktrace.c,v
retrieving revision 1.110
diff -u -r1.110 kern_ktrace.c
--- sys/kern/kern_ktrace.c	31 Jul 2006 15:31:43 -0000	1.110
+++ sys/kern/kern_ktrace.c	13 Sep 2006 08:56:14 -0000
@@ -48,6 +48,7 @@
 #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>
@@ -806,7 +807,8 @@
 			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 */
@@ -1012,7 +1014,7 @@
 
 	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)
Index: sys/kern/kern_linker.c
===================================================================
RCS file: /home/ncvs/src/sys/kern/kern_linker.c,v
retrieving revision 1.142
diff -u -r1.142 kern_linker.c
--- sys/kern/kern_linker.c	10 Jul 2006 19:28:57 -0000	1.142
+++ sys/kern/kern_linker.c	13 Sep 2006 08:56:14 -0000
@@ -37,6 +37,7 @@
 #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>
@@ -853,7 +854,7 @@
 	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);
 
 	/*
@@ -920,7 +921,7 @@
 	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();
Index: sys/kern/kern_ntptime.c
===================================================================
RCS file: /home/ncvs/src/sys/kern/kern_ntptime.c,v
retrieving revision 1.59
diff -u -r1.59 kern_ntptime.c
--- sys/kern/kern_ntptime.c	28 May 2005 14:34:41 -0000	1.59
+++ sys/kern/kern_ntptime.c	13 Sep 2006 08:56:14 -0000
@@ -39,6 +39,7 @@
 #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 @@
 	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 @@
 	struct timeval atv;
 	int error;
 
-	if ((error = suser(td)))
+	if ((error = priv_check(td, PRIV_ADJTIME)))
 		return (error);
 
 	mtx_lock(&Giant);
Index: sys/kern/kern_priv.c
===================================================================
RCS file: sys/kern/kern_priv.c
diff -N sys/kern/kern_priv.c
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ sys/kern/kern_priv.c	13 Sep 2006 09:01:42 -0000
@@ -0,0 +1,153 @@
+/*-
+ * 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:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR, NCIRCLE NETWORK SECURITY,
+ * INC., OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
+ * TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
+ * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+ * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * $FreeBSD$
+ */
+
+#include "opt_mac.h"
+
+#include <sys/param.h>
+#include <sys/jail.h>
+#include <sys/kernel.h>
+#include <sys/mac.h>
+#include <sys/priv.h>
+#include <sys/proc.h>
+#include <sys/sysctl.h>
+#include <sys/systm.h>
+
+/*
+ * `suser_enabled' (which can be set by the security.bsd.suser_enabled
+ * sysctl) determines whether the system 'super-user' policy is in effect.
+ * If it is nonzero, an effective uid of 0 connotes special privilege,
+ * overriding many mandatory and discretionary protections.  If it is zero,
+ * uid 0 is offered no special privilege in the kernel security policy.
+ * Setting it to zero may seriously impact the functionality of many
+ * existing userland programs, and should not be done without careful
+ * consideration of the consequences. 
+ *
+ * XXXRW: Update this comment as needed.
+ */
+int	suser_enabled = 1;
+SYSCTL_INT(_security_bsd, OID_AUTO, suser_enabled, CTLFLAG_RW,
+    &suser_enabled, 0, "processes with uid 0 have privilege");
+TUNABLE_INT("security.bsd.suser_enabled", &suser_enabled);
+
+/*
+ * Check a credential for privilege.  Lots of good reasons to deny privilege;
+ * only a few to grant it.
+ */
+int
+priv_check_cred(struct ucred *cred, enum priv priv, int flags)
+{
+	int error;
+
+	KASSERT(PRIV_VALID(priv), ("priv_check_cred: invalid privilege %d",
+	    priv));
+
+#ifdef MAC
+	error = mac_priv_check(cred, priv);
+	if (error)
+		return (error);
+#endif
+
+	/*
+	 * Jail policy will restrict certain privileges that may otherwise be
+	 * be granted.
+	 *
+	 * While debugging the transition from SUSER_ALLOWJAIL to Jail being
+	 * aware of specific privileges, perform run-time checking that the
+	 * two versions of the policy align.  This assertion will go away
+	 * once the SUSER_ALLOWJAIL flag has gone away.
+	 */
+	error = prison_priv_check(cred, priv);
+	KASSERT(!jailed(cred) || error == ((flags & SUSER_ALLOWJAIL) ? 0 :
+	    EPERM), ("priv_check_cred: prison_priv_check %d but flags %s",
+	    error, flags & SUSER_ALLOWJAIL ? "allowjail" : "!allowjail"));
+	if (error)
+		return (error);
+
+	/*
+	 * Having determined if privilege is restricted by various policies,
+	 * now determine if privilege is granted.  For now, we allow
+	 * short-circuit boolean evaluation, so may not call all policies.
+	 * Perhaps we should.
+	 *
+	 * Superuser policy grants privilege based on the effective (or in
+	 * certain edge cases, real) uid being 0.  We allow the policy to be
+	 * globally disabled, although this is currently of limited uility.
+	 */
+	if (suser_enabled) {
+		if (flags & SUSER_RUID) {
+			if (cred->cr_ruid == 0)
+				return (0);
+		} else {
+			if (cred->cr_uid == 0)
+				return (0);
+		}
+	}
+
+	/*
+	 * Now check with MAC, if enabled, to see if a policy module grants
+	 * privilege.
+	 */
+#ifdef MAC
+	if (mac_priv_grant(cred, priv) == 0)
+		return (0);
+#endif
+	return (EPERM);
+}
+
+int
+priv_check(struct thread *td, enum priv priv)
+{
+
+	KASSERT(td == curthread, ("priv_check: td != curthread"));
+
+	return (priv_check_cred(td->td_ucred, priv, 0));
+}
+
+/*
+ * Historical suser() wrapper functions, which now simply request PRIV_ROOT.
+ * These will be removed in the near future, and exist solely because the
+ * list of global privileges is not yet complete.
+ */
+int
+suser_cred(struct ucred *cred, int flags)
+{
+
+	return (priv_check_cred(cred, PRIV_ROOT, flags));
+}
+
+int
+suser(struct thread *td)
+{
+
+	KASSERT(td == curthread, ("suser: td != curthread"));
+
+	return (suser_cred(td->td_ucred, 0));
+}
Index: sys/kern/kern_prot.c
===================================================================
RCS file: /home/ncvs/src/sys/kern/kern_prot.c,v
retrieving revision 1.203
diff -u -r1.203 kern_prot.c
--- sys/kern/kern_prot.c	6 Jul 2006 21:32:20 -0000	1.203
+++ sys/kern/kern_prot.c	13 Sep 2006 08:56:14 -0000
@@ -56,6 +56,7 @@
 #include <sys/mutex.h>
 #include <sys/refcount.h>
 #include <sys/sx.h>
+#include <sys/priv.h>
 #include <sys/proc.h>
 #include <sys/sysproto.h>
 #include <sys/jail.h>
@@ -70,7 +71,6 @@
 
 static MALLOC_DEFINE(M_CRED, "cred", "credentials");
 
-SYSCTL_DECL(_security);
 SYSCTL_NODE(_security, OID_AUTO, bsd, CTLFLAG_RW, 0,
     "BSD security policy");
 
@@ -549,7 +549,8 @@
 #ifdef POSIX_APPENDIX_B_4_2_2	/* Use BSD-compat clause from B.4.2.2 */
 	    uid != oldcred->cr_uid &&		/* allow setuid(geteuid()) */
 #endif
-	    (error = suser_cred(oldcred, SUSER_ALLOWJAIL)) != 0)
+	    (error = priv_check_cred(oldcred, PRIV_CRED_SETUID,
+	    SUSER_ALLOWJAIL)) != 0)
 		goto fail;
 
 	/*
@@ -565,7 +566,8 @@
 #ifdef POSIX_APPENDIX_B_4_2_2	/* Use the clause from B.4.2.2 */
 	    uid == oldcred->cr_uid ||
 #endif
-	    suser_cred(oldcred, SUSER_ALLOWJAIL) == 0) /* we are using privs */
+	    /* We are using privs. */
+	    priv_check_cred(oldcred, PRIV_CRED_SETUID, SUSER_ALLOWJAIL) == 0)
 #endif
 	{
 		/*
@@ -641,7 +643,8 @@
 
 	if (euid != oldcred->cr_ruid &&		/* allow seteuid(getuid()) */
 	    euid != oldcred->cr_svuid &&	/* allow seteuid(saved uid) */
-	    (error = suser_cred(oldcred, SUSER_ALLOWJAIL)) != 0)
+	    (error = priv_check_cred(oldcred, PRIV_CRED_SETEUID,
+	    SUSER_ALLOWJAIL)) != 0)
 		goto fail;
 
 	/*
@@ -713,7 +716,8 @@
 #ifdef POSIX_APPENDIX_B_4_2_2	/* Use BSD-compat clause from B.4.2.2 */
 	    gid != oldcred->cr_groups[0] && /* allow setgid(getegid()) */
 #endif
-	    (error = suser_cred(oldcred, SUSER_ALLOWJAIL)) != 0)
+	    (error = priv_check_cred(oldcred, PRIV_CRED_SETGID,
+	    SUSER_ALLOWJAIL)) != 0)
 		goto fail;
 
 	crcopy(newcred, oldcred);
@@ -726,7 +730,8 @@
 #ifdef POSIX_APPENDIX_B_4_2_2	/* use the clause from B.4.2.2 */
 	    gid == oldcred->cr_groups[0] ||
 #endif
-	    suser_cred(oldcred, SUSER_ALLOWJAIL) == 0) /* we are using privs */
+	    /* We are using privs. */
+	    priv_check_cred(oldcred, PRIV_CRED_SETGID, SUSER_ALLOWJAIL) == 0)
 #endif
 	{
 		/*
@@ -798,7 +803,8 @@
 
 	if (egid != oldcred->cr_rgid &&		/* allow setegid(getgid()) */
 	    egid != oldcred->cr_svgid &&	/* allow setegid(saved gid) */
-	    (error = suser_cred(oldcred, SUSER_ALLOWJAIL)) != 0)
+	    (error = priv_check_cred(oldcred, PRIV_CRED_SETEGID,
+	    SUSER_ALLOWJAIL)) != 0)
 		goto fail;
 
 	crcopy(newcred, oldcred);
@@ -861,7 +867,8 @@
 		goto fail;
 #endif
 
-	error = suser_cred(oldcred, SUSER_ALLOWJAIL);
+	error = priv_check_cred(oldcred, PRIV_CRED_SETGROUPS,
+	    SUSER_ALLOWJAIL);
 	if (error)
 		goto fail;
 
@@ -933,7 +940,8 @@
 	      ruid != oldcred->cr_svuid) ||
 	     (euid != (uid_t)-1 && euid != oldcred->cr_uid &&
 	      euid != oldcred->cr_ruid && euid != oldcred->cr_svuid)) &&
-	    (error = suser_cred(oldcred, SUSER_ALLOWJAIL)) != 0)
+	    (error = priv_check_cred(oldcred, PRIV_CRED_SETREUID,
+	     SUSER_ALLOWJAIL)) != 0)
 		goto fail;
 
 	crcopy(newcred, oldcred);
@@ -1001,7 +1009,8 @@
 	    rgid != oldcred->cr_svgid) ||
 	     (egid != (gid_t)-1 && egid != oldcred->cr_groups[0] &&
 	     egid != oldcred->cr_rgid && egid != oldcred->cr_svgid)) &&
-	    (error = suser_cred(oldcred, SUSER_ALLOWJAIL)) != 0)
+	    (error = priv_check_cred(oldcred, PRIV_CRED_SETREGID,
+	     SUSER_ALLOWJAIL)) != 0)
 		goto fail;
 
 	crcopy(newcred, oldcred);
@@ -1081,7 +1090,8 @@
 	     (suid != (uid_t)-1 && suid != oldcred->cr_ruid &&
 	    suid != oldcred->cr_svuid &&
 	      suid != oldcred->cr_uid)) &&
-	    (error = suser_cred(oldcred, SUSER_ALLOWJAIL)) != 0)
+	    (error = priv_check_cred(oldcred, PRIV_CRED_SETRESUID,
+	     SUSER_ALLOWJAIL)) != 0)
 		goto fail;
 
 	crcopy(newcred, oldcred);
@@ -1162,7 +1172,8 @@
 	     (sgid != (gid_t)-1 && sgid != oldcred->cr_rgid &&
 	      sgid != oldcred->cr_svgid &&
 	      sgid != oldcred->cr_groups[0])) &&
-	    (error = suser_cred(oldcred, SUSER_ALLOWJAIL)) != 0)
+	    (error = priv_check_cred(oldcred, PRIV_CRED_SETRESGID,
+	     SUSER_ALLOWJAIL)) != 0)
 		goto fail;
 
 	crcopy(newcred, oldcred);
@@ -1326,65 +1337,14 @@
 }
 
 /*
- * `suser_enabled' (which can be set by the security.suser_enabled
- * sysctl) determines whether the system 'super-user' policy is in effect.
- * If it is nonzero, an effective uid of 0 connotes special privilege,
- * overriding many mandatory and discretionary protections.  If it is zero,
- * uid 0 is offered no special privilege in the kernel security policy.
- * Setting it to zero may seriously impact the functionality of many
- * existing userland programs, and should not be done without careful
- * consideration of the consequences.
- */
-int	suser_enabled = 1;
-SYSCTL_INT(_security_bsd, OID_AUTO, suser_enabled, CTLFLAG_RW,
-    &suser_enabled, 0, "processes with uid 0 have privilege");
-TUNABLE_INT("security.bsd.suser_enabled", &suser_enabled);
-
-/*
- * Test whether the specified credentials imply "super-user" privilege.
- * Return 0 or EPERM.
- */
-int
-suser_cred(struct ucred *cred, int flag)
-{
-
-	if (!suser_enabled)
-		return (EPERM);
-	if (((flag & SUSER_RUID) ? cred->cr_ruid : cred->cr_uid) != 0)
-		return (EPERM);
-	if (jailed(cred) && !(flag & SUSER_ALLOWJAIL))
-		return (EPERM);
-	return (0);
-}
-
-/*
- * Shortcut to hide contents of struct td and struct proc from the
- * caller, promoting binary compatibility.
- */
-int
-suser(struct thread *td)
-{
-
-#ifdef INVARIANTS
-	if (td != curthread) {
-		printf("suser: thread %p (%d %s) != curthread %p (%d %s)\n",
-		    td, td->td_proc->p_pid, td->td_proc->p_comm,
-		    curthread, curthread->td_proc->p_pid,
-		    curthread->td_proc->p_comm);
-#ifdef KDB
-		kdb_backtrace();
-#endif
-	}
-#endif
-	return (suser_cred(td->td_ucred, 0));
-}
-
-/*
  * Test the active securelevel against a given level.  securelevel_gt()
  * implements (securelevel > level).  securelevel_ge() implements
  * (securelevel >= level).  Note that the logic is inverted -- these
  * functions return EPERM on "success" and 0 on "failure".
  *
+ * XXXRW: Possibly since this has to do with privilege, it should move to
+ * kern_priv.c.
+ *
  * MPSAFE
  */
 int
@@ -1437,7 +1397,8 @@
 {
 
 	if (!see_other_uids && u1->cr_ruid != u2->cr_ruid) {
-		if (suser_cred(u1, SUSER_ALLOWJAIL) != 0)
+		if (priv_check_cred(u1, PRIV_SEEOTHERUIDS, SUSER_ALLOWJAIL)
+		    != 0)
 			return (ESRCH);
 	}
 	return (0);
@@ -1476,7 +1437,8 @@
 				break;
 		}
 		if (!match) {
-			if (suser_cred(u1, SUSER_ALLOWJAIL) != 0)
+			if (priv_check_cred(u1, PRIV_SEEOTHERGIDS,
+			    SUSER_ALLOWJAIL) != 0)
 				return (ESRCH);
 		}
 	}
@@ -1593,7 +1555,8 @@
 			break;
 		default:
 			/* Not permitted without privilege. */
-			error = suser_cred(cred, SUSER_ALLOWJAIL);
+			error = priv_check_cred(cred, PRIV_SIGNAL_SUGID,
+			    SUSER_ALLOWJAIL);
 			if (error)
 				return (error);
 		}
@@ -1608,7 +1571,8 @@
 	    cred->cr_uid != proc->p_ucred->cr_ruid &&
 	    cred->cr_uid != proc->p_ucred->cr_svuid) {
 		/* Not permitted without privilege. */
-		error = suser_cred(cred, SUSER_ALLOWJAIL);
+		error = priv_check_cred(cred, PRIV_SIGNAL_DIFFCRED,
+		    SUSER_ALLOWJAIL);
 		if (error)
 			return (error);
 	}
@@ -1616,7 +1580,6 @@
 	return (0);
 }
 
-
 /*-
  * Determine whether td may deliver the specified signal to p.
  * Returns: 0 for permitted, an errno value otherwise
@@ -1685,19 +1648,14 @@
 		return (error);
 	if ((error = cr_seeothergids(td->td_ucred, p->p_ucred)))
 		return (error);
-	if (td->td_ucred->cr_ruid == p->p_ucred->cr_ruid)
-		return (0);
-	if (td->td_ucred->cr_uid == p->p_ucred->cr_ruid)
-		return (0);
-	if (suser_cred(td->td_ucred, SUSER_ALLOWJAIL) == 0)
-		return (0);
-
-#ifdef CAPABILITIES
-	if (!cap_check(NULL, td, CAP_SYS_NICE, SUSER_ALLOWJAIL))
-		return (0);
-#endif
-
-	return (EPERM);
+	if (td->td_ucred->cr_ruid != p->p_ucred->cr_ruid &&
+	    td->td_ucred->cr_uid != p->p_ucred->cr_ruid) {
+		error = priv_check_cred(td->td_ucred, PRIV_SCHED_DIFFCRED,
+		    SUSER_ALLOWJAIL);
+		if (error)
+			return (error);
+	}
+	return (0);
 }
 
 /*
@@ -1732,7 +1690,8 @@
 	KASSERT(td == curthread, ("%s: td not curthread", __func__));
 	PROC_LOCK_ASSERT(p, MA_OWNED);
 	if (!unprivileged_proc_debug) {
-		error = suser_cred(td->td_ucred, SUSER_ALLOWJAIL);
+		error = priv_check_cred(td->td_ucred, PRIV_DEBUG_UNPRIV,
+		    SUSER_ALLOWJAIL);
 		if (error)
 			return (error);
 	}
@@ -1780,11 +1739,18 @@
 	/*
 	 * If p's gids aren't a subset, or the uids aren't a subset,
 	 * or the credential has changed, require appropriate privilege
-	 * for td to debug p.  For POSIX.1e capabilities, this will
-	 * require CAP_SYS_PTRACE.
+	 * for td to debug p.
 	 */
-	if (!grpsubset || !uidsubset || credentialchanged) {
-		error = suser_cred(td->td_ucred, SUSER_ALLOWJAIL);
+	if (!grpsubset || !uidsubset) {
+		error = priv_check_cred(td->td_ucred, PRIV_DEBUG_DIFFCRED,
+		    SUSER_ALLOWJAIL);
+		if (error)
+			return (error);
+	}
+
+	if (credentialchanged) {
+		error = priv_check_cred(td->td_ucred, PRIV_DEBUG_SUGID,
+		    SUSER_ALLOWJAIL);
 		if (error)
 			return (error);
 	}
@@ -1798,6 +1764,7 @@
 
 	/*
 	 * Can't trace a process that's currently exec'ing.
+	 *
 	 * XXX: Note, this is not a security policy decision, it's a
 	 * basic correctness/functionality decision.  Therefore, this check
 	 * should be moved to the caller's of p_candebug().
@@ -2059,7 +2026,8 @@
 	int error;
 	char logintmp[MAXLOGNAME];
 
-	error = suser_cred(td->td_ucred, SUSER_ALLOWJAIL);
+	error = priv_check_cred(td->td_ucred, PRIV_PROC_SETLOGIN,
+	    SUSER_ALLOWJAIL);
 	if (error)
 		return (error);
 	error = copyinstr(uap->namebuf, logintmp, sizeof(logintmp), NULL);
Index: sys/kern/kern_resource.c
===================================================================
RCS file: /home/ncvs/src/sys/kern/kern_resource.c,v
retrieving revision 1.159
diff -u -r1.159 kern_resource.c
--- sys/kern/kern_resource.c	4 Aug 2006 07:56:35 -0000	1.159
+++ sys/kern/kern_resource.c	13 Sep 2006 08:56:14 -0000
@@ -47,6 +47,7 @@
 #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 @@
 		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);
@@ -352,7 +353,7 @@
 			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;
@@ -573,7 +574,8 @@
 	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);
Index: sys/kern/kern_shutdown.c
===================================================================
RCS file: /home/ncvs/src/sys/kern/kern_shutdown.c,v
retrieving revision 1.178
diff -u -r1.178 kern_shutdown.c
--- sys/kern/kern_shutdown.c	10 Apr 2006 10:03:40 -0000	1.178
+++ sys/kern/kern_shutdown.c	13 Sep 2006 08:56:14 -0000
@@ -56,6 +56,7 @@
 #include <sys/mac.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>
@@ -163,7 +164,7 @@
 	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);
Index: sys/kern/kern_sysctl.c
===================================================================
RCS file: /home/ncvs/src/sys/kern/kern_sysctl.c,v
retrieving revision 1.170
diff -u -r1.170 kern_sysctl.c
--- sys/kern/kern_sysctl.c	16 Jun 2006 07:36:18 -0000	1.170
+++ sys/kern/kern_sysctl.c	13 Sep 2006 08:56:14 -0000
@@ -47,6 +47,7 @@
 #include <sys/sysctl.h>
 #include <sys/mac.h>
 #include <sys/malloc.h>
+#include <sys/priv.h>
 #include <sys/proc.h>
 #include <sys/lock.h>
 #include <sys/mutex.h>
@@ -510,7 +511,7 @@
 {
 	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);
@@ -1251,13 +1252,11 @@
 
 	/* 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);
 	}
Index: sys/kern/kern_thr.c
===================================================================
RCS file: /home/ncvs/src/sys/kern/kern_thr.c,v
retrieving revision 1.51
diff -u -r1.51 kern_thr.c
--- sys/kern/kern_thr.c	25 Aug 2006 10:05:30 -0000	1.51
+++ sys/kern/kern_thr.c	13 Sep 2006 08:56:14 -0000
@@ -32,6 +32,7 @@
 #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>
@@ -137,7 +138,7 @@
 		case SCHED_FIFO:
 		case SCHED_RR:
 			/* Only root can set scheduler policy */
-			if (suser(td) != 0)
+			if (priv_check(td, PRIV_SCHED_SETPOLICY) != 0)
 				return (EPERM);
 			if (sched->param.sched_priority < RTP_PRIO_MIN ||
 			    sched->param.sched_priority > RTP_PRIO_MAX)
@@ -453,7 +454,7 @@
 	if (ret != 0)
 		return (ret);
 
-	ret = suser(td);
+	ret = priv_check(td, PRIV_SCHED_SET);
 	if (ret != 0)
 		return (ret);
 
@@ -556,7 +557,7 @@
 	ret = copyin(uap->param, &param, sizeof(struct sched_param));
 	if (ret != 0)
 		return (ret);
-	ret = suser(td);
+	ret = priv_check(td, PRIV_SCHED_SETPARAM);
 	if (ret != 0)
 		return (ret);
 	p = td->td_proc;
Index: sys/kern/kern_time.c
===================================================================
RCS file: /home/ncvs/src/sys/kern/kern_time.c,v
retrieving revision 1.131
diff -u -r1.131 kern_time.c
--- sys/kern/kern_time.c	15 Aug 2006 12:10:57 -0000	1.131
+++ sys/kern/kern_time.c	13 Sep 2006 08:56:14 -0000
@@ -48,6 +48,7 @@
 #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>
@@ -287,7 +288,7 @@
 	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);
@@ -505,7 +506,7 @@
 	if (error)
 		return (error);
 #endif
-	error = suser(td);
+	error = priv_check(td, PRIV_SETTIMEOFDAY);
 	if (error)
 		return (error);
 	/* Verify all parameters before changing time. */
Index: sys/kern/kern_xxx.c
===================================================================
RCS file: /home/ncvs/src/sys/kern/kern_xxx.c,v
retrieving revision 1.46
diff -u -r1.46 kern_xxx.c
--- sys/kern/kern_xxx.c	6 Jan 2005 23:35:39 -0000	1.46
+++ sys/kern/kern_xxx.c	13 Sep 2006 08:56:14 -0000
@@ -38,6 +38,7 @@
 #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 @@
 {
 	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 @@
 {
         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 @@
 	mtx_unlock(&Giant);
         return (error);
 }
-
Index: sys/kern/subr_acl_posix1e.c
===================================================================
RCS file: /home/ncvs/src/sys/kern/subr_acl_posix1e.c,v
retrieving revision 1.50
diff -u -r1.50 subr_acl_posix1e.c
--- sys/kern/subr_acl_posix1e.c	23 Jul 2006 19:35:10 -0000	1.50
+++ sys/kern/subr_acl_posix1e.c	13 Sep 2006 08:56:14 -0000
@@ -39,6 +39,7 @@
 #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 @@
 
 /*
  * 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 @@
 {
 	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 @@
 
 	/*
 	 * 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.
-	 */
-#ifndef CAPABILITIES
-	if (suser_cred(cred, SUSER_ALLOWJAIL) == 0)
-		cap_granted = VALLPERM;
-	else
-		cap_granted = 0;
-#else
-	cap_granted = 0;
+	 * entry that matches but has failed to allow access.
+	 *
+	 * XXXRW: Ideally, we'd determine the privileges required before
+	 * asking for them.
+	 */
+	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 @@
 				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 @@
 		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 @@
 			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 @@
 					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 @@
 					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 @@
 
 	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);
Index: sys/kern/subr_firmware.c
===================================================================
RCS file: /home/ncvs/src/sys/kern/subr_firmware.c,v
retrieving revision 1.5
diff -u -r1.5 subr_firmware.c
--- sys/kern/subr_firmware.c	25 Jun 2006 12:36:21 -0000	1.5
+++ sys/kern/subr_firmware.c	13 Sep 2006 08:56:14 -0000
@@ -38,6 +38,7 @@
 #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 @@
 		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;
Index: sys/kern/subr_prf.c
===================================================================
RCS file: /home/ncvs/src/sys/kern/subr_prf.c,v
retrieving revision 1.124
diff -u -r1.124 subr_prf.c
--- sys/kern/subr_prf.c	12 Jul 2006 21:22:44 -0000	1.124
+++ sys/kern/subr_prf.c	13 Sep 2006 08:56:14 -0000
@@ -48,6 +48,7 @@
 #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>
@@ -856,8 +857,6 @@
 	oldp = msgbufp;
 }
 
-SYSCTL_DECL(_security_bsd);
-
 static int unprivileged_read_msgbuf = 1;
 SYSCTL_INT(_security_bsd, OID_AUTO, unprivileged_read_msgbuf,
     CTLFLAG_RW, &unprivileged_read_msgbuf, 0,
@@ -872,7 +871,7 @@
 	int error, len;
 
 	if (!unprivileged_read_msgbuf) {
-		error = suser(req->td);
+		error = priv_check(req->td, PRIV_MSGBUF);
 		if (error)
 			return (error);
 	}
Index: sys/kern/subr_witness.c
===================================================================
RCS file: /home/ncvs/src/sys/kern/subr_witness.c,v
retrieving revision 1.217
diff -u -r1.217 subr_witness.c
--- sys/kern/subr_witness.c	26 Aug 2006 11:21:25 -0000	1.217
+++ sys/kern/subr_witness.c	13 Sep 2006 08:56:14 -0000
@@ -95,6 +95,7 @@
 #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>
@@ -532,7 +533,10 @@
 	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)
Index: sys/kern/sysv_msg.c
===================================================================
RCS file: /home/ncvs/src/sys/kern/sysv_msg.c,v
retrieving revision 1.61
diff -u -r1.61 sysv_msg.c
--- sys/kern/sysv_msg.c	10 Jun 2006 14:34:07 -0000	1.61
+++ sys/kern/sysv_msg.c	13 Sep 2006 08:56:14 -0000
@@ -57,6 +57,7 @@
 #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/mac.h>
@@ -516,7 +517,7 @@
 		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;
 		}
Index: sys/kern/tty.c
===================================================================
RCS file: /home/ncvs/src/sys/kern/tty.c,v
retrieving revision 1.258
diff -u -r1.258 tty.c
--- sys/kern/tty.c	10 Sep 2006 16:51:56 -0000	1.258
+++ sys/kern/tty.c	13 Sep 2006 08:56:14 -0000
@@ -86,6 +86,7 @@
 #if defined(COMPAT_43TTY)
 #include <sys/ioctl_compat.h>
 #endif
+#include <sys/priv.h>
 #include <sys/proc.h>
 #define	TTYDEFCHARS
 #include <sys/tty.h>
@@ -1012,7 +1013,7 @@
 		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;
@@ -1161,9 +1162,9 @@
 		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);
@@ -1236,7 +1237,7 @@
 		}
 		break;
 	case TIOCSDRAINWAIT:
-		error = suser(td);
+		error = priv_check(td, PRIV_TTY_DRAINWAIT);
 		if (error)
 			return (error);
 		tp->t_timeout = *(int *)data * hz;
@@ -3094,7 +3095,8 @@
 				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 {
 		/*
@@ -3320,7 +3322,7 @@
 	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;
Index: sys/kern/tty_cons.c
===================================================================
RCS file: /home/ncvs/src/sys/kern/tty_cons.c,v
retrieving revision 1.135
diff -u -r1.135 tty_cons.c
--- sys/kern/tty_cons.c	26 May 2006 11:00:20 -0000	1.135
+++ sys/kern/tty_cons.c	13 Sep 2006 08:56:14 -0000
@@ -49,6 +49,7 @@
 #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>
@@ -506,7 +507,7 @@
 	 * 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;
Index: sys/kern/tty_pts.c
===================================================================
RCS file: /home/ncvs/src/sys/kern/tty_pts.c,v
retrieving revision 1.8
diff -u -r1.8 tty_pts.c
--- sys/kern/tty_pts.c	28 Apr 2006 21:39:57 -0000	1.8
+++ sys/kern/tty_pts.c	13 Sep 2006 08:56:14 -0000
@@ -56,6 +56,7 @@
 #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>
@@ -263,9 +264,11 @@
 	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. */
Index: sys/kern/tty_pty.c
===================================================================
RCS file: /home/ncvs/src/sys/kern/tty_pty.c,v
retrieving revision 1.145
diff -u -r1.145 tty_pty.c
--- sys/kern/tty_pty.c	2 Feb 2006 20:35:45 -0000	1.145
+++ sys/kern/tty_pty.c	13 Sep 2006 08:56:14 -0000
@@ -46,6 +46,7 @@
 #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>
@@ -198,9 +199,11 @@
 	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. */
 		(void)ttyld_modem(tp, 1);
Index: sys/kern/uipc_mqueue.c
===================================================================
RCS file: /home/ncvs/src/sys/kern/uipc_mqueue.c,v
retrieving revision 1.15
diff -u -r1.15 uipc_mqueue.c
--- sys/kern/uipc_mqueue.c	17 Apr 2006 18:20:37 -0000	1.15
+++ sys/kern/uipc_mqueue.c	13 Sep 2006 08:56:14 -0000
@@ -65,6 +65,7 @@
 #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>
@@ -953,8 +954,12 @@
 
 	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;
@@ -1205,10 +1210,16 @@
 		 */
 		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;
@@ -1217,7 +1228,8 @@
 
 	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;
Index: sys/kern/uipc_sem.c
===================================================================
RCS file: /home/ncvs/src/sys/kern/uipc_sem.c,v
retrieving revision 1.24
diff -u -r1.24 uipc_sem.c
--- sys/kern/uipc_sem.c	16 Aug 2006 08:25:40 -0000	1.24
+++ sys/kern/uipc_sem.c	13 Sep 2006 08:56:14 -0000
@@ -42,6 +42,7 @@
 #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>
@@ -418,15 +419,23 @@
 {
 	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
Index: sys/kern/vfs_mount.c
===================================================================
RCS file: /home/ncvs/src/sys/kern/vfs_mount.c,v
retrieving revision 1.231
diff -u -r1.231 vfs_mount.c
--- sys/kern/vfs_mount.c	26 Aug 2006 16:28:19 -0000	1.231
+++ sys/kern/vfs_mount.c	13 Sep 2006 08:56:14 -0000
@@ -47,6 +47,7 @@
 #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>
@@ -804,20 +805,29 @@
 	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.
+	 *
+	 * XXXRW: Which privileges to map this to?  Wouldn't it be better
+	 * to see if they weren't already set and only then check privilege?
 	 */
 	if (suser(td) != 0)
 		fsflags |= MNT_NOSUID | MNT_USER;
@@ -898,7 +908,9 @@
 			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);
 			}
@@ -1055,7 +1067,8 @@
 	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);
 	}
 
Index: sys/kern/vfs_subr.c
===================================================================
RCS file: /home/ncvs/src/sys/kern/vfs_subr.c,v
retrieving revision 1.682
diff -u -r1.682 vfs_subr.c
--- sys/kern/vfs_subr.c	4 Sep 2006 22:15:44 -0000	1.682
+++ sys/kern/vfs_subr.c	13 Sep 2006 08:56:14 -0000
@@ -62,6 +62,7 @@
 #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>
@@ -410,7 +411,7 @@
 
 	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);
@@ -3169,9 +3170,7 @@
     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
@@ -3225,59 +3224,46 @@
 		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);
 }
@@ -3298,16 +3284,13 @@
 		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:
Index: sys/kern/vfs_syscalls.c
===================================================================
RCS file: /home/ncvs/src/sys/kern/vfs_syscalls.c,v
retrieving revision 1.420
diff -u -r1.420 vfs_syscalls.c
--- sys/kern/vfs_syscalls.c	2 Aug 2006 15:27:48 -0000	1.420
+++ sys/kern/vfs_syscalls.c	13 Sep 2006 08:56:14 -0000
@@ -61,6 +61,7 @@
 #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>
@@ -266,7 +267,7 @@
 	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);
@@ -351,7 +352,7 @@
 	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);
@@ -462,7 +463,7 @@
 				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);
@@ -836,7 +837,8 @@
 	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,
@@ -890,8 +892,8 @@
 
 /*
  * 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)
@@ -1180,9 +1182,10 @@
 	switch (mode & S_IFMT) {
 	case S_IFCHR:
 	case S_IFBLK:
-		error = suser(td);
+		error = priv_check(td, PRIV_VFS_MKNOD_DEV);
 		break;
 	default:
+		/* XXXRW: Should do a full enumeration here. */
 		error = suser_cred(td->td_ucred, SUSER_ALLOWJAIL);
 		break;
 	}
@@ -1367,8 +1370,6 @@
 	return (error);
 }
 
-SYSCTL_DECL(_security_bsd);
-
 static int hardlink_check_uid = 0;
 SYSCTL_INT(_security_bsd, OID_AUTO, hardlink_check_uid, CTLFLAG_RW,
     &hardlink_check_uid, 0,
@@ -1386,9 +1387,6 @@
 	struct vattr va;
 	int error;
 
-	if (suser_cred(cred, SUSER_ALLOWJAIL) == 0)
-		return (0);
-
 	if (!hardlink_check_uid && !hardlink_check_gid)
 		return (0);
 
@@ -1396,14 +1394,18 @@
 	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);
@@ -2357,7 +2359,8 @@
 	 * 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);
 	}
@@ -3889,7 +3892,8 @@
 	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;
 	}
@@ -3955,7 +3959,7 @@
 	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,
@@ -3994,7 +3998,7 @@
 	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,
@@ -4017,10 +4021,10 @@
 }
 
 /*
- * 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
@@ -4053,7 +4057,7 @@
 	int vfslocked;
 	int indx;
 
-	error = suser(td);
+	error = priv_check(td, PRIV_VFS_FHOPEN);
 	if (error)
 		return (error);
 	fmode = FFLAGS(uap->flags);
@@ -4237,7 +4241,7 @@
 	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));
@@ -4302,7 +4306,7 @@
 	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)
Index: sys/kern/vfs_vnops.c
===================================================================
RCS file: /home/ncvs/src/sys/kern/vfs_vnops.c,v
retrieving revision 1.244
diff -u -r1.244 vfs_vnops.c
--- sys/kern/vfs_vnops.c	24 Jun 2006 22:55:43 -0000	1.244
+++ sys/kern/vfs_vnops.c	13 Sep 2006 08:56:14 -0000
@@ -45,6 +45,7 @@
 #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>
@@ -708,7 +709,7 @@
 	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;
Index: sys/modules/Makefile
===================================================================
RCS file: /home/ncvs/src/sys/modules/Makefile,v
retrieving revision 1.510
diff -u -r1.510 Makefile
--- sys/modules/Makefile	9 Sep 2006 16:58:22 -0000	1.510
+++ sys/modules/Makefile	13 Sep 2006 08:56:14 -0000
@@ -148,6 +148,7 @@
 	mac_none \
 	mac_partition \
 	mac_portacl \
+	mac_privs \
 	mac_seeotheruids \
 	mac_stub \
 	mac_test \
Index: sys/net/bpf.c
===================================================================
RCS file: /home/ncvs/src/sys/net/bpf.c,v
retrieving revision 1.172
diff -u -r1.172 bpf.c
--- sys/net/bpf.c	9 Aug 2006 16:30:26 -0000	1.172
+++ sys/net/bpf.c	13 Sep 2006 08:56:14 -0000
@@ -49,6 +49,7 @@
 #include <sys/malloc.h>
 #include <sys/mbuf.h>
 #include <sys/time.h>
+#include <sys/priv.h>
 #include <sys/proc.h>
 #include <sys/signalvar.h>
 #include <sys/filio.h>
@@ -1723,7 +1724,7 @@
 	 * if the users who opened the devices were able to retrieve
 	 * the statistics for them, too.
 	 */
-	error = suser(req->td);
+	error = priv_check(req->td, PRIV_NET_BPF);
 	if (error)
 		return (error);
 	if (req->oldptr == NULL)
Index: sys/net/if.c
===================================================================
RCS file: /home/ncvs/src/sys/net/if.c,v
retrieving revision 1.262
diff -u -r1.262 if.c
--- sys/net/if.c	6 Sep 2006 17:12:10 -0000	1.262
+++ sys/net/if.c	13 Sep 2006 08:56:14 -0000
@@ -45,6 +45,7 @@
 #include <sys/bus.h>
 #include <sys/mbuf.h>
 #include <sys/systm.h>
+#include <sys/priv.h>
 #include <sys/proc.h>
 #include <sys/socket.h>
 #include <sys/socketvar.h>
@@ -1488,7 +1489,7 @@
 		break;
 
 	case SIOCSIFFLAGS:
-		error = suser(td);
+		error = priv_check(td, PRIV_NET_SETIFFLAGS);
 		if (error)
 			return (error);
 		/*
@@ -1531,7 +1532,7 @@
 		break;
 
 	case SIOCSIFCAP:
-		error = suser(td);
+		error = priv_check(td, PRIV_NET_SETIFCAP);
 		if (error)
 			return (error);
 		if (ifp->if_ioctl == NULL)
@@ -1552,8 +1553,8 @@
 #endif
 
 	case SIOCSIFNAME:
-		error = suser(td);
-		if (error != 0)
+		error = priv_check(td, PRIV_NET_SETIFNAME);
+		if (error)
 			return (error);
 		error = copyinstr(ifr->ifr_data, new_name, IFNAMSIZ, NULL);
 		if (error != 0)
@@ -1599,7 +1600,7 @@
 		break;
 
 	case SIOCSIFMETRIC:
-		error = suser(td);
+		error = priv_check(td, PRIV_NET_SETIFMETRIC);
 		if (error)
 			return (error);
 		ifp->if_metric = ifr->ifr_metric;
@@ -1607,7 +1608,7 @@
 		break;
 
 	case SIOCSIFPHYS:
-		error = suser(td);
+		error = priv_check(td, PRIV_NET_SETIFPHYS);
 		if (error)
 			return (error);
 		if (ifp->if_ioctl == NULL)
@@ -1623,7 +1624,7 @@
 	{
 		u_long oldmtu = ifp->if_mtu;
 
-		error = suser(td);
+		error = priv_check(td, PRIV_NET_SETIFMTU);
 		if (error)
 			return (error);
 		if (ifr->ifr_mtu < IF_MINMTU || ifr->ifr_mtu > IF_MAXMTU)
@@ -1650,7 +1651,10 @@
 
 	case SIOCADDMULTI:
 	case SIOCDELMULTI:
-		error = suser(td);
+		if (cmd == SIOCADDMULTI)
+			error = priv_check(td, PRIV_NET_ADDMULTI);
+		else
+			error = priv_check(td, PRIV_NET_DELMULTI);
 		if (error)
 			return (error);
 
@@ -1680,7 +1684,7 @@
 	case SIOCSLIFPHYADDR:
 	case SIOCSIFMEDIA:
 	case SIOCSIFGENERIC:
-		error = suser(td);
+		error = priv_check(td, PRIV_NET_HWIOCTL);
 		if (error)
 			return (error);
 		if (ifp->if_ioctl == NULL)
@@ -1709,7 +1713,7 @@
 		break;
 
 	case SIOCSIFLLADDR:
-		error = suser(td);
+		error = priv_check(td, PRIV_NET_SETLLADDR);
 		if (error)
 			return (error);
 		error = if_setlladdr(ifp,
@@ -1720,7 +1724,7 @@
 	{
 		struct ifgroupreq *ifgr = (struct ifgroupreq *)ifr;
 
-		error = suser(td);
+		error = priv_check(td, PRIV_NET_ADDIFGROUP);
 		if (error)
 			return (error);
 		if ((error = if_addgroup(ifp, ifgr->ifgr_group)))
@@ -1737,7 +1741,7 @@
 	{
 		struct ifgroupreq *ifgr = (struct ifgroupreq *)ifr;
 
-		error = suser(td);
+		error = priv_check(td, PRIV_NET_DELIFGROUP);
 		if (error)
 			return (error);
 		if ((error = if_delgroup(ifp, ifgr->ifgr_group)))
@@ -1776,12 +1780,14 @@
 	switch (cmd) {
 	case SIOCIFCREATE:
 	case SIOCIFCREATE2:
-		if ((error = suser(td)) != 0)
+		error = priv_check(td, PRIV_NET_IFCREATE);
+		if (error)
 			return (error);
 		return (if_clone_create(ifr->ifr_name, sizeof(ifr->ifr_name),
 			cmd == SIOCIFCREATE2 ? ifr->ifr_data : NULL));
 	case SIOCIFDESTROY:
-		if ((error = suser(td)) != 0)
+		error = priv_check(td, PRIV_NET_IFDESTROY);
+		if (error)
 			return (error);
 		return if_clone_destroy(ifr->ifr_name);
 
Index: sys/net/if_bridge.c
===================================================================
RCS file: /home/ncvs/src/sys/net/if_bridge.c,v
retrieving revision 1.79
diff -u -r1.79 if_bridge.c
--- sys/net/if_bridge.c	25 Aug 2006 20:11:56 -0000	1.79
+++ sys/net/if_bridge.c	13 Sep 2006 08:56:14 -0000
@@ -101,6 +101,7 @@
 #include <sys/sysctl.h>
 #include <vm/uma.h>
 #include <sys/module.h>
+#include <sys/priv.h>
 #include <sys/proc.h>
 #include <sys/lock.h>
 #include <sys/mutex.h>
@@ -675,7 +676,7 @@
 		}
 
 		if (bc->bc_flags & BC_F_SUSER) {
-			error = suser(td);
+			error = priv_check(td, PRIV_NET_BRIDGE);
 			if (error)
 				break;
 		}
Index: sys/net/if_gre.c
===================================================================
RCS file: /home/ncvs/src/sys/net/if_gre.c,v
retrieving revision 1.44
diff -u -r1.44 if_gre.c
--- sys/net/if_gre.c	4 Aug 2006 21:27:37 -0000	1.44
+++ sys/net/if_gre.c	13 Sep 2006 08:56:14 -0000
@@ -57,6 +57,7 @@
 #include <sys/malloc.h>
 #include <sys/module.h>
 #include <sys/mbuf.h>
+#include <sys/priv.h>
 #include <sys/protosw.h>
 #include <sys/socket.h>
 #include <sys/sockio.h>
@@ -452,6 +453,10 @@
 	case SIOCSIFDSTADDR:
 		break;
 	case SIOCSIFFLAGS:
+		/*
+		 * XXXRW: Isn't this suser() redundant to the ifnet layer
+		 * check?
+		 */
 		if ((error = suser(curthread)) != 0)
 			break;
 		if ((ifr->ifr_flags & IFF_LINK0) != 0)
@@ -464,6 +469,10 @@
 			sc->wccp_ver = WCCP_V1;
 		goto recompute;
 	case SIOCSIFMTU:
+		/*
+		 * XXXRW: Isn't this suser() redundant to the ifnet layer
+		 * check?
+		 */
 		if ((error = suser(curthread)) != 0)
 			break;
 		if (ifr->ifr_mtu < 576) {
@@ -477,6 +486,10 @@
 		break;
 	case SIOCADDMULTI:
 	case SIOCDELMULTI:
+		/*
+		 * XXXRW: Isn't this suser() redundant to the ifnet layer
+		 * check?
+		 */
 		if ((error = suser(curthread)) != 0)
 			break;
 		if (ifr == 0) {
@@ -498,6 +511,10 @@
 		}
 		break;
 	case GRESPROTO:
+		/*
+		 * XXXRW: Isn't this suser() redundant to the ifnet layer
+		 * check?
+		 */
 		if ((error = suser(curthread)) != 0)
 			break;
 		sc->g_proto = ifr->ifr_flags;
@@ -518,8 +535,9 @@
 		break;
 	case GRESADDRS:
 	case GRESADDRD:
-		if ((error = suser(curthread)) != 0)
-			break;
+		error = priv_check(curthread, PRIV_NET_GRE);
+		if (error)
+			return (error);
 		/*
 		 * set tunnel endpoints, compute a less specific route
 		 * to the remote end and mark if as up
@@ -584,6 +602,10 @@
 		ifr->ifr_addr = *sa;
 		break;
 	case SIOCSIFPHYADDR:
+		/*
+		 * XXXRW: Isn't this suser() redundant to the ifnet layer
+		 * check?
+		 */
 		if ((error = suser(curthread)) != 0)
 			break;
 		if (aifr->ifra_addr.sin_family != AF_INET ||
@@ -600,6 +622,10 @@
 		sc->g_dst = aifr->ifra_dstaddr.sin_addr;
 		goto recompute;
 	case SIOCSLIFPHYADDR:
+		/*
+		 * XXXRW: Isn't this suser() redundant to the ifnet layer
+		 * check?
+		 */
 		if ((error = suser(curthread)) != 0)
 			break;
 		if (lifr->addr.ss_family != AF_INET ||
@@ -617,6 +643,10 @@
 		    (satosin(&lifr->dstaddr))->sin_addr;
 		goto recompute;
 	case SIOCDIFPHYADDR:
+		/*
+		 * XXXRW: Isn't this suser() redundant to the ifnet layer
+		 * check?
+		 */
 		if ((error = suser(curthread)) != 0)
 			break;
 		sc->g_src.s_addr = INADDR_ANY;
Index: sys/net/if_ppp.c
===================================================================
RCS file: /home/ncvs/src/sys/net/if_ppp.c,v
retrieving revision 1.114
diff -u -r1.114 if_ppp.c
--- sys/net/if_ppp.c	9 Jul 2006 06:04:00 -0000	1.114
+++ sys/net/if_ppp.c	13 Sep 2006 08:56:14 -0000
@@ -87,6 +87,7 @@
 
 #include <sys/param.h>
 #include <sys/systm.h>
+#include <sys/priv.h>
 #include <sys/proc.h>
 #include <sys/mac.h>
 #include <sys/mbuf.h>
@@ -450,7 +451,8 @@
 	break;
 
     case PPPIOCSFLAGS:
-	if ((error = suser(td)) != 0)
+	error = priv_check(td, PRIV_NET_PPP);
+	if (error)
 	    break;
 	flags = *(int *)data & SC_MASK;
 	s = splsoftnet();
@@ -464,8 +466,9 @@
 	break;
 
     case PPPIOCSMRU:
-	if ((error = suser(td)) != 0)
-	    return (error);
+	error = priv_check(td, PRIV_NET_PPP);
+	if (error)
+		return (error);
 	mru = *(int *)data;
 	if (mru >= PPP_MRU && mru <= PPP_MAXMRU)
 	    sc->sc_mru = mru;
@@ -477,7 +480,8 @@
 
 #ifdef VJC
     case PPPIOCSMAXCID:
-	if ((error = suser(td)) != 0)
+	error = priv_check(td, PRIV_NET_PPP);
+	if (error)
 	    break;
 	if (sc->sc_comp) {
 	    s = splsoftnet();
@@ -488,14 +492,16 @@
 #endif
 
     case PPPIOCXFERUNIT:
-	if ((error = suser(td)) != 0)
+	error = priv_check(td, PRIV_NET_PPP);
+	if (error)
 	    break;
 	sc->sc_xfer = p->p_pid;
 	break;
 
 #ifdef PPP_COMPRESS
     case PPPIOCSCOMPRESS:
-	if ((error = suser(td)) != 0)
+	error = priv_check(td, PRIV_NET_PPP);
+	if (error)
 	    break;
 	odp = (struct ppp_option_data *) data;
 	nb = odp->length;
@@ -568,7 +574,8 @@
 	if (cmd == PPPIOCGNPMODE) {
 	    npi->mode = sc->sc_npmode[npx];
 	} else {
-	    if ((error = suser(td)) != 0)
+	    error = priv_check(td, PRIV_NET_PPP);
+	    if (error)
 		break;
 	    if (npi->mode != sc->sc_npmode[npx]) {
 		s = splsoftnet();
@@ -694,6 +701,10 @@
 	break;
 
     case SIOCSIFMTU:
+	/*
+	 * XXXRW: Isn't this suser() check redundant to the one at the ifnet
+	 * layer?
+	 */
 	if ((error = suser(td)) != 0)
 	    break;
 	if (ifr->ifr_mtu > PPP_MAXMTU)
Index: sys/net/if_sl.c
===================================================================
RCS file: /home/ncvs/src/sys/net/if_sl.c,v
retrieving revision 1.132
diff -u -r1.132 if_sl.c
--- sys/net/if_sl.c	2 Jun 2006 19:59:32 -0000	1.132
+++ sys/net/if_sl.c	13 Sep 2006 08:56:14 -0000
@@ -68,6 +68,7 @@
 #include <sys/systm.h>
 #include <sys/malloc.h>
 #include <sys/mbuf.h>
+#include <sys/priv.h>
 #include <sys/proc.h>
 #include <sys/socket.h>
 #include <sys/sockio.h>
@@ -366,7 +367,7 @@
 	register struct sl_softc *sc;
 	int s, error;
 
-	error = suser(curthread);
+	error = priv_check(curthread, PRIV_NET_SLIP);
 	if (error)
 		return (error);
 
Index: sys/net/if_tap.c
===================================================================
RCS file: /home/ncvs/src/sys/net/if_tap.c,v
retrieving revision 1.62
diff -u -r1.62 if_tap.c
--- sys/net/if_tap.c	15 Jul 2006 02:13:05 -0000	1.62
+++ sys/net/if_tap.c	13 Sep 2006 08:56:14 -0000
@@ -46,6 +46,7 @@
 #include <sys/mbuf.h>
 #include <sys/module.h>
 #include <sys/poll.h>
+#include <sys/priv.h>
 #include <sys/proc.h>
 #include <sys/selinfo.h>
 #include <sys/signalvar.h>
@@ -372,10 +373,13 @@
 {
 	struct tap_softc	*tp = NULL;
 	struct ifnet		*ifp = NULL;
-	int			 s;
+	int			 error, s;
 
-	if (tapuopen == 0 && suser(td) != 0)
-		return (EPERM);
+	if (tapuopen == 0) {
+		error = priv_check(td, PRIV_NET_TAP);
+		if (error)
+			return (error);
+	}
 
 	if ((dev2unit(dev) & CLONE_UNITMASK) > TAPMAXUNIT)
 		return (ENXIO);
Index: sys/net/if_tun.c
===================================================================
RCS file: /home/ncvs/src/sys/net/if_tun.c,v
retrieving revision 1.158
diff -u -r1.158 if_tun.c
--- sys/net/if_tun.c	8 Aug 2006 19:22:25 -0000	1.158
+++ sys/net/if_tun.c	13 Sep 2006 08:56:14 -0000
@@ -23,6 +23,7 @@
 #include "opt_mac.h"
 
 #include <sys/param.h>
+#include <sys/priv.h>
 #include <sys/proc.h>
 #include <sys/systm.h>
 #include <sys/mac.h>
@@ -596,9 +597,11 @@
 		tunp = (struct tuninfo *)data;
 		if (tunp->mtu < IF_MINMTU)
 			return (EINVAL);
-		if (TUN2IFP(tp)->if_mtu != tunp->mtu
-		&& (error = suser(td)) != 0)
-			return (error);
+		if (TUN2IFP(tp)->if_mtu != tunp->mtu) {
+			error = priv_check(td, PRIV_NET_SETIFMTU);
+			if (error)
+				return (error);
+		}
 		TUN2IFP(tp)->if_mtu = tunp->mtu;
 		TUN2IFP(tp)->if_type = tunp->type;
 		TUN2IFP(tp)->if_baudrate = tunp->baudrate;
Index: sys/net/ppp_tty.c
===================================================================
RCS file: /home/ncvs/src/sys/net/ppp_tty.c,v
retrieving revision 1.69
diff -u -r1.69 ppp_tty.c
--- sys/net/ppp_tty.c	16 Oct 2005 20:44:18 -0000	1.69
+++ sys/net/ppp_tty.c	13 Sep 2006 08:56:14 -0000
@@ -79,6 +79,7 @@
 
 #include <sys/param.h>
 #include <sys/systm.h>
+#include <sys/priv.h>
 #include <sys/proc.h>
 #include <sys/mbuf.h>
 #include <sys/socket.h>
@@ -179,7 +180,8 @@
     register struct ppp_softc *sc;
     int error, s;
 
-    if ((error = suser(td)) != 0)
+    error = priv_check(td, PRIV_NET_PPP);
+    if (error)
 	return (error);
 
     s = spltty();
@@ -423,7 +425,8 @@
     error = 0;
     switch (cmd) {
     case PPPIOCSASYNCMAP:
-	if ((error = suser(td)) != 0)
+	error = priv_check(td, PRIV_NET_PPP);
+	if (error)
 	    break;
 	sc->sc_asyncmap[0] = *(u_int *)data;
 	break;
@@ -433,7 +436,8 @@
 	break;
 
     case PPPIOCSRASYNCMAP:
-	if ((error = suser(td)) != 0)
+	error = priv_check(td, PRIV_NET_PPP);
+	if (error)
 	    break;
 	sc->sc_rasyncmap = *(u_int *)data;
 	break;
@@ -443,7 +447,8 @@
 	break;
 
     case PPPIOCSXASYNCMAP:
-	if ((error = suser(td)) != 0)
+	error = priv_check(td, PRIV_NET_PPP);
+	if (error)
 	    break;
 	s = spltty();
 	bcopy(data, sc->sc_asyncmap, sizeof(sc->sc_asyncmap));
Index: sys/net/raw_usrreq.c
===================================================================
RCS file: /home/ncvs/src/sys/net/raw_usrreq.c,v
retrieving revision 1.43
diff -u -r1.43 raw_usrreq.c
--- sys/net/raw_usrreq.c	21 Jul 2006 17:11:12 -0000	1.43
+++ sys/net/raw_usrreq.c	13 Sep 2006 08:56:14 -0000
@@ -36,6 +36,7 @@
 #include <sys/malloc.h>
 #include <sys/mbuf.h>
 #include <sys/mutex.h>
+#include <sys/priv.h>
 #include <sys/protosw.h>
 #include <sys/signalvar.h>
 #include <sys/socket.h>
@@ -171,8 +172,11 @@
 	 */
 	KASSERT(sotorawcb(so) != NULL, ("raw_uattach: so_pcb == NULL"));
 
-	if (td && (error = suser(td)) != 0)
-		return error;
+	if (td != NULL) {
+		error = priv_check(td, PRIV_NET_RAW);
+		if (error)
+			return error;
+	}
 	return raw_attach(so, proto);
 }
 
Index: sys/net/rtsock.c
===================================================================
RCS file: /home/ncvs/src/sys/net/rtsock.c,v
retrieving revision 1.137
diff -u -r1.137 rtsock.c
--- sys/net/rtsock.c	21 Jul 2006 17:11:12 -0000	1.137
+++ sys/net/rtsock.c	13 Sep 2006 08:56:14 -0000
@@ -36,6 +36,7 @@
 #include <sys/jail.h>
 #include <sys/malloc.h>
 #include <sys/mbuf.h>
+#include <sys/priv.h>
 #include <sys/proc.h>
 #include <sys/protosw.h>
 #include <sys/signalvar.h>
@@ -368,8 +369,11 @@
 	 * Verify that the caller has the appropriate privilege; RTM_GET
 	 * is the only operation the non-superuser is allowed.
 	 */
-	if (rtm->rtm_type != RTM_GET && (error = suser(curthread)) != 0)
-		senderr(error);
+	if (rtm->rtm_type != RTM_GET) {
+		error = priv_check(curthread, PRIV_NET_ROUTE);
+		if (error)
+			senderr(error);
+	}
 
 	switch (rtm->rtm_type) {
 		struct rtentry *saved_nrt;
Index: sys/net80211/ieee80211_ioctl.c
===================================================================
RCS file: /home/ncvs/src/sys/net80211/ieee80211_ioctl.c,v
retrieving revision 1.49
diff -u -r1.49 ieee80211_ioctl.c
--- sys/net80211/ieee80211_ioctl.c	10 Aug 2006 06:04:00 -0000	1.49
+++ sys/net80211/ieee80211_ioctl.c	13 Sep 2006 08:56:14 -0000
@@ -43,6 +43,7 @@
 #include <sys/endian.h>
 #include <sys/param.h>
 #include <sys/kernel.h>
+#include <sys/priv.h>
 #include <sys/socket.h>
 #include <sys/sockio.h>
 #include <sys/systm.h>
@@ -342,7 +343,7 @@
 	case WI_RID_DEFLT_CRYPT_KEYS:
 		keys = (struct wi_ltv_keys *)&wreq;
 		/* do not show keys to non-root user */
-		error = suser(curthread);
+		error = priv_check(curthread, PRIV_NET80211_GETKEY);
 		if (error) {
 			memset(keys, 0, sizeof(*keys));
 			error = 0;
@@ -859,7 +860,7 @@
 	ik.ik_flags = wk->wk_flags & (IEEE80211_KEY_XMIT | IEEE80211_KEY_RECV);
 	if (wk->wk_keyix == ic->ic_def_txkey)
 		ik.ik_flags |= IEEE80211_KEY_DEFAULT;
-	if (suser(curthread) == 0) {
+	if (priv_check(curthread, PRIV_NET80211_GETKEY) == 0) {
 		/* NB: only root can read key data */
 		ik.ik_keyrsc = wk->wk_keyrsc;
 		ik.ik_keytsc = wk->wk_keytsc;
@@ -1509,7 +1510,7 @@
 			return EINVAL;
 		len = (u_int) ic->ic_nw_keys[kid].wk_keylen;
 		/* NB: only root can read WEP keys */
-		if (suser(curthread) == 0) {
+		if (priv_check(curthread, PRIV_NET80211_GETKEY) == 0) {
 			bcopy(ic->ic_nw_keys[kid].wk_key, tmpkey, len);
 		} else {
 			bzero(tmpkey, len);
@@ -2691,7 +2692,7 @@
 				(struct ieee80211req *) data);
 		break;
 	case SIOCS80211:
-		error = suser(curthread);
+		error = priv_check(curthread, PRIV_NET80211_MANAGE);
 		if (error == 0)
 			error = ieee80211_ioctl_set80211(ic, cmd,
 					(struct ieee80211req *) data);
@@ -2700,7 +2701,7 @@
 		error = ieee80211_cfgget(ic, cmd, data);
 		break;
 	case SIOCSIFGENERIC:
-		error = suser(curthread);
+		error = priv_check(curthread, PRIV_NET80211_MANAGE);
 		if (error)
 			break;
 		error = ieee80211_cfgset(ic, cmd, data);
Index: sys/netatalk/at_control.c
===================================================================
RCS file: /home/ncvs/src/sys/netatalk/at_control.c,v
retrieving revision 1.44
diff -u -r1.44 at_control.c
--- sys/netatalk/at_control.c	22 Feb 2005 14:20:29 -0000	1.44
+++ sys/netatalk/at_control.c	13 Sep 2006 08:56:14 -0000
@@ -118,6 +118,8 @@
 	case SIOCSIFADDR:
 		/* 
 		 * If we are not superuser, then we don't get to do these ops.
+		 *
+		 * XXXRW: Layering?
 		 */
 		if (suser(td))
 			return (EPERM);
Index: sys/netatalk/ddp_pcb.c
===================================================================
RCS file: /home/ncvs/src/sys/netatalk/ddp_pcb.c,v
retrieving revision 1.49
diff -u -r1.49 ddp_pcb.c
--- sys/netatalk/ddp_pcb.c	2 Aug 2006 16:22:34 -0000	1.49
+++ sys/netatalk/ddp_pcb.c	13 Sep 2006 08:56:14 -0000
@@ -30,6 +30,7 @@
 #include <sys/systm.h>
 #include <sys/malloc.h>
 #include <sys/mbuf.h>
+#include <sys/priv.h>
 #include <sys/socket.h>
 #include <sys/socketvar.h>
 #include <sys/protosw.h>
@@ -100,7 +101,7 @@
 		return (EINVAL);
 	    }
 	    if (sat->sat_port < ATPORT_RESERVED &&
-		 suser(td)) {
+		    priv_check(td, PRIV_NETATALK_RESERVEDPORT)) {
 		return (EACCES);
 	    }
 	}
Index: sys/netatm/atm_usrreq.c
===================================================================
RCS file: /home/ncvs/src/sys/netatm/atm_usrreq.c,v
retrieving revision 1.27
diff -u -r1.27 atm_usrreq.c
--- sys/netatm/atm_usrreq.c	21 Jul 2006 17:11:13 -0000	1.27
+++ sys/netatm/atm_usrreq.c	13 Sep 2006 08:56:14 -0000
@@ -36,6 +36,7 @@
 #include <sys/param.h>
 #include <sys/systm.h>
 #include <sys/sockio.h>
+#include <sys/priv.h>
 #include <sys/protosw.h>
 #include <sys/socket.h>
 #include <net/if.h>
@@ -181,8 +182,11 @@
 		struct atmcfgreq	*acp = (struct atmcfgreq *)data;
 		struct atm_pif		*pip;
 
-		if (td && (suser(td) != 0))
-			ATM_RETERR(EPERM);
+		if (td != 0) {
+			err = priv_check(td, PRIV_NETATM_CFG);
+			if (err)
+				ATM_RETERR(err);
+		}
 
 		switch (acp->acr_opcode) {
 
@@ -214,8 +218,11 @@
 		struct atmaddreq	*aap = (struct atmaddreq *)data;
 		Atm_endpoint		*epp;
 
-		if (td && (suser(td) != 0))
-			ATM_RETERR(EPERM);
+		if (td != NULL) {
+			err = priv_check(td, PRIV_NETATM_ADD);
+			if (err)
+				ATM_RETERR(err);
+		}
 
 		switch (aap->aar_opcode) {
 
@@ -264,8 +271,11 @@
 		struct sigmgr		*smp;
 		Atm_endpoint		*epp;
 
-		if (td && (suser(td) != 0))
-			ATM_RETERR(EPERM);
+		if (td != NULL) {
+			err = priv_check(td, PRIV_NETATM_DEL);
+			if (err)
+				ATM_RETERR(err);
+		}
 
 		switch (adp->adr_opcode) {
 
@@ -317,8 +327,11 @@
 		struct sigmgr		*smp;
 		struct ifnet		*ifp2;
 
-		if (td && (suser(td) != 0))
-			ATM_RETERR(EPERM);
+		if (td != NULL) {
+			err = priv_check(td, PRIV_NETATM_SET);
+			if (err)
+				ATM_RETERR(err);
+		}
 
 		switch (asp->asr_opcode) {
 
Index: sys/netgraph/ng_socket.c
===================================================================
RCS file: /home/ncvs/src/sys/netgraph/ng_socket.c,v
retrieving revision 1.77
diff -u -r1.77 ng_socket.c
--- sys/netgraph/ng_socket.c	21 Jul 2006 17:11:13 -0000	1.77
+++ sys/netgraph/ng_socket.c	13 Sep 2006 08:56:14 -0000
@@ -59,6 +59,7 @@
 #include <sys/malloc.h>
 #include <sys/mbuf.h>
 #include <sys/mutex.h>
+#include <sys/priv.h>
 #include <sys/protosw.h>
 #include <sys/queue.h>
 #include <sys/signalvar.h>
@@ -178,9 +179,11 @@
 ngc_attach(struct socket *so, int proto, struct thread *td)
 {
 	struct ngpcb *const pcbp = sotongpcb(so);
+	int error;
 
-	if (suser(td))
-		return (EPERM);
+	error = priv_check(td, PRIV_NETGRAPH_CONTROL);
+	if (error)
+		return (error);
 	if (pcbp != NULL)
 		return (EISCONN);
 	return (ng_attach_cntl(so));
Index: sys/netgraph/ng_tty.c
===================================================================
RCS file: /home/ncvs/src/sys/netgraph/ng_tty.c,v
retrieving revision 1.36
diff -u -r1.36 ng_tty.c
--- sys/netgraph/ng_tty.c	16 Oct 2005 20:44:18 -0000	1.36
+++ sys/netgraph/ng_tty.c	13 Sep 2006 08:56:14 -0000
@@ -66,6 +66,7 @@
 #include <sys/kernel.h>
 #include <sys/malloc.h>
 #include <sys/mbuf.h>
+#include <sys/priv.h>
 #include <sys/socket.h>
 #include <sys/syslog.h>
 #include <sys/tty.h>
@@ -189,7 +190,8 @@
 	int error;
 
 	/* Super-user only */
-	if ((error = suser(td)))
+	error = priv_check(td, PRIV_NETGRAPH_TTY);
+	if (error)
 		return (error);
 
 	/* Initialize private struct */
Index: sys/netinet/in_pcb.c
===================================================================
RCS file: /home/ncvs/src/sys/netinet/in_pcb.c,v
retrieving revision 1.181
diff -u -r1.181 in_pcb.c
--- sys/netinet/in_pcb.c	6 Sep 2006 13:56:35 -0000	1.181
+++ sys/netinet/in_pcb.c	13 Sep 2006 08:56:14 -0000
@@ -43,6 +43,7 @@
 #include <sys/protosw.h>
 #include <sys/socket.h>
 #include <sys/socketvar.h>
+#include <sys/priv.h>
 #include <sys/proc.h>
 #include <sys/jail.h>
 #include <sys/kernel.h>
@@ -330,7 +331,8 @@
 			/* GROSS */
 			if (ntohs(lport) <= ipport_reservedhigh &&
 			    ntohs(lport) >= ipport_reservedlow &&
-			    suser_cred(cred, SUSER_ALLOWJAIL))
+			    priv_check_cred(cred, PRIV_NETINET_RESERVEDPORT,
+			    SUSER_ALLOWJAIL))
 				return (EACCES);
 			if (jailed(cred))
 				prison = 1;
@@ -399,7 +401,9 @@
 			last  = ipport_hilastauto;
 			lastport = &pcbinfo->lasthi;
 		} else if (inp->inp_flags & INP_LOWPORT) {
-			if ((error = suser_cred(cred, SUSER_ALLOWJAIL)) != 0)
+			error = priv_check_cred(cred,
+			    PRIV_NETINET_RESERVEDPORT, SUSER_ALLOWJAIL);
+			if (error)
 				return error;
 			first = ipport_lowfirstauto;	/* 1023 */
 			last  = ipport_lowlastauto;	/* 600 */
Index: sys/netinet/ip_carp.c
===================================================================
RCS file: /home/ncvs/src/sys/netinet/ip_carp.c,v
retrieving revision 1.42
diff -u -r1.42 ip_carp.c
--- sys/netinet/ip_carp.c	9 Jul 2006 06:04:01 -0000	1.42
+++ sys/netinet/ip_carp.c	13 Sep 2006 08:56:14 -0000
@@ -41,6 +41,7 @@
 #include <sys/mbuf.h>
 #include <sys/module.h>
 #include <sys/time.h>
+#include <sys/priv.h>
 #include <sys/proc.h>
 #include <sys/sysctl.h>
 #include <sys/syslog.h>
@@ -1847,7 +1848,8 @@
 		break;
 
 	case SIOCSVH:
-		if ((error = suser(curthread)) != 0)
+		error = priv_check(curthread, PRIV_NETINET_CARP);
+		if (error)
 			break;
 		if ((error = copyin(ifr->ifr_data, &carpr, sizeof carpr)))
 			break;
@@ -1922,7 +1924,8 @@
 		carpr.carpr_vhid = sc->sc_vhid;
 		carpr.carpr_advbase = sc->sc_advbase;
 		carpr.carpr_advskew = sc->sc_advskew;
-		if (suser(curthread) == 0)
+		error = priv_check(curthread, PRIV_NETINET_CARP);
+		if (error == 0)
 			bcopy(sc->sc_key, carpr.carpr_key,
 			    sizeof(carpr.carpr_key));
 		error = copyout(&carpr, ifr->ifr_data, sizeof(carpr));
Index: sys/netinet/ip_divert.c
===================================================================
RCS file: /home/ncvs/src/sys/netinet/ip_divert.c,v
retrieving revision 1.120
diff -u -r1.120 ip_divert.c
--- sys/netinet/ip_divert.c	18 Jul 2006 22:34:27 -0000	1.120
+++ sys/netinet/ip_divert.c	13 Sep 2006 08:56:14 -0000
@@ -49,6 +49,7 @@
 #include <sys/mbuf.h>
 #include <sys/module.h>
 #include <sys/kernel.h>
+#include <sys/priv.h>
 #include <sys/proc.h>
 #include <sys/protosw.h>
 #include <sys/signalvar.h>
@@ -419,8 +420,11 @@
 
 	inp  = sotoinpcb(so);
 	KASSERT(inp == NULL, ("div_attach: inp != NULL"));
-	if (td && (error = suser(td)) != 0)
-		return error;
+	if (td != NULL) {
+		error = priv_check(td, PRIV_NETINET_DIVERT);
+		if (error)
+			return (error);
+	}
 	error = soreserve(so, div_sendspace, div_recvspace);
 	if (error)
 		return error;
Index: sys/netinet/ip_fw2.c
===================================================================
RCS file: /home/ncvs/src/sys/netinet/ip_fw2.c,v
retrieving revision 1.146
diff -u -r1.146 ip_fw2.c
--- sys/netinet/ip_fw2.c	12 Sep 2006 04:25:12 -0000	1.146
+++ sys/netinet/ip_fw2.c	13 Sep 2006 08:56:14 -0000
@@ -54,6 +54,7 @@
 #include <sys/jail.h>
 #include <sys/mac.h>
 #include <sys/module.h>
+#include <sys/priv.h>
 #include <sys/proc.h>
 #include <sys/rwlock.h>
 #include <sys/socket.h>
@@ -3935,7 +3936,7 @@
 	struct ip_fw *buf, *rule;
 	u_int32_t rulenum[2];
 
-	error = suser(sopt->sopt_td);
+	error = priv_check(sopt->sopt_td, PRIV_NETINET_IPFW);
 	if (error)
 		return (error);
 
Index: sys/netinet/ip_mroute.c
===================================================================
RCS file: /home/ncvs/src/sys/netinet/ip_mroute.c,v
retrieving revision 1.118
diff -u -r1.118 ip_mroute.c
--- sys/netinet/ip_mroute.c	18 May 2006 19:51:08 -0000	1.118
+++ sys/netinet/ip_mroute.c	13 Sep 2006 08:56:14 -0000
@@ -69,6 +69,7 @@
 #include <sys/malloc.h>
 #include <sys/mbuf.h>
 #include <sys/module.h>
+#include <sys/priv.h>
 #include <sys/protosw.h>
 #include <sys/signalvar.h>
 #include <sys/socket.h>
@@ -567,7 +568,7 @@
      * Typically, only root can create the raw socket in order to execute
      * this ioctl method, however the request might be coming from a prison
      */
-    error = suser(curthread);
+    error = priv_check(curthread, PRIV_NETINET_MROUTE);
     if (error)
 	return (error);
     switch (cmd) {
Index: sys/netinet/ip_output.c
===================================================================
RCS file: /home/ncvs/src/sys/netinet/ip_output.c,v
retrieving revision 1.263
diff -u -r1.263 ip_output.c
--- sys/netinet/ip_output.c	11 Sep 2006 19:56:10 -0000	1.263
+++ sys/netinet/ip_output.c	13 Sep 2006 08:56:14 -0000
@@ -41,6 +41,7 @@
 #include <sys/mac.h>
 #include <sys/malloc.h>
 #include <sys/mbuf.h>
+#include <sys/priv.h>
 #include <sys/protosw.h>
 #include <sys/socket.h>
 #include <sys/socketvar.h>
@@ -979,8 +980,20 @@
 				break;
 			if ((error = soopt_mcopyin(sopt, m)) != 0) /* XXX */
 				break;
-			priv = (sopt->sopt_td != NULL &&
-				suser(sopt->sopt_td) != 0) ? 0 : 1;
+			if (sopt->sopt_td != NULL) {
+				/*
+				 * XXXRW: Would be more desirable to do this
+				 * one layer down so that we only exercise
+				 * privilege if it is needed.
+				 */
+				error = priv_check(sopt->sopt_td,
+				    PRIV_NETINET_IPSEC);
+				if (error)
+					priv = 0;
+				else
+					priv = 1;
+			} else
+				priv = 1;
 			req = mtod(m, caddr_t);
 			len = m->m_len;
 			optname = sopt->sopt_name;
Index: sys/netinet/raw_ip.c
===================================================================
RCS file: /home/ncvs/src/sys/netinet/raw_ip.c,v
retrieving revision 1.165
diff -u -r1.165 raw_ip.c
--- sys/netinet/raw_ip.c	6 Sep 2006 19:04:36 -0000	1.165
+++ sys/netinet/raw_ip.c	13 Sep 2006 08:56:14 -0000
@@ -41,6 +41,7 @@
 #include <sys/mac.h>
 #include <sys/malloc.h>
 #include <sys/mbuf.h>
+#include <sys/priv.h>
 #include <sys/proc.h>
 #include <sys/protosw.h>
 #include <sys/signalvar.h>
@@ -386,7 +387,11 @@
 		case IP_FW_GET:
 		case IP_FW_TABLE_GETSIZE:
 		case IP_FW_TABLE_LIST:
-			error = suser(curthread);
+			/*
+			 * XXXRW: Isn't this checked one layer down?  Yes, it
+			 * is.
+			 */
+			error = priv_check(curthread, PRIV_NETINET_IPFW);
 			if (error != 0)
 				return (error);
 			if (ip_fw_ctl_ptr != NULL)
@@ -396,7 +401,7 @@
 			break;
 
 		case IP_DUMMYNET_GET:
-			error = suser(curthread);
+			error = priv_check(curthread, PRIV_NETINET_DUMMYNET);
 			if (error != 0)
 				return (error);
 			if (ip_dn_ctl_ptr != NULL)
@@ -417,7 +422,7 @@
 		case MRT_API_CONFIG:
 		case MRT_ADD_BW_UPCALL:
 		case MRT_DEL_BW_UPCALL:
-			error = suser(curthread);
+			error = priv_check(curthread, PRIV_NETINET_MROUTE);
 			if (error != 0)
 				return (error);
 			error = ip_mrouter_get ? ip_mrouter_get(so, sopt) :
@@ -451,7 +456,10 @@
 		case IP_FW_TABLE_ADD:
 		case IP_FW_TABLE_DEL:
 		case IP_FW_TABLE_FLUSH:
-			error = suser(curthread);
+			/*
+			 * XXXRW: Isn't this checked one layer down?
+			 */
+			error = priv_check(curthread, PRIV_NETINET_IPFW);
 			if (error != 0)
 				return (error);
 			if (ip_fw_ctl_ptr != NULL)
@@ -463,7 +471,7 @@
 		case IP_DUMMYNET_CONFIGURE:
 		case IP_DUMMYNET_DEL:
 		case IP_DUMMYNET_FLUSH:
-			error = suser(curthread);
+			error = priv_check(curthread, PRIV_NETINET_DUMMYNET);
 			if (error != 0)
 				return (error);
 			if (ip_dn_ctl_ptr != NULL)
@@ -473,14 +481,14 @@
 			break ;
 
 		case IP_RSVP_ON:
-			error = suser(curthread);
+			error = priv_check(curthread, PRIV_NETINET_MROUTE);
 			if (error != 0)
 				return (error);
 			error = ip_rsvp_init(so);
 			break;
 
 		case IP_RSVP_OFF:
-			error = suser(curthread);
+			error = priv_check(curthread, PRIV_NETINET_MROUTE);
 			if (error != 0)
 				return (error);
 			error = ip_rsvp_done();
@@ -488,7 +496,7 @@
 
 		case IP_RSVP_VIF_ON:
 		case IP_RSVP_VIF_OFF:
-			error = suser(curthread);
+			error = priv_check(curthread, PRIV_NETINET_MROUTE);
 			if (error != 0)
 				return (error);
 			error = ip_rsvp_vif ?
@@ -507,7 +515,7 @@
 		case MRT_API_CONFIG:
 		case MRT_ADD_BW_UPCALL:
 		case MRT_DEL_BW_UPCALL:
-			error = suser(curthread);
+			error = priv_check(curthread, PRIV_NETINET_MROUTE);
 			if (error != 0)
 				return (error);
 			error = ip_mrouter_set ? ip_mrouter_set(so, sopt) :
@@ -597,9 +605,14 @@
 
 	inp = sotoinpcb(so);
 	KASSERT(inp == NULL, ("rip_attach: inp != NULL"));
+	/*
+	 * XXXRW: Centralize privilege decision in kern_jail.c.
+	 */
 	if (jailed(td->td_ucred) && !jail_allow_raw_sockets)
 		return (EPERM);
-	if ((error = suser_cred(td->td_ucred, SUSER_ALLOWJAIL)) != 0)
+	error = priv_check_cred(td->td_ucred, PRIV_NETINET_RAW,
+	    SUSER_ALLOWJAIL);
+	if (error)
 		return error;
 	if (proto >= IPPROTO_MAX || proto < 0)
 		return EPROTONOSUPPORT;
Index: sys/netinet/tcp_subr.c
===================================================================
RCS file: /home/ncvs/src/sys/netinet/tcp_subr.c,v
retrieving revision 1.262
diff -u -r1.262 tcp_subr.c
--- sys/netinet/tcp_subr.c	8 Sep 2006 13:09:15 -0000	1.262
+++ sys/netinet/tcp_subr.c	13 Sep 2006 08:56:14 -0000
@@ -49,6 +49,7 @@
 #ifdef INET6
 #include <sys/domain.h>
 #endif
+#include <sys/priv.h>
 #include <sys/proc.h>
 #include <sys/socket.h>
 #include <sys/socketvar.h>
@@ -1064,7 +1065,8 @@
 	struct inpcb *inp;
 	int error;
 
-	error = suser_cred(req->td->td_ucred, SUSER_ALLOWJAIL);
+	error = priv_check_cred(req->td->td_ucred, PRIV_NETINET_GETCRED,
+	    SUSER_ALLOWJAIL);
 	if (error)
 		return (error);
 	error = SYSCTL_IN(req, addrs, sizeof(addrs));
@@ -1108,7 +1110,8 @@
 	struct inpcb *inp;
 	int error, mapped = 0;
 
-	error = suser_cred(req->td->td_ucred, SUSER_ALLOWJAIL);
+	error = priv_check_cred(req->td->td_ucred, PRIV_NETINET_GETCRED,
+	    SUSER_ALLOWJAIL);
 	if (error)
 		return (error);
 	error = SYSCTL_IN(req, addrs, sizeof(addrs));
Index: sys/netinet/udp_usrreq.c
===================================================================
RCS file: /home/ncvs/src/sys/netinet/udp_usrreq.c,v
retrieving revision 1.194
diff -u -r1.194 udp_usrreq.c
--- sys/netinet/udp_usrreq.c	6 Sep 2006 19:04:36 -0000	1.194
+++ sys/netinet/udp_usrreq.c	13 Sep 2006 08:56:14 -0000
@@ -45,6 +45,7 @@
 #include <sys/mac.h>
 #include <sys/malloc.h>
 #include <sys/mbuf.h>
+#include <sys/priv.h>
 #include <sys/proc.h>
 #include <sys/protosw.h>
 #include <sys/signalvar.h>
@@ -686,7 +687,8 @@
 	struct inpcb *inp;
 	int error;
 
-	error = suser_cred(req->td->td_ucred, SUSER_ALLOWJAIL);
+	error = priv_check_cred(req->td->td_ucred, PRIV_NETINET_GETCRED,
+	    SUSER_ALLOWJAIL);
 	if (error)
 		return (error);
 	error = SYSCTL_IN(req, addrs, sizeof(addrs));
Index: sys/netinet6/in6.c
===================================================================
RCS file: /home/ncvs/src/sys/netinet6/in6.c,v
retrieving revision 1.63
diff -u -r1.63 in6.c
--- sys/netinet6/in6.c	4 Aug 2006 21:27:38 -0000	1.63
+++ sys/netinet6/in6.c	13 Sep 2006 08:56:14 -0000
@@ -71,6 +71,7 @@
 #include <sys/socketvar.h>
 #include <sys/sockio.h>
 #include <sys/systm.h>
+#include <sys/priv.h>
 #include <sys/proc.h>
 #include <sys/time.h>
 #include <sys/kernel.h>
@@ -325,12 +326,8 @@
 	struct	in6_ifreq *ifr = (struct in6_ifreq *)data;
 	struct	in6_ifaddr *ia = NULL;
 	struct	in6_aliasreq *ifra = (struct in6_aliasreq *)data;
-	int error, privileged;
 	struct sockaddr_in6 *sa6;
-
-	privileged = 0;
-	if (td == NULL || !suser(td))
-		privileged++;
+	int error;
 
 	switch (cmd) {
 	case SIOCGETSGCNT_IN6:
@@ -341,8 +338,11 @@
 	switch(cmd) {
 	case SIOCAADDRCTL_POLICY:
 	case SIOCDADDRCTL_POLICY:
-		if (!privileged)
-			return (EPERM);
+		if (td != NULL) {
+			error = priv_check(td, PRIV_NETINET_ADDRCTRL6);
+			if (error)
+				return (error);
+		}
 		return (in6_src_ioctl(cmd, data));
 	}
 
@@ -355,8 +355,11 @@
 	case SIOCSRTRFLUSH_IN6:
 	case SIOCSDEFIFACE_IN6:
 	case SIOCSIFINFO_FLAGS:
-		if (!privileged)
-			return (EPERM);
+		if (td != NULL) {
+			error = priv_check(td, PRIV_NETINET_ND6);
+			if (error)
+				return (error);
+		}
 		/* FALLTHROUGH */
 	case OSIOCGIFINFO_IN6:
 	case SIOCGIFINFO_IN6:
@@ -383,8 +386,11 @@
 
 	switch (cmd) {
 	case SIOCSSCOPE6:
-		if (!privileged)
-			return (EPERM);
+		if (td != NULL) {
+			error = priv_check(td, PRIV_NETINET_SCOPE6);
+			if (error)
+				return (error);
+		}
 		return (scope6_set(ifp,
 		    (struct scope6_id *)ifr->ifr_ifru.ifru_scope_id));
 	case SIOCGSCOPE6:
@@ -398,8 +404,15 @@
 	switch (cmd) {
 	case SIOCALIFADDR:
 	case SIOCDLIFADDR:
-		if (!privileged)
-			return (EPERM);
+		/*
+		 * XXXRW: Is this checked at another layer?  What priv to use
+		 * here?
+		 */
+		if (td != NULL) {
+			error = suser(td);
+			if (error)
+				return (error);
+		}
 		/* FALLTHROUGH */
 	case SIOCGLIFADDR:
 		return in6_lifaddr_ioctl(so, cmd, data, ifp, td);
@@ -488,8 +501,16 @@
 		if (ifra->ifra_addr.sin6_family != AF_INET6 ||
 		    ifra->ifra_addr.sin6_len != sizeof(struct sockaddr_in6))
 			return (EAFNOSUPPORT);
-		if (!privileged)
-			return (EPERM);
+
+		/*
+		 * XXXRW: Is this checked at another layer?  What priv to use
+		 * here?
+		 */
+		if (td != NULL) {
+			error = suser(td);
+			if (error)
+				return (error);
+		}
 
 		break;
 
@@ -508,8 +529,11 @@
 	    {
 		struct in6_addrlifetime *lt;
 
-		if (!privileged)
-			return (EPERM);
+		if (td != NULL) {
+			error = priv_check(td, PRIV_NETINET_ALIFETIME6);
+			if (error)
+				return (error);
+		}
 		if (ia == NULL)
 			return (EADDRNOTAVAIL);
 		/* sanity for overflow - beware unsigned */
Index: sys/netinet6/in6_pcb.c
===================================================================
RCS file: /home/ncvs/src/sys/netinet6/in6_pcb.c,v
retrieving revision 1.73
diff -u -r1.73 in6_pcb.c
--- sys/netinet6/in6_pcb.c	18 Jul 2006 22:34:27 -0000	1.73
+++ sys/netinet6/in6_pcb.c	13 Sep 2006 08:56:14 -0000
@@ -77,6 +77,7 @@
 #include <sys/sockio.h>
 #include <sys/errno.h>
 #include <sys/time.h>
+#include <sys/priv.h>
 #include <sys/proc.h>
 #include <sys/jail.h>
 
@@ -190,8 +191,12 @@
 			/* GROSS */
 			if (ntohs(lport) <= ipport_reservedhigh &&
 			    ntohs(lport) >= ipport_reservedlow &&
-			    suser_cred(cred, SUSER_ALLOWJAIL))
+			    priv_check_cred(cred, PRIV_NETINET_RESERVEDPORT,
+			    SUSER_ALLOWJAIL))
 				return (EACCES);
+			/*
+			 * XXXRW: What priv to use here?
+			 */
 			if (!IN6_IS_ADDR_MULTICAST(&sin6->sin6_addr) &&
 			    suser_cred(so->so_cred, SUSER_ALLOWJAIL) != 0) {
 				t = in6_pcblookup_local(pcbinfo,
Index: sys/netinet6/in6_src.c
===================================================================
RCS file: /home/ncvs/src/sys/netinet6/in6_src.c,v
retrieving revision 1.39
diff -u -r1.39 in6_src.c
--- sys/netinet6/in6_src.c	4 Aug 2006 21:27:38 -0000	1.39
+++ sys/netinet6/in6_src.c	13 Sep 2006 08:56:14 -0000
@@ -68,6 +68,7 @@
 #include <sys/systm.h>
 #include <sys/malloc.h>
 #include <sys/mbuf.h>
+#include <sys/priv.h>
 #include <sys/protosw.h>
 #include <sys/socket.h>
 #include <sys/socketvar.h>
@@ -772,7 +773,9 @@
 		last  = ipport_hilastauto;
 		lastport = &pcbinfo->lasthi;
 	} else if (inp->inp_flags & INP_LOWPORT) {
-		if ((error = suser_cred(cred, 0)))
+		error = priv_check_cred(cred, PRIV_NETINET_RESERVEDPORT,
+		    SUSER_ALLOWJAIL);
+		if (error)
 			return error;
 		first = ipport_lowfirstauto;	/* 1023 */
 		last  = ipport_lowlastauto;	/* 600 */
Index: sys/netinet6/ipsec.c
===================================================================
RCS file: /home/ncvs/src/sys/netinet6/ipsec.c,v
retrieving revision 1.46
diff -u -r1.46 ipsec.c
--- sys/netinet6/ipsec.c	4 Aug 2006 21:27:39 -0000	1.46
+++ sys/netinet6/ipsec.c	13 Sep 2006 08:56:14 -0000
@@ -43,6 +43,7 @@
 #include <sys/malloc.h>
 #include <sys/mbuf.h>
 #include <sys/domain.h>
+#include <sys/priv.h>
 #include <sys/protosw.h>
 #include <sys/socket.h>
 #include <sys/socketvar.h>
@@ -1221,8 +1222,14 @@
 	}
 	bzero(new, sizeof(*new));
 
-	if (so->so_cred != NULL &&
-	    suser_cred(so->so_cred, SUSER_ALLOWJAIL) == 0)
+	/*
+	 * XXXRW: Can we avoid caching the privilege decision here, and
+	 * instead cache the credential?
+	 *
+	 * XXXRW: Why is suser_allowjail set here?
+	 */
+	if (so->so_cred != NULL && priv_check_cred(so->so_cred,
+	    PRIV_NETINET_IPSEC, 0) == 0)
 		new->priv = 1;
 	else
 		new->priv = 0;
Index: sys/netinet6/udp6_usrreq.c
===================================================================
RCS file: /home/ncvs/src/sys/netinet6/udp6_usrreq.c,v
retrieving revision 1.68
diff -u -r1.68 udp6_usrreq.c
--- sys/netinet6/udp6_usrreq.c	7 Sep 2006 18:44:54 -0000	1.68
+++ sys/netinet6/udp6_usrreq.c	13 Sep 2006 08:56:14 -0000
@@ -70,6 +70,7 @@
 #include <sys/kernel.h>
 #include <sys/lock.h>
 #include <sys/mbuf.h>
+#include <sys/priv.h>
 #include <sys/proc.h>
 #include <sys/protosw.h>
 #include <sys/signalvar.h>
@@ -434,7 +435,8 @@
 	struct inpcb *inp;
 	int error;
 
-	error = suser(req->td);
+	error = priv_check_cred(req->td->td_ucred, PRIV_NETINET_GETCRED,
+	    SUSER_ALLOWJAIL);
 	if (error)
 		return (error);
 
Index: sys/netipsec/ipsec_osdep.h
===================================================================
RCS file: /home/ncvs/src/sys/netipsec/ipsec_osdep.h,v
retrieving revision 1.3
diff -u -r1.3 ipsec_osdep.h
--- sys/netipsec/ipsec_osdep.h	27 Jun 2006 11:41:21 -0000	1.3
+++ sys/netipsec/ipsec_osdep.h	13 Sep 2006 08:56:14 -0000
@@ -215,11 +215,13 @@
  * NetBSD (1.6N) tests (so)->so_uid == 0).
  * This difference is wrapped inside  the IPSEC_PRIVILEGED_SO() macro.
  *
+ * XXXRW: Why was this suser_allowjail?
  */
 #ifdef __FreeBSD__ 
 #define IPSEC_IS_PRIVILEGED_SO(_so) \
 	((_so)->so_cred != NULL && \
-	 suser_cred((_so)->so_cred, SUSER_ALLOWJAIL) == 0)
+	 priv_check_cred((_so)->so_cred, PRIV_NETINET_IPSEC, 0) \
+	 == 0)
 #endif	/* __FreeBSD__ */
 
 #ifdef __NetBSD__
Index: sys/netipx/ipx_pcb.c
===================================================================
RCS file: /home/ncvs/src/sys/netipx/ipx_pcb.c,v
retrieving revision 1.45
diff -u -r1.45 ipx_pcb.c
--- sys/netipx/ipx_pcb.c	25 Mar 2006 17:28:42 -0000	1.45
+++ sys/netipx/ipx_pcb.c	13 Sep 2006 08:56:14 -0000
@@ -42,6 +42,7 @@
 #include <sys/param.h>
 #include <sys/systm.h>
 #include <sys/malloc.h>
+#include <sys/priv.h>
 #include <sys/socket.h>
 #include <sys/socketvar.h>
 
@@ -107,11 +108,10 @@
 	lport = sipx->sipx_port;
 	if (lport) {
 		u_short aport = ntohs(lport);
-		int error;
 
-		if (aport < IPXPORT_RESERVED &&
-		    td != NULL && (error = suser(td)) != 0)
-			return (error);
+		if (aport < IPXPORT_RESERVED && td != NULL &&
+		    priv_check(td, PRIV_NETIPX_RESERVEDPORT))
+			return (EACCES);
 		if (ipx_pcblookup(&zeroipx_addr, lport, 0))
 			return (EADDRINUSE);
 	}
Index: sys/netipx/ipx_usrreq.c
===================================================================
RCS file: /home/ncvs/src/sys/netipx/ipx_usrreq.c,v
retrieving revision 1.57
diff -u -r1.57 ipx_usrreq.c
--- sys/netipx/ipx_usrreq.c	21 Jul 2006 17:11:14 -0000	1.57
+++ sys/netipx/ipx_usrreq.c	13 Sep 2006 08:56:14 -0000
@@ -45,6 +45,7 @@
 #include <sys/kernel.h>
 #include <sys/lock.h>
 #include <sys/mbuf.h>
+#include <sys/priv.h>
 #include <sys/protosw.h>
 #include <sys/signalvar.h>
 #include <sys/socket.h>
@@ -658,8 +659,13 @@
 	struct ipxpcb *ipxp = sotoipxpcb(so);
 
 	KASSERT(ipxp == NULL, ("ripx_attach: ipxp != NULL"));
-	if (td != NULL && (error = suser(td)) != 0)
-		return (error);
+
+	if (td != NULL) {
+		error = priv_check(td, PRIV_NETIPX_RAW);
+		if (error)
+			return (error);
+	}
+
 	/*
 	 * We hold the IPX list lock for the duration as address parameters
 	 * of the IPX pcb are changed.  Since no one else holds a reference
Index: sys/netncp/ncp_conn.c
===================================================================
RCS file: /home/ncvs/src/sys/netncp/ncp_conn.c,v
retrieving revision 1.28
diff -u -r1.28 ncp_conn.c
--- sys/netncp/ncp_conn.c	14 Jan 2006 11:40:32 -0000	1.28
+++ sys/netncp/ncp_conn.c	13 Sep 2006 08:56:14 -0000
@@ -39,6 +39,7 @@
 #include <sys/systm.h>
 #include <sys/kernel.h>
 #include <sys/malloc.h>
+#include <sys/priv.h>
 #include <sys/proc.h>
 #include <sys/lock.h>
 #include <sys/sysctl.h>
Index: sys/netncp/ncp_mod.c
===================================================================
RCS file: /home/ncvs/src/sys/netncp/ncp_mod.c,v
retrieving revision 1.15
diff -u -r1.15 ncp_mod.c
--- sys/netncp/ncp_mod.c	7 Jan 2005 01:45:48 -0000	1.15
+++ sys/netncp/ncp_mod.c	13 Sep 2006 08:56:14 -0000
@@ -37,6 +37,7 @@
 #include <sys/param.h>
 #include <sys/systm.h>
 #include <sys/conf.h>
+#include <sys/priv.h>
 #include <sys/proc.h>
 #include <sys/kernel.h>
 #include <sys/module.h>
Index: sys/netncp/ncp_subr.h
===================================================================
RCS file: /home/ncvs/src/sys/netncp/ncp_subr.h,v
retrieving revision 1.9
diff -u -r1.9 ncp_subr.h
--- sys/netncp/ncp_subr.h	7 Jan 2005 01:45:49 -0000	1.9
+++ sys/netncp/ncp_subr.h	13 Sep 2006 08:56:14 -0000
@@ -84,7 +84,7 @@
 
 #define checkbad(fn) {error=(fn);if(error) goto bad;}
 
-#define	ncp_suser(cred)	suser_cred(cred, 0)
+#define	ncp_suser(cred)	priv_check_cred(cred, PRIV_NETNCP, 0)
 
 #define ncp_isowner(conn,cred) ((cred)->cr_uid == (conn)->nc_owner->cr_uid)
 
Index: sys/netsmb/smb_conn.c
===================================================================
RCS file: /home/ncvs/src/sys/netsmb/smb_conn.c,v
retrieving revision 1.17
diff -u -r1.17 smb_conn.c
--- sys/netsmb/smb_conn.c	17 Jul 2006 16:12:59 -0000	1.17
+++ sys/netsmb/smb_conn.c	13 Sep 2006 08:56:14 -0000
@@ -41,6 +41,7 @@
 #include <sys/systm.h>
 #include <sys/kernel.h>
 #include <sys/malloc.h>
+#include <sys/priv.h>
 #include <sys/proc.h>
 #include <sys/lock.h>
 #include <sys/sysctl.h>
Index: sys/netsmb/smb_subr.h
===================================================================
RCS file: /home/ncvs/src/sys/netsmb/smb_subr.h,v
retrieving revision 1.12
diff -u -r1.12 smb_subr.h
--- sys/netsmb/smb_subr.h	7 Jan 2005 01:45:49 -0000	1.12
+++ sys/netsmb/smb_subr.h	13 Sep 2006 08:56:14 -0000
@@ -68,7 +68,7 @@
 	 SIGISMEMBER(set, SIGHUP) || SIGISMEMBER(set, SIGKILL) ||	\
 	 SIGISMEMBER(set, SIGQUIT))
 
-#define	smb_suser(cred)	suser_cred(cred, 0)
+#define	smb_suser(cred)	priv_check_cred(cred, PRIV_NETSMB, 0)
 
 /*
  * Compatibility wrappers for simple locks
Index: sys/nfsserver/nfs_syscalls.c
===================================================================
RCS file: /home/ncvs/src/sys/nfsserver/nfs_syscalls.c,v
retrieving revision 1.106
diff -u -r1.106 nfs_syscalls.c
--- sys/nfsserver/nfs_syscalls.c	1 Aug 2006 15:32:25 -0000	1.106
+++ sys/nfsserver/nfs_syscalls.c	13 Sep 2006 08:56:14 -0000
@@ -49,6 +49,7 @@
 #include <sys/mac.h>
 #include <sys/malloc.h>
 #include <sys/mount.h>
+#include <sys/priv.h>
 #include <sys/proc.h>
 #include <sys/bio.h>
 #include <sys/buf.h>
@@ -141,7 +142,7 @@
 	if (error)
 		return (error);
 #endif
-	error = suser(td);
+	error = priv_check(td, PRIV_NFSD);
 	if (error)
 		return (error);
 	NET_LOCK_GIANT();
Index: sys/pc98/cbus/fdc.c
===================================================================
RCS file: /home/ncvs/src/sys/pc98/cbus/fdc.c,v
retrieving revision 1.167
diff -u -r1.167 fdc.c
--- sys/pc98/cbus/fdc.c	8 Sep 2006 21:46:01 -0000	1.167
+++ sys/pc98/cbus/fdc.c	13 Sep 2006 08:56:14 -0000
@@ -68,6 +68,7 @@
 #include <sys/malloc.h>
 #include <sys/module.h>
 #include <sys/mutex.h>
+#include <sys/priv.h>
 #include <sys/proc.h>
 #include <sys/rman.h>
 #include <sys/systm.h>
@@ -2512,7 +2513,7 @@
 #endif
 
 	case FD_CLRERR:
-		if (suser(td) != 0)
+		if (priv_check(td, PRIV_DRIVER) != 0)
 			return (EPERM);
 		fd->fdc->fdc_errs = 0;
 		return (0);
@@ -2556,7 +2557,7 @@
 
 	case FD_STYPE:                  /* set drive type */
 		/* this is considered harmful; only allow for superuser */
-		if (suser(td) != 0)
+		if (priv_check(td, PRIV_DRIVER) != 0)
 			return (EPERM);
 		*fd->ft = *(struct fd_type *)addr;
 		break;
@@ -2580,7 +2581,7 @@
 #endif
 
 	case FD_CLRERR:
-		if (suser(td) != 0)
+		if (priv_check(td, PRIV_DRIVER) != 0)
 			return (EPERM);
 		fd->fdc->fdc_errs = 0;
 		break;
Index: sys/posix4/p1003_1b.c
===================================================================
RCS file: /home/ncvs/src/sys/posix4/p1003_1b.c,v
retrieving revision 1.30
diff -u -r1.30 p1003_1b.c
--- sys/posix4/p1003_1b.c	13 Jul 2006 06:41:26 -0000	1.30
+++ sys/posix4/p1003_1b.c	13 Sep 2006 08:56:14 -0000
@@ -44,6 +44,7 @@
 #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 @@
 	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)
Index: sys/security/audit/audit.c
===================================================================
RCS file: /home/ncvs/src/sys/security/audit/audit.c,v
retrieving revision 1.19
diff -u -r1.19 audit.c
--- sys/security/audit/audit.c	9 Sep 2006 10:23:00 -0000	1.19
+++ sys/security/audit/audit.c	13 Sep 2006 08:56:14 -0000
@@ -42,6 +42,7 @@
 #include <sys/malloc.h>
 #include <sys/mount.h>
 #include <sys/namei.h>
+#include <sys/priv.h>
 #include <sys/proc.h>
 #include <sys/queue.h>
 #include <sys/socket.h>
@@ -511,7 +512,8 @@
 		 * audit record is still required for this event by
 		 * re-calling au_preselect().
 		 */
-		if (audit_in_failure && suser(td) != 0) {
+		if (audit_in_failure &&
+		    priv_check(td, PRIV_AUDIT_FAILSTOP) != 0) {
 			cv_wait(&audit_fail_cv, &audit_mtx);
 			panic("audit_failing_stop: thread continued");
 		}
Index: sys/security/audit/audit_pipe.c
===================================================================
RCS file: /home/ncvs/src/sys/security/audit/audit_pipe.c,v
retrieving revision 1.9
diff -u -r1.9 audit_pipe.c
--- sys/security/audit/audit_pipe.c	26 Aug 2006 17:59:31 -0000	1.9
+++ sys/security/audit/audit_pipe.c	13 Sep 2006 08:56:14 -0000
@@ -626,9 +626,9 @@
 }
 
 /*
- * Audit pipe open method.  Explicit suser check isn't used as this allows
- * file permissions on the special device to be used to grant audit review
- * access.
+ * Audit pipe open method.  Explicit privilege check isn't used as this
+ * allows file permissions on the special device to be used to grant audit
+ * review access.  Those file permissions should be managed carefully.
  */
 static int
 audit_pipe_open(struct cdev *dev, int oflags, int devtype, struct thread *td)
Index: sys/security/audit/audit_syscalls.c
===================================================================
RCS file: /home/ncvs/src/sys/security/audit/audit_syscalls.c,v
retrieving revision 1.5
diff -u -r1.5 audit_syscalls.c
--- sys/security/audit/audit_syscalls.c	1 Sep 2006 11:45:40 -0000	1.5
+++ sys/security/audit/audit_syscalls.c	13 Sep 2006 08:56:14 -0000
@@ -32,6 +32,7 @@
 #include <sys/param.h>
 #include <sys/mount.h>
 #include <sys/namei.h>
+#include <sys/priv.h>
 #include <sys/proc.h>
 #include <sys/sysproto.h>
 #include <sys/systm.h>
@@ -63,7 +64,7 @@
 	void * rec;
 	struct kaudit_record *ar;
 
-	error = suser(td);
+	error = priv_check(td, PRIV_AUDIT_SUBMIT);
 	if (error)
 		return (error);
 
@@ -143,7 +144,7 @@
 	struct proc *tp;
 
 	AUDIT_ARG(cmd, uap->cmd);
-	error = suser(td);
+	error = priv_check(td, PRIV_AUDIT_CONTROL);
 	if (error)
 		return (error);
 
@@ -389,7 +390,7 @@
 	int error;
 	au_id_t id;
 
-	error = suser(td);
+	error = priv_check(td, PRIV_AUDIT_GETAUDIT);
 	if (error)
 		return (error);
 
@@ -411,7 +412,7 @@
 	int error;
 	au_id_t id;
 
-	error = suser(td);
+	error = priv_check(td, PRIV_AUDIT_SETAUDIT);
 	if (error)
 		return (error);
 
@@ -449,7 +450,7 @@
 	struct auditinfo ai;
 	int error;
 
-	error = suser(td);
+	error = priv_check(td, PRIV_AUDIT_GETAUDIT);
 	if (error)
 		return (error);
 
@@ -468,7 +469,7 @@
 	struct auditinfo ai;
 	int error;
 
-	error = suser(td);
+	error = priv_check(td, PRIV_AUDIT_SETAUDIT);
 	if (error)
 		return (error);
 
@@ -495,7 +496,7 @@
 {
 	int error;
 
-	error = suser(td);
+	error = priv_check(td, PRIV_AUDIT_GETAUDIT);
 	if (error)
 		return (error);
 	return (ENOSYS);
@@ -508,7 +509,7 @@
 {
 	int error;
 
-	error = suser(td);
+	error = priv_check(td, PRIV_AUDIT_SETAUDIT);
 	if (error)
 		return (error);
 	return (ENOSYS);
@@ -530,7 +531,7 @@
 	int error = 0;
 	int flags, vfslocked;
 
-	error = suser(td);
+	error = priv_check(td, PRIV_AUDIT_CONTROL);
 	if (error)
 		return (error);
 
Index: sys/security/mac/mac_internal.h
===================================================================
RCS file: /home/ncvs/src/sys/security/mac/mac_internal.h,v
retrieving revision 1.112
diff -u -r1.112 mac_internal.h
--- sys/security/mac/mac_internal.h	22 Oct 2004 11:07:18 -0000	1.112
+++ sys/security/mac/mac_internal.h	13 Sep 2006 08:56:14 -0000
@@ -2,6 +2,7 @@
  * Copyright (c) 1999-2002 Robert N. M. Watson
  * Copyright (c) 2001 Ilmar S. Habibulin
  * Copyright (c) 2001-2004 Networks Associates Technology, Inc.
+ * Copyright (c) 2006 nCircle Network Security, Inc.
  * All rights reserved.
  *
  * This software was developed by Robert Watson and Ilmar Habibulin for the
@@ -12,6 +13,9 @@
  * Associates, Inc. under DARPA/SPAWAR contract N66001-01-C-8035 ("CBOSS"),
  * as part of the DARPA CHATS research program.
  *
+ * 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:
@@ -40,7 +44,6 @@
  * MAC Framework sysctl namespace.
  */
 #ifdef SYSCTL_DECL
-SYSCTL_DECL(_security);
 SYSCTL_DECL(_security_mac);
 #ifdef MAC_DEBUG
 SYSCTL_DECL(_security_mac_debug);
@@ -169,6 +172,36 @@
 } while (0)
 
 /*
+ * MAC_GRANT performs the designated check by walking the policy module
+ * list and checking with each as to how it feels about the request.  Unlike
+ * MAC_CHECK, it grants if any policies return '0', and otherwise returns
+ * EPERM.  Note that it returns its value via 'error' in the scope of the
+ * caller.
+ */
+#define	MAC_GRANT(check, args...) do {					\
+	struct mac_policy_conf *mpc;					\
+	int entrycount;							\
+									\
+	error = EPERM;							\
+	LIST_FOREACH(mpc, &mac_static_policy_list, mpc_list) {		\
+		if (mpc->mpc_ops->mpo_ ## check != NULL) {		\
+			if (mpc->mpc_ops->mpo_ ## check(args) == 0)	\
+				error = 0;				\
+		}							\
+	}								\
+	if ((entrycount = mac_policy_list_conditional_busy()) != 0) {	\
+		LIST_FOREACH(mpc, &mac_policy_list, mpc_list) {		\
+			if (mpc->mpc_ops->mpo_ ## check != NULL) {	\
+				if (mpc->mpc_ops->mpo_ ## check (args)	\
+				    == 0)				\
+					error = 0;			\
+			}						\
+		}							\
+		mac_policy_list_unbusy();				\
+	}								\
+} while (0)
+
+/*
  * MAC_BOOLEAN performs the designated boolean composition by walking
  * the module list, invoking each instance of the operation, and
  * combining the results using the passed C operator.  Note that it
Index: sys/security/mac/mac_net.c
===================================================================
RCS file: /home/ncvs/src/sys/security/mac/mac_net.c,v
retrieving revision 1.117
diff -u -r1.117 mac_net.c
--- sys/security/mac/mac_net.c	5 Jul 2005 23:39:50 -0000	1.117
+++ sys/security/mac/mac_net.c	13 Sep 2006 08:56:14 -0000
@@ -45,6 +45,7 @@
 #include <sys/malloc.h>
 #include <sys/mutex.h>
 #include <sys/mac.h>
+#include <sys/priv.h>
 #include <sys/sbuf.h>
 #include <sys/systm.h>
 #include <sys/mount.h>
@@ -487,11 +488,11 @@
 	}
 
 	/*
-	 * XXX: Note that this is a redundant privilege check, since
-	 * policies impose this check themselves if required by the
-	 * policy.  Eventually, this should go away.
+	 * XXX: Note that this is a redundant privilege check, since policies
+	 * impose this check themselves if required by the policy.
+	 * Eventually, this should go away.
 	 */
-	error = suser_cred(cred, 0);
+	error = priv_check_cred(cred, PRIV_NET_SETIFMAC, 0);
 	if (error) {
 		mac_ifnet_label_free(intlabel);
 		return (error);
Index: sys/security/mac/mac_priv.c
===================================================================
RCS file: sys/security/mac/mac_priv.c
diff -N sys/security/mac/mac_priv.c
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ sys/security/mac/mac_priv.c	13 Sep 2006 13:46:32 -0000
@@ -0,0 +1,64 @@
+/*-
+ * 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:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR, NCIRCLE NETWORK SECURITY,
+ * INC., OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
+ * TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
+ * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+ * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * $FreeBSD$
+ */
+
+/*
+ * MAC checks for system privileges.
+ */
+
+#include "opt_mac.h"
+
+#include <sys/param.h>
+#include <sys/priv.h>
+#include <sys/module.h>
+#include <sys/mac.h>
+#include <sys/mac_policy.h>
+
+#include <security/mac/mac_internal.h>
+
+int
+mac_priv_check(struct ucred *cred, enum priv priv)
+{
+	int error;
+
+	MAC_CHECK(priv_check, cred, priv);
+
+	return (error);
+}
+
+int
+mac_priv_grant(struct ucred *cred, enum priv priv)
+{
+	int error;
+
+	MAC_GRANT(priv_grant, cred, priv);
+
+	return (error);
+}
Index: sys/security/mac_bsdextended/mac_bsdextended.c
===================================================================
RCS file: /home/ncvs/src/sys/security/mac_bsdextended/mac_bsdextended.c,v
retrieving revision 1.29
diff -u -r1.29 mac_bsdextended.c
--- sys/security/mac_bsdextended/mac_bsdextended.c	23 Apr 2006 17:06:18 -0000	1.29
+++ sys/security/mac_bsdextended/mac_bsdextended.c	13 Sep 2006 08:56:14 -0000
@@ -456,6 +456,9 @@
 {
 	int error, i;
 
+	/*
+	 * XXXRW: More specific privilege selection needed?
+	 */
 	if (suser_cred(cred, 0) == 0)
 		return (0);
 
Index: sys/security/mac_lomac/mac_lomac.c
===================================================================
RCS file: /home/ncvs/src/sys/security/mac_lomac/mac_lomac.c,v
retrieving revision 1.40
diff -u -r1.40 mac_lomac.c
--- sys/security/mac_lomac/mac_lomac.c	12 Sep 2006 04:25:12 -0000	1.40
+++ sys/security/mac_lomac/mac_lomac.c	13 Sep 2006 08:56:14 -0000
@@ -49,6 +49,7 @@
 #include <sys/malloc.h>
 #include <sys/mman.h>
 #include <sys/mount.h>
+#include <sys/priv.h>
 #include <sys/proc.h>
 #include <sys/sbuf.h>
 #include <sys/systm.h>
@@ -1697,8 +1698,10 @@
 		 * Rely on the traditional superuser status for the LOMAC
 		 * interface relabel requirements.  XXXMAC: This will go
 		 * away.
+		 *
+		 * XXXRW: This is also redundant to a higher layer check.
 		 */
-		error = suser_cred(cred, 0);
+		error = priv_check_cred(cred, PRIV_NET_SETIFMAC, 0);
 		if (error)
 			return (EPERM);
 
Index: sys/security/mac_partition/mac_partition.c
===================================================================
RCS file: /home/ncvs/src/sys/security/mac_partition/mac_partition.c,v
retrieving revision 1.11
diff -u -r1.11 mac_partition.c
--- sys/security/mac_partition/mac_partition.c	19 Sep 2005 18:52:50 -0000	1.11
+++ sys/security/mac_partition/mac_partition.c	13 Sep 2006 08:56:14 -0000
@@ -45,6 +45,7 @@
 #include <sys/kernel.h>
 #include <sys/mac.h>
 #include <sys/mount.h>
+#include <sys/priv.h>
 #include <sys/proc.h>
 #include <sys/sbuf.h>
 #include <sys/systm.h>
@@ -191,7 +192,7 @@
 		 * in a partition in the first place, but this didn't
 		 * interact well with sendmail.
 		 */
-		error = suser_cred(cred, 0);
+		error = priv_check_cred(cred, PRIV_MAC_PARTITION, 0);
 	}
 
 	return (error);
Index: sys/security/mac_portacl/mac_portacl.c
===================================================================
RCS file: /home/ncvs/src/sys/security/mac_portacl/mac_portacl.c,v
retrieving revision 1.8
diff -u -r1.8 mac_portacl.c
--- sys/security/mac_portacl/mac_portacl.c	31 Oct 2005 15:41:28 -0000	1.8
+++ sys/security/mac_portacl/mac_portacl.c	13 Sep 2006 08:56:14 -0000
@@ -66,6 +66,7 @@
 #include <sys/malloc.h>
 #include <sys/mount.h>
 #include <sys/mutex.h>
+#include <sys/priv.h>
 #include <sys/proc.h>
 #include <sys/protosw.h>
 #include <sys/queue.h>
@@ -427,7 +428,8 @@
 	mtx_unlock(&rule_mtx);
 
 	if (error != 0 && mac_portacl_suser_exempt != 0)
-		error = suser_cred(cred, 0);
+		error = priv_check_cred(cred, PRIV_NETINET_RESERVEDPORT,
+		    SUSER_ALLOWJAIL);
 
 	return (error);
 }
Index: sys/security/mac_seeotheruids/mac_seeotheruids.c
===================================================================
RCS file: /home/ncvs/src/sys/security/mac_seeotheruids/mac_seeotheruids.c,v
retrieving revision 1.8
diff -u -r1.8 mac_seeotheruids.c
--- sys/security/mac_seeotheruids/mac_seeotheruids.c	30 Sep 2005 23:41:10 -0000	1.8
+++ sys/security/mac_seeotheruids/mac_seeotheruids.c	13 Sep 2006 08:56:14 -0000
@@ -46,6 +46,7 @@
 #include <sys/kernel.h>
 #include <sys/mac.h>
 #include <sys/mount.h>
+#include <sys/priv.h>
 #include <sys/proc.h>
 #include <sys/systm.h>
 #include <sys/sysproto.h>
@@ -126,7 +127,7 @@
 		return (0);
 
 	if (suser_privileged) {
-		if (suser_cred(u1, 0) == 0)
+		if (priv_check_cred(u1, PRIV_SEEOTHERUIDS, 0) == 0)
 			return (0);
 	}
 
Index: sys/sys/jail.h
===================================================================
RCS file: /home/ncvs/src/sys/sys/jail.h,v
retrieving revision 1.26
diff -u -r1.26 jail.h
--- sys/sys/jail.h	9 Jun 2005 18:49:19 -0000	1.26
+++ sys/sys/jail.h	13 Sep 2006 08:56:14 -0000
@@ -40,6 +40,7 @@
 #include <sys/_lock.h>
 #include <sys/_mutex.h>
 #include <sys/_task.h>
+#include <sys/priv.h>
 
 #define JAIL_MAX	999999
 
@@ -110,6 +111,7 @@
 void prison_hold(struct prison *pr);
 int prison_if(struct ucred *cred, struct sockaddr *sa);
 int prison_ip(struct ucred *cred, int flag, u_int32_t *ip);
+int prison_priv_check(struct ucred *cred, enum priv priv);
 void prison_remote_ip(struct ucred *cred, int flags, u_int32_t *ip);
 
 #endif /* _KERNEL */
Index: sys/sys/mac.h
===================================================================
RCS file: /home/ncvs/src/sys/sys/mac.h,v
retrieving revision 1.71
diff -u -r1.71 mac.h
--- sys/sys/mac.h	12 Sep 2006 04:25:13 -0000	1.71
+++ sys/sys/mac.h	13 Sep 2006 08:56:14 -0000
@@ -47,8 +47,6 @@
 #ifndef _SYS_MAC_H_
 #define	_SYS_MAC_H_
 
-#include <sys/_label.h>
-
 #ifndef _POSIX_MAC
 #define	_POSIX_MAC
 #endif
@@ -107,6 +105,9 @@
 
 #else /* _KERNEL */
 
+#include <sys/_label.h>
+#include <sys/priv.h>		/* XXXRW: Until name space issues resolved. */
+
 /*
  * Kernel functions to manage and evaluate labels.
  */
@@ -465,6 +466,8 @@
 	    struct label *label);
 void	mac_cred_mmapped_drop_perms(struct thread *td, struct ucred *cred);
 void	mac_associate_nfsd_label(struct ucred *cred);
+int	mac_priv_check(struct ucred *cred, enum priv priv);
+int	mac_priv_grant(struct ucred *cred, enum priv priv);
 
 /*
  * Calls to help various file systems implement labeling functionality
Index: sys/sys/mac_policy.h
===================================================================
RCS file: /home/ncvs/src/sys/sys/mac_policy.h,v
retrieving revision 1.75
diff -u -r1.75 mac_policy.h
--- sys/sys/mac_policy.h	12 Sep 2006 04:25:13 -0000	1.75
+++ sys/sys/mac_policy.h	13 Sep 2006 08:57:21 -0000
@@ -593,6 +593,8 @@
 		    struct ucred *file_cred, struct vnode *vp,
 		    struct label *label);
 typedef void	(*mpo_associate_nfsd_label_t)(struct ucred *cred);
+typedef int	(*mpo_priv_check_t)(struct ucred *cred, enum priv priv);
+typedef int	(*mpo_priv_grant_t)(struct ucred *cred, enum priv priv);
 
 struct mac_policy_ops {
 	/*
@@ -883,6 +885,8 @@
 	mpo_check_vnode_write_t			mpo_check_vnode_write;
 	mpo_associate_nfsd_label_t		mpo_associate_nfsd_label;
 	mpo_create_mbuf_from_firewall_t		mpo_create_mbuf_from_firewall;
+	mpo_priv_check_t			mpo_priv_check;
+	mpo_priv_grant_t			mpo_priv_grant;  
 };
 
 /*
Index: sys/sys/priv.h
===================================================================
RCS file: sys/sys/priv.h
diff -N sys/sys/priv.h
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ sys/sys/priv.h	13 Sep 2006 08:59:50 -0000
@@ -0,0 +1,309 @@
+/*-
+ * 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:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR, NCIRCLE NETWORK SECURITY,
+ * INC., OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
+ * TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
+ * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+ * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * $FreeBSD$
+ */
+
+/*
+ * Privilege checking interface for BSD kernel.
+ */
+#ifndef _SYS_PRIV_H_
+#define	_SYS_PRIV_H_
+
+/*
+ * Privilege list.  In no particular order.
+ *
+ * Think carefully before adding or reusing one of these privileges -- are
+ * there existing instances referring to the same privilege?  Third party
+ * vendors may request the assignment of privileges to be used in loadable
+ * modules.  Particular numeric privilege assignments are part of the
+ * loadable kernel module ABI, and should not be changed across minor
+ * releases.
+ *
+ * When adding a new privilege, remember to determine if it's appropriate for
+ * use in jail, and update the privilege switch in kern_jail.c as necessary.
+ */
+enum priv {
+	/* Track beginning of privilege list. */
+	_PRIV_LOWEST,
+
+	/*
+	 * PRIV_ROOT is a catch-all for as yet unnamed privileges.  No new
+	 * references to this privilege should be added.
+	 */
+	PRIV_ROOT,		/* Catch-all during development. */
+
+	/*
+	 * The remaining privileges typically correspond to one or a small
+	 * number of specific privilege checks, and have (relatively) precise
+	 * meanings.  They are loosely sorted into a set of base system
+	 * privileges, such as the ability to reboot, and then loosely by
+	 * subsystem, indicated by a subsystem name.
+	 */
+	PRIV_ACCT,		/* Manage process accounting. */
+	PRIV_MAXFILES,		/* Exceed system open files limit. */
+	PRIV_MAXPROC,		/* Exceed system processes limit. */
+	PRIV_KTRACE,		/* Set/accept KTRFAC_ROOT on ktrace. */
+	PRIV_SETDUMPER,		/* Configure dump device (XXX: needs work). */
+	PRIV_NFSD,		/* Can become NFS daemon. */
+	PRIV_REBOOT,		/* Can reboot system. */
+	PRIV_SWAPON,		/* Can swapon(). */
+	PRIV_SWAPOFF,		/* Can swapoff(). */
+	PRIV_MSGBUF,		/* Can read kernel message buffer. */
+	PRIV_WITNESS,		/* Can configure WITNESS. */
+	PRIV_IO,		/* Can perform low-level I/O. */
+	PRIV_KEYBOARD,		/* Reprogram keyboard. */
+	PRIV_DRIVER,		/* Low-level driver privilege. */
+	PRIV_ADJTIME,		/* Set time adjustment. */
+	PRIV_NTP_ADJTIME,	/* Set NTP time adjustment. */
+	PRIV_CLOCK_SETTIME,	/* Can call clock_settime. */
+	PRIV_SETTIMEOFDAY,	/* Can call settimeofday. */
+	PRIV_SETHOSTID,		/* Can call sethostid. */
+	PRIV_SETDOMAINNAME,	/* Can call setdomainname. */
+	PRIV_AUDIT_CONTROL,	/* Can configure audit. */
+	PRIV_AUDIT_FAILSTOP,	/* Can run during audit fail stop. */
+	PRIV_AUDIT_GETAUDIT,	/* Can get proc audit properties. */
+	PRIV_AUDIT_SETAUDIT,	/* Can set proc audit properties. */
+	PRIV_AUDIT_SUBMIT,	/* Can submit an audit record. */
+	PRIV_CRED_SETUID,	/* setuid. */
+	PRIV_CRED_SETEUID,	/* seteuid to !ruid and !svuid. */
+	PRIV_CRED_SETGID,	/* setgid. */
+	PRIV_CRED_SETEGID,	/* setgid to !rgid and !svgid. */
+	PRIV_CRED_SETGROUPS,	/* Set process additional groups. */
+	PRIV_CRED_SETREUID,	/* setreuid. */
+	PRIV_CRED_SETREGID,	/* setregid. */
+	PRIV_CRED_SETRESUID,	/* setresuid. */
+	PRIV_CRED_SETRESGID,	/* setresgid. */
+	PRIV_SEEOTHERGIDS,	/* Exempt bsd.seeothergids. */
+	PRIV_SEEOTHERUIDS,	/* Exempt bsd.seeotheruids. */
+	PRIV_DEBUG_DIFFCRED,	/* Exempt debugging other users. */
+	PRIV_DEBUG_SUGID,	/* Exempt debugging setuid proc. */
+	PRIV_DEBUG_UNPRIV,	/* Exempt unprivileged debug limit. */
+	PRIV_FIRMWARE_LOAD,	/* Can load firmware. */
+	PRIV_JAIL_ATTACH,	/* Attach to a jail. */
+	PRIV_KENV_SET,		/* Set kernel env. variables. */
+	PRIV_KENV_UNSET,	/* Unset kernel env. variables. */
+	PRIV_KLD_LOAD,		/* Load a kernel module. */
+	PRIV_KLD_UNLOAD,	/* Unload a kernel module. */
+	PRIV_MAC_PARTITION,	/* Privilege in mac_partition policy. */
+	PRIV_MAC_PRIVS,		/* Privilege in the mac_privs policy. */
+	PRIV_PROC_LIMIT,	/* Exceed user process limit. */
+	PRIV_PROC_SETLOGIN,	/* Can call setlogin. */
+	PRIV_PROC_SETRLIMIT,	/* Can raise resources limits. */
+	PRIV_IPC_READ,		/* Can override IPC read perm. */
+	PRIV_IPC_WRITE,		/* Can override IPC write perm. */
+	PRIV_IPC_EXEC,		/* Can override IPC exec perm. */
+	PRIV_IPC_ADMIN,		/* Can override IPC owner-only perm. */
+	PRIV_IPC_MSGSIZE,	/* Exempt IPC message queue limit. */
+	PRIV_MQ_ADMIN,		/* Can override msgq owner-only perm. */
+	PRIV_PMC_MANAGE,	/* Can administer PMC. */
+	PRIV_PMC_SYSTEM,	/* Can allocate a system-wide PMC. */
+	PRIV_SCHED_DIFFCRED,	/* Exempt scheduling other users. */
+	PRIV_SCHED_SETPRIORITY,	/* Can set lower nice value for proc. */
+	PRIV_SCHED_RTPRIO,	/* Can set real time scheduling. */
+	PRIV_SCHED_SETPOLICY,	/* Can set scheduler policy. */
+	PRIV_SCHED_SET,		/* Can set thread scheduler. */
+	PRIV_SCHED_SETPARAM,	/* Can set thread scheduler params. */
+	PRIV_SEM_WRITE,		/* Can override sem write perm. */
+	PRIV_SIGNAL_DIFFCRED,	/* Exempt signalling other users. */
+	PRIV_SIGNAL_SUGID,	/* Non-conserv signal setuid proc. */
+	PRIV_SYSCTL_DEBUG,	/* Can invoke sysctl.debug. */
+	PRIV_SYSCTL_WRITE,	/* Can write sysctls. */
+	PRIV_SYSCTL_WRITEJAIL,	/* Can write sysctls, jail permitted. */
+	PRIV_TTY_CONSOLE,	/* Set console to tty. */
+	PRIV_TTY_DRAINWAIT,	/* Set tty drain wait time. */
+	PRIV_TTY_DTRWAIT,	/* Set DTR wait on tty. */
+	PRIV_TTY_EXCLUSIVE,	/* Override tty exclusive flag. */
+	PRIV_TTY_PRISON,	/* Can open pts across jails. */
+	PRIV_TTY_STI,		/* Simulate input on another tty. */
+	PRIV_TTY_SETA,		/* Set tty termios structure. */
+	PRIV_UFS_EXTATTRCTL,	/* Can configure EAs on UFS1. */
+	PRIV_UFS_GETQUOTA,	/* getquota(). */
+	PRIV_UFS_QUOTAOFF,	/* quotaoff(). */
+	PRIV_UFS_QUOTAON,	/* quotaon(). */
+	PRIV_UFS_SETQUOTA,	/* setquota(). */
+	PRIV_UFS_SETUSE,	/* setuse(). */
+	PRIV_UFS_EXCEEDQUOTA,	/* Exempt from quota restrictions. */
+	PRIV_VFS_READ,		/* Override vnode DAC read perm. */
+	PRIV_VFS_WRITE,		/* Override vnode DAC write perm. */
+	PRIV_VFS_ADMIN,		/* Override vnode DAC admin perm. */
+	PRIV_VFS_EXEC,		/* Override vnode DAC exec perm. */
+	PRIV_VFS_LOOKUP,	/* Override vnode DAC lookup perm. */
+	PRIV_VFS_BLOCKRESERVE,	/* Can use free block reserve. */
+	PRIV_VFS_CHFLAGS_DEV,	/* Can chflags() a device node. */
+	PRIV_VFS_CHOWN,		/* Can set user; group to non-member. */
+	PRIV_VFS_CHROOT,	/* chroot(). */
+	PRIV_VFS_CLEARSUGID,	/* Don't clear sugid on change. */
+	PRIV_VFS_EXTATTR_SYSTEM,	/* Operate on system EA namespace. */
+	PRIV_VFS_FCHROOT,	/* fchrot(). */
+	PRIV_VFS_FHOPEN,	/* Can fhopen(). */
+	PRIV_VFS_FHSTAT,	/* Can fhstat(). */
+	PRIV_VFS_FHSTATFS,	/* Can fhstatfs(). */
+	PRIV_VFS_GENERATION,	/* stat() returns generation number. */
+	PRIV_VFS_GETFH,		/* Can retrieve file handles. */
+	PRIV_VFS_LINK,		/* bsd.hardlink_check_uid */
+	PRIV_VFS_MKNOD_DEV,	/* Can create device nodes. */
+	PRIV_VFS_MOUNT,		/* Can mount(). */
+	PRIV_VFS_MOUNT_OWNER,	/* Override owner on user mounts. */
+	PRIV_VFS_MOUNT_EXPORTED,	/* Can set MNT_EXPORTED on mount. */
+	PRIV_VFS_MOUNT_PERM,	/* Override device node perms at mount. */
+	PRIV_VFS_MOUNT_SUIDDIR,	/* Can set MNT_SUIDDIR on mount. */
+	PRIV_VFS_SETGID,	/* Can setgid if not in group. */
+	PRIV_VFS_STICKYFILE,	/* Can set sticky bit on file. */
+	PRIV_VFS_SYSFLAGS,	/* Can modify system flags. */
+	PRIV_VFS_UNMOUNT,	/* Can unmount(). */
+	PRIV_VM_MADV_PROTECT,	/* Can set MADV_PROTECT. */
+	PRIV_VM_MLOCK,		/* Can mlock(), mlockall(). */
+	PRIV_VM_MUNLOCK,	/* Can munlock(), munlockall(). */
+	PRIV_DEVFS_RULE,	/* Can manage devfs rules. */
+	PRIV_DEVFS_SYMLINK,	/* Can create symlinks in devfs. */
+	PRIV_RANDOM_RESEED,	/* Closing /dev/random reseeds. */
+	PRIV_NET_BRIDGE,	/* Administer bridge. */
+	PRIV_NET_GRE,		/* Administer GRE. */
+	PRIV_NET_PPP,		/* Administer PPP. */
+	PRIV_NET_SLIP,		/* Administer SLIP. */
+	PRIV_NET_BPF,		/* Monitor BPF. */
+	PRIV_NET_RAW,		/* Open raw socket. */
+	PRIV_NET_ROUTE,		/* Administer routing. */
+	PRIV_NET_TAP,		/* Can open tap device. */
+	PRIV_NET_SETIFMTU,	/* Set interface MTU. */
+	PRIV_NET_SETIFFLAGS,	/* Set interface flags. */
+	PRIV_NET_SETIFCAP,	/* Set interface capabilities. */
+	PRIV_NET_SETIFNAME,	/* Set interface name. */
+	PRIV_NET_SETIFMETRIC,	/* Set interface metrics. */
+	PRIV_NET_SETIFPHYS,	/* Set interface physical layer prop. */
+	PRIV_NET_SETIFMAC,	/* Set interface MAC label. */
+	PRIV_NET_ADDMULTI,	/* Add multicast addr. to ifnet. */
+	PRIV_NET_DELMULTI,	/* Delete multicast addr. from ifnet. */
+	PRIV_NET_HWIOCTL,	/* Issue hardware ioctl on ifnet. */
+	PRIV_NET_SETLLADDR,
+	PRIV_NET_ADDIFGROUP,	/* Add new interface group. */
+	PRIV_NET_DELIFGROUP,	/* Delete interface group. */
+	PRIV_NET_IFCREATE,	/* Create cloned interface. */
+	PRIV_NET_IFDESTROY,	/* Destroy cloned interface. */
+	PRIV_NET80211_GETKEY,	/* Query 802.11 keys. */
+	PRIV_NET80211_MANAGE,	/* Administer 802.11. */
+	PRIV_NETATALK_RESERVEDPORT,	/* Bind low port number. */
+	PRIV_NETATM_CFG,
+	PRIV_NETATM_ADD,
+	PRIV_NETATM_DEL,
+	PRIV_NETATM_SET,
+	PRIV_NETGRAPH_CONTROL,	/* Open netgraph control socket. */
+	PRIV_NETGRAPH_TTY,	/* Configure tty for netgraph. */
+	PRIV_NETINET_RESERVEDPORT,	/* Bind low port number. */
+	PRIV_NETINET_IPFW,	/* Administer IPFW firewall. */
+	PRIV_NETINET_DIVERT,	/* Open IP divert socket. */
+	PRIV_NETINET_PF,	/* Administer pf firewall. */
+	PRIV_NETINET_DUMMYNET,	/* Administer DUMMYNET. */
+	PRIV_NETINET_CARP,	/* Administer CARP. */
+	PRIV_NETINET_MROUTE,	/* Administer multicast routing. */
+	PRIV_NETINET_RAW,	/* Open netinet raw socket. */
+	PRIV_NETINET_GETCRED,	/* Query netinet pcb credentials. */
+	PRIV_NETINET_ADDRCTRL6,	/* Administer IPv6 address scopes. */
+	PRIV_NETINET_ND6,	/* Administer IPv6 neighbor disc. */
+	PRIV_NETINET_SCOPE6,	/* Administer IPv6 address scopes. */
+	PRIV_NETINET_ALIFETIME6,	/* Administer IPv6 address lifetimes. */
+	PRIV_NETINET_IPSEC,	/* Administer IPSEC. */
+	PRIV_NETIPX_RESERVEDPORT,	/* Bind low port number. */
+	PRIV_NETIPX_RAW,	/* Open netipx raw socket. */
+	PRIV_NETNCP,	/* Allow use of connection owned by another user. */
+	PRIV_NETSMB,	/* Allow use of connection owned by another user. */
+	PRIV_VM86_INTCALL,	/* Allow invoking vm86 int handlers. */
+
+	/*
+	 * Set of reserved privilege values, which will be allocated to code
+	 * as needed, in order to avoid renumbering later privileges due to
+	 * insertion.
+	 */
+	_PRIV_RESERVED0,
+	_PRIV_RESERVED1,
+	_PRIV_RESERVED2,
+	_PRIV_RESERVED3,
+	_PRIV_RESERVED4,
+	_PRIV_RESERVED5,
+	_PRIV_RESERVED6,
+	_PRIV_RESERVED7,
+	_PRIV_RESERVED8,
+	_PRIV_RESERVED9,
+	_PRIV_RESERVED10,
+	_PRIV_RESERVED11,
+	_PRIV_RESERVED12,
+	_PRIV_RESERVED13,
+	_PRIV_RESERVED14,
+	_PRIV_RESERVED15,
+
+	/*
+	 * Define a set of valid privilege numbers that can be used by
+	 * loadable modules that don't yet have privilege reservations.
+	 * Ideally, these should not be used, since their meaning is opaque
+	 * to any policies that are aware of specific privileges, such as
+	 * jail, and as such may be arbitrarily denied.
+	 */
+	PRIV_MODULE0,
+	PRIV_MODULE1,
+	PRIV_MODULE2,
+	PRIV_MODULE3,
+	PRIV_MODULE4,
+	PRIV_MODULE5,
+	PRIV_MODULE6,
+	PRIV_MODULE7,
+	PRIV_MODULE8,
+	PRIV_MODULE9,
+	PRIV_MODULE10,
+	PRIV_MODULE11,
+	PRIV_MODULE12,
+	PRIV_MODULE13,
+	PRIV_MODULE14,
+	PRIV_MODULE15,
+
+	/* Track end of privilege list. */
+	_PRIV_HIGHEST
+};
+
+/*
+ * Validate that a named privilege is known by the privilege system.  Invalid
+ * privileges presented to the privilege system by a priv_check interface
+ * will result in a panic.
+ */
+#define	PRIV_VALID(x)	((x) > _PRIV_LOWEST && (x) < _PRIV_HIGHEST)
+
+#ifdef _KERNEL
+/*
+ * Privilege check interfaces, modeled after historic suser() interfacs, but
+ * with the addition of a specific privilege name.  The existing SUSER_* flag
+ * name space is used here.  The jail flag will likely be something that can
+ * be removed at some point as jail itself will be able to decide if the priv
+ * is appropriate, rather than the caller.
+ */
+struct thread;
+struct ucred;
+int	priv_check(struct thread *td, enum priv priv);
+int	priv_check_cred(struct ucred *cred, enum priv priv, int flags);
+#endif
+
+#endif /* !_SYS_PRIV_H_ */
Index: sys/sys/sysctl.h
===================================================================
RCS file: /home/ncvs/src/sys/sys/sysctl.h,v
retrieving revision 1.144
diff -u -r1.144 sysctl.h
--- sys/sys/sysctl.h	21 Aug 2006 06:27:27 -0000	1.144
+++ sys/sys/sysctl.h	13 Sep 2006 08:56:40 -0000
@@ -628,6 +628,8 @@
 SYSCTL_DECL(_user);
 SYSCTL_DECL(_compat);
 SYSCTL_DECL(_regression);
+SYSCTL_DECL(_security);
+SYSCTL_DECL(_security_bsd);
 
 extern char	machine[];
 extern char	osrelease[];
Index: sys/sys/systm.h
===================================================================
RCS file: /home/ncvs/src/sys/sys/systm.h,v
retrieving revision 1.243
diff -u -r1.243 systm.h
--- sys/sys/systm.h	28 Aug 2006 02:28:14 -0000	1.243
+++ sys/sys/systm.h	13 Sep 2006 08:56:40 -0000
@@ -230,7 +230,7 @@
 #define SUSER_RUID	2
 
 int	suser(struct thread *td);
-int	suser_cred(struct ucred *cred, int flag);
+int	suser_cred(struct ucred *cred, int flags);
 int	cr_cansee(struct ucred *u1, struct ucred *u2);
 int	cr_canseesocket(struct ucred *cred, struct socket *so);
 
Index: sys/ufs/ffs/ffs_alloc.c
===================================================================
RCS file: /home/ncvs/src/sys/ufs/ffs/ffs_alloc.c,v
retrieving revision 1.140
diff -u -r1.140 ffs_alloc.c
--- sys/ufs/ffs/ffs_alloc.c	18 Jul 2006 07:03:43 -0000	1.140
+++ sys/ufs/ffs/ffs_alloc.c	13 Sep 2006 08:56:40 -0000
@@ -71,6 +71,7 @@
 #include <sys/conf.h>
 #include <sys/file.h>
 #include <sys/filedesc.h>
+#include <sys/priv.h>
 #include <sys/proc.h>
 #include <sys/vnode.h>
 #include <sys/mount.h>
@@ -171,7 +172,7 @@
 #endif
 	if (size == fs->fs_bsize && fs->fs_cstotal.cs_nbfree == 0)
 		goto nospace;
-	if (suser_cred(cred, SUSER_ALLOWJAIL) &&
+	if (priv_check_cred(cred, PRIV_VFS_BLOCKRESERVE, SUSER_ALLOWJAIL) &&
 	    freespace(fs, fs->fs_minfree) - numfrags(fs, size) < 0)
 		goto nospace;
 	if (bpref >= fs->fs_size)
@@ -259,7 +260,7 @@
 #endif /* DIAGNOSTIC */
 	reclaimed = 0;
 retry:
-	if (suser_cred(cred, SUSER_ALLOWJAIL) &&
+	if (priv_check_cred(cred, PRIV_VFS_BLOCKRESERVE, SUSER_ALLOWJAIL) &&
 	    freespace(fs, fs->fs_minfree) -  numfrags(fs, nsize - osize) < 0) {
 		goto nospace;
 	}
Index: sys/ufs/ffs/ffs_vfsops.c
===================================================================
RCS file: /home/ncvs/src/sys/ufs/ffs/ffs_vfsops.c,v
retrieving revision 1.318
diff -u -r1.318 ffs_vfsops.c
--- sys/ufs/ffs/ffs_vfsops.c	9 Jul 2006 14:11:09 -0000	1.318
+++ sys/ufs/ffs/ffs_vfsops.c	13 Sep 2006 08:56:40 -0000
@@ -40,6 +40,7 @@
 #include <sys/param.h>
 #include <sys/systm.h>
 #include <sys/namei.h>
+#include <sys/priv.h>
 #include <sys/proc.h>
 #include <sys/kernel.h>
 #include <sys/mac.h>
@@ -248,15 +249,16 @@
 			 * If upgrade to read-write by non-root, then verify
 			 * that user has necessary permissions on the device.
 			 */
-			if (suser(td)) {
-				vn_lock(devvp, LK_EXCLUSIVE | LK_RETRY, td);
-				if ((error = VOP_ACCESS(devvp, VREAD | VWRITE,
-				    td->td_ucred, td)) != 0) {
-					VOP_UNLOCK(devvp, 0, td);
-					return (error);
-				}
+			vn_lock(devvp, LK_EXCLUSIVE | LK_RETRY, td);
+			error = VOP_ACCESS(devvp, VREAD | VWRITE,
+			    td->td_ucred, td);
+			if (error)
+				error = priv_check(td, PRIV_VFS_MOUNT_PERM);
+			if (error) {
 				VOP_UNLOCK(devvp, 0, td);
+				return (error);
 			}
+			VOP_UNLOCK(devvp, 0, td);
 			fs->fs_flags &= ~FS_UNCLEAN;
 			if (fs->fs_clean == 0) {
 				fs->fs_flags |= FS_UNCLEAN;
@@ -345,14 +347,15 @@
 	 * If mount by non-root, then verify that user has necessary
 	 * permissions on the device.
 	 */
-	if (suser(td)) {
-		accessmode = VREAD;
-		if ((mp->mnt_flag & MNT_RDONLY) == 0)
-			accessmode |= VWRITE;
-		if ((error = VOP_ACCESS(devvp, accessmode, td->td_ucred, td))!= 0){
-			vput(devvp);
-			return (error);
-		}
+	accessmode = VREAD;
+	if ((mp->mnt_flag & MNT_RDONLY) == 0)
+		accessmode |= VWRITE;
+	error = VOP_ACCESS(devvp, accessmode, td->td_ucred, td);
+	if (error)
+		error = priv_check(td, PRIV_VFS_MOUNT_PERM);
+	if (error) {
+		vput(devvp);
+		return (error);
 	}
 
 	if (mp->mnt_flag & MNT_UPDATE) {
Index: sys/ufs/ffs/ffs_vnops.c
===================================================================
RCS file: /home/ncvs/src/sys/ufs/ffs/ffs_vnops.c,v
retrieving revision 1.160
diff -u -r1.160 ffs_vnops.c
--- sys/ufs/ffs/ffs_vnops.c	5 May 2006 19:58:36 -0000	1.160
+++ sys/ufs/ffs/ffs_vnops.c	13 Sep 2006 08:56:40 -0000
@@ -74,6 +74,7 @@
 #include <sys/limits.h>
 #include <sys/malloc.h>
 #include <sys/mount.h>
+#include <sys/priv.h>
 #include <sys/proc.h>
 #include <sys/resourcevar.h>
 #include <sys/signalvar.h>
@@ -778,7 +779,8 @@
 	 * tampering.
 	 */
 	if (resid > uio->uio_resid && ap->a_cred && 
-	    suser_cred(ap->a_cred, SUSER_ALLOWJAIL)) {
+	    priv_check_cred(ap->a_cred, PRIV_VFS_CLEARSUGID,
+	    SUSER_ALLOWJAIL)) {
 		ip->i_mode &= ~(ISUID | ISGID);
 		DIP_SET(ip, i_mode, ip->i_mode);
 	}
@@ -1101,7 +1103,7 @@
 	 * tampering.
 	 */
 	if (resid > uio->uio_resid && ucred && 
-	    suser_cred(ucred, SUSER_ALLOWJAIL)) {
+	    priv_check_cred(ucred, PRIV_VFS_CLEARSUGID, SUSER_ALLOWJAIL)) {
 		ip->i_mode &= ~(ISUID | ISGID);
 		dp->di_mode = ip->i_mode;
 	}
Index: sys/ufs/ufs/ufs_extattr.c
===================================================================
RCS file: /home/ncvs/src/sys/ufs/ufs/ufs_extattr.c,v
retrieving revision 1.84
diff -u -r1.84 ufs_extattr.c
--- sys/ufs/ufs/ufs_extattr.c	1 Feb 2006 00:25:26 -0000	1.84
+++ sys/ufs/ufs/ufs_extattr.c	13 Sep 2006 08:56:40 -0000
@@ -48,6 +48,7 @@
 #include <sys/namei.h>
 #include <sys/malloc.h>
 #include <sys/fcntl.h>
+#include <sys/priv.h>
 #include <sys/proc.h>
 #include <sys/vnode.h>
 #include <sys/mount.h>
@@ -699,7 +700,8 @@
 	 * Processes with privilege, but in jail, are not allowed to
 	 * configure extended attributes.
 	 */
-	if ((error = suser(td))) {
+	error = priv_check(td, PRIV_UFS_EXTATTRCTL);
+	if (error) {
 		if (filename_vp != NULL)
 			VOP_UNLOCK(filename_vp, 0, td);
 		return (error);
Index: sys/ufs/ufs/ufs_quota.c
===================================================================
RCS file: /home/ncvs/src/sys/ufs/ufs/ufs_quota.c,v
retrieving revision 1.82
diff -u -r1.82 ufs_quota.c
--- sys/ufs/ufs/ufs_quota.c	5 May 2006 20:10:04 -0000	1.82
+++ sys/ufs/ufs/ufs_quota.c	13 Sep 2006 08:56:40 -0000
@@ -46,6 +46,7 @@
 #include <sys/mount.h>
 #include <sys/mutex.h>
 #include <sys/namei.h>
+#include <sys/priv.h>
 #include <sys/proc.h>
 #include <sys/socket.h>
 #include <sys/stat.h>
@@ -58,8 +59,6 @@
 #include <ufs/ufs/ufsmount.h>
 #include <ufs/ufs/ufs_extern.h>
 
-SYSCTL_DECL(_security_bsd);
-
 static int unprivileged_get_quota = 0;
 SYSCTL_INT(_security_bsd, OID_AUTO, unprivileged_get_quota, CTLFLAG_RW,
     &unprivileged_get_quota, 0,
@@ -167,7 +166,8 @@
 		}
 		return (0);
 	}
-	if ((flags & FORCE) == 0 && suser_cred(cred, 0)) {
+	if ((flags & FORCE) == 0 && priv_check_cred(cred,
+	    PRIV_UFS_EXCEEDQUOTA, 0)) {
 		for (i = 0; i < MAXQUOTAS; i++) {
 			if ((dq = ip->i_dquot[i]) == NODQUOT)
 				continue;
@@ -290,7 +290,8 @@
 		}
 		return (0);
 	}
-	if ((flags & FORCE) == 0 && suser_cred(cred, 0)) {
+	if ((flags & FORCE) == 0 && priv_check_cred(cred,
+	    PRIV_UFS_EXCEEDQUOTA, 0)) {
 		for (i = 0; i < MAXQUOTAS; i++) {
 			if ((dq = ip->i_dquot[i]) == NODQUOT)
 				continue;
@@ -425,7 +426,11 @@
 	int error, flags;
 	struct nameidata nd;
 
-	error = suser_cred(td->td_ucred, SUSER_ALLOWJAIL);
+	/*
+	 * XXXRW: Can this be right?  Jail is allowed to do this?
+	 */
+	error = priv_check_cred(td->td_ucred, PRIV_UFS_QUOTAON,
+	    SUSER_ALLOWJAIL);
 	if (error)
 		return (error);
 
@@ -517,7 +522,11 @@
 	struct inode *ip;
 	int error;
 
-	error = suser_cred(td->td_ucred, SUSER_ALLOWJAIL);
+	/*
+	 * XXXRW: This also seems wrong to allow in a jail?
+	 */
+	error = priv_check_cred(td->td_ucred, PRIV_UFS_QUOTAOFF,
+	    SUSER_ALLOWJAIL);
 	if (error)
 		return (error);
 
@@ -586,15 +595,18 @@
 	switch (type) {
 	case USRQUOTA:
 		if ((td->td_ucred->cr_uid != id) && !unprivileged_get_quota) {
-			error = suser_cred(td->td_ucred, SUSER_ALLOWJAIL);
+			error = priv_check_cred(td->td_ucred,
+			    PRIV_UFS_GETQUOTA, SUSER_ALLOWJAIL);
 			if (error)
 				return (error);
 		}
 		break;  
 
 	case GRPQUOTA:
-		if (!groupmember(id, td->td_ucred) && !unprivileged_get_quota) {
-			error = suser_cred(td->td_ucred, SUSER_ALLOWJAIL);
+		if (!groupmember(id, td->td_ucred) &&
+		    !unprivileged_get_quota) {
+			error = priv_check_cred(td->td_ucred,
+			    PRIV_UFS_GETQUOTA, SUSER_ALLOWJAIL);
 			if (error)
 				return (error);
 		}
@@ -629,7 +641,8 @@
 	struct dqblk newlim;
 	int error;
 
-	error = suser_cred(td->td_ucred, SUSER_ALLOWJAIL);
+	error = priv_check_cred(td->td_ucred, PRIV_UFS_SETQUOTA,
+	    SUSER_ALLOWJAIL);
 	if (error)
 		return (error);
 
@@ -695,7 +708,8 @@
 	struct dqblk usage;
 	int error;
 
-	error = suser_cred(td->td_ucred, SUSER_ALLOWJAIL);
+	error = priv_check_cred(td->td_ucred, PRIV_UFS_SETUSE,
+	    SUSER_ALLOWJAIL);
 	if (error)
 		return (error);
 
Index: sys/ufs/ufs/ufs_vnops.c
===================================================================
RCS file: /home/ncvs/src/sys/ufs/ufs/ufs_vnops.c,v
retrieving revision 1.278
diff -u -r1.278 ufs_vnops.c
--- sys/ufs/ufs/ufs_vnops.c	20 Aug 2006 10:52:44 -0000	1.278
+++ sys/ufs/ufs/ufs_vnops.c	13 Sep 2006 08:56:40 -0000
@@ -53,6 +53,7 @@
 #include <sys/bio.h>
 #include <sys/buf.h>
 #include <sys/mount.h>
+#include <sys/priv.h>
 #include <sys/refcount.h>
 #include <sys/unistd.h>
 #include <sys/vnode.h>
@@ -465,8 +466,11 @@
 		 * processes if the security.jail.chflags_allowed sysctl is
 		 * is non-zero; otherwise, they behave like unprivileged
 		 * processes.
+		 *
+		 * XXXRW: Move implementation of jail_chflags_allowed to
+		 * kern_jail.c.
 		 */
-		if (!suser_cred(cred,
+		if (!priv_check_cred(cred, PRIV_VFS_SYSFLAGS,
 		    jail_chflags_allowed ? SUSER_ALLOWJAIL : 0)) {
 			if (ip->i_flags
 			    & (SF_NOUNLINK | SF_IMMUTABLE | SF_APPEND)) {
@@ -557,10 +561,19 @@
 		 * super-user.
 		 * If times is non-NULL, ... The caller must be the owner of
 		 * the file or be the super-user.
+		 *
+		 * Possibly for historical reasons, try to use VADMIN in
+		 * preference to VADMIN for a NULL timestamp.  This means we
+		 * will return EACCES in preference to EPERM if neither
+		 * check succeeds.
 		 */
-		if ((error = VOP_ACCESS(vp, VADMIN, cred, td)) &&
-		    ((vap->va_vaflags & VA_UTIMES_NULL) == 0 ||
-		    (error = VOP_ACCESS(vp, VWRITE, cred, td))))
+		if (vap->va_vaflags & VA_UTIMES_NULL) {
+			error = VOP_ACCESS(vp, VADMIN, cred, td);
+			if (error)
+				error = VOP_ACCESS(vp, VWRITE, cred, td);
+		} else
+			error = VOP_ACCESS(vp, VADMIN, cred, td);
+		if (error)
 			return (error);
 		if (vap->va_atime.tv_sec != VNOVAL)
 			ip->i_flag |= IN_ACCESS;
@@ -626,11 +639,13 @@
 	 * jail(8).
 	 */
 	if (vp->v_type != VDIR && (mode & S_ISTXT)) {
-		if (suser_cred(cred, SUSER_ALLOWJAIL))
+		if (priv_check_cred(cred, PRIV_VFS_STICKYFILE,
+		    SUSER_ALLOWJAIL))
 			return (EFTYPE);
 	}
 	if (!groupmember(ip->i_gid, cred) && (mode & ISGID)) {
-		error = suser_cred(cred, SUSER_ALLOWJAIL);
+		error = priv_check_cred(cred, PRIV_VFS_SETGID,
+		    SUSER_ALLOWJAIL);
 		if (error)
 			return (error);
 	}
@@ -667,19 +682,19 @@
 	if (gid == (gid_t)VNOVAL)
 		gid = ip->i_gid;
 	/*
-	 * To modify the ownership of a file, must possess VADMIN
-	 * for that file.
+	 * To modify the ownership of a file, must possess VADMIN for that
+	 * file.
 	 */
 	if ((error = VOP_ACCESS(vp, VADMIN, cred, td)))
 		return (error);
 	/*
-	 * To change the owner of a file, or change the group of a file
-	 * to a group of which we are not a member, the caller must
-	 * have privilege.
+	 * To change the owner of a file, or change the group of a file to a
+	 * group of which we are not a member, the caller must have
+	 * privilege.
 	 */
 	if ((uid != ip->i_uid || 
 	    (gid != ip->i_gid && !groupmember(gid, cred))) &&
-	    (error = suser_cred(cred, SUSER_ALLOWJAIL)))
+	    (error = priv_check_cred(cred, PRIV_VFS_CHOWN, SUSER_ALLOWJAIL)))
 		return (error);
 	ogid = ip->i_gid;
 	ouid = ip->i_uid;
@@ -750,7 +765,8 @@
 		panic("ufs_chown: lost quota");
 #endif /* QUOTA */
 	ip->i_flag |= IN_CHANGE;
-	if (suser_cred(cred, SUSER_ALLOWJAIL) && (ouid != uid || ogid != gid)) {
+	if (priv_check_cred(cred, PRIV_VFS_CLEARSUGID, SUSER_ALLOWJAIL) &&
+	    (ouid != uid || ogid != gid)) {
 		ip->i_mode &= ~(ISUID | ISGID);
 		DIP_SET(ip, i_mode, ip->i_mode);
 	}
@@ -2321,7 +2337,8 @@
 	if (DOINGSOFTDEP(tvp))
 		softdep_change_linkcnt(ip);
 	if ((ip->i_mode & ISGID) && !groupmember(ip->i_gid, cnp->cn_cred) &&
-	    suser_cred(cnp->cn_cred, SUSER_ALLOWJAIL)) {
+	    priv_check_cred(cnp->cn_cred, PRIV_VFS_SETGID,
+	    SUSER_ALLOWJAIL)) {
 		ip->i_mode &= ~ISGID;
 		DIP_SET(ip, i_mode, ip->i_mode);
 	}
Index: sys/vm/swap_pager.c
===================================================================
RCS file: /home/ncvs/src/sys/vm/swap_pager.c,v
retrieving revision 1.282
diff -u -r1.282 swap_pager.c
--- sys/vm/swap_pager.c	9 Aug 2006 17:43:27 -0000	1.282
+++ sys/vm/swap_pager.c	13 Sep 2006 08:56:40 -0000
@@ -77,6 +77,7 @@
 #include <sys/systm.h>
 #include <sys/conf.h>
 #include <sys/kernel.h>
+#include <sys/priv.h>
 #include <sys/proc.h>
 #include <sys/bio.h>
 #include <sys/buf.h>
@@ -1965,11 +1966,11 @@
 	struct nameidata nd;
 	int error;
 
-	mtx_lock(&Giant);
-	error = suser(td);
+	error = priv_check(td, PRIV_SWAPON);
 	if (error)
-		goto done2;
+		return (error);
 
+	mtx_lock(&Giant);
 	while (swdev_syscall_active)
 	    tsleep(&swdev_syscall_active, PUSER - 1, "swpon", 0);
 	swdev_syscall_active = 1;
@@ -2008,7 +2009,6 @@
 done:
 	swdev_syscall_active = 0;
 	wakeup_one(&swdev_syscall_active);
-done2:
 	mtx_unlock(&Giant);
 	return (error);
 }
@@ -2104,7 +2104,7 @@
 	struct swdevt *sp;
 	int error;
 
-	error = suser(td);
+	error = priv_check(td, PRIV_SWAPOFF);
 	if (error)
 		return (error);
 
Index: sys/vm/vm_mmap.c
===================================================================
RCS file: /home/ncvs/src/sys/vm/vm_mmap.c,v
retrieving revision 1.206
diff -u -r1.206 vm_mmap.c
--- sys/vm/vm_mmap.c	21 Jun 2006 12:59:05 -0000	1.206
+++ sys/vm/vm_mmap.c	13 Sep 2006 08:56:40 -0000
@@ -54,6 +54,7 @@
 #include <sys/mutex.h>
 #include <sys/sysproto.h>
 #include <sys/filedesc.h>
+#include <sys/priv.h>
 #include <sys/proc.h>
 #include <sys/resource.h>
 #include <sys/resourcevar.h>
@@ -683,7 +684,7 @@
 	 * "immortal."
 	 */
 	if (uap->behav == MADV_PROTECT) {
-		error = suser(td);
+		error = priv_check(td, PRIV_VM_MADV_PROTECT);
 		if (error == 0) {
 			p = td->td_proc;
 			PROC_LOCK(p);
@@ -950,7 +951,7 @@
 	vm_size_t npages, size;
 	int error;
 
-	error = suser(td);
+	error = priv_check(td, PRIV_VM_MLOCK);
 	if (error)
 		return (error);
 	addr = (vm_offset_t)uap->addr;
@@ -1015,7 +1016,7 @@
 	}
 	PROC_UNLOCK(td->td_proc);
 #else
-	error = suser(td);
+	error = priv_check(td, PRIV_VM_MLOCK);
 	if (error)
 		return (error);
 #endif
@@ -1060,7 +1061,7 @@
 	int error;
 
 	map = &td->td_proc->p_vmspace->vm_map;
-	error = suser(td);
+	error = priv_check(td, PRIV_VM_MUNLOCK);
 	if (error)
 		return (error);
 
@@ -1094,7 +1095,7 @@
 	vm_size_t size;
 	int error;
 
-	error = suser(td);
+	error = priv_check(td, PRIV_VM_MUNLOCK);
 	if (error)
 		return (error);
 	addr = (vm_offset_t)uap->addr;
