From patchwork Tue Jun 27 06:01:30 2017 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Harald Freudenberger X-Patchwork-Id: 9810831 X-Patchwork-Delegate: herbert@gondor.apana.org.au Return-Path: Received: from mail.wl.linuxfoundation.org (pdx-wl-mail.web.codeaurora.org [172.30.200.125]) by pdx-korg-patchwork.web.codeaurora.org (Postfix) with ESMTP id 963F46020A for ; Tue, 27 Jun 2017 06:04:18 +0000 (UTC) Received: from mail.wl.linuxfoundation.org (localhost [127.0.0.1]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id 5159C24B48 for ; Tue, 27 Jun 2017 06:02:08 +0000 (UTC) Received: by mail.wl.linuxfoundation.org (Postfix, from userid 486) id 44E8B2621D; Tue, 27 Jun 2017 06:02:08 +0000 (UTC) X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on pdx-wl-mail.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-6.9 required=2.0 tests=BAYES_00,RCVD_IN_DNSWL_HI autolearn=ham version=3.3.1 Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id CDBF824B48 for ; Tue, 27 Jun 2017 06:02:07 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1751473AbdF0GCG (ORCPT ); Tue, 27 Jun 2017 02:02:06 -0400 Received: from mx0b-001b2d01.pphosted.com ([148.163.158.5]:33994 "EHLO mx0a-001b2d01.pphosted.com" rhost-flags-OK-OK-OK-FAIL) by vger.kernel.org with ESMTP id S1751483AbdF0GCF (ORCPT ); Tue, 27 Jun 2017 02:02:05 -0400 Received: from pps.filterd (m0098419.ppops.net [127.0.0.1]) by mx0b-001b2d01.pphosted.com (8.16.0.20/8.16.0.20) with SMTP id v5R5xEkB049708 for ; Tue, 27 Jun 2017 02:02:04 -0400 Received: from e06smtp12.uk.ibm.com (e06smtp12.uk.ibm.com [195.75.94.108]) by mx0b-001b2d01.pphosted.com with ESMTP id 2bb2krammx-1 (version=TLSv1.2 cipher=AES256-SHA bits=256 verify=NOT) for ; Tue, 27 Jun 2017 02:02:04 -0400 Received: from localhost by e06smtp12.uk.ibm.com with IBM ESMTP SMTP Gateway: Authorized Use Only! Violators will be prosecuted for from ; Tue, 27 Jun 2017 07:02:03 +0100 Received: from b06cxnps3075.portsmouth.uk.ibm.com (9.149.109.195) by e06smtp12.uk.ibm.com (192.168.101.142) with IBM ESMTP SMTP Gateway: Authorized Use Only! Violators will be prosecuted; Tue, 27 Jun 2017 07:02:01 +0100 Received: from d06av25.portsmouth.uk.ibm.com (d06av25.portsmouth.uk.ibm.com [9.149.105.61]) by b06cxnps3075.portsmouth.uk.ibm.com (8.14.9/8.14.9/NCO v10.0) with ESMTP id v5R621QZ12059114; Tue, 27 Jun 2017 06:02:01 GMT Received: from d06av25.portsmouth.uk.ibm.com (unknown [127.0.0.1]) by IMSVA (Postfix) with ESMTP id B8FA511C04C; Tue, 27 Jun 2017 06:59:48 +0100 (BST) Received: from d06av25.portsmouth.uk.ibm.com (unknown [127.0.0.1]) by IMSVA (Postfix) with ESMTP id 8F82511C04A; Tue, 27 Jun 2017 06:59:48 +0100 (BST) Received: from mymint.boeblingen.de.ibm.com (unknown [9.152.224.25]) by d06av25.portsmouth.uk.ibm.com (Postfix) with ESMTP; Tue, 27 Jun 2017 06:59:48 +0100 (BST) From: Harald Freudenberger To: linux-crypto@vger.kernel.org Cc: schwidefsky@de.ibm.com, Harald Freudenberger Subject: [PATCH] hwrng: Make hwrng choose rng source by quality. Date: Tue, 27 Jun 2017 08:01:30 +0200 X-Mailer: git-send-email 2.7.4 X-TM-AS-GCONF: 00 x-cbid: 17062706-0008-0000-0000-00000471129A X-IBM-AV-DETECTION: SAVI=unused REMOTE=unused XFE=unused x-cbparentid: 17062706-0009-0000-0000-00001DFB2BF3 Message-Id: <1498543290-17824-1-git-send-email-freude@linux.vnet.ibm.com> X-Proofpoint-Virus-Version: vendor=fsecure engine=2.50.10432:, , definitions=2017-06-27_03:, , signatures=0 X-Proofpoint-Spam-Details: rule=outbound_notspam policy=outbound score=0 spamscore=0 suspectscore=1 malwarescore=0 phishscore=0 adultscore=0 bulkscore=0 classifier=spam adjust=0 reason=mlx scancount=1 engine=8.0.1-1703280000 definitions=main-1706270096 Sender: linux-crypto-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-crypto@vger.kernel.org X-Virus-Scanned: ClamAV using ClamSMTP The hwrng core implementation currently doesn't consider the quality field of the struct hwrng. So the first registered rng is the winner and further rng sources even with much better quality are ignored. The behavior should be that always the best rng with the highest quality rate should be used as current rng source. Only if the user explicitly chooses a rng source (via writing a rng name to /sys/class/misc/hw_random) the decision for the best quality should be suppressed. This patch makes hwrng always hold a list of registered rng sources sorted decreasing by quality. On registration of a new hwrng source the list is updated and if the current rng source was not chosen by user and the new rng provides better quality set as new current rng source. Similar on unregistration of an rng, if it was the current used rng source the one with the next highest quality is used. If a rng source has been set via sysfs from userland as long as this one doesn't unregister it is kept as current rng regardless of registration of 'better' rng sources. Signed-off-by: Harald Freudenberger --- drivers/char/hw_random/core.c | 31 +++++++++++++++++++++++++------ 1 file changed, 25 insertions(+), 6 deletions(-) diff --git a/drivers/char/hw_random/core.c b/drivers/char/hw_random/core.c index 503a41d..7fe47f8 100644 --- a/drivers/char/hw_random/core.c +++ b/drivers/char/hw_random/core.c @@ -28,7 +28,10 @@ #define RNG_MODULE_NAME "hw_random" static struct hwrng *current_rng; +/* the current rng has been explicitly chosen by user via sysfs */ +static int cur_rng_set_by_user; static struct task_struct *hwrng_fill; +/* list of registered rngs, sorted decending by quality */ static LIST_HEAD(rng_list); /* Protects rng_list and current_rng */ static DEFINE_MUTEX(rng_mutex); @@ -308,6 +311,8 @@ static ssize_t hwrng_attr_current_store(struct device *dev, break; } } + if (!err) + cur_rng_set_by_user = 1; mutex_unlock(&rng_mutex); return err ? : len; @@ -417,6 +422,7 @@ int hwrng_register(struct hwrng *rng) { int err = -EINVAL; struct hwrng *old_rng, *tmp; + struct list_head *ptr; if (!rng->name || (!rng->data_read && !rng->read)) goto out; @@ -432,14 +438,26 @@ int hwrng_register(struct hwrng *rng) init_completion(&rng->cleanup_done); complete(&rng->cleanup_done); + /* rng_list is sorted by decreasing quality */ + list_for_each(ptr, &rng_list) { + tmp = list_entry(ptr, struct hwrng, list); + if (tmp->quality < rng->quality) + break; + } + list_add_tail(&rng->list, ptr); + old_rng = current_rng; err = 0; - if (!old_rng) { + if (!old_rng || + (!cur_rng_set_by_user && rng->quality > old_rng->quality)) { + /* + * Set new rng as current if no current rng or rng was + * not chosen by user and the new one has better quality. + */ err = set_current_rng(rng); if (err) goto out_unlock; } - list_add_tail(&rng->list, &rng_list); if (old_rng && !rng->init) { /* @@ -466,12 +484,13 @@ void hwrng_unregister(struct hwrng *rng) list_del(&rng->list); if (current_rng == rng) { drop_current_rng(); + cur_rng_set_by_user = 0; + /* rng_list is sorted by quality, use the best (=first) one */ if (!list_empty(&rng_list)) { - struct hwrng *tail; - - tail = list_entry(rng_list.prev, struct hwrng, list); + struct hwrng *new_rng; - set_current_rng(tail); + new_rng = list_entry(rng_list.next, struct hwrng, list); + set_current_rng(new_rng); } }