2010-12-23 94 views
45

我希望有人能够解释linux内核源代码中使用的__user宏的细微差别。linux __user宏的含义是什么?

首先,宏:

# define __user   __attribute__((noderef, address_space(1))) 

现在,经过了一些谷歌上搜索我读到这个宏允许一个指定的指针为属于用户地址空间,而且它不应该被取消引用。

我可能会遗漏一些明显的事实,但有人可以解释这样一个宏的含义吗?例如,这个宏可以用在哪里的例子是什么?再次,原谅我,如果我失去了明显的东西。

为了说明这一点,我在考察一些USB代码(linux/usbdevice_fs.h)的同时,探讨了这个宏。我只是在寻找对这个宏(或其他类似宏)在内核中使用的一般理解。

感谢您的期待!

+2

有关示例,请参阅do_execve()源代码。 看看在count()中如何使用argv。 如果你只是取消引用(* argv [0])或者什么, 稀疏(1)会警告它。 address_space表示并非所有的指针都是相等的,需要不同的(解除引用)规则,不应该混合使用。 – adobriyan 2010-12-24 17:12:29

回答

33

它允许像sparse这样的工具告诉内核开发者他们可能使用了一个不可信的指针(或者在当前虚拟地址映射中可能无效的指针)。

+0

所以`__attribute __()`可以使用任何文本作为“属性”?它不限于对GCC本身有意义的固定集合? – 2015-03-23 20:10:50

+0

@AlexD从[GCC属性语法手册](https://gcc.gnu.org/onlinedocs/gcc/Attribute-Syntax.html):`属性说明符的形式是__attribute__((attribute-list))。属性列表可能是空的逗号分隔的属性序列,其中每个属性都是以下属性之一:1.空。空属性被忽略。 ** 2。一个属性名称(可能是一个标识符,如未使用的,或保留字,如const)。**(...)`。它似乎可以是任何你想要的标识符(使用标识符命名约定)。 – 2015-12-30 18:45:55

27

我认为__user标记用户空间指针,并告诉开发者/系统不要信任它。如果用户给你“无效”指针,那么内核会尝试引用它(请注意,内核可以在任何地方引用),并且它可以破坏它自己的空间。

例如在“读”(在你usbdevice_fs.h)应该提供一个(__user)缓冲区来写结果。所以你必须使用copy_to_user,而不是memcopy,strcpy或类似的东西。

注意:这不是正式的定义/描述,而是我所知道的唯一部分。

2

__user宏在compiler.h头文件中用一些其他宏定义,如__force/__kernel等。它们实际上对传统编译器(包括GCC/ICC等)没有任何用处,但对于稀疏等内核静态分析工具很有用(此处更多信息:稀疏 - Linux内核新手)。当你提到像__user/__kernel/__force等宏时,它对稀疏保持特殊含义。在Linux内核邮件列表中,Linus Torvalds解释了如何使用它:

这很重要,要记住:对于gcc,稀疏注释是没有意义的。它们仍然可以用于告诉编程人员“嘿,你得到的指针不是一个正常的指针”,但是最终,除非你使用稀疏,否则它们实际上并不是什么都可以。

然而,当你使用解析时,完全是另一回事。对于“疏”,即“__iomem”有很多含义:

# define __iomem __attribute__((noderef, address_space(2))) 

即“IOMEM”是指两个不同的东西:这意味着稀疏应该抱怨

如果指针永远取消引用(这是一个“ noderef“指针),它位于”地址空间2“中,而不是普通地址空间(0)。

现在,这意味着,如果这样的指针永远传递到想要一个普通指针(函数稀疏会抱怨,因为它是正常的指针,你显然不应该做这样的事情“ strcmp()“等),而稀疏也会抱怨,如果你试图将它转换到另一个地址空间中的另一个指针。