diff -u --recursive --new-file v2.0.32/linux/Makefile linux/Makefile
--- v2.0.32/linux/Makefile	Tue Dec  2 13:52:30 1997
+++ linux/Makefile	Wed Nov 26 15:31:03 1997
@@ -1,6 +1,6 @@
 VERSION = 2
 PATCHLEVEL = 0
-SUBLEVEL = 32
+SUBLEVEL = 33
 
 ARCH = i386
 
diff -u --recursive --new-file v2.0.32/linux/arch/i386/kernel/head.S linux/arch/i386/kernel/head.S
--- v2.0.32/linux/arch/i386/kernel/head.S	Tue Dec  2 13:52:31 1997
+++ linux/arch/i386/kernel/head.S	Tue Dec  2 13:58:53 1997
@@ -260,7 +260,7 @@
 	movw %dx,%ax		/* selector = 0x0010 = cs */
 	movw $0x8E00,%dx	/* interrupt gate - dpl=0, present */
 
-	lea SYMBOL_NAME(__idt),%edi
+	lea SYMBOL_NAME(idt),%edi
 	mov $256,%ecx
 rp_sidt:
 	movl %eax,(%edi)
@@ -342,6 +342,11 @@
 	.long SYMBOL_NAME(init_user_stack)+4096
 	.long KERNEL_DS
 
+/* NOTE: keep the idt short behind the above '.org 0x6000'
+	 It must fit completely within _one_ page */
+ENTRY(idt)
+	.fill 256,8,0		# idt is uninitialized
+
 /* This is the default interrupt "handler" :-) */
 int_msg:
 	.asciz "Unknown interrupt\n"
@@ -376,10 +381,7 @@
 .word 0
 idt_descr:
 	.word 256*8-1		# idt contains 256 entries
-	.long 0xc0000000+SYMBOL_NAME(__idt)
-
-ENTRY(__idt)
-	.fill 256,8,0		# idt is uninitialized
+	.long 0xc0000000+SYMBOL_NAME(idt)
 
 	ALIGN
 .word 0
diff -u --recursive --new-file v2.0.32/linux/arch/i386/kernel/traps.c linux/arch/i386/kernel/traps.c
--- v2.0.32/linux/arch/i386/kernel/traps.c	Tue Dec  2 13:52:31 1997
+++ linux/arch/i386/kernel/traps.c	Tue Dec  2 13:58:53 1997
@@ -337,7 +337,6 @@
 
 #endif /* CONFIG_MATH_EMULATION */
 
-struct desc_struct *idt = __idt+0;
 struct {
 	unsigned short limit;
 	unsigned long addr __attribute__((packed));
@@ -348,33 +347,35 @@
 	pgd_t * pgd;
 	pmd_t * pmd;
 	pte_t * pte;
-	unsigned long twopage;
-	struct desc_struct *new_idt;
+	unsigned long page;
+	unsigned long idtpage = (unsigned long)idt;
+	struct desc_struct *alias_idt;
 
-	printk("moving IDT ... ");
+	printk("alias mapping IDT readonly ... ");
 
-	twopage = (unsigned long) vmalloc (2*PAGE_SIZE);
-
-	new_idt = (void *)(twopage + 4096-7*8);
-
-	memcpy(new_idt,idt,256*8);
+		/* just to get free address space */
+	page = (unsigned long) vmalloc (PAGE_SIZE);
 
+	alias_idt = (void *)(page + (idtpage & ~PAGE_MASK));
 	idt_descriptor.limit = 256*8-1;
-	idt_descriptor.addr = VMALLOC_VMADDR(new_idt);
-
-	 __asm__ __volatile__("\tlidt %0": "=m" (idt_descriptor));
-	 idt = new_idt;
+	idt_descriptor.addr = VMALLOC_VMADDR(alias_idt);
 
 	/*
-	 * Unmap lower page:
+	 * alias map the original idt to the alias page:
 	 */
-	twopage = VMALLOC_VMADDR(twopage);
-	pgd = pgd_offset(current->mm, twopage);
-	pmd = pmd_offset(pgd, twopage);
-	pte = pte_offset(pmd, twopage);
-
-	pte_clear(pte);
+	page = VMALLOC_VMADDR(page);
+	pgd = pgd_offset(&init_mm, page);
+	pmd = pmd_offset(pgd, page);
+	pte = pte_offset(pmd, page);
+		/* give memory back to the pool, don't need it */
+	free_page(pte_page(*pte));
+		/* ... and set the readonly alias */
+	set_pte(pte, mk_pte(idtpage  & PAGE_MASK, PAGE_KERNEL));
+	*pte = pte_wrprotect(*pte);
 	flush_tlb_all();
+
+		/* now we have the mapping ok, we can do LIDT */
+	 __asm__ __volatile__("\tlidt %0": "=m" (idt_descriptor));
 
 	printk(" ... done\n");
 }
diff -u --recursive --new-file v2.0.32/linux/arch/i386/mm/fault.c linux/arch/i386/mm/fault.c
--- v2.0.32/linux/arch/i386/mm/fault.c	Tue Dec  2 13:52:31 1997
+++ linux/arch/i386/mm/fault.c	Tue Dec  2 13:58:53 1997
@@ -21,128 +21,10 @@
 
 extern void die_if_kernel(const char *,struct pt_regs *,long);
 
-asmlinkage void do_divide_error (struct pt_regs *, unsigned long);
-asmlinkage void do_debug (struct pt_regs *, unsigned long);
-asmlinkage void do_nmi (struct pt_regs *, unsigned long);
-asmlinkage void do_int3 (struct pt_regs *, unsigned long);
-asmlinkage void do_overflow (struct pt_regs *, unsigned long);
-asmlinkage void do_bounds (struct pt_regs *, unsigned long);
 asmlinkage void do_invalid_op (struct pt_regs *, unsigned long);
-asmlinkage void do_general_protection (struct pt_regs *, unsigned long);
 
 extern int pentium_f00f_bug;
 
-static int handle_intx_eip_adjust(struct pt_regs *regs)
-{
-	unsigned char *addr, *csp = 0;
-	int wrap = 0;
-	int count = 8; /* only check for reasonable number of bytes
-			 * else we do it the save 'simple way' */
-	unsigned long _eip;
-#define XX_WRAP(x) (wrap ? *((unsigned short *)&x) : x)
-
-	/* We rely on being able to access the memory pointed to by cs:eip
-	 * and the bytes behind it up to the faulting instruction,
-	 * because we just got an exception for this instruction and
-	 * hence the memory should just be successfully accessed.
-	 * In case of crossing a page boundary or when accessing kernel space
-	 * we just do the simple fix (increase eip by one).
-	 * This assumption also obsoletes checking of segment limit.
-	 * ( should be veryfied, however, if this assumption is true )
-	 */
-
-	if (regs->cs == KERNEL_CS) {
-		/* not what we expect */
-		regs->eip++;
-		return 0;
-	}
-
-	if (regs->eflags & VM_MASK) {
-		/* we have real mode type selector */
-		wrap = 1;
-		csp = (unsigned char *)((unsigned long)regs->cs << 4);
-	}
-	else if (regs->cs & 4) {
-		/* we have a LDT selector */
-		struct desc_struct *p, *ldt = current->ldt;
-		if (!ldt)
-			ldt = (struct desc_struct*) &default_ldt;
-		p = ldt + (regs->cs >> 3);
-		csp = (unsigned char *)((p->a >> 16) | ((p->b & 0xff) << 16) | (p->b & 0xFF000000));
-		if (!(p->b & 0x400000))
-			wrap = 1;	/* 16-bit segment */
-	}
-
-	_eip = regs->eip;
-	addr = csp+XX_WRAP(_eip);
-	while (count-- > 0) {
-		if ((unsigned long)addr >= TASK_SIZE) {
-			/* accessing kernel space, do the simple case */
-			regs->eip++;
-			return 0;
-		}
-		switch (get_user(addr)) {
-
-			case 0xCC:	/* single byte INT3 */
-				XX_WRAP(_eip)++;
-				regs->eip = _eip;
-				return 0;
-
-			case 0xCD:	/* two byte INT 3 */
-				XX_WRAP(_eip)++;
-				/* fall through */
-			case 0xCE:	/* INTO, single byte */
-				XX_WRAP(_eip)++;
-				if ( (regs->eflags & VM_MASK)
-					&& ((regs->eflags & IOPL_MASK) != IOPL_MASK)) {
-					/* not allowed, do GP0 fault */
-					do_general_protection(regs, 0);
-					return -1;
-				}
-				regs->eip = _eip;
-				return 0;
-
-					/* the prefixes from the Intel patch */
-			case 0xF2 ... 0xF3:
-			case 0x2E:
-			case 0x36:
-			case 0x3E:
-			case 0x26:
-			case 0x64 ... 0x67:
-				break;	/* just skipping them */
-
-			default:
-				/* not what we handle here,
-				 * just doing the simple fix
-				 */
-				regs->eip++;
-				return 0;
-		}
-
-		if ( !(++XX_WRAP(_eip)) ) {
-			/* we wrapped around */
-			regs->eip++;
-			return 0;
-		}
-
-		addr = csp+XX_WRAP(_eip);
-		if ( !((unsigned long)addr & ~(PAGE_SIZE -1)) ) {
-			/* we would cross page boundary, not good,
-			 * doing the simple fix
-			 */
-			regs->eip++;
-			return 0;
-		}
-	}
-
-	/* if we come here something weird happened,
-	 * just doing the simple fix
-	 */
-	regs->eip++;
-	return 0;
-}
-
-
 /*
  * This routine handles page faults.  It determines the address,
  * and the problem, and then passes it off to one of the appropriate
@@ -245,22 +127,15 @@
 	 */
 	if ( pentium_f00f_bug ) {
 		unsigned long nr;
+		extern struct {
+			unsigned short limit;
+			unsigned long addr __attribute__((packed));
+		} idt_descriptor;
 
-		nr = (address - TASK_SIZE - (unsigned long) idt) >> 3;
+		nr = (address - idt_descriptor.addr) >> 3;
 
-		if (nr < 7) {
-			static void (*handler[])(struct pt_regs *, unsigned long) = {
-				do_divide_error,	/* 0 - divide overflow */
-				do_debug,		/* 1 - debug trap */
-				do_nmi,			/* 2 - NMI */
-				do_int3,		/* 3 - int 3 */
-				do_overflow,		/* 4 - overflow */
-				do_bounds,		/* 5 - bound range */
-				do_invalid_op };	/* 6 - invalid opcode */
-			if ((nr == 3) || (nr == 4))
-				if (handle_intx_eip_adjust(regs))
-					return;
-			handler[nr](regs, error_code);
+		if (nr == 6) {
+			do_invalid_op(regs, 0);
 			return;
 		}
 	}
diff -u --recursive --new-file v2.0.32/linux/include/asm-i386/pgtable.h linux/include/asm-i386/pgtable.h
--- v2.0.32/linux/include/asm-i386/pgtable.h	Wed Oct 15 15:22:05 1997
+++ linux/include/asm-i386/pgtable.h	Tue Dec  2 14:18:13 1997
@@ -42,11 +42,28 @@
 #define __flush_tlb() \
 do { unsigned long tmpreg; __asm__ __volatile__("movl %%cr3,%0\n\tmovl %0,%%cr3":"=r" (tmpreg) : :"memory"); } while (0)
 
+/*
+ * NOTE! The intel "invlpg" semantics are extremely strange. The
+ * chip will add the segment base to the memory address, even though
+ * no segment checking is done. We correct for this by using an
+ * offset of 0x40000000 that will wrap around the kernel segment base
+ * of 0xC0000000 to get the correct address (it will always be outside
+ * the kernel segment, but we're only interested in the final linear
+ * address.
+ */
+#define __invlpg_mem(addr) \
+	(((char *)(addr))[0x40000000])
+#define __invlpg(addr) \
+	__asm__ __volatile__("invlpg %0": :"m" (__invlpg_mem(addr)))
+
+/*
+ * The i386 doesn't have a page-granular invalidate. Invalidate
+ * everything for it.
+ */
 #ifdef CONFIG_M386
-#define __flush_tlb_one(addr) flush_tlb()
+  #define __flush_tlb_one(addr) __flush_tlb()
 #else
-#define __flush_tlb_one(addr) \
-__asm__ __volatile__("invlpg %0": :"m" (*(char *) addr))
+  #define __flush_tlb_one(addr) __invlpg(addr)
 #endif
  
 #ifndef __SMP__
diff -u --recursive --new-file v2.0.32/linux/include/linux/ax25.h linux/include/linux/ax25.h
--- v2.0.32/linux/include/linux/ax25.h	Sat Aug 10 00:03:15 1996
+++ linux/include/linux/ax25.h	Thu Dec  4 13:13:23 1997
@@ -6,7 +6,6 @@
 #ifndef	AX25_KERNEL_H
 #define	AX25_KERNEL_H
  
-#define PF_AX25		AF_AX25
 #define AX25_MTU	256
 #define AX25_MAX_DIGIS	6	/* This is wrong, should be 8 */
 
diff -u --recursive --new-file v2.0.32/linux/include/linux/head.h linux/include/linux/head.h
--- v2.0.32/linux/include/linux/head.h	Tue Dec  2 13:52:33 1997
+++ linux/include/linux/head.h	Tue Dec  2 13:58:53 1997
@@ -5,8 +5,7 @@
 	unsigned long a,b;
 } desc_table[256];
 
-extern desc_table __idt,gdt;
-extern struct desc_struct *idt;
+extern desc_table idt,gdt;
 
 #define GDT_NUL 0
 #define GDT_CODE 1
diff -u --recursive --new-file v2.0.32/linux/include/linux/netrom.h linux/include/linux/netrom.h
--- v2.0.32/linux/include/linux/netrom.h	Sat Aug 10 00:03:15 1996
+++ linux/include/linux/netrom.h	Thu Dec  4 13:13:23 1997
@@ -7,7 +7,6 @@
 #ifndef	NETROM_KERNEL_H
 #define	NETROM_KERNEL_H
 
-#define PF_NETROM	AF_NETROM
 #define NETROM_MTU	236
 
 #define NETROM_T1	1
diff -u --recursive --new-file v2.0.32/linux/include/net/route.h linux/include/net/route.h
--- v2.0.32/linux/include/net/route.h	Wed Oct 15 15:23:10 1997
+++ linux/include/net/route.h	Wed Dec 10 09:14:00 1997
@@ -14,6 +14,11 @@
  *		Alan Cox	:	Support for TCP parameters.
  *		Alexey Kuznetsov:	Major changes for new routing code.
  *              Elliot Poger    :       Added support for SO_BINDTODEVICE.
+ *		Wolfgang Walter,
+ *		Daniel Ryde,
+ *		Ingo Molinar	:	fixed bug in ip_rt_put introduced
+ *					by SO_BINDTODEVICE support causing
+ *					a memory leak
  *
  *	FIXME:
  *		Make atomic ops more generic and hide them in asm/...
@@ -98,6 +103,7 @@
 extern atomic_t	    	ip_rt_lock;
 extern unsigned		ip_rt_bh_mask;
 extern struct rtable 	*ip_rt_hash_table[RT_HASH_DIVISOR];
+extern void	 	rt_free(struct rtable * rt);
 
 extern __inline__ void ip_rt_fast_lock(void)
 {
@@ -127,6 +133,11 @@
 {
 	if (rt)
 		atomic_dec(&rt->rt_refcnt);
+
+	/* If this rtable entry is not in the cache, we'd better free it once the
+	 * refcnt goes to zero, because nobody else will... */
+	if ( rt && (rt->rt_flags & RTF_NOTCACHED) && (!rt->rt_refcnt) )
+		rt_free(rt);
 }
 #else
 ;
diff -u --recursive --new-file v2.0.32/linux/net/ipv4/ip_forward.c linux/net/ipv4/ip_forward.c
--- v2.0.32/linux/net/ipv4/ip_forward.c	Tue Aug 12 11:30:25 1997
+++ linux/net/ipv4/ip_forward.c	Wed Dec 10 09:14:00 1997
@@ -16,6 +16,7 @@
  *					use output device for accounting.
  *		Jos Vos		:	Call forward firewall after routing
  *					(always use output device).
+ *		Philip Gladstone:	Add some missing ip_rt_put()
  */
 
 #include <linux/config.h>
@@ -113,7 +114,7 @@
 	struct device *dev2;	/* Output device */
 	struct iphdr *iph;	/* Our header */
 	struct sk_buff *skb2;	/* Output packet */
-	struct rtable *rt;	/* Route we use */
+	struct rtable *rt = NULL;	/* Route we use */
 	unsigned char *ptr;	/* Data pointer */
 	unsigned long raddr;	/* Router IP address */
 	struct   options * opt	= (struct options*)skb->proto_priv;
@@ -301,6 +302,8 @@
 			icmp_send(skb, ICMP_DEST_UNREACH, ICMP_HOST_UNREACH, 0, dev);
 			/* fall thru */
 		default:
+			if (rt)
+				ip_rt_put(rt);
 			return -1;
 		}
 
@@ -454,6 +457,8 @@
 				icmp_send(skb2, ICMP_DEST_UNREACH, ICMP_HOST_UNREACH, 0, dev);
 			if (skb != skb2)
 				kfree_skb(skb2,FREE_WRITE);
+			if (rt)
+				ip_rt_put(rt);
 			return -1;
 		}
 #endif
diff -u --recursive --new-file v2.0.32/linux/net/ipv4/route.c linux/net/ipv4/route.c
--- v2.0.32/linux/net/ipv4/route.c	Wed Sep 17 12:00:48 1997
+++ linux/net/ipv4/route.c	Wed Dec 10 09:14:01 1997
@@ -45,6 +45,7 @@
  *              Elliot Poger    :       Added support for SO_BINDTODEVICE.
  *		Andi Kleen	:	Don't send multicast addresses to
  *					kerneld.	
+ *		Wolfgang Walter	:	make rt_free() non-static
  *
  *	Juan Jose Ciarlante     :	Added ip_rt_dev 
  *		This program is free software; you can redistribute it and/or
@@ -891,7 +892,7 @@
 }
 
 
-static void rt_free(struct rtable * rt)
+void rt_free(struct rtable * rt)
 {
 	unsigned long flags;
 
diff -u --recursive --new-file v2.0.32/linux/net/ipv4/udp.c linux/net/ipv4/udp.c
--- v2.0.32/linux/net/ipv4/udp.c	Mon Sep 15 09:54:52 1997
+++ linux/net/ipv4/udp.c	Wed Dec 10 09:14:01 1997
@@ -55,6 +55,7 @@
  *              Elliot Poger    :       Added support for SO_BINDTODEVICE.
  *	Willy Konynenberg	:	Transparent proxy adapted to new
  *					socket hash code.
+ *		Philip Gladstone:	Added missing ip_rt_put
  *
  *
  *		This program is free software; you can redistribute it and/or
@@ -874,6 +875,8 @@
 	sk->daddr = usin->sin_addr.s_addr;
 	sk->dummy_th.dest = usin->sin_port;
 	sk->state = TCP_ESTABLISHED;
+	if (sk->ip_route_cache)
+	        ip_rt_put(sk->ip_route_cache);
 	sk->ip_route_cache = rt;
 	return(0);
 }
diff -u --recursive --new-file v2.0.32/linux/net/unix/garbage.c linux/net/unix/garbage.c
--- v2.0.32/linux/net/unix/garbage.c	Mon May 13 05:31:18 1996
+++ linux/net/unix/garbage.c	Thu Dec  4 10:16:31 1997
@@ -5,6 +5,16 @@
  *	Copyright (C) Barak A. Pearlmutter.
  *	Released under the GPL version 2 or later.
  *
+ * 12/3/97 -- Flood
+ * Internal stack is only allocated one page.  On systems with NR_FILE
+ * > 1024, this makes it quite easy for a user-space program to open
+ * a large number of AF_UNIX domain sockets, causing the garbage
+ * collection routines to run up against the wall (and panic).
+ * Changed the MAX_STACK to be associated to the system-wide open file
+ * maximum, and use vmalloc() instead of get_free_page() [as more than
+ * one page may be necessary].  As noted below, this should ideally be
+ * done with a linked list.  
+ *
  * Chopped about by Alan Cox 22/3/96 to make it fit the AF_UNIX socket problem.
  * If it doesn't work blame me, it worked when Barak sent it.
  *
@@ -59,10 +69,9 @@
 
 /* Internal data structures and random procedures: */
 
-#define MAX_STACK 1000		/* Maximum depth of tree (about 1 page) */
 static unix_socket **stack;	/* stack of objects to mark */
 static int in_stack = 0;	/* first free entry in stack */
-
+static int max_stack;		/* Calculated in unix_gc() */
 
 extern inline unix_socket *unix_get_socket(struct file *filp)
 {
@@ -110,7 +119,7 @@
  
 extern inline void push_stack(unix_socket *x)
 {
-	if (in_stack == MAX_STACK)
+	if (in_stack == max_stack)
 		panic("can't push onto full stack");
 	stack[in_stack++] = x;
 }
@@ -151,8 +160,14 @@
 	if(in_unix_gc)
 		return;
 	in_unix_gc=1;
-	
-	stack=(unix_socket **)get_free_page(GFP_KERNEL);
+
+	max_stack = max_files;
+
+	stack=(unix_socket **)vmalloc(max_stack * sizeof(unix_socket **));
+	if (!stack) {
+		in_unix_gc=0;
+		return;
+	}
 	
 	/*
 	 *	Assume everything is now unmarked 
@@ -276,5 +291,5 @@
 	
 	in_unix_gc=0;
 	
-	free_page((long)stack);
+	vfree(stack);
 }
