1

selinux: revert our use of vma_is_initial_heap()

Unfortunately it appears that vma_is_initial_heap() is currently broken
for applications that do not currently have any heap allocated, e.g.
brk == start_brk.  The breakage is such that it will cause SELinux to
check for the process/execheap permission on memory regions that cross
brk/start_brk even when there is no heap.

The proper fix would be to correct vma_is_initial_heap(), but as there
are multiple callers I am hesitant to unilaterally modify the helper
out of concern that I would end up breaking some other subsystem.  The
mm developers have been made aware of the situation and hopefully they
will have a fix at some point in the future, but we need a fix soon so
we are simply going to revert our use of vma_is_initial_heap() in favor
of our old logic/code which works as expected, even in the face of a
zero size heap.  We can return to using vma_is_initial_heap() at some
point in the future when it is fixed.

Cc: stable@vger.kernel.org
Reported-by: Marc Reisner <reisner.marc@gmail.com>
Closes: https://lore.kernel.org/all/ZrPmoLKJEf1wiFmM@marcreisner.com
Fixes: 68df1baf15 ("selinux: use vma_is_initial_stack() and vma_is_initial_heap()")
Signed-off-by: Paul Moore <paul@paul-moore.com>
This commit is contained in:
Paul Moore 2024-08-08 11:57:38 -04:00
parent 6dd1e4c045
commit 05a3d6e930

View File

@ -3852,7 +3852,17 @@ static int selinux_file_mprotect(struct vm_area_struct *vma,
if (default_noexec && if (default_noexec &&
(prot & PROT_EXEC) && !(vma->vm_flags & VM_EXEC)) { (prot & PROT_EXEC) && !(vma->vm_flags & VM_EXEC)) {
int rc = 0; int rc = 0;
if (vma_is_initial_heap(vma)) { /*
* We don't use the vma_is_initial_heap() helper as it has
* a history of problems and is currently broken on systems
* where there is no heap, e.g. brk == start_brk. Before
* replacing the conditional below with vma_is_initial_heap(),
* or something similar, please ensure that the logic is the
* same as what we have below or you have tested every possible
* corner case you can think to test.
*/
if (vma->vm_start >= vma->vm_mm->start_brk &&
vma->vm_end <= vma->vm_mm->brk) {
rc = avc_has_perm(sid, sid, SECCLASS_PROCESS, rc = avc_has_perm(sid, sid, SECCLASS_PROCESS,
PROCESS__EXECHEAP, NULL); PROCESS__EXECHEAP, NULL);
} else if (!vma->vm_file && (vma_is_initial_stack(vma) || } else if (!vma->vm_file && (vma_is_initial_stack(vma) ||