Merge with Linux 2.5.59.
[linux-2.6/linux-mips.git] / arch / sparc64 / kernel / sys_sparc32.c
blob1dd8bebcda4e176552fea4738569eceafcd12339
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.
4 * Copyright (C) 1997,1998 Jakub Jelinek (jj@sunsite.mff.cuni.cz)
5 * Copyright (C) 1997 David S. Miller (davem@caip.rutgers.edu)
7 * These routines maintain argument size conversion between 32bit and 64bit
8 * environment.
9 */
11 #include <linux/config.h>
12 #include <linux/kernel.h>
13 #include <linux/sched.h>
14 #include <linux/fs.h>
15 #include <linux/mm.h>
16 #include <linux/file.h>
17 #include <linux/signal.h>
18 #include <linux/resource.h>
19 #include <linux/times.h>
20 #include <linux/utsname.h>
21 #include <linux/timex.h>
22 #include <linux/smp.h>
23 #include <linux/smp_lock.h>
24 #include <linux/sem.h>
25 #include <linux/msg.h>
26 #include <linux/shm.h>
27 #include <linux/slab.h>
28 #include <linux/uio.h>
29 #include <linux/nfs_fs.h>
30 #include <linux/smb_fs.h>
31 #include <linux/smb_mount.h>
32 #include <linux/ncp_fs.h>
33 #include <linux/quota.h>
34 #include <linux/module.h>
35 #include <linux/sunrpc/svc.h>
36 #include <linux/nfsd/nfsd.h>
37 #include <linux/nfsd/cache.h>
38 #include <linux/nfsd/xdr.h>
39 #include <linux/nfsd/syscall.h>
40 #include <linux/poll.h>
41 #include <linux/personality.h>
42 #include <linux/stat.h>
43 #include <linux/filter.h>
44 #include <linux/highmem.h>
45 #include <linux/highuid.h>
46 #include <linux/mman.h>
47 #include <linux/ipv6.h>
48 #include <linux/in.h>
49 #include <linux/icmpv6.h>
50 #include <linux/sysctl.h>
51 #include <linux/binfmts.h>
52 #include <linux/dnotify.h>
53 #include <linux/security.h>
54 #include <linux/compat.h>
55 #include <linux/vfs.h>
56 #include <linux/netfilter_ipv4/ip_tables.h>
58 #include <asm/types.h>
59 #include <asm/ipc.h>
60 #include <asm/uaccess.h>
61 #include <asm/fpumacro.h>
62 #include <asm/semaphore.h>
63 #include <asm/mmu_context.h>
65 #include <net/scm.h>
67 /* Use this to get at 32-bit user passed pointers. */
68 /* Things to consider: the low-level assembly stub does
69 srl x, 0, x for first four arguments, so if you have
70 pointer to something in the first four arguments, just
71 declare it as a pointer, not u32. On the other side,
72 arguments from 5th onwards should be declared as u32
73 for pointers, and need AA() around each usage.
74 A() macro should be used for places where you e.g.
75 have some internal variable u32 and just want to get
76 rid of a compiler warning. AA() has to be used in
77 places where you want to convert a function argument
78 to 32bit pointer or when you e.g. access pt_regs
79 structure and want to consider 32bit registers only.
80 -jj
82 #define A(__x) ((unsigned long)(__x))
83 #define AA(__x) \
84 ({ unsigned long __ret; \
85 __asm__ ("srl %0, 0, %0" \
86 : "=r" (__ret) \
87 : "0" (__x)); \
88 __ret; \
91 extern asmlinkage long sys_chown(const char *, uid_t,gid_t);
92 extern asmlinkage long sys_lchown(const char *, uid_t,gid_t);
93 extern asmlinkage long sys_fchown(unsigned int, uid_t,gid_t);
94 extern asmlinkage long sys_setregid(gid_t, gid_t);
95 extern asmlinkage long sys_setgid(gid_t);
96 extern asmlinkage long sys_setreuid(uid_t, uid_t);
97 extern asmlinkage long sys_setuid(uid_t);
98 extern asmlinkage long sys_setresuid(uid_t, uid_t, uid_t);
99 extern asmlinkage long sys_setresgid(gid_t, gid_t, gid_t);
100 extern asmlinkage long sys_setfsuid(uid_t);
101 extern asmlinkage long sys_setfsgid(gid_t);
103 /* For this source file, we want overflow handling. */
105 #undef high2lowuid
106 #undef high2lowgid
107 #undef low2highuid
108 #undef low2highgid
109 #undef SET_UID16
110 #undef SET_GID16
111 #undef NEW_TO_OLD_UID
112 #undef NEW_TO_OLD_GID
113 #undef SET_OLDSTAT_UID
114 #undef SET_OLDSTAT_GID
115 #undef SET_STAT_UID
116 #undef SET_STAT_GID
118 #define high2lowuid(uid) ((uid) > 65535) ? (u16)overflowuid : (u16)(uid)
119 #define high2lowgid(gid) ((gid) > 65535) ? (u16)overflowgid : (u16)(gid)
120 #define low2highuid(uid) ((uid) == (u16)-1) ? (uid_t)-1 : (uid_t)(uid)
121 #define low2highgid(gid) ((gid) == (u16)-1) ? (gid_t)-1 : (gid_t)(gid)
122 #define SET_UID16(var, uid) var = high2lowuid(uid)
123 #define SET_GID16(var, gid) var = high2lowgid(gid)
124 #define NEW_TO_OLD_UID(uid) high2lowuid(uid)
125 #define NEW_TO_OLD_GID(gid) high2lowgid(gid)
126 #define SET_OLDSTAT_UID(stat, uid) (stat).st_uid = high2lowuid(uid)
127 #define SET_OLDSTAT_GID(stat, gid) (stat).st_gid = high2lowgid(gid)
128 #define SET_STAT_UID(stat, uid) (stat).st_uid = high2lowuid(uid)
129 #define SET_STAT_GID(stat, gid) (stat).st_gid = high2lowgid(gid)
131 asmlinkage long sys32_chown16(const char * filename, u16 user, u16 group)
133 return sys_chown(filename, low2highuid(user), low2highgid(group));
136 asmlinkage long sys32_lchown16(const char * filename, u16 user, u16 group)
138 return sys_lchown(filename, low2highuid(user), low2highgid(group));
141 asmlinkage long sys32_fchown16(unsigned int fd, u16 user, u16 group)
143 return sys_fchown(fd, low2highuid(user), low2highgid(group));
146 asmlinkage long sys32_setregid16(u16 rgid, u16 egid)
148 return sys_setregid(low2highgid(rgid), low2highgid(egid));
151 asmlinkage long sys32_setgid16(u16 gid)
153 return sys_setgid((gid_t)gid);
156 asmlinkage long sys32_setreuid16(u16 ruid, u16 euid)
158 return sys_setreuid(low2highuid(ruid), low2highuid(euid));
161 asmlinkage long sys32_setuid16(u16 uid)
163 return sys_setuid((uid_t)uid);
166 asmlinkage long sys32_setresuid16(u16 ruid, u16 euid, u16 suid)
168 return sys_setresuid(low2highuid(ruid), low2highuid(euid),
169 low2highuid(suid));
172 asmlinkage long sys32_getresuid16(u16 *ruid, u16 *euid, u16 *suid)
174 int retval;
176 if (!(retval = put_user(high2lowuid(current->uid), ruid)) &&
177 !(retval = put_user(high2lowuid(current->euid), euid)))
178 retval = put_user(high2lowuid(current->suid), suid);
180 return retval;
183 asmlinkage long sys32_setresgid16(u16 rgid, u16 egid, u16 sgid)
185 return sys_setresgid(low2highgid(rgid), low2highgid(egid),
186 low2highgid(sgid));
189 asmlinkage long sys32_getresgid16(u16 *rgid, u16 *egid, u16 *sgid)
191 int retval;
193 if (!(retval = put_user(high2lowgid(current->gid), rgid)) &&
194 !(retval = put_user(high2lowgid(current->egid), egid)))
195 retval = put_user(high2lowgid(current->sgid), sgid);
197 return retval;
200 asmlinkage long sys32_setfsuid16(u16 uid)
202 return sys_setfsuid((uid_t)uid);
205 asmlinkage long sys32_setfsgid16(u16 gid)
207 return sys_setfsgid((gid_t)gid);
210 asmlinkage long sys32_getgroups16(int gidsetsize, u16 *grouplist)
212 u16 groups[NGROUPS];
213 int i,j;
215 if (gidsetsize < 0)
216 return -EINVAL;
217 i = current->ngroups;
218 if (gidsetsize) {
219 if (i > gidsetsize)
220 return -EINVAL;
221 for(j=0;j<i;j++)
222 groups[j] = current->groups[j];
223 if (copy_to_user(grouplist, groups, sizeof(u16)*i))
224 return -EFAULT;
226 return i;
229 asmlinkage long sys32_setgroups16(int gidsetsize, u16 *grouplist)
231 u16 groups[NGROUPS];
232 int i;
234 if (!capable(CAP_SETGID))
235 return -EPERM;
236 if ((unsigned) gidsetsize > NGROUPS)
237 return -EINVAL;
238 if (copy_from_user(groups, grouplist, gidsetsize * sizeof(u16)))
239 return -EFAULT;
240 for (i = 0 ; i < gidsetsize ; i++)
241 current->groups[i] = (gid_t)groups[i];
242 current->ngroups = gidsetsize;
243 return 0;
246 asmlinkage long sys32_getuid16(void)
248 return high2lowuid(current->uid);
251 asmlinkage long sys32_geteuid16(void)
253 return high2lowuid(current->euid);
256 asmlinkage long sys32_getgid16(void)
258 return high2lowgid(current->gid);
261 asmlinkage long sys32_getegid16(void)
263 return high2lowgid(current->egid);
266 /* 32-bit timeval and related flotsam. */
268 static long get_tv32(struct timeval *o, struct compat_timeval *i)
270 return (!access_ok(VERIFY_READ, tv32, sizeof(*tv32)) ||
271 (__get_user(o->tv_sec, &i->tv_sec) |
272 __get_user(o->tv_usec, &i->tv_usec)));
275 static inline long put_tv32(struct compat_timeval *o, struct timeval *i)
277 return (!access_ok(VERIFY_WRITE, o, sizeof(*o)) ||
278 (__put_user(i->tv_sec, &o->tv_sec) |
279 __put_user(i->tv_usec, &o->tv_usec)));
282 extern asmlinkage int sys_ioperm(unsigned long from, unsigned long num, int on);
284 asmlinkage int sys32_ioperm(u32 from, u32 num, int on)
286 return sys_ioperm((unsigned long)from, (unsigned long)num, on);
289 struct msgbuf32 { s32 mtype; char mtext[1]; };
291 struct ipc_perm32
293 key_t key;
294 compat_uid_t uid;
295 compat_gid_t gid;
296 compat_uid_t cuid;
297 compat_gid_t cgid;
298 compat_mode_t mode;
299 unsigned short seq;
302 struct semid_ds32 {
303 struct ipc_perm32 sem_perm; /* permissions .. see ipc.h */
304 compat_time_t sem_otime; /* last semop time */
305 compat_time_t sem_ctime; /* last change time */
306 u32 sem_base; /* ptr to first semaphore in array */
307 u32 sem_pending; /* pending operations to be processed */
308 u32 sem_pending_last; /* last pending operation */
309 u32 undo; /* undo requests on this array */
310 unsigned short sem_nsems; /* no. of semaphores in array */
313 struct semid64_ds32 {
314 struct ipc64_perm sem_perm; /* this structure is the same on sparc32 and sparc64 */
315 unsigned int __pad1;
316 compat_time_t sem_otime;
317 unsigned int __pad2;
318 compat_time_t sem_ctime;
319 u32 sem_nsems;
320 u32 __unused1;
321 u32 __unused2;
324 struct msqid_ds32
326 struct ipc_perm32 msg_perm;
327 u32 msg_first;
328 u32 msg_last;
329 compat_time_t msg_stime;
330 compat_time_t msg_rtime;
331 compat_time_t msg_ctime;
332 u32 wwait;
333 u32 rwait;
334 unsigned short msg_cbytes;
335 unsigned short msg_qnum;
336 unsigned short msg_qbytes;
337 compat_ipc_pid_t msg_lspid;
338 compat_ipc_pid_t msg_lrpid;
341 struct msqid64_ds32 {
342 struct ipc64_perm msg_perm;
343 unsigned int __pad1;
344 compat_time_t msg_stime;
345 unsigned int __pad2;
346 compat_time_t msg_rtime;
347 unsigned int __pad3;
348 compat_time_t msg_ctime;
349 unsigned int msg_cbytes;
350 unsigned int msg_qnum;
351 unsigned int msg_qbytes;
352 compat_pid_t msg_lspid;
353 compat_pid_t msg_lrpid;
354 unsigned int __unused1;
355 unsigned int __unused2;
359 struct shmid_ds32 {
360 struct ipc_perm32 shm_perm;
361 int shm_segsz;
362 compat_time_t shm_atime;
363 compat_time_t shm_dtime;
364 compat_time_t shm_ctime;
365 compat_ipc_pid_t shm_cpid;
366 compat_ipc_pid_t shm_lpid;
367 unsigned short shm_nattch;
370 struct shmid64_ds32 {
371 struct ipc64_perm shm_perm;
372 unsigned int __pad1;
373 compat_time_t shm_atime;
374 unsigned int __pad2;
375 compat_time_t shm_dtime;
376 unsigned int __pad3;
377 compat_time_t shm_ctime;
378 compat_size_t shm_segsz;
379 compat_pid_t shm_cpid;
380 compat_pid_t shm_lpid;
381 unsigned int shm_nattch;
382 unsigned int __unused1;
383 unsigned int __unused2;
388 * sys32_ipc() is the de-multiplexer for the SysV IPC calls in 32bit emulation..
390 * This is really horribly ugly.
392 #define IPCOP_MASK(__x) (1UL << (__x))
393 static int do_sys32_semctl(int first, int second, int third, void *uptr)
395 union semun fourth;
396 u32 pad;
397 int err = -EINVAL;
399 if (!uptr)
400 goto out;
401 err = -EFAULT;
402 if (get_user (pad, (u32 *)uptr))
403 goto out;
404 if(third == SETVAL)
405 fourth.val = (int)pad;
406 else
407 fourth.__pad = (void *)A(pad);
408 if (IPCOP_MASK (third) &
409 (IPCOP_MASK (IPC_INFO) | IPCOP_MASK (SEM_INFO) | IPCOP_MASK (GETVAL) |
410 IPCOP_MASK (GETPID) | IPCOP_MASK (GETNCNT) | IPCOP_MASK (GETZCNT) |
411 IPCOP_MASK (GETALL) | IPCOP_MASK (SETALL) | IPCOP_MASK (IPC_RMID))) {
412 err = sys_semctl (first, second, third, fourth);
413 } else if (third & IPC_64) {
414 struct semid64_ds s;
415 struct semid64_ds32 *usp = (struct semid64_ds32 *)A(pad);
416 mm_segment_t old_fs;
417 int need_back_translation;
419 if (third == (IPC_SET|IPC_64)) {
420 err = get_user (s.sem_perm.uid, &usp->sem_perm.uid);
421 err |= __get_user (s.sem_perm.gid, &usp->sem_perm.gid);
422 err |= __get_user (s.sem_perm.mode, &usp->sem_perm.mode);
423 if (err)
424 goto out;
425 fourth.__pad = &s;
427 need_back_translation =
428 (IPCOP_MASK (third) &
429 (IPCOP_MASK (SEM_STAT) | IPCOP_MASK (IPC_STAT))) != 0;
430 if (need_back_translation)
431 fourth.__pad = &s;
432 old_fs = get_fs ();
433 set_fs (KERNEL_DS);
434 err = sys_semctl (first, second, third, fourth);
435 set_fs (old_fs);
436 if (need_back_translation) {
437 int err2 = copy_to_user (&usp->sem_perm, &s.sem_perm, sizeof(struct ipc64_perm) + 2*sizeof(time_t));
438 err2 |= __put_user (s.sem_nsems, &usp->sem_nsems);
439 if (err2) err = -EFAULT;
441 } else {
442 struct semid_ds s;
443 struct semid_ds32 *usp = (struct semid_ds32 *)A(pad);
444 mm_segment_t old_fs;
445 int need_back_translation;
447 if (third == IPC_SET) {
448 err = get_user (s.sem_perm.uid, &usp->sem_perm.uid);
449 err |= __get_user (s.sem_perm.gid, &usp->sem_perm.gid);
450 err |= __get_user (s.sem_perm.mode, &usp->sem_perm.mode);
451 if (err)
452 goto out;
453 fourth.__pad = &s;
455 need_back_translation =
456 (IPCOP_MASK (third) &
457 (IPCOP_MASK (SEM_STAT) | IPCOP_MASK (IPC_STAT))) != 0;
458 if (need_back_translation)
459 fourth.__pad = &s;
460 old_fs = get_fs ();
461 set_fs (KERNEL_DS);
462 err = sys_semctl (first, second, third, fourth);
463 set_fs (old_fs);
464 if (need_back_translation) {
465 int err2 = put_user (s.sem_perm.key, &usp->sem_perm.key);
466 err2 |= __put_user (high2lowuid(s.sem_perm.uid), &usp->sem_perm.uid);
467 err2 |= __put_user (high2lowgid(s.sem_perm.gid), &usp->sem_perm.gid);
468 err2 |= __put_user (high2lowuid(s.sem_perm.cuid), &usp->sem_perm.cuid);
469 err2 |= __put_user (high2lowgid(s.sem_perm.cgid), &usp->sem_perm.cgid);
470 err2 |= __put_user (s.sem_perm.mode, &usp->sem_perm.mode);
471 err2 |= __put_user (s.sem_perm.seq, &usp->sem_perm.seq);
472 err2 |= __put_user (s.sem_otime, &usp->sem_otime);
473 err2 |= __put_user (s.sem_ctime, &usp->sem_ctime);
474 err2 |= __put_user (s.sem_nsems, &usp->sem_nsems);
475 if (err2) err = -EFAULT;
478 out:
479 return err;
482 static int do_sys32_msgsnd (int first, int second, int third, void *uptr)
484 struct msgbuf *p = kmalloc (second + sizeof (struct msgbuf) + 4, GFP_USER);
485 struct msgbuf32 *up = (struct msgbuf32 *)uptr;
486 mm_segment_t old_fs;
487 int err;
489 if (!p)
490 return -ENOMEM;
491 err = -EFAULT;
492 if (get_user (p->mtype, &up->mtype) ||
493 __copy_from_user (p->mtext, &up->mtext, second))
494 goto out;
495 old_fs = get_fs ();
496 set_fs (KERNEL_DS);
497 err = sys_msgsnd (first, p, second, third);
498 set_fs (old_fs);
499 out:
500 kfree (p);
501 return err;
504 static int do_sys32_msgrcv (int first, int second, int msgtyp, int third,
505 int version, void *uptr)
507 struct msgbuf32 *up;
508 struct msgbuf *p;
509 mm_segment_t old_fs;
510 int err;
512 if (!version) {
513 struct ipc_kludge *uipck = (struct ipc_kludge *)uptr;
514 struct ipc_kludge ipck;
516 err = -EINVAL;
517 if (!uptr)
518 goto out;
519 err = -EFAULT;
520 if (copy_from_user (&ipck, uipck, sizeof (struct ipc_kludge)))
521 goto out;
522 uptr = (void *)A(ipck.msgp);
523 msgtyp = ipck.msgtyp;
525 err = -ENOMEM;
526 p = kmalloc (second + sizeof (struct msgbuf) + 4, GFP_USER);
527 if (!p)
528 goto out;
529 old_fs = get_fs ();
530 set_fs (KERNEL_DS);
531 err = sys_msgrcv (first, p, second + 4, msgtyp, third);
532 set_fs (old_fs);
533 if (err < 0)
534 goto free_then_out;
535 up = (struct msgbuf32 *)uptr;
536 if (put_user (p->mtype, &up->mtype) ||
537 __copy_to_user (&up->mtext, p->mtext, err))
538 err = -EFAULT;
539 free_then_out:
540 kfree (p);
541 out:
542 return err;
545 static int do_sys32_msgctl (int first, int second, void *uptr)
547 int err;
549 if (IPCOP_MASK (second) &
550 (IPCOP_MASK (IPC_INFO) | IPCOP_MASK (MSG_INFO) |
551 IPCOP_MASK (IPC_RMID))) {
552 err = sys_msgctl (first, second, (struct msqid_ds *)uptr);
553 } else if (second & IPC_64) {
554 struct msqid64_ds m;
555 struct msqid64_ds32 *up = (struct msqid64_ds32 *)uptr;
556 mm_segment_t old_fs;
558 if (second == (IPC_SET|IPC_64)) {
559 err = get_user (m.msg_perm.uid, &up->msg_perm.uid);
560 err |= __get_user (m.msg_perm.gid, &up->msg_perm.gid);
561 err |= __get_user (m.msg_perm.mode, &up->msg_perm.mode);
562 err |= __get_user (m.msg_qbytes, &up->msg_qbytes);
563 if (err)
564 goto out;
566 old_fs = get_fs ();
567 set_fs (KERNEL_DS);
568 err = sys_msgctl (first, second, (struct msqid_ds *)&m);
569 set_fs (old_fs);
570 if (IPCOP_MASK (second) &
571 (IPCOP_MASK (MSG_STAT) | IPCOP_MASK (IPC_STAT))) {
572 int err2 = copy_to_user(&up->msg_perm, &m.msg_perm, sizeof(struct ipc64_perm) + 3*sizeof(time_t));
573 err2 |= __put_user (m.msg_cbytes, &up->msg_cbytes);
574 err2 |= __put_user (m.msg_qnum, &up->msg_qnum);
575 err2 |= __put_user (m.msg_qbytes, &up->msg_qbytes);
576 err2 |= __put_user (m.msg_lspid, &up->msg_lspid);
577 err2 |= __put_user (m.msg_lrpid, &up->msg_lrpid);
578 if (err2)
579 err = -EFAULT;
581 } else {
582 struct msqid_ds m;
583 struct msqid_ds32 *up = (struct msqid_ds32 *)uptr;
584 mm_segment_t old_fs;
586 if (second == IPC_SET) {
587 err = get_user (m.msg_perm.uid, &up->msg_perm.uid);
588 err |= __get_user (m.msg_perm.gid, &up->msg_perm.gid);
589 err |= __get_user (m.msg_perm.mode, &up->msg_perm.mode);
590 err |= __get_user (m.msg_qbytes, &up->msg_qbytes);
591 if (err)
592 goto out;
594 old_fs = get_fs ();
595 set_fs (KERNEL_DS);
596 err = sys_msgctl (first, second, &m);
597 set_fs (old_fs);
598 if (IPCOP_MASK (second) &
599 (IPCOP_MASK (MSG_STAT) | IPCOP_MASK (IPC_STAT))) {
600 int err2 = put_user (m.msg_perm.key, &up->msg_perm.key);
601 err2 |= __put_user (high2lowuid(m.msg_perm.uid), &up->msg_perm.uid);
602 err2 |= __put_user (high2lowgid(m.msg_perm.gid), &up->msg_perm.gid);
603 err2 |= __put_user (high2lowuid(m.msg_perm.cuid), &up->msg_perm.cuid);
604 err2 |= __put_user (high2lowgid(m.msg_perm.cgid), &up->msg_perm.cgid);
605 err2 |= __put_user (m.msg_perm.mode, &up->msg_perm.mode);
606 err2 |= __put_user (m.msg_perm.seq, &up->msg_perm.seq);
607 err2 |= __put_user (m.msg_stime, &up->msg_stime);
608 err2 |= __put_user (m.msg_rtime, &up->msg_rtime);
609 err2 |= __put_user (m.msg_ctime, &up->msg_ctime);
610 err2 |= __put_user (m.msg_cbytes, &up->msg_cbytes);
611 err2 |= __put_user (m.msg_qnum, &up->msg_qnum);
612 err2 |= __put_user (m.msg_qbytes, &up->msg_qbytes);
613 err2 |= __put_user (m.msg_lspid, &up->msg_lspid);
614 err2 |= __put_user (m.msg_lrpid, &up->msg_lrpid);
615 if (err2)
616 err = -EFAULT;
620 out:
621 return err;
624 static int do_sys32_shmat (int first, int second, int third, int version, void *uptr)
626 unsigned long raddr;
627 u32 *uaddr = (u32 *)A((u32)third);
628 int err = -EINVAL;
630 if (version == 1)
631 goto out;
632 err = sys_shmat (first, uptr, second, &raddr);
633 if (err)
634 goto out;
635 err = put_user (raddr, uaddr);
636 out:
637 return err;
640 static int do_sys32_shmctl (int first, int second, void *uptr)
642 int err;
644 if (IPCOP_MASK (second) &
645 (IPCOP_MASK (IPC_INFO) | IPCOP_MASK (SHM_LOCK) | IPCOP_MASK (SHM_UNLOCK) |
646 IPCOP_MASK (IPC_RMID))) {
647 if (second == (IPC_INFO|IPC_64))
648 second = IPC_INFO; /* So that we don't have to translate it */
649 err = sys_shmctl (first, second, (struct shmid_ds *)uptr);
650 } else if ((second & IPC_64) && second != (SHM_INFO|IPC_64)) {
651 struct shmid64_ds s;
652 struct shmid64_ds32 *up = (struct shmid64_ds32 *)uptr;
653 mm_segment_t old_fs;
655 if (second == (IPC_SET|IPC_64)) {
656 err = get_user (s.shm_perm.uid, &up->shm_perm.uid);
657 err |= __get_user (s.shm_perm.gid, &up->shm_perm.gid);
658 err |= __get_user (s.shm_perm.mode, &up->shm_perm.mode);
659 if (err)
660 goto out;
662 old_fs = get_fs ();
663 set_fs (KERNEL_DS);
664 err = sys_shmctl (first, second, (struct shmid_ds *)&s);
665 set_fs (old_fs);
666 if (err < 0)
667 goto out;
669 /* Mask it even in this case so it becomes a CSE. */
670 if (IPCOP_MASK (second) &
671 (IPCOP_MASK (SHM_STAT) | IPCOP_MASK (IPC_STAT))) {
672 int err2 = copy_to_user (&up->shm_perm, &s.shm_perm, sizeof(struct ipc64_perm) + 3*sizeof(time_t));
673 err2 |= __put_user (s.shm_segsz, &up->shm_segsz);
674 err2 |= __put_user (s.shm_nattch, &up->shm_nattch);
675 err2 |= __put_user (s.shm_cpid, &up->shm_cpid);
676 err2 |= __put_user (s.shm_lpid, &up->shm_lpid);
677 if (err2)
678 err = -EFAULT;
680 } else {
681 struct shmid_ds s;
682 struct shmid_ds32 *up = (struct shmid_ds32 *)uptr;
683 mm_segment_t old_fs;
685 second &= ~IPC_64;
686 if (second == IPC_SET) {
687 err = get_user (s.shm_perm.uid, &up->shm_perm.uid);
688 err |= __get_user (s.shm_perm.gid, &up->shm_perm.gid);
689 err |= __get_user (s.shm_perm.mode, &up->shm_perm.mode);
690 if (err)
691 goto out;
693 old_fs = get_fs ();
694 set_fs (KERNEL_DS);
695 err = sys_shmctl (first, second, &s);
696 set_fs (old_fs);
697 if (err < 0)
698 goto out;
700 /* Mask it even in this case so it becomes a CSE. */
701 if (second == SHM_INFO) {
702 struct shm_info32 {
703 int used_ids;
704 u32 shm_tot, shm_rss, shm_swp;
705 u32 swap_attempts, swap_successes;
706 } *uip = (struct shm_info32 *)uptr;
707 struct shm_info *kp = (struct shm_info *)&s;
708 int err2 = put_user (kp->used_ids, &uip->used_ids);
709 err2 |= __put_user (kp->shm_tot, &uip->shm_tot);
710 err2 |= __put_user (kp->shm_rss, &uip->shm_rss);
711 err2 |= __put_user (kp->shm_swp, &uip->shm_swp);
712 err2 |= __put_user (kp->swap_attempts, &uip->swap_attempts);
713 err2 |= __put_user (kp->swap_successes, &uip->swap_successes);
714 if (err2)
715 err = -EFAULT;
716 } else if (IPCOP_MASK (second) &
717 (IPCOP_MASK (SHM_STAT) | IPCOP_MASK (IPC_STAT))) {
718 int err2 = put_user (s.shm_perm.key, &up->shm_perm.key);
719 err2 |= __put_user (high2lowuid(s.shm_perm.uid), &up->shm_perm.uid);
720 err2 |= __put_user (high2lowuid(s.shm_perm.gid), &up->shm_perm.gid);
721 err2 |= __put_user (high2lowuid(s.shm_perm.cuid), &up->shm_perm.cuid);
722 err2 |= __put_user (high2lowuid(s.shm_perm.cgid), &up->shm_perm.cgid);
723 err2 |= __put_user (s.shm_perm.mode, &up->shm_perm.mode);
724 err2 |= __put_user (s.shm_perm.seq, &up->shm_perm.seq);
725 err2 |= __put_user (s.shm_atime, &up->shm_atime);
726 err2 |= __put_user (s.shm_dtime, &up->shm_dtime);
727 err2 |= __put_user (s.shm_ctime, &up->shm_ctime);
728 err2 |= __put_user (s.shm_segsz, &up->shm_segsz);
729 err2 |= __put_user (s.shm_nattch, &up->shm_nattch);
730 err2 |= __put_user (s.shm_cpid, &up->shm_cpid);
731 err2 |= __put_user (s.shm_lpid, &up->shm_lpid);
732 if (err2)
733 err = -EFAULT;
736 out:
737 return err;
740 asmlinkage int sys32_ipc (u32 call, int first, int second, int third, u32 ptr, u32 fifth)
742 int version, err;
744 version = call >> 16; /* hack for backward compatibility */
745 call &= 0xffff;
747 if (call <= SEMCTL)
748 switch (call) {
749 case SEMOP:
750 /* struct sembuf is the same on 32 and 64bit :)) */
751 err = sys_semop (first, (struct sembuf *)AA(ptr), second);
752 goto out;
753 case SEMGET:
754 err = sys_semget (first, second, third);
755 goto out;
756 case SEMCTL:
757 err = do_sys32_semctl (first, second, third, (void *)AA(ptr));
758 goto out;
759 default:
760 err = -EINVAL;
761 goto out;
763 if (call <= MSGCTL)
764 switch (call) {
765 case MSGSND:
766 err = do_sys32_msgsnd (first, second, third, (void *)AA(ptr));
767 goto out;
768 case MSGRCV:
769 err = do_sys32_msgrcv (first, second, fifth, third,
770 version, (void *)AA(ptr));
771 goto out;
772 case MSGGET:
773 err = sys_msgget ((key_t) first, second);
774 goto out;
775 case MSGCTL:
776 err = do_sys32_msgctl (first, second, (void *)AA(ptr));
777 goto out;
778 default:
779 err = -EINVAL;
780 goto out;
782 if (call <= SHMCTL)
783 switch (call) {
784 case SHMAT:
785 err = do_sys32_shmat (first, second, third,
786 version, (void *)AA(ptr));
787 goto out;
788 case SHMDT:
789 err = sys_shmdt ((char *)AA(ptr));
790 goto out;
791 case SHMGET:
792 err = sys_shmget (first, second, third);
793 goto out;
794 case SHMCTL:
795 err = do_sys32_shmctl (first, second, (void *)AA(ptr));
796 goto out;
797 default:
798 err = -EINVAL;
799 goto out;
802 err = -EINVAL;
804 out:
805 return err;
808 extern asmlinkage long sys_fcntl(unsigned int fd, unsigned int cmd, unsigned long arg);
810 asmlinkage long sys32_fcntl(unsigned int fd, unsigned int cmd, unsigned long arg)
812 switch (cmd) {
813 case F_GETLK:
814 case F_SETLK:
815 case F_SETLKW:
817 struct flock f;
818 mm_segment_t old_fs;
819 long ret;
821 if (get_compat_flock(&f, (struct compat_flock *)arg))
822 return -EFAULT;
823 old_fs = get_fs(); set_fs (KERNEL_DS);
824 ret = sys_fcntl(fd, cmd, (unsigned long)&f);
825 set_fs (old_fs);
826 if (ret) return ret;
827 if (put_compat_flock(&f, (struct compat_flock *)arg))
828 return -EFAULT;
829 return 0;
831 default:
832 return sys_fcntl(fd, cmd, (unsigned long)arg);
836 asmlinkage long sys32_fcntl64(unsigned int fd, unsigned int cmd, unsigned long arg)
838 if (cmd >= F_GETLK64 && cmd <= F_SETLKW64)
839 return sys_fcntl(fd, cmd + F_GETLK - F_GETLK64, arg);
840 return sys32_fcntl(fd, cmd, arg);
843 extern asmlinkage long sys_truncate(const char * path, unsigned long length);
844 extern asmlinkage long sys_ftruncate(unsigned int fd, unsigned long length);
846 asmlinkage int sys32_truncate64(const char * path, unsigned long high, unsigned long low)
848 if ((int)high < 0)
849 return -EINVAL;
850 else
851 return sys_truncate(path, (high << 32) | low);
854 asmlinkage int sys32_ftruncate64(unsigned int fd, unsigned long high, unsigned long low)
856 if ((int)high < 0)
857 return -EINVAL;
858 else
859 return sys_ftruncate(fd, (high << 32) | low);
862 struct iovec32 { u32 iov_base; compat_size_t iov_len; };
864 typedef ssize_t (*io_fn_t)(struct file *, char *, size_t, loff_t *);
865 typedef ssize_t (*iov_fn_t)(struct file *, const struct iovec *, unsigned long, loff_t *);
867 static long do_readv_writev32(int type, struct file *file,
868 const struct iovec32 *vector, u32 count)
870 compat_ssize_t tot_len;
871 struct iovec iovstack[UIO_FASTIOV];
872 struct iovec *iov=iovstack, *ivp;
873 struct inode *inode;
874 long retval, i;
875 io_fn_t fn;
876 iov_fn_t fnv;
879 * SuS says "The readv() function *may* fail if the iovcnt argument
880 * was less than or equal to 0, or greater than {IOV_MAX}. Linux has
881 * traditionally returned zero for zero segments, so...
883 retval = 0;
884 if (count == 0)
885 goto out;
887 /* First get the "struct iovec" from user memory and
888 * verify all the pointers
890 retval = -EINVAL;
891 if (count > UIO_MAXIOV)
892 goto out;
893 if (!file->f_op)
894 goto out;
895 if (count > UIO_FASTIOV) {
896 retval = -ENOMEM;
897 iov = kmalloc(count*sizeof(struct iovec), GFP_KERNEL);
898 if (!iov)
899 goto out;
901 retval = -EFAULT;
902 if (verify_area(VERIFY_READ, vector, sizeof(struct iovec32)*count))
903 goto out;
906 * Single unix specification:
907 * We should -EINVAL if an element length is not >= 0 and fitting an
908 * ssize_t. The total length is fitting an ssize_t
910 * Be careful here because iov_len is a size_t not an ssize_t
912 tot_len = 0;
913 i = count;
914 ivp = iov;
915 retval = -EINVAL;
916 while(i > 0) {
917 compat_ssize_t tmp = tot_len;
918 compat_ssize_t len;
919 u32 buf;
921 if (__get_user(len, &vector->iov_len) ||
922 __get_user(buf, &vector->iov_base)) {
923 retval = -EFAULT;
924 goto out;
926 if (len < 0) /* size_t not fitting an ssize_t32 .. */
927 goto out;
928 tot_len += len;
929 if (tot_len < tmp) /* maths overflow on the compat_ssize_t */
930 goto out;
931 ivp->iov_base = (void *)A(buf);
932 ivp->iov_len = (__kernel_size_t) len;
933 vector++;
934 ivp++;
935 i--;
937 if (tot_len == 0) {
938 retval = 0;
939 goto out;
942 inode = file->f_dentry->d_inode;
943 /* VERIFY_WRITE actually means a read, as we write to user space */
944 retval = locks_verify_area((type == READ
945 ? FLOCK_VERIFY_READ : FLOCK_VERIFY_WRITE),
946 inode, file, file->f_pos, tot_len);
947 if (retval)
948 goto out;
950 if (type == READ) {
951 fn = file->f_op->read;
952 fnv = file->f_op->readv;
953 } else {
954 fn = (io_fn_t)file->f_op->write;
955 fnv = file->f_op->writev;
957 if (fnv) {
958 retval = fnv(file, iov, count, &file->f_pos);
959 goto out;
962 /* Do it by hand, with file-ops */
963 ivp = iov;
964 while (count > 0) {
965 void * base;
966 int len, nr;
968 base = ivp->iov_base;
969 len = ivp->iov_len;
970 ivp++;
971 count--;
973 nr = fn(file, base, len, &file->f_pos);
975 if (nr < 0) {
976 if (!retval)
977 retval = nr;
978 break;
980 retval += nr;
981 if (nr != len)
982 break;
984 out:
985 if (iov != iovstack)
986 kfree(iov);
987 if ((retval + (type == READ)) > 0)
988 dnotify_parent(file->f_dentry,
989 (type == READ) ? DN_ACCESS : DN_MODIFY);
991 return retval;
994 asmlinkage long sys32_readv(int fd, struct iovec32 *vector, u32 count)
996 struct file *file;
997 int ret;
999 file = fget(fd);
1000 if(!file)
1001 return -EBADF;
1003 ret = -EBADF;
1004 if (!(file->f_mode & FMODE_READ))
1005 goto out;
1006 ret = -EINVAL;
1007 if (!file->f_op || (!file->f_op->readv && !file->f_op->read))
1008 goto out;
1010 ret = do_readv_writev32(READ, file, vector, count);
1012 out:
1013 fput(file);
1014 return ret;
1017 asmlinkage long sys32_writev(int fd, struct iovec32 *vector, u32 count)
1019 struct file *file;
1020 int ret;
1022 file = fget(fd);
1023 if(!file)
1024 return -EBADF;
1026 ret = -EBADF;
1027 if (!(file->f_mode & FMODE_WRITE))
1028 goto out;
1029 ret = -EINVAL;
1030 if (!file->f_op || (!file->f_op->writev && !file->f_op->write))
1031 goto out;
1033 ret = do_readv_writev32(WRITE, file, vector, count);
1035 out:
1036 fput(file);
1037 return ret;
1040 /* readdir & getdents */
1042 #define NAME_OFFSET(de) ((int) ((de)->d_name - (char *) (de)))
1043 #define ROUND_UP(x) (((x)+sizeof(u32)-1) & ~(sizeof(u32)-1))
1045 struct old_linux_dirent32 {
1046 u32 d_ino;
1047 u32 d_offset;
1048 unsigned short d_namlen;
1049 char d_name[1];
1052 struct readdir_callback32 {
1053 struct old_linux_dirent32 * dirent;
1054 int count;
1057 static int fillonedir(void * __buf, const char * name, int namlen,
1058 loff_t offset, ino_t ino, unsigned int d_type)
1060 struct readdir_callback32 * buf = (struct readdir_callback32 *) __buf;
1061 struct old_linux_dirent32 * dirent;
1063 if (buf->count)
1064 return -EINVAL;
1065 buf->count++;
1066 dirent = buf->dirent;
1067 put_user(ino, &dirent->d_ino);
1068 put_user(offset, &dirent->d_offset);
1069 put_user(namlen, &dirent->d_namlen);
1070 copy_to_user(dirent->d_name, name, namlen);
1071 put_user(0, dirent->d_name + namlen);
1072 return 0;
1075 asmlinkage int old32_readdir(unsigned int fd, struct old_linux_dirent32 *dirent, unsigned int count)
1077 int error = -EBADF;
1078 struct file * file;
1079 struct readdir_callback32 buf;
1081 file = fget(fd);
1082 if (!file)
1083 goto out;
1085 buf.count = 0;
1086 buf.dirent = dirent;
1088 error = vfs_readdir(file, fillonedir, &buf);
1089 if (error < 0)
1090 goto out_putf;
1091 error = buf.count;
1093 out_putf:
1094 fput(file);
1095 out:
1096 return error;
1099 struct linux_dirent32 {
1100 u32 d_ino;
1101 u32 d_off;
1102 unsigned short d_reclen;
1103 char d_name[1];
1106 struct getdents_callback32 {
1107 struct linux_dirent32 * current_dir;
1108 struct linux_dirent32 * previous;
1109 int count;
1110 int error;
1113 static int filldir(void * __buf, const char * name, int namlen, loff_t offset, ino_t ino,
1114 unsigned int d_type)
1116 struct linux_dirent32 * dirent;
1117 struct getdents_callback32 * buf = (struct getdents_callback32 *) __buf;
1118 int reclen = ROUND_UP(NAME_OFFSET(dirent) + namlen + 1);
1120 buf->error = -EINVAL; /* only used if we fail.. */
1121 if (reclen > buf->count)
1122 return -EINVAL;
1123 dirent = buf->previous;
1124 if (dirent)
1125 put_user(offset, &dirent->d_off);
1126 dirent = buf->current_dir;
1127 buf->previous = dirent;
1128 put_user(ino, &dirent->d_ino);
1129 put_user(reclen, &dirent->d_reclen);
1130 copy_to_user(dirent->d_name, name, namlen);
1131 put_user(0, dirent->d_name + namlen);
1132 ((char *) dirent) += reclen;
1133 buf->current_dir = dirent;
1134 buf->count -= reclen;
1135 return 0;
1138 asmlinkage int sys32_getdents(unsigned int fd, struct linux_dirent32 *dirent, unsigned int count)
1140 struct file * file;
1141 struct linux_dirent32 * lastdirent;
1142 struct getdents_callback32 buf;
1143 int error = -EBADF;
1145 file = fget(fd);
1146 if (!file)
1147 goto out;
1149 buf.current_dir = dirent;
1150 buf.previous = NULL;
1151 buf.count = count;
1152 buf.error = 0;
1154 error = vfs_readdir(file, filldir, &buf);
1155 if (error < 0)
1156 goto out_putf;
1157 lastdirent = buf.previous;
1158 error = buf.error;
1159 if(lastdirent) {
1160 put_user(file->f_pos, &lastdirent->d_off);
1161 error = count - buf.count;
1163 out_putf:
1164 fput(file);
1165 out:
1166 return error;
1169 /* end of readdir & getdents */
1172 * Ooo, nasty. We need here to frob 32-bit unsigned longs to
1173 * 64-bit unsigned longs.
1176 static int get_fd_set32(unsigned long n, unsigned long *fdset, u32 *ufdset)
1178 if (ufdset) {
1179 unsigned long odd;
1181 if (verify_area(VERIFY_WRITE, ufdset, n*sizeof(u32)))
1182 return -EFAULT;
1184 odd = n & 1UL;
1185 n &= ~1UL;
1186 while (n) {
1187 unsigned long h, l;
1188 __get_user(l, ufdset);
1189 __get_user(h, ufdset+1);
1190 ufdset += 2;
1191 *fdset++ = h << 32 | l;
1192 n -= 2;
1194 if (odd)
1195 __get_user(*fdset, ufdset);
1196 } else {
1197 /* Tricky, must clear full unsigned long in the
1198 * kernel fdset at the end, this makes sure that
1199 * actually happens.
1201 memset(fdset, 0, ((n + 1) & ~1)*sizeof(u32));
1203 return 0;
1206 static void set_fd_set32(unsigned long n, u32 *ufdset, unsigned long *fdset)
1208 unsigned long odd;
1210 if (!ufdset)
1211 return;
1213 odd = n & 1UL;
1214 n &= ~1UL;
1215 while (n) {
1216 unsigned long h, l;
1217 l = *fdset++;
1218 h = l >> 32;
1219 __put_user(l, ufdset);
1220 __put_user(h, ufdset+1);
1221 ufdset += 2;
1222 n -= 2;
1224 if (odd)
1225 __put_user(*fdset, ufdset);
1228 #define MAX_SELECT_SECONDS \
1229 ((unsigned long) (MAX_SCHEDULE_TIMEOUT / HZ)-1)
1231 asmlinkage int sys32_select(int n, u32 *inp, u32 *outp, u32 *exp, u32 tvp_x)
1233 fd_set_bits fds;
1234 struct compat_timeval *tvp = (struct compat_timeval *)AA(tvp_x);
1235 char *bits;
1236 unsigned long nn;
1237 long timeout;
1238 int ret, size;
1240 timeout = MAX_SCHEDULE_TIMEOUT;
1241 if (tvp) {
1242 time_t sec, usec;
1244 if ((ret = verify_area(VERIFY_READ, tvp, sizeof(*tvp)))
1245 || (ret = __get_user(sec, &tvp->tv_sec))
1246 || (ret = __get_user(usec, &tvp->tv_usec)))
1247 goto out_nofds;
1249 ret = -EINVAL;
1250 if(sec < 0 || usec < 0)
1251 goto out_nofds;
1253 if ((unsigned long) sec < MAX_SELECT_SECONDS) {
1254 timeout = (usec + 1000000/HZ - 1) / (1000000/HZ);
1255 timeout += sec * (unsigned long) HZ;
1259 ret = -EINVAL;
1260 if (n < 0)
1261 goto out_nofds;
1262 if (n > current->files->max_fdset)
1263 n = current->files->max_fdset;
1266 * We need 6 bitmaps (in/out/ex for both incoming and outgoing),
1267 * since we used fdset we need to allocate memory in units of
1268 * long-words.
1270 ret = -ENOMEM;
1271 size = FDS_BYTES(n);
1272 bits = kmalloc(6 * size, GFP_KERNEL);
1273 if (!bits)
1274 goto out_nofds;
1275 fds.in = (unsigned long *) bits;
1276 fds.out = (unsigned long *) (bits + size);
1277 fds.ex = (unsigned long *) (bits + 2*size);
1278 fds.res_in = (unsigned long *) (bits + 3*size);
1279 fds.res_out = (unsigned long *) (bits + 4*size);
1280 fds.res_ex = (unsigned long *) (bits + 5*size);
1282 nn = (n + 8*sizeof(u32) - 1) / (8*sizeof(u32));
1283 if ((ret = get_fd_set32(nn, fds.in, inp)) ||
1284 (ret = get_fd_set32(nn, fds.out, outp)) ||
1285 (ret = get_fd_set32(nn, fds.ex, exp)))
1286 goto out;
1287 zero_fd_set(n, fds.res_in);
1288 zero_fd_set(n, fds.res_out);
1289 zero_fd_set(n, fds.res_ex);
1291 ret = do_select(n, &fds, &timeout);
1293 if (tvp && !(current->personality & STICKY_TIMEOUTS)) {
1294 time_t sec = 0, usec = 0;
1295 if (timeout) {
1296 sec = timeout / HZ;
1297 usec = timeout % HZ;
1298 usec *= (1000000/HZ);
1300 put_user(sec, &tvp->tv_sec);
1301 put_user(usec, &tvp->tv_usec);
1304 if (ret < 0)
1305 goto out;
1306 if (!ret) {
1307 ret = -ERESTARTNOHAND;
1308 if (signal_pending(current))
1309 goto out;
1310 ret = 0;
1313 set_fd_set32(nn, inp, fds.res_in);
1314 set_fd_set32(nn, outp, fds.res_out);
1315 set_fd_set32(nn, exp, fds.res_ex);
1317 out:
1318 kfree(bits);
1319 out_nofds:
1320 return ret;
1323 int cp_compat_stat(struct kstat *stat, struct compat_stat *statbuf)
1325 int err;
1327 if (stat->size > MAX_NON_LFS)
1328 return -EOVERFLOW;
1330 err = put_user(stat->dev, &statbuf->st_dev);
1331 err |= put_user(stat->ino, &statbuf->st_ino);
1332 err |= put_user(stat->mode, &statbuf->st_mode);
1333 err |= put_user(stat->nlink, &statbuf->st_nlink);
1334 err |= put_user(high2lowuid(stat->uid), &statbuf->st_uid);
1335 err |= put_user(high2lowgid(stat->gid), &statbuf->st_gid);
1336 err |= put_user(stat->rdev, &statbuf->st_rdev);
1337 err |= put_user(stat->size, &statbuf->st_size);
1338 err |= put_user(stat->atime.tv_sec, &statbuf->st_atime);
1339 err |= put_user(0, &statbuf->__unused1);
1340 err |= put_user(stat->mtime.tv_sec, &statbuf->st_mtime);
1341 err |= put_user(0, &statbuf->__unused2);
1342 err |= put_user(stat->ctime.tv_sec, &statbuf->st_ctime);
1343 err |= put_user(0, &statbuf->__unused3);
1344 err |= put_user(stat->blksize, &statbuf->st_blksize);
1345 err |= put_user(stat->blocks, &statbuf->st_blocks);
1346 err |= put_user(0, &statbuf->__unused4[0]);
1347 err |= put_user(0, &statbuf->__unused4[1]);
1349 return err;
1352 extern asmlinkage int sys_sysfs(int option, unsigned long arg1, unsigned long arg2);
1354 asmlinkage int sys32_sysfs(int option, u32 arg1, u32 arg2)
1356 return sys_sysfs(option, arg1, arg2);
1359 struct ncp_mount_data32_v3 {
1360 int version;
1361 unsigned int ncp_fd;
1362 compat_uid_t mounted_uid;
1363 compat_pid_t wdog_pid;
1364 unsigned char mounted_vol[NCP_VOLNAME_LEN + 1];
1365 unsigned int time_out;
1366 unsigned int retry_count;
1367 unsigned int flags;
1368 compat_uid_t uid;
1369 compat_gid_t gid;
1370 compat_mode_t file_mode;
1371 compat_mode_t dir_mode;
1374 struct ncp_mount_data32_v4 {
1375 int version;
1376 /* all members below are "long" in ABI ... i.e. 32bit on sparc32, while 64bits on sparc64 */
1377 unsigned int flags;
1378 unsigned int mounted_uid;
1379 int wdog_pid;
1381 unsigned int ncp_fd;
1382 unsigned int time_out;
1383 unsigned int retry_count;
1385 unsigned int uid;
1386 unsigned int gid;
1387 unsigned int file_mode;
1388 unsigned int dir_mode;
1391 static void *do_ncp_super_data_conv(void *raw_data)
1393 switch (*(int*)raw_data) {
1394 case NCP_MOUNT_VERSION:
1396 struct ncp_mount_data news, *n = &news;
1397 struct ncp_mount_data32_v3 *n32 = (struct ncp_mount_data32_v3 *)raw_data;
1399 n->version = n32->version;
1400 n->ncp_fd = n32->ncp_fd;
1401 n->mounted_uid = low2highuid(n32->mounted_uid);
1402 n->wdog_pid = n32->wdog_pid;
1403 memmove (n->mounted_vol, n32->mounted_vol, sizeof (n32->mounted_vol));
1404 n->time_out = n32->time_out;
1405 n->retry_count = n32->retry_count;
1406 n->flags = n32->flags;
1407 n->uid = low2highuid(n32->uid);
1408 n->gid = low2highgid(n32->gid);
1409 n->file_mode = n32->file_mode;
1410 n->dir_mode = n32->dir_mode;
1411 memcpy(raw_data, n, sizeof(*n));
1413 break;
1414 case NCP_MOUNT_VERSION_V4:
1416 struct ncp_mount_data_v4 news, *n = &news;
1417 struct ncp_mount_data32_v4 *n32 = (struct ncp_mount_data32_v4 *)raw_data;
1419 n->version = n32->version;
1420 n->flags = n32->flags;
1421 n->mounted_uid = n32->mounted_uid;
1422 n->wdog_pid = n32->wdog_pid;
1423 n->ncp_fd = n32->ncp_fd;
1424 n->time_out = n32->time_out;
1425 n->retry_count = n32->retry_count;
1426 n->uid = n32->uid;
1427 n->gid = n32->gid;
1428 n->file_mode = n32->file_mode;
1429 n->dir_mode = n32->dir_mode;
1430 memcpy(raw_data, n, sizeof(*n));
1432 break;
1433 default:
1434 /* do not touch unknown structures */
1435 break;
1437 return raw_data;
1440 struct smb_mount_data32 {
1441 int version;
1442 compat_uid_t mounted_uid;
1443 compat_uid_t uid;
1444 compat_gid_t gid;
1445 compat_mode_t file_mode;
1446 compat_mode_t dir_mode;
1449 static void *do_smb_super_data_conv(void *raw_data)
1451 struct smb_mount_data news, *s = &news;
1452 struct smb_mount_data32 *s32 = (struct smb_mount_data32 *)raw_data;
1454 if (s32->version != SMB_MOUNT_OLDVERSION)
1455 goto out;
1456 s->version = s32->version;
1457 s->mounted_uid = low2highuid(s32->mounted_uid);
1458 s->uid = low2highuid(s32->uid);
1459 s->gid = low2highgid(s32->gid);
1460 s->file_mode = s32->file_mode;
1461 s->dir_mode = s32->dir_mode;
1462 memcpy(raw_data, s, sizeof(struct smb_mount_data));
1463 out:
1464 return raw_data;
1467 static int copy_mount_stuff_to_kernel(const void *user, unsigned long *kernel)
1469 int i;
1470 unsigned long page;
1471 struct vm_area_struct *vma;
1473 *kernel = 0;
1474 if(!user)
1475 return 0;
1476 vma = find_vma(current->mm, (unsigned long)user);
1477 if(!vma || (unsigned long)user < vma->vm_start)
1478 return -EFAULT;
1479 if(!(vma->vm_flags & VM_READ))
1480 return -EFAULT;
1481 i = vma->vm_end - (unsigned long) user;
1482 if(PAGE_SIZE <= (unsigned long) i)
1483 i = PAGE_SIZE - 1;
1484 if(!(page = __get_free_page(GFP_KERNEL)))
1485 return -ENOMEM;
1486 if(copy_from_user((void *) page, user, i)) {
1487 free_page(page);
1488 return -EFAULT;
1490 *kernel = page;
1491 return 0;
1494 #define SMBFS_NAME "smbfs"
1495 #define NCPFS_NAME "ncpfs"
1497 asmlinkage int sys32_mount(char *dev_name, char *dir_name, char *type, unsigned long new_flags, u32 data)
1499 unsigned long type_page = 0;
1500 unsigned long data_page = 0;
1501 unsigned long dev_page = 0;
1502 unsigned long dir_page = 0;
1503 int err, is_smb, is_ncp;
1505 is_smb = is_ncp = 0;
1507 err = copy_mount_stuff_to_kernel((const void *)type, &type_page);
1508 if (err)
1509 goto out;
1511 if (!type_page) {
1512 err = -EINVAL;
1513 goto out;
1516 is_smb = !strcmp((char *)type_page, SMBFS_NAME);
1517 is_ncp = !strcmp((char *)type_page, NCPFS_NAME);
1519 err = copy_mount_stuff_to_kernel((const void *)AA(data), &data_page);
1520 if (err)
1521 goto type_out;
1523 err = copy_mount_stuff_to_kernel(dev_name, &dev_page);
1524 if (err)
1525 goto data_out;
1527 err = copy_mount_stuff_to_kernel(dir_name, &dir_page);
1528 if (err)
1529 goto dev_out;
1531 if (!is_smb && !is_ncp) {
1532 lock_kernel();
1533 err = do_mount((char*)dev_page, (char*)dir_page,
1534 (char*)type_page, new_flags, (char*)data_page);
1535 unlock_kernel();
1536 } else {
1537 if (is_ncp)
1538 do_ncp_super_data_conv((void *)data_page);
1539 else
1540 do_smb_super_data_conv((void *)data_page);
1542 lock_kernel();
1543 err = do_mount((char*)dev_page, (char*)dir_page,
1544 (char*)type_page, new_flags, (char*)data_page);
1545 unlock_kernel();
1547 free_page(dir_page);
1549 dev_out:
1550 free_page(dev_page);
1552 data_out:
1553 free_page(data_page);
1555 type_out:
1556 free_page(type_page);
1558 out:
1559 return err;
1562 struct rusage32 {
1563 struct compat_timeval ru_utime;
1564 struct compat_timeval ru_stime;
1565 s32 ru_maxrss;
1566 s32 ru_ixrss;
1567 s32 ru_idrss;
1568 s32 ru_isrss;
1569 s32 ru_minflt;
1570 s32 ru_majflt;
1571 s32 ru_nswap;
1572 s32 ru_inblock;
1573 s32 ru_oublock;
1574 s32 ru_msgsnd;
1575 s32 ru_msgrcv;
1576 s32 ru_nsignals;
1577 s32 ru_nvcsw;
1578 s32 ru_nivcsw;
1581 static int put_rusage (struct rusage32 *ru, struct rusage *r)
1583 int err;
1585 err = put_user (r->ru_utime.tv_sec, &ru->ru_utime.tv_sec);
1586 err |= __put_user (r->ru_utime.tv_usec, &ru->ru_utime.tv_usec);
1587 err |= __put_user (r->ru_stime.tv_sec, &ru->ru_stime.tv_sec);
1588 err |= __put_user (r->ru_stime.tv_usec, &ru->ru_stime.tv_usec);
1589 err |= __put_user (r->ru_maxrss, &ru->ru_maxrss);
1590 err |= __put_user (r->ru_ixrss, &ru->ru_ixrss);
1591 err |= __put_user (r->ru_idrss, &ru->ru_idrss);
1592 err |= __put_user (r->ru_isrss, &ru->ru_isrss);
1593 err |= __put_user (r->ru_minflt, &ru->ru_minflt);
1594 err |= __put_user (r->ru_majflt, &ru->ru_majflt);
1595 err |= __put_user (r->ru_nswap, &ru->ru_nswap);
1596 err |= __put_user (r->ru_inblock, &ru->ru_inblock);
1597 err |= __put_user (r->ru_oublock, &ru->ru_oublock);
1598 err |= __put_user (r->ru_msgsnd, &ru->ru_msgsnd);
1599 err |= __put_user (r->ru_msgrcv, &ru->ru_msgrcv);
1600 err |= __put_user (r->ru_nsignals, &ru->ru_nsignals);
1601 err |= __put_user (r->ru_nvcsw, &ru->ru_nvcsw);
1602 err |= __put_user (r->ru_nivcsw, &ru->ru_nivcsw);
1603 return err;
1606 asmlinkage int sys32_wait4(compat_pid_t pid, unsigned int *stat_addr, int options, struct rusage32 *ru)
1608 if (!ru)
1609 return sys_wait4(pid, stat_addr, options, NULL);
1610 else {
1611 struct rusage r;
1612 int ret;
1613 unsigned int status;
1614 mm_segment_t old_fs = get_fs();
1616 set_fs (KERNEL_DS);
1617 ret = sys_wait4(pid, stat_addr ? &status : NULL, options, &r);
1618 set_fs (old_fs);
1619 if (put_rusage (ru, &r)) return -EFAULT;
1620 if (stat_addr && put_user (status, stat_addr))
1621 return -EFAULT;
1622 return ret;
1626 struct sysinfo32 {
1627 s32 uptime;
1628 u32 loads[3];
1629 u32 totalram;
1630 u32 freeram;
1631 u32 sharedram;
1632 u32 bufferram;
1633 u32 totalswap;
1634 u32 freeswap;
1635 unsigned short procs;
1636 char _f[22];
1639 extern asmlinkage int sys_sysinfo(struct sysinfo *info);
1641 asmlinkage int sys32_sysinfo(struct sysinfo32 *info)
1643 struct sysinfo s;
1644 int ret, err;
1645 mm_segment_t old_fs = get_fs ();
1647 set_fs (KERNEL_DS);
1648 ret = sys_sysinfo(&s);
1649 set_fs (old_fs);
1650 err = put_user (s.uptime, &info->uptime);
1651 err |= __put_user (s.loads[0], &info->loads[0]);
1652 err |= __put_user (s.loads[1], &info->loads[1]);
1653 err |= __put_user (s.loads[2], &info->loads[2]);
1654 err |= __put_user (s.totalram, &info->totalram);
1655 err |= __put_user (s.freeram, &info->freeram);
1656 err |= __put_user (s.sharedram, &info->sharedram);
1657 err |= __put_user (s.bufferram, &info->bufferram);
1658 err |= __put_user (s.totalswap, &info->totalswap);
1659 err |= __put_user (s.freeswap, &info->freeswap);
1660 err |= __put_user (s.procs, &info->procs);
1661 if (err)
1662 return -EFAULT;
1663 return ret;
1666 extern asmlinkage int sys_sched_rr_get_interval(pid_t pid, struct timespec *interval);
1668 asmlinkage int sys32_sched_rr_get_interval(compat_pid_t pid, struct compat_timespec *interval)
1670 struct timespec t;
1671 int ret;
1672 mm_segment_t old_fs = get_fs ();
1674 set_fs (KERNEL_DS);
1675 ret = sys_sched_rr_get_interval(pid, &t);
1676 set_fs (old_fs);
1677 if (put_compat_timespec(&t, interval))
1678 return -EFAULT;
1679 return ret;
1682 extern asmlinkage int sys_sigprocmask(int how, old_sigset_t *set, old_sigset_t *oset);
1684 asmlinkage int sys32_sigprocmask(int how, old_sigset_t32 *set, old_sigset_t32 *oset)
1686 old_sigset_t s;
1687 int ret;
1688 mm_segment_t old_fs = get_fs();
1690 if (set && get_user (s, set)) return -EFAULT;
1691 set_fs (KERNEL_DS);
1692 ret = sys_sigprocmask(how, set ? &s : NULL, oset ? &s : NULL);
1693 set_fs (old_fs);
1694 if (ret) return ret;
1695 if (oset && put_user (s, oset)) return -EFAULT;
1696 return 0;
1699 extern asmlinkage int sys_rt_sigprocmask(int how, sigset_t *set, sigset_t *oset, size_t sigsetsize);
1701 asmlinkage int sys32_rt_sigprocmask(int how, sigset_t32 *set, sigset_t32 *oset, compat_size_t sigsetsize)
1703 sigset_t s;
1704 sigset_t32 s32;
1705 int ret;
1706 mm_segment_t old_fs = get_fs();
1708 if (set) {
1709 if (copy_from_user (&s32, set, sizeof(sigset_t32)))
1710 return -EFAULT;
1711 switch (_NSIG_WORDS) {
1712 case 4: s.sig[3] = s32.sig[6] | (((long)s32.sig[7]) << 32);
1713 case 3: s.sig[2] = s32.sig[4] | (((long)s32.sig[5]) << 32);
1714 case 2: s.sig[1] = s32.sig[2] | (((long)s32.sig[3]) << 32);
1715 case 1: s.sig[0] = s32.sig[0] | (((long)s32.sig[1]) << 32);
1718 set_fs (KERNEL_DS);
1719 ret = sys_rt_sigprocmask(how, set ? &s : NULL, oset ? &s : NULL, sigsetsize);
1720 set_fs (old_fs);
1721 if (ret) return ret;
1722 if (oset) {
1723 switch (_NSIG_WORDS) {
1724 case 4: s32.sig[7] = (s.sig[3] >> 32); s32.sig[6] = s.sig[3];
1725 case 3: s32.sig[5] = (s.sig[2] >> 32); s32.sig[4] = s.sig[2];
1726 case 2: s32.sig[3] = (s.sig[1] >> 32); s32.sig[2] = s.sig[1];
1727 case 1: s32.sig[1] = (s.sig[0] >> 32); s32.sig[0] = s.sig[0];
1729 if (copy_to_user (oset, &s32, sizeof(sigset_t32)))
1730 return -EFAULT;
1732 return 0;
1735 extern asmlinkage int sys_sigpending(old_sigset_t *set);
1737 asmlinkage int sys32_sigpending(old_sigset_t32 *set)
1739 old_sigset_t s;
1740 int ret;
1741 mm_segment_t old_fs = get_fs();
1743 set_fs (KERNEL_DS);
1744 ret = sys_sigpending(&s);
1745 set_fs (old_fs);
1746 if (put_user (s, set)) return -EFAULT;
1747 return ret;
1750 extern asmlinkage int sys_rt_sigpending(sigset_t *set, size_t sigsetsize);
1752 asmlinkage int sys32_rt_sigpending(sigset_t32 *set, compat_size_t sigsetsize)
1754 sigset_t s;
1755 sigset_t32 s32;
1756 int ret;
1757 mm_segment_t old_fs = get_fs();
1759 set_fs (KERNEL_DS);
1760 ret = sys_rt_sigpending(&s, sigsetsize);
1761 set_fs (old_fs);
1762 if (!ret) {
1763 switch (_NSIG_WORDS) {
1764 case 4: s32.sig[7] = (s.sig[3] >> 32); s32.sig[6] = s.sig[3];
1765 case 3: s32.sig[5] = (s.sig[2] >> 32); s32.sig[4] = s.sig[2];
1766 case 2: s32.sig[3] = (s.sig[1] >> 32); s32.sig[2] = s.sig[1];
1767 case 1: s32.sig[1] = (s.sig[0] >> 32); s32.sig[0] = s.sig[0];
1769 if (copy_to_user (set, &s32, sizeof(sigset_t32)))
1770 return -EFAULT;
1772 return ret;
1775 asmlinkage int
1776 sys32_rt_sigtimedwait(sigset_t32 *uthese, siginfo_t32 *uinfo,
1777 struct compat_timespec *uts, compat_size_t sigsetsize)
1779 int ret, sig;
1780 sigset_t these;
1781 sigset_t32 these32;
1782 struct timespec ts;
1783 siginfo_t info;
1784 long timeout = 0;
1786 /* XXX: Don't preclude handling different sized sigset_t's. */
1787 if (sigsetsize != sizeof(sigset_t))
1788 return -EINVAL;
1790 if (copy_from_user (&these32, uthese, sizeof(sigset_t32)))
1791 return -EFAULT;
1793 switch (_NSIG_WORDS) {
1794 case 4: these.sig[3] = these32.sig[6] | (((long)these32.sig[7]) << 32);
1795 case 3: these.sig[2] = these32.sig[4] | (((long)these32.sig[5]) << 32);
1796 case 2: these.sig[1] = these32.sig[2] | (((long)these32.sig[3]) << 32);
1797 case 1: these.sig[0] = these32.sig[0] | (((long)these32.sig[1]) << 32);
1801 * Invert the set of allowed signals to get those we
1802 * want to block.
1804 sigdelsetmask(&these, sigmask(SIGKILL)|sigmask(SIGSTOP));
1805 signotset(&these);
1807 if (uts) {
1808 if (get_compat_timespec(&ts, uts))
1809 return -EINVAL;
1810 if (ts.tv_nsec >= 1000000000L || ts.tv_nsec < 0
1811 || ts.tv_sec < 0)
1812 return -EINVAL;
1815 spin_lock_irq(&current->sig->siglock);
1816 sig = dequeue_signal(&these, &info);
1817 if (!sig) {
1818 timeout = MAX_SCHEDULE_TIMEOUT;
1819 if (uts)
1820 timeout = (timespec_to_jiffies(&ts)
1821 + (ts.tv_sec || ts.tv_nsec));
1823 if (timeout) {
1824 /* None ready -- temporarily unblock those we're
1825 * interested while we are sleeping in so that we'll
1826 * be awakened when they arrive. */
1827 current->real_blocked = current->blocked;
1828 sigandsets(&current->blocked, &current->blocked, &these);
1829 recalc_sigpending();
1830 spin_unlock_irq(&current->sig->siglock);
1832 current->state = TASK_INTERRUPTIBLE;
1833 timeout = schedule_timeout(timeout);
1835 spin_lock_irq(&current->sig->siglock);
1836 sig = dequeue_signal(&these, &info);
1837 current->blocked = current->real_blocked;
1838 siginitset(&current->real_blocked, 0);
1839 recalc_sigpending();
1842 spin_unlock_irq(&current->sig->siglock);
1844 if (sig) {
1845 ret = sig;
1846 if (uinfo) {
1847 if (copy_siginfo_to_user32(uinfo, &info))
1848 ret = -EFAULT;
1850 } else {
1851 ret = -EAGAIN;
1852 if (timeout)
1853 ret = -EINTR;
1856 return ret;
1859 extern asmlinkage int
1860 sys_rt_sigqueueinfo(int pid, int sig, siginfo_t *uinfo);
1862 asmlinkage int
1863 sys32_rt_sigqueueinfo(int pid, int sig, siginfo_t32 *uinfo)
1865 siginfo_t info;
1866 int ret;
1867 mm_segment_t old_fs = get_fs();
1869 if (copy_from_user (&info, uinfo, 3*sizeof(int)) ||
1870 copy_from_user (info._sifields._pad, uinfo->_sifields._pad, SI_PAD_SIZE))
1871 return -EFAULT;
1872 set_fs (KERNEL_DS);
1873 ret = sys_rt_sigqueueinfo(pid, sig, &info);
1874 set_fs (old_fs);
1875 return ret;
1878 #define RLIM_INFINITY32 0x7fffffff
1879 #define RESOURCE32(x) ((x > RLIM_INFINITY32) ? RLIM_INFINITY32 : x)
1881 struct rlimit32 {
1882 u32 rlim_cur;
1883 u32 rlim_max;
1886 extern asmlinkage int sys_getrlimit(unsigned int resource, struct rlimit *rlim);
1888 asmlinkage int sys32_getrlimit(unsigned int resource, struct rlimit32 *rlim)
1890 struct rlimit r;
1891 int ret;
1892 mm_segment_t old_fs = get_fs ();
1894 set_fs (KERNEL_DS);
1895 ret = sys_getrlimit(resource, &r);
1896 set_fs (old_fs);
1897 if (!ret) {
1898 ret = put_user (RESOURCE32(r.rlim_cur), &rlim->rlim_cur);
1899 ret |= __put_user (RESOURCE32(r.rlim_max), &rlim->rlim_max);
1901 return ret;
1904 extern asmlinkage int sys_setrlimit(unsigned int resource, struct rlimit *rlim);
1906 asmlinkage int sys32_setrlimit(unsigned int resource, struct rlimit32 *rlim)
1908 struct rlimit r;
1909 int ret;
1910 mm_segment_t old_fs = get_fs ();
1912 if (resource >= RLIM_NLIMITS) return -EINVAL;
1913 if (get_user (r.rlim_cur, &rlim->rlim_cur) ||
1914 __get_user (r.rlim_max, &rlim->rlim_max))
1915 return -EFAULT;
1916 if (r.rlim_cur == RLIM_INFINITY32)
1917 r.rlim_cur = RLIM_INFINITY;
1918 if (r.rlim_max == RLIM_INFINITY32)
1919 r.rlim_max = RLIM_INFINITY;
1920 set_fs (KERNEL_DS);
1921 ret = sys_setrlimit(resource, &r);
1922 set_fs (old_fs);
1923 return ret;
1926 extern asmlinkage int sys_getrusage(int who, struct rusage *ru);
1928 asmlinkage int sys32_getrusage(int who, struct rusage32 *ru)
1930 struct rusage r;
1931 int ret;
1932 mm_segment_t old_fs = get_fs();
1934 set_fs (KERNEL_DS);
1935 ret = sys_getrusage(who, &r);
1936 set_fs (old_fs);
1937 if (put_rusage (ru, &r)) return -EFAULT;
1938 return ret;
1941 /* XXX This really belongs in some header file... -DaveM */
1942 #define MAX_SOCK_ADDR 128 /* 108 for Unix domain -
1943 16 for IP, 16 for IPX,
1944 24 for IPv6,
1945 about 80 for AX.25 */
1947 struct msghdr32 {
1948 u32 msg_name;
1949 int msg_namelen;
1950 u32 msg_iov;
1951 compat_size_t msg_iovlen;
1952 u32 msg_control;
1953 compat_size_t msg_controllen;
1954 unsigned msg_flags;
1957 struct cmsghdr32 {
1958 compat_size_t cmsg_len;
1959 int cmsg_level;
1960 int cmsg_type;
1963 /* Bleech... */
1964 #define __CMSG32_NXTHDR(ctl, len, cmsg, cmsglen) __cmsg32_nxthdr((ctl),(len),(cmsg),(cmsglen))
1965 #define CMSG32_NXTHDR(mhdr, cmsg, cmsglen) cmsg32_nxthdr((mhdr), (cmsg), (cmsglen))
1967 #define CMSG32_ALIGN(len) ( ((len)+sizeof(int)-1) & ~(sizeof(int)-1) )
1969 #define CMSG32_DATA(cmsg) ((void *)((char *)(cmsg) + CMSG32_ALIGN(sizeof(struct cmsghdr32))))
1970 #define CMSG32_SPACE(len) (CMSG32_ALIGN(sizeof(struct cmsghdr32)) + CMSG32_ALIGN(len))
1971 #define CMSG32_LEN(len) (CMSG32_ALIGN(sizeof(struct cmsghdr32)) + (len))
1973 #define __CMSG32_FIRSTHDR(ctl,len) ((len) >= sizeof(struct cmsghdr32) ? \
1974 (struct cmsghdr32 *)(ctl) : \
1975 (struct cmsghdr32 *)NULL)
1976 #define CMSG32_FIRSTHDR(msg) __CMSG32_FIRSTHDR((msg)->msg_control, (msg)->msg_controllen)
1978 __inline__ struct cmsghdr32 *__cmsg32_nxthdr(void *__ctl, __kernel_size_t __size,
1979 struct cmsghdr32 *__cmsg, int __cmsg_len)
1981 struct cmsghdr32 * __ptr;
1983 __ptr = (struct cmsghdr32 *)(((unsigned char *) __cmsg) +
1984 CMSG32_ALIGN(__cmsg_len));
1985 if ((unsigned long)((char*)(__ptr+1) - (char *) __ctl) > __size)
1986 return NULL;
1988 return __ptr;
1991 __inline__ struct cmsghdr32 *cmsg32_nxthdr (struct msghdr *__msg,
1992 struct cmsghdr32 *__cmsg,
1993 int __cmsg_len)
1995 return __cmsg32_nxthdr(__msg->msg_control, __msg->msg_controllen,
1996 __cmsg, __cmsg_len);
1999 static inline int iov_from_user32_to_kern(struct iovec *kiov,
2000 struct iovec32 *uiov32,
2001 int niov)
2003 int tot_len = 0;
2005 while(niov > 0) {
2006 u32 len, buf;
2008 if(get_user(len, &uiov32->iov_len) ||
2009 get_user(buf, &uiov32->iov_base)) {
2010 tot_len = -EFAULT;
2011 break;
2013 tot_len += len;
2014 kiov->iov_base = (void *)A(buf);
2015 kiov->iov_len = (__kernel_size_t) len;
2016 uiov32++;
2017 kiov++;
2018 niov--;
2020 return tot_len;
2023 static int msghdr_from_user32_to_kern(struct msghdr *kmsg,
2024 struct msghdr32 *umsg)
2026 u32 tmp1, tmp2, tmp3;
2027 int err;
2029 err = get_user(tmp1, &umsg->msg_name);
2030 err |= __get_user(tmp2, &umsg->msg_iov);
2031 err |= __get_user(tmp3, &umsg->msg_control);
2032 if (err)
2033 return -EFAULT;
2035 kmsg->msg_name = (void *)A(tmp1);
2036 kmsg->msg_iov = (struct iovec *)A(tmp2);
2037 kmsg->msg_control = (void *)A(tmp3);
2039 err = get_user(kmsg->msg_namelen, &umsg->msg_namelen);
2040 err |= get_user(kmsg->msg_iovlen, &umsg->msg_iovlen);
2041 err |= get_user(kmsg->msg_controllen, &umsg->msg_controllen);
2042 err |= get_user(kmsg->msg_flags, &umsg->msg_flags);
2044 return err;
2047 /* I've named the args so it is easy to tell whose space the pointers are in. */
2048 static int verify_iovec32(struct msghdr *kern_msg, struct iovec *kern_iov,
2049 char *kern_address, int mode)
2051 int tot_len;
2053 if(kern_msg->msg_namelen) {
2054 if(mode==VERIFY_READ) {
2055 int err = move_addr_to_kernel(kern_msg->msg_name,
2056 kern_msg->msg_namelen,
2057 kern_address);
2058 if(err < 0)
2059 return err;
2061 kern_msg->msg_name = kern_address;
2062 } else
2063 kern_msg->msg_name = NULL;
2065 if(kern_msg->msg_iovlen > UIO_FASTIOV) {
2066 kern_iov = kmalloc(kern_msg->msg_iovlen * sizeof(struct iovec),
2067 GFP_KERNEL);
2068 if(!kern_iov)
2069 return -ENOMEM;
2072 tot_len = iov_from_user32_to_kern(kern_iov,
2073 (struct iovec32 *)kern_msg->msg_iov,
2074 kern_msg->msg_iovlen);
2075 if(tot_len >= 0)
2076 kern_msg->msg_iov = kern_iov;
2077 else if(kern_msg->msg_iovlen > UIO_FASTIOV)
2078 kfree(kern_iov);
2080 return tot_len;
2083 /* There is a lot of hair here because the alignment rules (and
2084 * thus placement) of cmsg headers and length are different for
2085 * 32-bit apps. -DaveM
2087 static int cmsghdr_from_user32_to_kern(struct msghdr *kmsg,
2088 unsigned char *stackbuf, int stackbuf_size)
2090 struct cmsghdr32 *ucmsg;
2091 struct cmsghdr *kcmsg, *kcmsg_base;
2092 compat_size_t ucmlen;
2093 __kernel_size_t kcmlen, tmp;
2095 kcmlen = 0;
2096 kcmsg_base = kcmsg = (struct cmsghdr *)stackbuf;
2097 ucmsg = CMSG32_FIRSTHDR(kmsg);
2098 while(ucmsg != NULL) {
2099 if(get_user(ucmlen, &ucmsg->cmsg_len))
2100 return -EFAULT;
2102 /* Catch bogons. */
2103 if(CMSG32_ALIGN(ucmlen) <
2104 CMSG32_ALIGN(sizeof(struct cmsghdr32)))
2105 return -EINVAL;
2106 if((unsigned long)(((char *)ucmsg - (char *)kmsg->msg_control)
2107 + ucmlen) > kmsg->msg_controllen)
2108 return -EINVAL;
2110 tmp = ((ucmlen - CMSG32_ALIGN(sizeof(*ucmsg))) +
2111 CMSG_ALIGN(sizeof(struct cmsghdr)));
2112 kcmlen += tmp;
2113 ucmsg = CMSG32_NXTHDR(kmsg, ucmsg, ucmlen);
2115 if(kcmlen == 0)
2116 return -EINVAL;
2118 /* The kcmlen holds the 64-bit version of the control length.
2119 * It may not be modified as we do not stick it into the kmsg
2120 * until we have successfully copied over all of the data
2121 * from the user.
2123 if(kcmlen > stackbuf_size)
2124 kcmsg_base = kcmsg = kmalloc(kcmlen, GFP_KERNEL);
2125 if(kcmsg == NULL)
2126 return -ENOBUFS;
2128 /* Now copy them over neatly. */
2129 memset(kcmsg, 0, kcmlen);
2130 ucmsg = CMSG32_FIRSTHDR(kmsg);
2131 while(ucmsg != NULL) {
2132 __get_user(ucmlen, &ucmsg->cmsg_len);
2133 tmp = ((ucmlen - CMSG32_ALIGN(sizeof(*ucmsg))) +
2134 CMSG_ALIGN(sizeof(struct cmsghdr)));
2135 kcmsg->cmsg_len = tmp;
2136 __get_user(kcmsg->cmsg_level, &ucmsg->cmsg_level);
2137 __get_user(kcmsg->cmsg_type, &ucmsg->cmsg_type);
2139 /* Copy over the data. */
2140 if(copy_from_user(CMSG_DATA(kcmsg),
2141 CMSG32_DATA(ucmsg),
2142 (ucmlen - CMSG32_ALIGN(sizeof(*ucmsg)))))
2143 goto out_free_efault;
2145 /* Advance. */
2146 kcmsg = (struct cmsghdr *)((char *)kcmsg + CMSG_ALIGN(tmp));
2147 ucmsg = CMSG32_NXTHDR(kmsg, ucmsg, ucmlen);
2150 /* Ok, looks like we made it. Hook it up and return success. */
2151 kmsg->msg_control = kcmsg_base;
2152 kmsg->msg_controllen = kcmlen;
2153 return 0;
2155 out_free_efault:
2156 if(kcmsg_base != (struct cmsghdr *)stackbuf)
2157 kfree(kcmsg_base);
2158 return -EFAULT;
2161 static void put_cmsg32(struct msghdr *kmsg, int level, int type,
2162 int len, void *data)
2164 struct cmsghdr32 *cm = (struct cmsghdr32 *) kmsg->msg_control;
2165 struct cmsghdr32 cmhdr;
2166 int cmlen = CMSG32_LEN(len);
2168 if(cm == NULL || kmsg->msg_controllen < sizeof(*cm)) {
2169 kmsg->msg_flags |= MSG_CTRUNC;
2170 return;
2173 if(kmsg->msg_controllen < cmlen) {
2174 kmsg->msg_flags |= MSG_CTRUNC;
2175 cmlen = kmsg->msg_controllen;
2177 cmhdr.cmsg_level = level;
2178 cmhdr.cmsg_type = type;
2179 cmhdr.cmsg_len = cmlen;
2181 if(copy_to_user(cm, &cmhdr, sizeof cmhdr))
2182 return;
2183 if(copy_to_user(CMSG32_DATA(cm), data, cmlen - sizeof(struct cmsghdr32)))
2184 return;
2185 cmlen = CMSG32_SPACE(len);
2186 kmsg->msg_control += cmlen;
2187 kmsg->msg_controllen -= cmlen;
2190 static void scm_detach_fds32(struct msghdr *kmsg, struct scm_cookie *scm)
2192 struct cmsghdr32 *cm = (struct cmsghdr32 *) kmsg->msg_control;
2193 int fdmax = (kmsg->msg_controllen - sizeof(struct cmsghdr32)) / sizeof(int);
2194 int fdnum = scm->fp->count;
2195 struct file **fp = scm->fp->fp;
2196 int *cmfptr;
2197 int err = 0, i;
2199 if (fdnum < fdmax)
2200 fdmax = fdnum;
2202 for (i = 0, cmfptr = (int *) CMSG32_DATA(cm); i < fdmax; i++, cmfptr++) {
2203 int new_fd;
2204 err = get_unused_fd();
2205 if (err < 0)
2206 break;
2207 new_fd = err;
2208 err = put_user(new_fd, cmfptr);
2209 if (err) {
2210 put_unused_fd(new_fd);
2211 break;
2213 /* Bump the usage count and install the file. */
2214 get_file(fp[i]);
2215 fd_install(new_fd, fp[i]);
2218 if (i > 0) {
2219 int cmlen = CMSG32_LEN(i * sizeof(int));
2220 if (!err)
2221 err = put_user(SOL_SOCKET, &cm->cmsg_level);
2222 if (!err)
2223 err = put_user(SCM_RIGHTS, &cm->cmsg_type);
2224 if (!err)
2225 err = put_user(cmlen, &cm->cmsg_len);
2226 if (!err) {
2227 cmlen = CMSG32_SPACE(i * sizeof(int));
2228 kmsg->msg_control += cmlen;
2229 kmsg->msg_controllen -= cmlen;
2232 if (i < fdnum)
2233 kmsg->msg_flags |= MSG_CTRUNC;
2236 * All of the files that fit in the message have had their
2237 * usage counts incremented, so we just free the list.
2239 __scm_destroy(scm);
2242 /* In these cases we (currently) can just copy to data over verbatim
2243 * because all CMSGs created by the kernel have well defined types which
2244 * have the same layout in both the 32-bit and 64-bit API. One must add
2245 * some special cased conversions here if we start sending control messages
2246 * with incompatible types.
2248 * SCM_RIGHTS and SCM_CREDENTIALS are done by hand in recvmsg32 right after
2249 * we do our work. The remaining cases are:
2251 * SOL_IP IP_PKTINFO struct in_pktinfo 32-bit clean
2252 * IP_TTL int 32-bit clean
2253 * IP_TOS __u8 32-bit clean
2254 * IP_RECVOPTS variable length 32-bit clean
2255 * IP_RETOPTS variable length 32-bit clean
2256 * (these last two are clean because the types are defined
2257 * by the IPv4 protocol)
2258 * IP_RECVERR struct sock_extended_err +
2259 * struct sockaddr_in 32-bit clean
2260 * SOL_IPV6 IPV6_RECVERR struct sock_extended_err +
2261 * struct sockaddr_in6 32-bit clean
2262 * IPV6_PKTINFO struct in6_pktinfo 32-bit clean
2263 * IPV6_HOPLIMIT int 32-bit clean
2264 * IPV6_FLOWINFO u32 32-bit clean
2265 * IPV6_HOPOPTS ipv6 hop exthdr 32-bit clean
2266 * IPV6_DSTOPTS ipv6 dst exthdr(s) 32-bit clean
2267 * IPV6_RTHDR ipv6 routing exthdr 32-bit clean
2268 * IPV6_AUTHHDR ipv6 auth exthdr 32-bit clean
2270 static void cmsg32_recvmsg_fixup(struct msghdr *kmsg, unsigned long orig_cmsg_uptr)
2272 unsigned char *workbuf, *wp;
2273 unsigned long bufsz, space_avail;
2274 struct cmsghdr *ucmsg;
2276 bufsz = ((unsigned long)kmsg->msg_control) - orig_cmsg_uptr;
2277 space_avail = kmsg->msg_controllen + bufsz;
2278 wp = workbuf = kmalloc(bufsz, GFP_KERNEL);
2279 if(workbuf == NULL)
2280 goto fail;
2282 /* To make this more sane we assume the kernel sends back properly
2283 * formatted control messages. Because of how the kernel will truncate
2284 * the cmsg_len for MSG_TRUNC cases, we need not check that case either.
2286 ucmsg = (struct cmsghdr *) orig_cmsg_uptr;
2287 while(((unsigned long)ucmsg) <=
2288 (((unsigned long)kmsg->msg_control) - sizeof(struct cmsghdr))) {
2289 struct cmsghdr32 *kcmsg32 = (struct cmsghdr32 *) wp;
2290 int clen64, clen32;
2292 /* UCMSG is the 64-bit format CMSG entry in user-space.
2293 * KCMSG32 is within the kernel space temporary buffer
2294 * we use to convert into a 32-bit style CMSG.
2296 __get_user(kcmsg32->cmsg_len, &ucmsg->cmsg_len);
2297 __get_user(kcmsg32->cmsg_level, &ucmsg->cmsg_level);
2298 __get_user(kcmsg32->cmsg_type, &ucmsg->cmsg_type);
2300 clen64 = kcmsg32->cmsg_len;
2301 if (kcmsg32->cmsg_level == SOL_SOCKET &&
2302 kcmsg32->cmsg_type == SO_TIMESTAMP) {
2303 struct timeval tv;
2304 struct compat_timeval *tv32;
2306 if (clen64 != CMSG_LEN(sizeof(struct timeval))) {
2307 kfree(workbuf);
2308 goto fail;
2310 copy_from_user(&tv, CMSG_DATA(ucmsg), sizeof(tv));
2311 tv32 = (struct compat_timeval *) CMSG32_DATA(kcmsg32);
2312 tv32->tv_sec = tv.tv_sec;
2313 tv32->tv_usec = tv.tv_usec;
2314 clen32 = sizeof(*tv32) +
2315 CMSG32_ALIGN(sizeof(struct cmsghdr32));
2316 } else {
2317 copy_from_user(CMSG32_DATA(kcmsg32), CMSG_DATA(ucmsg),
2318 clen64 - CMSG_ALIGN(sizeof(*ucmsg)));
2319 clen32 = ((clen64 - CMSG_ALIGN(sizeof(*ucmsg))) +
2320 CMSG32_ALIGN(sizeof(struct cmsghdr32)));
2322 kcmsg32->cmsg_len = clen32;
2324 ucmsg = (struct cmsghdr *) (((char *)ucmsg) + CMSG_ALIGN(clen64));
2325 wp = (((char *)kcmsg32) + CMSG32_ALIGN(clen32));
2328 /* Copy back fixed up data, and adjust pointers. */
2329 bufsz = (wp - workbuf);
2330 copy_to_user((void *)orig_cmsg_uptr, workbuf, bufsz);
2332 kmsg->msg_control = (struct cmsghdr *)
2333 (((char *)orig_cmsg_uptr) + bufsz);
2334 kmsg->msg_controllen = space_avail - bufsz;
2336 kfree(workbuf);
2337 return;
2339 fail:
2340 /* If we leave the 64-bit format CMSG chunks in there,
2341 * the application could get confused and crash. So to
2342 * ensure greater recovery, we report no CMSGs.
2344 kmsg->msg_controllen += bufsz;
2345 kmsg->msg_control = (void *) orig_cmsg_uptr;
2348 asmlinkage int sys32_sendmsg(int fd, struct msghdr32 *user_msg, unsigned user_flags)
2350 struct socket *sock;
2351 char address[MAX_SOCK_ADDR];
2352 struct iovec iov[UIO_FASTIOV];
2353 unsigned char ctl[sizeof(struct cmsghdr) + 20];
2354 unsigned char *ctl_buf = ctl;
2355 struct msghdr kern_msg;
2356 int err, total_len;
2358 if(msghdr_from_user32_to_kern(&kern_msg, user_msg))
2359 return -EFAULT;
2360 if(kern_msg.msg_iovlen > UIO_MAXIOV)
2361 return -EINVAL;
2362 err = verify_iovec32(&kern_msg, iov, address, VERIFY_READ);
2363 if (err < 0)
2364 goto out;
2365 total_len = err;
2367 if(kern_msg.msg_controllen) {
2368 err = cmsghdr_from_user32_to_kern(&kern_msg, ctl, sizeof(ctl));
2369 if(err)
2370 goto out_freeiov;
2371 ctl_buf = kern_msg.msg_control;
2373 kern_msg.msg_flags = user_flags;
2375 sock = sockfd_lookup(fd, &err);
2376 if (sock != NULL) {
2377 if (sock->file->f_flags & O_NONBLOCK)
2378 kern_msg.msg_flags |= MSG_DONTWAIT;
2379 err = sock_sendmsg(sock, &kern_msg, total_len);
2380 sockfd_put(sock);
2383 /* N.B. Use kfree here, as kern_msg.msg_controllen might change? */
2384 if(ctl_buf != ctl)
2385 kfree(ctl_buf);
2386 out_freeiov:
2387 if(kern_msg.msg_iov != iov)
2388 kfree(kern_msg.msg_iov);
2389 out:
2390 return err;
2393 asmlinkage int sys32_recvmsg(int fd, struct msghdr32 *user_msg, unsigned int user_flags)
2395 struct iovec iovstack[UIO_FASTIOV];
2396 struct msghdr kern_msg;
2397 char addr[MAX_SOCK_ADDR];
2398 struct socket *sock;
2399 struct iovec *iov = iovstack;
2400 struct sockaddr *uaddr;
2401 int *uaddr_len;
2402 unsigned long cmsg_ptr;
2403 int err, total_len, len = 0;
2405 if(msghdr_from_user32_to_kern(&kern_msg, user_msg))
2406 return -EFAULT;
2407 if(kern_msg.msg_iovlen > UIO_MAXIOV)
2408 return -EINVAL;
2410 uaddr = kern_msg.msg_name;
2411 uaddr_len = &user_msg->msg_namelen;
2412 err = verify_iovec32(&kern_msg, iov, addr, VERIFY_WRITE);
2413 if (err < 0)
2414 goto out;
2415 total_len = err;
2417 cmsg_ptr = (unsigned long) kern_msg.msg_control;
2418 kern_msg.msg_flags = 0;
2420 sock = sockfd_lookup(fd, &err);
2421 if (sock != NULL) {
2422 struct sock_iocb *si;
2423 struct kiocb iocb;
2425 if (sock->file->f_flags & O_NONBLOCK)
2426 user_flags |= MSG_DONTWAIT;
2428 init_sync_kiocb(&iocb, NULL);
2429 si = kiocb_to_siocb(&iocb);
2430 si->sock = sock;
2431 si->scm = &si->async_scm;
2432 si->msg = &kern_msg;
2433 si->size = total_len;
2434 si->flags = user_flags;
2435 memset(si->scm, 0, sizeof(*si->scm));
2437 err = sock->ops->recvmsg(&iocb, sock, &kern_msg, total_len,
2438 user_flags, si->scm);
2439 if (-EIOCBQUEUED == err)
2440 err = wait_on_sync_kiocb(&iocb);
2442 if(err >= 0) {
2443 len = err;
2444 if(!kern_msg.msg_control) {
2445 if(sock->passcred || si->scm->fp)
2446 kern_msg.msg_flags |= MSG_CTRUNC;
2447 if(si->scm->fp)
2448 __scm_destroy(si->scm);
2449 } else {
2450 /* If recvmsg processing itself placed some
2451 * control messages into user space, it's is
2452 * using 64-bit CMSG processing, so we need
2453 * to fix it up before we tack on more stuff.
2455 if((unsigned long) kern_msg.msg_control != cmsg_ptr)
2456 cmsg32_recvmsg_fixup(&kern_msg, cmsg_ptr);
2458 /* Wheee... */
2459 if(sock->passcred)
2460 put_cmsg32(&kern_msg,
2461 SOL_SOCKET, SCM_CREDENTIALS,
2462 sizeof(si->scm->creds),
2463 &si->scm->creds);
2464 if(si->scm->fp != NULL)
2465 scm_detach_fds32(&kern_msg, si->scm);
2468 sockfd_put(sock);
2471 if(uaddr != NULL && err >= 0)
2472 err = move_addr_to_user(addr, kern_msg.msg_namelen, uaddr, uaddr_len);
2473 if(cmsg_ptr != 0 && err >= 0) {
2474 unsigned long ucmsg_ptr = ((unsigned long)kern_msg.msg_control);
2475 compat_size_t uclen = (compat_size_t) (ucmsg_ptr - cmsg_ptr);
2476 err |= __put_user(uclen, &user_msg->msg_controllen);
2478 if(err >= 0)
2479 err = __put_user(kern_msg.msg_flags, &user_msg->msg_flags);
2480 if(kern_msg.msg_iov != iov)
2481 kfree(kern_msg.msg_iov);
2482 out:
2483 if(err < 0)
2484 return err;
2485 return len;
2488 extern asmlinkage int sys_setsockopt(int fd, int level, int optname,
2489 char *optval, int optlen);
2491 static int do_netfilter_replace(int fd, int level, int optname,
2492 char *optval, int optlen)
2494 struct ipt_replace32 {
2495 char name[IPT_TABLE_MAXNAMELEN];
2496 __u32 valid_hooks;
2497 __u32 num_entries;
2498 __u32 size;
2499 __u32 hook_entry[NF_IP_NUMHOOKS];
2500 __u32 underflow[NF_IP_NUMHOOKS];
2501 __u32 num_counters;
2502 __u32 counters;
2503 struct ipt_entry entries[0];
2504 } *repl32 = (struct ipt_replace32 *)optval;
2505 struct ipt_replace *krepl;
2506 struct ipt_counters *counters32;
2507 __u32 origsize;
2508 unsigned int kreplsize, kcountersize;
2509 mm_segment_t old_fs;
2510 int ret;
2512 if (optlen < sizeof(repl32))
2513 return -EINVAL;
2515 if (copy_from_user(&origsize,
2516 &repl32->size,
2517 sizeof(origsize)))
2518 return -EFAULT;
2520 kreplsize = sizeof(*krepl) + origsize;
2521 kcountersize = krepl->num_counters * sizeof(struct ipt_counters);
2523 /* Hack: Causes ipchains to give correct error msg --RR */
2524 if (optlen != kreplsize)
2525 return -ENOPROTOOPT;
2527 krepl = (struct ipt_replace *)kmalloc(kreplsize, GFP_KERNEL);
2528 if (krepl == NULL)
2529 return -ENOMEM;
2531 if (copy_from_user(krepl, optval, kreplsize)) {
2532 kfree(krepl);
2533 return -EFAULT;
2536 counters32 = (struct ipt_counters *)AA(
2537 ((struct ipt_replace32 *)krepl)->counters);
2539 kcountersize = krepl->num_counters * sizeof(struct ipt_counters);
2540 krepl->counters = (struct ipt_counters *)kmalloc(
2541 kcountersize, GFP_KERNEL);
2542 if (krepl->counters == NULL) {
2543 kfree(krepl);
2544 return -ENOMEM;
2547 old_fs = get_fs();
2548 set_fs(KERNEL_DS);
2549 ret = sys_setsockopt(fd, level, optname,
2550 (char *)krepl, kreplsize);
2551 set_fs(old_fs);
2553 if (ret == 0 &&
2554 copy_to_user(counters32, krepl->counters, kcountersize))
2555 ret = -EFAULT;
2557 kfree(krepl->counters);
2558 kfree(krepl);
2560 return ret;
2563 static int do_set_attach_filter(int fd, int level, int optname,
2564 char *optval, int optlen)
2566 struct sock_fprog32 {
2567 __u16 len;
2568 __u32 filter;
2569 } *fprog32 = (struct sock_fprog32 *)optval;
2570 struct sock_fprog kfprog;
2571 struct sock_filter *kfilter;
2572 unsigned int fsize;
2573 mm_segment_t old_fs;
2574 __u32 uptr;
2575 int ret;
2577 if (get_user(kfprog.len, &fprog32->len) ||
2578 __get_user(uptr, &fprog32->filter))
2579 return -EFAULT;
2581 kfprog.filter = (struct sock_filter *)A(uptr);
2582 fsize = kfprog.len * sizeof(struct sock_filter);
2584 kfilter = (struct sock_filter *)kmalloc(fsize, GFP_KERNEL);
2585 if (kfilter == NULL)
2586 return -ENOMEM;
2588 if (copy_from_user(kfilter, kfprog.filter, fsize)) {
2589 kfree(kfilter);
2590 return -EFAULT;
2593 kfprog.filter = kfilter;
2595 old_fs = get_fs();
2596 set_fs(KERNEL_DS);
2597 ret = sys_setsockopt(fd, level, optname,
2598 (char *)&kfprog, sizeof(kfprog));
2599 set_fs(old_fs);
2601 kfree(kfilter);
2603 return ret;
2606 static int do_set_icmpv6_filter(int fd, int level, int optname,
2607 char *optval, int optlen)
2609 struct icmp6_filter kfilter;
2610 mm_segment_t old_fs;
2611 int ret, i;
2613 if (copy_from_user(&kfilter, optval, sizeof(kfilter)))
2614 return -EFAULT;
2617 for (i = 0; i < 8; i += 2) {
2618 u32 tmp = kfilter.data[i];
2620 kfilter.data[i] = kfilter.data[i + 1];
2621 kfilter.data[i + 1] = tmp;
2624 old_fs = get_fs();
2625 set_fs(KERNEL_DS);
2626 ret = sys_setsockopt(fd, level, optname,
2627 (char *) &kfilter, sizeof(kfilter));
2628 set_fs(old_fs);
2630 return ret;
2633 static int do_set_sock_timeout(int fd, int level, int optname, char *optval, int optlen)
2635 struct compat_timeval *up = (struct compat_timeval *) optval;
2636 struct timeval ktime;
2637 mm_segment_t old_fs;
2638 int err;
2640 if (optlen < sizeof(*up))
2641 return -EINVAL;
2642 if (get_user(ktime.tv_sec, &up->tv_sec) ||
2643 __get_user(ktime.tv_usec, &up->tv_usec))
2644 return -EFAULT;
2645 old_fs = get_fs();
2646 set_fs(KERNEL_DS);
2647 err = sys_setsockopt(fd, level, optname, (char *) &ktime, sizeof(ktime));
2648 set_fs(old_fs);
2650 return err;
2653 asmlinkage int sys32_setsockopt(int fd, int level, int optname,
2654 char *optval, int optlen)
2656 if (optname == IPT_SO_SET_REPLACE)
2657 return do_netfilter_replace(fd, level, optname,
2658 optval, optlen);
2659 if (optname == SO_ATTACH_FILTER)
2660 return do_set_attach_filter(fd, level, optname,
2661 optval, optlen);
2662 if (optname == SO_RCVTIMEO || optname == SO_SNDTIMEO)
2663 return do_set_sock_timeout(fd, level, optname, optval, optlen);
2664 if (level == SOL_ICMPV6 && optname == ICMPV6_FILTER)
2665 return do_set_icmpv6_filter(fd, level, optname,
2666 optval, optlen);
2668 return sys_setsockopt(fd, level, optname, optval, optlen);
2671 extern asmlinkage long sys_getsockopt(int fd, int level, int optname,
2672 char *optval, int *optlen);
2674 static int do_get_sock_timeout(int fd, int level, int optname, char *optval, int *optlen)
2676 struct compat_timeval *up = (struct compat_timeval *) optval;
2677 struct timeval ktime;
2678 mm_segment_t old_fs;
2679 int len, err;
2681 if (get_user(len, optlen))
2682 return -EFAULT;
2683 if (len < sizeof(*up))
2684 return -EINVAL;
2685 len = sizeof(ktime);
2686 old_fs = get_fs();
2687 set_fs(KERNEL_DS);
2688 err = sys_getsockopt(fd, level, optname, (char *) &ktime, &len);
2689 set_fs(old_fs);
2691 if (!err) {
2692 if (put_user(sizeof(*up), optlen) ||
2693 put_user(ktime.tv_sec, &up->tv_sec) ||
2694 __put_user(ktime.tv_usec, &up->tv_usec))
2695 err = -EFAULT;
2697 return err;
2700 asmlinkage int sys32_getsockopt(int fd, int level, int optname,
2701 char *optval, int *optlen)
2703 if (optname == SO_RCVTIMEO || optname == SO_SNDTIMEO)
2704 return do_get_sock_timeout(fd, level, optname, optval, optlen);
2705 return sys_getsockopt(fd, level, optname, optval, optlen);
2708 extern void check_pending(int signum);
2710 asmlinkage int sys32_sigaction (int sig, struct old_sigaction32 *act, struct old_sigaction32 *oact)
2712 struct k_sigaction new_ka, old_ka;
2713 int ret;
2715 if (sig < 0) {
2716 set_thread_flag(TIF_NEWSIGNALS);
2717 sig = -sig;
2720 if (act) {
2721 old_sigset_t32 mask;
2723 ret = get_user((long)new_ka.sa.sa_handler, &act->sa_handler);
2724 ret |= __get_user((long)new_ka.sa.sa_restorer, &act->sa_restorer);
2725 ret |= __get_user(new_ka.sa.sa_flags, &act->sa_flags);
2726 ret |= __get_user(mask, &act->sa_mask);
2727 if (ret)
2728 return ret;
2729 new_ka.ka_restorer = NULL;
2730 siginitset(&new_ka.sa.sa_mask, mask);
2733 ret = do_sigaction(sig, act ? &new_ka : NULL, oact ? &old_ka : NULL);
2735 if (!ret && oact) {
2736 ret = put_user((long)old_ka.sa.sa_handler, &oact->sa_handler);
2737 ret |= __put_user((long)old_ka.sa.sa_restorer, &oact->sa_restorer);
2738 ret |= __put_user(old_ka.sa.sa_flags, &oact->sa_flags);
2739 ret |= __put_user(old_ka.sa.sa_mask.sig[0], &oact->sa_mask);
2742 return ret;
2745 asmlinkage int
2746 sys32_rt_sigaction(int sig, struct sigaction32 *act, struct sigaction32 *oact,
2747 void *restorer, compat_size_t sigsetsize)
2749 struct k_sigaction new_ka, old_ka;
2750 int ret;
2751 sigset_t32 set32;
2753 /* XXX: Don't preclude handling different sized sigset_t's. */
2754 if (sigsetsize != sizeof(sigset_t32))
2755 return -EINVAL;
2757 /* All tasks which use RT signals (effectively) use
2758 * new style signals.
2760 set_thread_flag(TIF_NEWSIGNALS);
2762 if (act) {
2763 new_ka.ka_restorer = restorer;
2764 ret = get_user((long)new_ka.sa.sa_handler, &act->sa_handler);
2765 ret |= __copy_from_user(&set32, &act->sa_mask, sizeof(sigset_t32));
2766 switch (_NSIG_WORDS) {
2767 case 4: new_ka.sa.sa_mask.sig[3] = set32.sig[6] | (((long)set32.sig[7]) << 32);
2768 case 3: new_ka.sa.sa_mask.sig[2] = set32.sig[4] | (((long)set32.sig[5]) << 32);
2769 case 2: new_ka.sa.sa_mask.sig[1] = set32.sig[2] | (((long)set32.sig[3]) << 32);
2770 case 1: new_ka.sa.sa_mask.sig[0] = set32.sig[0] | (((long)set32.sig[1]) << 32);
2772 ret |= __get_user(new_ka.sa.sa_flags, &act->sa_flags);
2773 ret |= __get_user((long)new_ka.sa.sa_restorer, &act->sa_restorer);
2774 if (ret)
2775 return -EFAULT;
2778 ret = do_sigaction(sig, act ? &new_ka : NULL, oact ? &old_ka : NULL);
2780 if (!ret && oact) {
2781 switch (_NSIG_WORDS) {
2782 case 4: set32.sig[7] = (old_ka.sa.sa_mask.sig[3] >> 32); set32.sig[6] = old_ka.sa.sa_mask.sig[3];
2783 case 3: set32.sig[5] = (old_ka.sa.sa_mask.sig[2] >> 32); set32.sig[4] = old_ka.sa.sa_mask.sig[2];
2784 case 2: set32.sig[3] = (old_ka.sa.sa_mask.sig[1] >> 32); set32.sig[2] = old_ka.sa.sa_mask.sig[1];
2785 case 1: set32.sig[1] = (old_ka.sa.sa_mask.sig[0] >> 32); set32.sig[0] = old_ka.sa.sa_mask.sig[0];
2787 ret = put_user((long)old_ka.sa.sa_handler, &oact->sa_handler);
2788 ret |= __copy_to_user(&oact->sa_mask, &set32, sizeof(sigset_t32));
2789 ret |= __put_user(old_ka.sa.sa_flags, &oact->sa_flags);
2790 ret |= __put_user((long)old_ka.sa.sa_restorer, &oact->sa_restorer);
2791 if (ret)
2792 ret = -EFAULT;
2795 return ret;
2800 * count32() counts the number of arguments/envelopes
2802 static int count32(u32 * argv, int max)
2804 int i = 0;
2806 if (argv != NULL) {
2807 for (;;) {
2808 u32 p; int error;
2810 error = get_user(p,argv);
2811 if (error)
2812 return error;
2813 if (!p)
2814 break;
2815 argv++;
2816 if (++i > max)
2817 return -E2BIG;
2820 return i;
2824 * 'copy_string32()' copies argument/envelope strings from user
2825 * memory to free pages in kernel mem. These are in a format ready
2826 * to be put directly into the top of new user memory.
2828 static int copy_strings32(int argc, u32 * argv, struct linux_binprm *bprm)
2830 while (argc-- > 0) {
2831 u32 str;
2832 int len;
2833 unsigned long pos;
2835 if (get_user(str, argv + argc) ||
2836 !str ||
2837 !(len = strnlen_user((char *)A(str), bprm->p)))
2838 return -EFAULT;
2840 if (bprm->p < len)
2841 return -E2BIG;
2843 bprm->p -= len;
2845 pos = bprm->p;
2846 while (len) {
2847 char *kaddr;
2848 struct page *page;
2849 int offset, bytes_to_copy, new, err;
2851 offset = pos % PAGE_SIZE;
2852 page = bprm->page[pos / PAGE_SIZE];
2853 new = 0;
2854 if (!page) {
2855 page = alloc_page(GFP_USER);
2856 bprm->page[pos / PAGE_SIZE] = page;
2857 if (!page)
2858 return -ENOMEM;
2859 new = 1;
2861 kaddr = kmap(page);
2863 if (new && offset)
2864 memset(kaddr, 0, offset);
2865 bytes_to_copy = PAGE_SIZE - offset;
2866 if (bytes_to_copy > len) {
2867 bytes_to_copy = len;
2868 if (new)
2869 memset(kaddr+offset+len, 0,
2870 PAGE_SIZE-offset-len);
2873 err = copy_from_user(kaddr + offset, (char *)A(str),
2874 bytes_to_copy);
2875 kunmap(page);
2877 if (err)
2878 return -EFAULT;
2880 pos += bytes_to_copy;
2881 str += bytes_to_copy;
2882 len -= bytes_to_copy;
2885 return 0;
2889 * sys32_execve() executes a new program.
2891 static inline int
2892 do_execve32(char * filename, u32 * argv, u32 * envp, struct pt_regs * regs)
2894 struct linux_binprm bprm;
2895 struct file * file;
2896 int retval;
2897 int i;
2899 file = open_exec(filename);
2901 retval = PTR_ERR(file);
2902 if (IS_ERR(file))
2903 return retval;
2905 bprm.p = PAGE_SIZE*MAX_ARG_PAGES-sizeof(void *);
2906 memset(bprm.page, 0, MAX_ARG_PAGES * sizeof(bprm.page[0]));
2908 bprm.file = file;
2909 bprm.filename = filename;
2910 bprm.sh_bang = 0;
2911 bprm.loader = 0;
2912 bprm.exec = 0;
2913 bprm.security = NULL;
2914 bprm.mm = mm_alloc();
2915 retval = -ENOMEM;
2916 if (!bprm.mm)
2917 goto out_file;
2919 retval = init_new_context(current, bprm.mm);
2920 if (retval < 0)
2921 goto out_mm;
2923 bprm.argc = count32(argv, bprm.p / sizeof(u32));
2924 if ((retval = bprm.argc) < 0)
2925 goto out_mm;
2927 bprm.envc = count32(envp, bprm.p / sizeof(u32));
2928 if ((retval = bprm.envc) < 0)
2929 goto out_mm;
2931 retval = security_bprm_alloc(&bprm);
2932 if (retval)
2933 goto out;
2935 retval = prepare_binprm(&bprm);
2936 if (retval < 0)
2937 goto out;
2939 retval = copy_strings_kernel(1, &bprm.filename, &bprm);
2940 if (retval < 0)
2941 goto out;
2943 bprm.exec = bprm.p;
2944 retval = copy_strings32(bprm.envc, envp, &bprm);
2945 if (retval < 0)
2946 goto out;
2948 retval = copy_strings32(bprm.argc, argv, &bprm);
2949 if (retval < 0)
2950 goto out;
2952 retval = search_binary_handler(&bprm, regs);
2953 if (retval >= 0) {
2954 /* execve success */
2955 security_bprm_free(&bprm);
2956 return retval;
2959 out:
2960 /* Something went wrong, return the inode and free the argument pages*/
2961 for (i = 0 ; i < MAX_ARG_PAGES ; i++) {
2962 struct page * page = bprm.page[i];
2963 if (page)
2964 __free_page(page);
2967 if (bprm.security)
2968 security_bprm_free(&bprm);
2970 out_mm:
2971 mmdrop(bprm.mm);
2973 out_file:
2974 if (bprm.file) {
2975 allow_write_access(bprm.file);
2976 fput(bprm.file);
2978 return retval;
2982 * sparc32_execve() executes a new program after the asm stub has set
2983 * things up for us. This should basically do what I want it to.
2985 asmlinkage int sparc32_execve(struct pt_regs *regs)
2987 int error, base = 0;
2988 char *filename;
2990 /* User register window flush is done by entry.S */
2992 /* Check for indirect call. */
2993 if((u32)regs->u_regs[UREG_G1] == 0)
2994 base = 1;
2996 filename = getname((char *)AA(regs->u_regs[base + UREG_I0]));
2997 error = PTR_ERR(filename);
2998 if(IS_ERR(filename))
2999 goto out;
3000 error = do_execve32(filename,
3001 (u32 *)AA((u32)regs->u_regs[base + UREG_I1]),
3002 (u32 *)AA((u32)regs->u_regs[base + UREG_I2]), regs);
3003 putname(filename);
3005 if(!error) {
3006 fprs_write(0);
3007 current_thread_info()->xfsr[0] = 0;
3008 current_thread_info()->fpsaved[0] = 0;
3009 regs->tstate &= ~TSTATE_PEF;
3010 current->ptrace &= ~PT_DTRACE;
3012 out:
3013 return error;
3016 #ifdef CONFIG_MODULES
3018 extern asmlinkage long sys_init_module(void *, unsigned long, const char *);
3020 asmlinkage int sys32_init_module(void *umod, u32 len, const char *uargs)
3022 return sys_init_module(umod, len, uargs);
3025 extern asmlinkage long sys_delete_module(const char *, unsigned int);
3027 asmlinkage int sys32_delete_module(const char *name_user, unsigned int flags)
3029 return sys_delete_module(name_user, flags);
3032 #else /* CONFIG_MODULES */
3034 asmlinkage int
3035 sys32_init_module(const char *name_user, struct module *mod_user)
3037 return -ENOSYS;
3040 asmlinkage int
3041 sys32_delete_module(const char *name_user)
3043 return -ENOSYS;
3046 #endif /* CONFIG_MODULES */
3048 #if defined(CONFIG_NFSD) || defined(CONFIG_NFSD_MODULE)
3049 /* Stuff for NFS server syscalls... */
3050 struct nfsctl_svc32 {
3051 u16 svc32_port;
3052 s32 svc32_nthreads;
3055 struct nfsctl_client32 {
3056 s8 cl32_ident[NFSCLNT_IDMAX+1];
3057 s32 cl32_naddr;
3058 struct in_addr cl32_addrlist[NFSCLNT_ADDRMAX];
3059 s32 cl32_fhkeytype;
3060 s32 cl32_fhkeylen;
3061 u8 cl32_fhkey[NFSCLNT_KEYMAX];
3064 struct nfsctl_export32 {
3065 s8 ex32_client[NFSCLNT_IDMAX+1];
3066 s8 ex32_path[NFS_MAXPATHLEN+1];
3067 compat_dev_t ex32_dev;
3068 compat_ino_t ex32_ino;
3069 s32 ex32_flags;
3070 compat_uid_t ex32_anon_uid;
3071 compat_gid_t ex32_anon_gid;
3074 struct nfsctl_uidmap32 {
3075 u32 ug32_ident; /* char * */
3076 compat_uid_t ug32_uidbase;
3077 s32 ug32_uidlen;
3078 u32 ug32_udimap; /* uid_t * */
3079 compat_uid_t ug32_gidbase;
3080 s32 ug32_gidlen;
3081 u32 ug32_gdimap; /* gid_t * */
3084 struct nfsctl_fhparm32 {
3085 struct sockaddr gf32_addr;
3086 compat_dev_t gf32_dev;
3087 compat_ino_t gf32_ino;
3088 s32 gf32_version;
3091 struct nfsctl_fdparm32 {
3092 struct sockaddr gd32_addr;
3093 s8 gd32_path[NFS_MAXPATHLEN+1];
3094 s32 gd32_version;
3097 struct nfsctl_fsparm32 {
3098 struct sockaddr gd32_addr;
3099 s8 gd32_path[NFS_MAXPATHLEN+1];
3100 s32 gd32_maxlen;
3103 struct nfsctl_arg32 {
3104 s32 ca32_version; /* safeguard */
3105 union {
3106 struct nfsctl_svc32 u32_svc;
3107 struct nfsctl_client32 u32_client;
3108 struct nfsctl_export32 u32_export;
3109 struct nfsctl_uidmap32 u32_umap;
3110 struct nfsctl_fhparm32 u32_getfh;
3111 struct nfsctl_fdparm32 u32_getfd;
3112 struct nfsctl_fsparm32 u32_getfs;
3113 } u;
3114 #define ca32_svc u.u32_svc
3115 #define ca32_client u.u32_client
3116 #define ca32_export u.u32_export
3117 #define ca32_umap u.u32_umap
3118 #define ca32_getfh u.u32_getfh
3119 #define ca32_getfd u.u32_getfd
3120 #define ca32_getfs u.u32_getfs
3121 #define ca32_authd u.u32_authd
3124 union nfsctl_res32 {
3125 __u8 cr32_getfh[NFS_FHSIZE];
3126 struct knfsd_fh cr32_getfs;
3129 static int nfs_svc32_trans(struct nfsctl_arg *karg, struct nfsctl_arg32 *arg32)
3131 int err;
3133 err = __get_user(karg->ca_version, &arg32->ca32_version);
3134 err |= __get_user(karg->ca_svc.svc_port, &arg32->ca32_svc.svc32_port);
3135 err |= __get_user(karg->ca_svc.svc_nthreads, &arg32->ca32_svc.svc32_nthreads);
3136 return err;
3139 static int nfs_clnt32_trans(struct nfsctl_arg *karg, struct nfsctl_arg32 *arg32)
3141 int err;
3143 err = __get_user(karg->ca_version, &arg32->ca32_version);
3144 err |= copy_from_user(&karg->ca_client.cl_ident[0],
3145 &arg32->ca32_client.cl32_ident[0],
3146 NFSCLNT_IDMAX);
3147 err |= __get_user(karg->ca_client.cl_naddr, &arg32->ca32_client.cl32_naddr);
3148 err |= copy_from_user(&karg->ca_client.cl_addrlist[0],
3149 &arg32->ca32_client.cl32_addrlist[0],
3150 (sizeof(struct in_addr) * NFSCLNT_ADDRMAX));
3151 err |= __get_user(karg->ca_client.cl_fhkeytype,
3152 &arg32->ca32_client.cl32_fhkeytype);
3153 err |= __get_user(karg->ca_client.cl_fhkeylen,
3154 &arg32->ca32_client.cl32_fhkeylen);
3155 err |= copy_from_user(&karg->ca_client.cl_fhkey[0],
3156 &arg32->ca32_client.cl32_fhkey[0],
3157 NFSCLNT_KEYMAX);
3158 return (err ? -EFAULT : 0);
3161 static int nfs_exp32_trans(struct nfsctl_arg *karg, struct nfsctl_arg32 *arg32)
3163 int err;
3165 err = __get_user(karg->ca_version, &arg32->ca32_version);
3166 err |= copy_from_user(&karg->ca_export.ex_client[0],
3167 &arg32->ca32_export.ex32_client[0],
3168 NFSCLNT_IDMAX);
3169 err |= copy_from_user(&karg->ca_export.ex_path[0],
3170 &arg32->ca32_export.ex32_path[0],
3171 NFS_MAXPATHLEN);
3172 err |= __get_user(karg->ca_export.ex_dev,
3173 &arg32->ca32_export.ex32_dev);
3174 err |= __get_user(karg->ca_export.ex_ino,
3175 &arg32->ca32_export.ex32_ino);
3176 err |= __get_user(karg->ca_export.ex_flags,
3177 &arg32->ca32_export.ex32_flags);
3178 err |= __get_user(karg->ca_export.ex_anon_uid,
3179 &arg32->ca32_export.ex32_anon_uid);
3180 err |= __get_user(karg->ca_export.ex_anon_gid,
3181 &arg32->ca32_export.ex32_anon_gid);
3182 karg->ca_export.ex_anon_uid = high2lowuid(karg->ca_export.ex_anon_uid);
3183 karg->ca_export.ex_anon_gid = high2lowgid(karg->ca_export.ex_anon_gid);
3184 return (err ? -EFAULT : 0);
3187 static int nfs_uud32_trans(struct nfsctl_arg *karg, struct nfsctl_arg32 *arg32)
3189 u32 uaddr;
3190 int i;
3191 int err;
3193 memset(karg, 0, sizeof(*karg));
3194 if(__get_user(karg->ca_version, &arg32->ca32_version))
3195 return -EFAULT;
3196 karg->ca_umap.ug_ident = (char *)get_zeroed_page(GFP_USER);
3197 if(!karg->ca_umap.ug_ident)
3198 return -ENOMEM;
3199 err = __get_user(uaddr, &arg32->ca32_umap.ug32_ident);
3200 if(strncpy_from_user(karg->ca_umap.ug_ident,
3201 (char *)A(uaddr), PAGE_SIZE) <= 0)
3202 return -EFAULT;
3203 err |= __get_user(karg->ca_umap.ug_uidbase,
3204 &arg32->ca32_umap.ug32_uidbase);
3205 err |= __get_user(karg->ca_umap.ug_uidlen,
3206 &arg32->ca32_umap.ug32_uidlen);
3207 err |= __get_user(uaddr, &arg32->ca32_umap.ug32_udimap);
3208 if (err)
3209 return -EFAULT;
3210 karg->ca_umap.ug_udimap = kmalloc((sizeof(uid_t) * karg->ca_umap.ug_uidlen),
3211 GFP_USER);
3212 if(!karg->ca_umap.ug_udimap)
3213 return -ENOMEM;
3214 for(i = 0; i < karg->ca_umap.ug_uidlen; i++)
3215 err |= __get_user(karg->ca_umap.ug_udimap[i],
3216 &(((compat_uid_t *)A(uaddr))[i]));
3217 err |= __get_user(karg->ca_umap.ug_gidbase,
3218 &arg32->ca32_umap.ug32_gidbase);
3219 err |= __get_user(karg->ca_umap.ug_uidlen,
3220 &arg32->ca32_umap.ug32_gidlen);
3221 err |= __get_user(uaddr, &arg32->ca32_umap.ug32_gdimap);
3222 if (err)
3223 return -EFAULT;
3224 karg->ca_umap.ug_gdimap = kmalloc((sizeof(gid_t) * karg->ca_umap.ug_uidlen),
3225 GFP_USER);
3226 if(!karg->ca_umap.ug_gdimap)
3227 return -ENOMEM;
3228 for(i = 0; i < karg->ca_umap.ug_gidlen; i++)
3229 err |= __get_user(karg->ca_umap.ug_gdimap[i],
3230 &(((compat_gid_t *)A(uaddr))[i]));
3232 return (err ? -EFAULT : 0);
3235 static int nfs_getfh32_trans(struct nfsctl_arg *karg, struct nfsctl_arg32 *arg32)
3237 int err;
3239 err = __get_user(karg->ca_version, &arg32->ca32_version);
3240 err |= copy_from_user(&karg->ca_getfh.gf_addr,
3241 &arg32->ca32_getfh.gf32_addr,
3242 (sizeof(struct sockaddr)));
3243 err |= __get_user(karg->ca_getfh.gf_dev,
3244 &arg32->ca32_getfh.gf32_dev);
3245 err |= __get_user(karg->ca_getfh.gf_ino,
3246 &arg32->ca32_getfh.gf32_ino);
3247 err |= __get_user(karg->ca_getfh.gf_version,
3248 &arg32->ca32_getfh.gf32_version);
3249 return (err ? -EFAULT : 0);
3252 static int nfs_getfd32_trans(struct nfsctl_arg *karg, struct nfsctl_arg32 *arg32)
3254 int err;
3256 err = __get_user(karg->ca_version, &arg32->ca32_version);
3257 err |= copy_from_user(&karg->ca_getfd.gd_addr,
3258 &arg32->ca32_getfd.gd32_addr,
3259 (sizeof(struct sockaddr)));
3260 err |= copy_from_user(&karg->ca_getfd.gd_path,
3261 &arg32->ca32_getfd.gd32_path,
3262 (NFS_MAXPATHLEN+1));
3263 err |= __get_user(karg->ca_getfd.gd_version,
3264 &arg32->ca32_getfd.gd32_version);
3265 return (err ? -EFAULT : 0);
3268 static int nfs_getfs32_trans(struct nfsctl_arg *karg, struct nfsctl_arg32 *arg32)
3270 int err;
3272 err = __get_user(karg->ca_version, &arg32->ca32_version);
3273 err |= copy_from_user(&karg->ca_getfs.gd_addr,
3274 &arg32->ca32_getfs.gd32_addr,
3275 (sizeof(struct sockaddr)));
3276 err |= copy_from_user(&karg->ca_getfs.gd_path,
3277 &arg32->ca32_getfs.gd32_path,
3278 (NFS_MAXPATHLEN+1));
3279 err |= __get_user(karg->ca_getfs.gd_maxlen,
3280 &arg32->ca32_getfs.gd32_maxlen);
3281 return (err ? -EFAULT : 0);
3284 /* This really doesn't need translations, we are only passing
3285 * back a union which contains opaque nfs file handle data.
3287 static int nfs_getfh32_res_trans(union nfsctl_res *kres, union nfsctl_res32 *res32)
3289 return (copy_to_user(res32, kres, sizeof(*res32)) ? -EFAULT : 0);
3292 int asmlinkage sys32_nfsservctl(int cmd, struct nfsctl_arg32 *arg32, union nfsctl_res32 *res32)
3294 struct nfsctl_arg *karg = NULL;
3295 union nfsctl_res *kres = NULL;
3296 mm_segment_t oldfs;
3297 int err;
3299 karg = kmalloc(sizeof(*karg), GFP_USER);
3300 if(!karg)
3301 return -ENOMEM;
3302 if(res32) {
3303 kres = kmalloc(sizeof(*kres), GFP_USER);
3304 if(!kres) {
3305 kfree(karg);
3306 return -ENOMEM;
3309 switch(cmd) {
3310 case NFSCTL_SVC:
3311 err = nfs_svc32_trans(karg, arg32);
3312 break;
3313 case NFSCTL_ADDCLIENT:
3314 err = nfs_clnt32_trans(karg, arg32);
3315 break;
3316 case NFSCTL_DELCLIENT:
3317 err = nfs_clnt32_trans(karg, arg32);
3318 break;
3319 case NFSCTL_EXPORT:
3320 case NFSCTL_UNEXPORT:
3321 err = nfs_exp32_trans(karg, arg32);
3322 break;
3323 /* This one is unimplemented, be we're ready for it. */
3324 case NFSCTL_UGIDUPDATE:
3325 err = nfs_uud32_trans(karg, arg32);
3326 break;
3327 case NFSCTL_GETFH:
3328 err = nfs_getfh32_trans(karg, arg32);
3329 break;
3330 case NFSCTL_GETFD:
3331 err = nfs_getfd32_trans(karg, arg32);
3332 break;
3333 case NFSCTL_GETFS:
3334 err = nfs_getfs32_trans(karg, arg32);
3335 break;
3336 default:
3337 err = -EINVAL;
3338 break;
3340 if(err)
3341 goto done;
3342 oldfs = get_fs();
3343 set_fs(KERNEL_DS);
3344 err = sys_nfsservctl(cmd, karg, kres);
3345 set_fs(oldfs);
3347 if (err)
3348 goto done;
3350 if((cmd == NFSCTL_GETFH) ||
3351 (cmd == NFSCTL_GETFD) ||
3352 (cmd == NFSCTL_GETFS))
3353 err = nfs_getfh32_res_trans(kres, res32);
3355 done:
3356 if(karg) {
3357 if(cmd == NFSCTL_UGIDUPDATE) {
3358 if(karg->ca_umap.ug_ident)
3359 kfree(karg->ca_umap.ug_ident);
3360 if(karg->ca_umap.ug_udimap)
3361 kfree(karg->ca_umap.ug_udimap);
3362 if(karg->ca_umap.ug_gdimap)
3363 kfree(karg->ca_umap.ug_gdimap);
3365 kfree(karg);
3367 if(kres)
3368 kfree(kres);
3369 return err;
3371 #else /* !NFSD */
3372 extern asmlinkage long sys_ni_syscall(void);
3373 int asmlinkage sys32_nfsservctl(int cmd, void *notused, void *notused2)
3375 return sys_ni_syscall();
3377 #endif
3379 /* Translations due to time_t size differences. Which affects all
3380 sorts of things, like timeval and itimerval. */
3382 extern struct timezone sys_tz;
3383 extern int do_sys_settimeofday(struct timeval *tv, struct timezone *tz);
3385 asmlinkage int sys32_gettimeofday(struct compat_timeval *tv, struct timezone *tz)
3387 if (tv) {
3388 struct timeval ktv;
3389 do_gettimeofday(&ktv);
3390 if (put_tv32(tv, &ktv))
3391 return -EFAULT;
3393 if (tz) {
3394 if (copy_to_user(tz, &sys_tz, sizeof(sys_tz)))
3395 return -EFAULT;
3397 return 0;
3400 asmlinkage int sys32_settimeofday(struct compat_timeval *tv, struct timezone *tz)
3402 struct timeval ktv;
3403 struct timezone ktz;
3405 if (tv) {
3406 if (get_tv32(&ktv, tv))
3407 return -EFAULT;
3409 if (tz) {
3410 if (copy_from_user(&ktz, tz, sizeof(ktz)))
3411 return -EFAULT;
3414 return do_sys_settimeofday(tv ? &ktv : NULL, tz ? &ktz : NULL);
3417 asmlinkage int sys32_utimes(char *filename, struct compat_timeval *tvs)
3419 char *kfilename;
3420 struct timeval ktvs[2];
3421 mm_segment_t old_fs;
3422 int ret;
3424 kfilename = getname(filename);
3425 ret = PTR_ERR(kfilename);
3426 if (!IS_ERR(kfilename)) {
3427 if (tvs) {
3428 if (get_tv32(&ktvs[0], tvs) ||
3429 get_tv32(&ktvs[1], 1+tvs))
3430 return -EFAULT;
3433 old_fs = get_fs();
3434 set_fs(KERNEL_DS);
3435 ret = do_utimes(kfilename, (tvs ? &ktvs[0] : NULL));
3436 set_fs(old_fs);
3438 putname(kfilename);
3440 return ret;
3443 /* These are here just in case some old sparc32 binary calls it. */
3444 asmlinkage int sys32_pause(void)
3446 current->state = TASK_INTERRUPTIBLE;
3447 schedule();
3448 return -ERESTARTNOHAND;
3451 /* PCI config space poking. */
3452 extern asmlinkage int sys_pciconfig_read(unsigned long bus,
3453 unsigned long dfn,
3454 unsigned long off,
3455 unsigned long len,
3456 unsigned char *buf);
3458 extern asmlinkage int sys_pciconfig_write(unsigned long bus,
3459 unsigned long dfn,
3460 unsigned long off,
3461 unsigned long len,
3462 unsigned char *buf);
3464 asmlinkage int sys32_pciconfig_read(u32 bus, u32 dfn, u32 off, u32 len, u32 ubuf)
3466 return sys_pciconfig_read((unsigned long) bus,
3467 (unsigned long) dfn,
3468 (unsigned long) off,
3469 (unsigned long) len,
3470 (unsigned char *)AA(ubuf));
3473 asmlinkage int sys32_pciconfig_write(u32 bus, u32 dfn, u32 off, u32 len, u32 ubuf)
3475 return sys_pciconfig_write((unsigned long) bus,
3476 (unsigned long) dfn,
3477 (unsigned long) off,
3478 (unsigned long) len,
3479 (unsigned char *)AA(ubuf));
3482 extern asmlinkage int sys_prctl(int option, unsigned long arg2, unsigned long arg3,
3483 unsigned long arg4, unsigned long arg5);
3485 asmlinkage int sys32_prctl(int option, u32 arg2, u32 arg3, u32 arg4, u32 arg5)
3487 return sys_prctl(option,
3488 (unsigned long) arg2,
3489 (unsigned long) arg3,
3490 (unsigned long) arg4,
3491 (unsigned long) arg5);
3495 extern asmlinkage ssize_t sys_pread64(unsigned int fd, char * buf,
3496 size_t count, loff_t pos);
3498 extern asmlinkage ssize_t sys_pwrite64(unsigned int fd, const char * buf,
3499 size_t count, loff_t pos);
3501 asmlinkage compat_ssize_t sys32_pread64(unsigned int fd, char *ubuf,
3502 compat_size_t count, u32 poshi, u32 poslo)
3504 return sys_pread64(fd, ubuf, count, ((loff_t)AA(poshi) << 32) | AA(poslo));
3507 asmlinkage compat_ssize_t sys32_pwrite64(unsigned int fd, char *ubuf,
3508 compat_size_t count, u32 poshi, u32 poslo)
3510 return sys_pwrite64(fd, ubuf, count, ((loff_t)AA(poshi) << 32) | AA(poslo));
3513 extern asmlinkage ssize_t sys_readahead(int fd, loff_t offset, size_t count);
3515 asmlinkage compat_ssize_t sys32_readahead(int fd, u32 offhi, u32 offlo, s32 count)
3517 return sys_readahead(fd, ((loff_t)AA(offhi) << 32) | AA(offlo), count);
3520 extern asmlinkage ssize_t sys_sendfile(int out_fd, int in_fd, off_t *offset, size_t count);
3522 asmlinkage int sys32_sendfile(int out_fd, int in_fd, compat_off_t *offset, s32 count)
3524 mm_segment_t old_fs = get_fs();
3525 int ret;
3526 off_t of;
3528 if (offset && get_user(of, offset))
3529 return -EFAULT;
3531 set_fs(KERNEL_DS);
3532 ret = sys_sendfile(out_fd, in_fd, offset ? &of : NULL, count);
3533 set_fs(old_fs);
3535 if (offset && put_user(of, offset))
3536 return -EFAULT;
3538 return ret;
3541 extern asmlinkage ssize_t sys_sendfile64(int out_fd, int in_fd, loff_t *offset, size_t count);
3543 asmlinkage int sys32_sendfile64(int out_fd, int in_fd, compat_loff_t *offset, s32 count)
3545 mm_segment_t old_fs = get_fs();
3546 int ret;
3547 loff_t lof;
3549 if (offset && get_user(lof, offset))
3550 return -EFAULT;
3552 set_fs(KERNEL_DS);
3553 ret = sys_sendfile64(out_fd, in_fd, offset ? &lof : NULL, count);
3554 set_fs(old_fs);
3556 if (offset && put_user(lof, offset))
3557 return -EFAULT;
3559 return ret;
3562 /* Handle adjtimex compatability. */
3564 struct timex32 {
3565 u32 modes;
3566 s32 offset, freq, maxerror, esterror;
3567 s32 status, constant, precision, tolerance;
3568 struct compat_timeval time;
3569 s32 tick;
3570 s32 ppsfreq, jitter, shift, stabil;
3571 s32 jitcnt, calcnt, errcnt, stbcnt;
3572 s32 :32; s32 :32; s32 :32; s32 :32;
3573 s32 :32; s32 :32; s32 :32; s32 :32;
3574 s32 :32; s32 :32; s32 :32; s32 :32;
3577 extern int do_adjtimex(struct timex *);
3579 asmlinkage int sys32_adjtimex(struct timex32 *utp)
3581 struct timex txc;
3582 int ret;
3584 memset(&txc, 0, sizeof(struct timex));
3586 if(get_user(txc.modes, &utp->modes) ||
3587 __get_user(txc.offset, &utp->offset) ||
3588 __get_user(txc.freq, &utp->freq) ||
3589 __get_user(txc.maxerror, &utp->maxerror) ||
3590 __get_user(txc.esterror, &utp->esterror) ||
3591 __get_user(txc.status, &utp->status) ||
3592 __get_user(txc.constant, &utp->constant) ||
3593 __get_user(txc.precision, &utp->precision) ||
3594 __get_user(txc.tolerance, &utp->tolerance) ||
3595 __get_user(txc.time.tv_sec, &utp->time.tv_sec) ||
3596 __get_user(txc.time.tv_usec, &utp->time.tv_usec) ||
3597 __get_user(txc.tick, &utp->tick) ||
3598 __get_user(txc.ppsfreq, &utp->ppsfreq) ||
3599 __get_user(txc.jitter, &utp->jitter) ||
3600 __get_user(txc.shift, &utp->shift) ||
3601 __get_user(txc.stabil, &utp->stabil) ||
3602 __get_user(txc.jitcnt, &utp->jitcnt) ||
3603 __get_user(txc.calcnt, &utp->calcnt) ||
3604 __get_user(txc.errcnt, &utp->errcnt) ||
3605 __get_user(txc.stbcnt, &utp->stbcnt))
3606 return -EFAULT;
3608 ret = do_adjtimex(&txc);
3610 if(put_user(txc.modes, &utp->modes) ||
3611 __put_user(txc.offset, &utp->offset) ||
3612 __put_user(txc.freq, &utp->freq) ||
3613 __put_user(txc.maxerror, &utp->maxerror) ||
3614 __put_user(txc.esterror, &utp->esterror) ||
3615 __put_user(txc.status, &utp->status) ||
3616 __put_user(txc.constant, &utp->constant) ||
3617 __put_user(txc.precision, &utp->precision) ||
3618 __put_user(txc.tolerance, &utp->tolerance) ||
3619 __put_user(txc.time.tv_sec, &utp->time.tv_sec) ||
3620 __put_user(txc.time.tv_usec, &utp->time.tv_usec) ||
3621 __put_user(txc.tick, &utp->tick) ||
3622 __put_user(txc.ppsfreq, &utp->ppsfreq) ||
3623 __put_user(txc.jitter, &utp->jitter) ||
3624 __put_user(txc.shift, &utp->shift) ||
3625 __put_user(txc.stabil, &utp->stabil) ||
3626 __put_user(txc.jitcnt, &utp->jitcnt) ||
3627 __put_user(txc.calcnt, &utp->calcnt) ||
3628 __put_user(txc.errcnt, &utp->errcnt) ||
3629 __put_user(txc.stbcnt, &utp->stbcnt))
3630 ret = -EFAULT;
3632 return ret;
3635 /* This is just a version for 32-bit applications which does
3636 * not force O_LARGEFILE on.
3639 asmlinkage long sparc32_open(const char * filename, int flags, int mode)
3641 char * tmp;
3642 int fd, error;
3644 tmp = getname(filename);
3645 fd = PTR_ERR(tmp);
3646 if (!IS_ERR(tmp)) {
3647 fd = get_unused_fd();
3648 if (fd >= 0) {
3649 struct file * f = filp_open(tmp, flags, mode);
3650 error = PTR_ERR(f);
3651 if (IS_ERR(f))
3652 goto out_error;
3653 fd_install(fd, f);
3655 out:
3656 putname(tmp);
3658 return fd;
3660 out_error:
3661 put_unused_fd(fd);
3662 fd = error;
3663 goto out;
3666 extern unsigned long do_mremap(unsigned long addr,
3667 unsigned long old_len, unsigned long new_len,
3668 unsigned long flags, unsigned long new_addr);
3670 asmlinkage unsigned long sys32_mremap(unsigned long addr,
3671 unsigned long old_len, unsigned long new_len,
3672 unsigned long flags, u32 __new_addr)
3674 struct vm_area_struct *vma;
3675 unsigned long ret = -EINVAL;
3676 unsigned long new_addr = AA(__new_addr);
3678 if (old_len > 0xf0000000UL || new_len > 0xf0000000UL)
3679 goto out;
3680 if (addr > 0xf0000000UL - old_len)
3681 goto out;
3682 down_write(&current->mm->mmap_sem);
3683 if (flags & MREMAP_FIXED) {
3684 if (new_addr > 0xf0000000UL - new_len)
3685 goto out_sem;
3686 } else if (addr > 0xf0000000UL - new_len) {
3687 unsigned long map_flags = 0;
3688 struct file *file = NULL;
3690 ret = -ENOMEM;
3691 if (!(flags & MREMAP_MAYMOVE))
3692 goto out_sem;
3694 vma = find_vma(current->mm, addr);
3695 if (vma) {
3696 if (vma->vm_flags & VM_SHARED)
3697 map_flags |= MAP_SHARED;
3698 file = vma->vm_file;
3701 /* MREMAP_FIXED checked above. */
3702 new_addr = get_unmapped_area(file, addr, new_len,
3703 vma ? vma->vm_pgoff : 0,
3704 map_flags);
3705 ret = new_addr;
3706 if (new_addr & ~PAGE_MASK)
3707 goto out_sem;
3708 flags |= MREMAP_FIXED;
3710 ret = do_mremap(addr, old_len, new_len, flags, new_addr);
3711 out_sem:
3712 up_write(&current->mm->mmap_sem);
3713 out:
3714 return ret;
3717 extern asmlinkage long sys_setpriority(int which, int who, int niceval);
3719 asmlinkage int sys_setpriority32(u32 which, u32 who, u32 niceval)
3721 return sys_setpriority((int) which,
3722 (int) who,
3723 (int) niceval);
3726 struct __sysctl_args32 {
3727 u32 name;
3728 int nlen;
3729 u32 oldval;
3730 u32 oldlenp;
3731 u32 newval;
3732 u32 newlen;
3733 u32 __unused[4];
3736 asmlinkage long sys32_sysctl(struct __sysctl_args32 *args)
3738 struct __sysctl_args32 tmp;
3739 int error;
3740 size_t oldlen, *oldlenp = NULL;
3741 unsigned long addr = (((long)&args->__unused[0]) + 7) & ~7;
3743 if (copy_from_user(&tmp, args, sizeof(tmp)))
3744 return -EFAULT;
3746 if (tmp.oldval && tmp.oldlenp) {
3747 /* Duh, this is ugly and might not work if sysctl_args
3748 is in read-only memory, but do_sysctl does indirectly
3749 a lot of uaccess in both directions and we'd have to
3750 basically copy the whole sysctl.c here, and
3751 glibc's __sysctl uses rw memory for the structure
3752 anyway. */
3753 if (get_user(oldlen, (u32 *)A(tmp.oldlenp)) ||
3754 put_user(oldlen, (size_t *)addr))
3755 return -EFAULT;
3756 oldlenp = (size_t *)addr;
3759 lock_kernel();
3760 error = do_sysctl((int *)A(tmp.name), tmp.nlen, (void *)A(tmp.oldval),
3761 oldlenp, (void *)A(tmp.newval), tmp.newlen);
3762 unlock_kernel();
3763 if (oldlenp) {
3764 if (!error) {
3765 if (get_user(oldlen, (size_t *)addr) ||
3766 put_user(oldlen, (u32 *)A(tmp.oldlenp)))
3767 error = -EFAULT;
3769 copy_to_user(args->__unused, tmp.__unused, sizeof(tmp.__unused));
3771 return error;
3774 extern asmlinkage int sys_sched_setaffinity(pid_t pid, unsigned int len,
3775 unsigned long *user_mask_ptr);
3777 asmlinkage int sys32_sched_setaffinity(compat_pid_t pid, unsigned int len,
3778 u32 *user_mask_ptr)
3780 unsigned long kernel_mask;
3781 mm_segment_t old_fs;
3782 int ret;
3784 if (get_user(kernel_mask, user_mask_ptr))
3785 return -EFAULT;
3787 old_fs = get_fs();
3788 set_fs(KERNEL_DS);
3789 ret = sys_sched_setaffinity(pid,
3790 /* XXX Nice api... */
3791 sizeof(kernel_mask),
3792 &kernel_mask);
3793 set_fs(old_fs);
3795 return ret;
3798 extern asmlinkage int sys_sched_getaffinity(pid_t pid, unsigned int len,
3799 unsigned long *user_mask_ptr);
3801 asmlinkage int sys32_sched_getaffinity(compat_pid_t pid, unsigned int len,
3802 u32 *user_mask_ptr)
3804 unsigned long kernel_mask;
3805 mm_segment_t old_fs;
3806 int ret;
3808 old_fs = get_fs();
3809 set_fs(KERNEL_DS);
3810 ret = sys_sched_getaffinity(pid,
3811 /* XXX Nice api... */
3812 sizeof(kernel_mask),
3813 &kernel_mask);
3814 set_fs(old_fs);
3816 if (ret > 0) {
3817 if (put_user(kernel_mask, user_mask_ptr))
3818 ret = -EFAULT;
3821 return ret;
3824 extern int sys_lookup_dcookie(u64 cookie64, char *buf, size_t len);
3826 int sys32_lookup_dcookie(u32 cookie_high, u32 cookie_low, char *buf, size_t len)
3828 return sys_lookup_dcookie((u64)cookie_high << 32 | cookie_low,
3829 buf, len);