mirror of
https://github.com/netbirdio/gvisor.git
synced 2026-05-22 17:12:49 -07:00
Add Points to some syscalls
Added a raw syscall points to all syscalls. Added schematized syscall points to the following syscalls: - read - close - socket - connect - execve - creat - openat - execveat Updates #4805 PiperOrigin-RevId: 446008358
This commit is contained in:
committed by
gVisor bot
parent
87180c225b
commit
f2b6fbb47e
@@ -10,6 +10,36 @@
|
||||
},
|
||||
{
|
||||
"name": "sentry/task_exit"
|
||||
},
|
||||
{
|
||||
"name": "syscall/openat/enter"
|
||||
},
|
||||
{
|
||||
"name": "syscall/openat/exit"
|
||||
},
|
||||
{
|
||||
"name": "syscall/read/enter",
|
||||
"optional_fields": [
|
||||
"fd_path"
|
||||
],
|
||||
"context_fields": [
|
||||
"time",
|
||||
"container_id",
|
||||
"thread_id"
|
||||
]
|
||||
},
|
||||
{
|
||||
"name": "syscall/read/exit"
|
||||
},
|
||||
{
|
||||
"name": "syscall/sysno/1/enter",
|
||||
"context_fields": [
|
||||
"time",
|
||||
"container_id"
|
||||
]
|
||||
},
|
||||
{
|
||||
"name": "syscall/sysno/1/exit"
|
||||
}
|
||||
],
|
||||
"sinks": [
|
||||
|
||||
@@ -31,6 +31,7 @@
|
||||
#include "absl/strings/string_view.h"
|
||||
#include "pkg/sentry/seccheck/points/container.pb.h"
|
||||
#include "pkg/sentry/seccheck/points/sentry.pb.h"
|
||||
#include "pkg/sentry/seccheck/points/syscall.pb.h"
|
||||
|
||||
typedef std::function<void(const google::protobuf::Any& any)> Callback;
|
||||
|
||||
@@ -55,6 +56,22 @@ void log(const char* fmt, ...) {
|
||||
}
|
||||
}
|
||||
|
||||
template <class T>
|
||||
void unpackSyscall(const google::protobuf::Any& any) {
|
||||
T evt;
|
||||
if (!any.UnpackTo(&evt)) {
|
||||
err(1, "UnpackTo(): %s", any.DebugString().c_str());
|
||||
}
|
||||
auto last_dot = any.type_url().find_last_of('.');
|
||||
if (last_dot == std::string::npos) {
|
||||
err(1, "invalid name: %.*s", static_cast<int>(any.type_url().size()),
|
||||
any.type_url().data());
|
||||
}
|
||||
auto name = any.type_url().substr(last_dot + 1);
|
||||
log("%s %.*s %s\n", evt.has_exit() ? "X" : "E", static_cast<int>(name.size()),
|
||||
name.data(), evt.ShortDebugString().c_str());
|
||||
}
|
||||
|
||||
template <class T>
|
||||
void unpack(const google::protobuf::Any& any) {
|
||||
T evt;
|
||||
@@ -67,6 +84,13 @@ void unpack(const google::protobuf::Any& any) {
|
||||
}
|
||||
|
||||
std::map<std::string, Callback> dispatchers = {
|
||||
{"gvisor.syscall.Syscall", unpackSyscall<::gvisor::syscall::Syscall>},
|
||||
{"gvisor.syscall.Read", unpackSyscall<::gvisor::syscall::Read>},
|
||||
{"gvisor.syscall.Open", unpackSyscall<::gvisor::syscall::Open>},
|
||||
{"gvisor.syscall.Connect", unpackSyscall<::gvisor::syscall::Connect>},
|
||||
{"gvisor.syscall.Execve", unpackSyscall<::gvisor::syscall::Execve>},
|
||||
{"gvisor.syscall.Close", unpackSyscall<::gvisor::syscall::Close>},
|
||||
{"gvisor.syscall.Socket", unpackSyscall<::gvisor::syscall::Socket>},
|
||||
{"gvisor.container.Start", unpack<::gvisor::container::Start>},
|
||||
{"gvisor.sentry.CloneInfo", unpack<::gvisor::sentry::CloneInfo>},
|
||||
{"gvisor.sentry.ExecveInfo", unpack<::gvisor::sentry::ExecveInfo>},
|
||||
|
||||
@@ -21,7 +21,6 @@ import (
|
||||
"gvisor.dev/gvisor/pkg/abi"
|
||||
"gvisor.dev/gvisor/pkg/atomicbitops"
|
||||
"gvisor.dev/gvisor/pkg/bits"
|
||||
"gvisor.dev/gvisor/pkg/context"
|
||||
"gvisor.dev/gvisor/pkg/hostarch"
|
||||
"gvisor.dev/gvisor/pkg/sentry/arch"
|
||||
"gvisor.dev/gvisor/pkg/sentry/seccheck"
|
||||
@@ -85,6 +84,8 @@ type Syscall struct {
|
||||
URLs []string
|
||||
// PointCallback is an optional callback that converts syscall arguments
|
||||
// to a proto that can be used with seccheck.Checker.
|
||||
// Callback functions must follow this naming convention:
|
||||
// PointSyscallNameInCamelCase, e.g. PointReadat, PointRtSigaction.
|
||||
PointCallback SyscallToProto
|
||||
}
|
||||
|
||||
@@ -398,7 +399,7 @@ func (s *SyscallTable) LookupSyscallToProto(sysno uintptr) SyscallToProto {
|
||||
|
||||
// SyscallToProto is a callback function that converts generic syscall data to
|
||||
// schematized protobuf for the corresponding syscall.
|
||||
type SyscallToProto func(context.Context, seccheck.FieldSet, *pb.ContextData, SyscallInfo) proto.Message
|
||||
type SyscallToProto func(*Task, seccheck.FieldSet, *pb.ContextData, SyscallInfo) proto.Message
|
||||
|
||||
// SyscallInfo provides generic information about the syscall.
|
||||
type SyscallInfo struct {
|
||||
|
||||
@@ -313,7 +313,7 @@ func getExecveSeccheckInfo(t *Task, argv, env []string, executable fsbridge.File
|
||||
if executable != nil {
|
||||
info.BinaryPath = pathname
|
||||
if vfs2bridgeFile, ok := executable.(*fsbridge.VFSFile); ok {
|
||||
if fields.Local.Contains(seccheck.ExecveFieldBinaryInfo) {
|
||||
if fields.Local.Contains(seccheck.FieldSentryExecveBinaryInfo) {
|
||||
statOpts := vfs.StatOptions{
|
||||
Mask: linux.STATX_TYPE | linux.STATX_MODE | linux.STATX_UID | linux.STATX_GID,
|
||||
}
|
||||
|
||||
@@ -19,6 +19,8 @@ go_library(
|
||||
srcs = [
|
||||
"config.go",
|
||||
"metadata.go",
|
||||
"metadata_amd64.go",
|
||||
"metadata_arm64.go",
|
||||
"seccheck.go",
|
||||
"seqatomic_checkerslice_unsafe.go",
|
||||
"syscall.go",
|
||||
|
||||
@@ -123,7 +123,7 @@ func findSession(name string) (*State, error) {
|
||||
}
|
||||
|
||||
func findPointDesc(name string) (PointDesc, error) {
|
||||
if desc, ok := points[name]; ok {
|
||||
if desc, ok := Points[name]; ok {
|
||||
return desc, nil
|
||||
}
|
||||
return PointDesc{}, fmt.Errorf("point %q not found", name)
|
||||
|
||||
@@ -17,6 +17,7 @@ package seccheck
|
||||
import (
|
||||
"fmt"
|
||||
"os"
|
||||
"path"
|
||||
|
||||
"gvisor.dev/gvisor/pkg/fd"
|
||||
)
|
||||
@@ -46,22 +47,25 @@ const (
|
||||
FieldCtxtTime
|
||||
)
|
||||
|
||||
// Fields for container/start point.
|
||||
const (
|
||||
// ContainerStartFieldEnv is an optional field to collect list of environment
|
||||
// FieldContainerStartEnv is an optional field to collect list of environment
|
||||
// variables set for the container start process.
|
||||
ContainerStartFieldEnv Field = iota
|
||||
FieldContainerStartEnv Field = iota
|
||||
)
|
||||
|
||||
// Fields for sentry/execve point.
|
||||
const (
|
||||
// ExecveFieldBinaryInfo is an optional field to collect information about the
|
||||
// binary being executed.
|
||||
ExecveFieldBinaryInfo Field = iota
|
||||
// FieldSentryExecveBinaryInfo is an optional field to collect information
|
||||
// about the binary being executed.
|
||||
FieldSentryExecveBinaryInfo Field = iota
|
||||
)
|
||||
|
||||
var points = map[string]PointDesc{}
|
||||
// Points is a map with all the Points registered in the system.
|
||||
var Points = map[string]PointDesc{}
|
||||
var sinks = map[string]SinkDesc{}
|
||||
|
||||
// defaultContextFields are the fields present in most points.
|
||||
// defaultContextFields are the fields present in most Points.
|
||||
var defaultContextFields = []FieldDesc{
|
||||
{
|
||||
ID: FieldCtxtTime,
|
||||
@@ -127,7 +131,7 @@ func RegisterSink(sink SinkDesc) {
|
||||
// PointDesc describes a Point that is available to be configured.
|
||||
// Schema for these points are defined in pkg/sentry/seccheck/points/.
|
||||
type PointDesc struct {
|
||||
// ID is the point unique indentifier.
|
||||
// ID is the point unique identifier.
|
||||
ID Point
|
||||
// Name is the point unique name. Convention is to use the following format:
|
||||
// namespace/name
|
||||
@@ -153,7 +157,7 @@ type FieldDesc struct {
|
||||
}
|
||||
|
||||
func registerPoint(pt PointDesc) {
|
||||
if _, ok := points[pt.Name]; ok {
|
||||
if _, ok := Points[pt.Name]; ok {
|
||||
panic(fmt.Sprintf("Point %q already registered", pt.Name))
|
||||
}
|
||||
if err := validateFields(pt.OptionalFields); err != nil {
|
||||
@@ -162,7 +166,7 @@ func registerPoint(pt PointDesc) {
|
||||
if err := validateFields(pt.ContextFields); err != nil {
|
||||
panic(err)
|
||||
}
|
||||
points[pt.Name] = pt
|
||||
Points[pt.Name] = pt
|
||||
}
|
||||
|
||||
func validateFields(fields []FieldDesc) error {
|
||||
@@ -181,7 +185,30 @@ func validateFields(fields []FieldDesc) error {
|
||||
return nil
|
||||
}
|
||||
|
||||
// These are all the points available in the system.
|
||||
func addRawSyscallPoint(sysno uintptr) {
|
||||
addSyscallPointHelper(SyscallRawEnter, sysno, fmt.Sprintf("sysno/%d", sysno), nil)
|
||||
}
|
||||
|
||||
func addSyscallPoint(sysno uintptr, name string, optionalFields []FieldDesc) {
|
||||
addSyscallPointHelper(SyscallEnter, sysno, name, optionalFields)
|
||||
}
|
||||
|
||||
func addSyscallPointHelper(typ SyscallType, sysno uintptr, name string, optionalFields []FieldDesc) {
|
||||
registerPoint(PointDesc{
|
||||
ID: GetPointForSyscall(typ, sysno),
|
||||
Name: path.Join("syscall", name, "enter"),
|
||||
OptionalFields: optionalFields,
|
||||
ContextFields: defaultContextFields,
|
||||
})
|
||||
registerPoint(PointDesc{
|
||||
ID: GetPointForSyscall(typ+1, sysno),
|
||||
Name: path.Join("syscall", name, "exit"),
|
||||
OptionalFields: optionalFields,
|
||||
ContextFields: defaultContextFields,
|
||||
})
|
||||
}
|
||||
|
||||
// These are all the Points available in the system.
|
||||
func init() {
|
||||
// Points from the container namespace.
|
||||
registerPoint(PointDesc{
|
||||
@@ -189,7 +216,7 @@ func init() {
|
||||
Name: "container/start",
|
||||
OptionalFields: []FieldDesc{
|
||||
{
|
||||
ID: ContainerStartFieldEnv,
|
||||
ID: FieldContainerStartEnv,
|
||||
Name: "env",
|
||||
},
|
||||
},
|
||||
@@ -207,7 +234,7 @@ func init() {
|
||||
Name: "sentry/execve",
|
||||
OptionalFields: []FieldDesc{
|
||||
{
|
||||
ID: ExecveFieldBinaryInfo,
|
||||
ID: FieldSentryExecveBinaryInfo,
|
||||
Name: "binary_info",
|
||||
},
|
||||
},
|
||||
|
||||
@@ -0,0 +1,74 @@
|
||||
// Copyright 2022 The gVisor Authors.
|
||||
//
|
||||
// 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.
|
||||
|
||||
//go:build amd64
|
||||
// +build amd64
|
||||
|
||||
package seccheck
|
||||
|
||||
func init() {
|
||||
addSyscallPoint(0, "read", []FieldDesc{
|
||||
{
|
||||
ID: FieldSyscallPath,
|
||||
Name: "fd_path",
|
||||
},
|
||||
})
|
||||
addSyscallPoint(2, "open", nil)
|
||||
addSyscallPoint(3, "close", []FieldDesc{
|
||||
{
|
||||
ID: FieldSyscallPath,
|
||||
Name: "fd_path",
|
||||
},
|
||||
})
|
||||
addSyscallPoint(41, "socket", nil)
|
||||
addSyscallPoint(42, "connect", []FieldDesc{
|
||||
{
|
||||
ID: FieldSyscallPath,
|
||||
Name: "fd_path",
|
||||
},
|
||||
})
|
||||
addSyscallPoint(59, "execve", []FieldDesc{
|
||||
{
|
||||
ID: FieldSyscallExecveEnvv,
|
||||
Name: "envv",
|
||||
},
|
||||
})
|
||||
addSyscallPoint(85, "creat", []FieldDesc{
|
||||
{
|
||||
ID: FieldSyscallPath,
|
||||
Name: "fd_path",
|
||||
},
|
||||
})
|
||||
addSyscallPoint(257, "openat", []FieldDesc{
|
||||
{
|
||||
ID: FieldSyscallPath,
|
||||
Name: "fd_path",
|
||||
},
|
||||
})
|
||||
addSyscallPoint(322, "execveat", []FieldDesc{
|
||||
{
|
||||
ID: FieldSyscallPath,
|
||||
Name: "fd_path",
|
||||
},
|
||||
{
|
||||
ID: FieldSyscallExecveEnvv,
|
||||
Name: "envv",
|
||||
},
|
||||
})
|
||||
|
||||
const lastSyscallInTable = 441
|
||||
for i := 0; i <= lastSyscallInTable; i++ {
|
||||
addRawSyscallPoint(uintptr(i))
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,67 @@
|
||||
// Copyright 2022 The gVisor Authors.
|
||||
//
|
||||
// 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.
|
||||
|
||||
//go:build arm64
|
||||
// +build arm64
|
||||
|
||||
package seccheck
|
||||
|
||||
func init() {
|
||||
addSyscallPoint(63, "read", []FieldDesc{
|
||||
{
|
||||
ID: FieldSyscallPath,
|
||||
Name: "fd_path",
|
||||
},
|
||||
})
|
||||
addSyscallPoint(57, "close", []FieldDesc{
|
||||
{
|
||||
ID: FieldSyscallPath,
|
||||
Name: "fd_path",
|
||||
},
|
||||
})
|
||||
addSyscallPoint(198, "socket", nil)
|
||||
addSyscallPoint(203, "connect", []FieldDesc{
|
||||
{
|
||||
ID: FieldSyscallPath,
|
||||
Name: "fd_path",
|
||||
},
|
||||
})
|
||||
addSyscallPoint(221, "execve", []FieldDesc{
|
||||
{
|
||||
ID: FieldSyscallExecveEnvv,
|
||||
Name: "envv",
|
||||
},
|
||||
})
|
||||
addSyscallPoint(56, "openat", []FieldDesc{
|
||||
{
|
||||
ID: FieldSyscallPath,
|
||||
Name: "fd_path",
|
||||
},
|
||||
})
|
||||
addSyscallPoint(281, "execveat", []FieldDesc{
|
||||
{
|
||||
ID: FieldSyscallPath,
|
||||
Name: "fd_path",
|
||||
},
|
||||
{
|
||||
ID: FieldSyscallExecveEnvv,
|
||||
Name: "envv",
|
||||
},
|
||||
})
|
||||
|
||||
const lastSyscallInTable = 441
|
||||
for i := 0; i <= lastSyscallInTable; i++ {
|
||||
addRawSyscallPoint(uintptr(i))
|
||||
}
|
||||
}
|
||||
@@ -35,7 +35,7 @@ func TestSinkRegistration(t *testing.T) {
|
||||
func TestPointRegistration(t *testing.T) {
|
||||
point := PointDesc{Name: "test"}
|
||||
registerPoint(point)
|
||||
if _, ok := points["test"]; !ok {
|
||||
if _, ok := Points["test"]; !ok {
|
||||
t.Errorf("point registration failed")
|
||||
}
|
||||
|
||||
|
||||
@@ -34,3 +34,62 @@ message Syscall {
|
||||
uint64 arg5 = 9;
|
||||
uint64 arg6 = 10;
|
||||
}
|
||||
|
||||
message Open {
|
||||
gvisor.common.ContextData context_data = 1;
|
||||
Exit exit = 2;
|
||||
uint64 sysno = 3;
|
||||
int64 fd = 4;
|
||||
string fd_path = 5;
|
||||
string pathname = 6;
|
||||
uint32 flags = 7;
|
||||
uint32 mode = 8;
|
||||
}
|
||||
|
||||
message Close {
|
||||
gvisor.common.ContextData context_data = 1;
|
||||
Exit exit = 2;
|
||||
uint64 sysno = 3;
|
||||
int64 fd = 4;
|
||||
string fd_path = 5;
|
||||
}
|
||||
|
||||
message Read {
|
||||
gvisor.common.ContextData context_data = 1;
|
||||
Exit exit = 2;
|
||||
uint64 sysno = 3;
|
||||
int64 fd = 4;
|
||||
string fd_path = 5;
|
||||
uint64 count = 6;
|
||||
bytes data = 7;
|
||||
}
|
||||
|
||||
message Connect {
|
||||
gvisor.common.ContextData context_data = 1;
|
||||
Exit exit = 2;
|
||||
uint64 sysno = 3;
|
||||
int64 fd = 4;
|
||||
string fd_path = 5;
|
||||
bytes address = 6;
|
||||
}
|
||||
|
||||
message Execve {
|
||||
gvisor.common.ContextData context_data = 1;
|
||||
Exit exit = 2;
|
||||
uint64 sysno = 3;
|
||||
int64 fd = 4;
|
||||
string fd_path = 5;
|
||||
string pathname = 6;
|
||||
repeated string argv = 7;
|
||||
repeated string envv = 8;
|
||||
uint32 flags = 9;
|
||||
}
|
||||
|
||||
message Socket {
|
||||
gvisor.common.ContextData context_data = 1;
|
||||
Exit exit = 2;
|
||||
uint64 sysno = 3;
|
||||
int32 domain = 4;
|
||||
int32 type = 5;
|
||||
int32 protocol = 6;
|
||||
}
|
||||
@@ -41,6 +41,21 @@ const (
|
||||
syscallPoints = syscallsMax * int(syscallTypesCount)
|
||||
)
|
||||
|
||||
// Fields that are common for many syscalls.
|
||||
const (
|
||||
// FieldSyscallPath is an optional field to collect path from an FD. Given
|
||||
// that many syscalls operate on FDs, this const is used across syscalls.
|
||||
FieldSyscallPath Field = iota
|
||||
)
|
||||
|
||||
// Fields for execve*(2) syscalls.
|
||||
const (
|
||||
// FieldSyscallExecveEnvv is an optional field to collect list of environment
|
||||
// variables. Start after FieldSyscallPath because execveat(2) can collect
|
||||
// path from FD.
|
||||
FieldSyscallExecveEnvv = FieldSyscallPath + 1
|
||||
)
|
||||
|
||||
// GetPointForSyscall translates the syscall number to the corresponding Point.
|
||||
func GetPointForSyscall(typ SyscallType, sysno uintptr) Point {
|
||||
return Point(sysno)*Point(syscallTypesCount) + Point(typ) + pointLengthBeforeSyscalls
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
load("//tools:defs.bzl", "go_library")
|
||||
load("//tools:defs.bzl", "go_library", "go_test")
|
||||
|
||||
package(licenses = ["notice"])
|
||||
|
||||
@@ -8,6 +8,7 @@ go_library(
|
||||
"error.go",
|
||||
"flags.go",
|
||||
"linux64.go",
|
||||
"points.go",
|
||||
"sigset.go",
|
||||
"sys_aio.go",
|
||||
"sys_capability.go",
|
||||
@@ -96,6 +97,8 @@ go_library(
|
||||
"//pkg/sentry/loader",
|
||||
"//pkg/sentry/memmap",
|
||||
"//pkg/sentry/mm",
|
||||
"//pkg/sentry/seccheck",
|
||||
"//pkg/sentry/seccheck/points:points_go_proto",
|
||||
"//pkg/sentry/socket",
|
||||
"//pkg/sentry/socket/control",
|
||||
"//pkg/sentry/socket/unix/transport",
|
||||
@@ -106,6 +109,19 @@ go_library(
|
||||
"//pkg/syserr",
|
||||
"//pkg/usermem",
|
||||
"//pkg/waiter",
|
||||
"@org_golang_google_protobuf//proto:go_default_library",
|
||||
"@org_golang_x_sys//unix:go_default_library",
|
||||
],
|
||||
)
|
||||
|
||||
go_test(
|
||||
name = "linux_test",
|
||||
size = "small",
|
||||
srcs = [
|
||||
"linux64_amd64_test.go",
|
||||
"linux64_arm64_test.go",
|
||||
"linux64_test.go",
|
||||
],
|
||||
library = ":linux",
|
||||
deps = ["//pkg/sentry/seccheck"],
|
||||
)
|
||||
|
||||
@@ -52,9 +52,9 @@ var AMD64 = &kernel.SyscallTable{
|
||||
},
|
||||
AuditNumber: linux.AUDIT_ARCH_X86_64,
|
||||
Table: map[uintptr]kernel.Syscall{
|
||||
0: syscalls.Supported("read", Read),
|
||||
0: syscalls.SupportedPoint("read", Read, PointRead),
|
||||
1: syscalls.Supported("write", Write),
|
||||
2: syscalls.PartiallySupported("open", Open, "Options O_DIRECT, O_NOATIME, O_PATH, O_TMPFILE, O_SYNC are not supported.", nil),
|
||||
2: syscalls.PartiallySupportedPoint("open", Open, PointOpen, "Options O_DIRECT, O_NOATIME, O_PATH, O_TMPFILE, O_SYNC are not supported.", nil),
|
||||
3: syscalls.Supported("close", Close),
|
||||
4: syscalls.Supported("stat", Stat),
|
||||
5: syscalls.Supported("fstat", Fstat),
|
||||
@@ -94,7 +94,7 @@ var AMD64 = &kernel.SyscallTable{
|
||||
39: syscalls.Supported("getpid", Getpid),
|
||||
40: syscalls.Supported("sendfile", Sendfile),
|
||||
41: syscalls.PartiallySupported("socket", Socket, "Limited support for AF_NETLINK, NETLINK_ROUTE sockets. Limited support for SOCK_RAW.", nil),
|
||||
42: syscalls.Supported("connect", Connect),
|
||||
42: syscalls.SupportedPoint("connect", Connect, PointConnect),
|
||||
43: syscalls.Supported("accept", Accept),
|
||||
44: syscalls.Supported("sendto", SendTo),
|
||||
45: syscalls.Supported("recvfrom", RecvFrom),
|
||||
@@ -111,7 +111,7 @@ var AMD64 = &kernel.SyscallTable{
|
||||
56: syscalls.PartiallySupported("clone", Clone, "Mount namespace (CLONE_NEWNS) not supported. Options CLONE_PARENT, CLONE_SYSVSEM not supported.", nil),
|
||||
57: syscalls.Supported("fork", Fork),
|
||||
58: syscalls.Supported("vfork", Vfork),
|
||||
59: syscalls.Supported("execve", Execve),
|
||||
59: syscalls.SupportedPoint("execve", Execve, PointExecve),
|
||||
60: syscalls.Supported("exit", Exit),
|
||||
61: syscalls.Supported("wait4", Wait4),
|
||||
62: syscalls.Supported("kill", Kill),
|
||||
@@ -309,7 +309,7 @@ var AMD64 = &kernel.SyscallTable{
|
||||
254: syscalls.PartiallySupported("inotify_add_watch", InotifyAddWatch, "Inotify events are only available inside the sandbox. Hard links are treated as different watch targets in gofer fs.", nil),
|
||||
255: syscalls.PartiallySupported("inotify_rm_watch", InotifyRmWatch, "Inotify events are only available inside the sandbox. Hard links are treated as different watch targets in gofer fs.", nil),
|
||||
256: syscalls.CapError("migrate_pages", linux.CAP_SYS_NICE, "", nil),
|
||||
257: syscalls.Supported("openat", Openat),
|
||||
257: syscalls.SupportedPoint("openat", Openat, PointOpenat),
|
||||
258: syscalls.Supported("mkdirat", Mkdirat),
|
||||
259: syscalls.Supported("mknodat", Mknodat),
|
||||
260: syscalls.Supported("fchownat", Fchownat),
|
||||
@@ -374,7 +374,7 @@ var AMD64 = &kernel.SyscallTable{
|
||||
319: syscalls.Supported("memfd_create", MemfdCreate),
|
||||
320: syscalls.CapError("kexec_file_load", linux.CAP_SYS_BOOT, "", nil),
|
||||
321: syscalls.CapError("bpf", linux.CAP_SYS_ADMIN, "", nil),
|
||||
322: syscalls.Supported("execveat", Execveat),
|
||||
322: syscalls.SupportedPoint("execveat", Execveat, PointExecveat),
|
||||
323: syscalls.ErrorWithEvent("userfaultfd", linuxerr.ENOSYS, "", []string{"gvisor.dev/issue/266"}), // TODO(b/118906345)
|
||||
324: syscalls.PartiallySupported("membarrier", Membarrier, "Not supported on all platforms.", nil),
|
||||
325: syscalls.PartiallySupported("mlock2", Mlock2, "Stub implementation. The sandbox lacks appropriate permissions.", nil),
|
||||
@@ -486,14 +486,14 @@ var ARM64 = &kernel.SyscallTable{
|
||||
53: syscalls.Supported("fchmodat", Fchmodat),
|
||||
54: syscalls.Supported("fchownat", Fchownat),
|
||||
55: syscalls.Supported("fchown", Fchown),
|
||||
56: syscalls.Supported("openat", Openat),
|
||||
56: syscalls.SupportedPoint("openat", Openat, PointOpenat),
|
||||
57: syscalls.Supported("close", Close),
|
||||
58: syscalls.CapError("vhangup", linux.CAP_SYS_TTY_CONFIG, "", nil),
|
||||
59: syscalls.Supported("pipe2", Pipe2),
|
||||
60: syscalls.CapError("quotactl", linux.CAP_SYS_ADMIN, "", nil), // requires cap_sys_admin for most operations
|
||||
61: syscalls.Supported("getdents64", Getdents64),
|
||||
62: syscalls.Supported("lseek", Lseek),
|
||||
63: syscalls.Supported("read", Read),
|
||||
63: syscalls.SupportedPoint("read", Read, PointRead),
|
||||
64: syscalls.Supported("write", Write),
|
||||
65: syscalls.Supported("readv", Readv),
|
||||
66: syscalls.Supported("writev", Writev),
|
||||
@@ -633,7 +633,7 @@ var ARM64 = &kernel.SyscallTable{
|
||||
200: syscalls.PartiallySupported("bind", Bind, "Autobind for abstract Unix sockets is not supported.", nil),
|
||||
201: syscalls.Supported("listen", Listen),
|
||||
202: syscalls.Supported("accept", Accept),
|
||||
203: syscalls.Supported("connect", Connect),
|
||||
203: syscalls.SupportedPoint("connect", Connect, PointConnect),
|
||||
204: syscalls.Supported("getsockname", GetSockName),
|
||||
205: syscalls.Supported("getpeername", GetPeerName),
|
||||
206: syscalls.Supported("sendto", SendTo),
|
||||
@@ -651,7 +651,7 @@ var ARM64 = &kernel.SyscallTable{
|
||||
218: syscalls.Error("request_key", linuxerr.EACCES, "Not available to user.", nil),
|
||||
219: syscalls.Error("keyctl", linuxerr.EACCES, "Not available to user.", nil),
|
||||
220: syscalls.PartiallySupported("clone", Clone, "Mount namespace (CLONE_NEWNS) not supported. Options CLONE_PARENT, CLONE_SYSVSEM not supported.", nil),
|
||||
221: syscalls.Supported("execve", Execve),
|
||||
221: syscalls.SupportedPoint("execve", Execve, PointExecve),
|
||||
222: syscalls.PartiallySupported("mmap", Mmap, "Generally supported with exceptions. Options MAP_FIXED_NOREPLACE, MAP_SHARED_VALIDATE, MAP_SYNC MAP_GROWSDOWN, MAP_HUGETLB are not supported.", nil),
|
||||
223: syscalls.PartiallySupported("fadvise64", Fadvise64, "Not all options are supported.", nil),
|
||||
224: syscalls.CapError("swapon", linux.CAP_SYS_ADMIN, "", nil),
|
||||
@@ -695,7 +695,7 @@ var ARM64 = &kernel.SyscallTable{
|
||||
278: syscalls.Supported("getrandom", GetRandom),
|
||||
279: syscalls.Supported("memfd_create", MemfdCreate),
|
||||
280: syscalls.CapError("bpf", linux.CAP_SYS_ADMIN, "", nil),
|
||||
281: syscalls.Supported("execveat", Execveat),
|
||||
281: syscalls.SupportedPoint("execveat", Execveat, PointExecveat),
|
||||
282: syscalls.ErrorWithEvent("userfaultfd", linuxerr.ENOSYS, "", []string{"gvisor.dev/issue/266"}), // TODO(b/118906345)
|
||||
283: syscalls.PartiallySupported("membarrier", Membarrier, "Not supported on all platforms.", nil),
|
||||
284: syscalls.PartiallySupported("mlock2", Mlock2, "Stub implementation. The sandbox lacks appropriate permissions.", nil),
|
||||
|
||||
@@ -0,0 +1,20 @@
|
||||
// Copyright 2022 The gVisor Authors.
|
||||
//
|
||||
// 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.
|
||||
|
||||
//go:build amd64
|
||||
// +build amd64
|
||||
|
||||
package linux
|
||||
|
||||
var archToTest = AMD64
|
||||
@@ -0,0 +1,20 @@
|
||||
// Copyright 2022 The gVisor Authors.
|
||||
//
|
||||
// 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.
|
||||
|
||||
//go:build arm64
|
||||
// +build arm64
|
||||
|
||||
package linux
|
||||
|
||||
var archToTest = ARM64
|
||||
@@ -0,0 +1,102 @@
|
||||
// Copyright 2022 The gVisor Authors.
|
||||
//
|
||||
// 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 linux
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"reflect"
|
||||
"runtime"
|
||||
"strings"
|
||||
"testing"
|
||||
"unicode"
|
||||
|
||||
"gvisor.dev/gvisor/pkg/sentry/seccheck"
|
||||
)
|
||||
|
||||
func findPoint(name string) (seccheck.PointDesc, bool) {
|
||||
for _, pt := range seccheck.Points {
|
||||
if pt.Name == name {
|
||||
return pt, true
|
||||
}
|
||||
}
|
||||
return seccheck.PointDesc{}, false
|
||||
}
|
||||
|
||||
// TestSeccheckMax catches cases that a new syscall was added but seccheck raw
|
||||
// syscall numbers (e.g. syscall/sysno/123) have not been updated.
|
||||
func TestSeccheckMax(t *testing.T) {
|
||||
max := uintptr(0)
|
||||
for sysno := range archToTest.Table {
|
||||
if sysno > max {
|
||||
max = sysno
|
||||
}
|
||||
}
|
||||
|
||||
want := fmt.Sprintf("syscall/sysno/%d/enter", max)
|
||||
if _, ok := findPoint(want); !ok {
|
||||
t.Errorf("seccheck.PointDesc for syscall %d not found. Update pkg/sentry/seccheck/metadata_amd64.go", max)
|
||||
}
|
||||
}
|
||||
|
||||
// TestSeccheckSyscalls verifies that all syscalls registered with a point
|
||||
// callback have the corresponding seccheck metadata created.
|
||||
func TestSeccheckSyscalls(t *testing.T) {
|
||||
for sysno, syscall := range archToTest.Table {
|
||||
if syscall.PointCallback == nil {
|
||||
continue
|
||||
}
|
||||
|
||||
// For every syscall with a PointCallback, there must be a corresponding
|
||||
// seccheck.PointDesc created.
|
||||
funcName := runtime.FuncForPC(reflect.ValueOf(syscall.PointCallback).Pointer()).Name()
|
||||
if idx := strings.LastIndex(funcName, "."); idx > -1 {
|
||||
funcName = funcName[idx+1:]
|
||||
}
|
||||
t.Run(funcName, func(t *testing.T) {
|
||||
if !strings.HasPrefix(funcName, "Point") {
|
||||
t.Errorf("PointCallback function name must start with Point: %q", funcName)
|
||||
}
|
||||
funcName = strings.TrimPrefix(funcName, "Point")
|
||||
if len(funcName) == 0 {
|
||||
t.Errorf("PointCallback function name invalid: %q", funcName)
|
||||
}
|
||||
|
||||
pointName := strings.ToLower(string(funcName[0]))
|
||||
for _, c := range funcName[1:] {
|
||||
if unicode.IsUpper(c) {
|
||||
pointName += "_"
|
||||
}
|
||||
pointName += string(unicode.ToLower(c))
|
||||
}
|
||||
|
||||
for _, flavor := range []struct {
|
||||
suffix string
|
||||
typ seccheck.SyscallType
|
||||
}{
|
||||
{suffix: "enter", typ: seccheck.SyscallEnter},
|
||||
{suffix: "exit", typ: seccheck.SyscallExit},
|
||||
} {
|
||||
fullName := fmt.Sprintf("syscall/%s/%s", pointName, flavor.suffix)
|
||||
pt, ok := findPoint(fullName)
|
||||
if !ok {
|
||||
t.Fatalf("seccheck.PointDesc %q not found.", fullName)
|
||||
}
|
||||
if want := seccheck.GetPointForSyscall(flavor.typ, sysno); want != pt.ID {
|
||||
t.Errorf("seccheck.Point for syscall %q is wrong, want: %v, got: %v", pointName, want, pt.ID)
|
||||
}
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,263 @@
|
||||
// Copyright 2022 The gVisor Authors.
|
||||
//
|
||||
// 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 linux
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
|
||||
"google.golang.org/protobuf/proto"
|
||||
"gvisor.dev/gvisor/pkg/abi/linux"
|
||||
"gvisor.dev/gvisor/pkg/sentry/kernel"
|
||||
"gvisor.dev/gvisor/pkg/sentry/seccheck"
|
||||
pb "gvisor.dev/gvisor/pkg/sentry/seccheck/points/points_go_proto"
|
||||
)
|
||||
|
||||
func newExitMaybe(info kernel.SyscallInfo) *pb.Exit {
|
||||
if !info.Exit {
|
||||
return nil
|
||||
}
|
||||
return &pb.Exit{
|
||||
Result: int64(info.Rval),
|
||||
Errorno: int64(info.Errno),
|
||||
}
|
||||
}
|
||||
|
||||
func getFilePath(t *kernel.Task, fd int32) string {
|
||||
fdt := t.FDTable()
|
||||
if fdt == nil {
|
||||
return "[err: no FD table]"
|
||||
}
|
||||
file, _ := fdt.GetVFS2(fd)
|
||||
if file == nil {
|
||||
return "[err: requires VFS2]"
|
||||
}
|
||||
defer file.DecRef(t)
|
||||
|
||||
root := t.MountNamespaceVFS2().Root()
|
||||
path, err := t.Kernel().VFS().PathnameWithDeleted(t, root, file.VirtualDentry())
|
||||
if err != nil {
|
||||
return fmt.Sprintf("[err: %v]", err)
|
||||
}
|
||||
return path
|
||||
}
|
||||
|
||||
// PointOpen converts open(2) syscall to proto.
|
||||
func PointOpen(t *kernel.Task, _ seccheck.FieldSet, cxtData *pb.ContextData, info kernel.SyscallInfo) proto.Message {
|
||||
p := &pb.Open{
|
||||
ContextData: cxtData,
|
||||
Sysno: uint64(info.Sysno),
|
||||
Fd: linux.AT_FDCWD,
|
||||
Flags: info.Args[1].Uint(),
|
||||
Mode: uint32(info.Args[2].ModeT()),
|
||||
}
|
||||
addr := info.Args[0].Pointer()
|
||||
if addr > 0 {
|
||||
path, err := t.CopyInString(addr, linux.PATH_MAX)
|
||||
if err == nil {
|
||||
p.Pathname = path
|
||||
}
|
||||
}
|
||||
p.Exit = newExitMaybe(info)
|
||||
return p
|
||||
}
|
||||
|
||||
// PointOpenat converts openat(2) syscall to proto.
|
||||
func PointOpenat(t *kernel.Task, fields seccheck.FieldSet, cxtData *pb.ContextData, info kernel.SyscallInfo) proto.Message {
|
||||
p := &pb.Open{
|
||||
ContextData: cxtData,
|
||||
Sysno: uint64(info.Sysno),
|
||||
Fd: int64(info.Args[0].Int()),
|
||||
Flags: info.Args[2].Uint(),
|
||||
}
|
||||
|
||||
addr := info.Args[1].Pointer()
|
||||
if addr > 0 {
|
||||
path, err := t.CopyInString(addr, linux.PATH_MAX)
|
||||
if err == nil {
|
||||
p.Pathname = path
|
||||
}
|
||||
}
|
||||
if p.Flags&linux.O_CREAT != 0 {
|
||||
p.Mode = uint32(info.Args[3].ModeT())
|
||||
}
|
||||
|
||||
if fields.Local.Contains(seccheck.FieldSyscallPath) {
|
||||
p.FdPath = getFilePath(t, int32(p.Fd))
|
||||
}
|
||||
|
||||
p.Exit = newExitMaybe(info)
|
||||
|
||||
return p
|
||||
}
|
||||
|
||||
// PointCreat converts creat(2) syscall to proto.
|
||||
func PointCreat(t *kernel.Task, fields seccheck.FieldSet, cxtData *pb.ContextData, info kernel.SyscallInfo) proto.Message {
|
||||
p := &pb.Open{
|
||||
ContextData: cxtData,
|
||||
Sysno: uint64(info.Sysno),
|
||||
Fd: linux.AT_FDCWD,
|
||||
Flags: linux.O_WRONLY | linux.O_CREAT | linux.O_TRUNC,
|
||||
Mode: uint32(info.Args[1].ModeT()),
|
||||
}
|
||||
|
||||
addr := info.Args[0].Pointer()
|
||||
if addr > 0 {
|
||||
path, err := t.CopyInString(addr, linux.PATH_MAX)
|
||||
if err == nil {
|
||||
p.Pathname = path
|
||||
}
|
||||
}
|
||||
|
||||
if fields.Local.Contains(seccheck.FieldSyscallPath) {
|
||||
p.FdPath = getFilePath(t, int32(p.Fd))
|
||||
}
|
||||
|
||||
p.Exit = newExitMaybe(info)
|
||||
|
||||
return p
|
||||
}
|
||||
|
||||
// PointClose converts close(2) syscall to proto.
|
||||
func PointClose(t *kernel.Task, fields seccheck.FieldSet, cxtData *pb.ContextData, info kernel.SyscallInfo) proto.Message {
|
||||
p := &pb.Close{
|
||||
ContextData: cxtData,
|
||||
Sysno: uint64(info.Sysno),
|
||||
Fd: int64(info.Args[0].Int()),
|
||||
}
|
||||
|
||||
if fields.Local.Contains(seccheck.FieldSyscallPath) {
|
||||
p.FdPath = getFilePath(t, int32(p.Fd))
|
||||
}
|
||||
|
||||
p.Exit = newExitMaybe(info)
|
||||
return p
|
||||
}
|
||||
|
||||
// PointRead converts read(2) syscall to proto.
|
||||
func PointRead(t *kernel.Task, fields seccheck.FieldSet, cxtData *pb.ContextData, info kernel.SyscallInfo) proto.Message {
|
||||
p := &pb.Read{
|
||||
ContextData: cxtData,
|
||||
Sysno: uint64(info.Sysno),
|
||||
Fd: int64(info.Args[0].Int()),
|
||||
Count: uint64(info.Args[2].SizeT()),
|
||||
}
|
||||
if fields.Local.Contains(seccheck.FieldSyscallPath) {
|
||||
p.FdPath = getFilePath(t, int32(p.Fd))
|
||||
}
|
||||
|
||||
p.Exit = newExitMaybe(info)
|
||||
|
||||
return p
|
||||
}
|
||||
|
||||
// PointSocket converts socket(2) syscall to proto.
|
||||
func PointSocket(_ *kernel.Task, _ seccheck.FieldSet, cxtData *pb.ContextData, info kernel.SyscallInfo) proto.Message {
|
||||
p := &pb.Socket{
|
||||
ContextData: cxtData,
|
||||
Sysno: uint64(info.Sysno),
|
||||
Domain: info.Args[0].Int(),
|
||||
Type: info.Args[1].Int(),
|
||||
Protocol: info.Args[2].Int(),
|
||||
}
|
||||
|
||||
p.Exit = newExitMaybe(info)
|
||||
|
||||
return p
|
||||
}
|
||||
|
||||
// PointConnect converts connect(2) syscall to proto.
|
||||
func PointConnect(t *kernel.Task, fields seccheck.FieldSet, cxtData *pb.ContextData, info kernel.SyscallInfo) proto.Message {
|
||||
p := &pb.Connect{
|
||||
ContextData: cxtData,
|
||||
Sysno: uint64(info.Sysno),
|
||||
Fd: int64(info.Args[0].Int()),
|
||||
}
|
||||
|
||||
addr := info.Args[1].Pointer()
|
||||
addrlen := info.Args[2].Uint()
|
||||
if addr > 0 {
|
||||
p.Address = make([]byte, addrlen)
|
||||
_, _ = t.CopyInBytes(addr, p.Address)
|
||||
}
|
||||
|
||||
if fields.Local.Contains(seccheck.FieldSyscallPath) {
|
||||
p.FdPath = getFilePath(t, int32(p.Fd))
|
||||
}
|
||||
|
||||
p.Exit = newExitMaybe(info)
|
||||
|
||||
return p
|
||||
}
|
||||
|
||||
// PointExecve converts execve(2) syscall to proto.
|
||||
func PointExecve(t *kernel.Task, fields seccheck.FieldSet, cxtData *pb.ContextData, info kernel.SyscallInfo) proto.Message {
|
||||
p := &pb.Execve{
|
||||
ContextData: cxtData,
|
||||
Sysno: uint64(info.Sysno),
|
||||
}
|
||||
if pathname, err := t.CopyInString(info.Args[0].Pointer(), linux.PATH_MAX); err == nil {
|
||||
p.Pathname = pathname
|
||||
}
|
||||
if argvAddr := info.Args[1].Pointer(); argvAddr != 0 {
|
||||
if argv, err := t.CopyInVector(argvAddr, ExecMaxElemSize, ExecMaxTotalSize); err == nil {
|
||||
p.Argv = argv
|
||||
}
|
||||
}
|
||||
|
||||
if fields.Local.Contains(seccheck.FieldSyscallExecveEnvv) {
|
||||
if envvAddr := info.Args[2].Pointer(); envvAddr != 0 {
|
||||
if envv, err := t.CopyInVector(envvAddr, ExecMaxElemSize, ExecMaxTotalSize); err == nil {
|
||||
p.Envv = envv
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
p.Exit = newExitMaybe(info)
|
||||
|
||||
return p
|
||||
}
|
||||
|
||||
// PointExecveat converts execveat(2) syscall to proto.
|
||||
func PointExecveat(t *kernel.Task, fields seccheck.FieldSet, cxtData *pb.ContextData, info kernel.SyscallInfo) proto.Message {
|
||||
p := &pb.Execve{
|
||||
ContextData: cxtData,
|
||||
Sysno: uint64(info.Sysno),
|
||||
Fd: int64(info.Args[0].Int()),
|
||||
Flags: info.Args[4].Uint(),
|
||||
}
|
||||
if pathname, err := t.CopyInString(info.Args[1].Pointer(), linux.PATH_MAX); err == nil {
|
||||
p.Pathname = pathname
|
||||
}
|
||||
if argvAddr := info.Args[2].Pointer(); argvAddr != 0 {
|
||||
if argv, err := t.CopyInVector(argvAddr, ExecMaxElemSize, ExecMaxTotalSize); err == nil {
|
||||
p.Argv = argv
|
||||
}
|
||||
}
|
||||
|
||||
if fields.Local.Contains(seccheck.FieldSyscallExecveEnvv) {
|
||||
if envvAddr := info.Args[3].Pointer(); envvAddr != 0 {
|
||||
if envv, err := t.CopyInVector(envvAddr, ExecMaxElemSize, ExecMaxTotalSize); err == nil {
|
||||
p.Envv = envv
|
||||
}
|
||||
}
|
||||
}
|
||||
if fields.Local.Contains(seccheck.FieldSyscallPath) {
|
||||
p.FdPath = getFilePath(t, int32(p.Fd))
|
||||
}
|
||||
|
||||
p.Exit = newExitMaybe(info)
|
||||
|
||||
return p
|
||||
}
|
||||
@@ -24,10 +24,10 @@ import (
|
||||
func Override() {
|
||||
// Override AMD64.
|
||||
s := linux.AMD64
|
||||
s.Table[0] = syscalls.Supported("read", Read)
|
||||
s.Table[0] = syscalls.SupportedPoint("read", Read, linux.PointRead)
|
||||
s.Table[1] = syscalls.Supported("write", Write)
|
||||
s.Table[2] = syscalls.Supported("open", Open)
|
||||
s.Table[3] = syscalls.Supported("close", Close)
|
||||
s.Table[2] = syscalls.SupportedPoint("open", Open, linux.PointOpen)
|
||||
s.Table[3] = syscalls.SupportedPoint("close", Close, linux.PointClose)
|
||||
s.Table[4] = syscalls.Supported("stat", Stat)
|
||||
s.Table[5] = syscalls.Supported("fstat", Fstat)
|
||||
s.Table[6] = syscalls.Supported("lstat", Lstat)
|
||||
@@ -45,8 +45,8 @@ func Override() {
|
||||
s.Table[32] = syscalls.Supported("dup", Dup)
|
||||
s.Table[33] = syscalls.Supported("dup2", Dup2)
|
||||
s.Table[40] = syscalls.Supported("sendfile", Sendfile)
|
||||
s.Table[41] = syscalls.Supported("socket", Socket)
|
||||
s.Table[42] = syscalls.Supported("connect", Connect)
|
||||
s.Table[41] = syscalls.SupportedPoint("socket", Socket, linux.PointSocket)
|
||||
s.Table[42] = syscalls.SupportedPoint("connect", Connect, linux.PointConnect)
|
||||
s.Table[43] = syscalls.Supported("accept", Accept)
|
||||
s.Table[44] = syscalls.Supported("sendto", SendTo)
|
||||
s.Table[45] = syscalls.Supported("recvfrom", RecvFrom)
|
||||
@@ -60,7 +60,7 @@ func Override() {
|
||||
s.Table[53] = syscalls.Supported("socketpair", SocketPair)
|
||||
s.Table[54] = syscalls.Supported("setsockopt", SetSockOpt)
|
||||
s.Table[55] = syscalls.Supported("getsockopt", GetSockOpt)
|
||||
s.Table[59] = syscalls.Supported("execve", Execve)
|
||||
s.Table[59] = syscalls.SupportedPoint("execve", Execve, linux.PointExecve)
|
||||
s.Table[72] = syscalls.Supported("fcntl", Fcntl)
|
||||
s.Table[73] = syscalls.Supported("flock", Flock)
|
||||
s.Table[74] = syscalls.Supported("fsync", Fsync)
|
||||
@@ -74,7 +74,7 @@ func Override() {
|
||||
s.Table[82] = syscalls.Supported("rename", Rename)
|
||||
s.Table[83] = syscalls.Supported("mkdir", Mkdir)
|
||||
s.Table[84] = syscalls.Supported("rmdir", Rmdir)
|
||||
s.Table[85] = syscalls.Supported("creat", Creat)
|
||||
s.Table[85] = syscalls.SupportedPoint("creat", Creat, linux.PointCreat)
|
||||
s.Table[86] = syscalls.Supported("link", Link)
|
||||
s.Table[87] = syscalls.Supported("unlink", Unlink)
|
||||
s.Table[88] = syscalls.Supported("symlink", Symlink)
|
||||
@@ -118,7 +118,7 @@ func Override() {
|
||||
s.Table[253] = syscalls.PartiallySupported("inotify_init", InotifyInit, "inotify events are only available inside the sandbox.", nil)
|
||||
s.Table[254] = syscalls.PartiallySupported("inotify_add_watch", InotifyAddWatch, "inotify events are only available inside the sandbox.", nil)
|
||||
s.Table[255] = syscalls.PartiallySupported("inotify_rm_watch", InotifyRmWatch, "inotify events are only available inside the sandbox.", nil)
|
||||
s.Table[257] = syscalls.Supported("openat", Openat)
|
||||
s.Table[257] = syscalls.SupportedPoint("openat", Openat, linux.PointOpenat)
|
||||
s.Table[258] = syscalls.Supported("mkdirat", Mkdirat)
|
||||
s.Table[259] = syscalls.Supported("mknodat", Mknodat)
|
||||
s.Table[260] = syscalls.Supported("fchownat", Fchownat)
|
||||
@@ -158,7 +158,7 @@ func Override() {
|
||||
s.Table[307] = syscalls.Supported("sendmmsg", SendMMsg)
|
||||
s.Table[316] = syscalls.Supported("renameat2", Renameat2)
|
||||
s.Table[319] = syscalls.Supported("memfd_create", MemfdCreate)
|
||||
s.Table[322] = syscalls.Supported("execveat", Execveat)
|
||||
s.Table[322] = syscalls.SupportedPoint("execveat", Execveat, linux.PointExecveat)
|
||||
s.Table[327] = syscalls.Supported("preadv2", Preadv2)
|
||||
s.Table[328] = syscalls.Supported("pwritev2", Pwritev2)
|
||||
s.Table[332] = syscalls.Supported("statx", Statx)
|
||||
@@ -217,12 +217,12 @@ func Override() {
|
||||
s.Table[53] = syscalls.Supported("fchmodat", Fchmodat)
|
||||
s.Table[54] = syscalls.Supported("fchownat", Fchownat)
|
||||
s.Table[55] = syscalls.Supported("fchown", Fchown)
|
||||
s.Table[56] = syscalls.Supported("openat", Openat)
|
||||
s.Table[57] = syscalls.Supported("close", Close)
|
||||
s.Table[56] = syscalls.SupportedPoint("openat", Openat, linux.PointOpenat)
|
||||
s.Table[57] = syscalls.SupportedPoint("close", Close, linux.PointClose)
|
||||
s.Table[59] = syscalls.Supported("pipe2", Pipe2)
|
||||
s.Table[61] = syscalls.Supported("getdents64", Getdents64)
|
||||
s.Table[62] = syscalls.Supported("lseek", Lseek)
|
||||
s.Table[63] = syscalls.Supported("read", Read)
|
||||
s.Table[63] = syscalls.SupportedPoint("read", Read, linux.PointRead)
|
||||
s.Table[64] = syscalls.Supported("write", Write)
|
||||
s.Table[65] = syscalls.Supported("readv", Readv)
|
||||
s.Table[66] = syscalls.Supported("writev", Writev)
|
||||
@@ -249,12 +249,12 @@ func Override() {
|
||||
s.Table[88] = syscalls.Supported("utimensat", Utimensat)
|
||||
s.Table[180] = syscalls.Supported("mq_open", MqOpen)
|
||||
s.Table[181] = syscalls.Supported("mq_unlink", MqUnlink)
|
||||
s.Table[198] = syscalls.Supported("socket", Socket)
|
||||
s.Table[198] = syscalls.SupportedPoint("socket", Socket, linux.PointSocket)
|
||||
s.Table[199] = syscalls.Supported("socketpair", SocketPair)
|
||||
s.Table[200] = syscalls.Supported("bind", Bind)
|
||||
s.Table[201] = syscalls.Supported("listen", Listen)
|
||||
s.Table[202] = syscalls.Supported("accept", Accept)
|
||||
s.Table[203] = syscalls.Supported("connect", Connect)
|
||||
s.Table[203] = syscalls.SupportedPoint("connect", Connect, linux.PointConnect)
|
||||
s.Table[204] = syscalls.Supported("getsockname", GetSockName)
|
||||
s.Table[205] = syscalls.Supported("getpeername", GetPeerName)
|
||||
s.Table[206] = syscalls.Supported("sendto", SendTo)
|
||||
@@ -265,7 +265,7 @@ func Override() {
|
||||
s.Table[211] = syscalls.Supported("sendmsg", SendMsg)
|
||||
s.Table[212] = syscalls.Supported("recvmsg", RecvMsg)
|
||||
s.Table[213] = syscalls.Supported("readahead", Readahead)
|
||||
s.Table[221] = syscalls.Supported("execve", Execve)
|
||||
s.Table[221] = syscalls.SupportedPoint("execve", Execve, linux.PointExecve)
|
||||
s.Table[222] = syscalls.Supported("mmap", Mmap)
|
||||
s.Table[223] = syscalls.PartiallySupported("fadvise64", Fadvise64, "Not all options are supported.", nil)
|
||||
s.Table[242] = syscalls.Supported("accept4", Accept4)
|
||||
@@ -274,7 +274,7 @@ func Override() {
|
||||
s.Table[269] = syscalls.Supported("sendmmsg", SendMMsg)
|
||||
s.Table[276] = syscalls.Supported("renameat2", Renameat2)
|
||||
s.Table[279] = syscalls.Supported("memfd_create", MemfdCreate)
|
||||
s.Table[281] = syscalls.Supported("execveat", Execveat)
|
||||
s.Table[281] = syscalls.SupportedPoint("execveat", Execveat, linux.PointExecveat)
|
||||
s.Table[286] = syscalls.Supported("preadv2", Preadv2)
|
||||
s.Table[287] = syscalls.Supported("pwritev2", Pwritev2)
|
||||
s.Table[291] = syscalls.Supported("statx", Statx)
|
||||
|
||||
@@ -43,6 +43,14 @@ func Supported(name string, fn kernel.SyscallFn) kernel.Syscall {
|
||||
}
|
||||
}
|
||||
|
||||
// SupportedPoint returns a syscall that is fully supported with a correspoding
|
||||
// seccheck.Point.
|
||||
func SupportedPoint(name string, fn kernel.SyscallFn, cb kernel.SyscallToProto) kernel.Syscall {
|
||||
sys := Supported(name, fn)
|
||||
sys.PointCallback = cb
|
||||
return sys
|
||||
}
|
||||
|
||||
// PartiallySupported returns a syscall that has a partial implementation.
|
||||
func PartiallySupported(name string, fn kernel.SyscallFn, note string, urls []string) kernel.Syscall {
|
||||
return kernel.Syscall{
|
||||
@@ -54,6 +62,14 @@ func PartiallySupported(name string, fn kernel.SyscallFn, note string, urls []st
|
||||
}
|
||||
}
|
||||
|
||||
// PartiallySupportedPoint returns a syscall that has a partial implementation
|
||||
// with a correspoding seccheck.Point.
|
||||
func PartiallySupportedPoint(name string, fn kernel.SyscallFn, cb kernel.SyscallToProto, note string, urls []string) kernel.Syscall {
|
||||
sys := PartiallySupported(name, fn, note, urls)
|
||||
sys.PointCallback = cb
|
||||
return sys
|
||||
}
|
||||
|
||||
// Error returns a syscall handler that will always give the passed error.
|
||||
func Error(name string, err error, note string, urls []string) kernel.Syscall {
|
||||
if note != "" {
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user