OpenCores
URL https://opencores.org/ocsvn/or1k/or1k/trunk

Subversion Repositories or1k

[/] [or1k/] [trunk/] [linux/] [linux-2.4/] [arch/] [ia64/] [ia32/] [sys_ia32.c] - Blame information for rev 1275

Go to most recent revision | Details | Compare with Previous | View Log

Line No. Rev Author Line
1 1275 phoenix
/*
2
 * sys_ia32.c: Conversion between 32bit and 64bit native syscalls. Derived from sys_sparc32.c.
3
 *
4
 * Copyright (C) 2000           VA Linux Co
5
 * Copyright (C) 2000           Don Dugger <n0ano@valinux.com>
6
 * Copyright (C) 1999           Arun Sharma <arun.sharma@intel.com>
7
 * Copyright (C) 1997,1998      Jakub Jelinek (jj@sunsite.mff.cuni.cz)
8
 * Copyright (C) 1997           David S. Miller (davem@caip.rutgers.edu)
9
 * Copyright (C) 2000-2002 Hewlett-Packard Co
10
 *      David Mosberger-Tang <davidm@hpl.hp.com>
11
 *
12
 * These routines maintain argument size conversion between 32bit and 64bit
13
 * environment.
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
 
79
extern asmlinkage long sys_execve (char *, char **, char **, struct pt_regs *);
80
extern asmlinkage long sys_mprotect (unsigned long, size_t, unsigned long);
81
extern asmlinkage long sys_munmap (unsigned long, size_t);
82
extern unsigned long arch_get_unmapped_area (struct file *, unsigned long, unsigned long,
83
                                             unsigned long, unsigned long);
84
 
85
/* forward declaration: */
86
asmlinkage long sys32_mprotect (unsigned int, unsigned int, int);
87
asmlinkage unsigned long sys_brk(unsigned long);
88
 
89
/*
90
 * Anything that modifies or inspects ia32 user virtual memory must hold this semaphore
91
 * while doing so.
92
 */
93
/* XXX make per-mm: */
94
static DECLARE_MUTEX(ia32_mmap_sem);
95
 
96
static int
97
nargs (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
 
118
asmlinkage long
119
sys32_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
        /* we may be exec'ing a 64-bit process: reset map base, task-size, and io-base: */
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
                /* oops, execve failed, switch back to old values... */
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);        /* establish new task-size as the address-limit */
170
        }
171
  out:
172
        kfree(av);
173
        return r;
174
}
175
 
176
static inline int
177
putstat (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
 
200
extern asmlinkage long sys_newstat (char * filename, struct stat * statbuf);
201
 
202
asmlinkage long
203
sys32_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
 
222
extern asmlinkage long sys_newlstat(char * filename, struct stat * statbuf);
223
 
224
asmlinkage long
225
sys32_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
 
244
extern asmlinkage long sys_newfstat(unsigned int fd, struct stat * statbuf);
245
 
246
asmlinkage long
247
sys32_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
 
264
static int
265
get_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
 * Map a subpage by creating an anonymous page that contains the union of the old page and
283
 * the subpage.
284
 */
285
static unsigned long
286
mmap_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
        /* Optimize the case where the old mmap and the new mmap are both anonymous */
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(&current->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(&current->mm->mmap_sem);
321
 
322
        if (IS_ERR((void *) ret))
323
                goto out;
324
 
325
        if (old_prot) {
326
                /* copy back the old page contents.  */
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
                /* read the file contents */
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
 
354
static unsigned long
355
emulate_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;   /* done */
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;   /* done */
392
                }
393
        } else {
394
                /*
395
                 * If a start address was specified, use it if the entire rounded out area
396
                 * is available.
397
                 */
398
                if (start && !pstart)
399
                        fudge = 1;      /* handle case of mapping to range (0,PAGE_SIZE) */
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); /* make start congruent with off */
404
                        end = start + len;
405
                        pend = PAGE_ALIGN(end);
406
                }
407
        }
408
 
409
        poff = off + (pstart - start);  /* note: (pstart - start) may be negative */
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(&current->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(&current->mm->mmap_sem);
429
 
430
        if (IS_ERR((void *) ret))
431
                return ret;
432
 
433
        if (!is_congruent) {
434
                /* read the file contents */
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 /* PAGE_SHIFT > IA32_PAGE_SHIFT */
449
 
450
static inline unsigned int
451
get_prot32 (unsigned int prot)
452
{
453
        if (prot & PROT_WRITE)
454
                /* on x86, PROT_WRITE implies PROT_READ which implies PROT_EEC */
455
                prot |= PROT_READ | PROT_WRITE | PROT_EXEC;
456
        else if (prot & (PROT_READ | PROT_EXEC))
457
                /* on x86, there is no distinction between PROT_READ and PROT_EXEC */
458
                prot |= (PROT_READ | PROT_EXEC);
459
 
460
        return prot;
461
}
462
 
463
unsigned long
464
ia32_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(&current->mm->mmap_sem);
498
        {
499
                addr = do_mmap(file, addr, len, prot, flags, offset);
500
        }
501
        up_write(&current->mm->mmap_sem);
502
#endif
503
        DBG("ia32_do_mmap: returning 0x%lx\n", addr);
504
        return addr;
505
}
506
 
507
/*
508
 * Linux/i386 didn't use to be able to handle more than 4 system call parameters, so these
509
 * system calls used a memory block for parameter passing..
510
 */
511
 
512
struct 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
 
521
asmlinkage long
522
sys32_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
 
551
asmlinkage long
552
sys32_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
 
573
asmlinkage long
574
sys32_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
 * When mprotect()ing a partial page, we set the permission to the union of the old
604
 * settings and the new settings.  In other words, it's only possible to make access to a
605
 * partial page less restrictive.
606
 */
607
static long
608
mprotect_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;                /* optimize case where nothing changes... */
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 /* PAGE_SHIFT > IA32_PAGE_SHIFT */
621
 
622
asmlinkage long
623
sys32_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
                        /* start address is 4KB aligned but not page aligned. */
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;       /* retval is already zero... */
653
                }
654
 
655
                if (PAGE_OFF(end)) {
656
                        /* end address is 4KB aligned but not page aligned. */
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
 
671
asmlinkage long
672
sys32_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
 
686
static inline int
687
put_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
 
707
extern asmlinkage long sys_statfs(const char * path, struct statfs * buf);
708
 
709
asmlinkage long
710
sys32_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
 
729
extern asmlinkage long sys_fstatfs(unsigned int fd, struct statfs * buf);
730
 
731
asmlinkage long
732
sys32_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
 
746
struct timeval32
747
{
748
    int tv_sec, tv_usec;
749
};
750
 
751
struct itimerval32
752
{
753
    struct timeval32 it_interval;
754
    struct timeval32 it_value;
755
};
756
 
757
static inline long
758
get_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
 
764
static inline long
765
put_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
 
771
static inline long
772
get_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
 
781
static inline long
782
put_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
 
791
extern int do_getitimer (int which, struct itimerval *value);
792
 
793
asmlinkage long
794
sys32_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
 
806
extern int do_setitimer (int which, struct itimerval *, struct itimerval *);
807
 
808
asmlinkage long
809
sys32_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
 
830
asmlinkage unsigned long
831
sys32_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
        /* ehhh.. We can't return 0 if we have an alarm pending.. */
842
        /* And we'd better return too much than too little anyway */
843
        if (it_old.it_value.tv_usec)
844
                oldalarm++;
845
        return oldalarm;
846
}
847
 
848
/* Translations due to time_t size differences.  Which affects all
849
   sorts of things, like timeval and itimerval.  */
850
 
851
struct utimbuf_32 {
852
        int     atime;
853
        int     mtime;
854
};
855
 
856
extern asmlinkage long sys_utimes(char * filename, struct timeval * utimes);
857
extern asmlinkage long sys_gettimeofday (struct timeval *tv, struct timezone *tz);
858
 
859
asmlinkage long
860
sys32_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, &times32->atime))
868
                        return -EFAULT;
869
                tv[0].tv_usec = 0;
870
                if (get_user(tv[1].tv_sec, &times32->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
 
882
extern struct timezone sys_tz;
883
extern int do_sys_settimeofday (struct timeval *tv, struct timezone *tz);
884
 
885
asmlinkage long
886
sys32_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
 
901
asmlinkage long
902
sys32_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
 
919
struct getdents32_callback {
920
        struct linux32_dirent * current_dir;
921
        struct linux32_dirent * previous;
922
        int count;
923
        int error;
924
};
925
 
926
struct readdir32_callback {
927
        struct old_linux32_dirent * dirent;
928
        int count;
929
};
930
 
931
static int
932
filldir32 (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;   /* only used if we fail.. */
940
        if (reclen > buf->count)
941
                return -EINVAL;
942
        buf->error = -EFAULT;   /* only used if we fail.. */
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
 
960
asmlinkage long
961
sys32_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
 
990
out_putf:
991
        fput(file);
992
out:
993
        return error;
994
}
995
 
996
static int
997
fillonedir32 (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
 
1016
asmlinkage long
1017
sys32_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);
1035
out:
1036
        return error;
1037
}
1038
 
1039
/*
1040
 * We can actually return ERESTARTSYS instead of EINTR, but I'd
1041
 * like to be certain this leads to no problems. So I return
1042
 * EINTR just for safety.
1043
 *
1044
 * Update: ERESTARTSYS breaks at least the xview clock binary, so
1045
 * I'm trying ERESTARTNOHAND which restart only when you want to.
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
 
1051
asmlinkage long
1052
sys32_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
         * We need 6 bitmaps (in/out/ex for both incoming and outgoing),
1086
         * since we used fdset we need to allocate memory in units of
1087
         * long-words.
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
 
1137
out:
1138
        kfree(bits);
1139
out_nofds:
1140
        return ret;
1141
}
1142
 
1143
struct 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
 
1151
asmlinkage long
1152
sys32_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
 
1162
extern asmlinkage long sys_nanosleep (struct timespec *rqtp, struct timespec *rmtp);
1163
 
1164
asmlinkage long
1165
sys32_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
 
1183
struct iovec32 { unsigned int iov_base; int iov_len; };
1184
asmlinkage ssize_t sys_readv (unsigned long,const struct iovec *,unsigned long);
1185
asmlinkage ssize_t sys_writev (unsigned long,const struct iovec *,unsigned long);
1186
 
1187
static struct iovec *
1188
get_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
        /* Get the "struct iovec" from user memory */
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
 
1229
asmlinkage long
1230
sys32_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
 
1248
asmlinkage long
1249
sys32_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
 
1270
struct rlimit32 {
1271
        unsigned int    rlim_cur;
1272
        unsigned int    rlim_max;
1273
};
1274
 
1275
extern asmlinkage long sys_getrlimit (unsigned int resource, struct rlimit *rlim);
1276
 
1277
asmlinkage long
1278
sys32_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
 
1294
asmlinkage long
1295
sys32_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
 
1315
extern asmlinkage long sys_setrlimit (unsigned int resource, struct rlimit *rlim);
1316
 
1317
asmlinkage long
1318
sys32_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
 *  Declare the IA32 version of the msghdr
1340
 */
1341
 
1342
struct msghdr32 {
1343
        unsigned int    msg_name;       /* Socket name                  */
1344
        int             msg_namelen;    /* Length of name               */
1345
        unsigned int    msg_iov;        /* Data blocks                  */
1346
        unsigned int    msg_iovlen;     /* Number of blocks             */
1347
        unsigned int    msg_control;    /* Per protocol magic (eg BSD file descriptor passing) */
1348
        unsigned int    msg_controllen; /* Length of cmsg list */
1349
        unsigned        msg_flags;
1350
};
1351
 
1352
struct cmsghdr32 {
1353
        __kernel_size_t32 cmsg_len;
1354
        int               cmsg_level;
1355
        int               cmsg_type;
1356
};
1357
 
1358
/* Bleech... */
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
 
1371
static 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
 
1382
static inline struct cmsghdr32 *
1383
cmsg32_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
 
1388
static inline int
1389
get_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
 * There is a lot of hair here because the alignment rules (and thus placement) of cmsg
1411
 * headers and length are different for 32-bit apps.  -DaveM
1412
 */
1413
static int
1414
get_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
                /* Catch bogons. */
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
         * The kcmlen holds the 64-bit version of the control length.  It may not be
1446
         * modified as we do not stick it into the kmsg until we have successfully copied
1447
         * over all of the data from the user.
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
        /* Now copy them over neatly. */
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
                /* Copy over the data. */
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
                /* Advance. */
1474
                kcmsg = (struct cmsghdr *)((char *)kcmsg + CMSG_ALIGN(tmp));
1475
                ucmsg = CMSG32_NXTHDR(kmsg, ucmsg, ucmlen);
1476
        }
1477
 
1478
        /* Ok, looks like we made it.  Hook it up and return success. */
1479
        kmsg->msg_control = kcmsg_base;
1480
        kmsg->msg_controllen = kcmlen;
1481
        return 0;
1482
 
1483
out_free_efault:
1484
        if (kcmsg_base != (struct cmsghdr *)stackbuf)
1485
                sock_kfree_s(sk, kcmsg_base, kcmlen);
1486
        return -EFAULT;
1487
}
1488
 
1489
/*
1490
 *      Verify & re-shape IA32 iovec. The caller must ensure that the
1491
 *      iovec is big enough to hold the re-shaped message iovec.
1492
 *
1493
 *      Save time not doing verify_area. copy_*_user will make this work
1494
 *      in any case.
1495
 *
1496
 *      Don't need to check the total size for overflow (cf net/core/iovec.c),
1497
 *      32-bit sizes can't overflow a 64-bit count.
1498
 */
1499
 
1500
static inline int
1501
verify_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
        }
1529
out:
1530
        return err;
1531
}
1532
 
1533
static void
1534
put_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
 
1563
static void
1564
scm_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
                /* Bump the usage count and install the file. */
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
         * All of the files that fit in the message have had their
1614
         * usage counts incremented, so we just free the list.
1615
         */
1616
        __scm_destroy(scm);
1617
}
1618
 
1619
/*
1620
 * In these cases we (currently) can just copy to data over verbatim because all CMSGs
1621
 * created by the kernel have well defined types which have the same layout in both the
1622
 * 32-bit and 64-bit API.  One must add some special cased conversions here if we start
1623
 * sending control messages with incompatible types.
1624
 *
1625
 * SCM_RIGHTS and SCM_CREDENTIALS are done by hand in recvmsg32 right after
1626
 * we do our work.  The remaining cases are:
1627
 *
1628
 * SOL_IP       IP_PKTINFO      struct in_pktinfo       32-bit clean
1629
 *              IP_TTL          int                     32-bit clean
1630
 *              IP_TOS          __u8                    32-bit clean
1631
 *              IP_RECVOPTS     variable length         32-bit clean
1632
 *              IP_RETOPTS      variable length         32-bit clean
1633
 *              (these last two are clean because the types are defined
1634
 *               by the IPv4 protocol)
1635
 *              IP_RECVERR      struct sock_extended_err +
1636
 *                              struct sockaddr_in      32-bit clean
1637
 * SOL_IPV6     IPV6_RECVERR    struct sock_extended_err +
1638
 *                              struct sockaddr_in6     32-bit clean
1639
 *              IPV6_PKTINFO    struct in6_pktinfo      32-bit clean
1640
 *              IPV6_HOPLIMIT   int                     32-bit clean
1641
 *              IPV6_FLOWINFO   u32                     32-bit clean
1642
 *              IPV6_HOPOPTS    ipv6 hop exthdr         32-bit clean
1643
 *              IPV6_DSTOPTS    ipv6 dst exthdr(s)      32-bit clean
1644
 *              IPV6_RTHDR      ipv6 routing exthdr     32-bit clean
1645
 *              IPV6_AUTHHDR    ipv6 auth exthdr        32-bit clean
1646
 */
1647
static void
1648
cmsg32_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
        /* To make this more sane we assume the kernel sends back properly
1662
         * formatted control messages.  Because of how the kernel will truncate
1663
         * the cmsg_len for MSG_TRUNC cases, we need not check that case either.
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
                 * UCMSG is the 64-bit format CMSG entry in user-space.  KCMSG32 is within
1672
                 * the kernel space temporary buffer we use to convert into a 32-bit style
1673
                 * CMSG.
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
        /* Copy back fixed up data, and adjust pointers. */
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
         * If we leave the 64-bit format CMSG chunks in there, the application could get
1707
         * confused and crash.  So to ensure greater recovery, we report no CMSGs.
1708
         */
1709
        kmsg->msg_controllen += bufsz;
1710
        kmsg->msg_control = (void *) orig_cmsg_uptr;
1711
}
1712
 
1713
static inline void
1714
sockfd_put (struct socket *sock)
1715
{
1716
        fput(sock->file);
1717
}
1718
 
1719
/* XXX This really belongs in some header file... -DaveM */
1720
#define MAX_SOCK_ADDR   128             /* 108 for Unix domain -
1721
                                           16 for IP, 16 for IPX,
1722
                                           24 for IPv6,
1723
                                           about 80 for AX.25 */
1724
 
1725
extern struct socket *sockfd_lookup (int fd, int *err);
1726
 
1727
/*
1728
 *      BSD sendmsg interface
1729
 */
1730
 
1731
int
1732
sys32_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]; /* 20 is size of ipv6_pktinfo */
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
        /* do not move before msg_sys is valid */
1752
        err = -EINVAL;
1753
        if (msg_sys.msg_iovlen > UIO_MAXIOV)
1754
                goto out_put;
1755
 
1756
        /* Check whether to allocate the iovec area*/
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
        /* This will also move the address data into kernel space */
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);
1790
out_freeiov:
1791
        if (iov != iovstack)
1792
                sock_kfree_s(sock->sk, iov, iov_size);
1793
out_put:
1794
        sockfd_put(sock);
1795
out:
1796
        return err;
1797
}
1798
 
1799
/*
1800
 *      BSD recvmsg interface
1801
 */
1802
 
1803
int
1804
sys32_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
        /* kernel mode address */
1815
        char addr[MAX_SOCK_ADDR];
1816
 
1817
        /* user mode address pointers */
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
        /* Check whether to allocate the iovec area*/
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
         *      Save the user-mode address (verify_iovec will change the
1844
         *      kernel msghdr to use the kernel address space)
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
                         * If recvmsg processing itself placed some control messages into
1877
                         * user space, it's is using 64-bit CMSG processing, so we need to
1878
                         * fix it up before we tack on more stuff.
1879
                         */
1880
                        if ((unsigned long) msg_sys.msg_control != cmsg_ptr)
1881
                                cmsg32_recvmsg_fixup(&msg_sys, cmsg_ptr);
1882
 
1883
                        /* Wheee... */
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
/* Argument list sizes for sys_socketcall */
1920
#define AL(x) ((x) * sizeof(u32))
1921
static 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
 
1926
extern asmlinkage long sys_bind(int fd, struct sockaddr *umyaddr, int addrlen);
1927
extern asmlinkage long sys_connect(int fd, struct sockaddr *uservaddr,
1928
                                  int addrlen);
1929
extern asmlinkage long sys_accept(int fd, struct sockaddr *upeer_sockaddr,
1930
                                 int *upeer_addrlen);
1931
extern asmlinkage long sys_getsockname(int fd, struct sockaddr *usockaddr,
1932
                                      int *usockaddr_len);
1933
extern asmlinkage long sys_getpeername(int fd, struct sockaddr *usockaddr,
1934
                                      int *usockaddr_len);
1935
extern asmlinkage long sys_send(int fd, void *buff, size_t len, unsigned flags);
1936
extern asmlinkage long sys_sendto(int fd, u32 buff, __kernel_size_t32 len,
1937
                                   unsigned flags, u32 addr, int addr_len);
1938
extern asmlinkage long sys_recv(int fd, void *ubuf, size_t size, unsigned flags);
1939
extern asmlinkage long sys_recvfrom(int fd, u32 ubuf, __kernel_size_t32 size,
1940
                                     unsigned flags, u32 addr, u32 addr_len);
1941
extern asmlinkage long sys_setsockopt(int fd, int level, int optname,
1942
                                     char *optval, int optlen);
1943
extern asmlinkage long sys_getsockopt(int fd, int level, int optname,
1944
                                       u32 optval, u32 optlen);
1945
 
1946
extern asmlinkage long sys_socket(int family, int type, int protocol);
1947
extern asmlinkage long sys_socketpair(int family, int type, int protocol,
1948
                                     int usockvec[2]);
1949
extern asmlinkage long sys_shutdown(int fd, int how);
1950
extern asmlinkage long sys_listen(int fd, int backlog);
1951
 
1952
asmlinkage long
1953
sys32_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
 * sys32_ipc() is the de-multiplexer for the SysV IPC calls in 32bit emulation..
2029
 *
2030
 * This is really horribly ugly.
2031
 */
2032
 
2033
struct msgbuf32 { s32 mtype; char mtext[1]; };
2034
 
2035
struct 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
 
2045
struct 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
 
2059
struct semid_ds32 {
2060
        struct ipc_perm32 sem_perm;               /* permissions .. see ipc.h */
2061
        __kernel_time_t32 sem_otime;              /* last semop time */
2062
        __kernel_time_t32 sem_ctime;              /* last change time */
2063
        u32 sem_base;              /* ptr to first semaphore in array */
2064
        u32 sem_pending;          /* pending operations to be processed */
2065
        u32 sem_pending_last;    /* last pending operation */
2066
        u32 undo;                  /* undo requests on this array */
2067
        unsigned short  sem_nsems;              /* no. of semaphores in array */
2068
};
2069
 
2070
struct 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
 
2081
struct 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
 
2097
struct 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
 
2114
struct 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
 
2125
struct 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
 
2141
struct 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
 
2153
struct shm_info32 {
2154
        int used_ids;
2155
        u32 shm_tot, shm_rss, shm_swp;
2156
        u32 swap_attempts, swap_successes;
2157
};
2158
 
2159
struct 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
 
2178
static int
2179
ipc_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
 
2189
static int
2190
semctl32 (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
 
2276
static int
2277
do_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
 
2299
static int
2300
do_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;
2333
free_then_out:
2334
        kfree(p);
2335
out:
2336
        return err;
2337
}
2338
 
2339
static int
2340
msgctl32 (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
 
2434
static int
2435
shmat32 (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; /* iBCS2 emulator entry point: unsupported */
2443
        err = sys_shmat(first, uptr, second, &raddr);
2444
        if (err)
2445
                return err;
2446
        return put_user(raddr, uaddr);
2447
}
2448
 
2449
static int
2450
shmctl32 (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
 
2598
asmlinkage long
2599
sys32_ipc (u32 call, int first, int second, int third, u32 ptr, u32 fifth)
2600
{
2601
        int version;
2602
 
2603
        version = call >> 16; /* hack for backward compatibility */
2604
        call &= 0xffff;
2605
 
2606
        switch (call) {
2607
              case SEMOP:
2608
                /* struct sembuf is the same on 32 and 64bit :)) */
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
 * sys_time() can be implemented in user-level using
2642
 * sys_gettimeofday().  IA64 did this but i386 Linux did not
2643
 * so we have to implement this system call here.
2644
 */
2645
asmlinkage long
2646
sys32_time (int *tloc)
2647
{
2648
        int i;
2649
 
2650
        /* SMP: This is fairly trivial. We grab CURRENT_TIME and
2651
           stuff it to user space. No side effects */
2652
        i = CURRENT_TIME;
2653
        if (tloc) {
2654
                if (put_user(i, tloc))
2655
                        i = -EFAULT;
2656
        }
2657
        return i;
2658
}
2659
 
2660
struct 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
 
2679
static int
2680
put_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
 
2708
asmlinkage long
2709
sys32_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
 
2730
asmlinkage long
2731
sys32_waitpid (int pid, unsigned int *stat_addr, int options)
2732
{
2733
        return sys32_wait4(pid, stat_addr, options, NULL);
2734
}
2735
 
2736
 
2737
extern asmlinkage long sys_getrusage (int who, struct rusage *ru);
2738
 
2739
asmlinkage long
2740
sys32_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
 
2754
struct 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
 
2761
extern asmlinkage long sys_times (struct tms * tbuf);
2762
 
2763
asmlinkage long
2764
sys32_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
 
2785
static unsigned int
2786
ia32_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
 
2795
static unsigned int
2796
ia32_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
 *  The order in which registers are stored in the ptrace regs structure
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
 
2825
static unsigned int
2826
getreg (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; /* see dispatch_to_ia32_handler() */
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
 
2853
static void
2854
putreg (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
 
2889
static void
2890
put_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
 
2922
static void
2923
get_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
 
2952
static int
2953
save_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
         *  Stack frames start with 16-bytes of temp space
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
 
2981
static int
2982
restore_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
         *  Stack frames start with 16-bytes of temp space
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
 
3014
static int
3015
save_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
         *  Stack frames start with 16-bytes of temp space
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
 
3053
static int
3054
restore_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
         *  Stack frames start with 16-bytes of temp space
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
 
3101
extern asmlinkage long sys_ptrace (long, pid_t, unsigned long, unsigned long, long, long, long,
3102
                                   long, long);
3103
 
3104
/*
3105
 *  Note that the IA32 version of `ptrace' calls the IA64 routine for
3106
 *    many of the requests.  This will only work for requests that do
3107
 *    not need access to the calling processes `pt_regs' which is located
3108
 *    at the address of `stack'.  Once we call the IA64 `sys_ptrace' then
3109
 *    the address of `stack' will not be the address of the `pt_regs'.
3110
 */
3111
asmlinkage long
3112
sys32_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)           /* no messing around with init! */
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:     /* read word at location addr */
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:     /* write the word at location addr */
3159
                ret = ia32_poke(regs, child, addr, data);
3160
                goto out_tsk;
3161
 
3162
              case PTRACE_PEEKUSR:      /* read word at addr in USER area */
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:      /* write word at addr in USER area */
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:      /* continue, stop after next syscall */
3223
              case PTRACE_CONT:         /* restart after signal. */
3224
              case PTRACE_KILL:
3225
              case PTRACE_SINGLESTEP:   /* execute chile for one instruction */
3226
              case PTRACE_DETACH:       /* detach a process */
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
 
3242
static inline int
3243
get_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
 
3258
static inline int
3259
put_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
 
3274
extern asmlinkage long sys_fcntl (unsigned int fd, unsigned int cmd, unsigned long arg);
3275
 
3276
asmlinkage long
3277
sys32_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
                 *  `sys_fcntl' lies about arg, for the F_SETOWN
3300
                 *  sub-function arg can have a negative value.
3301
                 */
3302
                return sys_fcntl(fd, cmd, arg);
3303
        }
3304
}
3305
 
3306
asmlinkage long sys_ni_syscall(void);
3307
 
3308
asmlinkage long
3309
sys32_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
 *  The IA64 maps 4 I/O ports for each 4K page
3321
 */
3322
#define IOLEN   ((65536 / 4) * 4096)
3323
 
3324
asmlinkage long
3325
sys32_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
        /* Trying to gain more privileges? */
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(&current->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(&current->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
 
3369
asmlinkage long
3370
sys32_ioperm (unsigned int from, unsigned int num, int on)
3371
{
3372
 
3373
        /*
3374
         *  Since IA64 doesn't have permission bits we'd have to go to
3375
         *    a lot of trouble to simulate them in software.  There's
3376
         *    no point, only trusted programs can make this call so we'll
3377
         *    just turn it into an iopl call and let the process have
3378
         *    access to all I/O ports.
3379
         *
3380
         * XXX proper ioperm() support should be emulated by
3381
         *      manipulating the page protections...
3382
         */
3383
        return sys32_iopl(3);
3384
}
3385
 
3386
typedef struct {
3387
        unsigned int    ss_sp;
3388
        unsigned int    ss_flags;
3389
        unsigned int    ss_size;
3390
} ia32_stack_t;
3391
 
3392
asmlinkage long
3393
sys32_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
        /* MINSIGSTKSZ is different for ia32 vs ia64. We lie here to pass the
3408
           check and set it to the user requested value later */
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);
3418
out:
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
 
3431
asmlinkage int
3432
sys32_pause (void)
3433
{
3434
        current->state = TASK_INTERRUPTIBLE;
3435
        schedule();
3436
        return -ERESTARTNOHAND;
3437
}
3438
 
3439
asmlinkage long sys_msync (unsigned long start, size_t len, int flags);
3440
 
3441
asmlinkage int
3442
sys32_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
 
3452
struct 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
 
3462
extern asmlinkage long sys_sysctl(struct __sysctl_args *args);
3463
 
3464
asmlinkage long
3465
sys32_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
         * We need to pre-validate these because we have to disable address checking
3480
         * before calling do_sysctl() because of OLDLEN but we can't run the risk of the
3481
         * user specifying bad addresses here.  Well, since we're dealing with 32 bit
3482
         * addresses, we KNOW that access_ok() will always succeed, so this is an
3483
         * expensive NOP, but so what...
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
 
3510
asmlinkage long
3511
sys32_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
 
3522
extern asmlinkage long sys_getresuid (uid_t *ruid, uid_t *euid, uid_t *suid);
3523
 
3524
asmlinkage long
3525
sys32_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
 
3540
extern asmlinkage long sys_getresgid (gid_t *rgid, gid_t *egid, gid_t *sgid);
3541
 
3542
asmlinkage long
3543
sys32_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
 
3559
asmlinkage long
3560
sys32_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
        /* Sign-extension of "offset" is important here... */
3565
        return sys_lseek(fd, offset, whence);
3566
}
3567
 
3568
extern asmlinkage long sys_getgroups (int gidsetsize, gid_t *grouplist);
3569
 
3570
asmlinkage long
3571
sys32_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
 
3588
extern asmlinkage long sys_setgroups (int gidsetsize, gid_t *grouplist);
3589
 
3590
asmlinkage long
3591
sys32_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
 * Unfortunately, the x86 compiler aligns variables of type "long long" to a 4 byte boundary
3610
 * only, which means that the x86 version of "struct flock64" doesn't match the ia64 version
3611
 * of struct flock.
3612
 */
3613
 
3614
static inline long
3615
ia32_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
 
3624
static inline long
3625
ia32_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
 
3640
asmlinkage long
3641
sys32_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
 
3670
asmlinkage long
3671
sys32_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
 
3678
asmlinkage long
3679
sys32_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
 
3686
static int
3687
putstat64 (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
 
3713
asmlinkage long
3714
sys32_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
 
3733
asmlinkage long
3734
sys32_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
 
3753
asmlinkage long
3754
sys32_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
 
3768
asmlinkage long
3769
sys32_sigpending (unsigned int *set)
3770
{
3771
        return do_sigpending(set, sizeof(*set));
3772
}
3773
 
3774
struct 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
 
3791
asmlinkage long
3792
sys32_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
        /* Check to see if any memory value is too large for 32-bit and
3804
         * scale down if needed.
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
/* In order to reduce some races, while at the same time doing additional
3844
 * checking and hopefully speeding things up, we copy filenames to the
3845
 * kernel data space before using them..
3846
 *
3847
 * POSIX.1 2.4: an empty pathname is invalid (ENOENT).
3848
 */
3849
static inline int
3850
do_getname32 (const char *filename, char *page)
3851
{
3852
        int retval;
3853
 
3854
        /* 32bit pointer will be always far below TASK_SIZE :)) */
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
 
3865
static char *
3866
getname32 (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
 
3884
struct 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
 
3895
asmlinkage long
3896
sys32_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
 
3938
asmlinkage long
3939
sys32_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
 
3954
asmlinkage long
3955
sys32_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
 
3961
asmlinkage long
3962
sys32_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
 
3968
asmlinkage long
3969
sys32_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
 
3989
asmlinkage long
3990
sys32_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
 
4003
asmlinkage unsigned long
4004
sys32_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
 * Exactly like fs/open.c:sys_open(), except that it doesn't set the O_LARGEFILE flag.
4018
 */
4019
asmlinkage long
4020
sys32_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
                }
4036
out:
4037
                putname(tmp);
4038
        }
4039
        return fd;
4040
 
4041
out_error:
4042
        put_unused_fd(fd);
4043
        fd = error;
4044
        goto out;
4045
}
4046
 
4047
#ifdef  NOTYET  /* UNTESTED FOR IA64 FROM HERE DOWN */
4048
 
4049
struct 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
 
4064
static void *
4065
do_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
 
4081
struct 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
 
4090
static void *
4091
do_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
 
4105
static int
4106
copy_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
 
4133
extern 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
 
4139
asmlinkage long
4140
sys32_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
 
4200
extern asmlinkage long sys_setreuid(uid_t ruid, uid_t euid);
4201
 
4202
asmlinkage 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
 
4211
extern asmlinkage long sys_setresuid(uid_t ruid, uid_t euid, uid_t suid);
4212
 
4213
asmlinkage long
4214
sys32_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
 
4225
extern asmlinkage long sys_setregid(gid_t rgid, gid_t egid);
4226
 
4227
asmlinkage long
4228
sys32_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
 
4237
extern asmlinkage long sys_setresgid(gid_t rgid, gid_t egid, gid_t sgid);
4238
 
4239
asmlinkage long
4240
sys32_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
/* Stuff for NFS server syscalls... */
4252
struct nfsctl_svc32 {
4253
        u16                     svc32_port;
4254
        s32                     svc32_nthreads;
4255
};
4256
 
4257
struct 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
 
4266
struct 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
 
4276
struct nfsctl_uidmap32 {
4277
        u32                     ug32_ident;   /* char * */
4278
        __kernel_uid_t32        ug32_uidbase;
4279
        s32                     ug32_uidlen;
4280
        u32                     ug32_udimap;  /* uid_t * */
4281
        __kernel_uid_t32        ug32_gidbase;
4282
        s32                     ug32_gidlen;
4283
        u32                     ug32_gdimap;  /* gid_t * */
4284
};
4285
 
4286
struct 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
 
4293
struct nfsctl_arg32 {
4294
        s32                     ca32_version;   /* safeguard */
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
 
4312
union nfsctl_res32 {
4313
        struct knfs_fh          cr32_getfh;
4314
        u32                     cr32_debug;
4315
};
4316
 
4317
static int
4318
nfs_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
 
4329
static int
4330
nfs_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
 
4353
static int
4354
nfs_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
 
4378
static int
4379
nfs_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
 
4429
static int
4430
nfs_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
 
4447
static int
4448
nfs_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
 
4459
extern asmlinkage long sys_nfsservctl(int cmd, void *arg, void *resp);
4460
 
4461
int asmlinkage
4462
sys32_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
        /* This one is unimplemented, be we're ready for it. */
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
 
4513
done:
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
/* Handle adjtimex compatability. */
4531
 
4532
struct 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
 
4545
extern int do_adjtimex(struct timex *);
4546
 
4547
asmlinkage long
4548
sys32_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 /* NOTYET */

powered by: WebSVN 2.1.0

© copyright 1999-2024 OpenCores.org, equivalent to Oliscience, all rights reserved. OpenCores®, registered trademark.