S[UG]ID files and [sg]et[re][ug]id() system calls

utzoo!decvax!ucbvax!unix-wizards utzoo!decvax!ucbvax!unix-wizards
Fri Oct 16 01:11:29 AEST 1981


>From decvax!ittvax!swatt at Berkeley Thu Oct 15 21:56:23 1981

	
	From decvax!ucbvax!MBM at MIT-XX Wed Oct 14 07:30:53 1981
	Date: 13 Oct 1981 2214-EDT
	From: MBM at MIT-XX
	Subject: Re: S[UG]ID files and s[re][ug]id() system calls
	To: decvax!ittvax!swatt at UCB-C70
	In-Reply-To: Your message of 8-Oct-81 2028-EDT
	
	When you say " we made the user - group relationship a hierarchy rather
	than an overlay" does that mean you could have the same uid representing
	2 different usrs in 2 different groups?  This would seem to require a 32
	bit number to uniquely identify a user...
	I was also thinking of having a hierarchy of groups , so that perhaps
	lower group numbers became more and more powerful, srt of like multics
	rings ... is that what you meant?
	--a little confused
	-------
[ This was originally a simple mail response to the above query, but
  the completed length of it is in excess of what I have been able to
  get through the ARPA gateway as mail, so I am sending it out as
  news.
]

Sorry for the confusion; I'll try to make this description complete.
The normal UNIX notion is that a process has both a "user id" and an
unrelated "group id" at the same time.  Each file has "userid" and
"groupid" attributes which are set to the effective user and group ID's
of the process which creates the file.  Each file also has three sets
of access permissions:  one for "owner", one for "group", and one for
"other".  The superuser is userid 0, and always has permission to do
anything.  Checks on file permissions are done by the following
method:

	IF caller's userid == 0 THEN
		return OK
	ENDIF
	IF caller's userid == file's userid THEN
		check "owner" permissions
	ELSEIF caller's groupid == file's groupid THEN
		check "group" permissions
	ELSE check "other" permissions
	ENDIF

In old V6 UNIX the ID information was kept in a byte; V7 uses 16-bit
words.  The painful issue was not the kernel structures to keep track
of process permissions, but the disk space for the inodes to record
file ownership.  Under V6 UNIX filesystems and the standard permission
checking, you could only have 256 unique users and 255 unique groups.
What we wanted was a way to have more unique users without restructuring
the disk filesystem.

When I said the user - group relationship became a hierarchy I meant
that there were 256 groups, each one containing 256 users.  The two IDs
TOGETHER determined permissions, making a total of 65536 user ID's.
Thus if I were user #27 in group #100, I would share group permissions
with anyone else in group #100, but be considered as an "other" to
anyone in any other group.  Or, to draw a picture:

    grp #0            grp #1      ...    grp#254           grp#255
    / | \            / |    \            / |  \            / |   \
   /  |  \          /  |     \          /  |   \          /  |    \
 #0  #1...#255    #0  #1 ... #255     #0  #1 ...#255    #0  #1 ... #255
	
	
The SUPER-user (we called it the "ultrauser") would be user id #0 in
group #0.  Userid #0 in any other group would be the group superuser
for that group, but just an ordinary user in any other group.  There
was no multics-like ring system, except that we tended to make users
in the lower-numbered groups own the important system files.

[ We even had a special status group reserved for Nobel Lauriates,
  Dennis Ritchie and Ken Thompson, but sadly none of them ever
  requested an account ...
]

The new permission checking was done according to the scheme:

	IF caller's userid == 0 AND caller's groupid == 0 THEN
		return OK
	ENDIF
	IF file's groupid == caller's groupid THEN
		IF caller's userid == 0 THEN
			return OK
		ENDIF
		IF file's userid == caller's userid THEN
		  	check "owner" permissions
		ELSE
			check "group" permissions
		ENDIF
	ELSE
		check "other" permissions
	ENDIF

The "newgroup" command went away as a result of this, although we
did think of having a special user id "guest" in each group which
would sort of accomplish the same effect.

It was also necessary to change the treatment of S[UG]ID files
so that:

	SUID only files would be honored only for callers whose groupid
	was the same as the groupid of the file.

	SUID+SGID files would work always.

	SGID only files would be honored only for callers whose userid
	was the same as the userid of the file.  This last is sort of
	a strange special case.  It's only use was for system privileged
	programs which could be set to work ONLY for people who were
	already group superusers (a security feature of dubious value).

It was therefore possible for someone to write a program which would
bestow his permissions ONLY on members of the same group, which I
think does have real value.

However the main reason for the change was not to allow group
superusers, but to allow more than 256 unique user ID's.  There is
another scheme, which may have been adopted by Interactive Systems (I
am fairly sure it has been proposed by Peter S.  Langston) for their
PWB/PDP-11 systems, which involves using the top 5 or six bits of an ID
word as the groupid and the remaining bits as the userid.  This
method would allow more unique userid's without disturbing the
interpretation of the groupid (although allowing fewer groups).

Amazingly little had to be changed in the kernel or systems programs
to make all this work.  Very few programs really know how to determine
permissions; they use the "access" system call if they're privileged,
simply attempt the operation if they're not.  All the kernel permission
checking is concentrated in a few routines.

I have never known a UNIX installation to use the standard user-group
system in any truly useful way, so we didn't consider our changes as
giving up anything.  It seems clear to me that without some special
privileged user for each "group" its usefulness for project
organization is very limited.  I can "newgroup" to any group which
lists me as a member in the group file "/etc/group".  To change this
requires editing the file (it is only writable for "root").  There is
also a provision in this file to demand a password from anyone wishing
to "newgroup" to a group, but just who should have the right to set the
password is arguable.  Now the first problem could easily be solved by
writing a SUID program to edit the group file and allow normal users to
change the list of users permitted to join a group, but it is again
unclear to me just who should be allowed to use this program.
Effectively, to administer a group's account, you have to be root.

	- Alan S. Watt (decvax!ittvax!swatt)



More information about the Comp.unix.wizards mailing list