From owner-svn-src-all@freebsd.org Sat Oct 20 21:09:13 2018 Return-Path: Delivered-To: svn-src-all@mailman.ysv.freebsd.org Received: from mx1.freebsd.org (mx1.freebsd.org [IPv6:2610:1c1:1:606c::19:1]) by mailman.ysv.freebsd.org (Postfix) with ESMTP id 87B89FF5E5B; Sat, 20 Oct 2018 21:09:13 +0000 (UTC) (envelope-from cem@FreeBSD.org) Received: from mxrelay.nyi.freebsd.org (mxrelay.nyi.freebsd.org [IPv6:2610:1c1:1:606c::19:3]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (Client CN "mxrelay.nyi.freebsd.org", Issuer "Let's Encrypt Authority X3" (verified OK)) by mx1.freebsd.org (Postfix) with ESMTPS id 2C9C489292; Sat, 20 Oct 2018 21:09:13 +0000 (UTC) (envelope-from cem@FreeBSD.org) Received: from repo.freebsd.org (repo.freebsd.org [IPv6:2610:1c1:1:6068::e6a:0]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (Client did not present a certificate) by mxrelay.nyi.freebsd.org (Postfix) with ESMTPS id 214F923694; Sat, 20 Oct 2018 21:09:13 +0000 (UTC) (envelope-from cem@FreeBSD.org) Received: from repo.freebsd.org ([127.0.1.37]) by repo.freebsd.org (8.15.2/8.15.2) with ESMTP id w9KL9DmD024272; Sat, 20 Oct 2018 21:09:13 GMT (envelope-from cem@FreeBSD.org) Received: (from cem@localhost) by repo.freebsd.org (8.15.2/8.15.2/Submit) id w9KL9CRp024271; Sat, 20 Oct 2018 21:09:13 GMT (envelope-from cem@FreeBSD.org) Message-Id: <201810202109.w9KL9CRp024271@repo.freebsd.org> X-Authentication-Warning: repo.freebsd.org: cem set sender to cem@FreeBSD.org using -f From: Conrad Meyer Date: Sat, 20 Oct 2018 21:09:12 +0000 (UTC) To: src-committers@freebsd.org, svn-src-all@freebsd.org, svn-src-head@freebsd.org Subject: svn commit: r339492 - head/sys/dev/random X-SVN-Group: head X-SVN-Commit-Author: cem X-SVN-Commit-Paths: head/sys/dev/random X-SVN-Commit-Revision: 339492 X-SVN-Commit-Repository: base MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit X-BeenThere: svn-src-all@freebsd.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: "SVN commit messages for the entire src tree \(except for " user" and " projects" \)" List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Sat, 20 Oct 2018 21:09:13 -0000 Author: cem Date: Sat Oct 20 21:09:12 2018 New Revision: 339492 URL: https://svnweb.freebsd.org/changeset/base/339492 Log: Fortuna: Fix a race to prevent reseed spamming If multiple threads enter fortuna_pre_read contemporaneously, such as via read(2) or getrandom(2), they could race to check how long it has been since the last update due to a TOCTOU problem with 'now'. Here is an example problematic execution: Thread A: Thread B: now_A = getsbinuptime(); now_B = getsbinuptime(); // now_B > now_A RANDOM_RESEED_LOCK(); if (now - fs_lasttime > SBT_1S/10) { fs_lasttime = now; ... // reseed } RANDOM_RESEED_UNLOCK(); RANDOM_RESEED_LOCK(); if (now_A - fs_lasttime > SBT_1S/10) // now_A - fs_lasttime underflows fs_lasttime = now_A; ... // reseed again, despite less than 100ms elapsing } RANDOM_RESEED_UNLOCK(); To resolve the race, simply check the current time after we win the lock race. If getsbinuptime is perceived to be expensive, another option might be to just accept the race and validate that fs_lasttime isn't "in the future." (It should be within the last ~2^31 seconds out of ~2^32 seconds representable duration.) Reviewed by: delphij, markm Approved by: secteam (delphij) Sponsored by: Dell EMC Isilon Differential Revision: https://reviews.freebsd.org/D16984 Modified: head/sys/dev/random/fortuna.c Modified: head/sys/dev/random/fortuna.c ============================================================================== --- head/sys/dev/random/fortuna.c Sat Oct 20 21:06:15 2018 (r339491) +++ head/sys/dev/random/fortuna.c Sat Oct 20 21:09:12 2018 (r339492) @@ -368,11 +368,11 @@ random_fortuna_pre_read(void) u_int i; KASSERT(fortuna_state.fs_minpoolsize > 0, ("random: Fortuna threshold must be > 0")); + RANDOM_RESEED_LOCK(); #ifdef _KERNEL /* FS&K - Use 'getsbinuptime()' to prevent reseed-spamming. */ now = getsbinuptime(); #endif - RANDOM_RESEED_LOCK(); if (fortuna_state.fs_pool[0].fsp_length >= fortuna_state.fs_minpoolsize #ifdef _KERNEL