Commit 967423e8 authored by Arjan van de Ven's avatar Arjan van de Ven Committed by Linus Torvalds

[PATCH] Randomisation: infrastructure

The patch below introduces get_random_int() and randomize_range(), two helpers
used in later patches in the series.  get_random_int() shares the tcp/ip
random number stuff so the CONFIG_INET ifdef needs to move slightly, and to
reduce the damange due to that, secure_ip_id() needs to move inside random.c
From: Frank Sorenson <frank@tuxrocks.com>
Acked-By: default avatarJeff Dike <jdike@addtoit.com>

The stack randomization patches that went into 2.6.11-rc3-mm1 broke
compilation of ARCH=um.  This patch fixes compiling by adding arch_align_stack
back in.
Signed-off-by: default avatarArjan van de Ven <arjan@infradead.org>
Signed-off-by: default avatarIngo Molnar <mingo@elte.hu>
Signed-off-by: default avatarFrank Sorenson <frank@tuxrocks.com>
Signed-off-by: default avatarAndrew Morton <akpm@osdl.org>
Signed-off-by: default avatarLinus Torvalds <torvalds@osdl.org>
parent 818bcba5
...@@ -21,6 +21,7 @@ ...@@ -21,6 +21,7 @@
#include "linux/spinlock.h" #include "linux/spinlock.h"
#include "linux/proc_fs.h" #include "linux/proc_fs.h"
#include "linux/ptrace.h" #include "linux/ptrace.h"
#include "linux/random.h"
#include "asm/unistd.h" #include "asm/unistd.h"
#include "asm/mman.h" #include "asm/mman.h"
#include "asm/segment.h" #include "asm/segment.h"
...@@ -479,6 +480,14 @@ int singlestepping(void * t) ...@@ -479,6 +480,14 @@ int singlestepping(void * t)
return 2; return 2;
} }
unsigned long arch_align_stack(unsigned long sp)
{
if (randomize_va_space)
sp -= get_random_int() % 8192;
return sp & ~0xf;
}
/* /*
* Overrides for Emacs so that we follow Linus's tabbing style. * Overrides for Emacs so that we follow Linus's tabbing style.
* Emacs will notice this stuff at the end of the file and automatically * Emacs will notice this stuff at the end of the file and automatically
......
...@@ -1965,7 +1965,6 @@ static void sysctl_init_random(struct entropy_store *random_state) ...@@ -1965,7 +1965,6 @@ static void sysctl_init_random(struct entropy_store *random_state)
* *
********************************************************************/ ********************************************************************/
#ifdef CONFIG_INET
/* /*
* TCP initial sequence number picking. This uses the random number * TCP initial sequence number picking. This uses the random number
* generator to pick an initial secret value. This value is hashed * generator to pick an initial secret value. This value is hashed
...@@ -2202,6 +2201,31 @@ __u32 secure_tcpv6_sequence_number(__u32 *saddr, __u32 *daddr, ...@@ -2202,6 +2201,31 @@ __u32 secure_tcpv6_sequence_number(__u32 *saddr, __u32 *daddr,
EXPORT_SYMBOL(secure_tcpv6_sequence_number); EXPORT_SYMBOL(secure_tcpv6_sequence_number);
#endif #endif
/* The code below is shamelessly stolen from secure_tcp_sequence_number().
* All blames to Andrey V. Savochkin <saw@msu.ru>.
*/
__u32 secure_ip_id(__u32 daddr)
{
struct keydata *keyptr;
__u32 hash[4];
keyptr = get_keyptr();
/*
* Pick a unique starting offset for each IP destination.
* The dest ip address is placed in the starting vector,
* which is then hashed with random data.
*/
hash[0] = daddr;
hash[1] = keyptr->secret[9];
hash[2] = keyptr->secret[10];
hash[3] = keyptr->secret[11];
return halfMD4Transform(hash, keyptr->secret);
}
#ifdef CONFIG_INET
__u32 secure_tcp_sequence_number(__u32 saddr, __u32 daddr, __u32 secure_tcp_sequence_number(__u32 saddr, __u32 daddr,
__u16 sport, __u16 dport) __u16 sport, __u16 dport)
{ {
...@@ -2242,28 +2266,7 @@ __u32 secure_tcp_sequence_number(__u32 saddr, __u32 daddr, ...@@ -2242,28 +2266,7 @@ __u32 secure_tcp_sequence_number(__u32 saddr, __u32 daddr,
EXPORT_SYMBOL(secure_tcp_sequence_number); EXPORT_SYMBOL(secure_tcp_sequence_number);
/* The code below is shamelessly stolen from secure_tcp_sequence_number().
* All blames to Andrey V. Savochkin <saw@msu.ru>.
*/
__u32 secure_ip_id(__u32 daddr)
{
struct keydata *keyptr;
__u32 hash[4];
keyptr = get_keyptr();
/*
* Pick a unique starting offset for each IP destination.
* The dest ip address is placed in the starting vector,
* which is then hashed with random data.
*/
hash[0] = daddr;
hash[1] = keyptr->secret[9];
hash[2] = keyptr->secret[10];
hash[3] = keyptr->secret[11];
return halfMD4Transform(hash, keyptr->secret);
}
/* Generate secure starting point for ephemeral TCP port search */ /* Generate secure starting point for ephemeral TCP port search */
u32 secure_tcp_port_ephemeral(__u32 saddr, __u32 daddr, __u16 dport) u32 secure_tcp_port_ephemeral(__u32 saddr, __u32 daddr, __u16 dport)
...@@ -2383,3 +2386,40 @@ __u32 check_tcp_syn_cookie(__u32 cookie, __u32 saddr, __u32 daddr, __u16 sport, ...@@ -2383,3 +2386,40 @@ __u32 check_tcp_syn_cookie(__u32 cookie, __u32 saddr, __u32 daddr, __u16 sport,
} }
#endif #endif
#endif /* CONFIG_INET */ #endif /* CONFIG_INET */
/*
* Get a random word for internal kernel use only. Similar to urandom but
* with the goal of minimal entropy pool depletion. As a result, the random
* value is not cryptographically secure but for several uses the cost of
* depleting entropy is too high
*/
unsigned int get_random_int(void)
{
/*
* Use IP's RNG. It suits our purpose perfectly: it re-keys itself
* every second, from the entropy pool (and thus creates a limited
* drain on it), and uses halfMD4Transform within the second. We
* also mix it with jiffies and the PID:
*/
return secure_ip_id(current->pid + jiffies);
}
/*
* randomize_range() returns a start address such that
*
* [...... <range> .....]
* start end
*
* a <range> with size "len" starting at the return value is inside in the
* area defined by [start, end], but is otherwise randomized.
*/
unsigned long
randomize_range(unsigned long start, unsigned long end, unsigned long len)
{
unsigned long range = end - len - start;
if (end <= start + len)
return 0;
return PAGE_ALIGN(get_random_int() % range + start);
}
...@@ -70,6 +70,9 @@ extern __u32 secure_tcpv6_sequence_number(__u32 *saddr, __u32 *daddr, ...@@ -70,6 +70,9 @@ extern __u32 secure_tcpv6_sequence_number(__u32 *saddr, __u32 *daddr,
extern struct file_operations random_fops, urandom_fops; extern struct file_operations random_fops, urandom_fops;
#endif #endif
unsigned int get_random_int(void);
unsigned long randomize_range(unsigned long start, unsigned long end, unsigned long len);
#endif /* __KERNEL___ */ #endif /* __KERNEL___ */
#endif /* _LINUX_RANDOM_H */ #endif /* _LINUX_RANDOM_H */
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment