--- linux-2.6.11-rc1/include/linux/sysctl.h 2005-01-14 12:35:58 +0100 +++ linux-2.6.11-rc1-vs1.9.4-rc2/include/linux/sysctl.h 2005-01-15 12:07:27 +0100 @@ -135,6 +135,7 @@ enum KERN_HZ_TIMER=65, /* int: hz timer on or off */ KERN_UNKNOWN_NMI_PANIC=66, /* int: unknown nmi panic flag */ KERN_BOOTLOADER_TYPE=67, /* int: boot loader type */ + KERN_VSHELPER=68, /* string: path to vshelper policy agent */ }; --- linux-2.6.11-rc1/kernel/sys.c 2005-01-14 12:36:01 +0100 +++ linux-2.6.11-rc1-vs1.9.4-rc2/kernel/sys.c 2005-01-15 12:54:14 +0100 @@ -356,6 +363,7 @@ out_unlock: return retval; } +long vs_reboot(unsigned int, void *); /* * Reboot system call: for obvious reasons only root may call it, --- linux-2.6.11-rc1/kernel/sys.c 2005-01-14 12:36:01 +0100 +++ linux-2.6.11-rc1-vs1.9.4-rc2/kernel/sys.c 2005-01-15 12:54:14 +0100 @@ -381,6 +389,9 @@ asmlinkage long sys_reboot(int magic1, i magic2 != LINUX_REBOOT_MAGIC2C)) return -EINVAL; + if (!vx_check(0, VX_ADMIN|VX_WATCH)) + return vs_reboot(cmd, arg); + lock_kernel(); switch (cmd) { case LINUX_REBOOT_CMD_RESTART: --- linux-2.6.11-rc1/kernel/sysctl.c 2005-01-14 12:36:01 +0100 +++ linux-2.6.11-rc1-vs1.9.4-rc2/kernel/sysctl.c 2005-01-15 11:27:52 +0100 @@ -85,6 +85,7 @@ extern char modprobe_path[]; #ifdef CONFIG_HOTPLUG extern char hotplug_path[]; #endif +extern char vshelper_path[]; #ifdef CONFIG_CHR_DEV_SG extern int sg_big_buff; #endif --- linux-2.6.11-rc1/kernel/sysctl.c 2005-01-14 12:36:01 +0100 +++ linux-2.6.11-rc1-vs1.9.4-rc2/kernel/sysctl.c 2005-01-15 11:27:52 +0100 @@ -399,6 +400,15 @@ static ctl_table kern_table[] = { .strategy = &sysctl_string, }, #endif + { + .ctl_name = KERN_VSHELPER, + .procname = "vshelper", + .data = &vshelper_path, + .maxlen = 256, + .mode = 0644, + .proc_handler = &proc_dostring, + .strategy = &sysctl_string, + }, #ifdef CONFIG_CHR_DEV_SG { .ctl_name = KERN_SG_BIG_BUFF, --- linux-2.6.11-rc1/kernel/vserver/helper.c 1970-01-01 01:00:00 +0100 +++ linux-2.6.11-rc1-vs1.9.4-rc2/kernel/vserver/helper.c 2005-01-15 11:27:52 +0100 @@ -0,0 +1,122 @@ +/* + * linux/kernel/vserver/helper.c + * + * Virtual Context Support + * + * Copyright (C) 2004 Herbert Pötzl + * + * V0.01 basic helper + * + */ + +#include +#include +#include +#include +#include +#include + +#include +#include + + +char vshelper_path[255] = "/sbin/vshelper"; + + +/* + * vshelper path is set via /proc/sys + * invoked by vserver sys_reboot(), with + * the following arguments + * + * argv [0] = vshelper_path; + * argv [1] = action: "restart", "halt", "poweroff", ... + * argv [2] = context identifier + * argv [3] = additional argument (restart2) + * + * envp [*] = type-specific parameters + */ + +long vs_reboot(unsigned int cmd, void * arg) +{ + char id_buf[8], cmd_buf[32]; + char uid_buf[32], pid_buf[32]; + char buffer[256]; + + char *argv[] = {vshelper_path, NULL, id_buf, NULL, 0}; + char *envp[] = {"HOME=/", "TERM=linux", + "PATH=/sbin:/usr/sbin:/bin:/usr/bin", + uid_buf, pid_buf, cmd_buf, 0}; + + snprintf(id_buf, sizeof(id_buf)-1, "%d", vx_current_xid()); + + snprintf(cmd_buf, sizeof(cmd_buf)-1, "VS_CMD=%08x", cmd); + snprintf(uid_buf, sizeof(uid_buf)-1, "VS_UID=%d", current->uid); + snprintf(pid_buf, sizeof(pid_buf)-1, "VS_PID=%d", current->pid); + + switch (cmd) { + case LINUX_REBOOT_CMD_RESTART: + argv[1] = "restart"; + break; + + case LINUX_REBOOT_CMD_HALT: + argv[1] = "halt"; + break; + + case LINUX_REBOOT_CMD_POWER_OFF: + argv[1] = "poweroff"; + break; + + case LINUX_REBOOT_CMD_SW_SUSPEND: + argv[1] = "swsusp"; + break; + + case LINUX_REBOOT_CMD_RESTART2: + if (strncpy_from_user(&buffer[0], (char *)arg, sizeof(buffer) - 1) < 0) + return -EFAULT; + argv[3] = buffer; + default: + argv[1] = "restart2"; + break; + } + + /* maybe we should wait ? */ + if (call_usermodehelper(*argv, argv, envp, 0)) { + printk( KERN_WARNING + "vs_reboot(): failed to exec (%s %s %s %s)\n", + vshelper_path, argv[1], argv[2], argv[3]); + return -EPERM; + } + return 0; +} + +long vs_context_state(unsigned int cmd) +{ + char id_buf[8], cmd_buf[32]; + + char *argv[] = {vshelper_path, NULL, id_buf, NULL, 0}; + char *envp[] = {"HOME=/", "TERM=linux", + "PATH=/sbin:/usr/sbin:/bin:/usr/bin", cmd_buf, 0}; + + snprintf(id_buf, sizeof(id_buf)-1, "%d", vx_current_xid()); + snprintf(cmd_buf, sizeof(cmd_buf)-1, "VS_CMD=%08x", cmd); + + switch (cmd) { + case VS_CONTEXT_CREATED: + argv[1] = "startup"; + break; + case VS_CONTEXT_DESTROY: + argv[1] = "shutdown"; + break; + default: + return 0; + } + + if (call_usermodehelper(*argv, argv, envp, 1)) { + printk( KERN_WARNING + "vs_context_state(): failed to exec (%s %s %s %s)\n", + vshelper_path, argv[1], argv[2], argv[3]); + return 0; + } + return 0; +} +