Skip to content

Commit 1b32de3

Browse files
kerneltoastPlaidCat
authored andcommitted
random: Restrict extrng registration to init time
It is technically a risk to permit extrng registration by modules after kernel init completes. Since there is only one user of the extrng interface and it is imperative that it is the _only_ registered extrng for FIPS compliance, restrict the extrng registration interface to only permit registration during kernel init and only from built-in drivers. This also eliminates the risks associated with the extrng interface itself being designed to solely accommodate a single registration, which would therefore permit the registered extrng to be overridden or even removed by an unrelated module. Signed-off-by: Sultan Alsawaf <sultan@ciq.com> Signed-off-by: Jonathan Maple <jmaple@ciq.com>
1 parent 2a3f618 commit 1b32de3

File tree

3 files changed

+20
-75
lines changed

3 files changed

+20
-75
lines changed

crypto/rng.c

Lines changed: 1 addition & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -322,8 +322,7 @@ static ssize_t crypto_devrandom_read_iter(struct iov_iter *iter, bool reseed)
322322
}
323323

324324
static const struct random_extrng crypto_devrandom_rng = {
325-
.extrng_read_iter = crypto_devrandom_read_iter,
326-
.owner = THIS_MODULE,
325+
.extrng_read_iter = crypto_devrandom_read_iter
327326
};
328327

329328
static int __init crypto_rng_init(void)
@@ -333,13 +332,7 @@ static int __init crypto_rng_init(void)
333332
return 0;
334333
}
335334

336-
static void __exit crypto_rng_exit(void)
337-
{
338-
random_unregister_extrng();
339-
}
340-
341335
late_initcall(crypto_rng_init);
342-
module_exit(crypto_rng_exit);
343336

344337
MODULE_LICENSE("GPL");
345338
MODULE_DESCRIPTION("Random Number Generator");

drivers/char/random.c

Lines changed: 12 additions & 58 deletions
Original file line numberDiff line numberDiff line change
@@ -51,7 +51,6 @@
5151
#include <linux/completion.h>
5252
#include <linux/uuid.h>
5353
#include <linux/uaccess.h>
54-
#include <linux/rcupdate.h>
5554
#include <linux/suspend.h>
5655
#include <linux/siphash.h>
5756
#include <linux/sched/isolation.h>
@@ -314,7 +313,7 @@ static void crng_fast_key_erasure(u8 key[CHACHA_KEY_SIZE],
314313
/*
315314
* Hook for external RNG.
316315
*/
317-
static const struct random_extrng __rcu *extrng;
316+
static const struct random_extrng *extrng __ro_after_init;
318317

319318
/*
320319
* This function returns a ChaCha state that you may use for generating
@@ -966,18 +965,12 @@ void __init add_bootloader_randomness(const void *buf, size_t len)
966965
credit_init_bits(len * 8);
967966
}
968967

969-
void random_register_extrng(const struct random_extrng *rng)
968+
void __init random_register_extrng(const struct random_extrng *rng)
970969
{
971-
rcu_assign_pointer(extrng, rng);
970+
/* Don't allow the registered extrng to be overridden */
971+
BUG_ON(extrng);
972+
extrng = rng;
972973
}
973-
EXPORT_SYMBOL_GPL(random_register_extrng);
974-
975-
void random_unregister_extrng(void)
976-
{
977-
RCU_INIT_POINTER(extrng, NULL);
978-
synchronize_rcu();
979-
}
980-
EXPORT_SYMBOL_GPL(random_unregister_extrng);
981974

982975
#if IS_ENABLED(CONFIG_VMGENID)
983976
static BLOCKING_NOTIFIER_HEAD(vmfork_chain);
@@ -1386,7 +1379,6 @@ static void __cold try_to_generate_entropy(void)
13861379

13871380
SYSCALL_DEFINE3(getrandom, char __user *, ubuf, size_t, len, unsigned int, flags)
13881381
{
1389-
const struct random_extrng *rng;
13901382
struct iov_iter iter;
13911383
struct iovec iov;
13921384
int ret;
@@ -1404,19 +1396,11 @@ SYSCALL_DEFINE3(getrandom, char __user *, ubuf, size_t, len, unsigned int, flags
14041396
if (len > INT_MAX)
14051397
len = INT_MAX;
14061398

1407-
rcu_read_lock();
1408-
rng = rcu_dereference(extrng);
1409-
if (rng && !try_module_get(rng->owner))
1410-
rng = NULL;
1411-
rcu_read_unlock();
1412-
1413-
if (rng) {
1399+
if (extrng) {
14141400
ret = import_single_range(READ, ubuf, len, &iov, &iter);
14151401
if (unlikely(ret))
14161402
return ret;
1417-
ret = rng->extrng_read_iter(&iter, !!(flags & GRND_RANDOM));
1418-
module_put(rng->owner);
1419-
return ret;
1403+
return extrng->extrng_read_iter(&iter, !!(flags & GRND_RANDOM));
14201404
}
14211405

14221406
if (!crng_ready() && !(flags & GRND_INSECURE)) {
@@ -1589,52 +1573,24 @@ static int random_fasync(int fd, struct file *filp, int on)
15891573

15901574
static int random_open(struct inode *inode, struct file *filp)
15911575
{
1592-
const struct random_extrng *rng;
1593-
1594-
rcu_read_lock();
1595-
rng = rcu_dereference(extrng);
1596-
if (rng && !try_module_get(rng->owner))
1597-
rng = NULL;
1598-
rcu_read_unlock();
1599-
1600-
if (!rng)
1601-
return 0;
1602-
1603-
filp->f_op = &extrng_random_fops;
1604-
filp->private_data = rng->owner;
1576+
if (extrng)
1577+
filp->f_op = &extrng_random_fops;
16051578

16061579
return 0;
16071580
}
16081581

16091582
static int urandom_open(struct inode *inode, struct file *filp)
16101583
{
1611-
const struct random_extrng *rng;
1584+
if (extrng)
1585+
filp->f_op = &extrng_urandom_fops;
16121586

1613-
rcu_read_lock();
1614-
rng = rcu_dereference(extrng);
1615-
if (rng && !try_module_get(rng->owner))
1616-
rng = NULL;
1617-
rcu_read_unlock();
1618-
1619-
if (!rng)
1620-
return 0;
1621-
1622-
filp->f_op = &extrng_urandom_fops;
1623-
filp->private_data = rng->owner;
1624-
1625-
return 0;
1626-
}
1627-
1628-
static int extrng_release(struct inode *inode, struct file *filp)
1629-
{
1630-
module_put(filp->private_data);
16311587
return 0;
16321588
}
16331589

16341590
static ssize_t
16351591
extrng_read_iter(struct kiocb *kiocb, struct iov_iter *iter)
16361592
{
1637-
return rcu_dereference_raw(extrng)->extrng_read_iter(iter, false);
1593+
return extrng->extrng_read_iter(iter, false);
16381594
}
16391595

16401596
const struct file_operations random_fops = {
@@ -1670,7 +1626,6 @@ static const struct file_operations extrng_random_fops = {
16701626
.unlocked_ioctl = random_ioctl,
16711627
.fasync = random_fasync,
16721628
.llseek = noop_llseek,
1673-
.release = extrng_release,
16741629
.splice_read = generic_file_splice_read,
16751630
.splice_write = iter_file_splice_write,
16761631
};
@@ -1682,7 +1637,6 @@ static const struct file_operations extrng_urandom_fops = {
16821637
.unlocked_ioctl = random_ioctl,
16831638
.fasync = random_fasync,
16841639
.llseek = noop_llseek,
1685-
.release = extrng_release,
16861640
.splice_read = generic_file_splice_read,
16871641
.splice_write = iter_file_splice_write,
16881642
};

include/linux/random.h

Lines changed: 7 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -9,12 +9,6 @@
99

1010
#include <uapi/linux/random.h>
1111

12-
struct iov_iter;
13-
struct random_extrng {
14-
ssize_t (*extrng_read_iter)(struct iov_iter *, bool reseed);
15-
struct module *owner;
16-
};
17-
1812
struct notifier_block;
1913

2014
void add_device_randomness(const void *buf, size_t len);
@@ -42,9 +36,6 @@ static inline int register_random_vmfork_notifier(struct notifier_block *nb) { r
4236
static inline int unregister_random_vmfork_notifier(struct notifier_block *nb) { return 0; }
4337
#endif
4438

45-
void random_register_extrng(const struct random_extrng *rng);
46-
void random_unregister_extrng(void);
47-
4839
void get_random_bytes(void *buf, size_t len);
4940
u8 get_random_u8(void);
5041
u16 get_random_u16(void);
@@ -173,6 +164,13 @@ int random_online_cpu(unsigned int cpu);
173164

174165
#ifndef MODULE
175166
extern const struct file_operations random_fops, urandom_fops;
167+
168+
struct iov_iter;
169+
struct random_extrng {
170+
ssize_t (*extrng_read_iter)(struct iov_iter *iter, bool reseed);
171+
};
172+
173+
void __init random_register_extrng(const struct random_extrng *rng);
176174
#endif
177175

178176
#endif /* _LINUX_RANDOM_H */

0 commit comments

Comments
 (0)