Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

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

[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: 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
Loading
Loading
Loading
Loading
+14 −14
Original line number Diff line number Diff line
@@ -15,11 +15,11 @@
#include <linux/slab.h>
#include <linux/security.h>
#include <linux/workqueue.h>
#include <linux/random.h>
#include <linux/err.h>
#include "internal.h"

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 */
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
 * - we work through all the serial numbers between 2 and 2^31-1 in turn and
 *   then wrap
 * - these are assigned randomly to avoid security issues through covert
 *   channel problems
 */
static inline void key_alloc_serial(struct key *key)
{
	struct rb_node *parent, **p;
	struct key *xkey;

	spin_lock(&key_serial_lock);

	/* propose a likely serial number and look for a hole for it in the
	/* propose a random serial number and look for a hole for it in the
	 * serial number tree */
	key->serial = key_serial_next;
	if (key->serial < 3)
		key->serial = 3;
	key_serial_next = key->serial + 1;
	do {
		get_random_bytes(&key->serial, sizeof(key->serial));

		key->serial >>= 1; /* negative numbers are not permitted */
	} while (key->serial < 3);

	spin_lock(&key_serial_lock);

	parent = NULL;
	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 */
serial_exists:
	for (;;) {
		key->serial = key_serial_next;
		key->serial++;
		if (key->serial < 2)
			key->serial = 2;
		key_serial_next = key->serial + 1;

		if (!rb_parent(parent))
			p = &key_serial_tree.rb_node;