On Tue, 2020-07-07 at 16:56 -0700, Kees Cook wrote:
@@ -951,21 +955,32 @@ int kernel_read_file(struct file *file, void **buf, loff_t *size, ret = -EINVAL; goto out; } - if (i_size > SIZE_MAX || (max_size > 0 && i_size > max_size)) {
+ /* Default read to end of file */ + read_end = i_size;
+ /* Allow reading partial portion of file */ + if ((id == READING_FIRMWARE_PARTIAL_READ) && + (i_size > (pos + max_size))) + read_end = pos + max_size;
There's no need to involve "id" here. There are other signals about what's happening (i.e. pos != 0, max_size != i_size, etc).
Both the pre and post security kernel_read_file hooks are called here, but there isn't enough information being passed to the LSM/IMA to be able to different which hook is applicable. One method of providing that additional information is by enumeration. The other option would be to pass some additional information.
For example, on the post kernel_read_file hook, the file is read once into memory. IMA calculates the firmware file hash based on the buffer contents. On the pre kernel_read_file hook, IMA would need to read the entire file, calculating the file hash. Both methods of calculating the file hash work, but the post hook is more efficient.
Mimi