1*4882a593Smuzhiyun // SPDX-License-Identifier: GPL-2.0
2*4882a593Smuzhiyun /*
3*4882a593Smuzhiyun * Author: Andrei Vagin <avagin@openvz.org>
4*4882a593Smuzhiyun * Author: Dmitry Safonov <dima@arista.com>
5*4882a593Smuzhiyun */
6*4882a593Smuzhiyun
7*4882a593Smuzhiyun #include <linux/time_namespace.h>
8*4882a593Smuzhiyun #include <linux/user_namespace.h>
9*4882a593Smuzhiyun #include <linux/sched/signal.h>
10*4882a593Smuzhiyun #include <linux/sched/task.h>
11*4882a593Smuzhiyun #include <linux/clocksource.h>
12*4882a593Smuzhiyun #include <linux/seq_file.h>
13*4882a593Smuzhiyun #include <linux/proc_ns.h>
14*4882a593Smuzhiyun #include <linux/export.h>
15*4882a593Smuzhiyun #include <linux/time.h>
16*4882a593Smuzhiyun #include <linux/slab.h>
17*4882a593Smuzhiyun #include <linux/cred.h>
18*4882a593Smuzhiyun #include <linux/err.h>
19*4882a593Smuzhiyun #include <linux/mm.h>
20*4882a593Smuzhiyun
21*4882a593Smuzhiyun #include <vdso/datapage.h>
22*4882a593Smuzhiyun
do_timens_ktime_to_host(clockid_t clockid,ktime_t tim,struct timens_offsets * ns_offsets)23*4882a593Smuzhiyun ktime_t do_timens_ktime_to_host(clockid_t clockid, ktime_t tim,
24*4882a593Smuzhiyun struct timens_offsets *ns_offsets)
25*4882a593Smuzhiyun {
26*4882a593Smuzhiyun ktime_t offset;
27*4882a593Smuzhiyun
28*4882a593Smuzhiyun switch (clockid) {
29*4882a593Smuzhiyun case CLOCK_MONOTONIC:
30*4882a593Smuzhiyun offset = timespec64_to_ktime(ns_offsets->monotonic);
31*4882a593Smuzhiyun break;
32*4882a593Smuzhiyun case CLOCK_BOOTTIME:
33*4882a593Smuzhiyun case CLOCK_BOOTTIME_ALARM:
34*4882a593Smuzhiyun offset = timespec64_to_ktime(ns_offsets->boottime);
35*4882a593Smuzhiyun break;
36*4882a593Smuzhiyun default:
37*4882a593Smuzhiyun return tim;
38*4882a593Smuzhiyun }
39*4882a593Smuzhiyun
40*4882a593Smuzhiyun /*
41*4882a593Smuzhiyun * Check that @tim value is in [offset, KTIME_MAX + offset]
42*4882a593Smuzhiyun * and subtract offset.
43*4882a593Smuzhiyun */
44*4882a593Smuzhiyun if (tim < offset) {
45*4882a593Smuzhiyun /*
46*4882a593Smuzhiyun * User can specify @tim *absolute* value - if it's lesser than
47*4882a593Smuzhiyun * the time namespace's offset - it's already expired.
48*4882a593Smuzhiyun */
49*4882a593Smuzhiyun tim = 0;
50*4882a593Smuzhiyun } else {
51*4882a593Smuzhiyun tim = ktime_sub(tim, offset);
52*4882a593Smuzhiyun if (unlikely(tim > KTIME_MAX))
53*4882a593Smuzhiyun tim = KTIME_MAX;
54*4882a593Smuzhiyun }
55*4882a593Smuzhiyun
56*4882a593Smuzhiyun return tim;
57*4882a593Smuzhiyun }
58*4882a593Smuzhiyun
inc_time_namespaces(struct user_namespace * ns)59*4882a593Smuzhiyun static struct ucounts *inc_time_namespaces(struct user_namespace *ns)
60*4882a593Smuzhiyun {
61*4882a593Smuzhiyun return inc_ucount(ns, current_euid(), UCOUNT_TIME_NAMESPACES);
62*4882a593Smuzhiyun }
63*4882a593Smuzhiyun
dec_time_namespaces(struct ucounts * ucounts)64*4882a593Smuzhiyun static void dec_time_namespaces(struct ucounts *ucounts)
65*4882a593Smuzhiyun {
66*4882a593Smuzhiyun dec_ucount(ucounts, UCOUNT_TIME_NAMESPACES);
67*4882a593Smuzhiyun }
68*4882a593Smuzhiyun
69*4882a593Smuzhiyun /**
70*4882a593Smuzhiyun * clone_time_ns - Clone a time namespace
71*4882a593Smuzhiyun * @user_ns: User namespace which owns a new namespace.
72*4882a593Smuzhiyun * @old_ns: Namespace to clone
73*4882a593Smuzhiyun *
74*4882a593Smuzhiyun * Clone @old_ns and set the clone refcount to 1
75*4882a593Smuzhiyun *
76*4882a593Smuzhiyun * Return: The new namespace or ERR_PTR.
77*4882a593Smuzhiyun */
clone_time_ns(struct user_namespace * user_ns,struct time_namespace * old_ns)78*4882a593Smuzhiyun static struct time_namespace *clone_time_ns(struct user_namespace *user_ns,
79*4882a593Smuzhiyun struct time_namespace *old_ns)
80*4882a593Smuzhiyun {
81*4882a593Smuzhiyun struct time_namespace *ns;
82*4882a593Smuzhiyun struct ucounts *ucounts;
83*4882a593Smuzhiyun int err;
84*4882a593Smuzhiyun
85*4882a593Smuzhiyun err = -ENOSPC;
86*4882a593Smuzhiyun ucounts = inc_time_namespaces(user_ns);
87*4882a593Smuzhiyun if (!ucounts)
88*4882a593Smuzhiyun goto fail;
89*4882a593Smuzhiyun
90*4882a593Smuzhiyun err = -ENOMEM;
91*4882a593Smuzhiyun ns = kmalloc(sizeof(*ns), GFP_KERNEL);
92*4882a593Smuzhiyun if (!ns)
93*4882a593Smuzhiyun goto fail_dec;
94*4882a593Smuzhiyun
95*4882a593Smuzhiyun kref_init(&ns->kref);
96*4882a593Smuzhiyun
97*4882a593Smuzhiyun ns->vvar_page = alloc_page(GFP_KERNEL | __GFP_ZERO);
98*4882a593Smuzhiyun if (!ns->vvar_page)
99*4882a593Smuzhiyun goto fail_free;
100*4882a593Smuzhiyun
101*4882a593Smuzhiyun err = ns_alloc_inum(&ns->ns);
102*4882a593Smuzhiyun if (err)
103*4882a593Smuzhiyun goto fail_free_page;
104*4882a593Smuzhiyun
105*4882a593Smuzhiyun ns->ucounts = ucounts;
106*4882a593Smuzhiyun ns->ns.ops = &timens_operations;
107*4882a593Smuzhiyun ns->user_ns = get_user_ns(user_ns);
108*4882a593Smuzhiyun ns->offsets = old_ns->offsets;
109*4882a593Smuzhiyun ns->frozen_offsets = false;
110*4882a593Smuzhiyun return ns;
111*4882a593Smuzhiyun
112*4882a593Smuzhiyun fail_free_page:
113*4882a593Smuzhiyun __free_page(ns->vvar_page);
114*4882a593Smuzhiyun fail_free:
115*4882a593Smuzhiyun kfree(ns);
116*4882a593Smuzhiyun fail_dec:
117*4882a593Smuzhiyun dec_time_namespaces(ucounts);
118*4882a593Smuzhiyun fail:
119*4882a593Smuzhiyun return ERR_PTR(err);
120*4882a593Smuzhiyun }
121*4882a593Smuzhiyun
122*4882a593Smuzhiyun /**
123*4882a593Smuzhiyun * copy_time_ns - Create timens_for_children from @old_ns
124*4882a593Smuzhiyun * @flags: Cloning flags
125*4882a593Smuzhiyun * @user_ns: User namespace which owns a new namespace.
126*4882a593Smuzhiyun * @old_ns: Namespace to clone
127*4882a593Smuzhiyun *
128*4882a593Smuzhiyun * If CLONE_NEWTIME specified in @flags, creates a new timens_for_children;
129*4882a593Smuzhiyun * adds a refcounter to @old_ns otherwise.
130*4882a593Smuzhiyun *
131*4882a593Smuzhiyun * Return: timens_for_children namespace or ERR_PTR.
132*4882a593Smuzhiyun */
copy_time_ns(unsigned long flags,struct user_namespace * user_ns,struct time_namespace * old_ns)133*4882a593Smuzhiyun struct time_namespace *copy_time_ns(unsigned long flags,
134*4882a593Smuzhiyun struct user_namespace *user_ns, struct time_namespace *old_ns)
135*4882a593Smuzhiyun {
136*4882a593Smuzhiyun if (!(flags & CLONE_NEWTIME))
137*4882a593Smuzhiyun return get_time_ns(old_ns);
138*4882a593Smuzhiyun
139*4882a593Smuzhiyun return clone_time_ns(user_ns, old_ns);
140*4882a593Smuzhiyun }
141*4882a593Smuzhiyun
offset_from_ts(struct timespec64 off)142*4882a593Smuzhiyun static struct timens_offset offset_from_ts(struct timespec64 off)
143*4882a593Smuzhiyun {
144*4882a593Smuzhiyun struct timens_offset ret;
145*4882a593Smuzhiyun
146*4882a593Smuzhiyun ret.sec = off.tv_sec;
147*4882a593Smuzhiyun ret.nsec = off.tv_nsec;
148*4882a593Smuzhiyun
149*4882a593Smuzhiyun return ret;
150*4882a593Smuzhiyun }
151*4882a593Smuzhiyun
152*4882a593Smuzhiyun /*
153*4882a593Smuzhiyun * A time namespace VVAR page has the same layout as the VVAR page which
154*4882a593Smuzhiyun * contains the system wide VDSO data.
155*4882a593Smuzhiyun *
156*4882a593Smuzhiyun * For a normal task the VVAR pages are installed in the normal ordering:
157*4882a593Smuzhiyun * VVAR
158*4882a593Smuzhiyun * PVCLOCK
159*4882a593Smuzhiyun * HVCLOCK
160*4882a593Smuzhiyun * TIMENS <- Not really required
161*4882a593Smuzhiyun *
162*4882a593Smuzhiyun * Now for a timens task the pages are installed in the following order:
163*4882a593Smuzhiyun * TIMENS
164*4882a593Smuzhiyun * PVCLOCK
165*4882a593Smuzhiyun * HVCLOCK
166*4882a593Smuzhiyun * VVAR
167*4882a593Smuzhiyun *
168*4882a593Smuzhiyun * The check for vdso_data->clock_mode is in the unlikely path of
169*4882a593Smuzhiyun * the seq begin magic. So for the non-timens case most of the time
170*4882a593Smuzhiyun * 'seq' is even, so the branch is not taken.
171*4882a593Smuzhiyun *
172*4882a593Smuzhiyun * If 'seq' is odd, i.e. a concurrent update is in progress, the extra check
173*4882a593Smuzhiyun * for vdso_data->clock_mode is a non-issue. The task is spin waiting for the
174*4882a593Smuzhiyun * update to finish and for 'seq' to become even anyway.
175*4882a593Smuzhiyun *
176*4882a593Smuzhiyun * Timens page has vdso_data->clock_mode set to VDSO_CLOCKMODE_TIMENS which
177*4882a593Smuzhiyun * enforces the time namespace handling path.
178*4882a593Smuzhiyun */
timens_setup_vdso_data(struct vdso_data * vdata,struct time_namespace * ns)179*4882a593Smuzhiyun static void timens_setup_vdso_data(struct vdso_data *vdata,
180*4882a593Smuzhiyun struct time_namespace *ns)
181*4882a593Smuzhiyun {
182*4882a593Smuzhiyun struct timens_offset *offset = vdata->offset;
183*4882a593Smuzhiyun struct timens_offset monotonic = offset_from_ts(ns->offsets.monotonic);
184*4882a593Smuzhiyun struct timens_offset boottime = offset_from_ts(ns->offsets.boottime);
185*4882a593Smuzhiyun
186*4882a593Smuzhiyun vdata->seq = 1;
187*4882a593Smuzhiyun vdata->clock_mode = VDSO_CLOCKMODE_TIMENS;
188*4882a593Smuzhiyun offset[CLOCK_MONOTONIC] = monotonic;
189*4882a593Smuzhiyun offset[CLOCK_MONOTONIC_RAW] = monotonic;
190*4882a593Smuzhiyun offset[CLOCK_MONOTONIC_COARSE] = monotonic;
191*4882a593Smuzhiyun offset[CLOCK_BOOTTIME] = boottime;
192*4882a593Smuzhiyun offset[CLOCK_BOOTTIME_ALARM] = boottime;
193*4882a593Smuzhiyun }
194*4882a593Smuzhiyun
195*4882a593Smuzhiyun /*
196*4882a593Smuzhiyun * Protects possibly multiple offsets writers racing each other
197*4882a593Smuzhiyun * and tasks entering the namespace.
198*4882a593Smuzhiyun */
199*4882a593Smuzhiyun static DEFINE_MUTEX(offset_lock);
200*4882a593Smuzhiyun
timens_set_vvar_page(struct task_struct * task,struct time_namespace * ns)201*4882a593Smuzhiyun static void timens_set_vvar_page(struct task_struct *task,
202*4882a593Smuzhiyun struct time_namespace *ns)
203*4882a593Smuzhiyun {
204*4882a593Smuzhiyun struct vdso_data *vdata;
205*4882a593Smuzhiyun unsigned int i;
206*4882a593Smuzhiyun
207*4882a593Smuzhiyun if (ns == &init_time_ns)
208*4882a593Smuzhiyun return;
209*4882a593Smuzhiyun
210*4882a593Smuzhiyun /* Fast-path, taken by every task in namespace except the first. */
211*4882a593Smuzhiyun if (likely(ns->frozen_offsets))
212*4882a593Smuzhiyun return;
213*4882a593Smuzhiyun
214*4882a593Smuzhiyun mutex_lock(&offset_lock);
215*4882a593Smuzhiyun /* Nothing to-do: vvar_page has been already initialized. */
216*4882a593Smuzhiyun if (ns->frozen_offsets)
217*4882a593Smuzhiyun goto out;
218*4882a593Smuzhiyun
219*4882a593Smuzhiyun ns->frozen_offsets = true;
220*4882a593Smuzhiyun vdata = arch_get_vdso_data(page_address(ns->vvar_page));
221*4882a593Smuzhiyun
222*4882a593Smuzhiyun for (i = 0; i < CS_BASES; i++)
223*4882a593Smuzhiyun timens_setup_vdso_data(&vdata[i], ns);
224*4882a593Smuzhiyun
225*4882a593Smuzhiyun out:
226*4882a593Smuzhiyun mutex_unlock(&offset_lock);
227*4882a593Smuzhiyun }
228*4882a593Smuzhiyun
free_time_ns(struct kref * kref)229*4882a593Smuzhiyun void free_time_ns(struct kref *kref)
230*4882a593Smuzhiyun {
231*4882a593Smuzhiyun struct time_namespace *ns;
232*4882a593Smuzhiyun
233*4882a593Smuzhiyun ns = container_of(kref, struct time_namespace, kref);
234*4882a593Smuzhiyun dec_time_namespaces(ns->ucounts);
235*4882a593Smuzhiyun put_user_ns(ns->user_ns);
236*4882a593Smuzhiyun ns_free_inum(&ns->ns);
237*4882a593Smuzhiyun __free_page(ns->vvar_page);
238*4882a593Smuzhiyun kfree(ns);
239*4882a593Smuzhiyun }
240*4882a593Smuzhiyun
to_time_ns(struct ns_common * ns)241*4882a593Smuzhiyun static struct time_namespace *to_time_ns(struct ns_common *ns)
242*4882a593Smuzhiyun {
243*4882a593Smuzhiyun return container_of(ns, struct time_namespace, ns);
244*4882a593Smuzhiyun }
245*4882a593Smuzhiyun
timens_get(struct task_struct * task)246*4882a593Smuzhiyun static struct ns_common *timens_get(struct task_struct *task)
247*4882a593Smuzhiyun {
248*4882a593Smuzhiyun struct time_namespace *ns = NULL;
249*4882a593Smuzhiyun struct nsproxy *nsproxy;
250*4882a593Smuzhiyun
251*4882a593Smuzhiyun task_lock(task);
252*4882a593Smuzhiyun nsproxy = task->nsproxy;
253*4882a593Smuzhiyun if (nsproxy) {
254*4882a593Smuzhiyun ns = nsproxy->time_ns;
255*4882a593Smuzhiyun get_time_ns(ns);
256*4882a593Smuzhiyun }
257*4882a593Smuzhiyun task_unlock(task);
258*4882a593Smuzhiyun
259*4882a593Smuzhiyun return ns ? &ns->ns : NULL;
260*4882a593Smuzhiyun }
261*4882a593Smuzhiyun
timens_for_children_get(struct task_struct * task)262*4882a593Smuzhiyun static struct ns_common *timens_for_children_get(struct task_struct *task)
263*4882a593Smuzhiyun {
264*4882a593Smuzhiyun struct time_namespace *ns = NULL;
265*4882a593Smuzhiyun struct nsproxy *nsproxy;
266*4882a593Smuzhiyun
267*4882a593Smuzhiyun task_lock(task);
268*4882a593Smuzhiyun nsproxy = task->nsproxy;
269*4882a593Smuzhiyun if (nsproxy) {
270*4882a593Smuzhiyun ns = nsproxy->time_ns_for_children;
271*4882a593Smuzhiyun get_time_ns(ns);
272*4882a593Smuzhiyun }
273*4882a593Smuzhiyun task_unlock(task);
274*4882a593Smuzhiyun
275*4882a593Smuzhiyun return ns ? &ns->ns : NULL;
276*4882a593Smuzhiyun }
277*4882a593Smuzhiyun
timens_put(struct ns_common * ns)278*4882a593Smuzhiyun static void timens_put(struct ns_common *ns)
279*4882a593Smuzhiyun {
280*4882a593Smuzhiyun put_time_ns(to_time_ns(ns));
281*4882a593Smuzhiyun }
282*4882a593Smuzhiyun
timens_commit(struct task_struct * tsk,struct time_namespace * ns)283*4882a593Smuzhiyun void timens_commit(struct task_struct *tsk, struct time_namespace *ns)
284*4882a593Smuzhiyun {
285*4882a593Smuzhiyun timens_set_vvar_page(tsk, ns);
286*4882a593Smuzhiyun vdso_join_timens(tsk, ns);
287*4882a593Smuzhiyun }
288*4882a593Smuzhiyun
timens_install(struct nsset * nsset,struct ns_common * new)289*4882a593Smuzhiyun static int timens_install(struct nsset *nsset, struct ns_common *new)
290*4882a593Smuzhiyun {
291*4882a593Smuzhiyun struct nsproxy *nsproxy = nsset->nsproxy;
292*4882a593Smuzhiyun struct time_namespace *ns = to_time_ns(new);
293*4882a593Smuzhiyun
294*4882a593Smuzhiyun if (!current_is_single_threaded())
295*4882a593Smuzhiyun return -EUSERS;
296*4882a593Smuzhiyun
297*4882a593Smuzhiyun if (!ns_capable(ns->user_ns, CAP_SYS_ADMIN) ||
298*4882a593Smuzhiyun !ns_capable(nsset->cred->user_ns, CAP_SYS_ADMIN))
299*4882a593Smuzhiyun return -EPERM;
300*4882a593Smuzhiyun
301*4882a593Smuzhiyun get_time_ns(ns);
302*4882a593Smuzhiyun put_time_ns(nsproxy->time_ns);
303*4882a593Smuzhiyun nsproxy->time_ns = ns;
304*4882a593Smuzhiyun
305*4882a593Smuzhiyun get_time_ns(ns);
306*4882a593Smuzhiyun put_time_ns(nsproxy->time_ns_for_children);
307*4882a593Smuzhiyun nsproxy->time_ns_for_children = ns;
308*4882a593Smuzhiyun return 0;
309*4882a593Smuzhiyun }
310*4882a593Smuzhiyun
timens_on_fork(struct nsproxy * nsproxy,struct task_struct * tsk)311*4882a593Smuzhiyun int timens_on_fork(struct nsproxy *nsproxy, struct task_struct *tsk)
312*4882a593Smuzhiyun {
313*4882a593Smuzhiyun struct ns_common *nsc = &nsproxy->time_ns_for_children->ns;
314*4882a593Smuzhiyun struct time_namespace *ns = to_time_ns(nsc);
315*4882a593Smuzhiyun
316*4882a593Smuzhiyun /* create_new_namespaces() already incremented the ref counter */
317*4882a593Smuzhiyun if (nsproxy->time_ns == nsproxy->time_ns_for_children)
318*4882a593Smuzhiyun return 0;
319*4882a593Smuzhiyun
320*4882a593Smuzhiyun get_time_ns(ns);
321*4882a593Smuzhiyun put_time_ns(nsproxy->time_ns);
322*4882a593Smuzhiyun nsproxy->time_ns = ns;
323*4882a593Smuzhiyun
324*4882a593Smuzhiyun timens_commit(tsk, ns);
325*4882a593Smuzhiyun
326*4882a593Smuzhiyun return 0;
327*4882a593Smuzhiyun }
328*4882a593Smuzhiyun
timens_owner(struct ns_common * ns)329*4882a593Smuzhiyun static struct user_namespace *timens_owner(struct ns_common *ns)
330*4882a593Smuzhiyun {
331*4882a593Smuzhiyun return to_time_ns(ns)->user_ns;
332*4882a593Smuzhiyun }
333*4882a593Smuzhiyun
show_offset(struct seq_file * m,int clockid,struct timespec64 * ts)334*4882a593Smuzhiyun static void show_offset(struct seq_file *m, int clockid, struct timespec64 *ts)
335*4882a593Smuzhiyun {
336*4882a593Smuzhiyun char *clock;
337*4882a593Smuzhiyun
338*4882a593Smuzhiyun switch (clockid) {
339*4882a593Smuzhiyun case CLOCK_BOOTTIME:
340*4882a593Smuzhiyun clock = "boottime";
341*4882a593Smuzhiyun break;
342*4882a593Smuzhiyun case CLOCK_MONOTONIC:
343*4882a593Smuzhiyun clock = "monotonic";
344*4882a593Smuzhiyun break;
345*4882a593Smuzhiyun default:
346*4882a593Smuzhiyun clock = "unknown";
347*4882a593Smuzhiyun break;
348*4882a593Smuzhiyun }
349*4882a593Smuzhiyun seq_printf(m, "%-10s %10lld %9ld\n", clock, ts->tv_sec, ts->tv_nsec);
350*4882a593Smuzhiyun }
351*4882a593Smuzhiyun
proc_timens_show_offsets(struct task_struct * p,struct seq_file * m)352*4882a593Smuzhiyun void proc_timens_show_offsets(struct task_struct *p, struct seq_file *m)
353*4882a593Smuzhiyun {
354*4882a593Smuzhiyun struct ns_common *ns;
355*4882a593Smuzhiyun struct time_namespace *time_ns;
356*4882a593Smuzhiyun
357*4882a593Smuzhiyun ns = timens_for_children_get(p);
358*4882a593Smuzhiyun if (!ns)
359*4882a593Smuzhiyun return;
360*4882a593Smuzhiyun time_ns = to_time_ns(ns);
361*4882a593Smuzhiyun
362*4882a593Smuzhiyun show_offset(m, CLOCK_MONOTONIC, &time_ns->offsets.monotonic);
363*4882a593Smuzhiyun show_offset(m, CLOCK_BOOTTIME, &time_ns->offsets.boottime);
364*4882a593Smuzhiyun put_time_ns(time_ns);
365*4882a593Smuzhiyun }
366*4882a593Smuzhiyun
proc_timens_set_offset(struct file * file,struct task_struct * p,struct proc_timens_offset * offsets,int noffsets)367*4882a593Smuzhiyun int proc_timens_set_offset(struct file *file, struct task_struct *p,
368*4882a593Smuzhiyun struct proc_timens_offset *offsets, int noffsets)
369*4882a593Smuzhiyun {
370*4882a593Smuzhiyun struct ns_common *ns;
371*4882a593Smuzhiyun struct time_namespace *time_ns;
372*4882a593Smuzhiyun struct timespec64 tp;
373*4882a593Smuzhiyun int i, err;
374*4882a593Smuzhiyun
375*4882a593Smuzhiyun ns = timens_for_children_get(p);
376*4882a593Smuzhiyun if (!ns)
377*4882a593Smuzhiyun return -ESRCH;
378*4882a593Smuzhiyun time_ns = to_time_ns(ns);
379*4882a593Smuzhiyun
380*4882a593Smuzhiyun if (!file_ns_capable(file, time_ns->user_ns, CAP_SYS_TIME)) {
381*4882a593Smuzhiyun put_time_ns(time_ns);
382*4882a593Smuzhiyun return -EPERM;
383*4882a593Smuzhiyun }
384*4882a593Smuzhiyun
385*4882a593Smuzhiyun for (i = 0; i < noffsets; i++) {
386*4882a593Smuzhiyun struct proc_timens_offset *off = &offsets[i];
387*4882a593Smuzhiyun
388*4882a593Smuzhiyun switch (off->clockid) {
389*4882a593Smuzhiyun case CLOCK_MONOTONIC:
390*4882a593Smuzhiyun ktime_get_ts64(&tp);
391*4882a593Smuzhiyun break;
392*4882a593Smuzhiyun case CLOCK_BOOTTIME:
393*4882a593Smuzhiyun ktime_get_boottime_ts64(&tp);
394*4882a593Smuzhiyun break;
395*4882a593Smuzhiyun default:
396*4882a593Smuzhiyun err = -EINVAL;
397*4882a593Smuzhiyun goto out;
398*4882a593Smuzhiyun }
399*4882a593Smuzhiyun
400*4882a593Smuzhiyun err = -ERANGE;
401*4882a593Smuzhiyun
402*4882a593Smuzhiyun if (off->val.tv_sec > KTIME_SEC_MAX ||
403*4882a593Smuzhiyun off->val.tv_sec < -KTIME_SEC_MAX)
404*4882a593Smuzhiyun goto out;
405*4882a593Smuzhiyun
406*4882a593Smuzhiyun tp = timespec64_add(tp, off->val);
407*4882a593Smuzhiyun /*
408*4882a593Smuzhiyun * KTIME_SEC_MAX is divided by 2 to be sure that KTIME_MAX is
409*4882a593Smuzhiyun * still unreachable.
410*4882a593Smuzhiyun */
411*4882a593Smuzhiyun if (tp.tv_sec < 0 || tp.tv_sec > KTIME_SEC_MAX / 2)
412*4882a593Smuzhiyun goto out;
413*4882a593Smuzhiyun }
414*4882a593Smuzhiyun
415*4882a593Smuzhiyun mutex_lock(&offset_lock);
416*4882a593Smuzhiyun if (time_ns->frozen_offsets) {
417*4882a593Smuzhiyun err = -EACCES;
418*4882a593Smuzhiyun goto out_unlock;
419*4882a593Smuzhiyun }
420*4882a593Smuzhiyun
421*4882a593Smuzhiyun err = 0;
422*4882a593Smuzhiyun /* Don't report errors after this line */
423*4882a593Smuzhiyun for (i = 0; i < noffsets; i++) {
424*4882a593Smuzhiyun struct proc_timens_offset *off = &offsets[i];
425*4882a593Smuzhiyun struct timespec64 *offset = NULL;
426*4882a593Smuzhiyun
427*4882a593Smuzhiyun switch (off->clockid) {
428*4882a593Smuzhiyun case CLOCK_MONOTONIC:
429*4882a593Smuzhiyun offset = &time_ns->offsets.monotonic;
430*4882a593Smuzhiyun break;
431*4882a593Smuzhiyun case CLOCK_BOOTTIME:
432*4882a593Smuzhiyun offset = &time_ns->offsets.boottime;
433*4882a593Smuzhiyun break;
434*4882a593Smuzhiyun }
435*4882a593Smuzhiyun
436*4882a593Smuzhiyun *offset = off->val;
437*4882a593Smuzhiyun }
438*4882a593Smuzhiyun
439*4882a593Smuzhiyun out_unlock:
440*4882a593Smuzhiyun mutex_unlock(&offset_lock);
441*4882a593Smuzhiyun out:
442*4882a593Smuzhiyun put_time_ns(time_ns);
443*4882a593Smuzhiyun
444*4882a593Smuzhiyun return err;
445*4882a593Smuzhiyun }
446*4882a593Smuzhiyun
447*4882a593Smuzhiyun const struct proc_ns_operations timens_operations = {
448*4882a593Smuzhiyun .name = "time",
449*4882a593Smuzhiyun .type = CLONE_NEWTIME,
450*4882a593Smuzhiyun .get = timens_get,
451*4882a593Smuzhiyun .put = timens_put,
452*4882a593Smuzhiyun .install = timens_install,
453*4882a593Smuzhiyun .owner = timens_owner,
454*4882a593Smuzhiyun };
455*4882a593Smuzhiyun
456*4882a593Smuzhiyun const struct proc_ns_operations timens_for_children_operations = {
457*4882a593Smuzhiyun .name = "time_for_children",
458*4882a593Smuzhiyun .real_ns_name = "time",
459*4882a593Smuzhiyun .type = CLONE_NEWTIME,
460*4882a593Smuzhiyun .get = timens_for_children_get,
461*4882a593Smuzhiyun .put = timens_put,
462*4882a593Smuzhiyun .install = timens_install,
463*4882a593Smuzhiyun .owner = timens_owner,
464*4882a593Smuzhiyun };
465*4882a593Smuzhiyun
466*4882a593Smuzhiyun struct time_namespace init_time_ns = {
467*4882a593Smuzhiyun .kref = KREF_INIT(3),
468*4882a593Smuzhiyun .user_ns = &init_user_ns,
469*4882a593Smuzhiyun .ns.inum = PROC_TIME_INIT_INO,
470*4882a593Smuzhiyun .ns.ops = &timens_operations,
471*4882a593Smuzhiyun .frozen_offsets = true,
472*4882a593Smuzhiyun };
473*4882a593Smuzhiyun
time_ns_init(void)474*4882a593Smuzhiyun static int __init time_ns_init(void)
475*4882a593Smuzhiyun {
476*4882a593Smuzhiyun return 0;
477*4882a593Smuzhiyun }
478*4882a593Smuzhiyun subsys_initcall(time_ns_init);
479