Re: R11 is invalid with LLVM 12 and later

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 





On 8/9/21 3:53 PM, Yonghong Song wrote:


On 8/9/21 8:12 AM, Paul Chaignon wrote:
Hello,

While trying to use LLVM 12.0.0 in Cilium, we've noticed that it can
generate invalid BPF bytecode:

     $ clang --version
     Ubuntu clang version 12.0.0-++20210409092622+fa0971b87fb2-1~exp1~20210409193326.73
     Target: x86_64-pc-linux-gnu
     Thread model: posix
     InstalledDir: /usr/bin
     $ make -C bpf -j6 KERNEL=419
     $ llvm-objdump -D -section=2/20 bpf/bpf_lxc.o | grep -i r11
          171:   7b ba 18 ff 00 00 00 00 *(u64 *)(r10 - 232) = r11
          436:   79 ab 18 ff 00 00 00 00 r11 = *(u64 *)(r10 - 232)
          484:   bf 8b 00 00 00 00 00 00 r11 = r8

That bytecode is of course rejected by the verifier:

     171: (7b) *(u64 *)(r10 -232) = r11
     R11 is invalid

Thanks for reporting. I can reproduce the problem and will take a look soon.


LLVM 12.0.1 and latest LLVM sources (e.g., commit 2b4a1d4b from today)
have the same issue. We've bisected it to LLVM commit 552c6c23
("PR44406: Follow behavior of array bound constant folding in more
recent versions of GCC."), but that could just be the commit where
the regression was exposed in Cilium's case.

The above commit is indeed responsible. With the above commit,
the variable length array compile time evaluation becomes conservative.
For cilium function dsr_reply_icmp4 in nodeport.h
  const __u32 l3_max = MAX_IPOPTLEN + sizeof(*ip4) + orig_dgram;
  __u8 tmp[l3_max];

I didn't try to compile with/without the above commit, the following
is the thesis.

Before the above commit, llvm evaluates the expression
  MAX_IPOPTLEN + sizeof(*ip4) + orig_dgram
and concludes that l3_max is a constant so tmp can be allocated
on stack with fixed size.

With the above commit, llvm becomes conservative to evaluate
the expression at compile time. So above l3_max becomes a
non-constant variable and tmp becomes a variable length
array. Since it becomes a variable length array, the
hidden stack pointer "r11" is used and this caused a problem
in verifier.

To workaround the issue, simply define "tmp" with
   __u8 tmp[68];
But that is not for from user experience. I guess we can do:
  1. for BPF target, let us still do aggressive constant folding
     in compile time in clang, basically restores to pre-commit-552c6c23
     level for BPF programs.
  2. provide an error message if r11 is generated in final code.

Will come back to this thread once I got concrete patches. Thanks!


--
Paul




[Index of Archives]     [Linux Samsung SoC]     [Linux Rockchip SoC]     [Linux Actions SoC]     [Linux for Synopsys ARC Processors]     [Linux NFS]     [Linux NILFS]     [Linux USB Devel]     [Video for Linux]     [Linux Audio Users]     [Yosemite News]     [Linux Kernel]     [Linux SCSI]


  Powered by Linux