Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit f307ab6d authored by Lorenzo Stoakes's avatar Lorenzo Stoakes Committed by Linus Torvalds
Browse files

mm: replace access_process_vm() write parameter with gup_flags



This removes the 'write' argument from access_process_vm() and replaces
it with 'gup_flags' as use of this function previously silently implied
FOLL_FORCE, whereas after this patch callers explicitly pass this flag.

We make this explicit as use of FOLL_FORCE can result in surprising
behaviour (and hence bugs) within the mm subsystem.

Signed-off-by: default avatarLorenzo Stoakes <lstoakes@gmail.com>
Acked-by: default avatarJesper Nilsson <jesper.nilsson@axis.com>
Acked-by: default avatarMichal Hocko <mhocko@suse.com>
Acked-by: default avatarMichael Ellerman <mpe@ellerman.id.au>
Signed-off-by: default avatarLinus Torvalds <torvalds@linux-foundation.org>
parent 6347e8d5
Loading
Loading
Loading
Loading
+6 −3
Original line number Diff line number Diff line
@@ -157,14 +157,16 @@ put_reg(struct task_struct *task, unsigned long regno, unsigned long data)
static inline int
read_int(struct task_struct *task, unsigned long addr, int * data)
{
	int copied = access_process_vm(task, addr, data, sizeof(int), 0);
	int copied = access_process_vm(task, addr, data, sizeof(int),
			FOLL_FORCE);
	return (copied == sizeof(int)) ? 0 : -EIO;
}

static inline int
write_int(struct task_struct *task, unsigned long addr, int data)
{
	int copied = access_process_vm(task, addr, &data, sizeof(int), 1);
	int copied = access_process_vm(task, addr, &data, sizeof(int),
			FOLL_FORCE | FOLL_WRITE);
	return (copied == sizeof(int)) ? 0 : -EIO;
}

@@ -281,7 +283,8 @@ long arch_ptrace(struct task_struct *child, long request,
	/* When I and D space are separate, these will need to be fixed.  */
	case PTRACE_PEEKTEXT: /* read word at location addr. */
	case PTRACE_PEEKDATA:
		copied = access_process_vm(child, addr, &tmp, sizeof(tmp), 0);
		copied = access_process_vm(child, addr, &tmp, sizeof(tmp),
				FOLL_FORCE);
		ret = -EIO;
		if (copied != sizeof(tmp))
			break;
+3 −2
Original line number Diff line number Diff line
@@ -271,7 +271,7 @@ long arch_ptrace(struct task_struct *child, long request,
			case BFIN_MEM_ACCESS_CORE:
			case BFIN_MEM_ACCESS_CORE_ONLY:
				copied = access_process_vm(child, addr, &tmp,
				                           to_copy, 0);
							   to_copy, FOLL_FORCE);
				if (copied)
					break;

@@ -324,7 +324,8 @@ long arch_ptrace(struct task_struct *child, long request,
			case BFIN_MEM_ACCESS_CORE:
			case BFIN_MEM_ACCESS_CORE_ONLY:
				copied = access_process_vm(child, addr, &data,
				                           to_copy, 1);
				                           to_copy,
							   FOLL_FORCE | FOLL_WRITE);
				break;
			case BFIN_MEM_ACCESS_DMA:
				if (safe_dma_memcpy(paddr, &data, to_copy))
+2 −2
Original line number Diff line number Diff line
@@ -147,7 +147,7 @@ long arch_ptrace(struct task_struct *child, long request,
				/* The trampoline page is globally mapped, no page table to traverse.*/
				tmp = *(unsigned long*)addr;
			} else {
				copied = access_process_vm(child, addr, &tmp, sizeof(tmp), 0);
				copied = access_process_vm(child, addr, &tmp, sizeof(tmp), FOLL_FORCE);

				if (copied != sizeof(tmp))
					break;
@@ -279,7 +279,7 @@ static int insn_size(struct task_struct *child, unsigned long pc)
  int opsize = 0;

  /* Read the opcode at pc (do what PTRACE_PEEKTEXT would do). */
  copied = access_process_vm(child, pc, &opcode, sizeof(opcode), 0);
  copied = access_process_vm(child, pc, &opcode, sizeof(opcode), FOLL_FORCE);
  if (copied != sizeof(opcode))
    return 0;

+9 −5
Original line number Diff line number Diff line
@@ -453,7 +453,7 @@ ia64_peek (struct task_struct *child, struct switch_stack *child_stack,
			return 0;
		}
	}
	copied = access_process_vm(child, addr, &ret, sizeof(ret), 0);
	copied = access_process_vm(child, addr, &ret, sizeof(ret), FOLL_FORCE);
	if (copied != sizeof(ret))
		return -EIO;
	*val = ret;
@@ -489,7 +489,8 @@ ia64_poke (struct task_struct *child, struct switch_stack *child_stack,
				*ia64_rse_skip_regs(krbs, regnum) = val;
			}
		}
	} else if (access_process_vm(child, addr, &val, sizeof(val), 1)
	} else if (access_process_vm(child, addr, &val, sizeof(val),
				FOLL_FORCE | FOLL_WRITE)
		   != sizeof(val))
		return -EIO;
	return 0;
@@ -543,7 +544,8 @@ ia64_sync_user_rbs (struct task_struct *child, struct switch_stack *sw,
		ret = ia64_peek(child, sw, user_rbs_end, addr, &val);
		if (ret < 0)
			return ret;
		if (access_process_vm(child, addr, &val, sizeof(val), 1)
		if (access_process_vm(child, addr, &val, sizeof(val),
				FOLL_FORCE | FOLL_WRITE)
		    != sizeof(val))
			return -EIO;
	}
@@ -559,7 +561,8 @@ ia64_sync_kernel_rbs (struct task_struct *child, struct switch_stack *sw,

	/* now copy word for word from user rbs to kernel rbs: */
	for (addr = user_rbs_start; addr < user_rbs_end; addr += 8) {
		if (access_process_vm(child, addr, &val, sizeof(val), 0)
		if (access_process_vm(child, addr, &val, sizeof(val),
				FOLL_FORCE)
				!= sizeof(val))
			return -EIO;

@@ -1156,7 +1159,8 @@ arch_ptrace (struct task_struct *child, long request,
	case PTRACE_PEEKTEXT:
	case PTRACE_PEEKDATA:
		/* read word at location addr */
		if (access_process_vm(child, addr, &data, sizeof(data), 0)
		if (access_process_vm(child, addr, &data, sizeof(data),
				FOLL_FORCE)
		    != sizeof(data))
			return -EIO;
		/* ensure return value is not mistaken for error code */
+10 −5
Original line number Diff line number Diff line
@@ -493,7 +493,8 @@ unregister_all_debug_traps(struct task_struct *child)
	int i;

	for (i = 0; i < p->nr_trap; i++)
		access_process_vm(child, p->addr[i], &p->insn[i], sizeof(p->insn[i]), 1);
		access_process_vm(child, p->addr[i], &p->insn[i], sizeof(p->insn[i]),
				FOLL_FORCE | FOLL_WRITE);
	p->nr_trap = 0;
}

@@ -537,7 +538,8 @@ embed_debug_trap(struct task_struct *child, unsigned long next_pc)
	unsigned long next_insn, code;
	unsigned long addr = next_pc & ~3;

	if (access_process_vm(child, addr, &next_insn, sizeof(next_insn), 0)
	if (access_process_vm(child, addr, &next_insn, sizeof(next_insn),
			FOLL_FORCE)
	    != sizeof(next_insn)) {
		return -1; /* error */
	}
@@ -546,7 +548,8 @@ embed_debug_trap(struct task_struct *child, unsigned long next_pc)
	if (register_debug_trap(child, next_pc, next_insn, &code)) {
		return -1; /* error */
	}
	if (access_process_vm(child, addr, &code, sizeof(code), 1)
	if (access_process_vm(child, addr, &code, sizeof(code),
			FOLL_FORCE | FOLL_WRITE)
	    != sizeof(code)) {
		return -1; /* error */
	}
@@ -562,7 +565,8 @@ withdraw_debug_trap(struct pt_regs *regs)
 	addr = (regs->bpc - 2) & ~3;
	regs->bpc -= 2;
	if (unregister_debug_trap(current, addr, &code)) {
	    access_process_vm(current, addr, &code, sizeof(code), 1);
	    access_process_vm(current, addr, &code, sizeof(code),
		    FOLL_FORCE | FOLL_WRITE);
	    invalidate_cache();
	}
}
@@ -589,7 +593,8 @@ void user_enable_single_step(struct task_struct *child)
	/* Compute next pc.  */
	pc = get_stack_long(child, PT_BPC);

	if (access_process_vm(child, pc&~3, &insn, sizeof(insn), 0)
	if (access_process_vm(child, pc&~3, &insn, sizeof(insn),
			FOLL_FORCE)
	    != sizeof(insn))
		return;

Loading