On Tue, Aug 15, 2017 at 5:23 PM, Sai Praneeth Prakhya <sai.praneeth.prakhya@xxxxxxxxx> wrote: > On Tue, 2017-08-15 at 14:46 -0700, Andy Lutomirski wrote: >> On Tue, Aug 15, 2017 at 12:18 PM, Sai Praneeth Prakhya >> <sai.praneeth.prakhya@xxxxxxxxx> wrote: >> > +/* >> > + * Makes the calling kernel thread switch to/from efi_mm context >> > + * Can be used from SetVirtualAddressMap() or during efi runtime calls >> > + * (Note: This routine is heavily inspired from use_mm) >> > + */ >> > +void efi_switch_mm(struct mm_struct *mm) >> > +{ >> > + struct task_struct *tsk = current; >> > + >> > + task_lock(tsk); >> > + efi_scratch.prev_mm = tsk->active_mm; >> > + if (efi_scratch.prev_mm != mm) { >> > + mmgrab(mm); >> > + tsk->active_mm = mm; >> > + } >> > + switch_mm(efi_scratch.prev_mm, mm, NULL); >> > + task_unlock(tsk); >> > + >> > + if (efi_scratch.prev_mm != mm) >> > + mmdrop(efi_scratch.prev_mm); >> > > Thanks for the quick review Andy, > >> I'm confused. You're mmdropping an mm that you are still keeping a >> pointer to. This is also a bit confusing in the case where you do >> efi_switch_mm(efi_scratch.prev_mm). >> > > This makes sense, I will look into it. > >> This whole manipulation seems fairly dangerous to me for another >> reason -- you're taking a user thread (I think) and swapping out its >> mm to something that the user in question should *not* have access to. > > We are switching to efi_mm from user mm_struct because > EFI_RUNTIME_SERVICES like efi_set_variable()/efi_get_variable() are > accessible only through efi_pgd. The user thread calls ioctl() which in > turn calls efi_call() and thus efi_switch_mm(). So, I think, the user > still does not have direct access to EFI_RUNTIME_SERVICES memory regions > but accesses them through sys call. > >> What if a perf interrupt happens while you're in the alternate mm? > > Since we are disabling/enabling interrupts around switching, I think we > are safe. We do these in following functions > phys_efi_set_virtual_address_map() > efi_thunk_set_virtual_address_map() > efi_call_virt_pointer() perf uses NMI, so this doesn't help. Perhaps the sequence could look like this: local_irq_disable(); current->active_mm = efi_mm; switch_to(); ... switch_to(back to old mm); current->active_mm = old mm; and make perf know that current->active_mm != current->mm means that user memory is off limits. -- To unsubscribe from this list: send the line "unsubscribe linux-efi" in the body of a message to majordomo@xxxxxxxxxxxxxxx More majordomo info at http://vger.kernel.org/majordomo-info.html