diff options
Diffstat (limited to 'kernel')
| -rw-r--r-- | kernel/cgroup.c | 33 | ||||
| -rw-r--r-- | kernel/compat.c | 5 | ||||
| -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/kmod.c | 4 | ||||
| -rw-r--r-- | kernel/kprobes.c | 281 | ||||
| -rw-r--r-- | kernel/ksysfs.c | 4 | ||||
| -rw-r--r-- | kernel/module.c | 33 | ||||
| -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/signal.c | 3 | ||||
| -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 |
19 files changed, 510 insertions, 223 deletions
diff --git a/kernel/cgroup.c b/kernel/cgroup.c index 87bb0258fd27..f221446aa02d 100644 --- a/kernel/cgroup.c +++ b/kernel/cgroup.c | |||
| @@ -116,7 +116,6 @@ static int root_count; | |||
| 116 | * be called. | 116 | * be called. |
| 117 | */ | 117 | */ |
| 118 | static int need_forkexit_callback __read_mostly; | 118 | static int need_forkexit_callback __read_mostly; |
| 119 | static int need_mm_owner_callback __read_mostly; | ||
| 120 | 119 | ||
| 121 | /* convenient tests for these bits */ | 120 | /* convenient tests for these bits */ |
| 122 | inline int cgroup_is_removed(const struct cgroup *cgrp) | 121 | inline int cgroup_is_removed(const struct cgroup *cgrp) |
| @@ -2539,7 +2538,6 @@ static void __init cgroup_init_subsys(struct cgroup_subsys *ss) | |||
| 2539 | init_css_set.subsys[ss->subsys_id] = dummytop->subsys[ss->subsys_id]; | 2538 | init_css_set.subsys[ss->subsys_id] = dummytop->subsys[ss->subsys_id]; |
| 2540 | 2539 | ||
| 2541 | need_forkexit_callback |= ss->fork || ss->exit; | 2540 | need_forkexit_callback |= ss->fork || ss->exit; |
| 2542 | need_mm_owner_callback |= !!ss->mm_owner_changed; | ||
| 2543 | 2541 | ||
| 2544 | /* At system boot, before all subsystems have been | 2542 | /* At system boot, before all subsystems have been |
| 2545 | * registered, no tasks have been forked, so we don't | 2543 | * registered, no tasks have been forked, so we don't |
| @@ -2789,37 +2787,6 @@ void cgroup_fork_callbacks(struct task_struct *child) | |||
| 2789 | } | 2787 | } |
| 2790 | } | 2788 | } |
| 2791 | 2789 | ||
| 2792 | #ifdef CONFIG_MM_OWNER | ||
| 2793 | /** | ||
| 2794 | * cgroup_mm_owner_callbacks - run callbacks when the mm->owner changes | ||
| 2795 | * @p: the new owner | ||
| 2796 | * | ||
| 2797 | * Called on every change to mm->owner. mm_init_owner() does not | ||
| 2798 | * invoke this routine, since it assigns the mm->owner the first time | ||
| 2799 | * and does not change it. | ||
| 2800 | * | ||
| 2801 | * The callbacks are invoked with mmap_sem held in read mode. | ||
| 2802 | */ | ||
| 2803 | void cgroup_mm_owner_callbacks(struct task_struct *old, struct task_struct *new) | ||
| 2804 | { | ||
| 2805 | struct cgroup *oldcgrp, *newcgrp = NULL; | ||
| 2806 | |||
| 2807 | if (need_mm_owner_callback) { | ||
| 2808 | int i; | ||
| 2809 | for (i = 0; i < CGROUP_SUBSYS_COUNT; i++) { | ||
| 2810 | struct cgroup_subsys *ss = subsys[i]; | ||
| 2811 | oldcgrp = task_cgroup(old, ss->subsys_id); | ||
| 2812 | if (new) | ||
| 2813 | newcgrp = task_cgroup(new, ss->subsys_id); | ||
| 2814 | if (oldcgrp == newcgrp) | ||
| 2815 | continue; | ||
| 2816 | if (ss->mm_owner_changed) | ||
| 2817 | ss->mm_owner_changed(ss, oldcgrp, newcgrp, new); | ||
| 2818 | } | ||
| 2819 | } | ||
| 2820 | } | ||
| 2821 | #endif /* CONFIG_MM_OWNER */ | ||
| 2822 | |||
| 2823 | /** | 2790 | /** |
| 2824 | * cgroup_post_fork - called on a new task after adding it to the task list | 2791 | * cgroup_post_fork - called on a new task after adding it to the task list |
| 2825 | * @child: the task in question | 2792 | * @child: the task in question |
diff --git a/kernel/compat.c b/kernel/compat.c index d52e2ec1deb5..42d56544460f 100644 --- a/kernel/compat.c +++ b/kernel/compat.c | |||
| @@ -24,6 +24,7 @@ | |||
| 24 | #include <linux/migrate.h> | 24 | #include <linux/migrate.h> |
| 25 | #include <linux/posix-timers.h> | 25 | #include <linux/posix-timers.h> |
| 26 | #include <linux/times.h> | 26 | #include <linux/times.h> |
| 27 | #include <linux/ptrace.h> | ||
| 27 | 28 | ||
| 28 | #include <asm/uaccess.h> | 29 | #include <asm/uaccess.h> |
| 29 | 30 | ||
| @@ -229,6 +230,7 @@ asmlinkage long compat_sys_times(struct compat_tms __user *tbuf) | |||
| 229 | if (copy_to_user(tbuf, &tmp, sizeof(tmp))) | 230 | if (copy_to_user(tbuf, &tmp, sizeof(tmp))) |
| 230 | return -EFAULT; | 231 | return -EFAULT; |
| 231 | } | 232 | } |
| 233 | force_successful_syscall_return(); | ||
| 232 | return compat_jiffies_to_clock_t(jiffies); | 234 | return compat_jiffies_to_clock_t(jiffies); |
| 233 | } | 235 | } |
| 234 | 236 | ||
| @@ -894,8 +896,9 @@ asmlinkage long compat_sys_time(compat_time_t __user * tloc) | |||
| 894 | 896 | ||
| 895 | if (tloc) { | 897 | if (tloc) { |
| 896 | if (put_user(i,tloc)) | 898 | if (put_user(i,tloc)) |
| 897 | i = -EFAULT; | 899 | return -EFAULT; |
| 898 | } | 900 | } |
| 901 | force_successful_syscall_return(); | ||
| 899 | return i; | 902 | return i; |
| 900 | } | 903 | } |
| 901 | 904 | ||
diff --git a/kernel/cpuset.c b/kernel/cpuset.c index 39c1a4c1c5a9..345ace5117de 100644 --- a/kernel/cpuset.c +++ b/kernel/cpuset.c | |||
| @@ -240,6 +240,17 @@ static struct cpuset top_cpuset = { | |||
| 240 | static DEFINE_MUTEX(callback_mutex); | 240 | static DEFINE_MUTEX(callback_mutex); |
| 241 | 241 | ||
| 242 | /* | 242 | /* |
| 243 | * cpuset_buffer_lock protects both the cpuset_name and cpuset_nodelist | ||
| 244 | * buffers. They are statically allocated to prevent using excess stack | ||
| 245 | * when calling cpuset_print_task_mems_allowed(). | ||
| 246 | */ | ||
| 247 | #define CPUSET_NAME_LEN (128) | ||
| 248 | #define CPUSET_NODELIST_LEN (256) | ||
| 249 | static char cpuset_name[CPUSET_NAME_LEN]; | ||
| 250 | static char cpuset_nodelist[CPUSET_NODELIST_LEN]; | ||
| 251 | static DEFINE_SPINLOCK(cpuset_buffer_lock); | ||
| 252 | |||
| 253 | /* | ||
| 243 | * This is ugly, but preserves the userspace API for existing cpuset | 254 | * This is ugly, but preserves the userspace API for existing cpuset |
| 244 | * users. If someone tries to mount the "cpuset" filesystem, we | 255 | * users. If someone tries to mount the "cpuset" filesystem, we |
| 245 | * silently switch it to mount "cgroup" instead | 256 | * silently switch it to mount "cgroup" instead |
| @@ -2356,6 +2367,29 @@ int cpuset_mems_allowed_intersects(const struct task_struct *tsk1, | |||
| 2356 | return nodes_intersects(tsk1->mems_allowed, tsk2->mems_allowed); | 2367 | return nodes_intersects(tsk1->mems_allowed, tsk2->mems_allowed); |
| 2357 | } | 2368 | } |
| 2358 | 2369 | ||
| 2370 | /** | ||
| 2371 | * cpuset_print_task_mems_allowed - prints task's cpuset and mems_allowed | ||
| 2372 | * @task: pointer to task_struct of some task. | ||
| 2373 | * | ||
| 2374 | * Description: Prints @task's name, cpuset name, and cached copy of its | ||
| 2375 | * mems_allowed to the kernel log. Must hold task_lock(task) to allow | ||
| 2376 | * dereferencing task_cs(task). | ||
| 2377 | */ | ||
| 2378 | void cpuset_print_task_mems_allowed(struct task_struct *tsk) | ||
| 2379 | { | ||
| 2380 | struct dentry *dentry; | ||
| 2381 | |||
| 2382 | dentry = task_cs(tsk)->css.cgroup->dentry; | ||
| 2383 | spin_lock(&cpuset_buffer_lock); | ||
| 2384 | snprintf(cpuset_name, CPUSET_NAME_LEN, | ||
| 2385 | dentry ? (const char *)dentry->d_name.name : "/"); | ||
| 2386 | nodelist_scnprintf(cpuset_nodelist, CPUSET_NODELIST_LEN, | ||
| 2387 | tsk->mems_allowed); | ||
| 2388 | printk(KERN_INFO "%s cpuset=%s mems_allowed=%s\n", | ||
| 2389 | tsk->comm, cpuset_name, cpuset_nodelist); | ||
| 2390 | spin_unlock(&cpuset_buffer_lock); | ||
| 2391 | } | ||
| 2392 | |||
| 2359 | /* | 2393 | /* |
| 2360 | * Collection of memory_pressure is suppressed unless | 2394 | * Collection of memory_pressure is suppressed unless |
| 2361 | * this flag is enabled by writing "1" to the special | 2395 | * this flag is enabled by writing "1" to the special |
diff --git a/kernel/dma-coherent.c b/kernel/dma-coherent.c index f013a0c2e111..038707404b76 100644 --- a/kernel/dma-coherent.c +++ b/kernel/dma-coherent.c | |||
| @@ -109,20 +109,40 @@ EXPORT_SYMBOL(dma_mark_declared_memory_occupied); | |||
| 109 | int dma_alloc_from_coherent(struct device *dev, ssize_t size, | 109 | int dma_alloc_from_coherent(struct device *dev, ssize_t size, |
| 110 | dma_addr_t *dma_handle, void **ret) | 110 | dma_addr_t *dma_handle, void **ret) |
| 111 | { | 111 | { |
| 112 | struct dma_coherent_mem *mem = dev ? dev->dma_mem : NULL; | 112 | struct dma_coherent_mem *mem; |
| 113 | int order = get_order(size); | 113 | int order = get_order(size); |
| 114 | int pageno; | ||
| 114 | 115 | ||
| 115 | if (mem) { | 116 | if (!dev) |
| 116 | int page = bitmap_find_free_region(mem->bitmap, mem->size, | 117 | return 0; |
| 117 | order); | 118 | mem = dev->dma_mem; |
| 118 | if (page >= 0) { | 119 | if (!mem) |
| 119 | *dma_handle = mem->device_base + (page << PAGE_SHIFT); | 120 | return 0; |
| 120 | *ret = mem->virt_base + (page << PAGE_SHIFT); | 121 | if (unlikely(size > mem->size)) |
| 121 | memset(*ret, 0, size); | 122 | return 0; |
| 122 | } else if (mem->flags & DMA_MEMORY_EXCLUSIVE) | 123 | |
| 123 | *ret = NULL; | 124 | pageno = bitmap_find_free_region(mem->bitmap, mem->size, order); |
| 125 | if (pageno >= 0) { | ||
| 126 | /* | ||
| 127 | * Memory was found in the per-device arena. | ||
| 128 | */ | ||
| 129 | *dma_handle = mem->device_base + (pageno << PAGE_SHIFT); | ||
| 130 | *ret = mem->virt_base + (pageno << PAGE_SHIFT); | ||
| 131 | memset(*ret, 0, size); | ||
| 132 | } else if (mem->flags & DMA_MEMORY_EXCLUSIVE) { | ||
| 133 | /* | ||
| 134 | * The per-device arena is exhausted and we are not | ||
| 135 | * permitted to fall back to generic memory. | ||
| 136 | */ | ||
| 137 | *ret = NULL; | ||
| 138 | } else { | ||
| 139 | /* | ||
| 140 | * The per-device arena is exhausted and we are | ||
| 141 | * permitted to fall back to generic memory. | ||
| 142 | */ | ||
| 143 | return 0; | ||
| 124 | } | 144 | } |
| 125 | return (mem != NULL); | 145 | return 1; |
| 126 | } | 146 | } |
| 127 | EXPORT_SYMBOL(dma_alloc_from_coherent); | 147 | EXPORT_SYMBOL(dma_alloc_from_coherent); |
| 128 | 148 | ||
diff --git a/kernel/exit.c b/kernel/exit.c index c9e5a1c14e08..c7740fa3252c 100644 --- a/kernel/exit.c +++ b/kernel/exit.c | |||
| @@ -642,35 +642,31 @@ retry: | |||
| 642 | /* | 642 | /* |
| 643 | * We found no owner yet mm_users > 1: this implies that we are | 643 | * We found no owner yet mm_users > 1: this implies that we are |
| 644 | * most likely racing with swapoff (try_to_unuse()) or /proc or | 644 | * most likely racing with swapoff (try_to_unuse()) or /proc or |
| 645 | * ptrace or page migration (get_task_mm()). Mark owner as NULL, | 645 | * ptrace or page migration (get_task_mm()). Mark owner as NULL. |
| 646 | * so that subsystems can understand the callback and take action. | ||
| 647 | */ | 646 | */ |
| 648 | down_write(&mm->mmap_sem); | ||
| 649 | cgroup_mm_owner_callbacks(mm->owner, NULL); | ||
| 650 | mm->owner = NULL; | 647 | mm->owner = NULL; |
| 651 | up_write(&mm->mmap_sem); | ||
| 652 | return; | 648 | return; |
| 653 | 649 | ||
| 654 | assign_new_owner: | 650 | assign_new_owner: |
| 655 | BUG_ON(c == p); | 651 | BUG_ON(c == p); |
| 656 | get_task_struct(c); | 652 | get_task_struct(c); |
| 657 | read_unlock(&tasklist_lock); | ||
| 658 | down_write(&mm->mmap_sem); | ||
| 659 | /* | 653 | /* |
| 660 | * The task_lock protects c->mm from changing. | 654 | * The task_lock protects c->mm from changing. |
| 661 | * We always want mm->owner->mm == mm | 655 | * We always want mm->owner->mm == mm |
| 662 | */ | 656 | */ |
| 663 | task_lock(c); | 657 | task_lock(c); |
| 658 | /* | ||
| 659 | * Delay read_unlock() till we have the task_lock() | ||
| 660 | * to ensure that c does not slip away underneath us | ||
| 661 | */ | ||
| 662 | read_unlock(&tasklist_lock); | ||
| 664 | if (c->mm != mm) { | 663 | if (c->mm != mm) { |
| 665 | task_unlock(c); | 664 | task_unlock(c); |
| 666 | up_write(&mm->mmap_sem); | ||
| 667 | put_task_struct(c); | 665 | put_task_struct(c); |
| 668 | goto retry; | 666 | goto retry; |
| 669 | } | 667 | } |
| 670 | cgroup_mm_owner_callbacks(mm->owner, c); | ||
| 671 | mm->owner = c; | 668 | mm->owner = c; |
| 672 | task_unlock(c); | 669 | task_unlock(c); |
| 673 | up_write(&mm->mmap_sem); | ||
| 674 | put_task_struct(c); | 670 | put_task_struct(c); |
| 675 | } | 671 | } |
| 676 | #endif /* CONFIG_MM_OWNER */ | 672 | #endif /* CONFIG_MM_OWNER */ |
| @@ -1055,10 +1051,7 @@ NORET_TYPE void do_exit(long code) | |||
| 1055 | preempt_count()); | 1051 | preempt_count()); |
| 1056 | 1052 | ||
| 1057 | acct_update_integrals(tsk); | 1053 | acct_update_integrals(tsk); |
| 1058 | if (tsk->mm) { | 1054 | |
| 1059 | update_hiwater_rss(tsk->mm); | ||
| 1060 | update_hiwater_vm(tsk->mm); | ||
| 1061 | } | ||
| 1062 | group_dead = atomic_dec_and_test(&tsk->signal->live); | 1055 | group_dead = atomic_dec_and_test(&tsk->signal->live); |
| 1063 | if (group_dead) { | 1056 | if (group_dead) { |
| 1064 | hrtimer_cancel(&tsk->signal->real_timer); | 1057 | hrtimer_cancel(&tsk->signal->real_timer); |
diff --git a/kernel/fork.c b/kernel/fork.c index 43cbf30669e6..7b8f2a78be3d 100644 --- a/kernel/fork.c +++ b/kernel/fork.c | |||
| @@ -400,6 +400,18 @@ __cacheline_aligned_in_smp DEFINE_SPINLOCK(mmlist_lock); | |||
| 400 | #define allocate_mm() (kmem_cache_alloc(mm_cachep, GFP_KERNEL)) | 400 | #define allocate_mm() (kmem_cache_alloc(mm_cachep, GFP_KERNEL)) |
| 401 | #define free_mm(mm) (kmem_cache_free(mm_cachep, (mm))) | 401 | #define free_mm(mm) (kmem_cache_free(mm_cachep, (mm))) |
| 402 | 402 | ||
| 403 | static unsigned long default_dump_filter = MMF_DUMP_FILTER_DEFAULT; | ||
| 404 | |||
| 405 | static int __init coredump_filter_setup(char *s) | ||
| 406 | { | ||
| 407 | default_dump_filter = | ||
| 408 | (simple_strtoul(s, NULL, 0) << MMF_DUMP_FILTER_SHIFT) & | ||
| 409 | MMF_DUMP_FILTER_MASK; | ||
| 410 | return 1; | ||
| 411 | } | ||
| 412 | |||
| 413 | __setup("coredump_filter=", coredump_filter_setup); | ||
| 414 | |||
| 403 | #include <linux/init_task.h> | 415 | #include <linux/init_task.h> |
| 404 | 416 | ||
| 405 | static struct mm_struct * mm_init(struct mm_struct * mm, struct task_struct *p) | 417 | 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) | |||
| 408 | atomic_set(&mm->mm_count, 1); | 420 | atomic_set(&mm->mm_count, 1); |
| 409 | init_rwsem(&mm->mmap_sem); | 421 | init_rwsem(&mm->mmap_sem); |
| 410 | INIT_LIST_HEAD(&mm->mmlist); | 422 | INIT_LIST_HEAD(&mm->mmlist); |
| 411 | mm->flags = (current->mm) ? current->mm->flags | 423 | mm->flags = (current->mm) ? current->mm->flags : default_dump_filter; |
| 412 | : MMF_DUMP_FILTER_DEFAULT; | ||
| 413 | mm->core_state = NULL; | 424 | mm->core_state = NULL; |
| 414 | mm->nr_ptes = 0; | 425 | mm->nr_ptes = 0; |
| 415 | set_mm_counter(mm, file_rss, 0); | 426 | set_mm_counter(mm, file_rss, 0); |
| @@ -758,7 +769,7 @@ static int copy_sighand(unsigned long clone_flags, struct task_struct *tsk) | |||
| 758 | { | 769 | { |
| 759 | struct sighand_struct *sig; | 770 | struct sighand_struct *sig; |
| 760 | 771 | ||
| 761 | if (clone_flags & (CLONE_SIGHAND | CLONE_THREAD)) { | 772 | if (clone_flags & CLONE_SIGHAND) { |
| 762 | atomic_inc(¤t->sighand->count); | 773 | atomic_inc(¤t->sighand->count); |
| 763 | return 0; | 774 | return 0; |
| 764 | } | 775 | } |
diff --git a/kernel/kmod.c b/kernel/kmod.c index b46dbb908669..a27a5f64443d 100644 --- a/kernel/kmod.c +++ b/kernel/kmod.c | |||
| @@ -51,8 +51,8 @@ char modprobe_path[KMOD_PATH_LEN] = "/sbin/modprobe"; | |||
| 51 | 51 | ||
| 52 | /** | 52 | /** |
| 53 | * request_module - try to load a kernel module | 53 | * request_module - try to load a kernel module |
| 54 | * @fmt: printf style format string for the name of the module | 54 | * @fmt: printf style format string for the name of the module |
| 55 | * @varargs: arguements as specified in the format string | 55 | * @...: arguments as specified in the format string |
| 56 | * | 56 | * |
| 57 | * Load a module using the user mode module loader. The function returns | 57 | * Load a module using the user mode module loader. The function returns |
| 58 | * zero on success or a negative errno code on failure. Note that a | 58 | * zero on success or a negative errno code on failure. Note that a |
diff --git a/kernel/kprobes.c b/kernel/kprobes.c index 9f8a3f25259a..1b9cbdc0127a 100644 --- a/kernel/kprobes.c +++ b/kernel/kprobes.c | |||
| @@ -69,7 +69,7 @@ static struct hlist_head kretprobe_inst_table[KPROBE_TABLE_SIZE]; | |||
| 69 | /* NOTE: change this value only with kprobe_mutex held */ | 69 | /* NOTE: change this value only with kprobe_mutex held */ |
| 70 | static bool kprobe_enabled; | 70 | static bool kprobe_enabled; |
| 71 | 71 | ||
| 72 | DEFINE_MUTEX(kprobe_mutex); /* Protects kprobe_table */ | 72 | static DEFINE_MUTEX(kprobe_mutex); /* Protects kprobe_table */ |
| 73 | static DEFINE_PER_CPU(struct kprobe *, kprobe_instance) = NULL; | 73 | static DEFINE_PER_CPU(struct kprobe *, kprobe_instance) = NULL; |
| 74 | static struct { | 74 | static struct { |
| 75 | spinlock_t lock ____cacheline_aligned_in_smp; | 75 | spinlock_t lock ____cacheline_aligned_in_smp; |
| @@ -115,6 +115,7 @@ enum kprobe_slot_state { | |||
| 115 | SLOT_USED = 2, | 115 | SLOT_USED = 2, |
| 116 | }; | 116 | }; |
| 117 | 117 | ||
| 118 | static DEFINE_MUTEX(kprobe_insn_mutex); /* Protects kprobe_insn_pages */ | ||
| 118 | static struct hlist_head kprobe_insn_pages; | 119 | static struct hlist_head kprobe_insn_pages; |
| 119 | static int kprobe_garbage_slots; | 120 | static int kprobe_garbage_slots; |
| 120 | static int collect_garbage_slots(void); | 121 | static int collect_garbage_slots(void); |
| @@ -144,10 +145,10 @@ loop_end: | |||
| 144 | } | 145 | } |
| 145 | 146 | ||
| 146 | /** | 147 | /** |
| 147 | * get_insn_slot() - Find a slot on an executable page for an instruction. | 148 | * __get_insn_slot() - Find a slot on an executable page for an instruction. |
| 148 | * We allocate an executable page if there's no room on existing ones. | 149 | * We allocate an executable page if there's no room on existing ones. |
| 149 | */ | 150 | */ |
| 150 | kprobe_opcode_t __kprobes *get_insn_slot(void) | 151 | static kprobe_opcode_t __kprobes *__get_insn_slot(void) |
| 151 | { | 152 | { |
| 152 | struct kprobe_insn_page *kip; | 153 | struct kprobe_insn_page *kip; |
| 153 | struct hlist_node *pos; | 154 | struct hlist_node *pos; |
| @@ -196,6 +197,15 @@ kprobe_opcode_t __kprobes *get_insn_slot(void) | |||
| 196 | return kip->insns; | 197 | return kip->insns; |
| 197 | } | 198 | } |
| 198 | 199 | ||
| 200 | kprobe_opcode_t __kprobes *get_insn_slot(void) | ||
| 201 | { | ||
| 202 | kprobe_opcode_t *ret; | ||
| 203 | mutex_lock(&kprobe_insn_mutex); | ||
| 204 | ret = __get_insn_slot(); | ||
| 205 | mutex_unlock(&kprobe_insn_mutex); | ||
| 206 | return ret; | ||
| 207 | } | ||
| 208 | |||
| 199 | /* Return 1 if all garbages are collected, otherwise 0. */ | 209 | /* Return 1 if all garbages are collected, otherwise 0. */ |
| 200 | static int __kprobes collect_one_slot(struct kprobe_insn_page *kip, int idx) | 210 | static int __kprobes collect_one_slot(struct kprobe_insn_page *kip, int idx) |
| 201 | { | 211 | { |
| @@ -226,9 +236,13 @@ static int __kprobes collect_garbage_slots(void) | |||
| 226 | { | 236 | { |
| 227 | struct kprobe_insn_page *kip; | 237 | struct kprobe_insn_page *kip; |
| 228 | struct hlist_node *pos, *next; | 238 | struct hlist_node *pos, *next; |
| 239 | int safety; | ||
| 229 | 240 | ||
| 230 | /* Ensure no-one is preepmted on the garbages */ | 241 | /* Ensure no-one is preepmted on the garbages */ |
| 231 | if (check_safety() != 0) | 242 | mutex_unlock(&kprobe_insn_mutex); |
| 243 | safety = check_safety(); | ||
| 244 | mutex_lock(&kprobe_insn_mutex); | ||
| 245 | if (safety != 0) | ||
| 232 | return -EAGAIN; | 246 | return -EAGAIN; |
| 233 | 247 | ||
| 234 | hlist_for_each_entry_safe(kip, pos, next, &kprobe_insn_pages, hlist) { | 248 | 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) | |||
| 251 | struct kprobe_insn_page *kip; | 265 | struct kprobe_insn_page *kip; |
| 252 | struct hlist_node *pos; | 266 | struct hlist_node *pos; |
| 253 | 267 | ||
| 268 | mutex_lock(&kprobe_insn_mutex); | ||
| 254 | hlist_for_each_entry(kip, pos, &kprobe_insn_pages, hlist) { | 269 | hlist_for_each_entry(kip, pos, &kprobe_insn_pages, hlist) { |
| 255 | if (kip->insns <= slot && | 270 | if (kip->insns <= slot && |
| 256 | slot < kip->insns + (INSNS_PER_PAGE * MAX_INSN_SIZE)) { | 271 | slot < kip->insns + (INSNS_PER_PAGE * MAX_INSN_SIZE)) { |
| @@ -267,6 +282,8 @@ void __kprobes free_insn_slot(kprobe_opcode_t * slot, int dirty) | |||
| 267 | 282 | ||
| 268 | if (dirty && ++kprobe_garbage_slots > INSNS_PER_PAGE) | 283 | if (dirty && ++kprobe_garbage_slots > INSNS_PER_PAGE) |
| 269 | collect_garbage_slots(); | 284 | collect_garbage_slots(); |
| 285 | |||
| 286 | mutex_unlock(&kprobe_insn_mutex); | ||
| 270 | } | 287 | } |
| 271 | #endif | 288 | #endif |
| 272 | 289 | ||
| @@ -310,7 +327,7 @@ static int __kprobes aggr_pre_handler(struct kprobe *p, struct pt_regs *regs) | |||
| 310 | struct kprobe *kp; | 327 | struct kprobe *kp; |
| 311 | 328 | ||
| 312 | list_for_each_entry_rcu(kp, &p->list, list) { | 329 | list_for_each_entry_rcu(kp, &p->list, list) { |
| 313 | if (kp->pre_handler) { | 330 | if (kp->pre_handler && !kprobe_gone(kp)) { |
| 314 | set_kprobe_instance(kp); | 331 | set_kprobe_instance(kp); |
| 315 | if (kp->pre_handler(kp, regs)) | 332 | if (kp->pre_handler(kp, regs)) |
| 316 | return 1; | 333 | return 1; |
| @@ -326,7 +343,7 @@ static void __kprobes aggr_post_handler(struct kprobe *p, struct pt_regs *regs, | |||
| 326 | struct kprobe *kp; | 343 | struct kprobe *kp; |
| 327 | 344 | ||
| 328 | list_for_each_entry_rcu(kp, &p->list, list) { | 345 | list_for_each_entry_rcu(kp, &p->list, list) { |
| 329 | if (kp->post_handler) { | 346 | if (kp->post_handler && !kprobe_gone(kp)) { |
| 330 | set_kprobe_instance(kp); | 347 | set_kprobe_instance(kp); |
| 331 | kp->post_handler(kp, regs, flags); | 348 | kp->post_handler(kp, regs, flags); |
| 332 | reset_kprobe_instance(); | 349 | reset_kprobe_instance(); |
| @@ -393,7 +410,7 @@ void __kprobes recycle_rp_inst(struct kretprobe_instance *ri, | |||
| 393 | hlist_add_head(&ri->hlist, head); | 410 | hlist_add_head(&ri->hlist, head); |
| 394 | } | 411 | } |
| 395 | 412 | ||
| 396 | void kretprobe_hash_lock(struct task_struct *tsk, | 413 | void __kprobes kretprobe_hash_lock(struct task_struct *tsk, |
| 397 | struct hlist_head **head, unsigned long *flags) | 414 | struct hlist_head **head, unsigned long *flags) |
| 398 | { | 415 | { |
| 399 | unsigned long hash = hash_ptr(tsk, KPROBE_HASH_BITS); | 416 | unsigned long hash = hash_ptr(tsk, KPROBE_HASH_BITS); |
| @@ -404,13 +421,15 @@ void kretprobe_hash_lock(struct task_struct *tsk, | |||
| 404 | spin_lock_irqsave(hlist_lock, *flags); | 421 | spin_lock_irqsave(hlist_lock, *flags); |
| 405 | } | 422 | } |
| 406 | 423 | ||
| 407 | static void kretprobe_table_lock(unsigned long hash, unsigned long *flags) | 424 | static void __kprobes kretprobe_table_lock(unsigned long hash, |
| 425 | unsigned long *flags) | ||
| 408 | { | 426 | { |
| 409 | spinlock_t *hlist_lock = kretprobe_table_lock_ptr(hash); | 427 | spinlock_t *hlist_lock = kretprobe_table_lock_ptr(hash); |
| 410 | spin_lock_irqsave(hlist_lock, *flags); | 428 | spin_lock_irqsave(hlist_lock, *flags); |
| 411 | } | 429 | } |
| 412 | 430 | ||
| 413 | void kretprobe_hash_unlock(struct task_struct *tsk, unsigned long *flags) | 431 | void __kprobes kretprobe_hash_unlock(struct task_struct *tsk, |
| 432 | unsigned long *flags) | ||
| 414 | { | 433 | { |
| 415 | unsigned long hash = hash_ptr(tsk, KPROBE_HASH_BITS); | 434 | unsigned long hash = hash_ptr(tsk, KPROBE_HASH_BITS); |
| 416 | spinlock_t *hlist_lock; | 435 | spinlock_t *hlist_lock; |
| @@ -419,7 +438,7 @@ void kretprobe_hash_unlock(struct task_struct *tsk, unsigned long *flags) | |||
| 419 | spin_unlock_irqrestore(hlist_lock, *flags); | 438 | spin_unlock_irqrestore(hlist_lock, *flags); |
| 420 | } | 439 | } |
| 421 | 440 | ||
| 422 | void kretprobe_table_unlock(unsigned long hash, unsigned long *flags) | 441 | void __kprobes kretprobe_table_unlock(unsigned long hash, unsigned long *flags) |
| 423 | { | 442 | { |
| 424 | spinlock_t *hlist_lock = kretprobe_table_lock_ptr(hash); | 443 | spinlock_t *hlist_lock = kretprobe_table_lock_ptr(hash); |
| 425 | spin_unlock_irqrestore(hlist_lock, *flags); | 444 | spin_unlock_irqrestore(hlist_lock, *flags); |
| @@ -526,9 +545,10 @@ static inline void add_aggr_kprobe(struct kprobe *ap, struct kprobe *p) | |||
| 526 | ap->addr = p->addr; | 545 | ap->addr = p->addr; |
| 527 | ap->pre_handler = aggr_pre_handler; | 546 | ap->pre_handler = aggr_pre_handler; |
| 528 | ap->fault_handler = aggr_fault_handler; | 547 | ap->fault_handler = aggr_fault_handler; |
| 529 | if (p->post_handler) | 548 | /* We don't care the kprobe which has gone. */ |
| 549 | if (p->post_handler && !kprobe_gone(p)) | ||
| 530 | ap->post_handler = aggr_post_handler; | 550 | ap->post_handler = aggr_post_handler; |
| 531 | if (p->break_handler) | 551 | if (p->break_handler && !kprobe_gone(p)) |
| 532 | ap->break_handler = aggr_break_handler; | 552 | ap->break_handler = aggr_break_handler; |
| 533 | 553 | ||
| 534 | INIT_LIST_HEAD(&ap->list); | 554 | INIT_LIST_HEAD(&ap->list); |
| @@ -547,17 +567,41 @@ static int __kprobes register_aggr_kprobe(struct kprobe *old_p, | |||
| 547 | int ret = 0; | 567 | int ret = 0; |
| 548 | struct kprobe *ap; | 568 | struct kprobe *ap; |
| 549 | 569 | ||
| 570 | if (kprobe_gone(old_p)) { | ||
| 571 | /* | ||
| 572 | * Attempting to insert new probe at the same location that | ||
| 573 | * had a probe in the module vaddr area which already | ||
| 574 | * freed. So, the instruction slot has already been | ||
| 575 | * released. We need a new slot for the new probe. | ||
| 576 | */ | ||
| 577 | ret = arch_prepare_kprobe(old_p); | ||
| 578 | if (ret) | ||
| 579 | return ret; | ||
| 580 | } | ||
| 550 | if (old_p->pre_handler == aggr_pre_handler) { | 581 | if (old_p->pre_handler == aggr_pre_handler) { |
| 551 | copy_kprobe(old_p, p); | 582 | copy_kprobe(old_p, p); |
| 552 | ret = add_new_kprobe(old_p, p); | 583 | ret = add_new_kprobe(old_p, p); |
| 584 | ap = old_p; | ||
| 553 | } else { | 585 | } else { |
| 554 | ap = kzalloc(sizeof(struct kprobe), GFP_KERNEL); | 586 | ap = kzalloc(sizeof(struct kprobe), GFP_KERNEL); |
| 555 | if (!ap) | 587 | if (!ap) { |
| 588 | if (kprobe_gone(old_p)) | ||
| 589 | arch_remove_kprobe(old_p); | ||
| 556 | return -ENOMEM; | 590 | return -ENOMEM; |
| 591 | } | ||
| 557 | add_aggr_kprobe(ap, old_p); | 592 | add_aggr_kprobe(ap, old_p); |
| 558 | copy_kprobe(ap, p); | 593 | copy_kprobe(ap, p); |
| 559 | ret = add_new_kprobe(ap, p); | 594 | ret = add_new_kprobe(ap, p); |
| 560 | } | 595 | } |
| 596 | if (kprobe_gone(old_p)) { | ||
| 597 | /* | ||
| 598 | * If the old_p has gone, its breakpoint has been disarmed. | ||
| 599 | * We have to arm it again after preparing real kprobes. | ||
| 600 | */ | ||
| 601 | ap->flags &= ~KPROBE_FLAG_GONE; | ||
| 602 | if (kprobe_enabled) | ||
| 603 | arch_arm_kprobe(ap); | ||
| 604 | } | ||
| 561 | return ret; | 605 | return ret; |
| 562 | } | 606 | } |
| 563 | 607 | ||
| @@ -600,8 +644,7 @@ static kprobe_opcode_t __kprobes *kprobe_addr(struct kprobe *p) | |||
| 600 | return (kprobe_opcode_t *)(((char *)addr) + p->offset); | 644 | return (kprobe_opcode_t *)(((char *)addr) + p->offset); |
| 601 | } | 645 | } |
| 602 | 646 | ||
| 603 | static int __kprobes __register_kprobe(struct kprobe *p, | 647 | int __kprobes register_kprobe(struct kprobe *p) |
| 604 | unsigned long called_from) | ||
| 605 | { | 648 | { |
| 606 | int ret = 0; | 649 | int ret = 0; |
| 607 | struct kprobe *old_p; | 650 | struct kprobe *old_p; |
| @@ -620,28 +663,30 @@ static int __kprobes __register_kprobe(struct kprobe *p, | |||
| 620 | return -EINVAL; | 663 | return -EINVAL; |
| 621 | } | 664 | } |
| 622 | 665 | ||
| 623 | p->mod_refcounted = 0; | 666 | p->flags = 0; |
| 624 | |||
| 625 | /* | 667 | /* |
| 626 | * Check if are we probing a module. | 668 | * Check if are we probing a module. |
| 627 | */ | 669 | */ |
| 628 | probed_mod = __module_text_address((unsigned long) p->addr); | 670 | probed_mod = __module_text_address((unsigned long) p->addr); |
| 629 | if (probed_mod) { | 671 | if (probed_mod) { |
| 630 | struct module *calling_mod; | ||
| 631 | calling_mod = __module_text_address(called_from); | ||
| 632 | /* | 672 | /* |
| 633 | * We must allow modules to probe themself and in this case | 673 | * We must hold a refcount of the probed module while updating |
| 634 | * avoid incrementing the module refcount, so as to allow | 674 | * its code to prohibit unexpected unloading. |
| 635 | * unloading of self probing modules. | ||
| 636 | */ | 675 | */ |
| 637 | if (calling_mod && calling_mod != probed_mod) { | 676 | if (unlikely(!try_module_get(probed_mod))) { |
| 638 | if (unlikely(!try_module_get(probed_mod))) { | 677 | preempt_enable(); |
| 639 | preempt_enable(); | 678 | return -EINVAL; |
| 640 | return -EINVAL; | 679 | } |
| 641 | } | 680 | /* |
| 642 | p->mod_refcounted = 1; | 681 | * If the module freed .init.text, we couldn't insert |
| 643 | } else | 682 | * kprobes in there. |
| 644 | probed_mod = NULL; | 683 | */ |
| 684 | if (within_module_init((unsigned long)p->addr, probed_mod) && | ||
| 685 | probed_mod->state != MODULE_STATE_COMING) { | ||
| 686 | module_put(probed_mod); | ||
| 687 | preempt_enable(); | ||
| 688 | return -EINVAL; | ||
| 689 | } | ||
| 645 | } | 690 | } |
| 646 | preempt_enable(); | 691 | preempt_enable(); |
| 647 | 692 | ||
| @@ -668,8 +713,9 @@ static int __kprobes __register_kprobe(struct kprobe *p, | |||
| 668 | out: | 713 | out: |
| 669 | mutex_unlock(&kprobe_mutex); | 714 | mutex_unlock(&kprobe_mutex); |
| 670 | 715 | ||
| 671 | if (ret && probed_mod) | 716 | if (probed_mod) |
| 672 | module_put(probed_mod); | 717 | module_put(probed_mod); |
| 718 | |||
| 673 | return ret; | 719 | return ret; |
| 674 | } | 720 | } |
| 675 | 721 | ||
| @@ -697,16 +743,16 @@ valid_p: | |||
| 697 | list_is_singular(&old_p->list))) { | 743 | list_is_singular(&old_p->list))) { |
| 698 | /* | 744 | /* |
| 699 | * Only probe on the hash list. Disarm only if kprobes are | 745 | * Only probe on the hash list. Disarm only if kprobes are |
| 700 | * enabled - otherwise, the breakpoint would already have | 746 | * enabled and not gone - otherwise, the breakpoint would |
| 701 | * been removed. We save on flushing icache. | 747 | * already have been removed. We save on flushing icache. |
| 702 | */ | 748 | */ |
| 703 | if (kprobe_enabled) | 749 | if (kprobe_enabled && !kprobe_gone(old_p)) |
| 704 | arch_disarm_kprobe(p); | 750 | arch_disarm_kprobe(p); |
| 705 | hlist_del_rcu(&old_p->hlist); | 751 | hlist_del_rcu(&old_p->hlist); |
| 706 | } else { | 752 | } else { |
| 707 | if (p->break_handler) | 753 | if (p->break_handler && !kprobe_gone(p)) |
| 708 | old_p->break_handler = NULL; | 754 | old_p->break_handler = NULL; |
| 709 | if (p->post_handler) { | 755 | if (p->post_handler && !kprobe_gone(p)) { |
| 710 | list_for_each_entry_rcu(list_p, &old_p->list, list) { | 756 | list_for_each_entry_rcu(list_p, &old_p->list, list) { |
| 711 | if ((list_p != p) && (list_p->post_handler)) | 757 | if ((list_p != p) && (list_p->post_handler)) |
| 712 | goto noclean; | 758 | goto noclean; |
| @@ -721,39 +767,27 @@ noclean: | |||
| 721 | 767 | ||
| 722 | static void __kprobes __unregister_kprobe_bottom(struct kprobe *p) | 768 | static void __kprobes __unregister_kprobe_bottom(struct kprobe *p) |
| 723 | { | 769 | { |
| 724 | struct module *mod; | ||
| 725 | struct kprobe *old_p; | 770 | struct kprobe *old_p; |
| 726 | 771 | ||
| 727 | if (p->mod_refcounted) { | 772 | if (list_empty(&p->list)) |
| 728 | /* | ||
| 729 | * Since we've already incremented refcount, | ||
| 730 | * we don't need to disable preemption. | ||
| 731 | */ | ||
| 732 | mod = module_text_address((unsigned long)p->addr); | ||
| 733 | if (mod) | ||
| 734 | module_put(mod); | ||
| 735 | } | ||
| 736 | |||
| 737 | if (list_empty(&p->list) || list_is_singular(&p->list)) { | ||
| 738 | if (!list_empty(&p->list)) { | ||
| 739 | /* "p" is the last child of an aggr_kprobe */ | ||
| 740 | old_p = list_entry(p->list.next, struct kprobe, list); | ||
| 741 | list_del(&p->list); | ||
| 742 | kfree(old_p); | ||
| 743 | } | ||
| 744 | arch_remove_kprobe(p); | 773 | arch_remove_kprobe(p); |
| 774 | else if (list_is_singular(&p->list)) { | ||
| 775 | /* "p" is the last child of an aggr_kprobe */ | ||
| 776 | old_p = list_entry(p->list.next, struct kprobe, list); | ||
| 777 | list_del(&p->list); | ||
| 778 | arch_remove_kprobe(old_p); | ||
| 779 | kfree(old_p); | ||
| 745 | } | 780 | } |
| 746 | } | 781 | } |
| 747 | 782 | ||
| 748 | static int __register_kprobes(struct kprobe **kps, int num, | 783 | int __kprobes register_kprobes(struct kprobe **kps, int num) |
| 749 | unsigned long called_from) | ||
| 750 | { | 784 | { |
| 751 | int i, ret = 0; | 785 | int i, ret = 0; |
| 752 | 786 | ||
| 753 | if (num <= 0) | 787 | if (num <= 0) |
| 754 | return -EINVAL; | 788 | return -EINVAL; |
| 755 | for (i = 0; i < num; i++) { | 789 | for (i = 0; i < num; i++) { |
| 756 | ret = __register_kprobe(kps[i], called_from); | 790 | ret = register_kprobe(kps[i]); |
| 757 | if (ret < 0) { | 791 | if (ret < 0) { |
| 758 | if (i > 0) | 792 | if (i > 0) |
| 759 | unregister_kprobes(kps, i); | 793 | unregister_kprobes(kps, i); |
| @@ -763,26 +797,11 @@ static int __register_kprobes(struct kprobe **kps, int num, | |||
| 763 | return ret; | 797 | return ret; |
| 764 | } | 798 | } |
| 765 | 799 | ||
| 766 | /* | ||
| 767 | * Registration and unregistration functions for kprobe. | ||
| 768 | */ | ||
| 769 | int __kprobes register_kprobe(struct kprobe *p) | ||
| 770 | { | ||
| 771 | return __register_kprobes(&p, 1, | ||
| 772 | (unsigned long)__builtin_return_address(0)); | ||
| 773 | } | ||
| 774 | |||
| 775 | void __kprobes unregister_kprobe(struct kprobe *p) | 800 | void __kprobes unregister_kprobe(struct kprobe *p) |
| 776 | { | 801 | { |
| 777 | unregister_kprobes(&p, 1); | 802 | unregister_kprobes(&p, 1); |
| 778 | } | 803 | } |
| 779 | 804 | ||
| 780 | int __kprobes register_kprobes(struct kprobe **kps, int num) | ||
| 781 | { | ||
| 782 | return __register_kprobes(kps, num, | ||
| 783 | (unsigned long)__builtin_return_address(0)); | ||
| 784 | } | ||
| 785 | |||
| 786 | void __kprobes unregister_kprobes(struct kprobe **kps, int num) | 805 | void __kprobes unregister_kprobes(struct kprobe **kps, int num) |
| 787 | { | 806 | { |
| 788 | int i; | 807 | int i; |
| @@ -811,8 +830,7 @@ unsigned long __weak arch_deref_entry_point(void *entry) | |||
| 811 | return (unsigned long)entry; | 830 | return (unsigned long)entry; |
| 812 | } | 831 | } |
| 813 | 832 | ||
| 814 | static int __register_jprobes(struct jprobe **jps, int num, | 833 | int __kprobes register_jprobes(struct jprobe **jps, int num) |
| 815 | unsigned long called_from) | ||
| 816 | { | 834 | { |
| 817 | struct jprobe *jp; | 835 | struct jprobe *jp; |
| 818 | int ret = 0, i; | 836 | int ret = 0, i; |
| @@ -830,7 +848,7 @@ static int __register_jprobes(struct jprobe **jps, int num, | |||
| 830 | /* Todo: Verify probepoint is a function entry point */ | 848 | /* Todo: Verify probepoint is a function entry point */ |
| 831 | jp->kp.pre_handler = setjmp_pre_handler; | 849 | jp->kp.pre_handler = setjmp_pre_handler; |
| 832 | jp->kp.break_handler = longjmp_break_handler; | 850 | jp->kp.break_handler = longjmp_break_handler; |
| 833 | ret = __register_kprobe(&jp->kp, called_from); | 851 | ret = register_kprobe(&jp->kp); |
| 834 | } | 852 | } |
| 835 | if (ret < 0) { | 853 | if (ret < 0) { |
| 836 | if (i > 0) | 854 | if (i > 0) |
| @@ -843,8 +861,7 @@ static int __register_jprobes(struct jprobe **jps, int num, | |||
| 843 | 861 | ||
| 844 | int __kprobes register_jprobe(struct jprobe *jp) | 862 | int __kprobes register_jprobe(struct jprobe *jp) |
| 845 | { | 863 | { |
| 846 | return __register_jprobes(&jp, 1, | 864 | return register_jprobes(&jp, 1); |
| 847 | (unsigned long)__builtin_return_address(0)); | ||
| 848 | } | 865 | } |
| 849 | 866 | ||
| 850 | void __kprobes unregister_jprobe(struct jprobe *jp) | 867 | void __kprobes unregister_jprobe(struct jprobe *jp) |
| @@ -852,12 +869,6 @@ void __kprobes unregister_jprobe(struct jprobe *jp) | |||
| 852 | unregister_jprobes(&jp, 1); | 869 | unregister_jprobes(&jp, 1); |
| 853 | } | 870 | } |
| 854 | 871 | ||
| 855 | int __kprobes register_jprobes(struct jprobe **jps, int num) | ||
| 856 | { | ||
| 857 | return __register_jprobes(jps, num, | ||
| 858 | (unsigned long)__builtin_return_address(0)); | ||
| 859 | } | ||
| 860 | |||
| 861 | void __kprobes unregister_jprobes(struct jprobe **jps, int num) | 872 | void __kprobes unregister_jprobes(struct jprobe **jps, int num) |
| 862 | { | 873 | { |
| 863 | int i; | 874 | int i; |
| @@ -920,8 +931,7 @@ static int __kprobes pre_handler_kretprobe(struct kprobe *p, | |||
| 920 | return 0; | 931 | return 0; |
| 921 | } | 932 | } |
| 922 | 933 | ||
| 923 | static int __kprobes __register_kretprobe(struct kretprobe *rp, | 934 | int __kprobes register_kretprobe(struct kretprobe *rp) |
| 924 | unsigned long called_from) | ||
| 925 | { | 935 | { |
| 926 | int ret = 0; | 936 | int ret = 0; |
| 927 | struct kretprobe_instance *inst; | 937 | struct kretprobe_instance *inst; |
| @@ -967,21 +977,20 @@ static int __kprobes __register_kretprobe(struct kretprobe *rp, | |||
| 967 | 977 | ||
| 968 | rp->nmissed = 0; | 978 | rp->nmissed = 0; |
| 969 | /* Establish function entry probe point */ | 979 | /* Establish function entry probe point */ |
| 970 | ret = __register_kprobe(&rp->kp, called_from); | 980 | ret = register_kprobe(&rp->kp); |
| 971 | if (ret != 0) | 981 | if (ret != 0) |
| 972 | free_rp_inst(rp); | 982 | free_rp_inst(rp); |
| 973 | return ret; | 983 | return ret; |
| 974 | } | 984 | } |
| 975 | 985 | ||
| 976 | static int __register_kretprobes(struct kretprobe **rps, int num, | 986 | int __kprobes register_kretprobes(struct kretprobe **rps, int num) |
| 977 | unsigned long called_from) | ||
| 978 | { | 987 | { |
| 979 | int ret = 0, i; | 988 | int ret = 0, i; |
| 980 | 989 | ||
| 981 | if (num <= 0) | 990 | if (num <= 0) |
| 982 | return -EINVAL; | 991 | return -EINVAL; |
| 983 | for (i = 0; i < num; i++) { | 992 | for (i = 0; i < num; i++) { |
| 984 | ret = __register_kretprobe(rps[i], called_from); | 993 | ret = register_kretprobe(rps[i]); |
| 985 | if (ret < 0) { | 994 | if (ret < 0) { |
| 986 | if (i > 0) | 995 | if (i > 0) |
| 987 | unregister_kretprobes(rps, i); | 996 | unregister_kretprobes(rps, i); |
| @@ -991,23 +1000,11 @@ static int __register_kretprobes(struct kretprobe **rps, int num, | |||
| 991 | return ret; | 1000 | return ret; |
| 992 | } | 1001 | } |
| 993 | 1002 | ||
| 994 | int __kprobes register_kretprobe(struct kretprobe *rp) | ||
| 995 | { | ||
| 996 | return __register_kretprobes(&rp, 1, | ||
| 997 | (unsigned long)__builtin_return_address(0)); | ||
| 998 | } | ||
| 999 | |||
| 1000 | void __kprobes unregister_kretprobe(struct kretprobe *rp) | 1003 | void __kprobes unregister_kretprobe(struct kretprobe *rp) |
| 1001 | { | 1004 | { |
| 1002 | unregister_kretprobes(&rp, 1); | 1005 | unregister_kretprobes(&rp, 1); |
| 1003 | } | 1006 | } |
| 1004 | 1007 | ||
| 1005 | int __kprobes register_kretprobes(struct kretprobe **rps, int num) | ||
| 1006 | { | ||
| 1007 | return __register_kretprobes(rps, num, | ||
| 1008 | (unsigned long)__builtin_return_address(0)); | ||
| 1009 | } | ||
| 1010 | |||
| 1011 | void __kprobes unregister_kretprobes(struct kretprobe **rps, int num) | 1008 | void __kprobes unregister_kretprobes(struct kretprobe **rps, int num) |
| 1012 | { | 1009 | { |
| 1013 | int i; | 1010 | int i; |
| @@ -1055,6 +1052,72 @@ static int __kprobes pre_handler_kretprobe(struct kprobe *p, | |||
| 1055 | 1052 | ||
| 1056 | #endif /* CONFIG_KRETPROBES */ | 1053 | #endif /* CONFIG_KRETPROBES */ |
| 1057 | 1054 | ||
| 1055 | /* Set the kprobe gone and remove its instruction buffer. */ | ||
| 1056 | static void __kprobes kill_kprobe(struct kprobe *p) | ||
| 1057 | { | ||
| 1058 | struct kprobe *kp; | ||
| 1059 | p->flags |= KPROBE_FLAG_GONE; | ||
| 1060 | if (p->pre_handler == aggr_pre_handler) { | ||
| 1061 | /* | ||
| 1062 | * If this is an aggr_kprobe, we have to list all the | ||
| 1063 | * chained probes and mark them GONE. | ||
| 1064 | */ | ||
| 1065 | list_for_each_entry_rcu(kp, &p->list, list) | ||
| 1066 | kp->flags |= KPROBE_FLAG_GONE; | ||
| 1067 | p->post_handler = NULL; | ||
| 1068 | p->break_handler = NULL; | ||
| 1069 | } | ||
| 1070 | /* | ||
| 1071 | * Here, we can remove insn_slot safely, because no thread calls | ||
| 1072 | * the original probed function (which will be freed soon) any more. | ||
| 1073 | */ | ||
| 1074 | arch_remove_kprobe(p); | ||
| 1075 | } | ||
| 1076 | |||
| 1077 | /* Module notifier call back, checking kprobes on the module */ | ||
| 1078 | static int __kprobes kprobes_module_callback(struct notifier_block *nb, | ||
| 1079 | unsigned long val, void *data) | ||
| 1080 | { | ||
| 1081 | struct module *mod = data; | ||
| 1082 | struct hlist_head *head; | ||
| 1083 | struct hlist_node *node; | ||
| 1084 | struct kprobe *p; | ||
| 1085 | unsigned int i; | ||
| 1086 | int checkcore = (val == MODULE_STATE_GOING); | ||
| 1087 | |||
| 1088 | if (val != MODULE_STATE_GOING && val != MODULE_STATE_LIVE) | ||
| 1089 | return NOTIFY_DONE; | ||
| 1090 | |||
| 1091 | /* | ||
| 1092 | * When MODULE_STATE_GOING was notified, both of module .text and | ||
| 1093 | * .init.text sections would be freed. When MODULE_STATE_LIVE was | ||
| 1094 | * notified, only .init.text section would be freed. We need to | ||
| 1095 | * disable kprobes which have been inserted in the sections. | ||
| 1096 | */ | ||
| 1097 | mutex_lock(&kprobe_mutex); | ||
| 1098 | for (i = 0; i < KPROBE_TABLE_SIZE; i++) { | ||
| 1099 | head = &kprobe_table[i]; | ||
| 1100 | hlist_for_each_entry_rcu(p, node, head, hlist) | ||
| 1101 | if (within_module_init((unsigned long)p->addr, mod) || | ||
| 1102 | (checkcore && | ||
| 1103 | within_module_core((unsigned long)p->addr, mod))) { | ||
| 1104 | /* | ||
| 1105 | * The vaddr this probe is installed will soon | ||
| 1106 | * be vfreed buy not synced to disk. Hence, | ||
| 1107 | * disarming the breakpoint isn't needed. | ||
| 1108 | */ | ||
| 1109 | kill_kprobe(p); | ||
| 1110 | } | ||
| 1111 | } | ||
| 1112 | mutex_unlock(&kprobe_mutex); | ||
| 1113 | return NOTIFY_DONE; | ||
| 1114 | } | ||
| 1115 | |||
| 1116 | static struct notifier_block kprobe_module_nb = { | ||
| 1117 | .notifier_call = kprobes_module_callback, | ||
| 1118 | .priority = 0 | ||
| 1119 | }; | ||
| 1120 | |||
| 1058 | static int __init init_kprobes(void) | 1121 | static int __init init_kprobes(void) |
| 1059 | { | 1122 | { |
| 1060 | int i, err = 0; | 1123 | int i, err = 0; |
| @@ -1111,6 +1174,9 @@ static int __init init_kprobes(void) | |||
| 1111 | err = arch_init_kprobes(); | 1174 | err = arch_init_kprobes(); |
| 1112 | if (!err) | 1175 | if (!err) |
| 1113 | err = register_die_notifier(&kprobe_exceptions_nb); | 1176 | err = register_die_notifier(&kprobe_exceptions_nb); |
| 1177 | if (!err) | ||
| 1178 | err = register_module_notifier(&kprobe_module_nb); | ||
| 1179 | |||
| 1114 | kprobes_initialized = (err == 0); | 1180 | kprobes_initialized = (err == 0); |
| 1115 | 1181 | ||
| 1116 | if (!err) | 1182 | if (!err) |
| @@ -1131,10 +1197,12 @@ static void __kprobes report_probe(struct seq_file *pi, struct kprobe *p, | |||
| 1131 | else | 1197 | else |
| 1132 | kprobe_type = "k"; | 1198 | kprobe_type = "k"; |
| 1133 | if (sym) | 1199 | if (sym) |
| 1134 | seq_printf(pi, "%p %s %s+0x%x %s\n", p->addr, kprobe_type, | 1200 | seq_printf(pi, "%p %s %s+0x%x %s %s\n", p->addr, kprobe_type, |
| 1135 | sym, offset, (modname ? modname : " ")); | 1201 | sym, offset, (modname ? modname : " "), |
| 1202 | (kprobe_gone(p) ? "[GONE]" : "")); | ||
| 1136 | else | 1203 | else |
| 1137 | seq_printf(pi, "%p %s %p\n", p->addr, kprobe_type, p->addr); | 1204 | seq_printf(pi, "%p %s %p %s\n", p->addr, kprobe_type, p->addr, |
| 1205 | (kprobe_gone(p) ? "[GONE]" : "")); | ||
| 1138 | } | 1206 | } |
| 1139 | 1207 | ||
| 1140 | static void __kprobes *kprobe_seq_start(struct seq_file *f, loff_t *pos) | 1208 | static void __kprobes *kprobe_seq_start(struct seq_file *f, loff_t *pos) |
| @@ -1215,7 +1283,8 @@ static void __kprobes enable_all_kprobes(void) | |||
| 1215 | for (i = 0; i < KPROBE_TABLE_SIZE; i++) { | 1283 | for (i = 0; i < KPROBE_TABLE_SIZE; i++) { |
| 1216 | head = &kprobe_table[i]; | 1284 | head = &kprobe_table[i]; |
| 1217 | hlist_for_each_entry_rcu(p, node, head, hlist) | 1285 | hlist_for_each_entry_rcu(p, node, head, hlist) |
| 1218 | arch_arm_kprobe(p); | 1286 | if (!kprobe_gone(p)) |
| 1287 | arch_arm_kprobe(p); | ||
| 1219 | } | 1288 | } |
| 1220 | 1289 | ||
| 1221 | kprobe_enabled = true; | 1290 | kprobe_enabled = true; |
| @@ -1244,7 +1313,7 @@ static void __kprobes disable_all_kprobes(void) | |||
| 1244 | for (i = 0; i < KPROBE_TABLE_SIZE; i++) { | 1313 | for (i = 0; i < KPROBE_TABLE_SIZE; i++) { |
| 1245 | head = &kprobe_table[i]; | 1314 | head = &kprobe_table[i]; |
| 1246 | hlist_for_each_entry_rcu(p, node, head, hlist) { | 1315 | hlist_for_each_entry_rcu(p, node, head, hlist) { |
| 1247 | if (!arch_trampoline_kprobe(p)) | 1316 | if (!arch_trampoline_kprobe(p) && !kprobe_gone(p)) |
| 1248 | arch_disarm_kprobe(p); | 1317 | arch_disarm_kprobe(p); |
| 1249 | } | 1318 | } |
| 1250 | } | 1319 | } |
diff --git a/kernel/ksysfs.c b/kernel/ksysfs.c index 08dd8ed86c77..528dd78e7e7e 100644 --- a/kernel/ksysfs.c +++ b/kernel/ksysfs.c | |||
| @@ -24,7 +24,7 @@ static struct kobj_attribute _name##_attr = __ATTR_RO(_name) | |||
| 24 | static struct kobj_attribute _name##_attr = \ | 24 | static struct kobj_attribute _name##_attr = \ |
| 25 | __ATTR(_name, 0644, _name##_show, _name##_store) | 25 | __ATTR(_name, 0644, _name##_show, _name##_store) |
| 26 | 26 | ||
| 27 | #if defined(CONFIG_HOTPLUG) && defined(CONFIG_NET) | 27 | #if defined(CONFIG_HOTPLUG) |
| 28 | /* current uevent sequence number */ | 28 | /* current uevent sequence number */ |
| 29 | static ssize_t uevent_seqnum_show(struct kobject *kobj, | 29 | static ssize_t uevent_seqnum_show(struct kobject *kobj, |
| 30 | struct kobj_attribute *attr, char *buf) | 30 | struct kobj_attribute *attr, char *buf) |
| @@ -137,7 +137,7 @@ struct kobject *kernel_kobj; | |||
| 137 | EXPORT_SYMBOL_GPL(kernel_kobj); | 137 | EXPORT_SYMBOL_GPL(kernel_kobj); |
| 138 | 138 | ||
| 139 | static struct attribute * kernel_attrs[] = { | 139 | static struct attribute * kernel_attrs[] = { |
| 140 | #if defined(CONFIG_HOTPLUG) && defined(CONFIG_NET) | 140 | #if defined(CONFIG_HOTPLUG) |
| 141 | &uevent_seqnum_attr.attr, | 141 | &uevent_seqnum_attr.attr, |
| 142 | &uevent_helper_attr.attr, | 142 | &uevent_helper_attr.attr, |
| 143 | #endif | 143 | #endif |
diff --git a/kernel/module.c b/kernel/module.c index f47cce910f25..496dcb57b608 100644 --- a/kernel/module.c +++ b/kernel/module.c | |||
| @@ -43,7 +43,6 @@ | |||
| 43 | #include <linux/device.h> | 43 | #include <linux/device.h> |
| 44 | #include <linux/string.h> | 44 | #include <linux/string.h> |
| 45 | #include <linux/mutex.h> | 45 | #include <linux/mutex.h> |
| 46 | #include <linux/unwind.h> | ||
| 47 | #include <linux/rculist.h> | 46 | #include <linux/rculist.h> |
| 48 | #include <asm/uaccess.h> | 47 | #include <asm/uaccess.h> |
| 49 | #include <asm/cacheflush.h> | 48 | #include <asm/cacheflush.h> |
| @@ -1449,8 +1448,6 @@ static void free_module(struct module *mod) | |||
| 1449 | remove_sect_attrs(mod); | 1448 | remove_sect_attrs(mod); |
| 1450 | mod_kobject_remove(mod); | 1449 | mod_kobject_remove(mod); |
| 1451 | 1450 | ||
| 1452 | unwind_remove_table(mod->unwind_info, 0); | ||
| 1453 | |||
| 1454 | /* Arch-specific cleanup. */ | 1451 | /* Arch-specific cleanup. */ |
| 1455 | module_arch_cleanup(mod); | 1452 | module_arch_cleanup(mod); |
| 1456 | 1453 | ||
| @@ -1867,7 +1864,6 @@ static noinline struct module *load_module(void __user *umod, | |||
| 1867 | unsigned int symindex = 0; | 1864 | unsigned int symindex = 0; |
| 1868 | unsigned int strindex = 0; | 1865 | unsigned int strindex = 0; |
| 1869 | unsigned int modindex, versindex, infoindex, pcpuindex; | 1866 | unsigned int modindex, versindex, infoindex, pcpuindex; |
| 1870 | unsigned int unwindex = 0; | ||
| 1871 | unsigned int num_kp, num_mcount; | 1867 | unsigned int num_kp, num_mcount; |
| 1872 | struct kernel_param *kp; | 1868 | struct kernel_param *kp; |
| 1873 | struct module *mod; | 1869 | struct module *mod; |
| @@ -1957,9 +1953,6 @@ static noinline struct module *load_module(void __user *umod, | |||
| 1957 | versindex = find_sec(hdr, sechdrs, secstrings, "__versions"); | 1953 | versindex = find_sec(hdr, sechdrs, secstrings, "__versions"); |
| 1958 | infoindex = find_sec(hdr, sechdrs, secstrings, ".modinfo"); | 1954 | infoindex = find_sec(hdr, sechdrs, secstrings, ".modinfo"); |
| 1959 | pcpuindex = find_pcpusec(hdr, sechdrs, secstrings); | 1955 | pcpuindex = find_pcpusec(hdr, sechdrs, secstrings); |
| 1960 | #ifdef ARCH_UNWIND_SECTION_NAME | ||
| 1961 | unwindex = find_sec(hdr, sechdrs, secstrings, ARCH_UNWIND_SECTION_NAME); | ||
| 1962 | #endif | ||
| 1963 | 1956 | ||
| 1964 | /* Don't keep modinfo and version sections. */ | 1957 | /* Don't keep modinfo and version sections. */ |
| 1965 | sechdrs[infoindex].sh_flags &= ~(unsigned long)SHF_ALLOC; | 1958 | sechdrs[infoindex].sh_flags &= ~(unsigned long)SHF_ALLOC; |
| @@ -1969,8 +1962,6 @@ static noinline struct module *load_module(void __user *umod, | |||
| 1969 | sechdrs[symindex].sh_flags |= SHF_ALLOC; | 1962 | sechdrs[symindex].sh_flags |= SHF_ALLOC; |
| 1970 | sechdrs[strindex].sh_flags |= SHF_ALLOC; | 1963 | sechdrs[strindex].sh_flags |= SHF_ALLOC; |
| 1971 | #endif | 1964 | #endif |
| 1972 | if (unwindex) | ||
| 1973 | sechdrs[unwindex].sh_flags |= SHF_ALLOC; | ||
| 1974 | 1965 | ||
| 1975 | /* Check module struct version now, before we try to use module. */ | 1966 | /* Check module struct version now, before we try to use module. */ |
| 1976 | if (!check_modstruct_version(sechdrs, versindex, mod)) { | 1967 | if (!check_modstruct_version(sechdrs, versindex, mod)) { |
| @@ -2267,11 +2258,6 @@ static noinline struct module *load_module(void __user *umod, | |||
| 2267 | add_sect_attrs(mod, hdr->e_shnum, secstrings, sechdrs); | 2258 | add_sect_attrs(mod, hdr->e_shnum, secstrings, sechdrs); |
| 2268 | add_notes_attrs(mod, hdr->e_shnum, secstrings, sechdrs); | 2259 | add_notes_attrs(mod, hdr->e_shnum, secstrings, sechdrs); |
| 2269 | 2260 | ||
| 2270 | /* Size of section 0 is 0, so this works well if no unwind info. */ | ||
| 2271 | mod->unwind_info = unwind_add_table(mod, | ||
| 2272 | (void *)sechdrs[unwindex].sh_addr, | ||
| 2273 | sechdrs[unwindex].sh_size); | ||
| 2274 | |||
| 2275 | /* Get rid of temporary copy */ | 2261 | /* Get rid of temporary copy */ |
| 2276 | vfree(hdr); | 2262 | vfree(hdr); |
| 2277 | 2263 | ||
| @@ -2366,11 +2352,12 @@ sys_init_module(void __user *umod, | |||
| 2366 | /* Now it's a first class citizen! Wake up anyone waiting for it. */ | 2352 | /* Now it's a first class citizen! Wake up anyone waiting for it. */ |
| 2367 | mod->state = MODULE_STATE_LIVE; | 2353 | mod->state = MODULE_STATE_LIVE; |
| 2368 | wake_up(&module_wq); | 2354 | wake_up(&module_wq); |
| 2355 | blocking_notifier_call_chain(&module_notify_list, | ||
| 2356 | MODULE_STATE_LIVE, mod); | ||
| 2369 | 2357 | ||
| 2370 | mutex_lock(&module_mutex); | 2358 | mutex_lock(&module_mutex); |
| 2371 | /* Drop initial reference. */ | 2359 | /* Drop initial reference. */ |
| 2372 | module_put(mod); | 2360 | module_put(mod); |
| 2373 | unwind_remove_table(mod->unwind_info, 1); | ||
| 2374 | module_free(mod, mod->module_init); | 2361 | module_free(mod, mod->module_init); |
| 2375 | mod->module_init = NULL; | 2362 | mod->module_init = NULL; |
| 2376 | mod->init_size = 0; | 2363 | mod->init_size = 0; |
| @@ -2405,7 +2392,7 @@ static const char *get_ksymbol(struct module *mod, | |||
| 2405 | unsigned long nextval; | 2392 | unsigned long nextval; |
| 2406 | 2393 | ||
| 2407 | /* At worse, next value is at end of module */ | 2394 | /* At worse, next value is at end of module */ |
| 2408 | if (within(addr, mod->module_init, mod->init_size)) | 2395 | if (within_module_init(addr, mod)) |
| 2409 | nextval = (unsigned long)mod->module_init+mod->init_text_size; | 2396 | nextval = (unsigned long)mod->module_init+mod->init_text_size; |
| 2410 | else | 2397 | else |
| 2411 | nextval = (unsigned long)mod->module_core+mod->core_text_size; | 2398 | nextval = (unsigned long)mod->module_core+mod->core_text_size; |
| @@ -2453,8 +2440,8 @@ const char *module_address_lookup(unsigned long addr, | |||
| 2453 | 2440 | ||
| 2454 | preempt_disable(); | 2441 | preempt_disable(); |
| 2455 | list_for_each_entry_rcu(mod, &modules, list) { | 2442 | list_for_each_entry_rcu(mod, &modules, list) { |
| 2456 | if (within(addr, mod->module_init, mod->init_size) | 2443 | if (within_module_init(addr, mod) || |
| 2457 | || within(addr, mod->module_core, mod->core_size)) { | 2444 | within_module_core(addr, mod)) { |
| 2458 | if (modname) | 2445 | if (modname) |
| 2459 | *modname = mod->name; | 2446 | *modname = mod->name; |
| 2460 | ret = get_ksymbol(mod, addr, size, offset); | 2447 | ret = get_ksymbol(mod, addr, size, offset); |
| @@ -2476,8 +2463,8 @@ int lookup_module_symbol_name(unsigned long addr, char *symname) | |||
| 2476 | 2463 | ||
| 2477 | preempt_disable(); | 2464 | preempt_disable(); |
| 2478 | list_for_each_entry_rcu(mod, &modules, list) { | 2465 | list_for_each_entry_rcu(mod, &modules, list) { |
| 2479 | if (within(addr, mod->module_init, mod->init_size) || | 2466 | if (within_module_init(addr, mod) || |
| 2480 | within(addr, mod->module_core, mod->core_size)) { | 2467 | within_module_core(addr, mod)) { |
| 2481 | const char *sym; | 2468 | const char *sym; |
| 2482 | 2469 | ||
| 2483 | sym = get_ksymbol(mod, addr, NULL, NULL); | 2470 | sym = get_ksymbol(mod, addr, NULL, NULL); |
| @@ -2500,8 +2487,8 @@ int lookup_module_symbol_attrs(unsigned long addr, unsigned long *size, | |||
| 2500 | 2487 | ||
| 2501 | preempt_disable(); | 2488 | preempt_disable(); |
| 2502 | list_for_each_entry_rcu(mod, &modules, list) { | 2489 | list_for_each_entry_rcu(mod, &modules, list) { |
| 2503 | if (within(addr, mod->module_init, mod->init_size) || | 2490 | if (within_module_init(addr, mod) || |
| 2504 | within(addr, mod->module_core, mod->core_size)) { | 2491 | within_module_core(addr, mod)) { |
| 2505 | const char *sym; | 2492 | const char *sym; |
| 2506 | 2493 | ||
| 2507 | sym = get_ksymbol(mod, addr, size, offset); | 2494 | sym = get_ksymbol(mod, addr, size, offset); |
| @@ -2720,7 +2707,7 @@ int is_module_address(unsigned long addr) | |||
| 2720 | preempt_disable(); | 2707 | preempt_disable(); |
| 2721 | 2708 | ||
| 2722 | list_for_each_entry_rcu(mod, &modules, list) { | 2709 | list_for_each_entry_rcu(mod, &modules, list) { |
| 2723 | if (within(addr, mod->module_core, mod->core_size)) { | 2710 | if (within_module_core(addr, mod)) { |
| 2724 | preempt_enable(); | 2711 | preempt_enable(); |
| 2725 | return 1; | 2712 | return 1; |
| 2726 | } | 2713 | } |
diff --git a/kernel/panic.c b/kernel/panic.c index 13f06349a786..2a2ff36ff44d 100644 --- a/kernel/panic.c +++ b/kernel/panic.c | |||
| @@ -299,6 +299,8 @@ static int init_oops_id(void) | |||
| 299 | { | 299 | { |
| 300 | if (!oops_id) | 300 | if (!oops_id) |
| 301 | get_random_bytes(&oops_id, sizeof(oops_id)); | 301 | get_random_bytes(&oops_id, sizeof(oops_id)); |
| 302 | else | ||
| 303 | oops_id++; | ||
| 302 | 304 | ||
| 303 | return 0; | 305 | return 0; |
| 304 | } | 306 | } |
diff --git a/kernel/power/main.c b/kernel/power/main.c index 613f16941b85..239988873971 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) | |||
| 615 | /* this may fail if the RTC hasn't been initialized */ | 615 | /* this may fail if the RTC hasn't been initialized */ |
| 616 | status = rtc_read_time(rtc, &alm.time); | 616 | status = rtc_read_time(rtc, &alm.time); |
| 617 | if (status < 0) { | 617 | if (status < 0) { |
| 618 | printk(err_readtime, rtc->dev.bus_id, status); | 618 | printk(err_readtime, dev_name(&rtc->dev), status); |
| 619 | return; | 619 | return; |
| 620 | } | 620 | } |
| 621 | rtc_tm_to_time(&alm.time, &now); | 621 | rtc_tm_to_time(&alm.time, &now); |
| @@ -626,7 +626,7 @@ static void __init test_wakealarm(struct rtc_device *rtc, suspend_state_t state) | |||
| 626 | 626 | ||
| 627 | status = rtc_set_alarm(rtc, &alm); | 627 | status = rtc_set_alarm(rtc, &alm); |
| 628 | if (status < 0) { | 628 | if (status < 0) { |
| 629 | printk(err_wakealarm, rtc->dev.bus_id, status); | 629 | printk(err_wakealarm, dev_name(&rtc->dev), status); |
| 630 | return; | 630 | return; |
| 631 | } | 631 | } |
| 632 | 632 | ||
| @@ -660,7 +660,7 @@ static int __init has_wakealarm(struct device *dev, void *name_ptr) | |||
| 660 | if (!device_may_wakeup(candidate->dev.parent)) | 660 | if (!device_may_wakeup(candidate->dev.parent)) |
| 661 | return 0; | 661 | return 0; |
| 662 | 662 | ||
| 663 | *(char **)name_ptr = dev->bus_id; | 663 | *(const char **)name_ptr = dev_name(dev); |
| 664 | return 1; | 664 | return 1; |
| 665 | } | 665 | } |
| 666 | 666 | ||
diff --git a/kernel/profile.c b/kernel/profile.c index d18e2d2654f2..784933acf5b8 100644 --- a/kernel/profile.c +++ b/kernel/profile.c | |||
| @@ -445,7 +445,6 @@ void profile_tick(int type) | |||
| 445 | #ifdef CONFIG_PROC_FS | 445 | #ifdef CONFIG_PROC_FS |
| 446 | #include <linux/proc_fs.h> | 446 | #include <linux/proc_fs.h> |
| 447 | #include <asm/uaccess.h> | 447 | #include <asm/uaccess.h> |
| 448 | #include <asm/ptrace.h> | ||
| 449 | 448 | ||
| 450 | static int prof_cpu_mask_read_proc(char *page, char **start, off_t off, | 449 | static int prof_cpu_mask_read_proc(char *page, char **start, off_t off, |
| 451 | int count, int *eof, void *data) | 450 | int count, int *eof, void *data) |
diff --git a/kernel/signal.c b/kernel/signal.c index 8e95855ff3cf..3152ac3b62e2 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, | |||
| 858 | q->info.si_signo = sig; | 858 | q->info.si_signo = sig; |
| 859 | q->info.si_errno = 0; | 859 | q->info.si_errno = 0; |
| 860 | q->info.si_code = SI_USER; | 860 | q->info.si_code = SI_USER; |
| 861 | q->info.si_pid = task_pid_vnr(current); | 861 | q->info.si_pid = task_tgid_nr_ns(current, |
| 862 | task_active_pid_ns(t)); | ||
| 862 | q->info.si_uid = current_uid(); | 863 | q->info.si_uid = current_uid(); |
| 863 | break; | 864 | break; |
| 864 | case (unsigned long) SEND_SIG_PRIV: | 865 | case (unsigned long) SEND_SIG_PRIV: |
diff --git a/kernel/sys.c b/kernel/sys.c index d356d79e84ac..4a43617cd565 100644 --- a/kernel/sys.c +++ b/kernel/sys.c | |||
| @@ -33,6 +33,7 @@ | |||
| 33 | #include <linux/task_io_accounting_ops.h> | 33 | #include <linux/task_io_accounting_ops.h> |
| 34 | #include <linux/seccomp.h> | 34 | #include <linux/seccomp.h> |
| 35 | #include <linux/cpu.h> | 35 | #include <linux/cpu.h> |
| 36 | #include <linux/ptrace.h> | ||
| 36 | 37 | ||
| 37 | #include <linux/compat.h> | 38 | #include <linux/compat.h> |
| 38 | #include <linux/syscalls.h> | 39 | #include <linux/syscalls.h> |
| @@ -927,6 +928,7 @@ asmlinkage long sys_times(struct tms __user * tbuf) | |||
| 927 | if (copy_to_user(tbuf, &tmp, sizeof(struct tms))) | 928 | if (copy_to_user(tbuf, &tmp, sizeof(struct tms))) |
| 928 | return -EFAULT; | 929 | return -EFAULT; |
| 929 | } | 930 | } |
| 931 | force_successful_syscall_return(); | ||
| 930 | return (long) jiffies_64_to_clock_t(get_jiffies_64()); | 932 | return (long) jiffies_64_to_clock_t(get_jiffies_64()); |
| 931 | } | 933 | } |
| 932 | 934 | ||
diff --git a/kernel/sysctl.c b/kernel/sysctl.c index ff6d45c7626f..92f6e5bc3c24 100644 --- a/kernel/sysctl.c +++ b/kernel/sysctl.c | |||
| @@ -87,10 +87,6 @@ extern int rcutorture_runnable; | |||
| 87 | #endif /* #ifdef CONFIG_RCU_TORTURE_TEST */ | 87 | #endif /* #ifdef CONFIG_RCU_TORTURE_TEST */ |
| 88 | 88 | ||
| 89 | /* Constants used for minimum and maximum */ | 89 | /* Constants used for minimum and maximum */ |
| 90 | #if defined(CONFIG_HIGHMEM) || defined(CONFIG_DETECT_SOFTLOCKUP) | ||
| 91 | static int one = 1; | ||
| 92 | #endif | ||
| 93 | |||
| 94 | #ifdef CONFIG_DETECT_SOFTLOCKUP | 90 | #ifdef CONFIG_DETECT_SOFTLOCKUP |
| 95 | static int sixty = 60; | 91 | static int sixty = 60; |
| 96 | static int neg_one = -1; | 92 | static int neg_one = -1; |
| @@ -101,6 +97,7 @@ static int two = 2; | |||
| 101 | #endif | 97 | #endif |
| 102 | 98 | ||
| 103 | static int zero; | 99 | static int zero; |
| 100 | static int one = 1; | ||
| 104 | static int one_hundred = 100; | 101 | static int one_hundred = 100; |
| 105 | 102 | ||
| 106 | /* this is needed for the proc_dointvec_minmax for [fs_]overflow UID and GID */ | 103 | /* this is needed for the proc_dointvec_minmax for [fs_]overflow UID and GID */ |
| @@ -952,12 +949,22 @@ static struct ctl_table vm_table[] = { | |||
| 952 | .data = &dirty_background_ratio, | 949 | .data = &dirty_background_ratio, |
| 953 | .maxlen = sizeof(dirty_background_ratio), | 950 | .maxlen = sizeof(dirty_background_ratio), |
| 954 | .mode = 0644, | 951 | .mode = 0644, |
| 955 | .proc_handler = &proc_dointvec_minmax, | 952 | .proc_handler = &dirty_background_ratio_handler, |
| 956 | .strategy = &sysctl_intvec, | 953 | .strategy = &sysctl_intvec, |
| 957 | .extra1 = &zero, | 954 | .extra1 = &zero, |
| 958 | .extra2 = &one_hundred, | 955 | .extra2 = &one_hundred, |
| 959 | }, | 956 | }, |
| 960 | { | 957 | { |
| 958 | .ctl_name = CTL_UNNUMBERED, | ||
| 959 | .procname = "dirty_background_bytes", | ||
| 960 | .data = &dirty_background_bytes, | ||
| 961 | .maxlen = sizeof(dirty_background_bytes), | ||
| 962 | .mode = 0644, | ||
| 963 | .proc_handler = &dirty_background_bytes_handler, | ||
| 964 | .strategy = &sysctl_intvec, | ||
| 965 | .extra1 = &one, | ||
| 966 | }, | ||
| 967 | { | ||
| 961 | .ctl_name = VM_DIRTY_RATIO, | 968 | .ctl_name = VM_DIRTY_RATIO, |
| 962 | .procname = "dirty_ratio", | 969 | .procname = "dirty_ratio", |
| 963 | .data = &vm_dirty_ratio, | 970 | .data = &vm_dirty_ratio, |
| @@ -969,6 +976,16 @@ static struct ctl_table vm_table[] = { | |||
| 969 | .extra2 = &one_hundred, | 976 | .extra2 = &one_hundred, |
| 970 | }, | 977 | }, |
| 971 | { | 978 | { |
| 979 | .ctl_name = CTL_UNNUMBERED, | ||
| 980 | .procname = "dirty_bytes", | ||
| 981 | .data = &vm_dirty_bytes, | ||
| 982 | .maxlen = sizeof(vm_dirty_bytes), | ||
| 983 | .mode = 0644, | ||
| 984 | .proc_handler = &dirty_bytes_handler, | ||
| 985 | .strategy = &sysctl_intvec, | ||
| 986 | .extra1 = &one, | ||
| 987 | }, | ||
| 988 | { | ||
| 972 | .procname = "dirty_writeback_centisecs", | 989 | .procname = "dirty_writeback_centisecs", |
| 973 | .data = &dirty_writeback_interval, | 990 | .data = &dirty_writeback_interval, |
| 974 | .maxlen = sizeof(dirty_writeback_interval), | 991 | .maxlen = sizeof(dirty_writeback_interval), |
diff --git a/kernel/test_kprobes.c b/kernel/test_kprobes.c index 06b6395b45b2..4f104515a19b 100644 --- a/kernel/test_kprobes.c +++ b/kernel/test_kprobes.c | |||
| @@ -22,21 +22,11 @@ | |||
| 22 | 22 | ||
| 23 | static u32 rand1, preh_val, posth_val, jph_val; | 23 | static u32 rand1, preh_val, posth_val, jph_val; |
| 24 | static int errors, handler_errors, num_tests; | 24 | static int errors, handler_errors, num_tests; |
| 25 | static u32 (*target)(u32 value); | ||
| 26 | static u32 (*target2)(u32 value); | ||
| 25 | 27 | ||
| 26 | static noinline u32 kprobe_target(u32 value) | 28 | static noinline u32 kprobe_target(u32 value) |
| 27 | { | 29 | { |
| 28 | /* | ||
| 29 | * gcc ignores noinline on some architectures unless we stuff | ||
| 30 | * sufficient lard into the function. The get_kprobe() here is | ||
| 31 | * just for that. | ||
| 32 | * | ||
| 33 | * NOTE: We aren't concerned about the correctness of get_kprobe() | ||
| 34 | * here; hence, this call is neither under !preempt nor with the | ||
| 35 | * kprobe_mutex held. This is fine(tm) | ||
| 36 | */ | ||
| 37 | if (get_kprobe((void *)0xdeadbeef)) | ||
| 38 | printk(KERN_INFO "Kprobe smoke test: probe on 0xdeadbeef!\n"); | ||
| 39 | |||
| 40 | return (value / div_factor); | 30 | return (value / div_factor); |
| 41 | } | 31 | } |
| 42 | 32 | ||
| @@ -74,7 +64,7 @@ static int test_kprobe(void) | |||
| 74 | return ret; | 64 | return ret; |
| 75 | } | 65 | } |
| 76 | 66 | ||
| 77 | ret = kprobe_target(rand1); | 67 | ret = target(rand1); |
| 78 | unregister_kprobe(&kp); | 68 | unregister_kprobe(&kp); |
| 79 | 69 | ||
| 80 | if (preh_val == 0) { | 70 | if (preh_val == 0) { |
| @@ -92,6 +82,84 @@ static int test_kprobe(void) | |||
| 92 | return 0; | 82 | return 0; |
| 93 | } | 83 | } |
| 94 | 84 | ||
| 85 | static noinline u32 kprobe_target2(u32 value) | ||
| 86 | { | ||
| 87 | return (value / div_factor) + 1; | ||
| 88 | } | ||
| 89 | |||
| 90 | static int kp_pre_handler2(struct kprobe *p, struct pt_regs *regs) | ||
| 91 | { | ||
| 92 | preh_val = (rand1 / div_factor) + 1; | ||
| 93 | return 0; | ||
| 94 | } | ||
| 95 | |||
| 96 | static void kp_post_handler2(struct kprobe *p, struct pt_regs *regs, | ||
| 97 | unsigned long flags) | ||
| 98 | { | ||
| 99 | if (preh_val != (rand1 / div_factor) + 1) { | ||
| 100 | handler_errors++; | ||
| 101 | printk(KERN_ERR "Kprobe smoke test failed: " | ||
| 102 | "incorrect value in post_handler2\n"); | ||
| 103 | } | ||
| 104 | posth_val = preh_val + div_factor; | ||
| 105 | } | ||
| 106 | |||
| 107 | static struct kprobe kp2 = { | ||
| 108 | .symbol_name = "kprobe_target2", | ||
| 109 | .pre_handler = kp_pre_handler2, | ||
| 110 | .post_handler = kp_post_handler2 | ||
| 111 | }; | ||
| 112 | |||
| 113 | static int test_kprobes(void) | ||
| 114 | { | ||
| 115 | int ret; | ||
| 116 | struct kprobe *kps[2] = {&kp, &kp2}; | ||
| 117 | |||
| 118 | kp.addr = 0; /* addr should be cleard for reusing kprobe. */ | ||
| 119 | ret = register_kprobes(kps, 2); | ||
| 120 | if (ret < 0) { | ||
| 121 | printk(KERN_ERR "Kprobe smoke test failed: " | ||
| 122 | "register_kprobes returned %d\n", ret); | ||
| 123 | return ret; | ||
| 124 | } | ||
| 125 | |||
| 126 | preh_val = 0; | ||
| 127 | posth_val = 0; | ||
| 128 | ret = target(rand1); | ||
| 129 | |||
| 130 | if (preh_val == 0) { | ||
| 131 | printk(KERN_ERR "Kprobe smoke test failed: " | ||
| 132 | "kprobe pre_handler not called\n"); | ||
| 133 | handler_errors++; | ||
| 134 | } | ||
| 135 | |||
| 136 | if (posth_val == 0) { | ||
| 137 | printk(KERN_ERR "Kprobe smoke test failed: " | ||
| 138 | "kprobe post_handler not called\n"); | ||
| 139 | handler_errors++; | ||
| 140 | } | ||
| 141 | |||
| 142 | preh_val = 0; | ||
| 143 | posth_val = 0; | ||
| 144 | ret = target2(rand1); | ||
| 145 | |||
| 146 | if (preh_val == 0) { | ||
| 147 | printk(KERN_ERR "Kprobe smoke test failed: " | ||
| 148 | "kprobe pre_handler2 not called\n"); | ||
| 149 | handler_errors++; | ||
| 150 | } | ||
| 151 | |||
| 152 | if (posth_val == 0) { | ||
| 153 | printk(KERN_ERR "Kprobe smoke test failed: " | ||
| 154 | "kprobe post_handler2 not called\n"); | ||
| 155 | handler_errors++; | ||
| 156 | } | ||
| 157 | |||
| 158 | unregister_kprobes(kps, 2); | ||
| 159 | return 0; | ||
| 160 | |||
| 161 | } | ||
| 162 | |||
| 95 | static u32 j_kprobe_target(u32 value) | 163 | static u32 j_kprobe_target(u32 value) |
| 96 | { | 164 | { |
| 97 | if (value != rand1) { | 165 | if (value != rand1) { |
| @@ -121,7 +189,7 @@ static int test_jprobe(void) | |||
| 121 | return ret; | 189 | return ret; |
| 122 | } | 190 | } |
| 123 | 191 | ||
| 124 | ret = kprobe_target(rand1); | 192 | ret = target(rand1); |
| 125 | unregister_jprobe(&jp); | 193 | unregister_jprobe(&jp); |
| 126 | if (jph_val == 0) { | 194 | if (jph_val == 0) { |
| 127 | printk(KERN_ERR "Kprobe smoke test failed: " | 195 | printk(KERN_ERR "Kprobe smoke test failed: " |
| @@ -132,6 +200,43 @@ static int test_jprobe(void) | |||
| 132 | return 0; | 200 | return 0; |
| 133 | } | 201 | } |
| 134 | 202 | ||
| 203 | static struct jprobe jp2 = { | ||
| 204 | .entry = j_kprobe_target, | ||
| 205 | .kp.symbol_name = "kprobe_target2" | ||
| 206 | }; | ||
| 207 | |||
| 208 | static int test_jprobes(void) | ||
| 209 | { | ||
| 210 | int ret; | ||
| 211 | struct jprobe *jps[2] = {&jp, &jp2}; | ||
| 212 | |||
| 213 | jp.kp.addr = 0; /* addr should be cleard for reusing kprobe. */ | ||
| 214 | ret = register_jprobes(jps, 2); | ||
| 215 | if (ret < 0) { | ||
| 216 | printk(KERN_ERR "Kprobe smoke test failed: " | ||
| 217 | "register_jprobes returned %d\n", ret); | ||
| 218 | return ret; | ||
| 219 | } | ||
| 220 | |||
| 221 | jph_val = 0; | ||
| 222 | ret = target(rand1); | ||
| 223 | if (jph_val == 0) { | ||
| 224 | printk(KERN_ERR "Kprobe smoke test failed: " | ||
| 225 | "jprobe handler not called\n"); | ||
| 226 | handler_errors++; | ||
| 227 | } | ||
| 228 | |||
| 229 | jph_val = 0; | ||
| 230 | ret = target2(rand1); | ||
| 231 | if (jph_val == 0) { | ||
| 232 | printk(KERN_ERR "Kprobe smoke test failed: " | ||
| 233 | "jprobe handler2 not called\n"); | ||
| 234 | handler_errors++; | ||
| 235 | } | ||
| 236 | unregister_jprobes(jps, 2); | ||
| 237 | |||
| 238 | return 0; | ||
| 239 | } | ||
| 135 | #ifdef CONFIG_KRETPROBES | 240 | #ifdef CONFIG_KRETPROBES |
| 136 | static u32 krph_val; | 241 | static u32 krph_val; |
| 137 | 242 | ||
| @@ -177,7 +282,7 @@ static int test_kretprobe(void) | |||
| 177 | return ret; | 282 | return ret; |
| 178 | } | 283 | } |
| 179 | 284 | ||
| 180 | ret = kprobe_target(rand1); | 285 | ret = target(rand1); |
| 181 | unregister_kretprobe(&rp); | 286 | unregister_kretprobe(&rp); |
| 182 | if (krph_val != rand1) { | 287 | if (krph_val != rand1) { |
| 183 | printk(KERN_ERR "Kprobe smoke test failed: " | 288 | printk(KERN_ERR "Kprobe smoke test failed: " |
| @@ -187,12 +292,72 @@ static int test_kretprobe(void) | |||
| 187 | 292 | ||
| 188 | return 0; | 293 | return 0; |
| 189 | } | 294 | } |
| 295 | |||
| 296 | static int return_handler2(struct kretprobe_instance *ri, struct pt_regs *regs) | ||
| 297 | { | ||
| 298 | unsigned long ret = regs_return_value(regs); | ||
| 299 | |||
| 300 | if (ret != (rand1 / div_factor) + 1) { | ||
| 301 | handler_errors++; | ||
| 302 | printk(KERN_ERR "Kprobe smoke test failed: " | ||
| 303 | "incorrect value in kretprobe handler2\n"); | ||
| 304 | } | ||
| 305 | if (krph_val == 0) { | ||
| 306 | handler_errors++; | ||
| 307 | printk(KERN_ERR "Kprobe smoke test failed: " | ||
| 308 | "call to kretprobe entry handler failed\n"); | ||
| 309 | } | ||
| 310 | |||
| 311 | krph_val = rand1; | ||
| 312 | return 0; | ||
| 313 | } | ||
| 314 | |||
| 315 | static struct kretprobe rp2 = { | ||
| 316 | .handler = return_handler2, | ||
| 317 | .entry_handler = entry_handler, | ||
| 318 | .kp.symbol_name = "kprobe_target2" | ||
| 319 | }; | ||
| 320 | |||
| 321 | static int test_kretprobes(void) | ||
| 322 | { | ||
| 323 | int ret; | ||
| 324 | struct kretprobe *rps[2] = {&rp, &rp2}; | ||
| 325 | |||
| 326 | rp.kp.addr = 0; /* addr should be cleard for reusing kprobe. */ | ||
| 327 | ret = register_kretprobes(rps, 2); | ||
| 328 | if (ret < 0) { | ||
| 329 | printk(KERN_ERR "Kprobe smoke test failed: " | ||
| 330 | "register_kretprobe returned %d\n", ret); | ||
| 331 | return ret; | ||
| 332 | } | ||
| 333 | |||
| 334 | krph_val = 0; | ||
| 335 | ret = target(rand1); | ||
| 336 | if (krph_val != rand1) { | ||
| 337 | printk(KERN_ERR "Kprobe smoke test failed: " | ||
| 338 | "kretprobe handler not called\n"); | ||
| 339 | handler_errors++; | ||
| 340 | } | ||
| 341 | |||
| 342 | krph_val = 0; | ||
| 343 | ret = target2(rand1); | ||
| 344 | if (krph_val != rand1) { | ||
| 345 | printk(KERN_ERR "Kprobe smoke test failed: " | ||
| 346 | "kretprobe handler2 not called\n"); | ||
| 347 | handler_errors++; | ||
| 348 | } | ||
| 349 | unregister_kretprobes(rps, 2); | ||
| 350 | return 0; | ||
| 351 | } | ||
| 190 | #endif /* CONFIG_KRETPROBES */ | 352 | #endif /* CONFIG_KRETPROBES */ |
| 191 | 353 | ||
| 192 | int init_test_probes(void) | 354 | int init_test_probes(void) |
| 193 | { | 355 | { |
| 194 | int ret; | 356 | int ret; |
| 195 | 357 | ||
| 358 | target = kprobe_target; | ||
| 359 | target2 = kprobe_target2; | ||
| 360 | |||
| 196 | do { | 361 | do { |
| 197 | rand1 = random32(); | 362 | rand1 = random32(); |
| 198 | } while (rand1 <= div_factor); | 363 | } while (rand1 <= div_factor); |
| @@ -204,15 +369,30 @@ int init_test_probes(void) | |||
| 204 | errors++; | 369 | errors++; |
| 205 | 370 | ||
| 206 | num_tests++; | 371 | num_tests++; |
| 372 | ret = test_kprobes(); | ||
| 373 | if (ret < 0) | ||
| 374 | errors++; | ||
| 375 | |||
| 376 | num_tests++; | ||
| 207 | ret = test_jprobe(); | 377 | ret = test_jprobe(); |
| 208 | if (ret < 0) | 378 | if (ret < 0) |
| 209 | errors++; | 379 | errors++; |
| 210 | 380 | ||
| 381 | num_tests++; | ||
| 382 | ret = test_jprobes(); | ||
| 383 | if (ret < 0) | ||
| 384 | errors++; | ||
| 385 | |||
| 211 | #ifdef CONFIG_KRETPROBES | 386 | #ifdef CONFIG_KRETPROBES |
| 212 | num_tests++; | 387 | num_tests++; |
| 213 | ret = test_kretprobe(); | 388 | ret = test_kretprobe(); |
| 214 | if (ret < 0) | 389 | if (ret < 0) |
| 215 | errors++; | 390 | errors++; |
| 391 | |||
| 392 | num_tests++; | ||
| 393 | ret = test_kretprobes(); | ||
| 394 | if (ret < 0) | ||
| 395 | errors++; | ||
| 216 | #endif /* CONFIG_KRETPROBES */ | 396 | #endif /* CONFIG_KRETPROBES */ |
| 217 | 397 | ||
| 218 | if (errors) | 398 | if (errors) |
diff --git a/kernel/time.c b/kernel/time.c index d63a4336fad6..4886e3ce83a4 100644 --- a/kernel/time.c +++ b/kernel/time.c | |||
| @@ -37,6 +37,7 @@ | |||
| 37 | #include <linux/fs.h> | 37 | #include <linux/fs.h> |
| 38 | #include <linux/slab.h> | 38 | #include <linux/slab.h> |
| 39 | #include <linux/math64.h> | 39 | #include <linux/math64.h> |
| 40 | #include <linux/ptrace.h> | ||
| 40 | 41 | ||
| 41 | #include <asm/uaccess.h> | 42 | #include <asm/uaccess.h> |
| 42 | #include <asm/unistd.h> | 43 | #include <asm/unistd.h> |
| @@ -65,8 +66,9 @@ asmlinkage long sys_time(time_t __user * tloc) | |||
| 65 | 66 | ||
| 66 | if (tloc) { | 67 | if (tloc) { |
| 67 | if (put_user(i,tloc)) | 68 | if (put_user(i,tloc)) |
| 68 | i = -EFAULT; | 69 | return -EFAULT; |
| 69 | } | 70 | } |
| 71 | force_successful_syscall_return(); | ||
| 70 | return i; | 72 | return i; |
| 71 | } | 73 | } |
| 72 | 74 | ||
diff --git a/kernel/tsacct.c b/kernel/tsacct.c index 2dc06ab35716..43f891b05a4b 100644 --- a/kernel/tsacct.c +++ b/kernel/tsacct.c | |||
| @@ -92,8 +92,8 @@ void xacct_add_tsk(struct taskstats *stats, struct task_struct *p) | |||
| 92 | mm = get_task_mm(p); | 92 | mm = get_task_mm(p); |
| 93 | if (mm) { | 93 | if (mm) { |
| 94 | /* adjust to KB unit */ | 94 | /* adjust to KB unit */ |
| 95 | stats->hiwater_rss = mm->hiwater_rss * PAGE_SIZE / KB; | 95 | stats->hiwater_rss = get_mm_hiwater_rss(mm) * PAGE_SIZE / KB; |
| 96 | stats->hiwater_vm = mm->hiwater_vm * PAGE_SIZE / KB; | 96 | stats->hiwater_vm = get_mm_hiwater_vm(mm) * PAGE_SIZE / KB; |
| 97 | mmput(mm); | 97 | mmput(mm); |
| 98 | } | 98 | } |
| 99 | stats->read_char = p->ioac.rchar; | 99 | stats->read_char = p->ioac.rchar; |
