您的位置:首页 > 其它

USB设备访问管理

2015-11-24 14:01 369 查看
主题是面向某一用户空间的设备访问管理。

大家都知道通常的设备访问流程是:内核设备驱动,包括usb驱动,一般情况下是通过kobject_uevent接口上报uevent消息到用户空间,由用户管理进程,如udevd、ueventd等接收uevent消息,然后解析,创建设备文件节点。之后,设备访问程序才能通过设备文件节点访问操作设备。

管理方法讨论

如果不希望用户空间访问某设备,最直接的方法是不提供相应设备驱动;次之,在koject_uevent接口过滤设备上报消息;再次之,由用户空间的设备管理进程过滤设备上报消息。

多用户空间下,如果不希望某一用户空间访问某设备,沿用上一思路,可以在具体的用户空间的设备管理进程过滤设备上报消息。那么问题来了,是否还有其他方法呢?答案是肯定的。linux2.6.24引入内核的cgroup功能,有1个device cgroup子系统,可以管理进程控制组内的进程是否能够访问某些设备节点。devices.allow指定 cgroup 中的任务可访问的设备,devices.deny指定 cgroup 中的任务禁止访问的设备。每个条目有四个字段:type、major、minor 和 access。type、major
和 minor 字段中使用的值对应 Linux 分配的设备,也称 Linux 设备列表中指定的设备类型和节点数。控制条目如下:
a 8:* rwm

其中,

a, 代表所有设备类型,也可以为b或c分别代表block块设备、character字符设备

b, 8代表设备的主设备号

c, *代表主设备号下的所有次设备号,可以根据需要指定为具体的值

d, r代表读权限、w代表写权限、m代表生成设备文件权限

将该条目写入dev cgroup组A的devices.allow,组A中的所有进程都可以操作该条目所匹配的设备;将该条目写入dev cgroup组A的devices.deny,组A中的所有进程都被禁止操作该条目所匹配的设备。
判定条件选取

通过venderId和productId作为判定条件,难以穷举所有的设备。我们就希望能够可以通过usb的接口设备类型来作为判定条件,而且usb驱动本身是定义了不同的接口类型(在ch9.h中)。

1个简单usb设备插入主机后,usb驱动上报消息的流程依次为:

usb_device、usb_interface、(分层封装设备)

它们也依次为父子关系,所以,可以通过寻找父亲的方式,找到设备对应的usb_interface、usb_device。(
InterfaceClass定义在usb_interface中,venderId和productId定义在usb_device中)

调整验证代码如下:

/*获取设备的venderId、productId和接口类型*/

dev = container_of(kobj, struct device,kobj);

if (NULL != dev)

{

structdevice *tdev = dev;

do{

if (tdev->type && tdev->type->name)

{

if(!strcmp("usb_interface", tdev->type->name))

{

intf =to_usb_interface(tdev);

iClass =intf->cur_altsetting->desc.bInterfaceClass;

}

if(!strcmp("usb_device", tdev->type->name))

{

udev = container_of(tdev,struct usb_device, dev);

Vid = le16_to_cpu(udev->descriptor.idVendor);

Pid = le16_to_cpu(udev->descriptor.idProduct);

break;

}

}

tdev = tdev->parent;

}while(tdev);

}

/*以或的方式判定*/

if ( iClass || ( Vid && Pid) )

{

if (MAJOR(dev->devt)) {

if ( (0x090c == Vid &&0x1000== Pid)||\

(0x10c4 == Vid &&0xea60== Pid) ||\

USB_CLASS_MASS_STORAGE == iClass)

{

/*wangshixin, modify dev cgroupto control device access*/

file =filp_open(DEV_CG_ANDROID, O_WRONLY|O_APPEND, 0644);

if (IS_ERR(file))

{

printk("error occuredwhile opening file %s", DEV_CG_ANDROID);

}

else

{

sprintf(buf, "a %d:%drwm", MAJOR(dev->devt), MINOR(dev->devt));

printk(KERN_DEBUG"#uevent---%d:%d\n", MAJOR(dev->devt),MINOR(dev->devt));

old_fs = get_fs();

set_fs(KERNEL_DS);

retval =file->f_op->write(file, (char*)buf, 15, &file->f_pos);

set_fs(old_fs);

filp_close(file, NULL);

}

}

}

}

经过调测,以上代码是可信的。不仅对内核无具体驱动的usb设备有效,而且对通用的多层驱动设备(如通用U盘)有效。这是比较理想的结果。

课题诞生初期就产生了两个思路:1)不同用户空间独立控制访问;2)通过device cgroup内核集中控制访问。思路1)优点是比较简单,用户空间逻辑便于理解,缺点是不同用户空间要维护多份,而且存在一致的情况;思路2)缺点是技术难度相对较大,在有限的时间内可能难以取得比较理想的控制效果,优点是取得理想效果后,维护简单、易于移植。

这里的验证没有涉及控制配置文件的设计与读写,因为这不是很难的事情。这里给出建议:控制配置文件做成1个内核驱动(配置条目做成链表),上述实施的条件判断修改为遍历链表比对,对控制配置文件的写只有1个实体(可以是对外的控制中心),实施时使用锁避免链表访问异常。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: