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

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

Issue 2578483002: Namespace sandbox: add check for unprivileged use of CLONE_NEWUSER (Closed)
Patch Set: Created 4 years 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
Index: sandbox/linux/services/credentials.cc
diff --git a/sandbox/linux/services/credentials.cc b/sandbox/linux/services/credentials.cc
index 803af159704f632102a65c6cea4b962b5d17524f..5561f41f822f62b8eabed6215338b602b2467e72 100644
--- a/sandbox/linux/services/credentials.cc
+++ b/sandbox/linux/services/credentials.cc
@@ -150,6 +150,18 @@ int CapabilityToKernelValue(Credentials::Capability cap) {
return 0;
}
+void SetGidAndUidMaps(gid_t gid, uid_t uid) {
+ if (NamespaceUtils::KernelSupportsDenySetgroups()) {
+ PCHECK(NamespaceUtils::DenySetgroups());
+ }
+ DCHECK(GetRESIds(NULL, NULL));
+ const char kGidMapFile[] = "/proc/self/gid_map";
+ const char kUidMapFile[] = "/proc/self/uid_map";
+ PCHECK(NamespaceUtils::WriteToIdMapFile(kGidMapFile, gid));
+ PCHECK(NamespaceUtils::WriteToIdMapFile(kUidMapFile, uid));
+ DCHECK(GetRESIds(NULL, NULL));
+}
+
} // namespace.
// static
@@ -253,6 +265,12 @@ bool Credentials::CanCreateProcessInNewUserNS() {
return false;
#endif
+ uid_t uid;
+ gid_t gid;
+ if (!GetRESIds(&uid, &gid)) {
+ return false;
+ }
+
// This is roughly a fork().
const pid_t pid = sys_clone(CLONE_NEWUSER | SIGCHLD, 0, 0, 0, 0);
@@ -265,17 +283,29 @@ bool Credentials::CanCreateProcessInNewUserNS() {
// have disappeared. Make sure to not do anything in the child, as this is a
// fragile execution environment.
if (pid == 0) {
- _exit(kExitSuccess);
+ // unshare() requires the effective uid and gid to have a mapping in the
+ // parent namespace.
+ SetGidAndUidMaps(gid, uid);
+
+ // Make sure we drop CAP_SYS_ADMIN.
+ auto proc_fd = sandbox::ProcUtil::OpenProc();
+ CHECK(sandbox::Credentials::DropAllCapabilities(proc_fd.get()));
+
+ // Ensure we have unprivileged use of CLONE_NEWUSER. Debian
+ // Jessie explicitly forbids this case. See:
+ // add-sysctl-to-disallow-unprivileged-CLONE_NEWUSER-by-default.patch
+ int ret = sys_unshare(CLONE_NEWUSER);
mdempsky 2016/12/14 05:11:11 I would probably do: PCHECK(sys_unshare(CLONE
Tom (Use chromium acct) 2016/12/14 21:10:26 Done. But when I run this as root on Debian, I ge
+ _exit(!!ret);
}
// Always reap the child.
int status = -1;
PCHECK(HANDLE_EINTR(waitpid(pid, &status, 0)) == pid);
CHECK(WIFEXITED(status));
- CHECK_EQ(kExitSuccess, WEXITSTATUS(status));
- // clone(2) succeeded, we can use CLONE_NEWUSER.
- return true;
+ // clone(2) succeeded. Now return true only if the system grants
+ // unprivileged use of CLONE_NEWUSER as well.
+ return !status;
}
bool Credentials::MoveToNewUserNS() {
@@ -296,18 +326,9 @@ bool Credentials::MoveToNewUserNS() {
return false;
}
- if (NamespaceUtils::KernelSupportsDenySetgroups()) {
- PCHECK(NamespaceUtils::DenySetgroups());
- }
-
// The current {r,e,s}{u,g}id is now an overflow id (c.f.
// /proc/sys/kernel/overflowuid). Setup the uid and gid maps.
- DCHECK(GetRESIds(NULL, NULL));
- const char kGidMapFile[] = "/proc/self/gid_map";
- const char kUidMapFile[] = "/proc/self/uid_map";
- PCHECK(NamespaceUtils::WriteToIdMapFile(kGidMapFile, gid));
- PCHECK(NamespaceUtils::WriteToIdMapFile(kUidMapFile, uid));
- DCHECK(GetRESIds(NULL, NULL));
+ SetGidAndUidMaps(gid, uid);
return true;
}
« no previous file with comments | « no previous file | sandbox/linux/suid/client/setuid_sandbox_client.cc » ('j') | sandbox/linux/suid/client/setuid_sandbox_client.cc » ('J')

Powered by Google App Engine
This is Rietveld 408576698