From: Xiongfeng Wang wangxiongfeng2@huawei.com
hulk inclusion category: bugfix bugzilla: 175146 CVE: NA
------------------------------------
Disable userswap by default and add a kernel parameter to enable it.
Signed-off-by: Xiongfeng Wang wangxiongfeng2@huawei.com Reviewed-by: Kefeng Wang wangkefeng.wang@huawei.com Signed-off-by: Yang Yingliang yangyingliang@huawei.com
Conflicts: include/linux/userfaultfd_k.h Signed-off-by: Xiongfeng Wang wangxiongfeng2@huawei.com Reviewed-by: Kefeng Wang wangkefeng.wang@huawei.com Signed-off-by: Zheng Zengkai zhengzengkai@huawei.com --- fs/userfaultfd.c | 17 +++++++++++++++-- include/linux/userfaultfd_k.h | 3 +++ mm/mmap.c | 6 +++--- 3 files changed, 21 insertions(+), 5 deletions(-)
diff --git a/fs/userfaultfd.c b/fs/userfaultfd.c index a89281fc2b68..bd71fbd68199 100644 --- a/fs/userfaultfd.c +++ b/fs/userfaultfd.c @@ -31,6 +31,9 @@ int sysctl_unprivileged_userfaultfd __read_mostly = 1;
static struct kmem_cache *userfaultfd_ctx_cachep __read_mostly; +#ifdef CONFIG_USERSWAP +int enable_userswap; +#endif
enum userfaultfd_state { UFFD_STATE_WAIT_API, @@ -863,7 +866,8 @@ static int userfaultfd_release(struct inode *inode, struct file *file) for (vma = mm->mmap; vma; vma = vma->vm_next) { userfault_flags = VM_UFFD_MISSING | VM_UFFD_WP; #ifdef CONFIG_USERSWAP - userfault_flags |= VM_USWAP; + if (enable_userswap) + userfault_flags |= VM_USWAP; #endif cond_resched(); BUG_ON(!!vma->vm_userfaultfd_ctx.ctx ^ @@ -1295,7 +1299,7 @@ static int userfaultfd_register(struct userfaultfd_ctx *ctx, * register the whole vma overlapping with the address range to avoid * splitting the vma. */ - if (uffdio_register.mode & UFFDIO_REGISTER_MODE_USWAP) { + if (enable_userswap && (uffdio_register.mode & UFFDIO_REGISTER_MODE_USWAP)) { uffdio_register.mode &= ~UFFDIO_REGISTER_MODE_USWAP; if (!uffdio_register.mode) goto out; @@ -2024,6 +2028,15 @@ SYSCALL_DEFINE1(userfaultfd, int, flags) return fd; }
+#ifdef CONFIG_USERSWAP +static int __init enable_userswap_setup(char *str) +{ + enable_userswap = true; + return 1; +} +__setup("enable_userswap", enable_userswap_setup); +#endif + static int __init userfaultfd_init(void) { userfaultfd_ctx_cachep = kmem_cache_create("userfaultfd_ctx_cache", diff --git a/include/linux/userfaultfd_k.h b/include/linux/userfaultfd_k.h index e91f31a4c830..e1cacab86bde 100644 --- a/include/linux/userfaultfd_k.h +++ b/include/linux/userfaultfd_k.h @@ -31,6 +31,9 @@ #define UFFD_FLAGS_SET (EFD_SHARED_FCNTL_FLAGS)
extern int sysctl_unprivileged_userfaultfd; +#ifdef CONFIG_USERSWAP +extern int enable_userswap; +#endif
extern vm_fault_t handle_userfault(struct vm_fault *vmf, unsigned long reason);
diff --git a/mm/mmap.c b/mm/mmap.c index 069d88aeeeba..e440f337238a 100644 --- a/mm/mmap.c +++ b/mm/mmap.c @@ -1598,7 +1598,7 @@ unsigned long do_mmap(struct file *file, unsigned long addr, prot |= PROT_EXEC;
#ifdef CONFIG_USERSWAP - if (flags & MAP_REPLACE) { + if (enable_userswap && (flags & MAP_REPLACE)) { if (offset_in_page(addr) || (len % PAGE_SIZE)) return -EINVAL; page_num = len / PAGE_SIZE; @@ -1765,7 +1765,7 @@ unsigned long do_mmap(struct file *file, unsigned long addr,
#ifdef CONFIG_USERSWAP /* mark the vma as special to avoid merging with other vmas */ - if (flags & MAP_REPLACE) + if (enable_userswap && (flags & MAP_REPLACE)) vm_flags |= VM_SPECIAL; #endif
@@ -1777,7 +1777,7 @@ unsigned long do_mmap(struct file *file, unsigned long addr, #ifndef CONFIG_USERSWAP return addr; #else - if (!(flags & MAP_REPLACE)) + if (!enable_userswap || !(flags & MAP_REPLACE)) return addr;
if (IS_ERR_VALUE(addr)) {