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