Skip to content

Commit

Permalink
map: remove MapSpec.Freeze field
Browse files Browse the repository at this point in the history
This has been an ambiguous flag since its inception. Internally, we would allow
maps to be created with BPF_F_RDONLY_PROG, but not freeze them afterwards.
Conversely, we would allow MapSpecs with Freeze set to 'true', but without the
rdonly map flag set.

The latter case has caused subtle bugs in the past, since BPF_MAP_FREEZE only
blocks further modifications from user space, but doesn't actually mark the map
as readonly for the verifier. This will prevent code pruning and other optimizations
from taking place.

This commit removes the Freeze field in favor of the map flag and adds a helper to
keep existing call sites simple. Sourcegraph code search yields no references to
this field in open-source code.

Signed-off-by: Timo Beckers <timo@isovalent.com>
  • Loading branch information
ti-mo committed Sep 3, 2024
1 parent efd05a7 commit acb5729
Show file tree
Hide file tree
Showing 4 changed files with 13 additions and 11 deletions.
8 changes: 5 additions & 3 deletions elf_reader.go
Original file line number Diff line number Diff line change
Expand Up @@ -200,6 +200,10 @@ func loadVersion(sec *elf.Section, bo binary.ByteOrder) (uint32, error) {
return version, nil
}

func isConstantDataSection(name string) bool {
return strings.HasPrefix(name, ".rodata")
}

type elfSectionKind int

const (
Expand Down Expand Up @@ -1137,9 +1141,8 @@ func (ec *elfCode) loadDataSections() error {
}
}

if strings.HasPrefix(sec.Name, ".rodata") {
if isConstantDataSection(sec.Name) {
mapSpec.Flags = sys.BPF_F_RDONLY_PROG
mapSpec.Freeze = true
}

ec.maps[sec.Name] = mapSpec
Expand Down Expand Up @@ -1175,7 +1178,6 @@ func (ec *elfCode) loadKconfigSection() error {
ValueSize: ds.Size,
MaxEntries: 1,
Flags: sys.BPF_F_RDONLY_PROG,
Freeze: true,
Key: &btf.Int{Size: 4},
Value: ds,
}
Expand Down
2 changes: 1 addition & 1 deletion elf_reader_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -491,7 +491,7 @@ func TestStringSection(t *testing.T) {
t.Fatal("Unable to find map '.rodata.str1.1' in loaded collection")
}

if !strMap.Freeze {
if !strMap.readOnly() {
t.Fatal("Read only data maps should be frozen")
}

Expand Down
11 changes: 6 additions & 5 deletions map.go
Original file line number Diff line number Diff line change
Expand Up @@ -73,9 +73,6 @@ type MapSpec struct {
// The initial contents of the map. May be nil.
Contents []MapKV

// Whether to freeze a map after setting its initial contents.
Freeze bool

// InnerMap is used as a template for ArrayOfMaps and HashOfMaps
InnerMap *MapSpec

Expand Down Expand Up @@ -190,6 +187,10 @@ func (ms *MapSpec) dataSection() ([]byte, *btf.Datasec, error) {
return value, ds, nil
}

func (ms *MapSpec) readOnly() bool {
return (ms.Flags & sys.BPF_F_RDONLY_PROG) > 0
}

// MapKV is used to initialize the contents of a Map.
type MapKV struct {
Key interface{}
Expand Down Expand Up @@ -484,7 +485,7 @@ func handleMapCreateError(attr sys.MapCreateAttr, spec *MapSpec, err error) erro
return fmt.Errorf("map create: %w", haveFeatErr)
}
}
if spec.Flags&(sys.BPF_F_RDONLY_PROG|sys.BPF_F_WRONLY_PROG) > 0 || spec.Freeze {
if spec.Flags&(sys.BPF_F_RDONLY_PROG|sys.BPF_F_WRONLY_PROG) > 0 {
if haveFeatErr := haveMapMutabilityModifiers(); haveFeatErr != nil {
return fmt.Errorf("map create: %w", haveFeatErr)
}
Expand Down Expand Up @@ -1400,7 +1401,7 @@ func (m *Map) finalize(spec *MapSpec) error {
}
}

if spec.Freeze {
if spec.readOnly() {
if err := m.Freeze(); err != nil {
return fmt.Errorf("freezing map: %w", err)
}
Expand Down
3 changes: 1 addition & 2 deletions map_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -104,8 +104,7 @@ func TestMapSpecCopy(t *testing.T) {
PinByName,
1,
[]MapKV{{1, 2}}, // Can't copy Contents, use value types
true,
nil, // InnerMap
nil, // InnerMap
bytes.NewReader(nil),
&btf.Int{},
&btf.Int{},
Expand Down

0 comments on commit acb5729

Please sign in to comment.