15

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?

1

3 Answers 3

12

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.

Sign up to request clarification or add additional context in comments.

Comments

1

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

1 Comment

And in arm64 case, current is defined as task_struct *get_current() and get_current returns sp_el0 register. because sp_el0 is not used in OS, for fast access they use sp_el0 (stack pointer for exception level 0(user level)) for the task_struct pointer.
0

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;

  1. current I believe contains the active kernel process's data.
  2. The struct variable task_struct.comm, shown as p->comm contains the running program's name.
  3. There exists a variable called pid that contains the process ID, there also exists a function to get a pointer to a task_struct using a pid_t directly.
  4. Through variables in the 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

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.