uprobe programs that can modify pt_regs require different runtime
assumptions than pt_regs-read-only uprobe programs. Mixing both in
one prog_array can make owner expectations diverge from callee behavior.

Reject the combination of !kprobe_write_ctx progs with kprobe_write_ctx
progs in __bpf_prog_map_compatible() to address the issue.

Fixes: 7384893d970e ("bpf: Allow uprobe program to change context registers")
Signed-off-by: Leon Hwang <[email protected]>
---
 include/linux/bpf.h | 7 ++++---
 kernel/bpf/core.c   | 3 +++
 2 files changed, 7 insertions(+), 3 deletions(-)

diff --git a/include/linux/bpf.h b/include/linux/bpf.h
index b78b53198a2e..2a2f6448a5fb 100644
--- a/include/linux/bpf.h
+++ b/include/linux/bpf.h
@@ -285,9 +285,10 @@ struct bpf_list_node_kern {
  */
 struct bpf_map_owner {
        enum bpf_prog_type type;
-       bool jited;
-       bool xdp_has_frags;
-       bool sleepable;
+       u32 jited:1,
+           xdp_has_frags:1,
+           sleepable:1,
+           kprobe_write_ctx:1;
        u64 storage_cookie[MAX_BPF_CGROUP_STORAGE_TYPE];
        const struct btf_type *attach_func_proto;
        enum bpf_attach_type expected_attach_type;
diff --git a/kernel/bpf/core.c b/kernel/bpf/core.c
index 3ece2da55625..f99a901b5e48 100644
--- a/kernel/bpf/core.c
+++ b/kernel/bpf/core.c
@@ -2402,6 +2402,7 @@ static bool __bpf_prog_map_compatible(struct bpf_map *map,
                map->owner->jited = fp->jited;
                map->owner->xdp_has_frags = aux->xdp_has_frags;
                map->owner->sleepable = fp->sleepable;
+               map->owner->kprobe_write_ctx = aux->kprobe_write_ctx;
                map->owner->expected_attach_type = fp->expected_attach_type;
                map->owner->attach_func_proto = aux->attach_func_proto;
                for_each_cgroup_storage_type(i) {
@@ -2415,6 +2416,8 @@ static bool __bpf_prog_map_compatible(struct bpf_map *map,
                      map->owner->jited == fp->jited &&
                      map->owner->xdp_has_frags == aux->xdp_has_frags &&
                      map->owner->sleepable == fp->sleepable;
+               if (ret && (!map->owner->kprobe_write_ctx && 
aux->kprobe_write_ctx))
+                       ret = false;
                if (ret &&
                    map->map_type == BPF_MAP_TYPE_PROG_ARRAY &&
                    map->owner->expected_attach_type != 
fp->expected_attach_type)
-- 
2.52.0


Reply via email to