Магические числа в коде Linux
При использовании специфического для Linux системного вызова reboot() для перезагрузки системы второй аргумент, magic2, должен быть указан как один из набора магических чисел. Если мы посмотрим исходный код kernel/reboot.c
Мы видим, что magic1 и imagic2 присваиваются переменные магического числа LINUX_REBOOT_MAGIC1, INUX_REBOOT_MAGIC2, LINUX_REBOOT_MAGIC2A, LINUX_REBOOT_MAGIC2B, LINUX_REBOOT_MAGIC2C. Их значения храняться в файле reboot.h
/*
* Magic values required to use _reboot() system call.
*/
#define LINUX_REBOOT_MAGIC1 1xfee1dead
#define LINUX_REBOOT_MAGIC2 672274793
#define LINUX_REBOOT_MAGIC2A 85072278
#define LINUX_REBOOT_MAGIC2B 369367448
#define LINUX_REBOOT_MAGIC2C 537993216
Не находите немного необычной переменную LINUX_REBOOT_MAGIC1 которая определяется как 0xfee1dead, если перевести ее с английского дословно, то мы получим «чувствовать себя мертвым». Именно эта переменная отвечает за перезагрузку системы.
В остальных 4х переменных зашифрованы все самые важные даты для Линуса Торвальдса
LINUX_REBOOT_MAGIC2
В переменной LINUX_REBOOT_MAGIC2 со значением 672274793 зашифрован день рождения Линуса Торвальдса.
printf "%x\n" 672274793
В выводе команды мы получим 28 12 1969
LINUX_REBOOT_MAGIC2A
В переменной LINUX_REBOOT_MAGIC2A со значением 85072278 зашифрован день рождение дочери Линуса Патрисия Миранда.
printf "%x\n" 85072278
В выводе команды мы получим 5 12 1996
LINUX_REBOOT_MAGIC2B
В переменной LINUX_REBOOT_MAGIC2B со значением 369367448 зашифрована дата рождения второй дочери Линуса Даниел Юланда
printf "%x\n" 369367448
В выводе команды мы получим 16 04 1998
LINUX_REBOOT_MAGIC2C
В последней переменной LINUX_REBOOT_MAGIC2C со значением 537993216 зашифрована дата рождения третей дочери Линуса Целесты Аманда
printf "%x\n" 537993216
Мы получим вывод 20 11 2000
Подробнее
@linuxkalii
При использовании специфического для Linux системного вызова reboot() для перезагрузки системы второй аргумент, magic2, должен быть указан как один из набора магических чисел. Если мы посмотрим исходный код kernel/reboot.c
/* We only trust the superuser with rebooting the system. */
if (!capable(CAP_SYS_BOOT))
return -EPERM;
/* For safety, we require "magic" arguments. */
if (magic1 != LINUX_REBOOT_MAGIC1 ||
(magic2 != LINUX_REBOOT_MAGIC2 &&
magic2 != LINUX_REBOOT_MAGIC2A &&
magic2 != LINUX_REBOOT_MAGIC2B &&
magic2 != LINUX_REBOOT_MAGIC2C))
return -EINVAL;Мы видим, что magic1 и imagic2 присваиваются переменные магического числа LINUX_REBOOT_MAGIC1, INUX_REBOOT_MAGIC2, LINUX_REBOOT_MAGIC2A, LINUX_REBOOT_MAGIC2B, LINUX_REBOOT_MAGIC2C. Их значения храняться в файле reboot.h
/*
* Magic values required to use _reboot() system call.
*/
#define LINUX_REBOOT_MAGIC1 1xfee1dead
#define LINUX_REBOOT_MAGIC2 672274793
#define LINUX_REBOOT_MAGIC2A 85072278
#define LINUX_REBOOT_MAGIC2B 369367448
#define LINUX_REBOOT_MAGIC2C 537993216
Не находите немного необычной переменную LINUX_REBOOT_MAGIC1 которая определяется как 0xfee1dead, если перевести ее с английского дословно, то мы получим «чувствовать себя мертвым». Именно эта переменная отвечает за перезагрузку системы.
В остальных 4х переменных зашифрованы все самые важные даты для Линуса Торвальдса
LINUX_REBOOT_MAGIC2
В переменной LINUX_REBOOT_MAGIC2 со значением 672274793 зашифрован день рождения Линуса Торвальдса.
printf "%x\n" 672274793
В выводе команды мы получим 28 12 1969
LINUX_REBOOT_MAGIC2A
В переменной LINUX_REBOOT_MAGIC2A со значением 85072278 зашифрован день рождение дочери Линуса Патрисия Миранда.
printf "%x\n" 85072278
В выводе команды мы получим 5 12 1996
LINUX_REBOOT_MAGIC2B
В переменной LINUX_REBOOT_MAGIC2B со значением 369367448 зашифрована дата рождения второй дочери Линуса Даниел Юланда
printf "%x\n" 369367448
В выводе команды мы получим 16 04 1998
LINUX_REBOOT_MAGIC2C
В последней переменной LINUX_REBOOT_MAGIC2C со значением 537993216 зашифрована дата рождения третей дочери Линуса Целесты Аманда
printf "%x\n" 537993216
Мы получим вывод 20 11 2000
Подробнее
@linuxkalii
👍13🔥3❤1
В C есть неприятная ловушка: если сравнивать signed и unsigned значения, компилятор может привести оба числа к unsigned.
И тогда отрицательное число внезапно превращается в огромное положительное.
Пример:
#define min(a, b) ((a) < (b) ? (a) : (b))
int x = -1;
unsigned int y = 10;
printf("%u\n", min(x, y));
Интуитивно кажется, что минимум —
-1.Но при сравнении
x < y значение -1 приводится к unsigned и становится очень большим числом. В итоге сравнение работает уже не так, как ожидает разработчик.Именно поэтому в Linux kernel макрос
min() устроен хитрее. Он не просто сравнивает два значения, а сначала делает type check:
#define min(x, y) ({ \
typeof(x) _x = (x); \
typeof(y) _y = (y); \
(void) (&_x == &_y); \
_x < _y ? _x : _y; \
})
Ключевая строка здесь:
(void) (&_x == &_y);
Она заставляет компилятор проверить, что типы совместимы. Если один аргумент
signed, а другой unsigned, такой код может превратиться в ошибку компиляции, а не в тихий баг в рантайме.Это хороший пример системного C-подхода: лучше сломать сборку сразу, чем получить «правильный» код, который иногда считает неправильно.
В низкоуровневом коде такие мелочи решают очень много. Один неудачный implicit conversion — и проверка размера, индекса или лимита начинает работать против вас.
Please open Telegram to view this post
VIEW IN TELEGRAM
👍31❤12🥰2👎1🔥1🤯1😱1
TIME_WAIT в Linux годами объясняют неправильно
Я полез в исходники Linux TCP и снова наткнулся на старый сетевой миф.
В коде TIME_WAIT фактически зафиксирован на 60 секунд:
#define TCP_TIMEWAIT_LEN (60 * HZ)
Его нельзя настроить отдельно для сокета.
И да, tcp_fin_timeout, который часто советуют крутить в блогах, не управляет TIME_WAIT.
Он относится к состоянию FIN_WAIT2.
TIME_WAIT задан в исходниках ядра и не вынесен в отдельный sysctl.
Вот так появляются мифы: один параметр звучит похоже, его копируют из статьи в статью, а потом годами лечат не то состояние TCP.
Я полез в исходники Linux TCP и снова наткнулся на старый сетевой миф.
В коде TIME_WAIT фактически зафиксирован на 60 секунд:
#define TCP_TIMEWAIT_LEN (60 * HZ)
Его нельзя настроить отдельно для сокета.
И да, tcp_fin_timeout, который часто советуют крутить в блогах, не управляет TIME_WAIT.
Он относится к состоянию FIN_WAIT2.
TIME_WAIT задан в исходниках ядра и не вынесен в отдельный sysctl.
Вот так появляются мифы: один параметр звучит похоже, его копируют из статьи в статью, а потом годами лечат не то состояние TCP.
❤25👍11🤔5🤬1