KEYS: Do LRU discard in full keyrings
authorDavid Howells <dhowells@redhat.com>
Fri, 11 May 2012 09:56:56 +0000 (10:56 +0100)
committerDavid Howells <dhowells@redhat.com>
Fri, 11 May 2012 09:56:56 +0000 (10:56 +0100)
commit31d5a79d7f3d436da176a78ebc12d53c06da402e
treed39a75d7d0d0e85102ff8ce5e55e5d6ab7db7262
parent233e4735f2a45d9e641c2488b8d7afeb1f377dac
KEYS: Do LRU discard in full keyrings

Do an LRU discard in keyrings that are full rather than returning ENFILE.  To
perform this, a time_t is added to the key struct and updated by the creation
of a link to a key and by a key being found as the result of a search.  At the
completion of a successful search, the keyrings in the path between the root of
the search and the first found link to it also have their last-used times
updated.

Note that discarding a link to a key from a keyring does not necessarily
destroy the key as there may be references held by other places.

An alternate discard method that might suffice is to perform FIFO discard from
the keyring, using the spare 2-byte hole in the keylist header as the index of
the next link to be discarded.

This is useful when using a keyring as a cache for DNS results or foreign
filesystem IDs.

This can be tested by the following.  As root do:

echo 1000 >/proc/sys/kernel/keys/root_maxkeys

kr=`keyctl newring foo @s`
for ((i=0; i<2000; i++)); do keyctl add user a$i a $kr; done

Without this patch ENFILE should be reported when the keyring fills up.  With
this patch, the keyring discards keys in an LRU fashion.  Note that the stored
LRU time has a granularity of 1s.

After doing this, /proc/key-users can be observed and should show that most of
the 2000 keys have been discarded:

[root@andromeda ~]# cat /proc/key-users
    0:   517 516/516 513/1000 5249/20000

The "513/1000" here is the number of quota-accounted keys present for this user
out of the maximum permitted.

In /proc/keys, the keyring shows the number of keys it has and the number of
slots it has allocated:

[root@andromeda ~]# grep foo /proc/keys
200c64c4 I--Q--     1 perm 3b3f0000     0     0 keyring   foo: 509/509

The maximum is (PAGE_SIZE - header) / key pointer size.  That's typically 509
on a 64-bit system and 1020 on a 32-bit system.

Signed-off-by: David Howells <dhowells@redhat.com>
include/linux/key.h
security/keys/keyring.c
security/keys/process_keys.c