fedora core 6 1.2949 + vserver 2.2.0
[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-2007  Herbert Pƶtzl
8  *
9  *  V0.01  broken out from vcontext.c V0.05
10  *  V0.02  updated to spaces *sigh*
11  *
12  */
13
14 #include <linux/sched.h>
15 #include <linux/vs_context.h>
16 #include <linux/vs_network.h>
17 #include <linux/vserver/legacy.h>
18 #include <linux/vserver/space.h>
19 // #include <linux/mnt_namespace.h>
20
21 #include <asm/errno.h>
22 #include <asm/uaccess.h>
23
24
25 extern int vx_set_init(struct vx_info *, struct task_struct *);
26
27 static int vx_set_initpid(struct vx_info *vxi, int pid)
28 {
29         struct task_struct *init;
30
31         init = find_task_by_real_pid(pid);
32         if (!init)
33                 return -ESRCH;
34         return vx_set_init(vxi, init);
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                         ret = vx_current_xid();
58                         current->vx_info->vx_flags |= vc_data.flags;
59                 }
60                 return ret;
61         }
62
63         if (!vx_check(0, VS_ADMIN) || !capable(CAP_SYS_ADMIN)
64                 /* might make sense in the future, or not ... */
65                 || vx_flags(VX_INFO_PRIVATE, 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 = lookup_or_create_vx_info(ctx);
80         else
81                 new_vxi = lookup_vx_info(ctx);
82
83         if (!new_vxi)
84                 return -EINVAL;
85
86         ret = -EPERM;
87         if (!vx_info_flags(new_vxi, VXF_STATE_SETUP, 0) &&
88                 vx_info_flags(new_vxi, VX_INFO_PRIVATE, 0))
89                 goto out_put;
90
91         ret = vx_migrate_task(current, new_vxi,
92                 vx_info_flags(new_vxi, VXF_STATE_SETUP, 0));
93         new_vxi->vx_flags &= ~VXF_STATE_SETUP;
94
95         if (ret == 0) {
96                 current->vx_info->vx_bcaps &= (~vc_data.remove_cap);
97                 new_vxi->vx_flags |= vc_data.flags;
98                 if (vc_data.flags & VX_INFO_INIT)
99                         vx_set_initpid(new_vxi, current->tgid);
100                 if (vc_data.flags & VX_INFO_NAMESPACE)
101                         vx_set_space(new_vxi, CLONE_NEWNS|CLONE_FS);
102                 if (vc_data.flags & VX_INFO_NPROC)
103                         __rlim_set(&new_vxi->limit, RLIMIT_NPROC,
104                                 current->signal->rlim[RLIMIT_NPROC].rlim_max);
105
106                 /* tweak some defaults for legacy */
107                 new_vxi->vx_flags |= (VXF_HIDE_NETIF|VXF_INFO_INIT);
108                 ret = new_vxi->vx_id;
109         }
110 out_put:
111         put_vx_info(new_vxi);
112         return ret;
113 }
114