diff options
author | David Woodhouse <dwmw2@infradead.org> | 2006-05-15 20:19:52 -0400 |
---|---|---|
committer | David Woodhouse <dwmw2@infradead.org> | 2006-05-15 20:19:52 -0400 |
commit | 18594822fcb01d4b35e05b9018f770a0b4156d1a (patch) | |
tree | 38d35c38086a564beaac215f8e52694cdbfab1c3 /kernel | |
parent | 5b5ffbc1e6d62d89747f3f59c09b2e488a7d7fce (diff) | |
parent | c4694c76ce28dd7e415b4f3014d8c6e580b5f3d2 (diff) |
Merge git://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux-2.6
Signed-off-by: David Woodhouse <dwmw2@infradead.org>
Diffstat (limited to 'kernel')
-rw-r--r-- | kernel/extable.c | 2 | ||||
-rw-r--r-- | kernel/module.c | 12 | ||||
-rw-r--r-- | kernel/ptrace.c | 57 | ||||
-rw-r--r-- | kernel/rcupdate.c | 19 |
4 files changed, 65 insertions, 25 deletions
diff --git a/kernel/extable.c b/kernel/extable.c index 7501b531ceed..7fe262855317 100644 --- a/kernel/extable.c +++ b/kernel/extable.c | |||
@@ -40,7 +40,7 @@ const struct exception_table_entry *search_exception_tables(unsigned long addr) | |||
40 | return e; | 40 | return e; |
41 | } | 41 | } |
42 | 42 | ||
43 | static int core_kernel_text(unsigned long addr) | 43 | int core_kernel_text(unsigned long addr) |
44 | { | 44 | { |
45 | if (addr >= (unsigned long)_stext && | 45 | if (addr >= (unsigned long)_stext && |
46 | addr <= (unsigned long)_etext) | 46 | addr <= (unsigned long)_etext) |
diff --git a/kernel/module.c b/kernel/module.c index d24deb0dbbc9..bbe04862e1b0 100644 --- a/kernel/module.c +++ b/kernel/module.c | |||
@@ -705,14 +705,14 @@ EXPORT_SYMBOL(__symbol_put); | |||
705 | 705 | ||
706 | void symbol_put_addr(void *addr) | 706 | void symbol_put_addr(void *addr) |
707 | { | 707 | { |
708 | unsigned long flags; | 708 | struct module *modaddr; |
709 | 709 | ||
710 | spin_lock_irqsave(&modlist_lock, flags); | 710 | if (core_kernel_text((unsigned long)addr)) |
711 | if (!kernel_text_address((unsigned long)addr)) | 711 | return; |
712 | BUG(); | ||
713 | 712 | ||
714 | module_put(module_text_address((unsigned long)addr)); | 713 | if (!(modaddr = module_text_address((unsigned long)addr))) |
715 | spin_unlock_irqrestore(&modlist_lock, flags); | 714 | BUG(); |
715 | module_put(modaddr); | ||
716 | } | 716 | } |
717 | EXPORT_SYMBOL_GPL(symbol_put_addr); | 717 | EXPORT_SYMBOL_GPL(symbol_put_addr); |
718 | 718 | ||
diff --git a/kernel/ptrace.c b/kernel/ptrace.c index 4e0f0ec003f7..921c22ad16e4 100644 --- a/kernel/ptrace.c +++ b/kernel/ptrace.c | |||
@@ -148,12 +148,34 @@ int ptrace_may_attach(struct task_struct *task) | |||
148 | int ptrace_attach(struct task_struct *task) | 148 | int ptrace_attach(struct task_struct *task) |
149 | { | 149 | { |
150 | int retval; | 150 | int retval; |
151 | task_lock(task); | 151 | |
152 | retval = -EPERM; | 152 | retval = -EPERM; |
153 | if (task->pid <= 1) | 153 | if (task->pid <= 1) |
154 | goto bad; | 154 | goto out; |
155 | if (task->tgid == current->tgid) | 155 | if (task->tgid == current->tgid) |
156 | goto bad; | 156 | goto out; |
157 | |||
158 | repeat: | ||
159 | /* | ||
160 | * Nasty, nasty. | ||
161 | * | ||
162 | * We want to hold both the task-lock and the | ||
163 | * tasklist_lock for writing at the same time. | ||
164 | * But that's against the rules (tasklist_lock | ||
165 | * is taken for reading by interrupts on other | ||
166 | * cpu's that may have task_lock). | ||
167 | */ | ||
168 | task_lock(task); | ||
169 | local_irq_disable(); | ||
170 | if (!write_trylock(&tasklist_lock)) { | ||
171 | local_irq_enable(); | ||
172 | task_unlock(task); | ||
173 | do { | ||
174 | cpu_relax(); | ||
175 | } while (!write_can_lock(&tasklist_lock)); | ||
176 | goto repeat; | ||
177 | } | ||
178 | |||
157 | /* the same process cannot be attached many times */ | 179 | /* the same process cannot be attached many times */ |
158 | if (task->ptrace & PT_PTRACED) | 180 | if (task->ptrace & PT_PTRACED) |
159 | goto bad; | 181 | goto bad; |
@@ -166,17 +188,15 @@ int ptrace_attach(struct task_struct *task) | |||
166 | ? PT_ATTACHED : 0); | 188 | ? PT_ATTACHED : 0); |
167 | if (capable(CAP_SYS_PTRACE)) | 189 | if (capable(CAP_SYS_PTRACE)) |
168 | task->ptrace |= PT_PTRACE_CAP; | 190 | task->ptrace |= PT_PTRACE_CAP; |
169 | task_unlock(task); | ||
170 | 191 | ||
171 | write_lock_irq(&tasklist_lock); | ||
172 | __ptrace_link(task, current); | 192 | __ptrace_link(task, current); |
173 | write_unlock_irq(&tasklist_lock); | ||
174 | 193 | ||
175 | force_sig_specific(SIGSTOP, task); | 194 | force_sig_specific(SIGSTOP, task); |
176 | return 0; | ||
177 | 195 | ||
178 | bad: | 196 | bad: |
197 | write_unlock_irq(&tasklist_lock); | ||
179 | task_unlock(task); | 198 | task_unlock(task); |
199 | out: | ||
180 | return retval; | 200 | return retval; |
181 | } | 201 | } |
182 | 202 | ||
@@ -417,21 +437,22 @@ int ptrace_request(struct task_struct *child, long request, | |||
417 | */ | 437 | */ |
418 | int ptrace_traceme(void) | 438 | int ptrace_traceme(void) |
419 | { | 439 | { |
420 | int ret; | 440 | int ret = -EPERM; |
421 | 441 | ||
422 | /* | 442 | /* |
423 | * Are we already being traced? | 443 | * Are we already being traced? |
424 | */ | 444 | */ |
425 | if (current->ptrace & PT_PTRACED) | 445 | task_lock(current); |
426 | return -EPERM; | 446 | if (!(current->ptrace & PT_PTRACED)) { |
427 | ret = security_ptrace(current->parent, current); | 447 | ret = security_ptrace(current->parent, current); |
428 | if (ret) | 448 | /* |
429 | return -EPERM; | 449 | * Set the ptrace bit in the process ptrace flags. |
430 | /* | 450 | */ |
431 | * Set the ptrace bit in the process ptrace flags. | 451 | if (!ret) |
432 | */ | 452 | current->ptrace |= PT_PTRACED; |
433 | current->ptrace |= PT_PTRACED; | 453 | } |
434 | return 0; | 454 | task_unlock(current); |
455 | return ret; | ||
435 | } | 456 | } |
436 | 457 | ||
437 | /** | 458 | /** |
diff --git a/kernel/rcupdate.c b/kernel/rcupdate.c index 6d32ff26f948..2058f88c7bbb 100644 --- a/kernel/rcupdate.c +++ b/kernel/rcupdate.c | |||
@@ -479,12 +479,31 @@ static int __rcu_pending(struct rcu_ctrlblk *rcp, struct rcu_data *rdp) | |||
479 | return 0; | 479 | return 0; |
480 | } | 480 | } |
481 | 481 | ||
482 | /* | ||
483 | * Check to see if there is any immediate RCU-related work to be done | ||
484 | * by the current CPU, returning 1 if so. This function is part of the | ||
485 | * RCU implementation; it is -not- an exported member of the RCU API. | ||
486 | */ | ||
482 | int rcu_pending(int cpu) | 487 | int rcu_pending(int cpu) |
483 | { | 488 | { |
484 | return __rcu_pending(&rcu_ctrlblk, &per_cpu(rcu_data, cpu)) || | 489 | return __rcu_pending(&rcu_ctrlblk, &per_cpu(rcu_data, cpu)) || |
485 | __rcu_pending(&rcu_bh_ctrlblk, &per_cpu(rcu_bh_data, cpu)); | 490 | __rcu_pending(&rcu_bh_ctrlblk, &per_cpu(rcu_bh_data, cpu)); |
486 | } | 491 | } |
487 | 492 | ||
493 | /* | ||
494 | * Check to see if any future RCU-related work will need to be done | ||
495 | * by the current CPU, even if none need be done immediately, returning | ||
496 | * 1 if so. This function is part of the RCU implementation; it is -not- | ||
497 | * an exported member of the RCU API. | ||
498 | */ | ||
499 | int rcu_needs_cpu(int cpu) | ||
500 | { | ||
501 | struct rcu_data *rdp = &per_cpu(rcu_data, cpu); | ||
502 | struct rcu_data *rdp_bh = &per_cpu(rcu_bh_data, cpu); | ||
503 | |||
504 | return (!!rdp->curlist || !!rdp_bh->curlist || rcu_pending(cpu)); | ||
505 | } | ||
506 | |||
488 | void rcu_check_callbacks(int cpu, int user) | 507 | void rcu_check_callbacks(int cpu, int user) |
489 | { | 508 | { |
490 | if (user || | 509 | if (user || |