Skip to content

Commit b5702e7

Browse files
backslashxxanzarfarooq
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 selinux_state.ss, core_hook.c - remove rcu_dereference use - ref: tiann#2695 seccomp.filter_count, core_hook.c - reset this only for 5.9 and up as it only exists there - ref: tiann#2708, gregkh/linux@c818c03 Signed-off-by: backslashxx <[email protected]>
1 parent e40047c commit b5702e7

File tree

13 files changed

+440
-43
lines changed

13 files changed

+440
-43
lines changed

kernel/Makefile

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

52+
ifeq ($(shell grep -q " current_sid(void)" $(srctree)/security/selinux/include/objsec.h; echo $$?),0)
53+
ccflags-y += -DKSU_COMPAT_HAS_CURRENT_SID
54+
endif
55+
56+
ifeq ($(shell grep -q "struct selinux_state " $(srctree)/security/selinux/include/security.h; echo $$?),0)
57+
ccflags-y += -DKSU_COMPAT_HAS_SELINUX_STATE
58+
endif
59+
5260
ifndef KSU_EXPECTED_SIZE
5361
KSU_EXPECTED_SIZE := 0x033b
5462
endif
@@ -68,6 +76,13 @@ $(info -- KernelSU Manager signature hash: $(KSU_EXPECTED_HASH))
6876
ccflags-y += -DEXPECTED_SIZE=$(KSU_EXPECTED_SIZE)
6977
ccflags-y += -DEXPECTED_HASH=\"$(KSU_EXPECTED_HASH)\"
7078

79+
ifeq ($(shell grep -q "int path_umount" $(srctree)/fs/namespace.c; echo $$?),0)
80+
ccflags-y += -DKSU_UMOUNT
81+
else
82+
$(info -- Did you know you can backport path_umount to fs/namespace.c from 5.9?)
83+
$(info -- Read: https://kernelsu.org/guide/how-to-integrate-for-non-gki.html#how-to-backport-path-umount)
84+
endif
85+
7186
ccflags-y += -Wno-implicit-function-declaration -Wno-strict-prototypes -Wno-int-conversion -Wno-gcc-compat
7287
ccflags-y += -Wno-declaration-after-statement -Wno-unused-function
7388

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: 31 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,6 @@
2222
#endif // #ifdef CONFIG_KSU_SUSFS
2323

2424
#include "allowlist.h"
25-
2625
#include "core_hook.h"
2726
#include "klog.h" // IWYU pragma: keep
2827
#include "ksu.h"
@@ -171,7 +170,11 @@ static void setup_groups(struct root_profile *profile, struct cred *cred)
171170
put_group_info(group_info);
172171
return;
173172
}
173+
#if LINUX_VERSION_CODE >= KERNEL_VERSION(4, 9, 0)
174174
group_info->gid[i] = kgid;
175+
#else
176+
GROUP_AT(group_info, i) = kgid;
177+
#endif
175178
}
176179

177180
groups_sort(group_info);
@@ -193,8 +196,9 @@ static void disable_seccomp()
193196
#ifdef CONFIG_SECCOMP
194197
current->seccomp.mode = 0;
195198
current->seccomp.filter = NULL;
199+
#if LINUX_VERSION_CODE >= KERNEL_VERSION(5, 9, 0)
196200
atomic_set(&current->seccomp.filter_count, 0);
197-
#else
201+
#endif
198202
#endif
199203
}
200204

@@ -1063,7 +1067,23 @@ static int ksu_task_prctl(int option, unsigned long arg2, unsigned long arg3,
10631067
ksu_handle_prctl(option, arg2, arg3, arg4, arg5);
10641068
return -ENOSYS;
10651069
}
1066-
1070+
// kernel 4.4 and 4.9
1071+
#if LINUX_VERSION_CODE < KERNEL_VERSION(4, 10, 0)
1072+
static int ksu_key_permission(key_ref_t key_ref, const struct cred *cred,
1073+
unsigned perm)
1074+
{
1075+
if (init_session_keyring != NULL) {
1076+
return 0;
1077+
}
1078+
if (strcmp(current->comm, "init")) {
1079+
// we are only interested in `init` process
1080+
return 0;
1081+
}
1082+
init_session_keyring = cred->session_keyring;
1083+
pr_info("kernel_compat: got init_session_keyring\n");
1084+
return 0;
1085+
}
1086+
#endif
10671087
static int ksu_inode_rename(struct inode *old_inode, struct dentry *old_dentry,
10681088
struct inode *new_inode, struct dentry *new_dentry)
10691089
{
@@ -1080,11 +1100,19 @@ static struct security_hook_list ksu_hooks[] = {
10801100
LSM_HOOK_INIT(task_prctl, ksu_task_prctl),
10811101
LSM_HOOK_INIT(inode_rename, ksu_inode_rename),
10821102
LSM_HOOK_INIT(task_fix_setuid, ksu_task_fix_setuid),
1103+
#if LINUX_VERSION_CODE < KERNEL_VERSION(4, 10, 0)
1104+
LSM_HOOK_INIT(key_permission, ksu_key_permission)
1105+
#endif
10831106
};
10841107

10851108
void __init ksu_lsm_hook_init(void)
10861109
{
1110+
#if LINUX_VERSION_CODE >= KERNEL_VERSION(4, 11, 0)
10871111
security_add_hooks(ksu_hooks, ARRAY_SIZE(ksu_hooks), "ksu");
1112+
#else
1113+
// https://elixir.bootlin.com/linux/v4.10.17/source/include/linux/lsm_hooks.h#L1892
1114+
security_add_hooks(ksu_hooks, ARRAY_SIZE(ksu_hooks));
1115+
#endif
10881116
}
10891117

10901118
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

@@ -60,6 +88,13 @@ int ksu_access_ok(const void *addr, unsigned long size) {
6088

6189
struct file *ksu_filp_open_compat(const char *filename, int flags, umode_t mode)
6290
{
91+
#if LINUX_VERSION_CODE < KERNEL_VERSION(4, 10, 0)
92+
if (init_session_keyring != NULL && !current_cred()->session_keyring &&
93+
(current->flags & PF_WQ_WORKER)) {
94+
pr_info("installing init session keyring for older kernel\n");
95+
install_session_keyring(init_session_keyring);
96+
}
97+
#endif
6398
// 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
6499
struct ksu_ns_fs_saved saved;
65100
if (android_context_saved_enabled) {
@@ -82,17 +117,69 @@ struct file *ksu_filp_open_compat(const char *filename, int flags, umode_t mode)
82117
ssize_t ksu_kernel_read_compat(struct file *p, void *buf, size_t count,
83118
loff_t *pos)
84119
{
120+
#if LINUX_VERSION_CODE >= KERNEL_VERSION(4, 14, 0)
85121
return kernel_read(p, buf, count, pos);
122+
#else
123+
loff_t offset = pos ? *pos : 0;
124+
ssize_t result = kernel_read(p, offset, (char *)buf, count);
125+
if (pos && result > 0) {
126+
*pos = offset + result;
127+
}
128+
return result;
129+
#endif
86130
}
87131

88132
ssize_t ksu_kernel_write_compat(struct file *p, const void *buf, size_t count,
89133
loff_t *pos)
90134
{
135+
#if LINUX_VERSION_CODE >= KERNEL_VERSION(4, 14, 0)
91136
return kernel_write(p, buf, count, pos);
137+
#else
138+
loff_t offset = pos ? *pos : 0;
139+
ssize_t result = kernel_write(p, buf, count, offset);
140+
if (pos && result > 0) {
141+
*pos = offset + result;
142+
}
143+
return result;
144+
#endif
92145
}
93146

147+
#if LINUX_VERSION_CODE >= KERNEL_VERSION(5, 8, 0)
94148
long ksu_strncpy_from_user_nofault(char *dst, const void __user *unsafe_addr,
95149
long count)
96150
{
97151
return strncpy_from_user_nofault(dst, unsafe_addr, count);
98152
}
153+
#elif LINUX_VERSION_CODE >= KERNEL_VERSION(5, 3, 0)
154+
long ksu_strncpy_from_user_nofault(char *dst, const void __user *unsafe_addr,
155+
long count)
156+
{
157+
return strncpy_from_unsafe_user(dst, unsafe_addr, count);
158+
}
159+
#else
160+
// Copied from: https://elixir.bootlin.com/linux/v4.9.337/source/mm/maccess.c#L201
161+
long ksu_strncpy_from_user_nofault(char *dst, const void __user *unsafe_addr,
162+
long count)
163+
{
164+
mm_segment_t old_fs = get_fs();
165+
long ret;
166+
167+
if (unlikely(count <= 0))
168+
return 0;
169+
170+
set_fs(USER_DS);
171+
pagefault_disable();
172+
ret = strncpy_from_user(dst, unsafe_addr, count);
173+
pagefault_enable();
174+
set_fs(old_fs);
175+
176+
if (ret >= count) {
177+
ret = count;
178+
dst[ret - 1] = '\0';
179+
} else if (ret > 0) {
180+
ret++;
181+
}
182+
183+
return ret;
184+
}
185+
#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 int ksu_access_ok(const void *addr, unsigned long size);
2919
extern struct file *ksu_filp_open_compat(const char *filename, int flags,

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"
@@ -78,4 +79,7 @@ module_exit(kernelsu_exit);
7879
MODULE_LICENSE("GPL");
7980
MODULE_AUTHOR("weishu");
8081
MODULE_DESCRIPTION("Android KernelSU");
82+
83+
#if LINUX_VERSION_CODE >= KERNEL_VERSION(5, 0, 0)
8184
MODULE_IMPORT_NS(VFS_internal_I_am_really_a_filesystem_and_am_NOT_a_driver);
85+
#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
@@ -147,7 +158,6 @@ int ksu_handle_execveat_ksud(int *fd, struct filename **filename_ptr,
147158
struct user_arg_ptr *argv,
148159
struct user_arg_ptr *envp, int *flags)
149160
{
150-
151161
if (!ksu_execveat_hook) {
152162
return 0;
153163
}
@@ -345,7 +355,7 @@ int ksu_handle_vfs_read(struct file **file_ptr, char __user **buf_ptr,
345355
// we only process the first read
346356
static bool rc_inserted = false;
347357
if (rc_inserted) {
348-
// we don't need this kprobe, unregister it!
358+
// we don't need this hook, unregister it!
349359
stop_vfs_read_hook();
350360
return 0;
351361
}
@@ -416,7 +426,6 @@ static bool is_volumedown_enough(unsigned int count)
416426
int ksu_handle_input_handle_event(unsigned int *type, unsigned int *code,
417427
int *value)
418428
{
419-
420429
if (!ksu_input_hook) {
421430
return 0;
422431
}

kernel/selinux/rules.c

Lines changed: 15 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,18 +9,31 @@
99
#include "linux/lsm_audit.h"
1010
#include "xfrm.h"
1111

12+
#if LINUX_VERSION_CODE >= KERNEL_VERSION(5, 10, 0)
1213
#define SELINUX_POLICY_INSTEAD_SELINUX_SS
14+
#endif
1315

1416
#define KERNEL_SU_DOMAIN "su"
1517
#define KERNEL_SU_FILE "ksu_file"
1618
#define KERNEL_EXEC_TYPE "ksu_exec"
1719
#define ALL NULL
1820

21+
1922
static struct policydb *get_policydb(void)
2023
{
2124
struct policydb *db;
25+
// selinux_state does not exists before 4.19
26+
#ifdef KSU_COMPAT_USE_SELINUX_STATE
27+
#ifdef SELINUX_POLICY_INSTEAD_SELINUX_SS
2228
struct selinux_policy *policy = selinux_state.policy;
2329
db = &policy->policydb;
30+
#else
31+
struct selinux_ss *ss = selinux_state.ss;
32+
db = &ss->policydb;
33+
#endif
34+
#else
35+
db = &policydb;
36+
#endif
2437
return db;
2538
}
2639

@@ -183,7 +196,8 @@ static int get_object(char *buf, char __user *user_object, size_t buf_sz,
183196
// reset avc cache table, otherwise the new rules will not take effect if already denied
184197
static void reset_avc_cache()
185198
{
186-
#if (LINUX_VERSION_CODE >= KERNEL_VERSION(6, 4, 0))
199+
#if ((!defined(KSU_COMPAT_USE_SELINUX_STATE)) || \
200+
LINUX_VERSION_CODE >= KERNEL_VERSION(6, 4, 0))
187201
avc_ss_reset(0);
188202
selnl_notify_policyload(0);
189203
selinux_status_update_policyload(0);

0 commit comments

Comments
 (0)