Skip to content

Commit e8c63ea

Browse files
backslashxxselfmusing
authored andcommitted
kernel: restore compat code required for old kernels
This commit restores compatibility code needed that was removed at tiann/KernelSU@898e9d4 . where upstream dropped all pre-5.10 support Reverts `kernel:Add Huawei hisi check (tiann#1545)` - upstream tiann/KernelSU@4f05fe2 - superceded by `kernel: expose allowlist workaround as Kconfig option` on next commit other changes and cleanups sucompat: ksu_handle_stat(), remove dead ifdef. - just use `ksu_handle_stat(&dfd, &filename->name, &flags);` if you want to hook vfs_statx on 6.1 LINUX_VERSION_CODE / KERNEL_VERSION, ksu.c - reported by Sinclair19 - fix by including version.h fatal_signal_pending, ksud.c - add compat by including sched.h or sched/signal.h conditionally - ref: torvalds/linux@2a1f062 Signed-off-by: backslashxx <[email protected]>
1 parent 0f65fa5 commit e8c63ea

File tree

13 files changed

+447
-48
lines changed

13 files changed

+447
-48
lines changed

kernel/Makefile

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,14 @@ $(warning "KSU_GIT_VERSION not defined! It is better to make KernelSU a git subm
2929
ccflags-y += -DKSU_VERSION=16
3030
endif
3131

32+
ifeq ($(shell grep -q " current_sid(void)" $(srctree)/security/selinux/include/objsec.h; echo $$?),0)
33+
ccflags-y += -DKSU_COMPAT_HAS_CURRENT_SID
34+
endif
35+
36+
ifeq ($(shell grep -q "struct selinux_state " $(srctree)/security/selinux/include/security.h; echo $$?),0)
37+
ccflags-y += -DKSU_COMPAT_HAS_SELINUX_STATE
38+
endif
39+
3240
ifndef KSU_EXPECTED_SIZE
3341
KSU_EXPECTED_SIZE := 0x033b
3442
endif
@@ -48,6 +56,13 @@ $(info -- KernelSU Manager signature hash: $(KSU_EXPECTED_HASH))
4856
ccflags-y += -DEXPECTED_SIZE=$(KSU_EXPECTED_SIZE)
4957
ccflags-y += -DEXPECTED_HASH=\"$(KSU_EXPECTED_HASH)\"
5058

59+
ifeq ($(shell grep -q "int path_umount" $(srctree)/fs/namespace.c; echo $$?),0)
60+
ccflags-y += -DKSU_UMOUNT
61+
else
62+
$(info -- Did you know you can backport path_umount to fs/namespace.c from 5.9?)
63+
$(info -- Read: https://kernelsu.org/guide/how-to-integrate-for-non-gki.html#how-to-backport-path-umount)
64+
endif
65+
5166
ccflags-y += -Wno-implicit-function-declaration -Wno-strict-prototypes -Wno-int-conversion -Wno-gcc-compat
5267
ccflags-y += -Wno-declaration-after-statement -Wno-unused-function
5368

kernel/allowlist.c

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,9 @@
88
#include <linux/slab.h>
99
#include <linux/types.h>
1010
#include <linux/version.h>
11+
#if LINUX_VERSION_CODE >= KERNEL_VERSION(4, 14, 0)
1112
#include <linux/compiler_types.h>
13+
#endif
1214

1315
#include "ksu.h"
1416
#include "klog.h" // IWYU pragma: keep

kernel/core_hook.c

Lines changed: 40 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,6 @@
1818
#include <linux/namei.h>
1919

2020
#include "allowlist.h"
21-
2221
#include "core_hook.h"
2322
#include "klog.h" // IWYU pragma: keep
2423
#include "ksu.h"
@@ -87,7 +86,11 @@ static void setup_groups(struct root_profile *profile, struct cred *cred)
8786
put_group_info(group_info);
8887
return;
8988
}
89+
#if LINUX_VERSION_CODE >= KERNEL_VERSION(4, 9, 0)
9090
group_info->gid[i] = kgid;
91+
#else
92+
GROUP_AT(group_info, i) = kgid;
93+
#endif
9194
}
9295

9396
groups_sort(group_info);
@@ -503,12 +506,14 @@ static bool should_umount(struct path *path)
503506
return false;
504507
}
505508

506-
static void ksu_umount_mnt(struct path *path, int flags)
509+
static int ksu_umount_mnt(struct path *path, int flags)
507510
{
508-
int err = path_umount(path, flags);
509-
if (err) {
510-
pr_info("umount %s failed: %d\n", path->dentry->d_iname, err);
511-
}
511+
#if LINUX_VERSION_CODE >= KERNEL_VERSION(5, 9, 0) || defined(KSU_UMOUNT)
512+
return path_umount(path, flags);
513+
#else
514+
// TODO: umount for non GKI kernel
515+
return -ENOSYS;
516+
#endif
512517
}
513518

514519
static void try_umount(const char *mnt, bool check_mnt, int flags)
@@ -529,7 +534,10 @@ static void try_umount(const char *mnt, bool check_mnt, int flags)
529534
return;
530535
}
531536

532-
ksu_umount_mnt(&path, flags);
537+
err = ksu_umount_mnt(&path, flags);
538+
if (err) {
539+
pr_warn("umount %s failed: %d\n", mnt, err);
540+
}
533541
}
534542

535543
int ksu_handle_setuid(struct cred *new, const struct cred *old)
@@ -605,7 +613,23 @@ static int ksu_task_prctl(int option, unsigned long arg2, unsigned long arg3,
605613
ksu_handle_prctl(option, arg2, arg3, arg4, arg5);
606614
return -ENOSYS;
607615
}
608-
616+
// kernel 4.4 and 4.9
617+
#if LINUX_VERSION_CODE < KERNEL_VERSION(4, 10, 0)
618+
static int ksu_key_permission(key_ref_t key_ref, const struct cred *cred,
619+
unsigned perm)
620+
{
621+
if (init_session_keyring != NULL) {
622+
return 0;
623+
}
624+
if (strcmp(current->comm, "init")) {
625+
// we are only interested in `init` process
626+
return 0;
627+
}
628+
init_session_keyring = cred->session_keyring;
629+
pr_info("kernel_compat: got init_session_keyring\n");
630+
return 0;
631+
}
632+
#endif
609633
static int ksu_inode_rename(struct inode *old_inode, struct dentry *old_dentry,
610634
struct inode *new_inode, struct dentry *new_dentry)
611635
{
@@ -622,11 +646,19 @@ static struct security_hook_list ksu_hooks[] = {
622646
LSM_HOOK_INIT(task_prctl, ksu_task_prctl),
623647
LSM_HOOK_INIT(inode_rename, ksu_inode_rename),
624648
LSM_HOOK_INIT(task_fix_setuid, ksu_task_fix_setuid),
649+
#if LINUX_VERSION_CODE < KERNEL_VERSION(4, 10, 0)
650+
LSM_HOOK_INIT(key_permission, ksu_key_permission)
651+
#endif
625652
};
626653

627654
void __init ksu_lsm_hook_init(void)
628655
{
656+
#if LINUX_VERSION_CODE >= KERNEL_VERSION(4, 11, 0)
629657
security_add_hooks(ksu_hooks, ARRAY_SIZE(ksu_hooks), "ksu");
658+
#else
659+
// https://elixir.bootlin.com/linux/v4.10.17/source/include/linux/lsm_hooks.h#L1892
660+
security_add_hooks(ksu_hooks, ARRAY_SIZE(ksu_hooks));
661+
#endif
630662
}
631663

632664
void __init ksu_core_init(void)

kernel/kernel_compat.c

Lines changed: 88 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,38 @@
11
#include <linux/version.h>
22
#include <linux/fs.h>
33
#include <linux/nsproxy.h>
4+
#if LINUX_VERSION_CODE >= KERNEL_VERSION(4, 10, 0)
45
#include <linux/sched/task.h>
6+
#else
7+
#include <linux/sched.h>
8+
#endif
59
#include <linux/uaccess.h>
610
#include "klog.h" // IWYU pragma: keep
7-
#include "kernel_compat.h"
11+
12+
#if LINUX_VERSION_CODE < KERNEL_VERSION(4, 10, 0)
13+
#include "linux/key.h"
14+
#include "linux/errno.h"
15+
#include "linux/cred.h"
16+
struct key *init_session_keyring = NULL;
17+
18+
static inline int install_session_keyring(struct key *keyring)
19+
{
20+
struct cred *new;
21+
int ret;
22+
23+
new = prepare_creds();
24+
if (!new)
25+
return -ENOMEM;
26+
27+
ret = install_session_keyring_to_cred(new, keyring);
28+
if (ret < 0) {
29+
abort_creds(new);
30+
return ret;
31+
}
32+
33+
return commit_creds(new);
34+
}
35+
#endif
836

937
extern struct task_struct init_task;
1038

@@ -50,6 +78,13 @@ void ksu_android_ns_fs_check()
5078

5179
struct file *ksu_filp_open_compat(const char *filename, int flags, umode_t mode)
5280
{
81+
#if LINUX_VERSION_CODE < KERNEL_VERSION(4, 10, 0)
82+
if (init_session_keyring != NULL && !current_cred()->session_keyring &&
83+
(current->flags & PF_WQ_WORKER)) {
84+
pr_info("installing init session keyring for older kernel\n");
85+
install_session_keyring(init_session_keyring);
86+
}
87+
#endif
5388
// switch mnt_ns even if current is not wq_worker, to ensure what we open is the correct file in android mnt_ns, rather than user created mnt_ns
5489
struct ksu_ns_fs_saved saved;
5590
if (android_context_saved_enabled) {
@@ -72,17 +107,69 @@ struct file *ksu_filp_open_compat(const char *filename, int flags, umode_t mode)
72107
ssize_t ksu_kernel_read_compat(struct file *p, void *buf, size_t count,
73108
loff_t *pos)
74109
{
110+
#if LINUX_VERSION_CODE >= KERNEL_VERSION(4, 14, 0)
75111
return kernel_read(p, buf, count, pos);
112+
#else
113+
loff_t offset = pos ? *pos : 0;
114+
ssize_t result = kernel_read(p, offset, (char *)buf, count);
115+
if (pos && result > 0) {
116+
*pos = offset + result;
117+
}
118+
return result;
119+
#endif
76120
}
77121

78122
ssize_t ksu_kernel_write_compat(struct file *p, const void *buf, size_t count,
79123
loff_t *pos)
80124
{
125+
#if LINUX_VERSION_CODE >= KERNEL_VERSION(4, 14, 0)
81126
return kernel_write(p, buf, count, pos);
127+
#else
128+
loff_t offset = pos ? *pos : 0;
129+
ssize_t result = kernel_write(p, buf, count, offset);
130+
if (pos && result > 0) {
131+
*pos = offset + result;
132+
}
133+
return result;
134+
#endif
82135
}
83136

137+
#if LINUX_VERSION_CODE >= KERNEL_VERSION(5, 8, 0)
84138
long ksu_strncpy_from_user_nofault(char *dst, const void __user *unsafe_addr,
85139
long count)
86140
{
87141
return strncpy_from_user_nofault(dst, unsafe_addr, count);
88142
}
143+
#elif LINUX_VERSION_CODE >= KERNEL_VERSION(5, 3, 0)
144+
long ksu_strncpy_from_user_nofault(char *dst, const void __user *unsafe_addr,
145+
long count)
146+
{
147+
return strncpy_from_unsafe_user(dst, unsafe_addr, count);
148+
}
149+
#else
150+
// Copied from: https://elixir.bootlin.com/linux/v4.9.337/source/mm/maccess.c#L201
151+
long ksu_strncpy_from_user_nofault(char *dst, const void __user *unsafe_addr,
152+
long count)
153+
{
154+
mm_segment_t old_fs = get_fs();
155+
long ret;
156+
157+
if (unlikely(count <= 0))
158+
return 0;
159+
160+
set_fs(USER_DS);
161+
pagefault_disable();
162+
ret = strncpy_from_user(dst, unsafe_addr, count);
163+
pagefault_enable();
164+
set_fs(old_fs);
165+
166+
if (ret >= count) {
167+
ret = count;
168+
dst[ret - 1] = '\0';
169+
} else if (ret > 0) {
170+
ret++;
171+
}
172+
173+
return ret;
174+
}
175+
#endif

kernel/kernel_compat.h

Lines changed: 7 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -1,29 +1,19 @@
11
#ifndef __KSU_H_KERNEL_COMPAT
22
#define __KSU_H_KERNEL_COMPAT
33

4-
#include <linux/fs.h>
5-
#include <linux/version.h>
6-
#include "ss/policydb.h"
4+
#include "linux/fs.h"
5+
#include "linux/key.h"
6+
#include "linux/version.h"
77
#include "linux/key.h"
8-
9-
/*
10-
* Adapt to Huawei HISI kernel without affecting other kernels ,
11-
* Huawei Hisi Kernel EBITMAP Enable or Disable Flag ,
12-
* From ss/ebitmap.h
13-
*/
14-
#if (LINUX_VERSION_CODE >= KERNEL_VERSION(4, 9, 0)) && \
15-
(LINUX_VERSION_CODE < KERNEL_VERSION(4, 10, 0)) || \
16-
(LINUX_VERSION_CODE >= KERNEL_VERSION(4, 14, 0)) && \
17-
(LINUX_VERSION_CODE < KERNEL_VERSION(4, 15, 0))
18-
#ifdef HISI_SELINUX_EBITMAP_RO
19-
#define CONFIG_IS_HW_HISI
20-
#endif
21-
#endif
228

239
extern long ksu_strncpy_from_user_nofault(char *dst,
2410
const void __user *unsafe_addr,
2511
long count);
2612

13+
#if LINUX_VERSION_CODE < KERNEL_VERSION(4, 10, 0)
14+
extern struct key *init_session_keyring;
15+
#endif
16+
2717
extern void ksu_android_ns_fs_check();
2818
extern struct file *ksu_filp_open_compat(const char *filename, int flags,
2919
umode_t mode);

kernel/ksu.c

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22
#include <linux/fs.h>
33
#include <linux/kobject.h>
44
#include <linux/module.h>
5+
#include <linux/version.h> /* LINUX_VERSION_CODE, KERNEL_VERSION macros */
56
#include <linux/workqueue.h>
67

78
#include "allowlist.h"
@@ -70,4 +71,7 @@ module_exit(kernelsu_exit);
7071
MODULE_LICENSE("GPL");
7172
MODULE_AUTHOR("weishu");
7273
MODULE_DESCRIPTION("Android KernelSU");
74+
75+
#if LINUX_VERSION_CODE >= KERNEL_VERSION(5, 0, 0)
7376
MODULE_IMPORT_NS(VFS_internal_I_am_really_a_filesystem_and_am_NOT_a_driver);
77+
#endif

kernel/ksud.c

Lines changed: 13 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -6,12 +6,23 @@
66
#include <linux/file.h>
77
#include <linux/fs.h>
88
#include <linux/version.h>
9+
#if LINUX_VERSION_CODE >= KERNEL_VERSION(4, 4, 0)
910
#include <linux/input-event-codes.h>
11+
#else
12+
#include <uapi/linux/input.h>
13+
#endif
14+
#if LINUX_VERSION_CODE < KERNEL_VERSION(4, 1, 0)
15+
#include <linux/aio.h>
16+
#endif
1017
#include <linux/printk.h>
1118
#include <linux/types.h>
1219
#include <linux/uaccess.h>
1320
#include <linux/workqueue.h>
14-
#include <linux/sched/signal.h>
21+
#if LINUX_VERSION_CODE >= KERNEL_VERSION(4, 11, 0)
22+
#include <linux/sched/signal.h> /* fatal_signal_pending */
23+
#else
24+
#include <linux/sched.h> /* fatal_signal_pending */
25+
#endif
1526

1627
#include "allowlist.h"
1728
#include "klog.h" // IWYU pragma: keep
@@ -143,7 +154,6 @@ int ksu_handle_execveat_ksud(int *fd, struct filename **filename_ptr,
143154
struct user_arg_ptr *argv,
144155
struct user_arg_ptr *envp, int *flags)
145156
{
146-
147157
if (!ksu_execveat_hook) {
148158
return 0;
149159
}
@@ -341,7 +351,7 @@ int ksu_handle_vfs_read(struct file **file_ptr, char __user **buf_ptr,
341351
// we only process the first read
342352
static bool rc_inserted = false;
343353
if (rc_inserted) {
344-
// we don't need this kprobe, unregister it!
354+
// we don't need this hook, unregister it!
345355
stop_vfs_read_hook();
346356
return 0;
347357
}
@@ -412,7 +422,6 @@ static bool is_volumedown_enough(unsigned int count)
412422
int ksu_handle_input_handle_event(unsigned int *type, unsigned int *code,
413423
int *value)
414424
{
415-
416425
if (!ksu_input_hook) {
417426
return 0;
418427
}

0 commit comments

Comments
 (0)