XFS Forensics: Inode Timestamps, crtime and Deleted Files
XFS on RHEL-family Linux: v5 inode timestamps with crtime, bigtime, xfs_db inspection, the metadata log, and what remains after a file is deleted.
- Location
- /dev/<xfs-volume>
- Distributions
- Proves
- When files were created, modified, changed and read on an XFS volume, and sometimes what deleted files contained
- Timestamps
- Seconds plus nanoseconds since the Unix epoch, UTC; crtime on v5 inodes; bigtime counter on newer filesystems
- Access
- Any user for stat on accessible files; root or raw device access for xfs_db
- Retention
- Timestamps until overwritten; deleted inode extents and data blocks until reused
- Collection
- dd, ewfacquire, UAC, xfs_metadump
Tools
Compare all tools- Disk Image ParserIn browser
- xfs_dbCLI · built into Linux
- statCLI · built into Linux
- libfsxfsLibrary · open source
- PlasoCLI · open source
What it is
XFS is the default filesystem for RHEL 7 and later, and therefore for Rocky Linux, AlmaLinux, Oracle Linux and many cloud images. It is a journaling filesystem split into allocation groups, each with its own inodes and free-space trees. For an investigator it offers the same core timestamps as ext4, a creation time on modern volumes, and deletion behaviour that leaves more residue than ext4 does.
Where it lives
| Structure | Where | Notes |
|---|---|---|
| Superblock | Start of each allocation group (primary at offset 0) | Version, features (crc, bigtime), UUID |
| Inodes | Inode chunks inside allocation groups | Version 3 inodes on v5 filesystems carry crtime |
| Directory entries | Short-form in the inode, or block/leaf/node directory blocks | Deleted entries may keep part of the inode number |
| Log (journal) | Internal log by default | Metadata-only journaling |
Check the format on a live system with xfs_info / (look for crc=1 meaning v5 and bigtime=1), or read-only on an image with xfs_db -r -c 'sb 0' -c 'print' <device>. mkfs.xfs has created v5 filesystems by default since RHEL 7.3, so RHEL 8 and later systems are normally v5; filesystems created on RHEL 7.0 to 7.2 are v4 without crtime.
What it proves
- crtime (
v3.crtime): inode creation on this filesystem, available on v5 only. - mtime, ctime, atime: content change, inode change and last read, with the same meaning and forgery caveats as on ext4 (
touchcan set mtime and atime, and moves ctime to the current time). - Deleted files: the directory entry often keeps the lower bytes of the inode number, and the deleted inode keeps its extent records, so file content can sometimes be located and recovered.
- Not proven: the acting user or process; pair with auditd, shell history and logs.
Key fields
| Inode field (xfs_db names) | Meaning |
|---|---|
core.atime, core.mtime, core.ctime | Access, modify, change times (seconds and nanoseconds) |
v3.crtime | Creation time (v5 filesystems) |
core.mode, core.uid, core.gid | Type and permissions, owner |
core.size, core.nextents | Size and extent count (both zeroed on deletion) |
core.nlinkv2 | Link count |
u3.bmx | Extent list: file offset, start block, block count |
Timestamps
All times are UTC. Classic XFS stores seconds and nanoseconds for each timestamp, limited to 2038. The bigtime feature (kernel 5.10 and later, enabled by default by mkfs.xfs from xfsprogs 5.15) stores a 64-bit nanosecond counter that extends the range to the year 2486; xfs_db decodes both. stat reports Birth on v5 volumes when coreutils, glibc and the kernel support statx.
stat --format='%n birth=%w modify=%y change=%z access=%x' /etc/shadow
ls -i /etc/shadow # inode number
xfs_db -r -c 'inode 12345' -c 'print core.mtime core.ctime v3.crtime' /dev/mapper/rhel-root
The same relatime default as other Linux filesystems applies to atime.
Retention
- Timestamps are overwritten by normal activity; image early.
- On deletion XFS zeroes the inode's size and extent count, but the extent records themselves stay in the inode until it is reused, and data blocks stay in free space until reallocated.
- The internal log holds recent metadata changes only briefly; it is circular.
- Discard/TRIM on SSDs and thin-provisioned cloud volumes can remove freed data quickly.
Collection
Image the block device (or logical volume, since RHEL installs usually use LVM) read-only and hash it. For large volumes where only metadata is needed, xfs_metadump creates a metadata-only copy; it obfuscates file names by default, so pass -o to keep real names for forensic use. For live triage, UAC bodyfile output and Velociraptor timelines record paths and timestamps.
Parsing
xfs_db -r(read-only) to print superblocks, inodes, directories and extent maps.- libfsxfs (libyal) provides
fsxfsinfofor listing and inspecting XFS v4/v5 volumes, and gives dfVFS and Plaso their XFS support; the libfsxfs project itself is marked experimental. - The Sleuth Kit shipped experimental XFS support in 4.13.0 and removed it in 4.14.0, so do not rely on
fls/istatfor XFS with current releases. - Deleted-file recovery is largely manual: locate the deleted directory entry and inode with
xfs_db, read the remaining extent records, and extract blocks withdd, as demonstrated in Hal Pomeranz's XFS recovery write-up.
Investigator tips
- Check
crc=1before promising a creation time: v4 filesystems have nocrtime. - On LVM, image the logical volume or the whole physical disk, and record the mapping (
lvs,pvs) so offsets can be reproduced. - Package-installed files keep the package's mtime; use crtime and package manager logs for install time.
- ctime newer than all other times with a suspiciously round mtime suggests timestomping, exactly as on ext4.
- Deleted staging files in /tmp and /var/tmp are often still recoverable on XFS because extents survive in the inode.
- Always mount evidence read-only with
-o ro,norecoveryso the log is not replayed.