Commit 03714218 authored by ZhangPeng's avatar ZhangPeng Committed by Ma Wupeng
Browse files

userswap: add checks for input addresses

hulk inclusion
category: feature
bugzilla: https://gitee.com/openeuler/kernel/issues/I6CAIM



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

Add checks for new_addr in uswap_mremap() and src_addr in
uswap_check_copy_mode(), including user mode checks, overlapping
checks, etc.

Signed-off-by: default avatarZhangPeng <zhangpeng362@huawei.com>
parent 74c0e7cd
Loading
Loading
Loading
Loading
+15 −3
Original line number Diff line number Diff line
@@ -36,10 +36,22 @@ bool uswap_adjust_uffd_range(struct uffdio_register *uffdio_register,
bool do_uswap_page(swp_entry_t entry, struct vm_fault *vmf,
		   struct vm_area_struct *vma, vm_fault_t *ret);

static inline bool uswap_check_copy_mode(struct vm_area_struct *vma, __u64 mode)
static inline bool uswap_check_copy(struct vm_area_struct *vma,
				    unsigned long src_addr,
				    unsigned long len, __u64 mode)
{
	if (!(vma->vm_flags & VM_USWAP) && (mode & UFFDIO_COPY_MODE_DIRECT_MAP))
	if (vma->vm_flags & VM_USWAP) {
		if (!(mode & UFFDIO_COPY_MODE_DIRECT_MAP))
			return false;
		if (offset_in_page(src_addr))
			return false;
		if (src_addr > TASK_SIZE || src_addr > TASK_SIZE - len)
			return false;
	} else {
		if (mode & UFFDIO_COPY_MODE_DIRECT_MAP)
			return false;
	}

	return true;
}

+1 −1
Original line number Diff line number Diff line
@@ -512,7 +512,7 @@ static __always_inline ssize_t __mcopy_atomic(struct mm_struct *dst_mm,

	err = -EINVAL;
#ifdef CONFIG_USERSWAP
	if (!uswap_check_copy_mode(dst_vma, mode))
	if (!uswap_check_copy(dst_vma, src_addr, len, mode))
		goto out_unlock;
#endif
	/*
+8 −1
Original line number Diff line number Diff line
@@ -364,7 +364,14 @@ unsigned long uswap_mremap(unsigned long old_addr, unsigned long old_len,
	unsigned long i;

	if (!len || old_len != new_len || offset_in_page(old_addr) ||
	    (len % PAGE_SIZE))
	    offset_in_page(new_addr) || (len % PAGE_SIZE))
		return ret;

	if (new_len > TASK_SIZE || new_addr > TASK_SIZE - new_len)
		return ret;

	/* Ensure the old/new locations do not overlap */
	if (old_addr + old_len > new_addr && new_addr + new_len > old_addr)
		return ret;

	down_read(&mm->mmap_lock);