diff options
author | David Howells <dhowells@redhat.com> | 2006-09-27 04:50:15 -0400 |
---|---|---|
committer | Linus Torvalds <torvalds@g5.osdl.org> | 2006-09-27 11:26:14 -0400 |
commit | 0ec76a110f432e98277e464b82ace8dd66571689 (patch) | |
tree | 3ed8de0ea6869fe17bec7689c493a2db02f73f4a /mm/nommu.c | |
parent | 361f6ed1d00f666a1a7c33f3e9aaccb713f9b9e4 (diff) |
[PATCH] NOMMU: Check that access_process_vm() has a valid target
Check that access_process_vm() is accessing a valid mapping in the target
process.
This limits ptrace() accesses and accesses through /proc/<pid>/maps to only
those regions actually mapped by a program.
Signed-off-by: David Howells <dhowells@redhat.com>
Signed-off-by: Andrew Morton <akpm@osdl.org>
Signed-off-by: Linus Torvalds <torvalds@osdl.org>
Diffstat (limited to 'mm/nommu.c')
-rw-r--r-- | mm/nommu.c | 47 |
1 files changed, 47 insertions, 0 deletions
diff --git a/mm/nommu.c b/mm/nommu.c index d99dea31e443..d08acdae0036 100644 --- a/mm/nommu.c +++ b/mm/nommu.c | |||
@@ -1206,3 +1206,50 @@ struct page *filemap_nopage(struct vm_area_struct *area, | |||
1206 | BUG(); | 1206 | BUG(); |
1207 | return NULL; | 1207 | return NULL; |
1208 | } | 1208 | } |
1209 | |||
1210 | /* | ||
1211 | * Access another process' address space. | ||
1212 | * - source/target buffer must be kernel space | ||
1213 | */ | ||
1214 | int access_process_vm(struct task_struct *tsk, unsigned long addr, void *buf, int len, int write) | ||
1215 | { | ||
1216 | struct vm_list_struct *vml; | ||
1217 | struct vm_area_struct *vma; | ||
1218 | struct mm_struct *mm; | ||
1219 | |||
1220 | if (addr + len < addr) | ||
1221 | return 0; | ||
1222 | |||
1223 | mm = get_task_mm(tsk); | ||
1224 | if (!mm) | ||
1225 | return 0; | ||
1226 | |||
1227 | down_read(&mm->mmap_sem); | ||
1228 | |||
1229 | /* the access must start within one of the target process's mappings */ | ||
1230 | for (vml = mm->context.vmlist; vml; vml = vml->next) | ||
1231 | if (addr >= vml->vma->vm_start && addr < vml->vma->vm_end) | ||
1232 | break; | ||
1233 | |||
1234 | if (vml) { | ||
1235 | vma = vml->vma; | ||
1236 | |||
1237 | /* don't overrun this mapping */ | ||
1238 | if (addr + len >= vma->vm_end) | ||
1239 | len = vma->vm_end - addr; | ||
1240 | |||
1241 | /* only read or write mappings where it is permitted */ | ||
1242 | if (write && vma->vm_flags & VM_WRITE) | ||
1243 | len -= copy_to_user((void *) addr, buf, len); | ||
1244 | else if (!write && vma->vm_flags & VM_READ) | ||
1245 | len -= copy_from_user(buf, (void *) addr, len); | ||
1246 | else | ||
1247 | len = 0; | ||
1248 | } else { | ||
1249 | len = 0; | ||
1250 | } | ||
1251 | |||
1252 | up_read(&mm->mmap_sem); | ||
1253 | mmput(mm); | ||
1254 | return len; | ||
1255 | } | ||