Подтвердить что ты не робот

Каковы последствия макросов linux __user?

Я надеялся, что кто-то сможет объяснить нюансы макроса __user, используемого в источнике ядра linux.

Прежде всего, макрос:

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

Теперь, после некоторого поиска в Google, я прочитал, что этот макрос позволяет назначить указатель как принадлежащий к адресному пространству пользователя и что он не должен быть разыменован.

Возможно, мне не хватает некоторых очевидных фактов, но кто-то может объяснить последствия такого макроса? Например, что является хорошим примером того, где этот макрос будет полезен? Опять же, простите меня, если я упустил что-то очевидное.

Чтобы добавить это в какой-то контекст, я пришел через макрос, изучая некоторый код USB (linux/usbdevice_fs.h). Я ищу только общее понимание этих макросов (или других подобных им) в ядре.

Спасибо, что посмотрели!

4b9b3361

Ответ 1

Он позволяет использовать такие инструменты, как sparse, чтобы сообщить разработчикам ядра, что они, возможно, используют ненадежный указатель (или указатель, который может быть недействительным в текущем сопоставлении виртуальных адресов).

Ответ 2

Я думаю, что __user помещает указатели на пространство пользователя и говорит разработчику/системе не доверять ему. Если пользователь дает вам "недействительный" указатель, то ядро ​​пытается ссылаться на него (обратите внимание, что ядро ​​может ссылаться повсюду), и оно может испортить его собственное пространство.

Например, в "read" (у вас usbdevice_fs.h) должен быть предоставлен вам буфер (__user) для записи результата. Поэтому вам нужно использовать copy_to_user, но не memcopy, strcpy или что-то вроде этого.

Примечание. Это не формальное определение/описание, а единственная часть, о которой я знаю.

Ответ 3

Макрос __user определяется с помощью некоторых других макросов, таких как __force/__kernel и т.д. в заголовочном файле compiler.h. На самом деле они не используются традиционными компиляторами, в том числе GCC/ICC и т.д. Но это полезно для инструментов статического анализа ядра, таких как разреженные (более подробная информация здесь: Sparse - Linux Kernel Newbies). Когда вы указываете макросы типа __user/__kernel/__force и т.д., Он сохраняет особое значение для разреженных. В списке рассылки ядра Linux Linus Torvalds объясняет его использование следующим образом:

Это важно помнить: для gcc разреженные аннотации бессмысленны. Они все еще могут быть полезны только для того, чтобы сказать программисту, что "эй, этот указатель, который вы получили, не был нормальным указателем" в довольно читаемом виде, но, в конце концов, если вы не используете разреженный язык, они фактически ничего не делают.

ОДНАКО. Когда вы используете синтаксический анализ, это совсем другое дело. Для "редкого", что "__iomem" имеет много смысла:

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

т.е. "iomem" означает две отдельные вещи: это означает, что разреженный должен жаловаться

если указатель когда-либо разыменован (он указатель "noderef" ) напрямую, и он находится в "адресном пространстве 2" в отличие от обычного адресного пространства (0).

Теперь это означает, что разреженный будет жаловаться, если такой указатель когда-либо передается в функцию, которая хочет регулярного указателя (потому что это не обычный указатель, и вы, очевидно, не должны делать такие вещи, как "strcmp()" и т.д. на нем), а разреженный будет также жаловаться, если вы попытаетесь передать его другому указателю в другом адресном пространстве.