How does NewMapFromFD() work? #1368
-
kernel 5.15 (Ubuntu 22.04 LTS) The godoc says not to reuse the original fd after calling it. Code inspection shows that a I understand that interacting with maps from userspace involves referencing a fd help open by the process. So therefore, I expect that the godoc for In this code, I expected a fail at L32, but instead I get a fail at L35. strace doesn't show a close or dup call, except there is a close where cilium is creating a What happened to the close from NewMapFromFD()? This should have occurred in package main
import (
"fmt"
"log"
"github.com/cilium/ebpf"
)
func main() {
key := uint32(0)
val := uint32(0)
spec := ebpf.MapSpec{
Name: "test_map",
Type: ebpf.LRUHash,
KeySize: 4,
ValueSize: 4,
MaxEntries: uint32(4096),
}
hashMap, err := ebpf.NewMap(&spec)
if err != nil {
log.Fatalln("Could not create map:", err)
}
fd := hashMap.FD()
fmt.Println(fd)
newMap, err := ebpf.NewMapFromFD(fd)
if err != nil {
log.Fatalln(err)
}
fmt.Println(hashMap.FD())
if err := hashMap.Update(&key, &val, ebpf.UpdateNoExist); err != nil {
log.Fatalln(err) // expected fail here due to referencing an old fd
}
if err := newMap.Update(&key, &val, ebpf.UpdateNoExist); err != nil {
log.Fatalln(err) // got EEXIST here, as newMap also shares fd 3.
}
}
|
Beta Was this translation helpful? Give feedback.
Replies: 1 comment 1 reply
-
@notrobpike Scratch what I said about NewMapFromFD calling The reason we warn the caller about not reusing a raw fd after passing it into e.g. |
Beta Was this translation helpful? Give feedback.
@notrobpike Scratch what I said about NewMapFromFD calling
dup()
andclose()
, I didn't have the code in front of me. We have a few abstractions that take a raw fd from the caller and dup() it, but I can't find any cases where we close a user-provided fd.The reason we warn the caller about not reusing a raw fd after passing it into e.g.
NewMapFromFD()
is that the underlying fd becomes bound to the lifecycle of the*Map
from there on out. If the Map gets garbage collected or explicitlyClose()
d, that will invalidate the original fd.