Changeset View
Changeset View
Standalone View
Standalone View
sys/dev/random/randomdev.c
Show First 20 Lines • Show All 230 Lines • ▼ Show 20 Lines | if (error == 0) { | ||||
if (error == ERESTART || error == EINTR) | if (error == ERESTART || error == EINTR) | ||||
error = 0; | error = 0; | ||||
} | } | ||||
free(random_buf, M_ENTROPY); | free(random_buf, M_ENTROPY); | ||||
return (error); | return (error); | ||||
} | } | ||||
/*- | /*- | ||||
* Kernel API version of read_random(). | * Kernel API version of read_random(). This is similar to read_random_uio(), | ||||
* This is similar to random_alg_read(), | * except it doesn't interface with uio(9). It cannot assumed that random_buf | ||||
* except it doesn't interface with uio(9). | * is a multiple of RANDOM_BLOCKSIZE bytes. | ||||
* It cannot assumed that random_buf is a multiple of | * | ||||
* RANDOM_BLOCKSIZE bytes. | * If the tunable 'kern.random.initial_seeding.bypass_before_seeding' is set | ||||
* non-zero, silently fail to emit random data (matching the pre-r346250 | |||||
* behavior). If read_random is called prior to seeding and bypassed because | |||||
* of this tunable, the condition is reported in the read-only sysctl | |||||
* 'kern.random.initial_seeding.read_random_bypassed_before_seeding'. | |||||
*/ | */ | ||||
void | void | ||||
READ_RANDOM(void *random_buf, u_int len) | READ_RANDOM(void *random_buf, u_int len) | ||||
{ | { | ||||
u_int read_directly_len; | u_int read_directly_len; | ||||
KASSERT(random_buf != NULL, ("No suitable random buffer in %s", __func__)); | KASSERT(random_buf != NULL, ("No suitable random buffer in %s", __func__)); | ||||
p_random_alg_context->ra_pre_read(); | p_random_alg_context->ra_pre_read(); | ||||
if (len == 0) | |||||
return; | |||||
/* (Un)Blocking logic */ | /* (Un)Blocking logic */ | ||||
if (!p_random_alg_context->ra_seeded()) | if (__predict_false(!p_random_alg_context->ra_seeded())) { | ||||
if (random_bypass_before_seeding) { | |||||
if (!read_random_bypassed_before_seeding) { | |||||
if (!random_bypass_disable_warnings) | |||||
printf("read_random: WARNING: bypassing" | |||||
" request for random data because " | |||||
"the random device is not yet " | |||||
"seeded and the knob " | |||||
"'bypass_before_seeding' was " | |||||
"enabled.\n"); | |||||
read_random_bypassed_before_seeding = true; | |||||
} | |||||
/* Avoid potentially leaking stack garbage */ | |||||
memset(random_buf, 0, len); | |||||
delphij: Why is this needed? I think this would zero out the result buffer, which would give… | |||||
cemAuthorUnsubmitted Done Inline ActionsOtherwise, if the consumer assumes the output is random and leaks it, kernel stack contents may be leaked. It does zero out the result buffer, which is deterministic. That is the point of the big knob — it is for people who don't care that their random is deterministic and prefer availability. Callers can pre-verify that the device is seeded with the is_random_seeded API. cem: Otherwise, if the consumer assumes the output is random and leaks it, kernel stack contents may… | |||||
cemAuthorUnsubmitted Done Inline ActionsAre you ok with this @delphij or is this still an open issue? cem: Are you ok with this @delphij or is this still an open issue? | |||||
delphijUnsubmitted Done Inline ActionsYes I'm convinced with your reasoning for zero'ing out. delphij: Yes I'm convinced with your reasoning for zero'ing out. | |||||
return; | |||||
} | |||||
(void)randomdev_wait_until_seeded(SEEDWAIT_UNINTERRUPTIBLE); | (void)randomdev_wait_until_seeded(SEEDWAIT_UNINTERRUPTIBLE); | ||||
} | |||||
read_rate_increment(roundup2(len, sizeof(uint32_t))); | read_rate_increment(roundup2(len, sizeof(uint32_t))); | ||||
if (len == 0) | |||||
return; | |||||
/* | /* | ||||
* The underlying generator expects multiples of | * The underlying generator expects multiples of | ||||
* RANDOM_BLOCKSIZE. | * RANDOM_BLOCKSIZE. | ||||
*/ | */ | ||||
read_directly_len = rounddown(len, RANDOM_BLOCKSIZE); | read_directly_len = rounddown(len, RANDOM_BLOCKSIZE); | ||||
if (read_directly_len > 0) | if (read_directly_len > 0) | ||||
p_random_alg_context->ra_read(random_buf, read_directly_len); | p_random_alg_context->ra_read(random_buf, read_directly_len); | ||||
if (read_directly_len < len) { | if (read_directly_len < len) { | ||||
▲ Show 20 Lines • Show All 208 Lines • Show Last 20 Lines |
Why is this needed? I think this would zero out the result buffer, which would give deterministic result (0's) and there is not any way to notify the caller?