2021-02-18 18:59:41

by Mario Limonciello

[permalink] [raw]
Subject: [RFC 0/2] Split out firmware upgrade from CAP_SYS_ADMIN

Currently NVME (and probably other drivers) require CAP_SYS_ADMIN to
send all commands to the device. This means that software running
in userspace needs the stronger CAP_SYS_ADMIN permission when realistically
a more limited subset of functionality is actually needed.

To allow software that performs firmware upgrades to run without CAP_SYS_ADMIN,
create a new capability CAP_FIRMWARE_UPGRADE that software can run with.

For the RFC, only include NVME. Other drivers can be added if suggested.

Mario Limonciello (2):
capability: Introduce CAP_FIRMWARE_UPGRADE
nvme: Use CAP_FIRMWARE_UPGRADE to check user commands

drivers/nvme/host/core.c | 28 ++++++++++++++++++++++++----
include/linux/capability.h | 5 +++++
include/uapi/linux/capability.h | 7 ++++++-
security/selinux/include/classmap.h | 4 ++--
4 files changed, 37 insertions(+), 7 deletions(-)

--
2.25.1


2021-02-18 18:59:41

by Mario Limonciello

[permalink] [raw]
Subject: [RFC 1/2] capability: Introduce CAP_FIRMWARE_UPGRADE

Split out permissions specifically for firmware upgrades from
CAP_SYS_ADMIN to a new separate capability. This will allow userspace
applications that would traditionally have needed CAP_SYS_ADMIN to perform
firmware upgrades to have a reduced permission set.

Signed-off-by: Mario Limonciello <[email protected]>
---
include/linux/capability.h | 5 +++++
include/uapi/linux/capability.h | 7 ++++++-
security/selinux/include/classmap.h | 4 ++--
3 files changed, 13 insertions(+), 3 deletions(-)

diff --git a/include/linux/capability.h b/include/linux/capability.h
index b2f698915c0f..e9233e217402 100644
--- a/include/linux/capability.h
+++ b/include/linux/capability.h
@@ -267,6 +267,11 @@ static inline bool checkpoint_restore_ns_capable(struct user_namespace *ns)
ns_capable(ns, CAP_SYS_ADMIN);
}

+static inline bool firmware_upgrade_capable(void)
+{
+ return capable(CAP_FIRMWARE_UPGRADE) || capable(CAP_SYS_ADMIN);
+}
+
/* audit system wants to get cap info from files as well */
extern int get_vfs_caps_from_disk(const struct dentry *dentry, struct cpu_vfs_cap_data *cpu_caps);

diff --git a/include/uapi/linux/capability.h b/include/uapi/linux/capability.h
index c6ca33034147..0f204c6a1c0b 100644
--- a/include/uapi/linux/capability.h
+++ b/include/uapi/linux/capability.h
@@ -275,6 +275,7 @@ struct vfs_ns_cap_data {
/* Allow setting encryption key on loopback filesystem */
/* Allow setting zone reclaim policy */
/* Allow everything under CAP_BPF and CAP_PERFMON for backward compatibility */
+/* Allow everything under CAP_FIRMWARE_UPGRADE for backward compatibility */

#define CAP_SYS_ADMIN 21

@@ -417,7 +418,11 @@ struct vfs_ns_cap_data {

#define CAP_CHECKPOINT_RESTORE 40

-#define CAP_LAST_CAP CAP_CHECKPOINT_RESTORE
+/* Allow a device firmware upgrade */
+
+#define CAP_FIRMWARE_UPGRADE 41
+
+#define CAP_LAST_CAP CAP_FIRMWARE_UPGRADE

#define cap_valid(x) ((x) >= 0 && (x) <= CAP_LAST_CAP)

diff --git a/security/selinux/include/classmap.h b/security/selinux/include/classmap.h
index 40cebde62856..188318eefb41 100644
--- a/security/selinux/include/classmap.h
+++ b/security/selinux/include/classmap.h
@@ -28,9 +28,9 @@

#define COMMON_CAP2_PERMS "mac_override", "mac_admin", "syslog", \
"wake_alarm", "block_suspend", "audit_read", "perfmon", "bpf", \
- "checkpoint_restore"
+ "checkpoint_restore", "firmware_upgrade"

-#if CAP_LAST_CAP > CAP_CHECKPOINT_RESTORE
+#if CAP_LAST_CAP > CAP_FIRMWARE_UPGRADE
#error New capability defined, please update COMMON_CAP2_PERMS.
#endif

--
2.25.1

2021-07-23 01:03:01

by Daniil Lunev

[permalink] [raw]
Subject: [RFC 0/2] Split out firmware upgrade from CAP_SYS_ADMIN

Signal boost on this thread for we are interested in a mechanism like that to
avoid running firmware updater with root privileges. We are looking into using
the mechanism to be able to update NVMe and SATA devices from a user with
limited permissions, and to tighten the security for eMMC device, which
currently require only RAW_IO capability to perform a firmware upgrade.