amdgpu_regs, amdgpu_regs2, and related debugfs nodes allow arbitrary
MMIO read/write via RREG32/WREG32 without checking security_locked_down().
On kernel_lockdown=integrity systems this bypasses the same restrictions
as /dev/mem and PCI config space sysfs.

Check LOCKDOWN_PCI_ACCESS (matching pci-sysfs) at the entry of every
debugfs handler that performs direct register access.

Signed-off-by: Asad Kamal <[email protected]>
---
 drivers/gpu/drm/amd/amdgpu/amdgpu_debugfs.c | 58 +++++++++++++++++++++
 1 file changed, 58 insertions(+)

diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_debugfs.c 
b/drivers/gpu/drm/amd/amdgpu/amdgpu_debugfs.c
index 0ce6e2e4342c..c1f22b0985d0 100644
--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_debugfs.c
+++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_debugfs.c
@@ -25,6 +25,7 @@
 
 #include <linux/kthread.h>
 #include <linux/pci.h>
+#include <linux/security.h>
 #include <linux/uaccess.h>
 #include <linux/pm_runtime.h>
 
@@ -43,6 +44,11 @@
 
 #if defined(CONFIG_DEBUG_FS)
 
+static int amdgpu_debugfs_lockdown_mmio(void)
+{
+       return security_locked_down(LOCKDOWN_PCI_ACCESS);
+}
+
 /**
  * amdgpu_debugfs_process_reg_op - Handle MMIO register reads/writes
  *
@@ -86,6 +92,10 @@ static int  amdgpu_debugfs_process_reg_op(bool read, struct 
file *f,
                        ((*pos & (1ULL << 62)) && (*pos & (1ULL << 61))))
                return -EINVAL;
 
+       r = amdgpu_debugfs_lockdown_mmio();
+       if (r)
+               return r;
+
        /* are we reading registers for which a PG lock is necessary? */
        pm_pg_lock = (*pos >> 23) & 1;
 
@@ -237,6 +247,10 @@ static ssize_t amdgpu_debugfs_regs2_op(struct file *f, 
char __user *buf, u32 off
        if (size & 0x3 || offset & 0x3)
                return -EINVAL;
 
+       r = amdgpu_debugfs_lockdown_mmio();
+       if (r)
+               return r;
+
        r = pm_runtime_get_sync(adev_to_drm(adev)->dev);
        if (r < 0) {
                pm_runtime_put_autosuspend(adev_to_drm(adev)->dev);
@@ -402,6 +416,10 @@ static ssize_t amdgpu_debugfs_gprwave_read(struct file *f, 
char __user *buf, siz
        if (size > 4096 || size & 0x3 || *pos & 0x3)
                return -EINVAL;
 
+       r = amdgpu_debugfs_lockdown_mmio();
+       if (r)
+               return r;
+
        r = pm_runtime_get_sync(adev_to_drm(adev)->dev);
        if (r < 0) {
                pm_runtime_put_autosuspend(adev_to_drm(adev)->dev);
@@ -521,6 +539,10 @@ static ssize_t amdgpu_debugfs_regs_pcie_read(struct file 
*f, char __user *buf,
        if (size & 0x3 || *pos & 0x3)
                return -EINVAL;
 
+       r = amdgpu_debugfs_lockdown_mmio();
+       if (r)
+               return r;
+
        r = pm_runtime_get_sync(adev_to_drm(adev)->dev);
        if (r < 0) {
                pm_runtime_put_autosuspend(adev_to_drm(adev)->dev);
@@ -580,6 +602,10 @@ static ssize_t amdgpu_debugfs_regs_pcie_write(struct file 
*f, const char __user
        if (size & 0x3 || *pos & 0x3)
                return -EINVAL;
 
+       r = amdgpu_debugfs_lockdown_mmio();
+       if (r)
+               return r;
+
        r = pm_runtime_get_sync(adev_to_drm(adev)->dev);
        if (r < 0) {
                pm_runtime_put_autosuspend(adev_to_drm(adev)->dev);
@@ -635,6 +661,10 @@ static ssize_t amdgpu_debugfs_regs_pcie64_read(struct file 
*f, char __user *buf,
        if (size & 0x7 || *pos & 0x7)
                return -EINVAL;
 
+       r = amdgpu_debugfs_lockdown_mmio();
+       if (r)
+               return r;
+
        r = pm_runtime_get_sync(adev_to_drm(adev)->dev);
        if (r < 0) {
                pm_runtime_put_autosuspend(adev_to_drm(adev)->dev);
@@ -687,6 +717,10 @@ static ssize_t amdgpu_debugfs_regs_pcie64_write(struct 
file *f, const char __use
        if (size & 0x7 || *pos & 0x7)
                return -EINVAL;
 
+       r = amdgpu_debugfs_lockdown_mmio();
+       if (r)
+               return r;
+
        r = pm_runtime_get_sync(adev_to_drm(adev)->dev);
        if (r < 0) {
                pm_runtime_put_autosuspend(adev_to_drm(adev)->dev);
@@ -746,6 +780,10 @@ static ssize_t amdgpu_debugfs_regs_didt_read(struct file 
*f, char __user *buf,
        if (!adev->reg.didt.rreg)
                return -EOPNOTSUPP;
 
+       r = amdgpu_debugfs_lockdown_mmio();
+       if (r)
+               return r;
+
        r = pm_runtime_get_sync(adev_to_drm(adev)->dev);
        if (r < 0) {
                pm_runtime_put_autosuspend(adev_to_drm(adev)->dev);
@@ -804,6 +842,10 @@ static ssize_t amdgpu_debugfs_regs_didt_write(struct file 
*f, const char __user
        if (!adev->reg.didt.wreg)
                return -EOPNOTSUPP;
 
+       r = amdgpu_debugfs_lockdown_mmio();
+       if (r)
+               return r;
+
        r = pm_runtime_get_sync(adev_to_drm(adev)->dev);
        if (r < 0) {
                pm_runtime_put_autosuspend(adev_to_drm(adev)->dev);
@@ -863,6 +905,10 @@ static ssize_t amdgpu_debugfs_regs_smc_read(struct file 
*f, char __user *buf,
        if (size & 0x3 || *pos & 0x3)
                return -EINVAL;
 
+       r = amdgpu_debugfs_lockdown_mmio();
+       if (r)
+               return r;
+
        r = pm_runtime_get_sync(adev_to_drm(adev)->dev);
        if (r < 0) {
                pm_runtime_put_autosuspend(adev_to_drm(adev)->dev);
@@ -921,6 +967,10 @@ static ssize_t amdgpu_debugfs_regs_smc_write(struct file 
*f, const char __user *
        if (size & 0x3 || *pos & 0x3)
                return -EINVAL;
 
+       r = amdgpu_debugfs_lockdown_mmio();
+       if (r)
+               return r;
+
        r = pm_runtime_get_sync(adev_to_drm(adev)->dev);
        if (r < 0) {
                pm_runtime_put_autosuspend(adev_to_drm(adev)->dev);
@@ -1156,6 +1206,10 @@ static ssize_t amdgpu_debugfs_wave_read(struct file *f, 
char __user *buf,
        if (size & 3 || *pos & 3)
                return -EINVAL;
 
+       r = amdgpu_debugfs_lockdown_mmio();
+       if (r)
+               return r;
+
        /* decode offset */
        offset = (*pos & GENMASK_ULL(6, 0));
        se = (*pos & GENMASK_ULL(14, 7)) >> 7;
@@ -1247,6 +1301,10 @@ static ssize_t amdgpu_debugfs_gpr_read(struct file *f, 
char __user *buf,
        if (size > 4096 || size & 3 || *pos & 3)
                return -EINVAL;
 
+       r = amdgpu_debugfs_lockdown_mmio();
+       if (r)
+               return r;
+
        /* decode offset */
        offset = (*pos & GENMASK_ULL(11, 0)) >> 2;
        se = (*pos & GENMASK_ULL(19, 12)) >> 12;
-- 
2.46.0

Reply via email to