LCOV - code coverage report
Current view: top level - drivers/char/hw_random - core.c (source / functions) Hit Total Coverage
Test: coverage.info Lines: 9 285 3.2 %
Date: 2023-04-06 08:38:28 Functions: 2 29 6.9 %

          Line data    Source code
       1             : /*
       2             :  * hw_random/core.c: HWRNG core API
       3             :  *
       4             :  * Copyright 2006 Michael Buesch <m@bues.ch>
       5             :  * Copyright 2005 (c) MontaVista Software, Inc.
       6             :  *
       7             :  * Please read Documentation/admin-guide/hw_random.rst for details on use.
       8             :  *
       9             :  * This software may be used and distributed according to the terms
      10             :  * of the GNU General Public License, incorporated herein by reference.
      11             :  */
      12             : 
      13             : #include <linux/delay.h>
      14             : #include <linux/device.h>
      15             : #include <linux/err.h>
      16             : #include <linux/fs.h>
      17             : #include <linux/hw_random.h>
      18             : #include <linux/random.h>
      19             : #include <linux/kernel.h>
      20             : #include <linux/kthread.h>
      21             : #include <linux/sched/signal.h>
      22             : #include <linux/miscdevice.h>
      23             : #include <linux/module.h>
      24             : #include <linux/random.h>
      25             : #include <linux/sched.h>
      26             : #include <linux/slab.h>
      27             : #include <linux/uaccess.h>
      28             : 
      29             : #define RNG_MODULE_NAME         "hw_random"
      30             : 
      31             : static struct hwrng *current_rng;
      32             : /* the current rng has been explicitly chosen by user via sysfs */
      33             : static int cur_rng_set_by_user;
      34             : static struct task_struct *hwrng_fill;
      35             : /* list of registered rngs */
      36             : static LIST_HEAD(rng_list);
      37             : /* Protects rng_list and current_rng */
      38             : static DEFINE_MUTEX(rng_mutex);
      39             : /* Protects rng read functions, data_avail, rng_buffer and rng_fillbuf */
      40             : static DEFINE_MUTEX(reading_mutex);
      41             : static int data_avail;
      42             : static u8 *rng_buffer, *rng_fillbuf;
      43             : static unsigned short current_quality;
      44             : static unsigned short default_quality = 1024; /* default to maximum */
      45             : 
      46             : module_param(current_quality, ushort, 0644);
      47             : MODULE_PARM_DESC(current_quality,
      48             :                  "current hwrng entropy estimation per 1024 bits of input -- obsolete, use rng_quality instead");
      49             : module_param(default_quality, ushort, 0644);
      50             : MODULE_PARM_DESC(default_quality,
      51             :                  "default maximum entropy content of hwrng per 1024 bits of input");
      52             : 
      53             : static void drop_current_rng(void);
      54             : static int hwrng_init(struct hwrng *rng);
      55             : static int hwrng_fillfn(void *unused);
      56             : 
      57             : static inline int rng_get_data(struct hwrng *rng, u8 *buffer, size_t size,
      58             :                                int wait);
      59             : 
      60             : static size_t rng_buffer_size(void)
      61             : {
      62             :         return SMP_CACHE_BYTES < 32 ? 32 : SMP_CACHE_BYTES;
      63             : }
      64             : 
      65           0 : static void add_early_randomness(struct hwrng *rng)
      66             : {
      67             :         int bytes_read;
      68             : 
      69           0 :         mutex_lock(&reading_mutex);
      70           0 :         bytes_read = rng_get_data(rng, rng_fillbuf, 32, 0);
      71           0 :         mutex_unlock(&reading_mutex);
      72           0 :         if (bytes_read > 0) {
      73           0 :                 size_t entropy = bytes_read * 8 * rng->quality / 1024;
      74           0 :                 add_hwgenerator_randomness(rng_fillbuf, bytes_read, entropy, false);
      75             :         }
      76           0 : }
      77             : 
      78           0 : static inline void cleanup_rng(struct kref *kref)
      79             : {
      80           0 :         struct hwrng *rng = container_of(kref, struct hwrng, ref);
      81             : 
      82           0 :         if (rng->cleanup)
      83           0 :                 rng->cleanup(rng);
      84             : 
      85           0 :         complete(&rng->cleanup_done);
      86           0 : }
      87             : 
      88           0 : static int set_current_rng(struct hwrng *rng)
      89             : {
      90             :         int err;
      91             : 
      92           0 :         BUG_ON(!mutex_is_locked(&rng_mutex));
      93             : 
      94           0 :         err = hwrng_init(rng);
      95           0 :         if (err)
      96             :                 return err;
      97             : 
      98           0 :         drop_current_rng();
      99           0 :         current_rng = rng;
     100             : 
     101             :         /* if necessary, start hwrng thread */
     102           0 :         if (!hwrng_fill) {
     103           0 :                 hwrng_fill = kthread_run(hwrng_fillfn, NULL, "hwrng");
     104           0 :                 if (IS_ERR(hwrng_fill)) {
     105           0 :                         pr_err("hwrng_fill thread creation failed\n");
     106           0 :                         hwrng_fill = NULL;
     107             :                 }
     108             :         }
     109             : 
     110             :         return 0;
     111             : }
     112             : 
     113           0 : static void drop_current_rng(void)
     114             : {
     115           0 :         BUG_ON(!mutex_is_locked(&rng_mutex));
     116           0 :         if (!current_rng)
     117             :                 return;
     118             : 
     119             :         /* decrease last reference for triggering the cleanup */
     120           0 :         kref_put(&current_rng->ref, cleanup_rng);
     121           0 :         current_rng = NULL;
     122             : }
     123             : 
     124             : /* Returns ERR_PTR(), NULL or refcounted hwrng */
     125             : static struct hwrng *get_current_rng_nolock(void)
     126             : {
     127           0 :         if (current_rng)
     128           0 :                 kref_get(&current_rng->ref);
     129             : 
     130           0 :         return current_rng;
     131             : }
     132             : 
     133           0 : static struct hwrng *get_current_rng(void)
     134             : {
     135             :         struct hwrng *rng;
     136             : 
     137           0 :         if (mutex_lock_interruptible(&rng_mutex))
     138             :                 return ERR_PTR(-ERESTARTSYS);
     139             : 
     140           0 :         rng = get_current_rng_nolock();
     141             : 
     142           0 :         mutex_unlock(&rng_mutex);
     143           0 :         return rng;
     144             : }
     145             : 
     146           0 : static void put_rng(struct hwrng *rng)
     147             : {
     148             :         /*
     149             :          * Hold rng_mutex here so we serialize in case they set_current_rng
     150             :          * on rng again immediately.
     151             :          */
     152           0 :         mutex_lock(&rng_mutex);
     153           0 :         if (rng)
     154           0 :                 kref_put(&rng->ref, cleanup_rng);
     155           0 :         mutex_unlock(&rng_mutex);
     156           0 : }
     157             : 
     158           0 : static int hwrng_init(struct hwrng *rng)
     159             : {
     160           0 :         if (kref_get_unless_zero(&rng->ref))
     161             :                 goto skip_init;
     162             : 
     163           0 :         if (rng->init) {
     164             :                 int ret;
     165             : 
     166           0 :                 ret =  rng->init(rng);
     167           0 :                 if (ret)
     168             :                         return ret;
     169             :         }
     170             : 
     171           0 :         kref_init(&rng->ref);
     172           0 :         reinit_completion(&rng->cleanup_done);
     173             : 
     174             : skip_init:
     175           0 :         rng->quality = min_t(u16, min_t(u16, default_quality, 1024), rng->quality ?: 1024);
     176           0 :         current_quality = rng->quality; /* obsolete */
     177             : 
     178           0 :         return 0;
     179             : }
     180             : 
     181           0 : static int rng_dev_open(struct inode *inode, struct file *filp)
     182             : {
     183             :         /* enforce read-only access to this chrdev */
     184           0 :         if ((filp->f_mode & FMODE_READ) == 0)
     185             :                 return -EINVAL;
     186           0 :         if (filp->f_mode & FMODE_WRITE)
     187             :                 return -EINVAL;
     188           0 :         return 0;
     189             : }
     190             : 
     191           0 : static inline int rng_get_data(struct hwrng *rng, u8 *buffer, size_t size,
     192             :                         int wait) {
     193             :         int present;
     194             : 
     195           0 :         BUG_ON(!mutex_is_locked(&reading_mutex));
     196           0 :         if (rng->read)
     197           0 :                 return rng->read(rng, (void *)buffer, size, wait);
     198             : 
     199           0 :         if (rng->data_present)
     200           0 :                 present = rng->data_present(rng, wait);
     201             :         else
     202             :                 present = 1;
     203             : 
     204           0 :         if (present)
     205           0 :                 return rng->data_read(rng, (u32 *)buffer);
     206             : 
     207             :         return 0;
     208             : }
     209             : 
     210           0 : static ssize_t rng_dev_read(struct file *filp, char __user *buf,
     211             :                             size_t size, loff_t *offp)
     212             : {
     213           0 :         ssize_t ret = 0;
     214           0 :         int err = 0;
     215             :         int bytes_read, len;
     216             :         struct hwrng *rng;
     217             : 
     218           0 :         while (size) {
     219           0 :                 rng = get_current_rng();
     220           0 :                 if (IS_ERR(rng)) {
     221           0 :                         err = PTR_ERR(rng);
     222           0 :                         goto out;
     223             :                 }
     224           0 :                 if (!rng) {
     225             :                         err = -ENODEV;
     226             :                         goto out;
     227             :                 }
     228             : 
     229           0 :                 if (mutex_lock_interruptible(&reading_mutex)) {
     230             :                         err = -ERESTARTSYS;
     231             :                         goto out_put;
     232             :                 }
     233           0 :                 if (!data_avail) {
     234           0 :                         bytes_read = rng_get_data(rng, rng_buffer,
     235             :                                 rng_buffer_size(),
     236           0 :                                 !(filp->f_flags & O_NONBLOCK));
     237           0 :                         if (bytes_read < 0) {
     238             :                                 err = bytes_read;
     239             :                                 goto out_unlock_reading;
     240             :                         }
     241           0 :                         data_avail = bytes_read;
     242             :                 }
     243             : 
     244           0 :                 if (!data_avail) {
     245           0 :                         if (filp->f_flags & O_NONBLOCK) {
     246             :                                 err = -EAGAIN;
     247             :                                 goto out_unlock_reading;
     248             :                         }
     249             :                 } else {
     250           0 :                         len = data_avail;
     251           0 :                         if (len > size)
     252           0 :                                 len = size;
     253             : 
     254           0 :                         data_avail -= len;
     255             : 
     256           0 :                         if (copy_to_user(buf + ret, rng_buffer + data_avail,
     257             :                                                                 len)) {
     258             :                                 err = -EFAULT;
     259             :                                 goto out_unlock_reading;
     260             :                         }
     261             : 
     262           0 :                         size -= len;
     263           0 :                         ret += len;
     264             :                 }
     265             : 
     266           0 :                 mutex_unlock(&reading_mutex);
     267           0 :                 put_rng(rng);
     268             : 
     269           0 :                 if (need_resched())
     270           0 :                         schedule_timeout_interruptible(1);
     271             : 
     272           0 :                 if (signal_pending(current)) {
     273             :                         err = -ERESTARTSYS;
     274             :                         goto out;
     275             :                 }
     276             :         }
     277             : out:
     278           0 :         return ret ? : err;
     279             : 
     280             : out_unlock_reading:
     281           0 :         mutex_unlock(&reading_mutex);
     282             : out_put:
     283           0 :         put_rng(rng);
     284           0 :         goto out;
     285             : }
     286             : 
     287             : static const struct file_operations rng_chrdev_ops = {
     288             :         .owner          = THIS_MODULE,
     289             :         .open           = rng_dev_open,
     290             :         .read           = rng_dev_read,
     291             :         .llseek         = noop_llseek,
     292             : };
     293             : 
     294             : static const struct attribute_group *rng_dev_groups[];
     295             : 
     296             : static struct miscdevice rng_miscdev = {
     297             :         .minor          = HWRNG_MINOR,
     298             :         .name           = RNG_MODULE_NAME,
     299             :         .nodename       = "hwrng",
     300             :         .fops           = &rng_chrdev_ops,
     301             :         .groups         = rng_dev_groups,
     302             : };
     303             : 
     304           0 : static int enable_best_rng(void)
     305             : {
     306           0 :         struct hwrng *rng, *new_rng = NULL;
     307           0 :         int ret = -ENODEV;
     308             : 
     309           0 :         BUG_ON(!mutex_is_locked(&rng_mutex));
     310             : 
     311             :         /* no rng to use? */
     312           0 :         if (list_empty(&rng_list)) {
     313           0 :                 drop_current_rng();
     314           0 :                 cur_rng_set_by_user = 0;
     315           0 :                 return 0;
     316             :         }
     317             : 
     318             :         /* use the rng which offers the best quality */
     319           0 :         list_for_each_entry(rng, &rng_list, list) {
     320           0 :                 if (!new_rng || rng->quality > new_rng->quality)
     321           0 :                         new_rng = rng;
     322             :         }
     323             : 
     324           0 :         ret = ((new_rng == current_rng) ? 0 : set_current_rng(new_rng));
     325           0 :         if (!ret)
     326           0 :                 cur_rng_set_by_user = 0;
     327             : 
     328             :         return ret;
     329             : }
     330             : 
     331           0 : static ssize_t rng_current_store(struct device *dev,
     332             :                                  struct device_attribute *attr,
     333             :                                  const char *buf, size_t len)
     334             : {
     335             :         int err;
     336             :         struct hwrng *rng, *old_rng, *new_rng;
     337             : 
     338           0 :         err = mutex_lock_interruptible(&rng_mutex);
     339           0 :         if (err)
     340             :                 return -ERESTARTSYS;
     341             : 
     342           0 :         old_rng = current_rng;
     343           0 :         if (sysfs_streq(buf, "")) {
     344           0 :                 err = enable_best_rng();
     345             :         } else {
     346           0 :                 list_for_each_entry(rng, &rng_list, list) {
     347           0 :                         if (sysfs_streq(rng->name, buf)) {
     348           0 :                                 err = set_current_rng(rng);
     349           0 :                                 if (!err)
     350           0 :                                         cur_rng_set_by_user = 1;
     351             :                                 break;
     352             :                         }
     353             :                 }
     354             :         }
     355           0 :         new_rng = get_current_rng_nolock();
     356           0 :         mutex_unlock(&rng_mutex);
     357             : 
     358           0 :         if (new_rng) {
     359           0 :                 if (new_rng != old_rng)
     360           0 :                         add_early_randomness(new_rng);
     361           0 :                 put_rng(new_rng);
     362             :         }
     363             : 
     364           0 :         return err ? : len;
     365             : }
     366             : 
     367           0 : static ssize_t rng_current_show(struct device *dev,
     368             :                                 struct device_attribute *attr,
     369             :                                 char *buf)
     370             : {
     371             :         ssize_t ret;
     372             :         struct hwrng *rng;
     373             : 
     374           0 :         rng = get_current_rng();
     375           0 :         if (IS_ERR(rng))
     376           0 :                 return PTR_ERR(rng);
     377             : 
     378           0 :         ret = snprintf(buf, PAGE_SIZE, "%s\n", rng ? rng->name : "none");
     379           0 :         put_rng(rng);
     380             : 
     381           0 :         return ret;
     382             : }
     383             : 
     384           0 : static ssize_t rng_available_show(struct device *dev,
     385             :                                   struct device_attribute *attr,
     386             :                                   char *buf)
     387             : {
     388             :         int err;
     389             :         struct hwrng *rng;
     390             : 
     391           0 :         err = mutex_lock_interruptible(&rng_mutex);
     392           0 :         if (err)
     393             :                 return -ERESTARTSYS;
     394           0 :         buf[0] = '\0';
     395           0 :         list_for_each_entry(rng, &rng_list, list) {
     396           0 :                 strlcat(buf, rng->name, PAGE_SIZE);
     397           0 :                 strlcat(buf, " ", PAGE_SIZE);
     398             :         }
     399           0 :         strlcat(buf, "\n", PAGE_SIZE);
     400           0 :         mutex_unlock(&rng_mutex);
     401             : 
     402           0 :         return strlen(buf);
     403             : }
     404             : 
     405           0 : static ssize_t rng_selected_show(struct device *dev,
     406             :                                  struct device_attribute *attr,
     407             :                                  char *buf)
     408             : {
     409           0 :         return sysfs_emit(buf, "%d\n", cur_rng_set_by_user);
     410             : }
     411             : 
     412           0 : static ssize_t rng_quality_show(struct device *dev,
     413             :                                 struct device_attribute *attr,
     414             :                                 char *buf)
     415             : {
     416             :         ssize_t ret;
     417             :         struct hwrng *rng;
     418             : 
     419           0 :         rng = get_current_rng();
     420           0 :         if (IS_ERR(rng))
     421           0 :                 return PTR_ERR(rng);
     422             : 
     423           0 :         if (!rng) /* no need to put_rng */
     424             :                 return -ENODEV;
     425             : 
     426           0 :         ret = sysfs_emit(buf, "%hu\n", rng->quality);
     427           0 :         put_rng(rng);
     428             : 
     429           0 :         return ret;
     430             : }
     431             : 
     432           0 : static ssize_t rng_quality_store(struct device *dev,
     433             :                                  struct device_attribute *attr,
     434             :                                  const char *buf, size_t len)
     435             : {
     436             :         u16 quality;
     437           0 :         int ret = -EINVAL;
     438             : 
     439           0 :         if (len < 2)
     440             :                 return -EINVAL;
     441             : 
     442           0 :         ret = mutex_lock_interruptible(&rng_mutex);
     443           0 :         if (ret)
     444             :                 return -ERESTARTSYS;
     445             : 
     446           0 :         ret = kstrtou16(buf, 0, &quality);
     447           0 :         if (ret || quality > 1024) {
     448             :                 ret = -EINVAL;
     449             :                 goto out;
     450             :         }
     451             : 
     452           0 :         if (!current_rng) {
     453             :                 ret = -ENODEV;
     454             :                 goto out;
     455             :         }
     456             : 
     457           0 :         current_rng->quality = quality;
     458           0 :         current_quality = quality; /* obsolete */
     459             : 
     460             :         /* the best available RNG may have changed */
     461           0 :         ret = enable_best_rng();
     462             : 
     463             : out:
     464           0 :         mutex_unlock(&rng_mutex);
     465           0 :         return ret ? ret : len;
     466             : }
     467             : 
     468             : static DEVICE_ATTR_RW(rng_current);
     469             : static DEVICE_ATTR_RO(rng_available);
     470             : static DEVICE_ATTR_RO(rng_selected);
     471             : static DEVICE_ATTR_RW(rng_quality);
     472             : 
     473             : static struct attribute *rng_dev_attrs[] = {
     474             :         &dev_attr_rng_current.attr,
     475             :         &dev_attr_rng_available.attr,
     476             :         &dev_attr_rng_selected.attr,
     477             :         &dev_attr_rng_quality.attr,
     478             :         NULL
     479             : };
     480             : 
     481             : ATTRIBUTE_GROUPS(rng_dev);
     482             : 
     483           0 : static void __exit unregister_miscdev(void)
     484             : {
     485           0 :         misc_deregister(&rng_miscdev);
     486           0 : }
     487             : 
     488           1 : static int __init register_miscdev(void)
     489             : {
     490           1 :         return misc_register(&rng_miscdev);
     491             : }
     492             : 
     493           0 : static int hwrng_fillfn(void *unused)
     494             : {
     495           0 :         size_t entropy, entropy_credit = 0; /* in 1/1024 of a bit */
     496             :         long rc;
     497             : 
     498           0 :         while (!kthread_should_stop()) {
     499             :                 unsigned short quality;
     500             :                 struct hwrng *rng;
     501             : 
     502           0 :                 rng = get_current_rng();
     503           0 :                 if (IS_ERR(rng) || !rng)
     504             :                         break;
     505           0 :                 mutex_lock(&reading_mutex);
     506           0 :                 rc = rng_get_data(rng, rng_fillbuf,
     507             :                                   rng_buffer_size(), 1);
     508           0 :                 if (current_quality != rng->quality)
     509           0 :                         rng->quality = current_quality; /* obsolete */
     510           0 :                 quality = rng->quality;
     511           0 :                 mutex_unlock(&reading_mutex);
     512             : 
     513           0 :                 if (rc <= 0)
     514             :                         hwrng_msleep(rng, 10000);
     515             : 
     516           0 :                 put_rng(rng);
     517             : 
     518           0 :                 if (rc <= 0)
     519           0 :                         continue;
     520             : 
     521             :                 /* If we cannot credit at least one bit of entropy,
     522             :                  * keep track of the remainder for the next iteration
     523             :                  */
     524           0 :                 entropy = rc * quality * 8 + entropy_credit;
     525           0 :                 if ((entropy >> 10) == 0)
     526           0 :                         entropy_credit = entropy;
     527             : 
     528             :                 /* Outside lock, sure, but y'know: randomness. */
     529           0 :                 add_hwgenerator_randomness((void *)rng_fillbuf, rc,
     530             :                                            entropy >> 10, true);
     531             :         }
     532           0 :         hwrng_fill = NULL;
     533           0 :         return 0;
     534             : }
     535             : 
     536           0 : int hwrng_register(struct hwrng *rng)
     537             : {
     538           0 :         int err = -EINVAL;
     539             :         struct hwrng *tmp;
     540           0 :         bool is_new_current = false;
     541             : 
     542           0 :         if (!rng->name || (!rng->data_read && !rng->read))
     543             :                 goto out;
     544             : 
     545           0 :         mutex_lock(&rng_mutex);
     546             : 
     547             :         /* Must not register two RNGs with the same name. */
     548           0 :         err = -EEXIST;
     549           0 :         list_for_each_entry(tmp, &rng_list, list) {
     550           0 :                 if (strcmp(tmp->name, rng->name) == 0)
     551             :                         goto out_unlock;
     552             :         }
     553           0 :         list_add_tail(&rng->list, &rng_list);
     554             : 
     555           0 :         init_completion(&rng->cleanup_done);
     556           0 :         complete(&rng->cleanup_done);
     557           0 :         init_completion(&rng->dying);
     558             : 
     559           0 :         if (!current_rng ||
     560           0 :             (!cur_rng_set_by_user && rng->quality > current_rng->quality)) {
     561             :                 /*
     562             :                  * Set new rng as current as the new rng source
     563             :                  * provides better entropy quality and was not
     564             :                  * chosen by userspace.
     565             :                  */
     566           0 :                 err = set_current_rng(rng);
     567           0 :                 if (err)
     568             :                         goto out_unlock;
     569             :                 /* to use current_rng in add_early_randomness() we need
     570             :                  * to take a ref
     571             :                  */
     572           0 :                 is_new_current = true;
     573           0 :                 kref_get(&rng->ref);
     574             :         }
     575           0 :         mutex_unlock(&rng_mutex);
     576           0 :         if (is_new_current || !rng->init) {
     577             :                 /*
     578             :                  * Use a new device's input to add some randomness to
     579             :                  * the system.  If this rng device isn't going to be
     580             :                  * used right away, its init function hasn't been
     581             :                  * called yet by set_current_rng(); so only use the
     582             :                  * randomness from devices that don't need an init callback
     583             :                  */
     584           0 :                 add_early_randomness(rng);
     585             :         }
     586           0 :         if (is_new_current)
     587           0 :                 put_rng(rng);
     588             :         return 0;
     589             : out_unlock:
     590           0 :         mutex_unlock(&rng_mutex);
     591             : out:
     592             :         return err;
     593             : }
     594             : EXPORT_SYMBOL_GPL(hwrng_register);
     595             : 
     596           0 : void hwrng_unregister(struct hwrng *rng)
     597             : {
     598             :         struct hwrng *old_rng, *new_rng;
     599             :         int err;
     600             : 
     601           0 :         mutex_lock(&rng_mutex);
     602             : 
     603           0 :         old_rng = current_rng;
     604           0 :         list_del(&rng->list);
     605           0 :         complete_all(&rng->dying);
     606           0 :         if (current_rng == rng) {
     607           0 :                 err = enable_best_rng();
     608           0 :                 if (err) {
     609           0 :                         drop_current_rng();
     610           0 :                         cur_rng_set_by_user = 0;
     611             :                 }
     612             :         }
     613             : 
     614           0 :         new_rng = get_current_rng_nolock();
     615           0 :         if (list_empty(&rng_list)) {
     616           0 :                 mutex_unlock(&rng_mutex);
     617           0 :                 if (hwrng_fill)
     618           0 :                         kthread_stop(hwrng_fill);
     619             :         } else
     620           0 :                 mutex_unlock(&rng_mutex);
     621             : 
     622           0 :         if (new_rng) {
     623           0 :                 if (old_rng != new_rng)
     624           0 :                         add_early_randomness(new_rng);
     625           0 :                 put_rng(new_rng);
     626             :         }
     627             : 
     628           0 :         wait_for_completion(&rng->cleanup_done);
     629           0 : }
     630             : EXPORT_SYMBOL_GPL(hwrng_unregister);
     631             : 
     632           0 : static void devm_hwrng_release(struct device *dev, void *res)
     633             : {
     634           0 :         hwrng_unregister(*(struct hwrng **)res);
     635           0 : }
     636             : 
     637           0 : static int devm_hwrng_match(struct device *dev, void *res, void *data)
     638             : {
     639           0 :         struct hwrng **r = res;
     640             : 
     641           0 :         if (WARN_ON(!r || !*r))
     642             :                 return 0;
     643             : 
     644           0 :         return *r == data;
     645             : }
     646             : 
     647           0 : int devm_hwrng_register(struct device *dev, struct hwrng *rng)
     648             : {
     649             :         struct hwrng **ptr;
     650             :         int error;
     651             : 
     652           0 :         ptr = devres_alloc(devm_hwrng_release, sizeof(*ptr), GFP_KERNEL);
     653           0 :         if (!ptr)
     654             :                 return -ENOMEM;
     655             : 
     656           0 :         error = hwrng_register(rng);
     657           0 :         if (error) {
     658           0 :                 devres_free(ptr);
     659           0 :                 return error;
     660             :         }
     661             : 
     662           0 :         *ptr = rng;
     663           0 :         devres_add(dev, ptr);
     664           0 :         return 0;
     665             : }
     666             : EXPORT_SYMBOL_GPL(devm_hwrng_register);
     667             : 
     668           0 : void devm_hwrng_unregister(struct device *dev, struct hwrng *rng)
     669             : {
     670           0 :         devres_release(dev, devm_hwrng_release, devm_hwrng_match, rng);
     671           0 : }
     672             : EXPORT_SYMBOL_GPL(devm_hwrng_unregister);
     673             : 
     674           0 : long hwrng_msleep(struct hwrng *rng, unsigned int msecs)
     675             : {
     676           0 :         unsigned long timeout = msecs_to_jiffies(msecs) + 1;
     677             : 
     678           0 :         return wait_for_completion_interruptible_timeout(&rng->dying, timeout);
     679             : }
     680             : EXPORT_SYMBOL_GPL(hwrng_msleep);
     681             : 
     682           1 : static int __init hwrng_modinit(void)
     683             : {
     684             :         int ret;
     685             : 
     686             :         /* kmalloc makes this safe for virt_to_page() in virtio_rng.c */
     687           2 :         rng_buffer = kmalloc(rng_buffer_size(), GFP_KERNEL);
     688           1 :         if (!rng_buffer)
     689             :                 return -ENOMEM;
     690             : 
     691           2 :         rng_fillbuf = kmalloc(rng_buffer_size(), GFP_KERNEL);
     692           1 :         if (!rng_fillbuf) {
     693           0 :                 kfree(rng_buffer);
     694           0 :                 return -ENOMEM;
     695             :         }
     696             : 
     697           1 :         ret = register_miscdev();
     698           1 :         if (ret) {
     699           0 :                 kfree(rng_fillbuf);
     700           0 :                 kfree(rng_buffer);
     701             :         }
     702             : 
     703             :         return ret;
     704             : }
     705             : 
     706           0 : static void __exit hwrng_modexit(void)
     707             : {
     708           0 :         mutex_lock(&rng_mutex);
     709           0 :         BUG_ON(current_rng);
     710           0 :         kfree(rng_buffer);
     711           0 :         kfree(rng_fillbuf);
     712           0 :         mutex_unlock(&rng_mutex);
     713             : 
     714           0 :         unregister_miscdev();
     715           0 : }
     716             : 
     717             : fs_initcall(hwrng_modinit); /* depends on misc_register() */
     718             : module_exit(hwrng_modexit);
     719             : 
     720             : MODULE_DESCRIPTION("H/W Random Number Generator (RNG) driver");
     721             : MODULE_LICENSE("GPL");

Generated by: LCOV version 1.14