Commit e51f6d343789a4f0a2a7587ad7ec7746969d5c1c

Authored by Michael LeMay
Committed by Linus Torvalds
1 parent 5801649d8b

[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.html

Signed-off-by: Michael LeMay <mdlemay@epoch.ncsc.mil>
Signed-off-by: James Morris <jmorris@namei.org>
Signed-off-by: David Howells <dhowells@redhat.com>
Signed-off-by: Andrew Morton <akpm@osdl.org>
Signed-off-by: Linus Torvalds <torvalds@osdl.org>

Showing 1 changed file with 14 additions and 14 deletions Side-by-side Diff

... ... @@ -15,11 +15,11 @@
15 15 #include <linux/slab.h>
16 16 #include <linux/security.h>
17 17 #include <linux/workqueue.h>
  18 +#include <linux/random.h>
18 19 #include <linux/err.h>
19 20 #include "internal.h"
20 21  
21 22 static kmem_cache_t *key_jar;
22   -static key_serial_t key_serial_next = 3;
23 23 struct rb_root key_serial_tree; /* tree of keys indexed by serial */
24 24 DEFINE_SPINLOCK(key_serial_lock);
25 25  
26 26  
27 27  
28 28  
... ... @@ -169,23 +169,24 @@
169 169 /*****************************************************************************/
170 170 /*
171 171 * assign a key the next unique serial number
172   - * - we work through all the serial numbers between 2 and 2^31-1 in turn and
173   - * then wrap
  172 + * - these are assigned randomly to avoid security issues through covert
  173 + * channel problems
174 174 */
175 175 static inline void key_alloc_serial(struct key *key)
176 176 {
177 177 struct rb_node *parent, **p;
178 178 struct key *xkey;
179 179  
180   - spin_lock(&key_serial_lock);
181   -
182   - /* propose a likely serial number and look for a hole for it in the
  180 + /* propose a random serial number and look for a hole for it in the
183 181 * serial number tree */
184   - key->serial = key_serial_next;
185   - if (key->serial < 3)
186   - key->serial = 3;
187   - key_serial_next = key->serial + 1;
  182 + do {
  183 + get_random_bytes(&key->serial, sizeof(key->serial));
188 184  
  185 + key->serial >>= 1; /* negative numbers are not permitted */
  186 + } while (key->serial < 3);
  187 +
  188 + spin_lock(&key_serial_lock);
  189 +
189 190 parent = NULL;
190 191 p = &key_serial_tree.rb_node;
191 192  
192 193  
193 194  
... ... @@ -204,12 +205,11 @@
204 205  
205 206 /* we found a key with the proposed serial number - walk the tree from
206 207 * that point looking for the next unused serial number */
207   - serial_exists:
  208 +serial_exists:
208 209 for (;;) {
209   - key->serial = key_serial_next;
  210 + key->serial++;
210 211 if (key->serial < 2)
211 212 key->serial = 2;
212   - key_serial_next = key->serial + 1;
213 213  
214 214 if (!rb_parent(parent))
215 215 p = &key_serial_tree.rb_node;
... ... @@ -228,7 +228,7 @@
228 228 }
229 229  
230 230 /* we've found a suitable hole - arrange for this key to occupy it */
231   - insert_here:
  231 +insert_here:
232 232 rb_link_node(&key->serial_node, parent, p);
233 233 rb_insert_color(&key->serial_node, &key_serial_tree);
234 234