Received: by 2002:ac0:a594:0:0:0:0:0 with SMTP id m20-v6csp806136imm; Mon, 21 May 2018 14:51:09 -0700 (PDT) X-Google-Smtp-Source: AB8JxZoaep//HINyOHkTs1O+S2gZxs9uskLXRFUBkkcmzm4rMy/IJw+2GoOqz1xfHvNrjvD6C+HS X-Received: by 2002:a17:902:8308:: with SMTP id bd8-v6mr14324171plb.195.1526939469539; Mon, 21 May 2018 14:51:09 -0700 (PDT) ARC-Seal: i=1; a=rsa-sha256; t=1526939469; cv=none; d=google.com; s=arc-20160816; b=RRa19VFN7vYN1rhieYXTKgzLqLV/iBk2VsOowKzbloXUAGWUjoT4FORen/fR8W3IxY bkkPwfR8P+f/8OsFYCZD5ZNErVqfkt+3X0SVGCWl2FZ7ivbT8nct3QJjFVcdk19PN32u UsRE7MtpkXe7lCYdEHXR4LEjkT3T0Bptac0NjwcuP99KifX0it9Bi2ZOkll9adCCcxAZ jAot8x1R3h6giiPgjt7oliYKG7akD9qy3ePYXqAk5hTKApgvIb/RP8K9zgz9pBaZbMag ZJrL4MuGZd/tcQUJzI1GKOSh7xil1axH5czfogIXWwMh24a8g1qsGU1hxyNvTUIBd0GW JFTA== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20160816; h=list-id:precedence:sender:mime-version:user-agent:references :in-reply-to:message-id:date:subject:cc:to:from:dkim-signature :arc-authentication-results; bh=yog8J7Qo2JFEmYEMZxNelD05518A1NlO2ni6S9Fb7z0=; b=fZsjz4RJhVUXuk5oETg03fylk0Qd0rRUbv3ZJAMMJGyOmEJqchwiV3kcLFGWtG1/HI y3DS5CohHVa2OchOdOWD6HQ/NJuC4MRXmXoz2cF9gdhBx+0HAS2uO3OC+7YYI2pE05U8 6ZL5c08z6u0KZlWT2LEWacduxLCTvFeZGlBhSOA+a2di8Qj8SA/nNJFMlsA8iAcU1+Go L+SNbbAumz8JVQuPFugzU4AXfbrSKsrs+86j/te0QKAIauuKJTCo1QqQGV0ZfmUrZSNV Pppxojnn+h4q/z9gmG3h+Rfwd24KbFehFRX+4FUVElRCGJR92LxmdfeZYmhKqfACu811 rFPw== ARC-Authentication-Results: i=1; mx.google.com; dkim=pass header.i=@kernel.org header.s=default header.b=h7+A7qZW; 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 u15-v6si15505627pfk.82.2018.05.21.14.50.54; Mon, 21 May 2018 14:51:09 -0700 (PDT) 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; dkim=pass header.i=@kernel.org header.s=default header.b=h7+A7qZW; 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 S932119AbeEUVXJ (ORCPT + 99 others); Mon, 21 May 2018 17:23:09 -0400 Received: from mail.kernel.org ([198.145.29.99]:37870 "EHLO mail.kernel.org" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S932087AbeEUVXC (ORCPT ); Mon, 21 May 2018 17:23:02 -0400 Received: from localhost (LFbn-1-12247-202.w90-92.abo.wanadoo.fr [90.92.61.202]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by mail.kernel.org (Postfix) with ESMTPSA id E80FA20871; Mon, 21 May 2018 21:23:00 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=default; t=1526937781; bh=IhqsW91FbevGqUEBdQldnL4RMWVGZoVPdhA4Ah2H+sQ=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=h7+A7qZWzDrdaySp60Bcv1Zh6kzlDQU2eM6SWdSHqU2YRLY2zx1lj9+GWVjGj5T3e kylKUGEam6vRCateUTXOLdkD+HzJFKhWDoFS9lcMF+FoyX9mc1GLHWoLyLIDIoUW6y CYY4nYE4XkWfUq5mBpodr2S4BM9QuyUjJVXcWjco= From: Greg Kroah-Hartman To: linux-kernel@vger.kernel.org Cc: Greg Kroah-Hartman , stable@vger.kernel.org, Linus Torvalds , "Steven Rostedt (VMware)" Subject: [PATCH 4.16 023/110] vsprintf: Replace memory barrier with static_key for random_ptr_key update Date: Mon, 21 May 2018 23:11:20 +0200 Message-Id: <20180521210505.930147328@linuxfoundation.org> X-Mailer: git-send-email 2.17.0 In-Reply-To: <20180521210503.823249477@linuxfoundation.org> References: <20180521210503.823249477@linuxfoundation.org> User-Agent: quilt/0.65 X-stable: review MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Sender: linux-kernel-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-kernel@vger.kernel.org 4.16-stable review patch. If anyone has any objections, please let me know. ------------------ From: Steven Rostedt (VMware) commit 85f4f12d51397f1648e1f4350f77e24039b82d61 upstream. Reviewing Tobin's patches for getting pointers out early before entropy has been established, I noticed that there's a lone smp_mb() in the code. As with most lone memory barriers, this one appears to be incorrectly used. We currently basically have this: get_random_bytes(&ptr_key, sizeof(ptr_key)); /* * have_filled_random_ptr_key==true is dependent on get_random_bytes(). * ptr_to_id() needs to see have_filled_random_ptr_key==true * after get_random_bytes() returns. */ smp_mb(); WRITE_ONCE(have_filled_random_ptr_key, true); And later we have: if (unlikely(!have_filled_random_ptr_key)) return string(buf, end, "(ptrval)", spec); /* Missing memory barrier here. */ hashval = (unsigned long)siphash_1u64((u64)ptr, &ptr_key); As the CPU can perform speculative loads, we could have a situation with the following: CPU0 CPU1 ---- ---- load ptr_key = 0 store ptr_key = random smp_mb() store have_filled_random_ptr_key load have_filled_random_ptr_key = true BAD BAD BAD! (you're so bad!) Because nothing prevents CPU1 from loading ptr_key before loading have_filled_random_ptr_key. But this race is very unlikely, but we can't keep an incorrect smp_mb() in place. Instead, replace the have_filled_random_ptr_key with a static_branch not_filled_random_ptr_key, that is initialized to true and changed to false when we get enough entropy. If the update happens in early boot, the static_key is updated immediately, otherwise it will have to wait till entropy is filled and this happens in an interrupt handler which can't enable a static_key, as that requires a preemptible context. In that case, a work_queue is used to enable it, as entropy already took too long to establish in the first place waiting a little more shouldn't hurt anything. The benefit of using the static key is that the unlikely branch in vsprintf() now becomes a nop. Link: http://lkml.kernel.org/r/20180515100558.21df515e@gandalf.local.home Cc: stable@vger.kernel.org Fixes: ad67b74d2469d ("printk: hash addresses printed with %p") Acked-by: Linus Torvalds Signed-off-by: Steven Rostedt (VMware) Signed-off-by: Greg Kroah-Hartman --- lib/vsprintf.c | 26 +++++++++++++++----------- 1 file changed, 15 insertions(+), 11 deletions(-) --- a/lib/vsprintf.c +++ b/lib/vsprintf.c @@ -1659,19 +1659,22 @@ char *pointer_string(char *buf, char *en return number(buf, end, (unsigned long int)ptr, spec); } -static bool have_filled_random_ptr_key __read_mostly; +static DEFINE_STATIC_KEY_TRUE(not_filled_random_ptr_key); static siphash_key_t ptr_key __read_mostly; -static void fill_random_ptr_key(struct random_ready_callback *unused) +static void enable_ptr_key_workfn(struct work_struct *work) { get_random_bytes(&ptr_key, sizeof(ptr_key)); - /* - * have_filled_random_ptr_key==true is dependent on get_random_bytes(). - * ptr_to_id() needs to see have_filled_random_ptr_key==true - * after get_random_bytes() returns. - */ - smp_mb(); - WRITE_ONCE(have_filled_random_ptr_key, true); + /* Needs to run from preemptible context */ + static_branch_disable(¬_filled_random_ptr_key); +} + +static DECLARE_WORK(enable_ptr_key_work, enable_ptr_key_workfn); + +static void fill_random_ptr_key(struct random_ready_callback *unused) +{ + /* This may be in an interrupt handler. */ + queue_work(system_unbound_wq, &enable_ptr_key_work); } static struct random_ready_callback random_ready = { @@ -1685,7 +1688,8 @@ static int __init initialize_ptr_random( if (!ret) { return 0; } else if (ret == -EALREADY) { - fill_random_ptr_key(&random_ready); + /* This is in preemptible context */ + enable_ptr_key_workfn(&enable_ptr_key_work); return 0; } @@ -1699,7 +1703,7 @@ static char *ptr_to_id(char *buf, char * unsigned long hashval; const int default_width = 2 * sizeof(ptr); - if (unlikely(!have_filled_random_ptr_key)) { + if (static_branch_unlikely(¬_filled_random_ptr_key)) { spec.field_width = default_width; /* string length must be less than default_width */ return string(buf, end, "(ptrval)", spec);