| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835 |
- .. SPDX-License-Identifier: GPL-2.0
- Integrity Policy Enforcement (IPE)
- ==================================
- .. NOTE::
- This is the documentation for admins, system builders, or individuals
- attempting to use IPE. If you're looking for more developer-focused
- documentation about IPE please see :doc:`the design docs </security/ipe>`.
- Overview
- --------
- Integrity Policy Enforcement (IPE) is a Linux Security Module that takes a
- complementary approach to access control. Unlike traditional access control
- mechanisms that rely on labels and paths for decision-making, IPE focuses
- on the immutable security properties inherent to system components. These
- properties are fundamental attributes or features of a system component
- that cannot be altered, ensuring a consistent and reliable basis for
- security decisions.
- To elaborate, in the context of IPE, system components primarily refer to
- files or the devices these files reside on. However, this is just a
- starting point. The concept of system components is flexible and can be
- extended to include new elements as the system evolves. The immutable
- properties include the origin of a file, which remains constant and
- unchangeable over time. For example, IPE policies can be crafted to trust
- files originating from the initramfs. Since initramfs is typically verified
- by the bootloader, its files are deemed trustworthy; "file is from
- initramfs" becomes an immutable property under IPE's consideration.
- The immutable property concept extends to the security features enabled on
- a file's origin, such as dm-verity or fs-verity, which provide a layer of
- integrity and trust. For example, IPE allows the definition of policies
- that trust files from a dm-verity protected device. dm-verity ensures the
- integrity of an entire device by providing a verifiable and immutable state
- of its contents. Similarly, fs-verity offers filesystem-level integrity
- checks, allowing IPE to enforce policies that trust files protected by
- fs-verity. These two features cannot be turned off once established, so
- they are considered immutable properties. These examples demonstrate how
- IPE leverages immutable properties, such as a file's origin and its
- integrity protection mechanisms, to make access control decisions.
- For the IPE policy, specifically, it grants the ability to enforce
- stringent access controls by assessing security properties against
- reference values defined within the policy. This assessment can be based on
- the existence of a security property (e.g., verifying if a file originates
- from initramfs) or evaluating the internal state of an immutable security
- property. The latter includes checking the roothash of a dm-verity
- protected device, determining whether dm-verity possesses a valid
- signature, assessing the digest of a fs-verity protected file, or
- determining whether fs-verity possesses a valid built-in signature. This
- nuanced approach to policy enforcement enables a highly secure and
- customizable system defense mechanism, tailored to specific security
- requirements and trust models.
- To enable IPE, ensure that ``CONFIG_SECURITY_IPE`` (under
- :menuselection:`Security -> Integrity Policy Enforcement (IPE)`) config
- option is enabled.
- Use Cases
- ---------
- IPE works best in fixed-function devices: devices in which their purpose
- is clearly defined and not supposed to be changed (e.g. network firewall
- device in a data center, an IoT device, etcetera), where all software and
- configuration is built and provisioned by the system owner.
- IPE is a long-way off for use in general-purpose computing: the Linux
- community as a whole tends to follow a decentralized trust model (known as
- the web of trust), which IPE has no support for it yet. Instead, IPE
- supports PKI (public key infrastructure), which generally designates a
- set of trusted entities that provide a measure of absolute trust.
- Additionally, while most packages are signed today, the files inside
- the packages (for instance, the executables), tend to be unsigned. This
- makes it difficult to utilize IPE in systems where a package manager is
- expected to be functional, without major changes to the package manager
- and ecosystem behind it.
- The digest_cache LSM [#digest_cache_lsm]_ is a system that when combined with IPE,
- could be used to enable and support general-purpose computing use cases.
- Known Limitations
- -----------------
- IPE cannot verify the integrity of anonymous executable memory, such as
- the trampolines created by gcc closures and libffi (<3.4.2), or JIT'd code.
- Unfortunately, as this is dynamically generated code, there is no way
- for IPE to ensure the integrity of this code to form a trust basis.
- IPE cannot verify the integrity of programs written in interpreted
- languages when these scripts are invoked by passing these program files
- to the interpreter. This is because the way interpreters execute these
- files; the scripts themselves are not evaluated as executable code
- through one of IPE's hooks, but they are merely text files that are read
- (as opposed to compiled executables). However, with the introduction of the
- ``AT_EXECVE_CHECK`` flag (:doc:`AT_EXECVE_CHECK </userspace-api/check_exec>`),
- interpreters can use it to signal the kernel that a script file will be executed,
- and request the kernel to perform LSM security checks on it.
- IPE's EXECUTE operation enforcement differs between compiled executables and
- interpreted scripts: For compiled executables, enforcement is triggered
- automatically by the kernel during ``execve()``, ``execveat()``, ``mmap()``
- and ``mprotect()`` syscalls when loading executable content. For interpreted
- scripts, enforcement requires explicit interpreter integration using
- ``execveat()`` with ``AT_EXECVE_CHECK`` flag. Unlike exec syscalls that IPE
- intercepts during the execution process, this mechanism needs the interpreter
- to take the initiative, and existing interpreters won't be automatically
- supported unless the signal call is added.
- Threat Model
- ------------
- IPE specifically targets the risk of tampering with user-space executable
- code after the kernel has initially booted, including the kernel modules
- loaded from userspace via ``modprobe`` or ``insmod``.
- To illustrate, consider a scenario where an untrusted binary, possibly
- malicious, is downloaded along with all necessary dependencies, including a
- loader and libc. The primary function of IPE in this context is to prevent
- the execution of such binaries and their dependencies.
- IPE achieves this by verifying the integrity and authenticity of all
- executable code before allowing them to run. It conducts a thorough
- check to ensure that the code's integrity is intact and that they match an
- authorized reference value (digest, signature, etc) as per the defined
- policy. If a binary does not pass this verification process, either
- because its integrity has been compromised or it does not meet the
- authorization criteria, IPE will deny its execution. Additionally, IPE
- generates audit logs which may be utilized to detect and analyze failures
- resulting from policy violation.
- Tampering threat scenarios include modification or replacement of
- executable code by a range of actors including:
- - Actors with physical access to the hardware
- - Actors with local network access to the system
- - Actors with access to the deployment system
- - Compromised internal systems under external control
- - Malicious end users of the system
- - Compromised end users of the system
- - Remote (external) compromise of the system
- IPE does not mitigate threats arising from malicious but authorized
- developers (with access to a signing certificate), or compromised
- developer tools used by them (i.e. return-oriented programming attacks).
- Additionally, IPE draws hard security boundary between userspace and
- kernelspace. As a result, kernel-level exploits are considered outside
- the scope of IPE and mitigation is left to other mechanisms.
- Policy
- ------
- IPE policy is a plain-text [#devdoc]_ policy composed of multiple statements
- over several lines. There is one required line, at the top of the
- policy, indicating the policy name, and the policy version, for
- instance::
- policy_name=Ex_Policy policy_version=0.0.0
- The policy name is a unique key identifying this policy in a human
- readable name. This is used to create nodes under securityfs as well as
- uniquely identify policies to deploy new policies vs update existing
- policies.
- The policy version indicates the current version of the policy (NOT the
- policy syntax version). This is used to prevent rollback of policy to
- potentially insecure previous versions of the policy.
- The next portion of IPE policy are rules. Rules are formed by key=value
- pairs, known as properties. IPE rules require two properties: ``action``,
- which determines what IPE does when it encounters a match against the
- rule, and ``op``, which determines when the rule should be evaluated.
- The ordering is significant, a rule must start with ``op``, and end with
- ``action``. Thus, a minimal rule is::
- op=EXECUTE action=ALLOW
- This example will allow any execution. Additional properties are used to
- assess immutable security properties about the files being evaluated.
- These properties are intended to be descriptions of systems within the
- kernel that can provide a measure of integrity verification, such that IPE
- can determine the trust of the resource based on the value of the property.
- Rules are evaluated top-to-bottom. As a result, any revocation rules,
- or denies should be placed early in the file to ensure that these rules
- are evaluated before a rule with ``action=ALLOW``.
- IPE policy supports comments. The character '#' will function as a
- comment, ignoring all characters to the right of '#' until the newline.
- The default behavior of IPE evaluations can also be expressed in policy,
- through the ``DEFAULT`` statement. This can be done at a global level,
- or a per-operation level::
- # Global
- DEFAULT action=ALLOW
- # Operation Specific
- DEFAULT op=EXECUTE action=ALLOW
- A default must be set for all known operations in IPE. If you want to
- preserve older policies being compatible with newer kernels that can introduce
- new operations, set a global default of ``ALLOW``, then override the
- defaults on a per-operation basis (as above).
- With configurable policy-based LSMs, there's several issues with
- enforcing the configurable policies at startup, around reading and
- parsing the policy:
- 1. The kernel *should* not read files from userspace, so directly reading
- the policy file is prohibited.
- 2. The kernel command line has a character limit, and one kernel module
- should not reserve the entire character limit for its own
- configuration.
- 3. There are various boot loaders in the kernel ecosystem, so handing
- off a memory block would be costly to maintain.
- As a result, IPE has addressed this problem through a concept of a "boot
- policy". A boot policy is a minimal policy which is compiled into the
- kernel. This policy is intended to get the system to a state where
- userspace is set up and ready to receive commands, at which point a more
- complex policy can be deployed via securityfs. The boot policy can be
- specified via ``SECURITY_IPE_BOOT_POLICY`` config option, which accepts
- a path to a plain-text version of the IPE policy to apply. This policy
- will be compiled into the kernel. If not specified, IPE will be disabled
- until a policy is deployed and activated through securityfs.
- Deploying Policies
- ~~~~~~~~~~~~~~~~~~
- Policies can be deployed from userspace through securityfs. These policies
- are signed through the PKCS#7 message format to enforce some level of
- authorization of the policies (prohibiting an attacker from gaining
- unconstrained root, and deploying an "allow all" policy). These
- policies must be signed by a certificate that chains to the
- ``SYSTEM_TRUSTED_KEYRING``, or to the secondary and/or platform keyrings if
- ``CONFIG_IPE_POLICY_SIG_SECONDARY_KEYRING`` and/or
- ``CONFIG_IPE_POLICY_SIG_PLATFORM_KEYRING`` are enabled, respectively.
- With openssl, the policy can be signed by::
- openssl smime -sign \
- -in "$MY_POLICY" \
- -signer "$MY_CERTIFICATE" \
- -inkey "$MY_PRIVATE_KEY" \
- -noattr \
- -nodetach \
- -nosmimecap \
- -outform der \
- -out "$MY_POLICY.p7b"
- Deploying the policies is done through securityfs, through the
- ``new_policy`` node. To deploy a policy, simply cat the file into the
- securityfs node::
- cat "$MY_POLICY.p7b" > /sys/kernel/security/ipe/new_policy
- Upon success, this will create one subdirectory under
- ``/sys/kernel/security/ipe/policies/``. The subdirectory will be the
- ``policy_name`` field of the policy deployed, so for the example above,
- the directory will be ``/sys/kernel/security/ipe/policies/Ex_Policy``.
- Within this directory, there will be seven files: ``pkcs7``, ``policy``,
- ``name``, ``version``, ``active``, ``update``, and ``delete``.
- The ``pkcs7`` file is read-only. Reading it returns the raw PKCS#7 data
- that was provided to the kernel, representing the policy. If the policy being
- read is the boot policy, this will return ``ENOENT``, as it is not signed.
- The ``policy`` file is read only. Reading it returns the PKCS#7 inner
- content of the policy, which will be the plain text policy.
- The ``active`` file is used to set a policy as the currently active policy.
- This file is rw, and accepts a value of ``"1"`` to set the policy as active.
- Since only a single policy can be active at one time, all other policies
- will be marked inactive. The policy being marked active must have a policy
- version greater or equal to the currently-running version.
- The ``update`` file is used to update a policy that is already present
- in the kernel. This file is write-only and accepts a PKCS#7 signed
- policy. Two checks will always be performed on this policy: First, the
- ``policy_names`` must match with the updated version and the existing
- version. Second the updated policy must have a policy version greater than
- the currently-running version. This is to prevent rollback attacks.
- The ``delete`` file is used to remove a policy that is no longer needed.
- This file is write-only and accepts a value of ``1`` to delete the policy.
- On deletion, the securityfs node representing the policy will be removed.
- However, delete the current active policy is not allowed and will return
- an operation not permitted error.
- Similarly, writing to both ``update`` and ``new_policy`` could result in
- bad message(policy syntax error) or file exists error. The latter error happens
- when trying to deploy a policy with a ``policy_name`` while the kernel already
- has a deployed policy with the same ``policy_name``.
- Deploying a policy will *not* cause IPE to start enforcing the policy. IPE will
- only enforce the policy marked active. Note that only one policy can be active
- at a time.
- Once deployment is successful, the policy can be activated, by writing file
- ``/sys/kernel/security/ipe/policies/$policy_name/active``.
- For example, the ``Ex_Policy`` can be activated by::
- echo 1 > "/sys/kernel/security/ipe/policies/Ex_Policy/active"
- From above point on, ``Ex_Policy`` is now the enforced policy on the
- system.
- IPE also provides a way to delete policies. This can be done via the
- ``delete`` securityfs node,
- ``/sys/kernel/security/ipe/policies/$policy_name/delete``.
- Writing ``1`` to that file deletes the policy::
- echo 1 > "/sys/kernel/security/ipe/policies/$policy_name/delete"
- There is only one requirement to delete a policy: the policy being deleted
- must be inactive.
- .. NOTE::
- If a traditional MAC system is enabled (SELinux, apparmor, smack), all
- writes to ipe's securityfs nodes require ``CAP_MAC_ADMIN``.
- Modes
- ~~~~~
- IPE supports two modes of operation: permissive (similar to SELinux's
- permissive mode) and enforced. In permissive mode, all events are
- checked and policy violations are logged, but the policy is not really
- enforced. This allows users to test policies before enforcing them.
- The default mode is enforce, and can be changed via the kernel command
- line parameter ``ipe.enforce=(0|1)``, or the securityfs node
- ``/sys/kernel/security/ipe/enforce``.
- .. NOTE::
- If a traditional MAC system is enabled (SELinux, apparmor, smack, etcetera),
- all writes to ipe's securityfs nodes require ``CAP_MAC_ADMIN``.
- Audit Events
- ~~~~~~~~~~~~
- 1420 AUDIT_IPE_ACCESS
- ^^^^^^^^^^^^^^^^^^^^^
- Event Examples::
- type=1420 audit(1653364370.067:61): ipe_op=EXECUTE ipe_hook=MMAP enforcing=1 pid=2241 comm="ld-linux.so" path="/deny/lib/libc.so.6" dev="sda2" ino=14549020 rule="DEFAULT action=DENY"
- type=1300 audit(1653364370.067:61): SYSCALL arch=c000003e syscall=9 success=no exit=-13 a0=7f1105a28000 a1=195000 a2=5 a3=812 items=0 ppid=2219 pid=2241 auid=0 uid=0 gid=0 euid=0 suid=0 fsuid=0 egid=0 sgid=0 fsgid=0 tty=pts0 ses=2 comm="ld-linux.so" exe="/tmp/ipe-test/lib/ld-linux.so" subj=unconfined key=(null)
- type=1327 audit(1653364370.067:61): 707974686F6E3300746573742F6D61696E2E7079002D6E00
- type=1420 audit(1653364735.161:64): ipe_op=EXECUTE ipe_hook=MMAP enforcing=1 pid=2472 comm="mmap_test" path=? dev=? ino=? rule="DEFAULT action=DENY"
- type=1300 audit(1653364735.161:64): SYSCALL arch=c000003e syscall=9 success=no exit=-13 a0=0 a1=1000 a2=4 a3=21 items=0 ppid=2219 pid=2472 auid=0 uid=0 gid=0 euid=0 suid=0 fsuid=0 egid=0 sgid=0 fsgid=0 tty=pts0 ses=2 comm="mmap_test" exe="/root/overlake_test/upstream_test/vol_fsverity/bin/mmap_test" subj=unconfined key=(null)
- type=1327 audit(1653364735.161:64): 707974686F6E3300746573742F6D61696E2E7079002D6E00
- This event indicates that IPE made an access control decision; the IPE
- specific record (1420) is always emitted in conjunction with a
- ``AUDITSYSCALL`` record.
- Determining whether IPE is in permissive or enforced mode can be derived
- from ``success`` property and exit code of the ``AUDITSYSCALL`` record.
- Field descriptions:
- +-----------+------------+-----------+---------------------------------------------------------------------------------+
- | Field | Value Type | Optional? | Description of Value |
- +===========+============+===========+=================================================================================+
- | ipe_op | string | No | The IPE operation name associated with the log |
- +-----------+------------+-----------+---------------------------------------------------------------------------------+
- | ipe_hook | string | No | The name of the LSM hook that triggered the IPE event |
- +-----------+------------+-----------+---------------------------------------------------------------------------------+
- | enforcing | integer | No | The current IPE enforcing state 1 is in enforcing mode, 0 is in permissive mode |
- +-----------+------------+-----------+---------------------------------------------------------------------------------+
- | pid | integer | No | The pid of the process that triggered the IPE event. |
- +-----------+------------+-----------+---------------------------------------------------------------------------------+
- | comm | string | No | The command line program name of the process that triggered the IPE event |
- +-----------+------------+-----------+---------------------------------------------------------------------------------+
- | path | string | Yes | The absolute path to the evaluated file |
- +-----------+------------+-----------+---------------------------------------------------------------------------------+
- | ino | integer | Yes | The inode number of the evaluated file |
- +-----------+------------+-----------+---------------------------------------------------------------------------------+
- | dev | string | Yes | The device name of the evaluated file, e.g. vda |
- +-----------+------------+-----------+---------------------------------------------------------------------------------+
- | rule | string | No | The matched policy rule |
- +-----------+------------+-----------+---------------------------------------------------------------------------------+
- 1421 AUDIT_IPE_CONFIG_CHANGE
- ^^^^^^^^^^^^^^^^^^^^^^^^^^^^
- Event Example::
- type=1421 audit(1653425583.136:54): old_active_pol_name="Allow_All" old_active_pol_version=0.0.0 old_policy_digest=sha256:E3B0C44298FC1C149AFBF4C8996FB92427AE41E4649B934CA495991B7852B855 new_active_pol_name="boot_verified" new_active_pol_version=0.0.0 new_policy_digest=sha256:820EEA5B40CA42B51F68962354BA083122A20BB846F26765076DD8EED7B8F4DB auid=4294967295 ses=4294967295 lsm=ipe res=1
- type=1300 audit(1653425583.136:54): SYSCALL arch=c000003e syscall=1 success=yes exit=2 a0=3 a1=5596fcae1fb0 a2=2 a3=2 items=0 ppid=184 pid=229 auid=4294967295 uid=0 gid=0 euid=0 suid=0 fsuid=0 egid=0 sgid=0 fsgid=0 tty=pts0 ses=4294967295 comm="python3" exe="/usr/bin/python3.10" key=(null)
- type=1327 audit(1653425583.136:54): PROCTITLE proctitle=707974686F6E3300746573742F6D61696E2E7079002D66002E2
- This event indicates that IPE switched the active poliy from one to another
- along with the version and the hash digest of the two policies.
- Note IPE can only have one policy active at a time, all access decision
- evaluation is based on the current active policy.
- The normal procedure to deploy a new policy is loading the policy to deploy
- into the kernel first, then switch the active policy to it.
- This record will always be emitted in conjunction with a ``AUDITSYSCALL`` record for the ``write`` syscall.
- Field descriptions:
- +------------------------+------------+-----------+---------------------------------------------------+
- | Field | Value Type | Optional? | Description of Value |
- +========================+============+===========+===================================================+
- | old_active_pol_name | string | Yes | The name of previous active policy |
- +------------------------+------------+-----------+---------------------------------------------------+
- | old_active_pol_version | string | Yes | The version of previous active policy |
- +------------------------+------------+-----------+---------------------------------------------------+
- | old_policy_digest | string | Yes | The hash of previous active policy |
- +------------------------+------------+-----------+---------------------------------------------------+
- | new_active_pol_name | string | No | The name of current active policy |
- +------------------------+------------+-----------+---------------------------------------------------+
- | new_active_pol_version | string | No | The version of current active policy |
- +------------------------+------------+-----------+---------------------------------------------------+
- | new_policy_digest | string | No | The hash of current active policy |
- +------------------------+------------+-----------+---------------------------------------------------+
- | auid | integer | No | The login user ID |
- +------------------------+------------+-----------+---------------------------------------------------+
- | ses | integer | No | The login session ID |
- +------------------------+------------+-----------+---------------------------------------------------+
- | lsm | string | No | The lsm name associated with the event |
- +------------------------+------------+-----------+---------------------------------------------------+
- | res | integer | No | The result of the audited operation(success/fail) |
- +------------------------+------------+-----------+---------------------------------------------------+
- 1422 AUDIT_IPE_POLICY_LOAD
- ^^^^^^^^^^^^^^^^^^^^^^^^^^
- Event Example::
- type=1422 audit(1653425529.927:53): policy_name="boot_verified" policy_version=0.0.0 policy_digest=sha256:820EEA5B40CA42B51F68962354BA083122A20BB846F26765076DD8EED7B8F4DB auid=4294967295 ses=4294967295 lsm=ipe res=1 errno=0
- type=1300 audit(1653425529.927:53): arch=c000003e syscall=1 success=yes exit=2567 a0=3 a1=5596fcae1fb0 a2=a07 a3=2 items=0 ppid=184 pid=229 auid=4294967295 uid=0 gid=0 euid=0 suid=0 fsuid=0 egid=0 sgid=0 fsgid=0 tty=pts0 ses=4294967295 comm="python3" exe="/usr/bin/python3.10" key=(null)
- type=1327 audit(1653425529.927:53): PROCTITLE proctitle=707974686F6E3300746573742F6D61696E2E7079002D66002E2E
- This record indicates a new policy has been loaded into the kernel with the policy name, policy version and policy hash.
- This record will always be emitted in conjunction with a ``AUDITSYSCALL`` record for the ``write`` syscall.
- Field descriptions:
- +----------------+------------+-----------+-------------------------------------------------------------+
- | Field | Value Type | Optional? | Description of Value |
- +================+============+===========+=============================================================+
- | policy_name | string | Yes | The policy_name |
- +----------------+------------+-----------+-------------------------------------------------------------+
- | policy_version | string | Yes | The policy_version |
- +----------------+------------+-----------+-------------------------------------------------------------+
- | policy_digest | string | Yes | The policy hash |
- +----------------+------------+-----------+-------------------------------------------------------------+
- | auid | integer | No | The login user ID |
- +----------------+------------+-----------+-------------------------------------------------------------+
- | ses | integer | No | The login session ID |
- +----------------+------------+-----------+-------------------------------------------------------------+
- | lsm | string | No | The lsm name associated with the event |
- +----------------+------------+-----------+-------------------------------------------------------------+
- | res | integer | No | The result of the audited operation(success/fail) |
- +----------------+------------+-----------+-------------------------------------------------------------+
- | errno | integer | No | Error code from policy loading operations (see table below) |
- +----------------+------------+-----------+-------------------------------------------------------------+
- Policy error codes (errno):
- The following table lists the error codes that may appear in the errno field while loading or updating the policy:
- +----------------+--------------------------------------------------------+
- | Error Code | Description |
- +================+========================================================+
- | 0 | Success |
- +----------------+--------------------------------------------------------+
- | -EPERM | Insufficient permission |
- +----------------+--------------------------------------------------------+
- | -EEXIST | Same name policy already deployed |
- +----------------+--------------------------------------------------------+
- | -EBADMSG | Policy is invalid |
- +----------------+--------------------------------------------------------+
- | -ENOMEM | Out of memory (OOM) |
- +----------------+--------------------------------------------------------+
- | -ERANGE | Policy version number overflow |
- +----------------+--------------------------------------------------------+
- | -EINVAL | Policy version parsing error |
- +----------------+--------------------------------------------------------+
- | -ENOKEY | Key used to sign the IPE policy not found in keyring |
- +----------------+--------------------------------------------------------+
- | -EKEYREJECTED | Policy signature verification failed |
- +----------------+--------------------------------------------------------+
- | -ESTALE | Attempting to update an IPE policy with older version |
- +----------------+--------------------------------------------------------+
- | -ENOENT | Policy was deleted while updating |
- +----------------+--------------------------------------------------------+
- 1404 AUDIT_MAC_STATUS
- ^^^^^^^^^^^^^^^^^^^^^
- Event Examples::
- type=1404 audit(1653425689.008:55): enforcing=0 old_enforcing=1 auid=4294967295 ses=4294967295 enabled=1 old-enabled=1 lsm=ipe res=1
- type=1300 audit(1653425689.008:55): arch=c000003e syscall=1 success=yes exit=2 a0=1 a1=55c1065e5c60 a2=2 a3=0 items=0 ppid=405 pid=441 auid=0 uid=0 gid=0 euid=0 suid=0 fsuid=0 egid=0 sgid=)
- type=1327 audit(1653425689.008:55): proctitle="-bash"
- type=1404 audit(1653425689.008:55): enforcing=1 old_enforcing=0 auid=4294967295 ses=4294967295 enabled=1 old-enabled=1 lsm=ipe res=1
- type=1300 audit(1653425689.008:55): arch=c000003e syscall=1 success=yes exit=2 a0=1 a1=55c1065e5c60 a2=2 a3=0 items=0 ppid=405 pid=441 auid=0 uid=0 gid=0 euid=0 suid=0 fsuid=0 egid=0 sgid=)
- type=1327 audit(1653425689.008:55): proctitle="-bash"
- This record will always be emitted in conjunction with a ``AUDITSYSCALL`` record for the ``write`` syscall.
- Field descriptions:
- +---------------+------------+-----------+-------------------------------------------------------------------------------------------------+
- | Field | Value Type | Optional? | Description of Value |
- +===============+============+===========+=================================================================================================+
- | enforcing | integer | No | The enforcing state IPE is being switched to, 1 is in enforcing mode, 0 is in permissive mode |
- +---------------+------------+-----------+-------------------------------------------------------------------------------------------------+
- | old_enforcing | integer | No | The enforcing state IPE is being switched from, 1 is in enforcing mode, 0 is in permissive mode |
- +---------------+------------+-----------+-------------------------------------------------------------------------------------------------+
- | auid | integer | No | The login user ID |
- +---------------+------------+-----------+-------------------------------------------------------------------------------------------------+
- | ses | integer | No | The login session ID |
- +---------------+------------+-----------+-------------------------------------------------------------------------------------------------+
- | enabled | integer | No | The new TTY audit enabled setting |
- +---------------+------------+-----------+-------------------------------------------------------------------------------------------------+
- | old-enabled | integer | No | The old TTY audit enabled setting |
- +---------------+------------+-----------+-------------------------------------------------------------------------------------------------+
- | lsm | string | No | The lsm name associated with the event |
- +---------------+------------+-----------+-------------------------------------------------------------------------------------------------+
- | res | integer | No | The result of the audited operation(success/fail) |
- +---------------+------------+-----------+-------------------------------------------------------------------------------------------------+
- Success Auditing
- ^^^^^^^^^^^^^^^^
- IPE supports success auditing. When enabled, all events that pass IPE
- policy and are not blocked will emit an audit event. This is disabled by
- default, and can be enabled via the kernel command line
- ``ipe.success_audit=(0|1)`` or
- ``/sys/kernel/security/ipe/success_audit`` securityfs file.
- This is *very* noisy, as IPE will check every userspace binary on the
- system, but is useful for debugging policies.
- .. NOTE::
- If a traditional MAC system is enabled (SELinux, apparmor, smack, etcetera),
- all writes to ipe's securityfs nodes require ``CAP_MAC_ADMIN``.
- Properties
- ----------
- As explained above, IPE properties are ``key=value`` pairs expressed in IPE
- policy. Two properties are built-into the policy parser: 'op' and 'action'.
- The other properties are used to restrict immutable security properties
- about the files being evaluated. Currently those properties are:
- '``boot_verified``', '``dmverity_signature``', '``dmverity_roothash``',
- '``fsverity_signature``', '``fsverity_digest``'. A description of all
- properties supported by IPE are listed below:
- op
- ~~
- Indicates the operation for a rule to apply to. Must be in every rule,
- as the first token. IPE supports the following operations:
- ``EXECUTE``
- Pertains to any file attempting to be executed, or loaded as an
- executable.
- ``FIRMWARE``:
- Pertains to firmware being loaded via the firmware_class interface.
- This covers both the preallocated buffer and the firmware file
- itself.
- ``KMODULE``:
- Pertains to loading kernel modules via ``modprobe`` or ``insmod``.
- ``KEXEC_IMAGE``:
- Pertains to kernel images loading via ``kexec``.
- ``KEXEC_INITRAMFS``
- Pertains to initrd images loading via ``kexec --initrd``.
- ``POLICY``:
- Controls loading policies via reading a kernel-space initiated read.
- An example of such is loading IMA policies by writing the path
- to the policy file to ``$securityfs/ima/policy``
- ``X509_CERT``:
- Controls loading IMA certificates through the Kconfigs,
- ``CONFIG_IMA_X509_PATH`` and ``CONFIG_EVM_X509_PATH``.
- action
- ~~~~~~
- Determines what IPE should do when a rule matches. Must be in every
- rule, as the final clause. Can be one of:
- ``ALLOW``:
- If the rule matches, explicitly allow access to the resource to proceed
- without executing any more rules.
- ``DENY``:
- If the rule matches, explicitly prohibit access to the resource to
- proceed without executing any more rules.
- boot_verified
- ~~~~~~~~~~~~~
- This property can be utilized for authorization of files from initramfs.
- The format of this property is::
- boot_verified=(TRUE|FALSE)
- .. WARNING::
- This property will trust files from initramfs(rootfs). It should
- only be used during early booting stage. Before mounting the real
- rootfs on top of the initramfs, initramfs script will recursively
- remove all files and directories on the initramfs. This is typically
- implemented by using switch_root(8) [#switch_root]_. Therefore the
- initramfs will be empty and not accessible after the real
- rootfs takes over. It is advised to switch to a different policy
- that doesn't rely on the property after this point.
- This ensures that the trust policies remain relevant and effective
- throughout the system's operation.
- dmverity_roothash
- ~~~~~~~~~~~~~~~~~
- This property can be utilized for authorization or revocation of
- specific dm-verity volumes, identified via their root hashes. It has a
- dependency on the DM_VERITY module. This property is controlled by
- the ``IPE_PROP_DM_VERITY`` config option, it will be automatically
- selected when ``SECURITY_IPE`` and ``DM_VERITY`` are all enabled.
- The format of this property is::
- dmverity_roothash=DigestName:HexadecimalString
- The supported DigestNames for dmverity_roothash are [#dmveritydigests]_
- + blake2b-512
- + blake2s-256
- + sha256
- + sha384
- + sha512
- + sha3-224
- + sha3-256
- + sha3-384
- + sha3-512
- + sm3
- + rmd160
- dmverity_signature
- ~~~~~~~~~~~~~~~~~~
- This property can be utilized for authorization of all dm-verity
- volumes that have a signed roothash that validated by a keyring
- specified by dm-verity's configuration, either the system trusted
- keyring, or the secondary keyring. It depends on
- ``DM_VERITY_VERIFY_ROOTHASH_SIG`` config option and is controlled by
- the ``IPE_PROP_DM_VERITY_SIGNATURE`` config option, it will be automatically
- selected when ``SECURITY_IPE``, ``DM_VERITY`` and
- ``DM_VERITY_VERIFY_ROOTHASH_SIG`` are all enabled.
- The format of this property is::
- dmverity_signature=(TRUE|FALSE)
- fsverity_digest
- ~~~~~~~~~~~~~~~
- This property can be utilized for authorization of specific fsverity
- enabled files, identified via their fsverity digests.
- It depends on ``FS_VERITY`` config option and is controlled by
- the ``IPE_PROP_FS_VERITY`` config option, it will be automatically
- selected when ``SECURITY_IPE`` and ``FS_VERITY`` are all enabled.
- The format of this property is::
- fsverity_digest=DigestName:HexadecimalString
- The supported DigestNames for fsverity_digest are [#fsveritydigest]_
- + sha256
- + sha512
- fsverity_signature
- ~~~~~~~~~~~~~~~~~~
- This property is used to authorize all fs-verity enabled files that have
- been verified by fs-verity's built-in signature mechanism. The signature
- verification relies on a key stored within the ".fs-verity" keyring. It
- depends on ``FS_VERITY_BUILTIN_SIGNATURES`` config option and
- it is controlled by the ``IPE_PROP_FS_VERITY`` config option,
- it will be automatically selected when ``SECURITY_IPE``, ``FS_VERITY``
- and ``FS_VERITY_BUILTIN_SIGNATURES`` are all enabled.
- The format of this property is::
- fsverity_signature=(TRUE|FALSE)
- Policy Examples
- ---------------
- Allow all
- ~~~~~~~~~
- ::
- policy_name=Allow_All policy_version=0.0.0
- DEFAULT action=ALLOW
- Allow only initramfs
- ~~~~~~~~~~~~~~~~~~~~
- ::
- policy_name=Allow_Initramfs policy_version=0.0.0
- DEFAULT action=DENY
- op=EXECUTE boot_verified=TRUE action=ALLOW
- Allow any signed and validated dm-verity volume and the initramfs
- ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
- ::
- policy_name=Allow_Signed_DMV_And_Initramfs policy_version=0.0.0
- DEFAULT action=DENY
- op=EXECUTE boot_verified=TRUE action=ALLOW
- op=EXECUTE dmverity_signature=TRUE action=ALLOW
- Prohibit execution from a specific dm-verity volume
- ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
- ::
- policy_name=Deny_DMV_By_Roothash policy_version=0.0.0
- DEFAULT action=DENY
- op=EXECUTE dmverity_roothash=sha256:cd2c5bae7c6c579edaae4353049d58eb5f2e8be0244bf05345bc8e5ed257baff action=DENY
- op=EXECUTE boot_verified=TRUE action=ALLOW
- op=EXECUTE dmverity_signature=TRUE action=ALLOW
- Allow only a specific dm-verity volume
- ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
- ::
- policy_name=Allow_DMV_By_Roothash policy_version=0.0.0
- DEFAULT action=DENY
- op=EXECUTE dmverity_roothash=sha256:401fcec5944823ae12f62726e8184407a5fa9599783f030dec146938 action=ALLOW
- Allow any fs-verity file with a valid built-in signature
- ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
- ::
- policy_name=Allow_Signed_And_Validated_FSVerity policy_version=0.0.0
- DEFAULT action=DENY
- op=EXECUTE fsverity_signature=TRUE action=ALLOW
- Allow execution of a specific fs-verity file
- ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
- ::
- policy_name=ALLOW_FSV_By_Digest policy_version=0.0.0
- DEFAULT action=DENY
- op=EXECUTE fsverity_digest=sha256:fd88f2b8824e197f850bf4c5109bea5cf0ee38104f710843bb72da796ba5af9e action=ALLOW
- Additional Information
- ----------------------
- - `Github Repository <https://github.com/microsoft/ipe>`_
- - :doc:`Developer and design docs for IPE </security/ipe>`
- FAQ
- ---
- Q:
- What's the difference between other LSMs which provide a measure of
- trust-based access control?
- A:
- In general, there's two other LSMs that can provide similar functionality:
- IMA, and Loadpin.
- IMA and IPE are functionally very similar. The significant difference between
- the two is the policy. [#devdoc]_
- Loadpin and IPE differ fairly dramatically, as Loadpin only covers the IPE's
- kernel read operations, whereas IPE is capable of controlling execution
- on top of kernel read. The trust model is also different; Loadpin roots its
- trust in the initial super-block, whereas trust in IPE is stemmed from kernel
- itself (via ``SYSTEM_TRUSTED_KEYS``).
- -----------
- .. [#digest_cache_lsm] https://lore.kernel.org/lkml/20240415142436.2545003-1-roberto.sassu@huaweicloud.com/
- .. [#devdoc] Please see :doc:`the design docs </security/ipe>` for more on
- this topic.
- .. [#switch_root] https://man7.org/linux/man-pages/man8/switch_root.8.html
- .. [#dmveritydigests] These hash algorithms are based on values accepted by
- the Linux crypto API; IPE does not impose any
- restrictions on the digest algorithm itself;
- thus, this list may be out of date.
- .. [#fsveritydigest] These hash algorithms are based on values accepted by the
- kernel's fsverity support; IPE does not impose any
- restrictions on the digest algorithm itself;
- thus, this list may be out of date.
|