diff options
author | Ralf Baechle <ralf@linux-mips.org> | 2000-06-19 22:45:37 +0000 |
---|---|---|
committer | Ralf Baechle <ralf@linux-mips.org> | 2000-06-19 22:45:37 +0000 |
commit | 6d403070f28cd44860fdb3a53be5da0275c65cf4 (patch) | |
tree | 0d0e7fe7b5fb7568d19e11d7d862b77a866ce081 /kernel | |
parent | ecf1bf5f6c2e668d03b0a9fb026db7aa41e292e1 (diff) |
Merge with 2.4.0-test1-ac21 + pile of MIPS cleanups to make merging
possible. Chainsawed RM200 kernel to compile again. Jazz machine
status unknown.
Diffstat (limited to 'kernel')
-rw-r--r-- | kernel/Makefile | 4 | ||||
-rw-r--r-- | kernel/acct.c | 12 | ||||
-rw-r--r-- | kernel/capability.c | 4 | ||||
-rw-r--r-- | kernel/dma.c | 3 | ||||
-rw-r--r-- | kernel/exec_domain.c | 49 | ||||
-rw-r--r-- | kernel/exit.c | 6 | ||||
-rw-r--r-- | kernel/fork.c | 7 | ||||
-rw-r--r-- | kernel/kmod.c | 3 | ||||
-rw-r--r-- | kernel/ksyms.c | 16 | ||||
-rw-r--r-- | kernel/module.c | 25 | ||||
-rw-r--r-- | kernel/panic.c | 1 | ||||
-rw-r--r-- | kernel/sched.c | 38 | ||||
-rw-r--r-- | kernel/signal.c | 8 | ||||
-rw-r--r-- | kernel/sys.c | 120 | ||||
-rw-r--r-- | kernel/sysctl.c | 9 | ||||
-rw-r--r-- | kernel/timer.c | 12 |
16 files changed, 244 insertions, 73 deletions
diff --git a/kernel/Makefile b/kernel/Makefile index 2a4f548af..53606a359 100644 --- a/kernel/Makefile +++ b/kernel/Makefile @@ -8,11 +8,11 @@ # Note 2! The CFLAGS definitions are now in the main makefile... O_TARGET := kernel.o -O_OBJS = sched.o dma.o fork.o exec_domain.o panic.o printk.o sys.o \ +O_OBJS = sched.o dma.o fork.o exec_domain.o panic.o printk.o \ module.o exit.o itimer.o info.o time.o softirq.o resource.o \ sysctl.o acct.o capability.o ptrace.o timer.o -OX_OBJS += signal.o +OX_OBJS += signal.o sys.o ifeq ($(CONFIG_UID16),y) O_OBJS += uid16.o diff --git a/kernel/acct.c b/kernel/acct.c index cef9aca85..eeab054d0 100644 --- a/kernel/acct.c +++ b/kernel/acct.c @@ -37,6 +37,10 @@ * one race (and leak) in BSD implementation. * OK, that's better. ANOTHER race and leak in BSD variant. There always * is one more bug... 10/11/98, AV. + * + * Oh, fsck... Oopsable SMP race in do_process_acct() - we must hold + * ->mmap_sem to walk the vma list of current->mm. Nasty, since it leaks + * a struct file opened for write. Fixed. 2/6/2000, AV. */ #include <linux/config.h> @@ -66,7 +70,6 @@ int acct_parm[3] = {4, 2, 30}; /* * External references and all of the globals. */ -void acct_timeout(unsigned long); static volatile int acct_active; static volatile int acct_needcheck; @@ -77,7 +80,7 @@ static int do_acct_process(long, struct file *); /* * Called whenever the timer says to check the free space. */ -void acct_timeout(unsigned long unused) +static void acct_timeout(unsigned long unused) { acct_needcheck = 1; } @@ -303,11 +306,14 @@ static int do_acct_process(long exitcode, struct file *file) vsize = 0; if (current->mm) { - struct vm_area_struct *vma = current->mm->mmap; + struct vm_area_struct *vma; + down(¤t->mm->mmap_sem); + vma = current->mm->mmap; while (vma) { vsize += vma->vm_end - vma->vm_start; vma = vma->vm_next; } + up(¤t->mm->mmap_sem); } vsize = vsize / 1024; ac.ac_mem = encode_comp_t(vsize); diff --git a/kernel/capability.c b/kernel/capability.c index 7c5f6df21..7aaf1a423 100644 --- a/kernel/capability.c +++ b/kernel/capability.c @@ -8,6 +8,8 @@ #include <linux/mm.h> #include <asm/uaccess.h> +kernel_cap_t cap_bset = CAP_INIT_EFF_SET; + /* Note: never hold tasklist_lock while spinning for this one */ spinlock_t task_capability_lock = SPIN_LOCK_UNLOCKED; @@ -17,8 +19,6 @@ spinlock_t task_capability_lock = SPIN_LOCK_UNLOCKED; * uninteresting and/or not to be changed. */ -kernel_cap_t cap_bset = CAP_FULL_SET; - asmlinkage long sys_capget(cap_user_header_t header, cap_user_data_t dataptr) { int error, pid; diff --git a/kernel/dma.c b/kernel/dma.c index 983dedb60..73b51a72b 100644 --- a/kernel/dma.c +++ b/kernel/dma.c @@ -115,9 +115,8 @@ int request_dma(unsigned int dmanr, const char *device_id) return -EINVAL; } -int free_dma(unsigned int dmanr) +void free_dma(unsigned int dmanr) { - return -EINVAL; } int get_dma_list(char *buf) diff --git a/kernel/exec_domain.c b/kernel/exec_domain.c index 3f3b5fc16..1daf64cc1 100644 --- a/kernel/exec_domain.c +++ b/kernel/exec_domain.c @@ -104,32 +104,37 @@ int unregister_exec_domain(struct exec_domain *it) void __set_personality(unsigned long personality) { - struct exec_domain *it; + struct exec_domain *it, *prev; it = lookup_exec_domain(personality); - if (it) { - if (atomic_read(¤t->fs->count) != 1) { - struct fs_struct *new = copy_fs_struct(current->fs); - struct fs_struct *old; - if (!new) { - put_exec_domain(it); - return; - } - task_lock(current); - old = current->fs; - current->fs = new; - task_unlock(current); - put_fs_struct(old); - } - /* - * At that point we are guaranteed to be the sole owner of - * current->fs. - */ + if (it == current->exec_domain) { current->personality = personality; - current->exec_domain = it; - set_fs_altroot(); - put_exec_domain(current->exec_domain); + return; + } + if (!it) + return; + if (atomic_read(¤t->fs->count) != 1) { + struct fs_struct *new = copy_fs_struct(current->fs); + struct fs_struct *old; + if (!new) { + put_exec_domain(it); + return; + } + task_lock(current); + old = current->fs; + current->fs = new; + task_unlock(current); + put_fs_struct(old); } + /* + * At that point we are guaranteed to be the sole owner of + * current->fs. + */ + current->personality = personality; + prev = current->exec_domain; + current->exec_domain = it; + set_fs_altroot(); + put_exec_domain(prev); } asmlinkage long sys_personality(unsigned long personality) diff --git a/kernel/exit.c b/kernel/exit.c index 8617b9d36..3bd501cf1 100644 --- a/kernel/exit.c +++ b/kernel/exit.c @@ -391,7 +391,7 @@ static void exit_notify(void) p = current->p_cptr; current->p_cptr = p->p_osptr; p->p_ysptr = NULL; - p->flags &= ~(PF_PTRACED|PF_TRACESYS); + p->ptrace = 0; p->p_pptr = p->p_opptr; p->p_osptr = p->p_pptr->p_cptr; @@ -432,6 +432,8 @@ NORET_TYPE void do_exit(long code) printk("Aiee, killing interrupt handler\n"); if (!tsk->pid) panic("Attempted to kill the idle task!"); + if (tsk->pid == 1) + panic("Attempted to kill init!"); tsk->flags |= PF_EXITING; del_timer_sync(&tsk->real_timer); @@ -512,7 +514,7 @@ repeat: case TASK_STOPPED: if (!p->exit_code) continue; - if (!(options & WUNTRACED) && !(p->flags & PF_PTRACED)) + if (!(options & WUNTRACED) && !(p->ptrace&PT_PTRACED)) continue; read_unlock(&tasklist_lock); retval = ru ? getrusage(p, RUSAGE_BOTH, ru) : 0; diff --git a/kernel/fork.c b/kernel/fork.c index 4300d242d..07bc503ac 100644 --- a/kernel/fork.c +++ b/kernel/fork.c @@ -601,8 +601,9 @@ static inline void copy_flags(unsigned long clone_flags, struct task_struct *p) new_flags &= ~(PF_SUPERPRIV | PF_USEDFPU | PF_VFORK); new_flags |= PF_FORKNOEXEC; - if (!(clone_flags & CLONE_PTRACE)) - new_flags &= ~(PF_PTRACED|PF_TRACESYS); + if (!(clone_flags & CLONE_PTRACE)) { + p->ptrace = 0; + } if (clone_flags & CLONE_VFORK) new_flags |= PF_VFORK; p->flags = new_flags; @@ -674,7 +675,7 @@ int do_fork(unsigned long clone_flags, unsigned long usp, struct pt_regs *regs) if ((clone_flags & CLONE_VFORK) || !(clone_flags & CLONE_PARENT)) { p->p_opptr = current; - if (!(p->flags & PF_PTRACED)) + if (!(p->ptrace&PT_PTRACED)) p->p_pptr = current; } p->p_cptr = NULL; diff --git a/kernel/kmod.c b/kernel/kmod.c index bbfaf2992..5e8d825a4 100644 --- a/kernel/kmod.c +++ b/kernel/kmod.c @@ -95,9 +95,8 @@ int exec_usermodehelper(char *program_path, char *argv[], char *envp[]) /* Drop the "current user" thing */ free_uid(current); - /* Give kmod all privileges.. */ + /* Give kmod all effective privileges.. */ current->uid = current->euid = current->fsuid = 0; - cap_set_full(current->cap_inheritable); cap_set_full(current->cap_effective); /* Allow execve args to be in kernel space. */ diff --git a/kernel/ksyms.c b/kernel/ksyms.c index 62426b761..a885a0c7f 100644 --- a/kernel/ksyms.c +++ b/kernel/ksyms.c @@ -44,6 +44,7 @@ #include <linux/capability.h> #include <linux/highuid.h> #include <linux/brlock.h> +#include <linux/fs.h> #if defined(CONFIG_PROC_FS) #include <linux/proc_fs.h> @@ -80,10 +81,9 @@ EXPORT_SYMBOL(exec_usermodehelper); #ifdef CONFIG_MODULES EXPORT_SYMBOL(get_module_symbol); +EXPORT_SYMBOL(put_module_symbol); EXPORT_SYMBOL(try_inc_mod_count); #endif -EXPORT_SYMBOL(get_option); -EXPORT_SYMBOL(get_options); /* process memory management */ EXPORT_SYMBOL(do_mmap_pgoff); @@ -129,7 +129,6 @@ EXPORT_SYMBOL(highmem_start_page); /* filesystem internal functions */ EXPORT_SYMBOL(def_blk_fops); -EXPORT_SYMBOL(in_group_p); EXPORT_SYMBOL(update_atime); EXPORT_SYMBOL(get_super); EXPORT_SYMBOL(get_empty_super); @@ -139,6 +138,7 @@ EXPORT_SYMBOL(igrab); EXPORT_SYMBOL(iunique); EXPORT_SYMBOL(iget4); EXPORT_SYMBOL(iput); +EXPORT_SYMBOL(force_delete); EXPORT_SYMBOL(follow_up); EXPORT_SYMBOL(follow_down); EXPORT_SYMBOL(path_init); @@ -172,6 +172,8 @@ EXPORT_SYMBOL(__invalidate_buffers); EXPORT_SYMBOL(invalidate_inodes); EXPORT_SYMBOL(invalidate_inode_pages); EXPORT_SYMBOL(truncate_inode_pages); +EXPORT_SYMBOL(fsync_inode_buffers); +EXPORT_SYMBOL(buffer_insert_inode_queue); EXPORT_SYMBOL(fsync_dev); EXPORT_SYMBOL(permission); EXPORT_SYMBOL(inode_setattr); @@ -205,7 +207,7 @@ EXPORT_SYMBOL(generic_ro_fops); EXPORT_SYMBOL(generic_buffer_fdatasync); EXPORT_SYMBOL(page_hash_bits); EXPORT_SYMBOL(page_hash_table); -EXPORT_SYMBOL(file_lock_table); +EXPORT_SYMBOL(file_lock_list); EXPORT_SYMBOL(posix_lock_file); EXPORT_SYMBOL(posix_test_lock); EXPORT_SYMBOL(posix_block_lock); @@ -294,6 +296,8 @@ EXPORT_SYMBOL(refile_buffer); EXPORT_SYMBOL(max_sectors); EXPORT_SYMBOL(max_readahead); EXPORT_SYMBOL(file_moveto); +EXPORT_SYMBOL(drive_stat_acct); +EXPORT_SYMBOL(set_bh_page); /* tty routines */ EXPORT_SYMBOL(tty_hangup); @@ -446,8 +450,6 @@ EXPORT_SYMBOL(sys_call_table); EXPORT_SYMBOL(machine_restart); EXPORT_SYMBOL(machine_halt); EXPORT_SYMBOL(machine_power_off); -EXPORT_SYMBOL(register_reboot_notifier); -EXPORT_SYMBOL(unregister_reboot_notifier); EXPORT_SYMBOL(_ctype); EXPORT_SYMBOL(secure_tcp_sequence_number); EXPORT_SYMBOL(get_random_bytes); @@ -497,6 +499,7 @@ EXPORT_SYMBOL(fs_overflowgid); /* all busmice */ EXPORT_SYMBOL(fasync_helper); +EXPORT_SYMBOL(kill_fasync); #ifdef CONFIG_BLK_DEV_MD EXPORT_SYMBOL(disk_name); /* for md.c */ @@ -504,7 +507,6 @@ EXPORT_SYMBOL(disk_name); /* for md.c */ /* binfmt_aout */ EXPORT_SYMBOL(get_write_access); -EXPORT_SYMBOL(put_write_access); /* dynamic registering of consoles */ EXPORT_SYMBOL(register_console); diff --git a/kernel/module.c b/kernel/module.c index 6e3534a15..c0c5c9053 100644 --- a/kernel/module.c +++ b/kernel/module.c @@ -973,7 +973,9 @@ leave_the_loop: * Gets the address for a symbol in the given module. If modname is * NULL, it looks for the name in any registered symbol table. If the * modname is an empty string, it looks for the symbol in kernel exported - * symbol tables. + * symbol tables. Increase the usage count of the module in which the + * symbol was found - it's the only way we can guarantee that it's still + * there by the time our caller actually uses it. */ unsigned long get_module_symbol(char *modname, char *symname) @@ -982,6 +984,7 @@ get_module_symbol(char *modname, char *symname) struct module_symbol *sym; int i; + spin_lock(&unload_lock); for (mp = module_list; mp; mp = mp->next) { if (((modname == NULL) || (strcmp(mp->name, modname) == 0)) && MOD_CAN_QUERY(mp) && @@ -990,14 +993,34 @@ get_module_symbol(char *modname, char *symname) i > 0; --i, ++sym) { if (strcmp(sym->name, symname) == 0) { + __MOD_INC_USE_COUNT(mp); + spin_unlock(&unload_lock); return sym->value; } } } } + spin_unlock(&unload_lock); return 0; } +/* Decrease the use count of the module containing a symbol with the + * address passed. + */ +void put_module_symbol(unsigned long addr) +{ + struct module *mp; + + for (mp = module_list; mp; mp = mp->next) { + if (MOD_CAN_QUERY(mp) && + addr >= (unsigned long)mp && + addr < (unsigned long)mp + mp->size) { + __MOD_DEC_USE_COUNT(mp); + return; + } + } +} + #else /* CONFIG_MODULES */ /* Dummy syscalls for people who don't want modules */ diff --git a/kernel/panic.c b/kernel/panic.c index 8ea4fd0b6..d6e37fbf7 100644 --- a/kernel/panic.c +++ b/kernel/panic.c @@ -19,7 +19,6 @@ asmlinkage void sys_sync(void); /* it's really int */ extern void unblank_console(void); -extern int C_A_D; int panic_timeout; diff --git a/kernel/sched.c b/kernel/sched.c index c42402e95..b8d389ef8 100644 --- a/kernel/sched.c +++ b/kernel/sched.c @@ -337,16 +337,23 @@ out: spin_unlock_irqrestore(&runqueue_lock, flags); } +struct foo_struct { + struct task_struct *process; + struct timer_list timer; +}; + static void process_timeout(unsigned long __data) { - struct task_struct * p = (struct task_struct *) __data; + struct foo_struct * foo = (struct foo_struct *) __data; - wake_up_process(p); + wake_up_process(foo->process); + + timer_exit(&foo->timer); } signed long schedule_timeout(signed long timeout) { - struct timer_list timer; + struct foo_struct foo; unsigned long expire; switch (timeout) @@ -381,14 +388,16 @@ signed long schedule_timeout(signed long timeout) expire = timeout + jiffies; - init_timer(&timer); - timer.expires = expire; - timer.data = (unsigned long) current; - timer.function = process_timeout; + init_timer(&foo.timer); + foo.timer.expires = expire; + foo.timer.data = (unsigned long) &foo; + foo.timer.function = process_timeout; - add_timer(&timer); + foo.process = current; + + add_timer(&foo.timer); schedule(); - del_timer(&timer); + del_timer_sync(&foo.timer); /* RED-PEN. Timer may be running now on another cpu. * Pray that process will not exit enough fastly. */ @@ -920,16 +929,11 @@ asmlinkage long sys_sched_getscheduler(pid_t pid) if (pid < 0) goto out_nounlock; - read_lock(&tasklist_lock); - retval = -ESRCH; + read_lock(&tasklist_lock); p = find_process_by_pid(pid); - if (!p) - goto out_unlock; - - retval = p->policy; - -out_unlock: + if (p) + retval = p->policy & ~SCHED_YIELD; read_unlock(&tasklist_lock); out_nounlock: diff --git a/kernel/signal.c b/kernel/signal.c index 3708a1b89..ad1b942ac 100644 --- a/kernel/signal.c +++ b/kernel/signal.c @@ -248,7 +248,7 @@ static int ignored_signal(int sig, struct task_struct *t) struct k_sigaction *ka; /* Don't ignore traced or blocked signals */ - if ((t->flags & PF_PTRACED) || sigismember(&t->blocked, sig)) + if ((t->ptrace & PT_PTRACED) || sigismember(&t->blocked, sig)) return 0; signals = t->sig; @@ -376,7 +376,7 @@ printk("SIG queue (%s:%d): %d ", t->comm, t->pid, sig); break; } } else if (sig >= SIGRTMIN && info && (unsigned long)info != 1 - && info->si_code < 0) { + && info->si_code != SI_USER) { /* * Queue overflow, abort. We may abort if the signal was rt * and sent by user using something other than kill(). @@ -626,7 +626,7 @@ notify_parent(struct task_struct *tsk, int sig) break; case TASK_STOPPED: /* FIXME -- can we deduce CLD_TRAPPED or CLD_CONTINUED? */ - if (tsk->flags & PF_PTRACED) + if (tsk->ptrace & PT_PTRACED) why = CLD_TRAPPED; else why = CLD_STOPPED; @@ -1110,7 +1110,7 @@ sys_ssetmask(int newmask) } #endif /* !defined(__alpha__) */ -#if !defined(__alpha__) && !defined(__mips__) +#if !defined(__alpha__) && !defined(__ia64__) && !defined(__mips__) /* * For backwards compatibility. Functionality superseded by sigaction. */ diff --git a/kernel/sys.c b/kernel/sys.c index 0c78f80b4..8bd07d55f 100644 --- a/kernel/sys.c +++ b/kernel/sys.c @@ -4,6 +4,7 @@ * Copyright (C) 1991, 1992 Linus Torvalds */ +#include <linux/module.h> #include <linux/mm.h> #include <linux/utsname.h> #include <linux/mman.h> @@ -46,13 +47,123 @@ int C_A_D = 1; * and the like. */ -struct notifier_block *reboot_notifier_list = NULL; +static struct notifier_block *reboot_notifier_list = NULL; +rwlock_t notifier_lock = RW_LOCK_UNLOCKED; +/** + * notifier_chain_register - Add notifier to a notifier chain + * @list: Pointer to root list pointer + * @n: New entry in notifier chain + * + * Adds a notifier to a notifier chain. + * + * Currently always returns zero. + */ + +int notifier_chain_register(struct notifier_block **list, struct notifier_block *n) +{ + write_lock(¬ifier_lock); + while(*list) + { + if(n->priority > (*list)->priority) + break; + list= &((*list)->next); + } + n->next = *list; + *list=n; + write_unlock(¬ifier_lock); + return 0; +} + +/** + * notifier_chain_unregister - Remove notifier from a notifier chain + * @nl: Pointer to root list pointer + * @n: New entry in notifier chain + * + * Removes a notifier from a notifier chain. + * + * Returns zero on success, or %-ENOENT on failure. + */ + +int notifier_chain_unregister(struct notifier_block **nl, struct notifier_block *n) +{ + write_lock(¬ifier_lock); + while((*nl)!=NULL) + { + if((*nl)==n) + { + *nl=n->next; + write_unlock(¬ifier_lock); + return 0; + } + nl=&((*nl)->next); + } + write_unlock(¬ifier_lock); + return -ENOENT; +} + +/** + * notifier_call_chain - Call functions in a notifier chain + * @n: Pointer to root pointer of notifier chain + * @val: Value passed unmodified to notifier function + * @v: Pointer passed unmodified to notifier function + * + * Calls each function in a notifier chain in turn. + * + * If the return value of the notifier can be and'd + * with %NOTIFY_STOP_MASK, then notifier_call_chain + * will return immediately, with the return value of + * the notifier function which halted execution. + * Otherwise, the return value is the return value + * of the last notifier function called. + */ + +int notifier_call_chain(struct notifier_block **n, unsigned long val, void *v) +{ + int ret=NOTIFY_DONE; + struct notifier_block *nb = *n; + + read_lock(¬ifier_lock); + while(nb) + { + ret=nb->notifier_call(nb,val,v); + if(ret&NOTIFY_STOP_MASK) + { + read_unlock(¬ifier_lock); + return ret; + } + nb=nb->next; + } + read_unlock(¬ifier_lock); + return ret; +} + +/** + * register_reboot_notifier - Register function to be called at reboot time + * @nb: Info about notifier function to be called + * + * Registers a function with the list of functions + * to be called at reboot time. + * + * Currently always returns zero, as notifier_chain_register + * always returns zero. + */ + int register_reboot_notifier(struct notifier_block * nb) { return notifier_chain_register(&reboot_notifier_list, nb); } +/** + * unregister_reboot_notifier - Unregister previously registered reboot notifier + * @nb: Hook to be unregistered + * + * Unregisters a previously registered reboot + * notifier function. + * + * Returns zero on success, or %-ENOENT on failure. + */ + int unregister_reboot_notifier(struct notifier_block * nb) { return notifier_chain_unregister(&reboot_notifier_list, nb); @@ -1109,3 +1220,10 @@ asmlinkage long sys_prctl(int option, unsigned long arg2, unsigned long arg3, return error; } +EXPORT_SYMBOL(notifier_chain_register); +EXPORT_SYMBOL(notifier_chain_unregister); +EXPORT_SYMBOL(notifier_call_chain); +EXPORT_SYMBOL(register_reboot_notifier); +EXPORT_SYMBOL(unregister_reboot_notifier); +EXPORT_SYMBOL(in_group_p); +EXPORT_SYMBOL(in_egroup_p); diff --git a/kernel/sysctl.c b/kernel/sysctl.c index 4dd683997..ab62787d1 100644 --- a/kernel/sysctl.c +++ b/kernel/sysctl.c @@ -255,9 +255,9 @@ static ctl_table fs_table[] = { 0444, NULL, &proc_dointvec}, {FS_STATINODE, "inode-state", &inodes_stat, 7*sizeof(int), 0444, NULL, &proc_dointvec}, - {FS_NRFILE, "file-nr", &nr_files, 3*sizeof(int), + {FS_NRFILE, "file-nr", &files_stat, 3*sizeof(int), 0444, NULL, &proc_dointvec}, - {FS_MAXFILE, "file-max", &max_files, sizeof(int), + {FS_MAXFILE, "file-max", &files_stat.max_files, sizeof(int), 0644, NULL, &proc_dointvec}, {FS_NRSUPER, "super-nr", &nr_super_blocks, sizeof(int), 0444, NULL, &proc_dointvec}, @@ -803,8 +803,11 @@ int proc_dointvec(ctl_table *table, int write, struct file *filp, int proc_dointvec_bset(ctl_table *table, int write, struct file *filp, void *buffer, size_t *lenp) { + if (!capable(CAP_SYS_MODULE)) { + return -EPERM; + } return do_proc_dointvec(table,write,filp,buffer,lenp,1, - (current->pid == 1) ? OP_SET : OP_AND); + (current->pid == 1) ? OP_SET : OP_AND); } int proc_dointvec_minmax(ctl_table *table, int write, struct file *filp, diff --git a/kernel/timer.c b/kernel/timer.c index 9fa35a63b..5457c450b 100644 --- a/kernel/timer.c +++ b/kernel/timer.c @@ -238,7 +238,17 @@ int del_timer_sync(struct timer_list * timer) if (!running) return ret; - timer_synchronize(timer); + + { + int count = 50*1000*1000; + while (timer_is_running(timer) && --count) + ; + if (count == 0) { + printk( "del_timer_sync(%p): deadlock! Called from %p\n", + timer, __builtin_return_address(0)); + printk("See http://www.uow.edu.au/~andrewm/linux/deadlock.html\n"); + } + } } return ret; |