Message ID | 20200508002739.19360-2-scott.branden@broadcom.com (mailing list archive) |
---|---|
State | New, archived |
Headers | show |
Series | firmware: add partial read support in request_firmware_into_buf | expand |
On Thu, May 07, 2020 at 05:27:33PM -0700, Scott Branden wrote: > diff --git a/fs/exec.c b/fs/exec.c > index 06b4c550af5d..cfab212fab9d 100644 > --- a/fs/exec.c > +++ b/fs/exec.c > @@ -896,10 +896,14 @@ struct file *open_exec(const char *name) > } > EXPORT_SYMBOL(open_exec); > > -int kernel_read_file(struct file *file, void **buf, loff_t *size, > - loff_t max_size, enum kernel_read_file_id id) > -{ > - loff_t i_size, pos; > +int kernel_pread_file(struct file *file, void **buf, loff_t *size, > + loff_t pos, loff_t max_size, unsigned int flags, You use int flags, but.. these are mutually exclusive operations, and so flags is a misnomer. Just use an enum instead of a define, that way we can use kdoc for documentation. > +EXPORT_SYMBOL_GPL(kernel_pread_file); > +EXPORT_SYMBOL_GPL(kernel_pread_file_from_path); > +EXPORT_SYMBOL_GPL(kernel_pread_file_from_path_initns); > +EXPORT_SYMBOL_GPL(kernel_pread_file_from_fd); If no one is using these don't export them. I think you only use one of these. In fact just remove the code from the ones which are not used. Luis
Hi Luis, A few comments inline before I cleanup. On 2020-05-12 5:27 p.m., Luis Chamberlain wrote: > On Thu, May 07, 2020 at 05:27:33PM -0700, Scott Branden wrote: >> diff --git a/fs/exec.c b/fs/exec.c >> index 06b4c550af5d..cfab212fab9d 100644 >> --- a/fs/exec.c >> +++ b/fs/exec.c >> @@ -896,10 +896,14 @@ struct file *open_exec(const char *name) >> } >> EXPORT_SYMBOL(open_exec); >> >> -int kernel_read_file(struct file *file, void **buf, loff_t *size, >> - loff_t max_size, enum kernel_read_file_id id) >> -{ >> - loff_t i_size, pos; >> +int kernel_pread_file(struct file *file, void **buf, loff_t *size, >> + loff_t pos, loff_t max_size, unsigned int flags, > You use int flags, but.. these are mutually exclusive operations, and > so flags is a misnomer. Just use an enum instead of a define, that way > we can use kdoc for documentation. OK, flags could be used to expand with additional flag options in the future (without change to function prototype, but will change to enum if that is what is desired. >> +EXPORT_SYMBOL_GPL(kernel_pread_file); >> +EXPORT_SYMBOL_GPL(kernel_pread_file_from_path); >> +EXPORT_SYMBOL_GPL(kernel_pread_file_from_path_initns); >> +EXPORT_SYMBOL_GPL(kernel_pread_file_from_fd); > If no one is using these don't export them. I think you only use one of > these. In fact just remove the code from the ones which are not used. I do not use them but added them to provide consistent api with kernel_read_file_* functions. That way someone can take advantage of the _from_path and from_fd variants in the future if desired. But if you want them removed it is simple to drop the EXPORT_SYMBOL_GPL and then add that back when first driver that calls them needs them in the future. Note: Existing kernel_read_file_from_path_initns is not used in the kernel. Should we delete that as well? > > Luis Thanks, Scott
On Tue, May 12, 2020 at 11:23:27PM -0700, Scott Branden wrote: > Hi Luis, > > A few comments inline before I cleanup. > > On 2020-05-12 5:27 p.m., Luis Chamberlain wrote: > > On Thu, May 07, 2020 at 05:27:33PM -0700, Scott Branden wrote: > > > diff --git a/fs/exec.c b/fs/exec.c > > > index 06b4c550af5d..cfab212fab9d 100644 > > > --- a/fs/exec.c > > > +++ b/fs/exec.c > > > @@ -896,10 +896,14 @@ struct file *open_exec(const char *name) > > > } > > > EXPORT_SYMBOL(open_exec); > > > -int kernel_read_file(struct file *file, void **buf, loff_t *size, > > > - loff_t max_size, enum kernel_read_file_id id) > > > -{ > > > - loff_t i_size, pos; > > > +int kernel_pread_file(struct file *file, void **buf, loff_t *size, > > > + loff_t pos, loff_t max_size, unsigned int flags, > > You use int flags, but.. these are mutually exclusive operations, and > > so flags is a misnomer. Just use an enum instead of a define, that way > > we can use kdoc for documentation. > OK, flags could be used to expand with additional flag options in the future > (without change to function prototype, but will change to enum if that is > what is desired. > > > +EXPORT_SYMBOL_GPL(kernel_pread_file); > > > +EXPORT_SYMBOL_GPL(kernel_pread_file_from_path); > > > +EXPORT_SYMBOL_GPL(kernel_pread_file_from_path_initns); > > > +EXPORT_SYMBOL_GPL(kernel_pread_file_from_fd); > > If no one is using these don't export them. I think you only use one of > > these. In fact just remove the code from the ones which are not used. > I do not use them but added them to provide consistent api with > kernel_read_file_* functions. That way someone can take advantage of the > _from_path and from_fd variants in the future if desired. But if you want > them removed it is simple to drop the EXPORT_SYMBOL_GPL and then add that > back when first driver that calls them needs them in the future. We do not export symbols when there are no in-kernel users. > Note: Existing kernel_read_file_from_path_initns is not used in the kernel. > Should we delete that as well? Probably, yes. thanks, greg k-h
On 2020-05-12 11:51 p.m., Greg Kroah-Hartman wrote: > On Tue, May 12, 2020 at 11:23:27PM -0700, Scott Branden wrote: >> Hi Luis, >> >> A few comments inline before I cleanup. >> >> We do not export symbols when there are no in-kernel users. >> >> Note: Existing kernel_read_file_from_path_initns is not used in the kernel. >> Should we delete that as well? > Probably, yes. I found drivers/base/firmware_loader calls kernel_read_file_from_path_initns so EXPORT_SYMBOL_GPL can stay there. > thanks, > > greg k-h
[Cc'ing linux-security-module, linux-integrity] On Thu, 2020-05-07 at 17:27 -0700, Scott Branden wrote: > Add kernel_pread_file* support to kernel to allow for partial read > of files with an offset into the file. Existing kernel_read_file > functions call new kernel_pread_file functions with offset=0 and > flags=KERNEL_PREAD_FLAG_WHOLE. > > Signed-off-by: Scott Branden <scott.branden@broadcom.com> > --- <snip> > @@ -941,14 +955,16 @@ int kernel_read_file(struct file *file, void **buf, loff_t *size, > > if (bytes == 0) > break; > + > + buf_pos += bytes; > } > > - if (pos != i_size) { > + if (pos != read_end) { > ret = -EIO; > goto out_free; > } > > - ret = security_kernel_post_read_file(file, *buf, i_size, id); > + ret = security_kernel_post_read_file(file, *buf, alloc_size, id); > if (!ret) > *size = pos; Prior to the patch set that introduced this security hook, firmware would be read twice, once for measuring/appraising the firmware and again reading the file contents into memory. Partial reads will break both IMA's measuring the file and appraising the file signatures. Mimi
Hi Mimi, On 2020-05-13 11:39 a.m., Mimi Zohar wrote: > [Cc'ing linux-security-module, linux-integrity] > > On Thu, 2020-05-07 at 17:27 -0700, Scott Branden wrote: >> Add kernel_pread_file* support to kernel to allow for partial read >> of files with an offset into the file. Existing kernel_read_file >> functions call new kernel_pread_file functions with offset=0 and >> flags=KERNEL_PREAD_FLAG_WHOLE. >> >> Signed-off-by: Scott Branden <scott.branden@broadcom.com> >> --- > <snip> > >> @@ -941,14 +955,16 @@ int kernel_read_file(struct file *file, void **buf, loff_t *size, The checkpatch shows this as kernel_read_file when it is actually the new function kernel_pread_file. Please see the call to kernel_pread_file from kernel_read_file in the complete patch rather this snippet. >> >> if (bytes == 0) >> break; >> + >> + buf_pos += bytes; >> } >> >> - if (pos != i_size) { >> + if (pos != read_end) { >> ret = -EIO; >> goto out_free; >> } >> >> - ret = security_kernel_post_read_file(file, *buf, i_size, id); >> + ret = security_kernel_post_read_file(file, *buf, alloc_size, id); >> if (!ret) >> *size = pos; > Prior to the patch set that introduced this security hook, firmware > would be read twice, once for measuring/appraising the firmware and > again reading the file contents into memory. Partial reads will break > both IMA's measuring the file and appraising the file signatures. The partial file read support is needed for request_firmware_into_buf from drivers. The EXPORT_SYMBOL_GPL is being removed so that there can be no abuse of the partial file read support. Such file integrity checks are not needed for this use case. The partial file (firmware image) is actually downloaded in portions and verified on the device it is loaded to. Regards, Scott
On 2020-05-13 11:53 a.m., Scott Branden wrote: > Hi Mimi, > > On 2020-05-13 11:39 a.m., Mimi Zohar wrote: >> [Cc'ing linux-security-module, linux-integrity] >> >> On Thu, 2020-05-07 at 17:27 -0700, Scott Branden wrote: >>> Add kernel_pread_file* support to kernel to allow for partial read >>> of files with an offset into the file. Existing kernel_read_file >>> functions call new kernel_pread_file functions with offset=0 and >>> flags=KERNEL_PREAD_FLAG_WHOLE. >>> >>> Signed-off-by: Scott Branden <scott.branden@broadcom.com> >>> --- >> <snip> >> >>> @@ -941,14 +955,16 @@ int kernel_read_file(struct file *file, void >>> **buf, loff_t *size, > The checkpatch shows this as kernel_read_file when it is actually the > new function kernel_pread_file. typo: "checkpatch" should be "patch diff" > Please see the call to kernel_pread_file from kernel_read_file in the > complete patch rather this snippet. >>> if (bytes == 0) >>> break; >>> + >>> + buf_pos += bytes; >>> } >>> - if (pos != i_size) { >>> + if (pos != read_end) { >>> ret = -EIO; >>> goto out_free; >>> } >>> - ret = security_kernel_post_read_file(file, *buf, i_size, id); >>> + ret = security_kernel_post_read_file(file, *buf, alloc_size, id); >>> if (!ret) >>> *size = pos; >> Prior to the patch set that introduced this security hook, firmware >> would be read twice, once for measuring/appraising the firmware and >> again reading the file contents into memory. Partial reads will break >> both IMA's measuring the file and appraising the file signatures. > The partial file read support is needed for request_firmware_into_buf > from drivers. The EXPORT_SYMBOL_GPL is being removed so that > there can be no abuse of the partial file read support. Such file > integrity checks are not needed for this use case. The partial file > (firmware image) is actually downloaded in portions and verified on > the device it is loaded to. > > Regards, > Scott
On Wed, 2020-05-13 at 11:53 -0700, Scott Branden wrote: > Hi Mimi, > > On 2020-05-13 11:39 a.m., Mimi Zohar wrote: > > [Cc'ing linux-security-module, linux-integrity] > > > > On Thu, 2020-05-07 at 17:27 -0700, Scott Branden wrote: > >> Add kernel_pread_file* support to kernel to allow for partial read > >> of files with an offset into the file. Existing kernel_read_file > >> functions call new kernel_pread_file functions with offset=0 and > >> flags=KERNEL_PREAD_FLAG_WHOLE. > >> > >> Signed-off-by: Scott Branden <scott.branden@broadcom.com> > >> --- > > <snip> > > > >> @@ -941,14 +955,16 @@ int kernel_read_file(struct file *file, void **buf, loff_t *size, > The checkpatch shows this as kernel_read_file when it is actually the > new function kernel_pread_file. > Please see the call to kernel_pread_file from kernel_read_file in the > complete patch rather this snippet. > >> > >> if (bytes == 0) > >> break; > >> + > >> + buf_pos += bytes; > >> } > >> > >> - if (pos != i_size) { > >> + if (pos != read_end) { > >> ret = -EIO; > >> goto out_free; > >> } > >> > >> - ret = security_kernel_post_read_file(file, *buf, i_size, id); > >> + ret = security_kernel_post_read_file(file, *buf, alloc_size, id); > >> if (!ret) > >> *size = pos; > > Prior to the patch set that introduced this security hook, firmware > > would be read twice, once for measuring/appraising the firmware and > > again reading the file contents into memory. Partial reads will break > > both IMA's measuring the file and appraising the file signatures. > The partial file read support is needed for request_firmware_into_buf > from drivers. The EXPORT_SYMBOL_GPL is being removed so that > there can be no abuse of the partial file read support. Such file > integrity checks are not needed for this use case. The partial file > (firmware image) is actually downloaded in portions and verified on the > device it is loaded to. It's all fine that the device will verify the firmware, but shouldn't the kernel be able to also verify the firmware file signature it is providing to the device, before providing it? The device firmware is being downloaded piecemeal from somewhere and won't be measured? Mimi
On 2020-05-13 12:03 p.m., Mimi Zohar wrote: > On Wed, 2020-05-13 at 11:53 -0700, Scott Branden wrote: >> Hi Mimi, >> >> On 2020-05-13 11:39 a.m., Mimi Zohar wrote: >>> [Cc'ing linux-security-module, linux-integrity] >>> >>> On Thu, 2020-05-07 at 17:27 -0700, Scott Branden wrote: >>>> Add kernel_pread_file* support to kernel to allow for partial read >>>> of files with an offset into the file. Existing kernel_read_file >>>> functions call new kernel_pread_file functions with offset=0 and >>>> flags=KERNEL_PREAD_FLAG_WHOLE. >>>> >>>> Signed-off-by: Scott Branden <scott.branden@broadcom.com> >>>> --- >>> <snip> >>> >>>> @@ -941,14 +955,16 @@ int kernel_read_file(struct file *file, void **buf, loff_t *size, >> The checkpatch shows this as kernel_read_file when it is actually the >> new function kernel_pread_file. >> Please see the call to kernel_pread_file from kernel_read_file in the >> complete patch rather this snippet. >>>> >>>> if (bytes == 0) >>>> break; >>>> + >>>> + buf_pos += bytes; >>>> } >>>> >>>> - if (pos != i_size) { >>>> + if (pos != read_end) { >>>> ret = -EIO; >>>> goto out_free; >>>> } >>>> >>>> - ret = security_kernel_post_read_file(file, *buf, i_size, id); >>>> + ret = security_kernel_post_read_file(file, *buf, alloc_size, id); >>>> if (!ret) >>>> *size = pos; >>> Prior to the patch set that introduced this security hook, firmware >>> would be read twice, once for measuring/appraising the firmware and >>> again reading the file contents into memory. Partial reads will break >>> both IMA's measuring the file and appraising the file signatures. >> The partial file read support is needed for request_firmware_into_buf >> from drivers. The EXPORT_SYMBOL_GPL is being removed so that >> there can be no abuse of the partial file read support. Such file >> integrity checks are not needed for this use case. The partial file >> (firmware image) is actually downloaded in portions and verified on the >> device it is loaded to. > It's all fine that the device will verify the firmware, but shouldn't > the kernel be able to also verify the firmware file signature it is > providing to the device, before providing it? Even if the kernel successfully verified the firmware file signature it would just be wasting its time. The kernel in these use cases is not always trusted. The device needs to authenticate the firmware image itself. > > The device firmware is being downloaded piecemeal from somewhere and > won't be measured? It doesn't need to be measured for current driver needs. If someone has such need the infrastructure could be added to the kernel at a later date. Existing functionality is not broken in any way by this patch series. > > Mimi
On Wed, 2020-05-13 at 12:18 -0700, Scott Branden wrote: > On 2020-05-13 12:03 p.m., Mimi Zohar wrote: > > On Wed, 2020-05-13 at 11:53 -0700, Scott Branden wrote: > Even if the kernel successfully verified the firmware file signature it > would just be wasting its time. The kernel in these use cases is not always > trusted. The device needs to authenticate the firmware image itself. There are also environments where the kernel is trusted and limits the firmware being provided to the device to one which they signed. > > The device firmware is being downloaded piecemeal from somewhere and > > won't be measured? > It doesn't need to be measured for current driver needs. Sure the device doesn't need the kernel measuring the firmware, but hardened environments do measure firmware. > If someone has such need the infrastructure could be added to the kernel > at a later date. Existing functionality is not broken in any way by > this patch series. Wow! You're saying that your patch set takes precedence over the existing expectations and can break them. Mimi
On 2020-05-13 12:39 p.m., Mimi Zohar wrote: > On Wed, 2020-05-13 at 12:18 -0700, Scott Branden wrote: >> On 2020-05-13 12:03 p.m., Mimi Zohar wrote: >>> On Wed, 2020-05-13 at 11:53 -0700, Scott Branden wrote: >> Even if the kernel successfully verified the firmware file signature it >> would just be wasting its time. The kernel in these use cases is not always >> trusted. The device needs to authenticate the firmware image itself. > There are also environments where the kernel is trusted and limits the > firmware being provided to the device to one which they signed. > >>> The device firmware is being downloaded piecemeal from somewhere and >>> won't be measured? >> It doesn't need to be measured for current driver needs. > Sure the device doesn't need the kernel measuring the firmware, but > hardened environments do measure firmware. > >> If someone has such need the infrastructure could be added to the kernel >> at a later date. Existing functionality is not broken in any way by >> this patch series. > Wow! You're saying that your patch set takes precedence over the > existing expectations and can break them. Huh? I said existing functionality is NOT broken by this patch series. > > Mimi
On Wed, 2020-05-13 at 12:41 -0700, Scott Branden wrote: > > On 2020-05-13 12:39 p.m., Mimi Zohar wrote: > > On Wed, 2020-05-13 at 12:18 -0700, Scott Branden wrote: > >> On 2020-05-13 12:03 p.m., Mimi Zohar wrote: > >>> On Wed, 2020-05-13 at 11:53 -0700, Scott Branden wrote: > >> Even if the kernel successfully verified the firmware file signature it > >> would just be wasting its time. The kernel in these use cases is not always > >> trusted. The device needs to authenticate the firmware image itself. > > There are also environments where the kernel is trusted and limits the > > firmware being provided to the device to one which they signed. > > > >>> The device firmware is being downloaded piecemeal from somewhere and > >>> won't be measured? > >> It doesn't need to be measured for current driver needs. > > Sure the device doesn't need the kernel measuring the firmware, but > > hardened environments do measure firmware. > > > >> If someone has such need the infrastructure could be added to the kernel > >> at a later date. Existing functionality is not broken in any way by > >> this patch series. > > Wow! You're saying that your patch set takes precedence over the > > existing expectations and can break them. > Huh? I said existing functionality is NOT broken by this patch series. Assuming a system is configured to measure and appraise firmware (rules below), with this change the firmware file will not be properly measured and will fail signature verification. Sample IMA policy rules: measure func=FIRMWARE_CHECK appraise func=FIRMWARE_CHECK appraise_type=imasig Mimi
On Wed, May 13, 2020 at 05:20:14PM -0400, Mimi Zohar wrote: > On Wed, 2020-05-13 at 12:41 -0700, Scott Branden wrote: > > > > On 2020-05-13 12:39 p.m., Mimi Zohar wrote: > > > On Wed, 2020-05-13 at 12:18 -0700, Scott Branden wrote: > > >> On 2020-05-13 12:03 p.m., Mimi Zohar wrote: > > >>> On Wed, 2020-05-13 at 11:53 -0700, Scott Branden wrote: > > >> Even if the kernel successfully verified the firmware file signature it > > >> would just be wasting its time. The kernel in these use cases is not always > > >> trusted. The device needs to authenticate the firmware image itself. > > > There are also environments where the kernel is trusted and limits the > > > firmware being provided to the device to one which they signed. > > > > > >>> The device firmware is being downloaded piecemeal from somewhere and > > >>> won't be measured? > > >> It doesn't need to be measured for current driver needs. > > > Sure the device doesn't need the kernel measuring the firmware, but > > > hardened environments do measure firmware. > > > > > >> If someone has such need the infrastructure could be added to the kernel > > >> at a later date. Existing functionality is not broken in any way by > > >> this patch series. > > > Wow! You're saying that your patch set takes precedence over the > > > existing expectations and can break them. > > Huh? I said existing functionality is NOT broken by this patch series. > > Assuming a system is configured to measure and appraise firmware > (rules below), with this change the firmware file will not be properly > measured and will fail signature verification. > > Sample IMA policy rules: > measure func=FIRMWARE_CHECK > appraise func=FIRMWARE_CHECK appraise_type=imasig Would a pre and post lsm hook for pread do it? Luis
On Wed, 2020-05-13 at 21:28 +0000, Luis Chamberlain wrote: > On Wed, May 13, 2020 at 05:20:14PM -0400, Mimi Zohar wrote: > > On Wed, 2020-05-13 at 12:41 -0700, Scott Branden wrote: > > > > > > On 2020-05-13 12:39 p.m., Mimi Zohar wrote: > > > > On Wed, 2020-05-13 at 12:18 -0700, Scott Branden wrote: > > > >> On 2020-05-13 12:03 p.m., Mimi Zohar wrote: > > > >>> On Wed, 2020-05-13 at 11:53 -0700, Scott Branden wrote: > > > >> Even if the kernel successfully verified the firmware file signature it > > > >> would just be wasting its time. The kernel in these use cases is not always > > > >> trusted. The device needs to authenticate the firmware image itself. > > > > There are also environments where the kernel is trusted and limits the > > > > firmware being provided to the device to one which they signed. > > > > > > > >>> The device firmware is being downloaded piecemeal from somewhere and > > > >>> won't be measured? > > > >> It doesn't need to be measured for current driver needs. > > > > Sure the device doesn't need the kernel measuring the firmware, but > > > > hardened environments do measure firmware. > > > > > > > >> If someone has such need the infrastructure could be added to the kernel > > > >> at a later date. Existing functionality is not broken in any way by > > > >> this patch series. > > > > Wow! You're saying that your patch set takes precedence over the > > > > existing expectations and can break them. > > > Huh? I said existing functionality is NOT broken by this patch series. > > > > Assuming a system is configured to measure and appraise firmware > > (rules below), with this change the firmware file will not be properly > > measured and will fail signature verification. > > > > Sample IMA policy rules: > > measure func=FIRMWARE_CHECK > > appraise func=FIRMWARE_CHECK appraise_type=imasig > > Would a pre and post lsm hook for pread do it? IMA currently measures and verifies the firmware file signature on the post hook. The file is read once into a buffer. With this change, IMA would need to be on the pre hook, to read the entire file, calculating the file hash and verifying the file signature. Basically the firmware would be read once for IMA and again for the device. Mimi
On 2020-05-13 3:12 p.m., Mimi Zohar wrote: > On Wed, 2020-05-13 at 21:28 +0000, Luis Chamberlain wrote: >> On Wed, May 13, 2020 at 05:20:14PM -0400, Mimi Zohar wrote: >>> On Wed, 2020-05-13 at 12:41 -0700, Scott Branden wrote: >>>> On 2020-05-13 12:39 p.m., Mimi Zohar wrote: >>>>> On Wed, 2020-05-13 at 12:18 -0700, Scott Branden wrote: >>>>>> On 2020-05-13 12:03 p.m., Mimi Zohar wrote: >>>>>>> On Wed, 2020-05-13 at 11:53 -0700, Scott Branden wrote: >>>>>> Even if the kernel successfully verified the firmware file signature it >>>>>> would just be wasting its time. The kernel in these use cases is not always >>>>>> trusted. The device needs to authenticate the firmware image itself. >>>>> There are also environments where the kernel is trusted and limits the >>>>> firmware being provided to the device to one which they signed. >>>>> >>>>>>> The device firmware is being downloaded piecemeal from somewhere and >>>>>>> won't be measured? >>>>>> It doesn't need to be measured for current driver needs. >>>>> Sure the device doesn't need the kernel measuring the firmware, but >>>>> hardened environments do measure firmware. >>>>> >>>>>> If someone has such need the infrastructure could be added to the kernel >>>>>> at a later date. Existing functionality is not broken in any way by >>>>>> this patch series. >>>>> Wow! You're saying that your patch set takes precedence over the >>>>> existing expectations and can break them. >>>> Huh? I said existing functionality is NOT broken by this patch series. >>> Assuming a system is configured to measure and appraise firmware >>> (rules below), with this change the firmware file will not be properly >>> measured and will fail signature verification. So no existing functionality has been broken. >>> >>> Sample IMA policy rules: >>> measure func=FIRMWARE_CHECK >>> appraise func=FIRMWARE_CHECK appraise_type=imasig >> Would a pre and post lsm hook for pread do it? > IMA currently measures and verifies the firmware file signature on the > post hook. The file is read once into a buffer. With this change, > IMA would need to be on the pre hook, to read the entire file, > calculating the file hash and verifying the file signature. Basically > the firmware would be read once for IMA and again for the device. The entire file may not fit into available memory to measure and verify. Hence the reason for a partial read. Is there some way we could add a flag when calling the request_firmware_into_buf to indicate it is ok that the data requested does not need to be measured? > Mimi
On Wed, 2020-05-13 at 15:48 -0700, Scott Branden wrote: > > On 2020-05-13 3:12 p.m., Mimi Zohar wrote: > > On Wed, 2020-05-13 at 21:28 +0000, Luis Chamberlain wrote: > >> On Wed, May 13, 2020 at 05:20:14PM -0400, Mimi Zohar wrote: > >>> On Wed, 2020-05-13 at 12:41 -0700, Scott Branden wrote: > >>>> On 2020-05-13 12:39 p.m., Mimi Zohar wrote: > >>>>> On Wed, 2020-05-13 at 12:18 -0700, Scott Branden wrote: > >>>>>> On 2020-05-13 12:03 p.m., Mimi Zohar wrote: > >>>>>>> On Wed, 2020-05-13 at 11:53 -0700, Scott Branden wrote: > >>>>>> Even if the kernel successfully verified the firmware file signature it > >>>>>> would just be wasting its time. The kernel in these use cases is not always > >>>>>> trusted. The device needs to authenticate the firmware image itself. > >>>>> There are also environments where the kernel is trusted and limits the > >>>>> firmware being provided to the device to one which they signed. > >>>>> > >>>>>>> The device firmware is being downloaded piecemeal from somewhere and > >>>>>>> won't be measured? > >>>>>> It doesn't need to be measured for current driver needs. > >>>>> Sure the device doesn't need the kernel measuring the firmware, but > >>>>> hardened environments do measure firmware. > >>>>> > >>>>>> If someone has such need the infrastructure could be added to the kernel > >>>>>> at a later date. Existing functionality is not broken in any way by > >>>>>> this patch series. > >>>>> Wow! You're saying that your patch set takes precedence over the > >>>>> existing expectations and can break them. > >>>> Huh? I said existing functionality is NOT broken by this patch series. > >>> Assuming a system is configured to measure and appraise firmware > >>> (rules below), with this change the firmware file will not be properly > >>> measured and will fail signature verification. > So no existing functionality has been broken. > >>> > >>> Sample IMA policy rules: > >>> measure func=FIRMWARE_CHECK > >>> appraise func=FIRMWARE_CHECK appraise_type=imasig > >> Would a pre and post lsm hook for pread do it? > > IMA currently measures and verifies the firmware file signature on the > > post hook. The file is read once into a buffer. With this change, > > IMA would need to be on the pre hook, to read the entire file, > > calculating the file hash and verifying the file signature. Basically > > the firmware would be read once for IMA and again for the device. > The entire file may not fit into available memory to measure and > verify. Hence the reason for a partial read. Previously, IMA pre-read the file in page size chunks in order to calculate the file hash. To avoid reading the file twice, the file is now read into a buffer. > > Is there some way we could add a flag when calling the > request_firmware_into_buf to indicate it is ok that the data requested > does not need to be measured? The decision as to what needs to be measured is a policy decision left up to the system owner, which they express by loading an IMA policy. Mimi
On Wed, May 13, 2020 at 07:00:43PM -0400, Mimi Zohar wrote: > On Wed, 2020-05-13 at 15:48 -0700, Scott Branden wrote: > > > > On 2020-05-13 3:12 p.m., Mimi Zohar wrote: > > > On Wed, 2020-05-13 at 21:28 +0000, Luis Chamberlain wrote: > > >> On Wed, May 13, 2020 at 05:20:14PM -0400, Mimi Zohar wrote: > > >>> On Wed, 2020-05-13 at 12:41 -0700, Scott Branden wrote: > > >>>> On 2020-05-13 12:39 p.m., Mimi Zohar wrote: > > >>>>> On Wed, 2020-05-13 at 12:18 -0700, Scott Branden wrote: > > >>>>>> On 2020-05-13 12:03 p.m., Mimi Zohar wrote: > > >>>>>>> On Wed, 2020-05-13 at 11:53 -0700, Scott Branden wrote: > > >>>>>> Even if the kernel successfully verified the firmware file signature it > > >>>>>> would just be wasting its time. The kernel in these use cases is not always > > >>>>>> trusted. The device needs to authenticate the firmware image itself. > > >>>>> There are also environments where the kernel is trusted and limits the > > >>>>> firmware being provided to the device to one which they signed. > > >>>>> > > >>>>>>> The device firmware is being downloaded piecemeal from somewhere and > > >>>>>>> won't be measured? > > >>>>>> It doesn't need to be measured for current driver needs. > > >>>>> Sure the device doesn't need the kernel measuring the firmware, but > > >>>>> hardened environments do measure firmware. > > >>>>> > > >>>>>> If someone has such need the infrastructure could be added to the kernel > > >>>>>> at a later date. Existing functionality is not broken in any way by > > >>>>>> this patch series. > > >>>>> Wow! You're saying that your patch set takes precedence over the > > >>>>> existing expectations and can break them. > > >>>> Huh? I said existing functionality is NOT broken by this patch series. > > >>> Assuming a system is configured to measure and appraise firmware > > >>> (rules below), with this change the firmware file will not be properly > > >>> measured and will fail signature verification. > > So no existing functionality has been broken. > > >>> > > >>> Sample IMA policy rules: > > >>> measure func=FIRMWARE_CHECK > > >>> appraise func=FIRMWARE_CHECK appraise_type=imasig > > >> Would a pre and post lsm hook for pread do it? > > > IMA currently measures and verifies the firmware file signature on the > > > post hook. The file is read once into a buffer. With this change, > > > IMA would need to be on the pre hook, to read the entire file, > > > calculating the file hash and verifying the file signature. Basically > > > the firmware would be read once for IMA and again for the device. > > The entire file may not fit into available memory to measure and > > verify. Hence the reason for a partial read. > > Previously, IMA pre-read the file in page size chunks in order to > calculate the file hash. To avoid reading the file twice, the file is > now read into a buffer. Can the VFS be locked in some way and then using the partial reads would trigger the "read twice" mode? I.e. something like: open first partial read: lock file contents (?) perform full page-at-a-time-read-and-measure rewind, read partial other partial reads final partial read unlock
On Wed, 2020-05-13 at 16:34 -0700, Kees Cook wrote: > On Wed, May 13, 2020 at 07:00:43PM -0400, Mimi Zohar wrote: > > On Wed, 2020-05-13 at 15:48 -0700, Scott Branden wrote: > > > > > > On 2020-05-13 3:12 p.m., Mimi Zohar wrote: > > > > On Wed, 2020-05-13 at 21:28 +0000, Luis Chamberlain wrote: > > > >> On Wed, May 13, 2020 at 05:20:14PM -0400, Mimi Zohar wrote: > > > >>> On Wed, 2020-05-13 at 12:41 -0700, Scott Branden wrote: > > > >>>> On 2020-05-13 12:39 p.m., Mimi Zohar wrote: > > > >>>>> On Wed, 2020-05-13 at 12:18 -0700, Scott Branden wrote: > > > >>>>>> On 2020-05-13 12:03 p.m., Mimi Zohar wrote: > > > >>>>>>> On Wed, 2020-05-13 at 11:53 -0700, Scott Branden wrote: > > > >>>>>> Even if the kernel successfully verified the firmware file signature it > > > >>>>>> would just be wasting its time. The kernel in these use cases is not always > > > >>>>>> trusted. The device needs to authenticate the firmware image itself. > > > >>>>> There are also environments where the kernel is trusted and limits the > > > >>>>> firmware being provided to the device to one which they signed. > > > >>>>> > > > >>>>>>> The device firmware is being downloaded piecemeal from somewhere and > > > >>>>>>> won't be measured? > > > >>>>>> It doesn't need to be measured for current driver needs. > > > >>>>> Sure the device doesn't need the kernel measuring the firmware, but > > > >>>>> hardened environments do measure firmware. > > > >>>>> > > > >>>>>> If someone has such need the infrastructure could be added to the kernel > > > >>>>>> at a later date. Existing functionality is not broken in any way by > > > >>>>>> this patch series. > > > >>>>> Wow! You're saying that your patch set takes precedence over the > > > >>>>> existing expectations and can break them. > > > >>>> Huh? I said existing functionality is NOT broken by this patch series. > > > >>> Assuming a system is configured to measure and appraise firmware > > > >>> (rules below), with this change the firmware file will not be properly > > > >>> measured and will fail signature verification. > > > So no existing functionality has been broken. > > > >>> > > > >>> Sample IMA policy rules: > > > >>> measure func=FIRMWARE_CHECK > > > >>> appraise func=FIRMWARE_CHECK appraise_type=imasig > > > >> Would a pre and post lsm hook for pread do it? > > > > IMA currently measures and verifies the firmware file signature on the > > > > post hook. The file is read once into a buffer. With this change, > > > > IMA would need to be on the pre hook, to read the entire file, > > > > calculating the file hash and verifying the file signature. Basically > > > > the firmware would be read once for IMA and again for the device. > > > The entire file may not fit into available memory to measure and > > > verify. Hence the reason for a partial read. > > > > Previously, IMA pre-read the file in page size chunks in order to > > calculate the file hash. To avoid reading the file twice, the file is > > now read into a buffer. > > Can the VFS be locked in some way and then using the partial reads would > trigger the "read twice" mode? I.e. something like: > > open > first partial read: > lock file contents (?) > perform full page-at-a-time-read-and-measure > rewind, read partial > other partial reads > final partial read > unlock The security_kernel_read_file(), the pre-hook, would need to be moved after getting the file size, but yes that's exactly what would be done in the pre-hook, when the current offset is 0 and the file size and buffer size aren't the same. Mimi
diff --git a/fs/exec.c b/fs/exec.c index 06b4c550af5d..cfab212fab9d 100644 --- a/fs/exec.c +++ b/fs/exec.c @@ -896,10 +896,14 @@ struct file *open_exec(const char *name) } EXPORT_SYMBOL(open_exec); -int kernel_read_file(struct file *file, void **buf, loff_t *size, - loff_t max_size, enum kernel_read_file_id id) -{ - loff_t i_size, pos; +int kernel_pread_file(struct file *file, void **buf, loff_t *size, + loff_t pos, loff_t max_size, unsigned int flags, + enum kernel_read_file_id id) +{ + loff_t alloc_size; + loff_t buf_pos; + loff_t read_end; + loff_t i_size; ssize_t bytes = 0; int ret; @@ -919,21 +923,31 @@ 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 ((flags & KERNEL_PREAD_FLAG_PART) && + (i_size > (pos + max_size))) + read_end = pos + max_size; + + alloc_size = read_end - pos; + if (i_size > SIZE_MAX || (max_size > 0 && alloc_size > max_size)) { ret = -EFBIG; goto out; } if (id != READING_FIRMWARE_PREALLOC_BUFFER) - *buf = vmalloc(i_size); + *buf = vmalloc(alloc_size); if (!*buf) { ret = -ENOMEM; goto out; } - pos = 0; - while (pos < i_size) { - bytes = kernel_read(file, *buf + pos, i_size - pos, &pos); + buf_pos = 0; + while (pos < read_end) { + bytes = kernel_read(file, *buf + buf_pos, read_end - pos, &pos); if (bytes < 0) { ret = bytes; goto out_free; @@ -941,14 +955,16 @@ int kernel_read_file(struct file *file, void **buf, loff_t *size, if (bytes == 0) break; + + buf_pos += bytes; } - if (pos != i_size) { + if (pos != read_end) { ret = -EIO; goto out_free; } - ret = security_kernel_post_read_file(file, *buf, i_size, id); + ret = security_kernel_post_read_file(file, *buf, alloc_size, id); if (!ret) *size = pos; @@ -964,10 +980,20 @@ int kernel_read_file(struct file *file, void **buf, loff_t *size, allow_write_access(file); return ret; } +EXPORT_SYMBOL_GPL(kernel_pread_file); + +int kernel_read_file(struct file *file, void **buf, loff_t *size, + loff_t max_size, enum kernel_read_file_id id) +{ + return kernel_pread_file(file, buf, size, 0, max_size, + KERNEL_PREAD_FLAG_WHOLE, id); +} EXPORT_SYMBOL_GPL(kernel_read_file); -int kernel_read_file_from_path(const char *path, void **buf, loff_t *size, - loff_t max_size, enum kernel_read_file_id id) +int kernel_pread_file_from_path(const char *path, void **buf, + loff_t *size, loff_t pos, + loff_t max_size, unsigned int flags, + enum kernel_read_file_id id) { struct file *file; int ret; @@ -979,15 +1005,25 @@ int kernel_read_file_from_path(const char *path, void **buf, loff_t *size, if (IS_ERR(file)) return PTR_ERR(file); - ret = kernel_read_file(file, buf, size, max_size, id); + ret = kernel_pread_file(file, buf, size, pos, max_size, flags, id); fput(file); return ret; } +EXPORT_SYMBOL_GPL(kernel_pread_file_from_path); + +int kernel_read_file_from_path(const char *path, void **buf, loff_t *size, + loff_t max_size, enum kernel_read_file_id id) +{ + return kernel_pread_file_from_path(path, buf, size, 0, max_size, + KERNEL_PREAD_FLAG_WHOLE, id); +} EXPORT_SYMBOL_GPL(kernel_read_file_from_path); -int kernel_read_file_from_path_initns(const char *path, void **buf, - loff_t *size, loff_t max_size, - enum kernel_read_file_id id) +extern int kernel_pread_file_from_path_initns(const char *path, void **buf, + loff_t *size, loff_t pos, + loff_t max_size, + unsigned int flags, + enum kernel_read_file_id id) { struct file *file; struct path root; @@ -1005,14 +1041,24 @@ int kernel_read_file_from_path_initns(const char *path, void **buf, if (IS_ERR(file)) return PTR_ERR(file); - ret = kernel_read_file(file, buf, size, max_size, id); + ret = kernel_pread_file(file, buf, size, pos, max_size, flags, id); fput(file); return ret; } +EXPORT_SYMBOL_GPL(kernel_pread_file_from_path_initns); + +int kernel_read_file_from_path_initns(const char *path, void **buf, + loff_t *size, loff_t max_size, + enum kernel_read_file_id id) +{ + return kernel_pread_file_from_path_initns(path, buf, size, 0, max_size, + KERNEL_PREAD_FLAG_WHOLE, id); +} EXPORT_SYMBOL_GPL(kernel_read_file_from_path_initns); -int kernel_read_file_from_fd(int fd, void **buf, loff_t *size, loff_t max_size, - enum kernel_read_file_id id) +int kernel_pread_file_from_fd(int fd, void **buf, loff_t *size, loff_t pos, + loff_t max_size, unsigned int flags, + enum kernel_read_file_id id) { struct fd f = fdget(fd); int ret = -EBADF; @@ -1020,11 +1066,19 @@ int kernel_read_file_from_fd(int fd, void **buf, loff_t *size, loff_t max_size, if (!f.file) goto out; - ret = kernel_read_file(f.file, buf, size, max_size, id); + ret = kernel_pread_file(f.file, buf, size, pos, max_size, flags, id); out: fdput(f); return ret; } +EXPORT_SYMBOL_GPL(kernel_pread_file_from_fd); + +int kernel_read_file_from_fd(int fd, void **buf, loff_t *size, loff_t max_size, + enum kernel_read_file_id id) +{ + return kernel_pread_file_from_fd(fd, buf, size, 0, max_size, + KERNEL_PREAD_FLAG_WHOLE, id); +} EXPORT_SYMBOL_GPL(kernel_read_file_from_fd); ssize_t read_code(struct file *file, unsigned long addr, loff_t pos, size_t len) diff --git a/include/linux/fs.h b/include/linux/fs.h index 45cc10cdf6dd..4bba930b77d7 100644 --- a/include/linux/fs.h +++ b/include/linux/fs.h @@ -3014,12 +3014,32 @@ static inline const char *kernel_read_file_id_str(enum kernel_read_file_id id) return kernel_read_file_str[id]; } +/* Flags used by kernel_pread_file functions */ +#define KERNEL_PREAD_FLAG_WHOLE 0x0000 /* Only Allow reading of whole file */ +#define KERNEL_PREAD_FLAG_PART 0x0001 /* Allow reading part of file */ + +extern int kernel_pread_file(struct file *file, void **buf, loff_t *size, + loff_t pos, loff_t max_size, unsigned int flags, + enum kernel_read_file_id id); extern int kernel_read_file(struct file *, void **, loff_t *, loff_t, enum kernel_read_file_id); +extern int kernel_pread_file_from_path(const char *path, void **buf, + loff_t *size, loff_t pos, + loff_t max_size, unsigned int flags, + enum kernel_read_file_id id); extern int kernel_read_file_from_path(const char *, void **, loff_t *, loff_t, enum kernel_read_file_id); +extern int kernel_pread_file_from_path_initns(const char *path, void **buf, + loff_t *size, loff_t pos, + loff_t max_size, + unsigned int flags, + enum kernel_read_file_id id); extern int kernel_read_file_from_path_initns(const char *, void **, loff_t *, loff_t, enum kernel_read_file_id); +extern int kernel_pread_file_from_fd(int fd, void **buf, loff_t *size, + loff_t pos, loff_t max_size, + unsigned int flags, + enum kernel_read_file_id id); extern int kernel_read_file_from_fd(int, void **, loff_t *, loff_t, enum kernel_read_file_id); extern ssize_t kernel_read(struct file *, void *, size_t, loff_t *);
Add kernel_pread_file* support to kernel to allow for partial read of files with an offset into the file. Existing kernel_read_file functions call new kernel_pread_file functions with offset=0 and flags=KERNEL_PREAD_FLAG_WHOLE. Signed-off-by: Scott Branden <scott.branden@broadcom.com> --- fs/exec.c | 96 ++++++++++++++++++++++++++++++++++++---------- include/linux/fs.h | 20 ++++++++++ 2 files changed, 95 insertions(+), 21 deletions(-)