Commit e51f6d34 authored by Michael LeMay's avatar Michael LeMay Committed by Linus Torvalds

[PATCH] keys: allocate key serial numbers randomly

Cause key_alloc_serial() to generate key serial numbers randomly rather than
in linear sequence.

Using an linear sequence permits a covert communication channel to be
established, in which one process can communicate with another by creating or
not creating new keys within a certain timeframe.  The second process can
probe for the expected next key serial number and judge its existence by the
error returned.

This is a problem as the serial number namespace is globally shared between
all tasks, regardless of their context.

For more information on this topic, this old TCSEC guide is recommended:

	http://www.radium.ncsc.mil/tpep/library/rainbow/NCSC-TG-030.htmlSigned-off-by: default avatarMichael LeMay <mdlemay@epoch.ncsc.mil>
Signed-off-by: default avatarJames Morris <jmorris@namei.org>
Signed-off-by: default avatarDavid Howells <dhowells@redhat.com>
Signed-off-by: default avatarAndrew Morton <akpm@osdl.org>
Signed-off-by: default avatarLinus Torvalds <torvalds@osdl.org>
parent 5801649d
...@@ -15,11 +15,11 @@ ...@@ -15,11 +15,11 @@
#include <linux/slab.h> #include <linux/slab.h>
#include <linux/security.h> #include <linux/security.h>
#include <linux/workqueue.h> #include <linux/workqueue.h>
#include <linux/random.h>
#include <linux/err.h> #include <linux/err.h>
#include "internal.h" #include "internal.h"
static kmem_cache_t *key_jar; static kmem_cache_t *key_jar;
static key_serial_t key_serial_next = 3;
struct rb_root key_serial_tree; /* tree of keys indexed by serial */ struct rb_root key_serial_tree; /* tree of keys indexed by serial */
DEFINE_SPINLOCK(key_serial_lock); DEFINE_SPINLOCK(key_serial_lock);
...@@ -169,22 +169,23 @@ static void __init __key_insert_serial(struct key *key) ...@@ -169,22 +169,23 @@ static void __init __key_insert_serial(struct key *key)
/*****************************************************************************/ /*****************************************************************************/
/* /*
* assign a key the next unique serial number * assign a key the next unique serial number
* - we work through all the serial numbers between 2 and 2^31-1 in turn and * - these are assigned randomly to avoid security issues through covert
* then wrap * channel problems
*/ */
static inline void key_alloc_serial(struct key *key) static inline void key_alloc_serial(struct key *key)
{ {
struct rb_node *parent, **p; struct rb_node *parent, **p;
struct key *xkey; struct key *xkey;
spin_lock(&key_serial_lock); /* propose a random serial number and look for a hole for it in the
/* propose a likely serial number and look for a hole for it in the
* serial number tree */ * serial number tree */
key->serial = key_serial_next; do {
if (key->serial < 3) get_random_bytes(&key->serial, sizeof(key->serial));
key->serial = 3;
key_serial_next = key->serial + 1; key->serial >>= 1; /* negative numbers are not permitted */
} while (key->serial < 3);
spin_lock(&key_serial_lock);
parent = NULL; parent = NULL;
p = &key_serial_tree.rb_node; p = &key_serial_tree.rb_node;
...@@ -204,12 +205,11 @@ static inline void key_alloc_serial(struct key *key) ...@@ -204,12 +205,11 @@ static inline void key_alloc_serial(struct key *key)
/* we found a key with the proposed serial number - walk the tree from /* we found a key with the proposed serial number - walk the tree from
* that point looking for the next unused serial number */ * that point looking for the next unused serial number */
serial_exists: serial_exists:
for (;;) { for (;;) {
key->serial = key_serial_next; key->serial++;
if (key->serial < 2) if (key->serial < 2)
key->serial = 2; key->serial = 2;
key_serial_next = key->serial + 1;
if (!rb_parent(parent)) if (!rb_parent(parent))
p = &key_serial_tree.rb_node; p = &key_serial_tree.rb_node;
...@@ -228,7 +228,7 @@ static inline void key_alloc_serial(struct key *key) ...@@ -228,7 +228,7 @@ static inline void key_alloc_serial(struct key *key)
} }
/* we've found a suitable hole - arrange for this key to occupy it */ /* we've found a suitable hole - arrange for this key to occupy it */
insert_here: insert_here:
rb_link_node(&key->serial_node, parent, p); rb_link_node(&key->serial_node, parent, p);
rb_insert_color(&key->serial_node, &key_serial_tree); rb_insert_color(&key->serial_node, &key_serial_tree);
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment