[comp.lang.c] [braindamaged?] use of access

friedl@vsi.UUCP (Stephen J. Friedl) (02/29/88)

Netlanders,

     This comes up all the time and it has been very frustrating.
I want to get this off my chest, see if anybody else has seen
this problem, get some suggestions, and plea for people not to
misuse the access(2) system call.

     First, a little background.  We develop business-type
applications using a commercial database package.  We use a 3B2
but I have seen this problem all over.  We like to set these
systems up in a secure manner with protected project areas and
limited entry points (say, just a single "inventory" command that
calls up a menu).

     To do this, we provide a front-end program (the "inventory"
program mentioned above) and make it set-group-id to the project.
Here, assume that the group is "inv" and only the project uses it
(everybody else is "staff" or whatever).  All the project
directories are rwxrwx--- and this effectively keeps everybody
else out.  It keeps the inventory package out too.

     The problem is with the access(2) system call.  Reading the
manual page of this function makes you think that this is a
handy-dandy "does the file exist?" function and it is used this
way by a lot of programs.  The curious/insighful person might
wonder why they would make a system call like this when stat(2)
can trivially do the same job -- access(2) should be access(3).
I wondered for a long time too.

      Access(2) should almost never be used.  It does what
stat(2) does except it uses the REAL userid and not the EFFECTIVE
userid like every other system call uses.  It is designed for use
by setuid/setgid programs to verify the permissions of the
"underlying" user.

     To illustrate, let's say that the uucp Systems or L.sys file
on your machine is unreadable by anybody other than uucp but you
want to see it.  So, you run /usr/bin/cu, which is setuid "uucp"
and call another system.  You figure that

        ~%put /usr/lib/uucp/Systems /tmp/Systems.stolen

will write the file over there.  Uucp clearly has permission to
access this file, and the open(2) call will work just fine, but
cu won't do this for you, probably because of access(2) [note:
several other methods come to mind but this is a pretty good demo
of access].  When you are running cu, your permissions might be
as follows:

        real uid      = friedl (that's me)
        effective uid = uucp   (that's him/her/it)

     When cu does an access("/usr/lib/uucp/Systems, READ), it is
asking "does the real uid (friedl) have READ access to this
file?" Access says no so cu tells me to get lost.

     It is possible to implement access(2) yourself with stat and
getuid/getgid but it is a little tricky and error prone.
Presumably the original Unix guys decided to put it in the kernel
to keep it safe and easy.

     "OK", you say, "so we have this handy function that does a
useful task.  If I'm not running setuid or setgid then it doesn't
matter".  You're right, your program may not be setuid but I
might want to run it that way as part of a larger system.  This
messes me up.

    [Disclaimer: I don't *know* that the shell is doing things
this way but it sure looks like it].  When the shell is asked to
execute a command without a full pathname, it searches along the
$PATH for the program you've requested.  For each component in
$PATH, it constructs the full pathname and runs access(2) on it.
If access says OK then it does an actual exec.  I would guess
this is done because access(2) is a lot quicker than trying a lot
of execs and having them fail, but I'm not sure.

     The problem comes about when the directory is open to the
group but closed to other.  Say I have a program:

  10 -rwxr-x---   1 inv   inv    4724 Feb 26 22:57 /usr/acct/report

and "/usr/acct" is in my search path.  In a shell script called
from a menu I try to execute "report" without a full pathname.
The shell looks in the $PATH, does access("/usr/acct/report") but
it fails because *my* personal group (staff) has no permissions
and I get a message to that effect from the shell.  If I type the
command so $PATH is not used, it works fine, presumably because
the shell believes you know where it is and just does an exec
directly without the access.  This problem occurs whether setuid
or setgid is used: if the effective user/group has permission but
the underlying (real) user/group does not, access(2) fails even
though exec(2) would not.

     There are a number of possible solutions to this:

(1)  Forget setuid/setgid.  I really don't like this because it
     requires full access for everybody.  I have a little sign on
     my wall:         _____
	             /   //\
	       	   /    //   \
	          | chmod 777 |
	           \  //     /
	             \/____/

     (imagine the sign being red and round).  I think 777 is
     sloppy.

(2)  Make all the commands open.  This is what we usually do but
     I don't like it: I make the main project directory rwxrwx--x
     and give the minimum permissions possible.  I have to really
     keep on my toes to have a secure system but not forget a
     chmod a+x somewhere.

(3)  Use full pathnames.  Sigh, that is really a lot of work.
     For the really secure systems it is the only way to really
     do it but it sure makes scripts messy and hard to maintain.

(4)  Make all the users in the same group.  This is not a bad
     idea but it gets messy if we develop more than one unrelated
     system on a machine -- this happens a lot.

(5)  Fix the shell ha ha ha.

(6)  Something I haven't thought of.  Anybody?

     If the shell were the only place it would not be so tough
but it is not.  The test(1) command uses access(2) for some of
its queries, so

     if [ -r $filename ] ; then
          ...

says "not readable" for the same reasons, so $filename must be
readable by everybody.  Note: I understand that System V Release
3 fixed test(1) but the $PATH search still seems to be broken.

     There are others: The tmpnam(3) function call uses
access(2), the Informix screen manager (sperform) uses it when
looking for forms to run, etc., etc.

     [coming down to the wire]  Am I correct that the majority of
uses of access(2) are incorrect?  What can be done about this?
Anybody have any thoughts?

     Sigh,
     Steve

P.S. - sorry this is so long...
-- 
Life : Stephen J. Friedl @ V-Systems, Inc/Santa Ana, CA    *Hi Mom*
CSNet: friedl%vsi.uucp@kent.edu  ARPA: friedl%vsi.uucp@uunet.uu.net
uucp : {kentvax, uunet, attmail, ihnp4!amdcad!uport}!vsi!friedl

strick@stratus.UUCP (henry strickland) (03/02/88)

In article <59@vsi.UUCP> friedl@vsi.UUCP (Stephen J. Friedl) writes:
>
> ....
>
>     The problem is with the access(2) system call.  Reading the
>manual page of this function makes you think that this is a
>handy-dandy "does the file exist?" function and it is used this
>way by a lot of programs.  The curious/insighful person might
>wonder why they would make a system call like this when stat(2)
>can trivially do the same job -- access(2) should be access(3).
>I wondered for a long time too.
>
>      Access(2) should almost never be used.  It does what
>stat(2) does except it uses the REAL userid and not the EFFECTIVE
>userid like every other system call uses.  It is designed for use
>by setuid/setgid programs to verify the permissions of the
>"underlying" user.

(*
	The question was kind of vague (if it was a question: it's more
	of a proclamation:  "Access(2) should almost never be used.")
	I think the following answers some aspect of your problem;
	particularly the 
		{ setuid(geteuid()) ; setgid(getegid()) }
	line may be what you need.
*)


I also feel that access() should almost never be used, but for
quite different reasons.

First (and I think you realized it) you're not using access()
for what it was intended.  

/*	Like you explained, it was intended for programs such as "mail"
	to make sure the REAL user/group has permission
	to write/read stuff from where the user has said to write/read
	the stuff from.      

	*** There are security holes in this approach. ***
	These holes are why I say one should rarely use access().

	The correct thing to do is 
		{ setuid(getuid()) ; getgid(getgid()) }
	before doing the i/o.   This allows the real unix permission
	checking to do its job.   This is the safe approach.

	( Even as we speak there are major UNIX
	  "supermicros" being sold that run mail as root and
	  don't use EITHER the flawed access() or the better
	  setuid,setgid approach.       I've told them about
	  it, but they haven't fixed it, to my knowledge.
	  But unless you're a real hack-unix
	  guru and think you know ALL the tricks, don't
	  ever assume your machine doesn't have one of these real
	  nasty rootholes.  BTW, I think berkeley /bin/mail is an example
	  of setuid-root code done correctly. )

	If you later will need the capabilities of your effective
	uid and gid, fork a child to do the job, and wait for it
	to die.   Then continue.
*/


But back to your problem.

How you should be doing things is also with the real unix permission
checking.

If you want to know if your effective uid/gid has permission
to read a file or directory, you can just try opening it.

But if you want to be using access(), do
		{ setuid(geteuid()) ; setgid(getegid()) }
(and then, if you like, use access).   It seems to me that your entire program
could work by doing this at the top of the program and then just
forgetting about it.  Or if you do need to open/creat some of the real
user's files, do all of that open/creating BEFORE doing the above line.
Be sure the program has no shell escapes, etc!
Opening the real user's files early and eliminating shell escapes seems 
far less drastic than any of the things you enumerated in your posting.

If your program is going to be needing a combination of real and
effective permissions at many points throughout, you can either

	-- keep the origional process with the different real/effective
		 permissions and do a lot of forking when the real permits
		are needed (or when you give the user a shell escape, etc.)

or else
	-- fork off a child with a pipe to it so that you can give it 
		commands, and let the child run as the real userid:
			{ setuid(getuid()) ; getgid(getgid()) }
		Then the parent can run as the effective id:
			{ setuid(geteuid()) ; setgid(getegid()) }
		and you've got either when you need it.
		Depending on how complex your application is, 
		this could get really ugly.

I'm sure that there is a real solution to your problem, without resorting
to any of the things your enumerated, or else it would have been fixed
already.   

I think that access() is a late addition to unix (when did it come?).
You're right, anything can be done without it, but using stat() as
you suggested may be as bad as access().



-- 
Henry Strickland     <strick@gatech.edu>     gatech!strick   404-676-1313

chris@trantor.umd.edu (Chris Torek) (03/02/88)

>In article <59@vsi.UUCP> friedl@vsi.UUCP (Stephen J. Friedl) writes:
>>      Access(2) should almost never be used.

In article <1056@stratus.UUCP> strick@stratus.UUCP (henry strickland) writes:
>Like you explained, it was intended for programs such as "mail"
>to make sure the REAL user/group has permission
>to write/read stuff from where the user has said to write/read
>the stuff from.      
>
>*** There are security holes in this approach. ***

This is true (the hole is a `race' hole: get a set-ID program to
decide something is secure, then change the operation while it is
not looking, just before it actually does it).  But:

>The correct thing to do is 
>	{ setuid(getuid()) ; getgid(getgid()) }
>before doing the i/o.   This allows the real unix permission
>checking to do its job.   This is the safe approach.

This approach may be (often is) insufficient.  In 4.2 and 4.3 BSD,
you can do this cleanly and correctly, by swapping real and effective
IDs; the swap may be performed any number of times, unlike setgid/setuid,
which is irreversable (except under peculiar conditions in SysV).

>If you later will need the capabilities of your effective
>uid and gid, fork a child to do the job, and wait for it
>to die.   Then continue.

This is horribly inefficient, and can be overly difficult.  It is,
however, portable.

>I think that access() is a late addition to unix (when did it come?).

It has been around since at least V7, I think.
-- 
In-Real-Life: Chris Torek, Univ of MD Computer Science, +1 301 454 7163
(still on trantor.umd.edu because mimsy is not yet re-news-networked)
Domain: chris@mimsy.umd.edu		Path: ...!uunet!mimsy!chris

friedl@vsi.UUCP (Stephen J. Friedl) (03/02/88)

In article <1056@stratus.UUCP>, strick@stratus.UUCP (henry strickland) writes:
> In article <59@vsi.UUCP> friedl@vsi.UUCP (Stephen J. Friedl) writes:
> >[....]
> >      Access(2) should almost never be used.  It does what
> >stat(2) does except it uses the REAL userid and not the EFFECTIVE
> >userid like every other system call uses.  It is designed for use
> >by setuid/setgid programs to verify the permissions of the
> >"underlying" user.
> 
> I also feel that access() should almost never be used, but for
> quite different reasons.
> 
> First (and I think you realized it) you're not using access()
> for what it was intended.  
>
> [lots more comments deleted]

     I guess I gave an unclear posting.  *I* know how access(2)
works and how to do the permissions checking in the right way.  A
version of access (I call it accfile) does the same kind of check-
ing but with the "proper" uid/gid.

     My lament is that *other* software (/bin/sh, test(1), temp-
nam(3), the Informix sacego report processor, etc.) does it wrong
and it keeps me from doing it right.  For example, the shell's
$PATH search mechanism means that I have to keep the project bin/
directory open to everybody because the shell won't find my com-
mands otherwise.

     I have just found out that mkdir(1) on System V doesn't work
right either.  It runs setuid root (only root may mknod a direc-
tory) and it uses access to find out if the underlying user has
permission to do this.  I guess they miss the case where the ef-
fective group has permission but the real+effective user and real
group do not.  Yet another case of the kernel doing what I tell
it rather than what I want.

     Wouldn't it make sense to (A) provide a "accfile()"
syscall/routine that does access(2) with real ids and (B) put a
note on the access manual page saying "you probably don't want to
use this function." Perhaps provide a version of access that is
passed the user/group ids to be checking against?  Then it could
fit all the needs.

     Steve
-- 
Life : Stephen J. Friedl @ V-Systems, Inc./Santa Ana, CA   *Hi Mom*
CSNet: friedl%vsi.uucp@kent.edu  ARPA: friedl%vsi.uucp@uunet.uu.net
uucp : {kentvax, uunet, attmail, ihnp4!amdcad!uport}!vsi!friedl

terry@wsccs.UUCP (terry) (03/12/88)

In article <70@vsi.UUCP>, friedl@vsi.UUCP (Stephen J. Friedl) writes:
>      I guess I gave an unclear posting.  *I* know how access(2)
> works and how to do the permissions checking in the right way.  A
> version of access (I call it accfile) does the same kind of check-
> ing but with the "proper" uid/gid.
> 
>      My lament is that *other* software (/bin/sh, test(1), temp-
> nam(3), the Informix sacego report processor, etc.) does it wrong
> and it keeps me from doing it right.  For example, the shell's
> $PATH search mechanism means that I have to keep the project bin/
> directory open to everybody because the shell won't find my com-
> mands otherwise.

	Obviously, you have not heard of the link function, which allows you
to link a file to another file.  For instance:

	login: root
	# mkdir /rbin
	# ln /rbin/test /bin/test
	# ln /rbin/sh /bin/sh

	login: dwiddly
	$ PATH=/rbin:.:/usr/rbin	(set by .profile, not owned by me)
	$ mkdir foo
	mkdir: command not found

>      I have just found out that mkdir(1) on System V doesn't work
> right either.  It runs setuid root (only root may mknod a direc-
> tory) and it uses access to find out if the underlying user has
> permission to do this.  I guess they miss the case where the ef-
> fective group has permission but the real+effective user and real
> group do not.  Yet another case of the kernel doing what I tell
> it rather than what I want.

	No, it does what it's supposed to.  I will assume that your effective
user an group ID are caused by a C program.  If you want to defeat it, however,
you could simply doo the following:

	instead of
		mkdir( "/bin/foo");
	or
		system( "/bin/mkdir /bin/foo");
	use
		system( "/bin/sh -c /bin/mkdir /bin/foo");

	This will cause the mkdir to see the system()'ed shell's real UID and
GID, which will be whatever your effective UID and GID were, thus getting
around a security feature of UNIX.  Note that I forced the path on the mkdir
command so the user could not have his own mkdir in his path before the /bin
one, thereby preventing:

	$ cat mkdir
	:
	# shell script to fool root
	echo "me::0:1:Fake root account:/:/bin/sh" >> /etc/passwd
	mkdir $1
	$

>      Wouldn't it make sense to (A) provide a "accfile()"
> syscall/routine that does access(2) with real ids and (B) put a
> note on the access manual page saying "you probably don't want to
> use this function." Perhaps provide a version of access that is
> passed the user/group ids to be checking against?  Then it could
> fit all the needs.

	Or you could use the method above... gee, now why should you complicate
the library more again?


| Terry Lambert           UUCP: ...!decvax!utah-cs!century!terry              |
| @ Century Software       or : ...utah-cs!uplherc!sp7040!obie!wsccs!terry    |
| SLC, Utah                                                                   |
|                   These opinions are not my companies, but if you find them |
|                   useful, send a $20.00 donation to Brisbane Australia...   |
| 'There are monkey boys in the facility.  Do not be alarmed; you are secure' |

friedl@vsi.UUCP (Stephen J. Friedl) (03/15/88)

In article <305@wsccs.UUCP>, terry@wsccs.UUCP (terry) writes:
> Obviously, you have not heard of the link function,
> which allows you to link a file to another file.

Saying thinks like "obviously you have not heard of xxx" only
irritates people, especially when they have indeed heard of it as
I have.  Surely you can find a more constructive/pleasant way of
offering your $.02.

> > (I write):
> >      I have just found out that mkdir(1) on System V doesn't work
> > right either.  It runs setuid root (only root may mknod a direc-
> > tory) and it uses access to find out if the underlying user has
> > permission to do this.  I guess they miss the case where the ef-
> > fective group has permission but the real+effective user and real
> > group do not.
> 
> 	No, it does what it's supposed to.

No, it doesn't.  If I have the following directories:

   3 drwxr-x---   4 acct  acct   1234 Feb 10 12:24 /usr/acct/
  20 drwxrwx---   1 acct  acct  10000 Feb 10 13:55 /usr/acct/datadir/
   5 drwxr-x---   4 acct  acct   2352 Feb 10 13:55 /usr/acct/bin/
  20 -rwx--x---   1 acct  acct  10000 Feb 10 13:55 /usr/acct/bin/report

Now, I have a front-end (say, "runacct") that makes me:

	uid  = friedl 
	euid = friedl
	gid  = staff
	egid = acct   <---- setgid!

This program calls up a menu and runs the entire system with an
egid of "acct".  If my $PATH includes /usr/acct/bin and a script
(probably also run from /usr/acct/bin) with the line

	report 1/88

the shell will not run my command, but

	/usr/acct/bin/report 1/88

works fine.  In the first case, the exec(2) will work -- I *do*
have permission to run the program.  The difficulty is because
the shell probably uses access(2) to see if /usr/acct/bin/report
is executable -- this is simply incorrect in a setuid/setgid
environment.

Mkdir is broken as well.  If I have a script -- running in the
same directory structure as above with the same permissions,
should:

	mkdir /usr/acct/datadir/disk.01

make the directory?  I say yes, mkdir(1) says no.  This probably
works in SVR3 (and 4.3BSD?) because mkdir(2) magically appeared
augmenting mknod(2).

> system( "/bin/sh -c /bin/mkdir /bin/foo");
> 
> [...]  Note that I forced the path on the mkdir
> command so the user could not have his own mkdir in his
> path before the /bin one, thereby preventing [...].
> 
"Obviously" you have not heard of the $IFS fraud :-).

I contend that access(2) is improperly used in the overwhelming
majority of cases.  If you want to find out if the current user
has permission to access a file, stat(2) or open(2) it, but don't
use access(2).  If you (generic programmer "you") use access but
don't understand the objections to it I think there is a good
chance that you don't fully understand access either.

> >      Wouldn't it make sense to (A) provide a "accfile()"
> > syscall/routine that does access(2) with real ids...
> 
> 	Or you could use the method above... gee, now why should
> you complicate the library more again?

OK, I blew it in this paragraph.  I wanted to say that accfile()
should use the EFFECTIVE uid/gid rather than the REAL uid/gid
as I so incorrectly said.  With that change, the rest of the
posting stands and I want accfile() very much.

Anybody else think I blew it on the entire posting?

-- 
Steve Friedl, KA8CMY     ARPA/UUNET/CSNet: friedl@vsi.com      *Hi Mom*
uucp email : { kentvax, uunet, attmail, ihnp4!amdcad!uport }!vsi!friedl
"Too bad we judge others by their actions and ourselves by our motives"

douglas@dcc1.UUCP (Douglas B. Jones) (03/17/88)

There has been some talk about the access(2) only working on the real
uid/gid pair. Two alternate possibilites:

1) have a saccess(2) which will check against setuid/setgid. If they fail,
   then it will check against realuid/realgid. OR, maybe it will just check
   against the setuid/setgid.

2) have another routine, call it faccess(2), which will have the call:

	ret = faccess(file_path,uid,gid);

   so you can check against the uid and gid pair. You could also set uid
   or gid to -1, and it would not check for that type.

	ret = faccess(file_path,uid,-1);	/* don't check for gid */

	ret = faccess(file_path,-1,gid);	/* don't check for uid */

	ret = faccess(file_path,uid,gid);	/* check for both */

   I'm not familiar with NFS, but I seem to remember something about some
   id having -1 as the uid (and/or maybe gid) number. If this is the case,
   some other number might have to be picked; say -9999 or -MAXINT.

-- 
Douglas B. Jones
DeKalb College / 555 N. Indian Creek Drive
Clarkston, Ga. 30021 / (404) 299-4233
{cbosgd,hplabs,ihnp4,seismo,ulyses}!gatech!dcc1!douglas or douglas@dcc1

chris@mimsy.UUCP (Chris Torek) (03/17/88)

In article <311@dcc1.UUCP> douglas@dcc1.UUCP (Douglas B. Jones) writes:
>There has been some talk about the access(2) only working on the real
>uid/gid pair. Two alternate possibilites:
>
>1) have a saccess(2) which will check against setuid/setgid ....
>2) have another routine, call it faccess(2) ...
>
>	ret = faccess(file_path,uid,gid);

The whole concept of an `access' system call is a bit goofy, because
it does not account for external events.  Consider, e.g.,

time	/* prog1 */			time	/* prog2 */
t=0	compute();			t=1	status = access(path,...);
t=2	mv(path, newname);		t=3	if (status == OK)
							operation(path);

prog2 has carefully verified the operation before performing it, yet
it goes awry anyway.  Since access() exists for `security' purposes,
but does not fulfill them, it should be reconsidered and probably
removed entirely.

Now, if you want a 99% solution for non-secure programs, that is
another matter entirely....  In most cases it is best to attempt the
operation anyway, and see whether it worked, but a 99% `test this out
now' call could be useful.
-- 
In-Real-Life: Chris Torek, Univ of MD Comp Sci Dept (+1 301 454 7163)
Domain:	chris@mimsy.umd.edu	Path:	uunet!mimsy!chris

terry@wsccs.UUCP (terry) (03/24/88)

Steven, the access() function is supposed to check using the real user and
group ID's.  This makes it do what it is documented as doing, ie: finding
out if you have access, NOT if who you are effectively has access.

In article <305@wsccs.UUCP>, I write:
> 
> 	No, it does what it's supposed to.

In article <393@vsi.UUCP>, you reply:
> 
> No, it doesn't.  If I have the following directories:
> 
>    3 drwxr-x---   4 acct  acct   1234 Feb 10 12:24 /usr/acct/
>   20 drwxrwx---   1 acct  acct  10000 Feb 10 13:55 /usr/acct/datadir/
>    5 drwxr-x---   4 acct  acct   2352 Feb 10 13:55 /usr/acct/bin/
>   20 -rwx--x---   1 acct  acct  10000 Feb 10 13:55 /usr/acct/bin/report
> 
> Now, I have a front-end (say, "runacct") that makes me:
> 
> 	uid  = friedl 
> 	euid = friedl
> 	gid  = staff
> 	egid = acct   <---- setgid!
> 
> This program calls up a menu and runs the entire system with an
> egid of "acct".  If my $PATH includes /usr/acct/bin and a script
> (probably also run from /usr/acct/bin) with the line
> 
> 	report 1/88
> 
> the shell will not run my command, but
> 
> 	/usr/acct/bin/report 1/88
> 
> works fine.  In the first case, the exec(2) will work -- I *do*
> have permission to run the program.

The process by which an exec() works is exactly that by which my example works;
your euid and egid become your uid and gid.

> The difficulty is because the shell probably uses access(2) to see if
> /usr/acct/bin/report is executable

It does.  Isn't that what it's supposed to do?

> -- this is simply incorrect in a setuid/setgid environment.

How so?  It prevents you from making a costly mistake even more costly.  If you
have a hole in a program you write, access() not operating in the fashion you
have suggested it "should" operate would act to minimize any damage by
restricting what it was possible to bash and what it was possible to bash it
with.  I don't admit an IFS problem with my method.  There are ways to avoid it,
most notably with "putenv()", which is available on a lot of systems.

> Mkdir is broken as well.  If I have a script -- running in the
> same directory structure as above with the same permissions,
> should:
> 
> 	mkdir /usr/acct/datadir/disk.01
> 
> make the directory?  I say yes, mkdir(1) says no.

If you are talking a shell script, the reason I believe it works in Berklix is
that Berklix runs another shell in order to interpret shell scripts... SysV.3
does not (at least on the systems I work on).  This has resulted in a number
of technical support calls as people installed older versions of our software
on their new SysV.3 ...it seems we used to use "exec" to avoid running an
additional process.  The shell scripts break, as exec is not allowed from
within a shell script (I can document the boxes this is true on).  The one
exception would be a user running a shell other than sh which forced the use
of the Bourne Shell (a ':' as the first character in the file).

> > system( "/bin/sh -c /bin/mkdir /bin/foo");
> > 
> > [...]  Note that I forced the path on the mkdir
> > command so the user could not have his own mkdir in his
> > path before the /bin one, thereby preventing [...].
> > 
> "Obviously" you have not heard of the $IFS fraud :-).

I have.  It's non-applicable.  I seem to remember the smell of roasting ME
last time I used the word "Obviously".

> Anybody else think I blew it on the entire posting?

I didn't flame your entire posting.  I could have nit-picked.  As you pointed
out in your return salvo, you were using access incorrectly.

The reason it is REAL uid/gid is to allow you to run suid/sgid programs which
allow you access to functions based on who you really are when the functions
themselves are normally priveledged.  This is useful if you are writing system
software... for instance, if mknod() had to be done by root, as the only user
capable of modifying a file system, as is the case in a number of recent UNIX
implimentations.  Your "mkdir" command would have to be SUID root, but still be
able to tell who actually ran it.

I think the primary use would be in a systems-software situation, not a user
software-that-needs-access.  I agree that if there was a great deal of demand
for determination of access for euid programs, it would be a good idea to
impliment another function ...I think eaccess() would be a better name, tho.


| Terry Lambert           UUCP: ...{ decvax, ihnp4 }                          |
| @ Century Software          : ...utah-cs!uplherc!sp7040!obie!wsccs!terry    |
| SLC, Utah                                                                   |
|                   These opinions are not my companies, but if you find them |
|                   useful, send a $20.00 donation to Brisbane Australia...   |
| 'There are monkey boys in the facility.  Do not be alarmed; you are secure' |

friedl@vsi.UUCP (Stephen J. Friedl) (04/09/88)

In article <7591@ncoast.UUCP>, allbery@ncoast.UUCP (Brandon Allbery) writes:
< As quoted from <368@wsccs.UUCP> by terry@wsccs.UUCP (terry):
< | I write:
< | > The difficulty is because the shell probably uses access(2) to see if
< | > /usr/acct/bin/report is executable
< | 
< | It does.  Isn't that what it's supposed to do?
< 
< sh uses access()?  Since the real and effective u/gids are not
< affected by an exec(), access() is the *wrong* function to use.

SVR2 and SVR3 shells do indeed use access(2) incorrectly. MORAL:
If you just want to know if a file exists, please use stat(),
not access(2).
-- 
Steve Friedl   V-Systems, Inc.   "Yes, I'm jeff@unh's brother"
friedl@vsi.com  {backbones}!vsi.com!friedl  attmail!vsi!friedl