summaryrefslogtreecommitdiff
path: root/drivers/char
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/char')
-rw-r--r--drivers/char/hpet.c6
-rw-r--r--drivers/char/ipmi/ipmi_msghandler.c10
-rw-r--r--drivers/char/sonypi.c6
-rw-r--r--drivers/char/tlclk.c4
-rw-r--r--drivers/char/tpm/eventlog/tpm1.c4
-rw-r--r--drivers/char/tpm/tpm-dev.c2
-rw-r--r--drivers/char/tpm/tpm2-cmd.c6
-rw-r--r--drivers/char/tpm/tpm2-sessions.c45
-rw-r--r--drivers/char/tpm/tpm_crb.c6
-rw-r--r--drivers/char/tpm/tpm_tis_core.c35
-rw-r--r--drivers/char/tpm/tpmrm-dev.c2
-rw-r--r--drivers/char/virtio_console.c52
12 files changed, 120 insertions, 58 deletions
diff --git a/drivers/char/hpet.c b/drivers/char/hpet.c
index 46c84e5df00f..285c6037417a 100644
--- a/drivers/char/hpet.c
+++ b/drivers/char/hpet.c
@@ -976,10 +976,14 @@ static acpi_status hpet_resources(struct acpi_resource *res, void *data)
static int hpet_acpi_probe(struct platform_device *pdev)
{
- struct acpi_device *device = ACPI_COMPANION(&pdev->dev);
+ struct acpi_device *device;
acpi_status result;
struct hpet_data data;
+ device = ACPI_COMPANION(&pdev->dev);
+ if (!device)
+ return -ENODEV;
+
memset(&data, 0, sizeof(data));
result =
diff --git a/drivers/char/ipmi/ipmi_msghandler.c b/drivers/char/ipmi/ipmi_msghandler.c
index 869ac87a4b6a..3e0b7d60269d 100644
--- a/drivers/char/ipmi/ipmi_msghandler.c
+++ b/drivers/char/ipmi/ipmi_msghandler.c
@@ -2347,6 +2347,10 @@ static int i_ipmi_request(struct ipmi_user *user,
if (smi_msg == NULL) {
if (!supplied_recv)
ipmi_free_recv_msg(recv_msg);
+ else if (recv_msg->user) {
+ atomic_dec(&recv_msg->user->nr_msgs);
+ kref_put(&recv_msg->user->refcount, free_ipmi_user);
+ }
return -ENOMEM;
}
}
@@ -2420,6 +2424,10 @@ out_err:
ipmi_free_smi_msg(smi_msg);
if (!supplied_recv)
ipmi_free_recv_msg(recv_msg);
+ else if (recv_msg->user) {
+ atomic_dec(&recv_msg->user->nr_msgs);
+ kref_put(&recv_msg->user->refcount, free_ipmi_user);
+ }
}
return rv;
}
@@ -4477,10 +4485,8 @@ static int handle_read_event_rsp(struct ipmi_smi *intf,
mutex_unlock(&intf->users_mutex);
list_for_each_entry_safe(recv_msg, recv_msg2, &msgs,
link) {
- user = recv_msg->user;
list_del(&recv_msg->link);
ipmi_free_recv_msg(recv_msg);
- kref_put(&user->refcount, free_ipmi_user);
}
/*
* We couldn't allocate memory for the
diff --git a/drivers/char/sonypi.c b/drivers/char/sonypi.c
index ccda997a9098..24c1b26f34d6 100644
--- a/drivers/char/sonypi.c
+++ b/drivers/char/sonypi.c
@@ -1117,7 +1117,11 @@ static int sonypi_disable(void)
#ifdef CONFIG_ACPI
static int sonypi_acpi_probe(struct platform_device *pdev)
{
- struct acpi_device *device = ACPI_COMPANION(&pdev->dev);
+ struct acpi_device *device;
+
+ device = ACPI_COMPANION(&pdev->dev);
+ if (!device)
+ return -ENODEV;
sonypi_acpi_device = device;
strcpy(acpi_device_name(device), "Sony laptop hotkeys");
diff --git a/drivers/char/tlclk.c b/drivers/char/tlclk.c
index 677d230a226c..dd45fe5eb6f2 100644
--- a/drivers/char/tlclk.c
+++ b/drivers/char/tlclk.c
@@ -264,6 +264,7 @@ static ssize_t tlclk_read(struct file *filp, char __user *buf, size_t count,
}
static const struct file_operations tlclk_fops = {
+ .owner = THIS_MODULE,
.read = tlclk_read,
.open = tlclk_open,
.release = tlclk_release,
@@ -837,6 +838,9 @@ static void __exit tlclk_cleanup(void)
misc_deregister(&tlclk_miscdev);
unregister_chrdev(tlclk_major, "telco_clock");
+ got_event = 1;
+ wake_up_all(&wq);
+
release_region(TLCLK_BASE, 8);
timer_delete_sync(&switchover_timer);
kfree(alarm_events);
diff --git a/drivers/char/tpm/eventlog/tpm1.c b/drivers/char/tpm/eventlog/tpm1.c
index e7913b2853d5..0397e3361020 100644
--- a/drivers/char/tpm/eventlog/tpm1.c
+++ b/drivers/char/tpm/eventlog/tpm1.c
@@ -236,12 +236,12 @@ static int tpm1_binary_bios_measurements_show(struct seq_file *m, void *v)
temp_ptr = (char *) &temp_event;
- for (i = 0; i < (sizeof(struct tcpa_event) - 1) ; i++)
+ for (i = 0; i < sizeof(struct tcpa_event); i++)
seq_putc(m, temp_ptr[i]);
temp_ptr = (char *) v;
- for (i = (sizeof(struct tcpa_event) - 1);
+ for (i = sizeof(struct tcpa_event);
i < (sizeof(struct tcpa_event) + temp_event.event_size); i++)
seq_putc(m, temp_ptr[i]);
diff --git a/drivers/char/tpm/tpm-dev.c b/drivers/char/tpm/tpm-dev.c
index 2779a8738c59..74488f0a7b78 100644
--- a/drivers/char/tpm/tpm-dev.c
+++ b/drivers/char/tpm/tpm-dev.c
@@ -36,7 +36,7 @@ static int tpm_open(struct inode *inode, struct file *file)
tpm_common_open(file, chip, priv, NULL);
- return 0;
+ return nonseekable_open(inode, file);
out:
clear_bit(0, &chip->is_open);
diff --git a/drivers/char/tpm/tpm2-cmd.c b/drivers/char/tpm/tpm2-cmd.c
index b11e6fa8b740..52ee350da867 100644
--- a/drivers/char/tpm/tpm2-cmd.c
+++ b/drivers/char/tpm/tpm2-cmd.c
@@ -71,9 +71,9 @@ static const struct {
{TPM2_CC_HIERARCHY_CHANGE_AUTH, 2000},
{TPM2_CC_GET_CAPABILITY, 750},
{TPM2_CC_NV_READ, 2000},
- {TPM2_CC_CREATE_PRIMARY, 30000},
- {TPM2_CC_CREATE, 30000},
- {TPM2_CC_CREATE_LOADED, 30000},
+ {TPM2_CC_CREATE_PRIMARY, 300000},
+ {TPM2_CC_CREATE, 300000},
+ {TPM2_CC_CREATE_LOADED, 300000},
};
/**
diff --git a/drivers/char/tpm/tpm2-sessions.c b/drivers/char/tpm/tpm2-sessions.c
index c4da6fde748f..f44646b26b19 100644
--- a/drivers/char/tpm/tpm2-sessions.c
+++ b/drivers/char/tpm/tpm2-sessions.c
@@ -489,15 +489,17 @@ static void tpm2_KDFe(u8 z[EC_PT_SZ], const char *str, u8 *pt_u, u8 *pt_v,
sha256_final(&sctx, out);
}
-static void tpm_buf_append_salt(struct tpm_buf *buf, struct tpm_chip *chip,
- struct tpm2_auth *auth)
+static int tpm_buf_append_salt(struct tpm_buf *buf, struct tpm_chip *chip,
+ struct tpm2_auth *auth)
{
struct crypto_kpp *kpp;
struct kpp_request *req;
+ DECLARE_CRYPTO_WAIT(wait);
struct scatterlist s[2], d[1];
struct ecdh p = {0};
u8 encoded_key[EC_PT_SZ], *x, *y;
unsigned int buf_len;
+ int rc;
/* secret is two sized points */
tpm_buf_append_u16(buf, (EC_PT_SZ + 2)*2);
@@ -520,14 +522,15 @@ static void tpm_buf_append_salt(struct tpm_buf *buf, struct tpm_chip *chip,
kpp = crypto_alloc_kpp("ecdh-nist-p256", CRYPTO_ALG_INTERNAL, 0);
if (IS_ERR(kpp)) {
dev_err(&chip->dev, "crypto ecdh allocation failed\n");
- return;
+ return PTR_ERR(kpp);
}
buf_len = crypto_ecdh_key_len(&p);
if (sizeof(encoded_key) < buf_len) {
dev_err(&chip->dev, "salt buffer too small needs %d\n",
buf_len);
- goto out;
+ rc = -EINVAL;
+ goto err_free_kpp;
}
crypto_ecdh_encode_key(encoded_key, buf_len, &p);
/* this generates a random private key */
@@ -535,11 +538,17 @@ static void tpm_buf_append_salt(struct tpm_buf *buf, struct tpm_chip *chip,
/* salt is now the public point of this private key */
req = kpp_request_alloc(kpp, GFP_KERNEL);
- if (!req)
- goto out;
+ if (!req) {
+ rc = -ENOMEM;
+ goto err_free_kpp;
+ }
+ kpp_request_set_callback(req, CRYPTO_TFM_REQ_MAY_BACKLOG,
+ crypto_req_done, &wait);
kpp_request_set_input(req, NULL, 0);
kpp_request_set_output(req, s, EC_PT_SZ*2);
- crypto_kpp_generate_public_key(req);
+ rc = crypto_wait_req(crypto_kpp_generate_public_key(req), &wait);
+ if (rc)
+ goto err_free_req;
/*
* we're not done: now we have to compute the shared secret
* which is our private key multiplied by the tpm_key public
@@ -551,8 +560,9 @@ static void tpm_buf_append_salt(struct tpm_buf *buf, struct tpm_chip *chip,
kpp_request_set_input(req, s, EC_PT_SZ*2);
sg_init_one(d, auth->salt, EC_PT_SZ);
kpp_request_set_output(req, d, EC_PT_SZ);
- crypto_kpp_compute_shared_secret(req);
- kpp_request_free(req);
+ rc = crypto_wait_req(crypto_kpp_compute_shared_secret(req), &wait);
+ if (rc)
+ goto err_free_req;
/*
* pass the shared secret through KDFe for salt. Note salt
@@ -562,8 +572,16 @@ static void tpm_buf_append_salt(struct tpm_buf *buf, struct tpm_chip *chip,
*/
tpm2_KDFe(auth->salt, "SECRET", x, chip->null_ec_key_x, auth->salt);
- out:
+ kpp_request_free(req);
crypto_free_kpp(kpp);
+ return 0;
+
+err_free_req:
+ kpp_request_free(req);
+
+err_free_kpp:
+ crypto_free_kpp(kpp);
+ return rc;
}
/**
@@ -1018,7 +1036,12 @@ int tpm2_start_auth_session(struct tpm_chip *chip)
tpm_buf_append(&buf, auth->our_nonce, sizeof(auth->our_nonce));
/* append encrypted salt and squirrel away unencrypted in auth */
- tpm_buf_append_salt(&buf, chip, auth);
+ rc = tpm_buf_append_salt(&buf, chip, auth);
+ if (rc) {
+ tpm2_flush_context(chip, null_key);
+ tpm_buf_destroy(&buf);
+ goto out;
+ }
/* session type (HMAC, audit or policy) */
tpm_buf_append_u8(&buf, TPM2_SE_HMAC);
diff --git a/drivers/char/tpm/tpm_crb.c b/drivers/char/tpm/tpm_crb.c
index 7d1377e8e616..ceb4100ba400 100644
--- a/drivers/char/tpm/tpm_crb.c
+++ b/drivers/char/tpm/tpm_crb.c
@@ -786,8 +786,8 @@ static int crb_map_pluton(struct device *dev, struct crb_priv *priv,
static int crb_acpi_probe(struct platform_device *pdev)
{
struct device *dev = &pdev->dev;
- struct acpi_device *device = ACPI_COMPANION(dev);
struct acpi_table_tpm2 *buf;
+ struct acpi_device *device;
struct crb_priv *priv;
struct tpm_chip *chip;
struct tpm2_crb_smc *crb_smc;
@@ -797,6 +797,10 @@ static int crb_acpi_probe(struct platform_device *pdev)
u32 sm;
int rc;
+ device = ACPI_COMPANION(dev);
+ if (!device)
+ return -ENODEV;
+
status = acpi_get_table(ACPI_SIG_TPM2, 1,
(struct acpi_table_header **) &buf);
if (ACPI_FAILURE(status) || buf->header.length < sizeof(*buf)) {
diff --git a/drivers/char/tpm/tpm_tis_core.c b/drivers/char/tpm/tpm_tis_core.c
index 21d79ad3b164..153a57c79240 100644
--- a/drivers/char/tpm/tpm_tis_core.c
+++ b/drivers/char/tpm/tpm_tis_core.c
@@ -66,8 +66,8 @@ static int wait_for_tpm_stat(struct tpm_chip *chip, u8 mask,
bool check_cancel)
{
struct tpm_tis_data *priv = dev_get_drvdata(&chip->dev);
+ DEFINE_WAIT_FUNC(wait, woken_wake_function);
unsigned long stop;
- long rc;
u8 status;
bool canceled = false;
u8 sts_mask;
@@ -87,23 +87,30 @@ static int wait_for_tpm_stat(struct tpm_chip *chip, u8 mask,
/* process status changes with irq support */
if (sts_mask) {
ret = -ETIME;
+ add_wait_queue(queue, &wait);
again:
+ if (wait_for_tpm_stat_cond(chip, sts_mask, check_cancel,
+ &canceled)) {
+ ret = canceled ? -ECANCELED : 0;
+ goto out;
+ }
+
timeout = stop - jiffies;
if ((long)timeout <= 0)
- return -ETIME;
- rc = wait_event_interruptible_timeout(*queue,
- wait_for_tpm_stat_cond(chip, sts_mask, check_cancel,
- &canceled),
- timeout);
- if (rc > 0) {
- if (canceled)
- return -ECANCELED;
- ret = 0;
- }
- if (rc == -ERESTARTSYS && freezing(current)) {
- clear_thread_flag(TIF_SIGPENDING);
- goto again;
+ goto out;
+
+ if (signal_pending(current)) {
+ if (freezing(current)) {
+ clear_thread_flag(TIF_SIGPENDING);
+ goto again;
+ }
+ goto out;
}
+
+ wait_woken(&wait, TASK_INTERRUPTIBLE, timeout);
+ goto again;
+out:
+ remove_wait_queue(queue, &wait);
}
if (ret)
diff --git a/drivers/char/tpm/tpmrm-dev.c b/drivers/char/tpm/tpmrm-dev.c
index f48d4d9e179c..19e8f2779265 100644
--- a/drivers/char/tpm/tpmrm-dev.c
+++ b/drivers/char/tpm/tpmrm-dev.c
@@ -29,7 +29,7 @@ static int tpmrm_open(struct inode *inode, struct file *file)
tpm_common_open(file, chip, &priv->priv, &priv->space);
- return 0;
+ return nonseekable_open(inode, file);
}
static int tpmrm_release(struct inode *inode, struct file *file)
diff --git a/drivers/char/virtio_console.c b/drivers/char/virtio_console.c
index 9a33217c68d9..198b97314168 100644
--- a/drivers/char/virtio_console.c
+++ b/drivers/char/virtio_console.c
@@ -1771,32 +1771,40 @@ static void config_intr(struct virtio_device *vdev)
schedule_work(&portdev->config_work);
}
-static void config_work_handler(struct work_struct *work)
+static void update_size_from_config(struct ports_device *portdev)
{
- struct ports_device *portdev;
+ struct virtio_device *vdev;
+ struct port *port;
+ u16 rows, cols;
- portdev = container_of(work, struct ports_device, config_work);
- if (!use_multiport(portdev)) {
- struct virtio_device *vdev;
- struct port *port;
- u16 rows, cols;
+ vdev = portdev->vdev;
- vdev = portdev->vdev;
- virtio_cread(vdev, struct virtio_console_config, cols, &cols);
- virtio_cread(vdev, struct virtio_console_config, rows, &rows);
+ /*
+ * We'll use this way of resizing only for legacy support.
+ * For multiport devices, use control messages to indicate
+ * console size changes so that it can be done per-port.
+ *
+ * Don't test F_SIZE at all if we're rproc: not a valid feature.
+ */
+ if (is_rproc_serial(vdev) ||
+ use_multiport(portdev) ||
+ !virtio_has_feature(vdev, VIRTIO_CONSOLE_F_SIZE))
+ return;
- port = find_port_by_id(portdev, 0);
- set_console_size(port, rows, cols);
+ virtio_cread(vdev, struct virtio_console_config, cols, &cols);
+ virtio_cread(vdev, struct virtio_console_config, rows, &rows);
- /*
- * We'll use this way of resizing only for legacy
- * support. For newer userspace
- * (VIRTIO_CONSOLE_F_MULTPORT+), use control messages
- * to indicate console size changes so that it can be
- * done per-port.
- */
- resize_console(port);
- }
+ port = find_port_by_id(portdev, 0);
+ set_console_size(port, rows, cols);
+ resize_console(port);
+}
+
+static void config_work_handler(struct work_struct *work)
+{
+ struct ports_device *portdev;
+
+ portdev = container_of(work, struct ports_device, config_work);
+ update_size_from_config(portdev);
}
static int init_vqs(struct ports_device *portdev)
@@ -2052,6 +2060,8 @@ static int virtcons_probe(struct virtio_device *vdev)
__send_control_msg(portdev, VIRTIO_CONSOLE_BAD_ID,
VIRTIO_CONSOLE_DEVICE_READY, 1);
+ update_size_from_config(portdev);
+
return 0;
free_chrdev: