diff options
Diffstat (limited to 'chromium/sandbox/linux/syscall_broker')
8 files changed, 135 insertions, 103 deletions
diff --git a/chromium/sandbox/linux/syscall_broker/DEPS b/chromium/sandbox/linux/syscall_broker/DEPS index c477f7d3639..149c463b068 100644 --- a/chromium/sandbox/linux/syscall_broker/DEPS +++ b/chromium/sandbox/linux/syscall_broker/DEPS @@ -1,4 +1,5 @@ include_rules = [ - "+sandbox/linux/system_headers", "+sandbox/linux/bpf_dsl", + "+sandbox/linux/services", + "+sandbox/linux/system_headers", ] diff --git a/chromium/sandbox/linux/syscall_broker/broker_client.cc b/chromium/sandbox/linux/syscall_broker/broker_client.cc index 6b1b5be4338..e24f659fcf8 100644 --- a/chromium/sandbox/linux/syscall_broker/broker_client.cc +++ b/chromium/sandbox/linux/syscall_broker/broker_client.cc @@ -166,7 +166,7 @@ int BrokerClient::Rmdir(const char* path) const { int BrokerClient::Stat(const char* pathname, bool follow_links, - struct stat* sb) const { + struct kernel_stat* sb) const { if (!pathname || !sb) return -EFAULT; @@ -181,7 +181,7 @@ int BrokerClient::Stat(const char* pathname, int BrokerClient::Stat64(const char* pathname, bool follow_links, - struct stat64* sb) const { + struct kernel_stat64* sb) const { if (!pathname || !sb) return -EFAULT; diff --git a/chromium/sandbox/linux/syscall_broker/broker_client.h b/chromium/sandbox/linux/syscall_broker/broker_client.h index 05e14c83f20..26ca78101c7 100644 --- a/chromium/sandbox/linux/syscall_broker/broker_client.h +++ b/chromium/sandbox/linux/syscall_broker/broker_client.h @@ -61,10 +61,10 @@ class SANDBOX_EXPORT BrokerClient : public SyscallDispatcher { int Rmdir(const char* path) const override; int Stat(const char* pathname, bool follow_links, - struct stat* sb) const override; + struct kernel_stat* sb) const override; int Stat64(const char* pathname, bool follow_links, - struct stat64* sb) const override; + struct kernel_stat64* sb) const override; int Unlink(const char* unlink) const override; private: diff --git a/chromium/sandbox/linux/syscall_broker/broker_host.cc b/chromium/sandbox/linux/syscall_broker/broker_host.cc index 1cd03a18df8..1cdc01a888f 100644 --- a/chromium/sandbox/linux/syscall_broker/broker_host.cc +++ b/chromium/sandbox/linux/syscall_broker/broker_host.cc @@ -20,9 +20,11 @@ #include "base/files/scoped_file.h" #include "base/logging.h" #include "base/posix/eintr_wrapper.h" +#include "sandbox/linux/services/syscall_wrappers.h" #include "sandbox/linux/syscall_broker/broker_command.h" #include "sandbox/linux/syscall_broker/broker_permission_list.h" #include "sandbox/linux/syscall_broker/broker_simple_message.h" +#include "sandbox/linux/system_headers/linux_stat.h" #include "sandbox/linux/system_headers/linux_syscalls.h" namespace sandbox { @@ -193,10 +195,12 @@ void StatFileForIPC(const BrokerCommandSet& allowed_command_set, RAW_CHECK(reply->AddIntToMessage(-permission_list.denied_errno())); return; } + if (command_type == COMMAND_STAT) { - struct stat sb; - int sts = - follow_links ? stat(file_to_access, &sb) : lstat(file_to_access, &sb); + struct kernel_stat sb; + + int sts = follow_links ? sandbox::sys_stat(file_to_access, &sb) + : sandbox::sys_lstat(file_to_access, &sb); if (sts < 0) { RAW_CHECK(reply->AddIntToMessage(-errno)); return; @@ -205,10 +209,12 @@ void StatFileForIPC(const BrokerCommandSet& allowed_command_set, RAW_CHECK( reply->AddDataToMessage(reinterpret_cast<char*>(&sb), sizeof(sb))); } else { +#if defined(__NR_fstatat64) DCHECK(command_type == COMMAND_STAT64); - struct stat64 sb; - int sts = follow_links ? stat64(file_to_access, &sb) - : lstat64(file_to_access, &sb); + struct kernel_stat64 sb; + + int sts = sandbox::sys_fstatat64(AT_FDCWD, file_to_access, &sb, + follow_links ? 0 : AT_SYMLINK_NOFOLLOW); if (sts < 0) { RAW_CHECK(reply->AddIntToMessage(-errno)); return; @@ -216,6 +222,11 @@ void StatFileForIPC(const BrokerCommandSet& allowed_command_set, RAW_CHECK(reply->AddIntToMessage(0)); RAW_CHECK( reply->AddDataToMessage(reinterpret_cast<char*>(&sb), sizeof(sb))); +#else // defined(__NR_fstatat64) + // We should not reach here on 64-bit systems, as the *stat*64() are only + // necessary on 32-bit. + RAW_CHECK(false); +#endif } } diff --git a/chromium/sandbox/linux/syscall_broker/broker_process_unittest.cc b/chromium/sandbox/linux/syscall_broker/broker_process_unittest.cc index 08096b95aa3..b1d71063409 100644 --- a/chromium/sandbox/linux/syscall_broker/broker_process_unittest.cc +++ b/chromium/sandbox/linux/syscall_broker/broker_process_unittest.cc @@ -811,7 +811,7 @@ void TestStatHelper(bool fast_check_in_client, bool follow_links) { const char* bad_leading_path5 = "/mbogo/fictitioux"; const char* bad_leading_path6 = "/mbogo/fictitiousa"; - struct stat sb; + default_stat_struct sb; { // Actual file with permissions to see file but command not allowed. @@ -824,7 +824,7 @@ void TestStatHelper(bool fast_check_in_client, bool follow_links) { memset(&sb, 0, sizeof(sb)); EXPECT_EQ(-kFakeErrnoSentinel, - open_broker.GetBrokerClientSignalBased()->Stat( + open_broker.GetBrokerClientSignalBased()->DefaultStatForTesting( tempfile_name, follow_links, &sb)); } @@ -840,7 +840,7 @@ void TestStatHelper(bool fast_check_in_client, bool follow_links) { memset(&sb, 0, sizeof(sb)); EXPECT_EQ(-kFakeErrnoSentinel, - open_broker.GetBrokerClientSignalBased()->Stat( + open_broker.GetBrokerClientSignalBased()->DefaultStatForTesting( nonesuch_name, follow_links, &sb)); } { @@ -852,7 +852,7 @@ void TestStatHelper(bool fast_check_in_client, bool follow_links) { memset(&sb, 0, sizeof(sb)); EXPECT_EQ(-kFakeErrnoSentinel, - open_broker.GetBrokerClientSignalBased()->Stat( + open_broker.GetBrokerClientSignalBased()->DefaultStatForTesting( tempfile_name, follow_links, &sb)); } { @@ -864,38 +864,39 @@ void TestStatHelper(bool fast_check_in_client, bool follow_links) { ASSERT_TRUE(open_broker.Init(base::BindOnce(&NoOpCallback))); memset(&sb, 0, sizeof(sb)); - EXPECT_EQ(-ENOENT, open_broker.GetBrokerClientSignalBased()->Stat( - nonesuch_name, follow_links, &sb)); + EXPECT_EQ(-ENOENT, + open_broker.GetBrokerClientSignalBased()->DefaultStatForTesting( + nonesuch_name, follow_links, &sb)); // Gets denied all the way back to root since no create permission. EXPECT_EQ(-kFakeErrnoSentinel, - open_broker.GetBrokerClientSignalBased()->Stat( + open_broker.GetBrokerClientSignalBased()->DefaultStatForTesting( leading_path1, follow_links, &sb)); EXPECT_EQ(-kFakeErrnoSentinel, - open_broker.GetBrokerClientSignalBased()->Stat( + open_broker.GetBrokerClientSignalBased()->DefaultStatForTesting( leading_path2, follow_links, &sb)); EXPECT_EQ(-kFakeErrnoSentinel, - open_broker.GetBrokerClientSignalBased()->Stat( + open_broker.GetBrokerClientSignalBased()->DefaultStatForTesting( leading_path3, follow_links, &sb)); // Not fooled by substrings. EXPECT_EQ(-kFakeErrnoSentinel, - open_broker.GetBrokerClientSignalBased()->Stat( + open_broker.GetBrokerClientSignalBased()->DefaultStatForTesting( bad_leading_path1, follow_links, &sb)); EXPECT_EQ(-kFakeErrnoSentinel, - open_broker.GetBrokerClientSignalBased()->Stat( + open_broker.GetBrokerClientSignalBased()->DefaultStatForTesting( bad_leading_path2, follow_links, &sb)); EXPECT_EQ(-kFakeErrnoSentinel, - open_broker.GetBrokerClientSignalBased()->Stat( + open_broker.GetBrokerClientSignalBased()->DefaultStatForTesting( bad_leading_path3, follow_links, &sb)); EXPECT_EQ(-kFakeErrnoSentinel, - open_broker.GetBrokerClientSignalBased()->Stat( + open_broker.GetBrokerClientSignalBased()->DefaultStatForTesting( bad_leading_path4, follow_links, &sb)); EXPECT_EQ(-kFakeErrnoSentinel, - open_broker.GetBrokerClientSignalBased()->Stat( + open_broker.GetBrokerClientSignalBased()->DefaultStatForTesting( bad_leading_path5, follow_links, &sb)); EXPECT_EQ(-kFakeErrnoSentinel, - open_broker.GetBrokerClientSignalBased()->Stat( + open_broker.GetBrokerClientSignalBased()->DefaultStatForTesting( bad_leading_path6, follow_links, &sb)); } { @@ -907,37 +908,41 @@ void TestStatHelper(bool fast_check_in_client, bool follow_links) { ASSERT_TRUE(open_broker.Init(base::BindOnce(&NoOpCallback))); memset(&sb, 0, sizeof(sb)); - EXPECT_EQ(-ENOENT, open_broker.GetBrokerClientSignalBased()->Stat( - nonesuch_name, follow_links, &sb)); + EXPECT_EQ(-ENOENT, + open_broker.GetBrokerClientSignalBased()->DefaultStatForTesting( + nonesuch_name, follow_links, &sb)); // Gets ENOENT all the way back to root since it has create permission. - EXPECT_EQ(-ENOENT, open_broker.GetBrokerClientSignalBased()->Stat( - leading_path1, follow_links, &sb)); - EXPECT_EQ(-ENOENT, open_broker.GetBrokerClientSignalBased()->Stat( - leading_path2, follow_links, &sb)); + EXPECT_EQ(-ENOENT, + open_broker.GetBrokerClientSignalBased()->DefaultStatForTesting( + leading_path1, follow_links, &sb)); + EXPECT_EQ(-ENOENT, + open_broker.GetBrokerClientSignalBased()->DefaultStatForTesting( + leading_path2, follow_links, &sb)); // But can always get the root. - EXPECT_EQ(0, open_broker.GetBrokerClientSignalBased()->Stat( - leading_path3, follow_links, &sb)); + EXPECT_EQ(0, + open_broker.GetBrokerClientSignalBased()->DefaultStatForTesting( + leading_path3, follow_links, &sb)); // Not fooled by substrings. EXPECT_EQ(-kFakeErrnoSentinel, - open_broker.GetBrokerClientSignalBased()->Stat( + open_broker.GetBrokerClientSignalBased()->DefaultStatForTesting( bad_leading_path1, follow_links, &sb)); EXPECT_EQ(-kFakeErrnoSentinel, - open_broker.GetBrokerClientSignalBased()->Stat( + open_broker.GetBrokerClientSignalBased()->DefaultStatForTesting( bad_leading_path2, follow_links, &sb)); EXPECT_EQ(-kFakeErrnoSentinel, - open_broker.GetBrokerClientSignalBased()->Stat( + open_broker.GetBrokerClientSignalBased()->DefaultStatForTesting( bad_leading_path3, follow_links, &sb)); EXPECT_EQ(-kFakeErrnoSentinel, - open_broker.GetBrokerClientSignalBased()->Stat( + open_broker.GetBrokerClientSignalBased()->DefaultStatForTesting( bad_leading_path4, follow_links, &sb)); EXPECT_EQ(-kFakeErrnoSentinel, - open_broker.GetBrokerClientSignalBased()->Stat( + open_broker.GetBrokerClientSignalBased()->DefaultStatForTesting( bad_leading_path5, follow_links, &sb)); EXPECT_EQ(-kFakeErrnoSentinel, - open_broker.GetBrokerClientSignalBased()->Stat( + open_broker.GetBrokerClientSignalBased()->DefaultStatForTesting( bad_leading_path6, follow_links, &sb)); } { @@ -949,8 +954,9 @@ void TestStatHelper(bool fast_check_in_client, bool follow_links) { ASSERT_TRUE(open_broker.Init(base::BindOnce(&NoOpCallback))); memset(&sb, 0, sizeof(sb)); - EXPECT_EQ(0, open_broker.GetBrokerClientSignalBased()->Stat( - tempfile_name, follow_links, &sb)); + EXPECT_EQ(0, + open_broker.GetBrokerClientSignalBased()->DefaultStatForTesting( + tempfile_name, follow_links, &sb)); // Following fields may never be consistent but should be non-zero. // Don't trust the platform to define fields with any particular sign. @@ -968,9 +974,9 @@ void TestStatHelper(bool fast_check_in_client, bool follow_links) { EXPECT_EQ(12, sb.st_size); // Can't go backwards in time, 1500000000 was some time ago. - EXPECT_LT(1500000000u, static_cast<unsigned int>(sb.st_atime)); - EXPECT_LT(1500000000u, static_cast<unsigned int>(sb.st_mtime)); - EXPECT_LT(1500000000u, static_cast<unsigned int>(sb.st_ctime)); + EXPECT_LT(1500000000u, static_cast<unsigned int>(sb.st_atime_)); + EXPECT_LT(1500000000u, static_cast<unsigned int>(sb.st_mtime_)); + EXPECT_LT(1500000000u, static_cast<unsigned int>(sb.st_ctime_)); } } diff --git a/chromium/sandbox/linux/syscall_broker/remote_syscall_arg_handler_unittest.cc b/chromium/sandbox/linux/syscall_broker/remote_syscall_arg_handler_unittest.cc index fffa9bb7082..f517a9867c5 100644 --- a/chromium/sandbox/linux/syscall_broker/remote_syscall_arg_handler_unittest.cc +++ b/chromium/sandbox/linux/syscall_broker/remote_syscall_arg_handler_unittest.cc @@ -16,6 +16,7 @@ #include "base/memory/page_size.h" #include "base/posix/unix_domain_socket.h" #include "base/test/bind.h" +#include "sandbox/linux/tests/test_utils.h" #include "sandbox/linux/tests/unit_tests.h" #include "testing/gtest/include/gtest/gtest.h" @@ -52,19 +53,6 @@ void VerifyCorrectString(std::string str, size_t size) { } } -void* MapPagesOrDie(size_t num_pages) { - void* addr = mmap(nullptr, num_pages * base::GetPageSize(), - PROT_READ | PROT_WRITE, MAP_PRIVATE | MAP_ANONYMOUS, -1, 0); - PCHECK(addr); - return addr; -} - -void MprotectLastPageOrDie(char* addr, size_t num_pages) { - size_t last_page_offset = (num_pages - 1) * base::GetPageSize(); - PCHECK(mprotect(addr + last_page_offset, base::GetPageSize(), PROT_NONE) >= - 0); -} - pid_t ForkWaitingChild(base::OnceCallback<void(int)> after_parent_signals_callback = base::DoNothing(), base::ScopedFD* parent_sync_fd = nullptr) { @@ -105,13 +93,13 @@ void ReadTest(const ReadTestConfig& test_config) { size_t total_pages = (test_config.start_at + test_config.total_size + base::GetPageSize() - 1) / base::GetPageSize(); - char* mmap_addr = static_cast<char*>(MapPagesOrDie(total_pages)); + char* mmap_addr = static_cast<char*>(TestUtils::MapPagesOrDie(total_pages)); char* addr = mmap_addr + test_config.start_at; FillBufferWithPath(addr, test_config.total_size, test_config.include_null_byte); if (test_config.last_page_inaccessible) - MprotectLastPageOrDie(mmap_addr, total_pages); + TestUtils::MprotectLastPageOrDie(mmap_addr, total_pages); pid_t pid = ForkWaitingChild(); munmap(mmap_addr, base::GetPageSize() * total_pages); @@ -212,7 +200,7 @@ SANDBOX_TEST(BrokerRemoteSyscallArgHandler, ReadChunkPlus1EndingOnePastPage) { } SANDBOX_TEST(BrokerRemoteSyscallArgHandler, ReadChildExited) { - void* addr = MapPagesOrDie(1); + void* addr = TestUtils::MapPagesOrDie(1); FillBufferWithPath(static_cast<char*>(addr), strlen(kPathPart) + 1, true); base::ScopedFD parent_sync, child_sync; @@ -240,10 +228,10 @@ SANDBOX_TEST(BrokerRemoteSyscallArgHandler, ReadChildExited) { } SANDBOX_TEST(BrokerRemoteSyscallArgHandler, BasicWrite) { - void* read_from = MapPagesOrDie(1); + void* read_from = TestUtils::MapPagesOrDie(1); const size_t write_size = base::GetPageSize(); FillBufferWithPath(static_cast<char*>(read_from), write_size, false); - char* write_to = static_cast<char*>(MapPagesOrDie(1)); + char* write_to = static_cast<char*>(TestUtils::MapPagesOrDie(1)); base::ScopedFD parent_signal_fd; const std::vector<int> empty_fd_vec; @@ -278,8 +266,8 @@ SANDBOX_TEST(BrokerRemoteSyscallArgHandler, BasicWrite) { } SANDBOX_TEST(BrokerRemoteSyscallArgHandler, WriteToInvalidAddress) { - char* write_to = static_cast<char*>(MapPagesOrDie(1)); - MprotectLastPageOrDie(write_to, 1); + char* write_to = static_cast<char*>(TestUtils::MapPagesOrDie(1)); + TestUtils::MprotectLastPageOrDie(write_to, 1); base::ScopedFD parent_signal_fd; const std::vector<int> empty_fd_vec; @@ -295,11 +283,11 @@ SANDBOX_TEST(BrokerRemoteSyscallArgHandler, WriteToInvalidAddress) { } SANDBOX_TEST(BrokerRemoteSyscallArgHandler, WritePartiallyToInvalidAddress) { - char* read_from = static_cast<char*>(MapPagesOrDie(2)); + char* read_from = static_cast<char*>(TestUtils::MapPagesOrDie(2)); const size_t write_size = base::GetPageSize(); FillBufferWithPath(static_cast<char*>(read_from), write_size, false); - char* write_to = static_cast<char*>(MapPagesOrDie(2)); - MprotectLastPageOrDie(write_to, 2); + char* write_to = static_cast<char*>(TestUtils::MapPagesOrDie(2)); + TestUtils::MprotectLastPageOrDie(write_to, 2); write_to += base::GetPageSize() / 2; base::ScopedFD parent_signal_fd; const std::vector<int> empty_fd_vec; @@ -314,7 +302,7 @@ SANDBOX_TEST(BrokerRemoteSyscallArgHandler, WritePartiallyToInvalidAddress) { } SANDBOX_TEST(BrokerRemoteSyscallArgHandler, WriteChildExited) { - char* addr = static_cast<char*>(MapPagesOrDie(1)); + char* addr = static_cast<char*>(TestUtils::MapPagesOrDie(1)); FillBufferWithPath(static_cast<char*>(addr), strlen(kPathPart) + 1, true); base::ScopedFD parent_sync, child_sync; diff --git a/chromium/sandbox/linux/syscall_broker/syscall_dispatcher.cc b/chromium/sandbox/linux/syscall_broker/syscall_dispatcher.cc index b9ee93c14ac..8a42397ef87 100644 --- a/chromium/sandbox/linux/syscall_broker/syscall_dispatcher.cc +++ b/chromium/sandbox/linux/syscall_broker/syscall_dispatcher.cc @@ -19,8 +19,18 @@ namespace syscall_broker { #define BROKER_UNPOISON_STRING(x) #endif +int SyscallDispatcher::DefaultStatForTesting(const char* pathname, + bool follow_links, + default_stat_struct* sb) { +#if defined(__NR_fstatat64) + return Stat64(pathname, follow_links, sb); +#elif defined(__NR_newfstatat) + return Stat(pathname, follow_links, sb); +#endif +} + int SyscallDispatcher::PerformStatat(const arch_seccomp_data& args, - bool arch64) { + bool stat64) { if (static_cast<int>(args.args[0]) != AT_FDCWD) return -EPERM; // Only allow the AT_SYMLINK_NOFOLLOW flag which is used by some libc @@ -30,13 +40,29 @@ int SyscallDispatcher::PerformStatat(const arch_seccomp_data& args, const bool follow_links = !(static_cast<int>(args.args[3]) & AT_SYMLINK_NOFOLLOW); - if (arch64) { + if (stat64) { return Stat64(reinterpret_cast<const char*>(args.args[1]), follow_links, - reinterpret_cast<struct stat64*>(args.args[2])); + reinterpret_cast<struct kernel_stat64*>(args.args[2])); } return Stat(reinterpret_cast<const char*>(args.args[1]), follow_links, - reinterpret_cast<struct stat*>(args.args[2])); + reinterpret_cast<struct kernel_stat*>(args.args[2])); +} + +int SyscallDispatcher::PerformUnlinkat(const arch_seccomp_data& args) { + if (static_cast<int>(args.args[0]) != AT_FDCWD) + return -EPERM; + + int flags = static_cast<int>(args.args[2]); + + if (flags == AT_REMOVEDIR) { + return Rmdir(reinterpret_cast<const char*>(args.args[1])); + } + + if (flags != 0) + return -EPERM; + + return Unlink(reinterpret_cast<const char*>(args.args[1])); } int SyscallDispatcher::DispatchSyscall(const arch_seccomp_data& args) { @@ -127,59 +153,42 @@ int SyscallDispatcher::DispatchSyscall(const arch_seccomp_data& args) { #if defined(__NR_stat) case __NR_stat: return Stat(reinterpret_cast<const char*>(args.args[0]), true, - reinterpret_cast<struct stat*>(args.args[1])); + reinterpret_cast<struct kernel_stat*>(args.args[1])); #endif #if defined(__NR_stat64) case __NR_stat64: return Stat64(reinterpret_cast<const char*>(args.args[0]), true, - reinterpret_cast<struct stat64*>(args.args[1])); + reinterpret_cast<struct kernel_stat64*>(args.args[1])); #endif #if defined(__NR_lstat) case __NR_lstat: // See https://crbug.com/847096 BROKER_UNPOISON_STRING(reinterpret_cast<const char*>(args.args[0])); return Stat(reinterpret_cast<const char*>(args.args[0]), false, - reinterpret_cast<struct stat*>(args.args[1])); + reinterpret_cast<struct kernel_stat*>(args.args[1])); #endif #if defined(__NR_lstat64) case __NR_lstat64: // See https://crbug.com/847096 BROKER_UNPOISON_STRING(reinterpret_cast<const char*>(args.args[0])); return Stat64(reinterpret_cast<const char*>(args.args[0]), false, - reinterpret_cast<struct stat64*>(args.args[1])); -#endif -#if defined(__NR_fstatat) - case __NR_fstatat: - return PerformStatat(args, /*arch64=*/false); + reinterpret_cast<struct kernel_stat64*>(args.args[1])); #endif #if defined(__NR_fstatat64) case __NR_fstatat64: - return PerformStatat(args, /*arch64=*/true); + return PerformStatat(args, /*stat64=*/true); #endif #if defined(__NR_newfstatat) case __NR_newfstatat: - return PerformStatat(args, /*arch64=*/false); + return PerformStatat(args, /*stat64=*/false); #endif #if defined(__NR_unlink) case __NR_unlink: return Unlink(reinterpret_cast<const char*>(args.args[0])); #endif #if defined(__NR_unlinkat) - case __NR_unlinkat: { - if (static_cast<int>(args.args[0]) != AT_FDCWD) - return -EPERM; - - int flags = static_cast<int>(args.args[2]); - - if (flags == AT_REMOVEDIR) { - return Rmdir(reinterpret_cast<const char*>(args.args[1])); - } - - if (flags != 0) - return -EPERM; - - return Unlink(reinterpret_cast<const char*>(args.args[1])); - } + case __NR_unlinkat: + return PerformUnlinkat(args); #endif // defined(__NR_unlinkat) default: RAW_CHECK(false); diff --git a/chromium/sandbox/linux/syscall_broker/syscall_dispatcher.h b/chromium/sandbox/linux/syscall_broker/syscall_dispatcher.h index d8b8874ad9c..1d6653caf3b 100644 --- a/chromium/sandbox/linux/syscall_broker/syscall_dispatcher.h +++ b/chromium/sandbox/linux/syscall_broker/syscall_dispatcher.h @@ -9,13 +9,15 @@ #include <cstddef> #include "sandbox/linux/system_headers/linux_seccomp.h" +#include "sandbox/linux/system_headers/linux_stat.h" +#include "sandbox/sandbox_export.h" namespace sandbox { namespace syscall_broker { // An abstract class that defines all the system calls we perform for the // sandboxed process. -class SyscallDispatcher { +class SANDBOX_EXPORT SyscallDispatcher { public: // Emulates access()/faccessat(). // X_OK will always return an error in practice since the broker process @@ -40,19 +42,34 @@ class SyscallDispatcher { virtual int Rmdir(const char* path) const = 0; // Emulates stat()/stat64()/lstat()/lstat64()/fstatat()/newfstatat(). + // Stat64 is only available on 32-bit systems. virtual int Stat(const char* pathname, bool follow_links, - struct stat* sb) const = 0; + struct kernel_stat* sb) const = 0; virtual int Stat64(const char* pathname, bool follow_links, - struct stat64* sb) const = 0; + struct kernel_stat64* sb) const = 0; // Emulates unlink()/unlinkat(). virtual int Unlink(const char* unlink) const = 0; + // Different architectures use a different syscall from the stat family by + // default in glibc. E.g. 32-bit systems use *stat*64() and fill out struct + // kernel_stat64, whereas 64-bit systems use *stat*() and fill out struct + // kernel_stat. Some tests want to call the SyscallDispatcher directly, and + // should be using the default stat in order to test against glibc. + int DefaultStatForTesting(const char* pathname, + bool follow_links, + default_stat_struct* sb); + // Validates the args passed to a *statat*() syscall and performs the syscall - // using Stat() or Stat64(). - int PerformStatat(const arch_seccomp_data& args, bool arch64); + // using Stat(), or on 32-bit systems it uses Stat64() for the *statat64() + // syscalls. + int PerformStatat(const arch_seccomp_data& args, bool stat64); + + // Validates the args passed to an unlinkat() syscall and performs the syscall + // using either Unlink() or Rmdir(). + int PerformUnlinkat(const arch_seccomp_data& args); // Reads the syscall number and arguments, imposes some policy (e.g. the *at() // system calls must only allow AT_FDCWD as the first argument), and |