Skip to content

Commit f307ab6

Browse files
lorenzo-stoakestorvalds
authored andcommitted
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 <[email protected]> Acked-by: Jesper Nilsson <[email protected]> Acked-by: Michal Hocko <[email protected]> Acked-by: Michael Ellerman <[email protected]> Signed-off-by: Linus Torvalds <[email protected]>
1 parent 6347e8d commit f307ab6

File tree

17 files changed

+84
-54
lines changed

17 files changed

+84
-54
lines changed

arch/alpha/kernel/ptrace.c

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -157,14 +157,16 @@ put_reg(struct task_struct *task, unsigned long regno, unsigned long data)
157157
static inline int
158158
read_int(struct task_struct *task, unsigned long addr, int * data)
159159
{
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);
161162
return (copied == sizeof(int)) ? 0 : -EIO;
162163
}
163164

164165
static inline int
165166
write_int(struct task_struct *task, unsigned long addr, int data)
166167
{
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);
168170
return (copied == sizeof(int)) ? 0 : -EIO;
169171
}
170172

@@ -281,7 +283,8 @@ long arch_ptrace(struct task_struct *child, long request,
281283
/* When I and D space are separate, these will need to be fixed. */
282284
case PTRACE_PEEKTEXT: /* read word at location addr. */
283285
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);
285288
ret = -EIO;
286289
if (copied != sizeof(tmp))
287290
break;

arch/blackfin/kernel/ptrace.c

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -271,7 +271,7 @@ long arch_ptrace(struct task_struct *child, long request,
271271
case BFIN_MEM_ACCESS_CORE:
272272
case BFIN_MEM_ACCESS_CORE_ONLY:
273273
copied = access_process_vm(child, addr, &tmp,
274-
to_copy, 0);
274+
to_copy, FOLL_FORCE);
275275
if (copied)
276276
break;
277277

@@ -324,7 +324,8 @@ long arch_ptrace(struct task_struct *child, long request,
324324
case BFIN_MEM_ACCESS_CORE:
325325
case BFIN_MEM_ACCESS_CORE_ONLY:
326326
copied = access_process_vm(child, addr, &data,
327-
to_copy, 1);
327+
to_copy,
328+
FOLL_FORCE | FOLL_WRITE);
328329
break;
329330
case BFIN_MEM_ACCESS_DMA:
330331
if (safe_dma_memcpy(paddr, &data, to_copy))

arch/cris/arch-v32/kernel/ptrace.c

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -147,7 +147,7 @@ long arch_ptrace(struct task_struct *child, long request,
147147
/* The trampoline page is globally mapped, no page table to traverse.*/
148148
tmp = *(unsigned long*)addr;
149149
} else {
150-
copied = access_process_vm(child, addr, &tmp, sizeof(tmp), 0);
150+
copied = access_process_vm(child, addr, &tmp, sizeof(tmp), FOLL_FORCE);
151151

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

281281
/* 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);
283283
if (copied != sizeof(opcode))
284284
return 0;
285285

arch/ia64/kernel/ptrace.c

Lines changed: 9 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -453,7 +453,7 @@ ia64_peek (struct task_struct *child, struct switch_stack *child_stack,
453453
return 0;
454454
}
455455
}
456-
copied = access_process_vm(child, addr, &ret, sizeof(ret), 0);
456+
copied = access_process_vm(child, addr, &ret, sizeof(ret), FOLL_FORCE);
457457
if (copied != sizeof(ret))
458458
return -EIO;
459459
*val = ret;
@@ -489,7 +489,8 @@ ia64_poke (struct task_struct *child, struct switch_stack *child_stack,
489489
*ia64_rse_skip_regs(krbs, regnum) = val;
490490
}
491491
}
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)
493494
!= sizeof(val))
494495
return -EIO;
495496
return 0;
@@ -543,7 +544,8 @@ ia64_sync_user_rbs (struct task_struct *child, struct switch_stack *sw,
543544
ret = ia64_peek(child, sw, user_rbs_end, addr, &val);
544545
if (ret < 0)
545546
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)
547549
!= sizeof(val))
548550
return -EIO;
549551
}
@@ -559,7 +561,8 @@ ia64_sync_kernel_rbs (struct task_struct *child, struct switch_stack *sw,
559561

560562
/* now copy word for word from user rbs to kernel rbs: */
561563
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)
563566
!= sizeof(val))
564567
return -EIO;
565568

@@ -1156,7 +1159,8 @@ arch_ptrace (struct task_struct *child, long request,
11561159
case PTRACE_PEEKTEXT:
11571160
case PTRACE_PEEKDATA:
11581161
/* 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)
11601164
!= sizeof(data))
11611165
return -EIO;
11621166
/* ensure return value is not mistaken for error code */

arch/m32r/kernel/ptrace.c

Lines changed: 10 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -493,7 +493,8 @@ unregister_all_debug_traps(struct task_struct *child)
493493
int i;
494494

495495
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);
497498
p->nr_trap = 0;
498499
}
499500

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

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)
541543
!= sizeof(next_insn)) {
542544
return -1; /* error */
543545
}
@@ -546,7 +548,8 @@ embed_debug_trap(struct task_struct *child, unsigned long next_pc)
546548
if (register_debug_trap(child, next_pc, next_insn, &code)) {
547549
return -1; /* error */
548550
}
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)
550553
!= sizeof(code)) {
551554
return -1; /* error */
552555
}
@@ -562,7 +565,8 @@ withdraw_debug_trap(struct pt_regs *regs)
562565
addr = (regs->bpc - 2) & ~3;
563566
regs->bpc -= 2;
564567
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);
566570
invalidate_cache();
567571
}
568572
}
@@ -589,7 +593,8 @@ void user_enable_single_step(struct task_struct *child)
589593
/* Compute next pc. */
590594
pc = get_stack_long(child, PT_BPC);
591595

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)
593598
!= sizeof(insn))
594599
return;
595600

arch/mips/kernel/ptrace32.c

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -70,7 +70,7 @@ long compat_arch_ptrace(struct task_struct *child, compat_long_t request,
7070
break;
7171

7272
copied = access_process_vm(child, (u64)addrOthers, &tmp,
73-
sizeof(tmp), 0);
73+
sizeof(tmp), FOLL_FORCE);
7474
if (copied != sizeof(tmp))
7575
break;
7676
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,
179179
break;
180180
ret = 0;
181181
if (access_process_vm(child, (u64)addrOthers, &data,
182-
sizeof(data), 1) == sizeof(data))
182+
sizeof(data),
183+
FOLL_FORCE | FOLL_WRITE) == sizeof(data))
183184
break;
184185
ret = -EIO;
185186
break;

arch/powerpc/kernel/ptrace32.c

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -74,7 +74,7 @@ long compat_arch_ptrace(struct task_struct *child, compat_long_t request,
7474
break;
7575

7676
copied = access_process_vm(child, (u64)addrOthers, &tmp,
77-
sizeof(tmp), 0);
77+
sizeof(tmp), FOLL_FORCE);
7878
if (copied != sizeof(tmp))
7979
break;
8080
ret = put_user(tmp, (u32 __user *)data);
@@ -179,7 +179,8 @@ long compat_arch_ptrace(struct task_struct *child, compat_long_t request,
179179
break;
180180
ret = 0;
181181
if (access_process_vm(child, (u64)addrOthers, &tmp,
182-
sizeof(tmp), 1) == sizeof(tmp))
182+
sizeof(tmp),
183+
FOLL_FORCE | FOLL_WRITE) == sizeof(tmp))
183184
break;
184185
ret = -EIO;
185186
break;

arch/score/kernel/ptrace.c

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -131,7 +131,7 @@ read_tsk_long(struct task_struct *child,
131131
{
132132
int copied;
133133

134-
copied = access_process_vm(child, addr, res, sizeof(*res), 0);
134+
copied = access_process_vm(child, addr, res, sizeof(*res), FOLL_FORCE);
135135

136136
return copied != sizeof(*res) ? -EIO : 0;
137137
}
@@ -142,7 +142,7 @@ read_tsk_short(struct task_struct *child,
142142
{
143143
int copied;
144144

145-
copied = access_process_vm(child, addr, res, sizeof(*res), 0);
145+
copied = access_process_vm(child, addr, res, sizeof(*res), FOLL_FORCE);
146146

147147
return copied != sizeof(*res) ? -EIO : 0;
148148
}
@@ -153,7 +153,8 @@ write_tsk_short(struct task_struct *child,
153153
{
154154
int copied;
155155

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);
157158

158159
return copied != sizeof(val) ? -EIO : 0;
159160
}
@@ -164,7 +165,8 @@ write_tsk_long(struct task_struct *child,
164165
{
165166
int copied;
166167

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);
168170

169171
return copied != sizeof(val) ? -EIO : 0;
170172
}

arch/sparc/kernel/ptrace_64.c

Lines changed: 16 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -127,7 +127,8 @@ static int get_from_target(struct task_struct *target, unsigned long uaddr,
127127
if (copy_from_user(kbuf, (void __user *) uaddr, len))
128128
return -EFAULT;
129129
} 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);
131132
if (len2 != len)
132133
return -EFAULT;
133134
}
@@ -141,7 +142,8 @@ static int set_to_target(struct task_struct *target, unsigned long uaddr,
141142
if (copy_to_user((void __user *) uaddr, kbuf, len))
142143
return -EFAULT;
143144
} 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);
145147
if (len2 != len)
146148
return -EFAULT;
147149
}
@@ -505,7 +507,8 @@ static int genregs32_get(struct task_struct *target,
505507
if (access_process_vm(target,
506508
(unsigned long)
507509
&reg_window[pos],
508-
k, sizeof(*k), 0)
510+
k, sizeof(*k),
511+
FOLL_FORCE)
509512
!= sizeof(*k))
510513
return -EFAULT;
511514
k++;
@@ -531,12 +534,14 @@ static int genregs32_get(struct task_struct *target,
531534
if (access_process_vm(target,
532535
(unsigned long)
533536
&reg_window[pos],
534-
&reg, sizeof(reg), 0)
537+
&reg, sizeof(reg),
538+
FOLL_FORCE)
535539
!= sizeof(reg))
536540
return -EFAULT;
537541
if (access_process_vm(target,
538542
(unsigned long) u,
539-
&reg, sizeof(reg), 1)
543+
&reg, sizeof(reg),
544+
FOLL_FORCE | FOLL_WRITE)
540545
!= sizeof(reg))
541546
return -EFAULT;
542547
pos++;
@@ -615,7 +620,8 @@ static int genregs32_set(struct task_struct *target,
615620
(unsigned long)
616621
&reg_window[pos],
617622
(void *) k,
618-
sizeof(*k), 1)
623+
sizeof(*k),
624+
FOLL_FORCE | FOLL_WRITE)
619625
!= sizeof(*k))
620626
return -EFAULT;
621627
k++;
@@ -642,13 +648,15 @@ static int genregs32_set(struct task_struct *target,
642648
if (access_process_vm(target,
643649
(unsigned long)
644650
u,
645-
&reg, sizeof(reg), 0)
651+
&reg, sizeof(reg),
652+
FOLL_FORCE)
646653
!= sizeof(reg))
647654
return -EFAULT;
648655
if (access_process_vm(target,
649656
(unsigned long)
650657
&reg_window[pos],
651-
&reg, sizeof(reg), 1)
658+
&reg, sizeof(reg),
659+
FOLL_FORCE | FOLL_WRITE)
652660
!= sizeof(reg))
653661
return -EFAULT;
654662
pos++;

arch/x86/kernel/step.c

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -57,7 +57,8 @@ static int is_setting_trap_flag(struct task_struct *child, struct pt_regs *regs)
5757
unsigned char opcode[15];
5858
unsigned long addr = convert_ip_to_linear(child, regs);
5959

60-
copied = access_process_vm(child, addr, opcode, sizeof(opcode), 0);
60+
copied = access_process_vm(child, addr, opcode, sizeof(opcode),
61+
FOLL_FORCE);
6162
for (i = 0; i < copied; i++) {
6263
switch (opcode[i]) {
6364
/* popf and iret */

0 commit comments

Comments
 (0)