Переполнение переменной jiffies
Переполнение переменной jiffies
Переменная jiffies, так же как и любое целое число языка программирования С, после достижения максимально возможного значения переполняется. Для 32-разрядного беззнакового целого числа максимальное значение равно 2??- 1. Поэтому перед тем как счетчик импульсов системного таймера переполнится, должно прийти 4294967295 импульсов таймера. Если значение счетчика равно этому значению и счетчик увеличивается на 1, то значение счетчика становится равным нулю.
Рассмотрим пример переполнения.
unsigned long timeout = jiffies + HZ/2; /* значение лимита времени
равно 0.5 с */
/* выполним некоторые действия и проверим, не слишком ли это много
заняло времени ... */
if (timeout < jiffies) {
/* мы превысили лимит времени — это ошибка ... */
} else {
/* мы не превысили лимит времени — это хорошо ... */
}
Назначение этого участка кода — установить лимит времени до наступления некоторого события в будущем, а точнее полсекунды от текущего момента. Код может продолжить выполнение некоторой работы — возможно, записать некоторые данные в аппаратное устройство и ожидать ответа. После выполнения, если весь процесс превысил лимит установленного времени, код соответственным образом обрабатывает ошибку.
В данном примере может возникнуть несколько потенциальных проблем, связанных с переполнением. Рассмотрим одну из них. Что произойдет, если переменная jiffies переполнится и снова начнет увеличиваться с нуля после того, как ей было присвоено значение переменной timeout? При этом условие гарантированно не выполнится, так как значение переменной jiffies будет меньше, чем значение переменной timeout, хотя логически оно должно быть больше. По идее значение переменной jiffies должно быть огромным числом, всегда большим значения переменной timeout. Так как эта переменная переполнилась, то теперь ее значение стало очень маленьким числом, которое, возможно, отличается от нуля на несколько импульсов таймера. Из-за переполнения результат выполнения оператора if меняется на противоположный!
К счастью, ядро предоставляет четыре макроса для сравнения двух значений счетчика импульсов таймера, которые корректно обрабатывают переполнение счетчиков. Они определены в файле <linux/jiffies.h> следующим образом.
#define time_after(unknown, known) ((long)(known) - (long)(unknown) < 0)
#define time_before(unknown, known)
((long) (unknown) - (long) (known) < 0)
#define time_after_eq(unknown, known)
((long)(unknown) - (long) (known) >= 0)
#define
time_before_eq(unknown, known) ((long)(known) - (long) (unknown) >= 0)
Параметр unknown — это обычно значение переменной jiffies, а параметр known — значение, с которым его необходимо сравнить.
Макрос time_after(unknown, known) возвращает значение true, если момент времени unknown происходит после момента времени known, в противном случае возвращается значение false. Макрос time_before(unknown, known) возвращает значение true, если момент времени unknown происходит раньше, чем момент времени known, в противном случае возвращается значение false. Последние два макроса работают аналогично первым двум, за исключением того, что возвращается значение "истинно", если оба параметра равны друг другу.
Версия кода из предыдущего примера, которая предотвращает ошибки, связанные с переполнением, будет выглядеть следующим образом.
unsigned long timeout = jiffies + HZ/2; /* значение лимита времени
равно 0.5 с */
/* выполним некоторые действия и проверим, не слишком ли это много
заняло времени ... */
if (time_after(jiffies, timeout}) {
/* мы превысили лимит времени — это ошибка ... */
} else {
/* мы не превысили лимит времени — это хорошо ... */
}
Если любопытно, каким образом эти макросы предотвращают ошибки, связанные с переполнением, то попробуйте подставить различные значения параметров. А затем представьте, что один из параметров переполнился, и посмотрите, что при этом произойдет.
Более 800 000 книг и аудиокниг! 📚
Получи 2 месяца Литрес Подписки в подарок и наслаждайся неограниченным чтением
ПОЛУЧИТЬ ПОДАРОКЧитайте также
Переменная jiffies
Переменная jiffies Глобальная переменная jiffies содержит количество импульсов системного таймера, которые были получены со времени загрузки системы. При загрузке ядро устанавливает значение этого параметра в нуль и он увеличивается на единицу при каждом прерывании
Внутреннее представление переменной jiffies
Внутреннее представление переменной jiffies Переменная jiffies исторически всегда представлялась с помощью типа unsigned long и, следовательно, имеет длину 32 бит для 32-разрядных аппаратных платформ и 64 бит для 64-разрядных. В случае 32-разрядного значения переменной jiffies и частоты
Переполнение адреса
Переполнение адреса Так как мы решили не использовать на System/38 48-разрядный адрес повторно до следующей перезагрузки, встал вопрос о том, что однажды все доступные адреса могут быть исчерпаны. В поисках ответа на него, мы провели некоторые интересные подсчеты. В
14.2. Переполнение буфера
14.2. Переполнение буфера Это одна из самых популярных и в то же время наиболее сложная в использовании уязвимость. Для начала определимся, почему программисты допускают такие ошибки, при которых возможно выполнить переполнение буфера?В таких языках, как С++, для работы с
Переполнение буфера
Переполнение буфера Некоторые вирусы и атаки достигают цели без участия пользователя. Несмотря на усилия, интенсивность удаленных атак не снижается, а отражать их становится все труднее. Как это получается? Ведь чтобы программа, пусть и зловредная, что-то сделала, она
3.1.3. Переполнение при арифметических операциях
3.1.3. Переполнение при арифметических операциях Переполнением принято называть ситуацию, когда при операциях над переменной результат выходит за пределы ее диапазона. Рассмотрим следующий пример (листинг 3.4, проект Overflow1 на компакт-диске).Листинг 3.4. Переполнение при
Переполнение и потеря значимости при обработке чисел с плавающей точкой
Переполнение и потеря значимости при обработке чисел с плавающей точкой Что произойдет, если значение переменной типа float выйдет за установленные границы? Например, предположим, что вы умножаете 10е38 на 100 (переполнение) или делите 10е - 37 на 1000 (потеря значимости).
10.6.1. Переполнение буфера
10.6.1. Переполнение буфера Почти псе основные Internet-демоны, включая демоны таких программ, как sendmail, finger, talk и др., подвержены атакам типа переполнение буфера. О них следует обязательно помнить при написании программ, которые должны выполняться с правами пользователя root, а
3.2.2. Имя переменной
3.2.2. Имя переменной Имя переменной, или идентификатор, может состоять из латинских букв, цифр и символа подчеркивания. Прописные и строчные буквы в именах различаются. Язык С++ не ограничивает длину идентификатора, однако пользоваться слишком длинными именами типа
14.2.2. Удаление значения переменной
14.2.2. Удаление значения переменной Чтобы удалить значение переменной, достаточно применить команду unset: unset имя_переменной$ PC=enterprise $ echo ${РС} enterprise $ unset PC $ echo ${PC)
17.5.1. Приращение переменной цикла
17.5.1. Приращение переменной цикла Команда expr выполняет приращение переменной цикла. Сначала переменной цикла присваивается начальное значение нуль. Затем добавляется единица. Кавычки применяются для обозначения подстановки команд. Выводимые данные, полученные с
Оператор описания переменной
Оператор описания переменной В PascalABC.NET можно описывать переменные внутри составного оператора begin-end в специальном операторе описания переменной. Такие описания называются внутриблочными.Внутриблочное описание имеет одну из форм: список имен: тип;или имя: тип :=
Глава 8 Переполнение буфера
Глава 8 Переполнение буфера В этой главе обсуждаются следующие темы: • Стек • Стековый фрейм функции • Основы переполнения буфера • Пример программы, уязвимой к переполнению буфера • Современные способы переполнения буфера • Новаторские принципы построения