Identifying whether a user-process or kernel-thread execution takes place by looking at CPU registers
Hi all, About a month ago I've made a question in the ML regarding the contents of the CR3 register and how the value of this register change when different processes/threads are executed. One of the conclusions of the conversation we had was that when kernel threads are executed, the CR3 register keeps the value of the process under which the kernel thread is executed (which is the previously executed process). That is, the kernel thread "borrows" the page-table of the previously executed process for executing. The problem is that by looking *only* at the CR3 register, we can't really tell if the user process in which the CR3 value corresponds to (each process is assigned a unique PGD value which results to a unique CR3 value) *or* a kernel-thread that uses its tables is executing. I was wondering if any other CPU register (apart from CR3) can indicate if a user-process or a kernel thread under it (and which one) is executed. Is it possible to know such a thing *only* by looking at CPU registers? I'll be happy to clarify any of the above. Thank you all in advance. John K.
Hi.... On Thu, May 12, 2011 at 17:55, limp <johnkyr83@hotmail.com> wrote:
I was wondering if any other CPU register (apart from CR3) can indicate if a user-process or a kernel thread under it (and which one) is executed. Is it possible to know such a thing *only* by looking at CPU registers?
one thing you can use is by looking at so called CPL (Current Privilege level) and check it whether it is 0. According to http://en.wikipedia.org/wiki/X86_memory_segmentation, CPL is the lower 2 bits in CS. However, you need to watch it continously, because user space apps could switch to CPL=0 (which denotes kernel mode, where CPL=3 denotes user mode) in the case of system call etc. perhaps better is by looking at the address of mm. However, to do this, you need to check starting from its task_struct, which is mapped in its kernel stack in x86 AFAIK. In other arch such as ARM, AFAIK task_struct could be simply derived from certain register. -- regards, Mulyadi Santosa Freelance Linux trainer and consultant blog: the-hydra.blogspot.com training: mulyaditraining.blogspot.com
Hi guys, On Thu, May 12, 2011 at 4:53 AM, Mulyadi Santosa <mulyadi.santosa@gmail.com> wrote:
Hi....
On Thu, May 12, 2011 at 17:55, limp <johnkyr83@hotmail.com> wrote:
I was wondering if any other CPU register (apart from CR3) can indicate if a user-process or a kernel thread under it (and which one) is executed. Is it possible to know such a thing *only* by looking at CPU registers?
one thing you can use is by looking at so called CPL (Current Privilege level) and check it whether it is 0. According to http://en.wikipedia.org/wiki/X86_memory_segmentation, CPL is the lower 2 bits in CS.
However, you need to watch it continously, because user space apps could switch to CPL=0 (which denotes kernel mode, where CPL=3 denotes user mode) in the case of system call etc.
perhaps better is by looking at the address of mm. However, to do this, you need to check starting from its task_struct, which is mapped in its kernel stack in x86 AFAIK. In other arch such as ARM, AFAIK task_struct could be simply derived from certain register.
On the ARM, you can derive the task_struct from the stack pointer.
From kernel context, you can just use "current" which is a pointer to the currently running task.
If you want details about how to determine the task_struct from SP, I can get into that, although it's subject to change. Using "current" it the normal technique. -- Dave Hylands Shuswap, BC, Canada http://www.davehylands.com
Thank you all for your replies.
If you want details about how to determine the task_struct from SP, I can get into that, although it's subject to change. Using "current" it the normal technique.
Yes, I want to determine the "task_struct" from the SP. According to what I read, on x86 "current" is calculated by masking out the 13 least significant bits of the stack pointer to obtain the "thread_info" structure and consequently the "task_struct". Is that what you had in mind? Another question is if the "task_struct" is allocated in contiguous memory space as I don't see a "packed" attribute in the structure definition. If yes, do you know of an easy way of finding the offset of the "mm" field of the structure so that I can obtain its value? I guess a way is by finding it manually from the structure definition but it seems quite complex. Thanks again, John K.
Hi John, On Sat, May 14, 2011 at 10:55 AM, limp <johnkyr83@hotmail.com> wrote:
Thank you all for your replies.
If you want details about how to determine the task_struct from SP, I can get into that, although it's subject to change. Using "current" it the normal technique.
Yes, I want to determine the "task_struct" from the SP. According to what I read, on x86 "current" is calculated by masking out the 13 least significant bits of the stack pointer to obtain the "thread_info" structure and consequently the "task_struct". Is that what you had in mind?
Well, what you get from the SP is something called thread_info (I'm familiar with ARM) http://lxr.linux.no/linux+v2.6.38/arch/arm/include/asm/thread_info.h#L50 The function current_thread_info gets the pointer to the thread_info struct by looking at the stack pointer: <http://lxr.linux.no/linux+v2.6.38/arch/arm/include/asm/thread_info.h#L94> The thread_info struct contains a pointer to the task_struct. So when the stack is allocated, it comes from an 8K chunk of memory (I think it may be 4K on x86) which is aligned on an 8K boundary, which is why the masking works. The stack starts at the high end of this and grow down. The thread_info is stored at the low end, so when you overflow your stack you corrupt your own thread_info. It looks like all of the architectures use a similar design. The thread_info is allocated here: http://lxr.linux.no/linux+v2.6.38/kernel/fork.c#L118 which is called from here: http://lxr.linux.no/linux+v2.6.38/kernel/fork.c#L260
Another question is if the "task_struct" is allocated in contiguous memory space as I don't see a "packed" attribute in the structure definition.
Those are mutually independant concepts. All allocated memory in the kernel is virtually contiguous. Packed data is when the packing between members in a structure is removed. <http://en.wikipedia.org/wiki/Data_structure_alignment>
If yes, do you know of an easy way of finding the offset of the "mm" field of the structure so that I can obtain its value? I guess a way is by finding it manually from the structure definition but it seems quite complex.
In C there is an offsetof macro: <http://linux.die.net/man/3/offsetof> <http://www.netrino.com/Embedded-Systems/How-To/C-Offsetof-Macro> -- Dave Hylands Shuswap, BC, Canada http://www.davehylands.com
participants (3)
-
Dave Hylands -
limp -
Mulyadi Santosa