diff options
author | Julian Andres Klode <julian.klode@canonical.com> | 2023-09-16 12:34:48 +0200 |
---|---|---|
committer | Julian Andres Klode <julian.klode@canonical.com> | 2023-09-16 12:37:31 +0200 |
commit | 99c888b5eabbb7008bf4451bc62c277f28bb925f (patch) | |
tree | 2375ab845a8c66a368bae090b799d819287ee589 | |
parent | 52dd18670bf7d22ecf234141d3c7b7b9f67c6fa3 (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.in | 3 | ||||
-rw-r--r-- | CMakeLists.txt | 1 | ||||
-rw-r--r-- | apt-pkg/aptconfiguration.cc | 29 | ||||
-rw-r--r-- | apt-pkg/aptconfiguration.h | 6 | ||||
-rw-r--r-- | apt-private/private-install.cc | 20 |
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 || |