diff --git a/pkgs/applications/networking/browsers/chromium/common.nix b/pkgs/applications/networking/browsers/chromium/common.nix index 85964ee7687..29b60967d55 100644 --- a/pkgs/applications/networking/browsers/chromium/common.nix +++ b/pkgs/applications/networking/browsers/chromium/common.nix @@ -67,7 +67,7 @@ let use_system_stlport = true; use_system_xdg_utils = true; use_system_yasm = true; - use_system_zlib = true; + use_system_zlib = false; use_system_protobuf = true; use_system_harfbuzz = false; @@ -112,7 +112,7 @@ let glib gtk dbus_glib libXScrnSaver libXcursor libXtst mesa pciutils protobuf speechd libXdamage - pythonPackages.gyp + pythonPackages.gyp pythonPackages.ply pythonPackages.jinja2 ] ++ optional gnomeKeyringSupport libgnome_keyring3 ++ optionals gnomeSupport [ gnome.GConf libgcrypt ] ++ optional enableSELinux libselinux diff --git a/pkgs/applications/networking/browsers/chromium/sandbox.nix b/pkgs/applications/networking/browsers/chromium/sandbox.nix index 81ae49ebbb8..b470ed63325 100644 --- a/pkgs/applications/networking/browsers/chromium/sandbox.nix +++ b/pkgs/applications/networking/browsers/chromium/sandbox.nix @@ -7,6 +7,7 @@ stdenv.mkDerivation { patchPhase = '' sed -i -e '/#include.*base_export/c \ #define BASE_EXPORT __attribute__((visibility("default"))) + /#include/s|sandbox/linux|'"$(pwd)"'/linux| ' linux/suid/*.[hc] ''; diff --git a/pkgs/applications/networking/browsers/chromium/source/default.nix b/pkgs/applications/networking/browsers/chromium/source/default.nix index e80e05ca9e2..4ec853bddf8 100644 --- a/pkgs/applications/networking/browsers/chromium/source/default.nix +++ b/pkgs/applications/networking/browsers/chromium/source/default.nix @@ -22,7 +22,9 @@ stdenv.mkDerivation { prePatch = "patchShebangs ."; - patches = singleton ./sandbox_userns_31.patch; + patches = if (versionOlder version "36.0.0.0") + then singleton ./sandbox_userns_31.patch + else singleton ./sandbox_userns_36.patch; postPatch = '' sed -i -r \ diff --git a/pkgs/applications/networking/browsers/chromium/source/sandbox_userns_36.patch b/pkgs/applications/networking/browsers/chromium/source/sandbox_userns_36.patch new file mode 100644 index 00000000000..a8f3ed0befd --- /dev/null +++ b/pkgs/applications/networking/browsers/chromium/source/sandbox_userns_36.patch @@ -0,0 +1,293 @@ +commit 3c80951744293441c2e66345ef7d82c199f4600e +Author: aszlig +Date: Thu May 16 14:17:56 2013 +0200 + + zygote: Add support for user namespaces on Linux. + + The implementation is done by patching the Zygote host to execute the sandbox + binary with CLONE_NEWUSER and setting the uid and gid mapping so that the child + process is using uid 0 and gid 0 which map to the current user of the parent. + Afterwards, the sandbox will continue as if it was called as a setuid binary. + + In addition, this adds new_user_namespace as an option in process_util in order + to set the UID and GID mapping correctly. The reason for this is that just + passing CLONE_NEWUSER to clone_flags doesn't help in LaunchProcess(), because + without setting the mappings exec*() will clear the process's capability sets. + + If the kernel doesn't support unprivileged user namespaces and the sandbox + binary doesn't have the setuid flag, the Zygote main process will run without a + sandbox. This is to mimic the behaviour if no SUID sandbox binary path is set. + + Signed-off-by: aszlig + +diff --git a/base/process/launch.cc b/base/process/launch.cc +index 81748f5..930f20f 100644 +--- a/base/process/launch.cc ++++ b/base/process/launch.cc +@@ -26,6 +26,7 @@ LaunchOptions::LaunchOptions() + #if defined(OS_LINUX) + , clone_flags(0) + , allow_new_privs(false) ++ , new_user_namespace(false) + #endif // OS_LINUX + #if defined(OS_CHROMEOS) + , ctrl_terminal_fd(-1) +diff --git a/base/process/launch.h b/base/process/launch.h +index 9e39fba..00e4c79 100644 +--- a/base/process/launch.h ++++ b/base/process/launch.h +@@ -115,6 +115,9 @@ struct BASE_EXPORT LaunchOptions { + // By default, child processes will have the PR_SET_NO_NEW_PRIVS bit set. If + // true, then this bit will not be set in the new child process. + bool allow_new_privs; ++ ++ // If true, start the process in a new user namespace. ++ bool new_user_namespace; + #endif // defined(OS_LINUX) + + #if defined(OS_CHROMEOS) +diff --git a/base/process/launch_posix.cc b/base/process/launch_posix.cc +index fe4da1a..7f118b8 100644 +--- a/base/process/launch_posix.cc ++++ b/base/process/launch_posix.cc +@@ -40,6 +40,10 @@ + + #if defined(OS_LINUX) + #include ++#include ++#if !defined(CLONE_NEWUSER) ++#define CLONE_NEWUSER 0x10000000 ++#endif + #endif + + #if defined(OS_CHROMEOS) +@@ -301,13 +305,23 @@ bool LaunchProcess(const std::vector& argv, + + pid_t pid; + #if defined(OS_LINUX) +- if (options.clone_flags) { ++ int map_pipe_fd[2]; ++ int flags = options.clone_flags; ++ ++ if (options.new_user_namespace) { ++ flags |= CLONE_NEWUSER; ++ if (pipe(map_pipe_fd) < 0) { ++ DPLOG(ERROR) << "user namespace pipe"; ++ return false; ++ } ++ } ++ ++ if (options.clone_flags || options.new_user_namespace) { + // Signal handling in this function assumes the creation of a new + // process, so we check that a thread is not being created by mistake + // and that signal handling follows the process-creation rules. +- RAW_CHECK( +- !(options.clone_flags & (CLONE_SIGHAND | CLONE_THREAD | CLONE_VM))); +- pid = syscall(__NR_clone, options.clone_flags, 0, 0, 0); ++ RAW_CHECK(!(flags & (CLONE_SIGHAND | CLONE_THREAD | CLONE_VM))); ++ pid = syscall(__NR_clone, flags, 0, 0, 0); + } else + #endif + { +@@ -328,6 +342,21 @@ bool LaunchProcess(const std::vector& argv, + // DANGER: no calls to malloc or locks are allowed from now on: + // http://crbug.com/36678 + ++#if defined(OS_LINUX) ++ if (options.new_user_namespace) { ++ // Close the write end of the pipe so we get an EOF when the parent closes ++ // the FD. This is to avoid race conditions when the UID/GID mappings are ++ // written _after_ execvp(). ++ close(map_pipe_fd[1]); ++ ++ char dummy; ++ if (HANDLE_EINTR(read(map_pipe_fd[0], &dummy, 1)) != 0) { ++ RAW_LOG(ERROR, "Unexpected input in uid/gid mapping pipe."); ++ _exit(127); ++ } ++ } ++#endif ++ + // DANGER: fork() rule: in the child, if you don't end up doing exec*(), + // you call _exit() instead of exit(). This is because _exit() does not + // call any previously-registered (in the parent) exit handlers, which +@@ -451,6 +480,40 @@ bool LaunchProcess(const std::vector& argv, + _exit(127); + } else { + // Parent process ++#if defined(OS_LINUX) ++ if (options.new_user_namespace) { ++ // We need to write UID/GID mapping here to map the current user outside ++ // the namespace to the root user inside the namespace in order to ++ // correctly "fool" the child process. ++ char buf[256]; ++ int map_fd, map_len; ++ ++ snprintf(buf, sizeof(buf), "/proc/%d/uid_map", pid); ++ map_fd = open(buf, O_RDWR); ++ DPCHECK(map_fd >= 0); ++ snprintf(buf, sizeof(buf), "0 %d 1", geteuid()); ++ map_len = strlen(buf); ++ if (write(map_fd, buf, map_len) != map_len) { ++ RAW_LOG(WARNING, "Can't write to uid_map."); ++ } ++ close(map_fd); ++ ++ snprintf(buf, sizeof(buf), "/proc/%d/gid_map", pid); ++ map_fd = open(buf, O_RDWR); ++ DPCHECK(map_fd >= 0); ++ snprintf(buf, sizeof(buf), "0 %d 1", getegid()); ++ map_len = strlen(buf); ++ if (write(map_fd, buf, map_len) != map_len) { ++ RAW_LOG(WARNING, "Can't write to gid_map."); ++ } ++ close(map_fd); ++ ++ // Close the pipe on the parent, so the child can continue doing the ++ // execvp() call. ++ close(map_pipe_fd[1]); ++ } ++#endif ++ + if (options.wait) { + // While this isn't strictly disk IO, waiting for another process to + // finish is the sort of thing ThreadRestrictions is trying to prevent. +diff --git a/content/browser/zygote_host/zygote_host_impl_linux.cc b/content/browser/zygote_host/zygote_host_impl_linux.cc +index 0106a7a..a0465af 100644 +--- a/content/browser/zygote_host/zygote_host_impl_linux.cc ++++ b/content/browser/zygote_host/zygote_host_impl_linux.cc +@@ -124,25 +124,31 @@ void ZygoteHostImpl::Init(const std::string& sandbox_cmd) { + + sandbox_binary_ = sandbox_cmd.c_str(); + +- // A non empty sandbox_cmd means we want a SUID sandbox. +- using_suid_sandbox_ = !sandbox_cmd.empty(); ++ bool userns_sandbox = false; ++ const std::vector cmd_line_unwrapped(cmd_line.argv()); + +- if (using_suid_sandbox_) { ++ if (!sandbox_cmd.empty()) { + struct stat st; + if (stat(sandbox_binary_.c_str(), &st) != 0) { + LOG(FATAL) << "The SUID sandbox helper binary is missing: " + << sandbox_binary_ << " Aborting now."; + } + +- if (access(sandbox_binary_.c_str(), X_OK) == 0 && +- (st.st_uid == 0) && +- (st.st_mode & S_ISUID) && +- (st.st_mode & S_IXOTH)) { ++ if (access(sandbox_binary_.c_str(), X_OK) == 0) { ++ using_suid_sandbox_ = true; ++ + cmd_line.PrependWrapper(sandbox_binary_); + + scoped_ptr + sandbox_client(sandbox::SetuidSandboxClient::Create()); + sandbox_client->SetupLaunchEnvironment(); ++ ++ if (!((st.st_uid == 0) && ++ (st.st_mode & S_ISUID) && ++ (st.st_mode & S_IXOTH))) { ++ userns_sandbox = true; ++ sandbox_client->SetNoSuid(); ++ } + } else { + LOG(FATAL) << "The SUID sandbox helper binary was found, but is not " + "configured correctly. Rather than run without sandboxing " +@@ -167,7 +173,19 @@ void ZygoteHostImpl::Init(const std::string& sandbox_cmd) { + base::LaunchOptions options; + options.fds_to_remap = &fds_to_map; + options.allow_new_privs = using_suid_sandbox_; // Don't PR_SET_NO_NEW_PRIVS. ++ if (userns_sandbox) ++ options.new_user_namespace = true; + base::LaunchProcess(cmd_line.argv(), options, &process); ++ ++ if (process == -1 && userns_sandbox) { ++ LOG(ERROR) << "User namespace sandbox failed to start, running without " ++ << "sandbox! You need at least kernel 3.8.0 with CONFIG_USER_NS " ++ << "enabled in order to use the sandbox without setuid bit."; ++ using_suid_sandbox_ = false; ++ options.new_user_namespace = false; ++ base::LaunchProcess(cmd_line_unwrapped, options, &process); ++ } ++ + CHECK(process != -1) << "Failed to launch zygote process"; + + if (using_suid_sandbox_) { +diff --git a/content/zygote/zygote_main_linux.cc b/content/zygote/zygote_main_linux.cc +index 5dc09fa..4e09bc4 100644 +--- a/content/zygote/zygote_main_linux.cc ++++ b/content/zygote/zygote_main_linux.cc +@@ -397,6 +397,13 @@ static bool EnterSuidSandbox(sandbox::SetuidSandboxClient* setuid_sandbox) { + CHECK(CreateInitProcessReaper()); + } + ++ // Don't set non-dumpable, as it causes trouble when the host tries to find ++ // the zygote process (XXX: Not quite sure why this happens with user ++ // namespaces). Fortunately, we also have the seccomp filter sandbox which ++ // should disallow the use of ptrace. ++ if (setuid_sandbox->IsNoSuid()) ++ return true; ++ + #if !defined(OS_OPENBSD) + // Previously, we required that the binary be non-readable. This causes the + // kernel to mark the process as non-dumpable at startup. The thinking was +diff --git a/sandbox/linux/suid/client/setuid_sandbox_client.cc b/sandbox/linux/suid/client/setuid_sandbox_client.cc +index 8ed1a97..cbdfadc 100644 +--- a/sandbox/linux/suid/client/setuid_sandbox_client.cc ++++ b/sandbox/linux/suid/client/setuid_sandbox_client.cc +@@ -173,6 +173,10 @@ bool SetuidSandboxClient::IsInNewNETNamespace() const { + return env_->HasVar(kSandboxNETNSEnvironmentVarName); + } + ++bool SetuidSandboxClient::IsNoSuid() const { ++ return env_->HasVar(kSandboxNoSuidVarName); ++} ++ + bool SetuidSandboxClient::IsSandboxed() const { + return sandboxed_; + } +@@ -182,4 +186,8 @@ void SetuidSandboxClient::SetupLaunchEnvironment() { + SetSandboxAPIEnvironmentVariable(env_); + } + ++void SetuidSandboxClient::SetNoSuid() { ++ env_->SetVar(kSandboxNoSuidVarName, "1"); ++} ++ + } // namespace sandbox +diff --git a/sandbox/linux/suid/client/setuid_sandbox_client.h b/sandbox/linux/suid/client/setuid_sandbox_client.h +index 0f6db7a..c629391 100644 +--- a/sandbox/linux/suid/client/setuid_sandbox_client.h ++++ b/sandbox/linux/suid/client/setuid_sandbox_client.h +@@ -46,6 +46,8 @@ class SANDBOX_EXPORT SetuidSandboxClient { + bool IsInNewPIDNamespace() const; + // Did the setuid helper create a new network namespace ? + bool IsInNewNETNamespace() const; ++ // Is sandboxed without SUID binary ? ++ bool IsNoSuid() const; + // Are we done and fully sandboxed ? + bool IsSandboxed() const; + +@@ -53,6 +55,8 @@ class SANDBOX_EXPORT SetuidSandboxClient { + // helper. + void SetupLaunchEnvironment(); + ++ void SetNoSuid(); ++ + private: + // Holds the environment. Will never be NULL. + base::Environment* env_; +diff --git a/sandbox/linux/suid/common/sandbox.h b/sandbox/linux/suid/common/sandbox.h +index 9345287..2db659e 100644 +--- a/sandbox/linux/suid/common/sandbox.h ++++ b/sandbox/linux/suid/common/sandbox.h +@@ -15,6 +15,7 @@ static const char kAdjustOOMScoreSwitch[] = "--adjust-oom-score"; + + static const char kSandboxDescriptorEnvironmentVarName[] = "SBX_D"; + static const char kSandboxHelperPidEnvironmentVarName[] = "SBX_HELPER_PID"; ++static const char kSandboxNoSuidVarName[] = "SBX_NO_SUID"; + + static const long kSUIDSandboxApiNumber = 1; + static const char kSandboxEnvironmentApiRequest[] = "SBX_CHROME_API_RQ"; diff --git a/pkgs/applications/networking/browsers/chromium/source/sources.nix b/pkgs/applications/networking/browsers/chromium/source/sources.nix index dceab16d38c..9204c7f08e5 100644 --- a/pkgs/applications/networking/browsers/chromium/source/sources.nix +++ b/pkgs/applications/networking/browsers/chromium/source/sources.nix @@ -1,15 +1,21 @@ # This file is autogenerated from update.sh in the same directory. { dev = { - version = "35.0.1883.0"; - sha256 = "0qbv6prxl18y5824pfd13ng9798g561gzb6nypwp502hqr45jvb6"; + version = "36.0.1941.0"; + sha256 = "12rhyq8hliwc8b3371h2axzlzabg99c06d02kl9ldag2kxfpsfps"; + sha256bin32 = "1rbl5x0pjid5lypdplbqvcx4lgvr2rlbiv83ivvqb5dbg6p7886g"; + sha256bin64 = "18440spj541w4bqjblb2wpf94slg4if176gprccbxw9sy6b7z38w"; }; beta = { - version = "34.0.1847.60"; - sha256 = "1na5d6z4a0wkabn7cj62vyiv3mmvcb6qdvrkyy6fj79h7gk2hb7k"; + version = "35.0.1916.47"; + sha256 = "0pq87aybfna4pgsf02v97lprj5kbsrzim7c44nqarmcvlj4l65ch"; + sha256bin32 = "057l59any3hiqdg1gh4nxry542083lxdaychhljbrfkipq1gy4yv"; + sha256bin64 = "07n8sqv234dg959id023w3mz5n9ascwrcmxq3px96bqgqim2vf8s"; }; stable = { version = "34.0.1847.116"; sha256 = "04cpfav5rqa117igvzmrw0045r2ljxg5fqb46qgqvkgff30pjrfx"; + sha256bin32 = "1k24j80xgc91p8ssynql9ifjdhpz6w7vl3pk9lvkr0sdhg16hlrf"; + sha256bin64 = "16gidav4ilc95fr1d6832xzpyynfwnglbz7b33gq62vp8bj77da4"; }; }