Interaction between chmod(), and ACL changing

Robert Watson rwatson at FreeBSD.org
Fri Sep 22 19:36:03 GMT 2000


While experimenting with the FreeBSD/TrustedBSD ACL implementation, I
observed the following counter-intuitive behavior.

The FreeBSD ACL implementation modifies ufs_chmod(), which is called from
ufs_setattr() (via VOP_SETATTR)).  When ufs_chmod() is invoked, if ACLs
are available on the file system, then the ACL_TYPE_ACCESS ACL on the
object is retrieved.  The following updates from 23.1.2 are performed:

(1) The corresponding permissions associated with the ACL_USER_OBJ entry
    shall be set equal to each of the file owner class permission bits.

This is a nop as I keep the *_OBJ and ACL_OTHER entries in the inode
permissions anyway.

(2) If the ACL does not contain an ACL_MASK entry, then the corresponding
    permissions associated with the ACL_GROUP_OBJ entry shall be set equal
    to each of the file group class permission bits. 

To perfom this, I retrieve the ACL, iterate to identify the ACL_MASK if
any.  If it is not present, the group bits in the inode mode are updated.

(3) If the ACL contains an ACL_MASK entry, then the corresponding
    permissions associated with the ACL_MASK entry shall be set equal to
    each of the file group class permission bits and the permissions
    associated with the ACL_GROUP_OBJ entry shall not be modified.

If the ACL_MASK was found above, it is updated with the permissions, and
ip->i_mode's group entries are used instead of being updated per the new
mode.  The ACL is written out to disk if a change has occured.

(4) The corresponding permissions associated with the ACL_OTHER entry
    shall be set equal to each of the file other class permission bits.

This is a nop since I keep the ACL_OTHER permissions in the mode anyway.

The problem is as follows: if I do a relative chmod using the chmod(1)
command, such as chmod o+w, the results may have odd side effects.  Sure
enough, the other class gains write permission, but because of the change
to the ACL_MASK, the ACL_USER entries may have modified effective rights.

Example:

% getfacl data
#file:data
#owner:1000
#group:0
user::rw-
group::r--
other::r--
user:test:rw-
mask::rw-
% chmod o+w data
% getfacl data
#file:data
#owner:1000
#group:0
user::rw-
group::r--
other::rw-
user:test:rw-           # effective: r--
mask::r--

The o+w has removed test's ability to write to the file.  The obvious fix
is to only perform each of the above ACL transformations if the relevant
bits are being changed from the existing settings.  I.e., perform a
specific equality test with the current "mode" (either real from the
inode, or generated from the ACL if there is actually no inode permission
set), and only perform the various steps above if a modification takes
place.

The spec does contain the following text:

    When the file permissions of an object are modified, e.g., using the
    chmod function, then:

However, that seems to say to me merely that if any of the mode changes
(as chmod(2) replaces the current mode, it doesn't actually update it), do
all the steps.

How have other people implemented this?  Is this odd behavior simply a
fact of life with ACLs, as relative mode changing is a product of the
chmod(1) tool, rather than of the POSIX API?  Should chmod(1) be taught
about ACLs (I'd rather not, I'd rather just modify the behavior of
chmod(2), as that catches other programs that set permissions).

On a similar note, if an ACL change modifies permissions (but not
ownership) for ACL_USER_OBJ or ACL_GROUP_OBJ, should the
{setuid,setgid,sticky} bits be removed from the inode?  CAP_FSETID covers
the case where their is a chown/chgrp operation, but it is always assumed
the chmod() will explicitely define all of the bits, rather than some of
the bits being modified as a result of the ACL operation.

  Robert N M Watson 

robert at fledge.watson.org              http://www.watson.org/~robert/
PGP key fingerprint: AF B5 5F FF A6 4A 79 37  ED 5F 55 E9 58 04 6A B1
TIS Labs at Network Associates, Safeport Network Services

To Unsubscribe: send mail to majordomo at cyrus.watson.org
with "unsubscribe posix1e" in the body of the message



More information about the posix1e mailing list