Re: Access thread stack from another thread

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



On Sun, 2010-06-06 at 13:49 +0530, Joel Fernandes wrote:
> On Sun, Jun 6, 2010 at 3:06 AM, Vimal <j.vimal@xxxxxxxxx> wrote:
> > Hi Joel,
> >
> >>
> >> now i have a question, even if they share the same vm address space -
> >> they definitely can't share the userspace stack, i'm sure the kernel
> >> would have to reset it up in the same address space of the group of
> >> threads but I really don't know how that works - could you share your
> >> thoughts on this?
> >
> > I get what you're telling.  I don't know how it's implemented, but it
> > would be easier to think of it this way:  A thread control block has
> > pointers to the process control block (which contains the list of fds,
> > sighands, the page tables, etc.), and the thread context (the set of
> > general purpose registers).  So two threads of the same process will
> > have the same PCB but different TCB.  So when a context switch occurs
> > between threads of different PCBs, it's a context switch to a
> > different process.
> 
> I know we're digressing slightly from the original topic a bit a bit
> I'm just curious to know how/where the new user-mode stack is setup
> for a thread that shares the address space of the cloning thread.
> 
> It appears that a new user mode stack is setup in the load_binary
> function which is called during exec() . But I don't see where the new
> stack for the thread is created during a clone() with CLONE_VM flag
> set.
> 
> During clone, the address spaces are shared , task_struct and
> thread_info are copied, a new kernel mode stack is created, but I
> don't see where a new userspace stack for the new thread is created.
> neither is the stack pointer value changed in the new task_struct
> (process control block), it is simply a copy of the process that
> cloned/forked.
> 
> I wonder if this is setup in userspace itself by a thread library?

Have you tried "man clone"?

This states that the clone() api is:
 int clone(int (*fn)(void *), void *child_stack,
                 int flags, void *arg, ...


Param child_stack is something that the *caller* of the clone() function
must allocate. Presumably this is done via a malloc() or similar, ie the
new thread's stack normally lives within the heap of the parent process.

Hmm..wonder how stack-overflow detection is done for threads..

File include/asm-generic/unistd.h defines syscalls, mapping clone to
sys_clone [1][2]. The sys_clone implementation can be found in an
arch-specific file, eg arch/x86/kernel/process.c. This then just
forwards to do_fork() in kernel/fork.c, where the new stack is passed as
an input param.

do_fork() calls copy_process() which creates a new task_struct with
dup_task_struct(current), then stores the stack start address into the
task_struct. So when the scheduler switches to this newly-created
thread's task_struct, that new stack address gets loaded into the
stack-pointer register.

You talk about "kernel mode" and "user mode" stacks, but AFAIK there is
no such distinction. I'm pretty sure that when a syscall occurs, the
kernel code that executes runs on the calling thread's stack. There are
things called "kernel threads" which do background tasks for the kernel,
but they are never visible to user-space. 

I'm not sure what you mean by CLONE_VM above. If the VM is being cloned,
then this is a traditional "fork process" call, and so the child can
have exactly the same stack-pointer as the parent, because it is running
with (effectively) a copy of the parent's memory. In this case, the
stack_address param to clone can be zero which causes the parent's
stack-pointer to be used. But you were asking about "a thread that
shares the address space of the cloning thread", so CLONE_VM is not set.

Just one note about your original goal of reading from the stack of some
other process or thread: presumably you will need to somehow stop that
thread before reading - otherwise, the stack will be changing as you
read it which is not healthy. This isn't a problem when a thread makes a
normal system call, as the kernel code is running in the caller's
context, and so can safely peek at "its own" stack. Not sure how you
would achieve this - or why anything except a debugger would need to do
so.

By the way, why are you trying to read from a thread's stack?

[1] The parameters to sys_clone don't quite match the clone() api. It
seems that libc partially handles clone() in user-space; in the libc
source I found file "sysdeps/unix/sysv/linux/i386/clone.S" which I can't
really understand, as my x86 assembly code knowledge is near zero.
However the file has these comments:
  /* clone() is even more special than fork() as it mucks with stacks
   and invokes a function in the right context after its all over.  */
and
  /* Save the function pointer as the zeroth argument.
   It will be popped off in the child in the ebx frobbing below.  */
which suggest that this is why the sys_clone() prototype doesn't exactly
match the clone() prototype.

[2] unistd.h seems to be declaring the clone syscall# as 220:
  #define __NR_clone 220
  __SYSCALL(__NR_clone, sys_clone)	/* .long sys_clone_wrapper */
but libc's clone.S seems to be using 120:
  #define __NR_clone 120
  #define SYS_clone 120
although oddly nothing appears to ever use these #defines. Can anyone
explain this mismatch?

Regards,
Simon




--
To unsubscribe from this list: send an email with
"unsubscribe kernelnewbies" to ecartis@xxxxxxxxxxxx
Please read the FAQ at http://kernelnewbies.org/FAQ



[Index of Archives]     [Newbies FAQ]     [Linux Kernel Mentors]     [Linux Kernel Development]     [IETF Annouce]     [Git]     [Networking]     [Security]     [Bugtraq]     [Yosemite]     [MIPS Linux]     [ARM Linux]     [Linux RAID]     [Linux SCSI]     [Linux ACPI]
  Powered by Linux