Received: by 2002:ad5:474a:0:0:0:0:0 with SMTP id i10csp1018192imu; Fri, 9 Nov 2018 09:36:35 -0800 (PST) X-Google-Smtp-Source: AJdET5cKGyAjyDHlCnLKJqzy5iAoH6ygbQMuhBuumuhwyMZX6Z8Ge3ysrUfL4/2CRAfq3uQxBnNU X-Received: by 2002:a63:ea07:: with SMTP id c7-v6mr7882231pgi.361.1541784995158; Fri, 09 Nov 2018 09:36:35 -0800 (PST) ARC-Seal: i=1; a=rsa-sha256; t=1541784995; cv=none; d=google.com; s=arc-20160816; b=j97saSNsW2JVoTZZZePIsJZt+Be6SVgqAmJHMNtim8GfpoQKTUgcrbHALoby8NK8BK VAWPMZEp+Ug+H6yg6ubkKUdGOEZam1cYcvxENBzxnIuGyr79AXcxlX09PQ9eXzGDwVNN NENRFVTG39K2fnLJuCnP6PGgo/0gXweMAgIZP1zAcZCbzUIJv3JSTMQZ+sYWqMm7Te6f Cr2yXu8UMfx1rHVCAhuWZ7X6rTIquorkdNggt3tI70pISkBq/aiXn3ejairQ+fAJWzew thEg6mO86G2fXj8r7oe4FlOqa1aFTImqzIwYIpj6qO9CEkCavGYnPIGdyUXU3KGsCJ1Y 2z3Q== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20160816; h=list-id:precedence:sender:user-agent:in-reply-to :content-transfer-encoding:content-disposition:mime-version :references:message-id:subject:cc:to:from:date; bh=0GIqITUbTAnB7CbJyjwDzfraWcQmxcmzj4SfbJSzBGM=; b=YjYp3brA2OK958VfN9z8TZ/t0cCfGLDqqt6J9ySuCyWPv9TwLqceqxMeLlUR1d7RyV ttl0EFOf+sE+DlVf5NhXrvOp1nmd1cHhiksxNpgxogdqAkb5LbIMN7vFC1b1UE6m7qBR k2GLNoo8V2vPZkLDxPJI4WGva0qMHXrqBe34cZhDXapSGDnDST8w1BDTSSCpDljJAw1L RdCyDwWDcxHFa8sADDhxWDimrY4+XnHa8IeTSqUeIcEc4rzdhaCrHpuQ/RP+N9MqybxR fUq/t6o/PR4+Gvlw7C1j5m0IklwELqg0nULN5cImUbrR5bt9O4qOnRYN5dsez98UGMPl z/Mg== ARC-Authentication-Results: i=1; mx.google.com; spf=pass (google.com: best guess record for domain of linux-kernel-owner@vger.kernel.org designates 209.132.180.67 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org Return-Path: Received: from vger.kernel.org (vger.kernel.org. [209.132.180.67]) by mx.google.com with ESMTP id u28si7785424pgn.436.2018.11.09.09.36.02; Fri, 09 Nov 2018 09:36:35 -0800 (PST) Received-SPF: pass (google.com: best guess record for domain of linux-kernel-owner@vger.kernel.org designates 209.132.180.67 as permitted sender) client-ip=209.132.180.67; Authentication-Results: mx.google.com; spf=pass (google.com: best guess record for domain of linux-kernel-owner@vger.kernel.org designates 209.132.180.67 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1728581AbeKJDRA convert rfc822-to-8bit (ORCPT + 99 others); Fri, 9 Nov 2018 22:17:00 -0500 Received: from Galois.linutronix.de ([146.0.238.70]:47494 "EHLO Galois.linutronix.de" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1728430AbeKJDRA (ORCPT ); Fri, 9 Nov 2018 22:17:00 -0500 Received: from bigeasy by Galois.linutronix.de with local (Exim 4.80) (envelope-from ) id 1gLAgj-00015V-DS; Fri, 09 Nov 2018 18:35:21 +0100 Date: Fri, 9 Nov 2018 18:35:21 +0100 From: Sebastian Andrzej Siewior To: Borislav Petkov Cc: linux-kernel@vger.kernel.org, x86@kernel.org, Andy Lutomirski , Paolo Bonzini , Radim =?utf-8?B?S3LEjW3DocWZ?= , kvm@vger.kernel.org, "Jason A. Donenfeld" , Rik van Riel , Dave Hansen Subject: Re: [PATCH 02/23] x86/fpu: Remove fpu->initialized usage in __fpu__restore_sig() Message-ID: <20181109173521.2m6iijp5wkncgi77@linutronix.de> References: <20181107194858.9380-1-bigeasy@linutronix.de> <20181107194858.9380-3-bigeasy@linutronix.de> <20181108145721.GC7543@zn.tnic> MIME-Version: 1.0 Content-Type: text/plain; charset=utf-8 Content-Disposition: inline Content-Transfer-Encoding: 8BIT In-Reply-To: <20181108145721.GC7543@zn.tnic> User-Agent: NeoMutt/20180716 Sender: linux-kernel-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-kernel@vger.kernel.org On 2018-11-08 15:57:21 [+0100], Borislav Petkov wrote: > On Wed, Nov 07, 2018 at 08:48:37PM +0100, Sebastian Andrzej Siewior wrote: > > This is a preparation for the removal of the ->initialized member in the > > fpu struct. > > __fpu__restore_sig() is deactivating the FPU via fpu__drop() and then > > setting manually ->initialized followed by fpu__restore(). The result is > > that it is possible to manipulate fpu->state and the state of registers > > won't be saved/restore on a context switch which would overwrite state. > > restored > > > > > Don't access the fpu->state while the content is read from user space > > and examined / sanitized. Use a temporary buffer kmalloc() buffer for > > one "buffer" too many. corrected. > More importantly, what I'm missing here is more detailed explanation > about how that manipulation can happen. Especially since the comment > over fpu__drop() you're removing below is claiming the exact opposite. > AFAICT. fpu__drop() stets ->initialized to 0. As a result the context switch will not save current FPU registers and so _not_ write to fpu->state. This also means that CPU's FPU register will be random (inherited from the last context) after the context switch. This is also true for usage in softirq via kernel_fpu_begin(). The "new" FPU state is prepared in fpu->state and once it is done, it gets loaded via fpu->initialized = 1; // make sure fpu__initialize() in fpu__restore() // is a nop fpu__restore(); // Load the registers. Since I plan to remove the ->initialized member, I don't have the luxury to play with fpu->state because the "new" content obtained by copy_from_user() will be overwritten with CPU's current FPU state during a context switch. Now with that information, what do you plan to alter? :) > Yeah, FPU code has always been nasty and tricky to follow so I think > we'd need to have this stuff explained in much more detail. Yeah, tell me about it. Now that you made me look into this again, I spotted this gem: | __fpu__restore_sig() … | if (ia32_fxstate) { … | fpu__drop(fpu); … | /* prepare new FPU state in fpu->state */ | | fpu->initialized = 1; *BOOM* context switch. ->initialized == 1 is seen so it stashes current CPU's FPU state into fpu->state and overwrites what has been prepared before. On the switch back to this task, the fpu__restore() becomes a "nop" because the saved registers are the same but not what was expected / prepared before. | preempt_disable(); | fpu__restore(fpu); | preempt_enable(); | So. The fix would be: @@ -344,10 +344,10 @@ static int __fpu__restore_sig(void __user *buf, void __user *buf_fx, int size) sanitize_restored_xstate(tsk, &env, xfeatures, fx_only); } + local_bh_disable(); fpu->initialized = 1; - preempt_disable(); fpu__restore(fpu); - preempt_enable(); + local_bh_enable(); return err; } else { local_bh_disable() due to possible kernel_fpu_begin() usage in softirq. How much do we care here about a theoretical race on 32bit anyway? I don't think someone complained :) I would have to rebase my queue… otherwise… > Thx. Sebastian