--- olpc-2.6-master.00/include/linux/vserver/signal.h 1969-12-31 19:00:00.000000000 -0500 +++ olpc-2.6-master-vs22x.02/include/linux/vserver/signal.h 2007-03-01 11:52:20.000000000 -0500 @@ -0,0 +1,14 @@ +#ifndef _VX_SIGNAL_H +#define _VX_SIGNAL_H + + +#ifdef __KERNEL__ + +struct vx_info; + +int vx_info_kill(struct vx_info *, int, int); + +#endif /* __KERNEL__ */ +#else /* _VX_SIGNAL_H */ +#warning duplicate inclusion +#endif /* _VX_SIGNAL_H */ --- olpc-2.6-master.00/kernel/signal.c 2007-02-28 20:05:29.000000000 -0500 +++ olpc-2.6-master-vs22x.02/kernel/signal.c 2007-03-01 11:52:20.000000000 -0500 @@ -605,11 +606,20 @@ static int check_kill_permission(int sig struct task_struct *t) { int error = -EINVAL; + if (!valid_signal(sig)) return error; + + if ((info != SEND_SIG_NOINFO) && + (is_si_special(info) || !SI_FROMUSER(info))) + goto skip; + + vxdprintk(VXD_CBIT(misc, 7), + "check_kill_permission(%d,%p,%p[#%u,%u])", + sig, info, t, vx_task_xid(t), t->pid); + error = -EPERM; - if ((info == SEND_SIG_NOINFO || (!is_si_special(info) && SI_FROMUSER(info))) - && ((sig != SIGCONT) || + if (((sig != SIGCONT) || (process_session(current) != process_session(t))) && (current->euid ^ t->suid) && (current->euid ^ t->uid) && (current->uid ^ t->suid) && (current->uid ^ t->uid) --- olpc-2.6-master.00/kernel/signal.c 2007-02-28 20:05:29.000000000 -0500 +++ olpc-2.6-master-vs22x.02/kernel/signal.c 2007-03-01 11:52:20.000000000 -0500 @@ -616,6 +626,14 @@ ***** && !capable(CAP_KILL)) return error; + error = -ESRCH; + if (!vx_check(vx_task_xid(t), VS_WATCH_P|VS_IDENT)) { + vxwprintk(current->xid || VXD_CBIT(misc, 7), + "signal %d[%p] xid mismatch %p[#%u,%u] xid=#%u", + sig, info, t, vx_task_xid(t), t->pid, current->xid); + return error; + } +skip: error = security_task_kill(t, info, sig, 0); if (!error) audit_signal_info(sig, t); /* Let audit system see the signal */ --- olpc-2.6-master.00/kernel/signal.c 2007-02-28 20:05:29.000000000 -0500 +++ olpc-2.6-master-vs22x.02/kernel/signal.c 2007-03-01 11:52:20.000000000 -0500 @@ -1131,7 +1149,7 @@ int kill_pid_info(int sig, struct siginf p = pid_task(pid, PIDTYPE_PID); error = -ESRCH; - if (p) + if (p && vx_check(vx_task_xid(p), VS_IDENT)) error = group_send_sig_info(sig, info, p); if (unlikely(sig_needs_tasklist(sig))) --- olpc-2.6-master.00/kernel/signal.c 2007-02-28 20:05:29.000000000 -0500 +++ olpc-2.6-master-vs22x.02/kernel/signal.c 2007-03-01 11:52:20.000000000 -0500 @@ -1206,7 +1224,8 @@ static int kill_something_info(int sig, read_lock(&tasklist_lock); for_each_process(p) { - if (p->pid > 1 && p->tgid != current->tgid) { + if (vx_check(vx_task_xid(p), VS_ADMIN_P|VS_IDENT) && + p->pid > 1 && p->tgid != current->tgid) { int err = group_send_sig_info(sig, info, p); ++count; if (err != -EPERM) --- olpc-2.6-master.00/kernel/vserver/signal.c 1969-12-31 19:00:00.000000000 -0500 +++ olpc-2.6-master-vs22x.02/kernel/vserver/signal.c 2007-03-01 11:52:20.000000000 -0500 @@ -0,0 +1,134 @@ +/* + * linux/kernel/vserver/signal.c + * + * Virtual Server: Signal Support + * + * 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 + +#include +#include + + +int vx_info_kill(struct vx_info *vxi, int pid, int sig) +{ + int retval, count=0; + struct task_struct *p; + 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 (pid) { + case 0: + case -1: + for_each_process(p) { + int err = 0; + + if (vx_task_xid(p) != vxi->vx_id || p->pid <= 1 || + (pid && vxi->vx_initpid == p->pid)) + continue; + + err = group_send_sig_info(sig, sip, p); + ++count; + if (err != -EPERM) + retval = err; + } + break; + + case 1: + if (vxi->vx_initpid) { + 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(pid); + if (p) { + if (vx_task_xid(p) == vxi->vx_id) + retval = group_send_sig_info(sig, sip, p); + } + break; + } + read_unlock(&tasklist_lock); + 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) +{ + DECLARE_WAITQUEUE(wait, current); + int ret = 0; + + add_wait_queue(&vxi->vx_wait, &wait); + set_current_state(TASK_INTERRUPTIBLE); + +wait: + if (vx_info_state(vxi, + VXS_SHUTDOWN|VXS_HASHED|VXS_HELPER) == VXS_SHUTDOWN) + goto out; + if (signal_pending(current)) { + ret = -ERESTARTSYS; + goto out; + } + schedule(); + goto wait; + +out: + set_current_state(TASK_RUNNING); + remove_wait_queue(&vxi->vx_wait, &wait); + return ret; +} + + + +int vc_wait_exit(struct vx_info *vxi, void __user *data) +{ + struct vcmd_wait_exit_v0 vc_data; + int ret; + + ret = __wait_exit(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; +} +