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 ((char *) 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 (optname == SO_ATTACH_FILTER)
3000 return do_set_attach_filter(fd, level, optname,
3001 optval, optlen);
3002 if (optname == SO_RCVTIMEO || optname == SO_SNDTIMEO)
3003 return do_set_sock_timeout(fd, level, optname, optval, optlen);
3004
3005 return sys_setsockopt(fd, level, optname, optval, optlen);
3006}
3007
3008extern asmlinkage long sys_getsockopt(int fd, int level, int optname,
3009 char *optval, int *optlen);
3010
3011static int do_get_sock_timeout(int fd, int level, int optname, char *optval, int *optlen)
3012{
3013 struct timeval32 *up = (struct timeval32 *) optval;
3014 struct timeval ktime;
3015 mm_segment_t old_fs;
3016 int len, err;
3017
3018 if (get_user(len, optlen))
3019 return -EFAULT;
3020 if (len < sizeof(*up))
3021 return -EINVAL;
3022 len = sizeof(ktime);
3023 old_fs = get_fs();
3024 set_fs(KERNEL_DS);
3025 err = sys_getsockopt(fd, level, optname, (char *) &ktime, &len);
3026 set_fs(old_fs);
3027
3028 if (!err) {
3029 if (put_user(sizeof(*up), optlen) ||
3030 put_user(ktime.tv_sec, &up->tv_sec) ||
3031 __put_user(ktime.tv_usec, &up->tv_usec))
3032 err = -EFAULT;
3033 }
3034 return err;
3035}
3036
3037asmlinkage int sys32_getsockopt(int fd, int level, int optname,
3038 char *optval, int *optlen)
3039{
3040 if (optname == SO_RCVTIMEO || optname == SO_SNDTIMEO)
3041 return do_get_sock_timeout(fd, level, optname, optval, optlen);
3042 return sys_getsockopt(fd, level, optname, optval, optlen);
3043}
3044
3045extern void check_pending(int signum);
3046
3047asmlinkage int sys32_sigaction (int sig, struct old_sigaction32 *act, struct old_sigaction32 *oact)
3048{
3049 struct k_sigaction new_ka, old_ka;
3050 int ret;
3051
3052 if(sig < 0) {
3053 current->thread.flags |= SPARC_FLAG_NEWSIGNALS;
3054 sig = -sig;
3055 }
3056
3057 if (act) {
3058 old_sigset_t32 mask;
3059
3060 ret = get_user((long)new_ka.sa.sa_handler, &act->sa_handler);
3061 ret |= __get_user((long)new_ka.sa.sa_restorer, &act->sa_restorer);
3062 ret |= __get_user(new_ka.sa.sa_flags, &act->sa_flags);
3063 ret |= __get_user(mask, &act->sa_mask);
3064 if (ret)
3065 return ret;
3066 new_ka.ka_restorer = NULL;
3067 siginitset(&new_ka.sa.sa_mask, mask);
3068 }
3069
3070 ret = do_sigaction(sig, act ? &new_ka : NULL, oact ? &old_ka : NULL);
3071
3072 if (!ret && oact) {
3073 ret = put_user((long)old_ka.sa.sa_handler, &oact->sa_handler);
3074 ret |= __put_user((long)old_ka.sa.sa_restorer, &oact->sa_restorer);
3075 ret |= __put_user(old_ka.sa.sa_flags, &oact->sa_flags);
3076 ret |= __put_user(old_ka.sa.sa_mask.sig[0], &oact->sa_mask);
3077 }
3078
3079 return ret;
3080}
3081
3082asmlinkage int
3083sys32_rt_sigaction(int sig, struct sigaction32 *act, struct sigaction32 *oact,
3084 void *restorer, __kernel_size_t32 sigsetsize)
3085{
3086 struct k_sigaction new_ka, old_ka;
3087 int ret;
3088 sigset_t32 set32;
3089
3090
3091 if (sigsetsize != sizeof(sigset_t32))
3092 return -EINVAL;
3093
3094
3095
3096
3097 current->thread.flags |= SPARC_FLAG_NEWSIGNALS;
3098
3099 if (act) {
3100 new_ka.ka_restorer = restorer;
3101 ret = get_user((long)new_ka.sa.sa_handler, &act->sa_handler);
3102 ret |= __copy_from_user(&set32, &act->sa_mask, sizeof(sigset_t32));
3103 switch (_NSIG_WORDS) {
3104 case 4: new_ka.sa.sa_mask.sig[3] = set32.sig[6] | (((long)set32.sig[7]) << 32);
3105 case 3: new_ka.sa.sa_mask.sig[2] = set32.sig[4] | (((long)set32.sig[5]) << 32);
3106 case 2: new_ka.sa.sa_mask.sig[1] = set32.sig[2] | (((long)set32.sig[3]) << 32);
3107 case 1: new_ka.sa.sa_mask.sig[0] = set32.sig[0] | (((long)set32.sig[1]) << 32);
3108 }
3109 ret |= __get_user(new_ka.sa.sa_flags, &act->sa_flags);
3110 ret |= __get_user((long)new_ka.sa.sa_restorer, &act->sa_restorer);
3111 if (ret)
3112 return -EFAULT;
3113 }
3114
3115 ret = do_sigaction(sig, act ? &new_ka : NULL, oact ? &old_ka : NULL);
3116
3117 if (!ret && oact) {
3118 switch (_NSIG_WORDS) {
3119 case 4: set32.sig[7] = (old_ka.sa.sa_mask.sig[3] >> 32); set32.sig[6] = old_ka.sa.sa_mask.sig[3];
3120 case 3: set32.sig[5] = (old_ka.sa.sa_mask.sig[2] >> 32); set32.sig[4] = old_ka.sa.sa_mask.sig[2];
3121 case 2: set32.sig[3] = (old_ka.sa.sa_mask.sig[1] >> 32); set32.sig[2] = old_ka.sa.sa_mask.sig[1];
3122 case 1: set32.sig[1] = (old_ka.sa.sa_mask.sig[0] >> 32); set32.sig[0] = old_ka.sa.sa_mask.sig[0];
3123 }
3124 ret = put_user((long)old_ka.sa.sa_handler, &oact->sa_handler);
3125 ret |= __copy_to_user(&oact->sa_mask, &set32, sizeof(sigset_t32));
3126 ret |= __put_user(old_ka.sa.sa_flags, &oact->sa_flags);
3127 ret |= __put_user((long)old_ka.sa.sa_restorer, &oact->sa_restorer);
3128 if (ret)
3129 ret = -EFAULT;
3130 }
3131
3132 return ret;
3133}
3134
3135
3136
3137
3138
3139static int count32(u32 * argv, int max)
3140{
3141 int i = 0;
3142
3143 if (argv != NULL) {
3144 for (;;) {
3145 u32 p; int error;
3146
3147 error = get_user(p,argv);
3148 if (error)
3149 return error;
3150 if (!p)
3151 break;
3152 argv++;
3153 if (++i > max)
3154 return -E2BIG;
3155 }
3156 }
3157 return i;
3158}
3159
3160
3161
3162
3163
3164
3165static int copy_strings32(int argc, u32 * argv, struct linux_binprm *bprm)
3166{
3167 while (argc-- > 0) {
3168 u32 str;
3169 int len;
3170 unsigned long pos;
3171
3172 if (get_user(str, argv + argc) ||
3173 !str ||
3174 !(len = strnlen_user((char *)A(str), bprm->p)))
3175 return -EFAULT;
3176
3177 if (bprm->p < len)
3178 return -E2BIG;
3179
3180 bprm->p -= len;
3181
3182 pos = bprm->p;
3183 while (len) {
3184 char *kaddr;
3185 struct page *page;
3186 int offset, bytes_to_copy, new, err;
3187
3188 offset = pos % PAGE_SIZE;
3189 page = bprm->page[pos / PAGE_SIZE];
3190 new = 0;
3191 if (!page) {
3192 page = alloc_page(GFP_USER);
3193 bprm->page[pos / PAGE_SIZE] = page;
3194 if (!page)
3195 return -ENOMEM;
3196 new = 1;
3197 }
3198 kaddr = kmap(page);
3199
3200 if (new && offset)
3201 memset(kaddr, 0, offset);
3202 bytes_to_copy = PAGE_SIZE - offset;
3203 if (bytes_to_copy > len) {
3204 bytes_to_copy = len;
3205 if (new)
3206 memset(kaddr+offset+len, 0,
3207 PAGE_SIZE-offset-len);
3208 }
3209
3210 err = copy_from_user(kaddr + offset, (char *)A(str),
3211 bytes_to_copy);
3212 kunmap(page);
3213
3214 if (err)
3215 return -EFAULT;
3216
3217 pos += bytes_to_copy;
3218 str += bytes_to_copy;
3219 len -= bytes_to_copy;
3220 }
3221 }
3222 return 0;
3223}
3224
3225
3226
3227
3228static inline int
3229do_execve32(char * filename, u32 * argv, u32 * envp, struct pt_regs * regs)
3230{
3231 struct linux_binprm bprm;
3232 struct file * file;
3233 int retval;
3234 int i;
3235
3236 bprm.p = PAGE_SIZE*MAX_ARG_PAGES-sizeof(void *);
3237 memset(bprm.page, 0, MAX_ARG_PAGES * sizeof(bprm.page[0]));
3238
3239 file = open_exec(filename);
3240
3241 retval = PTR_ERR(file);
3242 if (IS_ERR(file))
3243 return retval;
3244
3245 bprm.file = file;
3246 bprm.filename = filename;
3247 bprm.sh_bang = 0;
3248 bprm.loader = 0;
3249 bprm.exec = 0;
3250 if ((bprm.argc = count32(argv, bprm.p / sizeof(u32))) < 0) {
3251 allow_write_access(file);
3252 fput(file);
3253 return bprm.argc;
3254 }
3255 if ((bprm.envc = count32(envp, bprm.p / sizeof(u32))) < 0) {
3256 allow_write_access(file);
3257 fput(file);
3258 return bprm.envc;
3259 }
3260
3261 retval = prepare_binprm(&bprm);
3262 if (retval < 0)
3263 goto out;
3264
3265 retval = copy_strings_kernel(1, &bprm.filename, &bprm);
3266 if (retval < 0)
3267 goto out;
3268
3269 bprm.exec = bprm.p;
3270 retval = copy_strings32(bprm.envc, envp, &bprm);
3271 if (retval < 0)
3272 goto out;
3273
3274 retval = copy_strings32(bprm.argc, argv, &bprm);
3275 if (retval < 0)
3276 goto out;
3277
3278 retval = search_binary_handler(&bprm, regs);
3279 if (retval >= 0)
3280
3281 return retval;
3282
3283out:
3284
3285 allow_write_access(bprm.file);
3286 if (bprm.file)
3287 fput(bprm.file);
3288
3289 for (i=0 ; i<MAX_ARG_PAGES ; i++)
3290 if (bprm.page[i])
3291 __free_page(bprm.page[i]);
3292
3293 return retval;
3294}
3295
3296
3297
3298
3299
3300asmlinkage int sparc32_execve(struct pt_regs *regs)
3301{
3302 int error, base = 0;
3303 char *filename;
3304
3305
3306
3307
3308 if((u32)regs->u_regs[UREG_G1] == 0)
3309 base = 1;
3310
3311 filename = getname((char *)AA(regs->u_regs[base + UREG_I0]));
3312 error = PTR_ERR(filename);
3313 if(IS_ERR(filename))
3314 goto out;
3315 error = do_execve32(filename,
3316 (u32 *)AA((u32)regs->u_regs[base + UREG_I1]),
3317 (u32 *)AA((u32)regs->u_regs[base + UREG_I2]), regs);
3318 putname(filename);
3319
3320 if(!error) {
3321 fprs_write(0);
3322 current->thread.xfsr[0] = 0;
3323 current->thread.fpsaved[0] = 0;
3324 regs->tstate &= ~TSTATE_PEF;
3325 }
3326out:
3327 return error;
3328}
3329
3330#ifdef CONFIG_MODULES
3331
3332extern asmlinkage unsigned long sys_create_module(const char *name_user, size_t size);
3333
3334asmlinkage unsigned long sys32_create_module(const char *name_user, __kernel_size_t32 size)
3335{
3336 return sys_create_module(name_user, (size_t)size);
3337}
3338
3339extern asmlinkage int sys_init_module(const char *name_user, struct module *mod_user);
3340
3341
3342
3343
3344asmlinkage int sys32_init_module(const char *name_user, struct module *mod_user)
3345{
3346 return sys_init_module(name_user, mod_user);
3347}
3348
3349extern asmlinkage int sys_delete_module(const char *name_user);
3350
3351asmlinkage int sys32_delete_module(const char *name_user)
3352{
3353 return sys_delete_module(name_user);
3354}
3355
3356struct module_info32 {
3357 u32 addr;
3358 u32 size;
3359 u32 flags;
3360 s32 usecount;
3361};
3362
3363
3364
3365static inline long
3366get_mod_name(const char *user_name, char **buf)
3367{
3368 unsigned long page;
3369 long retval;
3370
3371 if ((unsigned long)user_name >= TASK_SIZE
3372 && !segment_eq(get_fs (), KERNEL_DS))
3373 return -EFAULT;
3374
3375 page = __get_free_page(GFP_KERNEL);
3376 if (!page)
3377 return -ENOMEM;
3378
3379 retval = strncpy_from_user((char *)page, user_name, PAGE_SIZE);
3380 if (retval > 0) {
3381 if (retval < PAGE_SIZE) {
3382 *buf = (char *)page;
3383 return retval;
3384 }
3385 retval = -ENAMETOOLONG;
3386 } else if (!retval)
3387 retval = -EINVAL;
3388
3389 free_page(page);
3390 return retval;
3391}
3392
3393static inline void
3394put_mod_name(char *buf)
3395{
3396 free_page((unsigned long)buf);
3397}
3398
3399static __inline__ struct module *find_module(const char *name)
3400{
3401 struct module *mod;
3402
3403 for (mod = module_list; mod ; mod = mod->next) {
3404 if (mod->flags & MOD_DELETED)
3405 continue;
3406 if (!strcmp(mod->name, name))
3407 break;
3408 }
3409
3410 return mod;
3411}
3412
3413static int
3414qm_modules(char *buf, size_t bufsize, __kernel_size_t32 *ret)
3415{
3416 struct module *mod;
3417 size_t nmod, space, len;
3418
3419 nmod = space = 0;
3420
3421 for (mod = module_list; mod->next != NULL; mod = mod->next, ++nmod) {
3422 len = strlen(mod->name)+1;
3423 if (len > bufsize)
3424 goto calc_space_needed;
3425 if (copy_to_user(buf, mod->name, len))
3426 return -EFAULT;
3427 buf += len;
3428 bufsize -= len;
3429 space += len;
3430 }
3431
3432 if (put_user(nmod, ret))
3433 return -EFAULT;
3434 else
3435 return 0;
3436
3437calc_space_needed:
3438 space += len;
3439 while ((mod = mod->next)->next != NULL)
3440 space += strlen(mod->name)+1;
3441
3442 if (put_user(space, ret))
3443 return -EFAULT;
3444 else
3445 return -ENOSPC;
3446}
3447
3448static int
3449qm_deps(struct module *mod, char *buf, size_t bufsize, __kernel_size_t32 *ret)
3450{
3451 size_t i, space, len;
3452
3453 if (mod->next == NULL)
3454 return -EINVAL;
3455 if (!MOD_CAN_QUERY(mod))
3456 return put_user(0, ret);
3457
3458 space = 0;
3459 for (i = 0; i < mod->ndeps; ++i) {
3460 const char *dep_name = mod->deps[i].dep->name;
3461
3462 len = strlen(dep_name)+1;
3463 if (len > bufsize)
3464 goto calc_space_needed;
3465 if (copy_to_user(buf, dep_name, len))
3466 return -EFAULT;
3467 buf += len;
3468 bufsize -= len;
3469 space += len;
3470 }
3471
3472 return put_user(i, ret);
3473
3474calc_space_needed:
3475 space += len;
3476 while (++i < mod->ndeps)
3477 space += strlen(mod->deps[i].dep->name)+1;
3478
3479 if (put_user(space, ret))
3480 return -EFAULT;
3481 else
3482 return -ENOSPC;
3483}
3484
3485static int
3486qm_refs(struct module *mod, char *buf, size_t bufsize, __kernel_size_t32 *ret)
3487{
3488 size_t nrefs, space, len;
3489 struct module_ref *ref;
3490
3491 if (mod->next == NULL)
3492 return -EINVAL;
3493 if (!MOD_CAN_QUERY(mod))
3494 if (put_user(0, ret))
3495 return -EFAULT;
3496 else
3497 return 0;
3498
3499 space = 0;
3500 for (nrefs = 0, ref = mod->refs; ref ; ++nrefs, ref = ref->next_ref) {
3501 const char *ref_name = ref->ref->name;
3502
3503 len = strlen(ref_name)+1;
3504 if (len > bufsize)
3505 goto calc_space_needed;
3506 if (copy_to_user(buf, ref_name, len))
3507 return -EFAULT;
3508 buf += len;
3509 bufsize -= len;
3510 space += len;
3511 }
3512
3513 if (put_user(nrefs, ret))
3514 return -EFAULT;
3515 else
3516 return 0;
3517
3518calc_space_needed:
3519 space += len;
3520 while ((ref = ref->next_ref) != NULL)
3521 space += strlen(ref->ref->name)+1;
3522
3523 if (put_user(space, ret))
3524 return -EFAULT;
3525 else
3526 return -ENOSPC;
3527}
3528
3529static inline int
3530qm_symbols(struct module *mod, char *buf, size_t bufsize, __kernel_size_t32 *ret)
3531{
3532 size_t i, space, len;
3533 struct module_symbol *s;
3534 char *strings;
3535 unsigned *vals;
3536
3537 if (!MOD_CAN_QUERY(mod))
3538 if (put_user(0, ret))
3539 return -EFAULT;
3540 else
3541 return 0;
3542
3543 space = mod->nsyms * 2*sizeof(u32);
3544
3545 i = len = 0;
3546 s = mod->syms;
3547
3548 if (space > bufsize)
3549 goto calc_space_needed;
3550
3551 if (!access_ok(VERIFY_WRITE, buf, space))
3552 return -EFAULT;
3553
3554 bufsize -= space;
3555 vals = (unsigned *)buf;
3556 strings = buf+space;
3557
3558 for (; i < mod->nsyms ; ++i, ++s, vals += 2) {
3559 len = strlen(s->name)+1;
3560 if (len > bufsize)
3561 goto calc_space_needed;
3562
3563 if (copy_to_user(strings, s->name, len)
3564 || __put_user(s->value, vals+0)
3565 || __put_user(space, vals+1))
3566 return -EFAULT;
3567
3568 strings += len;
3569 bufsize -= len;
3570 space += len;
3571 }
3572
3573 if (put_user(i, ret))
3574 return -EFAULT;
3575 else
3576 return 0;
3577
3578calc_space_needed:
3579 for (; i < mod->nsyms; ++i, ++s)
3580 space += strlen(s->name)+1;
3581
3582 if (put_user(space, ret))
3583 return -EFAULT;
3584 else
3585 return -ENOSPC;
3586}
3587
3588static inline int
3589qm_info(struct module *mod, char *buf, size_t bufsize, __kernel_size_t32 *ret)
3590{
3591 int error = 0;
3592
3593 if (mod->next == NULL)
3594 return -EINVAL;
3595
3596 if (sizeof(struct module_info32) <= bufsize) {
3597 struct module_info32 info;
3598 info.addr = (unsigned long)mod;
3599 info.size = mod->size;
3600 info.flags = mod->flags;
3601 info.usecount =
3602 ((mod_member_present(mod, can_unload)
3603 && mod->can_unload)
3604 ? -1 : atomic_read(&mod->uc.usecount));
3605
3606 if (copy_to_user(buf, &info, sizeof(struct module_info32)))
3607 return -EFAULT;
3608 } else
3609 error = -ENOSPC;
3610
3611 if (put_user(sizeof(struct module_info32), ret))
3612 return -EFAULT;
3613
3614 return error;
3615}
3616
3617asmlinkage int sys32_query_module(char *name_user, int which, char *buf, __kernel_size_t32 bufsize, u32 ret)
3618{
3619 struct module *mod;
3620 int err;
3621
3622 lock_kernel();
3623 if (name_user == 0) {
3624
3625 for(mod = module_list; mod->next != NULL; mod = mod->next)
3626 ;
3627 } else {
3628 long namelen;
3629 char *name;
3630
3631 if ((namelen = get_mod_name(name_user, &name)) < 0) {
3632 err = namelen;
3633 goto out;
3634 }
3635 err = -ENOENT;
3636 if (namelen == 0) {
3637
3638 for(mod = module_list; mod->next != NULL; mod = mod->next)
3639 ;
3640 } else if ((mod = find_module(name)) == NULL) {
3641 put_mod_name(name);
3642 goto out;
3643 }
3644 put_mod_name(name);
3645 }
3646
3647 switch (which)
3648 {
3649 case 0:
3650 err = 0;
3651 break;
3652 case QM_MODULES:
3653 err = qm_modules(buf, bufsize, (__kernel_size_t32 *)AA(ret));
3654 break;
3655 case QM_DEPS:
3656 err = qm_deps(mod, buf, bufsize, (__kernel_size_t32 *)AA(ret));
3657 break;
3658 case QM_REFS:
3659 err = qm_refs(mod, buf, bufsize, (__kernel_size_t32 *)AA(ret));
3660 break;
3661 case QM_SYMBOLS:
3662 err = qm_symbols(mod, buf, bufsize, (__kernel_size_t32 *)AA(ret));
3663 break;
3664 case QM_INFO:
3665 err = qm_info(mod, buf, bufsize, (__kernel_size_t32 *)AA(ret));
3666 break;
3667 default:
3668 err = -EINVAL;
3669 break;
3670 }
3671out:
3672 unlock_kernel();
3673 return err;
3674}
3675
3676struct kernel_sym32 {
3677 u32 value;
3678 char name[60];
3679};
3680
3681extern asmlinkage int sys_get_kernel_syms(struct kernel_sym *table);
3682
3683asmlinkage int sys32_get_kernel_syms(struct kernel_sym32 *table)
3684{
3685 int len, i;
3686 struct kernel_sym *tbl;
3687 mm_segment_t old_fs;
3688
3689 len = sys_get_kernel_syms(NULL);
3690 if (!table) return len;
3691 tbl = kmalloc (len * sizeof (struct kernel_sym), GFP_KERNEL);
3692 if (!tbl) return -ENOMEM;
3693 old_fs = get_fs();
3694 set_fs (KERNEL_DS);
3695 sys_get_kernel_syms(tbl);
3696 set_fs (old_fs);
3697 for (i = 0; i < len; i++, table++) {
3698 if (put_user (tbl[i].value, &table->value) ||
3699 copy_to_user (table->name, tbl[i].name, 60))
3700 break;
3701 }
3702 kfree (tbl);
3703 return i;
3704}
3705
3706#else
3707
3708asmlinkage unsigned long
3709sys32_create_module(const char *name_user, size_t size)
3710{
3711 return -ENOSYS;
3712}
3713
3714asmlinkage int
3715sys32_init_module(const char *name_user, struct module *mod_user)
3716{
3717 return -ENOSYS;
3718}
3719
3720asmlinkage int
3721sys32_delete_module(const char *name_user)
3722{
3723 return -ENOSYS;
3724}
3725
3726asmlinkage int
3727sys32_query_module(const char *name_user, int which, char *buf, size_t bufsize,
3728 size_t *ret)
3729{
3730
3731
3732 if (which == 0)
3733 return 0;
3734
3735 return -ENOSYS;
3736}
3737
3738asmlinkage int
3739sys32_get_kernel_syms(struct kernel_sym *table)
3740{
3741 return -ENOSYS;
3742}
3743
3744#endif
3745
3746#if defined(CONFIG_NFSD) || defined(CONFIG_NFSD_MODULE)
3747
3748struct nfsctl_svc32 {
3749 u16 svc32_port;
3750 s32 svc32_nthreads;
3751};
3752
3753struct nfsctl_client32 {
3754 s8 cl32_ident[NFSCLNT_IDMAX+1];
3755 s32 cl32_naddr;
3756 struct in_addr cl32_addrlist[NFSCLNT_ADDRMAX];
3757 s32 cl32_fhkeytype;
3758 s32 cl32_fhkeylen;
3759 u8 cl32_fhkey[NFSCLNT_KEYMAX];
3760};
3761
3762struct nfsctl_export32 {
3763 s8 ex32_client[NFSCLNT_IDMAX+1];
3764 s8 ex32_path[NFS_MAXPATHLEN+1];
3765 __kernel_dev_t32 ex32_dev;
3766 __kernel_ino_t32 ex32_ino;
3767 s32 ex32_flags;
3768 __kernel_uid_t32 ex32_anon_uid;
3769 __kernel_gid_t32 ex32_anon_gid;
3770};
3771
3772struct nfsctl_uidmap32 {
3773 u32 ug32_ident;
3774 __kernel_uid_t32 ug32_uidbase;
3775 s32 ug32_uidlen;
3776 u32 ug32_udimap;
3777 __kernel_uid_t32 ug32_gidbase;
3778 s32 ug32_gidlen;
3779 u32 ug32_gdimap;
3780};
3781
3782struct nfsctl_fhparm32 {
3783 struct sockaddr gf32_addr;
3784 __kernel_dev_t32 gf32_dev;
3785 __kernel_ino_t32 gf32_ino;
3786 s32 gf32_version;
3787};
3788
3789struct nfsctl_fdparm32 {
3790 struct sockaddr gd32_addr;
3791 s8 gd32_path[NFS_MAXPATHLEN+1];
3792 s32 gd32_version;
3793};
3794
3795struct nfsctl_fsparm32 {
3796 struct sockaddr gd32_addr;
3797 s8 gd32_path[NFS_MAXPATHLEN+1];
3798 s32 gd32_maxlen;
3799};
3800
3801struct nfsctl_arg32 {
3802 s32 ca32_version;
3803 union {
3804 struct nfsctl_svc32 u32_svc;
3805 struct nfsctl_client32 u32_client;
3806 struct nfsctl_export32 u32_export;
3807 struct nfsctl_uidmap32 u32_umap;
3808 struct nfsctl_fhparm32 u32_getfh;
3809 struct nfsctl_fdparm32 u32_getfd;
3810 struct nfsctl_fsparm32 u32_getfs;
3811 } u;
3812#define ca32_svc u.u32_svc
3813#define ca32_client u.u32_client
3814#define ca32_export u.u32_export
3815#define ca32_umap u.u32_umap
3816#define ca32_getfh u.u32_getfh
3817#define ca32_getfd u.u32_getfd
3818#define ca32_getfs u.u32_getfs
3819#define ca32_authd u.u32_authd
3820};
3821
3822union nfsctl_res32 {
3823 __u8 cr32_getfh[NFS_FHSIZE];
3824 struct knfsd_fh cr32_getfs;
3825};
3826
3827static int nfs_svc32_trans(struct nfsctl_arg *karg, struct nfsctl_arg32 *arg32)
3828{
3829 int err;
3830
3831 err = __get_user(karg->ca_version, &arg32->ca32_version);
3832 err |= __get_user(karg->ca_svc.svc_port, &arg32->ca32_svc.svc32_port);
3833 err |= __get_user(karg->ca_svc.svc_nthreads, &arg32->ca32_svc.svc32_nthreads);
3834 return err;
3835}
3836
3837static int nfs_clnt32_trans(struct nfsctl_arg *karg, struct nfsctl_arg32 *arg32)
3838{
3839 int err;
3840
3841 err = __get_user(karg->ca_version, &arg32->ca32_version);
3842 err |= copy_from_user(&karg->ca_client.cl_ident[0],
3843 &arg32->ca32_client.cl32_ident[0],
3844 NFSCLNT_IDMAX);
3845 err |= __get_user(karg->ca_client.cl_naddr, &arg32->ca32_client.cl32_naddr);
3846 err |= copy_from_user(&karg->ca_client.cl_addrlist[0],
3847 &arg32->ca32_client.cl32_addrlist[0],
3848 (sizeof(struct in_addr) * NFSCLNT_ADDRMAX));
3849 err |= __get_user(karg->ca_client.cl_fhkeytype,
3850 &arg32->ca32_client.cl32_fhkeytype);
3851 err |= __get_user(karg->ca_client.cl_fhkeylen,
3852 &arg32->ca32_client.cl32_fhkeylen);
3853 err |= copy_from_user(&karg->ca_client.cl_fhkey[0],
3854 &arg32->ca32_client.cl32_fhkey[0],
3855 NFSCLNT_KEYMAX);
3856 return (err ? -EFAULT : 0);
3857}
3858
3859static int nfs_exp32_trans(struct nfsctl_arg *karg, struct nfsctl_arg32 *arg32)
3860{
3861 int err;
3862
3863 err = __get_user(karg->ca_version, &arg32->ca32_version);
3864 err |= copy_from_user(&karg->ca_export.ex_client[0],
3865 &arg32->ca32_export.ex32_client[0],
3866 NFSCLNT_IDMAX);
3867 err |= copy_from_user(&karg->ca_export.ex_path[0],
3868 &arg32->ca32_export.ex32_path[0],
3869 NFS_MAXPATHLEN);
3870 err |= __get_user(karg->ca_export.ex_dev,
3871 &arg32->ca32_export.ex32_dev);
3872 err |= __get_user(karg->ca_export.ex_ino,
3873 &arg32->ca32_export.ex32_ino);
3874 err |= __get_user(karg->ca_export.ex_flags,
3875 &arg32->ca32_export.ex32_flags);
3876 err |= __get_user(karg->ca_export.ex_anon_uid,
3877 &arg32->ca32_export.ex32_anon_uid);
3878 err |= __get_user(karg->ca_export.ex_anon_gid,
3879 &arg32->ca32_export.ex32_anon_gid);
3880 karg->ca_export.ex_anon_uid = high2lowuid(karg->ca_export.ex_anon_uid);
3881 karg->ca_export.ex_anon_gid = high2lowgid(karg->ca_export.ex_anon_gid);
3882 return (err ? -EFAULT : 0);
3883}
3884
3885static int nfs_uud32_trans(struct nfsctl_arg *karg, struct nfsctl_arg32 *arg32)
3886{
3887 u32 uaddr;
3888 int i;
3889 int err;
3890
3891 memset(karg, 0, sizeof(*karg));
3892 if(__get_user(karg->ca_version, &arg32->ca32_version))
3893 return -EFAULT;
3894 karg->ca_umap.ug_ident = (char *)get_free_page(GFP_USER);
3895 if(!karg->ca_umap.ug_ident)
3896 return -ENOMEM;
3897 err = __get_user(uaddr, &arg32->ca32_umap.ug32_ident);
3898 if(strncpy_from_user(karg->ca_umap.ug_ident,
3899 (char *)A(uaddr), PAGE_SIZE) <= 0)
3900 return -EFAULT;
3901 err |= __get_user(karg->ca_umap.ug_uidbase,
3902 &arg32->ca32_umap.ug32_uidbase);
3903 err |= __get_user(karg->ca_umap.ug_uidlen,
3904 &arg32->ca32_umap.ug32_uidlen);
3905 err |= __get_user(uaddr, &arg32->ca32_umap.ug32_udimap);
3906 if (err)
3907 return -EFAULT;
3908 karg->ca_umap.ug_udimap = kmalloc((sizeof(uid_t) * karg->ca_umap.ug_uidlen),
3909 GFP_USER);
3910 if(!karg->ca_umap.ug_udimap)
3911 return -ENOMEM;
3912 for(i = 0; i < karg->ca_umap.ug_uidlen; i++)
3913 err |= __get_user(karg->ca_umap.ug_udimap[i],
3914 &(((__kernel_uid_t32 *)A(uaddr))[i]));
3915 err |= __get_user(karg->ca_umap.ug_gidbase,
3916 &arg32->ca32_umap.ug32_gidbase);
3917 err |= __get_user(karg->ca_umap.ug_uidlen,
3918 &arg32->ca32_umap.ug32_gidlen);
3919 err |= __get_user(uaddr, &arg32->ca32_umap.ug32_gdimap);
3920 if (err)
3921 return -EFAULT;
3922 karg->ca_umap.ug_gdimap = kmalloc((sizeof(gid_t) * karg->ca_umap.ug_uidlen),
3923 GFP_USER);
3924 if(!karg->ca_umap.ug_gdimap)
3925 return -ENOMEM;
3926 for(i = 0; i < karg->ca_umap.ug_gidlen; i++)
3927 err |= __get_user(karg->ca_umap.ug_gdimap[i],
3928 &(((__kernel_gid_t32 *)A(uaddr))[i]));
3929
3930 return (err ? -EFAULT : 0);
3931}
3932
3933static int nfs_getfh32_trans(struct nfsctl_arg *karg, struct nfsctl_arg32 *arg32)
3934{
3935 int err;
3936
3937 err = __get_user(karg->ca_version, &arg32->ca32_version);
3938 err |= copy_from_user(&karg->ca_getfh.gf_addr,
3939 &arg32->ca32_getfh.gf32_addr,
3940 (sizeof(struct sockaddr)));
3941 err |= __get_user(karg->ca_getfh.gf_dev,
3942 &arg32->ca32_getfh.gf32_dev);
3943 err |= __get_user(karg->ca_getfh.gf_ino,
3944 &arg32->ca32_getfh.gf32_ino);
3945 err |= __get_user(karg->ca_getfh.gf_version,
3946 &arg32->ca32_getfh.gf32_version);
3947 return (err ? -EFAULT : 0);
3948}
3949
3950static int nfs_getfd32_trans(struct nfsctl_arg *karg, struct nfsctl_arg32 *arg32)
3951{
3952 int err;
3953
3954 err = __get_user(karg->ca_version, &arg32->ca32_version);
3955 err |= copy_from_user(&karg->ca_getfd.gd_addr,
3956 &arg32->ca32_getfd.gd32_addr,
3957 (sizeof(struct sockaddr)));
3958 err |= copy_from_user(&karg->ca_getfd.gd_path,
3959 &arg32->ca32_getfd.gd32_path,
3960 (NFS_MAXPATHLEN+1));
3961 err |= __get_user(karg->ca_getfd.gd_version,
3962 &arg32->ca32_getfd.gd32_version);
3963 return (err ? -EFAULT : 0);
3964}
3965
3966static int nfs_getfs32_trans(struct nfsctl_arg *karg, struct nfsctl_arg32 *arg32)
3967{
3968 int err;
3969
3970 err = __get_user(karg->ca_version, &arg32->ca32_version);
3971 err |= copy_from_user(&karg->ca_getfs.gd_addr,
3972 &arg32->ca32_getfs.gd32_addr,
3973 (sizeof(struct sockaddr)));
3974 err |= copy_from_user(&karg->ca_getfs.gd_path,
3975 &arg32->ca32_getfs.gd32_path,
3976 (NFS_MAXPATHLEN+1));
3977 err |= __get_user(karg->ca_getfs.gd_maxlen,
3978 &arg32->ca32_getfs.gd32_maxlen);
3979 return (err ? -EFAULT : 0);
3980}
3981
3982
3983
3984
3985static int nfs_getfh32_res_trans(union nfsctl_res *kres, union nfsctl_res32 *res32)
3986{
3987 return (copy_to_user(res32, kres, sizeof(*res32)) ? -EFAULT : 0);
3988}
3989
3990int asmlinkage sys32_nfsservctl(int cmd, struct nfsctl_arg32 *arg32, union nfsctl_res32 *res32)
3991{
3992 struct nfsctl_arg *karg = NULL;
3993 union nfsctl_res *kres = NULL;
3994 mm_segment_t oldfs;
3995 int err;
3996
3997 karg = kmalloc(sizeof(*karg), GFP_USER);
3998 if(!karg)
3999 return -ENOMEM;
4000 if(res32) {
4001 kres = kmalloc(sizeof(*kres), GFP_USER);
4002 if(!kres) {
4003 kfree(karg);
4004 return -ENOMEM;
4005 }
4006 }
4007 switch(cmd) {
4008 case NFSCTL_SVC:
4009 err = nfs_svc32_trans(karg, arg32);
4010 break;
4011 case NFSCTL_ADDCLIENT:
4012 err = nfs_clnt32_trans(karg, arg32);
4013 break;
4014 case NFSCTL_DELCLIENT:
4015 err = nfs_clnt32_trans(karg, arg32);
4016 break;
4017 case NFSCTL_EXPORT:
4018 case NFSCTL_UNEXPORT:
4019 err = nfs_exp32_trans(karg, arg32);
4020 break;
4021
4022 case NFSCTL_UGIDUPDATE:
4023 err = nfs_uud32_trans(karg, arg32);
4024 break;
4025 case NFSCTL_GETFH:
4026 err = nfs_getfh32_trans(karg, arg32);
4027 break;
4028 case NFSCTL_GETFD:
4029 err = nfs_getfd32_trans(karg, arg32);
4030 break;
4031 case NFSCTL_GETFS:
4032 err = nfs_getfs32_trans(karg, arg32);
4033 break;
4034 default:
4035 err = -EINVAL;
4036 break;
4037 }
4038 if(err)
4039 goto done;
4040 oldfs = get_fs();
4041 set_fs(KERNEL_DS);
4042 err = sys_nfsservctl(cmd, karg, kres);
4043 set_fs(oldfs);
4044
4045 if (err)
4046 goto done;
4047
4048 if((cmd == NFSCTL_GETFH) ||
4049 (cmd == NFSCTL_GETFD) ||
4050 (cmd == NFSCTL_GETFS))
4051 err = nfs_getfh32_res_trans(kres, res32);
4052
4053done:
4054 if(karg) {
4055 if(cmd == NFSCTL_UGIDUPDATE) {
4056 if(karg->ca_umap.ug_ident)
4057 kfree(karg->ca_umap.ug_ident);
4058 if(karg->ca_umap.ug_udimap)
4059 kfree(karg->ca_umap.ug_udimap);
4060 if(karg->ca_umap.ug_gdimap)
4061 kfree(karg->ca_umap.ug_gdimap);
4062 }
4063 kfree(karg);
4064 }
4065 if(kres)
4066 kfree(kres);
4067 return err;
4068}
4069#else
4070extern asmlinkage long sys_ni_syscall(void);
4071int asmlinkage sys32_nfsservctl(int cmd, void *notused, void *notused2)
4072{
4073 return sys_ni_syscall();
4074}
4075#endif
4076
4077
4078
4079
4080extern struct timezone sys_tz;
4081extern int do_sys_settimeofday(struct timeval *tv, struct timezone *tz);
4082
4083asmlinkage int sys32_gettimeofday(struct timeval32 *tv, struct timezone *tz)
4084{
4085 if (tv) {
4086 struct timeval ktv;
4087 do_gettimeofday(&ktv);
4088 if (put_tv32(tv, &ktv))
4089 return -EFAULT;
4090 }
4091 if (tz) {
4092 if (copy_to_user(tz, &sys_tz, sizeof(sys_tz)))
4093 return -EFAULT;
4094 }
4095 return 0;
4096}
4097
4098asmlinkage int sys32_settimeofday(struct timeval32 *tv, struct timezone *tz)
4099{
4100 struct timeval ktv;
4101 struct timezone ktz;
4102
4103 if (tv) {
4104 if (get_tv32(&ktv, tv))
4105 return -EFAULT;
4106 }
4107 if (tz) {
4108 if (copy_from_user(&ktz, tz, sizeof(ktz)))
4109 return -EFAULT;
4110 }
4111
4112 return do_sys_settimeofday(tv ? &ktv : NULL, tz ? &ktz : NULL);
4113}
4114
4115extern int do_getitimer(int which, struct itimerval *value);
4116
4117asmlinkage int sys32_getitimer(int which, struct itimerval32 *it)
4118{
4119 struct itimerval kit;
4120 int error;
4121
4122 error = do_getitimer(which, &kit);
4123 if (!error && put_it32(it, &kit))
4124 error = -EFAULT;
4125
4126 return error;
4127}
4128
4129extern int do_setitimer(int which, struct itimerval *, struct itimerval *);
4130
4131asmlinkage int sys32_setitimer(int which, struct itimerval32 *in, struct itimerval32 *out)
4132{
4133 struct itimerval kin, kout;
4134 int error;
4135
4136 if (in) {
4137 if (get_it32(&kin, in))
4138 return -EFAULT;
4139 } else
4140 memset(&kin, 0, sizeof(kin));
4141
4142 error = do_setitimer(which, &kin, out ? &kout : NULL);
4143 if (error || !out)
4144 return error;
4145 if (put_it32(out, &kout))
4146 return -EFAULT;
4147
4148 return 0;
4149
4150}
4151
4152asmlinkage int sys_utimes(char *, struct timeval *);
4153
4154asmlinkage int sys32_utimes(char *filename, struct timeval32 *tvs)
4155{
4156 char *kfilename;
4157 struct timeval ktvs[2];
4158 mm_segment_t old_fs;
4159 int ret;
4160
4161 kfilename = getname(filename);
4162 ret = PTR_ERR(kfilename);
4163 if (!IS_ERR(kfilename)) {
4164 if (tvs) {
4165 if (get_tv32(&ktvs[0], tvs) ||
4166 get_tv32(&ktvs[1], 1+tvs))
4167 return -EFAULT;
4168 }
4169
4170 old_fs = get_fs();
4171 set_fs(KERNEL_DS);
4172 ret = sys_utimes(kfilename, &ktvs[0]);
4173 set_fs(old_fs);
4174
4175 putname(kfilename);
4176 }
4177 return ret;
4178}
4179
4180
4181asmlinkage int sys32_pause(void)
4182{
4183 current->state = TASK_INTERRUPTIBLE;
4184 schedule();
4185 return -ERESTARTNOHAND;
4186}
4187
4188
4189extern asmlinkage int sys_pciconfig_read(unsigned long bus,
4190 unsigned long dfn,
4191 unsigned long off,
4192 unsigned long len,
4193 unsigned char *buf);
4194
4195extern asmlinkage int sys_pciconfig_write(unsigned long bus,
4196 unsigned long dfn,
4197 unsigned long off,
4198 unsigned long len,
4199 unsigned char *buf);
4200
4201asmlinkage int sys32_pciconfig_read(u32 bus, u32 dfn, u32 off, u32 len, u32 ubuf)
4202{
4203 return sys_pciconfig_read((unsigned long) bus,
4204 (unsigned long) dfn,
4205 (unsigned long) off,
4206 (unsigned long) len,
4207 (unsigned char *)AA(ubuf));
4208}
4209
4210asmlinkage int sys32_pciconfig_write(u32 bus, u32 dfn, u32 off, u32 len, u32 ubuf)
4211{
4212 return sys_pciconfig_write((unsigned long) bus,
4213 (unsigned long) dfn,
4214 (unsigned long) off,
4215 (unsigned long) len,
4216 (unsigned char *)AA(ubuf));
4217}
4218
4219extern asmlinkage int sys_prctl(int option, unsigned long arg2, unsigned long arg3,
4220 unsigned long arg4, unsigned long arg5);
4221
4222asmlinkage int sys32_prctl(int option, u32 arg2, u32 arg3, u32 arg4, u32 arg5)
4223{
4224 return sys_prctl(option,
4225 (unsigned long) arg2,
4226 (unsigned long) arg3,
4227 (unsigned long) arg4,
4228 (unsigned long) arg5);
4229}
4230
4231
4232extern asmlinkage ssize_t sys_pread(unsigned int fd, char * buf,
4233 size_t count, loff_t pos);
4234
4235extern asmlinkage ssize_t sys_pwrite(unsigned int fd, const char * buf,
4236 size_t count, loff_t pos);
4237
4238typedef __kernel_ssize_t32 ssize_t32;
4239
4240asmlinkage ssize_t32 sys32_pread(unsigned int fd, char *ubuf,
4241 __kernel_size_t32 count, u32 poshi, u32 poslo)
4242{
4243 return sys_pread(fd, ubuf, count, ((loff_t)AA(poshi) << 32) | AA(poslo));
4244}
4245
4246asmlinkage ssize_t32 sys32_pwrite(unsigned int fd, char *ubuf,
4247 __kernel_size_t32 count, u32 poshi, u32 poslo)
4248{
4249 return sys_pwrite(fd, ubuf, count, ((loff_t)AA(poshi) << 32) | AA(poslo));
4250}
4251
4252extern asmlinkage ssize_t sys_readahead(int fd, loff_t offset, size_t count);
4253
4254asmlinkage ssize_t32 sys32_readahead(int fd, u32 offhi, u32 offlo, s32 count)
4255{
4256 return sys_readahead(fd, ((loff_t)AA(offhi) << 32) | AA(offlo), count);
4257}
4258
4259extern asmlinkage ssize_t sys_sendfile(int out_fd, int in_fd, off_t *offset, size_t count);
4260
4261asmlinkage int sys32_sendfile(int out_fd, int in_fd, __kernel_off_t32 *offset, s32 count)
4262{
4263 mm_segment_t old_fs = get_fs();
4264 int ret;
4265 off_t of;
4266
4267 if (offset && get_user(of, offset))
4268 return -EFAULT;
4269
4270 set_fs(KERNEL_DS);
4271 ret = sys_sendfile(out_fd, in_fd, offset ? &of : NULL, count);
4272 set_fs(old_fs);
4273
4274 if (offset && put_user(of, offset))
4275 return -EFAULT;
4276
4277 return ret;
4278}
4279
4280
4281
4282struct timex32 {
4283 u32 modes;
4284 s32 offset, freq, maxerror, esterror;
4285 s32 status, constant, precision, tolerance;
4286 struct timeval32 time;
4287 s32 tick;
4288 s32 ppsfreq, jitter, shift, stabil;
4289 s32 jitcnt, calcnt, errcnt, stbcnt;
4290 s32 :32; s32 :32; s32 :32; s32 :32;
4291 s32 :32; s32 :32; s32 :32; s32 :32;
4292 s32 :32; s32 :32; s32 :32; s32 :32;
4293};
4294
4295extern int do_adjtimex(struct timex *);
4296
4297asmlinkage int sys32_adjtimex(struct timex32 *utp)
4298{
4299 struct timex txc;
4300 int ret;
4301
4302 memset(&txc, 0, sizeof(struct timex));
4303
4304 if(get_user(txc.modes, &utp->modes) ||
4305 __get_user(txc.offset, &utp->offset) ||
4306 __get_user(txc.freq, &utp->freq) ||
4307 __get_user(txc.maxerror, &utp->maxerror) ||
4308 __get_user(txc.esterror, &utp->esterror) ||
4309 __get_user(txc.status, &utp->status) ||
4310 __get_user(txc.constant, &utp->constant) ||
4311 __get_user(txc.precision, &utp->precision) ||
4312 __get_user(txc.tolerance, &utp->tolerance) ||
4313 __get_user(txc.time.tv_sec, &utp->time.tv_sec) ||
4314 __get_user(txc.time.tv_usec, &utp->time.tv_usec) ||
4315 __get_user(txc.tick, &utp->tick) ||
4316 __get_user(txc.ppsfreq, &utp->ppsfreq) ||
4317 __get_user(txc.jitter, &utp->jitter) ||
4318 __get_user(txc.shift, &utp->shift) ||
4319 __get_user(txc.stabil, &utp->stabil) ||
4320 __get_user(txc.jitcnt, &utp->jitcnt) ||
4321 __get_user(txc.calcnt, &utp->calcnt) ||
4322 __get_user(txc.errcnt, &utp->errcnt) ||
4323 __get_user(txc.stbcnt, &utp->stbcnt))
4324 return -EFAULT;
4325
4326 ret = do_adjtimex(&txc);
4327
4328 if(put_user(txc.modes, &utp->modes) ||
4329 __put_user(txc.offset, &utp->offset) ||
4330 __put_user(txc.freq, &utp->freq) ||
4331 __put_user(txc.maxerror, &utp->maxerror) ||
4332 __put_user(txc.esterror, &utp->esterror) ||
4333 __put_user(txc.status, &utp->status) ||
4334 __put_user(txc.constant, &utp->constant) ||
4335 __put_user(txc.precision, &utp->precision) ||
4336 __put_user(txc.tolerance, &utp->tolerance) ||
4337 __put_user(txc.time.tv_sec, &utp->time.tv_sec) ||
4338 __put_user(txc.time.tv_usec, &utp->time.tv_usec) ||
4339 __put_user(txc.tick, &utp->tick) ||
4340 __put_user(txc.ppsfreq, &utp->ppsfreq) ||
4341 __put_user(txc.jitter, &utp->jitter) ||
4342 __put_user(txc.shift, &utp->shift) ||
4343 __put_user(txc.stabil, &utp->stabil) ||
4344 __put_user(txc.jitcnt, &utp->jitcnt) ||
4345 __put_user(txc.calcnt, &utp->calcnt) ||
4346 __put_user(txc.errcnt, &utp->errcnt) ||
4347 __put_user(txc.stbcnt, &utp->stbcnt))
4348 ret = -EFAULT;
4349
4350 return ret;
4351}
4352
4353
4354
4355
4356
4357asmlinkage long sparc32_open(const char * filename, int flags, int mode)
4358{
4359 char * tmp;
4360 int fd, error;
4361
4362 tmp = getname(filename);
4363 fd = PTR_ERR(tmp);
4364 if (!IS_ERR(tmp)) {
4365 fd = get_unused_fd();
4366 if (fd >= 0) {
4367 struct file * f = filp_open(tmp, flags, mode);
4368 error = PTR_ERR(f);
4369 if (IS_ERR(f))
4370 goto out_error;
4371 fd_install(fd, f);
4372 }
4373out:
4374 putname(tmp);
4375 }
4376 return fd;
4377
4378out_error:
4379 put_unused_fd(fd);
4380 fd = error;
4381 goto out;
4382}
4383
4384extern unsigned long do_mremap(unsigned long addr,
4385 unsigned long old_len, unsigned long new_len,
4386 unsigned long flags, unsigned long new_addr);
4387
4388asmlinkage unsigned long sys32_mremap(unsigned long addr,
4389 unsigned long old_len, unsigned long new_len,
4390 unsigned long flags, u32 __new_addr)
4391{
4392 struct vm_area_struct *vma;
4393 unsigned long ret = -EINVAL;
4394 unsigned long new_addr = AA(__new_addr);
4395
4396 if (old_len > 0xf0000000UL || new_len > 0xf0000000UL)
4397 goto out;
4398 if (addr > 0xf0000000UL - old_len)
4399 goto out;
4400 down_write(¤t->mm->mmap_sem);
4401 if (flags & MREMAP_FIXED) {
4402 if (new_addr > 0xf0000000UL - new_len)
4403 goto out_sem;
4404 } else if (addr > 0xf0000000UL - new_len) {
4405 unsigned long map_flags = 0;
4406 struct file *file = NULL;
4407
4408 ret = -ENOMEM;
4409 if (!(flags & MREMAP_MAYMOVE))
4410 goto out_sem;
4411
4412 vma = find_vma(current->mm, addr);
4413 if (vma) {
4414 if (vma->vm_flags & VM_SHARED)
4415 map_flags |= MAP_SHARED;
4416 file = vma->vm_file;
4417 }
4418
4419
4420 new_addr = get_unmapped_area(file, addr, new_len,
4421 vma ? vma->vm_pgoff : 0,
4422 map_flags);
4423 ret = new_addr;
4424 if (new_addr & ~PAGE_MASK)
4425 goto out_sem;
4426 flags |= MREMAP_FIXED;
4427 }
4428 ret = do_mremap(addr, old_len, new_len, flags, new_addr);
4429out_sem:
4430 up_write(¤t->mm->mmap_sem);
4431out:
4432 return ret;
4433}
4434
4435extern asmlinkage long sys_setpriority(int which, int who, int niceval);
4436
4437asmlinkage int sys_setpriority32(u32 which, u32 who, u32 niceval)
4438{
4439 return sys_setpriority((int) which,
4440 (int) who,
4441 (int) niceval);
4442}
4443
4444struct __sysctl_args32 {
4445 u32 name;
4446 int nlen;
4447 u32 oldval;
4448 u32 oldlenp;
4449 u32 newval;
4450 u32 newlen;
4451 u32 __unused[4];
4452};
4453
4454extern asmlinkage long sys32_sysctl(struct __sysctl_args32 *args)
4455{
4456#ifndef CONFIG_SYSCTL
4457 return -ENOSYS;
4458#else
4459 struct __sysctl_args32 tmp;
4460 int error;
4461 size_t oldlen, *oldlenp = NULL;
4462 unsigned long addr = (((long)&args->__unused[0]) + 7) & ~7;
4463
4464 if (copy_from_user(&tmp, args, sizeof(tmp)))
4465 return -EFAULT;
4466
4467 if (tmp.oldval && tmp.oldlenp) {
4468
4469
4470
4471
4472
4473
4474 if (get_user(oldlen, (u32 *)A(tmp.oldlenp)) ||
4475 put_user(oldlen, (size_t *)addr))
4476 return -EFAULT;
4477 oldlenp = (size_t *)addr;
4478 }
4479
4480 lock_kernel();
4481 error = do_sysctl((int *)A(tmp.name), tmp.nlen, (void *)A(tmp.oldval),
4482 oldlenp, (void *)A(tmp.newval), tmp.newlen);
4483 unlock_kernel();
4484 if (oldlenp) {
4485 if (!error) {
4486 if (get_user(oldlen, (size_t *)addr) ||
4487 put_user(oldlen, (u32 *)A(tmp.oldlenp)))
4488 error = -EFAULT;
4489 }
4490 copy_to_user(args->__unused, tmp.__unused, sizeof(tmp.__unused));
4491 }
4492 return error;
4493#endif
4494}
4495