Random number generator changes for Linux 5.18-rc1.
-----BEGIN PGP SIGNATURE----- iQIzBAABCAAdFiEEq5lC5tSkz8NBJiCnSfxwEqXeA64FAmIzwtEACgkQSfxwEqXe A67NCBAA1+U01HXx4ethmmy1m2pXHAIwngI7PP0QzyZtmoloWockdN1lRfQ1C0uJ Whk/9Hc9G7iujznsxOnCS+LeNwRzd7CjtFbTgK+yGIRKwL9GFcVwA5nrifP9TjqZ FWmTIomjjmA06YRYsNOdNSQdN6DdpQz8xLw0EqVOZerI4ITFErYlW8lLqOOKY99N f9glQK75kh41SUgo+K3JSn46fhB95HldL6dYSZzjQ6QsVKBQuQTDE9ryfrH2XZDw xI2nf/ycXPUBv7Bb+0op+7ES++CoDigM2nIyxapEj3ZkpplxL4M+cCIHq3Juzfwm jDdbZbs5SqDszOQM/dvCJSR+S/D3QIKdv3fwwWHDTigByZdgpudT3rr9k7dY60Z8 aNvOzNWOzGH9/0boLl55WysF6cBQnazbgtzeWpzeuWFhAyfxN/DJx2sf8U+TmN6n 3bDUafamAvmkkIOoHUzOXfjo2lhXxlmRZ40rWVNX5JvcJj5+5jRmTawrQj+9fn8/ MhiIZ6KBDV1OxPwJzG6jm++JP6rgXfXsxduomO7cIEWs10itf/cE8WD9qJrtZTtg kfjYUguFOd/QyzY0A1w6FD865vy8YhATk71Ywgwj9AI+cfH8QUajpDkXOutjop8x 8HBxIGx6Itgzilfuo5jpJxlVhNO3G6v1fX/A+mUMAfHufkmnfiQ= =cyDR -----END PGP SIGNATURE----- Merge tag 'random-5.18-rc1-for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/crng/random Pull random number generator updates from Jason Donenfeld: "There have been a few important changes to the RNG's crypto, but the intent for 5.18 has been to shore up the existing design as much as possible with modern cryptographic functions and proven constructions, rather than actually changing up anything fundamental to the RNG's design. So it's still the same old RNG at its core as before: it still counts entropy bits, and collects from the various sources with the same heuristics as before, and so forth. However, the cryptographic algorithms that transform that entropic data into safe random numbers have been modernized. Just as important, if not more, is that the code has been cleaned up and re-documented. As one of the first drivers in Linux, going back to 1.3.30, its general style and organization was showing its age and becoming both a maintenance burden and an auditability impediment. Hopefully this provides a more solid foundation to build on for the future. I encourage you to open up the file in full, and maybe you'll remark, "oh, that's what it's doing," and enjoy reading it. That, at least, is the eventual goal, which this pull begins working toward. Here's a summary of the various patches in this pull: - /dev/urandom and /dev/random now do the same thing, per the patch we discussed on the list. I think this is worth trying out. If it does appear problematic, I've made sure to keep it standalone and revertible without any conflicts. - Fixes and cleanups for numerous integer type problems, locking issues, and general code quality concerns. - The input pool's LFSR has been replaced with a cryptographically secure hash function, which has security and performance benefits alike, and consequently allows us to count entropy bits linearly. - The pre-init injection now uses a real hash function too, instead of an LFSR or vanilla xor. - The interrupt handler's fast_mix() function now uses one round of SipHash, rather than the fake crypto that was there before. - All additions of RDRAND and RDSEED now go through the input pool's hash function, in part to mitigate ridiculous hypothetical CPU backdoors, but more so to have a consistent interface for ingesting entropy that's easy to analyze, making everything happen one way, instead of a potpourri of different ways. - The crng now works on per-cpu data, while also being in accordance with the actual "fast key erasure RNG" design. This allows us to fix several boot-time race complications associated with the prior dynamically allocated model, eliminates much locking, and makes our backtrack protection more robust. - Batched entropy now erases doled out values so that it's backtrack resistant. - Working closely with Sebastian, the interrupt handler no longer needs to take any locks at all, as we punt the synchronized/expensive operations to a workqueue. This is especially nice for PREEMPT_RT, where taking spinlocks in irq context is problematic. It also makes the handler faster for the rest of us. - Also working with Sebastian, we now do the right thing on CPU hotplug, so that we don't use stale entropy or fail to accumulate new entropy when CPUs come back online. - We handle virtual machines that fork / clone / snapshot, using the "vmgenid" ACPI specification for retrieving a unique new RNG seed, which we can use to also make WireGuard (and in the future, other things) safe across VM forks. - Around boot time, we now try to reseed more often if enough entropy is available, before settling on the usual 5 minute schedule. - Last, but certainly not least, the documentation in the file has been updated considerably" * tag 'random-5.18-rc1-for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/crng/random: (60 commits) random: check for signal and try earlier when generating entropy random: reseed more often immediately after booting random: make consistent usage of crng_ready() random: use SipHash as interrupt entropy accumulator wireguard: device: clear keys on VM fork random: provide notifier for VM fork random: replace custom notifier chain with standard one random: do not export add_vmfork_randomness() unless needed virt: vmgenid: notify RNG of VM fork and supply generation ID ACPI: allow longer device IDs random: add mechanism for VM forks to reinitialize crng random: don't let 644 read-only sysctls be written to random: give sysctl_random_min_urandom_seed a more sensible value random: block in /dev/urandom random: do crng pre-init loading in worker rather than irq random: unify cycles_t and jiffies usage and types random: cleanup UUID handling random: only wake up writers after zap if threshold was passed random: round-robin registers as ulong, not u32 random: clear fast pool, crng, and batches in cpuhp bring up ...
This commit is contained in:
commit
5628b8de12
|
@ -1029,23 +1029,17 @@ This is a directory, with the following entries:
|
|||
* ``poolsize``: the entropy pool size, in bits;
|
||||
|
||||
* ``urandom_min_reseed_secs``: obsolete (used to determine the minimum
|
||||
number of seconds between urandom pool reseeding).
|
||||
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.
|
||||
|
||||
* ``uuid``: a UUID generated every time this is retrieved (this can
|
||||
thus be used to generate UUIDs at will);
|
||||
|
||||
* ``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.
|
||||
|
||||
If ``drivers/char/random.c`` is built with ``ADD_INTERRUPT_BENCH``
|
||||
defined, these additional entries are present:
|
||||
|
||||
* ``add_interrupt_avg_cycles``: the average number of cycles between
|
||||
interrupts used to feed the pool;
|
||||
|
||||
* ``add_interrupt_avg_deviation``: the standard deviation seen on the
|
||||
number of cycles between interrupts used to feed the pool.
|
||||
are woken up. This file is writable for compatibility purposes, but
|
||||
writing to it has no effect on any RNG behavior.
|
||||
|
||||
|
||||
randomize_va_space
|
||||
|
|
|
@ -16213,6 +16213,7 @@ M: Jason A. Donenfeld <Jason@zx2c4.com>
|
|||
T: git https://git.kernel.org/pub/scm/linux/kernel/git/crng/random.git
|
||||
S: Maintained
|
||||
F: drivers/char/random.c
|
||||
F: drivers/virt/vmgenid.c
|
||||
|
||||
RAPIDIO SUBSYSTEM
|
||||
M: Matt Porter <mporter@kernel.crashing.org>
|
||||
|
|
|
@ -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>
|
||||
|
|
|
@ -707,7 +707,7 @@ static const struct memdev {
|
|||
[5] = { "zero", 0666, &zero_fops, FMODE_NOWAIT },
|
||||
[7] = { "full", 0666, &full_fops, 0 },
|
||||
[8] = { "random", 0666, &random_fops, 0 },
|
||||
[9] = { "urandom", 0666, &urandom_fops, 0 },
|
||||
[9] = { "urandom", 0666, &random_fops, 0 },
|
||||
#ifdef CONFIG_PRINTK
|
||||
[11] = { "kmsg", 0644, &kmsg_fops, 0 },
|
||||
#endif
|
||||
|
|
File diff suppressed because it is too large
Load Diff
|
@ -59,9 +59,7 @@ out:
|
|||
return ret;
|
||||
}
|
||||
|
||||
#ifdef CONFIG_PM_SLEEP
|
||||
static int wg_pm_notification(struct notifier_block *nb, unsigned long action,
|
||||
void *data)
|
||||
static int wg_pm_notification(struct notifier_block *nb, unsigned long action, void *data)
|
||||
{
|
||||
struct wg_device *wg;
|
||||
struct wg_peer *peer;
|
||||
|
@ -92,7 +90,24 @@ static int wg_pm_notification(struct notifier_block *nb, unsigned long action,
|
|||
}
|
||||
|
||||
static struct notifier_block pm_notifier = { .notifier_call = wg_pm_notification };
|
||||
#endif
|
||||
|
||||
static int wg_vm_notification(struct notifier_block *nb, unsigned long action, void *data)
|
||||
{
|
||||
struct wg_device *wg;
|
||||
struct wg_peer *peer;
|
||||
|
||||
rtnl_lock();
|
||||
list_for_each_entry(wg, &device_list, device_list) {
|
||||
mutex_lock(&wg->device_update_lock);
|
||||
list_for_each_entry(peer, &wg->peer_list, peer_list)
|
||||
wg_noise_expire_current_peer_keypairs(peer);
|
||||
mutex_unlock(&wg->device_update_lock);
|
||||
}
|
||||
rtnl_unlock();
|
||||
return 0;
|
||||
}
|
||||
|
||||
static struct notifier_block vm_notifier = { .notifier_call = wg_vm_notification };
|
||||
|
||||
static int wg_stop(struct net_device *dev)
|
||||
{
|
||||
|
@ -424,15 +439,17 @@ int __init wg_device_init(void)
|
|||
{
|
||||
int ret;
|
||||
|
||||
#ifdef CONFIG_PM_SLEEP
|
||||
ret = register_pm_notifier(&pm_notifier);
|
||||
if (ret)
|
||||
return ret;
|
||||
#endif
|
||||
|
||||
ret = register_random_vmfork_notifier(&vm_notifier);
|
||||
if (ret)
|
||||
goto error_pm;
|
||||
|
||||
ret = register_pernet_device(&pernet_ops);
|
||||
if (ret)
|
||||
goto error_pm;
|
||||
goto error_vm;
|
||||
|
||||
ret = rtnl_link_register(&link_ops);
|
||||
if (ret)
|
||||
|
@ -442,10 +459,10 @@ int __init wg_device_init(void)
|
|||
|
||||
error_pernet:
|
||||
unregister_pernet_device(&pernet_ops);
|
||||
error_vm:
|
||||
unregister_random_vmfork_notifier(&vm_notifier);
|
||||
error_pm:
|
||||
#ifdef CONFIG_PM_SLEEP
|
||||
unregister_pm_notifier(&pm_notifier);
|
||||
#endif
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
@ -453,8 +470,7 @@ void wg_device_uninit(void)
|
|||
{
|
||||
rtnl_link_unregister(&link_ops);
|
||||
unregister_pernet_device(&pernet_ops);
|
||||
#ifdef CONFIG_PM_SLEEP
|
||||
unregister_random_vmfork_notifier(&vm_notifier);
|
||||
unregister_pm_notifier(&pm_notifier);
|
||||
#endif
|
||||
rcu_barrier();
|
||||
}
|
||||
|
|
|
@ -13,6 +13,17 @@ menuconfig VIRT_DRIVERS
|
|||
|
||||
if VIRT_DRIVERS
|
||||
|
||||
config VMGENID
|
||||
tristate "Virtual Machine Generation ID driver"
|
||||
default y
|
||||
depends on ACPI
|
||||
help
|
||||
Say Y here to use the hypervisor-provided Virtual Machine Generation ID
|
||||
to reseed the RNG when the VM is cloned. This is highly recommended if
|
||||
you intend to do any rollback / cloning / snapshotting of VMs.
|
||||
|
||||
Prefer Y to M so that this protection is activated very early.
|
||||
|
||||
config FSL_HV_MANAGER
|
||||
tristate "Freescale hypervisor management driver"
|
||||
depends on FSL_SOC
|
||||
|
|
|
@ -4,6 +4,7 @@
|
|||
#
|
||||
|
||||
obj-$(CONFIG_FSL_HV_MANAGER) += fsl_hypervisor.o
|
||||
obj-$(CONFIG_VMGENID) += vmgenid.o
|
||||
obj-y += vboxguest/
|
||||
|
||||
obj-$(CONFIG_NITRO_ENCLAVES) += nitro_enclaves/
|
||||
|
|
|
@ -0,0 +1,100 @@
|
|||
// SPDX-License-Identifier: GPL-2.0
|
||||
/*
|
||||
* Copyright (C) 2022 Jason A. Donenfeld <Jason@zx2c4.com>. All Rights Reserved.
|
||||
*
|
||||
* The "Virtual Machine Generation ID" is exposed via ACPI and changes when a
|
||||
* virtual machine forks or is cloned. This driver exists for shepherding that
|
||||
* information to random.c.
|
||||
*/
|
||||
|
||||
#include <linux/kernel.h>
|
||||
#include <linux/module.h>
|
||||
#include <linux/acpi.h>
|
||||
#include <linux/random.h>
|
||||
|
||||
ACPI_MODULE_NAME("vmgenid");
|
||||
|
||||
enum { VMGENID_SIZE = 16 };
|
||||
|
||||
struct vmgenid_state {
|
||||
u8 *next_id;
|
||||
u8 this_id[VMGENID_SIZE];
|
||||
};
|
||||
|
||||
static int vmgenid_add(struct acpi_device *device)
|
||||
{
|
||||
struct acpi_buffer parsed = { ACPI_ALLOCATE_BUFFER };
|
||||
struct vmgenid_state *state;
|
||||
union acpi_object *obj;
|
||||
phys_addr_t phys_addr;
|
||||
acpi_status status;
|
||||
int ret = 0;
|
||||
|
||||
state = devm_kmalloc(&device->dev, sizeof(*state), GFP_KERNEL);
|
||||
if (!state)
|
||||
return -ENOMEM;
|
||||
|
||||
status = acpi_evaluate_object(device->handle, "ADDR", NULL, &parsed);
|
||||
if (ACPI_FAILURE(status)) {
|
||||
ACPI_EXCEPTION((AE_INFO, status, "Evaluating ADDR"));
|
||||
return -ENODEV;
|
||||
}
|
||||
obj = parsed.pointer;
|
||||
if (!obj || obj->type != ACPI_TYPE_PACKAGE || obj->package.count != 2 ||
|
||||
obj->package.elements[0].type != ACPI_TYPE_INTEGER ||
|
||||
obj->package.elements[1].type != ACPI_TYPE_INTEGER) {
|
||||
ret = -EINVAL;
|
||||
goto out;
|
||||
}
|
||||
|
||||
phys_addr = (obj->package.elements[0].integer.value << 0) |
|
||||
(obj->package.elements[1].integer.value << 32);
|
||||
state->next_id = devm_memremap(&device->dev, phys_addr, VMGENID_SIZE, MEMREMAP_WB);
|
||||
if (IS_ERR(state->next_id)) {
|
||||
ret = PTR_ERR(state->next_id);
|
||||
goto out;
|
||||
}
|
||||
|
||||
memcpy(state->this_id, state->next_id, sizeof(state->this_id));
|
||||
add_device_randomness(state->this_id, sizeof(state->this_id));
|
||||
|
||||
device->driver_data = state;
|
||||
|
||||
out:
|
||||
ACPI_FREE(parsed.pointer);
|
||||
return ret;
|
||||
}
|
||||
|
||||
static void vmgenid_notify(struct acpi_device *device, u32 event)
|
||||
{
|
||||
struct vmgenid_state *state = acpi_driver_data(device);
|
||||
u8 old_id[VMGENID_SIZE];
|
||||
|
||||
memcpy(old_id, state->this_id, sizeof(old_id));
|
||||
memcpy(state->this_id, state->next_id, sizeof(state->this_id));
|
||||
if (!memcmp(old_id, state->this_id, sizeof(old_id)))
|
||||
return;
|
||||
add_vmfork_randomness(state->this_id, sizeof(state->this_id));
|
||||
}
|
||||
|
||||
static const struct acpi_device_id vmgenid_ids[] = {
|
||||
{ "VM_GEN_COUNTER", 0 },
|
||||
{ }
|
||||
};
|
||||
|
||||
static struct acpi_driver vmgenid_driver = {
|
||||
.name = "vmgenid",
|
||||
.ids = vmgenid_ids,
|
||||
.owner = THIS_MODULE,
|
||||
.ops = {
|
||||
.add = vmgenid_add,
|
||||
.notify = vmgenid_notify
|
||||
}
|
||||
};
|
||||
|
||||
module_acpi_driver(vmgenid_driver);
|
||||
|
||||
MODULE_DEVICE_TABLE(acpi, vmgenid_ids);
|
||||
MODULE_DESCRIPTION("Virtual Machine Generation ID");
|
||||
MODULE_LICENSE("GPL v2");
|
||||
MODULE_AUTHOR("Jason A. Donenfeld <Jason@zx2c4.com>");
|
|
@ -100,6 +100,7 @@ enum cpuhp_state {
|
|||
CPUHP_AP_ARM_CACHE_B15_RAC_DEAD,
|
||||
CPUHP_PADATA_DEAD,
|
||||
CPUHP_AP_DTPM_CPU_DEAD,
|
||||
CPUHP_RANDOM_PREPARE,
|
||||
CPUHP_WORKQUEUE_PREP,
|
||||
CPUHP_POWER_NUMA_PREPARE,
|
||||
CPUHP_HRTIMERS_PREPARE,
|
||||
|
@ -241,6 +242,7 @@ enum cpuhp_state {
|
|||
CPUHP_AP_PERF_CSKY_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,
|
||||
|
|
|
@ -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_ */
|
||||
|
|
|
@ -211,7 +211,7 @@ struct css_device_id {
|
|||
kernel_ulong_t driver_data;
|
||||
};
|
||||
|
||||
#define ACPI_ID_LEN 9
|
||||
#define ACPI_ID_LEN 16
|
||||
|
||||
struct acpi_device_id {
|
||||
__u8 id[ACPI_ID_LEN];
|
||||
|
|
|
@ -1,9 +1,5 @@
|
|||
/* 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
|
||||
|
||||
|
@ -14,14 +10,10 @@
|
|||
|
||||
#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);
|
||||
extern void add_device_randomness(const void *, size_t);
|
||||
extern void add_bootloader_randomness(const void *, size_t);
|
||||
|
||||
#if defined(LATENT_ENTROPY_PLUGIN) && !defined(__CHECKER__)
|
||||
static inline void add_latent_entropy(void)
|
||||
|
@ -36,17 +28,27 @@ static inline void add_latent_entropy(void) {}
|
|||
extern void add_input_randomness(unsigned int type, unsigned int code,
|
||||
unsigned int value) __latent_entropy;
|
||||
extern void add_interrupt_randomness(int irq) __latent_entropy;
|
||||
extern void add_hwgenerator_randomness(const void *buffer, size_t count,
|
||||
size_t entropy);
|
||||
#if IS_ENABLED(CONFIG_VMGENID)
|
||||
extern void add_vmfork_randomness(const void *unique_vm_id, size_t size);
|
||||
extern int register_random_vmfork_notifier(struct notifier_block *nb);
|
||||
extern int unregister_random_vmfork_notifier(struct notifier_block *nb);
|
||||
#else
|
||||
static inline int register_random_vmfork_notifier(struct notifier_block *nb) { return 0; }
|
||||
static inline int unregister_random_vmfork_notifier(struct notifier_block *nb) { return 0; }
|
||||
#endif
|
||||
|
||||
extern void get_random_bytes(void *buf, int nbytes);
|
||||
extern void get_random_bytes(void *buf, size_t 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);
|
||||
extern int register_random_ready_notifier(struct notifier_block *nb);
|
||||
extern int unregister_random_ready_notifier(struct notifier_block *nb);
|
||||
extern size_t __must_check get_random_bytes_arch(void *buf, size_t nbytes);
|
||||
|
||||
#ifndef MODULE
|
||||
extern const struct file_operations random_fops, urandom_fops;
|
||||
extern const struct file_operations random_fops;
|
||||
#endif
|
||||
|
||||
u32 get_random_u32(void);
|
||||
|
@ -87,7 +89,7 @@ static inline unsigned long get_random_canary(void)
|
|||
|
||||
/* 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);
|
||||
|
@ -158,4 +160,9 @@ static inline bool __init arch_get_random_long_early(unsigned long *v)
|
|||
}
|
||||
#endif
|
||||
|
||||
#ifdef CONFIG_SMP
|
||||
extern int random_prepare_cpu(unsigned int cpu);
|
||||
extern int random_online_cpu(unsigned int cpu);
|
||||
#endif
|
||||
|
||||
#endif /* _LINUX_RANDOM_H */
|
||||
|
|
|
@ -1,233 +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(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("input pool: bytes %d caller %pS",
|
||||
__entry->bytes, (void *)__entry->IP)
|
||||
);
|
||||
|
||||
DEFINE_EVENT(random__mix_pool_bytes, mix_pool_bytes,
|
||||
TP_PROTO(int bytes, unsigned long IP),
|
||||
|
||||
TP_ARGS(bytes, IP)
|
||||
);
|
||||
|
||||
DEFINE_EVENT(random__mix_pool_bytes, mix_pool_bytes_nolock,
|
||||
TP_PROTO(int bytes, unsigned long IP),
|
||||
|
||||
TP_ARGS(bytes, IP)
|
||||
);
|
||||
|
||||
TRACE_EVENT(credit_entropy_bits,
|
||||
TP_PROTO(int bits, int entropy_count, unsigned long IP),
|
||||
|
||||
TP_ARGS(bits, entropy_count, IP),
|
||||
|
||||
TP_STRUCT__entry(
|
||||
__field( int, bits )
|
||||
__field( int, entropy_count )
|
||||
__field(unsigned long, IP )
|
||||
),
|
||||
|
||||
TP_fast_assign(
|
||||
__entry->bits = bits;
|
||||
__entry->entropy_count = entropy_count;
|
||||
__entry->IP = IP;
|
||||
),
|
||||
|
||||
TP_printk("input pool: bits %d entropy_count %d caller %pS",
|
||||
__entry->bits, __entry->entropy_count, (void *)__entry->IP)
|
||||
);
|
||||
|
||||
TRACE_EVENT(debit_entropy,
|
||||
TP_PROTO(int debit_bits),
|
||||
|
||||
TP_ARGS( debit_bits),
|
||||
|
||||
TP_STRUCT__entry(
|
||||
__field( int, debit_bits )
|
||||
),
|
||||
|
||||
TP_fast_assign(
|
||||
__entry->debit_bits = debit_bits;
|
||||
),
|
||||
|
||||
TP_printk("input pool: debit_bits %d", __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)
|
||||
);
|
||||
|
||||
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(int nbytes, int entropy_count, unsigned long IP),
|
||||
|
||||
TP_ARGS(nbytes, entropy_count, IP),
|
||||
|
||||
TP_STRUCT__entry(
|
||||
__field( int, nbytes )
|
||||
__field( int, entropy_count )
|
||||
__field(unsigned long, IP )
|
||||
),
|
||||
|
||||
TP_fast_assign(
|
||||
__entry->nbytes = nbytes;
|
||||
__entry->entropy_count = entropy_count;
|
||||
__entry->IP = IP;
|
||||
),
|
||||
|
||||
TP_printk("input pool: nbytes %d entropy_count %d caller %pS",
|
||||
__entry->nbytes, __entry->entropy_count, (void *)__entry->IP)
|
||||
);
|
||||
|
||||
|
||||
DEFINE_EVENT(random__extract_entropy, extract_entropy,
|
||||
TP_PROTO(int nbytes, int entropy_count, unsigned long IP),
|
||||
|
||||
TP_ARGS(nbytes, entropy_count, IP)
|
||||
);
|
||||
|
||||
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)
|
||||
);
|
||||
|
||||
TRACE_EVENT(prandom_u32,
|
||||
|
||||
TP_PROTO(unsigned int ret),
|
||||
|
||||
TP_ARGS(ret),
|
||||
|
||||
TP_STRUCT__entry(
|
||||
__field( unsigned int, ret)
|
||||
),
|
||||
|
||||
TP_fast_assign(
|
||||
__entry->ret = ret;
|
||||
),
|
||||
|
||||
TP_printk("ret=%u" , __entry->ret)
|
||||
);
|
||||
|
||||
#endif /* _TRACE_RANDOM_H */
|
||||
|
||||
/* This part must be outside protection */
|
||||
#include <trace/define_trace.h>
|
11
kernel/cpu.c
11
kernel/cpu.c
|
@ -34,6 +34,7 @@
|
|||
#include <linux/scs.h>
|
||||
#include <linux/percpu-rwsem.h>
|
||||
#include <linux/cpuset.h>
|
||||
#include <linux/random.h>
|
||||
|
||||
#include <trace/events/power.h>
|
||||
#define CREATE_TRACE_POINTS
|
||||
|
@ -1659,6 +1660,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,
|
||||
|
@ -1782,6 +1788,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,
|
||||
|
|
|
@ -41,7 +41,6 @@
|
|||
#include <linux/bitops.h>
|
||||
#include <linux/slab.h>
|
||||
#include <asm/unaligned.h>
|
||||
#include <trace/events/random.h>
|
||||
|
||||
/**
|
||||
* prandom_u32_state - seeded pseudo-random number generator.
|
||||
|
@ -387,7 +386,6 @@ u32 prandom_u32(void)
|
|||
struct siprand_state *state = get_cpu_ptr(&net_rand_state);
|
||||
u32 res = siprand_u32(state);
|
||||
|
||||
trace_prandom_u32(res);
|
||||
put_cpu_ptr(&net_rand_state);
|
||||
return res;
|
||||
}
|
||||
|
@ -553,9 +551,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;
|
||||
}
|
||||
|
||||
#ifdef CONFIG_RANDOM32_SELFTEST
|
||||
|
@ -619,13 +619,13 @@ core_initcall(prandom32_state_selftest);
|
|||
*/
|
||||
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;
|
||||
|
|
|
@ -757,14 +757,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)
|
||||
|
@ -778,7 +780,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) {
|
||||
|
|
Loading…
Reference in New Issue