Skip to content

Conversation

@Karlson2k
Copy link
Contributor

@Karlson2k Karlson2k commented Jul 15, 2025

This PR aligns generated "ut_id" with ids produced by other modern software, like systemd and libutemper.
For reference:

To summarise the idea of this PR.
This PR does not change functionality for normal workflow (when utmp entry is created before login is started).

This PR does correct behaviour in non-standard situations, for example, when login is started as init process, aligning choice of ut_id value with modern software (systemd, utemper).

@Karlson2k
Copy link
Contributor Author

Karlson2k commented Jul 16, 2025

ut_id historically (on GNU/Linux) was identifier from inittab file.
See https://manpages.debian.org/unstable/sysvinit-core/inittab.5.en.html

If an entry is being written to utmp file, the file is first checked for entries with the same ut_id and if one found, it is replaced with the new/updated one.

It was designed to work in the following way (simplified, see https://man7.org/linux/man-pages/man5/utmp.5.html):

  • init process reads inittab file.
  • init process adds utmp file INIT_PROCESS entry with ut_id from inittab file and ut_pid for newly started *getty process.
  • *getty process finds utmp entry by ut_pid (and gets ut_id as assigned by init), sets entry type to LOGIN_PROCESS, sets ut_line and write utmp entry back. As entry has matching ut_id, it replaces old entry, created by init. login process started with the same PID.
  • login process finds utmp entry by ut_pid (and gets again the same ut_id as initially assigned by init). After successful user login (authentication), login changes utmp entry type to USER_PROCESS, sets ut_user, ut_host, ut_addr(_v6). When utmp entry is written, it replaces older LOGIN_PROCESS because the same ut_id is used.

I skipped extra details, like updates of ut_time on each step.

This mechanism allows init process to set ut_id initially for *getty and the same ut_id is preserved to the final user process.

However, this description does not provide any requirements for graphical terminal emulators (like xterm).
Graphical terminal does not have any inittab entries so they have no ut_id predefined. They decided to use last four chars from ut_line as ut_id. I guess the logic was something like: ut_id must not be empty (could rise compatibility problems), must be unique (as the entries with the same ut_id overwrites each other), and should not be confused with real console entries. As full pts/1 string does not fit ut_id and first four chars (pts/ would be the same for all terminals and would overwrite each other, they decided to use the unique part.

For graphical terminals the last four chars from ut_line are used as ut_id. See https://github.com/altlinux/libutempter/blob/4caa8ab94ff8b207228fa723a89214bf5e929321/libutempter/utempter.c#L99-L103 (the library used by many graphical terminal emulators).

The same is used for ssh logins. I haven't checked telnet logins. (Maybe it was invented first for telnet.)

However, inittab now is mostly historical implementation.

Modern implementations, like systemd, adapted utempter approach: used full name of the device (see https://github.com/systemd/systemd/blob/8013beb4a2221680b2c741bac6b3a33fe66406e1/units/getty%40.service.in#L41-L44) or last four chars if name is longer then four chars (see https://www.freedesktop.org/software/systemd/man/latest/systemd.exec.html#UtmpIdentifier=).
You may see it_id assigned by systemd here: #1282 (comment). Check the entry with LOGIN username.

This PR changes nothing if an entry with ut_id exists. The same ut_id will be reused as before.
But, if no utmp entry has been created before starting of login (should not happen formally, but may happen if login is started as init, for example), then utmp entry is created with the same name as it would be done by systemd (or graphical terminals). The ut_id must be unique and truncation from the start gives less chance of id conflicts.

@Karlson2k
Copy link
Contributor Author

To summarise the idea of this PR.
This PR does not change functionality for normal workflow (when utmp entry is created before login is started).

This PR does correct behaviour in non-standard situations, for example, when login is started as init process, aligning choice of ut_id value with modern software (systemd, utemper).

@Karlson2k Karlson2k changed the title lib/utmp.c: use larger strings for "ut_id" lib/utmp.c: Fix "ut_id" generation, align with other software Jul 16, 2025
@Karlson2k
Copy link
Contributor Author

Karlson2k commented Jul 16, 2025

The PR has been updated based on comments.
Feel free to cherry-pick just the first commit.

@Karlson2k Karlson2k force-pushed the better-ut_id branch 3 times, most recently from 233c65b to 0070316 Compare July 16, 2025 20:44
@Karlson2k
Copy link
Contributor Author

Updated again

@Karlson2k
Copy link
Contributor Author

Updated as requested

@Karlson2k Karlson2k changed the title lib/utmp.c: Fix "ut_id" generation, align with other software lib/utmp.c: align generated "ut_id" with other software Jul 17, 2025
@Karlson2k
Copy link
Contributor Author

Rebased, excluded merged commit.

@Karlson2k
Copy link
Contributor Author

Updated exactly as suggested.

Copy link
Collaborator

@alejandro-colomar alejandro-colomar left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks! LGTM.

Reviewed-by: Alejandro Colomar <alx@kernel.org>

@alejandro-colomar
Copy link
Collaborator

alejandro-colomar commented Jul 18, 2025

This PR aligns generated "ut_id" with ids produced by other modern software, like systemd and libutemper. For reference:

* libutemper implementation: https://github.com/altlinux/libutempter/blob/4caa8ab94ff8b207228fa723a89214bf5e929321/libutempter/utempter.c#L99-L103
  Note: libutemper is used by many graphical terminal emulator applications (konsole, xterm, others) to deal with utmp file.

* systemd implementation:
  use full name of the device (see https://github.com/systemd/systemd/blob/8013beb4a2221680b2c741bac6b3a33fe66406e1/units/getty%40.service.in#L41-L44) or last four chars if name is longer then four chars (see https://www.freedesktop.org/software/systemd/man/latest/systemd.exec.html#UtmpIdentifier=)

To summarise the idea of this PR. This PR does not change functionality for normal workflow (when utmp entry is created before login is started).

This PR does correct behaviour in non-standard situations, for example, when login is started as init process, aligning choice of ut_id value with modern software (systemd, utemper).

Please include those two links in the commit message, if you don't mind.

Modern software (systemd, utemper) usually use full "ut_line" as "ut_id"
if string is up to four chars or last four chars if "ut_line" is longer.
For reference:
* libutemper (used by many graphical terminal emulator applications
  (konsole, xterm, others) to deal with utmp file):
  https://github.com/altlinux/libutempter/blob/4caa8ab94ff8b207228fa723a89214bf5e929321/libutempter/utempter.c#L99-L103
* systemd:
  uses full name of the device:
  https://github.com/systemd/systemd/blob/8013beb4a2221680b2c741bac6b3a33fe66406e1/units/getty%40.service.in#L41-L44
  or **last** four characters:
  https://www.freedesktop.org/software/systemd/man/latest/systemd.exec.html#UtmpIdentifier=

The code in the commit is optimised for visual C code size.

Signed-off-by: Evgeny Grin (Karlson2k) <k2k@drgrin.dev>
Reviewed-by: Alejandro Colomar <alx@kernel.org>
@Karlson2k
Copy link
Contributor Author

@alejandro-colomar Includes sorted, links added.

@alejandro-colomar alejandro-colomar merged commit 59c5acb into shadow-maint:master Jul 18, 2025
10 checks passed
@alejandro-colomar
Copy link
Collaborator

Thanks!

@Karlson2k Karlson2k deleted the better-ut_id branch July 18, 2025 09:54
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants