summaryrefslogtreecommitdiffhomepage
path: root/pkg/sentry/syscalls/linux/sys_socket.go
diff options
context:
space:
mode:
authorRahat Mahmood <rahat@google.com>2019-06-13 17:23:35 -0700
committerShentubot <shentubot@google.com>2019-06-13 17:24:51 -0700
commit05ff1ffaadaa0ac370365eb14febc761506735ce (patch)
treee6505afe1536c60c7a2e362aa8355e01ec34f91a /pkg/sentry/syscalls/linux/sys_socket.go
parent7b0f068258146b4081060ae793ba6b73399f1452 (diff)
Implement getsockopt() SO_DOMAIN, SO_PROTOCOL and SO_TYPE.
SO_TYPE was already implemented for everything but netlink sockets. PiperOrigin-RevId: 253138157
Diffstat (limited to 'pkg/sentry/syscalls/linux/sys_socket.go')
-rw-r--r--pkg/sentry/syscalls/linux/sys_socket.go32
1 files changed, 31 insertions, 1 deletions
diff --git a/pkg/sentry/syscalls/linux/sys_socket.go b/pkg/sentry/syscalls/linux/sys_socket.go
index 4e3c682ed..ccdb079bb 100644
--- a/pkg/sentry/syscalls/linux/sys_socket.go
+++ b/pkg/sentry/syscalls/linux/sys_socket.go
@@ -29,6 +29,7 @@ import (
"gvisor.dev/gvisor/pkg/sentry/socket/control"
"gvisor.dev/gvisor/pkg/sentry/socket/unix/transport"
"gvisor.dev/gvisor/pkg/sentry/usermem"
+ "gvisor.dev/gvisor/pkg/syserr"
"gvisor.dev/gvisor/pkg/syserror"
)
@@ -61,6 +62,8 @@ const controlLenOffset = 40
// to the Flags field.
const flagsOffset = 48
+const sizeOfInt32 = 4
+
// messageHeader64Len is the length of a MessageHeader64 struct.
var messageHeader64Len = uint64(binary.Size(MessageHeader64{}))
@@ -466,7 +469,7 @@ func GetSockOpt(t *kernel.Task, args arch.SyscallArguments) (uintptr, *kernel.Sy
}
// Call syscall implementation then copy both value and value len out.
- v, e := s.GetSockOpt(t, int(level), int(name), int(optLen))
+ v, e := getSockOpt(t, s, int(level), int(name), int(optLen))
if e != nil {
return 0, nil, e.ToError()
}
@@ -487,6 +490,33 @@ func GetSockOpt(t *kernel.Task, args arch.SyscallArguments) (uintptr, *kernel.Sy
return 0, nil, nil
}
+// getSockOpt tries to handle common socket options, or dispatches to a specific
+// socket implementation.
+func getSockOpt(t *kernel.Task, s socket.Socket, level, name, len int) (interface{}, *syserr.Error) {
+ if level == linux.SOL_SOCKET {
+ switch name {
+ case linux.SO_TYPE, linux.SO_DOMAIN, linux.SO_PROTOCOL:
+ if len < sizeOfInt32 {
+ return nil, syserr.ErrInvalidArgument
+ }
+ }
+
+ switch name {
+ case linux.SO_TYPE:
+ _, skType, _ := s.Type()
+ return int32(skType), nil
+ case linux.SO_DOMAIN:
+ family, _, _ := s.Type()
+ return int32(family), nil
+ case linux.SO_PROTOCOL:
+ _, _, protocol := s.Type()
+ return int32(protocol), nil
+ }
+ }
+
+ return s.GetSockOpt(t, level, name, len)
+}
+
// SetSockOpt implements the linux syscall setsockopt(2).
//
// Note that unlike Linux, enabling SO_PASSCRED does not autobind the socket.