From: Robert Szeleney <skyos@liwest.at>
To: linux-kernel@vger.kernel.org
Subject: Register saving and signal handling
Date: Tue, 25 Jan 2005 21:16:11 +0100 [thread overview]
Message-ID: <41F6A90B.4020005@liwest.at> (raw)
Hi!
This is my first time posting to the Linux kernel mailing-list, and I
hope someone can help me or at least explain following to me.
When a task gets interrupted by a signal, the do_signal() function is
called. Now, when the signal is not handled by the task and the
interrupted function returned -EINTR, the syscall gets restarted by
modifying the user mode EIP to point to the int 0x80 again.
When the task leaves the do_signal function, it will pop the saved
registers and return to the user mode and immediately do the syscall again.
But now to the actual question:
Let's make a new "test" system call function. Let's call it: sys_test
asmlinkage int sys_test(int para1, int para2)
{
para1++;
para2++;
kill( current->pid, SIGCHLD);
return -EINTR;
}
When compiling this function, GCC increments para1 and para2 by one.
para1 and para2 are stored on the kernel stack. The system call entry
assembler function pushed the registers containing this values from the
usermode on the stack.
But GCC actually modified the values on the stack here, the "live" data.
(which will be poped later again, right before returning to user mode)
After returning from this function, the system call wrapper checks for a
signal and calls do_signal. The do_signal call will restart the system
call by modifying the user mode EIP. Then, the system call wrapper will
pop the saved registers from the stack. But here I see this problem. The
already modified values for para1 and para2 will be popped. When the
system call is then start again, para1 and para2 don't have to original
value.
One can say, why are you modifying para1 and para2 then? Yes, this is
correct, but after compiling a few more test sources, I got following
problem:
asmlinkage int sys_test(int iSize)
{
printk("Size is: %d\n", iSize * sizeof(any_structure));
}
When compiling this, GCC produces following assembler:
....
sall $4, 8(%ebp)
....
which actually modifies the content of the stack holding the iSize
again. It is very difficult to keep track of such implicit stack
argument modifications.
Thus, when a signal is waiting and the syscall is restarted, iSize
contains a different value already.
So, does anyone else have such a problem? Is there any compiler flag
missing? Is this possible at all?
Thank you very much!
Robert!
Btw, please CC to mf204005@liwest.at too.
next reply other threads:[~2005-01-25 20:16 UTC|newest]
Thread overview: 2+ messages / expand[flat|nested] mbox.gz Atom feed top
2005-01-25 20:16 Robert Szeleney [this message]
2005-01-25 21:26 ` Register saving and signal handling linux-os
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=41F6A90B.4020005@liwest.at \
--to=skyos@liwest.at \
--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