[OpenAFS] Loosing tokens...
Mon, 04 Apr 2005 19:54:09 -0400
On Monday, April 04, 2005 04:53:08 PM +0200 Frank Burkhardt <email@example.com>
> 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.