All of lore.kernel.org
 help / color / mirror / Atom feed
From: Yonghong Song <yhs@fb.com>
To: Tony Ambardar <tony.ambardar@gmail.com>
Cc: bpf <bpf@vger.kernel.org>, <linux-mips@vger.kernel.org>,
	Alexei Starovoitov <ast@kernel.org>,
	Daniel Borkmann <daniel@iogearbox.net>,
	Andrii Nakryiko <andrii@kernel.org>
Subject: Re: Kernel Oops in test_verifier "#828/p reference tracking: bpf_sk_release(btf_tcp_sock)"
Date: Tue, 15 Jun 2021 22:55:04 -0700	[thread overview]
Message-ID: <f888e1ef-acef-2b3d-3ac8-06a051f979d7@fb.com> (raw)
In-Reply-To: <CAPGftE8d03K4_S1pTyRVWZL7w67FukES_PV8SR=0_6DXhXzjQw@mail.gmail.com>



On 6/15/21 7:21 PM, Tony Ambardar wrote:
> On Sun, 13 Jun 2021 at 23:14, Yonghong Song <yhs@fb.com> wrote:
>>
>> On 6/12/21 5:07 PM, Tony Ambardar wrote:
>>> On Fri, 11 Jun 2021 at 08:57, Yonghong Song <yhs@fb.com> wrote:
>>>>
>>>> On 6/10/21 6:02 PM, Tony Ambardar wrote:
>>>>> Hello,
>>>>>
>>>>> I encountered an NPE and kernel Oops [1] while running the
>>>>> 'test_verifier' selftest on MIPS32 with LTS kernel 5.10.41. This was
>>>>> observed during development of a MIPS32 JIT but is verifier-related.
>>>>>
>>>>> Initial troubleshooting [2] points to an unchecked NULL dereference in
>>>>> btf_type_by_id(), with an unexpected BTF type ID. The root cause is
>>>>> unclear, whether source of the ID or a potential underlying BTF
>>>>> problem.
>>>>
>>>> Do you know what is the faulty btf ID number? What is the maximum id
>>>> for vmlinux BTF?
>>>
>>> Thanks for the suggestions, Yonghong.
>>>
>>> I had built/packaged bpftool for the target, which shows the maximum as:
>>>
>>>     root@OpenWrt:~# bpftool btf dump file /sys/kernel/btf/vmlinux format
>>> raw|tail -5
>>>     [43179] FUNC 'pci_load_of_ranges' type_id=43178 linkage=static
>>>     [43180] ARRAY '(anon)' type_id=23 index_type_id=23 nr_elems=16
>>>     [43181] FUNC 'pcibios_plat_dev_init' type_id=29264 linkage=static
>>>     [43182] FUNC 'pcibios_map_irq' type_id=29815 linkage=static
>>>     [43183] FUNC 'mips_pcibios_init' type_id=115 linkage=static
>>>
>>> After adding NULL handling and debug pr_err() to kernel_type_name(), I next see:
>>>
>>>     root@OpenWrt:~# ./test_verifier_eb 828
>>>     [   87.196692] btf_type_by_id(btf_vmlinux, 3062497280) returns NULL
>>>     [   87.196958] btf_type_by_id(btf_vmlinux, 2936995840) returns NULL
>>>     #828/p reference tracking: bpf_sk_release(btf_tcp_sock) FAIL
>>>
>>> Those large type ids make me suspect an endianness issue, even though bpftool
>>> can still properly access the vmlinux BTF. Changing byte order and
>>> looking up the
>>> resulting type ids seems to confirm this:
>>>
>>>     Check endianness:
>>>       3062497280 -> 0xB68A0000 --swap endian--> 0x00008AB6 -> 35510
>>>     bpftool btf dump file /sys/kernel/btf/vmlinux format raw|fgrep "[35510]":
>>>       [35510] STRUCT 'tcp_sock' size=1752 vlen=136
>>>
>>>     Check endianness:
>>>       2936995840 -> 0xAF0F0000 --swap endian--> 0x00000FAF -> 4015
>>>     bpftool btf dump file /sys/kernel/btf/vmlinux format raw|fgrep "[4015]":
>>>       [4015] STRUCT 'sock_common' size=112 vlen=25
>>>
>>> As a further test, I repeated "test_verifier 828" across mips{32,64}{be,le}
>>> systems and confirm seeing the problem only with the big-endian ones.
>>
>>   From the above information, looks like vmlinux BTF is correct.
>> Below resolve_btfids command output seems indicating the btf_id list
>> is also correct.
>>
>> The kernel_type_name is used in a few places for verifier verbose output.
>>
>> $ grep kernel_type_name kernel/bpf/verifier.c
>> static const char *kernel_type_name(const struct btf* btf, u32 id)
>>                                   verbose(env, "%s",
>> kernel_type_name(reg->btf, reg->btf_id));
>>                                   regno, kernel_type_name(reg->btf,
>> reg->btf_id),
>>                                   kernel_type_name(btf_vmlinux,
>> *arg_btf_id));
>>
>> The most suspicous target is reg->btf_id, which is propagated from
>> the result of bpf_sk_lookup_tcp() helper.
>>
>>>
>>>> The involved helper is bpf_sk_release.
>>>>
>>>> static const struct bpf_func_proto bpf_sk_release_proto = {
>>>>            .func           = bpf_sk_release,
>>>>            .gpl_only       = false,
>>>>            .ret_type       = RET_INTEGER,
>>>>            .arg1_type      = ARG_PTR_TO_BTF_ID_SOCK_COMMON,
>>>> };
>>>>
>>>> Eventually, the btf_id is taken from btf_sock_ids[6] where
>>>> btf_sock_ids is a kernel global variable.
>>>>
>>>> Could you check btf_sock_ids[6] to see whether the number
>>>> makes sense?
>>>
>>> What I see matches the second btf_type_by_id() NULL call above:
>>>     [   56.556121] btf_sock_ids[6]: 2936995840
>>>
>>>> The id is computed by resolve_btfids in
>>>> tools/bpf/resolve_btfids, you might add verbose mode to your linux build
>>>> to get more information.
>>>
>>> The verbose build didn't print any details of the btf ids. Was there anything
>>> special to do in invocation? I manually ran "resolve_btfids -v vmlinux" from
>>> the build dir and this, strangely, gave slightly different results than bpftool
>>> but not the huge endian-swapped type ids. Is this expected?
>>>
>>>     # ./tools/bpf/resolve_btfids/resolve_btfids -v vmlinux
>>>     ...
>>>     patching addr   116: ID   35522 [tcp_sock]
>>>     ...
>>>     patching addr   112: ID    4021 [sock_common]
>>>
>>> Do any of the details above help narrow down things? What do you suggest
>>> for next steps?
>>
>> We need to identify issues by dumping detailed verifier logs.
>> Could you apply the following change?
>>
>> --- a/tools/testing/selftests/bpf/test_verifier.c
>> +++ b/tools/testing/selftests/bpf/test_verifier.c
>> @@ -1088,7 +1088,7 @@ static void do_test_single(struct bpf_test *test,
>> bool unpriv,
>>           attr.insns_cnt = prog_len;
>>           attr.license = "GPL";
>>           if (verbose)
>> -               attr.log_level = 1;
>> +               attr.log_level = 3;
>>           else if (expected_ret == VERBOSE_ACCEPT)
>>                   attr.log_level = 2;
>>           else
>>
>> Run command like `./test_verifier -v 828 828`?
>>
>> I attached the verifier output for x86_64.
>> Maybe by comparing x86 output vs. mips32 output, you can
>> find which insn starts to have *wrong* verifier state
>> and then we can go from there.
> 
> I realized too late your test output must be for a different kernel version as
> well as arch, as the test numbering is different and doesn't match my test:
> "reference tracking: bpf_sk_release(btf_tcp_sock)".
> 
> Given the problem is seen on big-endian and not little-systems, I applied
> your patch for both mips32 variant systems and recaptured log output,
> which should make for a stricter A/B comparison. I also kept my earlier
> patches to catch the NULLs and print debug info.
> 
> The logs are identical until insn #18, where the failing MIPS32BE shows:
> 
> 18: R0_w=ptr_or_null_(null)(id=3,off=0,imm=0)
> R6_w=sock(id=0,ref_obj_id=2,off=0,imm=0) R10=fp0 fp-8=????0000
> fp-16=0000mmmm fp-24=mmmmmmmm fp-32=mmmmmmmm fp-40=mmmmmmmm
> fp-48=mmmmmmmm refs=2
> 
> while the succeed MIPS32LE test shows:
> 
> 18: R0_w=ptr_or_null_tcp_sock(id=3,off=0,imm=0)
> R6_w=sock(id=0,ref_obj_id=2,off=0,imm=0) R10=fp0 fp-8=????0000
> fp-16=0000mmmm fp-24=mmmmmmmm fp-32=mmmmmmmm fp-40=mmmmmmmm
> fp-48=mmmmmmmm refs=2
> 
> There are then further differences you can see in the attached logs. It's
> not clear to me what these differences mean however. Any ideas?

The above R0_w is to capture the return value for bpf_skc_to_tcp_sock()

const struct bpf_func_proto bpf_skc_to_tcp_sock_proto = {
         .func                   = bpf_skc_to_tcp_sock,
         .gpl_only               = false,
         .ret_type               = RET_PTR_TO_BTF_ID_OR_NULL,
         .arg1_type              = ARG_PTR_TO_BTF_ID_SOCK_COMMON,
         .ret_btf_id             = &btf_sock_ids[BTF_SOCK_TYPE_TCP],
};

 From the above func_proto, it should return the btf_id for
btf_sock_ids[BTF_SOCK_TYPE_TCP].

It does like the root cause is still endianness of btf_sock_ids
written by resolve_btfids.

> 
> Following your earlier comments on the large, endian-swapped values
> in btf_sock_ids[6], I noticed this is true of all btf_sock_ids[]
> elements, based on debug output:
> 
>      btf_sock_ids[0] = 2139684864
>      btf_sock_ids[1] = 2794061824
>      btf_sock_ids[2] = 2844459008
>      btf_sock_ids[3] = 1234305024
>      btf_sock_ids[4] = 3809411072
>      btf_sock_ids[5] = 1946812416
>      btf_sock_ids[6] = 2936995840
>      btf_sock_ids[7] = 3062497280
>      btf_sock_ids[8] = 2861236224
>      btf_sock_ids[9] = 1251082240
>      btf_sock_ids[10] = 1334968320
>      btf_sock_ids[11] = 1267859456
>      btf_sock_ids[12] = 1318191104
> 
> If these are populated by resolve_btfids, how could we re-verify that
> it's being done properly?
> 
>>>
>>> Thanks,
>>> Tony
>>>
[...]

      parent reply	other threads:[~2021-06-16  5:55 UTC|newest]

Thread overview: 8+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2021-06-11  1:02 Kernel Oops in test_verifier "#828/p reference tracking: bpf_sk_release(btf_tcp_sock)" Tony Ambardar
2021-06-11 15:57 ` Yonghong Song
2021-06-13  0:07   ` Tony Ambardar
2021-06-14  6:14     ` Yonghong Song
2021-06-16  2:21       ` Tony Ambardar
2021-06-16  3:38         ` Tony Ambardar
2021-06-16  6:13           ` Yonghong Song
2021-06-16  5:55         ` Yonghong Song [this message]

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=f888e1ef-acef-2b3d-3ac8-06a051f979d7@fb.com \
    --to=yhs@fb.com \
    --cc=andrii@kernel.org \
    --cc=ast@kernel.org \
    --cc=bpf@vger.kernel.org \
    --cc=daniel@iogearbox.net \
    --cc=linux-mips@vger.kernel.org \
    --cc=tony.ambardar@gmail.com \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.