xref: /linux/Documentation/userspace-api/check_exec.rst (revision 21266b8df5224c4f677acf9f353eecc9094731f0)
1.. SPDX-License-Identifier: GPL-2.0
2.. Copyright © 2024 Microsoft Corporation
3
4===================
5Executability check
6===================
7
8The ``AT_EXECVE_CHECK`` :manpage:`execveat(2)` flag, and the
9``SECBIT_EXEC_RESTRICT_FILE`` and ``SECBIT_EXEC_DENY_INTERACTIVE`` securebits
10are intended for script interpreters and dynamic linkers to enforce a
11consistent execution security policy handled by the kernel.  See the
12`samples/check-exec/inc.c`_ example.
13
14Whether an interpreter should check these securebits or not depends on the
15security risk of running malicious scripts with respect to the execution
16environment, and whether the kernel can check if a script is trustworthy or
17not.  For instance, Python scripts running on a server can use arbitrary
18syscalls and access arbitrary files.  Such interpreters should then be
19enlighten to use these securebits and let users define their security policy.
20However, a JavaScript engine running in a web browser should already be
21sandboxed and then should not be able to harm the user's environment.
22
23Script interpreters or dynamic linkers built for tailored execution environments
24(e.g. hardened Linux distributions or hermetic container images) could use
25``AT_EXECVE_CHECK`` without checking the related securebits if backward
26compatibility is handled by something else (e.g. atomic update ensuring that
27all legitimate libraries are allowed to be executed).  It is then recommended
28for script interpreters and dynamic linkers to check the securebits at run time
29by default, but also to provide the ability for custom builds to behave like if
30``SECBIT_EXEC_RESTRICT_FILE`` or ``SECBIT_EXEC_DENY_INTERACTIVE`` were always
31set to 1 (i.e. always enforce restrictions).
32
33AT_EXECVE_CHECK
34===============
35
36Passing the ``AT_EXECVE_CHECK`` flag to :manpage:`execveat(2)` only performs a
37check on a regular file and returns 0 if execution of this file would be
38allowed, ignoring the file format and then the related interpreter dependencies
39(e.g. ELF libraries, script's shebang).
40
41Programs should always perform this check to apply kernel-level checks against
42files that are not directly executed by the kernel but passed to a user space
43interpreter instead.  All files that contain executable code, from the point of
44view of the interpreter, should be checked.  However the result of this check
45should only be enforced according to ``SECBIT_EXEC_RESTRICT_FILE`` or
46``SECBIT_EXEC_DENY_INTERACTIVE.``.
47
48The main purpose of this flag is to improve the security and consistency of an
49execution environment to ensure that direct file execution (e.g.
50``./script.sh``) and indirect file execution (e.g. ``sh script.sh``) lead to
51the same result.  For instance, this can be used to check if a file is
52trustworthy according to the caller's environment.
53
54In a secure environment, libraries and any executable dependencies should also
55be checked.  For instance, dynamic linking should make sure that all libraries
56are allowed for execution to avoid trivial bypass (e.g. using ``LD_PRELOAD``).
57For such secure execution environment to make sense, only trusted code should
58be executable, which also requires integrity guarantees.
59
60To avoid race conditions leading to time-of-check to time-of-use issues,
61``AT_EXECVE_CHECK`` should be used with ``AT_EMPTY_PATH`` to check against a
62file descriptor instead of a path.
63
64SECBIT_EXEC_RESTRICT_FILE and SECBIT_EXEC_DENY_INTERACTIVE
65==========================================================
66
67When ``SECBIT_EXEC_RESTRICT_FILE`` is set, a process should only interpret or
68execute a file if a call to :manpage:`execveat(2)` with the related file
69descriptor and the ``AT_EXECVE_CHECK`` flag succeed.
70
71This secure bit may be set by user session managers, service managers,
72container runtimes, sandboxer tools...  Except for test environments, the
73related ``SECBIT_EXEC_RESTRICT_FILE_LOCKED`` bit should also be set.
74
75Programs should only enforce consistent restrictions according to the
76securebits but without relying on any other user-controlled configuration.
77Indeed, the use case for these securebits is to only trust executable code
78vetted by the system configuration (through the kernel), so we should be
79careful to not let untrusted users control this configuration.
80
81However, script interpreters may still use user configuration such as
82environment variables as long as it is not a way to disable the securebits
83checks.  For instance, the ``PATH`` and ``LD_PRELOAD`` variables can be set by
84a script's caller.  Changing these variables may lead to unintended code
85executions, but only from vetted executable programs, which is OK.  For this to
86make sense, the system should provide a consistent security policy to avoid
87arbitrary code execution e.g., by enforcing a write xor execute policy.
88
89When ``SECBIT_EXEC_DENY_INTERACTIVE`` is set, a process should never interpret
90interactive user commands (e.g. scripts).  However, if such commands are passed
91through a file descriptor (e.g. stdin), its content should be interpreted if a
92call to :manpage:`execveat(2)` with the related file descriptor and the
93``AT_EXECVE_CHECK`` flag succeed.
94
95For instance, script interpreters called with a script snippet as argument
96should always deny such execution if ``SECBIT_EXEC_DENY_INTERACTIVE`` is set.
97
98This secure bit may be set by user session managers, service managers,
99container runtimes, sandboxer tools...  Except for test environments, the
100related ``SECBIT_EXEC_DENY_INTERACTIVE_LOCKED`` bit should also be set.
101
102Here is the expected behavior for a script interpreter according to combination
103of any exec securebits:
104
1051. ``SECBIT_EXEC_RESTRICT_FILE=0`` and ``SECBIT_EXEC_DENY_INTERACTIVE=0``
106
107   Always interpret scripts, and allow arbitrary user commands (default).
108
109   No threat, everyone and everything is trusted, but we can get ahead of
110   potential issues thanks to the call to :manpage:`execveat(2)` with
111   ``AT_EXECVE_CHECK`` which should always be performed but ignored by the
112   script interpreter.  Indeed, this check is still important to enable systems
113   administrators to verify requests (e.g. with audit) and prepare for
114   migration to a secure mode.
115
1162. ``SECBIT_EXEC_RESTRICT_FILE=1`` and ``SECBIT_EXEC_DENY_INTERACTIVE=0``
117
118   Deny script interpretation if they are not executable, but allow
119   arbitrary user commands.
120
121   The threat is (potential) malicious scripts run by trusted (and not fooled)
122   users.  That can protect against unintended script executions (e.g. ``sh
123   /tmp/*.sh``).  This makes sense for (semi-restricted) user sessions.
124
1253. ``SECBIT_EXEC_RESTRICT_FILE=0`` and ``SECBIT_EXEC_DENY_INTERACTIVE=1``
126
127   Always interpret scripts, but deny arbitrary user commands.
128
129   This use case may be useful for secure services (i.e. without interactive
130   user session) where scripts' integrity is verified (e.g.  with IMA/EVM or
131   dm-verity/IPE) but where access rights might not be ready yet.  Indeed,
132   arbitrary interactive commands would be much more difficult to check.
133
1344. ``SECBIT_EXEC_RESTRICT_FILE=1`` and ``SECBIT_EXEC_DENY_INTERACTIVE=1``
135
136   Deny script interpretation if they are not executable, and also deny
137   any arbitrary user commands.
138
139   The threat is malicious scripts run by untrusted users (but trusted code).
140   This makes sense for system services that may only execute trusted scripts.
141
142.. Links
143.. _samples/check-exec/inc.c:
144   https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/tree/samples/check-exec/inc.c
145