diff options
Diffstat (limited to 'chromium/sandbox/linux/seccomp-bpf-helpers/baseline_policy.cc')
-rw-r--r-- | chromium/sandbox/linux/seccomp-bpf-helpers/baseline_policy.cc | 175 |
1 files changed, 175 insertions, 0 deletions
diff --git a/chromium/sandbox/linux/seccomp-bpf-helpers/baseline_policy.cc b/chromium/sandbox/linux/seccomp-bpf-helpers/baseline_policy.cc new file mode 100644 index 00000000000..d0e53e39bc8 --- /dev/null +++ b/chromium/sandbox/linux/seccomp-bpf-helpers/baseline_policy.cc @@ -0,0 +1,175 @@ +// Copyright (c) 2013 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.h" + +#include <errno.h> +#include <sys/mman.h> +#include <sys/types.h> +#include <sys/socket.h> + +#include "base/logging.h" +#include "build/build_config.h" +#include "sandbox/linux/seccomp-bpf-helpers/sigsys_handlers.h" +#include "sandbox/linux/seccomp-bpf-helpers/syscall_parameters_restrictions.h" +#include "sandbox/linux/seccomp-bpf-helpers/syscall_sets.h" +#include "sandbox/linux/seccomp-bpf/sandbox_bpf.h" +#include "sandbox/linux/seccomp-bpf/sandbox_bpf_policy.h" +#include "sandbox/linux/services/linux_syscalls.h" + +// Changing this implementation will have an effect on *all* policies. +// Currently this means: Renderer/Worker, GPU, Flash and NaCl. + +namespace sandbox { + +namespace { + +bool IsBaselinePolicyAllowed(int sysno) { + return SyscallSets::IsAllowedAddressSpaceAccess(sysno) || + SyscallSets::IsAllowedBasicScheduler(sysno) || + SyscallSets::IsAllowedEpoll(sysno) || + SyscallSets::IsAllowedFileSystemAccessViaFd(sysno) || + SyscallSets::IsAllowedGeneralIo(sysno) || + SyscallSets::IsAllowedGetOrModifySocket(sysno) || + SyscallSets::IsAllowedGettime(sysno) || + SyscallSets::IsAllowedPrctl(sysno) || + SyscallSets::IsAllowedProcessStartOrDeath(sysno) || + SyscallSets::IsAllowedSignalHandling(sysno) || + SyscallSets::IsFutex(sysno) || + SyscallSets::IsGetSimpleId(sysno) || + SyscallSets::IsKernelInternalApi(sysno) || +#if defined(__arm__) + SyscallSets::IsArmPrivate(sysno) || +#endif + SyscallSets::IsKill(sysno) || + SyscallSets::IsAllowedOperationOnFd(sysno); +} + +// System calls that will trigger the crashing SIGSYS handler. +bool IsBaselinePolicyWatched(int sysno) { + return SyscallSets::IsAdminOperation(sysno) || + SyscallSets::IsAdvancedScheduler(sysno) || + SyscallSets::IsAdvancedTimer(sysno) || + SyscallSets::IsAsyncIo(sysno) || + SyscallSets::IsDebug(sysno) || + SyscallSets::IsEventFd(sysno) || + SyscallSets::IsExtendedAttributes(sysno) || + SyscallSets::IsFaNotify(sysno) || + SyscallSets::IsFsControl(sysno) || + SyscallSets::IsGlobalFSViewChange(sysno) || + SyscallSets::IsGlobalProcessEnvironment(sysno) || + SyscallSets::IsGlobalSystemStatus(sysno) || + SyscallSets::IsInotify(sysno) || + SyscallSets::IsKernelModule(sysno) || + SyscallSets::IsKeyManagement(sysno) || + SyscallSets::IsMessageQueue(sysno) || + SyscallSets::IsMisc(sysno) || +#if defined(__x86_64__) + SyscallSets::IsNetworkSocketInformation(sysno) || +#endif + SyscallSets::IsNuma(sysno) || + SyscallSets::IsProcessGroupOrSession(sysno) || + SyscallSets::IsProcessPrivilegeChange(sysno) || +#if defined(__i386__) + SyscallSets::IsSocketCall(sysno) || +#endif +#if defined(__arm__) + SyscallSets::IsArmPciConfig(sysno) || +#endif + SyscallSets::IsTimer(sysno); +} + +// |fs_denied_errno| is the errno return for denied filesystem access. +ErrorCode EvaluateSyscallImpl(int fs_denied_errno, SandboxBPF* sandbox, + int sysno) { + if (IsBaselinePolicyAllowed(sysno)) { + return ErrorCode(ErrorCode::ERR_ALLOWED); + } + +#if defined(__x86_64__) || defined(__arm__) + if (sysno == __NR_socketpair) { + // Only allow AF_UNIX, PF_UNIX. Crash if anything else is seen. + COMPILE_ASSERT(AF_UNIX == PF_UNIX, af_unix_pf_unix_different); + return sandbox->Cond(0, ErrorCode::TP_32BIT, ErrorCode::OP_EQUAL, AF_UNIX, + ErrorCode(ErrorCode::ERR_ALLOWED), + sandbox->Trap(CrashSIGSYS_Handler, NULL)); + } +#endif + + if (sysno == __NR_madvise) { + // Only allow MADV_DONTNEED (aka MADV_FREE). + return sandbox->Cond(2, ErrorCode::TP_32BIT, + ErrorCode::OP_EQUAL, MADV_DONTNEED, + ErrorCode(ErrorCode::ERR_ALLOWED), + ErrorCode(EPERM)); + } + +#if defined(__i386__) || defined(__x86_64__) + if (sysno == __NR_mmap) + return RestrictMmapFlags(sandbox); +#endif + +#if defined(__i386__) || defined(__arm__) + if (sysno == __NR_mmap2) + return RestrictMmapFlags(sandbox); +#endif + + if (sysno == __NR_mprotect) + return RestrictMprotectFlags(sandbox); + + if (sysno == __NR_fcntl) + return RestrictFcntlCommands(sandbox); + +#if defined(__i386__) || defined(__arm__) + if (sysno == __NR_fcntl64) + return RestrictFcntlCommands(sandbox); +#endif + + if (SyscallSets::IsFileSystem(sysno) || + SyscallSets::IsCurrentDirectory(sysno)) { + return ErrorCode(fs_denied_errno); + } + + if (SyscallSets::IsAnySystemV(sysno)) { + return ErrorCode(EPERM); + } + + if (SyscallSets::IsUmask(sysno) || + SyscallSets::IsDeniedFileSystemAccessViaFd(sysno) || + SyscallSets::IsDeniedGetOrModifySocket(sysno)) { + return ErrorCode(EPERM); + } + +#if defined(__i386__) + if (SyscallSets::IsSocketCall(sysno)) + return RestrictSocketcallCommand(sandbox); +#endif + + if (IsBaselinePolicyWatched(sysno)) { + // Previously unseen syscalls. TODO(jln): some of these should + // be denied gracefully right away. + return sandbox->Trap(CrashSIGSYS_Handler, NULL); + } + // In any other case crash the program with our SIGSYS handler. + return sandbox->Trap(CrashSIGSYS_Handler, NULL); +} + +} // namespace. + +// Unfortunately C++03 doesn't allow delegated constructors. +// Call other constructor when C++11 lands. +BaselinePolicy::BaselinePolicy() + : fs_denied_errno_(EPERM) {} + +BaselinePolicy::BaselinePolicy(int fs_denied_errno) + : fs_denied_errno_(fs_denied_errno) {} + +BaselinePolicy::~BaselinePolicy() {} + +ErrorCode BaselinePolicy::EvaluateSyscall(SandboxBPF* sandbox, + int sysno) const { + return EvaluateSyscallImpl(fs_denied_errno_, sandbox, sysno); +} + +} // namespace sandbox. |