Skip to content

Commit

Permalink
x86/vsyscall: Document odd SIGSEGV error code for vsyscalls
Browse files Browse the repository at this point in the history
Even if vsyscall=none, user page faults on the vsyscall page are reported
as though the PROT bit in the error code was set.  Add a comment explaining
why this is probably okay and display the value in the test case.

While at it, explain why the behavior is correct with respect to PKRU.

Modify also the selftest to print the odd error code so that there is a
way to demonstrate the odd behaviour.

If anyone really cares about more accurate emulation, the behaviour could
be changed. But that needs a real good justification.

Signed-off-by: Andy Lutomirski <luto@kernel.org>
Signed-off-by: Thomas Gleixner <tglx@linutronix.de>
Reviewed-by: Kees Cook <keescook@chromium.org>
Cc: Florian Weimer <fweimer@redhat.com>
Cc: Jann Horn <jannh@google.com>
Cc: Borislav Petkov <bp@alien8.de>
Cc: Kernel Hardening <kernel-hardening@lists.openwall.com>
Cc: Peter Zijlstra <peterz@infradead.org>
Link: https://lkml.kernel.org/r/75c91855fd850649ace162eec5495a1354221aaa.1561610354.git.luto@kernel.org
  • Loading branch information
amluto authored and KAGA-KOKO committed Jun 27, 2019
1 parent 918ce32 commit e0a446c
Show file tree
Hide file tree
Showing 2 changed files with 15 additions and 1 deletion.
7 changes: 7 additions & 0 deletions arch/x86/mm/fault.c
Original file line number Diff line number Diff line change
Expand Up @@ -710,6 +710,10 @@ static void set_signal_archinfo(unsigned long address,
* To avoid leaking information about the kernel page
* table layout, pretend that user-mode accesses to
* kernel addresses are always protection faults.
*
* NB: This means that failed vsyscalls with vsyscall=none
* will have the PROT bit. This doesn't leak any
* information and does not appear to cause any problems.
*/
if (address >= TASK_SIZE_MAX)
error_code |= X86_PF_PROT;
Expand Down Expand Up @@ -1375,6 +1379,9 @@ void do_user_addr_fault(struct pt_regs *regs,
*
* The vsyscall page does not have a "real" VMA, so do this
* emulation before we go searching for VMAs.
*
* PKRU never rejects instruction fetches, so we don't need
* to consider the PF_PK bit.
*/
if (is_vsyscall_vaddr(address)) {
if (emulate_vsyscall(hw_error_code, regs, address))
Expand Down
9 changes: 8 additions & 1 deletion tools/testing/selftests/x86/test_vsyscall.c
Original file line number Diff line number Diff line change
Expand Up @@ -183,9 +183,13 @@ static inline long sys_getcpu(unsigned * cpu, unsigned * node,
}

static jmp_buf jmpbuf;
static volatile unsigned long segv_err;

static void sigsegv(int sig, siginfo_t *info, void *ctx_void)
{
ucontext_t *ctx = (ucontext_t *)ctx_void;

segv_err = ctx->uc_mcontext.gregs[REG_ERR];
siglongjmp(jmpbuf, 1);
}

Expand Down Expand Up @@ -416,8 +420,11 @@ static int test_vsys_r(void)
} else if (!can_read && should_read_vsyscall) {
printf("[FAIL]\tWe don't have read access, but we should\n");
return 1;
} else if (can_read) {
printf("[OK]\tWe have read access\n");
} else {
printf("[OK]\tgot expected result\n");
printf("[OK]\tWe do not have read access: #PF(0x%lx)\n",
segv_err);
}
#endif

Expand Down

0 comments on commit e0a446c

Please sign in to comment.