Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

bpf: btf: Fix arg verification in btf_ctx_access()

The bounds checking for the arguments accessed in the BPF program breaks
when the expected_attach_type is not BPF_TRACE_FEXIT, BPF_LSM_MAC or
BPF_MODIFY_RETURN resulting in no check being done for the default case
(the programs which do not receive the return value of the attached
function in its arguments) when the index of the argument being accessed
is equal to the number of arguments (nr_args).

This was a result of a misplaced "else if" block introduced by the
Commit 6ba43b761c41 ("bpf: Attachment verification for
BPF_MODIFY_RETURN")

Fixes: 6ba43b761c41 ("bpf: Attachment verification for BPF_MODIFY_RETURN")
Reported-by: Jann Horn <jannh@google.com>
Signed-off-by: KP Singh <kpsingh@google.com>
Signed-off-by: Alexei Starovoitov <ast@kernel.org>
Link: https://lore.kernel.org/bpf/20200330144246.338-1-kpsingh@chromium.org

authored by

KP Singh and committed by
Alexei Starovoitov
f50b49a0 0fc31b10

+17 -7
+17 -7
kernel/bpf/btf.c
··· 3709 3709 nr_args--; 3710 3710 } 3711 3711 3712 + if (arg > nr_args) { 3713 + bpf_log(log, "func '%s' doesn't have %d-th argument\n", 3714 + tname, arg + 1); 3715 + return false; 3716 + } 3717 + 3712 3718 if (arg == nr_args) { 3713 - if (prog->expected_attach_type == BPF_TRACE_FEXIT || 3714 - prog->expected_attach_type == BPF_LSM_MAC) { 3719 + switch (prog->expected_attach_type) { 3720 + case BPF_LSM_MAC: 3721 + case BPF_TRACE_FEXIT: 3715 3722 /* When LSM programs are attached to void LSM hooks 3716 3723 * they use FEXIT trampolines and when attached to 3717 3724 * int LSM hooks, they use MODIFY_RETURN trampolines. ··· 3735 3728 if (!t) 3736 3729 return true; 3737 3730 t = btf_type_by_id(btf, t->type); 3738 - } else if (prog->expected_attach_type == BPF_MODIFY_RETURN) { 3731 + break; 3732 + case BPF_MODIFY_RETURN: 3739 3733 /* For now the BPF_MODIFY_RETURN can only be attached to 3740 3734 * functions that return an int. 3741 3735 */ ··· 3750 3742 btf_kind_str[BTF_INFO_KIND(t->info)]); 3751 3743 return false; 3752 3744 } 3745 + break; 3746 + default: 3747 + bpf_log(log, "func '%s' doesn't have %d-th argument\n", 3748 + tname, arg + 1); 3749 + return false; 3753 3750 } 3754 - } else if (arg >= nr_args) { 3755 - bpf_log(log, "func '%s' doesn't have %d-th argument\n", 3756 - tname, arg + 1); 3757 - return false; 3758 3751 } else { 3759 3752 if (!t) 3760 3753 /* Default prog with 5 args */ 3761 3754 return true; 3762 3755 t = btf_type_by_id(btf, args[arg].type); 3763 3756 } 3757 + 3764 3758 /* skip modifiers */ 3765 3759 while (btf_type_is_modifier(t)) 3766 3760 t = btf_type_by_id(btf, t->type);