Compare commits

...

12 Commits

Author SHA1 Message Date
Christian Blichmann 597b4430ba GitHub workflows: Combine SAPI generator build and "prerelease"
PiperOrigin-RevId: 604644955
Change-Id: Ie855b0d5699d1f8e201d2ecae821f7adb2c75c17
2024-02-06 07:48:38 -08:00
A. Cody Schuffelen f708270f35 Add `DefaultAction(TraceAllSyscalls)` variant to `PolicyBuilder`
This helps write the kind of 'log, but allow' policy described in
[`notify.h`](b9c84a1f75/sandboxed_api/sandbox2/notify.h (L57)) for all system calls not mentioned explicitly. One use case is writing a "permissive mode" runtime to give more information during development.

PiperOrigin-RevId: 603766051
Change-Id: I3c72f433a1e21c330b5dd9f1ede2faa570b75b09
2024-02-02 13:01:37 -08:00
Wiktor Garbacz 044ba1cb90 Return ENOSYS instead of hard denying clone3
It's currently not possible to properly inspect arguments of clone3 via seccomp.
As userspace (notably glibc) started using clone3, other sandbox solutions (e.g. in Firefox and Chrome) switched to returning ENOSYS for that syscall, which usually will result in libraries falling back to clone/clone2.

PiperOrigin-RevId: 603332131
Change-Id: If2483f6f42eca46e1c8958ef17ca3c02fa82b658
2024-02-01 04:39:02 -08:00
Wiktor Garbacz 29a3b8cd39 Add AllowAccess to SAPI's default policy
The syscalls are fairly common and low risk.

PiperOrigin-RevId: 603312020
Change-Id: Id06bddc4e7fcc879cad567361ae5b0bad9533142
2024-02-01 02:51:48 -08:00
Chris Kennelly b9c84a1f75 Allow restartable sequences access to poll.
This is used as part of reading the proc files that tell us how many CPUs are
present.

PiperOrigin-RevId: 602953725
Change-Id: I0b64c8d3992119bb956d262cd0f39500a680cc60
2024-01-30 23:48:37 -08:00
Chris Kennelly 0e98cceb32 Permit TCMalloc to use MAP_FIXED_NOREPLACE.
PiperOrigin-RevId: 602616926
Change-Id: I6337f740baebea6f8c63622a502a200c6f7bdb47
2024-01-29 23:13:59 -08:00
Oliver Kunz f2840b37a3 NullPtr: Change SAPI to accept regular `nullptr` for sandboxed API calls.
This change allows to use a `nullptr` instead to having to instantiate a `sapi:✌️:NullPtr` object.

```
sapi:✌️:NullPtr null;
SAPI_RETURN_IF_ERROR(api.testNullPtr(&null);
```

Becomes:

```
SAPI_RETURN_IF_ERROR(api.testNullPtr(nullptr);
```

PiperOrigin-RevId: 602333882
Change-Id: Ie2517dbedab8c514d7a102c4ef4bad90b34a219d
2024-01-29 03:23:45 -08:00
Wiktor Garbacz fa5360351b Use `absl::string_view` consistently
PiperOrigin-RevId: 600363060
Change-Id: I14e4b78c90d1f66e6b429436b09fad9dcd0f2cfc
2024-01-21 23:42:32 -08:00
Sandboxed API Team 25cfb5ef03 Adding missing syscalls to the syscall tables.
PiperOrigin-RevId: 599971082
Change-Id: Icbec577ccf30a3868e4ac6ec356c3544c3d86aab
2024-01-19 16:46:15 -08:00
Sandboxed API Team 824d894822 Make sandbox2::SyscallTable::GetEntry public and add new helper GetEntries.
PiperOrigin-RevId: 599967495
Change-Id: Iae524c2c9b2829cbdcd51117134223d08e993a01
2024-01-19 16:28:20 -08:00
Wiktor Garbacz 28b45670c2 Allow `sched_getaffinity` in `AllowLlvmSanitizers`
Otherwise sanitizers might CHECK-fail at `pthread_getattr_np` call.

PiperOrigin-RevId: 598809849
Change-Id: I221b25ecc640672586acfa350e2748769e38c70c
2024-01-16 05:18:55 -08:00
Wiktor Garbacz fbfc2b9eac Handle `prlimit64` in `Allow*RLimit`
PiperOrigin-RevId: 598794581
Change-Id: If7898294aab1cf77f9b8007e4a9dc8bd74449f9b
2024-01-16 04:00:31 -08:00
13 changed files with 418 additions and 149 deletions

View File

@ -1,66 +0,0 @@
name: debian-sapi-generator-tool
on: push
jobs:
build:
runs-on: ubuntu-latest
container: debian:10.13
steps:
- uses: actions/checkout@v3
- name: Cache dependencies
uses: actions/cache@v3
with:
key: debian-10.13-clang16
path: |
${{github.workspace}}/build/_deps
- name: Install build tools
run: |
apt-get update
env DEBIAN_FRONTEND=noninteractive \
apt-get install -qy --no-install-recommends \
build-essential \
ca-certificates \
cmake \
file \
git \
gnupg \
libc6-dev \
lsb-release \
make \
ninja-build \
software-properties-common \
wget
wget https://apt.llvm.org/llvm.sh
chmod +x llvm.sh
./llvm.sh 16 all
- name: Configure CMake
run: |
mkdir -p "$GITHUB_WORKSPACE/build"
cmake \
-S "$GITHUB_WORKSPACE" \
-B "$GITHUB_WORKSPACE/build" \
-G Ninja \
-DCMAKE_BUILD_TYPE=Release \
-DSAPI_ENABLE_CLANG_TOOL=ON \
-DSAPI_ENABLE_CLANG_TOOL_STATIC=ON
- name: Build
run: |
cmake \
--build "$GITHUB_WORKSPACE/build" \
--config Release \
--target sapi_generator_tool
( \
cd "$GITHUB_WORKSPACE/build"; \
mv sandboxed_api/tools/clang_generator/sapi_generator_tool \
sapi_generator_tool-linux-x86_64; \
)
- name: Upload Build Artifact
uses: actions/upload-artifact@v3.1.2
with:
name: sapi_generator_tool-linux
path: ${{github.workspace}}/build/sapi_generator_tool-linux-x86_64

View File

@ -1,11 +1,71 @@
name: generate-pre-release
on:
workflow_run:
workflows: [debian-sapi-generator-tool]
types: [completed]
branches: [main]
name: generator-tool
on: push
jobs:
build:
runs-on: ubuntu-latest
container: debian:10.13
steps:
- uses: actions/checkout@v3
- name: Cache dependencies
uses: actions/cache@v3
with:
key: debian-10.13-clang16
path: |
${{github.workspace}}/build/_deps
- name: Install build tools
run: |
apt-get update
env DEBIAN_FRONTEND=noninteractive \
apt-get install -qy --no-install-recommends \
build-essential \
ca-certificates \
cmake \
file \
git \
gnupg \
libc6-dev \
lsb-release \
make \
ninja-build \
software-properties-common \
wget
wget https://apt.llvm.org/llvm.sh
chmod +x llvm.sh
./llvm.sh 16 all
- name: Configure CMake
run: |
mkdir -p "$GITHUB_WORKSPACE/build"
cmake \
-S "$GITHUB_WORKSPACE" \
-B "$GITHUB_WORKSPACE/build" \
-G Ninja \
-DCMAKE_BUILD_TYPE=Release \
-DSAPI_ENABLE_CLANG_TOOL=ON \
-DSAPI_ENABLE_CLANG_TOOL_STATIC=ON
- name: Build
run: |
cmake \
--build "$GITHUB_WORKSPACE/build" \
--config Release \
--target sapi_generator_tool
( \
cd "$GITHUB_WORKSPACE/build"; \
mv sandboxed_api/tools/clang_generator/sapi_generator_tool \
sapi_generator_tool-linux-x86_64; \
)
- name: Upload Build Artifact
uses: actions/upload-artifact@v3.1.2
with:
name: sapi_generator_tool-linux
path: ${{github.workspace}}/build/sapi_generator_tool-linux-x86_64
prerelease:
needs: build
runs-on: ubuntu-latest
env:
ARTIFACT_NAME: sapi_generator_tool-linux
@ -58,3 +118,4 @@ jobs:
prerelease: true
files: |
${{github.workspace}}/build/sapi_generator_tool-linux-x86_64.tar.gz

View File

@ -76,6 +76,7 @@ void InitDefaultPolicyBuilder(sandbox2::PolicyBuilder* builder) {
.AllowGetPIDs()
.AllowSleep()
.AllowReadlink()
.AllowAccess()
.AllowSyscalls({
__NR_recvmsg,
__NR_sendmsg,
@ -324,6 +325,14 @@ absl::Status Sandbox::Call(const std::string& func, v::Callable* ret,
// Copy all arguments into rfcall.
int i = 0;
for (auto* arg : args) {
if (arg == nullptr) {
rfcall.arg_type[i] = v::Type::kPointer;
rfcall.arg_size[i] = sizeof(void*);
rfcall.args[i].arg_int = 0;
VLOG(1) << "CALL ARG: (" << i << "): nullptr";
++i;
continue;
}
rfcall.arg_size[i] = arg->GetSize();
rfcall.arg_type[i] = arg->GetType();
@ -357,7 +366,6 @@ absl::Status Sandbox::Call(const std::string& func, v::Callable* ret,
}
rfcall.args[i].arg_int = fd->GetRemoteFd();
}
VLOG(1) << "CALL ARG: (" << i << "), Type: " << arg->GetTypeString()
<< ", Size: " << arg->GetSize() << ", Val: " << arg->ToString();
++i;
@ -382,7 +390,9 @@ absl::Status Sandbox::Call(const std::string& func, v::Callable* ret,
// Synchronize all pointers after the call if it's needed.
for (auto* arg : args) {
SAPI_RETURN_IF_ERROR(SynchronizePtrAfter(arg));
if (arg != nullptr) {
SAPI_RETURN_IF_ERROR(SynchronizePtrAfter(arg));
}
}
VLOG(1) << "CALL EXIT: Type: " << ret->GetTypeString()

View File

@ -40,6 +40,23 @@ cc_library(
visibility = ["//visibility:public"],
)
cc_library(
name = "trace_all_syscalls",
hdrs = ["trace_all_syscalls.h"],
copts = sapi_platform_copts(),
visibility = [
"//sandboxed_api/sandbox2:__pkg__",
],
)
cc_library(
name = "testonly_trace_all_syscalls",
testonly = True,
hdrs = ["trace_all_syscalls.h"],
copts = sapi_platform_copts(),
visibility = ["//visibility:public"],
)
cc_library(
name = "allow_unrestricted_networking",
hdrs = ["allow_unrestricted_networking.h"],
@ -109,15 +126,18 @@ cc_library(
srcs = [
"syscall.cc",
"syscall_defs.cc",
],
hdrs = [
"syscall.h",
"syscall_defs.h",
],
hdrs = ["syscall.h"],
copts = sapi_platform_copts(),
visibility = ["//visibility:public"],
deps = [
":util",
"//sandboxed_api:config",
"@com_google_absl//absl/algorithm:container",
"@com_google_absl//absl/status",
"@com_google_absl//absl/status:statusor",
"@com_google_absl//absl/strings",
"@com_google_absl//absl/strings:str_format",
@ -560,6 +580,7 @@ cc_library(
":namespace",
":policy",
":syscall",
":trace_all_syscalls",
":violation_cc_proto",
"//sandboxed_api:config",
"//sandboxed_api/sandbox2/network_proxy:filtering",
@ -921,6 +942,7 @@ cc_test(
deps = [
":comms",
":sandbox2",
":trace_all_syscalls",
"//sandboxed_api:testing",
"@com_google_absl//absl/log",
"@com_google_absl//absl/strings",

View File

@ -26,6 +26,15 @@ target_link_libraries(sandbox2_allow_all_syscalls PRIVATE
sapi::base
)
# sandboxed_api/sandbox2:trace_all_syscalls
add_library(sandbox2_trace_all_syscalls ${SAPI_LIB_TYPE}
trace_all_syscalls.h
)
add_library(sandbox2::trace_all_syscalls ALIAS sandbox2_trace_all_syscalls)
target_link_libraries(sandbox2_trace_all_syscalls PRIVATE
sapi::base
)
# sandboxed_api/sandbox2:allow_unrestricted_networking
add_library(sandbox2_allow_unrestricted_networking ${SAPI_LIB_TYPE}
allow_unrestricted_networking.h
@ -994,6 +1003,7 @@ if(BUILD_TESTING AND SAPI_BUILD_TESTING)
sandbox2::comms
sandbox2::regs
sandbox2::sandbox2
sandbox2::trace_all_syscalls
sapi::testing
sapi::test_main
)

View File

@ -33,6 +33,7 @@
#include "sandboxed_api/sandbox2/policybuilder.h"
#include "sandboxed_api/sandbox2/sandbox2.h"
#include "sandboxed_api/sandbox2/syscall.h"
#include "sandboxed_api/sandbox2/trace_all_syscalls.h"
#include "sandboxed_api/testing.h"
namespace sandbox2 {
@ -126,5 +127,21 @@ TEST(NotifyTest, PrintPidAndComms) {
EXPECT_THAT(result.reason_code(), Eq(33));
}
// Test EventSyscallTrap on personality syscall through TraceAllSyscalls
TEST(NotifyTest, TraceAllAllowPersonality) {
const std::string path = GetTestSourcePath("sandbox2/testcases/personality");
std::vector<std::string> args = {path};
auto policy = CreateDefaultPermissiveTestPolicy(path)
.DefaultAction(TraceAllSyscalls())
.BuildOrDie();
Sandbox2 s2(std::make_unique<Executor>(path, args),
NotifyTestcasePolicy(path),
std::make_unique<PersonalityNotify>(/*allow=*/true));
auto result = s2.Run();
ASSERT_THAT(result.final_status(), Eq(Result::OK));
EXPECT_THAT(result.reason_code(), Eq(22));
}
} // namespace
} // namespace sandbox2

View File

@ -183,8 +183,9 @@ std::vector<sock_filter> Policy::GetDefaultPolicy(bool user_notif) const {
policy.insert(policy.end(),
{
#ifdef __NR_clone3
// Disallow clone3
JEQ32(__NR_clone3, DENY),
// Disallow clone3. Errno instead of DENY so that libraries
// can fallback to regular clone/clone2.
JEQ32(__NR_clone3, ERRNO(ENOSYS)),
#endif
// Disallow clone3 and clone with unsafe flags. This uses
// LOAD_SYSCALL_NR from above.

View File

@ -60,6 +60,7 @@
#include "sandboxed_api/sandbox2/namespace.h"
#include "sandboxed_api/sandbox2/policy.h"
#include "sandboxed_api/sandbox2/syscall.h"
#include "sandboxed_api/sandbox2/trace_all_syscalls.h"
#include "sandboxed_api/sandbox2/util/bpf_helper.h"
#include "sandboxed_api/sandbox2/violation.pb.h"
#include "sandboxed_api/util/path.h"
@ -70,6 +71,9 @@
#include <asm/termbits.h> // On PPC, TCGETS macro needs termios
#endif
#ifndef MAP_FIXED_NOREPLACE
#define MAP_FIXED_NOREPLACE 0x100000
#endif
#ifndef PR_SET_VMA
#define PR_SET_VMA 0x53564d41
#endif
@ -285,6 +289,7 @@ PolicyBuilder& PolicyBuilder::AllowTcMalloc() {
LABEL(&labels, prot_none),
ARG_32(3), // flags
JEQ32(MAP_ANONYMOUS | MAP_PRIVATE | MAP_NORESERVE, ALLOW),
JEQ32(MAP_ANONYMOUS | MAP_PRIVATE | MAP_FIXED_NOREPLACE, ALLOW),
JEQ32(MAP_ANONYMOUS | MAP_PRIVATE, ALLOW),
LABEL(&labels, mmap_end),
@ -359,7 +364,7 @@ PolicyBuilder& PolicyBuilder::AllowLlvmSanitizers() {
OverridableBlockSyscallWithErrno(__NR_ioctl, EPERM);
// https://github.com/llvm/llvm-project/blob/9aa39481d9eb718e872993791547053a3c1f16d5/compiler-rt/lib/sanitizer_common/sanitizer_linux_libcdep.cpp#L150
// https://sourceware.org/git/?p=glibc.git;a=blob;f=nptl/pthread_getattr_np.c;h=de7edfa0928224eb8375e2fe894d6677570fbb3b;hb=HEAD#l188
OverridableBlockSyscallWithErrno(__NR_sched_getaffinity, EPERM);
AllowSyscall(__NR_sched_getaffinity);
// https://github.com/llvm/llvm-project/blob/02c2b472b510ff55679844c087b66e7837e13dc2/compiler-rt/lib/sanitizer_common/sanitizer_linux.cpp#L434
#ifdef __NR_readlink
OverridableBlockSyscallWithErrno(__NR_readlink, ENOENT);
@ -768,6 +773,7 @@ PolicyBuilder& PolicyBuilder::AllowRestartableSequences(
AllowFutexOp(FUTEX_WAKE);
AllowRead();
AllowOpen();
AllowPoll();
AllowSyscall(__NR_close);
AddPolicyOnSyscall(__NR_rt_sigprocmask, {
ARG_32(0),
@ -805,6 +811,9 @@ PolicyBuilder& PolicyBuilder::AllowGetPGIDs() {
}
PolicyBuilder& PolicyBuilder::AllowGetRlimit() {
#ifdef __NR_prlimit64
AddPolicyOnSyscall(__NR_prlimit64, {ARG(2), JEQ64(0, 0, ALLOW)});
#endif
return AllowSyscalls({
#ifdef __NR_getrlimit
__NR_getrlimit,
@ -817,6 +826,9 @@ PolicyBuilder& PolicyBuilder::AllowGetRlimit() {
PolicyBuilder& PolicyBuilder::AllowSetRlimit() {
return AllowSyscalls({
#ifdef __NR_prlimit64
__NR_prlimit64,
#endif
#ifdef __NR_setrlimit
__NR_setrlimit,
#endif
@ -865,7 +877,7 @@ PolicyBuilder& PolicyBuilder::AllowLogForwarding() {
ARG_32(0),
JEQ32(SIG_BLOCK, ALLOW),
});
AllowSyscall(__NR_prlimit64);
AllowGetRlimit();
// For LOG(FATAL)
return AddPolicyOnSyscall(__NR_kill,
@ -999,9 +1011,7 @@ PolicyBuilder& PolicyBuilder::AllowStaticStartup() {
OverridableBlockSyscallWithErrno(__NR_readlink, ENOENT);
#endif
#ifdef __NR_prlimit64
OverridableBlockSyscallWithErrno(__NR_prlimit64, EPERM);
#endif
AllowGetRlimit();
AddPolicyOnSyscall(__NR_mprotect, {
ARG_32(2),
JEQ32(PROT_READ, ALLOW),
@ -1235,6 +1245,11 @@ PolicyBuilder& PolicyBuilder::DefaultAction(AllowAllSyscalls) {
return *this;
}
PolicyBuilder& PolicyBuilder::DefaultAction(TraceAllSyscalls) {
default_action_ = SANDBOX2_TRACE;
return *this;
}
absl::StatusOr<std::string> PolicyBuilder::ValidateAbsolutePath(
absl::string_view path) {
if (!file::IsAbsolutePath(path)) {

View File

@ -43,6 +43,7 @@ struct bpf_labels;
namespace sandbox2 {
class AllowAllSyscalls;
class TraceAllSyscalls;
class UnrestrictedNetworking;
// PolicyBuilder is a helper class to simplify creation of policies. The builder
@ -712,6 +713,12 @@ class PolicyBuilder final {
// sandbox-team@ first if unsure.
PolicyBuilder& DefaultAction(AllowAllSyscalls);
// Changes the default action to SANDBOX2_TRACE.
// All syscalls not handled explicitly by the policy will be passed off to
// the `sandbox2::Notify` implementation given to the `sandbox2::Sandbox2`
// instance.
PolicyBuilder& DefaultAction(TraceAllSyscalls);
ABSL_DEPRECATED("Use DefaultAction(sandbox2::AllowAllSyscalls()) instead")
PolicyBuilder& DangerDefaultAllowAll();

View File

@ -8,6 +8,7 @@
#include <vector>
#include "absl/algorithm/container.h"
#include "absl/status/status.h"
#include "absl/status/statusor.h"
#include "absl/strings/escaping.h"
#include "absl/strings/str_cat.h"
@ -18,56 +19,15 @@
namespace sandbox2 {
// Type of a given syscall argument. Used with argument conversion routines.
enum ArgType {
kGen = 1,
kInt,
kPath,
kHex,
kOct,
kSocketCall,
kSocketCallPtr,
kSignal,
kString,
kAddressFamily,
kSockaddr,
kSockmsghdr,
kCloneFlag,
};
// Single syscall definition
struct SyscallTable::Entry {
// Returns the number of arguments which given syscall takes.
int GetNumArgs() const {
if (num_args < 0 || num_args > syscalls::kMaxArgs) {
return syscalls::kMaxArgs;
}
return num_args;
}
static std::string GetArgumentDescription(uint64_t value, ArgType type,
pid_t pid);
static constexpr bool BySyscallNr(const SyscallTable::Entry& a,
const SyscallTable::Entry& b) {
return a.nr < b.nr;
}
int nr;
absl::string_view name;
int num_args;
std::array<ArgType, syscalls::kMaxArgs> arg_types;
};
std::string SyscallTable::Entry::GetArgumentDescription(uint64_t value,
ArgType type,
syscalls::ArgType type,
pid_t pid) {
std::string ret = absl::StrFormat("%#x", value);
switch (type) {
case kOct:
case syscalls::kOct:
absl::StrAppendFormat(&ret, " [\\0%o]", value);
break;
case kPath:
case syscalls::kPath:
if (auto path_or = util::ReadCPathFromPid(pid, value); path_or.ok()) {
absl::StrAppendFormat(&ret, " ['%s']",
absl::CHexEscape(path_or.value()));
@ -75,7 +35,7 @@ std::string SyscallTable::Entry::GetArgumentDescription(uint64_t value,
absl::StrAppend(&ret, " [unreadable path]");
}
break;
case kInt:
case syscalls::kInt:
absl::StrAppendFormat(&ret, " [%d]", value);
break;
default:
@ -85,14 +45,11 @@ std::string SyscallTable::Entry::GetArgumentDescription(uint64_t value,
}
absl::string_view SyscallTable::GetName(int syscall) const {
auto it = absl::c_lower_bound(
data_, syscall, [](const SyscallTable::Entry& entry, int syscall) {
return entry.nr < syscall;
});
if (it == data_.end() || it->nr != syscall) {
auto entry = GetEntry(syscall);
if (!entry.ok()) {
return "";
}
return it->name;
return entry->name;
}
namespace {
@ -108,32 +65,61 @@ constexpr SyscallTable::Entry MakeEntry(int nr, absl::string_view name,
struct UnknownArguments {};
constexpr SyscallTable::Entry MakeEntry(int nr, absl::string_view name,
UnknownArguments) {
return {nr, name, -1, {kGen, kGen, kGen, kGen, kGen, kGen}};
return {nr,
name,
-1,
{syscalls::kGen, syscalls::kGen, syscalls::kGen, syscalls::kGen,
syscalls::kGen, syscalls::kGen}};
}
} // namespace
absl::StatusOr<SyscallTable::Entry> SyscallTable::GetEntry(int syscall) const {
auto it = absl::c_lower_bound(
data_, syscall, [](const SyscallTable::Entry& entry, int syscall) {
return entry.nr < syscall;
});
if (it == data_.end() || it->nr != syscall) {
return absl::NotFoundError(absl::StrCat("Syscall not found: ", syscall));
}
return *it;
}
absl::StatusOr<SyscallTable::Entry> SyscallTable::GetEntry(
absl::string_view name) const {
// Note: There's no uniqueness guarantee of syscall names in the table, but
// other than typos it's likely safe to assume uniqueness.
auto filter = [name](const SyscallTable::Entry& entry) {
return entry.name == name;
};
auto it = absl::c_find_if(data_, filter);
if (it != data_.end()) {
return *it;
} else {
return absl::NotFoundError(absl::StrCat("Name not found: ", name));
}
}
std::vector<std::string> SyscallTable::GetArgumentsDescription(
int syscall, const uint64_t values[], pid_t pid) const {
static SyscallTable::Entry kInvalidEntry =
MakeEntry(-1, "", UnknownArguments());
auto it = absl::c_lower_bound(
data_, syscall, [](const SyscallTable::Entry& entry, int syscall) {
return entry.nr < syscall;
});
const auto& entry =
it != data_.end() && it->nr == syscall ? *it : kInvalidEntry;
auto entry = GetEntry(syscall);
if (!entry.ok()) {
entry = kInvalidEntry;
}
int num_args = entry.GetNumArgs();
int num_args = entry->GetNumArgs();
std::vector<std::string> rv;
rv.reserve(num_args);
for (int i = 0; i < num_args; ++i) {
rv.push_back(SyscallTable::Entry::GetArgumentDescription(
values[i], entry.arg_types[i], pid));
values[i], entry->arg_types[i], pid));
}
return rv;
}
namespace syscalls {
namespace {
// TODO(C++20) Use std::is_sorted
@ -495,6 +481,32 @@ constexpr std::array kSyscallDataX8664 = {
MakeEntry(333, "io_pgetevents", UnknownArguments()),
MakeEntry(334, "rseq", kHex, kInt, kHex, kHex),
MakeEntry(435, "clone3", kHex, kInt),
MakeEntry(436, "close_range", kInt, kInt, kHex),
MakeEntry(437, "openat2", kInt, kPath, kHex, kInt),
MakeEntry(438, "pidfd_getfd", UnknownArguments()),
MakeEntry(439, "faccessat2", kInt, kPath, kHex, kHex),
MakeEntry(440, "process_madvise", UnknownArguments()),
MakeEntry(441, "epoll_pwait2", UnknownArguments()),
MakeEntry(442, "mount_setattr", UnknownArguments()),
MakeEntry(443, "quotactl_fd", UnknownArguments()),
MakeEntry(444, "landlock_create_ruleset", UnknownArguments()),
MakeEntry(445, "landlock_add_rule", UnknownArguments()),
MakeEntry(446, "landlock_restrict_self", UnknownArguments()),
MakeEntry(447, "memfd_secret", UnknownArguments()),
MakeEntry(448, "process_mrelease", UnknownArguments()),
MakeEntry(449, "futex_waitv", UnknownArguments()),
MakeEntry(450, "set_mempolicy_home_node", UnknownArguments()),
MakeEntry(451, "cachestat", UnknownArguments()),
MakeEntry(452, "fchmodat2", kInt, kPath, kHex, kHex),
MakeEntry(453, "map_shadow_stack", UnknownArguments()),
MakeEntry(454, "futex_wake", UnknownArguments()),
MakeEntry(455, "futex_wait", UnknownArguments()),
MakeEntry(456, "futex_requeue", UnknownArguments()),
MakeEntry(457, "statmount", UnknownArguments()),
MakeEntry(458, "listmount", UnknownArguments()),
MakeEntry(459, "lsm_get_self_attr", UnknownArguments()),
MakeEntry(460, "lsm_set_self_attr", UnknownArguments()),
MakeEntry(461, "lsm_list_modules", UnknownArguments()),
// clang-format on
};
@ -862,6 +874,32 @@ constexpr std::array kSyscallDataX8632 = {
MakeEntry(356, "memfd_create", kString, kHex),
MakeEntry(357, "bpf", kInt, kHex, kInt),
MakeEntry(435, "clone3", kHex, kInt),
MakeEntry(436, "close_range", kInt, kInt, kHex),
MakeEntry(437, "openat2", kInt, kPath, kHex, kInt),
MakeEntry(438, "pidfd_getfd", UnknownArguments()),
MakeEntry(439, "faccessat2", kInt, kPath, kHex, kHex),
MakeEntry(440, "process_madvise", UnknownArguments()),
MakeEntry(441, "epoll_pwait2", UnknownArguments()),
MakeEntry(442, "mount_setattr", UnknownArguments()),
MakeEntry(443, "quotactl_fd", UnknownArguments()),
MakeEntry(444, "landlock_create_ruleset", UnknownArguments()),
MakeEntry(445, "landlock_add_rule", UnknownArguments()),
MakeEntry(446, "landlock_restrict_self", UnknownArguments()),
MakeEntry(447, "memfd_secret", UnknownArguments()),
MakeEntry(448, "process_mrelease", UnknownArguments()),
MakeEntry(449, "futex_waitv", UnknownArguments()),
MakeEntry(450, "set_mempolicy_home_node", UnknownArguments()),
MakeEntry(451, "cachestat", UnknownArguments()),
MakeEntry(452, "fchmodat2", kInt, kPath, kHex, kHex),
MakeEntry(453, "map_shadow_stack", UnknownArguments()),
MakeEntry(454, "futex_wake", UnknownArguments()),
MakeEntry(455, "futex_wait", UnknownArguments()),
MakeEntry(456, "futex_requeue", UnknownArguments()),
MakeEntry(457, "statmount", UnknownArguments()),
MakeEntry(458, "listmount", UnknownArguments()),
MakeEntry(459, "lsm_get_self_attr", UnknownArguments()),
MakeEntry(460, "lsm_set_self_attr", UnknownArguments()),
MakeEntry(461, "lsm_list_modules", UnknownArguments()),
// clang-format on
};
@ -1242,6 +1280,31 @@ constexpr std::array kSyscallDataPPC64LE = {
MakeEntry(380, "preadv2", kInt, kHex, kInt, kInt, kInt, kHex),
MakeEntry(381, "pwritev2", kInt, kHex, kInt, kInt, kInt, kHex),
MakeEntry(435, "clone3", kHex, kInt),
MakeEntry(436, "close_range", kInt, kInt, kHex),
MakeEntry(437, "openat2", kInt, kPath, kHex, kInt),
MakeEntry(438, "pidfd_getfd", UnknownArguments()),
MakeEntry(439, "faccessat2", kInt, kPath, kHex, kHex),
MakeEntry(440, "process_madvise", UnknownArguments()),
MakeEntry(441, "epoll_pwait2", UnknownArguments()),
MakeEntry(442, "mount_setattr", UnknownArguments()),
MakeEntry(443, "quotactl_fd", UnknownArguments()),
MakeEntry(444, "landlock_create_ruleset", UnknownArguments()),
MakeEntry(445, "landlock_add_rule", UnknownArguments()),
MakeEntry(446, "landlock_restrict_self", UnknownArguments()),
MakeEntry(448, "process_mrelease", UnknownArguments()),
MakeEntry(449, "futex_waitv", UnknownArguments()),
MakeEntry(450, "set_mempolicy_home_node", UnknownArguments()),
MakeEntry(451, "cachestat", UnknownArguments()),
MakeEntry(452, "fchmodat2", kInt, kPath, kHex, kHex),
MakeEntry(453, "map_shadow_stack", UnknownArguments()),
MakeEntry(454, "futex_wake", UnknownArguments()),
MakeEntry(455, "futex_wait", UnknownArguments()),
MakeEntry(456, "futex_requeue", UnknownArguments()),
MakeEntry(457, "statmount", UnknownArguments()),
MakeEntry(458, "listmount", UnknownArguments()),
MakeEntry(459, "lsm_get_self_attr", UnknownArguments()),
MakeEntry(460, "lsm_set_self_attr", UnknownArguments()),
MakeEntry(461, "lsm_list_modules", UnknownArguments()),
// clang-format on
};
@ -1524,6 +1587,31 @@ constexpr std::array kSyscallDataArm64 = {
MakeEntry(286, "preadv2", kInt, kHex, kInt, kInt, kInt, kHex),
MakeEntry(287, "pwritev2", kInt, kHex, kInt, kInt, kInt, kHex),
MakeEntry(435, "clone3", kHex, kInt),
MakeEntry(436, "close_range", kInt, kInt, kHex),
MakeEntry(437, "openat2", kInt, kPath, kHex, kInt),
MakeEntry(438, "pidfd_getfd", UnknownArguments()),
MakeEntry(439, "faccessat2", kInt, kPath, kHex, kHex),
MakeEntry(440, "process_madvise", UnknownArguments()),
MakeEntry(441, "epoll_pwait2", UnknownArguments()),
MakeEntry(442, "mount_setattr", UnknownArguments()),
MakeEntry(443, "quotactl_fd", UnknownArguments()),
MakeEntry(444, "landlock_create_ruleset", UnknownArguments()),
MakeEntry(445, "landlock_add_rule", UnknownArguments()),
MakeEntry(446, "landlock_restrict_self", UnknownArguments()),
MakeEntry(448, "process_mrelease", UnknownArguments()),
MakeEntry(449, "futex_waitv", UnknownArguments()),
MakeEntry(450, "set_mempolicy_home_node", UnknownArguments()),
MakeEntry(451, "cachestat", UnknownArguments()),
MakeEntry(452, "fchmodat2", kInt, kPath, kHex, kHex),
MakeEntry(453, "map_shadow_stack", UnknownArguments()),
MakeEntry(454, "futex_wake", UnknownArguments()),
MakeEntry(455, "futex_wait", UnknownArguments()),
MakeEntry(456, "futex_requeue", UnknownArguments()),
MakeEntry(457, "statmount", UnknownArguments()),
MakeEntry(458, "listmount", UnknownArguments()),
MakeEntry(459, "lsm_get_self_attr", UnknownArguments()),
MakeEntry(460, "lsm_set_self_attr", UnknownArguments()),
MakeEntry(461, "lsm_list_modules", UnknownArguments()),
// clang-format on
};
@ -1882,6 +1970,31 @@ constexpr std::array kSyscallDataArm32 = {
MakeEntry(400, "migrate_pages", kGen, kGen, kGen, kGen),
MakeEntry(401, "kexec_file_load", kInt, kInt, kInt, kString, kHex),
MakeEntry(435, "clone3", kHex, kInt),
MakeEntry(436, "close_range", kInt, kInt, kHex),
MakeEntry(437, "openat2", kInt, kPath, kHex, kInt),
MakeEntry(438, "pidfd_getfd", UnknownArguments()),
MakeEntry(439, "faccessat2", kInt, kPath, kHex, kHex),
MakeEntry(440, "process_madvise", UnknownArguments()),
MakeEntry(441, "epoll_pwait2", UnknownArguments()),
MakeEntry(442, "mount_setattr", UnknownArguments()),
MakeEntry(443, "quotactl_fd", UnknownArguments()),
MakeEntry(444, "landlock_create_ruleset", UnknownArguments()),
MakeEntry(445, "landlock_add_rule", UnknownArguments()),
MakeEntry(446, "landlock_restrict_self", UnknownArguments()),
MakeEntry(448, "process_mrelease", UnknownArguments()),
MakeEntry(449, "futex_waitv", UnknownArguments()),
MakeEntry(450, "set_mempolicy_home_node", UnknownArguments()),
MakeEntry(451, "cachestat", UnknownArguments()),
MakeEntry(452, "fchmodat2", kInt, kPath, kHex, kHex),
MakeEntry(453, "map_shadow_stack", UnknownArguments()),
MakeEntry(454, "futex_wake", UnknownArguments()),
MakeEntry(455, "futex_wait", UnknownArguments()),
MakeEntry(456, "futex_requeue", UnknownArguments()),
MakeEntry(457, "statmount", UnknownArguments()),
MakeEntry(458, "listmount", UnknownArguments()),
MakeEntry(459, "lsm_get_self_attr", UnknownArguments()),
MakeEntry(460, "lsm_set_self_attr", UnknownArguments()),
MakeEntry(461, "lsm_list_modules", UnknownArguments()),
MakeEntry(0xf0001, "ARM_breakpoint", kHex, kHex, kHex, kHex),
MakeEntry(0xf0002, "ARM_cacheflush", kHex, kHex, kHex, kHex),
MakeEntry(0xf0003, "ARM_usr26", kHex, kHex, kHex, kHex),
@ -1894,19 +2007,20 @@ static_assert(IsSorted(kSyscallDataArm32, SyscallTable::Entry::BySyscallNr),
"Syscalls should be sorted");
} // namespace
} // namespace syscalls
SyscallTable SyscallTable::get(sapi::cpu::Architecture arch) {
switch (arch) {
case sapi::cpu::kX8664:
return SyscallTable(kSyscallDataX8664);
return SyscallTable(syscalls::kSyscallDataX8664);
case sapi::cpu::kX86:
return SyscallTable(kSyscallDataX8632);
return SyscallTable(syscalls::kSyscallDataX8632);
case sapi::cpu::kPPC64LE:
return SyscallTable(kSyscallDataPPC64LE);
return SyscallTable(syscalls::kSyscallDataPPC64LE);
case sapi::cpu::kArm64:
return SyscallTable(kSyscallDataArm64);
return SyscallTable(syscalls::kSyscallDataArm64);
case sapi::cpu::kArm:
return SyscallTable(kSyscallDataArm32);
return SyscallTable(syscalls::kSyscallDataArm32);
default:
return SyscallTable();
}

View File

@ -3,10 +3,12 @@
#include <sys/types.h>
#include <array>
#include <cstdint>
#include <string>
#include <vector>
#include "absl/status/statusor.h"
#include "absl/strings/string_view.h"
#include "absl/types/span.h"
#include "sandboxed_api/config.h"
@ -17,11 +19,51 @@ namespace syscalls {
constexpr int kMaxArgs = 6;
// Type of a given syscall argument. Used with argument conversion routines.
enum ArgType {
kGen = 1,
kInt,
kPath,
kHex,
kOct,
kSocketCall,
kSocketCallPtr,
kSignal,
kString,
kAddressFamily,
kSockaddr,
kSockmsghdr,
kCloneFlag,
};
} // namespace syscalls
class SyscallTable {
public:
struct Entry;
// Single syscall definition
struct Entry {
// Returns the number of arguments which given syscall takes.
int GetNumArgs() const {
if (num_args < 0 || num_args > syscalls::kMaxArgs) {
return syscalls::kMaxArgs;
}
return num_args;
}
static std::string GetArgumentDescription(uint64_t value,
syscalls::ArgType type,
pid_t pid);
static constexpr bool BySyscallNr(const SyscallTable::Entry& a,
const SyscallTable::Entry& b) {
return a.nr < b.nr;
}
int nr;
absl::string_view name;
int num_args;
std::array<syscalls::ArgType, syscalls::kMaxArgs> arg_types;
};
// Returns the syscall table for the architecture.
static SyscallTable get(sapi::cpu::Architecture arch);
@ -34,6 +76,12 @@ class SyscallTable {
const uint64_t values[],
pid_t pid) const;
absl::StatusOr<Entry> GetEntry(int syscall) const;
// Returns the first entry matching the provided name.
absl::StatusOr<Entry> GetEntry(absl::string_view name) const;
absl::Span<const Entry> GetEntries() const { return data_; }
private:
constexpr SyscallTable() = default;
explicit constexpr SyscallTable(absl::Span<const Entry> data) : data_(data) {}

View File

@ -0,0 +1,27 @@
// Copyright 2024 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
//
// https://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.
#ifndef SANDBOXED_API_SANDBOX2_TRACE_ALL_SYSCALLS_H_
#define SANDBOXED_API_SANDBOX2_TRACE_ALL_SYSCALLS_H_
namespace sandbox2 {
class TraceAllSyscalls {
public:
explicit TraceAllSyscalls() = default;
};
} // namespace sandbox2
#endif // SANDBOXED_API_SANDBOX2_ALLOW_ALL_SYSCALLS_H_

View File

@ -20,6 +20,7 @@
#include <memory>
#include <string>
#include "absl/base/attributes.h"
#include "absl/base/macros.h"
#include "absl/strings/str_format.h"
#include "sandboxed_api/var_abstract.h"
@ -79,7 +80,9 @@ class Ptr : public Reg<Var*> {
};
// Good, old nullptr
class NullPtr : public Ptr {
class ABSL_DEPRECATED(
"Use regular `nullptr` or `NULL` instead. This class will eventually get "
"removed") NullPtr : public Ptr {
public:
NullPtr() : Ptr(&void_obj_, SyncType::kSyncNone) {}