Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

Fix pagemap_read() use of struct mm_walk

Fix some issues in pagemap_read noted by Alexey:

- initialize pagemap_walk.mm to "mm" , so the code starts working as
advertised

- initialize ->private to "&pm" so it wouldn't immediately oops in
pagemap_pte_hole()

- unstatic struct pagemap_walk, so two threads won't fsckup each other
(including those started by root, including flipping ->mm when you don't
have permissions)

- pagemap_read() contains two calls to ptrace_may_attach(), second one
looks unneeded.

- avoid possible kmalloc(0) and integer wraparound.

Cc: Alexey Dobriyan <adobriyan@gmail.com>
Cc: Matt Mackall <mpm@selenic.com>
Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
[ Personally, I'd just remove the functionality entirely - Linus ]
Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>

authored by

Andrew Morton and committed by
Linus Torvalds
5d7e0d2b ca31e146

+36 -32
+36 -32
fs/proc/task_mmu.c
··· 602 602 return err; 603 603 } 604 604 605 - static struct mm_walk pagemap_walk = { 606 - .pmd_entry = pagemap_pte_range, 607 - .pte_hole = pagemap_pte_hole 608 - }; 609 - 610 605 /* 611 606 * /proc/pid/pagemap - an array mapping virtual pages to pfns 612 607 * ··· 636 641 struct pagemapread pm; 637 642 int pagecount; 638 643 int ret = -ESRCH; 644 + struct mm_walk pagemap_walk; 645 + unsigned long src; 646 + unsigned long svpfn; 647 + unsigned long start_vaddr; 648 + unsigned long end_vaddr; 639 649 640 650 if (!task) 641 651 goto out; ··· 659 659 if (!mm) 660 660 goto out_task; 661 661 662 - ret = -ENOMEM; 662 + 663 663 uaddr = (unsigned long)buf & PAGE_MASK; 664 664 uend = (unsigned long)(buf + count); 665 665 pagecount = (PAGE_ALIGN(uend) - uaddr) / PAGE_SIZE; 666 - pages = kmalloc(pagecount * sizeof(struct page *), GFP_KERNEL); 666 + ret = 0; 667 + if (pagecount == 0) 668 + goto out_mm; 669 + pages = kcalloc(pagecount, sizeof(struct page *), GFP_KERNEL); 670 + ret = -ENOMEM; 667 671 if (!pages) 668 672 goto out_mm; 669 673 ··· 688 684 pm.out = (u64 *)buf; 689 685 pm.end = (u64 *)(buf + count); 690 686 691 - if (!ptrace_may_attach(task)) { 692 - ret = -EIO; 693 - } else { 694 - unsigned long src = *ppos; 695 - unsigned long svpfn = src / PM_ENTRY_BYTES; 696 - unsigned long start_vaddr = svpfn << PAGE_SHIFT; 697 - unsigned long end_vaddr = TASK_SIZE_OF(task); 687 + pagemap_walk.pmd_entry = pagemap_pte_range; 688 + pagemap_walk.pte_hole = pagemap_pte_hole; 689 + pagemap_walk.mm = mm; 690 + pagemap_walk.private = &pm; 698 691 699 - /* watch out for wraparound */ 700 - if (svpfn > TASK_SIZE_OF(task) >> PAGE_SHIFT) 701 - start_vaddr = end_vaddr; 692 + src = *ppos; 693 + svpfn = src / PM_ENTRY_BYTES; 694 + start_vaddr = svpfn << PAGE_SHIFT; 695 + end_vaddr = TASK_SIZE_OF(task); 702 696 703 - /* 704 - * The odds are that this will stop walking way 705 - * before end_vaddr, because the length of the 706 - * user buffer is tracked in "pm", and the walk 707 - * will stop when we hit the end of the buffer. 708 - */ 709 - ret = walk_page_range(start_vaddr, end_vaddr, 710 - &pagemap_walk); 711 - if (ret == PM_END_OF_BUFFER) 712 - ret = 0; 713 - /* don't need mmap_sem for these, but this looks cleaner */ 714 - *ppos += (char *)pm.out - buf; 715 - if (!ret) 716 - ret = (char *)pm.out - buf; 717 - } 697 + /* watch out for wraparound */ 698 + if (svpfn > TASK_SIZE_OF(task) >> PAGE_SHIFT) 699 + start_vaddr = end_vaddr; 700 + 701 + /* 702 + * The odds are that this will stop walking way 703 + * before end_vaddr, because the length of the 704 + * user buffer is tracked in "pm", and the walk 705 + * will stop when we hit the end of the buffer. 706 + */ 707 + ret = walk_page_range(start_vaddr, end_vaddr, &pagemap_walk); 708 + if (ret == PM_END_OF_BUFFER) 709 + ret = 0; 710 + /* don't need mmap_sem for these, but this looks cleaner */ 711 + *ppos += (char *)pm.out - buf; 712 + if (!ret) 713 + ret = (char *)pm.out - buf; 718 714 719 715 out_pages: 720 716 for (; pagecount; pagecount--) {