Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

xen/arm: call uaccess_ttbr0_enable for dm_op hypercall

dm_op hypercalls might come from userspace and pass memory addresses as
parameters. The memory addresses typically correspond to buffers
allocated in userspace to hold extra hypercall parameters.

On ARM, when CONFIG_ARM64_SW_TTBR0_PAN is enabled, they might not be
accessible by Xen, as a result ioreq hypercalls might fail. See the
existing comment in arch/arm64/xen/hypercall.S regarding privcmd_call
for reference.

For privcmd_call, Linux calls uaccess_ttbr0_enable before issuing the
hypercall thanks to commit 9cf09d68b89a. We need to do the same for
dm_op. This resolves the problem.

Cc: stable@kernel.org
Fixes: 9cf09d68b89a ("arm64: xen: Enable user access before a privcmd hvc call")
Signed-off-by: Stefano Stabellini <stefano.stabellini@amd.com>
Reviewed-by: Juergen Gross <jgross@suse.com>
Message-ID: <alpine.DEB.2.22.394.2505121446370.8380@ubuntu-linux-20-04-desktop>
Signed-off-by: Juergen Gross <jgross@suse.com>

authored by

Stefano Stabellini and committed by
Juergen Gross
7f9bbc11 74287971

+20 -1
+20 -1
arch/arm64/xen/hypercall.S
··· 83 83 HYPERCALL1(platform_op_raw); 84 84 HYPERCALL2(multicall); 85 85 HYPERCALL2(vm_assist); 86 - HYPERCALL3(dm_op); 86 + 87 + SYM_FUNC_START(HYPERVISOR_dm_op) 88 + mov x16, #__HYPERVISOR_dm_op; \ 89 + /* 90 + * dm_op hypercalls are issued by the userspace. The kernel needs to 91 + * enable access to TTBR0_EL1 as the hypervisor would issue stage 1 92 + * translations to user memory via AT instructions. Since AT 93 + * instructions are not affected by the PAN bit (ARMv8.1), we only 94 + * need the explicit uaccess_enable/disable if the TTBR0 PAN emulation 95 + * is enabled (it implies that hardware UAO and PAN disabled). 96 + */ 97 + uaccess_ttbr0_enable x6, x7, x8 98 + hvc XEN_IMM 99 + 100 + /* 101 + * Disable userspace access from kernel once the hyp call completed. 102 + */ 103 + uaccess_ttbr0_disable x6, x7 104 + ret 105 + SYM_FUNC_END(HYPERVISOR_dm_op); 87 106 88 107 SYM_FUNC_START(privcmd_call) 89 108 mov x16, x0