2662a69e03829d009cd4216ff1d253085c718757
[sfrench/cifs-2.6.git] / kernel / time / namespace.c
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/time_namespace.h>
8 #include <linux/user_namespace.h>
9 #include <linux/sched/signal.h>
10 #include <linux/sched/task.h>
11 #include <linux/proc_ns.h>
12 #include <linux/export.h>
13 #include <linux/time.h>
14 #include <linux/slab.h>
15 #include <linux/cred.h>
16 #include <linux/err.h>
17
18 static struct ucounts *inc_time_namespaces(struct user_namespace *ns)
19 {
20         return inc_ucount(ns, current_euid(), UCOUNT_TIME_NAMESPACES);
21 }
22
23 static void dec_time_namespaces(struct ucounts *ucounts)
24 {
25         dec_ucount(ucounts, UCOUNT_TIME_NAMESPACES);
26 }
27
28 /**
29  * clone_time_ns - Clone a time namespace
30  * @user_ns:    User namespace which owns a new namespace.
31  * @old_ns:     Namespace to clone
32  *
33  * Clone @old_ns and set the clone refcount to 1
34  *
35  * Return: The new namespace or ERR_PTR.
36  */
37 static struct time_namespace *clone_time_ns(struct user_namespace *user_ns,
38                                           struct time_namespace *old_ns)
39 {
40         struct time_namespace *ns;
41         struct ucounts *ucounts;
42         int err;
43
44         err = -ENOSPC;
45         ucounts = inc_time_namespaces(user_ns);
46         if (!ucounts)
47                 goto fail;
48
49         err = -ENOMEM;
50         ns = kmalloc(sizeof(*ns), GFP_KERNEL);
51         if (!ns)
52                 goto fail_dec;
53
54         kref_init(&ns->kref);
55
56         err = ns_alloc_inum(&ns->ns);
57         if (err)
58                 goto fail_free;
59
60         ns->ucounts = ucounts;
61         ns->ns.ops = &timens_operations;
62         ns->user_ns = get_user_ns(user_ns);
63         return ns;
64
65 fail_free:
66         kfree(ns);
67 fail_dec:
68         dec_time_namespaces(ucounts);
69 fail:
70         return ERR_PTR(err);
71 }
72
73 /**
74  * copy_time_ns - Create timens_for_children from @old_ns
75  * @flags:      Cloning flags
76  * @user_ns:    User namespace which owns a new namespace.
77  * @old_ns:     Namespace to clone
78  *
79  * If CLONE_NEWTIME specified in @flags, creates a new timens_for_children;
80  * adds a refcounter to @old_ns otherwise.
81  *
82  * Return: timens_for_children namespace or ERR_PTR.
83  */
84 struct time_namespace *copy_time_ns(unsigned long flags,
85         struct user_namespace *user_ns, struct time_namespace *old_ns)
86 {
87         if (!(flags & CLONE_NEWTIME))
88                 return get_time_ns(old_ns);
89
90         return clone_time_ns(user_ns, old_ns);
91 }
92
93 void free_time_ns(struct kref *kref)
94 {
95         struct time_namespace *ns;
96
97         ns = container_of(kref, struct time_namespace, kref);
98         dec_time_namespaces(ns->ucounts);
99         put_user_ns(ns->user_ns);
100         ns_free_inum(&ns->ns);
101         kfree(ns);
102 }
103
104 static struct time_namespace *to_time_ns(struct ns_common *ns)
105 {
106         return container_of(ns, struct time_namespace, ns);
107 }
108
109 static struct ns_common *timens_get(struct task_struct *task)
110 {
111         struct time_namespace *ns = NULL;
112         struct nsproxy *nsproxy;
113
114         task_lock(task);
115         nsproxy = task->nsproxy;
116         if (nsproxy) {
117                 ns = nsproxy->time_ns;
118                 get_time_ns(ns);
119         }
120         task_unlock(task);
121
122         return ns ? &ns->ns : NULL;
123 }
124
125 static struct ns_common *timens_for_children_get(struct task_struct *task)
126 {
127         struct time_namespace *ns = NULL;
128         struct nsproxy *nsproxy;
129
130         task_lock(task);
131         nsproxy = task->nsproxy;
132         if (nsproxy) {
133                 ns = nsproxy->time_ns_for_children;
134                 get_time_ns(ns);
135         }
136         task_unlock(task);
137
138         return ns ? &ns->ns : NULL;
139 }
140
141 static void timens_put(struct ns_common *ns)
142 {
143         put_time_ns(to_time_ns(ns));
144 }
145
146 static int timens_install(struct nsproxy *nsproxy, struct ns_common *new)
147 {
148         struct time_namespace *ns = to_time_ns(new);
149
150         if (!current_is_single_threaded())
151                 return -EUSERS;
152
153         if (!ns_capable(ns->user_ns, CAP_SYS_ADMIN) ||
154             !ns_capable(current_user_ns(), CAP_SYS_ADMIN))
155                 return -EPERM;
156
157         get_time_ns(ns);
158         put_time_ns(nsproxy->time_ns);
159         nsproxy->time_ns = ns;
160
161         get_time_ns(ns);
162         put_time_ns(nsproxy->time_ns_for_children);
163         nsproxy->time_ns_for_children = ns;
164         return 0;
165 }
166
167 int timens_on_fork(struct nsproxy *nsproxy, struct task_struct *tsk)
168 {
169         struct ns_common *nsc = &nsproxy->time_ns_for_children->ns;
170         struct time_namespace *ns = to_time_ns(nsc);
171
172         /* create_new_namespaces() already incremented the ref counter */
173         if (nsproxy->time_ns == nsproxy->time_ns_for_children)
174                 return 0;
175
176         get_time_ns(ns);
177         put_time_ns(nsproxy->time_ns);
178         nsproxy->time_ns = ns;
179
180         return 0;
181 }
182
183 static struct user_namespace *timens_owner(struct ns_common *ns)
184 {
185         return to_time_ns(ns)->user_ns;
186 }
187
188 const struct proc_ns_operations timens_operations = {
189         .name           = "time",
190         .type           = CLONE_NEWTIME,
191         .get            = timens_get,
192         .put            = timens_put,
193         .install        = timens_install,
194         .owner          = timens_owner,
195 };
196
197 const struct proc_ns_operations timens_for_children_operations = {
198         .name           = "time_for_children",
199         .type           = CLONE_NEWTIME,
200         .get            = timens_for_children_get,
201         .put            = timens_put,
202         .install        = timens_install,
203         .owner          = timens_owner,
204 };
205
206 struct time_namespace init_time_ns = {
207         .kref           = KREF_INIT(3),
208         .user_ns        = &init_user_ns,
209         .ns.inum        = PROC_TIME_INIT_INO,
210         .ns.ops         = &timens_operations,
211 };
212
213 static int __init time_ns_init(void)
214 {
215         return 0;
216 }
217 subsys_initcall(time_ns_init);