diff options
author | Jiri Olsa <jolsa@kernel.org> | 2016-09-08 03:57:07 -0400 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2016-09-20 16:32:49 -0400 |
commit | f5beeb1851ea6f8cfcf2657f26cb24c0582b4945 (patch) | |
tree | f619d5d6686ec8e43fe5f234c52f551f1febacad /fs/proc/kcore.c | |
parent | d2ffb0103aaefa9b169da042cf39ce27bfb6cdbb (diff) |
fs/proc/kcore.c: Make bounce buffer global for read
Next patch adds bounce buffer for ktext area, so it's
convenient to have single bounce buffer for both
vmalloc/module and ktext cases.
Suggested-by: Linus Torvalds <torvalds@linux-foundation.org>
Signed-off-by: Jiri Olsa <jolsa@kernel.org>
Acked-by: Kees Cook <keescook@chromium.org>
Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
Diffstat (limited to 'fs/proc/kcore.c')
-rw-r--r-- | fs/proc/kcore.c | 24 |
1 files changed, 14 insertions, 10 deletions
diff --git a/fs/proc/kcore.c b/fs/proc/kcore.c index a939f5ed7f89..bd3ac9dca252 100644 --- a/fs/proc/kcore.c +++ b/fs/proc/kcore.c | |||
@@ -430,6 +430,7 @@ static void elf_kcore_store_hdr(char *bufp, int nphdr, int dataoff) | |||
430 | static ssize_t | 430 | static ssize_t |
431 | read_kcore(struct file *file, char __user *buffer, size_t buflen, loff_t *fpos) | 431 | read_kcore(struct file *file, char __user *buffer, size_t buflen, loff_t *fpos) |
432 | { | 432 | { |
433 | char *buf = file->private_data; | ||
433 | ssize_t acc = 0; | 434 | ssize_t acc = 0; |
434 | size_t size, tsz; | 435 | size_t size, tsz; |
435 | size_t elf_buflen; | 436 | size_t elf_buflen; |
@@ -500,18 +501,10 @@ read_kcore(struct file *file, char __user *buffer, size_t buflen, loff_t *fpos) | |||
500 | if (clear_user(buffer, tsz)) | 501 | if (clear_user(buffer, tsz)) |
501 | return -EFAULT; | 502 | return -EFAULT; |
502 | } else if (is_vmalloc_or_module_addr((void *)start)) { | 503 | } else if (is_vmalloc_or_module_addr((void *)start)) { |
503 | char * elf_buf; | 504 | vread(buf, (char *)start, tsz); |
504 | |||
505 | elf_buf = kzalloc(tsz, GFP_KERNEL); | ||
506 | if (!elf_buf) | ||
507 | return -ENOMEM; | ||
508 | vread(elf_buf, (char *)start, tsz); | ||
509 | /* we have to zero-fill user buffer even if no read */ | 505 | /* we have to zero-fill user buffer even if no read */ |
510 | if (copy_to_user(buffer, elf_buf, tsz)) { | 506 | if (copy_to_user(buffer, buf, tsz)) |
511 | kfree(elf_buf); | ||
512 | return -EFAULT; | 507 | return -EFAULT; |
513 | } | ||
514 | kfree(elf_buf); | ||
515 | } else { | 508 | } else { |
516 | if (kern_addr_valid(start)) { | 509 | if (kern_addr_valid(start)) { |
517 | unsigned long n; | 510 | unsigned long n; |
@@ -549,6 +542,11 @@ static int open_kcore(struct inode *inode, struct file *filp) | |||
549 | { | 542 | { |
550 | if (!capable(CAP_SYS_RAWIO)) | 543 | if (!capable(CAP_SYS_RAWIO)) |
551 | return -EPERM; | 544 | return -EPERM; |
545 | |||
546 | filp->private_data = kmalloc(PAGE_SIZE, GFP_KERNEL); | ||
547 | if (!filp->private_data) | ||
548 | return -ENOMEM; | ||
549 | |||
552 | if (kcore_need_update) | 550 | if (kcore_need_update) |
553 | kcore_update_ram(); | 551 | kcore_update_ram(); |
554 | if (i_size_read(inode) != proc_root_kcore->size) { | 552 | if (i_size_read(inode) != proc_root_kcore->size) { |
@@ -559,10 +557,16 @@ static int open_kcore(struct inode *inode, struct file *filp) | |||
559 | return 0; | 557 | return 0; |
560 | } | 558 | } |
561 | 559 | ||
560 | static int release_kcore(struct inode *inode, struct file *file) | ||
561 | { | ||
562 | kfree(file->private_data); | ||
563 | return 0; | ||
564 | } | ||
562 | 565 | ||
563 | static const struct file_operations proc_kcore_operations = { | 566 | static const struct file_operations proc_kcore_operations = { |
564 | .read = read_kcore, | 567 | .read = read_kcore, |
565 | .open = open_kcore, | 568 | .open = open_kcore, |
569 | .release = release_kcore, | ||
566 | .llseek = default_llseek, | 570 | .llseek = default_llseek, |
567 | }; | 571 | }; |
568 | 572 | ||