提交 7a99cdfb 编写于 作者: X Xiongfeng Wang 提交者: Zheng Zengkai

mmap: userswap: fix some format issues

hulk inclusion
category: bugfix
bugzilla: https://gitee.com/openeuler/kernel/issues/I4AHP2
CVE: NA

-------------------------------------------------

Fix some format issues in mm/mmap.c.

This patch also fix the wrong address range of mmu_notifier_range_init()
in do_user_swap().
Signed-off-by: NKefeng Wang <wangkefeng.wang@huawei.com>
Signed-off-by: NXiongfeng Wang <wangxiongfeng2@huawei.com>
Reviewed-by: NKefeng Wang <wangkefeng.wang@huawei.com>
Signed-off-by: NZheng Zengkai <zhengzengkai@huawei.com>
上级 653e67ab
...@@ -1399,12 +1399,10 @@ static inline bool file_mmap_ok(struct file *file, struct inode *inode, ...@@ -1399,12 +1399,10 @@ static inline bool file_mmap_ok(struct file *file, struct inode *inode,
return true; return true;
} }
static inline static inline unsigned long
unsigned long __do_mmap(struct file *file, unsigned long addr, __do_mmap(struct file *file, unsigned long addr, unsigned long len,
unsigned long len, unsigned long prot, unsigned long prot, unsigned long flags, vm_flags_t vm_flags,
unsigned long flags, vm_flags_t vm_flags, unsigned long pgoff, unsigned long *populate, struct list_head *uf)
unsigned long pgoff, unsigned long *populate,
struct list_head *uf)
{ {
struct mm_struct *mm = current->mm; struct mm_struct *mm = current->mm;
int pkey = 0; int pkey = 0;
...@@ -1593,13 +1591,13 @@ unsigned long __do_mmap(struct file *file, unsigned long addr, ...@@ -1593,13 +1591,13 @@ unsigned long __do_mmap(struct file *file, unsigned long addr,
* the reference of the pages and return the pages through input parameters * the reference of the pages and return the pages through input parameters
* 'ppages'. * 'ppages'.
*/ */
int pages_can_be_swapped(struct mm_struct *mm, unsigned long addr, static int pages_can_be_swapped(struct mm_struct *mm, unsigned long addr,
unsigned long len, struct page ***ppages) unsigned long len, struct page ***ppages)
{ {
struct vm_area_struct *vma; struct vm_area_struct *vma;
struct page *page = NULL; struct page *page = NULL;
struct page **pages = NULL; struct page **pages = NULL;
unsigned long addr_start, addr_end; unsigned long addr_end = addr + len;
unsigned long ret; unsigned long ret;
int i, page_num = 0; int i, page_num = 0;
...@@ -1607,13 +1605,11 @@ int pages_can_be_swapped(struct mm_struct *mm, unsigned long addr, ...@@ -1607,13 +1605,11 @@ int pages_can_be_swapped(struct mm_struct *mm, unsigned long addr,
if (!pages) if (!pages)
return -ENOMEM; return -ENOMEM;
addr_start = addr;
addr_end = addr + len;
while (addr < addr_end) { while (addr < addr_end) {
vma = find_vma(mm, addr); vma = find_vma(mm, addr);
if (!vma || !vma_is_anonymous(vma) || if (!vma || !vma_is_anonymous(vma) || vma->vm_file ||
(vma->vm_flags & VM_LOCKED) || vma->vm_file (vma->vm_flags & VM_LOCKED) || (vma->vm_flags & VM_STACK) ||
|| (vma->vm_flags & VM_STACK) || (vma->vm_flags & (VM_IO | VM_PFNMAP))) { (vma->vm_flags & (VM_IO | VM_PFNMAP))) {
ret = -EINVAL; ret = -EINVAL;
goto out; goto out;
} }
...@@ -1628,9 +1624,9 @@ int pages_can_be_swapped(struct mm_struct *mm, unsigned long addr, ...@@ -1628,9 +1624,9 @@ int pages_can_be_swapped(struct mm_struct *mm, unsigned long addr,
ret = -ENODEV; ret = -ENODEV;
goto out; goto out;
} }
pages[page_num] = page; pages[page_num++] = page;
page_num++; if (!PageAnon(page) || !PageSwapBacked(page) ||
if (!PageAnon(page) || !PageSwapBacked(page) || PageHuge(page) || PageSwapCache(page)) { PageHuge(page) || PageSwapCache(page)) {
ret = -EINVAL; ret = -EINVAL;
goto out; goto out;
} else if (PageTransCompound(page)) { } else if (PageTransCompound(page)) {
...@@ -1650,7 +1646,8 @@ int pages_can_be_swapped(struct mm_struct *mm, unsigned long addr, ...@@ -1650,7 +1646,8 @@ int pages_can_be_swapped(struct mm_struct *mm, unsigned long addr,
goto out; goto out;
} }
} }
if (page_mapcount(page) > 1 || page_mapcount(page) + 1 != page_count(page)) { if (page_mapcount(page) > 1 ||
page_mapcount(page) + 1 != page_count(page)) {
ret = -EBUSY; ret = -EBUSY;
goto out; goto out;
} }
...@@ -1676,8 +1673,9 @@ int pages_can_be_swapped(struct mm_struct *mm, unsigned long addr, ...@@ -1676,8 +1673,9 @@ int pages_can_be_swapped(struct mm_struct *mm, unsigned long addr,
#define USWAP_PAGES_DIRTY 1 #define USWAP_PAGES_DIRTY 1
/* unmap the pages between 'addr ~ addr+len' and remap them to a new address */ /* unmap the pages between 'addr ~ addr+len' and remap them to a new address */
unsigned long do_user_swap(struct mm_struct *mm, unsigned long addr_start, static unsigned long
unsigned long len, struct page **pages, unsigned long new_addr) do_user_swap(struct mm_struct *mm, unsigned long addr_start, unsigned long len,
struct page **pages, unsigned long new_addr)
{ {
struct vm_area_struct *vma; struct vm_area_struct *vma;
struct page *page; struct page *page;
...@@ -1685,28 +1683,25 @@ unsigned long do_user_swap(struct mm_struct *mm, unsigned long addr_start, ...@@ -1685,28 +1683,25 @@ unsigned long do_user_swap(struct mm_struct *mm, unsigned long addr_start,
pmd_t *pmd; pmd_t *pmd;
pte_t *pte, old_pte; pte_t *pte, old_pte;
spinlock_t *ptl; spinlock_t *ptl;
unsigned long addr, addr_end; unsigned long addr;
bool pages_dirty = false; bool pages_dirty = false;
int i, err; int i = 0;
addr_end = addr_start + len;
lru_add_drain();
addr = addr_start; addr = addr_start;
lru_add_drain();
i = 0; i = 0;
while (addr < addr_end) { while (addr < addr_start + len) {
page = pages[i]; page = pages[i];
vma = find_vma(mm, addr); vma = find_vma(mm, addr);
if (!vma) { if (!vma)
WARN_ON("find_vma failed\n");
return -EINVAL; return -EINVAL;
}
mmu_notifier_range_init(&range, MMU_NOTIFY_UNMAP, 0, vma, mmu_notifier_range_init(&range, MMU_NOTIFY_UNMAP, 0, vma,
vma->vm_mm, addr_start, addr_start + PAGE_SIZE); vma->vm_mm, addr, addr + PAGE_SIZE);
mmu_notifier_invalidate_range_start(&range); mmu_notifier_invalidate_range_start(&range);
pmd = mm_find_pmd(mm, addr); pmd = mm_find_pmd(mm, addr);
if (!pmd) { if (!pmd) {
mmu_notifier_invalidate_range_end(&range); mmu_notifier_invalidate_range_end(&range);
WARN_ON("mm_find_pmd failed, addr:%llx\n");
return -ENXIO; return -ENXIO;
} }
pte = pte_offset_map_lock(mm, pmd, addr, &ptl); pte = pte_offset_map_lock(mm, pmd, addr, &ptl);
...@@ -1714,7 +1709,8 @@ unsigned long do_user_swap(struct mm_struct *mm, unsigned long addr_start, ...@@ -1714,7 +1709,8 @@ unsigned long do_user_swap(struct mm_struct *mm, unsigned long addr_start,
old_pte = ptep_clear_flush(vma, addr, pte); old_pte = ptep_clear_flush(vma, addr, pte);
if (pte_dirty(old_pte) || PageDirty(page)) if (pte_dirty(old_pte) || PageDirty(page))
pages_dirty = true; pages_dirty = true;
set_pte(pte, swp_entry_to_pte(swp_entry(SWP_USERSWAP_ENTRY, page_to_pfn(page)))); set_pte(pte, swp_entry_to_pte(swp_entry(SWP_USERSWAP_ENTRY,
page_to_pfn(page))));
dec_mm_counter(mm, MM_ANONPAGES); dec_mm_counter(mm, MM_ANONPAGES);
page_remove_rmap(page, false); page_remove_rmap(page, false);
put_page(page); put_page(page);
...@@ -1727,20 +1723,19 @@ unsigned long do_user_swap(struct mm_struct *mm, unsigned long addr_start, ...@@ -1727,20 +1723,19 @@ unsigned long do_user_swap(struct mm_struct *mm, unsigned long addr_start,
i++; i++;
} }
addr_start = new_addr; addr = new_addr;
addr_end = new_addr + len;
addr = addr_start;
vma = find_vma(mm, addr); vma = find_vma(mm, addr);
i = 0; i = 0;
while (addr < addr_end) { while (addr < new_addr + len) {
page = pages[i];
if (addr > vma->vm_end - 1) if (addr > vma->vm_end - 1)
vma = find_vma(mm, addr); vma = find_vma(mm, addr);
err = vm_insert_page(vma, addr, page); if (!vma)
if (err) { return -ENODEV;
pr_err("vm_insert_page failed:%d\n", err);
} page = pages[i++];
i++; if (vm_insert_page(vma, addr, page))
return -EFAULT;
addr += PAGE_SIZE; addr += PAGE_SIZE;
} }
vma->vm_flags |= VM_USWAP; vma->vm_flags |= VM_USWAP;
...@@ -1751,22 +1746,20 @@ unsigned long do_user_swap(struct mm_struct *mm, unsigned long addr_start, ...@@ -1751,22 +1746,20 @@ unsigned long do_user_swap(struct mm_struct *mm, unsigned long addr_start,
return new_addr; return new_addr;
} }
static inline static inline unsigned long
unsigned long do_uswap_mmap(struct file *file, unsigned long addr, do_uswap_mmap(struct file *file, unsigned long addr, unsigned long len,
unsigned long len, unsigned long prot, unsigned long prot, unsigned long flags, unsigned long pgoff,
unsigned long flags, unsigned long pgoff, unsigned long *populate, struct list_head *uf)
unsigned long *populate, struct list_head *uf)
{ {
struct mm_struct *mm = current->mm; struct mm_struct *mm = current->mm;
unsigned long addr_start = addr; unsigned long old_addr = addr;
struct page **pages = NULL; struct page **pages = NULL;
unsigned long ret; unsigned long ret;
int i, page_num = 0; int i;
if (!len || offset_in_page(addr) || (len % PAGE_SIZE)) if (!len || offset_in_page(addr) || (len % PAGE_SIZE))
return -EINVAL; return -EINVAL;
page_num = len / PAGE_SIZE;
ret = pages_can_be_swapped(mm, addr, len, &pages); ret = pages_can_be_swapped(mm, addr, len, &pages);
if (ret) if (ret)
return ret; return ret;
...@@ -1779,12 +1772,11 @@ unsigned long do_uswap_mmap(struct file *file, unsigned long addr, ...@@ -1779,12 +1772,11 @@ unsigned long do_uswap_mmap(struct file *file, unsigned long addr,
goto out; goto out;
} }
ret = do_user_swap(mm, addr_start, len, pages, addr); ret = do_user_swap(mm, old_addr, len, pages, addr);
out: out:
/* follow_page() above increased the reference*/ /* follow_page() above increased the reference*/
for (i = 0; i < page_num; i++) for (i = 0; i < len / PAGE_SIZE; i++)
put_page(pages[i]); put_page(pages[i]);
if (pages) if (pages)
kfree(pages); kfree(pages);
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册