Bug#1061094: mmdebstrap vs. apt -o DPkg::Inhibit-Shutdown

2024-01-18 Thread David Kalnischkies
tl;dr: Fine by me, just some explaining comments for the record.

On Thu, Jan 18, 2024 at 12:54:45PM +1100, Trent W. Buck wrote:
> This MIGHT affect someone else doing "apt -o Dir=⋯" to do custom installs, but
> everything I can think of offhand is a wrapper around debootstrap, except for
> https://github.com/openSUSE/obs-build/blob/master/obs-docker-support#L118

This one sets different sources.list files, doesn't change Dir and is
hence still effected by the inhibit… except that this probably runs
somewhere in docker, so likely without dbus, systemd and what not.


> Everything I can find seems to set e.g. Dir::Etc rather than Dir itself.
> 
> https://codesearch.debian.net/search?q=apt.*-o.*Dir%5B%5E%3A%5D
> https://github.com/search?q=%2Fapt.*-o.*Dir%2F=code  (requires 
> Microsoft account, requires javascript)

Just for the record: To find more users you would need to look for
RootDir as well, which was used heavily before Dir. Looking for scripts
setting these options on the command line is probably not catching a lot
of users as command line parsing happens pretty late – after config
files are read – so setting {Root,}Dir is usually done in a config file
given via the APT_CONFIG environment variable.

Case in point: Our very own test cases do something akin to chrootless
mode of mmdebstrap with APT_CONFIG and Dir … and now I wonder how often
those tests inhibit and release the block on shutdown. I guess I never
tried to shutdown while running our tests. ☺

Also, as this is libapt, this isn't apt specific, could potentially be
used via apt-get, aptitude, python-apt, libapt-perl, synaptics, your run
of the mile software center, … its just increasingly unlikely.

A usecase I could imagine is someone trying to recover his main system
from a live CD. If your main system is sufficiently broken that
chrooting into it doesn't really work you could operate on it from the
outside similar to mmdebstrap (after all, the to be bootstrapped system
is sufficiently broken… given it doesn't really exist yet).


Anyway, this is a relatively new safeguard (60cc44d160 – April 2019)
nobody should really hard-depend on: Having it inhibited for too many
or for too few by default isn't that big of a problem and if someone
cares either way they can always set the option explicitly.

Given it is mainly supposed to avoid accidents for users who don't
interact with apt directly Dir == "/" is probably the closest we can
be to a sensible default value for the inhibition here if we ignore
that ideally the front ends would do the inhibition instead of our
low-level library, but that ship sailed…


Best regards

David Kalnischkies


signature.asc
Description: PGP signature


Bug#1061094: mmdebstrap vs. apt -o DPkg::Inhibit-Shutdown

2024-01-17 Thread Trent W. Buck
Package: apt
Version: 2.6.1
Severity: wishlist

I'm creating this bug so there's a bug number I can link to.
We discussed it on #debian-apt around 2024-01-16 08:54:47+00:00.

I noticed that since 2023-10-10, mmdebstrap triggers these errors:

2023-10-10T15:53:32+1100 hera polkitd[2696604]:
Error evaluating admin rules:
Error: Helper exited with non-zero exit status 1,
   stdout=`',
   stderr=`pkla-check-authorization: Invalid user `10': No UNIX 
user with name 10: Success
  (pkla-check-authorization:3461602): GLib-GObject-CRITICAL 
**: 15:53:32.183: g_object_unref: assertion 'G_IS_OBJECT (object)' failed'

I initially thought it was a faulty postinst, but
after several hours of digging, I managed to narrow it down:

bash5$ journalctl -o short-iso -u polkit --grep='Error evaluating admin 
rules' -fn0 &
bash5$ sudo dbus-monitor --system --pcap | tshark -r- -Y 'dbus.interface == 
"org.freedesktop.login1.Manager"' &

bash5$ mmdebstrap bookworm /dev/null --quiet
   11  24.706215  :1.1955 → org.freedesktop.login1 D-Bus 246 Inhibit() 
@ /org/freedesktop/login1
2024-01-18T10:36:10+1100 hera polkitd[1035]: Error evaluating admin rules: 
Error: Helper exited with non-zero exit status 1, stdout=`', 
stderr=`pkla-check-authorization: Invalid user `10': No UNIX user with name 
10: Success

 
(pkla-check-authorization:874223): GLib-GObject-CRITICAL **: 10:36:10.673: 
g_object_unref: assertion 'G_IS_OBJECT (object)' failed
 '
   50  37.507789  :1.1956 → org.freedesktop.login1 D-Bus 246 Inhibit() 
@ /org/freedesktop/login1
2024-01-18T10:36:23+1100 hera polkitd[1035]: Error evaluating admin rules: 
Error: Helper exited with non-zero exit status 1, stdout=`', 
stderr=`pkla-check-authorization: Invalid user `10': No UNIX user with name 
10: Success

 
(pkla-check-authorization:875795): GLib-GObject-CRITICAL **: 10:36:23.475: 
g_object_unref: assertion 'G_IS_OBJECT (object)' failed
 '

bash5$ mmdebstrap bookworm /dev/null --quiet 
'--aptopt=DPKG::Inhibit-Shutdown 0;'

The relevant code is here:


https://salsa.debian.org/apt-team/apt/-/blob/2.6.1/apt-pkg/deb/dpkgpm.cc?ref_type=tags#L1508-1509

What is happening is this:

* "apt install foo" starts
* apt/dpkg --dbus--> systemd, "please inhibit (refuse to) shutdown/reboot 
during installs"
* systemd --dbus--> polkit, "user 1234 asked to inhibit shutdowns, is that 
allowed?"
* polkit --dbus--> systemd, "user 1234 doesn't exist, therefore no"
* systemd ignores the request (maybe signalling an error?)
* apt/dpkg continues on without any real issue

This issue DOES NOT affect normal host usage of apt, because
"sudo apt install x" runs the host's apt, with a normal host-wide user that 
polkit can see.
The inhibit works there (assuming pid1 is systemd, I guess).

This issue DOES NOT affect normal chroots, because
"sudo chroot /target apt install x" cannot "see" the un-chrooted dbus, so
the inhibit attempt fails before reaching systemd/polkit.

This issue affects mmdebstrap, because mmdebstrap run's the host's apt,
with an unshare'd userns such that apt thinks the user is root, and
systemd/polkit thinks it's a transient UID with no record in nss passwd table.

(systemd DynamicUser= units and systemd-nspawn containers have similar 
transient UIDs, and
in those cases "apt install libnss-systemd libnss-machines" provides nss passwd 
entries.)



Julian suggested this change:

-if (_config->FindB("DPkg::Inhibit-Shutdown", true))
+if (_config->FindB("DPkg::Inhibit-Shutdown", _config->FindDir("Dir", 
"/") == "/"))

I like this plan.

This will fix the mmdebstrap case, because mmdebstrap runs something like 
"unshare ⋯ apt -o Dir=/tmp/mmdebstrap.XX".
(No one cares if an mmdebstrap image build is "corrupted" by a halt/reboot - 
you just rerun mmdebstrap and make a fresh one.)

This should NOT affect "sudo apt install x" or "sudo chroot /target apt install 
x", because
in both cases apt is operating on / (either the host's /, or the chroot's /).

This should NOT affect debootstrap because it only runs dpkg, not apt (I think).

This MIGHT affect someone else doing "apt -o Dir=⋯" to do custom installs, but
everything I can think of offhand is a wrapper around debootstrap, except for
https://github.com/openSUSE/obs-build/blob/master/obs-docker-support#L118

Everything I can find seems to set e.g. Dir::Etc rather than Dir itself.

https://codesearch.debian.net/search?q=apt.*-o.*Dir%5B%5E%3A%5D
https://github.com/search?q=%2Fapt.*-o.*Dir%2F=code  (requires 
Microsoft account, requires javascript)

PS: general details about the "inihibit" functionality are here: