patch-2.6.6-vs1.9.1
[linux-2.6.git] / kernel / vserver / legacy.c
1 /*
2  *  linux/kernel/vserver/legacy.c
3  *
4  *  Virtual Server: Legacy Funtions
5  *
6  *  Copyright (C) 2001-2003  Jacques Gelinas
7  *  Copyright (C) 2003-2004  Herbert Pƶtzl
8  *
9  *  V0.01  broken out from vcontext.c V0.05
10  *
11  */
12
13 #include <linux/config.h>
14 #include <linux/vserver/legacy.h>
15 #include <linux/vserver/context.h>
16 #include <linux/vserver/namespace.h>
17 #include <linux/vserver.h>
18 #include <linux/sched.h>
19 #include <linux/namespace.h>
20
21 #include <asm/errno.h>
22 #include <asm/uaccess.h>
23
24
25
26 static int vx_set_initpid(struct vx_info *vxi, int pid)
27 {
28         if (vxi->vx_initpid)
29                 return -EPERM;
30
31         vxi->vx_initpid = pid;
32         return 0;
33 }
34
35 int vc_new_s_context(uint32_t ctx, void __user *data)
36 {
37         int ret = -ENOMEM;
38         struct vcmd_new_s_context_v1 vc_data;
39         struct vx_info *new_vxi;
40
41         if (copy_from_user(&vc_data, data, sizeof(vc_data)))
42                 return -EFAULT;
43
44         /* legacy hack, will be removed soon */
45         if (ctx == -2) {
46                 /* assign flags and initpid */
47                 if (!current->vx_info)
48                         return -EINVAL;
49                 ret = 0;
50                 if (vc_data.flags & VX_INFO_INIT)
51                         ret = vx_set_initpid(current->vx_info, current->tgid);
52                 if (ret == 0) {
53                         /* We keep the same vx_id, but lower the capabilities */
54                         current->vx_info->vx_bcaps &= (~vc_data.remove_cap);
55                         // current->cap_bset &= (~vc_data.remove_cap);
56                         ret = vx_current_xid();
57                         current->vx_info->vx_flags |= vc_data.flags;
58                 }
59                 return ret;
60         }
61         
62         if (!vx_check(0, VX_ADMIN) ||
63                 !capable(CAP_SYS_ADMIN) || vx_flags(VX_INFO_LOCK, 0))
64                 return -EPERM;
65
66         /* ugly hack for Spectator */
67         if (ctx == 1) {
68                 current->xid = 1;
69                 return 0;
70         }
71
72         if (((ctx > MAX_S_CONTEXT) && (ctx != VX_DYNAMIC_ID)) ||
73                 (ctx == 0))
74                 return -EINVAL;
75                 
76         if ((ctx == VX_DYNAMIC_ID) || (ctx < MIN_D_CONTEXT))
77                 new_vxi = locate_or_create_vx_info(ctx);
78         else
79                 new_vxi = locate_vx_info(ctx);
80
81         if (!new_vxi)
82                 return -EINVAL;
83         new_vxi->vx_flags &= ~(VXF_STATE_SETUP|VXF_STATE_INIT);
84         
85         ret = vx_migrate_task(current, new_vxi);
86         if (ret == 0) {
87                 current->vx_info->vx_bcaps &= (~vc_data.remove_cap);
88                 // current->cap_bset &= (~vc_data.remove_cap);
89                 new_vxi->vx_flags |= vc_data.flags;
90                 if (vc_data.flags & VX_INFO_INIT)
91                         vx_set_initpid(new_vxi, current->tgid);
92                 if (vc_data.flags & VX_INFO_NAMESPACE)
93                         vx_set_namespace(new_vxi,
94                                 current->namespace, current->fs);
95                 if (vc_data.flags & VX_INFO_NPROC)
96                         new_vxi->limit.rlim[RLIMIT_NPROC] =
97                                 current->rlim[RLIMIT_NPROC].rlim_max;
98                 ret = new_vxi->vx_id;
99         }
100         put_vx_info(new_vxi);
101         return ret;
102 }
103
104
105 extern struct nx_info *create_nx_info(void);
106
107 /*  set ipv4 root (syscall) */
108
109 int vc_set_ipv4root(uint32_t nbip, void __user *data)
110 {
111         int i, err = -EPERM;
112         struct vcmd_set_ipv4root_v3 vc_data;
113         struct nx_info *new_nxi, *nxi = current->nx_info;
114
115         if (nbip < 0 || nbip > NB_IPV4ROOT)
116                 return -EINVAL;
117         if (copy_from_user (&vc_data, data, sizeof(vc_data)))
118                 return -EFAULT;
119
120         if (!nxi || nxi->ipv4[0] == 0 || capable(CAP_NET_ADMIN))
121                 // We are allowed to change everything
122                 err = 0;
123         else if (nxi) {
124                 int found = 0;
125                 
126                 // We are allowed to select a subset of the currently
127                 // installed IP numbers. No new one allowed
128                 // We can't change the broadcast address though
129                 for (i=0; i<nbip; i++) {
130                         int j;
131                         __u32 nxip = vc_data.nx_mask_pair[i].ip;
132                         for (j=0; j<nxi->nbipv4; j++) {
133                                 if (nxip == nxi->ipv4[j]) {
134                                         found++;
135                                         break;
136                                 }
137                         }
138                 }
139                 if ((found == nbip) &&
140                         (vc_data.broadcast == nxi->v4_bcast))
141                         err = 0;
142         }
143         if (err)
144                 return err;
145
146         new_nxi = create_nx_info();
147         if (!new_nxi)
148                 return -EINVAL;
149
150         new_nxi->nbipv4 = nbip;
151         for (i=0; i<nbip; i++) {
152                 new_nxi->ipv4[i] = vc_data.nx_mask_pair[i].ip;
153                 new_nxi->mask[i] = vc_data.nx_mask_pair[i].mask;
154         }
155         new_nxi->v4_bcast = vc_data.broadcast;
156         // current->nx_info = new_nxi;
157         if (nxi) {
158                 printk("!!! switching nx_info %p->%p\n", nxi, new_nxi);
159                 clr_nx_info(&current->nx_info);
160         }
161         nx_migrate_task(current, new_nxi);
162         // set_nx_info(&current->nx_info, new_nxi);
163         // current->nid = new_nxi->nx_id;
164         put_nx_info(new_nxi);
165         return 0;
166 }
167
168