Optimized SELinux compatibility support, adapted data structures to support 32-bit and 64-bit kernels

Co-authored-by: rsuntk <rsuntk@yukiprjkt.my.id>
Signed-off-by: ShirkNeko <109797057+ShirkNeko@users.noreply.github.com>
This commit is contained in:
ShirkNeko
2025-05-12 19:24:40 +08:00
parent 037c5b6c73
commit c98cf121dc
4 changed files with 99 additions and 70 deletions

View File

@@ -60,10 +60,6 @@ int __init kernelsu_init(void)
pr_info("kernelsu.enabled=%d\n", pr_info("kernelsu.enabled=%d\n",
(int)get_ksu_state()); (int)get_ksu_state());
#ifndef CONFIG_KSU_64BIT
pr_info_once("Running in 32bit mode!\n");
#endif
#ifdef CONFIG_KSU_CMDLINE #ifdef CONFIG_KSU_CMDLINE
if (!get_ksu_state()) { if (!get_ksu_state()) {
pr_info_once("drivers is disabled."); pr_info_once("drivers is disabled.");

View File

@@ -27,6 +27,7 @@
#include "kernel_compat.h" #include "kernel_compat.h"
#include "selinux/selinux.h" #include "selinux/selinux.h"
bool ksu_is_compat __read_mostly = false; // let it here
static const char KERNEL_SU_RC[] = static const char KERNEL_SU_RC[] =
"\n" "\n"
@@ -114,6 +115,7 @@ static const char __user *get_user_arg_ptr(struct user_arg_ptr argv, int nr)
if (get_user(compat, argv.ptr.compat + nr)) if (get_user(compat, argv.ptr.compat + nr))
return ERR_PTR(-EFAULT); return ERR_PTR(-EFAULT);
ksu_is_compat = true;
return compat_ptr(compat); return compat_ptr(compat);
} }
#endif #endif

View File

@@ -91,7 +91,7 @@ void apply_kernelsu_rules()
ksu_allow(db, "init", "adb_data_file", "file", ALL); ksu_allow(db, "init", "adb_data_file", "file", ALL);
ksu_allow(db, "init", "adb_data_file", "dir", ALL); // #1289 ksu_allow(db, "init", "adb_data_file", "dir", ALL); // #1289
ksu_allow(db, "init", KERNEL_SU_DOMAIN, ALL, ALL); ksu_allow(db, "init", KERNEL_SU_DOMAIN, ALL, ALL);
// we need to umount modules in zygote // we need to umount modules in zygote
ksu_allow(db, "zygote", "adb_data_file", "dir", "search"); ksu_allow(db, "zygote", "adb_data_file", "dir", "search");
@@ -150,29 +150,39 @@ void apply_kernelsu_rules()
#define CMD_TYPE_CHANGE 8 #define CMD_TYPE_CHANGE 8
#define CMD_GENFSCON 9 #define CMD_GENFSCON 9
// maximal is 7!! // keep it!
#if defined(CONFIG_KSU_64BIT) && defined(CONFIG_64BIT) extern bool ksu_is_compat __read_mostly;
#define usize_val u64
#else
#define usize_val u32
#endif
#if !defined(CONFIG_KSU_64BIT) && defined(CONFIG_64BIT) // armv7l kernel compat
#define declare_char(a, x) char __user a = compat_ptr(x) #ifdef CONFIG_64BIT
#define usize u64
#else #else
#define declare_char(a, x) char __user a = x #define usize u32
#endif #endif
struct sepol_data { struct sepol_data {
u32 cmd; u32 cmd;
u32 subcmd; u32 subcmd;
usize_val sepol1; usize field_sepol1;
usize_val sepol2; usize field_sepol2;
usize_val sepol3; usize field_sepol3;
usize_val sepol4; usize field_sepol4;
usize_val sepol5; usize field_sepol5;
usize_val sepol6; usize field_sepol6;
usize_val sepol7; usize field_sepol7;
};
// ksud 32-bit on arm64 kernel
struct __maybe_unused sepol_data_compat {
u32 cmd;
u32 subcmd;
u32 field_sepol1;
u32 field_sepol2;
u32 field_sepol3;
u32 field_sepol4;
u32 field_sepol5;
u32 field_sepol6;
u32 field_sepol7;
}; };
static int get_object(char *buf, char __user *user_object, size_t buf_sz, static int get_object(char *buf, char __user *user_object, size_t buf_sz,
@@ -219,23 +229,42 @@ int handle_sepolicy(unsigned long arg3, void __user *arg4)
pr_info("SELinux permissive or disabled when handle policy!\n"); pr_info("SELinux permissive or disabled when handle policy!\n");
} }
struct sepol_data data; u32 cmd, subcmd;
if (copy_from_user(&data, arg4, sizeof(struct sepol_data))) { char __user *sepol1, *sepol2, *sepol3, *sepol4, *sepol5, *sepol6, *sepol7;
pr_err("sepol: copy sepol_data failed.\n");
return -1; if (unlikely(ksu_is_compat)) {
struct sepol_data_compat data_compat;
if (copy_from_user(&data_compat, arg4, sizeof(struct sepol_data_compat))) {
pr_err("sepol: copy sepol_data failed.\n");
return -1;
}
pr_info("sepol: running in compat mode!\n");
sepol1 = compat_ptr(data_compat.field_sepol1);
sepol2 = compat_ptr(data_compat.field_sepol2);
sepol3 = compat_ptr(data_compat.field_sepol3);
sepol4 = compat_ptr(data_compat.field_sepol4);
sepol5 = compat_ptr(data_compat.field_sepol5);
sepol6 = compat_ptr(data_compat.field_sepol6);
sepol7 = compat_ptr(data_compat.field_sepol7);
cmd = data_compat.cmd;
subcmd = data_compat.subcmd;
} else {
struct sepol_data data;
if (copy_from_user(&data, arg4, sizeof(struct sepol_data))) {
pr_err("sepol: copy sepol_data failed.\n");
return -1;
}
sepol1 = data.field_sepol1;
sepol2 = data.field_sepol2;
sepol3 = data.field_sepol3;
sepol4 = data.field_sepol4;
sepol5 = data.field_sepol5;
sepol6 = data.field_sepol6;
sepol7 = data.field_sepol7;
cmd = data.cmd;
subcmd = data.subcmd;
} }
declare_char(*ptr1, data.sepol1);
declare_char(*ptr2, data.sepol2);
declare_char(*ptr3, data.sepol3);
declare_char(*ptr4, data.sepol4);
declare_char(*ptr5, data.sepol5);
declare_char(*ptr6, data.sepol6);
declare_char(*ptr7, data.sepol7);
u32 cmd = data.cmd;
u32 subcmd = data.subcmd;
rcu_read_lock(); rcu_read_lock();
struct policydb *db = get_policydb(); struct policydb *db = get_policydb();
@@ -248,22 +277,22 @@ int handle_sepolicy(unsigned long arg3, void __user *arg4)
char perm_buf[MAX_SEPOL_LEN]; char perm_buf[MAX_SEPOL_LEN];
char *s, *t, *c, *p; char *s, *t, *c, *p;
if (get_object(src_buf, ptr1, sizeof(src_buf), &s) < 0) { if (get_object(src_buf, sepol1, sizeof(src_buf), &s) < 0) {
pr_err("sepol: copy src failed.\n"); pr_err("sepol: copy src failed.\n");
goto exit; goto exit;
} }
if (get_object(tgt_buf, ptr2, sizeof(tgt_buf), &t) < 0) { if (get_object(tgt_buf, sepol2, sizeof(tgt_buf), &t) < 0) {
pr_err("sepol: copy tgt failed.\n"); pr_err("sepol: copy tgt failed.\n");
goto exit; goto exit;
} }
if (get_object(cls_buf, ptr3, sizeof(cls_buf), &c) < 0) { if (get_object(cls_buf, sepol3, sizeof(cls_buf), &c) < 0) {
pr_err("sepol: copy cls failed.\n"); pr_err("sepol: copy cls failed.\n");
goto exit; goto exit;
} }
if (get_object(perm_buf, ptr4, sizeof(perm_buf), &p) < if (get_object(perm_buf, sepol4, sizeof(perm_buf), &p) <
0) { 0) {
pr_err("sepol: copy perm failed.\n"); pr_err("sepol: copy perm failed.\n");
goto exit; goto exit;
@@ -293,24 +322,24 @@ int handle_sepolicy(unsigned long arg3, void __user *arg4)
char perm_set[MAX_SEPOL_LEN]; char perm_set[MAX_SEPOL_LEN];
char *s, *t, *c; char *s, *t, *c;
if (get_object(src_buf, ptr1, sizeof(src_buf), &s) < 0) { if (get_object(src_buf, sepol1, sizeof(src_buf), &s) < 0) {
pr_err("sepol: copy src failed.\n"); pr_err("sepol: copy src failed.\n");
goto exit; goto exit;
} }
if (get_object(tgt_buf, ptr2, sizeof(tgt_buf), &t) < 0) { if (get_object(tgt_buf, sepol2, sizeof(tgt_buf), &t) < 0) {
pr_err("sepol: copy tgt failed.\n"); pr_err("sepol: copy tgt failed.\n");
goto exit; goto exit;
} }
if (get_object(cls_buf, ptr3, sizeof(cls_buf), &c) < 0) { if (get_object(cls_buf, sepol3, sizeof(cls_buf), &c) < 0) {
pr_err("sepol: copy cls failed.\n"); pr_err("sepol: copy cls failed.\n");
goto exit; goto exit;
} }
if (strncpy_from_user(operation, ptr4, if (strncpy_from_user(operation, sepol4,
sizeof(operation)) < 0) { sizeof(operation)) < 0) {
pr_err("sepol: copy operation failed.\n"); pr_err("sepol: copy operation failed.\n");
goto exit; goto exit;
} }
if (strncpy_from_user(perm_set, ptr5, sizeof(perm_set)) < if (strncpy_from_user(perm_set, sepol5, sizeof(perm_set)) <
0) { 0) {
pr_err("sepol: copy perm_set failed.\n"); pr_err("sepol: copy perm_set failed.\n");
goto exit; goto exit;
@@ -330,7 +359,7 @@ int handle_sepolicy(unsigned long arg3, void __user *arg4)
} else if (cmd == CMD_TYPE_STATE) { } else if (cmd == CMD_TYPE_STATE) {
char src[MAX_SEPOL_LEN]; char src[MAX_SEPOL_LEN];
if (strncpy_from_user(src, ptr1, sizeof(src)) < 0) { if (strncpy_from_user(src, sepol1, sizeof(src)) < 0) {
pr_err("sepol: copy src failed.\n"); pr_err("sepol: copy src failed.\n");
goto exit; goto exit;
} }
@@ -350,11 +379,11 @@ int handle_sepolicy(unsigned long arg3, void __user *arg4)
char type[MAX_SEPOL_LEN]; char type[MAX_SEPOL_LEN];
char attr[MAX_SEPOL_LEN]; char attr[MAX_SEPOL_LEN];
if (strncpy_from_user(type, ptr1, sizeof(type)) < 0) { if (strncpy_from_user(type, sepol1, sizeof(type)) < 0) {
pr_err("sepol: copy type failed.\n"); pr_err("sepol: copy type failed.\n");
goto exit; goto exit;
} }
if (strncpy_from_user(attr, ptr2, sizeof(attr)) < 0) { if (strncpy_from_user(attr, sepol2, sizeof(attr)) < 0) {
pr_err("sepol: copy attr failed.\n"); pr_err("sepol: copy attr failed.\n");
goto exit; goto exit;
} }
@@ -374,7 +403,7 @@ int handle_sepolicy(unsigned long arg3, void __user *arg4)
} else if (cmd == CMD_ATTR) { } else if (cmd == CMD_ATTR) {
char attr[MAX_SEPOL_LEN]; char attr[MAX_SEPOL_LEN];
if (strncpy_from_user(attr, ptr1, sizeof(attr)) < 0) { if (strncpy_from_user(attr, sepol1, sizeof(attr)) < 0) {
pr_err("sepol: copy attr failed.\n"); pr_err("sepol: copy attr failed.\n");
goto exit; goto exit;
} }
@@ -391,28 +420,28 @@ int handle_sepolicy(unsigned long arg3, void __user *arg4)
char default_type[MAX_SEPOL_LEN]; char default_type[MAX_SEPOL_LEN];
char object[MAX_SEPOL_LEN]; char object[MAX_SEPOL_LEN];
if (strncpy_from_user(src, ptr1, sizeof(src)) < 0) { if (strncpy_from_user(src, sepol1, sizeof(src)) < 0) {
pr_err("sepol: copy src failed.\n"); pr_err("sepol: copy src failed.\n");
goto exit; goto exit;
} }
if (strncpy_from_user(tgt, ptr2, sizeof(tgt)) < 0) { if (strncpy_from_user(tgt, sepol2, sizeof(tgt)) < 0) {
pr_err("sepol: copy tgt failed.\n"); pr_err("sepol: copy tgt failed.\n");
goto exit; goto exit;
} }
if (strncpy_from_user(cls, ptr3, sizeof(cls)) < 0) { if (strncpy_from_user(cls, sepol3, sizeof(cls)) < 0) {
pr_err("sepol: copy cls failed.\n"); pr_err("sepol: copy cls failed.\n");
goto exit; goto exit;
} }
if (strncpy_from_user(default_type, ptr4, if (strncpy_from_user(default_type, sepol4,
sizeof(default_type)) < 0) { sizeof(default_type)) < 0) {
pr_err("sepol: copy default_type failed.\n"); pr_err("sepol: copy default_type failed.\n");
goto exit; goto exit;
} }
char *real_object; char *real_object;
if (ptr5 == NULL) { if (sepol5 == NULL) {
real_object = NULL; real_object = NULL;
} else { } else {
if (strncpy_from_user(object, ptr5, if (strncpy_from_user(object, sepol5,
sizeof(object)) < 0) { sizeof(object)) < 0) {
pr_err("sepol: copy object failed.\n"); pr_err("sepol: copy object failed.\n");
goto exit; goto exit;
@@ -431,19 +460,19 @@ int handle_sepolicy(unsigned long arg3, void __user *arg4)
char cls[MAX_SEPOL_LEN]; char cls[MAX_SEPOL_LEN];
char default_type[MAX_SEPOL_LEN]; char default_type[MAX_SEPOL_LEN];
if (strncpy_from_user(src, ptr1, sizeof(src)) < 0) { if (strncpy_from_user(src, sepol1, sizeof(src)) < 0) {
pr_err("sepol: copy src failed.\n"); pr_err("sepol: copy src failed.\n");
goto exit; goto exit;
} }
if (strncpy_from_user(tgt, ptr2, sizeof(tgt)) < 0) { if (strncpy_from_user(tgt, sepol2, sizeof(tgt)) < 0) {
pr_err("sepol: copy tgt failed.\n"); pr_err("sepol: copy tgt failed.\n");
goto exit; goto exit;
} }
if (strncpy_from_user(cls, ptr3, sizeof(cls)) < 0) { if (strncpy_from_user(cls, sepol3, sizeof(cls)) < 0) {
pr_err("sepol: copy cls failed.\n"); pr_err("sepol: copy cls failed.\n");
goto exit; goto exit;
} }
if (strncpy_from_user(default_type, ptr4, if (strncpy_from_user(default_type, sepol4,
sizeof(default_type)) < 0) { sizeof(default_type)) < 0) {
pr_err("sepol: copy default_type failed.\n"); pr_err("sepol: copy default_type failed.\n");
goto exit; goto exit;
@@ -464,15 +493,15 @@ int handle_sepolicy(unsigned long arg3, void __user *arg4)
char name[MAX_SEPOL_LEN]; char name[MAX_SEPOL_LEN];
char path[MAX_SEPOL_LEN]; char path[MAX_SEPOL_LEN];
char context[MAX_SEPOL_LEN]; char context[MAX_SEPOL_LEN];
if (strncpy_from_user(name, ptr1, sizeof(name)) < 0) { if (strncpy_from_user(name, sepol1, sizeof(name)) < 0) {
pr_err("sepol: copy name failed.\n"); pr_err("sepol: copy name failed.\n");
goto exit; goto exit;
} }
if (strncpy_from_user(path, ptr2, sizeof(path)) < 0) { if (strncpy_from_user(path, sepol2, sizeof(path)) < 0) {
pr_err("sepol: copy path failed.\n"); pr_err("sepol: copy path failed.\n");
goto exit; goto exit;
} }
if (strncpy_from_user(context, ptr3, sizeof(context)) < if (strncpy_from_user(context, sepol3, sizeof(context)) <
0) { 0) {
pr_err("sepol: copy context failed.\n"); pr_err("sepol: copy context failed.\n");
goto exit; goto exit;
@@ -495,4 +524,4 @@ exit:
reset_avc_cache(); reset_avc_cache();
return ret; return ret;
} }

View File

@@ -2,6 +2,9 @@
#include "objsec.h" #include "objsec.h"
#include "linux/version.h" #include "linux/version.h"
#include "../klog.h" // IWYU pragma: keep #include "../klog.h" // IWYU pragma: keep
#ifdef SAMSUNG_SELINUX_PORTING
#include "security.h" // Samsung SELinux Porting
#endif
#ifndef KSU_COMPAT_USE_SELINUX_STATE #ifndef KSU_COMPAT_USE_SELINUX_STATE
#include "avc.h" #include "avc.h"
#endif #endif
@@ -43,18 +46,14 @@ void setup_selinux(const char *domain)
pr_err("transive domain failed.\n"); pr_err("transive domain failed.\n");
return; return;
} }
/* we didn't need this now, we have change selinux rules when boot!
if (!is_domain_permissive) {
if (set_domain_permissive() == 0) {
is_domain_permissive = true;
}
}*/
} }
void setenforce(bool enforce) void setenforce(bool enforce)
{ {
#ifdef CONFIG_SECURITY_SELINUX_DEVELOP #ifdef CONFIG_SECURITY_SELINUX_DEVELOP
#ifdef SAMSUNG_SELINUX_PORTING
selinux_enforcing = enforce;
#endif
#ifdef KSU_COMPAT_USE_SELINUX_STATE #ifdef KSU_COMPAT_USE_SELINUX_STATE
selinux_state.enforcing = enforce; selinux_state.enforcing = enforce;
#else #else
@@ -76,6 +75,9 @@ bool getenforce()
#endif #endif
#ifdef CONFIG_SECURITY_SELINUX_DEVELOP #ifdef CONFIG_SECURITY_SELINUX_DEVELOP
#ifdef SAMSUNG_SELINUX_PORTING
return selinux_enforcing;
#endif
#ifdef KSU_COMPAT_USE_SELINUX_STATE #ifdef KSU_COMPAT_USE_SELINUX_STATE
return selinux_state.enforcing; return selinux_state.enforcing;
#else #else