Skip to content

Commit 52f6c58

Browse files
committed
Merge tag 'random_for_linus' of git://git.kernel.org/pub/scm/linux/kernel/git/tytso/random
Pull random updates from Ted Ts'o: "Add wait_for_random_bytes() and get_random_*_wait() functions so that callers can more safely get random bytes if they can block until the CRNG is initialized. Also print a warning if get_random_*() is called before the CRNG is initialized. By default, only one single-line warning will be printed per boot. If CONFIG_WARN_ALL_UNSEEDED_RANDOM is defined, then a warning will be printed for each function which tries to get random bytes before the CRNG is initialized. This can get spammy for certain architecture types, so it is not enabled by default" * tag 'random_for_linus' of git://git.kernel.org/pub/scm/linux/kernel/git/tytso/random: random: reorder READ_ONCE() in get_random_uXX random: suppress spammy warnings about unseeded randomness random: warn when kernel uses unseeded randomness net/route: use get_random_int for random counter net/neighbor: use get_random_u32 for 32-bit hash random rhashtable: use get_random_u32 for hash_rnd ceph: ensure RNG is seeded before using iscsi: ensure RNG is seeded before use cifs: use get_random_u32 for 32-bit lock random random: add get_random_{bytes,u32,u64,int,long,once}_wait family random: add wait_for_random_bytes() API
2 parents 78dcf73 + 72e5c74 commit 52f6c58

File tree

12 files changed

+168
-38
lines changed

12 files changed

+168
-38
lines changed

drivers/char/random.c

Lines changed: 76 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -288,7 +288,6 @@
288288
#define SEC_XFER_SIZE 512
289289
#define EXTRACT_SIZE 10
290290

291-
#define DEBUG_RANDOM_BOOT 0
292291

293292
#define LONGS(x) (((x) + sizeof(unsigned long) - 1)/sizeof(unsigned long))
294293

@@ -437,6 +436,7 @@ static void _extract_crng(struct crng_state *crng,
437436
static void _crng_backtrack_protect(struct crng_state *crng,
438437
__u8 tmp[CHACHA20_BLOCK_SIZE], int used);
439438
static void process_random_ready_list(void);
439+
static void _get_random_bytes(void *buf, int nbytes);
440440

441441
/**********************************************************************
442442
*
@@ -777,7 +777,7 @@ static void crng_initialize(struct crng_state *crng)
777777
_extract_entropy(&input_pool, &crng->state[4],
778778
sizeof(__u32) * 12, 0);
779779
else
780-
get_random_bytes(&crng->state[4], sizeof(__u32) * 12);
780+
_get_random_bytes(&crng->state[4], sizeof(__u32) * 12);
781781
for (i = 4; i < 16; i++) {
782782
if (!arch_get_random_seed_long(&rv) &&
783783
!arch_get_random_long(&rv))
@@ -851,11 +851,6 @@ static void crng_reseed(struct crng_state *crng, struct entropy_store *r)
851851
}
852852
}
853853

854-
static inline void crng_wait_ready(void)
855-
{
856-
wait_event_interruptible(crng_init_wait, crng_ready());
857-
}
858-
859854
static void _extract_crng(struct crng_state *crng,
860855
__u8 out[CHACHA20_BLOCK_SIZE])
861856
{
@@ -1477,22 +1472,44 @@ static ssize_t extract_entropy_user(struct entropy_store *r, void __user *buf,
14771472
return ret;
14781473
}
14791474

1475+
#define warn_unseeded_randomness(previous) \
1476+
_warn_unseeded_randomness(__func__, (void *) _RET_IP_, (previous))
1477+
1478+
static void _warn_unseeded_randomness(const char *func_name, void *caller,
1479+
void **previous)
1480+
{
1481+
#ifdef CONFIG_WARN_ALL_UNSEEDED_RANDOM
1482+
const bool print_once = false;
1483+
#else
1484+
static bool print_once __read_mostly;
1485+
#endif
1486+
1487+
if (print_once ||
1488+
crng_ready() ||
1489+
(previous && (caller == READ_ONCE(*previous))))
1490+
return;
1491+
WRITE_ONCE(*previous, caller);
1492+
#ifndef CONFIG_WARN_ALL_UNSEEDED_RANDOM
1493+
print_once = true;
1494+
#endif
1495+
pr_notice("random: %s called from %pF with crng_init=%d\n",
1496+
func_name, caller, crng_init);
1497+
}
1498+
14801499
/*
14811500
* This function is the exported kernel interface. It returns some
14821501
* number of good random numbers, suitable for key generation, seeding
14831502
* TCP sequence numbers, etc. It does not rely on the hardware random
14841503
* number generator. For random bytes direct from the hardware RNG
1485-
* (when available), use get_random_bytes_arch().
1504+
* (when available), use get_random_bytes_arch(). In order to ensure
1505+
* that the randomness provided by this function is okay, the function
1506+
* wait_for_random_bytes() should be called and return 0 at least once
1507+
* at any point prior.
14861508
*/
1487-
void get_random_bytes(void *buf, int nbytes)
1509+
static void _get_random_bytes(void *buf, int nbytes)
14881510
{
14891511
__u8 tmp[CHACHA20_BLOCK_SIZE];
14901512

1491-
#if DEBUG_RANDOM_BOOT > 0
1492-
if (!crng_ready())
1493-
printk(KERN_NOTICE "random: %pF get_random_bytes called "
1494-
"with crng_init = %d\n", (void *) _RET_IP_, crng_init);
1495-
#endif
14961513
trace_get_random_bytes(nbytes, _RET_IP_);
14971514

14981515
while (nbytes >= CHACHA20_BLOCK_SIZE) {
@@ -1509,8 +1526,34 @@ void get_random_bytes(void *buf, int nbytes)
15091526
crng_backtrack_protect(tmp, CHACHA20_BLOCK_SIZE);
15101527
memzero_explicit(tmp, sizeof(tmp));
15111528
}
1529+
1530+
void get_random_bytes(void *buf, int nbytes)
1531+
{
1532+
static void *previous;
1533+
1534+
warn_unseeded_randomness(&previous);
1535+
_get_random_bytes(buf, nbytes);
1536+
}
15121537
EXPORT_SYMBOL(get_random_bytes);
15131538

1539+
/*
1540+
* Wait for the urandom pool to be seeded and thus guaranteed to supply
1541+
* cryptographically secure random numbers. This applies to: the /dev/urandom
1542+
* device, the get_random_bytes function, and the get_random_{u32,u64,int,long}
1543+
* family of functions. Using any of these functions without first calling
1544+
* this function forfeits the guarantee of security.
1545+
*
1546+
* Returns: 0 if the urandom pool has been seeded.
1547+
* -ERESTARTSYS if the function was interrupted by a signal.
1548+
*/
1549+
int wait_for_random_bytes(void)
1550+
{
1551+
if (likely(crng_ready()))
1552+
return 0;
1553+
return wait_event_interruptible(crng_init_wait, crng_ready());
1554+
}
1555+
EXPORT_SYMBOL(wait_for_random_bytes);
1556+
15141557
/*
15151558
* Add a callback function that will be invoked when the nonblocking
15161559
* pool is initialised.
@@ -1865,6 +1908,8 @@ const struct file_operations urandom_fops = {
18651908
SYSCALL_DEFINE3(getrandom, char __user *, buf, size_t, count,
18661909
unsigned int, flags)
18671910
{
1911+
int ret;
1912+
18681913
if (flags & ~(GRND_NONBLOCK|GRND_RANDOM))
18691914
return -EINVAL;
18701915

@@ -1877,9 +1922,9 @@ SYSCALL_DEFINE3(getrandom, char __user *, buf, size_t, count,
18771922
if (!crng_ready()) {
18781923
if (flags & GRND_NONBLOCK)
18791924
return -EAGAIN;
1880-
crng_wait_ready();
1881-
if (signal_pending(current))
1882-
return -ERESTARTSYS;
1925+
ret = wait_for_random_bytes();
1926+
if (unlikely(ret))
1927+
return ret;
18831928
}
18841929
return urandom_read(NULL, buf, count, NULL);
18851930
}
@@ -2040,15 +2085,19 @@ static rwlock_t batched_entropy_reset_lock = __RW_LOCK_UNLOCKED(batched_entropy_
20402085
/*
20412086
* Get a random word for internal kernel use only. The quality of the random
20422087
* number is either as good as RDRAND or as good as /dev/urandom, with the
2043-
* goal of being quite fast and not depleting entropy.
2088+
* goal of being quite fast and not depleting entropy. In order to ensure
2089+
* that the randomness provided by this function is okay, the function
2090+
* wait_for_random_bytes() should be called and return 0 at least once
2091+
* at any point prior.
20442092
*/
20452093
static DEFINE_PER_CPU(struct batched_entropy, batched_entropy_u64);
20462094
u64 get_random_u64(void)
20472095
{
20482096
u64 ret;
2049-
bool use_lock = READ_ONCE(crng_init) < 2;
2097+
bool use_lock;
20502098
unsigned long flags = 0;
20512099
struct batched_entropy *batch;
2100+
static void *previous;
20522101

20532102
#if BITS_PER_LONG == 64
20542103
if (arch_get_random_long((unsigned long *)&ret))
@@ -2059,6 +2108,9 @@ u64 get_random_u64(void)
20592108
return ret;
20602109
#endif
20612110

2111+
warn_unseeded_randomness(&previous);
2112+
2113+
use_lock = READ_ONCE(crng_init) < 2;
20622114
batch = &get_cpu_var(batched_entropy_u64);
20632115
if (use_lock)
20642116
read_lock_irqsave(&batched_entropy_reset_lock, flags);
@@ -2078,13 +2130,17 @@ static DEFINE_PER_CPU(struct batched_entropy, batched_entropy_u32);
20782130
u32 get_random_u32(void)
20792131
{
20802132
u32 ret;
2081-
bool use_lock = READ_ONCE(crng_init) < 2;
2133+
bool use_lock;
20822134
unsigned long flags = 0;
20832135
struct batched_entropy *batch;
2136+
static void *previous;
20842137

20852138
if (arch_get_random_int(&ret))
20862139
return ret;
20872140

2141+
warn_unseeded_randomness(&previous);
2142+
2143+
use_lock = READ_ONCE(crng_init) < 2;
20882144
batch = &get_cpu_var(batched_entropy_u32);
20892145
if (use_lock)
20902146
read_lock_irqsave(&batched_entropy_reset_lock, flags);

drivers/target/iscsi/iscsi_target_auth.c

Lines changed: 11 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -47,18 +47,21 @@ static void chap_binaryhex_to_asciihex(char *dst, char *src, int src_len)
4747
}
4848
}
4949

50-
static void chap_gen_challenge(
50+
static int chap_gen_challenge(
5151
struct iscsi_conn *conn,
5252
int caller,
5353
char *c_str,
5454
unsigned int *c_len)
5555
{
56+
int ret;
5657
unsigned char challenge_asciihex[CHAP_CHALLENGE_LENGTH * 2 + 1];
5758
struct iscsi_chap *chap = conn->auth_protocol;
5859

5960
memset(challenge_asciihex, 0, CHAP_CHALLENGE_LENGTH * 2 + 1);
6061

61-
get_random_bytes(chap->challenge, CHAP_CHALLENGE_LENGTH);
62+
ret = get_random_bytes_wait(chap->challenge, CHAP_CHALLENGE_LENGTH);
63+
if (unlikely(ret))
64+
return ret;
6265
chap_binaryhex_to_asciihex(challenge_asciihex, chap->challenge,
6366
CHAP_CHALLENGE_LENGTH);
6467
/*
@@ -69,6 +72,7 @@ static void chap_gen_challenge(
6972

7073
pr_debug("[%s] Sending CHAP_C=0x%s\n\n", (caller) ? "server" : "client",
7174
challenge_asciihex);
75+
return 0;
7276
}
7377

7478
static int chap_check_algorithm(const char *a_str)
@@ -143,6 +147,7 @@ static struct iscsi_chap *chap_server_open(
143147
case CHAP_DIGEST_UNKNOWN:
144148
default:
145149
pr_err("Unsupported CHAP_A value\n");
150+
kfree(conn->auth_protocol);
146151
return NULL;
147152
}
148153

@@ -156,7 +161,10 @@ static struct iscsi_chap *chap_server_open(
156161
/*
157162
* Generate Challenge.
158163
*/
159-
chap_gen_challenge(conn, 1, aic_str, aic_len);
164+
if (chap_gen_challenge(conn, 1, aic_str, aic_len) < 0) {
165+
kfree(conn->auth_protocol);
166+
return NULL;
167+
}
160168

161169
return chap;
162170
}

drivers/target/iscsi/iscsi_target_login.c

Lines changed: 14 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -245,22 +245,26 @@ int iscsi_check_for_session_reinstatement(struct iscsi_conn *conn)
245245
return 0;
246246
}
247247

248-
static void iscsi_login_set_conn_values(
248+
static int iscsi_login_set_conn_values(
249249
struct iscsi_session *sess,
250250
struct iscsi_conn *conn,
251251
__be16 cid)
252252
{
253+
int ret;
253254
conn->sess = sess;
254255
conn->cid = be16_to_cpu(cid);
255256
/*
256257
* Generate a random Status sequence number (statsn) for the new
257258
* iSCSI connection.
258259
*/
259-
get_random_bytes(&conn->stat_sn, sizeof(u32));
260+
ret = get_random_bytes_wait(&conn->stat_sn, sizeof(u32));
261+
if (unlikely(ret))
262+
return ret;
260263

261264
mutex_lock(&auth_id_lock);
262265
conn->auth_id = iscsit_global->auth_id++;
263266
mutex_unlock(&auth_id_lock);
267+
return 0;
264268
}
265269

266270
__printf(2, 3) int iscsi_change_param_sprintf(
@@ -306,7 +310,11 @@ static int iscsi_login_zero_tsih_s1(
306310
return -ENOMEM;
307311
}
308312

309-
iscsi_login_set_conn_values(sess, conn, pdu->cid);
313+
ret = iscsi_login_set_conn_values(sess, conn, pdu->cid);
314+
if (unlikely(ret)) {
315+
kfree(sess);
316+
return ret;
317+
}
310318
sess->init_task_tag = pdu->itt;
311319
memcpy(&sess->isid, pdu->isid, 6);
312320
sess->exp_cmd_sn = be32_to_cpu(pdu->cmdsn);
@@ -497,8 +505,7 @@ static int iscsi_login_non_zero_tsih_s1(
497505
{
498506
struct iscsi_login_req *pdu = (struct iscsi_login_req *)buf;
499507

500-
iscsi_login_set_conn_values(NULL, conn, pdu->cid);
501-
return 0;
508+
return iscsi_login_set_conn_values(NULL, conn, pdu->cid);
502509
}
503510

504511
/*
@@ -554,9 +561,8 @@ static int iscsi_login_non_zero_tsih_s2(
554561
atomic_set(&sess->session_continuation, 1);
555562
spin_unlock_bh(&sess->conn_lock);
556563

557-
iscsi_login_set_conn_values(sess, conn, pdu->cid);
558-
559-
if (iscsi_copy_param_list(&conn->param_list,
564+
if (iscsi_login_set_conn_values(sess, conn, pdu->cid) < 0 ||
565+
iscsi_copy_param_list(&conn->param_list,
560566
conn->tpg->param_list, 0) < 0) {
561567
iscsit_tx_login_rsp(conn, ISCSI_STATUS_CLS_TARGET_ERR,
562568
ISCSI_LOGIN_STATUS_NO_RESOURCES);

fs/cifs/cifsfs.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1354,7 +1354,7 @@ init_cifs(void)
13541354
spin_lock_init(&cifs_tcp_ses_lock);
13551355
spin_lock_init(&GlobalMid_Lock);
13561356

1357-
get_random_bytes(&cifs_lock_secret, sizeof(cifs_lock_secret));
1357+
cifs_lock_secret = get_random_u32();
13581358

13591359
if (cifs_max_pending < 2) {
13601360
cifs_max_pending = 2;

include/linux/net.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -274,6 +274,8 @@ do { \
274274

275275
#define net_get_random_once(buf, nbytes) \
276276
get_random_once((buf), (nbytes))
277+
#define net_get_random_once_wait(buf, nbytes) \
278+
get_random_once_wait((buf), (nbytes))
277279

278280
int kernel_sendmsg(struct socket *sock, struct msghdr *msg, struct kvec *vec,
279281
size_t num, size_t len);

include/linux/once.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -53,5 +53,7 @@ void __do_once_done(bool *done, struct static_key *once_key,
5353

5454
#define get_random_once(buf, nbytes) \
5555
DO_ONCE(get_random_bytes, (buf), (nbytes))
56+
#define get_random_once_wait(buf, nbytes) \
57+
DO_ONCE(get_random_bytes_wait, (buf), (nbytes)) \
5658

5759
#endif /* _LINUX_ONCE_H */

include/linux/random.h

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,7 @@ extern void add_input_randomness(unsigned int type, unsigned int code,
3434
extern void add_interrupt_randomness(int irq, int irq_flags) __latent_entropy;
3535

3636
extern void get_random_bytes(void *buf, int nbytes);
37+
extern int wait_for_random_bytes(void);
3738
extern int add_random_ready_callback(struct random_ready_callback *rdy);
3839
extern void del_random_ready_callback(struct random_ready_callback *rdy);
3940
extern void get_random_bytes_arch(void *buf, int nbytes);
@@ -78,6 +79,31 @@ static inline unsigned long get_random_canary(void)
7879
return val & CANARY_MASK;
7980
}
8081

82+
/* Calls wait_for_random_bytes() and then calls get_random_bytes(buf, nbytes).
83+
* Returns the result of the call to wait_for_random_bytes. */
84+
static inline int get_random_bytes_wait(void *buf, int nbytes)
85+
{
86+
int ret = wait_for_random_bytes();
87+
if (unlikely(ret))
88+
return ret;
89+
get_random_bytes(buf, nbytes);
90+
return 0;
91+
}
92+
93+
#define declare_get_random_var_wait(var) \
94+
static inline int get_random_ ## var ## _wait(var *out) { \
95+
int ret = wait_for_random_bytes(); \
96+
if (unlikely(ret)) \
97+
return ret; \
98+
*out = get_random_ ## var(); \
99+
return 0; \
100+
}
101+
declare_get_random_var_wait(u32)
102+
declare_get_random_var_wait(u64)
103+
declare_get_random_var_wait(int)
104+
declare_get_random_var_wait(long)
105+
#undef declare_get_random_var
106+
81107
unsigned long randomize_page(unsigned long start, unsigned long range);
82108

83109
u32 prandom_u32(void);

0 commit comments

Comments
 (0)