All of lore.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 an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.