LINUX.ORG.RU

Определить «реальность» времени (т.е. наличие CMOS-часов или NTP-синхронизации)

 , , ,


1

2

Предположим у нас есть некий unix-blackbox без часов реального времени (без батарейки в них) и без NTP (вообще без сети). Тогда при каждом запуске (включении и загрузки) на системных часах такого unix-box будет примерно одинаковое время (или совсем одинаковое).

Задача: Переносимым способом определять такую ситуацию (для тех кто в танке: «переносимо» == «не только на linux, а на любом POSIX/Unix»).

Дополнение в 2019-10-31 20:25 (исправляю упущение в исходной формулировке задачи): Очевидный вариант «увеличивать счетчик в файле при старте» не подходит, так как TL;DR должно работать в библиотеке без изменения её API и без вмешательства в процесс загрузки системы.

У меня есть вариант решения (назовём его «900»), но хочется услышать идеи от молодых и талантливых.

Для понимания: Всё это нужно (т.е. полная постановка задачи) для принятия решения «откатывать или нет» последние транзакции при открытии БД внутри libmdbx (встраиваемый движок БД, замена Berkeley DB), что требует переносимого аналога /proc/sys/kernel/random/boot_id, что в свою очередь требует определения boot time. И вот тут-то и нужно понять что это самое «boot time» не будет одинаковым при каждой загрузке.


Итоговый вариант решения был исходно обозначен как «900» и не изменился:

  • минимальная разница между часовыми поясами 900 секунд (15 минут);
  • Контролируем разницу между CLOCK_REALTIME и CLOCK_MONOTONIC;
  • Если она примерно кратна 900 секундам, то считаем что в системе нет CMOS-часов и/или синхронизации по NTP;

Как и почему это работает:

  • Если в системе нет cmos/NTP, то нет повода чтобы CLOCK_REALTIME и CLOCK_MONOTONIC шли в разнобой, т.е. разница будет равна некоторому часовому поясу (в том числе нулю в случае TZ=UTC).
  • Шаг «квантования» временных зон 15 минут, т.е. любая тайм-зона (в том числе еще не определенная) будет иметь смещение кратное 15 минутам.
  • Поэтому, если разность между CLOCK_REALTIME и CLOCK_MONOTONIC не кратна 15 минутам, то их разность не может быть объяснена только использованием какого-либо часового пояса. Следовательно CLOCK_REALTIME включает сдвиг для соответствия реальному времени и в системе где-то есть источник реального времени (CMOS или NTP).

Эта схема не идеальна и может давать ложно-отрицательный результат. Например, «алгоритм» посчитает что «время не настоящее»:

  • Система вправе инициализировать CLOCK_MONOTONIC от любого удобного источника, включая CMOS-часы. Тогда при наличии СMOS-часов работающих в нужной TZ получается всегда CLOCK_MONOTONIC == CLOCK_REALTIME.
  • С некоторой вероятностью разность может быть кратной 15 минутам.

Тем не менее, субъективно этот вариант лучше остальных (проверке условия «текущая время меньше даты исходников или сборки»). В контексте полной постановки задачи, важно что этот способ не даёт ложно-положительных результатов, и не имеет абсолютных точек привязки ко времени (идемпотентен по временной оси).

Исходники PoC для баловства = https://abf.io/erthink/poc4-boottime-nearly-constant


Добавлено 2019-11-01 в 12:18: В целом тредик/срач для меня полезен благодаря выводам:

  • на embedded-like платформах (как минимум на Linux) следует полагаться только на нативный bootid, ибо boottime может превращаться в тыкву распространенными рецептами в rc-скриптах.
  • генерацию bootid из boottime следует вынести в опцию, ибо нет 100% гарантии выявить все варианты предыдущего пункта.

Всем еще раз спасибо за дискус/срачик. Всё.

Deleted

Последнее исправление: Deleted (всего исправлений: 6)
Ответ на: комментарий от Deleted

В ТС добавлено описания решения, т.е. исходного варианта «900».

Заведомо неправильного решения. Ты осильп рочитать то, что я тебе рассказал, разуй глазки. И говнокод не потому, что плохо написан, а потому, что никакой ценности не имеет ввиду того, что он ничего полезного не делает.

Для тех кто в танке:

Да ты сам в танке. Осиль уже почитать стандарт POSIX.

Deleted
()
Ответ на: комментарий от anonymous

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

Карго-культ в том, что так вы делаете вид, будто работаете на системе с настоящим RTC (с батарейкой) и/или NTP, но на самом деле у вас «деревянный» RTC и нет NTP.

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

Deleted
()
Ответ на: комментарий от anonymous

вот «холодный» старт - в этом случае определяет правильно

Только в частных случаях. И кратность к 900 тут вообще не нужна. Если CLOCK_MONOTONIC совпадает с CLOCK_REALTIME - значит система недавно была перезагружена, только и всего. И это может не работать в некоторых случаях.

Deleted
()
Ответ на: комментарий от Deleted

В ТС добавлено описания решения, т.е. исходного варианта «900».

Заведомо неправильного решения. Ты осильп рочитать то, что я тебе рассказал, разуй глазки. И говнокод не потому, что плохо написан, а потому, что никакой ценности не имеет ввиду того, что он ничего полезного не делает.

Для тех кто в танке:

Да ты сам в танке. Осиль уже почитать стандарт POSIX.

Ваше ЧСВ начинает зашкаливать и скоро переполниться. Однако, без RTFM (от простого к сложному: #1, #2, #3, #4, #5) вы совсем не интересны. Поэтому дальше >/dev/null

Deleted
()
Ответ на: комментарий от Deleted

Я смотрю, что ЧСВ тут только у тебя. Ты же так и не понял, что в Linux CLOCK_MONOTONIC при отсутствии RTC при загрузке совпадает с CLOCK_REALTIME, а в той же FreeBSD CLOCK_MONOTONIC будет считаться от Epoch, а в RTC может будет произвольное время. При чем тут кратность к 900 - вообще не ясно, это совсем не нужное сравнение.

Deleted
()
Последнее исправление: Deleted (всего исправлений: 1)
Ответ на: комментарий от anonymous

точно так же как и poc - смотри мою эмуляцию утсановки фиксированного времени, твой poc точно так же обсерется и посчитает что время загрузки разное, хотя оно 100% будет одним и тем же, только с меньшей вероятностью

Еще раз, беда в том что так (в моем понимании) вы эмулируете не установку системного времени, а установку времени из RTC с батарейкой или через NTP.

Тем не менее, в целом тредик/срач для меня полезен благодаря выводам:

  • на embedded-like платформах (как минимум на Linux) следует полагаться только на нативный bootid, ибо boottime может превращаться в тыкву распространенными рецептами в rc-скриптах.
  • генерацию bootid из boottime следует вынести в опцию, ибо нет 100% гарантии выявить все варианты предыдущего пункта.

Всем еще раз спасибо за дискус/срачик.

Deleted
()
Вы не можете добавлять комментарии в эту тему. Тема перемещена в архив.