From patchwork Wed May 20 07:53:50 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 8bit X-Patchwork-Submitter: Jan Beulich X-Patchwork-Id: 11559597 Return-Path: Received: from mail.kernel.org (pdx-korg-mail-1.web.codeaurora.org [172.30.200.123]) by pdx-korg-patchwork-2.web.codeaurora.org (Postfix) with ESMTP id 756B4138A for ; Wed, 20 May 2020 07:54:27 +0000 (UTC) Received: from lists.xenproject.org (lists.xenproject.org [192.237.175.120]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by mail.kernel.org (Postfix) with ESMTPS id 516DE207ED for ; Wed, 20 May 2020 07:54:27 +0000 (UTC) DMARC-Filter: OpenDMARC Filter v1.3.2 mail.kernel.org 516DE207ED Authentication-Results: mail.kernel.org; dmarc=none (p=none dis=none) header.from=suse.com Authentication-Results: mail.kernel.org; spf=pass smtp.mailfrom=xen-devel-bounces@lists.xenproject.org Received: from localhost ([127.0.0.1] helo=lists.xenproject.org) by lists.xenproject.org with esmtp (Exim 4.92) (envelope-from ) id 1jbJY0-0004Ei-4m; Wed, 20 May 2020 07:53:52 +0000 Received: from us1-rack-iad1.inumbo.com ([172.99.69.81]) by lists.xenproject.org with esmtp (Exim 4.92) (envelope-from ) id 1jbJXy-0004Ed-Pz for xen-devel@lists.xenproject.org; Wed, 20 May 2020 07:53:50 +0000 X-Inumbo-ID: 0a86d896-9a6f-11ea-9887-bc764e2007e4 Received: from mx2.suse.de (unknown [195.135.220.15]) by us1-rack-iad1.inumbo.com (Halon) with ESMTPS id 0a86d896-9a6f-11ea-9887-bc764e2007e4; Wed, 20 May 2020 07:53:50 +0000 (UTC) X-Virus-Scanned: by amavisd-new at test-mx.suse.de Received: from relay2.suse.de (unknown [195.135.220.254]) by mx2.suse.de (Postfix) with ESMTP id E3BC7ACED; Wed, 20 May 2020 07:53:51 +0000 (UTC) Subject: [PATCH v3 1/3] x86: relax GDT check in arch_set_info_guest() From: Jan Beulich To: "xen-devel@lists.xenproject.org" References: Message-ID: Date: Wed, 20 May 2020 09:53:50 +0200 User-Agent: Mozilla/5.0 (Windows NT 6.1; WOW64; rv:68.0) Gecko/20100101 Thunderbird/68.8.0 MIME-Version: 1.0 In-Reply-To: Content-Language: en-US X-BeenThere: xen-devel@lists.xenproject.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: Xen developer discussion List-Unsubscribe: , List-Post: List-Help: List-Subscribe: , Cc: Andrew Cooper , Wei Liu , =?utf-8?q?Roger_Pau_Monn=C3=A9?= Errors-To: xen-devel-bounces@lists.xenproject.org Sender: "Xen-devel" It is wrong for us to check frames beyond the guest specified limit (in the compat case another loop bound is already correct). Signed-off-by: Jan Beulich Reviewed-by: Roger Pau Monné --- v3: Move nr_gdt_frames range check earlier. Avoid |= where not really needed. --- a/xen/arch/x86/domain.c +++ b/xen/arch/x86/domain.c @@ -840,6 +840,7 @@ int arch_set_info_guest( #ifdef CONFIG_PV mfn_t cr3_mfn; struct page_info *cr3_page = NULL; + unsigned int nr_gdt_frames; int rc = 0; #endif @@ -957,6 +958,10 @@ int arch_set_info_guest( /* Ensure real hardware interrupts are enabled. */ v->arch.user_regs.eflags |= X86_EFLAGS_IF; + nr_gdt_frames = DIV_ROUND_UP(c(gdt_ents), 512); + if ( nr_gdt_frames > ARRAY_SIZE(v->arch.pv.gdt_frames) ) + return -EINVAL; + if ( !v->is_initialised ) { if ( !compat && !(flags & VGCF_in_kernel) && !c.nat->ctrlreg[1] ) @@ -988,9 +993,9 @@ int arch_set_info_guest( fail = compat_pfn_to_cr3(pfn) != c.cmp->ctrlreg[3]; } - for ( i = 0; i < ARRAY_SIZE(v->arch.pv.gdt_frames); ++i ) - fail |= v->arch.pv.gdt_frames[i] != c(gdt_frames[i]); fail |= v->arch.pv.gdt_ents != c(gdt_ents); + for ( i = 0; !fail && i < nr_gdt_frames; ++i ) + fail = v->arch.pv.gdt_frames[i] != c(gdt_frames[i]); fail |= v->arch.pv.ldt_base != c(ldt_base); fail |= v->arch.pv.ldt_ents != c(ldt_ents); @@ -1095,12 +1100,8 @@ int arch_set_info_guest( else { unsigned long gdt_frames[ARRAY_SIZE(v->arch.pv.gdt_frames)]; - unsigned int nr_frames = DIV_ROUND_UP(c.cmp->gdt_ents, 512); - - if ( nr_frames > ARRAY_SIZE(v->arch.pv.gdt_frames) ) - return -EINVAL; - for ( i = 0; i < nr_frames; ++i ) + for ( i = 0; i < nr_gdt_frames; ++i ) gdt_frames[i] = c.cmp->gdt_frames[i]; rc = (int)pv_set_gdt(v, gdt_frames, c.cmp->gdt_ents); From patchwork Wed May 20 07:54:14 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 8bit X-Patchwork-Submitter: Jan Beulich X-Patchwork-Id: 11559599 Return-Path: Received: from mail.kernel.org (pdx-korg-mail-1.web.codeaurora.org [172.30.200.123]) by pdx-korg-patchwork-2.web.codeaurora.org (Postfix) with ESMTP id DA23490 for ; Wed, 20 May 2020 07:54:51 +0000 (UTC) Received: from lists.xenproject.org (lists.xenproject.org [192.237.175.120]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by mail.kernel.org (Postfix) with ESMTPS id C0966207FB for ; Wed, 20 May 2020 07:54:51 +0000 (UTC) DMARC-Filter: OpenDMARC Filter v1.3.2 mail.kernel.org C0966207FB Authentication-Results: mail.kernel.org; dmarc=none (p=none dis=none) header.from=suse.com Authentication-Results: mail.kernel.org; spf=pass smtp.mailfrom=xen-devel-bounces@lists.xenproject.org Received: from localhost ([127.0.0.1] helo=lists.xenproject.org) by lists.xenproject.org with esmtp (Exim 4.92) (envelope-from ) id 1jbJYO-0004Go-DI; Wed, 20 May 2020 07:54:16 +0000 Received: from us1-rack-iad1.inumbo.com ([172.99.69.81]) by lists.xenproject.org with esmtp (Exim 4.92) (envelope-from ) id 1jbJYN-0004Gf-CS for xen-devel@lists.xenproject.org; Wed, 20 May 2020 07:54:15 +0000 X-Inumbo-ID: 193cb860-9a6f-11ea-b07b-bc764e2007e4 Received: from mx2.suse.de (unknown [195.135.220.15]) by us1-rack-iad1.inumbo.com (Halon) with ESMTPS id 193cb860-9a6f-11ea-b07b-bc764e2007e4; Wed, 20 May 2020 07:54:14 +0000 (UTC) X-Virus-Scanned: by amavisd-new at test-mx.suse.de Received: from relay2.suse.de (unknown [195.135.220.254]) by mx2.suse.de (Postfix) with ESMTP id A9D38AC37; Wed, 20 May 2020 07:54:16 +0000 (UTC) Subject: [PATCH v3 2/3] x86: relax LDT check in arch_set_info_guest() From: Jan Beulich To: "xen-devel@lists.xenproject.org" References: Message-ID: <802123c8-026d-ba84-5f0d-0faecd5a46a9@suse.com> Date: Wed, 20 May 2020 09:54:14 +0200 User-Agent: Mozilla/5.0 (Windows NT 6.1; WOW64; rv:68.0) Gecko/20100101 Thunderbird/68.8.0 MIME-Version: 1.0 In-Reply-To: Content-Language: en-US X-BeenThere: xen-devel@lists.xenproject.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: Xen developer discussion List-Unsubscribe: , List-Post: List-Help: List-Subscribe: , Cc: Andrew Cooper , Wei Liu , =?utf-8?q?Roger_Pau_Monn=C3=A9?= Errors-To: xen-devel-bounces@lists.xenproject.org Sender: "Xen-devel" It is wrong for us to check the base address when there's no LDT in the first place. Once we don't do this check anymore we can also set the base address to a non-canonical value when the LDT is empty. Signed-off-by: Jan Beulich Reviewed-by: Roger Pau Monné --- v3: Re-base over changes to earlier patch. v2: Set v->arch.pv.ldt_base to non-canonical for an empty LDT, plus related necessary adjustments. --- a/xen/arch/x86/domain.c +++ b/xen/arch/x86/domain.c @@ -967,8 +967,10 @@ int arch_set_info_guest( if ( !compat && !(flags & VGCF_in_kernel) && !c.nat->ctrlreg[1] ) return -EINVAL; - v->arch.pv.ldt_base = c(ldt_base); v->arch.pv.ldt_ents = c(ldt_ents); + v->arch.pv.ldt_base = v->arch.pv.ldt_ents + ? c(ldt_base) + : (unsigned long)ZERO_BLOCK_PTR; } else { @@ -997,8 +999,9 @@ int arch_set_info_guest( for ( i = 0; !fail && i < nr_gdt_frames; ++i ) fail = v->arch.pv.gdt_frames[i] != c(gdt_frames[i]); - fail |= v->arch.pv.ldt_base != c(ldt_base); fail |= v->arch.pv.ldt_ents != c(ldt_ents); + if ( v->arch.pv.ldt_ents ) + fail |= v->arch.pv.ldt_base != c(ldt_base); if ( fail ) return -EOPNOTSUPP; --- a/xen/arch/x86/domctl.c +++ b/xen/arch/x86/domctl.c @@ -1583,7 +1583,7 @@ void arch_get_info_guest(struct vcpu *v, } else { - c(ldt_base = v->arch.pv.ldt_base); + c(ldt_base = v->arch.pv.ldt_ents ? v->arch.pv.ldt_base : 0); c(ldt_ents = v->arch.pv.ldt_ents); for ( i = 0; i < ARRAY_SIZE(v->arch.pv.gdt_frames); ++i ) c(gdt_frames[i] = v->arch.pv.gdt_frames[i]); --- a/xen/arch/x86/mm.c +++ b/xen/arch/x86/mm.c @@ -3669,14 +3669,15 @@ long do_mmuext_op( case MMUEXT_SET_LDT: { unsigned int ents = op.arg2.nr_ents; - unsigned long ptr = ents ? op.arg1.linear_addr : 0; + unsigned long ptr = ents ? op.arg1.linear_addr + : (unsigned long)ZERO_BLOCK_PTR; if ( unlikely(currd != pg_owner) ) rc = -EPERM; else if ( paging_mode_external(currd) ) rc = -EINVAL; - else if ( ((ptr & (PAGE_SIZE - 1)) != 0) || !__addr_ok(ptr) || - (ents > 8192) ) + else if ( (ents > 8192) || + (ents && ((ptr & (PAGE_SIZE - 1)) || !__addr_ok(ptr))) ) { gdprintk(XENLOG_WARNING, "Bad args to SET_LDT: ptr=%lx, ents=%x\n", ptr, ents); From patchwork Wed May 20 07:54:39 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Jan Beulich X-Patchwork-Id: 11559601 Return-Path: Received: from mail.kernel.org (pdx-korg-mail-1.web.codeaurora.org [172.30.200.123]) by pdx-korg-patchwork-2.web.codeaurora.org (Postfix) with ESMTP id DC46D138A for ; Wed, 20 May 2020 07:55:14 +0000 (UTC) Received: from lists.xenproject.org (lists.xenproject.org [192.237.175.120]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by mail.kernel.org (Postfix) with ESMTPS id C253C207ED for ; Wed, 20 May 2020 07:55:14 +0000 (UTC) DMARC-Filter: OpenDMARC Filter v1.3.2 mail.kernel.org C253C207ED Authentication-Results: mail.kernel.org; dmarc=none (p=none dis=none) header.from=suse.com Authentication-Results: mail.kernel.org; spf=pass smtp.mailfrom=xen-devel-bounces@lists.xenproject.org Received: from localhost ([127.0.0.1] helo=lists.xenproject.org) by lists.xenproject.org with esmtp (Exim 4.92) (envelope-from ) id 1jbJYo-0004Ke-MS; Wed, 20 May 2020 07:54:42 +0000 Received: from all-amaz-eas1.inumbo.com ([34.197.232.57] helo=us1-amaz-eas2.inumbo.com) by lists.xenproject.org with esmtp (Exim 4.92) (envelope-from ) id 1jbJYm-0004KP-S6 for xen-devel@lists.xenproject.org; Wed, 20 May 2020 07:54:40 +0000 X-Inumbo-ID: 2822b28a-9a6f-11ea-a9cc-12813bfff9fa Received: from mx2.suse.de (unknown [195.135.220.15]) by us1-amaz-eas2.inumbo.com (Halon) with ESMTPS id 2822b28a-9a6f-11ea-a9cc-12813bfff9fa; Wed, 20 May 2020 07:54:39 +0000 (UTC) X-Virus-Scanned: by amavisd-new at test-mx.suse.de Received: from relay2.suse.de (unknown [195.135.220.254]) by mx2.suse.de (Postfix) with ESMTP id 7345DAC37; Wed, 20 May 2020 07:54:41 +0000 (UTC) Subject: [PATCH v3 3/3] x86/PV: polish pv_set_gdt() From: Jan Beulich To: "xen-devel@lists.xenproject.org" References: Message-ID: Date: Wed, 20 May 2020 09:54:39 +0200 User-Agent: Mozilla/5.0 (Windows NT 6.1; WOW64; rv:68.0) Gecko/20100101 Thunderbird/68.8.0 MIME-Version: 1.0 In-Reply-To: Content-Language: en-US X-BeenThere: xen-devel@lists.xenproject.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: Xen developer discussion List-Unsubscribe: , List-Post: List-Help: List-Subscribe: , Cc: Andrew Cooper , Wei Liu , =?utf-8?q?Roger_Pau_Monn=C3=A9?= Errors-To: xen-devel-bounces@lists.xenproject.org Sender: "Xen-devel" There's no need to invoke get_page_from_gfn(), and there's also no need to update the passed in frames[]. Invoke get_page_and_type() directly. Also make the function's frames[] parameter const, change its return type to int, and drop the bogus casts from two of its invocations. Finally a little bit of cosmetics. Signed-off-by: Jan Beulich Acked-by: Andrew Cooper --- a/xen/arch/x86/domain.c +++ b/xen/arch/x86/domain.c @@ -1099,7 +1099,7 @@ int arch_set_info_guest( return rc; if ( !compat ) - rc = (int)pv_set_gdt(v, c.nat->gdt_frames, c.nat->gdt_ents); + rc = pv_set_gdt(v, c.nat->gdt_frames, c.nat->gdt_ents); else { unsigned long gdt_frames[ARRAY_SIZE(v->arch.pv.gdt_frames)]; @@ -1107,7 +1107,7 @@ int arch_set_info_guest( for ( i = 0; i < nr_gdt_frames; ++i ) gdt_frames[i] = c.cmp->gdt_frames[i]; - rc = (int)pv_set_gdt(v, gdt_frames, c.cmp->gdt_ents); + rc = pv_set_gdt(v, gdt_frames, c.cmp->gdt_ents); } if ( rc != 0 ) return rc; --- a/xen/arch/x86/pv/descriptor-tables.c +++ b/xen/arch/x86/pv/descriptor-tables.c @@ -81,7 +81,8 @@ void pv_destroy_gdt(struct vcpu *v) } } -long pv_set_gdt(struct vcpu *v, unsigned long *frames, unsigned int entries) +int pv_set_gdt(struct vcpu *v, const unsigned long frames[], + unsigned int entries) { struct domain *d = v->domain; l1_pgentry_t *pl1e; @@ -95,17 +96,11 @@ long pv_set_gdt(struct vcpu *v, unsigned /* Check the pages in the new GDT. */ for ( i = 0; i < nr_frames; i++ ) { - struct page_info *page; + mfn_t mfn = _mfn(frames[i]); - page = get_page_from_gfn(d, frames[i], NULL, P2M_ALLOC); - if ( !page ) + if ( !mfn_valid(mfn) || + !get_page_and_type(mfn_to_page(mfn), d, PGT_seg_desc_page) ) goto fail; - if ( !get_page_type(page, PGT_seg_desc_page) ) - { - put_page(page); - goto fail; - } - frames[i] = mfn_x(page_to_mfn(page)); } /* Tear down the old GDT. */ @@ -124,9 +119,8 @@ long pv_set_gdt(struct vcpu *v, unsigned fail: while ( i-- > 0 ) - { put_page_and_type(mfn_to_page(_mfn(frames[i]))); - } + return -EINVAL; } --- a/xen/include/asm-x86/pv/mm.h +++ b/xen/include/asm-x86/pv/mm.h @@ -25,7 +25,8 @@ int pv_ro_page_fault(unsigned long addr, struct cpu_user_regs *regs); -long pv_set_gdt(struct vcpu *v, unsigned long *frames, unsigned int entries); +int pv_set_gdt(struct vcpu *v, const unsigned long frames[], + unsigned int entries); void pv_destroy_gdt(struct vcpu *v); bool pv_map_ldt_shadow_page(unsigned int off); @@ -43,8 +44,8 @@ static inline int pv_ro_page_fault(unsig return 0; } -static inline long pv_set_gdt(struct vcpu *v, unsigned long *frames, - unsigned int entries) +static inline int pv_set_gdt(struct vcpu *v, const unsigned long frames[], + unsigned int entries) { ASSERT_UNREACHABLE(); return -EINVAL; } static inline void pv_destroy_gdt(struct vcpu *v) { ASSERT_UNREACHABLE(); }