Apply list_entry to task_struct - linux

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?

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.

Inserting a PID in the Linux Hash-Table

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.

per-cpu variable definition in Linux kernel 2.6.27

In 2.6.27 there is the macro DEFINE_PER_CPU(type, variable) to define per-cpu variables.
I am able to define a variable in the global scope using this macro. But if its a variable inside a structure I see an error when compiling..
for ex:
struct port_stats {
... ....
DEFINE_PER_CPU(long *, stats);
}
The error I see is..
*error: section attribute not allowed for 'per_cpu__stats'*
The same definition is ok if its outside the structure. Not sure what this error means. Any suggestions ?
If you want to define a per-cpu variable within a struct in the Linux kernel, you need to make it a pointer to the desired type (so, in this case long **) with the __percpu attribute:
struct port_stats {
... ....
long __percpu **stats;
}
(On older kernels that lack the __percpu macro, just declare it as long **stats; with a comment that it is a pointer to an array of per-cpu variables).
Then when you create an instance of the structure, allocate the per-cpu variables with alloc_percpu() (which can fail):
pstats->stats = alloc_percpu(long *);
if (!pstats->stats)
return -ENOMEM;
To then access the percpu instance, you need to use get_cpu() and put_cpu():
long **stats;
stats = per_cpu_ptr(pstats->stats, get_cpu());
/* Read or write *stats, the per-cpu (long *) value for this cpu */
put_cpu();
When you free the structure, you must also execute free_percpu(pstats->stats); as well.

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.

enqueue_pushable_task function kernel

The following function is defined in ./kernel/sched/rt.c(v3.5.4):
static void enqueue_pushable_task(struct rq *rq, struct task_struct *p)
{
plist_del(&p->pushable_tasks, &rq->rt.pushable_tasks);
plist_node_init(&p->pushable_tasks, p->prio);
plist_add(&p->pushable_tasks, &rq->rt.pushable_tasks);
/* Update the highest prio pushable task */
if (p->prio < rq->rt.highest_prio.next)
rq->rt.highest_prio.next = p->prio;
}
What I am unable to understand is that why does one want to add and delete the same node form the same list over and over. First a node is deleted from the list by plist_del and same node is added to the same list by plist_add function. Any particular reasons why this is done
When the priority of a task changes, its position in the priority list must also change.

Resources