fs: implement susfs v1.5.12
- This is a heavily modified version of susfs v1.5.12
- It does not comply with the upstream offical susfs v1.5.12
- sus_mount functionality still remain in v1.5.5 as backporting it to the latest version will result a mount detection leak in some apps/detectors
- Increase susfs_open_redirect UID limit to <11000
- susfs magic mount support is still implemented and enabled
- sus_map is implemented and complied with the upstream v1.5.12 codebase
This commit requires a bunch of backports commits from v4.19 and v5.x to make sus_map working:
0a8cbf3725edbacc5f1ead33eeae7e4d78823b5a proc: less memory for /proc/*/map_files readdir
37ae2444584654f6785f2cc49181f05af788c9b2 mm: smaps: split PSS into components
49a5115e11350ee68f6a5fbd56b3e817bf9e5aac fs/task_mmu: add pkeys header
6f94042bed51121f8f28a5e572cda20c21fed2e1 mm/pkeys: Add an empty arch_pkeys_enabled()
bbd5aec12b32097a71dc6a0097194a18f3ee9a17 mm/pkeys, powerpc, x86: Provide an empty vma_pkey() in linux/pkeys.h
849ca8ce954d9dbb082dcf83c98af861e98e5635 mm: /proc/pid/smaps_rollup: convert to single value seq_file
6071a482c8e603be25895cc2cac5f0eab61c4051 mm: /proc/pid/smaps: factor out common stats printing
03fd2fbe9c40da8128cec5c69ef54755c0f38c6c mm: /proc/pid/smaps: factor out mem stats gathering
95f8be4c8a86a491a1c2ac9bfe470aef9e1baa8f mm: /proc/pid/*maps remove is_pid and related wrappers
27956d255e3b012372951dd6131e07c106d2daae procfs: add seq_put_hex_ll to speed up /proc/pid/maps
7f2847d02cdc4491b5ee6d4a0043854cbd6c7a1a proc: add seq_put_decimal_ull_width to speed up /proc/pid/smaps
For KernelSU side patches for this commit you need the sidex15's KernelSU-Next fork:
https://github.com/sidex15/KernelSU-Next/tree/n3x7g3n-kernel
Or if you want to patch on your own here's the commit patch of susfs in the KernelSU-Next:
13b1dfd6e2
Co-authored-by: simonpunk <simonpunk2016@gmail.com>
Signed-off-by: Pranav Vashi <neobuddy89@gmail.com>
This commit is contained in:
@@ -14,6 +14,8 @@ obj-y := open.o read_write.o file_table.o super.o \
|
|||||||
pnode.o splice.o sync.o utimes.o \
|
pnode.o splice.o sync.o utimes.o \
|
||||||
stack.o fs_struct.o statfs.o fs_pin.o nsfs.o
|
stack.o fs_struct.o statfs.o fs_pin.o nsfs.o
|
||||||
|
|
||||||
|
obj-$(CONFIG_KSU_SUSFS) += susfs.o
|
||||||
|
|
||||||
ifeq ($(CONFIG_BLOCK),y)
|
ifeq ($(CONFIG_BLOCK),y)
|
||||||
obj-y += buffer.o block_dev.o direct-io.o mpage.o
|
obj-y += buffer.o block_dev.o direct-io.o mpage.o
|
||||||
else
|
else
|
||||||
|
|||||||
262
fs/namei.c
262
fs/namei.c
@@ -39,6 +39,9 @@
|
|||||||
#include <linux/bitops.h>
|
#include <linux/bitops.h>
|
||||||
#include <linux/init_task.h>
|
#include <linux/init_task.h>
|
||||||
#include <linux/uaccess.h>
|
#include <linux/uaccess.h>
|
||||||
|
#if defined(CONFIG_KSU_SUSFS_SUS_PATH) || defined(CONFIG_KSU_SUSFS_OPEN_REDIRECT)
|
||||||
|
#include <linux/susfs_def.h>
|
||||||
|
#endif
|
||||||
|
|
||||||
#include "internal.h"
|
#include "internal.h"
|
||||||
#include "mount.h"
|
#include "mount.h"
|
||||||
@@ -46,6 +49,15 @@
|
|||||||
#define CREATE_TRACE_POINTS
|
#define CREATE_TRACE_POINTS
|
||||||
#include <trace/events/namei.h>
|
#include <trace/events/namei.h>
|
||||||
|
|
||||||
|
#ifdef CONFIG_KSU_SUSFS_SUS_PATH
|
||||||
|
extern bool susfs_is_sus_android_data_d_name_found(const char *d_name);
|
||||||
|
extern bool susfs_is_sus_sdcard_d_name_found(const char *d_name);
|
||||||
|
extern bool susfs_is_inode_sus_path(struct inode *inode);
|
||||||
|
extern bool susfs_is_base_dentry_android_data_dir(struct dentry* base);
|
||||||
|
extern bool susfs_is_base_dentry_sdcard_dir(struct dentry* base);
|
||||||
|
extern const struct qstr susfs_fake_qstr_name;
|
||||||
|
#endif
|
||||||
|
|
||||||
/* [Feb-1997 T. Schoebel-Theuer]
|
/* [Feb-1997 T. Schoebel-Theuer]
|
||||||
* Fundamental changes in the pathname lookup mechanisms (namei)
|
* Fundamental changes in the pathname lookup mechanisms (namei)
|
||||||
* were necessary because of omirr. The reason is that omirr needs
|
* were necessary because of omirr. The reason is that omirr needs
|
||||||
@@ -528,6 +540,9 @@ struct nameidata {
|
|||||||
struct path root;
|
struct path root;
|
||||||
struct inode *inode; /* path.dentry.d_inode */
|
struct inode *inode; /* path.dentry.d_inode */
|
||||||
unsigned int flags;
|
unsigned int flags;
|
||||||
|
#ifdef CONFIG_KSU_SUSFS_SUS_PATH
|
||||||
|
unsigned int state;
|
||||||
|
#endif
|
||||||
unsigned seq, m_seq;
|
unsigned seq, m_seq;
|
||||||
int last_type;
|
int last_type;
|
||||||
unsigned depth;
|
unsigned depth;
|
||||||
@@ -554,6 +569,9 @@ static void set_nameidata(struct nameidata *p, int dfd, struct filename *name)
|
|||||||
p->total_link_count = old ? old->total_link_count : 0;
|
p->total_link_count = old ? old->total_link_count : 0;
|
||||||
p->saved = old;
|
p->saved = old;
|
||||||
current->nameidata = p;
|
current->nameidata = p;
|
||||||
|
#ifdef CONFIG_KSU_SUSFS_SUS_PATH
|
||||||
|
p->state = 0;
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
static void restore_nameidata(void)
|
static void restore_nameidata(void)
|
||||||
@@ -1662,18 +1680,63 @@ static struct dentry *lookup_real(struct inode *dir, struct dentry *dentry,
|
|||||||
static struct dentry *__lookup_hash(const struct qstr *name,
|
static struct dentry *__lookup_hash(const struct qstr *name,
|
||||||
struct dentry *base, unsigned int flags)
|
struct dentry *base, unsigned int flags)
|
||||||
{
|
{
|
||||||
|
#ifdef CONFIG_KSU_SUSFS_SUS_PATH
|
||||||
|
struct dentry *dentry;
|
||||||
|
bool found_sus_path = false;
|
||||||
|
|
||||||
|
if (base && base->d_inode && !found_sus_path) {
|
||||||
|
if (susfs_is_base_dentry_android_data_dir(base) &&
|
||||||
|
susfs_is_sus_android_data_d_name_found(name->name))
|
||||||
|
{
|
||||||
|
dentry = lookup_dcache(&susfs_fake_qstr_name, base, flags);
|
||||||
|
found_sus_path = true;
|
||||||
|
goto retry;
|
||||||
|
} else if (susfs_is_base_dentry_sdcard_dir(base) &&
|
||||||
|
susfs_is_sus_sdcard_d_name_found(name->name))
|
||||||
|
{
|
||||||
|
dentry = lookup_dcache(&susfs_fake_qstr_name, base, flags);
|
||||||
|
found_sus_path = true;
|
||||||
|
goto retry;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
dentry = lookup_dcache(name, base, flags);
|
||||||
|
retry:
|
||||||
|
#else
|
||||||
struct dentry *dentry = lookup_dcache(name, base, flags);
|
struct dentry *dentry = lookup_dcache(name, base, flags);
|
||||||
|
#endif
|
||||||
|
|
||||||
if (dentry)
|
if (dentry)
|
||||||
|
#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;
|
||||||
|
}
|
||||||
return dentry;
|
return dentry;
|
||||||
|
}
|
||||||
|
#else
|
||||||
|
return dentry;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifdef CONFIG_KSU_SUSFS_SUS_PATH
|
||||||
|
if (found_sus_path) {
|
||||||
|
dentry = d_alloc(base, &susfs_fake_qstr_name);
|
||||||
|
goto skip_orig_flow;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
dentry = d_alloc(base, name);
|
dentry = d_alloc(base, name);
|
||||||
|
#ifdef CONFIG_KSU_SUSFS_SUS_PATH
|
||||||
|
skip_orig_flow:
|
||||||
|
#endif
|
||||||
if (unlikely(!dentry))
|
if (unlikely(!dentry))
|
||||||
return ERR_PTR(-ENOMEM);
|
return ERR_PTR(-ENOMEM);
|
||||||
|
|
||||||
return lookup_real(base->d_inode, dentry, flags);
|
return lookup_real(base->d_inode, dentry, flags);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
static int lookup_fast(struct nameidata *nd,
|
static int lookup_fast(struct nameidata *nd,
|
||||||
struct path *path, struct inode **inode,
|
struct path *path, struct inode **inode,
|
||||||
unsigned *seqp)
|
unsigned *seqp)
|
||||||
@@ -1682,6 +1745,9 @@ static int lookup_fast(struct nameidata *nd,
|
|||||||
struct dentry *dentry, *parent = nd->path.dentry;
|
struct dentry *dentry, *parent = nd->path.dentry;
|
||||||
int status = 1;
|
int status = 1;
|
||||||
int err;
|
int err;
|
||||||
|
#ifdef CONFIG_KSU_SUSFS_SUS_PATH
|
||||||
|
bool is_nd_state_lookup_last_and_open_last = (nd->state & ND_STATE_LOOKUP_LAST || nd->state & ND_STATE_OPEN_LAST);
|
||||||
|
#endif
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Rename seqlock is not required here because in the off chance
|
* Rename seqlock is not required here because in the off chance
|
||||||
@@ -1691,7 +1757,33 @@ static int lookup_fast(struct nameidata *nd,
|
|||||||
if (nd->flags & LOOKUP_RCU) {
|
if (nd->flags & LOOKUP_RCU) {
|
||||||
unsigned seq;
|
unsigned seq;
|
||||||
bool negative;
|
bool negative;
|
||||||
|
#ifdef CONFIG_KSU_SUSFS_SUS_PATH
|
||||||
|
unsigned backup_next_seq;
|
||||||
|
|
||||||
|
if (is_nd_state_lookup_last_and_open_last && parent->d_inode) {
|
||||||
|
if (susfs_is_base_dentry_android_data_dir(parent) &&
|
||||||
|
susfs_is_sus_android_data_d_name_found(nd->last.name))
|
||||||
|
{
|
||||||
|
dentry = __d_lookup_rcu(parent, &susfs_fake_qstr_name, &seq);
|
||||||
|
goto skip_orig_flow1;
|
||||||
|
} else if (susfs_is_base_dentry_sdcard_dir(parent) &&
|
||||||
|
susfs_is_sus_sdcard_d_name_found(nd->last.name))
|
||||||
|
{
|
||||||
|
dentry = __d_lookup_rcu(parent, &susfs_fake_qstr_name, &seq);
|
||||||
|
goto skip_orig_flow1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#endif
|
||||||
dentry = __d_lookup_rcu(parent, &nd->last, &seq);
|
dentry = __d_lookup_rcu(parent, &nd->last, &seq);
|
||||||
|
#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);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
skip_orig_flow1:
|
||||||
|
#endif
|
||||||
if (unlikely(!dentry)) {
|
if (unlikely(!dentry)) {
|
||||||
if (unlazy_walk(nd))
|
if (unlazy_walk(nd))
|
||||||
return -ECHILD;
|
return -ECHILD;
|
||||||
@@ -1737,7 +1829,31 @@ static int lookup_fast(struct nameidata *nd,
|
|||||||
/* we'd been told to redo it in non-rcu mode */
|
/* we'd been told to redo it in non-rcu mode */
|
||||||
status = d_revalidate(dentry, nd->flags);
|
status = d_revalidate(dentry, nd->flags);
|
||||||
} else {
|
} else {
|
||||||
|
#ifdef CONFIG_KSU_SUSFS_SUS_PATH
|
||||||
|
if (is_nd_state_lookup_last_and_open_last && parent->d_inode) {
|
||||||
|
if (susfs_is_base_dentry_android_data_dir(parent) &&
|
||||||
|
susfs_is_sus_android_data_d_name_found(nd->last.name))
|
||||||
|
{
|
||||||
|
dentry = __d_lookup(parent, &susfs_fake_qstr_name);
|
||||||
|
goto skip_orig_flow2;
|
||||||
|
} else if (susfs_is_base_dentry_sdcard_dir(parent) &&
|
||||||
|
susfs_is_sus_sdcard_d_name_found(nd->last.name))
|
||||||
|
{
|
||||||
|
dentry = __d_lookup(parent, &susfs_fake_qstr_name);
|
||||||
|
goto skip_orig_flow2;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#endif
|
||||||
dentry = __d_lookup(parent, &nd->last);
|
dentry = __d_lookup(parent, &nd->last);
|
||||||
|
#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);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
skip_orig_flow2:
|
||||||
|
#endif
|
||||||
if (unlikely(!dentry))
|
if (unlikely(!dentry))
|
||||||
return 0;
|
return 0;
|
||||||
status = d_revalidate(dentry, nd->flags);
|
status = d_revalidate(dentry, nd->flags);
|
||||||
@@ -1769,13 +1885,42 @@ static struct dentry *lookup_slow(const struct qstr *name,
|
|||||||
struct dentry *dentry = ERR_PTR(-ENOENT), *old;
|
struct dentry *dentry = ERR_PTR(-ENOENT), *old;
|
||||||
struct inode *inode = dir->d_inode;
|
struct inode *inode = dir->d_inode;
|
||||||
DECLARE_WAIT_QUEUE_HEAD_ONSTACK(wq);
|
DECLARE_WAIT_QUEUE_HEAD_ONSTACK(wq);
|
||||||
|
#ifdef CONFIG_KSU_SUSFS_SUS_PATH
|
||||||
|
DECLARE_WAIT_QUEUE_HEAD_ONSTACK(sus_wq);
|
||||||
|
bool found_sus_path = false;
|
||||||
|
bool is_nd_flags_lookup_last = (flags & ND_FLAGS_LOOKUP_LAST);
|
||||||
|
#endif
|
||||||
|
|
||||||
inode_lock_shared(inode);
|
inode_lock_shared(inode);
|
||||||
/* Don't go there if it's already dead */
|
/* Don't go there if it's already dead */
|
||||||
if (unlikely(IS_DEADDIR(inode)))
|
if (unlikely(IS_DEADDIR(inode)))
|
||||||
goto out;
|
goto out;
|
||||||
again:
|
again:
|
||||||
|
#ifdef CONFIG_KSU_SUSFS_SUS_PATH
|
||||||
|
if (found_sus_path) {
|
||||||
|
dentry = d_alloc_parallel(dir, &susfs_fake_qstr_name, &sus_wq);
|
||||||
|
goto retry;
|
||||||
|
}
|
||||||
|
if (is_nd_flags_lookup_last && !found_sus_path) {
|
||||||
|
if (susfs_is_base_dentry_android_data_dir(dir) &&
|
||||||
|
susfs_is_sus_android_data_d_name_found(name->name))
|
||||||
|
{
|
||||||
|
dentry = d_alloc_parallel(dir, &susfs_fake_qstr_name, &sus_wq);
|
||||||
|
found_sus_path = true;
|
||||||
|
goto retry;
|
||||||
|
} else if (susfs_is_base_dentry_sdcard_dir(dir) &&
|
||||||
|
susfs_is_sus_sdcard_d_name_found(name->name))
|
||||||
|
{
|
||||||
|
dentry = d_alloc_parallel(dir, &susfs_fake_qstr_name, &sus_wq);
|
||||||
|
found_sus_path = true;
|
||||||
|
goto retry;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#endif
|
||||||
dentry = d_alloc_parallel(dir, name, &wq);
|
dentry = d_alloc_parallel(dir, name, &wq);
|
||||||
|
#ifdef CONFIG_KSU_SUSFS_SUS_PATH
|
||||||
|
retry:
|
||||||
|
#endif
|
||||||
if (IS_ERR(dentry))
|
if (IS_ERR(dentry))
|
||||||
goto out;
|
goto out;
|
||||||
if (unlikely(!d_in_lookup(dentry))) {
|
if (unlikely(!d_in_lookup(dentry))) {
|
||||||
@@ -1799,6 +1944,18 @@ again:
|
|||||||
dentry = old;
|
dentry = old;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
#ifdef CONFIG_KSU_SUSFS_SUS_PATH
|
||||||
|
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;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#endif
|
||||||
out:
|
out:
|
||||||
inode_unlock_shared(inode);
|
inode_unlock_shared(inode);
|
||||||
return dentry;
|
return dentry;
|
||||||
@@ -1921,6 +2078,11 @@ static int walk_component(struct nameidata *nd, int flags)
|
|||||||
if (unlikely(err <= 0)) {
|
if (unlikely(err <= 0)) {
|
||||||
if (err < 0)
|
if (err < 0)
|
||||||
return err;
|
return err;
|
||||||
|
#ifdef CONFIG_KSU_SUSFS_SUS_PATH
|
||||||
|
if (nd->state & ND_STATE_LOOKUP_LAST) {
|
||||||
|
nd->flags |= ND_FLAGS_LOOKUP_LAST;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
path.dentry = lookup_slow(&nd->last, nd->path.dentry,
|
path.dentry = lookup_slow(&nd->last, nd->path.dentry,
|
||||||
nd->flags);
|
nd->flags);
|
||||||
if (IS_ERR(path.dentry))
|
if (IS_ERR(path.dentry))
|
||||||
@@ -2192,10 +2354,20 @@ static int link_path_walk(const char *name, struct nameidata *nd)
|
|||||||
for(;;) {
|
for(;;) {
|
||||||
u64 hash_len;
|
u64 hash_len;
|
||||||
int type;
|
int type;
|
||||||
|
#ifdef CONFIG_KSU_SUSFS_SUS_PATH
|
||||||
|
struct dentry *dentry;
|
||||||
|
#endif
|
||||||
|
|
||||||
err = may_lookup(nd);
|
err = may_lookup(nd);
|
||||||
if (err)
|
if (err)
|
||||||
return err;
|
return err;
|
||||||
|
#ifdef CONFIG_KSU_SUSFS_SUS_PATH
|
||||||
|
dentry = nd->path.dentry;
|
||||||
|
if (dentry->d_inode && susfs_is_inode_sus_path(dentry->d_inode)) {
|
||||||
|
// return -ENOENT here since it is walking the sub path of sus path
|
||||||
|
return -ENOENT;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
hash_len = hash_name(nd->path.dentry, name);
|
hash_len = hash_name(nd->path.dentry, name);
|
||||||
|
|
||||||
@@ -2221,6 +2393,23 @@ static int link_path_walk(const char *name, struct nameidata *nd)
|
|||||||
hash_len = this.hash_len;
|
hash_len = this.hash_len;
|
||||||
name = this.name;
|
name = this.name;
|
||||||
}
|
}
|
||||||
|
#ifdef CONFIG_KSU_SUSFS_SUS_PATH
|
||||||
|
if (nd->state & ND_STATE_LAST_SDCARD_SUS_PATH) {
|
||||||
|
// return -ENOENT here since it is walking the sub path of sus sdcard path
|
||||||
|
return -ENOENT;
|
||||||
|
}
|
||||||
|
if (parent->d_inode) {
|
||||||
|
if (susfs_is_base_dentry_android_data_dir(parent) &&
|
||||||
|
susfs_is_sus_android_data_d_name_found(name))
|
||||||
|
{
|
||||||
|
nd->state |= ND_STATE_LAST_SDCARD_SUS_PATH;
|
||||||
|
} else if (susfs_is_base_dentry_sdcard_dir(parent) &&
|
||||||
|
susfs_is_sus_sdcard_d_name_found(name))
|
||||||
|
{
|
||||||
|
nd->state |= ND_STATE_LAST_SDCARD_SUS_PATH;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
nd->last.hash_len = hash_len;
|
nd->last.hash_len = hash_len;
|
||||||
@@ -2387,7 +2576,9 @@ static inline int lookup_last(struct nameidata *nd)
|
|||||||
{
|
{
|
||||||
if (nd->last_type == LAST_NORM && nd->last.name[nd->last.len])
|
if (nd->last_type == LAST_NORM && nd->last.name[nd->last.len])
|
||||||
nd->flags |= LOOKUP_FOLLOW | LOOKUP_DIRECTORY;
|
nd->flags |= LOOKUP_FOLLOW | LOOKUP_DIRECTORY;
|
||||||
|
#ifdef CONFIG_KSU_SUSFS_SUS_PATH
|
||||||
|
nd->state |= ND_STATE_LOOKUP_LAST;
|
||||||
|
#endif
|
||||||
nd->flags &= ~LOOKUP_PARENT;
|
nd->flags &= ~LOOKUP_PARENT;
|
||||||
return walk_component(nd, 0);
|
return walk_component(nd, 0);
|
||||||
}
|
}
|
||||||
@@ -3278,15 +3469,55 @@ static int lookup_open(struct nameidata *nd, struct path *path,
|
|||||||
int error, create_error = 0;
|
int error, create_error = 0;
|
||||||
umode_t mode = op->mode;
|
umode_t mode = op->mode;
|
||||||
DECLARE_WAIT_QUEUE_HEAD_ONSTACK(wq);
|
DECLARE_WAIT_QUEUE_HEAD_ONSTACK(wq);
|
||||||
|
#ifdef CONFIG_KSU_SUSFS_SUS_PATH
|
||||||
|
bool found_sus_path = false;
|
||||||
|
bool is_nd_state_open_last = (nd->state & ND_STATE_OPEN_LAST);
|
||||||
|
#endif
|
||||||
|
|
||||||
if (unlikely(IS_DEADDIR(dir_inode)))
|
if (unlikely(IS_DEADDIR(dir_inode)))
|
||||||
return -ENOENT;
|
return -ENOENT;
|
||||||
|
|
||||||
*opened &= ~FILE_CREATED;
|
*opened &= ~FILE_CREATED;
|
||||||
|
#ifdef CONFIG_KSU_SUSFS_SUS_PATH
|
||||||
|
if (is_nd_state_open_last) {
|
||||||
|
if (susfs_is_base_dentry_android_data_dir(dir) &&
|
||||||
|
susfs_is_sus_android_data_d_name_found(nd->last.name))
|
||||||
|
{
|
||||||
|
dentry = d_lookup(dir, &susfs_fake_qstr_name);
|
||||||
|
found_sus_path = true;
|
||||||
|
goto skip_orig_flow1;
|
||||||
|
} else if (susfs_is_base_dentry_sdcard_dir(dir) &&
|
||||||
|
susfs_is_sus_sdcard_d_name_found(nd->last.name))
|
||||||
|
{
|
||||||
|
dentry = d_lookup(dir, &susfs_fake_qstr_name);
|
||||||
|
found_sus_path = true;
|
||||||
|
goto skip_orig_flow1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#endif
|
||||||
dentry = d_lookup(dir, &nd->last);
|
dentry = d_lookup(dir, &nd->last);
|
||||||
|
#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;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
skip_orig_flow1:
|
||||||
|
#endif
|
||||||
for (;;) {
|
for (;;) {
|
||||||
if (!dentry) {
|
if (!dentry) {
|
||||||
|
#ifdef CONFIG_KSU_SUSFS_SUS_PATH
|
||||||
|
if (found_sus_path) {
|
||||||
|
dentry = d_alloc_parallel(dir, &susfs_fake_qstr_name, &wq);
|
||||||
|
goto skip_orig_flow2;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
dentry = d_alloc_parallel(dir, &nd->last, &wq);
|
dentry = d_alloc_parallel(dir, &nd->last, &wq);
|
||||||
|
#ifdef CONFIG_KSU_SUSFS_SUS_PATH
|
||||||
|
skip_orig_flow2:
|
||||||
|
#endif
|
||||||
if (IS_ERR(dentry))
|
if (IS_ERR(dentry))
|
||||||
return PTR_ERR(dentry);
|
return PTR_ERR(dentry);
|
||||||
}
|
}
|
||||||
@@ -3412,6 +3643,9 @@ static int do_last(struct nameidata *nd,
|
|||||||
struct path path;
|
struct path path;
|
||||||
int error;
|
int error;
|
||||||
|
|
||||||
|
#ifdef CONFIG_KSU_SUSFS_SUS_PATH
|
||||||
|
nd->state |= ND_STATE_OPEN_LAST;
|
||||||
|
#endif
|
||||||
nd->flags &= ~LOOKUP_PARENT;
|
nd->flags &= ~LOOKUP_PARENT;
|
||||||
nd->flags |= op->intent;
|
nd->flags |= op->intent;
|
||||||
|
|
||||||
@@ -3731,12 +3965,19 @@ out2:
|
|||||||
return file;
|
return file;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#ifdef CONFIG_KSU_SUSFS_OPEN_REDIRECT
|
||||||
|
extern struct filename* susfs_get_redirected_path(unsigned long ino);
|
||||||
|
#endif
|
||||||
|
|
||||||
struct file *do_filp_open(int dfd, struct filename *pathname,
|
struct file *do_filp_open(int dfd, struct filename *pathname,
|
||||||
const struct open_flags *op)
|
const struct open_flags *op)
|
||||||
{
|
{
|
||||||
struct nameidata nd;
|
struct nameidata nd;
|
||||||
int flags = op->lookup_flags;
|
int flags = op->lookup_flags;
|
||||||
struct file *filp;
|
struct file *filp;
|
||||||
|
#ifdef CONFIG_KSU_SUSFS_OPEN_REDIRECT
|
||||||
|
struct filename *fake_pathname;
|
||||||
|
#endif
|
||||||
|
|
||||||
set_nameidata(&nd, dfd, pathname);
|
set_nameidata(&nd, dfd, pathname);
|
||||||
filp = path_openat(&nd, op, flags | LOOKUP_RCU);
|
filp = path_openat(&nd, op, flags | LOOKUP_RCU);
|
||||||
@@ -3744,6 +3985,25 @@ struct file *do_filp_open(int dfd, struct filename *pathname,
|
|||||||
filp = path_openat(&nd, op, flags);
|
filp = path_openat(&nd, op, flags);
|
||||||
if (unlikely(filp == ERR_PTR(-ESTALE)))
|
if (unlikely(filp == ERR_PTR(-ESTALE)))
|
||||||
filp = path_openat(&nd, op, flags | LOOKUP_REVAL);
|
filp = path_openat(&nd, op, flags | LOOKUP_REVAL);
|
||||||
|
#ifdef CONFIG_KSU_SUSFS_OPEN_REDIRECT
|
||||||
|
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();
|
||||||
|
filp_close(filp, NULL);
|
||||||
|
// no need to do `putname(pathname);` here as it will be done by calling process
|
||||||
|
set_nameidata(&nd, dfd, fake_pathname);
|
||||||
|
filp = path_openat(&nd, op, flags | LOOKUP_RCU);
|
||||||
|
if (unlikely(filp == ERR_PTR(-ECHILD)))
|
||||||
|
filp = path_openat(&nd, op, flags);
|
||||||
|
if (unlikely(filp == ERR_PTR(-ESTALE)))
|
||||||
|
filp = path_openat(&nd, op, flags | LOOKUP_REVAL);
|
||||||
|
restore_nameidata();
|
||||||
|
putname(fake_pathname);
|
||||||
|
return filp;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#endif
|
||||||
restore_nameidata();
|
restore_nameidata();
|
||||||
return filp;
|
return filp;
|
||||||
}
|
}
|
||||||
|
|||||||
293
fs/namespace.c
293
fs/namespace.c
@@ -27,10 +27,39 @@
|
|||||||
#include <linux/bootmem.h>
|
#include <linux/bootmem.h>
|
||||||
#include <linux/task_work.h>
|
#include <linux/task_work.h>
|
||||||
#include <linux/sched/task.h>
|
#include <linux/sched/task.h>
|
||||||
|
#if defined(CONFIG_KSU_SUSFS_SUS_MOUNT) || defined(CONFIG_KSU_SUSFS_TRY_UMOUNT)
|
||||||
|
#include <linux/susfs_def.h>
|
||||||
|
#endif
|
||||||
|
|
||||||
#include "pnode.h"
|
#include "pnode.h"
|
||||||
#include "internal.h"
|
#include "internal.h"
|
||||||
|
|
||||||
|
#ifdef CONFIG_KSU_SUSFS_SUS_MOUNT
|
||||||
|
extern bool susfs_is_current_ksu_domain(void);
|
||||||
|
extern bool susfs_is_current_zygote_domain(void);
|
||||||
|
|
||||||
|
static DEFINE_IDA(susfs_mnt_id_ida);
|
||||||
|
static DEFINE_IDA(susfs_mnt_group_ida);
|
||||||
|
static int susfs_mnt_id_start = DEFAULT_SUS_MNT_ID;
|
||||||
|
static int susfs_mnt_group_start = DEFAULT_SUS_MNT_GROUP_ID;
|
||||||
|
|
||||||
|
#define CL_ZYGOTE_COPY_MNT_NS BIT(24) /* used by copy_mnt_ns() */
|
||||||
|
#define CL_COPY_MNT_NS BIT(25) /* used by copy_mnt_ns() */
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifdef CONFIG_KSU_SUSFS_AUTO_ADD_SUS_KSU_DEFAULT_MOUNT
|
||||||
|
extern void susfs_auto_add_sus_ksu_default_mount(const char __user *to_pathname);
|
||||||
|
bool susfs_is_auto_add_sus_ksu_default_mount_enabled = true;
|
||||||
|
#endif
|
||||||
|
#ifdef CONFIG_KSU_SUSFS_AUTO_ADD_SUS_BIND_MOUNT
|
||||||
|
extern int susfs_auto_add_sus_bind_mount(const char *pathname, struct path *path_target);
|
||||||
|
bool susfs_is_auto_add_sus_bind_mount_enabled = true;
|
||||||
|
#endif
|
||||||
|
#ifdef CONFIG_KSU_SUSFS_AUTO_ADD_TRY_UMOUNT_FOR_BIND_MOUNT
|
||||||
|
extern void susfs_auto_add_try_umount_for_bind_mount(struct path *path);
|
||||||
|
bool susfs_is_auto_add_try_umount_for_bind_mount_enabled = true;
|
||||||
|
#endif
|
||||||
|
|
||||||
/* Maximum number of mounts in a mount namespace */
|
/* Maximum number of mounts in a mount namespace */
|
||||||
unsigned int sysctl_mount_max __read_mostly = 100000;
|
unsigned int sysctl_mount_max __read_mostly = 100000;
|
||||||
|
|
||||||
@@ -100,6 +129,25 @@ static inline struct hlist_head *mp_hash(struct dentry *dentry)
|
|||||||
return &mountpoint_hashtable[tmp & mp_hash_mask];
|
return &mountpoint_hashtable[tmp & mp_hash_mask];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#ifdef CONFIG_KSU_SUSFS_SUS_MOUNT
|
||||||
|
// Our own mnt_alloc_id() that assigns mnt_id starting from DEFAULT_SUS_MNT_ID
|
||||||
|
static int susfs_mnt_alloc_id(struct mount *mnt)
|
||||||
|
{
|
||||||
|
int res;
|
||||||
|
|
||||||
|
retry:
|
||||||
|
ida_pre_get(&susfs_mnt_id_ida, GFP_KERNEL);
|
||||||
|
spin_lock(&mnt_id_lock);
|
||||||
|
res = ida_get_new_above(&susfs_mnt_id_ida, susfs_mnt_id_start, &mnt->mnt_id);
|
||||||
|
if (!res)
|
||||||
|
susfs_mnt_id_start = mnt->mnt_id + 1;
|
||||||
|
spin_unlock(&mnt_id_lock);
|
||||||
|
if (res == -EAGAIN)
|
||||||
|
goto retry;
|
||||||
|
|
||||||
|
return res;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
static int mnt_alloc_id(struct mount *mnt)
|
static int mnt_alloc_id(struct mount *mnt)
|
||||||
{
|
{
|
||||||
int res;
|
int res;
|
||||||
@@ -120,6 +168,35 @@ retry:
|
|||||||
static void mnt_free_id(struct mount *mnt)
|
static void mnt_free_id(struct mount *mnt)
|
||||||
{
|
{
|
||||||
int id = mnt->mnt_id;
|
int id = mnt->mnt_id;
|
||||||
|
#ifdef CONFIG_KSU_SUSFS_SUS_MOUNT
|
||||||
|
int mnt_id_backup = mnt->mnt.susfs_mnt_id_backup;
|
||||||
|
// We should first check the 'mnt->mnt.susfs_mnt_id_backup', see if it is DEFAULT_SUS_MNT_ID_FOR_KSU_PROC_UNSHARE
|
||||||
|
// if so, these mnt_id were not assigned by mnt_alloc_id() so we don't need to free it.
|
||||||
|
if (unlikely(mnt_id_backup == DEFAULT_SUS_MNT_ID_FOR_KSU_PROC_UNSHARE)) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
// Now we can check if its mnt_id is sus
|
||||||
|
if (unlikely(mnt->mnt_id >= DEFAULT_SUS_MNT_ID)) {
|
||||||
|
spin_lock(&mnt_id_lock);
|
||||||
|
ida_remove(&susfs_mnt_id_ida, id);
|
||||||
|
if (susfs_mnt_id_start > id)
|
||||||
|
susfs_mnt_id_start = id;
|
||||||
|
spin_unlock(&mnt_id_lock);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
// Lastly if 'mnt->mnt.susfs_mnt_id_backup' is not 0, then it contains a backup origin mnt_id
|
||||||
|
// so we free it in the original way
|
||||||
|
if (likely(mnt_id_backup)) {
|
||||||
|
// If mnt->mnt.susfs_mnt_id_backup is not zero, it means mnt->mnt_id is spoofed,
|
||||||
|
// so here we return the original mnt_id for being freed.
|
||||||
|
spin_lock(&mnt_id_lock);
|
||||||
|
ida_remove(&mnt_id_ida, mnt_id_backup);
|
||||||
|
if (mnt_id_start > mnt_id_backup)
|
||||||
|
mnt_id_start = mnt_id_backup;
|
||||||
|
spin_unlock(&mnt_id_lock);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
spin_lock(&mnt_id_lock);
|
spin_lock(&mnt_id_lock);
|
||||||
ida_remove(&mnt_id_ida, id);
|
ida_remove(&mnt_id_ida, id);
|
||||||
if (mnt_id_start > id)
|
if (mnt_id_start > id)
|
||||||
@@ -136,6 +213,19 @@ static int mnt_alloc_group_id(struct mount *mnt)
|
|||||||
{
|
{
|
||||||
int res;
|
int res;
|
||||||
|
|
||||||
|
#ifdef CONFIG_KSU_SUSFS_SUS_MOUNT
|
||||||
|
if (mnt->mnt_id >= DEFAULT_SUS_MNT_ID) {
|
||||||
|
if (!ida_pre_get(&susfs_mnt_group_ida, GFP_KERNEL))
|
||||||
|
return -ENOMEM;
|
||||||
|
// If so, assign a sus mnt_group id DEFAULT_SUS_MNT_GROUP_ID from susfs_mnt_group_ida
|
||||||
|
res = ida_get_new_above(&susfs_mnt_group_ida,
|
||||||
|
susfs_mnt_group_start,
|
||||||
|
&mnt->mnt_group_id);
|
||||||
|
if (!res)
|
||||||
|
susfs_mnt_group_start = mnt->mnt_group_id + 1;
|
||||||
|
return res;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
if (!ida_pre_get(&mnt_group_ida, GFP_KERNEL))
|
if (!ida_pre_get(&mnt_group_ida, GFP_KERNEL))
|
||||||
return -ENOMEM;
|
return -ENOMEM;
|
||||||
|
|
||||||
@@ -154,6 +244,17 @@ static int mnt_alloc_group_id(struct mount *mnt)
|
|||||||
void mnt_release_group_id(struct mount *mnt)
|
void mnt_release_group_id(struct mount *mnt)
|
||||||
{
|
{
|
||||||
int id = mnt->mnt_group_id;
|
int id = mnt->mnt_group_id;
|
||||||
|
#ifdef CONFIG_KSU_SUSFS_SUS_MOUNT
|
||||||
|
// If mnt->mnt_group_id >= DEFAULT_SUS_MNT_GROUP_ID, it means 'mnt' is also sus mount,
|
||||||
|
// then we free the mnt->mnt_group_id from susfs_mnt_group_ida
|
||||||
|
if (id >= DEFAULT_SUS_MNT_GROUP_ID) {
|
||||||
|
ida_remove(&susfs_mnt_group_ida, id);
|
||||||
|
if (susfs_mnt_group_start > id)
|
||||||
|
susfs_mnt_group_start = id;
|
||||||
|
mnt->mnt_group_id = 0;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
ida_remove(&mnt_group_ida, id);
|
ida_remove(&mnt_group_ida, id);
|
||||||
if (mnt_group_start > id)
|
if (mnt_group_start > id)
|
||||||
mnt_group_start = id;
|
mnt_group_start = id;
|
||||||
@@ -201,13 +302,31 @@ static void drop_mountpoint(struct fs_pin *p)
|
|||||||
mntput(&m->mnt);
|
mntput(&m->mnt);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#ifdef CONFIG_KSU_SUSFS_SUS_MOUNT
|
||||||
|
static struct mount *alloc_vfsmnt(const char *name, bool should_spoof, int custom_mnt_id)
|
||||||
|
#else
|
||||||
static struct mount *alloc_vfsmnt(const char *name)
|
static struct mount *alloc_vfsmnt(const char *name)
|
||||||
|
#endif
|
||||||
{
|
{
|
||||||
struct mount *mnt = kmem_cache_zalloc(mnt_cache, GFP_KERNEL);
|
struct mount *mnt = kmem_cache_zalloc(mnt_cache, GFP_KERNEL);
|
||||||
if (mnt) {
|
if (mnt) {
|
||||||
int err;
|
int err;
|
||||||
|
|
||||||
|
#ifdef CONFIG_KSU_SUSFS_SUS_MOUNT
|
||||||
|
if (should_spoof) {
|
||||||
|
if (!custom_mnt_id) {
|
||||||
|
err = susfs_mnt_alloc_id(mnt);
|
||||||
|
} else {
|
||||||
|
mnt->mnt_id = custom_mnt_id;
|
||||||
|
err = 0;
|
||||||
|
}
|
||||||
|
goto bypass_orig_flow;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
err = mnt_alloc_id(mnt);
|
err = mnt_alloc_id(mnt);
|
||||||
|
#ifdef CONFIG_KSU_SUSFS_SUS_MOUNT
|
||||||
|
bypass_orig_flow:
|
||||||
|
#endif
|
||||||
if (err)
|
if (err)
|
||||||
goto out_free_cache;
|
goto out_free_cache;
|
||||||
|
|
||||||
@@ -1039,7 +1158,17 @@ vfs_kern_mount(struct file_system_type *type, int flags, const char *name, void
|
|||||||
if (!type)
|
if (!type)
|
||||||
return ERR_PTR(-ENODEV);
|
return ERR_PTR(-ENODEV);
|
||||||
|
|
||||||
|
#ifdef CONFIG_KSU_SUSFS_SUS_MOUNT
|
||||||
|
// For newly created mounts, the only caller process we care is KSU
|
||||||
|
if (unlikely(susfs_is_current_ksu_domain())) {
|
||||||
|
mnt = alloc_vfsmnt(name, true, 0);
|
||||||
|
goto bypass_orig_flow;
|
||||||
|
}
|
||||||
|
mnt = alloc_vfsmnt(name, false, 0);
|
||||||
|
bypass_orig_flow:
|
||||||
|
#else
|
||||||
mnt = alloc_vfsmnt(name);
|
mnt = alloc_vfsmnt(name);
|
||||||
|
#endif
|
||||||
if (!mnt)
|
if (!mnt)
|
||||||
return ERR_PTR(-ENOMEM);
|
return ERR_PTR(-ENOMEM);
|
||||||
|
|
||||||
@@ -1065,6 +1194,15 @@ vfs_kern_mount(struct file_system_type *type, int flags, const char *name, void
|
|||||||
mnt->mnt.mnt_sb = root->d_sb;
|
mnt->mnt.mnt_sb = root->d_sb;
|
||||||
mnt->mnt_mountpoint = mnt->mnt.mnt_root;
|
mnt->mnt_mountpoint = mnt->mnt.mnt_root;
|
||||||
mnt->mnt_parent = mnt;
|
mnt->mnt_parent = mnt;
|
||||||
|
|
||||||
|
#ifdef CONFIG_KSU_SUSFS_SUS_MOUNT
|
||||||
|
// If caller process is zygote, then it is a normal mount, so we just reorder the mnt_id
|
||||||
|
if (susfs_is_current_zygote_domain()) {
|
||||||
|
mnt->mnt.susfs_mnt_id_backup = mnt->mnt_id;
|
||||||
|
mnt->mnt_id = current->susfs_last_fake_mnt_id++;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
lock_mount_hash();
|
lock_mount_hash();
|
||||||
list_add_tail(&mnt->mnt_instance, &root->d_sb->s_mounts);
|
list_add_tail(&mnt->mnt_instance, &root->d_sb->s_mounts);
|
||||||
unlock_mount_hash();
|
unlock_mount_hash();
|
||||||
@@ -1093,8 +1231,52 @@ static struct mount *clone_mnt(struct mount *old, struct dentry *root,
|
|||||||
struct super_block *sb = old->mnt.mnt_sb;
|
struct super_block *sb = old->mnt.mnt_sb;
|
||||||
struct mount *mnt;
|
struct mount *mnt;
|
||||||
int err;
|
int err;
|
||||||
|
#ifdef CONFIG_KSU_SUSFS_SUS_MOUNT
|
||||||
|
bool is_current_ksu_domain = susfs_is_current_ksu_domain();
|
||||||
|
bool is_current_zygote_domain = susfs_is_current_zygote_domain();
|
||||||
|
|
||||||
|
/* - It is very important that we need to use CL_COPY_MNT_NS to identify whether
|
||||||
|
* the clone is a copy_tree() or single mount like called by __do_loopback()
|
||||||
|
* - if caller process is KSU, consider the following situation:
|
||||||
|
* 1. it is NOT doing unshare => call alloc_vfsmnt() to assign a new sus mnt_id
|
||||||
|
* 2. it is doing unshare => spoof the new mnt_id with the old mnt_id
|
||||||
|
* - If caller process is zygote and old mnt_id is sus => call alloc_vfsmnt() to assign a new sus mnt_id
|
||||||
|
* - For the rest of caller process that doing unshare => call alloc_vfsmnt() to assign a new sus mnt_id only for old sus mount
|
||||||
|
*/
|
||||||
|
// Firstly, check if it is KSU process
|
||||||
|
if (unlikely(is_current_ksu_domain)) {
|
||||||
|
// if it is doing single clone
|
||||||
|
if (!(flag & CL_COPY_MNT_NS)) {
|
||||||
|
mnt = alloc_vfsmnt(old->mnt_devname, true, 0);
|
||||||
|
goto bypass_orig_flow;
|
||||||
|
}
|
||||||
|
// if it is doing unshare
|
||||||
|
mnt = alloc_vfsmnt(old->mnt_devname, true, old->mnt_id);
|
||||||
|
if (mnt) {
|
||||||
|
mnt->mnt.susfs_mnt_id_backup = DEFAULT_SUS_MNT_ID_FOR_KSU_PROC_UNSHARE;
|
||||||
|
}
|
||||||
|
goto bypass_orig_flow;
|
||||||
|
}
|
||||||
|
// Secondly, check if it is zygote process and no matter it is doing unshare or not
|
||||||
|
if (likely(is_current_zygote_domain) && (old->mnt_id >= DEFAULT_SUS_MNT_ID)) {
|
||||||
|
/* Important Note:
|
||||||
|
* - Here we can't determine whether the unshare is called zygisk or not,
|
||||||
|
* so we can only patch out the unshare code in zygisk source code for now
|
||||||
|
* - But at least we can deal with old sus mounts using alloc_vfsmnt()
|
||||||
|
*/
|
||||||
|
mnt = alloc_vfsmnt(old->mnt_devname, true, 0);
|
||||||
|
goto bypass_orig_flow;
|
||||||
|
}
|
||||||
|
// Lastly, for other process that is doing unshare operation, but only deal with old sus mount
|
||||||
|
if ((flag & CL_COPY_MNT_NS) && (old->mnt_id >= DEFAULT_SUS_MNT_ID)) {
|
||||||
|
mnt = alloc_vfsmnt(old->mnt_devname, true, 0);
|
||||||
|
goto bypass_orig_flow;
|
||||||
|
}
|
||||||
|
mnt = alloc_vfsmnt(old->mnt_devname, false, 0);
|
||||||
|
bypass_orig_flow:
|
||||||
|
#else
|
||||||
mnt = alloc_vfsmnt(old->mnt_devname);
|
mnt = alloc_vfsmnt(old->mnt_devname);
|
||||||
|
#endif
|
||||||
if (!mnt)
|
if (!mnt)
|
||||||
return ERR_PTR(-ENOMEM);
|
return ERR_PTR(-ENOMEM);
|
||||||
|
|
||||||
@@ -1146,6 +1328,15 @@ static struct mount *clone_mnt(struct mount *old, struct dentry *root,
|
|||||||
mnt->mnt.mnt_root = dget(root);
|
mnt->mnt.mnt_root = dget(root);
|
||||||
mnt->mnt_mountpoint = mnt->mnt.mnt_root;
|
mnt->mnt_mountpoint = mnt->mnt.mnt_root;
|
||||||
mnt->mnt_parent = mnt;
|
mnt->mnt_parent = mnt;
|
||||||
|
|
||||||
|
#ifdef CONFIG_KSU_SUSFS_SUS_MOUNT
|
||||||
|
// If caller process is zygote and not doing unshare, so we just reorder the mnt_id
|
||||||
|
if (likely(is_current_zygote_domain) && !(flag & CL_ZYGOTE_COPY_MNT_NS)) {
|
||||||
|
mnt->mnt.susfs_mnt_id_backup = mnt->mnt_id;
|
||||||
|
mnt->mnt_id = current->susfs_last_fake_mnt_id++;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
lock_mount_hash();
|
lock_mount_hash();
|
||||||
list_add_tail(&mnt->mnt_instance, &sb->s_mounts);
|
list_add_tail(&mnt->mnt_instance, &sb->s_mounts);
|
||||||
unlock_mount_hash();
|
unlock_mount_hash();
|
||||||
@@ -1916,6 +2107,7 @@ struct mount *copy_tree(struct mount *mnt, struct dentry *dentry,
|
|||||||
p = mnt;
|
p = mnt;
|
||||||
list_for_each_entry(r, &mnt->mnt_mounts, mnt_child) {
|
list_for_each_entry(r, &mnt->mnt_mounts, mnt_child) {
|
||||||
struct mount *s;
|
struct mount *s;
|
||||||
|
|
||||||
if (!is_subdir(r->mnt_mountpoint, dentry))
|
if (!is_subdir(r->mnt_mountpoint, dentry))
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
@@ -1947,7 +2139,7 @@ struct mount *copy_tree(struct mount *mnt, struct dentry *dentry,
|
|||||||
goto out;
|
goto out;
|
||||||
lock_mount_hash();
|
lock_mount_hash();
|
||||||
list_add_tail(&q->mnt_list, &res->mnt_list);
|
list_add_tail(&q->mnt_list, &res->mnt_list);
|
||||||
attach_mnt(q, parent, p->mnt_mp);
|
attach_mnt(q, parent, p->mnt_mp);
|
||||||
unlock_mount_hash();
|
unlock_mount_hash();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -2410,6 +2602,27 @@ static int do_loopback(struct path *path, const char *old_name,
|
|||||||
umount_tree(mnt, UMOUNT_SYNC);
|
umount_tree(mnt, UMOUNT_SYNC);
|
||||||
unlock_mount_hash();
|
unlock_mount_hash();
|
||||||
}
|
}
|
||||||
|
#if defined(CONFIG_KSU_SUSFS_AUTO_ADD_SUS_BIND_MOUNT) || defined(CONFIG_KSU_SUSFS_AUTO_ADD_TRY_UMOUNT_FOR_BIND_MOUNT)
|
||||||
|
// Check if bind mounted path should be hidden and umounted automatically.
|
||||||
|
// And we target only process with ksu domain.
|
||||||
|
if (susfs_is_current_ksu_domain()) {
|
||||||
|
#if defined(CONFIG_KSU_SUSFS_AUTO_ADD_SUS_BIND_MOUNT)
|
||||||
|
if (susfs_is_auto_add_sus_bind_mount_enabled &&
|
||||||
|
susfs_auto_add_sus_bind_mount(old_name, &old_path)) {
|
||||||
|
goto orig_flow;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
#if defined(CONFIG_KSU_SUSFS_AUTO_ADD_TRY_UMOUNT_FOR_BIND_MOUNT)
|
||||||
|
if (susfs_is_auto_add_try_umount_for_bind_mount_enabled) {
|
||||||
|
susfs_auto_add_try_umount_for_bind_mount(path);
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
#if defined(CONFIG_KSU_SUSFS_AUTO_ADD_SUS_BIND_MOUNT)
|
||||||
|
orig_flow:
|
||||||
|
#endif
|
||||||
|
#endif // #if defined(CONFIG_KSU_SUSFS_AUTO_ADD_SUS_BIND_MOUNT) || defined(CONFIG_KSU_SUSFS_AUTO_ADD_TRY_UMOUNT_FOR_BIND_MOUNT)
|
||||||
|
|
||||||
out2:
|
out2:
|
||||||
unlock_mount(mp);
|
unlock_mount(mp);
|
||||||
out:
|
out:
|
||||||
@@ -3009,6 +3222,15 @@ long do_mount(const char *dev_name, const char __user *dir_name,
|
|||||||
else
|
else
|
||||||
retval = do_new_mount(&path, type_page, sb_flags, mnt_flags,
|
retval = do_new_mount(&path, type_page, sb_flags, mnt_flags,
|
||||||
dev_name, data_page);
|
dev_name, data_page);
|
||||||
|
#ifdef CONFIG_KSU_SUSFS_AUTO_ADD_SUS_KSU_DEFAULT_MOUNT
|
||||||
|
// For both Legacy and Magic Mount KernelSU
|
||||||
|
if (!retval && susfs_is_auto_add_sus_ksu_default_mount_enabled &&
|
||||||
|
(!(flags & (MS_REMOUNT | MS_BIND | MS_SHARED | MS_PRIVATE | MS_SLAVE | MS_UNBINDABLE)))) {
|
||||||
|
if (susfs_is_current_ksu_domain()) {
|
||||||
|
susfs_auto_add_sus_ksu_default_mount(dir_name);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#endif
|
||||||
dput_out:
|
dput_out:
|
||||||
path_put(&path);
|
path_put(&path);
|
||||||
return retval;
|
return retval;
|
||||||
@@ -3086,6 +3308,10 @@ struct mnt_namespace *copy_mnt_ns(unsigned long flags, struct mnt_namespace *ns,
|
|||||||
struct mount *old;
|
struct mount *old;
|
||||||
struct mount *new;
|
struct mount *new;
|
||||||
int copy_flags;
|
int copy_flags;
|
||||||
|
#ifdef CONFIG_KSU_SUSFS_SUS_MOUNT
|
||||||
|
bool is_zygote_pid = susfs_is_current_zygote_domain();
|
||||||
|
int last_entry_mnt_id = 0;
|
||||||
|
#endif
|
||||||
|
|
||||||
BUG_ON(!ns);
|
BUG_ON(!ns);
|
||||||
|
|
||||||
@@ -3105,6 +3331,14 @@ struct mnt_namespace *copy_mnt_ns(unsigned long flags, struct mnt_namespace *ns,
|
|||||||
copy_flags = CL_COPY_UNBINDABLE | CL_EXPIRE;
|
copy_flags = CL_COPY_UNBINDABLE | CL_EXPIRE;
|
||||||
if (user_ns != ns->user_ns)
|
if (user_ns != ns->user_ns)
|
||||||
copy_flags |= CL_SHARED_TO_SLAVE | CL_UNPRIVILEGED;
|
copy_flags |= CL_SHARED_TO_SLAVE | CL_UNPRIVILEGED;
|
||||||
|
#ifdef CONFIG_KSU_SUSFS_SUS_MOUNT
|
||||||
|
// Always let clone_mnt() in copy_tree() know it is from copy_mnt_ns()
|
||||||
|
copy_flags |= CL_COPY_MNT_NS;
|
||||||
|
if (is_zygote_pid) {
|
||||||
|
// Let clone_mnt() in copy_tree() know copy_mnt_ns() is run by zygote process
|
||||||
|
copy_flags |= CL_ZYGOTE_COPY_MNT_NS;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
new = copy_tree(old, old->mnt.mnt_root, copy_flags);
|
new = copy_tree(old, old->mnt.mnt_root, copy_flags);
|
||||||
if (IS_ERR(new)) {
|
if (IS_ERR(new)) {
|
||||||
namespace_unlock();
|
namespace_unlock();
|
||||||
@@ -3141,6 +3375,29 @@ struct mnt_namespace *copy_mnt_ns(unsigned long flags, struct mnt_namespace *ns,
|
|||||||
while (p->mnt.mnt_root != q->mnt.mnt_root)
|
while (p->mnt.mnt_root != q->mnt.mnt_root)
|
||||||
p = next_mnt(p, old);
|
p = next_mnt(p, old);
|
||||||
}
|
}
|
||||||
|
#ifdef CONFIG_KSU_SUSFS_SUS_MOUNT
|
||||||
|
// current->susfs_last_fake_mnt_id -> to record last valid fake mnt_id to zygote pid
|
||||||
|
// q->mnt.susfs_mnt_id_backup -> original mnt_id
|
||||||
|
// q->mnt_id -> will be modified to the fake mnt_id
|
||||||
|
|
||||||
|
// Here We are only interested in processes of which original mnt namespace belongs to zygote
|
||||||
|
// Also we just make use of existing 'q' mount pointer, no need to delcare extra mount pointer
|
||||||
|
if (is_zygote_pid) {
|
||||||
|
last_entry_mnt_id = list_first_entry(&new_ns->list, struct mount, mnt_list)->mnt_id;
|
||||||
|
list_for_each_entry(q, &new_ns->list, mnt_list) {
|
||||||
|
if (unlikely(q->mnt_id >= DEFAULT_SUS_MNT_ID)) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
q->mnt.susfs_mnt_id_backup = q->mnt_id;
|
||||||
|
q->mnt_id = last_entry_mnt_id++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// Assign the 'last_entry_mnt_id' to 'current->susfs_last_fake_mnt_id' for later use.
|
||||||
|
// should be fine here assuming zygote is forking/unsharing app in one single thread.
|
||||||
|
// Or should we put a lock here?
|
||||||
|
current->susfs_last_fake_mnt_id = last_entry_mnt_id;
|
||||||
|
#endif
|
||||||
|
|
||||||
namespace_unlock();
|
namespace_unlock();
|
||||||
|
|
||||||
if (rootmnt)
|
if (rootmnt)
|
||||||
@@ -3681,3 +3938,37 @@ const struct proc_ns_operations mntns_operations = {
|
|||||||
.install = mntns_install,
|
.install = mntns_install,
|
||||||
.owner = mntns_owner,
|
.owner = mntns_owner,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
#ifdef CONFIG_KSU_SUSFS_TRY_UMOUNT
|
||||||
|
extern void susfs_try_umount_all(uid_t uid);
|
||||||
|
void susfs_run_try_umount_for_current_mnt_ns(void) {
|
||||||
|
struct mount *mnt;
|
||||||
|
struct mnt_namespace *mnt_ns;
|
||||||
|
|
||||||
|
mnt_ns = current->nsproxy->mnt_ns;
|
||||||
|
// Lock the namespace
|
||||||
|
namespace_lock();
|
||||||
|
list_for_each_entry(mnt, &mnt_ns->list, mnt_list) {
|
||||||
|
// Change the sus mount to be private
|
||||||
|
if (mnt->mnt_id >= DEFAULT_SUS_MNT_ID) {
|
||||||
|
change_mnt_propagation(mnt, MS_PRIVATE);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// Unlock the namespace
|
||||||
|
namespace_unlock();
|
||||||
|
susfs_try_umount_all(current_uid().val);
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
#ifdef CONFIG_KSU_SUSFS
|
||||||
|
bool susfs_is_mnt_devname_ksu(struct path *path) {
|
||||||
|
struct mount *mnt;
|
||||||
|
|
||||||
|
if (path && path->mnt) {
|
||||||
|
mnt = real_mount(path->mnt);
|
||||||
|
if (mnt && mnt->mnt_devname && !strcmp(mnt->mnt_devname, "KSU")) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|||||||
@@ -13,6 +13,9 @@
|
|||||||
#include <linux/seq_file.h>
|
#include <linux/seq_file.h>
|
||||||
#include <linux/proc_fs.h>
|
#include <linux/proc_fs.h>
|
||||||
#include <linux/exportfs.h>
|
#include <linux/exportfs.h>
|
||||||
|
#ifdef CONFIG_KSU_SUSFS_SUS_MOUNT
|
||||||
|
#include <linux/susfs_def.h>
|
||||||
|
#endif
|
||||||
|
|
||||||
#include "inotify/inotify.h"
|
#include "inotify/inotify.h"
|
||||||
#include "../fs/mount.h"
|
#include "../fs/mount.h"
|
||||||
@@ -21,16 +24,27 @@
|
|||||||
|
|
||||||
#if defined(CONFIG_INOTIFY_USER) || defined(CONFIG_FANOTIFY)
|
#if defined(CONFIG_INOTIFY_USER) || defined(CONFIG_FANOTIFY)
|
||||||
|
|
||||||
|
#ifdef CONFIG_KSU_SUSFS_SUS_MOUNT
|
||||||
|
static void show_fdinfo(struct seq_file *m, struct file *f,
|
||||||
|
void (*show)(struct seq_file *m,
|
||||||
|
struct fsnotify_mark *mark,
|
||||||
|
struct file *file))
|
||||||
|
#else
|
||||||
static void show_fdinfo(struct seq_file *m, struct file *f,
|
static void show_fdinfo(struct seq_file *m, struct file *f,
|
||||||
void (*show)(struct seq_file *m,
|
void (*show)(struct seq_file *m,
|
||||||
struct fsnotify_mark *mark))
|
struct fsnotify_mark *mark))
|
||||||
|
#endif
|
||||||
{
|
{
|
||||||
struct fsnotify_group *group = f->private_data;
|
struct fsnotify_group *group = f->private_data;
|
||||||
struct fsnotify_mark *mark;
|
struct fsnotify_mark *mark;
|
||||||
|
|
||||||
mutex_lock(&group->mark_mutex);
|
mutex_lock(&group->mark_mutex);
|
||||||
list_for_each_entry(mark, &group->marks_list, g_list) {
|
list_for_each_entry(mark, &group->marks_list, g_list) {
|
||||||
|
#ifdef CONFIG_KSU_SUSFS_SUS_MOUNT
|
||||||
|
show(m, mark, f);
|
||||||
|
#else
|
||||||
show(m, mark);
|
show(m, mark);
|
||||||
|
#endif
|
||||||
if (seq_has_overflowed(m))
|
if (seq_has_overflowed(m))
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
@@ -72,7 +86,11 @@ static void show_mark_fhandle(struct seq_file *m, struct inode *inode)
|
|||||||
|
|
||||||
#ifdef CONFIG_INOTIFY_USER
|
#ifdef CONFIG_INOTIFY_USER
|
||||||
|
|
||||||
|
#ifdef CONFIG_KSU_SUSFS_SUS_MOUNT
|
||||||
|
static void inotify_fdinfo(struct seq_file *m, struct fsnotify_mark *mark, struct file *file)
|
||||||
|
#else
|
||||||
static void inotify_fdinfo(struct seq_file *m, struct fsnotify_mark *mark)
|
static void inotify_fdinfo(struct seq_file *m, struct fsnotify_mark *mark)
|
||||||
|
#endif
|
||||||
{
|
{
|
||||||
struct inotify_inode_mark *inode_mark;
|
struct inotify_inode_mark *inode_mark;
|
||||||
struct inode *inode;
|
struct inode *inode;
|
||||||
@@ -83,6 +101,36 @@ static void inotify_fdinfo(struct seq_file *m, struct fsnotify_mark *mark)
|
|||||||
inode_mark = container_of(mark, struct inotify_inode_mark, fsn_mark);
|
inode_mark = container_of(mark, struct inotify_inode_mark, fsn_mark);
|
||||||
inode = igrab(mark->connector->inode);
|
inode = igrab(mark->connector->inode);
|
||||||
if (inode) {
|
if (inode) {
|
||||||
|
#ifdef CONFIG_KSU_SUSFS_SUS_MOUNT
|
||||||
|
if (likely(susfs_is_current_proc_umounted()) &&
|
||||||
|
unlikely(inode->i_mapping->flags & BIT_SUS_KSTAT)) {
|
||||||
|
struct path path;
|
||||||
|
char *pathname = kmalloc(PAGE_SIZE, GFP_KERNEL);
|
||||||
|
char *dpath;
|
||||||
|
if (!pathname) {
|
||||||
|
goto out_seq_printf;
|
||||||
|
}
|
||||||
|
dpath = d_path(&file->f_path, pathname, PAGE_SIZE);
|
||||||
|
if (!dpath) {
|
||||||
|
goto out_free_pathname;
|
||||||
|
}
|
||||||
|
if (kern_path(dpath, 0, &path)) {
|
||||||
|
goto out_free_pathname;
|
||||||
|
}
|
||||||
|
seq_printf(m, "inotify wd:%x ino:%lx sdev:%x mask:%x ignored_mask:0 ",
|
||||||
|
inode_mark->wd, path.dentry->d_inode->i_ino, path.dentry->d_inode->i_sb->s_dev,
|
||||||
|
inotify_mark_user_mask(mark));
|
||||||
|
show_mark_fhandle(m, path.dentry->d_inode);
|
||||||
|
seq_putc(m, '\n');
|
||||||
|
iput(inode);
|
||||||
|
path_put(&path);
|
||||||
|
kfree(pathname);
|
||||||
|
return;
|
||||||
|
out_free_pathname:
|
||||||
|
kfree(pathname);
|
||||||
|
}
|
||||||
|
out_seq_printf:
|
||||||
|
#endif
|
||||||
seq_printf(m, "inotify wd:%x ino:%lx sdev:%x mask:%x ignored_mask:0 ",
|
seq_printf(m, "inotify wd:%x ino:%lx sdev:%x mask:%x ignored_mask:0 ",
|
||||||
inode_mark->wd, inode->i_ino, inode->i_sb->s_dev,
|
inode_mark->wd, inode->i_ino, inode->i_sb->s_dev,
|
||||||
inotify_mark_user_mask(mark));
|
inotify_mark_user_mask(mark));
|
||||||
|
|||||||
@@ -101,6 +101,9 @@
|
|||||||
#include <trace/events/oom.h>
|
#include <trace/events/oom.h>
|
||||||
#include "internal.h"
|
#include "internal.h"
|
||||||
#include "fd.h"
|
#include "fd.h"
|
||||||
|
#ifdef CONFIG_KSU_SUSFS_SUS_MAP
|
||||||
|
#include <linux/susfs_def.h>
|
||||||
|
#endif
|
||||||
|
|
||||||
#include "../../lib/kstrtox.h"
|
#include "../../lib/kstrtox.h"
|
||||||
|
|
||||||
@@ -822,6 +825,9 @@ static ssize_t mem_rw(struct file *file, char __user *buf,
|
|||||||
ssize_t copied;
|
ssize_t copied;
|
||||||
char *page;
|
char *page;
|
||||||
unsigned int flags;
|
unsigned int flags;
|
||||||
|
#ifdef CONFIG_KSU_SUSFS_SUS_MAP
|
||||||
|
struct vm_area_struct *vma;
|
||||||
|
#endif
|
||||||
|
|
||||||
if (!mm)
|
if (!mm)
|
||||||
return 0;
|
return 0;
|
||||||
@@ -838,7 +844,20 @@ static ssize_t mem_rw(struct file *file, char __user *buf,
|
|||||||
|
|
||||||
while (count > 0) {
|
while (count > 0) {
|
||||||
size_t this_len = min_t(size_t, count, PAGE_SIZE);
|
size_t this_len = min_t(size_t, count, PAGE_SIZE);
|
||||||
|
#ifdef CONFIG_KSU_SUSFS_SUS_MAP
|
||||||
|
vma = find_vma(mm, addr);
|
||||||
|
if (vma && vma->vm_file) {
|
||||||
|
struct inode *inode = file_inode(vma->vm_file);
|
||||||
|
if (unlikely(inode->i_mapping->flags & BIT_SUS_MAPS) && susfs_is_current_proc_umounted()) {
|
||||||
|
if (write) {
|
||||||
|
copied = -EFAULT;
|
||||||
|
} else {
|
||||||
|
copied = -EIO;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#endif
|
||||||
if (write && copy_from_user(page, buf, this_len)) {
|
if (write && copy_from_user(page, buf, this_len)) {
|
||||||
copied = -EFAULT;
|
copied = -EFAULT;
|
||||||
break;
|
break;
|
||||||
@@ -2406,6 +2425,13 @@ proc_map_files_readdir(struct file *file, struct dir_context *ctx)
|
|||||||
vma = vma->vm_next) {
|
vma = vma->vm_next) {
|
||||||
if (!vma->vm_file)
|
if (!vma->vm_file)
|
||||||
continue;
|
continue;
|
||||||
|
#ifdef CONFIG_KSU_SUSFS_SUS_MAP
|
||||||
|
if (unlikely(file_inode(vma->vm_file)->i_mapping->flags & BIT_SUS_MAPS) &&
|
||||||
|
susfs_is_current_proc_umounted())
|
||||||
|
{
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
if (++pos <= ctx->pos)
|
if (++pos <= ctx->pos)
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
|
|||||||
@@ -27,8 +27,18 @@ static void proc_command_line_init(void) {
|
|||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#ifdef CONFIG_KSU_SUSFS_SPOOF_CMDLINE_OR_BOOTCONFIG
|
||||||
|
extern int susfs_spoof_cmdline_or_bootconfig(struct seq_file *m);
|
||||||
|
#endif
|
||||||
|
|
||||||
static int cmdline_proc_show(struct seq_file *m, void *v)
|
static int cmdline_proc_show(struct seq_file *m, void *v)
|
||||||
{
|
{
|
||||||
|
#ifdef CONFIG_KSU_SUSFS_SPOOF_CMDLINE_OR_BOOTCONFIG
|
||||||
|
if (!susfs_spoof_cmdline_or_bootconfig(m)) {
|
||||||
|
seq_putc(m, '\n');
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
#ifdef CONFIG_INITRAMFS_IGNORE_SKIP_FLAG
|
#ifdef CONFIG_INITRAMFS_IGNORE_SKIP_FLAG
|
||||||
seq_printf(m, "%s\n", proc_command_line);
|
seq_printf(m, "%s\n", proc_command_line);
|
||||||
#else
|
#else
|
||||||
|
|||||||
17
fs/proc/fd.c
17
fs/proc/fd.c
@@ -12,6 +12,9 @@
|
|||||||
#include <linux/fs.h>
|
#include <linux/fs.h>
|
||||||
|
|
||||||
#include <linux/proc_fs.h>
|
#include <linux/proc_fs.h>
|
||||||
|
#ifdef CONFIG_KSU_SUSFS_SUS_MOUNT
|
||||||
|
#include <linux/susfs_def.h>
|
||||||
|
#endif
|
||||||
|
|
||||||
#include "../mount.h"
|
#include "../mount.h"
|
||||||
#include "internal.h"
|
#include "internal.h"
|
||||||
@@ -23,6 +26,9 @@ static int seq_show(struct seq_file *m, void *v)
|
|||||||
int f_flags = 0, ret = -ENOENT;
|
int f_flags = 0, ret = -ENOENT;
|
||||||
struct file *file = NULL;
|
struct file *file = NULL;
|
||||||
struct task_struct *task;
|
struct task_struct *task;
|
||||||
|
#ifdef CONFIG_KSU_SUSFS_SUS_MOUNT
|
||||||
|
struct mount *mnt = NULL;
|
||||||
|
#endif
|
||||||
|
|
||||||
task = get_proc_task(m->private);
|
task = get_proc_task(m->private);
|
||||||
if (!task)
|
if (!task)
|
||||||
@@ -53,9 +59,20 @@ static int seq_show(struct seq_file *m, void *v)
|
|||||||
if (ret)
|
if (ret)
|
||||||
return ret;
|
return ret;
|
||||||
|
|
||||||
|
#ifdef CONFIG_KSU_SUSFS_SUS_MOUNT
|
||||||
|
mnt = real_mount(file->f_path.mnt);
|
||||||
|
if (likely(susfs_is_current_proc_umounted()) &&
|
||||||
|
mnt->mnt_id >= DEFAULT_SUS_MNT_ID) {
|
||||||
|
for (; mnt->mnt_id >= DEFAULT_SUS_MNT_ID; mnt = mnt->mnt_parent) { }
|
||||||
|
}
|
||||||
|
seq_printf(m, "pos:\t%lli\nflags:\t0%o\nmnt_id:\t%i\n",
|
||||||
|
(long long)file->f_pos, f_flags,
|
||||||
|
mnt->mnt_id);
|
||||||
|
#else
|
||||||
seq_printf(m, "pos:\t%lli\nflags:\t0%o\nmnt_id:\t%i\n",
|
seq_printf(m, "pos:\t%lli\nflags:\t0%o\nmnt_id:\t%i\n",
|
||||||
(long long)file->f_pos, f_flags,
|
(long long)file->f_pos, f_flags,
|
||||||
real_mount(file->f_path.mnt)->mnt_id);
|
real_mount(file->f_path.mnt)->mnt_id);
|
||||||
|
#endif
|
||||||
|
|
||||||
show_fd_locks(m, file, files);
|
show_fd_locks(m, file, files);
|
||||||
if (seq_has_overflowed(m))
|
if (seq_has_overflowed(m))
|
||||||
|
|||||||
@@ -21,12 +21,19 @@
|
|||||||
#include <linux/mm_inline.h>
|
#include <linux/mm_inline.h>
|
||||||
#include <linux/ctype.h>
|
#include <linux/ctype.h>
|
||||||
#include <linux/pkeys.h>
|
#include <linux/pkeys.h>
|
||||||
|
#if defined(CONFIG_KSU_SUSFS_SUS_KSTAT) || defined(CONFIG_KSU_SUSFS_SUS_MAP)
|
||||||
|
#include <linux/susfs_def.h>
|
||||||
|
#endif
|
||||||
|
|
||||||
#include <asm/elf.h>
|
#include <asm/elf.h>
|
||||||
#include <asm/tlb.h>
|
#include <asm/tlb.h>
|
||||||
#include <asm/tlbflush.h>
|
#include <asm/tlbflush.h>
|
||||||
#include "internal.h"
|
#include "internal.h"
|
||||||
|
|
||||||
|
#ifdef CONFIG_KSU_SUSFS_SUS_KSTAT
|
||||||
|
extern void susfs_sus_ino_for_show_map_vma(unsigned long ino, dev_t *out_dev, unsigned long *out_ino);
|
||||||
|
#endif
|
||||||
|
|
||||||
#define SEQ_PUT_DEC(str, val) \
|
#define SEQ_PUT_DEC(str, val) \
|
||||||
seq_put_decimal_ull_width(m, str, (val) << (PAGE_SHIFT-10), 8)
|
seq_put_decimal_ull_width(m, str, (val) << (PAGE_SHIFT-10), 8)
|
||||||
void task_mem(struct seq_file *m, struct mm_struct *mm)
|
void task_mem(struct seq_file *m, struct mm_struct *mm)
|
||||||
@@ -355,8 +362,35 @@ show_map_vma(struct seq_file *m, struct vm_area_struct *vma)
|
|||||||
|
|
||||||
if (file) {
|
if (file) {
|
||||||
struct inode *inode = file_inode(vma->vm_file);
|
struct inode *inode = file_inode(vma->vm_file);
|
||||||
|
#ifdef CONFIG_KSU_SUSFS_SUS_MAP
|
||||||
|
if (unlikely(inode->i_mapping->flags & BIT_SUS_MAPS) && susfs_is_current_proc_umounted()) {
|
||||||
|
seq_setwidth(m, 25 + sizeof(void *) * 6 - 1);
|
||||||
|
seq_put_hex_ll(m, NULL, vma->vm_start, 8);
|
||||||
|
seq_put_hex_ll(m, "-", vma->vm_end, 8);
|
||||||
|
seq_putc(m, ' ');
|
||||||
|
seq_putc(m, '-');
|
||||||
|
seq_putc(m, '-');
|
||||||
|
seq_putc(m, '-');
|
||||||
|
seq_putc(m, 'p');
|
||||||
|
seq_put_hex_ll(m, " ", pgoff, 8);
|
||||||
|
seq_put_hex_ll(m, " ", MAJOR(dev), 2);
|
||||||
|
seq_put_hex_ll(m, ":", MINOR(dev), 2);
|
||||||
|
seq_put_decimal_ull(m, " ", ino);
|
||||||
|
seq_putc(m, ' ');
|
||||||
|
goto done;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
#ifdef CONFIG_KSU_SUSFS_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;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
dev = inode->i_sb->s_dev;
|
dev = inode->i_sb->s_dev;
|
||||||
ino = inode->i_ino;
|
ino = inode->i_ino;
|
||||||
|
#ifdef CONFIG_KSU_SUSFS_SUS_KSTAT
|
||||||
|
bypass_orig_flow:
|
||||||
|
#endif
|
||||||
pgoff = ((loff_t)vma->vm_pgoff) << PAGE_SHIFT;
|
pgoff = ((loff_t)vma->vm_pgoff) << PAGE_SHIFT;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -871,6 +905,25 @@ static int show_smap(struct seq_file *m, void *v)
|
|||||||
|
|
||||||
memset(&mss, 0, sizeof(mss));
|
memset(&mss, 0, sizeof(mss));
|
||||||
|
|
||||||
|
#ifdef CONFIG_KSU_SUSFS_SUS_MAP
|
||||||
|
if (vma->vm_file &&
|
||||||
|
unlikely(file_inode(vma->vm_file)->i_mapping->flags & BIT_SUS_MAPS) &&
|
||||||
|
susfs_is_current_proc_umounted())
|
||||||
|
{
|
||||||
|
show_map_vma(m, vma);
|
||||||
|
SEQ_PUT_DEC("Size: ", vma->vm_end - vma->vm_start);
|
||||||
|
SEQ_PUT_DEC(" kB\nKernelPageSize: ", 4);
|
||||||
|
SEQ_PUT_DEC(" kB\nMMUPageSize: ", 4);
|
||||||
|
seq_puts(m, " kB\n");
|
||||||
|
__show_smap(m, &mss, false);
|
||||||
|
if (arch_pkeys_enabled())
|
||||||
|
seq_printf(m, "ProtectionKey: %8u\n", vma_pkey(vma));
|
||||||
|
seq_puts(m, "VmFlags: mr mw me");
|
||||||
|
seq_putc(m, '\n');
|
||||||
|
goto bypass_orig_flow;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
smap_gather_stats(vma, &mss);
|
smap_gather_stats(vma, &mss);
|
||||||
|
|
||||||
show_map_vma(m, vma);
|
show_map_vma(m, vma);
|
||||||
@@ -891,8 +944,11 @@ static int show_smap(struct seq_file *m, void *v)
|
|||||||
seq_printf(m, "ProtectionKey: %8u\n", vma_pkey(vma));
|
seq_printf(m, "ProtectionKey: %8u\n", vma_pkey(vma));
|
||||||
show_smap_vma_flags(m, vma);
|
show_smap_vma_flags(m, vma);
|
||||||
|
|
||||||
|
#ifdef CONFIG_KSU_SUSFS_SUS_MAP
|
||||||
|
bypass_orig_flow:
|
||||||
|
#endif
|
||||||
m_cache_vma(m, vma);
|
m_cache_vma(m, vma);
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -921,7 +977,19 @@ static int show_smaps_rollup(struct seq_file *m, void *v)
|
|||||||
hold_task_mempolicy(priv);
|
hold_task_mempolicy(priv);
|
||||||
|
|
||||||
for (vma = priv->mm->mmap; vma; vma = vma->vm_next) {
|
for (vma = priv->mm->mmap; vma; vma = vma->vm_next) {
|
||||||
|
#ifdef CONFIG_KSU_SUSFS_SUS_MAP
|
||||||
|
if (vma->vm_file &&
|
||||||
|
unlikely(file_inode(vma->vm_file)->i_mapping->flags & BIT_SUS_MAPS) &&
|
||||||
|
susfs_is_current_proc_umounted())
|
||||||
|
{
|
||||||
|
memset(&mss, 0, sizeof(mss));
|
||||||
|
goto bypass_orig_flow;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
smap_gather_stats(vma, &mss);
|
smap_gather_stats(vma, &mss);
|
||||||
|
#ifdef CONFIG_KSU_SUSFS_SUS_MAP
|
||||||
|
bypass_orig_flow:
|
||||||
|
#endif
|
||||||
last_vma_end = vma->vm_end;
|
last_vma_end = vma->vm_end;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1567,6 +1635,9 @@ static ssize_t pagemap_read(struct file *file, char __user *buf,
|
|||||||
unsigned long start_vaddr;
|
unsigned long start_vaddr;
|
||||||
unsigned long end_vaddr;
|
unsigned long end_vaddr;
|
||||||
int ret = 0, copied = 0;
|
int ret = 0, copied = 0;
|
||||||
|
#ifdef CONFIG_KSU_SUSFS_SUS_MAP
|
||||||
|
struct vm_area_struct *vma;
|
||||||
|
#endif
|
||||||
|
|
||||||
if (!mm || !mmget_not_zero(mm))
|
if (!mm || !mmget_not_zero(mm))
|
||||||
goto out;
|
goto out;
|
||||||
@@ -1625,6 +1696,16 @@ static ssize_t pagemap_read(struct file *file, char __user *buf,
|
|||||||
down_read(&mm->mmap_sem);
|
down_read(&mm->mmap_sem);
|
||||||
ret = walk_page_range(start_vaddr, end, &pagemap_walk);
|
ret = walk_page_range(start_vaddr, end, &pagemap_walk);
|
||||||
up_read(&mm->mmap_sem);
|
up_read(&mm->mmap_sem);
|
||||||
|
#ifdef CONFIG_KSU_SUSFS_SUS_MAP
|
||||||
|
vma = find_vma(mm, start_vaddr);
|
||||||
|
if (vma && vma->vm_file) {
|
||||||
|
struct inode *inode = file_inode(vma->vm_file);
|
||||||
|
if (unlikely(inode->i_mapping->flags & BIT_SUS_MAPS) && susfs_is_current_proc_umounted()) {
|
||||||
|
pm.show_pfn = false;
|
||||||
|
pm.buffer->pme = 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#endif
|
||||||
start_vaddr = end;
|
start_vaddr = end;
|
||||||
|
|
||||||
len = min(count, PM_ENTRY_BYTES * pm.pos);
|
len = min(count, PM_ENTRY_BYTES * pm.pos);
|
||||||
|
|||||||
@@ -12,12 +12,20 @@
|
|||||||
#include <linux/security.h>
|
#include <linux/security.h>
|
||||||
#include <linux/fs_struct.h>
|
#include <linux/fs_struct.h>
|
||||||
#include <linux/sched/task.h>
|
#include <linux/sched/task.h>
|
||||||
|
#ifdef CONFIG_KSU_SUSFS_SUS_MOUNT
|
||||||
|
#include <linux/susfs_def.h>
|
||||||
|
#endif
|
||||||
|
|
||||||
#include "proc/internal.h" /* only for get_proc_task() in ->open() */
|
#include "proc/internal.h" /* only for get_proc_task() in ->open() */
|
||||||
|
|
||||||
#include "pnode.h"
|
#include "pnode.h"
|
||||||
#include "internal.h"
|
#include "internal.h"
|
||||||
|
|
||||||
|
#ifdef CONFIG_KSU_SUSFS_SUS_MOUNT
|
||||||
|
extern bool susfs_is_current_ksu_domain(void);
|
||||||
|
bool susfs_hide_sus_mnts_for_all_procs = true; // hide sus mounts for all processes by default
|
||||||
|
#endif
|
||||||
|
|
||||||
static unsigned mounts_poll(struct file *file, poll_table *wait)
|
static unsigned mounts_poll(struct file *file, poll_table *wait)
|
||||||
{
|
{
|
||||||
struct seq_file *m = file->private_data;
|
struct seq_file *m = file->private_data;
|
||||||
@@ -102,6 +110,11 @@ static int show_vfsmnt(struct seq_file *m, struct vfsmount *mnt)
|
|||||||
struct super_block *sb = mnt_path.dentry->d_sb;
|
struct super_block *sb = mnt_path.dentry->d_sb;
|
||||||
int err;
|
int err;
|
||||||
|
|
||||||
|
#ifdef CONFIG_KSU_SUSFS_SUS_MOUNT
|
||||||
|
if (susfs_hide_sus_mnts_for_all_procs && r->mnt_id >= DEFAULT_SUS_MNT_ID)
|
||||||
|
return 0;
|
||||||
|
#endif
|
||||||
|
|
||||||
if (sb->s_op->show_devname) {
|
if (sb->s_op->show_devname) {
|
||||||
err = sb->s_op->show_devname(m, mnt_path.dentry);
|
err = sb->s_op->show_devname(m, mnt_path.dentry);
|
||||||
if (err)
|
if (err)
|
||||||
@@ -138,6 +151,11 @@ static int show_mountinfo(struct seq_file *m, struct vfsmount *mnt)
|
|||||||
struct path mnt_path = { .dentry = mnt->mnt_root, .mnt = mnt };
|
struct path mnt_path = { .dentry = mnt->mnt_root, .mnt = mnt };
|
||||||
int err;
|
int err;
|
||||||
|
|
||||||
|
#ifdef CONFIG_KSU_SUSFS_SUS_MOUNT
|
||||||
|
if (susfs_hide_sus_mnts_for_all_procs && r->mnt_id >= DEFAULT_SUS_MNT_ID)
|
||||||
|
return 0;
|
||||||
|
#endif
|
||||||
|
|
||||||
seq_printf(m, "%i %i %u:%u ", r->mnt_id, r->mnt_parent->mnt_id,
|
seq_printf(m, "%i %i %u:%u ", r->mnt_id, r->mnt_parent->mnt_id,
|
||||||
MAJOR(sb->s_dev), MINOR(sb->s_dev));
|
MAJOR(sb->s_dev), MINOR(sb->s_dev));
|
||||||
if (sb->s_op->show_path) {
|
if (sb->s_op->show_path) {
|
||||||
@@ -202,6 +220,11 @@ static int show_vfsstat(struct seq_file *m, struct vfsmount *mnt)
|
|||||||
struct super_block *sb = mnt_path.dentry->d_sb;
|
struct super_block *sb = mnt_path.dentry->d_sb;
|
||||||
int err;
|
int err;
|
||||||
|
|
||||||
|
#ifdef CONFIG_KSU_SUSFS_SUS_MOUNT
|
||||||
|
if (susfs_hide_sus_mnts_for_all_procs && r->mnt_id >= DEFAULT_SUS_MNT_ID)
|
||||||
|
return 0;
|
||||||
|
#endif
|
||||||
|
|
||||||
/* device */
|
/* device */
|
||||||
if (sb->s_op->show_devname) {
|
if (sb->s_op->show_devname) {
|
||||||
seq_puts(m, "device ");
|
seq_puts(m, "device ");
|
||||||
|
|||||||
279
fs/readdir.c
279
fs/readdir.c
@@ -23,6 +23,14 @@
|
|||||||
|
|
||||||
#include <linux/uaccess.h>
|
#include <linux/uaccess.h>
|
||||||
|
|
||||||
|
#ifdef CONFIG_KSU_SUSFS_SUS_PATH
|
||||||
|
#include <linux/susfs_def.h>
|
||||||
|
extern bool susfs_is_inode_sus_path(struct inode *inode);
|
||||||
|
extern bool susfs_is_sus_android_data_d_name_found(const char *d_name);
|
||||||
|
extern bool susfs_is_sus_sdcard_d_name_found(const char *d_name);
|
||||||
|
extern bool susfs_is_base_dentry_android_data_dir(struct dentry* base);
|
||||||
|
extern bool susfs_is_base_dentry_sdcard_dir(struct dentry* base);
|
||||||
|
#endif
|
||||||
int iterate_dir(struct file *file, struct dir_context *ctx)
|
int iterate_dir(struct file *file, struct dir_context *ctx)
|
||||||
{
|
{
|
||||||
struct inode *inode = file_inode(file);
|
struct inode *inode = file_inode(file);
|
||||||
@@ -120,6 +128,11 @@ struct old_linux_dirent {
|
|||||||
struct readdir_callback {
|
struct readdir_callback {
|
||||||
struct dir_context ctx;
|
struct dir_context ctx;
|
||||||
struct old_linux_dirent __user * dirent;
|
struct old_linux_dirent __user * dirent;
|
||||||
|
#ifdef CONFIG_KSU_SUSFS_SUS_PATH
|
||||||
|
struct super_block *sb;
|
||||||
|
bool is_base_dentry_android_data_root_dir;
|
||||||
|
bool is_base_dentry_sdcard_root_dir;
|
||||||
|
#endif
|
||||||
int result;
|
int result;
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -130,6 +143,9 @@ static int fillonedir(struct dir_context *ctx, const char *name, int namlen,
|
|||||||
container_of(ctx, struct readdir_callback, ctx);
|
container_of(ctx, struct readdir_callback, ctx);
|
||||||
struct old_linux_dirent __user * dirent;
|
struct old_linux_dirent __user * dirent;
|
||||||
unsigned long d_ino;
|
unsigned long d_ino;
|
||||||
|
#ifdef CONFIG_KSU_SUSFS_SUS_PATH
|
||||||
|
struct inode *inode;
|
||||||
|
#endif
|
||||||
|
|
||||||
if (buf->result)
|
if (buf->result)
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
@@ -141,6 +157,28 @@ static int fillonedir(struct dir_context *ctx, const char *name, int namlen,
|
|||||||
buf->result = -EOVERFLOW;
|
buf->result = -EOVERFLOW;
|
||||||
return -EOVERFLOW;
|
return -EOVERFLOW;
|
||||||
}
|
}
|
||||||
|
#ifdef CONFIG_KSU_SUSFS_SUS_PATH
|
||||||
|
if (buf->is_base_dentry_android_data_root_dir) {
|
||||||
|
if (susfs_is_sus_android_data_d_name_found(name)) {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
} else if (buf->is_base_dentry_sdcard_root_dir) {
|
||||||
|
if (susfs_is_sus_sdcard_d_name_found(name)) {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
inode = ilookup(buf->sb, ino);
|
||||||
|
if (!inode) {
|
||||||
|
goto orig_flow;
|
||||||
|
}
|
||||||
|
if (susfs_is_inode_sus_path(inode)) {
|
||||||
|
iput(inode);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
iput(inode);
|
||||||
|
orig_flow:
|
||||||
|
#endif
|
||||||
buf->result++;
|
buf->result++;
|
||||||
dirent = buf->dirent;
|
dirent = buf->dirent;
|
||||||
if (!access_ok(VERIFY_WRITE, dirent,
|
if (!access_ok(VERIFY_WRITE, dirent,
|
||||||
@@ -168,9 +206,33 @@ SYSCALL_DEFINE3(old_readdir, unsigned int, fd,
|
|||||||
.ctx.actor = fillonedir,
|
.ctx.actor = fillonedir,
|
||||||
.dirent = dirent
|
.dirent = dirent
|
||||||
};
|
};
|
||||||
|
#ifdef CONFIG_KSU_SUSFS_SUS_PATH
|
||||||
|
struct inode *inode;
|
||||||
|
#endif
|
||||||
|
|
||||||
if (!f.file)
|
if (!f.file)
|
||||||
return -EBADF;
|
return -EBADF;
|
||||||
|
#ifdef CONFIG_KSU_SUSFS_SUS_PATH
|
||||||
|
buf.sb = f.file->f_inode->i_sb;
|
||||||
|
inode = f.file->f_path.dentry->d_inode;
|
||||||
|
if (f.file->f_path.dentry && inode) {
|
||||||
|
if (susfs_is_base_dentry_android_data_dir(f.file->f_path.dentry))
|
||||||
|
{
|
||||||
|
buf.is_base_dentry_android_data_root_dir = true;
|
||||||
|
buf.is_base_dentry_sdcard_root_dir = false;
|
||||||
|
goto orig_flow;
|
||||||
|
}
|
||||||
|
if (susfs_is_base_dentry_sdcard_dir(f.file->f_path.dentry))
|
||||||
|
{
|
||||||
|
buf.is_base_dentry_sdcard_root_dir = true;
|
||||||
|
buf.is_base_dentry_android_data_root_dir = false;
|
||||||
|
goto orig_flow;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
buf.is_base_dentry_android_data_root_dir = false;
|
||||||
|
buf.is_base_dentry_sdcard_root_dir = false;
|
||||||
|
orig_flow:
|
||||||
|
#endif
|
||||||
|
|
||||||
error = iterate_dir(f.file, &buf.ctx);
|
error = iterate_dir(f.file, &buf.ctx);
|
||||||
if (buf.result)
|
if (buf.result)
|
||||||
@@ -197,6 +259,11 @@ struct getdents_callback {
|
|||||||
struct dir_context ctx;
|
struct dir_context ctx;
|
||||||
struct linux_dirent __user * current_dir;
|
struct linux_dirent __user * current_dir;
|
||||||
struct linux_dirent __user * previous;
|
struct linux_dirent __user * previous;
|
||||||
|
#ifdef CONFIG_KSU_SUSFS_SUS_PATH
|
||||||
|
struct super_block *sb;
|
||||||
|
bool is_base_dentry_android_data_root_dir;
|
||||||
|
bool is_base_dentry_sdcard_root_dir;
|
||||||
|
#endif
|
||||||
int count;
|
int count;
|
||||||
int error;
|
int error;
|
||||||
};
|
};
|
||||||
@@ -210,6 +277,9 @@ static int filldir(struct dir_context *ctx, const char *name, int namlen,
|
|||||||
unsigned long d_ino;
|
unsigned long d_ino;
|
||||||
int reclen = ALIGN(offsetof(struct linux_dirent, d_name) + namlen + 2,
|
int reclen = ALIGN(offsetof(struct linux_dirent, d_name) + namlen + 2,
|
||||||
sizeof(long));
|
sizeof(long));
|
||||||
|
#ifdef CONFIG_KSU_SUSFS_SUS_PATH
|
||||||
|
struct inode *inode;
|
||||||
|
#endif
|
||||||
|
|
||||||
buf->error = verify_dirent_name(name, namlen);
|
buf->error = verify_dirent_name(name, namlen);
|
||||||
if (unlikely(buf->error))
|
if (unlikely(buf->error))
|
||||||
@@ -222,6 +292,28 @@ static int filldir(struct dir_context *ctx, const char *name, int namlen,
|
|||||||
buf->error = -EOVERFLOW;
|
buf->error = -EOVERFLOW;
|
||||||
return -EOVERFLOW;
|
return -EOVERFLOW;
|
||||||
}
|
}
|
||||||
|
#ifdef CONFIG_KSU_SUSFS_SUS_PATH
|
||||||
|
if (buf->is_base_dentry_android_data_root_dir) {
|
||||||
|
if (susfs_is_sus_android_data_d_name_found(name)) {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
} else if (buf->is_base_dentry_sdcard_root_dir) {
|
||||||
|
if (susfs_is_sus_sdcard_d_name_found(name)) {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
inode = ilookup(buf->sb, ino);
|
||||||
|
if (!inode) {
|
||||||
|
goto orig_flow;
|
||||||
|
}
|
||||||
|
if (susfs_is_inode_sus_path(inode)) {
|
||||||
|
iput(inode);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
iput(inode);
|
||||||
|
orig_flow:
|
||||||
|
#endif
|
||||||
dirent = buf->previous;
|
dirent = buf->previous;
|
||||||
if (dirent) {
|
if (dirent) {
|
||||||
if (signal_pending(current))
|
if (signal_pending(current))
|
||||||
@@ -261,6 +353,9 @@ SYSCALL_DEFINE3(getdents, unsigned int, fd,
|
|||||||
.current_dir = dirent
|
.current_dir = dirent
|
||||||
};
|
};
|
||||||
int error;
|
int error;
|
||||||
|
#ifdef CONFIG_KSU_SUSFS_SUS_PATH
|
||||||
|
struct inode *inode;
|
||||||
|
#endif
|
||||||
|
|
||||||
if (!access_ok(VERIFY_WRITE, dirent, count))
|
if (!access_ok(VERIFY_WRITE, dirent, count))
|
||||||
return -EFAULT;
|
return -EFAULT;
|
||||||
@@ -268,6 +363,27 @@ SYSCALL_DEFINE3(getdents, unsigned int, fd,
|
|||||||
f = fdget_pos(fd);
|
f = fdget_pos(fd);
|
||||||
if (!f.file)
|
if (!f.file)
|
||||||
return -EBADF;
|
return -EBADF;
|
||||||
|
#ifdef CONFIG_KSU_SUSFS_SUS_PATH
|
||||||
|
buf.sb = f.file->f_inode->i_sb;
|
||||||
|
inode = f.file->f_path.dentry->d_inode;
|
||||||
|
if (f.file->f_path.dentry && inode) {
|
||||||
|
if (susfs_is_base_dentry_android_data_dir(f.file->f_path.dentry))
|
||||||
|
{
|
||||||
|
buf.is_base_dentry_android_data_root_dir = true;
|
||||||
|
buf.is_base_dentry_sdcard_root_dir = false;
|
||||||
|
goto orig_flow;
|
||||||
|
}
|
||||||
|
if (susfs_is_base_dentry_sdcard_dir(f.file->f_path.dentry))
|
||||||
|
{
|
||||||
|
buf.is_base_dentry_sdcard_root_dir = true;
|
||||||
|
buf.is_base_dentry_android_data_root_dir = false;
|
||||||
|
goto orig_flow;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
buf.is_base_dentry_android_data_root_dir = false;
|
||||||
|
buf.is_base_dentry_sdcard_root_dir = false;
|
||||||
|
orig_flow:
|
||||||
|
#endif
|
||||||
|
|
||||||
error = iterate_dir(f.file, &buf.ctx);
|
error = iterate_dir(f.file, &buf.ctx);
|
||||||
if (error >= 0)
|
if (error >= 0)
|
||||||
@@ -287,6 +403,11 @@ struct getdents_callback64 {
|
|||||||
struct dir_context ctx;
|
struct dir_context ctx;
|
||||||
struct linux_dirent64 __user * current_dir;
|
struct linux_dirent64 __user * current_dir;
|
||||||
struct linux_dirent64 __user * previous;
|
struct linux_dirent64 __user * previous;
|
||||||
|
#ifdef CONFIG_KSU_SUSFS_SUS_PATH
|
||||||
|
struct super_block *sb;
|
||||||
|
bool is_base_dentry_android_data_root_dir;
|
||||||
|
bool is_base_dentry_sdcard_root_dir;
|
||||||
|
#endif
|
||||||
int count;
|
int count;
|
||||||
int error;
|
int error;
|
||||||
};
|
};
|
||||||
@@ -299,6 +420,9 @@ static int filldir64(struct dir_context *ctx, const char *name, int namlen,
|
|||||||
container_of(ctx, struct getdents_callback64, ctx);
|
container_of(ctx, struct getdents_callback64, ctx);
|
||||||
int reclen = ALIGN(offsetof(struct linux_dirent64, d_name) + namlen + 1,
|
int reclen = ALIGN(offsetof(struct linux_dirent64, d_name) + namlen + 1,
|
||||||
sizeof(u64));
|
sizeof(u64));
|
||||||
|
#ifdef CONFIG_KSU_SUSFS_SUS_PATH
|
||||||
|
struct inode *inode;
|
||||||
|
#endif
|
||||||
|
|
||||||
buf->error = verify_dirent_name(name, namlen);
|
buf->error = verify_dirent_name(name, namlen);
|
||||||
if (unlikely(buf->error))
|
if (unlikely(buf->error))
|
||||||
@@ -313,6 +437,28 @@ static int filldir64(struct dir_context *ctx, const char *name, int namlen,
|
|||||||
if (__put_user(offset, &dirent->d_off))
|
if (__put_user(offset, &dirent->d_off))
|
||||||
goto efault;
|
goto efault;
|
||||||
}
|
}
|
||||||
|
#ifdef CONFIG_KSU_SUSFS_SUS_PATH
|
||||||
|
if (buf->is_base_dentry_android_data_root_dir) {
|
||||||
|
if (susfs_is_sus_android_data_d_name_found(name)) {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
} else if (buf->is_base_dentry_sdcard_root_dir) {
|
||||||
|
if (susfs_is_sus_sdcard_d_name_found(name)) {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
inode = ilookup(buf->sb, ino);
|
||||||
|
if (!inode) {
|
||||||
|
goto orig_flow;
|
||||||
|
}
|
||||||
|
if (susfs_is_inode_sus_path(inode)) {
|
||||||
|
iput(inode);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
iput(inode);
|
||||||
|
orig_flow:
|
||||||
|
#endif
|
||||||
dirent = buf->current_dir;
|
dirent = buf->current_dir;
|
||||||
if (__put_user(ino, &dirent->d_ino))
|
if (__put_user(ino, &dirent->d_ino))
|
||||||
goto efault;
|
goto efault;
|
||||||
@@ -347,6 +493,9 @@ SYSCALL_DEFINE3(getdents64, unsigned int, fd,
|
|||||||
.current_dir = dirent
|
.current_dir = dirent
|
||||||
};
|
};
|
||||||
int error;
|
int error;
|
||||||
|
#ifdef CONFIG_KSU_SUSFS_SUS_PATH
|
||||||
|
struct inode *inode;
|
||||||
|
#endif
|
||||||
|
|
||||||
if (!access_ok(VERIFY_WRITE, dirent, count))
|
if (!access_ok(VERIFY_WRITE, dirent, count))
|
||||||
return -EFAULT;
|
return -EFAULT;
|
||||||
@@ -354,7 +503,27 @@ SYSCALL_DEFINE3(getdents64, unsigned int, fd,
|
|||||||
f = fdget_pos(fd);
|
f = fdget_pos(fd);
|
||||||
if (!f.file)
|
if (!f.file)
|
||||||
return -EBADF;
|
return -EBADF;
|
||||||
|
#ifdef CONFIG_KSU_SUSFS_SUS_PATH
|
||||||
|
buf.sb = f.file->f_inode->i_sb;
|
||||||
|
inode = f.file->f_path.dentry->d_inode;
|
||||||
|
if (f.file->f_path.dentry && inode) {
|
||||||
|
if (susfs_is_base_dentry_android_data_dir(f.file->f_path.dentry))
|
||||||
|
{
|
||||||
|
buf.is_base_dentry_android_data_root_dir = true;
|
||||||
|
buf.is_base_dentry_sdcard_root_dir = false;
|
||||||
|
goto orig_flow;
|
||||||
|
}
|
||||||
|
if (susfs_is_base_dentry_sdcard_dir(f.file->f_path.dentry))
|
||||||
|
{
|
||||||
|
buf.is_base_dentry_sdcard_root_dir = true;
|
||||||
|
buf.is_base_dentry_android_data_root_dir = false;
|
||||||
|
goto orig_flow;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
buf.is_base_dentry_android_data_root_dir = false;
|
||||||
|
buf.is_base_dentry_sdcard_root_dir = false;
|
||||||
|
orig_flow:
|
||||||
|
#endif
|
||||||
error = iterate_dir(f.file, &buf.ctx);
|
error = iterate_dir(f.file, &buf.ctx);
|
||||||
if (error >= 0)
|
if (error >= 0)
|
||||||
error = buf.error;
|
error = buf.error;
|
||||||
@@ -381,6 +550,11 @@ struct compat_old_linux_dirent {
|
|||||||
struct compat_readdir_callback {
|
struct compat_readdir_callback {
|
||||||
struct dir_context ctx;
|
struct dir_context ctx;
|
||||||
struct compat_old_linux_dirent __user *dirent;
|
struct compat_old_linux_dirent __user *dirent;
|
||||||
|
#ifdef CONFIG_KSU_SUSFS_SUS_PATH
|
||||||
|
struct super_block *sb;
|
||||||
|
bool is_base_dentry_android_data_root_dir;
|
||||||
|
bool is_base_dentry_sdcard_root_dir;
|
||||||
|
#endif
|
||||||
int result;
|
int result;
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -392,6 +566,9 @@ static int compat_fillonedir(struct dir_context *ctx, const char *name,
|
|||||||
container_of(ctx, struct compat_readdir_callback, ctx);
|
container_of(ctx, struct compat_readdir_callback, ctx);
|
||||||
struct compat_old_linux_dirent __user *dirent;
|
struct compat_old_linux_dirent __user *dirent;
|
||||||
compat_ulong_t d_ino;
|
compat_ulong_t d_ino;
|
||||||
|
#ifdef CONFIG_KSU_SUSFS_SUS_PATH
|
||||||
|
struct inode *inode;
|
||||||
|
#endif
|
||||||
|
|
||||||
if (buf->result)
|
if (buf->result)
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
@@ -403,6 +580,28 @@ static int compat_fillonedir(struct dir_context *ctx, const char *name,
|
|||||||
buf->result = -EOVERFLOW;
|
buf->result = -EOVERFLOW;
|
||||||
return -EOVERFLOW;
|
return -EOVERFLOW;
|
||||||
}
|
}
|
||||||
|
#ifdef CONFIG_KSU_SUSFS_SUS_PATH
|
||||||
|
if (buf->is_base_dentry_android_data_root_dir) {
|
||||||
|
if (susfs_is_sus_android_data_d_name_found(name)) {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
} else if (buf->is_base_dentry_sdcard_root_dir) {
|
||||||
|
if (susfs_is_sus_sdcard_d_name_found(name)) {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
inode = ilookup(buf->sb, ino);
|
||||||
|
if (!inode) {
|
||||||
|
goto orig_flow;
|
||||||
|
}
|
||||||
|
if (susfs_is_inode_sus_path(inode)) {
|
||||||
|
iput(inode);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
iput(inode);
|
||||||
|
orig_flow:
|
||||||
|
#endif
|
||||||
buf->result++;
|
buf->result++;
|
||||||
dirent = buf->dirent;
|
dirent = buf->dirent;
|
||||||
if (!access_ok(VERIFY_WRITE, dirent,
|
if (!access_ok(VERIFY_WRITE, dirent,
|
||||||
@@ -430,9 +629,33 @@ COMPAT_SYSCALL_DEFINE3(old_readdir, unsigned int, fd,
|
|||||||
.ctx.actor = compat_fillonedir,
|
.ctx.actor = compat_fillonedir,
|
||||||
.dirent = dirent
|
.dirent = dirent
|
||||||
};
|
};
|
||||||
|
#ifdef CONFIG_KSU_SUSFS_SUS_PATH
|
||||||
|
struct inode *inode;
|
||||||
|
#endif
|
||||||
|
|
||||||
if (!f.file)
|
if (!f.file)
|
||||||
return -EBADF;
|
return -EBADF;
|
||||||
|
#ifdef CONFIG_KSU_SUSFS_SUS_PATH
|
||||||
|
buf.sb = f.file->f_inode->i_sb;
|
||||||
|
inode = f.file->f_path.dentry->d_inode;
|
||||||
|
if (f.file->f_path.dentry && inode) {
|
||||||
|
if (susfs_is_base_dentry_android_data_dir(f.file->f_path.dentry))
|
||||||
|
{
|
||||||
|
buf.is_base_dentry_android_data_root_dir = true;
|
||||||
|
buf.is_base_dentry_sdcard_root_dir = false;
|
||||||
|
goto orig_flow;
|
||||||
|
}
|
||||||
|
if (susfs_is_base_dentry_sdcard_dir(f.file->f_path.dentry))
|
||||||
|
{
|
||||||
|
buf.is_base_dentry_sdcard_root_dir = true;
|
||||||
|
buf.is_base_dentry_android_data_root_dir = false;
|
||||||
|
goto orig_flow;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
buf.is_base_dentry_android_data_root_dir = false;
|
||||||
|
buf.is_base_dentry_sdcard_root_dir = false;
|
||||||
|
orig_flow:
|
||||||
|
#endif
|
||||||
|
|
||||||
error = iterate_dir(f.file, &buf.ctx);
|
error = iterate_dir(f.file, &buf.ctx);
|
||||||
if (buf.result)
|
if (buf.result)
|
||||||
@@ -453,6 +676,11 @@ struct compat_getdents_callback {
|
|||||||
struct dir_context ctx;
|
struct dir_context ctx;
|
||||||
struct compat_linux_dirent __user *current_dir;
|
struct compat_linux_dirent __user *current_dir;
|
||||||
struct compat_linux_dirent __user *previous;
|
struct compat_linux_dirent __user *previous;
|
||||||
|
#ifdef CONFIG_KSU_SUSFS_SUS_PATH
|
||||||
|
struct super_block *sb;
|
||||||
|
bool is_base_dentry_android_data_root_dir;
|
||||||
|
bool is_base_dentry_sdcard_root_dir;
|
||||||
|
#endif
|
||||||
int count;
|
int count;
|
||||||
int error;
|
int error;
|
||||||
};
|
};
|
||||||
@@ -466,6 +694,9 @@ static int compat_filldir(struct dir_context *ctx, const char *name, int namlen,
|
|||||||
compat_ulong_t d_ino;
|
compat_ulong_t d_ino;
|
||||||
int reclen = ALIGN(offsetof(struct compat_linux_dirent, d_name) +
|
int reclen = ALIGN(offsetof(struct compat_linux_dirent, d_name) +
|
||||||
namlen + 2, sizeof(compat_long_t));
|
namlen + 2, sizeof(compat_long_t));
|
||||||
|
#ifdef CONFIG_KSU_SUSFS_SUS_PATH
|
||||||
|
struct inode *inode;
|
||||||
|
#endif
|
||||||
|
|
||||||
buf->error = -EINVAL; /* only used if we fail.. */
|
buf->error = -EINVAL; /* only used if we fail.. */
|
||||||
if (reclen > buf->count)
|
if (reclen > buf->count)
|
||||||
@@ -475,6 +706,28 @@ static int compat_filldir(struct dir_context *ctx, const char *name, int namlen,
|
|||||||
buf->error = -EOVERFLOW;
|
buf->error = -EOVERFLOW;
|
||||||
return -EOVERFLOW;
|
return -EOVERFLOW;
|
||||||
}
|
}
|
||||||
|
#ifdef CONFIG_KSU_SUSFS_SUS_PATH
|
||||||
|
if (buf->is_base_dentry_android_data_root_dir) {
|
||||||
|
if (susfs_is_sus_android_data_d_name_found(name)) {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
} else if (buf->is_base_dentry_sdcard_root_dir) {
|
||||||
|
if (susfs_is_sus_sdcard_d_name_found(name)) {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
inode = ilookup(buf->sb, ino);
|
||||||
|
if (!inode) {
|
||||||
|
goto orig_flow;
|
||||||
|
}
|
||||||
|
if (susfs_is_inode_sus_path(inode)) {
|
||||||
|
iput(inode);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
iput(inode);
|
||||||
|
orig_flow:
|
||||||
|
#endif
|
||||||
dirent = buf->previous;
|
dirent = buf->previous;
|
||||||
if (dirent) {
|
if (dirent) {
|
||||||
if (signal_pending(current))
|
if (signal_pending(current))
|
||||||
@@ -514,6 +767,9 @@ COMPAT_SYSCALL_DEFINE3(getdents, unsigned int, fd,
|
|||||||
.count = count
|
.count = count
|
||||||
};
|
};
|
||||||
int error;
|
int error;
|
||||||
|
#ifdef CONFIG_KSU_SUSFS_SUS_PATH
|
||||||
|
struct inode *inode;
|
||||||
|
#endif
|
||||||
|
|
||||||
if (!access_ok(VERIFY_WRITE, dirent, count))
|
if (!access_ok(VERIFY_WRITE, dirent, count))
|
||||||
return -EFAULT;
|
return -EFAULT;
|
||||||
@@ -521,6 +777,27 @@ COMPAT_SYSCALL_DEFINE3(getdents, unsigned int, fd,
|
|||||||
f = fdget_pos(fd);
|
f = fdget_pos(fd);
|
||||||
if (!f.file)
|
if (!f.file)
|
||||||
return -EBADF;
|
return -EBADF;
|
||||||
|
#ifdef CONFIG_KSU_SUSFS_SUS_PATH
|
||||||
|
buf.sb = f.file->f_inode->i_sb;
|
||||||
|
inode = f.file->f_path.dentry->d_inode;
|
||||||
|
if (f.file->f_path.dentry && inode) {
|
||||||
|
if (susfs_is_base_dentry_android_data_dir(f.file->f_path.dentry))
|
||||||
|
{
|
||||||
|
buf.is_base_dentry_android_data_root_dir = true;
|
||||||
|
buf.is_base_dentry_sdcard_root_dir = false;
|
||||||
|
goto orig_flow;
|
||||||
|
}
|
||||||
|
if (susfs_is_base_dentry_sdcard_dir(f.file->f_path.dentry))
|
||||||
|
{
|
||||||
|
buf.is_base_dentry_sdcard_root_dir = true;
|
||||||
|
buf.is_base_dentry_android_data_root_dir = false;
|
||||||
|
goto orig_flow;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
buf.is_base_dentry_android_data_root_dir = false;
|
||||||
|
buf.is_base_dentry_sdcard_root_dir = false;
|
||||||
|
orig_flow:
|
||||||
|
#endif
|
||||||
|
|
||||||
error = iterate_dir(f.file, &buf.ctx);
|
error = iterate_dir(f.file, &buf.ctx);
|
||||||
if (error >= 0)
|
if (error >= 0)
|
||||||
|
|||||||
18
fs/stat.c
18
fs/stat.c
@@ -17,6 +17,9 @@
|
|||||||
#include <linux/syscalls.h>
|
#include <linux/syscalls.h>
|
||||||
#include <linux/pagemap.h>
|
#include <linux/pagemap.h>
|
||||||
#include <linux/compat.h>
|
#include <linux/compat.h>
|
||||||
|
#if defined(CONFIG_KSU_SUSFS_SUS_KSTAT) || defined(CONFIG_KSU_SUSFS_SUS_MOUNT)
|
||||||
|
#include <linux/susfs_def.h>
|
||||||
|
#endif
|
||||||
|
|
||||||
#include <linux/uaccess.h>
|
#include <linux/uaccess.h>
|
||||||
#include <asm/unistd.h>
|
#include <asm/unistd.h>
|
||||||
@@ -30,8 +33,23 @@
|
|||||||
* found on the VFS inode structure. This is the default if no getattr inode
|
* found on the VFS inode structure. This is the default if no getattr inode
|
||||||
* operation is supplied.
|
* operation is supplied.
|
||||||
*/
|
*/
|
||||||
|
#ifdef CONFIG_KSU_SUSFS_SUS_KSTAT
|
||||||
|
extern void susfs_sus_ino_for_generic_fillattr(unsigned long ino, struct kstat *stat);
|
||||||
|
#endif
|
||||||
|
|
||||||
void generic_fillattr(struct inode *inode, struct kstat *stat)
|
void generic_fillattr(struct inode *inode, struct kstat *stat)
|
||||||
{
|
{
|
||||||
|
#ifdef CONFIG_KSU_SUSFS_SUS_KSTAT
|
||||||
|
if (likely(susfs_is_current_proc_umounted()) &&
|
||||||
|
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;
|
||||||
|
stat->uid = inode->i_uid;
|
||||||
|
stat->gid = inode->i_gid;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
stat->dev = inode->i_sb->s_dev;
|
stat->dev = inode->i_sb->s_dev;
|
||||||
stat->ino = inode->i_ino;
|
stat->ino = inode->i_ino;
|
||||||
stat->mode = inode->i_mode;
|
stat->mode = inode->i_mode;
|
||||||
|
|||||||
21
fs/statfs.c
21
fs/statfs.c
@@ -9,6 +9,10 @@
|
|||||||
#include <linux/security.h>
|
#include <linux/security.h>
|
||||||
#include <linux/uaccess.h>
|
#include <linux/uaccess.h>
|
||||||
#include <linux/compat.h>
|
#include <linux/compat.h>
|
||||||
|
#ifdef CONFIG_KSU_SUSFS_SUS_MOUNT
|
||||||
|
#include <linux/susfs_def.h>
|
||||||
|
#include "mount.h"
|
||||||
|
#endif
|
||||||
#include "internal.h"
|
#include "internal.h"
|
||||||
|
|
||||||
static int flags_by_mnt(int mnt_flags)
|
static int flags_by_mnt(int mnt_flags)
|
||||||
@@ -70,11 +74,23 @@ static int statfs_by_dentry(struct dentry *dentry, struct kstatfs *buf)
|
|||||||
int vfs_statfs(const struct path *path, struct kstatfs *buf)
|
int vfs_statfs(const struct path *path, struct kstatfs *buf)
|
||||||
{
|
{
|
||||||
int error;
|
int error;
|
||||||
|
#ifdef CONFIG_KSU_SUSFS_SUS_MOUNT
|
||||||
|
struct mount *mnt;
|
||||||
|
|
||||||
|
mnt = real_mount(path->mnt);
|
||||||
|
if (likely(susfs_is_current_proc_umounted())) {
|
||||||
|
for (; mnt->mnt_id >= DEFAULT_SUS_MNT_ID; mnt = mnt->mnt_parent) {}
|
||||||
|
}
|
||||||
|
error = statfs_by_dentry(mnt->mnt.mnt_root, buf);
|
||||||
|
if (!error)
|
||||||
|
buf->f_flags = calculate_f_flags(&mnt->mnt);
|
||||||
|
return error;
|
||||||
|
#else
|
||||||
error = statfs_by_dentry(path->dentry, buf);
|
error = statfs_by_dentry(path->dentry, buf);
|
||||||
if (!error)
|
if (!error)
|
||||||
buf->f_flags = calculate_f_flags(path->mnt);
|
buf->f_flags = calculate_f_flags(path->mnt);
|
||||||
return error;
|
return error;
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
EXPORT_SYMBOL(vfs_statfs);
|
EXPORT_SYMBOL(vfs_statfs);
|
||||||
|
|
||||||
@@ -224,6 +240,11 @@ int vfs_ustat(dev_t dev, struct kstatfs *sbuf)
|
|||||||
if (!s)
|
if (!s)
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
|
|
||||||
|
#ifdef CONFIG_KSU_SUSFS_SUS_MOUNT
|
||||||
|
if (unlikely(s->s_root->d_inode->i_mapping->flags & BIT_SUS_MOUNT)) {
|
||||||
|
return -EINVAL;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
err = statfs_by_dentry(s->s_root, sbuf);
|
err = statfs_by_dentry(s->s_root, sbuf);
|
||||||
drop_super(s);
|
drop_super(s);
|
||||||
return err;
|
return err;
|
||||||
|
|||||||
1362
fs/susfs.c
Normal file
1362
fs/susfs.c
Normal file
File diff suppressed because it is too large
Load Diff
@@ -69,6 +69,9 @@ struct vfsmount {
|
|||||||
struct super_block *mnt_sb; /* pointer to superblock */
|
struct super_block *mnt_sb; /* pointer to superblock */
|
||||||
int mnt_flags;
|
int mnt_flags;
|
||||||
void *data;
|
void *data;
|
||||||
|
#ifdef CONFIG_KSU_SUSFS
|
||||||
|
u64 susfs_mnt_id_backup;
|
||||||
|
#endif
|
||||||
} __randomize_layout;
|
} __randomize_layout;
|
||||||
|
|
||||||
struct file; /* forward dec */
|
struct file; /* forward dec */
|
||||||
|
|||||||
@@ -1372,6 +1372,10 @@ struct task_struct {
|
|||||||
* New fields for task_struct should be added above here, so that
|
* New fields for task_struct should be added above here, so that
|
||||||
* they are included in the randomized portion of task_struct.
|
* they are included in the randomized portion of task_struct.
|
||||||
*/
|
*/
|
||||||
|
#ifdef CONFIG_KSU_SUSFS
|
||||||
|
u64 susfs_task_state;
|
||||||
|
u64 susfs_last_fake_mnt_id;
|
||||||
|
#endif
|
||||||
randomized_struct_fields_end
|
randomized_struct_fields_end
|
||||||
|
|
||||||
/* CPU-specific state of this task: */
|
/* CPU-specific state of this task: */
|
||||||
|
|||||||
213
include/linux/susfs.h
Normal file
213
include/linux/susfs.h
Normal file
@@ -0,0 +1,213 @@
|
|||||||
|
#ifndef KSU_SUSFS_H
|
||||||
|
#define KSU_SUSFS_H
|
||||||
|
|
||||||
|
#include <linux/version.h>
|
||||||
|
#include <linux/types.h>
|
||||||
|
#include <linux/utsname.h>
|
||||||
|
#include <linux/hashtable.h>
|
||||||
|
#include <linux/path.h>
|
||||||
|
#include <linux/susfs_def.h>
|
||||||
|
|
||||||
|
#define SUSFS_VERSION "v1.5.12"
|
||||||
|
#if LINUX_VERSION_CODE < KERNEL_VERSION(5,0,0)
|
||||||
|
#define SUSFS_VARIANT "NON-GKI"
|
||||||
|
#else
|
||||||
|
#define SUSFS_VARIANT "GKI"
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/*********/
|
||||||
|
/* MACRO */
|
||||||
|
/*********/
|
||||||
|
#define getname_safe(name) (name == NULL ? ERR_PTR(-EINVAL) : getname(name))
|
||||||
|
#define putname_safe(name) (IS_ERR(name) ? NULL : putname(name))
|
||||||
|
|
||||||
|
/**********/
|
||||||
|
/* STRUCT */
|
||||||
|
/**********/
|
||||||
|
/* sus_path */
|
||||||
|
#ifdef CONFIG_KSU_SUSFS_SUS_PATH
|
||||||
|
struct st_susfs_sus_path {
|
||||||
|
unsigned long target_ino;
|
||||||
|
char target_pathname[SUSFS_MAX_LEN_PATHNAME];
|
||||||
|
unsigned int i_uid;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct st_susfs_sus_path_list {
|
||||||
|
struct list_head list;
|
||||||
|
struct st_susfs_sus_path info;
|
||||||
|
char target_pathname[SUSFS_MAX_LEN_PATHNAME];
|
||||||
|
size_t path_len;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct st_android_data_path {
|
||||||
|
char pathname[SUSFS_MAX_LEN_PATHNAME];
|
||||||
|
bool is_inited;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct st_sdcard_path {
|
||||||
|
char pathname[SUSFS_MAX_LEN_PATHNAME];
|
||||||
|
bool is_inited;
|
||||||
|
};
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/* sus_mount */
|
||||||
|
#ifdef CONFIG_KSU_SUSFS_SUS_MOUNT
|
||||||
|
struct st_susfs_sus_mount {
|
||||||
|
char target_pathname[SUSFS_MAX_LEN_PATHNAME];
|
||||||
|
unsigned long target_dev;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct st_susfs_sus_mount_list {
|
||||||
|
struct list_head list;
|
||||||
|
struct st_susfs_sus_mount info;
|
||||||
|
};
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/* sus_kstat */
|
||||||
|
#ifdef CONFIG_KSU_SUSFS_SUS_KSTAT
|
||||||
|
struct st_susfs_sus_kstat {
|
||||||
|
int is_statically;
|
||||||
|
unsigned long target_ino; // the ino after bind mounted or overlayed
|
||||||
|
char target_pathname[SUSFS_MAX_LEN_PATHNAME];
|
||||||
|
unsigned long spoofed_ino;
|
||||||
|
unsigned long spoofed_dev;
|
||||||
|
unsigned int spoofed_nlink;
|
||||||
|
long long spoofed_size;
|
||||||
|
long spoofed_atime_tv_sec;
|
||||||
|
long spoofed_mtime_tv_sec;
|
||||||
|
long spoofed_ctime_tv_sec;
|
||||||
|
long spoofed_atime_tv_nsec;
|
||||||
|
long spoofed_mtime_tv_nsec;
|
||||||
|
long spoofed_ctime_tv_nsec;
|
||||||
|
unsigned long spoofed_blksize;
|
||||||
|
unsigned long long spoofed_blocks;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct st_susfs_sus_kstat_hlist {
|
||||||
|
unsigned long target_ino;
|
||||||
|
struct st_susfs_sus_kstat info;
|
||||||
|
struct hlist_node node;
|
||||||
|
};
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/* try_umount */
|
||||||
|
#ifdef CONFIG_KSU_SUSFS_TRY_UMOUNT
|
||||||
|
struct st_susfs_try_umount {
|
||||||
|
char target_pathname[SUSFS_MAX_LEN_PATHNAME];
|
||||||
|
int mnt_mode;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct st_susfs_try_umount_list {
|
||||||
|
struct list_head list;
|
||||||
|
struct st_susfs_try_umount info;
|
||||||
|
};
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/* spoof_uname */
|
||||||
|
#ifdef CONFIG_KSU_SUSFS_SPOOF_UNAME
|
||||||
|
struct st_susfs_uname {
|
||||||
|
char release[__NEW_UTS_LEN+1];
|
||||||
|
char version[__NEW_UTS_LEN+1];
|
||||||
|
};
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/* open_redirect */
|
||||||
|
#ifdef CONFIG_KSU_SUSFS_OPEN_REDIRECT
|
||||||
|
struct st_susfs_open_redirect {
|
||||||
|
unsigned long target_ino;
|
||||||
|
char target_pathname[SUSFS_MAX_LEN_PATHNAME];
|
||||||
|
char redirected_pathname[SUSFS_MAX_LEN_PATHNAME];
|
||||||
|
};
|
||||||
|
|
||||||
|
struct st_susfs_open_redirect_hlist {
|
||||||
|
unsigned long target_ino;
|
||||||
|
char target_pathname[SUSFS_MAX_LEN_PATHNAME];
|
||||||
|
char redirected_pathname[SUSFS_MAX_LEN_PATHNAME];
|
||||||
|
struct hlist_node node;
|
||||||
|
};
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/* sus_su */
|
||||||
|
#ifdef CONFIG_KSU_SUSFS_SUS_SU
|
||||||
|
struct st_sus_su {
|
||||||
|
int mode;
|
||||||
|
};
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/* sus_map */
|
||||||
|
#ifdef CONFIG_KSU_SUSFS_SUS_MAP
|
||||||
|
struct st_susfs_sus_map {
|
||||||
|
char target_pathname[SUSFS_MAX_LEN_PATHNAME];
|
||||||
|
};
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/***********************/
|
||||||
|
/* FORWARD DECLARATION */
|
||||||
|
/***********************/
|
||||||
|
/* sus_path */
|
||||||
|
#ifdef CONFIG_KSU_SUSFS_SUS_PATH
|
||||||
|
int susfs_set_i_state_on_external_dir(char __user* user_info, int cmd);
|
||||||
|
int susfs_add_sus_path(struct st_susfs_sus_path* __user user_info);
|
||||||
|
#endif
|
||||||
|
/* sus_mount */
|
||||||
|
#ifdef CONFIG_KSU_SUSFS_SUS_MOUNT
|
||||||
|
int susfs_add_sus_mount(struct st_susfs_sus_mount* __user user_info);
|
||||||
|
#ifdef CONFIG_KSU_SUSFS_AUTO_ADD_SUS_BIND_MOUNT
|
||||||
|
int susfs_auto_add_sus_bind_mount(const char *pathname, struct path *path_target);
|
||||||
|
#endif // #ifdef CONFIG_KSU_SUSFS_AUTO_ADD_SUS_BIND_MOUNT
|
||||||
|
#ifdef CONFIG_KSU_SUSFS_AUTO_ADD_SUS_KSU_DEFAULT_MOUNT
|
||||||
|
void susfs_auto_add_sus_ksu_default_mount(const char __user *to_pathname);
|
||||||
|
#endif // #ifdef CONFIG_KSU_SUSFS_AUTO_ADD_SUS_KSU_DEFAULT_MOUNT
|
||||||
|
#endif // #ifdef CONFIG_KSU_SUSFS_SUS_MOUNT
|
||||||
|
|
||||||
|
/* sus_kstat */
|
||||||
|
#ifdef CONFIG_KSU_SUSFS_SUS_KSTAT
|
||||||
|
int susfs_add_sus_kstat(struct st_susfs_sus_kstat* __user user_info);
|
||||||
|
int susfs_update_sus_kstat(struct st_susfs_sus_kstat* __user user_info);
|
||||||
|
void susfs_sus_ino_for_generic_fillattr(unsigned long ino, struct kstat *stat);
|
||||||
|
void susfs_sus_ino_for_show_map_vma(unsigned long ino, dev_t *out_dev, unsigned long *out_ino);
|
||||||
|
#endif
|
||||||
|
/* try_umount */
|
||||||
|
#ifdef CONFIG_KSU_SUSFS_TRY_UMOUNT
|
||||||
|
int susfs_add_try_umount(struct st_susfs_try_umount* __user user_info);
|
||||||
|
void susfs_try_umount(uid_t target_uid);
|
||||||
|
#ifdef CONFIG_KSU_SUSFS_AUTO_ADD_TRY_UMOUNT_FOR_BIND_MOUNT
|
||||||
|
void susfs_auto_add_try_umount_for_bind_mount(struct path *path);
|
||||||
|
#endif // #ifdef CONFIG_KSU_SUSFS_AUTO_ADD_TRY_UMOUNT_FOR_BIND_MOUNT
|
||||||
|
#endif // #ifdef CONFIG_KSU_SUSFS_TRY_UMOUNT
|
||||||
|
/* spoof_uname */
|
||||||
|
#ifdef CONFIG_KSU_SUSFS_SPOOF_UNAME
|
||||||
|
int susfs_set_uname(struct st_susfs_uname* __user user_info);
|
||||||
|
void susfs_spoof_uname(struct new_utsname* tmp);
|
||||||
|
#endif
|
||||||
|
/* set_log */
|
||||||
|
#ifdef CONFIG_KSU_SUSFS_ENABLE_LOG
|
||||||
|
void susfs_set_log(bool enabled);
|
||||||
|
#endif
|
||||||
|
/* spoof_cmdline_or_bootconfig */
|
||||||
|
#ifdef CONFIG_KSU_SUSFS_SPOOF_CMDLINE_OR_BOOTCONFIG
|
||||||
|
int susfs_set_cmdline_or_bootconfig(char* __user user_fake_boot_config);
|
||||||
|
int susfs_spoof_cmdline_or_bootconfig(struct seq_file *m);
|
||||||
|
#endif
|
||||||
|
/* open_redirect */
|
||||||
|
#ifdef CONFIG_KSU_SUSFS_OPEN_REDIRECT
|
||||||
|
int susfs_add_open_redirect(struct st_susfs_open_redirect* __user user_info);
|
||||||
|
struct filename* susfs_get_redirected_path(unsigned long ino);
|
||||||
|
#endif
|
||||||
|
/* sus_su */
|
||||||
|
#ifdef CONFIG_KSU_SUSFS_SUS_SU
|
||||||
|
int susfs_get_sus_su_working_mode(void);
|
||||||
|
int susfs_sus_su(struct st_sus_su* __user user_info);
|
||||||
|
#endif
|
||||||
|
/* sus_map */
|
||||||
|
#ifdef CONFIG_KSU_SUSFS_SUS_MAP
|
||||||
|
int susfs_add_sus_map(struct st_susfs_sus_map* __user user_info);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
int susfs_get_enabled_features(char __user* buf, size_t bufsize);
|
||||||
|
void susfs_set_avc_log_spoofing(bool enabled);
|
||||||
|
|
||||||
|
/* susfs_init */
|
||||||
|
void susfs_init(void);
|
||||||
|
|
||||||
|
#endif
|
||||||
92
include/linux/susfs_def.h
Normal file
92
include/linux/susfs_def.h
Normal file
@@ -0,0 +1,92 @@
|
|||||||
|
#ifndef KSU_SUSFS_DEF_H
|
||||||
|
#define KSU_SUSFS_DEF_H
|
||||||
|
|
||||||
|
#include <linux/bits.h>
|
||||||
|
|
||||||
|
/********/
|
||||||
|
/* ENUM */
|
||||||
|
/********/
|
||||||
|
/* shared with userspace ksu_susfs tool */
|
||||||
|
#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
|
||||||
|
#define CMD_SUSFS_ADD_SUS_KSTAT 0x55570
|
||||||
|
#define CMD_SUSFS_UPDATE_SUS_KSTAT 0x55571
|
||||||
|
#define CMD_SUSFS_ADD_SUS_KSTAT_STATICALLY 0x55572
|
||||||
|
#define CMD_SUSFS_ADD_TRY_UMOUNT 0x55580
|
||||||
|
#define CMD_SUSFS_SET_UNAME 0x55590
|
||||||
|
#define CMD_SUSFS_ENABLE_LOG 0x555a0
|
||||||
|
#define CMD_SUSFS_SET_CMDLINE_OR_BOOTCONFIG 0x555b0
|
||||||
|
#define CMD_SUSFS_ADD_OPEN_REDIRECT 0x555c0
|
||||||
|
#define CMD_SUSFS_RUN_UMOUNT_FOR_CURRENT_MNT_NS 0x555d0
|
||||||
|
#define CMD_SUSFS_SHOW_VERSION 0x555e1
|
||||||
|
#define CMD_SUSFS_SHOW_ENABLED_FEATURES 0x555e2
|
||||||
|
#define CMD_SUSFS_SHOW_VARIANT 0x555e3
|
||||||
|
#define CMD_SUSFS_SHOW_SUS_SU_WORKING_MODE 0x555e4
|
||||||
|
#define CMD_SUSFS_IS_SUS_SU_READY 0x555f0
|
||||||
|
#define CMD_SUSFS_SUS_SU 0x60000
|
||||||
|
#define CMD_SUSFS_ENABLE_AVC_LOG_SPOOFING 0x60010
|
||||||
|
#define CMD_SUSFS_ADD_SUS_MAP 0x60020
|
||||||
|
|
||||||
|
#define SUSFS_MAX_LEN_PATHNAME 256 // 256 should address many paths already unless you are doing some strange experimental stuff, then set your own desired length
|
||||||
|
#define SUSFS_FAKE_CMDLINE_OR_BOOTCONFIG_SIZE 4096
|
||||||
|
|
||||||
|
#define TRY_UMOUNT_DEFAULT 0 /* used by susfs_try_umount() */
|
||||||
|
#define TRY_UMOUNT_DETACH 1 /* used by susfs_try_umount() */
|
||||||
|
|
||||||
|
#define SUS_SU_DISABLED 0
|
||||||
|
#define SUS_SU_WITH_OVERLAY 1 /* deprecated */
|
||||||
|
#define SUS_SU_WITH_HOOKS 2
|
||||||
|
|
||||||
|
#define DEFAULT_SUS_MNT_ID 300000 /* used by mount->mnt_id */
|
||||||
|
#define DEFAULT_SUS_MNT_ID_FOR_KSU_PROC_UNSHARE 1000000 /* used by vfsmount->susfs_mnt_id_backup */
|
||||||
|
#define DEFAULT_SUS_MNT_GROUP_ID 3000 /* used by mount->mnt_group_id */
|
||||||
|
|
||||||
|
/*
|
||||||
|
* mount->mnt.susfs_mnt_id_backup => storing original mount's mnt_id
|
||||||
|
* 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_'
|
||||||
|
*/
|
||||||
|
// thread_info->flags is unsigned long :D
|
||||||
|
#define TIF_PROC_UMOUNTED 33
|
||||||
|
|
||||||
|
#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 AS_FLAGS_SUS_MAP 30
|
||||||
|
#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)
|
||||||
|
#define BIT_SUS_MAPS BIT(30)
|
||||||
|
|
||||||
|
#define ND_STATE_LOOKUP_LAST 32
|
||||||
|
#define ND_STATE_OPEN_LAST 64
|
||||||
|
#define ND_STATE_LAST_SDCARD_SUS_PATH 128
|
||||||
|
#define ND_FLAGS_LOOKUP_LAST 0x2000000
|
||||||
|
|
||||||
|
#define MAGIC_MOUNT_WORKDIR "/debug_ramdisk/workdir"
|
||||||
|
#define DATA_ADB_UMOUNT_FOR_ZYGOTE_SYSTEM_PROCESS "/data/adb/susfs_umount_for_zygote_system_process"
|
||||||
|
#define DATA_ADB_NO_AUTO_ADD_SUS_BIND_MOUNT "/data/adb/susfs_no_auto_add_sus_bind_mount"
|
||||||
|
#define DATA_ADB_NO_AUTO_ADD_SUS_KSU_DEFAULT_MOUNT "/data/adb/susfs_no_auto_add_sus_ksu_default_mount"
|
||||||
|
#define DATA_ADB_NO_AUTO_ADD_TRY_UMOUNT_FOR_BIND_MOUNT "/data/adb/susfs_no_auto_add_try_umount_for_bind_mount"
|
||||||
|
|
||||||
|
static inline bool susfs_is_current_proc_umounted(void) {
|
||||||
|
return test_ti_thread_flag(¤t->thread_info, TIF_PROC_UMOUNTED);
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline void susfs_set_current_proc_umounted(void) {
|
||||||
|
set_ti_thread_flag(¤t->thread_info, TIF_PROC_UMOUNTED);
|
||||||
|
}
|
||||||
|
#endif // #ifndef KSU_SUSFS_DEF_H
|
||||||
@@ -592,6 +592,11 @@ static void s_stop(struct seq_file *m, void *p)
|
|||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#ifdef CONFIG_KSU_SUSFS_HIDE_KSU_SUSFS_SYMBOLS
|
||||||
|
extern bool susfs_starts_with(const char *str, const char *prefix);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
||||||
static int s_show(struct seq_file *m, void *p)
|
static int s_show(struct seq_file *m, void *p)
|
||||||
{
|
{
|
||||||
struct kallsym_iter *iter = m->private;
|
struct kallsym_iter *iter = m->private;
|
||||||
@@ -612,8 +617,38 @@ static int s_show(struct seq_file *m, void *p)
|
|||||||
seq_printf(m, "%pK %c %s\t[%s]\n", (void *)iter->value,
|
seq_printf(m, "%pK %c %s\t[%s]\n", (void *)iter->value,
|
||||||
type, iter->name, iter->module_name);
|
type, iter->name, iter->module_name);
|
||||||
} else
|
} else
|
||||||
|
|
||||||
|
#ifndef CONFIG_KSU_SUSFS_HIDE_KSU_SUSFS_SYMBOLS
|
||||||
seq_printf(m, "%pK %c %s\n", (void *)iter->value,
|
seq_printf(m, "%pK %c %s\n", (void *)iter->value,
|
||||||
iter->type, iter->name);
|
iter->type, iter->name);
|
||||||
|
#else
|
||||||
|
{
|
||||||
|
if (susfs_starts_with(iter->name, "ksu_") ||
|
||||||
|
susfs_starts_with(iter->name, "__ksu_") ||
|
||||||
|
susfs_starts_with(iter->name, "susfs_") ||
|
||||||
|
susfs_starts_with(iter->name, "ksud") ||
|
||||||
|
susfs_starts_with(iter->name, "is_ksu_") ||
|
||||||
|
susfs_starts_with(iter->name, "is_manager_") ||
|
||||||
|
susfs_starts_with(iter->name, "escape_to_") ||
|
||||||
|
susfs_starts_with(iter->name, "setup_selinux") ||
|
||||||
|
susfs_starts_with(iter->name, "track_throne") ||
|
||||||
|
susfs_starts_with(iter->name, "on_post_fs_data") ||
|
||||||
|
susfs_starts_with(iter->name, "try_umount") ||
|
||||||
|
susfs_starts_with(iter->name, "kernelsu") ||
|
||||||
|
susfs_starts_with(iter->name, "__initcall__kmod_kernelsu") ||
|
||||||
|
susfs_starts_with(iter->name, "apply_kernelsu") ||
|
||||||
|
susfs_starts_with(iter->name, "handle_sepolicy") ||
|
||||||
|
susfs_starts_with(iter->name, "getenforce") ||
|
||||||
|
susfs_starts_with(iter->name, "setenforce") ||
|
||||||
|
susfs_starts_with(iter->name, "is_zygote"))
|
||||||
|
{
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
seq_printf(m, "%pK %c %s\n", (void *)iter->value,
|
||||||
|
iter->type, iter->name);
|
||||||
|
}
|
||||||
|
#endif
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -1182,12 +1182,18 @@ static int override_release(char __user *release, size_t len)
|
|||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#ifdef CONFIG_KSU_SUSFS_SPOOF_UNAME
|
||||||
|
extern void susfs_spoof_uname(struct new_utsname* tmp);
|
||||||
|
#endif
|
||||||
SYSCALL_DEFINE1(newuname, struct new_utsname __user *, name)
|
SYSCALL_DEFINE1(newuname, struct new_utsname __user *, name)
|
||||||
{
|
{
|
||||||
struct new_utsname tmp;
|
struct new_utsname tmp;
|
||||||
|
|
||||||
down_read(&uts_sem);
|
down_read(&uts_sem);
|
||||||
memcpy(&tmp, utsname(), sizeof(tmp));
|
memcpy(&tmp, utsname(), sizeof(tmp));
|
||||||
|
#ifdef CONFIG_KSU_SUSFS_SPOOF_UNAME
|
||||||
|
susfs_spoof_uname(&tmp);
|
||||||
|
#endif
|
||||||
up_read(&uts_sem);
|
up_read(&uts_sem);
|
||||||
if (copy_to_user(name, &tmp, sizeof(tmp)))
|
if (copy_to_user(name, &tmp, sizeof(tmp)))
|
||||||
return -EFAULT;
|
return -EFAULT;
|
||||||
|
|||||||
@@ -44,6 +44,13 @@
|
|||||||
#define avc_cache_stats_incr(field) do {} while (0)
|
#define avc_cache_stats_incr(field) do {} while (0)
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#ifdef CONFIG_KSU_SUSFS
|
||||||
|
extern u32 susfs_ksu_sid;
|
||||||
|
extern u32 susfs_kernel_sid;
|
||||||
|
bool susfs_is_avc_log_spoofing_enabled = false;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
||||||
struct avc_entry {
|
struct avc_entry {
|
||||||
u32 ssid;
|
u32 ssid;
|
||||||
u32 tsid;
|
u32 tsid;
|
||||||
@@ -187,6 +194,16 @@ static void avc_dump_query(struct audit_buffer *ab, struct selinux_state *state,
|
|||||||
}
|
}
|
||||||
|
|
||||||
rc = security_sid_to_context(state, tsid, &scontext, &scontext_len);
|
rc = security_sid_to_context(state, tsid, &scontext, &scontext_len);
|
||||||
|
#ifdef CONFIG_KSU_SUSFS
|
||||||
|
if (unlikely(tsid == susfs_ksu_sid && susfs_is_avc_log_spoofing_enabled)) {
|
||||||
|
if (rc)
|
||||||
|
audit_log_format(ab, " tsid=%d", susfs_kernel_sid);
|
||||||
|
else
|
||||||
|
audit_log_format(ab, " tcontext=%s", "u:r:kernel:s0");
|
||||||
|
goto bypass_orig_flow;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
if (rc)
|
if (rc)
|
||||||
audit_log_format(ab, " tsid=%d", tsid);
|
audit_log_format(ab, " tsid=%d", tsid);
|
||||||
else {
|
else {
|
||||||
@@ -194,6 +211,9 @@ static void avc_dump_query(struct audit_buffer *ab, struct selinux_state *state,
|
|||||||
kfree(scontext);
|
kfree(scontext);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#ifdef CONFIG_KSU_SUSFS
|
||||||
|
bypass_orig_flow:
|
||||||
|
#endif
|
||||||
BUG_ON(!tclass || tclass >= ARRAY_SIZE(secclass_map));
|
BUG_ON(!tclass || tclass >= ARRAY_SIZE(secclass_map));
|
||||||
audit_log_format(ab, " tclass=%s", secclass_map[tclass-1].name);
|
audit_log_format(ab, " tclass=%s", secclass_map[tclass-1].name);
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user