Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

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

[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
Loading
Loading
Loading
Loading
+1 −1
Original line number Diff line number Diff line
@@ -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 */
+33 −37
Original line number Diff line number Diff line
@@ -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)
@@ -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;
+21 −12
Original line number Diff line number Diff line
@@ -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;
}

+1 −3
Original line number Diff line number Diff line
@@ -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)