Random number generator updates for Linux 6.0-rc1.
-----BEGIN PGP SIGNATURE----- iQIzBAABCAAdFiEEq5lC5tSkz8NBJiCnSfxwEqXeA64FAmLnDOwACgkQSfxwEqXe A65Fiw//Z0YaPejSslQIGitQ1b0XzdWBhyJArYDieaaiQRXMqlaSKlIUqHz38xb7 +FykUY51/SJLjHV2riPxq1OK3/MPmk6VlTd0HHihcHVmg77oZcFcv2tPnDpZoqND TsBOujLbXKwxP8tNFedRY/4+K7w+ue9BTfDjuH7aCtz7uWd+4cNJmPg3x9FCfkMA +hbcRluwE9W3Pg4OCKwv+qxL0JF3qQtNKEOp1wpnjGAZZW/I9gFNgFBEkykvcAsj TkIRDc3agPFj6QgDeRIgLdnf9KCsLubKAg5oJneeCvQztJJUCSkn8nQXxpx+4sLo GsRgvCdfL/GyJqfSAzQJVYDHKtKMkJiCiWCC/oOALR8dzHJfSlULDAjbY1m/DAr9 at+vi4678Or7TNx2ZSaUlCXXKZ+UT7yWMlQWax9JuxGk1hGYP5/eT1AH5SGjqUwF w1q8oyzxt1vUcnOzEddFXPFirnqqhAk4dQFtu83+xKM4ZssMVyeB4NZdEhAdW0ng MX+RjrVj4l5gWWuoS0Cx3LUxDCgV6WT0dN+Vl9axAZkoJJbcXLEmXwQ6NbzTLPWg 1/MT7qFTxNcTCeAArMdZvvFbeh7pOBXO42pafrK/7vDRnTMUIw9tqXNLQUfvdFQp F5flPgiVRHDU2vSzKIFtnPTyXU0RBBGvNb4n0ss2ehH2DSsCxYE= =Zy3d -----END PGP SIGNATURE----- Merge tag 'random-6.0-rc1-for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/crng/random Pull random number generator updates from Jason Donenfeld: "Though there's been a decent amount of RNG-related development during this last cycle, not all of it is coming through this tree, as this cycle saw a shift toward tackling early boot time seeding issues, which took place in other trees as well. Here's a summary of the various patches: - The CONFIG_ARCH_RANDOM .config option and the "nordrand" boot option have been removed, as they overlapped with the more widely supported and more sensible options, CONFIG_RANDOM_TRUST_CPU and "random.trust_cpu". This change allowed simplifying a bit of arch code. - x86's RDRAND boot time test has been made a bit more robust, with RDRAND disabled if it's clearly producing bogus results. This would be a tip.git commit, technically, but I took it through random.git to avoid a large merge conflict. - The RNG has long since mixed in a timestamp very early in boot, on the premise that a computer that does the same things, but does so starting at different points in wall time, could be made to still produce a different RNG state. Unfortunately, the clock isn't set early in boot on all systems, so now we mix in that timestamp when the time is actually set. - User Mode Linux now uses the host OS's getrandom() syscall to generate a bootloader RNG seed and later on treats getrandom() as the platform's RDRAND-like faculty. - The arch_get_random_{seed_,}_long() family of functions is now arch_get_random_{seed_,}_longs(), which enables certain platforms, such as s390, to exploit considerable performance advantages from requesting multiple CPU random numbers at once, while at the same time compiling down to the same code as before on platforms like x86. - A small cleanup changing a cmpxchg() into a try_cmpxchg(), from Uros. - A comment spelling fix" More info about other random number changes that come in through various architecture trees in the full commentary in the pull request: https://lore.kernel.org/all/20220731232428.2219258-1-Jason@zx2c4.com/ * tag 'random-6.0-rc1-for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/crng/random: random: correct spelling of "overwrites" random: handle archrandom with multiple longs um: seed rng using host OS rng random: use try_cmpxchg in _credit_init_bits timekeeping: contribute wall clock to rng on time change x86/rdrand: Remove "nordrand" flag in favor of "random.trust_cpu" random: remove CONFIG_ARCH_RANDOM
This commit is contained in:
commit
a0b09f2d6f
|
@ -3741,11 +3741,6 @@
|
|||
noreplace-smp [X86-32,SMP] Don't replace SMP instructions
|
||||
with UP alternatives
|
||||
|
||||
nordrand [X86] Disable kernel use of the RDRAND and
|
||||
RDSEED instructions even if they are supported
|
||||
by the processor. RDRAND and RDSEED are still
|
||||
available to user space applications.
|
||||
|
||||
noresume [SWSUSP] Disables resume and restores original swap
|
||||
space.
|
||||
|
||||
|
|
|
@ -7,4 +7,6 @@ static inline bool __init smccc_probe_trng(void)
|
|||
return false;
|
||||
}
|
||||
|
||||
#include <asm-generic/archrandom.h>
|
||||
|
||||
#endif /* _ASM_ARCHRANDOM_H */
|
||||
|
|
|
@ -1895,14 +1895,6 @@ config ARM64_E0PD
|
|||
|
||||
This option enables E0PD for TTBR1 where available.
|
||||
|
||||
config ARCH_RANDOM
|
||||
bool "Enable support for random number generation"
|
||||
default y
|
||||
help
|
||||
Random number generation (part of the ARMv8.5 Extensions)
|
||||
provides a high bandwidth, cryptographically secure
|
||||
hardware random number generator.
|
||||
|
||||
config ARM64_AS_HAS_MTE
|
||||
# Initial support for MTE went in binutils 2.32.0, checked with
|
||||
# ".arch armv8.5-a+memtag" below. However, this was incomplete
|
||||
|
|
|
@ -2,8 +2,6 @@
|
|||
#ifndef _ASM_ARCHRANDOM_H
|
||||
#define _ASM_ARCHRANDOM_H
|
||||
|
||||
#ifdef CONFIG_ARCH_RANDOM
|
||||
|
||||
#include <linux/arm-smccc.h>
|
||||
#include <linux/bug.h>
|
||||
#include <linux/kernel.h>
|
||||
|
@ -60,7 +58,7 @@ static inline bool __arm64_rndrrs(unsigned long *v)
|
|||
return ok;
|
||||
}
|
||||
|
||||
static inline bool __must_check arch_get_random_long(unsigned long *v)
|
||||
static inline size_t __must_check arch_get_random_longs(unsigned long *v, size_t max_longs)
|
||||
{
|
||||
/*
|
||||
* Only support the generic interface after we have detected
|
||||
|
@ -68,27 +66,15 @@ static inline bool __must_check arch_get_random_long(unsigned long *v)
|
|||
* cpufeature code and with potential scheduling between CPUs
|
||||
* with and without the feature.
|
||||
*/
|
||||
if (cpus_have_const_cap(ARM64_HAS_RNG) && __arm64_rndr(v))
|
||||
return true;
|
||||
return false;
|
||||
if (max_longs && cpus_have_const_cap(ARM64_HAS_RNG) && __arm64_rndr(v))
|
||||
return 1;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static inline bool __must_check arch_get_random_int(unsigned int *v)
|
||||
static inline size_t __must_check arch_get_random_seed_longs(unsigned long *v, size_t max_longs)
|
||||
{
|
||||
if (cpus_have_const_cap(ARM64_HAS_RNG)) {
|
||||
unsigned long val;
|
||||
|
||||
if (__arm64_rndr(&val)) {
|
||||
*v = val;
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
static inline bool __must_check arch_get_random_seed_long(unsigned long *v)
|
||||
{
|
||||
struct arm_smccc_res res;
|
||||
if (!max_longs)
|
||||
return 0;
|
||||
|
||||
/*
|
||||
* We prefer the SMCCC call, since its semantics (return actual
|
||||
|
@ -97,10 +83,23 @@ static inline bool __must_check arch_get_random_seed_long(unsigned long *v)
|
|||
* (the output of a pseudo RNG freshly seeded by a TRNG).
|
||||
*/
|
||||
if (smccc_trng_available) {
|
||||
arm_smccc_1_1_invoke(ARM_SMCCC_TRNG_RND64, 64, &res);
|
||||
struct arm_smccc_res res;
|
||||
|
||||
max_longs = min_t(size_t, 3, max_longs);
|
||||
arm_smccc_1_1_invoke(ARM_SMCCC_TRNG_RND64, max_longs * 64, &res);
|
||||
if ((int)res.a0 >= 0) {
|
||||
*v = res.a3;
|
||||
return true;
|
||||
switch (max_longs) {
|
||||
case 3:
|
||||
*v++ = res.a1;
|
||||
fallthrough;
|
||||
case 2:
|
||||
*v++ = res.a2;
|
||||
fallthrough;
|
||||
case 1:
|
||||
*v++ = res.a3;
|
||||
break;
|
||||
}
|
||||
return max_longs;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -110,32 +109,9 @@ static inline bool __must_check arch_get_random_seed_long(unsigned long *v)
|
|||
* enough to implement this API if no other entropy source exists.
|
||||
*/
|
||||
if (cpus_have_const_cap(ARM64_HAS_RNG) && __arm64_rndrrs(v))
|
||||
return true;
|
||||
return 1;
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
static inline bool __must_check arch_get_random_seed_int(unsigned int *v)
|
||||
{
|
||||
struct arm_smccc_res res;
|
||||
unsigned long val;
|
||||
|
||||
if (smccc_trng_available) {
|
||||
arm_smccc_1_1_invoke(ARM_SMCCC_TRNG_RND64, 32, &res);
|
||||
if ((int)res.a0 >= 0) {
|
||||
*v = res.a3 & GENMASK(31, 0);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
if (cpus_have_const_cap(ARM64_HAS_RNG)) {
|
||||
if (__arm64_rndrrs(&val)) {
|
||||
*v = val;
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static inline bool __init __early_cpu_has_rndr(void)
|
||||
|
@ -145,34 +121,40 @@ static inline bool __init __early_cpu_has_rndr(void)
|
|||
return (ftr >> ID_AA64ISAR0_EL1_RNDR_SHIFT) & 0xf;
|
||||
}
|
||||
|
||||
static inline bool __init __must_check
|
||||
arch_get_random_seed_long_early(unsigned long *v)
|
||||
static inline size_t __init __must_check
|
||||
arch_get_random_seed_longs_early(unsigned long *v, size_t max_longs)
|
||||
{
|
||||
WARN_ON(system_state != SYSTEM_BOOTING);
|
||||
|
||||
if (!max_longs)
|
||||
return 0;
|
||||
|
||||
if (smccc_trng_available) {
|
||||
struct arm_smccc_res res;
|
||||
|
||||
arm_smccc_1_1_invoke(ARM_SMCCC_TRNG_RND64, 64, &res);
|
||||
max_longs = min_t(size_t, 3, max_longs);
|
||||
arm_smccc_1_1_invoke(ARM_SMCCC_TRNG_RND64, max_longs * 64, &res);
|
||||
if ((int)res.a0 >= 0) {
|
||||
*v = res.a3;
|
||||
return true;
|
||||
switch (max_longs) {
|
||||
case 3:
|
||||
*v++ = res.a1;
|
||||
fallthrough;
|
||||
case 2:
|
||||
*v++ = res.a2;
|
||||
fallthrough;
|
||||
case 1:
|
||||
*v++ = res.a3;
|
||||
break;
|
||||
}
|
||||
return max_longs;
|
||||
}
|
||||
}
|
||||
|
||||
if (__early_cpu_has_rndr() && __arm64_rndr(v))
|
||||
return true;
|
||||
return 1;
|
||||
|
||||
return false;
|
||||
return 0;
|
||||
}
|
||||
#define arch_get_random_seed_long_early arch_get_random_seed_long_early
|
||||
#define arch_get_random_seed_longs_early arch_get_random_seed_longs_early
|
||||
|
||||
#else /* !CONFIG_ARCH_RANDOM */
|
||||
|
||||
static inline bool __init smccc_probe_trng(void)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
#endif /* CONFIG_ARCH_RANDOM */
|
||||
#endif /* _ASM_ARCHRANDOM_H */
|
||||
|
|
|
@ -2502,7 +2502,6 @@ static const struct arm64_cpu_capabilities arm64_features[] = {
|
|||
.cpu_enable = cpu_enable_e0pd,
|
||||
},
|
||||
#endif
|
||||
#ifdef CONFIG_ARCH_RANDOM
|
||||
{
|
||||
.desc = "Random Number Generator",
|
||||
.capability = ARM64_HAS_RNG,
|
||||
|
@ -2514,7 +2513,6 @@ static const struct arm64_cpu_capabilities arm64_features[] = {
|
|||
.sign = FTR_UNSIGNED,
|
||||
.min_field_value = 1,
|
||||
},
|
||||
#endif
|
||||
#ifdef CONFIG_ARM64_BTI
|
||||
{
|
||||
.desc = "Branch Target Identification",
|
||||
|
|
|
@ -1257,9 +1257,6 @@ config PHYSICAL_START
|
|||
default "0x00000000"
|
||||
endif
|
||||
|
||||
config ARCH_RANDOM
|
||||
def_bool n
|
||||
|
||||
config PPC_LIB_RHEAP
|
||||
bool
|
||||
|
||||
|
|
|
@ -2,41 +2,20 @@
|
|||
#ifndef _ASM_POWERPC_ARCHRANDOM_H
|
||||
#define _ASM_POWERPC_ARCHRANDOM_H
|
||||
|
||||
#ifdef CONFIG_ARCH_RANDOM
|
||||
|
||||
#include <asm/machdep.h>
|
||||
|
||||
static inline bool __must_check arch_get_random_long(unsigned long *v)
|
||||
static inline size_t __must_check arch_get_random_longs(unsigned long *v, size_t max_longs)
|
||||
{
|
||||
return false;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static inline bool __must_check arch_get_random_int(unsigned int *v)
|
||||
static inline size_t __must_check arch_get_random_seed_longs(unsigned long *v, size_t max_longs)
|
||||
{
|
||||
return false;
|
||||
if (max_longs && ppc_md.get_random_seed && ppc_md.get_random_seed(v))
|
||||
return 1;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static inline bool __must_check arch_get_random_seed_long(unsigned long *v)
|
||||
{
|
||||
if (ppc_md.get_random_seed)
|
||||
return ppc_md.get_random_seed(v);
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
static inline bool __must_check arch_get_random_seed_int(unsigned int *v)
|
||||
{
|
||||
unsigned long val;
|
||||
bool rc;
|
||||
|
||||
rc = arch_get_random_seed_long(&val);
|
||||
if (rc)
|
||||
*v = val;
|
||||
|
||||
return rc;
|
||||
}
|
||||
#endif /* CONFIG_ARCH_RANDOM */
|
||||
|
||||
#ifdef CONFIG_PPC_POWERNV
|
||||
int powernv_hwrng_present(void);
|
||||
int powernv_get_random_long(unsigned long *v);
|
||||
|
|
|
@ -200,9 +200,7 @@ struct machdep_calls {
|
|||
ssize_t (*cpu_release)(const char *, size_t);
|
||||
#endif
|
||||
|
||||
#ifdef CONFIG_ARCH_RANDOM
|
||||
int (*get_random_seed)(unsigned long *v);
|
||||
#endif
|
||||
};
|
||||
|
||||
extern void e500_idle(void);
|
||||
|
|
|
@ -1207,7 +1207,7 @@ int kvmppc_pseries_do_hcall(struct kvm_vcpu *vcpu)
|
|||
break;
|
||||
#endif
|
||||
case H_RANDOM:
|
||||
if (!arch_get_random_seed_long(&vcpu->arch.regs.gpr[4]))
|
||||
if (!arch_get_random_seed_longs(&vcpu->arch.regs.gpr[4], 1))
|
||||
ret = H_HARDWARE;
|
||||
break;
|
||||
case H_RPT_INVALIDATE:
|
||||
|
|
|
@ -6,7 +6,6 @@ config PPC_MICROWATT
|
|||
select PPC_ICS_NATIVE
|
||||
select PPC_ICP_NATIVE
|
||||
select PPC_UDBG_16550
|
||||
select ARCH_RANDOM
|
||||
help
|
||||
This option enables support for FPGA-based Microwatt implementations.
|
||||
|
||||
|
|
|
@ -12,7 +12,6 @@ config PPC_POWERNV
|
|||
select EPAPR_BOOT
|
||||
select PPC_INDIRECT_PIO
|
||||
select PPC_UDBG_16550
|
||||
select ARCH_RANDOM
|
||||
select CPU_FREQ
|
||||
select PPC_DOORBELL
|
||||
select MMU_NOTIFIER
|
||||
|
|
|
@ -19,7 +19,6 @@ config PPC_PSERIES
|
|||
select PPC_UDBG_16550
|
||||
select PPC_DOORBELL
|
||||
select HOTPLUG_CPU
|
||||
select ARCH_RANDOM
|
||||
select FORCE_SMP
|
||||
select SWIOTLB
|
||||
default y
|
||||
|
|
|
@ -508,21 +508,6 @@ config KEXEC_SIG
|
|||
verification for the corresponding kernel image type being
|
||||
loaded in order for this to work.
|
||||
|
||||
config ARCH_RANDOM
|
||||
def_bool y
|
||||
prompt "s390 architectural random number generation API"
|
||||
help
|
||||
Enable the s390 architectural random number generation API
|
||||
to provide random data for all consumers within the Linux
|
||||
kernel.
|
||||
|
||||
When enabled the arch_random_* functions declared in linux/random.h
|
||||
are implemented. The implementation is based on the s390 CPACF
|
||||
instruction subfunction TRNG which provides a real true random
|
||||
number generator.
|
||||
|
||||
If unsure, say Y.
|
||||
|
||||
config KERNEL_NOBP
|
||||
def_bool n
|
||||
prompt "Enable modified branch prediction for the kernel by default"
|
||||
|
|
|
@ -15,7 +15,6 @@ CONFIG_TUNE_ZEC12=y
|
|||
# CONFIG_COMPAT is not set
|
||||
CONFIG_NR_CPUS=2
|
||||
CONFIG_HZ_100=y
|
||||
# CONFIG_ARCH_RANDOM is not set
|
||||
# CONFIG_RELOCATABLE is not set
|
||||
# CONFIG_CHSC_SCH is not set
|
||||
# CONFIG_SCM_BUS is not set
|
||||
|
|
|
@ -15,7 +15,7 @@ obj-$(CONFIG_CRYPTO_CHACHA_S390) += chacha_s390.o
|
|||
obj-$(CONFIG_S390_PRNG) += prng.o
|
||||
obj-$(CONFIG_CRYPTO_GHASH_S390) += ghash_s390.o
|
||||
obj-$(CONFIG_CRYPTO_CRC32_S390) += crc32-vx_s390.o
|
||||
obj-$(CONFIG_ARCH_RANDOM) += arch_random.o
|
||||
obj-y += arch_random.o
|
||||
|
||||
crc32-vx_s390-y := crc32-vx.o crc32le-vx.o crc32be-vx.o
|
||||
chacha_s390-y := chacha-glue.o chacha-s390.o
|
||||
|
|
|
@ -11,8 +11,6 @@
|
|||
#ifndef _ASM_S390_ARCHRANDOM_H
|
||||
#define _ASM_S390_ARCHRANDOM_H
|
||||
|
||||
#ifdef CONFIG_ARCH_RANDOM
|
||||
|
||||
#include <linux/static_key.h>
|
||||
#include <linux/preempt.h>
|
||||
#include <linux/atomic.h>
|
||||
|
@ -21,37 +19,20 @@
|
|||
DECLARE_STATIC_KEY_FALSE(s390_arch_random_available);
|
||||
extern atomic64_t s390_arch_random_counter;
|
||||
|
||||
static inline bool __must_check arch_get_random_long(unsigned long *v)
|
||||
static inline size_t __must_check arch_get_random_longs(unsigned long *v, size_t max_longs)
|
||||
{
|
||||
return false;
|
||||
return 0;
|
||||
}
|
||||
|
||||
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)
|
||||
static inline size_t __must_check arch_get_random_seed_longs(unsigned long *v, size_t max_longs)
|
||||
{
|
||||
if (static_branch_likely(&s390_arch_random_available) &&
|
||||
in_task()) {
|
||||
cpacf_trng(NULL, 0, (u8 *)v, sizeof(*v));
|
||||
atomic64_add(sizeof(*v), &s390_arch_random_counter);
|
||||
return true;
|
||||
cpacf_trng(NULL, 0, (u8 *)v, max_longs * sizeof(*v));
|
||||
atomic64_add(max_longs * sizeof(*v), &s390_arch_random_counter);
|
||||
return max_longs;
|
||||
}
|
||||
return false;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static inline bool __must_check arch_get_random_seed_int(unsigned int *v)
|
||||
{
|
||||
if (static_branch_likely(&s390_arch_random_available) &&
|
||||
in_task()) {
|
||||
cpacf_trng(NULL, 0, (u8 *)v, sizeof(*v));
|
||||
atomic64_add(sizeof(*v), &s390_arch_random_counter);
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
#endif /* CONFIG_ARCH_RANDOM */
|
||||
#endif /* _ASM_S390_ARCHRANDOM_H */
|
||||
|
|
|
@ -876,10 +876,8 @@ static void __init setup_randomness(void)
|
|||
add_device_randomness(&vmms->vm, sizeof(vmms->vm[0]) * vmms->count);
|
||||
memblock_free(vmms, PAGE_SIZE);
|
||||
|
||||
#ifdef CONFIG_ARCH_RANDOM
|
||||
if (cpacf_query_func(CPACF_PRNO, CPACF_PRNO_TRNG))
|
||||
static_branch_enable(&s390_arch_random_available);
|
||||
#endif
|
||||
}
|
||||
|
||||
/*
|
||||
|
|
|
@ -0,0 +1,25 @@
|
|||
/* SPDX-License-Identifier: GPL-2.0 */
|
||||
#ifndef __ASM_UM_ARCHRANDOM_H__
|
||||
#define __ASM_UM_ARCHRANDOM_H__
|
||||
|
||||
#include <linux/types.h>
|
||||
|
||||
/* This is from <os.h>, but better not to #include that in a global header here. */
|
||||
ssize_t os_getrandom(void *buf, size_t len, unsigned int flags);
|
||||
|
||||
static inline size_t __must_check arch_get_random_longs(unsigned long *v, size_t max_longs)
|
||||
{
|
||||
ssize_t ret;
|
||||
|
||||
ret = os_getrandom(v, max_longs * sizeof(*v), 0);
|
||||
if (ret < 0)
|
||||
return 0;
|
||||
return ret / sizeof(*v);
|
||||
}
|
||||
|
||||
static inline size_t __must_check arch_get_random_seed_longs(unsigned long *v, size_t max_longs)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
#endif
|
|
@ -11,6 +11,12 @@
|
|||
#include <irq_user.h>
|
||||
#include <longjmp.h>
|
||||
#include <mm_id.h>
|
||||
/* This is to get size_t */
|
||||
#ifndef __UM_HOST__
|
||||
#include <linux/types.h>
|
||||
#else
|
||||
#include <sys/types.h>
|
||||
#endif
|
||||
|
||||
#define CATCH_EINTR(expr) while ((errno = 0, ((expr) < 0)) && (errno == EINTR))
|
||||
|
||||
|
@ -243,6 +249,7 @@ extern void stack_protections(unsigned long address);
|
|||
extern int raw(int fd);
|
||||
extern void setup_machinename(char *machine_out);
|
||||
extern void setup_hostinfo(char *buf, int len);
|
||||
extern ssize_t os_getrandom(void *buf, size_t len, unsigned int flags);
|
||||
extern void os_dump_core(void) __attribute__ ((noreturn));
|
||||
extern void um_early_printk(const char *s, unsigned int n);
|
||||
extern void os_fix_helper_signals(void);
|
||||
|
|
|
@ -16,6 +16,7 @@
|
|||
#include <linux/sched/task.h>
|
||||
#include <linux/kmsg_dump.h>
|
||||
#include <linux/suspend.h>
|
||||
#include <linux/random.h>
|
||||
|
||||
#include <asm/processor.h>
|
||||
#include <asm/cpufeature.h>
|
||||
|
@ -406,6 +407,8 @@ int __init __weak read_initrd(void)
|
|||
|
||||
void __init setup_arch(char **cmdline_p)
|
||||
{
|
||||
u8 rng_seed[32];
|
||||
|
||||
stack_protections((unsigned long) &init_thread_info);
|
||||
setup_physmem(uml_physmem, uml_reserved, physmem_size, highmem);
|
||||
mem_total_pages(physmem_size, iomem_size, highmem);
|
||||
|
@ -416,6 +419,11 @@ void __init setup_arch(char **cmdline_p)
|
|||
strlcpy(boot_command_line, command_line, COMMAND_LINE_SIZE);
|
||||
*cmdline_p = command_line;
|
||||
setup_hostinfo(host_info, sizeof host_info);
|
||||
|
||||
if (os_getrandom(rng_seed, sizeof(rng_seed), 0) == sizeof(rng_seed)) {
|
||||
add_bootloader_randomness(rng_seed, sizeof(rng_seed));
|
||||
memzero_explicit(rng_seed, sizeof(rng_seed));
|
||||
}
|
||||
}
|
||||
|
||||
void __init check_bugs(void)
|
||||
|
|
|
@ -14,6 +14,7 @@
|
|||
#include <sys/wait.h>
|
||||
#include <sys/mman.h>
|
||||
#include <sys/utsname.h>
|
||||
#include <sys/random.h>
|
||||
#include <init.h>
|
||||
#include <os.h>
|
||||
|
||||
|
@ -96,6 +97,11 @@ static inline void __attribute__ ((noreturn)) uml_abort(void)
|
|||
exit(127);
|
||||
}
|
||||
|
||||
ssize_t os_getrandom(void *buf, size_t len, unsigned int flags)
|
||||
{
|
||||
return getrandom(buf, len, flags);
|
||||
}
|
||||
|
||||
/*
|
||||
* UML helper threads must not handle SIGWINCH/INT/TERM
|
||||
*/
|
||||
|
|
|
@ -1812,15 +1812,6 @@ config ARCH_USES_PG_UNCACHED
|
|||
def_bool y
|
||||
depends on X86_PAT
|
||||
|
||||
config ARCH_RANDOM
|
||||
def_bool y
|
||||
prompt "x86 architectural random number generator" if EXPERT
|
||||
help
|
||||
Enable the x86 architectural RDRAND instruction
|
||||
(Intel Bull Mountain technology) to generate random numbers.
|
||||
If supported, this is a high bandwidth, cryptographically
|
||||
secure hardware random number generator.
|
||||
|
||||
config X86_UMIP
|
||||
def_bool y
|
||||
prompt "User Mode Instruction Prevention" if EXPERT
|
||||
|
|
|
@ -31,20 +31,6 @@ static inline bool __must_check rdrand_long(unsigned long *v)
|
|||
return false;
|
||||
}
|
||||
|
||||
static inline bool __must_check rdrand_int(unsigned int *v)
|
||||
{
|
||||
bool ok;
|
||||
unsigned int retry = RDRAND_RETRY_LOOPS;
|
||||
do {
|
||||
asm volatile("rdrand %[out]"
|
||||
CC_SET(c)
|
||||
: CC_OUT(c) (ok), [out] "=r" (*v));
|
||||
if (ok)
|
||||
return true;
|
||||
} while (--retry);
|
||||
return false;
|
||||
}
|
||||
|
||||
static inline bool __must_check rdseed_long(unsigned long *v)
|
||||
{
|
||||
bool ok;
|
||||
|
@ -54,48 +40,23 @@ static inline bool __must_check rdseed_long(unsigned long *v)
|
|||
return ok;
|
||||
}
|
||||
|
||||
static inline bool __must_check rdseed_int(unsigned int *v)
|
||||
{
|
||||
bool ok;
|
||||
asm volatile("rdseed %[out]"
|
||||
CC_SET(c)
|
||||
: CC_OUT(c) (ok), [out] "=r" (*v));
|
||||
return ok;
|
||||
}
|
||||
|
||||
/*
|
||||
* These are the generic interfaces; they must not be declared if the
|
||||
* stubs in <linux/random.h> are to be invoked,
|
||||
* i.e. CONFIG_ARCH_RANDOM is not defined.
|
||||
* stubs in <linux/random.h> are to be invoked.
|
||||
*/
|
||||
#ifdef CONFIG_ARCH_RANDOM
|
||||
|
||||
static inline bool __must_check arch_get_random_long(unsigned long *v)
|
||||
static inline size_t __must_check arch_get_random_longs(unsigned long *v, size_t max_longs)
|
||||
{
|
||||
return static_cpu_has(X86_FEATURE_RDRAND) ? rdrand_long(v) : false;
|
||||
return max_longs && static_cpu_has(X86_FEATURE_RDRAND) && rdrand_long(v) ? 1 : 0;
|
||||
}
|
||||
|
||||
static inline bool __must_check arch_get_random_int(unsigned int *v)
|
||||
static inline size_t __must_check arch_get_random_seed_longs(unsigned long *v, size_t max_longs)
|
||||
{
|
||||
return static_cpu_has(X86_FEATURE_RDRAND) ? rdrand_int(v) : false;
|
||||
return max_longs && static_cpu_has(X86_FEATURE_RDSEED) && rdseed_long(v) ? 1 : 0;
|
||||
}
|
||||
|
||||
static inline bool __must_check arch_get_random_seed_long(unsigned long *v)
|
||||
{
|
||||
return static_cpu_has(X86_FEATURE_RDSEED) ? rdseed_long(v) : false;
|
||||
}
|
||||
|
||||
static inline bool __must_check arch_get_random_seed_int(unsigned int *v)
|
||||
{
|
||||
return static_cpu_has(X86_FEATURE_RDSEED) ? rdseed_int(v) : false;
|
||||
}
|
||||
|
||||
extern void x86_init_rdrand(struct cpuinfo_x86 *c);
|
||||
|
||||
#else /* !CONFIG_ARCH_RANDOM */
|
||||
|
||||
static inline void x86_init_rdrand(struct cpuinfo_x86 *c) { }
|
||||
|
||||
#endif /* !CONFIG_ARCH_RANDOM */
|
||||
#ifndef CONFIG_UML
|
||||
void x86_init_rdrand(struct cpuinfo_x86 *c);
|
||||
#endif
|
||||
|
||||
#endif /* ASM_X86_ARCHRANDOM_H */
|
||||
|
|
|
@ -808,7 +808,7 @@ static void clear_rdrand_cpuid_bit(struct cpuinfo_x86 *c)
|
|||
return;
|
||||
|
||||
/*
|
||||
* The nordrand option can clear X86_FEATURE_RDRAND, so check for
|
||||
* The self-test can clear X86_FEATURE_RDRAND, so check for
|
||||
* RDRAND support using the CPUID function directly.
|
||||
*/
|
||||
if (!(cpuid_ecx(1) & BIT(30)) || rdrand_force)
|
||||
|
|
|
@ -11,56 +11,39 @@
|
|||
#include <asm/archrandom.h>
|
||||
#include <asm/sections.h>
|
||||
|
||||
static int __init x86_rdrand_setup(char *s)
|
||||
{
|
||||
setup_clear_cpu_cap(X86_FEATURE_RDRAND);
|
||||
setup_clear_cpu_cap(X86_FEATURE_RDSEED);
|
||||
return 1;
|
||||
}
|
||||
__setup("nordrand", x86_rdrand_setup);
|
||||
|
||||
/*
|
||||
* RDRAND has Built-In-Self-Test (BIST) that runs on every invocation.
|
||||
* Run the instruction a few times as a sanity check.
|
||||
* If it fails, it is simple to disable RDRAND here.
|
||||
* Run the instruction a few times as a sanity check. Also make sure
|
||||
* it's not outputting the same value over and over, which has happened
|
||||
* as a result of past CPU bugs.
|
||||
*
|
||||
* If it fails, it is simple to disable RDRAND and RDSEED here.
|
||||
*/
|
||||
#define SANITY_CHECK_LOOPS 8
|
||||
|
||||
#ifdef CONFIG_ARCH_RANDOM
|
||||
void x86_init_rdrand(struct cpuinfo_x86 *c)
|
||||
{
|
||||
unsigned int changed = 0;
|
||||
unsigned long tmp, prev;
|
||||
int i;
|
||||
enum { SAMPLES = 8, MIN_CHANGE = 5 };
|
||||
unsigned long sample, prev;
|
||||
bool failure = false;
|
||||
size_t i, changed;
|
||||
|
||||
if (!cpu_has(c, X86_FEATURE_RDRAND))
|
||||
return;
|
||||
|
||||
for (i = 0; i < SANITY_CHECK_LOOPS; i++) {
|
||||
if (!rdrand_long(&tmp)) {
|
||||
for (changed = 0, i = 0; i < SAMPLES; ++i) {
|
||||
if (!rdrand_long(&sample)) {
|
||||
failure = true;
|
||||
break;
|
||||
}
|
||||
changed += i && sample != prev;
|
||||
prev = sample;
|
||||
}
|
||||
if (changed < MIN_CHANGE)
|
||||
failure = true;
|
||||
|
||||
if (failure) {
|
||||
clear_cpu_cap(c, X86_FEATURE_RDRAND);
|
||||
pr_warn_once("rdrand: disabled\n");
|
||||
return;
|
||||
clear_cpu_cap(c, X86_FEATURE_RDSEED);
|
||||
pr_emerg("RDRAND is not reliable on this platform; disabling.\n");
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Stupid sanity-check whether RDRAND does *actually* generate
|
||||
* some at least random-looking data.
|
||||
*/
|
||||
prev = tmp;
|
||||
for (i = 0; i < SANITY_CHECK_LOOPS; i++) {
|
||||
if (rdrand_long(&tmp)) {
|
||||
if (prev != tmp)
|
||||
changed++;
|
||||
|
||||
prev = tmp;
|
||||
}
|
||||
}
|
||||
|
||||
if (WARN_ON_ONCE(!changed))
|
||||
pr_emerg(
|
||||
"RDRAND gives funky smelling output, might consider not using it by booting with \"nordrand\"");
|
||||
|
||||
}
|
||||
#endif
|
||||
|
|
|
@ -100,7 +100,7 @@ static void init_espfix_random(void)
|
|||
* This is run before the entropy pools are initialized,
|
||||
* but this is hopefully better than nothing.
|
||||
*/
|
||||
if (!arch_get_random_long(&rand)) {
|
||||
if (!arch_get_random_longs(&rand, 1)) {
|
||||
/* The constant is an arbitrary large prime */
|
||||
rand = rdtsc();
|
||||
rand *= 0xc345c6b72fd16123UL;
|
||||
|
|
|
@ -431,7 +431,6 @@ config ADI
|
|||
config RANDOM_TRUST_CPU
|
||||
bool "Initialize RNG using CPU RNG instructions"
|
||||
default y
|
||||
depends on ARCH_RANDOM
|
||||
help
|
||||
Initialize the RNG using random numbers supplied by the CPU's
|
||||
RNG instructions (e.g. RDRAND), if supported and available. These
|
||||
|
|
|
@ -108,7 +108,6 @@ static ssize_t trng_counter_show(struct device *dev,
|
|||
{
|
||||
u64 dev_counter = atomic64_read(&trng_dev_counter);
|
||||
u64 hwrng_counter = atomic64_read(&trng_hwrng_counter);
|
||||
#if IS_ENABLED(CONFIG_ARCH_RANDOM)
|
||||
u64 arch_counter = atomic64_read(&s390_arch_random_counter);
|
||||
|
||||
return sysfs_emit(buf,
|
||||
|
@ -118,14 +117,6 @@ static ssize_t trng_counter_show(struct device *dev,
|
|||
"total: %llu\n",
|
||||
dev_counter, hwrng_counter, arch_counter,
|
||||
dev_counter + hwrng_counter + arch_counter);
|
||||
#else
|
||||
return sysfs_emit(buf,
|
||||
"trng: %llu\n"
|
||||
"hwrng: %llu\n"
|
||||
"total: %llu\n",
|
||||
dev_counter, hwrng_counter,
|
||||
dev_counter + hwrng_counter);
|
||||
#endif
|
||||
}
|
||||
static DEVICE_ATTR(byte_counter, 0444, trng_counter_show, NULL);
|
||||
|
||||
|
|
|
@ -229,7 +229,7 @@ static void crng_reseed(void)
|
|||
|
||||
/*
|
||||
* This generates a ChaCha block using the provided key, and then
|
||||
* immediately overwites that key with half the block. It returns
|
||||
* immediately overwrites 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.
|
||||
|
@ -596,12 +596,20 @@ static void extract_entropy(void *buf, size_t len)
|
|||
unsigned long rdseed[32 / sizeof(long)];
|
||||
size_t counter;
|
||||
} block;
|
||||
size_t i;
|
||||
size_t i, longs;
|
||||
|
||||
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();
|
||||
for (i = 0; i < ARRAY_SIZE(block.rdseed);) {
|
||||
longs = arch_get_random_seed_longs(&block.rdseed[i], ARRAY_SIZE(block.rdseed) - i);
|
||||
if (longs) {
|
||||
i += longs;
|
||||
continue;
|
||||
}
|
||||
longs = arch_get_random_longs(&block.rdseed[i], ARRAY_SIZE(block.rdseed) - i);
|
||||
if (longs) {
|
||||
i += longs;
|
||||
continue;
|
||||
}
|
||||
block.rdseed[i++] = random_get_entropy();
|
||||
}
|
||||
|
||||
spin_lock_irqsave(&input_pool.lock, flags);
|
||||
|
@ -643,10 +651,10 @@ static void __cold _credit_init_bits(size_t bits)
|
|||
|
||||
add = min_t(size_t, bits, POOL_BITS);
|
||||
|
||||
do {
|
||||
orig = READ_ONCE(input_pool.init_bits);
|
||||
do {
|
||||
new = min_t(unsigned int, POOL_BITS, orig + add);
|
||||
} while (cmpxchg(&input_pool.init_bits, orig, new) != orig);
|
||||
} while (!try_cmpxchg(&input_pool.init_bits, &orig, new));
|
||||
|
||||
if (orig < POOL_READY_BITS && new >= POOL_READY_BITS) {
|
||||
crng_reseed(); /* Sets crng_init to CRNG_READY under base_crng.lock. */
|
||||
|
@ -776,22 +784,31 @@ static struct notifier_block pm_notifier = { .notifier_call = random_pm_notifica
|
|||
int __init random_init(const char *command_line)
|
||||
{
|
||||
ktime_t now = ktime_get_real();
|
||||
unsigned int i, arch_bits;
|
||||
unsigned long entropy;
|
||||
size_t i, longs, arch_bits;
|
||||
unsigned long entropy[BLAKE2S_BLOCK_SIZE / sizeof(long)];
|
||||
|
||||
#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
|
||||
|
||||
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;
|
||||
for (i = 0, arch_bits = sizeof(entropy) * 8; i < ARRAY_SIZE(entropy);) {
|
||||
longs = arch_get_random_seed_longs(entropy, ARRAY_SIZE(entropy) - i);
|
||||
if (longs) {
|
||||
_mix_pool_bytes(entropy, sizeof(*entropy) * longs);
|
||||
i += longs;
|
||||
continue;
|
||||
}
|
||||
_mix_pool_bytes(&entropy, sizeof(entropy));
|
||||
longs = arch_get_random_longs(entropy, ARRAY_SIZE(entropy) - i);
|
||||
if (longs) {
|
||||
_mix_pool_bytes(entropy, sizeof(*entropy) * longs);
|
||||
i += longs;
|
||||
continue;
|
||||
}
|
||||
entropy[0] = random_get_entropy();
|
||||
_mix_pool_bytes(entropy, sizeof(*entropy));
|
||||
arch_bits -= sizeof(*entropy) * 8;
|
||||
++i;
|
||||
}
|
||||
_mix_pool_bytes(&now, sizeof(now));
|
||||
_mix_pool_bytes(utsname(), sizeof(*(utsname())));
|
||||
|
|
|
@ -5,6 +5,7 @@
|
|||
# asm headers from the host architecutre.)
|
||||
|
||||
mandatory-y += atomic.h
|
||||
mandatory-y += archrandom.h
|
||||
mandatory-y += barrier.h
|
||||
mandatory-y += bitops.h
|
||||
mandatory-y += bug.h
|
||||
|
|
|
@ -0,0 +1,15 @@
|
|||
/* SPDX-License-Identifier: GPL-2.0 */
|
||||
#ifndef __ASM_GENERIC_ARCHRANDOM_H__
|
||||
#define __ASM_GENERIC_ARCHRANDOM_H__
|
||||
|
||||
static inline size_t __must_check arch_get_random_longs(unsigned long *v, size_t max_longs)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
static inline size_t __must_check arch_get_random_seed_longs(unsigned long *v, size_t max_longs)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
#endif
|
|
@ -106,32 +106,25 @@ declare_get_random_var_wait(long, unsigned long)
|
|||
*/
|
||||
#include <linux/prandom.h>
|
||||
|
||||
#ifdef CONFIG_ARCH_RANDOM
|
||||
# include <asm/archrandom.h>
|
||||
#else
|
||||
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
|
||||
#include <asm/archrandom.h>
|
||||
|
||||
/*
|
||||
* 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)
|
||||
#ifndef arch_get_random_seed_longs_early
|
||||
static inline size_t __init arch_get_random_seed_longs_early(unsigned long *v, size_t max_longs)
|
||||
{
|
||||
WARN_ON(system_state != SYSTEM_BOOTING);
|
||||
return arch_get_random_seed_long(v);
|
||||
return arch_get_random_seed_longs(v, max_longs);
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifndef arch_get_random_long_early
|
||||
static inline bool __init arch_get_random_long_early(unsigned long *v)
|
||||
#ifndef arch_get_random_longs_early
|
||||
static inline bool __init arch_get_random_longs_early(unsigned long *v, size_t max_longs)
|
||||
{
|
||||
WARN_ON(system_state != SYSTEM_BOOTING);
|
||||
return arch_get_random_long(v);
|
||||
return arch_get_random_longs(v, max_longs);
|
||||
}
|
||||
#endif
|
||||
|
||||
|
|
|
@ -23,6 +23,7 @@
|
|||
#include <linux/pvclock_gtod.h>
|
||||
#include <linux/compiler.h>
|
||||
#include <linux/audit.h>
|
||||
#include <linux/random.h>
|
||||
|
||||
#include "tick-internal.h"
|
||||
#include "ntp_internal.h"
|
||||
|
@ -1343,8 +1344,10 @@ out:
|
|||
/* Signal hrtimers about time change */
|
||||
clock_was_set(CLOCK_SET_WALL);
|
||||
|
||||
if (!ret)
|
||||
if (!ret) {
|
||||
audit_tk_injoffset(ts_delta);
|
||||
add_device_randomness(ts, sizeof(*ts));
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
@ -2430,6 +2433,7 @@ int do_adjtimex(struct __kernel_timex *txc)
|
|||
ret = timekeeping_validate_timex(txc);
|
||||
if (ret)
|
||||
return ret;
|
||||
add_device_randomness(txc, sizeof(*txc));
|
||||
|
||||
if (txc->modes & ADJ_SETOFFSET) {
|
||||
struct timespec64 delta;
|
||||
|
@ -2447,6 +2451,7 @@ int do_adjtimex(struct __kernel_timex *txc)
|
|||
audit_ntp_init(&ad);
|
||||
|
||||
ktime_get_real_ts64(&ts);
|
||||
add_device_randomness(&ts, sizeof(ts));
|
||||
|
||||
raw_spin_lock_irqsave(&timekeeper_lock, flags);
|
||||
write_seqcount_begin(&tk_core.seq);
|
||||
|
|
|
@ -58,7 +58,6 @@ CONFIG_NO_HZ_IDLE=y
|
|||
CONFIG_NO_HZ_FULL=n
|
||||
CONFIG_HZ_PERIODIC=n
|
||||
CONFIG_HIGH_RES_TIMERS=y
|
||||
CONFIG_ARCH_RANDOM=y
|
||||
CONFIG_FILE_LOCKING=y
|
||||
CONFIG_POSIX_TIMERS=y
|
||||
CONFIG_DEVTMPFS=y
|
||||
|
|
Loading…
Reference in New Issue