From 2c9cf5074642459b37f19a2d4c6bc0233248d3a4 Mon Sep 17 00:00:00 2001 From: Shea Levy Date: Thu, 7 Mar 2013 19:39:55 -0500 Subject: 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 --- src/libstore/local-store.cc | 33 ++++++++++++--------------------- 1 file changed, 12 insertions(+), 21 deletions(-) (limited to 'src/libstore/local-store.cc') 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 #include -#if HAVE_UNSHARE +#if HAVE_UNSHARE && HAVE_STATVFS && HAVE_SYS_MOUNT_H #include +#include #include #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(readFile("/proc/self/mountinfo", true), "\n"); - foreach (Strings::iterator, i, mounts) { - vector fields = tokenizeString >(*i, " "); - if (fields.at(3) == "/" || fields.at(4) != settings.nixStore) continue; - Strings options = tokenizeString(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 } -- cgit 1.4.1