kernel: harden prctl check
Signed-off-by: backslashxx <118538522+backslashxx@users.noreply.github.com> Signed-off-by: rsuntk <rsuntk@yukiprjkt.my.id>
This commit is contained in:
@@ -300,19 +300,37 @@ int ksu_handle_prctl(int option, unsigned long arg2, unsigned long arg3,
|
|||||||
u32 *result = (u32 *)arg5;
|
u32 *result = (u32 *)arg5;
|
||||||
u32 reply_ok = KERNEL_SU_OPTION;
|
u32 reply_ok = KERNEL_SU_OPTION;
|
||||||
|
|
||||||
if (KERNEL_SU_OPTION != option) {
|
// we can skip this check when a manager is crowned already
|
||||||
return 0;
|
if (likely(ksu_is_manager_uid_valid()))
|
||||||
}
|
goto skip_check;
|
||||||
|
|
||||||
// TODO: find it in throne tracker!
|
// this is mostly for that multiuser bs
|
||||||
|
// here we just let them suffer
|
||||||
uid_t current_uid_val = current_uid().val;
|
uid_t current_uid_val = current_uid().val;
|
||||||
uid_t manager_uid = ksu_get_manager_uid();
|
uid_t manager_uid = ksu_get_manager_uid();
|
||||||
if (current_uid_val != manager_uid &&
|
if (current_uid_val != manager_uid &&
|
||||||
current_uid_val % 100000 == manager_uid) {
|
current_uid_val % 100000 == manager_uid) {
|
||||||
ksu_set_manager_uid(current_uid_val);
|
ksu_set_manager_uid(current_uid_val);
|
||||||
|
// make sure all cpus sees this change, next line will check
|
||||||
|
smp_mb();
|
||||||
}
|
}
|
||||||
|
|
||||||
bool from_root = 0 == current_uid().val;
|
skip_check:
|
||||||
|
// yes this causes delay, but this keeps the delay consistent, which is what we want
|
||||||
|
barrier();
|
||||||
|
if (!is_allow_su())
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
// we move it after uid check here so they cannot
|
||||||
|
// compare 0xdeadbeef call to a non-0xdeadbeef call
|
||||||
|
// with barriers around for safety as the compiler
|
||||||
|
// might try to do something smart.
|
||||||
|
barrier();
|
||||||
|
if (KERNEL_SU_OPTION != option)
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
// just continue old logic
|
||||||
|
bool from_root = !current_uid().val;
|
||||||
bool from_manager = is_manager();
|
bool from_manager = is_manager();
|
||||||
|
|
||||||
if (!from_root && !from_manager) {
|
if (!from_root && !from_manager) {
|
||||||
|
|||||||
Reference in New Issue
Block a user