Although we assume there are no hardware attacks against the TPM, we design the system such that a compromised system cannot change the measurement list undetected because it cannot manipulate the TPM successfully to cover such attacks in software. Thus, supporting our architecture with TPM hardware is useful and necessary even in the (assumed) absence of physical attacks in order to discover cheating systems. However, anybody with root identity could try to change the system through less known interfaces in a way that circumvents our measurement hooks and thus breaks the measurements' validity. Therefore, we implemented some fail-safe mechanisms that catch such efforts and invalidate (pessimistically) the TPM aggregate. We discuss some of them below.
Time-of-measurement Time-of-use race conditions: File contents
could theoretically be changed between the time they are measured and
the time they are actually loaded. Linux does protect memory-mapped
files, but not files that are normally loaded (e.g., script files,
configuration files). Therefore, we have implemented a counter measure count in the inode of a measured file that keeps track of
the number of open file descriptors pointing to this inode on which a
measure call was induced. We increase the counter before calling the
measure call (in the sysfs write implementation of the
/sys/security/measure
node) and decrease the counter when a
file descriptor that was measured is closed (using the
file_free_security
LSM hook). We add a check into the
inode_permission
LSM hook that catches requests for write or
append permission on files whose related inode has a measure
count . In this case, we invalidate the TPM aggregate because
the measurements might not reflect the file contents that were
actually loaded, but we choose not to interfere with the request. We
assume any such behavior is malicious.
Bypassing user-level measurements. To ensure that measure
requests issued by applications actually result in measurements in the
kernel, we must ensure that the /sys/security/measure
node is
actually the one that issues measurements on write. The only way to
circumvent this without leaving a suspicious fingerprint in the
measurement list is to prevent the system from mounting the sysfs file
system in the first place or to unmount it after it is mounted by using
unsuspicious programs (commands). We prevent the first by ensuring
that the sysfs is mounted before init is started (in the kernel
startup) and the second by keeping the sysfs in a busy state (lock it)
so it can't be unmounted by root.
Bypassing dirty flagging. Processes running as root could try
to circumvent dirty-flagging and thus change file content between
measurement and loading or try to change -otherwise non-vulnerable
and thus trusted- applications or the kernel in memory by accessing
the special storage control interfaces (e.g. /dev/hda
) or the
memory interface /dev/kmem
. We catch such special cases and
invalidate the TPM aggregate as described above. This is necessary to
prevent the kernel from being changed without this change being
measured. Such suspicious cases are rarely necessary or observed in
normal systems.
Unmounting file systems. We dirty-flag any measurement that belongs to a file system that is being unmounted because we don't have control over changes on this file system any longer. Hot-pluggable hard-drives could be changed and re-inserted with changed files. For this purpose, we keep the superblock pointer of a file in the file's measurement structure. Walking through the whole measurement list to dirty-flag entries related to the mount point imposes overhead, but this happens rarely (e.g., on shutdown) on most correctly setup and configured systems and the measurement lists are usually not very large (1000 entries).
Run-time Errors among the measurement functions. In case of any error throughout the recording of measurements, e.g., caused by out-of-memory errors when allocating a new measurement structure or other unexpected events preventing us from measuring correctly, we invalidate the TPM aggregate.
In summary, the measurement functions use the pseudo file system
sysfs, the kernel LSM hook file_mmap
, and an inserted
measure
call in the load_module
kernel routine to
instrument the system with measurement points. We use the LSM hooks
inode_permission
, sb_umount
, inode_free_security
,
and file_free_security
to implement the dirty flagging and to
protect against ToM-ToU race conditions (usually malicious). We use
LSM security substructures in the file
and inode
kernel
structures to store state information, such as dirty flag and
measure count.