From modulus@h24-77-20-99.wp.shawcable.net  Mon Feb 23 13:45:07 2004
Return-Path: <modulus@h24-77-20-99.wp.shawcable.net>
Received: from mx1.FreeBSD.org (mx1.freebsd.org [216.136.204.125])
	by hub.freebsd.org (Postfix) with ESMTP
	id 2466C16A4CE; Mon, 23 Feb 2004 13:45:07 -0800 (PST)
Received: from h24-77-20-99.wp.shawcable.net (h24-77-20-99.wp.shawcable.net [24.77.20.99])
	by mx1.FreeBSD.org (Postfix) with ESMTP
	id 50B5643D1D; Mon, 23 Feb 2004 13:45:06 -0800 (PST)
	(envelope-from modulus@h24-77-20-99.wp.shawcable.net)
Received: from h24-77-20-99.wp.shawcable.net (localhost [127.0.0.1])
	by h24-77-20-99.wp.shawcable.net (8.12.10/8.12.10) with ESMTP id i1NLmEeO025285;
	Mon, 23 Feb 2004 21:48:15 GMT
	(envelope-from modulus@h24-77-20-99.wp.shawcable.net)
Received: (from root@localhost)
	by h24-77-20-99.wp.shawcable.net (8.12.10/8.12.10/Submit) id i1NLmE1I025284;
	Mon, 23 Feb 2004 21:48:14 GMT
	(envelope-from modulus)
Message-Id: <200402232148.i1NLmE1I025284@h24-77-20-99.wp.shawcable.net>
Date: Mon, 23 Feb 2004 21:48:14 GMT
From: "Christian S.J. Peron" <maneo@bsdpro.com>
Reply-To: "Christian S.J. Peron" <maneo@bsdpro.com>
To: FreeBSD-gnats-submit@freebsd.org
Cc: green@freebsd.org
Subject: [patch] patch to make libc arc4random reentrant
X-Send-Pr-Version: 3.113
X-GNATS-Notify:

>Number:         63287
>Category:       bin
>Synopsis:       [patch] patch to make libc arc4random reentrant
>Confidential:   no
>Severity:       non-critical
>Priority:       low
>Responsible:    freebsd-bugs
>State:          closed
>Quarter:        
>Keywords:       
>Date-Required:  
>Class:          change-request
>Submitter-Id:   current-users
>Arrival-Date:   Mon Feb 23 13:50:11 PST 2004
>Closed-Date:    Wed Mar 24 19:37:14 PST 2004
>Last-Modified:  Wed Mar 24 19:37:14 PST 2004
>Originator:     Christian S.J. Peron
>Release:        FreeBSD 5.2-CURRENT i386
>Organization:
>Environment:
System: FreeBSD movl 5.2-CURRENT FreeBSD 5.2-CURRENT #8: Mon Feb 2 22:04:49 GMT 2004 modulus@movl:/usr/src/sys/i386/compile/ROUTER i386

	
>Description:
	Manipulation and permutation of S-boxes in the arc4random PRNG
	is susceptible to data races during multithreaded operation.

	I have enclosed a patch which serializes S-box manipulation.

>How-To-Repeat:
	N/A
	
>Fix:


--- lib/libc/gen/arc4random.c.orig	Mon Feb 23 20:15:57 2004
+++ lib/libc/gen/arc4random.c	Mon Feb 23 21:05:12 2004
@@ -34,6 +34,9 @@
 #include <stdlib.h>
 #include <fcntl.h>
 #include <unistd.h>
+#include <pthread.h>
+
+#include "libc_private.h"
 #include "un-namespace.h"
 
 struct arc4_stream {
@@ -42,10 +45,27 @@
 	u_int8_t s[256];
 };
 
-static int rs_initialized;
+static pthread_mutex_t	arc4random_mtx = PTHREAD_MUTEX_INITIALIZER;
+
+#define	RANDOMDEV	"/dev/urandom"
+#define	THREAD_LOCK()						\
+	do {							\
+		if (__isthreaded)				\
+			_pthread_mutex_lock(&arc4random_mtx);	\
+	} while (0)
+
+#define	THREAD_UNLOCK()						\
+	do {							\
+		if (__isthreaded)				\
+			_pthread_mutex_unlock(&arc4random_mtx);	\
+	} while (0)
+
 static struct arc4_stream rs;
+static int rs_initialized;
+static int rs_stired;
 
 static inline u_int8_t arc4_getbyte(struct arc4_stream *);
+static void arc4_stir(struct arc4_stream *);
 
 static inline void
 arc4_init(as)
@@ -91,11 +111,11 @@
 
 	gettimeofday(&rdat.tv, NULL);
 	rdat.pid = getpid();
-	fd = _open("/dev/urandom", O_RDONLY, 0);
+	fd = _open(RANDOMDEV, O_RDONLY, 0);
 	if (fd >= 0) {
 		(void) _read(fd, rdat.rnd, sizeof(rdat.rnd));
 		_close(fd);
-	}
+	} 
 	/* fd < 0?  Ah, what the heck. We'll just take whatever was on the
 	 * stack... */
 
@@ -142,14 +162,31 @@
 	return (val);
 }
 
-void
-arc4random_stir()
+static void
+arc4_check_init(void)
 {
 	if (!rs_initialized) {
 		arc4_init(&rs);
 		rs_initialized = 1;
 	}
+}
+
+static void
+arc4_check_stir(void)
+{
+	if (!rs_stired) {
+		arc4_stir(&rs);
+		rs_stired = 1;
+	}
+}
+
+void
+arc4random_stir()
+{
+	THREAD_LOCK();
+	arc4_check_init();
 	arc4_stir(&rs);
+	THREAD_UNLOCK();
 }
 
 void
@@ -157,18 +194,25 @@
 	u_char *dat;
 	int     datlen;
 {
-	if (!rs_initialized)
-		arc4random_stir();
+	THREAD_LOCK();
+	arc4_check_init();
+	arc4_check_stir();
 	arc4_addrandom(&rs, dat, datlen);
+	THREAD_UNLOCK();
 }
 
 u_int32_t
 arc4random()
 {
-	if (!rs_initialized)
-		arc4random_stir();
+	u_int32_t rnd;
+
+	THREAD_LOCK();
+	arc4_check_init();
+	arc4_check_stir();
+	rnd = arc4_getword(&rs);
+	THREAD_UNLOCK();
 
-	return (arc4_getword(&rs));
+	return (rnd);
 }
 
 #if 0
>Release-Note:
>Audit-Trail:
State-Changed-From-To: open->closed 
State-Changed-By: green 
State-Changed-When: Wed Mar 24 19:36:58 PST 2004 
State-Changed-Why:  
Committed to -current; thanks! 

http://www.freebsd.org/cgi/query-pr.cgi?pr=63287 
>Unformatted:
