2 * linux/kernel/vserver/switch.c
4 * Virtual Server: Syscall Switch
6 * Copyright (C) 2003-2007 Herbert Pƶtzl
9 * V0.02 added signal to context
10 * V0.03 added rlimit functions
11 * V0.04 added iattr, task/xid functions
12 * V0.05 added debug/history stuff
13 * V0.06 added compat32 layer
14 * V0.07 vcmd args and perms
15 * V0.08 added status commands
19 #include <linux/linkage.h>
20 #include <linux/sched.h>
21 #include <linux/compat.h>
22 #include <asm/errno.h>
24 #include <linux/vs_context.h>
25 #include <linux/vs_network.h>
26 #include <linux/vserver/switch.h>
28 #include "vci_config.h"
31 int vc_get_version(uint32_t id)
33 #ifdef CONFIG_VSERVER_LEGACY_VERSION
35 return VCI_LEGACY_VERSION;
41 int vc_get_vci(uint32_t id)
43 return vci_kernel_config();
46 #include <linux/vserver/context_cmd.h>
47 #include <linux/vserver/cvirt_cmd.h>
48 #include <linux/vserver/cacct_cmd.h>
49 #include <linux/vserver/limit_cmd.h>
50 #include <linux/vserver/network_cmd.h>
51 #include <linux/vserver/sched_cmd.h>
52 #include <linux/vserver/debug_cmd.h>
53 #include <linux/vserver/inode_cmd.h>
54 #include <linux/vserver/dlimit_cmd.h>
55 #include <linux/vserver/signal_cmd.h>
56 #include <linux/vserver/space_cmd.h>
58 #include <linux/vserver/legacy.h>
59 #include <linux/vserver/inode.h>
60 #include <linux/vserver/dlimit.h>
64 #define __COMPAT(name, id, data, compat) \
65 (compat) ? name ## _x32 (id, data) : name (id, data)
67 #define __COMPAT(name, id, data, compat) \
73 long do_vcmd(uint32_t cmd, uint32_t id,
74 struct vx_info *vxi, struct nx_info *nxi,
75 void __user *data, int compat)
79 case VCMD_get_version:
80 return vc_get_version(id);
82 return vc_get_vci(id);
85 return vc_task_xid(id, data);
87 return vc_vx_info(vxi, data);
90 return vc_task_nid(id, data);
92 return vc_nx_info(nxi, data);
94 case VCMD_set_space_v0:
95 /* this is version 1 */
97 return vc_set_space(vxi, data);
99 case VCMD_get_space_mask:
100 return vc_get_space_mask(vxi, data);
102 #ifdef CONFIG_IA32_EMULATION
103 case VCMD_get_rlimit:
104 return __COMPAT(vc_get_rlimit, vxi, data, compat);
105 case VCMD_set_rlimit:
106 return __COMPAT(vc_set_rlimit, vxi, data, compat);
108 case VCMD_get_rlimit:
109 return vc_get_rlimit(vxi, data);
110 case VCMD_set_rlimit:
111 return vc_set_rlimit(vxi, data);
113 case VCMD_get_rlimit_mask:
114 return vc_get_rlimit_mask(id, data);
115 case VCMD_reset_minmax:
116 return vc_reset_minmax(vxi, data);
118 case VCMD_get_vhi_name:
119 return vc_get_vhi_name(vxi, data);
120 case VCMD_set_vhi_name:
121 return vc_set_vhi_name(vxi, data);
124 return vc_ctx_stat(vxi, data);
126 return vc_virt_stat(vxi, data);
128 return vc_sock_stat(vxi, data);
129 case VCMD_rlimit_stat:
130 return vc_rlimit_stat(vxi, data);
132 case VCMD_set_cflags:
133 return vc_set_cflags(vxi, data);
134 case VCMD_get_cflags:
135 return vc_get_cflags(vxi, data);
137 case VCMD_set_ccaps_v0:
138 return vc_set_ccaps_v0(vxi, data);
139 /* this is version 1 */
141 return vc_set_ccaps(vxi, data);
142 case VCMD_get_ccaps_v0:
143 return vc_get_ccaps_v0(vxi, data);
144 /* this is version 1 */
146 return vc_get_ccaps(vxi, data);
148 return vc_set_bcaps(vxi, data);
150 return vc_get_bcaps(vxi, data);
152 case VCMD_set_nflags:
153 return vc_set_nflags(nxi, data);
154 case VCMD_get_nflags:
155 return vc_get_nflags(nxi, data);
158 return vc_set_ncaps(nxi, data);
160 return vc_get_ncaps(nxi, data);
162 #ifdef CONFIG_VSERVER_LEGACY
163 case VCMD_set_sched_v2:
164 return vc_set_sched_v2(vxi, data);
166 case VCMD_set_sched_v3:
167 return vc_set_sched_v3(vxi, data);
168 case VCMD_set_sched_v4:
169 return vc_set_sched_v4(vxi, data);
170 /* this is version 5 */
172 return vc_set_sched(vxi, data);
174 return vc_get_sched(vxi, data);
175 case VCMD_sched_info:
176 return vc_sched_info(vxi, data);
178 case VCMD_add_dlimit:
179 return __COMPAT(vc_add_dlimit, id, data, compat);
180 case VCMD_rem_dlimit:
181 return __COMPAT(vc_rem_dlimit, id, data, compat);
182 case VCMD_set_dlimit:
183 return __COMPAT(vc_set_dlimit, id, data, compat);
184 case VCMD_get_dlimit:
185 return __COMPAT(vc_get_dlimit, id, data, compat);
188 return vc_ctx_kill(vxi, data);
191 return vc_wait_exit(vxi, data);
193 #ifdef CONFIG_VSERVER_LEGACY
194 case VCMD_create_context:
195 return vc_ctx_create(id, NULL);
199 return __COMPAT(vc_get_iattr, id, data, compat);
201 return __COMPAT(vc_set_iattr, id, data, compat);
203 case VCMD_fget_iattr:
204 return vc_fget_iattr(id, data);
205 case VCMD_fset_iattr:
206 return vc_fset_iattr(id, data);
208 case VCMD_enter_space_v0:
209 return vc_enter_space(vxi, NULL);
210 /* this is version 1 */
211 case VCMD_enter_space:
212 return vc_enter_space(vxi, data);
214 case VCMD_ctx_create_v0:
215 return vc_ctx_create(id, NULL);
216 case VCMD_ctx_create:
217 return vc_ctx_create(id, data);
218 case VCMD_ctx_migrate_v0:
219 return vc_ctx_migrate(vxi, NULL);
220 case VCMD_ctx_migrate:
221 return vc_ctx_migrate(vxi, data);
223 case VCMD_net_create_v0:
224 return vc_net_create(id, NULL);
225 case VCMD_net_create:
226 return vc_net_create(id, data);
227 case VCMD_net_migrate:
228 return vc_net_migrate(nxi, data);
230 return vc_net_add(nxi, data);
231 case VCMD_net_remove:
232 return vc_net_remove(nxi, data);
234 #ifdef CONFIG_VSERVER_HISTORY
235 case VCMD_dump_history:
236 return vc_dump_history(id);
237 case VCMD_read_history:
238 return __COMPAT(vc_read_history, id, data, compat);
240 #ifdef CONFIG_VSERVER_MONITOR
241 case VCMD_read_monitor:
242 return __COMPAT(vc_read_monitor, id, data, compat);
244 #ifdef CONFIG_VSERVER_LEGACY
245 case VCMD_new_s_context:
246 return vc_new_s_context(id, data);
248 #ifdef CONFIG_VSERVER_LEGACYNET
249 case VCMD_set_ipv4root:
250 return vc_set_ipv4root(id, data);
253 vxwprintk(1, "unimplemented VCMD_%02d_%d[%d]",
254 VC_CATEGORY(cmd), VC_COMMAND(cmd), VC_VERSION(cmd));
260 #define __VCMD(vcmd, _perm, _args, _flags) \
261 case VCMD_ ## vcmd: perm = _perm; \
262 args = _args; flags = _flags; break
265 #define VCA_NONE 0x00
269 #define VCF_NONE 0x00
270 #define VCF_INFO 0x01
271 #define VCF_ADMIN 0x02
272 #define VCF_ARES 0x06 /* includes admin */
273 #define VCF_SETUP 0x08
275 #define VCF_ZIDOK 0x10 /* zero id okay */
279 long do_vserver(uint32_t cmd, uint32_t id, void __user *data, int compat)
282 int permit = -1, state = 0;
283 int perm = -1, args = 0, flags = 0;
284 struct vx_info *vxi = NULL;
285 struct nx_info *nxi = NULL;
288 /* unpriviledged commands */
289 __VCMD(get_version, 0, VCA_NONE, 0);
290 __VCMD(get_vci, 0, VCA_NONE, 0);
291 __VCMD(get_rlimit_mask, 0, VCA_NONE, 0);
292 __VCMD(get_space_mask, 0, VCA_NONE, 0);
295 __VCMD(task_xid, 2, VCA_NONE, 0);
296 __VCMD(reset_minmax, 2, VCA_VXI, 0);
297 __VCMD(vx_info, 3, VCA_VXI, VCF_INFO);
298 __VCMD(get_bcaps, 3, VCA_VXI, VCF_INFO);
299 __VCMD(get_ccaps_v0, 3, VCA_VXI, VCF_INFO);
300 __VCMD(get_ccaps, 3, VCA_VXI, VCF_INFO);
301 __VCMD(get_cflags, 3, VCA_VXI, VCF_INFO);
302 __VCMD(get_vhi_name, 3, VCA_VXI, VCF_INFO);
303 __VCMD(get_rlimit, 3, VCA_VXI, VCF_INFO);
305 __VCMD(ctx_stat, 3, VCA_VXI, VCF_INFO);
306 __VCMD(virt_stat, 3, VCA_VXI, VCF_INFO);
307 __VCMD(sock_stat, 3, VCA_VXI, VCF_INFO);
308 __VCMD(rlimit_stat, 3, VCA_VXI, VCF_INFO);
310 __VCMD(task_nid, 2, VCA_NONE, 0);
311 __VCMD(nx_info, 3, VCA_NXI, VCF_INFO);
312 __VCMD(get_ncaps, 3, VCA_NXI, VCF_INFO);
313 __VCMD(get_nflags, 3, VCA_NXI, VCF_INFO);
315 __VCMD(get_iattr, 2, VCA_NONE, 0);
316 __VCMD(fget_iattr, 2, VCA_NONE, 0);
317 __VCMD(get_dlimit, 3, VCA_NONE, VCF_INFO);
318 __VCMD(get_sched, 3, VCA_VXI, VCF_INFO);
319 __VCMD(sched_info, 3, VCA_VXI, VCF_INFO|VCF_ZIDOK);
321 /* lower admin commands */
322 __VCMD(wait_exit, 4, VCA_VXI, VCF_INFO);
323 __VCMD(ctx_create_v0, 5, VCA_NONE, 0);
324 __VCMD(ctx_create, 5, VCA_NONE, 0);
325 __VCMD(ctx_migrate_v0, 5, VCA_VXI, VCF_ADMIN);
326 __VCMD(ctx_migrate, 5, VCA_VXI, VCF_ADMIN);
327 __VCMD(enter_space_v0, 5, VCA_VXI, VCF_ADMIN);
328 __VCMD(enter_space, 5, VCA_VXI, VCF_ADMIN);
330 __VCMD(net_create_v0, 5, VCA_NONE, 0);
331 __VCMD(net_create, 5, VCA_NONE, 0);
332 __VCMD(net_migrate, 5, VCA_NXI, VCF_ADMIN);
334 /* higher admin commands */
335 __VCMD(ctx_kill, 6, VCA_VXI, VCF_ARES);
336 __VCMD(set_space_v0, 7, VCA_VXI, VCF_ARES|VCF_SETUP);
337 __VCMD(set_space, 7, VCA_VXI, VCF_ARES|VCF_SETUP);
339 __VCMD(set_ccaps_v0, 7, VCA_VXI, VCF_ARES|VCF_SETUP);
340 __VCMD(set_ccaps, 7, VCA_VXI, VCF_ARES|VCF_SETUP);
341 __VCMD(set_bcaps, 7, VCA_VXI, VCF_ARES|VCF_SETUP);
342 __VCMD(set_cflags, 7, VCA_VXI, VCF_ARES|VCF_SETUP);
344 __VCMD(set_vhi_name, 7, VCA_VXI, VCF_ARES|VCF_SETUP);
345 __VCMD(set_rlimit, 7, VCA_VXI, VCF_ARES|VCF_SETUP);
346 __VCMD(set_sched, 7, VCA_VXI, VCF_ARES|VCF_SETUP);
347 __VCMD(set_sched_v2, 7, VCA_VXI, VCF_ARES|VCF_SETUP);
348 __VCMD(set_sched_v3, 7, VCA_VXI, VCF_ARES|VCF_SETUP);
349 __VCMD(set_sched_v4, 7, VCA_VXI, VCF_ARES|VCF_SETUP);
351 __VCMD(set_ncaps, 7, VCA_NXI, VCF_ARES|VCF_SETUP);
352 __VCMD(set_nflags, 7, VCA_NXI, VCF_ARES|VCF_SETUP);
353 __VCMD(net_add, 8, VCA_NXI, VCF_ARES|VCF_SETUP);
354 __VCMD(net_remove, 8, VCA_NXI, VCF_ARES|VCF_SETUP);
356 __VCMD(set_iattr, 7, VCA_NONE, 0);
357 __VCMD(fset_iattr, 7, VCA_NONE, 0);
358 __VCMD(set_dlimit, 7, VCA_NONE, VCF_ARES);
359 __VCMD(add_dlimit, 8, VCA_NONE, VCF_ARES);
360 __VCMD(rem_dlimit, 8, VCA_NONE, VCF_ARES);
362 /* debug level admin commands */
363 #ifdef CONFIG_VSERVER_HISTORY
364 __VCMD(dump_history, 9, VCA_NONE, 0);
365 __VCMD(read_history, 9, VCA_NONE, 0);
367 #ifdef CONFIG_VSERVER_MONITOR
368 __VCMD(read_monitor, 9, VCA_NONE, 0);
371 /* legacy commands */
372 #ifdef CONFIG_VSERVER_LEGACY
373 __VCMD(new_s_context, 1, VCA_NONE, 0);
374 __VCMD(create_context, 5, VCA_NONE, 0);
376 #ifdef CONFIG_VSERVER_LEGACYNET
377 __VCMD(set_ipv4root, 5, VCA_NONE, 0);
383 vxdprintk(VXD_CBIT(switch, 0),
384 "vc: VCMD_%02d_%d[%d], %d,%p [%d,%d,%x,%x]",
385 VC_CATEGORY(cmd), VC_COMMAND(cmd),
386 VC_VERSION(cmd), id, data, compat,
394 #ifdef CONFIG_VSERVER_LEGACY
395 if (!capable(CAP_CONTEXT) &&
396 /* dirty hack for capremove */
397 !(cmd==VCMD_new_s_context && id==-2))
400 if (!capable(CAP_CONTEXT))
405 /* moved here from the individual commands */
407 if ((perm > 1) && !capable(CAP_SYS_ADMIN))
411 /* vcmd involves resource management */
413 if ((flags & VCF_ARES) && !capable(CAP_SYS_RESOURCE))
417 /* various legacy exceptions */
419 #ifdef CONFIG_VSERVER_LEGACY
420 case VCMD_set_cflags:
421 case VCMD_set_ccaps_v0:
423 if (vx_check(0, VS_WATCH))
427 case VCMD_ctx_create_v0:
429 /* will go away when spectator is a cap */
430 case VCMD_ctx_migrate_v0:
431 case VCMD_ctx_migrate:
439 /* will go away when spectator is a cap */
440 case VCMD_net_migrate:
448 /* legacy special casing */
449 case VCMD_set_space_v0:
454 /* vcmds are fine by default */
457 /* admin type vcmds require admin ... */
458 if (flags & VCF_ADMIN)
459 permit = vx_check(0, VS_ADMIN) ? 1 : 0;
461 /* ... but setup type vcmds override that */
462 if (!permit && (flags & VCF_SETUP))
463 permit = vx_flags(VXF_STATE_SETUP, 0) ? 2 : 0;
471 if (!id && (flags & VCF_ZIDOK))
475 if (args & VCA_VXI) {
476 vxi = lookup_vx_info(id);
480 if ((flags & VCF_ADMIN) &&
481 /* special case kill for shutdown */
482 (cmd != VCMD_ctx_kill) &&
483 /* can context be administrated? */
484 !vx_info_flags(vxi, VXF_STATE_ADMIN, 0)) {
490 if (args & VCA_NXI) {
491 nxi = lookup_nx_info(id);
495 if ((flags & VCF_ADMIN) &&
496 /* can context be administrated? */
497 !nx_info_flags(nxi, NXF_STATE_ADMIN, 0)) {
504 ret = do_vcmd(cmd, id, vxi, nxi, data, compat);
507 if ((args & VCA_NXI) && nxi)
510 if ((args & VCA_VXI) && vxi)
513 vxdprintk(VXD_CBIT(switch, 1),
514 "vc: VCMD_%02d_%d[%d] = %08lx(%ld) [%d,%d]",
515 VC_CATEGORY(cmd), VC_COMMAND(cmd),
516 VC_VERSION(cmd), ret, ret, state, permit);
521 sys_vserver(uint32_t cmd, uint32_t id, void __user *data)
523 return do_vserver(cmd, id, data, 0);
529 sys32_vserver(uint32_t cmd, uint32_t id, void __user *data)
531 return do_vserver(cmd, id, data, 1);
534 #endif /* CONFIG_COMPAT */