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