Lines Matching +full:ref +full:- +full:clock +full:- +full:period +full:- +full:ns

1 // SPDX-License-Identifier: GPL-2.0
31 offset = timespec64_to_ktime(ns_offsets->monotonic); in do_timens_ktime_to_host()
35 offset = timespec64_to_ktime(ns_offsets->boottime); in do_timens_ktime_to_host()
47 * User can specify @tim *absolute* value - if it's lesser than in do_timens_ktime_to_host()
48 * the time namespace's offset - it's already expired. in do_timens_ktime_to_host()
60 static struct ucounts *inc_time_namespaces(struct user_namespace *ns) in inc_time_namespaces() argument
62 return inc_ucount(ns, current_euid(), UCOUNT_TIME_NAMESPACES); in inc_time_namespaces()
71 * clone_time_ns - Clone a time namespace
82 struct time_namespace *ns; in clone_time_ns() local
86 err = -ENOSPC; in clone_time_ns()
91 err = -ENOMEM; in clone_time_ns()
92 ns = kzalloc(sizeof(*ns), GFP_KERNEL_ACCOUNT); in clone_time_ns()
93 if (!ns) in clone_time_ns()
96 ns->vvar_page = alloc_page(GFP_KERNEL_ACCOUNT | __GFP_ZERO); in clone_time_ns()
97 if (!ns->vvar_page) in clone_time_ns()
100 err = ns_common_init(ns); in clone_time_ns()
104 ns->ucounts = ucounts; in clone_time_ns()
105 ns->user_ns = get_user_ns(user_ns); in clone_time_ns()
106 ns->offsets = old_ns->offsets; in clone_time_ns()
107 ns->frozen_offsets = false; in clone_time_ns()
108 ns_tree_add(ns); in clone_time_ns()
109 return ns; in clone_time_ns()
112 __free_page(ns->vvar_page); in clone_time_ns()
114 kfree(ns); in clone_time_ns()
122 * copy_time_ns - Create timens_for_children from @old_ns
159 * TIMENS <- Not really required
167 * The check for vdso_clock->clock_mode is in the unlikely path of
168 * the seq begin magic. So for the non-timens case most of the time
172 * for vdso_clock->clock_mode is a non-issue. The task is spin waiting for the
175 * Timens page has vdso_clock->clock_mode set to VDSO_CLOCKMODE_TIMENS which
179 struct time_namespace *ns) in timens_setup_vdso_clock_data() argument
181 struct timens_offset *offset = vc->offset; in timens_setup_vdso_clock_data()
182 struct timens_offset monotonic = offset_from_ts(ns->offsets.monotonic); in timens_setup_vdso_clock_data()
183 struct timens_offset boottime = offset_from_ts(ns->offsets.boottime); in timens_setup_vdso_clock_data()
185 vc->seq = 1; in timens_setup_vdso_clock_data()
186 vc->clock_mode = VDSO_CLOCKMODE_TIMENS; in timens_setup_vdso_clock_data()
196 if (likely(vma->vm_mm == current->mm)) in find_timens_vvar_page()
197 return current->nsproxy->time_ns->vvar_page; in find_timens_vvar_page()
219 struct time_namespace *ns) in timens_set_vvar_page() argument
225 if (ns == &init_time_ns) in timens_set_vvar_page()
228 /* Fast-path, taken by every task in namespace except the first. */ in timens_set_vvar_page()
229 if (likely(ns->frozen_offsets)) in timens_set_vvar_page()
233 /* Nothing to-do: vvar_page has been already initialized. */ in timens_set_vvar_page()
234 if (ns->frozen_offsets) in timens_set_vvar_page()
237 ns->frozen_offsets = true; in timens_set_vvar_page()
238 vdata = page_address(ns->vvar_page); in timens_set_vvar_page()
239 vc = vdata->clock_data; in timens_set_vvar_page()
242 timens_setup_vdso_clock_data(&vc[i], ns); in timens_set_vvar_page()
245 for (i = 0; i < ARRAY_SIZE(vdata->aux_clock_data); i++) in timens_set_vvar_page()
246 timens_setup_vdso_clock_data(&vdata->aux_clock_data[i], ns); in timens_set_vvar_page()
253 void free_time_ns(struct time_namespace *ns) in free_time_ns() argument
255 ns_tree_remove(ns); in free_time_ns()
256 dec_time_namespaces(ns->ucounts); in free_time_ns()
257 put_user_ns(ns->user_ns); in free_time_ns()
258 ns_common_free(ns); in free_time_ns()
259 __free_page(ns->vvar_page); in free_time_ns()
260 /* Concurrent nstree traversal depends on a grace period. */ in free_time_ns()
261 kfree_rcu(ns, ns.ns_rcu); in free_time_ns()
266 struct time_namespace *ns = NULL; in timens_get() local
270 nsproxy = task->nsproxy; in timens_get()
272 ns = nsproxy->time_ns; in timens_get()
273 get_time_ns(ns); in timens_get()
277 return ns ? &ns->ns : NULL; in timens_get()
282 struct time_namespace *ns = NULL; in timens_for_children_get() local
286 nsproxy = task->nsproxy; in timens_for_children_get()
288 ns = nsproxy->time_ns_for_children; in timens_for_children_get()
289 get_time_ns(ns); in timens_for_children_get()
293 return ns ? &ns->ns : NULL; in timens_for_children_get()
296 static void timens_put(struct ns_common *ns) in timens_put() argument
298 put_time_ns(to_time_ns(ns)); in timens_put()
301 void timens_commit(struct task_struct *tsk, struct time_namespace *ns) in timens_commit() argument
303 timens_set_vvar_page(tsk, ns); in timens_commit()
304 vdso_join_timens(tsk, ns); in timens_commit()
309 struct nsproxy *nsproxy = nsset->nsproxy; in timens_install()
310 struct time_namespace *ns = to_time_ns(new); in timens_install() local
313 return -EUSERS; in timens_install()
315 if (!ns_capable(ns->user_ns, CAP_SYS_ADMIN) || in timens_install()
316 !ns_capable(nsset->cred->user_ns, CAP_SYS_ADMIN)) in timens_install()
317 return -EPERM; in timens_install()
319 get_time_ns(ns); in timens_install()
320 put_time_ns(nsproxy->time_ns); in timens_install()
321 nsproxy->time_ns = ns; in timens_install()
323 get_time_ns(ns); in timens_install()
324 put_time_ns(nsproxy->time_ns_for_children); in timens_install()
325 nsproxy->time_ns_for_children = ns; in timens_install()
331 struct ns_common *nsc = &nsproxy->time_ns_for_children->ns; in timens_on_fork()
332 struct time_namespace *ns = to_time_ns(nsc); in timens_on_fork() local
334 /* create_new_namespaces() already incremented the ref counter */ in timens_on_fork()
335 if (nsproxy->time_ns == nsproxy->time_ns_for_children) in timens_on_fork()
338 get_time_ns(ns); in timens_on_fork()
339 put_time_ns(nsproxy->time_ns); in timens_on_fork()
340 nsproxy->time_ns = ns; in timens_on_fork()
342 timens_commit(tsk, ns); in timens_on_fork()
345 static struct user_namespace *timens_owner(struct ns_common *ns) in timens_owner() argument
347 return to_time_ns(ns)->user_ns; in timens_owner()
352 char *clock; in show_offset() local
356 clock = "boottime"; in show_offset()
359 clock = "monotonic"; in show_offset()
362 clock = "unknown"; in show_offset()
365 seq_printf(m, "%-10s %10lld %9ld\n", clock, ts->tv_sec, ts->tv_nsec); in show_offset()
370 struct ns_common *ns; in proc_timens_show_offsets() local
373 ns = timens_for_children_get(p); in proc_timens_show_offsets()
374 if (!ns) in proc_timens_show_offsets()
376 time_ns = to_time_ns(ns); in proc_timens_show_offsets()
378 show_offset(m, CLOCK_MONOTONIC, &time_ns->offsets.monotonic); in proc_timens_show_offsets()
379 show_offset(m, CLOCK_BOOTTIME, &time_ns->offsets.boottime); in proc_timens_show_offsets()
386 struct ns_common *ns; in proc_timens_set_offset() local
391 ns = timens_for_children_get(p); in proc_timens_set_offset()
392 if (!ns) in proc_timens_set_offset()
393 return -ESRCH; in proc_timens_set_offset()
394 time_ns = to_time_ns(ns); in proc_timens_set_offset()
396 if (!file_ns_capable(file, time_ns->user_ns, CAP_SYS_TIME)) { in proc_timens_set_offset()
398 return -EPERM; in proc_timens_set_offset()
404 switch (off->clockid) { in proc_timens_set_offset()
412 err = -EINVAL; in proc_timens_set_offset()
416 err = -ERANGE; in proc_timens_set_offset()
418 if (off->val.tv_sec > KTIME_SEC_MAX || in proc_timens_set_offset()
419 off->val.tv_sec < -KTIME_SEC_MAX) in proc_timens_set_offset()
422 tp = timespec64_add(tp, off->val); in proc_timens_set_offset()
432 if (time_ns->frozen_offsets) { in proc_timens_set_offset()
433 err = -EACCES; in proc_timens_set_offset()
443 switch (off->clockid) { in proc_timens_set_offset()
445 offset = &time_ns->offsets.monotonic; in proc_timens_set_offset()
448 offset = &time_ns->offsets.boottime; in proc_timens_set_offset()
452 *offset = off->val; in proc_timens_set_offset()
481 .ns.ns_type = ns_common_type(&init_time_ns),
482 .ns.__ns_ref = REFCOUNT_INIT(3),
484 .ns.inum = ns_init_inum(&init_time_ns),
485 .ns.ops = &timens_operations,