SDB:Ima evm
Introduction
This document describes the IMA and EVM technologies from the Linux integrity subsystem, and how they can be utilized on SUSE Linux distributions.
Basically IMA and EVM provide the following functionality:
- measurement (hashing) of file content as it is accessed and keeping track of this information in an audit log.
- appraisal of files, which allows to prevent access when a measurement (hash) or digital signature does not match the expected value.
Both functionalities will be covered in more detail in the following sections.
General Concepts
In this section the different functionalities of IMA and EVM are discussed from a high level perspective. This should help understanding the practical usage which will follow in a later section.
Metadata in Extended Attributes
Both IMA and EVM store per file hash or signature data in extended attributes named security.ima or security.evm respectively. The data found in these attributes are binary data structures that are created, processed and updated by IMA and EVM internally.
The IMA extended attribute stores data about the actual file contents. The EVM extended attribute on the other hand stores data about the file metadata like ownership, mode bits, other extended attributes and so on.
IMA Measurement
With the help of IMA measurement the integrity of a Linux system can be verified by keeping track of the hashes of the files as they are accessed. When a system is first installed in a known, trusted state (during provisioning) a list of `good´ hash values is recorded.
During regular operation of the system a runtime list of file hashes as they are accessed is maintained by IMA. This list can then be compared against the initially recorded list of `good´ hashes to detect any unwarranted changes.
Of course the runtime list of file hashes can itself be subject to malicious modification. Therefore it can be coupled with a TPM chip (for more about TPM see SUSE blog article about TPM). In this case each new calculated file hash will extend one of the TPM's registers (which are called PCRs). The value stored in the PCR is the aggregated hash of all files seen by IMA. It is maintained by computing hash(PCR.value || file.hash). For more information look for example at the TPM2_PCR_Extend()
library function for TPM version 2.0.
In the process called TPM remote attestation, the TPM chip creates a cryptographically signed message containing the current PCR values. This message is sent to a remote party together with the audit log containing the runtime list of measured hashes. The remote party can then recalculate the aggregate hash value from the audit log and compare it with the aggregate hash value found in the TPM's PCR register.
If both values match then it made sure that the audit log has not been tampered with, because the recalculation yielded the same value as is stored in the TPM. The TPM register can never be reset it can just be extended. Thus even if a malicious attacker managed to get access to a system and modify files, manipulating the audit log accordingly would fail to verify.
As can be seen from this, the measurement feature of IMA is only used for detecting potentially malicious changes to a system but not for preventing them. This document focuses more on the appraisal part of IMA and EVM. For more practical details about measurement please refer to the references and official documentation.
IMA Appraisal
With the help of the appraisal functionality the execution or even the reading of untrusted files can be prevented. This is achieved by signing a hash of the file content and checking the signature using public key cryptography. The signature is stored in the security.ima extended attribute of each file.
Digital signatures are only suitable for files that aren't expected to change during runtime, because otherwise the signature would need to be recalculated using the private key, which should not be kept on the system for security reasons. Signatures are thus best used for binaries and not for configuration files.
IMA appraisal can also be used without digital signatures and just store plain file hashes instead. This variant does not provide real security on its own. However, it can be used together with EVM for protection against offline file tampering (as explained in the next section).
EVM for Protection Against Offline File Tampering
EVM (Extended Verification Module) has been designed with protection against offline file tampering in mind. The goal here is to detect when files on disk have been modified while the system was shut down ("evil maid attack").
Full disk encryption thwarts this kind of attack but introduces overhead. Additionally it might not be applicable in all situations (e.g. because entering a decryption password is not possible). In these cases IMA/EVM can be an alternative.
EVM addresses this issue by creating a signed hash or HMAC of a number of metadata of individual files, like the following:
- security related extended attributes (IMA hashes, SELinux or other security frameworks' data).
- Linux capabilities.
- file owner, group and mode.
- the file system UUID.
- the file inode number.
Should the verification of metadata fail, then the access to the file in question is rejected. The digital signature or HMAC is stored in the security.evm extended attribute of each file.
EVM does not work on its own but only in conjunction with security frameworks like IMA or SELinux. This means that the EVM metadata check is only made when e.g. an IMA appraisal is performed.
EVM Digital Signature
This approach uses a signed hash and works similar to IMA appraisal: A hash of the gathered metadata is calculated. Then a signature for the hash is made using public key cryptography. Once EVM is active, only file's for which hash and signature can be verified will be allowed to be accessed.
Again, this technique is only suitable for files that don't change often. Since all that metadata is part of the hash, a file would even fail to verify when it is identically copied, because of a new inode number or a different file system ID.
EVM HMAC
By using an HMAC, a file's metadata can be authenticated using a symmetric key. The symmetric key is best kept on a TPM chip. This way the symmetric key is only accessible when a successful trusted boot was performed. Also the key never leaves the TPM chip.
The functional difference to EVM based on digital signatures is that the symmetric key will be available during regular operation, so the IMA/EVM subsystem can recalculate the HMAC as files change. Thus the EVM HMAC approach is also suitable for files that do change regularly, like configuration files.
Since the secret symmetric key is kept on the TPM chip, this approach provides protection against offline file tampering. The secret key is not to be found while the system is shut down. It is also possible to use a software based symmetric key for testing, however.
The difference between IMA and EVM
IMA and EVM work closely together and can't always be well separated from each other. Some major differences:
- IMA cares about the actual file content while EVM cares about the metadata
- IMA provides logic to detect runtime changes to files and consequently updates calculated hashes. This logic is also required by EVM for the EVM HMAC approach.
- IMA behaviour can be fine tuned with custom policies while EVM simply is on or off and is only executed on behalf of IMA appraisal.
The Trusted Computing Base (TCB)
IMA and EVM have been developed with some goals of the Trusted Computing Group (TCG) in mind. One of these goals is to protect the so called TCB from unwarranted modification.
The TCB is defined to be a set of programs and files that are necessary for enforcing the security policy on a system (also see here for a more in-depth discussion of this topic).
With concepts like secure boot or trusted boot, signatures of firmware, boot loader and the Linux kernel are already checked. There the chain of trust typically ends. The TCB is comprised of more than that, however. For example many configuration files in /etc or programs responsible for processing user logins or privilege evelation are just as important for the overall security of a system.
IMA and EVM allow to extend the chain of trust into the userspace and to detect untrusted software as it is executed (measurement) or even prevent access to it (appraisal). The IMA and EVM subsystems come with a set of predefined policies that specifically aim to protect the TCB of a system.
IMA and EVM in practice
In this section the actual steps required to setup the different functionality of IMA and EVM will be discussed. First a reference of the available utilities and interfaces is given. Then in the example section a number of practical use cases are explained step by step.
Since not everybody has a TPM chip accessible and the chips are coming in two differing major versions 1.2 and 2.0, the following sections emphasize on the use of software based keys for the moment.
The evmctl utility
The evmctl
utility from openSUSE package evmctl
(subpackage of ima-evm-utils
) is used for explicitly creating the extended attributes security.ima and security.evm for the different use cases of IMA and EVM. The following list shows some major operations that evmctl
can perform and what they are used for.
evmctl ima_hash [...]
: IMA appraisal with hash digests. Calculates the hash digest of the selected files and stores it in individual security.ima extended attributes. A binary header identifying the type of attribute data and the digest algorithm used is also stored.evmctl ima_sign [...]
: IMA appraisal with digital signatures. Uses the configured private RSA key to create a signature of the hash digest of the selected files and stores it in individual security.ima extended attributes.evmctl sign [...]
: EVM digital signature. If one of the-s
or-d
switches is also passed, then first an IMA hash or signature like discussed in 1. and 2. is created and stored in security.ima. Then a sha1 digest of the involved metadata is calculated and signed with the configured private RSA key. The resulting signature is then stored in security.evm.evmctl hmac [...]
: EVM HMAC. Operates like in 3. but instead of creating an RSA private key signature, a symmetric key is used for calculating an HMAC which is stored in security.evm.evmctl ima_verify [...]
: Verify IMA digital signatures attached to a file in extended attribute "security.ima". If successful verified, nothing feedback from stdout.evmctl verify [...]
: Just like ima_verify, instead verify EVM digital signatures attached to a file in extended attribute "security.evm". If successful verified, nothing feedback from stdout.
Digest Algorithms
The digest algorithm used for calculating hashes can be selected with the -a
option of evmctl
. The default algorithm is currently sha1 which should be avoided, because it is no longer safe. When a TPM chip version 1.2 should be involved then there is not really a way around sha1, because those chips don't support stronger digests.
The EVM related functionality also currently seems to be limited to sha1. But IMA can be used with stronger digests. sha256 should be a safe choice. There are some more limitations, however, when using the IMA signature scheme version 1. See the next section for more about this.
RSA Key formats
IMA/EVM currently support two different versions of signature schemes. The older one (signing scheme v1) uses PEM formatted public/private RSA key pairs generated via openssl genrsa [...]
. This scheme only supports sha1 digests reliably. When selecting sha256 the signature will be created but the kernel will fail to verify these signatures.
The newer signature format version 2 uses X.509 certificates which are generated via openssl req [...]
. Only with this scheme stronger digest algorithms like sha256 can be used.
The default signature scheme expected by evmctl
was changed from older versions. Current evmctl
expects X.509 based keys. To use the old signature scheme instead, the --rsa
option needs to be passed, which is a bit confusing, because in both cases RSA keys are involved.
RSA Key lengths
Typically 2048 bit RSA keys are used which should be sufficient for the time being.
How to enable IMA
IMA is controlled through a policy rule set that defines which files are to be measured and/or appraised. See IMA Policy Grammar for the details. IMA comes with a number of builtin policies that can be activated via the kernel command line parameter ima_policy
, see Kernel Command Line Options.
To load a custom policy, the policy text needs to be written to the pseudo file ima/policy
in the securityfs which is normally mounted on /sys/kernel/security
:
root # cat /root/ima.policy >/sys/kernel/security/ima
If errors are detected in the policy file then the write fails with EINVAL and the policy will not be activated. Once a policy file was successfully read, the policy file node will disappear for security reasons.
In newer kernels the config option IMA_WRITE_POLICY
changes this behaviour and allows to append additional policy rules to the policy file node. Similarly the config option IMA_READ_POLICY
allows to read back the currently loaded policy from the kernel.
If a policy involves digital signatures then the appropriate public or symmetric keys need to be loaded into the kernel keyring before the policy is activated, because otherwise the IMA or EVM appraisal can't take place, all verifications will fail and access is denied.
In newer kernels, required public key paths (in X.509 DER format) can also be compiled into the kernel so they're immediately available.
For custom policies, the policy needs to be activated as soon as possible in the initrd during boot. See Enabling IMA/EVM during early boot. For testing, the policy can also be loaded manually at a later time.
Once an IMA policy becomes active, the respective measurement and appraisal takes place. The behaviour can't be disabled any more except by rebooting. Therefore a system can be rendered unusable if an appraisal setup is broken. Kernel command line parameters like ima_appraise=off
can be used to disable IMA restrictions completely.
How to enable EVM
Unlike IMA, EVM doesn't use a policy rule set. The metadata protection is implicitly enforced on behalf of IMA.
For EVM there only exists a one-way on-switch. During boot EVM will be initially disabled. This is necessary to allow loading of the necessary keys into the kernel that will be used for verifying signatures or HMACs. This should be done in the initrd, see Enabling IMA/EVM during early boot.
To manually enable EVM, a value of "1" needs to be written into the file node evm
in the securityfs which is normally mounted on /sys/kernel/security
:
root # echo 1 >/sys/kernel/security/evm
Activating EVM only works if there is a key loaded into the kernel keyring. The outcome of enabling EVM can be checked in the kernel log in dmesg
. The value can also be read back from the evm
file node to check whether EVM has been successfully enabled. Once it has been enabled it is not possible to disable it again.
Before enabling EVM it is therefore necessary to generate appropriate digital signatures or HMACs for all relevant files that are protected by IMA or SELinux or another security framework that interacts with EVM.
IMA Policy Grammar
For IMA there exists a policy rule set that defines exactly which files on the file system should be measured or appraised. The official documentation for the policy grammar can be found here. The documentation is a little sparse, however.
When writing custom policies the dont_measure
and dont_appraise
lines from the default policies should be taken over. They exclude pseudo files on /proc
, /sys
, remote network file systems and alike from IMA processing.
It is not possible to restrict rules to paths, like "measure all files from /home". This limitation is probably there for performance reasons. As every file open()
and some other file related operations need to be hooked by IMA it would be costly to compare paths. Also in some contexts there is not even any path known like with mmap()
.
Each policy rule must start with one of the following actions:
measure
: Perform IMA measurementdont_measure
: Exclude from IMA measurementappraise
: Perform IMA appraisaldont_appraise
: Exclude from IMA appraisalaudit
: Add messages to audit log
Application of a rule can be limited a number of conditions that are listed in the following table:
condition | description |
---|---|
fsmagic=<magic>
|
the file must be located on the given file system type. For possible values see man 2 statfs .
|
fsuuid=<id>
|
the file must be located on the file system with the given UUID. |
fowner=0 , fowner<1000
|
the file must be owned by the given UID or must be smaller/greater than the given UID. The latter is only possible in kernels >= 4.12. |
uid=0 , euid=0
|
the process trying to access the file must be running as the given (effective) uid. |
func=<context>
|
limit to a certain file operation, see table below. |
mask=MAY_READ
|
limit to certain file open modes, MAY_READ means that the process does request / have read permissions on the file. Can also be inverted with ^ i.e. ^MAY_READ means that the process does not request / have read permissions on the file.
|
This table lists the possible values for the func=<context>
condition:
value | description |
---|---|
BPRM_CHECK
|
"binary program check". this means the file is about to be executed as a program. |
MMAP_CHECK
|
the file about to be mapped into process memory. |
FILE_CHECK
|
the file is about to be opened. |
MODULE_CHECK
|
the file is supposed to be loaded as a kernel module. |
FIRMWARE_CHECK
|
The file is supposed to be loaded as a firmware blob into the kernel. |
KEXEC_KERNEL_CHECK
|
The file is supposed to be loaded as a kernel in the kexec() system call (since Kernel 4.6).
|
KEXEC_INITRAMFS_CHECK
|
The file is supposed to be loaded as an initramfs in the kexec() system call (since Kernel 4.6).
|
POLICY_CHECK
|
The file is supposed to be loaded as an additional IMA policy. |
Finally there is a number of options for each rule:
appraise_type=imasig
: For appraisal this requires that the file carries a digital signature, not just a digest.pcr=<num>
: For measurement rules the selected PCR register of the TPM should be extended, not the default PCR register.
Processing Logic
For each file IMA encounters, the complete stack of rules is cycled through, in the order given. If a dont_measure
or dont_appraise
rule matches then the processing is aborted and further rules won't apply. Otherwise the actions of the rest of the rules accumulate. For example:
measure func=BPRM_CHECK measure func=FILE_MMAP appraise fowner=0
These two rules would mean that for both, executing or memory mapping files, the measurement action would be performed. Also for files owned by root
the appraisal action would be performed.
The rule conditions are logically AND
ed i.e. if any of the conditions is not fulfilled, the rule is not executed. For example the following rule:
measure func=FILE_CHECK mask=MAY_READ euid=0
would only match if a file is opened for read by a process running as uid zero that wants to open a file including READ
permission.
Kernel Command Line Options
The following is an excerpt from the IMA kernel options. They influence how IMA and EVM operate and are mostly useful to enable default policies or to operate in a fixup mode during provisioning. The parameters need to be passed to the kernel during boot e.g. by adding them temporarily from the bootloader menu, or by adding additional boot loader entries via configuration.
ima_appraise=off|enforce|fix|log
off
: don't do appraisal of any filesenforce
: reject access to files not matching the expected hash according to policy (default)fix
: update hash values of files not matching the expectations, only for files that have no digital signature in security.ima!log
: allow access to files with bad hashes, but log them (typically to /var/log/audit/audit.log)
ima_appraise_tcb
(deprecated since Linux 4.13): seeima_policy=appraise_tcb
ima_tcb
: seeima_policy=tcb
ima_policy=tcb|appraise_tcb|secure_boot
tcb
: Apply an IMA policy that meets the needs of the Trusted Computing Base (TCB). Measure all programs exec'd, mmap'd for exec, opened with read bit set by (euid, uid) == 0.appraise_tcb
: Use the builtin IMA appraise policy, i.e. appraise all files owned by uid=0.secure_boot
: Appraises the integrity of files based on file signatures
evm=fix
: Allow the security.evm attribute to be updated even if it is currently invalid.ima_hash=md5|sha1|rmd160|sha256|sha384
: The default hash algorithm to use for IMA measurementintegrity_audit=0|1
: If set then additional informational auditing messages will be logged (not in the kernel docs?)ima_template=ima|ima-ng|ima-sig
: Selects a logging format for the measurement logima
only supports sha1 digestsima-ng
supports longer digestsima-sig
also includes the digital signature
ima_template_fmt
: Allows to define a custom logging format from field namesevmkey=<path>
: (only dracut) Specifies an alternate location of the EVM HMAC key to loadevmx509=<path>
: (only dracut): Specifies an alternate location of the EVM X.509 certificate to load
Enabling IMA/EVM during early boot
Dracut
Dracut has support for loading IMA and EVM keys, for loading an IMA policy and for enabling EVM. For this the openSUSE package dracut-ima
needs to be installed. If this is not available on your distribution, then you can try to install the dracut integrity modules manually.
Dracut performs the following steps:
For IMA:
- the IMA keys are looked up in
/etc/keys/ima
. Only X.509 certificates are supported. They will be passed toevmctl import
by dracut. - the IMA policy is looked for in
/etc/sysconfig/ima-policy
and will be loaded after the public keys are setup.
For EVM:
- the masterkey module looks in
/etc/keys/kmk-trusted.blob
for the kernel master keyring (trusted if a TPM is used, user for a software based key). - the integrity module looks in
/etc/keys/evm-trusted.blob
for an encrypted HMAC key and in/etc/keys/x509_evm.der
for a public X.509 certificate to load. The X.509 certificate is only loaded if an HMAC key was also found. - If at least an EVM HMAC key could be loaded then EVM is enabled in the kernel.
After installing the dracut IMA module and placing keys, certificates and policy at the correct locations, a new initrd can be built using dracut -f
. On the next boot with this new initrd, dracut should try to load the keys and enable the IMA policy.
If the IMA/EVM setup in the initrd is not working correctly the system may fail to boot at all. The kernel options ima_appraise=off
and evm=fix
can help in these cases. For safety it can be useful to keep an initrd without IMA support around for falling back to.
systemd
systemd currently has only support for loading a custom IMA policy file. The IMA support is currently not enabled in openSUSE's systemd package. When enabled then it looks for the policy file in /etc/ima/ima-policy
and loads it into the kernel.
Additional Helpers
getfattr
The command getfattr
from the attr
package can be used to check whether a file has any IMA/EVM related extended attributes:
# getfattr -m . -d /usr/bin/strace
Similarly the setfattr
command can be used for removing IMA or EVM attributes:
# setfattr -x security.ima /usr/bin/strace
ima_inspect
The binary data stored in the security.evm and security.ima attributes cannot be easily viewed using the evmctl
or getfattr
program. To get a human readable description of the contained data the program ima_inspect
can be used which can be found here. A corresponding ima-inspect
package is by now part of more recent openSUSE and SUSE Linux Enterprise releases (SLE-15 and newer, Tumbleweed, Leap 15 and newer).
To use it, the program simply has to be pointed to the file(s) in question:
user $ ./ima_inspect /usr/bin/ls
/usr/bin/ls
security.ima
------------
digital signature version 2
digest algorithm: sha256
key-id v2 (gpg compatible): 5f3bcd3a
signature length: 2048 bits
signature data:
87f3310cd4a917e9 ac74691e75a0790a 9e6d3f3e9c93b386 093913487ec96884 c51558521af5a124 7efea335d92a494f ef0e16b5b60a4434 0aef5df778ec97d4
728e154a202bc03b 4a464ebc271821dd f58f10c4a85d31c0 b0a66333cfd93938 54ceb3cd3dfb30d7 02ffa491f8c75223 c398c1c2bf1c5603 e7e19822016964fd
61c5eb7e428a0858 363987a41864129a a421c3770496dee8 944f974917322474 0b8a00df5bcc38b3 9c911c75ee5c8188 3ae8933d657e0a72 11a60d8934c75003
b842a5535bd0a0f2 76628e699d2ef1c6 18aad63686d6873b 0cf1242e872c4db3 5a6f248bb1efc756 f8278f0b79e4677a 941c4cc1e05b59ec 6d72a8e2e76a3112
security.evm
------------
no such attribute
Examples
The following practical guides are based on openSUSE distributions but should mostly apply to any current Linux distribution except from differences in package management and kernel support.
root
user and will often modify all files on disk. Data can easily be lost by mistake or the system will not be able to boot any more. Therefore the examples should only be tested on expendable machines or with very much care (and backups).General Prerequisites
The kernel needs to support IMA. Check the output of
zgrep CONFIG_IMA /proc/config.gz
to see which IMA related features are enabled.A current version of
evmctl
is needed, it is installed viazypper in evmctl
or needs to be compiled manually by checking it out from the upstream project.The
getfattr
andsetfattr
commands from theattr
package is required, which is installed viazypper in attr
.The dracut integrity modules are required for creating a suitable initrd with support for loading IMA and EVM keys, certificates and policies. Install it via
zypper in dracut-ima
or obtain the necessary modules manually.For all examples except those that solely rely on digital signatures for immutable files, filesystems with iversion mount option support must be used. btrfs has iversion enabled by default. xfs has iversion support in v5, also enabled by default. ext4 it requires to add
iversion
mount option to the/etc/fstab
and also add the kernel command line parameterrootflags=iversion
which will cause the dracut based initrd to add this mount flag for the root file system. On older version of dracut supposedlyrootflags=i_version
needs to be used, but current dracut fails to boot with this variant.The purpose of iversion mount option is to enable IMA to notice changes to files and be able to remeasure its content or to update hashes of HMACs, depending on the configuration. For more info see section FILESYSTEM-INDEPENDENT MOUNT OPTIONS in
mount(8)
.For being able to store data in extended attributes the
xattr
mount option needs to be used for all involved file systems (this is typically enabled by default).On small systems like on SUSE Linux Enterprise MicroOS you may also need to install
keyutils
.
IMA Measurement
This example shows how to enable IMA measurement of file contents. The measurement in this case will be restricted to files which are read by root
as well as all files that are executed in some way.
Reboot with tcb policy
first the system needs to be rebooted with kernel command line parameter ima_policy=tcb
set. This will activate a builtin policy rule set that performs measurement for all root
owned files. Note that this can also cause a kind of local denial of service, because regular users can cause the integrity log to grow rapidly.
Inspecting the integrity log
The integrity log can be found in /sys/kernel/security/ima/ascii_runtime_measurements
. The format varies based on the ima_template=
and ima_template_fmt=
kernel command line parameters which are optionally. Typically each line consists of the digest algorithm, hash and file name that was measured.
ima_template
Select one of defined IMA measurements template formats with: ima_template={ "ima" | "ima-ng" | "ima-sig" }
ima_template=ima
: In this mode, the system will create measurement value of target files with SHA1 digests, eg:10 45adda1f5d7fc3885f4e6d14b1107673f1cbc786 ima 3b7621d11aee17e96aef4fc2adfa5c344c586157 /lib64/ld-2.26.so
ima_template=ima-ng
: It is the default mode if no ima_template specified. The system will create longer measurement value of target files with SHA256 digests, eg:10 8674f3f06a823e6a06da98f409a67be0101f9bf7 ima-ng sha256:0ea8d8b9f6527ad176fcab0321271fa936c8faf9bac71eb7eef4c68e76e0e5f1 /lib64/ld-2.26.so
ima_template=ima-sig
: The system will create measurement value of target files like:10 60e1faa9118bda69cdec0976e94c30993aaff7ea ima-sig sha256:0ea8d8b9f6527ad176fcab0321271fa936c8faf9bac71eb7eef4c68e76e0e5f1 /lib64/ld-2.26.so
ima_template_fmt
Define a custom template format with: ima_template_fmt={ "field1|...|fieldN" }
The valide value for the field are:
d
- the digest of the event (i.e. the digest of a measured file), calculated with the SHA1 or MD5 hash algorithmn
- the name of the event (i.e. the file name), with size up to 255 bytesd-ng
- the digest of the event, calculated with an arbitrary hash algorithm (field format: [:]digest, where the digest prefix is shown only if the hash algorithm is not SHA1 or MD5)n-ng
- the name of the event, without size limitationssig
- the file signature
The customized ima_template_fmt fields equivalent to the build-in formats:
- Default format for
ima_template=ima
is same asima_template_fmt='d|n'
- Default format for
ima_template=ima-ng
is same asima_template_fmt='d-ng|n-ng'
- Default format for
ima_template=ima-sig
is same asima_template_fmt='d-ng|n-ng|sig'
Verifying the log using the TPM
If a TPM chip is available in the system then a pre-defined PCR register of the TPM is by default extended for each measurement in the integrity log as explained in IMA Measurement. The details of verification and remote attestation are beyond the scope of this document. Please refer to the official documentation for more on this topic.
IMA Appraisal using Hashes
In this example IMA will be setup to check file hash digests before allowing access to files belonging to the TCB. For our purposes all files owned by root
are considered to be part of the TCB.
Reboot in IMA fix mode: the system needs to be rebooted with the kernel parameters
ima_appraise=fix ima_appraise_tcb
. In this mode IMA hashes can be updated and will also be automatically corrected by the IMA module in the kernel in case a file is modified.Creating hashes: all regular files owned by
root
need to be hashed. Pseudo file systems need to be excluded. Note that the-fstype
needs to be replaced by the file system type(s) present on the system. In this case the default openSUSE file systembtrfs
is assumed. For updating the hash of a file all that needs to be done is opening it for reading. Therefore the statement sh -c "< '{}'" just does that with each file encountered:root # /usr/bin/find / -fstype btrfs -type f -uid 0 -exec sh -c "< '{}'" \;
Files can be checked with
getfattr -m . -d <path>
to see that they all should have asecurity.ima
extended attribute carrying the sha256 digest of the file contents.For demonstration purposes the attribute can be removed from some dispensable file so the appraisal can be seen in action in the next step:
# drop the digest from 'strace' for demo purposes root # setfattr -x security.ima /usr/bin/strace
Reboot with IMA appraise policy: The kernel parameter
ima_appraise=fix
from step 1 needs to be dropped now (but not the other one). This will enable a builtin policy rule set that performs appraisal of all files owned byroot
. After this,root
owned files are only accessible when they have valid hash digests.Continuing the demo from step 2 it should now be the case that
strace
can no longer be executed byroot
:root # /usr/bin/strace -bash: /usr/bin/strace: Permission denied # dmesg should show what caused this root # dmesg | tail -n 1 audit: type=1800 audit(1508942646.831:35): pid=2237 uid=0 auid=0 ses=1 op="appraise_data" cause="missing-hash" comm="bash" name="/usr/bin/strace" dev="vda2" ino=332 res=0
Volatile files like configuration files or log files would fail to verify once they are edited or otherwise changed, because the digest would no longer match. Therefore IMA implicitly recalculates and stores updated hashes in the security.ima
attribute once a file is changed. This is what the iversion
mount option is necessary for.
This kind of IMA appraisal provides no tight security on its own. Offline file tampering is still possible as long as the correct security.ima
attributes are added to files. To make it more secure it can be combined with EVM HMACs. In this case EVM protects the security.ima
against tampering with a secret key that is stored in the TPM (in the best case). See EVM concept and EVM HMAC example for more information.
IMA Appraisal using Digital Signatures
In this example IMA will be used to allow only digitally signed files to be executed.
Generation of Certificate and Private keys
For release earlier than openSUSE Leap 15 or SLE 15
It is first needed to create a X.509 certificate and a corresponding private PEM RSA key with OpenSSL. A configuration file for the creation of the certificate needs to be written. The organisation (O
), common name (CN
) and email address should be adjusted to fit your needs.
# store the certificates and keys in a separate folder
root # mkdir ~/certs
root # cd ~/certs
# write the config file for openssl
root # cat <<END >self_signed.conf
[ req ]
default_bits = 2048
default_md = sha256
distinguished_name = req_distinguished_name
prompt = no
string_mask = utf8only
x509_extensions = myexts
[ req_distinguished_name ]
O = IMASUSE
CN = Executable Signing Key
emailAddress = some@body.com
[ myexts ]
basicConstraints=critical,CA:FALSE
keyUsage=digitalSignature
subjectKeyIdentifier=hash
authorityKeyIdentifier=keyid
END
Next the certificate and private key will be created using OpenSSL and the configuration file. You should choose a suitable passphrase and keep the private key very secure if you intend to use it for production purposes.
# this environment variable will contain the passphrase for the private key
root # export PASS=mypass
root # /usr/bin/openssl req -x509 -new -passout env:PASS -utf8 -days 60 -batch -config self_signed.conf -outform DER -out ima_cert.der -keyout ima_priv.pem
For openSUSE Leap 15, SLE 15 and later release (MOK method)
Since upcoming SUSE Linux Enterprise and openSUSE distribution, MOK (Machine Owner Key) is the only way to enroll an customized IMA key, UEFI secure boot is a prerequisite. Instead of above method, follow the details at UEFI - Booting_a_custom_kernel to:
# Create a X.509 key/certificate pair, and convert certificate to DER format (ima_cert.der)
# Create new signature for the kernel file with pesign
# Reboot to MokManager, enroll the certificate
Make sure the secure boot is enabled and boot the system with kernel signed by MOK
The reason for MOK can not be used on IMA/EVM currently
Creation of Signatures for Relevant Files
Now that a suitable certificate and private key are available, the IMA signatures can be created. Digital signatures are only suitable for immutable files i.e. files that aren't changed during runtime or interactively. For this example all files owned by root
that are executable (scripts, binaries, libraries, kernel modules) will be signed.
Be aware that in the following command lines the private key passphrase is passed via a command line switch of evmctl
, which is bad practice, since regular users can see this parameter in the ps
listing. Sadly evmctl
does not provide an alternative at the moment.
# replace the filesystem type with what you're using
root # export FS=btrfs
# sign all executable files owned by root
root # /usr/bin/find / -fstype $FS -type f -executable -uid 0 -exec evmctl -a sha256 ima_sign -pmypass -k /root/certs/ima_priv.pem '{}' \;
# sign all libraries which don't carry an executable bit
root # for D in /lib /lib64 /usr/lib /usr/lib64; do
/usr/bin/find "$D" -fstype $FS -\! -executable -type f -name "*.so*" -uid 0 -exec evmctl -a sha256 ima_sign -pmypass -k /root/certs/ima_priv.pem '{}' \;
done
# also sign kernel modules
root # /usr/bin/find /lib/modules -fstype $FS -type f -name "*.ko" -uid 0 -exec evmctl -a sha256 ima_sign -pmypass -k /root/certs/ima_priv.pem '{}' \;
# also sign firmware files
root # /usr/bin/find /lib/firmware -fstype $FS -type f -uid 0 -exec evmctl -a sha256 ima_sign -pmypass -k /root/certs/ima_priv.pem '{}' \;
Configuration of the IMA Policy and dracut Early Init
The next step is to copy the public X.509 certificate into the location where the dracut based initrd will find and load it from. This is in /etc/keys/ima
:
root # mkdir -p /etc/keys/ima
root # cp /root/certs/ima_cert.der /etc/keys/ima
Finally an IMA policy rule set needs to be written to /etc/sysconfig/ima-policy
from where the initrd will load and activate it. For the purposes of this example the following policy is used:
root # cat <<END >/etc/sysconfig/ima-policy
# PROC_SUPER_MAGIC
dont_measure fsmagic=0x9fa0
dont_appraise fsmagic=0x9fa0
# SYSFS_MAGIC
dont_measure fsmagic=0x62656572
dont_appraise fsmagic=0x62656572
# DEBUGFS_MAGIC
dont_measure fsmagic=0x64626720
dont_appraise fsmagic=0x64626720
# TMPFS_MAGIC
dont_measure fsmagic=0x01021994
dont_appraise fsmagic=0x01021994
# RAMFS_MAGIC
dont_appraise fsmagic=0x858458f6
# DEVPTS_SUPER_MAGIC
dont_measure fsmagic=0x1cd1
dont_appraise fsmagic=0x1cd1
# BINFMTFS_MAGIC
dont_measure fsmagic=0x42494e4d
dont_appraise fsmagic=0x42494e4d
# SECURITYFS_MAGIC
dont_measure fsmagic=0x73636673
dont_appraise fsmagic=0x73636673
# SELINUX_MAGIC
dont_measure fsmagic=0xf97cff8c
dont_appraise fsmagic=0xf97cff8c
# CGROUP_SUPER_MAGIC
dont_measure fsmagic=0x27e0eb
dont_appraise fsmagic=0x27e0eb
# CGROUP2_SUPER_MAGIC
dont_measure fsmagic=0x63677270
dont_appraise fsmagic=0x63677270
# NSFS_MAGIC
dont_measure fsmagic=0x6e736673
dont_appraise fsmagic=0x6e736673
appraise func=BPRM_CHECK fowner=0 appraise_type=imasig
appraise func=BPRM_CHECK euid=0 appraise_type=imasig
appraise func=FILE_MMAP fowner=0 mask=MAY_EXEC appraise_type=imasig
appraise func=FILE_MMAP euid=0 mask=MAY_EXEC appraise_type=imasig
appraise func=MODULE_CHECK appraise_type=imasig
appraise func=FIRMWARE_CHECK appraise_type=imasig
# this is only for newer kernels that support loading policies
# from file by writing the file path to the ima sysfs node
appraise func=POLICY_CHECK appraise_type=imasig
END
The bulk of the rule set consists of dont_measure
and dont_appraise
rules borrowed from the IMA policy documentation. These exclude pseudo file systems from IMA appraisal.
The interesting rules are the appraise
rules which practically say the following: Require all files that are directly executed or memory mapped with execute permission to carry a digital signature. This is limited to files either owned by root
(fowner=0
) or to files opened by processes running as root
(euid=0
). Additionally kernel modules and firmware files loaded into the kernel also require digital signatures.
With this rule set it is made sure that:
- all
root
owned binaries executed byroot
or any other user are digitally signed and can be trusted - all files that a process with
root
privileges executes are digitally signed and can be trusted - all files that are loaded into the kernel are digitally signed and can be trusted
Regular users can still build their own binaries and run them without the need for digital signatures.
To verify one single file has been signed properly:
root # evmctl ima_verify /usr/bin/strace
The command should output nothing if it is successful verified.
Or you could check the signature in security.ima directly:
root # getfattr -m . -d /usr/bin/strace
# file: usr/bin/strace
security.ima=0sAwIE6yGPDAEAk0bU/ZA1iwEB/aYPx6bdlPDnMSPGggrwqdAALHKrVlOJEH/mD8OLazqM/+skok9EE/3JR04IKaIYDRqwU9XOVpE1P040ZFrvXp3L3t8CJCqHUW0JxDJ7gpbAgzWxeqeaW3nfErNwvlUxaG8CDrXjpZjd/bGeGemCm7gD+t3DhNS0HSgCh4ijTbD90+65WdE4UDCYBrdc+zRZRz77Xn/eHbj8b2ilh5dEtVufvZL9LfUqUiCcw9oq3Zn/9rnXlX1kxcOrmbwxAfpItFjbM3bAJS8QQYajU7l1A+w/4VA/mfcMuthNZJtdlawlk+eSH2MJNXmKr/qoYuFlRwxGHnFOCw==
Rebooting and Testing
Once everything is in place, the system needs to be rebooted and the initrd should automatically load the X.509 certificate into the kernel keyring and activate the custom IMA policy. If the boot should fail, then the kernel parameter ima_appraise=off
helps to disable the IMA appraisal temporarily again. If everything went well, the system should have booted like normal. You should see a message in the kernel log about the policy update:
root # dmesg | grep IMA:.*completed
IMA: policy update completed
When the security.ima
attribute that carries the digital signature is removed from a file then it should not be possible to execute it any more:
root # setfattr -x security.ima /usr/bin/strace
root # /usr/bin/strace
-bash: /usr/bin/strace: Permission denied
Similarly the root
user should not be able to run any binaries owned by regular users. Any regular users should also not be able to run any root
owned binaries with missing signatures.
Note, however, that scripts cannot be really secured by IMA appraisal and the behaviour regarding digital signatures is a bit strange.
For production purposes the private key in /root/certs/ima_priv.pem
should be removed from the system.
Updating software on a digitally signed system won't work if the RPMs that are installed don't carry suitable digital signatures as well.
EVM Protection Using HMACs
In this example we will configure EVM to protect file metadata and the security.ima
extended attribute.
Creation of Kernel Master Key and EVM HMAC key
For the EVM HMAC operation a secret symmetric key needs to be loaded into the kernel. This key is used both for creating updated HMACs and for verifying existing HMACs. For good security this secret key should be coupled to a TPM chip (so called trusted keys). For this example software based keys will be used, however (so called encrypted keys). For more information about the key generation see the evmctl README and the Gentoo Linux EVM guide.
# this creates a "kernel master keyring" and stores its representation in
# /etc/keys
root # /bin/keyctl add user kmk-user "`dd if=/dev/urandom bs=1 count=32 2>/dev/null`" @u
root # /bin/keyctl pipe `/bin/keyctl search @u user kmk-user` > /etc/keys/kmk-user.blob
# this creates an EVM key which will be used for EVM HMACs
root # /bin/keyctl add encrypted evm-key "new user:kmk-user 64" @u
root # /bin/keyctl pipe `/bin/keyctl search @u encrypted evm-key` >/etc/keys/evm.blob
The EVM key in evm.blob
is derived from the kernel master keyring kmk-user.blob
, so they need to be loaded in the correct order and the correct way to work. dracut will do just that during boot if some configuration files are adjusted accordingly:
# configuration for loading the kmk via dracut
root # cat <<END >/etc/sysconfig/masterkey
MASTERKEYTYPE="user"
MASTERKEY="/etc/keys/kmk-user.blob"
END
# configuration for loading the evm key via dracut
root # cat <<END >/etc/sysconfig/evm
EVMKEY="/etc/keys/evm.blob"
END
Rebooting into IMA/EVM Fix Mode
The system now needs to be rebooted with the kernel parameters evm=fix ima_appraise=fix ima_appraise_tcb
. Similarly to IMA Appraisal with Hashes this causes all files owned by root
to be appraised. And the IMA and EVM kernel modules automatically fix up invalid hashes and HMACs. When the key setup from the previous step was correct and dracut successfully loaded them, then EVM should now be enabled which can be tested this way:
root # cat /sys/kernel/security/evm
1
Once EVM is enabled it cannot be disabled again except by rebooting and changing kernel parameters or changing the dracut configuration.
The following command will cause IMA hashes to be created for all root
owned files. This will also implicitly trigger the EVM HMAC generation for those files. Note that the -fstype
needs to be adjusted to match the file systems actually in use on the system. This operation will take a couple of minutes depending on how fast the disk access is and how many files are present on the file system.
root # /usr/bin/find / -fstype btrfs -type f -uid 0 -exec evmctl -a sha256 ima_hash '{}' \;
Inspecting the files, both security.ima
and security.evm
attributes should now be visible:
root # getfattr -m . -d /usr/bin/strace
# file: usr/bin/strace
security.evm=0sAjJ76U7zXW65413dvLse3r3Mf7Yf
security.ima=0sBAToCmv9mpTW9VIp7fJ+Cyy4W8LXX4ELzGROf9DEtoZojg==
The EVM attribute is shorter, because it only employs sha1 digests, while the IMA attribute uses sha256 per the -a sha256
command line argument.
For seeing EVM protection in action the security.evm
attribute can be removed from some dispensable file:
# drop the HMAC from 'strace' for demo purposes
root # setfattr -x security.evm /usr/bin/strace
Rebooting into Enforced IMA/EVM Mode
After all files have got their digests and HMACs, a reboot with only the ima_appraise_tcb
kernel parameter can be performed. After the reboot all files that are protected by IMA are additionally protected by EVM i.e. before the IMA digest is checked, it is checked whether the IMA digest and other file metadata can be verified using the EVM HMAC.
This provides protection against offline file tempering, because an attacker would need the secret EVM HMAC key to produce the correct security.ima
and security.evm
attributes to make a modified file valid again. With software based EVM HMAC keys the secret key can still be found on disk, however. So only the variant using the TPM where the EVM HMAC key is a wrapped TPM key provides real protection.
To finish the demo from the previous section it should now be the case that the strace
command can no longer be executed:
root # /usr/bin/strace
-bash: /usr/bin/strace: Permission denied
And this although a valid security.ima
attribute is there:
root # getfattr -m . -d /usr/bin/strace
# file: usr/bin/strace
security.ima=0sBAToCmv9mpTW9VIp7fJ+Cyy4W8LXX4ELzGROf9DEtoZojg==
Since the HMAC for the EVM attributes is present during runtime, the EVM kernel module will implicitly update the security.evm
attribute when valid files are modified (like configuration files). This is the same mechanism as is explained in IMA Appraisal using Hashes.
EVM Protection Using Digital Signatures
Like in the previous section, in this example EVM will be setup to protect file metadata and the security.ima
extended attribute. The difference is that instead of the EVM HMAC a digital signature using a X.509 certificate is used. Just like in IMA Appraisal using Digital Signatures, this approach is only suitable for immutable files like binaries.
To continue with this example please first setup the system using EVM HMAC as described in EVM Protection Using HMACs. The reason for this is that the EVM HMAC keys are a pre-requisite for dracut loading the EVM X.509 certificate, although the HMAC keys aren't strictly needed in this case. Update:Newer versions of dracut as found in Tumbleweed, Leap 15.0 and SLES-15 can now load the X.509 certificate without HMAC keys being configure, but the kernel code won't initialize evm if no HMAC key is available, so this is still a prerequisite.
Generation of Certificate and Private Keys
For creation of the certificate and private keys, follow the procedure described here. Place the resulting private key in /root/certs/evm_priv.pem
and the public certificate in /etc/keys/x509_evm.der
. The latter is the default dracut location for the EVM X.509 certificate.
Creation of Signatures for Relevant Files
The system needs to be rebooted with kernel command line parameters ima_appraise=fix evm=fix ima_appraise_tcb
so it will be possible to replace some of the EVM HMACs with digital signatures.
The signatures are created just like for ima, with only the evmctl
command line adjusted to create EVM signatures. There is one import difference, however: We additionally need to set the immutable attribute for the files in question. This is done with help of the chattr
utility. This flag instructs the file system that no changes of any kind may be made to the file or its metadata. If this flag is not present then the EVM kernel code will start to replace the signatures with HMACs during runtime. The following commands will create EVM signatures and add immutable flags for relevant immutable files i.e. executables, kernel modules and firmware files:
# sign all executable files owned by root
root # /usr/bin/find / -fstype btrfs -type f -executable -uid 0 -exec evmctl sign -pmypass -k /root/certs/evm_priv.pem '{}' \;
# sign all libraries which don't carry an executable bit
root # for D in /lib /lib64 /usr/lib /usr/lib64; do
/usr/bin/find "$D" -fstype btrfs -\! -executable -type f -name "*.so*" -uid 0 -exec evmctl sign -pmypass -k /root/certs/evm_priv.pem '{}' \; -exec chattr +i '{}' \;
done
# also sign kernel modules
root # /usr/bin/find /lib/modules -fstype btrfs -type f -name "*.ko" -uid 0 -exec evmctl sign -pmypass -k /root/certs/evm_priv.pem '{}' \; -exec chattr +i '{}' \;
# also sign firmware files
root # /usr/bin/find /lib/firmware -fstype btrfs -type f -uid 0 -exec evmctl sign -pmypass -k /root/certs/evm_priv.pem '{}' \; -exec chattr +i '{}' \;
Be aware that EVM digital signatures currently fail on btrfs file systems. See btrfs restrictions for more information.
The EVM signature for the signed file could be verified with:
root # evmctl verify /usr/bin/strace
The command should output nothing if it is successful verified.
Rebooting into enforced IMA/EVM mode
Now the system needs to be rebooted with the kernel command line parameter ima_appraise_tcb
only. The EVM digital signatures should now be enforced.
The EVM private key in /root/certs/evm_priv.pem
should be removed from the system for best security. EVM with digital signatures is appropriate if no TPM chip is to be used and not just the file contents, but also the metadata should be protected by a digital signature. If only the file content needs to be protected then IMA with digital signatures should be enough.
Since EVM digital signatures cannot be automatically updated by the EVM kernel module, even changing the file owner, mode or security related extended attributes will cause the EVM verification to fail.
Signing Binaries in RPM packages with IMA signatures
The current rpm package from upstream ships support for adding IMA signatures to all non-configuration files in an RPM package. At the moment the openSUSE rpm package does not have IMA support compiled in, however.
Adding EVM signatures is not currently available for RPM packages. The reason for this is that the metadata that EVM covers is difficult to maintain in packages (inode numbers and such). There is a (hidden?) command line option in evmctl
to create a different digital signature format for EVM for immutable files (also see here). But this feature seems not to have made it into the IMA kernel code.
Example of using rpmsign to attach security.ima
You need to have an RPM package with IMA support available
The spec file of the RPM package that shall be signed must define the macro
_binary_filedigest_algorithm
like%define _binary_filedigest_algorithm 8
The 8 is for
sha256
. The numbers can be found in the RPM sourcebuild/files.c
, functiongenCpioListAndHeader()
.Adding the IMA signatures also requires adding a GPG signature to the RPM. See here for a quick setup of rpmsign and gpg, to achieve this.
A command line like this signed all non-configuration files in the RPM:
root # rpmsign --addsign --signfiles --fskpass=<pass> --fskpath=/root/certs/ima_priv.pem /tmp/some.rpm
Here the passphrase for the private PEM certificate is passed via the command line, which is bad practice. Supposedly a macro
_file_signing_key_password
in$HOME/.rpmmacros
should work but it didn't for me.Also even with adding the
--fskpass
,rpmsign
still asked me once for the passphrase on the command line. Without--fskpass
it asked me for every file in the package, however.
Also be aware that an RPM package that contains IMA signatures this way can't be read any more by RPM versions that don't support IMA. So it's not backward compatible.
Further Hardening of IMA/EVM
kexec() System Calls
Starting with Linux kernel 4.6 the IMA policy functions KEXEC_KERNEL_CHECK
and KEXEC_INITRAMFS_CHECK
are additionally available. They allow kernel and initramfs as they are passed in the context of a kexec()
system call to be appraised.
Doing this is important to avoid untrusted code to be executed when for example allowing only digitally signed binaries in the system.
Trusted Root Certificate in the Kernel
To get some real trust anchor into the certificate usage, a trusted system certificate can be compiled into the Linux kernel. Starting with kernel 4.5 the kernel option INTEGRITY_TRUSTED_KEYRING
is available. This allows to restrict IMA and EVM certificates to those ones that have been signed by a trusted system certificate. The system trusted certificate can be compiled into the kernel via kernel option SYSTEM_TRUSTED_KEYS
.
Using this approach it can be avoided that arbitrary additional X.509 certificates can be added during runtime which would lead to accepting additional signatures from unknown sources in security.ima
and security.evm
attributes.
This approach still allows third parties to add files signed by their own X.509 key to the system. The third party certificate needs to be signed by the system trusted key and then the third party signatures will also be accepted by IMA/EVM.
When the INTEGRITY_TRUSTED_KEYRING
kernel option is enabled then the integrity code in the kernel will itself create the .ima
keyring. This is to make sure the keyring gets the restrictions applied to only allow keys to be added that are signed by a key in the .builtin_trusted_keys
keyring. On the other hand, when the kernel option is not enabled, then dracut creates the _ima
keyring (notice the different name!) from within the initrd and loads keys onto it.
Furthermore there is kernel option CONFIG_SECONDARY_TRUSTED_KEYRING
which weakens the requirements a bit. With it keys that have been signed by a key found in the .secondary_trusted_keys
keyring are also accepted in the .ima
keyring.
These two kernel options will be activated in the upcoming SUSE Linux Enterprise 15 distribution. When using UEFI secure boot then it is possible to enroll a MOK (Machine Owner Key) in the UEFI firmware. In the evmctrl README in section "Generate trusted keys" the necessary
openssl
commands are documented for setting up a minimal CA and signing an IMA public certificate with it. The public CA certificate will need to be enrolled as a MOK and then the signed IMA public certificate can be loaded into the .ima
keyring.
This situation makes testing e.g. in virtual machines considerably more complicated. You will need a Qemu running with a UEFI firmware emulation and will have to install SLES15 in secure boot mode. Then using the
/boot/EFI/sles/MokManager.efi
EFI subroutine you can enroll the CA mentioned above. The details of configuring the UEFI firmware for secure boot vary between implementation. Refer to the secure boot page for more information.
The reason for MOK can not be used on IMA/EVM currently
Appraisal of the Policy File Itself
Starting with Linux kernel version 4.6 is has become possible to appraise policy files themselves. For this instead of writing the policy data directly to /sys/kernel/security/ima/policy
, the path of the file that contains the policy data is written. This allows subsequent policy updates to be appraised before they are accepted.
To appraise policy files, the policy rule condition func=POLICY_CHECK
needs to be used.
Appraisal of the initial policy file does not currently seem possible. The kernel option IMA_APPRAISE_SIGNED_INIT
seems to be suitable to achieve this. This option requires the init binary to be signed. Combined with a trusted system key this might provide the complete chain of trust.
Disabling of the ima_appraise=fix
kernel parameter
The kernel boot parameter ima_appraise=[...]
allows to circumvent the appraisal for attackers that have access to the kernel command line in some way. By disabling the IMA_APPRAISE_BOOTPARAM
kernel option this parameter will no longer be evaluated. This is only suitable for production systems, however, where no issues with the IMA/EVM setup remain.
This option has only been added in Linux kernel version 4.13, however.
Appraisal of RAM Based File Systems
The builtin file system exception list for IMA appraisal skips appraisal for TMPFS and RAMFS file systems. Thus executables found on e.g. a memory based /tmp
mount will not be checked for signatures or digests. The reason for this is probably the initrd which is placed into a RAM based file system during early boot. The initrd is a cpio archive which doesn't support adding metadata like extended attributes that are required by IMA.
If the initial initrd file system would be appraised then booting would fail. After early boot has finished the exception of TMPFS and RAMFS file systems weakens the security provided by IMA, however.
There have been attempts to extend the cpio archive format to carry extended attributes. But it doesn't seem to be implemented at the moment.
Performance Impact
The IMA and EVM modules perform a lot of caching on the kernel side which, avoids checks to be repeated needlessly. We need to differentiate between immutable files and files that change frequently:
- files that change rarely or are immutable and carry a digital signature will only be checked the first time they are encountered by IMA. Initial file access can thus be slowed down compared to a system that doesn't use IMA.
- files that change often and carry an IMA digest and/or an EVM HMAC will be updated/checked the first time they are accessed and also upon every modification performed on the file. Slowdown is thus higher in this case.
A system that only enforces IMA digital signatures for executable files would experience a bit slowdown during boot. During regular operation no mentionable slowdown should occur.
The slowdown of program execution for files with IMA digital signatures that are not yet in the IMA cache is about 30 % in an artificial test scenario. In practice the impact can be expected to be less due to parallelization, I/O delays and so on.
Caveats
Restrictions in SUSE distributions
The current openSUSE Leap and SLES-12 releases ship a kernel based on version 4.4, so some of the features mentioned in this document (like kexec appraisal) aren't available yet.
systemd
does not contain IMA support (usedracut
instead).The
dracut-ima
package is not available on older SUSE distributions at the moment. The missing dracut module can be copied over from the openSUSE dracut GitHub repository like this:user $ git clone git@github.com:openSUSE/dracut.git user $ cd dracut/modules.d # become root user $ su - root # cd /home/user/dracut root # cp -rvi 96securityfs 97masterkey 98integrity /usr/lib/dracut/modules.d # enable inclusion of the new module in the initrd # run this command as root root # echo 'add_dracutmodules+=" integrity "' >>/etc/dracut.conf.d/40-ima.conf # save the current initrd if something goes wrong root # cp /boot/initrd /boot/initrd.before.ima # rebuild the initrd, takes some time root # dracut -f
The
rpmsign
command from therpm
package is currently missing support for IMA/EVM signatures.The
evmctl
command fails when trying to generate EVM hashes on btrfs file systems. This is because on btrfs the UUID needs to be gathered differently than on traditional file systems. Additionally it looks like the Linux kernel assumes an all zero UUID for btrfs based file systems. To work around this, the option-u00000000-0000-0000-0000-000000000000
needs to be passed toevmctl
.There's also the possibility to exclude the file system UUID completely from EVM hashes. For this
evmctl
needs to be passed the-u
option without a value and the Linux kernel must be compiled without theCONFIG_EVM_ATTR_FSUUID
option set.Newer SUSE distributions like current Tumbleweed or SUSE Enterprise 15 Beta use the cgroup2 pseudo file system, but the ima_appraise_tcb default policy doesn't exclude this from measurement and appraisal. This will cause boot errors with systemd freezing, because it cannot access the cgroup2 mount.
Copying or Editing Files with Digital Signatures
When copying or editing files that carry digital signatures in the extended attributes security.ima or security.evm, special care has to be taken. A typical cp file1 file2
will not copy the extended attributes. So access to the file copy may be denied when appraisal is enabled.
When editing files then editors typically recreate the file in question. During this process the extended attributes will be lost and the same as with copying happens.
Using PEM RSA public keys with signature scheme version 1
When using the older signature scheme with a public/private PEM formatted RSA key, the following limitations apply:
- no digests stronger than sha1 can be used.
dracut
has no support for loading the PEM public keys so the early initiatlization cannot be performed this way.
The older signature scheme was the default in older versions of evmctl
but has to be explicitly selected in the current version by passing --rsa
as a parameter.
Digital Signatures and Executable Scripts
An IMA policy rule like appraise func=BPRM_CHECK appraise_type=imasig
causes appraisal of all executed files. On first sight this also seems to apply to scripts:
root # cat <<END >test.sh
#!/bin/bash
echo script executed
END
root # chmod +x ./test.sh
root # ./test.sh
-bash: ./test.sh: /bin/bash: bad interpreter: Permission denied
The script can still be executed explicitly via the interpreter, however:
root # /bin/bash ./test.sh
script executed
The reason for this is that the interpreter has a valid IMA digital signature and is executed as normal. The parameter to the interpreter is not validated by IMA. This would be unrealistic, because the kernel would need to know all possible interpreters and which parameters they support.
When the script is executed implicitly via the shebang line, the script is treated like an executable file, however, and IMA kicks in. This is undesirable, because it does not offer any extra security, since the script can be executed by passing it to the interpreter explicitly. It is not currently possible, however, to allow execution of unsigned scripts. This is a missing feature of IMA.
Minimum Signature and Digest Lengths
The current IMA policy grammar does not allow to mandate a minimum RSA key length or digest strength. Thus even though a policy can require files to be signed, it is not guaranteed that strong cryptography is envolved in the process. This can only be limited by the public certificates loaded into the kernel.
Enabling EVM when running with evm=fix Still Gives Permission Denied
It can happen that evm=fix
has been added to the kernel command line and after enabling EVM via /sys/kernel/security/evm
, file accesses are still refused. This is the case if IMA appraisal is enabled. In the context of IMA appraisal EVM is checked, too, and if that fails, the access if refused.
This can cause strange effects, because IMA caches appraisal results. Files that have been appraised by IMA before EVM was enabled will still work after enabling EVM. But files that aren't in the IMA cache won't work.
To fix this, both IMA and EVM need to be run in fix mode i.e. ima_appraise=fix
needs also to be added the kernel command line.
MOK (Machine Owner Key) can NOT be used for IMA/EVM
If you found that MOK (Machine Owner Key) have been enrolled to .secondary_trusted_keys on openSUSE Leap 15.0 or SLE15. It's a _side effect_ of kernel module verification, not a really supported function to SLE15. This _side effect_ be removed since SLE15-SP2 to align with v5.3 mainline kernel. The upstream mainline kernel also never has this function. In mainline kernel, the MOK be enrolled to .platform keyring which does not have linking with trusted keyrings (.builtin_trusted_keys or .secondary_trusted_keys).
The reason is that the purpose of keys in EFI db or MOK are for booting. Currently kernel upstream only accepts keys from db/mok for kexec. The trust of db/mok keys should not be extended to other purpose, e.g. IMA/EVM.
Currently there have two possible solutions that show on upstream:
- David Howells proposed patches to enhance the restriction of keys base on extendedKeyUsage extension on x.509 certification:
X.509: Restrict the usage of a key based on information in X.509 certificate
But this change did not merge to kernel mainline yet. If we can identify the purpose of keys in db/mok by X.509 information, then it's possible that we can enroll keys to different keyrings in kernel for different purpose. e.g. IMA file appraise. David's patch also be discussed in Linux Firmware Signing mailing loop:
But the direction of this mailing loop be moved to LSM with IMA finally. I think that mainline kernel should complete the IMA-filer-verify with LSM functions first.
- Eric Snowberg proposes two new EFI variables to indicate that user wants to trust platform keys in kernel or enable the secure boot IMA policy:
(2021-10-22 update)
PATCH v6 00/13 Enroll kernel keys thru MOK
Introduce a new MOK variable called MokListTrustedRT #423