#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>
#include <linux/security.h>
#include <linux/dcookies.h>
#include <linux/suspend.h>
+#include <linux/ckrm.h>
#include <asm/uaccess.h>
#include <asm/io.h>
cond_syscall(compat_sys_mq_timedreceive)
cond_syscall(compat_sys_mq_notify)
cond_syscall(compat_sys_mq_getsetattr)
+cond_syscall(sys_mbind)
+cond_syscall(sys_get_mempolicy)
+cond_syscall(sys_set_mempolicy)
+cond_syscall(compat_get_mempolicy)
/* arch-specific weak syscall entries */
cond_syscall(sys_pciconfig_read)
if (!who)
user = current->user;
else
- user = find_user(who);
+ user = find_user(vx_current_xid(), who);
if (!user)
goto out_unlock;
if (p->uid == who)
error = set_one_prio(p, niceval, error);
while_each_thread(g, p);
+ if (who)
+ free_uid(user); /* For find_user() */
break;
}
out_unlock:
if (!who)
user = current->user;
else
- user = find_user(who);
+ user = find_user(vx_current_xid(), who);
if (!user)
goto out_unlock;
retval = niceval;
}
while_each_thread(g, p);
+ if (who)
+ free_uid(user); /* for find_user() */
break;
}
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:
notifier_call_chain(&reboot_notifier_list, SYS_RESTART, NULL);
- system_state = SYSTEM_SHUTDOWN;
+ system_state = SYSTEM_RESTART;
device_shutdown();
printk(KERN_EMERG "Restarting system.\n");
machine_restart(NULL);
case LINUX_REBOOT_CMD_HALT:
notifier_call_chain(&reboot_notifier_list, SYS_HALT, NULL);
- system_state = SYSTEM_SHUTDOWN;
+ system_state = SYSTEM_HALT;
device_shutdown();
printk(KERN_EMERG "System halted.\n");
machine_halt();
case LINUX_REBOOT_CMD_POWER_OFF:
notifier_call_chain(&reboot_notifier_list, SYS_POWER_OFF, NULL);
- system_state = SYSTEM_SHUTDOWN;
+ system_state = SYSTEM_POWER_OFF;
device_shutdown();
printk(KERN_EMERG "Power down.\n");
machine_power_off();
buffer[sizeof(buffer) - 1] = '\0';
notifier_call_chain(&reboot_notifier_list, SYS_RESTART, buffer);
- system_state = SYSTEM_SHUTDOWN;
+ system_state = SYSTEM_RESTART;
device_shutdown();
printk(KERN_EMERG "Restarting system with command '%s'.\n", buffer);
machine_restart(buffer);
current->fsgid = new_egid;
current->egid = new_egid;
current->gid = new_rgid;
+
+ ckrm_cb_gid();
+
return 0;
}
}
else
return -EPERM;
+
+ ckrm_cb_gid();
+
return 0;
}
{
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;
current->suid = current->euid;
current->fsuid = current->euid;
+ ckrm_cb_uid();
+
return security_task_post_setuid(old_ruid, old_euid, old_suid, LSM_SETID_RE);
}
current->fsuid = current->euid = uid;
current->suid = new_suid;
+ ckrm_cb_uid();
+
return security_task_post_setuid(old_ruid, old_euid, old_suid, LSM_SETID_ID);
}
if (suid != (uid_t) -1)
current->suid = suid;
+ ckrm_cb_uid();
+
return security_task_post_setuid(old_ruid, old_euid, old_suid, LSM_SETID_RES);
}
-asmlinkage long sys_getresuid(uid_t *ruid, uid_t *euid, uid_t *suid)
+asmlinkage long sys_getresuid(uid_t __user *ruid, uid_t __user *euid, uid_t __user *suid)
{
int retval;
current->gid = rgid;
if (sgid != (gid_t) -1)
current->sgid = sgid;
+
+ ckrm_cb_gid();
+
return 0;
}
-asmlinkage long sys_getresgid(gid_t *rgid, gid_t *egid, gid_t *sgid)
+asmlinkage long sys_getresgid(gid_t __user *rgid, gid_t __user *egid, gid_t __user *sgid)
{
int retval;
}
}
+#ifdef __ARCH_WANT_SYS_GETPGRP
+
asmlinkage long sys_getpgrp(void)
{
/* SMP - assuming writes are word atomic this is fine */
return process_group(current);
}
+#endif
+
asmlinkage long sys_getsid(pid_t pid)
{
if (!pid) {
int nblocks;
int i;
- nblocks = (gidsetsize/NGROUPS_PER_BLOCK) +
- (gidsetsize%NGROUPS_PER_BLOCK?1:0);
- group_info = kmalloc(sizeof(*group_info) + nblocks*sizeof(gid_t *),
- GFP_USER);
+ nblocks = (gidsetsize + NGROUPS_PER_BLOCK - 1) / NGROUPS_PER_BLOCK;
+ /* Make sure we always allocate at least one indirect block pointer */
+ nblocks = nblocks ? : 1;
+ group_info = kmalloc(sizeof(*group_info) + nblocks*sizeof(gid_t *), GFP_USER);
if (!group_info)
return NULL;
group_info->ngroups = gidsetsize;
groups_sort(group_info);
get_group_info(group_info);
+
+ task_lock(current);
old_info = current->group_info;
current->group_info = group_info;
+ task_unlock(current);
+
put_group_info(old_info);
return 0;
if (gidsetsize < 0)
return -EINVAL;
+ /* no need to grab task_lock here; it cannot change */
get_group_info(current->group_info);
i = current->group_info->ngroups;
if (gidsetsize) {
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);
return errno;
}
+#ifdef __ARCH_WANT_SYS_GETHOSTNAME
+
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;
}
+#endif
+
/*
* Only setdomainname; getdomainname can be implemented by calling
* uname()
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);
? -EFAULT : 0;
}
-#if defined(COMPAT_RLIM_OLD_INFINITY) || !(defined(CONFIG_IA64) || defined(CONFIG_V850))
+#ifdef __ARCH_WANT_SYS_OLD_GETRLIMIT
/*
* Back compatibility for getrlimit. Needed for some apps.
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)