patch-2_6_7-vs1_9_1_12
[linux-2.6.git] / kernel / vserver / namespace.c
1 /*
2  *  linux/kernel/vserver/namespace.c
3  *
4  *  Virtual Server: Context Namespace Support
5  *
6  *  Copyright (C) 2003-2004  Herbert Pƶtzl
7  *
8  *  V0.01  broken out from context.c 0.07
9  *  V0.02  added task locking for namespace
10  *
11  */
12
13 #include <linux/config.h>
14 #include <linux/utsname.h>
15 #include <linux/vserver/namespace.h>
16 #include <linux/vs_base.h>
17 #include <linux/vs_context.h>
18 #include <linux/namespace.h>
19 #include <linux/dcache.h>
20
21 #include <asm/errno.h>
22 #include <asm/uaccess.h>
23
24
25 /* virtual host info names */
26
27 static char * vx_vhi_name(struct vx_info *vxi, int id)
28 {
29         switch (id) {
30                 case VHIN_CONTEXT:
31                         return vxi->vx_name;
32                 case VHIN_SYSNAME:
33                         return vxi->cvirt.utsname.sysname;
34                 case VHIN_NODENAME:
35                         return vxi->cvirt.utsname.nodename;
36                 case VHIN_RELEASE:
37                         return vxi->cvirt.utsname.release;
38                 case VHIN_VERSION:
39                         return vxi->cvirt.utsname.version;
40                 case VHIN_MACHINE:
41                         return vxi->cvirt.utsname.machine;
42                 case VHIN_DOMAINNAME:
43                         return vxi->cvirt.utsname.domainname;
44                 default:
45                         return NULL;
46         }
47         return NULL;
48 }
49
50 int vc_set_vhi_name(uint32_t id, void __user *data)
51 {
52         struct vx_info *vxi;
53         struct vcmd_vx_vhi_name_v0 vc_data;
54         char *name;
55
56         if (!capable(CAP_SYS_ADMIN))
57                 return -EPERM;
58         if (copy_from_user (&vc_data, data, sizeof(vc_data)))
59                 return -EFAULT;
60         
61         vxi = locate_vx_info(id);
62         if (!vxi)
63                 return -ESRCH;
64         
65         name = vx_vhi_name(vxi, vc_data.field);
66         if (name)
67                 memcpy(name, vc_data.name, 65);
68         put_vx_info(vxi);
69         return (name ? 0 : -EFAULT);
70 }
71
72 int vc_get_vhi_name(uint32_t id, void __user *data)
73 {
74         struct vx_info *vxi;
75         struct vcmd_vx_vhi_name_v0 vc_data;
76         char *name;
77
78         if (copy_from_user (&vc_data, data, sizeof(vc_data)))
79                 return -EFAULT;
80
81         vxi = locate_vx_info(id);
82         if (!vxi)
83                 return -ESRCH;
84
85         name = vx_vhi_name(vxi, vc_data.field);
86         if (!name)
87                 goto out_put;
88                         
89         memcpy(vc_data.name, name, 65);
90         if (copy_to_user (data, &vc_data, sizeof(vc_data)))
91                 return -EFAULT;
92 out_put:
93         put_vx_info(vxi);
94         return (name ? 0 : -EFAULT);
95 }
96
97 /* namespace functions */
98
99 #include <linux/namespace.h>
100
101 int vx_set_namespace(struct vx_info *vxi, struct namespace *ns, struct fs_struct *fs)
102 {
103         struct fs_struct *fs_copy;
104
105         if (vxi->vx_namespace)
106                 return -EPERM;
107         if (!ns || !fs)
108                 return -EINVAL;
109
110         fs_copy = copy_fs_struct(fs);
111         if (!fs_copy)
112                 return -ENOMEM;
113
114         get_namespace(ns);
115         vxi->vx_namespace = ns;
116         vxi->vx_fs = fs_copy;
117         return 0;
118 }
119
120 int vc_enter_namespace(uint32_t id, void *data)
121 {
122         struct vx_info *vxi;
123         struct fs_struct *old_fs, *fs;
124         struct namespace *old_ns;
125         int ret = 0;
126
127         if (!vx_check(0, VX_ADMIN))
128                 return -ENOSYS;
129
130         vxi = locate_vx_info(id);
131         if (!vxi)
132                 return -ESRCH;
133
134         ret = -EINVAL;
135         if (!vxi->vx_namespace)
136                 goto out_put;
137
138         ret = -ENOMEM;
139         fs = copy_fs_struct(vxi->vx_fs);
140         if (!fs)
141                 goto out_put;
142
143         ret = 0;
144         task_lock(current);
145         old_ns = current->namespace;
146         old_fs = current->fs;
147         get_namespace(vxi->vx_namespace);
148         current->namespace = vxi->vx_namespace; 
149         current->fs = fs;
150         task_unlock(current);
151
152         put_namespace(old_ns);
153         put_fs_struct(old_fs);
154 out_put:
155         put_vx_info(vxi);
156         return ret;
157 }
158
159 int vc_cleanup_namespace(uint32_t id, void *data)
160 {
161         down_write(&current->namespace->sem);
162         spin_lock(&vfsmount_lock);
163         umount_unused(current->namespace->root, current->fs);
164         spin_unlock(&vfsmount_lock);
165         up_write(&current->namespace->sem);
166         return 0;
167 }
168
169 int vc_set_namespace(uint32_t id, void __user *data)
170 {
171         struct fs_struct *fs;
172         struct namespace *ns;
173         struct vx_info *vxi;
174         int ret;
175
176         if (vx_check(0, VX_ADMIN|VX_WATCH))
177                 return -ENOSYS;
178
179         task_lock(current);
180         vxi = get_vx_info(current->vx_info);
181         fs = current->fs;
182         atomic_inc(&fs->count);
183         ns = current->namespace;
184         get_namespace(current->namespace);
185         task_unlock(current);
186
187         ret = vx_set_namespace(vxi, ns, fs);
188
189         put_namespace(ns);
190         put_fs_struct(fs);
191         put_vx_info(vxi);
192         return ret;
193 }
194