В ядре Linux устранена следующая уязвимость:
nfsd: отклонять uсекунды, выходящие за пределы диапазона, в NFSv2 SETATTR/CREATE
Декодер NFSv2 sattr преобразует проводные усекунды в наносекунды в
svcxdr_decode_sattr():
iap->ia_atime.tv_nsec = tmp2 * NSEC_PER_USEC;
tmp2 — это u32, а NSEC_PER_USEC — 1000, поэтому произведение вычисляется в
беззнаковый длинный. В ILP32 это 32 бита, а uсекунды выходят за пределы допустимого диапазона.
значение, такое как 4294968, переносится на tv_nsec == 704. Таким образом, повреждение
происходит во время декодирования, прежде чем какая-либо функция proc сможет проверить значение,
и более поздняя проверка диапазона на tv_nsec увидит результат в пределах диапазона и
примите это.
Отклонение в декодере приводит к ответу RPC GARBAGE_ARGS. NFSv2 не определяет NFSERR_INVAL, поэтому нет статуса уровня NFS для возврата.
из-за неправильного аргумента времени, и проверка не может перейти к процедуре
функционируют так же, как проверки диапазона nsec v3/v4. Сохраняйте необработанные uсекунды перед умножением и отклонением значений
больше 1000000. uсекунд == 1000000 сохраняется: это Солнце
соглашение для «установки текущего времени сервера» и встроенное в дерево Linux
Клиент NFSv2 выдает его как в поле atime, так и в поле mtime для простого
touch/utimes(file, NULL) (см. encode_sattr() и
xdr_encode_current_server_time() в fs/nfs/nfs2xdr.c).
Отклонение 1000000
превратит эту общую операцию в сбой жесткого декодирования для обоих
SETATTR и CREATE. 1000000 * NSEC_PER_USEC равно 10^9, что не переносит
на ILP32, поэтому значение соглашения Sun проходит безопасно. Только
Значения, действительно выходящие за пределы диапазона (> 1000000), отклоняются. Время и
Таким образом, охранники mtime симметричны.
Декодер применил соглашение Sun только в блоке mtime, что
очищает ATTR_ATIME_SET|ATTR_MTIME_SET, когда mtime uсекунд == 1000000. Если
клиент помещает 1000000 в поле atime, но не в поле mtime,
Блок atime сохранил значение tv_nsec, выходящее за пределы диапазона (10^9), и оставил ATTR_ATIME_SET
установлено, поэтому фиктивное значение достигло файловой системы. Примените соглашение в
блок atime, очищая ATTR_ATIME_SET, чтобы сервер использовал его
текущее время и игнорирует значение.
Там очищается только ATTR_ATIME_SET. Блок mtime сохраняет свое существующее поведение, где 1000000 означает «установить
как atime, так и mtime to now".
[ cel: различные настройки, дополнения и очистки ]
Показать оригинальное описание (EN)
In the Linux kernel, the following vulnerability has been resolved: nfsd: reject out-of-range useconds in NFSv2 SETATTR/CREATE The NFSv2 sattr decoder converts the wire useconds to nanoseconds in svcxdr_decode_sattr(): iap->ia_atime.tv_nsec = tmp2 * NSEC_PER_USEC; tmp2 is a u32 and NSEC_PER_USEC is 1000, so the product is computed in unsigned long. On ILP32 that is 32 bits, and an out-of-range useconds value such as 4294968 wraps to tv_nsec == 704. The corruption therefore happens during decode, before any proc function can inspect the value, and a later range check on tv_nsec would see an in-range result and accept it. Rejecting in the decoder yields an RPC GARBAGE_ARGS reply. NFSv2 defines no NFSERR_INVAL, so there is no NFS-level status to return for a malformed time argument, and the check cannot move to the proc function the way the v3/v4 nsec range checks do. Guard the raw useconds before the multiplication and reject values greater than 1000000. useconds == 1000000 is kept: it is the Sun convention for "set to the current server time", and the in-tree Linux NFSv2 client emits it in both the atime and the mtime field for a plain touch / utimes(file, NULL) (see encode_sattr() and xdr_encode_current_server_time() in fs/nfs/nfs2xdr.c). Rejecting 1000000 would turn that common operation into a hard decode failure for both SETATTR and CREATE. 1000000 * NSEC_PER_USEC is 10^9, which does not wrap on ILP32, so the Sun convention value passes through safely. Only genuinely out-of-range values (> 1000000) are rejected. The atime and mtime guards are therefore symmetric. The decoder only applied the Sun convention in the mtime block, which clears ATTR_ATIME_SET|ATTR_MTIME_SET when mtime useconds == 1000000. If a client puts 1000000 in the atime field but not in the mtime field, the atime block stored an out-of-range tv_nsec (10^9) and left ATTR_ATIME_SET set, so the bogus value reached the filesystem. Apply the convention in the atime block as well, clearing ATTR_ATIME_SET so the server uses its current time and ignores the value. Only ATTR_ATIME_SET is cleared there. The mtime block keeps its existing behavior, where 1000000 means "set both atime and mtime to now". [ cel: various tweaks, addenda, and clean-ups ]
Характеристики атаки
Последствия
Строка CVSS v3.1