Commit 966f039d authored by rickyz's avatar rickyz Committed by Commit bot

Remove sys/capability.h dependency from credentials.cc.

Also adds SetCapabilities and HasCapability functions for more fine-grained control over capabilities.
BUG=

Review URL: https://codereview.chromium.org/997463002

Cr-Commit-Position: refs/heads/master@{#320878}
parent c9266252
...@@ -3,7 +3,6 @@ libasound2 (>= 1.0.23) ...@@ -3,7 +3,6 @@ libasound2 (>= 1.0.23)
libatk1.0-0 (>= 1.12.4) libatk1.0-0 (>= 1.12.4)
libc6 (>= 2.11) libc6 (>= 2.11)
libcairo2 (>= 1.6.0) libcairo2 (>= 1.6.0)
libcap2 (>= 2.10)
libcups2 (>= 1.4.0) libcups2 (>= 1.4.0)
libdbus-1-3 (>= 1.2.14) libdbus-1-3 (>= 1.2.14)
libexpat1 (>= 1.95.8) libexpat1 (>= 1.95.8)
......
...@@ -3,7 +3,6 @@ libasound2 (>= 1.0.23) ...@@ -3,7 +3,6 @@ libasound2 (>= 1.0.23)
libatk1.0-0 (>= 1.12.4) libatk1.0-0 (>= 1.12.4)
libc6 (>= 2.11) libc6 (>= 2.11)
libcairo2 (>= 1.6.0) libcairo2 (>= 1.6.0)
libcap2 (>= 2.10)
libcups2 (>= 1.4.0) libcups2 (>= 1.4.0)
libdbus-1-3 (>= 1.2.14) libdbus-1-3 (>= 1.2.14)
libexpat1 (>= 1.95.8) libexpat1 (>= 1.95.8)
......
...@@ -4,7 +4,6 @@ ld-linux.so.2(GLIBC_2.3) ...@@ -4,7 +4,6 @@ ld-linux.so.2(GLIBC_2.3)
libasound.so.2 libasound.so.2
libatk-1.0.so.0 libatk-1.0.so.0
libcairo.so.2 libcairo.so.2
libcap.so.2
libc.so.6 libc.so.6
libc.so.6(GLIBC_2.0) libc.so.6(GLIBC_2.0)
libc.so.6(GLIBC_2.1) libc.so.6(GLIBC_2.1)
......
...@@ -4,7 +4,6 @@ ld-linux-x86-64.so.2(GLIBC_2.3)(64bit) ...@@ -4,7 +4,6 @@ ld-linux-x86-64.so.2(GLIBC_2.3)(64bit)
libasound.so.2()(64bit) libasound.so.2()(64bit)
libatk-1.0.so.0()(64bit) libatk-1.0.so.0()(64bit)
libcairo.so.2()(64bit) libcairo.so.2()(64bit)
libcap.so.2()(64bit)
libc.so.6()(64bit) libc.so.6()(64bit)
libc.so.6(GLIBC_2.11)(64bit) libc.so.6(GLIBC_2.11)(64bit)
libc.so.6(GLIBC_2.2.5)(64bit) libc.so.6(GLIBC_2.2.5)(64bit)
......
...@@ -126,6 +126,9 @@ source_set("sandbox_linux_unittests_sources") { ...@@ -126,6 +126,9 @@ source_set("sandbox_linux_unittests_sources") {
"services/namespace_sandbox_unittest.cc", "services/namespace_sandbox_unittest.cc",
"services/namespace_utils_unittest.cc", "services/namespace_utils_unittest.cc",
] ]
# For credentials_unittest.cc
configs += [ "//build/config/linux:libcap" ]
} }
} }
...@@ -265,6 +268,10 @@ component("sandbox_services") { ...@@ -265,6 +268,10 @@ component("sandbox_services") {
defines = [ "SANDBOX_IMPLEMENTATION" ] defines = [ "SANDBOX_IMPLEMENTATION" ]
deps = [
"//base",
]
if (compile_credentials) { if (compile_credentials) {
sources += [ sources += [
"services/credentials.cc", "services/credentials.cc",
...@@ -275,13 +282,8 @@ component("sandbox_services") { ...@@ -275,13 +282,8 @@ component("sandbox_services") {
"services/namespace_utils.h", "services/namespace_utils.h",
] ]
# For capabilities.cc. deps += [ ":sandbox_services_headers" ]
configs += [ "//build/config/linux:libcap" ]
} }
deps = [
"//base",
]
} }
source_set("sandbox_services_headers") { source_set("sandbox_services_headers") {
......
...@@ -266,8 +266,8 @@ ...@@ -266,8 +266,8 @@
'services/namespace_utils.h', 'services/namespace_utils.h',
], ],
'dependencies': [ 'dependencies': [
# for capabilities.cc. # for capability.h.
'../build/linux/system.gyp:libcap', 'sandbox_services_headers',
], ],
}], }],
], ],
...@@ -286,6 +286,7 @@ ...@@ -286,6 +286,7 @@
'system_headers/android_ucontext.h', 'system_headers/android_ucontext.h',
'system_headers/arm64_linux_syscalls.h', 'system_headers/arm64_linux_syscalls.h',
'system_headers/arm_linux_syscalls.h', 'system_headers/arm_linux_syscalls.h',
'system_headers/capability.h',
'system_headers/linux_seccomp.h', 'system_headers/linux_seccomp.h',
'system_headers/linux_syscalls.h', 'system_headers/linux_syscalls.h',
'system_headers/mips_linux_syscalls.h', 'system_headers/mips_linux_syscalls.h',
......
...@@ -62,6 +62,9 @@ ...@@ -62,6 +62,9 @@
'services/namespace_sandbox_unittest.cc', 'services/namespace_sandbox_unittest.cc',
'services/namespace_utils_unittest.cc', 'services/namespace_utils_unittest.cc',
], ],
'dependencies': [
'../build/linux/system.gyp:libcap'
],
}], }],
], ],
} }
...@@ -7,7 +7,6 @@ ...@@ -7,7 +7,6 @@
#include <errno.h> #include <errno.h>
#include <signal.h> #include <signal.h>
#include <stdio.h> #include <stdio.h>
#include <sys/capability.h>
#include <sys/syscall.h> #include <sys/syscall.h>
#include <sys/types.h> #include <sys/types.h>
#include <sys/wait.h> #include <sys/wait.h>
...@@ -27,6 +26,7 @@ ...@@ -27,6 +26,7 @@
#include "sandbox/linux/services/proc_util.h" #include "sandbox/linux/services/proc_util.h"
#include "sandbox/linux/services/syscall_wrappers.h" #include "sandbox/linux/services/syscall_wrappers.h"
#include "sandbox/linux/services/thread_helpers.h" #include "sandbox/linux/services/thread_helpers.h"
#include "sandbox/linux/system_headers/capability.h"
namespace sandbox { namespace sandbox {
...@@ -34,26 +34,6 @@ namespace { ...@@ -34,26 +34,6 @@ namespace {
bool IsRunningOnValgrind() { return RUNNING_ON_VALGRIND; } 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 // 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| // 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. // respectively. It's ok to pass NULL as one or both of the ids.
...@@ -130,21 +110,26 @@ void CheckCloneNewUserErrno(int error) { ...@@ -130,21 +110,26 @@ void CheckCloneNewUserErrno(int error) {
error == ENOSYS); error == ENOSYS);
} }
// Converts a LinuxCapability to the corresponding Linux CAP_XXX value.
int LinuxCapabilityToKernelValue(LinuxCapability cap) {
switch (cap) {
case LinuxCapability::kCapSysChroot:
return CAP_SYS_CHROOT;
case LinuxCapability::kCapSysAdmin:
return CAP_SYS_ADMIN;
}
LOG(FATAL) << "Invalid LinuxCapability: " << static_cast<int>(cap);
}
} // namespace. } // namespace.
bool Credentials::DropAllCapabilities(int proc_fd) { bool Credentials::DropAllCapabilities(int proc_fd) {
DCHECK_LE(0, proc_fd); if (!SetCapabilities(proc_fd, std::vector<LinuxCapability>())) {
#if !defined(THREAD_SANITIZER) return false;
// With TSAN, accept to break the security model as it is a testing }
// configuration.
CHECK(ThreadHelpers::IsSingleThreaded(proc_fd));
#endif
ScopedCap cap(cap_init());
CHECK(cap);
PCHECK(0 == cap_set_proc(cap.get()));
CHECK(!HasAnyCapability()); CHECK(!HasAnyCapability());
// We never let this function fail.
return true; return true;
} }
...@@ -153,20 +138,64 @@ bool Credentials::DropAllCapabilities() { ...@@ -153,20 +138,64 @@ bool Credentials::DropAllCapabilities() {
return Credentials::DropAllCapabilities(proc_fd.get()); return Credentials::DropAllCapabilities(proc_fd.get());
} }
// static
bool Credentials::SetCapabilities(int proc_fd,
const std::vector<LinuxCapability>& 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
struct cap_hdr hdr = {};
hdr.version = _LINUX_CAPABILITY_VERSION_3;
struct cap_data data[_LINUX_CAPABILITY_U32S_3] = {{}};
// Initially, cap has no capability flags set. Enable the effective and
// permitted flags only for the requested capabilities.
for (const LinuxCapability cap : caps) {
const int cap_num = LinuxCapabilityToKernelValue(cap);
const size_t index = CAP_TO_INDEX(cap_num);
const uint32_t mask = CAP_TO_MASK(cap_num);
data[index].effective |= mask;
data[index].permitted |= mask;
}
return sys_capset(&hdr, data) == 0;
}
bool Credentials::HasAnyCapability() { bool Credentials::HasAnyCapability() {
ScopedCap current_cap(cap_get_proc()); struct cap_hdr hdr = {};
CHECK(current_cap); hdr.version = _LINUX_CAPABILITY_VERSION_3;
ScopedCap empty_cap(cap_init()); struct cap_data data[_LINUX_CAPABILITY_U32S_3] = {{}};
CHECK(empty_cap);
return cap_compare(current_cap.get(), empty_cap.get()) != 0; 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() { bool Credentials::HasCapability(LinuxCapability cap) {
ScopedCap current_cap(cap_get_proc()); struct cap_hdr hdr = {};
CHECK(current_cap); hdr.version = _LINUX_CAPABILITY_VERSION_3;
ScopedCapText cap_text(cap_to_text(current_cap.get(), NULL)); struct cap_data data[_LINUX_CAPABILITY_U32S_3] = {{}};
CHECK(cap_text);
return scoped_ptr<std::string> (new std::string(cap_text.get())); PCHECK(sys_capget(&hdr, data) == 0);
const int cap_num = LinuxCapabilityToKernelValue(cap);
const size_t index = CAP_TO_INDEX(cap_num);
const uint32_t mask = CAP_TO_MASK(cap_num);
return (data[index].effective | data[index].permitted |
data[index].inheritable) &
mask;
} }
// static // static
......
...@@ -12,21 +12,30 @@ ...@@ -12,21 +12,30 @@
#endif // defined(OS_ANDROID). #endif // defined(OS_ANDROID).
#include <string> #include <string>
#include <vector>
#include "base/basictypes.h" #include "base/basictypes.h"
#include "base/compiler_specific.h" #include "base/compiler_specific.h"
#include "base/memory/scoped_ptr.h" #include "base/memory/scoped_ptr.h"
#include "sandbox/linux/system_headers/capability.h"
#include "sandbox/sandbox_export.h" #include "sandbox/sandbox_export.h"
namespace sandbox { namespace sandbox {
// For brevity, we only expose enums for the subset of capabilities we use.
// This can be expanded as the need arises.
enum class LinuxCapability {
kCapSysChroot,
kCapSysAdmin,
};
// This class should be used to manipulate the current process' credentials. // This class should be used to manipulate the current process' credentials.
// It is currently a stub used to manipulate POSIX.1e capabilities as // It is currently a stub used to manipulate POSIX.1e capabilities as
// implemented by the Linux kernel. // implemented by the Linux kernel.
class SANDBOX_EXPORT Credentials { class SANDBOX_EXPORT Credentials {
public: public:
// Drop all capabilities in the effective, inheritable and permitted sets for // Drop all capabilities in the effective, inheritable and permitted sets for
// the current process. For security reasons, since capabilities are // the current thread. For security reasons, since capabilities are
// per-thread, the caller is responsible for ensuring it is single-threaded // per-thread, the caller is responsible for ensuring it is single-threaded
// when calling this API. // when calling this API.
// |proc_fd| must be a file descriptor to /proc/ and remains owned by // |proc_fd| must be a file descriptor to /proc/ and remains owned by
...@@ -34,14 +43,19 @@ class SANDBOX_EXPORT Credentials { ...@@ -34,14 +43,19 @@ class SANDBOX_EXPORT Credentials {
static bool DropAllCapabilities(int proc_fd) WARN_UNUSED_RESULT; static bool DropAllCapabilities(int proc_fd) WARN_UNUSED_RESULT;
// A similar API which assumes that it can open /proc/self/ by itself. // A similar API which assumes that it can open /proc/self/ by itself.
static bool DropAllCapabilities() WARN_UNUSED_RESULT; static bool DropAllCapabilities() WARN_UNUSED_RESULT;
// Sets the effective and permitted capability sets for the current thread to
// the list of capabiltiies in |caps|. All other capability flags are cleared.
static bool SetCapabilities(int proc_fd,
const std::vector<LinuxCapability>& caps)
WARN_UNUSED_RESULT;
// Returns true if the current thread has either the effective, permitted, or
// inheritable flag set for the given capability.
static bool HasCapability(LinuxCapability cap);
// Return true iff there is any capability in any of the capabilities sets // Return true iff there is any capability in any of the capabilities sets
// of the current process. // of the current thread.
static bool HasAnyCapability(); static bool HasAnyCapability();
// Returns the capabilities of the current process in textual form, as
// documented in libcap2's cap_to_text(3). This is mostly useful for
// debugging and tests.
static scoped_ptr<std::string> GetCurrentCapString();
// Returns whether the kernel supports CLONE_NEWUSER and whether it would be // Returns whether the kernel supports CLONE_NEWUSER and whether it would be
// possible to immediately move to a new user namespace. There is no point // possible to immediately move to a new user namespace. There is no point
......
...@@ -7,16 +7,21 @@ ...@@ -7,16 +7,21 @@
#include <errno.h> #include <errno.h>
#include <fcntl.h> #include <fcntl.h>
#include <stdio.h> #include <stdio.h>
#include <sys/capability.h>
#include <sys/stat.h> #include <sys/stat.h>
#include <sys/types.h> #include <sys/types.h>
#include <unistd.h> #include <unistd.h>
#include <vector>
#include "base/files/file_path.h" #include "base/files/file_path.h"
#include "base/files/file_util.h" #include "base/files/file_util.h"
#include "base/files/scoped_file.h" #include "base/files/scoped_file.h"
#include "base/logging.h" #include "base/logging.h"
#include "base/memory/scoped_ptr.h" #include "base/memory/scoped_ptr.h"
#include "sandbox/linux/services/proc_util.h" #include "sandbox/linux/services/proc_util.h"
#include "sandbox/linux/services/syscall_wrappers.h"
#include "sandbox/linux/system_headers/capability.h"
#include "sandbox/linux/tests/unit_tests.h" #include "sandbox/linux/tests/unit_tests.h"
#include "testing/gtest/include/gtest/gtest.h" #include "testing/gtest/include/gtest/gtest.h"
...@@ -24,6 +29,16 @@ namespace sandbox { ...@@ -24,6 +29,16 @@ namespace sandbox {
namespace { namespace {
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;
bool WorkingDirectoryIsRoot() { bool WorkingDirectoryIsRoot() {
char current_dir[PATH_MAX]; char current_dir[PATH_MAX];
char* cwd = getcwd(current_dir, sizeof(current_dir)); char* cwd = getcwd(current_dir, sizeof(current_dir));
...@@ -48,12 +63,6 @@ SANDBOX_TEST(Credentials, DropAllCaps) { ...@@ -48,12 +63,6 @@ SANDBOX_TEST(Credentials, DropAllCaps) {
CHECK(!Credentials::HasAnyCapability()); CHECK(!Credentials::HasAnyCapability());
} }
SANDBOX_TEST(Credentials, GetCurrentCapString) {
CHECK(Credentials::DropAllCapabilities());
const char kNoCapabilityText[] = "=";
CHECK(*Credentials::GetCurrentCapString() == kNoCapabilityText);
}
SANDBOX_TEST(Credentials, MoveToNewUserNS) { SANDBOX_TEST(Credentials, MoveToNewUserNS) {
CHECK(Credentials::DropAllCapabilities()); CHECK(Credentials::DropAllCapabilities());
bool moved_to_new_ns = Credentials::MoveToNewUserNS(); bool moved_to_new_ns = Credentials::MoveToNewUserNS();
...@@ -161,6 +170,70 @@ SANDBOX_TEST(Credentials, DISABLE_ON_ASAN(CannotRegainPrivileges)) { ...@@ -161,6 +170,70 @@ SANDBOX_TEST(Credentials, DISABLE_ON_ASAN(CannotRegainPrivileges)) {
CHECK(!Credentials::MoveToNewUserNS()); CHECK(!Credentials::MoveToNewUserNS());
} }
SANDBOX_TEST(Credentials, SetCapabilities) {
// Probably missing kernel support.
if (!Credentials::MoveToNewUserNS())
return;
base::ScopedFD proc_fd(ProcUtil::OpenProc());
CHECK(Credentials::HasCapability(LinuxCapability::kCapSysAdmin));
CHECK(Credentials::HasCapability(LinuxCapability::kCapSysChroot));
const std::vector<LinuxCapability> caps = {LinuxCapability::kCapSysChroot};
CHECK(Credentials::SetCapabilities(proc_fd.get(), caps));
CHECK(!Credentials::HasCapability(LinuxCapability::kCapSysAdmin));
CHECK(Credentials::HasCapability(LinuxCapability::kCapSysChroot));
const std::vector<LinuxCapability> no_caps;
CHECK(Credentials::SetCapabilities(proc_fd.get(), no_caps));
CHECK(!Credentials::HasAnyCapability());
}
SANDBOX_TEST(Credentials, SetCapabilitiesAndChroot) {
// Probably missing kernel support.
if (!Credentials::MoveToNewUserNS())
return;
base::ScopedFD proc_fd(ProcUtil::OpenProc());
CHECK(Credentials::HasCapability(LinuxCapability::kCapSysChroot));
PCHECK(chroot("/") == 0);
const std::vector<LinuxCapability> caps = {LinuxCapability::kCapSysChroot};
CHECK(Credentials::SetCapabilities(proc_fd.get(), caps));
PCHECK(chroot("/") == 0);
CHECK(Credentials::DropAllCapabilities());
PCHECK(chroot("/") == -1 && errno == EPERM);
}
SANDBOX_TEST(Credentials, SetCapabilitiesMatchesLibCap2) {
// Probably missing kernel support.
if (!Credentials::MoveToNewUserNS())
return;
base::ScopedFD proc_fd(ProcUtil::OpenProc());
const std::vector<LinuxCapability> caps = {LinuxCapability::kCapSysChroot};
CHECK(Credentials::SetCapabilities(proc_fd.get(), caps));
ScopedCap actual_cap(cap_get_proc());
PCHECK(actual_cap != nullptr);
ScopedCap expected_cap(cap_init());
PCHECK(expected_cap != nullptr);
const cap_value_t allowed_cap = CAP_SYS_CHROOT;
for (const cap_flag_t flag : {CAP_EFFECTIVE, CAP_PERMITTED}) {
PCHECK(cap_set_flag(expected_cap.get(), flag, 1, &allowed_cap, CAP_SET) ==
0);
}
CHECK_EQ(0, cap_compare(expected_cap.get(), actual_cap.get()));
}
} // namespace. } // namespace.
} // namespace sandbox. } // namespace sandbox.
...@@ -77,4 +77,12 @@ int sys_prlimit64(pid_t pid, ...@@ -77,4 +77,12 @@ int sys_prlimit64(pid_t pid,
return syscall(__NR_prlimit64, pid, resource, new_limit, old_limit); return syscall(__NR_prlimit64, pid, resource, new_limit, old_limit);
} }
int sys_capget(cap_hdr* hdrp, cap_data* datap) {
return syscall(__NR_capget, hdrp, datap);
}
int sys_capset(cap_hdr* hdrp, const cap_data* datap) {
return syscall(__NR_capset, hdrp, datap);
}
} // namespace sandbox } // namespace sandbox
...@@ -5,12 +5,15 @@ ...@@ -5,12 +5,15 @@
#ifndef SANDBOX_LINUX_SERVICES_SYSCALL_WRAPPERS_H_ #ifndef SANDBOX_LINUX_SERVICES_SYSCALL_WRAPPERS_H_
#define SANDBOX_LINUX_SERVICES_SYSCALL_WRAPPERS_H_ #define SANDBOX_LINUX_SERVICES_SYSCALL_WRAPPERS_H_
#include <stdint.h>
#include <sys/types.h> #include <sys/types.h>
#include "sandbox/sandbox_export.h" #include "sandbox/sandbox_export.h"
struct sock_fprog; struct sock_fprog;
struct rlimit64; struct rlimit64;
struct cap_hdr;
struct cap_data;
namespace sandbox { namespace sandbox {
...@@ -47,6 +50,12 @@ SANDBOX_EXPORT int sys_prlimit64(pid_t pid, ...@@ -47,6 +50,12 @@ SANDBOX_EXPORT int sys_prlimit64(pid_t pid,
const struct rlimit64* new_limit, const struct rlimit64* new_limit,
struct rlimit64* old_limit); struct rlimit64* old_limit);
// Some libcs do not expose capget/capset wrappers. We want to use these
// directly in order to avoid pulling in libcap2.
SANDBOX_EXPORT int sys_capget(struct cap_hdr* hdrp, struct cap_data* datap);
SANDBOX_EXPORT int sys_capset(struct cap_hdr* hdrp,
const struct cap_data* datap);
} // namespace sandbox } // namespace sandbox
#endif // SANDBOX_LINUX_SERVICES_SYSCALL_WRAPPERS_H_ #endif // SANDBOX_LINUX_SERVICES_SYSCALL_WRAPPERS_H_
// Copyright 2015 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.
#ifndef SANDBOX_LINUX_SYSTEM_HEADERS_LINUX_CAPABILITY_H_
#define SANDBOX_LINUX_SYSTEM_HEADERS_LINUX_CAPABILITY_H_
#include <stdint.h>
// The following macros are taken from linux/capability.h.
// We only support capability version 3, which was introduced in Linux 2.6.26.
#ifndef _LINUX_CAPABILITY_VERSION_3
#define _LINUX_CAPABILITY_VERSION_3 0x20080522
#endif
#ifndef _LINUX_CAPABILITY_U32S_3
#define _LINUX_CAPABILITY_U32S_3 2
#endif
#ifndef CAP_TO_INDEX
#define CAP_TO_INDEX(x) ((x) >> 5) // 1 << 5 == bits in __u32
#endif
#ifndef CAP_TO_MASK
#define CAP_TO_MASK(x) (1 << ((x) & 31)) // mask for indexed __u32
#endif
#ifndef CAP_SYS_CHROOT
#define CAP_SYS_CHROOT 18
#endif
#ifndef CAP_SYS_ADMIN
#define CAP_SYS_ADMIN 21
#endif
struct cap_hdr {
uint32_t version;
int pid;
};
struct cap_data {
uint32_t effective;
uint32_t permitted;
uint32_t inheritable;
};
#endif // SANDBOX_LINUX_SYSTEM_HEADERS_LINUX_CAPABILITY_H_
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment