Skip site navigation (1)Skip section navigation (2)
Date:      Sat, 9 Sep 2006 10:00:42 GMT
From:      Robert Watson <rwatson@FreeBSD.org>
To:        Perforce Change Reviews <perforce@freebsd.org>
Subject:   PERFORCE change 105880 for review
Message-ID:  <200609091000.k89A0gQV024031@repoman.freebsd.org>

next in thread | raw e-mail | index | archive | help
http://perforce.freebsd.org/chv.cgi?CH=105880

Change 105880 by rwatson@rwatson_sesame on 2006/09/09 10:00:40

	Hook up mac_priv.c, which contains the MAC entry points for both
	denying and granting privilege.  Add a new composition operator,
	MAC_GRANT(), for the grant path.  Add a sample policy, mac_privs,
	which allows uid's to be assigned additional privileges using a
	rule based system.
	
	While here, update privileges, adding one for this policy,
	renaming the mount_owner privilege, and removing the VFS revoke
	privilege, which is actually just the vfs_admin privilege.
	change ifdef's so that user space can include privs.h for use in
	the management tool for mac_privs.c.

Affected files ...

.. //depot/projects/trustedbsd/priv/sys/conf/NOTES#3 edit
.. //depot/projects/trustedbsd/priv/sys/conf/files#3 edit
.. //depot/projects/trustedbsd/priv/sys/conf/options#2 edit
.. //depot/projects/trustedbsd/priv/sys/kern/kern_priv.c#2 edit
.. //depot/projects/trustedbsd/priv/sys/modules/Makefile#3 edit
.. //depot/projects/trustedbsd/priv/sys/modules/mac_privs/Makefile#1 add
.. //depot/projects/trustedbsd/priv/sys/security/mac/mac_internal.h#3 edit
.. //depot/projects/trustedbsd/priv/sys/security/mac/mac_priv.c#1 add
.. //depot/projects/trustedbsd/priv/sys/security/mac/mac_system.c#2 edit
.. //depot/projects/trustedbsd/priv/sys/security/mac_privs/mac_privs.c#1 add
.. //depot/projects/trustedbsd/priv/sys/security/mac_privs/mac_privs.h#1 add
.. //depot/projects/trustedbsd/priv/sys/sys/mac.h#2 edit
.. //depot/projects/trustedbsd/priv/sys/sys/mac_policy.h#2 edit
.. //depot/projects/trustedbsd/priv/sys/sys/priv.h#2 edit

Differences ...

==== //depot/projects/trustedbsd/priv/sys/conf/NOTES#3 (text+ko) ====

@@ -1001,6 +1001,7 @@
 options 	MAC_NONE
 options 	MAC_PARTITION
 options 	MAC_PORTACL
+options 	MAC_PRIVS
 options 	MAC_SEEOTHERUIDS
 options 	MAC_STUB
 options 	MAC_TEST

==== //depot/projects/trustedbsd/priv/sys/conf/files#3 (text+ko) ====

@@ -1912,6 +1912,7 @@
 security/mac/mac_net.c		optional mac
 security/mac/mac_pipe.c		optional mac
 security/mac/mac_posix_sem.c	optional mac
+security/mac/mac_priv.c		optional mac
 security/mac/mac_process.c	optional mac
 security/mac/mac_socket.c	optional mac
 security/mac/mac_system.c	optional mac
@@ -1927,6 +1928,7 @@
 security/mac_none/mac_none.c	optional mac_none
 security/mac_partition/mac_partition.c optional mac_partition
 security/mac_portacl/mac_portacl.c optional mac_portacl
+security/mac_privs/mac_privs.c	optional mac_privs
 security/mac_seeotheruids/mac_seeotheruids.c optional mac_seeotheruids
 security/mac_stub/mac_stub.c	optional mac_stub
 security/mac_test/mac_test.c	optional mac_test

==== //depot/projects/trustedbsd/priv/sys/conf/options#2 (text+ko) ====

@@ -110,6 +110,7 @@
 MAC_NONE	opt_dontuse.h
 MAC_PARTITION	opt_dontuse.h
 MAC_PORTACL	opt_dontuse.h
+MAC_PRIVS	opt_dontuse.h
 MAC_SEEOTHERUIDS	opt_dontuse.h
 MAC_STATIC	opt_mac.h
 MAC_STUB	opt_dontuse.h

==== //depot/projects/trustedbsd/priv/sys/kern/kern_priv.c#2 (text+ko) ====

@@ -58,7 +58,8 @@
 TUNABLE_INT("security.bsd.suser_enabled", &suser_enabled);
 
 /*
- * Check a credential for privilege.
+ * Check a credential for privilege.  Lots of good reasons to deny privilege;
+ * only a few to grant it.
  */
 int
 priv_check_cred(struct ucred *cred, enum priv priv, int flags)
@@ -68,44 +69,57 @@
 	KASSERT(PRIV_VALID(priv), ("priv_check_cred: invalid privilege %d",
 	    priv));
 
-#if defined(MAC) && defined(NOTYET)
+#ifdef MAC
 	error = mac_priv_check(cred, priv);
 	if (error)
 		return (error);
 #endif
 
+	/*
+	 * Jail policy will restrict certain privileges that may otherwise be
+	 * be granted.
+	 *
+	 * While debugging the transition from SUSER_ALLOWJAIL to Jail being
+	 * aware of specific privileges, perform run-time checking that the
+	 * two versions of the policy align.  This assertion will go away
+	 * once the SUSER_ALLOWJAIL flag has gone away.
+	 */
 	error = prison_priv_check(cred, priv);
+	KASSERT(!jailed(cred) || error == ((flags & SUSER_ALLOWJAIL) ? 0 :
+	    EPERM), ("priv_check_cred: prison_priv_check %d but flags %s",
+	    error, flags & SUSER_ALLOWJAIL ? "allowjail" : "!allowjail"));
 	if (error)
 		return (error);
 
 	/*
-	 * XXXRW: Historic SUSER_ALLOWJAIL check, which allows the calling
-	 * context to specify whether this privilege is permissible in a
-	 * jail.  This will go away shortly as we will be able to centralize
-	 * the decision in prison_priv_check().
+	 * 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.
 	 *
-	 * XXXRW: Consider an assertion that this never happens, as the
-	 * earlier prison_priv_check() function should have rejected it.
+	 * Superuser policy grants privilege based on the effective (or in
+	 * certain edge cases, real) uid being 0.  We allow the policy to be
+	 * globally disabled, although this is currently of limited uility.
 	 */
-	if (jailed(cred) && !(flags & SUSER_ALLOWJAIL))
-		return (EPERM);
+	if (suser_enabled) {
+		if (flags & SUSER_RUID) {
+			if (cred->cr_ruid == 0)
+				return (0);
+		} else {
+			if (cred->cr_uid == 0)
+				return (0);
+		}
+	}
 
 	/*
-	 * Global super-user privilege frob.
+	 * Now check with MAC, if enabled, to see if a policy module grants
+	 * privilege.
 	 */
-	if (!suser_enabled)
-		return (EPERM);
-
-	/*
-	 * Check for uid 0.
-	 */
-	if (((flags & SUSER_RUID) ? cred->cr_ruid : cred->cr_uid) != 0)
-		return (EPERM);
-
-	/*
-	 * Privilege is granted.
-	 */
-	return (0);
+#ifdef MAC
+	if (mac_priv_grant(cred, priv) == 0)
+		return (0);
+#endif
+	return (EPERM);
 }
 
 int

==== //depot/projects/trustedbsd/priv/sys/modules/Makefile#3 (text+ko) ====

@@ -147,6 +147,7 @@
 	mac_none \
 	mac_partition \
 	mac_portacl \
+	mac_privs \
 	mac_seeotheruids \
 	mac_stub \
 	mac_test \

==== //depot/projects/trustedbsd/priv/sys/security/mac/mac_internal.h#3 (text+ko) ====

@@ -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:
@@ -168,6 +172,36 @@
 } while (0)
 
 /*
+ * MAC_GRANT performs the designated check by walking the policy module
+ * list and checking with each as to how it feels about the request.  Unlike
+ * MAC_CHECK, it grants if any policies return '0', and otherwise returns
+ * EPERM.  Note that it returns its value via 'error' in the scope of the
+ * caller.
+ */
+#define	MAC_GRANT(check, args...) do {					\
+	struct mac_policy_conf *mpc;					\
+	int entrycount;							\
+									\
+	error = EPERM;							\
+	LIST_FOREACH(mpc, &mac_static_policy_list, mpc_list) {		\
+		if (mpc->mpc_ops->mpo_ ## check != NULL) {		\
+			if (mpc->mpc_ops->mpo_ ## check(args) == 0)	\
+				error = 0;				\
+		}							\
+	}								\
+	if ((entrycount = mac_policy_list_conditional_busy()) != 0) {	\
+		LIST_FOREACH(mpc, &mac_policy_list, mpc_list) {		\
+			if (mpc->mpc_ops->mpo_ ## check != NULL) {	\
+				if (mpc->mpc_ops->mpo_ ## check (args)	\
+				    == 0)				\
+					error = 0;			\
+			}						\
+		}							\
+		mac_policy_list_unbusy();				\
+	}								\
+} while (0)
+
+/*
  * MAC_BOOLEAN performs the designated boolean composition by walking
  * the module list, invoking each instance of the operation, and
  * combining the results using the passed C operator.  Note that it

==== //depot/projects/trustedbsd/priv/sys/security/mac/mac_system.c#2 (text+ko) ====


==== //depot/projects/trustedbsd/priv/sys/sys/mac.h#2 (text+ko) ====

@@ -47,8 +47,6 @@
 #ifndef _SYS_MAC_H_
 #define	_SYS_MAC_H_
 
-#include <sys/_label.h>
-
 #ifndef _POSIX_MAC
 #define	_POSIX_MAC
 #endif
@@ -107,6 +105,9 @@
 
 #else /* _KERNEL */
 
+#include <sys/_label.h>
+#include <sys/priv.h>		/* XXXRW: Until name space issues resolved. */
+
 /*
  * Kernel functions to manage and evaluate labels.
  */
@@ -464,6 +465,8 @@
 	    struct label *label);
 void	mac_cred_mmapped_drop_perms(struct thread *td, struct ucred *cred);
 void	mac_associate_nfsd_label(struct ucred *cred);
+int	mac_priv_check(struct ucred *cred, enum priv priv);
+int	mac_priv_grant(struct ucred *cred, enum priv priv);
 
 /*
  * Calls to help various file systems implement labeling functionality

==== //depot/projects/trustedbsd/priv/sys/sys/mac_policy.h#2 (text+ko) ====

@@ -68,6 +68,7 @@
 struct mac_policy_conf;
 struct mbuf;
 struct mount;
+struct msg;
 struct msqid_kernel;
 struct pipepair;
 struct proc;
@@ -590,6 +591,8 @@
 		    struct ucred *file_cred, struct vnode *vp,
 		    struct label *label);
 typedef void	(*mpo_associate_nfsd_label_t)(struct ucred *cred);
+typedef int	(*mpo_priv_check_t)(struct ucred *cred, enum priv priv);
+typedef int	(*mpo_priv_grant_t)(struct ucred *cred, enum priv priv);
 
 struct mac_policy_ops {
 	/*
@@ -879,6 +882,8 @@
 	mpo_check_vnode_stat_t			mpo_check_vnode_stat;
 	mpo_check_vnode_write_t			mpo_check_vnode_write;
 	mpo_associate_nfsd_label_t		mpo_associate_nfsd_label;
+	mpo_priv_check_t			mpo_priv_check;
+	mpo_priv_grant_t			mpo_priv_grant;
 };
 
 /*

==== //depot/projects/trustedbsd/priv/sys/sys/priv.h#2 (text+ko) ====

@@ -36,14 +36,6 @@
 #define	_SYS_PRIV_H_
 
 /*
- * Eventually we may need to export the privilege list to user space.  Until
- * then, don't do so unnecessarily.
- */
-#ifndef _KERNEL
-#error "no user-serviceable parts inside"
-#endif
-
-/*
  * Privilege list.  In no particular order.
  *
  * Think carefully before adding or reusing one of these privileges -- are
@@ -52,6 +44,9 @@
  * modules.  Particular numeric privilege assignments are part of the
  * loadable kernel module ABI, and should not be changed across minor
  * releases.
+ *
+ * When adding a new privilege, remember to determine if it's appropriate for
+ * use in jail, and update the privilege switch in kern_jail.c as necessary.
  */
 enum priv {
 	/* Track beginning of privilege list. */
@@ -116,6 +111,7 @@
 	PRIV_KLD_LOAD,		/* Load a kernel module. */
 	PRIV_KLD_UNLOAD,	/* Unload a kernel module. */
 	PRIV_MAC_PARTITION,	/* Privilege in mac_partition policy. */
+	PRIV_MAC_PRIVS,		/* Privilege in the mac_privs policy. */
 	PRIV_PROC_LIMIT,	/* Exceed user process limit. */
 	PRIV_PROC_SETLOGIN,	/* Can call setlogin. */
 	PRIV_PROC_SETRLIMIT,	/* Can raise resources limits. */
@@ -173,11 +169,10 @@
 	PRIV_VFS_LINK,		/* bsd.hardlink_check_uid */
 	PRIV_VFS_MKNOD_DEV,	/* Can create device nodes. */
 	PRIV_VFS_MOUNT,		/* Can mount(). */
-	PRIV_VFS_MOUNTOWNER,	/* Override owner on user mounts. */
+	PRIV_VFS_MOUNT_OWNER,	/* Override owner on user mounts. */
 	PRIV_VFS_MOUNT_EXPORTED,	/* Can set MNT_EXPORTED on mount. */
 	PRIV_VFS_MOUNT_PERM,	/* Override device node perms at mount. */
 	PRIV_VFS_MOUNT_SUIDDIR,	/* Can set MNT_SUIDDIR on mount. */
-	PRIV_VFS_REVOKE,	/* Can revoke(). */
 	PRIV_VFS_SETGID,	/* Can setgid if not in group. */
 	PRIV_VFS_STICKYFILE,	/* Can set sticky bit on file. */
 	PRIV_VFS_SYSFLAGS,	/* Can modify system flags. */
@@ -297,6 +292,7 @@
  */
 #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
@@ -308,5 +304,6 @@
 struct ucred;
 int	priv_check(struct thread *td, enum priv priv);
 int	priv_check_cred(struct ucred *cred, enum priv priv, int flags);
+#endif
 
 #endif /* !_SYS_PRIV_H_ */



Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?200609091000.k89A0gQV024031>