Каковы последствия макроса linux __user? - PullRequest
55 голосов
/ 23 декабря 2010

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

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

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

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

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

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

Спасибо за внимание!

Ответы [ 3 ]

41 голосов
/ 23 декабря 2010

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

32 голосов
/ 30 декабря 2010

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

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

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

8 голосов
/ 29 июня 2016

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

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

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

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

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

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

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

...