【问题标题】:Setting device permission from driver code fails从驱动程序代码设置设备权限失败
【发布时间】:2017-12-09 00:00:35
【问题描述】:

我想从 linux 内核 3.10.14 中的用户空间访问 I2C 设备驱动程序节点。 我在内核配置中添加了 i2c-dev 并获得了 /dev/i2c-* 设备节点。但是他们有权限

$ ls -l /dev/i2c-*
crw------- root     root      89,   1 2014-08-21 20:00 i2c-1

在 drivers/i2c/i2c-dev.c 我添加了回调

static char *i2c_dev_devnode(struct device *dev, umode_t *mode)
{
    if (!mode)
            return NULL;
    if (MAJOR(dev->devt) == I2C_MAJOR)
            *mode = 0666;
    return NULL;
}

在同一个文件中,我将回调添加到设备类结构中:

static int __init i2c_dev_init(void)
{
   ...
   i2c_dev_class = class_create(THIS_MODULE, "i2c-dev");
   ...

    /* set access rights */
    i2c_dev_class->devnode = i2c_dev_devnode;
   ...
}

但是设备节点的访问权限仍然存在

crw------- root     root      89,   1 2014-08-21 20:00 i2c-1

没有 /lib/udev/rules.d 或 /etc/udev/rules.d

如果有任何可能出现问题的建议,我将不胜感激。

我也对如何测试这个问题的想法感兴趣。

【问题讨论】:

    标签: linux-device-driver


    【解决方案1】:

    您可以尝试以下方法。这至少适用于内核 4.9.56。

    static int my_uevent(struct device *dev, struct kobj_uevent_env *env)
    {
        add_uevent_var(env, "DEVMODE=%#o", 0666);
        return 0;
    }
    
    static int __init i2c_dev_init(void)
    {
       ...
       i2c_dev_class = class_create(THIS_MODULE, "i2c-dev");
       ...
    
       /* set access rights */
       i2c_dev_class->dev_uevent = my_uevent;
       ...
    }
    

    【讨论】:

      【解决方案2】:

      我理解devnode回调函数的返回值不能是“NULL”,而是设备节点名。 所以, 将函数返回值从“NULL”更改为 devname。参考代码:

      ------------------------补丁--------

      diff --git a/drivers/i2c/i2c-dev.c b/drivers/i2c/i2c-dev.c
      index 6f638bb..35a42c6 100644
      --- a/drivers/i2c/i2c-dev.c
      +++ b/drivers/i2c/i2c-dev.c
      @@ -614,6 +614,14 @@ static int i2cdev_notifier_call(struct notifier_block *nb, unsigned long action,
          .notifier_call = i2cdev_notifier_call,
       };
      
      +static char *i2c_dev_devnode(struct device *dev, umode_t *mode)
      +{
      +   printk("\n\n****%s: %d\n\n",__func__,__LINE__);
      +    if (mode != NULL)
      +            *mode = 0666;
      +    return kasprintf(GFP_KERNEL, "i2cr/%s", dev_name(dev));;
      +}
      +
       /* ------------------------------------------------------------------------- */
      
       /*
      @@ -636,7 +644,12 @@ static int __init i2c_dev_init(void)
              goto out_unreg_chrdev;
          }
          i2c_dev_class->dev_groups = i2c_groups;
      +   /* set access rights */
      +   printk(KERN_INFO "i2c setting devnode\n");
      +   i2c_dev_class->devnode = i2c_dev_devnode;
      +
      
      +   
          /* Keep track of adapters which will be added or removed later */
          res = bus_register_notifier(&i2c_bus_type, &i2cdev_notifier);
          if (res)
      

      结果: 不应用此补丁:

      root@x86-generic-64:~# ls -l /dev/i2c-*
      crw------- 1 root root 89,  0 Nov  1 13:47 /dev/i2c-0
      crw------- 1 root root 89,  1 Nov  1 13:47 /dev/i2c-1
      

      带补丁:

      root@x86-generic-64:~# ls -l /dev/i2cr/*     
      crw-rw-rw- 1 root root 89,  0 Nov  1 13:38 /dev/i2cr/i2c-0
      crw-rw-rw- 1 root root 89,  1 Nov  1 13:38 /dev/i2cr/i2c-1
      

      【讨论】:

      • 这并没有改变设备文件的权限。
      • 在drivers/i2c/i2c-dev.c中我还找到了定义设备属性的辅助宏DEVICE_ATTR:它被用作:static DEVICE_ATTR(foo, S_IRUGO, show_foo, store_foo);所以 /dev/i2c-* 的权限应该是 cr--r--r-- 但不是。
      • 我为你测试了这个。这工作完美。低于补丁和测试资源。
      • 我无法在此处添加更长的文本.. 所以编辑了带有工作补丁和结果的答案。希望这会有所帮助。
      • 感谢您的所有帮助。但是在我的设置中似乎忽略了返回值(i2cr/%s),因为没有创建目录 /dev/i2cr(或者您是否手动创建了它?)我现在通过 chmod 0666 /dev/i2c-* 设置权限在 init.rc 中
      【解决方案3】:

      设置设备节点是 udev 的责任。所以我们需要使用正确的udev规则。如果驱动程序在引导时间之后加载,例如如果它是可加载模块,则进一步的 init.rc 方法将失败。您的发行版可能正在使用另一种支持热插拔的方式,因此我们需要查阅有关该发行版的文档。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 2021-01-18
        • 2015-09-27
        • 2012-01-05
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多