Skip to content

Commit 581dd69

Browse files
tweksteengregkh
authored andcommitted
firmware_loader: use kernel credentials when reading firmware
Device drivers may decide to not load firmware when probed to avoid slowing down the boot process should the firmware filesystem not be available yet. In this case, the firmware loading request may be done when a device file associated with the driver is first accessed. The credentials of the userspace process accessing the device file may be used to validate access to the firmware files requested by the driver. Ensure that the kernel assumes the responsibility of reading the firmware. This was observed on Android for a graphic driver loading their firmware when the device file (e.g. /dev/mali0) was first opened by userspace (i.e. surfaceflinger). The security context of surfaceflinger was used to validate the access to the firmware file (e.g. /vendor/firmware/mali.bin). Previously, Android configurations were not setting up the firmware_class.path command line argument and were relying on the userspace fallback mechanism. In this case, the security context of the userspace daemon (i.e. ueventd) was consistently used to read firmware files. More Android devices are now found to set firmware_class.path which gives the kernel the opportunity to read the firmware directly (via kernel_read_file_from_path_initns). In this scenario, the current process credentials were used, even if unrelated to the loading of the firmware file. Signed-off-by: Thiébaud Weksteen <[email protected]> Cc: <[email protected]> # 5.10 Reviewed-by: Paul Moore <[email protected]> Acked-by: Luis Chamberlain <[email protected]> Link: https://lore.kernel.org/r/[email protected] Signed-off-by: Greg Kroah-Hartman <[email protected]>
1 parent 672c0c5 commit 581dd69

File tree

1 file changed

+17
-0
lines changed
  • drivers/base/firmware_loader

1 file changed

+17
-0
lines changed

drivers/base/firmware_loader/main.c

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -735,6 +735,8 @@ _request_firmware(const struct firmware **firmware_p, const char *name,
735735
size_t offset, u32 opt_flags)
736736
{
737737
struct firmware *fw = NULL;
738+
struct cred *kern_cred = NULL;
739+
const struct cred *old_cred;
738740
bool nondirect = false;
739741
int ret;
740742

@@ -751,6 +753,18 @@ _request_firmware(const struct firmware **firmware_p, const char *name,
751753
if (ret <= 0) /* error or already assigned */
752754
goto out;
753755

756+
/*
757+
* We are about to try to access the firmware file. Because we may have been
758+
* called by a driver when serving an unrelated request from userland, we use
759+
* the kernel credentials to read the file.
760+
*/
761+
kern_cred = prepare_kernel_cred(NULL);
762+
if (!kern_cred) {
763+
ret = -ENOMEM;
764+
goto out;
765+
}
766+
old_cred = override_creds(kern_cred);
767+
754768
ret = fw_get_filesystem_firmware(device, fw->priv, "", NULL);
755769

756770
/* Only full reads can support decompression, platform, and sysfs. */
@@ -776,6 +790,9 @@ _request_firmware(const struct firmware **firmware_p, const char *name,
776790
} else
777791
ret = assign_fw(fw, device);
778792

793+
revert_creds(old_cred);
794+
put_cred(kern_cred);
795+
779796
out:
780797
if (ret < 0) {
781798
fw_abort_batch_reqs(fw);

0 commit comments

Comments
 (0)