+ use-the-correct-restart-option-for-futex_lock_pi.patch added to -mm tree

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



The patch titled

     Use the correct restart option for futex_lock_pi

has been added to the -mm tree.  Its filename is

     use-the-correct-restart-option-for-futex_lock_pi.patch

See http://www.zip.com.au/~akpm/linux/patches/stuff/added-to-mm.txt to find
out what to do about this

------------------------------------------------------
Subject: Use the correct restart option for futex_lock_pi
From: Thomas Gleixner <tglx@xxxxxxxxxxxxx>

The current implementation of futex_lock_pi returns -ERESTART_RESTARTBLOCK
in case that the lock operation has been interrupted by a signal.  This
results in a return of -EINTR to userspace in case there is an handler for
the signal.  This is wrong, because userspace expects that the lock
function does not return in any case of signal delivery.

This was not caught by my insufficient test case, but triggered a nasty
userspace problem in an high load application scenario.  Unfortunately also
glibc does not check for this invalid return value.

Using -ERSTARTNOINTR makes sure, that the interrupted syscall is restarted.
 The restart block related code can be safely removed, as the possible
timeout argument is an absolute time value.

Signed-off-by: Thomas Gleixner <tglx@xxxxxxxxxxxxx>
Acked-by: Ingo Molnar <mingo@xxxxxxx>
Signed-off-by: Andrew Morton <akpm@xxxxxxxx>
---

 kernel/futex.c |   84 ++++++-----------------------------------------
 1 file changed, 11 insertions(+), 73 deletions(-)

diff -puN kernel/futex.c~use-the-correct-restart-option-for-futex_lock_pi kernel/futex.c
--- a/kernel/futex.c~use-the-correct-restart-option-for-futex_lock_pi
+++ a/kernel/futex.c
@@ -1120,9 +1120,10 @@ static int futex_wait(u32 __user *uaddr,
  * if there are waiters then it will block, it does PI, etc. (Due to
  * races the kernel might see a 0 value of the futex too.)
  */
-static int do_futex_lock_pi(u32 __user *uaddr, int detect, int trylock,
-			    struct hrtimer_sleeper *to)
+static int futex_lock_pi(u32 __user *uaddr, int detect, unsigned long sec,
+			 long nsec, int trylock)
 {
+	struct hrtimer_sleeper timeout, *to = NULL;
 	struct task_struct *curr = current;
 	struct futex_hash_bucket *hb;
 	u32 uval, newval, curval;
@@ -1132,6 +1133,13 @@ static int do_futex_lock_pi(u32 __user *
 	if (refill_pi_state_cache())
 		return -ENOMEM;
 
+	if (sec != MAX_SCHEDULE_TIMEOUT) {
+		to = &timeout;
+		hrtimer_init(&to->timer, CLOCK_REALTIME, HRTIMER_ABS);
+		hrtimer_init_sleeper(to, current);
+		to->timer.expires = ktime_set(sec, nsec);
+	}
+
 	q.pi_state = NULL;
  retry:
 	down_read(&curr->mm->mmap_sem);
@@ -1307,7 +1315,7 @@ static int do_futex_lock_pi(u32 __user *
 	if (!detect && ret == -EDEADLK && 0)
 		force_sig(SIGKILL, current);
 
-	return ret;
+	return ret != -EINTR ? ret : -ERESTARTNOINTR;
 
  out_unlock_release_sem:
 	queue_unlock(&q, hb);
@@ -1342,76 +1350,6 @@ static int do_futex_lock_pi(u32 __user *
 }
 
 /*
- * Restart handler
- */
-static long futex_lock_pi_restart(struct restart_block *restart)
-{
-	struct hrtimer_sleeper timeout, *to = NULL;
-	int ret;
-
-	restart->fn = do_no_restart_syscall;
-
-	if (restart->arg2 || restart->arg3) {
-		to = &timeout;
-		hrtimer_init(&to->timer, CLOCK_REALTIME, HRTIMER_ABS);
-		hrtimer_init_sleeper(to, current);
-		to->timer.expires.tv64 = ((u64)restart->arg1 << 32) |
-			(u64) restart->arg0;
-	}
-
-	pr_debug("lock_pi restart: %p, %d (%d)\n",
-		 (u32 __user *)restart->arg0, current->pid);
-
-	ret = do_futex_lock_pi((u32 __user *)restart->arg0, restart->arg1,
-			       0, to);
-
-	if (ret != -EINTR)
-		return ret;
-
-	restart->fn = futex_lock_pi_restart;
-
-	/* The other values are filled in */
-	return -ERESTART_RESTARTBLOCK;
-}
-
-/*
- * Called from the syscall entry below.
- */
-static int futex_lock_pi(u32 __user *uaddr, int detect, unsigned long sec,
-			 long nsec, int trylock)
-{
-	struct hrtimer_sleeper timeout, *to = NULL;
-	struct restart_block *restart;
-	int ret;
-
-	if (sec != MAX_SCHEDULE_TIMEOUT) {
-		to = &timeout;
-		hrtimer_init(&to->timer, CLOCK_REALTIME, HRTIMER_ABS);
-		hrtimer_init_sleeper(to, current);
-		to->timer.expires = ktime_set(sec, nsec);
-	}
-
-	ret = do_futex_lock_pi(uaddr, detect, trylock, to);
-
-	if (ret != -EINTR)
-		return ret;
-
-	pr_debug("lock_pi interrupted: %p, %d (%d)\n", uaddr, current->pid);
-
-	restart = &current_thread_info()->restart_block;
-	restart->fn = futex_lock_pi_restart;
-	restart->arg0 = (unsigned long) uaddr;
-	restart->arg1 = detect;
-	if (to) {
-		restart->arg2 = to->timer.expires.tv64 & 0xFFFFFFFF;
-		restart->arg3 = to->timer.expires.tv64 >> 32;
-	} else
-		restart->arg2 = restart->arg3 = 0;
-
-	return -ERESTART_RESTARTBLOCK;
-}
-
-/*
  * Userspace attempted a TID -> 0 atomic transition, and failed.
  * This is the in-kernel slowpath: we look up the PI state (if any),
  * and do the rt-mutex unlock.
_

Patches currently in -mm which might be from tglx@xxxxxxxxxxxxx are

prevent-timespec-timeval-to-ktime_t-overflow.patch
use-the-correct-restart-option-for-futex_lock_pi.patch
git-mtd.patch
mtd-maps-ixp4xx-partition-parsing.patch
slab-fix-lockdep-warnings.patch
slab-fix-lockdep-warnings-fix.patch
slab-fix-lockdep-warnings-fix-2.patch
rtmutex-clean-up-and-remove-some-extra-spinlocks.patch
rtmutex-clean-up-and-remove-some-extra-spinlocks-more.patch
posix-timers-fix-clock_nanosleep-doesnt-return-the-remaining-time-in-compatibility-mode-2.patch
posix-timers-fix-the-flags-handling-in-posix_cpu_nsleep-2.patch
simplify-update_times-avoid-jiffies-jiffies_64-aliasing-problem-2.patch
do_sched_setscheduler-dont-take-tasklist_lock.patch
introduce-is_rt_policy-helper.patch
sched_setscheduler-fix-policy-checks.patch
reparent_to_init-use-has_rt_policy.patch
futex_find_get_task-dont-take-tasklist_lock.patch
sys_get_robust_list-dont-take-tasklist_lock.patch
genirq-convert-the-x86_64-architecture-to-irq-chips.patch
genirq-convert-the-i386-architecture-to-irq-chips.patch
genirq-irq-convert-the-move_irq-flag-from-a-32bit-word-to-a-single-bit.patch
genirq-irq-add-moved_masked_irq.patch
genirq-x86_64-irq-reenable-migrating-irqs-to-other-cpus.patch
genirq-msi-simplify-msi-enable-and-disable.patch
genirq-msi-make-the-msi-boolean-tests-return-either-0-or-1.patch
genirq-msi-implement-helper-functions-read_msi_msg-and-write_msi_msg.patch
genirq-msi-refactor-the-msi_ops.patch
genirq-msi-simplify-the-msi-irq-limit-policy.patch
genirq-irq-add-a-dynamic-irq-creation-api.patch
genirq-ia64-irq-dynamic-irq-support.patch
genirq-i386-irq-dynamic-irq-support.patch
genirq-x86_64-irq-dynamic-irq-support.patch
genirq-msi-make-the-msi-code-irq-based-and-not-vector-based.patch
genirq-x86_64-irq-move-msi-message-composition-into-io_apicc.patch
genirq-i386-irq-move-msi-message-composition-into-io_apicc.patch
genirq-msi-only-build-msi-apicc-on-ia64.patch
genirq-x86_64-irq-remove-the-msi-assumption-that-irq-==-vector.patch
genirq-i386-irq-remove-the-msi-assumption-that-irq-==-vector.patch
genirq-irq-remove-msi-hacks.patch
genirq-irq-generalize-the-check-for-hardirq_bits.patch
genirq-x86_64-irq-make-the-external-irq-handlers-report-their-vector-not-the-irq-number.patch
genirq-x86_64-irq-make-vector_irq-per-cpu.patch
genirq-x86_64-irq-make-vector_irq-per-cpu-warning-fix.patch
genirq-x86_64-irq-kill-gsi_irq_sharing.patch
genirq-x86_64-irq-kill-irq-compression.patch

-
To unsubscribe from this list: send the line "unsubscribe mm-commits" in
the body of a message to majordomo@xxxxxxxxxxxxxxx
More majordomo info at  http://vger.kernel.org/majordomo-info.html

[Index of Archives]     [Kernel Newbies FAQ]     [Kernel Archive]     [IETF Annouce]     [DCCP]     [Netdev]     [Networking]     [Security]     [Bugtraq]     [Photo]     [Yosemite]     [MIPS Linux]     [ARM Linux]     [Linux Security]     [Linux RAID]     [Linux SCSI]

  Powered by Linux