[net.bugs.4bsd] 4.1a setgid file access problems

madden (04/25/83)

As distributed in December, `82, 4.1a BSD alters the behavior of setgid
programs by making it impossible for them to use setgid(getgid()) to
forego any special file access privileges that they may have acquired
from being setgid.  This happens because, when such a program is
exec'ed, the bit corresponding to the effective gid is set in the group
mask (u.u_grps) of the process.  Unfortunately, when a setgid is
performed, the appropriate bit cannot be reset since there is no way to
know whether it was set because of the privileges of the user or
because the code file was setgid.

Since setgid programs have been useful here in the creation of code
with limited special privileges and since the new 4.1a code causes the
undesirable effect that those privileges are passed on to offspring,
I've applied the attached change to the system here.

The patch operates by removing the code in exec which sets the bit in
u.u_grps for the setgid group.  Instead, it provides setgid access by
adding to 'access' the old 4.1 code which checks for a match between
the target file's gid and the effective gid of the calling process.
Although this approach may be slightly less clean than the distributed
4.1a code, it allows setgid to work in the old, more reasonable,
manner.
			Jim Madden
			sdcsvax!madden

The changes:



------- sys1.c -------
***************
*** 379,384
  		u.u_uid = uid;
  		u.u_procp->p_uid = uid;
  		u.u_gid = gid;
  		if (gid < NGRPS)
  			u.u_grps[gid / (sizeof (int) * 8)] |=
  				1 << (gid % (sizeof (int) * 8));

--- 379,385 -----
  		u.u_uid = uid;
  		u.u_procp->p_uid = uid;
  		u.u_gid = gid;
+ #ifndef OLD_SETGID
  		if (gid < NGRPS)
  			u.u_grps[gid / (sizeof (int) * 8)] |=
  				1 << (gid % (sizeof (int) * 8));
***************
*** 382,387
  		if (gid < NGRPS)
  			u.u_grps[gid / (sizeof (int) * 8)] |=
  				1 << (gid % (sizeof (int) * 8));
  	} else
  		psignal(u.u_procp, SIGTRAP);
  	u.u_tsize = ts;

--- 383,389 -----
  		if (gid < NGRPS)
  			u.u_grps[gid / (sizeof (int) * 8)] |=
  				1 << (gid % (sizeof (int) * 8));
+ #endif
  	} else
  		psignal(u.u_procp, SIGTRAP);
  	u.u_tsize = ts;

------- fio.c -------
***************
*** 190,195
   	if(u.u_uid != ip->i_uid) {
  #endif
  		m >>= 3;
  		if (ip->i_gid >= NGRPS ||
  		    ((u.u_grps[ip->i_gid / (sizeof (int)*8)] &
  		     (1 << ip->i_gid % (sizeof (int)*8))) == 0))

--- 190,200 -----
   	if(u.u_uid != ip->i_uid) {
  #endif
  		m >>= 3;
+ #ifdef OLD_SETGID
+ 		if (ip->i_gid != u.u_gid && (ip->i_gid >= NGRPS ||
+ 		    ((u.u_grps[ip->i_gid / (sizeof (int)*8)] &
+ 		     (1 << ip->i_gid % (sizeof (int)*8))) == 0)))
+ #else
  		if (ip->i_gid >= NGRPS ||
  		    ((u.u_grps[ip->i_gid / (sizeof (int)*8)] &
  		     (1 << ip->i_gid % (sizeof (int)*8))) == 0))
***************
*** 193,198
  		if (ip->i_gid >= NGRPS ||
  		    ((u.u_grps[ip->i_gid / (sizeof (int)*8)] &
  		     (1 << ip->i_gid % (sizeof (int)*8))) == 0))
  			m >>= 3;
  	}
  	if ((ip->i_mode&m) != 0)

--- 198,204 -----
  		if (ip->i_gid >= NGRPS ||
  		    ((u.u_grps[ip->i_gid / (sizeof (int)*8)] &
  		     (1 << ip->i_gid % (sizeof (int)*8))) == 0))
+ #endif
  			m >>= 3;
  	}
  	if ((ip->i_mode&m) != 0)