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