summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJulian Andres Klode <julian.klode@canonical.com>2023-09-16 12:34:48 +0200
committerJulian Andres Klode <julian.klode@canonical.com>2023-09-16 12:37:31 +0200
commit99c888b5eabbb7008bf4451bc62c277f28bb925f (patch)
tree2375ab845a8c66a368bae090b799d819287ee589
parent52dd18670bf7d22ecf234141d3c7b7b9f67c6fa3 (diff)
Only accept installs of usrmerge on unmerged-usr systems
As of bookworm, merged-usr is mandatory, and people got caught in the crosshairs of the dpkg fsys-unmessusr debacle and inadvertently reverted back to an unmerged configuration and continue to remain on an unsupported system unknowingly. Help them by erroring out when they are installing packages on /, they are not in a chroot, and a usrmerge package is available.
-rw-r--r--CMake/config.h.in3
-rw-r--r--CMakeLists.txt1
-rw-r--r--apt-pkg/aptconfiguration.cc29
-rw-r--r--apt-pkg/aptconfiguration.h6
-rw-r--r--apt-private/private-install.cc20
5 files changed, 57 insertions, 2 deletions
diff --git a/CMake/config.h.in b/CMake/config.h.in
index e875c3735..65f983fa9 100644
--- a/CMake/config.h.in
+++ b/CMake/config.h.in
@@ -79,3 +79,6 @@
/* Group of the root user */
#cmakedefine ROOT_GROUP "${ROOT_GROUP}"
+
+/* Whether to check for and require merged usr if a usrmerge package is available. */
+#cmakedefine REQUIRE_MERGED_USR
diff --git a/CMakeLists.txt b/CMakeLists.txt
index 6f9a34034..7de549936 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -10,6 +10,7 @@ include_directories(${PROJECT_BINARY_DIR}/include)
enable_testing()
+option(REQUIRE_MERGED_USR "Require merged-usr." ON)
option(WITH_DOC "Build all documentation." ON)
include(CMakeDependentOption)
cmake_dependent_option(WITH_DOC_MANPAGES "Force building manpages." OFF "NOT WITH_DOC" OFF)
diff --git a/apt-pkg/aptconfiguration.cc b/apt-pkg/aptconfiguration.cc
index 00a97a0e7..cfe38ec83 100644
--- a/apt-pkg/aptconfiguration.cc
+++ b/apt-pkg/aptconfiguration.cc
@@ -28,8 +28,8 @@
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
+#include <sys/stat.h>
#include <unistd.h>
-
/*}}}*/
namespace APT {
// setDefaultConfigurationForCompressors /*{{{*/
@@ -538,4 +538,31 @@ bool Configuration::isChroot()
return once.res;
}
/*}}}*/
+// isUsrMerged - whether usr is merged t /*{{{*/
+// ---------------------------------------------------------------------
+/* */
+bool Configuration::checkUsrMerged()
+{
+ std::string rootDir = _config->FindDir("Dir");
+ for (auto dir : {"bin", "sbin", "lib"})
+ {
+ struct stat root;
+ struct stat usr;
+ std::string dirInRoot = rootDir + dir;
+ std::string dirInUsr = rootDir + "usr/" + dir;
+
+ // Missing directories are a boot strap scenario that needs to work
+ if (stat(dirInRoot.c_str(), &root))
+ continue;
+ if (stat(dirInUsr.c_str(), &usr))
+ continue;
+ if (root.st_dev != usr.st_dev)
+ return _error->Error("%s is on different device than %s", dirInRoot.c_str(), dirInUsr.c_str());
+ if (root.st_ino != usr.st_ino)
+ return _error->Error("%s resolved to a different inode than %s", dirInRoot.c_str(), dirInUsr.c_str());
+ }
+
+ return true;
+}
+ /*}}}*/
}
diff --git a/apt-pkg/aptconfiguration.h b/apt-pkg/aptconfiguration.h
index bbeb156b9..3e2636edc 100644
--- a/apt-pkg/aptconfiguration.h
+++ b/apt-pkg/aptconfiguration.h
@@ -125,8 +125,12 @@ namespace Configuration { /*{{{*/
std::string const getMachineID();
+#ifdef APT_COMPILING_APT
/** \return Whether we are running in a chroot */
- bool isChroot();
+ APT_PUBLIC bool isChroot();
+ /** \return Check usr is merged or produce error. */
+ APT_PUBLIC bool checkUsrMerged();
+#endif
/*}}}*/
}
/*}}}*/
diff --git a/apt-private/private-install.cc b/apt-private/private-install.cc
index 13ed35e2a..a195df848 100644
--- a/apt-private/private-install.cc
+++ b/apt-private/private-install.cc
@@ -215,6 +215,26 @@ bool InstallPackages(CacheFile &Cache, APT::PackageVector &HeldBackPackages, boo
if (Cache->DelCount() != 0 && _config->FindB("APT::Get::Remove",true) == false)
return _error->Error(_("Packages need to be removed but remove is disabled."));
+#ifdef REQUIRE_MERGED_USR
+ _error->PushToStack();
+ auto usrmergePkg = Cache->FindPkg("usrmerge");
+ if (not APT::Configuration::isChroot() && _config->FindDir("Dir") == std::string("/") &&
+ not usrmergePkg.end() && not usrmergePkg.VersionList().end() &&
+ not Cache[usrmergePkg].Install() && not APT::Configuration::checkUsrMerged())
+ {
+ _error->Error(_("Unmerged usr is no longer supported, install usrmerge to continue."));
+ for (auto VF = usrmergePkg.VersionList().FileList(); not VF.end(); ++VF)
+ if (VF.File().Origin() == std::string("Debian"))
+ {
+ // TRANSLATORS: %s is a url to a page describing merged-usr (bookworm release notes)
+ _error->Notice(_("See %s for more details."), "https://www.debian.org/releases/bookworm/amd64/release-notes/ch-information.en.html#a-merged-usr-is-now-required");
+ break;
+ }
+ return false;
+ }
+ _error->RevertToStack();
+#endif
+
// Fail safe check
bool const Fail = (Essential || Downgrade || Hold);
if (_config->FindI("quiet",0) >= 2 ||