sparc: Fix mremap address range validation.
[deliverable/linux.git] / arch / sparc64 / kernel / sys_sparc32.c
CommitLineData
bc5a2e64 1/* sys_sparc32.c: Conversion between 32bit and 64bit native syscalls.
1da177e4
LT
2 *
3 * Copyright (C) 1997,1998 Jakub Jelinek (jj@sunsite.mff.cuni.cz)
bc5a2e64 4 * Copyright (C) 1997, 2007 David S. Miller (davem@davemloft.net)
1da177e4
LT
5 *
6 * These routines maintain argument size conversion between 32bit and 64bit
7 * environment.
8 */
9
1da177e4
LT
10#include <linux/kernel.h>
11#include <linux/sched.h>
a9415644 12#include <linux/capability.h>
1da177e4
LT
13#include <linux/fs.h>
14#include <linux/mm.h>
15#include <linux/file.h>
16#include <linux/signal.h>
17#include <linux/resource.h>
18#include <linux/times.h>
19#include <linux/utsname.h>
1da177e4
LT
20#include <linux/smp.h>
21#include <linux/smp_lock.h>
22#include <linux/sem.h>
23#include <linux/msg.h>
24#include <linux/shm.h>
25#include <linux/slab.h>
26#include <linux/uio.h>
27#include <linux/nfs_fs.h>
28#include <linux/quota.h>
29#include <linux/module.h>
30#include <linux/sunrpc/svc.h>
31#include <linux/nfsd/nfsd.h>
32#include <linux/nfsd/cache.h>
33#include <linux/nfsd/xdr.h>
34#include <linux/nfsd/syscall.h>
35#include <linux/poll.h>
36#include <linux/personality.h>
37#include <linux/stat.h>
38#include <linux/filter.h>
39#include <linux/highmem.h>
40#include <linux/highuid.h>
41#include <linux/mman.h>
42#include <linux/ipv6.h>
43#include <linux/in.h>
44#include <linux/icmpv6.h>
45#include <linux/syscalls.h>
46#include <linux/sysctl.h>
47#include <linux/binfmts.h>
48#include <linux/dnotify.h>
49#include <linux/security.h>
50#include <linux/compat.h>
51#include <linux/vfs.h>
52#include <linux/netfilter_ipv4/ip_tables.h>
53#include <linux/ptrace.h>
1da177e4
LT
54
55#include <asm/types.h>
1da177e4
LT
56#include <asm/uaccess.h>
57#include <asm/fpumacro.h>
1da177e4 58#include <asm/mmu_context.h>
14cc6aba 59#include <asm/compat_signal.h>
1da177e4
LT
60
61asmlinkage long sys32_chown16(const char __user * filename, u16 user, u16 group)
62{
63 return sys_chown(filename, low2highuid(user), low2highgid(group));
64}
65
66asmlinkage long sys32_lchown16(const char __user * filename, u16 user, u16 group)
67{
68 return sys_lchown(filename, low2highuid(user), low2highgid(group));
69}
70
71asmlinkage long sys32_fchown16(unsigned int fd, u16 user, u16 group)
72{
73 return sys_fchown(fd, low2highuid(user), low2highgid(group));
74}
75
76asmlinkage long sys32_setregid16(u16 rgid, u16 egid)
77{
78 return sys_setregid(low2highgid(rgid), low2highgid(egid));
79}
80
81asmlinkage long sys32_setgid16(u16 gid)
82{
83 return sys_setgid((gid_t)gid);
84}
85
86asmlinkage long sys32_setreuid16(u16 ruid, u16 euid)
87{
88 return sys_setreuid(low2highuid(ruid), low2highuid(euid));
89}
90
91asmlinkage long sys32_setuid16(u16 uid)
92{
93 return sys_setuid((uid_t)uid);
94}
95
96asmlinkage long sys32_setresuid16(u16 ruid, u16 euid, u16 suid)
97{
98 return sys_setresuid(low2highuid(ruid), low2highuid(euid),
99 low2highuid(suid));
100}
101
102asmlinkage long sys32_getresuid16(u16 __user *ruid, u16 __user *euid, u16 __user *suid)
103{
104 int retval;
105
106 if (!(retval = put_user(high2lowuid(current->uid), ruid)) &&
107 !(retval = put_user(high2lowuid(current->euid), euid)))
108 retval = put_user(high2lowuid(current->suid), suid);
109
110 return retval;
111}
112
113asmlinkage long sys32_setresgid16(u16 rgid, u16 egid, u16 sgid)
114{
115 return sys_setresgid(low2highgid(rgid), low2highgid(egid),
116 low2highgid(sgid));
117}
118
119asmlinkage long sys32_getresgid16(u16 __user *rgid, u16 __user *egid, u16 __user *sgid)
120{
121 int retval;
122
123 if (!(retval = put_user(high2lowgid(current->gid), rgid)) &&
124 !(retval = put_user(high2lowgid(current->egid), egid)))
125 retval = put_user(high2lowgid(current->sgid), sgid);
126
127 return retval;
128}
129
130asmlinkage long sys32_setfsuid16(u16 uid)
131{
132 return sys_setfsuid((uid_t)uid);
133}
134
135asmlinkage long sys32_setfsgid16(u16 gid)
136{
137 return sys_setfsgid((gid_t)gid);
138}
139
140static int groups16_to_user(u16 __user *grouplist, struct group_info *group_info)
141{
142 int i;
143 u16 group;
144
145 for (i = 0; i < group_info->ngroups; i++) {
146 group = (u16)GROUP_AT(group_info, i);
147 if (put_user(group, grouplist+i))
148 return -EFAULT;
149 }
150
151 return 0;
152}
153
154static int groups16_from_user(struct group_info *group_info, u16 __user *grouplist)
155{
156 int i;
157 u16 group;
158
159 for (i = 0; i < group_info->ngroups; i++) {
160 if (get_user(group, grouplist+i))
161 return -EFAULT;
162 GROUP_AT(group_info, i) = (gid_t)group;
163 }
164
165 return 0;
166}
167
168asmlinkage long sys32_getgroups16(int gidsetsize, u16 __user *grouplist)
169{
170 int i;
171
172 if (gidsetsize < 0)
173 return -EINVAL;
174
175 get_group_info(current->group_info);
176 i = current->group_info->ngroups;
177 if (gidsetsize) {
178 if (i > gidsetsize) {
179 i = -EINVAL;
180 goto out;
181 }
182 if (groups16_to_user(grouplist, current->group_info)) {
183 i = -EFAULT;
184 goto out;
185 }
186 }
187out:
188 put_group_info(current->group_info);
189 return i;
190}
191
192asmlinkage long sys32_setgroups16(int gidsetsize, u16 __user *grouplist)
193{
194 struct group_info *group_info;
195 int retval;
196
197 if (!capable(CAP_SETGID))
198 return -EPERM;
199 if ((unsigned)gidsetsize > NGROUPS_MAX)
200 return -EINVAL;
201
202 group_info = groups_alloc(gidsetsize);
203 if (!group_info)
204 return -ENOMEM;
205 retval = groups16_from_user(group_info, grouplist);
206 if (retval) {
207 put_group_info(group_info);
208 return retval;
209 }
210
211 retval = set_current_groups(group_info);
212 put_group_info(group_info);
213
214 return retval;
215}
216
217asmlinkage long sys32_getuid16(void)
218{
219 return high2lowuid(current->uid);
220}
221
222asmlinkage long sys32_geteuid16(void)
223{
224 return high2lowuid(current->euid);
225}
226
227asmlinkage long sys32_getgid16(void)
228{
229 return high2lowgid(current->gid);
230}
231
232asmlinkage long sys32_getegid16(void)
233{
234 return high2lowgid(current->egid);
235}
236
237/* 32-bit timeval and related flotsam. */
238
1da177e4
LT
239static inline long put_tv32(struct compat_timeval __user *o, struct timeval *i)
240{
241 return (!access_ok(VERIFY_WRITE, o, sizeof(*o)) ||
242 (__put_user(i->tv_sec, &o->tv_sec) |
243 __put_user(i->tv_usec, &o->tv_usec)));
244}
245
246#ifdef CONFIG_SYSVIPC
247asmlinkage long compat_sys_ipc(u32 call, u32 first, u32 second, u32 third, compat_uptr_t ptr, u32 fifth)
248{
249 int version;
250
251 version = call >> 16; /* hack for backward compatibility */
252 call &= 0xffff;
253
254 switch (call) {
255 case SEMTIMEDOP:
256 if (fifth)
257 /* sign extend semid */
258 return compat_sys_semtimedop((int)first,
259 compat_ptr(ptr), second,
260 compat_ptr(fifth));
261 /* else fall through for normal semop() */
262 case SEMOP:
263 /* struct sembuf is the same on 32 and 64bit :)) */
264 /* sign extend semid */
265 return sys_semtimedop((int)first, compat_ptr(ptr), second,
266 NULL);
267 case SEMGET:
268 /* sign extend key, nsems */
269 return sys_semget((int)first, (int)second, third);
270 case SEMCTL:
271 /* sign extend semid, semnum */
272 return compat_sys_semctl((int)first, (int)second, third,
273 compat_ptr(ptr));
274
275 case MSGSND:
276 /* sign extend msqid */
277 return compat_sys_msgsnd((int)first, (int)second, third,
278 compat_ptr(ptr));
279 case MSGRCV:
280 /* sign extend msqid, msgtyp */
281 return compat_sys_msgrcv((int)first, second, (int)fifth,
282 third, version, compat_ptr(ptr));
283 case MSGGET:
284 /* sign extend key */
285 return sys_msgget((int)first, second);
286 case MSGCTL:
287 /* sign extend msqid */
288 return compat_sys_msgctl((int)first, second, compat_ptr(ptr));
289
290 case SHMAT:
291 /* sign extend shmid */
292 return compat_sys_shmat((int)first, second, third, version,
293 compat_ptr(ptr));
294 case SHMDT:
295 return sys_shmdt(compat_ptr(ptr));
296 case SHMGET:
297 /* sign extend key_t */
298 return sys_shmget((int)first, second, third);
299 case SHMCTL:
300 /* sign extend shmid */
301 return compat_sys_shmctl((int)first, second, compat_ptr(ptr));
302
303 default:
304 return -ENOSYS;
305 };
306
307 return -ENOSYS;
308}
309#endif
310
311asmlinkage long sys32_truncate64(const char __user * path, unsigned long high, unsigned long low)
312{
313 if ((int)high < 0)
314 return -EINVAL;
315 else
316 return sys_truncate(path, (high << 32) | low);
317}
318
319asmlinkage long sys32_ftruncate64(unsigned int fd, unsigned long high, unsigned long low)
320{
321 if ((int)high < 0)
322 return -EINVAL;
323 else
324 return sys_ftruncate(fd, (high << 32) | low);
325}
326
327int cp_compat_stat(struct kstat *stat, struct compat_stat __user *statbuf)
328{
afefdbb2 329 compat_ino_t ino;
1da177e4
LT
330 int err;
331
332 if (stat->size > MAX_NON_LFS || !old_valid_dev(stat->dev) ||
333 !old_valid_dev(stat->rdev))
334 return -EOVERFLOW;
335
afefdbb2
DH
336 ino = stat->ino;
337 if (sizeof(ino) < sizeof(stat->ino) && ino != stat->ino)
338 return -EOVERFLOW;
339
1da177e4
LT
340 err = put_user(old_encode_dev(stat->dev), &statbuf->st_dev);
341 err |= put_user(stat->ino, &statbuf->st_ino);
342 err |= put_user(stat->mode, &statbuf->st_mode);
343 err |= put_user(stat->nlink, &statbuf->st_nlink);
344 err |= put_user(high2lowuid(stat->uid), &statbuf->st_uid);
345 err |= put_user(high2lowgid(stat->gid), &statbuf->st_gid);
346 err |= put_user(old_encode_dev(stat->rdev), &statbuf->st_rdev);
347 err |= put_user(stat->size, &statbuf->st_size);
348 err |= put_user(stat->atime.tv_sec, &statbuf->st_atime);
0ba4da03 349 err |= put_user(stat->atime.tv_nsec, &statbuf->st_atime_nsec);
1da177e4 350 err |= put_user(stat->mtime.tv_sec, &statbuf->st_mtime);
0ba4da03 351 err |= put_user(stat->mtime.tv_nsec, &statbuf->st_mtime_nsec);
1da177e4 352 err |= put_user(stat->ctime.tv_sec, &statbuf->st_ctime);
0ba4da03 353 err |= put_user(stat->ctime.tv_nsec, &statbuf->st_ctime_nsec);
1da177e4
LT
354 err |= put_user(stat->blksize, &statbuf->st_blksize);
355 err |= put_user(stat->blocks, &statbuf->st_blocks);
356 err |= put_user(0, &statbuf->__unused4[0]);
357 err |= put_user(0, &statbuf->__unused4[1]);
358
359 return err;
360}
361
0ba4da03
DM
362int cp_compat_stat64(struct kstat *stat, struct compat_stat64 __user *statbuf)
363{
364 int err;
365
366 err = put_user(huge_encode_dev(stat->dev), &statbuf->st_dev);
367 err |= put_user(stat->ino, &statbuf->st_ino);
368 err |= put_user(stat->mode, &statbuf->st_mode);
369 err |= put_user(stat->nlink, &statbuf->st_nlink);
370 err |= put_user(stat->uid, &statbuf->st_uid);
371 err |= put_user(stat->gid, &statbuf->st_gid);
372 err |= put_user(huge_encode_dev(stat->rdev), &statbuf->st_rdev);
373 err |= put_user(0, (unsigned long __user *) &statbuf->__pad3[0]);
374 err |= put_user(stat->size, &statbuf->st_size);
375 err |= put_user(stat->blksize, &statbuf->st_blksize);
376 err |= put_user(0, (unsigned int __user *) &statbuf->__pad4[0]);
377 err |= put_user(0, (unsigned int __user *) &statbuf->__pad4[4]);
378 err |= put_user(stat->blocks, &statbuf->st_blocks);
379 err |= put_user(stat->atime.tv_sec, &statbuf->st_atime);
380 err |= put_user(stat->atime.tv_nsec, &statbuf->st_atime_nsec);
381 err |= put_user(stat->mtime.tv_sec, &statbuf->st_mtime);
382 err |= put_user(stat->mtime.tv_nsec, &statbuf->st_mtime_nsec);
383 err |= put_user(stat->ctime.tv_sec, &statbuf->st_ctime);
384 err |= put_user(stat->ctime.tv_nsec, &statbuf->st_ctime_nsec);
385 err |= put_user(0, &statbuf->__unused4);
386 err |= put_user(0, &statbuf->__unused5);
387
388 return err;
389}
390
391asmlinkage long compat_sys_stat64(char __user * filename,
392 struct compat_stat64 __user *statbuf)
393{
394 struct kstat stat;
395 int error = vfs_stat(filename, &stat);
396
397 if (!error)
398 error = cp_compat_stat64(&stat, statbuf);
399 return error;
400}
401
402asmlinkage long compat_sys_lstat64(char __user * filename,
403 struct compat_stat64 __user *statbuf)
404{
405 struct kstat stat;
406 int error = vfs_lstat(filename, &stat);
407
408 if (!error)
409 error = cp_compat_stat64(&stat, statbuf);
410 return error;
411}
412
413asmlinkage long compat_sys_fstat64(unsigned int fd,
414 struct compat_stat64 __user * statbuf)
415{
416 struct kstat stat;
417 int error = vfs_fstat(fd, &stat);
418
419 if (!error)
420 error = cp_compat_stat64(&stat, statbuf);
421 return error;
422}
423
40ad7a6a
DM
424asmlinkage long compat_sys_fstatat64(unsigned int dfd, char __user *filename,
425 struct compat_stat64 __user * statbuf, int flag)
426{
427 struct kstat stat;
428 int error = -EINVAL;
429
430 if ((flag & ~AT_SYMLINK_NOFOLLOW) != 0)
431 goto out;
432
433 if (flag & AT_SYMLINK_NOFOLLOW)
434 error = vfs_lstat_fd(dfd, filename, &stat);
435 else
436 error = vfs_stat_fd(dfd, filename, &stat);
437
438 if (!error)
439 error = cp_compat_stat64(&stat, statbuf);
440
441out:
442 return error;
443}
444
1da177e4
LT
445asmlinkage long compat_sys_sysfs(int option, u32 arg1, u32 arg2)
446{
447 return sys_sysfs(option, arg1, arg2);
448}
449
1da177e4
LT
450asmlinkage long compat_sys_sched_rr_get_interval(compat_pid_t pid, struct compat_timespec __user *interval)
451{
452 struct timespec t;
453 int ret;
454 mm_segment_t old_fs = get_fs ();
455
456 set_fs (KERNEL_DS);
457 ret = sys_sched_rr_get_interval(pid, (struct timespec __user *) &t);
458 set_fs (old_fs);
459 if (put_compat_timespec(&t, interval))
460 return -EFAULT;
461 return ret;
462}
463
464asmlinkage long compat_sys_rt_sigprocmask(int how,
465 compat_sigset_t __user *set,
466 compat_sigset_t __user *oset,
467 compat_size_t sigsetsize)
468{
469 sigset_t s;
470 compat_sigset_t s32;
471 int ret;
472 mm_segment_t old_fs = get_fs();
473
474 if (set) {
475 if (copy_from_user (&s32, set, sizeof(compat_sigset_t)))
476 return -EFAULT;
477 switch (_NSIG_WORDS) {
478 case 4: s.sig[3] = s32.sig[6] | (((long)s32.sig[7]) << 32);
479 case 3: s.sig[2] = s32.sig[4] | (((long)s32.sig[5]) << 32);
480 case 2: s.sig[1] = s32.sig[2] | (((long)s32.sig[3]) << 32);
481 case 1: s.sig[0] = s32.sig[0] | (((long)s32.sig[1]) << 32);
482 }
483 }
484 set_fs (KERNEL_DS);
485 ret = sys_rt_sigprocmask(how,
486 set ? (sigset_t __user *) &s : NULL,
487 oset ? (sigset_t __user *) &s : NULL,
488 sigsetsize);
489 set_fs (old_fs);
490 if (ret) return ret;
491 if (oset) {
492 switch (_NSIG_WORDS) {
493 case 4: s32.sig[7] = (s.sig[3] >> 32); s32.sig[6] = s.sig[3];
494 case 3: s32.sig[5] = (s.sig[2] >> 32); s32.sig[4] = s.sig[2];
495 case 2: s32.sig[3] = (s.sig[1] >> 32); s32.sig[2] = s.sig[1];
496 case 1: s32.sig[1] = (s.sig[0] >> 32); s32.sig[0] = s.sig[0];
497 }
498 if (copy_to_user (oset, &s32, sizeof(compat_sigset_t)))
499 return -EFAULT;
500 }
501 return 0;
502}
503
504asmlinkage long sys32_rt_sigpending(compat_sigset_t __user *set,
505 compat_size_t sigsetsize)
506{
507 sigset_t s;
508 compat_sigset_t s32;
509 int ret;
510 mm_segment_t old_fs = get_fs();
511
512 set_fs (KERNEL_DS);
513 ret = sys_rt_sigpending((sigset_t __user *) &s, sigsetsize);
514 set_fs (old_fs);
515 if (!ret) {
516 switch (_NSIG_WORDS) {
517 case 4: s32.sig[7] = (s.sig[3] >> 32); s32.sig[6] = s.sig[3];
518 case 3: s32.sig[5] = (s.sig[2] >> 32); s32.sig[4] = s.sig[2];
519 case 2: s32.sig[3] = (s.sig[1] >> 32); s32.sig[2] = s.sig[1];
520 case 1: s32.sig[1] = (s.sig[0] >> 32); s32.sig[0] = s.sig[0];
521 }
522 if (copy_to_user (set, &s32, sizeof(compat_sigset_t)))
523 return -EFAULT;
524 }
525 return ret;
526}
527
528asmlinkage long compat_sys_rt_sigqueueinfo(int pid, int sig,
529 struct compat_siginfo __user *uinfo)
530{
531 siginfo_t info;
532 int ret;
533 mm_segment_t old_fs = get_fs();
534
535 if (copy_siginfo_from_user32(&info, uinfo))
536 return -EFAULT;
537
538 set_fs (KERNEL_DS);
539 ret = sys_rt_sigqueueinfo(pid, sig, (siginfo_t __user *) &info);
540 set_fs (old_fs);
541 return ret;
542}
543
544asmlinkage long compat_sys_sigaction(int sig, struct old_sigaction32 __user *act,
545 struct old_sigaction32 __user *oact)
546{
547 struct k_sigaction new_ka, old_ka;
548 int ret;
549
5526b7e4
DM
550 WARN_ON_ONCE(sig >= 0);
551 sig = -sig;
1da177e4
LT
552
553 if (act) {
554 compat_old_sigset_t mask;
555 u32 u_handler, u_restorer;
556
557 ret = get_user(u_handler, &act->sa_handler);
558 new_ka.sa.sa_handler = compat_ptr(u_handler);
559 ret |= __get_user(u_restorer, &act->sa_restorer);
560 new_ka.sa.sa_restorer = compat_ptr(u_restorer);
561 ret |= __get_user(new_ka.sa.sa_flags, &act->sa_flags);
562 ret |= __get_user(mask, &act->sa_mask);
563 if (ret)
564 return ret;
565 new_ka.ka_restorer = NULL;
566 siginitset(&new_ka.sa.sa_mask, mask);
567 }
568
569 ret = do_sigaction(sig, act ? &new_ka : NULL, oact ? &old_ka : NULL);
570
571 if (!ret && oact) {
572 ret = put_user(ptr_to_compat(old_ka.sa.sa_handler), &oact->sa_handler);
573 ret |= __put_user(ptr_to_compat(old_ka.sa.sa_restorer), &oact->sa_restorer);
574 ret |= __put_user(old_ka.sa.sa_flags, &oact->sa_flags);
575 ret |= __put_user(old_ka.sa.sa_mask.sig[0], &oact->sa_mask);
576 }
577
578 return ret;
579}
580
581asmlinkage long compat_sys_rt_sigaction(int sig,
582 struct sigaction32 __user *act,
583 struct sigaction32 __user *oact,
584 void __user *restorer,
585 compat_size_t sigsetsize)
586{
587 struct k_sigaction new_ka, old_ka;
588 int ret;
589 compat_sigset_t set32;
590
591 /* XXX: Don't preclude handling different sized sigset_t's. */
592 if (sigsetsize != sizeof(compat_sigset_t))
593 return -EINVAL;
594
1da177e4
LT
595 if (act) {
596 u32 u_handler, u_restorer;
597
598 new_ka.ka_restorer = restorer;
599 ret = get_user(u_handler, &act->sa_handler);
600 new_ka.sa.sa_handler = compat_ptr(u_handler);
601 ret |= __copy_from_user(&set32, &act->sa_mask, sizeof(compat_sigset_t));
602 switch (_NSIG_WORDS) {
603 case 4: new_ka.sa.sa_mask.sig[3] = set32.sig[6] | (((long)set32.sig[7]) << 32);
604 case 3: new_ka.sa.sa_mask.sig[2] = set32.sig[4] | (((long)set32.sig[5]) << 32);
605 case 2: new_ka.sa.sa_mask.sig[1] = set32.sig[2] | (((long)set32.sig[3]) << 32);
606 case 1: new_ka.sa.sa_mask.sig[0] = set32.sig[0] | (((long)set32.sig[1]) << 32);
607 }
608 ret |= __get_user(new_ka.sa.sa_flags, &act->sa_flags);
609 ret |= __get_user(u_restorer, &act->sa_restorer);
610 new_ka.sa.sa_restorer = compat_ptr(u_restorer);
611 if (ret)
612 return -EFAULT;
613 }
614
615 ret = do_sigaction(sig, act ? &new_ka : NULL, oact ? &old_ka : NULL);
616
617 if (!ret && oact) {
618 switch (_NSIG_WORDS) {
619 case 4: set32.sig[7] = (old_ka.sa.sa_mask.sig[3] >> 32); set32.sig[6] = old_ka.sa.sa_mask.sig[3];
620 case 3: set32.sig[5] = (old_ka.sa.sa_mask.sig[2] >> 32); set32.sig[4] = old_ka.sa.sa_mask.sig[2];
621 case 2: set32.sig[3] = (old_ka.sa.sa_mask.sig[1] >> 32); set32.sig[2] = old_ka.sa.sa_mask.sig[1];
622 case 1: set32.sig[1] = (old_ka.sa.sa_mask.sig[0] >> 32); set32.sig[0] = old_ka.sa.sa_mask.sig[0];
623 }
624 ret = put_user(ptr_to_compat(old_ka.sa.sa_handler), &oact->sa_handler);
625 ret |= __copy_to_user(&oact->sa_mask, &set32, sizeof(compat_sigset_t));
626 ret |= __put_user(old_ka.sa.sa_flags, &oact->sa_flags);
627 ret |= __put_user(ptr_to_compat(old_ka.sa.sa_restorer), &oact->sa_restorer);
628 if (ret)
629 ret = -EFAULT;
630 }
631
632 return ret;
633}
634
635/*
636 * sparc32_execve() executes a new program after the asm stub has set
637 * things up for us. This should basically do what I want it to.
638 */
639asmlinkage long sparc32_execve(struct pt_regs *regs)
640{
641 int error, base = 0;
642 char *filename;
643
644 /* User register window flush is done by entry.S */
645
646 /* Check for indirect call. */
647 if ((u32)regs->u_regs[UREG_G1] == 0)
648 base = 1;
649
650 filename = getname(compat_ptr(regs->u_regs[base + UREG_I0]));
651 error = PTR_ERR(filename);
652 if (IS_ERR(filename))
653 goto out;
654
655 error = compat_do_execve(filename,
656 compat_ptr(regs->u_regs[base + UREG_I1]),
657 compat_ptr(regs->u_regs[base + UREG_I2]), regs);
658
659 putname(filename);
660
661 if (!error) {
662 fprs_write(0);
663 current_thread_info()->xfsr[0] = 0;
664 current_thread_info()->fpsaved[0] = 0;
665 regs->tstate &= ~TSTATE_PEF;
1da177e4
LT
666 }
667out:
668 return error;
669}
670
671#ifdef CONFIG_MODULES
672
673asmlinkage long sys32_init_module(void __user *umod, u32 len,
674 const char __user *uargs)
675{
676 return sys_init_module(umod, len, uargs);
677}
678
679asmlinkage long sys32_delete_module(const char __user *name_user,
680 unsigned int flags)
681{
682 return sys_delete_module(name_user, flags);
683}
684
685#else /* CONFIG_MODULES */
686
687asmlinkage long sys32_init_module(const char __user *name_user,
688 struct module __user *mod_user)
689{
690 return -ENOSYS;
691}
692
693asmlinkage long sys32_delete_module(const char __user *name_user)
694{
695 return -ENOSYS;
696}
697
698#endif /* CONFIG_MODULES */
699
700/* Translations due to time_t size differences. Which affects all
701 sorts of things, like timeval and itimerval. */
702
703extern struct timezone sys_tz;
704
705asmlinkage long sys32_gettimeofday(struct compat_timeval __user *tv,
706 struct timezone __user *tz)
707{
708 if (tv) {
709 struct timeval ktv;
710 do_gettimeofday(&ktv);
711 if (put_tv32(tv, &ktv))
712 return -EFAULT;
713 }
714 if (tz) {
715 if (copy_to_user(tz, &sys_tz, sizeof(sys_tz)))
716 return -EFAULT;
717 }
718 return 0;
719}
720
721static inline long get_ts32(struct timespec *o, struct compat_timeval __user *i)
722{
723 long usec;
724
725 if (!access_ok(VERIFY_READ, i, sizeof(*i)))
726 return -EFAULT;
727 if (__get_user(o->tv_sec, &i->tv_sec))
728 return -EFAULT;
729 if (__get_user(usec, &i->tv_usec))
730 return -EFAULT;
731 o->tv_nsec = usec * 1000;
732 return 0;
733}
734
735asmlinkage long sys32_settimeofday(struct compat_timeval __user *tv,
736 struct timezone __user *tz)
737{
738 struct timespec kts;
739 struct timezone ktz;
740
741 if (tv) {
742 if (get_ts32(&kts, tv))
743 return -EFAULT;
744 }
745 if (tz) {
746 if (copy_from_user(&ktz, tz, sizeof(ktz)))
747 return -EFAULT;
748 }
749
750 return do_sys_settimeofday(tv ? &kts : NULL, tz ? &ktz : NULL);
751}
752
1da177e4
LT
753/* These are here just in case some old sparc32 binary calls it. */
754asmlinkage long sys32_pause(void)
755{
756 current->state = TASK_INTERRUPTIBLE;
757 schedule();
758 return -ERESTARTNOHAND;
759}
760
761asmlinkage compat_ssize_t sys32_pread64(unsigned int fd,
762 char __user *ubuf,
763 compat_size_t count,
764 unsigned long poshi,
765 unsigned long poslo)
766{
767 return sys_pread64(fd, ubuf, count, (poshi << 32) | poslo);
768}
769
770asmlinkage compat_ssize_t sys32_pwrite64(unsigned int fd,
771 char __user *ubuf,
772 compat_size_t count,
773 unsigned long poshi,
774 unsigned long poslo)
775{
776 return sys_pwrite64(fd, ubuf, count, (poshi << 32) | poslo);
777}
778
779asmlinkage long compat_sys_readahead(int fd,
780 unsigned long offhi,
781 unsigned long offlo,
782 compat_size_t count)
783{
784 return sys_readahead(fd, (offhi << 32) | offlo, count);
785}
786
787long compat_sys_fadvise64(int fd,
788 unsigned long offhi,
789 unsigned long offlo,
790 compat_size_t len, int advice)
791{
792 return sys_fadvise64_64(fd, (offhi << 32) | offlo, len, advice);
793}
794
795long compat_sys_fadvise64_64(int fd,
796 unsigned long offhi, unsigned long offlo,
797 unsigned long lenhi, unsigned long lenlo,
798 int advice)
799{
800 return sys_fadvise64_64(fd,
801 (offhi << 32) | offlo,
802 (lenhi << 32) | lenlo,
803 advice);
804}
805
806asmlinkage long compat_sys_sendfile(int out_fd, int in_fd,
807 compat_off_t __user *offset,
808 compat_size_t count)
809{
810 mm_segment_t old_fs = get_fs();
811 int ret;
812 off_t of;
813
814 if (offset && get_user(of, offset))
815 return -EFAULT;
816
817 set_fs(KERNEL_DS);
818 ret = sys_sendfile(out_fd, in_fd,
819 offset ? (off_t __user *) &of : NULL,
820 count);
821 set_fs(old_fs);
822
823 if (offset && put_user(of, offset))
824 return -EFAULT;
825
826 return ret;
827}
828
829asmlinkage long compat_sys_sendfile64(int out_fd, int in_fd,
830 compat_loff_t __user *offset,
831 compat_size_t count)
832{
833 mm_segment_t old_fs = get_fs();
834 int ret;
835 loff_t lof;
836
837 if (offset && get_user(lof, offset))
838 return -EFAULT;
839
840 set_fs(KERNEL_DS);
841 ret = sys_sendfile64(out_fd, in_fd,
842 offset ? (loff_t __user *) &lof : NULL,
843 count);
844 set_fs(old_fs);
845
846 if (offset && put_user(lof, offset))
847 return -EFAULT;
848
849 return ret;
850}
851
1da177e4
LT
852/* This is just a version for 32-bit applications which does
853 * not force O_LARGEFILE on.
854 */
855
856asmlinkage long sparc32_open(const char __user *filename,
857 int flags, int mode)
858{
5590ff0d 859 return do_sys_open(AT_FDCWD, filename, flags, mode);
1da177e4
LT
860}
861
862extern unsigned long do_mremap(unsigned long addr,
863 unsigned long old_len, unsigned long new_len,
864 unsigned long flags, unsigned long new_addr);
865
866asmlinkage unsigned long sys32_mremap(unsigned long addr,
867 unsigned long old_len, unsigned long new_len,
868 unsigned long flags, u32 __new_addr)
869{
1da177e4
LT
870 unsigned long ret = -EINVAL;
871 unsigned long new_addr = __new_addr;
872
94d149c3 873 if (unlikely(sparc64_mmap_check(addr, old_len)))
1da177e4 874 goto out;
94d149c3 875 if (unlikely(sparc64_mmap_check(new_addr, new_len)))
1da177e4
LT
876 goto out;
877 down_write(&current->mm->mmap_sem);
1da177e4 878 ret = do_mremap(addr, old_len, new_len, flags, new_addr);
1da177e4
LT
879 up_write(&current->mm->mmap_sem);
880out:
881 return ret;
882}
883
884struct __sysctl_args32 {
885 u32 name;
886 int nlen;
887 u32 oldval;
888 u32 oldlenp;
889 u32 newval;
890 u32 newlen;
891 u32 __unused[4];
892};
893
894asmlinkage long sys32_sysctl(struct __sysctl_args32 __user *args)
895{
b89a8171 896#ifndef CONFIG_SYSCTL_SYSCALL
1da177e4
LT
897 return -ENOSYS;
898#else
899 struct __sysctl_args32 tmp;
900 int error;
901 size_t oldlen, __user *oldlenp = NULL;
902 unsigned long addr = (((unsigned long)&args->__unused[0]) + 7UL) & ~7UL;
903
904 if (copy_from_user(&tmp, args, sizeof(tmp)))
905 return -EFAULT;
906
907 if (tmp.oldval && tmp.oldlenp) {
908 /* Duh, this is ugly and might not work if sysctl_args
909 is in read-only memory, but do_sysctl does indirectly
910 a lot of uaccess in both directions and we'd have to
911 basically copy the whole sysctl.c here, and
912 glibc's __sysctl uses rw memory for the structure
913 anyway. */
914 if (get_user(oldlen, (u32 __user *)(unsigned long)tmp.oldlenp) ||
915 put_user(oldlen, (size_t __user *)addr))
916 return -EFAULT;
917 oldlenp = (size_t __user *)addr;
918 }
919
920 lock_kernel();
921 error = do_sysctl((int __user *)(unsigned long) tmp.name,
922 tmp.nlen,
923 (void __user *)(unsigned long) tmp.oldval,
924 oldlenp,
925 (void __user *)(unsigned long) tmp.newval,
926 tmp.newlen);
927 unlock_kernel();
928 if (oldlenp) {
929 if (!error) {
930 if (get_user(oldlen, (size_t __user *)addr) ||
931 put_user(oldlen, (u32 __user *)(unsigned long) tmp.oldlenp))
932 error = -EFAULT;
933 }
934 if (copy_to_user(args->__unused, tmp.__unused, sizeof(tmp.__unused)))
935 error = -EFAULT;
936 }
937 return error;
938#endif
939}
940
941long sys32_lookup_dcookie(unsigned long cookie_high,
942 unsigned long cookie_low,
943 char __user *buf, size_t len)
944{
945 return sys_lookup_dcookie((cookie_high << 32) | cookie_low,
946 buf, len);
947}
289eee6f
DM
948
949long compat_sync_file_range(int fd, unsigned long off_high, unsigned long off_low, unsigned long nb_high, unsigned long nb_low, int flags)
950{
951 return sys_sync_file_range(fd,
952 (off_high << 32) | off_low,
953 (nb_high << 32) | nb_low,
954 flags);
955}
bc5a2e64
DM
956
957asmlinkage long compat_sys_fallocate(int fd, int mode, u32 offhi, u32 offlo,
958 u32 lenhi, u32 lenlo)
959{
960 return sys_fallocate(fd, mode, ((loff_t)offhi << 32) | offlo,
961 ((loff_t)lenhi << 32) | lenlo);
962}
This page took 0.334761 seconds and 5 git commands to generate.