systemctl: fix edit and cat verbs with --global flag (#39606)
The --global flag has been broken since commit
d77d42ed3a, which added a
blanket restriction on acquiring D-Bus connections when
arg_runtime_scope is RUNTIME_SCOPE_GLOBAL. This was done to prevent
crashes, but inadvertently broke legitimate use cases like 'systemctl
edit --global' and 'systemctl cat --global'.
The issue is that verb_edit() and verb_cat() were unconditionally
calling acquire_bus(), which triggers the restriction and fails with
"--global is not supported for this operation."
This commit fixes the issue by making bus acquisition conditional,
following the same pattern used in verb_enable():
- Only acquire the bus when install_client_side() returns NO (i.e., for
system and user scopes)
- For client-side operations (--global, --root, etc.), skip bus
acquisition and use mangle_names() instead of expand_unit_names()
- Update find_paths_to_edit() and verb_cat() to handle NULL bus by
forcing client-side path lookups
- Skip bus-dependent checks (unit_is_masked, need_daemon_reload) when
bus is NULL
This allows both 'systemctl edit --global' and 'systemctl cat --global'
to work correctly by performing all operations client-side without
requiring a connection to the system or user manager.
Fixes #31272
This commit is contained in:
@@ -573,4 +573,48 @@ systemctl daemon-reload
|
||||
systemctl enable --now test-WantedBy.service || :
|
||||
systemctl daemon-reload
|
||||
|
||||
# Test systemctl edit --global and systemctl cat --global (issue #31272)
|
||||
GLOBAL_UNIT_NAME="systemctl-test-$RANDOM.service"
|
||||
GLOBAL_MASKED_UNIT="systemctl-test-masked-$RANDOM.service"
|
||||
|
||||
# Test 1: Create a new global user unit with --force and --runtime
|
||||
systemctl edit --global --runtime --stdin --full --force "$GLOBAL_UNIT_NAME" <<EOF
|
||||
[Unit]
|
||||
Description=Test global unit
|
||||
|
||||
[Service]
|
||||
ExecStart=/bin/true
|
||||
EOF
|
||||
|
||||
# Verify the unit file was created in /run/systemd/user/
|
||||
test -f "/run/systemd/user/$GLOBAL_UNIT_NAME"
|
||||
|
||||
# Test 2: Read the global unit with systemctl cat --global
|
||||
systemctl cat --global "$GLOBAL_UNIT_NAME" | grep -q "ExecStart=/bin/true"
|
||||
|
||||
# Test 3: Edit existing global unit (add a drop-in)
|
||||
systemctl edit --global --runtime --stdin "$GLOBAL_UNIT_NAME" <<EOF
|
||||
[Service]
|
||||
Environment=TEST=value
|
||||
EOF
|
||||
|
||||
# Verify drop-in was created
|
||||
test -f "/run/systemd/user/$GLOBAL_UNIT_NAME.d/override.conf"
|
||||
systemctl cat --global "$GLOBAL_UNIT_NAME" | grep -q "Environment=TEST=value"
|
||||
|
||||
# Test 4: Create a masked global unit in /run/
|
||||
mkdir -p /run/systemd/user
|
||||
ln -sf /dev/null "/run/systemd/user/$GLOBAL_MASKED_UNIT"
|
||||
|
||||
# Test 5: Verify cat shows it's masked
|
||||
systemctl cat --global "$GLOBAL_MASKED_UNIT" 2>&1 | grep -q "masked"
|
||||
|
||||
# Test 6: Verify edit refuses to edit masked unit
|
||||
(! systemctl edit --global --runtime --stdin --full "$GLOBAL_MASKED_UNIT" </dev/null 2>&1) | grep -q "masked"
|
||||
|
||||
# Cleanup global test units
|
||||
rm -f "/run/systemd/user/$GLOBAL_UNIT_NAME"
|
||||
rm -rf "/run/systemd/user/$GLOBAL_UNIT_NAME.d"
|
||||
rm -f "/run/systemd/user/$GLOBAL_MASKED_UNIT"
|
||||
|
||||
touch /testok
|
||||
|
||||
Reference in New Issue
Block a user