Commit e51f6d343789a4f0a2a7587ad7ec7746969d5c1c
Committed by
Linus Torvalds
1 parent
5801649d8b
Exists in
master
and in
4 other branches
[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
security/keys/key.c
... | ... | @@ -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 |