diff options
Diffstat (limited to 'pkg/sentry')
-rw-r--r-- | pkg/sentry/strace/BUILD | 1 | ||||
-rw-r--r-- | pkg/sentry/strace/capability.go | 176 | ||||
-rw-r--r-- | pkg/sentry/strace/linux64.go | 4 | ||||
-rw-r--r-- | pkg/sentry/strace/strace.go | 67 | ||||
-rw-r--r-- | pkg/sentry/strace/syscalls.go | 11 |
5 files changed, 257 insertions, 2 deletions
diff --git a/pkg/sentry/strace/BUILD b/pkg/sentry/strace/BUILD index 552e79686..73f1e9814 100644 --- a/pkg/sentry/strace/BUILD +++ b/pkg/sentry/strace/BUILD @@ -6,6 +6,7 @@ package(licenses = ["notice"]) go_library( name = "strace", srcs = [ + "capability.go", "clone.go", "futex.go", "linux64.go", diff --git a/pkg/sentry/strace/capability.go b/pkg/sentry/strace/capability.go new file mode 100644 index 000000000..9001181e7 --- /dev/null +++ b/pkg/sentry/strace/capability.go @@ -0,0 +1,176 @@ +// Copyright 2019 Google LLC +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package strace + +import ( + "gvisor.googlesource.com/gvisor/pkg/abi" + "gvisor.googlesource.com/gvisor/pkg/abi/linux" +) + +// CapabilityBitset is the set of capabilties in a bitset. +var CapabilityBitset = abi.FlagSet{ + { + Flag: 1 << uint32(linux.CAP_CHOWN), + Name: "CAP_CHOWN", + }, + { + Flag: 1 << uint32(linux.CAP_DAC_OVERRIDE), + Name: "CAP_DAC_OVERRIDE", + }, + { + Flag: 1 << uint32(linux.CAP_DAC_READ_SEARCH), + Name: "CAP_DAC_READ_SEARCH", + }, + { + Flag: 1 << uint32(linux.CAP_FOWNER), + Name: "CAP_FOWNER", + }, + { + Flag: 1 << uint32(linux.CAP_FSETID), + Name: "CAP_FSETID", + }, + { + Flag: 1 << uint32(linux.CAP_KILL), + Name: "CAP_KILL", + }, + { + Flag: 1 << uint32(linux.CAP_SETGID), + Name: "CAP_SETGID", + }, + { + Flag: 1 << uint32(linux.CAP_SETUID), + Name: "CAP_SETUID", + }, + { + Flag: 1 << uint32(linux.CAP_SETPCAP), + Name: "CAP_SETPCAP", + }, + { + Flag: 1 << uint32(linux.CAP_LINUX_IMMUTABLE), + Name: "CAP_LINUX_IMMUTABLE", + }, + { + Flag: 1 << uint32(linux.CAP_NET_BIND_SERVICE), + Name: "CAP_NET_BIND_SERVICE", + }, + { + Flag: 1 << uint32(linux.CAP_NET_BROADCAST), + Name: "CAP_NET_BROADCAST", + }, + { + Flag: 1 << uint32(linux.CAP_NET_ADMIN), + Name: "CAP_NET_ADMIN", + }, + { + Flag: 1 << uint32(linux.CAP_NET_RAW), + Name: "CAP_NET_RAW", + }, + { + Flag: 1 << uint32(linux.CAP_IPC_LOCK), + Name: "CAP_IPC_LOCK", + }, + { + Flag: 1 << uint32(linux.CAP_IPC_OWNER), + Name: "CAP_IPC_OWNER", + }, + { + Flag: 1 << uint32(linux.CAP_SYS_MODULE), + Name: "CAP_SYS_MODULE", + }, + { + Flag: 1 << uint32(linux.CAP_SYS_RAWIO), + Name: "CAP_SYS_RAWIO", + }, + { + Flag: 1 << uint32(linux.CAP_SYS_CHROOT), + Name: "CAP_SYS_CHROOT", + }, + { + Flag: 1 << uint32(linux.CAP_SYS_PTRACE), + Name: "CAP_SYS_PTRACE", + }, + { + Flag: 1 << uint32(linux.CAP_SYS_PACCT), + Name: "CAP_SYS_PACCT", + }, + { + Flag: 1 << uint32(linux.CAP_SYS_ADMIN), + Name: "CAP_SYS_ADMIN", + }, + { + Flag: 1 << uint32(linux.CAP_SYS_BOOT), + Name: "CAP_SYS_BOOT", + }, + { + Flag: 1 << uint32(linux.CAP_SYS_NICE), + Name: "CAP_SYS_NICE", + }, + { + Flag: 1 << uint32(linux.CAP_SYS_RESOURCE), + Name: "CAP_SYS_RESOURCE", + }, + { + Flag: 1 << uint32(linux.CAP_SYS_TIME), + Name: "CAP_SYS_TIME", + }, + { + Flag: 1 << uint32(linux.CAP_SYS_TTY_CONFIG), + Name: "CAP_SYS_TTY_CONFIG", + }, + { + Flag: 1 << uint32(linux.CAP_MKNOD), + Name: "CAP_MKNOD", + }, + { + Flag: 1 << uint32(linux.CAP_LEASE), + Name: "CAP_LEASE", + }, + { + Flag: 1 << uint32(linux.CAP_AUDIT_WRITE), + Name: "CAP_AUDIT_WRITE", + }, + { + Flag: 1 << uint32(linux.CAP_AUDIT_CONTROL), + Name: "CAP_AUDIT_CONTROL", + }, + { + Flag: 1 << uint32(linux.CAP_SETFCAP), + Name: "CAP_SETFCAP", + }, + { + Flag: 1 << uint32(linux.CAP_MAC_OVERRIDE), + Name: "CAP_MAC_OVERRIDE", + }, + { + Flag: 1 << uint32(linux.CAP_MAC_ADMIN), + Name: "CAP_MAC_ADMIN", + }, + { + Flag: 1 << uint32(linux.CAP_SYSLOG), + Name: "CAP_SYSLOG", + }, + { + Flag: 1 << uint32(linux.CAP_WAKE_ALARM), + Name: "CAP_WAKE_ALARM", + }, + { + Flag: 1 << uint32(linux.CAP_BLOCK_SUSPEND), + Name: "CAP_BLOCK_SUSPEND", + }, + { + Flag: 1 << uint32(linux.CAP_AUDIT_READ), + Name: "CAP_AUDIT_READ", + }, +} diff --git a/pkg/sentry/strace/linux64.go b/pkg/sentry/strace/linux64.go index de2da9369..ca695e80f 100644 --- a/pkg/sentry/strace/linux64.go +++ b/pkg/sentry/strace/linux64.go @@ -142,8 +142,8 @@ var linuxAMD64 = SyscallMap{ 122: makeSyscallInfo("setfsuid", Hex), 123: makeSyscallInfo("setfsgid", Hex), 124: makeSyscallInfo("getsid", Hex), - 125: makeSyscallInfo("capget", Hex, Hex), - 126: makeSyscallInfo("capset", Hex, Hex), + 125: makeSyscallInfo("capget", CapHeader, PostCapData), + 126: makeSyscallInfo("capset", CapHeader, CapData), 127: makeSyscallInfo("rt_sigpending", Hex), 128: makeSyscallInfo("rt_sigtimedwait", SigSet, Hex, Timespec, Hex), 129: makeSyscallInfo("rt_sigqueueinfo", Hex, Signal, Hex), diff --git a/pkg/sentry/strace/strace.go b/pkg/sentry/strace/strace.go index da27a2ae8..6c93d7de7 100644 --- a/pkg/sentry/strace/strace.go +++ b/pkg/sentry/strace/strace.go @@ -271,6 +271,67 @@ func rusage(t *kernel.Task, addr usermem.Addr) string { return fmt.Sprintf("%#x %+v", addr, ru) } +func capHeader(t *kernel.Task, addr usermem.Addr) string { + if addr == 0 { + return "null" + } + + var hdr linux.CapUserHeader + if _, err := t.CopyIn(addr, &hdr); err != nil { + return fmt.Sprintf("%#x (error decoding header: %s)", addr, err) + } + + var version string + switch hdr.Version { + case linux.LINUX_CAPABILITY_VERSION_1: + version = "1" + case linux.LINUX_CAPABILITY_VERSION_2: + version = "2" + case linux.LINUX_CAPABILITY_VERSION_3: + version = "3" + default: + version = strconv.FormatUint(uint64(hdr.Version), 16) + } + + return fmt.Sprintf("%#x {Version: %s, Pid: %d}", addr, version, hdr.Pid) +} + +func capData(t *kernel.Task, hdrAddr, dataAddr usermem.Addr) string { + if dataAddr == 0 { + return "null" + } + + var hdr linux.CapUserHeader + if _, err := t.CopyIn(hdrAddr, &hdr); err != nil { + return fmt.Sprintf("%#x (error decoding header: %v)", dataAddr, err) + } + + var p, i, e uint64 + + switch hdr.Version { + case linux.LINUX_CAPABILITY_VERSION_1: + var data linux.CapUserData + if _, err := t.CopyIn(dataAddr, &data); err != nil { + return fmt.Sprintf("%#x (error decoding data: %v)", dataAddr, err) + } + p = uint64(data.Permitted) + i = uint64(data.Inheritable) + e = uint64(data.Effective) + case linux.LINUX_CAPABILITY_VERSION_2, linux.LINUX_CAPABILITY_VERSION_3: + var data [2]linux.CapUserData + if _, err := t.CopyIn(dataAddr, &data); err != nil { + return fmt.Sprintf("%#x (error decoding data: %v)", dataAddr, err) + } + p = uint64(data[0].Permitted) | (uint64(data[1].Permitted) << 32) + i = uint64(data[0].Inheritable) | (uint64(data[1].Inheritable) << 32) + e = uint64(data[0].Effective) | (uint64(data[1].Effective) << 32) + default: + return fmt.Sprintf("%#x (unknown version %d)", dataAddr, hdr.Version) + } + + return fmt.Sprintf("%#x {Permitted: %s, Inheritable: %s, Effective: %s}", dataAddr, CapabilityBitset.Parse(p), CapabilityBitset.Parse(i), CapabilityBitset.Parse(e)) +} + // pre fills in the pre-execution arguments for a system call. If an argument // cannot be interpreted before the system call is executed, then a hex value // will be used. Note that a full output slice will always be provided, that is @@ -341,6 +402,10 @@ func (i *SyscallInfo) pre(t *kernel.Task, args arch.SyscallArguments, maximumBlo output = append(output, sigSet(t, args[arg].Pointer())) case SigAction: output = append(output, sigAction(t, args[arg].Pointer())) + case CapHeader: + output = append(output, capHeader(t, args[arg].Pointer())) + case CapData: + output = append(output, capData(t, args[arg-1].Pointer(), args[arg].Pointer())) case Oct: output = append(output, "0o"+strconv.FormatUint(args[arg].Uint64(), 8)) case Hex: @@ -403,6 +468,8 @@ func (i *SyscallInfo) post(t *kernel.Task, args arch.SyscallArguments, rval uint output[arg] = sigSet(t, args[arg].Pointer()) case PostSigAction: output[arg] = sigAction(t, args[arg].Pointer()) + case PostCapData: + output[arg] = capData(t, args[arg-1].Pointer(), args[arg].Pointer()) } } } diff --git a/pkg/sentry/strace/syscalls.go b/pkg/sentry/strace/syscalls.go index 1ae982354..b2715856e 100644 --- a/pkg/sentry/strace/syscalls.go +++ b/pkg/sentry/strace/syscalls.go @@ -188,6 +188,17 @@ const ( // PostSigAction is a struct sigaction, formatted after syscall execution. PostSigAction + + // CapHeader is a cap_user_header_t. + CapHeader + + // CapData is the data argument to capget(2)/capset(2). The previous + // argument must be CapHeader. + CapData + + // PostCapData is the data argument to capget(2)/capset(2), formatted + // after syscall execution. The previous argument must be CapHeader. + PostCapData ) // defaultFormat is the syscall argument format to use if the actual format is |