Merge to Fedora kernel-2.6.18-1.2239_FC5 patched with stable patch-2.6.18.2-vs2.0...
authorMarc Fiuczynski <mef@cs.princeton.edu>
Mon, 13 Nov 2006 19:54:30 +0000 (19:54 +0000)
committerMarc Fiuczynski <mef@cs.princeton.edu>
Mon, 13 Nov 2006 19:54:30 +0000 (19:54 +0000)
65 files changed:
.config
.config.old
arch/i386/mach-voyager/voyager_thread.c
arch/s390/kernel/compat_signal.c
arch/s390/kernel/ptrace.c
arch/sparc64/solaris/misc.c
arch/um/kernel/exec.c
configs/kernel-2.6.18-i586-smp.config
configs/kernel-2.6.18-i586.config
configs/kernel-2.6.18-i686-kdump.config
configs/kernel-2.6.18-i686-smp.config
configs/kernel-2.6.18-i686-xen.config
configs/kernel-2.6.18-i686-xen0.config
configs/kernel-2.6.18-i686-xenU.config
configs/kernel-2.6.18-i686.config
configs/kernel-2.6.18-ia64-xen.config
configs/kernel-2.6.18-ia64.config
configs/kernel-2.6.18-ppc-smp.config
configs/kernel-2.6.18-ppc.config
configs/kernel-2.6.18-ppc64-kdump.config
configs/kernel-2.6.18-ppc64.config
configs/kernel-2.6.18-ppc64iseries.config
configs/kernel-2.6.18-s390.config
configs/kernel-2.6.18-s390x.config
configs/kernel-2.6.18-x86_64-kdump.config
configs/kernel-2.6.18-x86_64-xen.config
configs/kernel-2.6.18-x86_64-xen0.config
configs/kernel-2.6.18-x86_64-xenU.config
configs/kernel-2.6.18-x86_64.config
drivers/char/selection.c
drivers/char/tty_io.c
drivers/char/tty_ioctl.c
drivers/char/vt.c
drivers/char/vt_ioctl.c
drivers/isdn/capi/capidrv.c
drivers/isdn/hisax/config.c
drivers/isdn/icn/icn.c
drivers/isdn/isdnloop/isdnloop.c
drivers/isdn/pcbit/drv.c
drivers/net/e1000/e1000_main.c
drivers/net/forcedeth.c
drivers/net/wan/pc300.h
drivers/s390/char/fs3270.c
drivers/s390/char/tty3270.c
fs/buffer.c
fs/cifs/inode.c
fs/cramfs/inode.c
fs/dquot.c
fs/nfs/direct.c
fs/open.c
fs/proc/array.c
fs/splice.c
include/linux/tracehook.h
include/linux/tty.h
include/linux/utrace.h
include/linux/vs_cvirt.h
include/linux/vt_kern.h
kernel/acct.c
kernel/auditsc.c
kernel/exit.c
kernel/ptrace.c
kernel/sys.c
kernel/utrace.c
mm/migrate.c
security/selinux/hooks.c

diff --git a/.config b/.config
index 813a75a..867d515 100644 (file)
--- a/.config
+++ b/.config
@@ -1,7 +1,7 @@
 #
 # Automatically generated make config: don't edit
-# Linux kernel version: 2.6.18.2-rc1
-# Mon Nov 13 09:44:43 2006
+# Linux kernel version: 2.6.18.2
+# Mon Nov 13 09:32:02 2006
 #
 CONFIG_X86_64=y
 CONFIG_64BIT=y
@@ -177,9 +177,9 @@ CONFIG_KEXEC=y
 CONFIG_PHYSICAL_START=0x200000
 # CONFIG_SECCOMP is not set
 # CONFIG_HZ_100 is not set
-CONFIG_HZ_250=y
-# CONFIG_HZ_1000 is not set
-CONFIG_HZ=250
+# CONFIG_HZ_250 is not set
+CONFIG_HZ_1000=y
+CONFIG_HZ=1000
 CONFIG_REORDER=y
 CONFIG_K8_NB=y
 CONFIG_GENERIC_HARDIRQS=y
@@ -1973,23 +1973,7 @@ CONFIG_SENSORS_MAX6875=m
 #
 # Dallas's 1-wire bus
 #
-CONFIG_W1=m
-CONFIG_W1_CON=y
-
-#
-# 1-wire Bus Masters
-#
-CONFIG_W1_MASTER_MATROX=m
-CONFIG_W1_MASTER_DS2490=m
-CONFIG_W1_MASTER_DS2482=m
-
-#
-# 1-wire Slaves
-#
-CONFIG_W1_SLAVE_THERM=m
-CONFIG_W1_SLAVE_SMEM=m
-CONFIG_W1_SLAVE_DS2433=m
-CONFIG_W1_SLAVE_DS2433_CRC=y
+# CONFIG_W1 is not set
 
 #
 # Hardware Monitoring support
index e5440ae..90ead9a 100644 (file)
@@ -1591,7 +1591,7 @@ CONFIG_SENSORS_W83627EHF=m
 CONFIG_SENSORS_W83791D=m
 CONFIG_SENSORS_W83792D=m
 
-CONFIG_W1=m
+# CONFIG_W1 is not set
 CONFIG_W1_MASTER_MATROX=m
 CONFIG_W1_MASTER_DS2482=m
 CONFIG_W1_SLAVE_THERM=m
@@ -2868,6 +2868,9 @@ CONFIG_CACHEFILES_DEBUG=y
 CONFIG_NFS_FSCACHE=y
 
 # CONFIG_SECURITY_SELINUX_POLICYDB_VERSION_MAX is not set
+
+CONFIG_HZ_1000=y
+
 CONFIG_UID16=y
 # CONFIG_X86_64_XEN is not set
 # CONFIG_MK8 is not set
index 50f6de6..f398873 100644 (file)
@@ -130,7 +130,6 @@ thread(void *unused)
        init_timer(&wakeup_timer);
 
        sigfillset(&current->blocked);
-       current->signal->tty = NULL;
 
        printk(KERN_NOTICE "Voyager starting monitor thread\n");
 
index bdb86e7..310d168 100644 (file)
@@ -586,4 +586,3 @@ handle_signal32(unsigned long sig, struct k_sigaction *ka,
 
        return ret;
 }
-
index 74c3133..395bd3a 100644 (file)
@@ -680,606 +680,6 @@ fastcall int arch_compat_ptrace(compat_long_t *request,
 #endif /* CONFIG_PTRACE */
 
 
-#if 0                          /* XXX */
-
-#ifndef CONFIG_64BIT
-# define __ADDR_MASK 3
-#else
-# define __ADDR_MASK 7
-#endif
-
-/*
- * Read the word at offset addr from the user area of a process. The
- * trouble here is that the information is littered over different
- * locations. The process registers are found on the kernel stack,
- * the floating point stuff and the trace settings are stored in
- * the task structure. In addition the different structures in
- * struct user contain pad bytes that should be read as zeroes.
- * Lovely...
- */
-static int
-peek_user(struct task_struct *child, addr_t addr, addr_t data)
-{
-       struct user *dummy = NULL;
-       addr_t offset, tmp, mask;
-
-       /*
-        * Stupid gdb peeks/pokes the access registers in 64 bit with
-        * an alignment of 4. Programmers from hell...
-        */
-       mask = __ADDR_MASK;
-#ifdef CONFIG_64BIT
-       if (addr >= (addr_t) &dummy->regs.acrs &&
-           addr < (addr_t) &dummy->regs.orig_gpr2)
-               mask = 3;
-#endif
-       if ((addr & mask) || addr > sizeof(struct user) - __ADDR_MASK)
-               return -EIO;
-
-       if (addr < (addr_t) &dummy->regs.acrs) {
-               /*
-                * psw and gprs are stored on the stack
-                */
-               tmp = *(addr_t *)((addr_t) &task_pt_regs(child)->psw + addr);
-               if (addr == (addr_t) &dummy->regs.psw.mask)
-                       /* Remove per bit from user psw. */
-                       tmp &= ~PSW_MASK_PER;
-
-       } else if (addr < (addr_t) &dummy->regs.orig_gpr2) {
-               /*
-                * access registers are stored in the thread structure
-                */
-               offset = addr - (addr_t) &dummy->regs.acrs;
-#ifdef CONFIG_64BIT
-               /*
-                * Very special case: old & broken 64 bit gdb reading
-                * from acrs[15]. Result is a 64 bit value. Read the
-                * 32 bit acrs[15] value and shift it by 32. Sick...
-                */
-               if (addr == (addr_t) &dummy->regs.acrs[15])
-                       tmp = ((unsigned long) child->thread.acrs[15]) << 32;
-               else
-#endif
-               tmp = *(addr_t *)((addr_t) &child->thread.acrs + offset);
-
-       } else if (addr == (addr_t) &dummy->regs.orig_gpr2) {
-               /*
-                * orig_gpr2 is stored on the kernel stack
-                */
-               tmp = (addr_t) task_pt_regs(child)->orig_gpr2;
-
-       } else if (addr < (addr_t) (&dummy->regs.fp_regs + 1)) {
-               /* 
-                * floating point regs. are stored in the thread structure
-                */
-               offset = addr - (addr_t) &dummy->regs.fp_regs;
-               tmp = *(addr_t *)((addr_t) &child->thread.fp_regs + offset);
-               if (addr == (addr_t) &dummy->regs.fp_regs.fpc)
-                       tmp &= (unsigned long) FPC_VALID_MASK
-                               << (BITS_PER_LONG - 32);
-
-       } else if (addr < (addr_t) (&dummy->regs.per_info + 1)) {
-               /*
-                * per_info is found in the thread structure
-                */
-               offset = addr - (addr_t) &dummy->regs.per_info;
-               tmp = *(addr_t *)((addr_t) &child->thread.per_info + offset);
-
-       } else
-               tmp = 0;
-
-       return put_user(tmp, (addr_t __user *) data);
-}
-
-/*
- * Write a word to the user area of a process at location addr. This
- * operation does have an additional problem compared to peek_user.
- * Stores to the program status word and on the floating point
- * control register needs to get checked for validity.
- */
-static int
-poke_user(struct task_struct *child, addr_t addr, addr_t data)
-{
-       struct user *dummy = NULL;
-       addr_t offset, mask;
-
-       /*
-        * Stupid gdb peeks/pokes the access registers in 64 bit with
-        * an alignment of 4. Programmers from hell indeed...
-        */
-       mask = __ADDR_MASK;
-#ifdef CONFIG_64BIT
-       if (addr >= (addr_t) &dummy->regs.acrs &&
-           addr < (addr_t) &dummy->regs.orig_gpr2)
-               mask = 3;
-#endif
-       if ((addr & mask) || addr > sizeof(struct user) - __ADDR_MASK)
-               return -EIO;
-
-       if (addr < (addr_t) &dummy->regs.acrs) {
-               /*
-                * psw and gprs are stored on the stack
-                */
-               if (addr == (addr_t) &dummy->regs.psw.mask &&
-#ifdef CONFIG_COMPAT
-                   data != PSW_MASK_MERGE(PSW_USER32_BITS, data) &&
-#endif
-                   data != PSW_MASK_MERGE(PSW_USER_BITS, data))
-                       /* Invalid psw mask. */
-                       return -EINVAL;
-#ifndef CONFIG_64BIT
-               if (addr == (addr_t) &dummy->regs.psw.addr)
-                       /* I'd like to reject addresses without the
-                          high order bit but older gdb's rely on it */
-                       data |= PSW_ADDR_AMODE;
-#endif
-               *(addr_t *)((addr_t) &task_pt_regs(child)->psw + addr) = data;
-
-       } else if (addr < (addr_t) (&dummy->regs.orig_gpr2)) {
-               /*
-                * access registers are stored in the thread structure
-                */
-               offset = addr - (addr_t) &dummy->regs.acrs;
-#ifdef CONFIG_64BIT
-               /*
-                * Very special case: old & broken 64 bit gdb writing
-                * to acrs[15] with a 64 bit value. Ignore the lower
-                * half of the value and write the upper 32 bit to
-                * acrs[15]. Sick...
-                */
-               if (addr == (addr_t) &dummy->regs.acrs[15])
-                       child->thread.acrs[15] = (unsigned int) (data >> 32);
-               else
-#endif
-               *(addr_t *)((addr_t) &child->thread.acrs + offset) = data;
-
-       } else if (addr == (addr_t) &dummy->regs.orig_gpr2) {
-               /*
-                * orig_gpr2 is stored on the kernel stack
-                */
-               task_pt_regs(child)->orig_gpr2 = data;
-
-       } else if (addr < (addr_t) (&dummy->regs.fp_regs + 1)) {
-               /*
-                * floating point regs. are stored in the thread structure
-                */
-               if (addr == (addr_t) &dummy->regs.fp_regs.fpc &&
-                   (data & ~((unsigned long) FPC_VALID_MASK
-                             << (BITS_PER_LONG - 32))) != 0)
-                       return -EINVAL;
-               offset = addr - (addr_t) &dummy->regs.fp_regs;
-               *(addr_t *)((addr_t) &child->thread.fp_regs + offset) = data;
-
-       } else if (addr < (addr_t) (&dummy->regs.per_info + 1)) {
-               /*
-                * per_info is found in the thread structure 
-                */
-               offset = addr - (addr_t) &dummy->regs.per_info;
-               *(addr_t *)((addr_t) &child->thread.per_info + offset) = data;
-
-       }
-
-       FixPerRegisters(child);
-       return 0;
-}
-
-static int
-do_ptrace_normal(struct task_struct *child, long request, long addr, long data)
-{
-       unsigned long tmp;
-       ptrace_area parea; 
-       int copied, ret;
-
-       switch (request) {
-       case PTRACE_PEEKTEXT:
-       case PTRACE_PEEKDATA:
-               /* Remove high order bit from address (only for 31 bit). */
-               addr &= PSW_ADDR_INSN;
-               /* read word at location addr. */
-               copied = access_process_vm(child, addr, &tmp, sizeof(tmp), 0);
-               if (copied != sizeof(tmp))
-                       return -EIO;
-               return put_user(tmp, (unsigned long __user *) data);
-
-       case PTRACE_PEEKUSR:
-               /* read the word at location addr in the USER area. */
-               return peek_user(child, addr, data);
-
-       case PTRACE_POKETEXT:
-       case PTRACE_POKEDATA:
-               /* Remove high order bit from address (only for 31 bit). */
-               addr &= PSW_ADDR_INSN;
-               /* write the word at location addr. */
-               copied = access_process_vm(child, addr, &data, sizeof(data),1);
-               if (copied != sizeof(data))
-                       return -EIO;
-               return 0;
-
-       case PTRACE_POKEUSR:
-               /* write the word at location addr in the USER area */
-               return poke_user(child, addr, data);
-
-       case PTRACE_PEEKUSR_AREA:
-       case PTRACE_POKEUSR_AREA:
-               if (copy_from_user(&parea, (void __user *) addr,
-                                                       sizeof(parea)))
-                       return -EFAULT;
-               addr = parea.kernel_addr;
-               data = parea.process_addr;
-               copied = 0;
-               while (copied < parea.len) {
-                       if (request == PTRACE_PEEKUSR_AREA)
-                               ret = peek_user(child, addr, data);
-                       else {
-                               addr_t tmp;
-                               if (get_user (tmp, (addr_t __user *) data))
-                                       return -EFAULT;
-                               ret = poke_user(child, addr, tmp);
-                       }
-                       if (ret)
-                               return ret;
-                       addr += sizeof(unsigned long);
-                       data += sizeof(unsigned long);
-                       copied += sizeof(unsigned long);
-               }
-               return 0;
-       }
-       return ptrace_request(child, request, addr, data);
-}
-
-#ifdef CONFIG_COMPAT
-/*
- * Now the fun part starts... a 31 bit program running in the
- * 31 bit emulation tracing another program. PTRACE_PEEKTEXT,
- * PTRACE_PEEKDATA, PTRACE_POKETEXT and PTRACE_POKEDATA are easy
- * to handle, the difference to the 64 bit versions of the requests
- * is that the access is done in multiples of 4 byte instead of
- * 8 bytes (sizeof(unsigned long) on 31/64 bit).
- * The ugly part are PTRACE_PEEKUSR, PTRACE_PEEKUSR_AREA,
- * PTRACE_POKEUSR and PTRACE_POKEUSR_AREA. If the traced program
- * is a 31 bit program too, the content of struct user can be
- * emulated. A 31 bit program peeking into the struct user of
- * a 64 bit program is a no-no.
- */
-
-/*
- * Same as peek_user but for a 31 bit program.
- */
-static int
-peek_user_emu31(struct task_struct *child, addr_t addr, addr_t data)
-{
-       struct user32 *dummy32 = NULL;
-       per_struct32 *dummy_per32 = NULL;
-       addr_t offset;
-       __u32 tmp;
-
-       if (!test_thread_flag(TIF_31BIT) ||
-           (addr & 3) || addr > sizeof(struct user) - 3)
-               return -EIO;
-
-       if (addr < (addr_t) &dummy32->regs.acrs) {
-               /*
-                * psw and gprs are stored on the stack
-                */
-               if (addr == (addr_t) &dummy32->regs.psw.mask) {
-                       /* Fake a 31 bit psw mask. */
-                       tmp = (__u32)(task_pt_regs(child)->psw.mask >> 32);
-                       tmp = PSW32_MASK_MERGE(PSW32_USER_BITS, tmp);
-               } else if (addr == (addr_t) &dummy32->regs.psw.addr) {
-                       /* Fake a 31 bit psw address. */
-                       tmp = (__u32) task_pt_regs(child)->psw.addr |
-                               PSW32_ADDR_AMODE31;
-               } else {
-                       /* gpr 0-15 */
-                       tmp = *(__u32 *)((addr_t) &task_pt_regs(child)->psw +
-                                        addr*2 + 4);
-               }
-       } else if (addr < (addr_t) (&dummy32->regs.orig_gpr2)) {
-               /*
-                * access registers are stored in the thread structure
-                */
-               offset = addr - (addr_t) &dummy32->regs.acrs;
-               tmp = *(__u32*)((addr_t) &child->thread.acrs + offset);
-
-       } else if (addr == (addr_t) (&dummy32->regs.orig_gpr2)) {
-               /*
-                * orig_gpr2 is stored on the kernel stack
-                */
-               tmp = *(__u32*)((addr_t) &task_pt_regs(child)->orig_gpr2 + 4);
-
-       } else if (addr < (addr_t) (&dummy32->regs.fp_regs + 1)) {
-               /*
-                * floating point regs. are stored in the thread structure 
-                */
-               offset = addr - (addr_t) &dummy32->regs.fp_regs;
-               tmp = *(__u32 *)((addr_t) &child->thread.fp_regs + offset);
-
-       } else if (addr < (addr_t) (&dummy32->regs.per_info + 1)) {
-               /*
-                * per_info is found in the thread structure
-                */
-               offset = addr - (addr_t) &dummy32->regs.per_info;
-               /* This is magic. See per_struct and per_struct32. */
-               if ((offset >= (addr_t) &dummy_per32->control_regs &&
-                    offset < (addr_t) (&dummy_per32->control_regs + 1)) ||
-                   (offset >= (addr_t) &dummy_per32->starting_addr &&
-                    offset <= (addr_t) &dummy_per32->ending_addr) ||
-                   offset == (addr_t) &dummy_per32->lowcore.words.address)
-                       offset = offset*2 + 4;
-               else
-                       offset = offset*2;
-               tmp = *(__u32 *)((addr_t) &child->thread.per_info + offset);
-
-       } else
-               tmp = 0;
-
-       return put_user(tmp, (__u32 __user *) data);
-}
-
-/*
- * Same as poke_user but for a 31 bit program.
- */
-static int
-poke_user_emu31(struct task_struct *child, addr_t addr, addr_t data)
-{
-       struct user32 *dummy32 = NULL;
-       per_struct32 *dummy_per32 = NULL;
-       addr_t offset;
-       __u32 tmp;
-
-       if (!test_thread_flag(TIF_31BIT) ||
-           (addr & 3) || addr > sizeof(struct user32) - 3)
-               return -EIO;
-
-       tmp = (__u32) data;
-
-       if (addr < (addr_t) &dummy32->regs.acrs) {
-               /*
-                * psw, gprs, acrs and orig_gpr2 are stored on the stack
-                */
-               if (addr == (addr_t) &dummy32->regs.psw.mask) {
-                       /* Build a 64 bit psw mask from 31 bit mask. */
-                       if (tmp != PSW32_MASK_MERGE(PSW32_USER_BITS, tmp))
-                               /* Invalid psw mask. */
-                               return -EINVAL;
-                       task_pt_regs(child)->psw.mask =
-                               PSW_MASK_MERGE(PSW_USER32_BITS, (__u64) tmp << 32);
-               } else if (addr == (addr_t) &dummy32->regs.psw.addr) {
-                       /* Build a 64 bit psw address from 31 bit address. */
-                       task_pt_regs(child)->psw.addr =
-                               (__u64) tmp & PSW32_ADDR_INSN;
-               } else {
-                       /* gpr 0-15 */
-                       *(__u32*)((addr_t) &task_pt_regs(child)->psw
-                                 + addr*2 + 4) = tmp;
-               }
-       } else if (addr < (addr_t) (&dummy32->regs.orig_gpr2)) {
-               /*
-                * access registers are stored in the thread structure
-                */
-               offset = addr - (addr_t) &dummy32->regs.acrs;
-               *(__u32*)((addr_t) &child->thread.acrs + offset) = tmp;
-
-       } else if (addr == (addr_t) (&dummy32->regs.orig_gpr2)) {
-               /*
-                * orig_gpr2 is stored on the kernel stack
-                */
-               *(__u32*)((addr_t) &task_pt_regs(child)->orig_gpr2 + 4) = tmp;
-
-       } else if (addr < (addr_t) (&dummy32->regs.fp_regs + 1)) {
-               /*
-                * floating point regs. are stored in the thread structure 
-                */
-               if (addr == (addr_t) &dummy32->regs.fp_regs.fpc &&
-                   (tmp & ~FPC_VALID_MASK) != 0)
-                       /* Invalid floating point control. */
-                       return -EINVAL;
-               offset = addr - (addr_t) &dummy32->regs.fp_regs;
-               *(__u32 *)((addr_t) &child->thread.fp_regs + offset) = tmp;
-
-       } else if (addr < (addr_t) (&dummy32->regs.per_info + 1)) {
-               /*
-                * per_info is found in the thread structure.
-                */
-               offset = addr - (addr_t) &dummy32->regs.per_info;
-               /*
-                * This is magic. See per_struct and per_struct32.
-                * By incident the offsets in per_struct are exactly
-                * twice the offsets in per_struct32 for all fields.
-                * The 8 byte fields need special handling though,
-                * because the second half (bytes 4-7) is needed and
-                * not the first half.
-                */
-               if ((offset >= (addr_t) &dummy_per32->control_regs &&
-                    offset < (addr_t) (&dummy_per32->control_regs + 1)) ||
-                   (offset >= (addr_t) &dummy_per32->starting_addr &&
-                    offset <= (addr_t) &dummy_per32->ending_addr) ||
-                   offset == (addr_t) &dummy_per32->lowcore.words.address)
-                       offset = offset*2 + 4;
-               else
-                       offset = offset*2;
-               *(__u32 *)((addr_t) &child->thread.per_info + offset) = tmp;
-
-       }
-
-       FixPerRegisters(child);
-       return 0;
-}
-
-static int
-do_ptrace_emu31(struct task_struct *child, long request, long addr, long data)
-{
-       unsigned int tmp;  /* 4 bytes !! */
-       ptrace_area_emu31 parea; 
-       int copied, ret;
-
-       switch (request) {
-       case PTRACE_PEEKTEXT:
-       case PTRACE_PEEKDATA:
-               /* read word at location addr. */
-               copied = access_process_vm(child, addr, &tmp, sizeof(tmp), 0);
-               if (copied != sizeof(tmp))
-                       return -EIO;
-               return put_user(tmp, (unsigned int __user *) data);
-
-       case PTRACE_PEEKUSR:
-               /* read the word at location addr in the USER area. */
-               return peek_user_emu31(child, addr, data);
-
-       case PTRACE_POKETEXT:
-       case PTRACE_POKEDATA:
-               /* write the word at location addr. */
-               tmp = data;
-               copied = access_process_vm(child, addr, &tmp, sizeof(tmp), 1);
-               if (copied != sizeof(tmp))
-                       return -EIO;
-               return 0;
-
-       case PTRACE_POKEUSR:
-               /* write the word at location addr in the USER area */
-               return poke_user_emu31(child, addr, data);
-
-       case PTRACE_PEEKUSR_AREA:
-       case PTRACE_POKEUSR_AREA:
-               if (copy_from_user(&parea, (void __user *) addr,
-                                                       sizeof(parea)))
-                       return -EFAULT;
-               addr = parea.kernel_addr;
-               data = parea.process_addr;
-               copied = 0;
-               while (copied < parea.len) {
-                       if (request == PTRACE_PEEKUSR_AREA)
-                               ret = peek_user_emu31(child, addr, data);
-                       else {
-                               __u32 tmp;
-                               if (get_user (tmp, (__u32 __user *) data))
-                                       return -EFAULT;
-                               ret = poke_user_emu31(child, addr, tmp);
-                       }
-                       if (ret)
-                               return ret;
-                       addr += sizeof(unsigned int);
-                       data += sizeof(unsigned int);
-                       copied += sizeof(unsigned int);
-               }
-               return 0;
-#if 0                          /* XXX */
-       case PTRACE_GETEVENTMSG:
-               return put_user((__u32) child->ptrace_message,
-                               (unsigned int __user *) data);
-       case PTRACE_GETSIGINFO:
-               if (child->last_siginfo == NULL)
-                       return -EINVAL;
-               return copy_siginfo_to_user32((compat_siginfo_t __user *) data,
-                                             child->last_siginfo);
-       case PTRACE_SETSIGINFO:
-               if (child->last_siginfo == NULL)
-                       return -EINVAL;
-               return copy_siginfo_from_user32(child->last_siginfo,
-                                               (compat_siginfo_t __user *) data);
-#endif
-       }
-       return ptrace_request(child, request, addr, data);
-}
-#endif
-
-#define PT32_IEEE_IP 0x13c
-
-static int
-do_ptrace(struct task_struct *child, long request, long addr, long data)
-{
-       int ret;
-
-       if (request == PTRACE_ATTACH)
-               return ptrace_attach(child);
-
-       /*
-        * Special cases to get/store the ieee instructions pointer.
-        */
-       if (child == current) {
-               if (request == PTRACE_PEEKUSR && addr == PT_IEEE_IP)
-                       return peek_user(child, addr, data);
-               if (request == PTRACE_POKEUSR && addr == PT_IEEE_IP)
-                       return poke_user(child, addr, data);
-#ifdef CONFIG_COMPAT
-               if (request == PTRACE_PEEKUSR &&
-                   addr == PT32_IEEE_IP && test_thread_flag(TIF_31BIT))
-                       return peek_user_emu31(child, addr, data);
-               if (request == PTRACE_POKEUSR &&
-                   addr == PT32_IEEE_IP && test_thread_flag(TIF_31BIT))
-                       return poke_user_emu31(child, addr, data);
-#endif
-       }
-
-       ret = ptrace_check_attach(child, request == PTRACE_KILL);
-       if (ret < 0)
-               return ret;
-
-       switch (request) {
-       case PTRACE_SYSCALL:
-               /* continue and stop at next (return from) syscall */
-       case PTRACE_CONT:
-               /* restart after signal. */
-               if (!valid_signal(data))
-                       return -EIO;
-               if (request == PTRACE_SYSCALL)
-                       set_tsk_thread_flag(child, TIF_SYSCALL_TRACE);
-               else
-                       clear_tsk_thread_flag(child, TIF_SYSCALL_TRACE);
-               child->exit_code = data;
-               /* make sure the single step bit is not set. */
-               tracehook_disable_single_step(child);
-               wake_up_process(child);
-               return 0;
-
-       case PTRACE_KILL:
-               /*
-                * make the child exit.  Best I can do is send it a sigkill. 
-                * perhaps it should be put in the status that it wants to 
-                * exit.
-                */
-               if (child->exit_state == EXIT_ZOMBIE) /* already dead */
-                       return 0;
-               child->exit_code = SIGKILL;
-               /* make sure the single step bit is not set. */
-               tracehook_disable_single_step(child);
-               wake_up_process(child);
-               return 0;
-
-       case PTRACE_SINGLESTEP:
-               /* set the trap flag. */
-               if (!valid_signal(data))
-                       return -EIO;
-               clear_tsk_thread_flag(child, TIF_SYSCALL_TRACE);
-               child->exit_code = data;
-               if (data)
-                       set_tsk_thread_flag(child, TIF_SINGLE_STEP);
-               else
-                       tracehook_enable_single_step(child);
-               /* give it a chance to run. */
-               wake_up_process(child);
-               return 0;
-
-       case PTRACE_DETACH:
-               /* detach a process that was attached. */
-               return ptrace_detach(child, data);
-
-
-       /* Do requests that differ for 31/64 bit */
-       default:
-#ifdef CONFIG_COMPAT
-               if (test_thread_flag(TIF_31BIT))
-                       return do_ptrace_emu31(child, request, addr, data);
-#endif
-               return do_ptrace_normal(child, request, addr, data);
-       }
-       /* Not reached.  */
-       return -EIO;
-}
-#endif
-
-
-
 asmlinkage void
 syscall_trace(struct pt_regs *regs, int entryexit)
 {
index a7f0dac..ebd4207 100644 (file)
@@ -11,6 +11,7 @@
 #include <linux/limits.h>
 #include <linux/mm.h>
 #include <linux/smp.h>
+#include <linux/tty.h>
 #include <linux/mman.h>
 #include <linux/file.h>
 #include <linux/timex.h>
@@ -423,7 +424,7 @@ asmlinkage int solaris_procids(int cmd, s32 pid, s32 pgid)
                           Solaris setpgrp and setsid? */
                        ret = sys_setpgid(0, 0);
                        if (ret) return ret;
-                       current->signal->tty = NULL;
+                       proc_clear_tty(current);
                        return process_group(current);
                }
        case 2: /* getsid */
index fc38a6d..8d56ec6 100644 (file)
@@ -39,11 +39,14 @@ static long execve1(char *file, char __user * __user *argv,
                    char __user *__user *env)
 {
         long error;
+       struct tty_struct *tty;
 
 #ifdef CONFIG_TTY_LOG
-       task_lock(current);
-       log_exec(argv, current->signal->tty);
-       task_unlock(current);
+       mutex_lock(&tty_mutex);
+       tty = get_current_tty();
+       if (tty)
+               log_exec(argv, tty);
+       mutex_unlock(&tty_mutex);
 #endif
         error = do_execve(file, argv, env, &current->thread.regs);
         if (error == 0){
index 224fc97..61a8317 100644 (file)
@@ -1,8 +1,8 @@
 # i386
 #
 # Automatically generated make config: don't edit
-# Linux kernel version: 2.6.18.2-rc1
-# Mon Nov 13 09:44:39 2006
+# Linux kernel version: 2.6.18.2
+# Mon Nov 13 09:31:57 2006
 #
 CONFIG_X86_32=y
 CONFIG_GENERIC_TIME=y
@@ -212,9 +212,9 @@ CONFIG_BOOT_IOREMAP=y
 CONFIG_REGPARM=y
 # CONFIG_SECCOMP is not set
 # CONFIG_HZ_100 is not set
-CONFIG_HZ_250=y
-# CONFIG_HZ_1000 is not set
-CONFIG_HZ=250
+# CONFIG_HZ_250 is not set
+CONFIG_HZ_1000=y
+CONFIG_HZ=1000
 CONFIG_KEXEC=y
 # CONFIG_CRASH_DUMP is not set
 CONFIG_PHYSICAL_START=0x400000
index 906c52b..f47689d 100644 (file)
@@ -1,8 +1,8 @@
 # i386
 #
 # Automatically generated make config: don't edit
-# Linux kernel version: 2.6.18.2-rc1
-# Mon Nov 13 09:44:39 2006
+# Linux kernel version: 2.6.18.2
+# Mon Nov 13 09:31:57 2006
 #
 CONFIG_X86_32=y
 CONFIG_GENERIC_TIME=y
@@ -202,9 +202,9 @@ CONFIG_BOOT_IOREMAP=y
 CONFIG_REGPARM=y
 # CONFIG_SECCOMP is not set
 # CONFIG_HZ_100 is not set
-CONFIG_HZ_250=y
-# CONFIG_HZ_1000 is not set
-CONFIG_HZ=250
+# CONFIG_HZ_250 is not set
+CONFIG_HZ_1000=y
+CONFIG_HZ=1000
 CONFIG_KEXEC=y
 # CONFIG_CRASH_DUMP is not set
 CONFIG_PHYSICAL_START=0x400000
index 8e2ca42..d42285d 100644 (file)
@@ -1,8 +1,8 @@
 # i386
 #
 # Automatically generated make config: don't edit
-# Linux kernel version: 2.6.18.2-rc1
-# Mon Nov 13 09:44:39 2006
+# Linux kernel version: 2.6.18.2
+# Mon Nov 13 09:31:57 2006
 #
 CONFIG_X86_32=y
 CONFIG_GENERIC_TIME=y
@@ -209,9 +209,9 @@ CONFIG_BOOT_IOREMAP=y
 CONFIG_REGPARM=y
 # CONFIG_SECCOMP is not set
 # CONFIG_HZ_100 is not set
-CONFIG_HZ_250=y
-# CONFIG_HZ_1000 is not set
-CONFIG_HZ=250
+# CONFIG_HZ_250 is not set
+CONFIG_HZ_1000=y
+CONFIG_HZ=1000
 CONFIG_KEXEC=y
 CONFIG_CRASH_DUMP=y
 CONFIG_PHYSICAL_START=0x1000000
@@ -2171,23 +2171,7 @@ CONFIG_SENSORS_MAX6875=m
 #
 # Dallas's 1-wire bus
 #
-CONFIG_W1=m
-CONFIG_W1_CON=y
-
-#
-# 1-wire Bus Masters
-#
-CONFIG_W1_MASTER_MATROX=m
-CONFIG_W1_MASTER_DS2490=m
-CONFIG_W1_MASTER_DS2482=m
-
-#
-# 1-wire Slaves
-#
-CONFIG_W1_SLAVE_THERM=m
-CONFIG_W1_SLAVE_SMEM=m
-CONFIG_W1_SLAVE_DS2433=m
-CONFIG_W1_SLAVE_DS2433_CRC=y
+# CONFIG_W1 is not set
 
 #
 # Hardware Monitoring support
index 00cc6b4..52cad34 100644 (file)
@@ -1,8 +1,8 @@
 # i386
 #
 # Automatically generated make config: don't edit
-# Linux kernel version: 2.6.18.2-rc1
-# Mon Nov 13 09:44:40 2006
+# Linux kernel version: 2.6.18.2
+# Mon Nov 13 09:31:58 2006
 #
 CONFIG_X86_32=y
 CONFIG_GENERIC_TIME=y
@@ -213,9 +213,9 @@ CONFIG_BOOT_IOREMAP=y
 CONFIG_REGPARM=y
 # CONFIG_SECCOMP is not set
 # CONFIG_HZ_100 is not set
-CONFIG_HZ_250=y
-# CONFIG_HZ_1000 is not set
-CONFIG_HZ=250
+# CONFIG_HZ_250 is not set
+CONFIG_HZ_1000=y
+CONFIG_HZ=1000
 CONFIG_KEXEC=y
 # CONFIG_CRASH_DUMP is not set
 CONFIG_PHYSICAL_START=0x400000
@@ -2169,23 +2169,7 @@ CONFIG_SENSORS_MAX6875=m
 #
 # Dallas's 1-wire bus
 #
-CONFIG_W1=m
-CONFIG_W1_CON=y
-
-#
-# 1-wire Bus Masters
-#
-CONFIG_W1_MASTER_MATROX=m
-CONFIG_W1_MASTER_DS2490=m
-CONFIG_W1_MASTER_DS2482=m
-
-#
-# 1-wire Slaves
-#
-CONFIG_W1_SLAVE_THERM=m
-CONFIG_W1_SLAVE_SMEM=m
-CONFIG_W1_SLAVE_DS2433=m
-CONFIG_W1_SLAVE_DS2433_CRC=y
+# CONFIG_W1 is not set
 
 #
 # Hardware Monitoring support
index b6af801..d01024b 100644 (file)
@@ -1,8 +1,8 @@
 # i386
 #
 # Automatically generated make config: don't edit
-# Linux kernel version: 2.6.18.2-rc1
-# Mon Nov 13 09:44:40 2006
+# Linux kernel version: 2.6.18.2
+# Mon Nov 13 09:31:58 2006
 #
 CONFIG_X86_32=y
 CONFIG_LOCKDEP_SUPPORT=y
@@ -2023,23 +2023,7 @@ CONFIG_SENSORS_MAX6875=m
 #
 # Dallas's 1-wire bus
 #
-CONFIG_W1=m
-CONFIG_W1_CON=y
-
-#
-# 1-wire Bus Masters
-#
-CONFIG_W1_MASTER_MATROX=m
-CONFIG_W1_MASTER_DS2490=m
-CONFIG_W1_MASTER_DS2482=m
-
-#
-# 1-wire Slaves
-#
-CONFIG_W1_SLAVE_THERM=m
-CONFIG_W1_SLAVE_SMEM=m
-CONFIG_W1_SLAVE_DS2433=m
-CONFIG_W1_SLAVE_DS2433_CRC=y
+# CONFIG_W1 is not set
 
 #
 # Hardware Monitoring support
@@ -3213,8 +3197,8 @@ CONFIG_XEN_PCIDEV_BACKEND_VPCI=y
 # CONFIG_XEN_TPMDEV_BACKEND is not set
 CONFIG_XEN_BLKDEV_FRONTEND=m
 CONFIG_XEN_NETDEV_FRONTEND=m
-CONFIG_XEN_FRAMEBUFFER=y
-CONFIG_XEN_KEYBOARD=y
+# CONFIG_XEN_FRAMEBUFFER is not set
+# CONFIG_XEN_KEYBOARD is not set
 CONFIG_XEN_SCRUB_PAGES=y
 # CONFIG_XEN_DISABLE_SERIAL is not set
 CONFIG_XEN_SYSFS=y
index c6fe1ef..71aa7cc 100644 (file)
@@ -1,8 +1,8 @@
 # i386
 #
 # Automatically generated make config: don't edit
-# Linux kernel version: 2.6.18.2-rc1
-# Mon Nov 13 09:44:40 2006
+# Linux kernel version: 2.6.18.2
+# Mon Nov 13 09:31:58 2006
 #
 CONFIG_X86_32=y
 CONFIG_LOCKDEP_SUPPORT=y
@@ -2021,23 +2021,7 @@ CONFIG_SENSORS_MAX6875=m
 #
 # Dallas's 1-wire bus
 #
-CONFIG_W1=m
-CONFIG_W1_CON=y
-
-#
-# 1-wire Bus Masters
-#
-CONFIG_W1_MASTER_MATROX=m
-CONFIG_W1_MASTER_DS2490=m
-CONFIG_W1_MASTER_DS2482=m
-
-#
-# 1-wire Slaves
-#
-CONFIG_W1_SLAVE_THERM=m
-CONFIG_W1_SLAVE_SMEM=m
-CONFIG_W1_SLAVE_DS2433=m
-CONFIG_W1_SLAVE_DS2433_CRC=y
+# CONFIG_W1 is not set
 
 #
 # Hardware Monitoring support
@@ -3211,8 +3195,8 @@ CONFIG_XEN_PCIDEV_BACKEND_VPCI=y
 # CONFIG_XEN_TPMDEV_BACKEND is not set
 CONFIG_XEN_BLKDEV_FRONTEND=m
 CONFIG_XEN_NETDEV_FRONTEND=m
-CONFIG_XEN_FRAMEBUFFER=y
-CONFIG_XEN_KEYBOARD=y
+# CONFIG_XEN_FRAMEBUFFER is not set
+# CONFIG_XEN_KEYBOARD is not set
 CONFIG_XEN_SCRUB_PAGES=y
 # CONFIG_XEN_DISABLE_SERIAL is not set
 CONFIG_XEN_SYSFS=y
index 309644b..50ea265 100644 (file)
@@ -1,8 +1,8 @@
 # i386
 #
 # Automatically generated make config: don't edit
-# Linux kernel version: 2.6.18.2-rc1
-# Mon Nov 13 09:44:40 2006
+# Linux kernel version: 2.6.18.2
+# Mon Nov 13 09:31:58 2006
 #
 CONFIG_X86_32=y
 CONFIG_LOCKDEP_SUPPORT=y
@@ -1590,8 +1590,8 @@ CONFIG_XEN_BLKDEV_TAP=m
 # CONFIG_XEN_TPMDEV_BACKEND is not set
 CONFIG_XEN_BLKDEV_FRONTEND=y
 CONFIG_XEN_NETDEV_FRONTEND=m
-CONFIG_XEN_FRAMEBUFFER=y
-CONFIG_XEN_KEYBOARD=y
+# CONFIG_XEN_FRAMEBUFFER is not set
+# CONFIG_XEN_KEYBOARD is not set
 CONFIG_XEN_SCRUB_PAGES=y
 CONFIG_XEN_DISABLE_SERIAL=y
 CONFIG_XEN_SYSFS=y
index 96690dc..f11ce54 100644 (file)
@@ -1,8 +1,8 @@
 # i386
 #
 # Automatically generated make config: don't edit
-# Linux kernel version: 2.6.18.2-rc1
-# Mon Nov 13 09:44:41 2006
+# Linux kernel version: 2.6.18.2
+# Mon Nov 13 09:31:58 2006
 #
 CONFIG_X86_32=y
 CONFIG_GENERIC_TIME=y
@@ -208,9 +208,9 @@ CONFIG_BOOT_IOREMAP=y
 CONFIG_REGPARM=y
 # CONFIG_SECCOMP is not set
 # CONFIG_HZ_100 is not set
-CONFIG_HZ_250=y
-# CONFIG_HZ_1000 is not set
-CONFIG_HZ=250
+# CONFIG_HZ_250 is not set
+CONFIG_HZ_1000=y
+CONFIG_HZ=1000
 CONFIG_KEXEC=y
 # CONFIG_CRASH_DUMP is not set
 CONFIG_PHYSICAL_START=0x400000
@@ -2171,23 +2171,7 @@ CONFIG_SENSORS_MAX6875=m
 #
 # Dallas's 1-wire bus
 #
-CONFIG_W1=m
-CONFIG_W1_CON=y
-
-#
-# 1-wire Bus Masters
-#
-CONFIG_W1_MASTER_MATROX=m
-CONFIG_W1_MASTER_DS2490=m
-CONFIG_W1_MASTER_DS2482=m
-
-#
-# 1-wire Slaves
-#
-CONFIG_W1_SLAVE_THERM=m
-CONFIG_W1_SLAVE_SMEM=m
-CONFIG_W1_SLAVE_DS2433=m
-CONFIG_W1_SLAVE_DS2433_CRC=y
+# CONFIG_W1 is not set
 
 #
 # Hardware Monitoring support
index 7fea409..f701d61 100644 (file)
@@ -1,8 +1,8 @@
 # ia64
 #
 # Automatically generated make config: don't edit
-# Linux kernel version: 2.6.18.2-rc1
-# Mon Nov 13 09:44:41 2006
+# Linux kernel version: 2.6.18.2
+# Mon Nov 13 09:31:59 2006
 #
 CONFIG_DEFCONFIG_LIST="/lib/modules/$UNAME_RELEASE/.config"
 
@@ -1718,23 +1718,7 @@ CONFIG_SENSORS_MAX6875=m
 #
 # Dallas's 1-wire bus
 #
-CONFIG_W1=m
-CONFIG_W1_CON=y
-
-#
-# 1-wire Bus Masters
-#
-CONFIG_W1_MASTER_MATROX=m
-CONFIG_W1_MASTER_DS2490=m
-CONFIG_W1_MASTER_DS2482=m
-
-#
-# 1-wire Slaves
-#
-CONFIG_W1_SLAVE_THERM=m
-CONFIG_W1_SLAVE_SMEM=m
-CONFIG_W1_SLAVE_DS2433=m
-CONFIG_W1_SLAVE_DS2433_CRC=y
+# CONFIG_W1 is not set
 
 #
 # Hardware Monitoring support
@@ -2019,9 +2003,9 @@ CONFIG_USB_DABUSB=m
 #
 # CONFIG_FIRMWARE_EDID is not set
 CONFIG_FB=y
-CONFIG_FB_CFB_FILLRECT=y
-CONFIG_FB_CFB_COPYAREA=y
-CONFIG_FB_CFB_IMAGEBLIT=y
+CONFIG_FB_CFB_FILLRECT=m
+CONFIG_FB_CFB_COPYAREA=m
+CONFIG_FB_CFB_IMAGEBLIT=m
 # CONFIG_FB_MACMODES is not set
 # CONFIG_FB_BACKLIGHT is not set
 CONFIG_FB_MODE_HELPERS=y
@@ -2871,8 +2855,8 @@ CONFIG_XEN_NETDEV_LOOPBACK=m
 # CONFIG_XEN_TPMDEV_BACKEND is not set
 CONFIG_XEN_BLKDEV_FRONTEND=m
 CONFIG_XEN_NETDEV_FRONTEND=m
-CONFIG_XEN_FRAMEBUFFER=y
-CONFIG_XEN_KEYBOARD=y
+# CONFIG_XEN_FRAMEBUFFER is not set
+# CONFIG_XEN_KEYBOARD is not set
 CONFIG_XEN_SCRUB_PAGES=y
 CONFIG_XEN_DISABLE_SERIAL=y
 CONFIG_XEN_SYSFS=y
index e6c8653..7b62204 100644 (file)
@@ -1,8 +1,8 @@
 # ia64
 #
 # Automatically generated make config: don't edit
-# Linux kernel version: 2.6.18.2-rc1
-# Mon Nov 13 09:44:41 2006
+# Linux kernel version: 2.6.18.2
+# Mon Nov 13 09:31:59 2006
 #
 CONFIG_DEFCONFIG_LIST="/lib/modules/$UNAME_RELEASE/.config"
 
@@ -123,9 +123,9 @@ CONFIG_IA64_PAGE_SIZE_16KB=y
 CONFIG_PGTABLE_3=y
 # CONFIG_PGTABLE_4 is not set
 # CONFIG_HZ_100 is not set
-CONFIG_HZ_250=y
-# CONFIG_HZ_1000 is not set
-CONFIG_HZ=250
+# CONFIG_HZ_250 is not set
+CONFIG_HZ_1000=y
+CONFIG_HZ=1000
 CONFIG_IA64_L1_CACHE_SHIFT=7
 CONFIG_IA64_CYCLONE=y
 CONFIG_IOSAPIC=y
@@ -1763,23 +1763,7 @@ CONFIG_SENSORS_MAX6875=m
 #
 # Dallas's 1-wire bus
 #
-CONFIG_W1=m
-CONFIG_W1_CON=y
-
-#
-# 1-wire Bus Masters
-#
-CONFIG_W1_MASTER_MATROX=m
-CONFIG_W1_MASTER_DS2490=m
-CONFIG_W1_MASTER_DS2482=m
-
-#
-# 1-wire Slaves
-#
-CONFIG_W1_SLAVE_THERM=m
-CONFIG_W1_SLAVE_SMEM=m
-CONFIG_W1_SLAVE_DS2433=m
-CONFIG_W1_SLAVE_DS2433_CRC=y
+# CONFIG_W1 is not set
 
 #
 # Hardware Monitoring support
index 66147ea..1e88dac 100644 (file)
@@ -1,8 +1,8 @@
 # powerpc
 #
 # Automatically generated make config: don't edit
-# Linux kernel version: 2.6.18.2-rc1
-# Mon Nov 13 09:44:41 2006
+# Linux kernel version: 2.6.18.2
+# Mon Nov 13 09:31:59 2006
 #
 # CONFIG_PPC64 is not set
 CONFIG_PPC32=y
@@ -176,9 +176,9 @@ CONFIG_MPIC=y
 #
 CONFIG_HIGHMEM=y
 # CONFIG_HZ_100 is not set
-CONFIG_HZ_250=y
-# CONFIG_HZ_1000 is not set
-CONFIG_HZ=250
+# CONFIG_HZ_250 is not set
+CONFIG_HZ_1000=y
+CONFIG_HZ=1000
 # CONFIG_PREEMPT_NONE is not set
 CONFIG_PREEMPT_VOLUNTARY=y
 # CONFIG_PREEMPT is not set
@@ -1993,23 +1993,7 @@ CONFIG_SENSORS_MAX6875=m
 #
 # Dallas's 1-wire bus
 #
-CONFIG_W1=m
-CONFIG_W1_CON=y
-
-#
-# 1-wire Bus Masters
-#
-CONFIG_W1_MASTER_MATROX=m
-CONFIG_W1_MASTER_DS2490=m
-CONFIG_W1_MASTER_DS2482=m
-
-#
-# 1-wire Slaves
-#
-CONFIG_W1_SLAVE_THERM=m
-CONFIG_W1_SLAVE_SMEM=m
-CONFIG_W1_SLAVE_DS2433=m
-CONFIG_W1_SLAVE_DS2433_CRC=y
+# CONFIG_W1 is not set
 
 #
 # Hardware Monitoring support
index 1db169f..4105f96 100644 (file)
@@ -1,8 +1,8 @@
 # powerpc
 #
 # Automatically generated make config: don't edit
-# Linux kernel version: 2.6.18.2-rc1
-# Mon Nov 13 09:44:41 2006
+# Linux kernel version: 2.6.18.2
+# Mon Nov 13 09:32:00 2006
 #
 # CONFIG_PPC64 is not set
 CONFIG_PPC32=y
@@ -173,9 +173,9 @@ CONFIG_MPIC=y
 #
 CONFIG_HIGHMEM=y
 # CONFIG_HZ_100 is not set
-CONFIG_HZ_250=y
-# CONFIG_HZ_1000 is not set
-CONFIG_HZ=250
+# CONFIG_HZ_250 is not set
+CONFIG_HZ_1000=y
+CONFIG_HZ=1000
 # CONFIG_PREEMPT_NONE is not set
 CONFIG_PREEMPT_VOLUNTARY=y
 # CONFIG_PREEMPT is not set
@@ -1997,23 +1997,7 @@ CONFIG_SENSORS_MAX6875=m
 #
 # Dallas's 1-wire bus
 #
-CONFIG_W1=m
-CONFIG_W1_CON=y
-
-#
-# 1-wire Bus Masters
-#
-CONFIG_W1_MASTER_MATROX=m
-CONFIG_W1_MASTER_DS2490=m
-CONFIG_W1_MASTER_DS2482=m
-
-#
-# 1-wire Slaves
-#
-CONFIG_W1_SLAVE_THERM=m
-CONFIG_W1_SLAVE_SMEM=m
-CONFIG_W1_SLAVE_DS2433=m
-CONFIG_W1_SLAVE_DS2433_CRC=y
+# CONFIG_W1 is not set
 
 #
 # Hardware Monitoring support
index aba7827..00a75ef 100644 (file)
@@ -1,8 +1,8 @@
 # powerpc
 #
 # Automatically generated make config: don't edit
-# Linux kernel version: 2.6.18.2-rc1
-# Mon Nov 13 09:44:42 2006
+# Linux kernel version: 2.6.18.2
+# Mon Nov 13 09:32:00 2006
 #
 CONFIG_PPC64=y
 CONFIG_64BIT=y
@@ -181,9 +181,9 @@ CONFIG_CBE_RAS=y
 # Kernel options
 #
 # CONFIG_HZ_100 is not set
-CONFIG_HZ_250=y
-# CONFIG_HZ_1000 is not set
-CONFIG_HZ=250
+# CONFIG_HZ_250 is not set
+CONFIG_HZ_1000=y
+CONFIG_HZ=1000
 # CONFIG_PREEMPT_NONE is not set
 CONFIG_PREEMPT_VOLUNTARY=y
 # CONFIG_PREEMPT is not set
@@ -1887,23 +1887,7 @@ CONFIG_SENSORS_MAX6875=m
 #
 # Dallas's 1-wire bus
 #
-CONFIG_W1=m
-CONFIG_W1_CON=y
-
-#
-# 1-wire Bus Masters
-#
-CONFIG_W1_MASTER_MATROX=m
-CONFIG_W1_MASTER_DS2490=m
-CONFIG_W1_MASTER_DS2482=m
-
-#
-# 1-wire Slaves
-#
-CONFIG_W1_SLAVE_THERM=m
-CONFIG_W1_SLAVE_SMEM=m
-CONFIG_W1_SLAVE_DS2433=m
-CONFIG_W1_SLAVE_DS2433_CRC=y
+# CONFIG_W1 is not set
 
 #
 # Hardware Monitoring support
index 7b31ef8..885dfec 100644 (file)
@@ -1,8 +1,8 @@
 # powerpc
 #
 # Automatically generated make config: don't edit
-# Linux kernel version: 2.6.18.2-rc1
-# Mon Nov 13 09:44:42 2006
+# Linux kernel version: 2.6.18.2
+# Mon Nov 13 09:32:00 2006
 #
 CONFIG_PPC64=y
 CONFIG_64BIT=y
@@ -181,9 +181,9 @@ CONFIG_CBE_RAS=y
 # Kernel options
 #
 # CONFIG_HZ_100 is not set
-CONFIG_HZ_250=y
-# CONFIG_HZ_1000 is not set
-CONFIG_HZ=250
+# CONFIG_HZ_250 is not set
+CONFIG_HZ_1000=y
+CONFIG_HZ=1000
 # CONFIG_PREEMPT_NONE is not set
 CONFIG_PREEMPT_VOLUNTARY=y
 # CONFIG_PREEMPT is not set
@@ -1887,23 +1887,7 @@ CONFIG_SENSORS_MAX6875=m
 #
 # Dallas's 1-wire bus
 #
-CONFIG_W1=m
-CONFIG_W1_CON=y
-
-#
-# 1-wire Bus Masters
-#
-CONFIG_W1_MASTER_MATROX=m
-CONFIG_W1_MASTER_DS2490=m
-CONFIG_W1_MASTER_DS2482=m
-
-#
-# 1-wire Slaves
-#
-CONFIG_W1_SLAVE_THERM=m
-CONFIG_W1_SLAVE_SMEM=m
-CONFIG_W1_SLAVE_DS2433=m
-CONFIG_W1_SLAVE_DS2433_CRC=y
+# CONFIG_W1 is not set
 
 #
 # Hardware Monitoring support
index ffeabee..22f7514 100644 (file)
@@ -1,8 +1,8 @@
 # powerpc
 #
 # Automatically generated make config: don't edit
-# Linux kernel version: 2.6.18.2-rc1
-# Mon Nov 13 09:44:42 2006
+# Linux kernel version: 2.6.18.2
+# Mon Nov 13 09:32:00 2006
 #
 CONFIG_PPC64=y
 CONFIG_64BIT=y
@@ -147,9 +147,9 @@ CONFIG_IBMVIO=y
 # Kernel options
 #
 # CONFIG_HZ_100 is not set
-CONFIG_HZ_250=y
-# CONFIG_HZ_1000 is not set
-CONFIG_HZ=250
+# CONFIG_HZ_250 is not set
+CONFIG_HZ_1000=y
+CONFIG_HZ=1000
 # CONFIG_PREEMPT_NONE is not set
 CONFIG_PREEMPT_VOLUNTARY=y
 # CONFIG_PREEMPT is not set
index 971ecd1..9853ff3 100644 (file)
@@ -1,8 +1,8 @@
 # s390
 #
 # Automatically generated make config: don't edit
-# Linux kernel version: 2.6.18.2-rc1
-# Mon Nov 13 09:44:42 2006
+# Linux kernel version: 2.6.18.2
+# Mon Nov 13 09:32:00 2006
 #
 CONFIG_MMU=y
 CONFIG_LOCKDEP_SUPPORT=y
index 6340b1b..25dc399 100644 (file)
@@ -1,8 +1,8 @@
 # s390
 #
 # Automatically generated make config: don't edit
-# Linux kernel version: 2.6.18.2-rc1
-# Mon Nov 13 09:44:42 2006
+# Linux kernel version: 2.6.18.2
+# Mon Nov 13 09:32:01 2006
 #
 CONFIG_MMU=y
 CONFIG_LOCKDEP_SUPPORT=y
index e62073e..f9b450d 100644 (file)
@@ -1,8 +1,8 @@
 # x86_64
 #
 # Automatically generated make config: don't edit
-# Linux kernel version: 2.6.18.2-rc1
-# Mon Nov 13 09:44:42 2006
+# Linux kernel version: 2.6.18.2
+# Mon Nov 13 09:32:01 2006
 #
 CONFIG_X86_64=y
 CONFIG_64BIT=y
@@ -161,9 +161,9 @@ CONFIG_CRASH_DUMP=y
 CONFIG_PHYSICAL_START=0x1000000
 # CONFIG_SECCOMP is not set
 # CONFIG_HZ_100 is not set
-CONFIG_HZ_250=y
-# CONFIG_HZ_1000 is not set
-CONFIG_HZ=250
+# CONFIG_HZ_250 is not set
+CONFIG_HZ_1000=y
+CONFIG_HZ=1000
 CONFIG_REORDER=y
 CONFIG_K8_NB=y
 CONFIG_GENERIC_HARDIRQS=y
@@ -1961,23 +1961,7 @@ CONFIG_SENSORS_MAX6875=m
 #
 # Dallas's 1-wire bus
 #
-CONFIG_W1=m
-CONFIG_W1_CON=y
-
-#
-# 1-wire Bus Masters
-#
-CONFIG_W1_MASTER_MATROX=m
-CONFIG_W1_MASTER_DS2490=m
-CONFIG_W1_MASTER_DS2482=m
-
-#
-# 1-wire Slaves
-#
-CONFIG_W1_SLAVE_THERM=m
-CONFIG_W1_SLAVE_SMEM=m
-CONFIG_W1_SLAVE_DS2433=m
-CONFIG_W1_SLAVE_DS2433_CRC=y
+# CONFIG_W1 is not set
 
 #
 # Hardware Monitoring support
index b4a0c30..efb0ffc 100644 (file)
@@ -1,8 +1,8 @@
 # x86_64
 #
 # Automatically generated make config: don't edit
-# Linux kernel version: 2.6.18.2-rc1
-# Mon Nov 13 09:44:43 2006
+# Linux kernel version: 2.6.18.2
+# Mon Nov 13 09:32:01 2006
 #
 CONFIG_X86_64=y
 CONFIG_64BIT=y
@@ -1935,23 +1935,7 @@ CONFIG_SENSORS_MAX6875=m
 #
 # Dallas's 1-wire bus
 #
-CONFIG_W1=m
-CONFIG_W1_CON=y
-
-#
-# 1-wire Bus Masters
-#
-CONFIG_W1_MASTER_MATROX=m
-CONFIG_W1_MASTER_DS2490=m
-CONFIG_W1_MASTER_DS2482=m
-
-#
-# 1-wire Slaves
-#
-CONFIG_W1_SLAVE_THERM=m
-CONFIG_W1_SLAVE_SMEM=m
-CONFIG_W1_SLAVE_DS2433=m
-CONFIG_W1_SLAVE_DS2433_CRC=y
+# CONFIG_W1 is not set
 
 #
 # Hardware Monitoring support
@@ -3107,8 +3091,8 @@ CONFIG_XEN_PCIDEV_BACKEND_VPCI=y
 # CONFIG_XEN_TPMDEV_BACKEND is not set
 CONFIG_XEN_BLKDEV_FRONTEND=m
 CONFIG_XEN_NETDEV_FRONTEND=m
-CONFIG_XEN_FRAMEBUFFER=y
-CONFIG_XEN_KEYBOARD=y
+# CONFIG_XEN_FRAMEBUFFER is not set
+# CONFIG_XEN_KEYBOARD is not set
 CONFIG_XEN_SCRUB_PAGES=y
 # CONFIG_XEN_DISABLE_SERIAL is not set
 CONFIG_XEN_SYSFS=y
index 25d6f90..18ad8c7 100644 (file)
@@ -1,8 +1,8 @@
 # x86_64
 #
 # Automatically generated make config: don't edit
-# Linux kernel version: 2.6.18.2-rc1
-# Mon Nov 13 09:44:43 2006
+# Linux kernel version: 2.6.18.2
+# Mon Nov 13 09:32:01 2006
 #
 CONFIG_X86_64=y
 CONFIG_64BIT=y
@@ -1935,23 +1935,7 @@ CONFIG_SENSORS_MAX6875=m
 #
 # Dallas's 1-wire bus
 #
-CONFIG_W1=m
-CONFIG_W1_CON=y
-
-#
-# 1-wire Bus Masters
-#
-CONFIG_W1_MASTER_MATROX=m
-CONFIG_W1_MASTER_DS2490=m
-CONFIG_W1_MASTER_DS2482=m
-
-#
-# 1-wire Slaves
-#
-CONFIG_W1_SLAVE_THERM=m
-CONFIG_W1_SLAVE_SMEM=m
-CONFIG_W1_SLAVE_DS2433=m
-CONFIG_W1_SLAVE_DS2433_CRC=y
+# CONFIG_W1 is not set
 
 #
 # Hardware Monitoring support
@@ -3107,8 +3091,8 @@ CONFIG_XEN_PCIDEV_BACKEND_VPCI=y
 # CONFIG_XEN_TPMDEV_BACKEND is not set
 CONFIG_XEN_BLKDEV_FRONTEND=m
 CONFIG_XEN_NETDEV_FRONTEND=m
-CONFIG_XEN_FRAMEBUFFER=y
-CONFIG_XEN_KEYBOARD=y
+# CONFIG_XEN_FRAMEBUFFER is not set
+# CONFIG_XEN_KEYBOARD is not set
 CONFIG_XEN_SCRUB_PAGES=y
 # CONFIG_XEN_DISABLE_SERIAL is not set
 CONFIG_XEN_SYSFS=y
index 78ffb64..ed4279c 100644 (file)
@@ -1,8 +1,8 @@
 # x86_64
 #
 # Automatically generated make config: don't edit
-# Linux kernel version: 2.6.18.2-rc1
-# Mon Nov 13 09:44:43 2006
+# Linux kernel version: 2.6.18.2
+# Mon Nov 13 09:32:01 2006
 #
 CONFIG_X86_64=y
 CONFIG_64BIT=y
@@ -1546,8 +1546,8 @@ CONFIG_XEN_BLKDEV_TAP=m
 # CONFIG_XEN_TPMDEV_BACKEND is not set
 CONFIG_XEN_BLKDEV_FRONTEND=y
 CONFIG_XEN_NETDEV_FRONTEND=m
-CONFIG_XEN_FRAMEBUFFER=y
-CONFIG_XEN_KEYBOARD=y
+# CONFIG_XEN_FRAMEBUFFER is not set
+# CONFIG_XEN_KEYBOARD is not set
 CONFIG_XEN_SCRUB_PAGES=y
 CONFIG_XEN_DISABLE_SERIAL=y
 CONFIG_XEN_SYSFS=y
index 16135f6..99308ef 100644 (file)
@@ -1,8 +1,8 @@
 # x86_64
 #
 # Automatically generated make config: don't edit
-# Linux kernel version: 2.6.18.2-rc1
-# Mon Nov 13 09:44:43 2006
+# Linux kernel version: 2.6.18.2
+# Mon Nov 13 09:32:02 2006
 #
 CONFIG_X86_64=y
 CONFIG_64BIT=y
@@ -178,9 +178,9 @@ CONFIG_KEXEC=y
 CONFIG_PHYSICAL_START=0x200000
 # CONFIG_SECCOMP is not set
 # CONFIG_HZ_100 is not set
-CONFIG_HZ_250=y
-# CONFIG_HZ_1000 is not set
-CONFIG_HZ=250
+# CONFIG_HZ_250 is not set
+CONFIG_HZ_1000=y
+CONFIG_HZ=1000
 CONFIG_REORDER=y
 CONFIG_K8_NB=y
 CONFIG_GENERIC_HARDIRQS=y
@@ -1974,23 +1974,7 @@ CONFIG_SENSORS_MAX6875=m
 #
 # Dallas's 1-wire bus
 #
-CONFIG_W1=m
-CONFIG_W1_CON=y
-
-#
-# 1-wire Bus Masters
-#
-CONFIG_W1_MASTER_MATROX=m
-CONFIG_W1_MASTER_DS2490=m
-CONFIG_W1_MASTER_DS2482=m
-
-#
-# 1-wire Slaves
-#
-CONFIG_W1_SLAVE_THERM=m
-CONFIG_W1_SLAVE_SMEM=m
-CONFIG_W1_SLAVE_DS2433=m
-CONFIG_W1_SLAVE_DS2433_CRC=y
+# CONFIG_W1 is not set
 
 #
 # Hardware Monitoring support
index 71093a9..74cff83 100644 (file)
@@ -33,7 +33,7 @@ extern void poke_blanked_console(void);
 
 /* Variables for selection control. */
 /* Use a dynamic buffer, instead of static (Dec 1994) */
-struct vc_data *sel_cons;              /* must not be disallocated */
+struct vc_data *sel_cons;              /* must not be deallocated */
 static volatile int sel_start = -1;    /* cleared by clear_selection */
 static int sel_end;
 static int sel_buffer_lth;
index 199e7f0..d70a259 100644 (file)
@@ -127,9 +127,10 @@ EXPORT_SYMBOL(tty_std_termios);
    
 LIST_HEAD(tty_drivers);                        /* linked list of tty drivers */
 
-/* Semaphore to protect creating and releasing a tty. This is shared with
+/* Mutex to protect creating and releasing a tty. This is shared with
    vt.c for deeply disgusting hack reasons */
 DEFINE_MUTEX(tty_mutex);
+EXPORT_SYMBOL(tty_mutex);
 
 #ifdef CONFIG_UNIX98_PTYS
 extern struct tty_driver *ptm_driver;  /* Unix98 pty masters; for /dev/ptmx */
@@ -161,17 +162,11 @@ static void release_mem(struct tty_struct *tty, int idx);
  *     been initialized in any way but has been zeroed
  *
  *     Locking: none
- *     FIXME: use kzalloc
  */
 
 static struct tty_struct *alloc_tty_struct(void)
 {
-       struct tty_struct *tty;
-
-       tty = kmalloc(sizeof(struct tty_struct), GFP_KERNEL);
-       if (tty)
-               memset(tty, 0, sizeof(struct tty_struct));
-       return tty;
+       return kzalloc(sizeof(struct tty_struct), GFP_KERNEL);
 }
 
 static void tty_buffer_free_all(struct tty_struct *);
@@ -256,7 +251,7 @@ static int check_tty_count(struct tty_struct *tty, const char *routine)
                                    "!= #fd's(%d) in %s\n",
                       tty->name, tty->count, count, routine);
                return count;
-       }       
+       }
 #endif
        return 0;
 }
@@ -265,18 +260,6 @@ static int check_tty_count(struct tty_struct *tty, const char *routine)
  * Tty buffer allocation management
  */
 
-
-/**
- *     tty_buffer_free_all             -       free buffers used by a tty
- *     @tty: tty to free from
- *
- *     Remove all the buffers pending on a tty whether queued with data
- *     or in the free ring. Must be called when the tty is no longer in use
- *
- *     Locking: none
- */
-
-
 /**
  *     tty_buffer_free_all             -       free buffers used by a tty
  *     @tty: tty to free from
@@ -484,10 +467,9 @@ int tty_insert_flip_string(struct tty_struct *tty, const unsigned char *chars,
                tb->used += space;
                copied += space;
                chars += space;
-       }
-       /* There is a small chance that we need to split the data over
-          several buffers. If this is the case we must loop */
-       while (unlikely(size > copied));
+               /* There is a small chance that we need to split the data over
+                  several buffers. If this is the case we must loop */
+       } while (unlikely(size > copied));
        return copied;
 }
 EXPORT_SYMBOL(tty_insert_flip_string);
@@ -522,10 +504,9 @@ int tty_insert_flip_string_flags(struct tty_struct *tty,
                copied += space;
                chars += space;
                flags += space;
-       }
-       /* There is a small chance that we need to split the data over
-          several buffers. If this is the case we must loop */
-       while (unlikely(size > copied));
+               /* There is a small chance that we need to split the data over
+                  several buffers. If this is the case we must loop */
+       } while (unlikely(size > copied));
        return copied;
 }
 EXPORT_SYMBOL(tty_insert_flip_string_flags);
@@ -622,14 +603,14 @@ EXPORT_SYMBOL_GPL(tty_prepare_flip_string_flags);
  *     they are not on hot paths so a little discipline won't do 
  *     any harm.
  *
- *     Locking: takes termios_sem
+ *     Locking: takes termios_mutex
  */
  
 static void tty_set_termios_ldisc(struct tty_struct *tty, int num)
 {
-       down(&tty->termios_sem);
+       mutex_lock(&tty->termios_mutex);
        tty->termios->c_line = num;
-       up(&tty->termios_sem);
+       mutex_unlock(&tty->termios_mutex);
 }
 
 /*
@@ -923,7 +904,7 @@ static void tty_ldisc_enable(struct tty_struct *tty)
  *     context.
  *
  *     Locking: takes tty_ldisc_lock.
- *             called functions take termios_sem
+ *              called functions take termios_mutex
  */
  
 static int tty_set_ldisc(struct tty_struct *tty, int ldisc)
@@ -1275,12 +1256,12 @@ EXPORT_SYMBOL_GPL(tty_ldisc_flush);
  *
  *     Locking:
  *             BKL
- *             redirect lock for undoing redirection
- *             file list lock for manipulating list of ttys
- *             tty_ldisc_lock from called functions
- *             termios_sem resetting termios data
- *             tasklist_lock to walk task list for hangup event
- *
+ *               redirect lock for undoing redirection
+ *               file list lock for manipulating list of ttys
+ *               tty_ldisc_lock from called functions
+ *               termios_mutex resetting termios data
+ *               tasklist_lock to walk task list for hangup event
+ *                 ->siglock to protect ->signal/->sighand
  */
 static void do_tty_hangup(void *data)
 {
@@ -1347,9 +1328,9 @@ static void do_tty_hangup(void *data)
         */
        if (tty->driver->flags & TTY_DRIVER_RESET_TERMIOS)
        {
-               down(&tty->termios_sem);
+               mutex_lock(&tty->termios_mutex);
                *tty->termios = tty->driver->init_termios;
-               up(&tty->termios_sem);
+               mutex_unlock(&tty->termios_mutex);
        }
        
        /* Defer ldisc switch */
@@ -1361,14 +1342,18 @@ static void do_tty_hangup(void *data)
        read_lock(&tasklist_lock);
        if (tty->session > 0) {
                do_each_task_pid(tty->session, PIDTYPE_SID, p) {
+                       spin_lock_irq(&p->sighand->siglock);
                        if (p->signal->tty == tty)
                                p->signal->tty = NULL;
-                       if (!p->signal->leader)
+                       if (!p->signal->leader) {
+                               spin_unlock_irq(&p->sighand->siglock);
                                continue;
-                       group_send_sig_info(SIGHUP, SEND_SIG_PRIV, p);
-                       group_send_sig_info(SIGCONT, SEND_SIG_PRIV, p);
+                       }
+                       __group_send_sig_info(SIGHUP, SEND_SIG_PRIV, p);
+                       __group_send_sig_info(SIGCONT, SEND_SIG_PRIV, p);
                        if (tty->pgrp > 0)
                                p->signal->tty_old_pgrp = tty->pgrp;
+                       spin_unlock_irq(&p->sighand->siglock);
                } while_each_task_pid(tty->session, PIDTYPE_SID, p);
        }
        read_unlock(&tasklist_lock);
@@ -1460,6 +1445,14 @@ int tty_hung_up_p(struct file * filp)
 
 EXPORT_SYMBOL(tty_hung_up_p);
 
+static void session_clear_tty(pid_t session)
+{
+       struct task_struct *p;
+       do_each_task_pid(session, PIDTYPE_SID, p) {
+               proc_clear_tty(p);
+       } while_each_task_pid(session, PIDTYPE_SID, p);
+}
+
 /**
  *     disassociate_ctty       -       disconnect controlling tty
  *     @on_exit: true if exiting so need to "hang up" the session
@@ -1476,31 +1469,35 @@ EXPORT_SYMBOL(tty_hung_up_p);
  *     The argument on_exit is set to 1 if called when a process is
  *     exiting; it is 0 if called by the ioctl TIOCNOTTY.
  *
- *     Locking: tty_mutex is taken to protect current->signal->tty
+ *     Locking:
  *             BKL is taken for hysterical raisins
- *             Tasklist lock is taken (under tty_mutex) to walk process
- *             lists for the session.
+ *               tty_mutex is taken to protect tty
+ *               ->siglock is taken to protect ->signal/->sighand
+ *               tasklist_lock is taken to walk process list for sessions
+ *                 ->siglock is taken to protect ->signal/->sighand
  */
 
 void disassociate_ctty(int on_exit)
 {
        struct tty_struct *tty;
-       struct task_struct *p;
        int tty_pgrp = -1;
+       int session;
 
        lock_kernel();
 
        mutex_lock(&tty_mutex);
-       tty = current->signal->tty;
+       tty = get_current_tty();
        if (tty) {
                tty_pgrp = tty->pgrp;
                mutex_unlock(&tty_mutex);
+               /* XXX: here we race, there is nothing protecting tty */
                if (on_exit && tty->driver->type != TTY_DRIVER_TYPE_PTY)
                        tty_vhangup(tty);
        } else {
-               if (current->signal->tty_old_pgrp) {
-                       kill_pg(current->signal->tty_old_pgrp, SIGHUP, on_exit);
-                       kill_pg(current->signal->tty_old_pgrp, SIGCONT, on_exit);
+               pid_t old_pgrp = current->signal->tty_old_pgrp;
+               if (old_pgrp) {
+                       kill_pg(old_pgrp, SIGHUP, on_exit);
+                       kill_pg(old_pgrp, SIGCONT, on_exit);
                }
                mutex_unlock(&tty_mutex);
                unlock_kernel();        
@@ -1512,19 +1509,29 @@ void disassociate_ctty(int on_exit)
                        kill_pg(tty_pgrp, SIGCONT, on_exit);
        }
 
-       /* Must lock changes to tty_old_pgrp */
-       mutex_lock(&tty_mutex);
+       spin_lock_irq(&current->sighand->siglock);
        current->signal->tty_old_pgrp = 0;
-       tty->session = 0;
-       tty->pgrp = -1;
+       session = current->signal->session;
+       spin_unlock_irq(&current->sighand->siglock);
+
+       mutex_lock(&tty_mutex);
+       /* It is possible that do_tty_hangup has free'd this tty */
+       tty = get_current_tty();
+       if (tty) {
+               tty->session = 0;
+               tty->pgrp = 0;
+       } else {
+#ifdef TTY_DEBUG_HANGUP
+               printk(KERN_DEBUG "error attempted to write to tty [0x%p]"
+                      " = NULL", tty);
+#endif
+       }
+       mutex_unlock(&tty_mutex);
 
        /* Now clear signal->tty under the lock */
        read_lock(&tasklist_lock);
-       do_each_task_pid(current->signal->session, PIDTYPE_SID, p) {
-               p->signal->tty = NULL;
-       } while_each_task_pid(current->signal->session, PIDTYPE_SID, p);
+       session_clear_tty(session);
        read_unlock(&tasklist_lock);
-       mutex_unlock(&tty_mutex);
        unlock_kernel();
 }
 
@@ -2343,16 +2350,10 @@ static void release_dev(struct file * filp)
         * tty.
         */
        if (tty_closing || o_tty_closing) {
-               struct task_struct *p;
-
                read_lock(&tasklist_lock);
-               do_each_task_pid(tty->session, PIDTYPE_SID, p) {
-                       p->signal->tty = NULL;
-               } while_each_task_pid(tty->session, PIDTYPE_SID, p);
+               session_clear_tty(tty->session);
                if (o_tty)
-                       do_each_task_pid(o_tty->session, PIDTYPE_SID, p) {
-                               p->signal->tty = NULL;
-                       } while_each_task_pid(o_tty->session, PIDTYPE_SID, p);
+                       session_clear_tty(o_tty->session);
                read_unlock(&tasklist_lock);
        }
 
@@ -2449,9 +2450,9 @@ static void release_dev(struct file * filp)
  *     The termios state of a pty is reset on first open so that
  *     settings don't persist across reuse.
  *
- *     Locking: tty_mutex protects current->signal->tty, get_tty_driver and
- *             init_dev work. tty->count should protect the rest.
- *             task_lock is held to update task details for sessions
+ *     Locking: tty_mutex protects tty, get_tty_driver and init_dev work.
+ *              tty->count should protect the rest.
+ *              ->siglock protects ->signal/->sighand
  */
 
 static int tty_open(struct inode * inode, struct file * filp)
@@ -2473,12 +2474,13 @@ retry_open:
        mutex_lock(&tty_mutex);
 
        if (device == MKDEV(TTYAUX_MAJOR,0)) {
-               if (!current->signal->tty) {
+               tty = get_current_tty();
+               if (!tty) {
                        mutex_unlock(&tty_mutex);
                        return -ENXIO;
                }
-               driver = current->signal->tty->driver;
-               index = current->signal->tty->index;
+               driver = tty->driver;
+               index = tty->index;
                filp->f_flags |= O_NONBLOCK; /* Don't let /dev/tty block */
                /* noctty = 1; */
                goto got_driver;
@@ -2553,17 +2555,16 @@ got_driver:
                        filp->f_op = &tty_fops;
                goto retry_open;
        }
+
+       mutex_lock(&tty_mutex);
+       spin_lock_irq(&current->sighand->siglock);
        if (!noctty &&
            current->signal->leader &&
            !current->signal->tty &&
-           tty->session == 0) {
-               task_lock(current);
-               current->signal->tty = tty;
-               task_unlock(current);
-               current->signal->tty_old_pgrp = 0;
-               tty->session = current->signal->session;
-               tty->pgrp = process_group(current);
-       }
+           tty->session == 0)
+               __proc_set_tty(current, tty);
+       spin_unlock_irq(&current->sighand->siglock);
+       mutex_unlock(&tty_mutex);
        return 0;
 }
 
@@ -2727,6 +2728,8 @@ static int tty_fasync(int fd, struct file * filp, int on)
  *     Locking:
  *             Called functions take tty_ldisc_lock
  *             current->signal->tty check is safe without locks
+ *
+ *     FIXME: may race normal receive processing
  */
 
 static int tiocsti(struct tty_struct *tty, char __user *p)
@@ -2749,18 +2752,21 @@ static int tiocsti(struct tty_struct *tty, char __user *p)
  *     @tty; tty
  *     @arg: user buffer for result
  *
- *     Copies the kernel idea of the window size into the user buffer. No
- *     locking is done.
+ *     Copies the kernel idea of the window size into the user buffer.
  *
- *     FIXME: Returning random values racing a window size set is wrong
- *     should lock here against that
+ *     Locking: tty->termios_mutex is taken to ensure the winsize data
+ *             is consistent.
  */
 
 static int tiocgwinsz(struct tty_struct *tty, struct winsize __user * arg)
 {
-       if (copy_to_user(arg, &tty->winsize, sizeof(*arg)))
-               return -EFAULT;
-       return 0;
+       int err;
+
+       mutex_lock(&tty->termios_mutex);
+       err = copy_to_user(arg, &tty->winsize, sizeof(*arg));
+       mutex_unlock(&tty->termios_mutex);
+
+       return err ? -EFAULT: 0;
 }
 
 /**
@@ -2773,12 +2779,11 @@ static int tiocgwinsz(struct tty_struct *tty, struct winsize __user * arg)
  *     actually has driver level meaning and triggers a VC resize.
  *
  *     Locking:
- *             The console_sem is used to ensure we do not try and resize
- *     the console twice at once.
- *     FIXME: Two racing size sets may leave the console and kernel
- *             parameters disagreeing. Is this exploitable ?
- *     FIXME: Random values racing a window size get is wrong
- *     should lock here against that
+ *             Called function use the console_sem is used to ensure we do
+ *     not try and resize the console twice at once.
+ *             The tty->termios_mutex is used to ensure we don't double
+ *     resize and get confused. Lock order - tty->termios_mutex before
+ *     console sem
  */
 
 static int tiocswinsz(struct tty_struct *tty, struct tty_struct *real_tty,
@@ -2788,17 +2793,18 @@ static int tiocswinsz(struct tty_struct *tty, struct tty_struct *real_tty,
 
        if (copy_from_user(&tmp_ws, arg, sizeof(*arg)))
                return -EFAULT;
+
+       mutex_lock(&tty->termios_mutex);
        if (!memcmp(&tmp_ws, &tty->winsize, sizeof(*arg)))
-               return 0;
+               goto done;
+
 #ifdef CONFIG_VT
        if (tty->driver->type == TTY_DRIVER_TYPE_CONSOLE) {
-               int rc;
-
-               acquire_console_sem();
-               rc = vc_resize(tty->driver_data, tmp_ws.ws_col, tmp_ws.ws_row);
-               release_console_sem();
-               if (rc)
-                       return -ENXIO;
+               if (vc_lock_resize(tty->driver_data, tmp_ws.ws_col,
+                                       tmp_ws.ws_row)) {
+                       mutex_unlock(&tty->termios_mutex);
+                       return -ENXIO;
+               }
        }
 #endif
        if (tty->pgrp > 0)
@@ -2807,6 +2813,8 @@ static int tiocswinsz(struct tty_struct *tty, struct tty_struct *real_tty,
                kill_pg(real_tty->pgrp, SIGWINCH, 1);
        tty->winsize = tmp_ws;
        real_tty->winsize = tmp_ws;
+done:
+       mutex_unlock(&tty->termios_mutex);
        return 0;
 }
 
@@ -2879,27 +2887,28 @@ static int fionbio(struct file *file, int __user *p)
  *     leader to set this tty as the controlling tty for the session.
  *
  *     Locking:
- *             Takes tasklist lock internally to walk sessions
- *             Takes task_lock() when updating signal->tty
- *
- *     FIXME: tty_mutex is needed to protect signal->tty references.
- *     FIXME: why task_lock on the signal->tty reference ??
- *
+ *             Takes tty_mutex() to protect tty instance
+ *             Takes tasklist_lock internally to walk sessions
+ *             Takes ->siglock() when updating signal->tty
  */
 
 static int tiocsctty(struct tty_struct *tty, int arg)
 {
-       struct task_struct *p;
-
+       int ret = 0;
        if (current->signal->leader &&
            (current->signal->session == tty->session))
-               return 0;
+               return ret;
+
+       mutex_lock(&tty_mutex);
        /*
         * The process must be a session leader and
         * not have a controlling tty already.
         */
-       if (!current->signal->leader || current->signal->tty)
-               return -EPERM;
+       if (!current->signal->leader || current->signal->tty) {
+               ret = -EPERM;
+               goto unlock;
+       }
+
        if (tty->session > 0) {
                /*
                 * This tty is already the controlling
@@ -2909,22 +2918,18 @@ static int tiocsctty(struct tty_struct *tty, int arg)
                        /*
                         * Steal it away
                         */
-
                        read_lock(&tasklist_lock);
-                       do_each_task_pid(tty->session, PIDTYPE_SID, p) {
-                               p->signal->tty = NULL;
-                       } while_each_task_pid(tty->session, PIDTYPE_SID, p);
+                       session_clear_tty(tty->session);
                        read_unlock(&tasklist_lock);
-               } else
-                       return -EPERM;
+               } else {
+                       ret = -EPERM;
+                       goto unlock;
+               }
        }
-       task_lock(current);
-       current->signal->tty = tty;
-       task_unlock(current);
-       current->signal->tty_old_pgrp = 0;
-       tty->session = current->signal->session;
-       tty->pgrp = process_group(current);
-       return 0;
+       proc_set_tty(current, tty);
+unlock:
+       mutex_unlock(&tty_mutex);
+       return ret;
 }
 
 /**
@@ -2936,7 +2941,7 @@ static int tiocsctty(struct tty_struct *tty, int arg)
  *     Obtain the process group of the tty. If there is no process group
  *     return an error.
  *
- *     Locking: none. Reference to ->signal->tty is safe.
+ *     Locking: none. Reference to current->signal->tty is safe.
  */
 
 static int tiocgpgrp(struct tty_struct *tty, struct tty_struct *real_tty, pid_t __user *p)
@@ -2963,8 +2968,6 @@ static int tiocgpgrp(struct tty_struct *tty, struct tty_struct *real_tty, pid_t
  *     permitted where the tty session is our session.
  *
  *     Locking: None
- *
- *     FIXME: current->signal->tty referencing is unsafe.
  */
 
 static int tiocspgrp(struct tty_struct *tty, struct tty_struct *real_tty, pid_t __user *p)
@@ -3001,7 +3004,7 @@ static int tiocspgrp(struct tty_struct *tty, struct tty_struct *real_tty, pid_t
  *     Obtain the session id of the tty. If there is no session
  *     return an error.
  *
- *     Locking: none. Reference to ->signal->tty is safe.
+ *     Locking: none. Reference to current->signal->tty is safe.
  */
 
 static int tiocgsid(struct tty_struct *tty, struct tty_struct *real_tty, pid_t __user *p)
@@ -3045,19 +3048,20 @@ static int tiocsetd(struct tty_struct *tty, int __user *p)
  *     timed break functionality.
  *
  *     Locking:
- *             None
+ *             atomic_write_lock serializes
  *
- *     FIXME:
- *             What if two overlap
  */
 
 static int send_break(struct tty_struct *tty, unsigned int duration)
 {
+       if (mutex_lock_interruptible(&tty->atomic_write_lock))
+               return -EINTR;
        tty->driver->break_ctl(tty, -1);
        if (!signal_pending(current)) {
                msleep_interruptible(duration);
        }
        tty->driver->break_ctl(tty, 0);
+       mutex_unlock(&tty->atomic_write_lock);
        if (signal_pending(current))
                return -EINTR;
        return 0;
@@ -3150,6 +3154,8 @@ int tty_ioctl(struct inode * inode, struct file * file,
        if (tty_paranoia_check(tty, inode, "tty_ioctl"))
                return -EINVAL;
 
+       /* CHECKME: is this safe as one end closes ? */
+
        real_tty = tty;
        if (tty->driver->type == TTY_DRIVER_TYPE_PTY &&
            tty->driver->subtype == PTY_TYPE_MASTER)
@@ -3217,14 +3223,11 @@ int tty_ioctl(struct inode * inode, struct file * file,
                        clear_bit(TTY_EXCLUSIVE, &tty->flags);
                        return 0;
                case TIOCNOTTY:
-                       /* FIXME: taks lock or tty_mutex ? */
                        if (current->signal->tty != tty)
                                return -ENOTTY;
                        if (current->signal->leader)
                                disassociate_ctty(0);
-                       task_lock(current);
-                       current->signal->tty = NULL;
-                       task_unlock(current);
+                       proc_clear_tty(current);
                        return 0;
                case TIOCSCTTY:
                        return tiocsctty(tty, arg);
@@ -3323,7 +3326,7 @@ static void __do_SAK(void *arg)
        
        if (!tty)
                return;
-       session  = tty->session;
+       session = tty->session;
        
        /* We don't want an ldisc switch during this */
        disc = tty_ldisc_ref(tty);
@@ -3586,7 +3589,7 @@ static void initialize_tty_struct(struct tty_struct *tty)
        tty_buffer_init(tty);
        INIT_WORK(&tty->buf.work, flush_to_ldisc, tty);
        init_MUTEX(&tty->buf.pty_sem);
-       init_MUTEX(&tty->termios_sem);
+       mutex_init(&tty->termios_mutex);
        init_waitqueue_head(&tty->write_wait);
        init_waitqueue_head(&tty->read_wait);
        INIT_WORK(&tty->hangup_work, do_tty_hangup, tty);
index 4ad47d3..3b6fa7b 100644 (file)
@@ -20,6 +20,7 @@
 #include <linux/mm.h>
 #include <linux/module.h>
 #include <linux/bitops.h>
+#include <linux/mutex.h>
 
 #include <asm/io.h>
 #include <asm/uaccess.h>
@@ -131,7 +132,7 @@ static void change_termios(struct tty_struct * tty, struct termios * new_termios
 
        /* FIXME: we need to decide on some locking/ordering semantics
           for the set_termios notification eventually */
-       down(&tty->termios_sem);
+       mutex_lock(&tty->termios_mutex);
 
        *tty->termios = *new_termios;
        unset_locked_termios(tty->termios, &old_termios, tty->termios_locked);
@@ -176,7 +177,7 @@ static void change_termios(struct tty_struct * tty, struct termios * new_termios
                        (ld->set_termios)(tty, &old_termios);
                tty_ldisc_deref(ld);
        }
-       up(&tty->termios_sem);
+       mutex_unlock(&tty->termios_mutex);
 }
 
 /**
@@ -284,13 +285,13 @@ static int get_sgttyb(struct tty_struct * tty, struct sgttyb __user * sgttyb)
 {
        struct sgttyb tmp;
 
-       down(&tty->termios_sem);
+       mutex_lock(&tty->termios_mutex);
        tmp.sg_ispeed = 0;
        tmp.sg_ospeed = 0;
        tmp.sg_erase = tty->termios->c_cc[VERASE];
        tmp.sg_kill = tty->termios->c_cc[VKILL];
        tmp.sg_flags = get_sgflags(tty);
-       up(&tty->termios_sem);
+       mutex_unlock(&tty->termios_mutex);
        
        return copy_to_user(sgttyb, &tmp, sizeof(tmp)) ? -EFAULT : 0;
 }
@@ -345,12 +346,12 @@ static int set_sgttyb(struct tty_struct * tty, struct sgttyb __user * sgttyb)
        if (copy_from_user(&tmp, sgttyb, sizeof(tmp)))
                return -EFAULT;
 
-       down(&tty->termios_sem);                
+       mutex_lock(&tty->termios_mutex);
        termios =  *tty->termios;
        termios.c_cc[VERASE] = tmp.sg_erase;
        termios.c_cc[VKILL] = tmp.sg_kill;
        set_sgflags(&termios, tmp.sg_flags);
-       up(&tty->termios_sem);
+       mutex_unlock(&tty->termios_mutex);
        change_termios(tty, &termios);
        return 0;
 }
@@ -422,24 +423,28 @@ static int set_ltchars(struct tty_struct * tty, struct ltchars __user * ltchars)
  *
  *     Send a high priority character to the tty even if stopped
  *
- *     Locking: none
- *
- *     FIXME: overlapping calls with start/stop tty lose state of tty
+ *     Locking: none for xchar method, write ordering for write method.
  */
 
-static void send_prio_char(struct tty_struct *tty, char ch)
+static int send_prio_char(struct tty_struct *tty, char ch)
 {
        int     was_stopped = tty->stopped;
 
        if (tty->driver->send_xchar) {
                tty->driver->send_xchar(tty, ch);
-               return;
+               return 0;
        }
+
+       if (mutex_lock_interruptible(&tty->atomic_write_lock))
+               return -ERESTARTSYS;
+
        if (was_stopped)
                start_tty(tty);
        tty->driver->write(tty, &ch, 1);
        if (was_stopped)
                stop_tty(tty);
+       mutex_unlock(&tty->atomic_write_lock);
+       return 0;
 }
 
 int n_tty_ioctl(struct tty_struct * tty, struct file * file,
@@ -513,11 +518,11 @@ int n_tty_ioctl(struct tty_struct * tty, struct file * file,
                                break;
                        case TCIOFF:
                                if (STOP_CHAR(tty) != __DISABLED_CHAR)
-                                       send_prio_char(tty, STOP_CHAR(tty));
+                                       return send_prio_char(tty, STOP_CHAR(tty));
                                break;
                        case TCION:
                                if (START_CHAR(tty) != __DISABLED_CHAR)
-                                       send_prio_char(tty, START_CHAR(tty));
+                                       return send_prio_char(tty, START_CHAR(tty));
                                break;
                        default:
                                return -EINVAL;
@@ -592,11 +597,11 @@ int n_tty_ioctl(struct tty_struct * tty, struct file * file,
                case TIOCSSOFTCAR:
                        if (get_user(arg, (unsigned int __user *) arg))
                                return -EFAULT;
-                       down(&tty->termios_sem);
+                       mutex_lock(&tty->termios_mutex);
                        tty->termios->c_cflag =
                                ((tty->termios->c_cflag & ~CLOCAL) |
                                 (arg ? CLOCAL : 0));
-                       up(&tty->termios_sem);
+                       mutex_unlock(&tty->termios_mutex);
                        return 0;
                default:
                        return -ENOIOCTLCMD;
index b217da7..4941c95 100644 (file)
@@ -878,8 +878,17 @@ int vc_resize(struct vc_data *vc, unsigned int cols, unsigned int lines)
        return err;
 }
 
+int vc_lock_resize(struct vc_data *vc, unsigned int cols, unsigned int lines)
+{
+       int rc;
+
+       acquire_console_sem();
+       rc = vc_resize(vc, cols, lines);
+       release_console_sem();
+       return rc;
+}
 
-void vc_disallocate(unsigned int currcons)
+void vc_deallocate(unsigned int currcons)
 {
        WARN_CONSOLE_UNLOCKED();
 
@@ -3765,6 +3774,7 @@ EXPORT_SYMBOL(default_blu);
 EXPORT_SYMBOL(update_region);
 EXPORT_SYMBOL(redraw_screen);
 EXPORT_SYMBOL(vc_resize);
+EXPORT_SYMBOL(vc_lock_resize);
 EXPORT_SYMBOL(fg_console);
 EXPORT_SYMBOL(console_blank_hook);
 EXPORT_SYMBOL(console_blanked);
index a5628a8..a53e382 100644 (file)
@@ -96,7 +96,7 @@ do_kdsk_ioctl(int cmd, struct kbentry __user *user_kbe, int perm, struct kbd_str
                if (!perm)
                        return -EPERM;
                if (!i && v == K_NOSUCHMAP) {
-                       /* disallocate map */
+                       /* deallocate map */
                        key_map = key_maps[s];
                        if (s && key_map) {
                            key_maps[s] = NULL;
@@ -819,20 +819,20 @@ int vt_ioctl(struct tty_struct *tty, struct file * file,
                if (arg > MAX_NR_CONSOLES)
                        return -ENXIO;
                if (arg == 0) {
-                   /* disallocate all unused consoles, but leave 0 */
+                   /* deallocate all unused consoles, but leave 0 */
                        acquire_console_sem();
                        for (i=1; i<MAX_NR_CONSOLES; i++)
                                if (! VT_BUSY(i))
-                                       vc_disallocate(i);
+                                       vc_deallocate(i);
                        release_console_sem();
                } else {
-                       /* disallocate a single console, if possible */
+                       /* deallocate a single console, if possible */
                        arg--;
                        if (VT_BUSY(arg))
                                return -EBUSY;
                        if (arg) {                            /* leave 0 */
                                acquire_console_sem();
-                               vc_disallocate(arg);
+                               vc_deallocate(arg);
                                release_console_sem();
                        }
                }
@@ -847,11 +847,8 @@ int vt_ioctl(struct tty_struct *tty, struct file * file,
                if (get_user(ll, &vtsizes->v_rows) ||
                    get_user(cc, &vtsizes->v_cols))
                        return -EFAULT;
-               for (i = 0; i < MAX_NR_CONSOLES; i++) {
-                       acquire_console_sem();
-                       vc_resize(vc_cons[i].d, cc, ll);
-                       release_console_sem();
-               }
+               for (i = 0; i < MAX_NR_CONSOLES; i++)
+                       vc_lock_resize(vc_cons[i].d, cc, ll);
                return 0;
        }
 
index d10c8b8..b6f9476 100644 (file)
@@ -1907,7 +1907,8 @@ static int if_readstat(u8 __user *buf, int len, int id, int channel)
        }
 
        for (p=buf, count=0; count < len; p++, count++) {
-               put_user(*card->q931_read++, p);
+               if (put_user(*card->q931_read++, p))
+                       return -EFAULT;
                if (card->q931_read > card->q931_end)
                        card->q931_read = card->q931_buf;
        }
index e103503..9280b58 100644 (file)
@@ -631,7 +631,8 @@ static int HiSax_readstatus(u_char __user *buf, int len, int id, int channel)
                count = cs->status_end - cs->status_read + 1;
                if (count >= len)
                        count = len;
-               copy_to_user(p, cs->status_read, count);
+               if (copy_to_user(p, cs->status_read, count))
+                       return -EFAULT;
                cs->status_read += count;
                if (cs->status_read > cs->status_end)
                        cs->status_read = cs->status_buf;
@@ -642,7 +643,8 @@ static int HiSax_readstatus(u_char __user *buf, int len, int id, int channel)
                                cnt = HISAX_STATUS_BUFSIZE;
                        else
                                cnt = count;
-                       copy_to_user(p, cs->status_read, cnt);
+                       if (copy_to_user(p, cs->status_read, cnt))
+                               return -EFAULT;
                        p += cnt;
                        cs->status_read += cnt % HISAX_STATUS_BUFSIZE;
                        count -= cnt;
index 6649f8b..730bbd0 100644 (file)
@@ -1010,7 +1010,8 @@ icn_readstatus(u_char __user *buf, int len, icn_card * card)
        for (p = buf, count = 0; count < len; p++, count++) {
                if (card->msg_buf_read == card->msg_buf_write)
                        return count;
-               put_user(*card->msg_buf_read++, p);
+               if (put_user(*card->msg_buf_read++, p))
+                       return -EFAULT;
                if (card->msg_buf_read > card->msg_buf_end)
                        card->msg_buf_read = card->msg_buf;
        }
index fabbd46..9a66524 100644 (file)
@@ -451,7 +451,8 @@ isdnloop_readstatus(u_char __user *buf, int len, isdnloop_card * card)
        for (p = buf, count = 0; count < len; p++, count++) {
                if (card->msg_buf_read == card->msg_buf_write)
                        return count;
-               put_user(*card->msg_buf_read++, p);
+               if (put_user(*card->msg_buf_read++, p))
+                       return -EFAULT;
                if (card->msg_buf_read > card->msg_buf_end)
                        card->msg_buf_read = card->msg_buf;
        }
index 94f2148..6ead5e1 100644 (file)
@@ -725,23 +725,27 @@ static int pcbit_stat(u_char __user *buf, int len, int driver, int channel)
 
        if (stat_st < stat_end)
        {
-               copy_to_user(buf, statbuf + stat_st, len);
+               if (copy_to_user(buf, statbuf + stat_st, len))
+                       return -EFAULT;
                stat_st += len;    
        }
        else
        {
                if (len > STATBUF_LEN - stat_st)
                {
-                       copy_to_user(buf, statbuf + stat_st, 
-                                      STATBUF_LEN - stat_st);
-                       copy_to_user(buf, statbuf, 
-                                      len - (STATBUF_LEN - stat_st));
+                       if (copy_to_user(buf, statbuf + stat_st,
+                                      STATBUF_LEN - stat_st))
+                               return -EFAULT;
+                       if (copy_to_user(buf, statbuf,
+                                      len - (STATBUF_LEN - stat_st)))
+                               return -EFAULT;
 
                        stat_st = len - (STATBUF_LEN - stat_st);
                }
                else
                {
-                       copy_to_user(buf, statbuf + stat_st, len);
+                       if (copy_to_user(buf, statbuf + stat_st, len))
+                               return -EFAULT;
 
                        stat_st += len;
                        
index 98ef9f8..a6dbfef 100644 (file)
@@ -4683,6 +4683,9 @@ e1000_suspend(struct pci_dev *pdev, pm_message_t state)
        if (adapter->hw.phy_type == e1000_phy_igp_3)
                e1000_phy_powerdown_workaround(&adapter->hw);
 
+       if (netif_running(netdev))
+               e1000_free_irq(adapter);
+
        /* Release control of h/w to f/w.  If f/w is AMT enabled, this
         * would have already happened in close and is redundant. */
        e1000_release_hw_control(adapter);
@@ -4701,6 +4704,7 @@ e1000_resume(struct pci_dev *pdev)
        struct net_device *netdev = pci_get_drvdata(pdev);
        struct e1000_adapter *adapter = netdev_priv(netdev);
        uint32_t manc, ret_val;
+       int err;
 
        pci_set_power_state(pdev, PCI_D0);
        e1000_pci_restore_state(adapter);
@@ -4710,6 +4714,10 @@ e1000_resume(struct pci_dev *pdev)
        pci_enable_wake(pdev, PCI_D3hot, 0);
        pci_enable_wake(pdev, PCI_D3cold, 0);
 
+       if (netif_running(netdev) && (err = e1000_request_irq(adapter)))
+               return err;
+
+       e1000_power_up_phy(adapter);
        e1000_reset(adapter);
        E1000_WRITE_REG(&adapter->hw, WUS, ~0);
 
index 94c38c0..38e8bfa 100644 (file)
@@ -4436,6 +4436,50 @@ static void __devexit nv_remove(struct pci_dev *pci_dev)
        pci_set_drvdata(pci_dev, NULL);
 }
 
+
+#ifdef CONFIG_PM
+
+static int nv_suspend(struct pci_dev *pdev, pm_message_t state)
+{
+       struct net_device *dev = pci_get_drvdata(pdev);
+       struct fe_priv *np = netdev_priv(dev);
+
+       if (!netif_running(dev))
+               goto out;
+
+       netif_device_detach(dev);
+
+       // Gross.
+       nv_close(dev);
+
+       pci_save_state(pdev);
+       pci_enable_wake(pdev, pci_choose_state(pdev, state), np->wolenabled);
+       pci_set_power_state(pdev, pci_choose_state(pdev, state));
+out:
+       return 0;
+}
+
+static int nv_resume(struct pci_dev *pdev)
+{
+       struct net_device *dev = pci_get_drvdata(pdev);
+       int rc = 0;
+
+       if (!netif_running(dev))
+               goto out;
+
+       netif_device_attach(dev);
+
+       pci_set_power_state(pdev, PCI_D0);
+       pci_restore_state(pdev);
+       pci_enable_wake(pdev, PCI_D0, 0);
+
+       rc = nv_open(dev);
+out:
+       return rc;
+}
+
+#endif /* CONFIG_PM */
+
 static struct pci_device_id pci_tbl[] = {
        {       /* nForce Ethernet Controller */
                PCI_DEVICE(PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_NVENET_1),
@@ -4537,6 +4581,10 @@ static struct pci_driver driver = {
        .id_table = pci_tbl,
        .probe = nv_probe,
        .remove = __devexit_p(nv_remove),
+#ifdef CONFIG_PM
+       .suspend        = nv_suspend,
+       .resume         = nv_resume,
+#endif
 };
 
 
index 2024b26..63e9fcf 100644 (file)
 #define        _PC300_H
 
 #include <linux/hdlc.h>
+#include <net/syncppp.h>
 #include "hd64572.h"
 #include "pc300-falc-lh.h"
 
index ef004d0..d54d502 100644 (file)
@@ -425,11 +425,15 @@ fs3270_open(struct inode *inode, struct file *filp)
        minor = iminor(filp->f_dentry->d_inode);
        /* Check for minor 0 multiplexer. */
        if (minor == 0) {
-               if (!current->signal->tty)
+               struct tty_struct *tty;
+               mutex_lock(&tty_mutex);
+               tty = get_current_tty();
+               if (!tty || tty->driver->major != IBM_TTY3270_MAJOR) {
+                       mutex_unlock(&tty_mutex);
                        return -ENODEV;
-               if (current->signal->tty->driver->major != IBM_TTY3270_MAJOR)
-                       return -ENODEV;
-               minor = current->signal->tty->index + RAW3270_FIRSTMINOR;
+               }
+               minor = tty->index + RAW3270_FIRSTMINOR;
+               mutex_unlock(&tty_mutex);
        }
        /* Check if some other program is already using fullscreen mode. */
        fp = (struct fs3270 *) raw3270_find_view(&fs3270_fn, minor);
index 2971804..06e2eee 100644 (file)
@@ -698,7 +698,6 @@ tty3270_alloc_view(void)
        if (!tp->freemem_pages)
                goto out_tp;
        INIT_LIST_HEAD(&tp->freemem);
-       init_timer(&tp->timer);
        for (pages = 0; pages < TTY3270_STRING_PAGES; pages++) {
                tp->freemem_pages[pages] = (void *)
                        __get_free_pages(GFP_KERNEL|GFP_DMA, 0);
index 9f27576..a61beb1 100644 (file)
@@ -1181,8 +1181,21 @@ grow_buffers(struct block_device *bdev, sector_t block, int size)
        } while ((size << sizebits) < PAGE_SIZE);
 
        index = block >> sizebits;
-       block = index << sizebits;
 
+       /*
+        * Check for a block which wants to lie outside our maximum possible
+        * pagecache index.  (this comparison is done using sector_t types).
+        */
+       if (unlikely(index != block >> sizebits)) {
+               char b[BDEVNAME_SIZE];
+
+               printk(KERN_ERR "%s: requested out-of-range block %llu for "
+                       "device %s\n",
+                       __FUNCTION__, (unsigned long long)block,
+                       bdevname(bdev, b));
+               return -EIO;
+       }
+       block = index << sizebits;
        /* Create a page with the proper size buffers.. */
        page = grow_dev_page(bdev, block, index, size);
        if (!page)
@@ -1209,12 +1222,16 @@ __getblk_slow(struct block_device *bdev, sector_t block, int size)
 
        for (;;) {
                struct buffer_head * bh;
+               int ret;
 
                bh = __find_get_block(bdev, block, size);
                if (bh)
                        return bh;
 
-               if (!grow_buffers(bdev, block, size))
+               ret = grow_buffers(bdev, block, size);
+               if (ret < 0)
+                       return NULL;
+               if (ret == 0)
                        free_more_memory();
        }
 }
index b88147c..36e069f 100644 (file)
@@ -1080,8 +1080,10 @@ int cifs_getattr(struct vfsmount *mnt, struct dentry *dentry,
        struct kstat *stat)
 {
        int err = cifs_revalidate(dentry);
-       if (!err)
+       if (!err) {
                generic_fillattr(dentry->d_inode, stat);
+               stat->blksize = CIFS_MAX_MSGSIZE;
+       }
        return err;
 }
 
index abc60b7..0e2294c 100644 (file)
@@ -482,6 +482,8 @@ static int cramfs_readpage(struct file *file, struct page * page)
                pgdata = kmap(page);
                if (compr_len == 0)
                        ; /* hole */
+               else if (compr_len > (PAGE_CACHE_SIZE << 1))
+                       printk(KERN_ERR "cramfs: bad compressed blocksize %u\n", compr_len);
                else {
                        mutex_lock(&read_mutex);
                        bytes_filled = cramfs_uncompress_block(pgdata,
index 0122a27..ad46d25 100644 (file)
@@ -828,18 +828,23 @@ static inline int need_print_warning(struct dquot *dquot)
 static void print_warning(struct dquot *dquot, const char warntype)
 {
        char *msg = NULL;
+       struct tty_struct *tty;
        int flag = (warntype == BHARDWARN || warntype == BSOFTLONGWARN) ? DQ_BLKS_B :
          ((warntype == IHARDWARN || warntype == ISOFTLONGWARN) ? DQ_INODES_B : 0);
 
        if (!need_print_warning(dquot) || (flag && test_and_set_bit(flag, &dquot->dq_flags)))
                return;
 
-       tty_write_message(current->signal->tty, dquot->dq_sb->s_id);
+       mutex_lock(&tty_mutex);
+       tty = get_current_tty();
+       if (!tty)
+               goto out_lock;
+       tty_write_message(tty, dquot->dq_sb->s_id);
        if (warntype == ISOFTWARN || warntype == BSOFTWARN)
-               tty_write_message(current->signal->tty, ": warning, ");
+               tty_write_message(tty, ": warning, ");
        else
-               tty_write_message(current->signal->tty, ": write failed, ");
-       tty_write_message(current->signal->tty, quotatypes[dquot->dq_type]);
+               tty_write_message(tty, ": write failed, ");
+       tty_write_message(tty, quotatypes[dquot->dq_type]);
        switch (warntype) {
                case IHARDWARN:
                        msg = " file limit reached.\r\n";
@@ -860,7 +865,9 @@ static void print_warning(struct dquot *dquot, const char warntype)
                        msg = " block quota exceeded.\r\n";
                        break;
        }
-       tty_write_message(current->signal->tty, msg);
+       tty_write_message(tty, msg);
+out_lock:
+       mutex_unlock(&tty_mutex);
 }
 
 static inline void flush_warnings(struct dquot **dquots, char *warntype)
index 76ca1cb..125d71f 100644 (file)
@@ -532,10 +532,12 @@ static void nfs_direct_write_result(struct rpc_task *task, void *calldata)
 
        spin_lock(&dreq->lock);
 
-       if (likely(status >= 0))
-               dreq->count += data->res.count;
-       else
-               dreq->error = task->tk_status;
+       if (unlikely(status < 0)) {
+               dreq->error = status;
+               goto out_unlock;
+       }
+
+       dreq->count += data->res.count;
 
        if (data->res.verf->committed != NFS_FILE_SYNC) {
                switch (dreq->flags) {
@@ -550,7 +552,7 @@ static void nfs_direct_write_result(struct rpc_task *task, void *calldata)
                                }
                }
        }
-
+out_unlock:
        spin_unlock(&dreq->lock);
 }
 
index e866a79..bda0a59 100644 (file)
--- a/fs/open.c
+++ b/fs/open.c
@@ -1214,6 +1214,7 @@ EXPORT_SYMBOL(sys_close);
 asmlinkage long sys_vhangup(void)
 {
        if (capable(CAP_SYS_TTY_CONFIG)) {
+               /* XXX: this needs locking */
                tty_vhangup(current->signal->tty);
                return 0;
        }
index 715194f..765cc29 100644 (file)
@@ -408,6 +408,8 @@ static int do_task_stat(struct task_struct *task, char * buffer, int whole)
        sigemptyset(&sigign);
        sigemptyset(&sigcatch);
        cutime = cstime = utime = stime = cputime_zero;
+
+       mutex_lock(&tty_mutex);
        read_lock(&tasklist_lock);
        if (task->sighand) {
                spin_lock_irq(&task->sighand->siglock);
@@ -453,6 +455,7 @@ static int do_task_stat(struct task_struct *task, char * buffer, int whole)
        pgid = vx_info_map_pid(task->vx_info, pgid);
 
        read_unlock(&tasklist_lock);
+       mutex_unlock(&tty_mutex);
 
        if (!whole || num_threads<2) {
                wchan = 0;
index 4eed2f6..0b83166 100644 (file)
@@ -1041,6 +1041,19 @@ out_release:
 
 EXPORT_SYMBOL(do_splice_direct);
 
+/*
+ * After the inode slimming patch, i_pipe/i_bdev/i_cdev share the same
+ * location, so checking ->i_pipe is not enough to verify that this is a
+ * pipe.
+ */
+static inline int is_pipe(struct inode *inode)
+{
+       if (inode->i_pipe && S_ISFIFO(inode->i_mode))
+               return 1;
+
+       return 0;
+}
+
 /*
  * Determine where to splice to/from.
  */
@@ -1052,8 +1065,8 @@ static long do_splice(struct file *in, loff_t __user *off_in,
        loff_t offset, *off;
        long ret;
 
-       pipe = in->f_dentry->d_inode->i_pipe;
-       if (pipe) {
+       if (is_pipe(in->f_dentry->d_inode)) {
+               pipe = in->f_dentry->d_inode->i_pipe;
                if (off_in)
                        return -ESPIPE;
                if (off_out) {
@@ -1073,8 +1086,8 @@ static long do_splice(struct file *in, loff_t __user *off_in,
                return ret;
        }
 
-       pipe = out->f_dentry->d_inode->i_pipe;
-       if (pipe) {
+       if (is_pipe(out->f_dentry->d_inode)) {
+               pipe = out->f_dentry->d_inode->i_pipe;
                if (off_out)
                        return -ESPIPE;
                if (off_in) {
@@ -1231,7 +1244,7 @@ static int get_iovec_page_array(const struct iovec __user *iov,
 static long do_vmsplice(struct file *file, const struct iovec __user *iov,
                        unsigned long nr_segs, unsigned int flags)
 {
-       struct pipe_inode_info *pipe = file->f_dentry->d_inode->i_pipe;
+       struct pipe_inode_info *pipe;
        struct page *pages[PIPE_BUFFERS];
        struct partial_page partial[PIPE_BUFFERS];
        struct splice_pipe_desc spd = {
@@ -1241,7 +1254,7 @@ static long do_vmsplice(struct file *file, const struct iovec __user *iov,
                .ops = &user_page_pipe_buf_ops,
        };
 
-       if (unlikely(!pipe))
+       if (!is_pipe(file->f_dentry->d_inode))
                return -EBADF;
        if (unlikely(nr_segs > UIO_MAXIOV))
                return -EINVAL;
@@ -1253,6 +1266,7 @@ static long do_vmsplice(struct file *file, const struct iovec __user *iov,
        if (spd.nr_pages <= 0)
                return spd.nr_pages;
 
+       pipe = file->f_dentry->d_inode->i_pipe;
        return splice_to_pipe(pipe, &spd);
 }
 
@@ -1475,15 +1489,20 @@ static int link_pipe(struct pipe_inode_info *ipipe,
 static long do_tee(struct file *in, struct file *out, size_t len,
                   unsigned int flags)
 {
-       struct pipe_inode_info *ipipe = in->f_dentry->d_inode->i_pipe;
-       struct pipe_inode_info *opipe = out->f_dentry->d_inode->i_pipe;
+       struct pipe_inode_info *ipipe;
+       struct pipe_inode_info *opipe;
        int ret = -EINVAL;
 
+       if (!is_pipe(in->f_dentry->d_inode) || !is_pipe(out->f_dentry->d_inode))
+               return ret;
+
        /*
         * Duplicate the contents of ipipe to opipe without actually
         * copying the data.
         */
-       if (ipipe && opipe && ipipe != opipe) {
+       ipipe = in->f_dentry->d_inode->i_pipe;
+       opipe = out->f_dentry->d_inode->i_pipe;
+       if (ipipe != opipe) {
                /*
                 * Keep going, unless we encounter an error. The ipipe/opipe
                 * ordering doesn't really matter.
index 3cadfa5..70f88ae 100644 (file)
@@ -646,7 +646,7 @@ static inline void tracehook_report_clone_complete(unsigned long clone_flags,
 {
 #ifdef CONFIG_UTRACE
        if (current->utrace_flags & UTRACE_ACTION_QUIESCE)
-               utrace_quiescent(current);
+               utrace_quiescent(current, NULL);
 #endif
 }
 
index 04827ca..3585883 100644 (file)
@@ -174,7 +174,7 @@ struct tty_struct {
        struct tty_driver *driver;
        int index;
        struct tty_ldisc ldisc;
-       struct semaphore termios_sem;
+       struct mutex termios_mutex;
        struct termios *termios, *termios_locked;
        char name[64];
        int pgrp;
@@ -190,7 +190,6 @@ struct tty_struct {
        struct tty_struct *link;
        struct fasync_struct *fasync;
        struct tty_bufhead buf;
-       int max_flip_cnt;
        int alt_speed;          /* For magic substitution of 38400 bps */
        wait_queue_head_t write_wait;
        wait_queue_head_t read_wait;
@@ -339,5 +338,45 @@ static inline dev_t tty_devnum(struct tty_struct *tty)
        return MKDEV(tty->driver->major, tty->driver->minor_start) + tty->index;
 }
 
+static inline void proc_clear_tty(struct task_struct *p)
+{
+       spin_lock_irq(&p->sighand->siglock);
+       p->signal->tty = NULL;
+       spin_unlock_irq(&p->sighand->siglock);
+}
+
+static inline
+void __proc_set_tty(struct task_struct *tsk, struct tty_struct *tty)
+{
+       if (tty) {
+               tty->session = tsk->signal->session;
+               tty->pgrp = process_group(tsk);
+       }
+       tsk->signal->tty = tty;
+       tsk->signal->tty_old_pgrp = 0;
+}
+
+static inline
+void proc_set_tty(struct task_struct *tsk, struct tty_struct *tty)
+{
+       spin_lock_irq(&tsk->sighand->siglock);
+       __proc_set_tty(tsk, tty);
+       spin_unlock_irq(&tsk->sighand->siglock);
+}
+
+static inline struct tty_struct *get_current_tty(void)
+{
+       struct tty_struct *tty;
+       WARN_ON_ONCE(!mutex_is_locked(&tty_mutex));
+       tty = current->signal->tty;
+       /*
+        * session->tty can be changed/cleared from under us, make sure we
+        * issue the load. The obtained pointer, when not NULL, is valid as
+        * long as we hold tty_mutex.
+        */
+       barrier();
+       return tty;
+}
+
 #endif /* __KERNEL__ */
 #endif
index e0f8ae1..f310aa3 100644 (file)
@@ -464,7 +464,7 @@ const struct utrace_regset *utrace_regset(struct task_struct *target,
 /*
  * Hooks in <linux/tracehook.h> call these entry points to the utrace dispatch.
  */
-void utrace_quiescent(struct task_struct *);
+int utrace_quiescent(struct task_struct *, struct utrace_signal *);
 void utrace_release_task(struct task_struct *);
 int utrace_get_signal(struct task_struct *, struct pt_regs *,
                      siginfo_t *, struct k_sigaction *);
index 3158d5a..c6aa9d3 100644 (file)
@@ -146,6 +146,7 @@ struct task_struct *vx_get_proc_task(struct inode *inode, struct pid *pid)
                        "dropping task %p[#%u,%u] for %p[#%u,%u]",
                        task, task->xid, task->pid,
                        current, current->xid, current->pid);
+               put_task_struct(task);
                task = NULL;
        }
        return task;
index 918a297..1009d3f 100644 (file)
@@ -33,7 +33,8 @@ extern int fg_console, last_console, want_console;
 int vc_allocate(unsigned int console);
 int vc_cons_allocated(unsigned int console);
 int vc_resize(struct vc_data *vc, unsigned int cols, unsigned int lines);
-void vc_disallocate(unsigned int console);
+int vc_lock_resize(struct vc_data *vc, unsigned int cols, unsigned int lines);
+void vc_deallocate(unsigned int console);
 void reset_palette(struct vc_data *vc);
 void do_blank_screen(int entering_gfx);
 void do_unblank_screen(int leaving_gfx);
index 2a7c933..fa54eeb 100644 (file)
@@ -427,6 +427,7 @@ static void do_acct_process(struct file *file)
        u64 elapsed;
        u64 run_time;
        struct timespec uptime;
+       struct tty_struct *tty;
 
        /*
         * First check to see if there is enough free_space to continue
@@ -483,10 +484,10 @@ static void do_acct_process(struct file *file)
        ac.ac_ppid = current->parent->tgid;
 #endif
 
-       read_lock(&tasklist_lock);      /* pin current->signal */
-       ac.ac_tty = current->signal->tty ?
-               old_encode_dev(tty_devnum(current->signal->tty)) : 0;
-       read_unlock(&tasklist_lock);
+       mutex_lock(&tty_mutex);
+       tty = get_current_tty();
+       ac.ac_tty = tty ? old_encode_dev(tty_devnum(tty)) : 0;
+       mutex_unlock(&tty_mutex);
 
        spin_lock_irq(&current->sighand->siglock);
        ac.ac_utime = encode_comp_t(jiffies_to_AHZ(cputime_to_jiffies(pacct->ac_utime)));
index c64da57..8fab061 100644 (file)
@@ -817,10 +817,14 @@ static void audit_log_exit(struct audit_context *context, struct task_struct *ts
                audit_log_format(ab, " success=%s exit=%ld", 
                                 (context->return_valid==AUDITSC_SUCCESS)?"yes":"no",
                                 context->return_code);
+
+       mutex_lock(&tty_mutex);
+       read_lock(&tasklist_lock);
        if (tsk->signal && tsk->signal->tty && tsk->signal->tty->name)
                tty = tsk->signal->tty->name;
        else
                tty = "(none)";
+       read_unlock(&tasklist_lock);
        audit_log_format(ab,
                  " a0=%lx a1=%lx a2=%lx a3=%lx items=%d"
                  " ppid=%d pid=%d auid=%u uid=%u gid=%u"
@@ -838,6 +842,9 @@ static void audit_log_exit(struct audit_context *context, struct task_struct *ts
                  context->gid,
                  context->euid, context->suid, context->fsuid,
                  context->egid, context->sgid, context->fsgid, tty);
+
+       mutex_unlock(&tty_mutex);
+
        audit_log_task_info(ab, tsk);
        if (context->filterkey) {
                audit_log_format(ab, " key=");
index 99e7912..80530fb 100644 (file)
@@ -385,9 +385,7 @@ void daemonize(const char *name, ...)
        exit_mm(current);
 
        set_special_pids(1, 1);
-       mutex_lock(&tty_mutex);
-       current->signal->tty = NULL;
-       mutex_unlock(&tty_mutex);
+       proc_clear_tty(current);
 
        /* Block and flush all signals */
        sigfillset(&blocked);
index 786130d..ee0b4cb 100644 (file)
@@ -1178,8 +1178,6 @@ ptrace_report(struct utrace_attached_engine *engine, struct task_struct *tsk,
        }
 #endif
 
-       BUG_ON(state->u.live.stopped);
-
        /*
         * Set our QUIESCE flag right now, before notifying the tracer.
         * We do this before setting state->u.live.stopped rather than
index ca7ce52..a87239d 100644 (file)
@@ -1395,7 +1395,6 @@ asmlinkage long sys_setsid(void)
        pid_t session;
        int err = -EPERM;
 
-       mutex_lock(&tty_mutex);
        write_lock_irq(&tasklist_lock);
 
        /* Fail if I am already a session leader */
@@ -1415,12 +1414,15 @@ asmlinkage long sys_setsid(void)
 
        group_leader->signal->leader = 1;
        __set_special_pids(session, session);
+
+       spin_lock(&group_leader->sighand->siglock);
        group_leader->signal->tty = NULL;
        group_leader->signal->tty_old_pgrp = 0;
+       spin_unlock(&group_leader->sighand->siglock);
+
        err = process_group(group_leader);
 out:
        write_unlock_irq(&tasklist_lock);
-       mutex_unlock(&tty_mutex);
        return err;
 }
 
index 52d9b00..5d1e261 100644 (file)
@@ -119,9 +119,13 @@ utrace_free(struct rcu_head *rhead)
        kmem_cache_free(utrace_cachep, utrace);
 }
 
+/*
+ * Called with utrace locked.  Clean it up and free it via RCU.
+ */
 static void
 rcu_utrace_free(struct utrace *utrace)
 {
+       utrace_unlock(utrace);
        INIT_RCU_HEAD(&utrace->u.dead);
        call_rcu(&utrace->u.dead, utrace_free);
 }
@@ -135,61 +139,125 @@ utrace_engine_free(struct rcu_head *rhead)
 }
 
 /*
- * Called with utrace locked and the target quiescent (maybe current).
- * If this was the last engine, utrace is left locked and not freed,
- * but is removed from the task.
+ * Remove the utrace pointer from the task, unless there is a pending
+ * forced signal (or it's quiescent in utrace_get_signal).
  */
-static void
-remove_engine(struct utrace_attached_engine *engine,
-             struct task_struct *tsk, struct utrace *utrace)
+static inline void
+utrace_clear_tsk(struct task_struct *tsk, struct utrace *utrace)
 {
-       list_del_rcu(&engine->entry);
-       if (list_empty(&utrace->engines)) {
+       if (utrace->u.live.signal == NULL) {
                task_lock(tsk);
                if (likely(tsk->utrace != NULL)) {
                        rcu_assign_pointer(tsk->utrace, NULL);
-                       tsk->utrace_flags = 0;
+                       tsk->utrace_flags &= UTRACE_ACTION_NOREAP;
                }
                task_unlock(tsk);
        }
-       call_rcu(&engine->rhead, utrace_engine_free);
 }
 
 /*
- * This is pointed to by the utrace struct, but it's really a private
- * structure between utrace_get_signal and utrace_inject_signal.
+ * Called with utrace locked and the target quiescent (maybe current).
+ * If this was the last engine and there is no parting forced signal
+ * pending, utrace is left locked and not freed, but is removed from the task.
  */
-struct utrace_signal
+static void
+remove_engine(struct utrace_attached_engine *engine,
+             struct task_struct *tsk, struct utrace *utrace)
 {
-       siginfo_t *const info;
-       struct k_sigaction *return_ka;
-       int signr;
-};
+       list_del_rcu(&engine->entry);
+       if (list_empty(&utrace->engines))
+               utrace_clear_tsk(tsk, utrace);
+       call_rcu(&engine->rhead, utrace_engine_free);
+}
+
 
 /*
  * Called with utrace locked, after remove_engine may have run.
  * Passed the flags from all remaining engines, i.e. zero if none left.
  * Install the flags in tsk->utrace_flags and return with utrace unlocked.
- * If no engines are left, utrace is freed and we return NULL.
+ * If no engines are left and there is no parting forced signal pending,
+ * utrace is freed and we return NULL.
  */
 static struct utrace *
 check_dead_utrace(struct task_struct *tsk, struct utrace *utrace,
-                unsigned long flags)
+                 unsigned long flags)
 {
-       if (flags) {
-               tsk->utrace_flags = flags;
-               utrace_unlock(utrace);
-               return utrace;
+       long exit_state = 0;
+
+       if (utrace->u.live.signal != NULL)
+               /*
+                * There is a pending forced signal.  It may have been
+                * left by an engine now detached.  The empty utrace
+                * remains attached until it can be processed.
+                */
+               flags |= UTRACE_ACTION_QUIESCE;
+
+       /*
+        * If tracing was preventing a SIGCHLD or self-reaping
+        * and is no longer, we'll do that report or reaping now.
+        */
+       if (((tsk->utrace_flags &~ flags) & UTRACE_ACTION_NOREAP)
+           && tsk->exit_state && !utrace->u.exit.notified) {
+               BUG_ON(tsk->exit_state != EXIT_ZOMBIE);
+               /*
+                * While holding the utrace lock, mark that it's been done.
+                * For self-reaping, we need to change tsk->exit_state
+                * before clearing tsk->utrace_flags, so that the real
+                * parent can't see it in EXIT_ZOMBIE momentarily and reap it.
+                */
+               utrace->u.exit.notified = 1;
+               if (tsk->exit_signal == -1) {
+                       exit_state = xchg(&tsk->exit_state, EXIT_DEAD);
+                       BUG_ON(exit_state != EXIT_ZOMBIE);
+                       exit_state = EXIT_DEAD;
+
+                       /*
+                        * Now that we've changed its state to DEAD,
+                        * it's safe to install the new tsk->utrace_flags
+                        * value without the UTRACE_ACTION_NOREAP bit set.
+                        */
+               }
+               else if (thread_group_empty(tsk)) {
+                       /*
+                        * We need to prevent the real parent from reaping
+                        * until after we've called do_notify_parent, below.
+                        * It can get into wait_task_zombie any time after
+                        * the UTRACE_ACTION_NOREAP bit is cleared.  It's
+                        * safe for that to do everything it does until its
+                        * release_task call starts tearing things down.
+                        * Holding tasklist_lock for reading prevents
+                        * release_task from proceeding until we've done
+                        * everything we need to do.
+                        */
+                       exit_state = EXIT_ZOMBIE;
+                       read_lock(&tasklist_lock);
+               }
        }
 
-       if (utrace->u.live.signal && utrace->u.live.signal->signr != 0) {
+       tsk->utrace_flags = flags;
+       if (flags)
                utrace_unlock(utrace);
-               return utrace;
+       else {
+               rcu_utrace_free(utrace);
+               utrace = NULL;
        }
 
-       utrace_unlock(utrace);
-       rcu_utrace_free(utrace);
-       return NULL;
+       /*
+        * Now we're finished updating the utrace state.
+        * Do a pending self-reaping or parent notification.
+        */
+       if (exit_state == EXIT_DEAD)
+               /*
+                * Note this can wind up in utrace_reap and do more callbacks.
+                * Our callers must be in places where that is OK.
+                */
+               release_task(tsk);
+       else if (exit_state == EXIT_ZOMBIE) {
+               do_notify_parent(tsk, tsk->exit_signal);
+               read_unlock(&tasklist_lock); /* See comment above.  */
+       }
+
+       return utrace;
 }
 
 
@@ -299,6 +367,7 @@ restart:
                        rcu_read_unlock();
                        return engine;
                }
+               rcu_read_unlock();
 
                engine = kmem_cache_alloc(utrace_engine_cachep, SLAB_KERNEL);
                if (unlikely(engine == NULL))
@@ -311,8 +380,8 @@ restart:
                        rcu_read_unlock();
                        goto first;
                }
-
                utrace_lock(utrace);
+
                if (flags & UTRACE_ATTACH_EXCLUSIVE) {
                        struct utrace_attached_engine *old;
                        old = matching_engine(utrace, flags, ops, data);
@@ -334,6 +403,8 @@ restart:
                        kmem_cache_free(utrace_engine_cachep, engine);
                        goto restart;
                }
+               rcu_read_unlock();
+
                list_add_tail_rcu(&engine->entry, &utrace->engines);
        }
 
@@ -365,29 +436,6 @@ static const struct utrace_engine_ops dead_engine_ops =
 };
 
 
-/*
- * If tracing was preventing a SIGCHLD or self-reaping
- * and is no longer, do that report or reaping right now.
- */
-static void
-check_noreap(struct task_struct *target, struct utrace *utrace,
-            u32 old_action, u32 action)
-{
-       if ((action | ~old_action) & UTRACE_ACTION_NOREAP)
-               return;
-
-       if (utrace && xchg(&utrace->u.exit.notified, 1))
-               return;
-
-       if (target->exit_signal == -1)
-               release_task(target);
-       else if (thread_group_empty(target)) {
-               read_lock(&tasklist_lock);
-               do_notify_parent(target, target->exit_signal);
-               read_unlock(&tasklist_lock);
-       }
-}
-
 /*
  * We may have been the one keeping the target thread quiescent.
  * Check if it should wake up now.
@@ -411,8 +459,6 @@ wake_quiescent(unsigned long old_flags,
                list_for_each_entry(engine, &utrace->engines, entry)
                        flags |= engine->flags | UTRACE_EVENT(REAP);
                utrace = check_dead_utrace(target, utrace, flags);
-
-               check_noreap(target, utrace, old_flags, flags);
                return;
        }
 
@@ -528,7 +574,6 @@ restart:
                }
                call_rcu(&engine->rhead, utrace_engine_free);
        }
-       utrace_unlock(utrace);
 
        rcu_utrace_free(utrace);
 }
@@ -694,9 +739,8 @@ remove_detached(struct task_struct *tsk, struct utrace *utrace,
                struct utrace **utracep, u32 action)
 {
        struct utrace_attached_engine *engine, *next;
-       unsigned long flags;
+       unsigned long flags = 0;
 
-       flags = 0;
        list_for_each_entry_safe(engine, next, &utrace->engines, entry) {
                if (engine->ops == &dead_engine_ops)
                        remove_engine(engine, tsk, utrace);
@@ -724,11 +768,12 @@ check_detach(struct task_struct *tsk, u32 action)
        return action;
 }
 
-static inline void
+static inline int
 check_quiescent(struct task_struct *tsk, u32 action)
 {
        if (action & UTRACE_ACTION_STATE_MASK)
-               utrace_quiescent(tsk);
+               return utrace_quiescent(tsk, NULL);
+       return 0;
 }
 
 /*
@@ -826,13 +871,31 @@ utrace_report_jctl(int what)
 }
 
 
+/*
+ * Return nonzero if there is a SIGKILL that should be waking us up.
+ * Called with the siglock held.
+ */
+static inline int
+sigkill_pending(struct task_struct *tsk)
+{
+       return ((sigismember(&tsk->pending.signal, SIGKILL)
+                || sigismember(&tsk->signal->shared_pending.signal, SIGKILL))
+               && !unlikely(sigismember(&tsk->blocked, SIGKILL)));
+}
+
 /*
  * Called if UTRACE_EVENT(QUIESCE) or UTRACE_ACTION_QUIESCE flag is set.
  * Also called after other event reports.
  * It is a good time to block.
+ * Returns nonzero if we woke up prematurely due to SIGKILL.
+ *
+ * The signal pointer is nonzero when called from utrace_get_signal,
+ * where a pending forced signal can be processed right away.  Otherwise,
+ * we keep UTRACE_ACTION_QUIESCE set after resuming so that utrace_get_signal
+ * will be entered before user mode.
  */
-void
-utrace_quiescent(struct task_struct *tsk)
+int
+utrace_quiescent(struct task_struct *tsk, struct utrace_signal *signal)
 {
        struct utrace *utrace = tsk->utrace;
        unsigned long action;
@@ -846,6 +909,13 @@ restart:
         * If some engines want us quiescent, we block here.
         */
        if (action & UTRACE_ACTION_QUIESCE) {
+               int killed;
+
+               if (signal != NULL) {
+                       BUG_ON(utrace->u.live.signal != NULL);
+                       utrace->u.live.signal = signal;
+               }
+
                spin_lock_irq(&tsk->sighand->siglock);
                /*
                 * If wake_quiescent is trying to wake us up now, it will
@@ -855,8 +925,8 @@ restart:
                 * release the siglock it's waiting for.
                 * Never stop when there is a SIGKILL bringing us down.
                 */
-               if ((tsk->utrace_flags & UTRACE_ACTION_QUIESCE)
-                   /*&& !(tsk->signal->flags & SIGNAL_GROUP_SIGKILL)*/) {
+               killed = sigkill_pending(tsk);
+               if (!killed && (tsk->utrace_flags & UTRACE_ACTION_QUIESCE)) {
                        set_current_state(TASK_TRACED);
                        /*
                         * If there is a group stop in progress,
@@ -870,6 +940,20 @@ restart:
                else
                        spin_unlock_irq(&tsk->sighand->siglock);
 
+               if (signal != NULL) {
+                       /*
+                        * We know the struct stays in place when its
+                        * u.live.signal is set, see check_dead_utrace.
+                        * This makes it safe to clear its pointer here.
+                        */
+                       BUG_ON(tsk->utrace != utrace);
+                       BUG_ON(utrace->u.live.signal != signal);
+                       utrace->u.live.signal = NULL;
+               }
+
+               if (killed)     /* Game over, man!  */
+                       return 1;
+
                /*
                 * We've woken up.  One engine could be waking us up while
                 * another has asked us to quiesce.  So check afresh.  We
@@ -887,6 +971,10 @@ restart:
                 * Our flags are out of date.
                 * Update the set of events of interest from the union
                 * of the interests of the remaining tracing engines.
+                * This may notice that there are no engines left
+                * and clean up the struct utrace.  It's left in place
+                * and the QUIESCE flag set as long as utrace_get_signal
+                * still needs to process a pending forced signal.
                 */
                struct utrace_attached_engine *engine;
                unsigned long flags = 0;
@@ -894,8 +982,9 @@ restart:
                utrace_lock(utrace);
                list_for_each_entry(engine, &utrace->engines, entry)
                        flags |= engine->flags | UTRACE_EVENT(REAP);
-               tsk->utrace_flags = flags;
-               utrace_unlock(utrace);
+               if (flags == 0)
+                       utrace_clear_tsk(tsk, utrace);
+               utrace = check_dead_utrace(tsk, utrace, flags);
        }
 
        /*
@@ -918,6 +1007,8 @@ restart:
                tracehook_enable_syscall_trace(tsk);
        else
                tracehook_disable_syscall_trace(tsk);
+
+       return 0;
 }
 
 
@@ -946,7 +1037,7 @@ utrace_report_exit(long *exit_code)
 }
 
 /*
- * Called iff UTRACE_EVENT(DEATH) flag is set.
+ * Called iff UTRACE_EVENT(DEATH) or UTRACE_ACTION_QUIESCE flag is set.
  *
  * It is always possible that we are racing with utrace_release_task here,
  * if UTRACE_ACTION_NOREAP is not set, or in the case of non-leader exec
@@ -974,6 +1065,7 @@ utrace_report_death(struct task_struct *tsk, struct utrace *utrace)
                if (engine->flags & UTRACE_EVENT(QUIESCE))
                        REPORT(report_quiesce);
        }
+
        /*
         * Unconditionally lock and recompute the flags.
         * This may notice that there are no engines left and
@@ -1006,8 +1098,6 @@ utrace_report_death(struct task_struct *tsk, struct utrace *utrace)
 
                        utrace_unlock(utrace);
                }
-
-               check_noreap(tsk, utrace, oaction, action);
        }
 }
 
@@ -1095,9 +1185,27 @@ utrace_report_syscall(struct pt_regs *regs, int is_exit)
                        break;
        }
        action = check_detach(tsk, action);
-       check_quiescent(tsk, action);
+       if (unlikely(check_quiescent(tsk, action)) && !is_exit)
+               /*
+                * We are continuing despite QUIESCE because of a SIGKILL.
+                * Don't let the system call actually proceed.
+                */
+               tracehook_abort_syscall(regs);
 }
 
+
+/*
+ * This is pointed to by the utrace struct, but it's really a private
+ * structure between utrace_get_signal and utrace_inject_signal.
+ */
+struct utrace_signal
+{
+       siginfo_t *const info;
+       struct k_sigaction *return_ka;
+       int signr;
+};
+
+
 // XXX copied from signal.c
 #ifdef SIGEMT
 #define M_SIGEMT       M(SIGEMT)
@@ -1191,38 +1299,15 @@ utrace_get_signal(struct task_struct *tsk, struct pt_regs *regs,
        struct k_sigaction *ka;
        unsigned long action, event;
 
-#if 0                          /* XXX */
-       if (tsk->signal->flags & SIGNAL_GROUP_SIGKILL)
-               return 0;
-#endif
-
-       /*
-        * If we should quiesce, now is the time.
-        * First stash a pointer to the state on our stack,
-        * so that utrace_inject_signal can tell us what to do.
-        */
-       if (utrace->u.live.signal == NULL)
-               utrace->u.live.signal = &signal;
-
-       if (tsk->utrace_flags & UTRACE_ACTION_QUIESCE) {
-               spin_unlock_irq(&tsk->sighand->siglock);
-               utrace_quiescent(tsk);
-               if (signal.signr == 0)
-                       /*
-                        * This return value says to reacquire the siglock
-                        * and check again.  This will check for a pending
-                        * group stop and process it before coming back here.
-                        */
-                       return -1;
-               spin_lock_irq(&tsk->sighand->siglock);
-       }
-
        /*
         * If a signal was injected previously, it could not use our
         * stack space directly.  It had to allocate a data structure,
         * which we can now copy out of and free.
+        *
+        * We don't have to lock access to u.live.signal because it's only
+        * touched by utrace_inject_signal when we're quiescent.
         */
-       if (utrace->u.live.signal != &signal) {
+       if (utrace->u.live.signal != NULL) {
                signal.signr = utrace->u.live.signal->signr;
                copy_siginfo(info, utrace->u.live.signal->info);
                if (utrace->u.live.signal->return_ka)
@@ -1230,8 +1315,57 @@ utrace_get_signal(struct task_struct *tsk, struct pt_regs *regs,
                else
                        signal.return_ka = NULL;
                kfree(utrace->u.live.signal);
+               utrace->u.live.signal = NULL;
+       }
+
+       /*
+        * If we should quiesce, now is the time.
+        * First stash a pointer to the state on our stack,
+        * so that utrace_inject_signal can tell us what to do.
+        */
+       if (tsk->utrace_flags & UTRACE_ACTION_QUIESCE) {
+               int killed = sigkill_pending(tsk);
+               if (!killed) {
+                       spin_unlock_irq(&tsk->sighand->siglock);
+
+                       killed = utrace_quiescent(tsk, &signal);
+
+                       /*
+                        * Noone wants us quiescent any more, we can take
+                        * signals.  Unless we have a forced signal to take,
+                        * back out to the signal code to resynchronize after
+                        * releasing the siglock.
+                        */
+                       if (signal.signr == 0 && !killed)
+                               /*
+                                * This return value says to reacquire the
+                                * siglock and check again.  This will check
+                                * for a pending group stop and process it
+                                * before coming back here.
+                                */
+                               return -1;
+
+                       spin_lock_irq(&tsk->sighand->siglock);
+               }
+               if (killed) {
+                       /*
+                        * The only reason we woke up now was because of a
+                        * SIGKILL.  Don't do normal dequeuing in case it
+                        * might get a signal other than SIGKILL.  That would
+                        * perturb the death state so it might differ from
+                        * what the debugger would have allowed to happen.
+                        * Instead, pluck out just the SIGKILL to be sure
+                        * we'll die immediately with nothing else different
+                        * from the quiescent state the debugger wanted us in.
+                        */
+                       sigset_t sigkill_only;
+                       sigfillset(&sigkill_only);
+                       sigdelset(&sigkill_only, SIGKILL);
+                       killed = dequeue_signal(tsk, &sigkill_only, info);
+                       BUG_ON(killed != SIGKILL);
+                       return killed;
+               }
        }
-       utrace->u.live.signal = NULL;
 
        /*
         * If a signal was injected, everything is in place now.  Go do it.
@@ -1270,6 +1404,10 @@ utrace_get_signal(struct task_struct *tsk, struct pt_regs *regs,
        ka = &tsk->sighand->action[signal.signr - 1];
        *return_ka = *ka;
 
+       /*
+        * We are never allowed to interfere with SIGKILL,
+        * just punt after filling in *return_ka for our caller.
+        */
        if (signal.signr == SIGKILL)
                return signal.signr;
 
@@ -1329,9 +1467,6 @@ utrace_get_signal(struct task_struct *tsk, struct pt_regs *regs,
                recalc_sigpending_tsk(tsk);
        }
 
-       if (tsk->utrace != utrace)
-               rcu_utrace_free(utrace);
-
        /*
         * We express the chosen action to the signals code in terms
         * of a representative signal whose default action does it.
@@ -1416,7 +1551,9 @@ utrace_inject_signal(struct task_struct *target,
 
        ret = 0;
        signal = utrace->u.live.signal;
-       if (signal == NULL) {
+       if (unlikely(target->exit_state))
+               ret = -ESRCH;
+       else if (signal == NULL) {
                ret = -ENOSYS;  /* XXX */
        }
        else if (signal->signr != 0)
index 08c9fff..e85c60a 100644 (file)
@@ -950,7 +950,8 @@ asmlinkage long sys_move_pages(pid_t pid, unsigned long nr_pages,
                                goto out;
 
                        pm[i].node = node;
-               }
+               } else
+                       pm[i].node = 0; /* anything to not match MAX_NUMNODES */
        }
        /* End marker */
        pm[nr_pages].node = MAX_NUMNODES;
index 4d6ba97..fc515fe 100644 (file)
@@ -1705,10 +1705,13 @@ static inline void flush_unauthorized_files(struct files_struct * files)
 {
        struct avc_audit_data ad;
        struct file *file, *devnull = NULL;
-       struct tty_struct *tty = current->signal->tty;
+       struct tty_struct *tty;
        struct fdtable *fdt;
        long j = -1;
+       int drop_tty = 0;
 
+       mutex_lock(&tty_mutex);
+       tty = get_current_tty();
        if (tty) {
                file_list_lock();
                file = list_entry(tty->tty_files.next, typeof(*file), f_u.fu_list);
@@ -1721,13 +1724,16 @@ static inline void flush_unauthorized_files(struct files_struct * files)
                        struct inode *inode = file->f_dentry->d_inode;
                        if (inode_has_perm(current, inode,
                                           FILE__READ | FILE__WRITE, NULL)) {
-                               /* Reset controlling tty. */
-                               current->signal->tty = NULL;
-                               current->signal->tty_old_pgrp = 0;
+                               drop_tty = 1;
                        }
                }
                file_list_unlock();
+
+               /* Reset controlling tty. */
+               if (drop_tty)
+                       proc_set_tty(current, NULL);
        }
+       mutex_unlock(&tty_mutex);
 
        /* Revalidate access to inherited open files. */