diff -urNp linux-2.6.10/arch/mips/kernel/irixelf.c linux-2.6.10-new/arch/mips/kernel/irixelf.c --- linux-2.6.10/arch/mips/kernel/irixelf.c 2005-01-07 10:51:20 -0500 +++ linux-2.6.10-new/arch/mips/kernel/irixelf.c 2005-01-07 11:21:06 -0500 @@ -127,7 +127,7 @@ static void set_brk(unsigned long start, end = PAGE_ALIGN(end); if (end <= start) return; - do_brk(start, end - start); + do_brk_locked(start, end - start); } @@ -375,7 +375,7 @@ static unsigned int load_irix_interp(str /* Map the last of the bss segment */ if (last_bss > len) { - do_brk(len, (last_bss - len)); + do_brk_locked(len, (last_bss - len)); } kfree(elf_phdata); @@ -562,7 +562,7 @@ void irix_map_prda_page (void) unsigned long v; struct prda *pp; - v = do_brk (PRDA_ADDRESS, PAGE_SIZE); + v = do_brk_locked (PRDA_ADDRESS, PAGE_SIZE); if (v < 0) return; @@ -853,7 +853,7 @@ static int load_irix_library(struct file len = (elf_phdata->p_filesz + elf_phdata->p_vaddr+ 0xfff) & 0xfffff000; bss = elf_phdata->p_memsz + elf_phdata->p_vaddr; if (bss > len) - do_brk(len, bss-len); + do_brk_locked(len, bss-len); kfree(elf_phdata); return 0; } diff -urNp linux-2.6.10/arch/sparc64/kernel/binfmt_aout32.c linux-2.6.10-new/arch/sparc64/kernel/binfmt_aout32.c --- linux-2.6.10/arch/sparc64/kernel/binfmt_aout32.c 2005-01-07 10:51:20 -0500 +++ linux-2.6.10-new/arch/sparc64/kernel/binfmt_aout32.c 2005-01-07 11:19:46 -0500 @@ -49,7 +49,7 @@ static void set_brk(unsigned long start, end = PAGE_ALIGN(end); if (end <= start) return; - do_brk(start, end - start); + do_brk_locked(start, end - start); } /* @@ -246,10 +246,10 @@ static int load_aout32_binary(struct lin if (N_MAGIC(ex) == NMAGIC) { loff_t pos = fd_offset; /* Fuck me plenty... */ - error = do_brk(N_TXTADDR(ex), ex.a_text); + error = do_brk_locked(N_TXTADDR(ex), ex.a_text); bprm->file->f_op->read(bprm->file, (char __user *)N_TXTADDR(ex), ex.a_text, &pos); - error = do_brk(N_DATADDR(ex), ex.a_data); + error = do_brk_locked(N_DATADDR(ex), ex.a_data); bprm->file->f_op->read(bprm->file, (char __user *)N_DATADDR(ex), ex.a_data, &pos); goto beyond_if; @@ -257,7 +257,7 @@ static int load_aout32_binary(struct lin if (N_MAGIC(ex) == OMAGIC) { loff_t pos = fd_offset; - do_brk(N_TXTADDR(ex) & PAGE_MASK, + do_brk_locked(N_TXTADDR(ex) & PAGE_MASK, ex.a_text+ex.a_data + PAGE_SIZE - 1); bprm->file->f_op->read(bprm->file, (char __user *)N_TXTADDR(ex), ex.a_text+ex.a_data, &pos); @@ -272,7 +272,7 @@ static int load_aout32_binary(struct lin if (!bprm->file->f_op->mmap) { loff_t pos = fd_offset; - do_brk(0, ex.a_text+ex.a_data); + do_brk_locked(0, ex.a_text+ex.a_data); bprm->file->f_op->read(bprm->file, (char __user *)N_TXTADDR(ex), ex.a_text+ex.a_data, &pos); @@ -389,7 +389,7 @@ static int load_aout32_library(struct fi len = PAGE_ALIGN(ex.a_text + ex.a_data); bss = ex.a_text + ex.a_data + ex.a_bss; if (bss > len) { - error = do_brk(start_addr + len, bss - len); + error = do_brk_locked(start_addr + len, bss - len); retval = error; if (error != start_addr + len) goto out; diff -urNp linux-2.6.10/arch/x86_64/ia32/ia32_aout.c linux-2.6.10-new/arch/x86_64/ia32/ia32_aout.c --- linux-2.6.10/arch/x86_64/ia32/ia32_aout.c 2005-01-07 10:51:21 -0500 +++ linux-2.6.10-new/arch/x86_64/ia32/ia32_aout.c 2005-01-07 11:22:38 -0500 @@ -114,7 +114,7 @@ static void set_brk(unsigned long start, end = PAGE_ALIGN(end); if (end <= start) return; - do_brk(start, end - start); + do_brk_locked(start, end - start); } #if CORE_DUMP @@ -324,7 +324,7 @@ static int load_aout_binary(struct linux pos = 32; map_size = ex.a_text+ex.a_data; - error = do_brk(text_addr & PAGE_MASK, map_size); + error = do_brk_locked(text_addr & PAGE_MASK, map_size); if (error != (text_addr & PAGE_MASK)) { send_sig(SIGKILL, current, 0); return error; @@ -360,7 +360,7 @@ static int load_aout_binary(struct linux if (!bprm->file->f_op->mmap||((fd_offset & ~PAGE_MASK) != 0)) { loff_t pos = fd_offset; - do_brk(N_TXTADDR(ex), ex.a_text+ex.a_data); + do_brk_locked(N_TXTADDR(ex), ex.a_text+ex.a_data); bprm->file->f_op->read(bprm->file,(char *)N_TXTADDR(ex), ex.a_text+ex.a_data, &pos); flush_icache_range((unsigned long) N_TXTADDR(ex), @@ -469,7 +469,8 @@ static int load_aout_library(struct file } #endif - do_brk(start_addr, ex.a_text + ex.a_data + ex.a_bss); + do_brk_locked(start_addr, ex.a_text + ex.a_data + +ex.a_bss); file->f_op->read(file, (char *)start_addr, ex.a_text + ex.a_data, &pos); @@ -493,7 +494,7 @@ static int load_aout_library(struct file len = PAGE_ALIGN(ex.a_text + ex.a_data); bss = ex.a_text + ex.a_data + ex.a_bss; if (bss > len) { - error = do_brk(start_addr + len, bss - len); + error = do_brk_locked(start_addr + len, bss - len); retval = error; if (error != start_addr + len) goto out; diff -urNp linux-2.6.10/drivers/block/scsi_ioctl.c linux-2.6.10-new/drivers/block/scsi_ioctl.c --- linux-2.6.10/drivers/block/scsi_ioctl.c 2005-01-07 10:51:24 -0500 +++ linux-2.6.10-new/drivers/block/scsi_ioctl.c 2005-01-07 10:51:33 -0500 @@ -339,7 +339,8 @@ static int sg_scsi_ioctl(struct file *fi struct gendisk *bd_disk, Scsi_Ioctl_Command __user *sic) { struct request *rq; - int err, in_len, out_len, bytes, opcode, cmdlen; + unsigned int in_len, out_len, bytes, opcode, cmdlen; + int err; char *buffer = NULL, sense[SCSI_SENSE_BUFFERSIZE]; /* diff -urNp linux-2.6.10/drivers/char/moxa.c linux-2.6.10-new/drivers/char/moxa.c --- linux-2.6.10/drivers/char/moxa.c 2005-01-07 10:51:23 -0500 +++ linux-2.6.10-new/drivers/char/moxa.c 2005-01-07 10:51:33 -0500 @@ -1668,6 +1668,8 @@ int MoxaDriverIoctl(unsigned int cmd, un return -EFAULT; if(dltmp.cardno < 0 || dltmp.cardno >= MAX_BOARDS) return -EINVAL; + if(dltmp.len < 0 || dltmp.len > sizeof(moxaBuff)) + return -EINVAL; switch(cmd) { @@ -2822,8 +2824,6 @@ static int moxaload320b(int cardno, unsi void __iomem *baseAddr; int i; - if(len > sizeof(moxaBuff)) - return -EINVAL; if(copy_from_user(moxaBuff, tmp, len)) return -EFAULT; baseAddr = moxaBaseAddr[cardno]; diff -urNp linux-2.6.10/drivers/char/random.c linux-2.6.10-new/drivers/char/random.c --- linux-2.6.10/drivers/char/random.c 2005-01-07 10:51:23 -0500 +++ linux-2.6.10-new/drivers/char/random.c 2005-01-07 10:51:33 -0500 @@ -1912,7 +1912,7 @@ static int poolsize_strategy(ctl_table * void __user *oldval, size_t __user *oldlenp, void __user *newval, size_t newlen, void **context) { - int len; + size_t len; sysctl_poolsize = random_state->poolinfo.POOLBYTES; diff -urNp linux-2.6.10/fs/binfmt_aout.c linux-2.6.10-new/fs/binfmt_aout.c --- linux-2.6.10/fs/binfmt_aout.c 2005-01-07 10:51:21 -0500 +++ linux-2.6.10-new/fs/binfmt_aout.c 2005-01-07 11:24:45 -0500 @@ -51,7 +51,7 @@ static int set_brk(unsigned long start, start = PAGE_ALIGN(start); end = PAGE_ALIGN(end); if (end > start) { - unsigned long addr = do_brk(start, end - start); + unsigned long addr = do_brk_locked(start, end - start); if (BAD_ADDR(addr)) return addr; } @@ -353,10 +353,10 @@ static int load_aout_binary(struct linux loff_t pos = fd_offset; /* Fuck me plenty... */ /* */ - error = do_brk(N_TXTADDR(ex), ex.a_text); + error = do_brk_locked(N_TXTADDR(ex), ex.a_text); bprm->file->f_op->read(bprm->file, (char *) N_TXTADDR(ex), ex.a_text, &pos); - error = do_brk(N_DATADDR(ex), ex.a_data); + error = do_brk_locked(N_DATADDR(ex), ex.a_data); bprm->file->f_op->read(bprm->file, (char *) N_DATADDR(ex), ex.a_data, &pos); goto beyond_if; @@ -377,7 +377,7 @@ static int load_aout_binary(struct linux map_size = ex.a_text+ex.a_data; #endif - error = do_brk(text_addr & PAGE_MASK, map_size); + error = do_brk_locked(text_addr & PAGE_MASK, map_size); if (error != (text_addr & PAGE_MASK)) { send_sig(SIGKILL, current, 0); return error; @@ -412,7 +412,7 @@ static int load_aout_binary(struct linux if (!bprm->file->f_op->mmap||((fd_offset & ~PAGE_MASK) != 0)) { loff_t pos = fd_offset; - do_brk(N_TXTADDR(ex), ex.a_text+ex.a_data); + do_brk_locked(N_TXTADDR(ex), ex.a_text+ex.a_data); bprm->file->f_op->read(bprm->file, (char __user *)N_TXTADDR(ex), ex.a_text+ex.a_data, &pos); @@ -518,7 +518,7 @@ static int load_aout_library(struct file error_time = jiffies; } - do_brk(start_addr, ex.a_text + ex.a_data + ex.a_bss); + do_brk_locked(start_addr, ex.a_text + ex.a_data + ex.a_bss); file->f_op->read(file, (char __user *)start_addr, ex.a_text + ex.a_data, &pos); @@ -542,7 +542,7 @@ static int load_aout_library(struct file len = PAGE_ALIGN(ex.a_text + ex.a_data); bss = ex.a_text + ex.a_data + ex.a_bss; if (bss > len) { - error = do_brk(start_addr + len, bss - len); + error = do_brk_locked(start_addr + len, bss - len); retval = error; if (error != start_addr + len) goto out; diff -urNp linux-2.6.10/fs/binfmt_elf.c linux-2.6.10-new/fs/binfmt_elf.c --- linux-2.6.10/fs/binfmt_elf.c 2005-01-07 10:51:21 -0500 +++ linux-2.6.10-new/fs/binfmt_elf.c 2005-01-07 11:23:40 -0500 @@ -344,7 +344,9 @@ static unsigned long load_elf_interp(str */ if (interp_elf_ex->e_phentsize != sizeof(struct elf_phdr)) goto out; - if (interp_elf_ex->e_phnum > 65536U / sizeof(struct elf_phdr)) + + if (interp_elf_ex->e_phnum < 1 || + interp_elf_ex->e_phnum > 65536U / sizeof(struct elf_phdr)) goto out; /* Now read in all of the header information */ @@ -435,7 +437,7 @@ static unsigned long load_elf_interp(str /* Map the last of the bss segment */ if (last_bss > elf_bss) { - error = do_brk(elf_bss, last_bss - elf_bss); + error = do_brk_locked(elf_bss, last_bss - elf_bss); if (BAD_ADDR(error)) goto out_close; } @@ -475,7 +477,7 @@ static unsigned long load_aout_interp(st goto out; } - do_brk(0, text_data); + do_brk_locked(0, text_data); if (!interpreter->f_op || !interpreter->f_op->read) goto out; if (interpreter->f_op->read(interpreter, addr, text_data, &offset) < 0) @@ -483,7 +485,7 @@ static unsigned long load_aout_interp(st flush_icache_range((unsigned long)addr, (unsigned long)addr + text_data); - do_brk(ELF_PAGESTART(text_data + ELF_MIN_ALIGN - 1), + do_brk_locked(ELF_PAGESTART(text_data + ELF_MIN_ALIGN - 1), interp_ex->a_bss); elf_entry = interp_ex->a_entry; @@ -1436,9 +1438,7 @@ static int load_elf_library(struct file len = ELF_PAGESTART(elf_phdata->p_filesz + elf_phdata->p_vaddr + ELF_MIN_ALIGN - 1); bss = elf_phdata->p_memsz + elf_phdata->p_vaddr; if (bss > len) { - down_write(¤t->mm->mmap_sem); - do_brk(len, bss - len); - up_write(¤t->mm->mmap_sem); + do_brk_locked(len, bss - len); } error = 0; diff -urNp linux-2.6.10/include/linux/mm.h linux-2.6.10-new/include/linux/mm.h --- linux-2.6.10/include/linux/mm.h 2005-01-07 10:51:22 -0500 +++ linux-2.6.10-new/include/linux/mm.h 2005-01-07 11:25:05 -0500 @@ -761,6 +761,7 @@ out: extern int do_munmap(struct mm_struct *, unsigned long, size_t); extern unsigned long do_brk(unsigned long, unsigned long); +extern unsigned long do_brk_locked(unsigned long, unsigned long); /* filemap.c */ extern unsigned long page_unuse(struct page *); diff -urNp linux-2.6.10/include/linux/writeback.h linux-2.6.10-new/include/linux/writeback.h --- linux-2.6.10/include/linux/writeback.h 2005-01-07 10:51:22 -0500 +++ linux-2.6.10-new/include/linux/writeback.h 2005-01-07 10:51:33 -0500 @@ -86,6 +86,7 @@ static inline void wait_on_inode(struct int wakeup_bdflush(long nr_pages); void laptop_io_completion(void); void laptop_sync_completion(void); +void throttle_vm_writeout(void); /* These are exported to sysctl. */ extern int dirty_background_ratio; diff -urNp linux-2.6.10/mm/mmap.c linux-2.6.10-new/mm/mmap.c --- linux-2.6.10/mm/mmap.c 2005-01-07 10:51:24 -0500 +++ linux-2.6.10-new/mm/mmap.c 2005-01-07 11:25:57 -0500 @@ -2252,7 +2252,20 @@ out: return addr; } +/* locking version of do_brk. */ +unsigned long do_brk_locked(unsigned long addr, unsigned long len) +{ + unsigned long ret; + + down_write(¤t->mm->mmap_sem); + ret = do_brk(addr, len); + up_write(¤t->mm->mmap_sem); + + return ret; +} + EXPORT_SYMBOL(do_brk); +EXPORT_SYMBOL(do_brk_locked); /* Release all mmaps. */ void exit_mmap(struct mm_struct *mm) diff -urNp linux-2.6.10/mm/page-writeback.c linux-2.6.10-new/mm/page-writeback.c --- linux-2.6.10/mm/page-writeback.c 2005-01-07 10:51:24 -0500 +++ linux-2.6.10-new/mm/page-writeback.c 2005-01-07 10:51:33 -0500 @@ -276,6 +276,28 @@ void balance_dirty_pages_ratelimited(str } EXPORT_SYMBOL(balance_dirty_pages_ratelimited); +void throttle_vm_writeout(void) +{ + struct writeback_state wbs; + long background_thresh; + long dirty_thresh; + + for ( ; ; ) { + get_dirty_limits(&wbs, &background_thresh, &dirty_thresh); + + /* + * Boost the allowable dirty threshold a bit for page + * allocators so they don't get DoS'ed by heavy writers + */ + dirty_thresh += dirty_thresh / 10; /* wheeee... */ + + if (wbs.nr_unstable + wbs.nr_writeback <= dirty_thresh) + break; + blk_congestion_wait(WRITE, HZ/10); + } +} + + /* * writeback at least _min_pages, and keep writing until the amount of dirty * memory is less than the background threshold, or until we're all clean. diff -urNp linux-2.6.10/mm/vmscan.c linux-2.6.10-new/mm/vmscan.c --- linux-2.6.10/mm/vmscan.c 2005-01-07 10:51:24 -0500 +++ linux-2.6.10-new/mm/vmscan.c 2005-01-07 10:51:33 -0500 @@ -369,14 +369,14 @@ static int shrink_list(struct list_head BUG_ON(PageActive(page)); - if (PageWriteback(page)) - goto keep_locked; - sc->nr_scanned++; /* Double the slab pressure for mapped and swapcache pages */ if (page_mapped(page) || PageSwapCache(page)) sc->nr_scanned++; + if (PageWriteback(page)) + goto keep_locked; + referenced = page_referenced(page, 1, sc->priority <= 0); /* In active use or really unfreeable? Activate it. */ if (referenced && page_mapping_inuse(page)) @@ -825,6 +825,8 @@ shrink_zone(struct zone *zone, struct sc break; } } + + throttle_vm_writeout(); } /* diff -urNp linux-2.6.10/net/ipv4/netfilter/ip_conntrack_proto_tcp.c linux-2.6.10-new/net/ipv4/netfilter/ip_conntrack_proto_tcp.c --- linux-2.6.10/net/ipv4/netfilter/ip_conntrack_proto_tcp.c 2005-01-07 10:51:24 -0500 +++ linux-2.6.10-new/net/ipv4/netfilter/ip_conntrack_proto_tcp.c 2005-01-07 10:51:33 -0500 @@ -906,7 +906,8 @@ static int tcp_packet(struct ip_conntrac if (index == TCP_RST_SET && ((test_bit(IPS_SEEN_REPLY_BIT, &conntrack->status) && conntrack->proto.tcp.last_index <= TCP_SYNACK_SET) - || conntrack->proto.tcp.last_index == TCP_ACK_SET) + || (!test_bit(IPS_ASSURED_BIT, &conntrack->status) + && conntrack->proto.tcp.last_index == TCP_ACK_SET)) && after(ntohl(th->ack_seq), conntrack->proto.tcp.last_seq)) { /* Ignore RST closing down invalid SYN or ACK