public inbox for linux-kernel@vger.kernel.org
 help / color / mirror / Atom feed
From: Brent Baccala <baccala@freesoft.org>
To: linux-kernel@vger.kernel.org
Subject: Do kernel threads need their own stack?
Date: Wed, 18 Jul 2001 03:16:27 -0400	[thread overview]
Message-ID: <3B5537CB.60B196E7@freesoft.org> (raw)

Hi -

I'm experimenting with some code to track down stack overruns in the
kernel, and I've stumbled across some stuff in the i386 kernel_thread
code that strikes me as very suspicious.  This is 2.4.6.

First off, here's kernel_thread from arch/i386/kernel/process.c:


int kernel_thread(int (*fn)(void *), void * arg, unsigned long flags)
{
        long retval, d0;

        __asm__ __volatile__(
                "movl %%esp,%%esi\n\t"
                "int $0x80\n\t"         /* Linux/i386 system call */
                "cmpl %%esp,%%esi\n\t"  /* child or parent? */
                "je 1f\n\t"             /* parent - jump */

 ... stuff omitted ...

                "1:\t"
                :"=&a" (retval), "=&S" (d0)
                :"0" (__NR_clone), "i" (__NR_exit),
                 "r" (arg), "r" (fn),
                 "b" (flags | CLONE_VM)
                : "memory");
        return retval;
}

The register constraints make sure that the "a" register (eax) is
operand 0 and contains __NR_clone to start with.  The "b" register (ebx)
contains (flags | CLONE_VM).  We save the stack pointer to ESI and INT
80, which (combined with the __NR_clone in eax) lands us in sys_clone
(same file):

asmlinkage int sys_clone(struct pt_regs regs)
{
        unsigned long clone_flags;
        unsigned long newsp;

        clone_flags = regs.ebx;
        newsp = regs.ecx;
        if (!newsp)
                newsp = regs.esp;
        return do_fork(clone_flags, newsp, &regs, 0);
}

The first thing I notice is that this function refers not only to the
clone flags in ebx, but also to a "newsp" in ecx - and ecx went
completely unmentioned in kernel_thread()!  A disassembly of
kernel_thread shows that "arg" winds up in ecx before the system call,
so I guess this is what gets passed to do_fork(), where (I think) it
ultimately ends up being the child's stack pointer.

In the case of bdflush_init() (end of fs/buffer.c), what gets passed in
as "arg" is the address of a semaphore on the stack - the only variable
allocated by the function.  That means that the child's stack pointer
starts at the bottom of the parent's stack in bdflush_init() and grows
down from there.  And if the parent never goes deeper into its stack
than bdflush_init(), I guess it works - sort of.

Anyway, I'm confused.  My analysis might be wrong, since I don't spend
that much time in the Linux kernel, but bottom line - doesn't
kernel_thread() need to allocate stack space for the child?  I mean,
even if everything else is shared, doesn't the child at least need it's
own stack?

I need to stare at this more, but maybe somebody else can explain what's
going on here.  At the very least, I think kernel_thread() needs to
explicitly specify what goes into the ECX register, because it looks to
me like it's just the luck of the compiler's draw...

-- 
                                        -bwb

                                        Brent Baccala
                                        baccala@freesoft.org

==============================================================================
       For news from freesoft.org, subscribe to announce@freesoft.org:
   
mailto:announce-request@freesoft.org?subject=subscribe&body=subscribe
==============================================================================

             reply	other threads:[~2001-07-18  7:16 UTC|newest]

Thread overview: 4+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2001-07-18  7:16 Brent Baccala [this message]
  -- strict thread matches above, loose matches on Subject: below --
2001-07-18 11:57 Do kernel threads need their own stack? Petr Vandrovec
2001-07-18 16:04 ` Brent Baccala
2001-07-19 10:57 alad

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=3B5537CB.60B196E7@freesoft.org \
    --to=baccala@freesoft.org \
    --cc=linux-kernel@vger.kernel.org \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox