1
2
3
4
5
6
7
8
9
10
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/utime.h>
19#include <linux/resource.h>
20#include <linux/times.h>
21#include <linux/utsname.h>
22#include <linux/timex.h>
23#include <linux/smp.h>
24#include <linux/smp_lock.h>
25#include <linux/sem.h>
26#include <linux/msg.h>
27#include <linux/shm.h>
28#include <linux/slab.h>
29#include <linux/uio.h>
30#include <linux/nfs_fs.h>
31#include <linux/smb_fs.h>
32#include <linux/smb_mount.h>
33#include <linux/ncp_fs.h>
34#include <linux/quota.h>
35#include <linux/quotacompat.h>
36#include <linux/module.h>
37#include <linux/sunrpc/svc.h>
38#include <linux/nfsd/nfsd.h>
39#include <linux/nfsd/cache.h>
40#include <linux/nfsd/xdr.h>
41#include <linux/nfsd/syscall.h>
42#include <linux/poll.h>
43#include <linux/personality.h>
44#include <linux/stat.h>
45#include <linux/filter.h>
46#include <linux/highmem.h>
47#include <linux/highuid.h>
48#include <linux/mman.h>
49#include <linux/ipv6.h>
50#include <linux/in.h>
51#include <linux/icmpv6.h>
52#include <linux/sysctl.h>
53#include <linux/dnotify.h>
54#include <linux/netfilter_ipv4/ip_tables.h>
55
56#include <asm/types.h>
57#include <asm/ipc.h>
58#include <asm/uaccess.h>
59#include <asm/fpumacro.h>
60#include <asm/semaphore.h>
61
62#include <net/scm.h>
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79#define A(__x) ((unsigned long)(__x))
80#define AA(__x) \
81({ unsigned long __ret; \
82 __asm__ ("srl %0, 0, %0" \
83 : "=r" (__ret) \
84 : "0" (__x)); \
85 __ret; \
86})
87
88extern asmlinkage long sys_chown(const char *, uid_t,gid_t);
89extern asmlinkage long sys_lchown(const char *, uid_t,gid_t);
90extern asmlinkage long sys_fchown(unsigned int, uid_t,gid_t);
91extern asmlinkage long sys_setregid(gid_t, gid_t);
92extern asmlinkage long sys_setgid(gid_t);
93extern asmlinkage long sys_setreuid(uid_t, uid_t);
94extern asmlinkage long sys_setuid(uid_t);
95extern asmlinkage long sys_setresuid(uid_t, uid_t, uid_t);
96extern asmlinkage long sys_setresgid(gid_t, gid_t, gid_t);
97extern asmlinkage long sys_setfsuid(uid_t);
98extern asmlinkage long sys_setfsgid(gid_t);
99
100
101
102#undef high2lowuid
103#undef high2lowgid
104#undef low2highuid
105#undef low2highgid
106#undef SET_UID16
107#undef SET_GID16
108#undef NEW_TO_OLD_UID
109#undef NEW_TO_OLD_GID
110#undef SET_OLDSTAT_UID
111#undef SET_OLDSTAT_GID
112#undef SET_STAT_UID
113#undef SET_STAT_GID
114
115#define high2lowuid(uid) ((uid) > 65535) ? (u16)overflowuid : (u16)(uid)
116#define high2lowgid(gid) ((gid) > 65535) ? (u16)overflowgid : (u16)(gid)
117#define low2highuid(uid) ((uid) == (u16)-1) ? (uid_t)-1 : (uid_t)(uid)
118#define low2highgid(gid) ((gid) == (u16)-1) ? (gid_t)-1 : (gid_t)(gid)
119#define SET_UID16(var, uid) var = high2lowuid(uid)
120#define SET_GID16(var, gid) var = high2lowgid(gid)
121#define NEW_TO_OLD_UID(uid) high2lowuid(uid)
122#define NEW_TO_OLD_GID(gid) high2lowgid(gid)
123#define SET_OLDSTAT_UID(stat, uid) (stat).st_uid = high2lowuid(uid)
124#define SET_OLDSTAT_GID(stat, gid) (stat).st_gid = high2lowgid(gid)
125#define SET_STAT_UID(stat, uid) (stat).st_uid = high2lowuid(uid)
126#define SET_STAT_GID(stat, gid) (stat).st_gid = high2lowgid(gid)
127
128asmlinkage long sys32_chown16(const char * filename, u16 user, u16 group)
129{
130 return sys_chown(filename, low2highuid(user), low2highgid(group));
131}
132
133asmlinkage long sys32_lchown16(const char * filename, u16 user, u16 group)
134{
135 return sys_lchown(filename, low2highuid(user), low2highgid(group));
136}
137
138asmlinkage long sys32_fchown16(unsigned int fd, u16 user, u16 group)
139{
140 return sys_fchown(fd, low2highuid(user), low2highgid(group));
141}
142
143asmlinkage long sys32_setregid16(u16 rgid, u16 egid)
144{
145 return sys_setregid(low2highgid(rgid), low2highgid(egid));
146}
147
148asmlinkage long sys32_setgid16(u16 gid)
149{
150 return sys_setgid((gid_t)gid);
151}
152
153asmlinkage long sys32_setreuid16(u16 ruid, u16 euid)
154{
155 return sys_setreuid(low2highuid(ruid), low2highuid(euid));
156}
157
158asmlinkage long sys32_setuid16(u16 uid)
159{
160 return sys_setuid((uid_t)uid);
161}
162
163asmlinkage long sys32_setresuid16(u16 ruid, u16 euid, u16 suid)
164{
165 return sys_setresuid(low2highuid(ruid), low2highuid(euid),
166 low2highuid(suid));
167}
168
169asmlinkage long sys32_getresuid16(u16 *ruid, u16 *euid, u16 *suid)
170{
171 int retval;
172
173 if (!(retval = put_user(high2lowuid(current->uid), ruid)) &&
174 !(retval = put_user(high2lowuid(current->euid), euid)))
175 retval = put_user(high2lowuid(current->suid), suid);
176
177 return retval;
178}
179
180asmlinkage long sys32_setresgid16(u16 rgid, u16 egid, u16 sgid)
181{
182 return sys_setresgid(low2highgid(rgid), low2highgid(egid),
183 low2highgid(sgid));
184}
185
186asmlinkage long sys32_getresgid16(u16 *rgid, u16 *egid, u16 *sgid)
187{
188 int retval;
189
190 if (!(retval = put_user(high2lowgid(current->gid), rgid)) &&
191 !(retval = put_user(high2lowgid(current->egid), egid)))
192 retval = put_user(high2lowgid(current->sgid), sgid);
193
194 return retval;
195}
196
197asmlinkage long sys32_setfsuid16(u16 uid)
198{
199 return sys_setfsuid((uid_t)uid);
200}
201
202asmlinkage long sys32_setfsgid16(u16 gid)
203{
204 return sys_setfsgid((gid_t)gid);
205}
206
207asmlinkage long sys32_getgroups16(int gidsetsize, u16 *grouplist)
208{
209 u16 groups[NGROUPS];
210 int i,j;
211
212 if (gidsetsize < 0)
213 return -EINVAL;
214 i = current->ngroups;
215 if (gidsetsize) {
216 if (i > gidsetsize)
217 return -EINVAL;
218 for(j=0;j<i;j++)
219 groups[j] = current->groups[j];
220 if (copy_to_user(grouplist, groups, sizeof(u16)*i))
221 return -EFAULT;
222 }
223 return i;
224}
225
226asmlinkage long sys32_setgroups16(int gidsetsize, u16 *grouplist)
227{
228 u16 groups[NGROUPS];
229 int i;
230
231 if (!capable(CAP_SETGID))
232 return -EPERM;
233 if ((unsigned) gidsetsize > NGROUPS)
234 return -EINVAL;
235 if (copy_from_user(groups, grouplist, gidsetsize * sizeof(u16)))
236 return -EFAULT;
237 for (i = 0 ; i < gidsetsize ; i++)
238 current->groups[i] = (gid_t)groups[i];
239 current->ngroups = gidsetsize;
240 return 0;
241}
242
243asmlinkage long sys32_getuid16(void)
244{
245 return high2lowuid(current->uid);
246}
247
248asmlinkage long sys32_geteuid16(void)
249{
250 return high2lowuid(current->euid);
251}
252
253asmlinkage long sys32_getgid16(void)
254{
255 return high2lowgid(current->gid);
256}
257
258asmlinkage long sys32_getegid16(void)
259{
260 return high2lowgid(current->egid);
261}
262
263
264
265struct timeval32
266{
267 int tv_sec, tv_usec;
268};
269
270struct itimerval32
271{
272 struct timeval32 it_interval;
273 struct timeval32 it_value;
274};
275
276static inline long get_tv32(struct timeval *o, struct timeval32 *i)
277{
278 return (!access_ok(VERIFY_READ, tv32, sizeof(*tv32)) ||
279 (__get_user(o->tv_sec, &i->tv_sec) |
280 __get_user(o->tv_usec, &i->tv_usec)));
281}
282
283static inline long put_tv32(struct timeval32 *o, struct timeval *i)
284{
285 return (!access_ok(VERIFY_WRITE, o, sizeof(*o)) ||
286 (__put_user(i->tv_sec, &o->tv_sec) |
287 __put_user(i->tv_usec, &o->tv_usec)));
288}
289
290static inline long get_it32(struct itimerval *o, struct itimerval32 *i)
291{
292 return (!access_ok(VERIFY_READ, i32, sizeof(*i32)) ||
293 (__get_user(o->it_interval.tv_sec, &i->it_interval.tv_sec) |
294 __get_user(o->it_interval.tv_usec, &i->it_interval.tv_usec) |
295 __get_user(o->it_value.tv_sec, &i->it_value.tv_sec) |
296 __get_user(o->it_value.tv_usec, &i->it_value.tv_usec)));
297}
298
299static inline long put_it32(struct itimerval32 *o, struct itimerval *i)
300{
301 return (!access_ok(VERIFY_WRITE, i32, sizeof(*i32)) ||
302 (__put_user(i->it_interval.tv_sec, &o->it_interval.tv_sec) |
303 __put_user(i->it_interval.tv_usec, &o->it_interval.tv_usec) |
304 __put_user(i->it_value.tv_sec, &o->it_value.tv_sec) |
305 __put_user(i->it_value.tv_usec, &o->it_value.tv_usec)));
306}
307
308extern asmlinkage int sys_ioperm(unsigned long from, unsigned long num, int on);
309
310asmlinkage int sys32_ioperm(u32 from, u32 num, int on)
311{
312 return sys_ioperm((unsigned long)from, (unsigned long)num, on);
313}
314
315struct msgbuf32 { s32 mtype; char mtext[1]; };
316
317struct ipc_perm32
318{
319 key_t key;
320 __kernel_uid_t32 uid;
321 __kernel_gid_t32 gid;
322 __kernel_uid_t32 cuid;
323 __kernel_gid_t32 cgid;
324 __kernel_mode_t32 mode;
325 unsigned short seq;
326};
327
328struct semid_ds32 {
329 struct ipc_perm32 sem_perm;
330 __kernel_time_t32 sem_otime;
331 __kernel_time_t32 sem_ctime;
332 u32 sem_base;
333 u32 sem_pending;
334 u32 sem_pending_last;
335 u32 undo;
336 unsigned short sem_nsems;
337};
338
339struct semid64_ds32 {
340 struct ipc64_perm sem_perm;
341 unsigned int __pad1;
342 __kernel_time_t32 sem_otime;
343 unsigned int __pad2;
344 __kernel_time_t32 sem_ctime;
345 u32 sem_nsems;
346 u32 __unused1;
347 u32 __unused2;
348};
349
350struct msqid_ds32
351{
352 struct ipc_perm32 msg_perm;
353 u32 msg_first;
354 u32 msg_last;
355 __kernel_time_t32 msg_stime;
356 __kernel_time_t32 msg_rtime;
357 __kernel_time_t32 msg_ctime;
358 u32 wwait;
359 u32 rwait;
360 unsigned short msg_cbytes;
361 unsigned short msg_qnum;
362 unsigned short msg_qbytes;
363 __kernel_ipc_pid_t32 msg_lspid;
364 __kernel_ipc_pid_t32 msg_lrpid;
365};
366
367struct msqid64_ds32 {
368 struct ipc64_perm msg_perm;
369 unsigned int __pad1;
370 __kernel_time_t32 msg_stime;
371 unsigned int __pad2;
372 __kernel_time_t32 msg_rtime;
373 unsigned int __pad3;
374 __kernel_time_t32 msg_ctime;
375 unsigned int msg_cbytes;
376 unsigned int msg_qnum;
377 unsigned int msg_qbytes;
378 __kernel_pid_t32 msg_lspid;
379 __kernel_pid_t32 msg_lrpid;
380 unsigned int __unused1;
381 unsigned int __unused2;
382};
383
384
385struct shmid_ds32 {
386 struct ipc_perm32 shm_perm;
387 int shm_segsz;
388 __kernel_time_t32 shm_atime;
389 __kernel_time_t32 shm_dtime;
390 __kernel_time_t32 shm_ctime;
391 __kernel_ipc_pid_t32 shm_cpid;
392 __kernel_ipc_pid_t32 shm_lpid;
393 unsigned short shm_nattch;
394};
395
396struct shmid64_ds32 {
397 struct ipc64_perm shm_perm;
398 unsigned int __pad1;
399 __kernel_time_t32 shm_atime;
400 unsigned int __pad2;
401 __kernel_time_t32 shm_dtime;
402 unsigned int __pad3;
403 __kernel_time_t32 shm_ctime;
404 __kernel_size_t32 shm_segsz;
405 __kernel_pid_t32 shm_cpid;
406 __kernel_pid_t32 shm_lpid;
407 unsigned int shm_nattch;
408 unsigned int __unused1;
409 unsigned int __unused2;
410};
411
412
413
414
415
416
417
418#define IPCOP_MASK(__x) (1UL << ((__x)&~IPC_64))
419static int do_sys32_semctl(int first, int second, int third, void *uptr)
420{
421 union semun fourth;
422 u32 pad;
423 int err = -EINVAL;
424
425 if (!uptr)
426 goto out;
427 err = -EFAULT;
428 if (get_user (pad, (u32 *)uptr))
429 goto out;
430 if ((third & ~IPC_64) == SETVAL)
431 fourth.val = (int)pad;
432 else
433 fourth.__pad = (void *)A(pad);
434 if (IPCOP_MASK (third) &
435 (IPCOP_MASK (IPC_INFO) | IPCOP_MASK (SEM_INFO) | IPCOP_MASK (GETVAL) |
436 IPCOP_MASK (GETPID) | IPCOP_MASK (GETNCNT) | IPCOP_MASK (GETZCNT) |
437 IPCOP_MASK (GETALL) | IPCOP_MASK (SETALL) | IPCOP_MASK (IPC_RMID))) {
438 err = sys_semctl (first, second, third, fourth);
439 } else if (third & IPC_64) {
440 struct semid64_ds s;
441 struct semid64_ds32 *usp = (struct semid64_ds32 *)A(pad);
442 mm_segment_t old_fs;
443 int need_back_translation;
444
445 if (third == (IPC_SET|IPC_64)) {
446 err = get_user (s.sem_perm.uid, &usp->sem_perm.uid);
447 err |= __get_user (s.sem_perm.gid, &usp->sem_perm.gid);
448 err |= __get_user (s.sem_perm.mode, &usp->sem_perm.mode);
449 if (err)
450 goto out;
451 fourth.__pad = &s;
452 }
453 need_back_translation =
454 (IPCOP_MASK (third) &
455 (IPCOP_MASK (SEM_STAT) | IPCOP_MASK (IPC_STAT))) != 0;
456 if (need_back_translation)
457 fourth.__pad = &s;
458 old_fs = get_fs ();
459 set_fs (KERNEL_DS);
460 err = sys_semctl (first, second, third, fourth);
461 set_fs (old_fs);
462 if (need_back_translation) {
463 int err2 = copy_to_user (&usp->sem_perm, &s.sem_perm, sizeof(struct ipc64_perm) + 2*sizeof(time_t));
464 err2 |= __put_user (s.sem_nsems, &usp->sem_nsems);
465 if (err2) err = -EFAULT;
466 }
467 } else {
468 struct semid_ds s;
469 struct semid_ds32 *usp = (struct semid_ds32 *)A(pad);
470 mm_segment_t old_fs;
471 int need_back_translation;
472
473 if (third == IPC_SET) {
474 err = get_user (s.sem_perm.uid, &usp->sem_perm.uid);
475 err |= __get_user (s.sem_perm.gid, &usp->sem_perm.gid);
476 err |= __get_user (s.sem_perm.mode, &usp->sem_perm.mode);
477 if (err)
478 goto out;
479 fourth.__pad = &s;
480 }
481 need_back_translation =
482 (IPCOP_MASK (third) &
483 (IPCOP_MASK (SEM_STAT) | IPCOP_MASK (IPC_STAT))) != 0;
484 if (need_back_translation)
485 fourth.__pad = &s;
486 old_fs = get_fs ();
487 set_fs (KERNEL_DS);
488 err = sys_semctl (first, second, third, fourth);
489 set_fs (old_fs);
490 if (need_back_translation) {
491 int err2 = put_user (s.sem_perm.key, &usp->sem_perm.key);
492 err2 |= __put_user (high2lowuid(s.sem_perm.uid), &usp->sem_perm.uid);
493 err2 |= __put_user (high2lowgid(s.sem_perm.gid), &usp->sem_perm.gid);
494 err2 |= __put_user (high2lowuid(s.sem_perm.cuid), &usp->sem_perm.cuid);
495 err2 |= __put_user (high2lowgid(s.sem_perm.cgid), &usp->sem_perm.cgid);
496 err2 |= __put_user (s.sem_perm.mode, &usp->sem_perm.mode);
497 err2 |= __put_user (s.sem_perm.seq, &usp->sem_perm.seq);
498 err2 |= __put_user (s.sem_otime, &usp->sem_otime);
499 err2 |= __put_user (s.sem_ctime, &usp->sem_ctime);
500 err2 |= __put_user (s.sem_nsems, &usp->sem_nsems);
501 if (err2) err = -EFAULT;
502 }
503 }
504out:
505 return err;
506}
507
508static int do_sys32_msgsnd (int first, int second, int third, void *uptr)
509{
510 struct msgbuf *p = kmalloc (second + sizeof (struct msgbuf), GFP_USER);
511 struct msgbuf32 *up = (struct msgbuf32 *)uptr;
512 mm_segment_t old_fs;
513 int err;
514
515 if (!p)
516 return -ENOMEM;
517 err = -EFAULT;
518 if (get_user (p->mtype, &up->mtype) ||
519 __copy_from_user (p->mtext, &up->mtext, second))
520 goto out;
521 old_fs = get_fs ();
522 set_fs (KERNEL_DS);
523 err = sys_msgsnd (first, p, second, third);
524 set_fs (old_fs);
525out:
526 kfree (p);
527 return err;
528}
529
530static int do_sys32_msgrcv (int first, int second, int msgtyp, int third,
531 int version, void *uptr)
532{
533 struct msgbuf32 *up;
534 struct msgbuf *p;
535 mm_segment_t old_fs;
536 int err;
537
538 if (!version) {
539 struct ipc_kludge *uipck = (struct ipc_kludge *)uptr;
540 struct ipc_kludge ipck;
541
542 err = -EINVAL;
543 if (!uptr)
544 goto out;
545 err = -EFAULT;
546 if (copy_from_user (&ipck, uipck, sizeof (struct ipc_kludge)))
547 goto out;
548 uptr = (void *)A(ipck.msgp);
549 msgtyp = ipck.msgtyp;
550 }
551 err = -ENOMEM;
552 p = kmalloc (second + sizeof (struct msgbuf), GFP_USER);
553 if (!p)
554 goto out;
555 old_fs = get_fs ();
556 set_fs (KERNEL_DS);
557 err = sys_msgrcv (first, p, second, msgtyp, third);
558 set_fs (old_fs);
559 if (err < 0)
560 goto free_then_out;
561 up = (struct msgbuf32 *)uptr;
562 if (put_user (p->mtype, &up->mtype) ||
563 __copy_to_user (&up->mtext, p->mtext, err))
564 err = -EFAULT;
565free_then_out:
566 kfree (p);
567out:
568 return err;
569}
570
571static int do_sys32_msgctl (int first, int second, void *uptr)
572{
573 int err;
574
575 if (IPCOP_MASK (second) &
576 (IPCOP_MASK (IPC_INFO) | IPCOP_MASK (MSG_INFO) |
577 IPCOP_MASK (IPC_RMID))) {
578 err = sys_msgctl (first, second, (struct msqid_ds *)uptr);
579 } else if (second & IPC_64) {
580 struct msqid64_ds m;
581 struct msqid64_ds32 *up = (struct msqid64_ds32 *)uptr;
582 mm_segment_t old_fs;
583
584 if (second == (IPC_SET|IPC_64)) {
585 err = get_user (m.msg_perm.uid, &up->msg_perm.uid);
586 err |= __get_user (m.msg_perm.gid, &up->msg_perm.gid);
587 err |= __get_user (m.msg_perm.mode, &up->msg_perm.mode);
588 err |= __get_user (m.msg_qbytes, &up->msg_qbytes);
589 if (err)
590 goto out;
591 }
592 old_fs = get_fs ();
593 set_fs (KERNEL_DS);
594 err = sys_msgctl (first, second, (struct msqid_ds *)&m);
595 set_fs (old_fs);
596 if (IPCOP_MASK (second) &
597 (IPCOP_MASK (MSG_STAT) | IPCOP_MASK (IPC_STAT))) {
598 int err2 = copy_to_user(&up->msg_perm, &m.msg_perm, sizeof(struct ipc64_perm) + 3*sizeof(time_t));
599 err2 |= __put_user (m.msg_cbytes, &up->msg_cbytes);
600 err2 |= __put_user (m.msg_qnum, &up->msg_qnum);
601 err2 |= __put_user (m.msg_qbytes, &up->msg_qbytes);
602 err2 |= __put_user (m.msg_lspid, &up->msg_lspid);
603 err2 |= __put_user (m.msg_lrpid, &up->msg_lrpid);
604 if (err2)
605 err = -EFAULT;
606 }
607 } else {
608 struct msqid_ds m;
609 struct msqid_ds32 *up = (struct msqid_ds32 *)uptr;
610 mm_segment_t old_fs;
611
612 if (second == IPC_SET) {
613 err = get_user (m.msg_perm.uid, &up->msg_perm.uid);
614 err |= __get_user (m.msg_perm.gid, &up->msg_perm.gid);
615 err |= __get_user (m.msg_perm.mode, &up->msg_perm.mode);
616 err |= __get_user (m.msg_qbytes, &up->msg_qbytes);
617 if (err)
618 goto out;
619 }
620 old_fs = get_fs ();
621 set_fs (KERNEL_DS);
622 err = sys_msgctl (first, second, &m);
623 set_fs (old_fs);
624 if (IPCOP_MASK (second) &
625 (IPCOP_MASK (MSG_STAT) | IPCOP_MASK (IPC_STAT))) {
626 int err2 = put_user (m.msg_perm.key, &up->msg_perm.key);
627 err2 |= __put_user (high2lowuid(m.msg_perm.uid), &up->msg_perm.uid);
628 err2 |= __put_user (high2lowgid(m.msg_perm.gid), &up->msg_perm.gid);
629 err2 |= __put_user (high2lowuid(m.msg_perm.cuid), &up->msg_perm.cuid);
630 err2 |= __put_user (high2lowgid(m.msg_perm.cgid), &up->msg_perm.cgid);
631 err2 |= __put_user (m.msg_perm.mode, &up->msg_perm.mode);
632 err2 |= __put_user (m.msg_perm.seq, &up->msg_perm.seq);
633 err2 |= __put_user (m.msg_stime, &up->msg_stime);
634 err2 |= __put_user (m.msg_rtime, &up->msg_rtime);
635 err2 |= __put_user (m.msg_ctime, &up->msg_ctime);
636 err2 |= __put_user (m.msg_cbytes, &up->msg_cbytes);
637 err2 |= __put_user (m.msg_qnum, &up->msg_qnum);
638 err2 |= __put_user (m.msg_qbytes, &up->msg_qbytes);
639 err2 |= __put_user (m.msg_lspid, &up->msg_lspid);
640 err2 |= __put_user (m.msg_lrpid, &up->msg_lrpid);
641 if (err2)
642 err = -EFAULT;
643 }
644 }
645
646out:
647 return err;
648}
649
650static int do_sys32_shmat (int first, int second, int third, int version, void *uptr)
651{
652 unsigned long raddr;
653 u32 *uaddr = (u32 *)A((u32)third);
654 int err = -EINVAL;
655
656 if (version == 1)
657 goto out;
658 err = sys_shmat (first, uptr, second, &raddr);
659 if (err)
660 goto out;
661 err = put_user (raddr, uaddr);
662out:
663 return err;
664}
665
666static int do_sys32_shmctl (int first, int second, void *uptr)
667{
668 int err;
669
670 if (IPCOP_MASK (second) &
671 (IPCOP_MASK (IPC_INFO) | IPCOP_MASK (SHM_LOCK) | IPCOP_MASK (SHM_UNLOCK) |
672 IPCOP_MASK (IPC_RMID))) {
673 if (second == (IPC_INFO|IPC_64))
674 second = IPC_INFO;
675 err = sys_shmctl (first, second, (struct shmid_ds *)uptr);
676 } else if ((second & IPC_64) && second != (SHM_INFO|IPC_64)) {
677 struct shmid64_ds s;
678 struct shmid64_ds32 *up = (struct shmid64_ds32 *)uptr;
679 mm_segment_t old_fs;
680
681 if (second == (IPC_SET|IPC_64)) {
682 err = get_user (s.shm_perm.uid, &up->shm_perm.uid);
683 err |= __get_user (s.shm_perm.gid, &up->shm_perm.gid);
684 err |= __get_user (s.shm_perm.mode, &up->shm_perm.mode);
685 if (err)
686 goto out;
687 }
688 old_fs = get_fs ();
689 set_fs (KERNEL_DS);
690 err = sys_shmctl (first, second, (struct shmid_ds *)&s);
691 set_fs (old_fs);
692 if (err < 0)
693 goto out;
694
695
696 if (IPCOP_MASK (second) &
697 (IPCOP_MASK (SHM_STAT) | IPCOP_MASK (IPC_STAT))) {
698 int err2 = copy_to_user (&up->shm_perm, &s.shm_perm, sizeof(struct ipc64_perm) + 3*sizeof(time_t));
699 err2 |= __put_user (s.shm_segsz, &up->shm_segsz);
700 err2 |= __put_user (s.shm_nattch, &up->shm_nattch);
701 err2 |= __put_user (s.shm_cpid, &up->shm_cpid);
702 err2 |= __put_user (s.shm_lpid, &up->shm_lpid);
703 if (err2)
704 err = -EFAULT;
705 }
706 } else {
707 struct shmid_ds s;
708 struct shmid_ds32 *up = (struct shmid_ds32 *)uptr;
709 mm_segment_t old_fs;
710
711 second &= ~IPC_64;
712 if (second == IPC_SET) {
713 err = get_user (s.shm_perm.uid, &up->shm_perm.uid);
714 err |= __get_user (s.shm_perm.gid, &up->shm_perm.gid);
715 err |= __get_user (s.shm_perm.mode, &up->shm_perm.mode);
716 if (err)
717 goto out;
718 }
719 old_fs = get_fs ();
720 set_fs (KERNEL_DS);
721 err = sys_shmctl (first, second, &s);
722 set_fs (old_fs);
723 if (err < 0)
724 goto out;
725
726
727 if (second == SHM_INFO) {
728 struct shm_info32 {
729 int used_ids;
730 u32 shm_tot, shm_rss, shm_swp;
731 u32 swap_attempts, swap_successes;
732 } *uip = (struct shm_info32 *)uptr;
733 struct shm_info *kp = (struct shm_info *)&s;
734 int err2 = put_user (kp->used_ids, &uip->used_ids);
735 err2 |= __put_user (kp->shm_tot, &uip->shm_tot);
736 err2 |= __put_user (kp->shm_rss, &uip->shm_rss);
737 err2 |= __put_user (kp->shm_swp, &uip->shm_swp);
738 err2 |= __put_user (kp->swap_attempts, &uip->swap_attempts);
739 err2 |= __put_user (kp->swap_successes, &uip->swap_successes);
740 if (err2)
741 err = -EFAULT;
742 } else if (IPCOP_MASK (second) &
743 (IPCOP_MASK (SHM_STAT) | IPCOP_MASK (IPC_STAT))) {
744 int err2 = put_user (s.shm_perm.key, &up->shm_perm.key);
745 err2 |= __put_user (high2lowuid(s.shm_perm.uid), &up->shm_perm.uid);
746 err2 |= __put_user (high2lowuid(s.shm_perm.gid), &up->shm_perm.gid);
747 err2 |= __put_user (high2lowuid(s.shm_perm.cuid), &up->shm_perm.cuid);
748 err2 |= __put_user (high2lowuid(s.shm_perm.cgid), &up->shm_perm.cgid);
749 err2 |= __put_user (s.shm_perm.mode, &up->shm_perm.mode);
750 err2 |= __put_user (s.shm_perm.seq, &up->shm_perm.seq);
751 err2 |= __put_user (s.shm_atime, &up->shm_atime);
752 err2 |= __put_user (s.shm_dtime, &up->shm_dtime);
753 err2 |= __put_user (s.shm_ctime, &up->shm_ctime);
754 err2 |= __put_user (s.shm_segsz, &up->shm_segsz);
755 err2 |= __put_user (s.shm_nattch, &up->shm_nattch);
756 err2 |= __put_user (s.shm_cpid, &up->shm_cpid);
757 err2 |= __put_user (s.shm_lpid, &up->shm_lpid);
758 if (err2)
759 err = -EFAULT;
760 }
761 }
762out:
763 return err;
764}
765
766static __inline__ void *alloc_user_space(long len)
767{
768 struct pt_regs *regs = current->thread.kregs;
769 unsigned long usp = regs->u_regs[UREG_I6];
770
771 if (!(current->thread.flags & SPARC_FLAG_32BIT))
772 usp += STACK_BIAS;
773
774 return (void *) (usp - len);
775}
776
777struct timespec32 {
778 s32 tv_sec;
779 s32 tv_nsec;
780};
781
782static int sys32_semtimedop(int semid, struct sembuf *tsems, int nsems,
783 const struct timespec32 *timeout32)
784{
785 struct timespec32 t32;
786 struct timespec *t64 = alloc_user_space(sizeof(*t64));
787
788 if (copy_from_user(&t32, timeout32, sizeof(t32)))
789 return -EFAULT;
790
791 if (put_user(t32.tv_sec, &t64->tv_sec) ||
792 put_user(t32.tv_nsec, &t64->tv_nsec))
793 return -EFAULT;
794
795 return sys_semtimedop(semid, tsems, nsems, t64);
796}
797
798asmlinkage int sys32_ipc (u32 call, int first, int second, int third, u32 ptr, u32 fifth)
799{
800 int version, err;
801
802 version = call >> 16;
803 call &= 0xffff;
804
805 if (call <= SEMCTL)
806 switch (call) {
807 case SEMOP:
808
809 err = sys_semtimedop (first, (struct sembuf *)AA(ptr), second, NULL);
810 goto out;
811 case SEMTIMEDOP:
812 err = sys32_semtimedop (first, (struct sembuf *)AA(ptr), second, (const struct timespec32 *) AA(fifth));
813 case SEMGET:
814 err = sys_semget (first, second, third);
815 goto out;
816 case SEMCTL:
817 err = do_sys32_semctl (first, second, third, (void *)AA(ptr));
818 goto out;
819 default:
820 err = -ENOSYS;
821 goto out;
822 };
823 if (call <= MSGCTL)
824 switch (call) {
825 case MSGSND:
826 err = do_sys32_msgsnd (first, second, third, (void *)AA(ptr));
827 goto out;
828 case MSGRCV:
829 err = do_sys32_msgrcv (first, second, fifth, third,
830 version, (void *)AA(ptr));
831 goto out;
832 case MSGGET:
833 err = sys_msgget ((key_t) first, second);
834 goto out;
835 case MSGCTL:
836 err = do_sys32_msgctl (first, second, (void *)AA(ptr));
837 goto out;
838 default:
839 err = -ENOSYS;
840 goto out;
841 }
842 if (call <= SHMCTL)
843 switch (call) {
844 case SHMAT:
845 err = do_sys32_shmat (first, second, third,
846 version, (void *)AA(ptr));
847 goto out;
848 case SHMDT:
849 err = sys_shmdt ((char *)AA(ptr));
850 goto out;
851 case SHMGET:
852 err = sys_shmget (first, second, third);
853 goto out;
854 case SHMCTL:
855 err = do_sys32_shmctl (first, second, (void *)AA(ptr));
856 goto out;
857 default:
858 err = -ENOSYS;
859 goto out;
860 }
861
862 err = -ENOSYS;
863
864out:
865 return err;
866}
867
868static inline int get_flock(struct flock *kfl, struct flock32 *ufl)
869{
870 int err;
871
872 err = get_user(kfl->l_type, &ufl->l_type);
873 err |= __get_user(kfl->l_whence, &ufl->l_whence);
874 err |= __get_user(kfl->l_start, &ufl->l_start);
875 err |= __get_user(kfl->l_len, &ufl->l_len);
876 err |= __get_user(kfl->l_pid, &ufl->l_pid);
877 return err;
878}
879
880static inline int put_flock(struct flock *kfl, struct flock32 *ufl)
881{
882 int err;
883
884 err = __put_user(kfl->l_type, &ufl->l_type);
885 err |= __put_user(kfl->l_whence, &ufl->l_whence);
886 err |= __put_user(kfl->l_start, &ufl->l_start);
887 err |= __put_user(kfl->l_len, &ufl->l_len);
888 err |= __put_user(kfl->l_pid, &ufl->l_pid);
889 return err;
890}
891
892extern asmlinkage long sys_fcntl(unsigned int fd, unsigned int cmd, unsigned long arg);
893
894asmlinkage long sys32_fcntl(unsigned int fd, unsigned int cmd, unsigned long arg)
895{
896 switch (cmd) {
897 case F_GETLK:
898 case F_SETLK:
899 case F_SETLKW:
900 {
901 struct flock f;
902 mm_segment_t old_fs;
903 long ret;
904
905 if (get_flock(&f, (struct flock32 *)arg))
906 return -EFAULT;
907 old_fs = get_fs(); set_fs (KERNEL_DS);
908 ret = sys_fcntl(fd, cmd, (unsigned long)&f);
909 set_fs (old_fs);
910 if (ret) return ret;
911 if (put_flock(&f, (struct flock32 *)arg))
912 return -EFAULT;
913 return 0;
914 }
915 default:
916 return sys_fcntl(fd, cmd, (unsigned long)arg);
917 }
918}
919
920asmlinkage long sys32_fcntl64(unsigned int fd, unsigned int cmd, unsigned long arg)
921{
922 if (cmd >= F_GETLK64 && cmd <= F_SETLKW64)
923 return sys_fcntl(fd, cmd + F_GETLK - F_GETLK64, arg);
924 return sys32_fcntl(fd, cmd, arg);
925}
926
927struct user_dqblk32 {
928 __u32 dqb_bhardlimit;
929 __u32 dqb_bsoftlimit;
930 __u32 dqb_curblocks;
931 __u32 dqb_ihardlimit;
932 __u32 dqb_isoftlimit;
933 __u32 dqb_curinodes;
934 __kernel_time_t32 dqb_btime;
935 __kernel_time_t32 dqb_itime;
936};
937
938extern asmlinkage int sys_quotactl(int cmd, const char *special, int id, caddr_t addr);
939
940asmlinkage int sys32_quotactl(int cmd, const char *special, int id, caddr_t addr)
941{
942 int cmds = cmd >> SUBCMDSHIFT;
943 int err;
944 struct v1c_mem_dqblk d;
945 mm_segment_t old_fs;
946 char *spec;
947
948 switch (cmds) {
949 case Q_V1_GETQUOTA:
950 break;
951 case Q_V1_SETQUOTA:
952 case Q_V1_SETUSE:
953 case Q_V1_SETQLIM:
954 if (copy_from_user(&d, addr, sizeof(struct user_dqblk32)))
955 return -EFAULT;
956 d.dqb_itime = ((struct user_dqblk32 *)&d)->dqb_itime;
957 d.dqb_btime = ((struct user_dqblk32 *)&d)->dqb_btime;
958 break;
959 default:
960 return sys_quotactl(cmd, special, id, addr);
961 }
962 spec = getname(special);
963 err = PTR_ERR(spec);
964 if (IS_ERR(spec))
965 return err;
966 old_fs = get_fs();
967 set_fs (KERNEL_DS);
968 err = sys_quotactl(cmd, (const char *)spec, id, (caddr_t)&d);
969 set_fs (old_fs);
970 putname (spec);
971 if (cmds == Q_V1_GETQUOTA) {
972 __kernel_time_t b = d.dqb_btime, i = d.dqb_itime;
973 ((struct user_dqblk32 *)&d)->dqb_itime = i;
974 ((struct user_dqblk32 *)&d)->dqb_btime = b;
975 if (copy_to_user(addr, &d, sizeof(struct user_dqblk32)))
976 return -EFAULT;
977 }
978 return err;
979}
980
981static inline int put_statfs (struct statfs32 *ubuf, struct statfs *kbuf)
982{
983 int err;
984
985 err = put_user (kbuf->f_type, &ubuf->f_type);
986 err |= __put_user (kbuf->f_bsize, &ubuf->f_bsize);
987 err |= __put_user (kbuf->f_blocks, &ubuf->f_blocks);
988 err |= __put_user (kbuf->f_bfree, &ubuf->f_bfree);
989 err |= __put_user (kbuf->f_bavail, &ubuf->f_bavail);
990 err |= __put_user (kbuf->f_files, &ubuf->f_files);
991 err |= __put_user (kbuf->f_ffree, &ubuf->f_ffree);
992 err |= __put_user (kbuf->f_namelen, &ubuf->f_namelen);
993 err |= __put_user (kbuf->f_fsid.val[0], &ubuf->f_fsid.val[0]);
994 err |= __put_user (kbuf->f_fsid.val[1], &ubuf->f_fsid.val[1]);
995 return err;
996}
997
998extern asmlinkage int sys_statfs(const char * path, struct statfs * buf);
999
1000asmlinkage int sys32_statfs(const char * path, struct statfs32 *buf)
1001{
1002 int ret;
1003 struct statfs s;
1004 mm_segment_t old_fs = get_fs();
1005 char *pth;
1006
1007 pth = getname (path);
1008 ret = PTR_ERR(pth);
1009 if (!IS_ERR(pth)) {
1010 set_fs (KERNEL_DS);
1011 ret = sys_statfs((const char *)pth, &s);
1012 set_fs (old_fs);
1013 putname (pth);
1014 if (put_statfs(buf, &s))
1015 return -EFAULT;
1016 }
1017 return ret;
1018}
1019
1020extern asmlinkage int sys_fstatfs(unsigned int fd, struct statfs * buf);
1021
1022asmlinkage int sys32_fstatfs(unsigned int fd, struct statfs32 *buf)
1023{
1024 int ret;
1025 struct statfs s;
1026 mm_segment_t old_fs = get_fs();
1027
1028 set_fs (KERNEL_DS);
1029 ret = sys_fstatfs(fd, &s);
1030 set_fs (old_fs);
1031 if (put_statfs(buf, &s))
1032 return -EFAULT;
1033 return ret;
1034}
1035
1036extern asmlinkage long sys_truncate(const char * path, unsigned long length);
1037extern asmlinkage long sys_ftruncate(unsigned int fd, unsigned long length);
1038
1039asmlinkage int sys32_truncate64(const char * path, unsigned long high, unsigned long low)
1040{
1041 if ((int)high < 0)
1042 return -EINVAL;
1043 else
1044 return sys_truncate(path, (high << 32) | low);
1045}
1046
1047asmlinkage int sys32_ftruncate64(unsigned int fd, unsigned long high, unsigned long low)
1048{
1049 if ((int)high < 0)
1050 return -EINVAL;
1051 else
1052 return sys_ftruncate(fd, (high << 32) | low);
1053}
1054
1055extern asmlinkage int sys_utime(char * filename, struct utimbuf * times);
1056
1057struct utimbuf32 {
1058 __kernel_time_t32 actime, modtime;
1059};
1060
1061asmlinkage int sys32_utime(char * filename, struct utimbuf32 *times)
1062{
1063 struct utimbuf t;
1064 mm_segment_t old_fs;
1065 int ret;
1066 char *filenam;
1067
1068 if (!times)
1069 return sys_utime(filename, NULL);
1070 if (get_user (t.actime, ×->actime) ||
1071 __get_user (t.modtime, ×->modtime))
1072 return -EFAULT;
1073 filenam = getname (filename);
1074 ret = PTR_ERR(filenam);
1075 if (!IS_ERR(filenam)) {
1076 old_fs = get_fs();
1077 set_fs (KERNEL_DS);
1078 ret = sys_utime(filenam, &t);
1079 set_fs (old_fs);
1080 putname (filenam);
1081 }
1082 return ret;
1083}
1084
1085struct iovec32 { u32 iov_base; __kernel_size_t32 iov_len; };
1086
1087typedef ssize_t (*io_fn_t)(struct file *, char *, size_t, loff_t *);
1088typedef ssize_t (*iov_fn_t)(struct file *, const struct iovec *, unsigned long, loff_t *);
1089
1090static long do_readv_writev32(int type, struct file *file,
1091 const struct iovec32 *vector, u32 count)
1092{
1093 __kernel_ssize_t32 tot_len;
1094 struct iovec iovstack[UIO_FASTIOV];
1095 struct iovec *iov=iovstack, *ivp;
1096 struct inode *inode;
1097 long retval, i;
1098 io_fn_t fn;
1099 iov_fn_t fnv;
1100
1101
1102
1103
1104 retval = 0;
1105 if (!count)
1106 goto out_nofree;
1107 retval = -EFAULT;
1108 if (verify_area(VERIFY_READ, vector, sizeof(struct iovec32)*count))
1109 goto out_nofree;
1110 retval = -EINVAL;
1111 if (count > UIO_MAXIOV)
1112 goto out_nofree;
1113 if (count > UIO_FASTIOV) {
1114 retval = -ENOMEM;
1115 iov = kmalloc(count*sizeof(struct iovec), GFP_KERNEL);
1116 if (!iov)
1117 goto out_nofree;
1118 }
1119
1120 tot_len = 0;
1121 i = count;
1122 ivp = iov;
1123 retval = -EINVAL;
1124 while(i > 0) {
1125 __kernel_ssize_t32 tmp = tot_len;
1126 __kernel_ssize_t32 len;
1127 u32 buf;
1128
1129 __get_user(len, &vector->iov_len);
1130 __get_user(buf, &vector->iov_base);
1131 if (len < 0)
1132 goto out;
1133 tot_len += len;
1134 if (tot_len < tmp)
1135 goto out;
1136 ivp->iov_base = (void *)A(buf);
1137 ivp->iov_len = (__kernel_size_t) len;
1138 vector++;
1139 ivp++;
1140 i--;
1141 }
1142
1143 inode = file->f_dentry->d_inode;
1144
1145 retval = locks_verify_area((type == VERIFY_WRITE
1146 ? FLOCK_VERIFY_READ : FLOCK_VERIFY_WRITE),
1147 inode, file, file->f_pos, tot_len);
1148 if (retval)
1149 goto out;
1150
1151
1152 fnv = (type == VERIFY_WRITE ? file->f_op->readv : file->f_op->writev);
1153 if (fnv) {
1154 retval = fnv(file, iov, count, &file->f_pos);
1155 goto out;
1156 }
1157
1158 fn = (type == VERIFY_WRITE ? file->f_op->read :
1159 (io_fn_t) file->f_op->write);
1160
1161 ivp = iov;
1162 while (count > 0) {
1163 void * base;
1164 int len, nr;
1165
1166 base = ivp->iov_base;
1167 len = ivp->iov_len;
1168 ivp++;
1169 count--;
1170 nr = fn(file, base, len, &file->f_pos);
1171 if (nr < 0) {
1172 if (!retval)
1173 retval = nr;
1174 break;
1175 }
1176 retval += nr;
1177 if (nr != len)
1178 break;
1179 }
1180out:
1181 if (iov != iovstack)
1182 kfree(iov);
1183out_nofree:
1184
1185 if ((retval + (type == VERIFY_WRITE)) > 0)
1186 dnotify_parent(file->f_dentry,
1187 (type == VERIFY_WRITE) ? DN_ACCESS : DN_MODIFY);
1188
1189 return retval;
1190}
1191
1192asmlinkage long sys32_readv(int fd, struct iovec32 *vector, u32 count)
1193{
1194 struct file *file;
1195 long ret = -EBADF;
1196
1197 file = fget(fd);
1198 if(!file)
1199 goto bad_file;
1200
1201 if (file->f_op && (file->f_mode & FMODE_READ) &&
1202 (file->f_op->readv || file->f_op->read))
1203 ret = do_readv_writev32(VERIFY_WRITE, file, vector, count);
1204 fput(file);
1205
1206bad_file:
1207 return ret;
1208}
1209
1210asmlinkage long sys32_writev(int fd, struct iovec32 *vector, u32 count)
1211{
1212 struct file *file;
1213 int ret = -EBADF;
1214
1215 file = fget(fd);
1216 if(!file)
1217 goto bad_file;
1218 if (file->f_op && (file->f_mode & FMODE_WRITE) &&
1219 (file->f_op->writev || file->f_op->write))
1220 ret = do_readv_writev32(VERIFY_READ, file, vector, count);
1221 fput(file);
1222
1223bad_file:
1224 return ret;
1225}
1226
1227
1228
1229#define NAME_OFFSET(de) ((int) ((de)->d_name - (char *) (de)))
1230#define ROUND_UP(x) (((x)+sizeof(u32)-1) & ~(sizeof(u32)-1))
1231
1232struct old_linux_dirent32 {
1233 u32 d_ino;
1234 u32 d_offset;
1235 unsigned short d_namlen;
1236 char d_name[1];
1237};
1238
1239struct readdir_callback32 {
1240 struct old_linux_dirent32 * dirent;
1241 int count;
1242};
1243
1244static int fillonedir(void * __buf, const char * name, int namlen,
1245 loff_t offset, ino_t ino, unsigned int d_type)
1246{
1247 struct readdir_callback32 * buf = (struct readdir_callback32 *) __buf;
1248 struct old_linux_dirent32 * dirent;
1249
1250 if (buf->count)
1251 return -EINVAL;
1252 buf->count++;
1253 dirent = buf->dirent;
1254 put_user(ino, &dirent->d_ino);
1255 put_user(offset, &dirent->d_offset);
1256 put_user(namlen, &dirent->d_namlen);
1257 copy_to_user(dirent->d_name, name, namlen);
1258 put_user(0, dirent->d_name + namlen);
1259 return 0;
1260}
1261
1262asmlinkage int old32_readdir(unsigned int fd, struct old_linux_dirent32 *dirent, unsigned int count)
1263{
1264 int error = -EBADF;
1265 struct file * file;
1266 struct readdir_callback32 buf;
1267
1268 file = fget(fd);
1269 if (!file)
1270 goto out;
1271
1272 buf.count = 0;
1273 buf.dirent = dirent;
1274
1275 error = vfs_readdir(file, fillonedir, &buf);
1276 if (error < 0)
1277 goto out_putf;
1278 error = buf.count;
1279
1280out_putf:
1281 fput(file);
1282out:
1283 return error;
1284}
1285
1286struct linux_dirent32 {
1287 u32 d_ino;
1288 u32 d_off;
1289 unsigned short d_reclen;
1290 char d_name[1];
1291};
1292
1293struct getdents_callback32 {
1294 struct linux_dirent32 * current_dir;
1295 struct linux_dirent32 * previous;
1296 int count;
1297 int error;
1298};
1299
1300static int filldir(void * __buf, const char * name, int namlen, loff_t offset, ino_t ino,
1301 unsigned int d_type)
1302{
1303 struct linux_dirent32 * dirent;
1304 struct getdents_callback32 * buf = (struct getdents_callback32 *) __buf;
1305 int reclen = ROUND_UP(NAME_OFFSET(dirent) + namlen + 1);
1306
1307 buf->error = -EINVAL;
1308 if (reclen > buf->count)
1309 return -EINVAL;
1310 dirent = buf->previous;
1311 if (dirent)
1312 put_user(offset, &dirent->d_off);
1313 dirent = buf->current_dir;
1314 buf->previous = dirent;
1315 put_user(ino, &dirent->d_ino);
1316 put_user(reclen, &dirent->d_reclen);
1317 copy_to_user(dirent->d_name, name, namlen);
1318 put_user(0, dirent->d_name + namlen);
1319 dirent = (void *) dirent + reclen;
1320 buf->current_dir = dirent;
1321 buf->count -= reclen;
1322 return 0;
1323}
1324
1325asmlinkage int sys32_getdents(unsigned int fd, struct linux_dirent32 *dirent, unsigned int count)
1326{
1327 struct file * file;
1328 struct linux_dirent32 * lastdirent;
1329 struct getdents_callback32 buf;
1330 int error = -EBADF;
1331
1332 file = fget(fd);
1333 if (!file)
1334 goto out;
1335
1336 buf.current_dir = dirent;
1337 buf.previous = NULL;
1338 buf.count = count;
1339 buf.error = 0;
1340
1341 error = vfs_readdir(file, filldir, &buf);
1342 if (error < 0)
1343 goto out_putf;
1344 lastdirent = buf.previous;
1345 error = buf.error;
1346 if(lastdirent) {
1347 put_user(file->f_pos, &lastdirent->d_off);
1348 error = count - buf.count;
1349 }
1350out_putf:
1351 fput(file);
1352out:
1353 return error;
1354}
1355
1356
1357
1358
1359
1360
1361
1362
1363static inline int
1364get_fd_set32(unsigned long n, unsigned long *fdset, u32 *ufdset)
1365{
1366 if (ufdset) {
1367 unsigned long odd;
1368
1369 if (verify_area(VERIFY_WRITE, ufdset, n*sizeof(u32)))
1370 return -EFAULT;
1371
1372 odd = n & 1UL;
1373 n &= ~1UL;
1374 while (n) {
1375 unsigned long h, l;
1376 __get_user(l, ufdset);
1377 __get_user(h, ufdset+1);
1378 ufdset += 2;
1379 *fdset++ = h << 32 | l;
1380 n -= 2;
1381 }
1382 if (odd)
1383 __get_user(*fdset, ufdset);
1384 } else {
1385
1386
1387
1388
1389 memset(fdset, 0, ((n + 1) & ~1)*sizeof(u32));
1390 }
1391 return 0;
1392}
1393
1394static inline void
1395set_fd_set32(unsigned long n, u32 *ufdset, unsigned long *fdset)
1396{
1397 unsigned long odd;
1398
1399 if (!ufdset)
1400 return;
1401
1402 odd = n & 1UL;
1403 n &= ~1UL;
1404 while (n) {
1405 unsigned long h, l;
1406 l = *fdset++;
1407 h = l >> 32;
1408 __put_user(l, ufdset);
1409 __put_user(h, ufdset+1);
1410 ufdset += 2;
1411 n -= 2;
1412 }
1413 if (odd)
1414 __put_user(*fdset, ufdset);
1415}
1416
1417#define MAX_SELECT_SECONDS \
1418 ((unsigned long) (MAX_SCHEDULE_TIMEOUT / HZ)-1)
1419
1420asmlinkage int sys32_select(int n, u32 *inp, u32 *outp, u32 *exp, u32 tvp_x)
1421{
1422 fd_set_bits fds;
1423 struct timeval32 *tvp = (struct timeval32 *)AA(tvp_x);
1424 char *bits;
1425 unsigned long nn;
1426 long timeout;
1427 int ret, size;
1428
1429 timeout = MAX_SCHEDULE_TIMEOUT;
1430 if (tvp) {
1431 time_t sec, usec;
1432
1433 if ((ret = verify_area(VERIFY_READ, tvp, sizeof(*tvp)))
1434 || (ret = __get_user(sec, &tvp->tv_sec))
1435 || (ret = __get_user(usec, &tvp->tv_usec)))
1436 goto out_nofds;
1437
1438 ret = -EINVAL;
1439 if(sec < 0 || usec < 0)
1440 goto out_nofds;
1441
1442 if ((unsigned long) sec < MAX_SELECT_SECONDS) {
1443 timeout = (usec + 1000000/HZ - 1) / (1000000/HZ);
1444 timeout += sec * (unsigned long) HZ;
1445 }
1446 }
1447
1448 ret = -EINVAL;
1449 if (n < 0)
1450 goto out_nofds;
1451 if (n > current->files->max_fdset)
1452 n = current->files->max_fdset;
1453
1454
1455
1456
1457
1458
1459 ret = -ENOMEM;
1460 size = FDS_BYTES(n);
1461 bits = kmalloc(6 * size, GFP_KERNEL);
1462 if (!bits)
1463 goto out_nofds;
1464 fds.in = (unsigned long *) bits;
1465 fds.out = (unsigned long *) (bits + size);
1466 fds.ex = (unsigned long *) (bits + 2*size);
1467 fds.res_in = (unsigned long *) (bits + 3*size);
1468 fds.res_out = (unsigned long *) (bits + 4*size);
1469 fds.res_ex = (unsigned long *) (bits + 5*size);
1470
1471 nn = (n + 8*sizeof(u32) - 1) / (8*sizeof(u32));
1472 if ((ret = get_fd_set32(nn, fds.in, inp)) ||
1473 (ret = get_fd_set32(nn, fds.out, outp)) ||
1474 (ret = get_fd_set32(nn, fds.ex, exp)))
1475 goto out;
1476 zero_fd_set(n, fds.res_in);
1477 zero_fd_set(n, fds.res_out);
1478 zero_fd_set(n, fds.res_ex);
1479
1480 ret = do_select(n, &fds, &timeout);
1481
1482 if (tvp && !(current->personality & STICKY_TIMEOUTS)) {
1483 time_t sec = 0, usec = 0;
1484 if (timeout) {
1485 sec = timeout / HZ;
1486 usec = timeout % HZ;
1487 usec *= (1000000/HZ);
1488 }
1489 put_user(sec, &tvp->tv_sec);
1490 put_user(usec, &tvp->tv_usec);
1491 }
1492
1493 if (ret < 0)
1494 goto out;
1495 if (!ret) {
1496 ret = -ERESTARTNOHAND;
1497 if (signal_pending(current))
1498 goto out;
1499 ret = 0;
1500 }
1501
1502 set_fd_set32(nn, inp, fds.res_in);
1503 set_fd_set32(nn, outp, fds.res_out);
1504 set_fd_set32(nn, exp, fds.res_ex);
1505
1506out:
1507 kfree(bits);
1508out_nofds:
1509 return ret;
1510}
1511
1512static int cp_new_stat32(struct inode *inode, struct stat32 *statbuf)
1513{
1514 unsigned long ino, blksize, blocks;
1515 kdev_t dev, rdev;
1516 umode_t mode;
1517 nlink_t nlink;
1518 uid_t uid;
1519 gid_t gid;
1520 off_t size;
1521 time_t atime, mtime, ctime;
1522 int err;
1523
1524
1525
1526
1527
1528 ino = inode->i_ino;
1529 dev = inode->i_dev;
1530 mode = inode->i_mode;
1531 nlink = inode->i_nlink;
1532 uid = inode->i_uid;
1533 gid = inode->i_gid;
1534 rdev = inode->i_rdev;
1535 size = inode->i_size;
1536 atime = inode->i_atime;
1537 mtime = inode->i_mtime;
1538 ctime = inode->i_ctime;
1539 blksize = inode->i_blksize;
1540 blocks = inode->i_blocks;
1541
1542 err = put_user(kdev_t_to_nr(dev), &statbuf->st_dev);
1543 err |= put_user(ino, &statbuf->st_ino);
1544 err |= put_user(mode, &statbuf->st_mode);
1545 err |= put_user(nlink, &statbuf->st_nlink);
1546 err |= put_user(high2lowuid(uid), &statbuf->st_uid);
1547 err |= put_user(high2lowgid(gid), &statbuf->st_gid);
1548 err |= put_user(kdev_t_to_nr(rdev), &statbuf->st_rdev);
1549 err |= put_user(size, &statbuf->st_size);
1550 err |= put_user(atime, &statbuf->st_atime);
1551 err |= put_user(0, &statbuf->__unused1);
1552 err |= put_user(mtime, &statbuf->st_mtime);
1553 err |= put_user(0, &statbuf->__unused2);
1554 err |= put_user(ctime, &statbuf->st_ctime);
1555 err |= put_user(0, &statbuf->__unused3);
1556 if (blksize) {
1557 err |= put_user(blksize, &statbuf->st_blksize);
1558 err |= put_user(blocks, &statbuf->st_blocks);
1559 } else {
1560 unsigned int tmp_blocks;
1561
1562#define D_B 7
1563#define I_B (BLOCK_SIZE / sizeof(unsigned short))
1564 tmp_blocks = (size + BLOCK_SIZE - 1) / BLOCK_SIZE;
1565 if (tmp_blocks > D_B) {
1566 unsigned int indirect;
1567
1568 indirect = (tmp_blocks - D_B + I_B - 1) / I_B;
1569 tmp_blocks += indirect;
1570 if (indirect > 1) {
1571 indirect = (indirect - 1 + I_B - 1) / I_B;
1572 tmp_blocks += indirect;
1573 if (indirect > 1)
1574 tmp_blocks++;
1575 }
1576 }
1577 err |= put_user(BLOCK_SIZE, &statbuf->st_blksize);
1578 err |= put_user((BLOCK_SIZE / 512) * tmp_blocks, &statbuf->st_blocks);
1579#undef D_B
1580#undef I_B
1581 }
1582 err |= put_user(0, &statbuf->__unused4[0]);
1583 err |= put_user(0, &statbuf->__unused4[1]);
1584
1585 return err;
1586}
1587
1588
1589static __inline__ int
1590do_revalidate(struct dentry *dentry)
1591{
1592 struct inode * inode = dentry->d_inode;
1593 if (inode->i_op && inode->i_op->revalidate)
1594 return inode->i_op->revalidate(dentry);
1595 return 0;
1596}
1597
1598asmlinkage int sys32_newstat(char * filename, struct stat32 *statbuf)
1599{
1600 struct nameidata nd;
1601 int error;
1602
1603 error = user_path_walk(filename, &nd);
1604 if (!error) {
1605 error = do_revalidate(nd.dentry);
1606 if (!error)
1607 error = cp_new_stat32(nd.dentry->d_inode, statbuf);
1608 path_release(&nd);
1609 }
1610 return error;
1611}
1612
1613asmlinkage int sys32_newlstat(char * filename, struct stat32 *statbuf)
1614{
1615 struct nameidata nd;
1616 int error;
1617
1618 error = user_path_walk_link(filename, &nd);
1619 if (!error) {
1620 error = do_revalidate(nd.dentry);
1621 if (!error)
1622 error = cp_new_stat32(nd.dentry->d_inode, statbuf);
1623
1624 path_release(&nd);
1625 }
1626 return error;
1627}
1628
1629asmlinkage int sys32_newfstat(unsigned int fd, struct stat32 *statbuf)
1630{
1631 struct file *f;
1632 int err = -EBADF;
1633
1634 f = fget(fd);
1635 if (f) {
1636 struct dentry * dentry = f->f_dentry;
1637
1638 err = do_revalidate(dentry);
1639 if (!err)
1640 err = cp_new_stat32(dentry->d_inode, statbuf);
1641 fput(f);
1642 }
1643 return err;
1644}
1645
1646extern asmlinkage int sys_sysfs(int option, unsigned long arg1, unsigned long arg2);
1647
1648asmlinkage int sys32_sysfs(int option, u32 arg1, u32 arg2)
1649{
1650 return sys_sysfs(option, arg1, arg2);
1651}
1652
1653struct ncp_mount_data32_v3 {
1654 int version;
1655 unsigned int ncp_fd;
1656 __kernel_uid_t32 mounted_uid;
1657 __kernel_pid_t32 wdog_pid;
1658 unsigned char mounted_vol[NCP_VOLNAME_LEN + 1];
1659 unsigned int time_out;
1660 unsigned int retry_count;
1661 unsigned int flags;
1662 __kernel_uid_t32 uid;
1663 __kernel_gid_t32 gid;
1664 __kernel_mode_t32 file_mode;
1665 __kernel_mode_t32 dir_mode;
1666};
1667
1668struct ncp_mount_data32_v4 {
1669 int version;
1670
1671 unsigned int flags;
1672 unsigned int mounted_uid;
1673 int wdog_pid;
1674
1675 unsigned int ncp_fd;
1676 unsigned int time_out;
1677 unsigned int retry_count;
1678
1679 unsigned int uid;
1680 unsigned int gid;
1681 unsigned int file_mode;
1682 unsigned int dir_mode;
1683};
1684
1685static void *do_ncp_super_data_conv(void *raw_data)
1686{
1687 switch (*(int*)raw_data) {
1688 case NCP_MOUNT_VERSION:
1689 {
1690 struct ncp_mount_data news, *n = &news;
1691 struct ncp_mount_data32_v3 *n32 = (struct ncp_mount_data32_v3 *)raw_data;
1692
1693 n->version = n32->version;
1694 n->ncp_fd = n32->ncp_fd;
1695 n->mounted_uid = low2highuid(n32->mounted_uid);
1696 n->wdog_pid = n32->wdog_pid;
1697 memmove (n->mounted_vol, n32->mounted_vol, sizeof (n32->mounted_vol));
1698 n->time_out = n32->time_out;
1699 n->retry_count = n32->retry_count;
1700 n->flags = n32->flags;
1701 n->uid = low2highuid(n32->uid);
1702 n->gid = low2highgid(n32->gid);
1703 n->file_mode = n32->file_mode;
1704 n->dir_mode = n32->dir_mode;
1705 memcpy(raw_data, n, sizeof(*n));
1706 }
1707 break;
1708 case NCP_MOUNT_VERSION_V4:
1709 {
1710 struct ncp_mount_data_v4 news, *n = &news;
1711 struct ncp_mount_data32_v4 *n32 = (struct ncp_mount_data32_v4 *)raw_data;
1712
1713 n->version = n32->version;
1714 n->flags = n32->flags;
1715 n->mounted_uid = n32->mounted_uid;
1716 n->wdog_pid = n32->wdog_pid;
1717 n->ncp_fd = n32->ncp_fd;
1718 n->time_out = n32->time_out;
1719 n->retry_count = n32->retry_count;
1720 n->uid = n32->uid;
1721 n->gid = n32->gid;
1722 n->file_mode = n32->file_mode;
1723 n->dir_mode = n32->dir_mode;
1724 memcpy(raw_data, n, sizeof(*n));
1725 }
1726 break;
1727 default:
1728
1729 break;
1730 }
1731 return raw_data;
1732}
1733
1734struct smb_mount_data32 {
1735 int version;
1736 __kernel_uid_t32 mounted_uid;
1737 __kernel_uid_t32 uid;
1738 __kernel_gid_t32 gid;
1739 __kernel_mode_t32 file_mode;
1740 __kernel_mode_t32 dir_mode;
1741};
1742
1743static void *do_smb_super_data_conv(void *raw_data)
1744{
1745 struct smb_mount_data news, *s = &news;
1746 struct smb_mount_data32 *s32 = (struct smb_mount_data32 *)raw_data;
1747
1748 s->version = s32->version;
1749 s->mounted_uid = low2highuid(s32->mounted_uid);
1750 s->uid = low2highuid(s32->uid);
1751 s->gid = low2highgid(s32->gid);
1752 s->file_mode = s32->file_mode;
1753 s->dir_mode = s32->dir_mode;
1754 memcpy(raw_data, s, sizeof(struct smb_mount_data));
1755 return raw_data;
1756}
1757
1758static int copy_mount_stuff_to_kernel(const void *user, unsigned long *kernel)
1759{
1760 int i;
1761 unsigned long page;
1762 struct vm_area_struct *vma;
1763
1764 *kernel = 0;
1765 if(!user)
1766 return 0;
1767 vma = find_vma(current->mm, (unsigned long)user);
1768 if(!vma || (unsigned long)user < vma->vm_start)
1769 return -EFAULT;
1770 if(!(vma->vm_flags & VM_READ))
1771 return -EFAULT;
1772 i = vma->vm_end - (unsigned long) user;
1773 if(PAGE_SIZE <= (unsigned long) i)
1774 i = PAGE_SIZE - 1;
1775 if(!(page = __get_free_page(GFP_KERNEL)))
1776 return -ENOMEM;
1777 if(copy_from_user((void *) page, user, i)) {
1778 free_page(page);
1779 return -EFAULT;
1780 }
1781 *kernel = page;
1782 return 0;
1783}
1784
1785#define SMBFS_NAME "smbfs"
1786#define NCPFS_NAME "ncpfs"
1787
1788asmlinkage int sys32_mount(char *dev_name, char *dir_name, char *type, unsigned long new_flags, u32 data)
1789{
1790 unsigned long type_page = 0;
1791 unsigned long data_page = 0;
1792 unsigned long dev_page = 0;
1793 unsigned long dir_page = 0;
1794 int err, is_smb, is_ncp;
1795
1796 is_smb = is_ncp = 0;
1797
1798 err = copy_mount_stuff_to_kernel((const void *)type, &type_page);
1799 if (err)
1800 goto out;
1801
1802 if (type_page) {
1803 is_smb = !strcmp((char *)type_page, SMBFS_NAME);
1804 is_ncp = !strcmp((char *)type_page, NCPFS_NAME);
1805 } else {
1806 is_smb = is_ncp = 0;
1807 }
1808
1809 err = copy_mount_stuff_to_kernel((const void *)AA(data), &data_page);
1810 if (err)
1811 goto type_out;
1812
1813 err = copy_mount_stuff_to_kernel(dev_name, &dev_page);
1814 if (err)
1815 goto data_out;
1816
1817 err = copy_mount_stuff_to_kernel(dir_name, &dir_page);
1818 if (err)
1819 goto dev_out;
1820
1821 if (!is_smb && !is_ncp) {
1822 lock_kernel();
1823 err = do_mount((char*)dev_page, (char*)dir_page,
1824 (char*)type_page, new_flags, (char*)data_page);
1825 unlock_kernel();
1826 } else {
1827 if (is_ncp)
1828 do_ncp_super_data_conv((void *)data_page);
1829 else
1830 do_smb_super_data_conv((void *)data_page);
1831
1832 lock_kernel();
1833 err = do_mount((char*)dev_page, (char*)dir_page,
1834 (char*)type_page, new_flags, (char*)data_page);
1835 unlock_kernel();
1836 }
1837 free_page(dir_page);
1838
1839dev_out:
1840 free_page(dev_page);
1841
1842data_out:
1843 free_page(data_page);
1844
1845type_out:
1846 free_page(type_page);
1847
1848out:
1849 return err;
1850}
1851
1852struct rusage32 {
1853 struct timeval32 ru_utime;
1854 struct timeval32 ru_stime;
1855 s32 ru_maxrss;
1856 s32 ru_ixrss;
1857 s32 ru_idrss;
1858 s32 ru_isrss;
1859 s32 ru_minflt;
1860 s32 ru_majflt;
1861 s32 ru_nswap;
1862 s32 ru_inblock;
1863 s32 ru_oublock;
1864 s32 ru_msgsnd;
1865 s32 ru_msgrcv;
1866 s32 ru_nsignals;
1867 s32 ru_nvcsw;
1868 s32 ru_nivcsw;
1869};
1870
1871static int put_rusage (struct rusage32 *ru, struct rusage *r)
1872{
1873 int err;
1874
1875 err = put_user (r->ru_utime.tv_sec, &ru->ru_utime.tv_sec);
1876 err |= __put_user (r->ru_utime.tv_usec, &ru->ru_utime.tv_usec);
1877 err |= __put_user (r->ru_stime.tv_sec, &ru->ru_stime.tv_sec);
1878 err |= __put_user (r->ru_stime.tv_usec, &ru->ru_stime.tv_usec);
1879 err |= __put_user (r->ru_maxrss, &ru->ru_maxrss);
1880 err |= __put_user (r->ru_ixrss, &ru->ru_ixrss);
1881 err |= __put_user (r->ru_idrss, &ru->ru_idrss);
1882 err |= __put_user (r->ru_isrss, &ru->ru_isrss);
1883 err |= __put_user (r->ru_minflt, &ru->ru_minflt);
1884 err |= __put_user (r->ru_majflt, &ru->ru_majflt);
1885 err |= __put_user (r->ru_nswap, &ru->ru_nswap);
1886 err |= __put_user (r->ru_inblock, &ru->ru_inblock);
1887 err |= __put_user (r->ru_oublock, &ru->ru_oublock);
1888 err |= __put_user (r->ru_msgsnd, &ru->ru_msgsnd);
1889 err |= __put_user (r->ru_msgrcv, &ru->ru_msgrcv);
1890 err |= __put_user (r->ru_nsignals, &ru->ru_nsignals);
1891 err |= __put_user (r->ru_nvcsw, &ru->ru_nvcsw);
1892 err |= __put_user (r->ru_nivcsw, &ru->ru_nivcsw);
1893 return err;
1894}
1895
1896asmlinkage int sys32_wait4(__kernel_pid_t32 pid, unsigned int *stat_addr, int options, struct rusage32 *ru)
1897{
1898 if (!ru)
1899 return sys_wait4(pid, stat_addr, options, NULL);
1900 else {
1901 struct rusage r;
1902 int ret;
1903 unsigned int status;
1904 mm_segment_t old_fs = get_fs();
1905
1906 set_fs (KERNEL_DS);
1907 ret = sys_wait4(pid, stat_addr ? &status : NULL, options, &r);
1908 set_fs (old_fs);
1909 if (put_rusage (ru, &r)) return -EFAULT;
1910 if (stat_addr && put_user (status, stat_addr))
1911 return -EFAULT;
1912 return ret;
1913 }
1914}
1915
1916struct sysinfo32 {
1917 s32 uptime;
1918 u32 loads[3];
1919 u32 totalram;
1920 u32 freeram;
1921 u32 sharedram;
1922 u32 bufferram;
1923 u32 totalswap;
1924 u32 freeswap;
1925 unsigned short procs;
1926 unsigned short pad;
1927 u32 totalhigh;
1928 u32 freehigh;
1929 u32 mem_unit;
1930 char _f[20-2*sizeof(int)-sizeof(int)];
1931};
1932
1933extern asmlinkage int sys_sysinfo(struct sysinfo *info);
1934
1935asmlinkage int sys32_sysinfo(struct sysinfo32 *info)
1936{
1937 struct sysinfo s;
1938 int ret, err;
1939 int bitcount = 0;
1940 mm_segment_t old_fs = get_fs ();
1941
1942 set_fs(KERNEL_DS);
1943 ret = sys_sysinfo(&s);
1944 set_fs(old_fs);
1945
1946
1947
1948 if ((s.totalram >> 32) || (s.totalswap >> 32)) {
1949 while (s.mem_unit < PAGE_SIZE) {
1950 s.mem_unit <<= 1;
1951 bitcount++;
1952 }
1953 s.totalram >>= bitcount;
1954 s.freeram >>= bitcount;
1955 s.sharedram >>= bitcount;
1956 s.bufferram >>= bitcount;
1957 s.totalswap >>= bitcount;
1958 s.freeswap >>= bitcount;
1959 s.totalhigh >>= bitcount;
1960 s.freehigh >>= bitcount;
1961 }
1962
1963 err = put_user (s.uptime, &info->uptime);
1964 err |= __put_user (s.loads[0], &info->loads[0]);
1965 err |= __put_user (s.loads[1], &info->loads[1]);
1966 err |= __put_user (s.loads[2], &info->loads[2]);
1967 err |= __put_user (s.totalram, &info->totalram);
1968 err |= __put_user (s.freeram, &info->freeram);
1969 err |= __put_user (s.sharedram, &info->sharedram);
1970 err |= __put_user (s.bufferram, &info->bufferram);
1971 err |= __put_user (s.totalswap, &info->totalswap);
1972 err |= __put_user (s.freeswap, &info->freeswap);
1973 err |= __put_user (s.procs, &info->procs);
1974 err |= __put_user (s.totalhigh, &info->totalhigh);
1975 err |= __put_user (s.freehigh, &info->freehigh);
1976 err |= __put_user (s.mem_unit, &info->mem_unit);
1977 if (err)
1978 return -EFAULT;
1979 return ret;
1980}
1981
1982extern asmlinkage int sys_sched_rr_get_interval(pid_t pid, struct timespec *interval);
1983
1984asmlinkage int sys32_sched_rr_get_interval(__kernel_pid_t32 pid, struct timespec32 *interval)
1985{
1986 struct timespec t;
1987 int ret;
1988 mm_segment_t old_fs = get_fs ();
1989
1990 set_fs (KERNEL_DS);
1991 ret = sys_sched_rr_get_interval(pid, &t);
1992 set_fs (old_fs);
1993 if (put_user (t.tv_sec, &interval->tv_sec) ||
1994 __put_user (t.tv_nsec, &interval->tv_nsec))
1995 return -EFAULT;
1996 return ret;
1997}
1998
1999extern asmlinkage int sys_nanosleep(struct timespec *rqtp, struct timespec *rmtp);
2000
2001asmlinkage int sys32_nanosleep(struct timespec32 *rqtp, struct timespec32 *rmtp)
2002{
2003 struct timespec t;
2004 int ret;
2005 mm_segment_t old_fs = get_fs ();
2006
2007 if (get_user (t.tv_sec, &rqtp->tv_sec) ||
2008 __get_user (t.tv_nsec, &rqtp->tv_nsec))
2009 return -EFAULT;
2010 set_fs (KERNEL_DS);
2011 ret = sys_nanosleep(&t, rmtp ? &t : NULL);
2012 set_fs (old_fs);
2013 if (rmtp && ret == -EINTR) {
2014 if (__put_user (t.tv_sec, &rmtp->tv_sec) ||
2015 __put_user (t.tv_nsec, &rmtp->tv_nsec))
2016 return -EFAULT;
2017 }
2018 return ret;
2019}
2020
2021extern asmlinkage int sys_sigprocmask(int how, old_sigset_t *set, old_sigset_t *oset);
2022
2023asmlinkage int sys32_sigprocmask(int how, old_sigset_t32 *set, old_sigset_t32 *oset)
2024{
2025 old_sigset_t s;
2026 int ret;
2027 mm_segment_t old_fs = get_fs();
2028
2029 if (set && get_user (s, set)) return -EFAULT;
2030 set_fs (KERNEL_DS);
2031 ret = sys_sigprocmask(how, set ? &s : NULL, oset ? &s : NULL);
2032 set_fs (old_fs);
2033 if (ret) return ret;
2034 if (oset && put_user (s, oset)) return -EFAULT;
2035 return 0;
2036}
2037
2038extern asmlinkage int sys_rt_sigprocmask(int how, sigset_t *set, sigset_t *oset, size_t sigsetsize);
2039
2040asmlinkage int sys32_rt_sigprocmask(int how, sigset_t32 *set, sigset_t32 *oset, __kernel_size_t32 sigsetsize)
2041{
2042 sigset_t s;
2043 sigset_t32 s32;
2044 int ret;
2045 mm_segment_t old_fs = get_fs();
2046
2047 if (set) {
2048 if (copy_from_user (&s32, set, sizeof(sigset_t32)))
2049 return -EFAULT;
2050 switch (_NSIG_WORDS) {
2051 case 4: s.sig[3] = s32.sig[6] | (((long)s32.sig[7]) << 32);
2052 case 3: s.sig[2] = s32.sig[4] | (((long)s32.sig[5]) << 32);
2053 case 2: s.sig[1] = s32.sig[2] | (((long)s32.sig[3]) << 32);
2054 case 1: s.sig[0] = s32.sig[0] | (((long)s32.sig[1]) << 32);
2055 }
2056 }
2057 set_fs (KERNEL_DS);
2058 ret = sys_rt_sigprocmask(how, set ? &s : NULL, oset ? &s : NULL, sigsetsize);
2059 set_fs (old_fs);
2060 if (ret) return ret;
2061 if (oset) {
2062 switch (_NSIG_WORDS) {
2063 case 4: s32.sig[7] = (s.sig[3] >> 32); s32.sig[6] = s.sig[3];
2064 case 3: s32.sig[5] = (s.sig[2] >> 32); s32.sig[4] = s.sig[2];
2065 case 2: s32.sig[3] = (s.sig[1] >> 32); s32.sig[2] = s.sig[1];
2066 case 1: s32.sig[1] = (s.sig[0] >> 32); s32.sig[0] = s.sig[0];
2067 }
2068 if (copy_to_user (oset, &s32, sizeof(sigset_t32)))
2069 return -EFAULT;
2070 }
2071 return 0;
2072}
2073
2074extern asmlinkage int sys_sigpending(old_sigset_t *set);
2075
2076asmlinkage int sys32_sigpending(old_sigset_t32 *set)
2077{
2078 old_sigset_t s;
2079 int ret;
2080 mm_segment_t old_fs = get_fs();
2081
2082 set_fs (KERNEL_DS);
2083 ret = sys_sigpending(&s);
2084 set_fs (old_fs);
2085 if (put_user (s, set)) return -EFAULT;
2086 return ret;
2087}
2088
2089extern asmlinkage int sys_rt_sigpending(sigset_t *set, size_t sigsetsize);
2090
2091asmlinkage int sys32_rt_sigpending(sigset_t32 *set, __kernel_size_t32 sigsetsize)
2092{
2093 sigset_t s;
2094 sigset_t32 s32;
2095 int ret;
2096 mm_segment_t old_fs = get_fs();
2097
2098 set_fs (KERNEL_DS);
2099 ret = sys_rt_sigpending(&s, sigsetsize);
2100 set_fs (old_fs);
2101 if (!ret) {
2102 switch (_NSIG_WORDS) {
2103 case 4: s32.sig[7] = (s.sig[3] >> 32); s32.sig[6] = s.sig[3];
2104 case 3: s32.sig[5] = (s.sig[2] >> 32); s32.sig[4] = s.sig[2];
2105 case 2: s32.sig[3] = (s.sig[1] >> 32); s32.sig[2] = s.sig[1];
2106 case 1: s32.sig[1] = (s.sig[0] >> 32); s32.sig[0] = s.sig[0];
2107 }
2108 if (copy_to_user (set, &s32, sizeof(sigset_t32)))
2109 return -EFAULT;
2110 }
2111 return ret;
2112}
2113
2114asmlinkage int
2115sys32_rt_sigtimedwait(sigset_t32 *uthese, siginfo_t32 *uinfo,
2116 struct timespec32 *uts, __kernel_size_t32 sigsetsize)
2117{
2118 int ret, sig;
2119 sigset_t these;
2120 sigset_t32 these32;
2121 struct timespec ts;
2122 siginfo_t info;
2123 long timeout = 0;
2124
2125
2126 if (sigsetsize != sizeof(sigset_t))
2127 return -EINVAL;
2128
2129 if (copy_from_user (&these32, uthese, sizeof(sigset_t32)))
2130 return -EFAULT;
2131
2132 switch (_NSIG_WORDS) {
2133 case 4: these.sig[3] = these32.sig[6] | (((long)these32.sig[7]) << 32);
2134 case 3: these.sig[2] = these32.sig[4] | (((long)these32.sig[5]) << 32);
2135 case 2: these.sig[1] = these32.sig[2] | (((long)these32.sig[3]) << 32);
2136 case 1: these.sig[0] = these32.sig[0] | (((long)these32.sig[1]) << 32);
2137 }
2138
2139
2140
2141
2142
2143 sigdelsetmask(&these, sigmask(SIGKILL)|sigmask(SIGSTOP));
2144 signotset(&these);
2145
2146 if (uts) {
2147 if (get_user (ts.tv_sec, &uts->tv_sec) ||
2148 get_user (ts.tv_nsec, &uts->tv_nsec))
2149 return -EINVAL;
2150 if (ts.tv_nsec >= 1000000000L || ts.tv_nsec < 0
2151 || ts.tv_sec < 0)
2152 return -EINVAL;
2153 }
2154
2155 spin_lock_irq(¤t->sigmask_lock);
2156 sig = dequeue_signal(&these, &info);
2157 if (!sig) {
2158 timeout = MAX_SCHEDULE_TIMEOUT;
2159 if (uts)
2160 timeout = (timespec_to_jiffies(&ts)
2161 + (ts.tv_sec || ts.tv_nsec));
2162
2163 current->state = TASK_INTERRUPTIBLE;
2164 timeout = schedule_timeout(timeout);
2165
2166 if (timeout) {
2167
2168
2169
2170 sigset_t oldblocked = current->blocked;
2171 sigandsets(¤t->blocked, ¤t->blocked, &these);
2172 recalc_sigpending(current);
2173 spin_unlock_irq(¤t->sigmask_lock);
2174
2175 current->state = TASK_INTERRUPTIBLE;
2176 timeout = schedule_timeout(timeout);
2177
2178 spin_lock_irq(¤t->sigmask_lock);
2179 sig = dequeue_signal(&these, &info);
2180 current->blocked = oldblocked;
2181 recalc_sigpending(current);
2182 }
2183 }
2184 spin_unlock_irq(¤t->sigmask_lock);
2185
2186 if (sig) {
2187 ret = sig;
2188 if (uinfo) {
2189 if (copy_siginfo_to_user32(uinfo, &info))
2190 ret = -EFAULT;
2191 }
2192 } else {
2193 ret = -EAGAIN;
2194 if (timeout)
2195 ret = -EINTR;
2196 }
2197
2198 return ret;
2199}
2200
2201extern asmlinkage int
2202sys_rt_sigqueueinfo(int pid, int sig, siginfo_t *uinfo);
2203
2204asmlinkage int
2205sys32_rt_sigqueueinfo(int pid, int sig, siginfo_t32 *uinfo)
2206{
2207 siginfo_t info;
2208 int ret;
2209 mm_segment_t old_fs = get_fs();
2210
2211 if (copy_from_user (&info, uinfo, 3*sizeof(int)) ||
2212 copy_from_user (info._sifields._pad, uinfo->_sifields._pad, SI_PAD_SIZE))
2213 return -EFAULT;
2214 set_fs (KERNEL_DS);
2215 ret = sys_rt_sigqueueinfo(pid, sig, &info);
2216 set_fs (old_fs);
2217 return ret;
2218}
2219
2220struct tms32 {
2221 __kernel_clock_t32 tms_utime;
2222 __kernel_clock_t32 tms_stime;
2223 __kernel_clock_t32 tms_cutime;
2224 __kernel_clock_t32 tms_cstime;
2225};
2226
2227extern asmlinkage long sys_times(struct tms * tbuf);
2228
2229asmlinkage long sys32_times(struct tms32 *tbuf)
2230{
2231 struct tms t;
2232 long ret;
2233 mm_segment_t old_fs = get_fs ();
2234 int err;
2235
2236 set_fs (KERNEL_DS);
2237 ret = sys_times(tbuf ? &t : NULL);
2238 set_fs (old_fs);
2239 if (tbuf) {
2240 err = put_user (t.tms_utime, &tbuf->tms_utime);
2241 err |= __put_user (t.tms_stime, &tbuf->tms_stime);
2242 err |= __put_user (t.tms_cutime, &tbuf->tms_cutime);
2243 err |= __put_user (t.tms_cstime, &tbuf->tms_cstime);
2244 if (err)
2245 ret = -EFAULT;
2246 }
2247 return ret;
2248}
2249
2250#define RLIM_INFINITY32 0x7fffffff
2251#define RESOURCE32(x) ((x > RLIM_INFINITY32) ? RLIM_INFINITY32 : x)
2252
2253struct rlimit32 {
2254 u32 rlim_cur;
2255 u32 rlim_max;
2256};
2257
2258extern asmlinkage int sys_getrlimit(unsigned int resource, struct rlimit *rlim);
2259
2260asmlinkage int sys32_getrlimit(unsigned int resource, struct rlimit32 *rlim)
2261{
2262 struct rlimit r;
2263 int ret;
2264 mm_segment_t old_fs = get_fs ();
2265
2266 set_fs (KERNEL_DS);
2267 ret = sys_getrlimit(resource, &r);
2268 set_fs (old_fs);
2269 if (!ret) {
2270 ret = put_user (RESOURCE32(r.rlim_cur), &rlim->rlim_cur);
2271 ret |= __put_user (RESOURCE32(r.rlim_max), &rlim->rlim_max);
2272 }
2273 return ret;
2274}
2275
2276extern asmlinkage int sys_setrlimit(unsigned int resource, struct rlimit *rlim);
2277
2278asmlinkage int sys32_setrlimit(unsigned int resource, struct rlimit32 *rlim)
2279{
2280 struct rlimit r;
2281 int ret;
2282 mm_segment_t old_fs = get_fs ();
2283
2284 if (resource >= RLIM_NLIMITS) return -EINVAL;
2285 if (get_user (r.rlim_cur, &rlim->rlim_cur) ||
2286 __get_user (r.rlim_max, &rlim->rlim_max))
2287 return -EFAULT;
2288 if (r.rlim_cur == RLIM_INFINITY32)
2289 r.rlim_cur = RLIM_INFINITY;
2290 if (r.rlim_max == RLIM_INFINITY32)
2291 r.rlim_max = RLIM_INFINITY;
2292 set_fs (KERNEL_DS);
2293 ret = sys_setrlimit(resource, &r);
2294 set_fs (old_fs);
2295 return ret;
2296}
2297
2298extern asmlinkage int sys_getrusage(int who, struct rusage *ru);
2299
2300asmlinkage int sys32_getrusage(int who, struct rusage32 *ru)
2301{
2302 struct rusage r;
2303 int ret;
2304 mm_segment_t old_fs = get_fs();
2305
2306 set_fs (KERNEL_DS);
2307 ret = sys_getrusage(who, &r);
2308 set_fs (old_fs);
2309 if (put_rusage (ru, &r)) return -EFAULT;
2310 return ret;
2311}
2312
2313
2314#define MAX_SOCK_ADDR 128
2315
2316
2317
2318
2319extern struct socket *sockfd_lookup(int fd, int *err);
2320
2321
2322extern __inline__ void sockfd_put(struct socket *sock)
2323{
2324 fput(sock->file);
2325}
2326
2327struct msghdr32 {
2328 u32 msg_name;
2329 int msg_namelen;
2330 u32 msg_iov;
2331 __kernel_size_t32 msg_iovlen;
2332 u32 msg_control;
2333 __kernel_size_t32 msg_controllen;
2334 unsigned msg_flags;
2335};
2336
2337struct cmsghdr32 {
2338 __kernel_size_t32 cmsg_len;
2339 int cmsg_level;
2340 int cmsg_type;
2341};
2342
2343
2344#define __CMSG32_NXTHDR(ctl, len, cmsg, cmsglen) __cmsg32_nxthdr((ctl),(len),(cmsg),(cmsglen))
2345#define CMSG32_NXTHDR(mhdr, cmsg, cmsglen) cmsg32_nxthdr((mhdr), (cmsg), (cmsglen))
2346
2347#define CMSG32_ALIGN(len) ( ((len)+sizeof(int)-1) & ~(sizeof(int)-1) )
2348
2349#define CMSG32_DATA(cmsg) ((void *)((char *)(cmsg) + CMSG32_ALIGN(sizeof(struct cmsghdr32))))
2350#define CMSG32_SPACE(len) (CMSG32_ALIGN(sizeof(struct cmsghdr32)) + CMSG32_ALIGN(len))
2351#define CMSG32_LEN(len) (CMSG32_ALIGN(sizeof(struct cmsghdr32)) + (len))
2352
2353#define __CMSG32_FIRSTHDR(ctl,len) ((len) >= sizeof(struct cmsghdr32) ? \
2354 (struct cmsghdr32 *)(ctl) : \
2355 (struct cmsghdr32 *)NULL)
2356#define CMSG32_FIRSTHDR(msg) __CMSG32_FIRSTHDR((msg)->msg_control, (msg)->msg_controllen)
2357
2358__inline__ struct cmsghdr32 *__cmsg32_nxthdr(void *__ctl, __kernel_size_t __size,
2359 struct cmsghdr32 *__cmsg, int __cmsg_len)
2360{
2361 struct cmsghdr32 * __ptr;
2362
2363 __ptr = (struct cmsghdr32 *)(((unsigned char *) __cmsg) +
2364 CMSG32_ALIGN(__cmsg_len));
2365 if ((unsigned long)((char*)(__ptr+1) - (char *) __ctl) > __size)
2366 return NULL;
2367
2368 return __ptr;
2369}
2370
2371__inline__ struct cmsghdr32 *cmsg32_nxthdr (struct msghdr *__msg,
2372 struct cmsghdr32 *__cmsg,
2373 int __cmsg_len)
2374{
2375 return __cmsg32_nxthdr(__msg->msg_control, __msg->msg_controllen,
2376 __cmsg, __cmsg_len);
2377}
2378
2379static inline int iov_from_user32_to_kern(struct iovec *kiov,
2380 struct iovec32 *uiov32,
2381 int niov)
2382{
2383 int tot_len = 0;
2384
2385 while(niov > 0) {
2386 u32 len, buf;
2387
2388 if(get_user(len, &uiov32->iov_len) ||
2389 get_user(buf, &uiov32->iov_base)) {
2390 tot_len = -EFAULT;
2391 break;
2392 }
2393 tot_len += len;
2394 kiov->iov_base = (void *)A(buf);
2395 kiov->iov_len = (__kernel_size_t) len;
2396 uiov32++;
2397 kiov++;
2398 niov--;
2399 }
2400 return tot_len;
2401}
2402
2403static inline int msghdr_from_user32_to_kern(struct msghdr *kmsg,
2404 struct msghdr32 *umsg)
2405{
2406 u32 tmp1, tmp2, tmp3;
2407 int err;
2408
2409 err = get_user(tmp1, &umsg->msg_name);
2410 err |= __get_user(tmp2, &umsg->msg_iov);
2411 err |= __get_user(tmp3, &umsg->msg_control);
2412 if (err)
2413 return -EFAULT;
2414
2415 kmsg->msg_name = (void *)A(tmp1);
2416 kmsg->msg_iov = (struct iovec *)A(tmp2);
2417 kmsg->msg_control = (void *)A(tmp3);
2418
2419 err = get_user(kmsg->msg_namelen, &umsg->msg_namelen);
2420 err |= get_user(kmsg->msg_iovlen, &umsg->msg_iovlen);
2421 err |= get_user(kmsg->msg_controllen, &umsg->msg_controllen);
2422 err |= get_user(kmsg->msg_flags, &umsg->msg_flags);
2423
2424 return err;
2425}
2426
2427
2428static int verify_iovec32(struct msghdr *kern_msg, struct iovec *kern_iov,
2429 char *kern_address, int mode)
2430{
2431 int tot_len;
2432
2433 if(kern_msg->msg_namelen) {
2434 if(mode==VERIFY_READ) {
2435 int err = move_addr_to_kernel(kern_msg->msg_name,
2436 kern_msg->msg_namelen,
2437 kern_address);
2438 if(err < 0)
2439 return err;
2440 }
2441 kern_msg->msg_name = kern_address;
2442 } else
2443 kern_msg->msg_name = NULL;
2444
2445 if(kern_msg->msg_iovlen > UIO_FASTIOV) {
2446 kern_iov = kmalloc(kern_msg->msg_iovlen * sizeof(struct iovec),
2447 GFP_KERNEL);
2448 if(!kern_iov)
2449 return -ENOMEM;
2450 }
2451
2452 tot_len = iov_from_user32_to_kern(kern_iov,
2453 (struct iovec32 *)kern_msg->msg_iov,
2454 kern_msg->msg_iovlen);
2455 if(tot_len >= 0)
2456 kern_msg->msg_iov = kern_iov;
2457 else if(kern_msg->msg_iovlen > UIO_FASTIOV)
2458 kfree(kern_iov);
2459
2460 return tot_len;
2461}
2462
2463
2464
2465
2466
2467static int cmsghdr_from_user32_to_kern(struct msghdr *kmsg,
2468 unsigned char *stackbuf, int stackbuf_size)
2469{
2470 struct cmsghdr32 *ucmsg;
2471 struct cmsghdr *kcmsg, *kcmsg_base;
2472 __kernel_size_t32 ucmlen;
2473 __kernel_size_t kcmlen, tmp;
2474
2475 kcmlen = 0;
2476 kcmsg_base = kcmsg = (struct cmsghdr *)stackbuf;
2477 ucmsg = CMSG32_FIRSTHDR(kmsg);
2478 while(ucmsg != NULL) {
2479 if(get_user(ucmlen, &ucmsg->cmsg_len))
2480 return -EFAULT;
2481
2482
2483 if(CMSG32_ALIGN(ucmlen) <
2484 CMSG32_ALIGN(sizeof(struct cmsghdr32)))
2485 return -EINVAL;
2486 if((unsigned long)(((char *)ucmsg - (char *)kmsg->msg_control)
2487 + ucmlen) > kmsg->msg_controllen)
2488 return -EINVAL;
2489
2490 tmp = ((ucmlen - CMSG32_ALIGN(sizeof(*ucmsg))) +
2491 CMSG_ALIGN(sizeof(struct cmsghdr)));
2492 kcmlen += tmp;
2493 ucmsg = CMSG32_NXTHDR(kmsg, ucmsg, ucmlen);
2494 }
2495 if(kcmlen == 0)
2496 return -EINVAL;
2497
2498
2499
2500
2501
2502
2503 if(kcmlen > stackbuf_size)
2504 kcmsg_base = kcmsg = kmalloc(kcmlen, GFP_KERNEL);
2505 if(kcmsg == NULL)
2506 return -ENOBUFS;
2507
2508
2509 memset(kcmsg, 0, kcmlen);
2510 ucmsg = CMSG32_FIRSTHDR(kmsg);
2511 while(ucmsg != NULL) {
2512 __get_user(ucmlen, &ucmsg->cmsg_len);
2513 tmp = ((ucmlen - CMSG32_ALIGN(sizeof(*ucmsg))) +
2514 CMSG_ALIGN(sizeof(struct cmsghdr)));
2515 kcmsg->cmsg_len = tmp;
2516 __get_user(kcmsg->cmsg_level, &ucmsg->cmsg_level);
2517 __get_user(kcmsg->cmsg_type, &ucmsg->cmsg_type);
2518
2519
2520 if(copy_from_user(CMSG_DATA(kcmsg),
2521 CMSG32_DATA(ucmsg),
2522 (ucmlen - CMSG32_ALIGN(sizeof(*ucmsg)))))
2523 goto out_free_efault;
2524
2525
2526 kcmsg = (struct cmsghdr *)((char *)kcmsg + CMSG_ALIGN(tmp));
2527 ucmsg = CMSG32_NXTHDR(kmsg, ucmsg, ucmlen);
2528 }
2529
2530
2531 kmsg->msg_control = kcmsg_base;
2532 kmsg->msg_controllen = kcmlen;
2533 return 0;
2534
2535out_free_efault:
2536 if(kcmsg_base != (struct cmsghdr *)stackbuf)
2537 kfree(kcmsg_base);
2538 return -EFAULT;
2539}
2540
2541static void put_cmsg32(struct msghdr *kmsg, int level, int type,
2542 int len, void *data)
2543{
2544 struct cmsghdr32 *cm = (struct cmsghdr32 *) kmsg->msg_control;
2545 struct cmsghdr32 cmhdr;
2546 int cmlen = CMSG32_LEN(len);
2547
2548 if(cm == NULL || kmsg->msg_controllen < sizeof(*cm)) {
2549 kmsg->msg_flags |= MSG_CTRUNC;
2550 return;
2551 }
2552
2553 if(kmsg->msg_controllen < cmlen) {
2554 kmsg->msg_flags |= MSG_CTRUNC;
2555 cmlen = kmsg->msg_controllen;
2556 }
2557 cmhdr.cmsg_level = level;
2558 cmhdr.cmsg_type = type;
2559 cmhdr.cmsg_len = cmlen;
2560
2561 if(copy_to_user(cm, &cmhdr, sizeof cmhdr))
2562 return;
2563 if(copy_to_user(CMSG32_DATA(cm), data, cmlen - sizeof(struct cmsghdr32)))
2564 return;
2565 cmlen = CMSG32_SPACE(len);
2566 kmsg->msg_control += cmlen;
2567 kmsg->msg_controllen -= cmlen;
2568}
2569
2570static void scm_detach_fds32(struct msghdr *kmsg, struct scm_cookie *scm)
2571{
2572 struct cmsghdr32 *cm = (struct cmsghdr32 *) kmsg->msg_control;
2573 int fdmax = (kmsg->msg_controllen - sizeof(struct cmsghdr32)) / sizeof(int);
2574 int fdnum = scm->fp->count;
2575 struct file **fp = scm->fp->fp;
2576 int *cmfptr;
2577 int err = 0, i;
2578
2579 if (fdnum < fdmax)
2580 fdmax = fdnum;
2581
2582 for (i = 0, cmfptr = (int *) CMSG32_DATA(cm); i < fdmax; i++, cmfptr++) {
2583 int new_fd;
2584 err = get_unused_fd();
2585 if (err < 0)
2586 break;
2587 new_fd = err;
2588 err = put_user(new_fd, cmfptr);
2589 if (err) {
2590 put_unused_fd(new_fd);
2591 break;
2592 }
2593
2594 get_file(fp[i]);
2595 fd_install(new_fd, fp[i]);
2596 }
2597
2598 if (i > 0) {
2599 int cmlen = CMSG32_LEN(i * sizeof(int));
2600 if (!err)
2601 err = put_user(SOL_SOCKET, &cm->cmsg_level);
2602 if (!err)
2603 err = put_user(SCM_RIGHTS, &cm->cmsg_type);
2604 if (!err)
2605 err = put_user(cmlen, &cm->cmsg_len);
2606 if (!err) {
2607 cmlen = CMSG32_SPACE(i * sizeof(int));
2608 kmsg->msg_control += cmlen;
2609 kmsg->msg_controllen -= cmlen;
2610 }
2611 }
2612 if (i < fdnum)
2613 kmsg->msg_flags |= MSG_CTRUNC;
2614
2615
2616
2617
2618
2619 __scm_destroy(scm);
2620}
2621
2622
2623
2624
2625
2626
2627
2628
2629
2630
2631
2632
2633
2634
2635
2636
2637
2638
2639
2640
2641
2642
2643
2644
2645
2646
2647
2648
2649
2650static void cmsg32_recvmsg_fixup(struct msghdr *kmsg, unsigned long orig_cmsg_uptr)
2651{
2652 unsigned char *workbuf, *wp;
2653 unsigned long bufsz, space_avail;
2654 struct cmsghdr *ucmsg;
2655
2656 bufsz = ((unsigned long)kmsg->msg_control) - orig_cmsg_uptr;
2657 space_avail = kmsg->msg_controllen + bufsz;
2658 wp = workbuf = kmalloc(bufsz, GFP_KERNEL);
2659 if(workbuf == NULL)
2660 goto fail;
2661
2662
2663
2664
2665
2666 ucmsg = (struct cmsghdr *) orig_cmsg_uptr;
2667 while(((unsigned long)ucmsg) <=
2668 (((unsigned long)kmsg->msg_control) - sizeof(struct cmsghdr))) {
2669 struct cmsghdr32 *kcmsg32 = (struct cmsghdr32 *) wp;
2670 int clen64, clen32;
2671
2672
2673
2674
2675
2676 __get_user(kcmsg32->cmsg_len, &ucmsg->cmsg_len);
2677 __get_user(kcmsg32->cmsg_level, &ucmsg->cmsg_level);
2678 __get_user(kcmsg32->cmsg_type, &ucmsg->cmsg_type);
2679
2680 clen64 = kcmsg32->cmsg_len;
2681 if (kcmsg32->cmsg_level == SOL_SOCKET &&
2682 kcmsg32->cmsg_type == SO_TIMESTAMP) {
2683 struct timeval tv;
2684 struct timeval32 *tv32;
2685
2686 if (clen64 != CMSG_LEN(sizeof(struct timeval))) {
2687 kfree(workbuf);
2688 goto fail;
2689 }
2690
2691 copy_from_user(&tv, CMSG_DATA(ucmsg), sizeof(tv));
2692 tv32 = (struct timeval32 *)CMSG32_DATA(kcmsg32);
2693 tv32->tv_sec = tv.tv_sec;
2694 tv32->tv_usec = tv.tv_usec;
2695 clen32 = sizeof(*tv32) +
2696 CMSG32_ALIGN(sizeof(struct cmsghdr32));
2697 } else {
2698 copy_from_user(CMSG32_DATA(kcmsg32), CMSG_DATA(ucmsg),
2699 clen64 - CMSG_ALIGN(sizeof(*ucmsg)));
2700 clen32 = ((clen64 - CMSG_ALIGN(sizeof(*ucmsg))) +
2701 CMSG32_ALIGN(sizeof(struct cmsghdr32)));
2702 }
2703 kcmsg32->cmsg_len = clen32;
2704
2705 ucmsg = (struct cmsghdr *) (((char *)ucmsg) + CMSG_ALIGN(clen64));
2706 wp = (((char *)kcmsg32) + CMSG32_ALIGN(clen32));
2707 }
2708
2709
2710 bufsz = (wp - workbuf);
2711 copy_to_user((void *)orig_cmsg_uptr, workbuf, bufsz);
2712
2713 kmsg->msg_control = (struct cmsghdr *)
2714 (((char *)orig_cmsg_uptr) + bufsz);
2715 kmsg->msg_controllen = space_avail - bufsz;
2716
2717 kfree(workbuf);
2718 return;
2719
2720fail:
2721
2722
2723
2724
2725 kmsg->msg_controllen += bufsz;
2726 kmsg->msg_control = (void *) orig_cmsg_uptr;
2727}
2728
2729asmlinkage int sys32_sendmsg(int fd, struct msghdr32 *user_msg, unsigned user_flags)
2730{
2731 struct socket *sock;
2732 char address[MAX_SOCK_ADDR];
2733 struct iovec iov[UIO_FASTIOV];
2734 unsigned char ctl[sizeof(struct cmsghdr) + 20];
2735 unsigned char *ctl_buf = ctl;
2736 struct msghdr kern_msg;
2737 int err, total_len;
2738
2739 if(msghdr_from_user32_to_kern(&kern_msg, user_msg))
2740 return -EFAULT;
2741 if(kern_msg.msg_iovlen > UIO_MAXIOV)
2742 return -EINVAL;
2743 err = verify_iovec32(&kern_msg, iov, address, VERIFY_READ);
2744 if (err < 0)
2745 goto out;
2746 total_len = err;
2747
2748 if(kern_msg.msg_controllen) {
2749 err = cmsghdr_from_user32_to_kern(&kern_msg, ctl, sizeof(ctl));
2750 if(err)
2751 goto out_freeiov;
2752 ctl_buf = kern_msg.msg_control;
2753 }
2754 kern_msg.msg_flags = user_flags;
2755
2756 sock = sockfd_lookup(fd, &err);
2757 if (sock != NULL) {
2758 if (sock->file->f_flags & O_NONBLOCK)
2759 kern_msg.msg_flags |= MSG_DONTWAIT;
2760 err = sock_sendmsg(sock, &kern_msg, total_len);
2761 sockfd_put(sock);
2762 }
2763
2764
2765 if(ctl_buf != ctl)
2766 kfree(ctl_buf);
2767out_freeiov:
2768 if(kern_msg.msg_iov != iov)
2769 kfree(kern_msg.msg_iov);
2770out:
2771 return err;
2772}
2773
2774asmlinkage int sys32_recvmsg(int fd, struct msghdr32 *user_msg, unsigned int user_flags)
2775{
2776 struct iovec iovstack[UIO_FASTIOV];
2777 struct msghdr kern_msg;
2778 char addr[MAX_SOCK_ADDR];
2779 struct socket *sock;
2780 struct iovec *iov = iovstack;
2781 struct sockaddr *uaddr;
2782 int *uaddr_len;
2783 unsigned long cmsg_ptr;
2784 int err, total_len, len = 0;
2785
2786 if(msghdr_from_user32_to_kern(&kern_msg, user_msg))
2787 return -EFAULT;
2788 if(kern_msg.msg_iovlen > UIO_MAXIOV)
2789 return -EINVAL;
2790
2791 uaddr = kern_msg.msg_name;
2792 uaddr_len = &user_msg->msg_namelen;
2793 err = verify_iovec32(&kern_msg, iov, addr, VERIFY_WRITE);
2794 if (err < 0)
2795 goto out;
2796 total_len = err;
2797
2798 cmsg_ptr = (unsigned long) kern_msg.msg_control;
2799 kern_msg.msg_flags = 0;
2800
2801 sock = sockfd_lookup(fd, &err);
2802 if (sock != NULL) {
2803 struct scm_cookie scm;
2804
2805 if (sock->file->f_flags & O_NONBLOCK)
2806 user_flags |= MSG_DONTWAIT;
2807 memset(&scm, 0, sizeof(scm));
2808 err = sock->ops->recvmsg(sock, &kern_msg, total_len,
2809 user_flags, &scm);
2810 if(err >= 0) {
2811 len = err;
2812 if(!kern_msg.msg_control) {
2813 if(sock->passcred || scm.fp)
2814 kern_msg.msg_flags |= MSG_CTRUNC;
2815 if(scm.fp)
2816 __scm_destroy(&scm);
2817 } else {
2818
2819
2820
2821
2822
2823 if((unsigned long) kern_msg.msg_control != cmsg_ptr)
2824 cmsg32_recvmsg_fixup(&kern_msg, cmsg_ptr);
2825
2826
2827 if(sock->passcred)
2828 put_cmsg32(&kern_msg,
2829 SOL_SOCKET, SCM_CREDENTIALS,
2830 sizeof(scm.creds), &scm.creds);
2831 if(scm.fp != NULL)
2832 scm_detach_fds32(&kern_msg, &scm);
2833 }
2834 }
2835 sockfd_put(sock);
2836 }
2837
2838 if(uaddr != NULL && err >= 0)
2839 err = move_addr_to_user(addr, kern_msg.msg_namelen, uaddr, uaddr_len);
2840 if(cmsg_ptr != 0 && err >= 0) {
2841 unsigned long ucmsg_ptr = ((unsigned long)kern_msg.msg_control);
2842 __kernel_size_t32 uclen = (__kernel_size_t32) (ucmsg_ptr - cmsg_ptr);
2843 err |= __put_user(uclen, &user_msg->msg_controllen);
2844 }
2845 if(err >= 0)
2846 err = __put_user(kern_msg.msg_flags, &user_msg->msg_flags);
2847 if(kern_msg.msg_iov != iov)
2848 kfree(kern_msg.msg_iov);
2849out:
2850 if(err < 0)
2851 return err;
2852 return len;
2853}
2854
2855extern asmlinkage int sys_setsockopt(int fd, int level, int optname,
2856 char *optval, int optlen);
2857
2858static int do_netfilter_replace(int fd, int level, int optname,
2859 char *optval, int optlen)
2860{
2861 struct ipt_replace32 {
2862 char name[IPT_TABLE_MAXNAMELEN];
2863 __u32 valid_hooks;
2864 __u32 num_entries;
2865 __u32 size;
2866 __u32 hook_entry[NF_IP_NUMHOOKS];
2867 __u32 underflow[NF_IP_NUMHOOKS];
2868 __u32 num_counters;
2869 __u32 counters;
2870 struct ipt_entry entries[0];
2871 } *repl32 = (struct ipt_replace32 *)optval;
2872 struct ipt_replace *krepl;
2873 struct ipt_counters *counters32;
2874 __u32 origsize;
2875 unsigned int kreplsize, kcountersize;
2876 mm_segment_t old_fs;
2877 int ret;
2878
2879 if (optlen < sizeof(repl32))
2880 return -EINVAL;
2881
2882 if (copy_from_user(&origsize,
2883 &repl32->size,
2884 sizeof(origsize)))
2885 return -EFAULT;
2886
2887 kreplsize = sizeof(*krepl) + origsize;
2888 kcountersize = krepl->num_counters * sizeof(struct ipt_counters);
2889
2890
2891 if (optlen != kreplsize)
2892 return -ENOPROTOOPT;
2893
2894 krepl = (struct ipt_replace *)kmalloc(kreplsize, GFP_KERNEL);
2895 if (krepl == NULL)
2896 return -ENOMEM;
2897
2898 if (copy_from_user(krepl, optval, kreplsize)) {
2899 kfree(krepl);
2900 return -EFAULT;
2901 }
2902
2903 counters32 = (struct ipt_counters *)AA(
2904 ((struct ipt_replace32 *)krepl)->counters);
2905
2906 kcountersize = krepl->num_counters * sizeof(struct ipt_counters);
2907 krepl->counters = (struct ipt_counters *)kmalloc(
2908 kcountersize, GFP_KERNEL);
2909 if (krepl->counters == NULL) {
2910 kfree(krepl);
2911 return -ENOMEM;
2912 }
2913
2914 old_fs = get_fs();
2915 set_fs(KERNEL_DS);
2916 ret = sys_setsockopt(fd, level, optname,
2917 (char *)krepl, kreplsize);
2918 set_fs(old_fs);
2919
2920 if (ret == 0 &&
2921 copy_to_user(counters32, krepl->counters, kcountersize))
2922 ret = -EFAULT;
2923
2924 kfree(krepl->counters);
2925 kfree(krepl);
2926
2927 return ret;
2928}
2929
2930static int do_set_attach_filter(int fd, int level, int optname,
2931 char *optval, int optlen)
2932{
2933 struct sock_fprog32 {
2934 __u16 len;
2935 __u32 filter;
2936 } *fprog32 = (struct sock_fprog32 *)optval;
2937 struct sock_fprog kfprog;
2938 struct sock_filter *kfilter;
2939 unsigned int fsize;
2940 mm_segment_t old_fs;
2941 __u32 uptr;
2942 int ret;
2943
2944 if (get_user(kfprog.len, &fprog32->len) ||
2945 __get_user(uptr, &fprog32->filter))
2946 return -EFAULT;
2947
2948 kfprog.filter = (struct sock_filter *)A(uptr);
2949 fsize = kfprog.len * sizeof(struct sock_filter);
2950
2951 kfilter = (struct sock_filter *)kmalloc(fsize, GFP_KERNEL);
2952 if (kfilter == NULL)
2953 return -ENOMEM;
2954
2955 if (copy_from_user(kfilter, kfprog.filter, fsize)) {
2956 kfree(kfilter);
2957 return -EFAULT;
2958 }
2959
2960 kfprog.filter = kfilter;
2961
2962 old_fs = get_fs();
2963 set_fs(KERNEL_DS);
2964 ret = sys_setsockopt(fd, level, optname,
2965 (char *)&kfprog, sizeof(kfprog));
2966 set_fs(old_fs);
2967
2968 kfree(kfilter);
2969
2970 return ret;
2971}
2972
2973static int do_set_sock_timeout(int fd, int level, int optname, char *optval, int optlen)
2974{
2975 struct timeval32 *up = (struct timeval32 *) optval;
2976 struct timeval ktime;
2977 mm_segment_t old_fs;
2978 int err;
2979
2980 if (optlen < sizeof(*up))
2981 return -EINVAL;
2982 if (get_user(ktime.tv_sec, &up->tv_sec) ||
2983 __get_user(ktime.tv_usec, &up->tv_usec))
2984 return -EFAULT;
2985 old_fs = get_fs();
2986 set_fs(KERNEL_DS);
2987 err = sys_setsockopt(fd, level, optname, (char *) &ktime, sizeof(ktime));
2988 set_fs(old_fs);
2989
2990 return err;
2991}
2992
2993asmlinkage int sys32_setsockopt(int fd, int level, int optname,
2994 char *optval, int optlen)
2995{
2996 if (optname == IPT_SO_SET_REPLACE)
2997 return do_netfilter_replace(fd, level, optname,
2998 optval, optlen);
2999 if (level == SOL_SOCKET && optname == SO_ATTACH_FILTER)
3000 return do_set_attach_filter(fd, level, optname,
3001 optval, optlen);
3002 if (level == SOL_SOCKET &&
3003 (optname == SO_RCVTIMEO || optname == SO_SNDTIMEO))
3004 return do_set_sock_timeout(fd, level, optname, optval, optlen);
3005
3006 return sys_setsockopt(fd, level, optname, optval, optlen);
3007}
3008
3009extern asmlinkage long sys_getsockopt(int fd, int level, int optname,
3010 char *optval, int *optlen);
3011
3012static int do_get_sock_timeout(int fd, int level, int optname, char *optval, int *optlen)
3013{
3014 struct timeval32 *up = (struct timeval32 *) optval;
3015 struct timeval ktime;
3016 mm_segment_t old_fs;
3017 int len, err;
3018
3019 if (get_user(len, optlen))
3020 return -EFAULT;
3021 if (len < sizeof(*up))
3022 return -EINVAL;
3023 len = sizeof(ktime);
3024 old_fs = get_fs();
3025 set_fs(KERNEL_DS);
3026 err = sys_getsockopt(fd, level, optname, (char *) &ktime, &len);
3027 set_fs(old_fs);
3028
3029 if (!err) {
3030 if (put_user(sizeof(*up), optlen) ||
3031 put_user(ktime.tv_sec, &up->tv_sec) ||
3032 __put_user(ktime.tv_usec, &up->tv_usec))
3033 err = -EFAULT;
3034 }
3035 return err;
3036}
3037
3038asmlinkage int sys32_getsockopt(int fd, int level, int optname,
3039 char *optval, int *optlen)
3040{
3041 if (optname == SO_RCVTIMEO || optname == SO_SNDTIMEO)
3042 return do_get_sock_timeout(fd, level, optname, optval, optlen);
3043 return sys_getsockopt(fd, level, optname, optval, optlen);
3044}
3045
3046extern void check_pending(int signum);
3047
3048asmlinkage int sys32_sigaction (int sig, struct old_sigaction32 *act, struct old_sigaction32 *oact)
3049{
3050 struct k_sigaction new_ka, old_ka;
3051 int ret;
3052
3053 if(sig < 0) {
3054 current->thread.flags |= SPARC_FLAG_NEWSIGNALS;
3055 sig = -sig;
3056 }
3057
3058 if (act) {
3059 old_sigset_t32 mask;
3060 u32 u_handler, u_restorer;
3061
3062 ret = get_user(u_handler, &act->sa_handler);
3063 new_ka.sa.sa_handler = (void *) (long) u_handler;
3064 ret |= __get_user(u_restorer, &act->sa_restorer);
3065 new_ka.sa.sa_restorer = (void *) (long) u_restorer;
3066 ret |= __get_user(new_ka.sa.sa_flags, &act->sa_flags);
3067 ret |= __get_user(mask, &act->sa_mask);
3068 if (ret)
3069 return ret;
3070 new_ka.ka_restorer = NULL;
3071 siginitset(&new_ka.sa.sa_mask, mask);
3072 }
3073
3074 ret = do_sigaction(sig, act ? &new_ka : NULL, oact ? &old_ka : NULL);
3075
3076 if (!ret && oact) {
3077 ret = put_user((long)old_ka.sa.sa_handler, &oact->sa_handler);
3078 ret |= __put_user((long)old_ka.sa.sa_restorer, &oact->sa_restorer);
3079 ret |= __put_user(old_ka.sa.sa_flags, &oact->sa_flags);
3080 ret |= __put_user(old_ka.sa.sa_mask.sig[0], &oact->sa_mask);
3081 }
3082
3083 return ret;
3084}
3085
3086asmlinkage int
3087sys32_rt_sigaction(int sig, struct sigaction32 *act, struct sigaction32 *oact,
3088 void *restorer, __kernel_size_t32 sigsetsize)
3089{
3090 struct k_sigaction new_ka, old_ka;
3091 int ret;
3092 sigset_t32 set32;
3093
3094
3095 if (sigsetsize != sizeof(sigset_t32))
3096 return -EINVAL;
3097
3098
3099
3100
3101 current->thread.flags |= SPARC_FLAG_NEWSIGNALS;
3102
3103 if (act) {
3104 u32 u_handler, u_restorer;
3105
3106 new_ka.ka_restorer = restorer;
3107 ret = get_user(u_handler, &act->sa_handler);
3108 new_ka.sa.sa_handler = (void *) (long) u_handler;
3109 ret |= __copy_from_user(&set32, &act->sa_mask, sizeof(sigset_t32));
3110 switch (_NSIG_WORDS) {
3111 case 4: new_ka.sa.sa_mask.sig[3] = set32.sig[6] | (((long)set32.sig[7]) << 32);
3112 case 3: new_ka.sa.sa_mask.sig[2] = set32.sig[4] | (((long)set32.sig[5]) << 32);
3113 case 2: new_ka.sa.sa_mask.sig[1] = set32.sig[2] | (((long)set32.sig[3]) << 32);
3114 case 1: new_ka.sa.sa_mask.sig[0] = set32.sig[0] | (((long)set32.sig[1]) << 32);
3115 }
3116 ret |= __get_user(new_ka.sa.sa_flags, &act->sa_flags);
3117 ret |= __get_user(u_restorer, &act->sa_restorer);
3118 new_ka.sa.sa_restorer = (void *) (long) u_restorer;
3119 if (ret)
3120 return -EFAULT;
3121 }
3122
3123 ret = do_sigaction(sig, act ? &new_ka : NULL, oact ? &old_ka : NULL);
3124
3125 if (!ret && oact) {
3126 switch (_NSIG_WORDS) {
3127 case 4: set32.sig[7] = (old_ka.sa.sa_mask.sig[3] >> 32); set32.sig[6] = old_ka.sa.sa_mask.sig[3];
3128 case 3: set32.sig[5] = (old_ka.sa.sa_mask.sig[2] >> 32); set32.sig[4] = old_ka.sa.sa_mask.sig[2];
3129 case 2: set32.sig[3] = (old_ka.sa.sa_mask.sig[1] >> 32); set32.sig[2] = old_ka.sa.sa_mask.sig[1];
3130 case 1: set32.sig[1] = (old_ka.sa.sa_mask.sig[0] >> 32); set32.sig[0] = old_ka.sa.sa_mask.sig[0];
3131 }
3132 ret = put_user((long)old_ka.sa.sa_handler, &oact->sa_handler);
3133 ret |= __copy_to_user(&oact->sa_mask, &set32, sizeof(sigset_t32));
3134 ret |= __put_user(old_ka.sa.sa_flags, &oact->sa_flags);
3135 ret |= __put_user((long)old_ka.sa.sa_restorer, &oact->sa_restorer);
3136 if (ret)
3137 ret = -EFAULT;
3138 }
3139
3140 return ret;
3141}
3142
3143
3144
3145
3146
3147static int count32(u32 * argv, int max)
3148{
3149 int i = 0;
3150
3151 if (argv != NULL) {
3152 for (;;) {
3153 u32 p; int error;
3154
3155 error = get_user(p,argv);
3156 if (error)
3157 return error;
3158 if (!p)
3159 break;
3160 argv++;
3161 if (++i > max)
3162 return -E2BIG;
3163 }
3164 }
3165 return i;
3166}
3167
3168
3169
3170
3171
3172
3173static int copy_strings32(int argc, u32 * argv, struct linux_binprm *bprm)
3174{
3175 while (argc-- > 0) {
3176 u32 str;
3177 int len;
3178 unsigned long pos;
3179
3180 if (get_user(str, argv + argc) ||
3181 !str ||
3182 !(len = strnlen_user((char *)A(str), bprm->p)))
3183 return -EFAULT;
3184
3185 if (bprm->p < len)
3186 return -E2BIG;
3187
3188 bprm->p -= len;
3189
3190 pos = bprm->p;
3191 while (len) {
3192 char *kaddr;
3193 struct page *page;
3194 int offset, bytes_to_copy, new, err;
3195
3196 offset = pos % PAGE_SIZE;
3197 page = bprm->page[pos / PAGE_SIZE];
3198 new = 0;
3199 if (!page) {
3200 page = alloc_page(GFP_USER);
3201 bprm->page[pos / PAGE_SIZE] = page;
3202 if (!page)
3203 return -ENOMEM;
3204 new = 1;
3205 }
3206 kaddr = kmap(page);
3207
3208 if (new && offset)
3209 memset(kaddr, 0, offset);
3210 bytes_to_copy = PAGE_SIZE - offset;
3211 if (bytes_to_copy > len) {
3212 bytes_to_copy = len;
3213 if (new)
3214 memset(kaddr+offset+len, 0,
3215 PAGE_SIZE-offset-len);
3216 }
3217
3218 err = copy_from_user(kaddr + offset, (char *)A(str),
3219 bytes_to_copy);
3220 kunmap(page);
3221
3222 if (err)
3223 return -EFAULT;
3224
3225 pos += bytes_to_copy;
3226 str += bytes_to_copy;
3227 len -= bytes_to_copy;
3228 }
3229 }
3230 return 0;
3231}
3232
3233
3234
3235
3236static inline int
3237do_execve32(char * filename, u32 * argv, u32 * envp, struct pt_regs * regs)
3238{
3239 struct linux_binprm bprm;
3240 struct file * file;
3241 int retval;
3242 int i;
3243
3244 bprm.p = PAGE_SIZE*MAX_ARG_PAGES-sizeof(void *);
3245 memset(bprm.page, 0, MAX_ARG_PAGES * sizeof(bprm.page[0]));
3246
3247 file = open_exec(filename);
3248
3249 retval = PTR_ERR(file);
3250 if (IS_ERR(file))
3251 return retval;
3252
3253 bprm.file = file;
3254 bprm.filename = filename;
3255 bprm.sh_bang = 0;
3256 bprm.loader = 0;
3257 bprm.exec = 0;
3258 if ((bprm.argc = count32(argv, bprm.p / sizeof(u32))) < 0) {
3259 allow_write_access(file);
3260 fput(file);
3261 return bprm.argc;
3262 }
3263 if ((bprm.envc = count32(envp, bprm.p / sizeof(u32))) < 0) {
3264 allow_write_access(file);
3265 fput(file);
3266 return bprm.envc;
3267 }
3268
3269 retval = prepare_binprm(&bprm);
3270 if (retval < 0)
3271 goto out;
3272
3273 retval = copy_strings_kernel(1, &bprm.filename, &bprm);
3274 if (retval < 0)
3275 goto out;
3276
3277 bprm.exec = bprm.p;
3278 retval = copy_strings32(bprm.envc, envp, &bprm);
3279 if (retval < 0)
3280 goto out;
3281
3282 retval = copy_strings32(bprm.argc, argv, &bprm);
3283 if (retval < 0)
3284 goto out;
3285
3286 retval = search_binary_handler(&bprm, regs);
3287 if (retval >= 0)
3288
3289 return retval;
3290
3291out:
3292
3293 allow_write_access(bprm.file);
3294 if (bprm.file)
3295 fput(bprm.file);
3296
3297 for (i=0 ; i<MAX_ARG_PAGES ; i++)
3298 if (bprm.page[i])
3299 __free_page(bprm.page[i]);
3300
3301 return retval;
3302}
3303
3304
3305
3306
3307
3308asmlinkage int sparc32_execve(struct pt_regs *regs)
3309{
3310 int error, base = 0;
3311 char *filename;
3312
3313
3314
3315
3316 if((u32)regs->u_regs[UREG_G1] == 0)
3317 base = 1;
3318
3319 filename = getname((char *)AA(regs->u_regs[base + UREG_I0]));
3320 error = PTR_ERR(filename);
3321 if(IS_ERR(filename))
3322 goto out;
3323 error = do_execve32(filename,
3324 (u32 *)AA((u32)regs->u_regs[base + UREG_I1]),
3325 (u32 *)AA((u32)regs->u_regs[base + UREG_I2]), regs);
3326 putname(filename);
3327
3328 if(!error) {
3329 fprs_write(0);
3330 current->thread.xfsr[0] = 0;
3331 current->thread.fpsaved[0] = 0;
3332 regs->tstate &= ~TSTATE_PEF;
3333 }
3334out:
3335 return error;
3336}
3337
3338#ifdef CONFIG_MODULES
3339
3340extern asmlinkage unsigned long sys_create_module(const char *name_user, size_t size);
3341
3342asmlinkage unsigned long sys32_create_module(const char *name_user, __kernel_size_t32 size)
3343{
3344 return sys_create_module(name_user, (size_t)size);
3345}
3346
3347extern asmlinkage int sys_init_module(const char *name_user, struct module *mod_user);
3348
3349
3350
3351
3352asmlinkage int sys32_init_module(const char *name_user, struct module *mod_user)
3353{
3354 return sys_init_module(name_user, mod_user);
3355}
3356
3357extern asmlinkage int sys_delete_module(const char *name_user);
3358
3359asmlinkage int sys32_delete_module(const char *name_user)
3360{
3361 return sys_delete_module(name_user);
3362}
3363
3364struct module_info32 {
3365 u32 addr;
3366 u32 size;
3367 u32 flags;
3368 s32 usecount;
3369};
3370
3371
3372
3373static inline long
3374get_mod_name(const char *user_name, char **buf)
3375{
3376 unsigned long page;
3377 long retval;
3378
3379 if ((unsigned long)user_name >= TASK_SIZE
3380 && !segment_eq(get_fs (), KERNEL_DS))
3381 return -EFAULT;
3382
3383 page = __get_free_page(GFP_KERNEL);
3384 if (!page)
3385 return -ENOMEM;
3386
3387 retval = strncpy_from_user((char *)page, user_name, PAGE_SIZE);
3388 if (retval > 0) {
3389 if (retval < PAGE_SIZE) {
3390 *buf = (char *)page;
3391 return retval;
3392 }
3393 retval = -ENAMETOOLONG;
3394 } else if (!retval)
3395 retval = -EINVAL;
3396
3397 free_page(page);
3398 return retval;
3399}
3400
3401static inline void
3402put_mod_name(char *buf)
3403{
3404 free_page((unsigned long)buf);
3405}
3406
3407static __inline__ struct module *find_module(const char *name)
3408{
3409 struct module *mod;
3410
3411 for (mod = module_list; mod ; mod = mod->next) {
3412 if (mod->flags & MOD_DELETED)
3413 continue;
3414 if (!strcmp(mod->name, name))
3415 break;
3416 }
3417
3418 return mod;
3419}
3420
3421static int
3422qm_modules(char *buf, size_t bufsize, __kernel_size_t32 *ret)
3423{
3424 struct module *mod;
3425 size_t nmod, space, len;
3426
3427 nmod = space = 0;
3428
3429 for (mod = module_list; mod->next != NULL; mod = mod->next, ++nmod) {
3430 len = strlen(mod->name)+1;
3431 if (len > bufsize)
3432 goto calc_space_needed;
3433 if (copy_to_user(buf, mod->name, len))
3434 return -EFAULT;
3435 buf += len;
3436 bufsize -= len;
3437 space += len;
3438 }
3439
3440 if (put_user(nmod, ret))
3441 return -EFAULT;
3442 else
3443 return 0;
3444
3445calc_space_needed:
3446 space += len;
3447 while ((mod = mod->next)->next != NULL)
3448 space += strlen(mod->name)+1;
3449
3450 if (put_user(space, ret))
3451 return -EFAULT;
3452 else
3453 return -ENOSPC;
3454}
3455
3456static int
3457qm_deps(struct module *mod, char *buf, size_t bufsize, __kernel_size_t32 *ret)
3458{
3459 size_t i, space, len;
3460
3461 if (mod->next == NULL)
3462 return -EINVAL;
3463 if (!MOD_CAN_QUERY(mod))
3464 return put_user(0, ret);
3465
3466 space = 0;
3467 for (i = 0; i < mod->ndeps; ++i) {
3468 const char *dep_name = mod->deps[i].dep->name;
3469
3470 len = strlen(dep_name)+1;
3471 if (len > bufsize)
3472 goto calc_space_needed;
3473 if (copy_to_user(buf, dep_name, len))
3474 return -EFAULT;
3475 buf += len;
3476 bufsize -= len;
3477 space += len;
3478 }
3479
3480 return put_user(i, ret);
3481
3482calc_space_needed:
3483 space += len;
3484 while (++i < mod->ndeps)
3485 space += strlen(mod->deps[i].dep->name)+1;
3486
3487 if (put_user(space, ret))
3488 return -EFAULT;
3489 else
3490 return -ENOSPC;
3491}
3492
3493static int
3494qm_refs(struct module *mod, char *buf, size_t bufsize, __kernel_size_t32 *ret)
3495{
3496 size_t nrefs, space, len;
3497 struct module_ref *ref;
3498
3499 if (mod->next == NULL)
3500 return -EINVAL;
3501 if (!MOD_CAN_QUERY(mod))
3502 if (put_user(0, ret))
3503 return -EFAULT;
3504 else
3505 return 0;
3506
3507 space = 0;
3508 for (nrefs = 0, ref = mod->refs; ref ; ++nrefs, ref = ref->next_ref) {
3509 const char *ref_name = ref->ref->name;
3510
3511 len = strlen(ref_name)+1;
3512 if (len > bufsize)
3513 goto calc_space_needed;
3514 if (copy_to_user(buf, ref_name, len))
3515 return -EFAULT;
3516 buf += len;
3517 bufsize -= len;
3518 space += len;
3519 }
3520
3521 if (put_user(nrefs, ret))
3522 return -EFAULT;
3523 else
3524 return 0;
3525
3526calc_space_needed:
3527 space += len;
3528 while ((ref = ref->next_ref) != NULL)
3529 space += strlen(ref->ref->name)+1;
3530
3531 if (put_user(space, ret))
3532 return -EFAULT;
3533 else
3534 return -ENOSPC;
3535}
3536
3537static inline int
3538qm_symbols(struct module *mod, char *buf, size_t bufsize, __kernel_size_t32 *ret)
3539{
3540 size_t i, space, len;
3541 struct module_symbol *s;
3542 char *strings;
3543 unsigned *vals;
3544
3545 if (!MOD_CAN_QUERY(mod))
3546 if (put_user(0, ret))
3547 return -EFAULT;
3548 else
3549 return 0;
3550
3551 space = mod->nsyms * 2*sizeof(u32);
3552
3553 i = len = 0;
3554 s = mod->syms;
3555
3556 if (space > bufsize)
3557 goto calc_space_needed;
3558
3559 if (!access_ok(VERIFY_WRITE, buf, space))
3560 return -EFAULT;
3561
3562 bufsize -= space;
3563 vals = (unsigned *)buf;
3564 strings = buf+space;
3565
3566 for (; i < mod->nsyms ; ++i, ++s, vals += 2) {
3567 len = strlen(s->name)+1;
3568 if (len > bufsize)
3569 goto calc_space_needed;
3570
3571 if (copy_to_user(strings, s->name, len)
3572 || __put_user(s->value, vals+0)
3573 || __put_user(space, vals+1))
3574 return -EFAULT;
3575
3576 strings += len;
3577 bufsize -= len;
3578 space += len;
3579 }
3580
3581 if (put_user(i, ret))
3582 return -EFAULT;
3583 else
3584 return 0;
3585
3586calc_space_needed:
3587 for (; i < mod->nsyms; ++i, ++s)
3588 space += strlen(s->name)+1;
3589
3590 if (put_user(space, ret))
3591 return -EFAULT;
3592 else
3593 return -ENOSPC;
3594}
3595
3596static inline int
3597qm_info(struct module *mod, char *buf, size_t bufsize, __kernel_size_t32 *ret)
3598{
3599 int error = 0;
3600
3601 if (mod->next == NULL)
3602 return -EINVAL;
3603
3604 if (sizeof(struct module_info32) <= bufsize) {
3605 struct module_info32 info;
3606 info.addr = (unsigned long)mod;
3607 info.size = mod->size;
3608 info.flags = mod->flags;
3609 info.usecount =
3610 ((mod_member_present(mod, can_unload)
3611 && mod->can_unload)
3612 ? -1 : atomic_read(&mod->uc.usecount));
3613
3614 if (copy_to_user(buf, &info, sizeof(struct module_info32)))
3615 return -EFAULT;
3616 } else
3617 error = -ENOSPC;
3618
3619 if (put_user(sizeof(struct module_info32), ret))
3620 return -EFAULT;
3621
3622 return error;
3623}
3624
3625asmlinkage int sys32_query_module(char *name_user, int which, char *buf, __kernel_size_t32 bufsize, u32 ret)
3626{
3627 struct module *mod;
3628 int err;
3629
3630 lock_kernel();
3631 if (name_user == 0) {
3632
3633 for(mod = module_list; mod->next != NULL; mod = mod->next)
3634 ;
3635 } else {
3636 long namelen;
3637 char *name;
3638
3639 if ((namelen = get_mod_name(name_user, &name)) < 0) {
3640 err = namelen;
3641 goto out;
3642 }
3643 err = -ENOENT;
3644 if (namelen == 0) {
3645
3646 for(mod = module_list; mod->next != NULL; mod = mod->next)
3647 ;
3648 } else if ((mod = find_module(name)) == NULL) {
3649 put_mod_name(name);
3650 goto out;
3651 }
3652 put_mod_name(name);
3653 }
3654
3655 switch (which)
3656 {
3657 case 0:
3658 err = 0;
3659 break;
3660 case QM_MODULES:
3661 err = qm_modules(buf, bufsize, (__kernel_size_t32 *)AA(ret));
3662 break;
3663 case QM_DEPS:
3664 err = qm_deps(mod, buf, bufsize, (__kernel_size_t32 *)AA(ret));
3665 break;
3666 case QM_REFS:
3667 err = qm_refs(mod, buf, bufsize, (__kernel_size_t32 *)AA(ret));
3668 break;
3669 case QM_SYMBOLS:
3670 err = qm_symbols(mod, buf, bufsize, (__kernel_size_t32 *)AA(ret));
3671 break;
3672 case QM_INFO:
3673 err = qm_info(mod, buf, bufsize, (__kernel_size_t32 *)AA(ret));
3674 break;
3675 default:
3676 err = -EINVAL;
3677 break;
3678 }
3679out:
3680 unlock_kernel();
3681 return err;
3682}
3683
3684struct kernel_sym32 {
3685 u32 value;
3686 char name[60];
3687};
3688
3689extern asmlinkage int sys_get_kernel_syms(struct kernel_sym *table);
3690
3691asmlinkage int sys32_get_kernel_syms(struct kernel_sym32 *table)
3692{
3693 int len, i;
3694 struct kernel_sym *tbl;
3695 mm_segment_t old_fs;
3696
3697 len = sys_get_kernel_syms(NULL);
3698 if (!table) return len;
3699 tbl = kmalloc (len * sizeof (struct kernel_sym), GFP_KERNEL);
3700 if (!tbl) return -ENOMEM;
3701 old_fs = get_fs();
3702 set_fs (KERNEL_DS);
3703 sys_get_kernel_syms(tbl);
3704 set_fs (old_fs);
3705 for (i = 0; i < len; i++, table++) {
3706 if (put_user (tbl[i].value, &table->value) ||
3707 copy_to_user (table->name, tbl[i].name, 60))
3708 break;
3709 }
3710 kfree (tbl);
3711 return i;
3712}
3713
3714#else
3715
3716asmlinkage unsigned long
3717sys32_create_module(const char *name_user, size_t size)
3718{
3719 return -ENOSYS;
3720}
3721
3722asmlinkage int
3723sys32_init_module(const char *name_user, struct module *mod_user)
3724{
3725 return -ENOSYS;
3726}
3727
3728asmlinkage int
3729sys32_delete_module(const char *name_user)
3730{
3731 return -ENOSYS;
3732}
3733
3734asmlinkage int
3735sys32_query_module(const char *name_user, int which, char *buf, size_t bufsize,
3736 size_t *ret)
3737{
3738
3739
3740 if (which == 0)
3741 return 0;
3742
3743 return -ENOSYS;
3744}
3745
3746asmlinkage int
3747sys32_get_kernel_syms(struct kernel_sym *table)
3748{
3749 return -ENOSYS;
3750}
3751
3752#endif
3753
3754#if defined(CONFIG_NFSD) || defined(CONFIG_NFSD_MODULE)
3755
3756struct nfsctl_svc32 {
3757 u16 svc32_port;
3758 s32 svc32_nthreads;
3759};
3760
3761struct nfsctl_client32 {
3762 s8 cl32_ident[NFSCLNT_IDMAX+1];
3763 s32 cl32_naddr;
3764 struct in_addr cl32_addrlist[NFSCLNT_ADDRMAX];
3765 s32 cl32_fhkeytype;
3766 s32 cl32_fhkeylen;
3767 u8 cl32_fhkey[NFSCLNT_KEYMAX];
3768};
3769
3770struct nfsctl_export32 {
3771 s8 ex32_client[NFSCLNT_IDMAX+1];
3772 s8 ex32_path[NFS_MAXPATHLEN+1];
3773 __kernel_dev_t32 ex32_dev;
3774 __kernel_ino_t32 ex32_ino;
3775 s32 ex32_flags;
3776 __kernel_uid_t32 ex32_anon_uid;
3777 __kernel_gid_t32 ex32_anon_gid;
3778};
3779
3780struct nfsctl_uidmap32 {
3781 u32 ug32_ident;
3782 __kernel_uid_t32 ug32_uidbase;
3783 s32 ug32_uidlen;
3784 u32 ug32_udimap;
3785 __kernel_uid_t32 ug32_gidbase;
3786 s32 ug32_gidlen;
3787 u32 ug32_gdimap;
3788};
3789
3790struct nfsctl_fhparm32 {
3791 struct sockaddr gf32_addr;
3792 __kernel_dev_t32 gf32_dev;
3793 __kernel_ino_t32 gf32_ino;
3794 s32 gf32_version;
3795};
3796
3797struct nfsctl_fdparm32 {
3798 struct sockaddr gd32_addr;
3799 s8 gd32_path[NFS_MAXPATHLEN+1];
3800 s32 gd32_version;
3801};
3802
3803struct nfsctl_fsparm32 {
3804 struct sockaddr gd32_addr;
3805 s8 gd32_path[NFS_MAXPATHLEN+1];
3806 s32 gd32_maxlen;
3807};
3808
3809struct nfsctl_arg32 {
3810 s32 ca32_version;
3811 union {
3812 struct nfsctl_svc32 u32_svc;
3813 struct nfsctl_client32 u32_client;
3814 struct nfsctl_export32 u32_export;
3815 struct nfsctl_uidmap32 u32_umap;
3816 struct nfsctl_fhparm32 u32_getfh;
3817 struct nfsctl_fdparm32 u32_getfd;
3818 struct nfsctl_fsparm32 u32_getfs;
3819 } u;
3820#define ca32_svc u.u32_svc
3821#define ca32_client u.u32_client
3822#define ca32_export u.u32_export
3823#define ca32_umap u.u32_umap
3824#define ca32_getfh u.u32_getfh
3825#define ca32_getfd u.u32_getfd
3826#define ca32_getfs u.u32_getfs
3827#define ca32_authd u.u32_authd
3828};
3829
3830union nfsctl_res32 {
3831 __u8 cr32_getfh[NFS_FHSIZE];
3832 struct knfsd_fh cr32_getfs;
3833};
3834
3835static int nfs_svc32_trans(struct nfsctl_arg *karg, struct nfsctl_arg32 *arg32)
3836{
3837 int err;
3838
3839 err = __get_user(karg->ca_version, &arg32->ca32_version);
3840 err |= __get_user(karg->ca_svc.svc_port, &arg32->ca32_svc.svc32_port);
3841 err |= __get_user(karg->ca_svc.svc_nthreads, &arg32->ca32_svc.svc32_nthreads);
3842 return err;
3843}
3844
3845static int nfs_clnt32_trans(struct nfsctl_arg *karg, struct nfsctl_arg32 *arg32)
3846{
3847 int err;
3848
3849 err = __get_user(karg->ca_version, &arg32->ca32_version);
3850 err |= copy_from_user(&karg->ca_client.cl_ident[0],
3851 &arg32->ca32_client.cl32_ident[0],
3852 NFSCLNT_IDMAX);
3853 err |= __get_user(karg->ca_client.cl_naddr, &arg32->ca32_client.cl32_naddr);
3854 err |= copy_from_user(&karg->ca_client.cl_addrlist[0],
3855 &arg32->ca32_client.cl32_addrlist[0],
3856 (sizeof(struct in_addr) * NFSCLNT_ADDRMAX));
3857 err |= __get_user(karg->ca_client.cl_fhkeytype,
3858 &arg32->ca32_client.cl32_fhkeytype);
3859 err |= __get_user(karg->ca_client.cl_fhkeylen,
3860 &arg32->ca32_client.cl32_fhkeylen);
3861 err |= copy_from_user(&karg->ca_client.cl_fhkey[0],
3862 &arg32->ca32_client.cl32_fhkey[0],
3863 NFSCLNT_KEYMAX);
3864 return (err ? -EFAULT : 0);
3865}
3866
3867static int nfs_exp32_trans(struct nfsctl_arg *karg, struct nfsctl_arg32 *arg32)
3868{
3869 int err;
3870
3871 err = __get_user(karg->ca_version, &arg32->ca32_version);
3872 err |= copy_from_user(&karg->ca_export.ex_client[0],
3873 &arg32->ca32_export.ex32_client[0],
3874 NFSCLNT_IDMAX);
3875 err |= copy_from_user(&karg->ca_export.ex_path[0],
3876 &arg32->ca32_export.ex32_path[0],
3877 NFS_MAXPATHLEN);
3878 err |= __get_user(karg->ca_export.ex_dev,
3879 &arg32->ca32_export.ex32_dev);
3880 err |= __get_user(karg->ca_export.ex_ino,
3881 &arg32->ca32_export.ex32_ino);
3882 err |= __get_user(karg->ca_export.ex_flags,
3883 &arg32->ca32_export.ex32_flags);
3884 err |= __get_user(karg->ca_export.ex_anon_uid,
3885 &arg32->ca32_export.ex32_anon_uid);
3886 err |= __get_user(karg->ca_export.ex_anon_gid,
3887 &arg32->ca32_export.ex32_anon_gid);
3888 karg->ca_export.ex_anon_uid = high2lowuid(karg->ca_export.ex_anon_uid);
3889 karg->ca_export.ex_anon_gid = high2lowgid(karg->ca_export.ex_anon_gid);
3890 return (err ? -EFAULT : 0);
3891}
3892
3893static int nfs_uud32_trans(struct nfsctl_arg *karg, struct nfsctl_arg32 *arg32)
3894{
3895 u32 uaddr;
3896 int i;
3897 int err;
3898
3899 memset(karg, 0, sizeof(*karg));
3900 if(__get_user(karg->ca_version, &arg32->ca32_version))
3901 return -EFAULT;
3902 karg->ca_umap.ug_ident = (char *)get_free_page(GFP_USER);
3903 if(!karg->ca_umap.ug_ident)
3904 return -ENOMEM;
3905 err = __get_user(uaddr, &arg32->ca32_umap.ug32_ident);
3906 if(strncpy_from_user(karg->ca_umap.ug_ident,
3907 (char *)A(uaddr), PAGE_SIZE) <= 0)
3908 return -EFAULT;
3909 err |= __get_user(karg->ca_umap.ug_uidbase,
3910 &arg32->ca32_umap.ug32_uidbase);
3911 err |= __get_user(karg->ca_umap.ug_uidlen,
3912 &arg32->ca32_umap.ug32_uidlen);
3913 err |= __get_user(uaddr, &arg32->ca32_umap.ug32_udimap);
3914 if (err)
3915 return -EFAULT;
3916 karg->ca_umap.ug_udimap = kmalloc((sizeof(uid_t) * karg->ca_umap.ug_uidlen),
3917 GFP_USER);
3918 if(!karg->ca_umap.ug_udimap)
3919 return -ENOMEM;
3920 for(i = 0; i < karg->ca_umap.ug_uidlen; i++)
3921 err |= __get_user(karg->ca_umap.ug_udimap[i],
3922 &(((__kernel_uid_t32 *)A(uaddr))[i]));
3923 err |= __get_user(karg->ca_umap.ug_gidbase,
3924 &arg32->ca32_umap.ug32_gidbase);
3925 err |= __get_user(karg->ca_umap.ug_uidlen,
3926 &arg32->ca32_umap.ug32_gidlen);
3927 err |= __get_user(uaddr, &arg32->ca32_umap.ug32_gdimap);
3928 if (err)
3929 return -EFAULT;
3930 karg->ca_umap.ug_gdimap = kmalloc((sizeof(gid_t) * karg->ca_umap.ug_uidlen),
3931 GFP_USER);
3932 if(!karg->ca_umap.ug_gdimap)
3933 return -ENOMEM;
3934 for(i = 0; i < karg->ca_umap.ug_gidlen; i++)
3935 err |= __get_user(karg->ca_umap.ug_gdimap[i],
3936 &(((__kernel_gid_t32 *)A(uaddr))[i]));
3937
3938 return (err ? -EFAULT : 0);
3939}
3940
3941static int nfs_getfh32_trans(struct nfsctl_arg *karg, struct nfsctl_arg32 *arg32)
3942{
3943 int err;
3944
3945 err = __get_user(karg->ca_version, &arg32->ca32_version);
3946 err |= copy_from_user(&karg->ca_getfh.gf_addr,
3947 &arg32->ca32_getfh.gf32_addr,
3948 (sizeof(struct sockaddr)));
3949 err |= __get_user(karg->ca_getfh.gf_dev,
3950 &arg32->ca32_getfh.gf32_dev);
3951 err |= __get_user(karg->ca_getfh.gf_ino,
3952 &arg32->ca32_getfh.gf32_ino);
3953 err |= __get_user(karg->ca_getfh.gf_version,
3954 &arg32->ca32_getfh.gf32_version);
3955 return (err ? -EFAULT : 0);
3956}
3957
3958static int nfs_getfd32_trans(struct nfsctl_arg *karg, struct nfsctl_arg32 *arg32)
3959{
3960 int err;
3961
3962 err = __get_user(karg->ca_version, &arg32->ca32_version);
3963 err |= copy_from_user(&karg->ca_getfd.gd_addr,
3964 &arg32->ca32_getfd.gd32_addr,
3965 (sizeof(struct sockaddr)));
3966 err |= copy_from_user(&karg->ca_getfd.gd_path,
3967 &arg32->ca32_getfd.gd32_path,
3968 (NFS_MAXPATHLEN+1));
3969 err |= __get_user(karg->ca_getfd.gd_version,
3970 &arg32->ca32_getfd.gd32_version);
3971 return (err ? -EFAULT : 0);
3972}
3973
3974static int nfs_getfs32_trans(struct nfsctl_arg *karg, struct nfsctl_arg32 *arg32)
3975{
3976 int err;
3977
3978 err = __get_user(karg->ca_version, &arg32->ca32_version);
3979 err |= copy_from_user(&karg->ca_getfs.gd_addr,
3980 &arg32->ca32_getfs.gd32_addr,
3981 (sizeof(struct sockaddr)));
3982 err |= copy_from_user(&karg->ca_getfs.gd_path,
3983 &arg32->ca32_getfs.gd32_path,
3984 (NFS_MAXPATHLEN+1));
3985 err |= __get_user(karg->ca_getfs.gd_maxlen,
3986 &arg32->ca32_getfs.gd32_maxlen);
3987 return (err ? -EFAULT : 0);
3988}
3989
3990
3991
3992
3993static int nfs_getfh32_res_trans(union nfsctl_res *kres, union nfsctl_res32 *res32)
3994{
3995 return (copy_to_user(res32, kres, sizeof(*res32)) ? -EFAULT : 0);
3996}
3997
3998int asmlinkage sys32_nfsservctl(int cmd, struct nfsctl_arg32 *arg32, union nfsctl_res32 *res32)
3999{
4000 struct nfsctl_arg *karg = NULL;
4001 union nfsctl_res *kres = NULL;
4002 mm_segment_t oldfs;
4003 int err;
4004
4005 karg = kmalloc(sizeof(*karg), GFP_USER);
4006 if(!karg)
4007 return -ENOMEM;
4008 if(res32) {
4009 kres = kmalloc(sizeof(*kres), GFP_USER);
4010 if(!kres) {
4011 kfree(karg);
4012 return -ENOMEM;
4013 }
4014 }
4015 switch(cmd) {
4016 case NFSCTL_SVC:
4017 err = nfs_svc32_trans(karg, arg32);
4018 break;
4019 case NFSCTL_ADDCLIENT:
4020 err = nfs_clnt32_trans(karg, arg32);
4021 break;
4022 case NFSCTL_DELCLIENT:
4023 err = nfs_clnt32_trans(karg, arg32);
4024 break;
4025 case NFSCTL_EXPORT:
4026 case NFSCTL_UNEXPORT:
4027 err = nfs_exp32_trans(karg, arg32);
4028 break;
4029
4030 case NFSCTL_UGIDUPDATE:
4031 err = nfs_uud32_trans(karg, arg32);
4032 break;
4033 case NFSCTL_GETFH:
4034 err = nfs_getfh32_trans(karg, arg32);
4035 break;
4036 case NFSCTL_GETFD:
4037 err = nfs_getfd32_trans(karg, arg32);
4038 break;
4039 case NFSCTL_GETFS:
4040 err = nfs_getfs32_trans(karg, arg32);
4041 break;
4042 default:
4043 err = -EINVAL;
4044 break;
4045 }
4046 if(err)
4047 goto done;
4048 oldfs = get_fs();
4049 set_fs(KERNEL_DS);
4050 err = sys_nfsservctl(cmd, karg, kres);
4051 set_fs(oldfs);
4052
4053 if (err)
4054 goto done;
4055
4056 if((cmd == NFSCTL_GETFH) ||
4057 (cmd == NFSCTL_GETFD) ||
4058 (cmd == NFSCTL_GETFS))
4059 err = nfs_getfh32_res_trans(kres, res32);
4060
4061done:
4062 if(karg) {
4063 if(cmd == NFSCTL_UGIDUPDATE) {
4064 if(karg->ca_umap.ug_ident)
4065 kfree(karg->ca_umap.ug_ident);
4066 if(karg->ca_umap.ug_udimap)
4067 kfree(karg->ca_umap.ug_udimap);
4068 if(karg->ca_umap.ug_gdimap)
4069 kfree(karg->ca_umap.ug_gdimap);
4070 }
4071 kfree(karg);
4072 }
4073 if(kres)
4074 kfree(kres);
4075 return err;
4076}
4077#else
4078extern asmlinkage long sys_ni_syscall(void);
4079int asmlinkage sys32_nfsservctl(int cmd, void *notused, void *notused2)
4080{
4081 return sys_ni_syscall();
4082}
4083#endif
4084
4085
4086
4087
4088extern struct timezone sys_tz;
4089extern int do_sys_settimeofday(struct timeval *tv, struct timezone *tz);
4090
4091asmlinkage int sys32_gettimeofday(struct timeval32 *tv, struct timezone *tz)
4092{
4093 if (tv) {
4094 struct timeval ktv;
4095 do_gettimeofday(&ktv);
4096 if (put_tv32(tv, &ktv))
4097 return -EFAULT;
4098 }
4099 if (tz) {
4100 if (copy_to_user(tz, &sys_tz, sizeof(sys_tz)))
4101 return -EFAULT;
4102 }
4103 return 0;
4104}
4105
4106asmlinkage int sys32_settimeofday(struct timeval32 *tv, struct timezone *tz)
4107{
4108 struct timeval ktv;
4109 struct timezone ktz;
4110
4111 if (tv) {
4112 if (get_tv32(&ktv, tv))
4113 return -EFAULT;
4114 }
4115 if (tz) {
4116 if (copy_from_user(&ktz, tz, sizeof(ktz)))
4117 return -EFAULT;
4118 }
4119
4120 return do_sys_settimeofday(tv ? &ktv : NULL, tz ? &ktz : NULL);
4121}
4122
4123extern int do_getitimer(int which, struct itimerval *value);
4124
4125asmlinkage int sys32_getitimer(int which, struct itimerval32 *it)
4126{
4127 struct itimerval kit;
4128 int error;
4129
4130 error = do_getitimer(which, &kit);
4131 if (!error && put_it32(it, &kit))
4132 error = -EFAULT;
4133
4134 return error;
4135}
4136
4137extern int do_setitimer(int which, struct itimerval *, struct itimerval *);
4138
4139asmlinkage int sys32_setitimer(int which, struct itimerval32 *in, struct itimerval32 *out)
4140{
4141 struct itimerval kin, kout;
4142 int error;
4143
4144 if (in) {
4145 if (get_it32(&kin, in))
4146 return -EFAULT;
4147 } else
4148 memset(&kin, 0, sizeof(kin));
4149
4150 error = do_setitimer(which, &kin, out ? &kout : NULL);
4151 if (error || !out)
4152 return error;
4153 if (put_it32(out, &kout))
4154 return -EFAULT;
4155
4156 return 0;
4157
4158}
4159
4160asmlinkage int sys_utimes(char *, struct timeval *);
4161
4162asmlinkage int sys32_utimes(char *filename, struct timeval32 *tvs)
4163{
4164 char *kfilename;
4165 struct timeval ktvs[2];
4166 mm_segment_t old_fs;
4167 int ret;
4168
4169 kfilename = getname(filename);
4170 ret = PTR_ERR(kfilename);
4171 if (!IS_ERR(kfilename)) {
4172 if (tvs) {
4173 if (get_tv32(&ktvs[0], tvs) ||
4174 get_tv32(&ktvs[1], 1+tvs))
4175 return -EFAULT;
4176 }
4177
4178 old_fs = get_fs();
4179 set_fs(KERNEL_DS);
4180 ret = sys_utimes(kfilename, &ktvs[0]);
4181 set_fs(old_fs);
4182
4183 putname(kfilename);
4184 }
4185 return ret;
4186}
4187
4188
4189asmlinkage int sys32_pause(void)
4190{
4191 current->state = TASK_INTERRUPTIBLE;
4192 schedule();
4193 return -ERESTARTNOHAND;
4194}
4195
4196
4197extern asmlinkage int sys_pciconfig_read(unsigned long bus,
4198 unsigned long dfn,
4199 unsigned long off,
4200 unsigned long len,
4201 unsigned char *buf);
4202
4203extern asmlinkage int sys_pciconfig_write(unsigned long bus,
4204 unsigned long dfn,
4205 unsigned long off,
4206 unsigned long len,
4207 unsigned char *buf);
4208
4209asmlinkage int sys32_pciconfig_read(u32 bus, u32 dfn, u32 off, u32 len, u32 ubuf)
4210{
4211 return sys_pciconfig_read((unsigned long) bus,
4212 (unsigned long) dfn,
4213 (unsigned long) off,
4214 (unsigned long) len,
4215 (unsigned char *)AA(ubuf));
4216}
4217
4218asmlinkage int sys32_pciconfig_write(u32 bus, u32 dfn, u32 off, u32 len, u32 ubuf)
4219{
4220 return sys_pciconfig_write((unsigned long) bus,
4221 (unsigned long) dfn,
4222 (unsigned long) off,
4223 (unsigned long) len,
4224 (unsigned char *)AA(ubuf));
4225}
4226
4227extern asmlinkage int sys_prctl(int option, unsigned long arg2, unsigned long arg3,
4228 unsigned long arg4, unsigned long arg5);
4229
4230asmlinkage int sys32_prctl(int option, u32 arg2, u32 arg3, u32 arg4, u32 arg5)
4231{
4232 return sys_prctl(option,
4233 (unsigned long) arg2,
4234 (unsigned long) arg3,
4235 (unsigned long) arg4,
4236 (unsigned long) arg5);
4237}
4238
4239
4240extern asmlinkage ssize_t sys_pread(unsigned int fd, char * buf,
4241 size_t count, loff_t pos);
4242
4243extern asmlinkage ssize_t sys_pwrite(unsigned int fd, const char * buf,
4244 size_t count, loff_t pos);
4245
4246typedef __kernel_ssize_t32 ssize_t32;
4247
4248asmlinkage ssize_t32 sys32_pread(unsigned int fd, char *ubuf,
4249 __kernel_size_t32 count, u32 poshi, u32 poslo)
4250{
4251 return sys_pread(fd, ubuf, count, ((loff_t)AA(poshi) << 32) | AA(poslo));
4252}
4253
4254asmlinkage ssize_t32 sys32_pwrite(unsigned int fd, char *ubuf,
4255 __kernel_size_t32 count, u32 poshi, u32 poslo)
4256{
4257 return sys_pwrite(fd, ubuf, count, ((loff_t)AA(poshi) << 32) | AA(poslo));
4258}
4259
4260extern asmlinkage ssize_t sys_readahead(int fd, loff_t offset, size_t count);
4261
4262asmlinkage ssize_t32 sys32_readahead(int fd, u32 offhi, u32 offlo, s32 count)
4263{
4264 return sys_readahead(fd, ((loff_t)AA(offhi) << 32) | AA(offlo), count);
4265}
4266
4267extern asmlinkage ssize_t sys_sendfile(int out_fd, int in_fd, off_t *offset, size_t count);
4268
4269asmlinkage int sys32_sendfile(int out_fd, int in_fd, __kernel_off_t32 *offset, s32 count)
4270{
4271 mm_segment_t old_fs = get_fs();
4272 int ret;
4273 off_t of;
4274
4275 if (offset && get_user(of, offset))
4276 return -EFAULT;
4277
4278 set_fs(KERNEL_DS);
4279 ret = sys_sendfile(out_fd, in_fd, offset ? &of : NULL, count);
4280 set_fs(old_fs);
4281
4282 if (offset && put_user(of, offset))
4283 return -EFAULT;
4284
4285 return ret;
4286}
4287
4288
4289
4290struct timex32 {
4291 u32 modes;
4292 s32 offset, freq, maxerror, esterror;
4293 s32 status, constant, precision, tolerance;
4294 struct timeval32 time;
4295 s32 tick;
4296 s32 ppsfreq, jitter, shift, stabil;
4297 s32 jitcnt, calcnt, errcnt, stbcnt;
4298 s32 :32; s32 :32; s32 :32; s32 :32;
4299 s32 :32; s32 :32; s32 :32; s32 :32;
4300 s32 :32; s32 :32; s32 :32; s32 :32;
4301};
4302
4303extern int do_adjtimex(struct timex *);
4304
4305asmlinkage int sys32_adjtimex(struct timex32 *utp)
4306{
4307 struct timex txc;
4308 int ret;
4309
4310 memset(&txc, 0, sizeof(struct timex));
4311
4312 if(get_user(txc.modes, &utp->modes) ||
4313 __get_user(txc.offset, &utp->offset) ||
4314 __get_user(txc.freq, &utp->freq) ||
4315 __get_user(txc.maxerror, &utp->maxerror) ||
4316 __get_user(txc.esterror, &utp->esterror) ||
4317 __get_user(txc.status, &utp->status) ||
4318 __get_user(txc.constant, &utp->constant) ||
4319 __get_user(txc.precision, &utp->precision) ||
4320 __get_user(txc.tolerance, &utp->tolerance) ||
4321 __get_user(txc.time.tv_sec, &utp->time.tv_sec) ||
4322 __get_user(txc.time.tv_usec, &utp->time.tv_usec) ||
4323 __get_user(txc.tick, &utp->tick) ||
4324 __get_user(txc.ppsfreq, &utp->ppsfreq) ||
4325 __get_user(txc.jitter, &utp->jitter) ||
4326 __get_user(txc.shift, &utp->shift) ||
4327 __get_user(txc.stabil, &utp->stabil) ||
4328 __get_user(txc.jitcnt, &utp->jitcnt) ||
4329 __get_user(txc.calcnt, &utp->calcnt) ||
4330 __get_user(txc.errcnt, &utp->errcnt) ||
4331 __get_user(txc.stbcnt, &utp->stbcnt))
4332 return -EFAULT;
4333
4334 ret = do_adjtimex(&txc);
4335
4336 if(put_user(txc.modes, &utp->modes) ||
4337 __put_user(txc.offset, &utp->offset) ||
4338 __put_user(txc.freq, &utp->freq) ||
4339 __put_user(txc.maxerror, &utp->maxerror) ||
4340 __put_user(txc.esterror, &utp->esterror) ||
4341 __put_user(txc.status, &utp->status) ||
4342 __put_user(txc.constant, &utp->constant) ||
4343 __put_user(txc.precision, &utp->precision) ||
4344 __put_user(txc.tolerance, &utp->tolerance) ||
4345 __put_user(txc.time.tv_sec, &utp->time.tv_sec) ||
4346 __put_user(txc.time.tv_usec, &utp->time.tv_usec) ||
4347 __put_user(txc.tick, &utp->tick) ||
4348 __put_user(txc.ppsfreq, &utp->ppsfreq) ||
4349 __put_user(txc.jitter, &utp->jitter) ||
4350 __put_user(txc.shift, &utp->shift) ||
4351 __put_user(txc.stabil, &utp->stabil) ||
4352 __put_user(txc.jitcnt, &utp->jitcnt) ||
4353 __put_user(txc.calcnt, &utp->calcnt) ||
4354 __put_user(txc.errcnt, &utp->errcnt) ||
4355 __put_user(txc.stbcnt, &utp->stbcnt))
4356 ret = -EFAULT;
4357
4358 return ret;
4359}
4360
4361
4362
4363
4364
4365asmlinkage long sparc32_open(const char * filename, int flags, int mode)
4366{
4367 char * tmp;
4368 int fd, error;
4369
4370 tmp = getname(filename);
4371 fd = PTR_ERR(tmp);
4372 if (!IS_ERR(tmp)) {
4373 fd = get_unused_fd();
4374 if (fd >= 0) {
4375 struct file * f = filp_open(tmp, flags, mode);
4376 error = PTR_ERR(f);
4377 if (IS_ERR(f))
4378 goto out_error;
4379 fd_install(fd, f);
4380 }
4381out:
4382 putname(tmp);
4383 }
4384 return fd;
4385
4386out_error:
4387 put_unused_fd(fd);
4388 fd = error;
4389 goto out;
4390}
4391
4392extern unsigned long do_mremap(unsigned long addr,
4393 unsigned long old_len, unsigned long new_len,
4394 unsigned long flags, unsigned long new_addr);
4395
4396asmlinkage unsigned long sys32_mremap(unsigned long addr,
4397 unsigned long old_len, unsigned long new_len,
4398 unsigned long flags, u32 __new_addr)
4399{
4400 struct vm_area_struct *vma;
4401 unsigned long ret = -EINVAL;
4402 unsigned long new_addr = AA(__new_addr);
4403
4404 if (old_len > 0xf0000000UL || new_len > 0xf0000000UL)
4405 goto out;
4406 if (addr > 0xf0000000UL - old_len)
4407 goto out;
4408 down_write(¤t->mm->mmap_sem);
4409 if (flags & MREMAP_FIXED) {
4410 if (new_addr > 0xf0000000UL - new_len)
4411 goto out_sem;
4412 } else if (addr > 0xf0000000UL - new_len) {
4413 unsigned long map_flags = 0;
4414 struct file *file = NULL;
4415
4416 ret = -ENOMEM;
4417 if (!(flags & MREMAP_MAYMOVE))
4418 goto out_sem;
4419
4420 vma = find_vma(current->mm, addr);
4421 if (vma) {
4422 if (vma->vm_flags & VM_SHARED)
4423 map_flags |= MAP_SHARED;
4424 file = vma->vm_file;
4425 }
4426
4427
4428 new_addr = get_unmapped_area(file, addr, new_len,
4429 vma ? vma->vm_pgoff : 0,
4430 map_flags);
4431 ret = new_addr;
4432 if (new_addr & ~PAGE_MASK)
4433 goto out_sem;
4434 flags |= MREMAP_FIXED;
4435 }
4436 ret = do_mremap(addr, old_len, new_len, flags, new_addr);
4437out_sem:
4438 up_write(¤t->mm->mmap_sem);
4439out:
4440 return ret;
4441}
4442
4443extern asmlinkage long sys_setpriority(int which, int who, int niceval);
4444
4445asmlinkage int sys_setpriority32(u32 which, u32 who, u32 niceval)
4446{
4447 return sys_setpriority((int) which,
4448 (int) who,
4449 (int) niceval);
4450}
4451
4452struct __sysctl_args32 {
4453 u32 name;
4454 int nlen;
4455 u32 oldval;
4456 u32 oldlenp;
4457 u32 newval;
4458 u32 newlen;
4459 u32 __unused[4];
4460};
4461
4462extern asmlinkage long sys32_sysctl(struct __sysctl_args32 *args)
4463{
4464#ifndef CONFIG_SYSCTL
4465 return -ENOSYS;
4466#else
4467 struct __sysctl_args32 tmp;
4468 int error;
4469 size_t oldlen, *oldlenp = NULL;
4470 unsigned long addr = (((long)&args->__unused[0]) + 7) & ~7;
4471
4472 if (copy_from_user(&tmp, args, sizeof(tmp)))
4473 return -EFAULT;
4474
4475 if (tmp.oldval && tmp.oldlenp) {
4476
4477
4478
4479
4480
4481
4482 if (get_user(oldlen, (u32 *)A(tmp.oldlenp)) ||
4483 put_user(oldlen, (size_t *)addr))
4484 return -EFAULT;
4485 oldlenp = (size_t *)addr;
4486 }
4487
4488 lock_kernel();
4489 error = do_sysctl((int *)A(tmp.name), tmp.nlen, (void *)A(tmp.oldval),
4490 oldlenp, (void *)A(tmp.newval), tmp.newlen);
4491 unlock_kernel();
4492 if (oldlenp) {
4493 if (!error) {
4494 if (get_user(oldlen, (size_t *)addr) ||
4495 put_user(oldlen, (u32 *)A(tmp.oldlenp)))
4496 error = -EFAULT;
4497 }
4498 copy_to_user(args->__unused, tmp.__unused, sizeof(tmp.__unused));
4499 }
4500 return error;
4501#endif
4502}
4503