about summary refs log tree commit diff
diff options
context:
space:
mode:
authorShea Levy <shea@shealevy.com>2013-03-08T00·39-0500
committerEelco Dolstra <eelco.dolstra@logicblox.com>2013-03-25T18·00+0100
commit2c9cf5074642459b37f19a2d4c6bc0233248d3a4 (patch)
treef0d7e719c13a9669ddfe7fa2a26b434c6d45a466
parentc3fc60d9369fc802b33f75d2d9cd6ef22b916112 (diff)
makeStoreWritable: Use statvfs instead of /proc/self/mountinfo to find out if /nix/store is a read-only bind mount
/nix/store could be a read-only bind mount even if it is / in its own filesystem, so checking the 4th field in mountinfo is insufficient.

Signed-off-by: Shea Levy <shea@shealevy.com>
-rw-r--r--configure.ac1
-rw-r--r--src/libstore/local-store.cc33
2 files changed, 13 insertions, 21 deletions
diff --git a/configure.ac b/configure.ac
index ef3a060c45e0..54b8dff08bb2 100644
--- a/configure.ac
+++ b/configure.ac
@@ -106,6 +106,7 @@ AC_LANG_POP(C++)
 # Check for chroot support (requires chroot() and bind mounts).
 AC_CHECK_FUNCS([chroot])
 AC_CHECK_FUNCS([unshare])
+AC_CHECK_FUNCS([statvfs])
 AC_CHECK_HEADERS([sched.h])
 AC_CHECK_HEADERS([sys/param.h])
 AC_CHECK_HEADERS([sys/mount.h], [], [],
diff --git a/src/libstore/local-store.cc b/src/libstore/local-store.cc
index 4b8203efe374..4086e553c0a9 100644
--- a/src/libstore/local-store.cc
+++ b/src/libstore/local-store.cc
@@ -19,8 +19,9 @@
 #include <stdio.h>
 #include <time.h>
 
-#if HAVE_UNSHARE
+#if HAVE_UNSHARE && HAVE_STATVFS && HAVE_SYS_MOUNT_H
 #include <sched.h>
+#include <sys/statvfs.h>
 #include <sys/mount.h>
 #endif
 
@@ -434,30 +435,20 @@ void LocalStore::openDB(bool create)
    bind mount.  So make the Nix store writable for this process. */
 void LocalStore::makeStoreWritable()
 {
-#if HAVE_UNSHARE
+#if HAVE_UNSHARE && HAVE_STATVFS && HAVE_SYS_MOUNT_H && defined(MS_BIND) && defined(MS_REMOUNT)
     if (getuid() != 0) return;
-
-    if (!pathExists("/proc/self/mountinfo")) return;
-
     /* Check if /nix/store is a read-only bind mount. */
-    bool found = false;
-    Strings mounts = tokenizeString<Strings>(readFile("/proc/self/mountinfo", true), "\n");
-    foreach (Strings::iterator, i, mounts) {
-        vector<string> fields = tokenizeString<vector<string> >(*i, " ");
-        if (fields.at(3) == "/" || fields.at(4) != settings.nixStore) continue;
-        Strings options = tokenizeString<Strings>(fields.at(5), ",");
-        if (std::find(options.begin(), options.end(), "ro") == options.end()) continue;
-        found = true;
-        break;
-    }
+    struct statvfs stat;
+    if (statvfs(settings.nixStore.c_str(), &stat) !=0)
+        throw SysError("Getting info of nix store mountpoint");
 
-    if (!found) return;
+    if (stat.f_flag & (ST_RDONLY | MS_BIND)) {
+        if (unshare(CLONE_NEWNS) == -1)
+            throw SysError("setting up a private mount namespace");
 
-    if (unshare(CLONE_NEWNS) == -1)
-        throw SysError("setting up a private mount namespace");
-
-    if (mount(0, settings.nixStore.c_str(), 0, MS_REMOUNT | MS_BIND, 0) == -1)
-        throw SysError(format("remounting %1% writable") % settings.nixStore);
+        if (mount(0, settings.nixStore.c_str(), 0, MS_REMOUNT | MS_BIND, 0) == -1)
+            throw SysError(format("remounting %1% writable") % settings.nixStore);
+    }
 #endif
 }