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