patch-2.3.10 linux/arch/mips/kernel/ptrace.c

Next file: linux/arch/mips/kernel/r4k_misc.S
Previous file: linux/arch/mips/kernel/irixioctl.c
Back to the patch index
Back to the overall index

diff -u --recursive --new-file v2.3.9/linux/arch/mips/kernel/ptrace.c linux/arch/mips/kernel/ptrace.c
@@ -25,218 +25,6 @@
 #include <asm/system.h>
 #include <asm/uaccess.h>
 
-/*
- * This routine gets a long from any process space by following the page
- * tables. NOTE! You should check that the long isn't on a page boundary,
- * and that it is in the task area before calling this: this routine does
- * no checking.
- */
-static unsigned long get_long(struct task_struct * tsk,
-			      struct vm_area_struct * vma, unsigned long addr)
-{
-	pgd_t *pgdir;
-	pmd_t *pgmiddle;
-	pte_t *pgtable;
-	unsigned long page, retval;
-
-repeat:
-	pgdir = pgd_offset(vma->vm_mm, addr);
-	if (pgd_none(*pgdir)) {
-		handle_mm_fault(tsk, vma, addr, 0);
-		goto repeat;
-	}
-	if (pgd_bad(*pgdir)) {
-		printk("ptrace: bad page directory %08lx\n", pgd_val(*pgdir));
-		pgd_clear(pgdir);
-		return 0;
-	}
-	pgmiddle = pmd_offset(pgdir, addr);
-	if (pmd_none(*pgmiddle)) {
-		handle_mm_fault(tsk, vma, addr, 0);
-		goto repeat;
-	}
-	if (pmd_bad(*pgmiddle)) {
-		printk("ptrace: bad page middle %08lx\n", pmd_val(*pgmiddle));
-		pmd_clear(pgmiddle);
-		return 0;
-	}
-	pgtable = pte_offset(pgmiddle, addr);
-	if (!pte_present(*pgtable)) {
-		handle_mm_fault(tsk, vma, addr, 0);
-		goto repeat;
-	}
-	page = pte_page(*pgtable);
-	/* This is a hack for non-kernel-mapped video buffers and similar */
-	if (MAP_NR(page) >= MAP_NR(high_memory))
-		return 0;
-	page += addr & ~PAGE_MASK;
-	/* We can't use flush_page_to_ram() since we're running in
-	 * another context ...
-	 */
-	flush_cache_all();
-	retval = *(unsigned long *) page;
-	flush_cache_all();	/* VCED avoidance  */
-	return retval;
-}
-
-/*
- * This routine puts a long into any process space by following the page
- * tables. NOTE! You should check that the long isn't on a page boundary,
- * and that it is in the task area before calling this: this routine does
- * no checking.
- *
- * Now keeps R/W state of page so that a text page stays readonly
- * even if a debugger scribbles breakpoints into it.  -M.U-
- */
-static void put_long(struct task_struct *tsk,
-		     struct vm_area_struct * vma, unsigned long addr,
-	unsigned long data)
-{
-	pgd_t *pgdir;
-	pmd_t *pgmiddle;
-	pte_t *pgtable;
-	unsigned long page;
-
-repeat:
-	pgdir = pgd_offset(vma->vm_mm, addr);
-	if (!pgd_present(*pgdir)) {
-		handle_mm_fault(tsk, vma, addr, 1);
-		goto repeat;
-	}
-	if (pgd_bad(*pgdir)) {
-		printk("ptrace: bad page directory %08lx\n", pgd_val(*pgdir));
-		pgd_clear(pgdir);
-		return;
-	}
-	pgmiddle = pmd_offset(pgdir, addr);
-	if (pmd_none(*pgmiddle)) {
-		handle_mm_fault(tsk, vma, addr, 1);
-		goto repeat;
-	}
-	if (pmd_bad(*pgmiddle)) {
-		printk("ptrace: bad page middle %08lx\n", pmd_val(*pgmiddle));
-		pmd_clear(pgmiddle);
-		return;
-	}
-	pgtable = pte_offset(pgmiddle, addr);
-	if (!pte_present(*pgtable)) {
-		handle_mm_fault(tsk, vma, addr, 1);
-		goto repeat;
-	}
-	page = pte_page(*pgtable);
-	if (!pte_write(*pgtable)) {
-		handle_mm_fault(tsk, vma, addr, 1);
-		goto repeat;
-	}
-	/* This is a hack for non-kernel-mapped video buffers and similar */
-	if (MAP_NR(page) < MAP_NR(high_memory))
-		flush_cache_all();
-	*(unsigned long *) (page + (addr & ~PAGE_MASK)) = data;
-	if (MAP_NR(page) < MAP_NR(high_memory))
-		flush_cache_all();
-	/*
-	 * We're bypassing pagetables, so we have to set the dirty bit
-	 * ourselves this should also re-instate whatever read-only mode
-	 * there was before
-	 */
-	set_pte(pgtable, pte_mkdirty(mk_pte(page, vma->vm_page_prot)));
-	flush_tlb_page(vma, addr);
-}
-
-/*
- * This routine checks the page boundaries, and that the offset is
- * within the task area. It then calls get_long() to read a long.
- */
-static int read_long(struct task_struct * tsk, unsigned long addr,
-	unsigned long * result)
-{
-	struct vm_area_struct * vma = find_extend_vma(tsk, addr);
-
-	if (!vma)
-		return -EIO;
-	if ((addr & ~PAGE_MASK) > PAGE_SIZE-sizeof(long)) {
-		unsigned long low,high;
-		struct vm_area_struct * vma_high = vma;
-
-		if (addr + sizeof(long) >= vma->vm_end) {
-			vma_high = vma->vm_next;
-			if (!vma_high || vma_high->vm_start != vma->vm_end)
-				return -EIO;
-		}
-		low = get_long(tsk, vma, addr & ~(sizeof(long)-1));
-		high = get_long(tsk, vma_high, (addr+sizeof(long)) & ~(sizeof(long)-1));
-		switch (addr & (sizeof(long)-1)) {
-			case 1:
-				low >>= 8;
-				low |= high << 24;
-				break;
-			case 2:
-				low >>= 16;
-				low |= high << 16;
-				break;
-			case 3:
-				low >>= 24;
-				low |= high << 8;
-				break;
-		}
-		*result = low;
-	} else
-		*result = get_long(tsk, vma, addr);
-	return 0;
-}
-
-/*
- * This routine checks the page boundaries, and that the offset is
- * within the task area. It then calls put_long() to write a long.
- */
-static int write_long(struct task_struct * tsk, unsigned long addr,
-	unsigned long data)
-{
-	struct vm_area_struct * vma = find_extend_vma(tsk, addr);
-
-	if (!vma)
-		return -EIO;
-	if ((addr & ~PAGE_MASK) > PAGE_SIZE-sizeof(long)) {
-		unsigned long low,high;
-		struct vm_area_struct * vma_high = vma;
-
-		if (addr + sizeof(long) >= vma->vm_end) {
-			vma_high = vma->vm_next;
-			if (!vma_high || vma_high->vm_start != vma->vm_end)
-				return -EIO;
-		}
-		low = get_long(tsk, vma, addr & ~(sizeof(long)-1));
-		high = get_long(tsk, vma_high, (addr+sizeof(long)) & ~(sizeof(long)-1));
-		switch (addr & (sizeof(long)-1)) {
-			case 0: /* shouldn't happen, but safety first */
-				low = data;
-				break;
-			case 1:
-				low &= 0x000000ff;
-				low |= data << 8;
-				high &= ~0xff;
-				high |= data >> 24;
-				break;
-			case 2:
-				low &= 0x0000ffff;
-				low |= data << 16;
-				high &= ~0xffff;
-				high |= data >> 16;
-				break;
-			case 3:
-				low &= 0x00ffffff;
-				low |= data << 24;
-				high &= ~0xffffff;
-				high |= data >> 8;
-				break;
-		}
-		put_long(tsk, vma, addr & ~(sizeof(long)-1),low);
-		put_long(tsk, vma_high, (addr+sizeof(long)) & ~(sizeof(long)-1),high);
-	} else
-		put_long(tsk, vma, addr, data);
-	return 0;
-}
-
 asmlinkage int sys_ptrace(long request, long pid, long addr, long data)
 {
 	struct task_struct *child;
@@ -322,15 +110,16 @@
 	case PTRACE_PEEKTEXT: /* read word at location addr. */ 
 	case PTRACE_PEEKDATA: {
 		unsigned long tmp;
+		int copied;
 
-		down(&child->mm->mmap_sem);
-		res = read_long(child, addr, &tmp);
-		up(&child->mm->mmap_sem);
-		if (res < 0)
+		copied = access_process_vm(child, addr, &tmp, sizeof(tmp), 0);
+		res = -EIO;
+		if (copied != sizeof(tmp))
 			goto out;
 		res = put_user(tmp,(unsigned long *) data);
+
 		goto out;
-		}
+	}
 
 	/* Read the word at location addr in the USER area.  */
 	case PTRACE_PEEKUSR: {
@@ -394,9 +183,11 @@
 
 	case PTRACE_POKETEXT: /* write the word at location addr. */
 	case PTRACE_POKEDATA:
-		down(&child->mm->mmap_sem);
-		res = write_long(child,addr,data);
-		up(&child->mm->mmap_sem);
+		res = 0;
+		if (access_process_vm(child, addr, &data, sizeof(data), 1)
+		    == sizeof(data))
+			goto out;
+		res = -EIO;
 		goto out;
 
 	case PTRACE_POKEUSR: {

FUNET's LINUX-ADM group, linux-adm@nic.funet.fi
TCL-scripts by Sam Shen (who was at: slshen@lbl.gov)