[Date Prev][Date Next] [Thread Prev][Thread Next] [Date Index] [Thread Index]

Re: setuid/setgid binaries contained in the Debian repository.



Hi,

On Mon, Aug 11, 2003 at 05:32:23PM -0400, Matt Zimmerman wrote:

> On Mon, Aug 11, 2003 at 10:30:24PM +0200, Emile van Bergen wrote:
> 
> > On Mon, Aug 11, 2003 at 04:14:36PM -0400, Matt Zimmerman wrote:
> > > allocated for every game.  And what have we gained?  The ability to share a
> > > file with other users.
> > 
> > No, a sandbox for every game. Every sandbox requires a uid. This is a
> > problem why?
> 
> Complexity.

Let me then ask this first. Do you want the game to run with the full
privileges of the user invoking it? If no, then you need a sandbox per
game in some form or another.

Using a different uid for a process is the simplest and strongest form
of sandbox imaginable. 

> > All other solutions require traversing the kernel. Now we traverse a
> > userspace wrapper. Is there any fundamental difference?
> 
> How does your proposed solution avoid the kernel?

It avoids having to put the one-way trapdoor feature in the kernel. 

[SNIP]

> I was talking about the current state of affairs in Debian, not about a
> hypothetical solution.  What I described is what we do _today_ in Debian
> (the problem).

Yes, and it seems you prefer to keep talking about the problem than
talking about solutions. I haven't heard any viable alternative from
you so far.

> > > I personally don't care one whit about impersonating high scores.
> > > I do care about the security of my system.
> > 
> > I do too. I don't trust game code. I don't want it to access my
> > $HOME at all. Have it use /var/games/<game>/$USER. My solution
> > allows that.
> 
> Moving data to /var/games is possible without setuid operation, as
> well, if it is desirable.

Sure, but moving is not an end in itself, but a means to and end, the
end being the ability to remove the need for access to the user's ~.

> > > And $LOGNAME.  And then make sure that none of the programs that
> > > you're wrapping will break, because they use getpwuid() or
> > > getlogin() or cuserid() or any other method which uses the uid.
> > 
> > Fine, they see the game user. This is bad why?
> 
> Because then the game doesn't work correctly.

Then you patch it. It only has to happen at one point; instead of
'getuid()' you need to use another bit of information ($UID or
something); the rest goes on as normal. 

Really, this is less complex than any client server solution, a
mandatory library, or taking advantage of some hot shot kernel feature.

> > > nethack, for example, uses the process uid in order to name its
> > > save files, and changing this would necessitate migration of
> > > existing games.  Of course, that needs to be done very carefully
> > > in order to avoid making it possible to exploit root from the
> > > games uid through filesystem-based attacks.
> > 
> > There is no games uid, there is only a 'nethack' uid and gid. This
> > uid and gid cannot attack anything. The consequence is that ~/.game
> > must be moved to /var/games/<game>/<user>. This is a trivial change.
> 
> I think you misunderstood my scenario.  The migration of the game
> files would typically be done by the maintainer scripts, with root
> privileges.  It was an example of additional risks which are
> introduced by adding complexity.  In this case, a migration is
> required, and secure migration in that situation is not necessarily
> trivial or obvious to the package maintainer.

*Any* solution to the age-old setgid games problem will require some
migration. We'll have to live with either the age-old problem or a
migration. I don't care which will happen, but don't complain that a
solution needs a migration. It's not a problem with *this* particular
solution. 

> (nethack, the example game, already stores its saved games under
> /var/lib/games/nethack)

That's excellent; then only the trivial getuid() -> atoi(getenv("UID"))
patch remains. 

- pwent = getpwuid(getuid());
+ envuid = getenv("UID");
+ pwent = getpwuid((envuid && getgid() == getegid()) ? atoi(envuid) : getuid());
 
  if (!pwent) { perror("getpwuid"); _exit(1); }
  username = pwent->pw_name;
  fullname = pwent->pw_gecos;
  if (fullname) { s = strchr(fullname, ','); if (s) *s = 0; }
  else fullname = username;
  ...

Note that this also ignores UID if the game is installed setgid, to
prevent impersonating other players. (Only a user that has been given
login gid 'games' can cheat this way, but that's a feature, not a bug
;-).

Cheers,


Emile.

--
E-Advies - Emile van Bergen           emile@e-advies.nl      
tel. +31 (0)70 3906153           http://www.e-advies.nl    



Reply to: