Commit 7e1fb765 authored by Linus Torvalds's avatar Linus Torvalds

Merge git://git.kernel.org/pub/scm/linux/kernel/git/mingo/linux-2.6-sched

* git://git.kernel.org/pub/scm/linux/kernel/git/mingo/linux-2.6-sched:
  futex: correctly return -EFAULT not -EINVAL
  lockdep: in_range() fix
  lockdep: fix debug_show_all_locks()
  sched: style cleanups
  futex: fix for futex_wait signal stack corruption
parents ad658cec cde898fa
......@@ -7,12 +7,25 @@
#ifndef _LINUX_THREAD_INFO_H
#define _LINUX_THREAD_INFO_H
#include <linux/types.h>
/*
* System call restart block.
* System call restart block.
*/
struct restart_block {
long (*fn)(struct restart_block *);
unsigned long arg0, arg1, arg2, arg3;
union {
struct {
unsigned long arg0, arg1, arg2, arg3;
};
/* For futex_wait */
struct {
u32 *uaddr;
u32 val;
u32 flags;
u64 time;
} futex;
};
};
extern long do_no_restart_syscall(struct restart_block *parm);
......
......@@ -658,7 +658,7 @@ static int wake_futex_pi(u32 __user *uaddr, u32 uval, struct futex_q *this)
if (curval == -EFAULT)
ret = -EFAULT;
if (curval != uval)
else if (curval != uval)
ret = -EINVAL;
if (ret) {
spin_unlock(&pi_state->pi_mutex.wait_lock);
......@@ -1149,9 +1149,9 @@ static int fixup_pi_state_owner(u32 __user *uaddr, struct futex_q *q,
/*
* In case we must use restart_block to restart a futex_wait,
* we encode in the 'arg3' shared capability
* we encode in the 'flags' shared capability
*/
#define ARG3_SHARED 1
#define FLAGS_SHARED 1
static long futex_wait_restart(struct restart_block *restart);
......@@ -1290,12 +1290,13 @@ static int futex_wait(u32 __user *uaddr, struct rw_semaphore *fshared,
struct restart_block *restart;
restart = &current_thread_info()->restart_block;
restart->fn = futex_wait_restart;
restart->arg0 = (unsigned long)uaddr;
restart->arg1 = (unsigned long)val;
restart->arg2 = (unsigned long)abs_time;
restart->arg3 = 0;
restart->futex.uaddr = (u32 *)uaddr;
restart->futex.val = val;
restart->futex.time = abs_time->tv64;
restart->futex.flags = 0;
if (fshared)
restart->arg3 |= ARG3_SHARED;
restart->futex.flags |= FLAGS_SHARED;
return -ERESTART_RESTARTBLOCK;
}
......@@ -1310,15 +1311,15 @@ static int futex_wait(u32 __user *uaddr, struct rw_semaphore *fshared,
static long futex_wait_restart(struct restart_block *restart)
{
u32 __user *uaddr = (u32 __user *)restart->arg0;
u32 val = (u32)restart->arg1;
ktime_t *abs_time = (ktime_t *)restart->arg2;
u32 __user *uaddr = (u32 __user *)restart->futex.uaddr;
struct rw_semaphore *fshared = NULL;
ktime_t t;
t.tv64 = restart->futex.time;
restart->fn = do_no_restart_syscall;
if (restart->arg3 & ARG3_SHARED)
if (restart->futex.flags & FLAGS_SHARED)
fshared = &current->mm->mmap_sem;
return (long)futex_wait(uaddr, fshared, val, abs_time);
return (long)futex_wait(uaddr, fshared, restart->futex.val, &t);
}
......
......@@ -3054,11 +3054,6 @@ void __init lockdep_info(void)
#endif
}
static inline int in_range(const void *start, const void *addr, const void *end)
{
return addr >= start && addr <= end;
}
static void
print_freed_lock_bug(struct task_struct *curr, const void *mem_from,
const void *mem_to, struct held_lock *hlock)
......@@ -3080,6 +3075,13 @@ print_freed_lock_bug(struct task_struct *curr, const void *mem_from,
dump_stack();
}
static inline int not_in_range(const void* mem_from, unsigned long mem_len,
const void* lock_from, unsigned long lock_len)
{
return lock_from + lock_len <= mem_from ||
mem_from + mem_len <= lock_from;
}
/*
* Called when kernel memory is freed (or unmapped), or if a lock
* is destroyed or reinitialized - this code checks whether there is
......@@ -3087,7 +3089,6 @@ print_freed_lock_bug(struct task_struct *curr, const void *mem_from,
*/
void debug_check_no_locks_freed(const void *mem_from, unsigned long mem_len)
{
const void *mem_to = mem_from + mem_len, *lock_from, *lock_to;
struct task_struct *curr = current;
struct held_lock *hlock;
unsigned long flags;
......@@ -3100,14 +3101,11 @@ void debug_check_no_locks_freed(const void *mem_from, unsigned long mem_len)
for (i = 0; i < curr->lockdep_depth; i++) {
hlock = curr->held_locks + i;
lock_from = (void *)hlock->instance;
lock_to = (void *)(hlock->instance + 1);
if (!in_range(mem_from, lock_from, mem_to) &&
!in_range(mem_from, lock_to, mem_to))
if (not_in_range(mem_from, mem_len, hlock->instance,
sizeof(*hlock->instance)))
continue;
print_freed_lock_bug(curr, mem_from, mem_to, hlock);
print_freed_lock_bug(curr, mem_from, mem_from + mem_len, hlock);
break;
}
local_irq_restore(flags);
......@@ -3173,6 +3171,13 @@ void debug_show_all_locks(void)
printk(" locked it.\n");
do_each_thread(g, p) {
/*
* It's not reliable to print a task's held locks
* if it's not sleeping (or if it's not the current
* task):
*/
if (p->state == TASK_RUNNING && p != current)
continue;
if (p->lockdep_depth)
lockdep_print_held_locks(p);
if (!unlock)
......
This diff is collapsed.
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment