security problem with large uids and gids

hedrick at geneva.rutgers.edu hedrick at geneva.rutgers.edu
Fri Mar 31 11:06:42 AEST 1989


[[ This has been reported to sunbugs.  --wnl ]]

The problem is that setuid(getuid()) and setgid(getgid()) do not work for
large uids and gids, i.e. 32K and larger.  In 4.3, the uid and gid in
<user.h> are declared unsigned short.  Thus no sign-extension problems
occur.  In SunOS, they are declared signed short.  getuid and getgid
sign-extend the returned value.  Unfortunately, setuid and setgid
(actually setreuid and setregid) contain explicit checks that reject
arguments with non-zero left half.  Thus setuid won't accept the value
returned by getuid, etc.  Note that you can't just do setuid(getuid() &
0xffff); After verifying that the left half is zero, setuid then checks to
see whether the value matches either the real or effective uid.  It
sign-extends the current values. So if you set the left half to zero, you
pass the explicit left-half check and then fail the comparision.  No
possible value will pass both checks.

Unfortunately, setuid(getuid()) is used by many setuid programs before
doing something like sprouting a shell.  It is intended to put things back
to an unprivileged state.  Because there's no way this can fail, it's
unusual for programs to check the value returned by setuid.  To the net
effect is that a setuid program is likely to sprout a root shell for users
whose uid's are 32K and larger.  We actually ran into the problem with
mail, where we got a shell whose gid was mail instead of the user's own
gid.  (We run mail setgid to mail, and do setgid(getgid()) in appropriate
places.)  I haven't examined the system to see exactly where the resulting
holes are.  It is even possible that no standard part of SunOS 4.0 relies
on that code (though I'd be very surprised).  But it's still a potentially
serious security problem.  Unfortunately the only fixes I can think of are

  - fix the kernel
  - make sure you don't have any uid's or gid's >= 32K

So non-source sites with lots of users may be in big trouble.  (We use
large gid's because our gid's have meaning to our accounting system.  We
don't really have 32K of them.  We just need all 16 bits to encode all the
things we want to encode.  We do have uid's >= 32K because of the way we
allocate uid's.  Because of NFS, we give users the same uid on all
systems.  AT one point we did this by assigning each department a range of
uids they could assign.  We assigned the whole 64K address space.  We now
have a better way of assigning uid's, but we are stuck with uid's > 32K.)

I believe SunOS 3.2 is OK.  setre[ug]id uses code much closer to 4.3.  It
still sign-extends the uid and gid, but it does so consistently.



More information about the Comp.sys.sun mailing list