summaryrefslogtreecommitdiffstats
path: root/kernel/exec_domain.c
diff options
context:
space:
mode:
authorRalf Baechle <ralf@linux-mips.org>2000-04-28 01:09:25 +0000
committerRalf Baechle <ralf@linux-mips.org>2000-04-28 01:09:25 +0000
commitb9ba7aeb165cffecdffb60aec8c3fa8d590d9ca9 (patch)
tree42d07b0c7246ae2536a702e7c5de9e2732341116 /kernel/exec_domain.c
parent7406b0a326f2d70ade2671c37d1beef62249db97 (diff)
Merge with 2.3.99-pre6.
Diffstat (limited to 'kernel/exec_domain.c')
-rw-r--r--kernel/exec_domain.c51
1 files changed, 29 insertions, 22 deletions
diff --git a/kernel/exec_domain.c b/kernel/exec_domain.c
index 111a3d69c..46a7443f1 100644
--- a/kernel/exec_domain.c
+++ b/kernel/exec_domain.c
@@ -32,9 +32,7 @@ static asmlinkage void no_lcall7(int segment, struct pt_regs * regs)
* personality set incorrectly. Check to see whether SVr4 is available,
* and use it, otherwise give the user a SEGV.
*/
- put_exec_domain(current->exec_domain);
- current->personality = PER_SVR4;
- current->exec_domain = lookup_exec_domain(current->personality);
+ set_personality(PER_SVR4);
if (current->exec_domain && current->exec_domain->handler
&& current->exec_domain->handler != no_lcall7) {
@@ -45,7 +43,7 @@ static asmlinkage void no_lcall7(int segment, struct pt_regs * regs)
send_sig(SIGSEGV, current, 1);
}
-struct exec_domain *lookup_exec_domain(unsigned long personality)
+static struct exec_domain *lookup_exec_domain(unsigned long personality)
{
unsigned long pers = personality & PER_MASK;
struct exec_domain *it;
@@ -104,28 +102,37 @@ int unregister_exec_domain(struct exec_domain *it)
return -EINVAL;
}
-asmlinkage long sys_personality(unsigned long personality)
+void __set_personality(unsigned long personality)
{
struct exec_domain *it;
- unsigned long old_personality;
- int ret;
-
- if (personality == 0xffffffff)
- return current->personality;
- ret = -EINVAL;
- lock_kernel();
it = lookup_exec_domain(personality);
- if (!it)
- goto out;
-
- old_personality = current->personality;
- put_exec_domain(current->exec_domain);
- current->personality = personality;
- current->exec_domain = it;
- ret = old_personality;
-out:
- unlock_kernel();
+ if (it) {
+ if (atomic_read(&current->fs->count) != 1) {
+ struct fs_struct *new = copy_fs_struct(current->fs);
+ if (!new)
+ return;
+ put_fs_struct(xchg(&current->fs,new));
+ }
+ /*
+ * At that point we are guaranteed to be the sole owner of
+ * current->fs.
+ */
+ current->personality = personality;
+ current->exec_domain = it;
+ set_fs_altroot();
+ put_exec_domain(current->exec_domain);
+ }
+}
+
+asmlinkage long sys_personality(unsigned long personality)
+{
+ int ret = current->personality;
+ if (personality != 0xffffffff) {
+ set_personality(personality);
+ if (current->personality != personality)
+ ret = -EINVAL;
+ }
return ret;
}