From nobody Sun Jun 28 02:49:20 2026 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by smtp.lore.kernel.org (Postfix) with ESMTP id 179C9C433F5 for ; Tue, 15 Feb 2022 11:48:26 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S237026AbiBOLse (ORCPT ); Tue, 15 Feb 2022 06:48:34 -0500 Received: from mxb-00190b01.gslb.pphosted.com ([23.128.96.19]:52122 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S229707AbiBOLsc (ORCPT ); Tue, 15 Feb 2022 06:48:32 -0500 Received: from dfw.source.kernel.org (dfw.source.kernel.org [139.178.84.217]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id 3D777710F9 for ; Tue, 15 Feb 2022 03:48:23 -0800 (PST) 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 CE8AB6157B for ; Tue, 15 Feb 2022 11:48:22 +0000 (UTC) Received: by smtp.kernel.org (Postfix) with ESMTPSA id CF59FC340EB; Tue, 15 Feb 2022 11:48:21 +0000 (UTC) Authentication-Results: smtp.kernel.org; dkim=pass (1024-bit key) header.d=zx2c4.com header.i=@zx2c4.com header.b="G4jSwocK" DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=zx2c4.com; s=20210105; t=1644925700; 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=XQTMRXJB9KfjEetgEwOx1Rgeuw93qd9A1BZQuEZHg9I=; b=G4jSwocKDUp8ByfkQXrCIZoXLqH+z0LVz9kkt63NuBcTLOHtvnexiXjKg31WUaNHMgcDwy r69p99id2DBagDkxjEbWa4yltyDwJT7ZoC3oZjID+jJG8F+hfVIJ6QnzBroMdEYPjOQ197 XLWBxJhF8PYzAvAIdEANDdzhOWpnrPk= Received: by mail.zx2c4.com (ZX2C4 Mail Server) with ESMTPSA id bb65e87b (TLSv1.3:AEAD-AES256-GCM-SHA384:256:NO); Tue, 15 Feb 2022 11:48:20 +0000 (UTC) From: "Jason A. Donenfeld" To: linux-kernel@vger.kernel.org Cc: "Jason A. Donenfeld" , Theodore Ts'o , Dominik Brodowski Subject: [PATCH v3] random: deobfuscate irq u32/u64 contributions Date: Tue, 15 Feb 2022 12:48:12 +0100 Message-Id: <20220215114812.96750-1-Jason@zx2c4.com> In-Reply-To: References: MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable Precedence: bulk List-ID: X-Mailing-List: linux-kernel@vger.kernel.org Content-Type: text/plain; charset="utf-8" In the irq handler, we fill out 16 bytes differently on 32-bit and 64-bit platforms, and for 32-bit vs 64-bit cycle counters, which doesn't always correspond with the bitness of the platform. Whether or not you like this strangeness, it is a matter of fact. But it might not be a fact you well realized until now, because the code that loaded the irq info into 4 32-bit words was quite confusing. Instead, this commit makes everything explicit by having separate (compile-time) branches for 32-bit and 64-bit types. Cc: Theodore Ts'o Reviewed-by: Dominik Brodowski Signed-off-by: Jason A. Donenfeld --- Changes v2->v3: - cycles_t is sometimes an `unsigned long long`, even on 32-bit x86, so separate that contribution from the other one. - rebased on the latest. drivers/char/random.c | 49 ++++++++++++++++++++++++------------------- 1 file changed, 28 insertions(+), 21 deletions(-) diff --git a/drivers/char/random.c b/drivers/char/random.c index 9714d9f05a84..6a2c7db94417 100644 --- a/drivers/char/random.c +++ b/drivers/char/random.c @@ -283,7 +283,10 @@ static void mix_pool_bytes(const void *in, size_t nbyt= es) } =20 struct fast_pool { - u32 pool[4]; + union { + u32 pool32[4]; + u64 pool64[2]; + }; unsigned long last; u16 reg_idx; u8 count; @@ -294,10 +297,10 @@ struct fast_pool { * collector. It's hardcoded for an 128 bit pool and assumes that any * locks that might be needed are taken by the caller. */ -static void fast_mix(struct fast_pool *f) +static void fast_mix(u32 pool[4]) { - u32 a =3D f->pool[0], b =3D f->pool[1]; - u32 c =3D f->pool[2], d =3D f->pool[3]; + u32 a =3D pool[0], b =3D pool[1]; + u32 c =3D pool[2], d =3D pool[3]; =20 a +=3D b; c +=3D d; b =3D rol32(b, 6); d =3D rol32(d, 27); @@ -315,9 +318,8 @@ static void fast_mix(struct fast_pool *f) b =3D rol32(b, 16); d =3D rol32(d, 14); d ^=3D a; b ^=3D c; =20 - f->pool[0] =3D a; f->pool[1] =3D b; - f->pool[2] =3D c; f->pool[3] =3D d; - f->count++; + pool[0] =3D a; pool[1] =3D b; + pool[2] =3D c; pool[3] =3D d; } =20 static void process_random_ready_list(void) @@ -778,29 +780,34 @@ void add_interrupt_randomness(int irq) struct pt_regs *regs =3D get_irq_regs(); unsigned long now =3D jiffies; cycles_t cycles =3D random_get_entropy(); - u32 c_high, j_high; - u64 ip; =20 if (cycles =3D=3D 0) cycles =3D get_reg(fast_pool, regs); - c_high =3D (sizeof(cycles) > 4) ? cycles >> 32 : 0; - j_high =3D (sizeof(now) > 4) ? now >> 32 : 0; - fast_pool->pool[0] ^=3D cycles ^ j_high ^ irq; - fast_pool->pool[1] ^=3D now ^ c_high; - ip =3D regs ? instruction_pointer(regs) : _RET_IP_; - fast_pool->pool[2] ^=3D ip; - fast_pool->pool[3] ^=3D - (sizeof(ip) > 4) ? ip >> 32 : get_reg(fast_pool, regs); =20 - fast_mix(fast_pool); + if (sizeof(cycles) =3D=3D 8) + fast_pool->pool64[0] ^=3D cycles ^ rol64(now, 32) ^ irq; + else { + fast_pool->pool32[0] ^=3D cycles ^ irq; + fast_pool->pool32[1] ^=3D now; + } + + if (sizeof(unsigned long) =3D=3D 8) + fast_pool->pool64[1] ^=3D regs ? instruction_pointer(regs) : _RET_IP_; + else { + fast_pool->pool32[2] ^=3D regs ? instruction_pointer(regs) : _RET_IP_; + fast_pool->pool32[3] ^=3D get_reg(fast_pool, regs); + } + + fast_mix(fast_pool->pool32); + ++fast_pool->count; =20 if (unlikely(crng_init =3D=3D 0)) { if (fast_pool->count >=3D 64 && - crng_fast_load(fast_pool->pool, sizeof(fast_pool->pool)) > 0) { + crng_fast_load(fast_pool->pool32, sizeof(fast_pool->pool32)) > 0) { fast_pool->count =3D 0; fast_pool->last =3D now; if (spin_trylock(&input_pool.lock)) { - _mix_pool_bytes(&fast_pool->pool, sizeof(fast_pool->pool)); + _mix_pool_bytes(&fast_pool->pool32, sizeof(fast_pool->pool32)); spin_unlock(&input_pool.lock); } } @@ -814,7 +821,7 @@ void add_interrupt_randomness(int irq) return; =20 fast_pool->last =3D now; - _mix_pool_bytes(&fast_pool->pool, sizeof(fast_pool->pool)); + _mix_pool_bytes(&fast_pool->pool32, sizeof(fast_pool->pool32)); spin_unlock(&input_pool.lock); =20 fast_pool->count =3D 0; --=20 2.35.0