diff options
author | jln@chromium.org <jln@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2014-04-29 18:42:09 +0000 |
---|---|---|
committer | jln@chromium.org <jln@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2014-04-29 18:42:09 +0000 |
commit | f700f51f5aafb24272990444d5ca392004d7e19f (patch) | |
tree | fa37318673b658ede829a34661d8f41be2db764d /sandbox | |
parent | af3486d738af606f6c9bdc267c2b9e3abab28a21 (diff) | |
download | chromium_src-f700f51f5aafb24272990444d5ca392004d7e19f.zip chromium_src-f700f51f5aafb24272990444d5ca392004d7e19f.tar.gz chromium_src-f700f51f5aafb24272990444d5ca392004d7e19f.tar.bz2 |
Linux sandbox: restrict *kill to the current process.
Restrict tgkill(2) and kill(2) to the current process, forbid tkill.
BUG=367986
R=jorgelo@chromium.org
Review URL: https://codereview.chromium.org/258073008
git-svn-id: svn://svn.chromium.org/chrome/trunk/src@266926 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'sandbox')
7 files changed, 73 insertions, 11 deletions
diff --git a/sandbox/linux/seccomp-bpf-helpers/baseline_policy.cc b/sandbox/linux/seccomp-bpf-helpers/baseline_policy.cc index c72b53a..508ae3e 100644 --- a/sandbox/linux/seccomp-bpf-helpers/baseline_policy.cc +++ b/sandbox/linux/seccomp-bpf-helpers/baseline_policy.cc @@ -6,8 +6,10 @@ #include <errno.h> #include <sys/mman.h> -#include <sys/types.h> #include <sys/socket.h> +#include <sys/syscall.h> +#include <sys/types.h> +#include <unistd.h> #include "base/logging.h" #include "build/build_config.h" @@ -42,7 +44,6 @@ bool IsBaselinePolicyAllowed(int sysno) { #if defined(__arm__) SyscallSets::IsArmPrivate(sysno) || #endif - SyscallSets::IsKill(sysno) || SyscallSets::IsAllowedOperationOnFd(sysno); } @@ -63,6 +64,7 @@ bool IsBaselinePolicyWatched(int sysno) { SyscallSets::IsInotify(sysno) || SyscallSets::IsKernelModule(sysno) || SyscallSets::IsKeyManagement(sysno) || + SyscallSets::IsKill(sysno) || SyscallSets::IsMessageQueue(sysno) || SyscallSets::IsMisc(sysno) || #if defined(__x86_64__) @@ -80,7 +82,9 @@ bool IsBaselinePolicyWatched(int sysno) { } // |fs_denied_errno| is the errno return for denied filesystem access. -ErrorCode EvaluateSyscallImpl(int fs_denied_errno, SandboxBPF* sandbox, +ErrorCode EvaluateSyscallImpl(int fs_denied_errno, + pid_t current_pid, + SandboxBPF* sandbox, int sysno) { if (IsBaselinePolicyAllowed(sysno)) { return ErrorCode(ErrorCode::ERR_ALLOWED); @@ -125,6 +129,10 @@ ErrorCode EvaluateSyscallImpl(int fs_denied_errno, SandboxBPF* sandbox, return RestrictFcntlCommands(sandbox); #endif + if (SyscallSets::IsKill(sysno)) { + return RestrictKillTarget(current_pid, sandbox, sysno); + } + if (SyscallSets::IsFileSystem(sysno) || SyscallSets::IsCurrentDirectory(sysno)) { return ErrorCode(fs_denied_errno); @@ -151,6 +159,7 @@ ErrorCode EvaluateSyscallImpl(int fs_denied_errno, SandboxBPF* sandbox, // 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); } @@ -160,16 +169,24 @@ ErrorCode EvaluateSyscallImpl(int fs_denied_errno, SandboxBPF* sandbox, // Unfortunately C++03 doesn't allow delegated constructors. // Call other constructor when C++11 lands. BaselinePolicy::BaselinePolicy() - : fs_denied_errno_(EPERM) {} + : fs_denied_errno_(EPERM), current_pid_(syscall(__NR_getpid)) {} BaselinePolicy::BaselinePolicy(int fs_denied_errno) - : fs_denied_errno_(fs_denied_errno) {} + : fs_denied_errno_(fs_denied_errno), current_pid_(syscall(__NR_getpid)) {} -BaselinePolicy::~BaselinePolicy() {} +BaselinePolicy::~BaselinePolicy() { + // Make sure that this policy is created, used and destroyed by a single + // process. + DCHECK_EQ(syscall(__NR_getpid), current_pid_); +} ErrorCode BaselinePolicy::EvaluateSyscall(SandboxBPF* sandbox, int sysno) const { - return EvaluateSyscallImpl(fs_denied_errno_, sandbox, sysno); + // Make sure that this policy is used in the creating process. + if (1 == sysno) { + DCHECK_EQ(syscall(__NR_getpid), current_pid_); + } + return EvaluateSyscallImpl(fs_denied_errno_, current_pid_, sandbox, sysno); } } // namespace sandbox. diff --git a/sandbox/linux/seccomp-bpf-helpers/baseline_policy.h b/sandbox/linux/seccomp-bpf-helpers/baseline_policy.h index f1e4bb9..fe7c5dc 100644 --- a/sandbox/linux/seccomp-bpf-helpers/baseline_policy.h +++ b/sandbox/linux/seccomp-bpf-helpers/baseline_policy.h @@ -18,11 +18,13 @@ class SandboxBPFPolicy; // that reduces the Linux kernel's attack surface. Given its nature, it doesn't // have a clear semantics and is mostly "implementation-defined". // -// This returns an object that implements the SandboxBPFPolicy interface with -// a "baseline" policy within Chromium. +// This class implements the SandboxBPFPolicy interface with a "baseline" +// policy for us within Chromium. // The "baseline" policy is somewhat arbitrary. All Chromium policies are an // alteration of it, and it represents a reasonable common ground to run most // code in a sandboxed environment. +// A baseline policy is only valid for the process for which this object was +// instantiated (so do not fork() and use it in a child). class SANDBOX_EXPORT BaselinePolicy : public SandboxBPFPolicy { public: BaselinePolicy(); @@ -36,6 +38,7 @@ class SANDBOX_EXPORT BaselinePolicy : public SandboxBPFPolicy { private: int fs_denied_errno_; + pid_t current_pid_; DISALLOW_COPY_AND_ASSIGN(BaselinePolicy); }; diff --git a/sandbox/linux/seccomp-bpf-helpers/sigsys_handlers.cc b/sandbox/linux/seccomp-bpf-helpers/sigsys_handlers.cc index 47c9989..c4a6f92 100644 --- a/sandbox/linux/seccomp-bpf-helpers/sigsys_handlers.cc +++ b/sandbox/linux/seccomp-bpf-helpers/sigsys_handlers.cc @@ -17,6 +17,7 @@ #define SECCOMP_MESSAGE_CLONE_CONTENT "clone() failure" #define SECCOMP_MESSAGE_PRCTL_CONTENT "prctl() failure" #define SECCOMP_MESSAGE_IOCTL_CONTENT "ioctl() failure" +#define SECCOMP_MESSAGE_KILL_CONTENT "(tg)kill() failure" namespace { @@ -147,6 +148,22 @@ intptr_t SIGSYSIoctlFailure(const struct arch_seccomp_data& args, _exit(1); } +intptr_t SIGSYSKillFailure(const struct arch_seccomp_data& args, + void* /* aux */) { + static const char kSeccompKillError[] = + __FILE__":**CRASHING**:" SECCOMP_MESSAGE_KILL_CONTENT "\n"; + WriteToStdErr(kSeccompKillError, sizeof(kSeccompKillError) - 1); + // Make "request" volatile so that we can see it on the stack in a minidump. + volatile uint64_t pid = args.args[0]; + volatile char* addr = reinterpret_cast<volatile char*>(pid & 0xFFF); + *addr = '\0'; + // Hit the NULL page if this fails. + addr = reinterpret_cast<volatile char*>(pid & 0xFFF); + *addr = '\0'; + for (;;) + _exit(1); +} + const char* GetErrorMessageContentForTests() { return SECCOMP_MESSAGE_COMMON_CONTENT; } diff --git a/sandbox/linux/seccomp-bpf-helpers/sigsys_handlers.h b/sandbox/linux/seccomp-bpf-helpers/sigsys_handlers.h index b8f626a..fdfbb66 100644 --- a/sandbox/linux/seccomp-bpf-helpers/sigsys_handlers.h +++ b/sandbox/linux/seccomp-bpf-helpers/sigsys_handlers.h @@ -38,6 +38,9 @@ SANDBOX_EXPORT intptr_t // argument. SANDBOX_EXPORT intptr_t SIGSYSIoctlFailure(const struct arch_seccomp_data& args, void* aux); +// The crashing address will be (pid & 0xFFF), where pid is the first +// argument (and can be a tid). +intptr_t SIGSYSKillFailure(const struct arch_seccomp_data& args, void* aux); // Following four functions return substrings of error messages used // in the above four functions. They are useful in death tests. diff --git a/sandbox/linux/seccomp-bpf-helpers/syscall_parameters_restrictions.cc b/sandbox/linux/seccomp-bpf-helpers/syscall_parameters_restrictions.cc index 9b417ce..e0e1ddca 100644 --- a/sandbox/linux/seccomp-bpf-helpers/syscall_parameters_restrictions.cc +++ b/sandbox/linux/seccomp-bpf-helpers/syscall_parameters_restrictions.cc @@ -211,4 +211,20 @@ ErrorCode RestrictSocketcallCommand(SandboxBPF* sandbox) { } #endif +ErrorCode RestrictKillTarget(pid_t target_pid, SandboxBPF* sandbox, int sysno) { + switch (sysno) { + case __NR_kill: + case __NR_tgkill: + return sandbox->Cond(0, ErrorCode::TP_32BIT, ErrorCode::OP_EQUAL, + target_pid, + ErrorCode(ErrorCode::ERR_ALLOWED), + sandbox->Trap(SIGSYSKillFailure, NULL)); + case __NR_tkill: + return sandbox->Trap(SIGSYSKillFailure, NULL); + default: + NOTREACHED(); + return sandbox->Trap(CrashSIGSYS_Handler, NULL); + } +} + } // namespace sandbox. diff --git a/sandbox/linux/seccomp-bpf-helpers/syscall_parameters_restrictions.h b/sandbox/linux/seccomp-bpf-helpers/syscall_parameters_restrictions.h index aa1e0d1..5283b49 100644 --- a/sandbox/linux/seccomp-bpf-helpers/syscall_parameters_restrictions.h +++ b/sandbox/linux/seccomp-bpf-helpers/syscall_parameters_restrictions.h @@ -5,6 +5,8 @@ #ifndef SANDBOX_LINUX_SECCOMP_BPF_HELPERS_SYSCALL_PARAMETERS_RESTRICTIONS_H_ #define SANDBOX_LINUX_SECCOMP_BPF_HELPERS_SYSCALL_PARAMETERS_RESTRICTIONS_H_ +#include <unistd.h> + #include "build/build_config.h" #include "sandbox/linux/sandbox_export.h" @@ -55,6 +57,11 @@ SANDBOX_EXPORT ErrorCode RestrictFcntlCommands(SandboxBPF* sandbox); SANDBOX_EXPORT ErrorCode RestrictSocketcallCommand(SandboxBPF* sandbox); #endif +// Restrict |sysno| (which must be kill, tkill or tgkill) by allowing tgkill or +// kill iff the first parameter is |target_pid|, crashing otherwise or if +// |sysno| is tkill. +ErrorCode RestrictKillTarget(pid_t target_pid, SandboxBPF* sandbox, int sysno); + } // namespace sandbox. #endif // SANDBOX_LINUX_SECCOMP_BPF_HELPERS_SYSCALL_PARAMETERS_RESTRICTIONS_H_ diff --git a/sandbox/linux/seccomp-bpf-helpers/syscall_sets.cc b/sandbox/linux/seccomp-bpf-helpers/syscall_sets.cc index 032f6c3..792807a 100644 --- a/sandbox/linux/seccomp-bpf-helpers/syscall_sets.cc +++ b/sandbox/linux/seccomp-bpf-helpers/syscall_sets.cc @@ -14,12 +14,11 @@ namespace sandbox { // The implicitly defined sets form a partition of the sets of // system calls. -// TODO(jln) we need to restrict the first parameter! bool SyscallSets::IsKill(int sysno) { switch (sysno) { case __NR_kill: - case __NR_tkill: case __NR_tgkill: + case __NR_tkill: // Deprecated. return true; default: return false; |