Question regarding UNIX access() call - Unix

This is a discussion on Question regarding UNIX access() call - Unix ; Hi, I was wondering if there is a function similar to access(2), but one that uses *effective* userid and groupid rather than *real*? For instance, in order to test whether the process has execute permissions on the file I can ...

+ Reply to Thread
Results 1 to 5 of 5

Thread: Question regarding UNIX access() call

  1. Question regarding UNIX access() call


    Hi,

    I was wondering if there is a function similar to access(2), but one
    that uses *effective* userid and groupid rather than *real*?

    For instance, in order to test whether the process has execute
    permissions on the file I can call access(file, X_OK). However, I want
    to check if my effective UID/GID and supplementary groups allow me to
    execute this file. How can I do this kind of check?
    I can certainly read the access control list using libacl, but I
    guess there must be simpler way to do it.

    Checking for read and write permissions is easy - I can just open the
    file in read or write mode and check the return value of open(). In
    case of execute I dont want to just execute the file since the process
    that is performing this check is a networked file server which is
    processing the requests from remote users. That is, the remote client
    checks with the file server to see if the user can execute this file
    (by forwarding the access request to the server). The file server
    which is running as root switches its effective uid and gid to that of
    the requester and then performs the requested operation.

    What would be a good way to handle this?

    Thanks in advance.
    -Fantoosh


  2. Re: Question regarding UNIX access() call

    On Jul 31, 9:05 pm, Fantoosh B wrote:
    > I was wondering if there is a function similar to access(2), but one
    > that uses *effective* userid and groupid rather than *real*?


    Not that I know of.


    > What would be a good way to handle this?


    Swap the process's effective and real uids and gids using setreuid()
    or setresuid() and one of their gid equivalents, call access(), then
    swap them back. Issues:
    1) if one of the set* calls fails, the process is screwed
    (this is probably a "can't happen", but to be safe in the face of
    OS
    changes you better test and die if one fails. Linux capabilities
    made
    it possible for setuid() to fail for root, creating security holes
    in several
    programs...)
    2) this is probably too painful if the process is multithreaded
    3) setreuid() and setresuid() aren't as portable as one might wish.


    Philip Guenther


  3. Re: Question regarding UNIX access() call

    Fantoosh B writes:

    >I was wondering if there is a function similar to access(2), but one
    >that uses *effective* userid and groupid rather than *real*?


    Not a standard one. (Solaris, e.g., has eaccess() in a separate library
    and a secret "E_OK" flag which you can or in to the access flags)

    >For instance, in order to test whether the process has execute
    >permissions on the file I can call access(file, X_OK). However, I want
    >to check if my effective UID/GID and supplementary groups allow me to
    >execute this file. How can I do this kind of check?
    >I can certainly read the access control list using libacl, but I
    >guess there must be simpler way to do it.


    You are approaching this incorrectly because you can never be sure
    you can execute a program before you actually executed it.

    Is there any reason why you can't "just do it"?

    Casper

  4. Re: Question regarding UNIX access() call

    I am running Linux and setresuid did the trick for me. Heres the
    simple function to switch ids. Thanks.

    /* Changes uid and gids to that of the requesting user */
    int set_access_ids(uid_t fsuid, uid_t fsgid, size_t num_sgrps, const
    gid_t *sgrps){
    /* Root uid and gid is disallowed */
    if(fsuid == ROOT_UID || fsgid == ROOT_GID)
    return -1;
    int i = 0;
    for( i = 0; i < num_sgrps; i++){
    if(sgrps[i] == 0) return -1;
    }

    /* Lets change the ids */
    if(setresuid(ROOT_UID, ROOT_UID, ROOT_UID) < 0) return -1; //
    Escalate to root
    if(setresgid(ROOT_UID, ROOT_GID, ROOT_GID) < 0) return -1;

    if(setgroups(1, &fsgid) < -1) return -1; /* Wipe out previous
    * supplementary groups */
    if(setresgid(fsgid, fsgid, fsgid) < 0) return -1; /* Drop
    * privileges to
    * that of the
    * user */

    if(num_sgrps > 0) {
    if(setgroups(num_sgrps,sgrps) < 0) return -1;;
    }

    if(setresuid(fsuid, fsuid, ROOT_UID) < 0) return -1; /* Always set
    * the euid at
    * the last */

    return 0;
    }

    On Jul 31, 10:49 pm, "guent...@gmail.com" wrote:
    > On Jul 31, 9:05 pm, Fantoosh B wrote:
    >
    > > I was wondering if there is a function similar to access(2), but one
    > > that uses *effective* userid and groupid rather than *real*?

    >
    > Not that I know of.
    >
    > > What would be a good way to handle this?

    >
    > Swap the process's effective and real uids and gids using setreuid()
    > or setresuid() and one of their gid equivalents, call access(), then
    > swap them back. Issues:
    > 1) if one of the set* calls fails, the process is screwed
    > (this is probably a "can't happen", but to be safe in the face of
    > OS
    > changes you better test and die if one fails. Linux capabilities
    > made
    > it possible for setuid() to fail for root, creating security holes
    > in several
    > programs...)
    > 2) this is probably too painful if the process is multithreaded
    > 3) setreuid() and setresuid() aren't as portable as one might wish.
    >
    > Philip Guenther




  5. Re: Question regarding UNIX access() call

    On Aug 1, 12:18 pm, Casper H.S. Dik wrote:
    > Fantoosh B writes:
    > >I was wondering if there is a function similar to access(2), but one
    > >that uses *effective* userid and groupid rather than *real*?

    >
    > Not a standard one. (Solaris, e.g., has eaccess() in a separate library
    > and a secret "E_OK" flag which you can or in to the access flags)
    >
    > >For instance, in order to test whether the process has execute
    > >permissions on the file I can call access(file, X_OK). However, I want
    > >to check if my effective UID/GID and supplementary groups allow me to
    > >execute this file. How can I do this kind of check?
    > >I can certainly read the access control list using libacl, but I
    > >guess there must be simpler way to do it.

    >
    > You are approaching this incorrectly because you can never be sure
    > you can execute a program before you actually executed it.


    I am writing a networked file system. The file server is a user-space
    process that receives requests from the clients and processes them.
    The client file system is built using FUSE(http://
    fuse.sourceforge.net/), which is also in the user-space. Now, If a
    process wants to check if it can perform a particular operation on a
    file R,W,X etc, then at the client side, I can let the OS take care of
    these checks based on the results retured by the stat (and getxattr
    for posix acls) calls from the client. However, for this to work uids
    and gids on the server and the client machine have to be synchronized,
    which is not happening in my case yet. Instead, FUSE lets my file
    system to trap the access() system call. This is nice because then the
    client filesystem can simply transfer the access call across to the
    server and the server can perform the check. For example, strace of vi
    shows that before opening a file vi calls: access(foo.txt, R_OK),
    access(foo.txt,W_OK). If the second access() call is successful VI
    does all kinds of strange things: creates foo.tmp, deletes the
    foo.txt, and then creates foo.txt again and copies foo.tmp to foo.txt.
    So if my uid and gids are not synchorized, the client side access()
    function has no way to accurately check the rights. A wrong response
    to the second access() call screws up the foo.txt. Instead, I forward
    the access() call to the server and the server switches ids and
    performs a local access().

    Since the server is doing the check, I dont want the server to
    unecessarily execute the users file ( which is dangerous as well since
    the server is running as root).

    Certainly, in case of X_OK a successful access() does not necessarily
    indicate that a user can execute the file (execv can still fail), but
    in this case the client is just trying to get a hint whether it can
    attempt to execute the file. Also, right now I am not to worried about
    portability. Please let me know if I am on a totally wrong path. Thank
    you.



    >
    > Is there any reason why you can't "just do it"?
    >
    > Casper




+ Reply to Thread