Received: by 2002:a05:6a10:2726:0:0:0:0 with SMTP id ib38csp3456335pxb; Mon, 4 Apr 2022 17:33:44 -0700 (PDT) X-Google-Smtp-Source: ABdhPJyBSwUKpv1PIcGVvYxChOhF+CDQU/NrJ+aWsy24QR6XGZeD+DZKdIaXZjs1PUgCOkCiM6y7 X-Received: by 2002:a17:902:a9c7:b0:156:8951:651d with SMTP id b7-20020a170902a9c700b001568951651dmr830200plr.79.1649118824174; Mon, 04 Apr 2022 17:33:44 -0700 (PDT) ARC-Seal: i=1; a=rsa-sha256; t=1649118824; cv=none; d=google.com; s=arc-20160816; b=mEvzkain56NsnMEqWY2y7ttls/KVKhiDtbiQ7Yxi9XXt5iPEc8Dli10GUjeBId5iWm a/+qN2HCZXPr53nozY27W+PcPn/Gfc686RFd6+vXlL0/V9xoR8BkiKVtbJmUwTVOzoXP zc3oRHMe7t4ICbWzygPE1tVc331x7SKsVUjfEBUO54ByZzm4eG1nX1+0GMqJdM539onh UZpWJDsmKz0m9dvix5BslNRVluaEmNfpB1m2/GcZoAWnaq7ZbNKdhAe75nVlxcBcMov9 /kjfpyfyRbcK6M4SRllUFVaBVcgPwmaKRVTXq6KGPAVnn31+jUtPWRPA7+roorPM+hvs 0gcw== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20160816; h=list-id:precedence:content-transfer-encoding:mime-version :references:in-reply-to:message-id:date:subject:cc:to:from :dkim-signature; bh=Mxt9T82sbpWz4IjiJ3VTsKRIsN86mlQjpIjacqSY2gw=; b=e7rrCqqhH8wOGegXxMnDxolJ3+172MuBzKLLLYzk6vu5dckFhKUwrsBOvcGpPc7oZ7 qr3Wd0z0q7y7HiJqh2wp8yuSt3mz3zrRCERoChXaX7SLpvgqzMcixKGuV5NO02Zzwuph C0Fpp/rplUbiX5tFLj457nygj7NYtxLF/W30rr1qtlOFALMhN+ggtqjG+xTWWsSA3CLT 03ZUVEP5N4gLrEVtozxynZtFYPWwYAprV5e0+IGgKLexDS4zuOGPhBTOiKT5prvDgAWQ G8v50Ce+Pp9ne4cmzdW1tLBGui+Du4+1nKczKhkQctcMswlC1dat86Q2bYW06lsKtCfM wp5g== ARC-Authentication-Results: i=1; mx.google.com; dkim=pass header.i=@zx2c4.com header.s=20210105 header.b=QggbICQn; spf=pass (google.com: domain of linux-kernel-owner@vger.kernel.org designates 2620:137:e000::1:18 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org; dmarc=pass (p=NONE sp=NONE dis=NONE) header.from=zx2c4.com Return-Path: Received: from lindbergh.monkeyblade.net (lindbergh.monkeyblade.net. [2620:137:e000::1:18]) by mx.google.com with ESMTPS id q12-20020a170902f78c00b00153b2d16537si10361434pln.319.2022.04.04.17.33.43 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Mon, 04 Apr 2022 17:33:44 -0700 (PDT) Received-SPF: pass (google.com: domain of linux-kernel-owner@vger.kernel.org designates 2620:137:e000::1:18 as permitted sender) client-ip=2620:137:e000::1:18; Authentication-Results: mx.google.com; dkim=pass header.i=@zx2c4.com header.s=20210105 header.b=QggbICQn; spf=pass (google.com: domain of linux-kernel-owner@vger.kernel.org designates 2620:137:e000::1:18 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org; dmarc=pass (p=NONE sp=NONE dis=NONE) header.from=zx2c4.com Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by lindbergh.monkeyblade.net (Postfix) with ESMTP id EED48887AF; Mon, 4 Apr 2022 16:52:03 -0700 (PDT) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1376460AbiDCUn1 (ORCPT + 99 others); Sun, 3 Apr 2022 16:43:27 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:47624 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S229637AbiDCUnZ (ORCPT ); Sun, 3 Apr 2022 16:43:25 -0400 Received: from dfw.source.kernel.org (dfw.source.kernel.org [IPv6:2604:1380:4641:c500::1]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id 41B5238BFE; Sun, 3 Apr 2022 13:41:30 -0700 (PDT) Received: from smtp.kernel.org (relay.kernel.org [52.25.139.140]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by dfw.source.kernel.org (Postfix) with ESMTPS id C329060DB6; Sun, 3 Apr 2022 20:41:29 +0000 (UTC) Received: by smtp.kernel.org (Postfix) with ESMTPSA id 7F519C340ED; Sun, 3 Apr 2022 20:41:28 +0000 (UTC) Authentication-Results: smtp.kernel.org; dkim=pass (1024-bit key) header.d=zx2c4.com header.i=@zx2c4.com header.b="QggbICQn" DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=zx2c4.com; s=20210105; t=1649018486; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:cc:mime-version:mime-version: content-transfer-encoding:content-transfer-encoding: in-reply-to:in-reply-to:references:references; bh=Mxt9T82sbpWz4IjiJ3VTsKRIsN86mlQjpIjacqSY2gw=; b=QggbICQnFwmujh620fX+x9WJA7mjM8IXOmX5M9ltLjv/2kga6M6vd7p3Pv5679fbyosP31 RfOLPzi3FY6jSk2PI83PnlqZkOnYs3S4HDY7Srrwcs8AL/0ggtOYUiVmMho0KuWgwutXal a3W+8Q6Pq/muKbKEO3lNWa4Rd66uCiE= Received: by mail.zx2c4.com (ZX2C4 Mail Server) with ESMTPSA id efd4d0cd (TLSv1.3:AEAD-AES256-GCM-SHA384:256:NO); Sun, 3 Apr 2022 20:41:26 +0000 (UTC) From: "Jason A. Donenfeld" To: keescook@chromium.org, linux-hardening@vger.kernel.org, linux-kernel@vger.kernel.org Cc: "Jason A. Donenfeld" , stable@vger.kernel.org, PaX Team Subject: [PATCH v2] gcc-plugins: latent_entropy: use /dev/urandom Date: Sun, 3 Apr 2022 22:40:36 +0200 Message-Id: <20220403204036.1269562-1-Jason@zx2c4.com> In-Reply-To: References: MIME-Version: 1.0 Content-Transfer-Encoding: 8bit X-Spam-Status: No, score=-2.0 required=5.0 tests=BAYES_00,DKIM_SIGNED, DKIM_VALID,DKIM_VALID_AU,HEADER_FROM_DIFFERENT_DOMAINS, MAILING_LIST_MULTI,RDNS_NONE,SPF_HELO_NONE,T_SCC_BODY_TEXT_LINE autolearn=no autolearn_force=no version=3.4.6 X-Spam-Checker-Version: SpamAssassin 3.4.6 (2021-04-09) on lindbergh.monkeyblade.net Precedence: bulk List-ID: X-Mailing-List: linux-kernel@vger.kernel.org While the latent entropy plugin mostly doesn't derive entropy from get_random_const() for measuring the call graph, when __latent_entropy is applied to a constant, then it's initialized statically to output from get_random_const(). In that case, this data is derived from a 64-bit seed, which means a buffer of 512 bits doesn't really have that amount of compile-time entropy. This patch fixes that shortcoming by just buffering chunks of /dev/urandom output and doling it out as requested. At the same time, it's important that we don't break the use of -frandom-seed, for people who want the runtime benefits of the latent entropy plugin, while still having compile-time determinism. In that case, we detect whether gcc's set_random_seed() has been called by making a call to get_random_seed(noinit=true) in the plugin init function, which is called after set_random_seed() is called but before anything that calls get_random_seed(noinit=false), and seeing if it's zero or not. If it's not zero, we're in deterministic mode, and so we just generate numbers with a basic xorshift prng. Fixes: 38addce8b600 ("gcc-plugins: Add latent_entropy plugin") Cc: stable@vger.kernel.org Cc: PaX Team Signed-off-by: Jason A. Donenfeld --- Changes v1->v2: - Pipacs pointed out that using /dev/urandom unconditionally would break the use of -frandom-seed, so now we check for that and keep with something deterministic in that case. I'm not super familiar with this plugin or its conventions, so pointers would be most welcome if something here looks amiss. The decision to buffer 2k at a time is pretty arbitrary too; I haven't measured usage. scripts/gcc-plugins/latent_entropy_plugin.c | 48 +++++++++++++-------- 1 file changed, 30 insertions(+), 18 deletions(-) diff --git a/scripts/gcc-plugins/latent_entropy_plugin.c b/scripts/gcc-plugins/latent_entropy_plugin.c index 589454bce930..042442013ae1 100644 --- a/scripts/gcc-plugins/latent_entropy_plugin.c +++ b/scripts/gcc-plugins/latent_entropy_plugin.c @@ -82,29 +82,37 @@ __visible int plugin_is_GPL_compatible; static GTY(()) tree latent_entropy_decl; static struct plugin_info latent_entropy_plugin_info = { - .version = "201606141920vanilla", + .version = "202203311920vanilla", .help = "disable\tturn off latent entropy instrumentation\n", }; -static unsigned HOST_WIDE_INT seed; -/* - * get_random_seed() (this is a GCC function) generates the seed. - * This is a simple random generator without any cryptographic security because - * the entropy doesn't come from here. - */ +static unsigned HOST_WIDE_INT deterministic_seed; +static unsigned HOST_WIDE_INT rnd_buf[256]; +static size_t rnd_idx = ARRAY_SIZE(rnd_buf); +static int urandom_fd = -1; + static unsigned HOST_WIDE_INT get_random_const(void) { - unsigned int i; - unsigned HOST_WIDE_INT ret = 0; - - for (i = 0; i < 8 * sizeof(ret); i++) { - ret = (ret << 1) | (seed & 1); - seed >>= 1; - if (ret & 1) - seed ^= 0xD800000000000000ULL; + if (deterministic_seed) { + unsigned HOST_WIDE_INT w = deterministic_seed; + w ^= w << 13; + w ^= w >> 7; + w ^= w << 17; + deterministic_seed = w; + return deterministic_seed; } - return ret; + if (urandom_fd < 0) { + urandom_fd = open("/dev/urandom", O_RDONLY); + if (urandom_fd < 0) + abort(); + } + if (rnd_idx >= ARRAY_SIZE(rnd_buf)) { + if (read(urandom_fd, rnd_buf, sizeof(rnd_buf)) != sizeof(rnd_buf)) + abort(); + rnd_idx = 0; + } + return rnd_buf[rnd_idx++]; } static tree tree_get_random_const(tree type) @@ -537,8 +545,6 @@ static void latent_entropy_start_unit(void *gcc_data __unused, tree type, id; int quals; - seed = get_random_seed(false); - if (in_lto_p) return; @@ -573,6 +579,12 @@ __visible int plugin_init(struct plugin_name_args *plugin_info, const struct plugin_argument * const argv = plugin_info->argv; int i; + /* + * Call get_random_seed() with noinit=true, so that this returns + * 0 in the case where no seed has been passed via -frandom-seed. + */ + deterministic_seed = get_random_seed(true); + static const struct ggc_root_tab gt_ggc_r_gt_latent_entropy[] = { { .base = &latent_entropy_decl, -- 2.35.1