--- /dev/null
+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)