mirror of https://gitee.com/openkylin/linux.git
[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>
This commit is contained in:
parent
5801649d8b
commit
e51f6d3437
|
@ -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)
|
||||||
/*****************************************************************************/
|
/*****************************************************************************/
|
||||||
/*
|
/*
|
||||||
* 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;
|
||||||
|
@ -206,10 +207,9 @@ static inline void key_alloc_serial(struct key *key)
|
||||||
* 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;
|
||||||
|
|
Loading…
Reference in New Issue