[OpenAFS] Loosing tokens...

Jeffrey Hutzelman jhutz@cmu.edu
Mon, 04 Apr 2005 19:54:09 -0400

On Monday, April 04, 2005 04:53:08 PM +0200 Frank Burkhardt <fbo2@gmx.net> 

> There's a debian-package containing 'unpagsh' + sources. unpagsh
> (at least the version inside this package) can't be used with kernel 2.6+
> - I hope to find the reason asap.

Hm; I thought I was over this with someone, but maybe it was in private 
mail.  The reason unpagsh does not work on Linux 2.6 is because it depends 
on details of the kernel implementation of PAG's and the per-process group 
list which do not hold on Linux 2.6.

As you know, on traditional UNIX systems, AFS tracks what PAG a process is 
in by encoding the PAG number as in two of the entries in the per-process 
group list.  Usually this is the first two entries, but on some platforms 
the first entry is always the process's gid, and the next two groups are 
used to store the PAG number.  PAG's are encoded as very large group ID's, 
so they cannot be confused with the ID's of real groups, as long as your 
gid assignment procedures don't vary too much with the expectations of the 
designers of this mechanism.

On most UNIX systems, the process's group list is a fixed-size array of 
GID's.  When you call setgroups(), the AFS kernel module traps the call, 
remembers the process's current PAG, lets the real setgroups() run, and 
then restores the PAG.  However, it can only restore the PAG if there is 
enough space left in the group list -- otherwise, the process will lose its 
PAG.  This is considered acceptable because only root can call setgroups(), 
and normally this is done only by initgroups(), which sets a process's 
group list to match the set of groups of which the specified user is a 
member.  Thus, if there is a problem, it is at least likely to behave 
consistently for any given user.  Also, it's considered acceptable because 
there's really not much we can do about it. :-)

unpagsh works by taking advantage of this architecture.  It assembles a 
list of the process's current groups, minus the ones that affect PAG's.  It 
then adds additional entries to fill out the size of the group list, and 
calls setgroups(), causing the process to lose its PAG.  It can then call 
setgroups() again with the original list (again, minus the PAG).

This technique doesn't work on Linux 2.6, and likely never will.  It 
doesn't work today because the group list is now dynamically-sized, and the 
AFS setgroups wrapper simply takes the list returned by setgroups, grows it 
by two entries, and inserts the PAG number storage.  So, you can't 
"overflow" the list because we'll just grow it as needed.

In the long term, this technique will continue not to work because in the 
future, we expect to transition to storing PAG's as keys on a process's 
session keyring.  They will not appear as groups at all, and no amount of 
calling setgroups() will affect them.

In the long term, if people want this functionality, we may have to add an 
interface to provide it in the kernel, rather than as a user-mode hack.

-- Jeff