Skip site navigation (1)Skip section navigation (2)
Date:      Thu, 28 Oct 1999 17:59:39 -0700 (PDT)
From:      babkin@bellatlantic.net
To:        freebsd-gnats-submit@freebsd.org
Subject:   kern/14584: Proposition for improved file permissions (partial substitution of ACLs)
Message-ID:  <19991029005939.02A8514E22@hub.freebsd.org>

next in thread | raw e-mail | index | archive | help

>Number:         14584
>Category:       kern
>Synopsis:       Proposition for improved file permissions (partial substitution of ACLs)
>Confidential:   no
>Severity:       non-critical
>Priority:       medium
>Responsible:    freebsd-bugs
>State:          open
>Quarter:        
>Keywords:       
>Date-Required:
>Class:          change-request
>Submitter-Id:   current-users
>Arrival-Date:   Thu Oct 28 18:00:00 PDT 1999
>Closed-Date:
>Last-Modified:
>Originator:     Sergey Babkin
>Release:        3.2-RELEASE
>Organization:
>Environment:
>Description:

Here is the copy of description I posted in -hackers some
time ago. Up to now I had one reply from someone who was 
interested in this proposition.

ACLs are a popular thing nowadays and
as far as I know FreeBSD does not have it yet. But although 
everyone boasts with their ACL support I think nobody is really
using it (and if somebody is using it then I think it's often 
not the best decision). ACLs have obvious drawbacks:

- they are not supported by the standard file formats like tar
or cpio
- they need lots of ugly flags for the commands like chown or
ls, and some new ugly commands
- they are just by themselves difficult to show clearly in ls
- they are a mess and promote ad-hoc assignment of permissions

For example, Netware suports ACLs and I have seen by myself
what mess the sysadmins who have head problems are able to
create with them.

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 Unix permissions support permissions for only one 
group and that makes the problem. A simple solution would be to 
add the second group but this would also break the compatibility.
I propose to re-use the "uid" field to hold the permissions
for the second group.

Suppose we do the following:

1. Add a sysctl flag enabling or disabling (by default) the extended
permissions. That should completely cover the compatibility issues.

2. Sysadmin uses unique IDs for the users and groups in the common
ID space. Say, if there is a user with ID=2000 then there must
be no group with ID=2000 (except a special case described later). 
Traditionally there is such overlapping in the low IDs, so let's 
enable the new behavior only for IDs > 1000 (or some other number,
possibly another sysctl parameter).

3. Implement the following semantics (a simple and straightforward
addition to ufs_access() ): if the new behavior is enabled and 
the file owner's ID is over 1000 (or a sysctl parameter) then
in addition to comparing the process'es UID with the file owner ID
we compare all process'es group IDs with the file owner ID
and if any of them matches we use the "owner" permissions for this
process. So, in effect we consider the file owner ID as both
user and group number, and the described problem with two
groups with different permissions is solved. 

4. The described semantics is used only for file access but not
modification of the access rights, the "owner group" can't modify
the permissions of the file. And here we come to the special case
mentioned in p.2: if there is an user with UID equal to the GID of
the "owner group" such user can modify the permissions. This user
may be a pseudo-user created together with the group. If we want
to give the "owner group" the right to change all permissions of
its files we can just do something like (suppose we have user 
`mygrp' and group `mygrp' with the same ID):
# cp /bin/chmod /usr/local/bin/mygrpchmod
# chown mygrp /usr/local/bin/mygrpchmod
# chmod 500 /usr/local/bin/mygrpchmod
# chmod u+s /usr/local/bin/mygrpchmod
The same thing may be ised for chown. 
In result all the group members will be able to execute mygrpchmod,
and when it will be executed it will assume the EUID of the user
mygrp and will be able the file permissions. Or we can do `chmod 050'
and give the permission to modify all the permissions of this "owner
group" to another group of users. Having a pseudo-user
with the same ID as a group also gives for free `ls' showing the 
right symbolic owner name.

5. If this behavior is wanted on NFS, that can be done too.
Probably, with a separate sysctl flag.

These additions give essentially the same flexibility as
ACLs give but without any change in the i-node format, ls and
tar/cpio formats, don't really need any special programs nor
flags to manipulate them. Though a few user-level additions may 
be added for convenience, such as automatic addition of a 
pseudo-user for each  defined group, check for user/group ID 
conflicts, multi-level groups, additional programs to give better 
granularity of control over file permissions.

The only thing this substitute misses is the ability of the 
users to grant access to their files to anyone else as an
arbitrary list. But that does not seem to be a big drawback.

That's all. I think the idea is rather simple and clean.


>How-To-Repeat:

>Fix:
And here is the patch itself. I'm willing to write the manual pages
also but only if there will be a decision to commit the changes to
the source tree, otherwise it would be a wasted work.

I'm not sure whether the sysctl sub-node vfs.ufs is really neccessary
but it seems to be logical.

-------------------------- cut here -----------------------------
*** /sys/ufs/ufs/ufs_vnops.c    1999/07/15 14:50:53     1.1
--- /sys/ufs/ufs/ufs_vnops.c    1999/07/22 18:16:28
***************
*** 57,62 ****
--- 57,63 ----
  #include <sys/dirent.h>
  #include <sys/lockf.h>
  #include <sys/poll.h>
+ #include <sys/sysctl.h>
  
  #include <vm/vm_zone.h>
  #include <vm/vm.h>
***************
*** 104,109 ****
--- 105,128 ----
  static int ufsspec_read __P((struct vop_read_args *));
  static int ufsspec_write __P((struct vop_write_args *));
  
+ #ifdef ENABLE_UFS_COMMONID
+ /*
+  * Sysctl variables to control the unified user and
+  * group ID space.
+  * commonid is the lowest ID from which the common UID/GID space starts
+  * MINCOMMONID is the minimal value, if commonid is lower then the
+  * common ID space is disabled
+  */
+ 
+ #define MINCOMMONID   100
+ 
+ SYSCTL_NODE(_vfs, OID_AUTO, ufs, CTLFLAG_RW, 0, "Local Unix-type filesystems");
+ static int commonid=0;
+ SYSCTL_INT(_vfs_ufs, OID_AUTO, commonid, CTLFLAG_RW, &commonid, 0,
+       "Lowest ID for the common GID/UID space");
+ 
+ #endif
+ 
  union _qcvt {
        int64_t qcvt;
        int32_t val[2];
***************
*** 339,344 ****
--- 360,382 ----
                        mask |= S_IWUSR;
                return ((ip->i_mode & mask) == mask ? 0 : EACCES);
        }
+ 
+ #ifdef ENABLE_UFS_COMMONID
+       /* if the common UID/GID is enabled check the groups against the file UID */
+       if (commonid >= MINCOMMONID && ip->i_uid >= commonid) {
+               for (i = 0, gp = cred->cr_groups; i < cred->cr_ngroups; 
+                               i++, gp++)
+                       if (ip->i_uid == *gp) {
+                               if (mode & VEXEC)
+                                       mask |= S_IXUSR;
+                               if (mode & VREAD)
+                                       mask |= S_IRUSR;
+                               if (mode & VWRITE)
+                                       mask |= S_IWUSR;
+                               return ((ip->i_mode & mask) == mask ? 0 : EACCES);
+                       }
+       }
+ #endif
  
        /* Otherwise, check the groups. */
        for (i = 0, gp = cred->cr_groups; i < cred->cr_ngroups; i++, gp++)
--------------------------- cut here ------------------------------------

It probably may be implemented as a FS layer but I'm not sure whether 
doig that is a good idea. It is certainly possible to do by snooping
at the getattr/setattr calls but IMHO it will mean completely bypassing
the VOP_ACCESS of the underlying filesystem what may be not good.

On the other hand the changes to ufs_assess() seem to be quite small
and cover all the UFS type filesystems, such as FFS and EXT2FS.

Of course yet another option is to create one more fs type with all
the operations in the filesystem switch the same as for FFS except
for ufs_access().



>Release-Note:
>Audit-Trail:
>Unformatted:


To Unsubscribe: send mail to majordomo@FreeBSD.org
with "unsubscribe freebsd-bugs" in the body of the message




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