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