Index: sandbox/linux/services/credentials_unittest.cc |
diff --git a/sandbox/linux/services/credentials_unittest.cc b/sandbox/linux/services/credentials_unittest.cc |
index 2884e740afef10e3aca7daf1b7cafa1f893bc118..db19f6fee561073c1dc7a0f0ba7dfc29b91abd65 100644 |
--- a/sandbox/linux/services/credentials_unittest.cc |
+++ b/sandbox/linux/services/credentials_unittest.cc |
@@ -7,16 +7,21 @@ |
#include <errno.h> |
#include <fcntl.h> |
#include <stdio.h> |
+#include <sys/capability.h> |
#include <sys/stat.h> |
#include <sys/types.h> |
#include <unistd.h> |
+#include <vector> |
+ |
#include "base/files/file_path.h" |
#include "base/files/file_util.h" |
#include "base/files/scoped_file.h" |
#include "base/logging.h" |
#include "base/memory/scoped_ptr.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 "testing/gtest/include/gtest/gtest.h" |
@@ -24,6 +29,16 @@ namespace sandbox { |
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() { |
char current_dir[PATH_MAX]; |
char* cwd = getcwd(current_dir, sizeof(current_dir)); |
@@ -48,12 +63,6 @@ SANDBOX_TEST(Credentials, DropAllCaps) { |
CHECK(!Credentials::HasAnyCapability()); |
} |
-SANDBOX_TEST(Credentials, GetCurrentCapString) { |
- CHECK(Credentials::DropAllCapabilities()); |
- const char kNoCapabilityText[] = "="; |
- CHECK(*Credentials::GetCurrentCapString() == kNoCapabilityText); |
-} |
- |
SANDBOX_TEST(Credentials, MoveToNewUserNS) { |
CHECK(Credentials::DropAllCapabilities()); |
bool moved_to_new_ns = Credentials::MoveToNewUserNS(); |
@@ -161,6 +170,70 @@ SANDBOX_TEST(Credentials, DISABLE_ON_ASAN(CannotRegainPrivileges)) { |
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 sandbox. |