mirror of
https://git.kernel.org/pub/scm/linux/kernel/git/stable/linux.git
synced 2024-09-06 19:07:52 +00:00
tpm: fix double write race and tpm_release free issue
Moved the atomic_set of the data_pending variable until after the tpm_read has completed processing. The existing code had a window of time where a second write to the driver could clobber the tpm command buffer. Also fixed an issue where if close was called on the tpm device before a read completed, the tpm command buffer would be returned to the OS, which could contain sensitive information. Signed-off-by: Kent Yoder <key@linux.vnet.ibm.com>
This commit is contained in:
parent
578b016fdc
commit
dd7da132f7
1 changed files with 3 additions and 2 deletions
|
@ -1171,7 +1171,7 @@ int tpm_release(struct inode *inode, struct file *file)
|
||||||
flush_work_sync(&chip->work);
|
flush_work_sync(&chip->work);
|
||||||
file->private_data = NULL;
|
file->private_data = NULL;
|
||||||
atomic_set(&chip->data_pending, 0);
|
atomic_set(&chip->data_pending, 0);
|
||||||
kfree(chip->data_buffer);
|
kzfree(chip->data_buffer);
|
||||||
clear_bit(0, &chip->is_open);
|
clear_bit(0, &chip->is_open);
|
||||||
put_device(chip->dev);
|
put_device(chip->dev);
|
||||||
return 0;
|
return 0;
|
||||||
|
@ -1223,7 +1223,6 @@ ssize_t tpm_read(struct file *file, char __user *buf,
|
||||||
del_singleshot_timer_sync(&chip->user_read_timer);
|
del_singleshot_timer_sync(&chip->user_read_timer);
|
||||||
flush_work_sync(&chip->work);
|
flush_work_sync(&chip->work);
|
||||||
ret_size = atomic_read(&chip->data_pending);
|
ret_size = atomic_read(&chip->data_pending);
|
||||||
atomic_set(&chip->data_pending, 0);
|
|
||||||
if (ret_size > 0) { /* relay data */
|
if (ret_size > 0) { /* relay data */
|
||||||
ssize_t orig_ret_size = ret_size;
|
ssize_t orig_ret_size = ret_size;
|
||||||
if (size < ret_size)
|
if (size < ret_size)
|
||||||
|
@ -1238,6 +1237,8 @@ ssize_t tpm_read(struct file *file, char __user *buf,
|
||||||
mutex_unlock(&chip->buffer_mutex);
|
mutex_unlock(&chip->buffer_mutex);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
atomic_set(&chip->data_pending, 0);
|
||||||
|
|
||||||
return ret_size;
|
return ret_size;
|
||||||
}
|
}
|
||||||
EXPORT_SYMBOL_GPL(tpm_read);
|
EXPORT_SYMBOL_GPL(tpm_read);
|
||||||
|
|
Loading…
Reference in a new issue