utmp
The utmp file is a binary log file used in Unix-like operating systems to record real-time information about currently active user sessions on the system, including details such as usernames, terminal devices, process IDs, and login timestamps.[1] It serves as a central data source for commands likewho and w to display information about logged-in users, enabling system administrators to monitor active logins and sessions.[2] Originating in Version 1 AT&T UNIX, the utmp format has become a de facto standard across various Unix variants, including Linux and BSD systems, though its exact implementation can vary between them.[3]
The utmp file, typically located at /var/run/utmp, consists of a sequence of fixed-size records defined by the struct utmp in the <utmp.h> header file.[1] The records include fields for user identification, terminal, process details, host, and timestamps, though the exact fields and sizes vary by system implementation (see File Formats section for details).[1] Programs such as login, init, and getty maintain these entries: a record is added upon login and updated or removed upon logout to reflect the system's current state.[2] For security, the file should not be writable by non-root users to prevent unauthorized modifications.[1]
Related files extend utmp's functionality for historical and security logging. The wtmp file, usually at /var/log/wtmp, archives all login and logout events in a similar format, allowing tools like last to review past sessions, including system reboots and shutdowns (displayed by tools like last with special entries such as "reboot").[2] In some systems, such as Linux, the btmp file at /var/log/btmp records failed login attempts for auditing purposes, aiding in the detection of brute-force attacks or unauthorized access attempts.[4] These files are managed by system daemons and utilities, with rotation recommended for wtmp and btmp (where applicable) due to their potential for rapid growth.[1] The lastlog file complements them by storing the most recent login details per user, such as the last login time and originating host.[2]
Introduction
Purpose and Functionality
The utmp file serves as a binary log on Unix-like operating systems, recording information about current user logins, logouts, and key system events such as boots and shutdowns. It provides a mechanism to track active sessions and system state changes in real time, enabling administrators and utilities to monitor who is using the system at any given moment. Although not all programs update this file, it captures essential details for processes that do, ensuring a snapshot of ongoing activity.[1] utmp supports various system commands by supplying data on active users, such as through thewho utility, which queries the file to display currently logged-in users along with their terminals and login times. For session history, utmp works in conjunction with related files that archive past entries, allowing reconstruction of login patterns over time. This functionality is crucial for tasks like resource allocation, security auditing, and performance analysis in multi-user environments.[5][1]
The file maintains specific record types to categorize entries, including user processes for normal login sessions, the init process for system initialization, run levels for state transitions, boot time for startup events, and clock changes for time adjustments. These records are populated dynamically as events occur. utmp is updated in real time by login daemons, such as getty for console access or sshd for remote sessions, with each entry typically including fields like the username, terminal device, remote host, process ID, session ID, and timestamp to provide context for the activity.[1][6]
Historical Development
The utmp file originated in the early Unix systems of the 1970s, serving as a key component for user accounting and system monitoring. It first appeared in Version 1 of AT&T UNIX in 1971, initially located at /tmp/utmp, to track current user sessions and support commands like who for displaying logged-in users.[3] By the release of Version 7 Unix in 1979, utmp had become integral to accounting tools, enabling real-time monitoring of active processes and terminals across multi-user environments. This early implementation laid the foundation for login session management in Unix-like operating systems.[3] In the 1980s, the ecosystem expanded with the introduction of wtmp and btmp files to provide persistent logging beyond the volatile utmp. The wtmp file, which records historical login and logout events, traces back to Version 2 AT&T UNIX in 1972 but gained widespread adoption in System V releases during the decade for auditing purposes.[3] Complementing this, btmp emerged to log failed login attempts, enhancing security monitoring by capturing unsuccessful authentication events, often integrated into login daemons like those in Berkeley Software Distribution (BSD) variants. These additions addressed the limitations of transient session data, allowing administrators to review past activity for accounting and troubleshooting.[1] The 1990s saw further evolution with the development of utmpx by Sun Microsystems, introduced as a 32-bit extension in Solaris 2.0 (released in 1992) to accommodate larger systems and extended fields for modern hardware. This variant, along with wtmpx and btmpx, supported longer usernames, IPv6 addresses, and timestamps, making it suitable for growing network environments and 64-bit architectures. Sun's implementation influenced other vendors, providing a more robust alternative to the original formats for high-volume user tracking.[7] Standardization efforts culminated in POSIX.1-2001, which formalized utmpx and wtmpx as part of the XSI extension in the Single UNIX Specification Version 3, while noting that the original utmp and wtmp were non-standard but prevalent.[8] This inclusion promoted portability across BSD and Linux variants by defining a common structure and API, such as getutxent(). Early implementations varied significantly by vendor—System V used different field conventions from BSD, leading to compatibility challenges in applications relying on utmp parsing—issues largely mitigated by the POSIX baseline.[9]File Formats
Original utmp, wtmp, and btmp
The original utmp file format consists of a sequence of fixed-size binary records, each representing a login session or system event, as defined by thestruct utmp in the <utmp.h> header file.[1] On many Unix-like systems, including Linux, each record is 384 bytes long, including padding for alignment and compatibility across 32-bit and 64-bit architectures.[1] The core fields include ut_type (a short integer enum indicating the record type, such as EMPTY for unused slots, USER_PROCESS for active logins, DEAD_PROCESS for logouts, BOOT_TIME for system boots, RUN_LVL for run-level changes, and others up to ACCOUNTING), ut_pid (process ID of the login shell as a pid_t), ut_line (a 32-byte array for the terminal device name, such as "tty1"), ut_id (a 4-byte array for a unique session identifier), ut_user (a 32-byte array for the username), ut_host (a 256-byte array for the remote hostname or kernel version string), ut_exit (a structure with two short integers for termination and exit status), ut_session (a long integer for the session ID), ut_tv (a structure holding the timestamp as seconds and microseconds since the epoch), and ut_addr_v6 (an array of four 32-bit integers for the remote host's IPv4 or IPv6 address).[1] String fields are null-terminated if shorter than their allocated size, ensuring consistent record length.[1]
The wtmp file uses the identical binary record format but serves as an append-only log for historical login and logout events, with new records added sequentially without overwriting.[1] Logouts are indicated by a DEAD_PROCESS record with an empty ut_user field, while active sessions mirror utmp entries.[1] Similarly, the btmp file employs the same utmp structure to record failed login attempts, capturing details such as the terminal (ut_line), timestamp (ut_tv), remote host (ut_host), and process ID (ut_pid), with ut_type set to LOGIN_PROCESS and ut_user set to the attempted username.[10]
Special entries in these files mark system events beyond user logins: for instance, boot records use BOOT_TIME with ut_line set to "ut_user to "reboot"; shutdown or reboot uses DEAD_PROCESS with ut_line as "ut_user as "shutdown" or "reboot"; run-level changes employ RUN_LVL with ut_line as "run-level" and ut_user holding the previous and current run-level digits (e.g., "23" for transition from level 2 to 3).[1] These conventions allow utilities to parse system state changes reliably.
The format exhibits system-specific variations, such as the exact field sizes and padding in Linux's 384-byte records, rendering it non-portable across different architectures or even between 32-bit and 64-bit variants without compatibility layers.[1] Over time, this legacy format has evolved into extended variants like utmpx to support larger usernames and IPv6 addresses on modern systems.[1]
Extended utmpx, wtmpx, and btmpx
The extended formats, utmpx, wtmpx, and btmpx, represent POSIX-compliant evolutions of the original utmp, wtmp, and btmp, designed to support modern system requirements including enhanced precision and compatibility. Defined in the<utmpx.h> header, the utmpx structure typically spans 384 bytes (or more in certain implementations) and includes expanded fields such as ut_exit—a structure capturing process termination and exit status—ut_session for session identification, and ut_tv as a struct timeval providing timestamps with microsecond resolution.[11][12][13]
This structure complies with POSIX.1-2001 by replacing the legacy ut_time field with ut_tv for improved temporal accuracy and incorporating ut_syslen to specify the effective length of the ut_host field (often truncated to accommodate longer names).[11][14]
The wtmpx and btmpx files parallel wtmp and btmp in purpose—recording login history and failed attempts, respectively—but employ the extended utmpx records for richer data capture, and are the preferred variants on platforms like Solaris and contemporary Linux systems.[13][14]
Originating from Sun Microsystems to facilitate 64-bit compatibility amid growing address spaces and data sizes, the utmpx format was standardized in POSIX.1-2001; Linux's glibc library accommodates both original and extended variants, prioritizing utmpx when _GNU_SOURCE is enabled for full feature access.[14][15][11]
Notably, the extended format better handles expanded hostnames and IPv6 addressing via dedicated fields like ut_host and ut_addr_v6 (a 16-byte array), addressing limitations in legacy networking support.[12][14]
System Integration
Default Locations and Paths
In Unix-like operating systems, the default locations for utmp and related files vary by implementation, reflecting historical conventions and system-specific standards. The Filesystem Hierarchy Standard (FHS) specifies paths for Linux distributions to ensure consistency.[16] These files typically reside in volatile directories like /var/run for current sessions and /var/log for persistent records. The following table summarizes the standard paths across major systems:| Operating System | Current Sessions | Historical Logins | Failed Logins | Extended Variants |
|---|---|---|---|---|
| Linux | /var/run/utmp | /var/log/wtmp | /var/log/btmp | /var/run/utmpx (current), /var/log/wtmpx (history)[1] |
| Solaris | /var/adm/utmpx | /var/adm/wtmpx | N/A | Uses extended format (utmpx/wtmpx); legacy /var/adm/utmp deprecated[17] |
| FreeBSD | /var/run/utx.active | /var/log/utx.log | N/A (failed logins in /var/log/auth.log) | N/A[18][19][20] |
| macOS | /var/run/utmpx | Deprecated (uses unified logging) | N/A | N/A (btmp not standard)[21] |
Access Mechanisms and Permissions
Processes interact with utmp files primarily through the C library functions defined in<utmpx.h>. The getutxent() function reads the next entry sequentially from the utmpx file, returning a pointer to a struct utmpx or NULL on end-of-file or error, while getutxid() and getutxline() search for specific entries matching identifiers or line names, respectively. For writing, pututxline() locks the file, updates or appends the provided struct utmpx entry, and returns a pointer to the written structure or NULL on failure. Access is closed using endutxent(), which flushes any buffered data and closes the file descriptor.[22]
utmp files, such as /var/run/utmp, typically have permissions of 644 (rw-r--r--), owned by root and the utmp group, ensuring readability by all users but writability restricted to the owner and group to prevent unauthorized modifications. This setup allows system programs like login to write entries via setgid mechanisms, while ordinary users cannot alter the file, mitigating risks of faked logins. The man page for utmp explicitly warns that the file must not be writable by the "other" class, as many programs rely on its integrity for accurate user accounting.[1][23]
Integration with modern init systems and authentication frameworks ensures controlled updates to utmp. In systemd-based distributions, the systemd-update-utmp.service automatically records system boot and shutdown events into utmp and wtmp, running as part of the boot process. Additionally, systemd services can use the UtmpIdentifier= directive in unit files to generate specific utmp/wtmp entries for user sessions, with modes like "user" creating USER_PROCESS records for session leaders. The Pluggable Authentication Modules (PAM) framework, through modules invoked during login sessions, coordinates with these library functions to update utmp records for user logins and logouts, maintaining consistency across authentication flows.[24][25]
On Linux systems, /var/run/utmp is often a symlink to /run/utmp, where /run is mounted as a tmpfs filesystem in memory for performance, avoiding disk I/O for current login data that is volatile across reboots. Non-root processes require the CAP_SYS_ADMIN capability to write to this file, as it is owned by root; login-related binaries typically run with elevated privileges to perform updates.[26]
For historical logs like wtmp, entries are appended sequentially rather than overwritten, preserving a complete record of past logins, logouts, and system events for auditing. Rotation is handled by tools like logrotate, which compress and archive the growing file when it exceeds configured thresholds, such as monthly or size-based limits, to manage disk space without losing history.[27][1]
Utilities and Commands
Viewing Current and Historical Logins
The primary utilities for viewing utmp and related log data in Unix-like systems are thewho, last, and lastb commands, which provide insights into current sessions, historical logins, and failed authentication attempts, respectively. However, as of late 2025, some Linux distributions such as Ubuntu 25.10 and Debian 13 are deprecating the last and lastb commands in favor of alternatives like systemd-logind.[28] These tools read from the utmp (or utmpx) file for active users and the wtmp (or wtmpx) and btmp (or btmpx) files for historical records, displaying formatted output that includes usernames, terminals, remote hosts (often as IP addresses), timestamps, and session durations. On Linux systems, these commands are implemented as part of the util-linux package, while BSD variants like FreeBSD, OpenBSD, and NetBSD offer equivalent functionality through their base system utilities that similarly parse utmp-derived files.[29][30][31]
The who command displays information about users currently logged into the system by examining the utmp file, typically located at /var/run/utmp. It outputs key details such as the username, associated terminal (e.g., tty1 or pts/0), remote host or IP address from which the login originated, and the login time in a human-readable format like Nov 14 10:30. For example, running who might produce lines like user pts/0 192.168.1.100 Nov 14 10:30, allowing administrators to monitor active sessions in real time. The -u option extends this by adding idle time, showing how long a user has been inactive (e.g., (1:23) for 1 minute and 23 seconds), which helps identify potentially stalled connections; the -a option includes details on all processes associated with terminals, such as dead processes or processes from defunct ttys.[5][32]
For historical login data, the last command parses the wtmp file, usually at /var/log/wtmp, to list past login and logout events in reverse chronological order, from most recent to oldest. Each entry includes the username, terminal, remote host, login and logout times, and session duration (e.g., 1:23 or already logged out), along with system events like reboots marked as reboot system boot. This enables tracking of user activity over time, such as total uptime or frequent access patterns; for instance, last root filters to show only root's sessions. The -F option provides full timestamps (e.g., Thu Nov 14 10:30:45 2025), while -n number limits output to the specified number of recent entries to avoid overwhelming logs from large wtmp files. On BSD systems, last functions similarly, reading wtmp and supporting options like -f to specify alternate files.[33]
The lastb command, specific to Linux implementations, reads the btmp file at /var/log/btmp to display records of failed login attempts, helping with security audits by revealing patterns in brute-force attacks or authentication issues. Output mirrors last but focuses on unsuccessful events, showing the attempted username, terminal or source IP, and timestamp (e.g., user1 pts/0 192.168.1.100 Thu Nov 14 10:30 bad [login](/page/Login)), without logout details since failures do not establish sessions. It requires root privileges due to the sensitive nature of failure logs and supports options like -n for limiting entries or -F for detailed times; on BSD systems, failed login attempts are typically logged to text files such as /var/log/auth.log, where they can be searched using commands like grep for patterns such as "Failed password".[34][20] These tools collectively offer a read-only interface to utmp-derived data, with output formats standardized across implementations to include idle times where applicable and remote sources for networked logins.
Managing and Maintaining Log Files
Managing utmp-related log files, such as wtmp and btmp, requires regular maintenance to prevent excessive growth and ensure system performance. On Linux, the logrotate utility is commonly used to automate the rotation of these binary files, configuring schedules like weekly rotations or size-based triggers (e.g., when exceeding 1 MB) to create compressed archives and limit the number of retained versions. On BSD systems, newsyslog(8) serves a similar purpose for log rotation.[35][36] This prevents unbounded file expansion, as wtmp records all login and logout events, potentially reaching gigabytes in high-activity environments and consuming significant disk space or straining resources if unrotated.[37] For inspecting the binary structure of utmp, wtmp, or btmp files, utmpdump from the util-linux package provides a hexadecimal dump in human-readable ASCII format, allowing administrators to examine or debug corrupted records without specialized tools.[38] It reads from standard input or a specified file and supports options like following file growth or writing back edited entries, making it suitable for low-level maintenance tasks. Manual management techniques include using the tac command to reverse the order of records in wtmp or btmp files, which are appended in chronological order (newest at the end), enabling chronological viewing when piped to other tools for processing. For security purposes, such as after investigating failed login attempts, administrators can safely clear btmp by truncating it with> /var/log/btmp or cat /dev/null > /var/log/btmp, which empties the file without deleting it and avoids disrupting processes expecting its presence.[39] Similarly, wtmp can be cleared using cat /dev/null > /var/log/wtmp to reset login history.
Integration with cron jobs facilitates automated archival, such as monthly tasks in /etc/cron.monthly to compress and relocate old wtmp files to secure storage, ensuring long-term retention without ongoing performance impacts.[40] An example logrotate configuration snippet for /var/log/wtmp, often placed in /etc/logrotate.d/, might appear as:
This rotates the file weekly, retains five archives, compresses older versions, and recreates the file with appropriate ownership upon rotation.[35] Verification of rotations can be performed using viewing commands like last to confirm updated log contents post-maintenance./var/log/wtmp { rotate 5 weekly compress create 0664 root utmp }/var/log/wtmp { rotate 5 weekly compress create 0664 root utmp }
Security and Auditing
Potential Vulnerabilities
The utmp file, typically located at/var/run/utmp, has default permissions such as 644 or 664 (world-readable), allowing any local user to access its contents and view current user sessions, including sensitive details like hostnames from remote logins stored in the ut_host field.[1] This exposure can reveal network topology or internal system information to unauthorized local users, increasing risks in multi-user environments where attackers might leverage session data for further reconnaissance.[1] Similarly, the wtmp and btmp files, which record historical logins and failed attempts, often have comparable readability, enabling potential leakage of login patterns without encryption, as all data—including hostnames or addresses—is stored in plain binary format.[1][41]
A significant denial-of-service (DoS) risk arises from log flooding, particularly targeting btmp, where brute-force attacks generate excessive failed login entries that can rapidly consume disk space on the /var partition.[42] For instance, automated password guessing attempts against SSH services can fill btmp to gigabytes in size, potentially rendering the system unresponsive by exhausting storage and disrupting normal logging operations.[42] Without regular rotation or size limits configured via tools like logrotate, this can lead to broader system instability, as observed in cases where public-facing servers experience sustained attack traffic.[43]
Historical exploits have highlighted tampering vulnerabilities in utmp-related utilities. In 2004, a symlink attack in the utempter utility (used to update utmp and wtmp entries) allowed local unprivileged users to overwrite arbitrary files by exploiting improper temporary file handling, potentially enabling privilege escalation or data corruption when combined with applications trusting these logs.[41] Earlier, pre-2000s implementations faced risks from inadequate file integrity checks, where improper permissions could permit modification of utmp entries, leading to faked login records that mislead auditing tools.[1] More recently, a 2023 glibc issue in utmp/wtmp locking permitted non-privileged users to acquire exclusive locks on these files, causing DoS by blocking access for legitimate processes.[44]
The lack of encryption in utmp, wtmp, and btmp files means remote login details, including originating IP addresses or hostnames, are directly accessible upon reading the binary records, potentially exposing attacker reconnaissance patterns in btmp if files are not promptly rotated.[1][43] While the extended utmpx format addresses some legacy limitations—such as larger field sizes for IPv6 support and additional metadata like session IDs—core risks like readability and tampering persist, though it mitigates certain race conditions in multi-threaded environments.[1]