patch-2.1.3 linux/arch/i386/mm/fault.c

Next file: linux/drivers/block/md.c
Previous file: linux/arch/i386/math-emu/reg_round.S
Back to the patch index
Back to the overall index

diff -u --recursive --new-file v2.1.2/linux/arch/i386/mm/fault.c linux/arch/i386/mm/fault.c
@@ -22,6 +22,57 @@
 extern void die_if_kernel(const char *,struct pt_regs *,long);
 
 /*
+ * Ugly, ugly, but the goto's result in better assembly..
+ */
+int __verify_write(const void * addr, unsigned long size)
+{
+	struct vm_area_struct * vma;
+	unsigned long start = (unsigned long) addr;
+
+	if (!size)
+		return 0;
+
+	vma = find_vma(current->mm, start);
+	if (!vma)
+		goto bad_area;
+	if (vma->vm_start > start)
+		goto check_stack;
+
+good_area:
+	if (!(vma->vm_flags & VM_WRITE))
+		goto bad_area;
+	size--;
+	size += start & ~PAGE_MASK;
+	size >>= PAGE_SHIFT;
+	start &= PAGE_MASK;
+
+	for (;;) {
+		do_wp_page(current, vma, start, 1);
+		if (!size)
+			break;
+		size--;
+		start += PAGE_SIZE;
+		if (start < vma->vm_end)
+			continue;
+		vma = vma->vm_next;
+		if (!vma || vma->vm_start != start)
+			goto bad_area;
+		if (!(vma->vm_flags & VM_WRITE))
+			goto bad_area;;
+	}
+	return 0;
+
+check_stack:
+	if (!(vma->vm_flags & VM_GROWSDOWN))
+		goto bad_area;
+	if (expand_stack(vma, start) == 0)
+		goto good_area;
+
+bad_area:
+	return -EFAULT;
+}
+
+/*
  * This routine handles page faults.  It determines the address,
  * and the problem, and then passes it off to one of the appropriate
  * routines.

FUNET's LINUX-ADM group, linux-adm@nic.funet.fi
TCL-scripts by Sam Shen, slshen@lbl.gov