logind, seats, sessions, and login

Explain sessions, seats and access coordination between logind and clients.

14 min readChapter 112 of 168Intermediate → advanced
In this chapter

Before you start#

Review userspace services, D-Bus messages and descriptors, user managers, and device lifetimes. This chapter reads systemd v256 commit 5c79cdec10a547a866764a66e1e14898112a00cd; the historical Linux v6.12 source baseline is independent. No host session, seat, device, inhibitor or power state is changed.

Learning goals#

Distinguish logind, PAM, the system manager and a display manager; trace selected session creation and teardown paths; and reason about session control, device descriptors and inhibitor lifetimes. Analyze disconnect and pause races with a supplied model rather than invoking host control methods.

Source walkthrough#

Session objects and device lifetimes
Session objects and device lifetimesUser: Can have multiple sessions. → Session: Tracks leader, event sources and lifecycle. (owns user association). Seat: May associate local sessions and devices. → Session: Tracks leader, event sources and lifecycle. (optional seat association). User: Can have multiple sessions. → Device FD: Has process-local references and device-specific pause behavior. (controller may receive FD). Seat: May associate local sessions and devices. → Device FD: Has process-local references and device-specific pause behavior. (device belongs to seat context)owns user associationoptional seatassociationcontroller may receiveFDdevice belongs to seatcontextUserCan have multiple sessions.SeatMay associate local sessionsand devices.SessionTracks leader, event sourcesand lifecycle.Device FDHas process-local referencesand device-specific pausebehavior.
UserCan have multiple sessions.
SessionTracks leader, event sources and lifecycle.
SeatMay associate local sessions and devices.
SessionTracks leader, event sources and lifecycle.
UserCan have multiple sessions.
Device FDHas process-local references and device-specific pause behavior.
SeatMay associate local sessions and devices.
Device FDHas process-local references and device-specific pause behavior.
Read the text version
  • User: Can have multiple sessions. → Session: Tracks leader, event sources and lifecycle. (owns user association)
  • Seat: May associate local sessions and devices. → Session: Tracks leader, event sources and lifecycle. (optional seat association)
  • User: Can have multiple sessions. → Device FD: Has process-local references and device-specific pause behavior. (controller may receive FD)
  • Seat: May associate local sessions and devices. → Device FD: Has process-local references and device-specific pause behavior. (device belongs to seat context)
Conceptual model. A conceptual object and descriptor map, not a captured login; sessions can be remote or seatless.

systemd-logind is a userspace service that tracks users, sessions and seats under its configuration. A session represents a login or similar scope; a user can have more than one session. A seat groups a set of local devices and sessions according to policy and system configuration. Remote, headless and non-graphical sessions can exist without an active local graphical seat. The Manager, User, Seat and Session objects are distinct systemd data structures with references and state; a display manager is another program, and system PID 1 is not identical to logind.

The following exact excerpt from systemd v256 src/login/logind-dbus.c, method_create_session, is LGPL-2.1-or-later under its SPDX notice. The message-read arguments and later call are omitted:

c
        if (r < 0)
                return r;

        return create_session(

The preceding code reads a typed set of fields from the incoming bus message, including UID, leader, session type, class, seat and other metadata. A negative read result returns before session creation is called. The message, caller credentials, userdata manager context and sd_bus_error have their own lifetime and ownership rules; the method cannot safely treat arbitrary client-supplied fields as authenticated authority without the surrounding checks. The later create_session path is conditional on validation, existing state, authorization and resource availability. The excerpt is a source-reading branch, not a captured D-Bus request.

The next exact excerpt from v256 src/login/logind-session.c, session_stop, is also LGPL-2.1-or-later. Earlier state checks and later seat and FIFO handling are omitted:

c
        s->timer_event_source = sd_event_source_unref(s->timer_event_source);
        s->leader_pidfd_event_source = sd_event_source_unref(s->leader_pidfd_event_source);

The session drops references to its timer and leader-pidfd event sources as teardown begins. This prevents those registrations from being treated as indefinitely live session resources, subject to the event library's lifecycle rules. The surrounding code rejects a stale session without a user, returns early for an unstarted or already stopping session, removes seat and FIFO associations, requests scope stopping and marks the session stopping. A session object can still need finalization after that request. Unrefing an event source is not proof that every external application has exited.

Login actors and lifelines#

PAM is a framework through which a login application invokes configured authentication, account, credential and session modules. A display manager or remote login service supplies a login flow; it is not itself the kernel or PID 1. On systems configured to use pam_systemd, its PAM session handling registers the session with logind and establishes associated session state; the exact PAM stack, authentication method, authorization and ordering depend on distribution and local configuration. See the pinned pam_systemd manual and implementation. The exact PAM stack, authentication method, authorization and ordering depend on the distribution and local configuration. This chapter does not authenticate anyone, inspect a PAM configuration or assume every login uses this module.

A session can have a leader process, UID, class, type and optional seat relationship. logind may coordinate a session scope, user runtime directory and per-user manager with the system manager under the applicable configuration. A returned file descriptor or FIFO-based lifeline can represent a session relationship: its lifetime matters because closing the last relevant reference can signal that the session should be released under the implementation's rules. An FD is not a magic process-global ownership token; duplicated descriptors and inherited copies can keep a reference open longer than intended. Conversely, a bus disconnect or leader exit can occur before all application cleanup has finished.

A per-user manager, often associated with a user@UID.service instance in systemd-based deployments, supervises user units under that user's authority. It is not logind and it is not a replacement for the system manager. A user bus, runtime directory and graphical session are related components but are not guaranteed on every machine or login. Lingering can keep a user manager available after a login session ends when enabled. KillUserProcesses= and related configuration affect session process cleanup under documented conditions; do not turn one configured policy into a universal claim that every process dies immediately on logout.

The v256 logind-dbus.c contains the selected creation method and its validation path. The separate logind-session.c implements state and teardown. A successful method response is not proof that a graphical compositor started or that all devices are ready. A failure to create a scope, allocate an object or validate credentials can leave a different partial path that must release its acquired references and report an error.

Seat control and device descriptors#

A session controller can request control of a session and, subject to logind policy, request access to eligible devices. TakeControl and TakeDevice are D-Bus operations with their own permissions, state and failure paths. For the documented device API, TakeDevice returns a descriptor plus a paused flag; PauseDevice/PauseDeviceComplete and ResumeDevice describe the handoff protocol. A returned device FD gives the receiving process a kernel descriptor reference; it does not grant arbitrary authority over all devices on the seat. A controller can be paused or disconnected, and it must follow the applicable pause, acknowledgement, resume and release protocol. See the pinned login1 interface documentation. A missing local seat or a denied device request is a normal possible result, especially for a remote or headless session.

The pinned src/login/logind-session-device.c has distinct handling for device types. Selected code uses DRM master operations for appropriate DRM devices and input-device revocation mechanisms for appropriate input devices. These mechanisms do not mean that every character device can be revoked in the same way, that every driver supports identical semantics, or that closing a D-Bus connection magically closes all independent copies of an open file. A resume can deliver or reactivate an appropriate descriptor according to the device and protocol path; clients must discard stale assumptions and handle failure.

In src/login/logind-session-device.c, session_device_stop, v256, LGPL-2.1-or-later under its SPDX notice (the start of the switch and the unknown-type branch omitted):

c
        case DEVICE_TYPE_DRM:
                if (sd->fd < 0) {
                        log_error("Failed to de-activate DRM fd, as the fd was lost (maybe logind restart went wrong?)");
                        return;
                }

                /* On DRM devices we simply drop DRM-Master but keep it open.
                 * This allows the user to keep resources allocated. The
                 * CAP_SYS_ADMIN restriction to DRM-Master prevents users from
                 * circumventing this. */
                sd_drmdropmaster(sd->fd);
                break;

        case DEVICE_TYPE_EVDEV:
                /* Revoke access on evdev file-descriptors during deactivation.
                 * This will basically prevent any operations on the fd and
                 * cannot be undone. Good side is: it needs no CAP_SYS_ADMIN
                 * protection this way. */
                sd_eviocrevoke(sd->fd);
                break;

The two branches have different effects. The DRM branch drops DRM master and keeps the file open so that resources stay allocated. The evdev branch calls EVIOCREVOKE, which the comment says prevents any operation on that file and cannot be undone. The excerpt does not show what happens to duplicate descriptors held by other processes.

Deactivation by device type
DRM
Drops DRM master and keeps the file open so resources stay allocated.
evdev
Calls EVIOCREVOKE on the file, which the comment says cannot be undone.
Other types
Fall through to a branch with no synchronization.
Duplicates
Each process copy is its own reference; this branch does not enumerate them.
Source map. A source map of session_device_stop branches in v256, not a captured revocation test; kernel drivers decide the effective result.

Consider a synthetic session S controlled by process C. At T0 the session is active and C receives descriptor 8 for an eligible device; C duplicates it as descriptor 9. Both descriptors refer to an underlying open-file description under the usual descriptor-duplication model. At T1 a seat switch leads to a pause request. At T2 C stops using the device and acknowledges the pause under the applicable protocol. At T3 the session loses control or logs out, and logind begins its own device and session cleanup. A duplicate FD in C has its own process-table lifetime; whether its operations are revoked or fail depends on the particular device and revocation mechanism. Never infer universal continued access or universal revocation from this model.

In the same file, session_device_pause_all, v256, LGPL-2.1-or-later under its SPDX notice, stops each active device and then sends a notification:

c
void session_device_pause_all(Session *s) {
        SessionDevice *sd;

        assert(s);

        HASHMAP_FOREACH(sd, s->devices) {
                if (!sd->active)
                        continue;

                session_device_stop(sd);
                session_device_notify(sd, SESSION_DEVICE_PAUSE);
        }
}

The order is a local stop first and a notification second. The controller is told about the pause after logind has already dropped DRM master or revoked the evdev file. This is only logind's side of the handshake: the excerpt does not show the controller acknowledgment or whether the controller has stopped using its own duplicate descriptors.

Take, pause and resume a device
Take, pause and resume a device1. Controller to logind: TakeDevice(major, minor). 2. logind to Controller (return): fd and inactive flag. 3. logind to Device file: stop: drop DRM master or revoke evdev. 4. logind to Controller: PauseDevice signal. 5. Controller to logind: PauseDeviceComplete(major, minor). 6. logind to Controller: ResumeDevice(major, minor, fd) signal.ControllerlogindDevice fileTakeDevice(major, minor)fd and inactive flagstop: drop DRM master orrevoke evdevPauseDevice signalPauseDeviceComplete(major, minor)ResumeDevice(major,minor, fd) signal
  1. Controllerlogind

    TakeDevice(major, minor)

  2. logindController

    Return. fd and inactive flag

  3. logindDevice file

    stop: drop DRM master or revoke evdev

  4. logindController

    PauseDevice signal

  5. Controllerlogind

    PauseDeviceComplete(major, minor)

  6. logindController

    ResumeDevice(major, minor, fd) signal

Time runs downward. Dashed arrows show returns.

Read the text version
  1. Controller → logind: TakeDevice(major, minor)
  2. logind → Controller (return): fd and inactive flag
  3. logind → Device file: stop: drop DRM master or revoke evdev
  4. logind → Controller: PauseDevice signal
  5. Controller → logind: PauseDeviceComplete(major, minor)
  6. logind → Controller: ResumeDevice(major, minor, fd) signal
Conceptual model. A teaching sequence based on the v256 login1 interface and session_device_stop, not a captured D-Bus trace; the controller reply does not prove every duplicate is idle.

A race occurs if C has an in-flight operation when pause or logout begins. C must coordinate its own threads, stop issuing new operations, handle an error from an operation already in progress and release or replace the relevant references according to the protocol. Logind's event loop cannot automatically serialize C's internal application state. An FD reference can keep a kernel object alive while its device is no longer usable. A later process can reuse the integer 8 for a completely different object, so a stale integer is not a durable device identity.

Session teardown and ownership table#

In session_stop, v256 first checks that the session has a user and has been started, and avoids repeating a stop already in progress. It unreferences timer and leader-pidfd event sources, evicts a seat position if applicable, removes the session FIFO, asks to stop the scope and marks the session as stopping. Later finalization and user/seat management still have work to do. Scope stopping can fail, and a forced explicit request differs from automatic cleanup after a scope disappears, FIFO EOF or a release timer. The source comment identifies these separate triggers; the stop request should not be described as a single synchronous “logout killed everything” operation.

For the worked case, draw four rows. The manager owns or indexes session-related objects; the user object groups the user's state; the seat tracks an assignment to a local seat when one exists; and the session records its leader, state, device relationships and event sources. These are conceptual ownership relationships, not a complete reference-count graph. At logout, event registrations and lifelines are released under their APIs, device pause/release paths run as needed, and scope and user cleanup proceed according to policy. A user with lingering enabled can retain a user manager after one session ends. A remote session with no seat simply has no local-seat device grant to clean up in this example.

Session IDs, UID values, leader PIDs, bus names and FDs each have different scopes and reuse rules. A numeric PID can be recycled; a UID identifies an account under the relevant namespace and configuration, not necessarily a unique application. A D-Bus connection can disappear while a delayed operation is pending. A method may fail after some resources were acquired; correct cleanup must release those resources without sending a success response. These claims are reasons to inspect selected error branches, not an assertion that every logind implementation has the same internal fields.

A session response is not a whole desktop#

A login application can receive a session identifier and runtime information before a desktop compositor has initialized. The display manager, user manager and compositor can each fail independently after logind accepted a session. A service that assumes an active graphical seat from the existence of a UID or runtime directory can therefore address the wrong session or fail on a headless machine. A remote session may legitimately have no local seat, and a single user may have several concurrent sessions with different states.

When investigating a pause, record which session was active, which controller received the notification, which device identity was requested and which FD reference the application used. The controller's acknowledgment describes its participation in a protocol; it does not prove that every worker thread stopped using every duplicate descriptor unless the application implements that synchronization. If the bus connection disappears before an acknowledgment, logind must follow its configured cleanup and timeout paths, while the application must treat the result as uncertain. This is why the worked timeline names both event ordering and ownership rather than just a sequence of method names.

Inhibitors and power decisions#

An inhibitor allows an authorized client to request that a class of operation be blocked or delayed under logind's policy. A block inhibitor requests that the operation be refused while the inhibitor exists, subject to policy; a delay inhibitor allows the operation to proceed after a bounded preparation window. The documented default maximum delay is controlled by InhibitDelayMaxSec=; this is not an indefinite veto. See the pinned login1 interface documentation. The returned FD is a lifetime token for the inhibition under the interface's contract. If a client duplicates or leaks the descriptor, the inhibition can last longer than intended; once the relevant references are closed or the connection and process lifecycle cause cleanup, the inhibitor can be removed according to the implementation.

The v256 logind-inhibit.c inhibitor_stop removes its FIFO, unlinks a state file if present, changes its started state and emits a change notification. This is internal cleanup in one version. It does not establish that every client may suspend the machine or that every action will prompt a user. logind, polkit, capabilities and system policy each have relevant roles; a request can be denied, delayed or fail. This chapter never calls an inhibitor, reboot, suspend, lock or session-control method on the host.

Practice#

This own-process model uses a pipe as a simple lifetime analogy. It duplicates the write end, closes the original and shows that the duplicate remains open. It does not create a logind session, inhibit an operation or access a seat:

sh
python3 - <<'PY'
import os
read_fd, write_fd = os.pipe()
duplicate = os.dup(write_fd)
try:
    os.close(write_fd)
    os.write(duplicate, b'X')
    print('duplicate still usable:', os.read(read_fd, 1) == b'X')
finally:
    os.close(duplicate)
    os.close(read_fd)
PY

Expected output is duplicate still usable: True. This demonstrates ordinary FD references in one process only; it does not implement logind's FIFO, device revocation or authorization. If Python or pipe creation is unavailable, record the error and use the T0–T3 session timeline. The program closes both remaining descriptors and does not alter a host session or bus policy.

For a source-only alternative, produce the manager/user/seat/session table described above and annotate the hypothetical descriptors 8 and 9 at pause and logout. Explain that the duplicate's behavior depends on the device-specific mechanism, and list the event sources released in the quoted session_stop block. Mark all session and FD numbers as teaching data.

Knowledge check#

  1. Why is a display manager different from logind and the system service manager?
  2. What does the quoted method_create_session error branch do before creation is attempted?
  3. Why can a duplicated descriptor outlive closure of the original number, and why does that not prove a paused device remains usable?
  4. What does session_stop release in the quoted block, and what does it not prove about all session processes?
  5. How do block and delay inhibitors differ, and what does their FD lifetime represent?

Answers#

  1. A display manager provides a login and graphical-session flow, logind manages session/seat-related state and policy interfaces, and the system manager supervises units. Their communication depends on configuration and none is simply another name for PID 1 or PAM.
  2. A negative message-read result is returned before the call to create_session. Successful decoding still requires the surrounding validation, authorization and resource setup.
  3. Duplication creates another descriptor reference to the underlying open-file description. Device-specific pause or revocation can nevertheless make operations fail or require a different descriptor; integer and device authority are distinct.
  4. It unreferences the session's timer and leader-pidfd event sources. Scope stopping and other cleanup occur separately, and policies such as lingering affect user-manager lifetime.
  5. A block inhibitor requests blocking under applicable policy, while a delay inhibitor provides bounded time for preparation. Its FD represents the inhibitor's lifetime under the API; an open duplicate can extend that reference, subject to implementation rules.

Checkpoint#

Submit the four-object session table, FD pause/logout timeline and either private pipe output or the supplied source-only reasoning. Ready means explaining creation failure, event-source cleanup, device-specific revocation limits and inhibitor lifetime without assuming a local seat or privileged host action. Retry with a headless session and no device before adding the pause case.

Sources#

A little further beneath the surface.

Check your understanding with the checkpoint. Marking a chapter as read saves a bookmark, not a proficiency assessment.