diff options
author | Shea Levy <shea@shealevy.com> | 2013-03-08T00·39-0500 |
---|---|---|
committer | Eelco Dolstra <eelco.dolstra@logicblox.com> | 2013-03-25T18·00+0100 |
commit | 2c9cf5074642459b37f19a2d4c6bc0233248d3a4 (patch) | |
tree | f0d7e719c13a9669ddfe7fa2a26b434c6d45a466 | |
parent | c3fc60d9369fc802b33f75d2d9cd6ef22b916112 (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.ac | 1 | ||||
-rw-r--r-- | src/libstore/local-store.cc | 33 |
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 } |