diff options
Diffstat (limited to 'kernel')
| -rw-r--r-- | kernel/cgroup.c | 34 | ||||
| -rw-r--r-- | kernel/compat.c | 5 | ||||
| -rw-r--r-- | kernel/cpu.c | 6 | ||||
| -rw-r--r-- | kernel/cpuset.c | 34 | ||||
| -rw-r--r-- | kernel/dma-coherent.c | 42 | ||||
| -rw-r--r-- | kernel/exit.c | 21 | ||||
| -rw-r--r-- | kernel/fork.c | 17 | ||||
| -rw-r--r-- | kernel/futex.c | 72 | ||||
| -rw-r--r-- | kernel/kmod.c | 4 | ||||
| -rw-r--r-- | kernel/kprobes.c | 281 | ||||
| -rw-r--r-- | kernel/ksysfs.c | 4 | ||||
| -rw-r--r-- | kernel/module.c | 92 | ||||
| -rw-r--r-- | kernel/panic.c | 2 | ||||
| -rw-r--r-- | kernel/power/main.c | 6 | ||||
| -rw-r--r-- | kernel/profile.c | 1 | ||||
| -rw-r--r-- | kernel/rcupdate.c | 11 | ||||
| -rw-r--r-- | kernel/rcupreempt.c | 11 | ||||
| -rw-r--r-- | kernel/rcutorture.c | 18 | ||||
| -rw-r--r-- | kernel/rcutree.c | 13 | ||||
| -rw-r--r-- | kernel/signal.c | 3 | ||||
| -rw-r--r-- | kernel/stop_machine.c | 55 | ||||
| -rw-r--r-- | kernel/sys.c | 2 | ||||
| -rw-r--r-- | kernel/sysctl.c | 27 | ||||
| -rw-r--r-- | kernel/test_kprobes.c | 210 | ||||
| -rw-r--r-- | kernel/time.c | 4 | ||||
| -rw-r--r-- | kernel/tsacct.c | 4 | 
26 files changed, 676 insertions, 303 deletions
| diff --git a/kernel/cgroup.c b/kernel/cgroup.c index 891a84eb9d3..f221446aa02 100644 --- a/kernel/cgroup.c +++ b/kernel/cgroup.c @@ -116,7 +116,6 @@ static int root_count;   * be called.   */  static int need_forkexit_callback __read_mostly; -static int need_mm_owner_callback __read_mostly;  /* convenient tests for these bits */  inline int cgroup_is_removed(const struct cgroup *cgrp) @@ -573,7 +572,6 @@ static struct inode *cgroup_new_inode(mode_t mode, struct super_block *sb)  		inode->i_mode = mode;  		inode->i_uid = current_fsuid();  		inode->i_gid = current_fsgid(); -		inode->i_blocks = 0;  		inode->i_atime = inode->i_mtime = inode->i_ctime = CURRENT_TIME;  		inode->i_mapping->backing_dev_info = &cgroup_backing_dev_info;  	} @@ -2540,7 +2538,6 @@ static void __init cgroup_init_subsys(struct cgroup_subsys *ss)  	init_css_set.subsys[ss->subsys_id] = dummytop->subsys[ss->subsys_id];  	need_forkexit_callback |= ss->fork || ss->exit; -	need_mm_owner_callback |= !!ss->mm_owner_changed;  	/* At system boot, before all subsystems have been  	 * registered, no tasks have been forked, so we don't @@ -2790,37 +2787,6 @@ void cgroup_fork_callbacks(struct task_struct *child)  	}  } -#ifdef CONFIG_MM_OWNER -/** - * cgroup_mm_owner_callbacks - run callbacks when the mm->owner changes - * @p: the new owner - * - * Called on every change to mm->owner. mm_init_owner() does not - * invoke this routine, since it assigns the mm->owner the first time - * and does not change it. - * - * The callbacks are invoked with mmap_sem held in read mode. - */ -void cgroup_mm_owner_callbacks(struct task_struct *old, struct task_struct *new) -{ -	struct cgroup *oldcgrp, *newcgrp = NULL; - -	if (need_mm_owner_callback) { -		int i; -		for (i = 0; i < CGROUP_SUBSYS_COUNT; i++) { -			struct cgroup_subsys *ss = subsys[i]; -			oldcgrp = task_cgroup(old, ss->subsys_id); -			if (new) -				newcgrp = task_cgroup(new, ss->subsys_id); -			if (oldcgrp == newcgrp) -				continue; -			if (ss->mm_owner_changed) -				ss->mm_owner_changed(ss, oldcgrp, newcgrp, new); -		} -	} -} -#endif /* CONFIG_MM_OWNER */ -  /**   * cgroup_post_fork - called on a new task after adding it to the task list   * @child: the task in question diff --git a/kernel/compat.c b/kernel/compat.c index d52e2ec1deb..42d56544460 100644 --- a/kernel/compat.c +++ b/kernel/compat.c @@ -24,6 +24,7 @@  #include <linux/migrate.h>  #include <linux/posix-timers.h>  #include <linux/times.h> +#include <linux/ptrace.h>  #include <asm/uaccess.h> @@ -229,6 +230,7 @@ asmlinkage long compat_sys_times(struct compat_tms __user *tbuf)  		if (copy_to_user(tbuf, &tmp, sizeof(tmp)))  			return -EFAULT;  	} +	force_successful_syscall_return();  	return compat_jiffies_to_clock_t(jiffies);  } @@ -894,8 +896,9 @@ asmlinkage long compat_sys_time(compat_time_t __user * tloc)  	if (tloc) {  		if (put_user(i,tloc)) -			i = -EFAULT; +			return -EFAULT;  	} +	force_successful_syscall_return();  	return i;  } diff --git a/kernel/cpu.c b/kernel/cpu.c index 47fff3b63cb..30e74dd6d01 100644 --- a/kernel/cpu.c +++ b/kernel/cpu.c @@ -269,8 +269,11 @@ out_release:  int __ref cpu_down(unsigned int cpu)  { -	int err = 0; +	int err; +	err = stop_machine_create(); +	if (err) +		return err;  	cpu_maps_update_begin();  	if (cpu_hotplug_disabled) { @@ -297,6 +300,7 @@ int __ref cpu_down(unsigned int cpu)  out:  	cpu_maps_update_done(); +	stop_machine_destroy();  	return err;  }  EXPORT_SYMBOL(cpu_down); diff --git a/kernel/cpuset.c b/kernel/cpuset.c index 39c1a4c1c5a..345ace5117d 100644 --- a/kernel/cpuset.c +++ b/kernel/cpuset.c @@ -240,6 +240,17 @@ static struct cpuset top_cpuset = {  static DEFINE_MUTEX(callback_mutex);  /* + * cpuset_buffer_lock protects both the cpuset_name and cpuset_nodelist + * buffers.  They are statically allocated to prevent using excess stack + * when calling cpuset_print_task_mems_allowed(). + */ +#define CPUSET_NAME_LEN		(128) +#define	CPUSET_NODELIST_LEN	(256) +static char cpuset_name[CPUSET_NAME_LEN]; +static char cpuset_nodelist[CPUSET_NODELIST_LEN]; +static DEFINE_SPINLOCK(cpuset_buffer_lock); + +/*   * This is ugly, but preserves the userspace API for existing cpuset   * users. If someone tries to mount the "cpuset" filesystem, we   * silently switch it to mount "cgroup" instead @@ -2356,6 +2367,29 @@ int cpuset_mems_allowed_intersects(const struct task_struct *tsk1,  	return nodes_intersects(tsk1->mems_allowed, tsk2->mems_allowed);  } +/** + * cpuset_print_task_mems_allowed - prints task's cpuset and mems_allowed + * @task: pointer to task_struct of some task. + * + * Description: Prints @task's name, cpuset name, and cached copy of its + * mems_allowed to the kernel log.  Must hold task_lock(task) to allow + * dereferencing task_cs(task). + */ +void cpuset_print_task_mems_allowed(struct task_struct *tsk) +{ +	struct dentry *dentry; + +	dentry = task_cs(tsk)->css.cgroup->dentry; +	spin_lock(&cpuset_buffer_lock); +	snprintf(cpuset_name, CPUSET_NAME_LEN, +		 dentry ? (const char *)dentry->d_name.name : "/"); +	nodelist_scnprintf(cpuset_nodelist, CPUSET_NODELIST_LEN, +			   tsk->mems_allowed); +	printk(KERN_INFO "%s cpuset=%s mems_allowed=%s\n", +	       tsk->comm, cpuset_name, cpuset_nodelist); +	spin_unlock(&cpuset_buffer_lock); +} +  /*   * Collection of memory_pressure is suppressed unless   * this flag is enabled by writing "1" to the special diff --git a/kernel/dma-coherent.c b/kernel/dma-coherent.c index f013a0c2e11..038707404b7 100644 --- a/kernel/dma-coherent.c +++ b/kernel/dma-coherent.c @@ -109,20 +109,40 @@ EXPORT_SYMBOL(dma_mark_declared_memory_occupied);  int dma_alloc_from_coherent(struct device *dev, ssize_t size,  				       dma_addr_t *dma_handle, void **ret)  { -	struct dma_coherent_mem *mem = dev ? dev->dma_mem : NULL; +	struct dma_coherent_mem *mem;  	int order = get_order(size); +	int pageno; -	if (mem) { -		int page = bitmap_find_free_region(mem->bitmap, mem->size, -						     order); -		if (page >= 0) { -			*dma_handle = mem->device_base + (page << PAGE_SHIFT); -			*ret = mem->virt_base + (page << PAGE_SHIFT); -			memset(*ret, 0, size); -		} else if (mem->flags & DMA_MEMORY_EXCLUSIVE) -			*ret = NULL; +	if (!dev) +		return 0; +	mem = dev->dma_mem; +	if (!mem) +		return 0; +	if (unlikely(size > mem->size)) + 		return 0; + +	pageno = bitmap_find_free_region(mem->bitmap, mem->size, order); +	if (pageno >= 0) { +		/* +		 * Memory was found in the per-device arena. +		 */ +		*dma_handle = mem->device_base + (pageno << PAGE_SHIFT); +		*ret = mem->virt_base + (pageno << PAGE_SHIFT); +		memset(*ret, 0, size); +	} else if (mem->flags & DMA_MEMORY_EXCLUSIVE) { +		/* +		 * The per-device arena is exhausted and we are not +		 * permitted to fall back to generic memory. +		 */ +		*ret = NULL; +	} else { +		/* +		 * The per-device arena is exhausted and we are +		 * permitted to fall back to generic memory. +		 */ +		 return 0;  	} -	return (mem != NULL); +	return 1;  }  EXPORT_SYMBOL(dma_alloc_from_coherent); diff --git a/kernel/exit.c b/kernel/exit.c index c9e5a1c14e0..c7740fa3252 100644 --- a/kernel/exit.c +++ b/kernel/exit.c @@ -642,35 +642,31 @@ retry:  	/*  	 * We found no owner yet mm_users > 1: this implies that we are  	 * most likely racing with swapoff (try_to_unuse()) or /proc or -	 * ptrace or page migration (get_task_mm()).  Mark owner as NULL, -	 * so that subsystems can understand the callback and take action. +	 * ptrace or page migration (get_task_mm()).  Mark owner as NULL.  	 */ -	down_write(&mm->mmap_sem); -	cgroup_mm_owner_callbacks(mm->owner, NULL);  	mm->owner = NULL; -	up_write(&mm->mmap_sem);  	return;  assign_new_owner:  	BUG_ON(c == p);  	get_task_struct(c); -	read_unlock(&tasklist_lock); -	down_write(&mm->mmap_sem);  	/*  	 * The task_lock protects c->mm from changing.  	 * We always want mm->owner->mm == mm  	 */  	task_lock(c); +	/* +	 * Delay read_unlock() till we have the task_lock() +	 * to ensure that c does not slip away underneath us +	 */ +	read_unlock(&tasklist_lock);  	if (c->mm != mm) {  		task_unlock(c); -		up_write(&mm->mmap_sem);  		put_task_struct(c);  		goto retry;  	} -	cgroup_mm_owner_callbacks(mm->owner, c);  	mm->owner = c;  	task_unlock(c); -	up_write(&mm->mmap_sem);  	put_task_struct(c);  }  #endif /* CONFIG_MM_OWNER */ @@ -1055,10 +1051,7 @@ NORET_TYPE void do_exit(long code)  				preempt_count());  	acct_update_integrals(tsk); -	if (tsk->mm) { -		update_hiwater_rss(tsk->mm); -		update_hiwater_vm(tsk->mm); -	} +  	group_dead = atomic_dec_and_test(&tsk->signal->live);  	if (group_dead) {  		hrtimer_cancel(&tsk->signal->real_timer); diff --git a/kernel/fork.c b/kernel/fork.c index 43cbf30669e..7b8f2a78be3 100644 --- a/kernel/fork.c +++ b/kernel/fork.c @@ -400,6 +400,18 @@ __cacheline_aligned_in_smp DEFINE_SPINLOCK(mmlist_lock);  #define allocate_mm()	(kmem_cache_alloc(mm_cachep, GFP_KERNEL))  #define free_mm(mm)	(kmem_cache_free(mm_cachep, (mm))) +static unsigned long default_dump_filter = MMF_DUMP_FILTER_DEFAULT; + +static int __init coredump_filter_setup(char *s) +{ +	default_dump_filter = +		(simple_strtoul(s, NULL, 0) << MMF_DUMP_FILTER_SHIFT) & +		MMF_DUMP_FILTER_MASK; +	return 1; +} + +__setup("coredump_filter=", coredump_filter_setup); +  #include <linux/init_task.h>  static struct mm_struct * mm_init(struct mm_struct * mm, struct task_struct *p) @@ -408,8 +420,7 @@ static struct mm_struct * mm_init(struct mm_struct * mm, struct task_struct *p)  	atomic_set(&mm->mm_count, 1);  	init_rwsem(&mm->mmap_sem);  	INIT_LIST_HEAD(&mm->mmlist); -	mm->flags = (current->mm) ? current->mm->flags -				  : MMF_DUMP_FILTER_DEFAULT; +	mm->flags = (current->mm) ? current->mm->flags : default_dump_filter;  	mm->core_state = NULL;  	mm->nr_ptes = 0;  	set_mm_counter(mm, file_rss, 0); @@ -758,7 +769,7 @@ static int copy_sighand(unsigned long clone_flags, struct task_struct *tsk)  {  	struct sighand_struct *sig; -	if (clone_flags & (CLONE_SIGHAND | CLONE_THREAD)) { +	if (clone_flags & CLONE_SIGHAND) {  		atomic_inc(¤t->sighand->count);  		return 0;  	} diff --git a/kernel/futex.c b/kernel/futex.c index 7c6cbabe52b..002aa189eb0 100644 --- a/kernel/futex.c +++ b/kernel/futex.c @@ -170,8 +170,11 @@ static void get_futex_key_refs(union futex_key *key)   */  static void drop_futex_key_refs(union futex_key *key)  { -	if (!key->both.ptr) +	if (!key->both.ptr) { +		/* If we're here then we tried to put a key we failed to get */ +		WARN_ON_ONCE(1);  		return; +	}  	switch (key->both.offset & (FUT_OFF_INODE|FUT_OFF_MMSHARED)) {  	case FUT_OFF_INODE: @@ -730,8 +733,8 @@ static int futex_wake(u32 __user *uaddr, int fshared, int nr_wake, u32 bitset)  	}  	spin_unlock(&hb->lock); -out:  	put_futex_key(fshared, &key); +out:  	return ret;  } @@ -755,7 +758,7 @@ retryfull:  		goto out;  	ret = get_futex_key(uaddr2, fshared, &key2);  	if (unlikely(ret != 0)) -		goto out; +		goto out_put_key1;  	hb1 = hash_futex(&key1);  	hb2 = hash_futex(&key2); @@ -777,12 +780,12 @@ retry:  		 * but we might get them from range checking  		 */  		ret = op_ret; -		goto out; +		goto out_put_keys;  #endif  		if (unlikely(op_ret != -EFAULT)) {  			ret = op_ret; -			goto out; +			goto out_put_keys;  		}  		/* @@ -796,7 +799,7 @@ retry:  			ret = futex_handle_fault((unsigned long)uaddr2,  						 attempt);  			if (ret) -				goto out; +				goto out_put_keys;  			goto retry;  		} @@ -834,10 +837,11 @@ retry:  	spin_unlock(&hb1->lock);  	if (hb1 != hb2)  		spin_unlock(&hb2->lock); -out: +out_put_keys:  	put_futex_key(fshared, &key2); +out_put_key1:  	put_futex_key(fshared, &key1); - +out:  	return ret;  } @@ -854,13 +858,13 @@ static int futex_requeue(u32 __user *uaddr1, int fshared, u32 __user *uaddr2,  	struct futex_q *this, *next;  	int ret, drop_count = 0; - retry: +retry:  	ret = get_futex_key(uaddr1, fshared, &key1);  	if (unlikely(ret != 0))  		goto out;  	ret = get_futex_key(uaddr2, fshared, &key2);  	if (unlikely(ret != 0)) -		goto out; +		goto out_put_key1;  	hb1 = hash_futex(&key1);  	hb2 = hash_futex(&key2); @@ -882,7 +886,7 @@ static int futex_requeue(u32 __user *uaddr1, int fshared, u32 __user *uaddr2,  			if (!ret)  				goto retry; -			return ret; +			goto out_put_keys;  		}  		if (curval != *cmpval) {  			ret = -EAGAIN; @@ -927,9 +931,11 @@ out_unlock:  	while (--drop_count >= 0)  		drop_futex_key_refs(&key1); -out: +out_put_keys:  	put_futex_key(fshared, &key2); +out_put_key1:  	put_futex_key(fshared, &key1); +out:  	return ret;  } @@ -990,7 +996,7 @@ static int unqueue_me(struct futex_q *q)  	int ret = 0;  	/* In the common case we don't take the spinlock, which is nice. */ - retry: +retry:  	lock_ptr = q->lock_ptr;  	barrier();  	if (lock_ptr != NULL) { @@ -1172,11 +1178,11 @@ static int futex_wait(u32 __user *uaddr, int fshared,  	q.pi_state = NULL;  	q.bitset = bitset; - retry: +retry:  	q.key = FUTEX_KEY_INIT;  	ret = get_futex_key(uaddr, fshared, &q.key);  	if (unlikely(ret != 0)) -		goto out_release_sem; +		goto out;  	hb = queue_lock(&q); @@ -1204,6 +1210,7 @@ static int futex_wait(u32 __user *uaddr, int fshared,  	if (unlikely(ret)) {  		queue_unlock(&q, hb); +		put_futex_key(fshared, &q.key);  		ret = get_user(uval, uaddr); @@ -1213,7 +1220,7 @@ static int futex_wait(u32 __user *uaddr, int fshared,  	}  	ret = -EWOULDBLOCK;  	if (uval != val) -		goto out_unlock_release_sem; +		goto out_unlock_put_key;  	/* Only actually queue if *uaddr contained val.  */  	queue_me(&q, hb); @@ -1305,11 +1312,11 @@ static int futex_wait(u32 __user *uaddr, int fshared,  		return -ERESTART_RESTARTBLOCK;  	} - out_unlock_release_sem: +out_unlock_put_key:  	queue_unlock(&q, hb); - - out_release_sem:  	put_futex_key(fshared, &q.key); + +out:  	return ret;  } @@ -1358,16 +1365,16 @@ static int futex_lock_pi(u32 __user *uaddr, int fshared,  	}  	q.pi_state = NULL; - retry: +retry:  	q.key = FUTEX_KEY_INIT;  	ret = get_futex_key(uaddr, fshared, &q.key);  	if (unlikely(ret != 0)) -		goto out_release_sem; +		goto out; - retry_unlocked: +retry_unlocked:  	hb = queue_lock(&q); - retry_locked: +retry_locked:  	ret = lock_taken = 0;  	/* @@ -1388,14 +1395,14 @@ static int futex_lock_pi(u32 __user *uaddr, int fshared,  	 */  	if (unlikely((curval & FUTEX_TID_MASK) == task_pid_vnr(current))) {  		ret = -EDEADLK; -		goto out_unlock_release_sem; +		goto out_unlock_put_key;  	}  	/*  	 * Surprise - we got the lock. Just return to userspace:  	 */  	if (unlikely(!curval)) -		goto out_unlock_release_sem; +		goto out_unlock_put_key;  	uval = curval; @@ -1431,7 +1438,7 @@ static int futex_lock_pi(u32 __user *uaddr, int fshared,  	 * We took the lock due to owner died take over.  	 */  	if (unlikely(lock_taken)) -		goto out_unlock_release_sem; +		goto out_unlock_put_key;  	/*  	 * We dont have the lock. Look up the PI state (or create it if @@ -1470,7 +1477,7 @@ static int futex_lock_pi(u32 __user *uaddr, int fshared,  				goto retry_locked;  			}  		default: -			goto out_unlock_release_sem; +			goto out_unlock_put_key;  		}  	} @@ -1561,16 +1568,17 @@ static int futex_lock_pi(u32 __user *uaddr, int fshared,  		destroy_hrtimer_on_stack(&to->timer);  	return ret != -EINTR ? ret : -ERESTARTNOINTR; - out_unlock_release_sem: +out_unlock_put_key:  	queue_unlock(&q, hb); - out_release_sem: +out_put_key:  	put_futex_key(fshared, &q.key); +out:  	if (to)  		destroy_hrtimer_on_stack(&to->timer);  	return ret; - uaddr_faulted: +uaddr_faulted:  	/*  	 * We have to r/w  *(int __user *)uaddr, and we have to modify it  	 * atomically.  Therefore, if we continue to fault after get_user() @@ -1583,7 +1591,7 @@ static int futex_lock_pi(u32 __user *uaddr, int fshared,  	if (attempt++) {  		ret = futex_handle_fault((unsigned long)uaddr, attempt);  		if (ret) -			goto out_release_sem; +			goto out_put_key;  		goto retry_unlocked;  	} @@ -1675,9 +1683,9 @@ retry_unlocked:  out_unlock:  	spin_unlock(&hb->lock); -out:  	put_futex_key(fshared, &key); +out:  	return ret;  pi_faulted: diff --git a/kernel/kmod.c b/kernel/kmod.c index b46dbb90866..a27a5f64443 100644 --- a/kernel/kmod.c +++ b/kernel/kmod.c @@ -51,8 +51,8 @@ char modprobe_path[KMOD_PATH_LEN] = "/sbin/modprobe";  /**   * request_module - try to load a kernel module - * @fmt:     printf style format string for the name of the module - * @varargs: arguements as specified in the format string + * @fmt: printf style format string for the name of the module + * @...: arguments as specified in the format string   *   * Load a module using the user mode module loader. The function returns   * zero on success or a negative errno code on failure. Note that a diff --git a/kernel/kprobes.c b/kernel/kprobes.c index 9f8a3f25259..1b9cbdc0127 100644 --- a/kernel/kprobes.c +++ b/kernel/kprobes.c @@ -69,7 +69,7 @@ static struct hlist_head kretprobe_inst_table[KPROBE_TABLE_SIZE];  /* NOTE: change this value only with kprobe_mutex held */  static bool kprobe_enabled; -DEFINE_MUTEX(kprobe_mutex);		/* Protects kprobe_table */ +static DEFINE_MUTEX(kprobe_mutex);	/* Protects kprobe_table */  static DEFINE_PER_CPU(struct kprobe *, kprobe_instance) = NULL;  static struct {  	spinlock_t lock ____cacheline_aligned_in_smp; @@ -115,6 +115,7 @@ enum kprobe_slot_state {  	SLOT_USED = 2,  }; +static DEFINE_MUTEX(kprobe_insn_mutex);	/* Protects kprobe_insn_pages */  static struct hlist_head kprobe_insn_pages;  static int kprobe_garbage_slots;  static int collect_garbage_slots(void); @@ -144,10 +145,10 @@ loop_end:  }  /** - * get_insn_slot() - Find a slot on an executable page for an instruction. + * __get_insn_slot() - Find a slot on an executable page for an instruction.   * We allocate an executable page if there's no room on existing ones.   */ -kprobe_opcode_t __kprobes *get_insn_slot(void) +static kprobe_opcode_t __kprobes *__get_insn_slot(void)  {  	struct kprobe_insn_page *kip;  	struct hlist_node *pos; @@ -196,6 +197,15 @@ kprobe_opcode_t __kprobes *get_insn_slot(void)  	return kip->insns;  } +kprobe_opcode_t __kprobes *get_insn_slot(void) +{ +	kprobe_opcode_t *ret; +	mutex_lock(&kprobe_insn_mutex); +	ret = __get_insn_slot(); +	mutex_unlock(&kprobe_insn_mutex); +	return ret; +} +  /* Return 1 if all garbages are collected, otherwise 0. */  static int __kprobes collect_one_slot(struct kprobe_insn_page *kip, int idx)  { @@ -226,9 +236,13 @@ static int __kprobes collect_garbage_slots(void)  {  	struct kprobe_insn_page *kip;  	struct hlist_node *pos, *next; +	int safety;  	/* Ensure no-one is preepmted on the garbages */ -	if (check_safety() != 0) +	mutex_unlock(&kprobe_insn_mutex); +	safety = check_safety(); +	mutex_lock(&kprobe_insn_mutex); +	if (safety != 0)  		return -EAGAIN;  	hlist_for_each_entry_safe(kip, pos, next, &kprobe_insn_pages, hlist) { @@ -251,6 +265,7 @@ void __kprobes free_insn_slot(kprobe_opcode_t * slot, int dirty)  	struct kprobe_insn_page *kip;  	struct hlist_node *pos; +	mutex_lock(&kprobe_insn_mutex);  	hlist_for_each_entry(kip, pos, &kprobe_insn_pages, hlist) {  		if (kip->insns <= slot &&  		    slot < kip->insns + (INSNS_PER_PAGE * MAX_INSN_SIZE)) { @@ -267,6 +282,8 @@ void __kprobes free_insn_slot(kprobe_opcode_t * slot, int dirty)  	if (dirty && ++kprobe_garbage_slots > INSNS_PER_PAGE)  		collect_garbage_slots(); + +	mutex_unlock(&kprobe_insn_mutex);  }  #endif @@ -310,7 +327,7 @@ static int __kprobes aggr_pre_handler(struct kprobe *p, struct pt_regs *regs)  	struct kprobe *kp;  	list_for_each_entry_rcu(kp, &p->list, list) { -		if (kp->pre_handler) { +		if (kp->pre_handler && !kprobe_gone(kp)) {  			set_kprobe_instance(kp);  			if (kp->pre_handler(kp, regs))  				return 1; @@ -326,7 +343,7 @@ static void __kprobes aggr_post_handler(struct kprobe *p, struct pt_regs *regs,  	struct kprobe *kp;  	list_for_each_entry_rcu(kp, &p->list, list) { -		if (kp->post_handler) { +		if (kp->post_handler && !kprobe_gone(kp)) {  			set_kprobe_instance(kp);  			kp->post_handler(kp, regs, flags);  			reset_kprobe_instance(); @@ -393,7 +410,7 @@ void __kprobes recycle_rp_inst(struct kretprobe_instance *ri,  		hlist_add_head(&ri->hlist, head);  } -void kretprobe_hash_lock(struct task_struct *tsk, +void __kprobes kretprobe_hash_lock(struct task_struct *tsk,  			 struct hlist_head **head, unsigned long *flags)  {  	unsigned long hash = hash_ptr(tsk, KPROBE_HASH_BITS); @@ -404,13 +421,15 @@ void kretprobe_hash_lock(struct task_struct *tsk,  	spin_lock_irqsave(hlist_lock, *flags);  } -static void kretprobe_table_lock(unsigned long hash, unsigned long *flags) +static void __kprobes kretprobe_table_lock(unsigned long hash, +	unsigned long *flags)  {  	spinlock_t *hlist_lock = kretprobe_table_lock_ptr(hash);  	spin_lock_irqsave(hlist_lock, *flags);  } -void kretprobe_hash_unlock(struct task_struct *tsk, unsigned long *flags) +void __kprobes kretprobe_hash_unlock(struct task_struct *tsk, +	unsigned long *flags)  {  	unsigned long hash = hash_ptr(tsk, KPROBE_HASH_BITS);  	spinlock_t *hlist_lock; @@ -419,7 +438,7 @@ void kretprobe_hash_unlock(struct task_struct *tsk, unsigned long *flags)  	spin_unlock_irqrestore(hlist_lock, *flags);  } -void kretprobe_table_unlock(unsigned long hash, unsigned long *flags) +void __kprobes kretprobe_table_unlock(unsigned long hash, unsigned long *flags)  {  	spinlock_t *hlist_lock = kretprobe_table_lock_ptr(hash);  	spin_unlock_irqrestore(hlist_lock, *flags); @@ -526,9 +545,10 @@ static inline void add_aggr_kprobe(struct kprobe *ap, struct kprobe *p)  	ap->addr = p->addr;  	ap->pre_handler = aggr_pre_handler;  	ap->fault_handler = aggr_fault_handler; -	if (p->post_handler) +	/* We don't care the kprobe which has gone. */ +	if (p->post_handler && !kprobe_gone(p))  		ap->post_handler = aggr_post_handler; -	if (p->break_handler) +	if (p->break_handler && !kprobe_gone(p))  		ap->break_handler = aggr_break_handler;  	INIT_LIST_HEAD(&ap->list); @@ -547,17 +567,41 @@ static int __kprobes register_aggr_kprobe(struct kprobe *old_p,  	int ret = 0;  	struct kprobe *ap; +	if (kprobe_gone(old_p)) { +		/* +		 * Attempting to insert new probe at the same location that +		 * had a probe in the module vaddr area which already +		 * freed. So, the instruction slot has already been +		 * released. We need a new slot for the new probe. +		 */ +		ret = arch_prepare_kprobe(old_p); +		if (ret) +			return ret; +	}  	if (old_p->pre_handler == aggr_pre_handler) {  		copy_kprobe(old_p, p);  		ret = add_new_kprobe(old_p, p); +		ap = old_p;  	} else {  		ap = kzalloc(sizeof(struct kprobe), GFP_KERNEL); -		if (!ap) +		if (!ap) { +			if (kprobe_gone(old_p)) +				arch_remove_kprobe(old_p);  			return -ENOMEM; +		}  		add_aggr_kprobe(ap, old_p);  		copy_kprobe(ap, p);  		ret = add_new_kprobe(ap, p);  	} +	if (kprobe_gone(old_p)) { +		/* +		 * If the old_p has gone, its breakpoint has been disarmed. +		 * We have to arm it again after preparing real kprobes. +		 */ +		ap->flags &= ~KPROBE_FLAG_GONE; +		if (kprobe_enabled) +			arch_arm_kprobe(ap); +	}  	return ret;  } @@ -600,8 +644,7 @@ static kprobe_opcode_t __kprobes *kprobe_addr(struct kprobe *p)  	return (kprobe_opcode_t *)(((char *)addr) + p->offset);  } -static int __kprobes __register_kprobe(struct kprobe *p, -	unsigned long called_from) +int __kprobes register_kprobe(struct kprobe *p)  {  	int ret = 0;  	struct kprobe *old_p; @@ -620,28 +663,30 @@ static int __kprobes __register_kprobe(struct kprobe *p,  		return -EINVAL;  	} -	p->mod_refcounted = 0; - +	p->flags = 0;  	/*  	 * Check if are we probing a module.  	 */  	probed_mod = __module_text_address((unsigned long) p->addr);  	if (probed_mod) { -		struct module *calling_mod; -		calling_mod = __module_text_address(called_from);  		/* -		 * We must allow modules to probe themself and in this case -		 * avoid incrementing the module refcount, so as to allow -		 * unloading of self probing modules. +		 * We must hold a refcount of the probed module while updating +		 * its code to prohibit unexpected unloading.  		 */ -		if (calling_mod && calling_mod != probed_mod) { -			if (unlikely(!try_module_get(probed_mod))) { -				preempt_enable(); -				return -EINVAL; -			} -			p->mod_refcounted = 1; -		} else -			probed_mod = NULL; +		if (unlikely(!try_module_get(probed_mod))) { +			preempt_enable(); +			return -EINVAL; +		} +		/* +		 * If the module freed .init.text, we couldn't insert +		 * kprobes in there. +		 */ +		if (within_module_init((unsigned long)p->addr, probed_mod) && +		    probed_mod->state != MODULE_STATE_COMING) { +			module_put(probed_mod); +			preempt_enable(); +			return -EINVAL; +		}  	}  	preempt_enable(); @@ -668,8 +713,9 @@ static int __kprobes __register_kprobe(struct kprobe *p,  out:  	mutex_unlock(&kprobe_mutex); -	if (ret && probed_mod) +	if (probed_mod)  		module_put(probed_mod); +  	return ret;  } @@ -697,16 +743,16 @@ valid_p:  	     list_is_singular(&old_p->list))) {  		/*  		 * Only probe on the hash list. Disarm only if kprobes are -		 * enabled - otherwise, the breakpoint would already have -		 * been removed. We save on flushing icache. +		 * enabled and not gone - otherwise, the breakpoint would +		 * already have been removed. We save on flushing icache.  		 */ -		if (kprobe_enabled) +		if (kprobe_enabled && !kprobe_gone(old_p))  			arch_disarm_kprobe(p);  		hlist_del_rcu(&old_p->hlist);  	} else { -		if (p->break_handler) +		if (p->break_handler && !kprobe_gone(p))  			old_p->break_handler = NULL; -		if (p->post_handler) { +		if (p->post_handler && !kprobe_gone(p)) {  			list_for_each_entry_rcu(list_p, &old_p->list, list) {  				if ((list_p != p) && (list_p->post_handler))  					goto noclean; @@ -721,39 +767,27 @@ noclean:  static void __kprobes __unregister_kprobe_bottom(struct kprobe *p)  { -	struct module *mod;  	struct kprobe *old_p; -	if (p->mod_refcounted) { -		/* -		 * Since we've already incremented refcount, -		 * we don't need to disable preemption. -		 */ -		mod = module_text_address((unsigned long)p->addr); -		if (mod) -			module_put(mod); -	} - -	if (list_empty(&p->list) || list_is_singular(&p->list)) { -		if (!list_empty(&p->list)) { -			/* "p" is the last child of an aggr_kprobe */ -			old_p = list_entry(p->list.next, struct kprobe, list); -			list_del(&p->list); -			kfree(old_p); -		} +	if (list_empty(&p->list))  		arch_remove_kprobe(p); +	else if (list_is_singular(&p->list)) { +		/* "p" is the last child of an aggr_kprobe */ +		old_p = list_entry(p->list.next, struct kprobe, list); +		list_del(&p->list); +		arch_remove_kprobe(old_p); +		kfree(old_p);  	}  } -static int __register_kprobes(struct kprobe **kps, int num, -	unsigned long called_from) +int __kprobes register_kprobes(struct kprobe **kps, int num)  {  	int i, ret = 0;  	if (num <= 0)  		return -EINVAL;  	for (i = 0; i < num; i++) { -		ret = __register_kprobe(kps[i], called_from); +		ret = register_kprobe(kps[i]);  		if (ret < 0) {  			if (i > 0)  				unregister_kprobes(kps, i); @@ -763,26 +797,11 @@ static int __register_kprobes(struct kprobe **kps, int num,  	return ret;  } -/* - * Registration and unregistration functions for kprobe. - */ -int __kprobes register_kprobe(struct kprobe *p) -{ -	return __register_kprobes(&p, 1, -				  (unsigned long)__builtin_return_address(0)); -} -  void __kprobes unregister_kprobe(struct kprobe *p)  {  	unregister_kprobes(&p, 1);  } -int __kprobes register_kprobes(struct kprobe **kps, int num) -{ -	return __register_kprobes(kps, num, -				  (unsigned long)__builtin_return_address(0)); -} -  void __kprobes unregister_kprobes(struct kprobe **kps, int num)  {  	int i; @@ -811,8 +830,7 @@ unsigned long __weak arch_deref_entry_point(void *entry)  	return (unsigned long)entry;  } -static int __register_jprobes(struct jprobe **jps, int num, -	unsigned long called_from) +int __kprobes register_jprobes(struct jprobe **jps, int num)  {  	struct jprobe *jp;  	int ret = 0, i; @@ -830,7 +848,7 @@ static int __register_jprobes(struct jprobe **jps, int num,  			/* Todo: Verify probepoint is a function entry point */  			jp->kp.pre_handler = setjmp_pre_handler;  			jp->kp.break_handler = longjmp_break_handler; -			ret = __register_kprobe(&jp->kp, called_from); +			ret = register_kprobe(&jp->kp);  		}  		if (ret < 0) {  			if (i > 0) @@ -843,8 +861,7 @@ static int __register_jprobes(struct jprobe **jps, int num,  int __kprobes register_jprobe(struct jprobe *jp)  { -	return __register_jprobes(&jp, 1, -		(unsigned long)__builtin_return_address(0)); +	return register_jprobes(&jp, 1);  }  void __kprobes unregister_jprobe(struct jprobe *jp) @@ -852,12 +869,6 @@ void __kprobes unregister_jprobe(struct jprobe *jp)  	unregister_jprobes(&jp, 1);  } -int __kprobes register_jprobes(struct jprobe **jps, int num) -{ -	return __register_jprobes(jps, num, -		(unsigned long)__builtin_return_address(0)); -} -  void __kprobes unregister_jprobes(struct jprobe **jps, int num)  {  	int i; @@ -920,8 +931,7 @@ static int __kprobes pre_handler_kretprobe(struct kprobe *p,  	return 0;  } -static int __kprobes __register_kretprobe(struct kretprobe *rp, -					  unsigned long called_from) +int __kprobes register_kretprobe(struct kretprobe *rp)  {  	int ret = 0;  	struct kretprobe_instance *inst; @@ -967,21 +977,20 @@ static int __kprobes __register_kretprobe(struct kretprobe *rp,  	rp->nmissed = 0;  	/* Establish function entry probe point */ -	ret = __register_kprobe(&rp->kp, called_from); +	ret = register_kprobe(&rp->kp);  	if (ret != 0)  		free_rp_inst(rp);  	return ret;  } -static int __register_kretprobes(struct kretprobe **rps, int num, -	unsigned long called_from) +int __kprobes register_kretprobes(struct kretprobe **rps, int num)  {  	int ret = 0, i;  	if (num <= 0)  		return -EINVAL;  	for (i = 0; i < num; i++) { -		ret = __register_kretprobe(rps[i], called_from); +		ret = register_kretprobe(rps[i]);  		if (ret < 0) {  			if (i > 0)  				unregister_kretprobes(rps, i); @@ -991,23 +1000,11 @@ static int __register_kretprobes(struct kretprobe **rps, int num,  	return ret;  } -int __kprobes register_kretprobe(struct kretprobe *rp) -{ -	return __register_kretprobes(&rp, 1, -			(unsigned long)__builtin_return_address(0)); -} -  void __kprobes unregister_kretprobe(struct kretprobe *rp)  {  	unregister_kretprobes(&rp, 1);  } -int __kprobes register_kretprobes(struct kretprobe **rps, int num) -{ -	return __register_kretprobes(rps, num, -			(unsigned long)__builtin_return_address(0)); -} -  void __kprobes unregister_kretprobes(struct kretprobe **rps, int num)  {  	int i; @@ -1055,6 +1052,72 @@ static int __kprobes pre_handler_kretprobe(struct kprobe *p,  #endif /* CONFIG_KRETPROBES */ +/* Set the kprobe gone and remove its instruction buffer. */ +static void __kprobes kill_kprobe(struct kprobe *p) +{ +	struct kprobe *kp; +	p->flags |= KPROBE_FLAG_GONE; +	if (p->pre_handler == aggr_pre_handler) { +		/* +		 * If this is an aggr_kprobe, we have to list all the +		 * chained probes and mark them GONE. +		 */ +		list_for_each_entry_rcu(kp, &p->list, list) +			kp->flags |= KPROBE_FLAG_GONE; +		p->post_handler = NULL; +		p->break_handler = NULL; +	} +	/* +	 * Here, we can remove insn_slot safely, because no thread calls +	 * the original probed function (which will be freed soon) any more. +	 */ +	arch_remove_kprobe(p); +} + +/* Module notifier call back, checking kprobes on the module */ +static int __kprobes kprobes_module_callback(struct notifier_block *nb, +					     unsigned long val, void *data) +{ +	struct module *mod = data; +	struct hlist_head *head; +	struct hlist_node *node; +	struct kprobe *p; +	unsigned int i; +	int checkcore = (val == MODULE_STATE_GOING); + +	if (val != MODULE_STATE_GOING && val != MODULE_STATE_LIVE) +		return NOTIFY_DONE; + +	/* +	 * When MODULE_STATE_GOING was notified, both of module .text and +	 * .init.text sections would be freed. When MODULE_STATE_LIVE was +	 * notified, only .init.text section would be freed. We need to +	 * disable kprobes which have been inserted in the sections. +	 */ +	mutex_lock(&kprobe_mutex); +	for (i = 0; i < KPROBE_TABLE_SIZE; i++) { +		head = &kprobe_table[i]; +		hlist_for_each_entry_rcu(p, node, head, hlist) +			if (within_module_init((unsigned long)p->addr, mod) || +			    (checkcore && +			     within_module_core((unsigned long)p->addr, mod))) { +				/* +				 * The vaddr this probe is installed will soon +				 * be vfreed buy not synced to disk. Hence, +				 * disarming the breakpoint isn't needed. +				 */ +				kill_kprobe(p); +			} +	} +	mutex_unlock(&kprobe_mutex); +	return NOTIFY_DONE; +} + +static struct notifier_block kprobe_module_nb = { +	.notifier_call = kprobes_module_callback, +	.priority = 0 +}; +  static int __init init_kprobes(void)  {  	int i, err = 0; @@ -1111,6 +1174,9 @@ static int __init init_kprobes(void)  	err = arch_init_kprobes();  	if (!err)  		err = register_die_notifier(&kprobe_exceptions_nb); +	if (!err) +		err = register_module_notifier(&kprobe_module_nb); +  	kprobes_initialized = (err == 0);  	if (!err) @@ -1131,10 +1197,12 @@ static void __kprobes report_probe(struct seq_file *pi, struct kprobe *p,  	else  		kprobe_type = "k";  	if (sym) -		seq_printf(pi, "%p  %s  %s+0x%x  %s\n", p->addr, kprobe_type, -			sym, offset, (modname ? modname : " ")); +		seq_printf(pi, "%p  %s  %s+0x%x  %s %s\n", p->addr, kprobe_type, +			sym, offset, (modname ? modname : " "), +			(kprobe_gone(p) ? "[GONE]" : ""));  	else -		seq_printf(pi, "%p  %s  %p\n", p->addr, kprobe_type, p->addr); +		seq_printf(pi, "%p  %s  %p %s\n", p->addr, kprobe_type, p->addr, +			(kprobe_gone(p) ? "[GONE]" : ""));  }  static void __kprobes *kprobe_seq_start(struct seq_file *f, loff_t *pos) @@ -1215,7 +1283,8 @@ static void __kprobes enable_all_kprobes(void)  	for (i = 0; i < KPROBE_TABLE_SIZE; i++) {  		head = &kprobe_table[i];  		hlist_for_each_entry_rcu(p, node, head, hlist) -			arch_arm_kprobe(p); +			if (!kprobe_gone(p)) +				arch_arm_kprobe(p);  	}  	kprobe_enabled = true; @@ -1244,7 +1313,7 @@ static void __kprobes disable_all_kprobes(void)  	for (i = 0; i < KPROBE_TABLE_SIZE; i++) {  		head = &kprobe_table[i];  		hlist_for_each_entry_rcu(p, node, head, hlist) { -			if (!arch_trampoline_kprobe(p)) +			if (!arch_trampoline_kprobe(p) && !kprobe_gone(p))  				arch_disarm_kprobe(p);  		}  	} diff --git a/kernel/ksysfs.c b/kernel/ksysfs.c index 08dd8ed86c7..528dd78e7e7 100644 --- a/kernel/ksysfs.c +++ b/kernel/ksysfs.c @@ -24,7 +24,7 @@ static struct kobj_attribute _name##_attr = __ATTR_RO(_name)  static struct kobj_attribute _name##_attr = \  	__ATTR(_name, 0644, _name##_show, _name##_store) -#if defined(CONFIG_HOTPLUG) && defined(CONFIG_NET) +#if defined(CONFIG_HOTPLUG)  /* current uevent sequence number */  static ssize_t uevent_seqnum_show(struct kobject *kobj,  				  struct kobj_attribute *attr, char *buf) @@ -137,7 +137,7 @@ struct kobject *kernel_kobj;  EXPORT_SYMBOL_GPL(kernel_kobj);  static struct attribute * kernel_attrs[] = { -#if defined(CONFIG_HOTPLUG) && defined(CONFIG_NET) +#if defined(CONFIG_HOTPLUG)  	&uevent_seqnum_attr.attr,  	&uevent_helper_attr.attr,  #endif diff --git a/kernel/module.c b/kernel/module.c index dd2a54155b5..496dcb57b60 100644 --- a/kernel/module.c +++ b/kernel/module.c @@ -43,7 +43,6 @@  #include <linux/device.h>  #include <linux/string.h>  #include <linux/mutex.h> -#include <linux/unwind.h>  #include <linux/rculist.h>  #include <asm/uaccess.h>  #include <asm/cacheflush.h> @@ -757,8 +756,16 @@ sys_delete_module(const char __user *name_user, unsigned int flags)  		return -EFAULT;  	name[MODULE_NAME_LEN-1] = '\0'; -	if (mutex_lock_interruptible(&module_mutex) != 0) -		return -EINTR; +	/* Create stop_machine threads since free_module relies on +	 * a non-failing stop_machine call. */ +	ret = stop_machine_create(); +	if (ret) +		return ret; + +	if (mutex_lock_interruptible(&module_mutex) != 0) { +		ret = -EINTR; +		goto out_stop; +	}  	mod = find_module(name);  	if (!mod) { @@ -817,10 +824,12 @@ sys_delete_module(const char __user *name_user, unsigned int flags)   out:  	mutex_unlock(&module_mutex); +out_stop: +	stop_machine_destroy();  	return ret;  } -static void print_unload_info(struct seq_file *m, struct module *mod) +static inline void print_unload_info(struct seq_file *m, struct module *mod)  {  	struct module_use *use;  	int printed_something = 0; @@ -893,7 +902,7 @@ void module_put(struct module *module)  EXPORT_SYMBOL(module_put);  #else /* !CONFIG_MODULE_UNLOAD */ -static void print_unload_info(struct seq_file *m, struct module *mod) +static inline void print_unload_info(struct seq_file *m, struct module *mod)  {  	/* We don't know the usage count, or what modules are using. */  	seq_printf(m, " - -"); @@ -1439,8 +1448,6 @@ static void free_module(struct module *mod)  	remove_sect_attrs(mod);  	mod_kobject_remove(mod); -	unwind_remove_table(mod->unwind_info, 0); -  	/* Arch-specific cleanup. */  	module_arch_cleanup(mod); @@ -1578,11 +1585,21 @@ static int simplify_symbols(Elf_Shdr *sechdrs,  	return ret;  } +/* Additional bytes needed by arch in front of individual sections */ +unsigned int __weak arch_mod_section_prepend(struct module *mod, +					     unsigned int section) +{ +	/* default implementation just returns zero */ +	return 0; +} +  /* Update size with this section: return offset. */ -static long get_offset(unsigned int *size, Elf_Shdr *sechdr) +static long get_offset(struct module *mod, unsigned int *size, +		       Elf_Shdr *sechdr, unsigned int section)  {  	long ret; +	*size += arch_mod_section_prepend(mod, section);  	ret = ALIGN(*size, sechdr->sh_addralign ?: 1);  	*size = ret + sechdr->sh_size;  	return ret; @@ -1622,7 +1639,7 @@ static void layout_sections(struct module *mod,  			    || strncmp(secstrings + s->sh_name,  				       ".init", 5) == 0)  				continue; -			s->sh_entsize = get_offset(&mod->core_size, s); +			s->sh_entsize = get_offset(mod, &mod->core_size, s, i);  			DEBUGP("\t%s\n", secstrings + s->sh_name);  		}  		if (m == 0) @@ -1640,7 +1657,7 @@ static void layout_sections(struct module *mod,  			    || strncmp(secstrings + s->sh_name,  				       ".init", 5) != 0)  				continue; -			s->sh_entsize = (get_offset(&mod->init_size, s) +			s->sh_entsize = (get_offset(mod, &mod->init_size, s, i)  					 | INIT_OFFSET_MASK);  			DEBUGP("\t%s\n", secstrings + s->sh_name);  		} @@ -1725,15 +1742,15 @@ static const struct kernel_symbol *lookup_symbol(const char *name,  	return NULL;  } -static int is_exported(const char *name, const struct module *mod) +static int is_exported(const char *name, unsigned long value, +		       const struct module *mod)  { -	if (!mod && lookup_symbol(name, __start___ksymtab, __stop___ksymtab)) -		return 1; +	const struct kernel_symbol *ks; +	if (!mod) +		ks = lookup_symbol(name, __start___ksymtab, __stop___ksymtab);  	else -		if (mod && lookup_symbol(name, mod->syms, mod->syms + mod->num_syms)) -			return 1; -		else -			return 0; +		ks = lookup_symbol(name, mod->syms, mod->syms + mod->num_syms); +	return ks != NULL && ks->value == value;  }  /* As per nm */ @@ -1847,7 +1864,6 @@ static noinline struct module *load_module(void __user *umod,  	unsigned int symindex = 0;  	unsigned int strindex = 0;  	unsigned int modindex, versindex, infoindex, pcpuindex; -	unsigned int unwindex = 0;  	unsigned int num_kp, num_mcount;  	struct kernel_param *kp;  	struct module *mod; @@ -1865,6 +1881,13 @@ static noinline struct module *load_module(void __user *umod,  	/* vmalloc barfs on "unusual" numbers.  Check here */  	if (len > 64 * 1024 * 1024 || (hdr = vmalloc(len)) == NULL)  		return ERR_PTR(-ENOMEM); + +	/* Create stop_machine threads since the error path relies on +	 * a non-failing stop_machine call. */ +	err = stop_machine_create(); +	if (err) +		goto free_hdr; +  	if (copy_from_user(hdr, umod, len) != 0) {  		err = -EFAULT;  		goto free_hdr; @@ -1930,9 +1953,6 @@ static noinline struct module *load_module(void __user *umod,  	versindex = find_sec(hdr, sechdrs, secstrings, "__versions");  	infoindex = find_sec(hdr, sechdrs, secstrings, ".modinfo");  	pcpuindex = find_pcpusec(hdr, sechdrs, secstrings); -#ifdef ARCH_UNWIND_SECTION_NAME -	unwindex = find_sec(hdr, sechdrs, secstrings, ARCH_UNWIND_SECTION_NAME); -#endif  	/* Don't keep modinfo and version sections. */  	sechdrs[infoindex].sh_flags &= ~(unsigned long)SHF_ALLOC; @@ -1942,8 +1962,6 @@ static noinline struct module *load_module(void __user *umod,  	sechdrs[symindex].sh_flags |= SHF_ALLOC;  	sechdrs[strindex].sh_flags |= SHF_ALLOC;  #endif -	if (unwindex) -		sechdrs[unwindex].sh_flags |= SHF_ALLOC;  	/* Check module struct version now, before we try to use module. */  	if (!check_modstruct_version(sechdrs, versindex, mod)) { @@ -2240,14 +2258,10 @@ static noinline struct module *load_module(void __user *umod,  	add_sect_attrs(mod, hdr->e_shnum, secstrings, sechdrs);  	add_notes_attrs(mod, hdr->e_shnum, secstrings, sechdrs); -	/* Size of section 0 is 0, so this works well if no unwind info. */ -	mod->unwind_info = unwind_add_table(mod, -					    (void *)sechdrs[unwindex].sh_addr, -					    sechdrs[unwindex].sh_size); -  	/* Get rid of temporary copy */  	vfree(hdr); +	stop_machine_destroy();  	/* Done! */  	return mod; @@ -2270,6 +2284,7 @@ static noinline struct module *load_module(void __user *umod,  	kfree(args);   free_hdr:  	vfree(hdr); +	stop_machine_destroy();  	return ERR_PTR(err);   truncated: @@ -2337,11 +2352,12 @@ sys_init_module(void __user *umod,  	/* Now it's a first class citizen!  Wake up anyone waiting for it. */  	mod->state = MODULE_STATE_LIVE;  	wake_up(&module_wq); +	blocking_notifier_call_chain(&module_notify_list, +				     MODULE_STATE_LIVE, mod);  	mutex_lock(&module_mutex);  	/* Drop initial reference. */  	module_put(mod); -	unwind_remove_table(mod->unwind_info, 1);  	module_free(mod, mod->module_init);  	mod->module_init = NULL;  	mod->init_size = 0; @@ -2376,7 +2392,7 @@ static const char *get_ksymbol(struct module *mod,  	unsigned long nextval;  	/* At worse, next value is at end of module */ -	if (within(addr, mod->module_init, mod->init_size)) +	if (within_module_init(addr, mod))  		nextval = (unsigned long)mod->module_init+mod->init_text_size;  	else  		nextval = (unsigned long)mod->module_core+mod->core_text_size; @@ -2424,8 +2440,8 @@ const char *module_address_lookup(unsigned long addr,  	preempt_disable();  	list_for_each_entry_rcu(mod, &modules, list) { -		if (within(addr, mod->module_init, mod->init_size) -		    || within(addr, mod->module_core, mod->core_size)) { +		if (within_module_init(addr, mod) || +		    within_module_core(addr, mod)) {  			if (modname)  				*modname = mod->name;  			ret = get_ksymbol(mod, addr, size, offset); @@ -2447,8 +2463,8 @@ int lookup_module_symbol_name(unsigned long addr, char *symname)  	preempt_disable();  	list_for_each_entry_rcu(mod, &modules, list) { -		if (within(addr, mod->module_init, mod->init_size) || -		    within(addr, mod->module_core, mod->core_size)) { +		if (within_module_init(addr, mod) || +		    within_module_core(addr, mod)) {  			const char *sym;  			sym = get_ksymbol(mod, addr, NULL, NULL); @@ -2471,8 +2487,8 @@ int lookup_module_symbol_attrs(unsigned long addr, unsigned long *size,  	preempt_disable();  	list_for_each_entry_rcu(mod, &modules, list) { -		if (within(addr, mod->module_init, mod->init_size) || -		    within(addr, mod->module_core, mod->core_size)) { +		if (within_module_init(addr, mod) || +		    within_module_core(addr, mod)) {  			const char *sym;  			sym = get_ksymbol(mod, addr, size, offset); @@ -2504,7 +2520,7 @@ int module_get_kallsym(unsigned int symnum, unsigned long *value, char *type,  			strlcpy(name, mod->strtab + mod->symtab[symnum].st_name,  				KSYM_NAME_LEN);  			strlcpy(module_name, mod->name, MODULE_NAME_LEN); -			*exported = is_exported(name, mod); +			*exported = is_exported(name, *value, mod);  			preempt_enable();  			return 0;  		} @@ -2691,7 +2707,7 @@ int is_module_address(unsigned long addr)  	preempt_disable();  	list_for_each_entry_rcu(mod, &modules, list) { -		if (within(addr, mod->module_core, mod->core_size)) { +		if (within_module_core(addr, mod)) {  			preempt_enable();  			return 1;  		} diff --git a/kernel/panic.c b/kernel/panic.c index 13f06349a78..2a2ff36ff44 100644 --- a/kernel/panic.c +++ b/kernel/panic.c @@ -299,6 +299,8 @@ static int init_oops_id(void)  {  	if (!oops_id)  		get_random_bytes(&oops_id, sizeof(oops_id)); +	else +		oops_id++;  	return 0;  } diff --git a/kernel/power/main.c b/kernel/power/main.c index 613f16941b8..23998887397 100644 --- a/kernel/power/main.c +++ b/kernel/power/main.c @@ -615,7 +615,7 @@ static void __init test_wakealarm(struct rtc_device *rtc, suspend_state_t state)  	/* this may fail if the RTC hasn't been initialized */  	status = rtc_read_time(rtc, &alm.time);  	if (status < 0) { -		printk(err_readtime, rtc->dev.bus_id, status); +		printk(err_readtime, dev_name(&rtc->dev), status);  		return;  	}  	rtc_tm_to_time(&alm.time, &now); @@ -626,7 +626,7 @@ static void __init test_wakealarm(struct rtc_device *rtc, suspend_state_t state)  	status = rtc_set_alarm(rtc, &alm);  	if (status < 0) { -		printk(err_wakealarm, rtc->dev.bus_id, status); +		printk(err_wakealarm, dev_name(&rtc->dev), status);  		return;  	} @@ -660,7 +660,7 @@ static int __init has_wakealarm(struct device *dev, void *name_ptr)  	if (!device_may_wakeup(candidate->dev.parent))  		return 0; -	*(char **)name_ptr = dev->bus_id; +	*(const char **)name_ptr = dev_name(dev);  	return 1;  } diff --git a/kernel/profile.c b/kernel/profile.c index d18e2d2654f..784933acf5b 100644 --- a/kernel/profile.c +++ b/kernel/profile.c @@ -445,7 +445,6 @@ void profile_tick(int type)  #ifdef CONFIG_PROC_FS  #include <linux/proc_fs.h>  #include <asm/uaccess.h> -#include <asm/ptrace.h>  static int prof_cpu_mask_read_proc(char *page, char **start, off_t off,  			int count, int *eof, void *data) diff --git a/kernel/rcupdate.c b/kernel/rcupdate.c index ad63af8b252..d92a76a881a 100644 --- a/kernel/rcupdate.c +++ b/kernel/rcupdate.c @@ -77,8 +77,15 @@ void wakeme_after_rcu(struct rcu_head  *head)   * sections are delimited by rcu_read_lock() and rcu_read_unlock(),   * and may be nested.   */ -void synchronize_rcu(void);	/* Makes kernel-doc tools happy */ -synchronize_rcu_xxx(synchronize_rcu, call_rcu) +void synchronize_rcu(void) +{ +	struct rcu_synchronize rcu; +	init_completion(&rcu.completion); +	/* Will wake me after RCU finished. */ +	call_rcu(&rcu.head, wakeme_after_rcu); +	/* Wait for it. */ +	wait_for_completion(&rcu.completion); +}  EXPORT_SYMBOL_GPL(synchronize_rcu);  static void rcu_barrier_callback(struct rcu_head *notused) diff --git a/kernel/rcupreempt.c b/kernel/rcupreempt.c index f9dc8f3720f..33cfc50781f 100644 --- a/kernel/rcupreempt.c +++ b/kernel/rcupreempt.c @@ -1177,7 +1177,16 @@ EXPORT_SYMBOL_GPL(call_rcu_sched);   * in -rt this does -not- necessarily result in all currently executing   * interrupt -handlers- having completed.   */ -synchronize_rcu_xxx(__synchronize_sched, call_rcu_sched) +void __synchronize_sched(void) +{ +	struct rcu_synchronize rcu; + +	init_completion(&rcu.completion); +	/* Will wake me after RCU finished. */ +	call_rcu_sched(&rcu.head, wakeme_after_rcu); +	/* Wait for it. */ +	wait_for_completion(&rcu.completion); +}  EXPORT_SYMBOL_GPL(__synchronize_sched);  /* diff --git a/kernel/rcutorture.c b/kernel/rcutorture.c index 3245b40952c..1cff28db56b 100644 --- a/kernel/rcutorture.c +++ b/kernel/rcutorture.c @@ -136,7 +136,7 @@ static int stutter_pause_test = 0;  #endif  int rcutorture_runnable = RCUTORTURE_RUNNABLE_INIT; -#define FULLSTOP_SIGNALED 1	/* Bail due to signal. */ +#define FULLSTOP_SHUTDOWN 1	/* Bail due to system shutdown/panic. */  #define FULLSTOP_CLEANUP  2	/* Orderly shutdown. */  static int fullstop;		/* stop generating callbacks at test end. */  DEFINE_MUTEX(fullstop_mutex);	/* protect fullstop transitions and */ @@ -151,12 +151,10 @@ rcutorture_shutdown_notify(struct notifier_block *unused1,  {  	if (fullstop)  		return NOTIFY_DONE; -	if (signal_pending(current)) { -		mutex_lock(&fullstop_mutex); -		if (!ACCESS_ONCE(fullstop)) -			fullstop = FULLSTOP_SIGNALED; -		mutex_unlock(&fullstop_mutex); -	} +	mutex_lock(&fullstop_mutex); +	if (!fullstop) +		fullstop = FULLSTOP_SHUTDOWN; +	mutex_unlock(&fullstop_mutex);  	return NOTIFY_DONE;  } @@ -624,7 +622,7 @@ rcu_torture_writer(void *arg)  		rcu_stutter_wait();  	} while (!kthread_should_stop() && !fullstop);  	VERBOSE_PRINTK_STRING("rcu_torture_writer task stopping"); -	while (!kthread_should_stop() && fullstop != FULLSTOP_SIGNALED) +	while (!kthread_should_stop() && fullstop != FULLSTOP_SHUTDOWN)  		schedule_timeout_uninterruptible(1);  	return 0;  } @@ -649,7 +647,7 @@ rcu_torture_fakewriter(void *arg)  	} while (!kthread_should_stop() && !fullstop);  	VERBOSE_PRINTK_STRING("rcu_torture_fakewriter task stopping"); -	while (!kthread_should_stop() && fullstop != FULLSTOP_SIGNALED) +	while (!kthread_should_stop() && fullstop != FULLSTOP_SHUTDOWN)  		schedule_timeout_uninterruptible(1);  	return 0;  } @@ -759,7 +757,7 @@ rcu_torture_reader(void *arg)  	VERBOSE_PRINTK_STRING("rcu_torture_reader task stopping");  	if (irqreader && cur_ops->irqcapable)  		del_timer_sync(&t); -	while (!kthread_should_stop() && fullstop != FULLSTOP_SIGNALED) +	while (!kthread_should_stop() && fullstop != FULLSTOP_SHUTDOWN)  		schedule_timeout_uninterruptible(1);  	return 0;  } diff --git a/kernel/rcutree.c b/kernel/rcutree.c index a342b032112..f2d8638e6c6 100644 --- a/kernel/rcutree.c +++ b/kernel/rcutree.c @@ -79,7 +79,10 @@ struct rcu_state rcu_bh_state = RCU_STATE_INITIALIZER(rcu_bh_state);  DEFINE_PER_CPU(struct rcu_data, rcu_bh_data);  #ifdef CONFIG_NO_HZ -DEFINE_PER_CPU(struct rcu_dynticks, rcu_dynticks); +DEFINE_PER_CPU(struct rcu_dynticks, rcu_dynticks) = { +	.dynticks_nesting = 1, +	.dynticks = 1, +};  #endif /* #ifdef CONFIG_NO_HZ */  static int blimit = 10;		/* Maximum callbacks per softirq. */ @@ -572,6 +575,7 @@ rcu_start_gp(struct rcu_state *rsp, unsigned long flags)  	/* Special-case the common single-level case. */  	if (NUM_RCU_NODES == 1) {  		rnp->qsmask = rnp->qsmaskinit; +		rsp->signaled = RCU_SIGNAL_INIT; /* force_quiescent_state OK. */  		spin_unlock_irqrestore(&rnp->lock, flags);  		return;  	} @@ -1379,13 +1383,6 @@ rcu_init_percpu_data(int cpu, struct rcu_state *rsp)  static void __cpuinit rcu_online_cpu(int cpu)  { -#ifdef CONFIG_NO_HZ -	struct rcu_dynticks *rdtp = &per_cpu(rcu_dynticks, cpu); - -	rdtp->dynticks_nesting = 1; -	rdtp->dynticks |= 1; 	/* need consecutive #s even for hotplug. */ -	rdtp->dynticks_nmi = (rdtp->dynticks_nmi + 1) & ~0x1; -#endif /* #ifdef CONFIG_NO_HZ */  	rcu_init_percpu_data(cpu, &rcu_state);  	rcu_init_percpu_data(cpu, &rcu_bh_state);  	open_softirq(RCU_SOFTIRQ, rcu_process_callbacks); diff --git a/kernel/signal.c b/kernel/signal.c index 8e95855ff3c..3152ac3b62e 100644 --- a/kernel/signal.c +++ b/kernel/signal.c @@ -858,7 +858,8 @@ static int send_signal(int sig, struct siginfo *info, struct task_struct *t,  			q->info.si_signo = sig;  			q->info.si_errno = 0;  			q->info.si_code = SI_USER; -			q->info.si_pid = task_pid_vnr(current); +			q->info.si_pid = task_tgid_nr_ns(current, +							task_active_pid_ns(t));  			q->info.si_uid = current_uid();  			break;  		case (unsigned long) SEND_SIG_PRIV: diff --git a/kernel/stop_machine.c b/kernel/stop_machine.c index 286c41722e8..0cd415ee62a 100644 --- a/kernel/stop_machine.c +++ b/kernel/stop_machine.c @@ -38,7 +38,10 @@ struct stop_machine_data {  static unsigned int num_threads;  static atomic_t thread_ack;  static DEFINE_MUTEX(lock); - +/* setup_lock protects refcount, stop_machine_wq and stop_machine_work. */ +static DEFINE_MUTEX(setup_lock); +/* Users of stop_machine. */ +static int refcount;  static struct workqueue_struct *stop_machine_wq;  static struct stop_machine_data active, idle;  static const cpumask_t *active_cpus; @@ -109,6 +112,43 @@ static int chill(void *unused)  	return 0;  } +int stop_machine_create(void) +{ +	mutex_lock(&setup_lock); +	if (refcount) +		goto done; +	stop_machine_wq = create_rt_workqueue("kstop"); +	if (!stop_machine_wq) +		goto err_out; +	stop_machine_work = alloc_percpu(struct work_struct); +	if (!stop_machine_work) +		goto err_out; +done: +	refcount++; +	mutex_unlock(&setup_lock); +	return 0; + +err_out: +	if (stop_machine_wq) +		destroy_workqueue(stop_machine_wq); +	mutex_unlock(&setup_lock); +	return -ENOMEM; +} +EXPORT_SYMBOL_GPL(stop_machine_create); + +void stop_machine_destroy(void) +{ +	mutex_lock(&setup_lock); +	refcount--; +	if (refcount) +		goto done; +	destroy_workqueue(stop_machine_wq); +	free_percpu(stop_machine_work); +done: +	mutex_unlock(&setup_lock); +} +EXPORT_SYMBOL_GPL(stop_machine_destroy); +  int __stop_machine(int (*fn)(void *), void *data, const struct cpumask *cpus)  {  	struct work_struct *sm_work; @@ -146,19 +186,14 @@ int stop_machine(int (*fn)(void *), void *data, const struct cpumask *cpus)  {  	int ret; +	ret = stop_machine_create(); +	if (ret) +		return ret;  	/* No CPUs can come up or down during this. */  	get_online_cpus();  	ret = __stop_machine(fn, data, cpus);  	put_online_cpus(); - +	stop_machine_destroy();  	return ret;  }  EXPORT_SYMBOL_GPL(stop_machine); - -static int __init stop_machine_init(void) -{ -	stop_machine_wq = create_rt_workqueue("kstop"); -	stop_machine_work = alloc_percpu(struct work_struct); -	return 0; -} -core_initcall(stop_machine_init); diff --git a/kernel/sys.c b/kernel/sys.c index d356d79e84a..4a43617cd56 100644 --- a/kernel/sys.c +++ b/kernel/sys.c @@ -33,6 +33,7 @@  #include <linux/task_io_accounting_ops.h>  #include <linux/seccomp.h>  #include <linux/cpu.h> +#include <linux/ptrace.h>  #include <linux/compat.h>  #include <linux/syscalls.h> @@ -927,6 +928,7 @@ asmlinkage long sys_times(struct tms __user * tbuf)  		if (copy_to_user(tbuf, &tmp, sizeof(struct tms)))  			return -EFAULT;  	} +	force_successful_syscall_return();  	return (long) jiffies_64_to_clock_t(get_jiffies_64());  } diff --git a/kernel/sysctl.c b/kernel/sysctl.c index ff6d45c7626..92f6e5bc3c2 100644 --- a/kernel/sysctl.c +++ b/kernel/sysctl.c @@ -87,10 +87,6 @@ extern int rcutorture_runnable;  #endif /* #ifdef CONFIG_RCU_TORTURE_TEST */  /* Constants used for minimum and  maximum */ -#if defined(CONFIG_HIGHMEM) || defined(CONFIG_DETECT_SOFTLOCKUP) -static int one = 1; -#endif -  #ifdef CONFIG_DETECT_SOFTLOCKUP  static int sixty = 60;  static int neg_one = -1; @@ -101,6 +97,7 @@ static int two = 2;  #endif  static int zero; +static int one = 1;  static int one_hundred = 100;  /* this is needed for the proc_dointvec_minmax for [fs_]overflow UID and GID */ @@ -952,12 +949,22 @@ static struct ctl_table vm_table[] = {  		.data		= &dirty_background_ratio,  		.maxlen		= sizeof(dirty_background_ratio),  		.mode		= 0644, -		.proc_handler	= &proc_dointvec_minmax, +		.proc_handler	= &dirty_background_ratio_handler,  		.strategy	= &sysctl_intvec,  		.extra1		= &zero,  		.extra2		= &one_hundred,  	},  	{ +		.ctl_name	= CTL_UNNUMBERED, +		.procname	= "dirty_background_bytes", +		.data		= &dirty_background_bytes, +		.maxlen		= sizeof(dirty_background_bytes), +		.mode		= 0644, +		.proc_handler	= &dirty_background_bytes_handler, +		.strategy	= &sysctl_intvec, +		.extra1		= &one, +	}, +	{  		.ctl_name	= VM_DIRTY_RATIO,  		.procname	= "dirty_ratio",  		.data		= &vm_dirty_ratio, @@ -969,6 +976,16 @@ static struct ctl_table vm_table[] = {  		.extra2		= &one_hundred,  	},  	{ +		.ctl_name	= CTL_UNNUMBERED, +		.procname	= "dirty_bytes", +		.data		= &vm_dirty_bytes, +		.maxlen		= sizeof(vm_dirty_bytes), +		.mode		= 0644, +		.proc_handler	= &dirty_bytes_handler, +		.strategy	= &sysctl_intvec, +		.extra1		= &one, +	}, +	{  		.procname	= "dirty_writeback_centisecs",  		.data		= &dirty_writeback_interval,  		.maxlen		= sizeof(dirty_writeback_interval), diff --git a/kernel/test_kprobes.c b/kernel/test_kprobes.c index 06b6395b45b..4f104515a19 100644 --- a/kernel/test_kprobes.c +++ b/kernel/test_kprobes.c @@ -22,21 +22,11 @@  static u32 rand1, preh_val, posth_val, jph_val;  static int errors, handler_errors, num_tests; +static u32 (*target)(u32 value); +static u32 (*target2)(u32 value);  static noinline u32 kprobe_target(u32 value)  { -	/* -	 * gcc ignores noinline on some architectures unless we stuff -	 * sufficient lard into the function. The get_kprobe() here is -	 * just for that. -	 * -	 * NOTE: We aren't concerned about the correctness of get_kprobe() -	 * here; hence, this call is neither under !preempt nor with the -	 * kprobe_mutex held. This is fine(tm) -	 */ -	if (get_kprobe((void *)0xdeadbeef)) -		printk(KERN_INFO "Kprobe smoke test: probe on 0xdeadbeef!\n"); -  	return (value / div_factor);  } @@ -74,7 +64,7 @@ static int test_kprobe(void)  		return ret;  	} -	ret = kprobe_target(rand1); +	ret = target(rand1);  	unregister_kprobe(&kp);  	if (preh_val == 0) { @@ -92,6 +82,84 @@ static int test_kprobe(void)  	return 0;  } +static noinline u32 kprobe_target2(u32 value) +{ +	return (value / div_factor) + 1; +} + +static int kp_pre_handler2(struct kprobe *p, struct pt_regs *regs) +{ +	preh_val = (rand1 / div_factor) + 1; +	return 0; +} + +static void kp_post_handler2(struct kprobe *p, struct pt_regs *regs, +		unsigned long flags) +{ +	if (preh_val != (rand1 / div_factor) + 1) { +		handler_errors++; +		printk(KERN_ERR "Kprobe smoke test failed: " +				"incorrect value in post_handler2\n"); +	} +	posth_val = preh_val + div_factor; +} + +static struct kprobe kp2 = { +	.symbol_name = "kprobe_target2", +	.pre_handler = kp_pre_handler2, +	.post_handler = kp_post_handler2 +}; + +static int test_kprobes(void) +{ +	int ret; +	struct kprobe *kps[2] = {&kp, &kp2}; + +	kp.addr = 0; /* addr should be cleard for reusing kprobe. */ +	ret = register_kprobes(kps, 2); +	if (ret < 0) { +		printk(KERN_ERR "Kprobe smoke test failed: " +				"register_kprobes returned %d\n", ret); +		return ret; +	} + +	preh_val = 0; +	posth_val = 0; +	ret = target(rand1); + +	if (preh_val == 0) { +		printk(KERN_ERR "Kprobe smoke test failed: " +				"kprobe pre_handler not called\n"); +		handler_errors++; +	} + +	if (posth_val == 0) { +		printk(KERN_ERR "Kprobe smoke test failed: " +				"kprobe post_handler not called\n"); +		handler_errors++; +	} + +	preh_val = 0; +	posth_val = 0; +	ret = target2(rand1); + +	if (preh_val == 0) { +		printk(KERN_ERR "Kprobe smoke test failed: " +				"kprobe pre_handler2 not called\n"); +		handler_errors++; +	} + +	if (posth_val == 0) { +		printk(KERN_ERR "Kprobe smoke test failed: " +				"kprobe post_handler2 not called\n"); +		handler_errors++; +	} + +	unregister_kprobes(kps, 2); +	return 0; + +} +  static u32 j_kprobe_target(u32 value)  {  	if (value != rand1) { @@ -121,7 +189,7 @@ static int test_jprobe(void)  		return ret;  	} -	ret = kprobe_target(rand1); +	ret = target(rand1);  	unregister_jprobe(&jp);  	if (jph_val == 0) {  		printk(KERN_ERR "Kprobe smoke test failed: " @@ -132,6 +200,43 @@ static int test_jprobe(void)  	return 0;  } +static struct jprobe jp2 = { +	.entry          = j_kprobe_target, +	.kp.symbol_name = "kprobe_target2" +}; + +static int test_jprobes(void) +{ +	int ret; +	struct jprobe *jps[2] = {&jp, &jp2}; + +	jp.kp.addr = 0; /* addr should be cleard for reusing kprobe. */ +	ret = register_jprobes(jps, 2); +	if (ret < 0) { +		printk(KERN_ERR "Kprobe smoke test failed: " +				"register_jprobes returned %d\n", ret); +		return ret; +	} + +	jph_val = 0; +	ret = target(rand1); +	if (jph_val == 0) { +		printk(KERN_ERR "Kprobe smoke test failed: " +				"jprobe handler not called\n"); +		handler_errors++; +	} + +	jph_val = 0; +	ret = target2(rand1); +	if (jph_val == 0) { +		printk(KERN_ERR "Kprobe smoke test failed: " +				"jprobe handler2 not called\n"); +		handler_errors++; +	} +	unregister_jprobes(jps, 2); + +	return 0; +}  #ifdef CONFIG_KRETPROBES  static u32 krph_val; @@ -177,7 +282,7 @@ static int test_kretprobe(void)  		return ret;  	} -	ret = kprobe_target(rand1); +	ret = target(rand1);  	unregister_kretprobe(&rp);  	if (krph_val != rand1) {  		printk(KERN_ERR "Kprobe smoke test failed: " @@ -187,12 +292,72 @@ static int test_kretprobe(void)  	return 0;  } + +static int return_handler2(struct kretprobe_instance *ri, struct pt_regs *regs) +{ +	unsigned long ret = regs_return_value(regs); + +	if (ret != (rand1 / div_factor) + 1) { +		handler_errors++; +		printk(KERN_ERR "Kprobe smoke test failed: " +				"incorrect value in kretprobe handler2\n"); +	} +	if (krph_val == 0) { +		handler_errors++; +		printk(KERN_ERR "Kprobe smoke test failed: " +				"call to kretprobe entry handler failed\n"); +	} + +	krph_val = rand1; +	return 0; +} + +static struct kretprobe rp2 = { +	.handler	= return_handler2, +	.entry_handler  = entry_handler, +	.kp.symbol_name = "kprobe_target2" +}; + +static int test_kretprobes(void) +{ +	int ret; +	struct kretprobe *rps[2] = {&rp, &rp2}; + +	rp.kp.addr = 0; /* addr should be cleard for reusing kprobe. */ +	ret = register_kretprobes(rps, 2); +	if (ret < 0) { +		printk(KERN_ERR "Kprobe smoke test failed: " +				"register_kretprobe returned %d\n", ret); +		return ret; +	} + +	krph_val = 0; +	ret = target(rand1); +	if (krph_val != rand1) { +		printk(KERN_ERR "Kprobe smoke test failed: " +				"kretprobe handler not called\n"); +		handler_errors++; +	} + +	krph_val = 0; +	ret = target2(rand1); +	if (krph_val != rand1) { +		printk(KERN_ERR "Kprobe smoke test failed: " +				"kretprobe handler2 not called\n"); +		handler_errors++; +	} +	unregister_kretprobes(rps, 2); +	return 0; +}  #endif /* CONFIG_KRETPROBES */  int init_test_probes(void)  {  	int ret; +	target = kprobe_target; +	target2 = kprobe_target2; +  	do {  		rand1 = random32();  	} while (rand1 <= div_factor); @@ -204,15 +369,30 @@ int init_test_probes(void)  		errors++;  	num_tests++; +	ret = test_kprobes(); +	if (ret < 0) +		errors++; + +	num_tests++;  	ret = test_jprobe();  	if (ret < 0)  		errors++; +	num_tests++; +	ret = test_jprobes(); +	if (ret < 0) +		errors++; +  #ifdef CONFIG_KRETPROBES  	num_tests++;  	ret = test_kretprobe();  	if (ret < 0)  		errors++; + +	num_tests++; +	ret = test_kretprobes(); +	if (ret < 0) +		errors++;  #endif /* CONFIG_KRETPROBES */  	if (errors) diff --git a/kernel/time.c b/kernel/time.c index d63a4336fad..4886e3ce83a 100644 --- a/kernel/time.c +++ b/kernel/time.c @@ -37,6 +37,7 @@  #include <linux/fs.h>  #include <linux/slab.h>  #include <linux/math64.h> +#include <linux/ptrace.h>  #include <asm/uaccess.h>  #include <asm/unistd.h> @@ -65,8 +66,9 @@ asmlinkage long sys_time(time_t __user * tloc)  	if (tloc) {  		if (put_user(i,tloc)) -			i = -EFAULT; +			return -EFAULT;  	} +	force_successful_syscall_return();  	return i;  } diff --git a/kernel/tsacct.c b/kernel/tsacct.c index 2dc06ab3571..43f891b05a4 100644 --- a/kernel/tsacct.c +++ b/kernel/tsacct.c @@ -92,8 +92,8 @@ void xacct_add_tsk(struct taskstats *stats, struct task_struct *p)  	mm = get_task_mm(p);  	if (mm) {  		/* adjust to KB unit */ -		stats->hiwater_rss   = mm->hiwater_rss * PAGE_SIZE / KB; -		stats->hiwater_vm    = mm->hiwater_vm * PAGE_SIZE / KB; +		stats->hiwater_rss   = get_mm_hiwater_rss(mm) * PAGE_SIZE / KB; +		stats->hiwater_vm    = get_mm_hiwater_vm(mm)  * PAGE_SIZE / KB;  		mmput(mm);  	}  	stats->read_char	= p->ioac.rchar; | 
