bpf: Fix an error in verifying a field in a union
[ Upstream commit33937607ef
] We are utilizing BPF LSM to monitor BPF operations within our container environment. When we add support for raw_tracepoint, it hits below error. ; (const void *)attr->raw_tracepoint.name); 27: (79) r3 = *(u64 *)(r2 +0) access beyond the end of member map_type (mend:4) in struct (anon) with off 0 size 8 It can be reproduced with below BPF prog. SEC("lsm/bpf") int BPF_PROG(bpf_audit, int cmd, union bpf_attr *attr, unsigned int size) { switch (cmd) { case BPF_RAW_TRACEPOINT_OPEN: bpf_printk("raw_tracepoint is %s", attr->raw_tracepoint.name); break; default: break; } return 0; } The reason is that when accessing a field in a union, such as bpf_attr, if the field is located within a nested struct that is not the first member of the union, it can result in incorrect field verification. union bpf_attr { struct { __u32 map_type; <<<< Actually it will find that field. __u32 key_size; __u32 value_size; ... }; ... struct { __u64 name; <<<< We want to verify this field. __u32 prog_fd; } raw_tracepoint; }; Considering the potential deep nesting levels, finding a perfect solution to address this issue has proven challenging. Therefore, I propose a solution where we simply skip the verification process if the field in question is located within a union. Fixes:7e3617a72d
("bpf: Add array support to btf_struct_access") Signed-off-by: Yafang Shao <laoar.shao@gmail.com> Link: https://lore.kernel.org/r/20230713025642.27477-4-laoar.shao@gmail.com Signed-off-by: Alexei Starovoitov <ast@kernel.org> Signed-off-by: Sasha Levin <sashal@kernel.org>
This commit is contained in:
parent
780f072f4f
commit
912310dd84
|
@ -5788,7 +5788,7 @@ static int btf_struct_walk(struct bpf_verifier_log *log, const struct btf *btf,
|
|||
* that also allows using an array of int as a scratch
|
||||
* space. e.g. skb->cb[].
|
||||
*/
|
||||
if (off + size > mtrue_end) {
|
||||
if (off + size > mtrue_end && !(*flag & PTR_UNTRUSTED)) {
|
||||
bpf_log(log,
|
||||
"access beyond the end of member %s (mend:%u) in struct %s with off %u size %u\n",
|
||||
mname, mtrue_end, tname, off, size);
|
||||
|
|
Loading…
Reference in New Issue