xref: /linux/kernel/time/namespace_vdso.c (revision 9ab500d47f5f1b8c463a4fd8f345a8756da625ab)
1 // SPDX-License-Identifier: GPL-2.0
2 /*
3  * Author: Andrei Vagin <avagin@openvz.org>
4  * Author: Dmitry Safonov <dima@arista.com>
5  */
6 
7 #include <linux/cleanup.h>
8 #include <linux/mm.h>
9 #include <linux/time_namespace.h>
10 #include <linux/time.h>
11 #include <linux/vdso_datastore.h>
12 
13 #include <vdso/clocksource.h>
14 #include <vdso/datapage.h>
15 
16 #include "namespace_internal.h"
17 
18 static struct timens_offset offset_from_ts(struct timespec64 off)
19 {
20 	struct timens_offset ret;
21 
22 	ret.sec = off.tv_sec;
23 	ret.nsec = off.tv_nsec;
24 
25 	return ret;
26 }
27 
28 /*
29  * A time namespace VVAR page has the same layout as the VVAR page which
30  * contains the system wide VDSO data.
31  *
32  * For a normal task the VVAR pages are installed in the normal ordering:
33  *     VVAR
34  *     PVCLOCK
35  *     HVCLOCK
36  *     TIMENS   <- Not really required
37  *
38  * Now for a timens task the pages are installed in the following order:
39  *     TIMENS
40  *     PVCLOCK
41  *     HVCLOCK
42  *     VVAR
43  *
44  * The check for vdso_clock->clock_mode is in the unlikely path of
45  * the seq begin magic. So for the non-timens case most of the time
46  * 'seq' is even, so the branch is not taken.
47  *
48  * If 'seq' is odd, i.e. a concurrent update is in progress, the extra check
49  * for vdso_clock->clock_mode is a non-issue. The task is spin waiting for the
50  * update to finish and for 'seq' to become even anyway.
51  *
52  * Timens page has vdso_clock->clock_mode set to VDSO_CLOCKMODE_TIMENS which
53  * enforces the time namespace handling path.
54  */
55 static void timens_setup_vdso_clock_data(struct vdso_clock *vc,
56 					 struct time_namespace *ns)
57 {
58 	struct timens_offset *offset = vc->offset;
59 	struct timens_offset monotonic = offset_from_ts(ns->offsets.monotonic);
60 	struct timens_offset boottime = offset_from_ts(ns->offsets.boottime);
61 
62 	vc->seq				= 1;
63 	vc->clock_mode			= VDSO_CLOCKMODE_TIMENS;
64 	offset[CLOCK_MONOTONIC]		= monotonic;
65 	offset[CLOCK_MONOTONIC_RAW]	= monotonic;
66 	offset[CLOCK_MONOTONIC_COARSE]	= monotonic;
67 	offset[CLOCK_BOOTTIME]		= boottime;
68 	offset[CLOCK_BOOTTIME_ALARM]	= boottime;
69 }
70 
71 struct page *find_timens_vvar_page(struct vm_area_struct *vma)
72 {
73 	if (likely(vma->vm_mm == current->mm))
74 		return current->nsproxy->time_ns->vvar_page;
75 
76 	/*
77 	 * vvar_fault() protects this from being called through remote interfaces like
78 	 * /proc/$pid/mem or process_vm_{readv,writev}().
79 	 */
80 
81 	WARN(1, "vvar_page accessed remotely");
82 
83 	return NULL;
84 }
85 
86 static void timens_set_vvar_page(struct task_struct *task,
87 				struct time_namespace *ns)
88 {
89 	struct vdso_time_data *vdata;
90 	struct vdso_clock *vc;
91 	unsigned int i;
92 
93 	if (ns == &init_time_ns)
94 		return;
95 
96 	/* Fast-path, taken by every task in namespace except the first. */
97 	if (likely(ns->frozen_offsets))
98 		return;
99 
100 	guard(mutex)(&timens_offset_lock);
101 	/* Nothing to-do: vvar_page has been already initialized. */
102 	if (ns->frozen_offsets)
103 		return;
104 
105 	ns->frozen_offsets = true;
106 	vdata = page_address(ns->vvar_page);
107 	vc = vdata->clock_data;
108 
109 	for (i = 0; i < CS_BASES; i++)
110 		timens_setup_vdso_clock_data(&vc[i], ns);
111 
112 	if (IS_ENABLED(CONFIG_POSIX_AUX_CLOCKS)) {
113 		for (i = 0; i < ARRAY_SIZE(vdata->aux_clock_data); i++)
114 			timens_setup_vdso_clock_data(&vdata->aux_clock_data[i], ns);
115 	}
116 }
117 
118 /*
119  * The vvar page layout depends on whether a task belongs to the root or
120  * non-root time namespace. Whenever a task changes its namespace, the VVAR
121  * page tables are cleared and then they will be re-faulted with a
122  * corresponding layout.
123  * See also the comment near timens_setup_vdso_clock_data() for details.
124  */
125 static int vdso_join_timens(struct task_struct *task, struct time_namespace *ns)
126 {
127 	struct mm_struct *mm = task->mm;
128 	struct vm_area_struct *vma;
129 	VMA_ITERATOR(vmi, mm, 0);
130 
131 	guard(mmap_read_lock)(mm);
132 	for_each_vma(vmi, vma) {
133 		if (vma_is_special_mapping(vma, &vdso_vvar_mapping))
134 			zap_vma(vma);
135 	}
136 	return 0;
137 }
138 
139 void timens_commit(struct task_struct *tsk, struct time_namespace *ns)
140 {
141 	timens_set_vvar_page(tsk, ns);
142 	vdso_join_timens(tsk, ns);
143 }
144 
145 int timens_vdso_alloc_vvar_page(struct time_namespace *ns)
146 {
147 	ns->vvar_page = alloc_page(GFP_KERNEL_ACCOUNT | __GFP_ZERO);
148 	if (!ns->vvar_page)
149 		return -ENOMEM;
150 
151 	return 0;
152 }
153 
154 void timens_vdso_free_vvar_page(struct time_namespace *ns)
155 {
156 	__free_page(ns->vvar_page);
157 }
158