Help needed for hacking the acl mask
Robert Watson
rwatson at FreeBSD.org
Fri Oct 21 03:40:38 PDT 2005
On Fri, 21 Oct 2005, Heinrich Rebehn wrote:
> Since we do need usable acls here at work, i decided to go for a quick
> and dirty hack. Can someone point me to the code location(s) where the
> acl mask is overwritten?
>
> I already found sys/kern/kern_acl.c and changed it so that the mask is
> ORed with the create mode. This works for newly created files,regardless
> of the umask setting.
My impression, although I haven't investigated in a year or two, is that
it actually should be a little more complicated than this if you want to
run with the Solaris mask semantics. Specifically, the problem is that
the umask has already masked application-requested creation bits by the
time cmode is passed to acl_posix1e_newfilemode(), so all you can do there
is decide not to impose the ACL mask, whereas to get the Solaris semantics
you want to impose the ACL mask but not the umask. Correcting this is
fairly complicated, as it requires that acl_posix1e_newfilemode() gain
access to the original requested mode from the system call, which is
normally not passed to the file system VOP, it's actually evaluted in the
high level system call code before even entering the file system code.
When I last left off exploring a solution, I concluded that what I wanted
to do was pass the process umask and process requested mode into all VOP's
that create objects, rather than the post-processed creation mode. Then
this would be passed into acl_posix1e_newfilemode(), and depending on the
presence of ah ACL mask entry in the parent default ACL,
acl_posix1e_newfilemode() could then decide whether or not to incorporate
the umask or not. This turned out to be further complicated by the fact
that the combination of the umask and system call creation mode was
performed in a way sensitive to the type of object and method of creation.
Different system calls mask or ignore different additional bits (such as
the sticky bit) depending on the object type. This left me with a todo
item of determining if this was correct or not, and I didn't have a chance
to follow up at that point. However, looking at the above, it requires
making modifications to the file system VFS interface, each file system,
etc, and so I moved on to other more pressing issues that had to be
addressed.
> However, chmod g-w still resets the write bit of the acl mask. I thought
> this was handled in lib/libc/posix1e/acl_calc_mask.c, but it does not
> seem to be called by chmod(1).
This is because, according to POSIX.1e, the file permission bits are in
fact simply a subset of the ACL, not an additional set of values that are
evaluated as well as the ACL. The confusing thing about the POSIX.1e ACL
behavior with chmod() and stat() is how this is done: the answer is that
it depends on whether or not there is an ACL_MASK entry. If there is no
ACL mask entry, the owner, group, and other fields in the mode override
the ACL_USER_OBJ, ACL_GROUP_OBJ, and ACL_OTHER entries in the ACL.
However, if there is a mask entry, they respectively override the
ACL_USER_OBJ, ACL_MASK, and ACL_OTHER entries. The idea being that if you
have an extended acl, the group bits in the requested mode change will
mask all non-owner and non-other entries in the ACL. This is discussed in
detail in POSIX.1e, and is a feature present in all POSIX.1e or
POSIX.1e-like implementations I'm aware of. This allows an application
that doesn't understand ACLs to conservatively change the file mode.
The implementation of this is somewhat complicated, so I draw your
attention to two functions in the UFS ACL code:
ufs_sync_acl_from_inode() - the mode field on the inode has changed, and
the ACL entries should be synchronized to it.
ufs_sync_inode_from_acl() - the ACL on a file has been changed, and the
inode mode should be updated.
You'll see that in ufs_chmod(), the two are not resynchronized: this
allows the ACL fields to be stale with respect to the inode mode field.
This is rectified later because when the ACL is pulled off the disk or out
of the buffer cache by ufs_getacl(), it calls ufs_sync_acl_from_inode() to
update those fields. This avoids chmod() resulting in an extended
attribute write, which is quite expensive. It also helps in the
implementation of optimizations that avoid storing an ACL for a file if no
ACL has been put on the file.
If you're looking to change how chmod() and ACLs interact, you'll need to
think very carefully about the implications in this context. Off hand,
I'm not sure the exact details of what you want to change will be -- you
will probably, among other things, need to change how ACLs are
re-synchronized to the inode mode when the ACL is read from the disk --
you might find that you do need to write out a new ACL when chmod()
occurs, or that you can use the same inconsistency optimization I describe
above but with a slightly different implementation.
The other thing to be aware of is that POSIX.1e (programmatic interfaces)
and POSIX.2c (user commands) provide slightly different semantics for the
user, so if you're used to the way the setfacl command works, the
underlying APIs that implement it are a bit different. Specifically,
setfacl has the notion that the mask is reculculated automatically based
on the change -- this is purely a property of the user application. The
kernel has no notion of recalculating the mask based on changes to ACL
fields, with the exception that the mask is modified by chmod().
Much of the weirdness in POSIX.1e ACLs is a property of trying to continue
to offer file mode semantics in a conservative way so that applications
see what they expect even if they don't support ACLs -- for example, that
if they chmod() a file, stat() will show the expected resulting mode, and
"something useful" will happen to the ACL as a result. I don't make any
claim that this is optimal from a user perspective in the presence of
applications that do understand ACLs. The only real modification to
mode/ACL semantics I've been considering is the change in umask operation,
as described above, and implemented in Solaris and Linux. In the past, it
has been observed that even minor tweaks in ACL/mode interaction can
result in security vulnerabilities, usually due to violating user or
application assumptions, and so I advise a lot of caution :-).
Robert N M Watson
More information about the freebsd-fs
mailing list