aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorLorenzo Stoakes <lstoakes@gmail.com>2016-10-12 20:20:20 -0400
committerLinus Torvalds <torvalds@linux-foundation.org>2016-10-19 11:31:25 -0400
commitf307ab6dcea03f9d8e4d70508fd7d1ca57cfa7f9 (patch)
tree94a96ebae9957cf1252231a69f8904796aa2563e
parent6347e8d5bcce33fc36e651901efefbe2c93a43ef (diff)
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: Lorenzo Stoakes <lstoakes@gmail.com> Acked-by: Jesper Nilsson <jesper.nilsson@axis.com> Acked-by: Michal Hocko <mhocko@suse.com> Acked-by: Michael Ellerman <mpe@ellerman.id.au> Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
-rw-r--r--arch/alpha/kernel/ptrace.c9
-rw-r--r--arch/blackfin/kernel/ptrace.c5
-rw-r--r--arch/cris/arch-v32/kernel/ptrace.c4
-rw-r--r--arch/ia64/kernel/ptrace.c14
-rw-r--r--arch/m32r/kernel/ptrace.c15
-rw-r--r--arch/mips/kernel/ptrace32.c5
-rw-r--r--arch/powerpc/kernel/ptrace32.c5
-rw-r--r--arch/score/kernel/ptrace.c10
-rw-r--r--arch/sparc/kernel/ptrace_64.c24
-rw-r--r--arch/x86/kernel/step.c3
-rw-r--r--arch/x86/um/ptrace_32.c3
-rw-r--r--arch/x86/um/ptrace_64.c3
-rw-r--r--include/linux/mm.h3
-rw-r--r--kernel/ptrace.c16
-rw-r--r--mm/memory.c8
-rw-r--r--mm/nommu.c6
-rw-r--r--mm/util.c5
17 files changed, 84 insertions, 54 deletions
diff --git a/arch/alpha/kernel/ptrace.c b/arch/alpha/kernel/ptrace.c
index d9ee81769899..940dfb406591 100644
--- a/arch/alpha/kernel/ptrace.c
+++ b/arch/alpha/kernel/ptrace.c
@@ -157,14 +157,16 @@ put_reg(struct task_struct *task, unsigned long regno, unsigned long data)
157static inline int 157static inline int
158read_int(struct task_struct *task, unsigned long addr, int * data) 158read_int(struct task_struct *task, unsigned long addr, int * data)
159{ 159{
160 int copied = access_process_vm(task, addr, data, sizeof(int), 0); 160 int copied = access_process_vm(task, addr, data, sizeof(int),
161 FOLL_FORCE);
161 return (copied == sizeof(int)) ? 0 : -EIO; 162 return (copied == sizeof(int)) ? 0 : -EIO;
162} 163}
163 164
164static inline int 165static inline int
165write_int(struct task_struct *task, unsigned long addr, int data) 166write_int(struct task_struct *task, unsigned long addr, int data)
166{ 167{
167 int copied = access_process_vm(task, addr, &data, sizeof(int), 1); 168 int copied = access_process_vm(task, addr, &data, sizeof(int),
169 FOLL_FORCE | FOLL_WRITE);
168 return (copied == sizeof(int)) ? 0 : -EIO; 170 return (copied == sizeof(int)) ? 0 : -EIO;
169} 171}
170 172
@@ -281,7 +283,8 @@ long arch_ptrace(struct task_struct *child, long request,
281 /* When I and D space are separate, these will need to be fixed. */ 283 /* When I and D space are separate, these will need to be fixed. */
282 case PTRACE_PEEKTEXT: /* read word at location addr. */ 284 case PTRACE_PEEKTEXT: /* read word at location addr. */
283 case PTRACE_PEEKDATA: 285 case PTRACE_PEEKDATA:
284 copied = access_process_vm(child, addr, &tmp, sizeof(tmp), 0); 286 copied = access_process_vm(child, addr, &tmp, sizeof(tmp),
287 FOLL_FORCE);
285 ret = -EIO; 288 ret = -EIO;
286 if (copied != sizeof(tmp)) 289 if (copied != sizeof(tmp))
287 break; 290 break;
diff --git a/arch/blackfin/kernel/ptrace.c b/arch/blackfin/kernel/ptrace.c
index 8b8fe671b1a6..8d79286ee4e8 100644
--- a/arch/blackfin/kernel/ptrace.c
+++ b/arch/blackfin/kernel/ptrace.c
@@ -271,7 +271,7 @@ long arch_ptrace(struct task_struct *child, long request,
271 case BFIN_MEM_ACCESS_CORE: 271 case BFIN_MEM_ACCESS_CORE:
272 case BFIN_MEM_ACCESS_CORE_ONLY: 272 case BFIN_MEM_ACCESS_CORE_ONLY:
273 copied = access_process_vm(child, addr, &tmp, 273 copied = access_process_vm(child, addr, &tmp,
274 to_copy, 0); 274 to_copy, FOLL_FORCE);
275 if (copied) 275 if (copied)
276 break; 276 break;
277 277
@@ -324,7 +324,8 @@ long arch_ptrace(struct task_struct *child, long request,
324 case BFIN_MEM_ACCESS_CORE: 324 case BFIN_MEM_ACCESS_CORE:
325 case BFIN_MEM_ACCESS_CORE_ONLY: 325 case BFIN_MEM_ACCESS_CORE_ONLY:
326 copied = access_process_vm(child, addr, &data, 326 copied = access_process_vm(child, addr, &data,
327 to_copy, 1); 327 to_copy,
328 FOLL_FORCE | FOLL_WRITE);
328 break; 329 break;
329 case BFIN_MEM_ACCESS_DMA: 330 case BFIN_MEM_ACCESS_DMA:
330 if (safe_dma_memcpy(paddr, &data, to_copy)) 331 if (safe_dma_memcpy(paddr, &data, to_copy))
diff --git a/arch/cris/arch-v32/kernel/ptrace.c b/arch/cris/arch-v32/kernel/ptrace.c
index f085229cf870..f0df654ac6fc 100644
--- a/arch/cris/arch-v32/kernel/ptrace.c
+++ b/arch/cris/arch-v32/kernel/ptrace.c
@@ -147,7 +147,7 @@ long arch_ptrace(struct task_struct *child, long request,
147 /* The trampoline page is globally mapped, no page table to traverse.*/ 147 /* The trampoline page is globally mapped, no page table to traverse.*/
148 tmp = *(unsigned long*)addr; 148 tmp = *(unsigned long*)addr;
149 } else { 149 } else {
150 copied = access_process_vm(child, addr, &tmp, sizeof(tmp), 0); 150 copied = access_process_vm(child, addr, &tmp, sizeof(tmp), FOLL_FORCE);
151 151
152 if (copied != sizeof(tmp)) 152 if (copied != sizeof(tmp))
153 break; 153 break;
@@ -279,7 +279,7 @@ static int insn_size(struct task_struct *child, unsigned long pc)
279 int opsize = 0; 279 int opsize = 0;
280 280
281 /* Read the opcode at pc (do what PTRACE_PEEKTEXT would do). */ 281 /* Read the opcode at pc (do what PTRACE_PEEKTEXT would do). */
282 copied = access_process_vm(child, pc, &opcode, sizeof(opcode), 0); 282 copied = access_process_vm(child, pc, &opcode, sizeof(opcode), FOLL_FORCE);
283 if (copied != sizeof(opcode)) 283 if (copied != sizeof(opcode))
284 return 0; 284 return 0;
285 285
diff --git a/arch/ia64/kernel/ptrace.c b/arch/ia64/kernel/ptrace.c
index 6f54d511cc50..31aa8c0f68e1 100644
--- a/arch/ia64/kernel/ptrace.c
+++ b/arch/ia64/kernel/ptrace.c
@@ -453,7 +453,7 @@ ia64_peek (struct task_struct *child, struct switch_stack *child_stack,
453 return 0; 453 return 0;
454 } 454 }
455 } 455 }
456 copied = access_process_vm(child, addr, &ret, sizeof(ret), 0); 456 copied = access_process_vm(child, addr, &ret, sizeof(ret), FOLL_FORCE);
457 if (copied != sizeof(ret)) 457 if (copied != sizeof(ret))
458 return -EIO; 458 return -EIO;
459 *val = ret; 459 *val = ret;
@@ -489,7 +489,8 @@ ia64_poke (struct task_struct *child, struct switch_stack *child_stack,
489 *ia64_rse_skip_regs(krbs, regnum) = val; 489 *ia64_rse_skip_regs(krbs, regnum) = val;
490 } 490 }
491 } 491 }
492 } else if (access_process_vm(child, addr, &val, sizeof(val), 1) 492 } else if (access_process_vm(child, addr, &val, sizeof(val),
493 FOLL_FORCE | FOLL_WRITE)
493 != sizeof(val)) 494 != sizeof(val))
494 return -EIO; 495 return -EIO;
495 return 0; 496 return 0;
@@ -543,7 +544,8 @@ ia64_sync_user_rbs (struct task_struct *child, struct switch_stack *sw,
543 ret = ia64_peek(child, sw, user_rbs_end, addr, &val); 544 ret = ia64_peek(child, sw, user_rbs_end, addr, &val);
544 if (ret < 0) 545 if (ret < 0)
545 return ret; 546 return ret;
546 if (access_process_vm(child, addr, &val, sizeof(val), 1) 547 if (access_process_vm(child, addr, &val, sizeof(val),
548 FOLL_FORCE | FOLL_WRITE)
547 != sizeof(val)) 549 != sizeof(val))
548 return -EIO; 550 return -EIO;
549 } 551 }
@@ -559,7 +561,8 @@ ia64_sync_kernel_rbs (struct task_struct *child, struct switch_stack *sw,
559 561
560 /* now copy word for word from user rbs to kernel rbs: */ 562 /* now copy word for word from user rbs to kernel rbs: */
561 for (addr = user_rbs_start; addr < user_rbs_end; addr += 8) { 563 for (addr = user_rbs_start; addr < user_rbs_end; addr += 8) {
562 if (access_process_vm(child, addr, &val, sizeof(val), 0) 564 if (access_process_vm(child, addr, &val, sizeof(val),
565 FOLL_FORCE)
563 != sizeof(val)) 566 != sizeof(val))
564 return -EIO; 567 return -EIO;
565 568
@@ -1156,7 +1159,8 @@ arch_ptrace (struct task_struct *child, long request,
1156 case PTRACE_PEEKTEXT: 1159 case PTRACE_PEEKTEXT:
1157 case PTRACE_PEEKDATA: 1160 case PTRACE_PEEKDATA:
1158 /* read word at location addr */ 1161 /* read word at location addr */
1159 if (access_process_vm(child, addr, &data, sizeof(data), 0) 1162 if (access_process_vm(child, addr, &data, sizeof(data),
1163 FOLL_FORCE)
1160 != sizeof(data)) 1164 != sizeof(data))
1161 return -EIO; 1165 return -EIO;
1162 /* ensure return value is not mistaken for error code */ 1166 /* ensure return value is not mistaken for error code */
diff --git a/arch/m32r/kernel/ptrace.c b/arch/m32r/kernel/ptrace.c
index 51f5e9aa4901..c145605a981f 100644
--- a/arch/m32r/kernel/ptrace.c
+++ b/arch/m32r/kernel/ptrace.c
@@ -493,7 +493,8 @@ unregister_all_debug_traps(struct task_struct *child)
493 int i; 493 int i;
494 494
495 for (i = 0; i < p->nr_trap; i++) 495 for (i = 0; i < p->nr_trap; i++)
496 access_process_vm(child, p->addr[i], &p->insn[i], sizeof(p->insn[i]), 1); 496 access_process_vm(child, p->addr[i], &p->insn[i], sizeof(p->insn[i]),
497 FOLL_FORCE | FOLL_WRITE);
497 p->nr_trap = 0; 498 p->nr_trap = 0;
498} 499}
499 500
@@ -537,7 +538,8 @@ embed_debug_trap(struct task_struct *child, unsigned long next_pc)
537 unsigned long next_insn, code; 538 unsigned long next_insn, code;
538 unsigned long addr = next_pc & ~3; 539 unsigned long addr = next_pc & ~3;
539 540
540 if (access_process_vm(child, addr, &next_insn, sizeof(next_insn), 0) 541 if (access_process_vm(child, addr, &next_insn, sizeof(next_insn),
542 FOLL_FORCE)
541 != sizeof(next_insn)) { 543 != sizeof(next_insn)) {
542 return -1; /* error */ 544 return -1; /* error */
543 } 545 }
@@ -546,7 +548,8 @@ embed_debug_trap(struct task_struct *child, unsigned long next_pc)
546 if (register_debug_trap(child, next_pc, next_insn, &code)) { 548 if (register_debug_trap(child, next_pc, next_insn, &code)) {
547 return -1; /* error */ 549 return -1; /* error */
548 } 550 }
549 if (access_process_vm(child, addr, &code, sizeof(code), 1) 551 if (access_process_vm(child, addr, &code, sizeof(code),
552 FOLL_FORCE | FOLL_WRITE)
550 != sizeof(code)) { 553 != sizeof(code)) {
551 return -1; /* error */ 554 return -1; /* error */
552 } 555 }
@@ -562,7 +565,8 @@ withdraw_debug_trap(struct pt_regs *regs)
562 addr = (regs->bpc - 2) & ~3; 565 addr = (regs->bpc - 2) & ~3;
563 regs->bpc -= 2; 566 regs->bpc -= 2;
564 if (unregister_debug_trap(current, addr, &code)) { 567 if (unregister_debug_trap(current, addr, &code)) {
565 access_process_vm(current, addr, &code, sizeof(code), 1); 568 access_process_vm(current, addr, &code, sizeof(code),
569 FOLL_FORCE | FOLL_WRITE);
566 invalidate_cache(); 570 invalidate_cache();
567 } 571 }
568} 572}
@@ -589,7 +593,8 @@ void user_enable_single_step(struct task_struct *child)
589 /* Compute next pc. */ 593 /* Compute next pc. */
590 pc = get_stack_long(child, PT_BPC); 594 pc = get_stack_long(child, PT_BPC);
591 595
592 if (access_process_vm(child, pc&~3, &insn, sizeof(insn), 0) 596 if (access_process_vm(child, pc&~3, &insn, sizeof(insn),
597 FOLL_FORCE)
593 != sizeof(insn)) 598 != sizeof(insn))
594 return; 599 return;
595 600
diff --git a/arch/mips/kernel/ptrace32.c b/arch/mips/kernel/ptrace32.c
index 283b5a1967d1..7e71a4e0281b 100644
--- a/arch/mips/kernel/ptrace32.c
+++ b/arch/mips/kernel/ptrace32.c
@@ -70,7 +70,7 @@ long compat_arch_ptrace(struct task_struct *child, compat_long_t request,
70 break; 70 break;
71 71
72 copied = access_process_vm(child, (u64)addrOthers, &tmp, 72 copied = access_process_vm(child, (u64)addrOthers, &tmp,
73 sizeof(tmp), 0); 73 sizeof(tmp), FOLL_FORCE);
74 if (copied != sizeof(tmp)) 74 if (copied != sizeof(tmp))
75 break; 75 break;
76 ret = put_user(tmp, (u32 __user *) (unsigned long) data); 76 ret = put_user(tmp, (u32 __user *) (unsigned long) data);
@@ -179,7 +179,8 @@ long compat_arch_ptrace(struct task_struct *child, compat_long_t request,
179 break; 179 break;
180 ret = 0; 180 ret = 0;
181 if (access_process_vm(child, (u64)addrOthers, &data, 181 if (access_process_vm(child, (u64)addrOthers, &data,
182 sizeof(data), 1) == sizeof(data)) 182 sizeof(data),
183 FOLL_FORCE | FOLL_WRITE) == sizeof(data))
183 break; 184 break;
184 ret = -EIO; 185 ret = -EIO;
185 break; 186 break;
diff --git a/arch/powerpc/kernel/ptrace32.c b/arch/powerpc/kernel/ptrace32.c
index f52b7db327c8..010b7b310237 100644
--- a/arch/powerpc/kernel/ptrace32.c
+++ b/arch/powerpc/kernel/ptrace32.c
@@ -74,7 +74,7 @@ long compat_arch_ptrace(struct task_struct *child, compat_long_t request,
74 break; 74 break;
75 75
76 copied = access_process_vm(child, (u64)addrOthers, &tmp, 76 copied = access_process_vm(child, (u64)addrOthers, &tmp,
77 sizeof(tmp), 0); 77 sizeof(tmp), FOLL_FORCE);
78 if (copied != sizeof(tmp)) 78 if (copied != sizeof(tmp))
79 break; 79 break;
80 ret = put_user(tmp, (u32 __user *)data); 80 ret = put_user(tmp, (u32 __user *)data);
@@ -179,7 +179,8 @@ long compat_arch_ptrace(struct task_struct *child, compat_long_t request,
179 break; 179 break;
180 ret = 0; 180 ret = 0;
181 if (access_process_vm(child, (u64)addrOthers, &tmp, 181 if (access_process_vm(child, (u64)addrOthers, &tmp,
182 sizeof(tmp), 1) == sizeof(tmp)) 182 sizeof(tmp),
183 FOLL_FORCE | FOLL_WRITE) == sizeof(tmp))
183 break; 184 break;
184 ret = -EIO; 185 ret = -EIO;
185 break; 186 break;
diff --git a/arch/score/kernel/ptrace.c b/arch/score/kernel/ptrace.c
index 55836188b217..4f7314d5f334 100644
--- a/arch/score/kernel/ptrace.c
+++ b/arch/score/kernel/ptrace.c
@@ -131,7 +131,7 @@ read_tsk_long(struct task_struct *child,
131{ 131{
132 int copied; 132 int copied;
133 133
134 copied = access_process_vm(child, addr, res, sizeof(*res), 0); 134 copied = access_process_vm(child, addr, res, sizeof(*res), FOLL_FORCE);
135 135
136 return copied != sizeof(*res) ? -EIO : 0; 136 return copied != sizeof(*res) ? -EIO : 0;
137} 137}
@@ -142,7 +142,7 @@ read_tsk_short(struct task_struct *child,
142{ 142{
143 int copied; 143 int copied;
144 144
145 copied = access_process_vm(child, addr, res, sizeof(*res), 0); 145 copied = access_process_vm(child, addr, res, sizeof(*res), FOLL_FORCE);
146 146
147 return copied != sizeof(*res) ? -EIO : 0; 147 return copied != sizeof(*res) ? -EIO : 0;
148} 148}
@@ -153,7 +153,8 @@ write_tsk_short(struct task_struct *child,
153{ 153{
154 int copied; 154 int copied;
155 155
156 copied = access_process_vm(child, addr, &val, sizeof(val), 1); 156 copied = access_process_vm(child, addr, &val, sizeof(val),
157 FOLL_FORCE | FOLL_WRITE);
157 158
158 return copied != sizeof(val) ? -EIO : 0; 159 return copied != sizeof(val) ? -EIO : 0;
159} 160}
@@ -164,7 +165,8 @@ write_tsk_long(struct task_struct *child,
164{ 165{
165 int copied; 166 int copied;
166 167
167 copied = access_process_vm(child, addr, &val, sizeof(val), 1); 168 copied = access_process_vm(child, addr, &val, sizeof(val),
169 FOLL_FORCE | FOLL_WRITE);
168 170
169 return copied != sizeof(val) ? -EIO : 0; 171 return copied != sizeof(val) ? -EIO : 0;
170} 172}
diff --git a/arch/sparc/kernel/ptrace_64.c b/arch/sparc/kernel/ptrace_64.c
index 9ddc4928a089..ac082dd8c67d 100644
--- a/arch/sparc/kernel/ptrace_64.c
+++ b/arch/sparc/kernel/ptrace_64.c
@@ -127,7 +127,8 @@ static int get_from_target(struct task_struct *target, unsigned long uaddr,
127 if (copy_from_user(kbuf, (void __user *) uaddr, len)) 127 if (copy_from_user(kbuf, (void __user *) uaddr, len))
128 return -EFAULT; 128 return -EFAULT;
129 } else { 129 } else {
130 int len2 = access_process_vm(target, uaddr, kbuf, len, 0); 130 int len2 = access_process_vm(target, uaddr, kbuf, len,
131 FOLL_FORCE);
131 if (len2 != len) 132 if (len2 != len)
132 return -EFAULT; 133 return -EFAULT;
133 } 134 }
@@ -141,7 +142,8 @@ static int set_to_target(struct task_struct *target, unsigned long uaddr,
141 if (copy_to_user((void __user *) uaddr, kbuf, len)) 142 if (copy_to_user((void __user *) uaddr, kbuf, len))
142 return -EFAULT; 143 return -EFAULT;
143 } else { 144 } else {
144 int len2 = access_process_vm(target, uaddr, kbuf, len, 1); 145 int len2 = access_process_vm(target, uaddr, kbuf, len,
146 FOLL_FORCE | FOLL_WRITE);
145 if (len2 != len) 147 if (len2 != len)
146 return -EFAULT; 148 return -EFAULT;
147 } 149 }
@@ -505,7 +507,8 @@ static int genregs32_get(struct task_struct *target,
505 if (access_process_vm(target, 507 if (access_process_vm(target,
506 (unsigned long) 508 (unsigned long)
507 &reg_window[pos], 509 &reg_window[pos],
508 k, sizeof(*k), 0) 510 k, sizeof(*k),
511 FOLL_FORCE)
509 != sizeof(*k)) 512 != sizeof(*k))
510 return -EFAULT; 513 return -EFAULT;
511 k++; 514 k++;
@@ -531,12 +534,14 @@ static int genregs32_get(struct task_struct *target,
531 if (access_process_vm(target, 534 if (access_process_vm(target,
532 (unsigned long) 535 (unsigned long)
533 &reg_window[pos], 536 &reg_window[pos],
534 &reg, sizeof(reg), 0) 537 &reg, sizeof(reg),
538 FOLL_FORCE)
535 != sizeof(reg)) 539 != sizeof(reg))
536 return -EFAULT; 540 return -EFAULT;
537 if (access_process_vm(target, 541 if (access_process_vm(target,
538 (unsigned long) u, 542 (unsigned long) u,
539 &reg, sizeof(reg), 1) 543 &reg, sizeof(reg),
544 FOLL_FORCE | FOLL_WRITE)
540 != sizeof(reg)) 545 != sizeof(reg))
541 return -EFAULT; 546 return -EFAULT;
542 pos++; 547 pos++;
@@ -615,7 +620,8 @@ static int genregs32_set(struct task_struct *target,
615 (unsigned long) 620 (unsigned long)
616 &reg_window[pos], 621 &reg_window[pos],
617 (void *) k, 622 (void *) k,
618 sizeof(*k), 1) 623 sizeof(*k),
624 FOLL_FORCE | FOLL_WRITE)
619 != sizeof(*k)) 625 != sizeof(*k))
620 return -EFAULT; 626 return -EFAULT;
621 k++; 627 k++;
@@ -642,13 +648,15 @@ static int genregs32_set(struct task_struct *target,
642 if (access_process_vm(target, 648 if (access_process_vm(target,
643 (unsigned long) 649 (unsigned long)
644 u, 650 u,
645 &reg, sizeof(reg), 0) 651 &reg, sizeof(reg),
652 FOLL_FORCE)
646 != sizeof(reg)) 653 != sizeof(reg))
647 return -EFAULT; 654 return -EFAULT;
648 if (access_process_vm(target, 655 if (access_process_vm(target,
649 (unsigned long) 656 (unsigned long)
650 &reg_window[pos], 657 &reg_window[pos],
651 &reg, sizeof(reg), 1) 658 &reg, sizeof(reg),
659 FOLL_FORCE | FOLL_WRITE)
652 != sizeof(reg)) 660 != sizeof(reg))
653 return -EFAULT; 661 return -EFAULT;
654 pos++; 662 pos++;
diff --git a/arch/x86/kernel/step.c b/arch/x86/kernel/step.c
index c9a073866ca7..a23ce84a3f6c 100644
--- a/arch/x86/kernel/step.c
+++ b/arch/x86/kernel/step.c
@@ -57,7 +57,8 @@ static int is_setting_trap_flag(struct task_struct *child, struct pt_regs *regs)
57 unsigned char opcode[15]; 57 unsigned char opcode[15];
58 unsigned long addr = convert_ip_to_linear(child, regs); 58 unsigned long addr = convert_ip_to_linear(child, regs);
59 59
60 copied = access_process_vm(child, addr, opcode, sizeof(opcode), 0); 60 copied = access_process_vm(child, addr, opcode, sizeof(opcode),
61 FOLL_FORCE);
61 for (i = 0; i < copied; i++) { 62 for (i = 0; i < copied; i++) {
62 switch (opcode[i]) { 63 switch (opcode[i]) {
63 /* popf and iret */ 64 /* popf and iret */
diff --git a/arch/x86/um/ptrace_32.c b/arch/x86/um/ptrace_32.c
index 5766ead6fdb9..60a5a5a85505 100644
--- a/arch/x86/um/ptrace_32.c
+++ b/arch/x86/um/ptrace_32.c
@@ -36,7 +36,8 @@ int is_syscall(unsigned long addr)
36 * slow, but that doesn't matter, since it will be called only 36 * slow, but that doesn't matter, since it will be called only
37 * in case of singlestepping, if copy_from_user failed. 37 * in case of singlestepping, if copy_from_user failed.
38 */ 38 */
39 n = access_process_vm(current, addr, &instr, sizeof(instr), 0); 39 n = access_process_vm(current, addr, &instr, sizeof(instr),
40 FOLL_FORCE);
40 if (n != sizeof(instr)) { 41 if (n != sizeof(instr)) {
41 printk(KERN_ERR "is_syscall : failed to read " 42 printk(KERN_ERR "is_syscall : failed to read "
42 "instruction from 0x%lx\n", addr); 43 "instruction from 0x%lx\n", addr);
diff --git a/arch/x86/um/ptrace_64.c b/arch/x86/um/ptrace_64.c
index 0b5c184dd5b3..e30202b1716e 100644
--- a/arch/x86/um/ptrace_64.c
+++ b/arch/x86/um/ptrace_64.c
@@ -212,7 +212,8 @@ int is_syscall(unsigned long addr)
212 * slow, but that doesn't matter, since it will be called only 212 * slow, but that doesn't matter, since it will be called only
213 * in case of singlestepping, if copy_from_user failed. 213 * in case of singlestepping, if copy_from_user failed.
214 */ 214 */
215 n = access_process_vm(current, addr, &instr, sizeof(instr), 0); 215 n = access_process_vm(current, addr, &instr, sizeof(instr),
216 FOLL_FORCE);
216 if (n != sizeof(instr)) { 217 if (n != sizeof(instr)) {
217 printk("is_syscall : failed to read instruction from " 218 printk("is_syscall : failed to read instruction from "
218 "0x%lx\n", addr); 219 "0x%lx\n", addr);
diff --git a/include/linux/mm.h b/include/linux/mm.h
index f31bf9058587..ffbd72979ee7 100644
--- a/include/linux/mm.h
+++ b/include/linux/mm.h
@@ -1266,7 +1266,8 @@ static inline int fixup_user_fault(struct task_struct *tsk,
1266} 1266}
1267#endif 1267#endif
1268 1268
1269extern int access_process_vm(struct task_struct *tsk, unsigned long addr, void *buf, int len, int write); 1269extern int access_process_vm(struct task_struct *tsk, unsigned long addr, void *buf, int len,
1270 unsigned int gup_flags);
1270extern int access_remote_vm(struct mm_struct *mm, unsigned long addr, 1271extern int access_remote_vm(struct mm_struct *mm, unsigned long addr,
1271 void *buf, int len, unsigned int gup_flags); 1272 void *buf, int len, unsigned int gup_flags);
1272 1273
diff --git a/kernel/ptrace.c b/kernel/ptrace.c
index 2a99027312a6..e6474f7272ec 100644
--- a/kernel/ptrace.c
+++ b/kernel/ptrace.c
@@ -537,7 +537,7 @@ int ptrace_readdata(struct task_struct *tsk, unsigned long src, char __user *dst
537 int this_len, retval; 537 int this_len, retval;
538 538
539 this_len = (len > sizeof(buf)) ? sizeof(buf) : len; 539 this_len = (len > sizeof(buf)) ? sizeof(buf) : len;
540 retval = access_process_vm(tsk, src, buf, this_len, 0); 540 retval = access_process_vm(tsk, src, buf, this_len, FOLL_FORCE);
541 if (!retval) { 541 if (!retval) {
542 if (copied) 542 if (copied)
543 break; 543 break;
@@ -564,7 +564,8 @@ int ptrace_writedata(struct task_struct *tsk, char __user *src, unsigned long ds
564 this_len = (len > sizeof(buf)) ? sizeof(buf) : len; 564 this_len = (len > sizeof(buf)) ? sizeof(buf) : len;
565 if (copy_from_user(buf, src, this_len)) 565 if (copy_from_user(buf, src, this_len))
566 return -EFAULT; 566 return -EFAULT;
567 retval = access_process_vm(tsk, dst, buf, this_len, 1); 567 retval = access_process_vm(tsk, dst, buf, this_len,
568 FOLL_FORCE | FOLL_WRITE);
568 if (!retval) { 569 if (!retval) {
569 if (copied) 570 if (copied)
570 break; 571 break;
@@ -1127,7 +1128,7 @@ int generic_ptrace_peekdata(struct task_struct *tsk, unsigned long addr,
1127 unsigned long tmp; 1128 unsigned long tmp;
1128 int copied; 1129 int copied;
1129 1130
1130 copied = access_process_vm(tsk, addr, &tmp, sizeof(tmp), 0); 1131 copied = access_process_vm(tsk, addr, &tmp, sizeof(tmp), FOLL_FORCE);
1131 if (copied != sizeof(tmp)) 1132 if (copied != sizeof(tmp))
1132 return -EIO; 1133 return -EIO;
1133 return put_user(tmp, (unsigned long __user *)data); 1134 return put_user(tmp, (unsigned long __user *)data);
@@ -1138,7 +1139,8 @@ int generic_ptrace_pokedata(struct task_struct *tsk, unsigned long addr,
1138{ 1139{
1139 int copied; 1140 int copied;
1140 1141
1141 copied = access_process_vm(tsk, addr, &data, sizeof(data), 1); 1142 copied = access_process_vm(tsk, addr, &data, sizeof(data),
1143 FOLL_FORCE | FOLL_WRITE);
1142 return (copied == sizeof(data)) ? 0 : -EIO; 1144 return (copied == sizeof(data)) ? 0 : -EIO;
1143} 1145}
1144 1146
@@ -1155,7 +1157,8 @@ int compat_ptrace_request(struct task_struct *child, compat_long_t request,
1155 switch (request) { 1157 switch (request) {
1156 case PTRACE_PEEKTEXT: 1158 case PTRACE_PEEKTEXT:
1157 case PTRACE_PEEKDATA: 1159 case PTRACE_PEEKDATA:
1158 ret = access_process_vm(child, addr, &word, sizeof(word), 0); 1160 ret = access_process_vm(child, addr, &word, sizeof(word),
1161 FOLL_FORCE);
1159 if (ret != sizeof(word)) 1162 if (ret != sizeof(word))
1160 ret = -EIO; 1163 ret = -EIO;
1161 else 1164 else
@@ -1164,7 +1167,8 @@ int compat_ptrace_request(struct task_struct *child, compat_long_t request,
1164 1167
1165 case PTRACE_POKETEXT: 1168 case PTRACE_POKETEXT:
1166 case PTRACE_POKEDATA: 1169 case PTRACE_POKEDATA:
1167 ret = access_process_vm(child, addr, &data, sizeof(data), 1); 1170 ret = access_process_vm(child, addr, &data, sizeof(data),
1171 FOLL_FORCE | FOLL_WRITE);
1168 ret = (ret != sizeof(data) ? -EIO : 0); 1172 ret = (ret != sizeof(data) ? -EIO : 0);
1169 break; 1173 break;
1170 1174
diff --git a/mm/memory.c b/mm/memory.c
index bac2d994850e..e18c57bdc75c 100644
--- a/mm/memory.c
+++ b/mm/memory.c
@@ -3951,20 +3951,16 @@ int access_remote_vm(struct mm_struct *mm, unsigned long addr,
3951 * Do not walk the page table directly, use get_user_pages 3951 * Do not walk the page table directly, use get_user_pages
3952 */ 3952 */
3953int access_process_vm(struct task_struct *tsk, unsigned long addr, 3953int access_process_vm(struct task_struct *tsk, unsigned long addr,
3954 void *buf, int len, int write) 3954 void *buf, int len, unsigned int gup_flags)
3955{ 3955{
3956 struct mm_struct *mm; 3956 struct mm_struct *mm;
3957 int ret; 3957 int ret;
3958 unsigned int flags = FOLL_FORCE;
3959 3958
3960 mm = get_task_mm(tsk); 3959 mm = get_task_mm(tsk);
3961 if (!mm) 3960 if (!mm)
3962 return 0; 3961 return 0;
3963 3962
3964 if (write) 3963 ret = __access_remote_vm(tsk, mm, addr, buf, len, gup_flags);
3965 flags |= FOLL_WRITE;
3966
3967 ret = __access_remote_vm(tsk, mm, addr, buf, len, flags);
3968 3964
3969 mmput(mm); 3965 mmput(mm);
3970 3966
diff --git a/mm/nommu.c b/mm/nommu.c
index 93d5bb53fc63..db5fd1795298 100644
--- a/mm/nommu.c
+++ b/mm/nommu.c
@@ -1861,7 +1861,8 @@ int access_remote_vm(struct mm_struct *mm, unsigned long addr,
1861 * Access another process' address space. 1861 * Access another process' address space.
1862 * - source/target buffer must be kernel space 1862 * - source/target buffer must be kernel space
1863 */ 1863 */
1864int access_process_vm(struct task_struct *tsk, unsigned long addr, void *buf, int len, int write) 1864int access_process_vm(struct task_struct *tsk, unsigned long addr, void *buf, int len,
1865 unsigned int gup_flags)
1865{ 1866{
1866 struct mm_struct *mm; 1867 struct mm_struct *mm;
1867 1868
@@ -1872,8 +1873,7 @@ int access_process_vm(struct task_struct *tsk, unsigned long addr, void *buf, in
1872 if (!mm) 1873 if (!mm)
1873 return 0; 1874 return 0;
1874 1875
1875 len = __access_remote_vm(tsk, mm, addr, buf, len, 1876 len = __access_remote_vm(tsk, mm, addr, buf, len, gup_flags);
1876 write ? FOLL_WRITE : 0);
1877 1877
1878 mmput(mm); 1878 mmput(mm);
1879 return len; 1879 return len;
diff --git a/mm/util.c b/mm/util.c
index 4c685bde5ebc..952cbe7ad7b7 100644
--- a/mm/util.c
+++ b/mm/util.c
@@ -624,7 +624,7 @@ int get_cmdline(struct task_struct *task, char *buffer, int buflen)
624 if (len > buflen) 624 if (len > buflen)
625 len = buflen; 625 len = buflen;
626 626
627 res = access_process_vm(task, arg_start, buffer, len, 0); 627 res = access_process_vm(task, arg_start, buffer, len, FOLL_FORCE);
628 628
629 /* 629 /*
630 * If the nul at the end of args has been overwritten, then 630 * If the nul at the end of args has been overwritten, then
@@ -639,7 +639,8 @@ int get_cmdline(struct task_struct *task, char *buffer, int buflen)
639 if (len > buflen - res) 639 if (len > buflen - res)
640 len = buflen - res; 640 len = buflen - res;
641 res += access_process_vm(task, env_start, 641 res += access_process_vm(task, env_start,
642 buffer+res, len, 0); 642 buffer+res, len,
643 FOLL_FORCE);
643 res = strnlen(buffer, res); 644 res = strnlen(buffer, res);
644 } 645 }
645 } 646 }