diff options
Diffstat (limited to 'mm/memory.c')
-rw-r--r-- | mm/memory.c | 106 |
1 files changed, 77 insertions, 29 deletions
diff --git a/mm/memory.c b/mm/memory.c index e48945ab362b..ce22a250926f 100644 --- a/mm/memory.c +++ b/mm/memory.c | |||
@@ -1410,6 +1410,13 @@ no_page_table: | |||
1410 | return page; | 1410 | return page; |
1411 | } | 1411 | } |
1412 | 1412 | ||
1413 | static inline int stack_guard_page(struct vm_area_struct *vma, unsigned long addr) | ||
1414 | { | ||
1415 | return (vma->vm_flags & VM_GROWSDOWN) && | ||
1416 | (vma->vm_start == addr) && | ||
1417 | !vma_stack_continue(vma->vm_prev, addr); | ||
1418 | } | ||
1419 | |||
1413 | /** | 1420 | /** |
1414 | * __get_user_pages() - pin user pages in memory | 1421 | * __get_user_pages() - pin user pages in memory |
1415 | * @tsk: task_struct of target task | 1422 | * @tsk: task_struct of target task |
@@ -1486,9 +1493,8 @@ int __get_user_pages(struct task_struct *tsk, struct mm_struct *mm, | |||
1486 | struct vm_area_struct *vma; | 1493 | struct vm_area_struct *vma; |
1487 | 1494 | ||
1488 | vma = find_extend_vma(mm, start); | 1495 | vma = find_extend_vma(mm, start); |
1489 | if (!vma && in_gate_area(tsk, start)) { | 1496 | if (!vma && in_gate_area(mm, start)) { |
1490 | unsigned long pg = start & PAGE_MASK; | 1497 | unsigned long pg = start & PAGE_MASK; |
1491 | struct vm_area_struct *gate_vma = get_gate_vma(tsk); | ||
1492 | pgd_t *pgd; | 1498 | pgd_t *pgd; |
1493 | pud_t *pud; | 1499 | pud_t *pud; |
1494 | pmd_t *pmd; | 1500 | pmd_t *pmd; |
@@ -1513,10 +1519,11 @@ int __get_user_pages(struct task_struct *tsk, struct mm_struct *mm, | |||
1513 | pte_unmap(pte); | 1519 | pte_unmap(pte); |
1514 | return i ? : -EFAULT; | 1520 | return i ? : -EFAULT; |
1515 | } | 1521 | } |
1522 | vma = get_gate_vma(mm); | ||
1516 | if (pages) { | 1523 | if (pages) { |
1517 | struct page *page; | 1524 | struct page *page; |
1518 | 1525 | ||
1519 | page = vm_normal_page(gate_vma, start, *pte); | 1526 | page = vm_normal_page(vma, start, *pte); |
1520 | if (!page) { | 1527 | if (!page) { |
1521 | if (!(gup_flags & FOLL_DUMP) && | 1528 | if (!(gup_flags & FOLL_DUMP) && |
1522 | is_zero_pfn(pte_pfn(*pte))) | 1529 | is_zero_pfn(pte_pfn(*pte))) |
@@ -1530,12 +1537,7 @@ int __get_user_pages(struct task_struct *tsk, struct mm_struct *mm, | |||
1530 | get_page(page); | 1537 | get_page(page); |
1531 | } | 1538 | } |
1532 | pte_unmap(pte); | 1539 | pte_unmap(pte); |
1533 | if (vmas) | 1540 | goto next_page; |
1534 | vmas[i] = gate_vma; | ||
1535 | i++; | ||
1536 | start += PAGE_SIZE; | ||
1537 | nr_pages--; | ||
1538 | continue; | ||
1539 | } | 1541 | } |
1540 | 1542 | ||
1541 | if (!vma || | 1543 | if (!vma || |
@@ -1549,6 +1551,13 @@ int __get_user_pages(struct task_struct *tsk, struct mm_struct *mm, | |||
1549 | continue; | 1551 | continue; |
1550 | } | 1552 | } |
1551 | 1553 | ||
1554 | /* | ||
1555 | * If we don't actually want the page itself, | ||
1556 | * and it's the stack guard page, just skip it. | ||
1557 | */ | ||
1558 | if (!pages && stack_guard_page(vma, start)) | ||
1559 | goto next_page; | ||
1560 | |||
1552 | do { | 1561 | do { |
1553 | struct page *page; | 1562 | struct page *page; |
1554 | unsigned int foll_flags = gup_flags; | 1563 | unsigned int foll_flags = gup_flags; |
@@ -1569,6 +1578,8 @@ int __get_user_pages(struct task_struct *tsk, struct mm_struct *mm, | |||
1569 | fault_flags |= FAULT_FLAG_WRITE; | 1578 | fault_flags |= FAULT_FLAG_WRITE; |
1570 | if (nonblocking) | 1579 | if (nonblocking) |
1571 | fault_flags |= FAULT_FLAG_ALLOW_RETRY; | 1580 | fault_flags |= FAULT_FLAG_ALLOW_RETRY; |
1581 | if (foll_flags & FOLL_NOWAIT) | ||
1582 | fault_flags |= (FAULT_FLAG_ALLOW_RETRY | FAULT_FLAG_RETRY_NOWAIT); | ||
1572 | 1583 | ||
1573 | ret = handle_mm_fault(mm, vma, start, | 1584 | ret = handle_mm_fault(mm, vma, start, |
1574 | fault_flags); | 1585 | fault_flags); |
@@ -1589,13 +1600,17 @@ int __get_user_pages(struct task_struct *tsk, struct mm_struct *mm, | |||
1589 | return i ? i : -EFAULT; | 1600 | return i ? i : -EFAULT; |
1590 | BUG(); | 1601 | BUG(); |
1591 | } | 1602 | } |
1592 | if (ret & VM_FAULT_MAJOR) | 1603 | |
1593 | tsk->maj_flt++; | 1604 | if (tsk) { |
1594 | else | 1605 | if (ret & VM_FAULT_MAJOR) |
1595 | tsk->min_flt++; | 1606 | tsk->maj_flt++; |
1607 | else | ||
1608 | tsk->min_flt++; | ||
1609 | } | ||
1596 | 1610 | ||
1597 | if (ret & VM_FAULT_RETRY) { | 1611 | if (ret & VM_FAULT_RETRY) { |
1598 | *nonblocking = 0; | 1612 | if (nonblocking) |
1613 | *nonblocking = 0; | ||
1599 | return i; | 1614 | return i; |
1600 | } | 1615 | } |
1601 | 1616 | ||
@@ -1625,6 +1640,7 @@ int __get_user_pages(struct task_struct *tsk, struct mm_struct *mm, | |||
1625 | flush_anon_page(vma, page, start); | 1640 | flush_anon_page(vma, page, start); |
1626 | flush_dcache_page(page); | 1641 | flush_dcache_page(page); |
1627 | } | 1642 | } |
1643 | next_page: | ||
1628 | if (vmas) | 1644 | if (vmas) |
1629 | vmas[i] = vma; | 1645 | vmas[i] = vma; |
1630 | i++; | 1646 | i++; |
@@ -1638,7 +1654,8 @@ EXPORT_SYMBOL(__get_user_pages); | |||
1638 | 1654 | ||
1639 | /** | 1655 | /** |
1640 | * get_user_pages() - pin user pages in memory | 1656 | * get_user_pages() - pin user pages in memory |
1641 | * @tsk: task_struct of target task | 1657 | * @tsk: the task_struct to use for page fault accounting, or |
1658 | * NULL if faults are not to be recorded. | ||
1642 | * @mm: mm_struct of target mm | 1659 | * @mm: mm_struct of target mm |
1643 | * @start: starting user address | 1660 | * @start: starting user address |
1644 | * @nr_pages: number of pages from start to pin | 1661 | * @nr_pages: number of pages from start to pin |
@@ -2764,7 +2781,7 @@ static int do_swap_page(struct mm_struct *mm, struct vm_area_struct *vma, | |||
2764 | swp_entry_t entry; | 2781 | swp_entry_t entry; |
2765 | pte_t pte; | 2782 | pte_t pte; |
2766 | int locked; | 2783 | int locked; |
2767 | struct mem_cgroup *ptr = NULL; | 2784 | struct mem_cgroup *ptr; |
2768 | int exclusive = 0; | 2785 | int exclusive = 0; |
2769 | int ret = 0; | 2786 | int ret = 0; |
2770 | 2787 | ||
@@ -3496,7 +3513,7 @@ static int __init gate_vma_init(void) | |||
3496 | __initcall(gate_vma_init); | 3513 | __initcall(gate_vma_init); |
3497 | #endif | 3514 | #endif |
3498 | 3515 | ||
3499 | struct vm_area_struct *get_gate_vma(struct task_struct *tsk) | 3516 | struct vm_area_struct *get_gate_vma(struct mm_struct *mm) |
3500 | { | 3517 | { |
3501 | #ifdef AT_SYSINFO_EHDR | 3518 | #ifdef AT_SYSINFO_EHDR |
3502 | return &gate_vma; | 3519 | return &gate_vma; |
@@ -3505,7 +3522,7 @@ struct vm_area_struct *get_gate_vma(struct task_struct *tsk) | |||
3505 | #endif | 3522 | #endif |
3506 | } | 3523 | } |
3507 | 3524 | ||
3508 | int in_gate_area_no_task(unsigned long addr) | 3525 | int in_gate_area_no_mm(unsigned long addr) |
3509 | { | 3526 | { |
3510 | #ifdef AT_SYSINFO_EHDR | 3527 | #ifdef AT_SYSINFO_EHDR |
3511 | if ((addr >= FIXADDR_USER_START) && (addr < FIXADDR_USER_END)) | 3528 | if ((addr >= FIXADDR_USER_START) && (addr < FIXADDR_USER_END)) |
@@ -3646,20 +3663,15 @@ int generic_access_phys(struct vm_area_struct *vma, unsigned long addr, | |||
3646 | #endif | 3663 | #endif |
3647 | 3664 | ||
3648 | /* | 3665 | /* |
3649 | * Access another process' address space. | 3666 | * Access another process' address space as given in mm. If non-NULL, use the |
3650 | * Source/target buffer must be kernel space, | 3667 | * given task for page fault accounting. |
3651 | * Do not walk the page table directly, use get_user_pages | ||
3652 | */ | 3668 | */ |
3653 | int access_process_vm(struct task_struct *tsk, unsigned long addr, void *buf, int len, int write) | 3669 | static int __access_remote_vm(struct task_struct *tsk, struct mm_struct *mm, |
3670 | unsigned long addr, void *buf, int len, int write) | ||
3654 | { | 3671 | { |
3655 | struct mm_struct *mm; | ||
3656 | struct vm_area_struct *vma; | 3672 | struct vm_area_struct *vma; |
3657 | void *old_buf = buf; | 3673 | void *old_buf = buf; |
3658 | 3674 | ||
3659 | mm = get_task_mm(tsk); | ||
3660 | if (!mm) | ||
3661 | return 0; | ||
3662 | |||
3663 | down_read(&mm->mmap_sem); | 3675 | down_read(&mm->mmap_sem); |
3664 | /* ignore errors, just check how much was successfully transferred */ | 3676 | /* ignore errors, just check how much was successfully transferred */ |
3665 | while (len) { | 3677 | while (len) { |
@@ -3676,7 +3688,7 @@ int access_process_vm(struct task_struct *tsk, unsigned long addr, void *buf, in | |||
3676 | */ | 3688 | */ |
3677 | #ifdef CONFIG_HAVE_IOREMAP_PROT | 3689 | #ifdef CONFIG_HAVE_IOREMAP_PROT |
3678 | vma = find_vma(mm, addr); | 3690 | vma = find_vma(mm, addr); |
3679 | if (!vma) | 3691 | if (!vma || vma->vm_start > addr) |
3680 | break; | 3692 | break; |
3681 | if (vma->vm_ops && vma->vm_ops->access) | 3693 | if (vma->vm_ops && vma->vm_ops->access) |
3682 | ret = vma->vm_ops->access(vma, addr, buf, | 3694 | ret = vma->vm_ops->access(vma, addr, buf, |
@@ -3708,11 +3720,47 @@ int access_process_vm(struct task_struct *tsk, unsigned long addr, void *buf, in | |||
3708 | addr += bytes; | 3720 | addr += bytes; |
3709 | } | 3721 | } |
3710 | up_read(&mm->mmap_sem); | 3722 | up_read(&mm->mmap_sem); |
3711 | mmput(mm); | ||
3712 | 3723 | ||
3713 | return buf - old_buf; | 3724 | return buf - old_buf; |
3714 | } | 3725 | } |
3715 | 3726 | ||
3727 | /** | ||
3728 | * access_remote_vm - access another process' address space | ||
3729 | * @mm: the mm_struct of the target address space | ||
3730 | * @addr: start address to access | ||
3731 | * @buf: source or destination buffer | ||
3732 | * @len: number of bytes to transfer | ||
3733 | * @write: whether the access is a write | ||
3734 | * | ||
3735 | * The caller must hold a reference on @mm. | ||
3736 | */ | ||
3737 | int access_remote_vm(struct mm_struct *mm, unsigned long addr, | ||
3738 | void *buf, int len, int write) | ||
3739 | { | ||
3740 | return __access_remote_vm(NULL, mm, addr, buf, len, write); | ||
3741 | } | ||
3742 | |||
3743 | /* | ||
3744 | * Access another process' address space. | ||
3745 | * Source/target buffer must be kernel space, | ||
3746 | * Do not walk the page table directly, use get_user_pages | ||
3747 | */ | ||
3748 | int access_process_vm(struct task_struct *tsk, unsigned long addr, | ||
3749 | void *buf, int len, int write) | ||
3750 | { | ||
3751 | struct mm_struct *mm; | ||
3752 | int ret; | ||
3753 | |||
3754 | mm = get_task_mm(tsk); | ||
3755 | if (!mm) | ||
3756 | return 0; | ||
3757 | |||
3758 | ret = __access_remote_vm(tsk, mm, addr, buf, len, write); | ||
3759 | mmput(mm); | ||
3760 | |||
3761 | return ret; | ||
3762 | } | ||
3763 | |||
3716 | /* | 3764 | /* |
3717 | * Print the name of a VMA. | 3765 | * Print the name of a VMA. |
3718 | */ | 3766 | */ |