Public bug reported:

## Summary

On Ubuntu 24.04.3 LTS (noble) with systemd 255.4-1ubuntu8.17, when the
last SSH session of a user with Linger=yes (loginctl enable-linger) is
closed, logind's garbage collection wrongly tears down the user domain:
[email protected] is SIGKILLed (Main process exited, code=killed,
status=9/KILL), [email protected] is stopped,
user-1000.slice is removed, and all user-domain processes (tmux server,
long-running tasks) are killed. This contradicts documented behavior:
with linger enabled the user manager must survive the last session.

## Environment

- Ubuntu 24.04.3 LTS (noble), kernel 6.8.0-137-generic (KVM VM)
- systemd 255.4-1ubuntu8.17 (latest from apt, no updates available)
- Reproduced 6 times on the same day, 100% hit rate after a leftover zombie 
session ended
- Linger=yes confirmed (loginctl show-user lou -p Linger = yes; D-Bus property 
true); KillUserProcesses=no (default)

## Steps to reproduce

1. loginctl enable-linger lou
2. SSH in, run: systemd-run --scope --user tmux new -s pi (user-domain tmux), 
run any process inside tmux
3. Disconnect SSH (the last session)
4. Wait 1-3 minutes (time for sshd to notice the half-open TCP disconnect)
5. Observe: [email protected] SIGKILLed, tmux/processes all dead, "tmux ls" = 
no server running

Note: if any other session of the user exists (even a zombie session
scope still holding processes), GC is short-circuited by "if
(u->sessions) return false;". In this case a leftover zombie session
protected the user domain for 3 days; after it ended on Aug 11, every
last-session logout triggered the bug (100%).

## Log evidence

### Normal case (07:09:52, zombie session present, user domain survives)
Aug 11 07:09:52 sshd[2850661]: pam_unix(sshd:session): session closed for user 
lou
Aug 11 07:09:52 systemd[1]: session-5664.scope: Deactivated successfully.
Aug 11 07:09:52 systemd-logind[700]: Session 5664 logged out. Waiting for 
processes to exit.
Aug 11 07:09:52 systemd-logind[700]: Removed session 5664.
(no further logind action on user domain)

### Buggy case (08:00:35, last session ends, user domain destroyed)
Aug 11 08:00:35 sshd[3163780]: pam_unix(sshd:session): session closed for user 
lou
Aug 11 08:00:35 systemd[1]: session-5183.scope: Deactivated successfully.
Aug 11 08:00:35 systemd[1]: [email protected]: Main process exited, 
code=killed, status=9/KILL
Aug 11 08:00:35 systemd[1]: [email protected]: Killing process 3165504 (pi) 
with signal SIGKILL.
Aug 11 08:00:35 systemd[1]: [email protected]: Killing process 3175333 (python) 
with signal SIGKILL.
Aug 11 08:00:35 systemd[1]: [email protected]: Failed to kill control group 
/user.slice/user-1000.slice/[email protected], ignoring: Invalid argument
Aug 11 08:00:35 systemd[1]: [email protected]: Failed with result 'signal'.
Aug 11 08:00:35 systemd[1]: [email protected]: Unit process 3165504 (pi) 
remains running after unit stopped.
Aug 11 08:00:35 systemd-logind[700]: Removed session 5183.
Aug 11 08:00:35 systemd[1]: session-5715.scope: Deactivated successfully.
Aug 11 08:00:35 systemd-logind[700]: Session 5715 logged out. Waiting for 
processes to exit.
Aug 11 08:00:35 systemd[1]: Stopping [email protected] - User 
Runtime Directory /run/user/1000...
Aug 11 08:00:35 systemd-logind[700]: Removed session 5715.
Aug 11 08:00:35 systemd[1]: Stopped [email protected]
Aug 11 08:00:35 systemd[1]: Removed slice user-1000.slice - User Slice of UID 
1000.

### Second reproduction (10:03:16, after reboot, still triggers on 8.17)
Aug 11 10:03:16 sshd[6788]: pam_unix(sshd:session): session closed for user lou
Aug 11 10:03:16 systemd-logind[766]: Session 3 logged out. Waiting for 
processes to exit.
Aug 11 10:03:16 systemd[1]: [email protected]: Main process exited, 
code=killed, status=9/KILL
Aug 11 10:03:16 systemd[1]: [email protected]: Killing process 9797 (python) 
with signal SIGKILL.
Aug 11 10:03:16 systemd[1]: [email protected]: Failed to kill control group 
/user.slice/user-1000.slice/[email protected], ignoring: Invalid argument
Aug 11 10:03:16 systemd[1]: [email protected]: Unit process 9797 (python) 
remains running after unit stopped.
Aug 11 10:03:16 systemd[1]: session-3.scope: Deactivated successfully.
Aug 11 10:03:16 systemd[1]: Stopping [email protected]
Aug 11 10:03:16 systemd-logind[766]: Removed session 3.
Aug 11 10:03:16 systemd[1]: Removed slice user-1000.slice - User Slice of UID 
1000.

## Root cause (v255 source)

user_may_gc() in src/login/logind-user.c (v255):

bool user_may_gc(User *u, bool drop_not_started) {
        if (u->sessions)
                return false;                       /* has sessions -> no GC */

        if (u->last_session_timestamp != USEC_INFINITY) {
                usec_t user_stop_delay = user_get_stop_delay(u);
                if (user_stop_delay == USEC_INFINITY)
                        return false;
                if (user_stop_delay > 0 &&
                    now(CLOCK_MONOTONIC) < usec_add(u->last_session_timestamp, 
user_stop_delay))
                        return false;               /* within stop delay window 
-> no GC */
        }

        /* linger protection */
        if (user_check_linger_file(u) > 0 && user_unit_active(u))
                return false;

        return true;                                /* GC -> user_stop() -> 
stop user domain */
}

The linger protection depends on user_unit_active(u), which queries
systemd[1] over D-Bus for the active state of [email protected] / user-
[email protected] / user-1000.slice:

static bool user_unit_active(User *u) {
        FOREACH_STRING(i, u->service, u->runtime_dir_service, u->slice) {
                r = manager_unit_is_active(u->manager, i, &error);
                if (r < 0)
                        log_debug_errno(r, "Failed to determine whether unit 
'%s' is active, ignoring: %s", ...);
                if (r != 0)
                        return true;
        }
        return false;
}

- When the D-Bus query fails (r<0), only a debug log is emitted and the unit is 
treated as "not active" -> linger protection silently fails -> GC proceeds
- Same when the query succeeds but reports "not active" (transient 
deactivating/failed states)
- The query happens inside the last-session teardown race window and fails 
sporadically -> non-deterministic behavior (6 hits one day, while 4 adjacent 
disconnects did not trigger, consistent with a race)

user_stop() -> user_stop_service() stops [email protected]
(StopWhenUnneeded=yes) -> [email protected] stopped via Requires= dependency
-> KillMode=mixed ends in SIGKILL of the whole user domain.

## Upstream status

- Similar regression area fixed upstream in v256: PR #30884 (gc_mode 
regression, see issue #33488)
- v256.3 (2024-07-19) fixes: PR #33786 (incl. "logind-user: take gc_mode into 
account when reporting user state", "logind-dbus: set gc_mode to USER_GC_BY_PIN 
when disable linger")
- v255-stable does not contain these fixes; Ubuntu 24.04's 255.4-1ubuntu8.17 
only carries security patches (per changelog), apt has no updates

## Impact

- Real user processes killed silently on last session logout 
(tmux/screen/pi/long-running jobs), despite Linger=yes and documented behavior 
(man logind.conf / man loginctl)
- Secondary anomalies: "Failed to kill control group ... Invalid argument" 
(cgroup.kill EINVAL) + "Unit process ... remains running after unit stopped"

## Workaround (verified)

# /etc/systemd/logind.conf.d/keep-user.conf
[Login]
UserStopDelaySec=infinity

systemctl restart systemd-logind to apply. Documented semantics: per-
user service never terminated after first login, until system shutdown.
Verified working; user domain no longer GC'd.

## Requested fix

Please backport the upstream v256.3 fixes (or an equivalent v255
version: the linger protection in user_may_gc() should not depend on a
fallible D-Bus query) to Ubuntu 24.04's systemd 255.4-1ubuntu8.x.

** Affects: systemd (Ubuntu)
     Importance: Undecided
         Status: New

-- 
You received this bug notification because you are a member of Ubuntu
Bugs, which is subscribed to Ubuntu.
https://bugs.launchpad.net/bugs/2163239

Title:
  systemd 255.4-1ubuntu8.17: logind GC kills [email protected] on last
  SSH session logout despite Linger=yes (regression fixed upstream in
  v256.3 PR #33786, please backport)

To manage notifications about this bug go to:
https://bugs.launchpad.net/ubuntu/+source/systemd/+bug/2163239/+subscriptions


-- 
ubuntu-bugs mailing list
[email protected]
https://lists.ubuntu.com/mailman/listinfo/ubuntu-bugs

Reply via email to