3.0.41-stable review
Subsystems (32)
Greg Kroah-Hartman
maintainercover 3.0.41-stable review
From: Greg KH <[email protected]>
This is the start of the stable review cycle for the 3.0.41 release. There are 44 patches in this series, all will be posted as a response to this one. If anyone has any issues with these being applied, please let me know.
Responses should be made by Wed Aug 15 22:01:40 UTC 2012. Anything received after that time might be too late.
The whole patch series can be found in one patch at:
kernel.org/pub/linux/kernel/v3.0/stable-review/patch-3.0.41-rc1.gz
and the diffstat can be found below.
thanks,
greg k-h
-------------
MAINTAINERS | 2 +- Makefile | 4 +- arch/arm/configs/mxs_defconfig | 1 - arch/arm/include/asm/cacheflush.h | 8 +- arch/arm/include/asm/mutex.h | 119 +---------- arch/arm/mm/tlb-v7.S | 12 ++ arch/arm/vfp/vfpmodule.c | 6 + arch/ia64/include/asm/atomic.h | 4 +- arch/ia64/kernel/irq_ia64.c | 1 - arch/x86/kernel/alternative.c | 2 +- arch/x86/kernel/microcode_core.c | 31 ++- drivers/char/mspec.c | 2 +- drivers/char/random.c | 374 ++++++++++++++++++++++----------- drivers/firmware/dmi_scan.c | 3 + drivers/firmware/pcdp.c | 4 +- drivers/input/tablet/wacom_wac.c | 2 +- drivers/mfd/ab3100-core.c | 5 - drivers/mfd/ab3550-core.c | 2 - drivers/mfd/ezx-pcap.c | 2 +- drivers/mfd/wm831x-otp.c | 8 + drivers/net/e1000e/82571.c | 4 +- drivers/net/wireless/rt2x00/rt61pci.c | 3 +- drivers/rtc/rtc-wm831x.c | 24 ++- drivers/usb/core/hub.c | 9 + fs/nilfs2/ioctl.c | 4 +- fs/nilfs2/super.c | 3 + fs/nilfs2/the_nilfs.c | 1 + fs/nilfs2/the_nilfs.h | 2 + include/linux/irqdesc.h | 1 - include/linux/mfd/ezx-pcap.h | 1 + include/linux/random.h | 19 +- include/trace/events/random.h | 134 ++++++++++++ kernel/irq/handle.c | 7 +- kernel/irq/manage.c | 17 -- mm/hugetlb.c | 25 ++- mm/memory-failure.c | 6 +- mm/mmu_notifier.c | 45 ++-- net/core/dev.c | 3 + net/core/rtnetlink.c | 1 + net/mac80211/mesh.c | 1 + net/sunrpc/rpcb_clnt.c | 4 +- net/wireless/core.c | 5 + net/wireless/core.h | 1 + net/wireless/util.c | 5 +- sound/pci/hda/patch_conexant.c | 1 - 45 files changed, 589 insertions(+), 329 deletions(-)
Greg Kroah-Hartman
maintainerPATCH 1/44 Redefine ATOMIC_INIT and ATOMIC64_INIT to drop the casts
From: Greg KH <[email protected]>
3.0-stable review patch. If anyone has any objections, please let me know.
------------------
From: Tony Luck <[email protected]>
commit a119365586b0130dfea06457f584953e0ff6481d upstream.
The following build error occured during a ia64 build with swap-over-NFS patches applied.
net/core/sock.c:274:36: error: initializer element is not constant net/core/sock.c:274:36: error: (near initialization for 'memalloc_socks') net/core/sock.c:274:36: error: initializer element is not constant
This is identical to a parisc build error. Fengguang Wu, Mel Gorman and James Bottomley did all the legwork to track the root cause of the problem. This fix and entire commit log is shamelessly copied from them with one extra detail to change a dubious runtime use of ATOMIC_INIT() to atomic_set() in drivers/char/mspec.c
Dave Anglin says:
Quoted 4 lines
Here is the line in sock.i:
struct
static_keymemalloc_socks= ((structstatic_key) { .enabled = ((atomic_t) { (0) }) });
The above line contains two compound literals. It also uses a designated initializer to initialize the field enabled. A compound literal is not a constant expression.
The location of the above statement isn't fully clear, but if a compound literal occurs outside the body of a function, the initializer list must consist of constant expressions.
--- arch/ia64/include/asm/atomic.h | 4 ++-- drivers/char/mspec.c | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-)
arch/ia64/include/asm/atomic.h +2 -2
@@ -18,8 +18,8 @@#include <asm/system.h> -#define ATOMIC_INIT (i) ((atomic_t) { (i) }) -#define ATOMIC64_INIT (i) ((atomic64_t) { (i) }) +#define ATOMIC_INIT (i) { (i) } +#define ATOMIC64_INIT (i) { (i) }#define atomic_read (v) (*(volatile int *)&(v)->counter)#define atomic64_read (v) (*(volatile long *)&(v)->counter)
drivers/char/mspec.c +1 -1
@@ -284,7 +284,7 @@ mspec_mmap(struct file *file, struct vm_ vdata->flags = flags; vdata->type = type;spin_lock_init (&vdata->lock); - vdata->refcnt =ATOMIC_INIT (1 ); +atomic_set (&vdata->refcnt,1 ); vma->vm_private_data = vdata; vma->vm_flags |= (VM_IO |VM_RESERVED |VM_PFNMAP |VM_DONTEXPAND );
Greg Kroah-Hartman
maintainerPATCH 2/44 SUNRPC: return negative value in case rpcbind client creation error
In reply to Greg Kroah-HartmanFrom: Greg KH <[email protected]>
3.0-stable review patch. If anyone has any objections, please let me know.
------------------
From: Stanislav Kinsbursky <[email protected]>
commit caea33da898e4e14f0ba58173e3b7689981d2c0b upstream.
Without this patch kernel will panic on LockD start, because lockd_up() checks lockd_up_net() result for negative value.
Quoted 1 line
From my pow it's better to return negative value from rpcbind routines instead
of replacing all such checks like in lockd_up().
--- net/sunrpc/rpcb_clnt.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-)
net/sunrpc/rpcb_clnt.c +2 -2
@@ -193,7 +193,7 @@ static int rpcb_create_local_unix(void)if (IS_ERR (clnt)) {dprintk ("RPC: failed to create AF_LOCAL rpcbind " "client (errno %ld).\n" ,PTR_ERR (clnt)); - result = -PTR_ERR (clnt); + result =PTR_ERR (clnt); goto out; }
@@ -242,7 +242,7 @@ static int rpcb_create_local_net(void)if (IS_ERR (clnt)) {dprintk ("RPC: failed to create local rpcbind " "client (errno %ld).\n" ,PTR_ERR (clnt)); - result = -PTR_ERR (clnt); + result =PTR_ERR (clnt); goto out; }
Greg Kroah-Hartman
maintainerPATCH 3/44 nilfs2: fix deadlock issue between chcp and thaw ioctls
In reply to Greg Kroah-HartmanFrom: Greg KH <[email protected]>
3.0-stable review patch. If anyone has any objections, please let me know.
------------------
From: Ryusuke Konishi <[email protected]>
commit 572d8b3945a31bee7c40d21556803e4807fd9141 upstream.
An fs-thaw ioctl causes deadlock with a chcp or mkcp -s command:
chcp D ffff88013870f3d0 0 1325 1324 0x00000004
...
Call Trace: nilfs_transaction_begin+0x11c/0x1a0 [nilfs2] wake_up_bit+0x20/0x20 copy_from_user+0x18/0x30 [nilfs2] nilfs_ioctl_change_cpmode+0x7d/0xcf [nilfs2] nilfs_ioctl+0x252/0x61a [nilfs2] do_page_fault+0x311/0x34c get_unmapped_area+0x132/0x14e do_vfs_ioctl+0x44b/0x490 __set_task_blocked+0x5a/0x61 vm_mmap_pgoff+0x76/0x87 __set_current_blocked+0x30/0x4a sys_ioctl+0x4b/0x6f system_call_fastpath+0x16/0x1b thaw D ffff88013870d890 0 1352 1351 0x00000004 ... Call Trace: rwsem_down_failed_common+0xdb/0x10f call_rwsem_down_write_failed+0x13/0x20 down_write+0x25/0x27 thaw_super+0x13/0x9e do_vfs_ioctl+0x1f5/0x490 vm_mmap_pgoff+0x76/0x87 sys_ioctl+0x4b/0x6f filp_close+0x64/0x6c system_call_fastpath+0x16/0x1b
where the thaw ioctl deadlocked at thaw_super() when called while chcp was waiting at nilfs_transaction_begin() called from nilfs_ioctl_change_cpmode(). This deadlock is 100% reproducible.
This is because nilfs_ioctl_change_cpmode() first locks sb->s_umount in read mode and then waits for unfreezing in nilfs_transaction_begin(), whereas thaw_super() locks sb->s_umount in write mode. The locking of sb->s_umount here was intended to make snapshot mounts and the downgrade of snapshots to checkpoints exclusive.
This fixes the deadlock issue by replacing the sb->s_umount usage in nilfs_ioctl_change_cpmode() with a dedicated mutex which protects snapshot mounts.
--- fs/nilfs2/ioctl.c | 4 ++-- fs/nilfs2/super.c | 3 +++ fs/nilfs2/the_nilfs.c | 1 + fs/nilfs2/the_nilfs.h | 2 ++ 4 files changed, 8 insertions(+), 2 deletions(-)
fs/nilfs2/ioctl.c +2 -2
@@ -182,7 +182,7 @@ static int nilfs_ioctl_change_cpmode(strif (copy_from_user (&cpmode, argp,sizeof (cpmode))) goto out; -down_read (&inode->i_sb->s_umount); +mutex_lock (&nilfs->ns_snapshot_mount_mutex);nilfs_transaction_begin (inode->i_sb, &ti,0 ); ret = nilfs_cpfile_change_cpmode(
@@ -192,7 +192,7 @@ static int nilfs_ioctl_change_cpmode(strelse nilfs_transaction_commit (inode->i_sb);/* never fails */ -up_read (&inode->i_sb->s_umount); +mutex_unlock (&nilfs->ns_snapshot_mount_mutex); out:mnt_drop_write (filp->f_path.mnt);return ret;
fs/nilfs2/super.c +3 -0
@@ -951,6 +951,8 @@ static int nilfs_attach_snapshot(structstruct nilfs_root *root;int ret; +mutex_lock (&nilfs->ns_snapshot_mount_mutex); +down_read (&nilfs->ns_segctor_sem); ret =nilfs_cpfile_is_snapshot (nilfs->ns_cpfile, cno);up_read (&nilfs->ns_segctor_sem);
@@ -975,6 +977,7 @@ static int nilfs_attach_snapshot(struct ret =nilfs_get_root_dentry (s, root, root_dentry);nilfs_put_root (root); out: +mutex_unlock (&nilfs->ns_snapshot_mount_mutex);return ret; }
fs/nilfs2/the_nilfs.c +1 -0
@@ -76,6 +76,7 @@ struct the_nilfs *alloc_nilfs(struct blo nilfs->ns_bdev = bdev;atomic_set (&nilfs->ns_ndirtyblks,0 );init_rwsem (&nilfs->ns_sem); +mutex_init (&nilfs->ns_snapshot_mount_mutex);INIT_LIST_HEAD (&nilfs->ns_dirty_files);INIT_LIST_HEAD (&nilfs->ns_gc_inodes);spin_lock_init (&nilfs->ns_inode_lock);
fs/nilfs2/the_nilfs.h +2 -0
@@ -47,6 +47,7 @@ enum {* @ns_flags: flags * @ns_bdev: block device * @ns_sem: semaphore for shared states +* @ns_snapshot_mount_mutex: mutex to protect snapshot mounts * @ns_sbh: buffer heads of on-disk super blocks * @ns_sbp: pointers to super block data * @ns_sbwtime: previous write time of super block
@@ -99,6 +100,7 @@ struct the_nilfs {struct block_device *ns_bdev;struct rw_semaphore ns_sem; +struct mutex ns_snapshot_mount_mutex;/* * used for
Greg Kroah-Hartman
maintainerPATCH 4/44 pcdp: use early_ioremap/early_iounmap to access pcdp table
In reply to Greg Kroah-HartmanFrom: Greg KH <[email protected]>
3.0-stable review patch. If anyone has any objections, please let me know.
------------------
From: Greg Pearson <[email protected]>
commit 6c4088ac3a4d82779903433bcd5f048c58fb1aca upstream.
efi_setup_pcdp_console() is called during boot to parse the HCDP/PCDP EFI system table and setup an early console for printk output. The routine uses ioremap/iounmap to setup access to the HCDP/PCDP table information.
The call to ioremap is happening early in the boot process which leads to a panic on x86_64 systems:
panic+0x01ca
do_exit+0x043c
oops_end+0x00a7
no_context+0x0119
__bad_area_nosemaphore+0x0138
bad_area_nosemaphore+0x000e
do_page_fault+0x0321
page_fault+0x0020
reserve_memtype+0x02a1
__ioremap_caller+0x0123
ioremap_nocache+0x0012
efi_setup_pcdp_console+0x002b
setup_arch+0x03a9
start_kernel+0x00d4
x86_64_start_reservations+0x012c
x86_64_start_kernel+0x00feThis replaces the calls to ioremap/iounmap in efi_setup_pcdp_console() with calls to early_ioremap/early_iounmap which can be called during early boot.
This patch was tested on an x86_64 prototype system which uses the HCDP/PCDP table for early console setup.
--- drivers/firmware/pcdp.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-)
drivers/firmware/pcdp.c +2 -2
@@ -95,7 +95,7 @@ efi_setup_pcdp_console(char *cmdline)if (efi.hcdp ==EFI_INVALID_TABLE_ADDR )return -ENODEV ; - pcdp =ioremap (efi.hcdp,4096 ); + pcdp =early_ioremap (efi.hcdp,4096 );printk (KERN_INFO "PCDP: v%d at 0x%lx\n" , pcdp->rev, efi.hcdp);if (strstr (cmdline,"console=hcdp" )) {
@@ -131,6 +131,6 @@ efi_setup_pcdp_console(char *cmdline) } out: -iounmap (pcdp); +early_iounmap (pcdp,4096 );return rc; }
Greg Kroah-Hartman
maintainerPATCH 5/44 mm: fix wrong argument of migrate_huge_pages() in soft_offline_huge_page()
In reply to Greg Kroah-HartmanFrom: Greg KH <[email protected]>
3.0-stable review patch. If anyone has any objections, please let me know.
------------------
From: Joonsoo Kim <[email protected]>
commit dc32f63453f56d07a1073a697dcd843dd3098c09 upstream.
Commit a6bc32b89922 ("mm: compaction: introduce sync-light migration for use by compaction") changed the declaration of migrate_pages() and migrate_huge_pages().
But it missed changing the argument of migrate_huge_pages() in soft_offline_huge_page(). In this case, we should call migrate_huge_pages() with MIGRATE_SYNC.
Additionally, there is a mismatch between type the of argument and the function declaration for migrate_pages().
--- mm/memory-failure.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-)
mm/memory-failure.c +3 -3
@@ -1334,8 +1334,8 @@ static int soft_offline_huge_page(struct/* Keep page count to indicate a given hugepage is isolated. */ list_add (&hpage->lru, &pagelist); - ret =migrate_huge_pages (&pagelist, new_page,MPOL_MF_MOVE_ALL ,0 , - true); + ret =migrate_huge_pages (&pagelist, new_page,MPOL_MF_MOVE_ALL , false, +MIGRATE_SYNC );if (ret) {struct page *page1, *page2;list_for_each_entry_safe (page1, page2, &pagelist, lru)
@@ -1464,7 +1464,7 @@ int soft_offline_page(struct page *page, page_is_file_cache(page));list_add (&page->lru, &pagelist); ret =migrate_pages (&pagelist, new_page,MPOL_MF_MOVE_ALL , -0 ,MIGRATE_SYNC ); + false,MIGRATE_SYNC );if (ret) {putback_lru_pages (&pagelist); pr_info("soft offline: %#lx: migration failed %d, type %lx\n",
Greg Kroah-Hartman
maintainerPATCH 6/44 ARM: 7467/1: mutex: use generic xchg-based implementation for ARMv6+
In reply to Greg Kroah-HartmanFrom: Greg KH <[email protected]>
3.0-stable review patch. If anyone has any objections, please let me know.
------------------
From: Will Deacon <[email protected]>
commit a76d7bd96d65fa5119adba97e1b58d95f2e78829 upstream.
The open-coded mutex implementation for ARMv6+ cores suffers from a severe lack of barriers, so in the uncontended case we don't actually protect any accesses performed during the critical section.
Furthermore, the code is largely a duplication of the ARMv6+ atomic_dec code but optimised to remove a branch instruction, as the mutex fastpath was previously inlined. Now that this is executed out-of-line, we can reuse the atomic access code for the locking (in fact, we use the xchg code as this produces shorter critical sections).
This patch uses the generic xchg based implementation for mutexes on ARMv6+, which introduces barriers to the lock/unlock operations and also has the benefit of removing a fair amount of inline assembly code.
--- arch/arm/include/asm/mutex.h | 119 +------------------------------------------ 1 file changed, 4 insertions(+), 115 deletions(-)
arch/arm/include/asm/mutex.h +4 -115
@@ -7,121 +7,10 @@*/ #ifndef _ASM_MUTEX_H#define _ASM_MUTEX_H - -#if __LINUX_ARM_ARCH__ <6 -/* On pre-ARMv6 hardware the swp based implementation is the most efficient. */ -# include <asm-generic/mutex-xchg.h> -#else -/* -* Attempting to lock a mutex on ARMv6+ can be done with a bastardized -* atomic decrement (it is not a reliable atomic decrement but it satisfies -* the defined semantics for our purpose, while being smaller and faster -* than a real atomic decrement or atomic swap. The idea is to attempt -* decrementing the lock value only once. If once decremented it isn't zero, -* or if its store-back fails due to a dispute on the exclusive store, we -* simply bail out immediately through the slow path where the lock will be -* reattempted until it succeeds. +* On pre-ARMv6 hardware this results in a swp-based implementation, +* which is the most efficient. For ARMv6+, we emit a pair of exclusive +* accesses instead. */ -static inline void -__mutex_fastpath_lock (atomic_t *count,void (*fail_fn)(atomic_t *)) -{ -int __ex_flag, __res; - - __asm__ ( - -"ldrex %0, [%2] \n\t" -"sub %0, %0, #1 \n\t" -"strex %1, %0, [%2] " - - :"=&r" (__res),"=&r" (__ex_flag) - :"r" (&(count)->counter) - :"cc" ,"memory" ); - - __res |= __ex_flag; -if (unlikely (__res !=0 )) -fail_fn (count); -} - -static inline int -__mutex_fastpath_lock_retval (atomic_t *count,int (*fail_fn)(atomic_t *)) -{ -int __ex_flag, __res; - - __asm__ ( - -"ldrex %0, [%2] \n\t" -"sub %0, %0, #1 \n\t" -"strex %1, %0, [%2] " - - :"=&r" (__res),"=&r" (__ex_flag) - :"r" (&(count)->counter) - :"cc" ,"memory" ); - - __res |= __ex_flag; -if (unlikely (__res !=0 )) - __res =fail_fn (count); -return __res; -} - -/* -* Same trick is used for the unlock fast path. However the original value, -* rather than the result, is used to test for success in order to have -* better generated assembly. -*/ -static inline void -__mutex_fastpath_unlock (atomic_t *count,void (*fail_fn)(atomic_t *)) -{ -int __ex_flag, __res, __orig; - - __asm__ ( - -"ldrex %0, [%3] \n\t" -"add %1, %0, #1 \n\t" -"strex %2, %1, [%3] " - - :"=&r" (__orig),"=&r" (__res),"=&r" (__ex_flag) - :"r" (&(count)->counter) - :"cc" ,"memory" ); - - __orig |= __ex_flag; -if (unlikely (__orig !=0 )) -fail_fn (count); -} - -/* -* If the unlock was done on a contended lock, or if the unlock simply fails -* then the mutex remains locked. -*/ -#define __mutex_slowpath_needs_to_unlock () 1 - -/* -* For __mutex_fastpath_trylock we use another construct which could be -* described as a "single value cmpxchg". -* -* This provides the needed trylock semantics like cmpxchg would, but it is -* lighter and less generic than a true cmpxchg implementation. -*/ -static inline int -__mutex_fastpath_trylock (atomic_t *count,int (*fail_fn)(atomic_t *)) -{ -int __ex_flag, __res, __orig; - - __asm__ ( - -"1: ldrex %0, [%3] \n\t" -"subs %1, %0, #1 \n\t" -"strexeq %2, %1, [%3] \n\t" -"movlt %0, #0 \n\t" -"cmpeq %2, #0 \n\t" -"bgt 1b " - - :"=&r" (__orig),"=&r" (__res),"=&r" (__ex_flag) - :"r" (&count->counter) - :"cc" ,"memory" ); - -return __orig; -} - -#endif +#include <asm-generic/mutex-xchg.h> #endif
Re: [ 06/44] ARM: 7467/1: mutex: use generic xchg-based implementation for ARMv6+
Quoted 20 lines · Greg Kroah-Hartman
From: Greg KH <[email protected]>
3.0-stable review patch. If anyone has any objections, please let me know.
------------------
From: Will Deacon <[email protected]>
commit
a76d7bd96d65fa5119adba97e1b58d95f2e78829upstream.The open-coded mutex implementation for ARMv6+ cores suffers from a severe lack of barriers, so in the uncontended case we don't actually protect any accesses performed during the critical section.
Furthermore, the code is largely a duplication of the ARMv6+
atomic_deccode but optimised to remove a branch instruction, as the mutex fastpath was previously inlined. Now that this is executed out-of-line, we can reuse the atomic access code for the locking (in fact, we use the xchg code as this produces shorter critical sections).
Quoted 3 lines
This patch uses the generic xchg based implementation for mutexes on ARMv6+, which introduces barriers to the lock/unlock operations and also has the benefit of removing a fair amount of inline assembly code.
[...]
This should be deferred, same as in 3.4.y and 3.5.y.
Ben.
Signature · 2 lines
Ben Hutchings I say we take off; nuke the site from orbit. It's the only way to be sure.
Greg Kroah-Hartman
maintainerPATCH 7/44 ARM: 7477/1: vfp: Always save VFP state in vfp_pm_suspend on UP
In reply to Greg Kroah-HartmanFrom: Greg KH <[email protected]>
3.0-stable review patch. If anyone has any objections, please let me know.
------------------
From: Colin Cross <[email protected]>
commit 24b35521b8ddf088531258f06f681bb7b227bf47 upstream.
vfp_pm_suspend should save the VFP state in suspend after any lazy context switch. If it only saves when the VFP is enabled, the state can get lost when, on a UP system:
Thread 1 uses the VFP
Context switch occurs to thread 2, VFP is disabled but the
VFP context is not saved
Thread 2 initiates suspend
vfp_pm_suspend is called with the VFP disabled, and the unsaved
VFP context of Thread 1 in the registers
Modify vfp_pm_suspend to save the VFP context whenever vfp_current_hw_state is not NULL.
Includes a fix from Ido Yariv <[email protected]>, who pointed out that on SMP systems, the state pointer can be pointing to a freed task struct if a task exited on another cpu, fixed by using #ifndef CONFIG_SMP in the new if clause.
--- arch/arm/vfp/vfpmodule.c | 6 ++++++ 1 file changed, 6 insertions(+)
arch/arm/vfp/vfpmodule.c +6 -0
@@ -412,6 +412,12 @@ static int vfp_pm_suspend(void)/* disable, just in case */ fmxr (FPEXC ,fmrx (FPEXC ) & ~FPEXC_EN ); + }else if (vfp_current_hw_state[ti->cpu]) { +#ifndef CONFIG_SMP +fmxr (FPEXC , fpexc |FPEXC_EN ); +vfp_save_state (vfp_current_hw_state[ti->cpu], fpexc); +fmxr (FPEXC , fpexc); +#endif }/* clear any information we had about last context state */
Re: [ 07/44] ARM: 7477/1: vfp: Always save VFP state in vfp_pm_suspend on UP
Quoted 2 lines · Greg Kroah-Hartman
From: Greg KH <[email protected]>
[...]
arch/arm/vfp/vfpmodule.c static int vfp_pm_suspend(void) · line 420
Quoted 12 lines
arch/arm/vfp/vfpmodule.c +6
-0@@ -412,6 +412,12 @@ static int vfp_pm_suspend(void)/* disable, just in case */ fmxr (FPEXC ,fmrx (FPEXC ) & ~FPEXC_EN ); + }else if (vfp_current_hw_state[ti->cpu]) { +#ifndef CONFIG_SMP +fmxr (FPEXC , fpexc |FPEXC_EN ); +vfp_save_state (vfp_current_hw_state[ti->cpu], fpexc); +fmxr (FPEXC , fpexc); +#endif
This fails to build on 3.0:
linux-stable/arch/arm/vfp/vfpmodule.c: In function 'vfp_pm_suspend':linux-stable/arch/arm/vfp/vfpmodule.c:415:13: error: 'vfp_current_hw_state' undeclared (first use in this function) linux-stable/arch/arm/vfp/vfpmodule.c:415:13: note: each undeclared identifier is reported only once for each function it appears in make[3]: *** [arch/arm/vfp/vfpmodule.o] Error 1
In 3.0, vfp_current_hw_state was still named last_VFP_context, so I think just renaming should be enough to fix this.
Quoted 4 lines
arch/arm/vfp/vfpmodule.c +0
-0}/* clear any information we had about last context state */
Signature · 2 lines
[]'s Herton
Greg Kroah-Hartman
maintainerRe: [ 07/44] ARM: 7477/1: vfp: Always save VFP state in vfp_pm_suspend on UP
Quoted 19 lines · Herton Ronaldo Krzesinski
Quoted 2 lines · Greg Kroah-Hartman
From: Greg KH <[email protected]>
[...]
arch/arm/vfp/vfpmodule.c static int vfp_pm_suspend(void) · line 420
Quoted 12 lines
arch/arm/vfp/vfpmodule.c +6
-0@@ -412,6 +412,12 @@ static int vfp_pm_suspend(void)/* disable, just in case */ fmxr (FPEXC ,fmrx (FPEXC ) & ~FPEXC_EN ); + }else if (vfp_current_hw_state[ti->cpu]) { +#ifndef CONFIG_SMP +fmxr (FPEXC , fpexc |FPEXC_EN ); +vfp_save_state (vfp_current_hw_state[ti->cpu], fpexc); +fmxr (FPEXC , fpexc); +#endif This fails to build on 3.0:
Quoted 7 lines
linux-stable/arch/arm/vfp/vfpmodule.c: In function 'vfp_pm_suspend':linux-stable/arch/arm/vfp/vfpmodule.c:415:13: error: 'vfp_current_hw_state' undeclared (first use in this function)linux-stable/arch/arm/vfp/vfpmodule.c:415:13: note: each undeclared identifier is reported only once for each function it appears in make[3]: *** [arch/arm/vfp/vfpmodule.o] Error 1In 3.0,
vfp_current_hw_statewas still namedlast_VFP_context, so I think just renaming should be enough to fix this.
I'll remove the patch as it probably just shouldn't be there, right? If you think it should be in 3.0-stable, can you please send me a fixed up patch that you have tested that it at least builds properly?
thanks,
greg k-h
Re: [ 07/44] ARM: 7477/1: vfp: Always save VFP state in vfp_pm_suspend on UP
Quoted 25 lines · Greg Kroah-Hartman
Quoted 24 lines · Herton Ronaldo Krzesinski
Quoted 2 lines · Greg Kroah-Hartman
From: Greg KH <[email protected]>
[...]
arch/arm/vfp/vfpmodule.c static int vfp_pm_suspend(void) · line 420
Quoted 12 lines
arch/arm/vfp/vfpmodule.c +6
-0@@ -412,6 +412,12 @@ static int vfp_pm_suspend(void)/* disable, just in case */ fmxr (FPEXC ,fmrx (FPEXC ) & ~FPEXC_EN ); + }else if (vfp_current_hw_state[ti->cpu]) { +#ifndef CONFIG_SMP +fmxr (FPEXC , fpexc |FPEXC_EN ); +vfp_save_state (vfp_current_hw_state[ti->cpu], fpexc); +fmxr (FPEXC , fpexc); +#endif This fails to build on 3.0:
linux-stable/arch/arm/vfp/vfpmodule.c: In function 'vfp_pm_suspend':linux-stable/arch/arm/vfp/vfpmodule.c:415:13: error: 'vfp_current_hw_state' undeclared (first use in this function)linux-stable/arch/arm/vfp/vfpmodule.c:415:13: note: each undeclared identifier is reported only once for each function it appears in make[3]: *** [arch/arm/vfp/vfpmodule.o] Error 1
Quoted 6 lines
Quoted 2 lines
In 3.0,
vfp_current_hw_statewas still namedlast_VFP_context, so I think just renaming should be enough to fix this.I'll remove the patch as it probably just shouldn't be there, right? If you think it should be in 3.0-stable, can you please send me a fixed up patch that you have tested that it at least builds properly?
I'm not intimate with this ARM code, so I think someone else in Cc can answer better, I just saw it doesn't build with 3.0. If the same problem affects 3.0, then the change should be backported renaming vfp_current_hw_state to last_VFP_context. It seems the same code was there with vfp_current_hw_state still named as last_VFP_context, so looks like 3.0 would be affected as well.
Also I noted that because the same naming, 3.0 didn't got commit a84b895a2348f0dbff31b71ddf954f70a6cde368 ("ARM: 7476/1: vfp: only clear vfp state for current cpu in vfp_pm_suspend") as the patch would fail to apply on 3.0 code base, while 3.4.9 and 3.5.2 have it.
I assume someone who did these commits or know it/are affected can take a look and if needed backport them to 3.0?
Quoted 5 lines
thanks,
greg k-h
Signature · 2 lines
[]'s Herton
Greg Kroah-Hartman
maintainerPATCH 8/44 ARM: 7478/1: errata: extend workaround for erratum #720789
In reply to Greg Kroah-HartmanFrom: Greg KH <[email protected]>
3.0-stable review patch. If anyone has any objections, please let me know.
------------------
From: Will Deacon <[email protected]>
commit 5a783cbc48367cfc7b65afc75430953dfe60098f upstream.
Commit cdf357f1 ("ARM: 6299/1: errata: TLBIASIDIS and TLBIMVAIS operations can broadcast a faulty ASID") replaced by-ASID TLB flushing operations with all-ASID variants to workaround A9 erratum #720789.
This patch extends the workaround to include the tlb_range operations, which were overlooked by the original patch.
--- arch/arm/mm/tlb-v7.S | 12 ++++++++++++ 1 file changed, 12 insertions(+)
arch/arm/mm/tlb-v7.S +12 -0
@@ -38,11 +38,19 @@ ENTRY(v7wbi_flush_user_tlb_range) dsb mov r0, r0, lsr #PAGE_SHIFT @ align address mov r1, r1, lsr #PAGE_SHIFT +#ifdef CONFIG_ARM_ERRATA_720789 + mov r3, #0 +#else asid r3, r3 @ mask ASID +#endif orr r0, r3, r0, lsl #PAGE_SHIFT @ Create initial MVA mov r1, r1, lsl #PAGE_SHIFT 1: +#ifdef CONFIG_ARM_ERRATA_720789 + ALT_SMP(mcr p15, 0, r0, c8, c3, 3) @ TLB invalidate U MVA all ASID (shareable) +#else ALT_SMP(mcr p15, 0, r0, c8, c3, 1) @ TLB invalidate U MVA (shareable) +#endif ALT_UP(mcr p15, 0, r0, c8, c7, 1) @ TLB invalidate U MVA add r0, r0, #PAGE_SZ
@@ -70,7 +78,11 @@ ENTRY(v7wbi_flush_kern_tlb_range) mov r0, r0, lsl #PAGE_SHIFT mov r1, r1, lsl #PAGE_SHIFT 1: +#ifdef CONFIG_ARM_ERRATA_720789 + ALT_SMP(mcr p15, 0, r0, c8, c3, 3) @ TLB invalidate U MVA all ASID (shareable) +#else ALT_SMP(mcr p15, 0, r0, c8, c3, 1) @ TLB invalidate U MVA (shareable) +#endif ALT_UP(mcr p15, 0, r0, c8, c7, 1) @ TLB invalidate U MVA add r0, r0, #PAGE_SZ cmp r0, r1
Greg Kroah-Hartman
maintainerPATCH 9/44 ARM: 7479/1: mm: avoid NULL dereference when flushing gate_vma with VIVT caches
In reply to Greg Kroah-HartmanFrom: Greg KH <[email protected]>
3.0-stable review patch. If anyone has any objections, please let me know.
------------------
From: Will Deacon <[email protected]>
commit b74253f78400f9a4b42da84bb1de7540b88ce7c4 upstream.
The vivt_flush_cache_{range,page} functions check that the mm_struct of the VMA being flushed has been active on the current CPU before performing the cache maintenance.
The gate_vma has a NULL mm_struct pointer and, as such, will cause a kernel fault if we try to flush it with the above operations. This happens during ELF core dumps, which include the gate_vma as it may be useful for debugging purposes.
This patch adds checks to the VIVT cache flushing functions so that VMAs with a NULL mm_struct are flushed unconditionally (the vectors page may be dirty if we use it to store the current TLS pointer).
--- arch/arm/include/asm/cacheflush.h | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-)
arch/arm/include/asm/cacheflush.h +6 -2
@@ -215,7 +215,9 @@ static inline void vivt_flush_cache_mm(sstatic inline void vivt_flush_cache_range (struct vm_area_struct *vma,unsigned long start,unsigned long end) { -if (cpumask_test_cpu (smp_processor_id (),mm_cpumask (vma->vm_mm))) +struct mm_struct *mm = vma->vm_mm; + +if (!mm ||cpumask_test_cpu (smp_processor_id (),mm_cpumask (mm)))__cpuc_flush_user_range (start &PAGE_MASK ,PAGE_ALIGN (end), vma->vm_flags); }
@@ -223,7 +225,9 @@ vivt_flush_cache_range(struct vm_area_ststatic inline void vivt_flush_cache_page (struct vm_area_struct *vma,unsigned long user_addr,unsigned long pfn) { -if (cpumask_test_cpu (smp_processor_id (),mm_cpumask (vma->vm_mm))) { +struct mm_struct *mm = vma->vm_mm; + +if (!mm ||cpumask_test_cpu (smp_processor_id (),mm_cpumask (mm))) {unsigned long addr = user_addr &PAGE_MASK ;__cpuc_flush_user_range (addr, addr +PAGE_SIZE , vma->vm_flags); }
Greg Kroah-Hartman
maintainerPATCH 10/44 ALSA: hda - remove quirk for Dell Vostro 1015
In reply to Greg Kroah-HartmanFrom: Greg KH <[email protected]>
3.0-stable review patch. If anyone has any objections, please let me know.
------------------
From: David Henningsson <[email protected]>
commit e9fc83cb2e5877801a255a37ddbc5be996ea8046 upstream.
This computer is confirmed working with model=auto on kernel 3.2. Also, parsing fails with hda-emu with the current model.
--- sound/pci/hda/patch_conexant.c | 1 - 1 file changed, 1 deletion(-)
sound/pci/hda/patch_conexant.c +0 -1
@@ -3089,7 +3089,6 @@ static const struct snd_pci_quirk cxt506SND_PCI_QUIRK (0x1028 ,0x02d8 ,"Dell Vostro" ,CXT5066_DELL_VOSTRO ),SND_PCI_QUIRK (0x1028 ,0x02f5 ,"Dell Vostro 320" ,CXT5066_IDEAPAD ),SND_PCI_QUIRK (0x1028 ,0x0401 ,"Dell Vostro 1014" ,CXT5066_DELL_VOSTRO ), -SND_PCI_QUIRK (0x1028 ,0x0402 ,"Dell Vostro" ,CXT5066_DELL_VOSTRO ),SND_PCI_QUIRK (0x1028 ,0x0408 ,"Dell Inspiron One 19T" ,CXT5066_IDEAPAD ),SND_PCI_QUIRK (0x1028 ,0x050f ,"Dell Inspiron" ,CXT5066_IDEAPAD ), SND_PCI_QUIRK(0x1028, 0x0510, "Dell Vostro", CXT5066_IDEAPAD),
Re: [ 10/44] ALSA: hda - remove quirk for Dell Vostro 1015
Quoted 3 lines · Greg Kroah-Hartman
From: Greg KH <[email protected]>
3.0-stable review patch. If anyone has any objections, please let me know.
As my previous email states, I still object to this patch being applied to 3.0 (it is for 3.2+). Repeating that text now:
This patch will not work on 3.0 because there is no model=auto fallback, so please remove it from 3.0-stable-queue.
In the original patch [1], the cc to stable was written as this:
Is there a better way to specify what kernels it should and should not be applied to, as it doesn't seem to have worked in this case?
Signature · 2 lines
David Henningsson, Canonical Ltd. https://launchpad.net/~diwic
Re: [ 10/44] ALSA: hda - remove quirk for Dell Vostro 1015
At Tue, 14 Aug 2012 07:17:43 +0200,
Quoted 11 lines · David Henningsson
Quoted 3 lines · Greg Kroah-Hartman
From: Greg KH <[email protected]>
3.0-stable review patch. If anyone has any objections, please let me know.
As my previous email states, I still object to this patch being applied to 3.0 (it is for 3.2+). Repeating that text now:
This patch will not work on 3.0 because there is no model=auto fallback, so please remove it from 3.0-stable-queue.
Right, Greg, could you remove this patch from the 3.0 queue? This will cause a regression on 3.0.
thanks,
Takashi
Quoted 15 lines
In the original patch [1], the cc to stable was written as this:
Cc [email protected] (3.2+)Is there a better way to specify what kernels it should and should not be applied to, as it doesn't seem to have worked in this case?
Signature · 2 lines
David Henningsson, Canonical Ltd. https://launchpad.net/~diwic
Greg Kroah-Hartman
maintainerRe: [ 10/44] ALSA: hda - remove quirk for Dell Vostro 1015
In reply to David HenningssonQuoted 11 lines · David Henningsson
Quoted 3 lines · Greg Kroah-Hartman
From: Greg KH <[email protected]>
3.0-stable review patch. If anyone has any objections, please let me know.
As my previous email states, I still object to this patch being applied to 3.0 (it is for 3.2+). Repeating that text now:
This patch will not work on 3.0 because there is no model=auto fallback, so please remove it from 3.0-stable-queue.
Quoted 8 lines
In the original patch [1], the cc to stable was written as this:
Cc [email protected] (3.2+)Is there a better way to specify what kernels it should and should not be applied to, as it doesn't seem to have worked in this case?
No, that's my fault, sorry, I missed that marking and shouldn't have applied it there. I'll go remove it right now from the queue.
greg k-h
Greg Kroah-Hartman
maintainerPATCH 11/44 mm: mmu_notifier: fix freed page still mapped in secondary MMU
In reply to Greg Kroah-HartmanFrom: Greg KH <[email protected]>
3.0-stable review patch. If anyone has any objections, please let me know.
------------------
From: Xiao Guangrong <[email protected]>
commit 3ad3d901bbcfb15a5e4690e55350db0899095a68 upstream.
mmu_notifier_release() is called when the process is exiting. It will delete all the mmu notifiers. But at this time the page belonging to the process is still present in page tables and is present on the LRU list, so this race will happen:
CPU 0 CPU 1mmu_notifier_release: try_to_unmap:
hlist_del_init_rcu(&mn->hlist);
ptep_clear_flush_notify:
mmu nofifler not found
free page !!!!!!
/*
* At the point, the page has been
* freed, but it is still mapped in
* the secondary MMU.
*/
mn->ops->release(mn, mm);
Then the box is not stable and sometimes we can get this bug:
[ 738.075923] BUG: Bad page state in process migrate-perf pfn:03bec [ 738.075931] page:ffffea00000efb00 count:0 mapcount:0 mapping: (null) index:0x8076 [ 738.075936] page flags: 0x20000000000014(referenced|dirty)
The same issue is present in mmu_notifier_unregister().
We can call ->release before deleting the notifier to ensure the page has been unmapped from the secondary MMU before it is freed.
--- mm/mmu_notifier.c | 45 +++++++++++++++++++++++---------------------- 1 file changed, 23 insertions(+), 22 deletions(-)
mm/mmu_notifier.c +23 -22
@@ -33,6 +33,24 @@void __mmu_notifier_release (struct mm_struct *mm) {struct mmu_notifier *mn; +struct hlist_node *n; + +/* +* RCU here will block mmu_notifier_unregister until +* ->release returns. +*/ +rcu_read_lock (); +hlist_for_each_entry_rcu (mn, n, &mm->mmu_notifier_mm->list, hlist) +/* +* if ->release runs before mmu_notifier_unregister it +* must be handled as it's the only way for the driver +* to flush all existing sptes and stop the driver +* from establishing any more sptes before all the +* pages in the mm are freed. +*/ +if (mn->ops->release) + mn->ops->release (mn, mm); +rcu_read_unlock ();spin_lock (&mm->mmu_notifier_mm->lock);while (unlikely (!hlist_empty (&mm->mmu_notifier_mm->list))) {
@@ -46,23 +64,6 @@ void __mmu_notifier_release(struct mm_st* mmu_notifier_unregister to return. */ hlist_del_init_rcu (&mn->hlist); -/* -* RCU here will block mmu_notifier_unregister until -* ->release returns. -*/ -rcu_read_lock (); -spin_unlock (&mm->mmu_notifier_mm->lock); -/* -* if ->release runs before mmu_notifier_unregister it -* must be handled as it's the only way for the driver -* to flush all existing sptes and stop the driver -* from establishing any more sptes before all the -* pages in the mm are freed. -*/ -if (mn->ops->release) - mn->ops->release (mn, mm); -rcu_read_unlock (); -spin_lock (&mm->mmu_notifier_mm->lock); }spin_unlock (&mm->mmu_notifier_mm->lock);
@@ -284,16 +285,13 @@ void mmu_notifier_unregister(struct mmu_ {BUG_ON (atomic_read (&mm->mm_count) <=0 ); -spin_lock (&mm->mmu_notifier_mm->lock);if (!hlist_unhashed (&mn->hlist)) { -hlist_del_rcu (&mn->hlist); -/* * RCU here will force exit_mmap to wait ->release to finish * before freeing the pages. */ rcu_read_lock (); -spin_unlock (&mm->mmu_notifier_mm->lock); +/* * exit_mmap will block in mmu_notifier_release to * guarantee ->release is called before freeing the
@@ -302,8 +300,11 @@ void mmu_notifier_unregister(struct mmu_if (mn->ops->release) mn->ops->release (mn, mm);rcu_read_unlock (); - }else + +spin_lock (&mm->mmu_notifier_mm->lock); +hlist_del_rcu (&mn->hlist);spin_unlock (&mm->mmu_notifier_mm->lock); + }/* * Wait any running method to finish, of course including
Greg Kroah-Hartman
maintainerPATCH 12/44 mac80211: cancel mesh path timer
In reply to Greg Kroah-HartmanFrom: Greg KH <[email protected]>
3.0-stable review patch. If anyone has any objections, please let me know.
------------------
From: Johannes Berg <[email protected]>
commit dd4c9260e7f23f2e951cbfb2726e468c6d30306c upstream.
The mesh path timer needs to be canceled when leaving the mesh as otherwise it could fire after the interface has been removed already.
--- net/mac80211/mesh.c | 1 + 1 file changed, 1 insertion(+)
net/mac80211/mesh.c +1 -0
@@ -490,6 +490,7 @@ void ieee80211_stop_mesh(struct ieee8021del_timer_sync (&sdata->u.mesh.housekeeping_timer);del_timer_sync (&sdata->u.mesh.mesh_path_root_timer); +del_timer_sync (&sdata->u.mesh.mesh_path_timer);/* * If the timer fired while we waited for it, it will have * requeued the work. Now the work will be running again
Greg Kroah-Hartman
maintainerPATCH 13/44 x86, nops: Missing break resulting in incorrect selection on Intel
In reply to Greg Kroah-HartmanFrom: Greg KH <[email protected]>
3.0-stable review patch. If anyone has any objections, please let me know.
------------------
From: Alan Cox <[email protected]>
commit d6250a3f12edb3a86db9598ffeca3de8b4a219e9 upstream.
The Intel case falls through into the generic case which then changes the values. For cases like the P6 it doesn't do the right thing so this seems to be a screwup.
--- arch/x86/kernel/alternative.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
arch/x86/kernel/alternative.c +1 -1
@@ -220,7 +220,7 @@ void __init arch_init_ideal_nops(void) ideal_nops = intel_nops;#endif } - +break ;default :#ifdef CONFIG_X86_64 ideal_nops = k8_nops;
Greg Kroah-Hartman
maintainerPATCH 14/44 random: Add support for architectural random hooks
In reply to Greg Kroah-HartmanFrom: Greg KH <[email protected]>
3.0-stable review patch. If anyone has any objections, please let me know.
------------------
From: "H. Peter Anvin" <[email protected]>
commit 63d77173266c1791f1553e9e8ccea65dc87c4485 upstream.
Add support for architecture-specific hooks into the kernel-directed random number generator interfaces. This patchset does not use the architecture random number generator interfaces for the userspace-directed interfaces (/dev/random and /dev/urandom), thus eliminating the need to distinguish between them based on a pool pointer.
Changes in version 3:
- Moved the hooks from extract_entropy() to get_random_bytes().
- Changes the hooks to inlines.
--- drivers/char/random.c | 23 +++++++++++++++++++++-- include/linux/random.h | 13 +++++++++++++ 2 files changed, 34 insertions(+), 2 deletions(-)
drivers/char/random.c +21 -2
@@ -932,7 +932,21 @@ static ssize_t extract_entropy_user(stru*/ void get_random_bytes (void *buf,int nbytes) { -extract_entropy (&nonblocking_pool, buf, nbytes,0 ,0 ); +char *p = buf; + +while (nbytes) { +unsigned long v; +int chunk =min (nbytes, (int )sizeof (unsigned long )); + +if (!arch_get_random_long (&v)) +break ; + +memcpy (buf, &v, chunk); + p += chunk; + nbytes -= chunk; + } + +extract_entropy (&nonblocking_pool, p, nbytes,0 ,0 ); }EXPORT_SYMBOL (get_random_bytes);
@@ -1318,9 +1332,14 @@ late_initcall(random_int_secret_init);DEFINE_PER_CPU (__u32 [MD5_DIGEST_WORDS ], get_random_int_hash);unsigned int get_random_int (void ) { -__u32 *hash =get_cpu_var (get_random_int_hash); +__u32 *hash;unsigned int ret; +if (arch_get_random_int (&ret)) +return ret; + + hash =get_cpu_var (get_random_int_hash); + hash[0 ] += current->pid + jiffies +get_cycles ();md5_transform (hash, random_int_secret); ret = hash[0 ];
include/linux/random.h +13 -0
@@ -91,6 +91,19 @@ static inline void prandom32_seed(struct state->s3 =__seed (i,15 ); } +#ifdef CONFIG_ARCH_RANDOM +# include <asm/archrandom.h> +#else +static inline int arch_get_random_long (unsigned long *v) +{ +return 0 ; +} +static inline int arch_get_random_int (unsigned int *v) +{ +return 0 ; +} +#endif +#endif /* __KERNEL___ */ #endif /* _LINUX_RANDOM_H */
Greg Kroah-Hartman
maintainerPATCH 15/44 fix typo/thinko in get_random_bytes()
In reply to Greg Kroah-HartmanFrom: Greg KH <[email protected]>
3.0-stable review patch. If anyone has any objections, please let me know.
------------------
From: "Luck, Tony" <[email protected]>
commit bd29e568a4cb6465f6e5ec7c1c1f3ae7d99cbec1 upstream.
If there is an architecture-specific random number generator we use it to acquire randomness one "long" at a time. We should put these random words into consecutive words in the result buffer - not just overwrite the first word again and again.
--- drivers/char/random.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
drivers/char/random.c +1 -1
@@ -941,7 +941,7 @@ void get_random_bytes(void *buf, int nbyif (!arch_get_random_long (&v))break ; -memcpy (buf, &v, chunk); +memcpy (p, &v, chunk); p += chunk; nbytes -= chunk; }
Greg Kroah-Hartman
maintainerPATCH 16/44 random: Use arch_get_random_int instead of cycle counter if avail
In reply to Greg Kroah-HartmanFrom: Greg KH <[email protected]>
3.0-stable review patch. If anyone has any objections, please let me know.
------------------
From: Linus Torvalds <[email protected]>
commit cf833d0b9937874b50ef2867c4e8badfd64948ce upstream.
We still don't use rdrand in /dev/random, which just seems stupid. We accept the *cycle*counter* as a random input, but we don't accept rdrand? That's just broken.
Sure, people can do things in user space (write to /dev/random, use rdrand in addition to /dev/random themselves etc etc), but that *still* seems to be a particularly stupid reason for saying "we shouldn't bother to try to do better in /dev/random".
And even if somebody really doesn't trust rdrand as a source of random bytes, it seems singularly stupid to trust the cycle counter *more*.
So I'd suggest the attached patch. I'm not going to even bother arguing that we should add more bits to the entropy estimate, because that's not the point - I don't care if /dev/random fills up slowly or not, I think it's just stupid to not use the bits we can get from rdrand and mix them into the strong randomness pool.
--- drivers/char/random.c | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-)
drivers/char/random.c +6 -2
@@ -624,8 +624,8 @@ static struct timer_rand_state input_timstatic void add_timer_randomness (struct timer_rand_state *state,unsigned num) {struct { -cycles_t cycles;long jiffies; +unsigned cycles;unsigned num; } sample;long delta, delta2, delta3;
@@ -637,7 +637,11 @@ static void add_timer_randomness(struct goto out; sample.jiffies = jiffies; - sample.cycles =get_cycles (); + +/* Use arch random value, fall back to cycles */ +if (!arch_get_random_int (&sample.cycles)) + sample.cycles =get_cycles (); + sample.num = num;mix_pool_bytes (&input_pool, &sample,sizeof (sample));
Greg Kroah-Hartman
maintainerPATCH 17/44 random: Use arch-specific RNG to initialize the entropy store
In reply to Greg Kroah-HartmanFrom: Greg KH <[email protected]>
3.0-stable review patch. If anyone has any objections, please let me know.
------------------
From: Theodore Ts'o <[email protected]>
commit 3e88bdff1c65145f7ba297ccec69c774afe4c785 upstream.
If there is an architecture-specific random number generator (such as RDRAND for Intel architectures), use it to initialize /dev/random's entropy stores. Even in the worst case, if RDRAND is something like AES(NSA_KEY, counter++), it won't hurt, and it will definitely help against any other adversaries.
--- drivers/char/random.c | 6 ++++++ 1 file changed, 6 insertions(+)
drivers/char/random.c +6 -0
@@ -965,6 +965,7 @@ EXPORT_SYMBOL(get_random_bytes);*/ static void init_std_data (struct entropy_store *r) { +int i;ktime_t now;unsigned long flags;
@@ -974,6 +975,11 @@ static void init_std_data(struct entropy now =ktime_get_real ();mix_pool_bytes (r, &now,sizeof (now)); +for (i = r->poolinfo->poolwords; i; i--) { +if (!arch_get_random_long (&flags)) +break ; +mix_pool_bytes (r, &flags,sizeof (flags)); + }mix_pool_bytes (r,utsname (),sizeof (*(utsname ()))); }
Greg Kroah-Hartman
maintainerPATCH 18/44 random: Adjust the number of loops when initializing
In reply to Greg Kroah-HartmanFrom: Greg KH <[email protected]>
3.0-stable review patch. If anyone has any objections, please let me know.
------------------
From: "H. Peter Anvin" <[email protected]>
commit 2dac8e54f988ab58525505d7ef982493374433c3 upstream.
When we are initializing using arch_get_random_long() we only need to loop enough times to touch all the bytes in the buffer; using poolwords for that does twice the number of operations necessary on a 64-bit machine, since in the random number generator code "word" means 32 bits.
--- drivers/char/random.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
drivers/char/random.c +1 -1
@@ -975,7 +975,7 @@ static void init_std_data(struct entropy now =ktime_get_real ();mix_pool_bytes (r, &now,sizeof (now)); -for (i = r->poolinfo->poolwords; i; i--) { +for (i = r->poolinfo->POOLBYTES; i >0 ; i -=sizeof flags) {if (!arch_get_random_long (&flags))break ;mix_pool_bytes (r, &flags,sizeof (flags));
Greg Kroah-Hartman
maintainerPATCH 19/44 drivers/char/random.c: fix boot id uniqueness race
In reply to Greg Kroah-HartmanFrom: Greg KH <[email protected]>
3.0-stable review patch. If anyone has any objections, please let me know.
------------------
From: Mathieu Desnoyers <[email protected]>
commit 44e4360fa3384850d65dd36fb4e6e5f2f112709b upstream.
/proc/sys/kernel/random/boot_id can be read concurrently by userspace processes. If two (or more) user-space processes concurrently read boot_id when sysctl_bootid is not yet assigned, a race can occur making boot_id differ between the reads. Because the whole point of the boot id is to be unique across a kernel execution, fix this by protecting this operation with a spinlock.
Given that this operation is not frequently used, hitting the spinlock on each call should not be an issue.
--- drivers/char/random.c | 11 ++++++++--- 1 file changed, 8 insertions(+), 3 deletions(-)
drivers/char/random.c +8 -3
@@ -1260,10 +1260,15 @@ static int proc_do_uuid(ctl_table *table uuid = table->data;if (!uuid) { uuid = tmp_uuid; - uuid[8 ] =0 ; - } -if (uuid[8 ] ==0 )generate_random_uuid (uuid); + }else { +static DEFINE_SPINLOCK (bootid_spinlock); + +spin_lock (&bootid_spinlock); +if (!uuid[8 ]) +generate_random_uuid (uuid); +spin_unlock (&bootid_spinlock); + }sprintf (buf,"%pU" , uuid);
Greg Kroah-Hartman
maintainerPATCH 20/44 random: make add_interrupt_randomness() do something sane
In reply to Greg Kroah-HartmanFrom: Greg KH <[email protected]>
3.0-stable review patch. If anyone has any objections, please let me know.
------------------
From: Theodore Ts'o <[email protected]>
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.)
--- 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(-)
drivers/char/random.c +86 -17
@@ -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 entropmix_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 entropyspin_lock_irqsave (&r->lock, flags); r->entropy_count =0 ; + r->entropy_total =0 ;spin_unlock_irqrestore (&r->lock, flags); now =ktime_get_real ();
drivers/mfd/ab3100-core.c +0 -2
@@ -408,8 +408,6 @@ static irqreturn_t ab3100_irq_handler(inu32 fatevent;int err; -add_interrupt_randomness (irq); - err =ab3100_get_register_page_interruptible (ab3100,AB3100_EVENTA1 , event_regs,3 );if (err)
include/linux/random.h +1 -1
@@ -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 ]);
kernel/irq/handle.c +3 -4
@@ -117,7 +117,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;
@@ -145,7 +145,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 :
@@ -156,8 +156,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);
Greg Kroah-Hartman
maintainerPATCH 21/44 random: use lockless techniques in the interrupt path
In reply to Greg Kroah-HartmanFrom: Greg KH <[email protected]>
3.0-stable review patch. If anyone has any objections, please let me know.
------------------
From: Theodore Ts'o <[email protected]>
commit 902c098a3663de3fa18639efbb71b6080f0bcd3c upstream.
The real-time Linux folks don't like add_interrupt_randomness() taking a spinlock since it is called in the low-level interrupt routine. This also allows us to reduce the overhead in the fast path, for the random driver, which is the interrupt collection path.
--- drivers/char/random.c | 78 +++++++++++++++++++++++++------------------------- 1 file changed, 39 insertions(+), 39 deletions(-)
drivers/char/random.c +39 -39
@@ -418,9 +418,9 @@ struct entropy_store {/* read-write data: */ spinlock_t lock;unsigned add_ptr; +unsigned input_rotate;int entropy_count;int entropy_total; -int input_rotate; unsigned int initialized:1;__u8 last_data[EXTRACT_SIZE ]; };
@@ -468,26 +468,24 @@ static __u32 const twist_table[8] = {* it's cheap to do so and helps slightly in the expected case where * the entropy is concentrated in the low-order bits. */ -static void mix_pool_bytes_extract (struct entropy_store *r,const void *in, -int nbytes,__u8 out[64 ]) +static void __mix_pool_bytes (struct entropy_store *r,const void *in, +int nbytes,__u8 out[64 ]) {unsigned long i, j, tap1, tap2, tap3, tap4, tap5;int input_rotate;int wordmask = r->poolinfo->poolwords -1 ;const char *bytes = in;__u32 w; -unsigned long flags; -/* Taps are constant, so we can load them without holding r->lock. */ tap1 = r->poolinfo->tap1; tap2 = r->poolinfo->tap2; tap3 = r->poolinfo->tap3; tap4 = r->poolinfo->tap4; tap5 = r->poolinfo->tap5; -spin_lock_irqsave (&r->lock, flags); - input_rotate = r->input_rotate; - i = r->add_ptr; +smp_rmb (); + input_rotate =ACCESS_ONCE (r->input_rotate); + i =ACCESS_ONCE (r->add_ptr);/* mix one byte at a time to simplify size handling and churn faster */ while (nbytes--) {
@@ -514,19 +512,23 @@ static void mix_pool_bytes_extract(struc input_rotate += i ?7 :14 ; } - r->input_rotate = input_rotate; - r->add_ptr = i; +ACCESS_ONCE (r->input_rotate) = input_rotate; +ACCESS_ONCE (r->add_ptr) = i; +smp_wmb ();if (out)for (j =0 ; j <16 ; j++) ((__u32 *)out)[j] = r->pool[(i - j) & wordmask]; - -spin_unlock_irqrestore (&r->lock, flags); } -static void mix_pool_bytes (struct entropy_store *r,const void *in,int bytes) +static void mix_pool_bytes (struct entropy_store *r,const void *in, +int nbytes,__u8 out[64 ]) { -mix_pool_bytes_extract (r, in, bytes,NULL ); +unsigned long flags; + +spin_lock_irqsave (&r->lock, flags); +__mix_pool_bytes (r, in, nbytes, out); +spin_unlock_irqrestore (&r->lock, flags); }struct fast_pool {
@@ -564,23 +566,22 @@ static void fast_mix(struct fast_pool *f*/ static void credit_entropy_bits (struct entropy_store *r,int nbits) { -unsigned long flags; -int entropy_count; +int entropy_count, orig;if (!nbits)return ; -spin_lock_irqsave (&r->lock, flags); -DEBUG_ENT ("added %d entropy credits to %s\n" , nbits, r->name); - entropy_count = r->entropy_count; +retry: + entropy_count = orig =ACCESS_ONCE (r->entropy_count); entropy_count += nbits;if (entropy_count <0 ) {DEBUG_ENT ("negative entropy/overflow\n" ); entropy_count =0 ; }else if (entropy_count > r->poolinfo->POOLBITS) entropy_count = r->poolinfo->POOLBITS; - r->entropy_count = entropy_count; +if (cmpxchg (&r->entropy_count, orig, entropy_count) != orig) + goto retry;if (!r->initialized && nbits >0 ) { r->entropy_total += nbits;
@@ -593,7 +594,6 @@ static void credit_entropy_bits(struct ewake_up_interruptible (&random_read_wait);kill_fasync (&fasync,SIGIO ,POLL_IN ); } -spin_unlock_irqrestore (&r->lock, flags); }/*********************************************************************
@@ -680,7 +680,7 @@ static void add_timer_randomness(struct sample.cycles =get_cycles (); sample.num = num; -mix_pool_bytes (&input_pool, &sample,sizeof (sample)); +mix_pool_bytes (&input_pool, &sample,sizeof (sample),NULL );/* * Calculate number of bits of randomness we probably added.
@@ -764,7 +764,7 @@ void add_interrupt_randomness(int irq, i fast_pool->last = now; r = nonblocking_pool.initialized ? &input_pool : &nonblocking_pool; -mix_pool_bytes (r, &fast_pool->pool,sizeof (fast_pool->pool)); +__mix_pool_bytes (r, &fast_pool->pool,sizeof (fast_pool->pool),NULL );/* * If we don't have a valid cycle counter, and we see * back-to-back timer interrupts, then skip giving credit for
@@ -829,7 +829,7 @@ static void xfer_secondary_pool(struct e bytes =extract_entropy (r->pull, tmp, bytes, random_read_wakeup_thresh /8 , rsvd); -mix_pool_bytes (r, tmp, bytes); +mix_pool_bytes (r, tmp, bytes,NULL );credit_entropy_bits (r, bytes*8 ); } }
@@ -890,9 +890,11 @@ static void extract_buf(struct entropy_sint i;__u32 hash[5 ], workspace[SHA_WORKSPACE_WORDS ];__u8 extract[64 ]; +unsigned long flags;/* Generate a hash across the pool, 16 words (512 bits) at a time */ sha_init (hash); +spin_lock_irqsave (&r->lock, flags);for (i =0 ; i < r->poolinfo->poolwords; i +=16 )sha_transform (hash, (__u8 *)(r->pool + i), workspace);
@@ -905,7 +907,8 @@ static void extract_buf(struct entropy_s* brute-forcing the feedback as hard as brute-forcing the * hash. */ -mix_pool_bytes_extract (r, hash,sizeof (hash), extract); +__mix_pool_bytes (r, hash,sizeof (hash), extract); +spin_unlock_irqrestore (&r->lock, flags);/* * To avoid duplicates, we atomically extract a portion of the
@@ -928,11 +931,10 @@ static void extract_buf(struct entropy_s }static ssize_t extract_entropy (struct entropy_store *r,void *buf, -size_t nbytes,int min,int reserved) +size_t nbytes,int min,int reserved) {ssize_t ret =0 , i;__u8 tmp[EXTRACT_SIZE ]; -unsigned long flags;xfer_secondary_pool (r, nbytes); nbytes =account (r, nbytes, min, reserved);
@@ -941,6 +943,8 @@ static ssize_t extract_entropy(struct enextract_buf (r, tmp);if (fips_enabled) { +unsigned long flags; +spin_lock_irqsave (&r->lock, flags);if (!memcmp (tmp, r->last_data,EXTRACT_SIZE ))panic ("Hardware RNG duplicated output!\n" );
@@ -1034,22 +1038,18 @@ EXPORT_SYMBOL(get_random_bytes);static void init_std_data (struct entropy_store *r) {int i; -ktime_t now; -unsigned long flags; +ktime_t now =ktime_get_real (); +unsigned long rv; -spin_lock_irqsave (&r->lock, flags); r->entropy_count =0 ; r->entropy_total =0 ; -spin_unlock_irqrestore (&r->lock, flags); - - now =ktime_get_real (); -mix_pool_bytes (r, &now,sizeof (now)); -for (i = r->poolinfo->POOLBYTES; i >0 ; i -=sizeof flags) { -if (!arch_get_random_long (&flags)) +mix_pool_bytes (r, &now,sizeof (now),NULL ); +for (i = r->poolinfo->POOLBYTES; i >0 ; i -=sizeof (rv)) { +if (!arch_get_random_long (&rv))break ; -mix_pool_bytes (r, &flags,sizeof (flags)); +mix_pool_bytes (r, &rv,sizeof (rv),NULL ); } -mix_pool_bytes (r,utsname (),sizeof (*(utsname ()))); +mix_pool_bytes (r,utsname (),sizeof (*(utsname ())),NULL ); }static int rand_initialize (void )
@@ -1186,7 +1186,7 @@ write_pool(struct entropy_store *r, cons count -= bytes; p += bytes; -mix_pool_bytes (r, buf, bytes); +mix_pool_bytes (r, buf, bytes,NULL );cond_resched (); }
Greg Kroah-Hartman
maintainerPATCH 22/44 random: create add_device_randomness() interface
In reply to Greg Kroah-HartmanFrom: Greg KH <[email protected]>
3.0-stable review patch. If anyone has any objections, please let me know.
------------------
From: Linus Torvalds <[email protected]>
commit a2080a67abe9e314f9e9c2cc3a4a176e8a8f8793 upstream.
Add a new interface, add_device_randomness() for adding data to the random pool that is likely to differ between two devices (or possibly even per boot). This would be things like MAC addresses or serial numbers, or the read-out of the RTC. This does *not* add any actual entropy to the pool, but it initializes the pool to different values for devices that might otherwise be identical and have very little entropy available to them (particularly common in the embedded world).
[ Modified by tytso to mix in a timestamp, since there may be some
variability caused by the time needed to detect/configure the hardware in question. ]
--- drivers/char/random.c | 28 ++++++++++++++++++++++++++++ include/linux/random.h | 1 + 2 files changed, 29 insertions(+)
drivers/char/random.c +28 -0
@@ -125,11 +125,20 @@* The current exported interfaces for gathering environmental noise * from the devices are: * +* void add_device_randomness(const void *buf, unsigned int size); * void add_input_randomness(unsigned int type, unsigned int code, * unsigned int value); * void add_interrupt_randomness(int irq, int irq_flags); * void add_disk_randomness(struct gendisk *disk); * +* add_device_randomness() is for adding data to the random pool that +* is likely to differ between two devices (or possibly even per boot). +* This would be things like MAC addresses or serial numbers, or the +* read-out of the RTC. This does *not* add any actual entropy to the +* pool, but it initializes the pool to different values for devices +* that might otherwise be identical and have very little entropy +* available to them (particularly common in the embedded world). +* * add_input_randomness() uses the input layer interrupt timing, as well as * the event type information from the hardware. *
@@ -646,6 +655,25 @@ static void set_timer_rand_state(unsigne }#endif +/* +* Add device- or boot-specific data to the input and nonblocking +* pools to help initialize them to unique values. +* +* None of this adds any entropy, it is meant to avoid the +* problem of the nonblocking pool having similar initial state +* across largely identical devices. +*/ +void add_device_randomness (const void *buf,unsigned int size) +{ +unsigned long time =get_cycles () ^ jiffies; + +mix_pool_bytes (&input_pool, buf, size,NULL ); +mix_pool_bytes (&input_pool, &time,sizeof (time),NULL ); +mix_pool_bytes (&nonblocking_pool, buf, size,NULL ); +mix_pool_bytes (&nonblocking_pool, &time,sizeof (time),NULL ); +} +EXPORT_SYMBOL (add_device_randomness); +static struct timer_rand_state input_timer_state;/*
include/linux/random.h +1 -0
@@ -50,6 +50,7 @@ struct rnd_state {extern void rand_initialize_irq (int irq); +extern void add_device_randomness (const void *,unsigned int );extern void add_input_randomness (unsigned int type,unsigned int code,unsigned int value);extern void add_interrupt_randomness (int irq,int irq_flags);
Greg Kroah-Hartman
maintainerPATCH 23/44 usb: feed USB device information to the /dev/random driver
In reply to Greg Kroah-HartmanFrom: Greg KH <[email protected]>
3.0-stable review patch. If anyone has any objections, please let me know.
------------------
From: Theodore Ts'o <[email protected]>
commit b04b3156a20d395a7faa8eed98698d1e17a36000 upstream.
Send the USB device's serial, product, and manufacturer strings to the /dev/random driver to help seed its pools.
--- drivers/usb/core/hub.c | 9 +++++++++ 1 file changed, 9 insertions(+)
drivers/usb/core/hub.c +9 -0
@@ -24,6 +24,7 @@#include <linux/kthread.h> #include <linux/mutex.h> #include <linux/freezer.h> +#include <linux/random.h> #include <asm/uaccess.h> #include <asm/byteorder.h>
@@ -1902,6 +1903,14 @@ int usb_new_device(struct usb_device *ud/* Tell the world! */ announce_device (udev); +if (udev->serial) +add_device_randomness (udev->serial,strlen (udev->serial)); +if (udev->product) +add_device_randomness (udev->product,strlen (udev->product)); +if (udev->manufacturer) +add_device_randomness (udev->manufacturer, +strlen (udev->manufacturer)); +device_enable_async_suspend (&udev->dev);/* Register the device. The device driver is responsible * for configuring the device and invoking the add-device
Greg Kroah-Hartman
maintainerPATCH 24/44 net: feed /dev/random with the MAC address when registering a device
In reply to Greg Kroah-HartmanFrom: Greg KH <[email protected]>
3.0-stable review patch. If anyone has any objections, please let me know.
------------------
From: Theodore Ts'o <[email protected]>
commit 7bf2357524408b97fec58344caf7397f8140c3fd upstream.
--- net/core/dev.c | 3 +++ net/core/rtnetlink.c | 1 + 2 files changed, 4 insertions(+)
net/core/dev.c +3 -0
@@ -1163,6 +1163,7 @@ static int __dev_open(struct net_devicenet_dmaengine_get ();dev_set_rx_mode (dev);dev_activate (dev); +add_device_randomness (dev->dev_addr, dev->addr_len); }return ret;
@@ -4730,6 +4731,7 @@ int dev_set_mac_address(struct net_devic err = ops->ndo_set_mac_address (dev, sa);if (!err)call_netdevice_notifiers (NETDEV_CHANGEADDR , dev); +add_device_randomness (dev->dev_addr, dev->addr_len);return err; }EXPORT_SYMBOL (dev_set_mac_address);
@@ -5507,6 +5509,7 @@ int register_netdevice(struct net_devicedev_init_scheduler (dev);dev_hold (dev);list_netdevice (dev); +add_device_randomness (dev->dev_addr, dev->addr_len);/* Notify protocols, that a new device appeared. */ ret =call_netdevice_notifiers (NETDEV_REGISTER , dev);
net/core/rtnetlink.c +1 -0
@@ -1304,6 +1304,7 @@ static int do_setlink(struct net_device goto errout; send_addr_notify =1 ; modified =1 ; +add_device_randomness (dev->dev_addr, dev->addr_len); }if (tb[IFLA_MTU ]) {
Greg Kroah-Hartman
maintainerPATCH 25/44 random: use the arch-specific rng in xfer_secondary_pool
In reply to Greg Kroah-HartmanFrom: Greg KH <[email protected]>
3.0-stable review patch. If anyone has any objections, please let me know.
------------------
From: Theodore Ts'o <[email protected]>
commit e6d4947b12e8ad947add1032dd754803c6004824 upstream.
If the CPU supports a hardware random number generator, use it in xfer_secondary_pool(), where it will significantly improve things and where we can afford it.
Also, remove the use of the arch-specific rng in add_timer_randomness(), since the call is significantly slower than get_cycles(), and we're much better off using it in xfer_secondary_pool() anyway.
--- drivers/char/random.c | 25 ++++++++++++++++--------- 1 file changed, 16 insertions(+), 9 deletions(-)
drivers/char/random.c +16 -9
@@ -254,6 +254,7 @@#include <linux/cryptohash.h> #include <linux/fips.h> #include <linux/ptrace.h> +#include <linux/kmemcheck.h> #ifdef CONFIG_GENERIC_HARDIRQS # include <linux/irq.h>
@@ -702,11 +703,7 @@ static void add_timer_randomness(struct goto out; sample.jiffies = jiffies; - -/* Use arch random value, fall back to cycles */ -if (!arch_get_random_int (&sample.cycles)) - sample.cycles =get_cycles (); - + sample.cycles =get_cycles (); sample.num = num;mix_pool_bytes (&input_pool, &sample,sizeof (sample),NULL );
@@ -838,7 +835,11 @@ static ssize_t extract_entropy(struct en*/ static void xfer_secondary_pool (struct entropy_store *r,size_t nbytes) { -__u32 tmp[OUTPUT_POOL_WORDS ]; +union { +__u32 tmp[OUTPUT_POOL_WORDS ]; +long hwrand[4 ]; + } u; +int i;if (r->pull && r->entropy_count < nbytes *8 && r->entropy_count < r->poolinfo->POOLBITS) {
@@ -849,17 +850,23 @@ static void xfer_secondary_pool(struct e/* pull at least as many as BYTES as wakeup BITS */ bytes =max_t (int, bytes, random_read_wakeup_thresh /8 );/* but never more than the buffer size */ - bytes =min_t (int, bytes,sizeof (tmp)); + bytes =min_t (int, bytes,sizeof (u.tmp));DEBUG_ENT ("going to reseed %s with %d bits " "(%d of %d requested)\n" , r->name, bytes *8 , nbytes *8 , r->entropy_count); - bytes =extract_entropy (r->pull, tmp, bytes, + bytes =extract_entropy (r->pull, u.tmp, bytes, random_read_wakeup_thresh /8 , rsvd); -mix_pool_bytes (r, tmp, bytes,NULL ); +mix_pool_bytes (r, u.tmp, bytes,NULL );credit_entropy_bits (r, bytes*8 ); } +kmemcheck_mark_initialized (&u.hwrand,sizeof (u.hwrand)); +for (i =0 ; i <4 ; i++) +if (arch_get_random_long (&u.hwrand[i])) +break ; +if (i) +mix_pool_bytes (r, &u.hwrand,sizeof (u.hwrand),0 ); }/*
Greg Kroah-Hartman
maintainerPATCH 26/44 random: add new get_random_bytes_arch() function
In reply to Greg Kroah-HartmanFrom: Greg KH <[email protected]>
3.0-stable review patch. If anyone has any objections, please let me know.
------------------
From: Theodore Ts'o <[email protected]>
commit c2557a303ab6712bb6e09447df828c557c710ac9 upstream.
Create a new function, get_random_bytes_arch() which will use the architecture-specific hardware random number generator if it is present. Change get_random_bytes() to not use the HW RNG, even if it is avaiable.
The reason for this is that the hw random number generator is fast (if it is present), but it requires that we trust the hardware manufacturer to have not put in a back door. (For example, an increasing counter encrypted by an AES key known to the NSA.)
It's unlikely that Intel (for example) was paid off by the US Government to do this, but it's impossible for them to prove otherwise
--- especially since Bull Mountain is documented to use AES as a
whitener. Hence, the output of an evil, trojan-horse version of RDRAND is statistically indistinguishable from an RDRAND implemented to the specifications claimed by Intel. Short of using a tunnelling electronic microscope to reverse engineer an Ivy Bridge chip and disassembling and analyzing the CPU microcode, there's no way for us to tell for sure.
Since users of get_random_bytes() in the Linux kernel need to be able to support hardware systems where the HW RNG is not present, most time-sensitive users of this interface have already created their own cryptographic RNG interface which uses get_random_bytes() as a seed. So it's much better to use the HW RNG to improve the existing random number generator, by mixing in any entropy returned by the HW RNG into /dev/random's entropy pool, but to always _use_ /dev/random's entropy pool.
This way we get almost of the benefits of the HW RNG without any potential liabilities. The only benefits we forgo is the speed/performance enhancements --- and generic kernel code can't depend on depend on get_random_bytes() having the speed of a HW RNG anyway.
For those places that really want access to the arch-specific HW RNG, if it is available, we provide get_random_bytes_arch().
--- drivers/char/random.c | 27 +++++++++++++++++++++++---- include/linux/random.h | 1 + 2 files changed, 24 insertions(+), 4 deletions(-)
drivers/char/random.c +23 -4
@@ -1038,11 +1038,28 @@ static ssize_t extract_entropy_user(stru/* * This function is the exported kernel interface. It returns some -* number of good random numbers, suitable for seeding TCP sequence -* numbers, etc. +* number of good random numbers, suitable for key generation, seeding +* TCP sequence numbers, etc. It does not use the hw random number +* generator, if available; use get_random_bytes_arch() for that. */ void get_random_bytes (void *buf,int nbytes) { +extract_entropy (&nonblocking_pool, buf, nbytes,0 ,0 ); +} +EXPORT_SYMBOL (get_random_bytes); + +/* +* This function will use the architecture-specific hardware random +* number generator if it is available. The arch-specific hw RNG will +* almost certainly be faster than what we can do in software, but it +* is impossible to verify that it is implemented securely (as +* opposed, to, say, the AES encryption of a sequence number using a +* key known by the NSA). So it's useful if we need the speed, but +* only if we're willing to trust the hardware manufacturer not to +* have put in a back door. +*/ +void get_random_bytes_arch (void *buf,int nbytes) +{char *p = buf;while (nbytes) {
@@ -1057,9 +1074,11 @@ void get_random_bytes(void *buf, int nby nbytes -= chunk; } -extract_entropy (&nonblocking_pool, p, nbytes,0 ,0 ); +if (nbytes) +extract_entropy (&nonblocking_pool, p, nbytes,0 ,0 ); } -EXPORT_SYMBOL (get_random_bytes); +EXPORT_SYMBOL (get_random_bytes_arch); +/* * init_std_data - initialize pool with system data
include/linux/random.h +1 -0
@@ -56,6 +56,7 @@ extern void add_input_randomness(unsigneextern void add_interrupt_randomness (int irq,int irq_flags);extern void get_random_bytes (void *buf,int nbytes); +extern void get_random_bytes_arch (void *buf,int nbytes);void generate_random_uuid (unsigned char uuid_out[16 ]);#ifndef MODULE
Greg Kroah-Hartman
maintainerPATCH 27/44 random: add tracepoints for easier debugging and verification
In reply to Greg Kroah-HartmanFrom: Greg KH <[email protected]>
3.0-stable review patch. If anyone has any objections, please let me know.
------------------
From: Theodore Ts'o <[email protected]>
commit 00ce1db1a634746040ace24c09a4e3a7949a3145 upstream.
--- drivers/char/random.c | 26 ++++++-- include/trace/events/random.h | 134 ++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 156 insertions(+), 4 deletions(-)
drivers/char/random.c +22 -4
@@ -266,6 +266,9 @@#include <asm/irq_regs.h> #include <asm/io.h> +#define CREATE_TRACE_POINTS +#include <trace/events/random.h> +/* * Configuration information */
@@ -478,8 +481,8 @@ static __u32 const twist_table[8] = {* it's cheap to do so and helps slightly in the expected case where * the entropy is concentrated in the low-order bits. */ -static void __mix_pool_bytes (struct entropy_store *r,const void *in, -int nbytes,__u8 out[64 ]) +static void _mix_pool_bytes (struct entropy_store *r,const void *in, +int nbytes,__u8 out[64 ]) {unsigned long i, j, tap1, tap2, tap3, tap4, tap5;int input_rotate;
@@ -531,13 +534,21 @@ static void __mix_pool_bytes(struct entr ((__u32 *)out)[j] = r->pool[(i - j) & wordmask]; } -static void mix_pool_bytes (struct entropy_store *r,const void *in, +static void __mix_pool_bytes (struct entropy_store *r,const void *in,int nbytes,__u8 out[64 ]) { +trace_mix_pool_bytes_nolock (r->name, nbytes, _RET_IP_); +_mix_pool_bytes (r, in, nbytes, out); +} + +static void mix_pool_bytes (struct entropy_store *r,const void *in, +int nbytes,__u8 out[64 ]) +{unsigned long flags; +trace_mix_pool_bytes (r->name, nbytes, _RET_IP_);spin_lock_irqsave (&r->lock, flags); -__mix_pool_bytes (r, in, nbytes, out); +_mix_pool_bytes (r, in, nbytes, out);spin_unlock_irqrestore (&r->lock, flags); }
@@ -585,6 +596,7 @@ static void credit_entropy_bits(struct e retry: entropy_count = orig =ACCESS_ONCE (r->entropy_count); entropy_count += nbits; +if (entropy_count <0 ) {DEBUG_ENT ("negative entropy/overflow\n" ); entropy_count =0 ;
@@ -599,6 +611,9 @@ retry: r->initialized =1 ; } +trace_credit_entropy_bits (r->name, nbits, entropy_count, + r->entropy_total, _RET_IP_); +/* should we wake readers? */ if (r == &input_pool && entropy_count >= random_read_wakeup_thresh) {wake_up_interruptible (&random_read_wait);
@@ -971,6 +986,7 @@ static ssize_t extract_entropy(struct enssize_t ret =0 , i;__u8 tmp[EXTRACT_SIZE ]; +trace_extract_entropy (r->name, nbytes, r->entropy_count, _RET_IP_);xfer_secondary_pool (r, nbytes); nbytes =account (r, nbytes, min, reserved);
@@ -1005,6 +1021,7 @@ static ssize_t extract_entropy_user(strussize_t ret =0 , i;__u8 tmp[EXTRACT_SIZE ]; +trace_extract_entropy_user (r->name, nbytes, r->entropy_count, _RET_IP_);xfer_secondary_pool (r, nbytes); nbytes =account (r, nbytes,0 ,0 );
@@ -1062,6 +1079,7 @@ void get_random_bytes_arch(void *buf, in {char *p = buf; +trace_get_random_bytes (nbytes, _RET_IP_);while (nbytes) {unsigned long v;int chunk =min (nbytes, (int )sizeof (unsigned long ));
include/trace/events/random.h new file +134 -0
134 lines not on this page · raw message
Greg Kroah-Hartman
maintainerPATCH 28/44 MAINTAINERS: Theodore Tso is taking over the random driver
In reply to Greg Kroah-HartmanFrom: Greg KH <[email protected]>
3.0-stable review patch. If anyone has any objections, please let me know.
------------------
From: Theodore Ts'o <[email protected]>
commit 330e0a01d54c2b8606c56816f99af6ebc58ec92c upstream.
Matt Mackall stepped down as the /dev/random driver maintainer last year, so Theodore Ts'o is taking back the /dev/random driver.
--- MAINTAINERS | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
MAINTAINERS +1 -1
@@ -5247,7 +5247,7 @@ F: Documentation/blockdev/ramdisk.txt F: drivers/block/brd.c RANDOM NUMBER DRIVER -M: Matt Mackall <[email protected]> +M: Theodore Ts'o" <[email protected]> S: Maintained F: drivers/char/random.c
Greg Kroah-Hartman
maintainerPATCH 29/44 rtc: wm831x: Feed the write counter into device_add_randomness()
In reply to Greg Kroah-HartmanFrom: Greg KH <[email protected]>
3.0-stable review patch. If anyone has any objections, please let me know.
------------------
From: Mark Brown <[email protected]>
commit 9dccf55f4cb011a7552a8a2749a580662f5ed8ed upstream.
The tamper evident features of the RTC include the "write counter" which is a pseudo-random number regenerated whenever we set the RTC. Since this value is unpredictable it should provide some useful seeding to the random number generator.
Only do this on boot since the goal is to seed the pool rather than add useful entropy.
--- drivers/rtc/rtc-wm831x.c | 24 +++++++++++++++++++++++- 1 file changed, 23 insertions(+), 1 deletion(-)
drivers/rtc/rtc-wm831x.c +23 -1
@@ -24,7 +24,7 @@#include <linux/mfd/wm831x/core.h> #include <linux/delay.h> #include <linux/platform_device.h> - +#include <linux/random.h> /* * R16416 (0x4020) - RTC Write Counter
@@ -96,6 +96,26 @@ struct wm831x_rtc { unsigned int alarm_enabled:1; }; +static void wm831x_rtc_add_randomness (struct wm831x *wm831x) +{ +int ret; +u16 reg; + +/* +* The write counter contains a pseudo-random number which is +* regenerated every time we set the RTC so it should be a +* useful per-system source of entropy. +*/ + ret =wm831x_reg_read (wm831x,WM831X_RTC_WRITE_COUNTER ); +if (ret >=0 ) { + reg = ret; +add_device_randomness (®,sizeof (reg)); + }else { +dev_warn (wm831x->dev,"Failed to read RTC write counter: %d\n" , + ret); + } +} +/* * Read current time and date in RTC */
@@ -449,6 +469,8 @@ static int wm831x_rtc_probe(struct platf alm_irq, ret); } +wm831x_rtc_add_randomness (wm831x); +return 0 ; err:
Greg Kroah-Hartman
maintainerPATCH 30/44 mfd: wm831x: Feed the device UUID into device_add_randomness()
In reply to Greg Kroah-HartmanFrom: Greg KH <[email protected]>
3.0-stable review patch. If anyone has any objections, please let me know.
------------------
From: Mark Brown <[email protected]>
commit 27130f0cc3ab97560384da437e4621fc4e94f21c upstream.
wm831x devices contain a unique ID value. Feed this into the newly added device_add_randomness() to add some per device seed data to the pool.
--- drivers/mfd/wm831x-otp.c | 8 ++++++++ 1 file changed, 8 insertions(+)
drivers/mfd/wm831x-otp.c +8 -0
@@ -18,6 +18,7 @@#include <linux/bcd.h> #include <linux/delay.h> #include <linux/mfd/core.h> +#include <linux/random.h> #include <linux/mfd/wm831x/core.h> #include <linux/mfd/wm831x/otp.h>
@@ -66,6 +67,7 @@ static DEVICE_ATTR(unique_id, 0444, wm83int wm831x_otp_init (struct wm831x *wm831x) { +char uuid[WM831X_UNIQUE_ID_LEN ];int ret; ret =device_create_file (wm831x->dev, &dev_attr_unique_id);
@@ -73,6 +75,12 @@ int wm831x_otp_init(struct wm831x *wm831dev_err (wm831x->dev,"Unique ID attribute not created: %d\n" , ret); + ret =wm831x_unique_id_read (wm831x, uuid); +if (ret ==0 ) +add_device_randomness (uuid,sizeof (uuid)); +else +dev_err (wm831x->dev,"Failed to read UUID: %d\n" , ret); +return ret; }
Greg Kroah-Hartman
maintainerPATCH 31/44 random: remove rand_initialize_irq()
In reply to Greg Kroah-HartmanFrom: Greg KH <[email protected]>
3.0-stable review patch. If anyone has any objections, please let me know.
------------------
From: Theodore Ts'o <[email protected]>
commit c5857ccf293968348e5eb4ebedc68074de3dcda6 upstream.
With the new interrupt sampling system, we are no longer using the timer_rand_state structure in the irq descriptor, so we can stop initializing it now.
[ Merged in fixes from Sedat to find some last missing references to
rand_initialize_irq() ]
--- arch/ia64/kernel/irq_ia64.c | 1 drivers/char/random.c | 55 -------------------------------------------- drivers/mfd/ab3100-core.c | 3 -- drivers/mfd/ab3550-core.c | 2 - include/linux/irqdesc.h | 1 include/linux/random.h | 2 - kernel/irq/manage.c | 17 ------------- 7 files changed, 81 deletions(-)
arch/ia64/kernel/irq_ia64.c +0 -1
@@ -23,7 +23,6 @@#include <linux/ioport.h> #include <linux/kernel_stat.h> #include <linux/ptrace.h> -#include <linux/random.h> /* for rand_initialize_irq() */ #include <linux/signal.h> #include <linux/smp.h> #include <linux/threads.h>
drivers/char/random.c +0 -55
67 lines not on this page · raw message
drivers/mfd/ab3100-core.c +0 -3
@@ -936,9 +936,6 @@ static int __devinit ab3100_probe(struct err =request_threaded_irq (client->irq,NULL , ab3100_irq_handler,IRQF_ONESHOT ,"ab3100-core" , ab3100); -/* This real unpredictable IRQ is of course sampled for entropy */ -rand_initialize_irq (client->irq); -if (err) goto exit_no_irq;
drivers/mfd/ab3550-core.c +0 -2
@@ -1309,8 +1309,6 @@ static int __init ab3550_probe(struct i2 err =request_threaded_irq (client->irq,NULL , ab3550_irq_handler,IRQF_ONESHOT ,"ab3550-core" , ab); -/* This real unpredictable IRQ is of course sampled for entropy */ -rand_initialize_irq (client->irq);if (err) goto exit_no_irq;
include/linux/irqdesc.h +0 -1
@@ -38,7 +38,6 @@ struct timer_rand_state;*/ struct irq_desc {struct irq_data irq_data; -struct timer_rand_state *timer_rand_state;unsigned int __percpu *kstat_irqs;irq_flow_handler_t handle_irq;#ifdef CONFIG_IRQ_PREFLOW_FASTEOI
include/linux/random.h +0 -2
@@ -48,8 +48,6 @@ struct rnd_state {#ifdef __KERNEL__ -extern void rand_initialize_irq (int irq); -extern void add_device_randomness (const void *,unsigned int );extern void add_input_randomness (unsigned int type,unsigned int code,unsigned int value);
kernel/irq/manage.c +0 -17
@@ -886,22 +886,6 @@ __setup_irq(unsigned int irq, struct irqif (desc->irq_data.chip == &no_irq_chip)return -ENOSYS ; -/* -* Some drivers like serial.c use request_irq() heavily, -* so we have to be careful not to interfere with a -* running system. -*/ -if (new->flags &IRQF_SAMPLE_RANDOM ) { -/* -* This function might sleep, we want to call it first, -* outside of the atomic block. -* Yes, this might clear the entropy pool if the wrong -* driver is attempted to be loaded, without actually -* installing a new handler, but is this really a problem, -* only the sysadmin is able to do this. -*/ -rand_initialize_irq (irq); - }/* * Check whether the interrupt nests into another interrupt
@@ -1325,7 +1309,6 @@ EXPORT_SYMBOL(free_irq);* Flags: * * IRQF_SHARED Interrupt is shared -* IRQF_SAMPLE_RANDOM The interrupt can be used for entropy * IRQF_TRIGGER_* Specify active edge(s) or level * */
Greg Kroah-Hartman
maintainerPATCH 32/44 random: Add comment to random_initialize()
In reply to Greg Kroah-HartmanFrom: Greg KH <[email protected]>
3.0-stable review patch. If anyone has any objections, please let me know.
------------------
From: Tony Luck <[email protected]>
commit cbc96b7594b5691d61eba2db8b2ea723645be9ca upstream.
Many platforms have per-machine instance data (serial numbers, asset tags, etc.) squirreled away in areas that are accessed during early system bringup. Mixing this data into the random pools has a very high value in providing better random data, so we should allow (and even encourage) architecture code to call add_device_randomness() from the setup_arch() paths.
However, this limits our options for internal structure of the random driver since random_initialize() is not called until long after setup_arch().
Add a big fat comment to rand_initialize() spelling out this requirement.
--- drivers/char/random.c | 10 ++++++++++ 1 file changed, 10 insertions(+)
drivers/char/random.c +10 -0
@@ -1087,6 +1087,16 @@ static void init_std_data(struct entropymix_pool_bytes (r,utsname (),sizeof (*(utsname ())),NULL ); } +/* +* Note that setup_arch() may call add_device_randomness() +* long before we get here. This allows seeding of the pools +* with some platform dependent data very early in the boot +* process. But it limits our options here. We must use +* statically allocated structures that already have all +* initializations complete at compile time. We should also +* take care not to overwrite the precious per platform data +* we were given. +*/ static int rand_initialize (void ) {init_std_data (&input_pool);
Greg Kroah-Hartman
maintainerPATCH 33/44 dmi: Feed DMI table to /dev/random driver
In reply to Greg Kroah-HartmanFrom: Greg KH <[email protected]>
3.0-stable review patch. If anyone has any objections, please let me know.
------------------
From: Tony Luck <[email protected]>
commit d114a33387472555188f142ed8e98acdb8181c6d upstream.
Send the entire DMI (SMBIOS) table to the /dev/random driver to help seed its pools.
--- drivers/firmware/dmi_scan.c | 3 +++ 1 file changed, 3 insertions(+)
drivers/firmware/dmi_scan.c +3 -0
@@ -6,6 +6,7 @@#include <linux/dmi.h> #include <linux/efi.h> #include <linux/bootmem.h> +#include <linux/random.h> #include <asm/dmi.h> /*
@@ -111,6 +112,8 @@ static int __init dmi_walk_early(void (*dmi_table (buf, dmi_len, dmi_num, decode,NULL ); +add_device_randomness (buf, dmi_len); +dmi_iounmap (buf, dmi_len);return 0 ; }
Greg Kroah-Hartman
maintainerPATCH 34/44 random: mix in architectural randomness in extract_buf()
In reply to Greg Kroah-HartmanFrom: Greg KH <[email protected]>
3.0-stable review patch. If anyone has any objections, please let me know.
------------------
From: "H. Peter Anvin" <[email protected]>
commit d2e7c96af1e54b507ae2a6a7dd2baf588417a7e5 upstream.
Mix in any architectural randomness in extract_buf() instead of xfer_secondary_buf(). This allows us to mix in more architectural randomness, and it also makes xfer_secondary_buf() faster, moving a tiny bit of additional CPU overhead to process which is extracting the randomness.
[ Commit description modified by tytso to remove an extended
advertisement for the RDRAND instruction. ]
--- drivers/char/random.c | 56 ++++++++++++++++++++++++++++---------------------- 1 file changed, 32 insertions(+), 24 deletions(-)
drivers/char/random.c +32 -24
@@ -277,6 +277,8 @@#define SEC_XFER_SIZE 512#define EXTRACT_SIZE 10 +#define LONGS (x) (((x) + sizeof(unsigned long) - 1)/sizeof(unsigned long)) +/* * The minimum number of bits of entropy before we wake up a read on * /dev/random. Should be enough to do a significant reseed.
@@ -813,11 +815,7 @@ static ssize_t extract_entropy(struct en*/ static void xfer_secondary_pool (struct entropy_store *r,size_t nbytes) { -union { -__u32 tmp[OUTPUT_POOL_WORDS ]; -long hwrand[4 ]; - } u; -int i; +__u32 tmp[OUTPUT_POOL_WORDS ];if (r->pull && r->entropy_count < nbytes *8 && r->entropy_count < r->poolinfo->POOLBITS) {
@@ -828,23 +826,17 @@ static void xfer_secondary_pool(struct e/* pull at least as many as BYTES as wakeup BITS */ bytes =max_t (int, bytes, random_read_wakeup_thresh /8 );/* but never more than the buffer size */ - bytes =min_t (int, bytes,sizeof (u.tmp)); + bytes =min_t (int, bytes,sizeof (tmp));DEBUG_ENT ("going to reseed %s with %d bits " "(%d of %d requested)\n" , r->name, bytes *8 , nbytes *8 , r->entropy_count); - bytes =extract_entropy (r->pull, u.tmp, bytes, + bytes =extract_entropy (r->pull, tmp, bytes, random_read_wakeup_thresh /8 , rsvd); -mix_pool_bytes (r, u.tmp, bytes,NULL ); +mix_pool_bytes (r, tmp, bytes,NULL );credit_entropy_bits (r, bytes*8 ); } -kmemcheck_mark_initialized (&u.hwrand,sizeof (u.hwrand)); -for (i =0 ; i <4 ; i++) -if (arch_get_random_long (&u.hwrand[i])) -break ; -if (i) -mix_pool_bytes (r, &u.hwrand,sizeof (u.hwrand),0 ); }/*
@@ -901,15 +893,19 @@ static size_t account(struct entropy_stostatic void extract_buf (struct entropy_store *r,__u8 *out) {int i; -__u32 hash[5 ], workspace[SHA_WORKSPACE_WORDS ]; +union { +__u32 w[5 ]; +unsigned long l[LONGS (EXTRACT_SIZE )]; + } hash; +__u32 workspace[SHA_WORKSPACE_WORDS ];__u8 extract[64 ];unsigned long flags;/* Generate a hash across the pool, 16 words (512 bits) at a time */ -sha_init (hash); +sha_init (hash.w);spin_lock_irqsave (&r->lock, flags);for (i =0 ; i < r->poolinfo->poolwords; i +=16 ) -sha_transform (hash, (__u8 *)(r->pool + i), workspace); +sha_transform (hash.w, (__u8 *)(r->pool + i), workspace);/* * We mix the hash back into the pool to prevent backtracking
@@ -920,14 +916,14 @@ static void extract_buf(struct entropy_s* brute-forcing the feedback as hard as brute-forcing the * hash. */ -__mix_pool_bytes (r, hash,sizeof (hash), extract); +__mix_pool_bytes (r, hash.w,sizeof (hash.w), extract);spin_unlock_irqrestore (&r->lock, flags);/* * To avoid duplicates, we atomically extract a portion of the * pool while mixing, and hash one final time. */ -sha_transform (hash, extract, workspace); +sha_transform (hash.w, extract, workspace);memset (extract,0 ,sizeof (extract));memset (workspace,0 ,sizeof (workspace));
@@ -936,11 +932,23 @@ static void extract_buf(struct entropy_s* pattern, we fold it in half. Thus, we always feed back * twice as much data as we output. */ - hash[0 ] ^= hash[3 ]; - hash[1 ] ^= hash[4 ]; - hash[2 ] ^=rol32 (hash[2 ],16 ); -memcpy (out, hash,EXTRACT_SIZE ); -memset (hash,0 ,sizeof (hash)); + hash.w[0 ] ^= hash.w[3 ]; + hash.w[1 ] ^= hash.w[4 ]; + hash.w[2 ] ^=rol32 (hash.w[2 ],16 ); + +/* +* If we have a architectural hardware random number +* generator, mix that in, too. +*/ +for (i =0 ; i <LONGS (EXTRACT_SIZE ); i++) { +unsigned long v; +if (!arch_get_random_long (&v)) +break ; + hash.l[i] ^= v; + } + +memcpy (out, &hash,EXTRACT_SIZE ); +memset (&hash,0 ,sizeof (hash)); } static ssize_t extract_entropy(struct entropy_store *r, void *buf,
Greg Kroah-Hartman
maintainerPATCH 35/44 x86, microcode: microcode_core.c simple_strtoul cleanup
In reply to Greg Kroah-HartmanFrom: Greg KH <[email protected]>
3.0-stable review patch. If anyone has any objections, please let me know.
------------------
From: Shuah Khan <[email protected]>
commit e826abd523913f63eb03b59746ffb16153c53dc4 upstream.
Change reload_for_cpu() in kernel/microcode_core.c to call kstrtoul() instead of calling obsoleted simple_strtoul().
--- arch/x86/kernel/microcode_core.c | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-)
arch/x86/kernel/microcode_core.c +4 -5
@@ -298,12 +298,11 @@ static ssize_t reload_store(struct sys_d {unsigned long val;int cpu = dev->id; -int ret =0 ; -char *end; +ssize_t ret =0 ; - val =simple_strtoul (buf, &end,0 ); -if (end == buf) -return -EINVAL ; + ret =kstrtoul (buf,0 , &val); +if (ret) +return ret;if (val ==1 ) {get_online_cpus ();
Greg Kroah-Hartman
maintainerPATCH 36/44 x86, microcode: Sanitize per-cpu microcode reloading interface
In reply to Greg Kroah-HartmanFrom: Greg KH <[email protected]>
3.0-stable review patch. If anyone has any objections, please let me know.
------------------
From: Borislav Petkov <[email protected]>
commit c9fc3f778a6a215ace14ee556067c73982b6d40f upstream.
Microcode reloading in a per-core manner is a very bad idea for both major x86 vendors. And the thing is, we have such interface with which we can end up with different microcode versions applied on different cores of an otherwise homogeneous wrt (family,model,stepping) system.
So turn off the possibility of doing that per core and allow it only system-wide.
This is a minimal fix which we'd like to see in stable too thus the more-or-less arbitrary decision to allow system-wide reloading only on the BSP:
$ echo 1 > /sys/devices/system/cpu/cpu0/microcode/reload ...
and disable the interface on the other cores:
$ echo 1 > /sys/devices/system/cpu/cpu23/microcode/reload -bash: echo: write error: Invalid argument
Also, allowing the reload only from one CPU (the BSP in that case) doesn't allow the reload procedure to degenerate into an O(n^2) deal when triggering reloads from all /sys/devices/system/cpu/cpuX/microcode/reload sysfs nodes simultaneously.
A more generic fix will follow.
--- arch/x86/kernel/microcode_core.c | 26 +++++++++++++++++++------- 1 file changed, 19 insertions(+), 7 deletions(-)
arch/x86/kernel/microcode_core.c +19 -7
@@ -297,19 +297,31 @@ static ssize_t reload_store(struct sys_d const char *buf, size_t size) { unsigned long val; -int cpu = dev->id; -ssize_t ret =0 ; +int cpu; +ssize_t ret =0 , tmp_ret; + +/* allow reload only from the BSP */ +if (boot_cpu_data.cpu_index != dev->id) +return -EINVAL ; ret =kstrtoul (buf,0 , &val);if (ret)return ret; -if (val ==1 ) { -get_online_cpus (); -if (cpu_online (cpu)) - ret =reload_for_cpu (cpu); -put_online_cpus (); +if (val !=1 ) +return size; + +get_online_cpus (); +for_each_online_cpu (cpu) { + tmp_ret =reload_for_cpu (cpu); +if (tmp_ret !=0 ) +pr_warn ("Error reloading microcode on CPU %d\n" , cpu); + +/* save retval of the first encountered reload error */ +if (!ret) + ret = tmp_ret; } +put_online_cpus ();if (!ret) ret = size;
Re: [ 36/44] x86, microcode: Sanitize per-cpu microcode reloading interface
I believe the patch bellow, which was required on 3.2, will also be necessary.
From: Kevin Winchester <[email protected]>
Subject: [PATCH] x86: Simplify code by removing a !SMP #ifdefs from 'struct
cpuinfo_x86'
commit 141168c36cdee3ff23d9c7700b0edc47cb65479f and commit 3f806e50981825fa56a7f1938f24c0680816be45 upstream.
Several fields in struct cpuinfo_x86 were not defined for the !SMP case, likely to save space. However, those fields still have some meaning for UP, and keeping them allows some #ifdef removal from other files. The additional size of the UP kernel from this change is not significant enough to worry about keeping up the distinction:
text data bss dec hex filename 4737168 506459 972040 6215667 5ed7f3 vmlinux.o.before 4737444 506459 972040 6215943 5ed907 vmlinux.o.after
for a difference of 276 bytes for an example UP config.
If someone wants those 276 bytes back badly then it should be implemented in a cleaner way.
--- arch/x86/include/asm/processor.h | 2 -- arch/x86/kernel/amd_nb.c | 8 ++------ arch/x86/kernel/cpu/amd.c | 2 -- arch/x86/kernel/cpu/common.c | 5 ----- arch/x86/kernel/cpu/intel.c | 2 -- arch/x86/kernel/cpu/mcheck/mce.c | 2 -- arch/x86/kernel/cpu/mcheck/mce_amd.c | 5 +---- arch/x86/kernel/cpu/proc.c | 4 +--- drivers/edac/sb_edac.c | 2 -- drivers/hwmon/coretemp.c | 7 +++---- 10 files changed, 7 insertions(+), 32 deletions(-)
arch/x86/include/asm/processor.h +0 -2
@@ -99,7 +99,6 @@ struct cpuinfo_x86 {u16 apicid;u16 initial_apicid;u16 x86_clflush_size; -#ifdef CONFIG_SMP /* number of cores as seen by the OS: */ u16 booted_cores;/* Physical processor id: */
@@ -110,7 +109,6 @@ struct cpuinfo_x86 {u8 compute_unit_id;/* Index into per_cpu list: */ u16 cpu_index; -#endif u32 microcode; } __attribute__((__aligned__(SMP_CACHE_BYTES)));
arch/x86/kernel/amd_nb.c +2 -6
@@ -154,16 +154,14 @@ int amd_get_subcaches(int cpu) {struct pci_dev *link =node_to_amd_nb (amd_get_nb_id (cpu))->link;unsigned int mask; -int cuid =0 ; +int cuid;if (!amd_nb_has_feature (AMD_NB_L3_PARTITIONING ))return 0 ;pci_read_config_dword (link,0x1d4 , &mask); -#ifdef CONFIG_SMP cuid =cpu_data (cpu).compute_unit_id; -#endif return (mask >> (4 * cuid)) &0xf ; }
@@ -172,7 +170,7 @@ int amd_set_subcaches(int cpu, int mask)static unsigned int reset, ban;struct amd_northbridge *nb =node_to_amd_nb (amd_get_nb_id (cpu));unsigned int reg; -int cuid =0 ; +int cuid;if (!amd_nb_has_feature (AMD_NB_L3_PARTITIONING ) || mask >0xf )return -EINVAL ;
@@ -190,9 +188,7 @@ int amd_set_subcaches(int cpu, int mask)pci_write_config_dword (nb->misc,0x1b8 , reg & ~0x180000 ); } -#ifdef CONFIG_SMP cuid =cpu_data (cpu).compute_unit_id; -#endif mask <<=4 * cuid; mask |= (0xf ^ (1 << cuid)) <<26 ;
arch/x86/kernel/cpu/amd.c +0 -2
@@ -148,7 +148,6 @@ static void __cpuinit init_amd_k6(struct cpuinfo_x86 *c)static void __cpuinit amd_k7_smp_check (struct cpuinfo_x86 *c) { -#ifdef CONFIG_SMP /* calling is from identify_secondary_cpu() ? */ if (!c->cpu_index)return ;
@@ -192,7 +191,6 @@ static void __cpuinit amd_k7_smp_check(struct cpuinfo_x86 *c) valid_k7: ; -#endif }static void __cpuinit init_amd_k7 (struct cpuinfo_x86 *c)
arch/x86/kernel/cpu/common.c +0 -5
@@ -676,9 +676,7 @@ static void __init early_identify_cpu(struct cpuinfo_x86 *c)if (this_cpu->c_early_init) this_cpu->c_early_init (c); -#ifdef CONFIG_SMP c->cpu_index =0 ; -#endif filter_cpuid_features (c, false);setup_smep (c);
@@ -764,10 +762,7 @@ static void __cpuinit generic_identify(struct cpuinfo_x86 *c) c->apicid = c->initial_apicid;# endif #endif - -#ifdef CONFIG_X86_HT c->phys_proc_id = c->initial_apicid; -#endif }setup_smep (c);
arch/x86/kernel/cpu/intel.c +0 -2
@@ -181,7 +181,6 @@ static void __cpuinit trap_init_f00f_bug(void)static void __cpuinit intel_smp_check (struct cpuinfo_x86 *c) { -#ifdef CONFIG_SMP /* calling is from identify_secondary_cpu() ? */ if (!c->cpu_index)return ;
@@ -198,7 +197,6 @@ static void __cpuinit intel_smp_check(struct cpuinfo_x86 *c)WARN_ONCE (1 ,"WARNING: SMP operation may be unreliable" "with B stepping processors.\n" ); } -#endif }static void __cpuinit intel_workarounds (struct cpuinfo_x86 *c)
arch/x86/kernel/cpu/mcheck/mce.c +0 -2
@@ -119,9 +119,7 @@ void mce_setup(struct mce *m) m->time =get_seconds (); m->cpuvendor = boot_cpu_data.x86_vendor; m->cpuid =cpuid_eax (1 ); -#ifdef CONFIG_SMP m->socketid =cpu_data (m->extcpu).phys_proc_id; -#endif m->apicid =cpu_data (m->extcpu).initial_apicid;rdmsrl (MSR_IA32_MCG_CAP , m->mcgcap); }
arch/x86/kernel/cpu/mcheck/mce_amd.c +1 -4
@@ -65,11 +65,9 @@ struct threshold_bank { }; static DEFINE_PER_CPU(struct threshold_bank * [NR_BANKS], threshold_banks); -#ifdef CONFIG_SMP static unsigned char shared_bank[NR_BANKS ] = {0 ,0 ,0 ,0 ,1 }; -#endif static DEFINE_PER_CPU(unsigned char, bank_map); /* see which banks are on */
@@ -227,10 +225,9 @@ void mce_amd_feature_init(struct cpuinfo_x86 *c)if (!block)per_cpu (bank_map, cpu) |= (1 << bank); -#ifdef CONFIG_SMP +if (shared_bank[bank] && c->cpu_core_id)break ; -#endif memset (&b,0 ,sizeof (b)); b.cpu = cpu;
arch/x86/kernel/cpu/proc.c +1 -3
@@ -64,12 +64,10 @@ static void show_cpuinfo_misc(struct seq_file *m, struct cpuinfo_x86 *c)static int show_cpuinfo (struct seq_file *m,void *v) {struct cpuinfo_x86 *c = v; -unsigned int cpu =0 ; +unsigned int cpu;int i; -#ifdef CONFIG_SMP cpu = c->cpu_index; -#endif seq_printf (m,"processor\t: %u\n" "vendor_id\t: %s\n" "cpu family\t: %d\n"
drivers/edac/sb_edac.c +0 -2
@@ -1609,11 +1609,9 @@ static int sbridge_mce_check_error(struct notifier_block *nb, unsigned long val, mce->cpuvendor, mce->cpuid, mce->time, mce->socketid, mce->apicid); -#ifdef CONFIG_SMP /* Only handle if it is the right mc controller */ if (cpu_data (mce->cpu).phys_proc_id != pvt->sbridge_dev->mc)return NOTIFY_DONE ; -#endif smp_rmb ();if ((pvt->mce_out +1 ) %MCE_LOG_LEN == pvt->mce_in) {
drivers/hwmon/coretemp.c +3 -4
@@ -57,16 +57,15 @@ MODULE_PARM_DESC(tjmax, "TjMax value in degrees Celsius");#define TOTAL_ATTRS (MAX_CORE_ATTRS + 1)#define MAX_CORE_DATA (NUM_REAL_CORES + BASE_SYSFS_ATTR_NO) -#ifdef CONFIG_SMP #define TO_PHYS_ID (cpu) cpu_data(cpu).phys_proc_id#define TO_CORE_ID (cpu) cpu_data(cpu).cpu_core_id +#define TO_ATTR_NO (cpu) (TO_CORE_ID(cpu) + BASE_SYSFS_ATTR_NO) + +#ifdef CONFIG_SMP #define for_each_sibling (i, cpu) for_each_cpu(i, cpu_sibling_mask(cpu))#else -#define TO_PHYS_ID (cpu) (cpu) -#define TO_CORE_ID (cpu) (cpu)#define for_each_sibling (i, cpu) for (i = 0; false; )#endif -#define TO_ATTR_NO (cpu) (TO_CORE_ID(cpu) + BASE_SYSFS_ATTR_NO)/* * Per-Core Temperature Data
Signature · 8 lines
1.7.10 -- "One disk to rule them all, One disk to find them. One disk to bring them all and in the darkness grind them. In the Land of Redmond where the shadows lie." -- The Silicon Valley Tarot Henrique Holschuh
Greg Kroah-Hartman
maintainerRe: [ 36/44] x86, microcode: Sanitize per-cpu microcode reloading interface
Quoted 2 lines · Henrique de Moraes Holschuh
I believe the patch bellow, which was required on 3.2, will also be necessary.
Will it be necessary to apply this before this patch goes in the series, or after it?
thanks,
greg k-h
Re: [ 36/44] x86, microcode: Sanitize per-cpu microcode reloading interface
Quoted 6 lines · Greg Kroah-Hartman
Quoted 2 lines · Henrique de Moraes Holschuh
I believe the patch bellow, which was required on 3.2, will also be necessary.
Will it be necessary to apply this before this patch goes in the series, or after it?
Applying after fixes a build error. Applying before might avoid the build error altogether (error happens when #undef CONFIG_SMP), AFAIK.
Signature · 4 lines
"One disk to rule them all, One disk to find them. One disk to bring them all and in the darkness grind them. In the Land of Redmond where the shadows lie." -- The Silicon Valley Tarot Henrique Holschuh
Greg Kroah-Hartman
maintainerRe: [ 36/44] x86, microcode: Sanitize per-cpu microcode reloading interface
Quoted 10 lines · Henrique de Moraes Holschuh
Quoted 6 lines · Greg Kroah-Hartman
Quoted 2 lines · Henrique de Moraes Holschuh
I believe the patch bellow, which was required on 3.2, will also be necessary.
Will it be necessary to apply this before this patch goes in the series, or after it?
Applying after fixes a build error. Applying before might avoid the build error altogether (error happens when #undef
CONFIG_SMP), AFAIK.
Ok, it doesn't apply directly, but looks easy enough to fix up by hand, I'll go work on that right now...
greg k-h
Greg Kroah-Hartman
maintainerPATCH 37/44 mm: hugetlbfs: close race during teardown of hugetlbfs shared page tables
In reply to Greg Kroah-HartmanFrom: Greg KH <[email protected]>
3.0-stable review patch. If anyone has any objections, please let me know.
------------------
From: Mel Gorman <[email protected]>
commit d833352a4338dc31295ed832a30c9ccff5c7a183 upstream.
If a process creates a large hugetlbfs mapping that is eligible for page table sharing and forks heavily with children some of whom fault and others which destroy the mapping then it is possible for page tables to get corrupted. Some teardowns of the mapping encounter a "bad pmd" and output a message to the kernel log. The final teardown will trigger a BUG_ON in mm/filemap.c.
This was reproduced in 3.4 but is known to have existed for a long time and goes back at least as far as 2.6.37. It was probably was introduced in 2.6.20 by [39dde65c: shared page table for hugetlb page]. The messages look like this;
[ ..........] Lots of bad pmd messages followed by this [ 127.164256] mm/memory.c:391: bad pmd ffff880412e04fe8(80000003de4000e7). [ 127.164257] mm/memory.c:391: bad pmd ffff880412e04ff0(80000003de6000e7). [ 127.164258] mm/memory.c:391: bad pmd ffff880412e04ff8(80000003de0000e7). [ 127.186778] ------------[ cut here ]------------ [ 127.186781] kernel BUG at mm/filemap.c:134! [ 127.186782] invalid opcode: 0000 [#1] SMP [ 127.186783] CPU 7 [ 127.186784] Modules linked in: af_packet cpufreq_conservative cpufreq_userspace cpufreq_powersave acpi_cpufreq mperf ext3 jbd dm_mod coretemp crc32c_intel usb_storage ghash_clmulni_intel aesni_intel i2c_i801 r8169 mii uas sr_mod cdrom sg iTCO_wdt iTCO_vendor_support shpchp serio_raw cryptd aes_x86_64 e1000e pci_hotplug dcdbas aes_generic container microcode ext4 mbcache jbd2 crc16 sd_mod crc_t10dif i915 drm_kms_helper drm i2c_algo_bit ehci_hcd ahci libahci usbcore rtc_cmos usb_common button i2c_core intel_agp video intel_gtt fan processor thermal thermal_sys hwmon ata_generic pata_atiixp libata scsi_mod [ 127.186801] [ 127.186802] Pid: 9017, comm: hugetlbfs-test Not tainted 3.4.0-autobuild #53 Dell Inc. OptiPlex 990/06D7TR [ 127.186804] RIP: 0010:[<ffffffff810ed6ce>] [<ffffffff810ed6ce>] __delete_from_page_cache+0x15e/0x160 [ 127.186809] RSP: 0000:ffff8804144b5c08 EFLAGS: 00010002 [ 127.186810] RAX: 0000000000000001 RBX: ffffea000a5c9000 RCX: 00000000ffffffc0 [ 127.186811] RDX: 0000000000000000 RSI: 0000000000000009 RDI: ffff88042dfdad00 [ 127.186812] RBP: ffff8804144b5c18 R08: 0000000000000009 R09: 0000000000000003 [ 127.186813] R10: 0000000000000000 R11: 000000000000002d R12: ffff880412ff83d8 [ 127.186814] R13: ffff880412ff83d8 R14: 0000000000000000 R15: ffff880412ff83d8 [ 127.186815] FS: 00007fe18ed2c700(0000) GS:ffff88042dce0000(0000) knlGS:0000000000000000 [ 127.186816] CS: 0010 DS: 0000 ES: 0000 CR0: 000000008005003b [ 127.186817] CR2: 00007fe340000503 CR3: 0000000417a14000 CR4: 00000000000407e0 [ 127.186818] DR0: 0000000000000000 DR1: 0000000000000000 DR2: 0000000000000000 [ 127.186819] DR3: 0000000000000000 DR6: 00000000ffff0ff0 DR7: 0000000000000400 [ 127.186820] Process hugetlbfs-test (pid: 9017, threadinfo ffff8804144b4000, task ffff880417f803c0) [ 127.186821] Stack: [ 127.186822] ffffea000a5c9000 0000000000000000 ffff8804144b5c48 ffffffff810ed83b [ 127.186824] ffff8804144b5c48 000000000000138a 0000000000001387 ffff8804144b5c98 [ 127.186825] ffff8804144b5d48 ffffffff811bc925 ffff8804144b5cb8 0000000000000000 [ 127.186827] Call Trace: [ 127.186829] [<ffffffff810ed83b>] delete_from_page_cache+0x3b/0x80 [ 127.186832] [<ffffffff811bc925>] truncate_hugepages+0x115/0x220 [ 127.186834] [<ffffffff811bca43>] hugetlbfs_evict_inode+0x13/0x30 [ 127.186837] [<ffffffff811655c7>] evict+0xa7/0x1b0 [ 127.186839] [<ffffffff811657a3>] iput_final+0xd3/0x1f0 [ 127.186840] [<ffffffff811658f9>] iput+0x39/0x50 [ 127.186842] [<ffffffff81162708>] d_kill+0xf8/0x130 [ 127.186843] [<ffffffff81162812>] dput+0xd2/0x1a0 [ 127.186845] [<ffffffff8114e2d0>] __fput+0x170/0x230 [ 127.186848] [<ffffffff81236e0e>] ? rb_erase+0xce/0x150 [ 127.186849] [<ffffffff8114e3ad>] fput+0x1d/0x30 [ 127.186851] [<ffffffff81117db7>] remove_vma+0x37/0x80 [ 127.186853] [<ffffffff81119182>] do_munmap+0x2d2/0x360 [ 127.186855] [<ffffffff811cc639>] sys_shmdt+0xc9/0x170 [ 127.186857] [<ffffffff81410a39>] system_call_fastpath+0x16/0x1b [ 127.186858] Code: 0f 1f 44 00 00 48 8b 43 08 48 8b 00 48 8b 40 28 8b b0 40 03 00 00 85 f6 0f 88 df fe ff ff 48 89 df e8 e7 cb 05 00 e9 d2 fe ff ff <0f> 0b 55 83 e2 fd 48 89 e5 48 83 ec 30 48 89 5d d8 4c 89 65 e0 [ 127.186868] RIP [<ffffffff810ed6ce>] __delete_from_page_cache+0x15e/0x160 [ 127.186870] RSP <ffff8804144b5c08> [ 127.186871] ---[ end trace 7cbac5d1db69f426 ]---
The bug is a race and not always easy to reproduce. To reproduce it I was doing the following on a single socket I7-based machine with 16G of RAM.
$ hugeadm --pool-pages-max DEFAULT:13G $ echo $((18*1048576*1024)) > /proc/sys/kernel/shmmax $ echo $((18*1048576*1024)) > /proc/sys/kernel/shmall $ for i in `seq 1 9000`; do ./hugetlbfs-test; done
On my particular machine, it usually triggers within 10 minutes but enabling debug options can change the timing such that it never hits. Once the bug is triggered, the machine is in trouble and needs to be rebooted. The machine will respond but processes accessing proc like "ps aux" will hang due to the BUG_ON. shutdown will also hang and needs a hard reset or a sysrq-b.
The basic problem is a race between page table sharing and teardown. For the most part page table sharing depends on i_mmap_mutex. In some cases, it is also taking the mm->page_table_lock for the PTE updates but with shared page tables, it is the i_mmap_mutex that is more important.
Unfortunately it appears to be also insufficient. Consider the following situation
Process A Process B
--------- ---------hugetlb_fault shmdt
LockWrite(mmap_sem)
do_munmap
unmap_region
unmap_vmas
unmap_single_vma
unmap_hugepage_range
Lock(i_mmap_mutex)
Lock(mm->page_table_lock)
huge_pmd_unshare/unmap tables <--- (1)
Unlock(mm->page_table_lock)
Unlock(i_mmap_mutex)
huge_pte_alloc ...
Lock(i_mmap_mutex) ...
vma_prio_walk, find svma, spte ...
Lock(mm->page_table_lock) ...
share spte ...
Unlock(mm->page_table_lock) ...
Unlock(i_mmap_mutex) ... hugetlb_no_page <--- (2)
free_pgtables
unlink_file_vma hugetlb_free_pgd_range
remove_vma_list
In this scenario, it is possible for Process A to share page tables with Process B that is trying to tear them down. The i_mmap_mutex on its own does not prevent Process A walking Process B's page tables. At (1) above, the page tables are not shared yet so it unmaps the PMDs. Process A sets up page table sharing and at (2) faults a new entry. Process B then trips up on it in free_pgtables.
This patch fixes the problem by adding a new function __unmap_hugepage_range_final that is only called when the VMA is about to be destroyed. This function clears VM_MAYSHARE during unmap_hugepage_range() under the i_mmap_mutex. This makes the VMA ineligible for sharing and avoids the race. Superficially this looks like it would then be vunerable to truncate and madvise issues but hugetlbfs has its own truncate handlers so does not use unmap_mapping_range() and does not support madvise(DONTNEED).
This should be treated as a -stable candidate if it is merged.
Test program is as follows. The test case was mostly written by Michal Hocko with a few minor changes to reproduce this bug.
==== CUT HERE ====
static size_t huge_page_size = (2UL << 20);
static size_t nr_huge_page_A = 512;
static size_t nr_huge_page_B = 5632;
unsigned int get_random(unsigned int max)
{
struct timeval tv;
gettimeofday(&tv, NULL);
srandom(tv.tv_usec);
return random() % max;
}static void play(void *addr, size_t size)
{
unsigned char *start = addr,
*end = start + size,
*a;
start += get_random(size/2);
/* we could itterate on huge pages but let's give it more time. */
for (a = start; a < end; a += 4096)
*a = 0;
}int main(int argc, char **argv)
{
key_t key = IPC_PRIVATE;
size_t sizeA = nr_huge_page_A * huge_page_size;
size_t sizeB = nr_huge_page_B * huge_page_size;
int shmidA, shmidB;
void *addrA = NULL, *addrB = NULL;
int nr_children = 300, n = 0;
if ((shmidA = shmget(key, sizeA, IPC_CREAT|SHM_HUGETLB|0660)) == -1) {
perror("shmget:");
return 1;
}
if ((addrA = shmat(shmidA, addrA, SHM_R|SHM_W)) == (void *)-1UL) {
perror("shmat");
return 1;
}
if ((shmidB = shmget(key, sizeB, IPC_CREAT|SHM_HUGETLB|0660)) == -1) {
perror("shmget:");
return 1;
}
if ((addrB = shmat(shmidB, addrB, SHM_R|SHM_W)) == (void *)-1UL) {
perror("shmat");
return 1;
}fork_child:
switch(fork()) {
case 0:
switch (n%3) {
case 0:
play(addrA, sizeA);
break;
case 1:
play(addrB, sizeB);
break;
case 2:
break;
}
break;
case -1:
perror("fork:");
break;
default:
if (++n < nr_children)
goto fork_child;
play(addrA, sizeA);
break;
}
shmdt(addrA);
shmdt(addrB);
do {
wait(NULL);
} while (--n > 0);
shmctl(shmidA, IPC_RMID, NULL);
shmctl(shmidB, IPC_RMID, NULL);
return 0;
}--- mm/hugetlb.c | 25 +++++++++++++++++++++++-- 1 file changed, 23 insertions(+), 2 deletions(-)
mm/hugetlb.c +23 -2
@@ -2301,6 +2301,22 @@ void unmap_hugepage_range(struct vm_area {mutex_lock (&vma->vm_file->f_mapping->i_mmap_mutex);__unmap_hugepage_range (vma, start, end, ref_page); +/* +* Clear this flag so that x86's huge_pmd_share page_table_shareable +* test will fail on a vma being torn down, and not grab a page table +* on its way out. We're lucky that the flag has such an appropriate +* name, and can in fact be safely cleared here. We could clear it +* before the __unmap_hugepage_range above, but all that's necessary +* is to clear it before releasing the i_mmap_mutex below. +* +* This works because in the contexts this is called, the VMA is +* going to be destroyed. It is not vunerable to madvise(DONTNEED) +* because madvise is not supported on hugetlbfs. The same applies +* for direct IO. unmap_hugepage_range() is only being called just +* before free_pgtables() so clearing VM_MAYSHARE will not cause +* surprises later. +*/ + vma->vm_flags &= ~VM_MAYSHARE ;mutex_unlock (&vma->vm_file->f_mapping->i_mmap_mutex); }
@@ -2853,9 +2869,14 @@ void hugetlb_change_protection(struct vm } }spin_unlock (&mm->page_table_lock); -mutex_unlock (&vma->vm_file->f_mapping->i_mmap_mutex); - +/* +* Must flush TLB before releasing i_mmap_mutex: x86's huge_pmd_unshare +* may have cleared our pud entry and done put_page on the page table: +* once we release i_mmap_mutex, another task can do the final put_page +* and that page table be reused and filled with junk. +*/ flush_tlb_range (vma, start, end); +mutex_unlock (&vma->vm_file->f_mapping->i_mmap_mutex); } int hugetlb_reserve_pages(struct inode *inode,
Greg Kroah-Hartman
maintainerPATCH 38/44 ARM: mxs: Remove MMAP_MIN_ADDR setting from mxs_defconfig
In reply to Greg Kroah-HartmanFrom: Greg KH <[email protected]>
3.0-stable review patch. If anyone has any objections, please let me know.
------------------
From: Marek Vasut <[email protected]>
commit 3bed491c8d28329e34f8a31e3fe64d03f3a350f1 upstream.
The CONFIG_DEFAULT_MMAP_MIN_ADDR was set to 65536 in mxs_defconfig, this caused severe breakage of userland applications since the upper limit for ARM is 32768. By default CONFIG_DEFAULT_MMAP_MIN_ADDR is set to 4096 and can also be changed via /proc/sys/vm/mmap_min_addr if needed.
Quoting Russell King [1]:
"4096 is also fine for ARM too. There's not much point in having defconfigs change it - that would just be pure noise in the config files."
the CONFIG_DEFAULT_MMAP_MIN_ADDR can be removed from the defconfig altogether.
This problem was introduced by commit cde7c41 (ARM: configs: add defconfig for mach-mxs).
[1] http://marc.info/?l=linux-arm-kernel&m=134401593807820&w=2
--- arch/arm/configs/mxs_defconfig | 1 - 1 file changed, 1 deletion(-)
arch/arm/configs/mxs_defconfig +0 -1
@@ -29,7 +29,6 @@ CONFIG_NO_HZ=y CONFIG_HIGH_RES_TIMERS=y CONFIG_PREEMPT_VOLUNTARY=y CONFIG_AEABI=y -CONFIG_DEFAULT_MMAP_MIN_ADDR=65536 CONFIG_AUTO_ZRELADDR=y CONFIG_FPE_NWFPE=y CONFIG_NET=y
Greg Kroah-Hartman
maintainerPATCH 39/44 ARM: pxa: remove irq_to_gpio from ezx-pcap driver
In reply to Greg Kroah-HartmanFrom: Greg KH <[email protected]>
3.0-stable review patch. If anyone has any objections, please let me know.
------------------
From: Arnd Bergmann <[email protected]>
commit 59ee93a528b94ef4e81a08db252b0326feff171f upstream.
The irq_to_gpio function was removed from the pxa platform in linux-3.2, and this driver has been broken since.
There is actually no in-tree user of this driver that adds this platform device, but the driver can and does get enabled on some platforms.
Without this patch, building ezx_defconfig results in:
drivers/mfd/ezx-pcap.c: In function 'pcap_isr_work':drivers/mfd/ezx-pcap.c:205:2: error: implicit declaration of function 'irq_to_gpio' [-Werror=implicit-function-declaration]
--- drivers/mfd/ezx-pcap.c | 2 +- include/linux/mfd/ezx-pcap.h | 1 + 2 files changed, 2 insertions(+), 1 deletion(-)
drivers/mfd/ezx-pcap.c +1 -1
@@ -202,7 +202,7 @@ static void pcap_isr_work(struct work_st }local_irq_enable ();ezx_pcap_write (pcap,PCAP_REG_MSR , pcap->msr); - }while (gpio_get_value (irq_to_gpio (pcap->spi->irq))); + }while (gpio_get_value (pdata->gpio)); }static void pcap_irq_handler (unsigned int irq,struct irq_desc *desc)
include/linux/mfd/ezx-pcap.h +1 -0
@@ -16,6 +16,7 @@ struct pcap_subdev {struct pcap_platform_data {unsigned int irq_base;unsigned int config; +int gpio;void (*init) (void *);/* board specific init */ int num_subdevs;struct pcap_subdev *subdevs;
Greg Kroah-Hartman
maintainerPATCH 40/44 cfg80211: process pending events when unregistering net device
In reply to Greg Kroah-HartmanFrom: Greg KH <[email protected]>
3.0-stable review patch. If anyone has any objections, please let me know.
------------------
From: Daniel Drake <[email protected]>
commit 1f6fc43e621167492ed4b7f3b4269c584c3d6ccc upstream.
libertas currently calls cfg80211_disconnected() when it is being brought down. This causes an event to be allocated, but since the wdev is already removed from the rdev by the time that the event processing work executes, the event is never processed or freed.
http://article.gmane.org/gmane.linux.kernel.wireless.general/95666
Fix this leak, and other possible situations, by processing the event queue when a device is being unregistered. Thanks to Johannes Berg for the suggestion.
--- net/wireless/core.c | 5 +++++ net/wireless/core.h | 1 + net/wireless/util.c | 2 +- 3 files changed, 7 insertions(+), 1 deletion(-)
net/wireless/core.c +5 -0
@@ -959,6 +959,11 @@ static int cfg80211_netdev_notifier_call*/ synchronize_rcu ();INIT_LIST_HEAD (&wdev->list); +/* +* Ensure that all events have been processed and +* freed. +*/ +cfg80211_process_wdev_events (wdev);break ;case NETDEV_PRE_UP :if (!(wdev->wiphy->interface_modes &BIT (wdev->iftype)))
net/wireless/core.h +1 -0
@@ -426,6 +426,7 @@ int cfg80211_change_iface(struct cfg8021 struct net_device *dev, enum nl80211_iftype ntype, u32 *flags, struct vif_params *params);void cfg80211_process_rdev_events (struct cfg80211_registered_device *rdev); +void cfg80211_process_wdev_events (struct wireless_dev *wdev); int cfg80211_can_change_interface(struct cfg80211_registered_device *rdev, struct wireless_dev *wdev,
net/wireless/util.c +1 -1
@@ -719,7 +719,7 @@ void cfg80211_upload_connect_keys(struct wdev->connect_keys =NULL ; } -static void cfg80211_process_wdev_events (struct wireless_dev *wdev) +void cfg80211_process_wdev_events (struct wireless_dev *wdev) {struct cfg80211_event *ev;unsigned long flags;
Greg Kroah-Hartman
maintainerPATCH 41/44 cfg80211: fix interface combinations check for ADHOC(IBSS)
In reply to Greg Kroah-HartmanFrom: Greg KH <[email protected]>
3.0-stable review patch. If anyone has any objections, please let me know.
------------------
From: Liang Li <[email protected]>
partial of commit 8e8b41f9d8c8e63fc92f899ace8da91a490ac573 upstream.
As part of commit 463454b5dbd8 ("cfg80211: fix interface combinations check"), this extra check was introduced:
if ((all_iftypes & used_iftypes) != used_iftypes)
goto cont;However, most wireless NIC drivers did not advertise ADHOC in wiphy.iface_combinations[i].limits[] and hence we'll get -EBUSY when we bring up a ADHOC wlan with commands similar to:
# iwconfig wlan0 mode ad-hoc && ifconfig wlan0 up
In commit 8e8b41f9d8c8e ("cfg80211: enforce lack of interface combinations"), the change below fixes the issue:
if (total == 1)
return 0;But it also introduces other dependencies for stable. For example, a full cherry pick of 8e8b41f9d8c8e would introduce additional regressions unless we also start cherry picking driver specific fixes like the following:
9b4760e ath5k: add possible wiphy interface combinations 1ae2fc2 mac80211_hwsim: advertise interface combinations 20c8e8d ath9k: add possible wiphy interface combinations
And the purpose of the 'if (total == 1)' is to cover the specific use case (IBSS, adhoc) that was mentioned above. So we just pick the specific part out from 8e8b41f9d8c8e here.
Doing so gives stable kernels a way to fix the change introduced by 463454b5dbd8, without having to make cherry picks specific to various NIC drivers.
--- net/wireless/util.c | 3 +++ 1 file changed, 3 insertions(+)
net/wireless/util.c +3 -0
@@ -975,6 +975,9 @@ int cfg80211_can_change_interface(struct }mutex_unlock (&rdev->devlist_mtx); +if (total ==1 ) +return 0 ; +for (i =0 ; i < rdev->wiphy.n_iface_combinations; i++) {const struct ieee80211_iface_combination *c;struct ieee80211_iface_limit *limits;
Greg Kroah-Hartman
maintainerPATCH 42/44 e1000e: NIC goes up and immediately goes down
In reply to Greg Kroah-HartmanFrom: Greg KH <[email protected]>
3.0-stable review patch. If anyone has any objections, please let me know.
------------------
From: Tushar Dave <[email protected]>
commit b7ec70be01a87f2c85df3ae11046e74f9b67e323 upstream.
Found that commit d478eb44 was a bad commit.
If the link partner is transmitting codeword (even if NULL codeword), then the RXCW.C bit will be set so check for RXCW.CW is unnecessary.
Ref: RH BZ 840642
--- drivers/net/e1000e/82571.c | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-)
drivers/net/e1000e/82571.c +1 -3
@@ -1602,10 +1602,8 @@ static s32 e1000_check_for_serdes_link_8* auto-negotiation in the TXCW register and disable * forced link in the Device Control register in an * attempt to auto-negotiate with our link partner. -* If the partner code word is null, stop forcing -* and restart auto negotiation. */ -if ((rxcw &E1000_RXCW_C ) || !(rxcw &E1000_RXCW_CW )) { +if (rxcw &E1000_RXCW_C ) {/* Enable autoneg, and unforce link up */ ew32 (TXCW , mac->txcw);ew32 (CTRL , (ctrl & ~E1000_CTRL_SLU ));
Greg Kroah-Hartman
maintainerPATCH 43/44 Input: wacom - Bamboo One 1024 pressure fix
In reply to Greg Kroah-HartmanFrom: Greg KH <[email protected]>
3.0-stable review patch. If anyone has any objections, please let me know.
------------------
From: Chris Bagwell <[email protected]>
commit 6dc463511d4a690f01a9248df3b384db717e0b1c upstream.
Bamboo One's with ID of 0x6a and 0x6b were added with correct indication of 1024 pressure levels but the Graphire packet routine was only looking at 9 bits. Increased to 10 bits.
This bug caused these devices to roll over to zero pressure at half way mark.
The other devices using this routine only support 256 or 512 range and look to fix unused bits at zero.
--- drivers/input/tablet/wacom_wac.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
drivers/input/tablet/wacom_wac.c +1 -1
@@ -242,7 +242,7 @@ static int wacom_graphire_irq(struct wacinput_report_abs (input,ABS_X ,le16_to_cpup ((__le16 *)&data[2 ]));input_report_abs (input,ABS_Y ,le16_to_cpup ((__le16 *)&data[4 ]));if (wacom->tool[0 ] !=BTN_TOOL_MOUSE ) { -input_report_abs (input,ABS_PRESSURE , data[6 ] | ((data[7 ] &0x01 ) <<8 )); +input_report_abs (input,ABS_PRESSURE , data[6 ] | ((data[7 ] &0x03 ) <<8 ));input_report_key (input,BTN_TOUCH , data[1 ] &0x01 );input_report_key (input,BTN_STYLUS , data[1 ] &0x02 );input_report_key (input,BTN_STYLUS2 , data[1 ] &0x04 );
Greg Kroah-Hartman
maintainerPATCH 44/44 rt61pci: fix NULL pointer dereference in config_lna_gain
In reply to Greg Kroah-HartmanFrom: Greg KH <[email protected]>
3.0-stable review patch. If anyone has any objections, please let me know.
------------------
From: Stanislaw Gruszka <[email protected]>
commit deee0214def5d8a32b8112f11d9c2b1696e9c0cb upstream.
We can not pass NULL libconf->conf->channel to rt61pci_config() as it is dereferenced unconditionally in rt61pci_config_lna_gain() subroutine.
Resolves:
https://bugzilla.kernel.org/show_bug.cgi?id=44361
--- drivers/net/wireless/rt2x00/rt61pci.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-)
drivers/net/wireless/rt2x00/rt61pci.c +1 -2
@@ -2254,8 +2254,7 @@ static void rt61pci_txdone(struct rt2x00static void rt61pci_wakeup (struct rt2x00_dev *rt2x00dev) { -struct ieee80211_conf conf = { .flags =0 }; -struct rt2x00lib_conf libconf = { .conf = &conf }; +struct rt2x00lib_conf libconf = { .conf = &rt2x00dev->hw->conf };rt61pci_config (rt2x00dev, &libconf,IEEE80211_CONF_CHANGE_PS ); }