add kernel 2.4 hot fixes
authorNicolas Thill <nico@openwrt.org>
Tue, 28 Mar 2006 00:43:49 +0000 (00:43 +0000)
committerNicolas Thill <nico@openwrt.org>
Tue, 28 Mar 2006 00:43:49 +0000 (00:43 +0000)
SVN-Revision: 3516

openwrt/target/linux/linux-2.4/patches/generic/214-net-ipv4-netfilter-ip_recent-last_pkts.patch [new file with mode: 0644]
openwrt/target/linux/linux-2.4/patches/generic/215_net-bridge-if_del-panic.patch [new file with mode: 0644]
openwrt/target/linux/linux-2.4/patches/generic/901-hot_fixes-32.3.patch [new file with mode: 0644]

diff --git a/openwrt/target/linux/linux-2.4/patches/generic/214-net-ipv4-netfilter-ip_recent-last_pkts.patch b/openwrt/target/linux/linux-2.4/patches/generic/214-net-ipv4-netfilter-ip_recent-last_pkts.patch
new file mode 100644 (file)
index 0000000..65372b6
--- /dev/null
@@ -0,0 +1,58 @@
+From: David S. Miller <davem@davemloft.net>
+Date: Thu, 16 Jun 2005 03:51:14 +0000 (-0700)
+Subject: [NETFILTER]: ipt_recent: last_pkts is an array of "unsigned long" not "u_int32_t"
+X-Git-Tag: v2.6.12
+X-Git-Url: http://www.kernel.org/git/?p=linux/kernel/git/chrisw/lsm-2.6.git;a=commitdiff;h=bcfff0b471a60df350338bcd727fc9b8a6aa54b2
+
+  [NETFILTER]: ipt_recent: last_pkts is an array of "unsigned long" not "u_int32_t"
+  
+  This fixes various crashes on 64-bit when using this module.
+  
+  Based upon a patch by Juergen Kreileder <jk@blackdown.de>.
+  
+  Signed-off-by: David S. Miller <davem@davemloft.net>
+  ACKed-by: Patrick McHardy <kaber@trash.net>
+---
+
+--- a/net/ipv4/netfilter/ipt_recent.c
++++ b/net/ipv4/netfilter/ipt_recent.c
+@@ -223,7 +223,7 @@ static int ip_recent_ctrl(struct file *f
+                       curr_table->table[count].last_seen = 0;
+                       curr_table->table[count].addr = 0;
+                       curr_table->table[count].ttl = 0;
+-                      memset(curr_table->table[count].last_pkts,0,ip_pkt_list_tot*sizeof(u_int32_t));
++                      memset(curr_table->table[count].last_pkts,0,ip_pkt_list_tot*sizeof(unsigned long));
+                       curr_table->table[count].oldest_pkt = 0;
+                       curr_table->table[count].time_pos = 0;
+                       curr_table->time_info[count].position = count;
+@@ -502,7 +502,7 @@ match(const struct sk_buff *skb,
+               location = time_info[curr_table->time_pos].position;
+               hash_table[r_list[location].hash_entry] = -1;
+               hash_table[hash_result] = location;
+-              memset(r_list[location].last_pkts,0,ip_pkt_list_tot*sizeof(u_int32_t));
++              memset(r_list[location].last_pkts,0,ip_pkt_list_tot*sizeof(unsigned long));
+               r_list[location].time_pos = curr_table->time_pos;
+               r_list[location].addr = addr;
+               r_list[location].ttl = ttl;
+@@ -631,7 +631,7 @@ match(const struct sk_buff *skb,
+                       r_list[location].last_seen = 0;
+                       r_list[location].addr = 0;
+                       r_list[location].ttl = 0;
+-                      memset(r_list[location].last_pkts,0,ip_pkt_list_tot*sizeof(u_int32_t));
++                      memset(r_list[location].last_pkts,0,ip_pkt_list_tot*sizeof(unsigned long));
+                       r_list[location].oldest_pkt = 0;
+                       ans = !info->invert;
+               }
+@@ -734,10 +734,10 @@ checkentry(const char *tablename,
+       memset(curr_table->table,0,sizeof(struct recent_ip_list)*ip_list_tot);
+ #ifdef DEBUG
+       if(debug) printk(KERN_INFO RECENT_NAME ": checkentry: Allocating %d for pkt_list.\n",
+-                      sizeof(u_int32_t)*ip_pkt_list_tot*ip_list_tot);
++                      sizeof(unsigned long)*ip_pkt_list_tot*ip_list_tot);
+ #endif
+-      hold = vmalloc(sizeof(u_int32_t)*ip_pkt_list_tot*ip_list_tot);
++      hold = vmalloc(sizeof(unsigned long)*ip_pkt_list_tot*ip_list_tot);
+ #ifdef DEBUG
+       if(debug) printk(KERN_INFO RECENT_NAME ": checkentry: After pkt_list allocation.\n");
+ #endif
diff --git a/openwrt/target/linux/linux-2.4/patches/generic/215_net-bridge-if_del-panic.patch b/openwrt/target/linux/linux-2.4/patches/generic/215_net-bridge-if_del-panic.patch
new file mode 100644 (file)
index 0000000..03e6a93
--- /dev/null
@@ -0,0 +1,43 @@
+# Date: Sun, 20 Jun 2004 19:56:26 +0200
+# From: Erich Schubert <erich@debian.org>
+# Changes: Rebackported from 2.6.14, Horms <horms@debian.org>
+# Reported: http://bugs.debian.org/255406
+# Security: No
+# Upstream: Forwarded to upstream
+
+Package: kernel-source-2.4.26
+Severity: normal
+
+Some time ago i found a kernel crash in 2.4.x and reported it to LKML.
+Unfortunately i never recieved a reply, and i didn't see it in recent
+pre-releases of the 2.4.x kernel.
+
+To verify your system is vulnerable (need bridge support):
+$ brctl addbr br0
+$ brctl addbr br1
+$ brctl addif br0 eth0
+$ brctl delif br1 eth0
+(note br1 in last line, not br0! Deleting from the wrong bridge triggers
+the kernel crash.)
+
+This is a 1:1 backport (100% copy&paste) from 2.6.5 of the fix.
+Verify yourself, grab the file from 2.6.5, go to the function, copy the
+code, paste it and the issue is done. Returns "einval" on invalid
+requests instead of causing an inconsistency and a panic.
+
+(fixed sometime in 2.5.x it seems; it might be worth looking at when
+this was fixed - it might contain other fixes, too.)
+
+--- a/net/bridge/br_if.c       2005-11-16 14:46:05.000000000 +0900
++++ b/net/bridge/br_if.c       2005-11-16 14:46:09.000000000 +0900
+@@ -246,6 +246,10 @@
+ int br_del_if(struct net_bridge *br, struct net_device *dev)
+ {
+       int retval;
++      struct net_bridge_port *p = dev->br_port;
++
++      if (!p || p->br != br)
++              return -EINVAL;
+       br_write_lock_bh(BR_NETPROTO_LOCK);
+       write_lock(&br->lock);
diff --git a/openwrt/target/linux/linux-2.4/patches/generic/901-hot_fixes-32.3.patch b/openwrt/target/linux/linux-2.4/patches/generic/901-hot_fixes-32.3.patch
new file mode 100644 (file)
index 0000000..eef6e4c
--- /dev/null
@@ -0,0 +1,3937 @@
+Hot Fix 32.3 for Linux Kernel 2.4.30 - 2006/03/18
+From Willy Tarreau - EXOSEC  < wtarreau at exosec.net >
+
+http://linux.exosec.net/kernel/2.4-hf/
+
+- CVE-2004-1058
+- CVE-2004-2607
+- CVE-2005-0204
+- CVE-2005-1263
+- CVE-2005-2457
+- CVE-2005-2490
+- CVE-2005-2708
+- CVE-2005-2709
+- CVE-2005-2973
+- CVE-2005-3180
+- CVE-2005-3257
+- CVE-2005-3783
+- CVE-2005-3806
+- CVE-2005-3857
+
+
+diff -urN linux-2.4.30/arch/alpha/kernel/Makefile linux-2.4.30-hf32.3/arch/alpha/kernel/Makefile
+--- linux-2.4.30/arch/alpha/kernel/Makefile    2003-11-28 19:26:19.000000000 +0100
++++ linux-2.4.30-hf32.3/arch/alpha/kernel/Makefile     2006-03-18 00:34:06.000000000 +0100
+@@ -76,7 +76,7 @@
+ obj-y    += sys_alcor.o
+ endif
+ ifneq ($(CONFIG_ALPHA_CABRIOLET)$(CONFIG_ALPHA_EB164)$(CONFIG_ALPHA_EB66P)$(CONFIG_ALPHA_LX164)$(CONFIG_ALPHA_PC164),)
+-obj-y    += sys_cabriolet.o
++obj-y    += sys_cabriolet.o ns87312.o
+ endif
+ obj-$(CONFIG_ALPHA_DP264) += sys_dp264.o
+diff -urN linux-2.4.30/arch/alpha/kernel/pci_iommu.c linux-2.4.30-hf32.3/arch/alpha/kernel/pci_iommu.c
+--- linux-2.4.30/arch/alpha/kernel/pci_iommu.c 2003-06-13 16:51:29.000000000 +0200
++++ linux-2.4.30-hf32.3/arch/alpha/kernel/pci_iommu.c  2006-03-18 00:34:06.000000000 +0100
+@@ -503,7 +503,7 @@
+ /* Given a scatterlist leader, choose an allocation method and fill
+    in the blanks.  */
+-static inline int
++static int
+ sg_fill(struct scatterlist *leader, struct scatterlist *end,
+       struct scatterlist *out, struct pci_iommu_arena *arena,
+       dma_addr_t max_dma, int dac_allowed)
+diff -urN linux-2.4.30/arch/i386/config.in linux-2.4.30-hf32.3/arch/i386/config.in
+--- linux-2.4.30/arch/i386/config.in   2004-11-17 12:54:21.000000000 +0100
++++ linux-2.4.30-hf32.3/arch/i386/config.in    2006-03-18 00:34:06.000000000 +0100
+@@ -65,6 +65,7 @@
+    define_bool CONFIG_X86_POPAD_OK y
+    define_bool CONFIG_RWSEM_GENERIC_SPINLOCK n
+    define_bool CONFIG_RWSEM_XCHGADD_ALGORITHM y
++   define_bool CONFIG_X86_TSC n
+ fi
+ if [ "$CONFIG_M486" = "y" ]; then
+    define_int  CONFIG_X86_L1_CACHE_SHIFT 4
+@@ -72,6 +73,7 @@
+    define_bool CONFIG_X86_ALIGNMENT_16 y
+    define_bool CONFIG_X86_PPRO_FENCE y
+    define_bool CONFIG_X86_F00F_WORKS_OK n
++   define_bool CONFIG_X86_TSC n
+ fi
+ if [ "$CONFIG_M586" = "y" ]; then
+    define_int  CONFIG_X86_L1_CACHE_SHIFT 5
+diff -urN linux-2.4.30/arch/i386/kernel/apm.c linux-2.4.30-hf32.3/arch/i386/kernel/apm.c
+--- linux-2.4.30/arch/i386/kernel/apm.c        2003-08-25 13:44:39.000000000 +0200
++++ linux-2.4.30-hf32.3/arch/i386/kernel/apm.c 2006-03-18 00:34:06.000000000 +0100
+@@ -327,7 +327,7 @@
+  * Save a segment register away
+  */
+ #define savesegment(seg, where) \
+-              __asm__ __volatile__("movl %%" #seg ",%0" : "=m" (where))
++              __asm__ __volatile__("mov %%" #seg ",%0" : "=m" (where))
+ /*
+  * Maximum number of events stored
+@@ -553,7 +553,7 @@
+ #ifdef APM_ZERO_SEGS
+ #     define APM_DECL_SEGS \
+-              unsigned int saved_fs; unsigned int saved_gs;
++              unsigned short saved_fs; unsigned short saved_gs;
+ #     define APM_DO_SAVE_SEGS \
+               savesegment(fs, saved_fs); savesegment(gs, saved_gs)
+ #     define APM_DO_ZERO_SEGS \
+diff -urN linux-2.4.30/arch/i386/kernel/io_apic.c linux-2.4.30-hf32.3/arch/i386/kernel/io_apic.c
+--- linux-2.4.30/arch/i386/kernel/io_apic.c    2004-11-17 12:54:21.000000000 +0100
++++ linux-2.4.30-hf32.3/arch/i386/kernel/io_apic.c     2006-03-18 00:34:06.000000000 +0100
+@@ -1194,7 +1194,7 @@
+        * might have cached one ExtINT interrupt.  Finally, at
+        * least one tick may be lost due to delays.
+        */
+-      if (jiffies - t1 > 4)
++      if (jiffies - t1 > 4 && jiffies - t1 < 16)
+               return 1;
+       return 0;
+diff -urN linux-2.4.30/arch/i386/kernel/mtrr.c linux-2.4.30-hf32.3/arch/i386/kernel/mtrr.c
+--- linux-2.4.30/arch/i386/kernel/mtrr.c       2004-08-08 01:26:04.000000000 +0200
++++ linux-2.4.30-hf32.3/arch/i386/kernel/mtrr.c        2006-03-18 00:34:06.000000000 +0100
+@@ -1674,6 +1674,7 @@
+     char *ptr;
+     char line[LINE_SIZE];
++    if (!len) return -EINVAL;
+     if ( !suser () ) return -EPERM;
+     /*  Can't seek (pwrite) on this device  */
+     if (ppos != &file->f_pos) return -ESPIPE;
+diff -urN linux-2.4.30/arch/i386/kernel/process.c linux-2.4.30-hf32.3/arch/i386/kernel/process.c
+--- linux-2.4.30/arch/i386/kernel/process.c    2004-11-17 12:54:21.000000000 +0100
++++ linux-2.4.30-hf32.3/arch/i386/kernel/process.c     2006-03-18 00:34:06.000000000 +0100
+@@ -544,7 +544,7 @@
+  * Save a segment.
+  */
+ #define savesegment(seg,value) \
+-      asm volatile("movl %%" #seg ",%0":"=m" (*(int *)&(value)))
++      asm volatile("mov %%" #seg ",%0":"=m" (value))
+ int copy_thread(int nr, unsigned long clone_flags, unsigned long esp,
+       unsigned long unused,
+@@ -661,8 +661,8 @@
+        * Save away %fs and %gs. No need to save %es and %ds, as
+        * those are always kernel segments while inside the kernel.
+        */
+-      asm volatile("movl %%fs,%0":"=m" (*(int *)&prev->fs));
+-      asm volatile("movl %%gs,%0":"=m" (*(int *)&prev->gs));
++      asm volatile("mov %%fs,%0":"=m" (prev->fs));
++      asm volatile("mov %%gs,%0":"=m" (prev->gs));
+       /*
+        * Restore %fs and %gs.
+diff -urN linux-2.4.30/arch/i386/kernel/traps.c linux-2.4.30-hf32.3/arch/i386/kernel/traps.c
+--- linux-2.4.30/arch/i386/kernel/traps.c      2002-11-29 00:53:09.000000000 +0100
++++ linux-2.4.30-hf32.3/arch/i386/kernel/traps.c       2006-03-18 00:34:06.000000000 +0100
+@@ -631,15 +631,14 @@
+        */
+       cwd = get_fpu_cwd(task);
+       swd = get_fpu_swd(task);
+-      switch (((~cwd) & swd & 0x3f) | (swd & 0x240)) {
++      switch (swd & ~cwd & 0x3f) {
+               case 0x000:
+               default:
+                       break;
+               case 0x001: /* Invalid Op */
+-              case 0x041: /* Stack Fault */
+-              case 0x241: /* Stack Fault | Direction */
++                      /* swd & 0x240 == 0x040: Stack Fault */
++                      /* swd & 0x240 == 0x240: Stack Fault | Direction */
+                       info.si_code = FPE_FLTINV;
+-                      /* Should we clear the SF or let user space do it ???? */
+                       break;
+               case 0x002: /* Denormalize */
+               case 0x010: /* Underflow */
+diff -urN linux-2.4.30/arch/ia64/ia32/sys_ia32.c linux-2.4.30-hf32.3/arch/ia64/ia32/sys_ia32.c
+--- linux-2.4.30/arch/ia64/ia32/sys_ia32.c     2005-04-14 09:43:32.000000000 +0200
++++ linux-2.4.30-hf32.3/arch/ia64/ia32/sys_ia32.c      2006-03-18 00:34:06.000000000 +0100
+@@ -94,7 +94,7 @@
+ static DECLARE_MUTEX(ia32_mmap_sem);
+ static int
+-nargs (unsigned int arg, char **ap)
++nargs (unsigned int arg, char **ap, int max)
+ {
+       unsigned int addr;
+       int n, err;
+@@ -107,6 +107,8 @@
+               err = get_user(addr, (unsigned int *)A(arg));
+               if (err)
+                       return err;
++              if (n > max)
++                      return -E2BIG;
+               if (ap)
+                       *ap++ = (char *) A(addr);
+               arg += sizeof(unsigned int);
+@@ -128,10 +130,11 @@
+       int na, ne, len;
+       long r;
+-      na = nargs(argv, NULL);
++      /* Allocates upto 2x MAX_ARG_PAGES */
++      na = nargs(argv, NULL, (MAX_ARG_PAGES*PAGE_SIZE) / sizeof(char *) - 1);
+       if (na < 0)
+               return na;
+-      ne = nargs(envp, NULL);
++      ne = nargs(envp, NULL, (MAX_ARG_PAGES*PAGE_SIZE) / sizeof(char *) - 1 );
+       if (ne < 0)
+               return ne;
+       len = (na + ne + 2) * sizeof(*av);
+@@ -143,10 +146,10 @@
+       av[na] = NULL;
+       ae[ne] = NULL;
+-      r = nargs(argv, av);
++      r = nargs(argv, av, na);
+       if (r < 0)
+               goto out;
+-      r = nargs(envp, ae);
++      r = nargs(envp, ae, ne);
+       if (r < 0)
+               goto out;
+@@ -1439,6 +1442,7 @@
+               tmp = ((ucmlen - CMSG32_ALIGN(sizeof(*ucmsg))) +
+                      CMSG_ALIGN(sizeof(struct cmsghdr)));
++              tmp = CMSG_ALIGN(tmp);
+               kcmlen += tmp;
+               ucmsg = CMSG32_NXTHDR(kmsg, ucmsg, ucmlen);
+       }
+@@ -1475,7 +1479,7 @@
+                       goto out_free_efault;
+               /* Advance. */
+-              kcmsg = (struct cmsghdr *)((char *)kcmsg + CMSG_ALIGN(tmp));
++              kcmsg = (struct cmsghdr *)((char *)kcmsg + tmp);
+               ucmsg = CMSG32_NXTHDR(kmsg, ucmsg, ucmlen);
+       }
+diff -urN linux-2.4.30/arch/ia64/mm/fault.c linux-2.4.30-hf32.3/arch/ia64/mm/fault.c
+--- linux-2.4.30/arch/ia64/mm/fault.c  2003-08-25 13:44:39.000000000 +0200
++++ linux-2.4.30-hf32.3/arch/ia64/mm/fault.c   2006-03-18 00:34:06.000000000 +0100
+@@ -206,9 +206,6 @@
+               return;
+       }
+-      if (done_with_exception(regs))
+-              return;
+-
+       /*
+        * Since we have no vma's for region 5, we might get here even if the address is
+        * valid, due to the VHPT walker inserting a non present translation that becomes
+@@ -219,6 +216,9 @@
+       if (REGION_NUMBER(address) == 5 && mapped_kernel_page_is_present(address))
+               return;
++      if (done_with_exception(regs))
++              return;
++
+       /*
+        * Oops. The kernel tried to access some bad page. We'll have to terminate things
+        * with extreme prejudice.
+diff -urN linux-2.4.30/arch/parisc/kernel/ioctl32.c linux-2.4.30-hf32.3/arch/parisc/kernel/ioctl32.c
+--- linux-2.4.30/arch/parisc/kernel/ioctl32.c  2005-01-27 18:57:31.000000000 +0100
++++ linux-2.4.30-hf32.3/arch/parisc/kernel/ioctl32.c   2006-03-18 00:34:06.000000000 +0100
+@@ -35,6 +35,7 @@
+ #include <linux/cdrom.h>
+ #include <linux/loop.h>
+ #include <linux/auto_fs.h>
++#include <linux/auto_fs4.h>
+ #include <linux/devfs_fs.h>
+ #include <linux/tty.h>
+ #include <linux/vt_kern.h>
+diff -urN linux-2.4.30/arch/parisc/kernel/sys_parisc32.c linux-2.4.30-hf32.3/arch/parisc/kernel/sys_parisc32.c
+--- linux-2.4.30/arch/parisc/kernel/sys_parisc32.c     2005-04-14 09:43:33.000000000 +0200
++++ linux-2.4.30-hf32.3/arch/parisc/kernel/sys_parisc32.c      2006-03-18 00:34:06.000000000 +0100
+@@ -1934,12 +1934,13 @@
+       struct cmsghdr *kcmsg, *kcmsg_base;
+       __kernel_size_t32 ucmlen;
+       __kernel_size_t kcmlen, tmp;
++      int err = -EFAULT;
+       kcmlen = 0;
+       kcmsg_base = kcmsg = (struct cmsghdr *)stackbuf;
+       ucmsg = CMSG32_FIRSTHDR(kmsg);
+       while(ucmsg != NULL) {
+-              if(get_user(ucmlen, &ucmsg->cmsg_len))
++              if (get_user(ucmlen, &ucmsg->cmsg_len))
+                       return -EFAULT;
+               /* Catch bogons. */
+@@ -1948,6 +1949,7 @@
+               tmp = ((ucmlen - CMSG32_ALIGN(sizeof(*ucmsg))) +
+                      CMSG_ALIGN(sizeof(struct cmsghdr)));
++              tmp = CMSG_ALIGN(tmp);
+               kcmlen += tmp;
+               ucmsg = CMSG32_NXTHDR(kmsg, ucmsg, ucmlen);
+       }
+@@ -1968,21 +1970,23 @@
+       memset(kcmsg, 0, kcmlen);
+       ucmsg = CMSG32_FIRSTHDR(kmsg);
+       while(ucmsg != NULL) {
+-              __get_user(ucmlen, &ucmsg->cmsg_len);
++              if (__get_user(ucmlen, &ucmsg->cmsg_len))
++                      goto Efault;
+               tmp = ((ucmlen - CMSG32_ALIGN(sizeof(*ucmsg))) +
+                      CMSG_ALIGN(sizeof(struct cmsghdr)));
++              if ((char *)kcmsg_base + kcmlen - (char *)kcmsg < CMSG_ALIGN(tmp))
++                      goto Einval;
+               kcmsg->cmsg_len = tmp;
+-              __get_user(kcmsg->cmsg_level, &ucmsg->cmsg_level);
+-              __get_user(kcmsg->cmsg_type, &ucmsg->cmsg_type);
+-
+-              /* Copy over the data. */
+-              if(copy_from_user(CMSG_DATA(kcmsg),
+-                                CMSG32_DATA(ucmsg),
+-                                (ucmlen - CMSG32_ALIGN(sizeof(*ucmsg)))))
+-                      goto out_free_efault;
++              tmp = CMSG_ALIGN(tmp);
++              if (__get_user(kcmsg->cmsg_level, &ucmsg->cmsg_level) ||
++                  __get_user(kcmsg->cmsg_type, &ucmsg->cmsg_type) ||
++                  copy_from_user(CMSG_DATA(kcmsg),
++                                 CMSG32_DATA(ucmsg),
++                                 (ucmlen - CMSG32_ALIGN(sizeof(*ucmsg)))))
++                      goto Efault;
+               /* Advance. */
+-              kcmsg = (struct cmsghdr *)((char *)kcmsg + CMSG_ALIGN(tmp));
++              kcmsg = (struct cmsghdr *)((char *)kcmsg + tmp);
+               ucmsg = CMSG32_NXTHDR(kmsg, ucmsg, ucmlen);
+       }
+@@ -1991,10 +1995,12 @@
+       kmsg->msg_controllen = kcmlen;
+       return 0;
+-out_free_efault:
+-      if(kcmsg_base != (struct cmsghdr *)stackbuf)
++Einval:
++      err = -EINVAL;
++Efault:
++      if (kcmsg_base != (struct cmsghdr *)stackbuf)
+               kfree(kcmsg_base);
+-      return -EFAULT;
++      return err;
+ }
+ static void put_cmsg32(struct msghdr *kmsg, int level, int type,
+diff -urN linux-2.4.30/arch/ppc/boot/lib/zlib.c linux-2.4.30-hf32.3/arch/ppc/boot/lib/zlib.c
+--- linux-2.4.30/arch/ppc/boot/lib/zlib.c      2003-08-25 13:44:40.000000000 +0200
++++ linux-2.4.30-hf32.3/arch/ppc/boot/lib/zlib.c       2006-03-18 00:34:06.000000000 +0100
+@@ -1322,6 +1322,7 @@
+     if ((j = *p++) != 0)
+       v[x[j]++] = i;
+   } while (++i < n);
++  n = x[g];                   /* set n to length of v */
+   /* Generate the Huffman codes and for each, make the table entries */
+diff -urN linux-2.4.30/arch/ppc64/boot/zlib.c linux-2.4.30-hf32.3/arch/ppc64/boot/zlib.c
+--- linux-2.4.30/arch/ppc64/boot/zlib.c        2003-08-25 13:44:40.000000000 +0200
++++ linux-2.4.30-hf32.3/arch/ppc64/boot/zlib.c 2006-03-18 00:34:06.000000000 +0100
+@@ -1338,6 +1338,7 @@
+     if ((j = *p++) != 0)
+       v[x[j]++] = i;
+   } while (++i < n);
++  n = x[g];                   /* set n to length of v */
+   /* Generate the Huffman codes and for each, make the table entries */
+diff -urN linux-2.4.30/arch/ppc64/kernel/ioctl32.c linux-2.4.30-hf32.3/arch/ppc64/kernel/ioctl32.c
+--- linux-2.4.30/arch/ppc64/kernel/ioctl32.c   2005-01-27 18:57:31.000000000 +0100
++++ linux-2.4.30-hf32.3/arch/ppc64/kernel/ioctl32.c    2006-03-18 00:34:06.000000000 +0100
+@@ -49,6 +49,7 @@
+ #include <linux/cdrom.h>
+ #include <linux/loop.h>
+ #include <linux/auto_fs.h>
++#include <linux/autofs_4.h>
+ #include <linux/devfs_fs.h>
+ #include <linux/tty.h>
+ #include <linux/vt_kern.h>
+@@ -876,13 +877,15 @@
+               r = (void *) &r4;
+       }
+-      if (ret)
+-              return -EFAULT;
++      if (ret) {
++              ret = -EFAULT;
++              goto out;
++      }
+       set_fs (KERNEL_DS);
+       ret = sys_ioctl (fd, cmd, (long) r);
+       set_fs (old_fs);
+-
++out:
+       if (mysock)
+               sockfd_put(mysock);
+diff -urN linux-2.4.30/arch/ppc64/kernel/signal.c linux-2.4.30-hf32.3/arch/ppc64/kernel/signal.c
+--- linux-2.4.30/arch/ppc64/kernel/signal.c    2005-01-27 18:57:31.000000000 +0100
++++ linux-2.4.30-hf32.3/arch/ppc64/kernel/signal.c     2006-03-18 00:34:06.000000000 +0100
+@@ -332,7 +332,7 @@
+ }
+-asmlinkage int
++asmlinkage long
+ sys_rt_sigreturn(unsigned long r3, unsigned long r4, unsigned long r5,
+                unsigned long r6, unsigned long r7, unsigned long r8,
+                struct pt_regs *regs)
+diff -urN linux-2.4.30/arch/ppc64/kernel/sys_ppc32.c linux-2.4.30-hf32.3/arch/ppc64/kernel/sys_ppc32.c
+--- linux-2.4.30/arch/ppc64/kernel/sys_ppc32.c 2005-04-14 09:43:33.000000000 +0200
++++ linux-2.4.30-hf32.3/arch/ppc64/kernel/sys_ppc32.c  2006-03-18 00:34:06.000000000 +0100
+@@ -3442,12 +3442,13 @@
+       struct cmsghdr *kcmsg, *kcmsg_base;
+       __kernel_size_t32 ucmlen;
+       __kernel_size_t kcmlen, tmp;
++      int err = -EFAULT;
+       kcmlen = 0;
+       kcmsg_base = kcmsg = (struct cmsghdr *)stackbuf;
+       ucmsg = CMSG32_FIRSTHDR(kmsg);
+       while(ucmsg != NULL) {
+-              if(get_user(ucmlen, &ucmsg->cmsg_len))
++              if (get_user(ucmlen, &ucmsg->cmsg_len))
+                       return -EFAULT;
+               /* Catch bogons. */
+@@ -3456,6 +3457,7 @@
+               tmp = ((ucmlen - CMSG32_ALIGN(sizeof(*ucmsg))) +
+                      CMSG_ALIGN(sizeof(struct cmsghdr)));
++              tmp = CMSG_ALIGN(tmp);
+               kcmlen += tmp;
+               ucmsg = CMSG32_NXTHDR(kmsg, ucmsg, ucmlen);
+       }
+@@ -3476,21 +3478,23 @@
+       memset(kcmsg, 0, kcmlen);
+       ucmsg = CMSG32_FIRSTHDR(kmsg);
+       while (ucmsg != NULL) {
+-              __get_user(ucmlen, &ucmsg->cmsg_len);
++              if (__get_user(ucmlen, &ucmsg->cmsg_len))
++                      goto Efault;
+               tmp = ((ucmlen - CMSG32_ALIGN(sizeof(*ucmsg))) +
+                      CMSG_ALIGN(sizeof(struct cmsghdr)));
++              if ((char *)kcmsg_base + kcmlen - (char *)kcmsg < CMSG_ALIGN(tmp))
++                      goto Einval;
+               kcmsg->cmsg_len = tmp;
+-              __get_user(kcmsg->cmsg_level, &ucmsg->cmsg_level);
+-              __get_user(kcmsg->cmsg_type, &ucmsg->cmsg_type);
+-
+-              /* Copy over the data. */
+-              if(copy_from_user(CMSG_DATA(kcmsg),
+-                                CMSG32_DATA(ucmsg),
+-                                (ucmlen - CMSG32_ALIGN(sizeof(*ucmsg)))))
+-                      goto out_free_efault;
++              tmp = CMSG_ALIGN(tmp);
++              if (__get_user(kcmsg->cmsg_level, &ucmsg->cmsg_level) ||
++                  __get_user(kcmsg->cmsg_type, &ucmsg->cmsg_type) ||
++                  copy_from_user(CMSG_DATA(kcmsg),
++                                 CMSG32_DATA(ucmsg),
++                                 (ucmlen - CMSG32_ALIGN(sizeof(*ucmsg)))))
++                      goto Efault;
+               /* Advance. */
+-              kcmsg = (struct cmsghdr *)((char *)kcmsg + CMSG_ALIGN(tmp));
++              kcmsg = (struct cmsghdr *)((char *)kcmsg + tmp);
+               ucmsg = CMSG32_NXTHDR(kmsg, ucmsg, ucmlen);
+       }
+@@ -3499,10 +3503,12 @@
+       kmsg->msg_controllen = kcmlen;
+       return 0;
+-out_free_efault:
+-      if(kcmsg_base != (struct cmsghdr *)stackbuf)
++Einval:
++      err = -EINVAL;
++Efault:
++      if (kcmsg_base != (struct cmsghdr *)stackbuf)
+               kfree(kcmsg_base);
+-      return -EFAULT;
++      return err;
+ }
+ asmlinkage long sys32_sendmsg(int fd, struct msghdr32* user_msg, unsigned int user_flags)
+diff -urN linux-2.4.30/arch/s390x/kernel/linux32.c linux-2.4.30-hf32.3/arch/s390x/kernel/linux32.c
+--- linux-2.4.30/arch/s390x/kernel/linux32.c   2005-04-14 09:43:33.000000000 +0200
++++ linux-2.4.30-hf32.3/arch/s390x/kernel/linux32.c    2006-03-18 00:34:06.000000000 +0100
+@@ -2425,12 +2425,13 @@
+       struct cmsghdr *kcmsg, *kcmsg_base;
+       __kernel_size_t32 ucmlen;
+       __kernel_size_t kcmlen, tmp;
++      int err = -EFAULT;
+       kcmlen = 0;
+       kcmsg_base = kcmsg = (struct cmsghdr *)stackbuf;
+       ucmsg = CMSG32_FIRSTHDR(kmsg);
+       while(ucmsg != NULL) {
+-              if(get_user(ucmlen, &ucmsg->cmsg_len))
++              if (get_user(ucmlen, &ucmsg->cmsg_len))
+                       return -EFAULT;
+               /* Catch bogons. */
+@@ -2439,6 +2440,7 @@
+               tmp = ((ucmlen - CMSG32_ALIGN(sizeof(*ucmsg))) +
+                      CMSG_ALIGN(sizeof(struct cmsghdr)));
++              tmp = CMSG_ALIGN(tmp);
+               kcmlen += tmp;
+               ucmsg = CMSG32_NXTHDR(kmsg, ucmsg, ucmlen);
+       }
+@@ -2459,21 +2461,23 @@
+       memset(kcmsg, 0, kcmlen);
+       ucmsg = CMSG32_FIRSTHDR(kmsg);
+       while(ucmsg != NULL) {
+-              __get_user(ucmlen, &ucmsg->cmsg_len);
++              if (__get_user(ucmlen, &ucmsg->cmsg_len))
++                      goto Efault;
+               tmp = ((ucmlen - CMSG32_ALIGN(sizeof(*ucmsg))) +
+                      CMSG_ALIGN(sizeof(struct cmsghdr)));
++              if ((char *)kcmsg_base + kcmlen - (char *)kcmsg < CMSG_ALIGN(tmp))
++                      goto Einval;
+               kcmsg->cmsg_len = tmp;
+-              __get_user(kcmsg->cmsg_level, &ucmsg->cmsg_level);
+-              __get_user(kcmsg->cmsg_type, &ucmsg->cmsg_type);
+-
+-              /* Copy over the data. */
+-              if(copy_from_user(CMSG_DATA(kcmsg),
+-                                CMSG32_DATA(ucmsg),
+-                                (ucmlen - CMSG32_ALIGN(sizeof(*ucmsg)))))
+-                      goto out_free_efault;
++              tmp = CMSG_ALIGN(tmp);
++              if (__get_user(kcmsg->cmsg_level, &ucmsg->cmsg_level) ||
++                  __get_user(kcmsg->cmsg_type, &ucmsg->cmsg_type) ||
++                  copy_from_user(CMSG_DATA(kcmsg),
++                                 CMSG32_DATA(ucmsg),
++                                 (ucmlen - CMSG32_ALIGN(sizeof(*ucmsg)))))
++                      goto Efault;
+               /* Advance. */
+-              kcmsg = (struct cmsghdr *)((char *)kcmsg + CMSG_ALIGN(tmp));
++              kcmsg = (struct cmsghdr *)((char *)kcmsg + tmp);
+               ucmsg = CMSG32_NXTHDR(kmsg, ucmsg, ucmlen);
+       }
+@@ -2482,10 +2486,12 @@
+       kmsg->msg_controllen = kcmlen;
+       return 0;
+-out_free_efault:
+-      if(kcmsg_base != (struct cmsghdr *)stackbuf)
++Einval:
++      err = -EINVAL;
++Efault:
++      if (kcmsg_base != (struct cmsghdr *)stackbuf)
+               kfree(kcmsg_base);
+-      return -EFAULT;
++      return err;
+ }
+ static void put_cmsg32(struct msghdr *kmsg, int level, int type,
+diff -urN linux-2.4.30/arch/sparc/math-emu/math.c linux-2.4.30-hf32.3/arch/sparc/math-emu/math.c
+--- linux-2.4.30/arch/sparc/math-emu/math.c    1999-12-03 00:28:54.000000000 +0100
++++ linux-2.4.30-hf32.3/arch/sparc/math-emu/math.c     2006-03-18 00:34:06.000000000 +0100
+@@ -323,10 +323,6 @@
+               case FMOVS:
+               case FABSS:
+               case FNEGS: TYPE(2,1,0,1,0,0,0); break;
+-              default:
+-#ifdef DEBUG_MATHEMU
+-                      printk("unknown FPop1: %03lx\n",(insn>>5)&0x1ff);
+-#endif
+               }
+       } else if ((insn & 0xc1f80000) == 0x81a80000)   /* FPOP2 */ {
+               switch ((insn >> 5) & 0x1ff) {
+@@ -336,10 +332,6 @@
+               case FCMPED: TYPE(3,0,0,2,1,2,1); break;
+               case FCMPQ: TYPE(3,0,0,3,1,3,1); break;
+               case FCMPEQ: TYPE(3,0,0,3,1,3,1); break;
+-              default:
+-#ifdef DEBUG_MATHEMU
+-                      printk("unknown FPop2: %03lx\n",(insn>>5)&0x1ff);
+-#endif
+               }
+       }
+diff -urN linux-2.4.30/arch/sparc64/kernel/ioctl32.c linux-2.4.30-hf32.3/arch/sparc64/kernel/ioctl32.c
+--- linux-2.4.30/arch/sparc64/kernel/ioctl32.c 2005-04-14 09:43:33.000000000 +0200
++++ linux-2.4.30-hf32.3/arch/sparc64/kernel/ioctl32.c  2006-03-18 00:34:06.000000000 +0100
+@@ -809,13 +809,15 @@
+               r = (void *) &r4;
+       }
+-      if (ret)
+-              return -EFAULT;
++      if (ret) {
++              ret = -EFAULT;
++              goto out;
++      }
+       set_fs (KERNEL_DS);
+       ret = sys_ioctl (fd, cmd, (long) r);
+       set_fs (old_fs);
+-
++out:
+       if (mysock)
+               sockfd_put(mysock);
+diff -urN linux-2.4.30/arch/sparc64/kernel/sys_sparc32.c linux-2.4.30-hf32.3/arch/sparc64/kernel/sys_sparc32.c
+--- linux-2.4.30/arch/sparc64/kernel/sys_sparc32.c     2005-04-14 09:43:33.000000000 +0200
++++ linux-2.4.30-hf32.3/arch/sparc64/kernel/sys_sparc32.c      2006-03-18 00:34:06.000000000 +0100
+@@ -50,6 +50,7 @@
+ #include <linux/in.h>
+ #include <linux/icmpv6.h>
+ #include <linux/sysctl.h>
++#include <linux/vmalloc.h>
+ #include <linux/dnotify.h>
+ #include <linux/netfilter_ipv4/ip_tables.h>
+@@ -2496,12 +2497,13 @@
+       struct cmsghdr *kcmsg, *kcmsg_base;
+       __kernel_size_t32 ucmlen;
+       __kernel_size_t kcmlen, tmp;
++      int err = -EFAULT;
+       kcmlen = 0;
+       kcmsg_base = kcmsg = (struct cmsghdr *)stackbuf;
+       ucmsg = CMSG32_FIRSTHDR(kmsg);
+       while(ucmsg != NULL) {
+-              if(get_user(ucmlen, &ucmsg->cmsg_len))
++              if (get_user(ucmlen, &ucmsg->cmsg_len))
+                       return -EFAULT;
+               /* Catch bogons. */
+@@ -2510,6 +2512,7 @@
+               tmp = ((ucmlen - CMSG32_ALIGN(sizeof(*ucmsg))) +
+                      CMSG_ALIGN(sizeof(struct cmsghdr)));
++              tmp = CMSG_ALIGN(tmp);
+               kcmlen += tmp;
+               ucmsg = CMSG32_NXTHDR(kmsg, ucmsg, ucmlen);
+       }
+@@ -2530,21 +2533,23 @@
+       memset(kcmsg, 0, kcmlen);
+       ucmsg = CMSG32_FIRSTHDR(kmsg);
+       while(ucmsg != NULL) {
+-              __get_user(ucmlen, &ucmsg->cmsg_len);
++              if (__get_user(ucmlen, &ucmsg->cmsg_len))
++                      goto Efault;
+               tmp = ((ucmlen - CMSG32_ALIGN(sizeof(*ucmsg))) +
+                      CMSG_ALIGN(sizeof(struct cmsghdr)));
++              if ((char *)kcmsg_base + kcmlen - (char *)kcmsg < CMSG_ALIGN(tmp))
++                      goto Einval;
+               kcmsg->cmsg_len = tmp;
+-              __get_user(kcmsg->cmsg_level, &ucmsg->cmsg_level);
+-              __get_user(kcmsg->cmsg_type, &ucmsg->cmsg_type);
+-
+-              /* Copy over the data. */
+-              if(copy_from_user(CMSG_DATA(kcmsg),
+-                                CMSG32_DATA(ucmsg),
+-                                (ucmlen - CMSG32_ALIGN(sizeof(*ucmsg)))))
+-                      goto out_free_efault;
++              tmp = CMSG_ALIGN(tmp);
++              if (__get_user(kcmsg->cmsg_level, &ucmsg->cmsg_level) ||
++                  __get_user(kcmsg->cmsg_type, &ucmsg->cmsg_type) ||
++                  copy_from_user(CMSG_DATA(kcmsg),
++                                 CMSG32_DATA(ucmsg),
++                                 (ucmlen - CMSG32_ALIGN(sizeof(*ucmsg)))))
++                      goto Efault;
+               /* Advance. */
+-              kcmsg = (struct cmsghdr *)((char *)kcmsg + CMSG_ALIGN(tmp));
++              kcmsg = (struct cmsghdr *)((char *)kcmsg + tmp);
+               ucmsg = CMSG32_NXTHDR(kmsg, ucmsg, ucmlen);
+       }
+@@ -2553,10 +2558,12 @@
+       kmsg->msg_controllen = kcmlen;
+       return 0;
+-out_free_efault:
+-      if(kcmsg_base != (struct cmsghdr *)stackbuf)
++Einval:
++      err = -EINVAL;
++Efault:
++      if (kcmsg_base != (struct cmsghdr *)stackbuf)
+               kfree(kcmsg_base);
+-      return -EFAULT;
++      return err;
+ }
+ static void put_cmsg32(struct msghdr *kmsg, int level, int type,
+@@ -2919,12 +2926,12 @@
+       if (optlen != kreplsize)
+               return -ENOPROTOOPT;
+-      krepl = (struct ipt_replace *)kmalloc(kreplsize, GFP_KERNEL);
++      krepl = (struct ipt_replace *)vmalloc(kreplsize);
+       if (krepl == NULL)
+               return -ENOMEM;
+       if (copy_from_user(krepl, optval, kreplsize)) {
+-              kfree(krepl);
++              vfree(krepl);
+               return -EFAULT;
+       }
+@@ -2932,10 +2939,9 @@
+               ((struct ipt_replace32 *)krepl)->counters);
+       kcountersize = krepl->num_counters * sizeof(struct ipt_counters);
+-      krepl->counters = (struct ipt_counters *)kmalloc(
+-                                      kcountersize, GFP_KERNEL);
++      krepl->counters = (struct ipt_counters *)vmalloc(kcountersize);
+       if (krepl->counters == NULL) {
+-              kfree(krepl);
++              vfree(krepl);
+               return -ENOMEM;
+       }
+@@ -2949,8 +2955,8 @@
+               copy_to_user(counters32, krepl->counters, kcountersize))
+                       ret = -EFAULT;
+-      kfree(krepl->counters);
+-      kfree(krepl);
++      vfree(krepl->counters);
++      vfree(krepl);
+       return ret;
+ }
+@@ -4205,7 +4211,7 @@
+               old_fs = get_fs();
+               set_fs(KERNEL_DS);
+-              ret = sys_utimes(kfilename, &ktvs[0]);
++              ret = sys_utimes(kfilename, (tvs ? &ktvs[0] : NULL));
+               set_fs(old_fs);
+               putname(kfilename);
+diff -urN linux-2.4.30/arch/sparc64/solaris/socket.c linux-2.4.30-hf32.3/arch/sparc64/solaris/socket.c
+--- linux-2.4.30/arch/sparc64/solaris/socket.c 2001-02-19 04:49:54.000000000 +0100
++++ linux-2.4.30-hf32.3/arch/sparc64/solaris/socket.c  2006-03-18 00:34:06.000000000 +0100
+@@ -410,8 +410,10 @@
+               unsigned long *kcmsg;
+               __kernel_size_t32 cmlen;
+-              if(kern_msg.msg_controllen > sizeof(ctl) &&
+-                 kern_msg.msg_controllen <= 256) {
++              if (kern_msg.msg_controllen <= sizeof(__kernel_size_t32))
++                      return -EINVAL;
++
++              if(kern_msg.msg_controllen > sizeof(ctl)) {
+                       err = -ENOBUFS;
+                       ctl_buf = kmalloc(kern_msg.msg_controllen, GFP_KERNEL);
+                       if(!ctl_buf)
+diff -urN linux-2.4.30/arch/x86_64/ia32/ia32_ioctl.c linux-2.4.30-hf32.3/arch/x86_64/ia32/ia32_ioctl.c
+--- linux-2.4.30/arch/x86_64/ia32/ia32_ioctl.c 2005-01-27 18:57:31.000000000 +0100
++++ linux-2.4.30-hf32.3/arch/x86_64/ia32/ia32_ioctl.c  2006-03-18 00:34:06.000000000 +0100
+@@ -816,6 +816,11 @@
+ extern struct socket *sockfd_lookup(int fd, int *err);
++extern __inline__ void sockfd_put(struct socket *sock)
++{
++      fput(sock->file);
++}
++
+ static int routing_ioctl(unsigned int fd, unsigned int cmd, unsigned long arg)
+ {
+       int ret;
+@@ -857,12 +862,17 @@
+               r = (void *) &r4;
+       }
+-      if (ret)
+-              return -EFAULT;
++      if (ret) {
++              ret = -EFAULT;
++              goto out;
++      }
+       set_fs (KERNEL_DS);
+       ret = sys_ioctl (fd, cmd, (long) r);
+       set_fs (old_fs);
++out:
++      if (mysock)
++              sockfd_put(mysock);
+       return ret;
+ }
+@@ -2766,17 +2776,24 @@
+ static int tiocgdev(unsigned fd, unsigned cmd,  unsigned int *ptr) 
+ { 
+-      struct file *file = fget(fd);
++      struct file *file;
+       struct tty_struct *real_tty;
++      int ret;
++      file = fget(fd);
+       if (!file)
+               return -EBADF;
++      ret = -EINVAL;
+       if (file->f_op->ioctl != tty_ioctl)
+-              return -EINVAL; 
++              goto out;
+       real_tty = (struct tty_struct *)file->private_data;
+       if (!real_tty)  
+-              return -EINVAL; 
+-      return put_user(kdev_t_to_nr(real_tty->device), ptr); 
++              goto out;
++      ret = put_user(kdev_t_to_nr(real_tty->device), ptr); 
++out:
++      fput(file);
++
++      return ret;
+ } 
+diff -urN linux-2.4.30/arch/x86_64/ia32/socket32.c linux-2.4.30-hf32.3/arch/x86_64/ia32/socket32.c
+--- linux-2.4.30/arch/x86_64/ia32/socket32.c   2005-04-14 09:43:33.000000000 +0200
++++ linux-2.4.30-hf32.3/arch/x86_64/ia32/socket32.c    2006-03-18 00:34:06.000000000 +0100
+@@ -127,12 +127,13 @@
+       struct cmsghdr *kcmsg, *kcmsg_base;
+       __kernel_size_t32 ucmlen;
+       __kernel_size_t kcmlen, tmp;
++      int err = -EFAULT;
+       kcmlen = 0;
+       kcmsg_base = kcmsg = (struct cmsghdr *)stackbuf;
+       ucmsg = CMSG32_FIRSTHDR(kmsg);
+       while(ucmsg != NULL) {
+-              if(get_user(ucmlen, &ucmsg->cmsg_len))
++              if (get_user(ucmlen, &ucmsg->cmsg_len))
+                       return -EFAULT;
+               /* Catch bogons. */
+@@ -164,18 +165,19 @@
+       memset(kcmsg, 0, kcmlen);
+       ucmsg = CMSG32_FIRSTHDR(kmsg);
+       while(ucmsg != NULL) {
+-              __get_user(ucmlen, &ucmsg->cmsg_len);
++              if (__get_user(ucmlen, &ucmsg->cmsg_len))
++                      goto Efault;
+               tmp = ((ucmlen - CMSG32_ALIGN(sizeof(*ucmsg))) +
+                      CMSG_ALIGN(sizeof(struct cmsghdr)));
++              if ((char *)kcmsg_base + kcmlen - (char *)kcmsg < CMSG_ALIGN(tmp))
++                      goto Einval;
+               kcmsg->cmsg_len = tmp;
+-              __get_user(kcmsg->cmsg_level, &ucmsg->cmsg_level);
+-              __get_user(kcmsg->cmsg_type, &ucmsg->cmsg_type);
+-
+-              /* Copy over the data. */
+-              if(copy_from_user(CMSG_DATA(kcmsg),
+-                                CMSG32_DATA(ucmsg),
+-                                (ucmlen - CMSG32_ALIGN(sizeof(*ucmsg)))))
+-                      goto out_free_efault;
++              if (__get_user(kcmsg->cmsg_level, &ucmsg->cmsg_level) ||
++                  __get_user(kcmsg->cmsg_type, &ucmsg->cmsg_type) ||
++                  copy_from_user(CMSG_DATA(kcmsg),
++                                 CMSG32_DATA(ucmsg),
++                                 (ucmlen - CMSG32_ALIGN(sizeof(*ucmsg)))))
++                      goto Efault;
+               /* Advance. */
+               kcmsg = (struct cmsghdr *)((char *)kcmsg + CMSG_ALIGN(tmp));
+@@ -187,10 +189,12 @@
+       kmsg->msg_controllen = kcmlen;
+       return 0;
+-out_free_efault:
+-      if(kcmsg_base != (struct cmsghdr *)stackbuf)
++Einval:
++      err = -EINVAL;
++Efault:
++      if (kcmsg_base != (struct cmsghdr *)stackbuf)
+               kfree(kcmsg_base);
+-      return -EFAULT;
++      return err;
+ }
+ static void put_cmsg32(struct msghdr *kmsg, int level, int type,
+diff -urN linux-2.4.30/arch/x86_64/ia32/sys_ia32.c linux-2.4.30-hf32.3/arch/x86_64/ia32/sys_ia32.c
+--- linux-2.4.30/arch/x86_64/ia32/sys_ia32.c   2005-01-27 18:57:31.000000000 +0100
++++ linux-2.4.30-hf32.3/arch/x86_64/ia32/sys_ia32.c    2006-03-18 00:34:06.000000000 +0100
+@@ -2200,7 +2200,7 @@
+       return ret;
+ } 
+-static int nargs(u32 src, char **dst) 
++static int nargs(u32 src, char **dst, int max) 
+ { 
+       int cnt;
+       u32 val; 
+@@ -2210,13 +2210,13 @@
+               int ret = get_user(val, (__u32 *)(u64)src); 
+               if (ret)
+                       return ret;
++              if (cnt > max)
++                      return -E2BIG; 
+               if (dst)
+                       dst[cnt] = (char *)(u64)val; 
+               cnt++;
+               src += 4;
+-              if (cnt >= (MAX_ARG_PAGES * PAGE_SIZE) / sizeof(char *))
+-                      return -E2BIG; 
+-      } while(val); 
++              } while(val); 
+       if (dst)
+               dst[cnt-1] = 0; 
+       return cnt; 
+@@ -2230,13 +2230,14 @@
+       int ret;
+       unsigned sz = 0; 
+       
++      /* Can actually allocate 2*MAX_ARG_PAGES */
+       if (argv) {
+-      na = nargs(argv, NULL); 
++      na = nargs(argv, NULL, (MAX_ARG_PAGES * PAGE_SIZE)/sizeof(char*) - 1); 
+       if (na < 0) 
+               return -EFAULT; 
+       }       
+       if (envp) { 
+-      ne = nargs(envp, NULL); 
++      ne = nargs(envp, NULL, (MAX_ARG_PAGES * PAGE_SIZE)/sizeof(char*) - 1); 
+       if (ne < 0) 
+               return -EFAULT; 
+       }
+@@ -2252,13 +2253,13 @@
+       } 
+       
+       if (argv) { 
+-      ret = nargs(argv, buf);
++      ret = nargs(argv, buf, na);
+       if (ret < 0)
+               goto free;
+       }
+       if (envp) { 
+-      ret = nargs(envp, buf + na); 
++      ret = nargs(envp, buf + na, ne); 
+       if (ret < 0)
+               goto free; 
+       }
+diff -urN linux-2.4.30/arch/x86_64/kernel/process.c linux-2.4.30-hf32.3/arch/x86_64/kernel/process.c
+--- linux-2.4.30/arch/x86_64/kernel/process.c  2004-04-14 15:05:28.000000000 +0200
++++ linux-2.4.30-hf32.3/arch/x86_64/kernel/process.c   2006-03-18 00:34:06.000000000 +0100
+@@ -527,10 +527,10 @@
+       p->thread.fs = me->thread.fs;
+       p->thread.gs = me->thread.gs;
+-      asm("movl %%gs,%0" : "=m" (p->thread.gsindex));
+-      asm("movl %%fs,%0" : "=m" (p->thread.fsindex));
+-      asm("movl %%es,%0" : "=m" (p->thread.es));
+-      asm("movl %%ds,%0" : "=m" (p->thread.ds));
++      asm("mov %%gs,%0" : "=m" (p->thread.gsindex));
++      asm("mov %%fs,%0" : "=m" (p->thread.fsindex));
++      asm("mov %%es,%0" : "=m" (p->thread.es));
++      asm("mov %%ds,%0" : "=m" (p->thread.ds));
+       unlazy_fpu(current);    
+       p->thread.i387 = current->thread.i387;
+@@ -575,11 +575,11 @@
+       /* 
+        * Switch DS and ES.     
+        */
+-      asm volatile("movl %%es,%0" : "=m" (prev->es)); 
++      asm volatile("mov %%es,%0" : "=m" (prev->es)); 
+       if (unlikely(next->es | prev->es))
+               loadsegment(es, next->es); 
+       
+-      asm volatile ("movl %%ds,%0" : "=m" (prev->ds)); 
++      asm volatile ("mov %%ds,%0" : "=m" (prev->ds)); 
+       if (unlikely(next->ds | prev->ds))
+               loadsegment(ds, next->ds);
+@@ -588,7 +588,7 @@
+        */
+       { 
+               unsigned fsindex;
+-              asm volatile("movl %%fs,%0" : "=g" (fsindex)); 
++              asm volatile("movl %%fs,%0" : "=r" (fsindex)); 
+               /* segment register != 0 always requires a reload. 
+                  also reload when it has changed. 
+                  when prev process used 64bit base always reload
+@@ -609,7 +609,7 @@
+       }
+       {
+               unsigned gsindex;
+-              asm volatile("movl %%gs,%0" : "=g" (gsindex)); 
++              asm volatile("movl %%gs,%0" : "=r" (gsindex)); 
+               if (unlikely((gsindex | next->gsindex) || prev->gs)) {
+                       load_gs_index(next->gsindex);
+                       if (gsindex)
+diff -urN linux-2.4.30/arch/x86_64/kernel/ptrace.c linux-2.4.30-hf32.3/arch/x86_64/kernel/ptrace.c
+--- linux-2.4.30/arch/x86_64/kernel/ptrace.c   2003-06-13 16:51:32.000000000 +0200
++++ linux-2.4.30-hf32.3/arch/x86_64/kernel/ptrace.c    2006-03-18 00:34:06.000000000 +0100
+@@ -114,13 +114,13 @@
+                       child->thread.es = value & 0xffff;
+                       return 0;
+               case offsetof(struct user_regs_struct,fs_base):
+-                      if (!((value >> 48) == 0 || (value >> 48) == 0xffff))
+-                              return -EIO; 
++                      if (value >= TASK_SIZE)
++                              return -EIO;
+                       child->thread.fs = value;
+                       return 0;
+               case offsetof(struct user_regs_struct,gs_base):
+-                      if (!((value >> 48) == 0 || (value >> 48) == 0xffff))
+-                              return -EIO; 
++                      if (value >= TASK_SIZE)
++                              return -EIO;
+                       child->thread.gs = value;
+                       return 0;
+               case offsetof(struct user_regs_struct, eflags):
+@@ -139,6 +139,11 @@
+                               return -EIO;
+                       value &= 0xffff;
+             break;
++              case offsetof(struct user_regs_struct, rip):
++                      /* Check if the new RIP address is canonical */
++                      if (value >= TASK_SIZE)
++                              return -EIO;
++                      break;
+       }      
+       put_stack_long(child, regno - sizeof(struct pt_regs), value);
+       return 0;
+diff -urN linux-2.4.30/arch/x86_64/kernel/traps.c linux-2.4.30-hf32.3/arch/x86_64/kernel/traps.c
+--- linux-2.4.30/arch/x86_64/kernel/traps.c    2004-04-14 15:05:28.000000000 +0200
++++ linux-2.4.30-hf32.3/arch/x86_64/kernel/traps.c     2006-03-18 00:34:06.000000000 +0100
+@@ -857,7 +857,7 @@
+       set_intr_gate(9,&coprocessor_segment_overrun);
+       set_intr_gate(10,&invalid_TSS);
+       set_intr_gate(11,&segment_not_present);
+-      set_intr_gate_ist(12,&stack_segment,STACKFAULT_STACK);
++      set_intr_gate(12,&stack_segment);
+       set_intr_gate(13,&general_protection);
+       set_intr_gate(14,&page_fault);
+       set_intr_gate(15,&spurious_interrupt_bug);
+diff -urN linux-2.4.30/drivers/block/loop.c linux-2.4.30-hf32.3/drivers/block/loop.c
+--- linux-2.4.30/drivers/block/loop.c  2003-08-25 13:44:41.000000000 +0200
++++ linux-2.4.30-hf32.3/drivers/block/loop.c   2006-03-18 00:34:06.000000000 +0100
+@@ -974,7 +974,7 @@
+ int loop_register_transfer(struct loop_func_table *funcs)
+ {
+-      if ((unsigned)funcs->number > MAX_LO_CRYPT || xfer_funcs[funcs->number])
++      if ((unsigned)funcs->number >= MAX_LO_CRYPT || xfer_funcs[funcs->number])
+               return -EINVAL;
+       xfer_funcs[funcs->number] = funcs;
+       return 0; 
+diff -urN linux-2.4.30/drivers/bluetooth/bfusb.c linux-2.4.30-hf32.3/drivers/bluetooth/bfusb.c
+--- linux-2.4.30/drivers/bluetooth/bfusb.c     2004-08-08 01:26:04.000000000 +0200
++++ linux-2.4.30-hf32.3/drivers/bluetooth/bfusb.c      2006-03-18 00:34:06.000000000 +0100
+@@ -470,12 +470,11 @@
+               return 0;
+       write_lock_irqsave(&bfusb->lock, flags);
++      write_unlock_irqrestore(&bfusb->lock, flags);
+       bfusb_unlink_urbs(bfusb);
+       bfusb_flush(hdev);
+-      write_unlock_irqrestore(&bfusb->lock, flags);
+-
+       MOD_DEC_USE_COUNT;
+       return 0;
+diff -urN linux-2.4.30/drivers/bluetooth/hci_usb.c linux-2.4.30-hf32.3/drivers/bluetooth/hci_usb.c
+--- linux-2.4.30/drivers/bluetooth/hci_usb.c   2004-08-08 01:26:04.000000000 +0200
++++ linux-2.4.30-hf32.3/drivers/bluetooth/hci_usb.c    2006-03-18 00:34:06.000000000 +0100
+@@ -398,13 +398,13 @@
+       BT_DBG("%s", hdev->name);
++      /* Synchronize with completion handlers */
+       write_lock_irqsave(&husb->completion_lock, flags);
+-      
++      write_unlock_irqrestore(&husb->completion_lock, flags);
++
+       hci_usb_unlink_urbs(husb);
+       hci_usb_flush(hdev);
+-      write_unlock_irqrestore(&husb->completion_lock, flags);
+-
+       MOD_DEC_USE_COUNT;
+       return 0;
+ }
+diff -urN linux-2.4.30/drivers/char/cyclades.c linux-2.4.30-hf32.3/drivers/char/cyclades.c
+--- linux-2.4.30/drivers/char/cyclades.c       2005-01-27 18:57:32.000000000 +0100
++++ linux-2.4.30-hf32.3/drivers/char/cyclades.c        2006-03-18 00:34:06.000000000 +0100
+@@ -2960,10 +2960,15 @@
+ cy_write(struct tty_struct * tty, int from_user,
+            const unsigned char *buf, int count)
+ {
+-  struct cyclades_port *info = (struct cyclades_port *)tty->driver_data;
++  struct cyclades_port *info;
+   unsigned long flags;
+   int c, ret = 0;
++    if (!tty)
++      return 0;
++
++    info = (struct cyclades_port *)tty->driver_data;
++  
+ #ifdef CY_DEBUG_IO
+     printk("cyc:cy_write ttyC%d\n", info->line); /* */
+ #endif
+@@ -2972,7 +2977,7 @@
+         return 0;
+     }
+         
+-    if (!tty || !info->xmit_buf || !tmp_buf){
++    if (!info->xmit_buf || !tmp_buf){
+         return 0;
+     }
+@@ -3047,9 +3052,14 @@
+ static void
+ cy_put_char(struct tty_struct *tty, unsigned char ch)
+ {
+-  struct cyclades_port *info = (struct cyclades_port *)tty->driver_data;
++  struct cyclades_port *info;
+   unsigned long flags;
++    if (!tty)
++        return;
++
++    info = (struct cyclades_port *)tty->driver_data;
++  
+ #ifdef CY_DEBUG_IO
+     printk("cyc:cy_put_char ttyC%d\n", info->line);
+ #endif
+@@ -3057,7 +3067,7 @@
+     if (serial_paranoia_check(info, tty->device, "cy_put_char"))
+         return;
+-    if (!tty || !info->xmit_buf)
++    if (!info->xmit_buf)
+         return;
+     CY_LOCK(info, flags);
+diff -urN linux-2.4.30/drivers/char/drm/drm_stub.h linux-2.4.30-hf32.3/drivers/char/drm/drm_stub.h
+--- linux-2.4.30/drivers/char/drm/drm_stub.h   2006-02-26 22:56:01.000000000 +0100
++++ linux-2.4.30-hf32.3/drivers/char/drm/drm_stub.h    2006-03-18 00:34:06.000000000 +0100
+@@ -52,6 +52,7 @@
+       int                    err   = -ENODEV;
+       struct file_operations *old_fops;
++      if (minor < 0 || minor >=DRM_STUB_MAXCARDS) return -ENODEV;
+       if (!DRM(stub_list) || !DRM(stub_list)[minor].fops) return -ENODEV;
+       old_fops   = filp->f_op;
+       filp->f_op = fops_get(DRM(stub_list)[minor].fops);
+diff -urN linux-2.4.30/drivers/char/esp.c linux-2.4.30-hf32.3/drivers/char/esp.c
+--- linux-2.4.30/drivers/char/esp.c    2005-01-27 18:57:32.000000000 +0100
++++ linux-2.4.30-hf32.3/drivers/char/esp.c     2006-03-18 00:34:06.000000000 +0100
+@@ -1251,13 +1251,18 @@
+ static void rs_put_char(struct tty_struct *tty, unsigned char ch)
+ {
+-      struct esp_struct *info = (struct esp_struct *)tty->driver_data;
++      struct esp_struct *info;
+       unsigned long flags;
++      if (!tty)
++              return;
++
++      info = (struct esp_struct *)tty->driver_data;
++      
+       if (serial_paranoia_check(info, tty->device, "rs_put_char"))
+               return;
+-      if (!tty || !info->xmit_buf)
++      if (!info->xmit_buf)
+               return;
+       save_flags(flags); cli();
+@@ -1296,13 +1301,19 @@
+                   const unsigned char *buf, int count)
+ {
+       int     c, t, ret = 0;
+-      struct esp_struct *info = (struct esp_struct *)tty->driver_data;
++      struct esp_struct *info;
+       unsigned long flags;
++
++      if (!tty)
++              return 0;
++      
++      info = (struct esp_struct *)tty->driver_data;
++
+       if (serial_paranoia_check(info, tty->device, "rs_write"))
+               return 0;
+-      if (!tty || !info->xmit_buf || !tmp_buf)
++      if (!info->xmit_buf || !tmp_buf)
+               return 0;
+           
+       if (from_user)
+diff -urN linux-2.4.30/drivers/char/isicom.c linux-2.4.30-hf32.3/drivers/char/isicom.c
+--- linux-2.4.30/drivers/char/isicom.c 2005-01-27 18:57:32.000000000 +0100
++++ linux-2.4.30-hf32.3/drivers/char/isicom.c  2006-03-18 00:34:06.000000000 +0100
+@@ -1223,9 +1223,15 @@
+ static int isicom_write(struct tty_struct * tty, int from_user,
+                       const unsigned char * buf, int count)
+ {
+-      struct isi_port * port = (struct isi_port *) tty->driver_data;
++      struct isi_port * port;
+       unsigned long flags;
+       int cnt, total = 0;
++
++      if (!tty)
++              return 0;
++      
++      port = (struct isi_port *) tty->driver_data;
++      
+ #ifdef ISICOM_DEBUG
+       printk(KERN_DEBUG "ISICOM: isicom_write for port%d: %d bytes.\n",
+                       port->channel+1, count);
+@@ -1233,7 +1239,7 @@
+       if (isicom_paranoia_check(port, tty->device, "isicom_write"))
+               return 0;
+       
+-      if (!tty || !port->xmit_buf || !tmp_buf)
++      if (!port->xmit_buf || !tmp_buf)
+               return 0;
+       if (from_user)
+               down(&tmp_buf_sem); /* acquire xclusive access to tmp_buf */
+@@ -1281,13 +1287,18 @@
+ /* put_char et all */
+ static void isicom_put_char(struct tty_struct * tty, unsigned char ch)
+ {
+-      struct isi_port * port = (struct isi_port *) tty->driver_data;
++      struct isi_port * port;
+       unsigned long flags;
++
++      if (!tty)
++              return;
++
++      port = (struct isi_port *) tty->driver_data;
+       
+       if (isicom_paranoia_check(port, tty->device, "isicom_put_char"))
+               return;
+       
+-      if (!tty || !port->xmit_buf)
++      if (!port->xmit_buf)
+               return;
+ #ifdef ISICOM_DEBUG
+       printk(KERN_DEBUG "ISICOM: put_char, port %d, char %c.\n", port->channel+1, ch);
+diff -urN linux-2.4.30/drivers/char/moxa.c linux-2.4.30-hf32.3/drivers/char/moxa.c
+--- linux-2.4.30/drivers/char/moxa.c   2005-01-27 18:57:32.000000000 +0100
++++ linux-2.4.30-hf32.3/drivers/char/moxa.c    2006-03-18 00:34:06.000000000 +0100
+@@ -294,6 +294,7 @@
+ static int moxa_get_serial_info(struct moxa_str *, struct serial_struct *);
+ static int moxa_set_serial_info(struct moxa_str *, struct serial_struct *);
+ static void MoxaSetFifo(int port, int enable);
++static unsigned long moxaIntPend[MAX_BOARDS];
+ #ifdef MODULE
+ int init_module(void)
+@@ -995,7 +996,8 @@
+               return;
+       }
+       for (card = 0; card < MAX_BOARDS; card++) {
+-              if ((ports = MoxaPortsOfCard(card)) <= 0)
++              if ((ports = MoxaPortsOfCard(card)) <= 0
++                              || moxaIntPend[card] == 0)
+                       continue;
+               ch = &moxaChannels[card * MAX_PORTS_PER_BOARD];
+               for (i = 0; i < ports; i++, ch++) {
+@@ -1578,7 +1580,6 @@
+ static unsigned char moxaBuff[10240];
+ static unsigned long moxaIntNdx[MAX_BOARDS];
+-static unsigned long moxaIntPend[MAX_BOARDS];
+ static unsigned long moxaIntTable[MAX_BOARDS];
+ static char moxaChkPort[MAX_PORTS];
+ static char moxaLineCtrl[MAX_PORTS];
+diff -urN linux-2.4.30/drivers/char/mxser.c linux-2.4.30-hf32.3/drivers/char/mxser.c
+--- linux-2.4.30/drivers/char/mxser.c  2005-01-27 18:57:32.000000000 +0100
++++ linux-2.4.30-hf32.3/drivers/char/mxser.c   2006-03-18 00:34:06.000000000 +0100
+@@ -911,10 +911,15 @@
+                      const unsigned char *buf, int count)
+ {
+       int c, total = 0;
+-      struct mxser_struct *info = (struct mxser_struct *) tty->driver_data;
++      struct mxser_struct *info;
+       unsigned long flags;
+-      if (!tty || !info->xmit_buf || !mxvar_tmp_buf)
++      if (!tty)
++              return (0);
++      
++      info = (struct mxser_struct *) tty->driver_data;
++      
++      if (!info->xmit_buf || !mxvar_tmp_buf)
+               return (0);
+       save_flags(flags);
+@@ -979,10 +984,15 @@
+ static void mxser_put_char(struct tty_struct *tty, unsigned char ch)
+ {
+-      struct mxser_struct *info = (struct mxser_struct *) tty->driver_data;
++      struct mxser_struct *info;
+       unsigned long flags;
+-      if (!tty || !info->xmit_buf)
++      if (!tty)
++              return;
++
++      info = (struct mxser_struct *) tty->driver_data;
++      
++      if (!info->xmit_buf)
+               return;
+       save_flags(flags);
+diff -urN linux-2.4.30/drivers/char/random.c linux-2.4.30-hf32.3/drivers/char/random.c
+--- linux-2.4.30/drivers/char/random.c 2005-01-27 18:57:32.000000000 +0100
++++ linux-2.4.30-hf32.3/drivers/char/random.c  2006-03-18 00:34:06.000000000 +0100
+@@ -1771,7 +1771,7 @@
+ static int proc_do_poolsize(ctl_table *table, int write, struct file *filp,
+                           void *buffer, size_t *lenp)
+ {
+-      unsigned int    ret;
++      int     ret;
+       sysctl_poolsize = random_state->poolinfo.POOLBYTES;
+@@ -1787,7 +1787,7 @@
+                            void *oldval, size_t *oldlenp,
+                            void *newval, size_t newlen, void **context)
+ {
+-      int     len;
++      unsigned int    len;
+       
+       sysctl_poolsize = random_state->poolinfo.POOLBYTES;
+diff -urN linux-2.4.30/drivers/char/riscom8.c linux-2.4.30-hf32.3/drivers/char/riscom8.c
+--- linux-2.4.30/drivers/char/riscom8.c        2005-01-27 18:57:32.000000000 +0100
++++ linux-2.4.30-hf32.3/drivers/char/riscom8.c 2006-03-18 00:34:06.000000000 +0100
+@@ -1220,17 +1220,22 @@
+ static int rc_write(struct tty_struct * tty, int from_user, 
+                   const unsigned char *buf, int count)
+ {
+-      struct riscom_port *port = (struct riscom_port *)tty->driver_data;
++      struct riscom_port *port;
+       struct riscom_board *bp;
+       int c, total = 0;
+       unsigned long flags;
++
++      if (!tty)
++              return 0;
++
++      port = (struct riscom_port *)tty->driver_data;
+                               
+       if (rc_paranoia_check(port, tty->device, "rc_write"))
+               return 0;
+       
+       bp = port_Board(port);
+-      if (!tty || !port->xmit_buf || !tmp_buf)
++      if (!port->xmit_buf || !tmp_buf)
+               return 0;
+       save_flags(flags);
+@@ -1298,13 +1303,18 @@
+ static void rc_put_char(struct tty_struct * tty, unsigned char ch)
+ {
+-      struct riscom_port *port = (struct riscom_port *)tty->driver_data;
++      struct riscom_port *port;
+       unsigned long flags;
++      if (!tty)
++              return;
++
++      port = (struct riscom_port *)tty->driver_data;
++
+       if (rc_paranoia_check(port, tty->device, "rc_put_char"))
+               return;
+-      if (!tty || !port->xmit_buf)
++      if (!port->xmit_buf)
+               return;
+       save_flags(flags); cli();
+diff -urN linux-2.4.30/drivers/char/serial.c linux-2.4.30-hf32.3/drivers/char/serial.c
+--- linux-2.4.30/drivers/char/serial.c 2005-01-27 18:57:32.000000000 +0100
++++ linux-2.4.30-hf32.3/drivers/char/serial.c  2006-03-18 00:34:06.000000000 +0100
+@@ -1827,13 +1827,18 @@
+ static void rs_put_char(struct tty_struct *tty, unsigned char ch)
+ {
+-      struct async_struct *info = (struct async_struct *)tty->driver_data;
++      struct async_struct *info;
+       unsigned long flags;
++      if (!tty)
++              return;
++      
++      info =  (struct async_struct *)tty->driver_data;
++      
+       if (serial_paranoia_check(info, tty->device, "rs_put_char"))
+               return;
+-      if (!tty || !info->xmit.buf)
++      if (!info->xmit.buf)
+               return;
+       save_flags(flags); cli();
+@@ -1873,13 +1878,18 @@
+                   const unsigned char *buf, int count)
+ {
+       int     c, ret = 0;
+-      struct async_struct *info = (struct async_struct *)tty->driver_data;
++      struct async_struct *info;
+       unsigned long flags;
+                               
++      if (!tty)
++              return 0;
++
++      info = (struct async_struct *)tty->driver_data;
++      
+       if (serial_paranoia_check(info, tty->device, "rs_write"))
+               return 0;
+-      if (!tty || !info->xmit.buf || !tmp_buf)
++      if (!info->xmit.buf || !tmp_buf)
+               return 0;
+       save_flags(flags);
+diff -urN linux-2.4.30/drivers/char/specialix.c linux-2.4.30-hf32.3/drivers/char/specialix.c
+--- linux-2.4.30/drivers/char/specialix.c      2005-01-27 18:57:32.000000000 +0100
++++ linux-2.4.30-hf32.3/drivers/char/specialix.c       2006-03-18 00:34:06.000000000 +0100
+@@ -1600,17 +1600,22 @@
+ static int sx_write(struct tty_struct * tty, int from_user, 
+                     const unsigned char *buf, int count)
+ {
+-      struct specialix_port *port = (struct specialix_port *)tty->driver_data;
++      struct specialix_port *port;
+       struct specialix_board *bp;
+       int c, total = 0;
+       unsigned long flags;
++
++      if (!tty)
++              return 0;
++
++      port = (struct specialix_port *)tty->driver_data;
+                               
+       if (sx_paranoia_check(port, tty->device, "sx_write"))
+               return 0;
+       
+       bp = port_Board(port);
+-      if (!tty || !port->xmit_buf || !tmp_buf)
++      if (!port->xmit_buf || !tmp_buf)
+               return 0;
+       save_flags(flags);
+@@ -1676,13 +1681,18 @@
+ static void sx_put_char(struct tty_struct * tty, unsigned char ch)
+ {
+-      struct specialix_port *port = (struct specialix_port *)tty->driver_data;
++      struct specialix_port *port;
+       unsigned long flags;
++      if (!tty)
++              return;
++
++      port = (struct specialix_port *)tty->driver_data;
++
+       if (sx_paranoia_check(port, tty->device, "sx_put_char"))
+               return;
+-      if (!tty || !port->xmit_buf)
++      if (!port->xmit_buf)
+               return;
+       save_flags(flags); cli();
+diff -urN linux-2.4.30/drivers/char/vt.c linux-2.4.30-hf32.3/drivers/char/vt.c
+--- linux-2.4.30/drivers/char/vt.c     2005-01-27 18:57:32.000000000 +0100
++++ linux-2.4.30-hf32.3/drivers/char/vt.c      2006-03-18 00:34:06.000000000 +0100
+@@ -166,6 +166,9 @@
+       if (i >= NR_KEYS || s >= MAX_NR_KEYMAPS)
+               return -EINVAL; 
++      if (!capable(CAP_SYS_TTY_CONFIG))
++              perm = 0;
++
+       switch (cmd) {
+       case KDGKBENT:
+               key_map = key_maps[s];
+@@ -276,6 +279,9 @@
+       char *first_free, *fj, *fnw;
+       int i, j, k;
++      if (!capable(CAP_SYS_TTY_CONFIG))
++              perm = 0;
++
+       /* we mostly copy too much here (512bytes), but who cares ;) */
+       if (copy_from_user(&tmp, user_kdgkb, sizeof(struct kbsentry)))
+               return -EFAULT;
+diff -urN linux-2.4.30/drivers/ide/ide-io.c linux-2.4.30-hf32.3/drivers/ide/ide-io.c
+--- linux-2.4.30/drivers/ide/ide-io.c  2003-11-28 19:26:20.000000000 +0100
++++ linux-2.4.30-hf32.3/drivers/ide/ide-io.c   2006-03-18 00:34:06.000000000 +0100
+@@ -899,11 +899,13 @@
+       rq = HWGROUP(drive)->rq;
+       HWGROUP(drive)->rq = NULL;
+-      rq->errors = 0;
+-      rq->sector = rq->bh->b_rsector;
+-      rq->current_nr_sectors = rq->bh->b_size >> 9;
+-      rq->hard_cur_sectors = rq->current_nr_sectors;
+-      rq->buffer = rq->bh->b_data;
++      if (rq) {
++              rq->errors = 0;
++              rq->sector = rq->bh->b_rsector;
++              rq->current_nr_sectors = rq->bh->b_size >> 9;
++              rq->hard_cur_sectors = rq->current_nr_sectors;
++              rq->buffer = rq->bh->b_data;
++      }
+       return ret;
+ }
+diff -urN linux-2.4.30/drivers/net/bonding/bond_alb.c linux-2.4.30-hf32.3/drivers/net/bonding/bond_alb.c
+--- linux-2.4.30/drivers/net/bonding/bond_alb.c        2004-04-14 15:05:30.000000000 +0200
++++ linux-2.4.30-hf32.3/drivers/net/bonding/bond_alb.c 2006-03-18 00:34:06.000000000 +0100
+@@ -37,6 +37,9 @@
+  *
+  * 2004/01/14 - Shmulik Hen <shmulik.hen at intel dot com>
+  *    - Add capability to tag self generated packets in ALB/TLB modes.
++ *
++ * 2005/12/02 - Michael O'Donnell <Michael.ODonnell at stratus dot com>
++ *    - Stratus88746: tlb_clear_slave() must tlb_init_slave() while locked.
+  */
+ //#define BONDING_DEBUG 1
+@@ -187,9 +190,9 @@
+               index = next_index;
+       }
+-      _unlock_tx_hashtbl(bond);
++      tlb_init_slave(slave); /* Stratus88746: do this before unlocking */
+-      tlb_init_slave(slave);
++      _unlock_tx_hashtbl(bond);
+ }
+ /* Must be called before starting the monitor timer */
+diff -urN linux-2.4.30/drivers/net/bonding/bond_main.c linux-2.4.30-hf32.3/drivers/net/bonding/bond_main.c
+--- linux-2.4.30/drivers/net/bonding/bond_main.c       2004-11-17 12:54:21.000000000 +0100
++++ linux-2.4.30-hf32.3/drivers/net/bonding/bond_main.c        2006-03-18 00:34:06.000000000 +0100
+@@ -469,6 +469,13 @@
+  *      * Add support for VLAN hardware acceleration capable slaves.
+  *      * Add capability to tag self generated packets in ALB/TLB modes.
+  *      Set version to 2.6.0.
++ * 2004/10/29 - Mitch Williams <mitch.a.williams at intel dot com>
++ *    - Fixed bug when unloading module while using 802.3ad.  If
++ *      spinlock debugging is turned on, this causes a stack dump.
++ *      Solution is to move call to dev_remove_pack outside of the
++ *      spinlock.
++ *      Set version to 2.6.1.
++ *
+  */
+ //#define BONDING_DEBUG 1
+@@ -3565,15 +3572,15 @@
+ {
+       struct bonding *bond = bond_dev->priv;
+-      write_lock_bh(&bond->lock);
+-
+-      bond_mc_list_destroy(bond);
+-
+       if (bond->params.mode == BOND_MODE_8023AD) {
+               /* Unregister the receive of LACPDUs */
+               bond_unregister_lacpdu(bond);
+       }
++      write_lock_bh(&bond->lock);
++
++      bond_mc_list_destroy(bond);
++
+       /* signal timers not to re-arm */
+       bond->kill_timers = 1;
+diff -urN linux-2.4.30/drivers/net/e1000/e1000_hw.c linux-2.4.30-hf32.3/drivers/net/e1000/e1000_hw.c
+--- linux-2.4.30/drivers/net/e1000/e1000_hw.c  2005-04-14 09:43:33.000000000 +0200
++++ linux-2.4.30-hf32.3/drivers/net/e1000/e1000_hw.c   2006-03-18 00:34:06.000000000 +0100
+@@ -5049,7 +5049,7 @@
+             if(ret_val)
+                 return ret_val;
+-            msec_delay(20);
++            msec_delay_irq(20);
+             ret_val = e1000_write_phy_reg(hw, 0x0000,
+                                           IGP01E1000_IEEE_FORCE_GIGA);
+@@ -5073,7 +5073,7 @@
+             if(ret_val)
+                 return ret_val;
+-            msec_delay(20);
++            msec_delay_irq(20);
+             /* Now enable the transmitter */
+             ret_val = e1000_write_phy_reg(hw, 0x2F5B, phy_saved_data);
+@@ -5098,7 +5098,7 @@
+             if(ret_val)
+                 return ret_val;
+-            msec_delay(20);
++            msec_delay_irq(20);
+             ret_val = e1000_write_phy_reg(hw, 0x0000,
+                                           IGP01E1000_IEEE_FORCE_GIGA);
+@@ -5114,7 +5114,7 @@
+             if(ret_val)
+                 return ret_val;
+-            msec_delay(20);
++            msec_delay_irq(20);
+             /* Now enable the transmitter */
+             ret_val = e1000_write_phy_reg(hw, 0x2F5B, phy_saved_data);
+diff -urN linux-2.4.30/drivers/net/wan/sdla.c linux-2.4.30-hf32.3/drivers/net/wan/sdla.c
+--- linux-2.4.30/drivers/net/wan/sdla.c        2005-01-27 18:57:32.000000000 +0100
++++ linux-2.4.30-hf32.3/drivers/net/wan/sdla.c 2006-03-18 00:34:06.000000000 +0100
+@@ -1201,6 +1201,7 @@
+               temp = kmalloc(mem.len, GFP_KERNEL);
+               if (!temp)
+                       return(-ENOMEM);
++              memset(temp, 0, mem.len);
+               sdla_read(dev, mem.addr, temp, mem.len);
+               if(copy_to_user(mem.data, temp, mem.len))
+               {
+diff -urN linux-2.4.30/drivers/net/wireless/airo.c linux-2.4.30-hf32.3/drivers/net/wireless/airo.c
+--- linux-2.4.30/drivers/net/wireless/airo.c   2004-08-08 01:26:05.000000000 +0200
++++ linux-2.4.30-hf32.3/drivers/net/wireless/airo.c    2006-03-18 00:34:06.000000000 +0100
+@@ -43,6 +43,8 @@
+ #include <linux/pci.h>
+ #include <asm/uaccess.h>
++#include "airo.h"
++
+ #ifdef CONFIG_PCI
+ static struct pci_device_id card_ids[] = {
+       { 0x14b9, 1, PCI_ANY_ID, PCI_ANY_ID, },
+diff -urN linux-2.4.30/drivers/net/wireless/airo.h linux-2.4.30-hf32.3/drivers/net/wireless/airo.h
+--- linux-2.4.30/drivers/net/wireless/airo.h   1970-01-01 01:00:00.000000000 +0100
++++ linux-2.4.30-hf32.3/drivers/net/wireless/airo.h    2006-03-18 00:34:06.000000000 +0100
+@@ -0,0 +1,8 @@
++#ifndef _AIRO_H_
++#define _AIRO_H_
++
++struct net_device *init_airo_card(unsigned short irq, int port, int is_pcmcia);
++void stop_airo_card(struct net_device *dev, int freeres);
++int reset_airo_card(struct net_device *dev);
++
++#endif  /*  _AIRO_H_  */
+diff -urN linux-2.4.30/drivers/net/wireless/airo_cs.c linux-2.4.30-hf32.3/drivers/net/wireless/airo_cs.c
+--- linux-2.4.30/drivers/net/wireless/airo_cs.c        2002-11-29 00:53:14.000000000 +0100
++++ linux-2.4.30-hf32.3/drivers/net/wireless/airo_cs.c 2006-03-18 00:34:06.000000000 +0100
+@@ -45,6 +45,8 @@
+ #include <pcmcia/cisreg.h>
+ #include <pcmcia/ds.h>
++#include "airo.h"
++
+ /*
+    All the PCMCIA modules use PCMCIA_DEBUG to control debugging.  If
+    you do not define PCMCIA_DEBUG at all, all the debug code will be
+@@ -91,10 +93,6 @@
+    event handler. 
+ */
+-struct net_device *init_airo_card( int, int, int );
+-void stop_airo_card( struct net_device *, int );
+-int reset_airo_card( struct net_device * );
+-
+ static void airo_config(dev_link_t *link);
+ static void airo_release(u_long arg);
+ static int airo_event(event_t event, int priority,
+diff -urN linux-2.4.30/drivers/net/wireless/hermes.c linux-2.4.30-hf32.3/drivers/net/wireless/hermes.c
+--- linux-2.4.30/drivers/net/wireless/hermes.c 2003-08-25 13:44:42.000000000 +0200
++++ linux-2.4.30-hf32.3/drivers/net/wireless/hermes.c  2006-03-18 00:34:06.000000000 +0100
+@@ -448,6 +448,43 @@
+       return err;
+ }
++/* Write a block of data to the chip's buffer with padding if
++ * neccessary, via the BAP. Synchronization/serialization is the
++ * caller's problem. len must be even.
++ *
++ * Returns: < 0 on internal failure (errno), 0 on success, > 0 on error from firmware
++ */
++int hermes_bap_pwrite_pad(hermes_t *hw, int bap, const void *buf, unsigned data_len, unsigned len,
++                    u16 id, u16 offset)
++{
++      int dreg = bap ? HERMES_DATA1 : HERMES_DATA0;
++      int err = 0;
++
++      if (len < 0 || len % 2 || data_len > len)
++              return -EINVAL;
++
++      err = hermes_bap_seek(hw, bap, id, offset);
++      if (err)
++              goto out;
++
++      /* Transfer all the complete words of data */
++      hermes_write_words(hw, dreg, buf, data_len/2);
++      /* If there is an odd byte left over pad and transfer it */
++      if (data_len & 1) {
++              u8 end[2];
++              end[1] = 0;
++              end[0] = ((unsigned char *)buf)[data_len - 1];
++              hermes_write_words(hw, dreg, end, 1);
++              data_len ++;
++      }
++      /* Now send zeros for the padding */
++      if (data_len < len)
++              hermes_clear_words(hw, dreg, (len - data_len) / 2);
++      /* Complete */
++ out:
++      return err;
++}
++
+ /* Read a Length-Type-Value record from the card.
+  *
+  * If length is NULL, we ignore the length read from the card, and
+@@ -534,6 +571,7 @@
+ EXPORT_SYMBOL(hermes_bap_pread);
+ EXPORT_SYMBOL(hermes_bap_pwrite);
++EXPORT_SYMBOL(hermes_bap_pwrite_pad);
+ EXPORT_SYMBOL(hermes_read_ltv);
+ EXPORT_SYMBOL(hermes_write_ltv);
+diff -urN linux-2.4.30/drivers/net/wireless/hermes.h linux-2.4.30-hf32.3/drivers/net/wireless/hermes.h
+--- linux-2.4.30/drivers/net/wireless/hermes.h 2006-01-29 08:47:28.000000000 +0100
++++ linux-2.4.30-hf32.3/drivers/net/wireless/hermes.h  2006-03-18 00:34:06.000000000 +0100
+@@ -319,6 +319,8 @@
+                      u16 id, u16 offset);
+ int hermes_bap_pwrite(hermes_t *hw, int bap, const void *buf, unsigned len,
+                       u16 id, u16 offset);
++int hermes_bap_pwrite_pad(hermes_t *hw, int bap, const void *buf,
++                      unsigned data_len, unsigned len, u16 id, u16 offset);
+ int hermes_read_ltv(hermes_t *hw, int bap, u16 rid, unsigned buflen,
+                   u16 *length, void *buf);
+ int hermes_write_ltv(hermes_t *hw, int bap, u16 rid,
+diff -urN linux-2.4.30/drivers/net/wireless/orinoco.c linux-2.4.30-hf32.3/drivers/net/wireless/orinoco.c
+--- linux-2.4.30/drivers/net/wireless/orinoco.c        2003-08-25 13:44:42.000000000 +0200
++++ linux-2.4.30-hf32.3/drivers/net/wireless/orinoco.c 2006-03-18 00:34:06.000000000 +0100
+@@ -2312,6 +2312,8 @@
+       }
+ }
++#define ALIGN(x,a) (((x)+(a)-1)&~((a)-1))
++
+ static int
+ orinoco_xmit(struct sk_buff *skb, struct net_device *dev)
+ {
+@@ -2407,14 +2409,22 @@
+                       stats->tx_errors++;
+                       goto fail;
+               }
++              /* Actual xfer length - allow for padding */
++              len = ALIGN(data_len, 2);
++              if (len < ETH_ZLEN - ETH_HLEN)
++                      len = ETH_ZLEN - ETH_HLEN;
+       } else { /* IEEE 802.3 frame */
+               data_len = len + ETH_HLEN;
+               data_off = HERMES_802_3_OFFSET;
+               p = skb->data;
++              /* Actual xfer length - round up for odd length packets */
++              len = ALIGN(data_len, 2);
++              if (len < ETH_ZLEN)
++                      len = ETH_ZLEN;
+       }
+-      /* Round up for odd length packets */
+-      err = hermes_bap_pwrite(hw, USER_BAP, p, RUP_EVEN(data_len), txfid, data_off);
++      err = hermes_bap_pwrite_pad(hw, USER_BAP, p, data_len, len,
++                              txfid, data_off);
+       if (err) {
+               printk(KERN_ERR "%s: Error %d writing packet to BAP\n",
+                      dev->name, err);
+diff -urN linux-2.4.30/drivers/scsi/sd.c linux-2.4.30-hf32.3/drivers/scsi/sd.c
+--- linux-2.4.30/drivers/scsi/sd.c     2005-04-14 09:43:34.000000000 +0200
++++ linux-2.4.30-hf32.3/drivers/scsi/sd.c      2006-03-18 00:34:06.000000000 +0100
+@@ -1472,6 +1472,7 @@
+               kfree(sd_sizes);
+               kfree(sd_blocksizes);
+               kfree(sd_hardsizes);
++              kfree(sd_max_sectors);
+               for (i = 0; i < N_USED_SD_MAJORS; i++) {
+                       kfree(sd_gendisks[i].de_arr);
+                       kfree(sd_gendisks[i].flags);
+@@ -1482,6 +1483,7 @@
+               del_gendisk(&sd_gendisks[i]);
+               blksize_size[SD_MAJOR(i)] = NULL;
+               hardsect_size[SD_MAJOR(i)] = NULL;
++              max_sectors[SD_MAJOR(i)] = NULL;
+               read_ahead[SD_MAJOR(i)] = 0;
+       }
+       sd_template.dev_max = 0;
+diff -urN linux-2.4.30/drivers/usb/serial/io_edgeport.c linux-2.4.30-hf32.3/drivers/usb/serial/io_edgeport.c
+--- linux-2.4.30/drivers/usb/serial/io_edgeport.c      2005-01-27 18:57:33.000000000 +0100
++++ linux-2.4.30-hf32.3/drivers/usb/serial/io_edgeport.c       2006-03-18 00:34:06.000000000 +0100
+@@ -2803,9 +2803,13 @@
+ static void unicode_to_ascii (char *string, short *unicode, int unicode_size)
+ {
+       int i;
+-      for (i = 0; i < unicode_size; ++i) {
++
++      if (unicode_size <= 0)
++              return;
++      
++      for (i = 0; i < unicode_size; ++i)
+               string[i] = (char)(le16_to_cpu(unicode[i]));
+-      }
++
+       string[unicode_size] = 0x00;
+ }
+diff -urN linux-2.4.30/fs/binfmt_elf.c linux-2.4.30-hf32.3/fs/binfmt_elf.c
+--- linux-2.4.30/fs/binfmt_elf.c       2005-04-14 09:43:34.000000000 +0200
++++ linux-2.4.30-hf32.3/fs/binfmt_elf.c        2006-03-18 00:34:06.000000000 +0100
+@@ -222,7 +222,7 @@
+       }
+       __put_user((elf_addr_t)argc,--sp);
+-      current->mm->arg_start = (unsigned long) p;
++      current->mm->arg_end = current->mm->arg_start = (unsigned long) p;
+       while (argc-->0) {
+               __put_user((elf_caddr_t)(unsigned long)p,argv++);
+               len = strnlen_user(p, PAGE_SIZE*MAX_ARG_PAGES);
+@@ -643,6 +643,11 @@
+               SET_PERSONALITY(elf_ex, ibcs2_interpreter);
+       }
++      if (BAD_ADDR(elf_ex.e_entry)) {
++              retval = -ENOEXEC;
++              goto out_free_dentry;
++      }
++
+       /* OK, we are done with that, now set up the arg stuff,
+          and then start this sucker up */
+@@ -820,7 +825,7 @@
+                       printk(KERN_ERR "Unable to load interpreter %.128s\n",
+                               elf_interpreter);
+                       force_sig(SIGSEGV, current);
+-                      retval = -ENOEXEC; /* Nobody gets to see this, but.. */
++                      retval = IS_ERR((void *)elf_entry) ? PTR_ERR((void *)elf_entry) : -ENOEXEC;
+                       goto out_free_dentry;
+               }
+               reloc_func_desc = interp_load_addr;
+@@ -1159,7 +1164,7 @@
+       /* first copy the parameters from user space */
+       memset(&psinfo, 0, sizeof(psinfo));
+       {
+-              int i, len;
++              unsigned int i, len;
+               len = current->mm->arg_end - current->mm->arg_start;
+               if (len >= ELF_PRARGSZ)
+diff -urN linux-2.4.30/fs/buffer.c linux-2.4.30-hf32.3/fs/buffer.c
+--- linux-2.4.30/fs/buffer.c   2004-11-17 12:54:21.000000000 +0100
++++ linux-2.4.30-hf32.3/fs/buffer.c    2006-03-18 00:34:06.000000000 +0100
+@@ -584,7 +584,7 @@
+       (*bhp)->b_prev_free->b_next_free = bh;
+       (*bhp)->b_prev_free = bh;
+       nr_buffers_type[blist]++;
+-      size_buffers_type[blist] += bh->b_size;
++      size_buffers_type[blist] += bh->b_size >> 9;
+ }
+ static void __remove_from_lru_list(struct buffer_head * bh)
+@@ -604,7 +604,7 @@
+               bh->b_next_free = NULL;
+               bh->b_prev_free = NULL;
+               nr_buffers_type[blist]--;
+-              size_buffers_type[blist] -= bh->b_size;
++              size_buffers_type[blist] -= bh->b_size >> 9;
+       }
+ }
+@@ -1033,7 +1033,7 @@
+ {
+       unsigned long dirty, tot, hard_dirty_limit, soft_dirty_limit;
+-      dirty = size_buffers_type[BUF_DIRTY] >> PAGE_SHIFT;
++      dirty = size_buffers_type[BUF_DIRTY] >> (PAGE_SHIFT - 9);
+       tot = nr_free_buffer_pages();
+       dirty *= 100;
+@@ -1054,7 +1054,7 @@
+ {
+       unsigned long dirty, tot, dirty_limit;
+-      dirty = size_buffers_type[BUF_DIRTY] >> PAGE_SHIFT;
++      dirty = size_buffers_type[BUF_DIRTY] >> (PAGE_SHIFT - 9);
+       tot = nr_free_buffer_pages();
+       dirty *= 100;
+@@ -2839,7 +2839,7 @@
+               }
+               printk("%9s: %d buffers, %lu kbyte, %d used (last=%d), "
+                      "%d locked, %d dirty, %d delay\n",
+-                     buf_types[nlist], found, size_buffers_type[nlist]>>10,
++                     buf_types[nlist], found, size_buffers_type[nlist]>>(10-9),
+                      used, lastused, locked, dirty, delalloc);
+       }
+       spin_unlock(&lru_list_lock);
+diff -urN linux-2.4.30/fs/dcache.c linux-2.4.30-hf32.3/fs/dcache.c
+--- linux-2.4.30/fs/dcache.c   2004-11-17 12:54:21.000000000 +0100
++++ linux-2.4.30-hf32.3/fs/dcache.c    2006-03-18 00:34:06.000000000 +0100
+@@ -221,7 +221,7 @@
+ static inline struct dentry * __dget_locked(struct dentry *dentry)
+ {
+       atomic_inc(&dentry->d_count);
+-      if (atomic_read(&dentry->d_count) == 1) {
++      if (!list_empty(&dentry->d_lru)) {
+               dentry_stat.nr_unused--;
+               list_del_init(&dentry->d_lru);
+       }
+diff -urN linux-2.4.30/fs/inode.c linux-2.4.30-hf32.3/fs/inode.c
+--- linux-2.4.30/fs/inode.c    2004-04-14 15:05:40.000000000 +0200
++++ linux-2.4.30-hf32.3/fs/inode.c     2006-03-18 00:34:06.000000000 +0100
+@@ -297,7 +297,7 @@
+ {
+       struct list_head *to;
+-      if (inode->i_state & I_FREEING)
++      if (inode->i_state & (I_FREEING|I_CLEAR))
+               return;
+       if (list_empty(&inode->i_hash))
+               return;
+@@ -634,7 +634,9 @@
+               cdput(inode->i_cdev);
+               inode->i_cdev = NULL;
+       }
++      spin_lock(&inode_lock);
+       inode->i_state = I_CLEAR;
++      spin_unlock(&inode_lock);
+ }
+ /*
+@@ -852,8 +854,8 @@
+        */
+       if (goal <= 0)
+               return;
+-      if (inodes_stat.nr_unused * sizeof(struct inode) * 10 <
+-                              freeable_lowmem() * PAGE_SIZE)
++      if (inodes_stat.nr_unused <
++          (freeable_lowmem() * PAGE_SIZE) / (sizeof(struct inode) * 10))
+               return;
+       wakeup_bdflush();
+diff -urN linux-2.4.30/fs/isofs/compress.c linux-2.4.30-hf32.3/fs/isofs/compress.c
+--- linux-2.4.30/fs/isofs/compress.c   2002-11-29 00:53:15.000000000 +0100
++++ linux-2.4.30-hf32.3/fs/isofs/compress.c    2006-03-18 00:34:06.000000000 +0100
+@@ -147,8 +147,14 @@
+       cend = le32_to_cpu(*(u32 *)(bh->b_data + (blockendptr & bufmask)));
+       brelse(bh);
++      if (cstart > cend)
++              goto eio;
++
+       csize = cend-cstart;
++      if (csize > deflateBound(1UL << zisofs_block_shift))
++              goto eio;
++
+       /* Now page[] contains an array of pages, any of which can be NULL,
+          and the locks on which we hold.  We should now read the data and
+          release the pages.  If the pages are NULL the decompressed data
+diff -urN linux-2.4.30/fs/isofs/inode.c linux-2.4.30-hf32.3/fs/isofs/inode.c
+--- linux-2.4.30/fs/isofs/inode.c      2005-04-14 09:43:34.000000000 +0200
++++ linux-2.4.30-hf32.3/fs/isofs/inode.c       2006-03-18 00:34:06.000000000 +0100
+@@ -335,16 +335,16 @@
+                       else if (!strcmp(value,"acorn")) popt->map = 'a';
+                       else return 0;
+               }
+-              if (!strcmp(this_char,"session") && value) {
++              else if (!strcmp(this_char,"session") && value) {
+                       char * vpnt = value;
+                       unsigned int ivalue = simple_strtoul(vpnt, &vpnt, 0);
+-                      if(ivalue < 0 || ivalue >99) return 0;
++                      if (ivalue > 99) return 0;
+                       popt->session=ivalue+1;
+               }
+-              if (!strcmp(this_char,"sbsector") && value) {
++              else if (!strcmp(this_char,"sbsector") && value) {
+                       char * vpnt = value;
+                       unsigned int ivalue = simple_strtoul(vpnt, &vpnt, 0);
+-                      if(ivalue < 0 || ivalue >660*512) return 0;
++                      if (ivalue > 660*512) return 0;
+                       popt->sbsector=ivalue;
+               }
+               else if (!strcmp(this_char,"check") && value) {
+diff -urN linux-2.4.30/fs/jfs/super.c linux-2.4.30-hf32.3/fs/jfs/super.c
+--- linux-2.4.30/fs/jfs/super.c        2005-04-14 09:43:34.000000000 +0200
++++ linux-2.4.30-hf32.3/fs/jfs/super.c 2006-03-18 00:34:06.000000000 +0100
+@@ -407,7 +407,7 @@
+               jfs_err("jfs_umount failed with return code %d", rc);
+       }
+ out_kfree:
+-      if (sbi->nls_tab)
++      if (sbi->nls_tab && sbi->nls_tab != (void *) -1)
+               unload_nls(sbi->nls_tab);
+       kfree(sbi);
+       return NULL;
+diff -urN linux-2.4.30/fs/locks.c linux-2.4.30-hf32.3/fs/locks.c
+--- linux-2.4.30/fs/locks.c    2004-04-14 15:05:40.000000000 +0200
++++ linux-2.4.30-hf32.3/fs/locks.c     2006-03-18 00:34:06.000000000 +0100
+@@ -1087,7 +1087,6 @@
+                       before = &fl->fl_next;
+                       continue;
+               }
+-              printk(KERN_INFO "lease broken - owner pid = %d\n", fl->fl_pid);
+               lease_modify(before, fl->fl_type & ~F_INPROGRESS);
+               if (fl == *before)      /* lease_modify may have freed fl */
+                       before = &fl->fl_next;
+diff -urN linux-2.4.30/fs/nfs/nfs2xdr.c linux-2.4.30-hf32.3/fs/nfs/nfs2xdr.c
+--- linux-2.4.30/fs/nfs/nfs2xdr.c      2002-11-29 00:53:15.000000000 +0100
++++ linux-2.4.30-hf32.3/fs/nfs/nfs2xdr.c       2006-03-18 00:34:06.000000000 +0100
+@@ -571,8 +571,11 @@
+       strlen = (u32*)kmap(rcvbuf->pages[0]);
+       /* Convert length of symlink */
+       len = ntohl(*strlen);
+-      if (len > rcvbuf->page_len)
+-              len = rcvbuf->page_len;
++      if (len >= rcvbuf->page_len - sizeof(u32) || len > NFS2_MAXPATHLEN) {
++              dprintk("NFS: server returned giant symlink!\n");
++              kunmap(rcvbuf->pages[0]);
++              return -ENAMETOOLONG;
++        }
+       *strlen = len;
+       /* NULL terminate the string we got */
+       string = (char *)(strlen + 1);
+diff -urN linux-2.4.30/fs/nfs/nfs3xdr.c linux-2.4.30-hf32.3/fs/nfs/nfs3xdr.c
+--- linux-2.4.30/fs/nfs/nfs3xdr.c      2003-11-28 19:26:21.000000000 +0100
++++ linux-2.4.30-hf32.3/fs/nfs/nfs3xdr.c       2006-03-18 00:34:06.000000000 +0100
+@@ -759,8 +759,11 @@
+       strlen = (u32*)kmap(rcvbuf->pages[0]);
+       /* Convert length of symlink */
+       len = ntohl(*strlen);
+-      if (len > rcvbuf->page_len)
+-              len = rcvbuf->page_len;
++      if (len >= rcvbuf->page_len - sizeof(u32)) {
++              dprintk("NFS: server returned giant symlink!\n");
++              kunmap(rcvbuf->pages[0]);
++              return -ENAMETOOLONG;
++        }
+       *strlen = len;
+       /* NULL terminate the string we got */
+       string = (char *)(strlen + 1);
+diff -urN linux-2.4.30/fs/proc/base.c linux-2.4.30-hf32.3/fs/proc/base.c
+--- linux-2.4.30/fs/proc/base.c        2005-01-27 18:57:33.000000000 +0100
++++ linux-2.4.30-hf32.3/fs/proc/base.c 2006-03-18 00:34:06.000000000 +0100
+@@ -185,8 +185,12 @@
+       int res = 0;
+       task_lock(task);
+       mm = task->mm;
+-      if (mm)
+-              atomic_inc(&mm->mm_users);
++      if (mm) {
++              if (mm->arg_end)
++                      atomic_inc(&mm->mm_users);
++              else
++                      mm = NULL;
++      }
+       task_unlock(task);
+       if (mm && mm->arg_start && mm->arg_start < mm->arg_end) {
+               unsigned long len = mm->arg_end - mm->arg_start;
+diff -urN linux-2.4.30/fs/smbfs/proc.c linux-2.4.30-hf32.3/fs/smbfs/proc.c
+--- linux-2.4.30/fs/smbfs/proc.c       2004-11-17 12:54:21.000000000 +0100
++++ linux-2.4.30-hf32.3/fs/smbfs/proc.c        2006-03-18 00:34:06.000000000 +0100
+@@ -2945,7 +2945,7 @@
+       LSET(data, 32, SMB_TIME_NO_CHANGE);
+       LSET(data, 40, SMB_UID_NO_CHANGE);
+       LSET(data, 48, SMB_GID_NO_CHANGE);
+-      LSET(data, 56, smb_filetype_from_mode(attr->ia_mode));
++      DSET(data, 56, smb_filetype_from_mode(attr->ia_mode));
+       LSET(data, 60, major);
+       LSET(data, 68, minor);
+       LSET(data, 76, 0);
+diff -urN linux-2.4.30/fs/xfs/linux-2.4/xfs_buf.c linux-2.4.30-hf32.3/fs/xfs/linux-2.4/xfs_buf.c
+--- linux-2.4.30/fs/xfs/linux-2.4/xfs_buf.c    2005-01-27 18:57:33.000000000 +0100
++++ linux-2.4.30-hf32.3/fs/xfs/linux-2.4/xfs_buf.c     2006-03-18 00:34:06.000000000 +0100
+@@ -1073,7 +1073,7 @@
+       return(locked ? 0 : -EBUSY);
+ }
+-#ifdef DEBUG
++#if defined(DEBUG) || defined(XFS_BLI_TRACE)
+ /*
+  *    pagebuf_lock_value
+  *
+diff -urN linux-2.4.30/include/asm-i386/system.h linux-2.4.30-hf32.3/include/asm-i386/system.h
+--- linux-2.4.30/include/asm-i386/system.h     2005-03-26 10:13:13.000000000 +0100
++++ linux-2.4.30-hf32.3/include/asm-i386/system.h      2006-03-18 00:34:06.000000000 +0100
+@@ -84,7 +84,7 @@
+ #define loadsegment(seg,value)                        \
+       asm volatile("\n"                       \
+               "1:\t"                          \
+-              "movl %0,%%" #seg "\n"          \
++              "mov %0,%%" #seg "\n"           \
+               "2:\n"                          \
+               ".section .fixup,\"ax\"\n"      \
+               "3:\t"                          \
+@@ -96,7 +96,7 @@
+               ".align 4\n\t"                  \
+               ".long 1b,3b\n"                 \
+               ".previous"                     \
+-              : :"m" (*(unsigned int *)&(value)))
++              : :"m" (value))
+ /*
+  * Clear and set 'TS' bit respectively
+diff -urN linux-2.4.30/include/asm-x86_64/desc.h linux-2.4.30-hf32.3/include/asm-x86_64/desc.h
+--- linux-2.4.30/include/asm-x86_64/desc.h     2004-08-08 01:26:06.000000000 +0200
++++ linux-2.4.30-hf32.3/include/asm-x86_64/desc.h      2006-03-18 00:34:06.000000000 +0100
+@@ -128,7 +128,7 @@
+ static inline void set_tss_desc(unsigned n, void *addr)
+ { 
+-      set_tssldt_descriptor((void *)&gdt_table + __CPU_DESC_INDEX(n,tss), (unsigned long)addr, DESC_TSS, sizeof(struct tss_struct)); 
++      set_tssldt_descriptor((void *)&gdt_table + __CPU_DESC_INDEX(n,tss), (unsigned long)addr, DESC_TSS, IO_BITMAP_OFFSET + IO_BITMAP_BYTES + 7); 
+ } 
+ static inline void set_ldt_desc(unsigned n, void *addr, int size)
+diff -urN linux-2.4.30/include/asm-x86_64/processor.h linux-2.4.30-hf32.3/include/asm-x86_64/processor.h
+--- linux-2.4.30/include/asm-x86_64/processor.h        2004-04-14 15:05:40.000000000 +0200
++++ linux-2.4.30-hf32.3/include/asm-x86_64/processor.h 2006-03-18 00:34:06.000000000 +0100
+@@ -260,6 +260,7 @@
+  * Size of io_bitmap in longwords: 32 is ports 0-0x3ff.
+  */
+ #define IO_BITMAP_SIZE        32
++#define IO_BITMAP_BYTES (IO_BITMAP_SIZE * sizeof(u32))
+ #define IO_BITMAP_OFFSET offsetof(struct tss_struct,io_bitmap)
+ #define INVALID_IO_BITMAP_OFFSET 0x8000
+@@ -325,10 +326,9 @@
+ #define INIT_MMAP \
+ { &init_mm, 0, 0, NULL, PAGE_SHARED, VM_READ | VM_WRITE | VM_EXEC, 1, NULL, NULL }
+-#define STACKFAULT_STACK 1
+-#define DOUBLEFAULT_STACK 2 
+-#define NMI_STACK 3 
+-#define N_EXCEPTION_STACKS 3  /* hw limit: 7 */
++#define DOUBLEFAULT_STACK 1
++#define NMI_STACK 2
++#define N_EXCEPTION_STACKS 2  /* hw limit: 7 */
+ #define EXCEPTION_STKSZ PAGE_SIZE
+ #define EXCEPTION_STK_ORDER 0
+diff -urN linux-2.4.30/include/linux/delay.h linux-2.4.30-hf32.3/include/linux/delay.h
+--- linux-2.4.30/include/linux/delay.h 2005-11-18 12:45:36.000000000 +0100
++++ linux-2.4.30-hf32.3/include/linux/delay.h  2006-03-18 00:34:06.000000000 +0100
+@@ -14,6 +14,24 @@
+ #include <asm/delay.h>
+ /*
++ * We define MAX_MSEC_OFFSET as the maximal value that can be accepted by
++ * msecs_to_jiffies() without risking a multiply overflow. This function
++ * returns MAX_JIFFY_OFFSET for arguments above those values.
++ */
++
++#if HZ <= 1000 && !(1000 % HZ)
++#  define MAX_MSEC_OFFSET \
++      (ULONG_MAX - (1000 / HZ) + 1)
++#elif HZ > 1000 && !(HZ % 1000)
++#  define MAX_MSEC_OFFSET \
++      (ULONG_MAX / (HZ / 1000))
++#else
++#  define MAX_MSEC_OFFSET \
++      ((ULONG_MAX - 999) / HZ)
++#endif
++
++
++/*
+  * Convert jiffies to milliseconds and back.
+  *
+  * Avoid unnecessary multiplications/divisions in the
+@@ -43,14 +61,14 @@
+ static inline unsigned long msecs_to_jiffies(const unsigned int m)
+ {
+-      if (m > jiffies_to_msecs(MAX_JIFFY_OFFSET))
++      if (MAX_MSEC_OFFSET < UINT_MAX && m > (unsigned int)MAX_MSEC_OFFSET)
+               return MAX_JIFFY_OFFSET;
+ #if HZ <= 1000 && !(1000 % HZ)
+-      return (m + (1000 / HZ) - 1) / (1000 / HZ);
++      return ((unsigned long)m + (1000 / HZ) - 1) / (1000 / HZ);
+ #elif HZ > 1000 && !(HZ % 1000)
+-      return m * (HZ / 1000);
++      return (unsigned long)m * (HZ / 1000);
+ #else
+-      return (m * HZ + 999) / 1000;
++      return ((unsigned long)m * HZ + 999) / 1000;
+ #endif
+ }
+diff -urN linux-2.4.30/include/linux/netfilter_ipv4/ip_conntrack.h linux-2.4.30-hf32.3/include/linux/netfilter_ipv4/ip_conntrack.h
+--- linux-2.4.30/include/linux/netfilter_ipv4/ip_conntrack.h   2005-07-27 13:13:58.000000000 +0200
++++ linux-2.4.30-hf32.3/include/linux/netfilter_ipv4/ip_conntrack.h    2006-03-18 00:34:06.000000000 +0100
+@@ -229,7 +229,7 @@
+ ip_conntrack_get(struct sk_buff *skb, enum ip_conntrack_info *ctinfo);
+ /* decrement reference count on a conntrack */
+-extern inline void ip_conntrack_put(struct ip_conntrack *ct);
++extern void ip_conntrack_put(struct ip_conntrack *ct);
+ /* find unconfirmed expectation based on tuple */
+ struct ip_conntrack_expect *
+diff -urN linux-2.4.30/include/linux/netfilter_ipv4/ip_nat_rule.h linux-2.4.30-hf32.3/include/linux/netfilter_ipv4/ip_nat_rule.h
+--- linux-2.4.30/include/linux/netfilter_ipv4/ip_nat_rule.h    2006-01-29 08:38:54.000000000 +0100
++++ linux-2.4.30-hf32.3/include/linux/netfilter_ipv4/ip_nat_rule.h     2006-03-18 00:34:06.000000000 +0100
+@@ -19,5 +19,10 @@
+ alloc_null_binding(struct ip_conntrack *conntrack,
+                  struct ip_nat_info *info,
+                  unsigned int hooknum);
++
++extern unsigned int
++alloc_null_binding_confirmed(struct ip_conntrack *conntrack,
++                           struct ip_nat_info *info,
++                           unsigned int hooknum);
+ #endif
+ #endif /* _IP_NAT_RULE_H */
+diff -urN linux-2.4.30/include/linux/proc_fs.h linux-2.4.30-hf32.3/include/linux/proc_fs.h
+--- linux-2.4.30/include/linux/proc_fs.h       2005-12-04 19:00:23.000000000 +0100
++++ linux-2.4.30-hf32.3/include/linux/proc_fs.h        2006-03-18 00:34:06.000000000 +0100
+@@ -70,6 +70,7 @@
+       atomic_t count;         /* use count */
+       int deleted;            /* delete flag */
+       kdev_t  rdev;
++      void *set;
+ };
+ #define PROC_INODE_PROPER(inode) ((inode)->i_ino & ~0xffff)
+diff -urN linux-2.4.30/include/linux/sysctl.h linux-2.4.30-hf32.3/include/linux/sysctl.h
+--- linux-2.4.30/include/linux/sysctl.h        2005-11-02 10:29:31.000000000 +0100
++++ linux-2.4.30-hf32.3/include/linux/sysctl.h 2006-03-18 00:34:06.000000000 +0100
+@@ -29,6 +29,7 @@
+ #include <linux/list.h>
+ struct file;
++struct completion;
+ #define CTL_MAXNAME 10
+@@ -829,6 +830,8 @@
+ {
+       ctl_table *ctl_table;
+       struct list_head ctl_entry;
++      int used;
++      struct completion *unregistering;
+ };
+ struct ctl_table_header * register_sysctl_table(ctl_table * table, 
+diff -urN linux-2.4.30/include/linux/zlib.h linux-2.4.30-hf32.3/include/linux/zlib.h
+--- linux-2.4.30/include/linux/zlib.h  2005-11-18 12:46:17.000000000 +0100
++++ linux-2.4.30-hf32.3/include/linux/zlib.h   2006-03-18 00:34:06.000000000 +0100
+@@ -516,6 +516,11 @@
+    stream state was inconsistent (such as zalloc or state being NULL).
+ */
++static inline unsigned long deflateBound(unsigned long s)
++{
++      return s + ((s + 7) >> 3) + ((s + 63) >> 6) + 11;
++}
++
+ ZEXTERN int ZEXPORT zlib_deflateParams OF((z_streamp strm,
+                                             int level,
+                                             int strategy));
+diff -urN linux-2.4.30/include/net/ax25.h linux-2.4.30-hf32.3/include/net/ax25.h
+--- linux-2.4.30/include/net/ax25.h    2005-11-18 12:45:59.000000000 +0100
++++ linux-2.4.30-hf32.3/include/net/ax25.h     2006-03-18 00:34:06.000000000 +0100
+@@ -142,7 +142,7 @@
+       ax25_address            calls[AX25_MAX_DIGIS];
+       unsigned char           repeated[AX25_MAX_DIGIS];
+       unsigned char           ndigi;
+-      char                    lastrepeat;
++      signed char             lastrepeat;
+ } ax25_digi;
+ typedef struct ax25_route {
+diff -urN linux-2.4.30/include/net/ip6_fib.h linux-2.4.30-hf32.3/include/net/ip6_fib.h
+--- linux-2.4.30/include/net/ip6_fib.h 2005-09-01 16:18:27.000000000 +0200
++++ linux-2.4.30-hf32.3/include/net/ip6_fib.h  2006-03-18 00:34:06.000000000 +0100
+@@ -171,13 +171,16 @@
+ extern int                    fib6_add(struct fib6_node *root,
+                                        struct rt6_info *rt,
+-                                       struct nlmsghdr *nlh);
++                                       struct nlmsghdr *nlh,
++                                       struct netlink_skb_parms *req);
+ extern int                    fib6_del(struct rt6_info *rt,
+-                                       struct nlmsghdr *nlh);
++                                       struct nlmsghdr *nlh,
++                                       struct netlink_skb_parms *req);
+ extern void                   inet6_rt_notify(int event, struct rt6_info *rt,
+-                                              struct nlmsghdr *nlh);
++                                              struct nlmsghdr *nlh,
++                                              struct netlink_skb_parms *req);
+ extern void                   fib6_run_gc(unsigned long dummy);
+diff -urN linux-2.4.30/include/net/ip6_route.h linux-2.4.30-hf32.3/include/net/ip6_route.h
+--- linux-2.4.30/include/net/ip6_route.h       2005-09-01 16:18:27.000000000 +0200
++++ linux-2.4.30-hf32.3/include/net/ip6_route.h        2006-03-18 00:34:06.000000000 +0100
+@@ -39,9 +39,11 @@
+ extern int                    ipv6_route_ioctl(unsigned int cmd, void *arg);
+ extern int                    ip6_route_add(struct in6_rtmsg *rtmsg,
+-                                            struct nlmsghdr *);
++                                            struct nlmsghdr *,
++                                            struct netlink_skb_parms *req);
+ extern int                    ip6_del_rt(struct rt6_info *,
+-                                         struct nlmsghdr *);
++                                         struct nlmsghdr *,
++                                         struct netlink_skb_parms *req);
+ extern int                    ip6_rt_addr_add(struct in6_addr *addr,
+                                               struct net_device *dev);
+diff -urN linux-2.4.30/include/net/ip_vs.h linux-2.4.30-hf32.3/include/net/ip_vs.h
+--- linux-2.4.30/include/net/ip_vs.h   2005-09-01 16:18:30.000000000 +0200
++++ linux-2.4.30-hf32.3/include/net/ip_vs.h    2006-03-18 00:34:06.000000000 +0100
+@@ -82,6 +82,7 @@
+ #define IP_VS_CONN_F_IN_SEQ           0x0400    /* must do input seq adjust */
+ #define IP_VS_CONN_F_SEQ_MASK         0x0600    /* in/out sequence mask */
+ #define IP_VS_CONN_F_NO_CPORT         0x0800    /* no client port set yet */
++#define IP_VS_CONN_F_TEMPLATE         0x1000    /* template, not connection */
+ /* Move it to better place one day, for now keep it unique */
+ #define NFC_IPVS_PROPERTY     0x10000
+@@ -592,6 +593,8 @@
+ extern struct ip_vs_conn *ip_vs_conn_in_get
+ (int protocol, __u32 s_addr, __u16 s_port, __u32 d_addr, __u16 d_port);
++extern struct ip_vs_conn *ip_vs_ct_in_get
++(int protocol, __u32 s_addr, __u16 s_port, __u32 d_addr, __u16 d_port);
+ extern struct ip_vs_conn *ip_vs_conn_out_get
+ (int protocol, __u32 s_addr, __u16 s_port, __u32 d_addr, __u16 d_port);
+diff -urN linux-2.4.30/kernel/kmod.c linux-2.4.30-hf32.3/kernel/kmod.c
+--- linux-2.4.30/kernel/kmod.c 2003-11-28 19:26:21.000000000 +0100
++++ linux-2.4.30-hf32.3/kernel/kmod.c  2006-03-18 00:34:06.000000000 +0100
+@@ -125,6 +125,8 @@
+       curtask->euid = curtask->uid = curtask->suid = curtask->fsuid = 0;
+       curtask->egid = curtask->gid = curtask->sgid = curtask->fsgid = 0;
++      memcpy(&curtask->rlim, &init_task.rlim, sizeof(struct rlimit)*RLIM_NLIMITS);
++
+       curtask->ngroups = 0;
+       cap_set_full(curtask->cap_effective);
+diff -urN linux-2.4.30/kernel/ptrace.c linux-2.4.30-hf32.3/kernel/ptrace.c
+--- linux-2.4.30/kernel/ptrace.c       2003-08-25 13:44:44.000000000 +0200
++++ linux-2.4.30-hf32.3/kernel/ptrace.c        2006-03-18 00:34:06.000000000 +0100
+@@ -58,7 +58,7 @@
+       task_lock(task);
+       if (task->pid <= 1)
+               goto bad;
+-      if (task == current)
++      if (task->tgid == current->tgid)
+               goto bad;
+       if (!task->mm)
+               goto bad;
+diff -urN linux-2.4.30/kernel/sysctl.c linux-2.4.30-hf32.3/kernel/sysctl.c
+--- linux-2.4.30/kernel/sysctl.c       2005-01-27 18:57:34.000000000 +0100
++++ linux-2.4.30-hf32.3/kernel/sysctl.c        2006-03-18 00:34:06.000000000 +0100
+@@ -147,7 +147,7 @@
+ extern struct proc_dir_entry *proc_sys_root;
+-static void register_proc_table(ctl_table *, struct proc_dir_entry *);
++static void register_proc_table(ctl_table *, struct proc_dir_entry *, void *);
+ static void unregister_proc_table(ctl_table *, struct proc_dir_entry *);
+ #endif
+@@ -360,10 +360,51 @@
+ extern void init_irq_proc (void);
++static spinlock_t sysctl_lock = SPIN_LOCK_UNLOCKED;
++
++/* called under sysctl_lock */
++static int use_table(struct ctl_table_header *p)
++{
++      if (unlikely(p->unregistering != NULL))
++              return 0;
++      p->used++;
++      return 1;
++}
++
++/* called under sysctl_lock */
++static void unuse_table(struct ctl_table_header *p)
++{
++      if (!--p->used)
++              if (unlikely(p->unregistering != NULL))
++                      complete(p->unregistering);
++}
++
++/* called under sysctl_lock, will reacquire if has to wait */
++static void start_unregistering(struct ctl_table_header *p)
++{
++      /*
++       * if p->used is 0, nobody will ever touch that entry again;
++       * we'll eliminate all paths to it before dropping sysctl_lock
++       */
++      if (unlikely(p->used)) {
++              struct completion wait;
++              init_completion(&wait);
++              p->unregistering = &wait;
++              spin_unlock(&sysctl_lock);
++              wait_for_completion(&wait);
++              spin_lock(&sysctl_lock);
++      }
++      /*
++       * do not remove from the list until nobody holds it; walking the
++       * list in do_sysctl() relies on that.
++       */
++      list_del_init(&p->ctl_entry);
++}
++
+ void __init sysctl_init(void)
+ {
+ #ifdef CONFIG_PROC_FS
+-      register_proc_table(root_table, proc_sys_root);
++      register_proc_table(root_table, proc_sys_root, &root_table_header);
+       init_irq_proc();
+ #endif
+ }
+@@ -372,6 +413,7 @@
+              void *newval, size_t newlen)
+ {
+       struct list_head *tmp;
++      int error = -ENOTDIR;
+       if (nlen <= 0 || nlen >= CTL_MAXNAME)
+               return -ENOTDIR;
+@@ -383,21 +425,31 @@
+               if ((ssize_t)old_len < 0)
+                       return -EINVAL;
+       }
++      spin_lock(&sysctl_lock);
+       tmp = &root_table_header.ctl_entry;
+       do {
+               struct ctl_table_header *head =
+                       list_entry(tmp, struct ctl_table_header, ctl_entry);
+               void *context = NULL;
+-              int error = parse_table(name, nlen, oldval, oldlenp, 
++
++              if (!use_table(head))
++                      continue;
++
++              spin_unlock(&sysctl_lock);
++
++              error = parse_table(name, nlen, oldval, oldlenp, 
+                                       newval, newlen, head->ctl_table,
+                                       &context);
+               if (context)
+                       kfree(context);
++
++              spin_lock(&sysctl_lock);
++              unuse_table(head);
+               if (error != -ENOTDIR)
+-                      return error;
+-              tmp = tmp->next;
+-      } while (tmp != &root_table_header.ctl_entry);
+-      return -ENOTDIR;
++                      break;
++      } while ((tmp = tmp->next) != &root_table_header.ctl_entry);
++      spin_unlock(&sysctl_lock);
++      return error;
+ }
+ extern asmlinkage long sys_sysctl(struct __sysctl_args *args)
+@@ -604,12 +656,16 @@
+               return NULL;
+       tmp->ctl_table = table;
+       INIT_LIST_HEAD(&tmp->ctl_entry);
++      tmp->used = 0;
++      tmp->unregistering = NULL;
++      spin_lock(&sysctl_lock);
+       if (insert_at_head)
+               list_add(&tmp->ctl_entry, &root_table_header.ctl_entry);
+       else
+               list_add_tail(&tmp->ctl_entry, &root_table_header.ctl_entry);
++      spin_unlock(&sysctl_lock);
+ #ifdef CONFIG_PROC_FS
+-      register_proc_table(table, proc_sys_root);
++      register_proc_table(table, proc_sys_root, tmp);
+ #endif
+       return tmp;
+ }
+@@ -623,10 +679,12 @@
+  */
+ void unregister_sysctl_table(struct ctl_table_header * header)
+ {
+-      list_del(&header->ctl_entry);
++      spin_lock(&sysctl_lock);
++      start_unregistering(header);
+ #ifdef CONFIG_PROC_FS
+       unregister_proc_table(header->ctl_table, proc_sys_root);
+ #endif
++      spin_unlock(&sysctl_lock);
+       kfree(header);
+ }
+@@ -637,7 +695,7 @@
+ #ifdef CONFIG_PROC_FS
+ /* Scan the sysctl entries in table and add them all into /proc */
+-static void register_proc_table(ctl_table * table, struct proc_dir_entry *root)
++static void register_proc_table(ctl_table * table, struct proc_dir_entry *root, void *set)
+ {
+       struct proc_dir_entry *de;
+       int len;
+@@ -673,6 +731,7 @@
+                       de = create_proc_entry(table->procname, mode, root);
+                       if (!de)
+                               continue;
++                      de->set = set;
+                       de->data = (void *) table;
+                       if (table->proc_handler) {
+                               de->proc_fops = &proc_sys_file_operations;
+@@ -681,7 +740,7 @@
+               }
+               table->de = de;
+               if (de->mode & S_IFDIR)
+-                      register_proc_table(table->child, de);
++                      register_proc_table(table->child, de, set);
+       }
+ }
+@@ -706,6 +765,13 @@
+                               continue;
+               }
++              /*
++               * In any case, mark the entry as goner; we'll keep it
++               * around if it's busy, but we'll know to do nothing with
++               * its fields.  We are under sysctl_lock here.
++               */
++              de->data = NULL;
++
+               /* Don't unregister proc entries that are still being used.. */
+               if (atomic_read(&de->count))
+                       continue;
+@@ -719,31 +785,44 @@
+                         size_t count, loff_t *ppos)
+ {
+       int op;
+-      struct proc_dir_entry *de;
++      struct proc_dir_entry *de =
++        (struct proc_dir_entry*) file->f_dentry->d_inode->u.generic_ip;
+       struct ctl_table *table;
+       size_t res;
+-      ssize_t error;
+-      
+-      de = (struct proc_dir_entry*) file->f_dentry->d_inode->u.generic_ip;
+-      if (!de || !de->data)
+-              return -ENOTDIR;
+-      table = (struct ctl_table *) de->data;
+-      if (!table || !table->proc_handler)
+-              return -ENOTDIR;
+-      op = (write ? 002 : 004);
+-      if (ctl_perm(table, op))
+-              return -EPERM;
+-      
+-      res = count;
++      ssize_t error = -ENOTDIR;
+-      /*
+-       * FIXME: we need to pass on ppos to the handler.
+-       */
++      spin_lock(&sysctl_lock);
++      if (de && de->data && use_table(de->set)) {
++              /*
++               * at that point we know that sysctl was not unregistered
++               * and won't be until we finish
++               */
++              spin_unlock(&sysctl_lock);
++              table = (struct ctl_table *) de->data;
++              if (!table || !table->proc_handler)
++                      goto out;
++              error = -EPERM;
++              op = (write ? 002 : 004);
++              if (ctl_perm(table, op))
++                      goto out;
++              
++              /* careful: calling conventions are nasty here */
++              res = count;
+-      error = (*table->proc_handler) (table, write, file, buf, &res);
+-      if (error)
+-              return error;
+-      return res;
++              /*
++               * FIXME: we need to pass on ppos to the handler.
++               */
++
++              error = (*table->proc_handler)(table, write, file,
++                                              buf, &res);
++              if (!error)
++                      error = res;
++      out:
++              spin_lock(&sysctl_lock);
++              unuse_table(de->set);
++      }
++      spin_unlock(&sysctl_lock);
++      return error;
+ }
+ static ssize_t proc_readsys(struct file * file, char * buf,
+diff -urN linux-2.4.30/lib/inflate.c linux-2.4.30-hf32.3/lib/inflate.c
+--- linux-2.4.30/lib/inflate.c 2002-11-29 00:53:15.000000000 +0100
++++ linux-2.4.30-hf32.3/lib/inflate.c  2006-03-18 00:34:06.000000000 +0100
+@@ -320,7 +320,7 @@
+   {
+     *t = (struct huft *)NULL;
+     *m = 0;
+-    return 0;
++    return 2;
+   }
+ DEBG("huft2 ");
+@@ -368,6 +368,7 @@
+     if ((j = *p++) != 0)
+       v[x[j]++] = i;
+   } while (++i < n);
++  n = x[g];                   /* set n to length of v */
+ DEBG("h6 ");
+@@ -404,12 +405,13 @@
+ DEBG1("2 ");
+           f -= a + 1;           /* deduct codes from patterns left */
+           xp = c + k;
+-          while (++j < z)       /* try smaller tables up to z bits */
+-          {
+-            if ((f <<= 1) <= *++xp)
+-              break;            /* enough codes to use up j bits */
+-            f -= *xp;           /* else deduct codes from patterns */
+-          }
++          if (j < z)
++            while (++j < z)       /* try smaller tables up to z bits */
++            {
++              if ((f <<= 1) <= *++xp)
++                break;            /* enough codes to use up j bits */
++              f -= *xp;           /* else deduct codes from patterns */
++            }
+         }
+ DEBG1("3 ");
+         z = 1 << j;             /* table entries for j-bit table */
+diff -urN linux-2.4.30/lib/rbtree.c linux-2.4.30-hf32.3/lib/rbtree.c
+--- linux-2.4.30/lib/rbtree.c  2004-11-17 12:54:22.000000000 +0100
++++ linux-2.4.30-hf32.3/lib/rbtree.c   2006-03-18 00:34:06.000000000 +0100
+@@ -332,6 +332,7 @@
+               node = node->rb_right;
+               while (node->rb_left)
+                       node = node->rb_left;
++              return node;
+       }
+       /* No right-hand children.  Everything down and left is
+@@ -355,6 +356,7 @@
+               node = node->rb_left;
+               while (node->rb_right)
+                       node = node->rb_right;   
++              return node;
+       }
+       /* No left-hand children. Go up till we find an ancestor which
+diff -urN linux-2.4.30/lib/rwsem-spinlock.c linux-2.4.30-hf32.3/lib/rwsem-spinlock.c
+--- linux-2.4.30/lib/rwsem-spinlock.c  2005-01-27 18:57:34.000000000 +0100
++++ linux-2.4.30-hf32.3/lib/rwsem-spinlock.c   2006-03-18 00:34:06.000000000 +0100
+@@ -127,12 +127,12 @@
+       rwsemtrace(sem,"Entering __down_read");
+-      spin_lock(&sem->wait_lock);
++      spin_lock_irq(&sem->wait_lock);
+       if (sem->activity>=0 && list_empty(&sem->wait_list)) {
+               /* granted */
+               sem->activity++;
+-              spin_unlock(&sem->wait_lock);
++              spin_unlock_irq(&sem->wait_lock);
+               goto out;
+       }
+@@ -147,7 +147,7 @@
+       list_add_tail(&waiter.list,&sem->wait_list);
+       /* we don't need to touch the semaphore struct anymore */
+-      spin_unlock(&sem->wait_lock);
++      spin_unlock_irq(&sem->wait_lock);
+       /* wait to be given the lock */
+       for (;;) {
+@@ -169,9 +169,10 @@
+ int fastcall __down_read_trylock(struct rw_semaphore *sem)
+ {
+       int ret = 0;
++      unsigned long flags;
+       rwsemtrace(sem,"Entering __down_read_trylock");
+-      spin_lock(&sem->wait_lock);
++      spin_lock_irqsave(&sem->wait_lock, flags);
+       if (sem->activity>=0 && list_empty(&sem->wait_list)) {
+               /* granted */
+@@ -179,7 +180,7 @@
+               ret = 1;
+       }
+-      spin_unlock(&sem->wait_lock);
++      spin_unlock_irqrestore(&sem->wait_lock, flags);
+       rwsemtrace(sem,"Leaving __down_read_trylock");
+       return ret;
+@@ -196,12 +197,12 @@
+       rwsemtrace(sem,"Entering __down_write");
+-      spin_lock(&sem->wait_lock);
++      spin_lock_irq(&sem->wait_lock);
+       if (sem->activity==0 && list_empty(&sem->wait_list)) {
+               /* granted */
+               sem->activity = -1;
+-              spin_unlock(&sem->wait_lock);
++              spin_unlock_irq(&sem->wait_lock);
+               goto out;
+       }
+@@ -216,7 +217,7 @@
+       list_add_tail(&waiter.list,&sem->wait_list);
+       /* we don't need to touch the semaphore struct anymore */
+-      spin_unlock(&sem->wait_lock);
++      spin_unlock_irq(&sem->wait_lock);
+       /* wait to be given the lock */
+       for (;;) {
+@@ -238,9 +239,10 @@
+ int fastcall __down_write_trylock(struct rw_semaphore *sem)
+ {
+       int ret = 0;
++      unsigned long flags;
+       rwsemtrace(sem,"Entering __down_write_trylock");
+-      spin_lock(&sem->wait_lock);
++      spin_lock_irqsave(&sem->wait_lock, flags);
+       if (sem->activity==0 && list_empty(&sem->wait_list)) {
+               /* granted */
+@@ -248,7 +250,7 @@
+               ret = 1;
+       }
+-      spin_unlock(&sem->wait_lock);
++      spin_unlock_irqrestore(&sem->wait_lock, flags);
+       rwsemtrace(sem,"Leaving __down_write_trylock");
+       return ret;
+@@ -259,14 +261,15 @@
+  */
+ void fastcall __up_read(struct rw_semaphore *sem)
+ {
++      unsigned long flags;
+       rwsemtrace(sem,"Entering __up_read");
+-      spin_lock(&sem->wait_lock);
++      spin_lock_irqsave(&sem->wait_lock, flags);
+       if (--sem->activity==0 && !list_empty(&sem->wait_list))
+               sem = __rwsem_wake_one_writer(sem);
+-      spin_unlock(&sem->wait_lock);
++      spin_unlock_irqrestore(&sem->wait_lock, flags);
+       rwsemtrace(sem,"Leaving __up_read");
+ }
+@@ -276,15 +279,16 @@
+  */
+ void fastcall __up_write(struct rw_semaphore *sem)
+ {
++      unsigned long flags;
+       rwsemtrace(sem,"Entering __up_write");
+-      spin_lock(&sem->wait_lock);
++      spin_lock_irqsave(&sem->wait_lock, flags);
+       sem->activity = 0;
+       if (!list_empty(&sem->wait_list))
+               sem = __rwsem_do_wake(sem);
+-      spin_unlock(&sem->wait_lock);
++      spin_unlock_irqrestore(&sem->wait_lock, flags);
+       rwsemtrace(sem,"Leaving __up_write");
+ }
+diff -urN linux-2.4.30/lib/rwsem.c linux-2.4.30-hf32.3/lib/rwsem.c
+--- linux-2.4.30/lib/rwsem.c   2004-11-17 12:54:22.000000000 +0100
++++ linux-2.4.30-hf32.3/lib/rwsem.c    2006-03-18 00:34:06.000000000 +0100
+@@ -127,7 +127,7 @@
+       set_task_state(tsk,TASK_UNINTERRUPTIBLE);
+       /* set up my own style of waitqueue */
+-      spin_lock(&sem->wait_lock);
++      spin_lock_irq(&sem->wait_lock);
+       waiter->task = tsk;
+       get_task_struct(tsk);
+@@ -142,7 +142,7 @@
+       if (!(count & RWSEM_ACTIVE_MASK))
+               sem = __rwsem_do_wake(sem);
+-      spin_unlock(&sem->wait_lock);
++      spin_unlock_irq(&sem->wait_lock);
+       /* wait to be given the lock */
+       for (;;) {
+@@ -195,15 +195,16 @@
+  */
+ struct rw_semaphore fastcall *rwsem_wake(struct rw_semaphore *sem)
+ {
++      unsigned long flags;
+       rwsemtrace(sem,"Entering rwsem_wake");
+-      spin_lock(&sem->wait_lock);
++      spin_lock_irqsave(&sem->wait_lock, flags);
+       /* do nothing if list empty */
+       if (!list_empty(&sem->wait_list))
+               sem = __rwsem_do_wake(sem);
+-      spin_unlock(&sem->wait_lock);
++      spin_unlock_irqrestore(&sem->wait_lock, flags);
+       rwsemtrace(sem,"Leaving rwsem_wake");
+diff -urN linux-2.4.30/mm/filemap.c linux-2.4.30-hf32.3/mm/filemap.c
+--- linux-2.4.30/mm/filemap.c  2005-04-14 09:43:35.000000000 +0200
++++ linux-2.4.30-hf32.3/mm/filemap.c   2006-03-18 00:34:06.000000000 +0100
+@@ -2605,6 +2605,8 @@
+               end = vma->vm_end;
+       end = ((end - vma->vm_start) >> PAGE_SHIFT) + vma->vm_pgoff;
++      error = -EIO;
++
+       /* round to cluster boundaries if this isn't a "random" area. */
+       if (!VM_RandomReadHint(vma)) {
+               start = CLUSTER_OFFSET(start);
+diff -urN linux-2.4.30/mm/vmscan.c linux-2.4.30-hf32.3/mm/vmscan.c
+--- linux-2.4.30/mm/vmscan.c   2005-01-27 18:57:34.000000000 +0100
++++ linux-2.4.30-hf32.3/mm/vmscan.c    2006-03-18 00:34:06.000000000 +0100
+@@ -556,6 +556,7 @@
+                       continue;
+                       
+               }
++              smp_rmb();
+               if (PageDirty(page)) {
+                       spin_unlock(&pagecache_lock);
+                       UnlockPage(page);
+diff -urN linux-2.4.30/net/core/rtnetlink.c linux-2.4.30-hf32.3/net/core/rtnetlink.c
+--- linux-2.4.30/net/core/rtnetlink.c  2003-08-25 13:44:44.000000000 +0200
++++ linux-2.4.30-hf32.3/net/core/rtnetlink.c   2006-03-18 00:34:06.000000000 +0100
+@@ -303,7 +303,7 @@
+               return 0;
+       family = ((struct rtgenmsg*)NLMSG_DATA(nlh))->rtgen_family;
+-      if (family > NPROTO) {
++      if (family >= NPROTO) {
+               *errp = -EAFNOSUPPORT;
+               return -1;
+       }
+diff -urN linux-2.4.30/net/ipv4/af_inet.c linux-2.4.30-hf32.3/net/ipv4/af_inet.c
+--- linux-2.4.30/net/ipv4/af_inet.c    2005-01-27 18:57:34.000000000 +0100
++++ linux-2.4.30-hf32.3/net/ipv4/af_inet.c     2006-03-18 00:34:06.000000000 +0100
+@@ -724,6 +724,7 @@
+               sin->sin_port = sk->sport;
+               sin->sin_addr.s_addr = addr;
+       }
++      memset(sin->sin_zero, 0, sizeof(sin->sin_zero));
+       *uaddr_len = sizeof(*sin);
+       return(0);
+ }
+diff -urN linux-2.4.30/net/ipv4/igmp.c linux-2.4.30-hf32.3/net/ipv4/igmp.c
+--- linux-2.4.30/net/ipv4/igmp.c       2005-01-27 18:57:34.000000000 +0100
++++ linux-2.4.30-hf32.3/net/ipv4/igmp.c        2006-03-18 00:34:06.000000000 +0100
+@@ -876,6 +876,10 @@
+               /* Is it our report looped back? */
+               if (((struct rtable*)skb->dst)->key.iif == 0)
+                       break;
++              /* don't rely on MC router hearing unicast reports */
++              if (skb->pkt_type == PACKET_MULTICAST ||
++                  skb->pkt_type == PACKET_BROADCAST)
++                      igmp_heard_report(in_dev, ih->group);
+               igmp_heard_report(in_dev, ih->group);
+               break;
+       case IGMP_PIM:
+@@ -1582,7 +1586,7 @@
+       }
+       pmc->sources = 0;
+       pmc->sfmode = MCAST_EXCLUDE;
+-      pmc->sfcount[MCAST_EXCLUDE] = 0;
++      pmc->sfcount[MCAST_INCLUDE] = 0;
+       pmc->sfcount[MCAST_EXCLUDE] = 1;
+ }
+@@ -1876,8 +1880,11 @@
+                       sock_kfree_s(sk, newpsl, IP_SFLSIZE(newpsl->sl_max));
+                       goto done;
+               }
+-      } else
+-              newpsl = 0;
++      } else {
++              newpsl = NULL;
++              (void) ip_mc_add_src(in_dev, &msf->imsf_multiaddr,
++                     msf->imsf_fmode, 0, NULL, 0);
++      }
+       psl = pmc->sflist;
+       if (psl) {
+               (void) ip_mc_del_src(in_dev, &msf->imsf_multiaddr, pmc->sfmode,
+diff -urN linux-2.4.30/net/ipv4/inetpeer.c linux-2.4.30-hf32.3/net/ipv4/inetpeer.c
+--- linux-2.4.30/net/ipv4/inetpeer.c   2001-10-01 18:19:56.000000000 +0200
++++ linux-2.4.30-hf32.3/net/ipv4/inetpeer.c    2006-03-18 00:34:06.000000000 +0100
+@@ -445,9 +445,12 @@
+       /* Trigger the timer after inet_peer_gc_mintime .. inet_peer_gc_maxtime
+        * interval depending on the total number of entries (more entries,
+        * less interval). */
+-      peer_periodic_timer.expires = jiffies
+-              + inet_peer_gc_maxtime
+-              - (inet_peer_gc_maxtime - inet_peer_gc_mintime) / HZ *
+-                      peer_total / inet_peer_threshold * HZ;
++      if (peer_total >= inet_peer_threshold)
++              peer_periodic_timer.expires = jiffies + inet_peer_gc_mintime;
++      else
++              peer_periodic_timer.expires = jiffies
++                      + inet_peer_gc_maxtime
++                      - (inet_peer_gc_maxtime - inet_peer_gc_mintime) / HZ *
++                              peer_total / inet_peer_threshold * HZ;
+       add_timer(&peer_periodic_timer);
+ }
+diff -urN linux-2.4.30/net/ipv4/ipvs/ip_vs_conn.c linux-2.4.30-hf32.3/net/ipv4/ipvs/ip_vs_conn.c
+--- linux-2.4.30/net/ipv4/ipvs/ip_vs_conn.c    2005-01-27 18:57:34.000000000 +0100
++++ linux-2.4.30-hf32.3/net/ipv4/ipvs/ip_vs_conn.c     2006-03-18 00:34:06.000000000 +0100
+@@ -210,6 +210,7 @@
+               cp = list_entry(e, struct ip_vs_conn, c_list);
+               if (s_addr==cp->caddr && s_port==cp->cport &&
+                   d_port==cp->vport && d_addr==cp->vaddr &&
++                  ((!s_port) ^ (!(cp->flags & IP_VS_CONN_F_NO_CPORT))) &&
+                   protocol==cp->protocol) {
+                       /* HIT */
+                       atomic_inc(&cp->refcnt);
+@@ -241,6 +242,40 @@
+       return cp;
+ }
++/* Get reference to connection template */
++struct ip_vs_conn *ip_vs_ct_in_get
++(int protocol, __u32 s_addr, __u16 s_port, __u32 d_addr, __u16 d_port)
++{
++      unsigned hash;
++      struct ip_vs_conn *cp;
++
++      hash = ip_vs_conn_hashkey(protocol, s_addr, s_port);
++
++      ct_read_lock(hash);
++
++      list_for_each_entry(cp, &ip_vs_conn_tab[hash], c_list) {
++              if (s_addr==cp->caddr && s_port==cp->cport &&
++                  d_port==cp->vport && d_addr==cp->vaddr &&
++                  cp->flags & IP_VS_CONN_F_TEMPLATE &&
++                  protocol==cp->protocol) {
++                      /* HIT */
++                      atomic_inc(&cp->refcnt);
++                      goto out;
++              }
++      }
++      cp = NULL;
++
++  out:
++      ct_read_unlock(hash);
++
++      IP_VS_DBG(7, "template lookup/in %s %u.%u.%u.%u:%d->%u.%u.%u.%u:%d %s\n",
++                ip_vs_proto_name(protocol),
++                NIPQUAD(s_addr), ntohs(s_port),
++                NIPQUAD(d_addr), ntohs(d_port),
++                cp?"hit":"not hit");
++
++      return cp;
++}
+ /*
+  *  Gets ip_vs_conn associated with supplied parameters in the ip_vs_conn_tab.
+@@ -1087,7 +1122,7 @@
+       IP_VS_DBG(9, "Unbind-dest %s c:%u.%u.%u.%u:%d "
+                 "v:%u.%u.%u.%u:%d d:%u.%u.%u.%u:%d fwd:%c "
+-                "s:%s flg:%X cnt:%d destcnt:%d",
++                "s:%s flg:%X cnt:%d destcnt:%d\n",
+                 ip_vs_proto_name(cp->protocol),
+                 NIPQUAD(cp->caddr), ntohs(cp->cport),
+                 NIPQUAD(cp->vaddr), ntohs(cp->vport),
+@@ -1098,10 +1133,9 @@
+       /*
+        * Decrease the inactconns or activeconns counter
+-       * if it is not a connection template ((cp->cport!=0)
+-       *   || (cp->flags & IP_VS_CONN_F_NO_CPORT)).
++       * if it is not a connection template
+        */
+-      if (cp->cport || (cp->flags & IP_VS_CONN_F_NO_CPORT)) {
++      if (!(cp->flags & IP_VS_CONN_F_TEMPLATE)) {
+               if (cp->flags & IP_VS_CONN_F_INACTIVE) {
+                       atomic_dec(&dest->inactconns);
+               } else {
+@@ -1145,7 +1179,7 @@
+               /*
+                * Invalidate the connection template
+                */
+-              if (ct->cport) {
++              if (ct->vport != 65535) {
+                       if (ip_vs_conn_unhash(ct)) {
+                               ct->dport = 65535;
+                               ct->vport = 65535;
+@@ -1430,7 +1464,7 @@
+               l = &ip_vs_conn_tab[hash];
+               for (e=l->next; e!=l; e=e->next) {
+                       cp = list_entry(e, struct ip_vs_conn, c_list);
+-                      if (!cp->cport && !(cp->flags & IP_VS_CONN_F_NO_CPORT))
++                      if (cp->flags & IP_VS_CONN_F_TEMPLATE)
+                               /* connection template */
+                               continue;
+                       switch(cp->state) {
+diff -urN linux-2.4.30/net/ipv4/ipvs/ip_vs_core.c linux-2.4.30-hf32.3/net/ipv4/ipvs/ip_vs_core.c
+--- linux-2.4.30/net/ipv4/ipvs/ip_vs_core.c    2005-04-14 09:43:35.000000000 +0200
++++ linux-2.4.30-hf32.3/net/ipv4/ipvs/ip_vs_core.c     2006-03-18 00:34:06.000000000 +0100
+@@ -188,10 +188,10 @@
+       if (portp[1] == svc->port) {
+               /* Check if a template already exists */
+               if (svc->port != FTPPORT)
+-                      ct = ip_vs_conn_in_get(iph->protocol, snet, 0,
++                      ct = ip_vs_ct_in_get(iph->protocol, snet, 0,
+                                              iph->daddr, portp[1]);
+               else
+-                      ct = ip_vs_conn_in_get(iph->protocol, snet, 0,
++                      ct = ip_vs_ct_in_get(iph->protocol, snet, 0,
+                                              iph->daddr, 0);
+               if (!ct || !ip_vs_check_template(ct)) {
+@@ -216,14 +216,14 @@
+                                                   snet, 0,
+                                                   iph->daddr, portp[1],
+                                                   dest->addr, dest->port,
+-                                                  0,
++                                                  IP_VS_CONN_F_TEMPLATE,
+                                                   dest);
+                       else
+                               ct = ip_vs_conn_new(iph->protocol,
+                                                   snet, 0,
+                                                   iph->daddr, 0,
+                                                   dest->addr, 0,
+-                                                  0,
++                                                  IP_VS_CONN_F_TEMPLATE,
+                                                   dest);
+                       if (ct == NULL)
+                               return NULL;
+@@ -242,10 +242,10 @@
+                * port zero template: <protocol,caddr,0,vaddr,0,daddr,0>
+                */
+               if (svc->fwmark)
+-                      ct = ip_vs_conn_in_get(IPPROTO_IP, snet, 0,
++                      ct = ip_vs_ct_in_get(IPPROTO_IP, snet, 0,
+                                              htonl(svc->fwmark), 0);
+               else
+-                      ct = ip_vs_conn_in_get(iph->protocol, snet, 0,
++                      ct = ip_vs_ct_in_get(iph->protocol, snet, 0,
+                                              iph->daddr, 0);
+               if (!ct || !ip_vs_check_template(ct)) {
+@@ -270,14 +270,14 @@
+                                                   snet, 0,
+                                                   htonl(svc->fwmark), 0,
+                                                   dest->addr, 0,
+-                                                  0,
++                                                  IP_VS_CONN_F_TEMPLATE,
+                                                   dest);
+                       else
+                               ct = ip_vs_conn_new(iph->protocol,
+                                                   snet, 0,
+                                                   iph->daddr, 0,
+                                                   dest->addr, 0,
+-                                                  0,
++                                                  IP_VS_CONN_F_TEMPLATE,
+                                                   dest);
+                       if (ct == NULL)
+                               return NULL;
+@@ -1111,11 +1111,10 @@
+               if (sysctl_ip_vs_expire_nodest_conn) {
+                       /* try to expire the connection immediately */
+                       ip_vs_conn_expire_now(cp);
+-              } else {
+-                      /* don't restart its timer, and silently
+-                         drop the packet. */
+-                      __ip_vs_conn_put(cp);
+               }
++              /* don't restart its timer, and silently
++                 drop the packet. */
++              __ip_vs_conn_put(cp);
+               return NF_DROP;
+       }
+diff -urN linux-2.4.30/net/ipv4/ipvs/ip_vs_ctl.c linux-2.4.30-hf32.3/net/ipv4/ipvs/ip_vs_ctl.c
+--- linux-2.4.30/net/ipv4/ipvs/ip_vs_ctl.c     2005-01-27 18:57:34.000000000 +0100
++++ linux-2.4.30-hf32.3/net/ipv4/ipvs/ip_vs_ctl.c      2006-03-18 00:34:06.000000000 +0100
+@@ -1842,7 +1842,8 @@
+                       entry.addr = svc->addr;
+                       entry.port = svc->port;
+                       entry.fwmark = svc->fwmark;
+-                      strcpy(entry.sched_name, svc->scheduler->name);
++                      strncpy(entry.sched_name, svc->scheduler->name, sizeof(entry.sched_name));
++                      entry.sched_name[sizeof(entry.sched_name) - 1] = 0;
+                       entry.flags = svc->flags;
+                       entry.timeout = svc->timeout / HZ;
+                       entry.netmask = svc->netmask;
+@@ -1866,7 +1867,8 @@
+                       entry.addr = svc->addr;
+                       entry.port = svc->port;
+                       entry.fwmark = svc->fwmark;
+-                      strcpy(entry.sched_name, svc->scheduler->name);
++                      strncpy(entry.sched_name, svc->scheduler->name, sizeof(entry.sched_name));
++                      entry.sched_name[sizeof(entry.sched_name) - 1] = 0;
+                       entry.flags = svc->flags;
+                       entry.timeout = svc->timeout / HZ;
+                       entry.netmask = svc->netmask;
+@@ -2020,7 +2022,8 @@
+                       svc = __ip_vs_service_get(get.protocol,
+                                                 get.addr, get.port);
+               if (svc) {
+-                      strcpy(get.sched_name, svc->scheduler->name);
++                      strncpy(get.sched_name, svc->scheduler->name, sizeof(get.sched_name));
++                      get.sched_name[sizeof(get.sched_name) - 1] = 0;
+                       get.flags = svc->flags;
+                       get.timeout = svc->timeout / HZ;
+                       get.netmask = svc->netmask;
+@@ -2083,10 +2086,14 @@
+                       goto out;
+               }
+               u.state = ip_vs_sync_state;
+-              if (ip_vs_sync_state & IP_VS_STATE_MASTER)
+-                      strcpy(u.mcast_master_ifn, ip_vs_mcast_master_ifn);
+-              if (ip_vs_sync_state & IP_VS_STATE_BACKUP)
+-                      strcpy(u.mcast_backup_ifn, ip_vs_mcast_backup_ifn);
++              if (ip_vs_sync_state & IP_VS_STATE_MASTER) {
++                      strncpy(u.mcast_master_ifn, ip_vs_mcast_master_ifn, sizeof(u.mcast_master_ifn));
++                      u.mcast_master_ifn[sizeof(u.mcast_master_ifn) - 1] = 0;
++              }
++              if (ip_vs_sync_state & IP_VS_STATE_BACKUP) {
++                      strncpy(u.mcast_backup_ifn, ip_vs_mcast_backup_ifn, sizeof(u.mcast_backup_ifn));
++                      u.mcast_backup_ifn[sizeof(u.mcast_backup_ifn) - 1] = 0;
++              }
+               if (copy_to_user(user, &u, sizeof(u)) != 0)
+                       ret = -EFAULT;
+       }
+diff -urN linux-2.4.30/net/ipv4/ipvs/ip_vs_sched.c linux-2.4.30-hf32.3/net/ipv4/ipvs/ip_vs_sched.c
+--- linux-2.4.30/net/ipv4/ipvs/ip_vs_sched.c   2004-04-14 15:05:41.000000000 +0200
++++ linux-2.4.30-hf32.3/net/ipv4/ipvs/ip_vs_sched.c    2006-03-18 00:34:06.000000000 +0100
+@@ -156,7 +156,7 @@
+        */
+       if (sched == NULL) {
+               char module_name[IP_VS_SCHEDNAME_MAXLEN+8];
+-              sprintf(module_name,"ip_vs_%s", sched_name);
++              snprintf(module_name, sizeof(module_name), "ip_vs_%s", sched_name);
+               request_module(module_name);
+               sched = ip_vs_sched_getbyname(sched_name);
+       }
+diff -urN linux-2.4.30/net/ipv4/ipvs/ip_vs_sync.c linux-2.4.30-hf32.3/net/ipv4/ipvs/ip_vs_sync.c
+--- linux-2.4.30/net/ipv4/ipvs/ip_vs_sync.c    2005-01-27 18:57:34.000000000 +0100
++++ linux-2.4.30-hf32.3/net/ipv4/ipvs/ip_vs_sync.c     2006-03-18 00:34:06.000000000 +0100
+@@ -295,16 +295,24 @@
+       p = (char *)buffer + sizeof(struct ip_vs_sync_mesg);
+       for (i=0; i<m->nr_conns; i++) {
++              unsigned flags;
++
+               s = (struct ip_vs_sync_conn *)p;
+-              cp = ip_vs_conn_in_get(s->protocol,
+-                                     s->caddr, s->cport,
+-                                     s->vaddr, s->vport);
++              flags = ntohs(s->flags);
++              if (!(flags & IP_VS_CONN_F_TEMPLATE))
++                      cp = ip_vs_conn_in_get(s->protocol,
++                                             s->caddr, s->cport,
++                                             s->vaddr, s->vport);
++              else
++                      cp = ip_vs_ct_in_get(s->protocol,
++                                             s->caddr, s->cport,
++                                             s->vaddr, s->vport);
+               if (!cp) {
+                       cp = ip_vs_conn_new(s->protocol,
+                                           s->caddr, s->cport,
+                                           s->vaddr, s->vport,
+                                           s->daddr, s->dport,
+-                                          ntohs(s->flags), NULL);
++                                          flags, NULL);
+                       if (!cp) {
+                               IP_VS_ERR("ip_vs_conn_new failed\n");
+                               return;
+@@ -313,11 +321,11 @@
+               } else if (!cp->dest) {
+                       /* it is an entry created by the synchronization */
+                       cp->state = ntohs(s->state);
+-                      cp->flags = ntohs(s->flags) | IP_VS_CONN_F_HASHED;
++                      cp->flags = flags | IP_VS_CONN_F_HASHED;
+               }       /* Note that we don't touch its state and flags
+                          if it is a normal entry. */
+-              if (ntohs(s->flags) & IP_VS_CONN_F_SEQ_MASK) {
++              if (flags & IP_VS_CONN_F_SEQ_MASK) {
+                       opt = (struct ip_vs_sync_conn_options *)&s[1];
+                       memcpy(&cp->in_seq, opt, sizeof(*opt));
+                       p += FULL_CONN_SIZE;
+@@ -808,10 +816,12 @@
+       ip_vs_sync_state |= state;
+       if (state == IP_VS_STATE_MASTER) {
+-              strcpy(ip_vs_mcast_master_ifn, mcast_ifn);
++              strncpy(ip_vs_mcast_master_ifn, mcast_ifn, sizeof(ip_vs_mcast_master_ifn));
++              ip_vs_mcast_master_ifn[sizeof(ip_vs_mcast_master_ifn) - 1] = 0;
+               ip_vs_master_syncid = syncid;
+       } else {
+-              strcpy(ip_vs_mcast_backup_ifn, mcast_ifn);
++              strncpy(ip_vs_mcast_backup_ifn, mcast_ifn, sizeof(ip_vs_mcast_backup_ifn));
++              ip_vs_mcast_backup_ifn[sizeof(ip_vs_mcast_backup_ifn) - 1] = 0;
+               ip_vs_backup_syncid = syncid;
+       }
+diff -urN linux-2.4.30/net/ipv4/netfilter/ip_conntrack_core.c linux-2.4.30-hf32.3/net/ipv4/netfilter/ip_conntrack_core.c
+--- linux-2.4.30/net/ipv4/netfilter/ip_conntrack_core.c        2005-04-14 09:43:35.000000000 +0200
++++ linux-2.4.30-hf32.3/net/ipv4/netfilter/ip_conntrack_core.c 2006-03-18 00:34:06.000000000 +0100
+@@ -1349,6 +1349,7 @@
+                       .tuple.dst.u.tcp.port;
+               sin.sin_addr.s_addr = h->ctrack->tuplehash[IP_CT_DIR_ORIGINAL]
+                       .tuple.dst.ip;
++              memset(sin.sin_zero, 0, sizeof(sin.sin_zero));
+               DEBUGP("SO_ORIGINAL_DST: %u.%u.%u.%u %u\n",
+                      NIPQUAD(sin.sin_addr.s_addr), ntohs(sin.sin_port));
+diff -urN linux-2.4.30/net/ipv4/netfilter/ip_nat_proto_tcp.c linux-2.4.30-hf32.3/net/ipv4/netfilter/ip_nat_proto_tcp.c
+--- linux-2.4.30/net/ipv4/netfilter/ip_nat_proto_tcp.c 2002-11-29 00:53:15.000000000 +0100
++++ linux-2.4.30-hf32.3/net/ipv4/netfilter/ip_nat_proto_tcp.c  2006-03-18 00:34:06.000000000 +0100
+@@ -31,7 +31,8 @@
+                enum ip_nat_manip_type maniptype,
+                const struct ip_conntrack *conntrack)
+ {
+-      static u_int16_t port = 0, *portptr;
++      static u_int16_t port = 0;
++      u_int16_t *portptr;
+       unsigned int range_size, min, i;
+       if (maniptype == IP_NAT_MANIP_SRC)
+diff -urN linux-2.4.30/net/ipv4/netfilter/ip_nat_proto_udp.c linux-2.4.30-hf32.3/net/ipv4/netfilter/ip_nat_proto_udp.c
+--- linux-2.4.30/net/ipv4/netfilter/ip_nat_proto_udp.c 2000-08-04 22:07:24.000000000 +0200
++++ linux-2.4.30-hf32.3/net/ipv4/netfilter/ip_nat_proto_udp.c  2006-03-18 00:34:06.000000000 +0100
+@@ -32,7 +32,8 @@
+                enum ip_nat_manip_type maniptype,
+                const struct ip_conntrack *conntrack)
+ {
+-      static u_int16_t port = 0, *portptr;
++      static u_int16_t port = 0;
++      u_int16_t *portptr;
+       unsigned int range_size, min, i;
+       if (maniptype == IP_NAT_MANIP_SRC)
+diff -urN linux-2.4.30/net/ipv4/netfilter/ip_nat_rule.c linux-2.4.30-hf32.3/net/ipv4/netfilter/ip_nat_rule.c
+--- linux-2.4.30/net/ipv4/netfilter/ip_nat_rule.c      2005-01-27 18:57:34.000000000 +0100
++++ linux-2.4.30-hf32.3/net/ipv4/netfilter/ip_nat_rule.c       2006-03-18 00:34:06.000000000 +0100
+@@ -241,6 +241,27 @@
+       return ip_nat_setup_info(conntrack, &mr, hooknum);
+ }
++unsigned int
++alloc_null_binding_confirmed(struct ip_conntrack *conntrack,
++                             struct ip_nat_info *info,
++                             unsigned int hooknum)
++{
++      u_int32_t ip
++              = (HOOK2MANIP(hooknum) == IP_NAT_MANIP_SRC
++                 ? conntrack->tuplehash[IP_CT_DIR_REPLY].tuple.dst.ip
++                 : conntrack->tuplehash[IP_CT_DIR_REPLY].tuple.src.ip);
++      u_int16_t all
++              = (HOOK2MANIP(hooknum) == IP_NAT_MANIP_SRC
++                 ? conntrack->tuplehash[IP_CT_DIR_REPLY].tuple.dst.u.all
++                 : conntrack->tuplehash[IP_CT_DIR_REPLY].tuple.src.u.all);
++      struct ip_nat_multi_range mr
++              = { 1, { { IP_NAT_RANGE_MAP_IPS, ip, ip, { all }, { all } } } };
++
++      DEBUGP("Allocating NULL binding for confirmed %p (%u.%u.%u.%u)\n",
++             conntrack, NIPQUAD(ip));
++      return ip_nat_setup_info(conntrack, &mr, hooknum);
++}
++
+ int ip_nat_rule_find(struct sk_buff **pskb,
+                    unsigned int hooknum,
+                    const struct net_device *in,
+diff -urN linux-2.4.30/net/ipv4/netfilter/ip_nat_standalone.c linux-2.4.30-hf32.3/net/ipv4/netfilter/ip_nat_standalone.c
+--- linux-2.4.30/net/ipv4/netfilter/ip_nat_standalone.c        2005-04-14 09:43:35.000000000 +0200
++++ linux-2.4.30-hf32.3/net/ipv4/netfilter/ip_nat_standalone.c 2006-03-18 00:34:06.000000000 +0100
+@@ -123,8 +123,12 @@
+                               ret = call_expect(master_ct(ct), pskb, 
+                                                 hooknum, ct, info);
+                       } else {
+-                              /* LOCAL_IN hook doesn't have a chain!  */
+-                              if (hooknum == NF_IP_LOCAL_IN)
++                              if (unlikely(is_confirmed(ct)))
++                                      /* NAT module was loaded late */
++                                      ret = alloc_null_binding_confirmed(ct, info,
++                                                                         hooknum);
++                              else if (hooknum == NF_IP_LOCAL_IN)
++                                      /* LOCAL_IN hook doesn't have a chain */
+                                       ret = alloc_null_binding(ct, info,
+                                                                hooknum);
+                               else
+diff -urN linux-2.4.30/net/ipv4/netfilter/ip_queue.c linux-2.4.30-hf32.3/net/ipv4/netfilter/ip_queue.c
+--- linux-2.4.30/net/ipv4/netfilter/ip_queue.c 2004-02-18 14:36:32.000000000 +0100
++++ linux-2.4.30-hf32.3/net/ipv4/netfilter/ip_queue.c  2006-03-18 00:34:06.000000000 +0100
+@@ -517,7 +517,7 @@
+       write_unlock_bh(&queue_lock);
+       
+       status = ipq_receive_peer(NLMSG_DATA(nlh), type,
+-                                skblen - NLMSG_LENGTH(0));
++                                nlmsglen - NLMSG_LENGTH(0));
+       if (status < 0)
+               RCV_SKB_FAIL(status);
+               
+diff -urN linux-2.4.30/net/ipv4/netfilter/ipt_unclean.c linux-2.4.30-hf32.3/net/ipv4/netfilter/ipt_unclean.c
+--- linux-2.4.30/net/ipv4/netfilter/ipt_unclean.c      2004-08-08 01:26:06.000000000 +0200
++++ linux-2.4.30-hf32.3/net/ipv4/netfilter/ipt_unclean.c       2006-03-18 00:34:06.000000000 +0100
+@@ -264,6 +264,7 @@
+ {
+       [TH_SYN]                        = 1,
+       [TH_SYN|TH_ACK]                 = 1,
++      [TH_SYN|TH_ACK|TH_PUSH]         = 1,
+       [TH_RST]                        = 1,
+       [TH_RST|TH_ACK]                 = 1,
+       [TH_RST|TH_ACK|TH_PUSH]         = 1,
+diff -urN linux-2.4.30/net/ipv4/tcp_input.c linux-2.4.30-hf32.3/net/ipv4/tcp_input.c
+--- linux-2.4.30/net/ipv4/tcp_input.c  2005-04-14 09:43:35.000000000 +0200
++++ linux-2.4.30-hf32.3/net/ipv4/tcp_input.c   2006-03-18 00:34:06.000000000 +0100
+@@ -374,8 +374,6 @@
+                       app_win -= tp->ack.rcv_mss;
+               app_win = max(app_win, 2U*tp->advmss);
+-              if (!ofo_win)
+-                      tp->window_clamp = min(tp->window_clamp, app_win);
+               tp->rcv_ssthresh = min(tp->window_clamp, 2U*tp->advmss);
+       }
+ }
+@@ -2488,6 +2486,7 @@
+                       /* Note, it is the only place, where
+                        * fast path is recovered for sending TCP.
+                        */
++                      tp->pred_flags = 0;
+                       tcp_fast_path_check(sk, tp);
+                       if (nwin > tp->max_window) {
+@@ -4243,16 +4242,7 @@
+                                       goto no_ack;
+                       }
+-                      if (eaten) {
+-                              if (tcp_in_quickack_mode(tp)) {
+-                                      tcp_send_ack(sk);
+-                              } else {
+-                                      tcp_send_delayed_ack(sk);
+-                              }
+-                      } else {
+-                              __tcp_ack_snd_check(sk, 0);
+-                      }
+-
++                      __tcp_ack_snd_check(sk, 0);
+ no_ack:
+                       if (eaten)
+                               __kfree_skb(skb);
+diff -urN linux-2.4.30/net/ipv6/addrconf.c linux-2.4.30-hf32.3/net/ipv6/addrconf.c
+--- linux-2.4.30/net/ipv6/addrconf.c   2004-11-17 12:54:22.000000000 +0100
++++ linux-2.4.30-hf32.3/net/ipv6/addrconf.c    2006-03-18 00:34:06.000000000 +0100
+@@ -883,7 +883,7 @@
+       if (dev->type == ARPHRD_SIT && (dev->flags&IFF_POINTOPOINT))
+               rtmsg.rtmsg_flags |= RTF_NONEXTHOP;
+-      ip6_route_add(&rtmsg, NULL);
++      ip6_route_add(&rtmsg, NULL, NULL);
+ }
+ /* Create "default" multicast route to the interface */
+@@ -900,7 +900,7 @@
+       rtmsg.rtmsg_ifindex = dev->ifindex;
+       rtmsg.rtmsg_flags = RTF_UP;
+       rtmsg.rtmsg_type = RTMSG_NEWROUTE;
+-      ip6_route_add(&rtmsg, NULL);
++      ip6_route_add(&rtmsg, NULL, NULL);
+ }
+ static void sit_route_add(struct net_device *dev)
+@@ -917,7 +917,7 @@
+       rtmsg.rtmsg_flags       = RTF_UP|RTF_NONEXTHOP;
+       rtmsg.rtmsg_ifindex     = dev->ifindex;
+-      ip6_route_add(&rtmsg, NULL);
++      ip6_route_add(&rtmsg, NULL, NULL);
+ }
+ static void addrconf_add_lroute(struct net_device *dev)
+@@ -1009,7 +1009,7 @@
+       if (rt && ((rt->rt6i_flags & (RTF_GATEWAY | RTF_DEFAULT)) == 0)) {
+               if (rt->rt6i_flags&RTF_EXPIRES) {
+                       if (pinfo->onlink == 0 || valid_lft == 0) {
+-                              ip6_del_rt(rt, NULL);
++                              ip6_del_rt(rt, NULL, NULL);
+                               rt = NULL;
+                       } else {
+                               rt->rt6i_expires = rt_expires;
+@@ -1592,7 +1592,7 @@
+               rtmsg.rtmsg_ifindex = ifp->idev->dev->ifindex;
+-              ip6_route_add(&rtmsg, NULL);
++              ip6_route_add(&rtmsg, NULL, NULL);
+       }
+ out:
+diff -urN linux-2.4.30/net/ipv6/ip6_fib.c linux-2.4.30-hf32.3/net/ipv6/ip6_fib.c
+--- linux-2.4.30/net/ipv6/ip6_fib.c    2004-11-17 12:54:22.000000000 +0100
++++ linux-2.4.30-hf32.3/net/ipv6/ip6_fib.c     2006-03-18 00:34:06.000000000 +0100
+@@ -424,7 +424,7 @@
+  */
+ static int fib6_add_rt2node(struct fib6_node *fn, struct rt6_info *rt,
+-    struct nlmsghdr *nlh)
++              struct nlmsghdr *nlh,  struct netlink_skb_parms *req)
+ {
+       struct rt6_info *iter = NULL;
+       struct rt6_info **ins;
+@@ -482,7 +482,7 @@
+       *ins = rt;
+       rt->rt6i_node = fn;
+       atomic_inc(&rt->rt6i_ref);
+-      inet6_rt_notify(RTM_NEWROUTE, rt, nlh);
++      inet6_rt_notify(RTM_NEWROUTE, rt, nlh, req);
+       rt6_stats.fib_rt_entries++;
+       if ((fn->fn_flags & RTN_RTINFO) == 0) {
+@@ -506,7 +506,8 @@
+  *    with source addr info in sub-trees
+  */
+-int fib6_add(struct fib6_node *root, struct rt6_info *rt, struct nlmsghdr *nlh)
++int fib6_add(struct fib6_node *root, struct rt6_info *rt, struct nlmsghdr *nlh,
++              struct netlink_skb_parms *req)
+ {
+       struct fib6_node *fn;
+       int err = -ENOMEM;
+@@ -579,7 +580,7 @@
+       }
+ #endif
+-      err = fib6_add_rt2node(fn, rt, nlh);
++      err = fib6_add_rt2node(fn, rt, nlh, req);
+       if (err == 0) {
+               fib6_start_gc(rt);
+@@ -888,7 +889,7 @@
+ }
+ static void fib6_del_route(struct fib6_node *fn, struct rt6_info **rtp,
+-    struct nlmsghdr *nlh)
++    struct nlmsghdr *nlh, struct netlink_skb_parms *req)
+ {
+       struct fib6_walker_t *w;
+       struct rt6_info *rt = *rtp;
+@@ -943,11 +944,11 @@
+               if (atomic_read(&rt->rt6i_ref) != 1) BUG();
+       }
+-      inet6_rt_notify(RTM_DELROUTE, rt, nlh);
++      inet6_rt_notify(RTM_DELROUTE, rt, nlh, req);
+       rt6_release(rt);
+ }
+-int fib6_del(struct rt6_info *rt, struct nlmsghdr *nlh)
++int fib6_del(struct rt6_info *rt, struct nlmsghdr *nlh, struct netlink_skb_parms *req)
+ {
+       struct fib6_node *fn = rt->rt6i_node;
+       struct rt6_info **rtp;
+@@ -972,7 +973,7 @@
+       for (rtp = &fn->leaf; *rtp; rtp = &(*rtp)->u.next) {
+               if (*rtp == rt) {
+-                      fib6_del_route(fn, rtp, nlh);
++                      fib6_del_route(fn, rtp, nlh, req);
+                       return 0;
+               }
+       }
+@@ -1101,7 +1102,7 @@
+               res = c->func(rt, c->arg);
+               if (res < 0) {
+                       w->leaf = rt;
+-                      res = fib6_del(rt, NULL);
++                      res = fib6_del(rt, NULL, NULL);
+                       if (res) {
+ #if RT6_DEBUG >= 2
+                               printk(KERN_DEBUG "fib6_clean_node: del failed: rt=%p@%p err=%d\n", rt, rt->rt6i_node, res);
+diff -urN linux-2.4.30/net/ipv6/ip6_flowlabel.c linux-2.4.30-hf32.3/net/ipv6/ip6_flowlabel.c
+--- linux-2.4.30/net/ipv6/ip6_flowlabel.c      2000-08-07 07:20:09.000000000 +0200
++++ linux-2.4.30-hf32.3/net/ipv6/ip6_flowlabel.c       2006-03-18 00:34:06.000000000 +0100
+@@ -475,7 +475,7 @@
+                                               goto done;
+                                       }
+                                       fl1 = sfl->fl;
+-                                      atomic_inc(&fl->users);
++                                      atomic_inc(&fl1->users);
+                                       break;
+                               }
+                       }
+diff -urN linux-2.4.30/net/ipv6/mcast.c linux-2.4.30-hf32.3/net/ipv6/mcast.c
+--- linux-2.4.30/net/ipv6/mcast.c      2005-01-27 18:57:34.000000000 +0100
++++ linux-2.4.30-hf32.3/net/ipv6/mcast.c       2006-03-18 00:34:06.000000000 +0100
+@@ -505,8 +505,11 @@
+                       sock_kfree_s(sk, newpsl, IP6_SFLSIZE(newpsl->sl_max));
+                       goto done;
+               }
+-      } else
+-              newpsl = 0;
++      } else {
++              newpsl = NULL;
++              (void) ip6_mc_add_src(idev, group, gsf->gf_fmode, 0, NULL, 0);
++      }
++
+       psl = pmc->sflist;
+       if (psl) {
+               (void) ip6_mc_del_src(idev, group, pmc->sfmode,
+@@ -1142,6 +1145,11 @@
+       if (skb->pkt_type == PACKET_LOOPBACK)
+               return 0;
++      /* send our report if the MC router may not have heard this report */
++      if (skb->pkt_type != PACKET_MULTICAST &&
++          skb->pkt_type != PACKET_BROADCAST)
++              return 0;
++
+       if (!pskb_may_pull(skb, sizeof(struct in6_addr)))
+               return -EINVAL;
+@@ -1867,7 +1875,7 @@
+       }
+       pmc->mca_sources = 0;
+       pmc->mca_sfmode = MCAST_EXCLUDE;
+-      pmc->mca_sfcount[MCAST_EXCLUDE] = 0;
++      pmc->mca_sfcount[MCAST_INCLUDE] = 0;
+       pmc->mca_sfcount[MCAST_EXCLUDE] = 1;
+ }
+diff -urN linux-2.4.30/net/ipv6/ndisc.c linux-2.4.30-hf32.3/net/ipv6/ndisc.c
+--- linux-2.4.30/net/ipv6/ndisc.c      2004-11-17 12:54:22.000000000 +0100
++++ linux-2.4.30-hf32.3/net/ipv6/ndisc.c       2006-03-18 00:34:06.000000000 +0100
+@@ -876,7 +876,7 @@
+                                       /* It is safe only because
+                                          we aer in BH */
+                                       dst_release(&rt->u.dst);
+-                                      ip6_del_rt(rt, NULL);
++                                      ip6_del_rt(rt, NULL, NULL);
+                               }
+                       }
+               } else {
+@@ -962,7 +962,7 @@
+       rt = rt6_get_dflt_router(&skb->nh.ipv6h->saddr, skb->dev);
+       if (rt && lifetime == 0) {
+-              ip6_del_rt(rt, NULL);
++              ip6_del_rt(rt, NULL, NULL);
+               rt = NULL;
+       }
+diff -urN linux-2.4.30/net/ipv6/netfilter/ip6_queue.c linux-2.4.30-hf32.3/net/ipv6/netfilter/ip6_queue.c
+--- linux-2.4.30/net/ipv6/netfilter/ip6_queue.c        2004-02-18 14:36:32.000000000 +0100
++++ linux-2.4.30-hf32.3/net/ipv6/netfilter/ip6_queue.c 2006-03-18 00:34:06.000000000 +0100
+@@ -521,7 +521,7 @@
+       write_unlock_bh(&queue_lock);
+       
+       status = ipq_receive_peer(NLMSG_DATA(nlh), type,
+-                                skblen - NLMSG_LENGTH(0));
++                                nlmsglen - NLMSG_LENGTH(0));
+       if (status < 0)
+               RCV_SKB_FAIL(status);
+               
+diff -urN linux-2.4.30/net/ipv6/route.c linux-2.4.30-hf32.3/net/ipv6/route.c
+--- linux-2.4.30/net/ipv6/route.c      2004-11-17 12:54:22.000000000 +0100
++++ linux-2.4.30-hf32.3/net/ipv6/route.c       2006-03-18 00:34:06.000000000 +0100
+@@ -325,12 +325,12 @@
+    be destroyed.
+  */
+-static int rt6_ins(struct rt6_info *rt, struct nlmsghdr *nlh)
++static int rt6_ins(struct rt6_info *rt, struct nlmsghdr *nlh, struct netlink_skb_parms *req)
+ {
+       int err;
+       write_lock_bh(&rt6_lock);
+-      err = fib6_add(&ip6_routing_table, rt, nlh);
++      err = fib6_add(&ip6_routing_table, rt, nlh, req);
+       write_unlock_bh(&rt6_lock);
+       return err;
+@@ -341,7 +341,7 @@
+  */
+ static struct rt6_info *rt6_cow(struct rt6_info *ort, struct in6_addr *daddr,
+-                              struct in6_addr *saddr)
++                              struct in6_addr *saddr, struct netlink_skb_parms *req)
+ {
+       int err;
+       struct rt6_info *rt;
+@@ -373,7 +373,7 @@
+               dst_hold(&rt->u.dst);
+-              err = rt6_ins(rt, NULL);
++              err = rt6_ins(rt, NULL, req);
+               if (err == 0)
+                       return rt;
+@@ -479,7 +479,8 @@
+                       read_unlock_bh(&rt6_lock);
+                       rt = rt6_cow(rt, &skb->nh.ipv6h->daddr,
+-                                   &skb->nh.ipv6h->saddr);
++                                   &skb->nh.ipv6h->saddr,
++                                   &NETLINK_CB(skb));
+                       
+                       if (rt->u.dst.error != -EEXIST || --attempts <= 0)
+                               goto out2;
+@@ -558,7 +559,7 @@
+                       read_unlock_bh(&rt6_lock);
+                       rt = rt6_cow(rt, fl->nl_u.ip6_u.daddr,
+-                                   fl->nl_u.ip6_u.saddr);
++                                   fl->nl_u.ip6_u.saddr, NULL);
+                       
+                       if (rt->u.dst.error != -EEXIST || --attempts <= 0)
+                               goto out2;
+@@ -619,7 +620,7 @@
+       if (rt) {
+               if (rt->rt6i_flags & RTF_CACHE)
+-                      ip6_del_rt(rt, NULL);
++                      ip6_del_rt(rt, NULL, NULL);
+               else
+                       dst_release(dst);
+       }
+@@ -712,7 +713,7 @@
+  *
+  */
+-int ip6_route_add(struct in6_rtmsg *rtmsg, struct nlmsghdr *nlh)
++int ip6_route_add(struct in6_rtmsg *rtmsg, struct nlmsghdr *nlh, struct netlink_skb_parms *req)
+ {
+       int err;
+       struct rtmsg *r;
+@@ -865,7 +866,7 @@
+       if (rt->u.dst.advmss > 65535-20)
+               rt->u.dst.advmss = 65535;
+       rt->u.dst.dev = dev;
+-      return rt6_ins(rt, nlh);
++      return rt6_ins(rt, nlh, req);
+ out:
+       if (dev)
+@@ -874,7 +875,7 @@
+       return err;
+ }
+-int ip6_del_rt(struct rt6_info *rt, struct nlmsghdr *nlh)
++int ip6_del_rt(struct rt6_info *rt, struct nlmsghdr *nlh, struct netlink_skb_parms *req)
+ {
+       int err;
+@@ -886,13 +887,13 @@
+       dst_release(&rt->u.dst);
+-      err = fib6_del(rt, nlh);
++      err = fib6_del(rt, nlh, req);
+       write_unlock_bh(&rt6_lock);
+       return err;
+ }
+-int ip6_route_del(struct in6_rtmsg *rtmsg, struct nlmsghdr *nlh)
++int ip6_route_del(struct in6_rtmsg *rtmsg, struct nlmsghdr *nlh, struct netlink_skb_parms *req)
+ {
+       struct fib6_node *fn;
+       struct rt6_info *rt;
+@@ -919,7 +920,7 @@
+                       dst_hold(&rt->u.dst);
+                       read_unlock_bh(&rt6_lock);
+-                      return ip6_del_rt(rt, nlh);
++                      return ip6_del_rt(rt, nlh, req);
+               }
+       }
+       read_unlock_bh(&rt6_lock);
+@@ -1021,11 +1022,11 @@
+               rt->u.dst.advmss = 65535;
+       nrt->rt6i_hoplimit = ipv6_get_hoplimit(neigh->dev);
+-      if (rt6_ins(nrt, NULL))
++      if (rt6_ins(nrt, NULL, NULL))
+               goto out;
+       if (rt->rt6i_flags&RTF_CACHE) {
+-              ip6_del_rt(rt, NULL);
++              ip6_del_rt(rt, NULL, NULL);
+               return;
+       }
+@@ -1087,7 +1088,7 @@
+          2. It is gatewayed route or NONEXTHOP route. Action: clone it.
+        */
+       if (!rt->rt6i_nexthop && !(rt->rt6i_flags & RTF_NONEXTHOP)) {
+-              nrt = rt6_cow(rt, daddr, saddr);
++              nrt = rt6_cow(rt, daddr, saddr, NULL);
+               if (!nrt->u.dst.error) {
+                       nrt->u.dst.pmtu = pmtu;
+                       /* According to RFC 1981, detecting PMTU increase shouldn't be
+@@ -1111,7 +1112,7 @@
+               dst_set_expires(&nrt->u.dst, ip6_rt_mtu_expires);
+               nrt->rt6i_flags |= RTF_DYNAMIC|RTF_CACHE|RTF_EXPIRES;
+               nrt->u.dst.pmtu = pmtu;
+-              rt6_ins(nrt, NULL);
++              rt6_ins(nrt, NULL, NULL);
+       }
+ out:
+@@ -1184,7 +1185,7 @@
+       rtmsg.rtmsg_ifindex = dev->ifindex;
+-      ip6_route_add(&rtmsg, NULL);
++      ip6_route_add(&rtmsg, NULL, NULL);
+       return rt6_get_dflt_router(gwaddr, dev);
+ }
+@@ -1210,7 +1211,7 @@
+                       read_unlock_bh(&rt6_lock);
+-                      ip6_del_rt(rt, NULL);
++                      ip6_del_rt(rt, NULL, NULL);
+                       goto restart;
+               }
+@@ -1236,10 +1237,10 @@
+               rtnl_lock();
+               switch (cmd) {
+               case SIOCADDRT:
+-                      err = ip6_route_add(&rtmsg, NULL);
++                      err = ip6_route_add(&rtmsg, NULL, NULL);
+                       break;
+               case SIOCDELRT:
+-                      err = ip6_route_del(&rtmsg, NULL);
++                      err = ip6_route_del(&rtmsg, NULL, NULL);
+                       break;
+               default:
+                       err = -EINVAL;
+@@ -1296,7 +1297,7 @@
+       ipv6_addr_copy(&rt->rt6i_dst.addr, addr);
+       rt->rt6i_dst.plen = 128;
+-      rt6_ins(rt, NULL);
++      rt6_ins(rt, NULL, NULL);
+       return 0;
+ }
+@@ -1313,7 +1314,7 @@
+       rt = rt6_lookup(addr, NULL, loopback_dev.ifindex, 1);
+       if (rt) {
+               if (rt->rt6i_dst.plen == 128)
+-                      err = ip6_del_rt(rt, NULL);
++                      err = ip6_del_rt(rt, NULL, NULL);
+               else
+                       dst_release(&rt->u.dst);
+       }
+@@ -1429,7 +1430,7 @@
+       nrt->rt6i_flags |= RTF_CACHE;
+       dst_hold(&nrt->u.dst);
+-      err = rt6_ins(nrt, NULL);
++      err = rt6_ins(nrt, NULL, NULL);
+       if (err)
+               nrt->u.dst.error = err;
+       return nrt;
+@@ -1556,7 +1557,7 @@
+       if (inet6_rtm_to_rtmsg(r, arg, &rtmsg))
+               return -EINVAL;
+-      return ip6_route_del(&rtmsg, nlh);
++      return ip6_route_del(&rtmsg, nlh, &NETLINK_CB(skb));
+ }
+ int inet6_rtm_newroute(struct sk_buff *skb, struct nlmsghdr* nlh, void *arg)
+@@ -1566,7 +1567,7 @@
+       if (inet6_rtm_to_rtmsg(r, arg, &rtmsg))
+               return -EINVAL;
+-      return ip6_route_add(&rtmsg, nlh);
++      return ip6_route_add(&rtmsg, nlh, &NETLINK_CB(skb));
+ }
+ struct rt6_rtnl_dump_arg
+@@ -1576,11 +1577,8 @@
+ };
+ static int rt6_fill_node(struct sk_buff *skb, struct rt6_info *rt,
+-                       struct in6_addr *dst,
+-                       struct in6_addr *src,
+-                       int iif,
+-                       int type, u32 pid, u32 seq,
+-                       struct nlmsghdr *in_nlh, int prefix)
++                       struct in6_addr *dst, struct in6_addr *src,
++                       int iif, int type, u32 pid, u32 seq, int prefix)
+ {
+       struct rtmsg *rtm;
+       struct nlmsghdr  *nlh;
+@@ -1593,9 +1591,6 @@
+                       return 1;
+               }
+       }
+-      if (!pid && in_nlh) {
+-              pid = in_nlh->nlmsg_pid;
+-      }
+       nlh = NLMSG_PUT(skb, pid, seq, type, sizeof(*rtm));
+       rtm = NLMSG_DATA(nlh);
+@@ -1683,7 +1678,7 @@
+       return rt6_fill_node(arg->skb, rt, NULL, NULL, 0, RTM_NEWROUTE,
+                    NETLINK_CB(arg->cb->skb).pid, arg->cb->nlh->nlmsg_seq,
+-                   NULL, prefix);
++                   prefix);
+ }
+ static int fib6_dump_node(struct fib6_walker_t *w)
+@@ -1834,7 +1829,7 @@
+                           fl.nl_u.ip6_u.saddr,
+                           iif,
+                           RTM_NEWROUTE, NETLINK_CB(in_skb).pid,
+-                          nlh->nlmsg_seq, nlh, 0);
++                          nlh->nlmsg_seq, 0);
+       if (err < 0) {
+               err = -EMSGSIZE;
+               goto out_free;
+@@ -1850,17 +1845,25 @@
+       goto out;       
+ }
+-void inet6_rt_notify(int event, struct rt6_info *rt, struct nlmsghdr *nlh)
++void inet6_rt_notify(int event, struct rt6_info *rt, struct nlmsghdr *nlh,
++                    struct netlink_skb_parms *req)
+ {
+       struct sk_buff *skb;
+       int size = NLMSG_SPACE(sizeof(struct rtmsg)+256);
++      u32 pid = current->pid;
++      u32 seq = 0;
++
++      if (req)
++              pid = req->pid;
++      if (nlh)
++              seq = nlh->nlmsg_seq;
+       skb = alloc_skb(size, gfp_any());
+       if (!skb) {
+               netlink_set_err(rtnl, 0, RTMGRP_IPV6_ROUTE, ENOBUFS);
+               return;
+       }
+-      if (rt6_fill_node(skb, rt, NULL, NULL, 0, event, 0, 0, nlh, 0) < 0) {
++      if (rt6_fill_node(skb, rt, NULL, NULL, 0, event, pid, seq, 0) < 0) {
+               kfree_skb(skb);
+               netlink_set_err(rtnl, 0, RTMGRP_IPV6_ROUTE, EINVAL);
+               return;
+diff -urN linux-2.4.30/net/ipv6/udp.c linux-2.4.30-hf32.3/net/ipv6/udp.c
+--- linux-2.4.30/net/ipv6/udp.c        2004-11-17 12:54:22.000000000 +0100
++++ linux-2.4.30-hf32.3/net/ipv6/udp.c 2006-03-18 00:34:06.000000000 +0100
+@@ -89,7 +89,7 @@
+               next:;
+               }
+               result = best;
+-              for(;; result += UDP_HTABLE_SIZE) {
++              for(i = 0; i < (1 << 16) / UDP_HTABLE_SIZE; i++, result += UDP_HTABLE_SIZE) {
+                       if (result > sysctl_local_port_range[1])
+                               result = sysctl_local_port_range[0]
+                                       + ((result - sysctl_local_port_range[0]) &
+@@ -97,6 +97,8 @@
+                       if (!udp_lport_inuse(result))
+                               break;
+               }
++              if (i >= (1 << 16) / UDP_HTABLE_SIZE)
++                      goto fail;
+ gotit:
+               udp_port_rover = snum = result;
+       } else {
+diff -urN linux-2.4.30/net/netlink/af_netlink.c linux-2.4.30-hf32.3/net/netlink/af_netlink.c
+--- linux-2.4.30/net/netlink/af_netlink.c      2005-04-14 09:43:35.000000000 +0200
++++ linux-2.4.30-hf32.3/net/netlink/af_netlink.c       2006-03-18 00:34:06.000000000 +0100
+@@ -330,9 +330,9 @@
+       u32 pid = nlk_sk(sk)->pid;
+       netlink_table_grab();
+-      hash->entries--;
+       for (skp = nl_pid_hashfn(hash, pid); *skp; skp = &((*skp)->next)) {
+               if (*skp == sk) {
++                      hash->entries--;
+                       *skp = sk->next;
+                       __sock_put(sk);
+                       break;
+@@ -450,7 +450,12 @@
+       err = netlink_insert(sk, pid);
+       if (err == -EADDRINUSE)
+               goto retry;
+-      return 0;
++
++      /* If 2 threads race to autobind, that is fine.  */
++      if (err == -EBUSY)
++              err = 0;
++
++      return err;
+ }
+ static inline int netlink_capable(struct socket *sock, unsigned int flag)