diff options
Diffstat (limited to 'kernel')
-rw-r--r-- | kernel/cpuset.c | 1 | ||||
-rw-r--r-- | kernel/fork.c | 5 | ||||
-rw-r--r-- | kernel/lockdep.c | 9 | ||||
-rw-r--r-- | kernel/panic.c | 13 | ||||
-rw-r--r-- | kernel/pid.c | 12 | ||||
-rw-r--r-- | kernel/power/Kconfig | 11 | ||||
-rw-r--r-- | kernel/power/disk.c | 4 | ||||
-rw-r--r-- | kernel/power/swsusp.c | 9 | ||||
-rw-r--r-- | kernel/power/user.c | 2 | ||||
-rw-r--r-- | kernel/ptrace.c | 54 | ||||
-rw-r--r-- | kernel/relay.c | 2 | ||||
-rw-r--r-- | kernel/resource.c | 32 | ||||
-rw-r--r-- | kernel/signal.c | 5 | ||||
-rw-r--r-- | kernel/spinlock.c | 5 | ||||
-rw-r--r-- | kernel/sys.c | 31 | ||||
-rw-r--r-- | kernel/sysctl.c | 136 | ||||
-rw-r--r-- | kernel/unwind.c | 35 |
17 files changed, 201 insertions, 165 deletions
diff --git a/kernel/cpuset.c b/kernel/cpuset.c index cff41511269f..1b32c2c04c15 100644 --- a/kernel/cpuset.c +++ b/kernel/cpuset.c | |||
@@ -289,7 +289,6 @@ static struct inode *cpuset_new_inode(mode_t mode) | |||
289 | inode->i_mode = mode; | 289 | inode->i_mode = mode; |
290 | inode->i_uid = current->fsuid; | 290 | inode->i_uid = current->fsuid; |
291 | inode->i_gid = current->fsgid; | 291 | inode->i_gid = current->fsgid; |
292 | inode->i_blksize = PAGE_CACHE_SIZE; | ||
293 | inode->i_blocks = 0; | 292 | inode->i_blocks = 0; |
294 | inode->i_atime = inode->i_mtime = inode->i_ctime = CURRENT_TIME; | 293 | inode->i_atime = inode->i_mtime = inode->i_ctime = CURRENT_TIME; |
295 | inode->i_mapping->backing_dev_info = &cpuset_backing_dev_info; | 294 | inode->i_mapping->backing_dev_info = &cpuset_backing_dev_info; |
diff --git a/kernel/fork.c b/kernel/fork.c index f9b014e3e700..a0dad84567c9 100644 --- a/kernel/fork.c +++ b/kernel/fork.c | |||
@@ -45,6 +45,7 @@ | |||
45 | #include <linux/cn_proc.h> | 45 | #include <linux/cn_proc.h> |
46 | #include <linux/delayacct.h> | 46 | #include <linux/delayacct.h> |
47 | #include <linux/taskstats_kern.h> | 47 | #include <linux/taskstats_kern.h> |
48 | #include <linux/random.h> | ||
48 | 49 | ||
49 | #include <asm/pgtable.h> | 50 | #include <asm/pgtable.h> |
50 | #include <asm/pgalloc.h> | 51 | #include <asm/pgalloc.h> |
@@ -175,6 +176,10 @@ static struct task_struct *dup_task_struct(struct task_struct *orig) | |||
175 | tsk->thread_info = ti; | 176 | tsk->thread_info = ti; |
176 | setup_thread_stack(tsk, orig); | 177 | setup_thread_stack(tsk, orig); |
177 | 178 | ||
179 | #ifdef CONFIG_CC_STACKPROTECTOR | ||
180 | tsk->stack_canary = get_random_int(); | ||
181 | #endif | ||
182 | |||
178 | /* One for us, one for whoever does the "release_task()" (usually parent) */ | 183 | /* One for us, one for whoever does the "release_task()" (usually parent) */ |
179 | atomic_set(&tsk->usage,2); | 184 | atomic_set(&tsk->usage,2); |
180 | atomic_set(&tsk->fs_excl, 0); | 185 | atomic_set(&tsk->fs_excl, 0); |
diff --git a/kernel/lockdep.c b/kernel/lockdep.c index 9bad17884513..c088e5542e84 100644 --- a/kernel/lockdep.c +++ b/kernel/lockdep.c | |||
@@ -224,7 +224,14 @@ static int save_trace(struct stack_trace *trace) | |||
224 | trace->max_entries = MAX_STACK_TRACE_ENTRIES - nr_stack_trace_entries; | 224 | trace->max_entries = MAX_STACK_TRACE_ENTRIES - nr_stack_trace_entries; |
225 | trace->entries = stack_trace + nr_stack_trace_entries; | 225 | trace->entries = stack_trace + nr_stack_trace_entries; |
226 | 226 | ||
227 | save_stack_trace(trace, NULL, 0, 3); | 227 | trace->skip = 3; |
228 | trace->all_contexts = 0; | ||
229 | |||
230 | /* Make sure to not recurse in case the the unwinder needs to tak | ||
231 | e locks. */ | ||
232 | lockdep_off(); | ||
233 | save_stack_trace(trace, NULL); | ||
234 | lockdep_on(); | ||
228 | 235 | ||
229 | trace->max_entries = trace->nr_entries; | 236 | trace->max_entries = trace->nr_entries; |
230 | 237 | ||
diff --git a/kernel/panic.c b/kernel/panic.c index 8010b9b17aca..6ceb664fb52a 100644 --- a/kernel/panic.c +++ b/kernel/panic.c | |||
@@ -21,6 +21,7 @@ | |||
21 | #include <linux/debug_locks.h> | 21 | #include <linux/debug_locks.h> |
22 | 22 | ||
23 | int panic_on_oops; | 23 | int panic_on_oops; |
24 | int panic_on_unrecovered_nmi; | ||
24 | int tainted; | 25 | int tainted; |
25 | static int pause_on_oops; | 26 | static int pause_on_oops; |
26 | static int pause_on_oops_flag; | 27 | static int pause_on_oops_flag; |
@@ -270,3 +271,15 @@ void oops_exit(void) | |||
270 | { | 271 | { |
271 | do_oops_enter_exit(); | 272 | do_oops_enter_exit(); |
272 | } | 273 | } |
274 | |||
275 | #ifdef CONFIG_CC_STACKPROTECTOR | ||
276 | /* | ||
277 | * Called when gcc's -fstack-protector feature is used, and | ||
278 | * gcc detects corruption of the on-stack canary value | ||
279 | */ | ||
280 | void __stack_chk_fail(void) | ||
281 | { | ||
282 | panic("stack-protector: Kernel stack is corrupted"); | ||
283 | } | ||
284 | EXPORT_SYMBOL(__stack_chk_fail); | ||
285 | #endif | ||
diff --git a/kernel/pid.c b/kernel/pid.c index 93e212f20671..8387e8c68193 100644 --- a/kernel/pid.c +++ b/kernel/pid.c | |||
@@ -223,9 +223,6 @@ int fastcall attach_pid(struct task_struct *task, enum pid_type type, int nr) | |||
223 | struct pid_link *link; | 223 | struct pid_link *link; |
224 | struct pid *pid; | 224 | struct pid *pid; |
225 | 225 | ||
226 | WARN_ON(!task->pid); /* to be removed soon */ | ||
227 | WARN_ON(!nr); /* to be removed soon */ | ||
228 | |||
229 | link = &task->pids[type]; | 226 | link = &task->pids[type]; |
230 | link->pid = pid = find_pid(nr); | 227 | link->pid = pid = find_pid(nr); |
231 | hlist_add_head_rcu(&link->node, &pid->tasks[type]); | 228 | hlist_add_head_rcu(&link->node, &pid->tasks[type]); |
@@ -252,6 +249,15 @@ void fastcall detach_pid(struct task_struct *task, enum pid_type type) | |||
252 | free_pid(pid); | 249 | free_pid(pid); |
253 | } | 250 | } |
254 | 251 | ||
252 | /* transfer_pid is an optimization of attach_pid(new), detach_pid(old) */ | ||
253 | void fastcall transfer_pid(struct task_struct *old, struct task_struct *new, | ||
254 | enum pid_type type) | ||
255 | { | ||
256 | new->pids[type].pid = old->pids[type].pid; | ||
257 | hlist_replace_rcu(&old->pids[type].node, &new->pids[type].node); | ||
258 | old->pids[type].pid = NULL; | ||
259 | } | ||
260 | |||
255 | struct task_struct * fastcall pid_task(struct pid *pid, enum pid_type type) | 261 | struct task_struct * fastcall pid_task(struct pid *pid, enum pid_type type) |
256 | { | 262 | { |
257 | struct task_struct *result = NULL; | 263 | struct task_struct *result = NULL; |
diff --git a/kernel/power/Kconfig b/kernel/power/Kconfig index 4b6e2f18e056..825068ca3479 100644 --- a/kernel/power/Kconfig +++ b/kernel/power/Kconfig | |||
@@ -64,6 +64,17 @@ config PM_TRACE | |||
64 | CAUTION: this option will cause your machine's real-time clock to be | 64 | CAUTION: this option will cause your machine's real-time clock to be |
65 | set to an invalid time after a resume. | 65 | set to an invalid time after a resume. |
66 | 66 | ||
67 | config PM_SYSFS_DEPRECATED | ||
68 | bool "Driver model /sys/devices/.../power/state files (DEPRECATED)" | ||
69 | depends on PM && SYSFS | ||
70 | default n | ||
71 | help | ||
72 | The driver model started out with a sysfs file intended to provide | ||
73 | a userspace hook for device power management. This feature has never | ||
74 | worked very well, except for limited testing purposes, and so it will | ||
75 | be removed. It's not clear that a generic mechanism could really | ||
76 | handle the wide variability of device power states; any replacements | ||
77 | are likely to be bus or driver specific. | ||
67 | 78 | ||
68 | config SOFTWARE_SUSPEND | 79 | config SOFTWARE_SUSPEND |
69 | bool "Software Suspend" | 80 | bool "Software Suspend" |
diff --git a/kernel/power/disk.c b/kernel/power/disk.c index 7c7b9b65e365..d72234942798 100644 --- a/kernel/power/disk.c +++ b/kernel/power/disk.c | |||
@@ -103,7 +103,7 @@ static void unprepare_processes(void) | |||
103 | } | 103 | } |
104 | 104 | ||
105 | /** | 105 | /** |
106 | * pm_suspend_disk - The granpappy of power management. | 106 | * pm_suspend_disk - The granpappy of hibernation power management. |
107 | * | 107 | * |
108 | * If we're going through the firmware, then get it over with quickly. | 108 | * If we're going through the firmware, then get it over with quickly. |
109 | * | 109 | * |
@@ -212,7 +212,7 @@ static int software_resume(void) | |||
212 | 212 | ||
213 | pr_debug("PM: Preparing devices for restore.\n"); | 213 | pr_debug("PM: Preparing devices for restore.\n"); |
214 | 214 | ||
215 | if ((error = device_suspend(PMSG_FREEZE))) { | 215 | if ((error = device_suspend(PMSG_PRETHAW))) { |
216 | printk("Some devices failed to suspend\n"); | 216 | printk("Some devices failed to suspend\n"); |
217 | swsusp_free(); | 217 | swsusp_free(); |
218 | goto Thaw; | 218 | goto Thaw; |
diff --git a/kernel/power/swsusp.c b/kernel/power/swsusp.c index 8ef677ea0cea..0b66659dc516 100644 --- a/kernel/power/swsusp.c +++ b/kernel/power/swsusp.c | |||
@@ -247,6 +247,9 @@ int swsusp_suspend(void) | |||
247 | restore_processor_state(); | 247 | restore_processor_state(); |
248 | Restore_highmem: | 248 | Restore_highmem: |
249 | restore_highmem(); | 249 | restore_highmem(); |
250 | /* NOTE: device_power_up() is just a resume() for devices | ||
251 | * that suspended with irqs off ... no overall powerup. | ||
252 | */ | ||
250 | device_power_up(); | 253 | device_power_up(); |
251 | Enable_irqs: | 254 | Enable_irqs: |
252 | local_irq_enable(); | 255 | local_irq_enable(); |
@@ -256,8 +259,12 @@ Enable_irqs: | |||
256 | int swsusp_resume(void) | 259 | int swsusp_resume(void) |
257 | { | 260 | { |
258 | int error; | 261 | int error; |
262 | |||
259 | local_irq_disable(); | 263 | local_irq_disable(); |
260 | if (device_power_down(PMSG_FREEZE)) | 264 | /* NOTE: device_power_down() is just a suspend() with irqs off; |
265 | * it has no special "power things down" semantics | ||
266 | */ | ||
267 | if (device_power_down(PMSG_PRETHAW)) | ||
261 | printk(KERN_ERR "Some devices failed to power down, very bad\n"); | 268 | printk(KERN_ERR "Some devices failed to power down, very bad\n"); |
262 | /* We'll ignore saved state, but this gets preempt count (etc) right */ | 269 | /* We'll ignore saved state, but this gets preempt count (etc) right */ |
263 | save_processor_state(); | 270 | save_processor_state(); |
diff --git a/kernel/power/user.c b/kernel/power/user.c index 2e4499f3e4d9..72825c853cd7 100644 --- a/kernel/power/user.c +++ b/kernel/power/user.c | |||
@@ -196,7 +196,7 @@ static int snapshot_ioctl(struct inode *inode, struct file *filp, | |||
196 | snapshot_free_unused_memory(&data->handle); | 196 | snapshot_free_unused_memory(&data->handle); |
197 | down(&pm_sem); | 197 | down(&pm_sem); |
198 | pm_prepare_console(); | 198 | pm_prepare_console(); |
199 | error = device_suspend(PMSG_FREEZE); | 199 | error = device_suspend(PMSG_PRETHAW); |
200 | if (!error) { | 200 | if (!error) { |
201 | error = swsusp_resume(); | 201 | error = swsusp_resume(); |
202 | device_resume(); | 202 | device_resume(); |
diff --git a/kernel/ptrace.c b/kernel/ptrace.c index 9a111f70145c..8aad0331d82e 100644 --- a/kernel/ptrace.c +++ b/kernel/ptrace.c | |||
@@ -241,60 +241,6 @@ int ptrace_detach(struct task_struct *child, unsigned int data) | |||
241 | return 0; | 241 | return 0; |
242 | } | 242 | } |
243 | 243 | ||
244 | /* | ||
245 | * Access another process' address space. | ||
246 | * Source/target buffer must be kernel space, | ||
247 | * Do not walk the page table directly, use get_user_pages | ||
248 | */ | ||
249 | |||
250 | int access_process_vm(struct task_struct *tsk, unsigned long addr, void *buf, int len, int write) | ||
251 | { | ||
252 | struct mm_struct *mm; | ||
253 | struct vm_area_struct *vma; | ||
254 | struct page *page; | ||
255 | void *old_buf = buf; | ||
256 | |||
257 | mm = get_task_mm(tsk); | ||
258 | if (!mm) | ||
259 | return 0; | ||
260 | |||
261 | down_read(&mm->mmap_sem); | ||
262 | /* ignore errors, just check how much was sucessfully transfered */ | ||
263 | while (len) { | ||
264 | int bytes, ret, offset; | ||
265 | void *maddr; | ||
266 | |||
267 | ret = get_user_pages(tsk, mm, addr, 1, | ||
268 | write, 1, &page, &vma); | ||
269 | if (ret <= 0) | ||
270 | break; | ||
271 | |||
272 | bytes = len; | ||
273 | offset = addr & (PAGE_SIZE-1); | ||
274 | if (bytes > PAGE_SIZE-offset) | ||
275 | bytes = PAGE_SIZE-offset; | ||
276 | |||
277 | maddr = kmap(page); | ||
278 | if (write) { | ||
279 | copy_to_user_page(vma, page, addr, | ||
280 | maddr + offset, buf, bytes); | ||
281 | set_page_dirty_lock(page); | ||
282 | } else { | ||
283 | copy_from_user_page(vma, page, addr, | ||
284 | buf, maddr + offset, bytes); | ||
285 | } | ||
286 | kunmap(page); | ||
287 | page_cache_release(page); | ||
288 | len -= bytes; | ||
289 | buf += bytes; | ||
290 | addr += bytes; | ||
291 | } | ||
292 | up_read(&mm->mmap_sem); | ||
293 | mmput(mm); | ||
294 | |||
295 | return buf - old_buf; | ||
296 | } | ||
297 | |||
298 | int ptrace_readdata(struct task_struct *tsk, unsigned long src, char __user *dst, int len) | 244 | int ptrace_readdata(struct task_struct *tsk, unsigned long src, char __user *dst, int len) |
299 | { | 245 | { |
300 | int copied = 0; | 246 | int copied = 0; |
diff --git a/kernel/relay.c b/kernel/relay.c index 33345e73485c..85786ff2a4f9 100644 --- a/kernel/relay.c +++ b/kernel/relay.c | |||
@@ -669,7 +669,7 @@ EXPORT_SYMBOL_GPL(relay_flush); | |||
669 | */ | 669 | */ |
670 | static int relay_file_open(struct inode *inode, struct file *filp) | 670 | static int relay_file_open(struct inode *inode, struct file *filp) |
671 | { | 671 | { |
672 | struct rchan_buf *buf = inode->u.generic_ip; | 672 | struct rchan_buf *buf = inode->i_private; |
673 | kref_get(&buf->kref); | 673 | kref_get(&buf->kref); |
674 | filp->private_data = buf; | 674 | filp->private_data = buf; |
675 | 675 | ||
diff --git a/kernel/resource.c b/kernel/resource.c index 46286434af80..9db38a1a7520 100644 --- a/kernel/resource.c +++ b/kernel/resource.c | |||
@@ -344,12 +344,11 @@ EXPORT_SYMBOL(allocate_resource); | |||
344 | * | 344 | * |
345 | * Returns 0 on success, -EBUSY if the resource can't be inserted. | 345 | * Returns 0 on success, -EBUSY if the resource can't be inserted. |
346 | * | 346 | * |
347 | * This function is equivalent of request_resource when no conflict | 347 | * This function is equivalent to request_resource when no conflict |
348 | * happens. If a conflict happens, and the conflicting resources | 348 | * happens. If a conflict happens, and the conflicting resources |
349 | * entirely fit within the range of the new resource, then the new | 349 | * entirely fit within the range of the new resource, then the new |
350 | * resource is inserted and the conflicting resources become childs of | 350 | * resource is inserted and the conflicting resources become children of |
351 | * the new resource. Otherwise the new resource becomes the child of | 351 | * the new resource. |
352 | * the conflicting resource | ||
353 | */ | 352 | */ |
354 | int insert_resource(struct resource *parent, struct resource *new) | 353 | int insert_resource(struct resource *parent, struct resource *new) |
355 | { | 354 | { |
@@ -357,20 +356,21 @@ int insert_resource(struct resource *parent, struct resource *new) | |||
357 | struct resource *first, *next; | 356 | struct resource *first, *next; |
358 | 357 | ||
359 | write_lock(&resource_lock); | 358 | write_lock(&resource_lock); |
360 | begin: | ||
361 | result = 0; | ||
362 | first = __request_resource(parent, new); | ||
363 | if (!first) | ||
364 | goto out; | ||
365 | 359 | ||
366 | result = -EBUSY; | 360 | for (;; parent = first) { |
367 | if (first == parent) | 361 | result = 0; |
368 | goto out; | 362 | first = __request_resource(parent, new); |
363 | if (!first) | ||
364 | goto out; | ||
369 | 365 | ||
370 | /* Resource fully contained by the clashing resource? Recurse into it */ | 366 | result = -EBUSY; |
371 | if (first->start <= new->start && first->end >= new->end) { | 367 | if (first == parent) |
372 | parent = first; | 368 | goto out; |
373 | goto begin; | 369 | |
370 | if ((first->start > new->start) || (first->end < new->end)) | ||
371 | break; | ||
372 | if ((first->start == new->start) && (first->end == new->end)) | ||
373 | break; | ||
374 | } | 374 | } |
375 | 375 | ||
376 | for (next = first; ; next = next->sibling) { | 376 | for (next = first; ; next = next->sibling) { |
diff --git a/kernel/signal.c b/kernel/signal.c index bfdb5686fa3e..05853a7337e3 100644 --- a/kernel/signal.c +++ b/kernel/signal.c | |||
@@ -2577,6 +2577,11 @@ asmlinkage long sys_rt_sigsuspend(sigset_t __user *unewset, size_t sigsetsize) | |||
2577 | } | 2577 | } |
2578 | #endif /* __ARCH_WANT_SYS_RT_SIGSUSPEND */ | 2578 | #endif /* __ARCH_WANT_SYS_RT_SIGSUSPEND */ |
2579 | 2579 | ||
2580 | __attribute__((weak)) const char *arch_vma_name(struct vm_area_struct *vma) | ||
2581 | { | ||
2582 | return NULL; | ||
2583 | } | ||
2584 | |||
2580 | void __init signals_init(void) | 2585 | void __init signals_init(void) |
2581 | { | 2586 | { |
2582 | sigqueue_cachep = | 2587 | sigqueue_cachep = |
diff --git a/kernel/spinlock.c b/kernel/spinlock.c index fb524b009eef..9644a41e0bef 100644 --- a/kernel/spinlock.c +++ b/kernel/spinlock.c | |||
@@ -7,6 +7,11 @@ | |||
7 | * | 7 | * |
8 | * This file contains the spinlock/rwlock implementations for the | 8 | * This file contains the spinlock/rwlock implementations for the |
9 | * SMP and the DEBUG_SPINLOCK cases. (UP-nondebug inlines them) | 9 | * SMP and the DEBUG_SPINLOCK cases. (UP-nondebug inlines them) |
10 | * | ||
11 | * Note that some architectures have special knowledge about the | ||
12 | * stack frames of these functions in their profile_pc. If you | ||
13 | * change anything significant here that could change the stack | ||
14 | * frame contact the architecture maintainers. | ||
10 | */ | 15 | */ |
11 | 16 | ||
12 | #include <linux/linkage.h> | 17 | #include <linux/linkage.h> |
diff --git a/kernel/sys.c b/kernel/sys.c index e236f98f7ec5..3f894775488d 100644 --- a/kernel/sys.c +++ b/kernel/sys.c | |||
@@ -28,6 +28,7 @@ | |||
28 | #include <linux/tty.h> | 28 | #include <linux/tty.h> |
29 | #include <linux/signal.h> | 29 | #include <linux/signal.h> |
30 | #include <linux/cn_proc.h> | 30 | #include <linux/cn_proc.h> |
31 | #include <linux/getcpu.h> | ||
31 | 32 | ||
32 | #include <linux/compat.h> | 33 | #include <linux/compat.h> |
33 | #include <linux/syscalls.h> | 34 | #include <linux/syscalls.h> |
@@ -2062,3 +2063,33 @@ asmlinkage long sys_prctl(int option, unsigned long arg2, unsigned long arg3, | |||
2062 | } | 2063 | } |
2063 | return error; | 2064 | return error; |
2064 | } | 2065 | } |
2066 | |||
2067 | asmlinkage long sys_getcpu(unsigned __user *cpup, unsigned __user *nodep, | ||
2068 | struct getcpu_cache __user *cache) | ||
2069 | { | ||
2070 | int err = 0; | ||
2071 | int cpu = raw_smp_processor_id(); | ||
2072 | if (cpup) | ||
2073 | err |= put_user(cpu, cpup); | ||
2074 | if (nodep) | ||
2075 | err |= put_user(cpu_to_node(cpu), nodep); | ||
2076 | if (cache) { | ||
2077 | /* | ||
2078 | * The cache is not needed for this implementation, | ||
2079 | * but make sure user programs pass something | ||
2080 | * valid. vsyscall implementations can instead make | ||
2081 | * good use of the cache. Only use t0 and t1 because | ||
2082 | * these are available in both 32bit and 64bit ABI (no | ||
2083 | * need for a compat_getcpu). 32bit has enough | ||
2084 | * padding | ||
2085 | */ | ||
2086 | unsigned long t0, t1; | ||
2087 | get_user(t0, &cache->t0); | ||
2088 | get_user(t1, &cache->t1); | ||
2089 | t0++; | ||
2090 | t1++; | ||
2091 | put_user(t0, &cache->t0); | ||
2092 | put_user(t1, &cache->t1); | ||
2093 | } | ||
2094 | return err ? -EFAULT : 0; | ||
2095 | } | ||
diff --git a/kernel/sysctl.c b/kernel/sysctl.c index fd43c3e6786b..8bfa7d117c54 100644 --- a/kernel/sysctl.c +++ b/kernel/sysctl.c | |||
@@ -76,8 +76,9 @@ extern int compat_log; | |||
76 | 76 | ||
77 | #if defined(CONFIG_X86_LOCAL_APIC) && defined(CONFIG_X86) | 77 | #if defined(CONFIG_X86_LOCAL_APIC) && defined(CONFIG_X86) |
78 | int unknown_nmi_panic; | 78 | int unknown_nmi_panic; |
79 | extern int proc_unknown_nmi_panic(ctl_table *, int, struct file *, | 79 | int nmi_watchdog_enabled; |
80 | void __user *, size_t *, loff_t *); | 80 | extern int proc_nmi_enabled(struct ctl_table *, int , struct file *, |
81 | void __user *, size_t *, loff_t *); | ||
81 | #endif | 82 | #endif |
82 | 83 | ||
83 | /* this is needed for the proc_dointvec_minmax for [fs_]overflow UID and GID */ | 84 | /* this is needed for the proc_dointvec_minmax for [fs_]overflow UID and GID */ |
@@ -136,8 +137,11 @@ extern int no_unaligned_warning; | |||
136 | extern int max_lock_depth; | 137 | extern int max_lock_depth; |
137 | #endif | 138 | #endif |
138 | 139 | ||
139 | static int parse_table(int __user *, int, void __user *, size_t __user *, void __user *, size_t, | 140 | #ifdef CONFIG_SYSCTL_SYSCALL |
140 | ctl_table *, void **); | 141 | static int parse_table(int __user *, int, void __user *, size_t __user *, |
142 | void __user *, size_t, ctl_table *, void **); | ||
143 | #endif | ||
144 | |||
141 | static int proc_doutsstring(ctl_table *table, int write, struct file *filp, | 145 | static int proc_doutsstring(ctl_table *table, int write, struct file *filp, |
142 | void __user *buffer, size_t *lenp, loff_t *ppos); | 146 | void __user *buffer, size_t *lenp, loff_t *ppos); |
143 | 147 | ||
@@ -164,7 +168,7 @@ int sysctl_legacy_va_layout; | |||
164 | 168 | ||
165 | /* /proc declarations: */ | 169 | /* /proc declarations: */ |
166 | 170 | ||
167 | #ifdef CONFIG_PROC_FS | 171 | #ifdef CONFIG_PROC_SYSCTL |
168 | 172 | ||
169 | static ssize_t proc_readsys(struct file *, char __user *, size_t, loff_t *); | 173 | static ssize_t proc_readsys(struct file *, char __user *, size_t, loff_t *); |
170 | static ssize_t proc_writesys(struct file *, const char __user *, size_t, loff_t *); | 174 | static ssize_t proc_writesys(struct file *, const char __user *, size_t, loff_t *); |
@@ -628,11 +632,27 @@ static ctl_table kern_table[] = { | |||
628 | .data = &unknown_nmi_panic, | 632 | .data = &unknown_nmi_panic, |
629 | .maxlen = sizeof (int), | 633 | .maxlen = sizeof (int), |
630 | .mode = 0644, | 634 | .mode = 0644, |
631 | .proc_handler = &proc_unknown_nmi_panic, | 635 | .proc_handler = &proc_dointvec, |
636 | }, | ||
637 | { | ||
638 | .ctl_name = KERN_NMI_WATCHDOG, | ||
639 | .procname = "nmi_watchdog", | ||
640 | .data = &nmi_watchdog_enabled, | ||
641 | .maxlen = sizeof (int), | ||
642 | .mode = 0644, | ||
643 | .proc_handler = &proc_nmi_enabled, | ||
632 | }, | 644 | }, |
633 | #endif | 645 | #endif |
634 | #if defined(CONFIG_X86) | 646 | #if defined(CONFIG_X86) |
635 | { | 647 | { |
648 | .ctl_name = KERN_PANIC_ON_NMI, | ||
649 | .procname = "panic_on_unrecovered_nmi", | ||
650 | .data = &panic_on_unrecovered_nmi, | ||
651 | .maxlen = sizeof(int), | ||
652 | .mode = 0644, | ||
653 | .proc_handler = &proc_dointvec, | ||
654 | }, | ||
655 | { | ||
636 | .ctl_name = KERN_BOOTLOADER_TYPE, | 656 | .ctl_name = KERN_BOOTLOADER_TYPE, |
637 | .procname = "bootloader_type", | 657 | .procname = "bootloader_type", |
638 | .data = &bootloader_type, | 658 | .data = &bootloader_type, |
@@ -1149,12 +1169,13 @@ static void start_unregistering(struct ctl_table_header *p) | |||
1149 | 1169 | ||
1150 | void __init sysctl_init(void) | 1170 | void __init sysctl_init(void) |
1151 | { | 1171 | { |
1152 | #ifdef CONFIG_PROC_FS | 1172 | #ifdef CONFIG_PROC_SYSCTL |
1153 | register_proc_table(root_table, proc_sys_root, &root_table_header); | 1173 | register_proc_table(root_table, proc_sys_root, &root_table_header); |
1154 | init_irq_proc(); | 1174 | init_irq_proc(); |
1155 | #endif | 1175 | #endif |
1156 | } | 1176 | } |
1157 | 1177 | ||
1178 | #ifdef CONFIG_SYSCTL_SYSCALL | ||
1158 | int do_sysctl(int __user *name, int nlen, void __user *oldval, size_t __user *oldlenp, | 1179 | int do_sysctl(int __user *name, int nlen, void __user *oldval, size_t __user *oldlenp, |
1159 | void __user *newval, size_t newlen) | 1180 | void __user *newval, size_t newlen) |
1160 | { | 1181 | { |
@@ -1208,6 +1229,7 @@ asmlinkage long sys_sysctl(struct __sysctl_args __user *args) | |||
1208 | unlock_kernel(); | 1229 | unlock_kernel(); |
1209 | return error; | 1230 | return error; |
1210 | } | 1231 | } |
1232 | #endif /* CONFIG_SYSCTL_SYSCALL */ | ||
1211 | 1233 | ||
1212 | /* | 1234 | /* |
1213 | * ctl_perm does NOT grant the superuser all rights automatically, because | 1235 | * ctl_perm does NOT grant the superuser all rights automatically, because |
@@ -1234,6 +1256,7 @@ static inline int ctl_perm(ctl_table *table, int op) | |||
1234 | return test_perm(table->mode, op); | 1256 | return test_perm(table->mode, op); |
1235 | } | 1257 | } |
1236 | 1258 | ||
1259 | #ifdef CONFIG_SYSCTL_SYSCALL | ||
1237 | static int parse_table(int __user *name, int nlen, | 1260 | static int parse_table(int __user *name, int nlen, |
1238 | void __user *oldval, size_t __user *oldlenp, | 1261 | void __user *oldval, size_t __user *oldlenp, |
1239 | void __user *newval, size_t newlen, | 1262 | void __user *newval, size_t newlen, |
@@ -1323,6 +1346,7 @@ int do_sysctl_strategy (ctl_table *table, | |||
1323 | } | 1346 | } |
1324 | return 0; | 1347 | return 0; |
1325 | } | 1348 | } |
1349 | #endif /* CONFIG_SYSCTL_SYSCALL */ | ||
1326 | 1350 | ||
1327 | /** | 1351 | /** |
1328 | * register_sysctl_table - register a sysctl hierarchy | 1352 | * register_sysctl_table - register a sysctl hierarchy |
@@ -1410,7 +1434,7 @@ struct ctl_table_header *register_sysctl_table(ctl_table * table, | |||
1410 | else | 1434 | else |
1411 | list_add_tail(&tmp->ctl_entry, &root_table_header.ctl_entry); | 1435 | list_add_tail(&tmp->ctl_entry, &root_table_header.ctl_entry); |
1412 | spin_unlock(&sysctl_lock); | 1436 | spin_unlock(&sysctl_lock); |
1413 | #ifdef CONFIG_PROC_FS | 1437 | #ifdef CONFIG_PROC_SYSCTL |
1414 | register_proc_table(table, proc_sys_root, tmp); | 1438 | register_proc_table(table, proc_sys_root, tmp); |
1415 | #endif | 1439 | #endif |
1416 | return tmp; | 1440 | return tmp; |
@@ -1428,18 +1452,31 @@ void unregister_sysctl_table(struct ctl_table_header * header) | |||
1428 | might_sleep(); | 1452 | might_sleep(); |
1429 | spin_lock(&sysctl_lock); | 1453 | spin_lock(&sysctl_lock); |
1430 | start_unregistering(header); | 1454 | start_unregistering(header); |
1431 | #ifdef CONFIG_PROC_FS | 1455 | #ifdef CONFIG_PROC_SYSCTL |
1432 | unregister_proc_table(header->ctl_table, proc_sys_root); | 1456 | unregister_proc_table(header->ctl_table, proc_sys_root); |
1433 | #endif | 1457 | #endif |
1434 | spin_unlock(&sysctl_lock); | 1458 | spin_unlock(&sysctl_lock); |
1435 | kfree(header); | 1459 | kfree(header); |
1436 | } | 1460 | } |
1437 | 1461 | ||
1462 | #else /* !CONFIG_SYSCTL */ | ||
1463 | struct ctl_table_header * register_sysctl_table(ctl_table * table, | ||
1464 | int insert_at_head) | ||
1465 | { | ||
1466 | return NULL; | ||
1467 | } | ||
1468 | |||
1469 | void unregister_sysctl_table(struct ctl_table_header * table) | ||
1470 | { | ||
1471 | } | ||
1472 | |||
1473 | #endif /* CONFIG_SYSCTL */ | ||
1474 | |||
1438 | /* | 1475 | /* |
1439 | * /proc/sys support | 1476 | * /proc/sys support |
1440 | */ | 1477 | */ |
1441 | 1478 | ||
1442 | #ifdef CONFIG_PROC_FS | 1479 | #ifdef CONFIG_PROC_SYSCTL |
1443 | 1480 | ||
1444 | /* Scan the sysctl entries in table and add them all into /proc */ | 1481 | /* Scan the sysctl entries in table and add them all into /proc */ |
1445 | static void register_proc_table(ctl_table * table, struct proc_dir_entry *root, void *set) | 1482 | static void register_proc_table(ctl_table * table, struct proc_dir_entry *root, void *set) |
@@ -2301,6 +2338,7 @@ int proc_doulongvec_ms_jiffies_minmax(ctl_table *table, int write, | |||
2301 | #endif /* CONFIG_PROC_FS */ | 2338 | #endif /* CONFIG_PROC_FS */ |
2302 | 2339 | ||
2303 | 2340 | ||
2341 | #ifdef CONFIG_SYSCTL_SYSCALL | ||
2304 | /* | 2342 | /* |
2305 | * General sysctl support routines | 2343 | * General sysctl support routines |
2306 | */ | 2344 | */ |
@@ -2443,11 +2481,19 @@ int sysctl_ms_jiffies(ctl_table *table, int __user *name, int nlen, | |||
2443 | return 1; | 2481 | return 1; |
2444 | } | 2482 | } |
2445 | 2483 | ||
2446 | #else /* CONFIG_SYSCTL */ | 2484 | #else /* CONFIG_SYSCTL_SYSCALL */ |
2447 | 2485 | ||
2448 | 2486 | ||
2449 | asmlinkage long sys_sysctl(struct __sysctl_args __user *args) | 2487 | asmlinkage long sys_sysctl(struct __sysctl_args __user *args) |
2450 | { | 2488 | { |
2489 | static int msg_count; | ||
2490 | |||
2491 | if (msg_count < 5) { | ||
2492 | msg_count++; | ||
2493 | printk(KERN_INFO | ||
2494 | "warning: process `%s' used the removed sysctl " | ||
2495 | "system call\n", current->comm); | ||
2496 | } | ||
2451 | return -ENOSYS; | 2497 | return -ENOSYS; |
2452 | } | 2498 | } |
2453 | 2499 | ||
@@ -2479,73 +2525,7 @@ int sysctl_ms_jiffies(ctl_table *table, int __user *name, int nlen, | |||
2479 | return -ENOSYS; | 2525 | return -ENOSYS; |
2480 | } | 2526 | } |
2481 | 2527 | ||
2482 | int proc_dostring(ctl_table *table, int write, struct file *filp, | 2528 | #endif /* CONFIG_SYSCTL_SYSCALL */ |
2483 | void __user *buffer, size_t *lenp, loff_t *ppos) | ||
2484 | { | ||
2485 | return -ENOSYS; | ||
2486 | } | ||
2487 | |||
2488 | int proc_dointvec(ctl_table *table, int write, struct file *filp, | ||
2489 | void __user *buffer, size_t *lenp, loff_t *ppos) | ||
2490 | { | ||
2491 | return -ENOSYS; | ||
2492 | } | ||
2493 | |||
2494 | int proc_dointvec_bset(ctl_table *table, int write, struct file *filp, | ||
2495 | void __user *buffer, size_t *lenp, loff_t *ppos) | ||
2496 | { | ||
2497 | return -ENOSYS; | ||
2498 | } | ||
2499 | |||
2500 | int proc_dointvec_minmax(ctl_table *table, int write, struct file *filp, | ||
2501 | void __user *buffer, size_t *lenp, loff_t *ppos) | ||
2502 | { | ||
2503 | return -ENOSYS; | ||
2504 | } | ||
2505 | |||
2506 | int proc_dointvec_jiffies(ctl_table *table, int write, struct file *filp, | ||
2507 | void __user *buffer, size_t *lenp, loff_t *ppos) | ||
2508 | { | ||
2509 | return -ENOSYS; | ||
2510 | } | ||
2511 | |||
2512 | int proc_dointvec_userhz_jiffies(ctl_table *table, int write, struct file *filp, | ||
2513 | void __user *buffer, size_t *lenp, loff_t *ppos) | ||
2514 | { | ||
2515 | return -ENOSYS; | ||
2516 | } | ||
2517 | |||
2518 | int proc_dointvec_ms_jiffies(ctl_table *table, int write, struct file *filp, | ||
2519 | void __user *buffer, size_t *lenp, loff_t *ppos) | ||
2520 | { | ||
2521 | return -ENOSYS; | ||
2522 | } | ||
2523 | |||
2524 | int proc_doulongvec_minmax(ctl_table *table, int write, struct file *filp, | ||
2525 | void __user *buffer, size_t *lenp, loff_t *ppos) | ||
2526 | { | ||
2527 | return -ENOSYS; | ||
2528 | } | ||
2529 | |||
2530 | int proc_doulongvec_ms_jiffies_minmax(ctl_table *table, int write, | ||
2531 | struct file *filp, | ||
2532 | void __user *buffer, | ||
2533 | size_t *lenp, loff_t *ppos) | ||
2534 | { | ||
2535 | return -ENOSYS; | ||
2536 | } | ||
2537 | |||
2538 | struct ctl_table_header * register_sysctl_table(ctl_table * table, | ||
2539 | int insert_at_head) | ||
2540 | { | ||
2541 | return NULL; | ||
2542 | } | ||
2543 | |||
2544 | void unregister_sysctl_table(struct ctl_table_header * table) | ||
2545 | { | ||
2546 | } | ||
2547 | |||
2548 | #endif /* CONFIG_SYSCTL */ | ||
2549 | 2529 | ||
2550 | /* | 2530 | /* |
2551 | * No sense putting this after each symbol definition, twice, | 2531 | * No sense putting this after each symbol definition, twice, |
diff --git a/kernel/unwind.c b/kernel/unwind.c index f69c804c8e62..3430475fcd88 100644 --- a/kernel/unwind.c +++ b/kernel/unwind.c | |||
@@ -603,6 +603,7 @@ int unwind(struct unwind_frame_info *frame) | |||
603 | #define FRAME_REG(r, t) (((t *)frame)[reg_info[r].offs]) | 603 | #define FRAME_REG(r, t) (((t *)frame)[reg_info[r].offs]) |
604 | const u32 *fde = NULL, *cie = NULL; | 604 | const u32 *fde = NULL, *cie = NULL; |
605 | const u8 *ptr = NULL, *end = NULL; | 605 | const u8 *ptr = NULL, *end = NULL; |
606 | unsigned long pc = UNW_PC(frame) - frame->call_frame; | ||
606 | unsigned long startLoc = 0, endLoc = 0, cfa; | 607 | unsigned long startLoc = 0, endLoc = 0, cfa; |
607 | unsigned i; | 608 | unsigned i; |
608 | signed ptrType = -1; | 609 | signed ptrType = -1; |
@@ -612,7 +613,7 @@ int unwind(struct unwind_frame_info *frame) | |||
612 | 613 | ||
613 | if (UNW_PC(frame) == 0) | 614 | if (UNW_PC(frame) == 0) |
614 | return -EINVAL; | 615 | return -EINVAL; |
615 | if ((table = find_table(UNW_PC(frame))) != NULL | 616 | if ((table = find_table(pc)) != NULL |
616 | && !(table->size & (sizeof(*fde) - 1))) { | 617 | && !(table->size & (sizeof(*fde) - 1))) { |
617 | unsigned long tableSize = table->size; | 618 | unsigned long tableSize = table->size; |
618 | 619 | ||
@@ -647,7 +648,7 @@ int unwind(struct unwind_frame_info *frame) | |||
647 | ptrType & DW_EH_PE_indirect | 648 | ptrType & DW_EH_PE_indirect |
648 | ? ptrType | 649 | ? ptrType |
649 | : ptrType & (DW_EH_PE_FORM|DW_EH_PE_signed)); | 650 | : ptrType & (DW_EH_PE_FORM|DW_EH_PE_signed)); |
650 | if (UNW_PC(frame) >= startLoc && UNW_PC(frame) < endLoc) | 651 | if (pc >= startLoc && pc < endLoc) |
651 | break; | 652 | break; |
652 | cie = NULL; | 653 | cie = NULL; |
653 | } | 654 | } |
@@ -657,16 +658,28 @@ int unwind(struct unwind_frame_info *frame) | |||
657 | state.cieEnd = ptr; /* keep here temporarily */ | 658 | state.cieEnd = ptr; /* keep here temporarily */ |
658 | ptr = (const u8 *)(cie + 2); | 659 | ptr = (const u8 *)(cie + 2); |
659 | end = (const u8 *)(cie + 1) + *cie; | 660 | end = (const u8 *)(cie + 1) + *cie; |
661 | frame->call_frame = 1; | ||
660 | if ((state.version = *ptr) != 1) | 662 | if ((state.version = *ptr) != 1) |
661 | cie = NULL; /* unsupported version */ | 663 | cie = NULL; /* unsupported version */ |
662 | else if (*++ptr) { | 664 | else if (*++ptr) { |
663 | /* check if augmentation size is first (and thus present) */ | 665 | /* check if augmentation size is first (and thus present) */ |
664 | if (*ptr == 'z') { | 666 | if (*ptr == 'z') { |
665 | /* check for ignorable (or already handled) | 667 | while (++ptr < end && *ptr) { |
666 | * nul-terminated augmentation string */ | 668 | switch(*ptr) { |
667 | while (++ptr < end && *ptr) | 669 | /* check for ignorable (or already handled) |
668 | if (strchr("LPR", *ptr) == NULL) | 670 | * nul-terminated augmentation string */ |
671 | case 'L': | ||
672 | case 'P': | ||
673 | case 'R': | ||
674 | continue; | ||
675 | case 'S': | ||
676 | frame->call_frame = 0; | ||
677 | continue; | ||
678 | default: | ||
669 | break; | 679 | break; |
680 | } | ||
681 | break; | ||
682 | } | ||
670 | } | 683 | } |
671 | if (ptr >= end || *ptr) | 684 | if (ptr >= end || *ptr) |
672 | cie = NULL; | 685 | cie = NULL; |
@@ -755,7 +768,7 @@ int unwind(struct unwind_frame_info *frame) | |||
755 | state.org = startLoc; | 768 | state.org = startLoc; |
756 | memcpy(&state.cfa, &badCFA, sizeof(state.cfa)); | 769 | memcpy(&state.cfa, &badCFA, sizeof(state.cfa)); |
757 | /* process instructions */ | 770 | /* process instructions */ |
758 | if (!processCFI(ptr, end, UNW_PC(frame), ptrType, &state) | 771 | if (!processCFI(ptr, end, pc, ptrType, &state) |
759 | || state.loc > endLoc | 772 | || state.loc > endLoc |
760 | || state.regs[retAddrReg].where == Nowhere | 773 | || state.regs[retAddrReg].where == Nowhere |
761 | || state.cfa.reg >= ARRAY_SIZE(reg_info) | 774 | || state.cfa.reg >= ARRAY_SIZE(reg_info) |
@@ -763,6 +776,11 @@ int unwind(struct unwind_frame_info *frame) | |||
763 | || state.cfa.offs % sizeof(unsigned long)) | 776 | || state.cfa.offs % sizeof(unsigned long)) |
764 | return -EIO; | 777 | return -EIO; |
765 | /* update frame */ | 778 | /* update frame */ |
779 | #ifndef CONFIG_AS_CFI_SIGNAL_FRAME | ||
780 | if(frame->call_frame | ||
781 | && !UNW_DEFAULT_RA(state.regs[retAddrReg], state.dataAlign)) | ||
782 | frame->call_frame = 0; | ||
783 | #endif | ||
766 | cfa = FRAME_REG(state.cfa.reg, unsigned long) + state.cfa.offs; | 784 | cfa = FRAME_REG(state.cfa.reg, unsigned long) + state.cfa.offs; |
767 | startLoc = min((unsigned long)UNW_SP(frame), cfa); | 785 | startLoc = min((unsigned long)UNW_SP(frame), cfa); |
768 | endLoc = max((unsigned long)UNW_SP(frame), cfa); | 786 | endLoc = max((unsigned long)UNW_SP(frame), cfa); |
@@ -866,6 +884,7 @@ int unwind_init_frame_info(struct unwind_frame_info *info, | |||
866 | /*const*/ struct pt_regs *regs) | 884 | /*const*/ struct pt_regs *regs) |
867 | { | 885 | { |
868 | info->task = tsk; | 886 | info->task = tsk; |
887 | info->call_frame = 0; | ||
869 | arch_unw_init_frame_info(info, regs); | 888 | arch_unw_init_frame_info(info, regs); |
870 | 889 | ||
871 | return 0; | 890 | return 0; |
@@ -879,6 +898,7 @@ int unwind_init_blocked(struct unwind_frame_info *info, | |||
879 | struct task_struct *tsk) | 898 | struct task_struct *tsk) |
880 | { | 899 | { |
881 | info->task = tsk; | 900 | info->task = tsk; |
901 | info->call_frame = 0; | ||
882 | arch_unw_init_blocked(info); | 902 | arch_unw_init_blocked(info); |
883 | 903 | ||
884 | return 0; | 904 | return 0; |
@@ -894,6 +914,7 @@ int unwind_init_running(struct unwind_frame_info *info, | |||
894 | void *arg) | 914 | void *arg) |
895 | { | 915 | { |
896 | info->task = current; | 916 | info->task = current; |
917 | info->call_frame = 0; | ||
897 | 918 | ||
898 | return arch_unwind_init_running(info, callback, arg); | 919 | return arch_unwind_init_running(info, callback, arg); |
899 | } | 920 | } |