我希望有人可以解释linux内核源代码中使用的__user宏的细微差别。
首先,宏:
# define __user __attribute__((noderef, address_space(1)))
现在,经过一些谷歌搜索后,我读到这个宏允许指定一个指针属于用户地址空间,并且不应该取消引用它。
我可能会遗漏一些明显的事实,但有人可以解释这样一个宏的含义吗?例如,这个宏的使用位置有什么好的例子?如果我错过了一些明显的东西,请再次原谅我。
在某些情况下,我在检查一些USB代码(linux / usbdevice_fs.h)时遇到了宏。我只是在寻找对这个宏(或其他类似的)在内核中使用的一般理解。
感谢您的期待!
答案 0 :(得分:40)
它允许像sparse这样的工具告诉内核开发人员他们可能使用不受信任的指针(或者在当前虚拟地址映射中可能无效的指针)。
答案 1 :(得分:32)
我认为__user标记用户空间指针并告诉开发人员/系统不要信任它。如果用户给你“无效”指针,那么内核会尝试引用它(注意内核可以在任何地方引用)并且它可以破坏它自己的空间。
例如在“read”(在你的usbdevice_fs.h中)应该为你提供一个(__ user)缓冲区来写结果。所以你必须使用copy_to_user,但不能使用memcopy,strcpy或类似的东西。
注意:这不是正式的定义/描述,而是我所知道的唯一部分。
答案 2 :(得分:7)
__user
宏在compiler.h头文件中定义了一些其他宏,如__force
/ __kernel
等。它们实际上对传统编译器没有任何用处,包括GCC / ICC等。但它对稀疏的内核静态分析工具很有用(更多信息在这里:Sparse - Linux Kernel Newbies)。当你提到像__user
/ __kernel
/ __force
等宏时,它对稀疏有特殊意义。在Linux内核邮件列表中,Linus Torvalds解释了它的用法:
重要的是要记住:对于gcc,稀疏注释是没有意义的。它们仍然可以用来告诉程序员"嘿,你得到的指针不是普通指针"以一种相当可读的方式,但最后,除非你使用稀疏,否则他们实际上做任何东西。
但是。当你做使用解析时,完全是另一回事。对于"稀疏",那" __ iomem"有很多意思:
# define __iomem __attribute__((noderef, address_space(2)))
ie" iomem"意味着两个不同的东西:它意味着稀疏应该抱怨
如果指针被直接取消引用(它是" noderef"指针),它就在地址空间2"而不是正常的地址空间(0)。
现在,这意味着稀疏会抱怨如果这样的指针传递到想要常规指针的函数(因为它不是正常指针,并且你显然不应该做像#34; strcmp()"等的事情,如果你试图将它转换为另一个地址空间中的另一个指针,稀疏也会抱怨。