brintos

brintos / linux-shallow public Read only

0
0
Text · 3.1 KiB · 7afcc48 Raw
87 lines · plain
1.. SPDX-License-Identifier: GPL-2.02 3==================================4Introduction of non-executable mfd5==================================6:Author:7    Daniel Verkamp <dverkamp@chromium.org>8    Jeff Xu <jeffxu@chromium.org>9 10:Contributor:11	Aleksa Sarai <cyphar@cyphar.com>12 13Since Linux introduced the memfd feature, memfds have always had their14execute bit set, and the memfd_create() syscall doesn't allow setting15it differently.16 17However, in a secure-by-default system, such as ChromeOS, (where all18executables should come from the rootfs, which is protected by verified19boot), this executable nature of memfd opens a door for NoExec bypass20and enables “confused deputy attack”.  E.g, in VRP bug [1]: cros_vm21process created a memfd to share the content with an external process,22however the memfd is overwritten and used for executing arbitrary code23and root escalation. [2] lists more VRP of this kind.24 25On the other hand, executable memfd has its legit use: runc uses memfd’s26seal and executable feature to copy the contents of the binary then27execute them. For such a system, we need a solution to differentiate runc's28use of executable memfds and an attacker's [3].29 30To address those above:31 - Let memfd_create() set X bit at creation time.32 - Let memfd be sealed for modifying X bit when NX is set.33 - Add a new pid namespace sysctl: vm.memfd_noexec to help applications in34   migrating and enforcing non-executable MFD.35 36User API37========38``int memfd_create(const char *name, unsigned int flags)``39 40``MFD_NOEXEC_SEAL``41	When MFD_NOEXEC_SEAL bit is set in the ``flags``, memfd is created42	with NX. F_SEAL_EXEC is set and the memfd can't be modified to43	add X later. MFD_ALLOW_SEALING is also implied.44	This is the most common case for the application to use memfd.45 46``MFD_EXEC``47	When MFD_EXEC bit is set in the ``flags``, memfd is created with X.48 49Note:50	``MFD_NOEXEC_SEAL`` implies ``MFD_ALLOW_SEALING``. In case that51	an app doesn't want sealing, it can add F_SEAL_SEAL after creation.52 53 54Sysctl:55========56``pid namespaced sysctl vm.memfd_noexec``57 58The new pid namespaced sysctl vm.memfd_noexec has 3 values:59 60 - 0: MEMFD_NOEXEC_SCOPE_EXEC61	memfd_create() without MFD_EXEC nor MFD_NOEXEC_SEAL acts like62	MFD_EXEC was set.63 64 - 1: MEMFD_NOEXEC_SCOPE_NOEXEC_SEAL65	memfd_create() without MFD_EXEC nor MFD_NOEXEC_SEAL acts like66	MFD_NOEXEC_SEAL was set.67 68 - 2: MEMFD_NOEXEC_SCOPE_NOEXEC_ENFORCED69	memfd_create() without MFD_NOEXEC_SEAL will be rejected.70 71The sysctl allows finer control of memfd_create for old software that72doesn't set the executable bit; for example, a container with73vm.memfd_noexec=1 means the old software will create non-executable memfd74by default while new software can create executable memfd by setting75MFD_EXEC.76 77The value of vm.memfd_noexec is passed to child namespace at creation78time. In addition, the setting is hierarchical, i.e. during memfd_create,79we will search from current ns to root ns and use the most restrictive80setting.81 82[1] https://crbug.com/130526783 84[2] https://bugs.chromium.org/p/chromium/issues/list?q=type%3Dbug-security%20memfd%20escalation&can=185 86[3] https://lwn.net/Articles/781013/87