diff options
| author | James Morris <james.morris@microsoft.com> | 2018-06-04 12:08:21 -0400 |
|---|---|---|
| committer | James Morris <james.morris@microsoft.com> | 2018-06-04 12:08:21 -0400 |
| commit | 2d06236ab3276000665ef55eccc111c3bbf90589 (patch) | |
| tree | e06f62b3998eb64b570b291ec07f42d56e6be558 | |
| parent | 82e5b03236e0eada87a59f4636c986dc319c6e78 (diff) | |
| parent | 3ab2011ea368ec3433ad49e1b9e1c7b70d2e65df (diff) | |
Merge tag 'tpmdd-next-20180602' of git://git.infradead.org/users/jjs/linux-tpmdd into next-tpm
tpmdd fixes for Linux 4.17 (just missed 4.17)
| -rw-r--r-- | drivers/char/tpm/tpm-dev-common.c | 40 | ||||
| -rw-r--r-- | drivers/char/tpm/tpm-dev.h | 2 |
2 files changed, 19 insertions, 23 deletions
diff --git a/drivers/char/tpm/tpm-dev-common.c b/drivers/char/tpm/tpm-dev-common.c index 230b99288024..e4a04b2d3c32 100644 --- a/drivers/char/tpm/tpm-dev-common.c +++ b/drivers/char/tpm/tpm-dev-common.c | |||
| @@ -37,7 +37,7 @@ static void timeout_work(struct work_struct *work) | |||
| 37 | struct file_priv *priv = container_of(work, struct file_priv, work); | 37 | struct file_priv *priv = container_of(work, struct file_priv, work); |
| 38 | 38 | ||
| 39 | mutex_lock(&priv->buffer_mutex); | 39 | mutex_lock(&priv->buffer_mutex); |
| 40 | atomic_set(&priv->data_pending, 0); | 40 | priv->data_pending = 0; |
| 41 | memset(priv->data_buffer, 0, sizeof(priv->data_buffer)); | 41 | memset(priv->data_buffer, 0, sizeof(priv->data_buffer)); |
| 42 | mutex_unlock(&priv->buffer_mutex); | 42 | mutex_unlock(&priv->buffer_mutex); |
| 43 | } | 43 | } |
| @@ -46,7 +46,6 @@ void tpm_common_open(struct file *file, struct tpm_chip *chip, | |||
| 46 | struct file_priv *priv) | 46 | struct file_priv *priv) |
| 47 | { | 47 | { |
| 48 | priv->chip = chip; | 48 | priv->chip = chip; |
| 49 | atomic_set(&priv->data_pending, 0); | ||
| 50 | mutex_init(&priv->buffer_mutex); | 49 | mutex_init(&priv->buffer_mutex); |
| 51 | timer_setup(&priv->user_read_timer, user_reader_timeout, 0); | 50 | timer_setup(&priv->user_read_timer, user_reader_timeout, 0); |
| 52 | INIT_WORK(&priv->work, timeout_work); | 51 | INIT_WORK(&priv->work, timeout_work); |
| @@ -58,29 +57,24 @@ ssize_t tpm_common_read(struct file *file, char __user *buf, | |||
| 58 | size_t size, loff_t *off) | 57 | size_t size, loff_t *off) |
| 59 | { | 58 | { |
| 60 | struct file_priv *priv = file->private_data; | 59 | struct file_priv *priv = file->private_data; |
| 61 | ssize_t ret_size; | 60 | ssize_t ret_size = 0; |
| 62 | ssize_t orig_ret_size; | ||
| 63 | int rc; | 61 | int rc; |
| 64 | 62 | ||
| 65 | del_singleshot_timer_sync(&priv->user_read_timer); | 63 | del_singleshot_timer_sync(&priv->user_read_timer); |
| 66 | flush_work(&priv->work); | 64 | flush_work(&priv->work); |
| 67 | ret_size = atomic_read(&priv->data_pending); | 65 | mutex_lock(&priv->buffer_mutex); |
| 68 | if (ret_size > 0) { /* relay data */ | ||
| 69 | orig_ret_size = ret_size; | ||
| 70 | if (size < ret_size) | ||
| 71 | ret_size = size; | ||
| 72 | 66 | ||
| 73 | mutex_lock(&priv->buffer_mutex); | 67 | if (priv->data_pending) { |
| 68 | ret_size = min_t(ssize_t, size, priv->data_pending); | ||
| 74 | rc = copy_to_user(buf, priv->data_buffer, ret_size); | 69 | rc = copy_to_user(buf, priv->data_buffer, ret_size); |
| 75 | memset(priv->data_buffer, 0, orig_ret_size); | 70 | memset(priv->data_buffer, 0, priv->data_pending); |
| 76 | if (rc) | 71 | if (rc) |
| 77 | ret_size = -EFAULT; | 72 | ret_size = -EFAULT; |
| 78 | 73 | ||
| 79 | mutex_unlock(&priv->buffer_mutex); | 74 | priv->data_pending = 0; |
| 80 | } | 75 | } |
| 81 | 76 | ||
| 82 | atomic_set(&priv->data_pending, 0); | 77 | mutex_unlock(&priv->buffer_mutex); |
| 83 | |||
| 84 | return ret_size; | 78 | return ret_size; |
| 85 | } | 79 | } |
| 86 | 80 | ||
| @@ -91,17 +85,19 @@ ssize_t tpm_common_write(struct file *file, const char __user *buf, | |||
| 91 | size_t in_size = size; | 85 | size_t in_size = size; |
| 92 | ssize_t out_size; | 86 | ssize_t out_size; |
| 93 | 87 | ||
| 88 | if (in_size > TPM_BUFSIZE) | ||
| 89 | return -E2BIG; | ||
| 90 | |||
| 91 | mutex_lock(&priv->buffer_mutex); | ||
| 92 | |||
| 94 | /* Cannot perform a write until the read has cleared either via | 93 | /* Cannot perform a write until the read has cleared either via |
| 95 | * tpm_read or a user_read_timer timeout. This also prevents split | 94 | * tpm_read or a user_read_timer timeout. This also prevents split |
| 96 | * buffered writes from blocking here. | 95 | * buffered writes from blocking here. |
| 97 | */ | 96 | */ |
| 98 | if (atomic_read(&priv->data_pending) != 0) | 97 | if (priv->data_pending != 0) { |
| 98 | mutex_unlock(&priv->buffer_mutex); | ||
| 99 | return -EBUSY; | 99 | return -EBUSY; |
| 100 | 100 | } | |
| 101 | if (in_size > TPM_BUFSIZE) | ||
| 102 | return -E2BIG; | ||
| 103 | |||
| 104 | mutex_lock(&priv->buffer_mutex); | ||
| 105 | 101 | ||
| 106 | if (copy_from_user | 102 | if (copy_from_user |
| 107 | (priv->data_buffer, (void __user *) buf, in_size)) { | 103 | (priv->data_buffer, (void __user *) buf, in_size)) { |
| @@ -132,7 +128,7 @@ ssize_t tpm_common_write(struct file *file, const char __user *buf, | |||
| 132 | return out_size; | 128 | return out_size; |
| 133 | } | 129 | } |
| 134 | 130 | ||
| 135 | atomic_set(&priv->data_pending, out_size); | 131 | priv->data_pending = out_size; |
| 136 | mutex_unlock(&priv->buffer_mutex); | 132 | mutex_unlock(&priv->buffer_mutex); |
| 137 | 133 | ||
| 138 | /* Set a timeout by which the reader must come claim the result */ | 134 | /* Set a timeout by which the reader must come claim the result */ |
| @@ -149,5 +145,5 @@ void tpm_common_release(struct file *file, struct file_priv *priv) | |||
| 149 | del_singleshot_timer_sync(&priv->user_read_timer); | 145 | del_singleshot_timer_sync(&priv->user_read_timer); |
| 150 | flush_work(&priv->work); | 146 | flush_work(&priv->work); |
| 151 | file->private_data = NULL; | 147 | file->private_data = NULL; |
| 152 | atomic_set(&priv->data_pending, 0); | 148 | priv->data_pending = 0; |
| 153 | } | 149 | } |
diff --git a/drivers/char/tpm/tpm-dev.h b/drivers/char/tpm/tpm-dev.h index ba3b6f9dacf7..b24cfb4d3ee1 100644 --- a/drivers/char/tpm/tpm-dev.h +++ b/drivers/char/tpm/tpm-dev.h | |||
| @@ -8,7 +8,7 @@ struct file_priv { | |||
| 8 | struct tpm_chip *chip; | 8 | struct tpm_chip *chip; |
| 9 | 9 | ||
| 10 | /* Data passed to and from the tpm via the read/write calls */ | 10 | /* Data passed to and from the tpm via the read/write calls */ |
| 11 | atomic_t data_pending; | 11 | size_t data_pending; |
| 12 | struct mutex buffer_mutex; | 12 | struct mutex buffer_mutex; |
| 13 | 13 | ||
| 14 | struct timer_list user_read_timer; /* user needs to claim result */ | 14 | struct timer_list user_read_timer; /* user needs to claim result */ |
