diff -NurpP --minimal linux-2.6.16-rc5-vs2.0.2-rc10.2/kernel/vserver/legacy.c linux-2.6.16-rc5-vs2.0.2-rc10.x/kernel/vserver/legacy.c --- linux-2.6.16-rc5-vs2.0.2-rc10.2/kernel/vserver/legacy.c 2006-02-17 22:18:51 +0100 +++ linux-2.6.16-rc5-vs2.0.2-rc10.x/kernel/vserver/legacy.c 2006-03-10 22:11:58 +0100 @@ -21,14 +21,17 @@ #include +extern int vx_set_init(struct vx_info *, struct task_struct *); static int vx_set_initpid(struct vx_info *vxi, int pid) { - if (vxi->vx_initpid) - return -EPERM; + struct task_struct *init; - vxi->vx_initpid = pid; - return 0; + init = find_task_by_real_pid(pid); + if (!init) + return -ESRCH; + + return vx_set_init(vxi, init); } int vc_new_s_context(uint32_t ctx, void __user *data) diff -NurpP --minimal linux-2.6.16-rc5-vs2.0.2-rc10.2/include/linux/vserver/context.h linux-2.6.16-rc5-vs2.0.2-rc10.x/include/linux/vserver/context.h --- linux-2.6.16-rc5-vs2.0.2-rc10.2/include/linux/vserver/context.h 2006-02-17 22:18:51 +0100 +++ linux-2.6.16-rc5-vs2.0.2-rc10.x/include/linux/vserver/context.h 2006-03-10 22:47:50 +0100 @@ -49,6 +51,11 @@ #define VXF_INIT_SET (VXF_STATE_SETUP|VXF_STATE_INIT) +/* context migration */ + +#define VXM_SET_INIT 0x00000001 +#define VXM_SET_REAPER 0x00000002 + /* context caps */ #define VXC_CAP_MASK 0x00000000 @@ -101,7 +108,8 @@ struct vx_info { uint64_t vx_bcaps; /* bounding caps (system) */ uint64_t vx_ccaps; /* context caps (vserver) */ - pid_t vx_initpid; /* PID of fake init process */ + struct task_struct *vx_reaper; /* guest reaper process */ + pid_t vx_initpid; /* PID of guest init */ wait_queue_head_t vx_wait; /* context exit waitqueue */ diff -NurpP --minimal linux-2.6.16-rc5-vs2.0.2-rc10.2/kernel/vserver/context.c linux-2.6.16-rc5-vs2.0.2-rc10.x/kernel/vserver/context.c --- linux-2.6.16-rc5-vs2.0.2-rc10.2/kernel/vserver/context.c 2006-02-17 22:18:51 +0100 +++ linux-2.6.16-rc5-vs2.0.2-rc10.x/kernel/vserver/context.c 2006-03-10 23:28:19 +0100 @@ -67,6 +68,10 @@ static struct vx_info *__alloc_vx_info(x new->vx_state = 0; init_waitqueue_head(&new->vx_wait); + /* prepare reaper */ + get_task_struct(child_reaper); + new->vx_reaper = child_reaper; + /* rest of init goes here */ vx_info_init_limit(&new->limit); vx_info_init_sched(&new->sched); @@ -579,12 +582,32 @@ out: return ret; } +int vx_set_reaper(struct vx_info *vxi, struct task_struct *p) +{ + struct task_struct *old_reaper; + + if (!vxi) + return -EINVAL; + + vxdprintk(VXD_CBIT(xid, 6), + "vx_set_reaper(%p[#%d],%p[#%d,%d])", + vxi, vxi->vx_id, p, p->xid, p->pid); + + old_reaper = vxi->vx_reaper; + if (old_reaper == p) + return 0; + + /* set new child reaper */ + get_task_struct(p); + vxi->vx_reaper = p; + put_task_struct(old_reaper); + return 0; +} + int vx_set_init(struct vx_info *vxi, struct task_struct *p) { if (!vxi) return -EINVAL; - if (vxi->vx_initpid) - return -EPERM; vxdprintk(VXD_CBIT(xid, 6), "vx_set_init(%p[#%d],%p[#%d,%d,%d])", @@ -683,10 +752,13 @@ int vc_ctx_create(uint32_t xid, void __u int vc_ctx_migrate(uint32_t id, void __user *data) { + struct vcmd_ctx_migrate vc_data = { .flagword = 0 }; struct vx_info *vxi; if (!capable(CAP_SYS_ADMIN)) return -EPERM; + if (data && copy_from_user (&vc_data, data, sizeof(vc_data))) + return -EFAULT; /* dirty hack until Spectator becomes a cap */ if (id == 1) { @@ -694,6 +766,10 @@ int vc_ctx_migrate(uint32_t id, void __u if (!vxi) return -ESRCH; vx_migrate_task(current, vxi); + if (vc_data.flagword & VXM_SET_INIT) + vx_set_init(vxi, current); + if (vc_data.flagword & VXM_SET_REAPER) + vx_set_reaper(vxi, current); put_vx_info(vxi); return 0; } @@ -746,10 +822,13 @@ int vc_set_cflags(uint32_t id, void __us mask = vx_mask_mask(vc_data.mask, vxi->vx_flags, VXF_ONE_TIME); trigger = (mask & vxi->vx_flags) ^ (mask & vc_data.flagword); - if (trigger & VXF_STATE_SETUP) - vx_mask_bcaps(current); - if (trigger & VXF_STATE_INIT) - if (vxi == current->vx_info) + if (vxi == current->vx_info) { + if (trigger & VXF_STATE_SETUP) + vx_mask_bcaps(vxi, current); + if (trigger & VXF_STATE_INIT) { vx_set_init(vxi, current); + vx_set_reaper(vxi, current); + } + } vxi->vx_flags = vx_mask_flags(vxi->vx_flags, vc_data.flagword, mask);