about summary refs log tree commit diff
path: root/src/libexpr/eval.cc
diff options
context:
space:
mode:
authorEelco Dolstra <eelco.dolstra@logicblox.com>2015-02-23T13·41+0100
committerEelco Dolstra <eelco.dolstra@logicblox.com>2015-02-23T14·54+0100
commit15d2d3c34e454fb7795998a3a2d73010dfbdec38 (patch)
tree677224a9270e2f70112f58ab7adf8956c293e8fc /src/libexpr/eval.cc
parent47bdc52c1bf7bcec0ea1b685cf4c22b6b93be06d (diff)
Add restricted evaluation mode
If ‘--option restrict-eval true’ is given, the evaluator will throw an
exception if an attempt is made to access any file outside of the Nix
search path. This is primarily intended for Hydra, where we don't want
people doing ‘builtins.readFile ~/.ssh/id_dsa’ or stuff like that.
Diffstat (limited to 'src/libexpr/eval.cc')
-rw-r--r--src/libexpr/eval.cc23
1 files changed, 20 insertions, 3 deletions
diff --git a/src/libexpr/eval.cc b/src/libexpr/eval.cc
index 95b56e84d89a..d82d1d6aafa2 100644
--- a/src/libexpr/eval.cc
+++ b/src/libexpr/eval.cc
@@ -195,6 +195,8 @@ EvalState::EvalState(const Strings & _searchPath)
     nrListConcats = nrPrimOpCalls = nrFunctionCalls = 0;
     countCalls = getEnv("NIX_COUNT_CALLS", "0") != "0";
 
+    restricted = settings.get("restrict-eval", false);
+
 #if HAVE_BOEHMGC
     static bool gcInitialised = false;
     if (!gcInitialised) {
@@ -250,6 +252,21 @@ EvalState::~EvalState()
 }
 
 
+Path EvalState::checkSourcePath(const Path & path_)
+{
+    if (!restricted) return path_;
+
+    /* Resolve symlinks. */
+    Path path = canonPath(path_, true);
+
+    for (auto & i : searchPath)
+        if (path == i.second || isInDir(path, i.second))
+            return path;
+
+    throw RestrictedPathError(format("access to path ‘%1%’ is forbidden in restricted mode") % path_);
+}
+
+
 void EvalState::addConstant(const string & name, Value & v)
 {
     Value * v2 = allocValue();
@@ -555,7 +572,7 @@ void EvalState::evalFile(const Path & path, Value & v)
     }
 
     startNest(nest, lvlTalkative, format("evaluating file ‘%1%’") % path2);
-    Expr * e = parseExprFromFile(path2);
+    Expr * e = parseExprFromFile(checkSourcePath(path2));
     try {
         eval(e, v);
     } catch (Error & e) {
@@ -1358,8 +1375,8 @@ string EvalState::copyPathToStore(PathSet & context, const Path & path)
         dstPath = srcToStore[path];
     else {
         dstPath = settings.readOnlyMode
-            ? computeStorePathForPath(path).first
-            : store->addToStore(path, true, htSHA256, defaultPathFilter, repair);
+            ? computeStorePathForPath(checkSourcePath(path)).first
+            : store->addToStore(checkSourcePath(path), true, htSHA256, defaultPathFilter, repair);
         srcToStore[path] = dstPath;
         printMsg(lvlChatty, format("copied source ‘%1%’ -> ‘%2%’")
             % path % dstPath);