Cайт веб-разработчика, программиста Ruby on Rails ESV Corp. Екатеринбург, Москва, Санкт-Петербург, Новосибирск, Первоуральск

Из ядра Linux 7.2 окончательно убрали strncpy спустя 6 лет чистки

В ядре Linux наконец закрыли старый долг, который тянулся годами: из ветки 7.2 полностью убрали API strncpy. Функция десятилетиями выглядела как обычный способ безопасно скопировать строку заданной длины, но на практике регулярно подсовывала разработчикам ошибки, лишнюю работу процессору и неприятные сюрпризы с завершением строк.

strncpy() копирует до заданного числа байтов, но ведёт себя не так, как многие ожидают от строковой функции. Главная проблема связана с нулевым символом в конце строки. В одних случаях функция не добавляет завершающий NUL, в других добивает оставшуюся часть буфера нулями. Для кода ядра такое поведение оказалось слишком удобной ловушкой: разработчик мог считать строку корректно завершённой, а на деле получать поле без финального нулевого байта. Параллельно ядро тратило время на лишнее заполнение памяти, даже когда код не нуждался в такой операции.

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

Финальный патч вошёл в ядро в пятницу. Вместе с самим API из дерева исходников убрали последние реализации strncpy для отдельных процессорных архитектур. После слияния патча ядро Linux 7.2 больше не предоставляет разработчикам внутренний интерфейс strncpy.

Вместо strncpy разработчикам ядра теперь предлагают выбирать функцию под конкретный сценарий. Для обычных строк с завершающим нулевым байтом подходит strscpy(), для строк с нулевым завершением и заполнением остатка буфера нулями используется strscpy_pad(). Для фиксированных полей без строкового NUL предназначена strtomem_pad(), для ограниченного копирования с явным заполнением есть memcpy_and_pad(), а для копирования памяти известной длины остаётся обычная memcpy().

Удаление strncpy не выглядит громкой пользовательской функцией Linux 7.2, но для ядра такой шаг важен. Разработчики убрали из кодовой базы старый API с неоднозначным поведением и заменили его набором функций, где назначение видно по названию. В результате код становится проще проверять, а целый класс ошибок с обрезанными строками и неверным завершением постепенно уходит из ядра.

SecurityLab