Re: [bug report] bpf, x86: allow function arguments up to 12 for TRACING

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

 




> 2023年7月17日 22:48,Dan Carpenter <dan.carpenter@xxxxxxxxxx> 写道:
> 
> Hello Menglong Dong,
> 
> The patch 473e3150e30a: "bpf, x86: allow function arguments up to 12
> for TRACING" from Jul 13, 2023 (linux-next), leads to the following
> Smatch static checker warning:
> 
> arch/x86/net/bpf_jit_comp.c:1999 save_args()
> error: uninitialized symbol 'first_off'.
> 
> arch/x86/net/bpf_jit_comp.c
>    1925 static void save_args(const struct btf_func_model *m, u8 **prog,
>    1926                       int stack_size, bool for_call_origin)
>    1927 {
>    1928         int arg_regs, first_off, nr_regs = 0, nr_stack_slots = 0;
>    1929         int i, j;
>    1930 
>    1931         /* Store function arguments to stack.
>    1932          * For a function that accepts two pointers the sequence will be:
>    1933          * mov QWORD PTR [rbp-0x10],rdi
>    1934          * mov QWORD PTR [rbp-0x8],rsi
>    1935          */
>    1936         for (i = 0; i < min_t(int, m->nr_args, MAX_BPF_FUNC_ARGS); i++) {
>    1937                 arg_regs = (m->arg_size[i] + 7) / 8;
>    1938 
>    1939                 /* According to the research of Yonghong, struct members
>    1940                  * should be all in register or all on the stack.
>    1941                  * Meanwhile, the compiler will pass the argument on regs
>    1942                  * if the remaining regs can hold the argument.
>    1943                  *
>    1944                  * Disorder of the args can happen. For example:
>    1945                  *
>    1946                  * struct foo_struct {
>    1947                  *     long a;
>    1948                  *     int b;
>    1949                  * };
>    1950                  * int foo(char, char, char, char, char, struct foo_struct,
>    1951                  *         char);
>    1952                  *
>    1953                  * the arg1-5,arg7 will be passed by regs, and arg6 will
>    1954                  * by stack.
>    1955                  */
>    1956                 if (nr_regs + arg_regs > 6) {
> 
> first_off is not set on else path.  It's also in a loop so maybe there
> is some guarantee that we will hit an else path...
> 
>    1957                         /* copy function arguments from origin stack frame
>    1958                          * into current stack frame.
>    1959                          *
>    1960                          * The starting address of the arguments on-stack
>    1961                          * is:
>    1962                          *   rbp + 8(push rbp) +
>    1963                          *   8(return addr of origin call) +
>    1964                          *   8(return addr of the caller)
>    1965                          * which means: rbp + 24
>    1966                          */
>    1967                         for (j = 0; j < arg_regs; j++) {
>    1968                                 emit_ldx(prog, BPF_DW, BPF_REG_0, BPF_REG_FP,
>    1969                                          nr_stack_slots * 8 + 0x18);
>    1970                                 emit_stx(prog, BPF_DW, BPF_REG_FP, BPF_REG_0,
>    1971                                          -stack_size);
>    1972 
>    1973                                 if (!nr_stack_slots)
>    1974                                         first_off = stack_size;
>    1975                                 stack_size -= 8;
>    1976                                 nr_stack_slots++;
>    1977                         }
>    1978                 } else {
>    1979                         /* Only copy the arguments on-stack to current
>    1980                          * 'stack_size' and ignore the regs, used to
>    1981                          * prepare the arguments on-stack for orign call.
>    1982                          */
>    1983                         if (for_call_origin) {
>    1984                                 nr_regs += arg_regs;
>    1985                                 continue;
>    1986                         }
>    1987 
>    1988                         /* copy the arguments from regs into stack */
>    1989                         for (j = 0; j < arg_regs; j++) {
>    1990                                 emit_stx(prog, BPF_DW, BPF_REG_FP,
>    1991                                          nr_regs == 5 ? X86_REG_R9 : BPF_REG_1 + nr_regs,
>    1992                                          -stack_size);
>    1993                                 stack_size -= 8;
>    1994                                 nr_regs++;
>    1995                         }
>    1996                 }
>    1997         }
>    1998 
> --> 1999         clean_stack_garbage(m, prog, nr_stack_slots, first_off);
>    2000 }

Hello,

Thanks for the reporting. The variable ‘first_off’ that passed to
clean_stack_garbage() should be ok, as it is only used when
"nr_stack_slots == 1”, in which case “first_off” should already be
initialized.

(Anyway, maybe we should initialize it to avoid passing a
uninitialized variable to a function?)

Thanks!
Menglong Dong


> regards,
> dan carpenter
> 






[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