Received: by 2002:a05:6a10:22f:0:0:0:0 with SMTP id 15csp2951702pxk; Mon, 21 Sep 2020 01:02:22 -0700 (PDT) X-Google-Smtp-Source: ABdhPJxZHCJW+c7JTkVifmX/Q3geVTkfVlqvnkasw/j+uqEnOeJs9Hfe2ooagEf2Tker7tXvxC74 X-Received: by 2002:a17:906:d7ab:: with SMTP id pk11mr48195332ejb.472.1600675342322; Mon, 21 Sep 2020 01:02:22 -0700 (PDT) ARC-Seal: i=1; a=rsa-sha256; t=1600675342; cv=none; d=google.com; s=arc-20160816; b=C5wLXto/88SWFTQ8z6Gfc7LmLbr2A3QRTddBdFeGK2hmoU9ZSy6TJMf2cB1SrFYsY6 p2+6wypitSUtTPERADU/DjXZOSTT90ivowpOih8nHB+YFKOmgrpmSru413o700hAorPB A6GhjyDR5RZcNe75Md3MhVwjA7LSP1h5lWxzT+cfnyAjGshX2eZ5W3tU/gZrjf76uRoE GxOGvVuViqT7jF4uWNhCP9HBEyhePj2rGtKoWRpJlkDJmS9rMTY0b0XSSOl2EyEG70RF 2t8D9wC+V3CJwp/nQxEUH/2s5DNAXZToseRLSeHJKlZPimabpttdSjnp975lFNp1ertF pR8Q== 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; bh=13PV04Bl71YCfGAJaqF95RIorDlHBS3tDrrI03nh4dU=; b=a3rLHJXoYtYCrJ+YvEeiMwMbvcA+ay6AsLSo/xeyLXBOP9KPxLAB3e+hkhcsfNhK7t /mhdYrDxo8uoym3VO5gypKKKgzWzmaR69TW+w7BsaXVR+uWdTL0x+dpThNvsvJ+7kUcm D9tl5bIlScGh/JACfUC/YUEzixw4/xxuV49+fRdfpexSVTF5dNzZKRD90DQDBYSNd5Ou LkkN4fUuFIfaZHrkeceRID/NXN1MtdcskQGvrg+AeS5o3N7F6hc/OGL/JB6zeoSHsH1N eLi+Q17KSHbimYrUTQACnQgFRkFj3g/uXYpzt2ShUxApw+2WHRpxj+J5U0lHJ62Ksow4 BTuQ== ARC-Authentication-Results: i=1; mx.google.com; spf=pass (google.com: domain of linux-kernel-owner@vger.kernel.org designates 23.128.96.18 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org Return-Path: Received: from vger.kernel.org (vger.kernel.org. [23.128.96.18]) by mx.google.com with ESMTP id l24si7975785eji.478.2020.09.21.01.01.59; Mon, 21 Sep 2020 01:02:22 -0700 (PDT) Received-SPF: pass (google.com: domain of linux-kernel-owner@vger.kernel.org designates 23.128.96.18 as permitted sender) client-ip=23.128.96.18; Authentication-Results: mx.google.com; spf=pass (google.com: domain of linux-kernel-owner@vger.kernel.org designates 23.128.96.18 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1726673AbgIUIAO (ORCPT + 99 others); Mon, 21 Sep 2020 04:00:14 -0400 Received: from mx2.suse.de ([195.135.220.15]:57374 "EHLO mx2.suse.de" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1726510AbgIUH7Y (ORCPT ); Mon, 21 Sep 2020 03:59:24 -0400 X-Virus-Scanned: by amavisd-new at test-mx.suse.de Received: from relay2.suse.de (unknown [195.135.221.27]) by mx2.suse.de (Postfix) with ESMTP id 66493B511; Mon, 21 Sep 2020 07:59:58 +0000 (UTC) From: Nicolai Stange To: "Theodore Y. Ts'o" Cc: linux-crypto@vger.kernel.org, LKML , Arnd Bergmann , Greg Kroah-Hartman , "Eric W. Biederman" , "Alexander E. Patrakov" , "Ahmed S. Darwish" , Willy Tarreau , Matthew Garrett , Vito Caputo , Andreas Dilger , Jan Kara , Ray Strode , William Jon McCann , zhangjs , Andy Lutomirski , Florian Weimer , Lennart Poettering , Peter Matthias , Marcelo Henrique Cerri , Roman Drahtmueller , Neil Horman , Randy Dunlap , Julia Lawall , Dan Carpenter , Andy Lavr , Eric Biggers , "Jason A. Donenfeld" , =?UTF-8?q?Stephan=20M=C3=BCller?= , Torsten Duwe , Petr Tesarik , Nicolai Stange Subject: [RFC PATCH 16/41] random: convert random_ioctl() to queued_entropy API Date: Mon, 21 Sep 2020 09:58:32 +0200 Message-Id: <20200921075857.4424-17-nstange@suse.de> X-Mailer: git-send-email 2.26.2 In-Reply-To: <20200921075857.4424-1-nstange@suse.de> References: <20200921075857.4424-1-nstange@suse.de> MIME-Version: 1.0 Content-Transfer-Encoding: 8bit Precedence: bulk List-ID: X-Mailing-List: linux-kernel@vger.kernel.org In an effort to drop credit_entropy_bits_safe() in favor of the new queue_entropy()/dispatch_queued_entropy() API, convert random_ioctl() from the former to the latter. Implement two helpers: - queue_entropy_bits_safe(), which checks the entropy passed from userspace for extreme values in analogy to what credit_entropy_bits_safe() did - discard_queue_entropy(), which is invoked from random_ioctly() to discard the entropy queued prior to the write_pool() call in case the latter fails. Use them to convert the two call sites of credit_entropy_bits_safe() in random_ioctl() to the new API. As a side effect, the pool entropy watermark as tracked over the duration of the write_pool() operation is now taken correctly taken into account when calulating the amount of new entropy to dispatch to the pool based on the latter's fill level. Signed-off-by: Nicolai Stange --- drivers/char/random.c | 57 ++++++++++++++++++++++++++++++++++++++++--- 1 file changed, 53 insertions(+), 4 deletions(-) diff --git a/drivers/char/random.c b/drivers/char/random.c index 78e65367ea86..03eadefabbca 100644 --- a/drivers/char/random.c +++ b/drivers/char/random.c @@ -737,7 +737,9 @@ struct queued_entropy { * dispatch. However, any such sequence of invocations must eventually * be followed by exactly one call to either of __dequeue_entropy(), * __dispatch_queued_entropy_fast() or dispatch_queued_entropy() - * when the actual pool mixing has completed. + * when the actual pool mixing has completed. Alternatively, + * discard_queued_entropy() may be called in case the mixing has + * failed. * __queue_entropy() must be called with r->lock held. * * Entropy extraction is a two-step process: @@ -813,6 +815,26 @@ static void queue_entropy(struct entropy_store *r, struct queued_entropy *q, spin_unlock_irqrestore(&r->lock, flags); } +/* + * Queue entropy which comes from userspace and might take extreme + * values. + */ +static int queue_entropy_bits_safe(struct entropy_store *r, + struct queued_entropy *q, + int nbits) +{ + const int nbits_max = r->poolinfo->poolwords * 32; + + if (nbits < 0) + return -EINVAL; + + /* Cap the value to avoid overflows */ + nbits = min(nbits, nbits_max); + + queue_entropy(r, q, nbits << ENTROPY_SHIFT); + return 0; +} + /* * Dequeue previously queued entropy and return the pool entropy * watermark to be used in pool_entropy_delta(). @@ -950,6 +972,22 @@ static void dispatch_queued_entropy(struct entropy_store *r, } } +/* + * Discard queued entropy. May be called when e.g. a write_pool() + * operation failed and the corresponding previously queued entropy + * should not get dispatched to the pool. + */ +static void discard_queued_entropy(struct entropy_store *r, + struct queued_entropy *q) +{ + unsigned long flags; + int pool_watermark; + + spin_lock_irqsave(&r->lock, flags); + __dequeue_entropy(r, q, &pool_watermark); + spin_unlock_irqrestore(&r->lock, flags); +} + /* * Credit the entropy store with n bits of entropy. * Use credit_entropy_bits_safe() if the value comes from userspace @@ -2272,6 +2310,7 @@ static long random_ioctl(struct file *f, unsigned int cmd, unsigned long arg) int size, ent_count; int __user *p = (int __user *)arg; int retval; + struct queued_entropy q = { 0 }; switch (cmd) { case RNDGETENTCNT: @@ -2285,7 +2324,11 @@ static long random_ioctl(struct file *f, unsigned int cmd, unsigned long arg) return -EPERM; if (get_user(ent_count, p)) return -EFAULT; - return credit_entropy_bits_safe(&input_pool, ent_count); + retval = queue_entropy_bits_safe(&input_pool, &q, ent_count); + if (retval < 0) + return retval; + dispatch_queued_entropy(&input_pool, &q); + return 0; case RNDADDENTROPY: if (!capable(CAP_SYS_ADMIN)) return -EPERM; @@ -2295,11 +2338,17 @@ static long random_ioctl(struct file *f, unsigned int cmd, unsigned long arg) return -EINVAL; if (get_user(size, p++)) return -EFAULT; + retval = queue_entropy_bits_safe(&input_pool, &q, ent_count); + if (retval < 0) + return retval; retval = write_pool(&input_pool, (const char __user *)p, size); - if (retval < 0) + if (retval < 0) { + discard_queued_entropy(&input_pool, &q); return retval; - return credit_entropy_bits_safe(&input_pool, ent_count); + } + discard_queued_entropy(&input_pool, &q); + return 0; case RNDZAPENTCNT: case RNDCLEARPOOL: /* -- 2.26.2