Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(973)

Unified Diff: sandbox/linux/services/credentials.cc

Issue 885443002: Roll Chrome into Mojo. (Closed) Base URL: https://github.com/domokit/mojo.git@master
Patch Set: Rebase to ToT mojo Created 5 years, 11 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
« no previous file with comments | « sandbox/linux/services/credentials.h ('k') | sandbox/linux/services/credentials_unittest.cc » ('j') | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: sandbox/linux/services/credentials.cc
diff --git a/sandbox/linux/services/credentials.cc b/sandbox/linux/services/credentials.cc
index 291c2cad4450e9a473281255cde6b72009c3852f..ce5eeda78ed177002b4bb4083d452e4fa6edcf2d 100644
--- a/sandbox/linux/services/credentials.cc
+++ b/sandbox/linux/services/credentials.cc
@@ -22,8 +22,11 @@
#include "base/process/launch.h"
#include "base/template_util.h"
#include "base/third_party/valgrind/valgrind.h"
+#include "sandbox/linux/services/namespace_utils.h"
#include "sandbox/linux/services/syscall_wrappers.h"
+namespace sandbox {
+
namespace {
bool IsRunningOnValgrind() { return RUNNING_ON_VALGRIND; }
@@ -48,39 +51,6 @@ struct CapTextFreeDeleter {
// Wrapper to manage the result from libcap2's cap_from_text().
typedef scoped_ptr<char, CapTextFreeDeleter> ScopedCapText;
-struct FILECloser {
- inline void operator()(FILE* f) const {
- DCHECK(f);
- PCHECK(0 == fclose(f));
- }
-};
-
-// Don't use ScopedFILE in base since it doesn't check fclose().
-// TODO(jln): fix base/.
-typedef scoped_ptr<FILE, FILECloser> ScopedFILE;
-
-static_assert((base::is_same<uid_t, gid_t>::value),
- "uid_t and gid_t should be the same type");
-// generic_id_t can be used for either uid_t or gid_t.
-typedef uid_t generic_id_t;
-
-// Write a uid or gid mapping from |id| to |id| in |map_file|.
-bool WriteToIdMapFile(const char* map_file, generic_id_t id) {
- ScopedFILE f(fopen(map_file, "w"));
- PCHECK(f);
- const uid_t inside_id = id;
- const uid_t outside_id = id;
- int num = fprintf(f.get(), "%d %d 1\n", inside_id, outside_id);
- if (num < 0) return false;
- // Manually call fflush() to catch permission failures.
- int ret = fflush(f.get());
- if (ret) {
- VLOG(1) << "Could not write to id map file";
- return false;
- }
- return true;
-}
-
// 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.
@@ -97,6 +67,17 @@ bool GetRESIds(uid_t* resuid, gid_t* resgid) {
return true;
}
+const int kExitSuccess = 0;
+
+int ChrootToSelfFdinfo(void*) {
+ RAW_CHECK(chroot("/proc/self/fdinfo/") == 0);
+
+ // CWD is essentially an implicit file descriptor, so be careful to not
+ // leave it behind.
+ RAW_CHECK(chdir("/") == 0);
+ _exit(kExitSuccess);
+}
+
// chroot() to an empty dir that is "safe". To be safe, it must not contain
// any subdirectory (chroot-ing there would allow a chroot escape) and it must
// be impossible to create an empty directory there.
@@ -108,25 +89,32 @@ bool GetRESIds(uid_t* resuid, gid_t* resgid) {
// 3. The process dies
// After (3) happens, the directory is not available anymore in /proc.
bool ChrootToSafeEmptyDir() {
- // We do not use a thread because when we are in a PID namespace, we cannot
- // easily get a handle to the /proc/tid directory for the thread (since /proc
- // may not be aware of the PID namespace). With a process, we can just use
- // /proc/self.
- pid_t pid = base::ForkWithFlags(SIGCHLD | CLONE_FS, nullptr, nullptr);
+ // We need to chroot to a fdinfo that is unique to a process and have that
+ // process die.
+ // 1. We don't want to simply fork() because duplicating the page tables is
+ // slow with a big address space.
+ // 2. We do not use a regular thread (that would unshare CLONE_FILES) because
+ // when we are in a PID namespace, we cannot easily get a handle to the
+ // /proc/tid directory for the thread (since /proc may not be aware of the
+ // PID namespace). With a process, we can just use /proc/self.
+ pid_t pid = -1;
+ char stack_buf[PTHREAD_STACK_MIN];
+#if defined(ARCH_CPU_X86_FAMILY) || defined(ARCH_CPU_ARM_FAMILY) || \
+ defined(ARCH_CPU_MIPS64_FAMILY) || defined(ARCH_CPU_MIPS_FAMILY)
+ // The stack grows downward.
+ void* stack = stack_buf + sizeof(stack_buf);
+#else
+#error "Unsupported architecture"
+#endif
+ pid = clone(ChrootToSelfFdinfo, stack,
+ CLONE_VM | CLONE_VFORK | CLONE_FS | SIGCHLD, nullptr, nullptr,
+ nullptr, nullptr);
PCHECK(pid != -1);
- if (pid == 0) {
- RAW_CHECK(chroot("/proc/self/fdinfo/") == 0);
-
- // CWD is essentially an implicit file descriptor, so be careful to not
- // leave it behind.
- RAW_CHECK(chdir("/") == 0);
- _exit(0);
- }
int status = -1;
PCHECK(HANDLE_EINTR(waitpid(pid, &status, 0)) == pid);
- return status == 0;
+ return kExitSuccess == status;
}
// CHECK() that an attempt to move to a new user namespace raised an expected
@@ -141,8 +129,6 @@ void CheckCloneNewUserErrno(int error) {
} // namespace.
-namespace sandbox {
-
bool Credentials::DropAllCapabilities() {
ScopedCap cap(cap_init());
CHECK(cap);
@@ -169,7 +155,7 @@ scoped_ptr<std::string> Credentials::GetCurrentCapString() {
}
// static
-bool Credentials::SupportsNewUserNS() {
+bool Credentials::CanCreateProcessInNewUserNS() {
// Valgrind will let clone(2) pass-through, but doesn't support unshare(),
// so always consider UserNS unsupported there.
if (IsRunningOnValgrind()) {
@@ -222,8 +208,8 @@ bool Credentials::MoveToNewUserNS() {
DCHECK(GetRESIds(NULL, NULL));
const char kGidMapFile[] = "/proc/self/gid_map";
const char kUidMapFile[] = "/proc/self/uid_map";
- CHECK(WriteToIdMapFile(kGidMapFile, gid));
- CHECK(WriteToIdMapFile(kUidMapFile, uid));
+ CHECK(NamespaceUtils::WriteToIdMapFile(kGidMapFile, gid));
+ CHECK(NamespaceUtils::WriteToIdMapFile(kUidMapFile, uid));
DCHECK(GetRESIds(NULL, NULL));
return true;
}
« no previous file with comments | « sandbox/linux/services/credentials.h ('k') | sandbox/linux/services/credentials_unittest.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698