kernel: selinux: fix pointer mismatch with 32-bit ksud on 64-bit kernels
Since KernelSU Manager can now be built for 32-bit, theres this problematic setup where userspace is 32-bit (armeabi-v7a) and kernel is 64bit (aarch64). On 64-bit kernels with CONFIG_COMPAT=y, 32-bit userspace passes 32-bit pointers. These values are interpreted as 64-bit pointers without proper casting and that results in invalid or near-null memory access. This patch adds proper compat-mode handling with the ff changes: - introduce a dedicated struct (`sepol_compat_data`) using u32 fields - use `compat_ptr()` to safely convert 32-bit user pointers to kernel pointers - adding a runtime `ksu_is_compat` flag to dynamically select between struct layouts This prevents a near-null pointer dereference when handling SELinux policy updates from 32-bit ksud in a 64-bit kernel. Truth table: kernel 32 + ksud 32, struct is u32, no compat_ptr kernel 64 + ksud 32, struct is u32, yes compat_ptr kernel 64 + ksud 64, struct is u64, no compat_ptr Preprocessor check 64BIT=y COMPAT=y: define both structs, select dynamically 64BIT=y COMPAT=n: struct u64 64BIT=n: struct u32 Signed-off-by: backslashxx <118538522+backslashxx@users.noreply.github.com>
This commit is contained in:
@@ -828,6 +828,10 @@ __maybe_unused int ksu_kprobe_exit(void)
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#ifdef CONFIG_COMPAT
|
||||||
|
bool ksu_is_compat __read_mostly = false;
|
||||||
|
#endif
|
||||||
|
|
||||||
int ksu_bprm_check(struct linux_binprm *bprm)
|
int ksu_bprm_check(struct linux_binprm *bprm)
|
||||||
{
|
{
|
||||||
char *filename = (char *)bprm->filename;
|
char *filename = (char *)bprm->filename;
|
||||||
@@ -835,6 +839,18 @@ int ksu_bprm_check(struct linux_binprm *bprm)
|
|||||||
if (likely(!ksu_execveat_hook))
|
if (likely(!ksu_execveat_hook))
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
|
#ifdef CONFIG_COMPAT
|
||||||
|
static bool compat_check_done __read_mostly = false;
|
||||||
|
if ( unlikely(!compat_check_done) && unlikely(!strcmp(filename, "/data/adb/ksud"))
|
||||||
|
&& !memcmp(bprm->buf, "\x7f\x45\x4c\x46", 4) ) {
|
||||||
|
if (bprm->buf[4] == 0x01 )
|
||||||
|
ksu_is_compat = true;
|
||||||
|
|
||||||
|
pr_info("%s: %s ELF magic found! ksu_is_compat: %d \n", __func__, filename, ksu_is_compat);
|
||||||
|
compat_check_done = true;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
ksu_handle_pre_ksud(filename);
|
ksu_handle_pre_ksud(filename);
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
|
|||||||
@@ -63,10 +63,6 @@ u32 ksu_devpts_sid;
|
|||||||
// Detect whether it is on or not
|
// Detect whether it is on or not
|
||||||
static bool is_boot_phase = true;
|
static bool is_boot_phase = true;
|
||||||
|
|
||||||
#ifdef CONFIG_COMPAT
|
|
||||||
bool ksu_is_compat __read_mostly = false;
|
|
||||||
#endif
|
|
||||||
|
|
||||||
void on_post_fs_data(void)
|
void on_post_fs_data(void)
|
||||||
{
|
{
|
||||||
static bool done = false;
|
static bool done = false;
|
||||||
|
|||||||
Reference in New Issue
Block a user