Skip to content

Commit

Permalink
Port socket-related syscalls to VFS2.
Browse files Browse the repository at this point in the history
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 google#1476, google#1478, google#1484, google#1485.

PiperOrigin-RevId: 306292294
  • Loading branch information
Dean Deng authored and gvisor-bot committed Apr 13, 2020
1 parent aa75a3d commit 5d885d7
Show file tree
Hide file tree
Showing 6 changed files with 1,238 additions and 19 deletions.
55 changes: 55 additions & 0 deletions pkg/sentry/kernel/fd_table.go
Original file line number Diff line number Diff line change
Expand Up @@ -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) {
Expand Down
9 changes: 9 additions & 0 deletions pkg/sentry/kernel/task.go
Original file line number Diff line number Diff line change
Expand Up @@ -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.
Expand Down
9 changes: 8 additions & 1 deletion pkg/sentry/syscalls/linux/sys_socket.go
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,8 @@ import (
"gvisor.dev/gvisor/pkg/usermem"
)

// LINT.IfChange

// minListenBacklog is the minimum reasonable backlog for listening sockets.
const minListenBacklog = 8

Expand Down Expand Up @@ -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
}

Expand Down Expand Up @@ -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)
6 changes: 6 additions & 0 deletions pkg/sentry/syscalls/linux/vfs2/BUILD
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@ go_library(
"poll.go",
"read_write.go",
"setstat.go",
"socket.go",
"stat.go",
"stat_amd64.go",
"stat_arm64.go",
Expand All @@ -32,6 +33,7 @@ go_library(
visibility = ["//:sandbox"],
deps = [
"//pkg/abi/linux",
"//pkg/binary",
"//pkg/bits",
"//pkg/fspath",
"//pkg/gohacks",
Expand All @@ -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",
Expand Down
40 changes: 22 additions & 18 deletions pkg/sentry/syscalls/linux/vfs2/linux64_override_amd64.go
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down Expand Up @@ -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)
Expand All @@ -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)
Expand Down
Loading

0 comments on commit 5d885d7

Please sign in to comment.