Skip to content
Browse files

makeStoreWritable: Use statvfs instead of /proc/self/mountinfo to fin…

…d 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>
  • Loading branch information...
1 parent c3fc60d commit 2c9cf5074642459b37f19a2d4c6bc0233248d3a4 @shlevy shlevy committed with edolstra Mar 7, 2013
Showing with 13 additions and 21 deletions.
  1. +1 −0 configure.ac
  2. +12 −21 src/libstore/local-store.cc
View
1 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], [], [],
View
33 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
}

0 comments on commit 2c9cf50

Please sign in to comment.
Something went wrong with that request. Please try again.