Re: ISS patch

Matthias Urlichs (smurf@noris.de)
20 Mar 1997 13:15:49 +0100


In linux.dev.kernel, article <Pine.LNX.3.95.970319095932.7354A-100000@cello.cs.iitm.ernet.in>,
Natchu Vishnu Priya <vishnu@cs.iitm.ernet.in> writes:

> > Speaking of this, I have a system that some people think is crashing due
> > to the primitive 1024fd patch I have installed on it (under 2.0.29).
> I use one in found http://www.linux.org.za/
>
That patch doesn't work.

It doesn't do anything about the stack overflow you'll get from select().
Note that select allocates six fd_bufs. They're either so big that they
overflow the stack, or you'll overrun them / get your file descriptors
ignored / whatever when you pass a larger number of file descriptors.

I have patched my kernel to do a two-page stack; that has reduced the
number of random crashes significantly (especially on machines with the
aic7xxx SCSI driver). Linus is against these patches because he thinks we
should fix the problems. I kindof agree, but in the meantime we have to
keep our systems running.

Here's the patch... no guarantee of completeness or non-Intel support -- it
works for me. :-/ (Unfortunately, right now it's difficult to liberate
enough round tuits for a better job at this.)

Index: kernel/linux/arch/i386/kernel/process.c
diff -u kernel/linux/arch/i386/kernel/process.c:1.1.1.6 kernel/linux/arch/i386/kernel/process.c:1.6
--- kernel/linux/arch/i386/kernel/process.c:1.1.1.6 Wed Oct 30 10:17:43 1996
+++ kernel/linux/arch/i386/kernel/process.c Mon Feb 10 19:22:51 1997
@@ -469,9 +469,9 @@
p->tss.fs = USER_DS;
p->tss.gs = KERNEL_DS;
p->tss.ss0 = KERNEL_DS;
- p->tss.esp0 = p->kernel_stack_page + PAGE_SIZE;
+ p->tss.esp0 = p->kernel_stack_page + kernel_stack_size;
p->tss.tr = _TSS(nr);
- childregs = ((struct pt_regs *) (p->kernel_stack_page + PAGE_SIZE)) - 1;
+ childregs = ((struct pt_regs *) (p->kernel_stack_page + kernel_stack_size)) - 1;
p->tss.esp = (unsigned long) childregs;
p->tss.eip = (unsigned long) ret_from_sys_call;
*childregs = *regs;
Index: kernel/linux/fs/proc/array.c
diff -u kernel/linux/fs/proc/array.c:1.1.1.6 kernel/linux/fs/proc/array.c:1.3
--- kernel/linux/fs/proc/array.c:1.1.1.6 Wed Oct 30 10:27:39 1996
+++ kernel/linux/fs/proc/array.c Mon Feb 10 21:05:26 1997
@@ -424,7 +445,7 @@
return 0;
ebp = p->tss.ebp;
do {
- if (ebp < stack_page || ebp >= 4092+stack_page)
+ if (ebp < stack_page || ebp >= kernel_stack_size-sizeof(unsigned long)+stack_page)
return 0;
eip = *(unsigned long *) (ebp+4);
if (eip < (unsigned long) interruptible_sleep_on
@@ -459,18 +480,18 @@
}

#if defined(__i386__)
-# define KSTK_EIP(tsk) (((unsigned long *)tsk->kernel_stack_page)[1019])
-# define KSTK_ESP(tsk) (((unsigned long *)tsk->kernel_stack_page)[1022])
+# define KSTK_EIP(tsk) (((unsigned long *)tsk->kernel_stack_page)[(kernel_stack_size/sizeof(unsigned long))-5])
+# define KSTK_ESP(tsk) (((unsigned long *)tsk->kernel_stack_page)[(kernel_stack_size/sizeof(unsigned long))-2])
#elif defined(__alpha__)
/*
* See arch/alpha/kernel/ptrace.c for details.
*/
-# define PT_REG(reg) (PAGE_SIZE - sizeof(struct pt_regs) \
+# define PT_REG(reg) (kernel_stack_size - sizeof(struct pt_regs) \
+ (long)&((struct pt_regs *)0)->reg)
# define KSTK_EIP(tsk) (*(unsigned long *)(tsk->kernel_stack_page + PT_REG(pc)))
# define KSTK_ESP(tsk) ((tsk) == current ? rdusp() : (tsk)->tss.usp)
#elif defined(__sparc__)
-# define PT_REG(reg) (PAGE_SIZE - sizeof(struct pt_regs) \
+# define PT_REG(reg) (kernel_stack_size - sizeof(struct pt_regs) \
+ (long)&((struct pt_regs *)0)->reg)
# define KSTK_EIP(tsk) (*(unsigned long *)(tsk->kernel_stack_page + PT_REG(pc)))
# define KSTK_ESP(tsk) (*(unsigned long *)(tsk->kernel_stack_page + PT_REG(u_regs[UREG_FP])))
Index: kernel/linux/include/asm-i386/processor.h
diff -u kernel/linux/include/asm-i386/processor.h:1.1.1.2 kernel/linux/include/asm-i386/processor.h:1.3
--- kernel/linux/include/asm-i386/processor.h:1.1.1.2 Sun Sep 15 12:34:23 1996
+++ kernel/linux/include/asm-i386/processor.h Mon Feb 10 20:49:28 1997
@@ -131,8 +131,10 @@
NULL, 0, 0, 0, 0 /* vm86_info */ \
}

-#define alloc_kernel_stack() __get_free_page(GFP_KERNEL)
-#define free_kernel_stack(page) free_page((page))
+#define STACK_SHIFT 1
+#define alloc_kernel_stack() __get_free_pages(GFP_KERNEL,STACK_SHIFT,0)
+#define free_kernel_stack(page) free_pages((page),STACK_SHIFT)
+#define kernel_stack_size (PAGE_SIZE<<STACK_SHIFT)

static inline void start_thread(struct pt_regs * regs, unsigned long eip, unsigned long esp)
{
Index: kernel/linux/kernel/sched.c
diff -u kernel/linux/kernel/sched.c:1.1.1.10 kernel/linux/kernel/sched.c:1.3
--- kernel/linux/kernel/sched.c:1.1.1.10 Sun Sep 15 12:31:38 1996
+++ kernel/linux/kernel/sched.c Mon Feb 10 19:23:07 1997
@@ -83,8 +83,8 @@

extern void mem_use(void);

-static unsigned long init_kernel_stack[1024] = { STACK_MAGIC, };
-unsigned long init_user_stack[1024] = { STACK_MAGIC, };
+static unsigned long init_kernel_stack[kernel_stack_size/sizeof(unsigned long)] = { STACK_MAGIC, };
+unsigned long init_user_stack[kernel_stack_size/sizeof(unsigned long)] = { STACK_MAGIC, };
static struct vm_area_struct init_mmap = INIT_MMAP;
static struct fs_struct init_fs = INIT_FS;
static struct files_struct init_files = INIT_FILES;