From b5591ece4c4afae6a0ea71396a72eea529b39b79 Mon Sep 17 00:00:00 2001 From: Ben Radford Date: Mon, 15 May 2023 10:20:16 +0100 Subject: [PATCH] Check that overlay store directory is mounted correctly. Nix does not manage the overlayfs mount point itself, but the correct functioning of the overlay store does depend on this mount point being set up correctly. Rather than just assume this is the case, check that the lowerdir and upperdir options are what we expect them to be. This check is on by default, but can be disabled if needed. --- src/libstore/local-overlay-store.cc | 27 +++++++++++++++++++++++++++ src/libstore/local-overlay-store.hh | 3 +++ 2 files changed, 30 insertions(+) diff --git a/src/libstore/local-overlay-store.cc b/src/libstore/local-overlay-store.cc index c6b721b48..a40f55fdb 100644 --- a/src/libstore/local-overlay-store.cc +++ b/src/libstore/local-overlay-store.cc @@ -1,5 +1,6 @@ #include "local-overlay-store.hh" #include "callback.hh" +#include namespace nix { @@ -17,6 +18,32 @@ LocalOverlayStore::LocalOverlayStore(const Params & params) , LocalStore(params) , lowerStore(openStore(lowerStoreUri).dynamic_pointer_cast()) { + if (checkMount.get()) { + std::smatch match; + std::string mountInfo; + auto mounts = readFile("/proc/self/mounts"); + auto regex = std::regex(R"((^|\n)overlay )" + realStoreDir.get() + R"( .*(\n|$))"); + + // Mount points can be stacked, so there might be multiple matching entries. + // Loop until the last match, which will be the current state of the mount point. + while (std::regex_search(mounts, match, regex)) { + mountInfo = match.str(); + mounts = match.suffix(); + } + + auto checkOption = [&](std::string option, std::string value) { + return std::regex_search(mountInfo, std::regex("\\b" + option + "=" + value + "( |,)")); + }; + + auto expectedLowerDir = lowerStore->realStoreDir.get(); + if (!checkOption("lowerdir", expectedLowerDir) || !checkOption("upperdir", upperLayer)) { + debug("expected lowerdir: %s", expectedLowerDir); + debug("expected upperdir: %s", upperLayer); + debug("actual mount: %s", mountInfo); + throw Error("overlay filesystem '%s' mounted incorrectly", + realStoreDir.get()); + } + } } diff --git a/src/libstore/local-overlay-store.hh b/src/libstore/local-overlay-store.hh index 9bc513b3e..8280ed273 100644 --- a/src/libstore/local-overlay-store.hh +++ b/src/libstore/local-overlay-store.hh @@ -30,6 +30,9 @@ struct LocalOverlayStoreConfig : virtual LocalStoreConfig Must be used as OverlayFS upper layer for this store's store dir. )"}; + Setting checkMount{(StoreConfig*) this, true, "check-mount", + "Check that the overlay filesystem is correctly mounted."}; + const std::string name() override { return "Experimental Local Overlay Store"; } std::string doc() override