iovisor / bcc

BCC - Tools for BPF-based Linux IO analysis, networking, monitoring, and more

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

Backported probe_user_read* probe_kernel_read* are not used by bcc

nitanmarcel opened this issue · comments

Table of contents

Issue

I'm trying to backport probe_{user/kernel}_read* to my android 4.9 kernel on adnroid 14 and I run into some issues with bcc not using them.

While running opensnoop, the argument is still empty hint that it's still using bpf_probe_read.

Testing the newly added methods they all have a return value of -14.

# b' id.gms.unstable-6051  [001] d..1  1271.064263: : bpf_probe_read_user: ret=-14, data=""'
# b' id.gms.unstable-6051  [001] d..1  1271.064271: : bpf_probe_read_kernel: ret=-14, data=""'
# b' id.gms.unstable-6051  [001] d..1  1271.064277: : bpf_probe_read_user_str: ret=-14, data=""'
# b' id.gms.unstable-6051  [001] d..1  1271.064281: : bpf_probe_read_kernel_str: ret=-14, data=""'

from bcc import BPF

# BPF program code
bpf_code = """
#include <linux/uaccess.h>

int test_bpf_functions(void *ctx) {
    char user_buf[100];
    char kernel_buf[100];
    const char *addr = "Hello, World!";
    
    // Test bpf_probe_read_user
    int ret_user = bpf_probe_read_user(user_buf, sizeof(user_buf), addr);
    bpf_trace_printk("bpf_probe_read_user: ret=%d, data=\\"%s\\"\\n", ret_user, user_buf);

    // Test bpf_probe_read_kernel
    int ret_kernel = bpf_probe_read_kernel(kernel_buf, sizeof(kernel_buf), addr);
    bpf_trace_printk("bpf_probe_read_kernel: ret=%d, data=\\"%s\\"\\n", ret_kernel, kernel_buf);

    // Test bpf_probe_read_user_str
    int ret_user_str = bpf_probe_read_user_str(user_buf, sizeof(user_buf), addr);
    bpf_trace_printk("bpf_probe_read_user_str: ret=%d, data=\\"%s\\"\\n", ret_user_str, user_buf);

    // Test bpf_probe_read_kernel_str
    int ret_kernel_str = bpf_probe_read_kernel_str(kernel_buf, sizeof(kernel_buf), addr);
    bpf_trace_printk("bpf_probe_read_kernel_str: ret=%d, data=\\"%s\\"\\n", ret_kernel_str, kernel_buf);

    return 0;
}
"""

# Load BPF program
bpf = BPF(text=bpf_code)
bpf.attach_kprobe(event=bpf.get_syscall_fnname("clone"), fn_name="test_bpf_functions")

# Print trace output
bpf.trace_print()

I've been using bcc built from ExtendedAndroidTools tool repo, could maybe that cause an issue?

This is the current diff I'm working on

diff --git a/include/uapi/linux/bpf.h b/include/uapi/linux/bpf.h
index 744b4763b80e..de94c13b7193 100644
--- a/include/uapi/linux/bpf.h
+++ b/include/uapi/linux/bpf.h
@@ -559,6 +559,43 @@ enum bpf_func_id {
    */
    BPF_FUNC_probe_read_user,
 
+   /**
+   * int bpf_probe_read_kernel(void *dst, int size, void *src)
+   *     Read a kernel pointer safely.
+   *     Return: 0 on success or negative error
+   */
+   BPF_FUNC_probe_read_kernel,
+
+	/**
+	 * int bpf_probe_read_str(void *dst, int size, const void *unsafe_ptr)
+	 *     Copy a NUL terminated string from user unsafe address. In case the string
+	 *     length is smaller than size, the target is not padded with further NUL
+	 *     bytes. In case the string length is larger than size, just count-1
+	 *     bytes are copied and the last byte is set to NUL.
+	 *     @dst: destination address
+	 *     @size: maximum number of bytes to copy, including the trailing NUL
+	 *     @unsafe_ptr: unsafe address
+	 *     Return:
+	 *       > 0 length of the string including the trailing NUL on success
+	 *       < 0 error
+	 */
+	BPF_FUNC_probe_read_user_str,
+
+	/**
+	 * int bpf_probe_read_str(void *dst, int size, const void *unsafe_ptr)
+	 *     Copy a NUL terminated string from unsafe address. In case the string
+	 *     length is smaller than size, the target is not padded with further NUL
+	 *     bytes. In case the string length is larger than size, just count-1
+	 *     bytes are copied and the last byte is set to NUL.
+	 *     @dst: destination address
+	 *     @size: maximum number of bytes to copy, including the trailing NUL
+	 *     @unsafe_ptr: unsafe address
+	 *     Return:
+	 *       > 0 length of the string including the trailing NUL on success
+	 *       < 0 error
+	 */
+	BPF_FUNC_probe_read_kernel_str,
+
 	__BPF_FUNC_MAX_ID,
 };
 
diff --git a/kernel/trace/bpf_trace.c b/kernel/trace/bpf_trace.c
index a1e37a5d8c88..3478ca744a45 100644
--- a/kernel/trace/bpf_trace.c
+++ b/kernel/trace/bpf_trace.c
@@ -94,7 +94,7 @@ static const struct bpf_func_proto bpf_probe_read_proto = {
 	.arg3_type	= ARG_ANYTHING,
 };
 
-BPF_CALL_3(bpf_probe_read_user, void *, dst, u32, size, const void *, unsafe_ptr)
+BPF_CALL_3(bpf_probe_read_user, void *, dst, u32, size, const void  __user *, unsafe_ptr)
 {
 	int ret;
 
@@ -115,6 +115,27 @@ static const struct bpf_func_proto bpf_probe_read_user_proto = {
 };
 
 
+BPF_CALL_3(bpf_probe_read_kernel, void *, dst, u32, size, const void *, unsafe_ptr)
+{
+	int ret;
+
+	ret = probe_kernel_read(dst, unsafe_ptr, size);
+	if (unlikely(ret < 0))
+		memset(dst, 0, size);
+
+	return ret;
+}
+
+static const struct bpf_func_proto bpf_probe_read_kernel_proto = {
+	.func		= bpf_probe_read_kernel,
+	.gpl_only	= true,
+	.ret_type	= RET_INTEGER,
+	.arg1_type	= ARG_PTR_TO_RAW_STACK,
+	.arg2_type	= ARG_CONST_STACK_SIZE,
+	.arg3_type	= ARG_ANYTHING,
+};
+
+
 BPF_CALL_3(bpf_probe_write_user, void *, unsafe_ptr, const void *, src,
 	   u32, size)
 {
@@ -487,6 +508,69 @@ static const struct bpf_func_proto bpf_probe_read_str_proto = {
 	.arg3_type	= ARG_ANYTHING,
 };
 
+
+
+BPF_CALL_3(bpf_probe_read_user_str, void *, dst, u32, size,
+	   const void __user *, unsafe_ptr)
+{
+	int ret;
+
+	/*
+	 * The strncpy_from_unsafe() call will likely not fill the entire
+	 * buffer, but that's okay in this circumstance as we're probing
+	 * arbitrary memory anyway similar to bpf_probe_read() and might
+	 * as well probe the stack. Thus, memory is explicitly cleared
+	 * only in error case, so that improper users ignoring return
+	 * code altogether don't copy garbage; otherwise length of string
+	 * is returned that can be used for bpf_perf_event_output() et al.
+	 */
+	ret = strncpy_from_unsafe_user(dst, unsafe_ptr, size);
+	if (unlikely(ret < 0))
+		memset(dst, 0, size);
+
+	return ret;
+}
+
+static const struct bpf_func_proto bpf_probe_read_user_str_proto = {
+	.func		= bpf_probe_read_user_str,
+	.gpl_only	= true,
+	.ret_type	= RET_INTEGER,
+	.arg1_type	= ARG_PTR_TO_RAW_STACK,
+	.arg2_type	= ARG_CONST_STACK_SIZE,
+	.arg3_type	= ARG_ANYTHING,
+};
+
+
+BPF_CALL_3(bpf_probe_read_kernel_str, void *, dst, u32, size,
+	   const void *, unsafe_ptr)
+{
+	int ret;
+
+	/*
+	 * The strncpy_from_unsafe() call will likely not fill the entire
+	 * buffer, but that's okay in this circumstance as we're probing
+	 * arbitrary memory anyway similar to bpf_probe_read() and might
+	 * as well probe the stack. Thus, memory is explicitly cleared
+	 * only in error case, so that improper users ignoring return
+	 * code altogether don't copy garbage; otherwise length of string
+	 * is returned that can be used for bpf_perf_event_output() et al.
+	 */
+	ret = strncpy_from_unsafe(dst, unsafe_ptr, size);
+	if (unlikely(ret < 0))
+		memset(dst, 0, size);
+
+	return ret;
+}
+
+static const struct bpf_func_proto bpf_probe_read_kernel_str_proto = {
+	.func		= bpf_probe_read_kernel_str,
+	.gpl_only	= true,
+	.ret_type	= RET_INTEGER,
+	.arg1_type	= ARG_PTR_TO_RAW_STACK,
+	.arg2_type	= ARG_CONST_STACK_SIZE,
+	.arg3_type	= ARG_ANYTHING,
+};
+
 static const struct bpf_func_proto *tracing_func_proto(enum bpf_func_id func_id)
 {
 	switch (func_id) {
@@ -500,8 +584,14 @@ static const struct bpf_func_proto *tracing_func_proto(enum bpf_func_id func_id)
 		return &bpf_probe_read_proto;
 	case BPF_FUNC_probe_read_user:
 		return &bpf_probe_read_user_proto;
+	case BPF_FUNC_probe_read_kernel:
+		return &bpf_probe_read_kernel_proto;
 	case BPF_FUNC_probe_read_str:
 		return &bpf_probe_read_str_proto;
+	case BPF_FUNC_probe_read_user_str:
+		return &bpf_probe_read_user_str_proto;
+	case BPF_FUNC_probe_read_kernel_str:
+		return &bpf_probe_read_kernel_proto;
 	case BPF_FUNC_ktime_get_ns:
 		return &bpf_ktime_get_ns_proto;
 	case BPF_FUNC_tail_call:
diff --git a/tools/include/uapi/linux/bpf.h b/tools/include/uapi/linux/bpf.h
index 155ce25c069d..91d5691288a7 100644
--- a/tools/include/uapi/linux/bpf.h
+++ b/tools/include/uapi/linux/bpf.h
@@ -522,7 +522,44 @@ enum bpf_func_id {
    *     Return: 0 on success or negative error
    */
    BPF_FUNC_probe_read_user,
+
+   /**
+   * int bpf_probe_read_kernel(void *dst, int size, void *src)
+   *     Read a kernel pointer safely.
+   *     Return: 0 on success or negative error
+   */
+   BPF_FUNC_probe_read_kernel,
 	
+	/**
+	 * int bpf_probe_read_str(void *dst, int size, const void *unsafe_ptr)
+	 *     Copy a NUL terminated string from user unsafe address. In case the string
+	 *     length is smaller than size, the target is not padded with further NUL
+	 *     bytes. In case the string length is larger than size, just count-1
+	 *     bytes are copied and the last byte is set to NUL.
+	 *     @dst: destination address
+	 *     @size: maximum number of bytes to copy, including the trailing NUL
+	 *     @unsafe_ptr: unsafe address
+	 *     Return:
+	 *       > 0 length of the string including the trailing NUL on success
+	 *       < 0 error
+	 */
+	BPF_FUNC_probe_read_user_str,
+
+	/**
+	 * int bpf_probe_read_str(void *dst, int size, const void *unsafe_ptr)
+	 *     Copy a NUL terminated string from unsafe address. In case the string
+	 *     length is smaller than size, the target is not padded with further NUL
+	 *     bytes. In case the string length is larger than size, just count-1
+	 *     bytes are copied and the last byte is set to NUL.
+	 *     @dst: destination address
+	 *     @size: maximum number of bytes to copy, including the trailing NUL
+	 *     @unsafe_ptr: unsafe address
+	 *     Return:
+	 *       > 0 length of the string including the trailing NUL on success
+	 *       < 0 error
+	 */
+	BPF_FUNC_probe_read_kernel_str,
+  
   __BPF_FUNC_MAX_ID,
 };

This is also a follow-up of the following patch that adds probe_read_user which now I see it didn't worked either

diff --git a/include/uapi/linux/bpf.h b/include/uapi/linux/bpf.h
index 67d7d771a944..744b4763b80e 100644
--- a/include/uapi/linux/bpf.h
+++ b/include/uapi/linux/bpf.h
@@ -552,6 +552,13 @@ enum bpf_func_id {
 	 */
 	BPF_FUNC_get_socket_uid,
 
+   /**
+   * int bpf_probe_read_user(void *dst, int size, void *src)
+   *     Read a userspace pointer safely.
+   *     Return: 0 on success or negative error
+   */
+   BPF_FUNC_probe_read_user,
+
 	__BPF_FUNC_MAX_ID,
 };
 
diff --git a/kernel/trace/bpf_trace.c b/kernel/trace/bpf_trace.c
index 59182e6d6f51..a1e37a5d8c88 100644
--- a/kernel/trace/bpf_trace.c
+++ b/kernel/trace/bpf_trace.c
@@ -94,35 +94,27 @@ static const struct bpf_func_proto bpf_probe_read_proto = {
 	.arg3_type	= ARG_ANYTHING,
 };
 
-BPF_CALL_3(bpf_probe_read_str, void *, dst, u32, size, const void *, unsafe_ptr)
+BPF_CALL_3(bpf_probe_read_user, void *, dst, u32, size, const void *, unsafe_ptr)
 {
 	int ret;
 
-	/*
-	 * The strncpy_from_unsafe() call will likely not fill the entire
-	 * buffer, but that's okay in this circumstance as we're probing
-	 * arbitrary memory anyway similar to bpf_probe_read() and might
-	 * as well probe the stack. Thus, memory is explicitly cleared
-	 * only in error case, so that improper users ignoring return
-	 * code altogether don't copy garbage; otherwise length of string
-	 * is returned that can be used for bpf_perf_event_output() et al.
-	 */
-	ret = strncpy_from_unsafe(dst, unsafe_ptr, size);
+	ret = probe_user_read(dst, unsafe_ptr, size);
 	if (unlikely(ret < 0))
 		memset(dst, 0, size);
 
 	return ret;
 }
 
-static const struct bpf_func_proto bpf_probe_read_str_proto = {
-	.func           = bpf_probe_read_str,
-	.gpl_only       = true,
-	.ret_type       = RET_INTEGER,
+static const struct bpf_func_proto bpf_probe_read_user_proto = {
+	.func		= bpf_probe_read_user,
+	.gpl_only	= true,
+	.ret_type	= RET_INTEGER,
 	.arg1_type	= ARG_PTR_TO_RAW_STACK,
 	.arg2_type	= ARG_CONST_STACK_SIZE,
 	.arg3_type	= ARG_ANYTHING,
 };
 
+
 BPF_CALL_3(bpf_probe_write_user, void *, unsafe_ptr, const void *, src,
 	   u32, size)
 {
@@ -506,6 +498,8 @@ static const struct bpf_func_proto *tracing_func_proto(enum bpf_func_id func_id)
 		return &bpf_map_delete_elem_proto;
 	case BPF_FUNC_probe_read:
 		return &bpf_probe_read_proto;
+	case BPF_FUNC_probe_read_user:
+		return &bpf_probe_read_user_proto;
 	case BPF_FUNC_probe_read_str:
 		return &bpf_probe_read_str_proto;
 	case BPF_FUNC_ktime_get_ns:
@@ -534,8 +528,6 @@ static const struct bpf_func_proto *tracing_func_proto(enum bpf_func_id func_id)
 		return &bpf_current_task_under_cgroup_proto;
 	case BPF_FUNC_get_prandom_u32:
 		return &bpf_get_prandom_u32_proto;
-	case BPF_FUNC_probe_read_str:
-		return &bpf_probe_read_str_proto;
 	default:
 		return NULL;
 	}
diff --git a/tools/include/uapi/linux/bpf.h b/tools/include/uapi/linux/bpf.h
index a339bea1f4c8..155ce25c069d 100644
--- a/tools/include/uapi/linux/bpf.h
+++ b/tools/include/uapi/linux/bpf.h
@@ -516,7 +516,14 @@ enum bpf_func_id {
 	 */
 	BPF_FUNC_get_socket_uid,
 
-	__BPF_FUNC_MAX_ID,
+   /**
+   * int bpf_probe_read_user(void *dst, int size, void *src)
+   *     Read a userspace pointer safely.
+   *     Return: 0 on success or negative error
+   */
+   BPF_FUNC_probe_read_user,
+	
+  __BPF_FUNC_MAX_ID,
 };
 
 /* All flags used by eBPF helper functions, placed here. */

Ok, this seems to habe been more an issue with adb root, doing echo 0 > /proc/sys/kernel/kptr_restrict made the kallsym adresses to work show non 0 values. Now there's another issue, invalid func 113.

Looks like it now sees the probe_read_kernel but it fails to use it

bpf: Failed to load program: Invalid argument
0: (bf) r6 = r1
1: (85) call 14
2: (7b) *(u64 *)(r10 -8) = r0
3: (b7) r1 = 0
4: (7b) *(u64 *)(r10 -16) = r1
5: (7b) *(u64 *)(r10 -24) = r1
6: (7b) *(u64 *)(r10 -32) = r1
7: (7b) *(u64 *)(r10 -40) = r1
8: (7b) *(u64 *)(r10 -48) = r1
9: (7b) *(u64 *)(r10 -56) = r1
10: (7b) *(u64 *)(r10 -64) = r1
11: (7b) *(u64 *)(r10 -72) = r1
12: (7b) *(u64 *)(r10 -80) = r1
13: (7b) *(u64 *)(r10 -88) = r1
14: (7b) *(u64 *)(r10 -96) = r1
15: (7b) *(u64 *)(r10 -104) = r1
16: (7b) *(u64 *)(r10 -112) = r1
17: (7b) *(u64 *)(r10 -120) = r1
18: (7b) *(u64 *)(r10 -128) = r1
19: (7b) *(u64 *)(r10 -136) = r1
20: (7b) *(u64 *)(r10 -144) = r1
21: (7b) *(u64 *)(r10 -152) = r1
22: (7b) *(u64 *)(r10 -160) = r1
23: (7b) *(u64 *)(r10 -168) = r1
24: (7b) *(u64 *)(r10 -176) = r1
25: (7b) *(u64 *)(r10 -184) = r1
26: (7b) *(u64 *)(r10 -192) = r1
27: (7b) *(u64 *)(r10 -200) = r1
28: (7b) *(u64 *)(r10 -208) = r1
29: (7b) *(u64 *)(r10 -216) = r1
30: (7b) *(u64 *)(r10 -224) = r1
31: (7b) *(u64 *)(r10 -232) = r1
32: (7b) *(u64 *)(r10 -240) = r1
33: (7b) *(u64 *)(r10 -248) = r1
34: (7b) *(u64 *)(r10 -256) = r1
35: (7b) *(u64 *)(r10 -264) = r1
36: (7b) *(u64 *)(r10 -272) = r1
37: (7b) *(u64 *)(r10 -280) = r1
38: (7b) *(u64 *)(r10 -288) = r1
39: (7b) *(u64 *)(r10 -296) = r1
40: (7b) *(u64 *)(r10 -304) = r1
41: (85) call 5
42: (bf) r7 = r0
43: (bf) r1 = r10
44: (07) r1 += -280
45: (b7) r2 = 16
46: (85) call 113
invalid func 113

HINT: bpf_probe_read_kernel missing (added in Linux 5.5).

Traceback (most recent call last):
  File "/data/local/tmp/out/bpftools/share/bcc/tools/opensnoop", line 385, in <module>
    b.attach_kretprobe(event=fnname_open, fn_name="trace_return")
  File "/data/local/tmp/out/bpftools/lib/python3.10/site-packages/bcc-0.29.1+eb8ede2d-py3.10.egg/bcc/__init__.py", line 885, in attach_kretprobe
  File "/data/local/tmp/out/bpftools/lib/python3.10/site-packages/bcc-0.29.1+eb8ede2d-py3.10.egg/bcc/__init__.py", line 526, in load_func
Exception: Failed to load BPF program b'trace_return': Invalid argument

bpf: Failed to load program: Invalid argument

After this error I assumed that the arguments are wrong, and somewhere around the road ARG_PTR_TO_RAW_STACK and ARG_CONST_STACK_SIZE changed.

I finally gave up on that patch and instead I've wen't with [bpf: fix userspace access for bpf_probe_read{, str}()](https://lore.kernel.org/all/358062d4-fdf8-f3da-fd8e-c55cf1a089ec@amazon.com/) and there seems to not be any issues so far and the string arguments work fines.

Here is my diff for kernel 4.9 if someone needs it

bpf: fix userspace access for bpf_probe_read{, str}()

diff --git a/arch/arm/Kconfig b/arch/arm/Kconfig
index 1c0b4001aca2..31675f1e489d 100644
--- a/arch/arm/Kconfig
+++ b/arch/arm/Kconfig
@@ -5,6 +5,7 @@ config ARM
 	select ARCH_HAS_DEVMEM_IS_ALLOWED
 	select ARCH_HAS_ELF_RANDOMIZE
 	select ARCH_HAS_TICK_BROADCAST if GENERIC_CLOCKEVENTS_BROADCAST
+	select ARCH_HAS_NON_OVERLAPPING_ADDRESS_SPACE
 	select ARCH_HAVE_CUSTOM_GPIO_H
 	select ARCH_HAS_GCOV_PROFILE_ALL
 	select ARCH_MIGHT_HAVE_PC_PARPORT
diff --git a/arch/arm64/Kconfig b/arch/arm64/Kconfig
index 9bba90cffb50..f0b753556b7e 100644
--- a/arch/arm64/Kconfig
+++ b/arch/arm64/Kconfig
@@ -14,6 +14,7 @@ config ARM64
 	select ARCH_HAS_GIGANTIC_PAGE
 	select ARCH_HAS_KCOV
 	select ARCH_HAS_SG_CHAIN
+	select ARCH_HAS_NON_OVERLAPPING_ADDRESS_SPACE
 	select ARCH_HAS_TICK_BROADCAST if GENERIC_CLOCKEVENTS_BROADCAST
 	select ARCH_INLINE_READ_LOCK if !PREEMPT
 	select ARCH_INLINE_READ_LOCK_BH if !PREEMPT
diff --git a/arch/powerpc/Kconfig b/arch/powerpc/Kconfig
index 2351ad8657c7..80d76a6461f8 100644
--- a/arch/powerpc/Kconfig
+++ b/arch/powerpc/Kconfig
@@ -85,6 +85,7 @@ config PPC
 	select BINFMT_ELF
 	select ARCH_HAS_ELF_RANDOMIZE
 	select ARCH_HAS_FORTIFY_SOURCE
+	select ARCH_HAS_NON_OVERLAPPING_ADDRESS_SPACE
 	select OF
 	select OF_DMA_DEFAULT_COHERENT		if !NOT_COHERENT_CACHE
 	select OF_EARLY_FLATTREE
diff --git a/arch/x86/Kconfig b/arch/x86/Kconfig
index f5c19fe2eb2c..d47581cc7ba0 100644
--- a/arch/x86/Kconfig
+++ b/arch/x86/Kconfig
@@ -33,6 +33,7 @@ config X86
 	select ARCH_HAS_MMIO_FLUSH
 	select ARCH_HAS_SG_CHAIN
 	select ARCH_HAS_UBSAN_SANITIZE_ALL
+	select ARCH_HAS_NON_OVERLAPPING_ADDRESS_SPACE
 	select ARCH_HAVE_NMI_SAFE_CMPXCHG
 	select ARCH_MIGHT_HAVE_ACPI_PDC		if ACPI
 	select ARCH_MIGHT_HAVE_PC_PARPORT
diff --git a/kernel/Kconfig.locks b/kernel/Kconfig.locks
index 2a31a580ac44..595343eac1e5 100644
--- a/kernel/Kconfig.locks
+++ b/kernel/Kconfig.locks
@@ -252,3 +252,6 @@ config QUEUED_RWLOCKS
 config RWSEM_PRIO_AWARE
        def_bool y
        depends on RWSEM_XCHGADD_ALGORITHM
+
+config ARCH_HAS_NON_OVERLAPPING_ADDRESS_SPACE
+		bool
\ No newline at end of file
diff --git a/kernel/trace/bpf_trace.c b/kernel/trace/bpf_trace.c
index 83b20092b84c..22c3d2593caa 100644
--- a/kernel/trace/bpf_trace.c
+++ b/kernel/trace/bpf_trace.c
@@ -77,8 +77,11 @@ EXPORT_SYMBOL_GPL(trace_call_bpf);
 BPF_CALL_3(bpf_probe_read, void *, dst, u32, size, const void *, unsafe_ptr)
 {
 	int ret;
-
+#ifdef CONFIG_ARCH_HAS_NON_OVERLAPPING_ADDRESS_SPACE
+	ret = probe_kernel_read(dst, unsafe_ptr, size);
+#else
 	ret = probe_kernel_read(dst, unsafe_ptr, size);
+#endif
 	if (unlikely(ret < 0))
 		memset(dst, 0, size);
 
@@ -107,7 +110,11 @@ BPF_CALL_3(bpf_probe_read_str, void *, dst, u32, size, const void *, unsafe_ptr)
 	 * code altogether don't copy garbage; otherwise length of string
 	 * is returned that can be used for bpf_perf_event_output() et al.
 	 */
+#ifdef CONFIG_ARCH_HAS_NON_OVERLAPPING_ADDRESS_SPACE
+	ret = strncpy_from_unsafe_user(dst, unsafe_ptr, size);
+#else
 	ret = strncpy_from_unsafe(dst, unsafe_ptr, size);
+#endif
 	if (unlikely(ret < 0))
 		memset(dst, 0, size);

Properly fixed by checking if the probed pointer is within user space or not.

nitanmarcel/android_kernel_oneplus_sdm845-bpf@7dcf378

BPF_CALL_3(bpf_probe_read, void *, dst, u32, size, const void *, unsafe_ptr)
{
    int ret;

    if ((unsigned long)unsafe_ptr < TASK_SIZE) {
        ret = bpf_probe_read_user(dst, size, unsafe_ptr);
    } else {
        ret = bpf_probe_read_kernel(dst, size, unsafe_ptr);
    }

    return ret;
}