From 975d7135e1b3d7ffc3c2c5a8a467d421b81248d5 Mon Sep 17 00:00:00 2001 From: Mikhail Novosyolov Date: Wed, 22 Sep 2021 17:44:54 +0300 Subject: [PATCH] upd: 93 -> 94 Do not use macro which was dropped from branding-configs --- .abf.yml | 6 +- ...8323d68840453b5ef826c3997568e2e0e8c7.patch | 1384 ----------------- ...e803ef2a4874d29799b638754152285e0ed9.patch | 348 ----- ...cdbe30cb84cd2f0b63e453f3782c49213264.patch | 70 - chromium-browser-stable.spec | 16 +- 5 files changed, 9 insertions(+), 1815 deletions(-) delete mode 100644 4b438323d68840453b5ef826c3997568e2e0e8c7.patch delete mode 100644 60d5e803ef2a4874d29799b638754152285e0ed9.patch delete mode 100644 b2fbcdbe30cb84cd2f0b63e453f3782c49213264.patch diff --git a/.abf.yml b/.abf.yml index f0dd209..cc042dd 100644 --- a/.abf.yml +++ b/.abf.yml @@ -1,8 +1,8 @@ sources: - chromium-93.0.4577.82.tar.xz: 6d1ea3759f421233dbe7c0ea9bddad3afa1ce6fe - chromium-gost-3181acb959fcb8de4aa3aca4c51d8a89b90d367d.tar.gz: 3f81e4ac5204d61384480c59f45a3ef5b8feb3b0 + chromium-94.0.4606.54.tar.xz: f7e748655cf994f9283d6bd7f9664ad975dd8ca2 + chromium-gost-63275ec358b1a1c0087dc3af770d18c1d5fe661d.tar.gz: 67349ca44d66bd239b5fca98f2cdc0b7dffa154b depot_tools.tar.xz: 082b7f9a4dfa7eb03900755b4866aef2d73543a5 icons.tar.bz2: a835954af164bf38f8ea4ea80608839bed7800a3 - msspi-676e76df03782fa965d8f985f4bd2e4c3ee81386.tar.gz: 5c82ce5a5780b06a481812986e3da8b1131ca1a8 + msspi-74a19443ca691e1acfee84e6176282e4ec338eac.tar.gz: 82954b8b58005505c32e92d4a8861ea2906f2a9f new-system-icons.tar.xz: 89339b8b3b05359a8745ed7968fe148902a2fa28 xcb-proto-1.14.1.tar.xz: 836d5b2dd00ff21bd038e92764fda9a256a1b022 diff --git a/4b438323d68840453b5ef826c3997568e2e0e8c7.patch b/4b438323d68840453b5ef826c3997568e2e0e8c7.patch deleted file mode 100644 index 4a99f1d..0000000 --- a/4b438323d68840453b5ef826c3997568e2e0e8c7.patch +++ /dev/null @@ -1,1384 +0,0 @@ -From 4b438323d68840453b5ef826c3997568e2e0e8c7 Mon Sep 17 00:00:00 2001 -From: Matthew Denton -Date: Mon, 19 Jul 2021 14:03:13 +0000 -Subject: [PATCH] Reland "Reland "Linux sandbox syscall broker: use struct - kernel_stat"" - -This reverts commit ff277a52ece0b216617d770f201ed66955fe70b9. - -Reason for revert: reland - -The fix included in the reland is that fstatat64() needs to be -allowed in the broker process's seccomp policy. - -This CL also includes some extra tests that the kernel_stat structures -match the layout the kernel expects. - -Bug: 1164975, 1199431 -Test: trogdor Chromebook successfully boots and allows login. - -Original change's description: -> Revert "Reland "Linux sandbox syscall broker: use struct kernel_stat"" -> -> This reverts commit cffbc4432af79f720ae3c75dff380b853701bd64. -> -> Reason for revert: https://bugs.chromium.org/p/chromium/issues/detail?id=1199431 -> -> Original change's description: -> > Reland "Linux sandbox syscall broker: use struct kernel_stat" -> > -> > This reverts commit 23030dc650cdfa22631f25bef937905f27f06a2c. -> > -> > Original change's description: -> > > Revert "Linux sandbox syscall broker: use struct kernel_stat" -> > > -> > > This reverts commit 784b0fcd8a3ca6bcd3acb9cfd624ec9cbbac2789. -> > > -> > > Reason for revert: Causing failure in -> > > Step "sandbox_linux_unittests" failing on builder "Linux ChromiumOS MSan Tests" -> > > See crbug.com/1198480 -> > > -> > > Original change's description: -> > > > Linux sandbox syscall broker: use struct kernel_stat -> > > > -> > > > The struct stat used in libc is different (in size and field ordering) -> > > > from the structure assumed by the Linux kernel. So, when emulating -> > > > system calls, we need to use the struct definition the kernel expects. -> > > > -> > > > This CL adds linux_stat.h that includes definitions of the different -> > > > kernel structs. -> > > > -> > > > Change-Id: I53cad35c2251dff0f6b7ea77528cfa58ef3cab4a -> > > > Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/2780876 -> > > > Commit-Queue: Matthew Denton -> > > > Reviewed-by: Robert Sesek -> > > > Cr-Commit-Position: refs/heads/master@{#871767} -> > > -> > > Change-Id: Icbec38f2103c8424dec79ab1870b97c3e83f9361 -> > > No-Presubmit: true -> > > No-Tree-Checks: true -> > > No-Try: true -> > > Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/2821812 -> > > Auto-Submit: Victor Vianna -> > > Owners-Override: Victor Vianna -> > > Commit-Queue: Rubber Stamper -> > > Bot-Commit: Rubber Stamper -> > > Cr-Commit-Position: refs/heads/master@{#871882} -> > -> > Change-Id: I1f39bb5242961474def594ff7dbea52009f2cee4 -> > Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/2824115 -> > Auto-Submit: Matthew Denton -> > Commit-Queue: Matthew Denton -> > Reviewed-by: Robert Sesek -> > Cr-Commit-Position: refs/heads/master@{#872812} -> -> Fixed: 1199431 -> Change-Id: Iebfc0c48201bf22ff9c54d8d5c8a43d26a880098 -> No-Presubmit: true -> No-Tree-Checks: true -> No-Try: true -> Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/2830459 -> Auto-Submit: Kyle Horimoto -> Commit-Queue: Matthew Denton -> Commit-Queue: Kinuko Yasuda -> Reviewed-by: Matthew Denton -> Reviewed-by: Kinuko Yasuda -> Owners-Override: Kinuko Yasuda -> Cr-Commit-Position: refs/heads/master@{#873173} - -Change-Id: Ibe6a485070f33489aaa157b51b908c2d23d174d7 -Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/2848936 -Reviewed-by: Robert Sesek -Commit-Queue: Matthew Denton -Cr-Commit-Position: refs/heads/master@{#902981} ---- - sandbox/linux/BUILD.gn | 1 + - .../seccomp_broker_process_unittest.cc | 40 +++- - sandbox/linux/seccomp-bpf-helpers/DEPS | 1 - - ...scall_parameters_restrictions_unittests.cc | 4 - - sandbox/linux/services/syscall_wrappers.cc | 50 ++++- - sandbox/linux/services/syscall_wrappers.h | 15 ++ - .../services/syscall_wrappers_unittest.cc | 129 +++++++++++- - sandbox/linux/syscall_broker/DEPS | 3 +- - sandbox/linux/syscall_broker/broker_client.cc | 4 +- - sandbox/linux/syscall_broker/broker_client.h | 4 +- - sandbox/linux/syscall_broker/broker_host.cc | 23 ++- - .../syscall_broker/broker_process_unittest.cc | 74 +++---- - .../remote_syscall_arg_handler_unittest.cc | 36 ++-- - .../syscall_broker/syscall_dispatcher.cc | 67 ++++--- - .../linux/syscall_broker/syscall_dispatcher.h | 27 ++- - sandbox/linux/system_headers/linux_stat.h | 188 ++++++++++++++++++ - sandbox/linux/system_headers/linux_time.h | 26 +++ - sandbox/linux/tests/test_utils.cc | 15 ++ - sandbox/linux/tests/test_utils.h | 2 + - .../policy/linux/bpf_broker_policy_linux.cc | 4 +- - 20 files changed, 595 insertions(+), 118 deletions(-) - create mode 100644 sandbox/linux/system_headers/linux_stat.h - -diff --git a/sandbox/linux/BUILD.gn b/sandbox/linux/BUILD.gn -index 2f778dd0bcab2..ccbbc91716e71 100644 ---- a/sandbox/linux/BUILD.gn -+++ b/sandbox/linux/BUILD.gn -@@ -443,6 +443,7 @@ source_set("sandbox_services_headers") { - "system_headers/linux_ptrace.h", - "system_headers/linux_seccomp.h", - "system_headers/linux_signal.h", -+ "system_headers/linux_stat.h", - "system_headers/linux_syscalls.h", - "system_headers/linux_time.h", - "system_headers/linux_ucontext.h", -diff --git a/sandbox/linux/integration_tests/seccomp_broker_process_unittest.cc b/sandbox/linux/integration_tests/seccomp_broker_process_unittest.cc -index 9da9c68911428..8a941983b198d 100644 ---- a/sandbox/linux/integration_tests/seccomp_broker_process_unittest.cc -+++ b/sandbox/linux/integration_tests/seccomp_broker_process_unittest.cc -@@ -34,6 +34,7 @@ - #include "sandbox/linux/syscall_broker/broker_file_permission.h" - #include "sandbox/linux/syscall_broker/broker_process.h" - #include "sandbox/linux/system_headers/linux_seccomp.h" -+#include "sandbox/linux/system_headers/linux_stat.h" - #include "sandbox/linux/system_headers/linux_syscalls.h" - #include "sandbox/linux/tests/scoped_temporary_file.h" - #include "sandbox/linux/tests/test_utils.h" -@@ -202,6 +203,26 @@ namespace { - // not accept this as a valid error number. E.g. bionic accepts up to 255, glibc - // and musl up to 4096. - const int kFakeErrnoSentinel = 254; -+ -+void ConvertKernelStatToLibcStat(default_stat_struct& in_stat, -+ struct stat& out_stat) { -+ out_stat.st_dev = in_stat.st_dev; -+ out_stat.st_ino = in_stat.st_ino; -+ out_stat.st_mode = in_stat.st_mode; -+ out_stat.st_nlink = in_stat.st_nlink; -+ out_stat.st_uid = in_stat.st_uid; -+ out_stat.st_gid = in_stat.st_gid; -+ out_stat.st_rdev = in_stat.st_rdev; -+ out_stat.st_size = in_stat.st_size; -+ out_stat.st_blksize = in_stat.st_blksize; -+ out_stat.st_blocks = in_stat.st_blocks; -+ out_stat.st_atim.tv_sec = in_stat.st_atime_; -+ out_stat.st_atim.tv_nsec = in_stat.st_atime_nsec_; -+ out_stat.st_mtim.tv_sec = in_stat.st_mtime_; -+ out_stat.st_mtim.tv_nsec = in_stat.st_mtime_nsec_; -+ out_stat.st_ctim.tv_sec = in_stat.st_ctime_; -+ out_stat.st_ctim.tv_nsec = in_stat.st_ctime_nsec_; -+} - } // namespace - - // There are a variety of ways to make syscalls in a sandboxed process. One is -@@ -217,6 +238,10 @@ class Syscaller { - - virtual int Open(const char* filepath, int flags) = 0; - virtual int Access(const char* filepath, int mode) = 0; -+ // NOTE: we use struct stat instead of default_stat_struct, to make the libc -+ // syscaller simpler. Copying from default_stat_struct (the structure returned -+ // from a stat sycall) to struct stat (the structure exposed by a libc to its -+ // users) is simpler than going in the opposite direction. - virtual int Stat(const char* filepath, - bool follow_links, - struct stat* statbuf) = 0; -@@ -243,8 +268,12 @@ class IPCSyscaller : public Syscaller { - int Stat(const char* filepath, - bool follow_links, - struct stat* statbuf) override { -- return broker_->GetBrokerClientSignalBased()->Stat(filepath, follow_links, -- statbuf); -+ default_stat_struct buf; -+ int ret = broker_->GetBrokerClientSignalBased()->DefaultStatForTesting( -+ filepath, follow_links, &buf); -+ if (ret >= 0) -+ ConvertKernelStatToLibcStat(buf, *statbuf); -+ return ret; - } - - int Rename(const char* oldpath, const char* newpath) override { -@@ -300,10 +329,13 @@ class DirectSyscaller : public Syscaller { - int Stat(const char* filepath, - bool follow_links, - struct stat* statbuf) override { -- int ret = follow_links ? syscall(__NR_stat, filepath, statbuf) -- : syscall(__NR_lstat, filepath, statbuf); -+ struct kernel_stat buf; -+ int ret = syscall(__NR_newfstatat, AT_FDCWD, filepath, &buf, -+ follow_links ? 0 : AT_SYMLINK_NOFOLLOW); - if (ret < 0) - return -errno; -+ -+ ConvertKernelStatToLibcStat(buf, *statbuf); - return ret; - } - -diff --git a/sandbox/linux/seccomp-bpf-helpers/DEPS b/sandbox/linux/seccomp-bpf-helpers/DEPS -index 4419fd1da34e8..95d1bb6cbbabf 100644 ---- a/sandbox/linux/seccomp-bpf-helpers/DEPS -+++ b/sandbox/linux/seccomp-bpf-helpers/DEPS -@@ -3,5 +3,4 @@ include_rules = [ - "+sandbox/linux/seccomp-bpf", - "+sandbox/linux/services", - "+sandbox/linux/system_headers", -- "+third_party/lss/linux_syscall_support.h", - ] -diff --git a/sandbox/linux/seccomp-bpf-helpers/syscall_parameters_restrictions_unittests.cc b/sandbox/linux/seccomp-bpf-helpers/syscall_parameters_restrictions_unittests.cc -index 903e702eab14b..76c393032c1fe 100644 ---- a/sandbox/linux/seccomp-bpf-helpers/syscall_parameters_restrictions_unittests.cc -+++ b/sandbox/linux/seccomp-bpf-helpers/syscall_parameters_restrictions_unittests.cc -@@ -37,10 +37,6 @@ - #include "sandbox/linux/system_headers/linux_time.h" - #include "sandbox/linux/tests/unit_tests.h" - --#if !defined(OS_ANDROID) --#include "third_party/lss/linux_syscall_support.h" // for MAKE_PROCESS_CPUCLOCK --#endif -- - namespace sandbox { - - namespace { -diff --git a/sandbox/linux/services/syscall_wrappers.cc b/sandbox/linux/services/syscall_wrappers.cc -index fcfd2aa129d4b..3bec18a14e91e 100644 ---- a/sandbox/linux/services/syscall_wrappers.cc -+++ b/sandbox/linux/services/syscall_wrappers.cc -@@ -4,6 +4,7 @@ - - #include "sandbox/linux/services/syscall_wrappers.h" - -+#include - #include - #include - #include -@@ -14,11 +15,13 @@ - #include - #include - -+#include "base/check.h" - #include "base/compiler_specific.h" - #include "base/logging.h" - #include "build/build_config.h" - #include "sandbox/linux/system_headers/capability.h" - #include "sandbox/linux/system_headers/linux_signal.h" -+#include "sandbox/linux/system_headers/linux_stat.h" - #include "sandbox/linux/system_headers/linux_syscalls.h" - - namespace sandbox { -@@ -217,7 +220,7 @@ asm( - #undef STR - #undef XSTR - --#endif -+#endif // defined(ARCH_CPU_X86_FAMILY) - - int sys_sigaction(int signum, - const struct sigaction* act, -@@ -241,7 +244,7 @@ int sys_sigaction(int signum, - #error "Unsupported architecture." - #endif - } --#endif -+#endif // defined(ARCH_CPU_X86_FAMILY) - } - - LinuxSigAction linux_oldact = {}; -@@ -259,6 +262,47 @@ int sys_sigaction(int signum, - return result; - } - --#endif // defined(MEMORY_SANITIZER) -+#endif // !defined(OS_NACL_NONSFI) -+ -+int sys_stat(const char* path, struct kernel_stat* stat_buf) { -+ int res; -+#if !defined(__NR_stat) -+ res = syscall(__NR_newfstatat, AT_FDCWD, path, stat_buf, 0); -+#else -+ res = syscall(__NR_stat, path, stat_buf); -+#endif -+ if (res == 0) -+ MSAN_UNPOISON(stat_buf, sizeof(*stat_buf)); -+ return res; -+} -+ -+int sys_lstat(const char* path, struct kernel_stat* stat_buf) { -+ int res; -+#if !defined(__NR_lstat) -+ res = syscall(__NR_newfstatat, AT_FDCWD, path, stat_buf, AT_SYMLINK_NOFOLLOW); -+#else -+ res = syscall(__NR_lstat, path, stat_buf); -+#endif -+ if (res == 0) -+ MSAN_UNPOISON(stat_buf, sizeof(*stat_buf)); -+ return res; -+} -+ -+int sys_fstatat64(int dirfd, -+ const char* pathname, -+ struct kernel_stat64* stat_buf, -+ int flags) { -+#if defined(__NR_fstatat64) -+ int res = syscall(__NR_fstatat64, dirfd, pathname, stat_buf, flags); -+ if (res == 0) -+ MSAN_UNPOISON(stat_buf, sizeof(*stat_buf)); -+ return res; -+#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); -+ return -ENOSYS; -+#endif -+} - - } // namespace sandbox -diff --git a/sandbox/linux/services/syscall_wrappers.h b/sandbox/linux/services/syscall_wrappers.h -index 1975bfbd88a6d..b55340e4a26b7 100644 ---- a/sandbox/linux/services/syscall_wrappers.h -+++ b/sandbox/linux/services/syscall_wrappers.h -@@ -17,6 +17,8 @@ struct sock_fprog; - struct rlimit64; - struct cap_hdr; - struct cap_data; -+struct kernel_stat; -+struct kernel_stat64; - - namespace sandbox { - -@@ -84,6 +86,19 @@ SANDBOX_EXPORT int sys_sigaction(int signum, - const struct sigaction* act, - struct sigaction* oldact); - -+// Some architectures do not have stat() and lstat() syscalls. In that case, -+// these wrappers will use newfstatat(), which is available on all other -+// architectures, with the same capabilities as stat() and lstat(). -+SANDBOX_EXPORT int sys_stat(const char* path, struct kernel_stat* stat_buf); -+SANDBOX_EXPORT int sys_lstat(const char* path, struct kernel_stat* stat_buf); -+ -+// Takes care of unpoisoning |stat_buf| for MSAN. Check-fails if fstatat64() is -+// not a supported syscall on the current platform. -+SANDBOX_EXPORT int sys_fstatat64(int dirfd, -+ const char* pathname, -+ struct kernel_stat64* stat_buf, -+ int flags); -+ - } // namespace sandbox - - #endif // SANDBOX_LINUX_SERVICES_SYSCALL_WRAPPERS_H_ -diff --git a/sandbox/linux/services/syscall_wrappers_unittest.cc b/sandbox/linux/services/syscall_wrappers_unittest.cc -index 32820f60a8cee..64b9cea80f319 100644 ---- a/sandbox/linux/services/syscall_wrappers_unittest.cc -+++ b/sandbox/linux/services/syscall_wrappers_unittest.cc -@@ -5,15 +5,19 @@ - #include "sandbox/linux/services/syscall_wrappers.h" - - #include -+#include - #include - #include - #include - #include --#include - -+#include "base/logging.h" -+#include "base/memory/page_size.h" - #include "base/posix/eintr_wrapper.h" - #include "build/build_config.h" - #include "sandbox/linux/system_headers/linux_signal.h" -+#include "sandbox/linux/system_headers/linux_stat.h" -+#include "sandbox/linux/tests/scoped_temporary_file.h" - #include "sandbox/linux/tests/test_utils.h" - #include "sandbox/linux/tests/unit_tests.h" - #include "testing/gtest/include/gtest/gtest.h" -@@ -93,6 +97,129 @@ TEST(SyscallWrappers, LinuxSigSet) { - linux_sigset); - } - -+TEST(SyscallWrappers, Stat) { -+ // Create a file to stat, with 12 bytes of data. -+ ScopedTemporaryFile tmp_file; -+ EXPECT_EQ(12, write(tmp_file.fd(), "blahblahblah", 12)); -+ -+ // To test we have the correct stat structures for each kernel/platform, we -+ // will right-align them on a page, with a guard page after. -+ char* two_pages = static_cast(TestUtils::MapPagesOrDie(2)); -+ TestUtils::MprotectLastPageOrDie(two_pages, 2); -+ char* page1_end = two_pages + base::GetPageSize(); -+ -+ // First, check that calling stat with |stat_buf| pointing to the last byte on -+ // a page causes EFAULT. -+ int res = sys_stat(tmp_file.full_file_name(), -+ reinterpret_cast(page1_end - 1)); -+ ASSERT_EQ(res, -1); -+ ASSERT_EQ(errno, EFAULT); -+ -+ // Now, check that we have the correctly sized stat structure. -+ struct kernel_stat* sb = reinterpret_cast( -+ page1_end - sizeof(struct kernel_stat)); -+ // Memset to c's so we can check the kernel zero'd the padding... -+ memset(sb, 'c', sizeof(struct kernel_stat)); -+ res = sys_stat(tmp_file.full_file_name(), sb); -+ ASSERT_EQ(res, 0); -+ -+ // Following fields may never be consistent but should be non-zero. -+ // Don't trust the platform to define fields with any particular sign. -+ EXPECT_NE(0u, static_cast(sb->st_dev)); -+ EXPECT_NE(0u, static_cast(sb->st_ino)); -+ EXPECT_NE(0u, static_cast(sb->st_mode)); -+ EXPECT_NE(0u, static_cast(sb->st_blksize)); -+ EXPECT_NE(0u, static_cast(sb->st_blocks)); -+ -+// We are the ones that made the file. -+// Note: normally gid and uid overflow on backwards-compatible 32-bit systems -+// and we end up with dummy uids and gids in place here. -+#if defined(ARCH_CPU_64_BITS) -+ EXPECT_EQ(geteuid(), sb->st_uid); -+ EXPECT_EQ(getegid(), sb->st_gid); -+#endif -+ -+ // Wrote 12 bytes above which should fit in one block. -+ EXPECT_EQ(12u, sb->st_size); -+ -+ // Can't go backwards in time, 1500000000 was some time ago. -+ EXPECT_LT(1500000000u, static_cast(sb->st_atime_)); -+ EXPECT_LT(1500000000u, static_cast(sb->st_mtime_)); -+ EXPECT_LT(1500000000u, static_cast(sb->st_ctime_)); -+ -+ // Checking the padding for good measure. -+#if defined(__x86_64__) -+ EXPECT_EQ(0u, sb->__pad0); -+ EXPECT_EQ(0u, sb->__unused4[0]); -+ EXPECT_EQ(0u, sb->__unused4[1]); -+ EXPECT_EQ(0u, sb->__unused4[2]); -+#elif defined(__aarch64__) -+ EXPECT_EQ(0u, sb->__pad1); -+ EXPECT_EQ(0, sb->__pad2); -+ EXPECT_EQ(0u, sb->__unused4); -+ EXPECT_EQ(0u, sb->__unused5); -+#endif -+} -+ -+TEST(SyscallWrappers, LStat) { -+ // Create a file to stat, with 12 bytes of data. -+ ScopedTemporaryFile tmp_file; -+ EXPECT_EQ(12, write(tmp_file.fd(), "blahblahblah", 12)); -+ -+ // Also create a symlink. -+ std::string symlink_name; -+ { -+ ScopedTemporaryFile tmp_file2; -+ symlink_name = tmp_file2.full_file_name(); -+ } -+ int rc = symlink(tmp_file.full_file_name(), symlink_name.c_str()); -+ if (rc != 0) { -+ PLOG(ERROR) << "Couldn't symlink " << symlink_name << " to target " -+ << tmp_file.full_file_name(); -+ GTEST_FAIL(); -+ } -+ -+ struct kernel_stat lstat_info; -+ rc = sys_lstat(symlink_name.c_str(), &lstat_info); -+ if (rc < 0 && errno == EOVERFLOW) { -+ GTEST_SKIP(); -+ } -+ if (rc != 0) { -+ PLOG(ERROR) << "Couldn't sys_lstat " << symlink_name; -+ GTEST_FAIL(); -+ } -+ -+ struct kernel_stat stat_info; -+ rc = sys_stat(symlink_name.c_str(), &stat_info); -+ if (rc < 0 && errno == EOVERFLOW) { -+ GTEST_SKIP(); -+ } -+ if (rc != 0) { -+ PLOG(ERROR) << "Couldn't sys_stat " << symlink_name; -+ GTEST_FAIL(); -+ } -+ -+ struct kernel_stat tmp_file_stat_info; -+ rc = sys_stat(tmp_file.full_file_name(), &tmp_file_stat_info); -+ if (rc < 0 && errno == EOVERFLOW) { -+ GTEST_SKIP(); -+ } -+ if (rc != 0) { -+ PLOG(ERROR) << "Couldn't sys_stat " << tmp_file.full_file_name(); -+ GTEST_FAIL(); -+ } -+ -+ // lstat should produce information about a symlink. -+ ASSERT_TRUE(S_ISLNK(lstat_info.st_mode)); -+ -+ // stat-ing symlink_name and tmp_file should produce the same inode. -+ ASSERT_EQ(stat_info.st_ino, tmp_file_stat_info.st_ino); -+ -+ // lstat-ing symlink_name should give a different inode than stat-ing -+ // symlink_name. -+ ASSERT_NE(stat_info.st_ino, lstat_info.st_ino); -+} -+ - } // namespace - - } // namespace sandbox -diff --git a/sandbox/linux/syscall_broker/DEPS b/sandbox/linux/syscall_broker/DEPS -index c477f7d36394b..149c463b06839 100644 ---- a/sandbox/linux/syscall_broker/DEPS -+++ b/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/sandbox/linux/syscall_broker/broker_client.cc b/sandbox/linux/syscall_broker/broker_client.cc -index 6b1b5be433899..e24f659fcf872 100644 ---- a/sandbox/linux/syscall_broker/broker_client.cc -+++ b/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/sandbox/linux/syscall_broker/broker_client.h b/sandbox/linux/syscall_broker/broker_client.h -index 05e14c83f2010..26ca78101c71c 100644 ---- a/sandbox/linux/syscall_broker/broker_client.h -+++ b/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/sandbox/linux/syscall_broker/broker_host.cc b/sandbox/linux/syscall_broker/broker_host.cc -index 1cd03a18df809..1cdc01a888f41 100644 ---- a/sandbox/linux/syscall_broker/broker_host.cc -+++ b/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(&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(&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/sandbox/linux/syscall_broker/broker_process_unittest.cc b/sandbox/linux/syscall_broker/broker_process_unittest.cc -index 55ba6bccb29ec..c65f25a78a999 100644 ---- a/sandbox/linux/syscall_broker/broker_process_unittest.cc -+++ b/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(sb.st_atime)); -- EXPECT_LT(1500000000u, static_cast(sb.st_mtime)); -- EXPECT_LT(1500000000u, static_cast(sb.st_ctime)); -+ EXPECT_LT(1500000000u, static_cast(sb.st_atime_)); -+ EXPECT_LT(1500000000u, static_cast(sb.st_mtime_)); -+ EXPECT_LT(1500000000u, static_cast(sb.st_ctime_)); - } - } - -diff --git a/sandbox/linux/syscall_broker/remote_syscall_arg_handler_unittest.cc b/sandbox/linux/syscall_broker/remote_syscall_arg_handler_unittest.cc -index fffa9bb7082ce..f517a9867c5de 100644 ---- a/sandbox/linux/syscall_broker/remote_syscall_arg_handler_unittest.cc -+++ b/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 - 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(MapPagesOrDie(total_pages)); -+ char* mmap_addr = static_cast(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(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(read_from), write_size, false); -- char* write_to = static_cast(MapPagesOrDie(1)); -+ char* write_to = static_cast(TestUtils::MapPagesOrDie(1)); - base::ScopedFD parent_signal_fd; - const std::vector empty_fd_vec; - -@@ -278,8 +266,8 @@ SANDBOX_TEST(BrokerRemoteSyscallArgHandler, BasicWrite) { - } - - SANDBOX_TEST(BrokerRemoteSyscallArgHandler, WriteToInvalidAddress) { -- char* write_to = static_cast(MapPagesOrDie(1)); -- MprotectLastPageOrDie(write_to, 1); -+ char* write_to = static_cast(TestUtils::MapPagesOrDie(1)); -+ TestUtils::MprotectLastPageOrDie(write_to, 1); - base::ScopedFD parent_signal_fd; - const std::vector empty_fd_vec; - -@@ -295,11 +283,11 @@ SANDBOX_TEST(BrokerRemoteSyscallArgHandler, WriteToInvalidAddress) { - } - - SANDBOX_TEST(BrokerRemoteSyscallArgHandler, WritePartiallyToInvalidAddress) { -- char* read_from = static_cast(MapPagesOrDie(2)); -+ char* read_from = static_cast(TestUtils::MapPagesOrDie(2)); - const size_t write_size = base::GetPageSize(); - FillBufferWithPath(static_cast(read_from), write_size, false); -- char* write_to = static_cast(MapPagesOrDie(2)); -- MprotectLastPageOrDie(write_to, 2); -+ char* write_to = static_cast(TestUtils::MapPagesOrDie(2)); -+ TestUtils::MprotectLastPageOrDie(write_to, 2); - write_to += base::GetPageSize() / 2; - base::ScopedFD parent_signal_fd; - const std::vector empty_fd_vec; -@@ -314,7 +302,7 @@ SANDBOX_TEST(BrokerRemoteSyscallArgHandler, WritePartiallyToInvalidAddress) { - } - - SANDBOX_TEST(BrokerRemoteSyscallArgHandler, WriteChildExited) { -- char* addr = static_cast(MapPagesOrDie(1)); -+ char* addr = static_cast(TestUtils::MapPagesOrDie(1)); - FillBufferWithPath(static_cast(addr), strlen(kPathPart) + 1, true); - - base::ScopedFD parent_sync, child_sync; -diff --git a/sandbox/linux/syscall_broker/syscall_dispatcher.cc b/sandbox/linux/syscall_broker/syscall_dispatcher.cc -index b9ee93c14ac59..8a42397ef872e 100644 ---- a/sandbox/linux/syscall_broker/syscall_dispatcher.cc -+++ b/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(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(args.args[3]) & AT_SYMLINK_NOFOLLOW); -- if (arch64) { -+ if (stat64) { - return Stat64(reinterpret_cast(args.args[1]), follow_links, -- reinterpret_cast(args.args[2])); -+ reinterpret_cast(args.args[2])); - } - - return Stat(reinterpret_cast(args.args[1]), follow_links, -- reinterpret_cast(args.args[2])); -+ reinterpret_cast(args.args[2])); -+} -+ -+int SyscallDispatcher::PerformUnlinkat(const arch_seccomp_data& args) { -+ if (static_cast(args.args[0]) != AT_FDCWD) -+ return -EPERM; -+ -+ int flags = static_cast(args.args[2]); -+ -+ if (flags == AT_REMOVEDIR) { -+ return Rmdir(reinterpret_cast(args.args[1])); -+ } -+ -+ if (flags != 0) -+ return -EPERM; -+ -+ return Unlink(reinterpret_cast(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(args.args[0]), true, -- reinterpret_cast(args.args[1])); -+ reinterpret_cast(args.args[1])); - #endif - #if defined(__NR_stat64) - case __NR_stat64: - return Stat64(reinterpret_cast(args.args[0]), true, -- reinterpret_cast(args.args[1])); -+ reinterpret_cast(args.args[1])); - #endif - #if defined(__NR_lstat) - case __NR_lstat: - // See https://crbug.com/847096 - BROKER_UNPOISON_STRING(reinterpret_cast(args.args[0])); - return Stat(reinterpret_cast(args.args[0]), false, -- reinterpret_cast(args.args[1])); -+ reinterpret_cast(args.args[1])); - #endif - #if defined(__NR_lstat64) - case __NR_lstat64: - // See https://crbug.com/847096 - BROKER_UNPOISON_STRING(reinterpret_cast(args.args[0])); - return Stat64(reinterpret_cast(args.args[0]), false, -- reinterpret_cast(args.args[1])); --#endif --#if defined(__NR_fstatat) -- case __NR_fstatat: -- return PerformStatat(args, /*arch64=*/false); -+ reinterpret_cast(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(args.args[0])); - #endif - #if defined(__NR_unlinkat) -- case __NR_unlinkat: { -- if (static_cast(args.args[0]) != AT_FDCWD) -- return -EPERM; -- -- int flags = static_cast(args.args[2]); -- -- if (flags == AT_REMOVEDIR) { -- return Rmdir(reinterpret_cast(args.args[1])); -- } -- -- if (flags != 0) -- return -EPERM; -- -- return Unlink(reinterpret_cast(args.args[1])); -- } -+ case __NR_unlinkat: -+ return PerformUnlinkat(args); - #endif // defined(__NR_unlinkat) - default: - RAW_CHECK(false); -diff --git a/sandbox/linux/syscall_broker/syscall_dispatcher.h b/sandbox/linux/syscall_broker/syscall_dispatcher.h -index d8b8874ad9ce4..1d6653caf3bd2 100644 ---- a/sandbox/linux/syscall_broker/syscall_dispatcher.h -+++ b/sandbox/linux/syscall_broker/syscall_dispatcher.h -@@ -9,13 +9,15 @@ - #include - - #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 -diff --git a/sandbox/linux/system_headers/linux_stat.h b/sandbox/linux/system_headers/linux_stat.h -new file mode 100644 -index 0000000000000..35788eb22a4e5 ---- /dev/null -+++ b/sandbox/linux/system_headers/linux_stat.h -@@ -0,0 +1,188 @@ -+// Copyright 2021 The Chromium Authors. All rights reserved. -+// Use of this source code is governed by a BSD-style license that can be -+// found in the LICENSE file. -+ -+#ifndef SANDBOX_LINUX_SYSTEM_HEADERS_LINUX_STAT_H_ -+#define SANDBOX_LINUX_SYSTEM_HEADERS_LINUX_STAT_H_ -+ -+#include -+ -+#include "build/build_config.h" -+#include "sandbox/linux/system_headers/linux_syscalls.h" -+ -+#if defined(ARCH_CPU_MIPS_FAMILY) -+#if defined(ARCH_CPU_64_BITS) -+struct kernel_stat { -+#else -+struct kernel_stat64 { -+#endif -+ unsigned st_dev; -+ unsigned __pad0[3]; -+ unsigned long long st_ino; -+ unsigned st_mode; -+ unsigned st_nlink; -+ unsigned st_uid; -+ unsigned st_gid; -+ unsigned st_rdev; -+ unsigned __pad1[3]; -+ long long st_size; -+ unsigned st_atime_; -+ unsigned st_atime_nsec_; -+ unsigned st_mtime_; -+ unsigned st_mtime_nsec_; -+ unsigned st_ctime_; -+ unsigned st_ctime_nsec_; -+ unsigned st_blksize; -+ unsigned __pad2; -+ unsigned long long st_blocks; -+}; -+#else -+struct kernel_stat64 { -+ unsigned long long st_dev; -+ unsigned char __pad0[4]; -+ unsigned __st_ino; -+ unsigned st_mode; -+ unsigned st_nlink; -+ unsigned st_uid; -+ unsigned st_gid; -+ unsigned long long st_rdev; -+ unsigned char __pad3[4]; -+ long long st_size; -+ unsigned st_blksize; -+ unsigned long long st_blocks; -+ unsigned st_atime_; -+ unsigned st_atime_nsec_; -+ unsigned st_mtime_; -+ unsigned st_mtime_nsec_; -+ unsigned st_ctime_; -+ unsigned st_ctime_nsec_; -+ unsigned long long st_ino; -+}; -+#endif -+ -+#if defined(__i386__) || defined(__ARM_ARCH_3__) || defined(__ARM_EABI__) -+struct kernel_stat { -+ /* The kernel headers suggest that st_dev and st_rdev should be 32bit -+ * quantities encoding 12bit major and 20bit minor numbers in an interleaved -+ * format. In reality, we do not see useful data in the top bits. So, -+ * we'll leave the padding in here, until we find a better solution. -+ */ -+ unsigned short st_dev; -+ short pad1; -+ unsigned st_ino; -+ unsigned short st_mode; -+ unsigned short st_nlink; -+ unsigned short st_uid; -+ unsigned short st_gid; -+ unsigned short st_rdev; -+ short pad2; -+ unsigned st_size; -+ unsigned st_blksize; -+ unsigned st_blocks; -+ unsigned st_atime_; -+ unsigned st_atime_nsec_; -+ unsigned st_mtime_; -+ unsigned st_mtime_nsec_; -+ unsigned st_ctime_; -+ unsigned st_ctime_nsec_; -+ unsigned __unused4; -+ unsigned __unused5; -+}; -+#elif defined(__x86_64__) -+struct kernel_stat { -+ uint64_t st_dev; -+ uint64_t st_ino; -+ uint64_t st_nlink; -+ unsigned st_mode; -+ unsigned st_uid; -+ unsigned st_gid; -+ unsigned __pad0; -+ uint64_t st_rdev; -+ int64_t st_size; -+ int64_t st_blksize; -+ int64_t st_blocks; -+ uint64_t st_atime_; -+ uint64_t st_atime_nsec_; -+ uint64_t st_mtime_; -+ uint64_t st_mtime_nsec_; -+ uint64_t st_ctime_; -+ uint64_t st_ctime_nsec_; -+ int64_t __unused4[3]; -+}; -+#elif (defined(ARCH_CPU_MIPS_FAMILY) && defined(ARCH_CPU_32_BITS)) -+struct kernel_stat { -+ unsigned st_dev; -+ int st_pad1[3]; -+ unsigned st_ino; -+ unsigned st_mode; -+ unsigned st_nlink; -+ unsigned st_uid; -+ unsigned st_gid; -+ unsigned st_rdev; -+ int st_pad2[2]; -+ long st_size; -+ int st_pad3; -+ long st_atime_; -+ long st_atime_nsec_; -+ long st_mtime_; -+ long st_mtime_nsec_; -+ long st_ctime_; -+ long st_ctime_nsec_; -+ int st_blksize; -+ int st_blocks; -+ int st_pad4[14]; -+}; -+#elif defined(__aarch64__) -+struct kernel_stat { -+ unsigned long st_dev; -+ unsigned long st_ino; -+ unsigned int st_mode; -+ unsigned int st_nlink; -+ unsigned int st_uid; -+ unsigned int st_gid; -+ unsigned long st_rdev; -+ unsigned long __pad1; -+ long st_size; -+ int st_blksize; -+ int __pad2; -+ long st_blocks; -+ long st_atime_; -+ unsigned long st_atime_nsec_; -+ long st_mtime_; -+ unsigned long st_mtime_nsec_; -+ long st_ctime_; -+ unsigned long st_ctime_nsec_; -+ unsigned int __unused4; -+ unsigned int __unused5; -+}; -+#endif -+ -+// On 32-bit systems, we default to the 64-bit stat struct like libc -+// implementations do. Otherwise we default to the normal stat struct which is -+// already 64-bit. -+// These defines make it easy to call the right syscall to fill out a 64-bit -+// stat struct, which is the default in libc implementations but requires -+// different syscall names on 32 and 64-bit platforms. -+#if defined(__NR_fstatat64) -+ -+namespace sandbox { -+using default_stat_struct = struct kernel_stat64; -+} // namespace sandbox -+ -+#define __NR_fstatat_default __NR_fstatat64 -+#define __NR_fstat_default __NR_fstat64 -+ -+#elif defined(__NR_newfstatat) -+ -+namespace sandbox { -+using default_stat_struct = struct kernel_stat; -+} // namespace sandbox -+ -+#define __NR_fstatat_default __NR_newfstatat -+#define __NR_fstat_default __NR_fstat -+ -+#else -+#error "one of fstatat64 and newfstatat must be defined" -+#endif -+ -+#endif // SANDBOX_LINUX_SYSTEM_HEADERS_LINUX_STAT_H_ -diff --git a/sandbox/linux/system_headers/linux_time.h b/sandbox/linux/system_headers/linux_time.h -index 780f24dddd9fa..f18c806611f83 100644 ---- a/sandbox/linux/system_headers/linux_time.h -+++ b/sandbox/linux/system_headers/linux_time.h -@@ -11,6 +11,32 @@ - #define CPUCLOCK_CLOCK_MASK 3 - #endif - -+#if !defined(CPUCLOCK_PROF) -+#define CPUCLOCK_PROF 0 -+#endif -+ -+#if !defined(CPUCLOCK_VIRT) -+#define CPUCLOCK_VIRT 1 -+#endif -+ -+#if !defined(CPUCLOCK_SCHED) -+#define CPUCLOCK_SCHED 2 -+#endif -+ -+#if !defined(CPUCLOCK_PERTHREAD_MASK) -+#define CPUCLOCK_PERTHREAD_MASK 4 -+#endif -+ -+#if !defined(MAKE_PROCESS_CPUCLOCK) -+#define MAKE_PROCESS_CPUCLOCK(pid, clock) \ -+ ((int)(~(unsigned)(pid) << 3) | (int)(clock)) -+#endif -+ -+#if !defined(MAKE_THREAD_CPUCLOCK) -+#define MAKE_THREAD_CPUCLOCK(tid, clock) \ -+ ((int)(~(unsigned)(tid) << 3) | (int)((clock) | CPUCLOCK_PERTHREAD_MASK)) -+#endif -+ - #if !defined(CLOCKFD) - #define CLOCKFD 3 - #endif -diff --git a/sandbox/linux/tests/test_utils.cc b/sandbox/linux/tests/test_utils.cc -index 847c20b20c5d2..cf6041a4b476a 100644 ---- a/sandbox/linux/tests/test_utils.cc -+++ b/sandbox/linux/tests/test_utils.cc -@@ -5,12 +5,14 @@ - #include "sandbox/linux/tests/test_utils.h" - - #include -+#include - #include - #include - #include - #include - - #include "base/check_op.h" -+#include "base/memory/page_size.h" - #include "base/posix/eintr_wrapper.h" - - namespace sandbox { -@@ -39,4 +41,17 @@ void TestUtils::HandlePostForkReturn(pid_t pid) { - } - } - -+void* TestUtils::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 TestUtils::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); -+} -+ - } // namespace sandbox -diff --git a/sandbox/linux/tests/test_utils.h b/sandbox/linux/tests/test_utils.h -index 7cf9749fe4f1f..43b028b1e34ef 100644 ---- a/sandbox/linux/tests/test_utils.h -+++ b/sandbox/linux/tests/test_utils.h -@@ -19,6 +19,8 @@ class TestUtils { - // makes sure that if fork() succeeded the child exits - // and the parent waits for it. - static void HandlePostForkReturn(pid_t pid); -+ static void* MapPagesOrDie(size_t num_pages); -+ static void MprotectLastPageOrDie(char* addr, size_t num_pages); - - private: - DISALLOW_IMPLICIT_CONSTRUCTORS(TestUtils); -diff --git a/sandbox/policy/linux/bpf_broker_policy_linux.cc b/sandbox/policy/linux/bpf_broker_policy_linux.cc -index 2963bb9ca8612..6dc8c0581b43c 100644 ---- a/sandbox/policy/linux/bpf_broker_policy_linux.cc -+++ b/sandbox/policy/linux/bpf_broker_policy_linux.cc -@@ -93,8 +93,8 @@ ResultExpr BrokerProcessPolicy::EvaluateSyscall(int sysno) const { - return Allow(); - break; - #endif --#if defined(__NR_fstatat) -- case __NR_fstatat: -+#if defined(__NR_fstatat64) -+ case __NR_fstatat64: - if (allowed_command_set_.test(syscall_broker::COMMAND_STAT)) - return Allow(); - break; diff --git a/60d5e803ef2a4874d29799b638754152285e0ed9.patch b/60d5e803ef2a4874d29799b638754152285e0ed9.patch deleted file mode 100644 index 7baf52b..0000000 --- a/60d5e803ef2a4874d29799b638754152285e0ed9.patch +++ /dev/null @@ -1,348 +0,0 @@ -From 60d5e803ef2a4874d29799b638754152285e0ed9 Mon Sep 17 00:00:00 2001 -From: Matthew Denton -Date: Wed, 21 Jul 2021 12:55:11 +0000 -Subject: [PATCH] Linux sandbox: fix fstatat() crash - -This is a reland of https://crrev.com/c/2801873. - -Glibc has started rewriting fstat(fd, stat_buf) to -fstatat(fd, "", stat_buf, AT_EMPTY_PATH). This works because when -AT_EMPTY_PATH is specified, and the second argument is an empty string, -then fstatat just performs an fstat on fd like normal. - -Unfortunately, fstatat() also allows stat-ing arbitrary pathnames like -with fstatat(AT_FDCWD, "/i/am/a/file", stat_buf, 0); -The baseline policy needs to prevent this usage of fstatat() since it -doesn't allow access to arbitrary pathnames. - -Sadly, if the second argument is not an empty string, AT_EMPTY_PATH is -simply ignored by current kernels. - -This means fstatat() is completely unsandboxable with seccomp, since -we *need* to verify that the second argument is the empty string, but -we can't dereference pointers in seccomp (due to limitations of BPF, -and the difficulty of addressing these limitations due to TOCTOU -issues). - -So, this CL Traps (raises a SIGSYS via seccomp) on any fstatat syscall. -The signal handler, which runs in the sandboxed process, checks for -AT_EMPTY_PATH and the empty string, and then rewrites any applicable -fstatat() back into the old-style fstat(). - -Bug: 1164975 -Change-Id: I3df6c04c0d781eb1f181d707ccaaead779337291 -Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/3042179 -Reviewed-by: Robert Sesek -Commit-Queue: Matthew Denton -Cr-Commit-Position: refs/heads/master@{#903873} ---- - .../seccomp-bpf-helpers/baseline_policy.cc | 8 ++++++ - .../baseline_policy_unittest.cc | 17 ++++++++++++- - .../seccomp-bpf-helpers/sigsys_handlers.cc | 25 +++++++++++++++++++ - .../seccomp-bpf-helpers/sigsys_handlers.h | 14 +++++++++++ - .../linux/syscall_broker/broker_process.cc | 21 ++++++++++------ - .../syscall_broker/broker_process_unittest.cc | 18 ++++++------- - sandbox/linux/system_headers/linux_stat.h | 4 +++ - 7 files changed, 89 insertions(+), 18 deletions(-) - -diff --git a/sandbox/linux/seccomp-bpf-helpers/baseline_policy.cc b/sandbox/linux/seccomp-bpf-helpers/baseline_policy.cc -index f2a60bb4d738d..9df0d2dbd3b5f 100644 ---- a/sandbox/linux/seccomp-bpf-helpers/baseline_policy.cc -+++ b/sandbox/linux/seccomp-bpf-helpers/baseline_policy.cc -@@ -20,6 +20,7 @@ - #include "sandbox/linux/seccomp-bpf-helpers/syscall_sets.h" - #include "sandbox/linux/seccomp-bpf/sandbox_bpf.h" - #include "sandbox/linux/services/syscall_wrappers.h" -+#include "sandbox/linux/system_headers/linux_stat.h" - #include "sandbox/linux/system_headers/linux_syscalls.h" - - #if !defined(SO_PEEK_OFF) -@@ -304,6 +305,13 @@ ResultExpr EvaluateSyscallImpl(int fs_denied_errno, - return Allow(); - } - -+ // The fstatat syscalls are file system syscalls, which will be denied below -+ // with fs_denied_errno. However some allowed fstat syscalls are rewritten by -+ // libc implementations to fstatat syscalls, and we need to rewrite them back. -+ if (sysno == __NR_fstatat_default) { -+ return RewriteFstatatSIGSYS(fs_denied_errno); -+ } -+ - if (SyscallSets::IsFileSystem(sysno) || - SyscallSets::IsCurrentDirectory(sysno)) { - return Error(fs_denied_errno); -diff --git a/sandbox/linux/seccomp-bpf-helpers/baseline_policy_unittest.cc b/sandbox/linux/seccomp-bpf-helpers/baseline_policy_unittest.cc -index 68c29b564bb8f..57d307e09d36b 100644 ---- a/sandbox/linux/seccomp-bpf-helpers/baseline_policy_unittest.cc -+++ b/sandbox/linux/seccomp-bpf-helpers/baseline_policy_unittest.cc -@@ -51,7 +51,8 @@ namespace sandbox { - - namespace { - --// This also tests that read(), write() and fstat() are allowed. -+// This also tests that read(), write(), fstat(), and fstatat(.., "", .., -+// AT_EMPTY_PATH) are allowed. - void TestPipeOrSocketPair(base::ScopedFD read_end, base::ScopedFD write_end) { - BPF_ASSERT_LE(0, read_end.get()); - BPF_ASSERT_LE(0, write_end.get()); -@@ -60,6 +61,20 @@ void TestPipeOrSocketPair(base::ScopedFD read_end, base::ScopedFD write_end) { - BPF_ASSERT_EQ(0, sys_ret); - BPF_ASSERT(S_ISFIFO(stat_buf.st_mode) || S_ISSOCK(stat_buf.st_mode)); - -+ sys_ret = fstatat(read_end.get(), "", &stat_buf, AT_EMPTY_PATH); -+ BPF_ASSERT_EQ(0, sys_ret); -+ BPF_ASSERT(S_ISFIFO(stat_buf.st_mode) || S_ISSOCK(stat_buf.st_mode)); -+ -+ // Make sure fstatat with anything other than an empty string is denied. -+ sys_ret = fstatat(read_end.get(), "/", &stat_buf, AT_EMPTY_PATH); -+ BPF_ASSERT_EQ(sys_ret, -1); -+ BPF_ASSERT_EQ(EPERM, errno); -+ -+ // Make sure fstatat without AT_EMPTY_PATH is denied. -+ sys_ret = fstatat(read_end.get(), "", &stat_buf, 0); -+ BPF_ASSERT_EQ(sys_ret, -1); -+ BPF_ASSERT_EQ(EPERM, errno); -+ - const ssize_t kTestTransferSize = 4; - static const char kTestString[kTestTransferSize] = {'T', 'E', 'S', 'T'}; - ssize_t transfered = 0; -diff --git a/sandbox/linux/seccomp-bpf-helpers/sigsys_handlers.cc b/sandbox/linux/seccomp-bpf-helpers/sigsys_handlers.cc -index 64edbd68bde6b..71068a045277b 100644 ---- a/sandbox/linux/seccomp-bpf-helpers/sigsys_handlers.cc -+++ b/sandbox/linux/seccomp-bpf-helpers/sigsys_handlers.cc -@@ -6,6 +6,7 @@ - - #include "sandbox/linux/seccomp-bpf-helpers/sigsys_handlers.h" - -+#include - #include - #include - #include -@@ -22,6 +23,7 @@ - #include "sandbox/linux/seccomp-bpf/syscall.h" - #include "sandbox/linux/services/syscall_wrappers.h" - #include "sandbox/linux/system_headers/linux_seccomp.h" -+#include "sandbox/linux/system_headers/linux_stat.h" - #include "sandbox/linux/system_headers/linux_syscalls.h" - - #if defined(__mips__) -@@ -355,6 +357,24 @@ intptr_t SIGSYSSchedHandler(const struct arch_seccomp_data& args, - return -ENOSYS; - } - -+intptr_t SIGSYSFstatatHandler(const struct arch_seccomp_data& args, -+ void* fs_denied_errno) { -+ if (args.nr == __NR_fstatat_default) { -+ if (*reinterpret_cast(args.args[1]) == '\0' && -+ args.args[3] == static_cast(AT_EMPTY_PATH)) { -+ return syscall(__NR_fstat_default, static_cast(args.args[0]), -+ reinterpret_cast(args.args[2])); -+ } -+ return -reinterpret_cast(fs_denied_errno); -+ } -+ -+ CrashSIGSYS_Handler(args, fs_denied_errno); -+ -+ // Should never be reached. -+ RAW_CHECK(false); -+ return -ENOSYS; -+} -+ - bpf_dsl::ResultExpr CrashSIGSYS() { - return bpf_dsl::Trap(CrashSIGSYS_Handler, NULL); - } -@@ -387,6 +407,11 @@ bpf_dsl::ResultExpr RewriteSchedSIGSYS() { - return bpf_dsl::Trap(SIGSYSSchedHandler, NULL); - } - -+bpf_dsl::ResultExpr RewriteFstatatSIGSYS(int fs_denied_errno) { -+ return bpf_dsl::Trap(SIGSYSFstatatHandler, -+ reinterpret_cast(fs_denied_errno)); -+} -+ - void AllocateCrashKeys() { - #if !defined(OS_NACL_NONSFI) - if (seccomp_crash_key) -diff --git a/sandbox/linux/seccomp-bpf-helpers/sigsys_handlers.h b/sandbox/linux/seccomp-bpf-helpers/sigsys_handlers.h -index 7a958b93b27a7..8cd735ce15793 100644 ---- a/sandbox/linux/seccomp-bpf-helpers/sigsys_handlers.h -+++ b/sandbox/linux/seccomp-bpf-helpers/sigsys_handlers.h -@@ -62,6 +62,19 @@ SANDBOX_EXPORT intptr_t SIGSYSPtraceFailure(const arch_seccomp_data& args, - // sched_setparam(), sched_setscheduler() - SANDBOX_EXPORT intptr_t SIGSYSSchedHandler(const arch_seccomp_data& args, - void* aux); -+// If the fstatat() syscall is functionally equivalent to an fstat() syscall, -+// then rewrite the syscall to the equivalent fstat() syscall which can be -+// adequately sandboxed. -+// If the fstatat() is not functionally equivalent to an fstat() syscall, we -+// fail with -fs_denied_errno. -+// If the syscall is not an fstatat() at all, crash in the same way as -+// CrashSIGSYS_Handler. -+// This is necessary because glibc and musl have started rewriting fstat(fd, -+// stat_buf) as fstatat(fd, "", stat_buf, AT_EMPTY_PATH). We rewrite the latter -+// back to the former, which is actually sandboxable. -+SANDBOX_EXPORT intptr_t -+SIGSYSFstatatHandler(const struct arch_seccomp_data& args, -+ void* fs_denied_errno); - - // Variants of the above functions for use with bpf_dsl. - SANDBOX_EXPORT bpf_dsl::ResultExpr CrashSIGSYS(); -@@ -72,6 +85,7 @@ SANDBOX_EXPORT bpf_dsl::ResultExpr CrashSIGSYSKill(); - SANDBOX_EXPORT bpf_dsl::ResultExpr CrashSIGSYSFutex(); - SANDBOX_EXPORT bpf_dsl::ResultExpr CrashSIGSYSPtrace(); - SANDBOX_EXPORT bpf_dsl::ResultExpr RewriteSchedSIGSYS(); -+SANDBOX_EXPORT bpf_dsl::ResultExpr RewriteFstatatSIGSYS(int fs_denied_errno); - - // Allocates a crash key so that Seccomp information can be recorded. - void AllocateCrashKeys(); -diff --git a/sandbox/linux/syscall_broker/broker_process.cc b/sandbox/linux/syscall_broker/broker_process.cc -index c2176eb785e78..e9dad37485aef 100644 ---- a/sandbox/linux/syscall_broker/broker_process.cc -+++ b/sandbox/linux/syscall_broker/broker_process.cc -@@ -113,44 +113,49 @@ bool BrokerProcess::IsSyscallAllowed(int sysno) const { - } - - bool BrokerProcess::IsSyscallBrokerable(int sysno, bool fast_check) const { -+ // The syscalls unavailable on aarch64 are all blocked by Android's default -+ // seccomp policy, even on non-aarch64 architectures. I.e., the syscalls XX() -+ // with a corresponding XXat() versions are typically unavailable in aarch64 -+ // and are default disabled in Android. So, we should refuse to broker them -+ // to be consistent with the platform's restrictions. - switch (sysno) { --#if !defined(__aarch64__) -+#if !defined(__aarch64__) && !defined(OS_ANDROID) - case __NR_access: - #endif - case __NR_faccessat: - return !fast_check || allowed_command_set_.test(COMMAND_ACCESS); - --#if !defined(__aarch64__) -+#if !defined(__aarch64__) && !defined(OS_ANDROID) - case __NR_mkdir: - #endif - case __NR_mkdirat: - return !fast_check || allowed_command_set_.test(COMMAND_MKDIR); - --#if !defined(__aarch64__) -+#if !defined(__aarch64__) && !defined(OS_ANDROID) - case __NR_open: - #endif - case __NR_openat: - return !fast_check || allowed_command_set_.test(COMMAND_OPEN); - --#if !defined(__aarch64__) -+#if !defined(__aarch64__) && !defined(OS_ANDROID) - case __NR_readlink: - #endif - case __NR_readlinkat: - return !fast_check || allowed_command_set_.test(COMMAND_READLINK); - --#if !defined(__aarch64__) -+#if !defined(__aarch64__) && !defined(OS_ANDROID) - case __NR_rename: - #endif - case __NR_renameat: - case __NR_renameat2: - return !fast_check || allowed_command_set_.test(COMMAND_RENAME); - --#if !defined(__aarch64__) -+#if !defined(__aarch64__) && !defined(OS_ANDROID) - case __NR_rmdir: - return !fast_check || allowed_command_set_.test(COMMAND_RMDIR); - #endif - --#if !defined(__aarch64__) -+#if !defined(__aarch64__) && !defined(OS_ANDROID) - case __NR_stat: - case __NR_lstat: - #endif -@@ -175,7 +180,7 @@ bool BrokerProcess::IsSyscallBrokerable(int sysno, bool fast_check) const { - return !fast_check || allowed_command_set_.test(COMMAND_STAT); - #endif - --#if !defined(__aarch64__) -+#if !defined(__aarch64__) && !defined(OS_ANDROID) - case __NR_unlink: - return !fast_check || allowed_command_set_.test(COMMAND_UNLINK); - #endif -diff --git a/sandbox/linux/syscall_broker/broker_process_unittest.cc b/sandbox/linux/syscall_broker/broker_process_unittest.cc -index c65f25a78a999..f0db08d84e06c 100644 ---- a/sandbox/linux/syscall_broker/broker_process_unittest.cc -+++ b/sandbox/linux/syscall_broker/broker_process_unittest.cc -@@ -1596,52 +1596,52 @@ TEST(BrokerProcess, IsSyscallAllowed) { - const base::flat_map> kSysnosForCommand = { - {COMMAND_ACCESS, - {__NR_faccessat, --#if defined(__NR_access) -+#if defined(__NR_access) && !defined(OS_ANDROID) - __NR_access - #endif - }}, - {COMMAND_MKDIR, - {__NR_mkdirat, --#if defined(__NR_mkdir) -+#if defined(__NR_mkdir) && !defined(OS_ANDROID) - __NR_mkdir - #endif - }}, - {COMMAND_OPEN, - {__NR_openat, --#if defined(__NR_open) -+#if defined(__NR_open) && !defined(OS_ANDROID) - __NR_open - #endif - }}, - {COMMAND_READLINK, - {__NR_readlinkat, --#if defined(__NR_readlink) -+#if defined(__NR_readlink) && !defined(OS_ANDROID) - __NR_readlink - #endif - }}, - {COMMAND_RENAME, - {__NR_renameat, --#if defined(__NR_rename) -+#if defined(__NR_rename) && !defined(OS_ANDROID) - __NR_rename - #endif - }}, - {COMMAND_UNLINK, - {__NR_unlinkat, --#if defined(__NR_unlink) -+#if defined(__NR_unlink) && !defined(OS_ANDROID) - __NR_unlink - #endif - }}, - {COMMAND_RMDIR, - {__NR_unlinkat, --#if defined(__NR_rmdir) -+#if defined(__NR_rmdir) && !defined(OS_ANDROID) - __NR_rmdir - #endif - }}, - {COMMAND_STAT, - { --#if defined(__NR_stat) -+#if defined(__NR_stat) && !defined(OS_ANDROID) - __NR_stat, - #endif --#if defined(__NR_lstat) -+#if defined(__NR_lstat) && !defined(OS_ANDROID) - __NR_lstat, - #endif - #if defined(__NR_fstatat) -diff --git a/sandbox/linux/system_headers/linux_stat.h b/sandbox/linux/system_headers/linux_stat.h -index 35788eb22a4e5..83b89efc75e5e 100644 ---- a/sandbox/linux/system_headers/linux_stat.h -+++ b/sandbox/linux/system_headers/linux_stat.h -@@ -157,6 +157,10 @@ struct kernel_stat { - }; - #endif - -+#if !defined(AT_EMPTY_PATH) -+#define AT_EMPTY_PATH 0x1000 -+#endif -+ - // On 32-bit systems, we default to the 64-bit stat struct like libc - // implementations do. Otherwise we default to the normal stat struct which is - // already 64-bit. diff --git a/b2fbcdbe30cb84cd2f0b63e453f3782c49213264.patch b/b2fbcdbe30cb84cd2f0b63e453f3782c49213264.patch deleted file mode 100644 index 78eab1c..0000000 --- a/b2fbcdbe30cb84cd2f0b63e453f3782c49213264.patch +++ /dev/null @@ -1,70 +0,0 @@ -From b2fbcdbe30cb84cd2f0b63e453f3782c49213264 Mon Sep 17 00:00:00 2001 -From: Matthew Denton -Date: Wed, 21 Jul 2021 17:12:27 +0000 -Subject: [PATCH] Linux sandbox: ENOSYS for some statx syscalls - -On some platforms, glibc will default to statx for normal stat-family -calls. Unfortunately there's no way to rewrite statx to something safe -using a signal handler. Returning ENOSYS will cause glibc to fallback -to old stat paths. - -Change-Id: Ieaddc8020b6555f2dfdc443197d13cb3fccc6bf1 -Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/2823150 -Commit-Queue: Matthew Denton -Reviewed-by: Robert Sesek -Cr-Commit-Position: refs/heads/master@{#903952} ---- - sandbox/linux/seccomp-bpf-helpers/baseline_policy.cc | 11 +++++++++++ - sandbox/linux/seccomp-bpf-helpers/syscall_sets.cc | 1 + - sandbox/linux/system_headers/linux_stat.h | 4 ++++ - 3 files changed, 16 insertions(+) - -diff --git a/sandbox/linux/seccomp-bpf-helpers/baseline_policy.cc b/sandbox/linux/seccomp-bpf-helpers/baseline_policy.cc -index 9df0d2dbd3b5f..049e921694eda 100644 ---- a/sandbox/linux/seccomp-bpf-helpers/baseline_policy.cc -+++ b/sandbox/linux/seccomp-bpf-helpers/baseline_policy.cc -@@ -312,6 +312,17 @@ ResultExpr EvaluateSyscallImpl(int fs_denied_errno, - return RewriteFstatatSIGSYS(fs_denied_errno); - } - -+ // The statx syscall is a filesystem syscall, which will be denied below with -+ // fs_denied_errno. However, on some platforms, glibc will default to statx -+ // for normal stat-family calls. Unfortunately there's no way to rewrite statx -+ // to something safe using a signal handler. Returning ENOSYS will cause glibc -+ // to fallback to old stat paths. -+ if (sysno == __NR_statx) { -+ const Arg mask(3); -+ return If(mask == STATX_BASIC_STATS, Error(ENOSYS)) -+ .Else(Error(fs_denied_errno)); -+ } -+ - if (SyscallSets::IsFileSystem(sysno) || - SyscallSets::IsCurrentDirectory(sysno)) { - return Error(fs_denied_errno); -diff --git a/sandbox/linux/seccomp-bpf-helpers/syscall_sets.cc b/sandbox/linux/seccomp-bpf-helpers/syscall_sets.cc -index 96c9f490e28cd..8227dc1854643 100644 ---- a/sandbox/linux/seccomp-bpf-helpers/syscall_sets.cc -+++ b/sandbox/linux/seccomp-bpf-helpers/syscall_sets.cc -@@ -171,6 +171,7 @@ bool SyscallSets::IsFileSystem(int sysno) { - (defined(ARCH_CPU_MIPS_FAMILY) && defined(ARCH_CPU_32_BITS)) - case __NR_statfs64: - #endif -+ case __NR_statx: // EPERM not a valid errno. - case __NR_symlinkat: - case __NR_truncate: - #if defined(__i386__) || defined(__arm__) || \ -diff --git a/sandbox/linux/system_headers/linux_stat.h b/sandbox/linux/system_headers/linux_stat.h -index 83b89efc75e5e..e697dd6777ef5 100644 ---- a/sandbox/linux/system_headers/linux_stat.h -+++ b/sandbox/linux/system_headers/linux_stat.h -@@ -161,6 +161,10 @@ struct kernel_stat { - #define AT_EMPTY_PATH 0x1000 - #endif - -+#if !defined(STATX_BASIC_STATS) -+#define STATX_BASIC_STATS 0x000007ffU -+#endif -+ - // On 32-bit systems, we default to the 64-bit stat struct like libc - // implementations do. Otherwise we default to the normal stat struct which is - // already 64-bit. diff --git a/chromium-browser-stable.spec b/chromium-browser-stable.spec index eb6ce64..fb7d0d2 100644 --- a/chromium-browser-stable.spec +++ b/chromium-browser-stable.spec @@ -50,8 +50,8 @@ # GOST patches and sources # Using commit hashes because upstream often puts tags long after making changes # (they wait for builds to finish to make a new "release" with binary packages) -%define chromium_gost_commit 3181acb959fcb8de4aa3aca4c51d8a89b90d367d -%define msspi_commit 676e76df03782fa965d8f985f4bd2e4c3ee81386 +%define chromium_gost_commit 63275ec358b1a1c0087dc3af770d18c1d5fe661d +%define msspi_commit 74a19443ca691e1acfee84e6176282e4ec338eac %define _gostsourcedir %{_builddir}/chromium-gost %define xcb_version 1.14.1 @@ -83,7 +83,7 @@ Summary: A fast web browser based on the Blink engine Name: chromium-browser-stable -Version: 93.0.4577.82 +Version: 94.0.4606.54 Release: 1 License: BSD, LGPL Group: Networking/WWW @@ -125,10 +125,6 @@ Patch647: ALT-allow-to-override-clang-through-env-variables.patch # XXX This patch is not enough to fully fix debuginfo and debugsource subpackages Patch648: fix-debugsource.patch Patch649: off-java-check.patch -# From Chromium 94+ for new glibc -Patch650: https://github.com/chromium/chromium/commit/4b438323d68840453b5ef826c3997568e2e0e8c7.patch -Patch651: https://github.com/chromium/chromium/commit/60d5e803ef2a4874d29799b638754152285e0ed9.patch -Patch652: https://github.com/chromium/chromium/commit/b2fbcdbe30cb84cd2f0b63e453f3782c49213264.patch BuildRequires: bison BuildRequires: llvm12 @@ -255,7 +251,7 @@ if proprietary CryptoPro is installed. %{_crdir}/chromium-wrapper %{_crdir}/chrome %{_crdir}/chrome-sandbox -%{_crdir}/crashpad_handler +%{_crdir}/chrome_crashpad_handler %{_crdir}/icudtl.dat %{_crdir}/locales %{_crdir}/*.pak @@ -358,7 +354,7 @@ popd # Hard code extra version FILE=chrome/common/channel_info_posix.cc -sed -i.orig -e 's/getenv("CHROME_VERSION_EXTRA")/"%{vendor} %{product_version}, RPM %{name} %{EVRD}%{?with_gost: + GOST TLS via CryptoPro}"/' $FILE +sed -i.orig -e 's/getenv("CHROME_VERSION_EXTRA")/"%{vendor} %{rosa_release}, RPM %{name} %{EVRD}%{?with_gost: + GOST TLS via CryptoPro}"/' $FILE cmp $FILE $FILE.orig && exit 1 # Use native page size on aarch64 ("if (current_cpu == "arm64")"), otherwise: @@ -585,7 +581,7 @@ mkdir -p %{buildroot}%{_crdir}/themes install -m 755 %{SOURCE1} %{buildroot}%{_crdir}/chromium-wrapper install -m 755 out/Release/chrome %{buildroot}%{_crdir}/ install -m 4755 out/Release/chrome_sandbox %{buildroot}%{_crdir}/chrome-sandbox -install -m 755 out/Release/crashpad_handler %{buildroot}%{_crdir}/crashpad_handler +install -m 755 out/Release/chrome_crashpad_handler %{buildroot}%{_crdir}/chrome_crashpad_handler cp -a out/Release/chromedriver %{buildroot}%{_crdir}/chromedriver install -m 644 out/Release/*.pak %{buildroot}%{_crdir}/ install -m 644 out/Release/icudtl.dat %{buildroot}%{_crdir}/