summaryrefslogtreecommitdiffstats
path: root/sys/kern/vfs_subr.c
diff options
context:
space:
mode:
Diffstat (limited to 'sys/kern/vfs_subr.c')
-rw-r--r--sys/kern/vfs_subr.c72
1 files changed, 72 insertions, 0 deletions
diff --git a/sys/kern/vfs_subr.c b/sys/kern/vfs_subr.c
index 45577ab..83cd325 100644
--- a/sys/kern/vfs_subr.c
+++ b/sys/kern/vfs_subr.c
@@ -43,6 +43,7 @@ __FBSDID("$FreeBSD$");
#include "opt_ddb.h"
#include "opt_mac.h"
+#include "opt_commonid.h"
#include <sys/param.h>
#include <sys/systm.h>
@@ -278,6 +279,36 @@ SYSCTL_INT(_debug, OID_AUTO, vnlru_nowhere, CTLFLAG_RW,
#define VSHOULDFREE(vp) (!((vp)->v_iflag & VI_FREE) && !(vp)->v_holdcnt)
#define VSHOULDBUSY(vp) (((vp)->v_iflag & VI_FREE) && (vp)->v_holdcnt)
+#ifdef COMMONID
+/*
+ * Sysctl variables to control the unified user and group ID space.
+ */
+
+/* ID below that are the traditional system IDs that
+ * can't be in the common space
+ */
+#define MINCOMMONID 100
+
+typedef struct {
+ int enabled; /* flag: commonid is enabled */
+ int low; /* the lowest common ID */
+ int high; /* the highest common ID */
+} commonid_ctl_t;
+
+static commonid_ctl_t commonid = { 0, 1000, 60000 }; /* safe values */
+
+SYSCTL_NODE(_vfs, OID_AUTO, commonid, CTLFLAG_RW, 0, "Common UID/GID space");
+SYSCTL_NODE(_vfs_commonid, OID_AUTO, local, CTLFLAG_RW, 0,
+ "Common UID/GID space for local filesystems");
+SYSCTL_INT(_vfs_commonid_local, OID_AUTO, enabled, CTLFLAG_RW,
+ &commonid.enabled, 0,
+ "Enable common UID/GID space for local filesystems");
+SYSCTL_INT(_vfs_commonid_local, OID_AUTO, low, CTLFLAG_RW, &commonid.low,
+ 0, "Lowest common UID/GID value for local filesystems");
+SYSCTL_INT(_vfs_commonid_local, OID_AUTO, high, CTLFLAG_RW, &commonid.high,
+ 0, "Highest common UID/GID value for local filesystems");
+
+#endif /* COMMONID */
/*
* Initialize the vnode management data structures.
@@ -3171,6 +3202,47 @@ vaccess(enum vtype type, mode_t file_mode, uid_t file_uid, gid_t file_gid,
goto privcheck;
}
+#ifdef COMMONID
+ /* If the common UID/GID is enabled, check the user agains the
+ * file GID and groups against file UID
+ */
+ if (commonid.enabled) {
+ if (commonid.low < MINCOMMONID)
+ commonid.low = MINCOMMONID;
+
+ if (cred->cr_uid == file_gid
+ && file_gid >= commonid.low && file_gid <= commonid.high) {
+ /* no VADMIN in this case */
+ if (file_mode & S_IXGRP)
+ dac_granted |= VEXEC;
+ if (file_mode & S_IRGRP)
+ dac_granted |= VREAD;
+ if (file_mode & S_IWGRP)
+ dac_granted |= (VWRITE | VAPPEND);
+
+ if ((acc_mode & dac_granted) == acc_mode)
+ return (0);
+
+ goto privcheck;
+ }
+ if (file_uid >= commonid.low && file_uid <= commonid.high
+ && groupmember(file_uid, cred)) {
+ /* no VADMIN in this case */
+ if (file_mode & S_IXUSR)
+ dac_granted |= VEXEC;
+ if (file_mode & S_IRUSR)
+ dac_granted |= VREAD;
+ if (file_mode & S_IWUSR)
+ dac_granted |= (VWRITE | VAPPEND);
+
+ if ((acc_mode & dac_granted) == acc_mode)
+ return (0);
+
+ goto privcheck;
+ }
+ }
+#endif /* COMMONID */
+
/* Otherwise, check the groups (first match) */
if (groupmember(file_gid, cred)) {
if (file_mode & S_IXGRP)
OpenPOWER on IntegriCloud