Skip to content

Commit 11aeff6

Browse files
manninglucasgvisor-bot
authored andcommitted
Fix host-backed event FD restore.
Before this change, host-backed event FDs would always crash the sandbox during exit when the sentry tried to wait on the fdnotifier for an FD that wasn't there. PiperOrigin-RevId: 736585573
1 parent 06f2254 commit 11aeff6

File tree

3 files changed

+63
-1
lines changed

3 files changed

+63
-1
lines changed

pkg/sentry/fsimpl/eventfd/BUILD

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,10 @@ licenses(["notice"])
66

77
go_library(
88
name = "eventfd",
9-
srcs = ["eventfd.go"],
9+
srcs = [
10+
"eventfd.go",
11+
"save_restore.go",
12+
],
1013
visibility = ["//pkg/sentry:internal"],
1114
deps = [
1215
"//pkg/abi/linux",

pkg/sentry/fsimpl/eventfd/eventfd.go

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -58,6 +58,12 @@ type EventFileDescription struct {
5858

5959
// hostfd indicates whether this eventfd is passed through to the host.
6060
hostfd int
61+
62+
// sentryOwnedHostfd indicates whether the sentry owns the hostfd.
63+
sentryOwnedHostfd bool
64+
65+
// hostfdState is the state of the hostfd during save/restore.
66+
hostfdState [8]byte
6167
}
6268

6369
var _ vfs.FileDescriptionImpl = (*EventFileDescription)(nil)
@@ -127,6 +133,7 @@ func (efd *EventFileDescription) HostFD() (int, error) {
127133
}
128134

129135
efd.hostfd = int(fd)
136+
efd.sentryOwnedHostfd = true
130137
return efd.hostfd, nil
131138
}
132139

@@ -140,6 +147,7 @@ func (efd *EventFileDescription) Release(context.Context) {
140147
log.Warningf("close(%d) eventfd failed: %v", efd.hostfd, closeErr)
141148
}
142149
efd.hostfd = -1
150+
efd.sentryOwnedHostfd = false
143151
}
144152
}
145153

Lines changed: 51 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,51 @@
1+
// Copyright 2025 The gVisor Authors.
2+
//
3+
// Licensed under the Apache License, Version 2.0 (the "License");
4+
// you may not use this file except in compliance with the License.
5+
// You may obtain a copy of the License at
6+
//
7+
// http://www.apache.org/licenses/LICENSE-2.0
8+
//
9+
// Unless required by applicable law or agreed to in writing, software
10+
// distributed under the License is distributed on an "AS IS" BASIS,
11+
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12+
// See the License for the specific language governing permissions and
13+
// limitations under the License.
14+
15+
package eventfd
16+
17+
import (
18+
"context"
19+
20+
"golang.org/x/sys/unix"
21+
"gvisor.dev/gvisor/pkg/log"
22+
)
23+
24+
func (efd *EventFileDescription) beforeSave() {
25+
if efd.hostfd < 0 {
26+
return
27+
}
28+
if !efd.sentryOwnedHostfd {
29+
panic("EventFileDescription.beforeSave: hostfd is not owned by the sentry")
30+
}
31+
var buf [8]byte
32+
if _, err := unix.Read(efd.hostfd, buf[:]); err != nil {
33+
log.Warningf("Failed to read host fd for eventfd: %v", err)
34+
return
35+
}
36+
copy(efd.hostfdState[:], buf[:])
37+
}
38+
39+
func (efd *EventFileDescription) afterLoad(ctx context.Context) {
40+
if efd.hostfd < 0 {
41+
return
42+
}
43+
efd.hostfd = -1
44+
if _, err := efd.HostFD(); err != nil {
45+
log.Warningf("Failed to create host fd for eventfd: %v", err)
46+
return
47+
}
48+
if _, err := unix.Write(efd.hostfd, efd.hostfdState[:]); err != nil {
49+
log.Warningf("Failed to write host fd for eventfd: %v", err)
50+
}
51+
}

0 commit comments

Comments
 (0)