Skip to content

Commit

Permalink
[PATCH] ppc64: Fix PER_LINUX32 behaviour
Browse files Browse the repository at this point in the history
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: Paul Mackerras <paulus@samba.org>
Signed-off-by: Linus Torvalds <torvalds@osdl.org>
  • Loading branch information
Paul Mackerras authored and Linus Torvalds committed Jun 8, 2005
1 parent fee02f8 commit ce10d97
Show file tree
Hide file tree
Showing 4 changed files with 56 additions and 53 deletions.
2 changes: 1 addition & 1 deletion arch/ppc64/kernel/misc.S
Original file line number Diff line number Diff line change
Expand Up @@ -792,7 +792,7 @@ _GLOBAL(sys_call_table32)
.llong .compat_sys_newstat
.llong .compat_sys_newlstat
.llong .compat_sys_newfstat
.llong .sys_uname
.llong .sys32_uname
.llong .sys_ni_syscall /* 110 old iopl syscall */
.llong .sys_vhangup
.llong .sys_ni_syscall /* old idle syscall */
Expand Down
70 changes: 33 additions & 37 deletions arch/ppc64/kernel/sys_ppc32.c
Original file line number Diff line number Diff line change
Expand Up @@ -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,
* 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)
Expand Down Expand Up @@ -1158,26 +1133,47 @@ asmlinkage long sys32_sysctl(struct __sysctl_args32 __user *args)
}
#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)
{
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,&system_utsname.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 -= __put_user(0,name->nodename+__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 -= __copy_to_user(&name->version,&system_utsname.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 = __put_user(0,name->machine+__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 |= __put_user(0,name->nodename+__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 |= __copy_to_user(&name->version,&system_utsname.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 |= __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);

error = error ? -EFAULT : 0;
Expand Down
33 changes: 21 additions & 12 deletions arch/ppc64/kernel/syscalls.c
Original file line number Diff line number Diff line change
Expand Up @@ -199,24 +199,33 @@ unsigned long sys_mmap(unsigned long addr, size_t len,
return ret;
}

static int __init set_fakeppc(char *str)
long ppc64_personality(unsigned long personality)
{
if (*str)
return 0;
init_task.personality = PER_LINUX32;
return 1;
long ret;

if (personality(current->personality) == PER_LINUX32
&& 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);
if (name && !copy_to_user(name, &system_utsname, sizeof (*name)))
err = 0;
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;
}

Expand Down
4 changes: 1 addition & 3 deletions include/asm-ppc64/elf.h
Original file line number Diff line number Diff line change
Expand Up @@ -221,9 +221,7 @@ do { \
set_thread_flag(TIF_ABI_PENDING); \
else \
clear_thread_flag(TIF_ABI_PENDING); \
if (ibcs2) \
set_personality(PER_SVR4); \
else if (current->personality != PER_LINUX32) \
if (personality(current->personality) != PER_LINUX32) \
set_personality(PER_LINUX); \
} while (0)

Expand Down

0 comments on commit ce10d97

Please sign in to comment.