在内核模块中获取/dev/random

3
我需要在内核模块中获取/dev/random/dev/urandom
提供了get_random_bytes API来获取/dev/urandom
但是没有API来获取/dev/random,所以我尝试在内核空间中使用ioctl和读取文件。以下是我的做法:
1. 使用RNDGETPOOL ioctl
include/linux/random.h中声明了RNDGETPOOL
/* Get the contents of the entropy pool.  (Superuser only.) */
#define RNDGETPOOL      _IOR( 'R', 0x02, int [2] )

但是,它不起作用,所以我查看了driver/char/random.h,发现RNDGETPOOL已经消失了!

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;

    switch (cmd) {
    case RNDGETENTCNT:
            /* inherently racy, no point locking */
            if (put_user(input_pool.entropy_count, p))
                    return -EFAULT;
            return 0;
    case RNDADDTOENTCNT:
            if (!capable(CAP_SYS_ADMIN))
                    return -EPERM;
            if (get_user(ent_count, p))
                    return -EFAULT;
            credit_entropy_bits(&input_pool, ent_count);
            return 0;
    case RNDADDENTROPY:
            if (!capable(CAP_SYS_ADMIN))
                    return -EPERM;
            if (get_user(ent_count, p++))
                    return -EFAULT;
            if (ent_count < 0)
                    return -EINVAL;
            if (get_user(size, p++))
                    return -EFAULT;
            retval = write_pool(&input_pool, (const char __user *)p,
                                size);
            if (retval < 0)
                    return retval;
            credit_entropy_bits(&input_pool, ent_count);
            return 0;
    case RNDZAPENTCNT:
    case RNDCLEARPOOL:
            /* Clear the entropy pool counters. */
            if (!capable(CAP_SYS_ADMIN))
                    return -EPERM;
            rand_initialize();
            return 0;
    default:
            return -EINVAL;
    }
}

我搜索了 谷歌,发现RNDGETPOOL ioctl已经被移除。完成!

  1. using random_read function from driver/char/random.c:997

    static ssize_t random_read(struct file *file, char __user *buf, size_t nbytes, loff_t *ppos)
    

这是我的内核模块访问/dev/random的函数。

static void read_file()
{
  struct file *file;
  loff_t pos = 0;
  //ssize_t wc;
  unsigned char buf_ent[21]={0,};
  int ent_c;
  int i;
  ssize_t length = 0;

  mm_segment_t old_fs = get_fs();
  set_fs(KERNEL_DS);

  file = filp_open("/dev/random", O_WRONLY, 0);
  file->f_op->unlocked_ioctl(file, RNDGETENTCNT, &ent_c);
  if(ent_c < sizeof(char))
  {
    printk("not enough entropy\n");
  }
  printk("ent counter : %d\n", ent_c);

  //file->f_op->unlocked_ioctl(file, RNDGETPOOL, &ent_st.buf);
  length = file->f_op->read(file, buf_ent, ent_c/ 8, &pos);
  if(length <0)
  {
    printk("failed to random_read\n");
  }
  printk("length : %d\n", length);
  printk("ent: ");
  for(i=0;i<length; i++)
  {
      printk("%02x", buf_ent[i]);
  }
  printk("\n");
  filp_close(file,0);
  set_fs(old_fs);
}

输出似乎是随机的。

第一次尝试

[1290902.992048] ent_c : 165  
[1290902.992060] length : 20  
[1290902.992060] ent: d89290f4a5eea8e087a63943ed0129041e80b568

第二次尝试

[1290911.493990] ent_c : 33  
[1290911.493994] length : 4  
[1290911.493994] ent: 7832640a  

顺便说一下,random_read 函数的参数中有 __user 关键字。代码中的 buf 在内核空间中。
在内核空间中使用 random_read 函数是否合适?

输出似乎是随机的。- https://xkcd.com/221/ - 0andriy
你为什么认为你需要从两个池中获取比特? - CL.
1个回答

3

获取随机字节的内核接口是get_random_bytes()

static void read_file(void)
{
    unsigned char buf_ent[21];

    get_random_bytes(buf_ent, 21);
    print_hex_dump_bytes("ent: ", DUMP_PREFIX_NONE, buf_ent, 21);
}

是的,有针对/dev/urandom的get_random_bytes函数,但我希望读取/dev/random。 - Sangpil Kim

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接