From: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
To: linux-kernel@vger.kernel.org, stable@vger.kernel.org
Cc: Greg KH <gregkh@linuxfoundation.org>,
torvalds@linux-foundation.org, akpm@linux-foundation.org,
alan@lxorguk.ukuu.org.uk, Eric Wustrow <ewust@umich.edu>,
Nadia Heninger <nadiah@cs.ucsd.edu>,
Zakir Durumeric <zakir@umich.edu>,
"J. Alex Halderman" <jhalderm@umich.edu>,
"Theodore Tso" <tytso@mit.edu>
Subject: [ 46/82] random: make add_interrupt_randomness() do something sane
Date: Mon, 13 Aug 2012 13:19:22 -0700 [thread overview]
Message-ID: <20120813201750.477794151@linuxfoundation.org> (raw)
In-Reply-To: <20120813201746.448504360@linuxfoundation.org>
From: Greg KH <gregkh@linuxfoundation.org>
3.5-stable review patch. If anyone has any objections, please let me know.
------------------
From: Theodore Ts'o <tytso@mit.edu>
commit 775f4b297b780601e61787b766f306ed3e1d23eb upstream.
We've been moving away from add_interrupt_randomness() for various
reasons: it's too expensive to do on every interrupt, and flooding the
CPU with interrupts could theoretically cause bogus floods of entropy
from a somewhat externally controllable source.
This solves both problems by limiting the actual randomness addition
to just once a second or after 64 interrupts, whicever comes first.
During that time, the interrupt cycle data is buffered up in a per-cpu
pool. Also, we make sure the the nonblocking pool used by urandom is
initialized before we start feeding the normal input pool. This
assures that /dev/urandom is returning unpredictable data as soon as
possible.
(Based on an original patch by Linus, but significantly modified by
tytso.)
Tested-by: Eric Wustrow <ewust@umich.edu>
Reported-by: Eric Wustrow <ewust@umich.edu>
Reported-by: Nadia Heninger <nadiah@cs.ucsd.edu>
Reported-by: Zakir Durumeric <zakir@umich.edu>
Reported-by: J. Alex Halderman <jhalderm@umich.edu>
Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
Signed-off-by: "Theodore Ts'o" <tytso@mit.edu>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
---
drivers/char/random.c | 103 ++++++++++++++++++++++++++++++++++++++--------
drivers/mfd/ab3100-core.c | 2
include/linux/random.h | 2
kernel/irq/handle.c | 7 +--
4 files changed, 90 insertions(+), 24 deletions(-)
--- a/drivers/char/random.c
+++ b/drivers/char/random.c
@@ -127,19 +127,15 @@
*
* void add_input_randomness(unsigned int type, unsigned int code,
* unsigned int value);
- * void add_interrupt_randomness(int irq);
+ * void add_interrupt_randomness(int irq, int irq_flags);
* void add_disk_randomness(struct gendisk *disk);
*
* add_input_randomness() uses the input layer interrupt timing, as well as
* the event type information from the hardware.
*
- * add_interrupt_randomness() uses the inter-interrupt timing as random
- * inputs to the entropy pool. Note that not all interrupts are good
- * sources of randomness! For example, the timer interrupts is not a
- * good choice, because the periodicity of the interrupts is too
- * regular, and hence predictable to an attacker. Network Interface
- * Controller interrupts are a better measure, since the timing of the
- * NIC interrupts are more unpredictable.
+ * add_interrupt_randomness() uses the interrupt timing as random
+ * inputs to the entropy pool. Using the cycle counters and the irq source
+ * as inputs, it feeds the randomness roughly once a second.
*
* add_disk_randomness() uses what amounts to the seek time of block
* layer request events, on a per-disk_devt basis, as input to the
@@ -248,6 +244,7 @@
#include <linux/percpu.h>
#include <linux/cryptohash.h>
#include <linux/fips.h>
+#include <linux/ptrace.h>
#ifdef CONFIG_GENERIC_HARDIRQS
# include <linux/irq.h>
@@ -256,6 +253,7 @@
#include <asm/processor.h>
#include <asm/uaccess.h>
#include <asm/irq.h>
+#include <asm/irq_regs.h>
#include <asm/io.h>
/*
@@ -421,7 +419,9 @@ struct entropy_store {
spinlock_t lock;
unsigned add_ptr;
int entropy_count;
+ int entropy_total;
int input_rotate;
+ unsigned int initialized:1;
__u8 last_data[EXTRACT_SIZE];
};
@@ -454,6 +454,10 @@ static struct entropy_store nonblocking_
.pool = nonblocking_pool_data
};
+static __u32 const twist_table[8] = {
+ 0x00000000, 0x3b6e20c8, 0x76dc4190, 0x4db26158,
+ 0xedb88320, 0xd6d6a3e8, 0x9b64c2b0, 0xa00ae278 };
+
/*
* This function adds bytes into the entropy "pool". It does not
* update the entropy estimate. The caller should call
@@ -467,9 +471,6 @@ static struct entropy_store nonblocking_
static void mix_pool_bytes_extract(struct entropy_store *r, const void *in,
int nbytes, __u8 out[64])
{
- static __u32 const twist_table[8] = {
- 0x00000000, 0x3b6e20c8, 0x76dc4190, 0x4db26158,
- 0xedb88320, 0xd6d6a3e8, 0x9b64c2b0, 0xa00ae278 };
unsigned long i, j, tap1, tap2, tap3, tap4, tap5;
int input_rotate;
int wordmask = r->poolinfo->poolwords - 1;
@@ -528,6 +529,36 @@ static void mix_pool_bytes(struct entrop
mix_pool_bytes_extract(r, in, bytes, NULL);
}
+struct fast_pool {
+ __u32 pool[4];
+ unsigned long last;
+ unsigned short count;
+ unsigned char rotate;
+ unsigned char last_timer_intr;
+};
+
+/*
+ * This is a fast mixing routine used by the interrupt randomness
+ * collector. It's hardcoded for an 128 bit pool and assumes that any
+ * locks that might be needed are taken by the caller.
+ */
+static void fast_mix(struct fast_pool *f, const void *in, int nbytes)
+{
+ const char *bytes = in;
+ __u32 w;
+ unsigned i = f->count;
+ unsigned input_rotate = f->rotate;
+
+ while (nbytes--) {
+ w = rol32(*bytes++, input_rotate & 31) ^ f->pool[i & 3] ^
+ f->pool[(i + 1) & 3];
+ f->pool[i & 3] = (w >> 3) ^ twist_table[w & 7];
+ input_rotate += (i++ & 3) ? 7 : 14;
+ }
+ f->count = i;
+ f->rotate = input_rotate;
+}
+
/*
* Credit (or debit) the entropy store with n bits of entropy
*/
@@ -551,6 +582,12 @@ static void credit_entropy_bits(struct e
entropy_count = r->poolinfo->POOLBITS;
r->entropy_count = entropy_count;
+ if (!r->initialized && nbits > 0) {
+ r->entropy_total += nbits;
+ if (r->entropy_total > 128)
+ r->initialized = 1;
+ }
+
/* should we wake readers? */
if (r == &input_pool && entropy_count >= random_read_wakeup_thresh) {
wake_up_interruptible(&random_read_wait);
@@ -700,17 +737,48 @@ void add_input_randomness(unsigned int t
}
EXPORT_SYMBOL_GPL(add_input_randomness);
-void add_interrupt_randomness(int irq)
+static DEFINE_PER_CPU(struct fast_pool, irq_randomness);
+
+void add_interrupt_randomness(int irq, int irq_flags)
{
- struct timer_rand_state *state;
+ struct entropy_store *r;
+ struct fast_pool *fast_pool = &__get_cpu_var(irq_randomness);
+ struct pt_regs *regs = get_irq_regs();
+ unsigned long now = jiffies;
+ __u32 input[4], cycles = get_cycles();
+
+ input[0] = cycles ^ jiffies;
+ input[1] = irq;
+ if (regs) {
+ __u64 ip = instruction_pointer(regs);
+ input[2] = ip;
+ input[3] = ip >> 32;
+ }
- state = get_timer_rand_state(irq);
+ fast_mix(fast_pool, input, sizeof(input));
- if (state == NULL)
+ if ((fast_pool->count & 1023) &&
+ !time_after(now, fast_pool->last + HZ))
return;
- DEBUG_ENT("irq event %d\n", irq);
- add_timer_randomness(state, 0x100 + irq);
+ fast_pool->last = now;
+
+ r = nonblocking_pool.initialized ? &input_pool : &nonblocking_pool;
+ mix_pool_bytes(r, &fast_pool->pool, sizeof(fast_pool->pool));
+ /*
+ * If we don't have a valid cycle counter, and we see
+ * back-to-back timer interrupts, then skip giving credit for
+ * any entropy.
+ */
+ if (cycles == 0) {
+ if (irq_flags & __IRQF_TIMER) {
+ if (fast_pool->last_timer_intr)
+ return;
+ fast_pool->last_timer_intr = 1;
+ } else
+ fast_pool->last_timer_intr = 0;
+ }
+ credit_entropy_bits(r, 1);
}
#ifdef CONFIG_BLOCK
@@ -971,6 +1039,7 @@ static void init_std_data(struct entropy
spin_lock_irqsave(&r->lock, flags);
r->entropy_count = 0;
+ r->entropy_total = 0;
spin_unlock_irqrestore(&r->lock, flags);
now = ktime_get_real();
--- a/drivers/mfd/ab3100-core.c
+++ b/drivers/mfd/ab3100-core.c
@@ -409,8 +409,6 @@ static irqreturn_t ab3100_irq_handler(in
u32 fatevent;
int err;
- add_interrupt_randomness(irq);
-
err = ab3100_get_register_page_interruptible(ab3100, AB3100_EVENTA1,
event_regs, 3);
if (err)
--- a/include/linux/random.h
+++ b/include/linux/random.h
@@ -52,7 +52,7 @@ extern void rand_initialize_irq(int irq)
extern void add_input_randomness(unsigned int type, unsigned int code,
unsigned int value);
-extern void add_interrupt_randomness(int irq);
+extern void add_interrupt_randomness(int irq, int irq_flags);
extern void get_random_bytes(void *buf, int nbytes);
void generate_random_uuid(unsigned char uuid_out[16]);
--- a/kernel/irq/handle.c
+++ b/kernel/irq/handle.c
@@ -133,7 +133,7 @@ irqreturn_t
handle_irq_event_percpu(struct irq_desc *desc, struct irqaction *action)
{
irqreturn_t retval = IRQ_NONE;
- unsigned int random = 0, irq = desc->irq_data.irq;
+ unsigned int flags = 0, irq = desc->irq_data.irq;
do {
irqreturn_t res;
@@ -161,7 +161,7 @@ handle_irq_event_percpu(struct irq_desc
/* Fall through to add to randomness */
case IRQ_HANDLED:
- random |= action->flags;
+ flags |= action->flags;
break;
default:
@@ -172,8 +172,7 @@ handle_irq_event_percpu(struct irq_desc
action = action->next;
} while (action);
- if (random & IRQF_SAMPLE_RANDOM)
- add_interrupt_randomness(irq);
+ add_interrupt_randomness(irq, flags);
if (!noirqdebug)
note_interrupt(irq, desc, retval);
next prev parent reply other threads:[~2012-08-13 20:23 UTC|newest]
Thread overview: 92+ messages / expand[flat|nested] mbox.gz Atom feed top
2012-08-13 20:18 [ 00/82] 3.5.2-stable review Greg Kroah-Hartman
2012-08-13 20:18 ` [ 01/82] virtio-blk: Call del_gendisk() before disable guest kick Greg Kroah-Hartman
2012-08-13 20:18 ` Greg Kroah-Hartman
2012-08-13 20:18 ` [ 02/82] virtio-blk: Reset device after blk_cleanup_queue() Greg Kroah-Hartman
2012-08-13 20:18 ` Greg Kroah-Hartman
2012-08-13 20:18 ` [ 03/82] virtio-blk: Use block layer provided spinlock Greg Kroah-Hartman
2012-08-13 20:18 ` Greg Kroah-Hartman
2012-08-13 20:18 ` [ 04/82] [IA64] Redefine ATOMIC_INIT and ATOMIC64_INIT to drop the casts Greg Kroah-Hartman
2012-08-13 20:18 ` [ 05/82] asus-wmi: use ASUS_WMI_METHODID_DSTS2 as default DSTS ID Greg Kroah-Hartman
2012-08-13 20:18 ` [ 06/82] selinux: fix selinux_inode_setxattr oops Greg Kroah-Hartman
2012-08-13 20:18 ` [ 07/82] lib/vsprintf.c: kptr_restrict: fix pK-error in SysRq show-all-timers(Q) Greg Kroah-Hartman
2012-08-13 20:18 ` [ 08/82] sunrpc: clnt: Add missing braces Greg Kroah-Hartman
2012-08-13 20:18 ` [ 09/82] SUNRPC: return negative value in case rpcbind client creation error Greg Kroah-Hartman
2012-08-13 20:18 ` [ 10/82] mISDN: Bugfix only few bytes are transfered on a connection Greg Kroah-Hartman
2012-08-13 20:18 ` [ 11/82] nilfs2: fix deadlock issue between chcp and thaw ioctls Greg Kroah-Hartman
2012-08-13 20:18 ` [ 12/82] media: ene_ir: Fix driver initialisation Greg Kroah-Hartman
2012-08-13 20:18 ` [ 13/82] media: m5mols: Correct reported ISO values Greg Kroah-Hartman
2012-08-13 20:18 ` [ 14/82] media: videobuf-dma-contig: restore buffer mapping for uncached bufers Greg Kroah-Hartman
2012-08-13 20:18 ` [ 15/82] pcdp: use early_ioremap/early_iounmap to access pcdp table Greg Kroah-Hartman
2012-08-13 20:18 ` [ 16/82] memcg: prevent OOM with too many dirty pages Greg Kroah-Hartman
2012-08-13 20:18 ` [ 17/82] memcg: further " Greg Kroah-Hartman
2012-08-13 20:18 ` [ 18/82] mm: fix wrong argument of migrate_huge_pages() in soft_offline_huge_page() Greg Kroah-Hartman
2012-08-13 20:18 ` [ 19/82] ARM: 7466/1: disable interrupt before spinning endlessly Greg Kroah-Hartman
2012-08-13 20:18 ` [ 20/82] ARM: 7467/1: mutex: use generic xchg-based implementation for ARMv6+ Greg Kroah-Hartman
2012-08-15 13:56 ` Ben Hutchings
2012-08-15 14:08 ` Greg Kroah-Hartman
2012-08-15 14:11 ` Ben Hutchings
2012-08-15 14:49 ` Nicolas Pitre
2012-08-15 14:49 ` Greg Kroah-Hartman
2012-08-15 14:55 ` Will Deacon
2012-08-13 20:18 ` [ 21/82] ARM: 7476/1: vfp: only clear vfp state for current cpu in vfp_pm_suspend Greg Kroah-Hartman
2012-08-13 20:18 ` [ 22/82] ARM: 7477/1: vfp: Always save VFP state in vfp_pm_suspend on UP Greg Kroah-Hartman
2012-08-13 20:18 ` [ 23/82] ARM: 7478/1: errata: extend workaround for erratum #720789 Greg Kroah-Hartman
2012-08-13 20:19 ` [ 24/82] ARM: 7479/1: mm: avoid NULL dereference when flushing gate_vma with VIVT caches Greg Kroah-Hartman
2012-08-13 20:19 ` [ 25/82] ARM: 7480/1: only call smp_send_stop() on SMP Greg Kroah-Hartman
2012-08-13 20:19 ` [ 26/82] ARM: Fix undefined instruction exception handling Greg Kroah-Hartman
2012-08-13 20:19 ` [ 27/82] ALSA: hda - add dock support for Thinkpad T430s Greg Kroah-Hartman
2012-08-13 20:19 ` [ 28/82] ALSA: hda - add dock support for Thinkpad X230 Greg Kroah-Hartman
2012-08-13 20:19 ` [ 29/82] ALSA: hda - remove quirk for Dell Vostro 1015 Greg Kroah-Hartman
2012-08-13 20:19 ` [ 30/82] ALSA: hda - Fix double quirk for Quanta FL1 / Lenovo Ideapad Greg Kroah-Hartman
2012-08-13 20:19 ` [ 31/82] mm: setup pageblock_order before its used by sparsemem Greg Kroah-Hartman
2012-08-13 20:19 ` [ 32/82] mm: mmu_notifier: fix freed page still mapped in secondary MMU Greg Kroah-Hartman
2012-08-13 20:19 ` [ 33/82] md/raid1: dont abort a resync on the first badblock Greg Kroah-Hartman
2012-08-13 20:19 ` [ 34/82] video/smscufx: fix line counting in fb_write Greg Kroah-Hartman
2012-08-13 20:19 ` [ 35/82] block: uninitialized ioc->nr_tasks triggers WARN_ON Greg Kroah-Hartman
2012-08-13 20:19 ` [ 36/82] sh: Fix up recursive fault in oops with unset TTB Greg Kroah-Hartman
2012-08-13 20:19 ` [ 37/82] ore: Fix out-of-bounds access in _ios_obj() Greg Kroah-Hartman
2012-08-13 20:19 ` [ 38/82] ACPI processor: Fix tick_broadcast_mask online/offline regression Greg Kroah-Hartman
2012-08-13 20:19 ` [ 39/82] mISDN: Bugfix for layer2 fixed TEI mode Greg Kroah-Hartman
2012-08-13 20:19 ` [ 40/82] mac80211: cancel mesh path timer Greg Kroah-Hartman
2012-08-13 20:19 ` [ 41/82] ath9k: Add PID/VID support for AR1111 Greg Kroah-Hartman
2012-08-13 20:19 ` [ 42/82] wireless: reg: restore previous behaviour of chan->max_power calculations Greg Kroah-Hartman
2012-08-13 20:19 ` [ 43/82] x86, nops: Missing break resulting in incorrect selection on Intel Greg Kroah-Hartman
2012-08-13 20:19 ` [ 44/82] x86-64, kcmp: The kcmp system call can be common Greg Kroah-Hartman
2012-08-13 20:19 ` [ 45/82] Input: synaptics - handle out of bounds values from the hardware Greg Kroah-Hartman
2012-08-13 20:19 ` Greg Kroah-Hartman [this message]
2012-08-13 20:19 ` [ 47/82] random: use lockless techniques in the interrupt path Greg Kroah-Hartman
2012-08-13 20:19 ` [ 48/82] random: create add_device_randomness() interface Greg Kroah-Hartman
2012-08-13 20:19 ` [ 49/82] usb: feed USB device information to the /dev/random driver Greg Kroah-Hartman
2012-08-13 20:19 ` [ 50/82] net: feed /dev/random with the MAC address when registering a device Greg Kroah-Hartman
2012-08-13 20:19 ` [ 51/82] random: use the arch-specific rng in xfer_secondary_pool Greg Kroah-Hartman
2012-08-13 20:19 ` [ 52/82] random: add new get_random_bytes_arch() function Greg Kroah-Hartman
2012-08-13 20:19 ` [ 53/82] random: add tracepoints for easier debugging and verification Greg Kroah-Hartman
2012-08-13 20:19 ` [ 54/82] MAINTAINERS: Theodore Tso is taking over the random driver Greg Kroah-Hartman
2012-08-13 20:19 ` [ 55/82] rtc: wm831x: Feed the write counter into device_add_randomness() Greg Kroah-Hartman
2012-08-13 20:19 ` [ 56/82] mfd: wm831x: Feed the device UUID " Greg Kroah-Hartman
2012-08-13 20:19 ` [ 57/82] random: remove rand_initialize_irq() Greg Kroah-Hartman
2012-08-13 20:19 ` [ 58/82] random: Add comment to random_initialize() Greg Kroah-Hartman
2012-08-13 20:19 ` [ 59/82] dmi: Feed DMI table to /dev/random driver Greg Kroah-Hartman
2012-08-13 20:19 ` [ 60/82] random: mix in architectural randomness in extract_buf() Greg Kroah-Hartman
2012-08-13 20:19 ` [ 61/82] HID: multitouch: add support for Novatek touchscreen Greg Kroah-Hartman
2012-08-13 20:19 ` [ 62/82] HID: add support for Cypress barcode scanner 04B4:ED81 Greg Kroah-Hartman
2012-08-13 20:19 ` [ 63/82] HID: add ASUS AIO keyboard model AK1D Greg Kroah-Hartman
2012-08-13 20:19 ` [ 64/82] mm: hugetlbfs: close race during teardown of hugetlbfs shared page tables Greg Kroah-Hartman
2012-08-13 20:19 ` [ 65/82] target: Add range checking to UNMAP emulation Greg Kroah-Hartman
2012-08-13 20:19 ` [ 66/82] target: Fix reading of data length fields for UNMAP commands Greg Kroah-Hartman
2012-08-13 20:19 ` [ 67/82] target: Fix possible integer underflow in UNMAP emulation Greg Kroah-Hartman
2012-08-13 20:19 ` [ 68/82] target: Check number of unmap descriptors against our limit Greg Kroah-Hartman
2012-08-13 20:19 ` [ 69/82] ARM: clk-imx31: Fix the keypad clock name Greg Kroah-Hartman
2012-08-13 20:19 ` [ 70/82] ARM: imx: enable emi_slow_gate clock for imx5 Greg Kroah-Hartman
2012-08-13 20:19 ` [ 71/82] ARM: mxs: Remove MMAP_MIN_ADDR setting from mxs_defconfig Greg Kroah-Hartman
2012-08-13 20:19 ` [ 72/82] ARM: dts: imx53-ard: add regulators for lan9220 Greg Kroah-Hartman
2012-08-13 20:19 ` [ 73/82] ARM: pxa: remove irq_to_gpio from ezx-pcap driver Greg Kroah-Hartman
2012-08-13 20:19 ` [ 74/82] cfg80211: process pending events when unregistering net device Greg Kroah-Hartman
2012-08-13 20:19 ` [ 75/82] printk: Fix calculation of length used to discard records Greg Kroah-Hartman
2012-08-13 20:19 ` [ 76/82] tun: dont zeroize sock->file on detach Greg Kroah-Hartman
2012-08-13 20:19 ` [ 77/82] Yama: higher restrictions should block PTRACE_TRACEME Greg Kroah-Hartman
2012-08-13 20:19 ` [ 78/82] iwlwifi: disable greenfield transmissions as a workaround Greg Kroah-Hartman
2012-08-13 20:19 ` [ 79/82] e1000e: NIC goes up and immediately goes down Greg Kroah-Hartman
2012-08-13 20:19 ` [ 80/82] Input: eeti_ts: pass gpio value instead of IRQ Greg Kroah-Hartman
2012-08-13 20:19 ` [ 81/82] Input: wacom - Bamboo One 1024 pressure fix Greg Kroah-Hartman
2012-08-13 20:19 ` [ 82/82] rt61pci: fix NULL pointer dereference in config_lna_gain Greg Kroah-Hartman
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=20120813201750.477794151@linuxfoundation.org \
--to=gregkh@linuxfoundation.org \
--cc=akpm@linux-foundation.org \
--cc=alan@lxorguk.ukuu.org.uk \
--cc=ewust@umich.edu \
--cc=jhalderm@umich.edu \
--cc=linux-kernel@vger.kernel.org \
--cc=nadiah@cs.ucsd.edu \
--cc=stable@vger.kernel.org \
--cc=torvalds@linux-foundation.org \
--cc=tytso@mit.edu \
--cc=zakir@umich.edu \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.