From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1753629AbbCJUxn (ORCPT ); Tue, 10 Mar 2015 16:53:43 -0400 Received: from mail-qc0-f174.google.com ([209.85.216.174]:40519 "EHLO mail-qc0-f174.google.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1753381AbbCJUxJ (ORCPT ); Tue, 10 Mar 2015 16:53:09 -0400 MIME-Version: 1.0 In-Reply-To: References: <54FF4244.5080600@redhat.com> From: Denys Vlasenko Date: Tue, 10 Mar 2015 21:52:48 +0100 Message-ID: Subject: Re: [PATCH 3/3] x86_32: Document our abuse of ss1 and sp1 To: Andy Lutomirski Cc: Denys Vlasenko , X86 ML , "linux-kernel@vger.kernel.org" , Borislav Petkov , Oleg Nesterov Content-Type: text/plain; charset=UTF-8 Sender: linux-kernel-owner@vger.kernel.org List-ID: X-Mailing-List: linux-kernel@vger.kernel.org On Tue, Mar 10, 2015 at 9:06 PM, Andy Lutomirski wrote: >> .ss1 also seems to be a write-only field: >> >> $ grep -r '[.>]ss1' . >> ./include/asm/processor.h: if (unlikely(tss->x86_tss.ss1 != thread->sysenter_cs)) { > > This is a read :) You are right. >> ./include/asm/processor.h: tss->x86_tss.ss1 = thread->sysenter_cs; >> ./include/asm/processor.h: .ss1 = __KERNEL_CS, \ >> ./kernel/cpu/common.c: tss->x86_tss.ss1 = __KERNEL_CS; >>> + * but we need to context switch it because we do >>> + * horrible things to the kernel stack in vm86 mode. >>> + * >>> + * We use SYSENTER_CS to disable sysenter in vm86 mode to avoid >>> + * corrupting the stack if we went through the sysenter path >>> + * from vm86 mode. >>> + */ >> >> I'm confused how loading ss1/sp1 with anything can disable sysenter. >> SYSENTER insn does not use those fields. >> >> What you _can_ disable is you can make it impossible to enter RING1 >> if tss.ss1 is invalid. > > Does it make sense now that I pointed out the read of ss1? If not, > I'll improve the comments. I propose the following comment about tss.ss1: /* tss.ss1 is used to avoid redundant wrmsr(MSR_IA32_SYSENTER_CS). After wrmsr, tss.ss1 is set to the written value. If on future task switches tss.ss1 already contains the value to be written, wrmsr is skipped. */ >>> + * We use SYSENTER_CS to disable sysenter in vm86 mode to avoid >>> + * corrupting the stack if we went through the sysenter path >>> + * from vm86 mode. This appears to be untrue - SYSENTER_CS isn't used to disable sysenter. Zero is. Disabling sysenter happens in vm86_32.c here, by setting it to 0: static void do_sys_vm86(struct kernel_vm86_struct *info, struct task_struct *tsk) { ... if (cpu_has_sep) tsk->thread.sysenter_cs = 0; load_sp0(tss, &tsk->thread); <-- this sets wrmsr(MSR_IA32_SYSENTER_CS, 0); ...