You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Copy file name to clipboardExpand all lines: src/linux-hardening/privilege-escalation/docker-security/namespaces/time-namespace.md
+86Lines changed: 86 additions & 0 deletions
Display the source diff
Display the rich diff
Original file line number
Diff line number
Diff line change
@@ -69,6 +69,92 @@ sudo find /proc -maxdepth 3 -type l -name time -exec ls -l {} \; 2>/dev/null |
69
69
nsenter -T TARGET_PID --pid /bin/bash
70
70
```
71
71
72
+
73
+
## Manipulating Time Offsets
74
+
75
+
Starting with Linux 5.6, two clocks can be virtualised per time namespace:
76
+
77
+
*`CLOCK_MONOTONIC`
78
+
*`CLOCK_BOOTTIME`
79
+
80
+
Their per-namespace deltas are exposed (and can be modified) through the file `/proc/<PID>/timens_offsets`:
81
+
82
+
```
83
+
$ sudo unshare -Tr --mount-proc bash # -T creates a new timens, -r drops capabilities
84
+
$ cat /proc/$$/timens_offsets
85
+
monotonic 0
86
+
boottime 0
87
+
```
88
+
89
+
The file contains two lines – one per clock – with the offset in **nanoseconds**. Processes that hold **CAP_SYS_TIME**_in the time namespace_ can change the value:
$ cat /proc/$$/uptime # first column uses CLOCK_MONOTONIC
96
+
172801.37 13.57
97
+
```
98
+
99
+
If you need the wall clock (`CLOCK_REALTIME`) to change as well you still have to rely on classic mechanisms (`date`, `hwclock`, `chronyd`, …); it is **not** namespaced.
100
+
101
+
102
+
### `unshare(1)` helper flags (util-linux ≥ 2.38)
103
+
104
+
```
105
+
sudo unshare -T \
106
+
--monotonic="+24h" \
107
+
--boottime="+7d" \
108
+
--mount-proc \
109
+
bash
110
+
```
111
+
112
+
The long options automatically write the chosen deltas to `timens_offsets` right after the namespace is created, saving a manual `echo`.
113
+
114
+
---
115
+
116
+
## OCI & Runtime support
117
+
118
+
* The **OCI Runtime Specification v1.1** (Nov 2023) added a dedicated `time` namespace type and the `linux.timeOffsets` field so that container engines can request time virtualisation in a portable way.
119
+
***runc >= 1.2.0** implements that part of the spec. A minimal `config.json` fragment looks like:
120
+
```json
121
+
{
122
+
"linux": {
123
+
"namespaces": [
124
+
{"type": "time"}
125
+
],
126
+
"timeOffsets": {
127
+
"monotonic": 86400,
128
+
"boottime": 600
129
+
}
130
+
}
131
+
}
132
+
```
133
+
Then run the container with `runc run <id>`.
134
+
135
+
> NOTE: runc **1.2.6** (Feb 2025) fixed an "exec into container with private timens" bug that could lead to a hang and potential DoS. Make sure you are on ≥ 1.2.6 in production.
136
+
137
+
---
138
+
139
+
## Security considerations
140
+
141
+
1.**Required capability** – A process needs **CAP_SYS_TIME** inside its user/time namespace to change the offsets. Dropping that capability in the container (default in Docker & Kubernetes) prevents tampering.
142
+
2.**No wall-clock changes** – Because `CLOCK_REALTIME` is shared with the host, attackers cannot spoof certificate lifetimes, JWT expiry, etc. via timens alone.
143
+
3.**Log / detection evasion** – Software that relies on `CLOCK_MONOTONIC` (e.g. rate-limiters based on uptime) can be confused if the namespace user adjusts the offset. Prefer `CLOCK_REALTIME` for security-relevant timestamps.
144
+
4.**Kernel attack surface** – Even with `CAP_SYS_TIME` removed, the kernel code remains accessible; keep the host patched. Linux 5.6 → 5.12 received multiple timens bug-fixes (NULL-deref, signedness issues).
145
+
146
+
### Hardening checklist
147
+
148
+
* Drop `CAP_SYS_TIME` in your container runtime default profile.
0 commit comments