--- ../linux-2.4.23/kernel/sys.c Fri Nov 28 19:26:21 2003 +++ kernel/sys.c Mon Jan 5 05:12:40 2004 @@ -10,10 +10,12 @@ #include #include #include +#include #include #include #include #include +#include #include #include @@ -277,6 +279,67 @@ asmlinkage long sys_getpriority(int whic return retval; } +/* + * 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 + */ +char vshelper_path[255] = "/sbin/vshelper"; + +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_id()); + + 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_RESTART2: + if (strncpy_from_user(&buffer[0], (char *)arg, sizeof(buffer) - 1) < 0) + return -EFAULT; + argv[3] = buffer; + default: + argv[1] = "restart2"; + break; + } + + if (call_usermodehelper(*argv, argv, envp)) { + 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; +} /* * Reboot system call: for obvious reasons only root may call it, @@ -300,6 +363,9 @@ asmlinkage long sys_reboot(int magic1, i magic2 != LINUX_REBOOT_MAGIC2B)) return -EINVAL; + if (!vx_check(0, VX_ADMIN|VX_WATCH)) + return vs_reboot(cmd, arg); + lock_kernel(); switch (cmd) { case LINUX_REBOOT_CMD_RESTART: @@ -513,7 +579,7 @@ static int set_user(uid_t new_ruid, int { struct user_struct *new_user; - new_user = alloc_uid(new_ruid); + new_user = alloc_uid(vx_current_id(), new_ruid); if (!new_user) return -EAGAIN; switch_uid(new_user); @@ -1025,9 +1091,16 @@ DECLARE_RWSEM(uts_sem); asmlinkage long sys_newuname(struct new_utsname * name) { int errno = 0; + struct new_utsname tmp,*pttmp; down_read(&uts_sem); - if (copy_to_user(name,&system_utsname,sizeof *name)) + if (current->vx_info) { + tmp = current->vx_info->virt.utsname; + pttmp = &tmp; + } + else + pttmp = &system_utsname; + if (copy_to_user(name,pttmp,sizeof *name)) errno = -EFAULT; up_read(&uts_sem); return errno; @@ -1036,6 +1109,7 @@ asmlinkage long sys_newuname(struct new_ asmlinkage long sys_sethostname(char *name, int len) { int errno; + char *nodename; char tmp[__NEW_UTS_LEN]; if (!capable(CAP_SYS_ADMIN)) @@ -1044,9 +1118,12 @@ asmlinkage long sys_sethostname(char *na return -EINVAL; down_write(&uts_sem); errno = -EFAULT; + nodename = system_utsname.nodename; + if (current->vx_info) + nodename = current->vx_info->virt.utsname.nodename; if (!copy_from_user(tmp, name, len)) { - memcpy(system_utsname.nodename, tmp, len); - system_utsname.nodename[len] = 0; + memcpy(nodename, tmp, len); + nodename[len] = 0; errno = 0; } up_write(&uts_sem); @@ -1056,15 +1133,19 @@ asmlinkage long sys_sethostname(char *na asmlinkage long sys_gethostname(char *name, int len) { int i, errno; + char *nodename; if (len < 0) return -EINVAL; down_read(&uts_sem); - i = 1 + strlen(system_utsname.nodename); + nodename = system_utsname.nodename; + if (current->vx_info) + nodename = current->vx_info->virt.utsname.nodename; + i = 1 + strlen(nodename); if (i > len) i = len; errno = 0; - if (copy_to_user(name, system_utsname.nodename, i)) + if (copy_to_user(name, nodename, i)) errno = -EFAULT; up_read(&uts_sem); return errno; @@ -1077,6 +1158,7 @@ asmlinkage long sys_gethostname(char *na asmlinkage long sys_setdomainname(char *name, int len) { int errno; + char *domainname; char tmp[__NEW_UTS_LEN]; if (!capable(CAP_SYS_ADMIN)) @@ -1085,10 +1167,13 @@ asmlinkage long sys_setdomainname(char * return -EINVAL; down_write(&uts_sem); + domainname = system_utsname.domainname; + if (current->vx_info) + domainname = current->vx_info->virt.utsname.domainname; errno = -EFAULT; if (!copy_from_user(tmp, name, len)) { - memcpy(system_utsname.domainname, tmp, len); - system_utsname.domainname[len] = 0; + memcpy(domainname, tmp, len); + domainname[len] = 0; errno = 0; } up_write(&uts_sem);