summaryrefslogtreecommitdiff
path: root/chromium/sandbox/linux/syscall_broker
diff options
context:
space:
mode:
Diffstat (limited to 'chromium/sandbox/linux/syscall_broker')
-rw-r--r--chromium/sandbox/linux/syscall_broker/DEPS3
-rw-r--r--chromium/sandbox/linux/syscall_broker/broker_client.cc4
-rw-r--r--chromium/sandbox/linux/syscall_broker/broker_client.h4
-rw-r--r--chromium/sandbox/linux/syscall_broker/broker_host.cc23
-rw-r--r--chromium/sandbox/linux/syscall_broker/broker_process_unittest.cc74
-rw-r--r--chromium/sandbox/linux/syscall_broker/remote_syscall_arg_handler_unittest.cc36
-rw-r--r--chromium/sandbox/linux/syscall_broker/syscall_dispatcher.cc67
-rw-r--r--chromium/sandbox/linux/syscall_broker/syscall_dispatcher.h27
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