# Time Namespace
{{#include ../../../../banners/hacktricks-training.md}}
## Basic Information
Часовий простір у Linux дозволяє використовувати зсуви для системних монотонних і завантажувальних годинників для кожного простору. Він зазвичай використовується в контейнерах Linux для зміни дати/часу всередині контейнера та коригування годинників після відновлення з контрольної точки або знімка.
## Lab:
### Create different Namespaces
#### CLI
```bash
sudo unshare -T [--mount-proc] /bin/bash
```
Монтування нової інстанції файлової системи `/proc`, якщо ви використовуєте параметр `--mount-proc`, забезпечує, що новий простір монтування має **точний та ізольований вигляд інформації про процеси, специфічної для цього простору**.
Помилка: bash: fork: Не вдалося виділити пам'ять
Коли `unshare` виконується без параметра `-f`, виникає помилка через те, як Linux обробляє нові PID (ідентифікатори процесів) простори. Основні деталі та рішення наведені нижче:
1. **Пояснення проблеми**:
- Ядро Linux дозволяє процесу створювати нові простори за допомогою системного виклику `unshare`. Однак процес, який ініціює створення нового PID простору (який називається "процесом unshare"), не входить до нового простору; лише його дочірні процеси входять.
- Виконання `%unshare -p /bin/bash%` запускає `/bin/bash` в тому ж процесі, що й `unshare`. Відповідно, `/bin/bash` та його дочірні процеси знаходяться в оригінальному PID просторі.
- Перший дочірній процес `/bin/bash` у новому просторі стає PID 1. Коли цей процес завершується, це викликає очищення простору, якщо немає інших процесів, оскільки PID 1 має особливу роль усиновлення сирітських процесів. Ядро Linux тоді вимкне виділення PID у цьому просторі.
2. **Наслідок**:
- Вихід PID 1 у новому просторі призводить до очищення прапора `PIDNS_HASH_ADDING`. Це призводить до того, що функція `alloc_pid` не може виділити новий PID при створенні нового процесу, що викликає помилку "Не вдалося виділити пам'ять".
3. **Рішення**:
- Проблему можна вирішити, використовуючи параметр `-f` з `unshare`. Цей параметр змушує `unshare` створити новий процес після створення нового PID простору.
- Виконання `%unshare -fp /bin/bash%` забезпечує, що команда `unshare` сама стає PID 1 у новому просторі. `/bin/bash` та його дочірні процеси тоді безпечно містяться в цьому новому просторі, запобігаючи передчасному виходу PID 1 та дозволяючи нормальне виділення PID.
Забезпечивши, що `unshare` виконується з прапором `-f`, новий PID простір правильно підтримується, що дозволяє `/bin/bash` та його підпроцесам працювати без виникнення помилки виділення пам'яті.
#### Docker
```bash
docker run -ti --name ubuntu1 -v /usr:/ubuntu1 ubuntu bash
```
### Перевірте, в якому просторі імен знаходиться ваш процес
```bash
ls -l /proc/self/ns/time
lrwxrwxrwx 1 root root 0 Apr 4 21:16 /proc/self/ns/time -> 'time:[4026531834]'
```
### Знайти всі простори часу
```bash
sudo find /proc -maxdepth 3 -type l -name time -exec readlink {} \; 2>/dev/null | sort -u
# Find the processes with an specific namespace
sudo find /proc -maxdepth 3 -type l -name time -exec ls -l {} \; 2>/dev/null | grep
```
### Увійти в простір часу
```bash
nsenter -T TARGET_PID --pid /bin/bash
```
## Маніпулювання часовими зсувами
Починаючи з Linux 5.6, два годинники можуть бути віртуалізовані для кожного простору часу:
* `CLOCK_MONOTONIC`
* `CLOCK_BOOTTIME`
Їхні делти на кожен простір часу відкриті (і можуть бути змінені) через файл `/proc//timens_offsets`:
```
$ sudo unshare -Tr --mount-proc bash # -T creates a new timens, -r drops capabilities
$ cat /proc/$$/timens_offsets
monotonic 0
boottime 0
```
Файл містить два рядки – по одному для кожного годинника – з зсувом у **наносекундах**. Процеси, які мають **CAP_SYS_TIME** _в часовому просторі_, можуть змінювати значення:
```
# advance CLOCK_MONOTONIC by two days (172 800 s)
echo "monotonic 172800000000000" > /proc/$$/timens_offsets
# verify
$ cat /proc/$$/uptime # first column uses CLOCK_MONOTONIC
172801.37 13.57
```
Якщо вам потрібно, щоб настінний годинник (`CLOCK_REALTIME`) також змінювався, вам все ще потрібно покладатися на класичні механізми (`date`, `hwclock`, `chronyd`, …); він **не** є просторовим.
### `unshare(1)` допоміжні прапори (util-linux ≥ 2.38)
```
sudo unshare -T \
--monotonic="+24h" \
--boottime="+7d" \
--mount-proc \
bash
```
Довгі параметри автоматично записують обрані дельти в `timens_offsets` одразу після створення простору імен, що заощаджує ручне `echo`.
---
## Підтримка OCI та Runtime
* **OCI Runtime Specification v1.1** (листопад 2023) додала спеціальний тип простору імен `time` та поле `linux.timeOffsets`, щоб контейнерні движки могли запитувати віртуалізацію часу у переносимий спосіб.
* **runc >= 1.2.0** реалізує цю частину специфікації. Мінімальний фрагмент `config.json` виглядає так:
```json
{
"linux": {
"namespaces": [
{"type": "time"}
],
"timeOffsets": {
"monotonic": 86400,
"boottime": 600
}
}
}
```
Потім запустіть контейнер за допомогою `runc run `.
> ЗАУВАЖТЕ: runc **1.2.6** (лютий 2025) виправив помилку "exec into container with private timens", яка могла призвести до зависання та потенційного DoS. Переконайтеся, що ви використовуєте версію ≥ 1.2.6 у виробництві.
---
## Розгляди безпеки
1. **Необхідна можливість** – Процес потребує **CAP_SYS_TIME** всередині свого простору імен користувача/часу, щоб змінити зсуви. Відмова від цієї можливості в контейнері (за замовчуванням у Docker та Kubernetes) запобігає маніпуляціям.
2. **Без змін годинника** – Оскільки `CLOCK_REALTIME` спільний з хостом, зловмисники не можуть підробити терміни дії сертифікатів, терміни дії JWT тощо лише за допомогою timens.
3. **Уникнення журналювання/виявлення** – Програмне забезпечення, яке покладається на `CLOCK_MONOTONIC` (наприклад, обмежувачі швидкості на основі часу безперервної роботи), може бути заплутаним, якщо користувач простору імен регулює зсув. Віддавайте перевагу `CLOCK_REALTIME` для часових міток, що мають значення для безпеки.
4. **Поверхня атаки ядра** – Навіть якщо `CAP_SYS_TIME` видалено, код ядра залишається доступним; підтримуйте хост в актуальному стані. Linux 5.6 → 5.12 отримав кілька виправлень помилок timens (NULL-deref, проблеми з підписом).
### Контрольний список посилення безпеки
* Відмовтеся від `CAP_SYS_TIME` у вашому профілі за замовчуванням контейнерного виконання.
* Підтримуйте виконання в актуальному стані (runc ≥ 1.2.6, crun ≥ 1.12).
* Закріпіть util-linux ≥ 2.38, якщо ви покладаєтеся на допоміжні програми `--monotonic/--boottime`.
* Аудит програмного забезпечення в контейнері, яке читає **uptime** або **CLOCK_MONOTONIC** для логіки, критично важливої для безпеки.
## Посилання
* man7.org – Сторінка посібника по просторах імен часу:
* Блог OCI – "OCI v1.1: нові простори імен часу та RDT" (15 листопада 2023):
{{#include ../../../../banners/hacktricks-training.md}}