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