aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--arch/alpha/kernel/ptrace.c2
-rw-r--r--arch/blackfin/kernel/ptrace.c4
-rw-r--r--arch/cris/arch-v32/kernel/ptrace.c2
-rw-r--r--arch/ia64/kernel/ptrace.c2
-rw-r--r--arch/mips/kernel/ptrace32.c4
-rw-r--r--arch/powerpc/kernel/ptrace32.c4
-rw-r--r--include/linux/mm.h2
-rw-r--r--include/linux/ptrace.h3
-rw-r--r--kernel/ptrace.c42
-rw-r--r--mm/memory.c2
-rw-r--r--mm/nommu.c2
11 files changed, 52 insertions, 17 deletions
diff --git a/arch/alpha/kernel/ptrace.c b/arch/alpha/kernel/ptrace.c
index 940dfb406591..04abdec7f496 100644
--- a/arch/alpha/kernel/ptrace.c
+++ b/arch/alpha/kernel/ptrace.c
@@ -283,7 +283,7 @@ long arch_ptrace(struct task_struct *child, long request,
283 /* 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. */
284 case PTRACE_PEEKTEXT: /* read word at location addr. */ 284 case PTRACE_PEEKTEXT: /* read word at location addr. */
285 case PTRACE_PEEKDATA: 285 case PTRACE_PEEKDATA:
286 copied = access_process_vm(child, addr, &tmp, sizeof(tmp), 286 copied = ptrace_access_vm(child, addr, &tmp, sizeof(tmp),
287 FOLL_FORCE); 287 FOLL_FORCE);
288 ret = -EIO; 288 ret = -EIO;
289 if (copied != sizeof(tmp)) 289 if (copied != sizeof(tmp))
diff --git a/arch/blackfin/kernel/ptrace.c b/arch/blackfin/kernel/ptrace.c
index 8d79286ee4e8..360d99645163 100644
--- a/arch/blackfin/kernel/ptrace.c
+++ b/arch/blackfin/kernel/ptrace.c
@@ -270,7 +270,7 @@ long arch_ptrace(struct task_struct *child, long request,
270 switch (bfin_mem_access_type(addr, to_copy)) { 270 switch (bfin_mem_access_type(addr, to_copy)) {
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 = ptrace_access_vm(child, addr, &tmp,
274 to_copy, FOLL_FORCE); 274 to_copy, FOLL_FORCE);
275 if (copied) 275 if (copied)
276 break; 276 break;
@@ -323,7 +323,7 @@ long arch_ptrace(struct task_struct *child, long request,
323 switch (bfin_mem_access_type(addr, to_copy)) { 323 switch (bfin_mem_access_type(addr, to_copy)) {
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 = ptrace_access_vm(child, addr, &data,
327 to_copy, 327 to_copy,
328 FOLL_FORCE | FOLL_WRITE); 328 FOLL_FORCE | FOLL_WRITE);
329 break; 329 break;
diff --git a/arch/cris/arch-v32/kernel/ptrace.c b/arch/cris/arch-v32/kernel/ptrace.c
index f0df654ac6fc..fe1f9cf7b391 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), FOLL_FORCE); 150 copied = ptrace_access_vm(child, addr, &tmp, sizeof(tmp), FOLL_FORCE);
151 151
152 if (copied != sizeof(tmp)) 152 if (copied != sizeof(tmp))
153 break; 153 break;
diff --git a/arch/ia64/kernel/ptrace.c b/arch/ia64/kernel/ptrace.c
index 31aa8c0f68e1..36f660da8124 100644
--- a/arch/ia64/kernel/ptrace.c
+++ b/arch/ia64/kernel/ptrace.c
@@ -1159,7 +1159,7 @@ arch_ptrace (struct task_struct *child, long request,
1159 case PTRACE_PEEKTEXT: 1159 case PTRACE_PEEKTEXT:
1160 case PTRACE_PEEKDATA: 1160 case PTRACE_PEEKDATA:
1161 /* read word at location addr */ 1161 /* read word at location addr */
1162 if (access_process_vm(child, addr, &data, sizeof(data), 1162 if (ptrace_access_vm(child, addr, &data, sizeof(data),
1163 FOLL_FORCE) 1163 FOLL_FORCE)
1164 != sizeof(data)) 1164 != sizeof(data))
1165 return -EIO; 1165 return -EIO;
diff --git a/arch/mips/kernel/ptrace32.c b/arch/mips/kernel/ptrace32.c
index 7e71a4e0281b..5fcbdcd7abd0 100644
--- a/arch/mips/kernel/ptrace32.c
+++ b/arch/mips/kernel/ptrace32.c
@@ -69,7 +69,7 @@ long compat_arch_ptrace(struct task_struct *child, compat_long_t request,
69 if (get_user(addrOthers, (u32 __user * __user *) (unsigned long) addr) != 0) 69 if (get_user(addrOthers, (u32 __user * __user *) (unsigned long) addr) != 0)
70 break; 70 break;
71 71
72 copied = access_process_vm(child, (u64)addrOthers, &tmp, 72 copied = ptrace_access_vm(child, (u64)addrOthers, &tmp,
73 sizeof(tmp), FOLL_FORCE); 73 sizeof(tmp), FOLL_FORCE);
74 if (copied != sizeof(tmp)) 74 if (copied != sizeof(tmp))
75 break; 75 break;
@@ -178,7 +178,7 @@ long compat_arch_ptrace(struct task_struct *child, compat_long_t request,
178 if (get_user(addrOthers, (u32 __user * __user *) (unsigned long) addr) != 0) 178 if (get_user(addrOthers, (u32 __user * __user *) (unsigned long) addr) != 0)
179 break; 179 break;
180 ret = 0; 180 ret = 0;
181 if (access_process_vm(child, (u64)addrOthers, &data, 181 if (ptrace_access_vm(child, (u64)addrOthers, &data,
182 sizeof(data), 182 sizeof(data),
183 FOLL_FORCE | FOLL_WRITE) == sizeof(data)) 183 FOLL_FORCE | FOLL_WRITE) == sizeof(data))
184 break; 184 break;
diff --git a/arch/powerpc/kernel/ptrace32.c b/arch/powerpc/kernel/ptrace32.c
index 010b7b310237..1e887f3a61a6 100644
--- a/arch/powerpc/kernel/ptrace32.c
+++ b/arch/powerpc/kernel/ptrace32.c
@@ -73,7 +73,7 @@ long compat_arch_ptrace(struct task_struct *child, compat_long_t request,
73 if (get_user(addrOthers, (u32 __user * __user *)addr) != 0) 73 if (get_user(addrOthers, (u32 __user * __user *)addr) != 0)
74 break; 74 break;
75 75
76 copied = access_process_vm(child, (u64)addrOthers, &tmp, 76 copied = ptrace_access_vm(child, (u64)addrOthers, &tmp,
77 sizeof(tmp), FOLL_FORCE); 77 sizeof(tmp), FOLL_FORCE);
78 if (copied != sizeof(tmp)) 78 if (copied != sizeof(tmp))
79 break; 79 break;
@@ -178,7 +178,7 @@ long compat_arch_ptrace(struct task_struct *child, compat_long_t request,
178 if (get_user(addrOthers, (u32 __user * __user *)addr) != 0) 178 if (get_user(addrOthers, (u32 __user * __user *)addr) != 0)
179 break; 179 break;
180 ret = 0; 180 ret = 0;
181 if (access_process_vm(child, (u64)addrOthers, &tmp, 181 if (ptrace_access_vm(child, (u64)addrOthers, &tmp,
182 sizeof(tmp), 182 sizeof(tmp),
183 FOLL_FORCE | FOLL_WRITE) == sizeof(tmp)) 183 FOLL_FORCE | FOLL_WRITE) == sizeof(tmp))
184 break; 184 break;
diff --git a/include/linux/mm.h b/include/linux/mm.h
index a92c8d73aeaf..0b5b2e4df14e 100644
--- a/include/linux/mm.h
+++ b/include/linux/mm.h
@@ -1270,6 +1270,8 @@ extern int access_process_vm(struct task_struct *tsk, unsigned long addr, void *
1270 unsigned int gup_flags); 1270 unsigned int gup_flags);
1271extern int access_remote_vm(struct mm_struct *mm, unsigned long addr, 1271extern int access_remote_vm(struct mm_struct *mm, unsigned long addr,
1272 void *buf, int len, unsigned int gup_flags); 1272 void *buf, int len, unsigned int gup_flags);
1273extern int __access_remote_vm(struct task_struct *tsk, struct mm_struct *mm,
1274 unsigned long addr, void *buf, int len, unsigned int gup_flags);
1273 1275
1274long get_user_pages_remote(struct task_struct *tsk, struct mm_struct *mm, 1276long get_user_pages_remote(struct task_struct *tsk, struct mm_struct *mm,
1275 unsigned long start, unsigned long nr_pages, 1277 unsigned long start, unsigned long nr_pages,
diff --git a/include/linux/ptrace.h b/include/linux/ptrace.h
index e13bfdf7f314..e0e539321ab9 100644
--- a/include/linux/ptrace.h
+++ b/include/linux/ptrace.h
@@ -8,6 +8,9 @@
8#include <linux/pid_namespace.h> /* For task_active_pid_ns. */ 8#include <linux/pid_namespace.h> /* For task_active_pid_ns. */
9#include <uapi/linux/ptrace.h> 9#include <uapi/linux/ptrace.h>
10 10
11extern int ptrace_access_vm(struct task_struct *tsk, unsigned long addr,
12 void *buf, int len, unsigned int gup_flags);
13
11/* 14/*
12 * Ptrace flags 15 * Ptrace flags
13 * 16 *
diff --git a/kernel/ptrace.c b/kernel/ptrace.c
index e82c15cadd6d..49ba7c1ade9d 100644
--- a/kernel/ptrace.c
+++ b/kernel/ptrace.c
@@ -27,6 +27,35 @@
27#include <linux/cn_proc.h> 27#include <linux/cn_proc.h>
28#include <linux/compat.h> 28#include <linux/compat.h>
29 29
30/*
31 * Access another process' address space via ptrace.
32 * Source/target buffer must be kernel space,
33 * Do not walk the page table directly, use get_user_pages
34 */
35int ptrace_access_vm(struct task_struct *tsk, unsigned long addr,
36 void *buf, int len, unsigned int gup_flags)
37{
38 struct mm_struct *mm;
39 int ret;
40
41 mm = get_task_mm(tsk);
42 if (!mm)
43 return 0;
44
45 if (!tsk->ptrace ||
46 (current != tsk->parent) ||
47 ((get_dumpable(mm) != SUID_DUMP_USER) &&
48 !ptracer_capable(tsk, mm->user_ns))) {
49 mmput(mm);
50 return 0;
51 }
52
53 ret = __access_remote_vm(tsk, mm, addr, buf, len, gup_flags);
54 mmput(mm);
55
56 return ret;
57}
58
30 59
31/* 60/*
32 * ptrace a task: make the debugger its new parent and 61 * ptrace a task: make the debugger its new parent and
@@ -535,7 +564,8 @@ int ptrace_readdata(struct task_struct *tsk, unsigned long src, char __user *dst
535 int this_len, retval; 564 int this_len, retval;
536 565
537 this_len = (len > sizeof(buf)) ? sizeof(buf) : len; 566 this_len = (len > sizeof(buf)) ? sizeof(buf) : len;
538 retval = access_process_vm(tsk, src, buf, this_len, FOLL_FORCE); 567 retval = ptrace_access_vm(tsk, src, buf, this_len, FOLL_FORCE);
568
539 if (!retval) { 569 if (!retval) {
540 if (copied) 570 if (copied)
541 break; 571 break;
@@ -562,7 +592,7 @@ int ptrace_writedata(struct task_struct *tsk, char __user *src, unsigned long ds
562 this_len = (len > sizeof(buf)) ? sizeof(buf) : len; 592 this_len = (len > sizeof(buf)) ? sizeof(buf) : len;
563 if (copy_from_user(buf, src, this_len)) 593 if (copy_from_user(buf, src, this_len))
564 return -EFAULT; 594 return -EFAULT;
565 retval = access_process_vm(tsk, dst, buf, this_len, 595 retval = ptrace_access_vm(tsk, dst, buf, this_len,
566 FOLL_FORCE | FOLL_WRITE); 596 FOLL_FORCE | FOLL_WRITE);
567 if (!retval) { 597 if (!retval) {
568 if (copied) 598 if (copied)
@@ -1126,7 +1156,7 @@ int generic_ptrace_peekdata(struct task_struct *tsk, unsigned long addr,
1126 unsigned long tmp; 1156 unsigned long tmp;
1127 int copied; 1157 int copied;
1128 1158
1129 copied = access_process_vm(tsk, addr, &tmp, sizeof(tmp), FOLL_FORCE); 1159 copied = ptrace_access_vm(tsk, addr, &tmp, sizeof(tmp), FOLL_FORCE);
1130 if (copied != sizeof(tmp)) 1160 if (copied != sizeof(tmp))
1131 return -EIO; 1161 return -EIO;
1132 return put_user(tmp, (unsigned long __user *)data); 1162 return put_user(tmp, (unsigned long __user *)data);
@@ -1137,7 +1167,7 @@ int generic_ptrace_pokedata(struct task_struct *tsk, unsigned long addr,
1137{ 1167{
1138 int copied; 1168 int copied;
1139 1169
1140 copied = access_process_vm(tsk, addr, &data, sizeof(data), 1170 copied = ptrace_access_vm(tsk, addr, &data, sizeof(data),
1141 FOLL_FORCE | FOLL_WRITE); 1171 FOLL_FORCE | FOLL_WRITE);
1142 return (copied == sizeof(data)) ? 0 : -EIO; 1172 return (copied == sizeof(data)) ? 0 : -EIO;
1143} 1173}
@@ -1155,7 +1185,7 @@ int compat_ptrace_request(struct task_struct *child, compat_long_t request,
1155 switch (request) { 1185 switch (request) {
1156 case PTRACE_PEEKTEXT: 1186 case PTRACE_PEEKTEXT:
1157 case PTRACE_PEEKDATA: 1187 case PTRACE_PEEKDATA:
1158 ret = access_process_vm(child, addr, &word, sizeof(word), 1188 ret = ptrace_access_vm(child, addr, &word, sizeof(word),
1159 FOLL_FORCE); 1189 FOLL_FORCE);
1160 if (ret != sizeof(word)) 1190 if (ret != sizeof(word))
1161 ret = -EIO; 1191 ret = -EIO;
@@ -1165,7 +1195,7 @@ int compat_ptrace_request(struct task_struct *child, compat_long_t request,
1165 1195
1166 case PTRACE_POKETEXT: 1196 case PTRACE_POKETEXT:
1167 case PTRACE_POKEDATA: 1197 case PTRACE_POKEDATA:
1168 ret = access_process_vm(child, addr, &data, sizeof(data), 1198 ret = ptrace_access_vm(child, addr, &data, sizeof(data),
1169 FOLL_FORCE | FOLL_WRITE); 1199 FOLL_FORCE | FOLL_WRITE);
1170 ret = (ret != sizeof(data) ? -EIO : 0); 1200 ret = (ret != sizeof(data) ? -EIO : 0);
1171 break; 1201 break;
diff --git a/mm/memory.c b/mm/memory.c
index e18c57bdc75c..cbb1e5e5f791 100644
--- a/mm/memory.c
+++ b/mm/memory.c
@@ -3868,7 +3868,7 @@ EXPORT_SYMBOL_GPL(generic_access_phys);
3868 * Access another process' address space as given in mm. If non-NULL, use the 3868 * Access another process' address space as given in mm. If non-NULL, use the
3869 * given task for page fault accounting. 3869 * given task for page fault accounting.
3870 */ 3870 */
3871static int __access_remote_vm(struct task_struct *tsk, struct mm_struct *mm, 3871int __access_remote_vm(struct task_struct *tsk, struct mm_struct *mm,
3872 unsigned long addr, void *buf, int len, unsigned int gup_flags) 3872 unsigned long addr, void *buf, int len, unsigned int gup_flags)
3873{ 3873{
3874 struct vm_area_struct *vma; 3874 struct vm_area_struct *vma;
diff --git a/mm/nommu.c b/mm/nommu.c
index 8b8faaf2a9e9..44265e00b701 100644
--- a/mm/nommu.c
+++ b/mm/nommu.c
@@ -1808,7 +1808,7 @@ void filemap_map_pages(struct fault_env *fe,
1808} 1808}
1809EXPORT_SYMBOL(filemap_map_pages); 1809EXPORT_SYMBOL(filemap_map_pages);
1810 1810
1811static int __access_remote_vm(struct task_struct *tsk, struct mm_struct *mm, 1811int __access_remote_vm(struct task_struct *tsk, struct mm_struct *mm,
1812 unsigned long addr, void *buf, int len, unsigned int gup_flags) 1812 unsigned long addr, void *buf, int len, unsigned int gup_flags)
1813{ 1813{
1814 struct vm_area_struct *vma; 1814 struct vm_area_struct *vma;