aboutsummaryrefslogtreecommitdiffstats
path: root/security/keys/key.c
diff options
context:
space:
mode:
authorMichael LeMay <mdlemay@epoch.ncsc.mil>2006-06-26 03:24:54 -0400
committerLinus Torvalds <torvalds@g5.osdl.org>2006-06-26 12:58:18 -0400
commite51f6d343789a4f0a2a7587ad7ec7746969d5c1c (patch)
tree39ca4e05c0dda995f3eaaea1aaa2c8689003f1d0 /security/keys/key.c
parent5801649d8b83e7cb9b15839761bdee594653c294 (diff)
[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>
Diffstat (limited to 'security/keys/key.c')
-rw-r--r--security/keys/key.c28
1 files changed, 14 insertions, 14 deletions
diff --git a/security/keys/key.c b/security/keys/key.c
index 3601fddca9f2..43295ca37b5d 100644
--- a/security/keys/key.c
+++ b/security/keys/key.c
@@ -15,11 +15,11 @@
15#include <linux/slab.h> 15#include <linux/slab.h>
16#include <linux/security.h> 16#include <linux/security.h>
17#include <linux/workqueue.h> 17#include <linux/workqueue.h>
18#include <linux/random.h>
18#include <linux/err.h> 19#include <linux/err.h>
19#include "internal.h" 20#include "internal.h"
20 21
21static kmem_cache_t *key_jar; 22static kmem_cache_t *key_jar;
22static key_serial_t key_serial_next = 3;
23struct rb_root key_serial_tree; /* tree of keys indexed by serial */ 23struct rb_root key_serial_tree; /* tree of keys indexed by serial */
24DEFINE_SPINLOCK(key_serial_lock); 24DEFINE_SPINLOCK(key_serial_lock);
25 25
@@ -169,22 +169,23 @@ static void __init __key_insert_serial(struct key *key)
169/*****************************************************************************/ 169/*****************************************************************************/
170/* 170/*
171 * assign a key the next unique serial number 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 172 * - these are assigned randomly to avoid security issues through covert
173 * then wrap 173 * channel problems
174 */ 174 */
175static inline void key_alloc_serial(struct key *key) 175static inline void key_alloc_serial(struct key *key)
176{ 176{
177 struct rb_node *parent, **p; 177 struct rb_node *parent, **p;
178 struct key *xkey; 178 struct key *xkey;
179 179
180 spin_lock(&key_serial_lock); 180 /* propose a random serial number and look for a hole for it in the
181
182 /* propose a likely serial number and look for a hole for it in the
183 * serial number tree */ 181 * serial number tree */
184 key->serial = key_serial_next; 182 do {
185 if (key->serial < 3) 183 get_random_bytes(&key->serial, sizeof(key->serial));
186 key->serial = 3; 184
187 key_serial_next = key->serial + 1; 185 key->serial >>= 1; /* negative numbers are not permitted */
186 } while (key->serial < 3);
187
188 spin_lock(&key_serial_lock);
188 189
189 parent = NULL; 190 parent = NULL;
190 p = &key_serial_tree.rb_node; 191 p = &key_serial_tree.rb_node;
@@ -204,12 +205,11 @@ static inline void key_alloc_serial(struct key *key)
204 205
205 /* we found a key with the proposed serial number - walk the tree from 206 /* we found a key with the proposed serial number - walk the tree from
206 * that point looking for the next unused serial number */ 207 * that point looking for the next unused serial number */
207 serial_exists: 208serial_exists:
208 for (;;) { 209 for (;;) {
209 key->serial = key_serial_next; 210 key->serial++;
210 if (key->serial < 2) 211 if (key->serial < 2)
211 key->serial = 2; 212 key->serial = 2;
212 key_serial_next = key->serial + 1;
213 213
214 if (!rb_parent(parent)) 214 if (!rb_parent(parent))
215 p = &key_serial_tree.rb_node; 215 p = &key_serial_tree.rb_node;
@@ -228,7 +228,7 @@ static inline void key_alloc_serial(struct key *key)
228 } 228 }
229 229
230 /* we've found a suitable hole - arrange for this key to occupy it */ 230 /* we've found a suitable hole - arrange for this key to occupy it */
231 insert_here: 231insert_here:
232 rb_link_node(&key->serial_node, parent, p); 232 rb_link_node(&key->serial_node, parent, p);
233 rb_insert_color(&key->serial_node, &key_serial_tree); 233 rb_insert_color(&key->serial_node, &key_serial_tree);
234 234