Event delivery bug

From: Ronald Oussoren <roussor_at_nospam.org>
Date: Tue Apr 18 1995 - 01:49:52 PDT

Hi,

I think the event mechanism for the i386 version of VSTa contains a bug in
the assembly part of the library (in mach/syscalls.s).

My understanding of the event delivery is as follows:
  - events are delivered by the kernel using sendev() (mach/trap.c). This
  function copies an event structure, containing the event string, the old
  stack pointer and the old IP on the stack. The stack pointer is updated
  to indicate this, and the IP is changed to the notify-handler of the process.
  - The handler in the library calls a user defined C function, after setting
  up a stack frame.
  - The assembly language handler then restores the old state, and returns to
  the old IP, letting the program continue at the place it was when the event
  was delivered (without reentering the kernel).

The problem is with the last step, returning to the old IP, from mach/syscalls.s:

>asm_handler:
> pusha /* Save state */
> pushf
> lea 0x28(%esp),%eax /* Point to event string */
> push %eax /* Leave as arg to routine */
> movl c_handler,%eax
> call %eax
> lea 4(%esp),%esp /* Drop arg */
> popf /* Restore state */
> popa
> pop %esp /* Skip event string */

At this point, the stack pointer will be restored to its old location, where
it was before the event was delivered (this is due to the layout of the event
structure that was pushed). I think that the old IP is now just below the
top of the stack (that is, when a value would be pushed on top of the stack,
it would erase the old IP).

> ret /* Resume at old IP */

The 'ret' instruction returns to the address on top of the stack, I think
this is _not_ the old IP!

(There really is a problem, I included the source for two small programs,
 event[.c] and notify[.c]. When an event is send to 'event', it will print the
 event to standard error and then continue. However, when I sent an event to
it using the 'notify' program, 'event' will stop after printing that event, and
the 'fault' event (a segmentation fault)

-- event.c

void handler(char *s)
{
   write(2, s, strlen(s));
   write(2, "\n");
}

int main(void)
{
   notify_handler(handler);
   while(1){
        /* DO NOTHING */
   }
}

-- notify.c

int main(int argc, char **argv)
{
   notify(atoi(argv[1]), 0, argv[2]);
}

[NOTE: I haven't checked if the included code fragments compile, I rewrote
 then from memory, the 'orginals' are at my home machine, not here where I have
 net access.]
)

I hope someone can fix this, I don't know enough of assembly to do it.

        Ronald
Received on Wed Apr 19 06:57:49 1995

This archive was generated by hypermail 2.1.8 : Thu Sep 22 2005 - 15:12:27 PDT