Re: [PATCH bpf-next 0/2] error checking where helpers call bpf_map_ops

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

 



On Mon, Mar 20, 2023 at 7:19 AM Eduard Zingerman <eddyz87@xxxxxxxxx> wrote:
>
> On Fri, 2023-03-17 at 18:13 -0700, inwardvessel wrote:
> > From: JP Kobryn <inwardvessel@xxxxxxxxx>
> >
> > Within bpf programs, the bpf helper functions can make inline calls to
> > kernel functions. In this scenario there can be a disconnect between the
> > register the kernel function writes a return value to and the register the
> > bpf program uses to evaluate that return value.
> >
> > As an example, this bpf code:
> >
> > long err = bpf_map_update_elem(...);
> > if (err && err != -EEXIST)
> >       // got some error other than -EEXIST
> >
> > ...can result in the bpf assembly:
> >
> > ; err = bpf_map_update_elem(&mymap, &key, &val, BPF_NOEXIST);
> >   37: movabs $0xffff976a10730400,%rdi
> >   41: mov    $0x1,%ecx
> >   46: call   0xffffffffe103291c       ; htab_map_update_elem
> > ; if (err && err != -EEXIST) {
> >   4b: cmp    $0xffffffffffffffef,%rax ; cmp -EEXIST,%rax
> >   4f: je     0x000000000000008e
> >   51: test   %rax,%rax
> >   54: je     0x000000000000008e
> >
> > The compare operation here evaluates %rax, while in the preceding call to
> > htab_map_update_elem the corresponding assembly returns -EEXIST via %eax:
> >
> > movl $0xffffffef, %r9d
> > ...
> > movl %r9d, %eax
> >
> > ...since it's returning int (32-bit). So the resulting comparison becomes:
> >
> > cmp $0xffffffffffffffef, $0x00000000ffffffef
> >
> > ...making it not possible to check for negative errors or specific errors,
> > since the sign value is left at the 32nd bit. It means in the original
> > example, the conditional branch will be entered even when the error is
> > -EEXIST, which was not intended.
> >
> > The selftests added cover these cases for the different bpf_map_ops
> > functions. When the second patch is applied, changing the return type of
> > those functions to long, the comparison works as intended and the tests
> > pass.
> >
>
> Looks like this fixes commit from 2020:
> bdb7b79b4ce8 ("bpf: Switch most helper return values from 32-bit int to 64-bit long")
>
> To add to the summary: the issue is caused by the fact that test
> program uses map function definitions from `bpf_helper_defs.h`, e.g.:
>
>     static long (*bpf_map_update_elem)(...) 2;
>
> These definitions are generated from `include/uapi/linux/bpf.h`,
> which specifies the return type for this helper to be `long`
> (changed to from `int` in the commit mentioned above).
> That's why clang does not insert sign extension instructions when
> helper is called.

JP,

could you please add Ed's clarification to the commit log
and add 'Fixes: bdb7b79b4ce8 ...' tag and respin ?

>
> Interesting how this went under the radar for so long, probably
> because user code mostly uses `int` to catch return value of map
> functions.
>
> That commit changes return types for a lot of functions.
> I looked through function definitions and verifier.c code for those,
> but have not found any additional issues, except for two obvious:
> - bpf_redirect_map / ops->map_redirect
> - bpf_for_each_map_elem / ops->map_for_each_callback

Please fix these two as well in the same patch.

> Tested-By: Eduard Zingerman <eddyz87@xxxxxxxxx>

and please carry the Tested-by tag in the respin.

Thanks!




[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