Re: In-kernel Authentication Tokens (PAGs)

From: David Howells
Date: Thu Jun 17 2004 - 06:50:05 EST



Kyle Moffett <mrmacman_g4@xxxxxxx> wrote:
> What if we leave the concept of a key-ring as completely general in nature,
> such that it can be associated with any object without needing to know what
> that object is. Then additional key-ring contexts could be created as
> needed for LSM modules or such.

The main reason that there are attachment points for keyrings on UIDs,
processes, etc, is that there needs to be some way for things like open() to
find them without adding an equivalent syscalls that take a key as well.

In a way, you could look at it as these attachment points are like the PATH
variable - they describe a search path. You still need one of those.

LSM modules can always create keyrings and subscribe one of the five keyrings
a task has to them so that they become accessible.

> I gave reasons earlier in this thread of why it is very useful to have
> nested key-rings, so perhaps we can give each key-ring a "parent" which
> happens to be an additional key-ring association. As long as we avoid
> cyclic graphs, that should give a great increase in flexibility without
> security problems.

It supports nested keyrings - up to a certain depth anyway - and when you add
one keyring into another it checks to see you're not trying to create a cycle
(at least, you can from the kernel... you can't from userspace yet).

I'm not keen on the "parent" idea. I'm not sure what you are thinking of
exactly - a keyring can have multiple parents, and also this sounds like it
may cause a cycle.

> Another complexity is the access control issue. I would rather not add more
> LSM hooks if we can avoid it, just to keep the complexity down, so I'm
> thinking that we could just represent all the information through the
> filesystem and file descriptors, with a couple of convenient IOCTLs. That
> way we could use the existing LSM hooks for filesystem access, and avoid
> giving sysadmins another system that they must start all over learning to
> secure.

Using LSM hooks could represent a chicken vs egg scenario if you want to use
these keys to represent LSM security data (which you might reasonably want to
do).

> I've looked at your patch, and it doesn't seem to be general enough to allow
> user-space to store arbitrary keys in the kernel, one of the features that
> others have expressed a desire for (see Andy Lutomirski's emails). With
> such a system the most critical aspect to get first is the most flexible way
> to manipulate such keys without creating too much complexity.

It could be made such that arbitrary keys can be stored there (just another
keytype)... it's just that the keys eat into the kernel low memory region. It
may be better to permit such keys to be stored in highmem or swap somehow.

Plus, should there be a quota system?

> It's essential to be able to tell the difference between different types of
> keys, especially if we want to let user-space use this to store other kinds
> of keys. We also need to be able to identify keys by "service" of some sort.

Keys have a serial number, a type, a description and a payload. Currently the
types can't be arbitrary - a kernel driver or whatever must have registered
that type for it to be used. If that driver unregisters its key type, all keys
of that type are immediately withdrawn.

For instance, my kafs module registers an "afs" key type in which it can store
a Krb5 ticket. Having a type management system like this allows the type to
have operations to validate, match and pretty-print key descriptions. The
first one is the most important, I feel, because we can validate a key upon
addition.

It might be possible to make this more flexible. Have userspace upload a
"potential" key with arbitrary type, description and payload; and then have,
say, a kafs's file open routine locate a candidate key and render it into
parsed key form. Hmmm...

One thing I want to avoid is having to have the filesystem (or whatever)
validate the key every time it looks at it.

> I think that would probably be a key-type specific parameter, but for a
> Kerberos TGT it could be something like "krbtgt/MY.REALM@xxxxxxxx". With a
> type based system we could even allow modules that implement additional
> functionality for certain types (IE something that uses CryptoAPI to do AES
> in-kernel for extra security).

In this example, you might have something like:

type krbtgt
desc MY.REALM@xxxxxxxx

Or:

type user
desc krbtgt/MY.REALM@xxxxxxxx

But you'd have to provide the kernel with a type registration for the key type
in question.

> Hmm, so going along with these ideas, how about this?
> /proc/keyring/
> MODE = 555
> DESC = keyringfs, contains keyring metadata

I presume you mean keyringfs or keyfs mounted on /proc/keyring/ (or /proc/keys/).

> <id>/
> MODE = Access control for entire keyring
> DESC = A keyring entry, referenced by number
> opendir = Increments the ref count to make sure it won't go away.
>
> parent => ../<id>
> DESC = A symlink or hardlink to the parent keyring
>
> <typeid>/
> MODE = 555
> DESC = A numerical "key-type" (KEYTYPE_KRB5)
>
> <service>
> MODE = Access control for a single key
> DESC = The key, accessed as a file.
>
> <typename> => <typeid>/
> DESC = A symlink or hardlink to a type number from
> a type name. These types could be registered
> by modules that implement them.
>
> There would be IOCTLs on the key-ring dir handles for getting the key-ring
> number

Why? That's the filename of the keyring dir.

> adding new keys, etc.

Some of this could be done by link and rename.

> On key handles there would be IOCTLs for deleting the key,

unlink.

> revoking access, etc.

> We'd also need a few syscalls for creating new key-rings.

mkdir would be nice, but the key manager supplies the ID.


I think I'd make the filesystem look like:

/proc/keys/
types
keys/
<keyID>
<keyringID>/
<keyID>
<keyringID> => ../<keyringID> [symlink]
<keyID>
<keyID> [hardlink to keyID]
<keyringID>/
<keyID>
<keyID>
<keyringID>/
<keyringID>/
<keyID>


Each key would then have a UID, GID and umask which behave like for normal
files. Reading key files would then get you a summary of the key contents and
state. getxattr could be used also. The payload would only be accessible
through getxattr.

I might even permit the use of link() and rename(), provided the keys
filenames stay the same, and unlink().

However, I think I'd prefer to extend the syscall interface some more.

I've got four prctls:

(*) Get process subscribed keyring ID (choose which of the five).

(*) Clear process subscribed keyring ID (choose which of the five).

(*) Request new session keyring for this process.

(*) Add key to process subscribed keyring ID (choose which of the five).

I could then add some more syscalls:

(*) Add key to arbitrary keyring.

(*) Update key.

(*) Retire key.

(*) Get list of key IDs from keyring.

(*) Get type of key.

(*) Get description of key.

(*) Get payload of key.

(*) Link key to keyring.

(*) Unlink key from keyring.

All but the first two are trivially easy to do with a keyfs using standard
operations.

David
-
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majordomo@xxxxxxxxxxxxxxx
More majordomo info at http://vger.kernel.org/majordomo-info.html
Please read the FAQ at http://www.tux.org/lkml/