Chasing down bugs with access(2)

Garrett Cooper yanegomi at
Tue Jul 20 19:21:24 UTC 2010

Hi Hackers,
    I ran into an issue last night where apparently several apps make
faulty assumptions w.r.t. whether or not access(2) returns functional
data when running as a superuser.

POSIX says:

    In early proposals, some inadequacies in the access() function led
to the creation of an eaccess() function because:

       1. Historical implementations of access() do not test file
access correctly when the process' real user ID is superuser. In
particular, they always return zero when testing execute permissions
without regard to whether the file is executable.
       2. The superuser has complete access to all files on a system.
As a consequence, programs started by the superuser and switched to
the effective user ID with lesser privileges cannot use access() to
test their file access permissions.

    However, the historical model of eaccess() does not resolve
problem (1), so this volume of IEEE Std 1003.1-2001 now allows
access() to behave in the desired way because several implementations
have corrected the problem. It was also argued that problem (2) is
more easily solved by using open(), chdir(), or one of the exec
functions as appropriate and responding to the error, rather than
creating a new function that would not be as reliable. Therefore,
eaccess() is not included in this volume of IEEE Std 1003.1-2001.

    The sentence concerning appropriate privileges and execute
permission bits reflects the two possibilities implemented by
historical implementations when checking superuser access for X_OK.

    New implementations are discouraged from returning X_OK unless at
least one execution permission bit is set.

FreeBSD says:

     Even if a process's real or effective user has appropriate privileges and
     indicates success for X_OK, the file may not actually have execute per-
     mission bits set.  Likewise for R_OK and W_OK.

    This results in:

    sh/test - ok-ish (a guy on bash-bugs challenged the fact that the
syscall was buggy based on the details returned).
    bash - broken (builtin test(1) always returns true)
    csh  - not really ok (uses whacky stat-like detection; doesn't
check for ACLs, or MAC info)
    perl - ok (uses eaccess(2) for our OS).
    python - broken (uses straight access(2), so os.access is broken).

    So now the question is how to fix this? Linux reports the correct
mode for the file (when operating as superuser or not), and there's a
lot of code outside of *BSD that builds upon that assumption because
stat(2) doesn't test for permissions via POSIX ACLs, MAC, etc.
    I tried munging through the code to determine where VOP_ACCESS was
coming from but I got lost. Where should I look for this?

More information about the freebsd-standards mailing list