🚀 go-pugleaf

RetroBBS NetNews Server

Inspired by RockSolid Light RIP Retro Guy

4 total messages Started by Stephen J. Friedl Mon, 04 Jun 1990 05:24
Bug in tempnam(3) function
#166
Author: Stephen J. Friedl
Date: Mon, 04 Jun 1990 05:24
34 lines
1677 bytes
Once again we find another library function that uses access(2)
in the wrong way.  Tempnam(3), called with

	char *tempnam(dir, pfx)
	char	*dir, *pfx;

makes a temp file name in the mentioned directory with the given
prefix and returns it.  If the directory suggested by the user is
not available, /tmp is used as a last resort (although I have
seen /usr/tmp used too).

Imagine writing an lp spooler and the "lp" command takes stdin.
The program might do something like:

	fname = tempname("/usr/lp/temp", "d-");

assuming that the filename will be built in the suggested place.
If the lp command is setgid lp *and* the underlying user cannot
write to /usr/lp/temp (but presumably the lp gid can), the file
will get stuck in /tmp or /usr/tmp.  Now reboot your machine and
watch your print request disappear.

Please, everybody, if you think that access is a handy does-the-
file-exist function you are very wrong, and it's a safe bet that
it does not belong.  Email will get a pretty detailed note on why
access(2) is evil.

     Steve

-- 
Stephen J. Friedl, KA8CMY / Software Consultant / Tustin, CA / 3B2-kind-of-guy
+1 714 544 6561  / friedl@mtndew.Tustin.CA.US  / {uunet,attmail}!mtndew!friedl

"I will defend to your death my right to my opinion" - me
Re: Bug in tempnam(3) function
#167
Author: Brian Matthews
Date: Wed, 06 Jun 1990 03:05
14 lines
1085 bytes
In article <433@mtndew.UUCP> friedl@mtndew.UUCP (Stephen J. Friedl) writes:
|Email will get a pretty detailed note on why
|access(2) is evil.

I wouldn't go that far.  Access(2) is quite necessary for certain things.
Unfortunately, it could probably have a better name, and the manual page
(at least all the ones I've seen) doesn't do a great job of indicating
when it should and shouldn't be used, so lots of people (evidently
including whoever wrote tempnam(3) :-)) misuse it.  This doesn't mean
that access(2) is evil though.

Remember: Access(2) doesn't kill people, people kill people :-)
-- 
Brian L. Matthews	blm@6sceng.UUCP
Re: Bug in tempnam(3) function
#168
Author: Don Lewis
Date: Thu, 07 Jun 1990 03:39
37 lines
2449 bytes
In article <2077@polari.UUCP> 6sigma2@polari.UUCP (Brian Matthews) writes:
>In article <433@mtndew.UUCP> friedl@mtndew.UUCP (Stephen J. Friedl) writes:
>|Email will get a pretty detailed note on why
>|access(2) is evil.

Would using stat(2), and checking if the uids/gids match and looking
at the permission bits have been better?  Should the effective or
real ids have be used?

>
>I wouldn't go that far.  Access(2) is quite necessary for certain things.
>Unfortunately, it could probably have a better name, and the manual page
>(at least all the ones I've seen) doesn't do a great job of indicating
>when it should and shouldn't be used, so lots of people (evidently
>including whoever wrote tempnam(3) :-)) misuse it.  This doesn't mean
>that access(2) is evil though.
>

I agree that access(2) is very useful.  I have seen a lot of objections
to its use in programs because of what how it interacts with set[ug]id'ness,
but all the examples I have seen have are not (and have no business
being) set[ug]id.  Even if a program is set[ug]id, I believe that
access(2) is still very useful, because it returns the file accessability
for the actual user running the program (assuming the program doesn't
fiddle with the real [ug]id).  For example, if a setuid root program
which uses access(2) to check for valid write access to a file before
fopen()ing it for writing will not overwrite any files that the user
does not actually have write permission for.

Using access(2) propery in a set[ug]id situation is a bit tricky, and
should be better documented.  Any library routines that use access(2)
or other validation methods should be documented as to exactly how they
behave.  The proper validation method depends on the circumstances.
--
Don "Truck" Lewis                      Harris Semiconductor
Internet:  del@mlb.semi.harris.com     PO Box 883   MS 62A-028
Phone:     (407) 729-5205              Melbourne, FL  32901
Alternative to access() (was: Bug in tempnam(3) function)
#169
Author: Kim F. Storm
Date: Tue, 12 Jun 1990 16:58
143 lines
4227 bytes
In article <2077@polari.UUCP> 6sigma2@polari.UUCP (Brian Matthews) writes:
>In article <433@mtndew.UUCP> friedl@mtndew.UUCP (Stephen J. Friedl) writes:
>|Email will get a pretty detailed note on why
>|access(2) is evil.

del@thrush.mlb.semi.harris.com (Don Lewis) writes:
> Would using stat(2), and checking if the uids/gids match and looking
> at the permission bits have been better?  Should the effective or
> real ids have be used?

Here is the "file_exist()" function which I wrote to make all sorts
of file checking easy.  It is extracted from the nn distribution, so
it may need a little hacking to be used out of context:


/*
 *	(c) Copyright 1990, Kim Fabricius Storm.  All rights reserved.
 */

#include <errno.h>
#include <sys/types.h>
#include <sys/stat.h>


#ifdef HAVE_MULTIGROUP
#ifndef NGROUPS
#include <sys/param.h>
#endif
#ifndef GIDSET_TYPE
#define GIDSET_TYPE int
#endif
static int ngroups;
static GIDSET_TYPE gidset[NGROUPS];

static in_grplist(gid)
GIDSET_TYPE gid;
{
    int n;

    for (n = 0; n < ngroups; ++n)
	if (gidset[n] == gid) return 1;

    return 0;
}

#define group_access(gpid)	in_grplist((GIDSET_TYPE)(gpid))
#else
#define group_access(gid)	((gid) == group_id)
#endif


/*
 *	Test existence and access modes of a file or directory
 *
 *	mode is a string composed of the following characters
 *		f -- name is a file
 *		d -- name is a directory
 *		r -- name is readable
 *		w -- name is writeable
 *		x -- name is executeable/searchable
 *
 *	0 is returned if file does not exist or any of the requested
 *	permissions are not present; the actual cause is returned in
 *	errno (EACCESS, EISDIR, ENOTDIR).  
 *	Otherwise, the modification time of the file is returned.
 *
 *	Examples:
 *	file_exist("/usr", "dwr") 
 *		-- is /usr a directory, writeable AND readable?
 *
 *	file_exist(file, "fx")
 *		-- is file an executeable file?
 *
 *	file_exist(file, (char *)NULL)
 *		-- does file exist?
 */

time_t file_exist(name, mode)
char *name;
char *mode;
{
    static unsigned short user_id, group_id;
    static init = 1;
    struct stat statb;
    extern int errno;

    if (init) {
	user_id = geteuid();

#ifdef HAVE_MULTIGROUP
	ngroups = getgroups(NGROUPS, gidset);	/* Get users's group set */
	group_id = gidset[0];	/* not used, but just in case... */
#else
	group_id = getegid();
#endif
	init = 0;
    }
    if (stat(name, &statb)) return 0;

    if (mode == NULL) return statb.st_mtime;

    while (*mode) {
	switch (*mode++) {
	case 'd':
	    if ((statb.st_mode & S_IFMT) == S_IFDIR) continue;
	    errno = ENOTDIR;
	    return 0;
	case 'f':
	    if ((statb.st_mode & S_IFMT) == S_IFREG) continue;
	    if ((statb.st_mode & S_IFMT) == 0000000) continue;
	    if ((statb.st_mode & S_IFMT) == S_IFDIR) {
		errno = EISDIR;
		return 0;
	    }
	    break;
	case 'r':
	    if ((statb.st_mode & 0400) && statb.st_uid == user_id) continue;
	    if ((statb.st_mode & 0040) && group_access(statb.st_gid)) continue;
    	    if ((statb.st_mode & 0004)) continue;
	    break;
	case 'w':
	    if ((statb.st_mode & 0200) && statb.st_uid == user_id) continue;
	    if ((statb.st_mode & 0020) && group_access(statb.st_gid)) continue;
    	    if ((statb.st_mode & 0002)) continue;
	    break;
	case 'x':
	    if ((statb.st_mode & 0100) && statb.st_uid == user_id) continue;
	    if ((statb.st_mode & 0010) && group_access(statb.st_gid)) continue;
    	    if ((statb.st_mode & 0001)) continue;
	    break;
	}
	errno = EACCES;
	return 0;
    }

    /* all modes are ok */
    return statb.st_mtime;
}

-- 
Kim F. Storm  <storm@texas.dk>		No news is good news,
Texas Instruments A/S, Denmark		  but nn is better!
Thread Navigation

This is a paginated view of messages in the thread with full content displayed inline.

Messages are displayed in chronological order, with the original post highlighted in green.

Use pagination controls to navigate through all messages in large threads.

Back to All Threads