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]

 



Thank you for your answer. Maybe my description is not clear. 

If we set the flag to 0 when we first create the map, it is ok.

If flag is set to 0x80 when the map is created for the first time, an error will occur. The information is as follows, and the error code is  `-EINVA` 
-------------------------------------------------------------------------------

<errout: Map object 'test_redirect' rejected: Invalid argument (22)!
 - Type:         14
 - Identifier:   0
 - Pinning:      2
 - Size key:     4
 - Size value:   4
 - Max elems:    1
 - Flags:        0x80     

Error loading maps into kernel!
Error fetching ELF ancillary data!

-----------------------------------------------------------------------------


If I set the flag to 0 the first time, the map can be created successfully, but when I load the second program, I get a check error.
This is because iproute2 will verify that the parameters of the maps with the pin tag 
-----------------------------------------------------------------------------
<errout: Map specification differs from pinned file!
 - Flags:        0 (obj) != 0x80 (pin)

Map 'test_redirect' self-check failed!
Error loading maps into kernel!
Error fetching ELF ancillary data!
----------------------------------------------------------------------------



The kernel version of my test environment was 5. 4. But I looked at the latest code and the validation logic here is the same
----------------------------------------------------------------------------


    // 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)  //  <---  here, failure occurs when flag is set to 0x80
    		return -EINVAL;


         attr->map_flags |= BPF_F_RDONLY_PROG;
----------------------------------------------------------------------------








At 2021-07-29 02:01:00, "Zvi Effron" <zeffron@xxxxxxxxxxxxx> wrote:
>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