Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

map: unmarshaling silently ignores too small keys or values #1157

Closed
ti-mo opened this issue Oct 6, 2023 · 4 comments · Fixed by #1181
Closed

map: unmarshaling silently ignores too small keys or values #1157

ti-mo opened this issue Oct 6, 2023 · 4 comments · Fixed by #1181
Labels
bug Something isn't working

Comments

@ti-mo
Copy link
Collaborator

ti-mo commented Oct 6, 2023

Describe the bug
Map.BatchLookup fails silently if nextKey is undersized, leaving nextKey with a zero value.

To Reproduce

package main

import (
	"errors"
	"log"

	"github.com/cilium/ebpf"
)

func main() {
	m, err := ebpf.NewMap(&ebpf.MapSpec{
		Type:       ebpf.LRUHash,
		KeySize:    8,
		ValueSize:  8,
		MaxEntries: 1_024_000,
	})
	if err != nil {
		log.Fatal(err)
	}
	defer m.Close()

	keys, values := make([]uint64, m.MaxEntries()), make([]uint64, m.MaxEntries())
	for i := 0; uint32(i) < m.MaxEntries(); i++ {
		keys[i] = uint64(i)
		values[i] = uint64(i)
	}

	count, err := m.BatchUpdate(keys, values, nil)
	if err != nil {
		log.Fatalf("BatchUpdate: %s", err)
	}
	log.Println("wrote", count, "entries")

	// Undersized nextKey. Only uint64 should be accepted here. (KeySize 8)
	// Should contain 1048576 at the end of program. uint32 works as well, as it
	// can represent up to 4.2B.
	var nextKey uint16

	keysOut, valuesOut := make([]uint64, m.MaxEntries()), make([]uint64, m.MaxEntries())
	count, err = m.BatchLookup(nil, &nextKey, keysOut, valuesOut, nil)
	if err != nil && !errors.Is(err, ebpf.ErrKeyNotExist) {
		log.Fatalf("BatchLookup: %s", err)
	}

	log.Printf("count: %d, nextKey: %d", count, nextKey)
}

Expected behavior

BatchLookup should fail with an unmarshaling error.

@ti-mo ti-mo added the bug Something isn't working label Oct 6, 2023
@devidasjadhav
Copy link

I can reproduced this.
Some of my findings:

  1. ebpf/map.go

    Line 919 in 3a926eb

    func (m *Map) BatchLookup(prevKey, nextKeyOut, keysOut, valuesOut interface{}, opts *BatchOptions) (int, error) {

nextKeyOut has no explicit type.

  1. As we are passing generic pointer so we cannot test this against m.keySize.

@ti-mo
Do you have any pointers on this ?

@lmb lmb self-assigned this Oct 10, 2023
@lmb
Copy link
Collaborator

lmb commented Oct 10, 2023

I'll see whether this was introduced by #1062.

P.S. Doesn't seem to be caused by the marshaling changes.

diff --git a/map_test.go b/map_test.go
index 2d3e4add..6d50e685 100644
--- a/map_test.go
+++ b/map_test.go
@@ -227,6 +227,36 @@ func TestBatchAPIHash(t *testing.T) {
 	}
 }
 
+func TestBatchLookupKeyTooSmall(t *testing.T) {
+	m, err := NewMap(&MapSpec{
+		Type:       LRUHash,
+		KeySize:    8,
+		ValueSize:  8,
+		MaxEntries: 10,
+	})
+	qt.Assert(t, err, qt.IsNil)
+	defer m.Close()
+
+	keys, values := make([]uint64, m.MaxEntries()), make([]uint64, m.MaxEntries())
+	for i := 0; uint32(i) < m.MaxEntries(); i++ {
+		keys[i] = uint64(i)
+		values[i] = uint64(i)
+	}
+
+	count, err := m.BatchUpdate(keys, values, nil)
+	qt.Assert(t, err, qt.IsNil)
+	t.Log("wrote", count, "entries")
+
+	// Undersized nextKey. Only uint64 should be accepted here. (KeySize 8)
+	// Should contain 1048576 at the end of program. uint32 works as well, as it
+	// can represent up to 4.2B.
+	var nextKey uint16
+
+	keysOut, valuesOut := make([]uint64, m.MaxEntries()), make([]uint64, m.MaxEntries())
+	_, err = m.BatchLookup(nil, &nextKey, keysOut, valuesOut, nil)
+	qt.Assert(t, err, qt.IsNotNil)
+}
+
 func TestBatchAPIMapDelete(t *testing.T) {
 	if err := haveBatchAPI(); err != nil {
 		t.Skipf("batch api not available: %v", err)

@lmb lmb removed their assignment Oct 10, 2023
@lmb
Copy link
Collaborator

lmb commented Oct 10, 2023

The problem is here somewhere most likely:

ebpf/map.go

Lines 985 to 993 in 9598c01

sysErr = wrapMapError(sysErr)
if sysErr != nil && !errors.Is(sysErr, unix.ENOENT) {
return 0, sysErr
}
err = nextBuf.Unmarshal(nextKeyOut)
if err != nil {
return 0, err
}

@lmb lmb changed the title Map.BatchLookup silently fails with undersized nextKey map: unmarshaling silenty ignores too small keys or values Oct 20, 2023
@lmb
Copy link
Collaborator

lmb commented Oct 20, 2023

This is actually not batch specific, it applies to all unmarshaling from map values.

lmb added a commit to lmb/ebpf that referenced this issue Oct 20, 2023
Unmarshal currently doesn't check that unmarshaling actually
consumes to full buffer. This means that looking uint16 from an
uint32 value doesn't return an error.

Fixes cilium#1157

Signed-off-by: Lorenz Bauer <lmb@isovalent.com>
lmb added a commit to lmb/ebpf that referenced this issue Oct 20, 2023
Unmarshal currently doesn't check that unmarshaling actually
consumes to full buffer. This means that looking uint16 from an
uint32 value doesn't return an error.

Fixes cilium#1157

Signed-off-by: Lorenz Bauer <lmb@isovalent.com>
lmb added a commit to lmb/ebpf that referenced this issue Oct 20, 2023
Unmarshal currently doesn't check that unmarshaling actually
consumes to full buffer. This means that looking uint16 from an
uint32 value doesn't return an error.

Fixes cilium#1157

Signed-off-by: Lorenz Bauer <lmb@isovalent.com>
@lmb lmb closed this as completed in #1181 Oct 20, 2023
lmb added a commit that referenced this issue Oct 20, 2023
Unmarshal currently doesn't check that unmarshaling actually
consumes to full buffer. This means that looking uint16 from an
uint32 value doesn't return an error.

Fixes #1157

Signed-off-by: Lorenz Bauer <lmb@isovalent.com>
@ti-mo ti-mo changed the title map: unmarshaling silenty ignores too small keys or values map: unmarshaling silently ignores too small keys or values Oct 24, 2023
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
bug Something isn't working
Projects
None yet
Development

Successfully merging a pull request may close this issue.

3 participants