diff -Naurp linux-2.2.25/ChangeLog-2.2.26 linux-2.2.26/ChangeLog-2.2.26 --- linux-2.2.25/ChangeLog-2.2.26 1970-01-01 01:00:00.000000000 +0100 +++ linux-2.2.26/ChangeLog-2.2.26 2004-02-24 19:03:01.000000000 +0100 @@ -0,0 +1,36 @@ +Kernel 2.2.xx Mainline +---------------------- +Person: Marc-Christian Petersen +EMail: m.c.p@wolk-project.de +Mailinglist: linux-kernel@vger.kernel.org +Website: http://www.kernel.org/pub/linux/kernel/people/mcp/ +Status: Maintained +Employed by: Linux-Systeme GmbH, http://www.linux-systeme.de/ + + + Thanks to Alan Cox 8-) + + +------------------------------------------------------------------------- +If you need a more secured, more stable, even faster, better SMP support, +IDE LBA48 support, LFS support, IPSec support, HTB support, IPVS support +etc. enabled kernel with many more features and important fixes, please +use my 2.2-secure tree. +You may find more informations about it at http://www.wolk-project.de. +------------------------------------------------------------------------- + + + +2.2.26 +------ +o CAN-2004-0077: behave safely in case of do_munmap() (Solar Designer) + failures in mremap(2) +o CAN-2003-0984: /dev/rtc can leak parts of kernel (Solar Designer) + memory to unprivileged users (2.4 backport) +o CAN-2003-0244: hashing exploits in network stack (David S. Miller) +o update_atime() performance improvement (2.4 backport) (Solar Designer) +o ability to swapoff after a device file might (Solar Designer) + have been re-created +o MAINTAINERS correction for Kernel 2.2 and 2.2 fixes (me) +o fixed some typos (Solar Designer, me) + diff -Naurp linux-2.2.25/MAINTAINERS linux-2.2.26/MAINTAINERS --- linux-2.2.25/MAINTAINERS 2004-02-23 12:37:06.000000000 +0100 +++ linux-2.2.26/MAINTAINERS 2004-02-24 19:00:05.000000000 +0100 @@ -561,11 +561,11 @@ L: linux-hams@vger.kernel.org S: Maintained KERNEL (2.2.XX TREE) -P: Alan Cox -M: Alan.Cox@linux.org -L: linux-kernel@vger.kernel.org -W: http://www.kernel.org/pub/linux/kernel/alan/ -S: Maintained +P: Marc-Christian Petersen +M: m.c.p@wolk-project.de +L: linux-kernel@vger.kernel.org +W: http://www.kernel.org/pub/linux/kernel/people/mcp/ +S: Maintained KERNEL AUTOMOUNTER (AUTOFS) P: H. Peter Anvin @@ -1172,8 +1172,8 @@ W: http://cvs.conectiva.com.br/drivers/Z S: Maintained LINUX 2.2 FIXES -P: Alan Cox -M: alan@lxorguk.ukuu.org.uk +P: Marc-Christian Petersen +M: m.c.p@wolk-project.de S: Maintained THE REST diff -Naurp linux-2.2.25/Makefile linux-2.2.26/Makefile --- linux-2.2.25/Makefile 2004-02-23 12:37:08.000000000 +0100 +++ linux-2.2.26/Makefile 2004-02-24 19:04:07.000000000 +0100 @@ -1,6 +1,6 @@ VERSION = 2 PATCHLEVEL = 2 -SUBLEVEL = 25 +SUBLEVEL = 26 EXTRAVERSION = ARCH := $(shell uname -m | sed -e s/i.86/i386/ -e s/sun4u/sparc64/ -e s/arm.*/arm/ -e s/sa110/arm/) diff -Naurp linux-2.2.25/arch/i386/kernel/traps.c linux-2.2.26/arch/i386/kernel/traps.c --- linux-2.2.25/arch/i386/kernel/traps.c 2004-02-23 12:37:04.000000000 +0100 +++ linux-2.2.26/arch/i386/kernel/traps.c 2004-02-24 14:48:05.000000000 +0100 @@ -389,7 +389,7 @@ asmlinkage void do_debug(struct pt_regs goto clear_TF; } - /* Mast out spurious debug traps due to lazy DR7 setting */ + /* Mask out spurious debug traps due to lazy DR7 setting */ if (condition & (DR_TRAP0|DR_TRAP1|DR_TRAP2|DR_TRAP3)) { if (!tsk->tss.debugreg[7]) goto clear_dr7; diff -Naurp linux-2.2.25/arch/i386/mm/fault.c linux-2.2.26/arch/i386/mm/fault.c --- linux-2.2.25/arch/i386/mm/fault.c 2001-03-25 18:31:45.000000000 +0200 +++ linux-2.2.26/arch/i386/mm/fault.c 2004-02-24 14:48:05.000000000 +0100 @@ -212,7 +212,7 @@ bad_area: /* User mode accesses just cause a SIGSEGV */ if (error_code & 4) { tsk->tss.cr2 = address; - tsk->tss.error_code = error_code; + tsk->tss.error_code = error_code | (address >= TASK_SIZE); tsk->tss.trap_no = 14; force_sig(SIGSEGV, tsk); return; diff -Naurp linux-2.2.25/arch/m68k/bvme6000/rtc.c linux-2.2.26/arch/m68k/bvme6000/rtc.c --- linux-2.2.25/arch/m68k/bvme6000/rtc.c 2001-03-25 18:31:52.000000000 +0200 +++ linux-2.2.26/arch/m68k/bvme6000/rtc.c 2004-02-24 14:48:05.000000000 +0100 @@ -53,6 +53,7 @@ static int rtc_ioctl(struct inode *inode /* Ensure clock and real-time-mode-register are accessible */ msr = rtc->msr & 0xc0; rtc->msr = 0x40; + memset(&wtime, 0, sizeof(wtime)); do { wtime.tm_sec = BCD2BIN(rtc->bcd_sec); wtime.tm_min = BCD2BIN(rtc->bcd_min); diff -Naurp linux-2.2.25/arch/m68k/mvme16x/rtc.c linux-2.2.26/arch/m68k/mvme16x/rtc.c --- linux-2.2.25/arch/m68k/mvme16x/rtc.c 2001-03-25 18:31:52.000000000 +0200 +++ linux-2.2.26/arch/m68k/mvme16x/rtc.c 2004-02-24 14:48:05.000000000 +0100 @@ -51,6 +51,7 @@ static int rtc_ioctl(struct inode *inode cli(); /* Ensure clock and real-time-mode-register are accessible */ rtc->ctrl = RTC_READ; + memset(&wtime, 0, sizeof(wtime)); wtime.tm_sec = BCD2BIN(rtc->bcd_sec); wtime.tm_min = BCD2BIN(rtc->bcd_min); wtime.tm_hour = BCD2BIN(rtc->bcd_hr); diff -Naurp linux-2.2.25/drivers/char/rtc.c linux-2.2.26/drivers/char/rtc.c --- linux-2.2.25/drivers/char/rtc.c 2004-02-23 12:37:06.000000000 +0100 +++ linux-2.2.26/drivers/char/rtc.c 2004-02-24 14:48:05.000000000 +0100 @@ -250,6 +250,7 @@ static int rtc_ioctl(struct inode *inode * tm_min, and tm_sec values are filled in. */ + memset(&wtime, 0, sizeof(wtime)); get_rtc_alm_time(&wtime); break; } @@ -293,6 +294,7 @@ static int rtc_ioctl(struct inode *inode } case RTC_RD_TIME: /* Read the time/date from RTC */ { + memset(&wtime, 0, sizeof(wtime)); get_rtc_time(&wtime); break; } diff -Naurp linux-2.2.25/drivers/macintosh/rtc.c linux-2.2.26/drivers/macintosh/rtc.c --- linux-2.2.25/drivers/macintosh/rtc.c 2001-03-25 18:31:41.000000000 +0200 +++ linux-2.2.26/drivers/macintosh/rtc.c 2004-02-24 14:48:05.000000000 +0100 @@ -73,6 +73,7 @@ static int rtc_ioctl(struct inode *inode case RTC_RD_TIME: if (ppc_md.get_rtc_time) { + memset(&rtc_tm, 0, sizeof(rtc_tm)); get_rtc_time(&rtc_tm); copy_to_user_ret((struct rtc_time*)arg, &rtc_tm, sizeof(struct rtc_time), -EFAULT); diff -Naurp linux-2.2.25/drivers/sbus/char/rtc.c linux-2.2.26/drivers/sbus/char/rtc.c --- linux-2.2.25/drivers/sbus/char/rtc.c 2001-03-25 18:31:39.000000000 +0200 +++ linux-2.2.26/drivers/sbus/char/rtc.c 2004-02-24 14:48:05.000000000 +0100 @@ -83,6 +83,7 @@ static int rtc_ioctl(struct inode *inode switch (cmd) { case RTCGET: + memset(&rtc_tm, 0, sizeof(rtc_tm)); get_rtc_time(&rtc_tm); copy_to_user_ret((struct rtc_time*)arg, &rtc_tm, sizeof(struct rtc_time), -EFAULT); diff -Naurp linux-2.2.25/drivers/sgi/char/ds1286.c linux-2.2.26/drivers/sgi/char/ds1286.c --- linux-2.2.25/drivers/sgi/char/ds1286.c 2001-03-25 18:31:41.000000000 +0200 +++ linux-2.2.26/drivers/sgi/char/ds1286.c 2004-02-24 14:48:05.000000000 +0100 @@ -222,6 +222,7 @@ static int ds1286_ioctl(struct inode *in * tm_min, and tm_sec values are filled in. */ + memset(&wtime, 0, sizeof(wtime)); get_rtc_alm_time(&wtime); break; } @@ -264,6 +265,7 @@ static int ds1286_ioctl(struct inode *in } case RTC_RD_TIME: /* Read the time/date from RTC */ { + memset(&wtime, 0, sizeof(wtime)); get_rtc_time(&wtime); break; } diff -Naurp linux-2.2.25/drivers/sgi/char/graphics.c linux-2.2.26/drivers/sgi/char/graphics.c --- linux-2.2.25/drivers/sgi/char/graphics.c 2001-03-25 18:31:41.000000000 +0200 +++ linux-2.2.26/drivers/sgi/char/graphics.c 2004-02-24 14:48:05.000000000 +0100 @@ -105,7 +105,7 @@ sgi_graphics_ioctl (struct inode *inode, if (board >= boards) return -EINVAL; - if (max_len < sizeof (struct gfx_getboardinfo_args)) + if (max_len < (int)sizeof (struct gfx_getboardinfo_args)) return -EINVAL; if (max_len > cards [board].g_board_info_len) max_len = cards [boards].g_board_info_len; diff -Naurp linux-2.2.25/fs/fat/inode.c linux-2.2.26/fs/fat/inode.c --- linux-2.2.25/fs/fat/inode.c 2002-05-21 01:32:35.000000000 +0200 +++ linux-2.2.26/fs/fat/inode.c 2004-02-24 14:48:05.000000000 +0100 @@ -852,7 +852,8 @@ retry: i_pos = MSDOS_I(inode)->i_location; if (inode->i_ino == MSDOS_ROOT_INO || !i_pos) return; if (!(bh = fat_bread(sb, ((unsigned long long) i_pos) >> MSDOS_DPB_BITS))) { - printk("dev = %s, ino = %ld\n", kdevname(inode->i_dev), i_pos); + printk("dev = %s, ino = %ld\n", + kdevname(inode->i_dev), (long)i_pos); fat_fs_panic(sb, "msdos_write_inode: unable to read i-node block"); return; } diff -Naurp linux-2.2.25/fs/inode.c linux-2.2.26/fs/inode.c --- linux-2.2.25/fs/inode.c 2001-03-25 18:37:38.000000000 +0200 +++ linux-2.2.26/fs/inode.c 2004-02-24 14:48:05.000000000 +0100 @@ -891,6 +891,7 @@ int fs_may_remount_ro(struct super_block void update_atime (struct inode *inode) { + if ( inode->i_atime == CURRENT_TIME ) return; if ( IS_NOATIME (inode) ) return; if ( IS_NODIRATIME (inode) && S_ISDIR (inode->i_mode) ) return; if ( IS_RDONLY (inode) ) return; diff -Naurp linux-2.2.25/fs/proc/array.c linux-2.2.26/fs/proc/array.c --- linux-2.2.25/fs/proc/array.c 2001-03-25 18:37:38.000000000 +0200 +++ linux-2.2.26/fs/proc/array.c 2004-02-24 14:48:05.000000000 +0100 @@ -457,7 +457,7 @@ static int get_array(struct task_struct int size = 0, result = 0; char c; - if (start >= end) + if (!start || start >= end) return result; for (;;) { addr = get_phys_addr(p, start); @@ -1540,8 +1540,7 @@ static ssize_t array_read(struct file * start = NULL; dp = (struct proc_dir_entry *) inode->u.generic_ip; - if (pid && process_unauthorized(type, pid)) - { + if (pid && process_unauthorized(type, pid)) { free_page(page); return -EIO; } @@ -1556,6 +1555,10 @@ static ssize_t array_read(struct file * free_page(page); return length; } + if (pid && process_unauthorized(type, pid)) { + free_page(page); + return -EIO; + } if (start != NULL) { /* We have had block-adjusting processing! */ copy_to_user(buf, start, length); diff -Naurp linux-2.2.25/fs/proc/proc_tty.c linux-2.2.26/fs/proc/proc_tty.c --- linux-2.2.25/fs/proc/proc_tty.c 2002-09-16 18:26:32.000000000 +0200 +++ linux-2.2.26/fs/proc/proc_tty.c 2004-02-24 14:48:05.000000000 +0100 @@ -138,7 +138,7 @@ static int tty_ldiscs_read_proc(char *pa } /* - * Thsi function is called by register_tty_driver() to handle + * This function is called by tty_register_driver() to handle * registering the driver's /proc handler into /proc/tty/driver/ */ void proc_tty_register_driver(struct tty_driver *driver) @@ -161,7 +161,7 @@ void proc_tty_register_driver(struct tty } /* - * This function is called by unregister_tty_driver() + * This function is called by tty_unregister_driver() */ void proc_tty_unregister_driver(struct tty_driver *driver) { diff -Naurp linux-2.2.25/fs/select.c linux-2.2.26/fs/select.c --- linux-2.2.25/fs/select.c 2002-09-16 18:26:32.000000000 +0200 +++ linux-2.2.26/fs/select.c 2004-02-24 14:48:05.000000000 +0100 @@ -265,7 +265,7 @@ sys_select(int n, fd_set *inp, fd_set *o fd_set_bits fds; char *bits; long timeout; - int ret, size; + int ret, size, max_fdset; timeout = MAX_SCHEDULE_TIMEOUT; if (tvp) { @@ -299,8 +299,11 @@ sys_select(int n, fd_set *inp, fd_set *o if (n < 0) goto out_nofds; - if (n > current->files->max_fdset) - n = current->files->max_fdset; + max_fdset = current->files->max_fdset; + if (n > max_fdset) + n = max_fdset; + if (n > NR_OPEN) + n = NR_OPEN; /* * We need 6 bitmaps (in/out/ex for both incoming and outgoing), @@ -412,7 +415,7 @@ asmlinkage int sys_poll(struct pollfd * lock_kernel(); /* Do a sanity check on nfds ... */ err = -EINVAL; - if (nfds > current->files->max_fds || nfds > 0x100000) + if (nfds > current->files->max_fds || nfds > NR_OPEN) goto out; if (timeout) { diff -Naurp linux-2.2.25/include/linux/jhash.h linux-2.2.26/include/linux/jhash.h --- linux-2.2.25/include/linux/jhash.h 1970-01-01 01:00:00.000000000 +0100 +++ linux-2.2.26/include/linux/jhash.h 2004-02-23 13:17:03.000000000 +0100 @@ -0,0 +1,143 @@ +#ifndef _LINUX_JHASH_H +#define _LINUX_JHASH_H + +/* jhash.h: Jenkins hash support. + * + * Copyright (C) 1996 Bob Jenkins (bob_jenkins@burtleburtle.net) + * + * http://burtleburtle.net/bob/hash/ + * + * These are the credits from Bob's sources: + * + * lookup2.c, by Bob Jenkins, December 1996, Public Domain. + * hash(), hash2(), hash3, and mix() are externally useful functions. + * Routines to test the hash are included if SELF_TEST is defined. + * You can use this free for any purpose. It has no warranty. + * + * Copyright (C) 2003 David S. Miller (davem@redhat.com) + * + * I've modified Bob's hash to be useful in the Linux kernel, and + * any bugs present are surely my fault. -DaveM + */ + +/* NOTE: Arguments are modified. */ +#define __jhash_mix(a, b, c) \ +{ \ + a -= b; a -= c; a ^= (c>>13); \ + b -= c; b -= a; b ^= (a<<8); \ + c -= a; c -= b; c ^= (b>>13); \ + a -= b; a -= c; a ^= (c>>12); \ + b -= c; b -= a; b ^= (a<<16); \ + c -= a; c -= b; c ^= (b>>5); \ + a -= b; a -= c; a ^= (c>>3); \ + b -= c; b -= a; b ^= (a<<10); \ + c -= a; c -= b; c ^= (b>>15); \ +} + +/* The golden ration: an arbitrary value */ +#define JHASH_GOLDEN_RATIO 0x9e3779b9 + +/* The most generic version, hashes an arbitrary sequence + * of bytes. No alignment or length assumptions are made about + * the input key. + */ +static inline u32 jhash(void *key, u32 length, u32 initval) +{ + u32 a, b, c, len; + u8 *k = key; + + len = length; + a = b = JHASH_GOLDEN_RATIO; + c = initval; + + while (len >= 12) { + a += (k[0] +((u32)k[1]<<8) +((u32)k[2]<<16) +((u32)k[3]<<24)); + b += (k[4] +((u32)k[5]<<8) +((u32)k[6]<<16) +((u32)k[7]<<24)); + c += (k[8] +((u32)k[9]<<8) +((u32)k[10]<<16)+((u32)k[11]<<24)); + + __jhash_mix(a,b,c); + + k += 12; + len -= 12; + } + + c += length; + switch (len) { + case 11: c += ((u32)k[10]<<24); + case 10: c += ((u32)k[9]<<16); + case 9 : c += ((u32)k[8]<<8); + case 8 : b += ((u32)k[7]<<24); + case 7 : b += ((u32)k[6]<<16); + case 6 : b += ((u32)k[5]<<8); + case 5 : b += k[4]; + case 4 : a += ((u32)k[3]<<24); + case 3 : a += ((u32)k[2]<<16); + case 2 : a += ((u32)k[1]<<8); + case 1 : a += k[0]; + }; + + __jhash_mix(a,b,c); + + return c; +} + +/* A special optimized version that handles 1 or more of u32s. + * The length parameter here is the number of u32s in the key. + */ +static inline u32 jhash2(u32 *k, u32 length, u32 initval) +{ + u32 a, b, c, len; + + a = b = JHASH_GOLDEN_RATIO; + c = initval; + len = length; + + while (len >= 3) { + a += k[0]; + b += k[1]; + c += k[2]; + __jhash_mix(a, b, c); + k += 3; len -= 3; + } + + c += length * 4; + + switch (len) { + case 2 : b += k[1]; + case 1 : a += k[0]; + }; + + __jhash_mix(a,b,c); + + return c; +} + + +/* A special ultra-optimized versions that knows they are hashing exactly + * 3, 2 or 1 word(s). + * + * NOTE: In partilar the "c += length; __jhash_mix(a,b,c);" normally + * done at the end is not done here. + */ +static inline u32 jhash_3words(u32 a, u32 b, u32 c, u32 initval) +{ + a += JHASH_GOLDEN_RATIO; + b += JHASH_GOLDEN_RATIO; + c += initval; + + __jhash_mix(a, b, c); + + return c; +} + +static inline u32 jhash_2words(u32 a, u32 b, u32 initval) +{ + return jhash_3words(a, b, 0, initval); +} + +static inline u32 jhash_1word(u32 a, u32 initval) +{ + return jhash_3words(a, 0, 0, initval); +} + +#endif /* _LINUX_JHASH_H */ diff -Naurp linux-2.2.25/include/linux/sysctl.h linux-2.2.26/include/linux/sysctl.h --- linux-2.2.25/include/linux/sysctl.h 2001-03-25 18:37:40.000000000 +0200 +++ linux-2.2.26/include/linux/sysctl.h 2004-02-23 13:17:03.000000000 +0100 @@ -249,7 +249,8 @@ enum { NET_IPV4_ROUTE_ERROR_COST=12, NET_IPV4_ROUTE_ERROR_BURST=13, NET_IPV4_ROUTE_GC_ELASTICITY=14, - NET_IPV4_ROUTE_MTU_EXPIRES=15 + NET_IPV4_ROUTE_MTU_EXPIRES=15, + NET_IPV4_ROUTE_SECRET_INTERVAL=16, }; enum diff -Naurp linux-2.2.25/mm/mmap.c linux-2.2.26/mm/mmap.c --- linux-2.2.25/mm/mmap.c 2001-03-25 18:31:02.000000000 +0200 +++ linux-2.2.26/mm/mmap.c 2004-02-24 14:48:05.000000000 +0100 @@ -610,7 +610,7 @@ int do_munmap(unsigned long addr, size_t struct mm_struct * mm; struct vm_area_struct *mpnt, *prev, **npp, *free, *extra; - if ((addr & ~PAGE_MASK) || addr > TASK_SIZE || len > TASK_SIZE-addr) + if ((addr & ~PAGE_MASK) || addr >= TASK_SIZE || len > TASK_SIZE-addr) return -EINVAL; if ((len = PAGE_ALIGN(len)) == 0) diff -Naurp linux-2.2.25/mm/mremap.c linux-2.2.26/mm/mremap.c --- linux-2.2.25/mm/mremap.c 2001-03-25 18:31:03.000000000 +0200 +++ linux-2.2.26/mm/mremap.c 2004-02-24 14:48:05.000000000 +0100 @@ -90,7 +90,6 @@ static int move_page_tables(struct mm_st unsigned long offset = len; flush_cache_range(mm, old_addr, old_addr + len); - flush_tlb_range(mm, old_addr, old_addr + len); /* * This is not the clever way to do this, but we're taking the @@ -102,6 +101,7 @@ static int move_page_tables(struct mm_st if (move_one_page(mm, old_addr + offset, new_addr + offset)) goto oops_we_failed; } + flush_tlb_range(mm, old_addr, old_addr + len); return 0; /* @@ -140,6 +140,7 @@ static inline unsigned long move_vma(str new_vma->vm_ops->open(new_vma); insert_vm_struct(current->mm, new_vma); merge_segments(current->mm, new_vma->vm_start, new_vma->vm_end); + /* XXX: possible errors masked, mapping might remain */ do_munmap(addr, old_len); current->mm->total_vm += new_len >> PAGE_SHIFT; if (new_vma->vm_flags & VM_LOCKED) { @@ -172,16 +173,26 @@ asmlinkage unsigned long sys_mremap(unsi old_len = PAGE_ALIGN(old_len); new_len = PAGE_ALIGN(new_len); + if (old_len > TASK_SIZE || addr > TASK_SIZE - old_len) + goto out; + + if (addr >= TASK_SIZE) + goto out; + /* * Always allow a shrinking remap: that just unmaps * the unnecessary pages.. */ - ret = addr; if (old_len >= new_len) { - do_munmap(addr+new_len, old_len - new_len); + ret = do_munmap(addr+new_len, old_len - new_len); + if (!ret || old_len == new_len) + ret = addr; goto out; } + if (new_len > TASK_SIZE || addr > TASK_SIZE - new_len) + goto out; + /* * Ok, we need to grow.. */ diff -Naurp linux-2.2.25/mm/swapfile.c linux-2.2.26/mm/swapfile.c --- linux-2.2.25/mm/swapfile.c 2001-11-02 17:39:16.000000000 +0100 +++ linux-2.2.26/mm/swapfile.c 2004-02-24 14:48:05.000000000 +0100 @@ -367,14 +367,11 @@ asmlinkage int sys_swapoff(const char * for (type = swap_list.head; type >= 0; type = swap_info[type].next) { p = swap_info + type; if ((p->flags & SWP_WRITEOK) == SWP_WRITEOK) { - if (p->swap_file) { - if (p->swap_file == dentry) - break; - } else { - if (S_ISBLK(dentry->d_inode->i_mode) - && (p->swap_device == dentry->d_inode->i_rdev)) - break; - } + if (p->swap_file == dentry) + break; + if (S_ISBLK(dentry->d_inode->i_mode) && + p->swap_device == dentry->d_inode->i_rdev) + break; } prev = type; } diff -Naurp linux-2.2.25/net/ipv4/af_inet.c linux-2.2.26/net/ipv4/af_inet.c --- linux-2.2.25/net/ipv4/af_inet.c 2001-11-02 17:39:16.000000000 +0100 +++ linux-2.2.26/net/ipv4/af_inet.c 2004-02-23 13:17:03.000000000 +0100 @@ -1060,6 +1060,7 @@ static struct proc_dir_entry proc_net_ud extern void tcp_init(void); extern void tcp_v4_init(struct net_proto_family *); +extern void ipfrag_init(void); /* @@ -1168,4 +1169,6 @@ __initfunc(void inet_proto_init(struct n proc_net_register(&proc_net_tcp); proc_net_register(&proc_net_udp); #endif /* CONFIG_PROC_FS */ + + ipfrag_init(); } diff -Naurp linux-2.2.25/net/ipv4/ip_fragment.c linux-2.2.26/net/ipv4/ip_fragment.c --- linux-2.2.25/net/ipv4/ip_fragment.c 2001-03-25 18:31:12.000000000 +0200 +++ linux-2.2.26/net/ipv4/ip_fragment.c 2004-02-23 13:17:03.000000000 +0100 @@ -27,6 +27,8 @@ #include #include #include +#include +#include #include #include #include @@ -72,9 +74,53 @@ struct ipq { #define IPQ_HASHSZ 64 struct ipq *ipq_hash[IPQ_HASHSZ]; +static u32 ipfrag_hash_rnd; -#define ipqhashfn(id, saddr, daddr, prot) \ - ((((id) >> 1) ^ (saddr) ^ (daddr) ^ (prot)) & (IPQ_HASHSZ - 1)) +static unsigned int ipqhashfn(u16 id, u32 saddr, u32 daddr, u8 prot) +{ + return jhash_3words((u32)id << 16 | prot, saddr, daddr, + ipfrag_hash_rnd) & (IPQ_HASHSZ - 1); +} + +static struct timer_list ipfrag_secret_timer; +static int ipfrag_secret_interval = 10 * 60 * HZ; + +static void ipfrag_secret_rebuild(unsigned long dummy) +{ + unsigned long now = jiffies; + int i; + + get_random_bytes(&ipfrag_hash_rnd, sizeof(u32)); + for (i = 0; i < IPQ_HASHSZ; i++) { + struct ipq *q; + + q = ipq_hash[i]; + while (q) { + struct ipq *next = q->next; + unsigned int hval = ipqhashfn(q->iph->id, + q->iph->saddr, + q->iph->daddr, + q->iph->protocol); + + if (hval != i) { + /* Unlink. */ + if (q->next) + q->next->pprev = q->pprev; + *q->pprev = q->next; + + /* Relink to new hash chain. */ + if ((q->next = ipq_hash[hval]) != NULL) + q->next->pprev = &q->next; + ipq_hash[hval] = q; + q->pprev = &ipq_hash[hval]; + } + + q = next; + } + } + + mod_timer(&ipfrag_secret_timer, now + ipfrag_secret_interval); +} atomic_t ip_frag_mem = ATOMIC_INIT(0); /* Memory used for fragments */ @@ -409,6 +455,17 @@ out_fail: return NULL; } +void ipfrag_init(void) +{ + ipfrag_hash_rnd = (u32) ((num_physpages ^ (num_physpages>>7)) ^ + (jiffies ^ (jiffies >> 6))); + + init_timer(&ipfrag_secret_timer); + ipfrag_secret_timer.function = ipfrag_secret_rebuild; + ipfrag_secret_timer.expires = jiffies + ipfrag_secret_interval; + add_timer(&ipfrag_secret_timer); +} + /* Process an incoming IP datagram fragment. */ struct sk_buff *ip_defrag(struct sk_buff *skb) { diff -Naurp linux-2.2.25/net/ipv4/route.c linux-2.2.26/net/ipv4/route.c --- linux-2.2.25/net/ipv4/route.c 2002-09-16 18:26:34.000000000 +0200 +++ linux-2.2.26/net/ipv4/route.c 2004-02-23 13:17:03.000000000 +0100 @@ -82,6 +82,8 @@ #include #include #include +#include +#include #include #include #include @@ -112,7 +114,7 @@ int ip_rt_error_cost = HZ; int ip_rt_error_burst = 5*HZ; int ip_rt_gc_elasticity = 8; int ip_rt_mtu_expires = 10*60*HZ; - +int ip_rt_secret_interval = 10*60*HZ; static unsigned long rt_deadline = 0; #define RTprint(a...) printk(KERN_DEBUG a) @@ -123,6 +125,8 @@ static struct timer_list rt_flush_timer { NULL, NULL, 0, 0L, rt_run_flush }; static struct timer_list rt_periodic_timer = { NULL, NULL, 0, 0L, NULL }; +static struct timer_list rt_secret_timer = + { NULL, NULL, 0, 0L, NULL }; /* * Interface to generic destination cache. @@ -174,16 +178,14 @@ __u8 ip_tos2prio[16] = { * Route cache. */ -struct rtable *rt_hash_table[RT_HASH_DIVISOR]; +struct rtable *rt_hash_table[RT_HASH_DIVISOR]; +static unsigned int rt_hash_rnd; static int rt_intern_hash(unsigned hash, struct rtable * rth, struct rtable ** res); -static __inline__ unsigned rt_hash_code(u32 daddr, u32 saddr, u8 tos) +static unsigned rt_hash_code(u32 daddr, u32 saddr, u8 tos) { - unsigned hash = ((daddr&0xF0F0F0F0)>>4)|((daddr&0x0F0F0F0F)<<4); - hash = hash^saddr^tos; - hash = hash^(hash>>16); - return (hash^(hash>>8)) & 0xFF; + return (jhash_3words(daddr, saddr, (u32) tos, rt_hash_rnd) & 0xFF); } #ifdef CONFIG_PROC_FS @@ -341,6 +343,8 @@ static void rt_run_flush(unsigned long d rt_deadline = 0; + get_random_bytes(&rt_hash_rnd, 4); + start_bh_atomic(); for (i=0; i