Ядро Linux в комментариях

Do_sysctl_strategy


Функция do_sysctl_strategy выполняет чтение и/или запись данных в отдельном объекте ctl_table. Ее замысел состоит в использовании члена strategy данного элемента таблицы, если он присутствует, для выполнения чтения/записи. Если данный элемент таблицы не имеет свою собственную strategy-процедуру, вместо нее используется некоторый универсальный код чтения/записи. Как будет показано ниже, функция работает именно так, как задумано.

Если значение oldval отлично от NULL, вызывающая программа пытается прочитать старое значение, поэтому в переменной ор устанавливается бит r. Аналогичным образом, если отлично от NULL значение newval, устанавливается бит w. Затем в строке выполняется проверка прав доступа и возвращается ошибка EPERM, если текущий процесс не имеет соответствующих прав.

Если данный вход таблицы имеет свою собственную strategy-процедуру, эта процедура получает шанс выполнить запрос на чтение/запись. Если она возвращает отрицательное значение (ошибку), ошибка передается вызывающей программе. Если она возвращает положительное значение, вызывающей программе передается 0 (успех). Если strategy-процедура возвращает 0, это значит, что она отказалась сама выполнить запрос, и вместо нее будет использоваться правило поведения, принятое по умолчанию. (Вполне можно представить себе strategy-процедуру, которая всегда будет возвращать только 0, но все равно будет иметь право на существование, если ей будет поручена какая-то другая работа, например, сбор статистической информации о том, как часто происходил ее вызов.)

Это начало универсального кода чтения. Обратите внимание, что возвращаемое значение функции get_user (строка ) не проверяется. (Аналогичная ошибка возникает в строках и .)

Проверка того, что будет возвращено не больше данных, чем указано в поле maxlen данного входа таблицы.

Копирует затребованные данные из таблицы с помощью oldval и сохраняет фактически считанный объем данных с помощью oldlenp.

Аналогично oldlenp, проверка того, что в данный вход таблицы не может быть записано больше данных, чем допускает его член maxlen. Обратите внимание, что может оказаться выполненным только частичное обновление члена table->data, если в ходе выполнения функции copy_from_user в строке будет обнаружена ошибка.


Возвращает 0 в качестве обозначения успеха. Эта точка достигается в любом из следующих трех случаев:

  • Вызывающая программа не пыталась ни читать, ни писать в этот вход таблицы.


  • Вызывающая программа пыталась читать и/или писать в этот вход таблицы и все этапы на этом пути были успешными.


  • Этот вход таблицы не имеет связанных с ним данных или он фактически предназначен только для чтения, поскольку его значение maxlen равно0.


  • Первый из этих случаев в определенной степени удивителен, а последний удивляет еще больше. В первом случае удивительным является то, что вызов sysctl без запроса ни на чтение, ни на запись в указанный вход таблицы не имеет смысла, поэтому такой вызов можно на законных основаниях рассматривать как ошибку. Тем не менее, он в целом соответствует принципам реализации в ядре других системных вызовов, согласно которым запрос пустой команды не является ошибкой. Например, функция sys_brk (строка ), рассматриваемая в , не сообщает об ошибке, если новое значение brk, которое указано вызывающей программой, совпадает со старым значением.

    Третий случай является более удивительным по сравнению с первым, поскольку он действительно может свидетельствовать об ошибке. Вызывающий код может, например, попытаться выполнить запись в параметр, для которого значение maxlen равно 0, и посчитать, что эта попытка удалась, поскольку системный вызов возвратил значение, свидетельствующее об успехе. Однако создается впечатление, что это в действительности не имеет значения, поскольку вход таблицы со значением maxlen равным 0, является бесполезным во всех отношениях; тем не менее, в коде есть вход таблицы со значением maxlen равным 0 — см. строку . В конечном итоге, все это сводится к тому, что в действительности предусмотрено документацией к функции sysctl, но справочное руководство по этому поводу умалчивает. Однако, автор считает, что в этом случае функция do_sysctl_strategy должна возвращать ошибку EPERM.


    Содержание раздела