summaryrefslogtreecommitdiffstats
path: root/drivers/base/firmware_loader
diff options
context:
space:
mode:
authorThiƩbaud Weksteen <tweek@google.com>2022-04-22 11:32:15 +1000
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>2022-04-22 17:13:56 +0200
commit3677563eb8731e1ad5970e3e57f74e5f9d63502a (patch)
tree7f0698fc9da67dfa7a1ad5ad19bbf4deff376909 /drivers/base/firmware_loader
parent736da0b657f615db7e29606eb8818871534a8943 (diff)
downloadlinux-3677563eb8731e1ad5970e3e57f74e5f9d63502a.tar.bz2
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). Because previous configurations were relying on the userspace fallback mechanism, the security context of the userspace daemon (i.e. ueventd) was consistently used to read firmware files. More devices are found to use the command line argument firmware_class.path which gives the kernel the opportunity to read the firmware directly, hence surfacing this misattribution. Signed-off-by: ThiƩbaud Weksteen <tweek@google.com> Reviewed-by: Luis Chamberlain <mcgrof@kernel.org> Tested-by: John Stultz <jstultz@google.com> Link: https://lore.kernel.org/r/20220422013215.2301793-1-tweek@google.com Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
Diffstat (limited to 'drivers/base/firmware_loader')
-rw-r--r--drivers/base/firmware_loader/main.c16
1 files changed, 16 insertions, 0 deletions
diff --git a/drivers/base/firmware_loader/main.c b/drivers/base/firmware_loader/main.c
index 3d9b2074912d..6ac6c7753acc 100644
--- a/drivers/base/firmware_loader/main.c
+++ b/drivers/base/firmware_loader/main.c
@@ -802,6 +802,8 @@ _request_firmware(const struct firmware **firmware_p, const char *name,
size_t offset, u32 opt_flags)
{
struct firmware *fw = NULL;
+ struct cred *kern_cred = NULL;
+ const struct cred *old_cred;
bool nondirect = false;
int ret;
@@ -818,6 +820,18 @@ _request_firmware(const struct firmware **firmware_p, const char *name,
if (ret <= 0) /* error or already assigned */
goto out;
+ /*
+ * We are about to try to access the firmware file. Because we may have been
+ * called by a driver when serving an unrelated request from userland, we use
+ * the kernel credentials to read the file.
+ */
+ kern_cred = prepare_kernel_cred(NULL);
+ if (!kern_cred) {
+ ret = -ENOMEM;
+ goto out;
+ }
+ old_cred = override_creds(kern_cred);
+
ret = fw_get_filesystem_firmware(device, fw->priv, "", NULL);
/* Only full reads can support decompression, platform, and sysfs. */
@@ -848,6 +862,8 @@ _request_firmware(const struct firmware **firmware_p, const char *name,
} else
ret = assign_fw(fw, device);
+ revert_creds(old_cred);
+
out:
if (ret < 0) {
fw_abort_batch_reqs(fw);