fs: susfs: merge and cherry-pick commits from susfs v1.5.9 gki-android14-6.1 branch
bade6e818c75cdd2eadb3e62ef841c
This commit is contained in:
@@ -1618,6 +1618,7 @@ retry:
|
||||
#ifdef CONFIG_KSU_SUSFS_SUS_PATH
|
||||
{
|
||||
if (!found_sus_path && !IS_ERR(dentry) && dentry->d_inode && susfs_is_inode_sus_path(dentry->d_inode)) {
|
||||
dput(dentry);
|
||||
dentry = lookup_dcache(&susfs_fake_qstr_name, base, flags);
|
||||
found_sus_path = true;
|
||||
goto retry;
|
||||
@@ -1686,6 +1687,7 @@ static int lookup_fast(struct nameidata *nd,
|
||||
#ifdef CONFIG_KSU_SUSFS_SUS_PATH
|
||||
if (is_nd_state_lookup_last_and_open_last && dentry && !IS_ERR(dentry) && dentry->d_inode && parent->d_inode) {
|
||||
if (susfs_is_inode_sus_path(dentry->d_inode)) {
|
||||
dput(dentry);
|
||||
dentry = __d_lookup_rcu(parent, &susfs_fake_qstr_name, &backup_next_seq);
|
||||
}
|
||||
}
|
||||
@@ -1758,6 +1760,7 @@ skip_orig_flow1:
|
||||
#ifdef CONFIG_KSU_SUSFS_SUS_PATH
|
||||
if (is_nd_state_lookup_last_and_open_last && dentry && !IS_ERR(dentry) && dentry->d_inode && parent->d_inode) {
|
||||
if (susfs_is_inode_sus_path(dentry->d_inode)) {
|
||||
dput(dentry);
|
||||
dentry = __d_lookup(parent, &susfs_fake_qstr_name);
|
||||
}
|
||||
}
|
||||
@@ -1859,6 +1862,7 @@ retry:
|
||||
if (is_nd_flags_lookup_last && !found_sus_path) {
|
||||
if (dentry && !IS_ERR(dentry) && dentry->d_inode) {
|
||||
if (susfs_is_inode_sus_path(dentry->d_inode)) {
|
||||
dput(dentry);
|
||||
dentry = d_alloc_parallel(dir, &susfs_fake_qstr_name, &sus_wq);
|
||||
found_sus_path = true;
|
||||
goto retry;
|
||||
@@ -3386,6 +3390,7 @@ static int lookup_open(struct nameidata *nd, struct path *path,
|
||||
#ifdef CONFIG_KSU_SUSFS_SUS_PATH
|
||||
if (is_nd_state_open_last && dentry && !IS_ERR(dentry) && dentry->d_inode) {
|
||||
if (susfs_is_inode_sus_path(dentry->d_inode)) {
|
||||
dput(dentry);
|
||||
dentry = d_lookup(dir, &susfs_fake_qstr_name);
|
||||
found_sus_path = true;
|
||||
}
|
||||
@@ -3861,7 +3866,7 @@ struct file *do_filp_open(int dfd, struct filename *pathname,
|
||||
if (unlikely(filp == ERR_PTR(-ESTALE)))
|
||||
filp = path_openat(&nd, op, flags | LOOKUP_REVAL);
|
||||
#ifdef CONFIG_KSU_SUSFS_OPEN_REDIRECT
|
||||
if (!IS_ERR(filp) && unlikely(filp->f_inode->i_state & INODE_STATE_OPEN_REDIRECT) && current_uid().val < 11000) {
|
||||
if (!IS_ERR(filp) && unlikely(filp->f_inode->i_mapping->flags & BIT_OPEN_REDIRECT) && current_uid().val < 11000) {
|
||||
fake_pathname = susfs_get_redirected_path(filp->f_inode->i_ino);
|
||||
if (!IS_ERR(fake_pathname)) {
|
||||
restore_nameidata();
|
||||
|
||||
@@ -103,7 +103,7 @@ static void inotify_fdinfo(struct seq_file *m, struct fsnotify_mark *mark)
|
||||
if (inode) {
|
||||
#ifdef CONFIG_KSU_SUSFS_SUS_MOUNT
|
||||
if (likely(susfs_is_current_non_root_user_app_proc()) &&
|
||||
unlikely(inode->i_state & INODE_STATE_SUS_KSTAT)) {
|
||||
unlikely(inode->i_mapping->flags & BIT_SUS_KSTAT)) {
|
||||
struct path path;
|
||||
char *pathname = kmalloc(PAGE_SIZE, GFP_KERNEL);
|
||||
char *dpath;
|
||||
|
||||
@@ -370,7 +370,7 @@ show_map_vma(struct seq_file *m, struct vm_area_struct *vma, int is_pid)
|
||||
if (file) {
|
||||
struct inode *inode = file_inode(vma->vm_file);
|
||||
#ifdef CONFIG_KSU_SUSFS_SUS_KSTAT
|
||||
if (unlikely(inode->i_state & INODE_STATE_SUS_KSTAT)) {
|
||||
if (unlikely(inode->i_mapping->flags & BIT_SUS_KSTAT)) {
|
||||
susfs_sus_ino_for_show_map_vma(inode->i_ino, &dev, &ino);
|
||||
goto bypass_orig_flow;
|
||||
}
|
||||
|
||||
@@ -38,7 +38,7 @@ void generic_fillattr(struct inode *inode, struct kstat *stat)
|
||||
{
|
||||
#ifdef CONFIG_KSU_SUSFS_SUS_KSTAT
|
||||
if (likely(susfs_is_current_non_root_user_app_proc()) &&
|
||||
unlikely(inode->i_state & INODE_STATE_SUS_KSTAT)) {
|
||||
unlikely(inode->i_mapping->flags & BIT_SUS_KSTAT)) {
|
||||
susfs_sus_ino_for_generic_fillattr(inode->i_ino, stat);
|
||||
stat->mode = inode->i_mode;
|
||||
stat->rdev = inode->i_rdev;
|
||||
|
||||
@@ -237,7 +237,7 @@ int vfs_ustat(dev_t dev, struct kstatfs *sbuf)
|
||||
return -EINVAL;
|
||||
|
||||
#ifdef CONFIG_KSU_SUSFS_SUS_MOUNT
|
||||
if (unlikely(s->s_root->d_inode->i_state & INODE_STATE_SUS_MOUNT)) {
|
||||
if (unlikely(s->s_root->d_inode->i_mapping->flags & BIT_SUS_MOUNT)) {
|
||||
return -EINVAL;
|
||||
}
|
||||
#endif
|
||||
|
||||
144
fs/susfs.c
144
fs/susfs.c
@@ -35,6 +35,7 @@ bool susfs_is_log_enabled __read_mostly = true;
|
||||
|
||||
/* sus_path */
|
||||
#ifdef CONFIG_KSU_SUSFS_SUS_PATH
|
||||
static LIST_HEAD(LH_SUS_PATH_LOOP);
|
||||
static LIST_HEAD(LH_SUS_PATH_ANDROID_DATA);
|
||||
static LIST_HEAD(LH_SUS_PATH_SDCARD);
|
||||
static struct st_android_data_path android_data_path = {0};
|
||||
@@ -127,7 +128,7 @@ int susfs_add_sus_path(struct st_susfs_sus_path* __user user_info) {
|
||||
return err;
|
||||
}
|
||||
|
||||
err = kern_path(info.target_pathname, LOOKUP_FOLLOW, &path);
|
||||
err = kern_path(info.target_pathname, 0, &path);
|
||||
if (err) {
|
||||
SUSFS_LOGE("Failed opening file '%s'\n", info.target_pathname);
|
||||
return err;
|
||||
@@ -228,8 +229,8 @@ int susfs_add_sus_path(struct st_susfs_sus_path* __user user_info) {
|
||||
}
|
||||
|
||||
spin_lock(&inode->i_lock);
|
||||
inode->i_state |= INODE_STATE_SUS_PATH;
|
||||
SUSFS_LOGI("pathname: '%s', ino: '%lu', is flagged as INODE_STATE_SUS_PATH\n", resolved_pathname, info.target_ino);
|
||||
set_bit(AS_FLAGS_SUS_PATH, &inode->i_mapping->flags);
|
||||
SUSFS_LOGI("pathname: '%s', ino: '%lu', is flagged as AS_FLAGS_SUS_PATH\n", resolved_pathname, info.target_ino);
|
||||
spin_unlock(&inode->i_lock);
|
||||
out_kfree_tmp_buf:
|
||||
kfree(tmp_buf);
|
||||
@@ -238,6 +239,111 @@ out_path_put_path:
|
||||
return err;
|
||||
}
|
||||
|
||||
int susfs_add_sus_path_loop(struct st_susfs_sus_path* __user user_info) {
|
||||
struct st_susfs_sus_path_list *cursor = NULL, *temp = NULL;
|
||||
struct st_susfs_sus_path_list *new_list = NULL;
|
||||
struct st_susfs_sus_path info;
|
||||
struct path path;
|
||||
struct inode *inode = NULL;
|
||||
char *resolved_pathname = NULL, *tmp_buf = NULL;
|
||||
int err = 0;
|
||||
|
||||
err = copy_from_user(&info, user_info, sizeof(info));
|
||||
if (err) {
|
||||
SUSFS_LOGE("failed copying from userspace\n");
|
||||
return err;
|
||||
}
|
||||
|
||||
err = kern_path(info.target_pathname, 0, &path);
|
||||
if (err) {
|
||||
SUSFS_LOGE("Failed opening file '%s'\n", info.target_pathname);
|
||||
return err;
|
||||
}
|
||||
|
||||
if (!path.dentry->d_inode) {
|
||||
err = -EINVAL;
|
||||
goto out_path_put_path;
|
||||
}
|
||||
inode = d_inode(path.dentry);
|
||||
|
||||
tmp_buf = kmalloc(PAGE_SIZE, GFP_KERNEL);
|
||||
if (!tmp_buf) {
|
||||
err = -ENOMEM;
|
||||
goto out_path_put_path;
|
||||
}
|
||||
|
||||
resolved_pathname = d_path(&path, tmp_buf, PAGE_SIZE);
|
||||
SUSFS_LOGI("resolved_pathname: %s\n", resolved_pathname);
|
||||
if (!resolved_pathname) {
|
||||
err = -ENOMEM;
|
||||
goto out_kfree_tmp_buf;
|
||||
}
|
||||
|
||||
if (susfs_starts_with(resolved_pathname, "/storage/")) {
|
||||
err = -EINVAL;
|
||||
SUSFS_LOGE("path starts with /storage and /sdcard cannot be added by add_sus_path_loop\n");
|
||||
goto out_kfree_tmp_buf;
|
||||
}
|
||||
|
||||
list_for_each_entry_safe(cursor, temp, &LH_SUS_PATH_LOOP, list) {
|
||||
if (unlikely(!strcmp(cursor->info.target_pathname, resolved_pathname))) {
|
||||
spin_lock(&susfs_spin_lock);
|
||||
cursor->info.target_ino = info.target_ino;
|
||||
strncpy(cursor->info.target_pathname, resolved_pathname, SUSFS_MAX_LEN_PATHNAME - 1);
|
||||
strncpy(cursor->target_pathname, resolved_pathname, SUSFS_MAX_LEN_PATHNAME - 1);
|
||||
cursor->info.i_uid = info.i_uid;
|
||||
cursor->path_len = strlen(cursor->info.target_pathname);
|
||||
SUSFS_LOGI("target_ino: '%lu', target_pathname: '%s', i_uid: '%u', is successfully updated to LH_SUS_PATH_LOOP\n",
|
||||
cursor->info.target_ino, cursor->target_pathname, cursor->info.i_uid);
|
||||
spin_unlock(&susfs_spin_lock);
|
||||
goto out_set_sus_path;
|
||||
}
|
||||
}
|
||||
new_list = kmalloc(sizeof(struct st_susfs_sus_path_list), GFP_KERNEL);
|
||||
if (!new_list) {
|
||||
err = -ENOMEM;
|
||||
goto out_kfree_tmp_buf;
|
||||
}
|
||||
new_list->info.target_ino = info.target_ino;
|
||||
strncpy(new_list->info.target_pathname, resolved_pathname, SUSFS_MAX_LEN_PATHNAME - 1);
|
||||
strncpy(new_list->target_pathname, resolved_pathname, SUSFS_MAX_LEN_PATHNAME - 1);
|
||||
new_list->info.i_uid = info.i_uid;
|
||||
new_list->path_len = strlen(new_list->info.target_pathname);
|
||||
INIT_LIST_HEAD(&new_list->list);
|
||||
spin_lock(&susfs_spin_lock);
|
||||
list_add_tail(&new_list->list, &LH_SUS_PATH_LOOP);
|
||||
SUSFS_LOGI("target_ino: '%lu', target_pathname: '%s', i_uid: '%u', is successfully added to LH_SUS_PATH_LOOP\n",
|
||||
new_list->info.target_ino, new_list->target_pathname, new_list->info.i_uid);
|
||||
spin_unlock(&susfs_spin_lock);
|
||||
out_set_sus_path:
|
||||
spin_lock(&inode->i_lock);
|
||||
set_bit(AS_FLAGS_SUS_PATH, &inode->i_mapping->flags);
|
||||
SUSFS_LOGI("pathname: '%s', ino: '%lu', is flagged as AS_FLAGS_SUS_PATH\n", resolved_pathname, info.target_ino);
|
||||
spin_unlock(&inode->i_lock);
|
||||
out_kfree_tmp_buf:
|
||||
kfree(tmp_buf);
|
||||
out_path_put_path:
|
||||
path_put(&path);
|
||||
return err;
|
||||
}
|
||||
|
||||
void susfs_run_sus_path_loop(uid_t uid) {
|
||||
struct st_susfs_sus_path_list *cursor = NULL, *temp = NULL;
|
||||
struct path path;
|
||||
struct inode *inode;
|
||||
|
||||
list_for_each_entry_safe(cursor, temp, &LH_SUS_PATH_LOOP, list) {
|
||||
if (!kern_path(cursor->target_pathname, 0, &path)) {
|
||||
inode = path.dentry->d_inode;
|
||||
spin_lock(&inode->i_lock);
|
||||
set_bit(AS_FLAGS_SUS_PATH, &inode->i_mapping->flags);
|
||||
spin_unlock(&inode->i_lock);
|
||||
path_put(&path);
|
||||
SUSFS_LOGI("re-flag '%s' as SUS_PATH for uid: %u\n", cursor->target_pathname, uid);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static inline bool is_i_uid_in_android_data_not_allowed(uid_t i_uid) {
|
||||
return (likely(susfs_is_current_non_root_user_app_proc()) &&
|
||||
unlikely(current_uid().val != i_uid));
|
||||
@@ -302,7 +408,7 @@ bool susfs_is_sus_sdcard_d_name_found(const char *d_name) {
|
||||
|
||||
#if LINUX_VERSION_CODE >= KERNEL_VERSION(6, 6, 0)
|
||||
bool susfs_is_inode_sus_path(struct mnt_idmap* idmap, struct inode *inode) {
|
||||
if (unlikely(inode->i_state & INODE_STATE_SUS_PATH &&
|
||||
if (unlikely(inode->i_mapping->flags & BIT_SUS_PATH &&
|
||||
is_i_uid_not_allowed(i_uid_into_vfsuid(idmap, inode).val)))
|
||||
{
|
||||
SUSFS_LOGI("hiding path with ino '%lu'\n", inode->i_ino);
|
||||
@@ -312,7 +418,7 @@ bool susfs_is_inode_sus_path(struct mnt_idmap* idmap, struct inode *inode) {
|
||||
}
|
||||
#elif LINUX_VERSION_CODE >= KERNEL_VERSION(5, 15, 0)
|
||||
bool susfs_is_inode_sus_path(struct inode *inode) {
|
||||
if (unlikely(inode->i_state & INODE_STATE_SUS_PATH &&
|
||||
if (unlikely(inode->i_mapping->flags & BIT_SUS_PATH &&
|
||||
is_i_uid_not_allowed(i_uid_into_mnt(i_user_ns(inode), inode).val)))
|
||||
{
|
||||
SUSFS_LOGI("hiding path with ino '%lu'\n", inode->i_ino);
|
||||
@@ -322,7 +428,7 @@ bool susfs_is_inode_sus_path(struct inode *inode) {
|
||||
}
|
||||
#else
|
||||
bool susfs_is_inode_sus_path(struct inode *inode) {
|
||||
if (unlikely(inode->i_state & INODE_STATE_SUS_PATH &&
|
||||
if (unlikely(inode->i_mapping->flags & BIT_SUS_PATH &&
|
||||
is_i_uid_not_allowed(inode->i_uid.val)))
|
||||
{
|
||||
SUSFS_LOGI("hiding path with ino '%lu'\n", inode->i_ino);
|
||||
@@ -352,7 +458,7 @@ static void susfs_update_sus_mount_inode(char *target_pathname) {
|
||||
/* It is important to check if the mount has a legit peer group id, if so we cannot add them to sus_mount,
|
||||
* since there are chances that the mount is a legit mountpoint, and it can be misued by other susfs functions in future.
|
||||
* And by doing this it won't affect the sus_mount check as other susfs functions check by mnt->mnt_id
|
||||
* instead of INODE_STATE_SUS_MOUNT.
|
||||
* instead of BIT_SUS_MOUNT.
|
||||
*/
|
||||
mnt = real_mount(p.mnt);
|
||||
if (mnt->mnt_group_id > 0 && // 0 means no peer group
|
||||
@@ -368,9 +474,9 @@ static void susfs_update_sus_mount_inode(char *target_pathname) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (!(inode->i_state & INODE_STATE_SUS_MOUNT)) {
|
||||
if (!(inode->i_mapping->flags & BIT_SUS_MOUNT)) {
|
||||
spin_lock(&inode->i_lock);
|
||||
inode->i_state |= INODE_STATE_SUS_MOUNT;
|
||||
set_bit(AS_FLAGS_SUS_MOUNT, &inode->i_mapping->flags);
|
||||
spin_unlock(&inode->i_lock);
|
||||
}
|
||||
path_put(&p);
|
||||
@@ -440,9 +546,9 @@ int susfs_auto_add_sus_bind_mount(const char *pathname, struct path *path_target
|
||||
}
|
||||
inode = path_target->dentry->d_inode;
|
||||
if (!inode) return 1;
|
||||
if (!(inode->i_state & INODE_STATE_SUS_MOUNT)) {
|
||||
if (!(inode->i_mapping->flags & BIT_SUS_MOUNT)) {
|
||||
spin_lock(&inode->i_lock);
|
||||
inode->i_state |= INODE_STATE_SUS_MOUNT;
|
||||
set_bit(AS_FLAGS_SUS_MOUNT, &inode->i_mapping->flags);
|
||||
spin_unlock(&inode->i_lock);
|
||||
SUSFS_LOGI("set SUS_MOUNT inode state for source bind mount path '%s'\n", pathname);
|
||||
}
|
||||
@@ -484,9 +590,9 @@ set_inode_sus_mount:
|
||||
goto out_path_put;
|
||||
return;
|
||||
}
|
||||
if (!(inode->i_state & INODE_STATE_SUS_MOUNT)) {
|
||||
if (!(inode->i_mapping->flags & BIT_SUS_MOUNT)) {
|
||||
spin_lock(&inode->i_lock);
|
||||
inode->i_state |= INODE_STATE_SUS_MOUNT;
|
||||
set_bit(AS_FLAGS_SUS_MOUNT, &inode->i_mapping->flags);
|
||||
spin_unlock(&inode->i_lock);
|
||||
SUSFS_LOGI("set SUS_MOUNT inode state for default KSU mount path '%s'\n", pathname);
|
||||
}
|
||||
@@ -506,7 +612,7 @@ static int susfs_update_sus_kstat_inode(char *target_pathname) {
|
||||
struct inode *inode = NULL;
|
||||
int err = 0;
|
||||
|
||||
err = kern_path(target_pathname, LOOKUP_FOLLOW, &p);
|
||||
err = kern_path(target_pathname, 0, &p);
|
||||
if (err) {
|
||||
SUSFS_LOGE("Failed opening file '%s'\n", target_pathname);
|
||||
return 1;
|
||||
@@ -519,9 +625,9 @@ static int susfs_update_sus_kstat_inode(char *target_pathname) {
|
||||
return 1;
|
||||
}
|
||||
|
||||
if (!(inode->i_state & INODE_STATE_SUS_KSTAT)) {
|
||||
if (!(inode->i_mapping->flags & BIT_SUS_KSTAT)) {
|
||||
spin_lock(&inode->i_lock);
|
||||
inode->i_state |= INODE_STATE_SUS_KSTAT;
|
||||
set_bit(AS_FLAGS_SUS_KSTAT, &inode->i_mapping->flags);
|
||||
spin_unlock(&inode->i_lock);
|
||||
}
|
||||
path_put(&p);
|
||||
@@ -771,8 +877,8 @@ void susfs_auto_add_try_umount_for_bind_mount(struct path *path) {
|
||||
#endif
|
||||
|
||||
#ifdef CONFIG_KSU_SUSFS_SUS_KSTAT
|
||||
if (path->dentry->d_inode->i_state & INODE_STATE_SUS_KSTAT) {
|
||||
SUSFS_LOGI("skip adding path to try_umount list as its inode is flagged INODE_STATE_SUS_KSTAT already\n");
|
||||
if (path->dentry->d_inode->i_mapping->flags & BIT_SUS_KSTAT) {
|
||||
SUSFS_LOGI("skip adding path to try_umount list as its inode is flagged BIT_SUS_KSTAT already\n");
|
||||
return;
|
||||
}
|
||||
#endif
|
||||
@@ -958,7 +1064,7 @@ static int susfs_update_open_redirect_inode(struct st_susfs_open_redirect_hlist
|
||||
}
|
||||
|
||||
spin_lock(&inode_target->i_lock);
|
||||
inode_target->i_state |= INODE_STATE_OPEN_REDIRECT;
|
||||
set_bit(AS_FLAGS_OPEN_REDIRECT, &inode_target->i_mapping->flags);
|
||||
spin_unlock(&inode_target->i_lock);
|
||||
|
||||
out_path_put_target:
|
||||
|
||||
@@ -10,6 +10,7 @@
|
||||
#define CMD_SUSFS_ADD_SUS_PATH 0x55550
|
||||
#define CMD_SUSFS_SET_ANDROID_DATA_ROOT_PATH 0x55551
|
||||
#define CMD_SUSFS_SET_SDCARD_ROOT_PATH 0x55552
|
||||
#define CMD_SUSFS_ADD_SUS_PATH_LOOP 0x55553
|
||||
#define CMD_SUSFS_ADD_SUS_MOUNT 0x55560
|
||||
#define CMD_SUSFS_HIDE_SUS_MNTS_FOR_ALL_PROCS 0x55561
|
||||
#define CMD_SUSFS_UMOUNT_FOR_ZYGOTE_ISO_SERVICE 0x55562
|
||||
@@ -44,24 +45,26 @@
|
||||
#define DEFAULT_SUS_MNT_GROUP_ID 1000 /* used by mount->mnt_group_id */
|
||||
|
||||
/*
|
||||
* inode->i_state => storing flag 'INODE_STATE_'
|
||||
* mount->mnt.susfs_mnt_id_backup => storing original mnt_id of normal mounts or custom sus mnt_id of sus mounts
|
||||
* inode->i_mapping->flags => storing flag 'AS_FLAGS_'
|
||||
* nd->state => storing flag 'ND_STATE_'
|
||||
* nd->flags => storing flag 'ND_FLAGS_'
|
||||
* task_struct->thread_info.flags => storing flag 'TIF_'
|
||||
*/
|
||||
#define INODE_STATE_SUS_PATH BIT(24)
|
||||
#define INODE_STATE_SUS_MOUNT BIT(25)
|
||||
#define INODE_STATE_SUS_KSTAT BIT(26)
|
||||
#define INODE_STATE_OPEN_REDIRECT BIT(27)
|
||||
|
||||
// thread_info->flags is unsigned long :D
|
||||
#define TIF_NON_ROOT_USER_APP_PROC 33
|
||||
#define TIF_PROC_SU_NOT_ALLOWED 34
|
||||
|
||||
#define AS_FLAGS_SUS_PATH 24
|
||||
#define AS_FLAGS_SUS_MOUNT 25
|
||||
#define AS_FLAGS_SUS_KSTAT 26
|
||||
#define AS_FLAGS_OPEN_REDIRECT 27
|
||||
#define AS_FLAGS_ANDROID_DATA_ROOT_DIR 28
|
||||
#define AS_FLAGS_SDCARD_ROOT_DIR 29
|
||||
#define BIT_SUS_PATH BIT(24)
|
||||
#define BIT_SUS_MOUNT BIT(25)
|
||||
#define BIT_SUS_KSTAT BIT(26)
|
||||
#define BIT_OPEN_REDIRECT BIT(27)
|
||||
#define BIT_ANDROID_DATA_ROOT_DIR BIT(28)
|
||||
#define BIT_ANDROID_SDCARD_ROOT_DIR BIT(29)
|
||||
|
||||
@@ -92,4 +95,11 @@ static inline void susfs_set_current_proc_su_not_allowed(void) {
|
||||
set_ti_thread_flag(¤t->thread_info, TIF_PROC_SU_NOT_ALLOWED);
|
||||
}
|
||||
|
||||
static inline bool susfs_starts_with(const char *str, const char *prefix) {
|
||||
while (*prefix) {
|
||||
if (*str++ != *prefix++)
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
#endif // #ifndef KSU_SUSFS_DEF_H
|
||||
|
||||
Reference in New Issue
Block a user