[PATCH 10/12] PCI/switchtec: Add permission check for the GAS access MRPC commands

From: Logan Gunthorpe
Date: Mon Jan 06 2020 - 14:04:14 EST


From: Kelvin Cao <kelvin.cao@xxxxxxxxxxxxx>

GEN4 hardware provides new MRPC commands to read and write from
directly from any address in the PCI BAR (which Microsemi refers to
as GAS). Seeing accessing BAR registers can be dangerous and break
the driver, we don't want unpriviliged users to have this ability.

Therefore, for the local and remote GAS access MRPC commands, the
requesting process should need CAP_SYS_ADMIN. Priviligded processes
will already have access to the bar through the sysfs resource file
so this doesn't give userspace any capabilities it didn't already have.

Signed-off-by: Kelvin Cao <kelvin.cao@xxxxxxxxxxxxx>
[logang@xxxxxxxxxxxx: rework commit message]
Signed-off-by: Logan Gunthorpe <logang@xxxxxxxxxxxx>
---
drivers/pci/switch/switchtec.c | 6 ++++++
include/linux/switchtec.h | 5 +++++
2 files changed, 11 insertions(+)

diff --git a/drivers/pci/switch/switchtec.c b/drivers/pci/switch/switchtec.c
index 524cb4e4bbf7..990e0ee32f7b 100644
--- a/drivers/pci/switch/switchtec.c
+++ b/drivers/pci/switch/switchtec.c
@@ -478,6 +478,12 @@ static ssize_t switchtec_dev_write(struct file *filp, const char __user *data,
rc = -EFAULT;
goto out;
}
+ if (((MRPC_CMD_ID(stuser->cmd) == MRPC_GAS_WRITE) ||
+ (MRPC_CMD_ID(stuser->cmd) == MRPC_GAS_READ)) &&
+ !capable(CAP_SYS_ADMIN)) {
+ rc = -EPERM;
+ goto out;
+ }

data += sizeof(stuser->cmd);
rc = copy_from_user(&stuser->data, data, size - sizeof(stuser->cmd));
diff --git a/include/linux/switchtec.h b/include/linux/switchtec.h
index e85155244135..1c3e76b535a2 100644
--- a/include/linux/switchtec.h
+++ b/include/linux/switchtec.h
@@ -21,6 +21,11 @@
#define SWITCHTEC_EVENT_FATAL BIT(4)

#define SWITCHTEC_DMA_MRPC_EN BIT(0)
+
+#define MRPC_GAS_READ 0x29
+#define MRPC_GAS_WRITE 0x87
+#define MRPC_CMD_ID(x) ((x) & 0xffff)
+
enum {
SWITCHTEC_GAS_MRPC_OFFSET = 0x0000,
SWITCHTEC_GAS_TOP_CFG_OFFSET = 0x1000,
--
2.20.1