From nobody@FreeBSD.ORG Fri May 28 11:09:57 1999
Return-Path: <nobody@FreeBSD.ORG>
Received: by hub.freebsd.org (Postfix, from userid 32767)
	id D86E3151E1; Fri, 28 May 1999 11:09:57 -0700 (PDT)
Message-Id: <19990528180957.D86E3151E1@hub.freebsd.org>
Date: Fri, 28 May 1999 11:09:57 -0700 (PDT)
From: aron@cs.rice.edu
Sender: nobody@FreeBSD.ORG
To: freebsd-gnats-submit@freebsd.org
Subject: access system call says file is readable when its not
X-Send-Pr-Version: www-1.0

>Number:         11915
>Category:       kern
>Synopsis:       access system call says file is readable when its not
>Confidential:   no
>Severity:       serious
>Priority:       medium
>Responsible:    freebsd-bugs
>State:          closed
>Quarter:        
>Keywords:       
>Date-Required:  
>Class:          sw-bug
>Submitter-Id:   current-users
>Arrival-Date:   Fri May 28 11:10:01 PDT 1999
>Closed-Date:    Thu May 24 02:37:56 PDT 2001
>Last-Modified:  Thu May 24 02:38:13 PDT 2001
>Originator:     Mohit Aron
>Release:        FreeBSD-3.2 Release
>Organization:
Rice University
>Environment:
FreeBSD luzern.cs.rice.edu 3.2-RELEASE FreeBSD 3.2-RELEASE #1: Wed May 26 18:02:08 CDT 1999     aron@luzern.cs.rice.edu:/usr/src/sys/compile/LUZERN  i386
>Description:
If a user has a file that is owned and readable only by him, and he
invokes a setuid executable (owned by some other user) that tries to
read this file, then the access() system call says that the file is
readable but when the file is opened for reading using fopen(), it fails.

>How-To-Repeat:
1) Create a file "foo" that's owned and is readable only by the current
   user (say X).
2) Compile the following C program and make the executable's owner to 
    be some other user (say Y) and turn on the setuid bit on the
    executable.
----------------------------- Cut Here ---------------------------------
#include <stdio.h>
#include <unistd.h>


main()
{
        FILE *fp;
        char *fname = "foo";


        if (!access(fname, R_OK)) {
                printf("access successful\n");
                fp = fopen(fname, "r");
                if (fp == NULL) {
                        printf("but fopen failed\n");
                }
        }
         
         
         
        return 0;
}
----------------------------- Cut Here ---------------------------------

3) Finally run the executable obtained above as user X. Notice how
   access is successful but an fopen() fails.

>Fix:


>Release-Note:
>Audit-Trail:

From: Bruce Evans <bde@zeta.org.au>
To: aron@cs.rice.edu, freebsd-gnats-submit@FreeBSD.ORG
Cc:  
Subject: Re: kern/11915: access system call says file is readable when its not
Date: Sat, 29 May 1999 20:31:05 +1000

 >>Description:
 >If a user has a file that is owned and readable only by him, and he
 >invokes a setuid executable (owned by some other user) that tries to
 >read this file, then the access() system call says that the file is
 >readable but when the file is opened for reading using fopen(), it fails.
 
 access() is supposed to work like that.  It checks that the real user can
 access the file.  Even if that's what you want, there may be races between
 checking the access and doing the access, so using access() is usually wrong.
 This is partly documented in the man page:
 
 CAVEAT
     Access() is a potential security hole and should never be used.
 
 Bruce
 

From: Mohit Aron <aron@cs.rice.edu>
To: freebsd-gnats-submit@freebsd.org
Cc:  
Subject: Re: kern/11915: access system call says file is readable when its not
Date: Sun, 30 May 1999 22:09:07 -0500

 Hi,
     I agree that using acess() may present a race condition and arguably
 one shouldn't use it. However, the very reason its still there is for
 backward compatibility for existing applications that use it. So the
 least it can do is to return the same value as fopen() when there was
 *no* race
 condition.
 
 As for how I ran into this. Well, it seems XOpenDisplay() library call
 in X11 uses access() to determine whether it can read a user's
 .Xauthority file. My home directory is NFS mounted on my
 desktop machine and the NFS server maps the "root" of my machine into
 "nobody". So setuid programs (like xterm and Eterm) have a potential
 problem - they run with the effective userid of
 root and when they try to open my .Xauthority file,  the NFS server
 refuses access. For this reason, Eterm temporarily swaps the real userid
 and effective userid (thus real userid becomes root and effective userid
 becomes my user id) before issuing XOpenDisplay(). However, because of
 thie problem with access() even this fails.  It can potentially make
 both the real userid and the
 effective userid to be my userid (and let the root's userid be saved in
 the FreeBSD saved userid),
 however, this might break its portability across other platforms - e.g.
 Linux.
 
 For these reasons, I'll argue that access() should behave similarly to
 the fopen() calls.
 
 
 - Mohit
 
 
 
State-Changed-From-To: open->closed 
State-Changed-By: phk 
State-Changed-When: Thu May 24 02:37:56 PDT 2001 
State-Changed-Why:  
As Bruce said: it's supposed to work like that. 

http://www.FreeBSD.org/cgi/query-pr.cgi?pr=11915 
>Unformatted:
