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

Re: vma_list_sem




On Tue, 12 Oct 1999, manfreds wrote:

> I've merged your patch and my patch, the result is below.
> It still contains the complete debugging code, and I've not
> yet performed any low-memory testing.
> 
> I found one more find_vma() caller which performs no locking:
> fs/super.c: copy_mount_options().
> 
> Unfortunately, I found no clean solution for this function, but
> I think my fix is acceptable. [there is an obscure race possible,
> a multi-threaded application could fail with -EFAULT although
> all parameters are valid].

a) you've missed several pieces in arch/* and drivers/*
b) correct code should not be punished. Ever. ASSERT is wrong.

Some of missing pieces (modulo binfmt-related stuff):

diff -urN linux-2.3.20/arch/mips/kernel/sysmips.c linux-bird.mm/arch/mips/kernel/sysmips.c
--- linux-2.3.20/arch/mips/kernel/sysmips.c	Sun Sep 12 05:54:08 1999
+++ linux-bird.mm/arch/mips/kernel/sysmips.c	Tue Oct 12 14:09:01 1999
@@ -23,29 +23,6 @@
 #include <asm/sysmips.h>
 #include <asm/uaccess.h>
 
-/*
- * How long a hostname can we get from user space?
- *  -EFAULT if invalid area or too long
- *  0 if ok
- *  >0 EFAULT after xx bytes
- */
-static inline int
-get_max_hostname(unsigned long address)
-{
-	struct vm_area_struct * vma;
-
-	vma = find_vma(current->mm, address);
-	if (!vma || vma->vm_start > address || !(vma->vm_flags & VM_READ))
-		return -EFAULT;
-	address = vma->vm_end - address;
-	if (address > PAGE_SIZE)
-		return 0;
-	if (vma->vm_next && vma->vm_next->vm_start == vma->vm_end &&
-	   (vma->vm_next->vm_flags & VM_READ))
-		return 0;
-	return address;
-}
-
 asmlinkage int
 sys_sysmips(int cmd, int arg1, int arg2, int arg3)
 {
diff -urN linux-2.3.20/arch/sparc64/kernel/sys_sparc32.c linux-bird.mm/arch/sparc64/kernel/sys_sparc32.c
--- linux-2.3.20/arch/sparc64/kernel/sys_sparc32.c	Sun Sep 12 13:27:24 1999
+++ linux-bird.mm/arch/sparc64/kernel/sys_sparc32.c	Tue Oct 12 14:31:18 1999
@@ -1331,26 +1331,34 @@
 	int i;
 	unsigned long page;
 	struct vm_area_struct *vma;
+	int err;
 
 	*kernel = 0;
 	if(!user)
 		return 0;
+	if(!(page = __get_free_page(GFP_KERNEL)))
+		return -ENOMEM;
+	down(&current->mm->mmap_sem);
 	vma = find_vma(current->mm, (unsigned long)user);
+	err = -EFAULT;
 	if(!vma || (unsigned long)user < vma->vm_start)
-		return -EFAULT;
+		goto out;
 	if(!(vma->vm_flags & VM_READ))
-		return -EFAULT;
+		goto out;
 	i = vma->vm_end - (unsigned long) user;
 	if(PAGE_SIZE <= (unsigned long) i)
 		i = PAGE_SIZE - 1;
-	if(!(page = __get_free_page(GFP_KERNEL)))
-		return -ENOMEM;
+	up(&current->mm->mmap_sem);
 	if(copy_from_user((void *) page, user, i)) {
 		free_page(page);
 		return -EFAULT;
 	}
 	*kernel = page;
 	return 0;
+out:
+	up(&current->mm->mmap_sem);
+	free_page(page);
+	return err;
 }
 
 extern asmlinkage int sys_mount(char * dev_name, char * dir_name, char * type,
diff -urN linux-2.3.20/drivers/char/drm/bufs.c linux-bird.mm/drivers/char/drm/bufs.c
--- linux-2.3.20/drivers/char/drm/bufs.c	Tue Sep 21 16:13:03 1999
+++ linux-bird.mm/drivers/char/drm/bufs.c	Tue Oct 12 14:10:51 1999
@@ -477,8 +477,10 @@
 			   -EFAULT);
 
 	if (request.count >= dma->buf_count) {
+		down(&current->mm->mmap_sem);
 		virtual = do_mmap(filp, 0, dma->byte_count,
 				  PROT_READ|PROT_WRITE, MAP_SHARED, 0);
+		up(&current->mm->mmap_sem);
 		if (virtual > -1024UL) {
 				/* Real error */
 			retcode = (signed long)virtual;
diff -urN linux-2.3.20/drivers/sgi/char/graphics.c linux-bird.mm/drivers/sgi/char/graphics.c
--- linux-2.3.20/drivers/sgi/char/graphics.c	Sun Sep 12 13:27:36 1999
+++ linux-bird.mm/drivers/sgi/char/graphics.c	Tue Oct 12 14:12:33 1999
@@ -150,9 +150,11 @@
 		 * sgi_graphics_mmap
 		 */
 		disable_gconsole ();
+		down(&current->mm->mmap_sem);
 		r = do_mmap (file, (unsigned long)vaddr,
 			     cards[board].g_regs_size, PROT_READ|PROT_WRITE,
 			     MAP_FIXED|MAP_PRIVATE, 0);
+		up(&current->mm->mmap_sem);
 		if (r)
 			return r;
 	}
diff -urN linux-2.3.20/drivers/sgi/char/shmiq.c linux-bird.mm/drivers/sgi/char/shmiq.c
--- linux-2.3.20/drivers/sgi/char/shmiq.c	Sun Sep 12 12:45:47 1999
+++ linux-bird.mm/drivers/sgi/char/shmiq.c	Tue Oct 12 14:07:48 1999
@@ -272,14 +272,17 @@
 		}
 
 		vaddr = (unsigned long) req.user_vaddr;
+		down(&current->mm->mmap_sem);
 		vma = find_vma (current->mm, vaddr);
 		if (!vma){
 			printk ("SHMIQ: could not find %lx the vma\n", vaddr);
+			up(&current->mm->mmap_sem);
 			return -EINVAL;
 		}
 		s = req.arg * sizeof (struct shmqevent) + sizeof (struct sharedMemoryInputQueue);
-		v = sys_munmap (vaddr, s);
+		v = do_munmap (vaddr, s);
 		do_mmap (filp, vaddr, s, PROT_READ | PROT_WRITE, MAP_PRIVATE|MAP_FIXED, 0);
+		up(&current->mm->mmap_sem);
 		shmiqs [minor].events = req.arg;
 		shmiqs [minor].mapped = 1;
 		return 0;

--
To unsubscribe, send a message with 'unsubscribe linux-mm' in
the body to majordomo@kvack.org.  For more info on Linux MM,
see: http://humbolt.geo.uu.nl/Linux-MM/