在看 scull 驱动的 ioctl 代码之前, 我们需要涉及的另一点是如何使用这个额外的参数. 如果它是一个整数, 就容易: 它可以直接使用. 如果它是一个指针, 但是, 必须小心些.

当用一个指针引用用户空间, 我们必须确保用户地址是有效的. 试图存取一个没验证过的 用户提供的指针可能导致不正确的行为, 一个内核 oops, 系统崩溃, 或者安全问题. 它 是驱动的责任来对每个它使用的用户空间地址进行正确的检查, 并且返回一个错误如果它 是无效的.

在第 3 章, 我们看了 copy_from_user 和 copy_to_user 函数, 它们可用来安全地移动 数据到和从用户空间. 这些函数也可用在 ioctl 方法中, 但是 ioctl 调用常常包含小数 据项, 可通过其他方法更有效地操作. 开始, 地址校验(不传送数据)由函数 access_ok 实现, 它定义在 <asm/uaccess.h>:

int access_ok(int type, const void *addr, unsigned long size);

第一个参数应当是 VERIFY_READ 或者 VERIFY_WRITE, 依据这个要进行的动作是否是读用 户空间内存区或者写它. addr 参数持有一个用户空间地址, size 是一个字节量. 例如, 如果 ioctl 需要从用户空间读一个整数, size 是 sizeof(int). 如果你需要读和写给定 地址, 使用 VERIFY_WRITE, 因为它是 VERIRY_READ 的超集.

不象大部分的内核函数, access_ok 返回一个布尔值: 1 是成功(存取没问题)和 0 是失 败(存取有问题). 如果它返回假, 驱动应当返回 -EFAULT 给调用者.

关于 access_ok 有多个有趣的东西要注意. 首先, 它不做校验内存存取的完整工作; 它只 检查看这个内存引用是在这个进程有合理权限的内存范围中. 特别地, access_ok 确保这 个地址不指向内核空间内存. 第 2, 大部分驱动代码不需要真正调用 access_ok. 后面描 述的内存存取函数为你负责这个. 但是, 我们来演示它的使用, 以便你可见到它如何完成.

scull 源码利用了 ioclt 号中的位段来检查参数, 在 switch 之前: int err = 0, tmp;

int retval = 0;

/*

*  extract the type and number bitfields, and don't decode

*  wrong cmds: return ENOTTY (inappropriate ioctl) before access_ok()

*/

if (_IOC_TYPE(cmd) != SCULL_IOC_MAGIC)

return -ENOTTY;

if (_IOC_NR(cmd) > SCULL_IOC_MAXNR)

return -ENOTTY;

/*

*  the direction is a bitmask, and VERIFY_WRITE catches R/W

*  transfers. `Type' is user-oriented, while

*  access_ok is kernel-oriented, so the concept of "read" and

*  "write" is reversed

*/

if (_IOC_DIR(cmd) & _IOC_READ)

err = !access_ok(VERIFY_WRITE, (void user *)arg, _IOC_SIZE(cmd)); else if (_IOC_DIR(cmd) & _IOC_WRITE)

err = !access_ok(VERIFY_READ, (void   user *)arg, _IOC_SIZE(cmd));

if (err)

return -EFAULT;

在调用 access_ok 之后, 驱动可安全地进行真正的传输. 加上 copy_from_user 和 copy_to_user_ 函数, 程序员可利用一组为被最多使用的数据大小(1, 2, 4, 和 8 字节) 而优化过的函数. 这些函数在下面列表中描述, 它们定义在 <asm/uaccess.h>:

put_user(datum, ptr)

put_user(datum, ptr)

这些宏定义写 datum 到用户空间; 它们相对快, 并且应当被调用来代替 copy_to_user 无论何时要传送单个值时. 这些宏已被编写来允许传递任何类型的 指针到 put_user, 只要它是一个用户空间地址. 传送的数据大小依赖 prt 参数的 类型, 并且在编译时使用 sizeof 和 typeof 等编译器内建宏确定. 结果是, 如果 prt 是一个 char 指针, 传送一个字节, 以及对于 2, 4, 和 可能的 8 字节.

put_user 检查来确保这个进程能够写入给定的内存地址. 它在成功时返回 0, 并 且在错误时返回 -EFAULT. put_user 进行更少的检查(它不调用 access_ok), 但是仍然能够失败如果被指向的内存对用户是不可写的. 因此, put_user 应当 只用在内存区已经用 access_ok 检查过的时候.

作为一个通用的规则, 当你实现一个 read 方法时, 调用 put_user 来节省几个 周期, 或者当你拷贝几个项时, 因此, 在第一次数据传送之前调用 access_ok 一 次, 如同上面 ioctl 所示.

get_user(local, ptr)

get_user(local, ptr)

这些宏定义用来从用户空间接收单个数据. 它们象 put_user 和 put_user, 但 是在相反方向传递数据. 获取的值存储于本地变量 local; 返回值指出这个操作是 否成功. 再次,   get_user 应当只用在已经使用 access_ok 校验过的地址.

如果做一个尝试来使用一个列出的函数来传送一个不适合特定大小的值, 结果常常是一个 来自编译器的奇怪消息, 例如"coversion to non-scalar type requested". 在这些情况 中, 必须使用 copy_to_user 或者 copy_from_user.

转载于:https://www.cnblogs.com/fanweisheng/p/11141815.html

linux 使用 ioctl 参数相关推荐

  1. linux驱动---ioctl函数解析

    转自(39条消息) linux驱动---ioctl函数解析_那可真是太开心了的博客-CSDN博客_linux驱动ioctl 参考:ioctl,unlocked_ioctl 处理方法-阿里云开发者社区 ...

  2. Linux mail 命令参数

    linux mail 命令参数: 使用mail发邮件时,必须先将sendmail服务启动. mail –s "邮件主题" –c"抄送地址" –b "密 ...

  3. linux mount命令参数及用法详解

    linux mount命令参数及用法详解 非原创,主要来自 http://www.360doc.com/content/13/0608/14/12600778_291501907.shtml. htt ...

  4. The Linux SG_IO ioctl in the 2.6 series

    http://gmd20.blog.163.com/blog/static/1684392320100227396270/ 原文地址:http://sg.danny.cz/sg/sg_io.html ...

  5. sort+参数+linux,linux sort下令参数及用法详解

    linux sort命令参数及用法详解 功能说明:将文本文件内容加以排序. 语 法:sort[-bcdfimMnr][-o][-t][+-][--help][--verison][文件] 补充说明:s ...

  6. linux中group命令详解,linux groupmod命令参数及用法详解

    需要更改群组的识别码或名称时,可用groupmod指令来完成这项工作.接下来是小编为大家收集的linux groupmod命令参数及用法详解,希望能帮到大家. linux groupmod命令参数及用 ...

  7. linux 的内核参数优化,Linux服务器内核参数优化

    Linux服务器内核参数优化 cat >> /etc/sysctl.conf << EOF #kernel optimization net.ipv4.tcp_fin_time ...

  8. linux的usermod命令参数,linux usermod命令参数及用法详解

    linuxusermod命令参数及用法详解,linux修改用户账号信息命令,usermod可用来修改用户帐号的各项设定.接下来是小编为大家收集的linux usermod命令参数及用法详解,欢迎大家阅 ...

  9. linux进程泄露命令明文参数,sshpass 使Linux可以明文参数输入SSH密码(示例代码)

    sshpass 使Linux可以明文参数输入SSH密码 这几天配置一台服务器,在某云平台创建云服务器后,生成了巨长.巨复杂的一串密码,在输入几十次密码后,依然是密码错误.这时候就想如果密码是非交互式输 ...

  10. linux :Tar 命令参数详解

    linux Tar 命令参数详解 tar命令 1. 作用 tar命令是Unix/Linux系统中备份文件的可靠方法,几乎可以工作于任何环境中,它的使用权限是所有用户. 2. 格式 tar [主选项+辅 ...

最新文章

  1. spire.doc 转html,c# html 转Word--Spire.Doc
  2. 在ASP.Net2.0中使用UrlRewritingNet实现链接重写(转)
  3. Azure Remoteapp 使用指南
  4. 二、制作最小linux系统
  5. Postgresql 字符串操作函数
  6. OpenCV相机运动估计
  7. 2020倩女幽魂服务器正在维修,倩女幽魂手游2020年12月3日维护公告
  8. 个人作业2——英语学习APP的案例分析
  9. Arrays工具、二维数组以及LeetCode练习题
  10. Zegraph遇到的一个崩溃的问题
  11. 全屏动态滑稽网站HTML源码
  12. windows下网络测试工具
  13. 时间漩涡的世界 (三)
  14. 关于linux的最新问题合集
  15. Perfmon - Windows 自带系统监测工具
  16. java导出excel 边框不全_POI导出excel,合并单元格后没有边框
  17. 购物车的制作 与注册表单验证
  18. arch linux yaourt arm,在ARM設備(樹莓派、香蕉派)上為Arch Linux配置yaourt
  19. 去掉无序列表前默认加上的小圆点——实战练习需到的问题解决办法mark
  20. 【太虚AR_v0.1】使用教程 | SLAM(Markerless)

热门文章

  1. linux没有.brashrc文件,Linux 安装 Redis4.0.6
  2. 学生选课系统代码-1start.py代码
  3. list里面的数据按3个字段排序_springboot2.X手册:redis的7种类型100个方法全解析
  4. CS224N刷题——Assignment1.4_情感分析
  5. 在Nutz中给Druid配置数据库加密
  6. 怎样通过java用web3j查询以太坊交易信息?
  7. MYSQL5.5.48编译安装
  8. ElasticSearch(1)CentOS安装ElasticSearch测试CRUD
  9. blogCommed
  10. 【转载】如何在Ubuntu上安装LAMP服务器系统?