fs: susfs: merge and cherry-pick commits from susfs v1.5.9 gki-android14-6.1 branch

bade6e818c
75cdd2eadb
3e62ef841c
This commit is contained in:
sidex15
2025-07-21 18:36:02 +08:00
committed by Onelots
parent 5dafb39428
commit c3f1cc07a7
7 changed files with 151 additions and 30 deletions

View File

@@ -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();

View File

@@ -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;

View File

@@ -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;
}

View File

@@ -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;

View File

@@ -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

View File

@@ -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:

View File

@@ -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(&current->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