[PATCH 1/2] bpf: fix userspace access for bpf_probe_read{, str}()

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



commit 8d92db5c04d10381f4db70ed99b1b576f5db18a7 upstream.

This is an adaptation of parts from above commit to kernel 5.4.

bpf_probe_read{,str}() BPF helpers are broken on arm64, where user
addresses cannot be accessed with normal kernelspace access.

Upstream solution got into v5.8 and cannot directly be cherry picked. We
implement the same mechanism in kernel 5.4.

Detection is only enabled for machines with non-overlapping address spaces
using CONFIG_ARCH_HAS_NON_OVERLAPPING_ADDRESS_SPACE from commits:
commit 0ebeea8ca8a4 ("bpf: Restrict bpf_probe_read{, str}() only to archs where they work")
commit d195b1d1d119 ("powerpc/bpf: Enable bpf_probe_read{, str}() on powerpc again")

To generally fix the issue, upstream includes new BPF helpers:
bpf_probe_read_{user,kernel}_str(). For details on them, see
commit 6ae08ae3dea2 ("bpf: Add probe_read_{user, kernel} and probe_read_{user, kernel}_str helpers")

Cc: <stable@xxxxxxxxxxxxxxx> # 5.4.x
Signed-off-by: Tsahi Zidenberg <tsahee@xxxxxxxxxx>
---
 arch/arm/Kconfig         |  1 +
 arch/arm64/Kconfig       |  1 +
 arch/powerpc/Kconfig     |  1 +
 arch/x86/Kconfig         |  1 +
 init/Kconfig             |  3 +++
 kernel/trace/bpf_trace.c | 18 ++++++++++++++++++
 6 files changed, 25 insertions(+)

diff --git a/arch/arm/Kconfig b/arch/arm/Kconfig
index 9aa88715f196..70f4057fb5b0 100644
--- a/arch/arm/Kconfig
+++ b/arch/arm/Kconfig
@@ -14,6 +14,7 @@ config ARM
     select ARCH_HAS_KEEPINITRD
     select ARCH_HAS_KCOV
     select ARCH_HAS_MEMBARRIER_SYNC_CORE
+    select ARCH_HAS_NON_OVERLAPPING_ADDRESS_SPACE
     select ARCH_HAS_PTE_SPECIAL if ARM_LPAE
     select ARCH_HAS_PHYS_TO_DMA
     select ARCH_HAS_SETUP_DMA_OPS
diff --git a/arch/arm64/Kconfig b/arch/arm64/Kconfig
index 9c8ea5939865..a8c49916ab8c 100644
--- a/arch/arm64/Kconfig
+++ b/arch/arm64/Kconfig
@@ -22,6 +22,7 @@ config ARM64
     select ARCH_HAS_KCOV
     select ARCH_HAS_KEEPINITRD
     select ARCH_HAS_MEMBARRIER_SYNC_CORE
+    select ARCH_HAS_NON_OVERLAPPING_ADDRESS_SPACE
     select ARCH_HAS_PTE_DEVMAP
     select ARCH_HAS_PTE_SPECIAL
     select ARCH_HAS_SETUP_DMA_OPS
diff --git a/arch/powerpc/Kconfig b/arch/powerpc/Kconfig
index c4cbb65e742f..c50bfab7930b 100644
--- a/arch/powerpc/Kconfig
+++ b/arch/powerpc/Kconfig
@@ -129,6 +129,7 @@ config PPC
     select ARCH_HAS_MMIOWB            if PPC64
     select ARCH_HAS_PHYS_TO_DMA
     select ARCH_HAS_PMEM_API
+    select ARCH_HAS_NON_OVERLAPPING_ADDRESS_SPACE
     select ARCH_HAS_PTE_DEVMAP        if PPC_BOOK3S_64
     select ARCH_HAS_PTE_SPECIAL
     select ARCH_HAS_MEMBARRIER_CALLBACKS
diff --git a/arch/x86/Kconfig b/arch/x86/Kconfig
index 8ef85139553f..b9f666db10c1 100644
--- a/arch/x86/Kconfig
+++ b/arch/x86/Kconfig
@@ -70,6 +70,7 @@ config X86
     select ARCH_HAS_KCOV            if X86_64
     select ARCH_HAS_MEM_ENCRYPT
     select ARCH_HAS_MEMBARRIER_SYNC_CORE
+    select ARCH_HAS_NON_OVERLAPPING_ADDRESS_SPACE
     select ARCH_HAS_PMEM_API        if X86_64
     select ARCH_HAS_PTE_DEVMAP        if X86_64
     select ARCH_HAS_PTE_SPECIAL
diff --git a/init/Kconfig b/init/Kconfig
index 96fc45d1b686..1781810d1501 100644
--- a/init/Kconfig
+++ b/init/Kconfig
@@ -2210,6 +2210,9 @@ config ASN1
 
 source "kernel/Kconfig.locks"
 
+config ARCH_HAS_NON_OVERLAPPING_ADDRESS_SPACE
+    bool
+
 config ARCH_HAS_SYNC_CORE_BEFORE_USERMODE
     bool
 
diff --git a/kernel/trace/bpf_trace.c b/kernel/trace/bpf_trace.c
index 74c1db7178cf..ef534ad3f94d 100644
--- a/kernel/trace/bpf_trace.c
+++ b/kernel/trace/bpf_trace.c
@@ -142,6 +142,15 @@ BPF_CALL_3(bpf_probe_read, void *, dst, u32, size, const void *, unsafe_ptr)
 {
     int ret;
 
+#ifdef CONFIG_ARCH_HAS_NON_OVERLAPPING_ADDRESS_SPACE
+    if ((unsigned long)unsafe_ptr < TASK_SIZE) {
+        ret = probe_user_read(dst, unsafe_ptr, size);
+        if (unlikely(ret < 0))
+            goto out;
+        return ret;
+    }
+#endif
+
     ret = security_locked_down(LOCKDOWN_BPF_READ);
     if (ret < 0)
         goto out;
@@ -588,6 +597,15 @@ BPF_CALL_3(bpf_probe_read_str, void *, dst, u32, size,
 {
     int ret;
 
+#ifdef CONFIG_ARCH_HAS_NON_OVERLAPPING_ADDRESS_SPACE
+    if ((unsigned long)unsafe_ptr < TASK_SIZE) {
+        ret = strncpy_from_unsafe_user(dst, (__force void __user *)unsafe_ptr, size);
+        if (unlikely(ret < 0))
+            goto out;
+        return ret;
+    }
+#endif
+
     ret = security_locked_down(LOCKDOWN_BPF_READ);
     if (ret < 0)
         goto out;
-- 
2.25.1





[Index of Archives]     [Linux Kernel]     [Kernel Development Newbies]     [Linux USB Devel]     [Video for Linux]     [Linux Audio Users]     [Yosemite Hiking]     [Linux Kernel]     [Linux SCSI]

  Powered by Linux