* Typo in packaga name * Bump sunxi version to latest and add upstream patches for odroid xu4
8542 lines
284 KiB
Diff
8542 lines
284 KiB
Diff
diff --git a/Documentation/admin-guide/kernel-parameters.txt b/Documentation/admin-guide/kernel-parameters.txt
|
|
index cad17c7a311e9..db9d53b879f89 100644
|
|
--- a/Documentation/admin-guide/kernel-parameters.txt
|
|
+++ b/Documentation/admin-guide/kernel-parameters.txt
|
|
@@ -3842,6 +3842,12 @@
|
|
fully seed the kernel's CRNG. Default is controlled
|
|
by CONFIG_RANDOM_TRUST_CPU.
|
|
|
|
+ random.trust_bootloader={on,off}
|
|
+ [KNL] Enable or disable trusting the use of a
|
|
+ seed passed by the bootloader (if available) to
|
|
+ fully seed the kernel's CRNG. Default is controlled
|
|
+ by CONFIG_RANDOM_TRUST_BOOTLOADER.
|
|
+
|
|
ras=option[,option,...] [KNL] RAS-specific options
|
|
|
|
cec_disable [X86]
|
|
diff --git a/Documentation/admin-guide/sysctl/kernel.rst b/Documentation/admin-guide/sysctl/kernel.rst
|
|
index 7b477fa19534d..9715685be6e3b 100644
|
|
--- a/Documentation/admin-guide/sysctl/kernel.rst
|
|
+++ b/Documentation/admin-guide/sysctl/kernel.rst
|
|
@@ -862,9 +862,40 @@ The kernel command line parameter printk.devkmsg= overrides this and is
|
|
a one-time setting until next reboot: once set, it cannot be changed by
|
|
this sysctl interface anymore.
|
|
|
|
+pty
|
|
+===
|
|
|
|
-randomize_va_space:
|
|
-===================
|
|
+See Documentation/filesystems/devpts.rst.
|
|
+
|
|
+
|
|
+random
|
|
+======
|
|
+
|
|
+This is a directory, with the following entries:
|
|
+
|
|
+* ``boot_id``: a UUID generated the first time this is retrieved, and
|
|
+ unvarying after that;
|
|
+
|
|
+* ``uuid``: a UUID generated every time this is retrieved (this can
|
|
+ thus be used to generate UUIDs at will);
|
|
+
|
|
+* ``entropy_avail``: the pool's entropy count, in bits;
|
|
+
|
|
+* ``poolsize``: the entropy pool size, in bits;
|
|
+
|
|
+* ``urandom_min_reseed_secs``: obsolete (used to determine the minimum
|
|
+ number of seconds between urandom pool reseeding). This file is
|
|
+ writable for compatibility purposes, but writing to it has no effect
|
|
+ on any RNG behavior;
|
|
+
|
|
+* ``write_wakeup_threshold``: when the entropy count drops below this
|
|
+ (as a number of bits), processes waiting to write to ``/dev/random``
|
|
+ are woken up. This file is writable for compatibility purposes, but
|
|
+ writing to it has no effect on any RNG behavior.
|
|
+
|
|
+
|
|
+randomize_va_space
|
|
+==================
|
|
|
|
This option can be used to select the type of process address
|
|
space randomization that is used in the system, for architectures
|
|
diff --git a/MAINTAINERS b/MAINTAINERS
|
|
index 1407008df7491..f45d6548a4aa8 100644
|
|
--- a/MAINTAINERS
|
|
+++ b/MAINTAINERS
|
|
@@ -13640,6 +13640,7 @@ F: arch/mips/configs/generic/board-ranchu.config
|
|
|
|
RANDOM NUMBER DRIVER
|
|
M: "Theodore Ts'o" <tytso@mit.edu>
|
|
+M: Jason A. Donenfeld <Jason@zx2c4.com>
|
|
S: Maintained
|
|
F: drivers/char/random.c
|
|
|
|
diff --git a/Makefile b/Makefile
|
|
index a8d2f2a1c052a..32da9117e9d76 100644
|
|
--- a/Makefile
|
|
+++ b/Makefile
|
|
@@ -1,7 +1,7 @@
|
|
# SPDX-License-Identifier: GPL-2.0
|
|
VERSION = 5
|
|
PATCHLEVEL = 4
|
|
-SUBLEVEL = 199
|
|
+SUBLEVEL = 200
|
|
EXTRAVERSION =
|
|
NAME = Kleptomaniac Octopus
|
|
|
|
diff --git a/arch/alpha/include/asm/timex.h b/arch/alpha/include/asm/timex.h
|
|
index b565cc6f408e9..f89798da8a147 100644
|
|
--- a/arch/alpha/include/asm/timex.h
|
|
+++ b/arch/alpha/include/asm/timex.h
|
|
@@ -28,5 +28,6 @@ static inline cycles_t get_cycles (void)
|
|
__asm__ __volatile__ ("rpcc %0" : "=r"(ret));
|
|
return ret;
|
|
}
|
|
+#define get_cycles get_cycles
|
|
|
|
#endif
|
|
diff --git a/arch/arm/include/asm/timex.h b/arch/arm/include/asm/timex.h
|
|
index 7c3b3671d6c25..6d1337c169cd3 100644
|
|
--- a/arch/arm/include/asm/timex.h
|
|
+++ b/arch/arm/include/asm/timex.h
|
|
@@ -11,5 +11,6 @@
|
|
|
|
typedef unsigned long cycles_t;
|
|
#define get_cycles() ({ cycles_t c; read_current_timer(&c) ? 0 : c; })
|
|
+#define random_get_entropy() (((unsigned long)get_cycles()) ?: random_get_entropy_fallback())
|
|
|
|
#endif
|
|
diff --git a/arch/arm64/include/asm/brk-imm.h b/arch/arm64/include/asm/brk-imm.h
|
|
index e3d47b52161db..ec7720dbe2c80 100644
|
|
--- a/arch/arm64/include/asm/brk-imm.h
|
|
+++ b/arch/arm64/include/asm/brk-imm.h
|
|
@@ -10,6 +10,7 @@
|
|
* #imm16 values used for BRK instruction generation
|
|
* 0x004: for installing kprobes
|
|
* 0x005: for installing uprobes
|
|
+ * 0x006: for kprobe software single-step
|
|
* Allowed values for kgdb are 0x400 - 0x7ff
|
|
* 0x100: for triggering a fault on purpose (reserved)
|
|
* 0x400: for dynamic BRK instruction
|
|
@@ -19,6 +20,7 @@
|
|
*/
|
|
#define KPROBES_BRK_IMM 0x004
|
|
#define UPROBES_BRK_IMM 0x005
|
|
+#define KPROBES_BRK_SS_IMM 0x006
|
|
#define FAULT_BRK_IMM 0x100
|
|
#define KGDB_DYN_DBG_BRK_IMM 0x400
|
|
#define KGDB_COMPILED_DBG_BRK_IMM 0x401
|
|
diff --git a/arch/arm64/include/asm/debug-monitors.h b/arch/arm64/include/asm/debug-monitors.h
|
|
index d825e3585e28d..0253691c4b3a1 100644
|
|
--- a/arch/arm64/include/asm/debug-monitors.h
|
|
+++ b/arch/arm64/include/asm/debug-monitors.h
|
|
@@ -53,6 +53,7 @@
|
|
|
|
/* kprobes BRK opcodes with ESR encoding */
|
|
#define BRK64_OPCODE_KPROBES (AARCH64_BREAK_MON | (KPROBES_BRK_IMM << 5))
|
|
+#define BRK64_OPCODE_KPROBES_SS (AARCH64_BREAK_MON | (KPROBES_BRK_SS_IMM << 5))
|
|
/* uprobes BRK opcodes with ESR encoding */
|
|
#define BRK64_OPCODE_UPROBES (AARCH64_BREAK_MON | (UPROBES_BRK_IMM << 5))
|
|
|
|
diff --git a/arch/arm64/include/asm/kprobes.h b/arch/arm64/include/asm/kprobes.h
|
|
index 97e511d645a21..8699ce30f587e 100644
|
|
--- a/arch/arm64/include/asm/kprobes.h
|
|
+++ b/arch/arm64/include/asm/kprobes.h
|
|
@@ -16,7 +16,7 @@
|
|
#include <linux/percpu.h>
|
|
|
|
#define __ARCH_WANT_KPROBES_INSN_SLOT
|
|
-#define MAX_INSN_SIZE 1
|
|
+#define MAX_INSN_SIZE 2
|
|
|
|
#define flush_insn_slot(p) do { } while (0)
|
|
#define kretprobe_blacklist_size 0
|
|
diff --git a/arch/arm64/kernel/ftrace.c b/arch/arm64/kernel/ftrace.c
|
|
index 822718eafdb44..d4a4be02d309c 100644
|
|
--- a/arch/arm64/kernel/ftrace.c
|
|
+++ b/arch/arm64/kernel/ftrace.c
|
|
@@ -69,7 +69,7 @@ int ftrace_make_call(struct dyn_ftrace *rec, unsigned long addr)
|
|
{
|
|
unsigned long pc = rec->ip;
|
|
u32 old, new;
|
|
- long offset = (long)pc - (long)addr;
|
|
+ long offset = (long)addr - (long)pc;
|
|
|
|
if (offset < -SZ_128M || offset >= SZ_128M) {
|
|
#ifdef CONFIG_ARM64_MODULE_PLTS
|
|
@@ -126,7 +126,7 @@ int ftrace_make_nop(struct module *mod, struct dyn_ftrace *rec,
|
|
unsigned long pc = rec->ip;
|
|
bool validate = true;
|
|
u32 old = 0, new;
|
|
- long offset = (long)pc - (long)addr;
|
|
+ long offset = (long)addr - (long)pc;
|
|
|
|
if (offset < -SZ_128M || offset >= SZ_128M) {
|
|
#ifdef CONFIG_ARM64_MODULE_PLTS
|
|
diff --git a/arch/arm64/kernel/probes/kprobes.c b/arch/arm64/kernel/probes/kprobes.c
|
|
index c4452827419b0..b41ed2f907b0e 100644
|
|
--- a/arch/arm64/kernel/probes/kprobes.c
|
|
+++ b/arch/arm64/kernel/probes/kprobes.c
|
|
@@ -36,25 +36,16 @@ DEFINE_PER_CPU(struct kprobe_ctlblk, kprobe_ctlblk);
|
|
static void __kprobes
|
|
post_kprobe_handler(struct kprobe_ctlblk *, struct pt_regs *);
|
|
|
|
-static int __kprobes patch_text(kprobe_opcode_t *addr, u32 opcode)
|
|
-{
|
|
- void *addrs[1];
|
|
- u32 insns[1];
|
|
-
|
|
- addrs[0] = addr;
|
|
- insns[0] = opcode;
|
|
-
|
|
- return aarch64_insn_patch_text(addrs, insns, 1);
|
|
-}
|
|
-
|
|
static void __kprobes arch_prepare_ss_slot(struct kprobe *p)
|
|
{
|
|
+ kprobe_opcode_t *addr = p->ainsn.api.insn;
|
|
+ void *addrs[] = {addr, addr + 1};
|
|
+ u32 insns[] = {p->opcode, BRK64_OPCODE_KPROBES_SS};
|
|
+
|
|
/* prepare insn slot */
|
|
- patch_text(p->ainsn.api.insn, p->opcode);
|
|
+ aarch64_insn_patch_text(addrs, insns, 2);
|
|
|
|
- flush_icache_range((uintptr_t) (p->ainsn.api.insn),
|
|
- (uintptr_t) (p->ainsn.api.insn) +
|
|
- MAX_INSN_SIZE * sizeof(kprobe_opcode_t));
|
|
+ flush_icache_range((uintptr_t)addr, (uintptr_t)(addr + MAX_INSN_SIZE));
|
|
|
|
/*
|
|
* Needs restoring of return address after stepping xol.
|
|
@@ -134,13 +125,18 @@ void *alloc_insn_page(void)
|
|
/* arm kprobe: install breakpoint in text */
|
|
void __kprobes arch_arm_kprobe(struct kprobe *p)
|
|
{
|
|
- patch_text(p->addr, BRK64_OPCODE_KPROBES);
|
|
+ void *addr = p->addr;
|
|
+ u32 insn = BRK64_OPCODE_KPROBES;
|
|
+
|
|
+ aarch64_insn_patch_text(&addr, &insn, 1);
|
|
}
|
|
|
|
/* disarm kprobe: remove breakpoint from text */
|
|
void __kprobes arch_disarm_kprobe(struct kprobe *p)
|
|
{
|
|
- patch_text(p->addr, p->opcode);
|
|
+ void *addr = p->addr;
|
|
+
|
|
+ aarch64_insn_patch_text(&addr, &p->opcode, 1);
|
|
}
|
|
|
|
void __kprobes arch_remove_kprobe(struct kprobe *p)
|
|
@@ -169,20 +165,15 @@ static void __kprobes set_current_kprobe(struct kprobe *p)
|
|
}
|
|
|
|
/*
|
|
- * Interrupts need to be disabled before single-step mode is set, and not
|
|
- * reenabled until after single-step mode ends.
|
|
- * Without disabling interrupt on local CPU, there is a chance of
|
|
- * interrupt occurrence in the period of exception return and start of
|
|
- * out-of-line single-step, that result in wrongly single stepping
|
|
- * into the interrupt handler.
|
|
+ * Mask all of DAIF while executing the instruction out-of-line, to keep things
|
|
+ * simple and avoid nesting exceptions. Interrupts do have to be disabled since
|
|
+ * the kprobe state is per-CPU and doesn't get migrated.
|
|
*/
|
|
static void __kprobes kprobes_save_local_irqflag(struct kprobe_ctlblk *kcb,
|
|
struct pt_regs *regs)
|
|
{
|
|
kcb->saved_irqflag = regs->pstate & DAIF_MASK;
|
|
- regs->pstate |= PSR_I_BIT;
|
|
- /* Unmask PSTATE.D for enabling software step exceptions. */
|
|
- regs->pstate &= ~PSR_D_BIT;
|
|
+ regs->pstate |= DAIF_MASK;
|
|
}
|
|
|
|
static void __kprobes kprobes_restore_local_irqflag(struct kprobe_ctlblk *kcb,
|
|
@@ -225,10 +216,7 @@ static void __kprobes setup_singlestep(struct kprobe *p,
|
|
slot = (unsigned long)p->ainsn.api.insn;
|
|
|
|
set_ss_context(kcb, slot); /* mark pending ss */
|
|
-
|
|
- /* IRQs and single stepping do not mix well. */
|
|
kprobes_save_local_irqflag(kcb, regs);
|
|
- kernel_enable_single_step(regs);
|
|
instruction_pointer_set(regs, slot);
|
|
} else {
|
|
/* insn simulation */
|
|
@@ -279,12 +267,8 @@ post_kprobe_handler(struct kprobe_ctlblk *kcb, struct pt_regs *regs)
|
|
}
|
|
/* call post handler */
|
|
kcb->kprobe_status = KPROBE_HIT_SSDONE;
|
|
- if (cur->post_handler) {
|
|
- /* post_handler can hit breakpoint and single step
|
|
- * again, so we enable D-flag for recursive exception.
|
|
- */
|
|
+ if (cur->post_handler)
|
|
cur->post_handler(cur, regs, 0);
|
|
- }
|
|
|
|
reset_current_kprobe();
|
|
}
|
|
@@ -308,8 +292,6 @@ int __kprobes kprobe_fault_handler(struct pt_regs *regs, unsigned int fsr)
|
|
if (!instruction_pointer(regs))
|
|
BUG();
|
|
|
|
- kernel_disable_single_step();
|
|
-
|
|
if (kcb->kprobe_status == KPROBE_REENTER)
|
|
restore_previous_kprobe(kcb);
|
|
else
|
|
@@ -371,10 +353,6 @@ static void __kprobes kprobe_handler(struct pt_regs *regs)
|
|
* pre-handler and it returned non-zero, it will
|
|
* modify the execution path and no need to single
|
|
* stepping. Let's just reset current kprobe and exit.
|
|
- *
|
|
- * pre_handler can hit a breakpoint and can step thru
|
|
- * before return, keep PSTATE D-flag enabled until
|
|
- * pre_handler return back.
|
|
*/
|
|
if (!p->pre_handler || !p->pre_handler(p, regs)) {
|
|
setup_singlestep(p, regs, kcb, 0);
|
|
@@ -405,7 +383,7 @@ kprobe_ss_hit(struct kprobe_ctlblk *kcb, unsigned long addr)
|
|
}
|
|
|
|
static int __kprobes
|
|
-kprobe_single_step_handler(struct pt_regs *regs, unsigned int esr)
|
|
+kprobe_breakpoint_ss_handler(struct pt_regs *regs, unsigned int esr)
|
|
{
|
|
struct kprobe_ctlblk *kcb = get_kprobe_ctlblk();
|
|
int retval;
|
|
@@ -415,16 +393,15 @@ kprobe_single_step_handler(struct pt_regs *regs, unsigned int esr)
|
|
|
|
if (retval == DBG_HOOK_HANDLED) {
|
|
kprobes_restore_local_irqflag(kcb, regs);
|
|
- kernel_disable_single_step();
|
|
-
|
|
post_kprobe_handler(kcb, regs);
|
|
}
|
|
|
|
return retval;
|
|
}
|
|
|
|
-static struct step_hook kprobes_step_hook = {
|
|
- .fn = kprobe_single_step_handler,
|
|
+static struct break_hook kprobes_break_ss_hook = {
|
|
+ .imm = KPROBES_BRK_SS_IMM,
|
|
+ .fn = kprobe_breakpoint_ss_handler,
|
|
};
|
|
|
|
static int __kprobes
|
|
@@ -568,7 +545,7 @@ int __kprobes arch_trampoline_kprobe(struct kprobe *p)
|
|
int __init arch_init_kprobes(void)
|
|
{
|
|
register_kernel_break_hook(&kprobes_break_hook);
|
|
- register_kernel_step_hook(&kprobes_step_hook);
|
|
+ register_kernel_break_hook(&kprobes_break_ss_hook);
|
|
|
|
return 0;
|
|
}
|
|
diff --git a/arch/ia64/include/asm/timex.h b/arch/ia64/include/asm/timex.h
|
|
index 869a3ac6bf23a..7ccc077a60bed 100644
|
|
--- a/arch/ia64/include/asm/timex.h
|
|
+++ b/arch/ia64/include/asm/timex.h
|
|
@@ -39,6 +39,7 @@ get_cycles (void)
|
|
ret = ia64_getreg(_IA64_REG_AR_ITC);
|
|
return ret;
|
|
}
|
|
+#define get_cycles get_cycles
|
|
|
|
extern void ia64_cpu_local_tick (void);
|
|
extern unsigned long long ia64_native_sched_clock (void);
|
|
diff --git a/arch/m68k/include/asm/timex.h b/arch/m68k/include/asm/timex.h
|
|
index 6a21d93582805..f4a7a340f4cae 100644
|
|
--- a/arch/m68k/include/asm/timex.h
|
|
+++ b/arch/m68k/include/asm/timex.h
|
|
@@ -35,7 +35,7 @@ static inline unsigned long random_get_entropy(void)
|
|
{
|
|
if (mach_random_get_entropy)
|
|
return mach_random_get_entropy();
|
|
- return 0;
|
|
+ return random_get_entropy_fallback();
|
|
}
|
|
#define random_get_entropy random_get_entropy
|
|
|
|
diff --git a/arch/mips/include/asm/timex.h b/arch/mips/include/asm/timex.h
|
|
index 8026baf46e729..2e107886f97ac 100644
|
|
--- a/arch/mips/include/asm/timex.h
|
|
+++ b/arch/mips/include/asm/timex.h
|
|
@@ -76,25 +76,24 @@ static inline cycles_t get_cycles(void)
|
|
else
|
|
return 0; /* no usable counter */
|
|
}
|
|
+#define get_cycles get_cycles
|
|
|
|
/*
|
|
* Like get_cycles - but where c0_count is not available we desperately
|
|
* use c0_random in an attempt to get at least a little bit of entropy.
|
|
- *
|
|
- * R6000 and R6000A neither have a count register nor a random register.
|
|
- * That leaves no entropy source in the CPU itself.
|
|
*/
|
|
static inline unsigned long random_get_entropy(void)
|
|
{
|
|
- unsigned int prid = read_c0_prid();
|
|
- unsigned int imp = prid & PRID_IMP_MASK;
|
|
+ unsigned int c0_random;
|
|
|
|
- if (can_use_mips_counter(prid))
|
|
+ if (can_use_mips_counter(read_c0_prid()))
|
|
return read_c0_count();
|
|
- else if (likely(imp != PRID_IMP_R6000 && imp != PRID_IMP_R6000A))
|
|
- return read_c0_random();
|
|
+
|
|
+ if (cpu_has_3kex)
|
|
+ c0_random = (read_c0_random() >> 8) & 0x3f;
|
|
else
|
|
- return 0; /* no usable register */
|
|
+ c0_random = read_c0_random() & 0x3f;
|
|
+ return (random_get_entropy_fallback() << 6) | (0x3f - c0_random);
|
|
}
|
|
#define random_get_entropy random_get_entropy
|
|
|
|
diff --git a/arch/nios2/include/asm/timex.h b/arch/nios2/include/asm/timex.h
|
|
index a769f871b28d9..40a1adc9bd03e 100644
|
|
--- a/arch/nios2/include/asm/timex.h
|
|
+++ b/arch/nios2/include/asm/timex.h
|
|
@@ -8,5 +8,8 @@
|
|
typedef unsigned long cycles_t;
|
|
|
|
extern cycles_t get_cycles(void);
|
|
+#define get_cycles get_cycles
|
|
+
|
|
+#define random_get_entropy() (((unsigned long)get_cycles()) ?: random_get_entropy_fallback())
|
|
|
|
#endif
|
|
diff --git a/arch/parisc/include/asm/timex.h b/arch/parisc/include/asm/timex.h
|
|
index 45537cd4d1d39..1cd2bd3eef33b 100644
|
|
--- a/arch/parisc/include/asm/timex.h
|
|
+++ b/arch/parisc/include/asm/timex.h
|
|
@@ -12,9 +12,10 @@
|
|
|
|
typedef unsigned long cycles_t;
|
|
|
|
-static inline cycles_t get_cycles (void)
|
|
+static inline cycles_t get_cycles(void)
|
|
{
|
|
return mfctl(16);
|
|
}
|
|
+#define get_cycles get_cycles
|
|
|
|
#endif
|
|
diff --git a/arch/powerpc/include/asm/archrandom.h b/arch/powerpc/include/asm/archrandom.h
|
|
index a09595f00cabe..f0f16b4fc5ea1 100644
|
|
--- a/arch/powerpc/include/asm/archrandom.h
|
|
+++ b/arch/powerpc/include/asm/archrandom.h
|
|
@@ -6,27 +6,28 @@
|
|
|
|
#include <asm/machdep.h>
|
|
|
|
-static inline int arch_get_random_long(unsigned long *v)
|
|
+static inline bool arch_get_random_long(unsigned long *v)
|
|
{
|
|
- return 0;
|
|
+ return false;
|
|
}
|
|
|
|
-static inline int arch_get_random_int(unsigned int *v)
|
|
+static inline bool arch_get_random_int(unsigned int *v)
|
|
{
|
|
- return 0;
|
|
+ return false;
|
|
}
|
|
|
|
-static inline int arch_get_random_seed_long(unsigned long *v)
|
|
+static inline bool arch_get_random_seed_long(unsigned long *v)
|
|
{
|
|
if (ppc_md.get_random_seed)
|
|
return ppc_md.get_random_seed(v);
|
|
|
|
- return 0;
|
|
+ return false;
|
|
}
|
|
-static inline int arch_get_random_seed_int(unsigned int *v)
|
|
+
|
|
+static inline bool arch_get_random_seed_int(unsigned int *v)
|
|
{
|
|
unsigned long val;
|
|
- int rc;
|
|
+ bool rc;
|
|
|
|
rc = arch_get_random_seed_long(&val);
|
|
if (rc)
|
|
@@ -34,16 +35,6 @@ static inline int arch_get_random_seed_int(unsigned int *v)
|
|
|
|
return rc;
|
|
}
|
|
-
|
|
-static inline int arch_has_random(void)
|
|
-{
|
|
- return 0;
|
|
-}
|
|
-
|
|
-static inline int arch_has_random_seed(void)
|
|
-{
|
|
- return !!ppc_md.get_random_seed;
|
|
-}
|
|
#endif /* CONFIG_ARCH_RANDOM */
|
|
|
|
#ifdef CONFIG_PPC_POWERNV
|
|
diff --git a/arch/powerpc/include/asm/ppc-opcode.h b/arch/powerpc/include/asm/ppc-opcode.h
|
|
index c1df75edde441..a9af63bd430f2 100644
|
|
--- a/arch/powerpc/include/asm/ppc-opcode.h
|
|
+++ b/arch/powerpc/include/asm/ppc-opcode.h
|
|
@@ -204,6 +204,7 @@
|
|
#define PPC_INST_ICBT 0x7c00002c
|
|
#define PPC_INST_ICSWX 0x7c00032d
|
|
#define PPC_INST_ICSWEPX 0x7c00076d
|
|
+#define PPC_INST_DSSALL 0x7e00066c
|
|
#define PPC_INST_ISEL 0x7c00001e
|
|
#define PPC_INST_ISEL_MASK 0xfc00003e
|
|
#define PPC_INST_LDARX 0x7c0000a8
|
|
@@ -439,6 +440,7 @@
|
|
__PPC_RA(a) | __PPC_RB(b))
|
|
#define PPC_DCBZL(a, b) stringify_in_c(.long PPC_INST_DCBZL | \
|
|
__PPC_RA(a) | __PPC_RB(b))
|
|
+#define PPC_DSSALL stringify_in_c(.long PPC_INST_DSSALL)
|
|
#define PPC_LQARX(t, a, b, eh) stringify_in_c(.long PPC_INST_LQARX | \
|
|
___PPC_RT(t) | ___PPC_RA(a) | \
|
|
___PPC_RB(b) | __PPC_EH(eh))
|
|
diff --git a/arch/powerpc/include/asm/timex.h b/arch/powerpc/include/asm/timex.h
|
|
index 6047402b0a4db..5405cb2fe65a2 100644
|
|
--- a/arch/powerpc/include/asm/timex.h
|
|
+++ b/arch/powerpc/include/asm/timex.h
|
|
@@ -22,6 +22,7 @@ static inline cycles_t get_cycles(void)
|
|
|
|
return mftb();
|
|
}
|
|
+#define get_cycles get_cycles
|
|
|
|
#endif /* __KERNEL__ */
|
|
#endif /* _ASM_POWERPC_TIMEX_H */
|
|
diff --git a/arch/powerpc/kernel/idle_6xx.S b/arch/powerpc/kernel/idle_6xx.S
|
|
index 0ffdd18b9f268..acb8215c5a01d 100644
|
|
--- a/arch/powerpc/kernel/idle_6xx.S
|
|
+++ b/arch/powerpc/kernel/idle_6xx.S
|
|
@@ -129,7 +129,7 @@ BEGIN_FTR_SECTION
|
|
END_FTR_SECTION_IFCLR(CPU_FTR_NO_DPM)
|
|
mtspr SPRN_HID0,r4
|
|
BEGIN_FTR_SECTION
|
|
- DSSALL
|
|
+ PPC_DSSALL
|
|
sync
|
|
END_FTR_SECTION_IFSET(CPU_FTR_ALTIVEC)
|
|
lwz r8,TI_LOCAL_FLAGS(r2) /* set napping bit */
|
|
diff --git a/arch/powerpc/kernel/l2cr_6xx.S b/arch/powerpc/kernel/l2cr_6xx.S
|
|
index 2020d255585fa..7684f644e93e4 100644
|
|
--- a/arch/powerpc/kernel/l2cr_6xx.S
|
|
+++ b/arch/powerpc/kernel/l2cr_6xx.S
|
|
@@ -96,7 +96,7 @@ END_FTR_SECTION_IFCLR(CPU_FTR_L2CR)
|
|
|
|
/* Stop DST streams */
|
|
BEGIN_FTR_SECTION
|
|
- DSSALL
|
|
+ PPC_DSSALL
|
|
sync
|
|
END_FTR_SECTION_IFSET(CPU_FTR_ALTIVEC)
|
|
|
|
@@ -293,7 +293,7 @@ END_FTR_SECTION_IFCLR(CPU_FTR_L3CR)
|
|
isync
|
|
|
|
/* Stop DST streams */
|
|
- DSSALL
|
|
+ PPC_DSSALL
|
|
sync
|
|
|
|
/* Get the current enable bit of the L3CR into r4 */
|
|
@@ -402,7 +402,7 @@ END_FTR_SECTION_IFSET(CPU_FTR_L3CR)
|
|
_GLOBAL(__flush_disable_L1)
|
|
/* Stop pending alitvec streams and memory accesses */
|
|
BEGIN_FTR_SECTION
|
|
- DSSALL
|
|
+ PPC_DSSALL
|
|
END_FTR_SECTION_IFSET(CPU_FTR_ALTIVEC)
|
|
sync
|
|
|
|
diff --git a/arch/powerpc/kernel/process.c b/arch/powerpc/kernel/process.c
|
|
index c94bba9142e7e..832663f214226 100644
|
|
--- a/arch/powerpc/kernel/process.c
|
|
+++ b/arch/powerpc/kernel/process.c
|
|
@@ -2001,12 +2001,12 @@ static unsigned long __get_wchan(struct task_struct *p)
|
|
return 0;
|
|
|
|
do {
|
|
- sp = *(unsigned long *)sp;
|
|
+ sp = READ_ONCE_NOCHECK(*(unsigned long *)sp);
|
|
if (!validate_sp(sp, p, STACK_FRAME_OVERHEAD) ||
|
|
p->state == TASK_RUNNING)
|
|
return 0;
|
|
if (count > 0) {
|
|
- ip = ((unsigned long *)sp)[STACK_FRAME_LR_SAVE];
|
|
+ ip = READ_ONCE_NOCHECK(((unsigned long *)sp)[STACK_FRAME_LR_SAVE]);
|
|
if (!in_sched_functions(ip))
|
|
return ip;
|
|
}
|
|
diff --git a/arch/powerpc/kernel/swsusp_32.S b/arch/powerpc/kernel/swsusp_32.S
|
|
index cbdf86228eaaa..54c44aea338c4 100644
|
|
--- a/arch/powerpc/kernel/swsusp_32.S
|
|
+++ b/arch/powerpc/kernel/swsusp_32.S
|
|
@@ -181,7 +181,7 @@ _GLOBAL(swsusp_arch_resume)
|
|
#ifdef CONFIG_ALTIVEC
|
|
/* Stop pending alitvec streams and memory accesses */
|
|
BEGIN_FTR_SECTION
|
|
- DSSALL
|
|
+ PPC_DSSALL
|
|
END_FTR_SECTION_IFSET(CPU_FTR_ALTIVEC)
|
|
#endif
|
|
sync
|
|
diff --git a/arch/powerpc/kernel/swsusp_asm64.S b/arch/powerpc/kernel/swsusp_asm64.S
|
|
index 6d3189830dd32..068a268a8013e 100644
|
|
--- a/arch/powerpc/kernel/swsusp_asm64.S
|
|
+++ b/arch/powerpc/kernel/swsusp_asm64.S
|
|
@@ -142,7 +142,7 @@ END_FW_FTR_SECTION_IFCLR(FW_FEATURE_LPAR)
|
|
_GLOBAL(swsusp_arch_resume)
|
|
/* Stop pending alitvec streams and memory accesses */
|
|
BEGIN_FTR_SECTION
|
|
- DSSALL
|
|
+ PPC_DSSALL
|
|
END_FTR_SECTION_IFSET(CPU_FTR_ALTIVEC)
|
|
sync
|
|
|
|
diff --git a/arch/powerpc/mm/mmu_context.c b/arch/powerpc/mm/mmu_context.c
|
|
index 18f20da0d3483..64290d343b557 100644
|
|
--- a/arch/powerpc/mm/mmu_context.c
|
|
+++ b/arch/powerpc/mm/mmu_context.c
|
|
@@ -79,7 +79,7 @@ void switch_mm_irqs_off(struct mm_struct *prev, struct mm_struct *next,
|
|
* context
|
|
*/
|
|
if (cpu_has_feature(CPU_FTR_ALTIVEC))
|
|
- asm volatile ("dssall");
|
|
+ asm volatile (PPC_DSSALL);
|
|
|
|
if (new_on_cpu)
|
|
radix_kvm_prefetch_workaround(next);
|
|
diff --git a/arch/powerpc/platforms/powermac/cache.S b/arch/powerpc/platforms/powermac/cache.S
|
|
index da69e0fcb4f15..9b85b030cbebb 100644
|
|
--- a/arch/powerpc/platforms/powermac/cache.S
|
|
+++ b/arch/powerpc/platforms/powermac/cache.S
|
|
@@ -48,7 +48,7 @@ flush_disable_75x:
|
|
|
|
/* Stop DST streams */
|
|
BEGIN_FTR_SECTION
|
|
- DSSALL
|
|
+ PPC_DSSALL
|
|
sync
|
|
END_FTR_SECTION_IFSET(CPU_FTR_ALTIVEC)
|
|
|
|
@@ -196,7 +196,7 @@ flush_disable_745x:
|
|
isync
|
|
|
|
/* Stop prefetch streams */
|
|
- DSSALL
|
|
+ PPC_DSSALL
|
|
sync
|
|
|
|
/* Disable L2 prefetching */
|
|
diff --git a/arch/riscv/include/asm/asm-prototypes.h b/arch/riscv/include/asm/asm-prototypes.h
|
|
index c9fecd120d187..8ae9708a8eee8 100644
|
|
--- a/arch/riscv/include/asm/asm-prototypes.h
|
|
+++ b/arch/riscv/include/asm/asm-prototypes.h
|
|
@@ -4,4 +4,8 @@
|
|
#include <linux/ftrace.h>
|
|
#include <asm-generic/asm-prototypes.h>
|
|
|
|
+long long __lshrti3(long long a, int b);
|
|
+long long __ashrti3(long long a, int b);
|
|
+long long __ashlti3(long long a, int b);
|
|
+
|
|
#endif /* _ASM_RISCV_PROTOTYPES_H */
|
|
diff --git a/arch/riscv/include/asm/processor.h b/arch/riscv/include/asm/processor.h
|
|
index f539149d04c20..8c5b11a640dd3 100644
|
|
--- a/arch/riscv/include/asm/processor.h
|
|
+++ b/arch/riscv/include/asm/processor.h
|
|
@@ -22,6 +22,8 @@
|
|
|
|
#ifndef __ASSEMBLY__
|
|
|
|
+#include <asm/barrier.h>
|
|
+
|
|
struct task_struct;
|
|
struct pt_regs;
|
|
|
|
diff --git a/arch/riscv/lib/tishift.S b/arch/riscv/lib/tishift.S
|
|
index 15f9d54c7db63..ef90075c4b0a9 100644
|
|
--- a/arch/riscv/lib/tishift.S
|
|
+++ b/arch/riscv/lib/tishift.S
|
|
@@ -4,34 +4,73 @@
|
|
*/
|
|
|
|
#include <linux/linkage.h>
|
|
+#include <asm-generic/export.h>
|
|
|
|
-ENTRY(__lshrti3)
|
|
+SYM_FUNC_START(__lshrti3)
|
|
beqz a2, .L1
|
|
li a5,64
|
|
sub a5,a5,a2
|
|
- addi sp,sp,-16
|
|
sext.w a4,a5
|
|
blez a5, .L2
|
|
sext.w a2,a2
|
|
- sll a4,a1,a4
|
|
srl a0,a0,a2
|
|
- srl a1,a1,a2
|
|
+ sll a4,a1,a4
|
|
+ srl a2,a1,a2
|
|
or a0,a0,a4
|
|
- sd a1,8(sp)
|
|
- sd a0,0(sp)
|
|
- ld a0,0(sp)
|
|
- ld a1,8(sp)
|
|
- addi sp,sp,16
|
|
- ret
|
|
+ mv a1,a2
|
|
.L1:
|
|
ret
|
|
.L2:
|
|
- negw a4,a4
|
|
- srl a1,a1,a4
|
|
- sd a1,0(sp)
|
|
- sd zero,8(sp)
|
|
- ld a0,0(sp)
|
|
- ld a1,8(sp)
|
|
- addi sp,sp,16
|
|
+ negw a0,a4
|
|
+ li a2,0
|
|
+ srl a0,a1,a0
|
|
+ mv a1,a2
|
|
+ ret
|
|
+SYM_FUNC_END(__lshrti3)
|
|
+EXPORT_SYMBOL(__lshrti3)
|
|
+
|
|
+SYM_FUNC_START(__ashrti3)
|
|
+ beqz a2, .L3
|
|
+ li a5,64
|
|
+ sub a5,a5,a2
|
|
+ sext.w a4,a5
|
|
+ blez a5, .L4
|
|
+ sext.w a2,a2
|
|
+ srl a0,a0,a2
|
|
+ sll a4,a1,a4
|
|
+ sra a2,a1,a2
|
|
+ or a0,a0,a4
|
|
+ mv a1,a2
|
|
+.L3:
|
|
+ ret
|
|
+.L4:
|
|
+ negw a0,a4
|
|
+ srai a2,a1,0x3f
|
|
+ sra a0,a1,a0
|
|
+ mv a1,a2
|
|
+ ret
|
|
+SYM_FUNC_END(__ashrti3)
|
|
+EXPORT_SYMBOL(__ashrti3)
|
|
+
|
|
+SYM_FUNC_START(__ashlti3)
|
|
+ beqz a2, .L5
|
|
+ li a5,64
|
|
+ sub a5,a5,a2
|
|
+ sext.w a4,a5
|
|
+ blez a5, .L6
|
|
+ sext.w a2,a2
|
|
+ sll a1,a1,a2
|
|
+ srl a4,a0,a4
|
|
+ sll a2,a0,a2
|
|
+ or a1,a1,a4
|
|
+ mv a0,a2
|
|
+.L5:
|
|
+ ret
|
|
+.L6:
|
|
+ negw a1,a4
|
|
+ li a2,0
|
|
+ sll a1,a0,a1
|
|
+ mv a0,a2
|
|
ret
|
|
-ENDPROC(__lshrti3)
|
|
+SYM_FUNC_END(__ashlti3)
|
|
+EXPORT_SYMBOL(__ashlti3)
|
|
diff --git a/arch/s390/include/asm/archrandom.h b/arch/s390/include/asm/archrandom.h
|
|
index c67b82dfa558e..9a6835137a164 100644
|
|
--- a/arch/s390/include/asm/archrandom.h
|
|
+++ b/arch/s390/include/asm/archrandom.h
|
|
@@ -21,18 +21,6 @@ extern atomic64_t s390_arch_random_counter;
|
|
|
|
bool s390_arch_random_generate(u8 *buf, unsigned int nbytes);
|
|
|
|
-static inline bool arch_has_random(void)
|
|
-{
|
|
- return false;
|
|
-}
|
|
-
|
|
-static inline bool arch_has_random_seed(void)
|
|
-{
|
|
- if (static_branch_likely(&s390_arch_random_available))
|
|
- return true;
|
|
- return false;
|
|
-}
|
|
-
|
|
static inline bool arch_get_random_long(unsigned long *v)
|
|
{
|
|
return false;
|
|
diff --git a/arch/s390/include/asm/timex.h b/arch/s390/include/asm/timex.h
|
|
index b6a4ce9dafafb..99a7e028232d8 100644
|
|
--- a/arch/s390/include/asm/timex.h
|
|
+++ b/arch/s390/include/asm/timex.h
|
|
@@ -177,6 +177,7 @@ static inline cycles_t get_cycles(void)
|
|
{
|
|
return (cycles_t) get_tod_clock() >> 2;
|
|
}
|
|
+#define get_cycles get_cycles
|
|
|
|
int get_phys_clock(unsigned long *clock);
|
|
void init_cpu_timer(void);
|
|
diff --git a/arch/sparc/include/asm/timex_32.h b/arch/sparc/include/asm/timex_32.h
|
|
index 542915b462097..f86326a6f89e0 100644
|
|
--- a/arch/sparc/include/asm/timex_32.h
|
|
+++ b/arch/sparc/include/asm/timex_32.h
|
|
@@ -9,8 +9,6 @@
|
|
|
|
#define CLOCK_TICK_RATE 1193180 /* Underlying HZ */
|
|
|
|
-/* XXX Maybe do something better at some point... -DaveM */
|
|
-typedef unsigned long cycles_t;
|
|
-#define get_cycles() (0)
|
|
+#include <asm-generic/timex.h>
|
|
|
|
#endif
|
|
diff --git a/arch/um/include/asm/timex.h b/arch/um/include/asm/timex.h
|
|
index e392a9a5bc9bd..9f27176adb26d 100644
|
|
--- a/arch/um/include/asm/timex.h
|
|
+++ b/arch/um/include/asm/timex.h
|
|
@@ -2,13 +2,8 @@
|
|
#ifndef __UM_TIMEX_H
|
|
#define __UM_TIMEX_H
|
|
|
|
-typedef unsigned long cycles_t;
|
|
-
|
|
-static inline cycles_t get_cycles (void)
|
|
-{
|
|
- return 0;
|
|
-}
|
|
-
|
|
#define CLOCK_TICK_RATE (HZ)
|
|
|
|
+#include <asm-generic/timex.h>
|
|
+
|
|
#endif
|
|
diff --git a/arch/x86/include/asm/archrandom.h b/arch/x86/include/asm/archrandom.h
|
|
index af45e1452f097..feb59461046c6 100644
|
|
--- a/arch/x86/include/asm/archrandom.h
|
|
+++ b/arch/x86/include/asm/archrandom.h
|
|
@@ -73,10 +73,6 @@ static inline bool rdseed_int(unsigned int *v)
|
|
return ok;
|
|
}
|
|
|
|
-/* Conditional execution based on CPU type */
|
|
-#define arch_has_random() static_cpu_has(X86_FEATURE_RDRAND)
|
|
-#define arch_has_random_seed() static_cpu_has(X86_FEATURE_RDSEED)
|
|
-
|
|
/*
|
|
* These are the generic interfaces; they must not be declared if the
|
|
* stubs in <linux/random.h> are to be invoked,
|
|
@@ -86,22 +82,22 @@ static inline bool rdseed_int(unsigned int *v)
|
|
|
|
static inline bool arch_get_random_long(unsigned long *v)
|
|
{
|
|
- return arch_has_random() ? rdrand_long(v) : false;
|
|
+ return static_cpu_has(X86_FEATURE_RDRAND) ? rdrand_long(v) : false;
|
|
}
|
|
|
|
static inline bool arch_get_random_int(unsigned int *v)
|
|
{
|
|
- return arch_has_random() ? rdrand_int(v) : false;
|
|
+ return static_cpu_has(X86_FEATURE_RDRAND) ? rdrand_int(v) : false;
|
|
}
|
|
|
|
static inline bool arch_get_random_seed_long(unsigned long *v)
|
|
{
|
|
- return arch_has_random_seed() ? rdseed_long(v) : false;
|
|
+ return static_cpu_has(X86_FEATURE_RDSEED) ? rdseed_long(v) : false;
|
|
}
|
|
|
|
static inline bool arch_get_random_seed_int(unsigned int *v)
|
|
{
|
|
- return arch_has_random_seed() ? rdseed_int(v) : false;
|
|
+ return static_cpu_has(X86_FEATURE_RDSEED) ? rdseed_int(v) : false;
|
|
}
|
|
|
|
extern void x86_init_rdrand(struct cpuinfo_x86 *c);
|
|
diff --git a/arch/x86/include/asm/timex.h b/arch/x86/include/asm/timex.h
|
|
index a4a8b1b16c0c1..956e4145311b1 100644
|
|
--- a/arch/x86/include/asm/timex.h
|
|
+++ b/arch/x86/include/asm/timex.h
|
|
@@ -5,6 +5,15 @@
|
|
#include <asm/processor.h>
|
|
#include <asm/tsc.h>
|
|
|
|
+static inline unsigned long random_get_entropy(void)
|
|
+{
|
|
+ if (!IS_ENABLED(CONFIG_X86_TSC) &&
|
|
+ !cpu_feature_enabled(X86_FEATURE_TSC))
|
|
+ return random_get_entropy_fallback();
|
|
+ return rdtsc();
|
|
+}
|
|
+#define random_get_entropy random_get_entropy
|
|
+
|
|
/* Assume we use the PIT time source for the clock tick */
|
|
#define CLOCK_TICK_RATE PIT_TICK_RATE
|
|
|
|
diff --git a/arch/x86/include/asm/tsc.h b/arch/x86/include/asm/tsc.h
|
|
index 8a0c25c6bf099..f1ea8f0c8b129 100644
|
|
--- a/arch/x86/include/asm/tsc.h
|
|
+++ b/arch/x86/include/asm/tsc.h
|
|
@@ -22,13 +22,12 @@ extern void disable_TSC(void);
|
|
|
|
static inline cycles_t get_cycles(void)
|
|
{
|
|
-#ifndef CONFIG_X86_TSC
|
|
- if (!boot_cpu_has(X86_FEATURE_TSC))
|
|
+ if (!IS_ENABLED(CONFIG_X86_TSC) &&
|
|
+ !cpu_feature_enabled(X86_FEATURE_TSC))
|
|
return 0;
|
|
-#endif
|
|
-
|
|
return rdtsc();
|
|
}
|
|
+#define get_cycles get_cycles
|
|
|
|
extern struct system_counterval_t convert_art_to_tsc(u64 art);
|
|
extern struct system_counterval_t convert_art_ns_to_tsc(u64 art_ns);
|
|
diff --git a/arch/x86/kernel/cpu/mshyperv.c b/arch/x86/kernel/cpu/mshyperv.c
|
|
index 1c2f9baf84832..51d95c4b692c3 100644
|
|
--- a/arch/x86/kernel/cpu/mshyperv.c
|
|
+++ b/arch/x86/kernel/cpu/mshyperv.c
|
|
@@ -82,7 +82,7 @@ __visible void __irq_entry hv_stimer0_vector_handler(struct pt_regs *regs)
|
|
inc_irq_stat(hyperv_stimer0_count);
|
|
if (hv_stimer0_handler)
|
|
hv_stimer0_handler();
|
|
- add_interrupt_randomness(HYPERV_STIMER0_VECTOR, 0);
|
|
+ add_interrupt_randomness(HYPERV_STIMER0_VECTOR);
|
|
ack_APIC_irq();
|
|
|
|
exiting_irq();
|
|
diff --git a/arch/xtensa/include/asm/timex.h b/arch/xtensa/include/asm/timex.h
|
|
index 233ec75e60c69..3f2462f2d0270 100644
|
|
--- a/arch/xtensa/include/asm/timex.h
|
|
+++ b/arch/xtensa/include/asm/timex.h
|
|
@@ -29,10 +29,6 @@
|
|
|
|
extern unsigned long ccount_freq;
|
|
|
|
-typedef unsigned long long cycles_t;
|
|
-
|
|
-#define get_cycles() (0)
|
|
-
|
|
void local_timer_setup(unsigned cpu);
|
|
|
|
/*
|
|
@@ -59,4 +55,6 @@ static inline void set_linux_timer (unsigned long ccompare)
|
|
xtensa_set_sr(ccompare, SREG_CCOMPARE + LINUX_TIMER);
|
|
}
|
|
|
|
+#include <asm-generic/timex.h>
|
|
+
|
|
#endif /* _XTENSA_TIMEX_H */
|
|
diff --git a/certs/blacklist_hashes.c b/certs/blacklist_hashes.c
|
|
index 344892337be07..d5961aa3d3380 100644
|
|
--- a/certs/blacklist_hashes.c
|
|
+++ b/certs/blacklist_hashes.c
|
|
@@ -1,7 +1,7 @@
|
|
// SPDX-License-Identifier: GPL-2.0
|
|
#include "blacklist.h"
|
|
|
|
-const char __initdata *const blacklist_hashes[] = {
|
|
+const char __initconst *const blacklist_hashes[] = {
|
|
#include CONFIG_SYSTEM_BLACKLIST_HASH_LIST
|
|
, NULL
|
|
};
|
|
diff --git a/crypto/drbg.c b/crypto/drbg.c
|
|
index 04379ca624cd8..9329d9dcc210f 100644
|
|
--- a/crypto/drbg.c
|
|
+++ b/crypto/drbg.c
|
|
@@ -1035,17 +1035,38 @@ static const struct drbg_state_ops drbg_hash_ops = {
|
|
******************************************************************/
|
|
|
|
static inline int __drbg_seed(struct drbg_state *drbg, struct list_head *seed,
|
|
- int reseed)
|
|
+ int reseed, enum drbg_seed_state new_seed_state)
|
|
{
|
|
int ret = drbg->d_ops->update(drbg, seed, reseed);
|
|
|
|
if (ret)
|
|
return ret;
|
|
|
|
- drbg->seeded = true;
|
|
+ drbg->seeded = new_seed_state;
|
|
/* 10.1.1.2 / 10.1.1.3 step 5 */
|
|
drbg->reseed_ctr = 1;
|
|
|
|
+ switch (drbg->seeded) {
|
|
+ case DRBG_SEED_STATE_UNSEEDED:
|
|
+ /* Impossible, but handle it to silence compiler warnings. */
|
|
+ fallthrough;
|
|
+ case DRBG_SEED_STATE_PARTIAL:
|
|
+ /*
|
|
+ * Require frequent reseeds until the seed source is
|
|
+ * fully initialized.
|
|
+ */
|
|
+ drbg->reseed_threshold = 50;
|
|
+ break;
|
|
+
|
|
+ case DRBG_SEED_STATE_FULL:
|
|
+ /*
|
|
+ * Seed source has become fully initialized, frequent
|
|
+ * reseeds no longer required.
|
|
+ */
|
|
+ drbg->reseed_threshold = drbg_max_requests(drbg);
|
|
+ break;
|
|
+ }
|
|
+
|
|
return ret;
|
|
}
|
|
|
|
@@ -1065,12 +1086,10 @@ static inline int drbg_get_random_bytes(struct drbg_state *drbg,
|
|
return 0;
|
|
}
|
|
|
|
-static void drbg_async_seed(struct work_struct *work)
|
|
+static int drbg_seed_from_random(struct drbg_state *drbg)
|
|
{
|
|
struct drbg_string data;
|
|
LIST_HEAD(seedlist);
|
|
- struct drbg_state *drbg = container_of(work, struct drbg_state,
|
|
- seed_work);
|
|
unsigned int entropylen = drbg_sec_strength(drbg->core->flags);
|
|
unsigned char entropy[32];
|
|
int ret;
|
|
@@ -1081,30 +1100,15 @@ static void drbg_async_seed(struct work_struct *work)
|
|
drbg_string_fill(&data, entropy, entropylen);
|
|
list_add_tail(&data.list, &seedlist);
|
|
|
|
- mutex_lock(&drbg->drbg_mutex);
|
|
-
|
|
ret = drbg_get_random_bytes(drbg, entropy, entropylen);
|
|
if (ret)
|
|
- goto unlock;
|
|
-
|
|
- /* If nonblocking pool is initialized, deactivate Jitter RNG */
|
|
- crypto_free_rng(drbg->jent);
|
|
- drbg->jent = NULL;
|
|
-
|
|
- /* Set seeded to false so that if __drbg_seed fails the
|
|
- * next generate call will trigger a reseed.
|
|
- */
|
|
- drbg->seeded = false;
|
|
-
|
|
- __drbg_seed(drbg, &seedlist, true);
|
|
-
|
|
- if (drbg->seeded)
|
|
- drbg->reseed_threshold = drbg_max_requests(drbg);
|
|
+ goto out;
|
|
|
|
-unlock:
|
|
- mutex_unlock(&drbg->drbg_mutex);
|
|
+ ret = __drbg_seed(drbg, &seedlist, true, DRBG_SEED_STATE_FULL);
|
|
|
|
+out:
|
|
memzero_explicit(entropy, entropylen);
|
|
+ return ret;
|
|
}
|
|
|
|
/*
|
|
@@ -1126,6 +1130,7 @@ static int drbg_seed(struct drbg_state *drbg, struct drbg_string *pers,
|
|
unsigned int entropylen = drbg_sec_strength(drbg->core->flags);
|
|
struct drbg_string data1;
|
|
LIST_HEAD(seedlist);
|
|
+ enum drbg_seed_state new_seed_state = DRBG_SEED_STATE_FULL;
|
|
|
|
/* 9.1 / 9.2 / 9.3.1 step 3 */
|
|
if (pers && pers->len > (drbg_max_addtl(drbg))) {
|
|
@@ -1153,6 +1158,9 @@ static int drbg_seed(struct drbg_state *drbg, struct drbg_string *pers,
|
|
BUG_ON((entropylen * 2) > sizeof(entropy));
|
|
|
|
/* Get seed from in-kernel /dev/urandom */
|
|
+ if (!rng_is_initialized())
|
|
+ new_seed_state = DRBG_SEED_STATE_PARTIAL;
|
|
+
|
|
ret = drbg_get_random_bytes(drbg, entropy, entropylen);
|
|
if (ret)
|
|
goto out;
|
|
@@ -1168,7 +1176,23 @@ static int drbg_seed(struct drbg_state *drbg, struct drbg_string *pers,
|
|
entropylen);
|
|
if (ret) {
|
|
pr_devel("DRBG: jent failed with %d\n", ret);
|
|
- goto out;
|
|
+
|
|
+ /*
|
|
+ * Do not treat the transient failure of the
|
|
+ * Jitter RNG as an error that needs to be
|
|
+ * reported. The combined number of the
|
|
+ * maximum reseed threshold times the maximum
|
|
+ * number of Jitter RNG transient errors is
|
|
+ * less than the reseed threshold required by
|
|
+ * SP800-90A allowing us to treat the
|
|
+ * transient errors as such.
|
|
+ *
|
|
+ * However, we mandate that at least the first
|
|
+ * seeding operation must succeed with the
|
|
+ * Jitter RNG.
|
|
+ */
|
|
+ if (!reseed || ret != -EAGAIN)
|
|
+ goto out;
|
|
}
|
|
|
|
drbg_string_fill(&data1, entropy, entropylen * 2);
|
|
@@ -1193,7 +1217,7 @@ static int drbg_seed(struct drbg_state *drbg, struct drbg_string *pers,
|
|
memset(drbg->C, 0, drbg_statelen(drbg));
|
|
}
|
|
|
|
- ret = __drbg_seed(drbg, &seedlist, reseed);
|
|
+ ret = __drbg_seed(drbg, &seedlist, reseed, new_seed_state);
|
|
|
|
out:
|
|
memzero_explicit(entropy, entropylen * 2);
|
|
@@ -1373,19 +1397,25 @@ static int drbg_generate(struct drbg_state *drbg,
|
|
* here. The spec is a bit convoluted here, we make it simpler.
|
|
*/
|
|
if (drbg->reseed_threshold < drbg->reseed_ctr)
|
|
- drbg->seeded = false;
|
|
+ drbg->seeded = DRBG_SEED_STATE_UNSEEDED;
|
|
|
|
- if (drbg->pr || !drbg->seeded) {
|
|
+ if (drbg->pr || drbg->seeded == DRBG_SEED_STATE_UNSEEDED) {
|
|
pr_devel("DRBG: reseeding before generation (prediction "
|
|
"resistance: %s, state %s)\n",
|
|
drbg->pr ? "true" : "false",
|
|
- drbg->seeded ? "seeded" : "unseeded");
|
|
+ (drbg->seeded == DRBG_SEED_STATE_FULL ?
|
|
+ "seeded" : "unseeded"));
|
|
/* 9.3.1 steps 7.1 through 7.3 */
|
|
len = drbg_seed(drbg, addtl, true);
|
|
if (len)
|
|
goto err;
|
|
/* 9.3.1 step 7.4 */
|
|
addtl = NULL;
|
|
+ } else if (rng_is_initialized() &&
|
|
+ drbg->seeded == DRBG_SEED_STATE_PARTIAL) {
|
|
+ len = drbg_seed_from_random(drbg);
|
|
+ if (len)
|
|
+ goto err;
|
|
}
|
|
|
|
if (addtl && 0 < addtl->len)
|
|
@@ -1478,51 +1508,15 @@ static int drbg_generate_long(struct drbg_state *drbg,
|
|
return 0;
|
|
}
|
|
|
|
-static void drbg_schedule_async_seed(struct random_ready_callback *rdy)
|
|
-{
|
|
- struct drbg_state *drbg = container_of(rdy, struct drbg_state,
|
|
- random_ready);
|
|
-
|
|
- schedule_work(&drbg->seed_work);
|
|
-}
|
|
-
|
|
static int drbg_prepare_hrng(struct drbg_state *drbg)
|
|
{
|
|
- int err;
|
|
-
|
|
/* We do not need an HRNG in test mode. */
|
|
if (list_empty(&drbg->test_data.list))
|
|
return 0;
|
|
|
|
- INIT_WORK(&drbg->seed_work, drbg_async_seed);
|
|
-
|
|
- drbg->random_ready.owner = THIS_MODULE;
|
|
- drbg->random_ready.func = drbg_schedule_async_seed;
|
|
-
|
|
- err = add_random_ready_callback(&drbg->random_ready);
|
|
-
|
|
- switch (err) {
|
|
- case 0:
|
|
- break;
|
|
-
|
|
- case -EALREADY:
|
|
- err = 0;
|
|
- /* fall through */
|
|
-
|
|
- default:
|
|
- drbg->random_ready.func = NULL;
|
|
- return err;
|
|
- }
|
|
-
|
|
drbg->jent = crypto_alloc_rng("jitterentropy_rng", 0, 0);
|
|
|
|
- /*
|
|
- * Require frequent reseeds until the seed source is fully
|
|
- * initialized.
|
|
- */
|
|
- drbg->reseed_threshold = 50;
|
|
-
|
|
- return err;
|
|
+ return 0;
|
|
}
|
|
|
|
/*
|
|
@@ -1565,7 +1559,7 @@ static int drbg_instantiate(struct drbg_state *drbg, struct drbg_string *pers,
|
|
if (!drbg->core) {
|
|
drbg->core = &drbg_cores[coreref];
|
|
drbg->pr = pr;
|
|
- drbg->seeded = false;
|
|
+ drbg->seeded = DRBG_SEED_STATE_UNSEEDED;
|
|
drbg->reseed_threshold = drbg_max_requests(drbg);
|
|
|
|
ret = drbg_alloc_state(drbg);
|
|
@@ -1616,12 +1610,9 @@ free_everything:
|
|
*/
|
|
static int drbg_uninstantiate(struct drbg_state *drbg)
|
|
{
|
|
- if (drbg->random_ready.func) {
|
|
- del_random_ready_callback(&drbg->random_ready);
|
|
- cancel_work_sync(&drbg->seed_work);
|
|
+ if (!IS_ERR_OR_NULL(drbg->jent))
|
|
crypto_free_rng(drbg->jent);
|
|
- drbg->jent = NULL;
|
|
- }
|
|
+ drbg->jent = NULL;
|
|
|
|
if (drbg->d_ops)
|
|
drbg->d_ops->crypto_fini(drbg);
|
|
diff --git a/drivers/ata/libata-core.c b/drivers/ata/libata-core.c
|
|
index af8a1bac93458..fc37e075f3e15 100644
|
|
--- a/drivers/ata/libata-core.c
|
|
+++ b/drivers/ata/libata-core.c
|
|
@@ -6235,7 +6235,7 @@ struct ata_host *ata_host_alloc_pinfo(struct device *dev,
|
|
const struct ata_port_info * const * ppi,
|
|
int n_ports)
|
|
{
|
|
- const struct ata_port_info *pi;
|
|
+ const struct ata_port_info *pi = &ata_dummy_port_info;
|
|
struct ata_host *host;
|
|
int i, j;
|
|
|
|
@@ -6243,7 +6243,7 @@ struct ata_host *ata_host_alloc_pinfo(struct device *dev,
|
|
if (!host)
|
|
return NULL;
|
|
|
|
- for (i = 0, j = 0, pi = NULL; i < host->n_ports; i++) {
|
|
+ for (i = 0, j = 0; i < host->n_ports; i++) {
|
|
struct ata_port *ap = host->ports[i];
|
|
|
|
if (ppi[j])
|
|
diff --git a/drivers/char/Kconfig b/drivers/char/Kconfig
|
|
index df0fc997dc3e3..85e97550a9a60 100644
|
|
--- a/drivers/char/Kconfig
|
|
+++ b/drivers/char/Kconfig
|
|
@@ -535,28 +535,41 @@ config ADI
|
|
and SSM (Silicon Secured Memory). Intended consumers of this
|
|
driver include crash and makedumpfile.
|
|
|
|
-endmenu
|
|
-
|
|
config RANDOM_TRUST_CPU
|
|
- bool "Trust the CPU manufacturer to initialize Linux's CRNG"
|
|
- depends on X86 || S390 || PPC
|
|
- default n
|
|
+ bool "Initialize RNG using CPU RNG instructions"
|
|
+ default y
|
|
+ depends on ARCH_RANDOM
|
|
help
|
|
- Assume that CPU manufacturer (e.g., Intel or AMD for RDSEED or
|
|
- RDRAND, IBM for the S390 and Power PC architectures) is trustworthy
|
|
- for the purposes of initializing Linux's CRNG. Since this is not
|
|
- something that can be independently audited, this amounts to trusting
|
|
- that CPU manufacturer (perhaps with the insistence or mandate
|
|
- of a Nation State's intelligence or law enforcement agencies)
|
|
- has not installed a hidden back door to compromise the CPU's
|
|
- random number generation facilities. This can also be configured
|
|
- at boot with "random.trust_cpu=on/off".
|
|
+ Initialize the RNG using random numbers supplied by the CPU's
|
|
+ RNG instructions (e.g. RDRAND), if supported and available. These
|
|
+ random numbers are never used directly, but are rather hashed into
|
|
+ the main input pool, and this happens regardless of whether or not
|
|
+ this option is enabled. Instead, this option controls whether the
|
|
+ they are credited and hence can initialize the RNG. Additionally,
|
|
+ other sources of randomness are always used, regardless of this
|
|
+ setting. Enabling this implies trusting that the CPU can supply high
|
|
+ quality and non-backdoored random numbers.
|
|
+
|
|
+ Say Y here unless you have reason to mistrust your CPU or believe
|
|
+ its RNG facilities may be faulty. This may also be configured at
|
|
+ boot time with "random.trust_cpu=on/off".
|
|
|
|
config RANDOM_TRUST_BOOTLOADER
|
|
- bool "Trust the bootloader to initialize Linux's CRNG"
|
|
+ bool "Initialize RNG using bootloader-supplied seed"
|
|
+ default y
|
|
help
|
|
- Some bootloaders can provide entropy to increase the kernel's initial
|
|
- device randomness. Say Y here to assume the entropy provided by the
|
|
- booloader is trustworthy so it will be added to the kernel's entropy
|
|
- pool. Otherwise, say N here so it will be regarded as device input that
|
|
- only mixes the entropy pool.
|
|
\ No newline at end of file
|
|
+ Initialize the RNG using a seed supplied by the bootloader or boot
|
|
+ environment (e.g. EFI or a bootloader-generated device tree). This
|
|
+ seed is not used directly, but is rather hashed into the main input
|
|
+ pool, and this happens regardless of whether or not this option is
|
|
+ enabled. Instead, this option controls whether the seed is credited
|
|
+ and hence can initialize the RNG. Additionally, other sources of
|
|
+ randomness are always used, regardless of this setting. Enabling
|
|
+ this implies trusting that the bootloader can supply high quality and
|
|
+ non-backdoored seeds.
|
|
+
|
|
+ Say Y here unless you have reason to mistrust your bootloader or
|
|
+ believe its RNG facilities may be faulty. This may also be configured
|
|
+ at boot time with "random.trust_bootloader=on/off".
|
|
+
|
|
+endmenu
|
|
diff --git a/drivers/char/hw_random/core.c b/drivers/char/hw_random/core.c
|
|
index 8d53b8ef545cb..559ca503b7b6e 100644
|
|
--- a/drivers/char/hw_random/core.c
|
|
+++ b/drivers/char/hw_random/core.c
|
|
@@ -15,6 +15,7 @@
|
|
#include <linux/err.h>
|
|
#include <linux/fs.h>
|
|
#include <linux/hw_random.h>
|
|
+#include <linux/random.h>
|
|
#include <linux/kernel.h>
|
|
#include <linux/kthread.h>
|
|
#include <linux/sched/signal.h>
|
|
diff --git a/drivers/char/random.c b/drivers/char/random.c
|
|
index 19bfbaf135989..82f9ee4404069 100644
|
|
--- a/drivers/char/random.c
|
|
+++ b/drivers/char/random.c
|
|
@@ -1,311 +1,29 @@
|
|
+// SPDX-License-Identifier: (GPL-2.0 OR BSD-3-Clause)
|
|
/*
|
|
- * random.c -- A strong random number generator
|
|
- *
|
|
- * Copyright (C) 2017 Jason A. Donenfeld <Jason@zx2c4.com>. All
|
|
- * Rights Reserved.
|
|
- *
|
|
+ * Copyright (C) 2017-2022 Jason A. Donenfeld <Jason@zx2c4.com>. All Rights Reserved.
|
|
* Copyright Matt Mackall <mpm@selenic.com>, 2003, 2004, 2005
|
|
- *
|
|
- * Copyright Theodore Ts'o, 1994, 1995, 1996, 1997, 1998, 1999. All
|
|
- * rights reserved.
|
|
- *
|
|
- * Redistribution and use in source and binary forms, with or without
|
|
- * modification, are permitted provided that the following conditions
|
|
- * are met:
|
|
- * 1. Redistributions of source code must retain the above copyright
|
|
- * notice, and the entire permission notice in its entirety,
|
|
- * including the disclaimer of warranties.
|
|
- * 2. Redistributions in binary form must reproduce the above copyright
|
|
- * notice, this list of conditions and the following disclaimer in the
|
|
- * documentation and/or other materials provided with the distribution.
|
|
- * 3. The name of the author may not be used to endorse or promote
|
|
- * products derived from this software without specific prior
|
|
- * written permission.
|
|
- *
|
|
- * ALTERNATIVELY, this product may be distributed under the terms of
|
|
- * the GNU General Public License, in which case the provisions of the GPL are
|
|
- * required INSTEAD OF the above restrictions. (This clause is
|
|
- * necessary due to a potential bad interaction between the GPL and
|
|
- * the restrictions contained in a BSD-style copyright.)
|
|
- *
|
|
- * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED
|
|
- * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
|
|
- * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ALL OF
|
|
- * WHICH ARE HEREBY DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE
|
|
- * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
|
- * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT
|
|
- * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
|
|
- * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
|
|
- * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
|
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE
|
|
- * USE OF THIS SOFTWARE, EVEN IF NOT ADVISED OF THE POSSIBILITY OF SUCH
|
|
- * DAMAGE.
|
|
+ * Copyright Theodore Ts'o, 1994, 1995, 1996, 1997, 1998, 1999. All rights reserved.
|
|
+ *
|
|
+ * This driver produces cryptographically secure pseudorandom data. It is divided
|
|
+ * into roughly six sections, each with a section header:
|
|
+ *
|
|
+ * - Initialization and readiness waiting.
|
|
+ * - Fast key erasure RNG, the "crng".
|
|
+ * - Entropy accumulation and extraction routines.
|
|
+ * - Entropy collection routines.
|
|
+ * - Userspace reader/writer interfaces.
|
|
+ * - Sysctl interface.
|
|
+ *
|
|
+ * The high level overview is that there is one input pool, into which
|
|
+ * various pieces of data are hashed. Prior to initialization, some of that
|
|
+ * data is then "credited" as having a certain number of bits of entropy.
|
|
+ * When enough bits of entropy are available, the hash is finalized and
|
|
+ * handed as a key to a stream cipher that expands it indefinitely for
|
|
+ * various consumers. This key is periodically refreshed as the various
|
|
+ * entropy collectors, described below, add data to the input pool.
|
|
*/
|
|
|
|
-/*
|
|
- * (now, with legal B.S. out of the way.....)
|
|
- *
|
|
- * This routine gathers environmental noise from device drivers, etc.,
|
|
- * and returns good random numbers, suitable for cryptographic use.
|
|
- * Besides the obvious cryptographic uses, these numbers are also good
|
|
- * for seeding TCP sequence numbers, and other places where it is
|
|
- * desirable to have numbers which are not only random, but hard to
|
|
- * predict by an attacker.
|
|
- *
|
|
- * Theory of operation
|
|
- * ===================
|
|
- *
|
|
- * Computers are very predictable devices. Hence it is extremely hard
|
|
- * to produce truly random numbers on a computer --- as opposed to
|
|
- * pseudo-random numbers, which can easily generated by using a
|
|
- * algorithm. Unfortunately, it is very easy for attackers to guess
|
|
- * the sequence of pseudo-random number generators, and for some
|
|
- * applications this is not acceptable. So instead, we must try to
|
|
- * gather "environmental noise" from the computer's environment, which
|
|
- * must be hard for outside attackers to observe, and use that to
|
|
- * generate random numbers. In a Unix environment, this is best done
|
|
- * from inside the kernel.
|
|
- *
|
|
- * Sources of randomness from the environment include inter-keyboard
|
|
- * timings, inter-interrupt timings from some interrupts, and other
|
|
- * events which are both (a) non-deterministic and (b) hard for an
|
|
- * outside observer to measure. Randomness from these sources are
|
|
- * added to an "entropy pool", which is mixed using a CRC-like function.
|
|
- * This is not cryptographically strong, but it is adequate assuming
|
|
- * the randomness is not chosen maliciously, and it is fast enough that
|
|
- * the overhead of doing it on every interrupt is very reasonable.
|
|
- * As random bytes are mixed into the entropy pool, the routines keep
|
|
- * an *estimate* of how many bits of randomness have been stored into
|
|
- * the random number generator's internal state.
|
|
- *
|
|
- * When random bytes are desired, they are obtained by taking the SHA
|
|
- * hash of the contents of the "entropy pool". The SHA hash avoids
|
|
- * exposing the internal state of the entropy pool. It is believed to
|
|
- * be computationally infeasible to derive any useful information
|
|
- * about the input of SHA from its output. Even if it is possible to
|
|
- * analyze SHA in some clever way, as long as the amount of data
|
|
- * returned from the generator is less than the inherent entropy in
|
|
- * the pool, the output data is totally unpredictable. For this
|
|
- * reason, the routine decreases its internal estimate of how many
|
|
- * bits of "true randomness" are contained in the entropy pool as it
|
|
- * outputs random numbers.
|
|
- *
|
|
- * If this estimate goes to zero, the routine can still generate
|
|
- * random numbers; however, an attacker may (at least in theory) be
|
|
- * able to infer the future output of the generator from prior
|
|
- * outputs. This requires successful cryptanalysis of SHA, which is
|
|
- * not believed to be feasible, but there is a remote possibility.
|
|
- * Nonetheless, these numbers should be useful for the vast majority
|
|
- * of purposes.
|
|
- *
|
|
- * Exported interfaces ---- output
|
|
- * ===============================
|
|
- *
|
|
- * There are four exported interfaces; two for use within the kernel,
|
|
- * and two or use from userspace.
|
|
- *
|
|
- * Exported interfaces ---- userspace output
|
|
- * -----------------------------------------
|
|
- *
|
|
- * The userspace interfaces are two character devices /dev/random and
|
|
- * /dev/urandom. /dev/random is suitable for use when very high
|
|
- * quality randomness is desired (for example, for key generation or
|
|
- * one-time pads), as it will only return a maximum of the number of
|
|
- * bits of randomness (as estimated by the random number generator)
|
|
- * contained in the entropy pool.
|
|
- *
|
|
- * The /dev/urandom device does not have this limit, and will return
|
|
- * as many bytes as are requested. As more and more random bytes are
|
|
- * requested without giving time for the entropy pool to recharge,
|
|
- * this will result in random numbers that are merely cryptographically
|
|
- * strong. For many applications, however, this is acceptable.
|
|
- *
|
|
- * Exported interfaces ---- kernel output
|
|
- * --------------------------------------
|
|
- *
|
|
- * The primary kernel interface is
|
|
- *
|
|
- * void get_random_bytes(void *buf, int nbytes);
|
|
- *
|
|
- * This interface will return the requested number of random bytes,
|
|
- * and place it in the requested buffer. This is equivalent to a
|
|
- * read from /dev/urandom.
|
|
- *
|
|
- * For less critical applications, there are the functions:
|
|
- *
|
|
- * u32 get_random_u32()
|
|
- * u64 get_random_u64()
|
|
- * unsigned int get_random_int()
|
|
- * unsigned long get_random_long()
|
|
- *
|
|
- * These are produced by a cryptographic RNG seeded from get_random_bytes,
|
|
- * and so do not deplete the entropy pool as much. These are recommended
|
|
- * for most in-kernel operations *if the result is going to be stored in
|
|
- * the kernel*.
|
|
- *
|
|
- * Specifically, the get_random_int() family do not attempt to do
|
|
- * "anti-backtracking". If you capture the state of the kernel (e.g.
|
|
- * by snapshotting the VM), you can figure out previous get_random_int()
|
|
- * return values. But if the value is stored in the kernel anyway,
|
|
- * this is not a problem.
|
|
- *
|
|
- * It *is* safe to expose get_random_int() output to attackers (e.g. as
|
|
- * network cookies); given outputs 1..n, it's not feasible to predict
|
|
- * outputs 0 or n+1. The only concern is an attacker who breaks into
|
|
- * the kernel later; the get_random_int() engine is not reseeded as
|
|
- * often as the get_random_bytes() one.
|
|
- *
|
|
- * get_random_bytes() is needed for keys that need to stay secret after
|
|
- * they are erased from the kernel. For example, any key that will
|
|
- * be wrapped and stored encrypted. And session encryption keys: we'd
|
|
- * like to know that after the session is closed and the keys erased,
|
|
- * the plaintext is unrecoverable to someone who recorded the ciphertext.
|
|
- *
|
|
- * But for network ports/cookies, stack canaries, PRNG seeds, address
|
|
- * space layout randomization, session *authentication* keys, or other
|
|
- * applications where the sensitive data is stored in the kernel in
|
|
- * plaintext for as long as it's sensitive, the get_random_int() family
|
|
- * is just fine.
|
|
- *
|
|
- * Consider ASLR. We want to keep the address space secret from an
|
|
- * outside attacker while the process is running, but once the address
|
|
- * space is torn down, it's of no use to an attacker any more. And it's
|
|
- * stored in kernel data structures as long as it's alive, so worrying
|
|
- * about an attacker's ability to extrapolate it from the get_random_int()
|
|
- * CRNG is silly.
|
|
- *
|
|
- * Even some cryptographic keys are safe to generate with get_random_int().
|
|
- * In particular, keys for SipHash are generally fine. Here, knowledge
|
|
- * of the key authorizes you to do something to a kernel object (inject
|
|
- * packets to a network connection, or flood a hash table), and the
|
|
- * key is stored with the object being protected. Once it goes away,
|
|
- * we no longer care if anyone knows the key.
|
|
- *
|
|
- * prandom_u32()
|
|
- * -------------
|
|
- *
|
|
- * For even weaker applications, see the pseudorandom generator
|
|
- * prandom_u32(), prandom_max(), and prandom_bytes(). If the random
|
|
- * numbers aren't security-critical at all, these are *far* cheaper.
|
|
- * Useful for self-tests, random error simulation, randomized backoffs,
|
|
- * and any other application where you trust that nobody is trying to
|
|
- * maliciously mess with you by guessing the "random" numbers.
|
|
- *
|
|
- * Exported interfaces ---- input
|
|
- * ==============================
|
|
- *
|
|
- * 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.
|
|
- *
|
|
- * 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
|
|
- * entropy pool. Note that high-speed solid state drives with very low
|
|
- * seek times do not make for good sources of entropy, as their seek
|
|
- * times are usually fairly consistent.
|
|
- *
|
|
- * All of these routines try to estimate how many bits of randomness a
|
|
- * particular randomness source. They do this by keeping track of the
|
|
- * first and second order deltas of the event timings.
|
|
- *
|
|
- * Ensuring unpredictability at system startup
|
|
- * ============================================
|
|
- *
|
|
- * When any operating system starts up, it will go through a sequence
|
|
- * of actions that are fairly predictable by an adversary, especially
|
|
- * if the start-up does not involve interaction with a human operator.
|
|
- * This reduces the actual number of bits of unpredictability in the
|
|
- * entropy pool below the value in entropy_count. In order to
|
|
- * counteract this effect, it helps to carry information in the
|
|
- * entropy pool across shut-downs and start-ups. To do this, put the
|
|
- * following lines an appropriate script which is run during the boot
|
|
- * sequence:
|
|
- *
|
|
- * echo "Initializing random number generator..."
|
|
- * random_seed=/var/run/random-seed
|
|
- * # Carry a random seed from start-up to start-up
|
|
- * # Load and then save the whole entropy pool
|
|
- * if [ -f $random_seed ]; then
|
|
- * cat $random_seed >/dev/urandom
|
|
- * else
|
|
- * touch $random_seed
|
|
- * fi
|
|
- * chmod 600 $random_seed
|
|
- * dd if=/dev/urandom of=$random_seed count=1 bs=512
|
|
- *
|
|
- * and the following lines in an appropriate script which is run as
|
|
- * the system is shutdown:
|
|
- *
|
|
- * # Carry a random seed from shut-down to start-up
|
|
- * # Save the whole entropy pool
|
|
- * echo "Saving random seed..."
|
|
- * random_seed=/var/run/random-seed
|
|
- * touch $random_seed
|
|
- * chmod 600 $random_seed
|
|
- * dd if=/dev/urandom of=$random_seed count=1 bs=512
|
|
- *
|
|
- * For example, on most modern systems using the System V init
|
|
- * scripts, such code fragments would be found in
|
|
- * /etc/rc.d/init.d/random. On older Linux systems, the correct script
|
|
- * location might be in /etc/rcb.d/rc.local or /etc/rc.d/rc.0.
|
|
- *
|
|
- * Effectively, these commands cause the contents of the entropy pool
|
|
- * to be saved at shut-down time and reloaded into the entropy pool at
|
|
- * start-up. (The 'dd' in the addition to the bootup script is to
|
|
- * make sure that /etc/random-seed is different for every start-up,
|
|
- * even if the system crashes without executing rc.0.) Even with
|
|
- * complete knowledge of the start-up activities, predicting the state
|
|
- * of the entropy pool requires knowledge of the previous history of
|
|
- * the system.
|
|
- *
|
|
- * Configuring the /dev/random driver under Linux
|
|
- * ==============================================
|
|
- *
|
|
- * The /dev/random driver under Linux uses minor numbers 8 and 9 of
|
|
- * the /dev/mem major number (#1). So if your system does not have
|
|
- * /dev/random and /dev/urandom created already, they can be created
|
|
- * by using the commands:
|
|
- *
|
|
- * mknod /dev/random c 1 8
|
|
- * mknod /dev/urandom c 1 9
|
|
- *
|
|
- * Acknowledgements:
|
|
- * =================
|
|
- *
|
|
- * Ideas for constructing this random number generator were derived
|
|
- * from Pretty Good Privacy's random number generator, and from private
|
|
- * discussions with Phil Karn. Colin Plumb provided a faster random
|
|
- * number generator, which speed up the mixing function of the entropy
|
|
- * pool, taken from PGPfone. Dale Worley has also contributed many
|
|
- * useful ideas and suggestions to improve this driver.
|
|
- *
|
|
- * Any flaws in the design are solely my responsibility, and should
|
|
- * not be attributed to the Phil, Colin, or any of authors of PGP.
|
|
- *
|
|
- * Further background information on this topic may be obtained from
|
|
- * RFC 1750, "Randomness Recommendations for Security", by Donald
|
|
- * Eastlake, Steve Crocker, and Jeff Schiller.
|
|
- */
|
|
+#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
|
|
|
|
#include <linux/utsname.h>
|
|
#include <linux/module.h>
|
|
@@ -325,8 +43,6 @@
|
|
#include <linux/spinlock.h>
|
|
#include <linux/kthread.h>
|
|
#include <linux/percpu.h>
|
|
-#include <linux/cryptohash.h>
|
|
-#include <linux/fips.h>
|
|
#include <linux/ptrace.h>
|
|
#include <linux/workqueue.h>
|
|
#include <linux/irq.h>
|
|
@@ -334,1663 +50,1067 @@
|
|
#include <linux/syscalls.h>
|
|
#include <linux/completion.h>
|
|
#include <linux/uuid.h>
|
|
+#include <linux/uaccess.h>
|
|
+#include <linux/siphash.h>
|
|
+#include <linux/uio.h>
|
|
#include <crypto/chacha.h>
|
|
-
|
|
+#include <crypto/blake2s.h>
|
|
#include <asm/processor.h>
|
|
-#include <linux/uaccess.h>
|
|
#include <asm/irq.h>
|
|
#include <asm/irq_regs.h>
|
|
#include <asm/io.h>
|
|
|
|
-#define CREATE_TRACE_POINTS
|
|
-#include <trace/events/random.h>
|
|
-
|
|
-/* #define ADD_INTERRUPT_BENCH */
|
|
+/*********************************************************************
|
|
+ *
|
|
+ * Initialization and readiness waiting.
|
|
+ *
|
|
+ * Much of the RNG infrastructure is devoted to various dependencies
|
|
+ * being able to wait until the RNG has collected enough entropy and
|
|
+ * is ready for safe consumption.
|
|
+ *
|
|
+ *********************************************************************/
|
|
|
|
/*
|
|
- * Configuration information
|
|
+ * crng_init is protected by base_crng->lock, and only increases
|
|
+ * its value (from empty->early->ready).
|
|
*/
|
|
-#define INPUT_POOL_SHIFT 12
|
|
-#define INPUT_POOL_WORDS (1 << (INPUT_POOL_SHIFT-5))
|
|
-#define OUTPUT_POOL_SHIFT 10
|
|
-#define OUTPUT_POOL_WORDS (1 << (OUTPUT_POOL_SHIFT-5))
|
|
-#define SEC_XFER_SIZE 512
|
|
-#define EXTRACT_SIZE 10
|
|
-
|
|
+static enum {
|
|
+ CRNG_EMPTY = 0, /* Little to no entropy collected */
|
|
+ CRNG_EARLY = 1, /* At least POOL_EARLY_BITS collected */
|
|
+ CRNG_READY = 2 /* Fully initialized with POOL_READY_BITS collected */
|
|
+} crng_init __read_mostly = CRNG_EMPTY;
|
|
+#define crng_ready() (likely(crng_init >= CRNG_READY))
|
|
+/* Various types of waiters for crng_init->CRNG_READY transition. */
|
|
+static DECLARE_WAIT_QUEUE_HEAD(crng_init_wait);
|
|
+static struct fasync_struct *fasync;
|
|
+static DEFINE_SPINLOCK(random_ready_chain_lock);
|
|
+static RAW_NOTIFIER_HEAD(random_ready_chain);
|
|
|
|
-#define LONGS(x) (((x) + sizeof(unsigned long) - 1)/sizeof(unsigned long))
|
|
+/* Control how we warn userspace. */
|
|
+static struct ratelimit_state urandom_warning =
|
|
+ RATELIMIT_STATE_INIT("warn_urandom_randomness", HZ, 3);
|
|
+static int ratelimit_disable __read_mostly =
|
|
+ IS_ENABLED(CONFIG_WARN_ALL_UNSEEDED_RANDOM);
|
|
+module_param_named(ratelimit_disable, ratelimit_disable, int, 0644);
|
|
+MODULE_PARM_DESC(ratelimit_disable, "Disable random ratelimit suppression");
|
|
|
|
/*
|
|
- * To allow fractional bits to be tracked, the entropy_count field is
|
|
- * denominated in units of 1/8th bits.
|
|
+ * Returns whether or not the input pool has been seeded and thus guaranteed
|
|
+ * to supply cryptographically secure random numbers. This applies to: the
|
|
+ * /dev/urandom device, the get_random_bytes function, and the get_random_{u32,
|
|
+ * ,u64,int,long} family of functions.
|
|
*
|
|
- * 2*(ENTROPY_SHIFT + poolbitshift) must <= 31, or the multiply in
|
|
- * credit_entropy_bits() needs to be 64 bits wide.
|
|
+ * Returns: true if the input pool has been seeded.
|
|
+ * false if the input pool has not been seeded.
|
|
*/
|
|
-#define ENTROPY_SHIFT 3
|
|
-#define ENTROPY_BITS(r) ((r)->entropy_count >> ENTROPY_SHIFT)
|
|
+bool rng_is_initialized(void)
|
|
+{
|
|
+ return crng_ready();
|
|
+}
|
|
+EXPORT_SYMBOL(rng_is_initialized);
|
|
|
|
-/*
|
|
- * The minimum number of bits of entropy before we wake up a read on
|
|
- * /dev/random. Should be enough to do a significant reseed.
|
|
- */
|
|
-static int random_read_wakeup_bits = 64;
|
|
+/* Used by wait_for_random_bytes(), and considered an entropy collector, below. */
|
|
+static void try_to_generate_entropy(void);
|
|
|
|
/*
|
|
- * If the entropy count falls under this number of bits, then we
|
|
- * should wake up processes which are selecting or polling on write
|
|
- * access to /dev/random.
|
|
+ * Wait for the input pool to be seeded and thus guaranteed to supply
|
|
+ * cryptographically secure random numbers. This applies to: the /dev/urandom
|
|
+ * device, the get_random_bytes function, and the get_random_{u32,u64,int,long}
|
|
+ * family of functions. Using any of these functions without first calling
|
|
+ * this function forfeits the guarantee of security.
|
|
+ *
|
|
+ * Returns: 0 if the input pool has been seeded.
|
|
+ * -ERESTARTSYS if the function was interrupted by a signal.
|
|
*/
|
|
-static int random_write_wakeup_bits = 28 * OUTPUT_POOL_WORDS;
|
|
+int wait_for_random_bytes(void)
|
|
+{
|
|
+ while (!crng_ready()) {
|
|
+ int ret;
|
|
+
|
|
+ try_to_generate_entropy();
|
|
+ ret = wait_event_interruptible_timeout(crng_init_wait, crng_ready(), HZ);
|
|
+ if (ret)
|
|
+ return ret > 0 ? 0 : ret;
|
|
+ }
|
|
+ return 0;
|
|
+}
|
|
+EXPORT_SYMBOL(wait_for_random_bytes);
|
|
|
|
/*
|
|
- * Originally, we used a primitive polynomial of degree .poolwords
|
|
- * over GF(2). The taps for various sizes are defined below. They
|
|
- * were chosen to be evenly spaced except for the last tap, which is 1
|
|
- * to get the twisting happening as fast as possible.
|
|
- *
|
|
- * For the purposes of better mixing, we use the CRC-32 polynomial as
|
|
- * well to make a (modified) twisted Generalized Feedback Shift
|
|
- * Register. (See M. Matsumoto & Y. Kurita, 1992. Twisted GFSR
|
|
- * generators. ACM Transactions on Modeling and Computer Simulation
|
|
- * 2(3):179-194. Also see M. Matsumoto & Y. Kurita, 1994. Twisted
|
|
- * GFSR generators II. ACM Transactions on Modeling and Computer
|
|
- * Simulation 4:254-266)
|
|
- *
|
|
- * Thanks to Colin Plumb for suggesting this.
|
|
- *
|
|
- * The mixing operation is much less sensitive than the output hash,
|
|
- * where we use SHA-1. All that we want of mixing operation is that
|
|
- * it be a good non-cryptographic hash; i.e. it not produce collisions
|
|
- * when fed "random" data of the sort we expect to see. As long as
|
|
- * the pool state differs for different inputs, we have preserved the
|
|
- * input entropy and done a good job. The fact that an intelligent
|
|
- * attacker can construct inputs that will produce controlled
|
|
- * alterations to the pool's state is not important because we don't
|
|
- * consider such inputs to contribute any randomness. The only
|
|
- * property we need with respect to them is that the attacker can't
|
|
- * increase his/her knowledge of the pool's state. Since all
|
|
- * additions are reversible (knowing the final state and the input,
|
|
- * you can reconstruct the initial state), if an attacker has any
|
|
- * uncertainty about the initial state, he/she can only shuffle that
|
|
- * uncertainty about, but never cause any collisions (which would
|
|
- * decrease the uncertainty).
|
|
+ * Add a callback function that will be invoked when the input
|
|
+ * pool is initialised.
|
|
*
|
|
- * Our mixing functions were analyzed by Lacharme, Roeck, Strubel, and
|
|
- * Videau in their paper, "The Linux Pseudorandom Number Generator
|
|
- * Revisited" (see: http://eprint.iacr.org/2012/251.pdf). In their
|
|
- * paper, they point out that we are not using a true Twisted GFSR,
|
|
- * since Matsumoto & Kurita used a trinomial feedback polynomial (that
|
|
- * is, with only three taps, instead of the six that we are using).
|
|
- * As a result, the resulting polynomial is neither primitive nor
|
|
- * irreducible, and hence does not have a maximal period over
|
|
- * GF(2**32). They suggest a slight change to the generator
|
|
- * polynomial which improves the resulting TGFSR polynomial to be
|
|
- * irreducible, which we have made here.
|
|
+ * returns: 0 if callback is successfully added
|
|
+ * -EALREADY if pool is already initialised (callback not called)
|
|
*/
|
|
-static const struct poolinfo {
|
|
- int poolbitshift, poolwords, poolbytes, poolfracbits;
|
|
-#define S(x) ilog2(x)+5, (x), (x)*4, (x) << (ENTROPY_SHIFT+5)
|
|
- int tap1, tap2, tap3, tap4, tap5;
|
|
-} poolinfo_table[] = {
|
|
- /* was: x^128 + x^103 + x^76 + x^51 +x^25 + x + 1 */
|
|
- /* x^128 + x^104 + x^76 + x^51 +x^25 + x + 1 */
|
|
- { S(128), 104, 76, 51, 25, 1 },
|
|
- /* was: x^32 + x^26 + x^20 + x^14 + x^7 + x + 1 */
|
|
- /* x^32 + x^26 + x^19 + x^14 + x^7 + x + 1 */
|
|
- { S(32), 26, 19, 14, 7, 1 },
|
|
-#if 0
|
|
- /* x^2048 + x^1638 + x^1231 + x^819 + x^411 + x + 1 -- 115 */
|
|
- { S(2048), 1638, 1231, 819, 411, 1 },
|
|
-
|
|
- /* x^1024 + x^817 + x^615 + x^412 + x^204 + x + 1 -- 290 */
|
|
- { S(1024), 817, 615, 412, 204, 1 },
|
|
-
|
|
- /* x^1024 + x^819 + x^616 + x^410 + x^207 + x^2 + 1 -- 115 */
|
|
- { S(1024), 819, 616, 410, 207, 2 },
|
|
-
|
|
- /* x^512 + x^411 + x^308 + x^208 + x^104 + x + 1 -- 225 */
|
|
- { S(512), 411, 308, 208, 104, 1 },
|
|
-
|
|
- /* x^512 + x^409 + x^307 + x^206 + x^102 + x^2 + 1 -- 95 */
|
|
- { S(512), 409, 307, 206, 102, 2 },
|
|
- /* x^512 + x^409 + x^309 + x^205 + x^103 + x^2 + 1 -- 95 */
|
|
- { S(512), 409, 309, 205, 103, 2 },
|
|
-
|
|
- /* x^256 + x^205 + x^155 + x^101 + x^52 + x + 1 -- 125 */
|
|
- { S(256), 205, 155, 101, 52, 1 },
|
|
-
|
|
- /* x^128 + x^103 + x^78 + x^51 + x^27 + x^2 + 1 -- 70 */
|
|
- { S(128), 103, 78, 51, 27, 2 },
|
|
-
|
|
- /* x^64 + x^52 + x^39 + x^26 + x^14 + x + 1 -- 15 */
|
|
- { S(64), 52, 39, 26, 14, 1 },
|
|
-#endif
|
|
-};
|
|
+int __cold register_random_ready_notifier(struct notifier_block *nb)
|
|
+{
|
|
+ unsigned long flags;
|
|
+ int ret = -EALREADY;
|
|
+
|
|
+ if (crng_ready())
|
|
+ return ret;
|
|
+
|
|
+ spin_lock_irqsave(&random_ready_chain_lock, flags);
|
|
+ if (!crng_ready())
|
|
+ ret = raw_notifier_chain_register(&random_ready_chain, nb);
|
|
+ spin_unlock_irqrestore(&random_ready_chain_lock, flags);
|
|
+ return ret;
|
|
+}
|
|
|
|
/*
|
|
- * Static global variables
|
|
+ * Delete a previously registered readiness callback function.
|
|
*/
|
|
-static DECLARE_WAIT_QUEUE_HEAD(random_read_wait);
|
|
-static DECLARE_WAIT_QUEUE_HEAD(random_write_wait);
|
|
-static struct fasync_struct *fasync;
|
|
-
|
|
-static DEFINE_SPINLOCK(random_ready_list_lock);
|
|
-static LIST_HEAD(random_ready_list);
|
|
+int __cold unregister_random_ready_notifier(struct notifier_block *nb)
|
|
+{
|
|
+ unsigned long flags;
|
|
+ int ret;
|
|
|
|
-struct crng_state {
|
|
- __u32 state[16];
|
|
- unsigned long init_time;
|
|
- spinlock_t lock;
|
|
-};
|
|
+ spin_lock_irqsave(&random_ready_chain_lock, flags);
|
|
+ ret = raw_notifier_chain_unregister(&random_ready_chain, nb);
|
|
+ spin_unlock_irqrestore(&random_ready_chain_lock, flags);
|
|
+ return ret;
|
|
+}
|
|
|
|
-static struct crng_state primary_crng = {
|
|
- .lock = __SPIN_LOCK_UNLOCKED(primary_crng.lock),
|
|
-};
|
|
+static void __cold process_random_ready_list(void)
|
|
+{
|
|
+ unsigned long flags;
|
|
|
|
-/*
|
|
- * crng_init = 0 --> Uninitialized
|
|
- * 1 --> Initialized
|
|
- * 2 --> Initialized from input_pool
|
|
- *
|
|
- * crng_init is protected by primary_crng->lock, and only increases
|
|
- * its value (from 0->1->2).
|
|
- */
|
|
-static int crng_init = 0;
|
|
-static bool crng_need_final_init = false;
|
|
-#define crng_ready() (likely(crng_init > 1))
|
|
-static int crng_init_cnt = 0;
|
|
-static unsigned long crng_global_init_time = 0;
|
|
-#define CRNG_INIT_CNT_THRESH (2*CHACHA_KEY_SIZE)
|
|
-static void _extract_crng(struct crng_state *crng, __u8 out[CHACHA_BLOCK_SIZE]);
|
|
-static void _crng_backtrack_protect(struct crng_state *crng,
|
|
- __u8 tmp[CHACHA_BLOCK_SIZE], int used);
|
|
-static void process_random_ready_list(void);
|
|
-static void _get_random_bytes(void *buf, int nbytes);
|
|
-
|
|
-static struct ratelimit_state unseeded_warning =
|
|
- RATELIMIT_STATE_INIT("warn_unseeded_randomness", HZ, 3);
|
|
-static struct ratelimit_state urandom_warning =
|
|
- RATELIMIT_STATE_INIT("warn_urandom_randomness", HZ, 3);
|
|
+ spin_lock_irqsave(&random_ready_chain_lock, flags);
|
|
+ raw_notifier_call_chain(&random_ready_chain, 0, NULL);
|
|
+ spin_unlock_irqrestore(&random_ready_chain_lock, flags);
|
|
+}
|
|
|
|
-static int ratelimit_disable __read_mostly;
|
|
+#define warn_unseeded_randomness() \
|
|
+ if (IS_ENABLED(CONFIG_WARN_ALL_UNSEEDED_RANDOM) && !crng_ready()) \
|
|
+ printk_deferred(KERN_NOTICE "random: %s called from %pS with crng_init=%d\n", \
|
|
+ __func__, (void *)_RET_IP_, crng_init)
|
|
|
|
-module_param_named(ratelimit_disable, ratelimit_disable, int, 0644);
|
|
-MODULE_PARM_DESC(ratelimit_disable, "Disable random ratelimit suppression");
|
|
|
|
-/**********************************************************************
|
|
+/*********************************************************************
|
|
*
|
|
- * OS independent entropy store. Here are the functions which handle
|
|
- * storing entropy in an entropy pool.
|
|
+ * Fast key erasure RNG, the "crng".
|
|
*
|
|
- **********************************************************************/
|
|
+ * These functions expand entropy from the entropy extractor into
|
|
+ * long streams for external consumption using the "fast key erasure"
|
|
+ * RNG described at <https://blog.cr.yp.to/20170723-random.html>.
|
|
+ *
|
|
+ * There are a few exported interfaces for use by other drivers:
|
|
+ *
|
|
+ * void get_random_bytes(void *buf, size_t len)
|
|
+ * u32 get_random_u32()
|
|
+ * u64 get_random_u64()
|
|
+ * unsigned int get_random_int()
|
|
+ * unsigned long get_random_long()
|
|
+ *
|
|
+ * These interfaces will return the requested number of random bytes
|
|
+ * into the given buffer or as a return value. This is equivalent to
|
|
+ * a read from /dev/urandom. The u32, u64, int, and long family of
|
|
+ * functions may be higher performance for one-off random integers,
|
|
+ * because they do a bit of buffering and do not invoke reseeding
|
|
+ * until the buffer is emptied.
|
|
+ *
|
|
+ *********************************************************************/
|
|
|
|
-struct entropy_store;
|
|
-struct entropy_store {
|
|
- /* read-only data: */
|
|
- const struct poolinfo *poolinfo;
|
|
- __u32 *pool;
|
|
- const char *name;
|
|
- struct entropy_store *pull;
|
|
- struct work_struct push_work;
|
|
-
|
|
- /* read-write data: */
|
|
- unsigned long last_pulled;
|
|
- spinlock_t lock;
|
|
- unsigned short add_ptr;
|
|
- unsigned short input_rotate;
|
|
- int entropy_count;
|
|
- unsigned int initialized:1;
|
|
- unsigned int last_data_init:1;
|
|
- __u8 last_data[EXTRACT_SIZE];
|
|
+enum {
|
|
+ CRNG_RESEED_START_INTERVAL = HZ,
|
|
+ CRNG_RESEED_INTERVAL = 60 * HZ
|
|
};
|
|
|
|
-static ssize_t extract_entropy(struct entropy_store *r, void *buf,
|
|
- size_t nbytes, int min, int rsvd);
|
|
-static ssize_t _extract_entropy(struct entropy_store *r, void *buf,
|
|
- size_t nbytes, int fips);
|
|
-
|
|
-static void crng_reseed(struct crng_state *crng, struct entropy_store *r);
|
|
-static void push_to_pool(struct work_struct *work);
|
|
-static __u32 input_pool_data[INPUT_POOL_WORDS] __latent_entropy;
|
|
-static __u32 blocking_pool_data[OUTPUT_POOL_WORDS] __latent_entropy;
|
|
+static struct {
|
|
+ u8 key[CHACHA_KEY_SIZE] __aligned(__alignof__(long));
|
|
+ unsigned long birth;
|
|
+ unsigned long generation;
|
|
+ spinlock_t lock;
|
|
+} base_crng = {
|
|
+ .lock = __SPIN_LOCK_UNLOCKED(base_crng.lock)
|
|
+};
|
|
|
|
-static struct entropy_store input_pool = {
|
|
- .poolinfo = &poolinfo_table[0],
|
|
- .name = "input",
|
|
- .lock = __SPIN_LOCK_UNLOCKED(input_pool.lock),
|
|
- .pool = input_pool_data
|
|
+struct crng {
|
|
+ u8 key[CHACHA_KEY_SIZE];
|
|
+ unsigned long generation;
|
|
};
|
|
|
|
-static struct entropy_store blocking_pool = {
|
|
- .poolinfo = &poolinfo_table[1],
|
|
- .name = "blocking",
|
|
- .pull = &input_pool,
|
|
- .lock = __SPIN_LOCK_UNLOCKED(blocking_pool.lock),
|
|
- .pool = blocking_pool_data,
|
|
- .push_work = __WORK_INITIALIZER(blocking_pool.push_work,
|
|
- push_to_pool),
|
|
+static DEFINE_PER_CPU(struct crng, crngs) = {
|
|
+ .generation = ULONG_MAX
|
|
};
|
|
|
|
-static __u32 const twist_table[8] = {
|
|
- 0x00000000, 0x3b6e20c8, 0x76dc4190, 0x4db26158,
|
|
- 0xedb88320, 0xd6d6a3e8, 0x9b64c2b0, 0xa00ae278 };
|
|
+/* Used by crng_reseed() and crng_make_state() to extract a new seed from the input pool. */
|
|
+static void extract_entropy(void *buf, size_t len);
|
|
|
|
-/*
|
|
- * This function adds bytes into the entropy "pool". It does not
|
|
- * update the entropy estimate. The caller should call
|
|
- * credit_entropy_bits if this is appropriate.
|
|
- *
|
|
- * The pool is stirred with a primitive polynomial of the appropriate
|
|
- * degree, and then twisted. We twist by three bits at a time because
|
|
- * 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)
|
|
+/* This extracts a new crng key from the input pool. */
|
|
+static void crng_reseed(void)
|
|
{
|
|
- unsigned long i, tap1, tap2, tap3, tap4, tap5;
|
|
- int input_rotate;
|
|
- int wordmask = r->poolinfo->poolwords - 1;
|
|
- const char *bytes = in;
|
|
- __u32 w;
|
|
-
|
|
- tap1 = r->poolinfo->tap1;
|
|
- tap2 = r->poolinfo->tap2;
|
|
- tap3 = r->poolinfo->tap3;
|
|
- tap4 = r->poolinfo->tap4;
|
|
- tap5 = r->poolinfo->tap5;
|
|
-
|
|
- input_rotate = r->input_rotate;
|
|
- i = r->add_ptr;
|
|
-
|
|
- /* mix one byte at a time to simplify size handling and churn faster */
|
|
- while (nbytes--) {
|
|
- w = rol32(*bytes++, input_rotate);
|
|
- i = (i - 1) & wordmask;
|
|
-
|
|
- /* XOR in the various taps */
|
|
- w ^= r->pool[i];
|
|
- w ^= r->pool[(i + tap1) & wordmask];
|
|
- w ^= r->pool[(i + tap2) & wordmask];
|
|
- w ^= r->pool[(i + tap3) & wordmask];
|
|
- w ^= r->pool[(i + tap4) & wordmask];
|
|
- w ^= r->pool[(i + tap5) & wordmask];
|
|
-
|
|
- /* Mix the result back in with a twist */
|
|
- r->pool[i] = (w >> 3) ^ twist_table[w & 7];
|
|
-
|
|
- /*
|
|
- * Normally, we add 7 bits of rotation to the pool.
|
|
- * At the beginning of the pool, add an extra 7 bits
|
|
- * rotation, so that successive passes spread the
|
|
- * input bits across the pool evenly.
|
|
- */
|
|
- input_rotate = (input_rotate + (i ? 7 : 14)) & 31;
|
|
- }
|
|
+ unsigned long flags;
|
|
+ unsigned long next_gen;
|
|
+ u8 key[CHACHA_KEY_SIZE];
|
|
|
|
- r->input_rotate = input_rotate;
|
|
- r->add_ptr = i;
|
|
-}
|
|
+ extract_entropy(key, sizeof(key));
|
|
|
|
-static void __mix_pool_bytes(struct entropy_store *r, const void *in,
|
|
- int nbytes)
|
|
-{
|
|
- trace_mix_pool_bytes_nolock(r->name, nbytes, _RET_IP_);
|
|
- _mix_pool_bytes(r, in, nbytes);
|
|
+ /*
|
|
+ * We copy the new key into the base_crng, overwriting the old one,
|
|
+ * and update the generation counter. We avoid hitting ULONG_MAX,
|
|
+ * because the per-cpu crngs are initialized to ULONG_MAX, so this
|
|
+ * forces new CPUs that come online to always initialize.
|
|
+ */
|
|
+ spin_lock_irqsave(&base_crng.lock, flags);
|
|
+ memcpy(base_crng.key, key, sizeof(base_crng.key));
|
|
+ next_gen = base_crng.generation + 1;
|
|
+ if (next_gen == ULONG_MAX)
|
|
+ ++next_gen;
|
|
+ WRITE_ONCE(base_crng.generation, next_gen);
|
|
+ WRITE_ONCE(base_crng.birth, jiffies);
|
|
+ if (!crng_ready())
|
|
+ crng_init = CRNG_READY;
|
|
+ spin_unlock_irqrestore(&base_crng.lock, flags);
|
|
+ memzero_explicit(key, sizeof(key));
|
|
}
|
|
|
|
-static void mix_pool_bytes(struct entropy_store *r, const void *in,
|
|
- int nbytes)
|
|
+/*
|
|
+ * This generates a ChaCha block using the provided key, and then
|
|
+ * immediately overwites that key with half the block. It returns
|
|
+ * the resultant ChaCha state to the user, along with the second
|
|
+ * half of the block containing 32 bytes of random data that may
|
|
+ * be used; random_data_len may not be greater than 32.
|
|
+ *
|
|
+ * The returned ChaCha state contains within it a copy of the old
|
|
+ * key value, at index 4, so the state should always be zeroed out
|
|
+ * immediately after using in order to maintain forward secrecy.
|
|
+ * If the state cannot be erased in a timely manner, then it is
|
|
+ * safer to set the random_data parameter to &chacha_state[4] so
|
|
+ * that this function overwrites it before returning.
|
|
+ */
|
|
+static void crng_fast_key_erasure(u8 key[CHACHA_KEY_SIZE],
|
|
+ u32 chacha_state[CHACHA_BLOCK_SIZE / sizeof(u32)],
|
|
+ u8 *random_data, size_t random_data_len)
|
|
{
|
|
- unsigned long flags;
|
|
+ u8 first_block[CHACHA_BLOCK_SIZE];
|
|
+
|
|
+ BUG_ON(random_data_len > 32);
|
|
|
|
- trace_mix_pool_bytes(r->name, nbytes, _RET_IP_);
|
|
- spin_lock_irqsave(&r->lock, flags);
|
|
- _mix_pool_bytes(r, in, nbytes);
|
|
- spin_unlock_irqrestore(&r->lock, flags);
|
|
+ chacha_init_consts(chacha_state);
|
|
+ memcpy(&chacha_state[4], key, CHACHA_KEY_SIZE);
|
|
+ memset(&chacha_state[12], 0, sizeof(u32) * 4);
|
|
+ chacha20_block(chacha_state, first_block);
|
|
+
|
|
+ memcpy(key, first_block, CHACHA_KEY_SIZE);
|
|
+ memcpy(random_data, first_block + CHACHA_KEY_SIZE, random_data_len);
|
|
+ memzero_explicit(first_block, sizeof(first_block));
|
|
}
|
|
|
|
-struct fast_pool {
|
|
- __u32 pool[4];
|
|
- unsigned long last;
|
|
- unsigned short reg_idx;
|
|
- unsigned char count;
|
|
-};
|
|
+/*
|
|
+ * Return whether the crng seed is considered to be sufficiently old
|
|
+ * that a reseeding is needed. This happens if the last reseeding
|
|
+ * was CRNG_RESEED_INTERVAL ago, or during early boot, at an interval
|
|
+ * proportional to the uptime.
|
|
+ */
|
|
+static bool crng_has_old_seed(void)
|
|
+{
|
|
+ static bool early_boot = true;
|
|
+ unsigned long interval = CRNG_RESEED_INTERVAL;
|
|
+
|
|
+ if (unlikely(READ_ONCE(early_boot))) {
|
|
+ time64_t uptime = ktime_get_seconds();
|
|
+ if (uptime >= CRNG_RESEED_INTERVAL / HZ * 2)
|
|
+ WRITE_ONCE(early_boot, false);
|
|
+ else
|
|
+ interval = max_t(unsigned int, CRNG_RESEED_START_INTERVAL,
|
|
+ (unsigned int)uptime / 2 * HZ);
|
|
+ }
|
|
+ return time_is_before_jiffies(READ_ONCE(base_crng.birth) + interval);
|
|
+}
|
|
|
|
/*
|
|
- * 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.
|
|
+ * This function returns a ChaCha state that you may use for generating
|
|
+ * random data. It also returns up to 32 bytes on its own of random data
|
|
+ * that may be used; random_data_len may not be greater than 32.
|
|
*/
|
|
-static void fast_mix(struct fast_pool *f)
|
|
+static void crng_make_state(u32 chacha_state[CHACHA_BLOCK_SIZE / sizeof(u32)],
|
|
+ u8 *random_data, size_t random_data_len)
|
|
{
|
|
- __u32 a = f->pool[0], b = f->pool[1];
|
|
- __u32 c = f->pool[2], d = f->pool[3];
|
|
+ unsigned long flags;
|
|
+ struct crng *crng;
|
|
|
|
- a += b; c += d;
|
|
- b = rol32(b, 6); d = rol32(d, 27);
|
|
- d ^= a; b ^= c;
|
|
+ BUG_ON(random_data_len > 32);
|
|
+
|
|
+ /*
|
|
+ * For the fast path, we check whether we're ready, unlocked first, and
|
|
+ * then re-check once locked later. In the case where we're really not
|
|
+ * ready, we do fast key erasure with the base_crng directly, extracting
|
|
+ * when crng_init is CRNG_EMPTY.
|
|
+ */
|
|
+ if (!crng_ready()) {
|
|
+ bool ready;
|
|
+
|
|
+ spin_lock_irqsave(&base_crng.lock, flags);
|
|
+ ready = crng_ready();
|
|
+ if (!ready) {
|
|
+ if (crng_init == CRNG_EMPTY)
|
|
+ extract_entropy(base_crng.key, sizeof(base_crng.key));
|
|
+ crng_fast_key_erasure(base_crng.key, chacha_state,
|
|
+ random_data, random_data_len);
|
|
+ }
|
|
+ spin_unlock_irqrestore(&base_crng.lock, flags);
|
|
+ if (!ready)
|
|
+ return;
|
|
+ }
|
|
|
|
- a += b; c += d;
|
|
- b = rol32(b, 16); d = rol32(d, 14);
|
|
- d ^= a; b ^= c;
|
|
+ /*
|
|
+ * If the base_crng is old enough, we reseed, which in turn bumps the
|
|
+ * generation counter that we check below.
|
|
+ */
|
|
+ if (unlikely(crng_has_old_seed()))
|
|
+ crng_reseed();
|
|
|
|
- a += b; c += d;
|
|
- b = rol32(b, 6); d = rol32(d, 27);
|
|
- d ^= a; b ^= c;
|
|
+ local_irq_save(flags);
|
|
+ crng = raw_cpu_ptr(&crngs);
|
|
|
|
- a += b; c += d;
|
|
- b = rol32(b, 16); d = rol32(d, 14);
|
|
- d ^= a; b ^= c;
|
|
+ /*
|
|
+ * If our per-cpu crng is older than the base_crng, then it means
|
|
+ * somebody reseeded the base_crng. In that case, we do fast key
|
|
+ * erasure on the base_crng, and use its output as the new key
|
|
+ * for our per-cpu crng. This brings us up to date with base_crng.
|
|
+ */
|
|
+ if (unlikely(crng->generation != READ_ONCE(base_crng.generation))) {
|
|
+ spin_lock(&base_crng.lock);
|
|
+ crng_fast_key_erasure(base_crng.key, chacha_state,
|
|
+ crng->key, sizeof(crng->key));
|
|
+ crng->generation = base_crng.generation;
|
|
+ spin_unlock(&base_crng.lock);
|
|
+ }
|
|
|
|
- f->pool[0] = a; f->pool[1] = b;
|
|
- f->pool[2] = c; f->pool[3] = d;
|
|
- f->count++;
|
|
+ /*
|
|
+ * Finally, when we've made it this far, our per-cpu crng has an up
|
|
+ * to date key, and we can do fast key erasure with it to produce
|
|
+ * some random data and a ChaCha state for the caller. All other
|
|
+ * branches of this function are "unlikely", so most of the time we
|
|
+ * should wind up here immediately.
|
|
+ */
|
|
+ crng_fast_key_erasure(crng->key, chacha_state, random_data, random_data_len);
|
|
+ local_irq_restore(flags);
|
|
}
|
|
|
|
-static void process_random_ready_list(void)
|
|
+static void _get_random_bytes(void *buf, size_t len)
|
|
{
|
|
- unsigned long flags;
|
|
- struct random_ready_callback *rdy, *tmp;
|
|
+ u32 chacha_state[CHACHA_BLOCK_SIZE / sizeof(u32)];
|
|
+ u8 tmp[CHACHA_BLOCK_SIZE];
|
|
+ size_t first_block_len;
|
|
+
|
|
+ if (!len)
|
|
+ return;
|
|
+
|
|
+ first_block_len = min_t(size_t, 32, len);
|
|
+ crng_make_state(chacha_state, buf, first_block_len);
|
|
+ len -= first_block_len;
|
|
+ buf += first_block_len;
|
|
|
|
- spin_lock_irqsave(&random_ready_list_lock, flags);
|
|
- list_for_each_entry_safe(rdy, tmp, &random_ready_list, list) {
|
|
- struct module *owner = rdy->owner;
|
|
+ while (len) {
|
|
+ if (len < CHACHA_BLOCK_SIZE) {
|
|
+ chacha20_block(chacha_state, tmp);
|
|
+ memcpy(buf, tmp, len);
|
|
+ memzero_explicit(tmp, sizeof(tmp));
|
|
+ break;
|
|
+ }
|
|
|
|
- list_del_init(&rdy->list);
|
|
- rdy->func(rdy);
|
|
- module_put(owner);
|
|
+ chacha20_block(chacha_state, buf);
|
|
+ if (unlikely(chacha_state[12] == 0))
|
|
+ ++chacha_state[13];
|
|
+ len -= CHACHA_BLOCK_SIZE;
|
|
+ buf += CHACHA_BLOCK_SIZE;
|
|
}
|
|
- spin_unlock_irqrestore(&random_ready_list_lock, flags);
|
|
+
|
|
+ memzero_explicit(chacha_state, sizeof(chacha_state));
|
|
}
|
|
|
|
/*
|
|
- * Credit (or debit) the entropy store with n bits of entropy.
|
|
- * Use credit_entropy_bits_safe() if the value comes from userspace
|
|
- * or otherwise should be checked for extreme values.
|
|
+ * This function is the exported kernel interface. It returns some
|
|
+ * number of good random numbers, suitable for key generation, seeding
|
|
+ * TCP sequence numbers, etc. It does not rely on the hardware random
|
|
+ * number generator. For random bytes direct from the hardware RNG
|
|
+ * (when available), use get_random_bytes_arch(). In order to ensure
|
|
+ * that the randomness provided by this function is okay, the function
|
|
+ * wait_for_random_bytes() should be called and return 0 at least once
|
|
+ * at any point prior.
|
|
*/
|
|
-static void credit_entropy_bits(struct entropy_store *r, int nbits)
|
|
+void get_random_bytes(void *buf, size_t len)
|
|
{
|
|
- int entropy_count, orig, has_initialized = 0;
|
|
- const int pool_size = r->poolinfo->poolfracbits;
|
|
- int nfrac = nbits << ENTROPY_SHIFT;
|
|
+ warn_unseeded_randomness();
|
|
+ _get_random_bytes(buf, len);
|
|
+}
|
|
+EXPORT_SYMBOL(get_random_bytes);
|
|
|
|
- if (!nbits)
|
|
- return;
|
|
+static ssize_t get_random_bytes_user(struct iov_iter *iter)
|
|
+{
|
|
+ u32 chacha_state[CHACHA_BLOCK_SIZE / sizeof(u32)];
|
|
+ u8 block[CHACHA_BLOCK_SIZE];
|
|
+ size_t ret = 0, copied;
|
|
|
|
-retry:
|
|
- entropy_count = orig = READ_ONCE(r->entropy_count);
|
|
- if (nfrac < 0) {
|
|
- /* Debit */
|
|
- entropy_count += nfrac;
|
|
- } else {
|
|
- /*
|
|
- * Credit: we have to account for the possibility of
|
|
- * overwriting already present entropy. Even in the
|
|
- * ideal case of pure Shannon entropy, new contributions
|
|
- * approach the full value asymptotically:
|
|
- *
|
|
- * entropy <- entropy + (pool_size - entropy) *
|
|
- * (1 - exp(-add_entropy/pool_size))
|
|
- *
|
|
- * For add_entropy <= pool_size/2 then
|
|
- * (1 - exp(-add_entropy/pool_size)) >=
|
|
- * (add_entropy/pool_size)*0.7869...
|
|
- * so we can approximate the exponential with
|
|
- * 3/4*add_entropy/pool_size and still be on the
|
|
- * safe side by adding at most pool_size/2 at a time.
|
|
- *
|
|
- * The use of pool_size-2 in the while statement is to
|
|
- * prevent rounding artifacts from making the loop
|
|
- * arbitrarily long; this limits the loop to log2(pool_size)*2
|
|
- * turns no matter how large nbits is.
|
|
- */
|
|
- int pnfrac = nfrac;
|
|
- const int s = r->poolinfo->poolbitshift + ENTROPY_SHIFT + 2;
|
|
- /* The +2 corresponds to the /4 in the denominator */
|
|
-
|
|
- do {
|
|
- unsigned int anfrac = min(pnfrac, pool_size/2);
|
|
- unsigned int add =
|
|
- ((pool_size - entropy_count)*anfrac*3) >> s;
|
|
-
|
|
- entropy_count += add;
|
|
- pnfrac -= anfrac;
|
|
- } while (unlikely(entropy_count < pool_size-2 && pnfrac));
|
|
- }
|
|
+ if (unlikely(!iov_iter_count(iter)))
|
|
+ return 0;
|
|
|
|
- if (unlikely(entropy_count < 0)) {
|
|
- pr_warn("random: negative entropy/overflow: pool %s count %d\n",
|
|
- r->name, entropy_count);
|
|
- WARN_ON(1);
|
|
- entropy_count = 0;
|
|
- } else if (entropy_count > pool_size)
|
|
- entropy_count = pool_size;
|
|
- if ((r == &blocking_pool) && !r->initialized &&
|
|
- (entropy_count >> ENTROPY_SHIFT) > 128)
|
|
- has_initialized = 1;
|
|
- if (cmpxchg(&r->entropy_count, orig, entropy_count) != orig)
|
|
- goto retry;
|
|
-
|
|
- if (has_initialized) {
|
|
- r->initialized = 1;
|
|
- wake_up_interruptible(&random_read_wait);
|
|
- kill_fasync(&fasync, SIGIO, POLL_IN);
|
|
+ /*
|
|
+ * Immediately overwrite the ChaCha key at index 4 with random
|
|
+ * bytes, in case userspace causes copy_to_user() below to sleep
|
|
+ * forever, so that we still retain forward secrecy in that case.
|
|
+ */
|
|
+ crng_make_state(chacha_state, (u8 *)&chacha_state[4], CHACHA_KEY_SIZE);
|
|
+ /*
|
|
+ * However, if we're doing a read of len <= 32, we don't need to
|
|
+ * use chacha_state after, so we can simply return those bytes to
|
|
+ * the user directly.
|
|
+ */
|
|
+ if (iov_iter_count(iter) <= CHACHA_KEY_SIZE) {
|
|
+ ret = copy_to_iter(&chacha_state[4], CHACHA_KEY_SIZE, iter);
|
|
+ goto out_zero_chacha;
|
|
}
|
|
|
|
- trace_credit_entropy_bits(r->name, nbits,
|
|
- entropy_count >> ENTROPY_SHIFT, _RET_IP_);
|
|
+ for (;;) {
|
|
+ chacha20_block(chacha_state, block);
|
|
+ if (unlikely(chacha_state[12] == 0))
|
|
+ ++chacha_state[13];
|
|
|
|
- if (r == &input_pool) {
|
|
- int entropy_bits = entropy_count >> ENTROPY_SHIFT;
|
|
- struct entropy_store *other = &blocking_pool;
|
|
-
|
|
- if (crng_init < 2) {
|
|
- if (entropy_bits < 128)
|
|
- return;
|
|
- crng_reseed(&primary_crng, r);
|
|
- entropy_bits = r->entropy_count >> ENTROPY_SHIFT;
|
|
- }
|
|
-
|
|
- /* initialize the blocking pool if necessary */
|
|
- if (entropy_bits >= random_read_wakeup_bits &&
|
|
- !other->initialized) {
|
|
- schedule_work(&other->push_work);
|
|
- return;
|
|
- }
|
|
+ copied = copy_to_iter(block, sizeof(block), iter);
|
|
+ ret += copied;
|
|
+ if (!iov_iter_count(iter) || copied != sizeof(block))
|
|
+ break;
|
|
|
|
- /* should we wake readers? */
|
|
- if (entropy_bits >= random_read_wakeup_bits &&
|
|
- wq_has_sleeper(&random_read_wait)) {
|
|
- wake_up_interruptible(&random_read_wait);
|
|
- kill_fasync(&fasync, SIGIO, POLL_IN);
|
|
+ BUILD_BUG_ON(PAGE_SIZE % sizeof(block) != 0);
|
|
+ if (ret % PAGE_SIZE == 0) {
|
|
+ if (signal_pending(current))
|
|
+ break;
|
|
+ cond_resched();
|
|
}
|
|
- /* If the input pool is getting full, and the blocking
|
|
- * pool has room, send some entropy to the blocking
|
|
- * pool.
|
|
- */
|
|
- if (!work_pending(&other->push_work) &&
|
|
- (ENTROPY_BITS(r) > 6 * r->poolinfo->poolbytes) &&
|
|
- (ENTROPY_BITS(other) <= 6 * other->poolinfo->poolbytes))
|
|
- schedule_work(&other->push_work);
|
|
}
|
|
-}
|
|
|
|
-static int credit_entropy_bits_safe(struct entropy_store *r, int nbits)
|
|
-{
|
|
- const int nbits_max = r->poolinfo->poolwords * 32;
|
|
-
|
|
- if (nbits < 0)
|
|
- return -EINVAL;
|
|
-
|
|
- /* Cap the value to avoid overflows */
|
|
- nbits = min(nbits, nbits_max);
|
|
-
|
|
- credit_entropy_bits(r, nbits);
|
|
- return 0;
|
|
+ memzero_explicit(block, sizeof(block));
|
|
+out_zero_chacha:
|
|
+ memzero_explicit(chacha_state, sizeof(chacha_state));
|
|
+ return ret ? ret : -EFAULT;
|
|
}
|
|
|
|
-/*********************************************************************
|
|
- *
|
|
- * CRNG using CHACHA20
|
|
- *
|
|
- *********************************************************************/
|
|
-
|
|
-#define CRNG_RESEED_INTERVAL (300*HZ)
|
|
-
|
|
-static DECLARE_WAIT_QUEUE_HEAD(crng_init_wait);
|
|
+/*
|
|
+ * Batched entropy returns random integers. The quality of the random
|
|
+ * number is good as /dev/urandom. In order to ensure that the randomness
|
|
+ * provided by this function is okay, the function wait_for_random_bytes()
|
|
+ * should be called and return 0 at least once at any point prior.
|
|
+ */
|
|
|
|
-#ifdef CONFIG_NUMA
|
|
+#define DEFINE_BATCHED_ENTROPY(type) \
|
|
+struct batch_ ##type { \
|
|
+ /* \
|
|
+ * We make this 1.5x a ChaCha block, so that we get the \
|
|
+ * remaining 32 bytes from fast key erasure, plus one full \
|
|
+ * block from the detached ChaCha state. We can increase \
|
|
+ * the size of this later if needed so long as we keep the \
|
|
+ * formula of (integer_blocks + 0.5) * CHACHA_BLOCK_SIZE. \
|
|
+ */ \
|
|
+ type entropy[CHACHA_BLOCK_SIZE * 3 / (2 * sizeof(type))]; \
|
|
+ unsigned long generation; \
|
|
+ unsigned int position; \
|
|
+}; \
|
|
+ \
|
|
+static DEFINE_PER_CPU(struct batch_ ##type, batched_entropy_ ##type) = { \
|
|
+ .position = UINT_MAX \
|
|
+}; \
|
|
+ \
|
|
+type get_random_ ##type(void) \
|
|
+{ \
|
|
+ type ret; \
|
|
+ unsigned long flags; \
|
|
+ struct batch_ ##type *batch; \
|
|
+ unsigned long next_gen; \
|
|
+ \
|
|
+ warn_unseeded_randomness(); \
|
|
+ \
|
|
+ if (!crng_ready()) { \
|
|
+ _get_random_bytes(&ret, sizeof(ret)); \
|
|
+ return ret; \
|
|
+ } \
|
|
+ \
|
|
+ local_irq_save(flags); \
|
|
+ batch = raw_cpu_ptr(&batched_entropy_##type); \
|
|
+ \
|
|
+ next_gen = READ_ONCE(base_crng.generation); \
|
|
+ if (batch->position >= ARRAY_SIZE(batch->entropy) || \
|
|
+ next_gen != batch->generation) { \
|
|
+ _get_random_bytes(batch->entropy, sizeof(batch->entropy)); \
|
|
+ batch->position = 0; \
|
|
+ batch->generation = next_gen; \
|
|
+ } \
|
|
+ \
|
|
+ ret = batch->entropy[batch->position]; \
|
|
+ batch->entropy[batch->position] = 0; \
|
|
+ ++batch->position; \
|
|
+ local_irq_restore(flags); \
|
|
+ return ret; \
|
|
+} \
|
|
+EXPORT_SYMBOL(get_random_ ##type);
|
|
+
|
|
+DEFINE_BATCHED_ENTROPY(u64)
|
|
+DEFINE_BATCHED_ENTROPY(u32)
|
|
+
|
|
+#ifdef CONFIG_SMP
|
|
/*
|
|
- * Hack to deal with crazy userspace progams when they are all trying
|
|
- * to access /dev/urandom in parallel. The programs are almost
|
|
- * certainly doing something terribly wrong, but we'll work around
|
|
- * their brain damage.
|
|
+ * This function is called when the CPU is coming up, with entry
|
|
+ * CPUHP_RANDOM_PREPARE, which comes before CPUHP_WORKQUEUE_PREP.
|
|
*/
|
|
-static struct crng_state **crng_node_pool __read_mostly;
|
|
+int __cold random_prepare_cpu(unsigned int cpu)
|
|
+{
|
|
+ /*
|
|
+ * When the cpu comes back online, immediately invalidate both
|
|
+ * the per-cpu crng and all batches, so that we serve fresh
|
|
+ * randomness.
|
|
+ */
|
|
+ per_cpu_ptr(&crngs, cpu)->generation = ULONG_MAX;
|
|
+ per_cpu_ptr(&batched_entropy_u32, cpu)->position = UINT_MAX;
|
|
+ per_cpu_ptr(&batched_entropy_u64, cpu)->position = UINT_MAX;
|
|
+ return 0;
|
|
+}
|
|
#endif
|
|
|
|
-static void invalidate_batched_entropy(void);
|
|
-static void numa_crng_init(void);
|
|
+/*
|
|
+ * This function will use the architecture-specific hardware random
|
|
+ * number generator if it is available. It is not recommended for
|
|
+ * use. Use get_random_bytes() instead. It returns the number of
|
|
+ * bytes filled in.
|
|
+ */
|
|
+size_t __must_check get_random_bytes_arch(void *buf, size_t len)
|
|
+{
|
|
+ size_t left = len;
|
|
+ u8 *p = buf;
|
|
|
|
-static bool trust_cpu __ro_after_init = IS_ENABLED(CONFIG_RANDOM_TRUST_CPU);
|
|
-static int __init parse_trust_cpu(char *arg)
|
|
-{
|
|
- return kstrtobool(arg, &trust_cpu);
|
|
-}
|
|
-early_param("random.trust_cpu", parse_trust_cpu);
|
|
-
|
|
-static void crng_initialize(struct crng_state *crng)
|
|
-{
|
|
- int i;
|
|
- int arch_init = 1;
|
|
- unsigned long rv;
|
|
-
|
|
- memcpy(&crng->state[0], "expand 32-byte k", 16);
|
|
- if (crng == &primary_crng)
|
|
- _extract_entropy(&input_pool, &crng->state[4],
|
|
- sizeof(__u32) * 12, 0);
|
|
- else
|
|
- _get_random_bytes(&crng->state[4], sizeof(__u32) * 12);
|
|
- for (i = 4; i < 16; i++) {
|
|
- if (!arch_get_random_seed_long(&rv) &&
|
|
- !arch_get_random_long(&rv)) {
|
|
- rv = random_get_entropy();
|
|
- arch_init = 0;
|
|
- }
|
|
- crng->state[i] ^= rv;
|
|
- }
|
|
- if (trust_cpu && arch_init && crng == &primary_crng) {
|
|
- invalidate_batched_entropy();
|
|
- numa_crng_init();
|
|
- crng_init = 2;
|
|
- pr_notice("random: crng done (trusting CPU's manufacturer)\n");
|
|
- }
|
|
- crng->init_time = jiffies - CRNG_RESEED_INTERVAL - 1;
|
|
-}
|
|
+ while (left) {
|
|
+ unsigned long v;
|
|
+ size_t block_len = min_t(size_t, left, sizeof(unsigned long));
|
|
|
|
-static void crng_finalize_init(struct crng_state *crng)
|
|
-{
|
|
- if (crng != &primary_crng || crng_init >= 2)
|
|
- return;
|
|
- if (!system_wq) {
|
|
- /* We can't call numa_crng_init until we have workqueues,
|
|
- * so mark this for processing later. */
|
|
- crng_need_final_init = true;
|
|
- return;
|
|
- }
|
|
+ if (!arch_get_random_long(&v))
|
|
+ break;
|
|
|
|
- invalidate_batched_entropy();
|
|
- numa_crng_init();
|
|
- crng_init = 2;
|
|
- process_random_ready_list();
|
|
- wake_up_interruptible(&crng_init_wait);
|
|
- kill_fasync(&fasync, SIGIO, POLL_IN);
|
|
- pr_notice("crng init done\n");
|
|
- if (unseeded_warning.missed) {
|
|
- pr_notice("random: %d get_random_xx warning(s) missed "
|
|
- "due to ratelimiting\n",
|
|
- unseeded_warning.missed);
|
|
- unseeded_warning.missed = 0;
|
|
- }
|
|
- if (urandom_warning.missed) {
|
|
- pr_notice("random: %d urandom warning(s) missed "
|
|
- "due to ratelimiting\n",
|
|
- urandom_warning.missed);
|
|
- urandom_warning.missed = 0;
|
|
+ memcpy(p, &v, block_len);
|
|
+ p += block_len;
|
|
+ left -= block_len;
|
|
}
|
|
-}
|
|
|
|
-#ifdef CONFIG_NUMA
|
|
-static void do_numa_crng_init(struct work_struct *work)
|
|
-{
|
|
- int i;
|
|
- struct crng_state *crng;
|
|
- struct crng_state **pool;
|
|
-
|
|
- pool = kcalloc(nr_node_ids, sizeof(*pool), GFP_KERNEL|__GFP_NOFAIL);
|
|
- for_each_online_node(i) {
|
|
- crng = kmalloc_node(sizeof(struct crng_state),
|
|
- GFP_KERNEL | __GFP_NOFAIL, i);
|
|
- spin_lock_init(&crng->lock);
|
|
- crng_initialize(crng);
|
|
- pool[i] = crng;
|
|
- }
|
|
- /* pairs with READ_ONCE() in select_crng() */
|
|
- if (cmpxchg_release(&crng_node_pool, NULL, pool) != NULL) {
|
|
- for_each_node(i)
|
|
- kfree(pool[i]);
|
|
- kfree(pool);
|
|
- }
|
|
+ return len - left;
|
|
}
|
|
+EXPORT_SYMBOL(get_random_bytes_arch);
|
|
|
|
-static DECLARE_WORK(numa_crng_init_work, do_numa_crng_init);
|
|
-
|
|
-static void numa_crng_init(void)
|
|
-{
|
|
- schedule_work(&numa_crng_init_work);
|
|
-}
|
|
|
|
-static struct crng_state *select_crng(void)
|
|
-{
|
|
- struct crng_state **pool;
|
|
- int nid = numa_node_id();
|
|
+/**********************************************************************
|
|
+ *
|
|
+ * Entropy accumulation and extraction routines.
|
|
+ *
|
|
+ * Callers may add entropy via:
|
|
+ *
|
|
+ * static void mix_pool_bytes(const void *buf, size_t len)
|
|
+ *
|
|
+ * After which, if added entropy should be credited:
|
|
+ *
|
|
+ * static void credit_init_bits(size_t bits)
|
|
+ *
|
|
+ * Finally, extract entropy via:
|
|
+ *
|
|
+ * static void extract_entropy(void *buf, size_t len)
|
|
+ *
|
|
+ **********************************************************************/
|
|
|
|
- /* pairs with cmpxchg_release() in do_numa_crng_init() */
|
|
- pool = READ_ONCE(crng_node_pool);
|
|
- if (pool && pool[nid])
|
|
- return pool[nid];
|
|
+enum {
|
|
+ POOL_BITS = BLAKE2S_HASH_SIZE * 8,
|
|
+ POOL_READY_BITS = POOL_BITS, /* When crng_init->CRNG_READY */
|
|
+ POOL_EARLY_BITS = POOL_READY_BITS / 2 /* When crng_init->CRNG_EARLY */
|
|
+};
|
|
|
|
- return &primary_crng;
|
|
-}
|
|
-#else
|
|
-static void numa_crng_init(void) {}
|
|
+static struct {
|
|
+ struct blake2s_state hash;
|
|
+ spinlock_t lock;
|
|
+ unsigned int init_bits;
|
|
+} input_pool = {
|
|
+ .hash.h = { BLAKE2S_IV0 ^ (0x01010000 | BLAKE2S_HASH_SIZE),
|
|
+ BLAKE2S_IV1, BLAKE2S_IV2, BLAKE2S_IV3, BLAKE2S_IV4,
|
|
+ BLAKE2S_IV5, BLAKE2S_IV6, BLAKE2S_IV7 },
|
|
+ .hash.outlen = BLAKE2S_HASH_SIZE,
|
|
+ .lock = __SPIN_LOCK_UNLOCKED(input_pool.lock),
|
|
+};
|
|
|
|
-static struct crng_state *select_crng(void)
|
|
+static void _mix_pool_bytes(const void *buf, size_t len)
|
|
{
|
|
- return &primary_crng;
|
|
+ blake2s_update(&input_pool.hash, buf, len);
|
|
}
|
|
-#endif
|
|
|
|
/*
|
|
- * crng_fast_load() can be called by code in the interrupt service
|
|
- * path. So we can't afford to dilly-dally. Returns the number of
|
|
- * bytes processed from cp.
|
|
+ * This function adds bytes into the input pool. It does not
|
|
+ * update the initialization bit counter; the caller should call
|
|
+ * credit_init_bits if this is appropriate.
|
|
*/
|
|
-static size_t crng_fast_load(const char *cp, size_t len)
|
|
+static void mix_pool_bytes(const void *buf, size_t len)
|
|
{
|
|
unsigned long flags;
|
|
- char *p;
|
|
- size_t ret = 0;
|
|
-
|
|
- if (!spin_trylock_irqsave(&primary_crng.lock, flags))
|
|
- return 0;
|
|
- if (crng_init != 0) {
|
|
- spin_unlock_irqrestore(&primary_crng.lock, flags);
|
|
- return 0;
|
|
- }
|
|
- p = (unsigned char *) &primary_crng.state[4];
|
|
- while (len > 0 && crng_init_cnt < CRNG_INIT_CNT_THRESH) {
|
|
- p[crng_init_cnt % CHACHA_KEY_SIZE] ^= *cp;
|
|
- cp++; crng_init_cnt++; len--; ret++;
|
|
- }
|
|
- spin_unlock_irqrestore(&primary_crng.lock, flags);
|
|
- if (crng_init_cnt >= CRNG_INIT_CNT_THRESH) {
|
|
- invalidate_batched_entropy();
|
|
- crng_init = 1;
|
|
- wake_up_interruptible(&crng_init_wait);
|
|
- pr_notice("random: fast init done\n");
|
|
- }
|
|
- return ret;
|
|
-}
|
|
|
|
-/*
|
|
- * crng_slow_load() is called by add_device_randomness, which has two
|
|
- * attributes. (1) We can't trust the buffer passed to it is
|
|
- * guaranteed to be unpredictable (so it might not have any entropy at
|
|
- * all), and (2) it doesn't have the performance constraints of
|
|
- * crng_fast_load().
|
|
- *
|
|
- * So we do something more comprehensive which is guaranteed to touch
|
|
- * all of the primary_crng's state, and which uses a LFSR with a
|
|
- * period of 255 as part of the mixing algorithm. Finally, we do
|
|
- * *not* advance crng_init_cnt since buffer we may get may be something
|
|
- * like a fixed DMI table (for example), which might very well be
|
|
- * unique to the machine, but is otherwise unvarying.
|
|
- */
|
|
-static int crng_slow_load(const char *cp, size_t len)
|
|
-{
|
|
- unsigned long flags;
|
|
- static unsigned char lfsr = 1;
|
|
- unsigned char tmp;
|
|
- unsigned i, max = CHACHA_KEY_SIZE;
|
|
- const char * src_buf = cp;
|
|
- char * dest_buf = (char *) &primary_crng.state[4];
|
|
-
|
|
- if (!spin_trylock_irqsave(&primary_crng.lock, flags))
|
|
- return 0;
|
|
- if (crng_init != 0) {
|
|
- spin_unlock_irqrestore(&primary_crng.lock, flags);
|
|
- return 0;
|
|
- }
|
|
- if (len > max)
|
|
- max = len;
|
|
-
|
|
- for (i = 0; i < max ; i++) {
|
|
- tmp = lfsr;
|
|
- lfsr >>= 1;
|
|
- if (tmp & 1)
|
|
- lfsr ^= 0xE1;
|
|
- tmp = dest_buf[i % CHACHA_KEY_SIZE];
|
|
- dest_buf[i % CHACHA_KEY_SIZE] ^= src_buf[i % len] ^ lfsr;
|
|
- lfsr += (tmp << 3) | (tmp >> 5);
|
|
- }
|
|
- spin_unlock_irqrestore(&primary_crng.lock, flags);
|
|
- return 1;
|
|
-}
|
|
-
|
|
-static void crng_reseed(struct crng_state *crng, struct entropy_store *r)
|
|
-{
|
|
- unsigned long flags;
|
|
- int i, num;
|
|
- union {
|
|
- __u8 block[CHACHA_BLOCK_SIZE];
|
|
- __u32 key[8];
|
|
- } buf;
|
|
-
|
|
- if (r) {
|
|
- num = extract_entropy(r, &buf, 32, 16, 0);
|
|
- if (num == 0)
|
|
- return;
|
|
- } else {
|
|
- _extract_crng(&primary_crng, buf.block);
|
|
- _crng_backtrack_protect(&primary_crng, buf.block,
|
|
- CHACHA_KEY_SIZE);
|
|
- }
|
|
- spin_lock_irqsave(&crng->lock, flags);
|
|
- for (i = 0; i < 8; i++) {
|
|
- unsigned long rv;
|
|
- if (!arch_get_random_seed_long(&rv) &&
|
|
- !arch_get_random_long(&rv))
|
|
- rv = random_get_entropy();
|
|
- crng->state[i+4] ^= buf.key[i] ^ rv;
|
|
- }
|
|
- memzero_explicit(&buf, sizeof(buf));
|
|
- WRITE_ONCE(crng->init_time, jiffies);
|
|
- spin_unlock_irqrestore(&crng->lock, flags);
|
|
- crng_finalize_init(crng);
|
|
-}
|
|
-
|
|
-static void _extract_crng(struct crng_state *crng,
|
|
- __u8 out[CHACHA_BLOCK_SIZE])
|
|
-{
|
|
- unsigned long v, flags, init_time;
|
|
-
|
|
- if (crng_ready()) {
|
|
- init_time = READ_ONCE(crng->init_time);
|
|
- if (time_after(READ_ONCE(crng_global_init_time), init_time) ||
|
|
- time_after(jiffies, init_time + CRNG_RESEED_INTERVAL))
|
|
- crng_reseed(crng, crng == &primary_crng ?
|
|
- &input_pool : NULL);
|
|
- }
|
|
- spin_lock_irqsave(&crng->lock, flags);
|
|
- if (arch_get_random_long(&v))
|
|
- crng->state[14] ^= v;
|
|
- chacha20_block(&crng->state[0], out);
|
|
- if (crng->state[12] == 0)
|
|
- crng->state[13]++;
|
|
- spin_unlock_irqrestore(&crng->lock, flags);
|
|
-}
|
|
-
|
|
-static void extract_crng(__u8 out[CHACHA_BLOCK_SIZE])
|
|
-{
|
|
- _extract_crng(select_crng(), out);
|
|
+ spin_lock_irqsave(&input_pool.lock, flags);
|
|
+ _mix_pool_bytes(buf, len);
|
|
+ spin_unlock_irqrestore(&input_pool.lock, flags);
|
|
}
|
|
|
|
/*
|
|
- * Use the leftover bytes from the CRNG block output (if there is
|
|
- * enough) to mutate the CRNG key to provide backtracking protection.
|
|
+ * This is an HKDF-like construction for using the hashed collected entropy
|
|
+ * as a PRF key, that's then expanded block-by-block.
|
|
*/
|
|
-static void _crng_backtrack_protect(struct crng_state *crng,
|
|
- __u8 tmp[CHACHA_BLOCK_SIZE], int used)
|
|
+static void extract_entropy(void *buf, size_t len)
|
|
{
|
|
- unsigned long flags;
|
|
- __u32 *s, *d;
|
|
- int i;
|
|
-
|
|
- used = round_up(used, sizeof(__u32));
|
|
- if (used + CHACHA_KEY_SIZE > CHACHA_BLOCK_SIZE) {
|
|
- extract_crng(tmp);
|
|
- used = 0;
|
|
+ unsigned long flags;
|
|
+ u8 seed[BLAKE2S_HASH_SIZE], next_key[BLAKE2S_HASH_SIZE];
|
|
+ struct {
|
|
+ unsigned long rdseed[32 / sizeof(long)];
|
|
+ size_t counter;
|
|
+ } block;
|
|
+ size_t i;
|
|
+
|
|
+ for (i = 0; i < ARRAY_SIZE(block.rdseed); ++i) {
|
|
+ if (!arch_get_random_seed_long(&block.rdseed[i]) &&
|
|
+ !arch_get_random_long(&block.rdseed[i]))
|
|
+ block.rdseed[i] = random_get_entropy();
|
|
}
|
|
- spin_lock_irqsave(&crng->lock, flags);
|
|
- s = (__u32 *) &tmp[used];
|
|
- d = &crng->state[4];
|
|
- for (i=0; i < 8; i++)
|
|
- *d++ ^= *s++;
|
|
- spin_unlock_irqrestore(&crng->lock, flags);
|
|
-}
|
|
|
|
-static void crng_backtrack_protect(__u8 tmp[CHACHA_BLOCK_SIZE], int used)
|
|
-{
|
|
- _crng_backtrack_protect(select_crng(), tmp, used);
|
|
-}
|
|
+ spin_lock_irqsave(&input_pool.lock, flags);
|
|
|
|
-static ssize_t extract_crng_user(void __user *buf, size_t nbytes)
|
|
-{
|
|
- ssize_t ret = 0, i = CHACHA_BLOCK_SIZE;
|
|
- __u8 tmp[CHACHA_BLOCK_SIZE] __aligned(4);
|
|
- int large_request = (nbytes > 256);
|
|
-
|
|
- while (nbytes) {
|
|
- if (large_request && need_resched()) {
|
|
- if (signal_pending(current)) {
|
|
- if (ret == 0)
|
|
- ret = -ERESTARTSYS;
|
|
- break;
|
|
- }
|
|
- schedule();
|
|
- }
|
|
+ /* seed = HASHPRF(last_key, entropy_input) */
|
|
+ blake2s_final(&input_pool.hash, seed);
|
|
|
|
- extract_crng(tmp);
|
|
- i = min_t(int, nbytes, CHACHA_BLOCK_SIZE);
|
|
- if (copy_to_user(buf, tmp, i)) {
|
|
- ret = -EFAULT;
|
|
- break;
|
|
- }
|
|
+ /* next_key = HASHPRF(seed, RDSEED || 0) */
|
|
+ block.counter = 0;
|
|
+ blake2s(next_key, (u8 *)&block, seed, sizeof(next_key), sizeof(block), sizeof(seed));
|
|
+ blake2s_init_key(&input_pool.hash, BLAKE2S_HASH_SIZE, next_key, sizeof(next_key));
|
|
|
|
- nbytes -= i;
|
|
+ spin_unlock_irqrestore(&input_pool.lock, flags);
|
|
+ memzero_explicit(next_key, sizeof(next_key));
|
|
+
|
|
+ while (len) {
|
|
+ i = min_t(size_t, len, BLAKE2S_HASH_SIZE);
|
|
+ /* output = HASHPRF(seed, RDSEED || ++counter) */
|
|
+ ++block.counter;
|
|
+ blake2s(buf, (u8 *)&block, seed, i, sizeof(block), sizeof(seed));
|
|
+ len -= i;
|
|
buf += i;
|
|
- ret += i;
|
|
}
|
|
- crng_backtrack_protect(tmp, i);
|
|
-
|
|
- /* Wipe data just written to memory */
|
|
- memzero_explicit(tmp, sizeof(tmp));
|
|
|
|
- return ret;
|
|
+ memzero_explicit(seed, sizeof(seed));
|
|
+ memzero_explicit(&block, sizeof(block));
|
|
}
|
|
|
|
+#define credit_init_bits(bits) if (!crng_ready()) _credit_init_bits(bits)
|
|
|
|
-/*********************************************************************
|
|
- *
|
|
- * Entropy input management
|
|
- *
|
|
- *********************************************************************/
|
|
-
|
|
-/* There is one of these per entropy source */
|
|
-struct timer_rand_state {
|
|
- cycles_t last_time;
|
|
- long last_delta, last_delta2;
|
|
-};
|
|
-
|
|
-#define INIT_TIMER_RAND_STATE { INITIAL_JIFFIES, };
|
|
-
|
|
-/*
|
|
- * Add device- or boot-specific data to the input pool to help
|
|
- * initialize it.
|
|
- *
|
|
- * None of this adds any entropy; it is meant to avoid the problem of
|
|
- * the entropy pool having similar initial state across largely
|
|
- * identical devices.
|
|
- */
|
|
-void add_device_randomness(const void *buf, unsigned int size)
|
|
+static void __cold _credit_init_bits(size_t bits)
|
|
{
|
|
- unsigned long time = random_get_entropy() ^ jiffies;
|
|
+ unsigned int new, orig, add;
|
|
unsigned long flags;
|
|
|
|
- if (!crng_ready() && size)
|
|
- crng_slow_load(buf, size);
|
|
-
|
|
- trace_add_device_randomness(size, _RET_IP_);
|
|
- spin_lock_irqsave(&input_pool.lock, flags);
|
|
- _mix_pool_bytes(&input_pool, buf, size);
|
|
- _mix_pool_bytes(&input_pool, &time, sizeof(time));
|
|
- spin_unlock_irqrestore(&input_pool.lock, flags);
|
|
-}
|
|
-EXPORT_SYMBOL(add_device_randomness);
|
|
-
|
|
-static struct timer_rand_state input_timer_state = INIT_TIMER_RAND_STATE;
|
|
-
|
|
-/*
|
|
- * This function adds entropy to the entropy "pool" by using timing
|
|
- * delays. It uses the timer_rand_state structure to make an estimate
|
|
- * of how many bits of entropy this call has added to the pool.
|
|
- *
|
|
- * The number "num" is also added to the pool - it should somehow describe
|
|
- * the type of event which just happened. This is currently 0-255 for
|
|
- * keyboard scan codes, and 256 upwards for interrupts.
|
|
- *
|
|
- */
|
|
-static void add_timer_randomness(struct timer_rand_state *state, unsigned num)
|
|
-{
|
|
- struct entropy_store *r;
|
|
- struct {
|
|
- long jiffies;
|
|
- unsigned cycles;
|
|
- unsigned num;
|
|
- } sample;
|
|
- long delta, delta2, delta3;
|
|
-
|
|
- sample.jiffies = jiffies;
|
|
- sample.cycles = random_get_entropy();
|
|
- sample.num = num;
|
|
- r = &input_pool;
|
|
- mix_pool_bytes(r, &sample, sizeof(sample));
|
|
-
|
|
- /*
|
|
- * Calculate number of bits of randomness we probably added.
|
|
- * We take into account the first, second and third-order deltas
|
|
- * in order to make our estimate.
|
|
- */
|
|
- delta = sample.jiffies - READ_ONCE(state->last_time);
|
|
- WRITE_ONCE(state->last_time, sample.jiffies);
|
|
-
|
|
- delta2 = delta - READ_ONCE(state->last_delta);
|
|
- WRITE_ONCE(state->last_delta, delta);
|
|
-
|
|
- delta3 = delta2 - READ_ONCE(state->last_delta2);
|
|
- WRITE_ONCE(state->last_delta2, delta2);
|
|
-
|
|
- if (delta < 0)
|
|
- delta = -delta;
|
|
- if (delta2 < 0)
|
|
- delta2 = -delta2;
|
|
- if (delta3 < 0)
|
|
- delta3 = -delta3;
|
|
- if (delta > delta2)
|
|
- delta = delta2;
|
|
- if (delta > delta3)
|
|
- delta = delta3;
|
|
-
|
|
- /*
|
|
- * delta is now minimum absolute delta.
|
|
- * Round down by 1 bit on general principles,
|
|
- * and limit entropy entimate to 12 bits.
|
|
- */
|
|
- credit_entropy_bits(r, min_t(int, fls(delta>>1), 11));
|
|
-}
|
|
-
|
|
-void add_input_randomness(unsigned int type, unsigned int code,
|
|
- unsigned int value)
|
|
-{
|
|
- static unsigned char last_value;
|
|
-
|
|
- /* ignore autorepeat and the like */
|
|
- if (value == last_value)
|
|
+ if (!bits)
|
|
return;
|
|
|
|
- last_value = value;
|
|
- add_timer_randomness(&input_timer_state,
|
|
- (type << 4) ^ code ^ (code >> 4) ^ value);
|
|
- trace_add_input_randomness(ENTROPY_BITS(&input_pool));
|
|
-}
|
|
-EXPORT_SYMBOL_GPL(add_input_randomness);
|
|
-
|
|
-static DEFINE_PER_CPU(struct fast_pool, irq_randomness);
|
|
-
|
|
-#ifdef ADD_INTERRUPT_BENCH
|
|
-static unsigned long avg_cycles, avg_deviation;
|
|
-
|
|
-#define AVG_SHIFT 8 /* Exponential average factor k=1/256 */
|
|
-#define FIXED_1_2 (1 << (AVG_SHIFT-1))
|
|
-
|
|
-static void add_interrupt_bench(cycles_t start)
|
|
-{
|
|
- long delta = random_get_entropy() - start;
|
|
-
|
|
- /* Use a weighted moving average */
|
|
- delta = delta - ((avg_cycles + FIXED_1_2) >> AVG_SHIFT);
|
|
- avg_cycles += delta;
|
|
- /* And average deviation */
|
|
- delta = abs(delta) - ((avg_deviation + FIXED_1_2) >> AVG_SHIFT);
|
|
- avg_deviation += delta;
|
|
-}
|
|
-#else
|
|
-#define add_interrupt_bench(x)
|
|
-#endif
|
|
-
|
|
-static __u32 get_reg(struct fast_pool *f, struct pt_regs *regs)
|
|
-{
|
|
- __u32 *ptr = (__u32 *) regs;
|
|
- unsigned int idx;
|
|
+ add = min_t(size_t, bits, POOL_BITS);
|
|
|
|
- if (regs == NULL)
|
|
- return 0;
|
|
- idx = READ_ONCE(f->reg_idx);
|
|
- if (idx >= sizeof(struct pt_regs) / sizeof(__u32))
|
|
- idx = 0;
|
|
- ptr += idx++;
|
|
- WRITE_ONCE(f->reg_idx, idx);
|
|
- return *ptr;
|
|
-}
|
|
+ do {
|
|
+ orig = READ_ONCE(input_pool.init_bits);
|
|
+ new = min_t(unsigned int, POOL_BITS, orig + add);
|
|
+ } while (cmpxchg(&input_pool.init_bits, orig, new) != orig);
|
|
|
|
-void add_interrupt_randomness(int irq, int irq_flags)
|
|
-{
|
|
- struct entropy_store *r;
|
|
- struct fast_pool *fast_pool = this_cpu_ptr(&irq_randomness);
|
|
- struct pt_regs *regs = get_irq_regs();
|
|
- unsigned long now = jiffies;
|
|
- cycles_t cycles = random_get_entropy();
|
|
- __u32 c_high, j_high;
|
|
- __u64 ip;
|
|
- unsigned long seed;
|
|
- int credit = 0;
|
|
-
|
|
- if (cycles == 0)
|
|
- cycles = get_reg(fast_pool, regs);
|
|
- c_high = (sizeof(cycles) > 4) ? cycles >> 32 : 0;
|
|
- j_high = (sizeof(now) > 4) ? now >> 32 : 0;
|
|
- fast_pool->pool[0] ^= cycles ^ j_high ^ irq;
|
|
- fast_pool->pool[1] ^= now ^ c_high;
|
|
- ip = regs ? instruction_pointer(regs) : _RET_IP_;
|
|
- fast_pool->pool[2] ^= ip;
|
|
- fast_pool->pool[3] ^= (sizeof(ip) > 4) ? ip >> 32 :
|
|
- get_reg(fast_pool, regs);
|
|
-
|
|
- fast_mix(fast_pool);
|
|
- add_interrupt_bench(cycles);
|
|
-
|
|
- if (unlikely(crng_init == 0)) {
|
|
- if ((fast_pool->count >= 64) &&
|
|
- crng_fast_load((char *) fast_pool->pool,
|
|
- sizeof(fast_pool->pool)) > 0) {
|
|
- fast_pool->count = 0;
|
|
- fast_pool->last = now;
|
|
+ if (orig < POOL_READY_BITS && new >= POOL_READY_BITS) {
|
|
+ crng_reseed(); /* Sets crng_init to CRNG_READY under base_crng.lock. */
|
|
+ process_random_ready_list();
|
|
+ wake_up_interruptible(&crng_init_wait);
|
|
+ kill_fasync(&fasync, SIGIO, POLL_IN);
|
|
+ pr_notice("crng init done\n");
|
|
+ if (urandom_warning.missed)
|
|
+ pr_notice("%d urandom warning(s) missed due to ratelimiting\n",
|
|
+ urandom_warning.missed);
|
|
+ } else if (orig < POOL_EARLY_BITS && new >= POOL_EARLY_BITS) {
|
|
+ spin_lock_irqsave(&base_crng.lock, flags);
|
|
+ /* Check if crng_init is CRNG_EMPTY, to avoid race with crng_reseed(). */
|
|
+ if (crng_init == CRNG_EMPTY) {
|
|
+ extract_entropy(base_crng.key, sizeof(base_crng.key));
|
|
+ crng_init = CRNG_EARLY;
|
|
}
|
|
- return;
|
|
- }
|
|
-
|
|
- if ((fast_pool->count < 64) &&
|
|
- !time_after(now, fast_pool->last + HZ))
|
|
- return;
|
|
-
|
|
- r = &input_pool;
|
|
- if (!spin_trylock(&r->lock))
|
|
- return;
|
|
-
|
|
- fast_pool->last = now;
|
|
- __mix_pool_bytes(r, &fast_pool->pool, sizeof(fast_pool->pool));
|
|
-
|
|
- /*
|
|
- * If we have architectural seed generator, produce a seed and
|
|
- * add it to the pool. For the sake of paranoia don't let the
|
|
- * architectural seed generator dominate the input from the
|
|
- * interrupt noise.
|
|
- */
|
|
- if (arch_get_random_seed_long(&seed)) {
|
|
- __mix_pool_bytes(r, &seed, sizeof(seed));
|
|
- credit = 1;
|
|
+ spin_unlock_irqrestore(&base_crng.lock, flags);
|
|
}
|
|
- spin_unlock(&r->lock);
|
|
-
|
|
- fast_pool->count = 0;
|
|
-
|
|
- /* award one bit for the contents of the fast pool */
|
|
- credit_entropy_bits(r, credit + 1);
|
|
}
|
|
-EXPORT_SYMBOL_GPL(add_interrupt_randomness);
|
|
|
|
-#ifdef CONFIG_BLOCK
|
|
-void add_disk_randomness(struct gendisk *disk)
|
|
-{
|
|
- if (!disk || !disk->random)
|
|
- return;
|
|
- /* first major is 1, so we get >= 0x200 here */
|
|
- add_timer_randomness(disk->random, 0x100 + disk_devt(disk));
|
|
- trace_add_disk_randomness(disk_devt(disk), ENTROPY_BITS(&input_pool));
|
|
-}
|
|
-EXPORT_SYMBOL_GPL(add_disk_randomness);
|
|
-#endif
|
|
|
|
-/*********************************************************************
|
|
+/**********************************************************************
|
|
*
|
|
- * Entropy extraction routines
|
|
+ * Entropy collection routines.
|
|
*
|
|
- *********************************************************************/
|
|
-
|
|
-/*
|
|
- * This utility inline function is responsible for transferring entropy
|
|
- * from the primary pool to the secondary extraction pool. We make
|
|
- * sure we pull enough for a 'catastrophic reseed'.
|
|
- */
|
|
-static void _xfer_secondary_pool(struct entropy_store *r, size_t nbytes);
|
|
-static void xfer_secondary_pool(struct entropy_store *r, size_t nbytes)
|
|
-{
|
|
- if (!r->pull ||
|
|
- r->entropy_count >= (nbytes << (ENTROPY_SHIFT + 3)) ||
|
|
- r->entropy_count > r->poolinfo->poolfracbits)
|
|
- return;
|
|
-
|
|
- _xfer_secondary_pool(r, nbytes);
|
|
-}
|
|
+ * The following exported functions are used for pushing entropy into
|
|
+ * the above entropy accumulation routines:
|
|
+ *
|
|
+ * void add_device_randomness(const void *buf, size_t len);
|
|
+ * void add_hwgenerator_randomness(const void *buf, size_t len, size_t entropy);
|
|
+ * void add_bootloader_randomness(const void *buf, size_t len);
|
|
+ * void add_interrupt_randomness(int irq);
|
|
+ * void add_input_randomness(unsigned int type, unsigned int code, unsigned int value);
|
|
+ * void add_disk_randomness(struct gendisk *disk);
|
|
+ *
|
|
+ * add_device_randomness() adds data to the input 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* credit 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_hwgenerator_randomness() is for true hardware RNGs, and will credit
|
|
+ * entropy as specified by the caller. If the entropy pool is full it will
|
|
+ * block until more entropy is needed.
|
|
+ *
|
|
+ * add_bootloader_randomness() is called by bootloader drivers, such as EFI
|
|
+ * and device tree, and credits its input depending on whether or not the
|
|
+ * configuration option CONFIG_RANDOM_TRUST_BOOTLOADER is set.
|
|
+ *
|
|
+ * 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 input pool roughly once a second or after 64
|
|
+ * interrupts, crediting 1 bit of entropy for whichever comes first.
|
|
+ *
|
|
+ * add_input_randomness() uses the input layer interrupt timing, as well
|
|
+ * as the event type information from the hardware.
|
|
+ *
|
|
+ * 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
|
|
+ * entropy pool. Note that high-speed solid state drives with very low
|
|
+ * seek times do not make for good sources of entropy, as their seek
|
|
+ * times are usually fairly consistent.
|
|
+ *
|
|
+ * The last two routines try to estimate how many bits of entropy
|
|
+ * to credit. They do this by keeping track of the first and second
|
|
+ * order deltas of the event timings.
|
|
+ *
|
|
+ **********************************************************************/
|
|
|
|
-static void _xfer_secondary_pool(struct entropy_store *r, size_t nbytes)
|
|
+static bool trust_cpu __initdata = IS_ENABLED(CONFIG_RANDOM_TRUST_CPU);
|
|
+static bool trust_bootloader __initdata = IS_ENABLED(CONFIG_RANDOM_TRUST_BOOTLOADER);
|
|
+static int __init parse_trust_cpu(char *arg)
|
|
{
|
|
- __u32 tmp[OUTPUT_POOL_WORDS];
|
|
-
|
|
- int bytes = nbytes;
|
|
-
|
|
- /* pull at least as much as a wakeup */
|
|
- bytes = max_t(int, bytes, random_read_wakeup_bits / 8);
|
|
- /* but never more than the buffer size */
|
|
- bytes = min_t(int, bytes, sizeof(tmp));
|
|
-
|
|
- trace_xfer_secondary_pool(r->name, bytes * 8, nbytes * 8,
|
|
- ENTROPY_BITS(r), ENTROPY_BITS(r->pull));
|
|
- bytes = extract_entropy(r->pull, tmp, bytes,
|
|
- random_read_wakeup_bits / 8, 0);
|
|
- mix_pool_bytes(r, tmp, bytes);
|
|
- credit_entropy_bits(r, bytes*8);
|
|
+ return kstrtobool(arg, &trust_cpu);
|
|
}
|
|
-
|
|
-/*
|
|
- * Used as a workqueue function so that when the input pool is getting
|
|
- * full, we can "spill over" some entropy to the output pools. That
|
|
- * way the output pools can store some of the excess entropy instead
|
|
- * of letting it go to waste.
|
|
- */
|
|
-static void push_to_pool(struct work_struct *work)
|
|
+static int __init parse_trust_bootloader(char *arg)
|
|
{
|
|
- struct entropy_store *r = container_of(work, struct entropy_store,
|
|
- push_work);
|
|
- BUG_ON(!r);
|
|
- _xfer_secondary_pool(r, random_read_wakeup_bits/8);
|
|
- trace_push_to_pool(r->name, r->entropy_count >> ENTROPY_SHIFT,
|
|
- r->pull->entropy_count >> ENTROPY_SHIFT);
|
|
+ return kstrtobool(arg, &trust_bootloader);
|
|
}
|
|
+early_param("random.trust_cpu", parse_trust_cpu);
|
|
+early_param("random.trust_bootloader", parse_trust_bootloader);
|
|
|
|
/*
|
|
- * This function decides how many bytes to actually take from the
|
|
- * given pool, and also debits the entropy count accordingly.
|
|
+ * The first collection of entropy occurs at system boot while interrupts
|
|
+ * are still turned off. Here we push in latent entropy, RDSEED, a timestamp,
|
|
+ * utsname(), and the command line. Depending on the above configuration knob,
|
|
+ * RDSEED may be considered sufficient for initialization. Note that much
|
|
+ * earlier setup may already have pushed entropy into the input pool by the
|
|
+ * time we get here.
|
|
*/
|
|
-static size_t account(struct entropy_store *r, size_t nbytes, int min,
|
|
- int reserved)
|
|
+int __init random_init(const char *command_line)
|
|
{
|
|
- int entropy_count, orig, have_bytes;
|
|
- size_t ibytes, nfrac;
|
|
-
|
|
- BUG_ON(r->entropy_count > r->poolinfo->poolfracbits);
|
|
-
|
|
- /* Can we pull enough? */
|
|
-retry:
|
|
- entropy_count = orig = READ_ONCE(r->entropy_count);
|
|
- ibytes = nbytes;
|
|
- /* never pull more than available */
|
|
- have_bytes = entropy_count >> (ENTROPY_SHIFT + 3);
|
|
-
|
|
- if ((have_bytes -= reserved) < 0)
|
|
- have_bytes = 0;
|
|
- ibytes = min_t(size_t, ibytes, have_bytes);
|
|
- if (ibytes < min)
|
|
- ibytes = 0;
|
|
-
|
|
- if (unlikely(entropy_count < 0)) {
|
|
- pr_warn("random: negative entropy count: pool %s count %d\n",
|
|
- r->name, entropy_count);
|
|
- WARN_ON(1);
|
|
- entropy_count = 0;
|
|
- }
|
|
- nfrac = ibytes << (ENTROPY_SHIFT + 3);
|
|
- if ((size_t) entropy_count > nfrac)
|
|
- entropy_count -= nfrac;
|
|
- else
|
|
- entropy_count = 0;
|
|
+ ktime_t now = ktime_get_real();
|
|
+ unsigned int i, arch_bits;
|
|
+ unsigned long entropy;
|
|
|
|
- if (cmpxchg(&r->entropy_count, orig, entropy_count) != orig)
|
|
- goto retry;
|
|
+#if defined(LATENT_ENTROPY_PLUGIN)
|
|
+ static const u8 compiletime_seed[BLAKE2S_BLOCK_SIZE] __initconst __latent_entropy;
|
|
+ _mix_pool_bytes(compiletime_seed, sizeof(compiletime_seed));
|
|
+#endif
|
|
|
|
- trace_debit_entropy(r->name, 8 * ibytes);
|
|
- if (ibytes &&
|
|
- (r->entropy_count >> ENTROPY_SHIFT) < random_write_wakeup_bits) {
|
|
- wake_up_interruptible(&random_write_wait);
|
|
- kill_fasync(&fasync, SIGIO, POLL_OUT);
|
|
+ for (i = 0, arch_bits = BLAKE2S_BLOCK_SIZE * 8;
|
|
+ i < BLAKE2S_BLOCK_SIZE; i += sizeof(entropy)) {
|
|
+ if (!arch_get_random_seed_long_early(&entropy) &&
|
|
+ !arch_get_random_long_early(&entropy)) {
|
|
+ entropy = random_get_entropy();
|
|
+ arch_bits -= sizeof(entropy) * 8;
|
|
+ }
|
|
+ _mix_pool_bytes(&entropy, sizeof(entropy));
|
|
}
|
|
+ _mix_pool_bytes(&now, sizeof(now));
|
|
+ _mix_pool_bytes(utsname(), sizeof(*(utsname())));
|
|
+ _mix_pool_bytes(command_line, strlen(command_line));
|
|
+ add_latent_entropy();
|
|
+
|
|
+ if (crng_ready())
|
|
+ crng_reseed();
|
|
+ else if (trust_cpu)
|
|
+ _credit_init_bits(arch_bits);
|
|
|
|
- return ibytes;
|
|
+ return 0;
|
|
}
|
|
|
|
/*
|
|
- * This function does the actual extraction for extract_entropy and
|
|
- * extract_entropy_user.
|
|
+ * Add device- or boot-specific data to the input pool to help
|
|
+ * initialize it.
|
|
*
|
|
- * Note: we assume that .poolwords is a multiple of 16 words.
|
|
+ * None of this adds any entropy; it is meant to avoid the problem of
|
|
+ * the entropy pool having similar initial state across largely
|
|
+ * identical devices.
|
|
*/
|
|
-static void extract_buf(struct entropy_store *r, __u8 *out)
|
|
-{
|
|
- int i;
|
|
- union {
|
|
- __u32 w[5];
|
|
- unsigned long l[LONGS(20)];
|
|
- } hash;
|
|
- __u32 workspace[SHA_WORKSPACE_WORDS];
|
|
- unsigned long flags;
|
|
-
|
|
- /*
|
|
- * If we have an architectural hardware random number
|
|
- * generator, use it for SHA's initial vector
|
|
- */
|
|
- sha_init(hash.w);
|
|
- for (i = 0; i < LONGS(20); i++) {
|
|
- unsigned long v;
|
|
- if (!arch_get_random_long(&v))
|
|
- break;
|
|
- hash.l[i] = v;
|
|
- }
|
|
-
|
|
- /* Generate a hash across the pool, 16 words (512 bits) at a time */
|
|
- spin_lock_irqsave(&r->lock, flags);
|
|
- for (i = 0; i < r->poolinfo->poolwords; i += 16)
|
|
- sha_transform(hash.w, (__u8 *)(r->pool + i), workspace);
|
|
-
|
|
- /*
|
|
- * We mix the hash back into the pool to prevent backtracking
|
|
- * attacks (where the attacker knows the state of the pool
|
|
- * plus the current outputs, and attempts to find previous
|
|
- * ouputs), unless the hash function can be inverted. By
|
|
- * mixing at least a SHA1 worth of hash data back, we make
|
|
- * brute-forcing the feedback as hard as brute-forcing the
|
|
- * hash.
|
|
- */
|
|
- __mix_pool_bytes(r, hash.w, sizeof(hash.w));
|
|
- spin_unlock_irqrestore(&r->lock, flags);
|
|
-
|
|
- memzero_explicit(workspace, sizeof(workspace));
|
|
-
|
|
- /*
|
|
- * In case the hash function has some recognizable output
|
|
- * pattern, we fold it in half. Thus, we always feed back
|
|
- * twice as much data as we output.
|
|
- */
|
|
- hash.w[0] ^= hash.w[3];
|
|
- hash.w[1] ^= hash.w[4];
|
|
- hash.w[2] ^= rol32(hash.w[2], 16);
|
|
-
|
|
- memcpy(out, &hash, EXTRACT_SIZE);
|
|
- memzero_explicit(&hash, sizeof(hash));
|
|
-}
|
|
-
|
|
-static ssize_t _extract_entropy(struct entropy_store *r, void *buf,
|
|
- size_t nbytes, int fips)
|
|
+void add_device_randomness(const void *buf, size_t len)
|
|
{
|
|
- ssize_t ret = 0, i;
|
|
- __u8 tmp[EXTRACT_SIZE];
|
|
+ unsigned long entropy = random_get_entropy();
|
|
unsigned long flags;
|
|
|
|
- while (nbytes) {
|
|
- extract_buf(r, tmp);
|
|
-
|
|
- if (fips) {
|
|
- spin_lock_irqsave(&r->lock, flags);
|
|
- if (!memcmp(tmp, r->last_data, EXTRACT_SIZE))
|
|
- panic("Hardware RNG duplicated output!\n");
|
|
- memcpy(r->last_data, tmp, EXTRACT_SIZE);
|
|
- spin_unlock_irqrestore(&r->lock, flags);
|
|
- }
|
|
- i = min_t(int, nbytes, EXTRACT_SIZE);
|
|
- memcpy(buf, tmp, i);
|
|
- nbytes -= i;
|
|
- buf += i;
|
|
- ret += i;
|
|
- }
|
|
-
|
|
- /* Wipe data just returned from memory */
|
|
- memzero_explicit(tmp, sizeof(tmp));
|
|
-
|
|
- return ret;
|
|
+ spin_lock_irqsave(&input_pool.lock, flags);
|
|
+ _mix_pool_bytes(&entropy, sizeof(entropy));
|
|
+ _mix_pool_bytes(buf, len);
|
|
+ spin_unlock_irqrestore(&input_pool.lock, flags);
|
|
}
|
|
+EXPORT_SYMBOL(add_device_randomness);
|
|
|
|
/*
|
|
- * This function extracts randomness from the "entropy pool", and
|
|
- * returns it in a buffer.
|
|
- *
|
|
- * The min parameter specifies the minimum amount we can pull before
|
|
- * failing to avoid races that defeat catastrophic reseeding while the
|
|
- * reserved parameter indicates how much entropy we must leave in the
|
|
- * pool after each pull to avoid starving other readers.
|
|
+ * Interface for in-kernel drivers of true hardware RNGs.
|
|
+ * Those devices may produce endless random bits and will be throttled
|
|
+ * when our pool is full.
|
|
*/
|
|
-static ssize_t extract_entropy(struct entropy_store *r, void *buf,
|
|
- size_t nbytes, int min, int reserved)
|
|
+void add_hwgenerator_randomness(const void *buf, size_t len, size_t entropy)
|
|
{
|
|
- __u8 tmp[EXTRACT_SIZE];
|
|
- unsigned long flags;
|
|
+ mix_pool_bytes(buf, len);
|
|
+ credit_init_bits(entropy);
|
|
|
|
- /* if last_data isn't primed, we need EXTRACT_SIZE extra bytes */
|
|
- if (fips_enabled) {
|
|
- spin_lock_irqsave(&r->lock, flags);
|
|
- if (!r->last_data_init) {
|
|
- r->last_data_init = 1;
|
|
- spin_unlock_irqrestore(&r->lock, flags);
|
|
- trace_extract_entropy(r->name, EXTRACT_SIZE,
|
|
- ENTROPY_BITS(r), _RET_IP_);
|
|
- xfer_secondary_pool(r, EXTRACT_SIZE);
|
|
- extract_buf(r, tmp);
|
|
- spin_lock_irqsave(&r->lock, flags);
|
|
- memcpy(r->last_data, tmp, EXTRACT_SIZE);
|
|
- }
|
|
- spin_unlock_irqrestore(&r->lock, flags);
|
|
- }
|
|
-
|
|
- trace_extract_entropy(r->name, nbytes, ENTROPY_BITS(r), _RET_IP_);
|
|
- xfer_secondary_pool(r, nbytes);
|
|
- nbytes = account(r, nbytes, min, reserved);
|
|
-
|
|
- return _extract_entropy(r, buf, nbytes, fips_enabled);
|
|
+ /*
|
|
+ * Throttle writing to once every CRNG_RESEED_INTERVAL, unless
|
|
+ * we're not yet initialized.
|
|
+ */
|
|
+ if (!kthread_should_stop() && crng_ready())
|
|
+ schedule_timeout_interruptible(CRNG_RESEED_INTERVAL);
|
|
}
|
|
+EXPORT_SYMBOL_GPL(add_hwgenerator_randomness);
|
|
|
|
/*
|
|
- * This function extracts randomness from the "entropy pool", and
|
|
- * returns it in a userspace buffer.
|
|
+ * Handle random seed passed by bootloader, and credit it if
|
|
+ * CONFIG_RANDOM_TRUST_BOOTLOADER is set.
|
|
*/
|
|
-static ssize_t extract_entropy_user(struct entropy_store *r, void __user *buf,
|
|
- size_t nbytes)
|
|
+void __init add_bootloader_randomness(const void *buf, size_t len)
|
|
{
|
|
- ssize_t ret = 0, i;
|
|
- __u8 tmp[EXTRACT_SIZE];
|
|
- int large_request = (nbytes > 256);
|
|
-
|
|
- trace_extract_entropy_user(r->name, nbytes, ENTROPY_BITS(r), _RET_IP_);
|
|
- if (!r->initialized && r->pull) {
|
|
- xfer_secondary_pool(r, ENTROPY_BITS(r->pull)/8);
|
|
- if (!r->initialized)
|
|
- return 0;
|
|
- }
|
|
- xfer_secondary_pool(r, nbytes);
|
|
- nbytes = account(r, nbytes, 0, 0);
|
|
-
|
|
- while (nbytes) {
|
|
- if (large_request && need_resched()) {
|
|
- if (signal_pending(current)) {
|
|
- if (ret == 0)
|
|
- ret = -ERESTARTSYS;
|
|
- break;
|
|
- }
|
|
- schedule();
|
|
- }
|
|
-
|
|
- extract_buf(r, tmp);
|
|
- i = min_t(int, nbytes, EXTRACT_SIZE);
|
|
- if (copy_to_user(buf, tmp, i)) {
|
|
- ret = -EFAULT;
|
|
- break;
|
|
- }
|
|
-
|
|
- nbytes -= i;
|
|
- buf += i;
|
|
- ret += i;
|
|
- }
|
|
-
|
|
- /* Wipe data just returned from memory */
|
|
- memzero_explicit(tmp, sizeof(tmp));
|
|
-
|
|
- return ret;
|
|
+ mix_pool_bytes(buf, len);
|
|
+ if (trust_bootloader)
|
|
+ credit_init_bits(len * 8);
|
|
}
|
|
|
|
-#define warn_unseeded_randomness(previous) \
|
|
- _warn_unseeded_randomness(__func__, (void *) _RET_IP_, (previous))
|
|
+struct fast_pool {
|
|
+ struct work_struct mix;
|
|
+ unsigned long pool[4];
|
|
+ unsigned long last;
|
|
+ unsigned int count;
|
|
+};
|
|
|
|
-static void _warn_unseeded_randomness(const char *func_name, void *caller,
|
|
- void **previous)
|
|
-{
|
|
-#ifdef CONFIG_WARN_ALL_UNSEEDED_RANDOM
|
|
- const bool print_once = false;
|
|
+static DEFINE_PER_CPU(struct fast_pool, irq_randomness) = {
|
|
+#ifdef CONFIG_64BIT
|
|
+#define FASTMIX_PERM SIPHASH_PERMUTATION
|
|
+ .pool = { SIPHASH_CONST_0, SIPHASH_CONST_1, SIPHASH_CONST_2, SIPHASH_CONST_3 }
|
|
#else
|
|
- static bool print_once __read_mostly;
|
|
+#define FASTMIX_PERM HSIPHASH_PERMUTATION
|
|
+ .pool = { HSIPHASH_CONST_0, HSIPHASH_CONST_1, HSIPHASH_CONST_2, HSIPHASH_CONST_3 }
|
|
#endif
|
|
-
|
|
- if (print_once ||
|
|
- crng_ready() ||
|
|
- (previous && (caller == READ_ONCE(*previous))))
|
|
- return;
|
|
- WRITE_ONCE(*previous, caller);
|
|
-#ifndef CONFIG_WARN_ALL_UNSEEDED_RANDOM
|
|
- print_once = true;
|
|
-#endif
|
|
- if (__ratelimit(&unseeded_warning))
|
|
- printk_deferred(KERN_NOTICE "random: %s called from %pS "
|
|
- "with crng_init=%d\n", func_name, caller,
|
|
- crng_init);
|
|
-}
|
|
+};
|
|
|
|
/*
|
|
- * This function is the exported kernel interface. It returns some
|
|
- * number of good random numbers, suitable for key generation, seeding
|
|
- * TCP sequence numbers, etc. It does not rely on the hardware random
|
|
- * number generator. For random bytes direct from the hardware RNG
|
|
- * (when available), use get_random_bytes_arch(). In order to ensure
|
|
- * that the randomness provided by this function is okay, the function
|
|
- * wait_for_random_bytes() should be called and return 0 at least once
|
|
- * at any point prior.
|
|
+ * This is [Half]SipHash-1-x, starting from an empty key. Because
|
|
+ * the key is fixed, it assumes that its inputs are non-malicious,
|
|
+ * and therefore this has no security on its own. s represents the
|
|
+ * four-word SipHash state, while v represents a two-word input.
|
|
*/
|
|
-static void _get_random_bytes(void *buf, int nbytes)
|
|
-{
|
|
- __u8 tmp[CHACHA_BLOCK_SIZE] __aligned(4);
|
|
-
|
|
- trace_get_random_bytes(nbytes, _RET_IP_);
|
|
-
|
|
- while (nbytes >= CHACHA_BLOCK_SIZE) {
|
|
- extract_crng(buf);
|
|
- buf += CHACHA_BLOCK_SIZE;
|
|
- nbytes -= CHACHA_BLOCK_SIZE;
|
|
- }
|
|
-
|
|
- if (nbytes > 0) {
|
|
- extract_crng(tmp);
|
|
- memcpy(buf, tmp, nbytes);
|
|
- crng_backtrack_protect(tmp, nbytes);
|
|
- } else
|
|
- crng_backtrack_protect(tmp, CHACHA_BLOCK_SIZE);
|
|
- memzero_explicit(tmp, sizeof(tmp));
|
|
-}
|
|
-
|
|
-void get_random_bytes(void *buf, int nbytes)
|
|
+static void fast_mix(unsigned long s[4], unsigned long v1, unsigned long v2)
|
|
{
|
|
- static void *previous;
|
|
-
|
|
- warn_unseeded_randomness(&previous);
|
|
- _get_random_bytes(buf, nbytes);
|
|
+ s[3] ^= v1;
|
|
+ FASTMIX_PERM(s[0], s[1], s[2], s[3]);
|
|
+ s[0] ^= v1;
|
|
+ s[3] ^= v2;
|
|
+ FASTMIX_PERM(s[0], s[1], s[2], s[3]);
|
|
+ s[0] ^= v2;
|
|
}
|
|
-EXPORT_SYMBOL(get_random_bytes);
|
|
-
|
|
|
|
+#ifdef CONFIG_SMP
|
|
/*
|
|
- * Each time the timer fires, we expect that we got an unpredictable
|
|
- * jump in the cycle counter. Even if the timer is running on another
|
|
- * CPU, the timer activity will be touching the stack of the CPU that is
|
|
- * generating entropy..
|
|
- *
|
|
- * Note that we don't re-arm the timer in the timer itself - we are
|
|
- * happy to be scheduled away, since that just makes the load more
|
|
- * complex, but we do not want the timer to keep ticking unless the
|
|
- * entropy loop is running.
|
|
- *
|
|
- * So the re-arming always happens in the entropy loop itself.
|
|
+ * This function is called when the CPU has just come online, with
|
|
+ * entry CPUHP_AP_RANDOM_ONLINE, just after CPUHP_AP_WORKQUEUE_ONLINE.
|
|
*/
|
|
-static void entropy_timer(struct timer_list *t)
|
|
+int __cold random_online_cpu(unsigned int cpu)
|
|
{
|
|
- credit_entropy_bits(&input_pool, 1);
|
|
+ /*
|
|
+ * During CPU shutdown and before CPU onlining, add_interrupt_
|
|
+ * randomness() may schedule mix_interrupt_randomness(), and
|
|
+ * set the MIX_INFLIGHT flag. However, because the worker can
|
|
+ * be scheduled on a different CPU during this period, that
|
|
+ * flag will never be cleared. For that reason, we zero out
|
|
+ * the flag here, which runs just after workqueues are onlined
|
|
+ * for the CPU again. This also has the effect of setting the
|
|
+ * irq randomness count to zero so that new accumulated irqs
|
|
+ * are fresh.
|
|
+ */
|
|
+ per_cpu_ptr(&irq_randomness, cpu)->count = 0;
|
|
+ return 0;
|
|
}
|
|
+#endif
|
|
|
|
-/*
|
|
- * If we have an actual cycle counter, see if we can
|
|
- * generate enough entropy with timing noise
|
|
- */
|
|
-static void try_to_generate_entropy(void)
|
|
+static void mix_interrupt_randomness(struct work_struct *work)
|
|
{
|
|
- struct {
|
|
- unsigned long now;
|
|
- struct timer_list timer;
|
|
- } stack;
|
|
-
|
|
- stack.now = random_get_entropy();
|
|
+ struct fast_pool *fast_pool = container_of(work, struct fast_pool, mix);
|
|
+ /*
|
|
+ * The size of the copied stack pool is explicitly 2 longs so that we
|
|
+ * only ever ingest half of the siphash output each time, retaining
|
|
+ * the other half as the next "key" that carries over. The entropy is
|
|
+ * supposed to be sufficiently dispersed between bits so on average
|
|
+ * we don't wind up "losing" some.
|
|
+ */
|
|
+ unsigned long pool[2];
|
|
+ unsigned int count;
|
|
|
|
- /* Slow counter - or none. Don't even bother */
|
|
- if (stack.now == random_get_entropy())
|
|
+ /* Check to see if we're running on the wrong CPU due to hotplug. */
|
|
+ local_irq_disable();
|
|
+ if (fast_pool != this_cpu_ptr(&irq_randomness)) {
|
|
+ local_irq_enable();
|
|
return;
|
|
-
|
|
- timer_setup_on_stack(&stack.timer, entropy_timer, 0);
|
|
- while (!crng_ready()) {
|
|
- if (!timer_pending(&stack.timer))
|
|
- mod_timer(&stack.timer, jiffies+1);
|
|
- mix_pool_bytes(&input_pool, &stack.now, sizeof(stack.now));
|
|
- schedule();
|
|
- stack.now = random_get_entropy();
|
|
}
|
|
|
|
- del_timer_sync(&stack.timer);
|
|
- destroy_timer_on_stack(&stack.timer);
|
|
- mix_pool_bytes(&input_pool, &stack.now, sizeof(stack.now));
|
|
-}
|
|
-
|
|
-/*
|
|
- * Wait for the urandom pool to be seeded and thus guaranteed to supply
|
|
- * cryptographically secure random numbers. This applies to: the /dev/urandom
|
|
- * device, the get_random_bytes function, and the get_random_{u32,u64,int,long}
|
|
- * family of functions. Using any of these functions without first calling
|
|
- * this function forfeits the guarantee of security.
|
|
- *
|
|
- * Returns: 0 if the urandom pool has been seeded.
|
|
- * -ERESTARTSYS if the function was interrupted by a signal.
|
|
- */
|
|
-int wait_for_random_bytes(void)
|
|
-{
|
|
- if (likely(crng_ready()))
|
|
- return 0;
|
|
-
|
|
- do {
|
|
- int ret;
|
|
- ret = wait_event_interruptible_timeout(crng_init_wait, crng_ready(), HZ);
|
|
- if (ret)
|
|
- return ret > 0 ? 0 : ret;
|
|
-
|
|
- try_to_generate_entropy();
|
|
- } while (!crng_ready());
|
|
+ /*
|
|
+ * Copy the pool to the stack so that the mixer always has a
|
|
+ * consistent view, before we reenable irqs again.
|
|
+ */
|
|
+ memcpy(pool, fast_pool->pool, sizeof(pool));
|
|
+ count = fast_pool->count;
|
|
+ fast_pool->count = 0;
|
|
+ fast_pool->last = jiffies;
|
|
+ local_irq_enable();
|
|
|
|
- return 0;
|
|
-}
|
|
-EXPORT_SYMBOL(wait_for_random_bytes);
|
|
+ mix_pool_bytes(pool, sizeof(pool));
|
|
+ credit_init_bits(max(1u, (count & U16_MAX) / 64));
|
|
|
|
-/*
|
|
- * Returns whether or not the urandom pool has been seeded and thus guaranteed
|
|
- * to supply cryptographically secure random numbers. This applies to: the
|
|
- * /dev/urandom device, the get_random_bytes function, and the get_random_{u32,
|
|
- * ,u64,int,long} family of functions.
|
|
- *
|
|
- * Returns: true if the urandom pool has been seeded.
|
|
- * false if the urandom pool has not been seeded.
|
|
- */
|
|
-bool rng_is_initialized(void)
|
|
-{
|
|
- return crng_ready();
|
|
+ memzero_explicit(pool, sizeof(pool));
|
|
}
|
|
-EXPORT_SYMBOL(rng_is_initialized);
|
|
|
|
-/*
|
|
- * Add a callback function that will be invoked when the nonblocking
|
|
- * pool is initialised.
|
|
- *
|
|
- * returns: 0 if callback is successfully added
|
|
- * -EALREADY if pool is already initialised (callback not called)
|
|
- * -ENOENT if module for callback is not alive
|
|
- */
|
|
-int add_random_ready_callback(struct random_ready_callback *rdy)
|
|
+void add_interrupt_randomness(int irq)
|
|
{
|
|
- struct module *owner;
|
|
- unsigned long flags;
|
|
- int err = -EALREADY;
|
|
-
|
|
- if (crng_ready())
|
|
- return err;
|
|
-
|
|
- owner = rdy->owner;
|
|
- if (!try_module_get(owner))
|
|
- return -ENOENT;
|
|
-
|
|
- spin_lock_irqsave(&random_ready_list_lock, flags);
|
|
- if (crng_ready())
|
|
- goto out;
|
|
-
|
|
- owner = NULL;
|
|
+ enum { MIX_INFLIGHT = 1U << 31 };
|
|
+ unsigned long entropy = random_get_entropy();
|
|
+ struct fast_pool *fast_pool = this_cpu_ptr(&irq_randomness);
|
|
+ struct pt_regs *regs = get_irq_regs();
|
|
+ unsigned int new_count;
|
|
|
|
- list_add(&rdy->list, &random_ready_list);
|
|
- err = 0;
|
|
+ fast_mix(fast_pool->pool, entropy,
|
|
+ (regs ? instruction_pointer(regs) : _RET_IP_) ^ swab(irq));
|
|
+ new_count = ++fast_pool->count;
|
|
|
|
-out:
|
|
- spin_unlock_irqrestore(&random_ready_list_lock, flags);
|
|
+ if (new_count & MIX_INFLIGHT)
|
|
+ return;
|
|
|
|
- module_put(owner);
|
|
+ if (new_count < 64 && !time_is_before_jiffies(fast_pool->last + HZ))
|
|
+ return;
|
|
|
|
- return err;
|
|
+ if (unlikely(!fast_pool->mix.func))
|
|
+ INIT_WORK(&fast_pool->mix, mix_interrupt_randomness);
|
|
+ fast_pool->count |= MIX_INFLIGHT;
|
|
+ queue_work_on(raw_smp_processor_id(), system_highpri_wq, &fast_pool->mix);
|
|
}
|
|
-EXPORT_SYMBOL(add_random_ready_callback);
|
|
+EXPORT_SYMBOL_GPL(add_interrupt_randomness);
|
|
+
|
|
+/* There is one of these per entropy source */
|
|
+struct timer_rand_state {
|
|
+ unsigned long last_time;
|
|
+ long last_delta, last_delta2;
|
|
+};
|
|
|
|
/*
|
|
- * Delete a previously registered readiness callback function.
|
|
+ * This function adds entropy to the entropy "pool" by using timing
|
|
+ * delays. It uses the timer_rand_state structure to make an estimate
|
|
+ * of how many bits of entropy this call has added to the pool. The
|
|
+ * value "num" is also added to the pool; it should somehow describe
|
|
+ * the type of event that just happened.
|
|
*/
|
|
-void del_random_ready_callback(struct random_ready_callback *rdy)
|
|
+static void add_timer_randomness(struct timer_rand_state *state, unsigned int num)
|
|
{
|
|
- unsigned long flags;
|
|
- struct module *owner = NULL;
|
|
+ unsigned long entropy = random_get_entropy(), now = jiffies, flags;
|
|
+ long delta, delta2, delta3;
|
|
+ unsigned int bits;
|
|
|
|
- spin_lock_irqsave(&random_ready_list_lock, flags);
|
|
- if (!list_empty(&rdy->list)) {
|
|
- list_del_init(&rdy->list);
|
|
- owner = rdy->owner;
|
|
+ /*
|
|
+ * If we're in a hard IRQ, add_interrupt_randomness() will be called
|
|
+ * sometime after, so mix into the fast pool.
|
|
+ */
|
|
+ if (in_irq()) {
|
|
+ fast_mix(this_cpu_ptr(&irq_randomness)->pool, entropy, num);
|
|
+ } else {
|
|
+ spin_lock_irqsave(&input_pool.lock, flags);
|
|
+ _mix_pool_bytes(&entropy, sizeof(entropy));
|
|
+ _mix_pool_bytes(&num, sizeof(num));
|
|
+ spin_unlock_irqrestore(&input_pool.lock, flags);
|
|
}
|
|
- spin_unlock_irqrestore(&random_ready_list_lock, flags);
|
|
|
|
- module_put(owner);
|
|
-}
|
|
-EXPORT_SYMBOL(del_random_ready_callback);
|
|
+ if (crng_ready())
|
|
+ return;
|
|
+
|
|
+ /*
|
|
+ * Calculate number of bits of randomness we probably added.
|
|
+ * We take into account the first, second and third-order deltas
|
|
+ * in order to make our estimate.
|
|
+ */
|
|
+ delta = now - READ_ONCE(state->last_time);
|
|
+ WRITE_ONCE(state->last_time, now);
|
|
|
|
-/*
|
|
- * 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.
|
|
- *
|
|
- * Return number of bytes filled in.
|
|
- */
|
|
-int __must_check get_random_bytes_arch(void *buf, int nbytes)
|
|
-{
|
|
- int left = nbytes;
|
|
- char *p = buf;
|
|
+ delta2 = delta - READ_ONCE(state->last_delta);
|
|
+ WRITE_ONCE(state->last_delta, delta);
|
|
|
|
- trace_get_random_bytes_arch(left, _RET_IP_);
|
|
- while (left) {
|
|
- unsigned long v;
|
|
- int chunk = min_t(int, left, sizeof(unsigned long));
|
|
+ delta3 = delta2 - READ_ONCE(state->last_delta2);
|
|
+ WRITE_ONCE(state->last_delta2, delta2);
|
|
|
|
- if (!arch_get_random_long(&v))
|
|
- break;
|
|
+ if (delta < 0)
|
|
+ delta = -delta;
|
|
+ if (delta2 < 0)
|
|
+ delta2 = -delta2;
|
|
+ if (delta3 < 0)
|
|
+ delta3 = -delta3;
|
|
+ if (delta > delta2)
|
|
+ delta = delta2;
|
|
+ if (delta > delta3)
|
|
+ delta = delta3;
|
|
|
|
- memcpy(p, &v, chunk);
|
|
- p += chunk;
|
|
- left -= chunk;
|
|
- }
|
|
+ /*
|
|
+ * delta is now minimum absolute delta. Round down by 1 bit
|
|
+ * on general principles, and limit entropy estimate to 11 bits.
|
|
+ */
|
|
+ bits = min(fls(delta >> 1), 11);
|
|
|
|
- return nbytes - left;
|
|
+ /*
|
|
+ * As mentioned above, if we're in a hard IRQ, add_interrupt_randomness()
|
|
+ * will run after this, which uses a different crediting scheme of 1 bit
|
|
+ * per every 64 interrupts. In order to let that function do accounting
|
|
+ * close to the one in this function, we credit a full 64/64 bit per bit,
|
|
+ * and then subtract one to account for the extra one added.
|
|
+ */
|
|
+ if (in_irq())
|
|
+ this_cpu_ptr(&irq_randomness)->count += max(1u, bits * 64) - 1;
|
|
+ else
|
|
+ _credit_init_bits(bits);
|
|
}
|
|
-EXPORT_SYMBOL(get_random_bytes_arch);
|
|
|
|
-/*
|
|
- * init_std_data - initialize pool with system data
|
|
- *
|
|
- * @r: pool to initialize
|
|
- *
|
|
- * This function clears the pool's entropy count and mixes some system
|
|
- * data into the pool to prepare it for use. The pool is not cleared
|
|
- * as that can only decrease the entropy in the pool.
|
|
- */
|
|
-static void __init init_std_data(struct entropy_store *r)
|
|
+void add_input_randomness(unsigned int type, unsigned int code, unsigned int value)
|
|
{
|
|
- int i;
|
|
- ktime_t now = ktime_get_real();
|
|
- unsigned long rv;
|
|
-
|
|
- r->last_pulled = jiffies;
|
|
- mix_pool_bytes(r, &now, sizeof(now));
|
|
- for (i = r->poolinfo->poolbytes; i > 0; i -= sizeof(rv)) {
|
|
- if (!arch_get_random_seed_long(&rv) &&
|
|
- !arch_get_random_long(&rv))
|
|
- rv = random_get_entropy();
|
|
- mix_pool_bytes(r, &rv, sizeof(rv));
|
|
- }
|
|
- mix_pool_bytes(r, utsname(), sizeof(*(utsname())));
|
|
+ static unsigned char last_value;
|
|
+ static struct timer_rand_state input_timer_state = { INITIAL_JIFFIES };
|
|
+
|
|
+ /* Ignore autorepeat and the like. */
|
|
+ if (value == last_value)
|
|
+ return;
|
|
+
|
|
+ last_value = value;
|
|
+ add_timer_randomness(&input_timer_state,
|
|
+ (type << 4) ^ code ^ (code >> 4) ^ value);
|
|
}
|
|
+EXPORT_SYMBOL_GPL(add_input_randomness);
|
|
|
|
-/*
|
|
- * 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.
|
|
- */
|
|
-int __init rand_initialize(void)
|
|
+#ifdef CONFIG_BLOCK
|
|
+void add_disk_randomness(struct gendisk *disk)
|
|
{
|
|
- init_std_data(&input_pool);
|
|
- init_std_data(&blocking_pool);
|
|
- if (crng_need_final_init)
|
|
- crng_finalize_init(&primary_crng);
|
|
- crng_initialize(&primary_crng);
|
|
- crng_global_init_time = jiffies;
|
|
- if (ratelimit_disable) {
|
|
- urandom_warning.interval = 0;
|
|
- unseeded_warning.interval = 0;
|
|
- }
|
|
- return 0;
|
|
+ if (!disk || !disk->random)
|
|
+ return;
|
|
+ /* First major is 1, so we get >= 0x200 here. */
|
|
+ add_timer_randomness(disk->random, 0x100 + disk_devt(disk));
|
|
}
|
|
+EXPORT_SYMBOL_GPL(add_disk_randomness);
|
|
|
|
-#ifdef CONFIG_BLOCK
|
|
-void rand_initialize_disk(struct gendisk *disk)
|
|
+void __cold rand_initialize_disk(struct gendisk *disk)
|
|
{
|
|
struct timer_rand_state *state;
|
|
|
|
@@ -2006,134 +1126,189 @@ void rand_initialize_disk(struct gendisk *disk)
|
|
}
|
|
#endif
|
|
|
|
-static ssize_t
|
|
-_random_read(int nonblock, char __user *buf, size_t nbytes)
|
|
+/*
|
|
+ * Each time the timer fires, we expect that we got an unpredictable
|
|
+ * jump in the cycle counter. Even if the timer is running on another
|
|
+ * CPU, the timer activity will be touching the stack of the CPU that is
|
|
+ * generating entropy..
|
|
+ *
|
|
+ * Note that we don't re-arm the timer in the timer itself - we are
|
|
+ * happy to be scheduled away, since that just makes the load more
|
|
+ * complex, but we do not want the timer to keep ticking unless the
|
|
+ * entropy loop is running.
|
|
+ *
|
|
+ * So the re-arming always happens in the entropy loop itself.
|
|
+ */
|
|
+static void __cold entropy_timer(struct timer_list *t)
|
|
+{
|
|
+ credit_init_bits(1);
|
|
+}
|
|
+
|
|
+/*
|
|
+ * If we have an actual cycle counter, see if we can
|
|
+ * generate enough entropy with timing noise
|
|
+ */
|
|
+static void __cold try_to_generate_entropy(void)
|
|
{
|
|
- ssize_t n;
|
|
+ struct {
|
|
+ unsigned long entropy;
|
|
+ struct timer_list timer;
|
|
+ } stack;
|
|
|
|
- if (nbytes == 0)
|
|
- return 0;
|
|
+ stack.entropy = random_get_entropy();
|
|
|
|
- nbytes = min_t(size_t, nbytes, SEC_XFER_SIZE);
|
|
- while (1) {
|
|
- n = extract_entropy_user(&blocking_pool, buf, nbytes);
|
|
- if (n < 0)
|
|
- return n;
|
|
- trace_random_read(n*8, (nbytes-n)*8,
|
|
- ENTROPY_BITS(&blocking_pool),
|
|
- ENTROPY_BITS(&input_pool));
|
|
- if (n > 0)
|
|
- return n;
|
|
-
|
|
- /* Pool is (near) empty. Maybe wait and retry. */
|
|
- if (nonblock)
|
|
- return -EAGAIN;
|
|
+ /* Slow counter - or none. Don't even bother */
|
|
+ if (stack.entropy == random_get_entropy())
|
|
+ return;
|
|
|
|
- wait_event_interruptible(random_read_wait,
|
|
- blocking_pool.initialized &&
|
|
- (ENTROPY_BITS(&input_pool) >= random_read_wakeup_bits));
|
|
- if (signal_pending(current))
|
|
- return -ERESTARTSYS;
|
|
+ timer_setup_on_stack(&stack.timer, entropy_timer, 0);
|
|
+ while (!crng_ready() && !signal_pending(current)) {
|
|
+ if (!timer_pending(&stack.timer))
|
|
+ mod_timer(&stack.timer, jiffies + 1);
|
|
+ mix_pool_bytes(&stack.entropy, sizeof(stack.entropy));
|
|
+ schedule();
|
|
+ stack.entropy = random_get_entropy();
|
|
}
|
|
-}
|
|
|
|
-static ssize_t
|
|
-random_read(struct file *file, char __user *buf, size_t nbytes, loff_t *ppos)
|
|
-{
|
|
- return _random_read(file->f_flags & O_NONBLOCK, buf, nbytes);
|
|
+ del_timer_sync(&stack.timer);
|
|
+ destroy_timer_on_stack(&stack.timer);
|
|
+ mix_pool_bytes(&stack.entropy, sizeof(stack.entropy));
|
|
}
|
|
|
|
-static ssize_t
|
|
-urandom_read(struct file *file, char __user *buf, size_t nbytes, loff_t *ppos)
|
|
+
|
|
+/**********************************************************************
|
|
+ *
|
|
+ * Userspace reader/writer interfaces.
|
|
+ *
|
|
+ * getrandom(2) is the primary modern interface into the RNG and should
|
|
+ * be used in preference to anything else.
|
|
+ *
|
|
+ * Reading from /dev/random has the same functionality as calling
|
|
+ * getrandom(2) with flags=0. In earlier versions, however, it had
|
|
+ * vastly different semantics and should therefore be avoided, to
|
|
+ * prevent backwards compatibility issues.
|
|
+ *
|
|
+ * Reading from /dev/urandom has the same functionality as calling
|
|
+ * getrandom(2) with flags=GRND_INSECURE. Because it does not block
|
|
+ * waiting for the RNG to be ready, it should not be used.
|
|
+ *
|
|
+ * Writing to either /dev/random or /dev/urandom adds entropy to
|
|
+ * the input pool but does not credit it.
|
|
+ *
|
|
+ * Polling on /dev/random indicates when the RNG is initialized, on
|
|
+ * the read side, and when it wants new entropy, on the write side.
|
|
+ *
|
|
+ * Both /dev/random and /dev/urandom have the same set of ioctls for
|
|
+ * adding entropy, getting the entropy count, zeroing the count, and
|
|
+ * reseeding the crng.
|
|
+ *
|
|
+ **********************************************************************/
|
|
+
|
|
+SYSCALL_DEFINE3(getrandom, char __user *, ubuf, size_t, len, unsigned int, flags)
|
|
{
|
|
- unsigned long flags;
|
|
- static int maxwarn = 10;
|
|
+ struct iov_iter iter;
|
|
+ struct iovec iov;
|
|
int ret;
|
|
|
|
- if (!crng_ready() && maxwarn > 0) {
|
|
- maxwarn--;
|
|
- if (__ratelimit(&urandom_warning))
|
|
- printk(KERN_NOTICE "random: %s: uninitialized "
|
|
- "urandom read (%zd bytes read)\n",
|
|
- current->comm, nbytes);
|
|
- spin_lock_irqsave(&primary_crng.lock, flags);
|
|
- crng_init_cnt = 0;
|
|
- spin_unlock_irqrestore(&primary_crng.lock, flags);
|
|
+ if (flags & ~(GRND_NONBLOCK | GRND_RANDOM | GRND_INSECURE))
|
|
+ return -EINVAL;
|
|
+
|
|
+ /*
|
|
+ * Requesting insecure and blocking randomness at the same time makes
|
|
+ * no sense.
|
|
+ */
|
|
+ if ((flags & (GRND_INSECURE | GRND_RANDOM)) == (GRND_INSECURE | GRND_RANDOM))
|
|
+ return -EINVAL;
|
|
+
|
|
+ if (!crng_ready() && !(flags & GRND_INSECURE)) {
|
|
+ if (flags & GRND_NONBLOCK)
|
|
+ return -EAGAIN;
|
|
+ ret = wait_for_random_bytes();
|
|
+ if (unlikely(ret))
|
|
+ return ret;
|
|
}
|
|
- nbytes = min_t(size_t, nbytes, INT_MAX >> (ENTROPY_SHIFT + 3));
|
|
- ret = extract_crng_user(buf, nbytes);
|
|
- trace_urandom_read(8 * nbytes, 0, ENTROPY_BITS(&input_pool));
|
|
- return ret;
|
|
+
|
|
+ ret = import_single_range(READ, ubuf, len, &iov, &iter);
|
|
+ if (unlikely(ret))
|
|
+ return ret;
|
|
+ return get_random_bytes_user(&iter);
|
|
}
|
|
|
|
-static __poll_t
|
|
-random_poll(struct file *file, poll_table * wait)
|
|
+static __poll_t random_poll(struct file *file, poll_table *wait)
|
|
{
|
|
- __poll_t mask;
|
|
-
|
|
- poll_wait(file, &random_read_wait, wait);
|
|
- poll_wait(file, &random_write_wait, wait);
|
|
- mask = 0;
|
|
- if (ENTROPY_BITS(&input_pool) >= random_read_wakeup_bits)
|
|
- mask |= EPOLLIN | EPOLLRDNORM;
|
|
- if (ENTROPY_BITS(&input_pool) < random_write_wakeup_bits)
|
|
- mask |= EPOLLOUT | EPOLLWRNORM;
|
|
- return mask;
|
|
+ poll_wait(file, &crng_init_wait, wait);
|
|
+ return crng_ready() ? EPOLLIN | EPOLLRDNORM : EPOLLOUT | EPOLLWRNORM;
|
|
}
|
|
|
|
-static int
|
|
-write_pool(struct entropy_store *r, const char __user *buffer, size_t count)
|
|
+static ssize_t write_pool_user(struct iov_iter *iter)
|
|
{
|
|
- size_t bytes;
|
|
- __u32 t, buf[16];
|
|
- const char __user *p = buffer;
|
|
+ u8 block[BLAKE2S_BLOCK_SIZE];
|
|
+ ssize_t ret = 0;
|
|
+ size_t copied;
|
|
|
|
- while (count > 0) {
|
|
- int b, i = 0;
|
|
+ if (unlikely(!iov_iter_count(iter)))
|
|
+ return 0;
|
|
|
|
- bytes = min(count, sizeof(buf));
|
|
- if (copy_from_user(&buf, p, bytes))
|
|
- return -EFAULT;
|
|
+ for (;;) {
|
|
+ copied = copy_from_iter(block, sizeof(block), iter);
|
|
+ ret += copied;
|
|
+ mix_pool_bytes(block, copied);
|
|
+ if (!iov_iter_count(iter) || copied != sizeof(block))
|
|
+ break;
|
|
|
|
- for (b = bytes ; b > 0 ; b -= sizeof(__u32), i++) {
|
|
- if (!arch_get_random_int(&t))
|
|
+ BUILD_BUG_ON(PAGE_SIZE % sizeof(block) != 0);
|
|
+ if (ret % PAGE_SIZE == 0) {
|
|
+ if (signal_pending(current))
|
|
break;
|
|
- buf[i] ^= t;
|
|
+ cond_resched();
|
|
}
|
|
+ }
|
|
+
|
|
+ memzero_explicit(block, sizeof(block));
|
|
+ return ret ? ret : -EFAULT;
|
|
+}
|
|
|
|
- count -= bytes;
|
|
- p += bytes;
|
|
+static ssize_t random_write_iter(struct kiocb *kiocb, struct iov_iter *iter)
|
|
+{
|
|
+ return write_pool_user(iter);
|
|
+}
|
|
+
|
|
+static ssize_t urandom_read_iter(struct kiocb *kiocb, struct iov_iter *iter)
|
|
+{
|
|
+ static int maxwarn = 10;
|
|
|
|
- mix_pool_bytes(r, buf, bytes);
|
|
- cond_resched();
|
|
+ if (!crng_ready()) {
|
|
+ if (!ratelimit_disable && maxwarn <= 0)
|
|
+ ++urandom_warning.missed;
|
|
+ else if (ratelimit_disable || __ratelimit(&urandom_warning)) {
|
|
+ --maxwarn;
|
|
+ pr_notice("%s: uninitialized urandom read (%zu bytes read)\n",
|
|
+ current->comm, iov_iter_count(iter));
|
|
+ }
|
|
}
|
|
|
|
- return 0;
|
|
+ return get_random_bytes_user(iter);
|
|
}
|
|
|
|
-static ssize_t random_write(struct file *file, const char __user *buffer,
|
|
- size_t count, loff_t *ppos)
|
|
+static ssize_t random_read_iter(struct kiocb *kiocb, struct iov_iter *iter)
|
|
{
|
|
- size_t ret;
|
|
+ int ret;
|
|
|
|
- ret = write_pool(&input_pool, buffer, count);
|
|
- if (ret)
|
|
+ ret = wait_for_random_bytes();
|
|
+ if (ret != 0)
|
|
return ret;
|
|
-
|
|
- return (ssize_t)count;
|
|
+ return get_random_bytes_user(iter);
|
|
}
|
|
|
|
static long random_ioctl(struct file *f, unsigned int cmd, unsigned long arg)
|
|
{
|
|
- int size, ent_count;
|
|
int __user *p = (int __user *)arg;
|
|
- int retval;
|
|
+ int ent_count;
|
|
|
|
switch (cmd) {
|
|
case RNDGETENTCNT:
|
|
- /* inherently racy, no point locking */
|
|
- ent_count = ENTROPY_BITS(&input_pool);
|
|
- if (put_user(ent_count, p))
|
|
+ /* Inherently racy, no point locking. */
|
|
+ if (put_user(input_pool.init_bits, p))
|
|
return -EFAULT;
|
|
return 0;
|
|
case RNDADDTOENTCNT:
|
|
@@ -2141,39 +1316,48 @@ static long random_ioctl(struct file *f, unsigned int cmd, unsigned long arg)
|
|
return -EPERM;
|
|
if (get_user(ent_count, p))
|
|
return -EFAULT;
|
|
- return credit_entropy_bits_safe(&input_pool, ent_count);
|
|
- case RNDADDENTROPY:
|
|
+ if (ent_count < 0)
|
|
+ return -EINVAL;
|
|
+ credit_init_bits(ent_count);
|
|
+ return 0;
|
|
+ case RNDADDENTROPY: {
|
|
+ struct iov_iter iter;
|
|
+ struct iovec iov;
|
|
+ ssize_t ret;
|
|
+ int len;
|
|
+
|
|
if (!capable(CAP_SYS_ADMIN))
|
|
return -EPERM;
|
|
if (get_user(ent_count, p++))
|
|
return -EFAULT;
|
|
if (ent_count < 0)
|
|
return -EINVAL;
|
|
- if (get_user(size, p++))
|
|
+ if (get_user(len, p++))
|
|
+ return -EFAULT;
|
|
+ ret = import_single_range(WRITE, p, len, &iov, &iter);
|
|
+ if (unlikely(ret))
|
|
+ return ret;
|
|
+ ret = write_pool_user(&iter);
|
|
+ if (unlikely(ret < 0))
|
|
+ return ret;
|
|
+ /* Since we're crediting, enforce that it was all written into the pool. */
|
|
+ if (unlikely(ret != len))
|
|
return -EFAULT;
|
|
- retval = write_pool(&input_pool, (const char __user *)p,
|
|
- size);
|
|
- if (retval < 0)
|
|
- return retval;
|
|
- return credit_entropy_bits_safe(&input_pool, ent_count);
|
|
+ credit_init_bits(ent_count);
|
|
+ return 0;
|
|
+ }
|
|
case RNDZAPENTCNT:
|
|
case RNDCLEARPOOL:
|
|
- /*
|
|
- * Clear the entropy pool counters. We no longer clear
|
|
- * the entropy pool, as that's silly.
|
|
- */
|
|
+ /* No longer has any effect. */
|
|
if (!capable(CAP_SYS_ADMIN))
|
|
return -EPERM;
|
|
- input_pool.entropy_count = 0;
|
|
- blocking_pool.entropy_count = 0;
|
|
return 0;
|
|
case RNDRESEEDCRNG:
|
|
if (!capable(CAP_SYS_ADMIN))
|
|
return -EPERM;
|
|
- if (crng_init < 2)
|
|
+ if (!crng_ready())
|
|
return -ENODATA;
|
|
- crng_reseed(&primary_crng, &input_pool);
|
|
- WRITE_ONCE(crng_global_init_time, jiffies - 1);
|
|
+ crng_reseed();
|
|
return 0;
|
|
default:
|
|
return -EINVAL;
|
|
@@ -2186,49 +1370,56 @@ static int random_fasync(int fd, struct file *filp, int on)
|
|
}
|
|
|
|
const struct file_operations random_fops = {
|
|
- .read = random_read,
|
|
- .write = random_write,
|
|
- .poll = random_poll,
|
|
+ .read_iter = random_read_iter,
|
|
+ .write_iter = random_write_iter,
|
|
+ .poll = random_poll,
|
|
.unlocked_ioctl = random_ioctl,
|
|
+ .compat_ioctl = compat_ptr_ioctl,
|
|
.fasync = random_fasync,
|
|
.llseek = noop_llseek,
|
|
+ .splice_read = generic_file_splice_read,
|
|
+ .splice_write = iter_file_splice_write,
|
|
};
|
|
|
|
const struct file_operations urandom_fops = {
|
|
- .read = urandom_read,
|
|
- .write = random_write,
|
|
+ .read_iter = urandom_read_iter,
|
|
+ .write_iter = random_write_iter,
|
|
.unlocked_ioctl = random_ioctl,
|
|
+ .compat_ioctl = compat_ptr_ioctl,
|
|
.fasync = random_fasync,
|
|
.llseek = noop_llseek,
|
|
+ .splice_read = generic_file_splice_read,
|
|
+ .splice_write = iter_file_splice_write,
|
|
};
|
|
|
|
-SYSCALL_DEFINE3(getrandom, char __user *, buf, size_t, count,
|
|
- unsigned int, flags)
|
|
-{
|
|
- int ret;
|
|
-
|
|
- if (flags & ~(GRND_NONBLOCK|GRND_RANDOM))
|
|
- return -EINVAL;
|
|
-
|
|
- if (count > INT_MAX)
|
|
- count = INT_MAX;
|
|
-
|
|
- if (flags & GRND_RANDOM)
|
|
- return _random_read(flags & GRND_NONBLOCK, buf, count);
|
|
-
|
|
- if (!crng_ready()) {
|
|
- if (flags & GRND_NONBLOCK)
|
|
- return -EAGAIN;
|
|
- ret = wait_for_random_bytes();
|
|
- if (unlikely(ret))
|
|
- return ret;
|
|
- }
|
|
- return urandom_read(NULL, buf, count, NULL);
|
|
-}
|
|
|
|
/********************************************************************
|
|
*
|
|
- * Sysctl interface
|
|
+ * Sysctl interface.
|
|
+ *
|
|
+ * These are partly unused legacy knobs with dummy values to not break
|
|
+ * userspace and partly still useful things. They are usually accessible
|
|
+ * in /proc/sys/kernel/random/ and are as follows:
|
|
+ *
|
|
+ * - boot_id - a UUID representing the current boot.
|
|
+ *
|
|
+ * - uuid - a random UUID, different each time the file is read.
|
|
+ *
|
|
+ * - poolsize - the number of bits of entropy that the input pool can
|
|
+ * hold, tied to the POOL_BITS constant.
|
|
+ *
|
|
+ * - entropy_avail - the number of bits of entropy currently in the
|
|
+ * input pool. Always <= poolsize.
|
|
+ *
|
|
+ * - write_wakeup_threshold - the amount of entropy in the input pool
|
|
+ * below which write polls to /dev/random will unblock, requesting
|
|
+ * more entropy, tied to the POOL_READY_BITS constant. It is writable
|
|
+ * to avoid breaking old userspaces, but writing to it does not
|
|
+ * change any behavior of the RNG.
|
|
+ *
|
|
+ * - urandom_min_reseed_secs - fixed to the value CRNG_RESEED_INTERVAL.
|
|
+ * It is writable to avoid breaking old userspaces, but writing
|
|
+ * to it does not change any behavior of the RNG.
|
|
*
|
|
********************************************************************/
|
|
|
|
@@ -2236,26 +1427,28 @@ SYSCALL_DEFINE3(getrandom, char __user *, buf, size_t, count,
|
|
|
|
#include <linux/sysctl.h>
|
|
|
|
-static int min_read_thresh = 8, min_write_thresh;
|
|
-static int max_read_thresh = OUTPUT_POOL_WORDS * 32;
|
|
-static int max_write_thresh = INPUT_POOL_WORDS * 32;
|
|
-static int random_min_urandom_seed = 60;
|
|
-static char sysctl_bootid[16];
|
|
+static int sysctl_random_min_urandom_seed = CRNG_RESEED_INTERVAL / HZ;
|
|
+static int sysctl_random_write_wakeup_bits = POOL_READY_BITS;
|
|
+static int sysctl_poolsize = POOL_BITS;
|
|
+static u8 sysctl_bootid[UUID_SIZE];
|
|
|
|
/*
|
|
* This function is used to return both the bootid UUID, and random
|
|
- * UUID. The difference is in whether table->data is NULL; if it is,
|
|
+ * UUID. The difference is in whether table->data is NULL; if it is,
|
|
* then a new UUID is generated and returned to the user.
|
|
- *
|
|
- * If the user accesses this via the proc interface, the UUID will be
|
|
- * returned as an ASCII string in the standard UUID format; if via the
|
|
- * sysctl system call, as 16 bytes of binary data.
|
|
*/
|
|
-static int proc_do_uuid(struct ctl_table *table, int write,
|
|
- void __user *buffer, size_t *lenp, loff_t *ppos)
|
|
-{
|
|
- struct ctl_table fake_table;
|
|
- unsigned char buf[64], tmp_uuid[16], *uuid;
|
|
+static int proc_do_uuid(struct ctl_table *table, int write, void __user *buf,
|
|
+ size_t *lenp, loff_t *ppos)
|
|
+{
|
|
+ u8 tmp_uuid[UUID_SIZE], *uuid;
|
|
+ char uuid_string[UUID_STRING_LEN + 1];
|
|
+ struct ctl_table fake_table = {
|
|
+ .data = uuid_string,
|
|
+ .maxlen = UUID_STRING_LEN
|
|
+ };
|
|
+
|
|
+ if (write)
|
|
+ return -EPERM;
|
|
|
|
uuid = table->data;
|
|
if (!uuid) {
|
|
@@ -2270,32 +1463,17 @@ static int proc_do_uuid(struct ctl_table *table, int write,
|
|
spin_unlock(&bootid_spinlock);
|
|
}
|
|
|
|
- sprintf(buf, "%pU", uuid);
|
|
-
|
|
- fake_table.data = buf;
|
|
- fake_table.maxlen = sizeof(buf);
|
|
-
|
|
- return proc_dostring(&fake_table, write, buffer, lenp, ppos);
|
|
+ snprintf(uuid_string, sizeof(uuid_string), "%pU", uuid);
|
|
+ return proc_dostring(&fake_table, 0, buf, lenp, ppos);
|
|
}
|
|
|
|
-/*
|
|
- * Return entropy available scaled to integral bits
|
|
- */
|
|
-static int proc_do_entropy(struct ctl_table *table, int write,
|
|
- void __user *buffer, size_t *lenp, loff_t *ppos)
|
|
+/* The same as proc_dointvec, but writes don't change anything. */
|
|
+static int proc_do_rointvec(struct ctl_table *table, int write, void __user *buf,
|
|
+ size_t *lenp, loff_t *ppos)
|
|
{
|
|
- struct ctl_table fake_table;
|
|
- int entropy_count;
|
|
-
|
|
- entropy_count = *(int *)table->data >> ENTROPY_SHIFT;
|
|
-
|
|
- fake_table.data = &entropy_count;
|
|
- fake_table.maxlen = sizeof(entropy_count);
|
|
-
|
|
- return proc_dointvec(&fake_table, write, buffer, lenp, ppos);
|
|
+ return write ? 0 : proc_dointvec(table, 0, buf, lenp, ppos);
|
|
}
|
|
|
|
-static int sysctl_poolsize = INPUT_POOL_WORDS * 32;
|
|
extern struct ctl_table random_table[];
|
|
struct ctl_table random_table[] = {
|
|
{
|
|
@@ -2307,231 +1485,36 @@ struct ctl_table random_table[] = {
|
|
},
|
|
{
|
|
.procname = "entropy_avail",
|
|
+ .data = &input_pool.init_bits,
|
|
.maxlen = sizeof(int),
|
|
.mode = 0444,
|
|
- .proc_handler = proc_do_entropy,
|
|
- .data = &input_pool.entropy_count,
|
|
- },
|
|
- {
|
|
- .procname = "read_wakeup_threshold",
|
|
- .data = &random_read_wakeup_bits,
|
|
- .maxlen = sizeof(int),
|
|
- .mode = 0644,
|
|
- .proc_handler = proc_dointvec_minmax,
|
|
- .extra1 = &min_read_thresh,
|
|
- .extra2 = &max_read_thresh,
|
|
+ .proc_handler = proc_dointvec,
|
|
},
|
|
{
|
|
.procname = "write_wakeup_threshold",
|
|
- .data = &random_write_wakeup_bits,
|
|
+ .data = &sysctl_random_write_wakeup_bits,
|
|
.maxlen = sizeof(int),
|
|
.mode = 0644,
|
|
- .proc_handler = proc_dointvec_minmax,
|
|
- .extra1 = &min_write_thresh,
|
|
- .extra2 = &max_write_thresh,
|
|
+ .proc_handler = proc_do_rointvec,
|
|
},
|
|
{
|
|
.procname = "urandom_min_reseed_secs",
|
|
- .data = &random_min_urandom_seed,
|
|
+ .data = &sysctl_random_min_urandom_seed,
|
|
.maxlen = sizeof(int),
|
|
.mode = 0644,
|
|
- .proc_handler = proc_dointvec,
|
|
+ .proc_handler = proc_do_rointvec,
|
|
},
|
|
{
|
|
.procname = "boot_id",
|
|
.data = &sysctl_bootid,
|
|
- .maxlen = 16,
|
|
.mode = 0444,
|
|
.proc_handler = proc_do_uuid,
|
|
},
|
|
{
|
|
.procname = "uuid",
|
|
- .maxlen = 16,
|
|
.mode = 0444,
|
|
.proc_handler = proc_do_uuid,
|
|
},
|
|
-#ifdef ADD_INTERRUPT_BENCH
|
|
- {
|
|
- .procname = "add_interrupt_avg_cycles",
|
|
- .data = &avg_cycles,
|
|
- .maxlen = sizeof(avg_cycles),
|
|
- .mode = 0444,
|
|
- .proc_handler = proc_doulongvec_minmax,
|
|
- },
|
|
- {
|
|
- .procname = "add_interrupt_avg_deviation",
|
|
- .data = &avg_deviation,
|
|
- .maxlen = sizeof(avg_deviation),
|
|
- .mode = 0444,
|
|
- .proc_handler = proc_doulongvec_minmax,
|
|
- },
|
|
-#endif
|
|
{ }
|
|
};
|
|
-#endif /* CONFIG_SYSCTL */
|
|
-
|
|
-struct batched_entropy {
|
|
- union {
|
|
- u64 entropy_u64[CHACHA_BLOCK_SIZE / sizeof(u64)];
|
|
- u32 entropy_u32[CHACHA_BLOCK_SIZE / sizeof(u32)];
|
|
- };
|
|
- unsigned int position;
|
|
- spinlock_t batch_lock;
|
|
-};
|
|
-
|
|
-/*
|
|
- * Get a random word for internal kernel use only. The quality of the random
|
|
- * number is good as /dev/urandom, but there is no backtrack protection, with
|
|
- * the goal of being quite fast and not depleting entropy. In order to ensure
|
|
- * that the randomness provided by this function is okay, the function
|
|
- * wait_for_random_bytes() should be called and return 0 at least once at any
|
|
- * point prior.
|
|
- */
|
|
-static DEFINE_PER_CPU(struct batched_entropy, batched_entropy_u64) = {
|
|
- .batch_lock = __SPIN_LOCK_UNLOCKED(batched_entropy_u64.lock),
|
|
-};
|
|
-
|
|
-u64 get_random_u64(void)
|
|
-{
|
|
- u64 ret;
|
|
- unsigned long flags;
|
|
- struct batched_entropy *batch;
|
|
- static void *previous;
|
|
-
|
|
- warn_unseeded_randomness(&previous);
|
|
-
|
|
- batch = raw_cpu_ptr(&batched_entropy_u64);
|
|
- spin_lock_irqsave(&batch->batch_lock, flags);
|
|
- if (batch->position % ARRAY_SIZE(batch->entropy_u64) == 0) {
|
|
- extract_crng((u8 *)batch->entropy_u64);
|
|
- batch->position = 0;
|
|
- }
|
|
- ret = batch->entropy_u64[batch->position++];
|
|
- spin_unlock_irqrestore(&batch->batch_lock, flags);
|
|
- return ret;
|
|
-}
|
|
-EXPORT_SYMBOL(get_random_u64);
|
|
-
|
|
-static DEFINE_PER_CPU(struct batched_entropy, batched_entropy_u32) = {
|
|
- .batch_lock = __SPIN_LOCK_UNLOCKED(batched_entropy_u32.lock),
|
|
-};
|
|
-u32 get_random_u32(void)
|
|
-{
|
|
- u32 ret;
|
|
- unsigned long flags;
|
|
- struct batched_entropy *batch;
|
|
- static void *previous;
|
|
-
|
|
- warn_unseeded_randomness(&previous);
|
|
-
|
|
- batch = raw_cpu_ptr(&batched_entropy_u32);
|
|
- spin_lock_irqsave(&batch->batch_lock, flags);
|
|
- if (batch->position % ARRAY_SIZE(batch->entropy_u32) == 0) {
|
|
- extract_crng((u8 *)batch->entropy_u32);
|
|
- batch->position = 0;
|
|
- }
|
|
- ret = batch->entropy_u32[batch->position++];
|
|
- spin_unlock_irqrestore(&batch->batch_lock, flags);
|
|
- return ret;
|
|
-}
|
|
-EXPORT_SYMBOL(get_random_u32);
|
|
-
|
|
-/* It's important to invalidate all potential batched entropy that might
|
|
- * be stored before the crng is initialized, which we can do lazily by
|
|
- * simply resetting the counter to zero so that it's re-extracted on the
|
|
- * next usage. */
|
|
-static void invalidate_batched_entropy(void)
|
|
-{
|
|
- int cpu;
|
|
- unsigned long flags;
|
|
-
|
|
- for_each_possible_cpu (cpu) {
|
|
- struct batched_entropy *batched_entropy;
|
|
-
|
|
- batched_entropy = per_cpu_ptr(&batched_entropy_u32, cpu);
|
|
- spin_lock_irqsave(&batched_entropy->batch_lock, flags);
|
|
- batched_entropy->position = 0;
|
|
- spin_unlock(&batched_entropy->batch_lock);
|
|
-
|
|
- batched_entropy = per_cpu_ptr(&batched_entropy_u64, cpu);
|
|
- spin_lock(&batched_entropy->batch_lock);
|
|
- batched_entropy->position = 0;
|
|
- spin_unlock_irqrestore(&batched_entropy->batch_lock, flags);
|
|
- }
|
|
-}
|
|
-
|
|
-/**
|
|
- * randomize_page - Generate a random, page aligned address
|
|
- * @start: The smallest acceptable address the caller will take.
|
|
- * @range: The size of the area, starting at @start, within which the
|
|
- * random address must fall.
|
|
- *
|
|
- * If @start + @range would overflow, @range is capped.
|
|
- *
|
|
- * NOTE: Historical use of randomize_range, which this replaces, presumed that
|
|
- * @start was already page aligned. We now align it regardless.
|
|
- *
|
|
- * Return: A page aligned address within [start, start + range). On error,
|
|
- * @start is returned.
|
|
- */
|
|
-unsigned long
|
|
-randomize_page(unsigned long start, unsigned long range)
|
|
-{
|
|
- if (!PAGE_ALIGNED(start)) {
|
|
- range -= PAGE_ALIGN(start) - start;
|
|
- start = PAGE_ALIGN(start);
|
|
- }
|
|
-
|
|
- if (start > ULONG_MAX - range)
|
|
- range = ULONG_MAX - start;
|
|
-
|
|
- range >>= PAGE_SHIFT;
|
|
-
|
|
- if (range == 0)
|
|
- return start;
|
|
-
|
|
- return start + (get_random_long() % range << PAGE_SHIFT);
|
|
-}
|
|
-
|
|
-/* Interface for in-kernel drivers of true hardware RNGs.
|
|
- * Those devices may produce endless random bits and will be throttled
|
|
- * when our pool is full.
|
|
- */
|
|
-void add_hwgenerator_randomness(const char *buffer, size_t count,
|
|
- size_t entropy)
|
|
-{
|
|
- struct entropy_store *poolp = &input_pool;
|
|
-
|
|
- if (unlikely(crng_init == 0)) {
|
|
- size_t ret = crng_fast_load(buffer, count);
|
|
- count -= ret;
|
|
- buffer += ret;
|
|
- if (!count || crng_init == 0)
|
|
- return;
|
|
- }
|
|
-
|
|
- /* Suspend writing if we're above the trickle threshold.
|
|
- * We'll be woken up again once below random_write_wakeup_thresh,
|
|
- * or when the calling thread is about to terminate.
|
|
- */
|
|
- wait_event_interruptible(random_write_wait,
|
|
- !system_wq || kthread_should_stop() ||
|
|
- ENTROPY_BITS(&input_pool) <= random_write_wakeup_bits);
|
|
- mix_pool_bytes(poolp, buffer, count);
|
|
- credit_entropy_bits(poolp, entropy);
|
|
-}
|
|
-EXPORT_SYMBOL_GPL(add_hwgenerator_randomness);
|
|
-
|
|
-/* Handle random seed passed by bootloader.
|
|
- * If the seed is trustworthy, it would be regarded as hardware RNGs. Otherwise
|
|
- * it would be regarded as device data.
|
|
- * The decision is controlled by CONFIG_RANDOM_TRUST_BOOTLOADER.
|
|
- */
|
|
-void add_bootloader_randomness(const void *buf, unsigned int size)
|
|
-{
|
|
- if (IS_ENABLED(CONFIG_RANDOM_TRUST_BOOTLOADER))
|
|
- add_hwgenerator_randomness(buf, size, size * 8);
|
|
- else
|
|
- add_device_randomness(buf, size);
|
|
-}
|
|
-EXPORT_SYMBOL_GPL(add_bootloader_randomness);
|
|
+#endif /* CONFIG_SYSCTL */
|
|
diff --git a/drivers/clocksource/hyperv_timer.c b/drivers/clocksource/hyperv_timer.c
|
|
index 36933e2b3b0df..80b4b8fee54d5 100644
|
|
--- a/drivers/clocksource/hyperv_timer.c
|
|
+++ b/drivers/clocksource/hyperv_timer.c
|
|
@@ -325,4 +325,3 @@ void __init hv_init_clocksource(void)
|
|
hv_sched_clock_offset = hyperv_cs->read(hyperv_cs);
|
|
hv_setup_sched_clock(read_hv_sched_clock_msr);
|
|
}
|
|
-EXPORT_SYMBOL_GPL(hv_init_clocksource);
|
|
diff --git a/drivers/hv/vmbus_drv.c b/drivers/hv/vmbus_drv.c
|
|
index 943654ded73d0..56918274c48cf 100644
|
|
--- a/drivers/hv/vmbus_drv.c
|
|
+++ b/drivers/hv/vmbus_drv.c
|
|
@@ -1303,7 +1303,7 @@ static void vmbus_isr(void)
|
|
tasklet_schedule(&hv_cpu->msg_dpc);
|
|
}
|
|
|
|
- add_interrupt_randomness(HYPERVISOR_CALLBACK_VECTOR, 0);
|
|
+ add_interrupt_randomness(HYPERVISOR_CALLBACK_VECTOR);
|
|
}
|
|
|
|
/*
|
|
diff --git a/drivers/i2c/busses/i2c-designware-common.c b/drivers/i2c/busses/i2c-designware-common.c
|
|
index 2de7452fcd6d7..c9036675bd779 100644
|
|
--- a/drivers/i2c/busses/i2c-designware-common.c
|
|
+++ b/drivers/i2c/busses/i2c-designware-common.c
|
|
@@ -253,9 +253,6 @@ int i2c_dw_prepare_clk(struct dw_i2c_dev *dev, bool prepare)
|
|
{
|
|
int ret;
|
|
|
|
- if (IS_ERR(dev->clk))
|
|
- return PTR_ERR(dev->clk);
|
|
-
|
|
if (prepare) {
|
|
/* Optional interface clock */
|
|
ret = clk_prepare_enable(dev->pclk);
|
|
diff --git a/drivers/i2c/busses/i2c-designware-platdrv.c b/drivers/i2c/busses/i2c-designware-platdrv.c
|
|
index 0c55c54372d7e..75313c80f132f 100644
|
|
--- a/drivers/i2c/busses/i2c-designware-platdrv.c
|
|
+++ b/drivers/i2c/busses/i2c-designware-platdrv.c
|
|
@@ -349,8 +349,17 @@ static int dw_i2c_plat_probe(struct platform_device *pdev)
|
|
goto exit_reset;
|
|
}
|
|
|
|
- dev->clk = devm_clk_get(&pdev->dev, NULL);
|
|
- if (!i2c_dw_prepare_clk(dev, true)) {
|
|
+ dev->clk = devm_clk_get_optional(&pdev->dev, NULL);
|
|
+ if (IS_ERR(dev->clk)) {
|
|
+ ret = PTR_ERR(dev->clk);
|
|
+ goto exit_reset;
|
|
+ }
|
|
+
|
|
+ ret = i2c_dw_prepare_clk(dev, true);
|
|
+ if (ret)
|
|
+ goto exit_reset;
|
|
+
|
|
+ if (dev->clk) {
|
|
u64 clk_khz;
|
|
|
|
dev->get_clk_rate_khz = i2c_dw_get_clk_rate_khz;
|
|
diff --git a/drivers/irqchip/irq-gic-realview.c b/drivers/irqchip/irq-gic-realview.c
|
|
index b4c1924f02554..38fab02ffe9d0 100644
|
|
--- a/drivers/irqchip/irq-gic-realview.c
|
|
+++ b/drivers/irqchip/irq-gic-realview.c
|
|
@@ -57,6 +57,7 @@ realview_gic_of_init(struct device_node *node, struct device_node *parent)
|
|
|
|
/* The PB11MPCore GIC needs to be configured in the syscon */
|
|
map = syscon_node_to_regmap(np);
|
|
+ of_node_put(np);
|
|
if (!IS_ERR(map)) {
|
|
/* new irq mode with no DCC */
|
|
regmap_write(map, REALVIEW_SYS_LOCK_OFFSET,
|
|
diff --git a/drivers/irqchip/irq-gic-v3.c b/drivers/irqchip/irq-gic-v3.c
|
|
index f589ca2480a1d..77a130c032238 100644
|
|
--- a/drivers/irqchip/irq-gic-v3.c
|
|
+++ b/drivers/irqchip/irq-gic-v3.c
|
|
@@ -1616,7 +1616,7 @@ static void __init gic_populate_ppi_partitions(struct device_node *gic_node)
|
|
|
|
gic_data.ppi_descs = kcalloc(gic_data.ppi_nr, sizeof(*gic_data.ppi_descs), GFP_KERNEL);
|
|
if (!gic_data.ppi_descs)
|
|
- return;
|
|
+ goto out_put_node;
|
|
|
|
nr_parts = of_get_child_count(parts_node);
|
|
|
|
@@ -1657,12 +1657,15 @@ static void __init gic_populate_ppi_partitions(struct device_node *gic_node)
|
|
continue;
|
|
|
|
cpu = of_cpu_node_to_id(cpu_node);
|
|
- if (WARN_ON(cpu < 0))
|
|
+ if (WARN_ON(cpu < 0)) {
|
|
+ of_node_put(cpu_node);
|
|
continue;
|
|
+ }
|
|
|
|
pr_cont("%pOF[%d] ", cpu_node, cpu);
|
|
|
|
cpumask_set_cpu(cpu, &part->mask);
|
|
+ of_node_put(cpu_node);
|
|
}
|
|
|
|
pr_cont("}\n");
|
|
diff --git a/drivers/md/dm-log.c b/drivers/md/dm-log.c
|
|
index 33e71ea6cc143..8b15f53cbdd95 100644
|
|
--- a/drivers/md/dm-log.c
|
|
+++ b/drivers/md/dm-log.c
|
|
@@ -415,8 +415,7 @@ static int create_log_context(struct dm_dirty_log *log, struct dm_target *ti,
|
|
/*
|
|
* Work out how many "unsigned long"s we need to hold the bitset.
|
|
*/
|
|
- bitset_size = dm_round_up(region_count,
|
|
- sizeof(*lc->clean_bits) << BYTE_SHIFT);
|
|
+ bitset_size = dm_round_up(region_count, BITS_PER_LONG);
|
|
bitset_size >>= BYTE_SHIFT;
|
|
|
|
lc->bitset_uint32_count = bitset_size / sizeof(*lc->clean_bits);
|
|
diff --git a/drivers/misc/atmel-ssc.c b/drivers/misc/atmel-ssc.c
|
|
index d6cd5537126c6..69f9b0336410d 100644
|
|
--- a/drivers/misc/atmel-ssc.c
|
|
+++ b/drivers/misc/atmel-ssc.c
|
|
@@ -232,9 +232,9 @@ static int ssc_probe(struct platform_device *pdev)
|
|
clk_disable_unprepare(ssc->clk);
|
|
|
|
ssc->irq = platform_get_irq(pdev, 0);
|
|
- if (!ssc->irq) {
|
|
+ if (ssc->irq < 0) {
|
|
dev_dbg(&pdev->dev, "could not get irq\n");
|
|
- return -ENXIO;
|
|
+ return ssc->irq;
|
|
}
|
|
|
|
mutex_lock(&user_lock);
|
|
diff --git a/drivers/net/ethernet/broadcom/bgmac-bcma.c b/drivers/net/ethernet/broadcom/bgmac-bcma.c
|
|
index 34d18302b1a38..2d52754afc33a 100644
|
|
--- a/drivers/net/ethernet/broadcom/bgmac-bcma.c
|
|
+++ b/drivers/net/ethernet/broadcom/bgmac-bcma.c
|
|
@@ -323,7 +323,6 @@ static void bgmac_remove(struct bcma_device *core)
|
|
bcma_mdio_mii_unregister(bgmac->mii_bus);
|
|
bgmac_enet_remove(bgmac);
|
|
bcma_set_drvdata(core, NULL);
|
|
- kfree(bgmac);
|
|
}
|
|
|
|
static struct bcma_driver bgmac_bcma_driver = {
|
|
diff --git a/drivers/net/ethernet/intel/i40e/i40e_ethtool.c b/drivers/net/ethernet/intel/i40e/i40e_ethtool.c
|
|
index 2cc4f63b1e910..689deecb4e1a3 100644
|
|
--- a/drivers/net/ethernet/intel/i40e/i40e_ethtool.c
|
|
+++ b/drivers/net/ethernet/intel/i40e/i40e_ethtool.c
|
|
@@ -2578,15 +2578,16 @@ static void i40e_diag_test(struct net_device *netdev,
|
|
|
|
set_bit(__I40E_TESTING, pf->state);
|
|
|
|
+ if (test_bit(__I40E_RESET_RECOVERY_PENDING, pf->state) ||
|
|
+ test_bit(__I40E_RESET_INTR_RECEIVED, pf->state)) {
|
|
+ dev_warn(&pf->pdev->dev,
|
|
+ "Cannot start offline testing when PF is in reset state.\n");
|
|
+ goto skip_ol_tests;
|
|
+ }
|
|
+
|
|
if (i40e_active_vfs(pf) || i40e_active_vmdqs(pf)) {
|
|
dev_warn(&pf->pdev->dev,
|
|
"Please take active VFs and Netqueues offline and restart the adapter before running NIC diagnostics\n");
|
|
- data[I40E_ETH_TEST_REG] = 1;
|
|
- data[I40E_ETH_TEST_EEPROM] = 1;
|
|
- data[I40E_ETH_TEST_INTR] = 1;
|
|
- data[I40E_ETH_TEST_LINK] = 1;
|
|
- eth_test->flags |= ETH_TEST_FL_FAILED;
|
|
- clear_bit(__I40E_TESTING, pf->state);
|
|
goto skip_ol_tests;
|
|
}
|
|
|
|
@@ -2633,9 +2634,17 @@ static void i40e_diag_test(struct net_device *netdev,
|
|
data[I40E_ETH_TEST_INTR] = 0;
|
|
}
|
|
|
|
-skip_ol_tests:
|
|
-
|
|
netif_info(pf, drv, netdev, "testing finished\n");
|
|
+ return;
|
|
+
|
|
+skip_ol_tests:
|
|
+ data[I40E_ETH_TEST_REG] = 1;
|
|
+ data[I40E_ETH_TEST_EEPROM] = 1;
|
|
+ data[I40E_ETH_TEST_INTR] = 1;
|
|
+ data[I40E_ETH_TEST_LINK] = 1;
|
|
+ eth_test->flags |= ETH_TEST_FL_FAILED;
|
|
+ clear_bit(__I40E_TESTING, pf->state);
|
|
+ netif_info(pf, drv, netdev, "testing failed\n");
|
|
}
|
|
|
|
static void i40e_get_wol(struct net_device *netdev,
|
|
diff --git a/drivers/net/ethernet/intel/i40e/i40e_main.c b/drivers/net/ethernet/intel/i40e/i40e_main.c
|
|
index 7f4aa22397867..05442bbc218cd 100644
|
|
--- a/drivers/net/ethernet/intel/i40e/i40e_main.c
|
|
+++ b/drivers/net/ethernet/intel/i40e/i40e_main.c
|
|
@@ -8108,6 +8108,11 @@ static int i40e_configure_clsflower(struct i40e_vsi *vsi,
|
|
return -EOPNOTSUPP;
|
|
}
|
|
|
|
+ if (!tc) {
|
|
+ dev_err(&pf->pdev->dev, "Unable to add filter because of invalid destination");
|
|
+ return -EINVAL;
|
|
+ }
|
|
+
|
|
if (test_bit(__I40E_RESET_RECOVERY_PENDING, pf->state) ||
|
|
test_bit(__I40E_RESET_INTR_RECEIVED, pf->state))
|
|
return -EBUSY;
|
|
diff --git a/drivers/net/ethernet/intel/i40e/i40e_virtchnl_pf.c b/drivers/net/ethernet/intel/i40e/i40e_virtchnl_pf.c
|
|
index 4962e6193eeca..4080fdacca4cc 100644
|
|
--- a/drivers/net/ethernet/intel/i40e/i40e_virtchnl_pf.c
|
|
+++ b/drivers/net/ethernet/intel/i40e/i40e_virtchnl_pf.c
|
|
@@ -2149,7 +2149,7 @@ static int i40e_vc_config_queues_msg(struct i40e_vf *vf, u8 *msg)
|
|
}
|
|
|
|
if (vf->adq_enabled) {
|
|
- for (i = 0; i < I40E_MAX_VF_VSI; i++)
|
|
+ for (i = 0; i < vf->num_tc; i++)
|
|
num_qps_all += vf->ch[i].num_qps;
|
|
if (num_qps_all != qci->num_queue_pairs) {
|
|
aq_ret = I40E_ERR_PARAM;
|
|
diff --git a/drivers/net/ethernet/mediatek/mtk_eth_soc.c b/drivers/net/ethernet/mediatek/mtk_eth_soc.c
|
|
index 5dce4cd60f58d..f9139150a8a26 100644
|
|
--- a/drivers/net/ethernet/mediatek/mtk_eth_soc.c
|
|
+++ b/drivers/net/ethernet/mediatek/mtk_eth_soc.c
|
|
@@ -802,6 +802,17 @@ static inline void mtk_rx_get_desc(struct mtk_rx_dma *rxd,
|
|
rxd->rxd4 = READ_ONCE(dma_rxd->rxd4);
|
|
}
|
|
|
|
+static void *mtk_max_lro_buf_alloc(gfp_t gfp_mask)
|
|
+{
|
|
+ unsigned int size = mtk_max_frag_size(MTK_MAX_LRO_RX_LENGTH);
|
|
+ unsigned long data;
|
|
+
|
|
+ data = __get_free_pages(gfp_mask | __GFP_COMP | __GFP_NOWARN,
|
|
+ get_order(size));
|
|
+
|
|
+ return (void *)data;
|
|
+}
|
|
+
|
|
/* the qdma core needs scratch memory to be setup */
|
|
static int mtk_init_fq_dma(struct mtk_eth *eth)
|
|
{
|
|
@@ -1299,7 +1310,10 @@ static int mtk_poll_rx(struct napi_struct *napi, int budget,
|
|
goto release_desc;
|
|
|
|
/* alloc new buffer */
|
|
- new_data = napi_alloc_frag(ring->frag_size);
|
|
+ if (ring->frag_size <= PAGE_SIZE)
|
|
+ new_data = napi_alloc_frag(ring->frag_size);
|
|
+ else
|
|
+ new_data = mtk_max_lro_buf_alloc(GFP_ATOMIC);
|
|
if (unlikely(!new_data)) {
|
|
netdev->stats.rx_dropped++;
|
|
goto release_desc;
|
|
@@ -1696,7 +1710,10 @@ static int mtk_rx_alloc(struct mtk_eth *eth, int ring_no, int rx_flag)
|
|
return -ENOMEM;
|
|
|
|
for (i = 0; i < rx_dma_size; i++) {
|
|
- ring->data[i] = netdev_alloc_frag(ring->frag_size);
|
|
+ if (ring->frag_size <= PAGE_SIZE)
|
|
+ ring->data[i] = netdev_alloc_frag(ring->frag_size);
|
|
+ else
|
|
+ ring->data[i] = mtk_max_lro_buf_alloc(GFP_KERNEL);
|
|
if (!ring->data[i])
|
|
return -ENOMEM;
|
|
}
|
|
diff --git a/drivers/net/ethernet/mellanox/mlxsw/spectrum_cnt.h b/drivers/net/ethernet/mellanox/mlxsw/spectrum_cnt.h
|
|
index 81465e267b100..b7eb3674e2856 100644
|
|
--- a/drivers/net/ethernet/mellanox/mlxsw/spectrum_cnt.h
|
|
+++ b/drivers/net/ethernet/mellanox/mlxsw/spectrum_cnt.h
|
|
@@ -7,8 +7,8 @@
|
|
#include "spectrum.h"
|
|
|
|
enum mlxsw_sp_counter_sub_pool_id {
|
|
- MLXSW_SP_COUNTER_SUB_POOL_FLOW,
|
|
MLXSW_SP_COUNTER_SUB_POOL_RIF,
|
|
+ MLXSW_SP_COUNTER_SUB_POOL_FLOW,
|
|
};
|
|
|
|
int mlxsw_sp_counter_alloc(struct mlxsw_sp *mlxsw_sp,
|
|
diff --git a/drivers/nfc/nfcmrvl/usb.c b/drivers/nfc/nfcmrvl/usb.c
|
|
index 888e298f610b8..f26986eb53f19 100644
|
|
--- a/drivers/nfc/nfcmrvl/usb.c
|
|
+++ b/drivers/nfc/nfcmrvl/usb.c
|
|
@@ -401,13 +401,25 @@ static void nfcmrvl_play_deferred(struct nfcmrvl_usb_drv_data *drv_data)
|
|
int err;
|
|
|
|
while ((urb = usb_get_from_anchor(&drv_data->deferred))) {
|
|
+ usb_anchor_urb(urb, &drv_data->tx_anchor);
|
|
+
|
|
err = usb_submit_urb(urb, GFP_ATOMIC);
|
|
- if (err)
|
|
+ if (err) {
|
|
+ kfree(urb->setup_packet);
|
|
+ usb_unanchor_urb(urb);
|
|
+ usb_free_urb(urb);
|
|
break;
|
|
+ }
|
|
|
|
drv_data->tx_in_flight++;
|
|
+ usb_free_urb(urb);
|
|
+ }
|
|
+
|
|
+ /* Cleanup the rest deferred urbs. */
|
|
+ while ((urb = usb_get_from_anchor(&drv_data->deferred))) {
|
|
+ kfree(urb->setup_packet);
|
|
+ usb_free_urb(urb);
|
|
}
|
|
- usb_scuttle_anchored_urbs(&drv_data->deferred);
|
|
}
|
|
|
|
static int nfcmrvl_resume(struct usb_interface *intf)
|
|
diff --git a/drivers/nfc/st21nfca/se.c b/drivers/nfc/st21nfca/se.c
|
|
index ccaace2a5b0e5..d416365042462 100644
|
|
--- a/drivers/nfc/st21nfca/se.c
|
|
+++ b/drivers/nfc/st21nfca/se.c
|
|
@@ -304,6 +304,8 @@ int st21nfca_connectivity_event_received(struct nfc_hci_dev *hdev, u8 host,
|
|
int r = 0;
|
|
struct device *dev = &hdev->ndev->dev;
|
|
struct nfc_evt_transaction *transaction;
|
|
+ u32 aid_len;
|
|
+ u8 params_len;
|
|
|
|
pr_debug("connectivity gate event: %x\n", event);
|
|
|
|
@@ -312,51 +314,48 @@ int st21nfca_connectivity_event_received(struct nfc_hci_dev *hdev, u8 host,
|
|
r = nfc_se_connectivity(hdev->ndev, host);
|
|
break;
|
|
case ST21NFCA_EVT_TRANSACTION:
|
|
- /*
|
|
- * According to specification etsi 102 622
|
|
+ /* According to specification etsi 102 622
|
|
* 11.2.2.4 EVT_TRANSACTION Table 52
|
|
* Description Tag Length
|
|
* AID 81 5 to 16
|
|
* PARAMETERS 82 0 to 255
|
|
+ *
|
|
+ * The key differences are aid storage length is variably sized
|
|
+ * in the packet, but fixed in nfc_evt_transaction, and that the aid_len
|
|
+ * is u8 in the packet, but u32 in the structure, and the tags in
|
|
+ * the packet are not included in nfc_evt_transaction.
|
|
+ *
|
|
+ * size in bytes: 1 1 5-16 1 1 0-255
|
|
+ * offset: 0 1 2 aid_len + 2 aid_len + 3 aid_len + 4
|
|
+ * member name: aid_tag(M) aid_len aid params_tag(M) params_len params
|
|
+ * example: 0x81 5-16 X 0x82 0-255 X
|
|
*/
|
|
- if (skb->len < NFC_MIN_AID_LENGTH + 2 ||
|
|
- skb->data[0] != NFC_EVT_TRANSACTION_AID_TAG)
|
|
+ if (skb->len < 2 || skb->data[0] != NFC_EVT_TRANSACTION_AID_TAG)
|
|
return -EPROTO;
|
|
|
|
- transaction = (struct nfc_evt_transaction *)devm_kzalloc(dev,
|
|
- skb->len - 2, GFP_KERNEL);
|
|
- if (!transaction)
|
|
- return -ENOMEM;
|
|
-
|
|
- transaction->aid_len = skb->data[1];
|
|
+ aid_len = skb->data[1];
|
|
|
|
- /* Checking if the length of the AID is valid */
|
|
- if (transaction->aid_len > sizeof(transaction->aid)) {
|
|
- devm_kfree(dev, transaction);
|
|
- return -EINVAL;
|
|
- }
|
|
+ if (skb->len < aid_len + 4 || aid_len > sizeof(transaction->aid))
|
|
+ return -EPROTO;
|
|
|
|
- memcpy(transaction->aid, &skb->data[2],
|
|
- transaction->aid_len);
|
|
+ params_len = skb->data[aid_len + 3];
|
|
|
|
- /* Check next byte is PARAMETERS tag (82) */
|
|
- if (skb->data[transaction->aid_len + 2] !=
|
|
- NFC_EVT_TRANSACTION_PARAMS_TAG) {
|
|
- devm_kfree(dev, transaction);
|
|
+ /* Verify PARAMETERS tag is (82), and final check that there is enough
|
|
+ * space in the packet to read everything.
|
|
+ */
|
|
+ if ((skb->data[aid_len + 2] != NFC_EVT_TRANSACTION_PARAMS_TAG) ||
|
|
+ (skb->len < aid_len + 4 + params_len))
|
|
return -EPROTO;
|
|
- }
|
|
|
|
- transaction->params_len = skb->data[transaction->aid_len + 3];
|
|
+ transaction = devm_kzalloc(dev, sizeof(*transaction) + params_len, GFP_KERNEL);
|
|
+ if (!transaction)
|
|
+ return -ENOMEM;
|
|
|
|
- /* Total size is allocated (skb->len - 2) minus fixed array members */
|
|
- if (transaction->params_len > ((skb->len - 2) -
|
|
- sizeof(struct nfc_evt_transaction))) {
|
|
- devm_kfree(dev, transaction);
|
|
- return -EINVAL;
|
|
- }
|
|
+ transaction->aid_len = aid_len;
|
|
+ transaction->params_len = params_len;
|
|
|
|
- memcpy(transaction->params, skb->data +
|
|
- transaction->aid_len + 4, transaction->params_len);
|
|
+ memcpy(transaction->aid, &skb->data[2], aid_len);
|
|
+ memcpy(transaction->params, &skb->data[aid_len + 4], params_len);
|
|
|
|
r = nfc_se_transaction(hdev->ndev, host, transaction);
|
|
break;
|
|
diff --git a/drivers/scsi/ipr.c b/drivers/scsi/ipr.c
|
|
index 7a57b61f0340e..a163fd9331b3c 100644
|
|
--- a/drivers/scsi/ipr.c
|
|
+++ b/drivers/scsi/ipr.c
|
|
@@ -9772,7 +9772,7 @@ static int ipr_alloc_mem(struct ipr_ioa_cfg *ioa_cfg)
|
|
GFP_KERNEL);
|
|
|
|
if (!ioa_cfg->hrrq[i].host_rrq) {
|
|
- while (--i > 0)
|
|
+ while (--i >= 0)
|
|
dma_free_coherent(&pdev->dev,
|
|
sizeof(u32) * ioa_cfg->hrrq[i].size,
|
|
ioa_cfg->hrrq[i].host_rrq,
|
|
@@ -10045,7 +10045,7 @@ static int ipr_request_other_msi_irqs(struct ipr_ioa_cfg *ioa_cfg,
|
|
ioa_cfg->vectors_info[i].desc,
|
|
&ioa_cfg->hrrq[i]);
|
|
if (rc) {
|
|
- while (--i >= 0)
|
|
+ while (--i > 0)
|
|
free_irq(pci_irq_vector(pdev, i),
|
|
&ioa_cfg->hrrq[i]);
|
|
return rc;
|
|
diff --git a/drivers/scsi/lpfc/lpfc_hw4.h b/drivers/scsi/lpfc/lpfc_hw4.h
|
|
index b8a772f80d6c5..cbea3e0c1a7d8 100644
|
|
--- a/drivers/scsi/lpfc/lpfc_hw4.h
|
|
+++ b/drivers/scsi/lpfc/lpfc_hw4.h
|
|
@@ -4249,6 +4249,9 @@ struct wqe_common {
|
|
#define wqe_sup_SHIFT 6
|
|
#define wqe_sup_MASK 0x00000001
|
|
#define wqe_sup_WORD word11
|
|
+#define wqe_ffrq_SHIFT 6
|
|
+#define wqe_ffrq_MASK 0x00000001
|
|
+#define wqe_ffrq_WORD word11
|
|
#define wqe_wqec_SHIFT 7
|
|
#define wqe_wqec_MASK 0x00000001
|
|
#define wqe_wqec_WORD word11
|
|
diff --git a/drivers/scsi/lpfc/lpfc_nportdisc.c b/drivers/scsi/lpfc/lpfc_nportdisc.c
|
|
index df2f7c3d7f845..e6a94f550a572 100644
|
|
--- a/drivers/scsi/lpfc/lpfc_nportdisc.c
|
|
+++ b/drivers/scsi/lpfc/lpfc_nportdisc.c
|
|
@@ -842,7 +842,8 @@ lpfc_rcv_logo(struct lpfc_vport *vport, struct lpfc_nodelist *ndlp,
|
|
else
|
|
lpfc_els_rsp_acc(vport, ELS_CMD_ACC, cmdiocb, ndlp, NULL);
|
|
if (ndlp->nlp_DID == Fabric_DID) {
|
|
- if (vport->port_state <= LPFC_FDISC)
|
|
+ if (vport->port_state <= LPFC_FDISC ||
|
|
+ vport->fc_flag & FC_PT2PT)
|
|
goto out;
|
|
lpfc_linkdown_port(vport);
|
|
spin_lock_irq(shost->host_lock);
|
|
diff --git a/drivers/scsi/lpfc/lpfc_nvme.c b/drivers/scsi/lpfc/lpfc_nvme.c
|
|
index 5a86a1ee0de3b..193c1a81cac01 100644
|
|
--- a/drivers/scsi/lpfc/lpfc_nvme.c
|
|
+++ b/drivers/scsi/lpfc/lpfc_nvme.c
|
|
@@ -1202,7 +1202,8 @@ lpfc_nvme_prep_io_cmd(struct lpfc_vport *vport,
|
|
{
|
|
struct lpfc_hba *phba = vport->phba;
|
|
struct nvmefc_fcp_req *nCmd = lpfc_ncmd->nvmeCmd;
|
|
- struct lpfc_iocbq *pwqeq = &(lpfc_ncmd->cur_iocbq);
|
|
+ struct nvme_common_command *sqe;
|
|
+ struct lpfc_iocbq *pwqeq = &lpfc_ncmd->cur_iocbq;
|
|
union lpfc_wqe128 *wqe = &pwqeq->wqe;
|
|
uint32_t req_len;
|
|
|
|
@@ -1258,8 +1259,14 @@ lpfc_nvme_prep_io_cmd(struct lpfc_vport *vport,
|
|
cstat->control_requests++;
|
|
}
|
|
|
|
- if (pnode->nlp_nvme_info & NLP_NVME_NSLER)
|
|
+ if (pnode->nlp_nvme_info & NLP_NVME_NSLER) {
|
|
bf_set(wqe_erp, &wqe->generic.wqe_com, 1);
|
|
+ sqe = &((struct nvme_fc_cmd_iu *)
|
|
+ nCmd->cmdaddr)->sqe.common;
|
|
+ if (sqe->opcode == nvme_admin_async_event)
|
|
+ bf_set(wqe_ffrq, &wqe->generic.wqe_com, 1);
|
|
+ }
|
|
+
|
|
/*
|
|
* Finish initializing those WQE fields that are independent
|
|
* of the nvme_cmnd request_buffer
|
|
diff --git a/drivers/scsi/pmcraid.c b/drivers/scsi/pmcraid.c
|
|
index 398d2af60832c..f95a970db8fdb 100644
|
|
--- a/drivers/scsi/pmcraid.c
|
|
+++ b/drivers/scsi/pmcraid.c
|
|
@@ -4532,7 +4532,7 @@ pmcraid_register_interrupt_handler(struct pmcraid_instance *pinstance)
|
|
return 0;
|
|
|
|
out_unwind:
|
|
- while (--i > 0)
|
|
+ while (--i >= 0)
|
|
free_irq(pci_irq_vector(pdev, i), &pinstance->hrrq_vector[i]);
|
|
pci_free_irq_vectors(pdev);
|
|
return rc;
|
|
diff --git a/drivers/scsi/vmw_pvscsi.h b/drivers/scsi/vmw_pvscsi.h
|
|
index 75966d3f326e0..d87c12324c032 100644
|
|
--- a/drivers/scsi/vmw_pvscsi.h
|
|
+++ b/drivers/scsi/vmw_pvscsi.h
|
|
@@ -333,8 +333,8 @@ struct PVSCSIRingReqDesc {
|
|
u8 tag;
|
|
u8 bus;
|
|
u8 target;
|
|
- u8 vcpuHint;
|
|
- u8 unused[59];
|
|
+ u16 vcpuHint;
|
|
+ u8 unused[58];
|
|
} __packed;
|
|
|
|
/*
|
|
diff --git a/drivers/staging/comedi/drivers/vmk80xx.c b/drivers/staging/comedi/drivers/vmk80xx.c
|
|
index 7769eadfaf61d..ccc65cfc519f5 100644
|
|
--- a/drivers/staging/comedi/drivers/vmk80xx.c
|
|
+++ b/drivers/staging/comedi/drivers/vmk80xx.c
|
|
@@ -685,7 +685,7 @@ static int vmk80xx_alloc_usb_buffers(struct comedi_device *dev)
|
|
if (!devpriv->usb_rx_buf)
|
|
return -ENOMEM;
|
|
|
|
- size = max(usb_endpoint_maxp(devpriv->ep_rx), MIN_BUF_SIZE);
|
|
+ size = max(usb_endpoint_maxp(devpriv->ep_tx), MIN_BUF_SIZE);
|
|
devpriv->usb_tx_buf = kzalloc(size, GFP_KERNEL);
|
|
if (!devpriv->usb_tx_buf)
|
|
return -ENOMEM;
|
|
diff --git a/drivers/tty/goldfish.c b/drivers/tty/goldfish.c
|
|
index abc84d84f6386..9180ca5e4dcd4 100644
|
|
--- a/drivers/tty/goldfish.c
|
|
+++ b/drivers/tty/goldfish.c
|
|
@@ -428,7 +428,7 @@ static int goldfish_tty_remove(struct platform_device *pdev)
|
|
tty_unregister_device(goldfish_tty_driver, qtty->console.index);
|
|
iounmap(qtty->base);
|
|
qtty->base = NULL;
|
|
- free_irq(qtty->irq, pdev);
|
|
+ free_irq(qtty->irq, qtty);
|
|
tty_port_destroy(&qtty->port);
|
|
goldfish_tty_current_line_count--;
|
|
if (goldfish_tty_current_line_count == 0)
|
|
diff --git a/drivers/tty/serial/8250/8250_port.c b/drivers/tty/serial/8250/8250_port.c
|
|
index c1891c55897ad..cb975228726e0 100644
|
|
--- a/drivers/tty/serial/8250/8250_port.c
|
|
+++ b/drivers/tty/serial/8250/8250_port.c
|
|
@@ -1476,6 +1476,8 @@ static inline void __stop_tx(struct uart_8250_port *p)
|
|
|
|
if (em485) {
|
|
unsigned char lsr = serial_in(p, UART_LSR);
|
|
+ p->lsr_saved_flags |= lsr & LSR_SAVE_FLAGS;
|
|
+
|
|
/*
|
|
* To provide required timeing and allow FIFO transfer,
|
|
* __stop_tx_rs485() must be called only when both FIFO and
|
|
diff --git a/drivers/usb/dwc2/hcd.c b/drivers/usb/dwc2/hcd.c
|
|
index 78329d0e9af0a..a412ef67af18d 100644
|
|
--- a/drivers/usb/dwc2/hcd.c
|
|
+++ b/drivers/usb/dwc2/hcd.c
|
|
@@ -5076,7 +5076,7 @@ int dwc2_hcd_init(struct dwc2_hsotg *hsotg)
|
|
res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
|
|
if (!res) {
|
|
retval = -EINVAL;
|
|
- goto error1;
|
|
+ goto error2;
|
|
}
|
|
hcd->rsrc_start = res->start;
|
|
hcd->rsrc_len = resource_size(res);
|
|
diff --git a/drivers/usb/gadget/udc/lpc32xx_udc.c b/drivers/usb/gadget/udc/lpc32xx_udc.c
|
|
index 6d2f1f98f13df..f71f61bcfe1e1 100644
|
|
--- a/drivers/usb/gadget/udc/lpc32xx_udc.c
|
|
+++ b/drivers/usb/gadget/udc/lpc32xx_udc.c
|
|
@@ -3027,6 +3027,7 @@ static int lpc32xx_udc_probe(struct platform_device *pdev)
|
|
}
|
|
|
|
udc->isp1301_i2c_client = isp1301_get_client(isp1301_node);
|
|
+ of_node_put(isp1301_node);
|
|
if (!udc->isp1301_i2c_client) {
|
|
return -EPROBE_DEFER;
|
|
}
|
|
diff --git a/drivers/usb/serial/io_ti.c b/drivers/usb/serial/io_ti.c
|
|
index c327d4cf79285..03bcab3b9bd09 100644
|
|
--- a/drivers/usb/serial/io_ti.c
|
|
+++ b/drivers/usb/serial/io_ti.c
|
|
@@ -168,6 +168,7 @@ static const struct usb_device_id edgeport_2port_id_table[] = {
|
|
{ USB_DEVICE(USB_VENDOR_ID_ION, ION_DEVICE_ID_TI_EDGEPORT_8S) },
|
|
{ USB_DEVICE(USB_VENDOR_ID_ION, ION_DEVICE_ID_TI_EDGEPORT_416) },
|
|
{ USB_DEVICE(USB_VENDOR_ID_ION, ION_DEVICE_ID_TI_EDGEPORT_416B) },
|
|
+ { USB_DEVICE(USB_VENDOR_ID_ION, ION_DEVICE_ID_E5805A) },
|
|
{ }
|
|
};
|
|
|
|
@@ -206,6 +207,7 @@ static const struct usb_device_id id_table_combined[] = {
|
|
{ USB_DEVICE(USB_VENDOR_ID_ION, ION_DEVICE_ID_TI_EDGEPORT_8S) },
|
|
{ USB_DEVICE(USB_VENDOR_ID_ION, ION_DEVICE_ID_TI_EDGEPORT_416) },
|
|
{ USB_DEVICE(USB_VENDOR_ID_ION, ION_DEVICE_ID_TI_EDGEPORT_416B) },
|
|
+ { USB_DEVICE(USB_VENDOR_ID_ION, ION_DEVICE_ID_E5805A) },
|
|
{ }
|
|
};
|
|
|
|
diff --git a/drivers/usb/serial/io_usbvend.h b/drivers/usb/serial/io_usbvend.h
|
|
index c38e87ac5ea9e..7ca5ca49adff8 100644
|
|
--- a/drivers/usb/serial/io_usbvend.h
|
|
+++ b/drivers/usb/serial/io_usbvend.h
|
|
@@ -212,6 +212,7 @@
|
|
//
|
|
// Definitions for other product IDs
|
|
#define ION_DEVICE_ID_MT4X56USB 0x1403 // OEM device
|
|
+#define ION_DEVICE_ID_E5805A 0x1A01 // OEM device (rebranded Edgeport/4)
|
|
|
|
|
|
#define GENERATION_ID_FROM_USB_PRODUCT_ID(ProductId) \
|
|
diff --git a/drivers/usb/serial/option.c b/drivers/usb/serial/option.c
|
|
index 62f79fd5257bc..ec4fdb8140917 100644
|
|
--- a/drivers/usb/serial/option.c
|
|
+++ b/drivers/usb/serial/option.c
|
|
@@ -432,6 +432,8 @@ static void option_instat_callback(struct urb *urb);
|
|
#define CINTERION_PRODUCT_CLS8 0x00b0
|
|
#define CINTERION_PRODUCT_MV31_MBIM 0x00b3
|
|
#define CINTERION_PRODUCT_MV31_RMNET 0x00b7
|
|
+#define CINTERION_PRODUCT_MV31_2_MBIM 0x00b8
|
|
+#define CINTERION_PRODUCT_MV31_2_RMNET 0x00b9
|
|
#define CINTERION_PRODUCT_MV32_WA 0x00f1
|
|
#define CINTERION_PRODUCT_MV32_WB 0x00f2
|
|
|
|
@@ -1979,6 +1981,10 @@ static const struct usb_device_id option_ids[] = {
|
|
.driver_info = RSVD(3)},
|
|
{ USB_DEVICE_INTERFACE_CLASS(CINTERION_VENDOR_ID, CINTERION_PRODUCT_MV31_RMNET, 0xff),
|
|
.driver_info = RSVD(0)},
|
|
+ { USB_DEVICE_INTERFACE_CLASS(CINTERION_VENDOR_ID, CINTERION_PRODUCT_MV31_2_MBIM, 0xff),
|
|
+ .driver_info = RSVD(3)},
|
|
+ { USB_DEVICE_INTERFACE_CLASS(CINTERION_VENDOR_ID, CINTERION_PRODUCT_MV31_2_RMNET, 0xff),
|
|
+ .driver_info = RSVD(0)},
|
|
{ USB_DEVICE_INTERFACE_CLASS(CINTERION_VENDOR_ID, CINTERION_PRODUCT_MV32_WA, 0xff),
|
|
.driver_info = RSVD(3)},
|
|
{ USB_DEVICE_INTERFACE_CLASS(CINTERION_VENDOR_ID, CINTERION_PRODUCT_MV32_WB, 0xff),
|
|
diff --git a/drivers/virtio/virtio_mmio.c b/drivers/virtio/virtio_mmio.c
|
|
index e09edb5c5e065..74547323aa836 100644
|
|
--- a/drivers/virtio/virtio_mmio.c
|
|
+++ b/drivers/virtio/virtio_mmio.c
|
|
@@ -669,6 +669,7 @@ static int vm_cmdline_set(const char *device,
|
|
if (!vm_cmdline_parent_registered) {
|
|
err = device_register(&vm_cmdline_parent);
|
|
if (err) {
|
|
+ put_device(&vm_cmdline_parent);
|
|
pr_err("Failed to register parent device!\n");
|
|
return err;
|
|
}
|
|
diff --git a/drivers/virtio/virtio_pci_common.c b/drivers/virtio/virtio_pci_common.c
|
|
index b35bb2d57f62c..1e890ef176873 100644
|
|
--- a/drivers/virtio/virtio_pci_common.c
|
|
+++ b/drivers/virtio/virtio_pci_common.c
|
|
@@ -254,8 +254,7 @@ void vp_del_vqs(struct virtio_device *vdev)
|
|
|
|
if (vp_dev->msix_affinity_masks) {
|
|
for (i = 0; i < vp_dev->msix_vectors; i++)
|
|
- if (vp_dev->msix_affinity_masks[i])
|
|
- free_cpumask_var(vp_dev->msix_affinity_masks[i]);
|
|
+ free_cpumask_var(vp_dev->msix_affinity_masks[i]);
|
|
}
|
|
|
|
if (vp_dev->msix_enabled) {
|
|
diff --git a/fs/9p/vfs_inode_dotl.c b/fs/9p/vfs_inode_dotl.c
|
|
index 60328b21c5fbd..9795fe0f1ba21 100644
|
|
--- a/fs/9p/vfs_inode_dotl.c
|
|
+++ b/fs/9p/vfs_inode_dotl.c
|
|
@@ -641,14 +641,10 @@ v9fs_stat2inode_dotl(struct p9_stat_dotl *stat, struct inode *inode,
|
|
if (stat->st_result_mask & P9_STATS_NLINK)
|
|
set_nlink(inode, stat->st_nlink);
|
|
if (stat->st_result_mask & P9_STATS_MODE) {
|
|
- inode->i_mode = stat->st_mode;
|
|
- if ((S_ISBLK(inode->i_mode)) ||
|
|
- (S_ISCHR(inode->i_mode)))
|
|
- init_special_inode(inode, inode->i_mode,
|
|
- inode->i_rdev);
|
|
+ mode = stat->st_mode & S_IALLUGO;
|
|
+ mode |= inode->i_mode & ~S_IALLUGO;
|
|
+ inode->i_mode = mode;
|
|
}
|
|
- if (stat->st_result_mask & P9_STATS_RDEV)
|
|
- inode->i_rdev = new_decode_dev(stat->st_rdev);
|
|
if (!(flags & V9FS_STAT2INODE_KEEP_ISIZE) &&
|
|
stat->st_result_mask & P9_STATS_SIZE)
|
|
v9fs_i_size_write(inode, stat->st_size);
|
|
diff --git a/fs/compat_ioctl.c b/fs/compat_ioctl.c
|
|
index e0226b2138d64..8fcc53d83af2d 100644
|
|
--- a/fs/compat_ioctl.c
|
|
+++ b/fs/compat_ioctl.c
|
|
@@ -808,13 +808,6 @@ COMPATIBLE_IOCTL(WDIOC_SETTIMEOUT)
|
|
COMPATIBLE_IOCTL(WDIOC_GETTIMEOUT)
|
|
COMPATIBLE_IOCTL(WDIOC_SETPRETIMEOUT)
|
|
COMPATIBLE_IOCTL(WDIOC_GETPRETIMEOUT)
|
|
-/* Big R */
|
|
-COMPATIBLE_IOCTL(RNDGETENTCNT)
|
|
-COMPATIBLE_IOCTL(RNDADDTOENTCNT)
|
|
-COMPATIBLE_IOCTL(RNDGETPOOL)
|
|
-COMPATIBLE_IOCTL(RNDADDENTROPY)
|
|
-COMPATIBLE_IOCTL(RNDZAPENTCNT)
|
|
-COMPATIBLE_IOCTL(RNDCLEARPOOL)
|
|
/* Bluetooth */
|
|
COMPATIBLE_IOCTL(HCIDEVUP)
|
|
COMPATIBLE_IOCTL(HCIDEVDOWN)
|
|
diff --git a/fs/ext4/mballoc.c b/fs/ext4/mballoc.c
|
|
index 0307702d114db..3c3166ba43649 100644
|
|
--- a/fs/ext4/mballoc.c
|
|
+++ b/fs/ext4/mballoc.c
|
|
@@ -3172,6 +3172,15 @@ ext4_mb_normalize_request(struct ext4_allocation_context *ac,
|
|
size = size >> bsbits;
|
|
start = start_off >> bsbits;
|
|
|
|
+ /*
|
|
+ * For tiny groups (smaller than 8MB) the chosen allocation
|
|
+ * alignment may be larger than group size. Make sure the
|
|
+ * alignment does not move allocation to a different group which
|
|
+ * makes mballoc fail assertions later.
|
|
+ */
|
|
+ start = max(start, rounddown(ac->ac_o_ex.fe_logical,
|
|
+ (ext4_lblk_t)EXT4_BLOCKS_PER_GROUP(ac->ac_sb)));
|
|
+
|
|
/* don't cover already allocated blocks in selected range */
|
|
if (ar->pleft && start <= ar->lleft) {
|
|
size -= ar->lleft + 1 - start;
|
|
diff --git a/fs/ext4/namei.c b/fs/ext4/namei.c
|
|
index b01059bb562c0..d151892db8b0c 100644
|
|
--- a/fs/ext4/namei.c
|
|
+++ b/fs/ext4/namei.c
|
|
@@ -1836,7 +1836,8 @@ static struct ext4_dir_entry_2 *do_split(handle_t *handle, struct inode *dir,
|
|
struct dx_hash_info *hinfo)
|
|
{
|
|
unsigned blocksize = dir->i_sb->s_blocksize;
|
|
- unsigned count, continued;
|
|
+ unsigned continued;
|
|
+ int count;
|
|
struct buffer_head *bh2;
|
|
ext4_lblk_t newblock;
|
|
u32 hash2;
|
|
diff --git a/fs/ext4/resize.c b/fs/ext4/resize.c
|
|
index b7f20196439a2..6410c1e098d36 100644
|
|
--- a/fs/ext4/resize.c
|
|
+++ b/fs/ext4/resize.c
|
|
@@ -52,6 +52,16 @@ int ext4_resize_begin(struct super_block *sb)
|
|
if (!capable(CAP_SYS_RESOURCE))
|
|
return -EPERM;
|
|
|
|
+ /*
|
|
+ * If the reserved GDT blocks is non-zero, the resize_inode feature
|
|
+ * should always be set.
|
|
+ */
|
|
+ if (EXT4_SB(sb)->s_es->s_reserved_gdt_blocks &&
|
|
+ !ext4_has_feature_resize_inode(sb)) {
|
|
+ ext4_error(sb, "resize_inode disabled but reserved GDT blocks non-zero");
|
|
+ return -EFSCORRUPTED;
|
|
+ }
|
|
+
|
|
/*
|
|
* If we are not using the primary superblock/GDT copy don't resize,
|
|
* because the user tools have no way of handling this. Probably a
|
|
diff --git a/fs/nfs/pnfs.c b/fs/nfs/pnfs.c
|
|
index 2fe48982fbb48..3b19fa74b0620 100644
|
|
--- a/fs/nfs/pnfs.c
|
|
+++ b/fs/nfs/pnfs.c
|
|
@@ -2111,6 +2111,12 @@ lookup_again:
|
|
case -ERECALLCONFLICT:
|
|
case -EAGAIN:
|
|
break;
|
|
+ case -ENODATA:
|
|
+ /* The server returned NFS4ERR_LAYOUTUNAVAILABLE */
|
|
+ pnfs_layout_set_fail_bit(
|
|
+ lo, pnfs_iomode_to_fail_bit(iomode));
|
|
+ lseg = NULL;
|
|
+ goto out_put_layout_hdr;
|
|
default:
|
|
if (!nfs_error_is_fatal(PTR_ERR(lseg))) {
|
|
pnfs_layout_clear_fail_bit(lo, pnfs_iomode_to_fail_bit(iomode));
|
|
diff --git a/include/crypto/blake2s.h b/include/crypto/blake2s.h
|
|
new file mode 100644
|
|
index 0000000000000..d439496fa6baa
|
|
--- /dev/null
|
|
+++ b/include/crypto/blake2s.h
|
|
@@ -0,0 +1,102 @@
|
|
+/* SPDX-License-Identifier: GPL-2.0 OR MIT */
|
|
+/*
|
|
+ * Copyright (C) 2015-2019 Jason A. Donenfeld <Jason@zx2c4.com>. All Rights Reserved.
|
|
+ */
|
|
+
|
|
+#ifndef _CRYPTO_BLAKE2S_H
|
|
+#define _CRYPTO_BLAKE2S_H
|
|
+
|
|
+#include <linux/bug.h>
|
|
+#include <linux/types.h>
|
|
+#include <linux/kernel.h>
|
|
+#include <linux/string.h>
|
|
+
|
|
+enum blake2s_lengths {
|
|
+ BLAKE2S_BLOCK_SIZE = 64,
|
|
+ BLAKE2S_HASH_SIZE = 32,
|
|
+ BLAKE2S_KEY_SIZE = 32,
|
|
+
|
|
+ BLAKE2S_128_HASH_SIZE = 16,
|
|
+ BLAKE2S_160_HASH_SIZE = 20,
|
|
+ BLAKE2S_224_HASH_SIZE = 28,
|
|
+ BLAKE2S_256_HASH_SIZE = 32,
|
|
+};
|
|
+
|
|
+struct blake2s_state {
|
|
+ u32 h[8];
|
|
+ u32 t[2];
|
|
+ u32 f[2];
|
|
+ u8 buf[BLAKE2S_BLOCK_SIZE];
|
|
+ unsigned int buflen;
|
|
+ unsigned int outlen;
|
|
+};
|
|
+
|
|
+enum blake2s_iv {
|
|
+ BLAKE2S_IV0 = 0x6A09E667UL,
|
|
+ BLAKE2S_IV1 = 0xBB67AE85UL,
|
|
+ BLAKE2S_IV2 = 0x3C6EF372UL,
|
|
+ BLAKE2S_IV3 = 0xA54FF53AUL,
|
|
+ BLAKE2S_IV4 = 0x510E527FUL,
|
|
+ BLAKE2S_IV5 = 0x9B05688CUL,
|
|
+ BLAKE2S_IV6 = 0x1F83D9ABUL,
|
|
+ BLAKE2S_IV7 = 0x5BE0CD19UL,
|
|
+};
|
|
+
|
|
+void blake2s_update(struct blake2s_state *state, const u8 *in, size_t inlen);
|
|
+void blake2s_final(struct blake2s_state *state, u8 *out);
|
|
+
|
|
+static inline void blake2s_init_param(struct blake2s_state *state,
|
|
+ const u32 param)
|
|
+{
|
|
+ *state = (struct blake2s_state){{
|
|
+ BLAKE2S_IV0 ^ param,
|
|
+ BLAKE2S_IV1,
|
|
+ BLAKE2S_IV2,
|
|
+ BLAKE2S_IV3,
|
|
+ BLAKE2S_IV4,
|
|
+ BLAKE2S_IV5,
|
|
+ BLAKE2S_IV6,
|
|
+ BLAKE2S_IV7,
|
|
+ }};
|
|
+}
|
|
+
|
|
+static inline void blake2s_init(struct blake2s_state *state,
|
|
+ const size_t outlen)
|
|
+{
|
|
+ blake2s_init_param(state, 0x01010000 | outlen);
|
|
+ state->outlen = outlen;
|
|
+}
|
|
+
|
|
+static inline void blake2s_init_key(struct blake2s_state *state,
|
|
+ const size_t outlen, const void *key,
|
|
+ const size_t keylen)
|
|
+{
|
|
+ WARN_ON(IS_ENABLED(DEBUG) && (!outlen || outlen > BLAKE2S_HASH_SIZE ||
|
|
+ !key || !keylen || keylen > BLAKE2S_KEY_SIZE));
|
|
+
|
|
+ blake2s_init_param(state, 0x01010000 | keylen << 8 | outlen);
|
|
+ memcpy(state->buf, key, keylen);
|
|
+ state->buflen = BLAKE2S_BLOCK_SIZE;
|
|
+ state->outlen = outlen;
|
|
+}
|
|
+
|
|
+static inline void blake2s(u8 *out, const u8 *in, const u8 *key,
|
|
+ const size_t outlen, const size_t inlen,
|
|
+ const size_t keylen)
|
|
+{
|
|
+ struct blake2s_state state;
|
|
+
|
|
+ WARN_ON(IS_ENABLED(DEBUG) && ((!in && inlen > 0) || !out || !outlen ||
|
|
+ outlen > BLAKE2S_HASH_SIZE || keylen > BLAKE2S_KEY_SIZE ||
|
|
+ (!key && keylen)));
|
|
+
|
|
+ if (keylen)
|
|
+ blake2s_init_key(&state, outlen, key, keylen);
|
|
+ else
|
|
+ blake2s_init(&state, outlen);
|
|
+
|
|
+ blake2s_update(&state, in, inlen);
|
|
+ blake2s_final(&state, out);
|
|
+}
|
|
+
|
|
+#endif /* _CRYPTO_BLAKE2S_H */
|
|
diff --git a/include/crypto/chacha.h b/include/crypto/chacha.h
|
|
index d1e723c6a37dd..542f896115f45 100644
|
|
--- a/include/crypto/chacha.h
|
|
+++ b/include/crypto/chacha.h
|
|
@@ -51,4 +51,19 @@ int crypto_chacha12_setkey(struct crypto_skcipher *tfm, const u8 *key,
|
|
int crypto_chacha_crypt(struct skcipher_request *req);
|
|
int crypto_xchacha_crypt(struct skcipher_request *req);
|
|
|
|
+enum chacha_constants { /* expand 32-byte k */
|
|
+ CHACHA_CONSTANT_EXPA = 0x61707865U,
|
|
+ CHACHA_CONSTANT_ND_3 = 0x3320646eU,
|
|
+ CHACHA_CONSTANT_2_BY = 0x79622d32U,
|
|
+ CHACHA_CONSTANT_TE_K = 0x6b206574U
|
|
+};
|
|
+
|
|
+static inline void chacha_init_consts(u32 *state)
|
|
+{
|
|
+ state[0] = CHACHA_CONSTANT_EXPA;
|
|
+ state[1] = CHACHA_CONSTANT_ND_3;
|
|
+ state[2] = CHACHA_CONSTANT_2_BY;
|
|
+ state[3] = CHACHA_CONSTANT_TE_K;
|
|
+}
|
|
+
|
|
#endif /* _CRYPTO_CHACHA_H */
|
|
diff --git a/include/crypto/drbg.h b/include/crypto/drbg.h
|
|
index 8c9af21efce1d..a6c3b8e7deb64 100644
|
|
--- a/include/crypto/drbg.h
|
|
+++ b/include/crypto/drbg.h
|
|
@@ -105,6 +105,12 @@ struct drbg_test_data {
|
|
struct drbg_string *testentropy; /* TEST PARAMETER: test entropy */
|
|
};
|
|
|
|
+enum drbg_seed_state {
|
|
+ DRBG_SEED_STATE_UNSEEDED,
|
|
+ DRBG_SEED_STATE_PARTIAL, /* Seeded with !rng_is_initialized() */
|
|
+ DRBG_SEED_STATE_FULL,
|
|
+};
|
|
+
|
|
struct drbg_state {
|
|
struct mutex drbg_mutex; /* lock around DRBG */
|
|
unsigned char *V; /* internal state 10.1.1.1 1a) */
|
|
@@ -127,16 +133,14 @@ struct drbg_state {
|
|
struct crypto_wait ctr_wait; /* CTR mode async wait obj */
|
|
struct scatterlist sg_in, sg_out; /* CTR mode SGLs */
|
|
|
|
- bool seeded; /* DRBG fully seeded? */
|
|
+ enum drbg_seed_state seeded; /* DRBG fully seeded? */
|
|
bool pr; /* Prediction resistance enabled? */
|
|
bool fips_primed; /* Continuous test primed? */
|
|
unsigned char *prev; /* FIPS 140-2 continuous test value */
|
|
- struct work_struct seed_work; /* asynchronous seeding support */
|
|
struct crypto_rng *jent;
|
|
const struct drbg_state_ops *d_ops;
|
|
const struct drbg_core *core;
|
|
struct drbg_string test_data;
|
|
- struct random_ready_callback random_ready;
|
|
};
|
|
|
|
static inline __u8 drbg_statelen(struct drbg_state *drbg)
|
|
@@ -184,11 +188,7 @@ static inline size_t drbg_max_addtl(struct drbg_state *drbg)
|
|
static inline size_t drbg_max_requests(struct drbg_state *drbg)
|
|
{
|
|
/* SP800-90A requires 2**48 maximum requests before reseeding */
|
|
-#if (__BITS_PER_LONG == 32)
|
|
- return SIZE_MAX;
|
|
-#else
|
|
- return (1UL<<48);
|
|
-#endif
|
|
+ return (1<<20);
|
|
}
|
|
|
|
/*
|
|
diff --git a/include/crypto/internal/blake2s.h b/include/crypto/internal/blake2s.h
|
|
new file mode 100644
|
|
index 0000000000000..3ba066845b699
|
|
--- /dev/null
|
|
+++ b/include/crypto/internal/blake2s.h
|
|
@@ -0,0 +1,19 @@
|
|
+/* SPDX-License-Identifier: GPL-2.0 OR MIT */
|
|
+
|
|
+#ifndef _CRYPTO_INTERNAL_BLAKE2S_H
|
|
+#define _CRYPTO_INTERNAL_BLAKE2S_H
|
|
+
|
|
+#include <crypto/blake2s.h>
|
|
+
|
|
+void blake2s_compress_generic(struct blake2s_state *state,const u8 *block,
|
|
+ size_t nblocks, const u32 inc);
|
|
+
|
|
+void blake2s_compress_arch(struct blake2s_state *state,const u8 *block,
|
|
+ size_t nblocks, const u32 inc);
|
|
+
|
|
+static inline void blake2s_set_lastblock(struct blake2s_state *state)
|
|
+{
|
|
+ state->f[0] = -1;
|
|
+}
|
|
+
|
|
+#endif /* _CRYPTO_INTERNAL_BLAKE2S_H */
|
|
diff --git a/include/linux/cpuhotplug.h b/include/linux/cpuhotplug.h
|
|
index bd1f23536b1b6..15835f37bd5f2 100644
|
|
--- a/include/linux/cpuhotplug.h
|
|
+++ b/include/linux/cpuhotplug.h
|
|
@@ -60,6 +60,7 @@ enum cpuhp_state {
|
|
CPUHP_LUSTRE_CFS_DEAD,
|
|
CPUHP_AP_ARM_CACHE_B15_RAC_DEAD,
|
|
CPUHP_PADATA_DEAD,
|
|
+ CPUHP_RANDOM_PREPARE,
|
|
CPUHP_WORKQUEUE_PREP,
|
|
CPUHP_POWER_NUMA_PREPARE,
|
|
CPUHP_HRTIMERS_PREPARE,
|
|
@@ -177,6 +178,7 @@ enum cpuhp_state {
|
|
CPUHP_AP_PERF_POWERPC_TRACE_IMC_ONLINE,
|
|
CPUHP_AP_WATCHDOG_ONLINE,
|
|
CPUHP_AP_WORKQUEUE_ONLINE,
|
|
+ CPUHP_AP_RANDOM_ONLINE,
|
|
CPUHP_AP_RCUTREE_ONLINE,
|
|
CPUHP_AP_BASE_CACHEINFO_ONLINE,
|
|
CPUHP_AP_ONLINE_DYN,
|
|
diff --git a/include/linux/hw_random.h b/include/linux/hw_random.h
|
|
index 8e6dd908da216..aa1d4da03538b 100644
|
|
--- a/include/linux/hw_random.h
|
|
+++ b/include/linux/hw_random.h
|
|
@@ -60,7 +60,5 @@ extern int devm_hwrng_register(struct device *dev, struct hwrng *rng);
|
|
/** Unregister a Hardware Random Number Generator driver. */
|
|
extern void hwrng_unregister(struct hwrng *rng);
|
|
extern void devm_hwrng_unregister(struct device *dve, struct hwrng *rng);
|
|
-/** Feed random bits into the pool. */
|
|
-extern void add_hwgenerator_randomness(const char *buffer, size_t count, size_t entropy);
|
|
|
|
#endif /* LINUX_HWRANDOM_H_ */
|
|
diff --git a/include/linux/mm.h b/include/linux/mm.h
|
|
index a7d626b4cad1c..c125fea49752f 100644
|
|
--- a/include/linux/mm.h
|
|
+++ b/include/linux/mm.h
|
|
@@ -2354,6 +2354,7 @@ extern int install_special_mapping(struct mm_struct *mm,
|
|
unsigned long flags, struct page **pages);
|
|
|
|
unsigned long randomize_stack_top(unsigned long stack_top);
|
|
+unsigned long randomize_page(unsigned long start, unsigned long range);
|
|
|
|
extern unsigned long get_unmapped_area(struct file *, unsigned long, unsigned long, unsigned long, unsigned long);
|
|
|
|
diff --git a/include/linux/prandom.h b/include/linux/prandom.h
|
|
index e20339c78a84c..709e8e69fb39b 100644
|
|
--- a/include/linux/prandom.h
|
|
+++ b/include/linux/prandom.h
|
|
@@ -10,6 +10,7 @@
|
|
|
|
#include <linux/types.h>
|
|
#include <linux/percpu.h>
|
|
+#include <linux/siphash.h>
|
|
|
|
u32 prandom_u32(void);
|
|
void prandom_bytes(void *buf, size_t nbytes);
|
|
@@ -21,15 +22,10 @@ void prandom_reseed_late(void);
|
|
* The core SipHash round function. Each line can be executed in
|
|
* parallel given enough CPU resources.
|
|
*/
|
|
-#define PRND_SIPROUND(v0, v1, v2, v3) ( \
|
|
- v0 += v1, v1 = rol64(v1, 13), v2 += v3, v3 = rol64(v3, 16), \
|
|
- v1 ^= v0, v0 = rol64(v0, 32), v3 ^= v2, \
|
|
- v0 += v3, v3 = rol64(v3, 21), v2 += v1, v1 = rol64(v1, 17), \
|
|
- v3 ^= v0, v1 ^= v2, v2 = rol64(v2, 32) \
|
|
-)
|
|
+#define PRND_SIPROUND(v0, v1, v2, v3) SIPHASH_PERMUTATION(v0, v1, v2, v3)
|
|
|
|
-#define PRND_K0 (0x736f6d6570736575 ^ 0x6c7967656e657261)
|
|
-#define PRND_K1 (0x646f72616e646f6d ^ 0x7465646279746573)
|
|
+#define PRND_K0 (SIPHASH_CONST_0 ^ SIPHASH_CONST_2)
|
|
+#define PRND_K1 (SIPHASH_CONST_1 ^ SIPHASH_CONST_3)
|
|
|
|
#elif BITS_PER_LONG == 32
|
|
/*
|
|
@@ -37,14 +33,9 @@ void prandom_reseed_late(void);
|
|
* This is weaker, but 32-bit machines are not used for high-traffic
|
|
* applications, so there is less output for an attacker to analyze.
|
|
*/
|
|
-#define PRND_SIPROUND(v0, v1, v2, v3) ( \
|
|
- v0 += v1, v1 = rol32(v1, 5), v2 += v3, v3 = rol32(v3, 8), \
|
|
- v1 ^= v0, v0 = rol32(v0, 16), v3 ^= v2, \
|
|
- v0 += v3, v3 = rol32(v3, 7), v2 += v1, v1 = rol32(v1, 13), \
|
|
- v3 ^= v0, v1 ^= v2, v2 = rol32(v2, 16) \
|
|
-)
|
|
-#define PRND_K0 0x6c796765
|
|
-#define PRND_K1 0x74656462
|
|
+#define PRND_SIPROUND(v0, v1, v2, v3) HSIPHASH_PERMUTATION(v0, v1, v2, v3)
|
|
+#define PRND_K0 (HSIPHASH_CONST_0 ^ HSIPHASH_CONST_2)
|
|
+#define PRND_K1 (HSIPHASH_CONST_1 ^ HSIPHASH_CONST_3)
|
|
|
|
#else
|
|
#error Unsupported BITS_PER_LONG
|
|
diff --git a/include/linux/random.h b/include/linux/random.h
|
|
index 5b3ec7d2791f8..3feafab498ad9 100644
|
|
--- a/include/linux/random.h
|
|
+++ b/include/linux/random.h
|
|
@@ -1,52 +1,35 @@
|
|
/* SPDX-License-Identifier: GPL-2.0 */
|
|
-/*
|
|
- * include/linux/random.h
|
|
- *
|
|
- * Include file for the random number generator.
|
|
- */
|
|
+
|
|
#ifndef _LINUX_RANDOM_H
|
|
#define _LINUX_RANDOM_H
|
|
|
|
+#include <linux/bug.h>
|
|
+#include <linux/kernel.h>
|
|
#include <linux/list.h>
|
|
#include <linux/once.h>
|
|
|
|
#include <uapi/linux/random.h>
|
|
|
|
-struct random_ready_callback {
|
|
- struct list_head list;
|
|
- void (*func)(struct random_ready_callback *rdy);
|
|
- struct module *owner;
|
|
-};
|
|
+struct notifier_block;
|
|
|
|
-extern void add_device_randomness(const void *, unsigned int);
|
|
-extern void add_bootloader_randomness(const void *, unsigned int);
|
|
+void add_device_randomness(const void *buf, size_t len);
|
|
+void __init add_bootloader_randomness(const void *buf, size_t len);
|
|
+void add_input_randomness(unsigned int type, unsigned int code,
|
|
+ unsigned int value) __latent_entropy;
|
|
+void add_interrupt_randomness(int irq) __latent_entropy;
|
|
+void add_hwgenerator_randomness(const void *buf, size_t len, size_t entropy);
|
|
|
|
#if defined(LATENT_ENTROPY_PLUGIN) && !defined(__CHECKER__)
|
|
static inline void add_latent_entropy(void)
|
|
{
|
|
- add_device_randomness((const void *)&latent_entropy,
|
|
- sizeof(latent_entropy));
|
|
+ add_device_randomness((const void *)&latent_entropy, sizeof(latent_entropy));
|
|
}
|
|
#else
|
|
-static inline void add_latent_entropy(void) {}
|
|
-#endif
|
|
-
|
|
-extern void add_input_randomness(unsigned int type, unsigned int code,
|
|
- unsigned int value) __latent_entropy;
|
|
-extern void add_interrupt_randomness(int irq, int irq_flags) __latent_entropy;
|
|
-
|
|
-extern void get_random_bytes(void *buf, int nbytes);
|
|
-extern int wait_for_random_bytes(void);
|
|
-extern int __init rand_initialize(void);
|
|
-extern bool rng_is_initialized(void);
|
|
-extern int add_random_ready_callback(struct random_ready_callback *rdy);
|
|
-extern void del_random_ready_callback(struct random_ready_callback *rdy);
|
|
-extern int __must_check get_random_bytes_arch(void *buf, int nbytes);
|
|
-
|
|
-#ifndef MODULE
|
|
-extern const struct file_operations random_fops, urandom_fops;
|
|
+static inline void add_latent_entropy(void) { }
|
|
#endif
|
|
|
|
+void get_random_bytes(void *buf, size_t len);
|
|
+size_t __must_check get_random_bytes_arch(void *buf, size_t len);
|
|
u32 get_random_u32(void);
|
|
u64 get_random_u64(void);
|
|
static inline unsigned int get_random_int(void)
|
|
@@ -78,36 +61,38 @@ static inline unsigned long get_random_long(void)
|
|
|
|
static inline unsigned long get_random_canary(void)
|
|
{
|
|
- unsigned long val = get_random_long();
|
|
-
|
|
- return val & CANARY_MASK;
|
|
+ return get_random_long() & CANARY_MASK;
|
|
}
|
|
|
|
+int __init random_init(const char *command_line);
|
|
+bool rng_is_initialized(void);
|
|
+int wait_for_random_bytes(void);
|
|
+int register_random_ready_notifier(struct notifier_block *nb);
|
|
+int unregister_random_ready_notifier(struct notifier_block *nb);
|
|
+
|
|
/* Calls wait_for_random_bytes() and then calls get_random_bytes(buf, nbytes).
|
|
* Returns the result of the call to wait_for_random_bytes. */
|
|
-static inline int get_random_bytes_wait(void *buf, int nbytes)
|
|
+static inline int get_random_bytes_wait(void *buf, size_t nbytes)
|
|
{
|
|
int ret = wait_for_random_bytes();
|
|
get_random_bytes(buf, nbytes);
|
|
return ret;
|
|
}
|
|
|
|
-#define declare_get_random_var_wait(var) \
|
|
- static inline int get_random_ ## var ## _wait(var *out) { \
|
|
+#define declare_get_random_var_wait(name, ret_type) \
|
|
+ static inline int get_random_ ## name ## _wait(ret_type *out) { \
|
|
int ret = wait_for_random_bytes(); \
|
|
if (unlikely(ret)) \
|
|
return ret; \
|
|
- *out = get_random_ ## var(); \
|
|
+ *out = get_random_ ## name(); \
|
|
return 0; \
|
|
}
|
|
-declare_get_random_var_wait(u32)
|
|
-declare_get_random_var_wait(u64)
|
|
-declare_get_random_var_wait(int)
|
|
-declare_get_random_var_wait(long)
|
|
+declare_get_random_var_wait(u32, u32)
|
|
+declare_get_random_var_wait(u64, u32)
|
|
+declare_get_random_var_wait(int, unsigned int)
|
|
+declare_get_random_var_wait(long, unsigned long)
|
|
#undef declare_get_random_var
|
|
|
|
-unsigned long randomize_page(unsigned long start, unsigned long range);
|
|
-
|
|
/*
|
|
* This is designed to be standalone for just prandom
|
|
* users, but for now we include it from <linux/random.h>
|
|
@@ -118,30 +103,39 @@ unsigned long randomize_page(unsigned long start, unsigned long range);
|
|
#ifdef CONFIG_ARCH_RANDOM
|
|
# include <asm/archrandom.h>
|
|
#else
|
|
-static inline bool arch_get_random_long(unsigned long *v)
|
|
-{
|
|
- return 0;
|
|
-}
|
|
-static inline bool arch_get_random_int(unsigned int *v)
|
|
-{
|
|
- return 0;
|
|
-}
|
|
-static inline bool arch_has_random(void)
|
|
-{
|
|
- return 0;
|
|
-}
|
|
-static inline bool arch_get_random_seed_long(unsigned long *v)
|
|
-{
|
|
- return 0;
|
|
-}
|
|
-static inline bool arch_get_random_seed_int(unsigned int *v)
|
|
+static inline bool __must_check arch_get_random_long(unsigned long *v) { return false; }
|
|
+static inline bool __must_check arch_get_random_int(unsigned int *v) { return false; }
|
|
+static inline bool __must_check arch_get_random_seed_long(unsigned long *v) { return false; }
|
|
+static inline bool __must_check arch_get_random_seed_int(unsigned int *v) { return false; }
|
|
+#endif
|
|
+
|
|
+/*
|
|
+ * Called from the boot CPU during startup; not valid to call once
|
|
+ * secondary CPUs are up and preemption is possible.
|
|
+ */
|
|
+#ifndef arch_get_random_seed_long_early
|
|
+static inline bool __init arch_get_random_seed_long_early(unsigned long *v)
|
|
{
|
|
- return 0;
|
|
+ WARN_ON(system_state != SYSTEM_BOOTING);
|
|
+ return arch_get_random_seed_long(v);
|
|
}
|
|
-static inline bool arch_has_random_seed(void)
|
|
+#endif
|
|
+
|
|
+#ifndef arch_get_random_long_early
|
|
+static inline bool __init arch_get_random_long_early(unsigned long *v)
|
|
{
|
|
- return 0;
|
|
+ WARN_ON(system_state != SYSTEM_BOOTING);
|
|
+ return arch_get_random_long(v);
|
|
}
|
|
#endif
|
|
|
|
+#ifdef CONFIG_SMP
|
|
+int random_prepare_cpu(unsigned int cpu);
|
|
+int random_online_cpu(unsigned int cpu);
|
|
+#endif
|
|
+
|
|
+#ifndef MODULE
|
|
+extern const struct file_operations random_fops, urandom_fops;
|
|
+#endif
|
|
+
|
|
#endif /* _LINUX_RANDOM_H */
|
|
diff --git a/include/linux/siphash.h b/include/linux/siphash.h
|
|
index 0cda61855d907..0bb5ecd507bef 100644
|
|
--- a/include/linux/siphash.h
|
|
+++ b/include/linux/siphash.h
|
|
@@ -136,4 +136,32 @@ static inline u32 hsiphash(const void *data, size_t len,
|
|
return ___hsiphash_aligned(data, len, key);
|
|
}
|
|
|
|
+/*
|
|
+ * These macros expose the raw SipHash and HalfSipHash permutations.
|
|
+ * Do not use them directly! If you think you have a use for them,
|
|
+ * be sure to CC the maintainer of this file explaining why.
|
|
+ */
|
|
+
|
|
+#define SIPHASH_PERMUTATION(a, b, c, d) ( \
|
|
+ (a) += (b), (b) = rol64((b), 13), (b) ^= (a), (a) = rol64((a), 32), \
|
|
+ (c) += (d), (d) = rol64((d), 16), (d) ^= (c), \
|
|
+ (a) += (d), (d) = rol64((d), 21), (d) ^= (a), \
|
|
+ (c) += (b), (b) = rol64((b), 17), (b) ^= (c), (c) = rol64((c), 32))
|
|
+
|
|
+#define SIPHASH_CONST_0 0x736f6d6570736575ULL
|
|
+#define SIPHASH_CONST_1 0x646f72616e646f6dULL
|
|
+#define SIPHASH_CONST_2 0x6c7967656e657261ULL
|
|
+#define SIPHASH_CONST_3 0x7465646279746573ULL
|
|
+
|
|
+#define HSIPHASH_PERMUTATION(a, b, c, d) ( \
|
|
+ (a) += (b), (b) = rol32((b), 5), (b) ^= (a), (a) = rol32((a), 16), \
|
|
+ (c) += (d), (d) = rol32((d), 8), (d) ^= (c), \
|
|
+ (a) += (d), (d) = rol32((d), 7), (d) ^= (a), \
|
|
+ (c) += (b), (b) = rol32((b), 13), (b) ^= (c), (c) = rol32((c), 16))
|
|
+
|
|
+#define HSIPHASH_CONST_0 0U
|
|
+#define HSIPHASH_CONST_1 0U
|
|
+#define HSIPHASH_CONST_2 0x6c796765U
|
|
+#define HSIPHASH_CONST_3 0x74656462U
|
|
+
|
|
#endif /* _LINUX_SIPHASH_H */
|
|
diff --git a/include/linux/timex.h b/include/linux/timex.h
|
|
index ce08597636705..2efab9a806a9d 100644
|
|
--- a/include/linux/timex.h
|
|
+++ b/include/linux/timex.h
|
|
@@ -62,6 +62,8 @@
|
|
#include <linux/types.h>
|
|
#include <linux/param.h>
|
|
|
|
+unsigned long random_get_entropy_fallback(void);
|
|
+
|
|
#include <asm/timex.h>
|
|
|
|
#ifndef random_get_entropy
|
|
@@ -74,8 +76,14 @@
|
|
*
|
|
* By default we use get_cycles() for this purpose, but individual
|
|
* architectures may override this in their asm/timex.h header file.
|
|
+ * If a given arch does not have get_cycles(), then we fallback to
|
|
+ * using random_get_entropy_fallback().
|
|
*/
|
|
-#define random_get_entropy() get_cycles()
|
|
+#ifdef get_cycles
|
|
+#define random_get_entropy() ((unsigned long)get_cycles())
|
|
+#else
|
|
+#define random_get_entropy() random_get_entropy_fallback()
|
|
+#endif
|
|
#endif
|
|
|
|
/*
|
|
diff --git a/include/trace/events/random.h b/include/trace/events/random.h
|
|
deleted file mode 100644
|
|
index 32c10a515e2d5..0000000000000
|
|
--- a/include/trace/events/random.h
|
|
+++ /dev/null
|
|
@@ -1,313 +0,0 @@
|
|
-/* SPDX-License-Identifier: GPL-2.0 */
|
|
-#undef TRACE_SYSTEM
|
|
-#define TRACE_SYSTEM random
|
|
-
|
|
-#if !defined(_TRACE_RANDOM_H) || defined(TRACE_HEADER_MULTI_READ)
|
|
-#define _TRACE_RANDOM_H
|
|
-
|
|
-#include <linux/writeback.h>
|
|
-#include <linux/tracepoint.h>
|
|
-
|
|
-TRACE_EVENT(add_device_randomness,
|
|
- TP_PROTO(int bytes, unsigned long IP),
|
|
-
|
|
- TP_ARGS(bytes, IP),
|
|
-
|
|
- TP_STRUCT__entry(
|
|
- __field( int, bytes )
|
|
- __field(unsigned long, IP )
|
|
- ),
|
|
-
|
|
- TP_fast_assign(
|
|
- __entry->bytes = bytes;
|
|
- __entry->IP = IP;
|
|
- ),
|
|
-
|
|
- TP_printk("bytes %d caller %pS",
|
|
- __entry->bytes, (void *)__entry->IP)
|
|
-);
|
|
-
|
|
-DECLARE_EVENT_CLASS(random__mix_pool_bytes,
|
|
- TP_PROTO(const char *pool_name, int bytes, unsigned long IP),
|
|
-
|
|
- TP_ARGS(pool_name, bytes, IP),
|
|
-
|
|
- TP_STRUCT__entry(
|
|
- __field( const char *, pool_name )
|
|
- __field( int, bytes )
|
|
- __field(unsigned long, IP )
|
|
- ),
|
|
-
|
|
- TP_fast_assign(
|
|
- __entry->pool_name = pool_name;
|
|
- __entry->bytes = bytes;
|
|
- __entry->IP = IP;
|
|
- ),
|
|
-
|
|
- TP_printk("%s pool: bytes %d caller %pS",
|
|
- __entry->pool_name, __entry->bytes, (void *)__entry->IP)
|
|
-);
|
|
-
|
|
-DEFINE_EVENT(random__mix_pool_bytes, mix_pool_bytes,
|
|
- TP_PROTO(const char *pool_name, int bytes, unsigned long IP),
|
|
-
|
|
- TP_ARGS(pool_name, bytes, IP)
|
|
-);
|
|
-
|
|
-DEFINE_EVENT(random__mix_pool_bytes, mix_pool_bytes_nolock,
|
|
- TP_PROTO(const char *pool_name, int bytes, unsigned long IP),
|
|
-
|
|
- TP_ARGS(pool_name, bytes, IP)
|
|
-);
|
|
-
|
|
-TRACE_EVENT(credit_entropy_bits,
|
|
- TP_PROTO(const char *pool_name, int bits, int entropy_count,
|
|
- unsigned long IP),
|
|
-
|
|
- TP_ARGS(pool_name, bits, entropy_count, IP),
|
|
-
|
|
- TP_STRUCT__entry(
|
|
- __field( const char *, pool_name )
|
|
- __field( int, bits )
|
|
- __field( int, entropy_count )
|
|
- __field(unsigned long, IP )
|
|
- ),
|
|
-
|
|
- TP_fast_assign(
|
|
- __entry->pool_name = pool_name;
|
|
- __entry->bits = bits;
|
|
- __entry->entropy_count = entropy_count;
|
|
- __entry->IP = IP;
|
|
- ),
|
|
-
|
|
- TP_printk("%s pool: bits %d entropy_count %d caller %pS",
|
|
- __entry->pool_name, __entry->bits,
|
|
- __entry->entropy_count, (void *)__entry->IP)
|
|
-);
|
|
-
|
|
-TRACE_EVENT(push_to_pool,
|
|
- TP_PROTO(const char *pool_name, int pool_bits, int input_bits),
|
|
-
|
|
- TP_ARGS(pool_name, pool_bits, input_bits),
|
|
-
|
|
- TP_STRUCT__entry(
|
|
- __field( const char *, pool_name )
|
|
- __field( int, pool_bits )
|
|
- __field( int, input_bits )
|
|
- ),
|
|
-
|
|
- TP_fast_assign(
|
|
- __entry->pool_name = pool_name;
|
|
- __entry->pool_bits = pool_bits;
|
|
- __entry->input_bits = input_bits;
|
|
- ),
|
|
-
|
|
- TP_printk("%s: pool_bits %d input_pool_bits %d",
|
|
- __entry->pool_name, __entry->pool_bits,
|
|
- __entry->input_bits)
|
|
-);
|
|
-
|
|
-TRACE_EVENT(debit_entropy,
|
|
- TP_PROTO(const char *pool_name, int debit_bits),
|
|
-
|
|
- TP_ARGS(pool_name, debit_bits),
|
|
-
|
|
- TP_STRUCT__entry(
|
|
- __field( const char *, pool_name )
|
|
- __field( int, debit_bits )
|
|
- ),
|
|
-
|
|
- TP_fast_assign(
|
|
- __entry->pool_name = pool_name;
|
|
- __entry->debit_bits = debit_bits;
|
|
- ),
|
|
-
|
|
- TP_printk("%s: debit_bits %d", __entry->pool_name,
|
|
- __entry->debit_bits)
|
|
-);
|
|
-
|
|
-TRACE_EVENT(add_input_randomness,
|
|
- TP_PROTO(int input_bits),
|
|
-
|
|
- TP_ARGS(input_bits),
|
|
-
|
|
- TP_STRUCT__entry(
|
|
- __field( int, input_bits )
|
|
- ),
|
|
-
|
|
- TP_fast_assign(
|
|
- __entry->input_bits = input_bits;
|
|
- ),
|
|
-
|
|
- TP_printk("input_pool_bits %d", __entry->input_bits)
|
|
-);
|
|
-
|
|
-TRACE_EVENT(add_disk_randomness,
|
|
- TP_PROTO(dev_t dev, int input_bits),
|
|
-
|
|
- TP_ARGS(dev, input_bits),
|
|
-
|
|
- TP_STRUCT__entry(
|
|
- __field( dev_t, dev )
|
|
- __field( int, input_bits )
|
|
- ),
|
|
-
|
|
- TP_fast_assign(
|
|
- __entry->dev = dev;
|
|
- __entry->input_bits = input_bits;
|
|
- ),
|
|
-
|
|
- TP_printk("dev %d,%d input_pool_bits %d", MAJOR(__entry->dev),
|
|
- MINOR(__entry->dev), __entry->input_bits)
|
|
-);
|
|
-
|
|
-TRACE_EVENT(xfer_secondary_pool,
|
|
- TP_PROTO(const char *pool_name, int xfer_bits, int request_bits,
|
|
- int pool_entropy, int input_entropy),
|
|
-
|
|
- TP_ARGS(pool_name, xfer_bits, request_bits, pool_entropy,
|
|
- input_entropy),
|
|
-
|
|
- TP_STRUCT__entry(
|
|
- __field( const char *, pool_name )
|
|
- __field( int, xfer_bits )
|
|
- __field( int, request_bits )
|
|
- __field( int, pool_entropy )
|
|
- __field( int, input_entropy )
|
|
- ),
|
|
-
|
|
- TP_fast_assign(
|
|
- __entry->pool_name = pool_name;
|
|
- __entry->xfer_bits = xfer_bits;
|
|
- __entry->request_bits = request_bits;
|
|
- __entry->pool_entropy = pool_entropy;
|
|
- __entry->input_entropy = input_entropy;
|
|
- ),
|
|
-
|
|
- TP_printk("pool %s xfer_bits %d request_bits %d pool_entropy %d "
|
|
- "input_entropy %d", __entry->pool_name, __entry->xfer_bits,
|
|
- __entry->request_bits, __entry->pool_entropy,
|
|
- __entry->input_entropy)
|
|
-);
|
|
-
|
|
-DECLARE_EVENT_CLASS(random__get_random_bytes,
|
|
- TP_PROTO(int nbytes, unsigned long IP),
|
|
-
|
|
- TP_ARGS(nbytes, IP),
|
|
-
|
|
- TP_STRUCT__entry(
|
|
- __field( int, nbytes )
|
|
- __field(unsigned long, IP )
|
|
- ),
|
|
-
|
|
- TP_fast_assign(
|
|
- __entry->nbytes = nbytes;
|
|
- __entry->IP = IP;
|
|
- ),
|
|
-
|
|
- TP_printk("nbytes %d caller %pS", __entry->nbytes, (void *)__entry->IP)
|
|
-);
|
|
-
|
|
-DEFINE_EVENT(random__get_random_bytes, get_random_bytes,
|
|
- TP_PROTO(int nbytes, unsigned long IP),
|
|
-
|
|
- TP_ARGS(nbytes, IP)
|
|
-);
|
|
-
|
|
-DEFINE_EVENT(random__get_random_bytes, get_random_bytes_arch,
|
|
- TP_PROTO(int nbytes, unsigned long IP),
|
|
-
|
|
- TP_ARGS(nbytes, IP)
|
|
-);
|
|
-
|
|
-DECLARE_EVENT_CLASS(random__extract_entropy,
|
|
- TP_PROTO(const char *pool_name, int nbytes, int entropy_count,
|
|
- unsigned long IP),
|
|
-
|
|
- TP_ARGS(pool_name, nbytes, entropy_count, IP),
|
|
-
|
|
- TP_STRUCT__entry(
|
|
- __field( const char *, pool_name )
|
|
- __field( int, nbytes )
|
|
- __field( int, entropy_count )
|
|
- __field(unsigned long, IP )
|
|
- ),
|
|
-
|
|
- TP_fast_assign(
|
|
- __entry->pool_name = pool_name;
|
|
- __entry->nbytes = nbytes;
|
|
- __entry->entropy_count = entropy_count;
|
|
- __entry->IP = IP;
|
|
- ),
|
|
-
|
|
- TP_printk("%s pool: nbytes %d entropy_count %d caller %pS",
|
|
- __entry->pool_name, __entry->nbytes, __entry->entropy_count,
|
|
- (void *)__entry->IP)
|
|
-);
|
|
-
|
|
-
|
|
-DEFINE_EVENT(random__extract_entropy, extract_entropy,
|
|
- TP_PROTO(const char *pool_name, int nbytes, int entropy_count,
|
|
- unsigned long IP),
|
|
-
|
|
- TP_ARGS(pool_name, nbytes, entropy_count, IP)
|
|
-);
|
|
-
|
|
-DEFINE_EVENT(random__extract_entropy, extract_entropy_user,
|
|
- TP_PROTO(const char *pool_name, int nbytes, int entropy_count,
|
|
- unsigned long IP),
|
|
-
|
|
- TP_ARGS(pool_name, nbytes, entropy_count, IP)
|
|
-);
|
|
-
|
|
-TRACE_EVENT(random_read,
|
|
- TP_PROTO(int got_bits, int need_bits, int pool_left, int input_left),
|
|
-
|
|
- TP_ARGS(got_bits, need_bits, pool_left, input_left),
|
|
-
|
|
- TP_STRUCT__entry(
|
|
- __field( int, got_bits )
|
|
- __field( int, need_bits )
|
|
- __field( int, pool_left )
|
|
- __field( int, input_left )
|
|
- ),
|
|
-
|
|
- TP_fast_assign(
|
|
- __entry->got_bits = got_bits;
|
|
- __entry->need_bits = need_bits;
|
|
- __entry->pool_left = pool_left;
|
|
- __entry->input_left = input_left;
|
|
- ),
|
|
-
|
|
- TP_printk("got_bits %d still_needed_bits %d "
|
|
- "blocking_pool_entropy_left %d input_entropy_left %d",
|
|
- __entry->got_bits, __entry->got_bits, __entry->pool_left,
|
|
- __entry->input_left)
|
|
-);
|
|
-
|
|
-TRACE_EVENT(urandom_read,
|
|
- TP_PROTO(int got_bits, int pool_left, int input_left),
|
|
-
|
|
- TP_ARGS(got_bits, pool_left, input_left),
|
|
-
|
|
- TP_STRUCT__entry(
|
|
- __field( int, got_bits )
|
|
- __field( int, pool_left )
|
|
- __field( int, input_left )
|
|
- ),
|
|
-
|
|
- TP_fast_assign(
|
|
- __entry->got_bits = got_bits;
|
|
- __entry->pool_left = pool_left;
|
|
- __entry->input_left = input_left;
|
|
- ),
|
|
-
|
|
- TP_printk("got_bits %d nonblocking_pool_entropy_left %d "
|
|
- "input_entropy_left %d", __entry->got_bits,
|
|
- __entry->pool_left, __entry->input_left)
|
|
-);
|
|
-
|
|
-#endif /* _TRACE_RANDOM_H */
|
|
-
|
|
-/* This part must be outside protection */
|
|
-#include <trace/define_trace.h>
|
|
diff --git a/include/uapi/linux/random.h b/include/uapi/linux/random.h
|
|
index 26ee91300e3ec..dcc1b3e6106fe 100644
|
|
--- a/include/uapi/linux/random.h
|
|
+++ b/include/uapi/linux/random.h
|
|
@@ -48,9 +48,11 @@ struct rand_pool_info {
|
|
* Flags for getrandom(2)
|
|
*
|
|
* GRND_NONBLOCK Don't block and return EAGAIN instead
|
|
- * GRND_RANDOM Use the /dev/random pool instead of /dev/urandom
|
|
+ * GRND_RANDOM No effect
|
|
+ * GRND_INSECURE Return non-cryptographic random bytes
|
|
*/
|
|
#define GRND_NONBLOCK 0x0001
|
|
#define GRND_RANDOM 0x0002
|
|
+#define GRND_INSECURE 0x0004
|
|
|
|
#endif /* _UAPI_LINUX_RANDOM_H */
|
|
diff --git a/init/main.c b/init/main.c
|
|
index d292daabd9a22..a17a111d93362 100644
|
|
--- a/init/main.c
|
|
+++ b/init/main.c
|
|
@@ -680,21 +680,18 @@ asmlinkage __visible void __init start_kernel(void)
|
|
hrtimers_init();
|
|
softirq_init();
|
|
timekeeping_init();
|
|
+ time_init();
|
|
|
|
/*
|
|
* For best initial stack canary entropy, prepare it after:
|
|
* - setup_arch() for any UEFI RNG entropy and boot cmdline access
|
|
- * - timekeeping_init() for ktime entropy used in rand_initialize()
|
|
- * - rand_initialize() to get any arch-specific entropy like RDRAND
|
|
- * - add_latent_entropy() to get any latent entropy
|
|
- * - adding command line entropy
|
|
+ * - timekeeping_init() for ktime entropy used in random_init()
|
|
+ * - time_init() for making random_get_entropy() work on some platforms
|
|
+ * - random_init() to initialize the RNG from from early entropy sources
|
|
*/
|
|
- rand_initialize();
|
|
- add_latent_entropy();
|
|
- add_device_randomness(command_line, strlen(command_line));
|
|
+ random_init(command_line);
|
|
boot_init_stack_canary();
|
|
|
|
- time_init();
|
|
perf_event_init();
|
|
profile_init();
|
|
call_function_init();
|
|
diff --git a/kernel/bpf/stackmap.c b/kernel/bpf/stackmap.c
|
|
index 768ffd6037875..811071c227f11 100644
|
|
--- a/kernel/bpf/stackmap.c
|
|
+++ b/kernel/bpf/stackmap.c
|
|
@@ -117,7 +117,8 @@ static struct bpf_map *stack_map_alloc(union bpf_attr *attr)
|
|
return ERR_PTR(-E2BIG);
|
|
|
|
cost = n_buckets * sizeof(struct stack_map_bucket *) + sizeof(*smap);
|
|
- err = bpf_map_charge_init(&mem, cost);
|
|
+ err = bpf_map_charge_init(&mem, cost + attr->max_entries *
|
|
+ (sizeof(struct stack_map_bucket) + (u64)value_size));
|
|
if (err)
|
|
return ERR_PTR(err);
|
|
|
|
diff --git a/kernel/cpu.c b/kernel/cpu.c
|
|
index 06c009489892f..c08456af0c7fe 100644
|
|
--- a/kernel/cpu.c
|
|
+++ b/kernel/cpu.c
|
|
@@ -33,6 +33,7 @@
|
|
#include <linux/slab.h>
|
|
#include <linux/percpu-rwsem.h>
|
|
#include <linux/cpuset.h>
|
|
+#include <linux/random.h>
|
|
|
|
#include <trace/events/power.h>
|
|
#define CREATE_TRACE_POINTS
|
|
@@ -1459,6 +1460,11 @@ static struct cpuhp_step cpuhp_hp_states[] = {
|
|
.startup.single = perf_event_init_cpu,
|
|
.teardown.single = perf_event_exit_cpu,
|
|
},
|
|
+ [CPUHP_RANDOM_PREPARE] = {
|
|
+ .name = "random:prepare",
|
|
+ .startup.single = random_prepare_cpu,
|
|
+ .teardown.single = NULL,
|
|
+ },
|
|
[CPUHP_WORKQUEUE_PREP] = {
|
|
.name = "workqueue:prepare",
|
|
.startup.single = workqueue_prepare_cpu,
|
|
@@ -1575,6 +1581,11 @@ static struct cpuhp_step cpuhp_hp_states[] = {
|
|
.startup.single = workqueue_online_cpu,
|
|
.teardown.single = workqueue_offline_cpu,
|
|
},
|
|
+ [CPUHP_AP_RANDOM_ONLINE] = {
|
|
+ .name = "random:online",
|
|
+ .startup.single = random_online_cpu,
|
|
+ .teardown.single = NULL,
|
|
+ },
|
|
[CPUHP_AP_RCUTREE_ONLINE] = {
|
|
.name = "RCU/tree:online",
|
|
.startup.single = rcutree_online_cpu,
|
|
diff --git a/kernel/dma/debug.c b/kernel/dma/debug.c
|
|
index 1c133f610f592..9a4837b68e18f 100644
|
|
--- a/kernel/dma/debug.c
|
|
+++ b/kernel/dma/debug.c
|
|
@@ -616,7 +616,7 @@ static void add_dma_entry(struct dma_debug_entry *entry)
|
|
|
|
rc = active_cacheline_insert(entry);
|
|
if (rc == -ENOMEM) {
|
|
- pr_err("cacheline tracking ENOMEM, dma-debug disabled\n");
|
|
+ pr_err_once("cacheline tracking ENOMEM, dma-debug disabled\n");
|
|
global_disable = true;
|
|
}
|
|
|
|
diff --git a/kernel/irq/handle.c b/kernel/irq/handle.c
|
|
index a4ace611f47fe..d2d7559ecbfec 100644
|
|
--- a/kernel/irq/handle.c
|
|
+++ b/kernel/irq/handle.c
|
|
@@ -188,7 +188,7 @@ irqreturn_t handle_irq_event_percpu(struct irq_desc *desc)
|
|
|
|
retval = __handle_irq_event_percpu(desc, &flags);
|
|
|
|
- add_interrupt_randomness(desc->irq_data.irq, flags);
|
|
+ add_interrupt_randomness(desc->irq_data.irq);
|
|
|
|
if (!noirqdebug)
|
|
note_interrupt(desc, retval);
|
|
diff --git a/kernel/time/timekeeping.c b/kernel/time/timekeeping.c
|
|
index 36ed8bad3909e..e23c9e765a5ff 100644
|
|
--- a/kernel/time/timekeeping.c
|
|
+++ b/kernel/time/timekeeping.c
|
|
@@ -17,6 +17,7 @@
|
|
#include <linux/clocksource.h>
|
|
#include <linux/jiffies.h>
|
|
#include <linux/time.h>
|
|
+#include <linux/timex.h>
|
|
#include <linux/tick.h>
|
|
#include <linux/stop_machine.h>
|
|
#include <linux/pvclock_gtod.h>
|
|
@@ -2304,6 +2305,20 @@ static int timekeeping_validate_timex(const struct __kernel_timex *txc)
|
|
return 0;
|
|
}
|
|
|
|
+/**
|
|
+ * random_get_entropy_fallback - Returns the raw clock source value,
|
|
+ * used by random.c for platforms with no valid random_get_entropy().
|
|
+ */
|
|
+unsigned long random_get_entropy_fallback(void)
|
|
+{
|
|
+ struct tk_read_base *tkr = &tk_core.timekeeper.tkr_mono;
|
|
+ struct clocksource *clock = READ_ONCE(tkr->clock);
|
|
+
|
|
+ if (unlikely(timekeeping_suspended || !clock))
|
|
+ return 0;
|
|
+ return clock->read(clock);
|
|
+}
|
|
+EXPORT_SYMBOL_GPL(random_get_entropy_fallback);
|
|
|
|
/**
|
|
* do_adjtimex() - Accessor function to NTP __do_adjtimex function
|
|
diff --git a/lib/Kconfig.debug b/lib/Kconfig.debug
|
|
index a846f03901dbd..dd7044aa1a120 100644
|
|
--- a/lib/Kconfig.debug
|
|
+++ b/lib/Kconfig.debug
|
|
@@ -1292,8 +1292,7 @@ config WARN_ALL_UNSEEDED_RANDOM
|
|
so architecture maintainers really need to do what they can
|
|
to get the CRNG seeded sooner after the system is booted.
|
|
However, since users cannot do anything actionable to
|
|
- address this, by default the kernel will issue only a single
|
|
- warning for the first use of unseeded randomness.
|
|
+ address this, by default this option is disabled.
|
|
|
|
Say Y here if you want to receive warnings for all uses of
|
|
unseeded randomness. This will be of use primarily for
|
|
diff --git a/lib/crypto/Makefile b/lib/crypto/Makefile
|
|
index cbe0b6a6450d7..9d7feabacd1d6 100644
|
|
--- a/lib/crypto/Makefile
|
|
+++ b/lib/crypto/Makefile
|
|
@@ -11,3 +11,9 @@ libdes-y := des.o
|
|
|
|
obj-$(CONFIG_CRYPTO_LIB_SHA256) += libsha256.o
|
|
libsha256-y := sha256.o
|
|
+
|
|
+obj-y += libblake2s.o
|
|
+libblake2s-y += blake2s.o blake2s-generic.o
|
|
+ifneq ($(CONFIG_CRYPTO_MANAGER_DISABLE_TESTS),y)
|
|
+libblake2s-y += blake2s-selftest.o
|
|
+endif
|
|
diff --git a/lib/crypto/blake2s-generic.c b/lib/crypto/blake2s-generic.c
|
|
new file mode 100644
|
|
index 0000000000000..04ff8df245136
|
|
--- /dev/null
|
|
+++ b/lib/crypto/blake2s-generic.c
|
|
@@ -0,0 +1,111 @@
|
|
+// SPDX-License-Identifier: GPL-2.0 OR MIT
|
|
+/*
|
|
+ * Copyright (C) 2015-2019 Jason A. Donenfeld <Jason@zx2c4.com>. All Rights Reserved.
|
|
+ *
|
|
+ * This is an implementation of the BLAKE2s hash and PRF functions.
|
|
+ *
|
|
+ * Information: https://blake2.net/
|
|
+ *
|
|
+ */
|
|
+
|
|
+#include <crypto/internal/blake2s.h>
|
|
+#include <linux/types.h>
|
|
+#include <linux/string.h>
|
|
+#include <linux/kernel.h>
|
|
+#include <linux/module.h>
|
|
+#include <linux/init.h>
|
|
+#include <linux/bug.h>
|
|
+#include <asm/unaligned.h>
|
|
+
|
|
+static const u8 blake2s_sigma[10][16] = {
|
|
+ { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15 },
|
|
+ { 14, 10, 4, 8, 9, 15, 13, 6, 1, 12, 0, 2, 11, 7, 5, 3 },
|
|
+ { 11, 8, 12, 0, 5, 2, 15, 13, 10, 14, 3, 6, 7, 1, 9, 4 },
|
|
+ { 7, 9, 3, 1, 13, 12, 11, 14, 2, 6, 5, 10, 4, 0, 15, 8 },
|
|
+ { 9, 0, 5, 7, 2, 4, 10, 15, 14, 1, 11, 12, 6, 8, 3, 13 },
|
|
+ { 2, 12, 6, 10, 0, 11, 8, 3, 4, 13, 7, 5, 15, 14, 1, 9 },
|
|
+ { 12, 5, 1, 15, 14, 13, 4, 10, 0, 7, 6, 3, 9, 2, 8, 11 },
|
|
+ { 13, 11, 7, 14, 12, 1, 3, 9, 5, 0, 15, 4, 8, 6, 2, 10 },
|
|
+ { 6, 15, 14, 9, 11, 3, 0, 8, 12, 2, 13, 7, 1, 4, 10, 5 },
|
|
+ { 10, 2, 8, 4, 7, 6, 1, 5, 15, 11, 9, 14, 3, 12, 13, 0 },
|
|
+};
|
|
+
|
|
+static inline void blake2s_increment_counter(struct blake2s_state *state,
|
|
+ const u32 inc)
|
|
+{
|
|
+ state->t[0] += inc;
|
|
+ state->t[1] += (state->t[0] < inc);
|
|
+}
|
|
+
|
|
+void blake2s_compress_generic(struct blake2s_state *state,const u8 *block,
|
|
+ size_t nblocks, const u32 inc)
|
|
+{
|
|
+ u32 m[16];
|
|
+ u32 v[16];
|
|
+ int i;
|
|
+
|
|
+ WARN_ON(IS_ENABLED(DEBUG) &&
|
|
+ (nblocks > 1 && inc != BLAKE2S_BLOCK_SIZE));
|
|
+
|
|
+ while (nblocks > 0) {
|
|
+ blake2s_increment_counter(state, inc);
|
|
+ memcpy(m, block, BLAKE2S_BLOCK_SIZE);
|
|
+ le32_to_cpu_array(m, ARRAY_SIZE(m));
|
|
+ memcpy(v, state->h, 32);
|
|
+ v[ 8] = BLAKE2S_IV0;
|
|
+ v[ 9] = BLAKE2S_IV1;
|
|
+ v[10] = BLAKE2S_IV2;
|
|
+ v[11] = BLAKE2S_IV3;
|
|
+ v[12] = BLAKE2S_IV4 ^ state->t[0];
|
|
+ v[13] = BLAKE2S_IV5 ^ state->t[1];
|
|
+ v[14] = BLAKE2S_IV6 ^ state->f[0];
|
|
+ v[15] = BLAKE2S_IV7 ^ state->f[1];
|
|
+
|
|
+#define G(r, i, a, b, c, d) do { \
|
|
+ a += b + m[blake2s_sigma[r][2 * i + 0]]; \
|
|
+ d = ror32(d ^ a, 16); \
|
|
+ c += d; \
|
|
+ b = ror32(b ^ c, 12); \
|
|
+ a += b + m[blake2s_sigma[r][2 * i + 1]]; \
|
|
+ d = ror32(d ^ a, 8); \
|
|
+ c += d; \
|
|
+ b = ror32(b ^ c, 7); \
|
|
+} while (0)
|
|
+
|
|
+#define ROUND(r) do { \
|
|
+ G(r, 0, v[0], v[ 4], v[ 8], v[12]); \
|
|
+ G(r, 1, v[1], v[ 5], v[ 9], v[13]); \
|
|
+ G(r, 2, v[2], v[ 6], v[10], v[14]); \
|
|
+ G(r, 3, v[3], v[ 7], v[11], v[15]); \
|
|
+ G(r, 4, v[0], v[ 5], v[10], v[15]); \
|
|
+ G(r, 5, v[1], v[ 6], v[11], v[12]); \
|
|
+ G(r, 6, v[2], v[ 7], v[ 8], v[13]); \
|
|
+ G(r, 7, v[3], v[ 4], v[ 9], v[14]); \
|
|
+} while (0)
|
|
+ ROUND(0);
|
|
+ ROUND(1);
|
|
+ ROUND(2);
|
|
+ ROUND(3);
|
|
+ ROUND(4);
|
|
+ ROUND(5);
|
|
+ ROUND(6);
|
|
+ ROUND(7);
|
|
+ ROUND(8);
|
|
+ ROUND(9);
|
|
+
|
|
+#undef G
|
|
+#undef ROUND
|
|
+
|
|
+ for (i = 0; i < 8; ++i)
|
|
+ state->h[i] ^= v[i] ^ v[i + 8];
|
|
+
|
|
+ block += BLAKE2S_BLOCK_SIZE;
|
|
+ --nblocks;
|
|
+ }
|
|
+}
|
|
+
|
|
+EXPORT_SYMBOL(blake2s_compress_generic);
|
|
+
|
|
+MODULE_LICENSE("GPL v2");
|
|
+MODULE_DESCRIPTION("BLAKE2s hash function");
|
|
+MODULE_AUTHOR("Jason A. Donenfeld <Jason@zx2c4.com>");
|
|
diff --git a/lib/crypto/blake2s-selftest.c b/lib/crypto/blake2s-selftest.c
|
|
new file mode 100644
|
|
index 0000000000000..7a9edc96ddddf
|
|
--- /dev/null
|
|
+++ b/lib/crypto/blake2s-selftest.c
|
|
@@ -0,0 +1,591 @@
|
|
+// SPDX-License-Identifier: GPL-2.0 OR MIT
|
|
+/*
|
|
+ * Copyright (C) 2015-2019 Jason A. Donenfeld <Jason@zx2c4.com>. All Rights Reserved.
|
|
+ */
|
|
+
|
|
+#include <crypto/blake2s.h>
|
|
+#include <linux/string.h>
|
|
+
|
|
+/*
|
|
+ * blake2s_testvecs[] generated with the program below (using libb2-dev and
|
|
+ * libssl-dev [OpenSSL])
|
|
+ *
|
|
+ * #include <blake2.h>
|
|
+ * #include <stdint.h>
|
|
+ * #include <stdio.h>
|
|
+ *
|
|
+ * #include <openssl/evp.h>
|
|
+ *
|
|
+ * #define BLAKE2S_TESTVEC_COUNT 256
|
|
+ *
|
|
+ * static void print_vec(const uint8_t vec[], int len)
|
|
+ * {
|
|
+ * int i;
|
|
+ *
|
|
+ * printf(" { ");
|
|
+ * for (i = 0; i < len; i++) {
|
|
+ * if (i && (i % 12) == 0)
|
|
+ * printf("\n ");
|
|
+ * printf("0x%02x, ", vec[i]);
|
|
+ * }
|
|
+ * printf("},\n");
|
|
+ * }
|
|
+ *
|
|
+ * int main(void)
|
|
+ * {
|
|
+ * uint8_t key[BLAKE2S_KEYBYTES];
|
|
+ * uint8_t buf[BLAKE2S_TESTVEC_COUNT];
|
|
+ * uint8_t hash[BLAKE2S_OUTBYTES];
|
|
+ * int i, j;
|
|
+ *
|
|
+ * key[0] = key[1] = 1;
|
|
+ * for (i = 2; i < BLAKE2S_KEYBYTES; ++i)
|
|
+ * key[i] = key[i - 2] + key[i - 1];
|
|
+ *
|
|
+ * for (i = 0; i < BLAKE2S_TESTVEC_COUNT; ++i)
|
|
+ * buf[i] = (uint8_t)i;
|
|
+ *
|
|
+ * printf("static const u8 blake2s_testvecs[][BLAKE2S_HASH_SIZE] __initconst = {\n");
|
|
+ *
|
|
+ * for (i = 0; i < BLAKE2S_TESTVEC_COUNT; ++i) {
|
|
+ * int outlen = 1 + i % BLAKE2S_OUTBYTES;
|
|
+ * int keylen = (13 * i) % (BLAKE2S_KEYBYTES + 1);
|
|
+ *
|
|
+ * blake2s(hash, buf, key + BLAKE2S_KEYBYTES - keylen, outlen, i,
|
|
+ * keylen);
|
|
+ * print_vec(hash, outlen);
|
|
+ * }
|
|
+ * printf("};\n\n");
|
|
+ *
|
|
+ * return 0;
|
|
+ *}
|
|
+ */
|
|
+static const u8 blake2s_testvecs[][BLAKE2S_HASH_SIZE] __initconst = {
|
|
+ { 0xa1, },
|
|
+ { 0x7c, 0x89, },
|
|
+ { 0x74, 0x0e, 0xd4, },
|
|
+ { 0x47, 0x0c, 0x21, 0x15, },
|
|
+ { 0x18, 0xd6, 0x9c, 0xa6, 0xc4, },
|
|
+ { 0x13, 0x5d, 0x16, 0x63, 0x2e, 0xf9, },
|
|
+ { 0x2c, 0xb5, 0x04, 0xb7, 0x99, 0xe2, 0x73, },
|
|
+ { 0x9a, 0x0f, 0xd2, 0x39, 0xd6, 0x68, 0x1b, 0x92, },
|
|
+ { 0xc8, 0xde, 0x7a, 0xea, 0x2f, 0xf4, 0xd2, 0xe3, 0x2b, },
|
|
+ { 0x5b, 0xf9, 0x43, 0x52, 0x0c, 0x12, 0xba, 0xb5, 0x93, 0x9f, },
|
|
+ { 0xc6, 0x2c, 0x4e, 0x80, 0xfc, 0x32, 0x5b, 0x33, 0xb8, 0xb8, 0x0a, },
|
|
+ { 0xa7, 0x5c, 0xfd, 0x3a, 0xcc, 0xbf, 0x90, 0xca, 0xb7, 0x97, 0xde, 0xd8, },
|
|
+ { 0x66, 0xca, 0x3c, 0xc4, 0x19, 0xef, 0x92, 0x66, 0x3f, 0x21, 0x8f, 0xda,
|
|
+ 0xb7, },
|
|
+ { 0xba, 0xe5, 0xbb, 0x30, 0x25, 0x94, 0x6d, 0xc3, 0x89, 0x09, 0xc4, 0x25,
|
|
+ 0x52, 0x3e, },
|
|
+ { 0xa2, 0xef, 0x0e, 0x52, 0x0b, 0x5f, 0xa2, 0x01, 0x6d, 0x0a, 0x25, 0xbc,
|
|
+ 0x57, 0xe2, 0x27, },
|
|
+ { 0x4f, 0xe0, 0xf9, 0x52, 0x12, 0xda, 0x84, 0xb7, 0xab, 0xae, 0xb0, 0xa6,
|
|
+ 0x47, 0x2a, 0xc7, 0xf5, },
|
|
+ { 0x56, 0xe7, 0xa8, 0x1c, 0x4c, 0xca, 0xed, 0x90, 0x31, 0xec, 0x87, 0x43,
|
|
+ 0xe7, 0x72, 0x08, 0xec, 0xbe, },
|
|
+ { 0x7e, 0xdf, 0x80, 0x1c, 0x93, 0x33, 0xfd, 0x53, 0x44, 0xba, 0xfd, 0x96,
|
|
+ 0xe1, 0xbb, 0xb5, 0x65, 0xa5, 0x00, },
|
|
+ { 0xec, 0x6b, 0xed, 0xf7, 0x7b, 0x62, 0x1d, 0x7d, 0xf4, 0x82, 0xf3, 0x1e,
|
|
+ 0x18, 0xff, 0x2b, 0xc4, 0x06, 0x20, 0x2a, },
|
|
+ { 0x74, 0x98, 0xd7, 0x68, 0x63, 0xed, 0x87, 0xe4, 0x5d, 0x8d, 0x9e, 0x1d,
|
|
+ 0xfd, 0x2a, 0xbb, 0x86, 0xac, 0xe9, 0x2a, 0x89, },
|
|
+ { 0x89, 0xc3, 0x88, 0xce, 0x2b, 0x33, 0x1e, 0x10, 0xd1, 0x37, 0x20, 0x86,
|
|
+ 0x28, 0x43, 0x70, 0xd9, 0xfb, 0x96, 0xd9, 0xb5, 0xd3, },
|
|
+ { 0xcb, 0x56, 0x74, 0x41, 0x8d, 0x80, 0x01, 0x9a, 0x6b, 0x38, 0xe1, 0x41,
|
|
+ 0xad, 0x9c, 0x62, 0x74, 0xce, 0x35, 0xd5, 0x6c, 0x89, 0x6e, },
|
|
+ { 0x79, 0xaf, 0x94, 0x59, 0x99, 0x26, 0xe1, 0xc9, 0x34, 0xfe, 0x7c, 0x22,
|
|
+ 0xf7, 0x43, 0xd7, 0x65, 0xd4, 0x48, 0x18, 0xac, 0x3d, 0xfd, 0x93, },
|
|
+ { 0x85, 0x0d, 0xff, 0xb8, 0x3e, 0x87, 0x41, 0xb0, 0x95, 0xd3, 0x3d, 0x00,
|
|
+ 0x47, 0x55, 0x9e, 0xd2, 0x69, 0xea, 0xbf, 0xe9, 0x7a, 0x2d, 0x61, 0x45, },
|
|
+ { 0x03, 0xe0, 0x85, 0xec, 0x54, 0xb5, 0x16, 0x53, 0xa8, 0xc4, 0x71, 0xe9,
|
|
+ 0x6a, 0xe7, 0xcb, 0xc4, 0x15, 0x02, 0xfc, 0x34, 0xa4, 0xa4, 0x28, 0x13,
|
|
+ 0xd1, },
|
|
+ { 0xe3, 0x34, 0x4b, 0xe1, 0xd0, 0x4b, 0x55, 0x61, 0x8f, 0xc0, 0x24, 0x05,
|
|
+ 0xe6, 0xe0, 0x3d, 0x70, 0x24, 0x4d, 0xda, 0xb8, 0x91, 0x05, 0x29, 0x07,
|
|
+ 0x01, 0x3e, },
|
|
+ { 0x61, 0xff, 0x01, 0x72, 0xb1, 0x4d, 0xf6, 0xfe, 0xd1, 0xd1, 0x08, 0x74,
|
|
+ 0xe6, 0x91, 0x44, 0xeb, 0x61, 0xda, 0x40, 0xaf, 0xfc, 0x8c, 0x91, 0x6b,
|
|
+ 0xec, 0x13, 0xed, },
|
|
+ { 0xd4, 0x40, 0xd2, 0xa0, 0x7f, 0xc1, 0x58, 0x0c, 0x85, 0xa0, 0x86, 0xc7,
|
|
+ 0x86, 0xb9, 0x61, 0xc9, 0xea, 0x19, 0x86, 0x1f, 0xab, 0x07, 0xce, 0x37,
|
|
+ 0x72, 0x67, 0x09, 0xfc, },
|
|
+ { 0x9e, 0xf8, 0x18, 0x67, 0x93, 0x10, 0x9b, 0x39, 0x75, 0xe8, 0x8b, 0x38,
|
|
+ 0x82, 0x7d, 0xb8, 0xb7, 0xa5, 0xaf, 0xe6, 0x6a, 0x22, 0x5e, 0x1f, 0x9c,
|
|
+ 0x95, 0x29, 0x19, 0xf2, 0x4b, },
|
|
+ { 0xc8, 0x62, 0x25, 0xf5, 0x98, 0xc9, 0xea, 0xe5, 0x29, 0x3a, 0xd3, 0x22,
|
|
+ 0xeb, 0xeb, 0x07, 0x7c, 0x15, 0x07, 0xee, 0x15, 0x61, 0xbb, 0x05, 0x30,
|
|
+ 0x99, 0x7f, 0x11, 0xf6, 0x0a, 0x1d, },
|
|
+ { 0x68, 0x70, 0xf7, 0x90, 0xa1, 0x8b, 0x1f, 0x0f, 0xbb, 0xce, 0xd2, 0x0e,
|
|
+ 0x33, 0x1f, 0x7f, 0xa9, 0x78, 0xa8, 0xa6, 0x81, 0x66, 0xab, 0x8d, 0xcd,
|
|
+ 0x58, 0x55, 0x3a, 0x0b, 0x7a, 0xdb, 0xb5, },
|
|
+ { 0xdd, 0x35, 0xd2, 0xb4, 0xf6, 0xc7, 0xea, 0xab, 0x64, 0x24, 0x4e, 0xfe,
|
|
+ 0xe5, 0x3d, 0x4e, 0x95, 0x8b, 0x6d, 0x6c, 0xbc, 0xb0, 0xf8, 0x88, 0x61,
|
|
+ 0x09, 0xb7, 0x78, 0xa3, 0x31, 0xfe, 0xd9, 0x2f, },
|
|
+ { 0x0a, },
|
|
+ { 0x6e, 0xd4, },
|
|
+ { 0x64, 0xe9, 0xd1, },
|
|
+ { 0x30, 0xdd, 0x71, 0xef, },
|
|
+ { 0x11, 0xb5, 0x0c, 0x87, 0xc9, },
|
|
+ { 0x06, 0x1c, 0x6d, 0x04, 0x82, 0xd0, },
|
|
+ { 0x5c, 0x42, 0x0b, 0xee, 0xc5, 0x9c, 0xb2, },
|
|
+ { 0xe8, 0x29, 0xd6, 0xb4, 0x5d, 0xf7, 0x2b, 0x93, },
|
|
+ { 0x18, 0xca, 0x27, 0x72, 0x43, 0x39, 0x16, 0xbc, 0x6a, },
|
|
+ { 0x39, 0x8f, 0xfd, 0x64, 0xf5, 0x57, 0x23, 0xb0, 0x45, 0xf8, },
|
|
+ { 0xbb, 0x3a, 0x78, 0x6b, 0x02, 0x1d, 0x0b, 0x16, 0xe3, 0xb2, 0x9a, },
|
|
+ { 0xb8, 0xb4, 0x0b, 0xe5, 0xd4, 0x1d, 0x0d, 0x85, 0x49, 0x91, 0x35, 0xfa, },
|
|
+ { 0x6d, 0x48, 0x2a, 0x0c, 0x42, 0x08, 0xbd, 0xa9, 0x78, 0x6f, 0x18, 0xaf,
|
|
+ 0xe2, },
|
|
+ { 0x10, 0x45, 0xd4, 0x58, 0x88, 0xec, 0x4e, 0x1e, 0xf6, 0x14, 0x92, 0x64,
|
|
+ 0x7e, 0xb0, },
|
|
+ { 0x8b, 0x0b, 0x95, 0xee, 0x92, 0xc6, 0x3b, 0x91, 0xf1, 0x1e, 0xeb, 0x51,
|
|
+ 0x98, 0x0a, 0x8d, },
|
|
+ { 0xa3, 0x50, 0x4d, 0xa5, 0x1d, 0x03, 0x68, 0xe9, 0x57, 0x78, 0xd6, 0x04,
|
|
+ 0xf1, 0xc3, 0x94, 0xd8, },
|
|
+ { 0xb8, 0x66, 0x6e, 0xdd, 0x46, 0x15, 0xae, 0x3d, 0x83, 0x7e, 0xcf, 0xe7,
|
|
+ 0x2c, 0xe8, 0x8f, 0xc7, 0x34, },
|
|
+ { 0x2e, 0xc0, 0x1f, 0x29, 0xea, 0xf6, 0xb9, 0xe2, 0xc2, 0x93, 0xeb, 0x41,
|
|
+ 0x0d, 0xf0, 0x0a, 0x13, 0x0e, 0xa2, },
|
|
+ { 0x71, 0xb8, 0x33, 0xa9, 0x1b, 0xac, 0xf1, 0xb5, 0x42, 0x8f, 0x5e, 0x81,
|
|
+ 0x34, 0x43, 0xb7, 0xa4, 0x18, 0x5c, 0x47, },
|
|
+ { 0xda, 0x45, 0xb8, 0x2e, 0x82, 0x1e, 0xc0, 0x59, 0x77, 0x9d, 0xfa, 0xb4,
|
|
+ 0x1c, 0x5e, 0xa0, 0x2b, 0x33, 0x96, 0x5a, 0x58, },
|
|
+ { 0xe3, 0x09, 0x05, 0xa9, 0xeb, 0x48, 0x13, 0xad, 0x71, 0x88, 0x81, 0x9a,
|
|
+ 0x3e, 0x2c, 0xe1, 0x23, 0x99, 0x13, 0x35, 0x9f, 0xb5, },
|
|
+ { 0xb7, 0x86, 0x2d, 0x16, 0xe1, 0x04, 0x00, 0x47, 0x47, 0x61, 0x31, 0xfb,
|
|
+ 0x14, 0xac, 0xd8, 0xe9, 0xe3, 0x49, 0xbd, 0xf7, 0x9c, 0x3f, },
|
|
+ { 0x7f, 0xd9, 0x95, 0xa8, 0xa7, 0xa0, 0xcc, 0xba, 0xef, 0xb1, 0x0a, 0xa9,
|
|
+ 0x21, 0x62, 0x08, 0x0f, 0x1b, 0xff, 0x7b, 0x9d, 0xae, 0xb2, 0x95, },
|
|
+ { 0x85, 0x99, 0xea, 0x33, 0xe0, 0x56, 0xff, 0x13, 0xc6, 0x61, 0x8c, 0xf9,
|
|
+ 0x57, 0x05, 0x03, 0x11, 0xf9, 0xfb, 0x3a, 0xf7, 0xce, 0xbb, 0x52, 0x30, },
|
|
+ { 0xb2, 0x72, 0x9c, 0xf8, 0x77, 0x4e, 0x8f, 0x6b, 0x01, 0x6c, 0xff, 0x4e,
|
|
+ 0x4f, 0x02, 0xd2, 0xbc, 0xeb, 0x51, 0x28, 0x99, 0x50, 0xab, 0xc4, 0x42,
|
|
+ 0xe3, },
|
|
+ { 0x8b, 0x0a, 0xb5, 0x90, 0x8f, 0xf5, 0x7b, 0xdd, 0xba, 0x47, 0x37, 0xc9,
|
|
+ 0x2a, 0xd5, 0x4b, 0x25, 0x08, 0x8b, 0x02, 0x17, 0xa7, 0x9e, 0x6b, 0x6e,
|
|
+ 0xe3, 0x90, },
|
|
+ { 0x90, 0xdd, 0xf7, 0x75, 0xa7, 0xa3, 0x99, 0x5e, 0x5b, 0x7d, 0x75, 0xc3,
|
|
+ 0x39, 0x6b, 0xa0, 0xe2, 0x44, 0x53, 0xb1, 0x9e, 0xc8, 0xf1, 0x77, 0x10,
|
|
+ 0x58, 0x06, 0x9a, },
|
|
+ { 0x99, 0x52, 0xf0, 0x49, 0xa8, 0x8c, 0xec, 0xa6, 0x97, 0x32, 0x13, 0xb5,
|
|
+ 0xf7, 0xa3, 0x8e, 0xfb, 0x4b, 0x59, 0x31, 0x3d, 0x01, 0x59, 0x98, 0x5d,
|
|
+ 0x53, 0x03, 0x1a, 0x39, },
|
|
+ { 0x9f, 0xe0, 0xc2, 0xe5, 0x5d, 0x93, 0xd6, 0x9b, 0x47, 0x8f, 0x9b, 0xe0,
|
|
+ 0x26, 0x35, 0x84, 0x20, 0x1d, 0xc5, 0x53, 0x10, 0x0f, 0x22, 0xb9, 0xb5,
|
|
+ 0xd4, 0x36, 0xb1, 0xac, 0x73, },
|
|
+ { 0x30, 0x32, 0x20, 0x3b, 0x10, 0x28, 0xec, 0x1f, 0x4f, 0x9b, 0x47, 0x59,
|
|
+ 0xeb, 0x7b, 0xee, 0x45, 0xfb, 0x0c, 0x49, 0xd8, 0x3d, 0x69, 0xbd, 0x90,
|
|
+ 0x2c, 0xf0, 0x9e, 0x8d, 0xbf, 0xd5, },
|
|
+ { 0x2a, 0x37, 0x73, 0x7f, 0xf9, 0x96, 0x19, 0xaa, 0x25, 0xd8, 0x13, 0x28,
|
|
+ 0x01, 0x29, 0x89, 0xdf, 0x6e, 0x0c, 0x9b, 0x43, 0x44, 0x51, 0xe9, 0x75,
|
|
+ 0x26, 0x0c, 0xb7, 0x87, 0x66, 0x0b, 0x5f, },
|
|
+ { 0x23, 0xdf, 0x96, 0x68, 0x91, 0x86, 0xd0, 0x93, 0x55, 0x33, 0x24, 0xf6,
|
|
+ 0xba, 0x08, 0x75, 0x5b, 0x59, 0x11, 0x69, 0xb8, 0xb9, 0xe5, 0x2c, 0x77,
|
|
+ 0x02, 0xf6, 0x47, 0xee, 0x81, 0xdd, 0xb9, 0x06, },
|
|
+ { 0x9d, },
|
|
+ { 0x9d, 0x7d, },
|
|
+ { 0xfd, 0xc3, 0xda, },
|
|
+ { 0xe8, 0x82, 0xcd, 0x21, },
|
|
+ { 0xc3, 0x1d, 0x42, 0x4c, 0x74, },
|
|
+ { 0xe9, 0xda, 0xf1, 0xa2, 0xe5, 0x7c, },
|
|
+ { 0x52, 0xb8, 0x6f, 0x81, 0x5c, 0x3a, 0x4c, },
|
|
+ { 0x5b, 0x39, 0x26, 0xfc, 0x92, 0x5e, 0xe0, 0x49, },
|
|
+ { 0x59, 0xe4, 0x7c, 0x93, 0x1c, 0xf9, 0x28, 0x93, 0xde, },
|
|
+ { 0xde, 0xdf, 0xb2, 0x43, 0x61, 0x0b, 0x86, 0x16, 0x4c, 0x2e, },
|
|
+ { 0x14, 0x8f, 0x75, 0x51, 0xaf, 0xb9, 0xee, 0x51, 0x5a, 0xae, 0x23, },
|
|
+ { 0x43, 0x5f, 0x50, 0xd5, 0x70, 0xb0, 0x5b, 0x87, 0xf5, 0xd9, 0xb3, 0x6d, },
|
|
+ { 0x66, 0x0a, 0x64, 0x93, 0x79, 0x71, 0x94, 0x40, 0xb7, 0x68, 0x2d, 0xd3,
|
|
+ 0x63, },
|
|
+ { 0x15, 0x00, 0xc4, 0x0c, 0x7d, 0x1b, 0x10, 0xa9, 0x73, 0x1b, 0x90, 0x6f,
|
|
+ 0xe6, 0xa9, },
|
|
+ { 0x34, 0x75, 0xf3, 0x86, 0x8f, 0x56, 0xcf, 0x2a, 0x0a, 0xf2, 0x62, 0x0a,
|
|
+ 0xf6, 0x0e, 0x20, },
|
|
+ { 0xb1, 0xde, 0xc9, 0xf5, 0xdb, 0xf3, 0x2f, 0x4c, 0xd6, 0x41, 0x7d, 0x39,
|
|
+ 0x18, 0x3e, 0xc7, 0xc3, },
|
|
+ { 0xc5, 0x89, 0xb2, 0xf8, 0xb8, 0xc0, 0xa3, 0xb9, 0x3b, 0x10, 0x6d, 0x7c,
|
|
+ 0x92, 0xfc, 0x7f, 0x34, 0x41, },
|
|
+ { 0xc4, 0xd8, 0xef, 0xba, 0xef, 0xd2, 0xaa, 0xc5, 0x6c, 0x8e, 0x3e, 0xbb,
|
|
+ 0x12, 0xfc, 0x0f, 0x72, 0xbf, 0x0f, },
|
|
+ { 0xdd, 0x91, 0xd1, 0x15, 0x9e, 0x7d, 0xf8, 0xc1, 0xb9, 0x14, 0x63, 0x96,
|
|
+ 0xb5, 0xcb, 0x83, 0x1d, 0x35, 0x1c, 0xec, },
|
|
+ { 0xa9, 0xf8, 0x52, 0xc9, 0x67, 0x76, 0x2b, 0xad, 0xfb, 0xd8, 0x3a, 0xa6,
|
|
+ 0x74, 0x02, 0xae, 0xb8, 0x25, 0x2c, 0x63, 0x49, },
|
|
+ { 0x77, 0x1f, 0x66, 0x70, 0xfd, 0x50, 0x29, 0xaa, 0xeb, 0xdc, 0xee, 0xba,
|
|
+ 0x75, 0x98, 0xdc, 0x93, 0x12, 0x3f, 0xdc, 0x7c, 0x38, },
|
|
+ { 0xe2, 0xe1, 0x89, 0x5c, 0x37, 0x38, 0x6a, 0xa3, 0x40, 0xac, 0x3f, 0xb0,
|
|
+ 0xca, 0xfc, 0xa7, 0xf3, 0xea, 0xf9, 0x0f, 0x5d, 0x8e, 0x39, },
|
|
+ { 0x0f, 0x67, 0xc8, 0x38, 0x01, 0xb1, 0xb7, 0xb8, 0xa2, 0xe7, 0x0a, 0x6d,
|
|
+ 0xd2, 0x63, 0x69, 0x9e, 0xcc, 0xf0, 0xf2, 0xbe, 0x9b, 0x98, 0xdd, },
|
|
+ { 0x13, 0xe1, 0x36, 0x30, 0xfe, 0xc6, 0x01, 0x8a, 0xa1, 0x63, 0x96, 0x59,
|
|
+ 0xc2, 0xa9, 0x68, 0x3f, 0x58, 0xd4, 0x19, 0x0c, 0x40, 0xf3, 0xde, 0x02, },
|
|
+ { 0xa3, 0x9e, 0xce, 0xda, 0x42, 0xee, 0x8c, 0x6c, 0x5a, 0x7d, 0xdc, 0x89,
|
|
+ 0x02, 0x77, 0xdd, 0xe7, 0x95, 0xbb, 0xff, 0x0d, 0xa4, 0xb5, 0x38, 0x1e,
|
|
+ 0xaf, },
|
|
+ { 0x9a, 0xf6, 0xb5, 0x9a, 0x4f, 0xa9, 0x4f, 0x2c, 0x35, 0x3c, 0x24, 0xdc,
|
|
+ 0x97, 0x6f, 0xd9, 0xa1, 0x7d, 0x1a, 0x85, 0x0b, 0xf5, 0xda, 0x2e, 0xe7,
|
|
+ 0xb1, 0x1d, },
|
|
+ { 0x84, 0x1e, 0x8e, 0x3d, 0x45, 0xa5, 0xf2, 0x27, 0xf3, 0x31, 0xfe, 0xb9,
|
|
+ 0xfb, 0xc5, 0x45, 0x99, 0x99, 0xdd, 0x93, 0x43, 0x02, 0xee, 0x58, 0xaf,
|
|
+ 0xee, 0x6a, 0xbe, },
|
|
+ { 0x07, 0x2f, 0xc0, 0xa2, 0x04, 0xc4, 0xab, 0x7c, 0x26, 0xbb, 0xa8, 0xd8,
|
|
+ 0xe3, 0x1c, 0x75, 0x15, 0x64, 0x5d, 0x02, 0x6a, 0xf0, 0x86, 0xe9, 0xcd,
|
|
+ 0x5c, 0xef, 0xa3, 0x25, },
|
|
+ { 0x2f, 0x3b, 0x1f, 0xb5, 0x91, 0x8f, 0x86, 0xe0, 0xdc, 0x31, 0x48, 0xb6,
|
|
+ 0xa1, 0x8c, 0xfd, 0x75, 0xbb, 0x7d, 0x3d, 0xc1, 0xf0, 0x10, 0x9a, 0xd8,
|
|
+ 0x4b, 0x0e, 0xe3, 0x94, 0x9f, },
|
|
+ { 0x29, 0xbb, 0x8f, 0x6c, 0xd1, 0xf2, 0xb6, 0xaf, 0xe5, 0xe3, 0x2d, 0xdc,
|
|
+ 0x6f, 0xa4, 0x53, 0x88, 0xd8, 0xcf, 0x4d, 0x45, 0x42, 0x62, 0xdb, 0xdf,
|
|
+ 0xf8, 0x45, 0xc2, 0x13, 0xec, 0x35, },
|
|
+ { 0x06, 0x3c, 0xe3, 0x2c, 0x15, 0xc6, 0x43, 0x03, 0x81, 0xfb, 0x08, 0x76,
|
|
+ 0x33, 0xcb, 0x02, 0xc1, 0xba, 0x33, 0xe5, 0xe0, 0xd1, 0x92, 0xa8, 0x46,
|
|
+ 0x28, 0x3f, 0x3e, 0x9d, 0x2c, 0x44, 0x54, },
|
|
+ { 0xea, 0xbb, 0x96, 0xf8, 0xd1, 0x8b, 0x04, 0x11, 0x40, 0x78, 0x42, 0x02,
|
|
+ 0x19, 0xd1, 0xbc, 0x65, 0x92, 0xd3, 0xc3, 0xd6, 0xd9, 0x19, 0xe7, 0xc3,
|
|
+ 0x40, 0x97, 0xbd, 0xd4, 0xed, 0xfa, 0x5e, 0x28, },
|
|
+ { 0x02, },
|
|
+ { 0x52, 0xa8, },
|
|
+ { 0x38, 0x25, 0x0d, },
|
|
+ { 0xe3, 0x04, 0xd4, 0x92, },
|
|
+ { 0x97, 0xdb, 0xf7, 0x81, 0xca, },
|
|
+ { 0x8a, 0x56, 0x9d, 0x62, 0x56, 0xcc, },
|
|
+ { 0xa1, 0x8e, 0x3c, 0x72, 0x8f, 0x63, 0x03, },
|
|
+ { 0xf7, 0xf3, 0x39, 0x09, 0x0a, 0xa1, 0xbb, 0x23, },
|
|
+ { 0x6b, 0x03, 0xc0, 0xe9, 0xd9, 0x83, 0x05, 0x22, 0x01, },
|
|
+ { 0x1b, 0x4b, 0xf5, 0xd6, 0x4f, 0x05, 0x75, 0x91, 0x4c, 0x7f, },
|
|
+ { 0x4c, 0x8c, 0x25, 0x20, 0x21, 0xcb, 0xc2, 0x4b, 0x3a, 0x5b, 0x8d, },
|
|
+ { 0x56, 0xe2, 0x77, 0xa0, 0xb6, 0x9f, 0x81, 0xec, 0x83, 0x75, 0xc4, 0xf9, },
|
|
+ { 0x71, 0x70, 0x0f, 0xad, 0x4d, 0x35, 0x81, 0x9d, 0x88, 0x69, 0xf9, 0xaa,
|
|
+ 0xd3, },
|
|
+ { 0x50, 0x6e, 0x86, 0x6e, 0x43, 0xc0, 0xc2, 0x44, 0xc2, 0xe2, 0xa0, 0x1c,
|
|
+ 0xb7, 0x9a, },
|
|
+ { 0xe4, 0x7e, 0x72, 0xc6, 0x12, 0x8e, 0x7c, 0xfc, 0xbd, 0xe2, 0x08, 0x31,
|
|
+ 0x3d, 0x47, 0x3d, },
|
|
+ { 0x08, 0x97, 0x5b, 0x80, 0xae, 0xc4, 0x1d, 0x50, 0x77, 0xdf, 0x1f, 0xd0,
|
|
+ 0x24, 0xf0, 0x17, 0xc0, },
|
|
+ { 0x01, 0xb6, 0x29, 0xf4, 0xaf, 0x78, 0x5f, 0xb6, 0x91, 0xdd, 0x76, 0x76,
|
|
+ 0xd2, 0xfd, 0x0c, 0x47, 0x40, },
|
|
+ { 0xa1, 0xd8, 0x09, 0x97, 0x7a, 0xa6, 0xc8, 0x94, 0xf6, 0x91, 0x7b, 0xae,
|
|
+ 0x2b, 0x9f, 0x0d, 0x83, 0x48, 0xf7, },
|
|
+ { 0x12, 0xd5, 0x53, 0x7d, 0x9a, 0xb0, 0xbe, 0xd9, 0xed, 0xe9, 0x9e, 0xee,
|
|
+ 0x61, 0x5b, 0x42, 0xf2, 0xc0, 0x73, 0xc0, },
|
|
+ { 0xd5, 0x77, 0xd6, 0x5c, 0x6e, 0xa5, 0x69, 0x2b, 0x3b, 0x8c, 0xd6, 0x7d,
|
|
+ 0x1d, 0xbe, 0x2c, 0xa1, 0x02, 0x21, 0xcd, 0x29, },
|
|
+ { 0xa4, 0x98, 0x80, 0xca, 0x22, 0xcf, 0x6a, 0xab, 0x5e, 0x40, 0x0d, 0x61,
|
|
+ 0x08, 0x21, 0xef, 0xc0, 0x6c, 0x52, 0xb4, 0xb0, 0x53, },
|
|
+ { 0xbf, 0xaf, 0x8f, 0x3b, 0x7a, 0x97, 0x33, 0xe5, 0xca, 0x07, 0x37, 0xfd,
|
|
+ 0x15, 0xdf, 0xce, 0x26, 0x2a, 0xb1, 0xa7, 0x0b, 0xb3, 0xac, },
|
|
+ { 0x16, 0x22, 0xe1, 0xbc, 0x99, 0x4e, 0x01, 0xf0, 0xfa, 0xff, 0x8f, 0xa5,
|
|
+ 0x0c, 0x61, 0xb0, 0xad, 0xcc, 0xb1, 0xe1, 0x21, 0x46, 0xfa, 0x2e, },
|
|
+ { 0x11, 0x5b, 0x0b, 0x2b, 0xe6, 0x14, 0xc1, 0xd5, 0x4d, 0x71, 0x5e, 0x17,
|
|
+ 0xea, 0x23, 0xdd, 0x6c, 0xbd, 0x1d, 0xbe, 0x12, 0x1b, 0xee, 0x4c, 0x1a, },
|
|
+ { 0x40, 0x88, 0x22, 0xf3, 0x20, 0x6c, 0xed, 0xe1, 0x36, 0x34, 0x62, 0x2c,
|
|
+ 0x98, 0x83, 0x52, 0xe2, 0x25, 0xee, 0xe9, 0xf5, 0xe1, 0x17, 0xf0, 0x5c,
|
|
+ 0xae, },
|
|
+ { 0xc3, 0x76, 0x37, 0xde, 0x95, 0x8c, 0xca, 0x2b, 0x0c, 0x23, 0xe7, 0xb5,
|
|
+ 0x38, 0x70, 0x61, 0xcc, 0xff, 0xd3, 0x95, 0x7b, 0xf3, 0xff, 0x1f, 0x9d,
|
|
+ 0x59, 0x00, },
|
|
+ { 0x0c, 0x19, 0x52, 0x05, 0x22, 0x53, 0xcb, 0x48, 0xd7, 0x10, 0x0e, 0x7e,
|
|
+ 0x14, 0x69, 0xb5, 0xa2, 0x92, 0x43, 0xa3, 0x9e, 0x4b, 0x8f, 0x51, 0x2c,
|
|
+ 0x5a, 0x2c, 0x3b, },
|
|
+ { 0xe1, 0x9d, 0x70, 0x70, 0x28, 0xec, 0x86, 0x40, 0x55, 0x33, 0x56, 0xda,
|
|
+ 0x88, 0xca, 0xee, 0xc8, 0x6a, 0x20, 0xb1, 0xe5, 0x3d, 0x57, 0xf8, 0x3c,
|
|
+ 0x10, 0x07, 0x2a, 0xc4, },
|
|
+ { 0x0b, 0xae, 0xf1, 0xc4, 0x79, 0xee, 0x1b, 0x3d, 0x27, 0x35, 0x8d, 0x14,
|
|
+ 0xd6, 0xae, 0x4e, 0x3c, 0xe9, 0x53, 0x50, 0xb5, 0xcc, 0x0c, 0xf7, 0xdf,
|
|
+ 0xee, 0xa1, 0x74, 0xd6, 0x71, },
|
|
+ { 0xe6, 0xa4, 0xf4, 0x99, 0x98, 0xb9, 0x80, 0xea, 0x96, 0x7f, 0x4f, 0x33,
|
|
+ 0xcf, 0x74, 0x25, 0x6f, 0x17, 0x6c, 0xbf, 0xf5, 0x5c, 0x38, 0xd0, 0xff,
|
|
+ 0x96, 0xcb, 0x13, 0xf9, 0xdf, 0xfd, },
|
|
+ { 0xbe, 0x92, 0xeb, 0xba, 0x44, 0x2c, 0x24, 0x74, 0xd4, 0x03, 0x27, 0x3c,
|
|
+ 0x5d, 0x5b, 0x03, 0x30, 0x87, 0x63, 0x69, 0xe0, 0xb8, 0x94, 0xf4, 0x44,
|
|
+ 0x7e, 0xad, 0xcd, 0x20, 0x12, 0x16, 0x79, },
|
|
+ { 0x30, 0xf1, 0xc4, 0x8e, 0x05, 0x90, 0x2a, 0x97, 0x63, 0x94, 0x46, 0xff,
|
|
+ 0xce, 0xd8, 0x67, 0xa7, 0xac, 0x33, 0x8c, 0x95, 0xb7, 0xcd, 0xa3, 0x23,
|
|
+ 0x98, 0x9d, 0x76, 0x6c, 0x9d, 0xa8, 0xd6, 0x8a, },
|
|
+ { 0xbe, },
|
|
+ { 0x17, 0x6c, },
|
|
+ { 0x1a, 0x42, 0x4f, },
|
|
+ { 0xba, 0xaf, 0xb7, 0x65, },
|
|
+ { 0xc2, 0x63, 0x43, 0x6a, 0xea, },
|
|
+ { 0xe4, 0x4d, 0xad, 0xf2, 0x0b, 0x02, },
|
|
+ { 0x04, 0xc7, 0xc4, 0x7f, 0xa9, 0x2b, 0xce, },
|
|
+ { 0x66, 0xf6, 0x67, 0xcb, 0x03, 0x53, 0xc8, 0xf1, },
|
|
+ { 0x56, 0xa3, 0x60, 0x78, 0xc9, 0x5f, 0x70, 0x1b, 0x5e, },
|
|
+ { 0x99, 0xff, 0x81, 0x7c, 0x13, 0x3c, 0x29, 0x79, 0x4b, 0x65, },
|
|
+ { 0x51, 0x10, 0x50, 0x93, 0x01, 0x93, 0xb7, 0x01, 0xc9, 0x18, 0xb7, },
|
|
+ { 0x8e, 0x3c, 0x42, 0x1e, 0x5e, 0x7d, 0xc1, 0x50, 0x70, 0x1f, 0x00, 0x98, },
|
|
+ { 0x5f, 0xd9, 0x9b, 0xc8, 0xd7, 0xb2, 0x72, 0x62, 0x1a, 0x1e, 0xba, 0x92,
|
|
+ 0xe9, },
|
|
+ { 0x70, 0x2b, 0xba, 0xfe, 0xad, 0x5d, 0x96, 0x3f, 0x27, 0xc2, 0x41, 0x6d,
|
|
+ 0xc4, 0xb3, },
|
|
+ { 0xae, 0xe0, 0xd5, 0xd4, 0xc7, 0xae, 0x15, 0x5e, 0xdc, 0xdd, 0x33, 0x60,
|
|
+ 0xd7, 0xd3, 0x5e, },
|
|
+ { 0x79, 0x8e, 0xbc, 0x9e, 0x20, 0xb9, 0x19, 0x4b, 0x63, 0x80, 0xf3, 0x16,
|
|
+ 0xaf, 0x39, 0xbd, 0x92, },
|
|
+ { 0xc2, 0x0e, 0x85, 0xa0, 0x0b, 0x9a, 0xb0, 0xec, 0xde, 0x38, 0xd3, 0x10,
|
|
+ 0xd9, 0xa7, 0x66, 0x27, 0xcf, },
|
|
+ { 0x0e, 0x3b, 0x75, 0x80, 0x67, 0x14, 0x0c, 0x02, 0x90, 0xd6, 0xb3, 0x02,
|
|
+ 0x81, 0xf6, 0xa6, 0x87, 0xce, 0x58, },
|
|
+ { 0x79, 0xb5, 0xe9, 0x5d, 0x52, 0x4d, 0xf7, 0x59, 0xf4, 0x2e, 0x27, 0xdd,
|
|
+ 0xb3, 0xed, 0x57, 0x5b, 0x82, 0xea, 0x6f, },
|
|
+ { 0xa2, 0x97, 0xf5, 0x80, 0x02, 0x3d, 0xde, 0xa3, 0xf9, 0xf6, 0xab, 0xe3,
|
|
+ 0x57, 0x63, 0x7b, 0x9b, 0x10, 0x42, 0x6f, 0xf2, },
|
|
+ { 0x12, 0x7a, 0xfc, 0xb7, 0x67, 0x06, 0x0c, 0x78, 0x1a, 0xfe, 0x88, 0x4f,
|
|
+ 0xc6, 0xac, 0x52, 0x96, 0x64, 0x28, 0x97, 0x84, 0x06, },
|
|
+ { 0xc5, 0x04, 0x44, 0x6b, 0xb2, 0xa5, 0xa4, 0x66, 0xe1, 0x76, 0xa2, 0x51,
|
|
+ 0xf9, 0x59, 0x69, 0x97, 0x56, 0x0b, 0xbf, 0x50, 0xb3, 0x34, },
|
|
+ { 0x21, 0x32, 0x6b, 0x42, 0xb5, 0xed, 0x71, 0x8d, 0xf7, 0x5a, 0x35, 0xe3,
|
|
+ 0x90, 0xe2, 0xee, 0xaa, 0x89, 0xf6, 0xc9, 0x9c, 0x4d, 0x73, 0xf4, },
|
|
+ { 0x4c, 0xa6, 0x09, 0xf4, 0x48, 0xe7, 0x46, 0xbc, 0x49, 0xfc, 0xe5, 0xda,
|
|
+ 0xd1, 0x87, 0x13, 0x17, 0x4c, 0x59, 0x71, 0x26, 0x5b, 0x2c, 0x42, 0xb7, },
|
|
+ { 0x13, 0x63, 0xf3, 0x40, 0x02, 0xe5, 0xa3, 0x3a, 0x5e, 0x8e, 0xf8, 0xb6,
|
|
+ 0x8a, 0x49, 0x60, 0x76, 0x34, 0x72, 0x94, 0x73, 0xf6, 0xd9, 0x21, 0x6a,
|
|
+ 0x26, },
|
|
+ { 0xdf, 0x75, 0x16, 0x10, 0x1b, 0x5e, 0x81, 0xc3, 0xc8, 0xde, 0x34, 0x24,
|
|
+ 0xb0, 0x98, 0xeb, 0x1b, 0x8f, 0xa1, 0x9b, 0x05, 0xee, 0xa5, 0xe9, 0x35,
|
|
+ 0xf4, 0x1d, },
|
|
+ { 0xcd, 0x21, 0x93, 0x6e, 0x5b, 0xa0, 0x26, 0x2b, 0x21, 0x0e, 0xa0, 0xb9,
|
|
+ 0x1c, 0xb5, 0xbb, 0xb8, 0xf8, 0x1e, 0xff, 0x5c, 0xa8, 0xf9, 0x39, 0x46,
|
|
+ 0x4e, 0x29, 0x26, },
|
|
+ { 0x73, 0x7f, 0x0e, 0x3b, 0x0b, 0x5c, 0xf9, 0x60, 0xaa, 0x88, 0xa1, 0x09,
|
|
+ 0xb1, 0x5d, 0x38, 0x7b, 0x86, 0x8f, 0x13, 0x7a, 0x8d, 0x72, 0x7a, 0x98,
|
|
+ 0x1a, 0x5b, 0xff, 0xc9, },
|
|
+ { 0xd3, 0x3c, 0x61, 0x71, 0x44, 0x7e, 0x31, 0x74, 0x98, 0x9d, 0x9a, 0xd2,
|
|
+ 0x27, 0xf3, 0x46, 0x43, 0x42, 0x51, 0xd0, 0x5f, 0xe9, 0x1c, 0x5c, 0x69,
|
|
+ 0xbf, 0xf6, 0xbe, 0x3c, 0x40, },
|
|
+ { 0x31, 0x99, 0x31, 0x9f, 0xaa, 0x43, 0x2e, 0x77, 0x3e, 0x74, 0x26, 0x31,
|
|
+ 0x5e, 0x61, 0xf1, 0x87, 0xe2, 0xeb, 0x9b, 0xcd, 0xd0, 0x3a, 0xee, 0x20,
|
|
+ 0x7e, 0x10, 0x0a, 0x0b, 0x7e, 0xfa, },
|
|
+ { 0xa4, 0x27, 0x80, 0x67, 0x81, 0x2a, 0xa7, 0x62, 0xf7, 0x6e, 0xda, 0xd4,
|
|
+ 0x5c, 0x39, 0x74, 0xad, 0x7e, 0xbe, 0xad, 0xa5, 0x84, 0x7f, 0xa9, 0x30,
|
|
+ 0x5d, 0xdb, 0xe2, 0x05, 0x43, 0xf7, 0x1b, },
|
|
+ { 0x0b, 0x37, 0xd8, 0x02, 0xe1, 0x83, 0xd6, 0x80, 0xf2, 0x35, 0xc2, 0xb0,
|
|
+ 0x37, 0xef, 0xef, 0x5e, 0x43, 0x93, 0xf0, 0x49, 0x45, 0x0a, 0xef, 0xb5,
|
|
+ 0x76, 0x70, 0x12, 0x44, 0xc4, 0xdb, 0xf5, 0x7a, },
|
|
+ { 0x1f, },
|
|
+ { 0x82, 0x60, },
|
|
+ { 0xcc, 0xe3, 0x08, },
|
|
+ { 0x56, 0x17, 0xe4, 0x59, },
|
|
+ { 0xe2, 0xd7, 0x9e, 0xc4, 0x4c, },
|
|
+ { 0xb2, 0xad, 0xd3, 0x78, 0x58, 0x5a, },
|
|
+ { 0xce, 0x43, 0xb4, 0x02, 0x96, 0xab, 0x3c, },
|
|
+ { 0xe6, 0x05, 0x1a, 0x73, 0x22, 0x32, 0xbb, 0x77, },
|
|
+ { 0x23, 0xe7, 0xda, 0xfe, 0x2c, 0xef, 0x8c, 0x22, 0xec, },
|
|
+ { 0xe9, 0x8e, 0x55, 0x38, 0xd1, 0xd7, 0x35, 0x23, 0x98, 0xc7, },
|
|
+ { 0xb5, 0x81, 0x1a, 0xe5, 0xb5, 0xa5, 0xd9, 0x4d, 0xca, 0x41, 0xe7, },
|
|
+ { 0x41, 0x16, 0x16, 0x95, 0x8d, 0x9e, 0x0c, 0xea, 0x8c, 0x71, 0x9a, 0xc1, },
|
|
+ { 0x7c, 0x33, 0xc0, 0xa4, 0x00, 0x62, 0xea, 0x60, 0x67, 0xe4, 0x20, 0xbc,
|
|
+ 0x5b, },
|
|
+ { 0xdb, 0xb1, 0xdc, 0xfd, 0x08, 0xc0, 0xde, 0x82, 0xd1, 0xde, 0x38, 0xc0,
|
|
+ 0x90, 0x48, },
|
|
+ { 0x37, 0x18, 0x2e, 0x0d, 0x61, 0xaa, 0x61, 0xd7, 0x86, 0x20, 0x16, 0x60,
|
|
+ 0x04, 0xd9, 0xd5, },
|
|
+ { 0xb0, 0xcf, 0x2c, 0x4c, 0x5e, 0x5b, 0x4f, 0x2a, 0x23, 0x25, 0x58, 0x47,
|
|
+ 0xe5, 0x31, 0x06, 0x70, },
|
|
+ { 0x91, 0xa0, 0xa3, 0x86, 0x4e, 0xe0, 0x72, 0x38, 0x06, 0x67, 0x59, 0x5c,
|
|
+ 0x70, 0x25, 0xdb, 0x33, 0x27, },
|
|
+ { 0x44, 0x58, 0x66, 0xb8, 0x58, 0xc7, 0x13, 0xed, 0x4c, 0xc0, 0xf4, 0x9a,
|
|
+ 0x1e, 0x67, 0x75, 0x33, 0xb6, 0xb8, },
|
|
+ { 0x7f, 0x98, 0x4a, 0x8e, 0x50, 0xa2, 0x5c, 0xcd, 0x59, 0xde, 0x72, 0xb3,
|
|
+ 0x9d, 0xc3, 0x09, 0x8a, 0xab, 0x56, 0xf1, },
|
|
+ { 0x80, 0x96, 0x49, 0x1a, 0x59, 0xa2, 0xc5, 0xd5, 0xa7, 0x20, 0x8a, 0xb7,
|
|
+ 0x27, 0x62, 0x84, 0x43, 0xc6, 0xe1, 0x1b, 0x5d, },
|
|
+ { 0x6b, 0xb7, 0x2b, 0x26, 0x62, 0x14, 0x70, 0x19, 0x3d, 0x4d, 0xac, 0xac,
|
|
+ 0x63, 0x58, 0x5e, 0x94, 0xb5, 0xb7, 0xe8, 0xe8, 0xa2, },
|
|
+ { 0x20, 0xa8, 0xc0, 0xfd, 0x63, 0x3d, 0x6e, 0x98, 0xcf, 0x0c, 0x49, 0x98,
|
|
+ 0xe4, 0x5a, 0xfe, 0x8c, 0xaa, 0x70, 0x82, 0x1c, 0x7b, 0x74, },
|
|
+ { 0xc8, 0xe8, 0xdd, 0xdf, 0x69, 0x30, 0x01, 0xc2, 0x0f, 0x7e, 0x2f, 0x11,
|
|
+ 0xcc, 0x3e, 0x17, 0xa5, 0x69, 0x40, 0x3f, 0x0e, 0x79, 0x7f, 0xcf, },
|
|
+ { 0xdb, 0x61, 0xc0, 0xe2, 0x2e, 0x49, 0x07, 0x31, 0x1d, 0x91, 0x42, 0x8a,
|
|
+ 0xfc, 0x5e, 0xd3, 0xf8, 0x56, 0x1f, 0x2b, 0x73, 0xfd, 0x9f, 0xb2, 0x8e, },
|
|
+ { 0x0c, 0x89, 0x55, 0x0c, 0x1f, 0x59, 0x2c, 0x9d, 0x1b, 0x29, 0x1d, 0x41,
|
|
+ 0x1d, 0xe6, 0x47, 0x8f, 0x8c, 0x2b, 0xea, 0x8f, 0xf0, 0xff, 0x21, 0x70,
|
|
+ 0x88, },
|
|
+ { 0x12, 0x18, 0x95, 0xa6, 0x59, 0xb1, 0x31, 0x24, 0x45, 0x67, 0x55, 0xa4,
|
|
+ 0x1a, 0x2d, 0x48, 0x67, 0x1b, 0x43, 0x88, 0x2d, 0x8e, 0xa0, 0x70, 0xb3,
|
|
+ 0xc6, 0xbb, },
|
|
+ { 0xe7, 0xb1, 0x1d, 0xb2, 0x76, 0x4d, 0x68, 0x68, 0x68, 0x23, 0x02, 0x55,
|
|
+ 0x3a, 0xe2, 0xe5, 0xd5, 0x4b, 0x43, 0xf9, 0x34, 0x77, 0x5c, 0xa1, 0xf5,
|
|
+ 0x55, 0xfd, 0x4f, },
|
|
+ { 0x8c, 0x87, 0x5a, 0x08, 0x3a, 0x73, 0xad, 0x61, 0xe1, 0xe7, 0x99, 0x7e,
|
|
+ 0xf0, 0x5d, 0xe9, 0x5d, 0x16, 0x43, 0x80, 0x2f, 0xd0, 0x66, 0x34, 0xe2,
|
|
+ 0x42, 0x64, 0x3b, 0x1a, },
|
|
+ { 0x39, 0xc1, 0x99, 0xcf, 0x22, 0xbf, 0x16, 0x8f, 0x9f, 0x80, 0x7f, 0x95,
|
|
+ 0x0a, 0x05, 0x67, 0x27, 0xe7, 0x15, 0xdf, 0x9d, 0xb2, 0xfe, 0x1c, 0xb5,
|
|
+ 0x1d, 0x60, 0x8f, 0x8a, 0x1d, },
|
|
+ { 0x9b, 0x6e, 0x08, 0x09, 0x06, 0x73, 0xab, 0x68, 0x02, 0x62, 0x1a, 0xe4,
|
|
+ 0xd4, 0xdf, 0xc7, 0x02, 0x4c, 0x6a, 0x5f, 0xfd, 0x23, 0xac, 0xae, 0x6d,
|
|
+ 0x43, 0xa4, 0x7a, 0x50, 0x60, 0x3c, },
|
|
+ { 0x1d, 0xb4, 0xc6, 0xe1, 0xb1, 0x4b, 0xe3, 0xf2, 0xe2, 0x1a, 0x73, 0x1b,
|
|
+ 0xa0, 0x92, 0xa7, 0xf5, 0xff, 0x8f, 0x8b, 0x5d, 0xdf, 0xa8, 0x04, 0xb3,
|
|
+ 0xb0, 0xf7, 0xcc, 0x12, 0xfa, 0x35, 0x46, },
|
|
+ { 0x49, 0x45, 0x97, 0x11, 0x0f, 0x1c, 0x60, 0x8e, 0xe8, 0x47, 0x30, 0xcf,
|
|
+ 0x60, 0xa8, 0x71, 0xc5, 0x1b, 0xe9, 0x39, 0x4d, 0x49, 0xb6, 0x12, 0x1f,
|
|
+ 0x24, 0xab, 0x37, 0xff, 0x83, 0xc2, 0xe1, 0x3a, },
|
|
+ { 0x60, },
|
|
+ { 0x24, 0x26, },
|
|
+ { 0x47, 0xeb, 0xc9, },
|
|
+ { 0x4a, 0xd0, 0xbc, 0xf0, },
|
|
+ { 0x8e, 0x2b, 0xc9, 0x85, 0x3c, },
|
|
+ { 0xa2, 0x07, 0x15, 0xb8, 0x12, 0x74, },
|
|
+ { 0x0f, 0xdb, 0x5b, 0x33, 0x69, 0xfe, 0x4b, },
|
|
+ { 0xa2, 0x86, 0x54, 0xf4, 0xfd, 0xb2, 0xd4, 0xe6, },
|
|
+ { 0xbb, 0x84, 0x78, 0x49, 0x27, 0x8e, 0x61, 0xda, 0x60, },
|
|
+ { 0x04, 0xc3, 0xcd, 0xaa, 0x8f, 0xa7, 0x03, 0xc9, 0xf9, 0xb6, },
|
|
+ { 0xf8, 0x27, 0x1d, 0x61, 0xdc, 0x21, 0x42, 0xdd, 0xad, 0x92, 0x40, },
|
|
+ { 0x12, 0x87, 0xdf, 0xc2, 0x41, 0x45, 0x5a, 0x36, 0x48, 0x5b, 0x51, 0x2b, },
|
|
+ { 0xbb, 0x37, 0x5d, 0x1f, 0xf1, 0x68, 0x7a, 0xc4, 0xa5, 0xd2, 0xa4, 0x91,
|
|
+ 0x8d, },
|
|
+ { 0x5b, 0x27, 0xd1, 0x04, 0x54, 0x52, 0x9f, 0xa3, 0x47, 0x86, 0x33, 0x33,
|
|
+ 0xbf, 0xa0, },
|
|
+ { 0xcf, 0x04, 0xea, 0xf8, 0x03, 0x2a, 0x43, 0xff, 0xa6, 0x68, 0x21, 0x4c,
|
|
+ 0xd5, 0x4b, 0xed, },
|
|
+ { 0xaf, 0xb8, 0xbc, 0x63, 0x0f, 0x18, 0x4d, 0xe2, 0x7a, 0xdd, 0x46, 0x44,
|
|
+ 0xc8, 0x24, 0x0a, 0xb7, },
|
|
+ { 0x3e, 0xdc, 0x36, 0xe4, 0x89, 0xb1, 0xfa, 0xc6, 0x40, 0x93, 0x2e, 0x75,
|
|
+ 0xb2, 0x15, 0xd1, 0xb1, 0x10, },
|
|
+ { 0x6c, 0xd8, 0x20, 0x3b, 0x82, 0x79, 0xf9, 0xc8, 0xbc, 0x9d, 0xe0, 0x35,
|
|
+ 0xbe, 0x1b, 0x49, 0x1a, 0xbc, 0x3a, },
|
|
+ { 0x78, 0x65, 0x2c, 0xbe, 0x35, 0x67, 0xdc, 0x78, 0xd4, 0x41, 0xf6, 0xc9,
|
|
+ 0xde, 0xde, 0x1f, 0x18, 0x13, 0x31, 0x11, },
|
|
+ { 0x8a, 0x7f, 0xb1, 0x33, 0x8f, 0x0c, 0x3c, 0x0a, 0x06, 0x61, 0xf0, 0x47,
|
|
+ 0x29, 0x1b, 0x29, 0xbc, 0x1c, 0x47, 0xef, 0x7a, },
|
|
+ { 0x65, 0x91, 0xf1, 0xe6, 0xb3, 0x96, 0xd3, 0x8c, 0xc2, 0x4a, 0x59, 0x35,
|
|
+ 0x72, 0x8e, 0x0b, 0x9a, 0x87, 0xca, 0x34, 0x7b, 0x63, },
|
|
+ { 0x5f, 0x08, 0x87, 0x80, 0x56, 0x25, 0x89, 0x77, 0x61, 0x8c, 0x64, 0xa1,
|
|
+ 0x59, 0x6d, 0x59, 0x62, 0xe8, 0x4a, 0xc8, 0x58, 0x99, 0xd1, },
|
|
+ { 0x23, 0x87, 0x1d, 0xed, 0x6f, 0xf2, 0x91, 0x90, 0xe2, 0xfe, 0x43, 0x21,
|
|
+ 0xaf, 0x97, 0xc6, 0xbc, 0xd7, 0x15, 0xc7, 0x2d, 0x08, 0x77, 0x91, },
|
|
+ { 0x90, 0x47, 0x9a, 0x9e, 0x3a, 0xdf, 0xf3, 0xc9, 0x4c, 0x1e, 0xa7, 0xd4,
|
|
+ 0x6a, 0x32, 0x90, 0xfe, 0xb7, 0xb6, 0x7b, 0xfa, 0x96, 0x61, 0xfb, 0xa4, },
|
|
+ { 0xb1, 0x67, 0x60, 0x45, 0xb0, 0x96, 0xc5, 0x15, 0x9f, 0x4d, 0x26, 0xd7,
|
|
+ 0x9d, 0xf1, 0xf5, 0x6d, 0x21, 0x00, 0x94, 0x31, 0x64, 0x94, 0xd3, 0xa7,
|
|
+ 0xd3, },
|
|
+ { 0x02, 0x3e, 0xaf, 0xf3, 0x79, 0x73, 0xa5, 0xf5, 0xcc, 0x7a, 0x7f, 0xfb,
|
|
+ 0x79, 0x2b, 0x85, 0x8c, 0x88, 0x72, 0x06, 0xbe, 0xfe, 0xaf, 0xc1, 0x16,
|
|
+ 0xa6, 0xd6, },
|
|
+ { 0x2a, 0xb0, 0x1a, 0xe5, 0xaa, 0x6e, 0xb3, 0xae, 0x53, 0x85, 0x33, 0x80,
|
|
+ 0x75, 0xae, 0x30, 0xe6, 0xb8, 0x72, 0x42, 0xf6, 0x25, 0x4f, 0x38, 0x88,
|
|
+ 0x55, 0xd1, 0xa9, },
|
|
+ { 0x90, 0xd8, 0x0c, 0xc0, 0x93, 0x4b, 0x4f, 0x9e, 0x65, 0x6c, 0xa1, 0x54,
|
|
+ 0xa6, 0xf6, 0x6e, 0xca, 0xd2, 0xbb, 0x7e, 0x6a, 0x1c, 0xd3, 0xce, 0x46,
|
|
+ 0xef, 0xb0, 0x00, 0x8d, },
|
|
+ { 0xed, 0x9c, 0x49, 0xcd, 0xc2, 0xde, 0x38, 0x0e, 0xe9, 0x98, 0x6c, 0xc8,
|
|
+ 0x90, 0x9e, 0x3c, 0xd4, 0xd3, 0xeb, 0x88, 0x32, 0xc7, 0x28, 0xe3, 0x94,
|
|
+ 0x1c, 0x9f, 0x8b, 0xf3, 0xcb, },
|
|
+ { 0xac, 0xe7, 0x92, 0x16, 0xb4, 0x14, 0xa0, 0xe4, 0x04, 0x79, 0xa2, 0xf4,
|
|
+ 0x31, 0xe6, 0x0c, 0x26, 0xdc, 0xbf, 0x2f, 0x69, 0x1b, 0x55, 0x94, 0x67,
|
|
+ 0xda, 0x0c, 0xd7, 0x32, 0x1f, 0xef, },
|
|
+ { 0x68, 0x63, 0x85, 0x57, 0x95, 0x9e, 0x42, 0x27, 0x41, 0x43, 0x42, 0x02,
|
|
+ 0xa5, 0x78, 0xa7, 0xc6, 0x43, 0xc1, 0x6a, 0xba, 0x70, 0x80, 0xcd, 0x04,
|
|
+ 0xb6, 0x78, 0x76, 0x29, 0xf3, 0xe8, 0xa0, },
|
|
+ { 0xe6, 0xac, 0x8d, 0x9d, 0xf0, 0xc0, 0xf7, 0xf7, 0xe3, 0x3e, 0x4e, 0x28,
|
|
+ 0x0f, 0x59, 0xb2, 0x67, 0x9e, 0x84, 0x34, 0x42, 0x96, 0x30, 0x2b, 0xca,
|
|
+ 0x49, 0xb6, 0xc5, 0x9a, 0x84, 0x59, 0xa7, 0x81, },
|
|
+ { 0x7e, },
|
|
+ { 0x1e, 0x21, },
|
|
+ { 0x26, 0xd3, 0xdd, },
|
|
+ { 0x2c, 0xd4, 0xb3, 0x3d, },
|
|
+ { 0x86, 0x7b, 0x76, 0x3c, 0xf0, },
|
|
+ { 0x12, 0xc3, 0x70, 0x1d, 0x55, 0x18, },
|
|
+ { 0x96, 0xc2, 0xbd, 0x61, 0x55, 0xf4, 0x24, },
|
|
+ { 0x20, 0x51, 0xf7, 0x86, 0x58, 0x8f, 0x07, 0x2a, },
|
|
+ { 0x93, 0x15, 0xa8, 0x1d, 0xda, 0x97, 0xee, 0x0e, 0x6c, },
|
|
+ { 0x39, 0x93, 0xdf, 0xd5, 0x0e, 0xca, 0xdc, 0x7a, 0x92, 0xce, },
|
|
+ { 0x60, 0xd5, 0xfd, 0xf5, 0x1b, 0x26, 0x82, 0x26, 0x73, 0x02, 0xbc, },
|
|
+ { 0x98, 0xf2, 0x34, 0xe1, 0xf5, 0xfb, 0x00, 0xac, 0x10, 0x4a, 0x38, 0x9f, },
|
|
+ { 0xda, 0x3a, 0x92, 0x8a, 0xd0, 0xcd, 0x12, 0xcd, 0x15, 0xbb, 0xab, 0x77,
|
|
+ 0x66, },
|
|
+ { 0xa2, 0x92, 0x1a, 0xe5, 0xca, 0x0c, 0x30, 0x75, 0xeb, 0xaf, 0x00, 0x31,
|
|
+ 0x55, 0x66, },
|
|
+ { 0x06, 0xea, 0xfd, 0x3e, 0x86, 0x38, 0x62, 0x4e, 0xa9, 0x12, 0xa4, 0x12,
|
|
+ 0x43, 0xbf, 0xa1, },
|
|
+ { 0xe4, 0x71, 0x7b, 0x94, 0xdb, 0xa0, 0xd2, 0xff, 0x9b, 0xeb, 0xad, 0x8e,
|
|
+ 0x95, 0x8a, 0xc5, 0xed, },
|
|
+ { 0x25, 0x5a, 0x77, 0x71, 0x41, 0x0e, 0x7a, 0xe9, 0xed, 0x0c, 0x10, 0xef,
|
|
+ 0xf6, 0x2b, 0x3a, 0xba, 0x60, },
|
|
+ { 0xee, 0xe2, 0xa3, 0x67, 0x64, 0x1d, 0xc6, 0x04, 0xc4, 0xe1, 0x68, 0xd2,
|
|
+ 0x6e, 0xd2, 0x91, 0x75, 0x53, 0x07, },
|
|
+ { 0xe0, 0xf6, 0x4d, 0x8f, 0x68, 0xfc, 0x06, 0x7e, 0x18, 0x79, 0x7f, 0x2b,
|
|
+ 0x6d, 0xef, 0x46, 0x7f, 0xab, 0xb2, 0xad, },
|
|
+ { 0x3d, 0x35, 0x88, 0x9f, 0x2e, 0xcf, 0x96, 0x45, 0x07, 0x60, 0x71, 0x94,
|
|
+ 0x00, 0x8d, 0xbf, 0xf4, 0xef, 0x46, 0x2e, 0x3c, },
|
|
+ { 0x43, 0xcf, 0x98, 0xf7, 0x2d, 0xf4, 0x17, 0xe7, 0x8c, 0x05, 0x2d, 0x9b,
|
|
+ 0x24, 0xfb, 0x4d, 0xea, 0x4a, 0xec, 0x01, 0x25, 0x29, },
|
|
+ { 0x8e, 0x73, 0x9a, 0x78, 0x11, 0xfe, 0x48, 0xa0, 0x3b, 0x1a, 0x26, 0xdf,
|
|
+ 0x25, 0xe9, 0x59, 0x1c, 0x70, 0x07, 0x9f, 0xdc, 0xa0, 0xa6, },
|
|
+ { 0xe8, 0x47, 0x71, 0xc7, 0x3e, 0xdf, 0xb5, 0x13, 0xb9, 0x85, 0x13, 0xa8,
|
|
+ 0x54, 0x47, 0x6e, 0x59, 0x96, 0x09, 0x13, 0x5f, 0x82, 0x16, 0x0b, },
|
|
+ { 0xfb, 0xc0, 0x8c, 0x03, 0x21, 0xb3, 0xc4, 0xb5, 0x43, 0x32, 0x6c, 0xea,
|
|
+ 0x7f, 0xa8, 0x43, 0x91, 0xe8, 0x4e, 0x3f, 0xbf, 0x45, 0x58, 0x6a, 0xa3, },
|
|
+ { 0x55, 0xf8, 0xf3, 0x00, 0x76, 0x09, 0xef, 0x69, 0x5d, 0xd2, 0x8a, 0xf2,
|
|
+ 0x65, 0xc3, 0xcb, 0x9b, 0x43, 0xfd, 0xb1, 0x7e, 0x7f, 0xa1, 0x94, 0xb0,
|
|
+ 0xd7, },
|
|
+ { 0xaa, 0x13, 0xc1, 0x51, 0x40, 0x6d, 0x8d, 0x4c, 0x0a, 0x95, 0x64, 0x7b,
|
|
+ 0xd1, 0x96, 0xb6, 0x56, 0xb4, 0x5b, 0xcf, 0xd6, 0xd9, 0x15, 0x97, 0xdd,
|
|
+ 0xb6, 0xef, },
|
|
+ { 0xaf, 0xb7, 0x36, 0xb0, 0x04, 0xdb, 0xd7, 0x9c, 0x9a, 0x44, 0xc4, 0xf6,
|
|
+ 0x1f, 0x12, 0x21, 0x2d, 0x59, 0x30, 0x54, 0xab, 0x27, 0x61, 0xa3, 0x57,
|
|
+ 0xef, 0xf8, 0x53, },
|
|
+ { 0x97, 0x34, 0x45, 0x3e, 0xce, 0x7c, 0x35, 0xa2, 0xda, 0x9f, 0x4b, 0x46,
|
|
+ 0x6c, 0x11, 0x67, 0xff, 0x2f, 0x76, 0x58, 0x15, 0x71, 0xfa, 0x44, 0x89,
|
|
+ 0x89, 0xfd, 0xf7, 0x99, },
|
|
+ { 0x1f, 0xb1, 0x62, 0xeb, 0x83, 0xc5, 0x9c, 0x89, 0xf9, 0x2c, 0xd2, 0x03,
|
|
+ 0x61, 0xbc, 0xbb, 0xa5, 0x74, 0x0e, 0x9b, 0x7e, 0x82, 0x3e, 0x70, 0x0a,
|
|
+ 0xa9, 0x8f, 0x2b, 0x59, 0xfb, },
|
|
+ { 0xf8, 0xca, 0x5e, 0x3a, 0x4f, 0x9e, 0x10, 0x69, 0x10, 0xd5, 0x4c, 0xeb,
|
|
+ 0x1a, 0x0f, 0x3c, 0x6a, 0x98, 0xf5, 0xb0, 0x97, 0x5b, 0x37, 0x2f, 0x0d,
|
|
+ 0xbd, 0x42, 0x4b, 0x69, 0xa1, 0x82, },
|
|
+ { 0x12, 0x8c, 0x6d, 0x52, 0x08, 0xef, 0x74, 0xb2, 0xe6, 0xaa, 0xd3, 0xb0,
|
|
+ 0x26, 0xb0, 0xd9, 0x94, 0xb6, 0x11, 0x45, 0x0e, 0x36, 0x71, 0x14, 0x2d,
|
|
+ 0x41, 0x8c, 0x21, 0x53, 0x31, 0xe9, 0x68, },
|
|
+ { 0xee, 0xea, 0x0d, 0x89, 0x47, 0x7e, 0x72, 0xd1, 0xd8, 0xce, 0x58, 0x4c,
|
|
+ 0x94, 0x1f, 0x0d, 0x51, 0x08, 0xa3, 0xb6, 0x3d, 0xe7, 0x82, 0x46, 0x92,
|
|
+ 0xd6, 0x98, 0x6b, 0x07, 0x10, 0x65, 0x52, 0x65, },
|
|
+};
|
|
+
|
|
+bool __init blake2s_selftest(void)
|
|
+{
|
|
+ u8 key[BLAKE2S_KEY_SIZE];
|
|
+ u8 buf[ARRAY_SIZE(blake2s_testvecs)];
|
|
+ u8 hash[BLAKE2S_HASH_SIZE];
|
|
+ struct blake2s_state state;
|
|
+ bool success = true;
|
|
+ int i, l;
|
|
+
|
|
+ key[0] = key[1] = 1;
|
|
+ for (i = 2; i < sizeof(key); ++i)
|
|
+ key[i] = key[i - 2] + key[i - 1];
|
|
+
|
|
+ for (i = 0; i < sizeof(buf); ++i)
|
|
+ buf[i] = (u8)i;
|
|
+
|
|
+ for (i = l = 0; i < ARRAY_SIZE(blake2s_testvecs); l = (l + 37) % ++i) {
|
|
+ int outlen = 1 + i % BLAKE2S_HASH_SIZE;
|
|
+ int keylen = (13 * i) % (BLAKE2S_KEY_SIZE + 1);
|
|
+
|
|
+ blake2s(hash, buf, key + BLAKE2S_KEY_SIZE - keylen, outlen, i,
|
|
+ keylen);
|
|
+ if (memcmp(hash, blake2s_testvecs[i], outlen)) {
|
|
+ pr_err("blake2s self-test %d: FAIL\n", i + 1);
|
|
+ success = false;
|
|
+ }
|
|
+
|
|
+ if (!keylen)
|
|
+ blake2s_init(&state, outlen);
|
|
+ else
|
|
+ blake2s_init_key(&state, outlen,
|
|
+ key + BLAKE2S_KEY_SIZE - keylen,
|
|
+ keylen);
|
|
+
|
|
+ blake2s_update(&state, buf, l);
|
|
+ blake2s_update(&state, buf + l, i - l);
|
|
+ blake2s_final(&state, hash);
|
|
+ if (memcmp(hash, blake2s_testvecs[i], outlen)) {
|
|
+ pr_err("blake2s init/update/final self-test %d: FAIL\n",
|
|
+ i + 1);
|
|
+ success = false;
|
|
+ }
|
|
+ }
|
|
+
|
|
+ return success;
|
|
+}
|
|
diff --git a/lib/crypto/blake2s.c b/lib/crypto/blake2s.c
|
|
new file mode 100644
|
|
index 0000000000000..536fce87555b3
|
|
--- /dev/null
|
|
+++ b/lib/crypto/blake2s.c
|
|
@@ -0,0 +1,78 @@
|
|
+// SPDX-License-Identifier: GPL-2.0 OR MIT
|
|
+/*
|
|
+ * Copyright (C) 2015-2019 Jason A. Donenfeld <Jason@zx2c4.com>. All Rights Reserved.
|
|
+ *
|
|
+ * This is an implementation of the BLAKE2s hash and PRF functions.
|
|
+ *
|
|
+ * Information: https://blake2.net/
|
|
+ *
|
|
+ */
|
|
+
|
|
+#include <crypto/internal/blake2s.h>
|
|
+#include <linux/types.h>
|
|
+#include <linux/string.h>
|
|
+#include <linux/kernel.h>
|
|
+#include <linux/module.h>
|
|
+#include <linux/init.h>
|
|
+#include <linux/bug.h>
|
|
+#include <asm/unaligned.h>
|
|
+
|
|
+bool blake2s_selftest(void);
|
|
+
|
|
+void blake2s_update(struct blake2s_state *state, const u8 *in, size_t inlen)
|
|
+{
|
|
+ const size_t fill = BLAKE2S_BLOCK_SIZE - state->buflen;
|
|
+
|
|
+ if (unlikely(!inlen))
|
|
+ return;
|
|
+ if (inlen > fill) {
|
|
+ memcpy(state->buf + state->buflen, in, fill);
|
|
+ blake2s_compress_generic(state, state->buf, 1,
|
|
+ BLAKE2S_BLOCK_SIZE);
|
|
+ state->buflen = 0;
|
|
+ in += fill;
|
|
+ inlen -= fill;
|
|
+ }
|
|
+ if (inlen > BLAKE2S_BLOCK_SIZE) {
|
|
+ const size_t nblocks = DIV_ROUND_UP(inlen, BLAKE2S_BLOCK_SIZE);
|
|
+ /* Hash one less (full) block than strictly possible */
|
|
+ blake2s_compress_generic(state, in, nblocks - 1,
|
|
+ BLAKE2S_BLOCK_SIZE);
|
|
+ in += BLAKE2S_BLOCK_SIZE * (nblocks - 1);
|
|
+ inlen -= BLAKE2S_BLOCK_SIZE * (nblocks - 1);
|
|
+ }
|
|
+ memcpy(state->buf + state->buflen, in, inlen);
|
|
+ state->buflen += inlen;
|
|
+}
|
|
+EXPORT_SYMBOL(blake2s_update);
|
|
+
|
|
+void blake2s_final(struct blake2s_state *state, u8 *out)
|
|
+{
|
|
+ WARN_ON(IS_ENABLED(DEBUG) && !out);
|
|
+ blake2s_set_lastblock(state);
|
|
+ memset(state->buf + state->buflen, 0,
|
|
+ BLAKE2S_BLOCK_SIZE - state->buflen); /* Padding */
|
|
+ blake2s_compress_generic(state, state->buf, 1, state->buflen);
|
|
+ cpu_to_le32_array(state->h, ARRAY_SIZE(state->h));
|
|
+ memcpy(out, state->h, state->outlen);
|
|
+ memzero_explicit(state, sizeof(*state));
|
|
+}
|
|
+EXPORT_SYMBOL(blake2s_final);
|
|
+
|
|
+static int __init mod_init(void)
|
|
+{
|
|
+ if (!IS_ENABLED(CONFIG_CRYPTO_MANAGER_DISABLE_TESTS) &&
|
|
+ WARN_ON(!blake2s_selftest()))
|
|
+ return -ENODEV;
|
|
+ return 0;
|
|
+}
|
|
+
|
|
+static void __exit mod_exit(void)
|
|
+{
|
|
+}
|
|
+
|
|
+module_init(mod_init);
|
|
+module_exit(mod_exit);
|
|
+MODULE_LICENSE("GPL v2");
|
|
+MODULE_DESCRIPTION("BLAKE2s hash function");
|
|
+MODULE_AUTHOR("Jason A. Donenfeld <Jason@zx2c4.com>");
|
|
diff --git a/lib/random32.c b/lib/random32.c
|
|
index 9085b1172015e..339624191b515 100644
|
|
--- a/lib/random32.c
|
|
+++ b/lib/random32.c
|
|
@@ -38,6 +38,9 @@
|
|
#include <linux/jiffies.h>
|
|
#include <linux/random.h>
|
|
#include <linux/sched.h>
|
|
+#include <linux/bitops.h>
|
|
+#include <linux/slab.h>
|
|
+#include <linux/notifier.h>
|
|
#include <asm/unaligned.h>
|
|
|
|
/**
|
|
@@ -544,9 +547,11 @@ static void prandom_reseed(struct timer_list *unused)
|
|
* To avoid worrying about whether it's safe to delay that interrupt
|
|
* long enough to seed all CPUs, just schedule an immediate timer event.
|
|
*/
|
|
-static void prandom_timer_start(struct random_ready_callback *unused)
|
|
+static int prandom_timer_start(struct notifier_block *nb,
|
|
+ unsigned long action, void *data)
|
|
{
|
|
mod_timer(&seed_timer, jiffies);
|
|
+ return 0;
|
|
}
|
|
|
|
/*
|
|
@@ -555,13 +560,13 @@ static void prandom_timer_start(struct random_ready_callback *unused)
|
|
*/
|
|
static int __init prandom_init_late(void)
|
|
{
|
|
- static struct random_ready_callback random_ready = {
|
|
- .func = prandom_timer_start
|
|
+ static struct notifier_block random_ready = {
|
|
+ .notifier_call = prandom_timer_start
|
|
};
|
|
- int ret = add_random_ready_callback(&random_ready);
|
|
+ int ret = register_random_ready_notifier(&random_ready);
|
|
|
|
if (ret == -EALREADY) {
|
|
- prandom_timer_start(&random_ready);
|
|
+ prandom_timer_start(&random_ready, 0, NULL);
|
|
ret = 0;
|
|
}
|
|
return ret;
|
|
diff --git a/lib/sha1.c b/lib/sha1.c
|
|
index 1d96d2c02b826..bad46695476bd 100644
|
|
--- a/lib/sha1.c
|
|
+++ b/lib/sha1.c
|
|
@@ -10,6 +10,7 @@
|
|
#include <linux/export.h>
|
|
#include <linux/bitops.h>
|
|
#include <linux/cryptohash.h>
|
|
+#include <linux/string.h>
|
|
#include <asm/unaligned.h>
|
|
|
|
/*
|
|
@@ -55,7 +56,8 @@
|
|
#define SHA_ROUND(t, input, fn, constant, A, B, C, D, E) do { \
|
|
__u32 TEMP = input(t); setW(t, TEMP); \
|
|
E += TEMP + rol32(A,5) + (fn) + (constant); \
|
|
- B = ror32(B, 2); } while (0)
|
|
+ B = ror32(B, 2); \
|
|
+ TEMP = E; E = D; D = C; C = B; B = A; A = TEMP; } while (0)
|
|
|
|
#define T_0_15(t, A, B, C, D, E) SHA_ROUND(t, SHA_SRC, (((C^D)&B)^D) , 0x5a827999, A, B, C, D, E )
|
|
#define T_16_19(t, A, B, C, D, E) SHA_ROUND(t, SHA_MIX, (((C^D)&B)^D) , 0x5a827999, A, B, C, D, E )
|
|
@@ -82,6 +84,7 @@
|
|
void sha_transform(__u32 *digest, const char *data, __u32 *array)
|
|
{
|
|
__u32 A, B, C, D, E;
|
|
+ unsigned int i = 0;
|
|
|
|
A = digest[0];
|
|
B = digest[1];
|
|
@@ -90,94 +93,24 @@ void sha_transform(__u32 *digest, const char *data, __u32 *array)
|
|
E = digest[4];
|
|
|
|
/* Round 1 - iterations 0-16 take their input from 'data' */
|
|
- T_0_15( 0, A, B, C, D, E);
|
|
- T_0_15( 1, E, A, B, C, D);
|
|
- T_0_15( 2, D, E, A, B, C);
|
|
- T_0_15( 3, C, D, E, A, B);
|
|
- T_0_15( 4, B, C, D, E, A);
|
|
- T_0_15( 5, A, B, C, D, E);
|
|
- T_0_15( 6, E, A, B, C, D);
|
|
- T_0_15( 7, D, E, A, B, C);
|
|
- T_0_15( 8, C, D, E, A, B);
|
|
- T_0_15( 9, B, C, D, E, A);
|
|
- T_0_15(10, A, B, C, D, E);
|
|
- T_0_15(11, E, A, B, C, D);
|
|
- T_0_15(12, D, E, A, B, C);
|
|
- T_0_15(13, C, D, E, A, B);
|
|
- T_0_15(14, B, C, D, E, A);
|
|
- T_0_15(15, A, B, C, D, E);
|
|
+ for (; i < 16; ++i)
|
|
+ T_0_15(i, A, B, C, D, E);
|
|
|
|
/* Round 1 - tail. Input from 512-bit mixing array */
|
|
- T_16_19(16, E, A, B, C, D);
|
|
- T_16_19(17, D, E, A, B, C);
|
|
- T_16_19(18, C, D, E, A, B);
|
|
- T_16_19(19, B, C, D, E, A);
|
|
+ for (; i < 20; ++i)
|
|
+ T_16_19(i, A, B, C, D, E);
|
|
|
|
/* Round 2 */
|
|
- T_20_39(20, A, B, C, D, E);
|
|
- T_20_39(21, E, A, B, C, D);
|
|
- T_20_39(22, D, E, A, B, C);
|
|
- T_20_39(23, C, D, E, A, B);
|
|
- T_20_39(24, B, C, D, E, A);
|
|
- T_20_39(25, A, B, C, D, E);
|
|
- T_20_39(26, E, A, B, C, D);
|
|
- T_20_39(27, D, E, A, B, C);
|
|
- T_20_39(28, C, D, E, A, B);
|
|
- T_20_39(29, B, C, D, E, A);
|
|
- T_20_39(30, A, B, C, D, E);
|
|
- T_20_39(31, E, A, B, C, D);
|
|
- T_20_39(32, D, E, A, B, C);
|
|
- T_20_39(33, C, D, E, A, B);
|
|
- T_20_39(34, B, C, D, E, A);
|
|
- T_20_39(35, A, B, C, D, E);
|
|
- T_20_39(36, E, A, B, C, D);
|
|
- T_20_39(37, D, E, A, B, C);
|
|
- T_20_39(38, C, D, E, A, B);
|
|
- T_20_39(39, B, C, D, E, A);
|
|
+ for (; i < 40; ++i)
|
|
+ T_20_39(i, A, B, C, D, E);
|
|
|
|
/* Round 3 */
|
|
- T_40_59(40, A, B, C, D, E);
|
|
- T_40_59(41, E, A, B, C, D);
|
|
- T_40_59(42, D, E, A, B, C);
|
|
- T_40_59(43, C, D, E, A, B);
|
|
- T_40_59(44, B, C, D, E, A);
|
|
- T_40_59(45, A, B, C, D, E);
|
|
- T_40_59(46, E, A, B, C, D);
|
|
- T_40_59(47, D, E, A, B, C);
|
|
- T_40_59(48, C, D, E, A, B);
|
|
- T_40_59(49, B, C, D, E, A);
|
|
- T_40_59(50, A, B, C, D, E);
|
|
- T_40_59(51, E, A, B, C, D);
|
|
- T_40_59(52, D, E, A, B, C);
|
|
- T_40_59(53, C, D, E, A, B);
|
|
- T_40_59(54, B, C, D, E, A);
|
|
- T_40_59(55, A, B, C, D, E);
|
|
- T_40_59(56, E, A, B, C, D);
|
|
- T_40_59(57, D, E, A, B, C);
|
|
- T_40_59(58, C, D, E, A, B);
|
|
- T_40_59(59, B, C, D, E, A);
|
|
+ for (; i < 60; ++i)
|
|
+ T_40_59(i, A, B, C, D, E);
|
|
|
|
/* Round 4 */
|
|
- T_60_79(60, A, B, C, D, E);
|
|
- T_60_79(61, E, A, B, C, D);
|
|
- T_60_79(62, D, E, A, B, C);
|
|
- T_60_79(63, C, D, E, A, B);
|
|
- T_60_79(64, B, C, D, E, A);
|
|
- T_60_79(65, A, B, C, D, E);
|
|
- T_60_79(66, E, A, B, C, D);
|
|
- T_60_79(67, D, E, A, B, C);
|
|
- T_60_79(68, C, D, E, A, B);
|
|
- T_60_79(69, B, C, D, E, A);
|
|
- T_60_79(70, A, B, C, D, E);
|
|
- T_60_79(71, E, A, B, C, D);
|
|
- T_60_79(72, D, E, A, B, C);
|
|
- T_60_79(73, C, D, E, A, B);
|
|
- T_60_79(74, B, C, D, E, A);
|
|
- T_60_79(75, A, B, C, D, E);
|
|
- T_60_79(76, E, A, B, C, D);
|
|
- T_60_79(77, D, E, A, B, C);
|
|
- T_60_79(78, C, D, E, A, B);
|
|
- T_60_79(79, B, C, D, E, A);
|
|
+ for (; i < 80; ++i)
|
|
+ T_60_79(i, A, B, C, D, E);
|
|
|
|
digest[0] += A;
|
|
digest[1] += B;
|
|
diff --git a/lib/siphash.c b/lib/siphash.c
|
|
index 025f0cbf6d7a7..b4055b1cc2f67 100644
|
|
--- a/lib/siphash.c
|
|
+++ b/lib/siphash.c
|
|
@@ -18,19 +18,13 @@
|
|
#include <asm/word-at-a-time.h>
|
|
#endif
|
|
|
|
-#define SIPROUND \
|
|
- do { \
|
|
- v0 += v1; v1 = rol64(v1, 13); v1 ^= v0; v0 = rol64(v0, 32); \
|
|
- v2 += v3; v3 = rol64(v3, 16); v3 ^= v2; \
|
|
- v0 += v3; v3 = rol64(v3, 21); v3 ^= v0; \
|
|
- v2 += v1; v1 = rol64(v1, 17); v1 ^= v2; v2 = rol64(v2, 32); \
|
|
- } while (0)
|
|
+#define SIPROUND SIPHASH_PERMUTATION(v0, v1, v2, v3)
|
|
|
|
#define PREAMBLE(len) \
|
|
- u64 v0 = 0x736f6d6570736575ULL; \
|
|
- u64 v1 = 0x646f72616e646f6dULL; \
|
|
- u64 v2 = 0x6c7967656e657261ULL; \
|
|
- u64 v3 = 0x7465646279746573ULL; \
|
|
+ u64 v0 = SIPHASH_CONST_0; \
|
|
+ u64 v1 = SIPHASH_CONST_1; \
|
|
+ u64 v2 = SIPHASH_CONST_2; \
|
|
+ u64 v3 = SIPHASH_CONST_3; \
|
|
u64 b = ((u64)(len)) << 56; \
|
|
v3 ^= key->key[1]; \
|
|
v2 ^= key->key[0]; \
|
|
@@ -389,19 +383,13 @@ u32 hsiphash_4u32(const u32 first, const u32 second, const u32 third,
|
|
}
|
|
EXPORT_SYMBOL(hsiphash_4u32);
|
|
#else
|
|
-#define HSIPROUND \
|
|
- do { \
|
|
- v0 += v1; v1 = rol32(v1, 5); v1 ^= v0; v0 = rol32(v0, 16); \
|
|
- v2 += v3; v3 = rol32(v3, 8); v3 ^= v2; \
|
|
- v0 += v3; v3 = rol32(v3, 7); v3 ^= v0; \
|
|
- v2 += v1; v1 = rol32(v1, 13); v1 ^= v2; v2 = rol32(v2, 16); \
|
|
- } while (0)
|
|
+#define HSIPROUND HSIPHASH_PERMUTATION(v0, v1, v2, v3)
|
|
|
|
#define HPREAMBLE(len) \
|
|
- u32 v0 = 0; \
|
|
- u32 v1 = 0; \
|
|
- u32 v2 = 0x6c796765U; \
|
|
- u32 v3 = 0x74656462U; \
|
|
+ u32 v0 = HSIPHASH_CONST_0; \
|
|
+ u32 v1 = HSIPHASH_CONST_1; \
|
|
+ u32 v2 = HSIPHASH_CONST_2; \
|
|
+ u32 v3 = HSIPHASH_CONST_3; \
|
|
u32 b = ((u32)(len)) << 24; \
|
|
v3 ^= key->key[1]; \
|
|
v2 ^= key->key[0]; \
|
|
diff --git a/lib/vsprintf.c b/lib/vsprintf.c
|
|
index 2766d1b2c301d..393623bf3258f 100644
|
|
--- a/lib/vsprintf.c
|
|
+++ b/lib/vsprintf.c
|
|
@@ -731,14 +731,16 @@ static void enable_ptr_key_workfn(struct work_struct *work)
|
|
|
|
static DECLARE_WORK(enable_ptr_key_work, enable_ptr_key_workfn);
|
|
|
|
-static void fill_random_ptr_key(struct random_ready_callback *unused)
|
|
+static int fill_random_ptr_key(struct notifier_block *nb,
|
|
+ unsigned long action, void *data)
|
|
{
|
|
/* This may be in an interrupt handler. */
|
|
queue_work(system_unbound_wq, &enable_ptr_key_work);
|
|
+ return 0;
|
|
}
|
|
|
|
-static struct random_ready_callback random_ready = {
|
|
- .func = fill_random_ptr_key
|
|
+static struct notifier_block random_ready = {
|
|
+ .notifier_call = fill_random_ptr_key
|
|
};
|
|
|
|
static int __init initialize_ptr_random(void)
|
|
@@ -752,7 +754,7 @@ static int __init initialize_ptr_random(void)
|
|
return 0;
|
|
}
|
|
|
|
- ret = add_random_ready_callback(&random_ready);
|
|
+ ret = register_random_ready_notifier(&random_ready);
|
|
if (!ret) {
|
|
return 0;
|
|
} else if (ret == -EALREADY) {
|
|
diff --git a/mm/util.c b/mm/util.c
|
|
index ab358c64bbd3e..04ebc76588aac 100644
|
|
--- a/mm/util.c
|
|
+++ b/mm/util.c
|
|
@@ -320,6 +320,38 @@ unsigned long randomize_stack_top(unsigned long stack_top)
|
|
#endif
|
|
}
|
|
|
|
+/**
|
|
+ * randomize_page - Generate a random, page aligned address
|
|
+ * @start: The smallest acceptable address the caller will take.
|
|
+ * @range: The size of the area, starting at @start, within which the
|
|
+ * random address must fall.
|
|
+ *
|
|
+ * If @start + @range would overflow, @range is capped.
|
|
+ *
|
|
+ * NOTE: Historical use of randomize_range, which this replaces, presumed that
|
|
+ * @start was already page aligned. We now align it regardless.
|
|
+ *
|
|
+ * Return: A page aligned address within [start, start + range). On error,
|
|
+ * @start is returned.
|
|
+ */
|
|
+unsigned long randomize_page(unsigned long start, unsigned long range)
|
|
+{
|
|
+ if (!PAGE_ALIGNED(start)) {
|
|
+ range -= PAGE_ALIGN(start) - start;
|
|
+ start = PAGE_ALIGN(start);
|
|
+ }
|
|
+
|
|
+ if (start > ULONG_MAX - range)
|
|
+ range = ULONG_MAX - start;
|
|
+
|
|
+ range >>= PAGE_SHIFT;
|
|
+
|
|
+ if (range == 0)
|
|
+ return start;
|
|
+
|
|
+ return start + (get_random_long() % range << PAGE_SHIFT);
|
|
+}
|
|
+
|
|
#ifdef CONFIG_ARCH_WANT_DEFAULT_TOPDOWN_MMAP_LAYOUT
|
|
unsigned long arch_randomize_brk(struct mm_struct *mm)
|
|
{
|
|
diff --git a/net/l2tp/l2tp_ip6.c b/net/l2tp/l2tp_ip6.c
|
|
index 0fa694bd3f6a9..23e9ce985ed6a 100644
|
|
--- a/net/l2tp/l2tp_ip6.c
|
|
+++ b/net/l2tp/l2tp_ip6.c
|
|
@@ -515,14 +515,15 @@ static int l2tp_ip6_sendmsg(struct sock *sk, struct msghdr *msg, size_t len)
|
|
struct ipcm6_cookie ipc6;
|
|
int addr_len = msg->msg_namelen;
|
|
int transhdrlen = 4; /* zero session-id */
|
|
- int ulen = len + transhdrlen;
|
|
+ int ulen;
|
|
int err;
|
|
|
|
/* Rough check on arithmetic overflow,
|
|
better check is made in ip6_append_data().
|
|
*/
|
|
- if (len > INT_MAX)
|
|
+ if (len > INT_MAX - transhdrlen)
|
|
return -EMSGSIZE;
|
|
+ ulen = len + transhdrlen;
|
|
|
|
/* Mirror BSD error message compatibility */
|
|
if (msg->msg_flags & MSG_OOB)
|
|
diff --git a/net/openvswitch/actions.c b/net/openvswitch/actions.c
|
|
index ae40593daf214..9e8a5c4862d04 100644
|
|
--- a/net/openvswitch/actions.c
|
|
+++ b/net/openvswitch/actions.c
|
|
@@ -377,6 +377,7 @@ static void set_ip_addr(struct sk_buff *skb, struct iphdr *nh,
|
|
update_ip_l4_checksum(skb, nh, *addr, new_addr);
|
|
csum_replace4(&nh->check, *addr, new_addr);
|
|
skb_clear_hash(skb);
|
|
+ ovs_ct_clear(skb, NULL);
|
|
*addr = new_addr;
|
|
}
|
|
|
|
@@ -424,6 +425,7 @@ static void set_ipv6_addr(struct sk_buff *skb, u8 l4_proto,
|
|
update_ipv6_checksum(skb, l4_proto, addr, new_addr);
|
|
|
|
skb_clear_hash(skb);
|
|
+ ovs_ct_clear(skb, NULL);
|
|
memcpy(addr, new_addr, sizeof(__be32[4]));
|
|
}
|
|
|
|
@@ -664,6 +666,7 @@ static int set_nsh(struct sk_buff *skb, struct sw_flow_key *flow_key,
|
|
static void set_tp_port(struct sk_buff *skb, __be16 *port,
|
|
__be16 new_port, __sum16 *check)
|
|
{
|
|
+ ovs_ct_clear(skb, NULL);
|
|
inet_proto_csum_replace2(check, skb, *port, new_port, false);
|
|
*port = new_port;
|
|
}
|
|
@@ -703,6 +706,7 @@ static int set_udp(struct sk_buff *skb, struct sw_flow_key *flow_key,
|
|
uh->dest = dst;
|
|
flow_key->tp.src = src;
|
|
flow_key->tp.dst = dst;
|
|
+ ovs_ct_clear(skb, NULL);
|
|
}
|
|
|
|
skb_clear_hash(skb);
|
|
@@ -765,6 +769,8 @@ static int set_sctp(struct sk_buff *skb, struct sw_flow_key *flow_key,
|
|
sh->checksum = old_csum ^ old_correct_csum ^ new_csum;
|
|
|
|
skb_clear_hash(skb);
|
|
+ ovs_ct_clear(skb, NULL);
|
|
+
|
|
flow_key->tp.src = sh->source;
|
|
flow_key->tp.dst = sh->dest;
|
|
|
|
diff --git a/net/openvswitch/conntrack.c b/net/openvswitch/conntrack.c
|
|
index 816036b9c223a..78448b6888ddc 100644
|
|
--- a/net/openvswitch/conntrack.c
|
|
+++ b/net/openvswitch/conntrack.c
|
|
@@ -1319,7 +1319,8 @@ int ovs_ct_clear(struct sk_buff *skb, struct sw_flow_key *key)
|
|
if (skb_nfct(skb)) {
|
|
nf_conntrack_put(skb_nfct(skb));
|
|
nf_ct_set(skb, NULL, IP_CT_UNTRACKED);
|
|
- ovs_ct_fill_key(skb, key);
|
|
+ if (key)
|
|
+ ovs_ct_fill_key(skb, key);
|
|
}
|
|
|
|
return 0;
|
|
diff --git a/net/openvswitch/flow_netlink.c b/net/openvswitch/flow_netlink.c
|
|
index 8461de79f67b4..67125939d7eee 100644
|
|
--- a/net/openvswitch/flow_netlink.c
|
|
+++ b/net/openvswitch/flow_netlink.c
|
|
@@ -2266,6 +2266,51 @@ static struct sw_flow_actions *nla_alloc_flow_actions(int size)
|
|
return sfa;
|
|
}
|
|
|
|
+static void ovs_nla_free_nested_actions(const struct nlattr *actions, int len);
|
|
+
|
|
+static void ovs_nla_free_check_pkt_len_action(const struct nlattr *action)
|
|
+{
|
|
+ const struct nlattr *a;
|
|
+ int rem;
|
|
+
|
|
+ nla_for_each_nested(a, action, rem) {
|
|
+ switch (nla_type(a)) {
|
|
+ case OVS_CHECK_PKT_LEN_ATTR_ACTIONS_IF_LESS_EQUAL:
|
|
+ case OVS_CHECK_PKT_LEN_ATTR_ACTIONS_IF_GREATER:
|
|
+ ovs_nla_free_nested_actions(nla_data(a), nla_len(a));
|
|
+ break;
|
|
+ }
|
|
+ }
|
|
+}
|
|
+
|
|
+static void ovs_nla_free_clone_action(const struct nlattr *action)
|
|
+{
|
|
+ const struct nlattr *a = nla_data(action);
|
|
+ int rem = nla_len(action);
|
|
+
|
|
+ switch (nla_type(a)) {
|
|
+ case OVS_CLONE_ATTR_EXEC:
|
|
+ /* The real list of actions follows this attribute. */
|
|
+ a = nla_next(a, &rem);
|
|
+ ovs_nla_free_nested_actions(a, rem);
|
|
+ break;
|
|
+ }
|
|
+}
|
|
+
|
|
+static void ovs_nla_free_sample_action(const struct nlattr *action)
|
|
+{
|
|
+ const struct nlattr *a = nla_data(action);
|
|
+ int rem = nla_len(action);
|
|
+
|
|
+ switch (nla_type(a)) {
|
|
+ case OVS_SAMPLE_ATTR_ARG:
|
|
+ /* The real list of actions follows this attribute. */
|
|
+ a = nla_next(a, &rem);
|
|
+ ovs_nla_free_nested_actions(a, rem);
|
|
+ break;
|
|
+ }
|
|
+}
|
|
+
|
|
static void ovs_nla_free_set_action(const struct nlattr *a)
|
|
{
|
|
const struct nlattr *ovs_key = nla_data(a);
|
|
@@ -2279,25 +2324,50 @@ static void ovs_nla_free_set_action(const struct nlattr *a)
|
|
}
|
|
}
|
|
|
|
-void ovs_nla_free_flow_actions(struct sw_flow_actions *sf_acts)
|
|
+static void ovs_nla_free_nested_actions(const struct nlattr *actions, int len)
|
|
{
|
|
const struct nlattr *a;
|
|
int rem;
|
|
|
|
- if (!sf_acts)
|
|
+ /* Whenever new actions are added, the need to update this
|
|
+ * function should be considered.
|
|
+ */
|
|
+ BUILD_BUG_ON(OVS_ACTION_ATTR_MAX != 21);
|
|
+
|
|
+ if (!actions)
|
|
return;
|
|
|
|
- nla_for_each_attr(a, sf_acts->actions, sf_acts->actions_len, rem) {
|
|
+ nla_for_each_attr(a, actions, len, rem) {
|
|
switch (nla_type(a)) {
|
|
- case OVS_ACTION_ATTR_SET:
|
|
- ovs_nla_free_set_action(a);
|
|
+ case OVS_ACTION_ATTR_CHECK_PKT_LEN:
|
|
+ ovs_nla_free_check_pkt_len_action(a);
|
|
break;
|
|
+
|
|
+ case OVS_ACTION_ATTR_CLONE:
|
|
+ ovs_nla_free_clone_action(a);
|
|
+ break;
|
|
+
|
|
case OVS_ACTION_ATTR_CT:
|
|
ovs_ct_free_action(a);
|
|
break;
|
|
+
|
|
+ case OVS_ACTION_ATTR_SAMPLE:
|
|
+ ovs_nla_free_sample_action(a);
|
|
+ break;
|
|
+
|
|
+ case OVS_ACTION_ATTR_SET:
|
|
+ ovs_nla_free_set_action(a);
|
|
+ break;
|
|
}
|
|
}
|
|
+}
|
|
+
|
|
+void ovs_nla_free_flow_actions(struct sw_flow_actions *sf_acts)
|
|
+{
|
|
+ if (!sf_acts)
|
|
+ return;
|
|
|
|
+ ovs_nla_free_nested_actions(sf_acts->actions, sf_acts->actions_len);
|
|
kfree(sf_acts);
|
|
}
|
|
|
|
diff --git a/net/sched/act_police.c b/net/sched/act_police.c
|
|
index 8fd23a8b88a5e..a7660b602237d 100644
|
|
--- a/net/sched/act_police.c
|
|
+++ b/net/sched/act_police.c
|
|
@@ -213,6 +213,20 @@ release_idr:
|
|
return err;
|
|
}
|
|
|
|
+static bool tcf_police_mtu_check(struct sk_buff *skb, u32 limit)
|
|
+{
|
|
+ u32 len;
|
|
+
|
|
+ if (skb_is_gso(skb))
|
|
+ return skb_gso_validate_mac_len(skb, limit);
|
|
+
|
|
+ len = qdisc_pkt_len(skb);
|
|
+ if (skb_at_tc_ingress(skb))
|
|
+ len += skb->mac_len;
|
|
+
|
|
+ return len <= limit;
|
|
+}
|
|
+
|
|
static int tcf_police_act(struct sk_buff *skb, const struct tc_action *a,
|
|
struct tcf_result *res)
|
|
{
|
|
@@ -235,7 +249,7 @@ static int tcf_police_act(struct sk_buff *skb, const struct tc_action *a,
|
|
goto inc_overlimits;
|
|
}
|
|
|
|
- if (qdisc_pkt_len(skb) <= p->tcfp_mtu) {
|
|
+ if (tcf_police_mtu_check(skb, p->tcfp_mtu)) {
|
|
if (!p->rate_present) {
|
|
ret = p->tcfp_result;
|
|
goto end;
|
|
diff --git a/scripts/faddr2line b/scripts/faddr2line
|
|
index 0e6268d598835..94ed98dd899f3 100755
|
|
--- a/scripts/faddr2line
|
|
+++ b/scripts/faddr2line
|
|
@@ -95,17 +95,25 @@ __faddr2line() {
|
|
local print_warnings=$4
|
|
|
|
local sym_name=${func_addr%+*}
|
|
- local offset=${func_addr#*+}
|
|
- offset=${offset%/*}
|
|
+ local func_offset=${func_addr#*+}
|
|
+ func_offset=${func_offset%/*}
|
|
local user_size=
|
|
+ local file_type
|
|
+ local is_vmlinux=0
|
|
[[ $func_addr =~ "/" ]] && user_size=${func_addr#*/}
|
|
|
|
- if [[ -z $sym_name ]] || [[ -z $offset ]] || [[ $sym_name = $func_addr ]]; then
|
|
+ if [[ -z $sym_name ]] || [[ -z $func_offset ]] || [[ $sym_name = $func_addr ]]; then
|
|
warn "bad func+offset $func_addr"
|
|
DONE=1
|
|
return
|
|
fi
|
|
|
|
+ # vmlinux uses absolute addresses in the section table rather than
|
|
+ # section offsets.
|
|
+ local file_type=$(${READELF} --file-header $objfile |
|
|
+ ${AWK} '$1 == "Type:" { print $2; exit }')
|
|
+ [[ $file_type = "EXEC" ]] && is_vmlinux=1
|
|
+
|
|
# Go through each of the object's symbols which match the func name.
|
|
# In rare cases there might be duplicates, in which case we print all
|
|
# matches.
|
|
@@ -114,9 +122,11 @@ __faddr2line() {
|
|
local sym_addr=0x${fields[1]}
|
|
local sym_elf_size=${fields[2]}
|
|
local sym_sec=${fields[6]}
|
|
+ local sec_size
|
|
+ local sec_name
|
|
|
|
# Get the section size:
|
|
- local sec_size=$(${READELF} --section-headers --wide $objfile |
|
|
+ sec_size=$(${READELF} --section-headers --wide $objfile |
|
|
sed 's/\[ /\[/' |
|
|
${AWK} -v sec=$sym_sec '$1 == "[" sec "]" { print "0x" $6; exit }')
|
|
|
|
@@ -126,6 +136,17 @@ __faddr2line() {
|
|
return
|
|
fi
|
|
|
|
+ # Get the section name:
|
|
+ sec_name=$(${READELF} --section-headers --wide $objfile |
|
|
+ sed 's/\[ /\[/' |
|
|
+ ${AWK} -v sec=$sym_sec '$1 == "[" sec "]" { print $2; exit }')
|
|
+
|
|
+ if [[ -z $sec_name ]]; then
|
|
+ warn "bad section name: section: $sym_sec"
|
|
+ DONE=1
|
|
+ return
|
|
+ fi
|
|
+
|
|
# Calculate the symbol size.
|
|
#
|
|
# Unfortunately we can't use the ELF size, because kallsyms
|
|
@@ -174,10 +195,10 @@ __faddr2line() {
|
|
|
|
sym_size=0x$(printf %x $sym_size)
|
|
|
|
- # Calculate the section address from user-supplied offset:
|
|
- local addr=$(($sym_addr + $offset))
|
|
+ # Calculate the address from user-supplied offset:
|
|
+ local addr=$(($sym_addr + $func_offset))
|
|
if [[ -z $addr ]] || [[ $addr = 0 ]]; then
|
|
- warn "bad address: $sym_addr + $offset"
|
|
+ warn "bad address: $sym_addr + $func_offset"
|
|
DONE=1
|
|
return
|
|
fi
|
|
@@ -191,9 +212,9 @@ __faddr2line() {
|
|
fi
|
|
|
|
# Make sure the provided offset is within the symbol's range:
|
|
- if [[ $offset -gt $sym_size ]]; then
|
|
+ if [[ $func_offset -gt $sym_size ]]; then
|
|
[[ $print_warnings = 1 ]] &&
|
|
- echo "skipping $sym_name address at $addr due to size mismatch ($offset > $sym_size)"
|
|
+ echo "skipping $sym_name address at $addr due to size mismatch ($func_offset > $sym_size)"
|
|
continue
|
|
fi
|
|
|
|
@@ -202,11 +223,13 @@ __faddr2line() {
|
|
[[ $FIRST = 0 ]] && echo
|
|
FIRST=0
|
|
|
|
- echo "$sym_name+$offset/$sym_size:"
|
|
+ echo "$sym_name+$func_offset/$sym_size:"
|
|
|
|
# Pass section address to addr2line and strip absolute paths
|
|
# from the output:
|
|
- local output=$(${ADDR2LINE} -fpie $objfile $addr | sed "s; $dir_prefix\(\./\)*; ;")
|
|
+ local args="--functions --pretty-print --inlines --exe=$objfile"
|
|
+ [[ $is_vmlinux = 0 ]] && args="$args --section=$sec_name"
|
|
+ local output=$(${ADDR2LINE} $args $addr | sed "s; $dir_prefix\(\./\)*; ;")
|
|
[[ -z $output ]] && continue
|
|
|
|
# Default output (non --list):
|
|
diff --git a/sound/hda/hdac_device.c b/sound/hda/hdac_device.c
|
|
index b84e12f4f8046..489f996d86bcb 100644
|
|
--- a/sound/hda/hdac_device.c
|
|
+++ b/sound/hda/hdac_device.c
|
|
@@ -656,6 +656,7 @@ static struct hda_vendor_id hda_vendor_ids[] = {
|
|
{ 0x14f1, "Conexant" },
|
|
{ 0x17e8, "Chrontel" },
|
|
{ 0x1854, "LG" },
|
|
+ { 0x19e5, "Huawei" },
|
|
{ 0x1aec, "Wolfson Microelectronics" },
|
|
{ 0x1af4, "QEMU" },
|
|
{ 0x434d, "C-Media" },
|
|
diff --git a/sound/pci/hda/patch_realtek.c b/sound/pci/hda/patch_realtek.c
|
|
index 8a221866ab01b..8c37de7793463 100644
|
|
--- a/sound/pci/hda/patch_realtek.c
|
|
+++ b/sound/pci/hda/patch_realtek.c
|
|
@@ -382,6 +382,7 @@ static void alc_fill_eapd_coef(struct hda_codec *codec)
|
|
case 0x10ec0245:
|
|
case 0x10ec0255:
|
|
case 0x10ec0256:
|
|
+ case 0x19e58326:
|
|
case 0x10ec0257:
|
|
case 0x10ec0282:
|
|
case 0x10ec0283:
|
|
@@ -519,6 +520,7 @@ static void alc_shutup_pins(struct hda_codec *codec)
|
|
switch (codec->core.vendor_id) {
|
|
case 0x10ec0236:
|
|
case 0x10ec0256:
|
|
+ case 0x19e58326:
|
|
case 0x10ec0283:
|
|
case 0x10ec0286:
|
|
case 0x10ec0288:
|
|
@@ -3194,6 +3196,7 @@ static void alc_disable_headset_jack_key(struct hda_codec *codec)
|
|
case 0x10ec0230:
|
|
case 0x10ec0236:
|
|
case 0x10ec0256:
|
|
+ case 0x19e58326:
|
|
alc_write_coef_idx(codec, 0x48, 0x0);
|
|
alc_update_coef_idx(codec, 0x49, 0x0045, 0x0);
|
|
break;
|
|
@@ -3222,6 +3225,7 @@ static void alc_enable_headset_jack_key(struct hda_codec *codec)
|
|
case 0x10ec0230:
|
|
case 0x10ec0236:
|
|
case 0x10ec0256:
|
|
+ case 0x19e58326:
|
|
alc_write_coef_idx(codec, 0x48, 0xd011);
|
|
alc_update_coef_idx(codec, 0x49, 0x007f, 0x0045);
|
|
break;
|
|
@@ -4292,6 +4296,12 @@ static void alc_fixup_hp_gpio_led(struct hda_codec *codec,
|
|
}
|
|
}
|
|
|
|
+static void alc236_fixup_hp_gpio_led(struct hda_codec *codec,
|
|
+ const struct hda_fixup *fix, int action)
|
|
+{
|
|
+ alc_fixup_hp_gpio_led(codec, action, 0x02, 0x01);
|
|
+}
|
|
+
|
|
static void alc269_fixup_hp_gpio_led(struct hda_codec *codec,
|
|
const struct hda_fixup *fix, int action)
|
|
{
|
|
@@ -4684,6 +4694,7 @@ static void alc_headset_mode_unplugged(struct hda_codec *codec)
|
|
case 0x10ec0230:
|
|
case 0x10ec0236:
|
|
case 0x10ec0256:
|
|
+ case 0x19e58326:
|
|
alc_process_coef_fw(codec, coef0256);
|
|
break;
|
|
case 0x10ec0234:
|
|
@@ -4799,6 +4810,7 @@ static void alc_headset_mode_mic_in(struct hda_codec *codec, hda_nid_t hp_pin,
|
|
case 0x10ec0230:
|
|
case 0x10ec0236:
|
|
case 0x10ec0256:
|
|
+ case 0x19e58326:
|
|
alc_write_coef_idx(codec, 0x45, 0xc489);
|
|
snd_hda_set_pin_ctl_cache(codec, hp_pin, 0);
|
|
alc_process_coef_fw(codec, coef0256);
|
|
@@ -4949,6 +4961,7 @@ static void alc_headset_mode_default(struct hda_codec *codec)
|
|
case 0x10ec0230:
|
|
case 0x10ec0236:
|
|
case 0x10ec0256:
|
|
+ case 0x19e58326:
|
|
alc_write_coef_idx(codec, 0x1b, 0x0e4b);
|
|
alc_write_coef_idx(codec, 0x45, 0xc089);
|
|
msleep(50);
|
|
@@ -5048,6 +5061,7 @@ static void alc_headset_mode_ctia(struct hda_codec *codec)
|
|
case 0x10ec0230:
|
|
case 0x10ec0236:
|
|
case 0x10ec0256:
|
|
+ case 0x19e58326:
|
|
alc_process_coef_fw(codec, coef0256);
|
|
break;
|
|
case 0x10ec0234:
|
|
@@ -5162,6 +5176,7 @@ static void alc_headset_mode_omtp(struct hda_codec *codec)
|
|
case 0x10ec0230:
|
|
case 0x10ec0236:
|
|
case 0x10ec0256:
|
|
+ case 0x19e58326:
|
|
alc_process_coef_fw(codec, coef0256);
|
|
break;
|
|
case 0x10ec0234:
|
|
@@ -5258,6 +5273,7 @@ static void alc_determine_headset_type(struct hda_codec *codec)
|
|
case 0x10ec0230:
|
|
case 0x10ec0236:
|
|
case 0x10ec0256:
|
|
+ case 0x19e58326:
|
|
alc_write_coef_idx(codec, 0x1b, 0x0e4b);
|
|
alc_write_coef_idx(codec, 0x06, 0x6104);
|
|
alc_write_coefex_idx(codec, 0x57, 0x3, 0x09a3);
|
|
@@ -5552,6 +5568,7 @@ static void alc255_set_default_jack_type(struct hda_codec *codec)
|
|
case 0x10ec0230:
|
|
case 0x10ec0236:
|
|
case 0x10ec0256:
|
|
+ case 0x19e58326:
|
|
alc_process_coef_fw(codec, alc256fw);
|
|
break;
|
|
}
|
|
@@ -6155,6 +6172,7 @@ static void alc_combo_jack_hp_jd_restart(struct hda_codec *codec)
|
|
case 0x10ec0236:
|
|
case 0x10ec0255:
|
|
case 0x10ec0256:
|
|
+ case 0x19e58326:
|
|
alc_update_coef_idx(codec, 0x1b, 0x8000, 1 << 15); /* Reset HP JD */
|
|
alc_update_coef_idx(codec, 0x1b, 0x8000, 0 << 15);
|
|
break;
|
|
@@ -6465,6 +6483,7 @@ enum {
|
|
ALC294_FIXUP_ASUS_GU502_VERBS,
|
|
ALC285_FIXUP_HP_GPIO_LED,
|
|
ALC285_FIXUP_HP_MUTE_LED,
|
|
+ ALC236_FIXUP_HP_GPIO_LED,
|
|
ALC236_FIXUP_HP_MUTE_LED,
|
|
ALC298_FIXUP_SAMSUNG_HEADPHONE_VERY_QUIET,
|
|
ALC256_FIXUP_SAMSUNG_HEADPHONE_VERY_QUIET,
|
|
@@ -7741,6 +7760,10 @@ static const struct hda_fixup alc269_fixups[] = {
|
|
.type = HDA_FIXUP_FUNC,
|
|
.v.func = alc285_fixup_hp_mute_led,
|
|
},
|
|
+ [ALC236_FIXUP_HP_GPIO_LED] = {
|
|
+ .type = HDA_FIXUP_FUNC,
|
|
+ .v.func = alc236_fixup_hp_gpio_led,
|
|
+ },
|
|
[ALC236_FIXUP_HP_MUTE_LED] = {
|
|
.type = HDA_FIXUP_FUNC,
|
|
.v.func = alc236_fixup_hp_mute_led,
|
|
@@ -8162,6 +8185,8 @@ static const struct snd_pci_quirk alc269_fixup_tbl[] = {
|
|
SND_PCI_QUIRK(0x103c, 0x8760, "HP", ALC285_FIXUP_HP_MUTE_LED),
|
|
SND_PCI_QUIRK(0x103c, 0x877a, "HP", ALC285_FIXUP_HP_MUTE_LED),
|
|
SND_PCI_QUIRK(0x103c, 0x877d, "HP", ALC236_FIXUP_HP_MUTE_LED),
|
|
+ SND_PCI_QUIRK(0x103c, 0x87e5, "HP ProBook 440 G8 Notebook PC", ALC236_FIXUP_HP_GPIO_LED),
|
|
+ SND_PCI_QUIRK(0x103c, 0x89aa, "HP EliteBook 630 G9", ALC236_FIXUP_HP_GPIO_LED),
|
|
SND_PCI_QUIRK(0x1043, 0x103e, "ASUS X540SA", ALC256_FIXUP_ASUS_MIC),
|
|
SND_PCI_QUIRK(0x1043, 0x103f, "ASUS TX300", ALC282_FIXUP_ASUS_TX300),
|
|
SND_PCI_QUIRK(0x1043, 0x106d, "Asus K53BE", ALC269_FIXUP_LIMIT_INT_MIC_BOOST),
|
|
@@ -9160,6 +9185,7 @@ static int patch_alc269(struct hda_codec *codec)
|
|
case 0x10ec0230:
|
|
case 0x10ec0236:
|
|
case 0x10ec0256:
|
|
+ case 0x19e58326:
|
|
spec->codec_variant = ALC269_TYPE_ALC256;
|
|
spec->shutup = alc256_shutup;
|
|
spec->init_hook = alc256_init;
|
|
@@ -10602,6 +10628,7 @@ static const struct hda_device_id snd_hda_id_realtek[] = {
|
|
HDA_CODEC_ENTRY(0x10ec0b00, "ALCS1200A", patch_alc882),
|
|
HDA_CODEC_ENTRY(0x10ec1168, "ALC1220", patch_alc882),
|
|
HDA_CODEC_ENTRY(0x10ec1220, "ALC1220", patch_alc882),
|
|
+ HDA_CODEC_ENTRY(0x19e58326, "HW8326", patch_alc269),
|
|
{} /* terminator */
|
|
};
|
|
MODULE_DEVICE_TABLE(hdaudio, snd_hda_id_realtek);
|
|
diff --git a/sound/soc/codecs/cs35l36.c b/sound/soc/codecs/cs35l36.c
|
|
index e9b5f76f27a86..aa32b8c26578a 100644
|
|
--- a/sound/soc/codecs/cs35l36.c
|
|
+++ b/sound/soc/codecs/cs35l36.c
|
|
@@ -444,7 +444,8 @@ static bool cs35l36_volatile_reg(struct device *dev, unsigned int reg)
|
|
}
|
|
}
|
|
|
|
-static DECLARE_TLV_DB_SCALE(dig_vol_tlv, -10200, 25, 0);
|
|
+static const DECLARE_TLV_DB_RANGE(dig_vol_tlv, 0, 912,
|
|
+ TLV_DB_MINMAX_ITEM(-10200, 1200));
|
|
static DECLARE_TLV_DB_SCALE(amp_gain_tlv, 0, 1, 1);
|
|
|
|
static const char * const cs35l36_pcm_sftramp_text[] = {
|
|
diff --git a/sound/soc/codecs/cs42l52.c b/sound/soc/codecs/cs42l52.c
|
|
index 2ea4cba3be2ad..6c054b357205b 100644
|
|
--- a/sound/soc/codecs/cs42l52.c
|
|
+++ b/sound/soc/codecs/cs42l52.c
|
|
@@ -137,7 +137,9 @@ static DECLARE_TLV_DB_SCALE(mic_tlv, 1600, 100, 0);
|
|
|
|
static DECLARE_TLV_DB_SCALE(pga_tlv, -600, 50, 0);
|
|
|
|
-static DECLARE_TLV_DB_SCALE(mix_tlv, -50, 50, 0);
|
|
+static DECLARE_TLV_DB_SCALE(pass_tlv, -6000, 50, 0);
|
|
+
|
|
+static DECLARE_TLV_DB_SCALE(mix_tlv, -5150, 50, 0);
|
|
|
|
static DECLARE_TLV_DB_SCALE(beep_tlv, -56, 200, 0);
|
|
|
|
@@ -351,7 +353,7 @@ static const struct snd_kcontrol_new cs42l52_snd_controls[] = {
|
|
CS42L52_SPKB_VOL, 0, 0x40, 0xC0, hl_tlv),
|
|
|
|
SOC_DOUBLE_R_SX_TLV("Bypass Volume", CS42L52_PASSTHRUA_VOL,
|
|
- CS42L52_PASSTHRUB_VOL, 0, 0x88, 0x90, pga_tlv),
|
|
+ CS42L52_PASSTHRUB_VOL, 0, 0x88, 0x90, pass_tlv),
|
|
|
|
SOC_DOUBLE("Bypass Mute", CS42L52_MISC_CTL, 4, 5, 1, 0),
|
|
|
|
@@ -364,7 +366,7 @@ static const struct snd_kcontrol_new cs42l52_snd_controls[] = {
|
|
CS42L52_ADCB_VOL, 0, 0xA0, 0x78, ipd_tlv),
|
|
SOC_DOUBLE_R_SX_TLV("ADC Mixer Volume",
|
|
CS42L52_ADCA_MIXER_VOL, CS42L52_ADCB_MIXER_VOL,
|
|
- 0, 0x19, 0x7F, ipd_tlv),
|
|
+ 0, 0x19, 0x7F, mix_tlv),
|
|
|
|
SOC_DOUBLE("ADC Switch", CS42L52_ADC_MISC_CTL, 0, 1, 1, 0),
|
|
|
|
diff --git a/sound/soc/codecs/cs42l56.c b/sound/soc/codecs/cs42l56.c
|
|
index 51d7a87ab4c3b..8be7d83f0ce9a 100644
|
|
--- a/sound/soc/codecs/cs42l56.c
|
|
+++ b/sound/soc/codecs/cs42l56.c
|
|
@@ -391,9 +391,9 @@ static const struct snd_kcontrol_new cs42l56_snd_controls[] = {
|
|
SOC_DOUBLE("ADC Boost Switch", CS42L56_GAIN_BIAS_CTL, 3, 2, 1, 1),
|
|
|
|
SOC_DOUBLE_R_SX_TLV("Headphone Volume", CS42L56_HPA_VOLUME,
|
|
- CS42L56_HPB_VOLUME, 0, 0x84, 0x48, hl_tlv),
|
|
+ CS42L56_HPB_VOLUME, 0, 0x44, 0x48, hl_tlv),
|
|
SOC_DOUBLE_R_SX_TLV("LineOut Volume", CS42L56_LOA_VOLUME,
|
|
- CS42L56_LOB_VOLUME, 0, 0x84, 0x48, hl_tlv),
|
|
+ CS42L56_LOB_VOLUME, 0, 0x44, 0x48, hl_tlv),
|
|
|
|
SOC_SINGLE_TLV("Bass Shelving Volume", CS42L56_TONE_CTL,
|
|
0, 0x00, 1, tone_tlv),
|
|
diff --git a/sound/soc/codecs/cs53l30.c b/sound/soc/codecs/cs53l30.c
|
|
index ed22361b35c14..a5a383b923054 100644
|
|
--- a/sound/soc/codecs/cs53l30.c
|
|
+++ b/sound/soc/codecs/cs53l30.c
|
|
@@ -347,22 +347,22 @@ static const struct snd_kcontrol_new cs53l30_snd_controls[] = {
|
|
SOC_ENUM("ADC2 NG Delay", adc2_ng_delay_enum),
|
|
|
|
SOC_SINGLE_SX_TLV("ADC1A PGA Volume",
|
|
- CS53L30_ADC1A_AFE_CTL, 0, 0x34, 0x18, pga_tlv),
|
|
+ CS53L30_ADC1A_AFE_CTL, 0, 0x34, 0x24, pga_tlv),
|
|
SOC_SINGLE_SX_TLV("ADC1B PGA Volume",
|
|
- CS53L30_ADC1B_AFE_CTL, 0, 0x34, 0x18, pga_tlv),
|
|
+ CS53L30_ADC1B_AFE_CTL, 0, 0x34, 0x24, pga_tlv),
|
|
SOC_SINGLE_SX_TLV("ADC2A PGA Volume",
|
|
- CS53L30_ADC2A_AFE_CTL, 0, 0x34, 0x18, pga_tlv),
|
|
+ CS53L30_ADC2A_AFE_CTL, 0, 0x34, 0x24, pga_tlv),
|
|
SOC_SINGLE_SX_TLV("ADC2B PGA Volume",
|
|
- CS53L30_ADC2B_AFE_CTL, 0, 0x34, 0x18, pga_tlv),
|
|
+ CS53L30_ADC2B_AFE_CTL, 0, 0x34, 0x24, pga_tlv),
|
|
|
|
SOC_SINGLE_SX_TLV("ADC1A Digital Volume",
|
|
- CS53L30_ADC1A_DIG_VOL, 0, 0xA0, 0x0C, dig_tlv),
|
|
+ CS53L30_ADC1A_DIG_VOL, 0, 0xA0, 0x6C, dig_tlv),
|
|
SOC_SINGLE_SX_TLV("ADC1B Digital Volume",
|
|
- CS53L30_ADC1B_DIG_VOL, 0, 0xA0, 0x0C, dig_tlv),
|
|
+ CS53L30_ADC1B_DIG_VOL, 0, 0xA0, 0x6C, dig_tlv),
|
|
SOC_SINGLE_SX_TLV("ADC2A Digital Volume",
|
|
- CS53L30_ADC2A_DIG_VOL, 0, 0xA0, 0x0C, dig_tlv),
|
|
+ CS53L30_ADC2A_DIG_VOL, 0, 0xA0, 0x6C, dig_tlv),
|
|
SOC_SINGLE_SX_TLV("ADC2B Digital Volume",
|
|
- CS53L30_ADC2B_DIG_VOL, 0, 0xA0, 0x0C, dig_tlv),
|
|
+ CS53L30_ADC2B_DIG_VOL, 0, 0xA0, 0x6C, dig_tlv),
|
|
};
|
|
|
|
static const struct snd_soc_dapm_widget cs53l30_dapm_widgets[] = {
|
|
diff --git a/sound/soc/codecs/es8328.c b/sound/soc/codecs/es8328.c
|
|
index fdf64c29f563d..4117ab6e9b6ff 100644
|
|
--- a/sound/soc/codecs/es8328.c
|
|
+++ b/sound/soc/codecs/es8328.c
|
|
@@ -161,13 +161,16 @@ static int es8328_put_deemph(struct snd_kcontrol *kcontrol,
|
|
if (deemph > 1)
|
|
return -EINVAL;
|
|
|
|
+ if (es8328->deemph == deemph)
|
|
+ return 0;
|
|
+
|
|
ret = es8328_set_deemph(component);
|
|
if (ret < 0)
|
|
return ret;
|
|
|
|
es8328->deemph = deemph;
|
|
|
|
- return 0;
|
|
+ return 1;
|
|
}
|
|
|
|
|
|
diff --git a/sound/soc/codecs/nau8822.c b/sound/soc/codecs/nau8822.c
|
|
index 78db3bd0b3bcb..cd163978792e9 100644
|
|
--- a/sound/soc/codecs/nau8822.c
|
|
+++ b/sound/soc/codecs/nau8822.c
|
|
@@ -740,6 +740,8 @@ static int nau8822_set_pll(struct snd_soc_dai *dai, int pll_id, int source,
|
|
pll_param->pll_int, pll_param->pll_frac,
|
|
pll_param->mclk_scaler, pll_param->pre_factor);
|
|
|
|
+ snd_soc_component_update_bits(component,
|
|
+ NAU8822_REG_POWER_MANAGEMENT_1, NAU8822_PLL_EN_MASK, NAU8822_PLL_OFF);
|
|
snd_soc_component_update_bits(component,
|
|
NAU8822_REG_PLL_N, NAU8822_PLLMCLK_DIV2 | NAU8822_PLLN_MASK,
|
|
(pll_param->pre_factor ? NAU8822_PLLMCLK_DIV2 : 0) |
|
|
@@ -757,6 +759,8 @@ static int nau8822_set_pll(struct snd_soc_dai *dai, int pll_id, int source,
|
|
pll_param->mclk_scaler << NAU8822_MCLKSEL_SFT);
|
|
snd_soc_component_update_bits(component,
|
|
NAU8822_REG_CLOCKING, NAU8822_CLKM_MASK, NAU8822_CLKM_PLL);
|
|
+ snd_soc_component_update_bits(component,
|
|
+ NAU8822_REG_POWER_MANAGEMENT_1, NAU8822_PLL_EN_MASK, NAU8822_PLL_ON);
|
|
|
|
return 0;
|
|
}
|
|
diff --git a/sound/soc/codecs/nau8822.h b/sound/soc/codecs/nau8822.h
|
|
index 489191ff187ec..b45d42c15de6b 100644
|
|
--- a/sound/soc/codecs/nau8822.h
|
|
+++ b/sound/soc/codecs/nau8822.h
|
|
@@ -90,6 +90,9 @@
|
|
#define NAU8822_REFIMP_3K 0x3
|
|
#define NAU8822_IOBUF_EN (0x1 << 2)
|
|
#define NAU8822_ABIAS_EN (0x1 << 3)
|
|
+#define NAU8822_PLL_EN_MASK (0x1 << 5)
|
|
+#define NAU8822_PLL_ON (0x1 << 5)
|
|
+#define NAU8822_PLL_OFF (0x0 << 5)
|
|
|
|
/* NAU8822_REG_AUDIO_INTERFACE (0x4) */
|
|
#define NAU8822_AIFMT_MASK (0x3 << 3)
|
|
diff --git a/sound/soc/codecs/wm8962.c b/sound/soc/codecs/wm8962.c
|
|
index d9d59f45833fd..ebaee468057b8 100644
|
|
--- a/sound/soc/codecs/wm8962.c
|
|
+++ b/sound/soc/codecs/wm8962.c
|
|
@@ -3854,6 +3854,7 @@ static int wm8962_runtime_suspend(struct device *dev)
|
|
#endif
|
|
|
|
static const struct dev_pm_ops wm8962_pm = {
|
|
+ SET_SYSTEM_SLEEP_PM_OPS(pm_runtime_force_suspend, pm_runtime_force_resume)
|
|
SET_RUNTIME_PM_OPS(wm8962_runtime_suspend, wm8962_runtime_resume, NULL)
|
|
};
|
|
|
|
diff --git a/sound/soc/codecs/wm_adsp.c b/sound/soc/codecs/wm_adsp.c
|
|
index 13672928da997..aedfa6b2895bd 100644
|
|
--- a/sound/soc/codecs/wm_adsp.c
|
|
+++ b/sound/soc/codecs/wm_adsp.c
|
|
@@ -791,7 +791,7 @@ int wm_adsp_fw_put(struct snd_kcontrol *kcontrol,
|
|
struct snd_soc_component *component = snd_soc_kcontrol_component(kcontrol);
|
|
struct soc_enum *e = (struct soc_enum *)kcontrol->private_value;
|
|
struct wm_adsp *dsp = snd_soc_component_get_drvdata(component);
|
|
- int ret = 0;
|
|
+ int ret = 1;
|
|
|
|
if (ucontrol->value.enumerated.item[0] == dsp[e->shift_l].fw)
|
|
return 0;
|