diff options
Diffstat (limited to 'kernel')
| -rw-r--r-- | kernel/fork.c | 11 | ||||
| -rw-r--r-- | kernel/module.c | 51 | ||||
| -rw-r--r-- | kernel/signal.c | 8 | ||||
| -rw-r--r-- | kernel/softirq.c | 1 | ||||
| -rw-r--r-- | kernel/tsacct.c | 6 | ||||
| -rw-r--r-- | kernel/user.c | 16 |
6 files changed, 51 insertions, 42 deletions
diff --git a/kernel/fork.c b/kernel/fork.c index a66fbde20715..4854c2c4a82e 100644 --- a/kernel/fork.c +++ b/kernel/fork.c | |||
| @@ -1179,10 +1179,6 @@ static struct task_struct *copy_process(unsigned long clone_flags, | |||
| 1179 | #endif | 1179 | #endif |
| 1180 | clear_all_latency_tracing(p); | 1180 | clear_all_latency_tracing(p); |
| 1181 | 1181 | ||
| 1182 | /* Our parent execution domain becomes current domain | ||
| 1183 | These must match for thread signalling to apply */ | ||
| 1184 | p->parent_exec_id = p->self_exec_id; | ||
| 1185 | |||
| 1186 | /* ok, now we should be set up.. */ | 1182 | /* ok, now we should be set up.. */ |
| 1187 | p->exit_signal = (clone_flags & CLONE_THREAD) ? -1 : (clone_flags & CSIGNAL); | 1183 | p->exit_signal = (clone_flags & CLONE_THREAD) ? -1 : (clone_flags & CSIGNAL); |
| 1188 | p->pdeath_signal = 0; | 1184 | p->pdeath_signal = 0; |
| @@ -1220,10 +1216,13 @@ static struct task_struct *copy_process(unsigned long clone_flags, | |||
| 1220 | set_task_cpu(p, smp_processor_id()); | 1216 | set_task_cpu(p, smp_processor_id()); |
| 1221 | 1217 | ||
| 1222 | /* CLONE_PARENT re-uses the old parent */ | 1218 | /* CLONE_PARENT re-uses the old parent */ |
| 1223 | if (clone_flags & (CLONE_PARENT|CLONE_THREAD)) | 1219 | if (clone_flags & (CLONE_PARENT|CLONE_THREAD)) { |
| 1224 | p->real_parent = current->real_parent; | 1220 | p->real_parent = current->real_parent; |
| 1225 | else | 1221 | p->parent_exec_id = current->parent_exec_id; |
| 1222 | } else { | ||
| 1226 | p->real_parent = current; | 1223 | p->real_parent = current; |
| 1224 | p->parent_exec_id = current->self_exec_id; | ||
| 1225 | } | ||
| 1227 | 1226 | ||
| 1228 | spin_lock(¤t->sighand->siglock); | 1227 | spin_lock(¤t->sighand->siglock); |
| 1229 | 1228 | ||
diff --git a/kernel/module.c b/kernel/module.c index ba22484a987e..77672233387f 100644 --- a/kernel/module.c +++ b/kernel/module.c | |||
| @@ -822,7 +822,7 @@ SYSCALL_DEFINE2(delete_module, const char __user *, name_user, | |||
| 822 | mutex_lock(&module_mutex); | 822 | mutex_lock(&module_mutex); |
| 823 | /* Store the name of the last unloaded module for diagnostic purposes */ | 823 | /* Store the name of the last unloaded module for diagnostic purposes */ |
| 824 | strlcpy(last_unloaded_module, mod->name, sizeof(last_unloaded_module)); | 824 | strlcpy(last_unloaded_module, mod->name, sizeof(last_unloaded_module)); |
| 825 | unregister_dynamic_debug_module(mod->name); | 825 | ddebug_remove_module(mod->name); |
| 826 | free_module(mod); | 826 | free_module(mod); |
| 827 | 827 | ||
| 828 | out: | 828 | out: |
| @@ -1827,19 +1827,13 @@ static inline void add_kallsyms(struct module *mod, | |||
| 1827 | } | 1827 | } |
| 1828 | #endif /* CONFIG_KALLSYMS */ | 1828 | #endif /* CONFIG_KALLSYMS */ |
| 1829 | 1829 | ||
| 1830 | static void dynamic_printk_setup(struct mod_debug *debug, unsigned int num) | 1830 | static void dynamic_debug_setup(struct _ddebug *debug, unsigned int num) |
| 1831 | { | 1831 | { |
| 1832 | #ifdef CONFIG_DYNAMIC_PRINTK_DEBUG | 1832 | #ifdef CONFIG_DYNAMIC_DEBUG |
| 1833 | unsigned int i; | 1833 | if (ddebug_add_module(debug, num, debug->modname)) |
| 1834 | 1834 | printk(KERN_ERR "dynamic debug error adding module: %s\n", | |
| 1835 | for (i = 0; i < num; i++) { | 1835 | debug->modname); |
| 1836 | register_dynamic_debug_module(debug[i].modname, | 1836 | #endif |
| 1837 | debug[i].type, | ||
| 1838 | debug[i].logical_modname, | ||
| 1839 | debug[i].flag_names, | ||
| 1840 | debug[i].hash, debug[i].hash2); | ||
| 1841 | } | ||
| 1842 | #endif /* CONFIG_DYNAMIC_PRINTK_DEBUG */ | ||
| 1843 | } | 1837 | } |
| 1844 | 1838 | ||
| 1845 | static void *module_alloc_update_bounds(unsigned long size) | 1839 | static void *module_alloc_update_bounds(unsigned long size) |
| @@ -2015,14 +2009,6 @@ static noinline struct module *load_module(void __user *umod, | |||
| 2015 | if (err < 0) | 2009 | if (err < 0) |
| 2016 | goto free_mod; | 2010 | goto free_mod; |
| 2017 | 2011 | ||
| 2018 | #if defined(CONFIG_MODULE_UNLOAD) && defined(CONFIG_SMP) | ||
| 2019 | mod->refptr = percpu_modalloc(sizeof(local_t), __alignof__(local_t), | ||
| 2020 | mod->name); | ||
| 2021 | if (!mod->refptr) { | ||
| 2022 | err = -ENOMEM; | ||
| 2023 | goto free_mod; | ||
| 2024 | } | ||
| 2025 | #endif | ||
| 2026 | if (pcpuindex) { | 2012 | if (pcpuindex) { |
| 2027 | /* We have a special allocation for this section. */ | 2013 | /* We have a special allocation for this section. */ |
| 2028 | percpu = percpu_modalloc(sechdrs[pcpuindex].sh_size, | 2014 | percpu = percpu_modalloc(sechdrs[pcpuindex].sh_size, |
| @@ -2030,7 +2016,7 @@ static noinline struct module *load_module(void __user *umod, | |||
| 2030 | mod->name); | 2016 | mod->name); |
| 2031 | if (!percpu) { | 2017 | if (!percpu) { |
| 2032 | err = -ENOMEM; | 2018 | err = -ENOMEM; |
| 2033 | goto free_percpu; | 2019 | goto free_mod; |
| 2034 | } | 2020 | } |
| 2035 | sechdrs[pcpuindex].sh_flags &= ~(unsigned long)SHF_ALLOC; | 2021 | sechdrs[pcpuindex].sh_flags &= ~(unsigned long)SHF_ALLOC; |
| 2036 | mod->percpu = percpu; | 2022 | mod->percpu = percpu; |
| @@ -2082,6 +2068,14 @@ static noinline struct module *load_module(void __user *umod, | |||
| 2082 | /* Module has been moved. */ | 2068 | /* Module has been moved. */ |
| 2083 | mod = (void *)sechdrs[modindex].sh_addr; | 2069 | mod = (void *)sechdrs[modindex].sh_addr; |
| 2084 | 2070 | ||
| 2071 | #if defined(CONFIG_MODULE_UNLOAD) && defined(CONFIG_SMP) | ||
| 2072 | mod->refptr = percpu_modalloc(sizeof(local_t), __alignof__(local_t), | ||
| 2073 | mod->name); | ||
| 2074 | if (!mod->refptr) { | ||
| 2075 | err = -ENOMEM; | ||
| 2076 | goto free_init; | ||
| 2077 | } | ||
| 2078 | #endif | ||
| 2085 | /* Now we've moved module, initialize linked lists, etc. */ | 2079 | /* Now we've moved module, initialize linked lists, etc. */ |
| 2086 | module_unload_init(mod); | 2080 | module_unload_init(mod); |
| 2087 | 2081 | ||
| @@ -2213,12 +2207,13 @@ static noinline struct module *load_module(void __user *umod, | |||
| 2213 | add_kallsyms(mod, sechdrs, symindex, strindex, secstrings); | 2207 | add_kallsyms(mod, sechdrs, symindex, strindex, secstrings); |
| 2214 | 2208 | ||
| 2215 | if (!mod->taints) { | 2209 | if (!mod->taints) { |
| 2216 | struct mod_debug *debug; | 2210 | struct _ddebug *debug; |
| 2217 | unsigned int num_debug; | 2211 | unsigned int num_debug; |
| 2218 | 2212 | ||
| 2219 | debug = section_objs(hdr, sechdrs, secstrings, "__verbose", | 2213 | debug = section_objs(hdr, sechdrs, secstrings, "__verbose", |
| 2220 | sizeof(*debug), &num_debug); | 2214 | sizeof(*debug), &num_debug); |
| 2221 | dynamic_printk_setup(debug, num_debug); | 2215 | if (debug) |
| 2216 | dynamic_debug_setup(debug, num_debug); | ||
| 2222 | } | 2217 | } |
| 2223 | 2218 | ||
| 2224 | /* sechdrs[0].sh_size is always zero */ | 2219 | /* sechdrs[0].sh_size is always zero */ |
| @@ -2288,15 +2283,17 @@ static noinline struct module *load_module(void __user *umod, | |||
| 2288 | ftrace_release(mod->module_core, mod->core_size); | 2283 | ftrace_release(mod->module_core, mod->core_size); |
| 2289 | free_unload: | 2284 | free_unload: |
| 2290 | module_unload_free(mod); | 2285 | module_unload_free(mod); |
| 2286 | free_init: | ||
| 2287 | #if defined(CONFIG_MODULE_UNLOAD) && defined(CONFIG_SMP) | ||
| 2288 | percpu_modfree(mod->refptr); | ||
| 2289 | #endif | ||
| 2291 | module_free(mod, mod->module_init); | 2290 | module_free(mod, mod->module_init); |
| 2292 | free_core: | 2291 | free_core: |
| 2293 | module_free(mod, mod->module_core); | 2292 | module_free(mod, mod->module_core); |
| 2293 | /* mod will be freed with core. Don't access it beyond this line! */ | ||
| 2294 | free_percpu: | 2294 | free_percpu: |
| 2295 | if (percpu) | 2295 | if (percpu) |
| 2296 | percpu_modfree(percpu); | 2296 | percpu_modfree(percpu); |
| 2297 | #if defined(CONFIG_MODULE_UNLOAD) && defined(CONFIG_SMP) | ||
| 2298 | percpu_modfree(mod->refptr); | ||
| 2299 | #endif | ||
| 2300 | free_mod: | 2297 | free_mod: |
| 2301 | kfree(args); | 2298 | kfree(args); |
| 2302 | free_hdr: | 2299 | free_hdr: |
diff --git a/kernel/signal.c b/kernel/signal.c index 2a74fe87c0dd..1c8814481a11 100644 --- a/kernel/signal.c +++ b/kernel/signal.c | |||
| @@ -1575,7 +1575,15 @@ static void ptrace_stop(int exit_code, int clear_code, siginfo_t *info) | |||
| 1575 | read_lock(&tasklist_lock); | 1575 | read_lock(&tasklist_lock); |
| 1576 | if (may_ptrace_stop()) { | 1576 | if (may_ptrace_stop()) { |
| 1577 | do_notify_parent_cldstop(current, CLD_TRAPPED); | 1577 | do_notify_parent_cldstop(current, CLD_TRAPPED); |
| 1578 | /* | ||
| 1579 | * Don't want to allow preemption here, because | ||
| 1580 | * sys_ptrace() needs this task to be inactive. | ||
| 1581 | * | ||
| 1582 | * XXX: implement read_unlock_no_resched(). | ||
| 1583 | */ | ||
| 1584 | preempt_disable(); | ||
| 1578 | read_unlock(&tasklist_lock); | 1585 | read_unlock(&tasklist_lock); |
| 1586 | preempt_enable_no_resched(); | ||
| 1579 | schedule(); | 1587 | schedule(); |
| 1580 | } else { | 1588 | } else { |
| 1581 | /* | 1589 | /* |
diff --git a/kernel/softirq.c b/kernel/softirq.c index bdbe9de9cd8d..9041ea7948fe 100644 --- a/kernel/softirq.c +++ b/kernel/softirq.c | |||
| @@ -626,6 +626,7 @@ static int ksoftirqd(void * __bind_cpu) | |||
| 626 | preempt_enable_no_resched(); | 626 | preempt_enable_no_resched(); |
| 627 | cond_resched(); | 627 | cond_resched(); |
| 628 | preempt_disable(); | 628 | preempt_disable(); |
| 629 | rcu_qsctr_inc((long)__bind_cpu); | ||
| 629 | } | 630 | } |
| 630 | preempt_enable(); | 631 | preempt_enable(); |
| 631 | set_current_state(TASK_INTERRUPTIBLE); | 632 | set_current_state(TASK_INTERRUPTIBLE); |
diff --git a/kernel/tsacct.c b/kernel/tsacct.c index 43f891b05a4b..00d59d048edf 100644 --- a/kernel/tsacct.c +++ b/kernel/tsacct.c | |||
| @@ -122,8 +122,10 @@ void acct_update_integrals(struct task_struct *tsk) | |||
| 122 | if (likely(tsk->mm)) { | 122 | if (likely(tsk->mm)) { |
| 123 | cputime_t time, dtime; | 123 | cputime_t time, dtime; |
| 124 | struct timeval value; | 124 | struct timeval value; |
| 125 | unsigned long flags; | ||
| 125 | u64 delta; | 126 | u64 delta; |
| 126 | 127 | ||
| 128 | local_irq_save(flags); | ||
| 127 | time = tsk->stime + tsk->utime; | 129 | time = tsk->stime + tsk->utime; |
| 128 | dtime = cputime_sub(time, tsk->acct_timexpd); | 130 | dtime = cputime_sub(time, tsk->acct_timexpd); |
| 129 | jiffies_to_timeval(cputime_to_jiffies(dtime), &value); | 131 | jiffies_to_timeval(cputime_to_jiffies(dtime), &value); |
| @@ -131,10 +133,12 @@ void acct_update_integrals(struct task_struct *tsk) | |||
| 131 | delta = delta * USEC_PER_SEC + value.tv_usec; | 133 | delta = delta * USEC_PER_SEC + value.tv_usec; |
| 132 | 134 | ||
| 133 | if (delta == 0) | 135 | if (delta == 0) |
| 134 | return; | 136 | goto out; |
| 135 | tsk->acct_timexpd = time; | 137 | tsk->acct_timexpd = time; |
| 136 | tsk->acct_rss_mem1 += delta * get_mm_rss(tsk->mm); | 138 | tsk->acct_rss_mem1 += delta * get_mm_rss(tsk->mm); |
| 137 | tsk->acct_vm_mem1 += delta * tsk->mm->total_vm; | 139 | tsk->acct_vm_mem1 += delta * tsk->mm->total_vm; |
| 140 | out: | ||
| 141 | local_irq_restore(flags); | ||
| 138 | } | 142 | } |
| 139 | } | 143 | } |
| 140 | 144 | ||
diff --git a/kernel/user.c b/kernel/user.c index 6a9b696128c8..850e0ba41c1e 100644 --- a/kernel/user.c +++ b/kernel/user.c | |||
| @@ -20,7 +20,7 @@ | |||
| 20 | 20 | ||
| 21 | struct user_namespace init_user_ns = { | 21 | struct user_namespace init_user_ns = { |
| 22 | .kref = { | 22 | .kref = { |
| 23 | .refcount = ATOMIC_INIT(1), | 23 | .refcount = ATOMIC_INIT(2), |
| 24 | }, | 24 | }, |
| 25 | .creator = &root_user, | 25 | .creator = &root_user, |
| 26 | }; | 26 | }; |
| @@ -286,14 +286,12 @@ int __init uids_sysfs_init(void) | |||
| 286 | /* work function to remove sysfs directory for a user and free up | 286 | /* work function to remove sysfs directory for a user and free up |
| 287 | * corresponding structures. | 287 | * corresponding structures. |
| 288 | */ | 288 | */ |
| 289 | static void remove_user_sysfs_dir(struct work_struct *w) | 289 | static void cleanup_user_struct(struct work_struct *w) |
| 290 | { | 290 | { |
| 291 | struct user_struct *up = container_of(w, struct user_struct, work); | 291 | struct user_struct *up = container_of(w, struct user_struct, work); |
| 292 | unsigned long flags; | 292 | unsigned long flags; |
| 293 | int remove_user = 0; | 293 | int remove_user = 0; |
| 294 | 294 | ||
| 295 | if (up->user_ns != &init_user_ns) | ||
| 296 | return; | ||
| 297 | /* Make uid_hash_remove() + sysfs_remove_file() + kobject_del() | 295 | /* Make uid_hash_remove() + sysfs_remove_file() + kobject_del() |
| 298 | * atomic. | 296 | * atomic. |
| 299 | */ | 297 | */ |
| @@ -312,9 +310,11 @@ static void remove_user_sysfs_dir(struct work_struct *w) | |||
| 312 | if (!remove_user) | 310 | if (!remove_user) |
| 313 | goto done; | 311 | goto done; |
| 314 | 312 | ||
| 315 | kobject_uevent(&up->kobj, KOBJ_REMOVE); | 313 | if (up->user_ns == &init_user_ns) { |
| 316 | kobject_del(&up->kobj); | 314 | kobject_uevent(&up->kobj, KOBJ_REMOVE); |
| 317 | kobject_put(&up->kobj); | 315 | kobject_del(&up->kobj); |
| 316 | kobject_put(&up->kobj); | ||
| 317 | } | ||
| 318 | 318 | ||
| 319 | sched_destroy_user(up); | 319 | sched_destroy_user(up); |
| 320 | key_put(up->uid_keyring); | 320 | key_put(up->uid_keyring); |
| @@ -335,7 +335,7 @@ static void free_user(struct user_struct *up, unsigned long flags) | |||
| 335 | atomic_inc(&up->__count); | 335 | atomic_inc(&up->__count); |
| 336 | spin_unlock_irqrestore(&uidhash_lock, flags); | 336 | spin_unlock_irqrestore(&uidhash_lock, flags); |
| 337 | 337 | ||
| 338 | INIT_WORK(&up->work, remove_user_sysfs_dir); | 338 | INIT_WORK(&up->work, cleanup_user_struct); |
| 339 | schedule_work(&up->work); | 339 | schedule_work(&up->work); |
| 340 | } | 340 | } |
| 341 | 341 | ||
