For now, allow only the obvious ones, like sk_priority and sk_mark. Signed-off-by: Stanislav Fomichev <sdf@xxxxxxxxxx> --- kernel/bpf/bpf_lsm.c | 58 +++++++++++++++++++++++++++++++++++++++++++ kernel/bpf/verifier.c | 3 ++- 2 files changed, 60 insertions(+), 1 deletion(-) diff --git a/kernel/bpf/bpf_lsm.c b/kernel/bpf/bpf_lsm.c index 8b948ec9ab73..cc13da18d8b3 100644 --- a/kernel/bpf/bpf_lsm.c +++ b/kernel/bpf/bpf_lsm.c @@ -332,7 +332,65 @@ bool bpf_lsm_is_sleepable_hook(u32 btf_id) const struct bpf_prog_ops lsm_prog_ops = { }; +static int lsm_btf_struct_access(struct bpf_verifier_log *log, + const struct btf *btf, + const struct btf_type *t, int off, + int size, enum bpf_access_type atype, + u32 *next_btf_id, + enum bpf_type_flag *flag) +{ + const struct btf_type *sock_type; + struct btf *btf_vmlinux; + s32 type_id; + size_t end; + + if (atype == BPF_READ) + return btf_struct_access(log, btf, t, off, size, atype, next_btf_id, + flag); + + btf_vmlinux = bpf_get_btf_vmlinux(); + if (!btf_vmlinux) { + bpf_log(log, "no vmlinux btf\n"); + return -EOPNOTSUPP; + } + + type_id = btf_find_by_name_kind(btf_vmlinux, "sock", BTF_KIND_STRUCT); + if (type_id < 0) { + bpf_log(log, "'struct sock' not found in vmlinux btf\n"); + return -EINVAL; + } + + sock_type = btf_type_by_id(btf_vmlinux, type_id); + + if (t != sock_type) { + bpf_log(log, "only 'struct sock' writes are supported\n"); + return -EACCES; + } + + switch (off) { + case bpf_ctx_range(struct sock, sk_priority): + end = offsetofend(struct sock, sk_priority); + break; + case bpf_ctx_range(struct sock, sk_mark): + end = offsetofend(struct sock, sk_mark); + break; + default: + bpf_log(log, "no write support to 'struct sock' at off %d\n", off); + return -EACCES; + } + + if (off + size > end) { + bpf_log(log, + "write access at off %d with size %d beyond the member of 'struct sock' ended at %zu\n", + off, size, end); + return -EACCES; + } + + return NOT_INIT; +} + const struct bpf_verifier_ops lsm_verifier_ops = { .get_func_proto = bpf_lsm_func_proto, .is_valid_access = btf_ctx_access, + .btf_struct_access = lsm_btf_struct_access, }; diff --git a/kernel/bpf/verifier.c b/kernel/bpf/verifier.c index 1d2f2e7babb2..d42ee0033755 100644 --- a/kernel/bpf/verifier.c +++ b/kernel/bpf/verifier.c @@ -12843,7 +12843,8 @@ static int convert_ctx_accesses(struct bpf_verifier_env *env) insn->code = BPF_LDX | BPF_PROBE_MEM | BPF_SIZE((insn)->code); env->prog->aux->num_exentries++; - } else if (resolve_prog_type(env->prog) != BPF_PROG_TYPE_STRUCT_OPS) { + } else if (resolve_prog_type(env->prog) != BPF_PROG_TYPE_STRUCT_OPS && + resolve_prog_type(env->prog) != BPF_PROG_TYPE_LSM) { verbose(env, "Writes through BTF pointers are not allowed\n"); return -EINVAL; } -- 2.35.1.1094.g7c7d902a7c-goog