We implemented kernel measurements based on the Linux kernel LSM
interface. Using the file_mmap
LSM hook, we induce a
measurement on any file before it is mapped executable into virtual
memory.
Using the sysfs file system, we allow user-space applications to issue
measure requests by writing requests to /sys/security/measure
,
including the file descriptor of the file to measure. Using the
kernel load_module
routine, we induce a measure
call on
the memory area of a loading module before it is relocated.
In Section 4.2, we outline the approach to measurement, where measured executable code itself (e.g., shell) can induce additional measurements on loaded file contents its behavior depends on (e.g., shell command files). If that executable code is not of high integrity, it will be detected (because it is already in the measurement list). If it is of high-integrity, then it may be trusted to measure its loaded data.
We describe below how we measure dynamic run-time loads and how we protect measured files throughout their use.
User-level Executables: User-level executables are loaded
through the user-level loader. When a binary executable is
invoked via the system call execve
, the kernel calls the binary
handler routine, which then interprets the binary and locates the
appropriate loader for the executable. The kernel then maps the
loader into memory and sets up the environment such that when the
execve
call returns, execution resumes with the loader. The
loader in turn performs further loading operations and finally passes
control to the main
function of the target executable. In the
case of a statically linked binary, the only file being loaded is the
target binary itself, which we measure in the file_mmap
LSM
hook, called by the kernel before mapping it.
Dynamically Loadable Libraries: A dynamically linked binary
typically requires loading of additional libraries that it depends on.
This process is done by the user-level loader and is transparent to
the kernel. However, the linker maps shared libraries (flagged
executable) into virtual memory by using the mmap
system call,
which always invokes the file_mmap
LSM hook. Thus, the
mediation provided by the file_mmap
LSM hook instrumentation
yields measurements of all statically and dynamically linked
executables including shared libraries.
Kernel Modules: Kernel modules are extensions to the kernel that
can be dynamically loaded after the system is booted. Module loading
can be explicit (via insmod or modprobe) or implicit if
automatic module loading is enabled. In the latter case, when the
kernel detects that a module is needed, it automatically finds and
loads the appropriate module by invoking modprobe in the context
of a user process. With a 2.6 kernel, both programs load kernel
modules into memory and then call the sys_init_module
system
call to inform the kernel about the new module that is then copied
into kernel memory and relocated. Thus, kernel modules can either be
measured by insmod or modprobe on user level when they are
loaded from the file system, or they can be measured in the kernel
when they reside in kernel memory and before they are relocated. We
implemented both versions. However, we prefer the latter version
because it prevents exploits of (possibly unknown) vulnerabilities in
the kernel loader applications insmod or modprobe from tampering
the measurement of kernel level code. Because there is no suitable
LSM hook available, we added a measure
call into the
load_module
routine that is called by the init_module
system call to relocate a module that is in memory.
Scripts: Script interpreters are loaded and measured as binary executables. However, interpreters load additional code that determines their behavior, so we would prefer that the script interpreters also be capable of measuring their integrity-relevant input. At present, we have instrumented the bash shell to measure any interpreted script and configuration files before loading and interpreting them. This includes all service startup scripts into the measurement list. We observe about 60-70 measurements of bash scripts and source files in our experiments booting Redhat 9.0 Linux and running a Gnome Desktop system. Instrumenting other programs (Perl, Java) is straightforward, but we anticipate the need for more support from application programmers.