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

Sysctl_string


sysctl_string— это одна из strategy-процедур объекта ctl_table. Напомним, что strategy-процедуры при желании могут быть вызваны из строки (в функции do_sysctl_strategy) для замещения применяемого по умолчанию кода чтения/записи входа таблицы. (strategy-процедуры могут быть также вызваны из строки , но данная процедура к ним не относится.)

Если таблица не имеет связанных с ней данных или если длина доступной части равна 0, возвращается ошибка ENOTDIR. Это не совместимо с правилами поведения функции do_sysctl_strategy, которая в аналогичном случае возвращает успешный результат.

Текущее значение строки копируется в пространство пользователя и результат оканчивается символом NUL (это значит, что может быть выведено число байтов, которое на единицу больше указанного параметром lenp; возможно, это — ошибка, в зависимости от того, что указано в документации). Поскольку текущее значение уже оканчивается символом NUL, эти четыре строки кода можно легко свести к двум:

if (copy_to_user(oldval, table->data, len + 1)) return -EFAULT;

Допустимость этого изменения частично зависит от трех свойств, которые учитываются в остальной части кода при записи в член table->data:

  • В остальной части кода не происходит копирование в table->data больше символов, чем указано в table->maxlen. (При этом, также становится не нужной проверка в строке . Даже если бы эта проверка была необходима, в ней нужно было проверять только соответствие оператору сравнения >, в не >=).
  • Затем в конце table->data записывается символ NUL с перекрытием в случае необходимости последнего скопированного байта с тем, чтобы общая длина, включая символ NUL, не превышала величины table->maxlen.
  • Величина table->maxlen никогда не изменяется.
  • Поскольку все эти три свойства соблюдаются, значение len всегда будет строго меньше значения table->maxlen в строке , и завершающий символ NUL должен появляться в позиции или перед позицией table->data[len + 1].

    По аналогии с предыдущим случаем, новое значение копируется из пространства пользователя и результат оканчивается символом NUL. Однако в этом случае не стоит копировать байт NUL из пространства пользователя, поскольку будет менее эффективным копировать его из пространства пользователя, чем просто присвоить значение NUL соответствующему байту объекта . К тому же, это позволяет записывать символ NUL в конце table->data, даже если его не было на входе. Безусловно, строка, считанная из newval, уже могла оканчиваться символом NUL, и в этом случае присваивание в строке будет излишним. Это еще один пример того, что иногда быстрее просто выполнить работу, чем проверять, нужно ли ее выполнять.

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



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