futex: Fix issues found with trinity and static analysis
cover futex: Fix issues found with trinity and static analysis
Dave Jones and Dan Carpenter reported issues uncovered via trinity and static analysis respectively.
The following changes since commit 85efc72a0218335324d358ac479a04c16316fd4d:
Merge branch 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/sage/ceph-client (2012-07-19 16:11:28 -0700)
are available in the git repository at:
git://git.infradead.org/users/dvhart/linux-2.6.git futex
Darren Hart (3):
futex: Test for pi_mutex on fault in futex_wait_requeue_pi
futex: Fix bug in WARN_ON for NULL q.pi_state
futex: Forbid uaddr == uaddr2 in futex_wait_requeue_pi()
kernel/futex.c | 17 ++++++++++------- 1 file changed, 10 insertions(+), 7 deletions(-)
Signature · 1 line
1.7.10.4
PATCH 1/3 futex: Test for pi_mutex on fault in futex_wait_requeue_pi
If fixup_pi_state_owner() faults, pi_mutex may be NULL. Test for pi_mutex != NULL before testing the owner against current and possibly unlocking it.
--- kernel/futex.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
kernel/futex.c +1 -1
@@ -2370,7 +2370,7 @@ static int futex_wait_requeue_pi(u32 __user *uaddr, unsigned int flags,* fault, unlock the rt_mutex and return the fault to userspace. */ if (ret == -EFAULT ) { -if (rt_mutex_owner (pi_mutex) == current) +if (pi_mutex &&rt_mutex_owner (pi_mutex) == current)rt_mutex_unlock (pi_mutex); }else if (ret == -EINTR ) {/*
Signature · 1 line
1.7.10.4
[tip:core/urgent] futex: Test for pi_mutex on fault in futex_wait_requeue_pi()
Commit-ID: b6070a8d9853eda010a549fa9a09eb8d7269b929 Gitweb: http://git.kernel.org/tip/b6070a8d9853eda010a549fa9a09eb8d7269b929 Author: Darren Hart <[email protected]> AuthorDate: Fri, 20 Jul 2012 11:53:29 -0700 Committer: Thomas Gleixner <[email protected]> CommitDate: Tue, 24 Jul 2012 16:02:56 +0200
futex: Test for pi_mutex on fault in futex_wait_requeue_pi()
If fixup_pi_state_owner() faults, pi_mutex may be NULL. Test for pi_mutex != NULL before testing the owner against current and possibly unlocking it.
--- kernel/futex.c | 2 +- 1 files changed, 1 insertions(+), 1 deletions(-)
kernel/futex.c +1 -1
@@ -2370,7 +2370,7 @@ static int futex_wait_requeue_pi(u32 __user *uaddr, unsigned int flags,* fault, unlock the rt_mutex and return the fault to userspace. */ if (ret == -EFAULT ) { -if (rt_mutex_owner (pi_mutex) == current) +if (pi_mutex &&rt_mutex_owner (pi_mutex) == current)rt_mutex_unlock (pi_mutex); }else if (ret == -EINTR ) {/*
PATCH 2/3 futex: Fix bug in WARN_ON for NULL q.pi_state
In reply to Darren HartThe WARN_ON in futex_wait_requeue_pi() for a NULL q.pi_state was testing the address (&q.pi_state) of the pointer instead of the value (q.pi_state) of the pointer. Correct it accordingly.
--- kernel/futex.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
kernel/futex.c +1 -1
@@ -2343,7 +2343,7 @@ static int futex_wait_requeue_pi(u32 __user *uaddr, unsigned int flags,* signal. futex_unlock_pi() will not destroy the lock_ptr nor * the pi_state. */ -WARN_ON (!&q.pi_state); +WARN_ON (!q.pi_state); pi_mutex = &q.pi_state->pi_mutex; ret =rt_mutex_finish_proxy_lock (pi_mutex, to, &rt_waiter,1 );debug_rt_mutex_free_waiter (&rt_waiter);
Signature · 1 line
1.7.10.4
[tip:core/urgent] futex: Fix bug in WARN_ON for NULL q.pi_state
Commit-ID: f27071cb7fe3e1d37a9dbe6c0dfc5395cd40fa43 Gitweb: http://git.kernel.org/tip/f27071cb7fe3e1d37a9dbe6c0dfc5395cd40fa43 Author: Darren Hart <[email protected]> AuthorDate: Fri, 20 Jul 2012 11:53:30 -0700 Committer: Thomas Gleixner <[email protected]> CommitDate: Tue, 24 Jul 2012 16:02:57 +0200
futex: Fix bug in WARN_ON for NULL q.pi_state
The WARN_ON in futex_wait_requeue_pi() for a NULL q.pi_state was testing the address (&q.pi_state) of the pointer instead of the value (q.pi_state) of the pointer. Correct it accordingly.
--- kernel/futex.c | 2 +- 1 files changed, 1 insertions(+), 1 deletions(-)
kernel/futex.c +1 -1
@@ -2343,7 +2343,7 @@ static int futex_wait_requeue_pi(u32 __user *uaddr, unsigned int flags,* signal. futex_unlock_pi() will not destroy the lock_ptr nor * the pi_state. */ -WARN_ON (!&q.pi_state); +WARN_ON (!q.pi_state); pi_mutex = &q.pi_state->pi_mutex; ret =rt_mutex_finish_proxy_lock (pi_mutex, to, &rt_waiter,1 );debug_rt_mutex_free_waiter (&rt_waiter);
PATCH 3/3 futex: Forbid uaddr == uaddr2 in futex_wait_requeue_pi()
In reply to Darren HartIf uaddr == uaddr2, then we have broken the rule of only requeueing from a non-pi futex to a pi futex with this call. If we attempt this, as the trinity test suite manages to do, we miss early wakeups as q.key is equal to key2 (because they are the same uaddr). We will then attempt to dereference the pi_mutex (which would exist had the futex_q been properly requeued to a pi futex) and trigger a NULL pointer dereference.
--- kernel/futex.c | 13 ++++++++----- 1 file changed, 8 insertions(+), 5 deletions(-)
kernel/futex.c +8 -5
@@ -2231,11 +2231,11 @@ int handle_early_requeue_pi_wakeup(struct futex_hash_bucket *hb,* @uaddr2: the pi futex we will take prior to returning to user-space * * The caller will wait on uaddr and will be requeued by futex_requeue() to -* uaddr2 which must be PI aware. Normal wakeup will wake on uaddr2 and -* complete the acquisition of the rt_mutex prior to returning to userspace. -* This ensures the rt_mutex maintains an owner when it has waiters; without -* one, the pi logic wouldn't know which task to boost/deboost, if there was a -* need to. +* uaddr2 which must be PI aware and unique from uaddr. Normal wakeup will wake +* on uaddr2 and complete the acquisition of the rt_mutex prior to returning to +* userspace. This ensures the rt_mutex maintains an owner when it has waiters; +* without one, the pi logic would not know which task to boost/deboost, if +* there was a need to. * * We call schedule in futex_wait_queue_me() when we enqueue and return there * via the following:
@@ -2272,6 +2272,9 @@ static int futex_wait_requeue_pi(u32 __user *uaddr, unsigned int flags,struct futex_q q = futex_q_init;int res, ret; +if (uaddr == uaddr2) +return -EINVAL ; +if (!bitset)return -EINVAL ;
Signature · 1 line
1.7.10.4
[tip:core/urgent] futex: Forbid uaddr == uaddr2 in futex_wait_requeue_pi()
Commit-ID: 6f7b0a2a5c0fb03be7c25bd1745baa50582348ef Gitweb: http://git.kernel.org/tip/6f7b0a2a5c0fb03be7c25bd1745baa50582348ef Author: Darren Hart <[email protected]> AuthorDate: Fri, 20 Jul 2012 11:53:31 -0700 Committer: Thomas Gleixner <[email protected]> CommitDate: Tue, 24 Jul 2012 16:02:57 +0200
futex: Forbid uaddr == uaddr2 in futex_wait_requeue_pi()
If uaddr == uaddr2, then we have broken the rule of only requeueing from a non-pi futex to a pi futex with this call. If we attempt this, as the trinity test suite manages to do, we miss early wakeups as q.key is equal to key2 (because they are the same uaddr). We will then attempt to dereference the pi_mutex (which would exist had the futex_q been properly requeued to a pi futex) and trigger a NULL pointer dereference.
--- kernel/futex.c | 13 ++++++++----- 1 files changed, 8 insertions(+), 5 deletions(-)
kernel/futex.c +8 -5
@@ -2231,11 +2231,11 @@ int handle_early_requeue_pi_wakeup(struct futex_hash_bucket *hb,* @uaddr2: the pi futex we will take prior to returning to user-space * * The caller will wait on uaddr and will be requeued by futex_requeue() to -* uaddr2 which must be PI aware. Normal wakeup will wake on uaddr2 and -* complete the acquisition of the rt_mutex prior to returning to userspace. -* This ensures the rt_mutex maintains an owner when it has waiters; without -* one, the pi logic wouldn't know which task to boost/deboost, if there was a -* need to. +* uaddr2 which must be PI aware and unique from uaddr. Normal wakeup will wake +* on uaddr2 and complete the acquisition of the rt_mutex prior to returning to +* userspace. This ensures the rt_mutex maintains an owner when it has waiters; +* without one, the pi logic would not know which task to boost/deboost, if +* there was a need to. * * We call schedule in futex_wait_queue_me() when we enqueue and return there * via the following:
@@ -2272,6 +2272,9 @@ static int futex_wait_requeue_pi(u32 __user *uaddr, unsigned int flags,struct futex_q q = futex_q_init;int res, ret; +if (uaddr == uaddr2) +return -EINVAL ; +if (!bitset)return -EINVAL ;