diff options
author | Paul Mackerras <paulus@samba.org> | 2005-06-08 07:59:15 -0400 |
---|---|---|
committer | Linus Torvalds <torvalds@ppc970.osdl.org> | 2005-06-08 19:24:15 -0400 |
commit | ce10d979053379553757c3b178a138facaddff82 (patch) | |
tree | ce88ba988eebab6cafb1ed34feedbcb13aa926e3 | |
parent | fee02f80e68abbcc45ed3c5dd5ed09d04a284791 (diff) |
[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: Paul Mackerras <paulus@samba.org>
Signed-off-by: Linus Torvalds <torvalds@osdl.org>
-rw-r--r-- | arch/ppc64/kernel/misc.S | 2 | ||||
-rw-r--r-- | arch/ppc64/kernel/sys_ppc32.c | 70 | ||||
-rw-r--r-- | arch/ppc64/kernel/syscalls.c | 33 | ||||
-rw-r--r-- | include/asm-ppc64/elf.h | 4 |
4 files changed, 56 insertions, 53 deletions
diff --git a/arch/ppc64/kernel/misc.S b/arch/ppc64/kernel/misc.S index b944717c1dbd..e3c73b3425dc 100644 --- a/arch/ppc64/kernel/misc.S +++ b/arch/ppc64/kernel/misc.S | |||
@@ -792,7 +792,7 @@ _GLOBAL(sys_call_table32) | |||
792 | .llong .compat_sys_newstat | 792 | .llong .compat_sys_newstat |
793 | .llong .compat_sys_newlstat | 793 | .llong .compat_sys_newlstat |
794 | .llong .compat_sys_newfstat | 794 | .llong .compat_sys_newfstat |
795 | .llong .sys_uname | 795 | .llong .sys32_uname |
796 | .llong .sys_ni_syscall /* 110 old iopl syscall */ | 796 | .llong .sys_ni_syscall /* 110 old iopl syscall */ |
797 | .llong .sys_vhangup | 797 | .llong .sys_vhangup |
798 | .llong .sys_ni_syscall /* old idle syscall */ | 798 | .llong .sys_ni_syscall /* old idle syscall */ |
diff --git a/arch/ppc64/kernel/sys_ppc32.c b/arch/ppc64/kernel/sys_ppc32.c index 7cf7a9600025..9c8e317c598d 100644 --- a/arch/ppc64/kernel/sys_ppc32.c +++ b/arch/ppc64/kernel/sys_ppc32.c | |||
@@ -791,31 +791,6 @@ asmlinkage int sys32_pciconfig_iobase(u32 which, u32 in_bus, u32 in_devfn) | |||
791 | } | 791 | } |
792 | 792 | ||
793 | 793 | ||
794 | asmlinkage int ppc64_newuname(struct new_utsname __user * name) | ||
795 | { | ||
796 | int errno = sys_newuname(name); | ||
797 | |||
798 | if (current->personality == PER_LINUX32 && !errno) { | ||
799 | if(copy_to_user(name->machine, "ppc\0\0", 8)) { | ||
800 | errno = -EFAULT; | ||
801 | } | ||
802 | } | ||
803 | return errno; | ||
804 | } | ||
805 | |||
806 | asmlinkage int ppc64_personality(unsigned long personality) | ||
807 | { | ||
808 | int ret; | ||
809 | if (current->personality == PER_LINUX32 && personality == PER_LINUX) | ||
810 | personality = PER_LINUX32; | ||
811 | ret = sys_personality(personality); | ||
812 | if (ret == PER_LINUX32) | ||
813 | ret = PER_LINUX; | ||
814 | return ret; | ||
815 | } | ||
816 | |||
817 | |||
818 | |||
819 | /* Note: it is necessary to treat mode as an unsigned int, | 794 | /* Note: it is necessary to treat mode as an unsigned int, |
820 | * with the corresponding cast to a signed int to insure that the | 795 | * with the corresponding cast to a signed int to insure that the |
821 | * proper conversion (sign extension) between the register representation of a signed int (msr in 32-bit mode) | 796 | * 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 | } | 1133 | } |
1159 | #endif | 1134 | #endif |
1160 | 1135 | ||
1136 | asmlinkage int sys32_uname(struct old_utsname __user * name) | ||
1137 | { | ||
1138 | int err = 0; | ||
1139 | |||
1140 | down_read(&uts_sem); | ||
1141 | if (copy_to_user(name, &system_utsname, sizeof(*name))) | ||
1142 | err = -EFAULT; | ||
1143 | up_read(&uts_sem); | ||
1144 | if (!err && personality(current->personality) == PER_LINUX32) { | ||
1145 | /* change "ppc64" to "ppc" */ | ||
1146 | if (__put_user(0, name->machine + 3) | ||
1147 | || __put_user(0, name->machine + 4)) | ||
1148 | err = -EFAULT; | ||
1149 | } | ||
1150 | return err; | ||
1151 | } | ||
1152 | |||
1161 | asmlinkage int sys32_olduname(struct oldold_utsname __user * name) | 1153 | asmlinkage int sys32_olduname(struct oldold_utsname __user * name) |
1162 | { | 1154 | { |
1163 | int error; | 1155 | int error; |
1164 | 1156 | ||
1165 | if (!name) | ||
1166 | return -EFAULT; | ||
1167 | if (!access_ok(VERIFY_WRITE,name,sizeof(struct oldold_utsname))) | 1157 | if (!access_ok(VERIFY_WRITE,name,sizeof(struct oldold_utsname))) |
1168 | return -EFAULT; | 1158 | return -EFAULT; |
1169 | 1159 | ||
1170 | down_read(&uts_sem); | 1160 | down_read(&uts_sem); |
1171 | error = __copy_to_user(&name->sysname,&system_utsname.sysname,__OLD_UTS_LEN); | 1161 | error = __copy_to_user(&name->sysname,&system_utsname.sysname,__OLD_UTS_LEN); |
1172 | error -= __put_user(0,name->sysname+__OLD_UTS_LEN); | 1162 | error |= __put_user(0,name->sysname+__OLD_UTS_LEN); |
1173 | error -= __copy_to_user(&name->nodename,&system_utsname.nodename,__OLD_UTS_LEN); | 1163 | error |= __copy_to_user(&name->nodename,&system_utsname.nodename,__OLD_UTS_LEN); |
1174 | error -= __put_user(0,name->nodename+__OLD_UTS_LEN); | 1164 | error |= __put_user(0,name->nodename+__OLD_UTS_LEN); |
1175 | error -= __copy_to_user(&name->release,&system_utsname.release,__OLD_UTS_LEN); | 1165 | error |= __copy_to_user(&name->release,&system_utsname.release,__OLD_UTS_LEN); |
1176 | error -= __put_user(0,name->release+__OLD_UTS_LEN); | 1166 | error |= __put_user(0,name->release+__OLD_UTS_LEN); |
1177 | error -= __copy_to_user(&name->version,&system_utsname.version,__OLD_UTS_LEN); | 1167 | error |= __copy_to_user(&name->version,&system_utsname.version,__OLD_UTS_LEN); |
1178 | error -= __put_user(0,name->version+__OLD_UTS_LEN); | 1168 | error |= __put_user(0,name->version+__OLD_UTS_LEN); |
1179 | error -= __copy_to_user(&name->machine,&system_utsname.machine,__OLD_UTS_LEN); | 1169 | error |= __copy_to_user(&name->machine,&system_utsname.machine,__OLD_UTS_LEN); |
1180 | error = __put_user(0,name->machine+__OLD_UTS_LEN); | 1170 | error |= __put_user(0,name->machine+__OLD_UTS_LEN); |
1171 | if (personality(current->personality) == PER_LINUX32) { | ||
1172 | /* change "ppc64" to "ppc" */ | ||
1173 | error |= __put_user(0, name->machine + 3); | ||
1174 | error |= __put_user(0, name->machine + 4); | ||
1175 | } | ||
1176 | |||
1181 | up_read(&uts_sem); | 1177 | up_read(&uts_sem); |
1182 | 1178 | ||
1183 | error = error ? -EFAULT : 0; | 1179 | error = error ? -EFAULT : 0; |
diff --git a/arch/ppc64/kernel/syscalls.c b/arch/ppc64/kernel/syscalls.c index f2865ff8d2f9..a8cbb202b8cd 100644 --- a/arch/ppc64/kernel/syscalls.c +++ b/arch/ppc64/kernel/syscalls.c | |||
@@ -199,24 +199,33 @@ out: | |||
199 | return ret; | 199 | return ret; |
200 | } | 200 | } |
201 | 201 | ||
202 | static int __init set_fakeppc(char *str) | 202 | long ppc64_personality(unsigned long personality) |
203 | { | 203 | { |
204 | if (*str) | 204 | long ret; |
205 | return 0; | 205 | |
206 | init_task.personality = PER_LINUX32; | 206 | if (personality(current->personality) == PER_LINUX32 |
207 | return 1; | 207 | && personality == PER_LINUX) |
208 | personality = PER_LINUX32; | ||
209 | ret = sys_personality(personality); | ||
210 | if (ret == PER_LINUX32) | ||
211 | ret = PER_LINUX; | ||
212 | return ret; | ||
208 | } | 213 | } |
209 | __setup("fakeppc", set_fakeppc); | ||
210 | 214 | ||
211 | asmlinkage int sys_uname(struct old_utsname __user * name) | 215 | long ppc64_newuname(struct new_utsname __user * name) |
212 | { | 216 | { |
213 | int err = -EFAULT; | 217 | int err = 0; |
214 | 218 | ||
215 | down_read(&uts_sem); | 219 | down_read(&uts_sem); |
216 | if (name && !copy_to_user(name, &system_utsname, sizeof (*name))) | 220 | if (copy_to_user(name, &system_utsname, sizeof(*name))) |
217 | err = 0; | 221 | err = -EFAULT; |
218 | up_read(&uts_sem); | 222 | up_read(&uts_sem); |
219 | 223 | if (!err && personality(current->personality) == PER_LINUX32) { | |
224 | /* change ppc64 to ppc */ | ||
225 | if (__put_user(0, name->machine + 3) | ||
226 | || __put_user(0, name->machine + 4)) | ||
227 | err = -EFAULT; | ||
228 | } | ||
220 | return err; | 229 | return err; |
221 | } | 230 | } |
222 | 231 | ||
diff --git a/include/asm-ppc64/elf.h b/include/asm-ppc64/elf.h index 6c42d61bedd1..085eedb956fe 100644 --- a/include/asm-ppc64/elf.h +++ b/include/asm-ppc64/elf.h | |||
@@ -221,9 +221,7 @@ do { \ | |||
221 | set_thread_flag(TIF_ABI_PENDING); \ | 221 | set_thread_flag(TIF_ABI_PENDING); \ |
222 | else \ | 222 | else \ |
223 | clear_thread_flag(TIF_ABI_PENDING); \ | 223 | clear_thread_flag(TIF_ABI_PENDING); \ |
224 | if (ibcs2) \ | 224 | if (personality(current->personality) != PER_LINUX32) \ |
225 | set_personality(PER_SVR4); \ | ||
226 | else if (current->personality != PER_LINUX32) \ | ||
227 | set_personality(PER_LINUX); \ | 225 | set_personality(PER_LINUX); \ |
228 | } while (0) | 226 | } while (0) |
229 | 227 | ||