chromium/sandbox/linux/services/syscall_wrappers_unittest.cc

// Copyright 2014 The Chromium Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#ifdef UNSAFE_BUFFERS_BUILD
// TODO(crbug.com/351564777): Remove this and convert code to safer constructs.
#pragma allow_unsafe_buffers
#endif

#include "sandbox/linux/services/syscall_wrappers.h"

#include <fcntl.h>
#include <stdint.h>
#include <string.h>
#include <sys/syscall.h>
#include <sys/types.h>
#include <sys/wait.h>
#include <unistd.h>

#include "base/logging.h"
#include "base/memory/page_size.h"
#include "base/posix/eintr_wrapper.h"
#include "base/system/sys_info.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"

namespace sandbox {

namespace {

TEST(SyscallWrappers, BasicSyscalls) {}

TEST(SyscallWrappers, CloneBasic) {}

TEST(SyscallWrappers, CloneParentSettid) {}

TEST(SyscallWrappers, CloneChildSettid) {}

TEST(SyscallWrappers, GetRESUid) {}

TEST(SyscallWrappers, GetRESGid) {}

TEST(SyscallWrappers, LinuxSigSet) {}

TEST(SyscallWrappers, Stat) {}

#if defined(__NR_fstatat64)
TEST(SyscallWrappers, Stat64) {
  static_assert(sizeof(struct kernel_stat64) == sizeof(default_stat_struct),
                "This test only works on systems where the default_stat_struct "
                "is kernel_stat64");
  // 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<char*>(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_fstatat64(AT_FDCWD, tmp_file.full_file_name(),
                    reinterpret_cast<struct kernel_stat64*>(page1_end - 1), 0);
  ASSERT_EQ(res, -1);
  ASSERT_EQ(errno, EFAULT);

  // Now, check that we have the correctly sized stat structure.
  struct kernel_stat64* sb = reinterpret_cast<struct kernel_stat64*>(
      page1_end - sizeof(struct kernel_stat64));
  memset(sb, 0, sizeof(struct kernel_stat64));
  res = sys_fstatat64(AT_FDCWD, tmp_file.full_file_name(), sb, 0);
  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<unsigned int>(sb->st_dev));
  EXPECT_NE(0u, static_cast<unsigned int>(sb->st_ino));
  EXPECT_NE(0u, static_cast<unsigned int>(sb->st_mode));
  EXPECT_NE(0u, static_cast<unsigned int>(sb->st_blksize));
  EXPECT_NE(0u, static_cast<unsigned int>(sb->st_blocks));

  // We are the ones that made the file.
  EXPECT_EQ(geteuid(), sb->st_uid);
  EXPECT_EQ(getegid(), sb->st_gid);

  // Wrote 12 bytes above which should fit in one block.
  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_));
}
#endif  // defined(__NR_fstatat64)

TEST(SyscallWrappers, LStat) {}

}  // namespace

}  // namespace sandbox