Inserting a PID in the Linux Hash-Table - linux

Currently I'm working on a Linux-Kernel-Module, that can hide any normal Process.
The hiding works fine, but I haven't found a way to unhide the process yet.
First I delete the struct task_struct from the big list of task_structs inside the Kernel:
struct task_struct *p;
//Finding the correct task_struct
for_each_process(p)
if(p->pid == pid){
// Removing the task_struct
struct list_head *next = task->tasks.next;
struct list_head *prev = task->tasks.prev;
next->prev=prev;
prev->next=next;
}
But the task_struct is still traceable, because it's inside a hash_table containing every process' task_struct. In fact most of the PID-Lookup is performed by this hash-table. Removing the task-struct from there is a bit tricky:
struct pid *pid; //struct pid of the task_struct
//Deleting for every pid_namespace the pid_chain from the hash_list
for (i = 0; i <= pid->level; i++) {
struct upid *upid = pid->numbers + i;
hlist_del_rcu(&upid->pid_chain);
}
The Problem is to restore both structs: Inserting the task_struct back in the list of task_structs is easy, but I haven't found a way to restore the link in the hash-table. It's difficult, because the kernel doesn't expose the needed structures.
Inside the Kernel, it's done within this line:
hlist_add_head_rcu(&upid->pid_chain,&pid_hash[pid_hashfn(upid->nr, upid->ns)]);
pid_hashfn and pid_hash are defined as follows:
#define pid_hashfn(nr, ns) hash_long((unsigned long)nr + (unsigned long)ns, pidhash_shift)
static struct hlist_head *pid_hash;
And the struct I need to insert, is the pid_chain:
struct hlist_node pid_chain;
So my question is, how can I insert the pid_chain in the correct hash-list?
Is there a way to obtain the reference to the hash-list-array, even if it's declared as static?
Or, maybe an uncommon idea: The hash-list is allocated via
pid_hash = alloc_large_system_hash("PID", sizeof(*pid_hash), 0, 18,HASH_EARLY | HASH_SMALL, &pidhash_shift, NULL,0, 4096);
So, if I could get the starting-position of the memory of the hash-list, could I scan the corresponding memoryspace for the pointer of my struct and then cast the surrounding memoryregion to struct of type struct hlist?
Thanks for your help. Every solution or idea is appreciated :)

There is a hash list available in sysmap file. you can check that once.

The pid_hash can be located in /proc/kallsyms and also is accesible programatically by kallsyms_lookup_name.

Related

TSS usage in linux kernel

While reading linux kernel code, I came across usage of tss (task state segment) inside __switch_to (arch/x86_64/kernel/process.c#L441).
Since linux handles saving/restoring process context via software, what is the need to maintain duplicate data? For e.g. stack pointer. Attaching a small snippet for reference
struct task_struct *__switch_to(struct task_struct *prev_p, struct task_struct *next_p)
{
struct thread_struct *prev = &prev_p->thread,
*next = &next_p->thread;
int cpu = smp_processor_id();
struct tss_struct *tss = &per_cpu(init_tss, cpu);
unlazy_fpu(prev_p);
/*
* Reload esp0, LDT and the page table pointer:
*/
tss->rsp0 = next->rsp0;
What is the need to copy rsp0 from next(thread_struct) to tss(tss_struct). Why can't we use next->rsp0 wherever tss-rsp0 is used? Why is tss_struct still present in kernel?
I am a noob who has recently started to learn kernel insides.

How to access the /proc file system's iiterate function pointer

I am trying to create a simple linux rootkit that can be used to hide processess. The method I have chosen to try is to replace the pointer to "/proc" 's iterate function with a pointer to a custom one that will hide the processess I need. To do this I have to first save a pointer to it's originale iterate function so it can be replaced later. The '/proc' file system's iterate function can be accessed by accessing the 'iterate' function pointer which is a member of it's 'file_operations' structure.
I have tried the following two methods to access it, as can be seen in the code segment as label_1 and label_2, each tested with the other commented out.
static struct file *proc_filp;
static struct proc_dir_entry *test_proc;
static struct proc_dir_entry *proc_root;
static struct file_operations *fs_ops;
int (*proc_iterate) (struct file *, struct dir_context *);
static int __init module_init(void)
{
label_1:
proc_filp = filp_open("/proc", O_RDONLY | O_DIRECTORY, 0);
fs_ops = (struct file_operations *) proc_filp->f_op;
printk(KERN_INFO "file_operations is %p", fs_ops);
proc_iterate = fs_ops->iterate;
printk(KERN_INFO "proc_iterate is %p", proc_iterate);
filp_close(proc_filp, NULL);
label_2:
test_proc = proc_create("test_proc", 0, NULL, &proc_fops);
proc_root = test_proc->parent;
printk(KERN_INFO "proc_root is %p", proc_root);
fs_ops = (struct file_operations *) proc_root->proc_fops;
printk(KERN_INFO "file_operations is %p", fs_ops);
proc_iterate = fs_ops->iterate;
printk(KERN_INFO "proc_iterate is %p", proc_iterate);
remove_proc_entry("test_proc", NULL);
return 0;
}
As per method 1, I open '/proc' as a file, then follow the file pointer to access it's 'struct file_operations' (f_op), and then follow this pointer to try and locate 'iterate'. However, although I am able to successfully access the 'f_op' structure, somehow it's 'iterate' seems to point to NULL. The following dmesg log shows the output of this.
[ 47.707558] file_operations is 00000000b8d10f59
[ 47.707564] proc_iterate is (null)
As per method 2, I create a new proc directory entry, then try to access it's parent directory (which should point to '/proc' itself), and then try to access it's 'struct file_operations' (proc_fops), and then try to follow on to 'iterate'. However, using this method I am not even able to access the '/proc' directory, as 'proc_root = test_proc->parent;' seems to return NULL. This causes a 'kernel NULL pointer dereference' error in the code that follows. The following dmesg log shows the output of this.
[ 212.078552] proc_root is (null)
[ 212.078567] BUG: unable to handle kernel NULL pointer dereference at 000000000000003
Now, I know that things have changed in the linux kernel, and we are not allowed to write at various addresses (like change the iterate pointer to point at a custom function for example) and that this can be overcome by making those pages writable in the kernel, but that will come later in my attempt to create this rootkit. At present I can't even figure out how to even read the original 'iterate' pointer.
So, I have these questions :
[1] Is something wrong in the following code ? How to fix it ?
[2] Is there any other way to access the pointer to the /proc 's iterate function ?
Tested on Arch Linux running linux 4.15.7

Dynamic memory in a struct

So, my struct is like this:
struct player{
char name[20];
int time;
}s[50];
I don't know how many players i am going to add to the struct, and i also have to use dynamic memory for this. So how can i allocate and reallocate more space when i add a player to my struct?
I am inexperienced programmer, but i have been googling for this for a long time and i also don't perfectly understand structs.
This site doesn't accept my question so let's put some more text to this post
I assume you are programming in C/C++.
Your struct player has static-allocated fields, so, when you use malloc on it, you are asking space for a 20-byte char array a for one integer.
My suggestion is to store in a variable (or #define a symbol) the initial number of structures you can accept. Then, use malloc to allocate a static array that contains these structures.
Also you have to think about a strategy to store new players coming. The simplest one could be have an index variable to store last free position and use it to add over that position.
A short example follows:
#define init_cap 50
struct player {
char name[20];
int time;
};
int main() {
int index;
struct player* players;
players = (struct player*) malloc(init_cap * sizeof(struct player));
for(i = 0; i < init_cap; i++) {
strcpy(players[i].name, "peppe");
players[i].time = i;
}
free(players);
return 0;
}
At this point you should also think about reallocating memory if the number of players you get a runtime exceeds your initial capacity. You can use:
players = (struct player*) realloc(2 * init_cap * sizeof(struct player));
in order to double the initial capacity.
At the end, always remember to free the requested memory.

current directory of a process in linux-kernel

Is it possible to get the process current directory via struct task_struct? I can see that struct fs_struct has pwd pointer, but I'm not able get the exact variable where this info is stored.
Also, can we change current directory value?
Your working on quite an old kernel so I've had to do some digging. One of the easier ways to deal with this sort of thing is see if the information is in /proc and look at what it does. If we grep for cwd in fs/proc we find:
static int proc_cwd_link(struct inode *inode, struct dentry **dentry, struct vfsmount **mnt)
{
struct fs_struct *fs;
int result = -ENOENT;
task_lock(inode->u.proc_i.task);
fs = inode->u.proc_i.task->fs;
if(fs)
atomic_inc(&fs->count);
task_unlock(inode->u.proc_i.task);
if (fs) {
read_lock(&fs->lock);
*mnt = mntget(fs->pwdmnt);
*dentry = dget(fs->pwd);
read_unlock(&fs->lock);
result = 0;
put_fs_struct(fs);
}
return result;
}
The proc inode points to the task (inode->u.proc_i.task, also given away by the task_lock() stuff). Looking at the task_struct definition it has a reference to struct fs_struct *fs which has the dentry pointers for the pwd. Translating the dentry entry to an actual name is another exercise however.

Apply list_entry to task_struct

list_for_each(list, &current->children) {
task = list_entry(list, struct task_struct, sibling);
/* task now points to one of current’s children */
}
According to this answer: list_entry in Linux, the list_entry() macro will cast to specified struct based on the offset of the supplied pointer (in this case, list) in the specified data structure (in this case, task_struct). However, in the above code, I think list is the pointer to the next task_struct, starts from the beginning. How come the code cast list back to task_struct from the offset sibling, which is not the start of the task_struct? Or, list points directly to the sibling member of its next task_struct?

Resources