summaryrefslogtreecommitdiff
path: root/drivers/char
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/char')
-rw-r--r--drivers/char/ds1620.c2
-rw-r--r--drivers/char/dtlk.c3
-rw-r--r--drivers/char/hpet.c2
-rw-r--r--drivers/char/hw_random/omap-rng.c1
-rw-r--r--drivers/char/hw_random/stm32-rng.c9
-rw-r--r--drivers/char/ipmi/ipmi_devintf.c3
-rw-r--r--drivers/char/ipmi/ipmi_dmi.c2
-rw-r--r--drivers/char/ipmi/ipmi_msghandler.c4
-rw-r--r--drivers/char/ipmi/ipmi_plat_data.c27
-rw-r--r--drivers/char/ipmi/ipmi_plat_data.h3
-rw-r--r--drivers/char/ipmi/ipmi_si_hardcode.c1
-rw-r--r--drivers/char/ipmi/ipmi_si_hotmod.c1
-rw-r--r--drivers/char/ipmi/ipmi_si_intf.c2
-rw-r--r--drivers/char/ipmi/ipmi_si_platform.c6
-rw-r--r--drivers/char/ipmi/ipmi_ssif.c11
-rw-r--r--drivers/char/ipmi/ipmi_watchdog.c2
-rw-r--r--drivers/char/pcmcia/cm4000_cs.c2
-rw-r--r--drivers/char/pcmcia/scr24x_cs.c2
-rw-r--r--drivers/char/random.c199
-rw-r--r--drivers/char/tb0219.c2
-rw-r--r--drivers/char/tpm/Kconfig1
-rw-r--r--drivers/char/virtio_console.c3
22 files changed, 190 insertions, 98 deletions
diff --git a/drivers/char/ds1620.c b/drivers/char/ds1620.c
index a5ecf6dae02e..373f549525fe 100644
--- a/drivers/char/ds1620.c
+++ b/drivers/char/ds1620.c
@@ -212,7 +212,7 @@ static void ds1620_read_state(struct therm *therm)
static int ds1620_open(struct inode *inode, struct file *file)
{
- return nonseekable_open(inode, file);
+ return stream_open(inode, file);
}
static ssize_t
diff --git a/drivers/char/dtlk.c b/drivers/char/dtlk.c
index f882460b5a44..4fed8fafa0f0 100644
--- a/drivers/char/dtlk.c
+++ b/drivers/char/dtlk.c
@@ -298,12 +298,11 @@ static int dtlk_open(struct inode *inode, struct file *file)
{
TRACE_TEXT("(dtlk_open");
- nonseekable_open(inode, file);
switch (iminor(inode)) {
case DTLK_MINOR:
if (dtlk_busy)
return -EBUSY;
- return nonseekable_open(inode, file);
+ return stream_open(inode, file);
default:
return -ENXIO;
diff --git a/drivers/char/hpet.c b/drivers/char/hpet.c
index d0ad85900b79..3a1e6b3ccd10 100644
--- a/drivers/char/hpet.c
+++ b/drivers/char/hpet.c
@@ -973,6 +973,8 @@ static acpi_status hpet_resources(struct acpi_resource *res, void *data)
if (ACPI_SUCCESS(status)) {
hdp->hd_phys_address = addr.address.minimum;
hdp->hd_address = ioremap(addr.address.minimum, addr.address.address_length);
+ if (!hdp->hd_address)
+ return AE_ERROR;
if (hpet_is_known(hdp)) {
iounmap(hdp->hd_address);
diff --git a/drivers/char/hw_random/omap-rng.c b/drivers/char/hw_random/omap-rng.c
index b65ff6962899..e9b6ac61fb7f 100644
--- a/drivers/char/hw_random/omap-rng.c
+++ b/drivers/char/hw_random/omap-rng.c
@@ -443,6 +443,7 @@ static int omap_rng_probe(struct platform_device *pdev)
priv->rng.read = omap_rng_do_read;
priv->rng.init = omap_rng_init;
priv->rng.cleanup = omap_rng_cleanup;
+ priv->rng.quality = 900;
priv->rng.priv = (unsigned long)priv;
platform_set_drvdata(pdev, priv);
diff --git a/drivers/char/hw_random/stm32-rng.c b/drivers/char/hw_random/stm32-rng.c
index 042860d97b15..0ef5b6a3f560 100644
--- a/drivers/char/hw_random/stm32-rng.c
+++ b/drivers/char/hw_random/stm32-rng.c
@@ -161,6 +161,7 @@ static int stm32_rng_probe(struct platform_device *ofdev)
#endif
priv->rng.read = stm32_rng_read,
priv->rng.priv = (unsigned long) dev;
+ priv->rng.quality = 900;
pm_runtime_set_autosuspend_delay(dev, 100);
pm_runtime_use_autosuspend(dev);
@@ -169,6 +170,13 @@ static int stm32_rng_probe(struct platform_device *ofdev)
return devm_hwrng_register(dev, &priv->rng);
}
+static int stm32_rng_remove(struct platform_device *ofdev)
+{
+ pm_runtime_disable(&ofdev->dev);
+
+ return 0;
+}
+
#ifdef CONFIG_PM
static int stm32_rng_runtime_suspend(struct device *dev)
{
@@ -210,6 +218,7 @@ static struct platform_driver stm32_rng_driver = {
.of_match_table = stm32_rng_match,
},
.probe = stm32_rng_probe,
+ .remove = stm32_rng_remove,
};
module_platform_driver(stm32_rng_driver);
diff --git a/drivers/char/ipmi/ipmi_devintf.c b/drivers/char/ipmi/ipmi_devintf.c
index 99c9f581a1f3..f7b1c004a12b 100644
--- a/drivers/char/ipmi/ipmi_devintf.c
+++ b/drivers/char/ipmi/ipmi_devintf.c
@@ -29,7 +29,6 @@ struct ipmi_file_private
struct ipmi_user *user;
spinlock_t recv_msg_lock;
struct list_head recv_msgs;
- struct file *file;
struct fasync_struct *fasync_queue;
wait_queue_head_t wait;
struct mutex recv_mutex;
@@ -95,8 +94,6 @@ static int ipmi_open(struct inode *inode, struct file *file)
if (!priv)
return -ENOMEM;
- priv->file = file;
-
rv = ipmi_create_user(if_num,
&ipmi_hndlrs,
priv,
diff --git a/drivers/char/ipmi/ipmi_dmi.c b/drivers/char/ipmi/ipmi_dmi.c
index f2411468f33f..f38e651dd1b5 100644
--- a/drivers/char/ipmi/ipmi_dmi.c
+++ b/drivers/char/ipmi/ipmi_dmi.c
@@ -47,9 +47,11 @@ static void __init dmi_add_platform_ipmi(unsigned long base_addr,
memset(&p, 0, sizeof(p));
name = "dmi-ipmi-si";
+ p.iftype = IPMI_PLAT_IF_SI;
switch (type) {
case IPMI_DMI_TYPE_SSIF:
name = "dmi-ipmi-ssif";
+ p.iftype = IPMI_PLAT_IF_SSIF;
p.type = SI_TYPE_INVALID;
break;
case IPMI_DMI_TYPE_BT:
diff --git a/drivers/char/ipmi/ipmi_msghandler.c b/drivers/char/ipmi/ipmi_msghandler.c
index 00bf4b17edbf..1dc10740fc0f 100644
--- a/drivers/char/ipmi/ipmi_msghandler.c
+++ b/drivers/char/ipmi/ipmi_msghandler.c
@@ -635,7 +635,7 @@ static DEFINE_MUTEX(ipmidriver_mutex);
static LIST_HEAD(ipmi_interfaces);
static DEFINE_MUTEX(ipmi_interfaces_mutex);
-struct srcu_struct ipmi_interfaces_srcu;
+static struct srcu_struct ipmi_interfaces_srcu;
/*
* List of watchers that want to know when smi's are added and deleted.
@@ -5179,7 +5179,7 @@ static void __exit cleanup_ipmi(void)
* avoids problems with race conditions removing the timer
* here.
*/
- atomic_inc(&stop_operation);
+ atomic_set(&stop_operation, 1);
del_timer_sync(&ipmi_timer);
initialized = false;
diff --git a/drivers/char/ipmi/ipmi_plat_data.c b/drivers/char/ipmi/ipmi_plat_data.c
index 8f0ca2a848eb..28471ff2a3a3 100644
--- a/drivers/char/ipmi/ipmi_plat_data.c
+++ b/drivers/char/ipmi/ipmi_plat_data.c
@@ -12,7 +12,7 @@ struct platform_device *ipmi_platform_add(const char *name, unsigned int inst,
struct ipmi_plat_data *p)
{
struct platform_device *pdev;
- unsigned int num_r = 1, size, pidx = 0;
+ unsigned int num_r = 1, size = 0, pidx = 0;
struct resource r[4];
struct property_entry pr[6];
u32 flags;
@@ -21,19 +21,22 @@ struct platform_device *ipmi_platform_add(const char *name, unsigned int inst,
memset(pr, 0, sizeof(pr));
memset(r, 0, sizeof(r));
- if (p->type == SI_BT)
- size = 3;
- else if (p->type == SI_TYPE_INVALID)
- size = 0;
- else
- size = 2;
+ if (p->iftype == IPMI_PLAT_IF_SI) {
+ if (p->type == SI_BT)
+ size = 3;
+ else if (p->type != SI_TYPE_INVALID)
+ size = 2;
+
+ if (p->regsize == 0)
+ p->regsize = DEFAULT_REGSIZE;
+ if (p->regspacing == 0)
+ p->regspacing = p->regsize;
- if (p->regsize == 0)
- p->regsize = DEFAULT_REGSIZE;
- if (p->regspacing == 0)
- p->regspacing = p->regsize;
+ pr[pidx++] = PROPERTY_ENTRY_U8("ipmi-type", p->type);
+ } else if (p->iftype == IPMI_PLAT_IF_SSIF) {
+ pr[pidx++] = PROPERTY_ENTRY_U16("i2c-addr", p->addr);
+ }
- pr[pidx++] = PROPERTY_ENTRY_U8("ipmi-type", p->type);
if (p->slave_addr)
pr[pidx++] = PROPERTY_ENTRY_U8("slave-addr", p->slave_addr);
pr[pidx++] = PROPERTY_ENTRY_U8("addr-source", p->addr_source);
diff --git a/drivers/char/ipmi/ipmi_plat_data.h b/drivers/char/ipmi/ipmi_plat_data.h
index 567cfcec8ada..9ba744ea9571 100644
--- a/drivers/char/ipmi/ipmi_plat_data.h
+++ b/drivers/char/ipmi/ipmi_plat_data.h
@@ -6,7 +6,10 @@
#include <linux/ipmi.h>
+enum ipmi_plat_interface_type { IPMI_PLAT_IF_SI, IPMI_PLAT_IF_SSIF };
+
struct ipmi_plat_data {
+ enum ipmi_plat_interface_type iftype;
unsigned int type; /* si_type for si, SI_INVALID for others */
unsigned int space; /* addr_space for si, intf# for ssif. */
unsigned long addr;
diff --git a/drivers/char/ipmi/ipmi_si_hardcode.c b/drivers/char/ipmi/ipmi_si_hardcode.c
index 682221eebd66..f6ece7569504 100644
--- a/drivers/char/ipmi/ipmi_si_hardcode.c
+++ b/drivers/char/ipmi/ipmi_si_hardcode.c
@@ -83,6 +83,7 @@ static void __init ipmi_hardcode_init_one(const char *si_type_str,
memset(&p, 0, sizeof(p));
+ p.iftype = IPMI_PLAT_IF_SI;
if (!si_type_str || !*si_type_str || strcmp(si_type_str, "kcs") == 0) {
p.type = SI_KCS;
} else if (strcmp(si_type_str, "smic") == 0) {
diff --git a/drivers/char/ipmi/ipmi_si_hotmod.c b/drivers/char/ipmi/ipmi_si_hotmod.c
index 03140f6cdf6f..42a925f8cf69 100644
--- a/drivers/char/ipmi/ipmi_si_hotmod.c
+++ b/drivers/char/ipmi/ipmi_si_hotmod.c
@@ -108,6 +108,7 @@ static int parse_hotmod_str(const char *curr, enum hotmod_op *op,
int rv;
unsigned int ival;
+ h->iftype = IPMI_PLAT_IF_SI;
rv = parse_str(hotmod_ops, &ival, "operation", &curr);
if (rv)
return rv;
diff --git a/drivers/char/ipmi/ipmi_si_intf.c b/drivers/char/ipmi/ipmi_si_intf.c
index b1732882b97e..f124a2d2bb9f 100644
--- a/drivers/char/ipmi/ipmi_si_intf.c
+++ b/drivers/char/ipmi/ipmi_si_intf.c
@@ -1931,7 +1931,6 @@ static int try_smi_init(struct smi_info *new_smi)
{
int rv = 0;
int i;
- char *init_name = NULL;
pr_info("Trying %s-specified %s state machine at %s address 0x%lx, slave address 0x%x, irq %d\n",
ipmi_addr_src_to_str(new_smi->io.addr_source),
@@ -2073,7 +2072,6 @@ static int try_smi_init(struct smi_info *new_smi)
new_smi->io.io_cleanup = NULL;
}
- kfree(init_name);
return rv;
}
diff --git a/drivers/char/ipmi/ipmi_si_platform.c b/drivers/char/ipmi/ipmi_si_platform.c
index 54c7ded2a1ff..f2a91c4d8cab 100644
--- a/drivers/char/ipmi/ipmi_si_platform.c
+++ b/drivers/char/ipmi/ipmi_si_platform.c
@@ -188,12 +188,10 @@ static int platform_ipmi_probe(struct platform_device *pdev)
return -EINVAL;
rv = device_property_read_u8(&pdev->dev, "slave-addr", &slave_addr);
- if (rv) {
- dev_warn(&pdev->dev, "device has no slave-addr property\n");
+ if (rv)
io.slave_addr = 0x20;
- } else {
+ else
io.slave_addr = slave_addr;
- }
io.irq = platform_get_irq(pdev, 0);
if (io.irq > 0)
diff --git a/drivers/char/ipmi/ipmi_ssif.c b/drivers/char/ipmi/ipmi_ssif.c
index 8b5aec5430f1..cf8156d6bc07 100644
--- a/drivers/char/ipmi/ipmi_ssif.c
+++ b/drivers/char/ipmi/ipmi_ssif.c
@@ -727,12 +727,16 @@ static void msg_done_handler(struct ssif_info *ssif_info, int result,
/* End of read */
len = ssif_info->multi_len;
data = ssif_info->data;
- } else if (blocknum != ssif_info->multi_pos) {
+ } else if (blocknum + 1 != ssif_info->multi_pos) {
/*
* Out of sequence block, just abort. Block
* numbers start at zero for the second block,
* but multi_pos starts at one, so the +1.
*/
+ if (ssif_info->ssif_debug & SSIF_DEBUG_MSG)
+ dev_dbg(&ssif_info->client->dev,
+ "Received message out of sequence, expected %u, got %u\n",
+ ssif_info->multi_pos - 1, blocknum);
result = -EIO;
} else {
ssif_inc_stat(ssif_info, received_message_parts);
@@ -1991,7 +1995,7 @@ static int dmi_ipmi_probe(struct platform_device *pdev)
rv = device_property_read_u8(&pdev->dev, "slave-addr", &slave_addr);
if (rv)
- dev_warn(&pdev->dev, "device has no slave-addr property");
+ slave_addr = 0x20;
return new_ssif_client(i2c_addr, NULL, 0,
slave_addr, SI_SMBIOS, &pdev->dev);
@@ -2107,7 +2111,8 @@ static void cleanup_ipmi_ssif(void)
kfree(ssif_i2c_driver.address_list);
- platform_driver_unregister(&ipmi_driver);
+ if (ssif_trydmi)
+ platform_driver_unregister(&ipmi_driver);
free_ssif_clients();
}
diff --git a/drivers/char/ipmi/ipmi_watchdog.c b/drivers/char/ipmi/ipmi_watchdog.c
index 2924a4bc4a32..74c6d1f34132 100644
--- a/drivers/char/ipmi/ipmi_watchdog.c
+++ b/drivers/char/ipmi/ipmi_watchdog.c
@@ -837,7 +837,7 @@ static int ipmi_open(struct inode *ino, struct file *filep)
* first heartbeat.
*/
ipmi_start_timer_on_heartbeat = 1;
- return nonseekable_open(ino, filep);
+ return stream_open(ino, filep);
default:
return (-ENODEV);
diff --git a/drivers/char/pcmcia/cm4000_cs.c b/drivers/char/pcmcia/cm4000_cs.c
index 7a4eb86aedac..15bf585af5d3 100644
--- a/drivers/char/pcmcia/cm4000_cs.c
+++ b/drivers/char/pcmcia/cm4000_cs.c
@@ -1682,7 +1682,7 @@ static int cmm_open(struct inode *inode, struct file *filp)
link->open = 1; /* only one open per device */
DEBUGP(2, dev, "<- cmm_open\n");
- ret = nonseekable_open(inode, filp);
+ ret = stream_open(inode, filp);
out:
mutex_unlock(&cmm_mutex);
return ret;
diff --git a/drivers/char/pcmcia/scr24x_cs.c b/drivers/char/pcmcia/scr24x_cs.c
index f6b43d9350f0..04b39c3596cc 100644
--- a/drivers/char/pcmcia/scr24x_cs.c
+++ b/drivers/char/pcmcia/scr24x_cs.c
@@ -92,7 +92,7 @@ static int scr24x_open(struct inode *inode, struct file *filp)
kref_get(&dev->refcnt);
filp->private_data = dev;
- return nonseekable_open(inode, filp);
+ return stream_open(inode, filp);
}
static int scr24x_release(struct inode *inode, struct file *filp)
diff --git a/drivers/char/random.c b/drivers/char/random.c
index 38c6d1af6d1c..a42b3d764da8 100644
--- a/drivers/char/random.c
+++ b/drivers/char/random.c
@@ -101,15 +101,13 @@
* Exported interfaces ---- output
* ===============================
*
- * There are three exported interfaces; the first is one designed to
- * be used from within the kernel:
+ * There are four exported interfaces; two for use within the kernel,
+ * and two or use from userspace.
*
- * void get_random_bytes(void *buf, int nbytes);
- *
- * This interface will return the requested number of random bytes,
- * and place it in the requested buffer.
+ * Exported interfaces ---- userspace output
+ * -----------------------------------------
*
- * The two other interfaces are two character devices /dev/random and
+ * The userspace interfaces are two character devices /dev/random and
* /dev/urandom. /dev/random is suitable for use when very high
* quality randomness is desired (for example, for key generation or
* one-time pads), as it will only return a maximum of the number of
@@ -122,6 +120,77 @@
* this will result in random numbers that are merely cryptographically
* strong. For many applications, however, this is acceptable.
*
+ * Exported interfaces ---- kernel output
+ * --------------------------------------
+ *
+ * The primary kernel interface is
+ *
+ * void get_random_bytes(void *buf, int nbytes);
+ *
+ * This interface will return the requested number of random bytes,
+ * and place it in the requested buffer. This is equivalent to a
+ * read from /dev/urandom.
+ *
+ * For less critical applications, there are the functions:
+ *
+ * u32 get_random_u32()
+ * u64 get_random_u64()
+ * unsigned int get_random_int()
+ * unsigned long get_random_long()
+ *
+ * These are produced by a cryptographic RNG seeded from get_random_bytes,
+ * and so do not deplete the entropy pool as much. These are recommended
+ * for most in-kernel operations *if the result is going to be stored in
+ * the kernel*.
+ *
+ * Specifically, the get_random_int() family do not attempt to do
+ * "anti-backtracking". If you capture the state of the kernel (e.g.
+ * by snapshotting the VM), you can figure out previous get_random_int()
+ * return values. But if the value is stored in the kernel anyway,
+ * this is not a problem.
+ *
+ * It *is* safe to expose get_random_int() output to attackers (e.g. as
+ * network cookies); given outputs 1..n, it's not feasible to predict
+ * outputs 0 or n+1. The only concern is an attacker who breaks into
+ * the kernel later; the get_random_int() engine is not reseeded as
+ * often as the get_random_bytes() one.
+ *
+ * get_random_bytes() is needed for keys that need to stay secret after
+ * they are erased from the kernel. For example, any key that will
+ * be wrapped and stored encrypted. And session encryption keys: we'd
+ * like to know that after the session is closed and the keys erased,
+ * the plaintext is unrecoverable to someone who recorded the ciphertext.
+ *
+ * But for network ports/cookies, stack canaries, PRNG seeds, address
+ * space layout randomization, session *authentication* keys, or other
+ * applications where the sensitive data is stored in the kernel in
+ * plaintext for as long as it's sensitive, the get_random_int() family
+ * is just fine.
+ *
+ * Consider ASLR. We want to keep the address space secret from an
+ * outside attacker while the process is running, but once the address
+ * space is torn down, it's of no use to an attacker any more. And it's
+ * stored in kernel data structures as long as it's alive, so worrying
+ * about an attacker's ability to extrapolate it from the get_random_int()
+ * CRNG is silly.
+ *
+ * Even some cryptographic keys are safe to generate with get_random_int().
+ * In particular, keys for SipHash are generally fine. Here, knowledge
+ * of the key authorizes you to do something to a kernel object (inject
+ * packets to a network connection, or flood a hash table), and the
+ * key is stored with the object being protected. Once it goes away,
+ * we no longer care if anyone knows the key.
+ *
+ * prandom_u32()
+ * -------------
+ *
+ * For even weaker applications, see the pseudorandom generator
+ * prandom_u32(), prandom_max(), and prandom_bytes(). If the random
+ * numbers aren't security-critical at all, these are *far* cheaper.
+ * Useful for self-tests, random error simulation, randomized backoffs,
+ * and any other application where you trust that nobody is trying to
+ * maliciously mess with you by guessing the "random" numbers.
+ *
* Exported interfaces ---- input
* ==============================
*
@@ -295,7 +364,7 @@
* To allow fractional bits to be tracked, the entropy_count field is
* denominated in units of 1/8th bits.
*
- * 2*(ENTROPY_SHIFT + log2(poolbits)) must <= 31, or the multiply in
+ * 2*(ENTROPY_SHIFT + poolbitshift) must <= 31, or the multiply in
* credit_entropy_bits() needs to be 64 bits wide.
*/
#define ENTROPY_SHIFT 3
@@ -359,9 +428,9 @@ static int random_write_wakeup_bits = 28 * OUTPUT_POOL_WORDS;
* polynomial which improves the resulting TGFSR polynomial to be
* irreducible, which we have made here.
*/
-static struct poolinfo {
- int poolbitshift, poolwords, poolbytes, poolbits, poolfracbits;
-#define S(x) ilog2(x)+5, (x), (x)*4, (x)*32, (x) << (ENTROPY_SHIFT+5)
+static const struct poolinfo {
+ int poolbitshift, poolwords, poolbytes, poolfracbits;
+#define S(x) ilog2(x)+5, (x), (x)*4, (x) << (ENTROPY_SHIFT+5)
int tap1, tap2, tap3, tap4, tap5;
} poolinfo_table[] = {
/* was: x^128 + x^103 + x^76 + x^51 +x^25 + x + 1 */
@@ -415,7 +484,7 @@ struct crng_state {
spinlock_t lock;
};
-struct crng_state primary_crng = {
+static struct crng_state primary_crng = {
.lock = __SPIN_LOCK_UNLOCKED(primary_crng.lock),
};
@@ -470,7 +539,6 @@ struct entropy_store {
unsigned short add_ptr;
unsigned short input_rotate;
int entropy_count;
- int entropy_total;
unsigned int initialized:1;
unsigned int last_data_init:1;
__u8 last_data[EXTRACT_SIZE];
@@ -643,7 +711,7 @@ static void process_random_ready_list(void)
*/
static void credit_entropy_bits(struct entropy_store *r, int nbits)
{
- int entropy_count, orig;
+ int entropy_count, orig, has_initialized = 0;
const int pool_size = r->poolinfo->poolfracbits;
int nfrac = nbits << ENTROPY_SHIFT;
@@ -698,23 +766,25 @@ retry:
entropy_count = 0;
} else if (entropy_count > pool_size)
entropy_count = pool_size;
+ if ((r == &blocking_pool) && !r->initialized &&
+ (entropy_count >> ENTROPY_SHIFT) > 128)
+ has_initialized = 1;
if (cmpxchg(&r->entropy_count, orig, entropy_count) != orig)
goto retry;
- r->entropy_total += nbits;
- if (!r->initialized && r->entropy_total > 128) {
+ if (has_initialized)
r->initialized = 1;
- r->entropy_total = 0;
- }
trace_credit_entropy_bits(r->name, nbits,
- entropy_count >> ENTROPY_SHIFT,
- r->entropy_total, _RET_IP_);
+ entropy_count >> ENTROPY_SHIFT, _RET_IP_);
if (r == &input_pool) {
int entropy_bits = entropy_count >> ENTROPY_SHIFT;
+ struct entropy_store *other = &blocking_pool;
- if (crng_init < 2 && entropy_bits >= 128) {
+ if (crng_init < 2) {
+ if (entropy_bits < 128)
+ return;
crng_reseed(&primary_crng, r);
entropy_bits = r->entropy_count >> ENTROPY_SHIFT;
}
@@ -725,20 +795,14 @@ retry:
wake_up_interruptible(&random_read_wait);
kill_fasync(&fasync, SIGIO, POLL_IN);
}
- /* If the input pool is getting full, send some
- * entropy to the blocking pool until it is 75% full.
+ /* If the input pool is getting full, and the blocking
+ * pool has room, send some entropy to the blocking
+ * pool.
*/
- if (entropy_bits > random_write_wakeup_bits &&
- r->initialized &&
- r->entropy_total >= 2*random_read_wakeup_bits) {
- struct entropy_store *other = &blocking_pool;
-
- if (other->entropy_count <=
- 3 * other->poolinfo->poolfracbits / 4) {
- schedule_work(&other->push_work);
- r->entropy_total = 0;
- }
- }
+ if (!work_pending(&other->push_work) &&
+ (ENTROPY_BITS(r) > 6 * r->poolinfo->poolbytes) &&
+ (ENTROPY_BITS(other) <= 6 * other->poolinfo->poolbytes))
+ schedule_work(&other->push_work);
}
}
@@ -777,6 +841,7 @@ static struct crng_state **crng_node_pool __read_mostly;
#endif
static void invalidate_batched_entropy(void);
+static void numa_crng_init(void);
static bool trust_cpu __ro_after_init = IS_ENABLED(CONFIG_RANDOM_TRUST_CPU);
static int __init parse_trust_cpu(char *arg)
@@ -805,7 +870,9 @@ static void crng_initialize(struct crng_state *crng)
}
crng->state[i] ^= rv;
}
- if (trust_cpu && arch_init) {
+ if (trust_cpu && arch_init && crng == &primary_crng) {
+ invalidate_batched_entropy();
+ numa_crng_init();
crng_init = 2;
pr_notice("random: crng done (trusting CPU's manufacturer)\n");
}
@@ -1553,6 +1620,11 @@ static ssize_t extract_entropy_user(struct entropy_store *r, void __user *buf,
int large_request = (nbytes > 256);
trace_extract_entropy_user(r->name, nbytes, ENTROPY_BITS(r), _RET_IP_);
+ if (!r->initialized && r->pull) {
+ xfer_secondary_pool(r, ENTROPY_BITS(r->pull)/8);
+ if (!r->initialized)
+ return 0;
+ }
xfer_secondary_pool(r, nbytes);
nbytes = account(r, nbytes, 0, 0);
@@ -1783,7 +1855,7 @@ EXPORT_SYMBOL(get_random_bytes_arch);
* data into the pool to prepare it for use. The pool is not cleared
* as that can only decrease the entropy in the pool.
*/
-static void init_std_data(struct entropy_store *r)
+static void __init init_std_data(struct entropy_store *r)
{
int i;
ktime_t now = ktime_get_real();
@@ -1810,7 +1882,7 @@ static void init_std_data(struct entropy_store *r)
* take care not to overwrite the precious per platform data
* we were given.
*/
-static int rand_initialize(void)
+int __init rand_initialize(void)
{
init_std_data(&input_pool);
init_std_data(&blocking_pool);
@@ -1822,7 +1894,6 @@ static int rand_initialize(void)
}
return 0;
}
-early_initcall(rand_initialize);
#ifdef CONFIG_BLOCK
void rand_initialize_disk(struct gendisk *disk)
@@ -2211,8 +2282,8 @@ struct batched_entropy {
u32 entropy_u32[CHACHA_BLOCK_SIZE / sizeof(u32)];
};
unsigned int position;
+ spinlock_t batch_lock;
};
-static rwlock_t batched_entropy_reset_lock = __RW_LOCK_UNLOCKED(batched_entropy_reset_lock);
/*
* Get a random word for internal kernel use only. The quality of the random
@@ -2222,12 +2293,14 @@ static rwlock_t batched_entropy_reset_lock = __RW_LOCK_UNLOCKED(batched_entropy_
* wait_for_random_bytes() should be called and return 0 at least once
* at any point prior.
*/
-static DEFINE_PER_CPU(struct batched_entropy, batched_entropy_u64);
+static DEFINE_PER_CPU(struct batched_entropy, batched_entropy_u64) = {
+ .batch_lock = __SPIN_LOCK_UNLOCKED(batched_entropy_u64.lock),
+};
+
u64 get_random_u64(void)
{
u64 ret;
- bool use_lock;
- unsigned long flags = 0;
+ unsigned long flags;
struct batched_entropy *batch;
static void *previous;
@@ -2242,28 +2315,25 @@ u64 get_random_u64(void)
warn_unseeded_randomness(&previous);
- use_lock = READ_ONCE(crng_init) < 2;
- batch = &get_cpu_var(batched_entropy_u64);
- if (use_lock)
- read_lock_irqsave(&batched_entropy_reset_lock, flags);
+ batch = raw_cpu_ptr(&batched_entropy_u64);
+ spin_lock_irqsave(&batch->batch_lock, flags);
if (batch->position % ARRAY_SIZE(batch->entropy_u64) == 0) {
extract_crng((u8 *)batch->entropy_u64);
batch->position = 0;
}
ret = batch->entropy_u64[batch->position++];
- if (use_lock)
- read_unlock_irqrestore(&batched_entropy_reset_lock, flags);
- put_cpu_var(batched_entropy_u64);
+ spin_unlock_irqrestore(&batch->batch_lock, flags);
return ret;
}
EXPORT_SYMBOL(get_random_u64);
-static DEFINE_PER_CPU(struct batched_entropy, batched_entropy_u32);
+static DEFINE_PER_CPU(struct batched_entropy, batched_entropy_u32) = {
+ .batch_lock = __SPIN_LOCK_UNLOCKED(batched_entropy_u32.lock),
+};
u32 get_random_u32(void)
{
u32 ret;
- bool use_lock;
- unsigned long flags = 0;
+ unsigned long flags;
struct batched_entropy *batch;
static void *previous;
@@ -2272,18 +2342,14 @@ u32 get_random_u32(void)
warn_unseeded_randomness(&previous);
- use_lock = READ_ONCE(crng_init) < 2;
- batch = &get_cpu_var(batched_entropy_u32);
- if (use_lock)
- read_lock_irqsave(&batched_entropy_reset_lock, flags);
+ batch = raw_cpu_ptr(&batched_entropy_u32);
+ spin_lock_irqsave(&batch->batch_lock, flags);
if (batch->position % ARRAY_SIZE(batch->entropy_u32) == 0) {
extract_crng((u8 *)batch->entropy_u32);
batch->position = 0;
}
ret = batch->entropy_u32[batch->position++];
- if (use_lock)
- read_unlock_irqrestore(&batched_entropy_reset_lock, flags);
- put_cpu_var(batched_entropy_u32);
+ spin_unlock_irqrestore(&batch->batch_lock, flags);
return ret;
}
EXPORT_SYMBOL(get_random_u32);
@@ -2297,12 +2363,19 @@ static void invalidate_batched_entropy(void)
int cpu;
unsigned long flags;
- write_lock_irqsave(&batched_entropy_reset_lock, flags);
for_each_possible_cpu (cpu) {
- per_cpu_ptr(&batched_entropy_u32, cpu)->position = 0;
- per_cpu_ptr(&batched_entropy_u64, cpu)->position = 0;
+ struct batched_entropy *batched_entropy;
+
+ batched_entropy = per_cpu_ptr(&batched_entropy_u32, cpu);
+ spin_lock_irqsave(&batched_entropy->batch_lock, flags);
+ batched_entropy->position = 0;
+ spin_unlock(&batched_entropy->batch_lock);
+
+ batched_entropy = per_cpu_ptr(&batched_entropy_u64, cpu);
+ spin_lock(&batched_entropy->batch_lock);
+ batched_entropy->position = 0;
+ spin_unlock_irqrestore(&batched_entropy->batch_lock, flags);
}
- write_unlock_irqrestore(&batched_entropy_reset_lock, flags);
}
/**
diff --git a/drivers/char/tb0219.c b/drivers/char/tb0219.c
index 7c19d9b22785..e8614ea843e2 100644
--- a/drivers/char/tb0219.c
+++ b/drivers/char/tb0219.c
@@ -243,7 +243,7 @@ static int tanbac_tb0219_open(struct inode *inode, struct file *file)
case 16 ... 23:
case 32 ... 39:
case 48 ... 55:
- return nonseekable_open(inode, file);
+ return stream_open(inode, file);
default:
break;
}
diff --git a/drivers/char/tpm/Kconfig b/drivers/char/tpm/Kconfig
index 536e55d3919f..f3e4bc490cf0 100644
--- a/drivers/char/tpm/Kconfig
+++ b/drivers/char/tpm/Kconfig
@@ -157,7 +157,6 @@ config TCG_CRB
config TCG_VTPM_PROXY
tristate "VTPM Proxy Interface"
depends on TCG_TPM
- select ANON_INODES
---help---
This driver proxies for an emulated TPM (vTPM) running in userspace.
A device /dev/vtpmx is provided that creates a device pair
diff --git a/drivers/char/virtio_console.c b/drivers/char/virtio_console.c
index fbeb71953526..05dbfdb9f4af 100644
--- a/drivers/char/virtio_console.c
+++ b/drivers/char/virtio_console.c
@@ -75,7 +75,7 @@ struct ports_driver_data {
/* All the console devices handled by this driver */
struct list_head consoles;
};
-static struct ports_driver_data pdrvdata;
+static struct ports_driver_data pdrvdata = { .next_vtermno = 1};
static DEFINE_SPINLOCK(pdrvdata_lock);
static DECLARE_COMPLETION(early_console_added);
@@ -1394,6 +1394,7 @@ static int add_port(struct ports_device *portdev, u32 id)
port->async_queue = NULL;
port->cons.ws.ws_row = port->cons.ws.ws_col = 0;
+ port->cons.vtermno = 0;
port->host_connected = port->guest_connected = false;
port->stats = (struct port_stats) { 0 };