Capabilities and the sticky bit

Robert Watson rwatson at FreeBSD.org
Mon Oct 9 16:20:09 GMT 2000


On Thu, 7 Sep 2000, James Buster wrote:

> On Sep 7,  1:48pm, Robert Watson wrote:
> } The capabilities draft makes no mention of the sticky bit in its
> } discussion of interections between various capabilities, discretionary,
> } and mandatory access control policies.
> 
> On Irix, you need CAP_DAC_WRITE to remove a file you don't own when
> the sticky bit is set.

Hmm.  I've been thinking about this answer for a while, and seem to have
drawn different conclusions.  Let me take your through my analysis and
argument, and you can decide I'm nuts :-).

In the FreeBSD UFS implementation, there seem to be a class of access
checks based on comparing the effective uid of the process and the owner
uid of the file.  In my own development tree, I have replaced direct tests
of the effective/inode uids with invocations of VOP_ACCESS() and a new
access right, VADMIN.  Here are the commented and annotated checks.
Essentially, my conclusion was that the sticky bit overrides refer
specifically to the ownership property, not to the DAC override property,
and as such, they probably go under CAP_FOWNER.

ufs_lookup.c:
                /*
                 * If directory is "sticky", then user must own
                 * the directory, or the file in it, else she
                 * may not delete it (unless she's root). This
                 * implements append-only directories.
                 */
                if ((dp->i_mode & ISVTX) &&
                    VOP_ACCESS(vdp, VADMIN, cred, cnp->cn_proc) &&
                    VOP_ACCESS(tdp, VADMIN, cred, cnp->cn_proc)) {
                        vput(tdp);
                        return (EPERM);
                }

In this check, removal of a file in a sticky directory requires ownership
of the sticky directory, or of the file to be removed.  Either is
sufficient, and privilege may override the requirement for either. 

ufs_vnops.c:

                /*
                 * Callers may only modify the file flags on objects they
                 * have VADMIN rights for.
                 */
                if ((error = VOP_ACCESS(vp, VADMIN, cred, p)))
                        return (error);

In this check, setting of flags on an object requires ownership of the
object, or appropriate privilege.  This is distinct from the later
privilege check associated with system flags.

                /*
                 * From utimes(2):
                 * If times is NULL, ... The caller must be the owner of
                 * the file, have permission to write the file, or be the
                 * super-user.
                 * If times is non-NULL, ... The caller must be the owner of
                 * the file or be the super-user.
                 */
                if ((error = VOP_ACCESS(vp, VADMIN, cred, p)) &&
                    ((vap->va_vaflags & VA_UTIMES_NULL) == 0 ||
                    (error = VOP_ACCESS(vp, VWRITE, cred, p))))
                        return (error);

Updating the timestamps on a file requires you to own the file, or to
update to the current time, be able to write to the file.  Privilege can
override the requirement of either check.

        /*
         * To modify the permissions on a file, must possess VADMIN
         * for that file.
         */
        if ((error = VOP_ACCESS(vp, VADMIN, cred, p)))
                return (error);

Ownership is required, or appropriate privilege must be asserted, to
change permissions on a file.  This is distinct from the requirement of
privilege to set specific aspects of the file permission, rather, this is
the initial check that any permissions can be set at all.

        /*
         * To modify the ownership of a file, must possess VADMIN
         * for that file.
         */
        if ((error = VOP_ACCESS(vp, VADMIN, cred, p)))
                return (error);

Same goes with this: to change any ownership properties, must be the
owner, or hold appropriate privilege.  Later access checks verify whether
or not this particular ownership change is appropriate based on group
membership and privilege.

                /*
                 * If the parent directory is "sticky", then the caller
                 * must possess VADMIN for the parent directory, or the
                 * destination of the rename.  This implements append-only
                 * directories.
                 */
                if ((dp->i_mode & S_ISTXT) &&
                    VOP_ACCESS(tdvp, VADMIN, tcnp->cn_cred, p) &&
                    VOP_ACCESS(tvp, VADMIN, tcnp->cn_cred, p)) {
                        error = EPERM;
                        goto bad;
                }

In this check, over-writing of a file in a sticky directory via rename
requires ownership of the sticky directory, or the target file.  Either is
sufficient, and privilege may override the requirement for either. 

I.e., this class of checks is well-described by the CAP_FOWNER description
in POSIX.1e D17:

  This capability overrides the requirement that the user ID associated
  with a process be equal to the file owner ID, except in the cases where
  the CAP_FSETID capability is applicable.  In general, this capability,
  when effective, will permit a process to perform all the functions that
  any file owner would have for their files.

It is possible to imagine situations in which CAP_DAC_WRITE might be
relied upon to provide the ability to delete any file.  This would fail
for sticky directories where the holder of the capability is not owner of
either the target or the directory in which the target is present.  On the
other hand, the sticky bit is an odd character, and not part of the
traditional mode bits: when it is present, the definition of other mode
bits is substantially warped.  Due to the nature of the mode bits, the
sticky bit is the only bit you can add that removes rights--other bits all
add new rights.  It is certainly more consistent with our current access
checks that CAP_FOWNER would override the sticky bit behavior: CAP_FOWNER
would simply satisfy any requirement for VADMIN:

        if ((acc_mode & VADMIN) && ((dac_granted & VADMIN) == 0) &&
            !cap_check_xxx(cred, NULL, CAP_FOWNER, PRISON_ROOT))
                cap_granted |= VADMIN;

  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