Reputation: 329
I am a student doing research involving Linux processes, and I need to learn more about them to proceed with my experiment. In reading a couple books and things online, I've come across task_struct
, which I'm not sure I'm understanding fully, and would like confirmation/correction onto my existing thought.
From what I think I've understood, task_struct
is the C structure that acts as the process descriptor, holding everything the kernel might need to know about a processes. At the end of the process kernel stack lives another struct, thread_info
, which has a pointer to the processes task_struct
.
Another question: how does one access the task_struct
of a process? Is there a calculation to find the location of it's thread_info
? Is there a macro/function within the kernel?
Upvotes: 13
Views: 21935
Reputation: 47
Here's an example of a kernel module that uses task_struct
to determine if a process of a certain name exists upon module insertion:
/*
* File Name : test.c
*/
#include <linux/module.h>
#include <linux/kernel.h>
#include <linux/sched.h>
#include <linux/mm_types.h>
#include <linux/sched/signal.h>
rwlock_t tasklist_lock;
static int __init Init(void){
struct task_struct *p = current;
read_lock(&tasklist_lock);
for_each_process(p){
if(!strncmp((const char *)p->comm, "Slay999", 16)){
printk(KERN_INFO "Found target program\n");
break;
}
}
read_unlock(&tasklist_lock);
return 0;
}
static void __exit Exit(void){
printk(KERN_INFO "Module removed.\n");
}
MODULE_DESCRIPTION("Experements in privlege escalation.");
MODULE_AUTHOR("a name");
MODULE_LICENSE("GPL");
MODULE_VERSION("0.0");
module_init(Init);
module_exit(Exit);
By obtaining a pointer to an valid task_struct
address we can get information about a process that we can then use for statistical purposes and reconfiguration purposes.
For example, you can see the entire definition of task_struct
using the following bash command (obtainable through apt-get install pahole
):
pahole -C task_struct
Some quick side notes;
current
I believe contains the active kernel process's data.task_struct.comm
, shown as p->comm
contains the running program's name.pid
that contains the process ID, there also exists a function to get a pointer to a task_struct
using a pid_t
directly.task_struct
structure you can obtain things like struct mm_struct *active_mm
which from what I understand can give you the current memory address of a running process.Here is the accompanying make file for the module:
obj-m += test.o
all:
make -C /lib/modules/$(shell uname -r)/build/ M=$(PWD) modules
clean:
make -C /lib/modules/$(shell uname -r)/build/ M=$(PWD) clean
Upvotes: 0
Reputation: 802
Let me try answer second question.
On the top of each process kernel stack there is a structure thread_info.
To get address of/pointer to thread_info, different architectures have different solutions, but on x86 it looks something like this:
To get pointer to thread_info just mask 13 bits of the stack pointer value:
movl $0xFFFFE000, %eax
andl %esp, %eax
Now we have pointer, and this structure has pointer for task_struct structure.
To get it, there is a current macro, which looks something like this:
#define current (current_thread_info()->task)
and it gives you pointer (address of) task_struct
Upvotes: 1
Reputation: 23719
Yes, the task_struct
structure contains all the information about a process. You can obtain a pointer to the structure that describes the current process using the current
macro as follows:
struct task_struct *p = current;
If you want to get the structure that describes a process given a pid
, you can use the find_task_by_vpid
function as follows:
read_lock(&tasklist_lock);
p = find_task_by_vpid(pid);
if (p) get_task_struct(p);
read_unlock(&tasklist_lock);
if (p == NULL) {
// Task not found.
}
// Later, once you're finished with the task, execute:
put_task_struct(p);
Finally, if you want to iterate over all processes, you can use for_each_process
as follows:
read_lock(&tasklist_lock);
for_each_process(p) {
// p is a pointer to a task_struct instance.
}
read_unlock(&tasklist_lock);
If you want to an exclusive access to the task list to be able to make changes to one or more fields in the structure, write_lock_irqsave
must be used instead of read_lock
.
Upvotes: 11