firmware: Store opt_flags in fw_priv

Instead of passing opt_flags around so much, store it in the private
structure so it can be examined by internals without needing to add more
arguments to functions.

Co-developed-by: Scott Branden <scott.branden@broadcom.com>
Signed-off-by: Scott Branden <scott.branden@broadcom.com>
Signed-off-by: Kees Cook <keescook@chromium.org>
Link: https://lore.kernel.org/r/20201002173828.2099543-15-keescook@chromium.org
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
This commit is contained in:
Kees Cook 2020-10-02 10:38:26 -07:00 committed by Greg Kroah-Hartman
parent 0fa8e08464
commit 89287c169f
5 changed files with 25 additions and 23 deletions

View file

@ -490,13 +490,11 @@ fw_create_instance(struct firmware *firmware, const char *fw_name,
/** /**
* fw_load_sysfs_fallback() - load a firmware via the sysfs fallback mechanism * fw_load_sysfs_fallback() - load a firmware via the sysfs fallback mechanism
* @fw_sysfs: firmware sysfs information for the firmware to load * @fw_sysfs: firmware sysfs information for the firmware to load
* @opt_flags: flags of options, FW_OPT_*
* @timeout: timeout to wait for the load * @timeout: timeout to wait for the load
* *
* In charge of constructing a sysfs fallback interface for firmware loading. * In charge of constructing a sysfs fallback interface for firmware loading.
**/ **/
static int fw_load_sysfs_fallback(struct fw_sysfs *fw_sysfs, static int fw_load_sysfs_fallback(struct fw_sysfs *fw_sysfs, long timeout)
u32 opt_flags, long timeout)
{ {
int retval = 0; int retval = 0;
struct device *f_dev = &fw_sysfs->dev; struct device *f_dev = &fw_sysfs->dev;
@ -518,7 +516,7 @@ static int fw_load_sysfs_fallback(struct fw_sysfs *fw_sysfs,
list_add(&fw_priv->pending_list, &pending_fw_head); list_add(&fw_priv->pending_list, &pending_fw_head);
mutex_unlock(&fw_lock); mutex_unlock(&fw_lock);
if (opt_flags & FW_OPT_UEVENT) { if (fw_priv->opt_flags & FW_OPT_UEVENT) {
fw_priv->need_uevent = true; fw_priv->need_uevent = true;
dev_set_uevent_suppress(f_dev, false); dev_set_uevent_suppress(f_dev, false);
dev_dbg(f_dev, "firmware: requesting %s\n", fw_priv->fw_name); dev_dbg(f_dev, "firmware: requesting %s\n", fw_priv->fw_name);
@ -580,10 +578,10 @@ static int fw_load_from_user_helper(struct firmware *firmware,
} }
fw_sysfs->fw_priv = firmware->priv; fw_sysfs->fw_priv = firmware->priv;
ret = fw_load_sysfs_fallback(fw_sysfs, opt_flags, timeout); ret = fw_load_sysfs_fallback(fw_sysfs, timeout);
if (!ret) if (!ret)
ret = assign_fw(firmware, device, opt_flags); ret = assign_fw(firmware, device);
out_unlock: out_unlock:
usermodehelper_read_unlock(); usermodehelper_read_unlock();
@ -625,7 +623,6 @@ static bool fw_run_sysfs_fallback(u32 opt_flags)
* @fw: pointer to firmware image * @fw: pointer to firmware image
* @name: name of firmware file to look for * @name: name of firmware file to look for
* @device: device for which firmware is being loaded * @device: device for which firmware is being loaded
* @opt_flags: options to control firmware loading behaviour
* @ret: return value from direct lookup which triggered the fallback mechanism * @ret: return value from direct lookup which triggered the fallback mechanism
* *
* This function is called if direct lookup for the firmware failed, it enables * This function is called if direct lookup for the firmware failed, it enables

View file

@ -67,10 +67,9 @@ static inline void unregister_sysfs_loader(void)
#endif /* CONFIG_FW_LOADER_USER_HELPER */ #endif /* CONFIG_FW_LOADER_USER_HELPER */
#ifdef CONFIG_EFI_EMBEDDED_FIRMWARE #ifdef CONFIG_EFI_EMBEDDED_FIRMWARE
int firmware_fallback_platform(struct fw_priv *fw_priv, u32 opt_flags); int firmware_fallback_platform(struct fw_priv *fw_priv);
#else #else
static inline int firmware_fallback_platform(struct fw_priv *fw_priv, static inline int firmware_fallback_platform(struct fw_priv *fw_priv)
u32 opt_flags)
{ {
return -ENOENT; return -ENOENT;
} }

View file

@ -8,13 +8,13 @@
#include "fallback.h" #include "fallback.h"
#include "firmware.h" #include "firmware.h"
int firmware_fallback_platform(struct fw_priv *fw_priv, u32 opt_flags) int firmware_fallback_platform(struct fw_priv *fw_priv)
{ {
const u8 *data; const u8 *data;
size_t size; size_t size;
int rc; int rc;
if (!(opt_flags & FW_OPT_FALLBACK_PLATFORM)) if (!(fw_priv->opt_flags & FW_OPT_FALLBACK_PLATFORM))
return -ENOENT; return -ENOENT;
rc = security_kernel_load_data(LOADING_FIRMWARE, true); rc = security_kernel_load_data(LOADING_FIRMWARE, true);

View file

@ -68,6 +68,7 @@ struct fw_priv {
void *data; void *data;
size_t size; size_t size;
size_t allocated_size; size_t allocated_size;
u32 opt_flags;
#ifdef CONFIG_FW_LOADER_PAGED_BUF #ifdef CONFIG_FW_LOADER_PAGED_BUF
bool is_paged_buf; bool is_paged_buf;
struct page **pages; struct page **pages;
@ -136,7 +137,7 @@ static inline void fw_state_done(struct fw_priv *fw_priv)
__fw_state_set(fw_priv, FW_STATUS_DONE); __fw_state_set(fw_priv, FW_STATUS_DONE);
} }
int assign_fw(struct firmware *fw, struct device *device, u32 opt_flags); int assign_fw(struct firmware *fw, struct device *device);
#ifdef CONFIG_FW_LOADER_PAGED_BUF #ifdef CONFIG_FW_LOADER_PAGED_BUF
void fw_free_paged_buf(struct fw_priv *fw_priv); void fw_free_paged_buf(struct fw_priv *fw_priv);

View file

@ -168,7 +168,9 @@ static int fw_cache_piggyback_on_request(const char *name);
static struct fw_priv *__allocate_fw_priv(const char *fw_name, static struct fw_priv *__allocate_fw_priv(const char *fw_name,
struct firmware_cache *fwc, struct firmware_cache *fwc,
void *dbuf, size_t size) void *dbuf,
size_t size,
u32 opt_flags)
{ {
struct fw_priv *fw_priv; struct fw_priv *fw_priv;
@ -186,6 +188,7 @@ static struct fw_priv *__allocate_fw_priv(const char *fw_name,
fw_priv->fwc = fwc; fw_priv->fwc = fwc;
fw_priv->data = dbuf; fw_priv->data = dbuf;
fw_priv->allocated_size = size; fw_priv->allocated_size = size;
fw_priv->opt_flags = opt_flags;
fw_state_init(fw_priv); fw_state_init(fw_priv);
#ifdef CONFIG_FW_LOADER_USER_HELPER #ifdef CONFIG_FW_LOADER_USER_HELPER
INIT_LIST_HEAD(&fw_priv->pending_list); INIT_LIST_HEAD(&fw_priv->pending_list);
@ -210,8 +213,10 @@ static struct fw_priv *__lookup_fw_priv(const char *fw_name)
/* Returns 1 for batching firmware requests with the same name */ /* Returns 1 for batching firmware requests with the same name */
static int alloc_lookup_fw_priv(const char *fw_name, static int alloc_lookup_fw_priv(const char *fw_name,
struct firmware_cache *fwc, struct firmware_cache *fwc,
struct fw_priv **fw_priv, void *dbuf, struct fw_priv **fw_priv,
size_t size, u32 opt_flags) void *dbuf,
size_t size,
u32 opt_flags)
{ {
struct fw_priv *tmp; struct fw_priv *tmp;
@ -227,7 +232,7 @@ static int alloc_lookup_fw_priv(const char *fw_name,
} }
} }
tmp = __allocate_fw_priv(fw_name, fwc, dbuf, size); tmp = __allocate_fw_priv(fw_name, fwc, dbuf, size, opt_flags);
if (tmp) { if (tmp) {
INIT_LIST_HEAD(&tmp->list); INIT_LIST_HEAD(&tmp->list);
if (!(opt_flags & FW_OPT_NOCACHE)) if (!(opt_flags & FW_OPT_NOCACHE))
@ -640,7 +645,7 @@ static int fw_add_devm_name(struct device *dev, const char *name)
} }
#endif #endif
int assign_fw(struct firmware *fw, struct device *device, u32 opt_flags) int assign_fw(struct firmware *fw, struct device *device)
{ {
struct fw_priv *fw_priv = fw->priv; struct fw_priv *fw_priv = fw->priv;
int ret; int ret;
@ -659,8 +664,8 @@ int assign_fw(struct firmware *fw, struct device *device, u32 opt_flags)
* should be fixed in devres or driver core. * should be fixed in devres or driver core.
*/ */
/* don't cache firmware handled without uevent */ /* don't cache firmware handled without uevent */
if (device && (opt_flags & FW_OPT_UEVENT) && if (device && (fw_priv->opt_flags & FW_OPT_UEVENT) &&
!(opt_flags & FW_OPT_NOCACHE)) { !(fw_priv->opt_flags & FW_OPT_NOCACHE)) {
ret = fw_add_devm_name(device, fw_priv->fw_name); ret = fw_add_devm_name(device, fw_priv->fw_name);
if (ret) { if (ret) {
mutex_unlock(&fw_lock); mutex_unlock(&fw_lock);
@ -672,7 +677,7 @@ int assign_fw(struct firmware *fw, struct device *device, u32 opt_flags)
* After caching firmware image is started, let it piggyback * After caching firmware image is started, let it piggyback
* on request firmware. * on request firmware.
*/ */
if (!(opt_flags & FW_OPT_NOCACHE) && if (!(fw_priv->opt_flags & FW_OPT_NOCACHE) &&
fw_priv->fwc->state == FW_LOADER_START_CACHE) { fw_priv->fwc->state == FW_LOADER_START_CACHE) {
if (fw_cache_piggyback_on_request(fw_priv->fw_name)) if (fw_cache_piggyback_on_request(fw_priv->fw_name))
kref_get(&fw_priv->ref); kref_get(&fw_priv->ref);
@ -783,7 +788,7 @@ _request_firmware(const struct firmware **firmware_p, const char *name,
#endif #endif
if (ret == -ENOENT) if (ret == -ENOENT)
ret = firmware_fallback_platform(fw->priv, opt_flags); ret = firmware_fallback_platform(fw->priv);
if (ret) { if (ret) {
if (!(opt_flags & FW_OPT_NO_WARN)) if (!(opt_flags & FW_OPT_NO_WARN))
@ -792,7 +797,7 @@ _request_firmware(const struct firmware **firmware_p, const char *name,
name, ret); name, ret);
ret = firmware_fallback_sysfs(fw, name, device, opt_flags, ret); ret = firmware_fallback_sysfs(fw, name, device, opt_flags, ret);
} else } else
ret = assign_fw(fw, device, opt_flags); ret = assign_fw(fw, device);
out: out:
if (ret < 0) { if (ret < 0) {