linux/security/selinux
Ondrej Mosnacek 6406887a12 selinux: fix variable scope issue in live sidtab conversion
Commit 02a52c5c8c ("selinux: move policy commit after updating
selinuxfs") moved the selinux_policy_commit() call out of
security_load_policy() into sel_write_load(), which caused a subtle yet
rather serious bug.

The problem is that security_load_policy() passes a reference to the
convert_params local variable to sidtab_convert(), which stores it in
the sidtab, where it may be accessed until the policy is swapped over
and RCU synchronized. Before 02a52c5c8c, selinux_policy_commit() was
called directly from security_load_policy(), so the convert_params
pointer remained valid all the way until the old sidtab was destroyed,
but now that's no longer the case and calls to sidtab_context_to_sid()
on the old sidtab after security_load_policy() returns may cause invalid
memory accesses.

This can be easily triggered using the stress test from commit
ee1a84fdfe ("selinux: overhaul sidtab to fix bug and improve
performance"):
```
function rand_cat() {
	echo $(( $RANDOM % 1024 ))
}

function do_work() {
	while true; do
		echo -n "system_u:system_r:kernel_t:s0:c$(rand_cat),c$(rand_cat)" \
			>/sys/fs/selinux/context 2>/dev/null || true
	done
}

do_work >/dev/null &
do_work >/dev/null &
do_work >/dev/null &

while load_policy; do echo -n .; sleep 0.1; done

kill %1
kill %2
kill %3
```

Fix this by allocating the temporary sidtab convert structures
dynamically and passing them among the
selinux_policy_{load,cancel,commit} functions.

Fixes: 02a52c5c8c ("selinux: move policy commit after updating selinuxfs")
Cc: stable@vger.kernel.org
Tested-by: Tyler Hicks <tyhicks@linux.microsoft.com>
Reviewed-by: Tyler Hicks <tyhicks@linux.microsoft.com>
Signed-off-by: Ondrej Mosnacek <omosnace@redhat.com>
[PM: merge fuzz in security.h and services.c]
Signed-off-by: Paul Moore <paul@paul-moore.com>
2021-03-18 23:23:46 -04:00
..
include selinux: fix variable scope issue in live sidtab conversion 2021-03-18 23:23:46 -04:00
ss selinux: fix variable scope issue in live sidtab conversion 2021-03-18 23:23:46 -04:00
.gitignore .gitignore: add SPDX License Identifier 2020-03-25 11:50:48 +01:00
avc.c selinux: mark some global variables __ro_after_init 2021-01-12 10:08:55 -05:00
hooks.c selinux: teach SELinux about anonymous inodes 2021-01-14 17:38:10 -05:00
ibpkey.c selinux: remove unused global variables 2021-01-12 09:49:01 -05:00
Kconfig Documentation,selinux: deprecate setting checkreqprot to 1 2020-02-10 10:49:01 -05:00
Makefile selinux: hash context structure directly 2020-04-17 16:04:34 -04:00
netif.c selinux: remove unused global variables 2021-01-12 09:49:01 -05:00
netlabel.c treewide: Replace GPLv2 boilerplate/reference with SPDX - rule 13 2019-05-21 11:28:45 +02:00
netlink.c selinux: mark some global variables __ro_after_init 2021-01-12 10:08:55 -05:00
netnode.c selinux: remove unused global variables 2021-01-12 09:49:01 -05:00
netport.c selinux: remove unused global variables 2021-01-12 09:49:01 -05:00
nlmsgtab.c net: bridge: vlan: add rtm definitions and dump support 2020-01-15 13:48:17 +01:00
selinuxfs.c selinux: fix variable scope issue in live sidtab conversion 2021-03-18 23:23:46 -04:00
status.c selinux: move status variables out of selinux_ss 2020-02-10 10:49:01 -05:00
xfrm.c selinux: mark selinux_xfrm_refcount as __read_mostly 2021-01-12 10:12:58 -05:00