Script 'mail_helper' called by obssrc
Hello community,

here is the log from the commit of package transactional-update for 
openSUSE:Factory checked in at 2023-01-24 19:42:21
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Comparing /work/SRC/openSUSE:Factory/transactional-update (Old)
 and      /work/SRC/openSUSE:Factory/.transactional-update.new.32243 (New)
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++

Package is "transactional-update"

Tue Jan 24 19:42:21 2023 rev:95 rq:1060452 version:4.1.2

Changes:
--------
--- 
/work/SRC/openSUSE:Factory/transactional-update/transactional-update.changes    
    2023-01-23 04:38:08.576888702 +0100
+++ 
/work/SRC/openSUSE:Factory/.transactional-update.new.32243/transactional-update.changes
     2023-01-24 20:36:05.561550354 +0100
@@ -0,0 +1,23 @@
+-------------------------------------------------------------------
+Mon Jan 23 13:54:11 UTC 2023 - Ignaz Forster <ifors...@suse.com>
+
+- Version 4.1.2
+  - Don't try to mount user mounts if they don't exist [boo#1207366]
+
+-------------------------------------------------------------------
+Wed Jan 18 16:56:16 UTC 2023 - Ignaz Forster <ifors...@suse.com>
+
+- Version 4.1.1
+  - Mount user specific binddirs last: Prevously the internal mounts would
+    potentially overwrite user bind mounts [boo#1205011]
+  - selinux: Relabel shadowed /var files during update to make sure they
+    don't interfere with the update [boo#1205937]
+  - Clean up /var/lib/overlay more aggressively [boo#1206947]
+  - tukit: Merge /etc overlay into parent if --discard is used together
+    with --continue - previously the files were incorrectly always merged
+    with the currently running system
+  - status: do not execute the status command if experimental
+  - Don't delete created mount point dirs any more
+  - Small code optimizations
+
+-------------------------------------------------------------------

Old:
----
  transactional-update-4.1.0.tar.gz

New:
----
  transactional-update-4.1.2.tar.gz

++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++

Other differences:
------------------
++++++ transactional-update.spec ++++++
--- /var/tmp/diff_new_pack.bCmhYg/_old  2023-01-24 20:36:06.061552944 +0100
+++ /var/tmp/diff_new_pack.bCmhYg/_new  2023-01-24 20:36:06.077553027 +0100
@@ -1,7 +1,7 @@
 #
 # spec file for package transactional-update
 #
-# Copyright (c) 2022 SUSE LLC
+# Copyright (c) 2023 SUSE LLC
 # Copyright (c) 2021 Neal Gompa
 #
 # All modifications and additions to the file contributed by third parties
@@ -26,7 +26,7 @@
 %{!?_distconfdir: %global _distconfdir %{_prefix}%{_sysconfdir}}
 
 Name:           transactional-update
-Version:        4.1.0
+Version:        4.1.2
 Release:        0
 Summary:        Transactional Updates with btrfs and snapshots
 License:        GPL-2.0-or-later AND LGPL-2.1-or-later

++++++ transactional-update-4.1.0.tar.gz -> transactional-update-4.1.2.tar.gz 
++++++
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/transactional-update-4.1.0/NEWS 
new/transactional-update-4.1.2/NEWS
--- old/transactional-update-4.1.0/NEWS 2022-10-26 16:50:43.000000000 +0200
+++ new/transactional-update-4.1.2/NEWS 2023-01-23 14:31:20.000000000 +0100
@@ -2,6 +2,22 @@
 
 Copyright (C) 2016-2022 Thorsten Kukuk, Ignaz Forster et al.
 
+Version 4.1.2
+* Don't try to mount user mounts if they don't exist [boo#1207366]
+
+Version 4.1.1
+* Mount user specific binddirs last: Prevously the internal mounts would
+  potentially overwrite user bind mounts [boo#1205011]
+* selinux: Relabel shadowed /var files during update to make sure they
+  don't interfere with the update [boo#1205937]
+* Clean up /var/lib/overlay more aggressively [boo#1206947]
+* tukit: Merge /etc overlay into parent if --discard is used together
+  with --continue - previously the files were incorrectly always merged
+  with the currently running system
+* status: do not execute the status command if experimental
+* Don't delete created mount point dirs any more
+* Small code optimizations
+
 Version 4.1.0
 * t-u: Add a "setup-kdump" command; implements [jsc#PED-1441]
 * Add support for ULP (Userspace Live Patching) [jsc#PED-1078]:
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/transactional-update-4.1.0/README.md 
new/transactional-update-4.1.2/README.md
--- old/transactional-update-4.1.0/README.md    2022-10-26 16:50:43.000000000 
+0200
+++ new/transactional-update-4.1.2/README.md    2023-01-23 14:31:20.000000000 
+0100
@@ -29,7 +29,7 @@
 
 ## Known users
 * **dnf**, Fedora's package management system, supports transactional systems 
directly via the 
[libdnf-plugin-txnupd](https://code.opensuse.org/microos/libdnf-plugin-txnupd) 
plugin (libtukit).
-* **Cockpit** can update transactionals systems via the 
[cockpit-tukit](https://github.com/openSUSE/cockpit-tukit) plugin (tukitd).
+* **Cockpit** can update transactional systems via the 
[cockpit-tukit](https://github.com/openSUSE/cockpit-tukit) plugin (tukitd).
 * **Salt** contains the [salt.modules.transactional\_update 
module](https://docs.saltproject.io/en/3004/ref/modules/all/salt.modules.transactional_update.html)
 module (transactional-update).
 * **Ansible** also supports transactional-update via the the 
[community.general.zypper](https://docs.ansible.com/ansible/latest/collections/community/general/zypper_module.html)
 module (transactional-update).
 
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/transactional-update-4.1.0/configure.ac 
new/transactional-update-4.1.2/configure.ac
--- old/transactional-update-4.1.0/configure.ac 2022-10-26 16:50:43.000000000 
+0200
+++ new/transactional-update-4.1.2/configure.ac 2023-01-23 14:31:20.000000000 
+0100
@@ -1,11 +1,11 @@
 dnl Process this file with autoconf to produce a configure script.
-AC_INIT(transactional-update, 4.1.0)
+AC_INIT(transactional-update, 4.1.2)
 # Increase on any interface change and reset revision
 LIBTOOL_CURRENT=4
 # On interface change increase if backwards compatible, reset otherwise
 LIBTOOL_AGE=0
 # Increase on *any* C/C++ library code change, reset at interface change
-LIBTOOL_REVISION=1
+LIBTOOL_REVISION=2
 AC_CANONICAL_SYSTEM
 AM_INIT_AUTOMAKE([foreign])
 AC_CONFIG_FILES([tukit.pc])
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/transactional-update-4.1.0/lib/Mount.cpp 
new/transactional-update-4.1.2/lib/Mount.cpp
--- old/transactional-update-4.1.0/lib/Mount.cpp        2022-10-26 
16:50:43.000000000 +0200
+++ new/transactional-update-4.1.2/lib/Mount.cpp        2023-01-23 
14:31:20.000000000 +0100
@@ -13,9 +13,9 @@
 
 namespace TransactionalUpdate {
 
-Mount::Mount(std::string mountpoint, unsigned long flags)
+Mount::Mount(std::string mountpoint, unsigned long flags, bool umount)
     : mnt_table{mnt_new_table()}, mountpoint{std::move(mountpoint)},
-      flags{std::move(flags)}
+      flags{std::move(flags)}, umount{std::move(umount)}
 {
 }
 
@@ -29,7 +29,7 @@
 }
 
 Mount::~Mount() {
-    if (mnt_fs) {
+    if (mnt_fs && umount) {
         struct libmnt_table* umount_table = mnt_new_table();
         if ((mnt_table_parse_mtab(umount_table, nullptr)) != 0)
             tulog.error("Error reading mtab for umount");
@@ -39,14 +39,6 @@
         mnt_free_table(umount_table);
     }
 
-    if (!directoryCreated.empty()) {
-        try {
-            
std::filesystem::remove_all(std::filesystem::path{directoryCreated});
-        }  catch (const std::exception &e) {
-            tulog.error("ERROR: ", e.what());
-        }
-    }
-
     mnt_free_context(mnt_cxt);
     mnt_unref_fs(mnt_fs);
     mnt_free_table(mnt_table);
@@ -192,10 +184,6 @@
         throw std::runtime_error{"Setting mount flags for '" + mountpoint + "' 
failed: " + std::to_string(rc)};
     }
 
-    if (! std::filesystem::is_directory(mounttarget)) {
-        tulog.debug("Mount target ", mounttarget, " does not exist - 
creating...");
-        directoryCreated = mounttarget;
-    }
     std::filesystem::create_directories(mounttarget);
 
     rc = mnt_context_mount(mnt_cxt);
@@ -269,8 +257,8 @@
     mnt_free_context(umount_cxt);
 }
 
-BindMount::BindMount(std::string mountpoint, unsigned long flags)
-    : Mount(mountpoint, flags | MS_BIND)
+BindMount::BindMount(std::string mountpoint, unsigned long flags, bool umount)
+    : Mount(mountpoint, flags | MS_BIND, umount)
 {
 }
 
@@ -281,8 +269,8 @@
     Mount::mount(prefix);
 }
 
-PropagatedBindMount::PropagatedBindMount(std::string mountpoint, unsigned long 
flags)
-    : BindMount(mountpoint, flags | MS_REC | MS_SLAVE)
+PropagatedBindMount::PropagatedBindMount(std::string mountpoint, unsigned long 
flags, bool umount)
+    : BindMount(mountpoint, flags | MS_REC | MS_SLAVE, umount)
 {
 }
 
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/transactional-update-4.1.0/lib/Mount.hpp 
new/transactional-update-4.1.2/lib/Mount.hpp
--- old/transactional-update-4.1.0/lib/Mount.hpp        2022-10-26 
16:50:43.000000000 +0200
+++ new/transactional-update-4.1.2/lib/Mount.hpp        2023-01-23 
14:31:20.000000000 +0100
@@ -18,7 +18,7 @@
 class Mount
 {
 public:
-    Mount(std::string mountpoint, unsigned long flags = 0);
+    Mount(std::string mountpoint, unsigned long flags = 0, bool umount = 
false);
     Mount(Mount&& other) noexcept;
     virtual ~Mount();
     std::string getFilesystem();
@@ -38,7 +38,7 @@
     std::string tabsource;
     std::string mountpoint;
     unsigned long flags;
-    std::string directoryCreated;
+    bool umount;
     struct libmnt_fs* findFS();
     struct libmnt_fs* getTabEntry();
     struct libmnt_fs* newFS();
@@ -48,14 +48,14 @@
 class BindMount : public Mount
 {
 public:
-    BindMount(std::string mountpoint, unsigned long flags = 0);
+    BindMount(std::string mountpoint, unsigned long flags = 0, bool umount = 
false);
     void mount(std::string prefix = "/") override;
 };
 
 class PropagatedBindMount : public BindMount
 {
 public:
-    PropagatedBindMount(std::string mountpoint, unsigned long flags = 0);
+    PropagatedBindMount(std::string mountpoint, unsigned long flags = 0, bool 
umount = false);
 };
 
 class MountList
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/transactional-update-4.1.0/lib/Overlay.cpp 
new/transactional-update-4.1.2/lib/Overlay.cpp
--- old/transactional-update-4.1.0/lib/Overlay.cpp      2022-10-26 
16:50:43.000000000 +0200
+++ new/transactional-update-4.1.2/lib/Overlay.cpp      2023-01-23 
14:31:20.000000000 +0100
@@ -115,7 +115,6 @@
     previousEtc->removeOption("workdir");
 
     string syncSource = string(previousOvl.upperdir.parent_path() / "sync" / 
"etc") + "/";
-    string rsyncExtraArgs;
     previousEtc->mount(previousOvl.upperdir.parent_path() / "sync");
     tulog.info("Syncing /etc of previous snapshot ", previousSnapId, " as base 
into new snapshot ", snapRoot);
 
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/transactional-update-4.1.0/lib/Snapshot/Snapper.cpp 
new/transactional-update-4.1.2/lib/Snapshot/Snapper.cpp
--- old/transactional-update-4.1.0/lib/Snapshot/Snapper.cpp     2022-10-26 
16:50:43.000000000 +0200
+++ new/transactional-update-4.1.2/lib/Snapshot/Snapper.cpp     2023-01-23 
14:31:20.000000000 +0100
@@ -7,7 +7,6 @@
 
 #include "Snapper.hpp"
 #include "Exceptions.hpp"
-#include "Log.hpp"
 #include "Util.hpp"
 #include <regex>
 
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/transactional-update-4.1.0/lib/Transaction.cpp 
new/transactional-update-4.1.2/lib/Transaction.cpp
--- old/transactional-update-4.1.0/lib/Transaction.cpp  2022-10-26 
16:50:43.000000000 +0200
+++ new/transactional-update-4.1.2/lib/Transaction.cpp  2023-01-23 
14:31:20.000000000 +0100
@@ -25,6 +25,8 @@
 #include <limits.h>
 #include <poll.h>
 #include <sched.h>
+#include <selinux/restorecon.h>
+#include <selinux/selinux.h>
 #include <signal.h>
 #include <sys/inotify.h>
 #include <sys/mount.h>
@@ -106,18 +108,13 @@
     // mount the snapshot directory on a temporary mount point
     char bindTemplate[] = "/tmp/transactional-update-XXXXXX";
     bindDir = mkdtemp(bindTemplate);
-    std::unique_ptr<BindMount> mntBind{new BindMount{bindDir, MS_PRIVATE}};
+    std::unique_ptr<BindMount> mntBind{new BindMount{bindDir, MS_PRIVATE, 
true}};
     mntBind->setSource(snapshot->getRoot());
     mntBind->mount();
 
     dirsToMount.push_back(std::make_unique<PropagatedBindMount>("/dev"));
     dirsToMount.push_back(std::make_unique<BindMount>("/var/log"));
 
-    std::vector<std::string> customDirs = config.getArray("BINDDIRS");
-    for (auto it = customDirs.begin(); it != customDirs.end(); ++it) {
-        dirsToMount.push_back(std::make_unique<BindMount>(*it));
-    }
-
     Mount mntVar{"/var"};
     if (mntVar.isMount()) {
         if (fs::is_directory("/var/lib/zypp"))
@@ -127,7 +124,41 @@
             
dirsToMount.push_back(std::make_unique<BindMount>("/var/lib/alternatives"));
         if (fs::is_directory("/var/lib/selinux"))
             
dirsToMount.push_back(std::make_unique<BindMount>("/var/lib/selinux"));
+        if (is_selinux_enabled()) {
+            // If packages installed files into /var (which is not allowed, 
but still happens), they will end
+            // up in the root file system, but will always be shadowed by the 
real /var mount. Due to that they
+            // also won't be relabelled at any time. During updates this may 
cause problems if packages try to
+            // access those leftover directories with wrong permissions, so 
they have to be relabelled manually...
+            BindMount selinuxVar("/var/lib/selinux", 0, true);
+            selinuxVar.mount(bindDir);
+            BindMount selinuxEtc("/etc/selinux", 0, true);
+            selinuxEtc.mount(bindDir);
+
+            // restorecon keeps open file handles, so execute it in a child 
process - umount will fail otherwise
+            pid_t childPid = fork();
+            if (childPid < 0) {
+                throw std::runtime_error{"Forking for SELinux relabelling 
failed: " + std::string(strerror(errno))};
+            } else if (childPid == 0) {
+                if (chroot(bindDir.c_str()) < 0) {
+                    tulog.error("Chrooting to " + bindDir + " for SELinux 
relabelling failed: " + std::string(strerror(errno)));
+                    _exit(errno);
+                }
+                if (selinux_restorecon("/var", SELINUX_RESTORECON_RECURSE | 
SELINUX_RESTORECON_VERBOSE | SELINUX_RESTORECON_IGNORE_DIGEST) < 0) {
+                    tulog.error("Relabelling of snapshot /var failed: " + 
std::string(strerror(errno)));
+                    _exit(errno);
+                }
+                _exit(0);
+            }
+            else {
+                int status;
+                waitpid(childPid, &status, 0);
+                if ((WIFEXITED(status) && WEXITSTATUS(status) != 0) || 
WIFSIGNALED(status)) {
+                    throw std::runtime_error{"SELinux relabelling failed."};
+                }
+            }
+        }
     }
+
     std::unique_ptr<Mount> mntEtc{new Mount{"/etc"}};
     if (mntEtc->isMount() && mntEtc->getFilesystem() == "overlay") {
         Overlay overlay = Overlay{snapshot->getUid()};
@@ -171,6 +202,14 @@
     if (BindMount{"/boot/writable"}.isMount())
         dirsToMount.push_back(std::make_unique<BindMount>("/boot/writable"));
 
+    std::vector<std::string> customDirs = config.getArray("BINDDIRS");
+    for (auto it = customDirs.begin(); it != customDirs.end(); ++it) {
+        if (fs::is_directory(*it))
+            dirsToMount.push_back(std::make_unique<BindMount>(*it));
+        else
+            tulog.info("Not bind mounting directory '" + *it + "' as it 
doesn't exist.");
+    }
+
     dirsToMount.push_back(std::make_unique<BindMount>("/.snapshots"));
 
     for (auto it = dirsToMount.begin(); it != dirsToMount.end(); ++it) {
@@ -276,7 +315,7 @@
     struct pollfd pfd = {inotifyFd, POLLIN, 0};
     ret = (poll(&pfd, 1, 500));
     if (ret == -1) {
-        throw std::runtime_error{"Polling inotify file descriptior failed: " + 
std::string(strerror(errno))};
+        throw std::runtime_error{"Polling inotify file descriptor failed: " + 
std::string(strerror(errno))};
     } else if (ret > 0) {
         numRead = read(inotifyFd, buf, bufLen);
         if (numRead == 0)
@@ -432,12 +471,33 @@
             (inotifyFd == 0 && fs::exists(getRoot() / "discardIfNoChange")))) {
         tulog.info("No changes to the root file system - discarding 
snapshot.");
 
-        // Even if the snapshot itself did not contain any changes, /etc may 
do so. Changes
-        // in /etc may be applied immediately, so merge them back into the 
running system.
+        // Even if the snapshot itself does not contain any changes, /etc may 
do so. If the new snapshot is a
+        // direct descendant of the currently running system, then merge the 
changes back into the currently
+        // running system directly and delete the snapshot. Otherwise merge it 
back into the previous overlay
+        // (using rsync instead of a plain copy to preserve xattrs).
         std::unique_ptr<Mount> mntEtc{new Mount{"/etc"}};
         if (mntEtc->isMount() && mntEtc->getFilesystem() == "overlay") {
-            Util::exec("rsync --archive --inplace --xattrs --acls --exclude 
'fstab' --delete --quiet '" + this->pImpl->bindDir + "/etc/' /etc");
+            std::filesystem::path targetRoot;
+            std::unique_ptr<Mount> previousEtc{new Mount("/etc", 0, true)};
+            if (pImpl->snapshotMgr->getCurrent() == 
Overlay{pImpl->snapshot->getUid()}.getPreviousSnapshotOvlId()) {
+                tulog.info("Merging changes in /etc into the running system.");
+                targetRoot = "/";
+            } else {
+                tulog.info("Merging changes in /etc into the previous 
snapshot.");
+
+                auto previousSnapId = 
Overlay{pImpl->snapshot->getUid()}.getPreviousSnapshotOvlId();
+                std::unique_ptr<Snapshot> previousSnapshot = 
pImpl->snapshotMgr->open(previousSnapId);
+                previousEtc->setTabSource(previousSnapshot->getRoot() / "etc" 
/ "fstab");
+
+                Overlay previousOvl{previousSnapId};
+                previousOvl.lowerdirs.back() = previousSnapshot->getRoot();
+                previousOvl.setMountOptionsForMount(previousEtc);
+                targetRoot = previousOvl.upperdir.parent_path() / "sync";
+                previousEtc->mount(targetRoot);
+            }
+            Util::exec("rsync --archive --inplace --xattrs --acls --exclude 
'fstab' --delete --quiet '" + this->pImpl->bindDir + "/etc/' " + 
targetRoot.native() + "/etc");
         }
+
         return;
     }
     if (fs::exists(getRoot() / "discardIfNoChange")) {
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' 
old/transactional-update-4.1.0/sbin/transactional-update.in 
new/transactional-update-4.1.2/sbin/transactional-update.in
--- old/transactional-update-4.1.0/sbin/transactional-update.in 2022-10-26 
16:50:43.000000000 +0200
+++ new/transactional-update-4.1.2/sbin/transactional-update.in 2023-01-23 
14:31:20.000000000 +0100
@@ -1209,10 +1209,14 @@
 fi
 
 if [ "${DO_STATUS}" -eq 1 ]; then
-    for snapshot in $(ls -d /.snapshots/*/ | cut -d '/' -f 3 | sort --reverse 
--numeric-sort); do
-       show_snapshot_status "/.snapshots/$snapshot/"
-       [ "${DO_STATUS_LAST}" -eq 1 ] && break
-    done
+    if [ "${EXPERIMENTAL_STATUS}" -eq 1 ]; then
+        for snapshot in $(ls -d /.snapshots/*/ | cut -d '/' -f 3 | sort 
--reverse --numeric-sort); do
+           show_snapshot_status "/.snapshots/$snapshot/"
+           [ "${DO_STATUS_LAST}" -eq 1 ] && break
+       done
+    else
+       echo "The status command is disabled by default as it is marked as 
experimental"
+    fi
     exit 0
 fi
 
@@ -1290,11 +1294,10 @@
     # Clean up old unused overlays
     if [ ${RO_ROOT} == "true" ]; then
        shopt -s nullglob
-       for overlay in /var/lib/overlay/[0-9]*/etc /var/lib/overlay/etc; do
+       for overlay in /var/lib/overlay/*; do
            if [ -e ${overlay} ] && ! grep -qs "${overlay}" 
/.snapshots/*/snapshot/etc/fstab{,.sys}; then
                log_info "Deleting unused overlay ${overlay}"
-               rm -rf "${overlay}"
-               rmdir --ignore-fail-on-non-empty "$(dirname "${overlay}")"
+               rm -r "${overlay}"
            fi
        done
        shopt -u nullglob

Reply via email to