Skip to content
Permalink

Comparing changes

Choose two branches to see what’s changed or to start a new pull request. If you need to, you can also or learn more about diff comparisons.

Open a pull request

Create a new pull request by comparing changes across two branches. If you need to, you can also . Learn more about diff comparisons here.
base repository: NixOS/nix
Failed to load repositories. Confirm that selected base ref is valid, then try again.
Loading
base: 56f6e382be03
Choose a base ref
...
head repository: NixOS/nix
Failed to load repositories. Confirm that selected head ref is valid, then try again.
Loading
compare: a0ef21262f4d
Choose a head ref
  • 1 commit
  • 8 files changed
  • 1 contributor

Commits on Nov 13, 2018

  1. Restore parent mount namespace before executing a child process

    This ensures that they can't write to /nix/store. Fixes #2535.
    edolstra committed Nov 13, 2018
    4
    Copy the full SHA
    a0ef212 View commit details
Showing with 48 additions and 4 deletions.
  1. +2 −0 src/libstore/local-store.cc
  2. +3 −0 src/libstore/ssh.cc
  3. +23 −0 src/libutil/util.cc
  4. +9 −0 src/libutil/util.hh
  5. +2 −2 src/nix-build/nix-build.cc
  6. +5 −0 src/nix/edit.cc
  7. +2 −0 src/nix/repl.cc
  8. +2 −2 src/nix/run.cc
2 changes: 2 additions & 0 deletions src/libstore/local-store.cc
Original file line number Diff line number Diff line change
@@ -366,6 +366,8 @@ void LocalStore::makeStoreWritable()
throw SysError("getting info about the Nix store mount point");

if (stat.f_flag & ST_RDONLY) {
saveMountNamespace();

if (unshare(CLONE_NEWNS) == -1)
throw SysError("setting up a private mount namespace");

3 changes: 3 additions & 0 deletions src/libstore/ssh.cc
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
#include "ssh.hh"
#include "affinity.hh"

namespace nix {

@@ -34,7 +35,9 @@ std::unique_ptr<SSHMaster::Connection> SSHMaster::startCommand(const std::string

auto conn = std::make_unique<Connection>();
conn->sshPid = startProcess([&]() {
restoreAffinity();
restoreSignals();
restoreMountNamespace();

close(in.writeSide.get());
close(out.readSide.get());
23 changes: 23 additions & 0 deletions src/libutil/util.cc
Original file line number Diff line number Diff line change
@@ -936,6 +936,7 @@ pid_t startProcess(std::function<void()> 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<InterruptCallback> createInterruptCallback(std::function<void()>
return std::unique_ptr<InterruptCallback>(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
}

}
9 changes: 9 additions & 0 deletions src/libutil/util.hh
Original file line number Diff line number Diff line change
@@ -514,4 +514,13 @@ typedef std::function<bool(const Path & path)> 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();


}
4 changes: 2 additions & 2 deletions src/nix-build/nix-build.cc
Original file line number Diff line number Diff line change
@@ -401,8 +401,6 @@ static void _main(int argc, char * * argv)
} else
env[var.first] = var.second;

restoreAffinity();

/* Run a shell using the derivation's environment. For
convenience, source $stdenv/setup to setup additional
environment variables and shell functions. Also don't
@@ -446,7 +444,9 @@ static void _main(int argc, char * * argv)

auto argPtrs = stringsToCharPtrs(args);

restoreAffinity();
restoreSignals();
restoreMountNamespace();

execvp(shell.c_str(), argPtrs.data());

5 changes: 5 additions & 0 deletions src/nix/edit.cc
Original file line number Diff line number Diff line change
@@ -3,6 +3,7 @@
#include "eval.hh"
#include "attr-path.hh"
#include "progress-bar.hh"
#include "affinity.hh"

#include <unistd.h>

@@ -72,6 +73,10 @@ struct CmdEdit : InstallableCommand

stopProgressBar();

restoreAffinity();
restoreSignals();
restoreMountNamespace();

execvp(args.front().c_str(), stringsToCharPtrs(args).data());

throw SysError("cannot run editor '%s'", editor);
2 changes: 2 additions & 0 deletions src/nix/repl.cc
Original file line number Diff line number Diff line change
@@ -285,6 +285,8 @@ static int runProgram(const string & program, const Strings & args)
if (pid == -1) throw SysError("forking");
if (pid == 0) {
restoreAffinity();
restoreSignals();
restoreMountNamespace();
execvp(program.c_str(), stringsToCharPtrs(args2).data());
_exit(1);
}
4 changes: 2 additions & 2 deletions src/nix/run.cc
Original file line number Diff line number Diff line change
@@ -153,9 +153,9 @@ struct CmdRun : InstallablesCommand

stopProgressBar();

restoreSignals();

restoreAffinity();
restoreSignals();
restoreMountNamespace();

/* If this is a diverted store (i.e. its "logical" location
(typically /nix/store) differs from its "physical" location