This commit was manufactured by cvs2svn to create branch 'vserver'.
[linux-2.6.git] / kernel / vserver / legacy.c
diff --git a/kernel/vserver/legacy.c b/kernel/vserver/legacy.c
new file mode 100644 (file)
index 0000000..a620ae3
--- /dev/null
@@ -0,0 +1,161 @@
+/*
+ *  linux/kernel/vserver/legacy.c
+ *
+ *  Virtual Server: Legacy Funtions
+ *
+ *  Copyright (C) 2001-2003  Jacques Gelinas
+ *  Copyright (C) 2003-2004  Herbert Pƶtzl
+ *
+ *  V0.01  broken out from vcontext.c V0.05
+ *
+ */
+
+#include <linux/config.h>
+#include <linux/vserver/legacy.h>
+#include <linux/vserver/context.h>
+#include <linux/vserver/namespace.h>
+#include <linux/vserver.h>
+#include <linux/sched.h>
+#include <linux/namespace.h>
+
+#include <asm/errno.h>
+#include <asm/uaccess.h>
+
+
+
+static int vx_set_initpid(struct vx_info *vxi, int pid)
+{
+       if (vxi->vx_initpid)
+               return -EPERM;
+
+       vxi->vx_initpid = pid;
+       return 0;
+}
+
+int vc_new_s_context(uint32_t ctx, void __user *data)
+{
+       int ret = -ENOMEM;
+       struct vcmd_new_s_context_v1 vc_data;
+       struct vx_info *new_vxi;
+
+       if (copy_from_user(&vc_data, data, sizeof(vc_data)))
+               return -EFAULT;
+
+       /* legacy hack, will be removed soon */
+       if (ctx == -2) {
+               /* assign flags and initpid */
+               if (!current->vx_info)
+                       return -EINVAL;
+               ret = 0;
+               if (vc_data.flags & VX_INFO_INIT)
+                       ret = vx_set_initpid(current->vx_info, current->tgid);
+               if (ret == 0) {
+                       /* We keep the same vx_id, but lower the capabilities */
+                       current->vx_info->vx_bcaps &= (~vc_data.remove_cap);
+                       // current->cap_bset &= (~vc_data.remove_cap);
+                       ret = vx_current_xid();
+                       current->vx_info->vx_flags |= vc_data.flags;
+               }
+               return ret;
+       }
+       
+       if (!vx_check(0, VX_ADMIN) ||
+               !capable(CAP_SYS_ADMIN) || vx_flags(VX_INFO_LOCK, 0))
+               return -EPERM;
+
+       /* ugly hack for Spectator */
+       if (ctx == 1) {
+               current->xid = 1;
+               return 0;
+       }
+
+       if (((ctx > MAX_S_CONTEXT) && (ctx != VX_DYNAMIC_ID)) ||
+               (ctx == 0))
+               return -EINVAL;
+               
+       if ((ctx == VX_DYNAMIC_ID) || (ctx < MIN_D_CONTEXT))
+               new_vxi = find_or_create_vx_info(ctx);
+       else
+               new_vxi = find_vx_info(ctx);
+
+       if (!new_vxi)
+               return -EINVAL;
+       new_vxi->vx_flags &= ~(VXF_STATE_SETUP|VXF_STATE_INIT);
+       
+       ret = vx_migrate_task(current, new_vxi);
+       if (ret == 0) {
+               current->vx_info->vx_bcaps &= (~vc_data.remove_cap);
+               // current->cap_bset &= (~vc_data.remove_cap);
+               new_vxi->vx_flags |= vc_data.flags;
+               if (vc_data.flags & VX_INFO_INIT)
+                       vx_set_initpid(new_vxi, current->tgid);
+               if (vc_data.flags & VX_INFO_NAMESPACE)
+                       vx_set_namespace(new_vxi,
+                               current->namespace, current->fs);
+               if (vc_data.flags & VX_INFO_NPROC)
+                       new_vxi->limit.rlim[RLIMIT_NPROC] =
+                               current->rlim[RLIMIT_NPROC].rlim_max;
+               ret = new_vxi->vx_id;
+       }
+       put_vx_info(new_vxi);
+       return ret;
+}
+
+
+
+/*  set ipv4 root (syscall) */
+
+int vc_set_ipv4root(uint32_t nbip, void __user *data)
+{
+       int i, err = -EPERM;
+       struct vcmd_set_ipv4root_v3 vc_data;
+       struct nx_info *new_nxi, *nxi = current->nx_info;
+
+       if (nbip < 0 || nbip > NB_IPV4ROOT)
+               return -EINVAL;
+       if (copy_from_user (&vc_data, data, sizeof(vc_data)))
+               return -EFAULT;
+
+       if (!nxi || nxi->ipv4[0] == 0 || capable(CAP_NET_ADMIN))
+               // We are allowed to change everything
+               err = 0;
+       else if (nxi) {
+               int found = 0;
+               
+               // We are allowed to select a subset of the currently
+               // installed IP numbers. No new one allowed
+               // We can't change the broadcast address though
+               for (i=0; i<nbip; i++) {
+                       int j;
+                       __u32 nxip = vc_data.nx_mask_pair[i].ip;
+                       for (j=0; j<nxi->nbipv4; j++) {
+                               if (nxip == nxi->ipv4[j]) {
+                                       found++;
+                                       break;
+                               }
+                       }
+               }
+               if ((found == nbip) &&
+                       (vc_data.broadcast == nxi->v4_bcast))
+                       err = 0;
+       }
+       if (err)
+               return err;
+
+       new_nxi = create_nx_info();
+       if (!new_nxi)
+               return -EINVAL;
+
+       new_nxi->nbipv4 = nbip;
+       for (i=0; i<nbip; i++) {
+               new_nxi->ipv4[i] = vc_data.nx_mask_pair[i].ip;
+               new_nxi->mask[i] = vc_data.nx_mask_pair[i].mask;
+       }
+       new_nxi->v4_bcast = vc_data.broadcast;
+       current->nx_info = new_nxi;
+       current->nid = new_nxi->nx_id;
+       put_nx_info(nxi);
+       return 0;
+}
+
+