Check out the new USENIX Web site. next up previous
Next: Validating Measurements Up: Implementation Previous: Taking Measurements

Measurement Bypass-Protection

Whenever we encounter a situation in which our measurement architecture cannot provide correct measurements or is potentially being bypassed, we invalidate the TPM aggregate by extending it with random values without extending the measurement list and deleting the random value to protect it from later use. Thus, from this time on, validations of the aggregate will fail against the measurement list. We do not interfere with the system (non-intrusive) but we disable such a system from successful attestation until it reboots. In our experiments, none of these mechanisms was triggered throughout normal system usage but only by malicious or very unusual behavior.

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 $>0$. 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.

next up previous
Next: Validating Measurements Up: Implementation Previous: Taking Measurements
sailer 2004-05-18