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