From 1b8b07605f09e286b49efe7c5d9d142d9d9145ad Mon Sep 17 00:00:00 2001 From: Linus Torvalds Date: Fri, 23 Nov 2007 15:26:20 -0500 Subject: [PATCH] Import 2.3.12pre1 --- Makefile | 2 +- arch/alpha/kernel/signal.c | 6 +-- arch/arm/kernel/signal.c | 6 +-- arch/i386/kernel/process.c | 4 +- arch/i386/kernel/signal.c | 6 +-- arch/m68k/kernel/signal.c | 4 +- arch/mips/kernel/irixelf.c | 46 ++++--------------- arch/mips/kernel/irixsig.c | 6 +-- arch/mips/kernel/signal.c | 6 +-- arch/ppc/kernel/signal.c | 6 +-- arch/sparc/kernel/signal.c | 10 +---- arch/sparc64/kernel/binfmt_aout32.c | 43 +++--------------- arch/sparc64/kernel/signal.c | 8 +--- arch/sparc64/kernel/signal32.c | 10 +---- drivers/char/ppdev.c | 28 +++++++++--- fs/binfmt_aout.c | 48 +++++--------------- fs/binfmt_elf.c | 50 ++++----------------- fs/binfmt_em86.c | 6 ++- fs/binfmt_misc.c | 6 ++- fs/binfmt_script.c | 6 ++- fs/buffer.c | 69 ++++++++++++++++------------- fs/exec.c | 53 +++++++++++++++++++++- fs/minix/file.c | 1 + include/asm-i386/mmu_context.h | 17 +++++-- include/asm-i386/pgtable.h | 15 ++----- include/linux/binfmts.h | 4 +- include/linux/parport.h | 1 + kernel/fork.c | 3 +- net/ipv4/tcp_ipv4.c | 7 ++- scripts/ver_linux | 2 +- 30 files changed, 202 insertions(+), 277 deletions(-) diff --git a/Makefile b/Makefile index 9a69d721eb09..429bcedf0d11 100644 --- a/Makefile +++ b/Makefile @@ -1,6 +1,6 @@ VERSION = 2 PATCHLEVEL = 3 -SUBLEVEL = 11 +SUBLEVEL = 12 EXTRAVERSION = ARCH := $(shell uname -m | sed -e s/i.86/i386/ -e s/sun4u/sparc64/ -e s/arm.*/arm/ -e s/sa110/arm/) diff --git a/arch/alpha/kernel/signal.c b/arch/alpha/kernel/signal.c index 832d72ee0de4..cd8f6e0adb10 100644 --- a/arch/alpha/kernel/signal.c +++ b/arch/alpha/kernel/signal.c @@ -688,12 +688,8 @@ do_signal(sigset_t *oldset, struct pt_regs * regs, struct switch_stack * sw, case SIGQUIT: case SIGILL: case SIGTRAP: case SIGABRT: case SIGFPE: case SIGSEGV: - lock_kernel(); - if (current->binfmt - && current->binfmt->core_dump - && current->binfmt->core_dump(signr, regs)) + if (do_coredump(signr, regs)) exit_code |= 0x80; - unlock_kernel(); /* FALLTHRU */ default: diff --git a/arch/arm/kernel/signal.c b/arch/arm/kernel/signal.c index 5ec48f75285d..fe8b5c502fb3 100644 --- a/arch/arm/kernel/signal.c +++ b/arch/arm/kernel/signal.c @@ -543,12 +543,8 @@ asmlinkage int do_signal(sigset_t *oldset, struct pt_regs *regs, int syscall) case SIGQUIT: case SIGILL: case SIGTRAP: case SIGABRT: case SIGFPE: case SIGSEGV: - lock_kernel(); - if (current->binfmt - && current->binfmt->core_dump - && current->binfmt->core_dump(signr, regs)) + if (do_coredump(signr, regs)) exit_code |= 0x80; - unlock_kernel(); /* FALLTHRU */ default: diff --git a/arch/i386/kernel/process.c b/arch/i386/kernel/process.c index 9e2d4432b5b1..952f5b93d789 100644 --- a/arch/i386/kernel/process.c +++ b/arch/i386/kernel/process.c @@ -40,6 +40,7 @@ #include #include #include +#include #ifdef CONFIG_MATH_EMULATION #include #endif @@ -327,7 +328,8 @@ void machine_restart(char * __unused) * seldom used feature ;) */ - SET_PAGE_DIR(current,swapper_pg_dir); + current->mm->pgd = swapper_pg_dir; + activate_context(); /* Write 0x1234 to absolute memory location 0x472. The BIOS reads this on booting to tell it to "Bypass memory test (also warm diff --git a/arch/i386/kernel/signal.c b/arch/i386/kernel/signal.c index e5bc3141b40b..cc9a992da75c 100644 --- a/arch/i386/kernel/signal.c +++ b/arch/i386/kernel/signal.c @@ -687,12 +687,8 @@ int do_signal(struct pt_regs *regs, sigset_t *oldset) case SIGQUIT: case SIGILL: case SIGTRAP: case SIGABRT: case SIGFPE: case SIGSEGV: - lock_kernel(); - if (current->binfmt - && current->binfmt->core_dump - && current->binfmt->core_dump(signr, regs)) + if (do_coredump(signr, regs)) exit_code |= 0x80; - unlock_kernel(); /* FALLTHRU */ default: diff --git a/arch/m68k/kernel/signal.c b/arch/m68k/kernel/signal.c index a2b9ce1d4102..dfb6d50fd9da 100644 --- a/arch/m68k/kernel/signal.c +++ b/arch/m68k/kernel/signal.c @@ -1084,9 +1084,7 @@ asmlinkage int do_signal(sigset_t *oldset, struct pt_regs *regs) case SIGQUIT: case SIGILL: case SIGTRAP: case SIGIOT: case SIGFPE: case SIGSEGV: - if (current->binfmt - && current->binfmt->core_dump - && current->binfmt->core_dump(signr, regs)) + if (do_coredump(signr, regs)) exit_code |= 0x80; /* FALLTHRU */ diff --git a/arch/mips/kernel/irixelf.c b/arch/mips/kernel/irixelf.c index 521e836e8340..cf5dd2ea323d 100644 --- a/arch/mips/kernel/irixelf.c +++ b/arch/mips/kernel/irixelf.c @@ -48,11 +48,13 @@ static int irix_core_dump(long signr, struct pt_regs * regs); extern int dump_fpu (elf_fpregset_t *); static struct linux_binfmt irix_format = { + NULL, #ifndef MODULE - NULL, NULL, load_irix_binary, load_irix_library, irix_core_dump + NULL, #else - NULL, &__this_module.usecount, load_irix_binary, load_irix_library, irix_core_dump + &__this_module.usecount, #endif + load_irix_binary, load_irix_library, irix_core_dump, PAGE_SIZE }; #ifndef elf_addr_t @@ -1105,24 +1107,20 @@ static int writenote(struct memelfnote *men, struct file *file) #define DUMP_WRITE(addr, nr) \ if (!dump_write(file, (addr), (nr))) \ - goto close_coredump; + goto end_coredump; #define DUMP_SEEK(off) \ if (!dump_seek(file, (off))) \ - goto close_coredump; + goto end_coredump; /* Actual dumper. * * This is a two-pass process; first we find the offsets of the bits, * and then they are actually written out. If we run out of core limit * we just truncate. */ -static int irix_core_dump(long signr, struct pt_regs * regs) +static int irix_core_dump(long signr, struct pt_regs * regs, struct file *file) { int has_dumped = 0; - struct file *file; - struct dentry *dentry; - struct inode *inode; mm_segment_t fs; - char corefile[6+sizeof(current->comm)]; int segs; int i; size_t size; @@ -1135,10 +1133,6 @@ static int irix_core_dump(long signr, struct pt_regs * regs) struct elf_prstatus prstatus; /* NT_PRSTATUS */ elf_fpregset_t fpu; /* NT_PRFPREG */ struct elf_prpsinfo psinfo; /* NT_PRPSINFO */ - - if (!current->dumpable || limit < PAGE_SIZE) - return 0; - current->dumpable = 0; #ifndef CONFIG_BINFMT_IRIX MOD_INC_USE_COUNT; @@ -1188,27 +1182,6 @@ static int irix_core_dump(long signr, struct pt_regs * regs) fs = get_fs(); set_fs(KERNEL_DS); - memcpy(corefile,"core.", 5); -#if 0 - memcpy(corefile+5,current->comm,sizeof(current->comm)); -#else - corefile[4] = '\0'; -#endif - file = filp_open(corefile, O_CREAT | 2 | O_TRUNC | O_NOFOLLOW, 0600); - if (IS_ERR(file)) - goto end_coredump; - dentry = file->f_dentry; - inode = dentry->d_inode; - if (inode->i_nlink > 1) - goto close_coredump; /* multiple links - don't dump */ - - if (!S_ISREG(inode->i_mode)) - goto close_coredump; - if (!inode->i_op || !inode->i_op->default_file_ops) - goto close_coredump; - if (!file->f_op->write) - goto close_coredump; - has_dumped = 1; current->flags |= PF_DUMPCORE; @@ -1345,7 +1318,7 @@ static int irix_core_dump(long signr, struct pt_regs * regs) for(i = 0; i < numnote; i++) if (!writenote(¬es[i], file)) - goto close_coredump; + goto end_coredump; set_fs(fs); @@ -1372,9 +1345,6 @@ static int irix_core_dump(long signr, struct pt_regs * regs) (off_t) file->f_pos, offset); } - close_coredump: - filp_close(file, NULL); - end_coredump: set_fs(fs); #ifndef CONFIG_BINFMT_ELF diff --git a/arch/mips/kernel/irixsig.c b/arch/mips/kernel/irixsig.c index 47f89deda1d3..e7541051837d 100644 --- a/arch/mips/kernel/irixsig.c +++ b/arch/mips/kernel/irixsig.c @@ -261,12 +261,8 @@ asmlinkage int do_irix_signal(sigset_t *oldset, struct pt_regs *regs) case SIGQUIT: case SIGILL: case SIGTRAP: case SIGABRT: case SIGFPE: case SIGSEGV: - lock_kernel(); - if (current->binfmt - && current->binfmt->core_dump - && current->binfmt->core_dump(signr, regs)) + if (do_coredump(signr, regs)) exit_code |= 0x80; - unlock_kernel(); /* FALLTHRU */ default: diff --git a/arch/mips/kernel/signal.c b/arch/mips/kernel/signal.c index 3b2bf33fcfd5..c58f1e7cae9f 100644 --- a/arch/mips/kernel/signal.c +++ b/arch/mips/kernel/signal.c @@ -493,12 +493,8 @@ asmlinkage int do_signal(sigset_t *oldset, struct pt_regs *regs) case SIGQUIT: case SIGILL: case SIGTRAP: case SIGABRT: case SIGFPE: case SIGSEGV: case SIGBUS: - lock_kernel(); - if (current->binfmt - && current->binfmt->core_dump - && current->binfmt->core_dump(signr, regs)) + if (do_coredump(signr, regs)) exit_code |= 0x80; - unlock_kernel(); /* FALLTHRU */ default: diff --git a/arch/ppc/kernel/signal.c b/arch/ppc/kernel/signal.c index a1b590658790..785204b933a8 100644 --- a/arch/ppc/kernel/signal.c +++ b/arch/ppc/kernel/signal.c @@ -444,12 +444,8 @@ int do_signal(sigset_t *oldset, struct pt_regs *regs) case SIGQUIT: case SIGILL: case SIGTRAP: case SIGABRT: case SIGFPE: case SIGSEGV: - lock_kernel(); - if (current->binfmt - && current->binfmt->core_dump - && current->binfmt->core_dump(signr, regs)) + if (do_coredump(signr, regs)) exit_code |= 0x80; - unlock_kernel(); /* FALLTHRU */ default: diff --git a/arch/sparc/kernel/signal.c b/arch/sparc/kernel/signal.c index 9f7b5b1f77ca..50952ef6dd36 100644 --- a/arch/sparc/kernel/signal.c +++ b/arch/sparc/kernel/signal.c @@ -1160,14 +1160,8 @@ asmlinkage int do_signal(sigset_t *oldset, struct pt_regs * regs, case SIGQUIT: case SIGILL: case SIGTRAP: case SIGABRT: case SIGFPE: case SIGSEGV: case SIGBUS: - if(current->binfmt && current->binfmt->core_dump) { - lock_kernel(); - if(current->binfmt && - current->binfmt->core_dump && - current->binfmt->core_dump(signr, regs)) - exit_code |= 0x80; - unlock_kernel(); - } + if (do_coredump(signr, regs)) + exit_code |= 0x80; #ifdef DEBUG_SIGNALS /* Very useful to debug dynamic linker problems */ printk ("Sig %ld going for %s[%d]...\n", signr, current->comm, current->pid); diff --git a/arch/sparc64/kernel/binfmt_aout32.c b/arch/sparc64/kernel/binfmt_aout32.c index bc77266f90cb..34dee33a24a1 100644 --- a/arch/sparc64/kernel/binfmt_aout32.c +++ b/arch/sparc64/kernel/binfmt_aout32.c @@ -39,7 +39,8 @@ static int aout32_core_dump(long signr, struct pt_regs * regs); extern void dump_thread(struct pt_regs *, struct user *); static struct linux_binfmt aout32_format = { - NULL, NULL, load_aout32_binary, load_aout32_library, aout32_core_dump + NULL, NULL, load_aout32_binary, load_aout32_library, aout32_core_dump, + PAGE_SIZE }; static void set_brk(unsigned long start, unsigned long end) @@ -63,12 +64,12 @@ static int dump_write(struct file *file, const void *addr, int nr) #define DUMP_WRITE(addr, nr) \ if (!dump_write(file, (void *)(addr), (nr))) \ - goto close_coredump; + goto end_coredump; #define DUMP_SEEK(offset) \ if (file->f_op->llseek) { \ if (file->f_op->llseek(file,(offset),0) != (offset)) \ - goto close_coredump; \ + goto end_coredump; \ } else file->f_pos = (offset) /* @@ -82,45 +83,17 @@ if (file->f_op->llseek) { \ */ static inline int -do_aout32_core_dump(long signr, struct pt_regs * regs) +do_aout32_core_dump(long signr, struct pt_regs * regs, struct file *file) { - struct dentry * dentry = NULL; - struct inode * inode = NULL; - struct file * file; mm_segment_t fs; int has_dumped = 0; - char corefile[6+sizeof(current->comm)]; unsigned long dump_start, dump_size; struct user dump; # define START_DATA(u) (u.u_tsize) # define START_STACK(u) ((regs->u_regs[UREG_FP]) & ~(PAGE_SIZE - 1)) - if (!current->dumpable || atomic_read(¤t->mm->count) != 1) - return 0; - current->dumpable = 0; - -/* See if we have enough room to write the upage. */ - if (current->rlim[RLIMIT_CORE].rlim_cur < PAGE_SIZE) - return 0; fs = get_fs(); set_fs(KERNEL_DS); - memcpy(corefile,"core.",5); -#if 0 - memcpy(corefile+5,current->comm,sizeof(current->comm)); -#else - corefile[4] = '\0'; -#endif - file = filp_open(corefile,O_CREAT | 2 | O_TRUNC | O_NOFOLLOW, 0600); - if (IS_ERR(file)) - goto end_coredump; - dentry = file->f_dentry; - inode = dentry->d_inode; - if (!S_ISREG(inode->i_mode)) - goto close_coredump; - if (!inode->i_op || !inode->i_op->default_file_ops) - goto close_coredump; - if (!file->f_op->write) - goto close_coredump; has_dumped = 1; current->flags |= PF_DUMPCORE; strncpy(dump.u_comm, current->comm, sizeof(current->comm)); @@ -165,20 +138,18 @@ do_aout32_core_dump(long signr, struct pt_regs * regs) /* Finally dump the task struct. Not be used by gdb, but could be useful */ set_fs(KERNEL_DS); DUMP_WRITE(current,sizeof(*current)); -close_coredump: - filp_close(file, NULL); end_coredump: set_fs(fs); return has_dumped; } static int -aout32_core_dump(long signr, struct pt_regs * regs) +aout32_core_dump(long signr, struct pt_regs * regs, struct file * file) { int retval; MOD_INC_USE_COUNT; - retval = do_aout32_core_dump(signr, regs); + retval = do_aout32_core_dump(signr, regs, file); MOD_DEC_USE_COUNT; return retval; } diff --git a/arch/sparc64/kernel/signal.c b/arch/sparc64/kernel/signal.c index 247afc77c172..4310ca607fa9 100644 --- a/arch/sparc64/kernel/signal.c +++ b/arch/sparc64/kernel/signal.c @@ -866,12 +866,8 @@ asmlinkage int do_signal(sigset_t *oldset, struct pt_regs * regs, case SIGQUIT: case SIGILL: case SIGTRAP: case SIGABRT: case SIGFPE: case SIGSEGV: case SIGBUS: - if(current->binfmt && current->binfmt->core_dump) { - lock_kernel(); - if(current->binfmt->core_dump(signr, regs)) - exit_code |= 0x80; - unlock_kernel(); - } + if (do_coredump(signr, regs)) + exit_code |= 0x80; #ifdef DEBUG_SIGNALS /* Very useful to debug the dynamic linker */ printk ("Sig %d going...\n", (int)signr); diff --git a/arch/sparc64/kernel/signal32.c b/arch/sparc64/kernel/signal32.c index b1190d244756..c20fe22fc012 100644 --- a/arch/sparc64/kernel/signal32.c +++ b/arch/sparc64/kernel/signal32.c @@ -1291,14 +1291,8 @@ asmlinkage int do_signal32(sigset_t *oldset, struct pt_regs * regs, case SIGQUIT: case SIGILL: case SIGTRAP: case SIGABRT: case SIGFPE: case SIGSEGV: case SIGBUS: - if(current->binfmt && current->binfmt->core_dump) { - lock_kernel(); - if(current->binfmt && - current->binfmt->core_dump && - current->binfmt->core_dump(signr, regs)) - exit_code |= 0x80; - unlock_kernel(); - } + if (do_coredump(signr, regs)) + exit_code |= 0x80; #ifdef DEBUG_SIGNALS /* Very useful to debug dynamic linker problems */ printk ("Sig %ld going for %s[%d]...\n", signr, current->comm, current->pid); diff --git a/drivers/char/ppdev.c b/drivers/char/ppdev.c index 485ae1dfd827..4a24bf1e3a86 100644 --- a/drivers/char/ppdev.c +++ b/drivers/char/ppdev.c @@ -85,8 +85,10 @@ static ssize_t do_read (struct pp_struct *pp, void *buf, size_t len) { size_t (*fn) (struct parport *, void *, size_t, int); struct parport *port = pp->pdev->port; + int addr = pp->mode & IEEE1284_ADDR; + int mode = pp->mode & ~(IEEE1284_DEVICEID | IEEE1284_ADDR); - switch (pp->mode) { + switch (mode) { case IEEE1284_MODE_COMPAT: /* This is a write-only mode. */ return -EIO; @@ -100,7 +102,10 @@ static ssize_t do_read (struct pp_struct *pp, void *buf, size_t len) break; case IEEE1284_MODE_EPP: - fn = port->ops->epp_read_data; + if (addr) + fn = port->ops->epp_read_addr; + else + fn = port->ops->epp_read_data; break; case IEEE1284_MODE_ECP: @@ -128,8 +133,10 @@ static ssize_t do_write (struct pp_struct *pp, const void *buf, size_t len) { size_t (*fn) (struct parport *, const void *, size_t, int); struct parport *port = pp->pdev->port; + int addr = pp->mode & IEEE1284_ADDR; + int mode = pp->mode & ~(IEEE1284_DEVICEID | IEEE1284_ADDR); - switch (pp->mode) { + switch (mode) { case IEEE1284_MODE_NIBBLE: case IEEE1284_MODE_BYTE: /* Read-only modes. */ @@ -140,16 +147,25 @@ static ssize_t do_write (struct pp_struct *pp, const void *buf, size_t len) break; case IEEE1284_MODE_EPP: - fn = port->ops->epp_write_data; + if (addr) + fn = port->ops->epp_write_addr; + else + fn = port->ops->epp_write_data; break; case IEEE1284_MODE_ECP: case IEEE1284_MODE_ECPRLE: - fn = port->ops->ecp_write_data; + if (addr) + fn = port->ops->ecp_write_addr; + else + fn = port->ops->ecp_write_data; break; case IEEE1284_MODE_ECPSWE: - fn = parport_ieee1284_ecp_write_data; + if (addr) + fn = parport_ieee1284_ecp_write_addr; + else + fn = parport_ieee1284_ecp_write_data; break; default: diff --git a/fs/binfmt_aout.c b/fs/binfmt_aout.c index 3984e85ed01a..2649d0fa1ae3 100644 --- a/fs/binfmt_aout.c +++ b/fs/binfmt_aout.c @@ -31,16 +31,18 @@ static int load_aout_binary(struct linux_binprm *, struct pt_regs * regs); static int load_aout_library(int fd); -static int aout_core_dump(long signr, struct pt_regs * regs); +static int aout_core_dump(long signr, struct pt_regs * regs, struct file *file); extern void dump_thread(struct pt_regs *, struct user *); static struct linux_binfmt aout_format = { + NULL, #ifndef MODULE - NULL, NULL, load_aout_binary, load_aout_library, aout_core_dump + NULL, #else - NULL, &__this_module, load_aout_binary, load_aout_library, aout_core_dump + &__this_module, #endif + load_aout_binary, load_aout_library, aout_core_dump, PAGE_SIZE }; static void set_brk(unsigned long start, unsigned long end) @@ -64,12 +66,12 @@ static int dump_write(struct file *file, const void *addr, int nr) #define DUMP_WRITE(addr, nr) \ if (!dump_write(file, (void *)(addr), (nr))) \ - goto close_coredump; + goto end_coredump; #define DUMP_SEEK(offset) \ if (file->f_op->llseek) { \ if (file->f_op->llseek(file,(offset),0) != (offset)) \ - goto close_coredump; \ + goto end_coredump; \ } else file->f_pos = (offset) /* @@ -83,14 +85,10 @@ if (file->f_op->llseek) { \ */ static inline int -do_aout_core_dump(long signr, struct pt_regs * regs) +do_aout_core_dump(long signr, struct pt_regs * regs, struct file *file) { - struct dentry * dentry = NULL; - struct inode * inode = NULL; - struct file * file; mm_segment_t fs; int has_dumped = 0; - char corefile[6+sizeof(current->comm)]; unsigned long dump_start, dump_size; struct user dump; #if defined(__alpha__) @@ -106,32 +104,8 @@ do_aout_core_dump(long signr, struct pt_regs * regs) # define START_STACK(u) (u.start_stack) #endif - if (!current->dumpable || atomic_read(¤t->mm->mm_users) != 1) - return 0; - current->dumpable = 0; - -/* See if we have enough room to write the upage. */ - if (current->rlim[RLIMIT_CORE].rlim_cur < PAGE_SIZE) - return 0; fs = get_fs(); set_fs(KERNEL_DS); - memcpy(corefile,"core.",5); -#if 0 - memcpy(corefile+5,current->comm,sizeof(current->comm)); -#else - corefile[4] = '\0'; -#endif - file = filp_open(corefile,O_CREAT | 2 | O_TRUNC | O_NOFOLLOW, 0600); - if (IS_ERR(file)) - goto end_coredump; - dentry = file->f_dentry; - inode = dentry->d_inode; - if (!S_ISREG(inode->i_mode)) - goto close_coredump; - if (!inode->i_op || !inode->i_op->default_file_ops) - goto close_coredump; - if (!file->f_op->write) - goto close_coredump; has_dumped = 1; current->flags |= PF_DUMPCORE; strncpy(dump.u_comm, current->comm, sizeof(current->comm)); @@ -210,20 +184,18 @@ do_aout_core_dump(long signr, struct pt_regs * regs) /* Finally dump the task struct. Not be used by gdb, but could be useful */ set_fs(KERNEL_DS); DUMP_WRITE(current,sizeof(*current)); -close_coredump: - filp_close(file, NULL); end_coredump: set_fs(fs); return has_dumped; } static int -aout_core_dump(long signr, struct pt_regs * regs) +aout_core_dump(long signr, struct pt_regs * regs, struct file *file) { int retval; MOD_INC_USE_COUNT; - retval = do_aout_core_dump(signr, regs); + retval = do_aout_core_dump(signr, regs, file); MOD_DEC_USE_COUNT; return retval; } diff --git a/fs/binfmt_elf.c b/fs/binfmt_elf.c index e933ff98e92d..5b2988201bcb 100644 --- a/fs/binfmt_elf.c +++ b/fs/binfmt_elf.c @@ -54,7 +54,7 @@ extern void dump_thread(struct pt_regs *, struct user *); * don't even try. */ #ifdef USE_ELF_CORE_DUMP -static int elf_core_dump(long signr, struct pt_regs * regs); +static int elf_core_dump(long signr, struct pt_regs * regs, struct file * file); #else #define elf_core_dump NULL #endif @@ -64,11 +64,13 @@ static int elf_core_dump(long signr, struct pt_regs * regs); #define ELF_PAGEALIGN(_v) (((_v) + ELF_EXEC_PAGESIZE - 1) & ~(ELF_EXEC_PAGESIZE - 1)) static struct linux_binfmt elf_format = { + NULL, #ifndef MODULE - NULL, NULL, load_elf_binary, load_elf_library, elf_core_dump + NULL, #else - NULL, &__this_module, load_elf_binary, load_elf_library, elf_core_dump + &__this_module, #endif + load_elf_binary, load_elf_library, elf_core_dump, ELF_EXEC_PAGESIZE }; static void set_brk(unsigned long start, unsigned long end) @@ -1026,10 +1028,10 @@ static int writenote(struct memelfnote *men, struct file *file) #define DUMP_WRITE(addr, nr) \ if (!dump_write(file, (addr), (nr))) \ - goto close_coredump; + goto end_coredump; #define DUMP_SEEK(off) \ if (!dump_seek(file, (off))) \ - goto close_coredump; + goto end_coredump; /* * Actual dumper * @@ -1037,14 +1039,10 @@ static int writenote(struct memelfnote *men, struct file *file) * and then they are actually written out. If we run out of core limit * we just truncate. */ -static int elf_core_dump(long signr, struct pt_regs * regs) +static int elf_core_dump(long signr, struct pt_regs * regs, struct file * file) { int has_dumped = 0; - struct file *file; - struct dentry *dentry; - struct inode *inode; mm_segment_t fs; - char corefile[6+sizeof(current->comm)]; int segs; int i; size_t size; @@ -1058,12 +1056,6 @@ static int elf_core_dump(long signr, struct pt_regs * regs) elf_fpregset_t fpu; /* NT_PRFPREG */ struct elf_prpsinfo psinfo; /* NT_PRPSINFO */ - if (!current->dumpable || - limit < ELF_EXEC_PAGESIZE || - atomic_read(¤t->mm->mm_users) != 1) - return 0; - current->dumpable = 0; - #ifndef CONFIG_BINFMT_ELF MOD_INC_USE_COUNT; #endif @@ -1112,27 +1104,6 @@ static int elf_core_dump(long signr, struct pt_regs * regs) fs = get_fs(); set_fs(KERNEL_DS); - memcpy(corefile,"core.",5); -#if 0 - memcpy(corefile+5,current->comm,sizeof(current->comm)); -#else - corefile[4] = '\0'; -#endif - file = filp_open(corefile, O_CREAT | 2 | O_TRUNC | O_NOFOLLOW, 0600); - if (IS_ERR(file)) - goto end_coredump; - dentry = file->f_dentry; - inode = dentry->d_inode; - if (inode->i_nlink > 1) - goto close_coredump; /* multiple links - don't dump */ - - if (!S_ISREG(inode->i_mode)) - goto close_coredump; - if (!inode->i_op || !inode->i_op->default_file_ops) - goto close_coredump; - if (!file->f_op->write) - goto close_coredump; - has_dumped = 1; current->flags |= PF_DUMPCORE; @@ -1289,7 +1260,7 @@ static int elf_core_dump(long signr, struct pt_regs * regs) for(i = 0; i < numnote; i++) if (!writenote(¬es[i], file)) - goto close_coredump; + goto end_coredump; set_fs(fs); @@ -1316,9 +1287,6 @@ static int elf_core_dump(long signr, struct pt_regs * regs) (off_t) file->f_pos, offset); } - close_coredump: - filp_close(file, NULL); - end_coredump: set_fs(fs); #ifndef CONFIG_BINFMT_ELF diff --git a/fs/binfmt_em86.c b/fs/binfmt_em86.c index f102f2dec87e..0a499e7d0ea7 100644 --- a/fs/binfmt_em86.c +++ b/fs/binfmt_em86.c @@ -105,11 +105,13 @@ static int load_em86(struct linux_binprm *bprm,struct pt_regs *regs) } struct linux_binfmt em86_format = { + NULL, #ifndef MODULE - NULL, 0, load_em86, NULL, NULL + NULL, #else - NULL, &__this_module, load_em86, NULL, NULL + &__this_module, #endif + load_em86, NULL, NULL, 0 }; int __init init_em86_binfmt(void) diff --git a/fs/binfmt_misc.c b/fs/binfmt_misc.c index 7b9cead81959..69920f45b151 100644 --- a/fs/binfmt_misc.c +++ b/fs/binfmt_misc.c @@ -64,11 +64,13 @@ static void entry_proc_cleanup(struct binfmt_entry *e); static int entry_proc_setup(struct binfmt_entry *e); static struct linux_binfmt misc_format = { + NULL, #ifndef MODULE - NULL, 0, load_misc_binary, NULL, NULL + NULL, #else - NULL, &__this_module, load_misc_binary, NULL, NULL + &__this_module, #endif + load_misc_binary, NULL, NULL, 0 }; static struct proc_dir_entry *bm_dir = NULL; diff --git a/fs/binfmt_script.c b/fs/binfmt_script.c index 8cc685acaeb7..1d2e778ec678 100644 --- a/fs/binfmt_script.c +++ b/fs/binfmt_script.c @@ -101,11 +101,13 @@ static int load_script(struct linux_binprm *bprm,struct pt_regs *regs) } struct linux_binfmt script_format = { + NULL, #ifndef MODULE - NULL, 0, load_script, NULL, NULL + NULL, #else - NULL, &__this_module, load_script, NULL, NULL + &__this_module, #endif + load_script, NULL, NULL, 0 }; int __init init_script_binfmt(void) diff --git a/fs/buffer.c b/fs/buffer.c index ea30c86909e7..f578992b3b2f 100644 --- a/fs/buffer.c +++ b/fs/buffer.c @@ -44,6 +44,7 @@ #include #include #include +#include #define NR_SIZES 7 static char buffersize_index[65] = @@ -1955,6 +1956,26 @@ static int sync_old_buffers(void) return 0; } +struct mm_struct * start_lazy_tlb(void) +{ + struct mm_struct *mm = current->mm; + atomic_inc(&mm->mm_count); + current->mm = NULL; + /* active_mm is still 'mm' */ + return mm; +} + +void end_lazy_tlb(struct mm_struct *mm) +{ + struct mm_struct *active_mm = current->active_mm; + + current->mm = mm; + if (mm != active_mm) { + current->active_mm = mm; + activate_context(); + } + mmdrop(active_mm); +} /* This is the interface to bdflush. As we get more sophisticated, we can * pass tuning parameters to this "process", to adjust how it behaves. @@ -1963,57 +1984,45 @@ static int sync_old_buffers(void) asmlinkage int sys_bdflush(int func, long data) { - int i, error = -EPERM; - if (!capable(CAP_SYS_ADMIN)) - goto out; + return -EPERM; if (func == 1) { + int error; struct mm_struct *user_mm; + /* * bdflush will spend all of it's time in kernel-space, * without touching user-space, so we can switch it into * 'lazy TLB mode' to reduce the cost of context-switches * to and from bdflush. */ - user_mm = current->mm; - atomic_inc(&user_mm->mm_count); - current->mm = NULL; - /* active_mm is still 'user_mm' */ - + user_mm = start_lazy_tlb(); error = sync_old_buffers(); - - current->mm = user_mm; - mmdrop(current->active_mm); - current->active_mm = user_mm; - - goto out; + end_lazy_tlb(user_mm); + return error; } /* Basically func 1 means read param 1, 2 means write param 1, etc */ if (func >= 2) { - i = (func-2) >> 1; - error = -EINVAL; - if (i < 0 || i >= N_PARAM) - goto out; - if((func & 1) == 0) { - error = put_user(bdf_prm.data[i], (int*)data); - goto out; + int i = (func-2) >> 1; + if (i >= 0 && i < N_PARAM) { + if ((func & 1) == 0) + return put_user(bdf_prm.data[i], (int*)data); + + if (data >= bdflush_min[i] && data <= bdflush_max[i]) { + bdf_prm.data[i] = data; + return 0; + } } - if (data < bdflush_min[i] || data > bdflush_max[i]) - goto out; - bdf_prm.data[i] = data; - error = 0; - goto out; - }; + return -EINVAL; + } /* Having func 0 used to launch the actual bdflush and then never * return (unless explicitly killed). We return zero here to * remain semi-compatible with present update(8) programs. */ - error = 0; -out: - return error; + return 0; } /* diff --git a/fs/exec.c b/fs/exec.c index debc7ed04da1..d8b62ab55792 100644 --- a/fs/exec.c +++ b/fs/exec.c @@ -388,8 +388,7 @@ static int exec_mmap(void) current->mm = mm; current->active_mm = mm; - SET_PAGE_DIR(current, mm->pgd); - activate_context(current); + activate_context(); mm_release(); if (old_mm) { mmput(old_mm); @@ -837,3 +836,53 @@ out: return retval; } + +int do_coredump(long signr, struct pt_regs * regs) +{ + struct linux_binfmt * binfmt; + char corename[6+sizeof(current->comm)]; + struct file * file; + struct dentry * dentry; + struct inode * inode; + + lock_kernel(); + binfmt = current->binfmt; + if (!binfmt || !binfmt->core_dump) + goto fail; + if (!current->dumpable || atomic_read(¤t->mm->mm_users) != 1) + current->dumpable = 0; + if (current->rlim[RLIMIT_CORE].rlim_cur < binfmt->min_coredump) + goto fail; + + memcpy(corename,"core.", 5); +#if 0 + memcpy(corename+5,current->comm,sizeof(current->comm)); +#else + corename[4] = '\0'; +#endif + file = filp_open(corename, O_CREAT | 2 | O_TRUNC | O_NOFOLLOW, 0600); + if (IS_ERR(file)) + goto fail; + dentry = file->f_dentry; + inode = dentry->d_inode; + if (inode->i_nlink > 1) + goto close_fail; /* multiple links - don't dump */ + + if (!S_ISREG(inode->i_mode)) + goto close_fail; + if (!inode->i_op || !inode->i_op->default_file_ops) + goto close_fail; + if (!file->f_op->write) + goto close_fail; + if (!binfmt->core_dump(signr, regs, file)) + goto close_fail; + filp_close(file, NULL); + unlock_kernel(); + return 1; + +close_fail: + filp_close(file, NULL); +fail: + unlock_kernel(); + return 0; +} diff --git a/fs/minix/file.c b/fs/minix/file.c index 9eab1fb176c7..6683c393cc64 100644 --- a/fs/minix/file.c +++ b/fs/minix/file.c @@ -24,6 +24,7 @@ #define MAX(a,b) (((a)>(b))?(a):(b)) #include +#include /* * Write to a file (through the page cache). diff --git a/include/asm-i386/mmu_context.h b/include/asm-i386/mmu_context.h index b2d0bf6cf640..3e007f13b8b8 100644 --- a/include/asm-i386/mmu_context.h +++ b/include/asm-i386/mmu_context.h @@ -17,11 +17,22 @@ #define get_mmu_context(next) do { } while (0) #define set_mmu_context(prev,next) do { next->thread.cr3 = prev->thread.cr3; } while(0) -#define init_new_context(mm) do { } while(0) /* * possibly do the LDT unload here? */ -#define destroy_context(mm) do { } while(0) -#define activate_context(x) load_LDT((x)->mm) +#define destroy_context(mm) do { } while(0) +#define init_new_context(tsk,mm) do { (tsk)->thread.cr3 = __pa((mm)->pgd); } while (0) + +static inline void activate_context(void) +{ + struct task_struct *tsk = current; + struct mm_struct *mm = tsk->mm; + unsigned long cr3; + + load_LDT(mm); + cr3 = __pa(mm->pgd); + tsk->thread.cr3 = cr3; + __asm__ __volatile__("movl %0,%%cr3": :"r" (cr3)); +} #endif diff --git a/include/asm-i386/pgtable.h b/include/asm-i386/pgtable.h index 34c7439862fd..c2909cec2f95 100644 --- a/include/asm-i386/pgtable.h +++ b/include/asm-i386/pgtable.h @@ -56,21 +56,21 @@ __asm__ __volatile__("invlpg %0": :"m" (*(char *) addr)) static inline void flush_tlb_mm(struct mm_struct *mm) { - if (mm == current->mm) + if (mm == current->active_mm) __flush_tlb(); } static inline void flush_tlb_page(struct vm_area_struct *vma, unsigned long addr) { - if (vma->vm_mm == current->mm) + if (vma->vm_mm == current->active_mm) __flush_tlb_one(addr); } static inline void flush_tlb_range(struct mm_struct *mm, unsigned long start, unsigned long end) { - if (mm == current->mm) + if (mm == current->active_mm) __flush_tlb(); } @@ -302,15 +302,6 @@ extern pte_t * __bad_pagetable(void); #define PAGE_PTR(address) \ ((unsigned long)(address)>>(PAGE_SHIFT-SIZEOF_PTR_LOG2)&PTR_MASK&~PAGE_MASK) -/* to set the page-dir */ -#define SET_PAGE_DIR(tsk,pgdir) \ -do { \ - unsigned long __pgdir = __pa(pgdir); \ - (tsk)->thread.cr3 = __pgdir; \ - if ((tsk) == current) \ - __asm__ __volatile__("movl %0,%%cr3": :"r" (__pgdir)); \ -} while (0) - #define pte_none(x) (!pte_val(x)) #define pte_present(x) (pte_val(x) & (_PAGE_PRESENT | _PAGE_PROTNONE)) #define pte_clear(xp) do { pte_val(*(xp)) = 0; } while (0) diff --git a/include/linux/binfmts.h b/include/linux/binfmts.h index 7ada5424685b..89024e2ab511 100644 --- a/include/linux/binfmts.h +++ b/include/linux/binfmts.h @@ -38,7 +38,8 @@ struct linux_binfmt { struct module *module; int (*load_binary)(struct linux_binprm *, struct pt_regs * regs); int (*load_shlib)(int fd); - int (*core_dump)(long signr, struct pt_regs * regs); + int (*core_dump)(long signr, struct pt_regs * regs, struct file * file); + unsigned long min_coredump; /* minimal dump size */ }; extern int register_binfmt(struct linux_binfmt *); @@ -66,6 +67,7 @@ extern int setup_arg_pages(struct linux_binprm * bprm); extern int copy_strings(int argc,char ** argv,struct linux_binprm *bprm); extern int copy_strings_kernel(int argc,char ** argv,struct linux_binprm *bprm); extern void compute_creds(struct linux_binprm *binprm); +extern int do_coredump(long signr, struct pt_regs * regs); #if 0 diff --git a/include/linux/parport.h b/include/linux/parport.h index fa8db76db1b6..b6e0317e65ef 100644 --- a/include/linux/parport.h +++ b/include/linux/parport.h @@ -74,6 +74,7 @@ typedef enum { * parport_negotiate to use address operations. They have no effect * other than to make parport_read/write use address transfers. */ #define IEEE1284_ADDR (1<<13) /* This is a flag */ +#define IEEE1284_DATA 0 /* So is this */ /* The rest is for the kernel only */ #ifdef __KERNEL__ diff --git a/kernel/fork.c b/kernel/fork.c index 4fe376d1b378..b11112ceb817 100644 --- a/kernel/fork.c +++ b/kernel/fork.c @@ -300,7 +300,6 @@ struct mm_struct * mm_alloc(void) mm = kmem_cache_alloc(mm_cachep, SLAB_KERNEL); if (mm) { memset(mm, 0, sizeof(*mm)); - init_new_context(mm); atomic_set(&mm->mm_users, 1); atomic_set(&mm->mm_count, 1); init_MUTEX(&mm->mmap_sem); @@ -409,7 +408,7 @@ static inline int copy_mm(unsigned long clone_flags, struct task_struct * tsk) good_mm: tsk->mm = mm; tsk->active_mm = mm; - SET_PAGE_DIR(tsk, mm->pgd); + init_new_context(tsk,mm); return 0; free_mm: diff --git a/net/ipv4/tcp_ipv4.c b/net/ipv4/tcp_ipv4.c index 3c5102b42435..0b36c6a69514 100644 --- a/net/ipv4/tcp_ipv4.c +++ b/net/ipv4/tcp_ipv4.c @@ -401,10 +401,9 @@ static struct sock *tcp_v4_lookup_listener(u32 daddr, unsigned short hnum, int d * The sockhash lock must be held as a reader here. */ static inline struct sock *__tcp_v4_lookup(u32 saddr, u16 sport, - u32 daddr, u16 dport, int dif) + u32 daddr, u16 hnum, int dif) { TCP_V4_ADDR_COOKIE(acookie, saddr, daddr) - __u16 hnum = ntohs(dport); __u32 ports = TCP_COMBINED_PORTS(sport, hnum); struct sock *sk; int hash; @@ -439,7 +438,7 @@ __inline__ struct sock *tcp_v4_lookup(u32 saddr, u16 sport, u32 daddr, u16 dport struct sock *sk; SOCKHASH_LOCK_READ(); - sk = __tcp_v4_lookup(saddr, sport, daddr, dport, dif); + sk = __tcp_v4_lookup(saddr, sport, daddr, ntohs(dport), dif); SOCKHASH_UNLOCK_READ(); return sk; @@ -1729,7 +1728,7 @@ int tcp_v4_rcv(struct sk_buff *skb, unsigned short len) #endif SOCKHASH_LOCK_READ_BH(); sk = __tcp_v4_lookup(skb->nh.iph->saddr, th->source, - skb->nh.iph->daddr, th->dest, skb->dev->ifindex); + skb->nh.iph->daddr, ntohs(th->dest), skb->dev->ifindex); SOCKHASH_UNLOCK_READ_BH(); #ifdef CONFIG_IP_TRANSPARENT_PROXY if (!sk) diff --git a/scripts/ver_linux b/scripts/ver_linux index a1b8642a45a4..b885791ddc55 100644 --- a/scripts/ver_linux +++ b/scripts/ver_linux @@ -5,7 +5,7 @@ # differ on your system. # PATH=/sbin:/usr/sbin:/bin:/usr/bin:$PATH -echo '-- Versions installed: (if some fields are empty or looks' +echo '-- Versions installed: (if some fields are empty or look' echo '-- unusual then possibly you have very old versions)' uname -a insmod -V 2>&1 | awk 'NR==1 {print "Kernel modules ",$NF}' -- 2.39.5