All of lore.kernel.org
 help / color / mirror / Atom feed
* [PATCH] futex: use fault_in to avoid infinite loop
@ 2017-12-06 14:21 Cheng Jian
  2017-12-06 16:04 ` Peter Zijlstra
  0 siblings, 1 reply; 8+ messages in thread
From: Cheng Jian @ 2017-12-06 14:21 UTC (permalink / raw)
  To: tglx, mingo, peterz, dvhart, linux-kernel
  Cc: xiexiuqi, huawei.libin, cj.chengjian

It will cause softlockup(infinite loop) in kernel
space when we use SYS_set_robust_list in futex which
incoming a misaligned address from user space.

It can be triggered by the following demo

	// futex_align.c

	#include <stdio.h>
	#include <linux/futex.h>
	#include <syscall.h>
	#include <unistd.h>
	#include <stdlib.h>

	int main()
	{
		char *p = malloc(128);

		struct robust_list_head *ro1;
		struct robust_list *entry;
		struct robust_list *pending;

		int ret = 0;

		pid_t pid = getpid();

		printf("size = %d, p %p  pid [%d] \n",
			sizeof(struct robust_list_head), p, pid);

		ro1 = p;
		entry = p + 20;
		pending = p + 40;

		ro1->list.next = entry;
		ro1->list_op_pending = pending;

		entry->next = &(ro1->list);

		ro1->futex_offset = 41;

		*((int *)((char *)entry + 41)) = pid;

		printf(" entry + offert [%p] [%d] \n",
			(int *)((char *)entry + 41),
			*((int *)((char *)entry + 41)));
			ret = syscall(SYS_set_robust_list, ro1,
				sizeof(struct robust_list_head));
		printf("ret = [%d]\n", ret);

		return 0;
	}

It is because LDXER instructions requires the address
which is aligned under arm64 architecture. otherwise
it can trigger an exception, cmpxchg_futex_value_locked
return -EFAULT.

	int handle_futex_death(u32 __user *uaddr, struct task_struct *curr, int pi)
	{
	retry:
		//......

		/* return -EFAULT */
        	if (cmpxchg_futex_value_locked (& nval, uaddr, uval, mval)) {
			/* always return 0 */
			if (fault_in_user_writeable(uaddr))
				return -1;	/* never here */
		goto retry; /* then goto retry */

		//......
	}

So

	retry - => goto retry -=> retry -=> goto retry ...

Then dead loop here.

So use fault_in to avoid it, It will not enter the retry label
twice under this branch.

Signed-off-by: Cheng Jian <cj.chengjian@huawei.com>
---
 kernel/futex.c | 9 +++++++--
 1 file changed, 7 insertions(+), 2 deletions(-)

diff --git a/kernel/futex.c b/kernel/futex.c
index 76ed592..bc0b14f 100644
--- a/kernel/futex.c
+++ b/kernel/futex.c
@@ -3327,6 +3327,7 @@ static int futex_wait_requeue_pi(u32 __user *uaddr, unsigned int flags,
 int handle_futex_death(u32 __user *uaddr, struct task_struct *curr, int pi)
 {
 	u32 uval, uninitialized_var(nval), mval;
+	int fault_in = false;
 
 retry:
 	if (get_user(uval, uaddr))
@@ -3351,11 +3352,15 @@ int handle_futex_death(u32 __user *uaddr, struct task_struct *curr, int pi)
 		 * access fails we try to fault in the futex with R/W
 		 * verification via get_user_pages. get_user() above
 		 * does not guarantee R/W access. If that fails we
-		 * give up and leave the futex locked.
+		 * give up and leave the futex locked. use fault_in
+		 * infinite loop when other exceptions
 		 */
 		if (cmpxchg_futex_value_locked(&nval, uaddr, uval, mval)) {
-			if (fault_in_user_writeable(uaddr))
+			if (unlikely(fault_in) ||
+				fault_in_user_writeable(uaddr)) {
 				return -1;
+			}
+			fault_in = true;
 			goto retry;
 		}
 		if (nval != uval)
-- 
1.8.3.1

^ permalink raw reply related	[flat|nested] 8+ messages in thread

end of thread, other threads:[~2017-12-30  7:41 UTC | newest]

Thread overview: 8+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2017-12-06 14:21 [PATCH] futex: use fault_in to avoid infinite loop Cheng Jian
2017-12-06 16:04 ` Peter Zijlstra
2017-12-06 21:40   ` Peter Zijlstra
2017-12-08  5:21     ` Darren Hart
2017-12-08 10:50       ` Peter Zijlstra
2017-12-08 12:42     ` chengjian (D)
2017-12-28 14:21     ` [tip:locking/urgent] futex: Sanitize user address in set_robust_list() tip-bot for Peter Zijlstra
2017-12-30  7:40     ` [PATCH] futex: use fault_in to avoid infinite loop Michael Kerrisk

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.