blob: 9a1a932fe263f2d98c62569f9eb38f2d6a49fa57 [file] [log] [blame]
// Copyright 2018 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.
#include "sandbox/linux/seccomp-bpf-helpers/baseline_policy_android.h"
#include <fcntl.h>
#include <linux/android/binder.h>
#include <linux/ashmem.h>
#include <linux/nbd.h>
#include <linux/userfaultfd.h>
#include <sched.h>
#include <sys/ioctl.h>
#include <sys/resource.h>
#include <sys/stat.h>
#include <sys/types.h>
#include "base/files/scoped_file.h"
#include "base/posix/eintr_wrapper.h"
#include "sandbox/linux/seccomp-bpf-helpers/sigsys_handlers.h"
#include "sandbox/linux/seccomp-bpf/bpf_tests.h"
namespace sandbox {
namespace {
BPF_TEST_C(BaselinePolicyAndroid, Getrusage, BaselinePolicyAndroid) {
struct rusage usage{};
errno = 0;
BPF_ASSERT_EQ(0, getrusage(RUSAGE_SELF, &usage));
errno = 0;
BPF_ASSERT_EQ(0, getrusage(RUSAGE_THREAD, &usage));
}
BPF_TEST_C(BaselinePolicyAndroid, CanOpenProcCpuinfo, BaselinePolicyAndroid) {
// This is required for |android_getCpuFeatures()|, which is used to enable
// various fast paths in the renderer (for instance, in zlib).
//
// __NR_open is blocked in 64 bit mode, but as long as libc's open() redirects
// open() to openat(), then this should work. Make sure this stays true.
BPF_ASSERT_NE(-1, open("/proc/cpuinfo", O_RDONLY));
}
BPF_TEST_C(BaselinePolicyAndroid, Membarrier, BaselinePolicyAndroid) {
// Should not crash.
syscall(__NR_membarrier, 32 /* cmd */, 0 /* flags */);
}
BPF_TEST_C(BaselinePolicyAndroid,
SchedGetAffinity_Blocked,
BaselinePolicyAndroid) {
cpu_set_t set{};
errno = 0;
BPF_ASSERT_EQ(-1, sched_getaffinity(0, sizeof(set), &set));
BPF_ASSERT_EQ(EPERM, errno);
}
BPF_TEST_C(BaselinePolicyAndroid,
SchedSetAffinity_Blocked,
BaselinePolicyAndroid) {
cpu_set_t set{};
errno = 0;
BPF_ASSERT_EQ(-1, sched_setaffinity(0, sizeof(set), &set));
BPF_ASSERT_EQ(EPERM, errno);
}
class AllowSchedSetaffinityBaselinePoliyAndroid : public BaselinePolicyAndroid {
public:
AllowSchedSetaffinityBaselinePoliyAndroid()
: BaselinePolicyAndroid(RuntimeOptions{.allow_sched_affinity = true}) {}
};
BPF_TEST_C(BaselinePolicyAndroid,
SchedAffinity_Allowed,
AllowSchedSetaffinityBaselinePoliyAndroid) {
cpu_set_t set{};
BPF_ASSERT_NE(-1, sched_getaffinity(0, sizeof(set), &set));
BPF_ASSERT_NE(-1, sched_setaffinity(0, sizeof(set), &set));
}
BPF_TEST_C(BaselinePolicyAndroid, Ioctl_Allowed, BaselinePolicyAndroid) {
base::ScopedFD fd(HANDLE_EINTR(open("/dev/null", O_RDWR)));
BPF_ASSERT(fd.is_valid());
errno = 0;
BPF_ASSERT_EQ(-1, ioctl(fd.get(), ASHMEM_SET_PROT_MASK));
BPF_ASSERT_EQ(ENOTTY, errno);
errno = 0;
BPF_ASSERT_EQ(-1, ioctl(fd.get(), BINDER_WRITE_READ));
BPF_ASSERT_EQ(ENOTTY, errno);
// 32- and 64-bit constant values for BINDER_WRITE_READ.
errno = 0;
BPF_ASSERT_EQ(-1, ioctl(fd.get(), 0xc0186201));
BPF_ASSERT_EQ(ENOTTY, errno);
errno = 0;
BPF_ASSERT_EQ(-1, ioctl(fd.get(), 0xc0306201));
BPF_ASSERT_EQ(ENOTTY, errno);
errno = 0;
BPF_ASSERT_EQ(-1, ioctl(fd.get(), TCGETS));
BPF_ASSERT_EQ(ENOTTY, errno);
}
BPF_TEST_C(BaselinePolicyAndroid, Ioctl_Blocked, BaselinePolicyAndroid) {
base::ScopedFD fd(HANDLE_EINTR(open("/dev/null", O_RDWR)));
BPF_ASSERT(fd.is_valid());
errno = 0;
BPF_ASSERT_EQ(-1, ioctl(fd.get(), NBD_CLEAR_SOCK));
BPF_ASSERT_EQ(EINVAL, errno);
}
BPF_DEATH_TEST_C(BaselinePolicyAndroid,
UserfaultfdIoctl_BlockedDefault,
DEATH_SEGV_MESSAGE(GetIoctlErrorMessageContentForTests()),
BaselinePolicyAndroid) {
base::ScopedFD fd(HANDLE_EINTR(open("/dev/null", O_RDWR)));
BPF_ASSERT(fd.is_valid());
ioctl(fd.get(), UFFDIO_WAKE);
}
class AllowUserfaultfdBaselinePolicyAndroid : public BaselinePolicyAndroid {
public:
AllowUserfaultfdBaselinePolicyAndroid()
: BaselinePolicyAndroid(
RuntimeOptions{.allow_userfaultfd_ioctls = true}) {}
};
BPF_TEST_C(BaselinePolicyAndroid,
UserfaultfdIoctl_Allowed,
AllowUserfaultfdBaselinePolicyAndroid) {
base::ScopedFD fd(HANDLE_EINTR(open("/dev/null", O_RDWR)));
BPF_ASSERT(fd.is_valid());
errno = 0;
BPF_ASSERT_EQ(-1, ioctl(fd.get(), UFFDIO_WAKE));
BPF_ASSERT_EQ(ENOTTY, errno);
}
BPF_DEATH_TEST_C(BaselinePolicyAndroid,
UserfaultfdIoctl_BlockedSubset,
DEATH_SEGV_MESSAGE(GetIoctlErrorMessageContentForTests()),
BaselinePolicyAndroid) {
base::ScopedFD fd(HANDLE_EINTR(open("/dev/null", O_RDWR)));
BPF_ASSERT(fd.is_valid());
ioctl(fd.get(), UFFDIO_API);
}
} // namespace
} // namespace sandbox