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

userswap: fix VM_BUG_ON() in handle_userfault()

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



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

When CONFIG_VM_BUG_ON=y and userswap feature is used, there is a kernel
BUG in handle_userfault(). VM_BUG_ON() didn't allow more than one reason
flag.
Fix this by skipping VM_BUG_ON() if reason is VM_UFFD_MISSING|VM_USWAP.

Signed-off-by: default avatarZhangPeng <zhangpeng362@huawei.com>
parent c97cdd7e
Loading
Loading
Loading
Loading
+4 −0
Original line number Diff line number Diff line
@@ -406,8 +406,12 @@ vm_fault_t handle_userfault(struct vm_fault *vmf, unsigned long reason)

	BUG_ON(ctx->mm != mm);

#ifdef CONFIG_USERSWAP
	VM_BUG_ON(uswap_vm_flag_bug_on(reason));
#else
	VM_BUG_ON(reason & ~(VM_UFFD_MISSING|VM_UFFD_WP));
	VM_BUG_ON(!(reason & VM_UFFD_MISSING) ^ !!(reason & VM_UFFD_WP));
#endif

	if (ctx->features & UFFD_FEATURE_SIGBUS)
		goto out;
+12 −0
Original line number Diff line number Diff line
@@ -47,6 +47,18 @@ static inline bool uswap_validate_mremap_flags(unsigned long flags)
	return true;
}

/* When CONFIG_USERSWAP=y, VM_UFFD_MISSING|VM_USWAP is right;
 * 0 or > 1 flags set is a bug; we expect exactly 1.
 */
static inline bool uswap_vm_flag_bug_on(unsigned long reason)
{
	if (reason & ~(VM_UFFD_MISSING | VM_UFFD_WP | VM_USWAP))
		return true;
	if (reason & VM_USWAP)
		return !(reason & VM_UFFD_MISSING) || reason & ~(VM_USWAP|VM_UFFD_MISSING);
	return !(reason & VM_UFFD_MISSING) ^ !!(reason & VM_UFFD_WP);
}

#endif /* CONFIG_USERSWAP */

#endif /* _LINUX_USERSWAP_H */