lists.openwall.net | lists / announce owl-users owl-dev john-users john-dev passwdqc-users yescrypt popa3d-users / oss-security kernel-hardening musl sabotage tlsify passwords / crypt-dev xvendor / Bugtraq Full-Disclosure linux-kernel linux-netdev linux-ext4 linux-hardening linux-cve-announce PHC | |
Open Source and information security mailing list archives
| ||
|
Message-ID: <f1b4a42e-12da-1a40-60c9-cc81c8926e40@iogearbox.net> Date: Fri, 1 Mar 2019 01:19:12 +0100 From: Daniel Borkmann <daniel@...earbox.net> To: Stanislav Fomichev <sdf@...ichev.me> Cc: ast@...com, bpf@...r.kernel.org, netdev@...r.kernel.org, joe@...d.net.nz, john.fastabend@...il.com, tgraf@...g.ch, yhs@...com, andriin@...com, jakub.kicinski@...ronome.com, lmb@...udflare.com Subject: Re: [PATCH bpf-next v2 5/7] bpf, libbpf: support global data/bss/rodata sections On 03/01/2019 12:41 AM, Stanislav Fomichev wrote: > On 03/01, Daniel Borkmann wrote: >> This work adds BPF loader support for global data sections >> to libbpf. This allows to write BPF programs in more natural >> C-like way by being able to define global variables and const >> data. >> >> Back at LPC 2018 [0] we presented a first prototype which >> implemented support for global data sections by extending BPF >> syscall where union bpf_attr would get additional memory/size >> pair for each section passed during prog load in order to later >> add this base address into the ldimm64 instruction along with >> the user provided offset when accessing a variable. Consensus >> from LPC was that for proper upstream support, it would be >> more desirable to use maps instead of bpf_attr extension as >> this would allow for introspection of these sections as well >> as potential life updates of their content. This work follows >> this path by taking the following steps from loader side: >> >> 1) In bpf_object__elf_collect() step we pick up ".data", >> ".rodata", and ".bss" section information. >> >> 2) If present, in bpf_object__init_global_maps() we create >> a map that corresponds to each of the present sections. >> Given section size and access properties can differ, a >> single entry array map is created with value size that >> is corresponding to the ELF section size of .data, .bss >> or .rodata. In the latter case, the map is created as >> read-only from program side such that verifier rejects >> any write attempts into .rodata. In a subsequent step, >> for .data and .rodata sections, the section content is >> copied into the map through bpf_map_update_elem(). For >> .bss this is not necessary since array map is already >> zero-initialized by default. >> >> 3) In bpf_program__collect_reloc() step, we record the >> corresponding map, insn index, and relocation type for >> the global data. >> >> 4) And last but not least in the actual relocation step in >> bpf_program__relocate(), we mark the ldimm64 instruction >> with src_reg = BPF_PSEUDO_MAP_VALUE where in the first >> imm field the map's file descriptor is stored as similarly >> done as in BPF_PSEUDO_MAP_FD, and in the second imm field >> (as ldimm64 is 2-insn wide) we store the access offset >> into the section. >> >> 5) On kernel side, this special marked BPF_PSEUDO_MAP_VALUE >> load will then store the actual target address in order >> to have a 'map-lookup'-free access. That is, the actual >> map value base address + offset. The destination register >> in the verifier will then be marked as PTR_TO_MAP_VALUE, >> containing the fixed offset as reg->off and backing BPF >> map as reg->map_ptr. Meaning, it's treated as any other >> normal map value from verification side, only with >> efficient, direct value access instead of actual call to >> map lookup helper as in the typical case. >> >> Simple example dump of program using globals vars in each >> section: >> >> # readelf -a test_global_data.o >> [...] >> [ 6] .bss NOBITS 0000000000000000 00000328 >> 0000000000000010 0000000000000000 WA 0 0 8 >> [ 7] .data PROGBITS 0000000000000000 00000328 >> 0000000000000010 0000000000000000 WA 0 0 8 >> [ 8] .rodata PROGBITS 0000000000000000 00000338 >> 0000000000000018 0000000000000000 A 0 0 8 >> [...] >> 95: 0000000000000000 8 OBJECT LOCAL DEFAULT 6 static_bss >> 96: 0000000000000008 8 OBJECT LOCAL DEFAULT 6 static_bss2 >> 97: 0000000000000000 8 OBJECT LOCAL DEFAULT 7 static_data >> 98: 0000000000000008 8 OBJECT LOCAL DEFAULT 7 static_data2 >> 99: 0000000000000000 8 OBJECT LOCAL DEFAULT 8 static_rodata >> 100: 0000000000000008 8 OBJECT LOCAL DEFAULT 8 static_rodata2 >> 101: 0000000000000010 8 OBJECT LOCAL DEFAULT 8 static_rodata3 >> [...] >> >> # bpftool prog >> 103: sched_cls name load_static_dat tag 37a8b6822fc39a29 gpl >> loaded_at 2019-02-28T02:02:35+0000 uid 0 >> xlated 712B jited 426B memlock 4096B map_ids 63,64,65,66 >> # bpftool map show id 63 >> 63: array name .bss flags 0x0 <-- .bss area, rw > Can we use <main prog>.bss/data/rodata names? If we load more than one > prog with global data that should make it easier to find which one is which. Yeah that's fine, we can change it. They could potentially also be shared, so <main prog>.bss/data/rodata might be misleading, but <obj>.bss/data/rodata could be. Thanks, Daniel
Powered by blists - more mailing lists