public inbox for linux-kernel@vger.kernel.org
 help / color / mirror / Atom feed
From: Stephan Mueller <smueller@chronox.de>
To: Herbert Xu <herbert@gondor.apana.org.au>
Cc: pebolle@tiscali.nl, andreas.steffen@strongswan.org,
	tytso@mit.edu, sandyinchina@gmail.com,
	linux-kernel@vger.kernel.org, linux-crypto@vger.kernel.org
Subject: Re: [PATCH v6 1/5] random: Blocking API for accessing nonblocking_pool
Date: Mon, 18 May 2015 07:32:01 +0200	[thread overview]
Message-ID: <3672239.xqA2RrDaZY@tachyon.chronox.de> (raw)
In-Reply-To: <20150515064626.GA16704@gondor.apana.org.au>

Am Freitag, 15. Mai 2015, 14:46:26 schrieb Herbert Xu:

Hi Herbert,

> On Wed, May 13, 2015 at 09:54:41PM +0200, Stephan Mueller wrote:
> >  /*
> > 
> > + * Equivalent function to get_random_bytes with the difference that this
> > + * function blocks the request until the nonblocking_pool is initialized.
> > + */
> > +void get_blocking_random_bytes(void *buf, int nbytes)
> > +{
> > +	if (unlikely(nonblocking_pool.initialized == 0))
> > +		wait_event_interruptible(urandom_init_wait,
> > +					 nonblocking_pool.initialized);
> > +	extract_entropy(&nonblocking_pool, buf, nbytes, 0, 0);
> 
> So what if the wait was interrupted? You are going to extract
> entropy from an empty pool.
> 
> Anyway, you still haven't addressed my primary concern with this
> model which is the potential for dead-lock.  Sleeping for an open
> period of time like this in a work queue is bad form.  It may also
> lead to dead-locks if whatever you're waiting for happened to use
> the same work thread.
> 
> That's why I think you should simply provide a function and data
> pointer which random.c can then stash onto a list to call when
> the pool is ready.

Thanks for the hint to the list. Before handing in another formal patch, may i ask for checking the following approach? I would think that this one should cover your concerns.

diff --git a/drivers/char/random.c b/drivers/char/random.c
index 9cd6968..9bc2a57 100644
--- a/drivers/char/random.c
+++ b/drivers/char/random.c
@@ -409,6 +409,19 @@ static DECLARE_WAIT_QUEUE_HEAD(random_write_wait);
 static DECLARE_WAIT_QUEUE_HEAD(urandom_init_wait);
 static struct fasync_struct *fasync;
 
+static LIST_HEAD(random_wait_list);
+static DEFINE_MUTEX(random_wait_list_mutex);
+struct random_work {
+	struct list_head	list;
+	struct work_struct	rw_work;
+	void			*rw_buf;
+	int			rw_len;
+	void			*rw_private;
+	void			(*rw_cb)(void *buf, int buflen,
+					 void *private);
+};
+static void process_random_waiters(void);
+
 /**********************************************************************
  *
  * OS independent entropy store.   Here are the functions which handle
@@ -660,6 +673,7 @@ retry:
 		r->entropy_total = 0;
 		if (r == &nonblocking_pool) {
 			prandom_reseed_late();
+			process_random_waiters();
 			wake_up_interruptible(&urandom_init_wait);
 			pr_notice("random: %s pool is initialized\n", r->name);
 		}
@@ -1778,3 +1792,64 @@ void add_hwgenerator_randomness(const char *buffer, size_t count,
 	credit_entropy_bits(poolp, entropy);
 }
 EXPORT_SYMBOL_GPL(add_hwgenerator_randomness);
+
+static void process_random_waiters(void)
+{
+	struct random_work *rw = NULL;
+
+	mutex_lock(&random_wait_list_mutex);
+	while (!list_empty(&random_wait_list)) {
+		rw = list_first_entry(&random_wait_list, struct random_work,
+				      list);
+		list_del(&rw->list);
+		schedule_work(&rw->rw_work);
+	}
+	mutex_unlock(&random_wait_list_mutex);
+}
+
+static void get_blocking_random_bytes_work(struct work_struct *work)
+{
+	struct random_work *rw = container_of(work, struct random_work,
+					      rw_work);
+
+	get_random_bytes(rw->rw_buf, rw->rw_len);
+	rw->rw_cb(rw->rw_buf, rw->rw_len, rw->rw_private);
+	kfree(rw);
+}
+
+/*
+ * Equivalent function to get_random_bytes with the difference that this
+ * function blocks the request until the nonblocking_pool is initialized.
+ */
+int get_blocking_random_bytes_cb(void *buf, int nbytes, void *private,
+				 void (*cb)(void *buf, int buflen,
+					    void *private))
+{
+	struct random_work *rw = NULL;
+	int ret = 0;
+
+	mutex_lock(&random_wait_list_mutex);
+	list_for_each_entry(rw, &random_wait_list, list)
+		if (buf == rw->rw_buf)
+			goto out;
+
+	rw = kmalloc(sizeof(struct random_work), GFP_KERNEL);
+	if (!rw) {
+		ret = -ENOMEM;
+		goto out;
+	}
+	INIT_WORK(&rw->rw_work, get_blocking_random_bytes_work);
+	rw->rw_buf = buf;
+	rw->rw_len = nbytes;
+	rw->rw_private = private;
+	rw->rw_cb = cb;
+	list_add_tail(&rw->list, &random_wait_list);
+
+out:
+	mutex_unlock(&random_wait_list_mutex);
+	if (nonblocking_pool.initialized)
+		process_random_waiters();
+
+	return ret;
+}
+EXPORT_SYMBOL(get_blocking_random_bytes_cb);
diff --git a/include/linux/random.h b/include/linux/random.h
index b05856e..b57525f 100644
--- a/include/linux/random.h
+++ b/include/linux/random.h
@@ -15,6 +15,9 @@ extern void add_interrupt_randomness(int irq, int irq_flags);
 
 extern void get_random_bytes(void *buf, int nbytes);
 extern void get_random_bytes_arch(void *buf, int nbytes);
+extern int get_blocking_random_bytes_cb(void *buf, int nbytes, void *private,
+					void (*cb)(void *buf, int buflen,
+						   void *private));
 void generate_random_uuid(unsigned char uuid_out[16]);
 extern int random_int_secret_init(void);
 
-- 
2.1.0



-- 
Ciao
Stephan

  reply	other threads:[~2015-05-18  5:32 UTC|newest]

Thread overview: 26+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2015-05-13 19:54 [PATCH v6 0/5] Seeding DRBG with more entropy Stephan Mueller
2015-05-13 19:54 ` [PATCH v6 1/5] random: Blocking API for accessing nonblocking_pool Stephan Mueller
2015-05-15  6:46   ` Herbert Xu
2015-05-18  5:32     ` Stephan Mueller [this message]
2015-05-18  9:21       ` Herbert Xu
2015-05-18 13:07         ` Stephan Mueller
2015-05-18 13:26           ` Stephan Mueller
2015-05-18 15:02             ` Theodore Ts'o
2015-05-19  5:58               ` Stephan Mueller
2015-05-19  7:22                 ` Herbert Xu
2015-05-19  7:35                   ` Stephan Mueller
2015-05-19  7:51                     ` Herbert Xu
2015-05-19  7:56                       ` Stephan Mueller
2015-05-19 13:50                       ` Theodore Ts'o
2015-05-19 14:18                         ` Herbert Xu
2015-05-19 14:27                           ` Stephan Mueller
2015-05-19 14:30                             ` Herbert Xu
2015-05-19 14:36                               ` Stephan Mueller
2015-05-19 22:55                                 ` Herbert Xu
2015-05-20  6:13                                   ` Stephan Mueller
2015-06-05  5:28                           ` Herbert Xu
2015-06-05  9:50                             ` Stephan Mueller
2015-05-13 19:55 ` [PATCH v6 2/5] crypto: drbg - prepare for async seeding Stephan Mueller
2015-05-13 19:55 ` [PATCH v6 3/5] crypto: drbg - add async seeding operation Stephan Mueller
2015-05-13 19:56 ` [PATCH v6 4/5] crypto: drbg - use Jitter RNG to obtain seed Stephan Mueller
2015-05-13 19:56 ` [PATCH v6 5/5] crypto: add jitterentropy RNG Stephan Mueller

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=3672239.xqA2RrDaZY@tachyon.chronox.de \
    --to=smueller@chronox.de \
    --cc=andreas.steffen@strongswan.org \
    --cc=herbert@gondor.apana.org.au \
    --cc=linux-crypto@vger.kernel.org \
    --cc=linux-kernel@vger.kernel.org \
    --cc=pebolle@tiscali.nl \
    --cc=sandyinchina@gmail.com \
    --cc=tytso@mit.edu \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox