mirror of
https://git.kernel.org/pub/scm/linux/kernel/git/stable/linux.git
synced 2024-08-28 20:02:17 +00:00
![Jiashuo Liang](/assets/img/avatar_default.png)
The function __bad_area_nosemaphore() calls kernelmode_fixup_or_oops()
with the parameter @signal being actually @pkey, which will send a
signal numbered with the argument in @pkey.
This bug can be triggered when the kernel fails to access user-given
memory pages that are protected by a pkey, so it can go down the
do_user_addr_fault() path and pass the !user_mode() check in
__bad_area_nosemaphore().
Most cases will simply run the kernel fixup code to make an -EFAULT. But
when another condition current->thread.sig_on_uaccess_err is met, which
is only used to emulate vsyscall, the kernel will generate the wrong
signal.
Add a new parameter @pkey to kernelmode_fixup_or_oops() to fix this.
[ bp: Massage commit message, fix build error as reported by the 0day
bot: https://lkml.kernel.org/r/202109202245.APvuT8BX-lkp@intel.com ]
Fixes: 5042d40a26
("x86/fault: Bypass no_context() for implicit kernel faults from usermode")
Reported-by: kernel test robot <lkp@intel.com>
Signed-off-by: Jiashuo Liang <liangjs@pku.edu.cn>
Signed-off-by: Borislav Petkov <bp@suse.de>
Acked-by: Dave Hansen <dave.hansen@linux.intel.com>
Link: https://lkml.kernel.org/r/20210730030152.249106-1-liangjs@pku.edu.cn
51 lines
990 B
C
51 lines
990 B
C
/* SPDX-License-Identifier: GPL-2.0 */
|
|
#ifndef _LINUX_PKEYS_H
|
|
#define _LINUX_PKEYS_H
|
|
|
|
#include <linux/mm.h>
|
|
|
|
#define ARCH_DEFAULT_PKEY 0
|
|
|
|
#ifdef CONFIG_ARCH_HAS_PKEYS
|
|
#include <asm/pkeys.h>
|
|
#else /* ! CONFIG_ARCH_HAS_PKEYS */
|
|
#define arch_max_pkey() (1)
|
|
#define execute_only_pkey(mm) (0)
|
|
#define arch_override_mprotect_pkey(vma, prot, pkey) (0)
|
|
#define PKEY_DEDICATED_EXECUTE_ONLY 0
|
|
#define ARCH_VM_PKEY_FLAGS 0
|
|
|
|
static inline int vma_pkey(struct vm_area_struct *vma)
|
|
{
|
|
return 0;
|
|
}
|
|
|
|
static inline bool mm_pkey_is_allocated(struct mm_struct *mm, int pkey)
|
|
{
|
|
return (pkey == 0);
|
|
}
|
|
|
|
static inline int mm_pkey_alloc(struct mm_struct *mm)
|
|
{
|
|
return -1;
|
|
}
|
|
|
|
static inline int mm_pkey_free(struct mm_struct *mm, int pkey)
|
|
{
|
|
return -EINVAL;
|
|
}
|
|
|
|
static inline int arch_set_user_pkey_access(struct task_struct *tsk, int pkey,
|
|
unsigned long init_val)
|
|
{
|
|
return 0;
|
|
}
|
|
|
|
static inline bool arch_pkeys_enabled(void)
|
|
{
|
|
return false;
|
|
}
|
|
|
|
#endif /* ! CONFIG_ARCH_HAS_PKEYS */
|
|
|
|
#endif /* _LINUX_PKEYS_H */
|