#include <linux/mman.h>
#include <linux/smp_lock.h>
#include <linux/notifier.h>
+#include <linux/kmod.h>
#include <linux/reboot.h>
#include <linux/prctl.h>
#include <linux/init.h>
if (!who)
user = current->user;
else
- user = find_user(who);
+ user = find_user(vx_current_xid(), who);
if (!user)
goto out_unlock;
if (!who)
user = current->user;
else
- user = find_user(who);
+ user = find_user(vx_current_xid(), who);
if (!user)
goto out_unlock;
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_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;
+}
/*
* Reboot system call: for obvious reasons only root may call it,
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:
{
struct user_struct *new_user;
- new_user = alloc_uid(new_ruid);
+ new_user = alloc_uid(vx_current_xid(), new_ruid);
if (!new_user)
return -EAGAIN;
int errno = 0;
down_read(&uts_sem);
- if (copy_to_user(name,&system_utsname,sizeof *name))
+ if (copy_to_user(name, vx_new_utsname(), sizeof *name))
errno = -EFAULT;
up_read(&uts_sem);
return errno;
int errno;
char tmp[__NEW_UTS_LEN];
- if (!capable(CAP_SYS_ADMIN))
+ if (!capable(CAP_SYS_ADMIN) && !vx_ccaps(VXC_SET_UTSNAME))
return -EPERM;
if (len < 0 || len > __NEW_UTS_LEN)
return -EINVAL;
down_write(&uts_sem);
errno = -EFAULT;
if (!copy_from_user(tmp, name, len)) {
- memcpy(system_utsname.nodename, tmp, len);
- system_utsname.nodename[len] = 0;
+ char *ptr = vx_new_uts(nodename);
+
+ memcpy(ptr, tmp, len);
+ ptr[len] = 0;
errno = 0;
}
up_write(&uts_sem);
asmlinkage long sys_gethostname(char __user *name, int len)
{
int i, errno;
+ char *ptr;
if (len < 0)
return -EINVAL;
down_read(&uts_sem);
- i = 1 + strlen(system_utsname.nodename);
+ ptr = vx_new_uts(nodename);
+ i = 1 + strlen(ptr);
if (i > len)
i = len;
errno = 0;
- if (copy_to_user(name, system_utsname.nodename, i))
+ if (copy_to_user(name, ptr, i))
errno = -EFAULT;
up_read(&uts_sem);
return errno;
int errno;
char tmp[__NEW_UTS_LEN];
- if (!capable(CAP_SYS_ADMIN))
+ if (!capable(CAP_SYS_ADMIN) && !vx_ccaps(VXC_SET_UTSNAME))
return -EPERM;
if (len < 0 || len > __NEW_UTS_LEN)
return -EINVAL;
down_write(&uts_sem);
errno = -EFAULT;
if (!copy_from_user(tmp, name, len)) {
- memcpy(system_utsname.domainname, tmp, len);
- system_utsname.domainname[len] = 0;
+ char *ptr = vx_new_uts(domainname);
+
+ memcpy(ptr, tmp, len);
+ ptr[len] = 0;
errno = 0;
}
up_write(&uts_sem);
old_rlim = current->rlim + resource;
if (((new_rlim.rlim_cur > old_rlim->rlim_max) ||
(new_rlim.rlim_max > old_rlim->rlim_max)) &&
- !capable(CAP_SYS_RESOURCE))
+ !capable(CAP_SYS_RESOURCE) && vx_ccaps(VXC_SET_RLIMIT))
return -EPERM;
if (resource == RLIMIT_NOFILE) {
if (new_rlim.rlim_cur > NR_OPEN || new_rlim.rlim_max > NR_OPEN)