From 7a799f1ef0eca608477b6d3b0e7ee4a458ef7330 Mon Sep 17 00:00:00 2001 From: Sergey Babkin Date: Sun, 25 Jun 2006 18:37:44 +0000 Subject: [PATCH] The common UID/GID space implementation. It has been discussed on -arch in 1999, and there are changes to the sysctl names compared to PR, according to that discussion. The description is in sys/conf/NOTES. Lines in the GENERIC files are added in commented-out form. I'll attach the test script I've used to PR. PR: kern/14584 Submitted by: babkin --- sys/amd64/conf/GENERIC | 1 + sys/conf/NOTES | 64 +++++++++++++++++++++++++++++++++++ sys/conf/options | 1 + sys/i386/conf/GENERIC | 1 + sys/ia64/conf/GENERIC | 1 + sys/kern/vfs_subr.c | 72 ++++++++++++++++++++++++++++++++++++++++ sys/pc98/conf/GENERIC | 1 + sys/powerpc/conf/GENERIC | 1 + sys/sparc64/conf/GENERIC | 1 + 9 files changed, 143 insertions(+) diff --git a/sys/amd64/conf/GENERIC b/sys/amd64/conf/GENERIC index b27c52dd9b9a..222c8d4fd8dd 100644 --- a/sys/amd64/conf/GENERIC +++ b/sys/amd64/conf/GENERIC @@ -59,6 +59,7 @@ options _KPOSIX_PRIORITY_SCHEDULING # POSIX P1003_1B real-time extensions options KBD_INSTALL_CDEV # install a CDEV entry in /dev options ADAPTIVE_GIANT # Giant mutex is adaptive. options STOP_NMI # Stop CPUS using NMI instead of IPI +#options COMMONID # Enable support for common UID/GID space # Debugging for use in -current options KDB # Enable kernel debugger support. diff --git a/sys/conf/NOTES b/sys/conf/NOTES index 7d610bc84719..79ecc5d6c748 100644 --- a/sys/conf/NOTES +++ b/sys/conf/NOTES @@ -905,6 +905,70 @@ options QUOTA #enable disk quotas # options SUIDDIR +# The common user and group ID space for the local filesystems +# (see PR kern/14584), AKA "poor man's ACLs". +# +# From the systems administration standpoint ACLs are a pain to use: +# * they are not supported by the classic file formats like tar and cpio +# * they need lots of ugly flags to commands like chown or ls +# * they are just by themselves difficult to show in ls +# * they promote ad-hoc and messy assignment of permissions +# +# But in fact the classic Unix permissions seem to have only one real problem: +# sometimes it's neccessary to give read permissions to one group of +# users and read-write permissions to another group of users. But only +# one group is supported and that makes a problem. The common ID +# support solves this problem without breaking any compatibility. +# +# Controlled by the sysctl: +# vfs.commonid.local.enabled: Enable common UID/GID space for local filesystems +# vfs.commonid.local.low: Lowest common UID/GID value for local filesystems +# vfs.commonid.local.high: Highest common UID/GID value for local filesystems +# +# When enabled, the user and group ID space in the range [low, high] +# becomes common. That is, if there is an user with some ID in this range, +# there must not be a group with the same ID (except for a special case +# described later). Traditionally this kind of overlapping exists in the +# low values of system IDs, so the implementation won't allow to set the +# low border below 100. If it's set manually below 100, the first time +# an access check is done, the system will reset it to 100. +# +# The special case is that for the symbolic group and user names to work +# correctly, every time a user is created, a pseudo-group with the same +# ID and name must be created. And the other way around - every time +# a group is created, a pseudo-user with the same name and ID must be created. +# Otherwise command like "ls" won't show the user/group names correctly +# and command like "chown" won't understand the symbolic names correctly. +# +# The IDs in the common range can be used interchangeably in both the +# user and group fields of file permissions. For example, if you have +# groups group1 and group2 with IDs in the common range, you can do: +# chmod 240 file +# chown group1:group2 file +# This would allow the group1 to write to the file and group2 to read +# the file. +# +# This semantics works only for the access but not for modification of +# the permissions. In the example above the members of group1 aren't allowed +# to call chmod on the file. Such changes must be done either by root +# or through the pseudo-user group1. +# +# If it's desiable to give the "owner group" of some files (like group1 +# in this example) the rights to change the permissions of all the files +# it owns, it can be achieved through cloning the chmod binary and +# adding the pseudo-user setuid rights to it: +# cp /bin/chmod /usr/local/bin/group1chmod +# chown group1 /usr/local/bin/group1chmod +# chmod u=xs,g=,o= /usr/local/bin/group1chmod +# A similar thing can be done for chown. +# In result all the members of group1 would be able to execute group1chmod, +# which would assume the ID of pseudo-user "group1" and will be able +# to change the file permissions. +# +# This logic does not work on the remote filesystems (such as NFS). + +options COMMONID # Enable support for common UID/GID space + # NFS options: options NFS_MINATTRTIMO=3 # VREG attrib cache timeout in sec options NFS_MAXATTRTIMO=60 diff --git a/sys/conf/options b/sys/conf/options index 19cca6f96c1a..2aee2d478b20 100644 --- a/sys/conf/options +++ b/sys/conf/options @@ -163,6 +163,7 @@ VFS_AIO VERBOSE_SYSINIT opt_global.h WLCACHE opt_wavelan.h WLDEBUG opt_wavelan.h +COMMONID opt_commonid.h # POSIX kernel options P1003_1B_MQUEUE opt_posix.h diff --git a/sys/i386/conf/GENERIC b/sys/i386/conf/GENERIC index b8025414824c..3c305cea0210 100644 --- a/sys/i386/conf/GENERIC +++ b/sys/i386/conf/GENERIC @@ -59,6 +59,7 @@ options _KPOSIX_PRIORITY_SCHEDULING # POSIX P1003_1B real-time extensions options KBD_INSTALL_CDEV # install a CDEV entry in /dev options ADAPTIVE_GIANT # Giant mutex is adaptive. options STOP_NMI # Stop CPUS using NMI instead of IPI +#options COMMONID # Enable support for common UID/GID space # Debugging for use in -current options KDB # Enable kernel debugger support. diff --git a/sys/ia64/conf/GENERIC b/sys/ia64/conf/GENERIC index b2f7183519f1..f28fcdff2f6f 100644 --- a/sys/ia64/conf/GENERIC +++ b/sys/ia64/conf/GENERIC @@ -53,6 +53,7 @@ options SYSVSHM # SYSV-style shared memory options UFS_ACL # Support for access control lists options UFS_DIRHASH # Hash-based directory lookup scheme options _KPOSIX_PRIORITY_SCHEDULING # Posix P1003_1B RT extensions +#options COMMONID # Enable support for common UID/GID space # Various "busses" device firewire # FireWire bus code diff --git a/sys/kern/vfs_subr.c b/sys/kern/vfs_subr.c index 45577abfa50f..83cd325ebd27 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 #include @@ -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) diff --git a/sys/pc98/conf/GENERIC b/sys/pc98/conf/GENERIC index 1903d71a5c10..fc79b866678b 100644 --- a/sys/pc98/conf/GENERIC +++ b/sys/pc98/conf/GENERIC @@ -59,6 +59,7 @@ options SYSVMSG # SYSV-style message queues options SYSVSEM # SYSV-style semaphores options _KPOSIX_PRIORITY_SCHEDULING # POSIX P1003_1B real-time extensions options KBD_INSTALL_CDEV # install a CDEV entry in /dev +#options COMMONID # Enable support for common UID/GID space # Debugging for use in -current options KDB # Enable kernel debugger support. diff --git a/sys/powerpc/conf/GENERIC b/sys/powerpc/conf/GENERIC index 87672623412a..d30b79565382 100644 --- a/sys/powerpc/conf/GENERIC +++ b/sys/powerpc/conf/GENERIC @@ -57,6 +57,7 @@ options SYSVSHM #SYSV-style shared memory options SYSVMSG #SYSV-style message queues options SYSVSEM #SYSV-style semaphores options _KPOSIX_PRIORITY_SCHEDULING #Posix P1003_1B real-time extensions +#options COMMONID # Enable support for common UID/GID space # Debugging for use in -current options KDB #Enable the kernel debugger diff --git a/sys/sparc64/conf/GENERIC b/sys/sparc64/conf/GENERIC index 77ac662dfedd..53ba35954ea4 100644 --- a/sys/sparc64/conf/GENERIC +++ b/sys/sparc64/conf/GENERIC @@ -58,6 +58,7 @@ options SYSVMSG # SYSV-style message queues options SYSVSEM # SYSV-style semaphores options _KPOSIX_PRIORITY_SCHEDULING # POSIX P1003_1B real-time extensions options ADAPTIVE_GIANT # Giant mutex is adaptive. +#options COMMONID # Enable support for common UID/GID space # Debugging for use in -current options KDB # Enable kernel debugger support.