access() and security

Chris Torek chris at mimsy.UUCP
Wed Apr 27 10:27:32 AEST 1988


In article <13113 at brl-adm.ARPA> mouse at larry.mcrcim.mcgill.edu (der Mouse)
writes:
>What we need, it seems, is a way to say "I wish to restrict myself to
>the real user's access privileges" for a time, with the potential to
>revert back to the previous state.  4.3's setreuid() appears to be
>exactly this

It does.

>though I seem to recall that if the real uid is 0, the process has
>superuser access even if the effective uid is not 0 ...

Not so.

The proper way to test the validity of operation X `before' doing
operation X is to write:

	uid_t ruid, euid; gid_t rgid, egid;
	ruid = getuid(), euid = geteuid(); /* there should be getreuid */
	rgid = getgid(), egid = getegid(); /* and getregid interfaces. */
	...

	int
	do_restricted_operation(op, arg)
		int (*op)();
		caddr_t arg;
	{
		int result, saverr;

		/* this should never fail */
		if (setregid(egid, rgid) || setreuid(euid, ruid))
			panic("setre?id 1");
		result = (*op)(arg);
		/* note that successful syscalls are allowed to alter errno */
		saverr = errno;
		if (setregid(rgid, egid) || setreuid(ruid, euid))
			panic("setre?id 2");
		errno = saverr;
		return (result);
	}

In practise, one would just do the desired operation directly.
To use this particular encapsulation correctly, one must write,
for instance,

	struct open_context {
		char	*path;
		int	flags;
		int	mode;
	};

	int
	do_open(arg)
		caddr_t arg;
	{
		struct open_context *c = (struct open_context *)arg;

		return (open(c->path, c->flags, c->mode));
	}
	...
		struct open_context c;
		int fd;

		c.path = "/some/file/name";
		c.flags = O_CREAT|O_RDWR|O_EXCL;
		c.mode = 0600;
		fd = do_restricted_operation(do_open, (caddr_t)&c);

This is quite a bother; it would be nice if C had a `package
up some arguments into a generic argument blob' operation and
an `expand generic argument blob into real arguments' operation,
so that one could write instead

		fd = do_restricted_operation(open,
			[["/some/file/name", O_CREAT|O_RDWR|O_EXCL, 0600]]);

and inside do_restricted_operation itself,

		result = (*op)(<< arg);

(presuming that [[...]] is the argument-builder and unary << is the
argument exploder).  An equivalent if less compact representation
would be unnamed functions (a C version of lambda :-) ) and aggregates:

		fd = do_restricted_operation(
			int (void *arg) {
				struct open_context *c = arg;
				return (open(c->path, c->flags, c->mode));
			},
			(void *) &(struct open_context) {
				"/some/file/name", O_CREAT|O_RDWR|O_EXCL, 0600
			});

which requires no exploder operation.
-- 
In-Real-Life: Chris Torek, Univ of MD Comp Sci Dept (+1 301 454 7163)
Domain:	chris at mimsy.umd.edu	Path:	uunet!mimsy!chris



More information about the Comp.unix.wizards mailing list