Resguardo inicial

This commit is contained in:
lastdragon
2026-09-06 12:53:21 -06:00
parent 662efe3c2a
commit ad2088d178
94853 changed files with 43200404 additions and 0 deletions
@@ -0,0 +1,31 @@
=======
LoadPin
=======
LoadPin is a Linux Security Module that ensures all kernel-loaded files
(modules, firmware, etc) all originate from the same filesystem, with
the expectation that such a filesystem is backed by a read-only device
such as dm-verity or CDROM. This allows systems that have a verified
and/or unchangeable filesystem to enforce module and firmware loading
restrictions without needing to sign the files individually.
The LSM is selectable at build-time with ``CONFIG_SECURITY_LOADPIN``, and
can be controlled at boot-time with the kernel command line option
"``loadpin.enforce``". By default, it is enabled, but can be disabled at
boot ("``loadpin.enforce=0``").
LoadPin starts pinning when it sees the first file loaded. If the
block device backing the filesystem is not read-only, a sysctl is
created to toggle pinning: ``/proc/sys/kernel/loadpin/enabled``. (Having
a mutable filesystem means pinning is mutable too, but having the
sysctl allows for easy testing on systems with a mutable filesystem.)
It's also possible to exclude specific file types from LoadPin using kernel
command line option "``loadpin.exclude``". By default, all files are
included, but they can be excluded using kernel command line option such
as "``loadpin.exclude=kernel-module,kexec-image``". This allows to use
different mechanisms such as ``CONFIG_MODULE_SIG`` and
``CONFIG_KEXEC_VERIFY_SIG`` to verify kernel module and kernel image while
still use LoadPin to protect the integrity of other files kernel loads. The
full list of valid file types can be found in ``kernel_read_file_str``
defined in ``include/linux/kernel_read_file.h``.
@@ -0,0 +1,44 @@
=======
SELinux
=======
Information about the SELinux kernel subsystem can be found at the
following links:
https://git.kernel.org/pub/scm/linux/kernel/git/pcmoore/selinux.git/tree/README.md
https://github.com/selinuxproject/selinux-kernel/wiki
Information about the SELinux userspace can be found at:
https://github.com/SELinuxProject/selinux/wiki
If you want to use SELinux, chances are you will want
to use the distro-provided policies, or install the
latest reference policy release from
https://github.com/SELinuxProject/refpolicy
However, if you want to install a dummy policy for
testing, you can do using ``mdp`` provided under
scripts/selinux. Note that this requires the selinux
userspace to be installed - in particular you will
need checkpolicy to compile a kernel, and setfiles and
fixfiles to label the filesystem.
1. Compile the kernel with selinux enabled.
2. Type ``make`` to compile ``mdp``.
3. Make sure that you are not running with
SELinux enabled and a real policy. If
you are, reboot with selinux disabled
before continuing.
4. Run install_policy.sh::
cd scripts/selinux
sh install_policy.sh
Step 4 will create a new dummy policy valid for your
kernel, with a single selinux user, role, and type.
It will compile the policy, will set your ``SELINUXTYPE`` to
``dummy`` in ``/etc/selinux/config``, install the compiled policy
as ``dummy``, and relabel your filesystem.
@@ -0,0 +1,118 @@
=========
SafeSetID
=========
SafeSetID is an LSM module that gates the setid family of syscalls to restrict
UID/GID transitions from a given UID/GID to only those approved by a
system-wide allowlist. These restrictions also prohibit the given UIDs/GIDs
from obtaining auxiliary privileges associated with CAP_SET{U/G}ID, such as
allowing a user to set up user namespace UID/GID mappings.
Background
==========
In absence of file capabilities, processes spawned on a Linux system that need
to switch to a different user must be spawned with CAP_SETUID privileges.
CAP_SETUID is granted to programs running as root or those running as a non-root
user that have been explicitly given the CAP_SETUID runtime capability. It is
often preferable to use Linux runtime capabilities rather than file
capabilities, since using file capabilities to run a program with elevated
privileges opens up possible security holes since any user with access to the
file can exec() that program to gain the elevated privileges.
While it is possible to implement a tree of processes by giving full
CAP_SET{U/G}ID capabilities, this is often at odds with the goals of running a
tree of processes under non-root user(s) in the first place. Specifically,
since CAP_SETUID allows changing to any user on the system, including the root
user, it is an overpowered capability for what is needed in this scenario,
especially since programs often only call setuid() to drop privileges to a
lesser-privileged user -- not elevate privileges. Unfortunately, there is no
generally feasible way in Linux to restrict the potential UIDs that a user can
switch to through setuid() beyond allowing a switch to any user on the system.
This SafeSetID LSM seeks to provide a solution for restricting setid
capabilities in such a way.
The main use case for this LSM is to allow a non-root program to transition to
other untrusted uids without full blown CAP_SETUID capabilities. The non-root
program would still need CAP_SETUID to do any kind of transition, but the
additional restrictions imposed by this LSM would mean it is a "safer" version
of CAP_SETUID since the non-root program cannot take advantage of CAP_SETUID to
do any unapproved actions (e.g. setuid to uid 0 or create/enter new user
namespace). The higher level goal is to allow for uid-based sandboxing of system
services without having to give out CAP_SETUID all over the place just so that
non-root programs can drop to even-lesser-privileged uids. This is especially
relevant when one non-root daemon on the system should be allowed to spawn other
processes as different uids, but it's undesirable to give the daemon a
basically-root-equivalent CAP_SETUID.
Other Approaches Considered
===========================
Solve this problem in userspace
-------------------------------
For candidate applications that would like to have restricted setid capabilities
as implemented in this LSM, an alternative option would be to simply take away
setid capabilities from the application completely and refactor the process
spawning semantics in the application (e.g. by using a privileged helper program
to do process spawning and UID/GID transitions). Unfortunately, there are a
number of semantics around process spawning that would be affected by this, such
as fork() calls where the program doesn't immediately call exec() after the
fork(), parent processes specifying custom environment variables or command line
args for spawned child processes, or inheritance of file handles across a
fork()/exec(). Because of this, as solution that uses a privileged helper in
userspace would likely be less appealing to incorporate into existing projects
that rely on certain process-spawning semantics in Linux.
Use user namespaces
-------------------
Another possible approach would be to run a given process tree in its own user
namespace and give programs in the tree setid capabilities. In this way,
programs in the tree could change to any desired UID/GID in the context of their
own user namespace, and only approved UIDs/GIDs could be mapped back to the
initial system user namespace, affectively preventing privilege escalation.
Unfortunately, it is not generally feasible to use user namespaces in isolation,
without pairing them with other namespace types, which is not always an option.
Linux checks for capabilities based off of the user namespace that "owns" some
entity. For example, Linux has the notion that network namespaces are owned by
the user namespace in which they were created. A consequence of this is that
capability checks for access to a given network namespace are done by checking
whether a task has the given capability in the context of the user namespace
that owns the network namespace -- not necessarily the user namespace under
which the given task runs. Therefore spawning a process in a new user namespace
effectively prevents it from accessing the network namespace owned by the
initial namespace. This is a deal-breaker for any application that expects to
retain the CAP_NET_ADMIN capability for the purpose of adjusting network
configurations. Using user namespaces in isolation causes problems regarding
other system interactions, including use of pid namespaces and device creation.
Use an existing LSM
-------------------
None of the other in-tree LSMs have the capability to gate setid transitions, or
even employ the security_task_fix_setuid hook at all. SELinux says of that hook:
"Since setuid only affects the current process, and since the SELinux controls
are not based on the Linux identity attributes, SELinux does not need to control
this operation."
Directions for use
==================
This LSM hooks the setid syscalls to make sure transitions are allowed if an
applicable restriction policy is in place. Policies are configured through
securityfs by writing to the safesetid/uid_allowlist_policy and
safesetid/gid_allowlist_policy files at the location where securityfs is
mounted. The format for adding a policy is '<UID>:<UID>' or '<GID>:<GID>',
using literal numbers, and ending with a newline character such as '123:456\n'.
Writing an empty string "" will flush the policy. Again, configuring a policy
for a UID/GID will prevent that UID/GID from obtaining auxiliary setid
privileges, such as allowing a user to set up user namespace UID/GID mappings.
Note on GID policies and setgroups()
====================================
In v5.9 we are adding support for limiting CAP_SETGID privileges as was done
previously for CAP_SETUID. However, for compatibility with common sandboxing
related code conventions in userspace, we currently allow arbitrary
setgroups() calls for processes with CAP_SETGID restrictions. Until we add
support in a future release for restricting setgroups() calls, these GID
policies add no meaningful security. setgroups() restrictions will be enforced
once we have the policy checking code in place, which will rely on GID policy
configuration code added in v5.9.
@@ -0,0 +1,871 @@
=====
Smack
=====
"Good for you, you've decided to clean the elevator!"
- The Elevator, from Dark Star
Smack is the Simplified Mandatory Access Control Kernel.
Smack is a kernel based implementation of mandatory access
control that includes simplicity in its primary design goals.
Smack is not the only Mandatory Access Control scheme
available for Linux. Those new to Mandatory Access Control
are encouraged to compare Smack with the other mechanisms
available to determine which is best suited to the problem
at hand.
Smack consists of three major components:
- The kernel
- Basic utilities, which are helpful but not required
- Configuration data
The kernel component of Smack is implemented as a Linux
Security Modules (LSM) module. It requires netlabel and
works best with file systems that support extended attributes,
although xattr support is not strictly required.
It is safe to run a Smack kernel under a "vanilla" distribution.
Smack kernels use the CIPSO IP option. Some network
configurations are intolerant of IP options and can impede
access to systems that use them as Smack does.
Smack is used in the Tizen operating system. Please
go to http://wiki.tizen.org for information about how
Smack is used in Tizen.
The current git repository for Smack user space is:
git://github.com/smack-team/smack.git
This should make and install on most modern distributions.
There are five commands included in smackutil:
chsmack:
display or set Smack extended attribute values
smackctl:
load the Smack access rules
smackaccess:
report if a process with one label has access
to an object with another
These two commands are obsolete with the introduction of
the smackfs/load2 and smackfs/cipso2 interfaces.
smackload:
properly formats data for writing to smackfs/load
smackcipso:
properly formats data for writing to smackfs/cipso
In keeping with the intent of Smack, configuration data is
minimal and not strictly required. The most important
configuration step is mounting the smackfs pseudo filesystem.
If smackutil is installed the startup script will take care
of this, but it can be manually as well.
Add this line to ``/etc/fstab``::
smackfs /sys/fs/smackfs smackfs defaults 0 0
The ``/sys/fs/smackfs`` directory is created by the kernel.
Smack uses extended attributes (xattrs) to store labels on filesystem
objects. The attributes are stored in the extended attribute security
name space. A process must have ``CAP_MAC_ADMIN`` to change any of these
attributes.
The extended attributes that Smack uses are:
SMACK64
Used to make access control decisions. In almost all cases
the label given to a new filesystem object will be the label
of the process that created it.
SMACK64EXEC
The Smack label of a process that execs a program file with
this attribute set will run with this attribute's value.
SMACK64MMAP
Don't allow the file to be mmapped by a process whose Smack
label does not allow all of the access permitted to a process
with the label contained in this attribute. This is a very
specific use case for shared libraries.
SMACK64TRANSMUTE
Can only have the value "TRUE". If this attribute is present
on a directory when an object is created in the directory and
the Smack rule (more below) that permitted the write access
to the directory includes the transmute ("t") mode the object
gets the label of the directory instead of the label of the
creating process. If the object being created is a directory
the SMACK64TRANSMUTE attribute is set as well.
SMACK64IPIN
This attribute is only available on file descriptors for sockets.
Use the Smack label in this attribute for access control
decisions on packets being delivered to this socket.
SMACK64IPOUT
This attribute is only available on file descriptors for sockets.
Use the Smack label in this attribute for access control
decisions on packets coming from this socket.
There are multiple ways to set a Smack label on a file::
# attr -S -s SMACK64 -V "value" path
# chsmack -a value path
A process can see the Smack label it is running with by
reading ``/proc/self/attr/current``. A process with ``CAP_MAC_ADMIN``
can set the process Smack by writing there.
Most Smack configuration is accomplished by writing to files
in the smackfs filesystem. This pseudo-filesystem is mounted
on ``/sys/fs/smackfs``.
access
Provided for backward compatibility. The access2 interface
is preferred and should be used instead.
This interface reports whether a subject with the specified
Smack label has a particular access to an object with a
specified Smack label. Write a fixed format access rule to
this file. The next read will indicate whether the access
would be permitted. The text will be either "1" indicating
access, or "0" indicating denial.
access2
This interface reports whether a subject with the specified
Smack label has a particular access to an object with a
specified Smack label. Write a long format access rule to
this file. The next read will indicate whether the access
would be permitted. The text will be either "1" indicating
access, or "0" indicating denial.
ambient
This contains the Smack label applied to unlabeled network
packets.
change-rule
This interface allows modification of existing access control rules.
The format accepted on write is::
"%s %s %s %s"
where the first string is the subject label, the second the
object label, the third the access to allow and the fourth the
access to deny. The access strings may contain only the characters
"rwxat-". If a rule for a given subject and object exists it will be
modified by enabling the permissions in the third string and disabling
those in the fourth string. If there is no such rule it will be
created using the access specified in the third and the fourth strings.
cipso
Provided for backward compatibility. The cipso2 interface
is preferred and should be used instead.
This interface allows a specific CIPSO header to be assigned
to a Smack label. The format accepted on write is::
"%24s%4d%4d"["%4d"]...
The first string is a fixed Smack label. The first number is
the level to use. The second number is the number of categories.
The following numbers are the categories::
"level-3-cats-5-19 3 2 5 19"
cipso2
This interface allows a specific CIPSO header to be assigned
to a Smack label. The format accepted on write is::
"%s%4d%4d"["%4d"]...
The first string is a long Smack label. The first number is
the level to use. The second number is the number of categories.
The following numbers are the categories::
"level-3-cats-5-19 3 2 5 19"
direct
This contains the CIPSO level used for Smack direct label
representation in network packets.
doi
This contains the CIPSO domain of interpretation used in
network packets.
ipv6host
This interface allows specific IPv6 internet addresses to be
treated as single label hosts. Packets are sent to single
label hosts only from processes that have Smack write access
to the host label. All packets received from single label hosts
are given the specified label. The format accepted on write is::
"%h:%h:%h:%h:%h:%h:%h:%h label" or
"%h:%h:%h:%h:%h:%h:%h:%h/%d label".
The "::" address shortcut is not supported.
If label is "-DELETE" a matched entry will be deleted.
load
Provided for backward compatibility. The load2 interface
is preferred and should be used instead.
This interface allows access control rules in addition to
the system defined rules to be specified. The format accepted
on write is::
"%24s%24s%5s"
where the first string is the subject label, the second the
object label, and the third the requested access. The access
string may contain only the characters "rwxat-", and specifies
which sort of access is allowed. The "-" is a placeholder for
permissions that are not allowed. The string "r-x--" would
specify read and execute access. Labels are limited to 23
characters in length.
load2
This interface allows access control rules in addition to
the system defined rules to be specified. The format accepted
on write is::
"%s %s %s"
where the first string is the subject label, the second the
object label, and the third the requested access. The access
string may contain only the characters "rwxat-", and specifies
which sort of access is allowed. The "-" is a placeholder for
permissions that are not allowed. The string "r-x--" would
specify read and execute access.
load-self
Provided for backward compatibility. The load-self2 interface
is preferred and should be used instead.
This interface allows process specific access rules to be
defined. These rules are only consulted if access would
otherwise be permitted, and are intended to provide additional
restrictions on the process. The format is the same as for
the load interface.
load-self2
This interface allows process specific access rules to be
defined. These rules are only consulted if access would
otherwise be permitted, and are intended to provide additional
restrictions on the process. The format is the same as for
the load2 interface.
logging
This contains the Smack logging state.
mapped
This contains the CIPSO level used for Smack mapped label
representation in network packets.
netlabel
This interface allows specific internet addresses to be
treated as single label hosts. Packets are sent to single
label hosts without CIPSO headers, but only from processes
that have Smack write access to the host label. All packets
received from single label hosts are given the specified
label. The format accepted on write is::
"%d.%d.%d.%d label" or "%d.%d.%d.%d/%d label".
If the label specified is "-CIPSO" the address is treated
as a host that supports CIPSO headers.
onlycap
This contains labels processes must have for CAP_MAC_ADMIN
and ``CAP_MAC_OVERRIDE`` to be effective. If this file is empty
these capabilities are effective at for processes with any
label. The values are set by writing the desired labels, separated
by spaces, to the file or cleared by writing "-" to the file.
ptrace
This is used to define the current ptrace policy
0 - default:
this is the policy that relies on Smack access rules.
For the ``PTRACE_READ`` a subject needs to have a read access on
object. For the ``PTRACE_ATTACH`` a read-write access is required.
1 - exact:
this is the policy that limits ``PTRACE_ATTACH``. Attach is
only allowed when subject's and object's labels are equal.
``PTRACE_READ`` is not affected. Can be overridden with ``CAP_SYS_PTRACE``.
2 - draconian:
this policy behaves like the 'exact' above with an
exception that it can't be overridden with ``CAP_SYS_PTRACE``.
revoke-subject
Writing a Smack label here sets the access to '-' for all access
rules with that subject label.
unconfined
If the kernel is configured with ``CONFIG_SECURITY_SMACK_BRINGUP``
a process with ``CAP_MAC_ADMIN`` can write a label into this interface.
Thereafter, accesses that involve that label will be logged and
the access permitted if it wouldn't be otherwise. Note that this
is dangerous and can ruin the proper labeling of your system.
It should never be used in production.
relabel-self
This interface contains a list of labels to which the process can
transition to, by writing to ``/proc/self/attr/current``.
Normally a process can change its own label to any legal value, but only
if it has ``CAP_MAC_ADMIN``. This interface allows a process without
``CAP_MAC_ADMIN`` to relabel itself to one of labels from predefined list.
A process without ``CAP_MAC_ADMIN`` can change its label only once. When it
does, this list will be cleared.
The values are set by writing the desired labels, separated
by spaces, to the file or cleared by writing "-" to the file.
If you are using the smackload utility
you can add access rules in ``/etc/smack/accesses``. They take the form::
subjectlabel objectlabel access
access is a combination of the letters rwxatb which specify the
kind of access permitted a subject with subjectlabel on an
object with objectlabel. If there is no rule no access is allowed.
Look for additional programs on http://schaufler-ca.com
The Simplified Mandatory Access Control Kernel (Whitepaper)
===========================================================
Casey Schaufler
casey@schaufler-ca.com
Mandatory Access Control
------------------------
Computer systems employ a variety of schemes to constrain how information is
shared among the people and services using the machine. Some of these schemes
allow the program or user to decide what other programs or users are allowed
access to pieces of data. These schemes are called discretionary access
control mechanisms because the access control is specified at the discretion
of the user. Other schemes do not leave the decision regarding what a user or
program can access up to users or programs. These schemes are called mandatory
access control mechanisms because you don't have a choice regarding the users
or programs that have access to pieces of data.
Bell & LaPadula
---------------
From the middle of the 1980's until the turn of the century Mandatory Access
Control (MAC) was very closely associated with the Bell & LaPadula security
model, a mathematical description of the United States Department of Defense
policy for marking paper documents. MAC in this form enjoyed a following
within the Capital Beltway and Scandinavian supercomputer centers but was
often sited as failing to address general needs.
Domain Type Enforcement
-----------------------
Around the turn of the century Domain Type Enforcement (DTE) became popular.
This scheme organizes users, programs, and data into domains that are
protected from each other. This scheme has been widely deployed as a component
of popular Linux distributions. The administrative overhead required to
maintain this scheme and the detailed understanding of the whole system
necessary to provide a secure domain mapping leads to the scheme being
disabled or used in limited ways in the majority of cases.
Smack
-----
Smack is a Mandatory Access Control mechanism designed to provide useful MAC
while avoiding the pitfalls of its predecessors. The limitations of Bell &
LaPadula are addressed by providing a scheme whereby access can be controlled
according to the requirements of the system and its purpose rather than those
imposed by an arcane government policy. The complexity of Domain Type
Enforcement and avoided by defining access controls in terms of the access
modes already in use.
Smack Terminology
-----------------
The jargon used to talk about Smack will be familiar to those who have dealt
with other MAC systems and shouldn't be too difficult for the uninitiated to
pick up. There are four terms that are used in a specific way and that are
especially important:
Subject:
A subject is an active entity on the computer system.
On Smack a subject is a task, which is in turn the basic unit
of execution.
Object:
An object is a passive entity on the computer system.
On Smack files of all types, IPC, and tasks can be objects.
Access:
Any attempt by a subject to put information into or get
information from an object is an access.
Label:
Data that identifies the Mandatory Access Control
characteristics of a subject or an object.
These definitions are consistent with the traditional use in the security
community. There are also some terms from Linux that are likely to crop up:
Capability:
A task that possesses a capability has permission to
violate an aspect of the system security policy, as identified by
the specific capability. A task that possesses one or more
capabilities is a privileged task, whereas a task with no
capabilities is an unprivileged task.
Privilege:
A task that is allowed to violate the system security
policy is said to have privilege. As of this writing a task can
have privilege either by possessing capabilities or by having an
effective user of root.
Smack Basics
------------
Smack is an extension to a Linux system. It enforces additional restrictions
on what subjects can access which objects, based on the labels attached to
each of the subject and the object.
Labels
~~~~~~
Smack labels are ASCII character strings. They can be up to 255 characters
long, but keeping them to twenty-three characters is recommended.
Single character labels using special characters, that being anything
other than a letter or digit, are reserved for use by the Smack development
team. Smack labels are unstructured, case sensitive, and the only operation
ever performed on them is comparison for equality. Smack labels cannot
contain unprintable characters, the "/" (slash), the "\" (backslash), the "'"
(quote) and '"' (double-quote) characters.
Smack labels cannot begin with a '-'. This is reserved for special options.
There are some predefined labels::
_ Pronounced "floor", a single underscore character.
^ Pronounced "hat", a single circumflex character.
* Pronounced "star", a single asterisk character.
? Pronounced "huh", a single question mark character.
@ Pronounced "web", a single at sign character.
Every task on a Smack system is assigned a label. The Smack label
of a process will usually be assigned by the system initialization
mechanism.
Access Rules
~~~~~~~~~~~~
Smack uses the traditional access modes of Linux. These modes are read,
execute, write, and occasionally append. There are a few cases where the
access mode may not be obvious. These include:
Signals:
A signal is a write operation from the subject task to
the object task.
Internet Domain IPC:
Transmission of a packet is considered a
write operation from the source task to the destination task.
Smack restricts access based on the label attached to a subject and the label
attached to the object it is trying to access. The rules enforced are, in
order:
1. Any access requested by a task labeled "*" is denied.
2. A read or execute access requested by a task labeled "^"
is permitted.
3. A read or execute access requested on an object labeled "_"
is permitted.
4. Any access requested on an object labeled "*" is permitted.
5. Any access requested by a task on an object with the same
label is permitted.
6. Any access requested that is explicitly defined in the loaded
rule set is permitted.
7. Any other access is denied.
Smack Access Rules
~~~~~~~~~~~~~~~~~~
With the isolation provided by Smack access separation is simple. There are
many interesting cases where limited access by subjects to objects with
different labels is desired. One example is the familiar spy model of
sensitivity, where a scientist working on a highly classified project would be
able to read documents of lower classifications and anything she writes will
be "born" highly classified. To accommodate such schemes Smack includes a
mechanism for specifying rules allowing access between labels.
Access Rule Format
~~~~~~~~~~~~~~~~~~
The format of an access rule is::
subject-label object-label access
Where subject-label is the Smack label of the task, object-label is the Smack
label of the thing being accessed, and access is a string specifying the sort
of access allowed. The access specification is searched for letters that
describe access modes:
a: indicates that append access should be granted.
r: indicates that read access should be granted.
w: indicates that write access should be granted.
x: indicates that execute access should be granted.
t: indicates that the rule requests transmutation.
b: indicates that the rule should be reported for bring-up.
Uppercase values for the specification letters are allowed as well.
Access mode specifications can be in any order. Examples of acceptable rules
are::
TopSecret Secret rx
Secret Unclass R
Manager Game x
User HR w
Snap Crackle rwxatb
New Old rRrRr
Closed Off -
Examples of unacceptable rules are::
Top Secret Secret rx
Ace Ace r
Odd spells waxbeans
Spaces are not allowed in labels. Since a subject always has access to files
with the same label specifying a rule for that case is pointless. Only
valid letters (rwxatbRWXATB) and the dash ('-') character are allowed in
access specifications. The dash is a placeholder, so "a-r" is the same
as "ar". A lone dash is used to specify that no access should be allowed.
Applying Access Rules
~~~~~~~~~~~~~~~~~~~~~
The developers of Linux rarely define new sorts of things, usually importing
schemes and concepts from other systems. Most often, the other systems are
variants of Unix. Unix has many endearing properties, but consistency of
access control models is not one of them. Smack strives to treat accesses as
uniformly as is sensible while keeping with the spirit of the underlying
mechanism.
File system objects including files, directories, named pipes, symbolic links,
and devices require access permissions that closely match those used by mode
bit access. To open a file for reading read access is required on the file. To
search a directory requires execute access. Creating a file with write access
requires both read and write access on the containing directory. Deleting a
file requires read and write access to the file and to the containing
directory. It is possible that a user may be able to see that a file exists
but not any of its attributes by the circumstance of having read access to the
containing directory but not to the differently labeled file. This is an
artifact of the file name being data in the directory, not a part of the file.
If a directory is marked as transmuting (SMACK64TRANSMUTE=TRUE) and the
access rule that allows a process to create an object in that directory
includes 't' access the label assigned to the new object will be that
of the directory, not the creating process. This makes it much easier
for two processes with different labels to share data without granting
access to all of their files.
IPC objects, message queues, semaphore sets, and memory segments exist in flat
namespaces and access requests are only required to match the object in
question.
Process objects reflect tasks on the system and the Smack label used to access
them is the same Smack label that the task would use for its own access
attempts. Sending a signal via the kill() system call is a write operation
from the signaler to the recipient. Debugging a process requires both reading
and writing. Creating a new task is an internal operation that results in two
tasks with identical Smack labels and requires no access checks.
Sockets are data structures attached to processes and sending a packet from
one process to another requires that the sender have write access to the
receiver. The receiver is not required to have read access to the sender.
Setting Access Rules
~~~~~~~~~~~~~~~~~~~~
The configuration file /etc/smack/accesses contains the rules to be set at
system startup. The contents are written to the special file
/sys/fs/smackfs/load2. Rules can be added at any time and take effect
immediately. For any pair of subject and object labels there can be only
one rule, with the most recently specified overriding any earlier
specification.
Task Attribute
~~~~~~~~~~~~~~
The Smack label of a process can be read from ``/proc/<pid>/attr/current``. A
process can read its own Smack label from ``/proc/self/attr/current``. A
privileged process can change its own Smack label by writing to
``/proc/self/attr/current`` but not the label of another process.
Format of writing is : only the label or the label followed by one of the
3 trailers: ``\n`` (by common agreement for ``/proc/...`` interfaces),
``\0`` (because some applications incorrectly include it),
``\n\0`` (because we think some applications may incorrectly include it).
File Attribute
~~~~~~~~~~~~~~
The Smack label of a filesystem object is stored as an extended attribute
named SMACK64 on the file. This attribute is in the security namespace. It can
only be changed by a process with privilege.
Privilege
~~~~~~~~~
A process with CAP_MAC_OVERRIDE or CAP_MAC_ADMIN is privileged.
CAP_MAC_OVERRIDE allows the process access to objects it would
be denied otherwise. CAP_MAC_ADMIN allows a process to change
Smack data, including rules and attributes.
Smack Networking
~~~~~~~~~~~~~~~~
As mentioned before, Smack enforces access control on network protocol
transmissions. Every packet sent by a Smack process is tagged with its Smack
label. This is done by adding a CIPSO tag to the header of the IP packet. Each
packet received is expected to have a CIPSO tag that identifies the label and
if it lacks such a tag the network ambient label is assumed. Before the packet
is delivered a check is made to determine that a subject with the label on the
packet has write access to the receiving process and if that is not the case
the packet is dropped.
CIPSO Configuration
~~~~~~~~~~~~~~~~~~~
It is normally unnecessary to specify the CIPSO configuration. The default
values used by the system handle all internal cases. Smack will compose CIPSO
label values to match the Smack labels being used without administrative
intervention. Unlabeled packets that come into the system will be given the
ambient label.
Smack requires configuration in the case where packets from a system that is
not Smack that speaks CIPSO may be encountered. Usually this will be a Trusted
Solaris system, but there are other, less widely deployed systems out there.
CIPSO provides 3 important values, a Domain Of Interpretation (DOI), a level,
and a category set with each packet. The DOI is intended to identify a group
of systems that use compatible labeling schemes, and the DOI specified on the
Smack system must match that of the remote system or packets will be
discarded. The DOI is 3 by default. The value can be read from
/sys/fs/smackfs/doi and can be changed by writing to /sys/fs/smackfs/doi.
The label and category set are mapped to a Smack label as defined in
/etc/smack/cipso.
A Smack/CIPSO mapping has the form::
smack level [category [category]*]
Smack does not expect the level or category sets to be related in any
particular way and does not assume or assign accesses based on them. Some
examples of mappings::
TopSecret 7
TS:A,B 7 1 2
SecBDE 5 2 4 6
RAFTERS 7 12 26
The ":" and "," characters are permitted in a Smack label but have no special
meaning.
The mapping of Smack labels to CIPSO values is defined by writing to
/sys/fs/smackfs/cipso2.
In addition to explicit mappings Smack supports direct CIPSO mappings. One
CIPSO level is used to indicate that the category set passed in the packet is
in fact an encoding of the Smack label. The level used is 250 by default. The
value can be read from /sys/fs/smackfs/direct and changed by writing to
/sys/fs/smackfs/direct.
Socket Attributes
~~~~~~~~~~~~~~~~~
There are two attributes that are associated with sockets. These attributes
can only be set by privileged tasks, but any task can read them for their own
sockets.
SMACK64IPIN:
The Smack label of the task object. A privileged
program that will enforce policy may set this to the star label.
SMACK64IPOUT:
The Smack label transmitted with outgoing packets.
A privileged program may set this to match the label of another
task with which it hopes to communicate.
UNIX domain socket (UDS) with a BSD address functions both as a file in a
filesystem and as a socket. As a file, it carries the SMACK64 attribute. This
attribute is not involved in Smack security enforcement and is immutably
assigned the label "*".
Smack Netlabel Exceptions
~~~~~~~~~~~~~~~~~~~~~~~~~
You will often find that your labeled application has to talk to the outside,
unlabeled world. To do this there's a special file /sys/fs/smackfs/netlabel
where you can add some exceptions in the form of::
@IP1 LABEL1 or
@IP2/MASK LABEL2
It means that your application will have unlabeled access to @IP1 if it has
write access on LABEL1, and access to the subnet @IP2/MASK if it has write
access on LABEL2.
Entries in the /sys/fs/smackfs/netlabel file are matched by longest mask
first, like in classless IPv4 routing.
A special label '@' and an option '-CIPSO' can be used there::
@ means Internet, any application with any label has access to it
-CIPSO means standard CIPSO networking
If you don't know what CIPSO is and don't plan to use it, you can just do::
echo 127.0.0.1 -CIPSO > /sys/fs/smackfs/netlabel
echo 0.0.0.0/0 @ > /sys/fs/smackfs/netlabel
If you use CIPSO on your 192.168.0.0/16 local network and need also unlabeled
Internet access, you can have::
echo 127.0.0.1 -CIPSO > /sys/fs/smackfs/netlabel
echo 192.168.0.0/16 -CIPSO > /sys/fs/smackfs/netlabel
echo 0.0.0.0/0 @ > /sys/fs/smackfs/netlabel
Writing Applications for Smack
------------------------------
There are three sorts of applications that will run on a Smack system. How an
application interacts with Smack will determine what it will have to do to
work properly under Smack.
Smack Ignorant Applications
---------------------------
By far the majority of applications have no reason whatever to care about the
unique properties of Smack. Since invoking a program has no impact on the
Smack label associated with the process the only concern likely to arise is
whether the process has execute access to the program.
Smack Relevant Applications
---------------------------
Some programs can be improved by teaching them about Smack, but do not make
any security decisions themselves. The utility ls(1) is one example of such a
program.
Smack Enforcing Applications
----------------------------
These are special programs that not only know about Smack, but participate in
the enforcement of system policy. In most cases these are the programs that
set up user sessions. There are also network services that provide information
to processes running with various labels.
File System Interfaces
----------------------
Smack maintains labels on file system objects using extended attributes. The
Smack label of a file, directory, or other file system object can be obtained
using getxattr(2)::
len = getxattr("/", "security.SMACK64", value, sizeof (value));
will put the Smack label of the root directory into value. A privileged
process can set the Smack label of a file system object with setxattr(2)::
len = strlen("Rubble");
rc = setxattr("/foo", "security.SMACK64", "Rubble", len, 0);
will set the Smack label of /foo to "Rubble" if the program has appropriate
privilege.
Socket Interfaces
-----------------
The socket attributes can be read using fgetxattr(2).
A privileged process can set the Smack label of outgoing packets with
fsetxattr(2)::
len = strlen("Rubble");
rc = fsetxattr(fd, "security.SMACK64IPOUT", "Rubble", len, 0);
will set the Smack label "Rubble" on packets going out from the socket if the
program has appropriate privilege::
rc = fsetxattr(fd, "security.SMACK64IPIN, "*", strlen("*"), 0);
will set the Smack label "*" as the object label against which incoming
packets will be checked if the program has appropriate privilege.
Administration
--------------
Smack supports some mount options:
smackfsdef=label:
specifies the label to give files that lack
the Smack label extended attribute.
smackfsroot=label:
specifies the label to assign the root of the
file system if it lacks the Smack extended attribute.
smackfshat=label:
specifies a label that must have read access to
all labels set on the filesystem. Not yet enforced.
smackfsfloor=label:
specifies a label to which all labels set on the
filesystem must have read access. Not yet enforced.
smackfstransmute=label:
behaves exactly like smackfsroot except that it also
sets the transmute flag on the root of the mount
These mount options apply to all file system types.
Smack auditing
--------------
If you want Smack auditing of security events, you need to set CONFIG_AUDIT
in your kernel configuration.
By default, all denied events will be audited. You can change this behavior by
writing a single character to the /sys/fs/smackfs/logging file::
0 : no logging
1 : log denied (default)
2 : log accepted
3 : log denied & accepted
Events are logged as 'key=value' pairs, for each event you at least will get
the subject, the object, the rights requested, the action, the kernel function
that triggered the event, plus other pairs depending on the type of event
audited.
Bringup Mode
------------
Bringup mode provides logging features that can make application
configuration and system bringup easier. Configure the kernel with
CONFIG_SECURITY_SMACK_BRINGUP to enable these features. When bringup
mode is enabled accesses that succeed due to rules marked with the "b"
access mode will logged. When a new label is introduced for processes
rules can be added aggressively, marked with the "b". The logging allows
tracking of which rules actual get used for that label.
Another feature of bringup mode is the "unconfined" option. Writing
a label to /sys/fs/smackfs/unconfined makes subjects with that label
able to access any object, and objects with that label accessible to
all subjects. Any access that is granted because a label is unconfined
is logged. This feature is dangerous, as files and directories may
be created in places they couldn't if the policy were being enforced.
@@ -0,0 +1,75 @@
====
Yama
====
Yama is a Linux Security Module that collects system-wide DAC security
protections that are not handled by the core kernel itself. This is
selectable at build-time with ``CONFIG_SECURITY_YAMA``, and can be controlled
at run-time through sysctls in ``/proc/sys/kernel/yama``:
ptrace_scope
============
As Linux grows in popularity, it will become a larger target for
malware. One particularly troubling weakness of the Linux process
interfaces is that a single user is able to examine the memory and
running state of any of their processes. For example, if one application
(e.g. Pidgin) was compromised, it would be possible for an attacker to
attach to other running processes (e.g. Firefox, SSH sessions, GPG agent,
etc) to extract additional credentials and continue to expand the scope
of their attack without resorting to user-assisted phishing.
This is not a theoretical problem. `SSH session hijacking
<https://www.blackhat.com/presentations/bh-usa-05/bh-us-05-boileau.pdf>`_
and `arbitrary code injection
<https://c-skills.blogspot.com/2007/05/injectso.html>`_ attacks already
exist and remain possible if ptrace is allowed to operate as before.
Since ptrace is not commonly used by non-developers and non-admins, system
builders should be allowed the option to disable this debugging system.
For a solution, some applications use ``prctl(PR_SET_DUMPABLE, ...)`` to
specifically disallow such ptrace attachment (e.g. ssh-agent), but many
do not. A more general solution is to only allow ptrace directly from a
parent to a child process (i.e. direct "gdb EXE" and "strace EXE" still
work), or with ``CAP_SYS_PTRACE`` (i.e. "gdb --pid=PID", and "strace -p PID"
still work as root).
In mode 1, software that has defined application-specific relationships
between a debugging process and its inferior (crash handlers, etc),
``prctl(PR_SET_PTRACER, pid, ...)`` can be used. An inferior can declare which
other process (and its descendants) are allowed to call ``PTRACE_ATTACH``
against it. Only one such declared debugging process can exists for
each inferior at a time. For example, this is used by KDE, Chromium, and
Firefox's crash handlers, and by Wine for allowing only Wine processes
to ptrace each other. If a process wishes to entirely disable these ptrace
restrictions, it can call ``prctl(PR_SET_PTRACER, PR_SET_PTRACER_ANY, ...)``
so that any otherwise allowed process (even those in external pid namespaces)
may attach.
The sysctl settings (writable only with ``CAP_SYS_PTRACE``) are:
0 - classic ptrace permissions:
a process can ``PTRACE_ATTACH`` to any other
process running under the same uid, as long as it is dumpable (i.e.
did not transition uids, start privileged, or have called
``prctl(PR_SET_DUMPABLE...)`` already). Similarly, ``PTRACE_TRACEME`` is
unchanged.
1 - restricted ptrace:
a process must have a predefined relationship
with the inferior it wants to call ``PTRACE_ATTACH`` on. By default,
this relationship is that of only its descendants when the above
classic criteria is also met. To change the relationship, an
inferior can call ``prctl(PR_SET_PTRACER, debugger, ...)`` to declare
an allowed debugger PID to call ``PTRACE_ATTACH`` on the inferior.
Using ``PTRACE_TRACEME`` is unchanged.
2 - admin-only attach:
only processes with ``CAP_SYS_PTRACE`` may use ptrace, either with
``PTRACE_ATTACH`` or through children calling ``PTRACE_TRACEME``.
3 - no attach:
no processes may use ptrace with ``PTRACE_ATTACH`` nor via
``PTRACE_TRACEME``. Once set, this sysctl value cannot be changed.
The original children-only logic was based on the restrictions in grsecurity.
@@ -0,0 +1,54 @@
========
AppArmor
========
What is AppArmor?
=================
AppArmor is MAC style security extension for the Linux kernel. It implements
a task centered policy, with task "profiles" being created and loaded
from user space. Tasks on the system that do not have a profile defined for
them run in an unconfined state which is equivalent to standard Linux DAC
permissions.
How to enable/disable
=====================
set ``CONFIG_SECURITY_APPARMOR=y``
If AppArmor should be selected as the default security module then set::
CONFIG_DEFAULT_SECURITY_APPARMOR=y
The CONFIG_LSM parameter manages the order and selection of LSMs.
Specify apparmor as the first "major" module (e.g. AppArmor, SELinux, Smack)
in the list.
Build the kernel
If AppArmor is not the default security module it can be enabled by passing
``security=apparmor`` on the kernel's command line.
If AppArmor is the default security module it can be disabled by passing
``apparmor=0, security=XXXX`` (where ``XXXX`` is valid security module), on the
kernel's command line.
For AppArmor to enforce any restrictions beyond standard Linux DAC permissions
policy must be loaded into the kernel from user space (see the Documentation
and tools links).
Documentation
=============
Documentation can be found on the wiki, linked below.
Links
=====
Mailing List - apparmor@lists.ubuntu.com
Wiki - http://wiki.apparmor.net
User space tools - https://gitlab.com/apparmor
Kernel module - git://git.kernel.org/pub/scm/linux/kernel/git/jj/linux-apparmor
@@ -0,0 +1,51 @@
===========================
Linux Security Module Usage
===========================
The Linux Security Module (LSM) framework provides a mechanism for
various security checks to be hooked by new kernel extensions. The name
"module" is a bit of a misnomer since these extensions are not actually
loadable kernel modules. Instead, they are selectable at build-time via
CONFIG_DEFAULT_SECURITY and can be overridden at boot-time via the
``"security=..."`` kernel command line argument, in the case where multiple
LSMs were built into a given kernel.
The primary users of the LSM interface are Mandatory Access Control
(MAC) extensions which provide a comprehensive security policy. Examples
include SELinux, Smack, Tomoyo, and AppArmor. In addition to the larger
MAC extensions, other extensions can be built using the LSM to provide
specific changes to system operation when these tweaks are not available
in the core functionality of Linux itself.
The Linux capabilities modules will always be included. This may be
followed by any number of "minor" modules and at most one "major" module.
For more details on capabilities, see ``capabilities(7)`` in the Linux
man-pages project.
A list of the active security modules can be found by reading
``/sys/kernel/security/lsm``. This is a comma separated list, and
will always include the capability module. The list reflects the
order in which checks are made. The capability module will always
be first, followed by any "minor" modules (e.g. Yama) and then
the one "major" module (e.g. SELinux) if there is one configured.
Process attributes associated with "major" security modules should
be accessed and maintained using the special files in ``/proc/.../attr``.
A security module may maintain a module specific subdirectory there,
named after the module. ``/proc/.../attr/smack`` is provided by the Smack
security module and contains all its special files. The files directly
in ``/proc/.../attr`` remain as legacy interfaces for modules that provide
subdirectories.
.. toctree::
:maxdepth: 1
apparmor
LoadPin
SELinux
Smack
tomoyo
Yama
SafeSetID
ipe
landlock
@@ -0,0 +1,835 @@
.. 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.
@@ -0,0 +1,194 @@
.. SPDX-License-Identifier: GPL-2.0
.. Copyright © 2025 Microsoft Corporation
================================
Landlock: system-wide management
================================
:Author: Mickaël Salaün
:Date: June 2026
Landlock can leverage the audit framework to log events.
User space documentation can be found here:
Documentation/userspace-api/landlock.rst.
Audit
=====
Denied access requests are logged by default for a sandboxed program if `audit`
is enabled. This default behavior can be changed with the
sys_landlock_restrict_self() flags (cf.
Documentation/userspace-api/landlock.rst), or suppressed on a per-object
basis by using ``LANDLOCK_ADD_RULE_QUIET`` (ABI 10+). Landlock logs can
also be masked thanks to audit rules. Landlock can generate 2 audit
record types.
Record types
------------
AUDIT_LANDLOCK_ACCESS
This record type identifies a denied access request to a kernel resource.
The ``domain`` field indicates the ID of the domain that blocked the
request. The ``blockers`` field indicates the cause(s) of this denial
(separated by a comma), and the following fields identify the kernel object
(similar to SELinux). There may be more than one of this record type per
audit event.
Example with a file link request generating two records in the same event::
domain=195ba459b blockers=fs.refer path="/usr/bin" dev="vda2" ino=351
domain=195ba459b blockers=fs.make_reg,fs.refer path="/usr/local" dev="vda2" ino=365
The ``blockers`` field uses dot-separated prefixes to indicate the type of
restriction that caused the denial:
**fs.*** - Filesystem access rights (ABI 1+):
- fs.execute, fs.write_file, fs.read_file, fs.read_dir
- fs.remove_dir, fs.remove_file
- fs.make_char, fs.make_dir, fs.make_reg, fs.make_sock
- fs.make_fifo, fs.make_block, fs.make_sym
- fs.refer (ABI 2+)
- fs.truncate (ABI 3+)
- fs.ioctl_dev (ABI 5+)
**net.*** - Network access rights (ABI 4+):
- net.bind_tcp - TCP port binding was denied
- net.connect_tcp - TCP connection was denied
- net.bind_udp - UDP port binding was denied
- net.connect_send_udp - UDP connection and send was denied
**scope.*** - IPC scoping restrictions (ABI 6+):
- scope.abstract_unix_socket - Abstract UNIX socket connection denied
- scope.signal - Signal sending denied
Multiple blockers can appear in a single event (comma-separated) when
multiple access rights are missing. For example, creating a regular file
in a directory that lacks both ``make_reg`` and ``refer`` rights would show
``blockers=fs.make_reg,fs.refer``.
The object identification fields (path, dev, ino for filesystem; opid,
ocomm for signals) depend on the type of access being blocked and provide
context about what resource was involved in the denial.
AUDIT_LANDLOCK_DOMAIN
This record type describes the status of a Landlock domain. The ``status``
field can be either ``allocated`` or ``deallocated``.
The ``allocated`` status is part of the same audit event and follows
the first logged ``AUDIT_LANDLOCK_ACCESS`` record of a domain. It identifies
Landlock domain information at the time of the sys_landlock_restrict_self()
call with the following fields:
- the ``domain`` ID
- the enforcement ``mode``
- the domain creator's ``pid``
- the domain creator's ``uid``
- the domain creator's executable path (``exe``)
- the domain creator's command line (``comm``)
Example::
domain=195ba459b status=allocated mode=enforcing pid=300 uid=0 exe="/root/sandboxer" comm="sandboxer"
The ``deallocated`` status is an event on its own and it identifies a
Landlock domain release. After such event, it is guarantee that the
related domain ID will never be reused during the lifetime of the system.
The ``domain`` field indicates the ID of the domain which is released, and
the ``denials`` field indicates the total number of denied access request,
which might not have been logged according to the audit rules and
sys_landlock_restrict_self()'s flags.
Example::
domain=195ba459b status=deallocated denials=3
Event samples
--------------
Here are two examples of log events (see serial numbers).
In this example a sandboxed program (``kill``) tries to send a signal to the
init process, which is denied because of the signal scoping restriction
(``LL_SCOPED=s``)::
$ LL_FS_RO=/ LL_FS_RW=/ LL_SCOPED=s LL_FORCE_LOG=1 ./sandboxer kill 1
This command generates two events, each identified with a unique serial
number following a timestamp (``msg=audit(1729738800.268:30)``). The first
event (serial ``30``) contains 4 records. The first record
(``type=LANDLOCK_ACCESS``) shows an access denied by the domain `1a6fdc66f`.
The cause of this denial is signal scoping restriction
(``blockers=scope.signal``). The process that would have receive this signal
is the init process (``opid=1 ocomm="systemd"``).
The second record (``type=LANDLOCK_DOMAIN``) describes (``status=allocated``)
domain `1a6fdc66f`. This domain was created by process ``286`` executing the
``/root/sandboxer`` program launched by the root user.
The third record (``type=SYSCALL``) describes the syscall, its provided
arguments, its result (``success=no exit=-1``), and the process that called it.
The fourth record (``type=PROCTITLE``) shows the command's name as an
hexadecimal value. This can be translated with ``python -c
'print(bytes.fromhex("6B696C6C0031"))'``.
Finally, the last record (``type=LANDLOCK_DOMAIN``) is also the only one from
the second event (serial ``31``). It is not tied to a direct user space action
but an asynchronous one to free resources tied to a Landlock domain
(``status=deallocated``). This can be useful to know that the following logs
will not concern the domain ``1a6fdc66f`` anymore. This record also summarize
the number of requests this domain denied (``denials=1``), whether they were
logged or not.
.. code-block::
type=LANDLOCK_ACCESS msg=audit(1729738800.268:30): domain=1a6fdc66f blockers=scope.signal opid=1 ocomm="systemd"
type=LANDLOCK_DOMAIN msg=audit(1729738800.268:30): domain=1a6fdc66f status=allocated mode=enforcing pid=286 uid=0 exe="/root/sandboxer" comm="sandboxer"
type=SYSCALL msg=audit(1729738800.268:30): arch=c000003e syscall=62 success=no exit=-1 [..] ppid=272 pid=286 auid=0 uid=0 gid=0 [...] comm="kill" [...]
type=PROCTITLE msg=audit(1729738800.268:30): proctitle=6B696C6C0031
type=LANDLOCK_DOMAIN msg=audit(1729738800.324:31): domain=1a6fdc66f status=deallocated denials=1
Here is another example showcasing filesystem access control::
$ LL_FS_RO=/ LL_FS_RW=/tmp LL_FORCE_LOG=1 ./sandboxer sh -c "echo > /etc/passwd"
The related audit logs contains 8 records from 3 different events (serials 33,
34 and 35) created by the same domain `1a6fdc679`::
type=LANDLOCK_ACCESS msg=audit(1729738800.221:33): domain=1a6fdc679 blockers=fs.write_file path="/dev/tty" dev="devtmpfs" ino=9
type=LANDLOCK_DOMAIN msg=audit(1729738800.221:33): domain=1a6fdc679 status=allocated mode=enforcing pid=289 uid=0 exe="/root/sandboxer" comm="sandboxer"
type=SYSCALL msg=audit(1729738800.221:33): arch=c000003e syscall=257 success=no exit=-13 [...] ppid=272 pid=289 auid=0 uid=0 gid=0 [...] comm="sh" [...]
type=PROCTITLE msg=audit(1729738800.221:33): proctitle=7368002D63006563686F203E202F6574632F706173737764
type=LANDLOCK_ACCESS msg=audit(1729738800.221:34): domain=1a6fdc679 blockers=fs.write_file path="/etc/passwd" dev="vda2" ino=143821
type=SYSCALL msg=audit(1729738800.221:34): arch=c000003e syscall=257 success=no exit=-13 [...] ppid=272 pid=289 auid=0 uid=0 gid=0 [...] comm="sh" [...]
type=PROCTITLE msg=audit(1729738800.221:34): proctitle=7368002D63006563686F203E202F6574632F706173737764
type=LANDLOCK_DOMAIN msg=audit(1729738800.261:35): domain=1a6fdc679 status=deallocated denials=2
Event filtering
---------------
If you get spammed with audit logs related to Landlock, this is either an
attack attempt or a bug in the security policy. We can put in place some
filters to limit noise with two complementary ways:
- with sys_landlock_restrict_self()'s flags, or
``LANDLOCK_ADD_RULE_QUIET`` (ABI 10+) if we can fix the sandboxed
programs,
- or with audit rules (see :manpage:`auditctl(8)`).
Additional documentation
========================
* `Linux Audit Documentation`_
* Documentation/userspace-api/landlock.rst
* Documentation/security/landlock.rst
* https://landlock.io
.. Links
.. _Linux Audit Documentation:
https://github.com/linux-audit/audit-documentation/wiki
@@ -0,0 +1,52 @@
======
TOMOYO
======
What is TOMOYO?
===============
TOMOYO is a name-based MAC extension (LSM module) for the Linux kernel.
LiveCD-based tutorials are available at
https://tomoyo.sourceforge.net/1.8/ubuntu12.04-live.html
https://tomoyo.sourceforge.net/1.8/centos6-live.html
Though these tutorials use non-LSM version of TOMOYO, they are useful for you
to know what TOMOYO is.
How to enable TOMOYO?
=====================
Build the kernel with ``CONFIG_SECURITY_TOMOYO=y`` and pass ``security=tomoyo`` on
kernel's command line.
Please see https://tomoyo.sourceforge.net/2.6/ for details.
Where is documentation?
=======================
User <-> Kernel interface documentation is available at
https://tomoyo.sourceforge.net/2.6/policy-specification/index.html .
Materials we prepared for seminars and symposiums are available at
https://sourceforge.net/projects/tomoyo/files/docs/ .
Below lists are chosen from three aspects.
What is TOMOYO?
TOMOYO Linux Overview
https://sourceforge.net/projects/tomoyo/files/docs/lca2009-takeda.pdf
TOMOYO Linux: pragmatic and manageable security for Linux
https://sourceforge.net/projects/tomoyo/files/docs/freedomhectaipei-tomoyo.pdf
TOMOYO Linux: A Practical Method to Understand and Protect Your Own Linux Box
https://sourceforge.net/projects/tomoyo/files/docs/PacSec2007-en-no-demo.pdf
What can TOMOYO do?
Deep inside TOMOYO Linux
https://sourceforge.net/projects/tomoyo/files/docs/lca2009-kumaneko.pdf
The role of "pathname based access control" in security.
https://sourceforge.net/projects/tomoyo/files/docs/lfj2008-bof.pdf
History of TOMOYO?
Realities of Mainlining
https://sourceforge.net/projects/tomoyo/files/docs/lfj2008.pdf