summaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
-rw-r--r--pkg/sentry/strace/BUILD1
-rw-r--r--pkg/sentry/strace/capability.go176
-rw-r--r--pkg/sentry/strace/linux64.go4
-rw-r--r--pkg/sentry/strace/strace.go67
-rw-r--r--pkg/sentry/strace/syscalls.go11
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