diff options
author | Ralf Baechle <ralf@linux-mips.org> | 2000-04-28 01:09:25 +0000 |
---|---|---|
committer | Ralf Baechle <ralf@linux-mips.org> | 2000-04-28 01:09:25 +0000 |
commit | b9ba7aeb165cffecdffb60aec8c3fa8d590d9ca9 (patch) | |
tree | 42d07b0c7246ae2536a702e7c5de9e2732341116 /kernel/exec_domain.c | |
parent | 7406b0a326f2d70ade2671c37d1beef62249db97 (diff) |
Merge with 2.3.99-pre6.
Diffstat (limited to 'kernel/exec_domain.c')
-rw-r--r-- | kernel/exec_domain.c | 51 |
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(¤t->fs->count) != 1) { + struct fs_struct *new = copy_fs_struct(current->fs); + if (!new) + return; + put_fs_struct(xchg(¤t->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; } |