aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorKevin Coffman <kwc@citi.umich.edu>2008-04-29 04:01:22 -0400
committerLinus Torvalds <torvalds@linux-foundation.org>2008-04-29 11:06:16 -0400
commitdceba9944181b1fd5993417b5c8fa0e3dda38f8d (patch)
tree697e247a7a99c81af7ba4d7ad5d9cdf9941b3741
parent38bbca6b6f164e08a4a9cdfd719fff679af98375 (diff)
keys: check starting keyring as part of search
Check the starting keyring as part of the search to (a) see if that is what we're searching for, and (b) to check it is still valid for searching. The scenario: User in process A does things that cause things to be created in its process session keyring. The user then does an su to another user and starts a new process, B. The two processes now share the same process session keyring. Process B does an NFS access which results in an upcall to gssd. When gssd attempts to instantiate the context key (to be linked into the process session keyring), it is denied access even though it has an authorization key. The order of calls is: keyctl_instantiate_key() lookup_user_key() (the default: case) search_process_keyrings(current) search_process_keyrings(rka->context) (recursive call) keyring_search_aux() keyring_search_aux() verifies the keys and keyrings underneath the top-level keyring it is given, but that top-level keyring is neither fully validated nor checked to see if it is the thing being searched for. This patch changes keyring_search_aux() to: 1) do more validation on the top keyring it is given and 2) check whether that top-level keyring is the thing being searched for Signed-off-by: Kevin Coffman <kwc@citi.umich.edu> Signed-off-by: David Howells <dhowells@redhat.com> Cc: Paul Moore <paul.moore@hp.com> Cc: Chris Wright <chrisw@sous-sol.org> Cc: Stephen Smalley <sds@tycho.nsa.gov> Cc: James Morris <jmorris@namei.org> Cc: Kevin Coffman <kwc@citi.umich.edu> Cc: Trond Myklebust <trond.myklebust@fys.uio.no> Cc: "J. Bruce Fields" <bfields@fieldses.org> Signed-off-by: Andrew Morton <akpm@linux-foundation.org> Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
-rw-r--r--security/keys/keyring.c35
1 files changed, 31 insertions, 4 deletions
diff --git a/security/keys/keyring.c b/security/keys/keyring.c
index 88292e3dee96..70f0c313c888 100644
--- a/security/keys/keyring.c
+++ b/security/keys/keyring.c
@@ -292,7 +292,7 @@ key_ref_t keyring_search_aux(key_ref_t keyring_ref,
292 292
293 struct keyring_list *keylist; 293 struct keyring_list *keylist;
294 struct timespec now; 294 struct timespec now;
295 unsigned long possessed; 295 unsigned long possessed, kflags;
296 struct key *keyring, *key; 296 struct key *keyring, *key;
297 key_ref_t key_ref; 297 key_ref_t key_ref;
298 long err; 298 long err;
@@ -319,6 +319,32 @@ key_ref_t keyring_search_aux(key_ref_t keyring_ref,
319 err = -EAGAIN; 319 err = -EAGAIN;
320 sp = 0; 320 sp = 0;
321 321
322 /* firstly we should check to see if this top-level keyring is what we
323 * are looking for */
324 key_ref = ERR_PTR(-EAGAIN);
325 kflags = keyring->flags;
326 if (keyring->type == type && match(keyring, description)) {
327 key = keyring;
328
329 /* check it isn't negative and hasn't expired or been
330 * revoked */
331 if (kflags & (1 << KEY_FLAG_REVOKED))
332 goto error_2;
333 if (key->expiry && now.tv_sec >= key->expiry)
334 goto error_2;
335 key_ref = ERR_PTR(-ENOKEY);
336 if (kflags & (1 << KEY_FLAG_NEGATIVE))
337 goto error_2;
338 goto found;
339 }
340
341 /* otherwise, the top keyring must not be revoked, expired, or
342 * negatively instantiated if we are to search it */
343 key_ref = ERR_PTR(-EAGAIN);
344 if (kflags & ((1 << KEY_FLAG_REVOKED) | (1 << KEY_FLAG_NEGATIVE)) ||
345 (keyring->expiry && now.tv_sec >= keyring->expiry))
346 goto error_2;
347
322 /* start processing a new keyring */ 348 /* start processing a new keyring */
323descend: 349descend:
324 if (test_bit(KEY_FLAG_REVOKED, &keyring->flags)) 350 if (test_bit(KEY_FLAG_REVOKED, &keyring->flags))
@@ -331,13 +357,14 @@ descend:
331 /* iterate through the keys in this keyring first */ 357 /* iterate through the keys in this keyring first */
332 for (kix = 0; kix < keylist->nkeys; kix++) { 358 for (kix = 0; kix < keylist->nkeys; kix++) {
333 key = keylist->keys[kix]; 359 key = keylist->keys[kix];
360 kflags = key->flags;
334 361
335 /* ignore keys not of this type */ 362 /* ignore keys not of this type */
336 if (key->type != type) 363 if (key->type != type)
337 continue; 364 continue;
338 365
339 /* skip revoked keys and expired keys */ 366 /* skip revoked keys and expired keys */
340 if (test_bit(KEY_FLAG_REVOKED, &key->flags)) 367 if (kflags & (1 << KEY_FLAG_REVOKED))
341 continue; 368 continue;
342 369
343 if (key->expiry && now.tv_sec >= key->expiry) 370 if (key->expiry && now.tv_sec >= key->expiry)
@@ -352,8 +379,8 @@ descend:
352 context, KEY_SEARCH) < 0) 379 context, KEY_SEARCH) < 0)
353 continue; 380 continue;
354 381
355 /* we set a different error code if we find a negative key */ 382 /* we set a different error code if we pass a negative key */
356 if (test_bit(KEY_FLAG_NEGATIVE, &key->flags)) { 383 if (kflags & (1 << KEY_FLAG_NEGATIVE)) {
357 err = -ENOKEY; 384 err = -ENOKEY;
358 continue; 385 continue;
359 } 386 }