X-Git-Url: http://git.onelab.eu/?a=blobdiff_plain;f=kernel%2Fvserver%2Fsignal.c;h=c56c750200096bbcb1c54a4aa5790029d5ba8eba;hb=97bf2856c6014879bd04983a3e9dfcdac1e7fe85;hp=963cc06513ebf97be645b191833cf3bb6a0fcf75;hpb=8e8ece46a861c84343256819eaec77e608ff9217;p=linux-2.6.git diff --git a/kernel/vserver/signal.c b/kernel/vserver/signal.c index 963cc0651..c56c75020 100644 --- a/kernel/vserver/signal.c +++ b/kernel/vserver/signal.c @@ -3,13 +3,14 @@ * * Virtual Server: Signal Support * - * Copyright (C) 2003-2005 Herbert Pötzl + * Copyright (C) 2003-2007 Herbert Pötzl * * V0.01 broken out from vcontext V0.05 + * V0.02 changed vcmds to vxi arg + * V0.03 adjusted siginfo for kill * */ -#include #include #include @@ -19,37 +20,28 @@ #include -int vc_ctx_kill(uint32_t id, void __user *data) +int vx_info_kill(struct vx_info *vxi, int pid, int sig) { int retval, count=0; - struct vcmd_ctx_kill_v0 vc_data; struct task_struct *p; - struct vx_info *vxi; - unsigned long priv = 0; - - if (!vx_check(0, VX_ADMIN)) - return -ENOSYS; - if (copy_from_user (&vc_data, data, sizeof(vc_data))) - return -EFAULT; - - vxi = locate_vx_info(id); - if (!vxi) - return -ESRCH; + struct siginfo *sip = SEND_SIG_PRIV; retval = -ESRCH; + vxdprintk(VXD_CBIT(misc, 4), + "vx_info_kill(%p[#%d],%d,%d)*", + vxi, vxi->vx_id, pid, sig); read_lock(&tasklist_lock); - switch (vc_data.pid) { + switch (pid) { case 0: - priv = 1; case -1: for_each_process(p) { int err = 0; - if (vx_task_xid(p) != id || p->pid <= 1 || - (vc_data.pid && vxi->vx_initpid == p->pid)) + if (vx_task_xid(p) != vxi->vx_id || p->pid <= 1 || + (pid && vxi->vx_initpid == p->pid)) continue; - err = group_send_sig_info(vc_data.sig, (void*)priv, p); + err = group_send_sig_info(sig, sip, p); ++count; if (err != -EPERM) retval = err; @@ -58,24 +50,46 @@ int vc_ctx_kill(uint32_t id, void __user *data) case 1: if (vxi->vx_initpid) { - vc_data.pid = vxi->vx_initpid; - priv = 1; + pid = vxi->vx_initpid; + /* for now, only SIGINT to private init ... */ + if (!vx_info_flags(vxi, VXF_STATE_ADMIN, 0) && + /* ... as long as there are tasks left */ + (atomic_read(&vxi->vx_tasks) > 1)) + sig = SIGINT; } /* fallthrough */ default: - p = find_task_by_real_pid(vc_data.pid); + p = find_task_by_real_pid(pid); if (p) { - if ((id == -1) || (vx_task_xid(p) == id)) - retval = group_send_sig_info(vc_data.sig, - (void*)priv, p); + if (vx_task_xid(p) == vxi->vx_id) + retval = group_send_sig_info(sig, sip, p); } break; } read_unlock(&tasklist_lock); - put_vx_info(vxi); + vxdprintk(VXD_CBIT(misc, 4), + "vx_info_kill(%p[#%d],%d,%d,%ld) = %d", + vxi, vxi->vx_id, pid, sig, (long)sip, retval); return retval; } +int vc_ctx_kill(struct vx_info *vxi, void __user *data) +{ + struct vcmd_ctx_kill_v0 vc_data; + + if (copy_from_user (&vc_data, data, sizeof(vc_data))) + return -EFAULT; + + /* special check to allow guest shutdown */ + if (!vx_info_flags(vxi, VXF_STATE_ADMIN, 0) && + /* forbid killall pid=0 when init is present */ + (((vc_data.pid < 1) && vxi->vx_initpid) || + (vc_data.pid > 1))) + return -EACCES; + + return vx_info_kill(vxi, vc_data.pid, vc_data.sig); +} + static int __wait_exit(struct vx_info *vxi) { @@ -86,7 +100,8 @@ static int __wait_exit(struct vx_info *vxi) set_current_state(TASK_INTERRUPTIBLE); wait: - if (vx_info_state(vxi, VXS_SHUTDOWN|VXS_HASHED) == VXS_SHUTDOWN) + if (vx_info_state(vxi, + VXS_SHUTDOWN|VXS_HASHED|VXS_HELPER) == VXS_SHUTDOWN) goto out; if (signal_pending(current)) { ret = -ERESTARTSYS; @@ -103,17 +118,17 @@ out: -int vc_wait_exit(uint32_t id, void __user *data) +int vc_wait_exit(struct vx_info *vxi, void __user *data) { - struct vx_info *vxi; + struct vcmd_wait_exit_v0 vc_data; int ret; - vxi = locate_vx_info(id); - if (!vxi) - return -ESRCH; - ret = __wait_exit(vxi); - put_vx_info(vxi); + vc_data.reboot_cmd = vxi->reboot_cmd; + vc_data.exit_code = vxi->exit_code; + + if (copy_to_user (data, &vc_data, sizeof(vc_data))) + ret = -EFAULT; return ret; }