Re: using "BPF_MAP_TYPE_DEVMAP" when pinning it to a global path

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

 



On Tue, Jul 27, 2021 at 8:05 PM G <chapterk93@xxxxxxx> wrote:
>
> Hi BPF Experts
>
> I'm having an issue with using "BPF_MAP_TYPE_DEVMAP" when pinning it to a global path for sharing with multiple programs.
> I used iproute2 to load the program, the parameters for creating a map are as follows:
> ----------------------------------------------------------------------------------
>     struct bpf_elf_map BPFM_SEC_MAPS dev_map_test = {
>         .type                = BPF_MAP_TYPE_DEVMAP,
>         .size_key       = sizeof(int32),
>         .size_value   = sizeof(int32),
>         .max_elem   = 1,
>         .flags               = 0,
>         .pinning         = PIN_GLOBAL_NS,
>     };
> ----------------------------------------------------------------------------------
>
> Here I set the flags to 0, but the actual map is created with flags 0x80, so when the second program is loaded, map parameter check is incorrect.
> When I tried to set the flags directly to 0x80, I failed with the parameter error `-EINVA`  when the first program was loaded
> The general process for iproute2 to create a map with a pin tag is as follows:
> -----------------------------------------------------------------------------------
> bpf_map_attach
> -> bpf_probe_pinned
>     bpf_map_selfcheck_pinned
>     -> bpf_derive_elf_map_from_fdinfo
>          bpf_map_pin_report
>          -> if (obj->flags != pin->flags)
>                    fprintf(stderr, " - Flags:        %#x (obj) != %#x (pin)\n", obj->flags, pin->flags);
> -----------------------------------------------------------------------------------
>
> I have tried to read the relevant kernel code :
> -----------------------------------------------------------------------------------
>     // kernel/bpf/devmap.c
>     #define DEV_CREATE_FLAG_MASK \
>          (BPF_F_NUMA_NODE | BPF_F_RDONLY | BPF_F_WRONLY)
>
>     static int dev_map_init_map(struct bpf_dtab *dtab, union bpf_attr *attr)
>     {
>        ...
>         /* check sanity of attributes */
>         if (attr->max_entries == 0 || attr->key_size != 4 ||
>                 attr->value_size != 4 || attr->map_flags & ~DEV_CREATE_FLAG_MASK)
>                 return -EINVAL;
>
>         /* Lookup returns a pointer straight to dev->ifindex, so make sure the
>          * verifier prevents writes from the BPF side
>          */
>         attr->map_flags |= BPF_F_RDONLY_PROG;
>         ...
>     }
> -----------------------------------------------------------------------------------
>
> At the time of check , it does not allow 0x80 to be set (DEV_CREATE_FLAG_MASK) , but then the code sets the 0x80 flag itself.

It looks like the kernel itself is setting the flags to 0x80 when it
initializes a devmap[1]. (Note: BPF_PROG_READONLY is 0x80.[2])

I believe you do not need to worry about setting this flag when you call the
BPF_MAP_CREATE syscall.

[1] https://elixir.bootlin.com/linux/v5.13.5/source/kernel/bpf/devmap.c#L126
[2] https://elixir.bootlin.com/linux/v5.13.5/source/include/uapi/linux/bpf.h#L1179

> So I'm not sure if we should allow 0x80 on the check here as well ? If anyone has suggestions please let me know, thanks.
> -----------------------------------------------------------------------------------
>     #define DEV_CREATE_FLAG_MASK \
>          (BPF_F_NUMA_NODE | BPF_F_RDONLY | BPF_F_WRONLY | BPF_F_RDONLY_PROG)
> -----------------------------------------------------------------------------------
>
> Best regards
> W.Gao



[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