Commit bca1d4de authored by Linus Torvalds's avatar Linus Torvalds
Browse files

Merge branch 'akpm' (patches from Andrew)

Merge misc mm fixes from Andrew Morton:
 "15 patches.

  VM subsystems affected by this patch series: userfaultfd, kfence,
  highmem, pagealloc, memblock, pagecache, secretmem, pagemap, and
  hugetlbfs"

* akpm:
  hugetlbfs: fix mount mode command line processing
  mm: fix the deadlock in finish_fault()
  mm: mmap_lock: fix disabling preemption directly
  mm/secretmem: wire up ->set_page_dirty
  writeback, cgroup: do not reparent dax inodes
  writeback, cgroup: remove wb from offline list before releasing refcnt
  memblock: make for_each_mem_range() traverse MEMBLOCK_HOTPLUG regions
  mm: page_alloc: fix page_poison=1 / INIT_ON_ALLOC_DEFAULT_ON interaction
  mm: use kmap_local_page in memzero_page
  mm: call flush_dcache_page() in memcpy_to_page() and memzero_page()
  kfence: skip all GFP_ZONEMASK allocations
  kfence: move the size check to the beginning of __kfence_alloc()
  kfence: defer kfence_test_init to ensure that kunit debugfs is created
  selftest: use mmap instead of posix_memalign to allocate memory
  userfaultfd: do not untag user pointers
parents f0fddcec e0f7e2b2
Loading
Loading
Loading
Loading
+18 −8
Original line number Diff line number Diff line
@@ -45,8 +45,9 @@ how the user addresses are used by the kernel:

1. User addresses not accessed by the kernel but used for address space
   management (e.g. ``mprotect()``, ``madvise()``). The use of valid
   tagged pointers in this context is allowed with the exception of
   ``brk()``, ``mmap()`` and the ``new_address`` argument to
   tagged pointers in this context is allowed with these exceptions:

   - ``brk()``, ``mmap()`` and the ``new_address`` argument to
     ``mremap()`` as these have the potential to alias with existing
      user addresses.

@@ -54,6 +55,15 @@ how the user addresses are used by the kernel:
     incorrectly accept valid tagged pointers for the ``brk()``,
     ``mmap()`` and ``mremap()`` system calls.

   - The ``range.start``, ``start`` and ``dst`` arguments to the
     ``UFFDIO_*`` ``ioctl()``s used on a file descriptor obtained from
     ``userfaultfd()``, as fault addresses subsequently obtained by reading
     the file descriptor will be untagged, which may otherwise confuse
     tag-unaware programs.

     NOTE: This behaviour changed in v5.14 and so some earlier kernels may
     incorrectly accept valid tagged pointers for this system call.

2. User addresses accessed by the kernel (e.g. ``write()``). This ABI
   relaxation is disabled by default and the application thread needs to
   explicitly enable it via ``prctl()`` as follows:
+3 −0
Original line number Diff line number Diff line
@@ -521,6 +521,9 @@ static bool inode_prepare_wbs_switch(struct inode *inode,
	 */
	smp_mb();

	if (IS_DAX(inode))
		return false;

	/* while holding I_WB_SWITCH, no one else can update the association */
	spin_lock(&inode->i_lock);
	if (!(inode->i_sb->s_flags & SB_ACTIVE) ||
+1 −1
Original line number Diff line number Diff line
@@ -77,7 +77,7 @@ enum hugetlb_param {
static const struct fs_parameter_spec hugetlb_fs_parameters[] = {
	fsparam_u32   ("gid",		Opt_gid),
	fsparam_string("min_size",	Opt_min_size),
	fsparam_u32   ("mode",		Opt_mode),
	fsparam_u32oct("mode",		Opt_mode),
	fsparam_string("nr_inodes",	Opt_nr_inodes),
	fsparam_string("pagesize",	Opt_pagesize),
	fsparam_string("size",		Opt_size),
+12 −14
Original line number Diff line number Diff line
@@ -1236,23 +1236,21 @@ static __always_inline void wake_userfault(struct userfaultfd_ctx *ctx,
}

static __always_inline int validate_range(struct mm_struct *mm,
					  __u64 *start, __u64 len)
					  __u64 start, __u64 len)
{
	__u64 task_size = mm->task_size;

	*start = untagged_addr(*start);

	if (*start & ~PAGE_MASK)
	if (start & ~PAGE_MASK)
		return -EINVAL;
	if (len & ~PAGE_MASK)
		return -EINVAL;
	if (!len)
		return -EINVAL;
	if (*start < mmap_min_addr)
	if (start < mmap_min_addr)
		return -EINVAL;
	if (*start >= task_size)
	if (start >= task_size)
		return -EINVAL;
	if (len > task_size - *start)
	if (len > task_size - start)
		return -EINVAL;
	return 0;
}
@@ -1316,7 +1314,7 @@ static int userfaultfd_register(struct userfaultfd_ctx *ctx,
		vm_flags |= VM_UFFD_MINOR;
	}

	ret = validate_range(mm, &uffdio_register.range.start,
	ret = validate_range(mm, uffdio_register.range.start,
			     uffdio_register.range.len);
	if (ret)
		goto out;
@@ -1522,7 +1520,7 @@ static int userfaultfd_unregister(struct userfaultfd_ctx *ctx,
	if (copy_from_user(&uffdio_unregister, buf, sizeof(uffdio_unregister)))
		goto out;

	ret = validate_range(mm, &uffdio_unregister.start,
	ret = validate_range(mm, uffdio_unregister.start,
			     uffdio_unregister.len);
	if (ret)
		goto out;
@@ -1671,7 +1669,7 @@ static int userfaultfd_wake(struct userfaultfd_ctx *ctx,
	if (copy_from_user(&uffdio_wake, buf, sizeof(uffdio_wake)))
		goto out;

	ret = validate_range(ctx->mm, &uffdio_wake.start, uffdio_wake.len);
	ret = validate_range(ctx->mm, uffdio_wake.start, uffdio_wake.len);
	if (ret)
		goto out;

@@ -1711,7 +1709,7 @@ static int userfaultfd_copy(struct userfaultfd_ctx *ctx,
			   sizeof(uffdio_copy)-sizeof(__s64)))
		goto out;

	ret = validate_range(ctx->mm, &uffdio_copy.dst, uffdio_copy.len);
	ret = validate_range(ctx->mm, uffdio_copy.dst, uffdio_copy.len);
	if (ret)
		goto out;
	/*
@@ -1768,7 +1766,7 @@ static int userfaultfd_zeropage(struct userfaultfd_ctx *ctx,
			   sizeof(uffdio_zeropage)-sizeof(__s64)))
		goto out;

	ret = validate_range(ctx->mm, &uffdio_zeropage.range.start,
	ret = validate_range(ctx->mm, uffdio_zeropage.range.start,
			     uffdio_zeropage.range.len);
	if (ret)
		goto out;
@@ -1818,7 +1816,7 @@ static int userfaultfd_writeprotect(struct userfaultfd_ctx *ctx,
			   sizeof(struct uffdio_writeprotect)))
		return -EFAULT;

	ret = validate_range(ctx->mm, &uffdio_wp.range.start,
	ret = validate_range(ctx->mm, uffdio_wp.range.start,
			     uffdio_wp.range.len);
	if (ret)
		return ret;
@@ -1866,7 +1864,7 @@ static int userfaultfd_continue(struct userfaultfd_ctx *ctx, unsigned long arg)
			   sizeof(uffdio_continue) - (sizeof(__s64))))
		goto out;

	ret = validate_range(ctx->mm, &uffdio_continue.range.start,
	ret = validate_range(ctx->mm, uffdio_continue.range.start,
			     uffdio_continue.range.len);
	if (ret)
		goto out;
+4 −2
Original line number Diff line number Diff line
@@ -318,14 +318,16 @@ static inline void memcpy_to_page(struct page *page, size_t offset,

	VM_BUG_ON(offset + len > PAGE_SIZE);
	memcpy(to + offset, from, len);
	flush_dcache_page(page);
	kunmap_local(to);
}

static inline void memzero_page(struct page *page, size_t offset, size_t len)
{
	char *addr = kmap_atomic(page);
	char *addr = kmap_local_page(page);
	memset(addr + offset, 0, len);
	kunmap_atomic(addr);
	flush_dcache_page(page);
	kunmap_local(addr);
}

#endif /* _LINUX_HIGHMEM_H */
Loading