From: Kees Cook <keescook@chromium.org>
To: linux-kernel@vger.kernel.org
Cc: Kees Cook <keescook@chromium.org>,
Ming Lei <ming.lei@canonical.com>,
"Luis R. Rodriguez" <mcgrof@suse.com>,
Greg Kroah-Hartman <gregkh@linuxfoundation.org>,
James Morris <james.l.morris@oracle.com>,
David Howells <dhowells@redhat.com>,
linux-doc@vger.kernel.org, linux-security-module@vger.kernel.org,
linux-firmware@kernel.org,
linux-wireless <linux-wireless@vger.kernel.org>
Subject: [PATCH 6/7] firmware_class: add "fd" input file
Date: Mon, 14 Jul 2014 14:38:16 -0700 [thread overview]
Message-ID: <1405373897-31671-7-git-send-email-keescook@chromium.org> (raw)
In-Reply-To: <1405373897-31671-1-git-send-email-keescook@chromium.org>
As an alternative to loading bytes from the "data" blob when reading
firmware, let kernel read from an fd, so that the LSM can reason about
the origin of firmware contents during userspace on-demand loading.
Signed-off-by: Kees Cook <keescook@chromium.org>
---
Documentation/firmware_class/README | 10 +++++
drivers/base/firmware_class.c | 77 ++++++++++++++++++++++++++++++++++-
2 files changed, 86 insertions(+), 1 deletion(-)
diff --git a/Documentation/firmware_class/README b/Documentation/firmware_class/README
index 71f86859d7d8..d899bdacba1e 100644
--- a/Documentation/firmware_class/README
+++ b/Documentation/firmware_class/README
@@ -59,6 +59,16 @@
8), kernel(driver): Driver code calls release_firmware(fw_entry) releasing
the firmware image and any related resource.
+ Alternative loading (via file descriptor):
+ ==========================================
+ Instead of "loading", and "data" above, firmware can be loaded through
+ an open file descriptor as well, via the "fd" file:
+
+ Replacing steps 2 thorugh 6 above with the following userspace actions,
+ performs the same loading:
+ - open firmware image file (e.g. as fd 3).
+ - write fd (e.g. "3") to /sys/class/firmware/xxx/fd.
+
High level behavior (driver code):
==================================
diff --git a/drivers/base/firmware_class.c b/drivers/base/firmware_class.c
index b38cbcd6ebb1..eac996447d28 100644
--- a/drivers/base/firmware_class.c
+++ b/drivers/base/firmware_class.c
@@ -839,6 +839,70 @@ static struct bin_attribute firmware_attr_data = {
.write = firmware_data_write,
};
+/**
+ * fd_store - set value in the 'fd' control file
+ * @dev: device pointer
+ * @attr: device attribute pointer
+ * @buf: buffer to scan for loading fd value
+ * @count: number of bytes in @buf
+ *
+ * Parses an fd number from buf, and then loads firmware bytes from
+ * the current process's matching open fd.
+ *
+ **/
+static ssize_t fd_store(struct device *dev,
+ struct device_attribute *attr,
+ const char *buf, size_t count)
+{
+ struct firmware_priv *fw_priv = to_firmware_priv(dev);
+ struct firmware_buf *fw_buf = fw_priv->buf;
+ ssize_t retval;
+ int fd;
+ struct fd f;
+
+ if (!capable(CAP_SYS_RAWIO))
+ return -EPERM;
+
+ retval = kstrtoint(buf, 10, &fd);
+ if (retval)
+ return retval;
+
+ f = fdget(fd);
+ if (!f.file)
+ return -EBADF;
+
+ mutex_lock(&fw_lock);
+ /* If we raced another loader, we must fail. */
+ if (test_bit(FW_STATUS_DONE, &fw_buf->status)) {
+ retval = -EINVAL;
+ goto unlock;
+ }
+
+ fw_load_start(fw_buf);
+ /* fw_read_file_contents uses vmalloc, not pages. */
+ fw_buf->is_paged_buf = false;
+ retval = fw_read_file_contents(f.file, fw_buf);
+ if (retval) {
+ /* If we called fw_load_start, we must abort on fail. */
+ fw_load_abort(fw_priv);
+ goto unlock;
+ }
+
+ /* Success. */
+ set_bit(FW_STATUS_DONE, &fw_buf->status);
+ list_del_init(&fw_buf->pending_list);
+ complete_all(&fw_buf->completion);
+
+unlock:
+ mutex_unlock(&fw_lock);
+ fdput(f);
+
+ if (retval)
+ return retval;
+ return count;
+}
+static DEVICE_ATTR_WO(fd);
+
static void firmware_class_timeout_work(struct work_struct *work)
{
struct firmware_priv *fw_priv = container_of(work,
@@ -912,10 +976,19 @@ static int _request_firmware_load(struct firmware_priv *fw_priv,
mutex_lock(&fw_lock);
list_del_init(&buf->pending_list);
mutex_unlock(&fw_lock);
- dev_err(f_dev, "%s: device_create_file failed\n", __func__);
+ dev_err(f_dev, "%s: dev_attr_loading failed\n", __func__);
goto err_del_bin_attr;
}
+ retval = device_create_file(f_dev, &dev_attr_fd);
+ if (retval) {
+ mutex_lock(&fw_lock);
+ list_del_init(&buf->pending_list);
+ mutex_unlock(&fw_lock);
+ dev_err(f_dev, "%s: &dev_attr_fd failed\n", __func__);
+ goto err_del_loading;
+ }
+
if (opt_flags & FW_OPT_UEVENT) {
buf->need_uevent = true;
dev_set_uevent_suppress(f_dev, false);
@@ -933,6 +1006,8 @@ static int _request_firmware_load(struct firmware_priv *fw_priv,
if (!buf->data)
retval = -ENOMEM;
+ device_remove_file(f_dev, &dev_attr_fd);
+err_del_loading:
device_remove_file(f_dev, &dev_attr_loading);
err_del_bin_attr:
device_remove_bin_file(f_dev, &firmware_attr_data);
--
1.7.9.5
next prev parent reply other threads:[~2014-07-14 21:38 UTC|newest]
Thread overview: 44+ messages / expand[flat|nested] mbox.gz Atom feed top
2014-07-14 21:38 [PATCH 0/7] firmware validation Kees Cook
2014-07-14 21:38 ` [PATCH 1/7] doc: fix minor typos in firmware_class README Kees Cook
2014-07-20 2:20 ` Ming Lei
2014-07-14 21:38 ` [PATCH 2/7] test: add firmware_class loader test Kees Cook
2014-07-18 1:47 ` Greg Kroah-Hartman
2014-07-18 15:27 ` Kees Cook
2014-09-18 1:51 ` Sasha Levin
2014-09-18 16:56 ` Kees Cook
2014-07-14 21:38 ` [PATCH 3/7] security: introduce kernel_fw_from_file hook Kees Cook
2014-07-14 22:24 ` Luis R. Rodriguez
2014-07-14 22:31 ` Kees Cook
2014-07-22 19:39 ` Luis R. Rodriguez
2014-07-22 20:55 ` Kees Cook
2014-07-22 22:11 ` Luis R. Rodriguez
2014-07-22 22:20 ` Kees Cook
2014-07-22 22:25 ` Luis R. Rodriguez
2014-07-23 18:52 ` One Thousand Gnomes
2014-07-18 1:48 ` Greg Kroah-Hartman
2014-07-18 17:11 ` Mimi Zohar
2014-07-14 21:38 ` [PATCH 4/7] firmware_class: perform new LSM checks Kees Cook
2014-07-18 3:41 ` James Morris
2014-07-18 17:05 ` Kees Cook
2014-07-19 7:22 ` James Morris
2014-07-19 15:15 ` Kees Cook
2014-07-20 23:43 ` James Morris
2014-07-21 2:50 ` Mimi Zohar
2014-07-21 17:43 ` Greg Kroah-Hartman
2014-07-14 21:38 ` [PATCH 5/7] firmware_class: extract start loading logic Kees Cook
2014-07-20 3:06 ` Ming Lei
2014-07-14 21:38 ` Kees Cook [this message]
2014-07-18 17:11 ` [PATCH 6/7] firmware_class: add "fd" input file Mimi Zohar
2014-07-18 19:04 ` Kees Cook
2014-07-20 3:04 ` Ming Lei
2014-07-20 17:43 ` Kees Cook
2014-07-21 1:42 ` Ming Lei
2014-07-21 15:08 ` Kees Cook
2014-07-21 15:26 ` Greg Kroah-Hartman
2014-07-21 15:43 ` Kees Cook
2014-07-21 16:36 ` Greg Kroah-Hartman
2014-07-21 17:27 ` Kees Cook
2014-07-21 17:43 ` Greg Kroah-Hartman
2014-07-14 21:38 ` [PATCH 7/7] test: add "fd" firmware loading test to selftests Kees Cook
2014-07-18 1:49 ` [PATCH 0/7] firmware validation Greg Kroah-Hartman
2014-07-23 18:53 ` One Thousand Gnomes
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=1405373897-31671-7-git-send-email-keescook@chromium.org \
--to=keescook@chromium.org \
--cc=dhowells@redhat.com \
--cc=gregkh@linuxfoundation.org \
--cc=james.l.morris@oracle.com \
--cc=linux-doc@vger.kernel.org \
--cc=linux-firmware@kernel.org \
--cc=linux-kernel@vger.kernel.org \
--cc=linux-security-module@vger.kernel.org \
--cc=linux-wireless@vger.kernel.org \
--cc=mcgrof@suse.com \
--cc=ming.lei@canonical.com \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox
all inboxes | Powered by JetHome®