Fix correctness bugs across the helper scripts
panama-osd read the wrong brightnessctl field, showing the hardware max instead of a percentage on any backlight device. panama-doctor called three sibling scripts by bare name with nothing on PATH, making three health checks permanently and falsely report broken; its repair actions also reused the short probe timeout, so a slow-but- successful restart was reported as failed. panama-wifi-qr left the cleartext passphrase temp file behind on its failure path (the RETURN trap doesn't fire on exit), and its nmcli parsing broke on connection names containing a colon or backslash -- verified against a real NetworkManager profile. panama-power-profile's set command always returned success regardless of whether the write actually took. panama-keyring's daemon-origin check picked whichever gnome-keyring-daemon process happened to enumerate first in /proc, defeating the exact dual-daemon scenario it exists to detect; it now resolves the PID that actually owns the Secret Service D-Bus name. gnf aborted before running a firmware update whenever the metadata was already current (a non-error exit under set -e), and its flatpak update lacked the -y its own docs promise. Claude-Session: https://claude.ai/code/session_01E6TJUAh41HaP25MVHWkhRZ
This commit is contained in:
@@ -39,13 +39,36 @@ import re
|
||||
import sys
|
||||
|
||||
|
||||
def daemon_origin():
|
||||
"""Whether the running secrets daemon came from PAM or from D-Bus activation.
|
||||
def secrets_name_owner_pid():
|
||||
"""PID currently owning the org.freedesktop.secrets D-Bus name, if any.
|
||||
|
||||
A D-Bus-activated daemon is the signature of the crash-and-replace case
|
||||
above: it is the one that cannot have the login password. PAM's daemon lives
|
||||
outside the app slice, so the cgroup tells the two apart.
|
||||
This is the only reliable way to identify which daemon actually answers
|
||||
Secret Service calls right now.
|
||||
"""
|
||||
try:
|
||||
import gi
|
||||
|
||||
gi.require_version("Gio", "2.0")
|
||||
from gi.repository import Gio, GLib
|
||||
|
||||
bus = Gio.bus_get_sync(Gio.BusType.SESSION, None)
|
||||
result = bus.call_sync(
|
||||
"org.freedesktop.DBus",
|
||||
"/org/freedesktop/DBus",
|
||||
"org.freedesktop.DBus",
|
||||
"GetConnectionUnixProcessID",
|
||||
GLib.Variant("(s)", ("org.freedesktop.secrets",)),
|
||||
GLib.VariantType("(u)"),
|
||||
Gio.DBusCallFlags.NONE,
|
||||
-1,
|
||||
None,
|
||||
)
|
||||
return result.unpack()[0]
|
||||
except Exception: # noqa: BLE001 - no name owner is a legitimate state
|
||||
return None
|
||||
|
||||
|
||||
def any_keyring_daemon_running():
|
||||
try:
|
||||
for pid in os.listdir("/proc"):
|
||||
if not pid.isdigit():
|
||||
@@ -55,19 +78,46 @@ def daemon_origin():
|
||||
cmdline = handle.read().decode("utf-8", "replace")
|
||||
except OSError:
|
||||
continue
|
||||
if "gnome-keyring-daemon" not in cmdline:
|
||||
continue
|
||||
try:
|
||||
with open(f"/proc/{pid}/cgroup", "r") as handle:
|
||||
cgroup = handle.read()
|
||||
except OSError:
|
||||
return "unknown"
|
||||
if re.search(r"dbus-.*org\.freedesktop\.secrets", cgroup):
|
||||
return "dbus"
|
||||
return "pam"
|
||||
if "gnome-keyring-daemon" in cmdline:
|
||||
return True
|
||||
except OSError:
|
||||
pass
|
||||
return "none"
|
||||
return False
|
||||
|
||||
|
||||
def daemon_origin():
|
||||
"""Whether the running secrets daemon came from PAM or from D-Bus activation.
|
||||
|
||||
A D-Bus-activated daemon is the signature of the crash-and-replace case
|
||||
above: it is the one that cannot have the login password. PAM's daemon lives
|
||||
outside the app slice, so the cgroup tells the two apart.
|
||||
|
||||
A machine can have two gnome-keyring-daemon processes at once -- a
|
||||
lingering PAM one alongside its D-Bus-activated replacement -- so which
|
||||
process this reports on matters: it must be the one that actually owns
|
||||
org.freedesktop.secrets right now, not merely the first one /proc happens
|
||||
to enumerate.
|
||||
"""
|
||||
owner_pid = secrets_name_owner_pid()
|
||||
if owner_pid is None:
|
||||
return "unknown" if any_keyring_daemon_running() else "none"
|
||||
|
||||
try:
|
||||
with open(f"/proc/{owner_pid}/cmdline", "rb") as handle:
|
||||
cmdline = handle.read().decode("utf-8", "replace")
|
||||
except OSError:
|
||||
return "unknown"
|
||||
if "gnome-keyring-daemon" not in cmdline:
|
||||
return "unknown"
|
||||
|
||||
try:
|
||||
with open(f"/proc/{owner_pid}/cgroup", "r") as handle:
|
||||
cgroup = handle.read()
|
||||
except OSError:
|
||||
return "unknown"
|
||||
if re.search(r"dbus-.*org\.freedesktop\.secrets", cgroup):
|
||||
return "dbus"
|
||||
return "pam"
|
||||
|
||||
|
||||
def load_service():
|
||||
|
||||
Reference in New Issue
Block a user