linux 2.6.16.38 w/ vs2.0.3-rc1
[linux-2.6.git] / kernel / vserver / switch.c
1 /*
2  *  linux/kernel/vserver/switch.c
3  *
4  *  Virtual Server: Syscall Switch
5  *
6  *  Copyright (C) 2003-2005  Herbert Pƶtzl
7  *
8  *  V0.01  syscall switch
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  *
15  */
16
17 #include <linux/linkage.h>
18 #include <linux/sched.h>
19 #include <linux/compat.h>
20 #include <asm/errno.h>
21
22 #include <linux/vs_base.h>
23 #include <linux/vserver/network.h>
24 #include <linux/vserver/switch.h>
25 #include <linux/vserver/debug.h>
26
27
28 static inline
29 int vc_get_version(uint32_t id)
30 {
31 #ifdef  CONFIG_VSERVER_LEGACY_VERSION
32         if (id == 63)
33                 return VCI_LEGACY_VERSION;
34 #endif
35         return VCI_VERSION;
36 }
37
38 #include <linux/vserver/context_cmd.h>
39 #include <linux/vserver/cvirt_cmd.h>
40 #include <linux/vserver/limit_cmd.h>
41 #include <linux/vserver/network_cmd.h>
42 #include <linux/vserver/sched_cmd.h>
43 #include <linux/vserver/debug_cmd.h>
44 #include <linux/vserver/inode_cmd.h>
45 #include <linux/vserver/dlimit_cmd.h>
46 #include <linux/vserver/signal_cmd.h>
47 #include <linux/vserver/namespace_cmd.h>
48
49 #include <linux/vserver/legacy.h>
50 #include <linux/vserver/inode.h>
51 #include <linux/vserver/dlimit.h>
52
53
54 #ifdef  CONFIG_COMPAT
55 #define __COMPAT(name, id, data, compat)        \
56         (compat) ? name ## _x32 (id, data) : name (id, data)
57 #else
58 #define __COMPAT(name, id, data, compat)        \
59         name (id, data)
60 #endif
61
62
63 static inline
64 long do_vserver(uint32_t cmd, uint32_t id, void __user *data, int compat)
65 {
66         vxdprintk(VXD_CBIT(switch, 0),
67                 "vc: VCMD_%02d_%d[%d], %d,%p,%d",
68                 VC_CATEGORY(cmd), VC_COMMAND(cmd),
69                 VC_VERSION(cmd), id, data, compat);
70
71 #ifdef  CONFIG_VSERVER_LEGACY
72         if (!capable(CAP_CONTEXT) &&
73                 /* dirty hack for capremove */
74                 !(cmd==VCMD_new_s_context && id==-2))
75                 return -EPERM;
76 #else
77         if (!capable(CAP_CONTEXT))
78                 return -EPERM;
79 #endif
80
81         switch (cmd) {
82         case VCMD_get_version:
83                 return vc_get_version(id);
84
85         case VCMD_dump_history:
86 #ifdef  CONFIG_VSERVER_HISTORY
87                 return vc_dump_history(id);
88 #else
89                 return -ENOSYS;
90 #endif
91
92 #ifdef  CONFIG_VSERVER_LEGACY
93         case VCMD_new_s_context:
94                 return vc_new_s_context(id, data);
95 #endif
96 #ifdef  CONFIG_VSERVER_LEGACYNET
97         case VCMD_set_ipv4root:
98                 return vc_set_ipv4root(id, data);
99 #endif
100
101         case VCMD_task_xid:
102                 return vc_task_xid(id, data);
103         case VCMD_vx_info:
104                 return vc_vx_info(id, data);
105
106         case VCMD_task_nid:
107                 return vc_task_nid(id, data);
108         case VCMD_nx_info:
109                 return vc_nx_info(id, data);
110
111         case VCMD_set_namespace_v0:
112                 return vc_set_namespace(-1, data);
113         case VCMD_set_namespace:
114                 return vc_set_namespace(id, data);
115         }
116
117         /* those are allowed while in setup too */
118         if (!vx_check(0, VX_ADMIN|VX_WATCH) &&
119                 !vx_flags(VXF_STATE_SETUP,0))
120                 return -EPERM;
121
122 #ifdef  CONFIG_VSERVER_LEGACY
123         switch (cmd) {
124         case VCMD_set_cflags:
125         case VCMD_set_ccaps:
126                 if (vx_check(0, VX_WATCH))
127                         return 0;
128         }
129 #endif
130
131         switch (cmd) {
132 #ifdef  CONFIG_IA32_EMULATION
133         case VCMD_get_rlimit:
134                 return __COMPAT(vc_get_rlimit, id, data, compat);
135         case VCMD_set_rlimit:
136                 return __COMPAT(vc_set_rlimit, id, data, compat);
137 #else
138         case VCMD_get_rlimit:
139                 return vc_get_rlimit(id, data);
140         case VCMD_set_rlimit:
141                 return vc_set_rlimit(id, data);
142 #endif
143         case VCMD_get_rlimit_mask:
144                 return vc_get_rlimit_mask(id, data);
145
146         case VCMD_get_vhi_name:
147                 return vc_get_vhi_name(id, data);
148         case VCMD_set_vhi_name:
149                 return vc_set_vhi_name(id, data);
150
151         case VCMD_set_cflags:
152                 return vc_set_cflags(id, data);
153         case VCMD_get_cflags:
154                 return vc_get_cflags(id, data);
155
156         case VCMD_set_ccaps:
157                 return vc_set_ccaps(id, data);
158         case VCMD_get_ccaps:
159                 return vc_get_ccaps(id, data);
160
161         case VCMD_set_nflags:
162                 return vc_set_nflags(id, data);
163         case VCMD_get_nflags:
164                 return vc_get_nflags(id, data);
165
166         case VCMD_set_ncaps:
167                 return vc_set_ncaps(id, data);
168         case VCMD_get_ncaps:
169                 return vc_get_ncaps(id, data);
170
171         case VCMD_set_sched_v2:
172                 return vc_set_sched_v2(id, data);
173         /* this is version 3 */
174         case VCMD_set_sched:
175                 return vc_set_sched(id, data);
176
177         case VCMD_add_dlimit:
178                 return __COMPAT(vc_add_dlimit, id, data, compat);
179         case VCMD_rem_dlimit:
180                 return __COMPAT(vc_rem_dlimit, id, data, compat);
181         case VCMD_set_dlimit:
182                 return __COMPAT(vc_set_dlimit, id, data, compat);
183         case VCMD_get_dlimit:
184                 return __COMPAT(vc_get_dlimit, id, data, compat);
185         }
186
187         /* below here only with VX_ADMIN */
188         if (!vx_check(0, VX_ADMIN|VX_WATCH))
189                 return -EPERM;
190
191         switch (cmd) {
192         case VCMD_ctx_kill:
193                 return vc_ctx_kill(id, data);
194
195         case VCMD_wait_exit:
196                 return vc_wait_exit(id, data);
197
198         case VCMD_create_context:
199 #ifdef  CONFIG_VSERVER_LEGACY
200                 return vc_ctx_create(id, NULL);
201 #else
202                 return -ENOSYS;
203 #endif
204
205         case VCMD_get_iattr:
206                 return __COMPAT(vc_get_iattr, id, data, compat);
207         case VCMD_set_iattr:
208                 return __COMPAT(vc_set_iattr, id, data, compat);
209
210         case VCMD_enter_namespace:
211                 return vc_enter_namespace(id, data);
212
213         case VCMD_ctx_create_v0:
214 #ifdef  CONFIG_VSERVER_LEGACY
215                 if (id == 1) {
216                         current->xid = 1;
217                         return 1;
218                 }
219 #endif
220                 return vc_ctx_create(id, NULL);
221         case VCMD_ctx_create:
222                 return vc_ctx_create(id, data);
223         case VCMD_ctx_migrate_v0:
224                 return vc_ctx_migrate(id, NULL);
225         case VCMD_ctx_migrate:
226                 return vc_ctx_migrate(id, data);
227
228         case VCMD_net_create_v0:
229                 return vc_net_create(id, NULL);
230         case VCMD_net_create:
231                 return vc_net_create(id, data);
232         case VCMD_net_migrate:
233                 return vc_net_migrate(id, data);
234         case VCMD_net_add:
235                 return vc_net_add(id, data);
236         case VCMD_net_remove:
237                 return vc_net_remove(id, data);
238
239         }
240         return -ENOSYS;
241 }
242
243 asmlinkage long
244 sys_vserver(uint32_t cmd, uint32_t id, void __user *data)
245 {
246         long ret = do_vserver(cmd, id, data, 0);
247
248         vxdprintk(VXD_CBIT(switch, 1),
249                 "vc: VCMD_%02d_%d[%d] = %08lx(%ld)",
250                 VC_CATEGORY(cmd), VC_COMMAND(cmd),
251                 VC_VERSION(cmd), ret, ret);
252         return ret;
253 }
254
255 #ifdef  CONFIG_COMPAT
256
257 asmlinkage long
258 sys32_vserver(uint32_t cmd, uint32_t id, void __user *data)
259 {
260         long ret = do_vserver(cmd, id, data, 1);
261
262         vxdprintk(VXD_CBIT(switch, 1),
263                 "vc: VCMD_%02d_%d[%d] = %08lx(%ld)",
264                 VC_CATEGORY(cmd), VC_COMMAND(cmd),
265                 VC_VERSION(cmd), ret, ret);
266         return ret;
267 }
268
269 #endif  /* CONFIG_COMPAT */