Chromium Code Reviews| Index: sandbox/linux/services/credentials.cc |
| diff --git a/sandbox/linux/services/credentials.cc b/sandbox/linux/services/credentials.cc |
| index 6f84a66b7a60f2877a7dc2d85ab7a1d31983c27b..4e814552a8a63d834d93bf536de2bc1e265a3293 100644 |
| --- a/sandbox/linux/services/credentials.cc |
| +++ b/sandbox/linux/services/credentials.cc |
| @@ -7,7 +7,6 @@ |
| #include <errno.h> |
| #include <signal.h> |
| #include <stdio.h> |
| -#include <sys/capability.h> |
| #include <sys/syscall.h> |
| #include <sys/types.h> |
| #include <sys/wait.h> |
| @@ -27,6 +26,7 @@ |
| #include "sandbox/linux/services/proc_util.h" |
| #include "sandbox/linux/services/syscall_wrappers.h" |
| #include "sandbox/linux/services/thread_helpers.h" |
| +#include "sandbox/linux/system_headers/capability.h" |
| namespace sandbox { |
| @@ -34,26 +34,6 @@ namespace { |
| bool IsRunningOnValgrind() { return RUNNING_ON_VALGRIND; } |
| -struct CapFreeDeleter { |
| - inline void operator()(cap_t cap) const { |
| - int ret = cap_free(cap); |
| - CHECK_EQ(0, ret); |
| - } |
| -}; |
| - |
| -// Wrapper to manage libcap2's cap_t type. |
| -typedef scoped_ptr<typeof(*((cap_t)0)), CapFreeDeleter> ScopedCap; |
| - |
| -struct CapTextFreeDeleter { |
| - inline void operator()(char* cap_text) const { |
| - int ret = cap_free(cap_text); |
| - CHECK_EQ(0, ret); |
| - } |
| -}; |
| - |
| -// Wrapper to manage the result from libcap2's cap_from_text(). |
| -typedef scoped_ptr<char, CapTextFreeDeleter> ScopedCapText; |
| - |
| // Checks that the set of RES-uids and the set of RES-gids have |
| // one element each and return that element in |resuid| and |resgid| |
| // respectively. It's ok to pass NULL as one or both of the ids. |
| @@ -133,18 +113,11 @@ void CheckCloneNewUserErrno(int error) { |
| } // namespace. |
| bool Credentials::DropAllCapabilities(int proc_fd) { |
| - DCHECK_LE(0, proc_fd); |
| -#if !defined(THREAD_SANITIZER) |
| - // With TSAN, accept to break the security model as it is a testing |
| - // configuration. |
| - CHECK(ThreadHelpers::IsSingleThreaded(proc_fd)); |
| -#endif |
| + if (!SetCapabilities(proc_fd, std::vector<int>())) { |
| + return false; |
| + } |
| - ScopedCap cap(cap_init()); |
| - CHECK(cap); |
| - PCHECK(0 == cap_set_proc(cap.get())); |
| CHECK(!HasAnyCapability()); |
| - // We never let this function fail. |
| return true; |
| } |
| @@ -153,20 +126,62 @@ bool Credentials::DropAllCapabilities() { |
| return Credentials::DropAllCapabilities(proc_fd.get()); |
| } |
| +// static |
| +bool Credentials::SetCapabilities(int proc_fd, |
| + const std::vector<int>& caps) { |
| + DCHECK_LE(0, proc_fd); |
| + |
| +#if !defined(THREAD_SANITIZER) |
| + // With TSAN, accept to break the security model as it is a testing |
| + // configuration. |
| + CHECK(ThreadHelpers::IsSingleThreaded(proc_fd)); |
| +#endif |
| + |
| + cap_hdr hdr; |
| + hdr.version = _LINUX_CAPABILITY_VERSION_3; |
| + cap_data data[_LINUX_CAPABILITY_U32S_3]; |
|
jln (very slow on Chromium)
2015/03/12 19:24:15
Even here I would use "struct cap_data", given tha
rickyz (no longer on Chrome)
2015/03/12 23:36:01
Done.
|
| + |
| + // Initially, cap has no capability flags set. Enable the effective and |
| + // permitted flags only for the requested capabilities. |
| + for (const int cap : caps) { |
| + DCHECK(cap >= 0 && cap < CAP_LAST_CAP); |
| + data[CAP_TO_INDEX(cap)].effective |= CAP_TO_MASK(cap); |
| + data[CAP_TO_INDEX(cap)].permitted |= CAP_TO_MASK(cap); |
| + } |
| + |
| + return sys_capset(&hdr, data) == 0; |
| +} |
| + |
| bool Credentials::HasAnyCapability() { |
| - ScopedCap current_cap(cap_get_proc()); |
| - CHECK(current_cap); |
| - ScopedCap empty_cap(cap_init()); |
| - CHECK(empty_cap); |
| - return cap_compare(current_cap.get(), empty_cap.get()) != 0; |
| + cap_hdr hdr; |
| + hdr.version = _LINUX_CAPABILITY_VERSION_3; |
| + cap_data data[_LINUX_CAPABILITY_U32S_3]; |
| + |
| + PCHECK(sys_capget(&hdr, data) == 0); |
| + |
| + for (size_t i = 0; i < arraysize(data); ++i) { |
| + if (data[i].effective || data[i].permitted || data[i].inheritable) { |
| + return true; |
| + } |
| + } |
| + |
| + return false; |
| } |
| -scoped_ptr<std::string> Credentials::GetCurrentCapString() { |
| - ScopedCap current_cap(cap_get_proc()); |
| - CHECK(current_cap); |
| - ScopedCapText cap_text(cap_to_text(current_cap.get(), NULL)); |
| - CHECK(cap_text); |
| - return scoped_ptr<std::string> (new std::string(cap_text.get())); |
| +bool Credentials::HasCapability(int cap) { |
| + DCHECK(cap >= 0 && cap < CAP_LAST_CAP); |
| + cap_hdr hdr; |
| + hdr.version = _LINUX_CAPABILITY_VERSION_3; |
| + cap_data data[_LINUX_CAPABILITY_U32S_3]; |
| + |
| + PCHECK(sys_capget(&hdr, data) == 0); |
| + |
| + const size_t index = CAP_TO_INDEX(cap); |
| + const uint32_t mask = CAP_TO_MASK(cap); |
| + |
| + return (data[index].effective | data[index].permitted | |
| + data[index].inheritable) & |
|
jln (very slow on Chromium)
2015/03/12 19:24:14
conidering .inheritable doesn't match the document
rickyz (no longer on Chrome)
2015/03/12 23:36:01
Done.
|
| + mask; |
| } |
| // static |