linux-kernel.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
From: dvorak <dvorak@xs4all.nl>
To: linux-kernel@vger.kernel.org
Subject: Syscall changes registers beyond %eax, on linux-i386
Date: Thu, 19 Sep 2002 16:45:33 +0200	[thread overview]
Message-ID: <20020919144533.GB2976@xs4all.nl> (raw)

[-- Attachment #1: Type: text/plain, Size: 2095 bytes --]

Hi,

recently i came across a situation were on linux-i386 not only %eax was
altered after a syscall but also %ebx. I tracked this problem down, to
gcc re-using a variable passed to a function.

This was found on a debian system with a 2.4.17 kernel compiled with gcc
2.95.2 and verified on another system, kernel 2.4.18 compiled with 2.95.4 
Attached is small program to test for this 'bug'

a syscall gets his data off the stack, the stack looks like:

saved(edx)
saved(ecx)
saved(ebx)
return_addres 	(somewhere in entry.S)

When the syscall is called.

the register came there through use of 'SAVE_ALL'.

After the syscall returns these registers are restored using RESTORE_ALL
and execution is transferred to userland again.

A short snippet of sys_poll, with irrelavant data removed.

sys_poll(struct pollfd *ufds, .. , ..) {
    ...
    ufds++;
    ...
}

It seems that gcc in certain cases optimizes in such a way that it changes
the variable ufds as placed on the stack directly. Which results in saved(ebx)
being overwritten and thus in a changed %ebx on return from the system call.

I don't know if this is considered a bug, and if it is, from whom.
If it's not a bug it means low-level userland programs need to be rewritten
to store all registers on a syscall and restore them on return.

It shouldn't be a bug in gcc, since the C-standard doesn't talk about how to 
pass variables and stuff. So it seems like a kernel(-gcc-interaction) bug.

To solve this issue 2 solutions spring to mind
1) add a flag to gcc to tell it that it shouldn't do this optimization, this
   won't work with the gcc's already out there.
2) When calling a syscall explicitly push all variable an extra time, since
   the code in entry.S doesn't know the amount of variables to a syscall it
   needs to push all theoretical 6 parameters every time, a not so nice
   overhead.


I hope someone can shed some light on this issue, i am not myself reading
the linux-kernel mailing list, and would like to be cc'd if possible (i'll
also check the archives so it's not 100% needed).

Thanks in advance,
  Dvorak

[-- Attachment #2: reg-bug.c --]
[-- Type: text/plain, Size: 1241 bytes --]

/*
 * usage is easy, though not very friendly:
 * gcc reg-bug.c
 * ./a.out | od -tx4
 * <ENTER>
 * if the values outputted by hexdump are different the 'bug' is present
 * else the bug is not present
 * on a system without the bug:

dvorak$ dmesg | head -1
Linux version 2.2.21 (kernel@debian) (gcc version 2.95.4 20011002 (Debian prerelease)) #6 Sat Sep 7 22:48:42 CEST 2002
dvorak$ gcc reg-bug.c
dvorak$ ./a.out | od -tx4

0000000 bff7de6c bff7de6c
 
 * on a 'buggy' system:
 *

(m4xx) dmesg | head -1
(m4xx) Linux version 2.4.18 (maxx@meuuh) (gcc version 2.95.4 20011002 (Debian
+prerelease)) #2 Mon Jul 29 17:01:30 CEST 2002
(m4xx) $ gcc reg-bug.c
(m4xx) $ ./a.out | od -tx4
(m4xx) 0000000 bffffdcc bffffdbc

 */
int main(void)
{
    __asm__("
        pushl   $0x00010001 
        pushl   $0x0
        pushl   $0x00010001 
        pushl   $0x1
        movl    %esp, %ebx
        pushl   %ebx
        movl    $0x2, %ecx
        movl    $0xa8, %eax
        movl    $(-1), %edx
        int     $0x80
        pushl   %ebx
        movl    %esp, %ecx
        movl    $0x08, %edx
        movl    $0x04, %eax
        movl    $0x01, %ebx
        int     $0x80
        movl    $0x01, %eax
        xorl    %ebx, %ebx
        int     $0x80
   ");
}

             reply	other threads:[~2002-09-19 14:40 UTC|newest]

Thread overview: 29+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2002-09-19 14:45 dvorak [this message]
2002-09-19 16:11 ` Syscall changes registers beyond %eax, on linux-i386 Richard B. Johnson
2002-09-19 17:09   ` Brian Gerst
2002-09-19 17:22     ` Richard B. Johnson
2002-09-19 17:51       ` Brian Gerst
2002-09-19 18:30         ` Richard B. Johnson
2002-09-19 17:59       ` dvorak
2002-09-19 18:32         ` Richard B. Johnson
2002-09-19 17:44 Petr Vandrovec
2002-09-19 18:04 ` Brian Gerst
2002-09-19 18:30   ` Richard Henderson
2002-09-19 18:51     ` Brian Gerst
2002-09-19 18:57       ` Richard Henderson
2002-09-19 19:40         ` Richard B. Johnson
2002-09-19 19:41           ` Richard Henderson
2002-09-19 19:53             ` Richard B. Johnson
2002-09-19 22:46               ` J.A. Magallon
2002-09-20 12:27                 ` Richard B. Johnson
2002-09-20 17:16                   ` Richard Henderson
2002-09-22  1:33               ` Pavel Machek
2002-09-23 13:11                 ` Richard B. Johnson
2002-09-23 18:31                   ` Pavel Machek
2002-09-19 19:18       ` Richard B. Johnson
2002-09-19 19:24   ` Daniel Jacobowitz
2002-09-19 20:25     ` Mikael Pettersson
2002-09-20  8:32       ` george anzinger
2002-09-21  6:19         ` Richard Henderson
2002-09-21  8:09           ` george anzinger
2002-09-21 15:08             ` Richard Henderson

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=20020919144533.GB2976@xs4all.nl \
    --to=dvorak@xs4all.nl \
    --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;
as well as URLs for NNTP newsgroup(s).