Commit ce10d979 authored by Paul Mackerras's avatar Paul Mackerras Committed by Linus Torvalds

[PATCH] ppc64: Fix PER_LINUX32 behaviour

This patch fixes some bugs in the ppc64 PER_LINUX32 implementation,
noted by Juergen Kreileder:

* uname(2) doesn't respect PER_LINUX32, it returns 'ppc64' instead of 'ppc'
* Child processes of a PER_LINUX32 process don't inherit PER_LINUX32

Along the way I took the opportunity to move things around so that
sys_ppc32.c only has 32-bit syscall emulation functions and to remove
the obsolete "fakeppc" command line option.
Signed-off-by: default avatarPaul Mackerras <paulus@samba.org>
Signed-off-by: default avatarLinus Torvalds <torvalds@osdl.org>
parent fee02f80
...@@ -792,7 +792,7 @@ _GLOBAL(sys_call_table32) ...@@ -792,7 +792,7 @@ _GLOBAL(sys_call_table32)
.llong .compat_sys_newstat .llong .compat_sys_newstat
.llong .compat_sys_newlstat .llong .compat_sys_newlstat
.llong .compat_sys_newfstat .llong .compat_sys_newfstat
.llong .sys_uname .llong .sys32_uname
.llong .sys_ni_syscall /* 110 old iopl syscall */ .llong .sys_ni_syscall /* 110 old iopl syscall */
.llong .sys_vhangup .llong .sys_vhangup
.llong .sys_ni_syscall /* old idle syscall */ .llong .sys_ni_syscall /* old idle syscall */
......
...@@ -791,31 +791,6 @@ asmlinkage int sys32_pciconfig_iobase(u32 which, u32 in_bus, u32 in_devfn) ...@@ -791,31 +791,6 @@ asmlinkage int sys32_pciconfig_iobase(u32 which, u32 in_bus, u32 in_devfn)
} }
asmlinkage int ppc64_newuname(struct new_utsname __user * name)
{
int errno = sys_newuname(name);
if (current->personality == PER_LINUX32 && !errno) {
if(copy_to_user(name->machine, "ppc\0\0", 8)) {
errno = -EFAULT;
}
}
return errno;
}
asmlinkage int ppc64_personality(unsigned long personality)
{
int ret;
if (current->personality == PER_LINUX32 && personality == PER_LINUX)
personality = PER_LINUX32;
ret = sys_personality(personality);
if (ret == PER_LINUX32)
ret = PER_LINUX;
return ret;
}
/* Note: it is necessary to treat mode as an unsigned int, /* Note: it is necessary to treat mode as an unsigned int,
* with the corresponding cast to a signed int to insure that the * with the corresponding cast to a signed int to insure that the
* proper conversion (sign extension) between the register representation of a signed int (msr in 32-bit mode) * proper conversion (sign extension) between the register representation of a signed int (msr in 32-bit mode)
...@@ -1158,26 +1133,47 @@ asmlinkage long sys32_sysctl(struct __sysctl_args32 __user *args) ...@@ -1158,26 +1133,47 @@ asmlinkage long sys32_sysctl(struct __sysctl_args32 __user *args)
} }
#endif #endif
asmlinkage int sys32_uname(struct old_utsname __user * name)
{
int err = 0;
down_read(&uts_sem);
if (copy_to_user(name, &system_utsname, sizeof(*name)))
err = -EFAULT;
up_read(&uts_sem);
if (!err && personality(current->personality) == PER_LINUX32) {
/* change "ppc64" to "ppc" */
if (__put_user(0, name->machine + 3)
|| __put_user(0, name->machine + 4))
err = -EFAULT;
}
return err;
}
asmlinkage int sys32_olduname(struct oldold_utsname __user * name) asmlinkage int sys32_olduname(struct oldold_utsname __user * name)
{ {
int error; int error;
if (!name)
return -EFAULT;
if (!access_ok(VERIFY_WRITE,name,sizeof(struct oldold_utsname))) if (!access_ok(VERIFY_WRITE,name,sizeof(struct oldold_utsname)))
return -EFAULT; return -EFAULT;
down_read(&uts_sem); down_read(&uts_sem);
error = __copy_to_user(&name->sysname,&system_utsname.sysname,__OLD_UTS_LEN); error = __copy_to_user(&name->sysname,&system_utsname.sysname,__OLD_UTS_LEN);
error -= __put_user(0,name->sysname+__OLD_UTS_LEN); error |= __put_user(0,name->sysname+__OLD_UTS_LEN);
error -= __copy_to_user(&name->nodename,&system_utsname.nodename,__OLD_UTS_LEN); error |= __copy_to_user(&name->nodename,&system_utsname.nodename,__OLD_UTS_LEN);
error -= __put_user(0,name->nodename+__OLD_UTS_LEN); error |= __put_user(0,name->nodename+__OLD_UTS_LEN);
error -= __copy_to_user(&name->release,&system_utsname.release,__OLD_UTS_LEN); error |= __copy_to_user(&name->release,&system_utsname.release,__OLD_UTS_LEN);
error -= __put_user(0,name->release+__OLD_UTS_LEN); error |= __put_user(0,name->release+__OLD_UTS_LEN);
error -= __copy_to_user(&name->version,&system_utsname.version,__OLD_UTS_LEN); error |= __copy_to_user(&name->version,&system_utsname.version,__OLD_UTS_LEN);
error -= __put_user(0,name->version+__OLD_UTS_LEN); error |= __put_user(0,name->version+__OLD_UTS_LEN);
error -= __copy_to_user(&name->machine,&system_utsname.machine,__OLD_UTS_LEN); error |= __copy_to_user(&name->machine,&system_utsname.machine,__OLD_UTS_LEN);
error = __put_user(0,name->machine+__OLD_UTS_LEN); error |= __put_user(0,name->machine+__OLD_UTS_LEN);
if (personality(current->personality) == PER_LINUX32) {
/* change "ppc64" to "ppc" */
error |= __put_user(0, name->machine + 3);
error |= __put_user(0, name->machine + 4);
}
up_read(&uts_sem); up_read(&uts_sem);
error = error ? -EFAULT : 0; error = error ? -EFAULT : 0;
......
...@@ -199,24 +199,33 @@ out: ...@@ -199,24 +199,33 @@ out:
return ret; return ret;
} }
static int __init set_fakeppc(char *str) long ppc64_personality(unsigned long personality)
{ {
if (*str) long ret;
return 0;
init_task.personality = PER_LINUX32; if (personality(current->personality) == PER_LINUX32
return 1; && personality == PER_LINUX)
personality = PER_LINUX32;
ret = sys_personality(personality);
if (ret == PER_LINUX32)
ret = PER_LINUX;
return ret;
} }
__setup("fakeppc", set_fakeppc);
asmlinkage int sys_uname(struct old_utsname __user * name) long ppc64_newuname(struct new_utsname __user * name)
{ {
int err = -EFAULT; int err = 0;
down_read(&uts_sem); down_read(&uts_sem);
if (name && !copy_to_user(name, &system_utsname, sizeof (*name))) if (copy_to_user(name, &system_utsname, sizeof(*name)))
err = 0; err = -EFAULT;
up_read(&uts_sem); up_read(&uts_sem);
if (!err && personality(current->personality) == PER_LINUX32) {
/* change ppc64 to ppc */
if (__put_user(0, name->machine + 3)
|| __put_user(0, name->machine + 4))
err = -EFAULT;
}
return err; return err;
} }
......
...@@ -221,9 +221,7 @@ do { \ ...@@ -221,9 +221,7 @@ do { \
set_thread_flag(TIF_ABI_PENDING); \ set_thread_flag(TIF_ABI_PENDING); \
else \ else \
clear_thread_flag(TIF_ABI_PENDING); \ clear_thread_flag(TIF_ABI_PENDING); \
if (ibcs2) \ if (personality(current->personality) != PER_LINUX32) \
set_personality(PER_SVR4); \
else if (current->personality != PER_LINUX32) \
set_personality(PER_LINUX); \ set_personality(PER_LINUX); \
} while (0) } while (0)
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment