From a0ef21262f4d5652bfb65cfacaec01d89c475a93 Mon Sep 17 00:00:00 2001 From: Eelco Dolstra Date: Tue, 13 Nov 2018 16:15:30 +0100 Subject: Restore parent mount namespace before executing a child process This ensures that they can't write to /nix/store. Fixes #2535. --- src/libutil/util.cc | 23 +++++++++++++++++++++++ src/libutil/util.hh | 9 +++++++++ 2 files changed, 32 insertions(+) (limited to 'src/libutil') diff --git a/src/libutil/util.cc b/src/libutil/util.cc index 259eaf0a0dd3..6e4536e6e4ea 100644 --- a/src/libutil/util.cc +++ b/src/libutil/util.cc @@ -936,6 +936,7 @@ pid_t startProcess(std::function fun, const ProcessOptions & options) throw SysError("setting death signal"); #endif restoreAffinity(); + restoreMountNamespace(); fun(); } catch (std::exception & e) { try { @@ -1504,4 +1505,26 @@ std::unique_ptr createInterruptCallback(std::function return std::unique_ptr(res.release()); } +static AutoCloseFD fdSavedMountNamespace; + +void saveMountNamespace() +{ +#if __linux__ + std::once_flag done; + std::call_once(done, []() { + fdSavedMountNamespace = open("/proc/self/ns/mnt", O_RDONLY); + if (!fdSavedMountNamespace) + throw SysError("saving parent mount namespace"); + }); +#endif +} + +void restoreMountNamespace() +{ +#if __linux__ + if (fdSavedMountNamespace && setns(fdSavedMountNamespace.get(), CLONE_NEWNS) == -1) + throw SysError("restoring parent mount namespace"); +#endif +} + } diff --git a/src/libutil/util.hh b/src/libutil/util.hh index bda87bee433e..2689cbd8b412 100644 --- a/src/libutil/util.hh +++ b/src/libutil/util.hh @@ -514,4 +514,13 @@ typedef std::function PathFilter; extern PathFilter defaultPathFilter; +/* Save the current mount namespace. Ignored if called more than + once. */ +void saveMountNamespace(); + +/* Restore the mount namespace saved by saveMountNamespace(). Ignored + if saveMountNamespace() was never called. */ +void restoreMountNamespace(); + + } -- cgit 1.4.1