Port socket-related syscalls to VFS2.
Note that most kinds of sockets are not yet supported in VFS2 (only Unix sockets are partially supported at the moment), so these syscalls will still generally fail. Enabling them allows us to begin running socket tests for VFS2 as more features are ported over. Updates #1476, #1478, #1484, #1485. PiperOrigin-RevId: 306292294
This commit is contained in:
parent
aa75a3da51
commit
5d885d7fb2
|
@ -307,6 +307,61 @@ func (f *FDTable) NewFDs(ctx context.Context, fd int32, files []*fs.File, flags
|
|||
return fds, nil
|
||||
}
|
||||
|
||||
// NewFDsVFS2 allocates new FDs guaranteed to be the lowest number available
|
||||
// greater than or equal to the fd parameter. All files will share the set
|
||||
// flags. Success is guaranteed to be all or none.
|
||||
func (f *FDTable) NewFDsVFS2(ctx context.Context, fd int32, files []*vfs.FileDescription, flags FDFlags) (fds []int32, err error) {
|
||||
if fd < 0 {
|
||||
// Don't accept negative FDs.
|
||||
return nil, syscall.EINVAL
|
||||
}
|
||||
|
||||
// Default limit.
|
||||
end := int32(math.MaxInt32)
|
||||
|
||||
// Ensure we don't get past the provided limit.
|
||||
if limitSet := limits.FromContext(ctx); limitSet != nil {
|
||||
lim := limitSet.Get(limits.NumberOfFiles)
|
||||
if lim.Cur != limits.Infinity {
|
||||
end = int32(lim.Cur)
|
||||
}
|
||||
if fd >= end {
|
||||
return nil, syscall.EMFILE
|
||||
}
|
||||
}
|
||||
|
||||
f.mu.Lock()
|
||||
defer f.mu.Unlock()
|
||||
|
||||
// From f.next to find available fd.
|
||||
if fd < f.next {
|
||||
fd = f.next
|
||||
}
|
||||
|
||||
// Install all entries.
|
||||
for i := fd; i < end && len(fds) < len(files); i++ {
|
||||
if d, _, _ := f.getVFS2(i); d == nil {
|
||||
f.setVFS2(i, files[len(fds)], flags) // Set the descriptor.
|
||||
fds = append(fds, i) // Record the file descriptor.
|
||||
}
|
||||
}
|
||||
|
||||
// Failure? Unwind existing FDs.
|
||||
if len(fds) < len(files) {
|
||||
for _, i := range fds {
|
||||
f.setVFS2(i, nil, FDFlags{}) // Zap entry.
|
||||
}
|
||||
return nil, syscall.EMFILE
|
||||
}
|
||||
|
||||
if fd == f.next {
|
||||
// Update next search start position.
|
||||
f.next = fds[len(fds)-1] + 1
|
||||
}
|
||||
|
||||
return fds, nil
|
||||
}
|
||||
|
||||
// NewFDVFS2 allocates a file descriptor greater than or equal to minfd for
|
||||
// the given file description. If it succeeds, it takes a reference on file.
|
||||
func (f *FDTable) NewFDVFS2(ctx context.Context, minfd int32, file *vfs.FileDescription, flags FDFlags) (int32, error) {
|
||||
|
|
|
@ -777,6 +777,15 @@ func (t *Task) NewFDs(fd int32, files []*fs.File, flags FDFlags) ([]int32, error
|
|||
return t.fdTable.NewFDs(t, fd, files, flags)
|
||||
}
|
||||
|
||||
// NewFDsVFS2 is a convenience wrapper for t.FDTable().NewFDsVFS2.
|
||||
//
|
||||
// This automatically passes the task as the context.
|
||||
//
|
||||
// Precondition: same as FDTable.
|
||||
func (t *Task) NewFDsVFS2(fd int32, files []*vfs.FileDescription, flags FDFlags) ([]int32, error) {
|
||||
return t.fdTable.NewFDsVFS2(t, fd, files, flags)
|
||||
}
|
||||
|
||||
// NewFDFrom is a convenience wrapper for t.FDTable().NewFDs with a single file.
|
||||
//
|
||||
// This automatically passes the task as the context.
|
||||
|
|
|
@ -31,6 +31,8 @@ import (
|
|||
"gvisor.dev/gvisor/pkg/usermem"
|
||||
)
|
||||
|
||||
// LINT.IfChange
|
||||
|
||||
// minListenBacklog is the minimum reasonable backlog for listening sockets.
|
||||
const minListenBacklog = 8
|
||||
|
||||
|
@ -244,7 +246,10 @@ func SocketPair(t *kernel.Task, args arch.SyscallArguments) (uintptr, *kernel.Sy
|
|||
|
||||
// Copy the file descriptors out.
|
||||
if _, err := t.CopyOut(socks, fds); err != nil {
|
||||
// Note that we don't close files here; see pipe(2) also.
|
||||
for _, fd := range fds {
|
||||
_, file := t.FDTable().Remove(fd)
|
||||
file.DecRef()
|
||||
}
|
||||
return 0, nil, err
|
||||
}
|
||||
|
||||
|
@ -1128,3 +1133,5 @@ func SendTo(t *kernel.Task, args arch.SyscallArguments) (uintptr, *kernel.Syscal
|
|||
n, err := sendTo(t, fd, bufPtr, bufLen, flags, namePtr, nameLen)
|
||||
return n, nil, err
|
||||
}
|
||||
|
||||
// LINT.ThenChange(./vfs2/socket.go)
|
||||
|
|
|
@ -21,6 +21,7 @@ go_library(
|
|||
"poll.go",
|
||||
"read_write.go",
|
||||
"setstat.go",
|
||||
"socket.go",
|
||||
"stat.go",
|
||||
"stat_amd64.go",
|
||||
"stat_arm64.go",
|
||||
|
@ -32,6 +33,7 @@ go_library(
|
|||
visibility = ["//:sandbox"],
|
||||
deps = [
|
||||
"//pkg/abi/linux",
|
||||
"//pkg/binary",
|
||||
"//pkg/bits",
|
||||
"//pkg/fspath",
|
||||
"//pkg/gohacks",
|
||||
|
@ -43,10 +45,14 @@ go_library(
|
|||
"//pkg/sentry/limits",
|
||||
"//pkg/sentry/loader",
|
||||
"//pkg/sentry/memmap",
|
||||
"//pkg/sentry/socket",
|
||||
"//pkg/sentry/socket/control",
|
||||
"//pkg/sentry/socket/unix/transport",
|
||||
"//pkg/sentry/syscalls",
|
||||
"//pkg/sentry/syscalls/linux",
|
||||
"//pkg/sentry/vfs",
|
||||
"//pkg/sync",
|
||||
"//pkg/syserr",
|
||||
"//pkg/syserror",
|
||||
"//pkg/usermem",
|
||||
"//pkg/waiter",
|
||||
|
|
|
@ -44,21 +44,22 @@ func Override(table map[uintptr]kernel.Syscall) {
|
|||
table[32] = syscalls.Supported("dup", Dup)
|
||||
table[33] = syscalls.Supported("dup2", Dup2)
|
||||
delete(table, 40) // sendfile
|
||||
delete(table, 41) // socket
|
||||
delete(table, 42) // connect
|
||||
delete(table, 43) // accept
|
||||
delete(table, 44) // sendto
|
||||
delete(table, 45) // recvfrom
|
||||
delete(table, 46) // sendmsg
|
||||
delete(table, 47) // recvmsg
|
||||
delete(table, 48) // shutdown
|
||||
delete(table, 49) // bind
|
||||
delete(table, 50) // listen
|
||||
delete(table, 51) // getsockname
|
||||
delete(table, 52) // getpeername
|
||||
delete(table, 53) // socketpair
|
||||
delete(table, 54) // setsockopt
|
||||
delete(table, 55) // getsockopt
|
||||
// TODO(gvisor.dev/issue/1485): Port all socket variants to VFS2.
|
||||
table[41] = syscalls.PartiallySupported("socket", Socket, "In process of porting socket syscalls to VFS2.", nil)
|
||||
table[42] = syscalls.PartiallySupported("connect", Connect, "In process of porting socket syscalls to VFS2.", nil)
|
||||
table[43] = syscalls.PartiallySupported("accept", Accept, "In process of porting socket syscalls to VFS2.", nil)
|
||||
table[44] = syscalls.PartiallySupported("sendto", SendTo, "In process of porting socket syscalls to VFS2.", nil)
|
||||
table[45] = syscalls.PartiallySupported("recvfrom", RecvFrom, "In process of porting socket syscalls to VFS2.", nil)
|
||||
table[46] = syscalls.PartiallySupported("sendmsg", SendMsg, "In process of porting socket syscalls to VFS2.", nil)
|
||||
table[47] = syscalls.PartiallySupported("recvmsg", RecvMsg, "In process of porting socket syscalls to VFS2.", nil)
|
||||
table[48] = syscalls.PartiallySupported("shutdown", Shutdown, "In process of porting socket syscalls to VFS2.", nil)
|
||||
table[49] = syscalls.PartiallySupported("bind", Bind, "In process of porting socket syscalls to VFS2.", nil)
|
||||
table[50] = syscalls.PartiallySupported("listen", Listen, "In process of porting socket syscalls to VFS2.", nil)
|
||||
table[51] = syscalls.PartiallySupported("getsockname", GetSockName, "In process of porting socket syscalls to VFS2.", nil)
|
||||
table[52] = syscalls.PartiallySupported("getpeername", GetPeerName, "In process of porting socket syscalls to VFS2.", nil)
|
||||
table[53] = syscalls.PartiallySupported("socketpair", SocketPair, "In process of porting socket syscalls to VFS2.", nil)
|
||||
table[54] = syscalls.PartiallySupported("getsockopt", GetSockOpt, "In process of porting socket syscalls to VFS2.", nil)
|
||||
table[55] = syscalls.PartiallySupported("setsockopt", SetSockOpt, "In process of porting socket syscalls to VFS2.", nil)
|
||||
table[59] = syscalls.Supported("execve", Execve)
|
||||
table[72] = syscalls.Supported("fcntl", Fcntl)
|
||||
delete(table, 73) // flock
|
||||
|
@ -144,7 +145,8 @@ func Override(table map[uintptr]kernel.Syscall) {
|
|||
delete(table, 285) // fallocate
|
||||
table[286] = syscalls.Supported("timerfd_settime", TimerfdSettime)
|
||||
table[287] = syscalls.Supported("timerfd_gettime", TimerfdGettime)
|
||||
delete(table, 288) // accept4
|
||||
// TODO(gvisor.dev/issue/1485): Port all socket variants to VFS2.
|
||||
table[288] = syscalls.PartiallySupported("accept4", Accept4, "In process of porting socket syscalls to VFS2.", nil)
|
||||
delete(table, 289) // signalfd4
|
||||
delete(table, 290) // eventfd2
|
||||
table[291] = syscalls.Supported("epoll_create1", EpollCreate1)
|
||||
|
@ -153,9 +155,11 @@ func Override(table map[uintptr]kernel.Syscall) {
|
|||
delete(table, 294) // inotify_init1
|
||||
table[295] = syscalls.Supported("preadv", Preadv)
|
||||
table[296] = syscalls.Supported("pwritev", Pwritev)
|
||||
delete(table, 299) // recvmmsg
|
||||
// TODO(gvisor.dev/issue/1485): Port all socket variants to VFS2.
|
||||
table[299] = syscalls.PartiallySupported("recvmmsg", RecvMMsg, "In process of porting socket syscalls to VFS2.", nil)
|
||||
table[306] = syscalls.Supported("syncfs", Syncfs)
|
||||
delete(table, 307) // sendmmsg
|
||||
// TODO(gvisor.dev/issue/1485): Port all socket variants to VFS2.
|
||||
table[307] = syscalls.PartiallySupported("sendmmsg", SendMMsg, "In process of porting socket syscalls to VFS2.", nil)
|
||||
table[316] = syscalls.Supported("renameat2", Renameat2)
|
||||
delete(table, 319) // memfd_create
|
||||
table[322] = syscalls.Supported("execveat", Execveat)
|
||||
|
|
File diff suppressed because it is too large
Load Diff
Loading…
Reference in New Issue