#
# 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
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
#
# 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
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
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
init_timer(&wakeup_timer);
sigfillset(¤t->blocked);
- current->signal->tty = NULL;
printk(KERN_NOTICE "Voyager starting monitor thread\n");
#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)
{
#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>
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 */
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, ¤t->thread.regs);
if (error == 0){
# 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
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
# 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
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
# 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
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
#
# 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
# 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
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
#
# 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
# 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
#
# 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
# 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
# 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
#
# 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
# 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
# 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
# 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
# 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
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
#
# 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
# 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"
#
# 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
#
# 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
# 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
# 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"
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
#
# 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
# 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
#
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
#
# 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
# 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
#
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
#
# 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
# 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
# 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
#
# 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
# 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
# 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
#
# 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
# 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
# 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
# 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
# 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
# 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
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
#
# 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
# 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
#
# 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
# 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
# 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
#
# 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
# 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
# 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
# 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
# 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
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
#
# 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
/* 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;
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 */
* 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 *);
"!= #fd's(%d) in %s\n",
tty->name, tty->count, count, routine);
return count;
- }
+ }
#endif
return 0;
}
* 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
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);
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);
* 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);
}
/*
* 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)
*
* 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)
{
*/
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 */
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);
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
* 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();
kill_pg(tty_pgrp, SIGCONT, on_exit);
}
- /* Must lock changes to tty_old_pgrp */
- mutex_lock(&tty_mutex);
+ spin_lock_irq(¤t->sighand->siglock);
current->signal->tty_old_pgrp = 0;
- tty->session = 0;
- tty->pgrp = -1;
+ session = current->signal->session;
+ spin_unlock_irq(¤t->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();
}
* 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);
}
* 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)
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;
filp->f_op = &tty_fops;
goto retry_open;
}
+
+ mutex_lock(&tty_mutex);
+ spin_lock_irq(¤t->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(¤t->sighand->siglock);
+ mutex_unlock(&tty_mutex);
return 0;
}
* 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)
* @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;
}
/**
* 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,
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)
kill_pg(real_tty->pgrp, SIGWINCH, 1);
tty->winsize = tmp_ws;
real_tty->winsize = tmp_ws;
+done:
+ mutex_unlock(&tty->termios_mutex);
return 0;
}
* 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
/*
* 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;
}
/**
* 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)
* 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)
* 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)
* 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;
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)
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);
if (!tty)
return;
- session = tty->session;
+ session = tty->session;
/* We don't want an ldisc switch during this */
disc = tty_ldisc_ref(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);
#include <linux/mm.h>
#include <linux/module.h>
#include <linux/bitops.h>
+#include <linux/mutex.h>
#include <asm/io.h>
#include <asm/uaccess.h>
/* 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);
(ld->set_termios)(tty, &old_termios);
tty_ldisc_deref(ld);
}
- up(&tty->termios_sem);
+ mutex_unlock(&tty->termios_mutex);
}
/**
{
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;
}
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;
}
*
* 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,
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;
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;
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();
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);
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;
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();
}
}
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;
}
}
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;
}
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;
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;
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;
}
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;
}
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;
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);
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);
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);
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),
.id_table = pci_tbl,
.probe = nv_probe,
.remove = __devexit_p(nv_remove),
+#ifdef CONFIG_PM
+ .suspend = nv_suspend,
+ .resume = nv_resume,
+#endif
};
#define _PC300_H
#include <linux/hdlc.h>
+#include <net/syncppp.h>
#include "hd64572.h"
#include "pc300-falc-lh.h"
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);
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);
} 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)
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();
}
}
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;
}
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,
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";
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)
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) {
}
}
}
-
+out_unlock:
spin_unlock(&dreq->lock);
}
asmlinkage long sys_vhangup(void)
{
if (capable(CAP_SYS_TTY_CONFIG)) {
+ /* XXX: this needs locking */
tty_vhangup(current->signal->tty);
return 0;
}
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);
pgid = vx_info_map_pid(task->vx_info, pgid);
read_unlock(&tasklist_lock);
+ mutex_unlock(&tty_mutex);
if (!whole || num_threads<2) {
wchan = 0;
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.
*/
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) {
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) {
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 = {
.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;
if (spd.nr_pages <= 0)
return spd.nr_pages;
+ pipe = file->f_dentry->d_inode->i_pipe;
return splice_to_pipe(pipe, &spd);
}
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.
{
#ifdef CONFIG_UTRACE
if (current->utrace_flags & UTRACE_ACTION_QUIESCE)
- utrace_quiescent(current);
+ utrace_quiescent(current, NULL);
#endif
}
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;
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;
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
/*
* 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 *);
"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;
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);
u64 elapsed;
u64 run_time;
struct timespec uptime;
+ struct tty_struct *tty;
/*
* First check to see if there is enough free_space to continue
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(¤t->sighand->siglock);
ac.ac_utime = encode_comp_t(jiffies_to_AHZ(cputime_to_jiffies(pacct->ac_utime)));
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"
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=");
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);
}
#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
pid_t session;
int err = -EPERM;
- mutex_lock(&tty_mutex);
write_lock_irq(&tasklist_lock);
/* Fail if I am already a session leader */
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;
}
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);
}
}
/*
- * 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;
}
rcu_read_unlock();
return engine;
}
+ rcu_read_unlock();
engine = kmem_cache_alloc(utrace_engine_cachep, SLAB_KERNEL);
if (unlikely(engine == NULL))
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);
kmem_cache_free(utrace_engine_cachep, engine);
goto restart;
}
+ rcu_read_unlock();
+
list_add_tail_rcu(&engine->entry, &utrace->engines);
}
};
-/*
- * 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.
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;
}
}
call_rcu(&engine->rhead, utrace_engine_free);
}
- utrace_unlock(utrace);
rcu_utrace_free(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);
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;
}
/*
}
+/*
+ * 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;
* 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
* 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,
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
* 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;
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);
}
/*
tracehook_enable_syscall_trace(tsk);
else
tracehook_disable_syscall_trace(tsk);
+
+ return 0;
}
}
/*
- * 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
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
utrace_unlock(utrace);
}
-
- check_noreap(tsk, utrace, oaction, action);
}
}
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)
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)
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.
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;
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.
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)
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;
{
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);
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. */