Skip to content

Commit b8d7b75

Browse files
author
James Morris
committed
Merge tag 'tpmdd-next-20181005' of git://git.infradead.org/users/jjs/linux-tpmdd into next-tpm
tpmdd updates for Linux 4.20 From Jarkko: These are the updates to v4.20. The only new feature is non-blocking operation for /dev/tpm0.
2 parents 2ecefa0 + e487a0f commit b8d7b75

File tree

9 files changed

+157
-74
lines changed

9 files changed

+157
-74
lines changed

drivers/char/tpm/Kconfig

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@
55
menuconfig TCG_TPM
66
tristate "TPM Hardware Support"
77
depends on HAS_IOMEM
8-
select SECURITYFS
8+
imply SECURITYFS
99
select CRYPTO
1010
select CRYPTO_HASH_INFO
1111
---help---

drivers/char/tpm/tpm-dev-common.c

Lines changed: 109 additions & 38 deletions
Original file line numberDiff line numberDiff line change
@@ -17,39 +17,69 @@
1717
* License.
1818
*
1919
*/
20+
#include <linux/poll.h>
2021
#include <linux/slab.h>
2122
#include <linux/uaccess.h>
23+
#include <linux/workqueue.h>
2224
#include "tpm.h"
2325
#include "tpm-dev.h"
2426

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+
2550
static void user_reader_timeout(struct timer_list *t)
2651
{
2752
struct file_priv *priv = from_timer(priv, t, user_read_timer);
2853

2954
pr_warn("TPM user space timeout is deprecated (pid=%d)\n",
3055
task_tgid_nr(current));
3156

32-
schedule_work(&priv->work);
57+
schedule_work(&priv->timeout_work);
3358
}
3459

35-
static void timeout_work(struct work_struct *work)
60+
static void tpm_timeout_work(struct work_struct *work)
3661
{
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);
3864

3965
mutex_lock(&priv->buffer_mutex);
4066
priv->data_pending = 0;
4167
memset(priv->data_buffer, 0, sizeof(priv->data_buffer));
4268
mutex_unlock(&priv->buffer_mutex);
69+
wake_up_interruptible(&priv->async_wait);
4370
}
4471

4572
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)
4774
{
4875
priv->chip = chip;
76+
priv->space = space;
77+
4978
mutex_init(&priv->buffer_mutex);
5079
timer_setup(&priv->user_read_timer, user_reader_timeout, 0);
51-
INIT_WORK(&priv->work, timeout_work);
52-
80+
INIT_WORK(&priv->timeout_work, tpm_timeout_work);
81+
INIT_WORK(&priv->async_work, tpm_async_work);
82+
init_waitqueue_head(&priv->async_wait);
5383
file->private_data = priv;
5484
}
5585

@@ -61,15 +91,17 @@ ssize_t tpm_common_read(struct file *file, char __user *buf,
6191
int rc;
6292

6393
del_singleshot_timer_sync(&priv->user_read_timer);
64-
flush_work(&priv->work);
94+
flush_work(&priv->timeout_work);
6595
mutex_lock(&priv->buffer_mutex);
6696

6797
if (priv->data_pending) {
6898
ret_size = min_t(ssize_t, size, priv->data_pending);
69-
rc = copy_to_user(buf, priv->data_buffer, ret_size);
70-
memset(priv->data_buffer, 0, priv->data_pending);
71-
if (rc)
72-
ret_size = -EFAULT;
99+
if (ret_size > 0) {
100+
rc = copy_to_user(buf, priv->data_buffer, ret_size);
101+
memset(priv->data_buffer, 0, priv->data_pending);
102+
if (rc)
103+
ret_size = -EFAULT;
104+
}
73105

74106
priv->data_pending = 0;
75107
}
@@ -79,13 +111,12 @@ ssize_t tpm_common_read(struct file *file, char __user *buf,
79111
}
80112

81113
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)
83115
{
84116
struct file_priv *priv = file->private_data;
85-
size_t in_size = size;
86-
ssize_t out_size;
117+
int ret = 0;
87118

88-
if (in_size > TPM_BUFSIZE)
119+
if (size > TPM_BUFSIZE)
89120
return -E2BIG;
90121

91122
mutex_lock(&priv->buffer_mutex);
@@ -94,56 +125,96 @@ ssize_t tpm_common_write(struct file *file, const char __user *buf,
94125
* tpm_read or a user_read_timer timeout. This also prevents split
95126
* buffered writes from blocking here.
96127
*/
97-
if (priv->data_pending != 0) {
98-
mutex_unlock(&priv->buffer_mutex);
99-
return -EBUSY;
128+
if (priv->data_pending != 0 || priv->command_enqueued) {
129+
ret = -EBUSY;
130+
goto out;
100131
}
101132

102-
if (copy_from_user
103-
(priv->data_buffer, (void __user *) buf, in_size)) {
104-
mutex_unlock(&priv->buffer_mutex);
105-
return -EFAULT;
133+
if (copy_from_user(priv->data_buffer, buf, size)) {
134+
ret = -EFAULT;
135+
goto out;
106136
}
107137

108-
if (in_size < 6 ||
109-
in_size < be32_to_cpu(*((__be32 *) (priv->data_buffer + 2)))) {
110-
mutex_unlock(&priv->buffer_mutex);
111-
return -EINVAL;
138+
if (size < 6 ||
139+
size < be32_to_cpu(*((__be32 *)(priv->data_buffer + 2)))) {
140+
ret = -EINVAL;
141+
goto out;
112142
}
113143

114144
/* atomic tpm command send and result receive. We only hold the ops
115145
* lock during this period so that the tpm can be unregistered even if
116146
* the char dev is held open.
117147
*/
118148
if (tpm_try_get_ops(priv->chip)) {
119-
mutex_unlock(&priv->buffer_mutex);
120-
return -EPIPE;
149+
ret = -EPIPE;
150+
goto out;
121151
}
122-
out_size = tpm_transmit(priv->chip, space, priv->data_buffer,
123-
sizeof(priv->data_buffer), 0);
124152

125-
tpm_put_ops(priv->chip);
126-
if (out_size < 0) {
153+
/*
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);
127162
mutex_unlock(&priv->buffer_mutex);
128-
return out_size;
163+
return size;
129164
}
130165

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:
132176
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);
133186

134-
/* Set a timeout by which the reader must come claim the result */
135-
mod_timer(&priv->user_read_timer, jiffies + (120 * HZ));
187+
if (priv->data_pending)
188+
mask = EPOLLIN | EPOLLRDNORM;
189+
else
190+
mask = EPOLLOUT | EPOLLWRNORM;
136191

137-
return in_size;
192+
return mask;
138193
}
139194

140195
/*
141196
* Called on file close
142197
*/
143198
void tpm_common_release(struct file *file, struct file_priv *priv)
144199
{
200+
flush_work(&priv->async_work);
145201
del_singleshot_timer_sync(&priv->user_read_timer);
146-
flush_work(&priv->work);
202+
flush_work(&priv->timeout_work);
147203
file->private_data = NULL;
148204
priv->data_pending = 0;
149205
}
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+
}

drivers/char/tpm/tpm-dev.c

Lines changed: 3 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -39,7 +39,7 @@ static int tpm_open(struct inode *inode, struct file *file)
3939
if (priv == NULL)
4040
goto out;
4141

42-
tpm_common_open(file, chip, priv);
42+
tpm_common_open(file, chip, priv, NULL);
4343

4444
return 0;
4545

@@ -48,12 +48,6 @@ static int tpm_open(struct inode *inode, struct file *file)
4848
return -ENOMEM;
4949
}
5050

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-
5751
/*
5852
* Called on file close
5953
*/
@@ -73,6 +67,7 @@ const struct file_operations tpm_fops = {
7367
.llseek = no_llseek,
7468
.open = tpm_open,
7569
.read = tpm_common_read,
76-
.write = tpm_write,
70+
.write = tpm_common_write,
71+
.poll = tpm_common_poll,
7772
.release = tpm_release,
7873
};

drivers/char/tpm/tpm-dev.h

Lines changed: 12 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -2,27 +2,33 @@
22
#ifndef _TPM_DEV_H
33
#define _TPM_DEV_H
44

5+
#include <linux/poll.h>
56
#include "tpm.h"
67

78
struct file_priv {
89
struct tpm_chip *chip;
10+
struct tpm_space *space;
911

10-
/* Data passed to and from the tpm via the read/write calls */
11-
size_t data_pending;
12+
/* Holds the amount of data passed or an error code from async op */
13+
ssize_t data_pending;
1214
struct mutex buffer_mutex;
1315

1416
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;
1621

1722
u8 data_buffer[TPM_BUFSIZE];
1823
};
1924

2025
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);
2227
ssize_t tpm_common_read(struct file *file, char __user *buf,
2328
size_t size, loff_t *off);
2429
ssize_t tpm_common_write(struct file *file, const char __user *buf,
25-
size_t size, loff_t *off, struct tpm_space *space);
26-
void tpm_common_release(struct file *file, struct file_priv *priv);
30+
size_t size, loff_t *off);
31+
__poll_t tpm_common_poll(struct file *file, poll_table *wait);
2732

33+
void tpm_common_release(struct file *file, struct file_priv *priv);
2834
#endif

drivers/char/tpm/tpm-interface.c

Lines changed: 23 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -663,7 +663,8 @@ ssize_t tpm_transmit_cmd(struct tpm_chip *chip, struct tpm_space *space,
663663
return len;
664664

665665
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)
667668
dev_err(&chip->dev, "A TPM error (%d) occurred %s\n", err,
668669
desc);
669670
if (err)
@@ -1321,7 +1322,8 @@ int tpm_get_random(struct tpm_chip *chip, u8 *out, size_t max)
13211322
}
13221323

13231324
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) +
13251327
recd) {
13261328
total = -EFAULT;
13271329
break;
@@ -1407,19 +1409,32 @@ static int __init tpm_init(void)
14071409
tpmrm_class = class_create(THIS_MODULE, "tpmrm");
14081410
if (IS_ERR(tpmrm_class)) {
14091411
pr_err("couldn't create tpmrm class\n");
1410-
class_destroy(tpm_class);
1411-
return PTR_ERR(tpmrm_class);
1412+
rc = PTR_ERR(tpmrm_class);
1413+
goto out_destroy_tpm_class;
14121414
}
14131415

14141416
rc = alloc_chrdev_region(&tpm_devt, 0, 2*TPM_NUM_DEVICES, "tpm");
14151417
if (rc < 0) {
14161418
pr_err("tpm: failed to allocate char dev region\n");
1417-
class_destroy(tpmrm_class);
1418-
class_destroy(tpm_class);
1419-
return rc;
1419+
goto out_destroy_tpmrm_class;
1420+
}
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;
14201426
}
14211427

14221428
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;
14231438
}
14241439

14251440
static void __exit tpm_exit(void)
@@ -1428,6 +1443,7 @@ static void __exit tpm_exit(void)
14281443
class_destroy(tpm_class);
14291444
class_destroy(tpmrm_class);
14301445
unregister_chrdev_region(tpm_devt, 2*TPM_NUM_DEVICES);
1446+
tpm_dev_common_exit();
14311447
}
14321448

14331449
subsys_initcall(tpm_init);

drivers/char/tpm/tpm.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -604,4 +604,6 @@ int tpm2_commit_space(struct tpm_chip *chip, struct tpm_space *space,
604604

605605
int tpm_bios_log_setup(struct tpm_chip *chip);
606606
void tpm_bios_log_teardown(struct tpm_chip *chip);
607+
int tpm_dev_common_init(void);
608+
void tpm_dev_common_exit(void);
607609
#endif

drivers/char/tpm/tpm2-cmd.c

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -329,7 +329,9 @@ int tpm2_get_random(struct tpm_chip *chip, u8 *dest, size_t max)
329329
&buf.data[TPM_HEADER_SIZE];
330330
recd = min_t(u32, be16_to_cpu(out->size), num_bytes);
331331
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) {
333335
err = -EFAULT;
334336
goto out;
335337
}

0 commit comments

Comments
 (0)