diff options
author | Linus Torvalds <torvalds@linux-foundation.org> | 2018-10-25 16:25:18 -0400 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2018-10-25 16:25:18 -0400 |
commit | 52ff0779d6cfcce24c0204c22b0b4899dc55449d (patch) | |
tree | 76bc30ca328f4f6263426b6d5b1c530f91164eb7 | |
parent | 57ce66d39f10fb01efabd72b14eb033deddb226b (diff) | |
parent | b8d7b758145252e60ea0198e531a8b00a75b8895 (diff) |
Merge branch 'next-tpm' of git://git.kernel.org/pub/scm/linux/kernel/git/jmorris/linux-security
Pull TPM updates from James Morris:
"From Jarkko: The only new feature is non-blocking operation for
/dev/tpm0"
* 'next-tpm' of git://git.kernel.org/pub/scm/linux/kernel/git/jmorris/linux-security:
tpm: Restore functionality to xen vtpm driver.
tpm: add support for nonblocking operation
tpm: add ptr to the tpm_space struct to file_priv
tpm: Make SECURITYFS a weak dependency
tpm: suppress transmit cmd error logs when TPM 1.2 is disabled/deactivated
tpm: fix response size validation in tpm_get_random()
-rw-r--r-- | drivers/char/tpm/Kconfig | 2 | ||||
-rw-r--r-- | drivers/char/tpm/tpm-dev-common.c | 147 | ||||
-rw-r--r-- | drivers/char/tpm/tpm-dev.c | 11 | ||||
-rw-r--r-- | drivers/char/tpm/tpm-dev.h | 18 | ||||
-rw-r--r-- | drivers/char/tpm/tpm-interface.c | 30 | ||||
-rw-r--r-- | drivers/char/tpm/tpm.h | 2 | ||||
-rw-r--r-- | drivers/char/tpm/tpm2-cmd.c | 4 | ||||
-rw-r--r-- | drivers/char/tpm/tpmrm-dev.c | 15 | ||||
-rw-r--r-- | drivers/char/tpm/xen-tpmfront.c | 2 |
9 files changed, 157 insertions, 74 deletions
diff --git a/drivers/char/tpm/Kconfig b/drivers/char/tpm/Kconfig index 18c81cbe4704..536e55d3919f 100644 --- a/drivers/char/tpm/Kconfig +++ b/drivers/char/tpm/Kconfig | |||
@@ -5,7 +5,7 @@ | |||
5 | menuconfig TCG_TPM | 5 | menuconfig TCG_TPM |
6 | tristate "TPM Hardware Support" | 6 | tristate "TPM Hardware Support" |
7 | depends on HAS_IOMEM | 7 | depends on HAS_IOMEM |
8 | select SECURITYFS | 8 | imply SECURITYFS |
9 | select CRYPTO | 9 | select CRYPTO |
10 | select CRYPTO_HASH_INFO | 10 | select CRYPTO_HASH_INFO |
11 | ---help--- | 11 | ---help--- |
diff --git a/drivers/char/tpm/tpm-dev-common.c b/drivers/char/tpm/tpm-dev-common.c index e4a04b2d3c32..99b5133a9d05 100644 --- a/drivers/char/tpm/tpm-dev-common.c +++ b/drivers/char/tpm/tpm-dev-common.c | |||
@@ -17,11 +17,36 @@ | |||
17 | * License. | 17 | * License. |
18 | * | 18 | * |
19 | */ | 19 | */ |
20 | #include <linux/poll.h> | ||
20 | #include <linux/slab.h> | 21 | #include <linux/slab.h> |
21 | #include <linux/uaccess.h> | 22 | #include <linux/uaccess.h> |
23 | #include <linux/workqueue.h> | ||
22 | #include "tpm.h" | 24 | #include "tpm.h" |
23 | #include "tpm-dev.h" | 25 | #include "tpm-dev.h" |
24 | 26 | ||
27 | static struct workqueue_struct *tpm_dev_wq; | ||
28 | static DEFINE_MUTEX(tpm_dev_wq_lock); | ||
29 | |||
30 | static void tpm_async_work(struct work_struct *work) | ||
31 | { | ||
32 | struct file_priv *priv = | ||
33 | container_of(work, struct file_priv, async_work); | ||
34 | ssize_t ret; | ||
35 | |||
36 | mutex_lock(&priv->buffer_mutex); | ||
37 | priv->command_enqueued = false; | ||
38 | ret = tpm_transmit(priv->chip, priv->space, priv->data_buffer, | ||
39 | sizeof(priv->data_buffer), 0); | ||
40 | |||
41 | tpm_put_ops(priv->chip); | ||
42 | if (ret > 0) { | ||
43 | priv->data_pending = ret; | ||
44 | mod_timer(&priv->user_read_timer, jiffies + (120 * HZ)); | ||
45 | } | ||
46 | mutex_unlock(&priv->buffer_mutex); | ||
47 | wake_up_interruptible(&priv->async_wait); | ||
48 | } | ||
49 | |||
25 | static void user_reader_timeout(struct timer_list *t) | 50 | static void user_reader_timeout(struct timer_list *t) |
26 | { | 51 | { |
27 | struct file_priv *priv = from_timer(priv, t, user_read_timer); | 52 | struct file_priv *priv = from_timer(priv, t, user_read_timer); |
@@ -29,27 +54,32 @@ static void user_reader_timeout(struct timer_list *t) | |||
29 | pr_warn("TPM user space timeout is deprecated (pid=%d)\n", | 54 | pr_warn("TPM user space timeout is deprecated (pid=%d)\n", |
30 | task_tgid_nr(current)); | 55 | task_tgid_nr(current)); |
31 | 56 | ||
32 | schedule_work(&priv->work); | 57 | schedule_work(&priv->timeout_work); |
33 | } | 58 | } |
34 | 59 | ||
35 | static void timeout_work(struct work_struct *work) | 60 | static void tpm_timeout_work(struct work_struct *work) |
36 | { | 61 | { |
37 | struct file_priv *priv = container_of(work, struct file_priv, work); | 62 | struct file_priv *priv = container_of(work, struct file_priv, |
63 | timeout_work); | ||
38 | 64 | ||
39 | mutex_lock(&priv->buffer_mutex); | 65 | mutex_lock(&priv->buffer_mutex); |
40 | priv->data_pending = 0; | 66 | priv->data_pending = 0; |
41 | memset(priv->data_buffer, 0, sizeof(priv->data_buffer)); | 67 | memset(priv->data_buffer, 0, sizeof(priv->data_buffer)); |
42 | mutex_unlock(&priv->buffer_mutex); | 68 | mutex_unlock(&priv->buffer_mutex); |
69 | wake_up_interruptible(&priv->async_wait); | ||
43 | } | 70 | } |
44 | 71 | ||
45 | void tpm_common_open(struct file *file, struct tpm_chip *chip, | 72 | void tpm_common_open(struct file *file, struct tpm_chip *chip, |
46 | struct file_priv *priv) | 73 | struct file_priv *priv, struct tpm_space *space) |
47 | { | 74 | { |
48 | priv->chip = chip; | 75 | priv->chip = chip; |
76 | priv->space = space; | ||
77 | |||
49 | mutex_init(&priv->buffer_mutex); | 78 | mutex_init(&priv->buffer_mutex); |
50 | timer_setup(&priv->user_read_timer, user_reader_timeout, 0); | 79 | timer_setup(&priv->user_read_timer, user_reader_timeout, 0); |
51 | INIT_WORK(&priv->work, timeout_work); | 80 | INIT_WORK(&priv->timeout_work, tpm_timeout_work); |
52 | 81 | INIT_WORK(&priv->async_work, tpm_async_work); | |
82 | init_waitqueue_head(&priv->async_wait); | ||
53 | file->private_data = priv; | 83 | file->private_data = priv; |
54 | } | 84 | } |
55 | 85 | ||
@@ -61,15 +91,17 @@ ssize_t tpm_common_read(struct file *file, char __user *buf, | |||
61 | int rc; | 91 | int rc; |
62 | 92 | ||
63 | del_singleshot_timer_sync(&priv->user_read_timer); | 93 | del_singleshot_timer_sync(&priv->user_read_timer); |
64 | flush_work(&priv->work); | 94 | flush_work(&priv->timeout_work); |
65 | mutex_lock(&priv->buffer_mutex); | 95 | mutex_lock(&priv->buffer_mutex); |
66 | 96 | ||
67 | if (priv->data_pending) { | 97 | if (priv->data_pending) { |
68 | ret_size = min_t(ssize_t, size, priv->data_pending); | 98 | ret_size = min_t(ssize_t, size, priv->data_pending); |
69 | rc = copy_to_user(buf, priv->data_buffer, ret_size); | 99 | if (ret_size > 0) { |
70 | memset(priv->data_buffer, 0, priv->data_pending); | 100 | rc = copy_to_user(buf, priv->data_buffer, ret_size); |
71 | if (rc) | 101 | memset(priv->data_buffer, 0, priv->data_pending); |
72 | ret_size = -EFAULT; | 102 | if (rc) |
103 | ret_size = -EFAULT; | ||
104 | } | ||
73 | 105 | ||
74 | priv->data_pending = 0; | 106 | priv->data_pending = 0; |
75 | } | 107 | } |
@@ -79,13 +111,12 @@ ssize_t tpm_common_read(struct file *file, char __user *buf, | |||
79 | } | 111 | } |
80 | 112 | ||
81 | ssize_t tpm_common_write(struct file *file, const char __user *buf, | 113 | ssize_t tpm_common_write(struct file *file, const char __user *buf, |
82 | size_t size, loff_t *off, struct tpm_space *space) | 114 | size_t size, loff_t *off) |
83 | { | 115 | { |
84 | struct file_priv *priv = file->private_data; | 116 | struct file_priv *priv = file->private_data; |
85 | size_t in_size = size; | 117 | int ret = 0; |
86 | ssize_t out_size; | ||
87 | 118 | ||
88 | if (in_size > TPM_BUFSIZE) | 119 | if (size > TPM_BUFSIZE) |
89 | return -E2BIG; | 120 | return -E2BIG; |
90 | 121 | ||
91 | mutex_lock(&priv->buffer_mutex); | 122 | mutex_lock(&priv->buffer_mutex); |
@@ -94,21 +125,20 @@ ssize_t tpm_common_write(struct file *file, const char __user *buf, | |||
94 | * tpm_read or a user_read_timer timeout. This also prevents split | 125 | * tpm_read or a user_read_timer timeout. This also prevents split |
95 | * buffered writes from blocking here. | 126 | * buffered writes from blocking here. |
96 | */ | 127 | */ |
97 | if (priv->data_pending != 0) { | 128 | if (priv->data_pending != 0 || priv->command_enqueued) { |
98 | mutex_unlock(&priv->buffer_mutex); | 129 | ret = -EBUSY; |
99 | return -EBUSY; | 130 | goto out; |
100 | } | 131 | } |
101 | 132 | ||
102 | if (copy_from_user | 133 | if (copy_from_user(priv->data_buffer, buf, size)) { |
103 | (priv->data_buffer, (void __user *) buf, in_size)) { | 134 | ret = -EFAULT; |
104 | mutex_unlock(&priv->buffer_mutex); | 135 | goto out; |
105 | return -EFAULT; | ||
106 | } | 136 | } |
107 | 137 | ||
108 | if (in_size < 6 || | 138 | if (size < 6 || |
109 | in_size < be32_to_cpu(*((__be32 *) (priv->data_buffer + 2)))) { | 139 | size < be32_to_cpu(*((__be32 *)(priv->data_buffer + 2)))) { |
110 | mutex_unlock(&priv->buffer_mutex); | 140 | ret = -EINVAL; |
111 | return -EINVAL; | 141 | goto out; |
112 | } | 142 | } |
113 | 143 | ||
114 | /* atomic tpm command send and result receive. We only hold the ops | 144 | /* atomic tpm command send and result receive. We only hold the ops |
@@ -116,25 +146,50 @@ ssize_t tpm_common_write(struct file *file, const char __user *buf, | |||
116 | * the char dev is held open. | 146 | * the char dev is held open. |
117 | */ | 147 | */ |
118 | if (tpm_try_get_ops(priv->chip)) { | 148 | if (tpm_try_get_ops(priv->chip)) { |
119 | mutex_unlock(&priv->buffer_mutex); | 149 | ret = -EPIPE; |
120 | return -EPIPE; | 150 | goto out; |
121 | } | 151 | } |
122 | out_size = tpm_transmit(priv->chip, space, priv->data_buffer, | ||
123 | sizeof(priv->data_buffer), 0); | ||
124 | 152 | ||
125 | tpm_put_ops(priv->chip); | 153 | /* |
126 | if (out_size < 0) { | 154 | * If in nonblocking mode schedule an async job to send |
155 | * the command return the size. | ||
156 | * In case of error the err code will be returned in | ||
157 | * the subsequent read call. | ||
158 | */ | ||
159 | if (file->f_flags & O_NONBLOCK) { | ||
160 | priv->command_enqueued = true; | ||
161 | queue_work(tpm_dev_wq, &priv->async_work); | ||
127 | mutex_unlock(&priv->buffer_mutex); | 162 | mutex_unlock(&priv->buffer_mutex); |
128 | return out_size; | 163 | return size; |
129 | } | 164 | } |
130 | 165 | ||
131 | priv->data_pending = out_size; | 166 | ret = tpm_transmit(priv->chip, priv->space, priv->data_buffer, |
167 | sizeof(priv->data_buffer), 0); | ||
168 | tpm_put_ops(priv->chip); | ||
169 | |||
170 | if (ret > 0) { | ||
171 | priv->data_pending = ret; | ||
172 | mod_timer(&priv->user_read_timer, jiffies + (120 * HZ)); | ||
173 | ret = size; | ||
174 | } | ||
175 | out: | ||
132 | mutex_unlock(&priv->buffer_mutex); | 176 | mutex_unlock(&priv->buffer_mutex); |
177 | return ret; | ||
178 | } | ||
179 | |||
180 | __poll_t tpm_common_poll(struct file *file, poll_table *wait) | ||
181 | { | ||
182 | struct file_priv *priv = file->private_data; | ||
183 | __poll_t mask = 0; | ||
184 | |||
185 | poll_wait(file, &priv->async_wait, wait); | ||
133 | 186 | ||
134 | /* Set a timeout by which the reader must come claim the result */ | 187 | if (priv->data_pending) |
135 | mod_timer(&priv->user_read_timer, jiffies + (120 * HZ)); | 188 | mask = EPOLLIN | EPOLLRDNORM; |
189 | else | ||
190 | mask = EPOLLOUT | EPOLLWRNORM; | ||
136 | 191 | ||
137 | return in_size; | 192 | return mask; |
138 | } | 193 | } |
139 | 194 | ||
140 | /* | 195 | /* |
@@ -142,8 +197,24 @@ ssize_t tpm_common_write(struct file *file, const char __user *buf, | |||
142 | */ | 197 | */ |
143 | void tpm_common_release(struct file *file, struct file_priv *priv) | 198 | void tpm_common_release(struct file *file, struct file_priv *priv) |
144 | { | 199 | { |
200 | flush_work(&priv->async_work); | ||
145 | del_singleshot_timer_sync(&priv->user_read_timer); | 201 | del_singleshot_timer_sync(&priv->user_read_timer); |
146 | flush_work(&priv->work); | 202 | flush_work(&priv->timeout_work); |
147 | file->private_data = NULL; | 203 | file->private_data = NULL; |
148 | priv->data_pending = 0; | 204 | priv->data_pending = 0; |
149 | } | 205 | } |
206 | |||
207 | int __init tpm_dev_common_init(void) | ||
208 | { | ||
209 | tpm_dev_wq = alloc_workqueue("tpm_dev_wq", WQ_MEM_RECLAIM, 0); | ||
210 | |||
211 | return !tpm_dev_wq ? -ENOMEM : 0; | ||
212 | } | ||
213 | |||
214 | void __exit tpm_dev_common_exit(void) | ||
215 | { | ||
216 | if (tpm_dev_wq) { | ||
217 | destroy_workqueue(tpm_dev_wq); | ||
218 | tpm_dev_wq = NULL; | ||
219 | } | ||
220 | } | ||
diff --git a/drivers/char/tpm/tpm-dev.c b/drivers/char/tpm/tpm-dev.c index ebd74ab5abef..32f9738f1cb2 100644 --- a/drivers/char/tpm/tpm-dev.c +++ b/drivers/char/tpm/tpm-dev.c | |||
@@ -39,7 +39,7 @@ static int tpm_open(struct inode *inode, struct file *file) | |||
39 | if (priv == NULL) | 39 | if (priv == NULL) |
40 | goto out; | 40 | goto out; |
41 | 41 | ||
42 | tpm_common_open(file, chip, priv); | 42 | tpm_common_open(file, chip, priv, NULL); |
43 | 43 | ||
44 | return 0; | 44 | return 0; |
45 | 45 | ||
@@ -48,12 +48,6 @@ static int tpm_open(struct inode *inode, struct file *file) | |||
48 | return -ENOMEM; | 48 | return -ENOMEM; |
49 | } | 49 | } |
50 | 50 | ||
51 | static ssize_t tpm_write(struct file *file, const char __user *buf, | ||
52 | size_t size, loff_t *off) | ||
53 | { | ||
54 | return tpm_common_write(file, buf, size, off, NULL); | ||
55 | } | ||
56 | |||
57 | /* | 51 | /* |
58 | * Called on file close | 52 | * Called on file close |
59 | */ | 53 | */ |
@@ -73,6 +67,7 @@ const struct file_operations tpm_fops = { | |||
73 | .llseek = no_llseek, | 67 | .llseek = no_llseek, |
74 | .open = tpm_open, | 68 | .open = tpm_open, |
75 | .read = tpm_common_read, | 69 | .read = tpm_common_read, |
76 | .write = tpm_write, | 70 | .write = tpm_common_write, |
71 | .poll = tpm_common_poll, | ||
77 | .release = tpm_release, | 72 | .release = tpm_release, |
78 | }; | 73 | }; |
diff --git a/drivers/char/tpm/tpm-dev.h b/drivers/char/tpm/tpm-dev.h index b24cfb4d3ee1..a126b575cb8c 100644 --- a/drivers/char/tpm/tpm-dev.h +++ b/drivers/char/tpm/tpm-dev.h | |||
@@ -2,27 +2,33 @@ | |||
2 | #ifndef _TPM_DEV_H | 2 | #ifndef _TPM_DEV_H |
3 | #define _TPM_DEV_H | 3 | #define _TPM_DEV_H |
4 | 4 | ||
5 | #include <linux/poll.h> | ||
5 | #include "tpm.h" | 6 | #include "tpm.h" |
6 | 7 | ||
7 | struct file_priv { | 8 | struct file_priv { |
8 | struct tpm_chip *chip; | 9 | struct tpm_chip *chip; |
10 | struct tpm_space *space; | ||
9 | 11 | ||
10 | /* Data passed to and from the tpm via the read/write calls */ | 12 | /* Holds the amount of data passed or an error code from async op */ |
11 | size_t data_pending; | 13 | ssize_t data_pending; |
12 | struct mutex buffer_mutex; | 14 | struct mutex buffer_mutex; |
13 | 15 | ||
14 | struct timer_list user_read_timer; /* user needs to claim result */ | 16 | struct timer_list user_read_timer; /* user needs to claim result */ |
15 | struct work_struct work; | 17 | struct work_struct timeout_work; |
18 | struct work_struct async_work; | ||
19 | wait_queue_head_t async_wait; | ||
20 | bool command_enqueued; | ||
16 | 21 | ||
17 | u8 data_buffer[TPM_BUFSIZE]; | 22 | u8 data_buffer[TPM_BUFSIZE]; |
18 | }; | 23 | }; |
19 | 24 | ||
20 | void tpm_common_open(struct file *file, struct tpm_chip *chip, | 25 | void tpm_common_open(struct file *file, struct tpm_chip *chip, |
21 | struct file_priv *priv); | 26 | struct file_priv *priv, struct tpm_space *space); |
22 | ssize_t tpm_common_read(struct file *file, char __user *buf, | 27 | ssize_t tpm_common_read(struct file *file, char __user *buf, |
23 | size_t size, loff_t *off); | 28 | size_t size, loff_t *off); |
24 | ssize_t tpm_common_write(struct file *file, const char __user *buf, | 29 | ssize_t tpm_common_write(struct file *file, const char __user *buf, |
25 | size_t size, loff_t *off, struct tpm_space *space); | 30 | size_t size, loff_t *off); |
26 | void tpm_common_release(struct file *file, struct file_priv *priv); | 31 | __poll_t tpm_common_poll(struct file *file, poll_table *wait); |
27 | 32 | ||
33 | void tpm_common_release(struct file *file, struct file_priv *priv); | ||
28 | #endif | 34 | #endif |
diff --git a/drivers/char/tpm/tpm-interface.c b/drivers/char/tpm/tpm-interface.c index 1a803b0cf980..129f640424b7 100644 --- a/drivers/char/tpm/tpm-interface.c +++ b/drivers/char/tpm/tpm-interface.c | |||
@@ -663,7 +663,8 @@ ssize_t tpm_transmit_cmd(struct tpm_chip *chip, struct tpm_space *space, | |||
663 | return len; | 663 | return len; |
664 | 664 | ||
665 | err = be32_to_cpu(header->return_code); | 665 | err = be32_to_cpu(header->return_code); |
666 | if (err != 0 && desc) | 666 | if (err != 0 && err != TPM_ERR_DISABLED && err != TPM_ERR_DEACTIVATED |
667 | && desc) | ||
667 | dev_err(&chip->dev, "A TPM error (%d) occurred %s\n", err, | 668 | dev_err(&chip->dev, "A TPM error (%d) occurred %s\n", err, |
668 | desc); | 669 | desc); |
669 | if (err) | 670 | if (err) |
@@ -1321,7 +1322,8 @@ int tpm_get_random(struct tpm_chip *chip, u8 *out, size_t max) | |||
1321 | } | 1322 | } |
1322 | 1323 | ||
1323 | rlength = be32_to_cpu(tpm_cmd.header.out.length); | 1324 | rlength = be32_to_cpu(tpm_cmd.header.out.length); |
1324 | if (rlength < offsetof(struct tpm_getrandom_out, rng_data) + | 1325 | if (rlength < TPM_HEADER_SIZE + |
1326 | offsetof(struct tpm_getrandom_out, rng_data) + | ||
1325 | recd) { | 1327 | recd) { |
1326 | total = -EFAULT; | 1328 | total = -EFAULT; |
1327 | break; | 1329 | break; |
@@ -1407,19 +1409,32 @@ static int __init tpm_init(void) | |||
1407 | tpmrm_class = class_create(THIS_MODULE, "tpmrm"); | 1409 | tpmrm_class = class_create(THIS_MODULE, "tpmrm"); |
1408 | if (IS_ERR(tpmrm_class)) { | 1410 | if (IS_ERR(tpmrm_class)) { |
1409 | pr_err("couldn't create tpmrm class\n"); | 1411 | pr_err("couldn't create tpmrm class\n"); |
1410 | class_destroy(tpm_class); | 1412 | rc = PTR_ERR(tpmrm_class); |
1411 | return PTR_ERR(tpmrm_class); | 1413 | goto out_destroy_tpm_class; |
1412 | } | 1414 | } |
1413 | 1415 | ||
1414 | rc = alloc_chrdev_region(&tpm_devt, 0, 2*TPM_NUM_DEVICES, "tpm"); | 1416 | rc = alloc_chrdev_region(&tpm_devt, 0, 2*TPM_NUM_DEVICES, "tpm"); |
1415 | if (rc < 0) { | 1417 | if (rc < 0) { |
1416 | pr_err("tpm: failed to allocate char dev region\n"); | 1418 | pr_err("tpm: failed to allocate char dev region\n"); |
1417 | class_destroy(tpmrm_class); | 1419 | goto out_destroy_tpmrm_class; |
1418 | class_destroy(tpm_class); | 1420 | } |
1419 | return rc; | 1421 | |
1422 | rc = tpm_dev_common_init(); | ||
1423 | if (rc) { | ||
1424 | pr_err("tpm: failed to allocate char dev region\n"); | ||
1425 | goto out_unreg_chrdev; | ||
1420 | } | 1426 | } |
1421 | 1427 | ||
1422 | return 0; | 1428 | return 0; |
1429 | |||
1430 | out_unreg_chrdev: | ||
1431 | unregister_chrdev_region(tpm_devt, 2 * TPM_NUM_DEVICES); | ||
1432 | out_destroy_tpmrm_class: | ||
1433 | class_destroy(tpmrm_class); | ||
1434 | out_destroy_tpm_class: | ||
1435 | class_destroy(tpm_class); | ||
1436 | |||
1437 | return rc; | ||
1423 | } | 1438 | } |
1424 | 1439 | ||
1425 | static void __exit tpm_exit(void) | 1440 | static void __exit tpm_exit(void) |
@@ -1428,6 +1443,7 @@ static void __exit tpm_exit(void) | |||
1428 | class_destroy(tpm_class); | 1443 | class_destroy(tpm_class); |
1429 | class_destroy(tpmrm_class); | 1444 | class_destroy(tpmrm_class); |
1430 | unregister_chrdev_region(tpm_devt, 2*TPM_NUM_DEVICES); | 1445 | unregister_chrdev_region(tpm_devt, 2*TPM_NUM_DEVICES); |
1446 | tpm_dev_common_exit(); | ||
1431 | } | 1447 | } |
1432 | 1448 | ||
1433 | subsys_initcall(tpm_init); | 1449 | subsys_initcall(tpm_init); |
diff --git a/drivers/char/tpm/tpm.h b/drivers/char/tpm/tpm.h index f3501d05264f..f20dc8ece348 100644 --- a/drivers/char/tpm/tpm.h +++ b/drivers/char/tpm/tpm.h | |||
@@ -604,4 +604,6 @@ int tpm2_commit_space(struct tpm_chip *chip, struct tpm_space *space, | |||
604 | 604 | ||
605 | int tpm_bios_log_setup(struct tpm_chip *chip); | 605 | int tpm_bios_log_setup(struct tpm_chip *chip); |
606 | void tpm_bios_log_teardown(struct tpm_chip *chip); | 606 | void tpm_bios_log_teardown(struct tpm_chip *chip); |
607 | int tpm_dev_common_init(void); | ||
608 | void tpm_dev_common_exit(void); | ||
607 | #endif | 609 | #endif |
diff --git a/drivers/char/tpm/tpm2-cmd.c b/drivers/char/tpm/tpm2-cmd.c index c31b490bd41d..3acf4fd4e5a5 100644 --- a/drivers/char/tpm/tpm2-cmd.c +++ b/drivers/char/tpm/tpm2-cmd.c | |||
@@ -329,7 +329,9 @@ int tpm2_get_random(struct tpm_chip *chip, u8 *dest, size_t max) | |||
329 | &buf.data[TPM_HEADER_SIZE]; | 329 | &buf.data[TPM_HEADER_SIZE]; |
330 | recd = min_t(u32, be16_to_cpu(out->size), num_bytes); | 330 | recd = min_t(u32, be16_to_cpu(out->size), num_bytes); |
331 | if (tpm_buf_length(&buf) < | 331 | if (tpm_buf_length(&buf) < |
332 | offsetof(struct tpm2_get_random_out, buffer) + recd) { | 332 | TPM_HEADER_SIZE + |
333 | offsetof(struct tpm2_get_random_out, buffer) + | ||
334 | recd) { | ||
333 | err = -EFAULT; | 335 | err = -EFAULT; |
334 | goto out; | 336 | goto out; |
335 | } | 337 | } |
diff --git a/drivers/char/tpm/tpmrm-dev.c b/drivers/char/tpm/tpmrm-dev.c index 1a0e97a5da5a..0c751a79bbed 100644 --- a/drivers/char/tpm/tpmrm-dev.c +++ b/drivers/char/tpm/tpmrm-dev.c | |||
@@ -28,7 +28,7 @@ static int tpmrm_open(struct inode *inode, struct file *file) | |||
28 | return -ENOMEM; | 28 | return -ENOMEM; |
29 | } | 29 | } |
30 | 30 | ||
31 | tpm_common_open(file, chip, &priv->priv); | 31 | tpm_common_open(file, chip, &priv->priv, &priv->space); |
32 | 32 | ||
33 | return 0; | 33 | return 0; |
34 | } | 34 | } |
@@ -45,21 +45,12 @@ static int tpmrm_release(struct inode *inode, struct file *file) | |||
45 | return 0; | 45 | return 0; |
46 | } | 46 | } |
47 | 47 | ||
48 | static ssize_t tpmrm_write(struct file *file, const char __user *buf, | ||
49 | size_t size, loff_t *off) | ||
50 | { | ||
51 | struct file_priv *fpriv = file->private_data; | ||
52 | struct tpmrm_priv *priv = container_of(fpriv, struct tpmrm_priv, priv); | ||
53 | |||
54 | return tpm_common_write(file, buf, size, off, &priv->space); | ||
55 | } | ||
56 | |||
57 | const struct file_operations tpmrm_fops = { | 48 | const struct file_operations tpmrm_fops = { |
58 | .owner = THIS_MODULE, | 49 | .owner = THIS_MODULE, |
59 | .llseek = no_llseek, | 50 | .llseek = no_llseek, |
60 | .open = tpmrm_open, | 51 | .open = tpmrm_open, |
61 | .read = tpm_common_read, | 52 | .read = tpm_common_read, |
62 | .write = tpmrm_write, | 53 | .write = tpm_common_write, |
54 | .poll = tpm_common_poll, | ||
63 | .release = tpmrm_release, | 55 | .release = tpmrm_release, |
64 | }; | 56 | }; |
65 | |||
diff --git a/drivers/char/tpm/xen-tpmfront.c b/drivers/char/tpm/xen-tpmfront.c index 911475d36800..b150f87f38f5 100644 --- a/drivers/char/tpm/xen-tpmfront.c +++ b/drivers/char/tpm/xen-tpmfront.c | |||
@@ -264,7 +264,7 @@ static int setup_ring(struct xenbus_device *dev, struct tpm_private *priv) | |||
264 | return -ENOMEM; | 264 | return -ENOMEM; |
265 | } | 265 | } |
266 | 266 | ||
267 | rv = xenbus_grant_ring(dev, &priv->shr, 1, &gref); | 267 | rv = xenbus_grant_ring(dev, priv->shr, 1, &gref); |
268 | if (rv < 0) | 268 | if (rv < 0) |
269 | return rv; | 269 | return rv; |
270 | 270 | ||