Merge to Fedora kernel-2.6.18-1.2255_FC5-vs2.0.2.2-rc9 patched with stable patch...
[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-2005  Herbert Pƶtzl
8  *
9  *  V0.01  broken out from vcontext.c V0.05
10  *
11  */
12
13 #include <linux/sched.h>
14 #include <linux/vs_context.h>
15 #include <linux/vs_network.h>
16 #include <linux/vserver/legacy.h>
17 #include <linux/vserver/namespace.h>
18 #include <linux/namespace.h>
19
20 #include <asm/errno.h>
21 #include <asm/uaccess.h>
22
23
24 extern int vx_set_init(struct vx_info *, struct task_struct *);
25
26 static int vx_set_initpid(struct vx_info *vxi, int pid)
27 {
28         struct task_struct *init;
29
30         init = find_task_by_real_pid(pid);
31         if (!init)
32                 return -ESRCH;
33         return vx_set_init(vxi, init);
34 }
35
36 int vc_new_s_context(uint32_t ctx, void __user *data)
37 {
38         int ret = -ENOMEM;
39         struct vcmd_new_s_context_v1 vc_data;
40         struct vx_info *new_vxi;
41
42         if (copy_from_user(&vc_data, data, sizeof(vc_data)))
43                 return -EFAULT;
44
45         /* legacy hack, will be removed soon */
46         if (ctx == -2) {
47                 /* assign flags and initpid */
48                 if (!current->vx_info)
49                         return -EINVAL;
50                 ret = 0;
51                 if (vc_data.flags & VX_INFO_INIT)
52                         ret = vx_set_initpid(current->vx_info, current->tgid);
53                 if (ret == 0) {
54                         /* We keep the same vx_id, but lower the capabilities */
55                         current->vx_info->vx_bcaps &= (~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) || !capable(CAP_SYS_ADMIN))
63                 return -EPERM;
64
65         /* ugly hack for Spectator */
66         if (ctx == 1) {
67                 current->xid = 1;
68                 return 0;
69         }
70
71         if (((ctx > MAX_S_CONTEXT) && (ctx != VX_DYNAMIC_ID)) ||
72                 (ctx == 0))
73                 return -EINVAL;
74
75         if ((ctx == VX_DYNAMIC_ID) || (ctx < MIN_D_CONTEXT))
76                 new_vxi = lookup_or_create_vx_info(ctx);
77         else
78                 new_vxi = lookup_vx_info(ctx);
79
80         if (!new_vxi)
81                 return -EINVAL;
82
83         ret = -EPERM;
84         if (!vx_info_flags(new_vxi, VXF_STATE_SETUP, 0) &&
85                 vx_info_flags(new_vxi, VX_INFO_PRIVATE, 0))
86                 goto out_put;
87
88         new_vxi->vx_flags &= ~VXF_STATE_SETUP;
89
90         ret = vx_migrate_task(current, new_vxi);
91         if (ret == 0) {
92                 current->vx_info->vx_bcaps &= (~vc_data.remove_cap);
93                 new_vxi->vx_flags |= vc_data.flags;
94                 if (vc_data.flags & VX_INFO_INIT)
95                         vx_set_initpid(new_vxi, current->tgid);
96                 if (vc_data.flags & VX_INFO_NAMESPACE)
97                         vx_set_namespace(new_vxi,
98                                 current->namespace, current->fs);
99                 if (vc_data.flags & VX_INFO_NPROC)
100                         new_vxi->limit.rlim[RLIMIT_NPROC] =
101                                 current->signal->rlim[RLIMIT_NPROC].rlim_max;
102
103                 /* tweak some defaults for legacy */
104                 new_vxi->vx_flags |= (VXF_HIDE_NETIF|VXF_INFO_INIT);
105                 ret = new_vxi->vx_id;
106         }
107 out_put:
108         put_vx_info(new_vxi);
109         return ret;
110 }
111