[net.emacs] setuid/setgid programs & Emacs

chris.umcp-cs@UDel-Relay (04/08/83)

From:  Chris Torek <chris.umcp-cs@UDel-Relay>

Emacs does not work correctly with setuid and setgid programs.
Specifically, if a setuid or setgid program runs Emacs, and the
Emacs user tries to read or write a file that is readable or writable
by the setuid user (or setgid group), Emacs thinks that it cannot
access the file, when, in fact, it can.  This is because it uses
the "access" system call, which is designed for programs that want
to check the real user's permissions (i.e. setuid programs).

This came up here when we wrote a setgid shell script to edit a
file with locking, ala vipw.  We took write permission off except
for owner and group, and made a special group for the file and
shell script.  Running the shell script brings up your favorite
editor on the file.  Vi complains that the file is read-only, but
given a ":w!" command writes the file.  Emacs refused to write
the file at all.

Here is a new version of access(), as user-level code, which checks
permissions based on the effective user/group IDs.

access.c:
/* User-mode version of access system call with one change: checks for
   effective user/group ID permission */

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

extern errno;

access (name, mode)
char *name;
register mode;
{
	struct stat st;
	register uid, m;

	if (stat (name, &st))
		return -1;	/* File does not exist */
	uid = geteuid ();

	if (uid == 0 || mode == 0)
		return 0;	/* su, or just checking existence */
	m = 0;
	if (mode & 1)
		m |= S_IEXEC;
	if (mode & 2)
		m |= S_IWRITE;
	if (mode & 4)
		m |= S_IREAD;
	if (st.st_uid != uid) {
		m >>= 3;
		if (st.st_gid != getegid ())
			m >>= 3;
	}
	if ((st.st_mode & m) != m) {
		errno = EACCES;
		return -1;
	}
	return 0;
}