kernel: selinux: rules: Fix illegal RCU lock usage in handle_sepolicy()
Currently, handle_sepolicy() holds an RCU read lock across the entire function including calls to strncpy_from_user() which can sleep, which is illegal in RCU semantics. This triggers the following warning when the kernel is compiled with CONFIG_DEBUG_ATOMIC_SLEEP enabled: [ 8.526345] BUG: sleeping function called from invalid context at lib/strncpy_from_user.c:40 [ 8.526349] in_atomic(): 0, irqs_disabled(): 0, non_block: 0, pid: 683, name: ksud [ 8.526351] preempt_count: 0, expected: 0 [ 8.526352] RCU nest depth: 1, expected: 0 [ 8.526354] 1 lock held by ksud/683: [ 8.526355] #0: ffffffe013e1b970 (rcu_read_lock){....}, at: handle_sepolicy+0xe4/0xaa0 [ 8.526365] CPU: 6 PID: 683 Comm: ksud Tainted: G W 5.4.289-Scarlet-v2.2-beta2 #1 [ 8.526366] Hardware name: redwood based Qualcomm Technologies, Inc. SM7325 (DT) [ 8.526367] Call trace: [ 8.526371] dump_backtrace+0x0/0x1c0 [ 8.526374] dump_stack+0x90/0xcc [ 8.526376] __might_sleep+0x1a0/0x200 [ 8.526378] __might_fault+0x28/0x40 [ 8.526381] strncpy_from_user+0xac/0x300 [ 8.526383] handle_sepolicy+0x588/0xaa0 [ 8.526385] ksu_handle_prctl+0x368/0xd60 [ 8.526386] ksu_task_prctl+0xc/0x20 [ 8.526389] security_task_prctl+0x5c/0xa0 [ 8.526391] __arm64_sys_prctl+0x58/0x7e0 [ 8.526393] do_el0_svc+0x68/0x120 [ 8.526394] el0_sync_handler+0x11c/0x1c0 [ 8.526395] el0_sync+0x140/0x180 To fix this, replace the rcu_read_lock() with the `ksu_rules` mutex_lock() introduced with commit 9014c663d1eb4 ("kernel: selinux: rules: Fix illegal RCU lock usage in apply_kernelsu_rules()") which allows sleeping. This mutex_lock() ensures mutual exclusion between threads invoking dynamic policy modifications via handle_sepolicy() and those applying KernelSU rules via apply_kernelsu_rules(), both of which access the policydb structure through get_policydb(). Signed-off-by: Tashfin Shakeer Rhythm <tashfinshakeerrhythm@gmail.com>
This commit is contained in:
committed by
ShirkNeko
parent
71f8944ffb
commit
ccee5e51c6
@@ -36,7 +36,7 @@ static struct policydb *get_policydb(void)
|
|||||||
return db;
|
return db;
|
||||||
}
|
}
|
||||||
|
|
||||||
static DEFINE_MUTEX(apply_ksu_rules_mutex);
|
static DEFINE_MUTEX(ksu_rules);
|
||||||
|
|
||||||
void ksu_apply_kernelsu_rules()
|
void ksu_apply_kernelsu_rules()
|
||||||
{
|
{
|
||||||
@@ -46,7 +46,7 @@ void ksu_apply_kernelsu_rules()
|
|||||||
pr_info("SELinux permissive or disabled, apply rules!\n");
|
pr_info("SELinux permissive or disabled, apply rules!\n");
|
||||||
}
|
}
|
||||||
|
|
||||||
mutex_lock(&apply_ksu_rules_mutex);
|
mutex_lock(&ksu_rules);
|
||||||
|
|
||||||
db = get_policydb();
|
db = get_policydb();
|
||||||
|
|
||||||
@@ -149,7 +149,7 @@ void ksu_apply_kernelsu_rules()
|
|||||||
susfs_set_zygote_sid();
|
susfs_set_zygote_sid();
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
mutex_unlock(&apply_ksu_rules_mutex);
|
mutex_unlock(&ksu_rules);
|
||||||
}
|
}
|
||||||
|
|
||||||
#define MAX_SEPOL_LEN 128
|
#define MAX_SEPOL_LEN 128
|
||||||
@@ -233,9 +233,10 @@ static void reset_avc_cache()
|
|||||||
selinux_xfrm_notify_policyload();
|
selinux_xfrm_notify_policyload();
|
||||||
}
|
}
|
||||||
|
|
||||||
static DEFINE_MUTEX(ksu_handle_sepolicy_mutex);
|
|
||||||
int ksu_handle_sepolicy(unsigned long arg3, void __user *arg4)
|
int ksu_handle_sepolicy(unsigned long arg3, void __user *arg4)
|
||||||
{
|
{
|
||||||
|
struct policydb *db;
|
||||||
|
|
||||||
if (!arg4) {
|
if (!arg4) {
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
@@ -282,7 +283,7 @@ int ksu_handle_sepolicy(unsigned long arg3, void __user *arg4)
|
|||||||
|
|
||||||
struct policydb *db;
|
struct policydb *db;
|
||||||
|
|
||||||
mutex_lock(&ksu_handle_sepolicy_mutex);
|
mutex_lock(&ksu_rules);
|
||||||
|
|
||||||
db = get_policydb();
|
db = get_policydb();
|
||||||
|
|
||||||
@@ -534,7 +535,7 @@ int ksu_handle_sepolicy(unsigned long arg3, void __user *arg4)
|
|||||||
}
|
}
|
||||||
|
|
||||||
exit:
|
exit:
|
||||||
mutex_unlock(&ksu_handle_sepolicy_mutex);
|
mutex_unlock(&ksu_rules);
|
||||||
|
|
||||||
// only allow and xallow needs to reset avc cache, but we cannot do that because
|
// only allow and xallow needs to reset avc cache, but we cannot do that because
|
||||||
// we are in atomic context. so we just reset it every time.
|
// we are in atomic context. so we just reset it every time.
|
||||||
|
|||||||
Reference in New Issue
Block a user