New in-kernel privilege API: priv(9)

Robert Watson rwatson at FreeBSD.org
Tue Oct 31 11:01:33 UTC 2006


Dear all,

A month and a half ago, I posted a patch implementing a priv(9) API.  I've now 
updated this patch to reflect a more thorough review of kernel privilege, 
corrected some of the nits, etc.  I would like to move ahead with committing 
priv(9), so this is a final request for review (or serious objections) before 
I do so in a few days.  The commit will occur in two phases:

(1) Commit of the base portions of the patch:

     Modified Files:
         sys/kern/kern_jail.c sys/kern/kern_prot.c
         sys/security/mac/mac_framework.h
         sys/security/mac/mac_internal.h sys/sys/jail.h sys/sys/systm.h
         sys/conf/files share/man/man9/Makefile share/man/man9/suser.9
     Added Files:
         sys/kern/kern_priv.c sys/security/mac/mac_priv.c
         sys/sys/priv.h share/man/man9/priv.9

     Commit message for this attached below.

(2) Sweep of the remaining kernel files, cleaning up privilege checks,
     replacing suser()/suser_cred() calls, etc, across the kernel.

Among other things, I'd like to be able to add some additional names to the 
"Reviewed by:" list. :-)  This is, of course, a set of highly sensitive 
security-related changes, and having detailed reviews is very important.

The primary changes from the previous patch to this one are:

- Significant cleanup of the kern_jail.c code.  It's now simply a list of
   privileges granted in jail, with justifications.

- A number of tweaks and fixes to privilege use across the kernel.  A moderate
   number of the XXX's added in the previous patch are now fixed.  Not all
   though.

- The privilege list has changed from an enum to an int with #define's.  This
   has several benefits -- one is that there's no longer a concern about the C
   limit of not being able to forward declare enumerated types.  Also, since
   the numeric assignment of privilege identifiers is part of the kernel ABI
   for modules, I've moved to explicitly assigning privilege numbers, and have
   left gaps for subsystem growth, etc.

A few XXX's still exist that will require some further attention, likely after 
merging the patch.  Pawel and I are also discussing whether there are some UFS 
privileges that should become general VFS privileges such as quota bypass 
privileges).  Another concern is that there are one or two places where 
privileges are inconsistently granted inside and outside of jail, and we will 
want to either subdivide the privilege or move to a more consistent approach. 
For this reason, the KASSERT() after prison_priv_check() in priv_check() 
concerning the consistency of SUSER_ALLOWJAIL and the internal logic is 
temporarily disabled.  Once we've decided that all looks good with regard to 
jail, I can sweep the kernel removing the SUSER_ALLOWJAIL arguments, and 
complete the migration of jail configuration frobs to kern_jail.c from their 
current scattered locations across the kernel.

Thanks,

Robert N M Watson
Computer Laboratory
University of Cambridge

> Add a new priv(9) kernel interface for checking the availability of
> privilege for threads and credentials.  Unlike the existing suser(9)
> interface, priv(9) exposes a named privilege identifier to the privilege
> checking code, allowing more complex policies regarding the granting of
> privilege to be expressed.  Two interfaces are provided, replacing the
> existing suser(9) interface:
>
> suser(td)                 ->   priv_check(td, priv)
> suser_cred(cred, flags)   ->   priv_check_cred(cred, priv, flags)
>
> A comprehensive list of currently available kernel privileges may be
> found in priv.h.  New privileges are easily added as required, but the
> comments on adding privileges found in priv.h and priv(9) should be read
> before doing so.
>
> The new privilege interface exposed sufficient information to the
> privilege checking routine that it will now be possible for jail to
> determine whether a particular privilege is granted in the check routine,
> rather than relying on hints from the calling context via the
> SUSER_ALLOWJAIL flag.  For now, the flag is maintained, but a new jail
> check function, prison_priv_check(), is exposed from kern_jail.c and used
> by the privilege check routine to determine if the privilege is permitted
> in jail.  As a result, a centralized list of privileges permitted in jail
> is now present in kern_jail.c.
>
> The MAC Framework is now also able to instrument privilege checks, both
> to deny privileges otherwise granted (mac_priv_check()), and to grant
> privileges otherwise denied (mac_priv_grant()), permitting MAC Policy
> modules to implement privilege models, as well as control a much broader
> range of system behavior in order to constrain processes running with
> root privilege.
>
> The suser() and suser_cred() functions remain implemented, now in terms
> of priv_check() and the PRIV_ROOT privilege, for use during the transition
> and possibly continuing use by third party kernel modules that have not
> been updated.  The PRIV_DRIVER privilege exists to allow device drivers to
> check privilege without adopting a more specific privilege identifier.
>
> This change does not modify the actual security policy, rather, it
> modifies the interface for privilege checks so changes to the security
> policy become more feasible.
>
> Sponsored by:   nCircle Network Security, Inc.
> Discussed on:   arch@
> Reviewed (at least in part) by: mlaier, jmg


Index: share/man/man9/Makefile
===================================================================
RCS file: /zoo/cvsup/FreeBSD-CVS/src/share/man/man9/Makefile,v
retrieving revision 1.282
diff -u -r1.282 Makefile
--- share/man/man9/Makefile	5 Oct 2006 12:40:44 -0000	1.282
+++ share/man/man9/Makefile	31 Oct 2006 09:06:00 -0000
@@ -188,6 +188,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	31 Oct 2006 09:03:48 -0000
@@ -0,0 +1,115 @@
+.\"-
+.\" 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
+.Ft int
+.Fn priv_check "struct thread *td" "int priv"
+.Ft int
+.Fn priv_check_cred "struct ucred *cred" "int 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.
+This interface replaces the
+.Xr suser 9
+privilege checking interface.
+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 suser 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: share/man/man9/suser.9
===================================================================
RCS file: /zoo/cvsup/FreeBSD-CVS/src/share/man/man9/suser.9,v
retrieving revision 1.29
diff -u -r1.29 suser.9
--- share/man/man9/suser.9	16 May 2006 22:58:43 -0000	1.29
+++ share/man/man9/suser.9	31 Oct 2006 09:05:47 -0000
@@ -54,6 +54,12 @@
  .Fn suser_cred
  functions check if the credentials given include superuser powers.
  .Pp
+These interfaces have now been obsoleted by
+.Xr priv 9 ,
+and are provided only for compatibility with third party kernel modules that
+have not yet been updated to the new interface.
+They should not be used in any new kernel code.
+.Pp
  The
  .Fn suser
  function is the most common, and should be used unless special
@@ -123,7 +129,8 @@
  in which a TRUE response indicates superuser powers.
  .Sh SEE ALSO
  .Xr chroot 2 ,
-.Xr jail 2
+.Xr jail 2 ,
+.Xr priv 9
  .Sh BUGS
  The
  .Fn suser
Index: sys/amd64/amd64/io.c
===================================================================
RCS file: /zoo/cvsup/FreeBSD-CVS/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	30 Oct 2006 17:07:54 -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: /zoo/cvsup/FreeBSD-CVS/src/sys/compat/linux/linux_misc.c,v
retrieving revision 1.191
diff -u -r1.191 linux_misc.c
--- sys/compat/linux/linux_misc.c	28 Oct 2006 16:47:38 -0000	1.191
+++ sys/compat/linux/linux_misc.c	30 Oct 2006 17:07:54 -0000
@@ -48,6 +48,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>
@@ -1020,7 +1021,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);
@@ -1341,7 +1343,7 @@
  	switch (args->cmd) {
  	case REBOOT_CAD_ON:
  	case REBOOT_CAD_OFF:
-		return suser(td);
+		return (priv_check(td, PRIV_REBOOT));
  	case REBOOT_HALT:
  		bsd_args.opt = RB_HALT;
  		break;
Index: sys/compat/linux/linux_uid16.c
===================================================================
RCS file: /zoo/cvsup/FreeBSD-CVS/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	30 Oct 2006 17:07:54 -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: /zoo/cvsup/FreeBSD-CVS/src/sys/compat/svr4/svr4_fcntl.c,v
retrieving revision 1.38
diff -u -r1.38 svr4_fcntl.c
--- sys/compat/svr4/svr4_fcntl.c	22 Oct 2006 11:52:11 -0000	1.38
+++ sys/compat/svr4/svr4_fcntl.c	30 Oct 2006 17:07:54 -0000
@@ -44,6 +44,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>
@@ -280,7 +281,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: /zoo/cvsup/FreeBSD-CVS/src/sys/compat/svr4/svr4_misc.c,v
retrieving revision 1.90
diff -u -r1.90 svr4_misc.c
--- sys/compat/svr4/svr4_misc.c	22 Oct 2006 11:52:11 -0000	1.90
+++ sys/compat/svr4/svr4_misc.c	30 Oct 2006 17:07:54 -0000
@@ -52,6 +52,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>
@@ -611,7 +612,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/files
===================================================================
RCS file: /zoo/cvsup/FreeBSD-CVS/src/sys/conf/files,v
retrieving revision 1.1156
diff -u -r1.1156 files
--- sys/conf/files	30 Oct 2006 05:51:53 -0000	1.1156
+++ sys/conf/files	30 Oct 2006 21:24:56 -0000
@@ -1347,6 +1347,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
@@ -1920,6 +1921,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
Index: sys/contrib/altq/altq/altq_cbq.c
===================================================================
RCS file: /zoo/cvsup/FreeBSD-CVS/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	30 Oct 2006 17:07:54 -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: /zoo/cvsup/FreeBSD-CVS/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	30 Oct 2006 17:07:54 -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: /zoo/cvsup/FreeBSD-CVS/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	30 Oct 2006 17:07:54 -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: /zoo/cvsup/FreeBSD-CVS/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	30 Oct 2006 17:07:54 -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: /zoo/cvsup/FreeBSD-CVS/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	30 Oct 2006 17:07:54 -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: /zoo/cvsup/FreeBSD-CVS/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	30 Oct 2006 17:07:54 -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: /zoo/cvsup/FreeBSD-CVS/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	30 Oct 2006 17:07:54 -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: /zoo/cvsup/FreeBSD-CVS/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	30 Oct 2006 17:07:54 -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: /zoo/cvsup/FreeBSD-CVS/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	30 Oct 2006 17:07:54 -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: /zoo/cvsup/FreeBSD-CVS/src/sys/dev/asr/asr.c,v
retrieving revision 1.79
diff -u -r1.79 asr.c
--- sys/dev/asr/asr.c	31 Oct 2006 05:53:26 -0000	1.79
+++ sys/dev/asr/asr.c	31 Oct 2006 08:40:40 -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>
@@ -3145,7 +3146,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: /zoo/cvsup/FreeBSD-CVS/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	30 Oct 2006 17:07:54 -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: /zoo/cvsup/FreeBSD-CVS/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	30 Oct 2006 17:07:54 -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/cnw/if_cnw.c
===================================================================
RCS file: /zoo/cvsup/FreeBSD-CVS/src/sys/dev/cnw/if_cnw.c,v
retrieving revision 1.23
diff -u -r1.23 if_cnw.c
--- sys/dev/cnw/if_cnw.c	16 May 2006 14:36:23 -0000	1.23
+++ sys/dev/cnw/if_cnw.c	30 Oct 2006 17:07:54 -0000
@@ -236,6 +236,7 @@
  #include <sys/mbuf.h>
  #include <sys/malloc.h>
  #include <sys/kernel.h>
+#include <sys/priv.h>
  #include <sys/proc.h>
  #include <sys/ucred.h>
  #include <sys/socket.h>
@@ -1339,7 +1340,7 @@
  #if !defined(__FreeBSD__)
  		error = suser(p->p_ucred, &p->p_acflag);
  #else
-		error = suser(td);
+		error = priv_check(td, PRIV_DRIVER);
  #endif
  		if (error)
  			break;
@@ -1350,7 +1351,7 @@
  #if !defined(__FreeBSD__)
  		error = suser(p->p_ucred, &p->p_acflag);
  #else
-		error = suser(td);
+		error = priv_check(td, PRIV_DRIVER);
  #endif
  		if (error)
  			break;
@@ -1361,7 +1362,7 @@
  #if !defined(__FreeBSD__)
  		error = suser(p->p_ucred, &p->p_acflag);
  #else
-		error = suser(td);
+		error = priv_check(td, PRIV_DRIVER);
  #endif
  		if (error)
  			break;
Index: sys/dev/cp/if_cp.c
===================================================================
RCS file: /zoo/cvsup/FreeBSD-CVS/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	30 Oct 2006 17:07:54 -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: /zoo/cvsup/FreeBSD-CVS/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	30 Oct 2006 17:07:54 -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: /zoo/cvsup/FreeBSD-CVS/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	30 Oct 2006 17:07:54 -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: /zoo/cvsup/FreeBSD-CVS/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	30 Oct 2006 17:07:54 -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: /zoo/cvsup/FreeBSD-CVS/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	30 Oct 2006 17:07:54 -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: /zoo/cvsup/FreeBSD-CVS/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	30 Oct 2006 17:07:54 -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: /zoo/cvsup/FreeBSD-CVS/src/sys/dev/hwpmc/hwpmc_mod.c,v
retrieving revision 1.25
diff -u -r1.25 hwpmc_mod.c
--- sys/dev/hwpmc/hwpmc_mod.c	17 Sep 2006 20:00:35 -0000	1.25
+++ sys/dev/hwpmc/hwpmc_mod.c	30 Oct 2006 17:07:54 -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>
@@ -2782,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;
@@ -2918,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: /zoo/cvsup/FreeBSD-CVS/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	30 Oct 2006 17:07:54 -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: /zoo/cvsup/FreeBSD-CVS/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	30 Oct 2006 17:07:54 -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: /zoo/cvsup/FreeBSD-CVS/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	30 Oct 2006 17:07:55 -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: /zoo/cvsup/FreeBSD-CVS/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	30 Oct 2006 17:07:55 -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: /zoo/cvsup/FreeBSD-CVS/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	30 Oct 2006 17:07:55 -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: /zoo/cvsup/FreeBSD-CVS/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	30 Oct 2006 17:07:55 -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: /zoo/cvsup/FreeBSD-CVS/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	30 Oct 2006 17:07:55 -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: /zoo/cvsup/FreeBSD-CVS/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	30 Oct 2006 17:07:55 -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: /zoo/cvsup/FreeBSD-CVS/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	30 Oct 2006 17:07:55 -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: /zoo/cvsup/FreeBSD-CVS/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	30 Oct 2006 17:07:55 -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: /zoo/cvsup/FreeBSD-CVS/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	30 Oct 2006 17:07:55 -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: /zoo/cvsup/FreeBSD-CVS/src/sys/dev/syscons/syscons.c,v
retrieving revision 1.447
diff -u -r1.447 syscons.c
--- sys/dev/syscons/syscons.c	27 Sep 2006 19:56:59 -0000	1.447
+++ sys/dev/syscons/syscons.c	30 Oct 2006 17:07:55 -0000
@@ -50,6 +50,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>
@@ -517,7 +518,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);
@@ -1092,7 +1093,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: /zoo/cvsup/FreeBSD-CVS/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	30 Oct 2006 17:07:55 -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: /zoo/cvsup/FreeBSD-CVS/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	30 Oct 2006 17:07:55 -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: /zoo/cvsup/FreeBSD-CVS/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	30 Oct 2006 17:07:55 -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: /zoo/cvsup/FreeBSD-CVS/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	30 Oct 2006 17:07:55 -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: /zoo/cvsup/FreeBSD-CVS/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	31 Oct 2006 08:25:32 -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.
+	 *
+	 * 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: /zoo/cvsup/FreeBSD-CVS/src/sys/fs/devfs/devfs_vnops.c,v
retrieving revision 1.139
diff -u -r1.139 devfs_vnops.c
--- sys/fs/devfs/devfs_vnops.c	22 Oct 2006 11:52:12 -0000	1.139
+++ sys/fs/devfs/devfs_vnops.c	30 Oct 2006 17:07:55 -0000
@@ -55,6 +55,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>
@@ -1145,19 +1146,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;
  	}
@@ -1227,7 +1234,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: /zoo/cvsup/FreeBSD-CVS/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	30 Oct 2006 17:07:55 -0000
@@ -501,11 +501,12 @@
  	if (vap->va_atime.tv_sec != VNOVAL || vap->va_mtime.tv_sec != VNOVAL) {
  		if (vp->v_mount->mnt_flag & MNT_RDONLY)
  			return (EROFS);
-		if (cred->cr_uid != hp->h_uid &&
-		    (error = suser_cred(cred, SUSER_ALLOWJAIL)) &&
-		    ((vap->va_vaflags & VA_UTIMES_NULL) == 0 ||
-		    (error = VOP_ACCESS(vp, VWRITE, cred, td))))
-			return (error);
+		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 (vap->va_atime.tv_sec != VNOVAL)
  			hp->h_atime = vap->va_atime.tv_sec;
  		if (vap->va_mtime.tv_sec != VNOVAL)
Index: sys/fs/msdosfs/msdosfs_vfsops.c
===================================================================
RCS file: /zoo/cvsup/FreeBSD-CVS/src/sys/fs/msdosfs/msdosfs_vfsops.c,v
retrieving revision 1.153
diff -u -r1.153 msdosfs_vfsops.c
--- sys/fs/msdosfs/msdosfs_vfsops.c	26 Sep 2006 04:12:45 -0000	1.153
+++ sys/fs/msdosfs/msdosfs_vfsops.c	30 Oct 2006 17:07:55 -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: /zoo/cvsup/FreeBSD-CVS/src/sys/fs/msdosfs/msdosfs_vnops.c,v
retrieving revision 1.164
diff -u -r1.164 msdosfs_vnops.c
--- sys/fs/msdosfs/msdosfs_vnops.c	24 Oct 2006 11:14:05 -0000	1.164
+++ sys/fs/msdosfs/msdosfs_vnops.c	30 Oct 2006 17:07:55 -0000
@@ -59,6 +59,7 @@
  #include <sys/conf.h>
  #include <sys/clock.h>
  #include <sys/buf.h>
+#include <sys/priv.h>
  #include <sys/proc.h>
  #include <sys/mount.h>
  #include <sys/unistd.h>
@@ -404,9 +405,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
@@ -419,9 +423,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;
@@ -444,10 +450,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;
  	}
@@ -477,11 +486,13 @@
  	if (vap->va_atime.tv_sec != VNOVAL || vap->va_mtime.tv_sec != VNOVAL) {
  		if (vp->v_mount->mnt_flag & MNT_RDONLY)
  			return (EROFS);
-		if (cred->cr_uid != pmp->pm_uid &&
-		    (error = suser_cred(cred, SUSER_ALLOWJAIL)) &&
-		    ((vap->va_vaflags & VA_UTIMES_NULL) == 0 ||
-		    (error = VOP_ACCESS(ap->a_vp, VWRITE, cred, ap->a_td))))
-			return (error);
+		if (vap->va_vaflags & VA_UTIMES_NULL) {
+			error = VOP_ACCESS(vp, VADMIN, cred, ap->a_td); 
+			if (error)
+				error = VOP_ACCESS(vp, VWRITE, cred,
+				    ap->a_td);
+		} else
+			error = VOP_ACCESS(vp, VADMIN, cred, ap->a_td);
  		if (vp->v_type != VDIR) {
  			if ((pmp->pm_flags & MSDOSFSMNT_NOWIN95) == 0 &&
  			    vap->va_atime.tv_sec != VNOVAL) {
@@ -506,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: /zoo/cvsup/FreeBSD-CVS/src/sys/fs/procfs/procfs_ioctl.c,v
retrieving revision 1.13
diff -u -r1.13 procfs_ioctl.c
--- sys/fs/procfs/procfs_ioctl.c	27 Sep 2006 19:57:00 -0000	1.13
+++ sys/fs/procfs/procfs_ioctl.c	30 Oct 2006 17:07:55 -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>
@@ -104,8 +105,19 @@
  #endif
  	case PIOCSFL:
  		flags = *(unsigned int *)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: /zoo/cvsup/FreeBSD-CVS/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	30 Oct 2006 17:07:55 -0000
@@ -352,11 +352,13 @@
  	if (vap->va_atime.tv_sec != VNOVAL)
  		atime = &vap->va_atime;
  	if (mtime != atime) {
-		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 ||
-		    (error = VOP_ACCESS(vp, VWRITE, ap->a_cred, ap->a_td))))
-			return (error);
+		if (vap->va_vaflags & VA_UTIMES_NULL) {
+			error = VOP_ACCESS(vp, VADMIN, ap->a_cred, ap->a_td);
+			if (error)
+				error = VOP_ACCESS(vp, VWRITE, ap->a_cred,
+				    ap->a_td);
+		} else
+			error = VOP_ACCESS(vp, VADMIN, ap->a_cred, ap->a_td);
  #if 0
  		if (mtime == NULL)
  			mtime = &np->n_mtime;
Index: sys/fs/udf/udf_vfsops.c
===================================================================
RCS file: /zoo/cvsup/FreeBSD-CVS/src/sys/fs/udf/udf_vfsops.c,v
retrieving revision 1.44
diff -u -r1.44 udf_vfsops.c
--- sys/fs/udf/udf_vfsops.c	26 Sep 2006 04:12:46 -0000	1.44
+++ sys/fs/udf/udf_vfsops.c	30 Oct 2006 17:07:55 -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>
@@ -238,7 +239,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: /zoo/cvsup/FreeBSD-CVS/src/sys/fs/umapfs/umap_vfsops.c,v
retrieving revision 1.65
diff -u -r1.65 umap_vfsops.c
--- sys/fs/umapfs/umap_vfsops.c	26 Sep 2006 04:12:46 -0000	1.65
+++ sys/fs/umapfs/umap_vfsops.c	30 Oct 2006 17:07:55 -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: /zoo/cvsup/FreeBSD-CVS/src/sys/gnu/fs/ext2fs/ext2_vfsops.c,v
retrieving revision 1.158
diff -u -r1.158 ext2_vfsops.c
--- sys/gnu/fs/ext2fs/ext2_vfsops.c	26 Sep 2006 04:12:47 -0000	1.158
+++ sys/gnu/fs/ext2fs/ext2_vfsops.c	30 Oct 2006 17:07:55 -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);
@@ -259,15 +261,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: /zoo/cvsup/FreeBSD-CVS/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	30 Oct 2006 17:07:55 -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: /zoo/cvsup/FreeBSD-CVS/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	30 Oct 2006 17:07:55 -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: /zoo/cvsup/FreeBSD-CVS/src/sys/gnu/fs/reiserfs/reiserfs_vfsops.c,v
retrieving revision 1.6
diff -u -r1.6 reiserfs_vfsops.c
--- sys/gnu/fs/reiserfs/reiserfs_vfsops.c	26 Sep 2006 04:12:47 -0000	1.6
+++ sys/gnu/fs/reiserfs/reiserfs_vfsops.c	30 Oct 2006 17:07:55 -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: /zoo/cvsup/FreeBSD-CVS/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	30 Oct 2006 17:07:55 -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: /zoo/cvsup/FreeBSD-CVS/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	30 Oct 2006 17:07:55 -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: /zoo/cvsup/FreeBSD-CVS/src/sys/i386/i386/sys_machdep.c,v
retrieving revision 1.106
diff -u -r1.106 sys_machdep.c
--- sys/i386/i386/sys_machdep.c	22 Oct 2006 11:52:12 -0000	1.106
+++ sys/i386/i386/sys_machdep.c	30 Oct 2006 17:07:55 -0000
@@ -40,6 +40,7 @@
  #include <sys/lock.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: /zoo/cvsup/FreeBSD-CVS/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	30 Oct 2006 17:07:55 -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: /zoo/cvsup/FreeBSD-CVS/src/sys/i386/ibcs2/ibcs2_misc.c,v
retrieving revision 1.65
diff -u -r1.65 ibcs2_misc.c
--- sys/i386/ibcs2/ibcs2_misc.c	22 Oct 2006 11:52:12 -0000	1.65
+++ sys/i386/ibcs2/ibcs2_misc.c	30 Oct 2006 17:07:55 -0000
@@ -68,6 +68,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>
@@ -1008,14 +1009,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;
  }
@@ -1043,9 +1052,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:
@@ -1055,11 +1061,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: /zoo/cvsup/FreeBSD-CVS/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	30 Oct 2006 17:07:55 -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: /zoo/cvsup/FreeBSD-CVS/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	30 Oct 2006 17:07:55 -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: /zoo/cvsup/FreeBSD-CVS/src/sys/i386/linux/linux_machdep.c,v
retrieving revision 1.63
diff -u -r1.63 linux_machdep.c
--- sys/i386/linux/linux_machdep.c	20 Oct 2006 10:09:40 -0000	1.63
+++ sys/i386/linux/linux_machdep.c	30 Oct 2006 17:07:55 -0000
@@ -39,6 +39,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>
@@ -812,7 +813,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: /zoo/cvsup/FreeBSD-CVS/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	30 Oct 2006 17:07:55 -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: /zoo/cvsup/FreeBSD-CVS/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	30 Oct 2006 17:07:55 -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: /zoo/cvsup/FreeBSD-CVS/src/sys/isofs/cd9660/cd9660_vfsops.c,v
retrieving revision 1.146
diff -u -r1.146 cd9660_vfsops.c
--- sys/isofs/cd9660/cd9660_vfsops.c	26 Sep 2006 04:12:47 -0000	1.146
+++ sys/isofs/cd9660/cd9660_vfsops.c	30 Oct 2006 17:07:55 -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>
@@ -174,7 +175,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: /zoo/cvsup/FreeBSD-CVS/src/sys/kern/kern_acct.c,v
retrieving revision 1.84
diff -u -r1.84 kern_acct.c
--- sys/kern/kern_acct.c	22 Oct 2006 11:52:12 -0000	1.84
+++ sys/kern/kern_acct.c	30 Oct 2006 17:07:55 -0000
@@ -56,6 +56,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>
@@ -166,8 +167,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);

Index: sys/kern/kern_descrip.c
===================================================================
RCS file: /zoo/cvsup/FreeBSD-CVS/src/sys/kern/kern_descrip.c,v
retrieving revision 1.298
diff -u -r1.298 kern_descrip.c
--- sys/kern/kern_descrip.c	24 Sep 2006 02:29:53 -0000	1.298
+++ sys/kern/kern_descrip.c	30 Oct 2006 17:07:55 -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: /zoo/cvsup/FreeBSD-CVS/src/sys/kern/kern_environment.c,v
retrieving revision 1.45
diff -u -r1.45 kern_environment.c
--- sys/kern/kern_environment.c	22 Oct 2006 11:52:12 -0000	1.45
+++ sys/kern/kern_environment.c	30 Oct 2006 17:07:55 -0000
@@ -46,6 +46,7 @@
  #include <sys/lock.h>
  #include <sys/malloc.h>
  #include <sys/mutex.h>
+#include <sys/priv.h>
  #include <sys/kernel.h>
  #include <sys/systm.h>
  #include <sys/sysent.h>
@@ -125,11 +126,18 @@
  		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: /zoo/cvsup/FreeBSD-CVS/src/sys/kern/kern_exec.c,v
retrieving revision 1.298
diff -u -r1.298 kern_exec.c
--- sys/kern/kern_exec.c	22 Oct 2006 21:18:47 -0000	1.298
+++ sys/kern/kern_exec.c	31 Oct 2006 08:28:07 -0000
@@ -48,6 +48,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,11 @@
  		 * we do not regain any tracing during a possible block.
  		 */
  		setsugid(p);
+
  #ifdef KTRACE
-		if (p->p_tracevp != NULL && suser_cred(oldcred, SUSER_ALLOWJAIL)) {
+		if (p->p_tracevp != NULL &&
+		    priv_check_cred(oldcred, PRIV_DEBUG_DIFFCRED,
+		    SUSER_ALLOWJAIL)) {
  			mtx_lock(&ktrace_mtx);
  			p->p_traceflag = 0;
  			tracevp = p->p_tracevp;
Index: sys/kern/kern_fork.c
===================================================================
RCS file: /zoo/cvsup/FreeBSD-CVS/src/sys/kern/kern_fork.c,v
retrieving revision 1.263
diff -u -r1.263 kern_fork.c
--- sys/kern/kern_fork.c	26 Oct 2006 21:42:19 -0000	1.263
+++ sys/kern/kern_fork.c	30 Oct 2006 17:07:55 -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>
@@ -310,7 +311,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;
@@ -319,8 +320,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: /zoo/cvsup/FreeBSD-CVS/src/sys/kern/kern_jail.c,v
retrieving revision 1.53
diff -u -r1.53 kern_jail.c
--- sys/kern/kern_jail.c	22 Oct 2006 11:52:13 -0000	1.53
+++ sys/kern/kern_jail.c	30 Oct 2006 17:07:55 -0000
@@ -19,6 +19,7 @@
  #include <sys/errno.h>
  #include <sys/sysproto.h>
  #include <sys/malloc.h>
+#include <sys/priv.h>
  #include <sys/proc.h>
  #include <sys/taskqueue.h>
  #include <sys/jail.h>
@@ -205,7 +206,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 +524,172 @@
  	}
  }

+/*
+ * 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, int priv)
+{
+
+	if (!(jailed(cred)))
+		return (0);
+
+	switch (priv) {
+
+		/*
+		 * Allow ktrace privileges for root in jail.
+		 */
+	case PRIV_KTRACE:
+
+		/*
+		 * Allow jailed processes to configure audit identity and
+		 * submit audit records (login, etc).  In the future we may
+		 * want to further refine the relationship between audit and
+		 * jail.
+		 */
+	case PRIV_AUDIT_GETAUDIT:
+	case PRIV_AUDIT_SETAUDIT:
+	case PRIV_AUDIT_SUBMIT:
+
+		/*
+		 * Allow jailed processes to manipulate process UNIX
+		 * credentials in any way they see fit.
+		 */
+	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:
+
+		/*
+		 * Jail implements visibility constraints already, so allow
+		 * jailed root to override uid/gid-based constraints.
+		 */
+	case PRIV_SEEOTHERGIDS:
+	case PRIV_SEEOTHERUIDS:
+
+		/*
+		 * Jail implements inter-process debugging limits already, so
+		 * allow jailed root various debugging privileges.
+		 */
+	case PRIV_DEBUG_DIFFCRED:
+	case PRIV_DEBUG_SUGID:
+	case PRIV_DEBUG_UNPRIV:
+
+		/*
+		 * Allow jail to set various resource limits and login
+		 * properties, and for now, exceed process resource limits.
+		 */
+	case PRIV_PROC_LIMIT:
+	case PRIV_PROC_SETLOGIN:
+	case PRIV_PROC_SETRLIMIT:
+
+		/*
+		 * System V and POSIX IPC privileges are granted in jail.
+		 */
+	case PRIV_IPC_READ:
+	case PRIV_IPC_WRITE:
+	case PRIV_IPC_EXEC:
+	case PRIV_IPC_ADMIN:
+	case PRIV_IPC_MSGSIZE:
+	case PRIV_MQ_ADMIN:
+
+		/*
+		 * Jail implements its own inter-process limits, so allow
+		 * root processes in jail to change scheduling on other
+		 * processes in the same jail.  Likewise for signalling.
+		 */
+	case PRIV_SCHED_DIFFCRED:
+	case PRIV_SIGNAL_DIFFCRED:
+	case PRIV_SIGNAL_SUGID:
+
+		/*
+		 * Allow jailed processes to write to sysctls marked as jail
+		 * writable.
+		 */
+	case PRIV_SYSCTL_WRITEJAIL:
+
+		/*
+		 * Allow root in jail to manage a variety of quota
+		 * properties.  Some are a bit surprising and should be
+		 * reconsidered.
+		 */
+	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. */
+
+		/*
+		 * Since Jail relies on chroot() to implement file system
+		 * protections, grant many VFS privileges to root in jail.
+		 * Be careful to exclude mount-related and NFS-related
+		 * privileges.
+		 */
+	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_FCHROOT:
+	case PRIV_VFS_LINK:
+	case PRIV_VFS_SETGID:
+	case PRIV_VFS_STICKYFILE:
+		return (0);
+
+		/*
+		 * Depending on the global setting, allow privilege of
+		 * setting system flags.
+		 */
+	case PRIV_VFS_SYSFLAGS:
+		if (jail_chflags_allowed)
+			return (0);
+		else
+			return (EPERM);
+
+		/*
+		 * Allow jailed root to bind reserved ports.
+		 */
+	case PRIV_NETINET_RESERVEDPORT:
+		return (0);
+
+		/*
+		 * Conditionally allow creating raw sockets in jail.
+		 */
+	case PRIV_NETINET_RAW:
+		if (jail_allow_raw_sockets)
+			return (0);
+		else
+			return (EPERM);
+
+		/*
+		 * Since jail implements its own visibility limits on netstat
+		 * sysctls, allow getcred.  This allows identd to work in
+		 * jail.
+		 */
+	case PRIV_NETINET_GETCRED:
+		return (0);
+
+	default:
+		/*
+		 * In all remaining cases, deny the privilege request.  This
+		 * includes almost all network privileges, many system
+		 * configuration privileges.
+		 */
+		return (EPERM);
+	}
+}
+
  static int
  sysctl_jail_list(SYSCTL_HANDLER_ARGS)
  {
Index: sys/kern/kern_ktrace.c
===================================================================
RCS file: /zoo/cvsup/FreeBSD-CVS/src/sys/kern/kern_ktrace.c,v
retrieving revision 1.111
diff -u -r1.111 kern_ktrace.c
--- sys/kern/kern_ktrace.c	22 Oct 2006 11:52:13 -0000	1.111
+++ sys/kern/kern_ktrace.c	30 Oct 2006 17:07:55 -0000
@@ -47,6 +47,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>
@@ -807,7 +808,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 */
@@ -1013,7 +1015,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: /zoo/cvsup/FreeBSD-CVS/src/sys/kern/kern_linker.c,v
retrieving revision 1.143
diff -u -r1.143 kern_linker.c
--- sys/kern/kern_linker.c	22 Oct 2006 11:52:13 -0000	1.143
+++ sys/kern/kern_linker.c	30 Oct 2006 17:07:55 -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>
@@ -854,7 +855,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);

  	/*
@@ -921,7 +922,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: /zoo/cvsup/FreeBSD-CVS/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	30 Oct 2006 17:07:55 -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	31 Oct 2006 08:22:47 -0000
@@ -0,0 +1,154 @@
+/*-
+ * 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/priv.h>
+#include <sys/proc.h>
+#include <sys/sysctl.h>
+#include <sys/systm.h>
+
+#include <security/mac/mac_framework.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. 
+ */
+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, int 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);
+#ifdef NOTYET
+	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"));
+#endif
+	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 utility.
+	 */
+	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, int 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 kernel and modules are not yet fully adapted to the new model.
+ */
+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: /zoo/cvsup/FreeBSD-CVS/src/sys/kern/kern_prot.c,v
retrieving revision 1.205
diff -u -r1.205 kern_prot.c
--- sys/kern/kern_prot.c	22 Oct 2006 11:52:13 -0000	1.205
+++ sys/kern/kern_prot.c	30 Oct 2006 17:07:55 -0000
@@ -55,6 +55,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>
@@ -547,7 +548,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;

  	/*
@@ -563,7 +565,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
  	{
  		/*
@@ -639,7 +642,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;

  	/*
@@ -711,7 +715,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);
@@ -724,7 +729,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
  	{
  		/*
@@ -796,7 +802,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);
@@ -859,7 +866,8 @@
  		goto fail;
  #endif

-	error = suser_cred(oldcred, SUSER_ALLOWJAIL);
+	error = priv_check_cred(oldcred, PRIV_CRED_SETGROUPS,
+	    SUSER_ALLOWJAIL);
  	if (error)
  		goto fail;

@@ -931,7 +939,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);
@@ -999,7 +1008,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);
@@ -1079,7 +1089,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);
@@ -1160,7 +1171,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);
@@ -1324,65 +1336,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
@@ -1435,7 +1396,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);
@@ -1474,7 +1436,8 @@
  				break;
  		}
  		if (!match) {
-			if (suser_cred(u1, SUSER_ALLOWJAIL) != 0)
+			if (priv_check_cred(u1, PRIV_SEEOTHERGIDS,
+			    SUSER_ALLOWJAIL) != 0)
  				return (ESRCH);
  		}
  	}
@@ -1591,7 +1554,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);
  		}
@@ -1606,7 +1570,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);
  	}
@@ -1614,7 +1579,6 @@
  	return (0);
  }

-
  /*-
   * Determine whether td may deliver the specified signal to p.
   * Returns: 0 for permitted, an errno value otherwise
@@ -1683,19 +1647,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);
  }

  /*
@@ -1730,7 +1689,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);
  	}
@@ -1778,11 +1738,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);
  	}
@@ -1796,6 +1763,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().
@@ -2057,7 +2025,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: /zoo/cvsup/FreeBSD-CVS/src/sys/kern/kern_resource.c,v
retrieving revision 1.161
diff -u -r1.161 kern_resource.c
--- sys/kern/kern_resource.c	26 Oct 2006 21:42:19 -0000	1.161
+++ sys/kern/kern_resource.c	30 Oct 2006 17:07:55 -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);
@@ -468,7 +469,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;
@@ -754,7 +755,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: /zoo/cvsup/FreeBSD-CVS/src/sys/kern/kern_shutdown.c,v
retrieving revision 1.179
diff -u -r1.179 kern_shutdown.c
--- sys/kern/kern_shutdown.c	22 Oct 2006 11:52:13 -0000	1.179
+++ sys/kern/kern_shutdown.c	30 Oct 2006 17:07:55 -0000
@@ -55,6 +55,7 @@
  #include <sys/kthread.h>
  #include <sys/malloc.h>
  #include <sys/mount.h>
+#include <sys/priv.h>
  #include <sys/proc.h>
  #include <sys/reboot.h>
  #include <sys/resourcevar.h>
@@ -164,7 +165,7 @@
  	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: /zoo/cvsup/FreeBSD-CVS/src/sys/kern/kern_sysctl.c,v
retrieving revision 1.171
diff -u -r1.171 kern_sysctl.c
--- sys/kern/kern_sysctl.c	22 Oct 2006 11:52:13 -0000	1.171
+++ sys/kern/kern_sysctl.c	30 Oct 2006 17:07:55 -0000
@@ -46,6 +46,7 @@
  #include <sys/kernel.h>
  #include <sys/sysctl.h>
  #include <sys/malloc.h>
+#include <sys/priv.h>
  #include <sys/proc.h>
  #include <sys/lock.h>
  #include <sys/mutex.h>
@@ -512,7 +513,7 @@
  {
  	int error;

-	error = suser(req->td);
+	error = priv_check(req->td, PRIV_SYSCTL_DEBUG);
  	if (error)
  		return (error);
  	sysctl_sysctl_debug_dump_node(&sysctl__children, 0);
@@ -1253,13 +1254,11 @@

  	/* 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: /zoo/cvsup/FreeBSD-CVS/src/sys/kern/kern_thr.c,v
retrieving revision 1.54
diff -u -r1.54 kern_thr.c
--- sys/kern/kern_thr.c	26 Oct 2006 21:42:20 -0000	1.54
+++ sys/kern/kern_thr.c	30 Oct 2006 17:07:55 -0000
@@ -33,6 +33,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>
@@ -164,7 +165,7 @@
  		case RTP_PRIO_REALTIME:
  		case RTP_PRIO_FIFO:
  			/* Only root can set scheduler policy */
-			if (suser(td) != 0)
+			if (priv_check(td, PRIV_SCHED_SETPOLICY) != 0)
  				return (EPERM);
  			if (rtp->prio > RTP_PRIO_MAX)
  				return (EINVAL);
Index: sys/kern/kern_time.c
===================================================================
RCS file: /zoo/cvsup/FreeBSD-CVS/src/sys/kern/kern_time.c,v
retrieving revision 1.134
diff -u -r1.134 kern_time.c
--- sys/kern/kern_time.c	22 Oct 2006 11:52:13 -0000	1.134
+++ sys/kern/kern_time.c	30 Oct 2006 17:07:55 -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>
@@ -286,7 +287,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);
@@ -504,7 +505,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_umtx.c
===================================================================
RCS file: /zoo/cvsup/FreeBSD-CVS/src/sys/kern/kern_umtx.c,v
retrieving revision 1.53
diff -u -r1.53 kern_umtx.c
--- sys/kern/kern_umtx.c	26 Oct 2006 21:42:20 -0000	1.53
+++ sys/kern/kern_umtx.c	30 Oct 2006 17:07:55 -0000
@@ -35,6 +35,7 @@
  #include <sys/lock.h>
  #include <sys/malloc.h>
  #include <sys/mutex.h>
+#include <sys/priv.h>
  #include <sys/proc.h>
  #include <sys/sched.h>
  #include <sys/sysctl.h>
@@ -1813,7 +1814,7 @@
  	if ((error = umtx_key_get(m, TYPE_PP_UMUTEX, GET_SHARE(flags),
  	    &uq->uq_key)) != 0)
  		return (error);
-	su = (suser(td) == 0);
+	su = (priv_check(td, PRIV_SCHED_RTPRIO) == 0);
  	for (;;) {
  		old_inherited_pri = uq->uq_inherited_pri;
  		umtxq_lock(&uq->uq_key);
@@ -1934,7 +1935,7 @@

  	id = td->td_tid;
  	uq = td->td_umtxq;
-	su = (suser(td) == 0);
+	su = (priv_check(td, PRIV_SCHED_RTPRIO) == 0);

  	/*
  	 * Make sure we own this mtx.
Index: sys/kern/kern_xxx.c
===================================================================
RCS file: /zoo/cvsup/FreeBSD-CVS/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	30 Oct 2006 17:07:55 -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: /zoo/cvsup/FreeBSD-CVS/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	31 Oct 2006 08:30:24 -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: /zoo/cvsup/FreeBSD-CVS/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	30 Oct 2006 17:07:55 -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: /zoo/cvsup/FreeBSD-CVS/src/sys/kern/subr_prf.c,v
retrieving revision 1.125
diff -u -r1.125 subr_prf.c
--- sys/kern/subr_prf.c	17 Sep 2006 20:00:35 -0000	1.125
+++ sys/kern/subr_prf.c	30 Oct 2006 17:07:55 -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>
@@ -870,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: /zoo/cvsup/FreeBSD-CVS/src/sys/kern/subr_witness.c,v
retrieving revision 1.218
diff -u -r1.218 subr_witness.c
--- sys/kern/subr_witness.c	13 Sep 2006 15:48:15 -0000	1.218
+++ sys/kern/subr_witness.c	30 Oct 2006 17:07:55 -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>
@@ -533,7 +534,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_ipc.c
===================================================================
RCS file: /zoo/cvsup/FreeBSD-CVS/src/sys/kern/sysv_ipc.c,v
retrieving revision 1.29
diff -u -r1.29 sysv_ipc.c
--- sys/kern/sysv_ipc.c	6 Jan 2005 23:35:39 -0000	1.29
+++ sys/kern/sysv_ipc.c	31 Oct 2006 08:31:20 -0000
@@ -1,8 +1,12 @@
  /*	$NetBSD: sysv_ipc.c,v 1.7 1994/06/29 06:33:11 cgd Exp $	*/
  /*-
   * Copyright (c) 1994 Herb Peyerl <hpeyerl at novatel.ca>
+ * Copyright (c) 2006 nCircle Network Security, Inc.
   * All rights reserved.
   *
+ * This software was developed by Robert N. M. Watson for the TrustedBSD
+ * Project under contract to nCircle Network Security, Inc.
+ *
   * Redistribution and use in source and binary forms, with or without
   * modification, are permitted provided that the following conditions
   * are met:
@@ -39,6 +43,7 @@
  #include <sys/sem.h>
  #include <sys/shm.h>
  #include <sys/ipc.h>
+#include <sys/priv.h>
  #include <sys/proc.h>
  #include <sys/ucred.h>

@@ -72,50 +77,73 @@
   * Note: The MAC Framework does not require any modifications to the
   * ipcperm() function, as access control checks are performed throughout the
   * implementation of each primitive.  Those entry point calls complement the
- * ipcperm() discertionary checks.
+ * ipcperm() discertionary checks.  Unlike file system discretionary access
+ * control, the original create of an object is given the same rights as the
+ * current owner.
   */
  int
-ipcperm(td, perm, mode)
-	struct thread *td;
-	struct ipc_perm *perm;
-	int mode;
+ipcperm(struct thread *td, struct ipc_perm *perm, int acc_mode)
  {
  	struct ucred *cred = td->td_ucred;
-	int error;
+	int error, obj_mode, dac_granted, priv_granted;

-	if (cred->cr_uid != perm->cuid && cred->cr_uid != perm->uid) {
-		/*
-		 * For a non-create/owner, we require privilege to
-		 * modify the object protections.  Note: some other
-		 * implementations permit IPC_M to be delegated to
-		 * unprivileged non-creator/owner uids/gids.
-		 */
-		if (mode & IPC_M) {
-			error = suser(td);
-			if (error)
-				return (error);
-		}
-		/*
-		 * Try to match against creator/owner group; if not, fall
-		 * back on other.
-		 */
-		mode >>= 3;
-		if (!groupmember(perm->gid, cred) &&
-		    !groupmember(perm->cgid, cred))
-			mode >>= 3;
+	dac_granted = 0;
+	if (cred->cr_uid == perm->cuid || cred->cr_uid == perm->uid) {
+		obj_mode = perm->mode;
+		dac_granted |= IPC_M;
+	} else if (groupmember(perm->gid, cred) ||
+	    groupmember(perm->cgid, cred)) {
+		obj_mode = perm->mode;
+		obj_mode <<= 3;
  	} else {
-		/*
-		 * Always permit the creator/owner to update the object
-		 * protections regardless of whether the object mode
-		 * permits it.
-		 */
-		if (mode & IPC_M)
-			return (0);
+		obj_mode = perm->mode;
+		obj_mode <<= 6;
+	}
+
+	/*
+	 * While the System V IPC permission model allows IPC_M to be
+	 * granted, as part of the mode, our implementation requires
+	 * privilege to adminster the object if not the owner or creator.
+	 */
+#if 0
+	if (obj_mode & IPC_M)
+		dac_granted |= IPC_M;
+#endif
+	if (obj_mode & IPC_R)
+		dac_granted |= IPC_R;
+	if (obj_mode & IPC_W)
+		dac_granted |= IPC_W;
+
+	/*
+	 * Simple case: all required rights are granted by DAC.
+	 */
+	if ((dac_granted & acc_mode) == acc_mode)
+		return (0);
+
+	/*
+	 * Privilege is required to satisfy the request.
+	 */
+	priv_granted = 0;
+	if ((acc_mode & IPC_M) && !(dac_granted & IPC_M)) {
+		error = priv_check(td, PRIV_IPC_ADMIN);
+		if (error == 0)
+			priv_granted |= IPC_M;
  	}

-	if ((mode & perm->mode) != mode) {
-		if (suser(td) != 0)
-			return (EACCES);
+	if ((acc_mode & IPC_R) && !(dac_granted & IPC_R)) {
+		error = priv_check(td, PRIV_IPC_READ);
+		if (error == 0)
+			priv_granted |= IPC_R;
  	}
-	return (0);
+
+	if ((acc_mode & IPC_W) && !(dac_granted & IPC_W)) {
+		error = priv_check(td, PRIV_IPC_WRITE);
+		if (error == 0)
+			priv_granted |= IPC_W;
+	}
+
+	if (((dac_granted | priv_granted) & acc_mode) == acc_mode)
+		return (0);
+	else
+		return (EACCES);
  }
Index: sys/kern/sysv_msg.c
===================================================================
RCS file: /zoo/cvsup/FreeBSD-CVS/src/sys/kern/sysv_msg.c,v
retrieving revision 1.63
diff -u -r1.63 sysv_msg.c
--- sys/kern/sysv_msg.c	22 Oct 2006 11:52:13 -0000	1.63
+++ sys/kern/sysv_msg.c	30 Oct 2006 17:07:55 -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/mutex.h>
@@ -507,7 +508,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: /zoo/cvsup/FreeBSD-CVS/src/sys/kern/tty.c,v
retrieving revision 1.262
diff -u -r1.262 tty.c
--- sys/kern/tty.c	26 Oct 2006 21:42:20 -0000	1.262
+++ sys/kern/tty.c	30 Oct 2006 17:07:55 -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>
@@ -1020,7 +1021,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;
@@ -1169,9 +1170,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);
@@ -1244,7 +1245,7 @@
  		}
  		break;
  	case TIOCSDRAINWAIT:
-		error = suser(td);
+		error = priv_check(td, PRIV_TTY_DRAINWAIT);
  		if (error)
  			return (error);
  		tp->t_timeout = *(int *)data * hz;
@@ -3114,7 +3115,8 @@
  				goto out;
  			goto open_top;
  		}
-		if (tp->t_state & TS_XCLUDE && suser(td))
+		if (tp->t_state & TS_XCLUDE && priv_check(td,
+		    PRIV_TTY_EXCLUSIVE))
  			return (EBUSY);
  	} else {
  		/*
@@ -3340,7 +3342,7 @@
  	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: /zoo/cvsup/FreeBSD-CVS/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	30 Oct 2006 17:07:55 -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: /zoo/cvsup/FreeBSD-CVS/src/sys/kern/tty_pts.c,v
retrieving revision 1.10
diff -u -r1.10 tty_pts.c
--- sys/kern/tty_pts.c	29 Sep 2006 09:53:19 -0000	1.10
+++ sys/kern/tty_pts.c	30 Oct 2006 17:07:55 -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>
@@ -268,9 +269,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: /zoo/cvsup/FreeBSD-CVS/src/sys/kern/tty_pty.c,v
retrieving revision 1.150
diff -u -r1.150 tty_pty.c
--- sys/kern/tty_pty.c	4 Oct 2006 05:43:39 -0000	1.150
+++ sys/kern/tty_pty.c	30 Oct 2006 17:07:55 -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>
@@ -207,9 +208,11 @@

  	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: /zoo/cvsup/FreeBSD-CVS/src/sys/kern/uipc_mqueue.c,v
retrieving revision 1.16
diff -u -r1.16 uipc_mqueue.c
--- sys/kern/uipc_mqueue.c	26 Sep 2006 04:12:47 -0000	1.16
+++ sys/kern/uipc_mqueue.c	30 Oct 2006 17:07:55 -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>
@@ -955,8 +956,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;
@@ -1207,10 +1212,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;
@@ -1219,7 +1230,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: /zoo/cvsup/FreeBSD-CVS/src/sys/kern/uipc_sem.c,v
retrieving revision 1.25
diff -u -r1.25 uipc_sem.c
--- sys/kern/uipc_sem.c	22 Oct 2006 11:52:13 -0000	1.25
+++ sys/kern/uipc_sem.c	30 Oct 2006 17:07:55 -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>
@@ -419,15 +420,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: /zoo/cvsup/FreeBSD-CVS/src/sys/kern/vfs_mount.c,v
retrieving revision 1.241
diff -u -r1.241 vfs_mount.c
--- sys/kern/vfs_mount.c	22 Oct 2006 11:52:14 -0000	1.241
+++ sys/kern/vfs_mount.c	30 Oct 2006 17:07:55 -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>
@@ -808,23 +809,31 @@
  	if (jailed(td->td_ucred))
  		return (EPERM);
  	if (usermount == 0) {
-		if ((error = suser(td)) != 0)
+		if ((error = priv_check(td, PRIV_VFS_MOUNT)) != 0)
  			return (error);
  	}

  	/*
  	 * Do not allow NFS export or MNT_SUIDDIR by unprivileged users.
  	 */
-	if (fsflags & (MNT_EXPORTED | MNT_SUIDDIR)) {
-		if ((error = suser(td)) != 0)
+	if (fsflags & MNT_EXPORTED) {
+		error = priv_check(td, PRIV_VFS_MOUNT_EXPORTED);
+		if (error)
  			return (error);
  	}
+	if (fsflags & MNT_SUIDDIR) {
+		error = priv_check(td, PRIV_VFS_MOUNT_SUIDDIR);
+		if (error)
+			return (error);
+
+	}
  	/*
-	 * Silently enforce MNT_NOSUID and MNT_USER for
-	 * unprivileged users.
+	 * Silently enforce MNT_NOSUID and MNT_USER for unprivileged users.
  	 */
-	if (suser(td) != 0)
-		fsflags |= MNT_NOSUID | MNT_USER;
+	if ((fsflags & (MNT_NOSUID | MNT_USER)) != (MNT_NOSUID | MNT_USER)) {
+		if (priv_check(td, PRIV_VFS_MOUNT_NONUSER) != 0)
+			fsflags |= MNT_NOSUID | MNT_USER;
+	}

  	/* Load KLDs before we lock the covered vnode to avoid reversals. */
  	vfsp = NULL;
@@ -906,7 +915,9 @@
  			return (error);
  		}
  		if (va.va_uid != td->td_ucred->cr_uid) {
-			if ((error = suser(td)) != 0) {
+			error = priv_check_cred(td->td_ucred, PRIV_VFS_ADMIN,
+			    SUSER_ALLOWJAIL);
+			if (error) {
  				vput(vp);
  				return (error);
  			}
@@ -1078,7 +1089,8 @@
  	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: /zoo/cvsup/FreeBSD-CVS/src/sys/kern/vfs_subr.c,v
retrieving revision 1.686
diff -u -r1.686 vfs_subr.c
--- sys/kern/vfs_subr.c	22 Oct 2006 11:52:14 -0000	1.686
+++ sys/kern/vfs_subr.c	30 Oct 2006 17:07:55 -0000
@@ -61,6 +61,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>
@@ -412,7 +413,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);
@@ -3176,9 +3177,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
@@ -3232,59 +3231,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);
  }
@@ -3305,16 +3291,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: /zoo/cvsup/FreeBSD-CVS/src/sys/kern/vfs_syscalls.c,v
retrieving revision 1.427
diff -u -r1.427 vfs_syscalls.c
--- sys/kern/vfs_syscalls.c	26 Oct 2006 13:20:28 -0000	1.427
+++ sys/kern/vfs_syscalls.c	30 Oct 2006 17:07:55 -0000
@@ -60,6 +60,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>
@@ -272,7 +273,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);
@@ -357,7 +358,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);
@@ -468,7 +469,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);
@@ -842,7 +843,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,
@@ -896,8 +898,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)
@@ -1186,10 +1188,16 @@
  	switch (mode & S_IFMT) {
  	case S_IFCHR:
  	case S_IFBLK:
-		error = suser(td);
+		error = priv_check(td, PRIV_VFS_MKNOD_DEV);
+		break;
+	case S_IFMT:
+		error = priv_check(td, PRIV_VFS_MKNOD_BAD);
+		break;
+	case S_IFWHT:
+		error = priv_check(td, PRIV_VFS_MKNOD_WHT);
  		break;
  	default:
-		error = suser_cred(td->td_ucred, SUSER_ALLOWJAIL);
+		error = EINVAL;
  		break;
  	}
  	if (error)
@@ -1234,8 +1242,7 @@
  			whiteout = 1;
  			break;
  		default:
-			error = EINVAL;
-			break;
+			panic("kern_mknod: invalid mode");
  		}
  	}
  	if (vn_start_write(nd.ni_dvp, &mp, V_NOWAIT) != 0) {
@@ -1390,9 +1397,6 @@
  	struct vattr va;
  	int error;

-	if (suser_cred(cred, SUSER_ALLOWJAIL) == 0)
-		return (0);
-
  	if (!hardlink_check_uid && !hardlink_check_gid)
  		return (0);

@@ -1400,14 +1404,18 @@
  	if (error != 0)
  		return (error);

-	if (hardlink_check_uid) {
-		if (cred->cr_uid != va.va_uid)
-			return (EPERM);
+	if (hardlink_check_uid && cred->cr_uid != va.va_uid) {
+		error = priv_check_cred(cred, PRIV_VFS_LINK,
+		    SUSER_ALLOWJAIL);
+		if (error)
+			return (error);
  	}

-	if (hardlink_check_gid) {
-		if (!groupmember(va.va_gid, cred))
-			return (EPERM);
+	if (hardlink_check_gid && !groupmember(va.va_gid, cred)) {
+		error = priv_check_cred(cred, PRIV_VFS_LINK,
+		    SUSER_ALLOWJAIL);
+		if (error)
+			return (error);
  	}

  	return (0);
@@ -2361,7 +2369,8 @@
  	 * chown can't fail when done as root.
  	 */
  	if (vp->v_type == VCHR || vp->v_type == VBLK) {
-		error = suser_cred(td->td_ucred, SUSER_ALLOWJAIL);
+		error = priv_check_cred(td->td_ucred, PRIV_VFS_CHFLAGS_DEV,
+		    SUSER_ALLOWJAIL);
  		if (error)
  			return (error);
  	}
@@ -3894,7 +3903,8 @@
  	if (error)
  		goto out;
  	if (td->td_ucred->cr_uid != vattr.va_uid) {
-		error = suser_cred(td->td_ucred, SUSER_ALLOWJAIL);
+		error = priv_check_cred(td->td_ucred, PRIV_VFS_ADMIN,
+		    SUSER_ALLOWJAIL);
  		if (error)
  			goto out;
  	}
@@ -3960,7 +3970,7 @@
  	int vfslocked;
  	int error;

-	error = suser(td);
+	error = priv_check(td, PRIV_VFS_GETFH);
  	if (error)
  		return (error);
  	NDINIT(&nd, LOOKUP, NOFOLLOW | LOCKLEAF | MPSAFE | AUDITVNODE1,
@@ -3999,7 +4009,7 @@
  	int vfslocked;
  	int error;

-	error = suser(td);
+	error = priv_check(td, PRIV_VFS_GETFH);
  	if (error)
  		return (error);
  	NDINIT(&nd, LOOKUP, FOLLOW | LOCKLEAF | MPSAFE | AUDITVNODE1,
@@ -4022,10 +4032,10 @@
  }

  /*
- * syscall for the rpc.lockd to use to translate a NFS file handle into
- * an open descriptor.
+ * syscall for the rpc.lockd to use to translate a NFS file handle into an
+ * open descriptor.
   *
- * warning: do not remove the suser() call or this becomes one giant
+ * warning: do not remove the priv_check() call or this becomes one giant
   * security hole.
   *
   * MP SAFE
@@ -4058,7 +4068,7 @@
  	int vfslocked;
  	int indx;

-	error = suser(td);
+	error = priv_check(td, PRIV_VFS_FHOPEN);
  	if (error)
  		return (error);
  	fmode = FFLAGS(uap->flags);
@@ -4242,7 +4252,7 @@
  	int vfslocked;
  	int error;

-	error = suser(td);
+	error = priv_check(td, PRIV_VFS_FHSTAT);
  	if (error)
  		return (error);
  	error = copyin(uap->u_fhp, &fh, sizeof(fhandle_t));
@@ -4307,7 +4317,7 @@
  	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: /zoo/cvsup/FreeBSD-CVS/src/sys/kern/vfs_vnops.c,v
retrieving revision 1.245
diff -u -r1.245 vfs_vnops.c
--- sys/kern/vfs_vnops.c	22 Oct 2006 11:52:14 -0000	1.245
+++ sys/kern/vfs_vnops.c	30 Oct 2006 17:07:55 -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>
@@ -709,7 +710,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/net/bpf.c
===================================================================
RCS file: /zoo/cvsup/FreeBSD-CVS/src/sys/net/bpf.c,v
retrieving revision 1.173
diff -u -r1.173 bpf.c
--- sys/net/bpf.c	22 Oct 2006 11:52:15 -0000	1.173
+++ sys/net/bpf.c	30 Oct 2006 17:07:55 -0000
@@ -48,6 +48,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>
@@ -1724,7 +1725,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: /zoo/cvsup/FreeBSD-CVS/src/sys/net/if.c,v
retrieving revision 1.263
diff -u -r1.263 if.c
--- sys/net/if.c	22 Oct 2006 11:52:15 -0000	1.263
+++ sys/net/if.c	30 Oct 2006 17:07:55 -0000
@@ -44,6 +44,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>
@@ -1489,7 +1490,7 @@
  		break;

  	case SIOCSIFFLAGS:
-		error = suser(td);
+		error = priv_check(td, PRIV_NET_SETIFFLAGS);
  		if (error)
  			return (error);
  		/*
@@ -1532,7 +1533,7 @@
  		break;

  	case SIOCSIFCAP:
-		error = suser(td);
+		error = priv_check(td, PRIV_NET_SETIFCAP);
  		if (error)
  			return (error);
  		if (ifp->if_ioctl == NULL)
@@ -1553,8 +1554,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)
@@ -1600,7 +1601,7 @@
  		break;

  	case SIOCSIFMETRIC:
-		error = suser(td);
+		error = priv_check(td, PRIV_NET_SETIFMETRIC);
  		if (error)
  			return (error);
  		ifp->if_metric = ifr->ifr_metric;
@@ -1608,7 +1609,7 @@
  		break;

  	case SIOCSIFPHYS:
-		error = suser(td);
+		error = priv_check(td, PRIV_NET_SETIFPHYS);
  		if (error)
  			return (error);
  		if (ifp->if_ioctl == NULL)
@@ -1624,7 +1625,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)
@@ -1651,7 +1652,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);

@@ -1681,7 +1685,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)
@@ -1710,7 +1714,7 @@
  		break;

  	case SIOCSIFLLADDR:
-		error = suser(td);
+		error = priv_check(td, PRIV_NET_SETLLADDR);
  		if (error)
  			return (error);
  		error = if_setlladdr(ifp,
@@ -1721,7 +1725,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)))
@@ -1738,7 +1742,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)))
@@ -1777,12 +1781,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: /zoo/cvsup/FreeBSD-CVS/src/sys/net/if_bridge.c,v
retrieving revision 1.82
diff -u -r1.82 if_bridge.c
--- sys/net/if_bridge.c	9 Oct 2006 00:49:57 -0000	1.82
+++ sys/net/if_bridge.c	30 Oct 2006 17:07:55 -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>
@@ -678,7 +679,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: /zoo/cvsup/FreeBSD-CVS/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	30 Oct 2006 17:07:55 -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,7 +453,11 @@
  	case SIOCSIFDSTADDR:
  		break;
  	case SIOCSIFFLAGS:
-		if ((error = suser(curthread)) != 0)
+		/*
+		 * XXXRW: Isn't this suser() redundant to the ifnet layer
+		 * check?
+		 */
+		if ((error = priv_check(curthread, PRIV_NET_SETIFFLAGS)) != 0)
  			break;
  		if ((ifr->ifr_flags & IFF_LINK0) != 0)
  			sc->g_proto = IPPROTO_GRE;
@@ -464,7 +469,11 @@
  			sc->wccp_ver = WCCP_V1;
  		goto recompute;
  	case SIOCSIFMTU:
-		if ((error = suser(curthread)) != 0)
+		/*
+		 * XXXRW: Isn't this suser() redundant to the ifnet layer
+		 * check?
+		 */
+		if ((error = priv_check(curthread, PRIV_NET_SETIFMTU)) != 0)
  			break;
  		if (ifr->ifr_mtu < 576) {
  			error = EINVAL;
@@ -476,8 +485,36 @@
  		ifr->ifr_mtu = GRE2IFP(sc)->if_mtu;
  		break;
  	case SIOCADDMULTI:
+		/*
+		 * XXXRW: Isn't this suser() redundant to the ifnet layer
+		 * check?
+		 */
+		if ((error = priv_check(curthread, PRIV_NET_ADDMULTI)) != 0)
+			break;
+		if (ifr == 0) {
+			error = EAFNOSUPPORT;
+			break;
+		}
+		switch (ifr->ifr_addr.sa_family) {
+#ifdef INET
+		case AF_INET:
+			break;
+#endif
+#ifdef INET6
+		case AF_INET6:
+			break;
+#endif
+		default:
+			error = EAFNOSUPPORT;
+			break;
+		}
+		break;
  	case SIOCDELMULTI:
-		if ((error = suser(curthread)) != 0)
+		/*
+		 * XXXRW: Isn't this suser() redundant to the ifnet layer
+		 * check?
+		 */
+		if ((error = priv_check(curthread, PRIV_NET_DELIFGROUP)) != 0)
  			break;
  		if (ifr == 0) {
  			error = EAFNOSUPPORT;
@@ -498,7 +535,11 @@
  		}
  		break;
  	case GRESPROTO:
-		if ((error = suser(curthread)) != 0)
+		/*
+		 * XXXRW: Isn't this suser() redundant to the ifnet layer
+		 * check?
+		 */
+		if ((error = priv_check(curthread, PRIV_NET_GRE)) != 0)
  			break;
  		sc->g_proto = ifr->ifr_flags;
  		switch (sc->g_proto) {
@@ -518,8 +559,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,7 +626,11 @@
  		ifr->ifr_addr = *sa;
  		break;
  	case SIOCSIFPHYADDR:
-		if ((error = suser(curthread)) != 0)
+		/*
+		 * XXXRW: Isn't this suser() redundant to the ifnet layer
+		 * check?
+		 */
+		if ((error = priv_check(curthread, PRIV_NET_SETIFPHYS)) != 0)
  			break;
  		if (aifr->ifra_addr.sin_family != AF_INET ||
  		    aifr->ifra_dstaddr.sin_family != AF_INET) {
@@ -600,7 +646,11 @@
  		sc->g_dst = aifr->ifra_dstaddr.sin_addr;
  		goto recompute;
  	case SIOCSLIFPHYADDR:
-		if ((error = suser(curthread)) != 0)
+		/*
+		 * XXXRW: Isn't this suser() redundant to the ifnet layer
+		 * check?
+		 */
+		if ((error = priv_check(curthread, PRIV_NET_SETIFPHYS)) != 0)
  			break;
  		if (lifr->addr.ss_family != AF_INET ||
  		    lifr->dstaddr.ss_family != AF_INET) {
@@ -617,7 +667,11 @@
  		    (satosin(&lifr->dstaddr))->sin_addr;
  		goto recompute;
  	case SIOCDIFPHYADDR:
-		if ((error = suser(curthread)) != 0)
+		/*
+		 * XXXRW: Isn't this suser() redundant to the ifnet layer
+		 * check?
+		 */
+		if ((error = priv_check(curthread, PRIV_NET_SETIFPHYS)) != 0)
  			break;
  		sc->g_src.s_addr = INADDR_ANY;
  		sc->g_dst.s_addr = INADDR_ANY;
Index: sys/net/if_ppp.c
===================================================================
RCS file: /zoo/cvsup/FreeBSD-CVS/src/sys/net/if_ppp.c,v
retrieving revision 1.116
diff -u -r1.116 if_ppp.c
--- sys/net/if_ppp.c	22 Oct 2006 11:52:15 -0000	1.116
+++ sys/net/if_ppp.c	30 Oct 2006 17:07:55 -0000
@@ -87,6 +87,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>
@@ -451,7 +452,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();
@@ -465,8 +467,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;
@@ -478,7 +481,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();
@@ -489,14 +493,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;
@@ -569,7 +575,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();
@@ -695,6 +702,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: /zoo/cvsup/FreeBSD-CVS/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	30 Oct 2006 17:07:55 -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: /zoo/cvsup/FreeBSD-CVS/src/sys/net/if_tap.c,v
retrieving revision 1.63
diff -u -r1.63 if_tap.c
--- sys/net/if_tap.c	27 Sep 2006 19:57:01 -0000	1.63
+++ sys/net/if_tap.c	30 Oct 2006 17:07:55 -0000
@@ -47,6 +47,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>
@@ -373,10 +374,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: /zoo/cvsup/FreeBSD-CVS/src/sys/net/if_tun.c,v
retrieving revision 1.159
diff -u -r1.159 if_tun.c
--- sys/net/if_tun.c	22 Oct 2006 11:52:15 -0000	1.159
+++ sys/net/if_tun.c	30 Oct 2006 17:07:55 -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/mbuf.h>
@@ -597,9 +598,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: /zoo/cvsup/FreeBSD-CVS/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	30 Oct 2006 17:07:55 -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: /zoo/cvsup/FreeBSD-CVS/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	30 Oct 2006 17:07:55 -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: /zoo/cvsup/FreeBSD-CVS/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	30 Oct 2006 17:07:55 -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: /zoo/cvsup/FreeBSD-CVS/src/sys/net80211/ieee80211_ioctl.c,v
retrieving revision 1.50
diff -u -r1.50 ieee80211_ioctl.c
--- sys/net80211/ieee80211_ioctl.c	26 Sep 2006 12:41:13 -0000	1.50
+++ sys/net80211/ieee80211_ioctl.c	30 Oct 2006 17:07:55 -0000
@@ -45,6 +45,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>
@@ -344,7 +345,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;
@@ -861,7 +862,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;
@@ -1510,7 +1511,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);
@@ -2692,7 +2693,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);
@@ -2701,7 +2702,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: /zoo/cvsup/FreeBSD-CVS/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	30 Oct 2006 17:07:55 -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: /zoo/cvsup/FreeBSD-CVS/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	30 Oct 2006 17:07:55 -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: /zoo/cvsup/FreeBSD-CVS/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	30 Oct 2006 17:07:55 -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: /zoo/cvsup/FreeBSD-CVS/src/sys/netgraph/ng_socket.c,v
retrieving revision 1.80
diff -u -r1.80 ng_socket.c
--- sys/netgraph/ng_socket.c	18 Oct 2006 07:47:07 -0000	1.80
+++ sys/netgraph/ng_socket.c	30 Oct 2006 17:07:55 -0000
@@ -57,6 +57,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/socket.h>
@@ -167,9 +168,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: /zoo/cvsup/FreeBSD-CVS/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	30 Oct 2006 17:07:55 -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/netgraph/bluetooth/drivers/h4/ng_h4.c
===================================================================
RCS file: /zoo/cvsup/FreeBSD-CVS/src/sys/netgraph/bluetooth/drivers/h4/ng_h4.c,v
retrieving revision 1.14
diff -u -r1.14 ng_h4.c
--- sys/netgraph/bluetooth/drivers/h4/ng_h4.c	16 Oct 2005 20:44:18 -0000	1.14
+++ sys/netgraph/bluetooth/drivers/h4/ng_h4.c	30 Oct 2006 17:07:55 -0000
@@ -48,6 +48,7 @@
  #include <sys/ioccom.h>
  #include <sys/malloc.h>
  #include <sys/mbuf.h>
+#include <sys/priv.h>
  #include <sys/tty.h>
  #include <sys/ttycom.h>
  #include <netgraph/ng_message.h>
@@ -156,7 +157,7 @@
  	int		 s, error;

  	/* Super-user only */
-	error = suser(curthread); /* XXX */
+	error = priv_check(curthread, PRIV_NETGRAPH_TTY); /* XXX */
  	if (error != 0)
  		return (error);

Index: sys/netgraph/bluetooth/socket/ng_btsocket_hci_raw.c
===================================================================
RCS file: /zoo/cvsup/FreeBSD-CVS/src/sys/netgraph/bluetooth/socket/ng_btsocket_hci_raw.c,v
retrieving revision 1.22
diff -u -r1.22 ng_btsocket_hci_raw.c
--- sys/netgraph/bluetooth/socket/ng_btsocket_hci_raw.c	21 Jul 2006 17:11:13 -0000	1.22
+++ sys/netgraph/bluetooth/socket/ng_btsocket_hci_raw.c	30 Oct 2006 17:07:55 -0000
@@ -44,6 +44,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/socket.h>
@@ -916,7 +917,7 @@
  	so->so_pcb = (caddr_t) pcb;
  	pcb->so = so;

-	if (suser(td) == 0)
+	if (priv_check(td, PRIV_NETBLUETOOTH_RAW) == 0)
  		pcb->flags |= NG_BTSOCKET_HCI_RAW_PRIVILEGED;

  	/*
Index: sys/netgraph/bluetooth/socket/ng_btsocket_l2cap_raw.c
===================================================================
RCS file: /zoo/cvsup/FreeBSD-CVS/src/sys/netgraph/bluetooth/socket/ng_btsocket_l2cap_raw.c,v
retrieving revision 1.19
diff -u -r1.19 ng_btsocket_l2cap_raw.c
--- sys/netgraph/bluetooth/socket/ng_btsocket_l2cap_raw.c	21 Jul 2006 17:11:13 -0000	1.19
+++ sys/netgraph/bluetooth/socket/ng_btsocket_l2cap_raw.c	30 Oct 2006 17:07:55 -0000
@@ -43,6 +43,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/socket.h>
@@ -620,7 +621,7 @@
  	so->so_pcb = (caddr_t) pcb;
  	pcb->so = so;

-	if (suser(td) == 0)
+	if (priv_check(td, PRIV_NETBLUETOOTH_RAW) == 0)
  		pcb->flags |= NG_BTSOCKET_L2CAP_RAW_PRIVILEGED;

  	mtx_init(&pcb->pcb_mtx, "btsocks_l2cap_raw_pcb_mtx", NULL, MTX_DEF);
Index: sys/netinet/in.c
===================================================================
RCS file: /zoo/cvsup/FreeBSD-CVS/src/sys/netinet/in.c,v
retrieving revision 1.94
diff -u -r1.94 in.c
--- sys/netinet/in.c	28 Sep 2006 10:04:07 -0000	1.94
+++ sys/netinet/in.c	30 Oct 2006 17:07:55 -0000
@@ -37,6 +37,7 @@
  #include <sys/systm.h>
  #include <sys/sockio.h>
  #include <sys/malloc.h>
+#include <sys/priv.h>
  #include <sys/socket.h>
  #include <sys/kernel.h>
  #include <sys/sysctl.h>
@@ -232,10 +233,25 @@

  	switch (cmd) {
  	case SIOCALIFADDR:
+		if (td != NULL) {
+			error = priv_check(td, PRIV_NET_ADDIFADDR);
+			if (error)
+				return (error);
+		}
+		if (!ifp)
+			return EINVAL;
+		return in_lifaddr_ioctl(so, cmd, data, ifp, td);
+
  	case SIOCDLIFADDR:
-		if (td && (error = suser(td)) != 0)
-			return error;
-		/*fall through*/
+		if (td != NULL) {
+			error = priv_check(td, PRIV_NET_DELIFADDR);
+			if (error)
+				return (error);
+		}
+		if (!ifp)
+			return EINVAL;
+		return in_lifaddr_ioctl(so, cmd, data, ifp, td);
+
  	case SIOCGLIFADDR:
  		if (!ifp)
  			return EINVAL;
@@ -292,8 +308,11 @@
  	case SIOCSIFADDR:
  	case SIOCSIFNETMASK:
  	case SIOCSIFDSTADDR:
-		if (td && (error = suser(td)) != 0)
-			return error;
+		if (td != NULL) {
+			error = priv_check(td, PRIV_NET_ADDIFADDR);
+			if (error)
+				return (error);
+		}

  		if (ifp == 0)
  			return (EADDRNOTAVAIL);
@@ -330,8 +349,11 @@
  		break;

  	case SIOCSIFBRDADDR:
-		if (td && (error = suser(td)) != 0)
-			return error;
+		if (td != NULL) {
+			error = priv_check(td, PRIV_NET_ADDIFADDR);
+			if (error)
+				return (error);
+		}
  		/* FALLTHROUGH */

  	case SIOCGIFADDR:
Index: sys/netinet/in_pcb.c
===================================================================
RCS file: /zoo/cvsup/FreeBSD-CVS/src/sys/netinet/in_pcb.c,v
retrieving revision 1.182
diff -u -r1.182 in_pcb.c
--- sys/netinet/in_pcb.c	22 Oct 2006 11:52:16 -0000	1.182
+++ sys/netinet/in_pcb.c	30 Oct 2006 17:07:55 -0000
@@ -42,6 +42,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>
@@ -331,7 +332,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;
@@ -400,7 +402,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: /zoo/cvsup/FreeBSD-CVS/src/sys/netinet/ip_carp.c,v
retrieving revision 1.44
diff -u -r1.44 ip_carp.c
--- sys/netinet/ip_carp.c	7 Oct 2006 10:19:58 -0000	1.44
+++ sys/netinet/ip_carp.c	30 Oct 2006 17:07:55 -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>
@@ -1853,7 +1854,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;
@@ -1928,7 +1930,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: /zoo/cvsup/FreeBSD-CVS/src/sys/netinet/ip_divert.c,v
retrieving revision 1.121
diff -u -r1.121 ip_divert.c
--- sys/netinet/ip_divert.c	22 Oct 2006 11:52:16 -0000	1.121
+++ sys/netinet/ip_divert.c	30 Oct 2006 17:07:55 -0000
@@ -48,6 +48,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>
@@ -420,8 +421,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: /zoo/cvsup/FreeBSD-CVS/src/sys/netinet/ip_fw2.c,v
retrieving revision 1.152
diff -u -r1.152 ip_fw2.c
--- sys/netinet/ip_fw2.c	22 Oct 2006 11:52:16 -0000	1.152
+++ sys/netinet/ip_fw2.c	30 Oct 2006 17:07:55 -0000
@@ -53,6 +53,7 @@
  #include <sys/lock.h>
  #include <sys/jail.h>
  #include <sys/module.h>
+#include <sys/priv.h>
  #include <sys/proc.h>
  #include <sys/rwlock.h>
  #include <sys/socket.h>
@@ -3980,7 +3981,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: /zoo/cvsup/FreeBSD-CVS/src/sys/netinet/ip_mroute.c,v
retrieving revision 1.121
diff -u -r1.121 ip_mroute.c
--- sys/netinet/ip_mroute.c	22 Oct 2006 11:52:16 -0000	1.121
+++ sys/netinet/ip_mroute.c	30 Oct 2006 17:07:56 -0000
@@ -68,6 +68,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>
@@ -576,7 +577,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: /zoo/cvsup/FreeBSD-CVS/src/sys/netinet/ip_output.c,v
retrieving revision 1.267
diff -u -r1.267 ip_output.c
--- sys/netinet/ip_output.c	22 Oct 2006 11:52:16 -0000	1.267
+++ sys/netinet/ip_output.c	30 Oct 2006 17:07:56 -0000
@@ -40,6 +40,7 @@
  #include <sys/kernel.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>
@@ -987,8 +988,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: /zoo/cvsup/FreeBSD-CVS/src/sys/netinet/raw_ip.c,v
retrieving revision 1.166
diff -u -r1.166 raw_ip.c
--- sys/netinet/raw_ip.c	22 Oct 2006 11:52:16 -0000	1.166
+++ sys/netinet/raw_ip.c	30 Oct 2006 17:07:56 -0000
@@ -40,6 +40,7 @@
  #include <sys/lock.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>
@@ -387,7 +388,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)
@@ -397,7 +402,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)
@@ -418,7 +423,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) :
@@ -452,7 +457,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)
@@ -464,7 +472,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)
@@ -474,14 +482,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();
@@ -489,7 +497,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 ?
@@ -508,7 +516,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) :
@@ -598,9 +606,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: /zoo/cvsup/FreeBSD-CVS/src/sys/netinet/tcp_subr.c,v
retrieving revision 1.265
diff -u -r1.265 tcp_subr.c
--- sys/netinet/tcp_subr.c	22 Oct 2006 11:52:16 -0000	1.265
+++ sys/netinet/tcp_subr.c	30 Oct 2006 17:07:56 -0000
@@ -48,6 +48,7 @@
  #ifdef INET6
  #include <sys/domain.h>
  #endif
+#include <sys/priv.h>
  #include <sys/proc.h>
  #include <sys/socket.h>
  #include <sys/socketvar.h>
@@ -1081,7 +1082,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));
@@ -1125,7 +1127,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: /zoo/cvsup/FreeBSD-CVS/src/sys/netinet/udp_usrreq.c,v
retrieving revision 1.195
diff -u -r1.195 udp_usrreq.c
--- sys/netinet/udp_usrreq.c	22 Oct 2006 11:52:17 -0000	1.195
+++ sys/netinet/udp_usrreq.c	30 Oct 2006 17:07:56 -0000
@@ -44,6 +44,7 @@
  #include <sys/lock.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>
@@ -687,7 +688,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: /zoo/cvsup/FreeBSD-CVS/src/sys/netinet6/in6.c,v
retrieving revision 1.64
diff -u -r1.64 in6.c
--- sys/netinet6/in6.c	22 Sep 2006 01:42:22 -0000	1.64
+++ sys/netinet6/in6.c	30 Oct 2006 17:07:56 -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: /zoo/cvsup/FreeBSD-CVS/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	30 Oct 2006 17:07:56 -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: /zoo/cvsup/FreeBSD-CVS/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	30 Oct 2006 17:07:56 -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: /zoo/cvsup/FreeBSD-CVS/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	30 Oct 2006 17:07:56 -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: /zoo/cvsup/FreeBSD-CVS/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	30 Oct 2006 17:07:56 -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: /zoo/cvsup/FreeBSD-CVS/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	30 Oct 2006 17:07:56 -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: /zoo/cvsup/FreeBSD-CVS/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	30 Oct 2006 17:07:56 -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: /zoo/cvsup/FreeBSD-CVS/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	30 Oct 2006 17:07:56 -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: /zoo/cvsup/FreeBSD-CVS/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	30 Oct 2006 17:07:56 -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: /zoo/cvsup/FreeBSD-CVS/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	30 Oct 2006 17:07:56 -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: /zoo/cvsup/FreeBSD-CVS/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	30 Oct 2006 17:07:56 -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: /zoo/cvsup/FreeBSD-CVS/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	30 Oct 2006 17:07:56 -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: /zoo/cvsup/FreeBSD-CVS/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	30 Oct 2006 17:07:56 -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: /zoo/cvsup/FreeBSD-CVS/src/sys/nfsserver/nfs_syscalls.c,v
retrieving revision 1.107
diff -u -r1.107 nfs_syscalls.c
--- sys/nfsserver/nfs_syscalls.c	22 Oct 2006 11:52:17 -0000	1.107
+++ sys/nfsserver/nfs_syscalls.c	30 Oct 2006 17:07:56 -0000
@@ -48,6 +48,7 @@
  #include <sys/vnode.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>
@@ -142,7 +143,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: /zoo/cvsup/FreeBSD-CVS/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	30 Oct 2006 17:07:56 -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: /zoo/cvsup/FreeBSD-CVS/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	30 Oct 2006 17:07:56 -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: /zoo/cvsup/FreeBSD-CVS/src/sys/security/audit/audit.c,v
retrieving revision 1.21
diff -u -r1.21 audit.c
--- sys/security/audit/audit.c	2 Oct 2006 11:32:23 -0000	1.21
+++ sys/security/audit/audit.c	30 Oct 2006 17:07:56 -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>
@@ -509,7 +510,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: /zoo/cvsup/FreeBSD-CVS/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	30 Oct 2006 17:07:56 -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: /zoo/cvsup/FreeBSD-CVS/src/sys/security/audit/audit_syscalls.c,v
retrieving revision 1.8
diff -u -r1.8 audit_syscalls.c
--- sys/security/audit/audit_syscalls.c	10 Oct 2006 15:49:10 -0000	1.8
+++ sys/security/audit/audit_syscalls.c	30 Oct 2006 17:07:56 -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>
@@ -66,7 +67,7 @@

  	if (jailed(td->td_ucred))
  		return (ENOSYS);
-	error = suser(td);
+	error = priv_check(td, PRIV_AUDIT_SUBMIT);
  	if (error)
  		return (error);

@@ -156,7 +157,7 @@
  	if (jailed(td->td_ucred))
  		return (ENOSYS);
  	AUDIT_ARG(cmd, uap->cmd);
-	error = suser(td);
+	error = priv_check(td, PRIV_AUDIT_CONTROL);
  	if (error)
  		return (error);

@@ -404,7 +405,7 @@

  	if (jailed(td->td_ucred))
  		return (ENOSYS);
-	error = suser(td);
+	error = priv_check(td, PRIV_AUDIT_GETAUDIT);
  	if (error)
  		return (error);

@@ -428,7 +429,7 @@

  	if (jailed(td->td_ucred))
  		return (ENOSYS);
-	error = suser(td);
+	error = priv_check(td, PRIV_AUDIT_SETAUDIT);
  	if (error)
  		return (error);

@@ -468,7 +469,7 @@

  	if (jailed(td->td_ucred))
  		return (ENOSYS);
-	error = suser(td);
+	error = priv_check(td, PRIV_AUDIT_GETAUDIT);
  	if (error)
  		return (error);

@@ -489,7 +490,7 @@

  	if (jailed(td->td_ucred))
  		return (ENOSYS);
-	error = suser(td);
+	error = priv_check(td, PRIV_AUDIT_SETAUDIT);
  	if (error)
  		return (error);

@@ -518,7 +519,7 @@

  	if (jailed(td->td_ucred))
  		return (ENOSYS);
-	error = suser(td);
+	error = priv_check(td, PRIV_AUDIT_GETAUDIT);
  	if (error)
  		return (error);
  	return (ENOSYS);
@@ -533,7 +534,7 @@

  	if (jailed(td->td_ucred))
  		return (ENOSYS);
-	error = suser(td);
+	error = priv_check(td, PRIV_AUDIT_SETAUDIT);
  	if (error)
  		return (error);
  	return (ENOSYS);
@@ -557,7 +558,7 @@

  	if (jailed(td->td_ucred))
  		return (ENOSYS);
-	error = suser(td);
+	error = priv_check(td, PRIV_AUDIT_CONTROL);
  	if (error)
  		return (error);

Index: sys/security/mac/mac_framework.h
===================================================================
RCS file: /zoo/cvsup/FreeBSD-CVS/src/sys/security/mac/mac_framework.h,v
retrieving revision 1.74
diff -u -r1.74 mac_framework.h
--- sys/security/mac/mac_framework.h	25 Oct 2006 13:14:25 -0000	1.74
+++ sys/security/mac/mac_framework.h	30 Oct 2006 17:07:56 -0000
@@ -407,6 +407,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, int priv);
+int	mac_priv_grant(struct ucred *cred, int priv);

  /*
   * Calls to help various file systems implement labeling functionality
Index: sys/security/mac/mac_internal.h
===================================================================
RCS file: /zoo/cvsup/FreeBSD-CVS/src/sys/security/mac/mac_internal.h,v
retrieving revision 1.114
diff -u -r1.114 mac_internal.h
--- sys/security/mac/mac_internal.h	20 Sep 2006 13:33:40 -0000	1.114
+++ sys/security/mac/mac_internal.h	30 Oct 2006 17:07:56 -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:
@@ -152,6 +156,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: /zoo/cvsup/FreeBSD-CVS/src/sys/security/mac/mac_net.c,v
retrieving revision 1.119
diff -u -r1.119 mac_net.c
--- sys/security/mac/mac_net.c	22 Oct 2006 11:52:18 -0000	1.119
+++ sys/security/mac/mac_net.c	30 Oct 2006 17:07:56 -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>
@@ -470,11 +471,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	30 Oct 2006 18:53:30 -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_policy.h>
+
+#include <security/mac/mac_framework.h>
+#include <security/mac/mac_internal.h>
+
+int
+mac_priv_check(struct ucred *cred, int priv)
+{
+	int error;
+
+	MAC_CHECK(priv_check, cred, priv);
+
+	return (error);
+}
+
+int
+mac_priv_grant(struct ucred *cred, int priv)
+{
+	int error;
+
+	MAC_GRANT(priv_grant, cred, priv);
+
+	return (error);
+}
Index: sys/security/mac/mac_system.c
===================================================================
RCS file: /zoo/cvsup/FreeBSD-CVS/src/sys/security/mac/mac_system.c,v
retrieving revision 1.106
diff -u -r1.106 mac_system.c
--- sys/security/mac/mac_system.c	22 Oct 2006 11:52:18 -0000	1.106
+++ sys/security/mac/mac_system.c	30 Oct 2006 17:07:56 -0000
@@ -60,6 +60,12 @@
      &mac_enforce_system, 0, "Enforce MAC policy on system operations");
  TUNABLE_INT("security.mac.enforce_system", &mac_enforce_system);

+/*
+ * XXXRW: Some of these checks now duplicate privilege checks.  However,
+ * others provide additional security context that may be useful to policies.
+ * We need to review these and remove ones that are pure duplicates.
+ */
+
  int
  mac_check_kenv_dump(struct ucred *cred)
  {
Index: sys/security/mac_bsdextended/mac_bsdextended.c
===================================================================
RCS file: /zoo/cvsup/FreeBSD-CVS/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	30 Oct 2006 17:07:56 -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: /zoo/cvsup/FreeBSD-CVS/src/sys/security/mac_lomac/mac_lomac.c,v
retrieving revision 1.41
diff -u -r1.41 mac_lomac.c
--- sys/security/mac_lomac/mac_lomac.c	22 Oct 2006 11:52:19 -0000	1.41
+++ sys/security/mac_lomac/mac_lomac.c	30 Oct 2006 17:07:56 -0000
@@ -48,6 +48,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: /zoo/cvsup/FreeBSD-CVS/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	30 Oct 2006 17:07:56 -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: /zoo/cvsup/FreeBSD-CVS/src/sys/security/mac_portacl/mac_portacl.c,v
retrieving revision 1.9
diff -u -r1.9 mac_portacl.c
--- sys/security/mac_portacl/mac_portacl.c	10 Oct 2006 17:04:19 -0000	1.9
+++ sys/security/mac_portacl/mac_portacl.c	30 Oct 2006 17:07:56 -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, SUSER_ALLOWJAIL);
+		error = priv_check_cred(cred, PRIV_NETINET_RESERVEDPORT,
+		    SUSER_ALLOWJAIL);

  	return (error);
  }
Index: sys/security/mac_seeotheruids/mac_seeotheruids.c
===================================================================
RCS file: /zoo/cvsup/FreeBSD-CVS/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	30 Oct 2006 17:07:56 -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/sun4v/sun4v/hvcons.c
===================================================================
RCS file: /zoo/cvsup/FreeBSD-CVS/src/sys/sun4v/sun4v/hvcons.c,v
retrieving revision 1.2
diff -u -r1.2 hvcons.c
--- sys/sun4v/sun4v/hvcons.c	13 Oct 2006 06:45:50 -0000	1.2
+++ sys/sun4v/sun4v/hvcons.c	30 Oct 2006 17:07:56 -0000
@@ -36,6 +36,7 @@
  #include <sys/conf.h>
  #include <sys/cons.h>
  #include <sys/consio.h>
+#include <sys/priv.h>
  #include <sys/rman.h>
  #include <sys/tty.h>

@@ -118,7 +119,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/sys/jail.h
===================================================================
RCS file: /zoo/cvsup/FreeBSD-CVS/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	30 Oct 2006 18:52:31 -0000
@@ -110,6 +110,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, int priv);
  void prison_remote_ip(struct ucred *cred, int flags, u_int32_t *ip);

  #endif /* _KERNEL */
Index: sys/sys/mac_policy.h
===================================================================
RCS file: /zoo/cvsup/FreeBSD-CVS/src/sys/sys/mac_policy.h,v
retrieving revision 1.77
diff -u -r1.77 mac_policy.h
--- sys/sys/mac_policy.h	30 Oct 2006 15:20:49 -0000	1.77
+++ sys/sys/mac_policy.h	30 Oct 2006 17:07:56 -0000
@@ -596,6 +596,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, int priv);
+typedef int	(*mpo_priv_grant_t)(struct ucred *cred, int priv);

  struct mac_policy_ops {
  	/*
@@ -886,6 +888,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	31 Oct 2006 08:20:40 -0000
@@ -0,0 +1,457 @@
+/*-
+ * 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.
+ */
+
+/*
+ * Track beginning of privilege list.
+ */
+#define	_PRIV_LOWEST	0
+
+/*
+ * PRIV_ROOT is a catch-all for as yet unnamed privileges.  No new
+ * references to this privilege should be added.
+ */
+#define	PRIV_ROOT	1	/* 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.
+ */
+#define	PRIV_ACCT		2	/* Manage process accounting. */
+#define	PRIV_MAXFILES		3	/* Exceed system open files limit. */
+#define	PRIV_MAXPROC		4	/* Exceed system processes limit. */
+#define	PRIV_KTRACE		5	/* Set/clear KTRFAC_ROOT on ktrace. */
+#define	PRIV_SETDUMPER		6	/* Configure dump device. */
+#define	PRIV_NFSD		7	/* Can become NFS daemon. */
+#define	PRIV_REBOOT		8	/* Can reboot system. */
+#define	PRIV_SWAPON		9	/* Can swapon(). */
+#define	PRIV_SWAPOFF		10	/* Can swapoff(). */
+#define	PRIV_MSGBUF		11	/* Can read kernel message buffer. */
+#define	PRIV_WITNESS		12	/* Can configure WITNESS. */
+#define	PRIV_IO			13	/* Can perform low-level I/O. */
+#define	PRIV_KEYBOARD		14	/* Reprogram keyboard. */
+#define	PRIV_DRIVER		15	/* Low-level driver privilege. */
+#define	PRIV_ADJTIME		16	/* Set time adjustment. */
+#define	PRIV_NTP_ADJTIME	17	/* Set NTP time adjustment. */
+#define	PRIV_CLOCK_SETTIME	18	/* Can call clock_settime. */
+#define	PRIV_SETTIMEOFDAY	19	/* Can call settimeofday. */
+#define	PRIV_SETHOSTID		20	/* Can call sethostid. */
+#define	PRIV_SETDOMAINNAME	21	/* Can call setdomainname. */
+
+/*
+ * Audit subsystem privileges.
+ */
+#define	PRIV_AUDIT_CONTROL	40	/* Can configure audit. */
+#define	PRIV_AUDIT_FAILSTOP	41	/* Can run during audit fail stop. */
+#define	PRIV_AUDIT_GETAUDIT	42	/* Can get proc audit properties. */
+#define	PRIV_AUDIT_SETAUDIT	43	/* Can set proc audit properties. */
+#define	PRIV_AUDIT_SUBMIT	44	/* Can submit an audit record. */
+
+/*
+ * Credential management privileges.
+ */
+#define	PRIV_CRED_SETUID	50	/* setuid. */
+#define	PRIV_CRED_SETEUID	51	/* seteuid to !ruid and !svuid. */
+#define	PRIV_CRED_SETGID	52	/* setgid. */
+#define	PRIV_CRED_SETEGID	53	/* setgid to !rgid and !svgid. */
+#define	PRIV_CRED_SETGROUPS	54	/* Set process additional groups. */
+#define	PRIV_CRED_SETREUID	55	/* setreuid. */
+#define	PRIV_CRED_SETREGID	56	/* setregid. */
+#define	PRIV_CRED_SETRESUID	57	/* setresuid. */
+#define	PRIV_CRED_SETRESGID	58	/* setresgid. */
+#define	PRIV_SEEOTHERGIDS	59	/* Exempt bsd.seeothergids. */
+#define	PRIV_SEEOTHERUIDS	60	/* Exempt bsd.seeotheruids. */
+
+/*
+ * Debugging privileges.
+ */
+#define	PRIV_DEBUG_DIFFCRED	80	/* Exempt debugging other users. */
+#define	PRIV_DEBUG_SUGID	81	/* Exempt debugging setuid proc. */
+#define	PRIV_DEBUG_UNPRIV	82	/* Exempt unprivileged debug limit. */
+
+/*
+ * Dtrace privileges.
+ */
+#define	PRIV_DTRACE_KERNEL	90	/* Allow use of DTrace on the kernel. */
+#define	PRIV_DTRACE_PROC	91	/* Allow attaching DTrace to process. */
+#define	PRIV_DTRACE_USER	92	/* Process may submit DTrace events. */
+
+/*
+ * Firmware privilegs.
+ */
+#define	PRIV_FIRMWARE_LOAD	100	/* Can load firmware. */
+
+/*
+ * Jail privileges.
+ */
+#define	PRIV_JAIL_ATTACH	110	/* Attach to a jail. */
+
+/*
+ * Kernel environment priveleges.
+ */
+#define	PRIV_KENV_SET		120	/* Set kernel env. variables. */
+#define	PRIV_KENV_UNSET		121	/* Unset kernel env. variables. */
+
+/*
+ * Loadable kernel module privileges.
+ */
+#define	PRIV_KLD_LOAD		130	/* Load a kernel module. */
+#define	PRIV_KLD_UNLOAD		131	/* Unload a kernel module. */
+
+/*
+ * Privileges associated with the MAC Framework and specific MAC policy
+ * modules.
+ */
+#define	PRIV_MAC_PARTITION	140	/* Privilege in mac_partition policy. */
+#define	PRIV_MAC_PRIVS		141	/* Privilege in the mac_privs policy. */
+
+/*
+ * Process-related privileges.
+ */
+#define	PRIV_PROC_LIMIT		160	/* Exceed user process limit. */
+#define	PRIV_PROC_SETLOGIN	161	/* Can call setlogin. */
+#define	PRIV_PROC_SETRLIMIT	162	/* Can raise resources limits. */
+
+/* System V IPC privileges.
+ */
+#define	PRIV_IPC_READ		170	/* Can override IPC read perm. */
+#define	PRIV_IPC_WRITE		171	/* Can override IPC write perm. */
+#define	PRIV_IPC_EXEC		172	/* Can override IPC exec perm. */
+#define	PRIV_IPC_ADMIN		173	/* Can override IPC owner-only perm. */
+#define	PRIV_IPC_MSGSIZE	174	/* Exempt IPC message queue limit. */
+
+/*
+ * POSIX message queue privileges.
+ */
+#define	PRIV_MQ_ADMIN		180	/* Can override msgq owner-only perm. */
+
+/*
+ * Performance monitoring counter privileges.
+ */
+#define	PRIV_PMC_MANAGE		190	/* Can administer PMC. */
+#define	PRIV_PMC_SYSTEM		191	/* Can allocate a system-wide PMC. */
+
+/*
+ * Scheduling privileges.
+ */
+#define	PRIV_SCHED_DIFFCRED	200	/* Exempt scheduling other users. */
+#define	PRIV_SCHED_SETPRIORITY	201	/* Can set lower nice value for proc. */
+#define	PRIV_SCHED_RTPRIO	202	/* Can set real time scheduling. */
+#define	PRIV_SCHED_SETPOLICY	203	/* Can set scheduler policy. */
+#define	PRIV_SCHED_SET		204	/* Can set thread scheduler. */
+#define	PRIV_SCHED_SETPARAM	205	/* Can set thread scheduler params. */
+
+/*
+ * POSIX semaphore privileges.
+ */
+#define	PRIV_SEM_WRITE		220	/* Can override sem write perm. */
+
+/*
+ * Signal privileges.
+ */
+#define	PRIV_SIGNAL_DIFFCRED	230	/* Exempt signalling other users. */
+#define	PRIV_SIGNAL_SUGID	231	/* Non-conserv signal setuid proc. */
+
+/*
+ * Sysctl privileges.
+ */
+#define	PRIV_SYSCTL_DEBUG	240	/* Can invoke sysctl.debug. */
+#define	PRIV_SYSCTL_WRITE	241	/* Can write sysctls. */
+#define	PRIV_SYSCTL_WRITEJAIL	242	/* Can write sysctls, jail permitted. */
+
+/*
+ * TTY privileges.
+ */
+#define	PRIV_TTY_CONSOLE	250	/* Set console to tty. */
+#define	PRIV_TTY_DRAINWAIT	251	/* Set tty drain wait time. */
+#define	PRIV_TTY_DTRWAIT	252	/* Set DTR wait on tty. */
+#define	PRIV_TTY_EXCLUSIVE	253	/* Override tty exclusive flag. */
+#define	PRIV_TTY_PRISON		254	/* Can open pts across jails. */
+#define	PRIV_TTY_STI		255	/* Simulate input on another tty. */
+#define	PRIV_TTY_SETA		256	/* Set tty termios structure. */
+
+/*
+ * UFS-specific privileges.
+ */
+#define	PRIV_UFS_EXTATTRCTL	270	/* Can configure EAs on UFS1. */
+#define	PRIV_UFS_GETQUOTA	271	/* getquota(). */
+#define	PRIV_UFS_QUOTAOFF	272	/* quotaoff(). */
+#define	PRIV_UFS_QUOTAON	273	/* quotaon(). */
+#define	PRIV_UFS_SETQUOTA	274	/* setquota(). */
+#define	PRIV_UFS_SETUSE		275	/* setuse(). */
+#define	PRIV_UFS_EXCEEDQUOTA	276	/* Exempt from quota restrictions. */
+
+/*
+ * VFS privileges.
+ */
+#define	PRIV_VFS_READ		310	/* Override vnode DAC read perm. */
+#define	PRIV_VFS_WRITE		311	/* Override vnode DAC write perm. */
+#define	PRIV_VFS_ADMIN		312	/* Override vnode DAC admin perm. */
+#define	PRIV_VFS_EXEC		313	/* Override vnode DAC exec perm. */
+#define	PRIV_VFS_LOOKUP		314	/* Override vnode DAC lookup perm. */
+#define	PRIV_VFS_BLOCKRESERVE	315	/* Can use free block reserve. */
+#define	PRIV_VFS_CHFLAGS_DEV	316	/* Can chflags() a device node. */
+#define	PRIV_VFS_CHOWN		317	/* Can set user; group to non-member. */
+#define	PRIV_VFS_CHROOT		318	/* chroot(). */
+#define	PRIV_VFS_CLEARSUGID	319	/* Don't clear sugid on change. */
+#define	PRIV_VFS_EXTATTR_SYSTEM	320	/* Operate on system EA namespace. */
+#define	PRIV_VFS_FCHROOT	321	/* fchroot(). */
+#define	PRIV_VFS_FHOPEN		322	/* Can fhopen(). */
+#define	PRIV_VFS_FHSTAT		323	/* Can fhstat(). */
+#define	PRIV_VFS_FHSTATFS	324	/* Can fhstatfs(). */
+#define	PRIV_VFS_GENERATION	325	/* stat() returns generation number. */
+#define	PRIV_VFS_GETFH		326	/* Can retrieve file handles. */
+#define	PRIV_VFS_LINK		327	/* bsd.hardlink_check_uid */
+#define	PRIV_VFS_MKNOD_BAD	328	/* Can mknod() to mark bad inodes. */
+#define	PRIV_VFS_MKNOD_DEV	329	/* Can mknod() to create dev nodes. */
+#define	PRIV_VFS_MKNOD_WHT	330	/* Can mknod() to create whiteout. */
+#define	PRIV_VFS_MOUNT		331	/* Can mount(). */
+#define	PRIV_VFS_MOUNT_OWNER	332	/* Override owner on user mounts. */
+#define	PRIV_VFS_MOUNT_EXPORTED	333	/* Can set MNT_EXPORTED on mount. */
+#define	PRIV_VFS_MOUNT_PERM	334	/* Override dev node perms at mount. */
+#define	PRIV_VFS_MOUNT_SUIDDIR	335	/* Can set MNT_SUIDDIR on mount. */
+#define	PRIV_VFS_MOUNT_NONUSER	336	/* Can perform a non-user mount. */
+#define	PRIV_VFS_SETGID		337	/* Can setgid if not in group. */
+#define	PRIV_VFS_STICKYFILE	338	/* Can set sticky bit on file. */
+#define	PRIV_VFS_SYSFLAGS	339	/* Can modify system flags. */
+#define	PRIV_VFS_UNMOUNT	340	/* Can unmount(). */
+
+/*
+ * Virtual memory privileges.
+ */
+#define	PRIV_VM_MADV_PROTECT	360	/* Can set MADV_PROTECT. */
+#define	PRIV_VM_MLOCK		361	/* Can mlock(), mlockall(). */
+#define	PRIV_VM_MUNLOCK		362	/* Can munlock(), munlockall(). */
+
+/*
+ * Device file system privileges.
+ */
+#define	PRIV_DEVFS_RULE		370	/* Can manage devfs rules. */
+#define	PRIV_DEVFS_SYMLINK	371	/* Can create symlinks in devfs. */
+
+/*
+ * Random number generator privileges.
+ */
+#define	PRIV_RANDOM_RESEED	380	/* Closing /dev/random reseeds. */
+
+/*
+ * Network stack privileges.
+ */
+#define	PRIV_NET_BRIDGE		390	/* Administer bridge. */
+#define	PRIV_NET_GRE		391	/* Administer GRE. */
+#define	PRIV_NET_PPP		392	/* Administer PPP. */
+#define	PRIV_NET_SLIP		393	/* Administer SLIP. */
+#define	PRIV_NET_BPF		394	/* Monitor BPF. */
+#define	PRIV_NET_RAW		395	/* Open raw socket. */
+#define	PRIV_NET_ROUTE		396	/* Administer routing. */
+#define	PRIV_NET_TAP		397	/* Can open tap device. */
+#define	PRIV_NET_SETIFMTU	398	/* Set interface MTU. */
+#define	PRIV_NET_SETIFFLAGS	399	/* Set interface flags. */
+#define	PRIV_NET_SETIFCAP	400	/* Set interface capabilities. */
+#define	PRIV_NET_SETIFNAME	401	/* Set interface name. */
+#define	PRIV_NET_SETIFMETRIC	402	/* Set interface metrics. */
+#define	PRIV_NET_SETIFPHYS	403	/* Set interface physical layer prop. */
+#define	PRIV_NET_SETIFMAC	404	/* Set interface MAC label. */
+#define	PRIV_NET_ADDMULTI	405	/* Add multicast addr. to ifnet. */
+#define	PRIV_NET_DELMULTI	406	/* Delete multicast addr. from ifnet. */
+#define	PRIV_NET_HWIOCTL	507	/* Issue hardware ioctl on ifnet. */
+#define	PRIV_NET_SETLLADDR	508
+#define	PRIV_NET_ADDIFGROUP	509	/* Add new interface group. */
+#define	PRIV_NET_DELIFGROUP	510	/* Delete interface group. */
+#define	PRIV_NET_IFCREATE	511	/* Create cloned interface. */
+#define	PRIV_NET_IFDESTROY	512	/* Destroy cloned interface. */
+#define	PRIV_NET_ADDIFADDR	513	/* Add protocol addr to interface. */
+#define	PRIV_NET_DELIFADDR	514	/* Delete protocol addr on interface. */
+
+/*
+ * 802.11-related privileges.
+ */
+#define	PRIV_NET80211_GETKEY	540	/* Query 802.11 keys. */
+#define	PRIV_NET80211_MANAGE	541	/* Administer 802.11. */
+
+/*
+ * AppleTalk privileges.
+ */
+#define	PRIV_NETATALK_RESERVEDPORT	550	/* Bind low port number. */
+
+/*
+ * ATM privileges.
+ */
+#define	PRIV_NETATM_CFG		560
+#define	PRIV_NETATM_ADD		561
+#define	PRIV_NETATM_DEL		562
+#define	PRIV_NETATM_SET		563
+
+/*
+ * Bluetooth privileges.
+ */
+#define	PRIV_NETBLUETOOTH_RAW	570	/* Open raw bluetooth socket. */
+
+/*
+ * Netgraph and netgraph module privileges.
+ */
+#define	PRIV_NETGRAPH_CONTROL	580	/* Open netgraph control socket. */
+#define	PRIV_NETGRAPH_TTY	581	/* Configure tty for netgraph. */
+
+/*
+ * IPv4 and IPv6 privileges.
+ */
+#define	PRIV_NETINET_RESERVEDPORT	590	/* Bind low port number. */
+#define	PRIV_NETINET_IPFW	591	/* Administer IPFW firewall. */
+#define	PRIV_NETINET_DIVERT	592	/* Open IP divert socket. */
+#define	PRIV_NETINET_PF		593	/* Administer pf firewall. */
+#define	PRIV_NETINET_DUMMYNET	594	/* Administer DUMMYNET. */
+#define	PRIV_NETINET_CARP	595	/* Administer CARP. */
+#define	PRIV_NETINET_MROUTE	596	/* Administer multicast routing. */
+#define	PRIV_NETINET_RAW	597	/* Open netinet raw socket. */
+#define	PRIV_NETINET_GETCRED	598	/* Query netinet pcb credentials. */
+#define	PRIV_NETINET_ADDRCTRL6	599	/* Administer IPv6 address scopes. */
+#define	PRIV_NETINET_ND6	600	/* Administer IPv6 neighbor disc. */
+#define	PRIV_NETINET_SCOPE6	601	/* Administer IPv6 address scopes. */
+#define	PRIV_NETINET_ALIFETIME6	602	/* Administer IPv6 address lifetimes. */
+#define	PRIV_NETINET_IPSEC	603	/* Administer IPSEC. */
+
+/*
+ * IPX/SPX privileges.
+ */
+#define	PRIV_NETIPX_RESERVEDPORT	620	/* Bind low port number. */
+#define	PRIV_NETIPX_RAW		621	/* Open netipx raw socket. */
+
+/*
+ * NCP privileges.
+ */
+#define	PRIV_NETNCP		630	/* Use another user's connection. */
+
+/*
+ * SMB privileges.
+ */
+#define	PRIV_NETSMB		640	/* Use another user's connection. */
+
+/*
+ * VM86 privileges.
+ */
+#define	PRIV_VM86_INTCALL	650/* 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.
+ */
+#define	_PRIV_RESERVED0		660
+#define	_PRIV_RESERVED1		661
+#define	_PRIV_RESERVED2		662
+#define	_PRIV_RESERVED3		663
+#define	_PRIV_RESERVED4		664
+#define	_PRIV_RESERVED5		665
+#define	_PRIV_RESERVED6		666
+#define	_PRIV_RESERVED7		667
+#define	_PRIV_RESERVED8		668
+#define	_PRIV_RESERVED9		669
+#define	_PRIV_RESERVED10	670
+#define	_PRIV_RESERVED11	671
+#define	_PRIV_RESERVED12	672
+#define	_PRIV_RESERVED13	673
+#define	_PRIV_RESERVED14	674
+#define	_PRIV_RESERVED15	675
+
+/*
+ * 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.
+ */
+#define	PRIV_MODULE0		700
+#define	PRIV_MODULE1		701
+#define	PRIV_MODULE2		702
+#define	PRIV_MODULE3		703
+#define	PRIV_MODULE4		704
+#define	PRIV_MODULE5		705
+#define	PRIV_MODULE6		706
+#define	PRIV_MODULE7		707
+#define	PRIV_MODULE8		708
+#define	PRIV_MODULE9		709
+#define	PRIV_MODULE10		710
+#define	PRIV_MODULE11		711
+#define	PRIV_MODULE12		712
+#define	PRIV_MODULE13		713
+#define	PRIV_MODULE14		714
+#define	PRIV_MODULE15		715
+
+/*
+ * Track end of privilege list.
+ */
+#define	_PRIV_HIGHEST		716
+
+/*
+ * 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.  This is only approximate due to sparse allocation
+ * of the privilege space.
+ */
+#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, int priv);
+int	priv_check_cred(struct ucred *cred, int priv, int flags);
+#endif
+
+#endif /* !_SYS_PRIV_H_ */
Index: sys/sys/systm.h
===================================================================
RCS file: /zoo/cvsup/FreeBSD-CVS/src/sys/sys/systm.h,v
retrieving revision 1.245
diff -u -r1.245 systm.h
--- sys/sys/systm.h	17 Oct 2006 02:24:47 -0000	1.245
+++ sys/sys/systm.h	30 Oct 2006 17:07:56 -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: /zoo/cvsup/FreeBSD-CVS/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	30 Oct 2006 17:07:56 -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: /zoo/cvsup/FreeBSD-CVS/src/sys/ufs/ffs/ffs_vfsops.c,v
retrieving revision 1.321
diff -u -r1.321 ffs_vfsops.c
--- sys/ufs/ffs/ffs_vfsops.c	22 Oct 2006 11:52:19 -0000	1.321
+++ sys/ufs/ffs/ffs_vfsops.c	30 Oct 2006 17:07:56 -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>
@@ -257,15 +258,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;
@@ -364,14 +366,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: /zoo/cvsup/FreeBSD-CVS/src/sys/ufs/ffs/ffs_vnops.c,v
retrieving revision 1.161
diff -u -r1.161 ffs_vnops.c
--- sys/ufs/ffs/ffs_vnops.c	10 Oct 2006 09:20:54 -0000	1.161
+++ sys/ufs/ffs/ffs_vnops.c	30 Oct 2006 17:07:56 -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>
@@ -781,7 +782,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);
  	}
@@ -1107,7 +1109,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: /zoo/cvsup/FreeBSD-CVS/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	30 Oct 2006 17:07:56 -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: /zoo/cvsup/FreeBSD-CVS/src/sys/ufs/ufs/ufs_quota.c,v
retrieving revision 1.84
diff -u -r1.84 ufs_quota.c
--- sys/ufs/ufs/ufs_quota.c	26 Sep 2006 04:12:49 -0000	1.84
+++ sys/ufs/ufs/ufs_quota.c	30 Oct 2006 17:07:56 -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>
@@ -165,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;
@@ -288,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;
@@ -423,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 +524,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);

@@ -589,15 +600,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);
  		}
@@ -632,7 +646,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);

@@ -698,7 +713,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: /zoo/cvsup/FreeBSD-CVS/src/sys/ufs/ufs/ufs_vnops.c,v
retrieving revision 1.281
diff -u -r1.281 ufs_vnops.c
--- sys/ufs/ufs/ufs_vnops.c	22 Oct 2006 11:52:19 -0000	1.281
+++ sys/ufs/ufs/ufs_vnops.c	30 Oct 2006 17:07:56 -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>
@@ -490,8 +491,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)) {
@@ -582,10 +586,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;
@@ -651,11 +664,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);
  	}
@@ -692,19 +707,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;
@@ -775,7 +790,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);
  	}
@@ -2348,7 +2364,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: /zoo/cvsup/FreeBSD-CVS/src/sys/vm/swap_pager.c,v
retrieving revision 1.284
diff -u -r1.284 swap_pager.c
--- sys/vm/swap_pager.c	23 Oct 2006 05:27:31 -0000	1.284
+++ sys/vm/swap_pager.c	30 Oct 2006 17:07:56 -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>
@@ -1966,11 +1967,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;
@@ -2009,7 +2010,6 @@
  done:
  	swdev_syscall_active = 0;
  	wakeup_one(&swdev_syscall_active);
-done2:
  	mtx_unlock(&Giant);
  	return (error);
  }
@@ -2105,7 +2105,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: /zoo/cvsup/FreeBSD-CVS/src/sys/vm/vm_mmap.c,v
retrieving revision 1.207
diff -u -r1.207 vm_mmap.c
--- sys/vm/vm_mmap.c	22 Oct 2006 11:52:19 -0000	1.207
+++ sys/vm/vm_mmap.c	30 Oct 2006 17:07:56 -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>
@@ -684,7 +685,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);
@@ -951,7 +952,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;
@@ -1016,7 +1017,7 @@
  	}
  	PROC_UNLOCK(td->td_proc);
  #else
-	error = suser(td);
+	error = priv_check(td, PRIV_VM_MLOCK);
  	if (error)
  		return (error);
  #endif
@@ -1061,7 +1062,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);

@@ -1095,7 +1096,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;


More information about the trustedbsd-discuss mailing list