Commit 7d09d324 authored by William Lee Irwin III's avatar William Lee Irwin III Committed by Linus Torvalds

[PATCH] vm86 IRQ bugfix

vm86 does broken tasklist scanning for matching task_struct pointers,
which is oopsable. This registers a notifier for it to GC vm86 IRQ's in
release_thread() and removes the broken tasklist scanning.

This bugfix is in 2.4.x and has been in 2.5.x-dj for an extended period
of time.
parent b0830bd2
...@@ -44,6 +44,7 @@ ...@@ -44,6 +44,7 @@
#include <asm/ldt.h> #include <asm/ldt.h>
#include <asm/processor.h> #include <asm/processor.h>
#include <asm/i387.h> #include <asm/i387.h>
#include <asm/irq.h>
#include <asm/desc.h> #include <asm/desc.h>
#ifdef CONFIG_MATH_EMULATION #ifdef CONFIG_MATH_EMULATION
#include <asm/math_emu.h> #include <asm/math_emu.h>
...@@ -269,6 +270,8 @@ void release_thread(struct task_struct *dead_task) ...@@ -269,6 +270,8 @@ void release_thread(struct task_struct *dead_task)
BUG(); BUG();
} }
} }
release_x86_irqs(dead_task);
} }
/* /*
......
...@@ -708,23 +708,6 @@ static inline void free_vm86_irq(int irqnumber) ...@@ -708,23 +708,6 @@ static inline void free_vm86_irq(int irqnumber)
spin_unlock_irqrestore(&irqbits_lock, flags); spin_unlock_irqrestore(&irqbits_lock, flags);
} }
static inline int task_valid(struct task_struct *tsk)
{
struct task_struct *g, *p;
int ret = 0;
read_lock(&tasklist_lock);
do_each_thread(g, p)
if ((p == tsk) && (p->sig)) {
ret = 1;
goto out;
}
while_each_thread(g, p);
out:
read_unlock(&tasklist_lock);
return ret;
}
void release_x86_irqs(struct task_struct *task) void release_x86_irqs(struct task_struct *task)
{ {
int i; int i;
...@@ -733,17 +716,6 @@ void release_x86_irqs(struct task_struct *task) ...@@ -733,17 +716,6 @@ void release_x86_irqs(struct task_struct *task)
free_vm86_irq(i); free_vm86_irq(i);
} }
static inline void handle_irq_zombies(void)
{
int i;
for (i=3; i<16; i++) {
if (vm86_irqs[i].tsk) {
if (task_valid(vm86_irqs[i].tsk)) continue;
free_vm86_irq(i);
}
}
}
static inline int get_and_reset_irq(int irqnumber) static inline int get_and_reset_irq(int irqnumber)
{ {
int bit; int bit;
...@@ -772,7 +744,6 @@ static int do_vm86_irq_handling(int subfunction, int irqnumber) ...@@ -772,7 +744,6 @@ static int do_vm86_irq_handling(int subfunction, int irqnumber)
case VM86_REQUEST_IRQ: { case VM86_REQUEST_IRQ: {
int sig = irqnumber >> 8; int sig = irqnumber >> 8;
int irq = irqnumber & 255; int irq = irqnumber & 255;
handle_irq_zombies();
if (!capable(CAP_SYS_ADMIN)) return -EPERM; if (!capable(CAP_SYS_ADMIN)) return -EPERM;
if (!((1 << sig) & ALLOWED_SIGS)) return -EPERM; if (!((1 << sig) & ALLOWED_SIGS)) return -EPERM;
if ( (irq<3) || (irq>15) ) return -EPERM; if ( (irq<3) || (irq>15) ) return -EPERM;
...@@ -784,7 +755,6 @@ static int do_vm86_irq_handling(int subfunction, int irqnumber) ...@@ -784,7 +755,6 @@ static int do_vm86_irq_handling(int subfunction, int irqnumber)
return irq; return irq;
} }
case VM86_FREE_IRQ: { case VM86_FREE_IRQ: {
handle_irq_zombies();
if ( (irqnumber<3) || (irqnumber>15) ) return -EPERM; if ( (irqnumber<3) || (irqnumber>15) ) return -EPERM;
if (!vm86_irqs[irqnumber].tsk) return 0; if (!vm86_irqs[irqnumber].tsk) return 0;
if (vm86_irqs[irqnumber].tsk != current) return -EPERM; if (vm86_irqs[irqnumber].tsk != current) return -EPERM;
......
...@@ -23,6 +23,7 @@ static __inline__ int irq_cannonicalize(int irq) ...@@ -23,6 +23,7 @@ static __inline__ int irq_cannonicalize(int irq)
extern void disable_irq(unsigned int); extern void disable_irq(unsigned int);
extern void disable_irq_nosync(unsigned int); extern void disable_irq_nosync(unsigned int);
extern void enable_irq(unsigned int); extern void enable_irq(unsigned int);
extern void release_x86_irqs(struct task_struct *);
#ifdef CONFIG_X86_LOCAL_APIC #ifdef CONFIG_X86_LOCAL_APIC
#define ARCH_HAS_NMI_WATCHDOG /* See include/linux/nmi.h */ #define ARCH_HAS_NMI_WATCHDOG /* See include/linux/nmi.h */
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment