summaryrefslogtreecommitdiffstats
path: root/kernel/sys.c
diff options
context:
space:
mode:
Diffstat (limited to 'kernel/sys.c')
-rw-r--r--kernel/sys.c75
1 files changed, 68 insertions, 7 deletions
diff --git a/kernel/sys.c b/kernel/sys.c
index 18bde979f34..8298878f4f7 100644
--- a/kernel/sys.c
+++ b/kernel/sys.c
@@ -33,6 +33,7 @@
#include <linux/task_io_accounting_ops.h>
#include <linux/seccomp.h>
#include <linux/cpu.h>
+#include <linux/personality.h>
#include <linux/ptrace.h>
#include <linux/fs_struct.h>
@@ -571,13 +572,7 @@ static int set_user(struct cred *new)
if (!new_user)
return -EAGAIN;
- if (!task_can_switch_user(new_user, current)) {
- free_uid(new_user);
- return -EINVAL;
- }
-
- if (atomic_read(&new_user->processes) >=
- current->signal->rlim[RLIMIT_NPROC].rlim_cur &&
+ if (atomic_read(&new_user->processes) >= rlimit(RLIMIT_NPROC) &&
new_user != INIT_USER) {
free_uid(new_user);
return -EAGAIN;
@@ -1120,6 +1115,15 @@ out:
DECLARE_RWSEM(uts_sem);
+#ifdef COMPAT_UTS_MACHINE
+#define override_architecture(name) \
+ (current->personality == PER_LINUX32 && \
+ copy_to_user(name->machine, COMPAT_UTS_MACHINE, \
+ sizeof(COMPAT_UTS_MACHINE)))
+#else
+#define override_architecture(name) 0
+#endif
+
SYSCALL_DEFINE1(newuname, struct new_utsname __user *, name)
{
int errno = 0;
@@ -1128,9 +1132,66 @@ SYSCALL_DEFINE1(newuname, struct new_utsname __user *, name)
if (copy_to_user(name, utsname(), sizeof *name))
errno = -EFAULT;
up_read(&uts_sem);
+
+ if (!errno && override_architecture(name))
+ errno = -EFAULT;
return errno;
}
+#ifdef __ARCH_WANT_SYS_OLD_UNAME
+/*
+ * Old cruft
+ */
+SYSCALL_DEFINE1(uname, struct old_utsname __user *, name)
+{
+ int error = 0;
+
+ if (!name)
+ return -EFAULT;
+
+ down_read(&uts_sem);
+ if (copy_to_user(name, utsname(), sizeof(*name)))
+ error = -EFAULT;
+ up_read(&uts_sem);
+
+ if (!error && override_architecture(name))
+ error = -EFAULT;
+ return error;
+}
+
+SYSCALL_DEFINE1(olduname, struct oldold_utsname __user *, name)
+{
+ int error;
+
+ if (!name)
+ return -EFAULT;
+ if (!access_ok(VERIFY_WRITE, name, sizeof(struct oldold_utsname)))
+ return -EFAULT;
+
+ down_read(&uts_sem);
+ error = __copy_to_user(&name->sysname, &utsname()->sysname,
+ __OLD_UTS_LEN);
+ error |= __put_user(0, name->sysname + __OLD_UTS_LEN);
+ error |= __copy_to_user(&name->nodename, &utsname()->nodename,
+ __OLD_UTS_LEN);
+ error |= __put_user(0, name->nodename + __OLD_UTS_LEN);
+ error |= __copy_to_user(&name->release, &utsname()->release,
+ __OLD_UTS_LEN);
+ error |= __put_user(0, name->release + __OLD_UTS_LEN);
+ error |= __copy_to_user(&name->version, &utsname()->version,
+ __OLD_UTS_LEN);
+ error |= __put_user(0, name->version + __OLD_UTS_LEN);
+ error |= __copy_to_user(&name->machine, &utsname()->machine,
+ __OLD_UTS_LEN);
+ error |= __put_user(0, name->machine + __OLD_UTS_LEN);
+ up_read(&uts_sem);
+
+ if (!error && override_architecture(name))
+ error = -EFAULT;
+ return error ? -EFAULT : 0;
+}
+#endif
+
SYSCALL_DEFINE2(sethostname, char __user *, name, int, len)
{
int errno;