[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index] Re: [PATCH 02/17] x86: split __{get,put}_user() into "guest" and "unsafe" variants
On Thu, Jan 14, 2021 at 04:04:11PM +0100, Jan Beulich wrote: > The "guest" variants are intended to work with (potentially) fully guest > controlled addresses, while the "unsafe" variants are not. (For > descriptor table accesses the low bits of the addresses may still be > guest controlled, but this still won't allow speculation to "escape" > into unwanted areas.) Descriptor table is also in guest address space, and hence would be fine using the _guest accessors? (even if not in guest control and thus unsuitable as an speculation vector) > Subsequently we will want them to have different > behavior, so as first step identify which one is which. For now, both > groups of constructs alias one another. > > Double underscore prefixes are retained only on __{get,put}_guest(), to > allow still distinguishing them from their "checking" counterparts once > they also get renamed (to {get,put}_guest()). > > Since for them it's almost a full re-write, move what becomes > {get,put}_unsafe_size() into the "common" uaccess.h (x86_64/*.h should > disappear at some point anyway). > > In __copy_to_user() one of the two casts in each put_guest_size() > invocation gets dropped. They're not needed and did break symmetry with > __copy_from_user(). > > Signed-off-by: Jan Beulich <jbeulich@xxxxxxxx> > > --- a/xen/arch/x86/mm/shadow/multi.c > +++ b/xen/arch/x86/mm/shadow/multi.c > @@ -776,9 +776,9 @@ shadow_write_entries(void *d, void *s, i > /* Because we mirror access rights at all levels in the shadow, an > * l2 (or higher) entry with the RW bit cleared will leave us with > * no write access through the linear map. > - * We detect that by writing to the shadow with __put_user() and > + * We detect that by writing to the shadow with put_unsafe() and > * using map_domain_page() to get a writeable mapping if we need to. */ > - if ( __put_user(*dst, dst) ) > + if ( put_unsafe(*dst, dst) ) > { > perfc_incr(shadow_linear_map_failed); > map = map_domain_page(mfn); > --- a/xen/arch/x86/pv/emul-gate-op.c > +++ b/xen/arch/x86/pv/emul-gate-op.c > @@ -40,7 +40,7 @@ static int read_gate_descriptor(unsigned > ((gate_sel >> 3) + !is_pv_32bit_vcpu(v) >= > (gate_sel & 4 ? v->arch.pv.ldt_ents > : v->arch.pv.gdt_ents)) || > - __get_user(desc, pdesc) ) > + get_unsafe(desc, pdesc) ) > return 0; > > *sel = (desc.a >> 16) & 0x0000fffc; > @@ -59,7 +59,7 @@ static int read_gate_descriptor(unsigned > { > if ( (*ar & 0x1f00) != 0x0c00 || > /* Limit check done above already. */ > - __get_user(desc, pdesc + 1) || > + get_unsafe(desc, pdesc + 1) || > (desc.b & 0x1f00) ) > return 0; > > @@ -294,7 +294,7 @@ void pv_emulate_gate_op(struct cpu_user_ > { \ > --stkp; \ > esp -= 4; \ > - rc = __put_user(item, stkp); \ > + rc = __put_guest(item, stkp); \ > if ( rc ) \ > { \ > pv_inject_page_fault(PFEC_write_access, \ > @@ -362,7 +362,7 @@ void pv_emulate_gate_op(struct cpu_user_ > unsigned int parm; > > --ustkp; > - rc = __get_user(parm, ustkp); > + rc = __get_guest(parm, ustkp); > if ( rc ) > { > pv_inject_page_fault(0, (unsigned long)(ustkp + 1) - > rc); > --- a/xen/arch/x86/pv/emulate.c > +++ b/xen/arch/x86/pv/emulate.c > @@ -34,13 +34,13 @@ int pv_emul_read_descriptor(unsigned int > if ( sel < 4 || > /* > * Don't apply the GDT limit here, as the selector may be a Xen > - * provided one. __get_user() will fail (without taking further > + * provided one. get_unsafe() will fail (without taking further > * action) for ones falling in the gap between guest populated > * and Xen ones. > */ > ((sel & 4) && (sel >> 3) >= v->arch.pv.ldt_ents) ) > desc.b = desc.a = 0; > - else if ( __get_user(desc, gdt_ldt_desc_ptr(sel)) ) > + else if ( get_unsafe(desc, gdt_ldt_desc_ptr(sel)) ) > return 0; > if ( !insn_fetch ) > desc.b &= ~_SEGMENT_L; > --- a/xen/arch/x86/pv/iret.c > +++ b/xen/arch/x86/pv/iret.c > @@ -114,15 +114,15 @@ unsigned int compat_iret(void) > regs->rsp = (u32)regs->rsp; > > /* Restore EAX (clobbered by hypercall). */ > - if ( unlikely(__get_user(regs->eax, (u32 *)regs->rsp)) ) > + if ( unlikely(__get_guest(regs->eax, (u32 *)regs->rsp)) ) > { > domain_crash(v->domain); > return 0; > } > > /* Restore CS and EIP. */ > - if ( unlikely(__get_user(regs->eip, (u32 *)regs->rsp + 1)) || > - unlikely(__get_user(regs->cs, (u32 *)regs->rsp + 2)) ) > + if ( unlikely(__get_guest(regs->eip, (u32 *)regs->rsp + 1)) || > + unlikely(__get_guest(regs->cs, (u32 *)regs->rsp + 2)) ) > { > domain_crash(v->domain); > return 0; > @@ -132,7 +132,7 @@ unsigned int compat_iret(void) > * Fix up and restore EFLAGS. We fix up in a local staging area > * to avoid firing the BUG_ON(IOPL) check in arch_get_info_guest. > */ > - if ( unlikely(__get_user(eflags, (u32 *)regs->rsp + 3)) ) > + if ( unlikely(__get_guest(eflags, (u32 *)regs->rsp + 3)) ) > { > domain_crash(v->domain); > return 0; > @@ -164,16 +164,16 @@ unsigned int compat_iret(void) > { > for (i = 1; i < 10; ++i) > { > - rc |= __get_user(x, (u32 *)regs->rsp + i); > - rc |= __put_user(x, (u32 *)(unsigned long)ksp + i); > + rc |= __get_guest(x, (u32 *)regs->rsp + i); > + rc |= __put_guest(x, (u32 *)(unsigned long)ksp + i); > } > } > else if ( ksp > regs->esp ) > { > for ( i = 9; i > 0; --i ) > { > - rc |= __get_user(x, (u32 *)regs->rsp + i); > - rc |= __put_user(x, (u32 *)(unsigned long)ksp + i); > + rc |= __get_guest(x, (u32 *)regs->rsp + i); > + rc |= __put_guest(x, (u32 *)(unsigned long)ksp + i); > } > } > if ( rc ) > @@ -189,7 +189,7 @@ unsigned int compat_iret(void) > eflags &= ~X86_EFLAGS_IF; > regs->eflags &= ~(X86_EFLAGS_VM|X86_EFLAGS_RF| > X86_EFLAGS_NT|X86_EFLAGS_TF); > - if ( unlikely(__put_user(0, (u32 *)regs->rsp)) ) > + if ( unlikely(__put_guest(0, (u32 *)regs->rsp)) ) > { > domain_crash(v->domain); > return 0; > @@ -205,8 +205,8 @@ unsigned int compat_iret(void) > else if ( ring_1(regs) ) > regs->esp += 16; > /* Return to ring 2/3: restore ESP and SS. */ > - else if ( __get_user(regs->ss, (u32 *)regs->rsp + 5) || > - __get_user(regs->esp, (u32 *)regs->rsp + 4) ) > + else if ( __get_guest(regs->ss, (u32 *)regs->rsp + 5) || > + __get_guest(regs->esp, (u32 *)regs->rsp + 4) ) > { > domain_crash(v->domain); > return 0; > --- a/xen/arch/x86/traps.c > +++ b/xen/arch/x86/traps.c > @@ -274,7 +274,7 @@ static void compat_show_guest_stack(stru > { > if ( (((long)stack - 1) ^ ((long)(stack + 1) - 1)) & mask ) > break; > - if ( __get_user(addr, stack) ) > + if ( get_unsafe(addr, stack) ) > { > if ( i != 0 ) > printk("\n "); > @@ -343,7 +343,7 @@ static void show_guest_stack(struct vcpu > { > if ( (((long)stack - 1) ^ ((long)(stack + 1) - 1)) & mask ) > break; > - if ( __get_user(addr, stack) ) > + if ( get_unsafe(addr, stack) ) Shouldn't accessing the guest stack use the _guest accessors? Or has this address been verified by Xen and not in idrect control of the guest, and thus can't be used for speculation purposes? I feel like this should be using the _guest accessors anyway, as the guest stack is an address in guest space? Thanks, Roger.
|
Lists.xenproject.org is hosted with RackSpace, monitoring our |