Skip to content

Commit 27dfe16

Browse files
d-e-s-odanielocfb
authored andcommitted
libbpf-cargo: Don't provide kconfig data access after "open"
The .kconfig section is special in that libbpf sets its values as part of the load procedure. That means that until then, i.e., during open, contents are invalid. To that end the library doesn't even set the mmap pointer to anything but NULL, despite all heuristics pointing at it being mmapable and whatnot. That's a problem for us, because we generate section contents and attempt to have them reference this nonexistent mmap area, which will fail. Work around the issue by special casing this section and not emitting data access functionality for the OpenMaps type. Closes: #909 Signed-off-by: Daniel Müller <[email protected]>
1 parent c38b01a commit 27dfe16

File tree

2 files changed

+57
-29
lines changed

2 files changed

+57
-29
lines changed

libbpf-cargo/CHANGELOG.md

+5
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,8 @@
1+
Unreleased
2+
----------
3+
- Fixed panic on "open" of skeleton with `kconfig` map
4+
5+
16
0.24.1
27
------
38
- Fixed missing BPF object cleanup after skeleton destruction

libbpf-cargo/src/gen/mod.rs

+52-29
Original file line numberDiff line numberDiff line change
@@ -46,6 +46,14 @@ use crate::metadata::UnprocessedObj;
4646
use self::btf::GenBtf;
4747
use self::btf::GenStructOps;
4848

49+
50+
/// Name of the `.kconfig` map.
51+
///
52+
/// It requires special treatment because `libbpf` doesn't set the
53+
/// corresponding mmap pointer during "open", only as part of "load".
54+
const MAP_NAME_KCONFIG: &str = "kconfig";
55+
56+
4957
/// Escape certain characters in a "raw" name of a section, for example.
5058
fn escape_raw_name(name: &str) -> String {
5159
name.replace('.', "_")
@@ -82,15 +90,20 @@ impl Display for InternalMapType<'_> {
8290
/// Meta-data about a BPF map.
8391
enum MapMeta {
8492
NonDatasec,
85-
Datasec { mmap_idx: usize, read_only: bool },
93+
Datasec {
94+
mmap_idx: usize,
95+
read_only: bool,
96+
not_openable: bool,
97+
},
8698
}
8799

88100
impl MapMeta {
89-
fn new(idx: usize, map: &Map<'_>) -> Self {
101+
fn new(name: &str, idx: usize, map: &Map<'_>) -> Self {
90102
if map_is_datasec(map) {
91103
Self::Datasec {
92104
mmap_idx: idx,
93105
read_only: map_is_readonly(map),
106+
not_openable: name == MAP_NAME_KCONFIG,
94107
}
95108
} else {
96109
Self::NonDatasec
@@ -124,8 +137,8 @@ impl MapData {
124137

125138
let slf = Self {
126139
raw_name,
140+
meta: MapMeta::new(&name, idx, map),
127141
name,
128-
meta: MapMeta::new(idx, map),
129142
};
130143
Ok(Some(slf))
131144
}
@@ -399,17 +412,24 @@ fn gen_skel_map_defs(
399412
name = map.name
400413
)?;
401414

402-
if let MapMeta::Datasec { read_only, .. } = map.meta {
403-
// After "open" all maps are writable. That's the point,
404-
// they can be modified.
405-
let ref_mut = if open || !read_only { " mut" } else { "" };
406-
write!(
407-
skel,
408-
"\
409-
pub {name}_data: &'obj{ref_mut} types::{name},
410-
",
411-
name = map.name,
412-
)?;
415+
if let MapMeta::Datasec {
416+
read_only,
417+
not_openable,
418+
..
419+
} = map.meta
420+
{
421+
if !(open && not_openable) {
422+
// After "open" all maps are writable. That's the point,
423+
// they can be modified.
424+
let ref_mut = if open || !read_only { " mut" } else { "" };
425+
write!(
426+
skel,
427+
"\
428+
pub {name}_data: &'obj{ref_mut} types::{name},
429+
",
430+
name = map.name,
431+
)?;
432+
}
413433
}
414434
}
415435

@@ -486,23 +506,26 @@ fn gen_skel_map_defs(
486506
if let MapMeta::Datasec {
487507
mmap_idx,
488508
read_only,
509+
not_openable,
489510
} = map.meta
490511
{
491-
let ref_conv = if open || !read_only { "mut" } else { "ref" };
492-
write!(
493-
skel,
494-
"\
495-
{name}_data: unsafe {{
496-
config
497-
.map_mmap_ptr({mmap_idx})
498-
.expect(\"BPF map `{name}` does not have mmap pointer\")
499-
.cast::<types::{name}>()
500-
.as_{ref_conv}()
501-
.expect(\"BPF map `{name}` mmap pointer is NULL\")
502-
}},
503-
",
504-
name = map.name,
505-
)?;
512+
if !(open && not_openable) {
513+
let ref_conv = if open || !read_only { "mut" } else { "ref" };
514+
write!(
515+
skel,
516+
"\
517+
{name}_data: unsafe {{
518+
config
519+
.map_mmap_ptr({mmap_idx})
520+
.expect(\"BPF map `{name}` does not have mmap pointer\")
521+
.cast::<types::{name}>()
522+
.as_{ref_conv}()
523+
.expect(\"BPF map `{name}` mmap pointer is NULL\")
524+
}},
525+
",
526+
name = map.name,
527+
)?;
528+
}
506529
}
507530
}
508531

0 commit comments

Comments
 (0)