From: Juan Perez-Sanchez <lithoxs@gmail.com>
To: linux-8086 <linux-8086@vger.kernel.org>
Subject: [PATCH] Fix to signal handler processing bug
Date: Fri, 6 Jul 2012 00:08:01 -0500 [thread overview]
Message-ID: <CAD6VGuajt9riSGj=t3m2QE+Sg+gaoZHApgwwp2RxQ6NtXH-UBQ@mail.gmail.com> (raw)
[-- Attachment #1: Type: text/plain, Size: 2148 bytes --]
Hi,
The attached patch fixes the signal handler processing bug
described in the last mail. You can use the procedure of that mail to
verify that the bug is really fixed.
Greetings,
Juan
PREVIOUS OPERATION AND BUGS
1. Checking of signals was done at two places: after a task switch and
at the end of a system call, before returning to user space. There is
the possibility of duplicating the work of manipulating the user stack
in a call to schedule() during a system call and again at the end of
the system call.
2. At the end of interrupts, a call to schedule is done before
returning to user space, but checking of signals will be done only
after a task switch, thus missing perfectly valid opportunities to
deliver signals.
3. The user stack layout is different during a system call than during
an interrupt. The function that modifies the user stack to call a
signal handler ("arch_setup_sighandler_stack") assumes the user stack
layout to be as during a system call.
4. However, installing a signal handler after an interrupt did not
(immediately) crash the task because the manipulation of the user
stack did not modify the return address, and the modification to the
user stack pointer was ignored. As result, the signal handler is not
called.
NEW OPERATION
1. Checking of signals is done at the end of a system call, before
returning to user space. Also at the end of any interrupt, if the
interrupt routine will return to user space. It is removed from the
function schedule. Now, checking of signals is done only at the
moments when it makes sense.
2. Function "arch_setup_sighandler_stack" accounts for the difference
in the user stack layout at different times.
3. User stack pointer is reloaded from the task structure before
returning to user space from an interrupt. Now, delivery of signals
always work.
OTHER CHANGES
1. A small optimization to reduce code size was done to function
"run_init_process".
2. Despite the above optimization, there is an increase in code size
of 32 bytes.
The Image builded without errors. The kernel was tested with QEMU and
dioscuri emulators. Also in a PPro pc booting from floppy.
[-- Attachment #2: elksI.patch --]
[-- Type: text/x-diff, Size: 10402 bytes --]
diff -Nurb elks.orig/arch/i86/kernel/irqtab.c elks/arch/i86/kernel/irqtab.c
--- elks.orig/arch/i86/kernel/irqtab.c 2012-06-20 13:45:28.000000000 -0500
+++ elks/arch/i86/kernel/irqtab.c 2012-06-26 14:14:08.000000000 -0500
@@ -19,19 +19,17 @@
#define SEG_IRQ_DATA es
#define stashed_ds [0]
- /* _our_ds [18] bios16.c */
#else
#define SEG_IRQ_DATA cs
- #define stashed_ds cseg_stashed_ds
#ifndef S_SPLINT_S
#asm
- .globl cseg_stashed_ds
+ .globl stashed_ds
.even
-cseg_stashed_ds:
+stashed_ds:
.word 0
#endasm
@@ -39,6 +37,8 @@
#endif
+extern void sig_check(void);
+
void irqtab_init(void)
{
#ifndef S_SPLINT_S
@@ -413,20 +413,22 @@
mov ss,bx ! /* Set SS: right */
mov bx,_current
cmp dx,TASK_USER_SS[bx] ! entry ss = current->t_regs.ss?
- je utask ! Switch to kernel
-!
-! Bios etc - switch to interrupt stack
-!
- mov sp,#_intstack
- j ktask
+ jne btask ! Switch to interrupt stack
!
! User task. Extract kernel SP. (BX already holds current)
! At this point, the kernel stack is empty. Thus, we can load
! the kernel stack pointer without accesing memory
!
-utask:
+ mov TASK_USER_SP[bx],sp
lea sp,TASK_KSTKTOP[bx] ! switch to kernel stack ptr
+ lea bp,TASK_USER_SP[bx]
inc ch ! Switch allowable
+ j updct
+!
+! Bios etc - switch to interrupt stack
+!
+btask:
+ mov sp,#_intstack
!
! In ktask state we have a suitable stack. It might be
! better to use the intstack..
@@ -437,8 +439,8 @@
! leave them in stashed_ss/sp as we could re-enter the
! routine on a reschedule.
! */
- push bp ! push entry SP
push dx ! push entry SS
+ push bp ! push entry SP
!
! The registers are now stored. Remember where
!
@@ -446,6 +448,7 @@
!
! Update intr_count
!
+updct:
inc _intr_count
!
! We are on a suitable stack and ch says whether
@@ -513,40 +516,40 @@
! mov bx,_need_resched ! Schedule needed
! cmp bx,#0 !
! je nosched ! No
- call _schedule ! Task switch
!
! This path will return directly to user space
!
- pop ax ! stacked SS
- pop cx ! stacked SP
-#ifdef CONFIG_ADVANCED_MM
+ call _schedule ! Task switch
mov bx,_current
- mov ax, TASK_USER_SS[bx] ! user ds
- mov bp, sp
-; mov 12[bp], ax ! change the es in the stack
-; mov 14[bp], ax ! change the ds in the stack
-#endif
+ mov 8[bx],#1
+ call _sig_check ! Check signals
!
! At this point, the kernel stack is empty. Thus, there is no
! need to save the kernel stack pointer.
!
+ mov bx,_current
+ mov sp,TASK_USER_SP[bx]
+#ifndef CONFIG_ADVANCED_MM
+ mov ss,TASK_USER_SS[bx]
+#else
+ mov ax, TASK_USER_SS[bx] ! user ds
+ mov bp, sp
+ mov ss, ax
+ mov 12[bp], ax ! change the es in the stack
+ mov 14[bp], ax ! change the ds in the stack
+#endif
j noschedpop
-
-nosched:
!
! Now we have to rescue our stack pointer/segment.
!
- pop ax ! SS
+nosched:
pop cx ! SP
-!
-! Switch stacks to the interrupting stack
-!
-noschedpop:
- mov ss,ax
+ pop ss ! SS
mov sp,cx
!
! Restore registers and return
!
+noschedpop:
pop bp
pop di
pop si
diff -Nurb elks.orig/arch/i86/kernel/process.c elks/arch/i86/kernel/process.c
--- elks.orig/arch/i86/kernel/process.c 2012-06-20 13:45:28.000000000 -0500
+++ elks/arch/i86/kernel/process.c 2012-06-26 14:16:09.000000000 -0500
@@ -50,8 +50,6 @@
#else
-#define stashed_ds cseg_stashed_ds
-
#ifndef S_SPLINT_S
#asm
@@ -63,7 +61,7 @@
* linker doesnt store them in block.
*/
- .extern cseg_stashed_ds
+ .extern stashed_ds
/* and now code */
@@ -79,11 +77,8 @@
void sig_check(void)
{
- register __ptask currentp = current;
-
- if (currentp->signal)
- (void) do_signal();
- currentp->signal = 0;
+ if (current->signal)
+ do_signal();
}
#ifndef S_SPLINT_S
@@ -189,6 +184,8 @@
pop ax
call _syscall
push ax
+ mov bx,_current
+ mov 8[bx],#0
call _sig_check
pop ax
pop bx
@@ -310,14 +307,7 @@
*/
{
#asm
- cli
- mov bx, _current
- mov sp, TASK_USER_SP[bx] ! user stack offset
- mov ax, TASK_USER_SS[bx] ! user stack segment
- mov ss, ax
- mov ds, ax
- mov es, ax
- iret ! reloads flags = >reenables interrupts
+ br _ret_from_syscall
#endasm
}
#endif
@@ -411,16 +401,23 @@
void arch_setup_sighandler_stack(register struct task_struct *t,
__sighandler_t addr,unsigned signr)
{
- debug4("Stack %x was %x %x %x\n", addr, get_ustack(t,0), get_ustack(t,2),
- get_ustack(t,4));
- put_ustack(t, 2, (int) get_ustack(t,0));
- put_ustack(t, 0, (int) get_ustack(t,4));
- put_ustack(t, 4, (int) signr);
- put_ustack(t, -2, (int)t->t_regs.cs);
- put_ustack(t, -4, (int) addr);
+ register char *i;
+
+ i = 0;
+ if(t->t_regs.bx != 0) {
+ for(; (int)i < 18; i += 2)
+ put_ustack(t, (int)i-4, (int)get_ustack(t,(int)i));
+ }
+ debug4("Stack %x was %x %x %x\n", addr, get_ustack(t,(int)i), get_ustack(t,(int)i+2),
+ get_ustack(t,(int)i+4));
+ put_ustack(t, (int)i-4, (int)addr);
+ put_ustack(t, (int)i-2, (int)get_ustack(t,(int)i+2));
+ put_ustack(t, (int)i+2, (int)get_ustack(t,(int)i));
+ put_ustack(t, (int)i, (int)get_ustack(t,(int)i+4));
+ put_ustack(t, (int)i+4, (int)signr);
t->t_regs.sp -= 4;
- debug5("Stack is %x %x %x %x %x\n", get_ustack(t,0), get_ustack(t,2),
- get_ustack(t,4),get_ustack(t,6), get_ustack(t,8));
+ debug5("Stack is %x %x %x %x %x\n", get_ustack(t,(int)i), get_ustack(t,(int)i+2),
+ get_ustack(t,(int)i+4),get_ustack(t,(int)i+6), get_ustack(t,(int)i+8));
}
/*
diff -Nurb elks.orig/arch/i86/kernel/signal.c elks/arch/i86/kernel/signal.c
--- elks.orig/arch/i86/kernel/signal.c 2012-05-11 13:26:27.000000000 -0500
+++ elks/arch/i86/kernel/signal.c 2012-06-25 13:06:36.000000000 -0500
@@ -24,10 +24,9 @@
register struct sigaction *sa;
unsigned signr;
- while (currentp->signal) {
+ while ((currentp->signal &= ((1 << NSIG) - 1))) {
signr = find_first_non_zero_bit(¤tp->signal, NSIG);
- if (signr == NSIG)
- panic("No signal set!\n");
+ clear_bit(signr, ¤tp->signal);
debug2("Process %d has signal %d.\n", currentp->pid, signr);
sa = ¤tp->sig.action[signr];
@@ -81,6 +80,7 @@
arch_setup_sighandler_stack(current, sa->sa_handler, signr);
debug1("Stack at %x\n", current->t_regs.sp);
sa->sa_handler = SIG_DFL;
+ currentp->signal = 0;
return 1;
}
diff -Nurb elks.orig/arch/i86/sibo/irqtab.c elks/arch/i86/sibo/irqtab.c
--- elks.orig/arch/i86/sibo/irqtab.c 2012-06-20 13:45:28.000000000 -0500
+++ elks/arch/i86/sibo/irqtab.c 2012-06-26 14:19:40.000000000 -0500
@@ -19,19 +19,17 @@
#define SEG_IRQ_DATA es
#define stashed_ds [0]
- /* _our_ds [18] bios16.c */
#else
#define SEG_IRQ_DATA cs
- #define stashed_ds cseg_stashed_ds
#ifndef S_SPLINT_S
#asm
- .globl cseg_stashed_ds
+ .globl stashed_ds
.even
-cseg_stashed_ds:
+stashed_ds:
.word 0
#endasm
@@ -39,6 +37,8 @@
#endif
+extern void sig_check(void);
+
void irqtab_init(void)
{
#ifndef S_SPLINT_S
@@ -412,20 +412,22 @@
mov ss,bx ! /* Set SS: right */
mov bx,_current
cmp dx,TASK_USER_SS[bx] ! entry ss = current->t_regs.ss?
- je utask ! Switch to kernel
-!
-! Bios etc - switch to interrupt stack
-!
- mov sp,#_intstack
- j ktask
+ jne btask ! Switch to interrupt stack
!
! User task. Extract kernel SP. (BX already holds current)
! At this point, the kernel stack is empty. Thus, we can load
! the kernel stack pointer without accesing memory
!
-utask:
+ mov TASK_USER_SP[bx],sp
lea sp,TASK_KSTKTOP[bx] ! switch to kernel stack ptr
+ lea bp,TASK_USER_SP[bx]
inc ch ! Switch allowable
+ j updct
+!
+! Bios etc - switch to interrupt stack
+!
+btask:
+ mov sp,#_intstack
!
! In ktask state we have a suitable stack. It might be
! better to use the intstack..
@@ -436,8 +438,8 @@
! leave them in stashed_ss/sp as we could re-enter the
! routine on a reschedule.
! */
- push bp ! push entry SP
push dx ! push entry SS
+ push bp ! push entry SP
!
! The registers are now stored. Remember where
!
@@ -445,6 +447,7 @@
!
! Update intr_count
!
+updct:
inc _intr_count
!
! We are on a suitable stack and ch says whether
@@ -483,40 +486,40 @@
! mov bx,_need_resched ! Schedule needed
! cmp bx,#0 !
! je nosched ! No
- call _schedule ! Task switch
!
! This path will return directly to user space
!
- pop ax ! stacked SS
- pop cx ! stacked SP
-#ifdef CONFIG_ADVANCED_MM
+ call _schedule ! Task switch
mov bx,_current
- mov ax, TASK_USER_SS[bx] ! user ds
- mov bp, sp
-; mov 12[bp], ax ! change the es in the stack
-; mov 14[bp], ax ! change the ds in the stack
-#endif
+ mov 8[bx],#1
+ call _sig_check ! Check signals
!
! At this point, the kernel stack is empty. Thus, there in no
! need to save the kernel stack pointer.
!
+ mov bx,_current
+ mov sp,TASK_USER_SP[bx]
+#ifndef CONFIG_ADVANCED_MM
+ mov ss,TASK_USER_SS[bx]
+#else
+ mov ax, TASK_USER_SS[bx] ! user ds
+ mov bp, sp
+ mov ss, ax
+ mov 12[bp], ax ! change the es in the stack
+ mov 14[bp], ax ! change the ds in the stack
+#endif
j noschedpop
-
-nosched:
!
! Now we have to rescue our stack pointer/segment.
!
- pop ax ! SS
+nosched:
pop cx ! SP
-!
-! Switch stacks to the interrupting stack
-!
-noschedpop:
- mov ss,ax
+ pop ss ! SS
mov sp,cx
!
! Restore registers and return
!
+noschedpop:
pop bp
pop di
pop si
diff -Nurb elks.orig/kernel/sched.c elks/kernel/sched.c
--- elks.orig/kernel/sched.c 2012-06-20 13:45:28.000000000 -0500
+++ elks/kernel/sched.c 2012-06-25 13:06:36.000000000 -0500
@@ -24,8 +24,6 @@
extern int intr_count;
-extern int do_signal(void);
-
static void run_timer_list();
void add_to_runqueue(register struct task_struct *p)
@@ -150,11 +148,6 @@
tswitch(); /* Won't return for a new task */
- if(current->signal){
- do_signal();
- current->signal = 0;
- }
-
if (timeout) {
del_timer(&timer);
}
reply other threads:[~2012-07-06 5:08 UTC|newest]
Thread overview: [no followups] expand[flat|nested] mbox.gz Atom feed
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='CAD6VGuajt9riSGj=t3m2QE+Sg+gaoZHApgwwp2RxQ6NtXH-UBQ@mail.gmail.com' \
--to=lithoxs@gmail.com \
--cc=linux-8086@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 read-only IMAP folder(s) and NNTP newsgroup(s).