Mon Mar 16 01:20:37 2009 UTC ()
Pull up following revision(s) (requested by adrianp in ticket #582):
	sys/compat/linux/common/linux_futex.c: revision 1.24 via patch
fix robust_list pointer mess!


(snj)
diff -r1.18.4.1 -r1.18.4.2 src/sys/compat/linux/common/linux_futex.c

cvs diff -r1.18.4.1 -r1.18.4.2 src/sys/compat/linux/common/Attic/linux_futex.c (expand / switch to context diff)
--- src/sys/compat/linux/common/Attic/linux_futex.c 2009/02/26 20:40:52 1.18.4.1
+++ src/sys/compat/linux/common/Attic/linux_futex.c 2009/03/16 01:20:37 1.18.4.2
@@ -1,4 +1,4 @@
-/*	$NetBSD: linux_futex.c,v 1.18.4.1 2009/02/26 20:40:52 snj Exp $ */
+/*	$NetBSD: linux_futex.c,v 1.18.4.2 2009/03/16 01:20:37 snj Exp $ */
 
 /*-
  * Copyright (c) 2005 Emmanuel Dreyfus, all rights reserved.
@@ -32,7 +32,7 @@
  */
 
 #include <sys/cdefs.h>
-__KERNEL_RCSID(1, "$NetBSD: linux_futex.c,v 1.18.4.1 2009/02/26 20:40:52 snj Exp $");
+__KERNEL_RCSID(1, "$NetBSD: linux_futex.c,v 1.18.4.2 2009/03/16 01:20:37 snj Exp $");
 
 #include <sys/param.h>
 #include <sys/time.h>
@@ -498,6 +498,8 @@
 	struct proc *p = l->l_proc;
 	struct linux_emuldata *led = p->p_emuldata;
 
+	if (SCARG(uap, len) != sizeof(*(led->robust_futexes)))
+		return EINVAL;
 	led->robust_futexes = SCARG(uap, head);
 	*retval = 0;
 	return 0;
@@ -508,13 +510,13 @@
     const struct linux_sys_get_robust_list_args *uap, register_t *retval)
 {
 	struct linux_emuldata *led;
-	struct linux_robust_list_head *head;
-	size_t len = sizeof(struct linux_robust_list_head);
+	struct linux_robust_list_head **head;
+	size_t len = sizeof(*led->robust_futexes);
 	int error = 0;
 
 	if (!SCARG(uap, pid)) {
 		led = l->l_proc->p_emuldata;
-		head = led->robust_futexes;
+		head = &led->robust_futexes;
 	} else {
 		struct proc *p;
 
@@ -525,15 +527,14 @@
 			return ESRCH;
 		}
 		led = p->p_emuldata;
-		head = led->robust_futexes;
+		head = &led->robust_futexes;
 		mutex_exit(proc_lock);
 	}
 
-	error = copyout(&len, SCARG(uap, len), sizeof(size_t));
+	error = copyout(&len, SCARG(uap, len), sizeof(len));
 	if (error)
 		return error;
-	return copyout(head, SCARG(uap, head),
-	    sizeof(struct linux_robust_list_head));
+	return copyout(head, SCARG(uap, head), sizeof(*head));
 }
 
 static int
@@ -584,7 +585,7 @@
 void
 release_futexes(struct proc *p)
 {
-	struct linux_robust_list_head *head = NULL;
+	struct linux_robust_list_head head;
 	struct linux_robust_list *entry, *next_entry, *pending;
 	unsigned int limit = 2048, pi, next_pi, pip;
 	struct linux_emuldata *led;
@@ -592,21 +593,22 @@
 	int rc;
 
 	led = p->p_emuldata;
-	head = led->robust_futexes;
+	if (led->robust_futexes == NULL)
+		return;
 
-	if (head == NULL)
+	if (copyin(led->robust_futexes, &head, sizeof(head)))
 		return;
 
-	if (fetch_robust_entry(&entry, &head->list.next, &pi))
+	if (fetch_robust_entry(&entry, &head.list.next, &pi))
 		return;
 
-	if (copyin(&head->futex_offset, &futex_offset, sizeof(unsigned long)))
+	if (copyin(&head.futex_offset, &futex_offset, sizeof(unsigned long)))
 		return;
 
-	if (fetch_robust_entry(&pending, &head->pending_list, &pip))
+	if (fetch_robust_entry(&pending, &head.pending_list, &pip))
 		return;
 
-	while (entry != &head->list) {
+	while (entry != &head.list) {
 		rc = fetch_robust_entry(&next_entry, &entry->next, &next_pi);
 
 		if (entry != pending)