linux-old/arch/ia64/ia32/sys_ia32.c
<<
>>
Prefs
   1/*
   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
  79extern asmlinkage long sys_execve (char *, char **, char **, struct pt_regs *);
  80extern asmlinkage long sys_mprotect (unsigned long, size_t, unsigned long);
  81extern asmlinkage long sys_munmap (unsigned long, size_t);
  82extern unsigned long arch_get_unmapped_area (struct file *, unsigned long, unsigned long,
  83                                             unsigned long, unsigned long);
  84
  85/* forward declaration: */
  86asmlinkage long sys32_mprotect (unsigned int, unsigned int, int);
  87asmlinkage 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: */
  94static DECLARE_MUTEX(ia32_mmap_sem);
  95
  96static int
  97nargs (unsigned int arg, char **ap)
  98{
  99        unsigned int addr;
 100        int n, err;
 101
 102        if (!arg)
 103                return 0;
 104
 105        n = 0;
 106        do {
 107                err = get_user(addr, (unsigned int *)A(arg));
 108                if (err)
 109                        return err;
 110                if (ap)
 111                        *ap++ = (char *) A(addr);
 112                arg += sizeof(unsigned int);
 113                n++;
 114        } while (addr);
 115        return n - 1;
 116}
 117
 118asmlinkage long
 119sys32_execve (char *filename, unsigned int argv, unsigned int envp,
 120              int dummy3, int dummy4, int dummy5, int dummy6, int dummy7,
 121              int stack)
 122{
 123        struct pt_regs *regs = (struct pt_regs *)&stack;
 124        unsigned long old_map_base, old_task_size, tssd;
 125        char **av, **ae;
 126        int na, ne, len;
 127        long r;
 128
 129        na = nargs(argv, NULL);
 130        if (na < 0)
 131                return na;
 132        ne = nargs(envp, NULL);
 133        if (ne < 0)
 134                return ne;
 135        len = (na + ne + 2) * sizeof(*av);
 136        av = kmalloc(len, GFP_KERNEL);
 137        if (!av)
 138                return -ENOMEM;
 139
 140        ae = av + na + 1;
 141        av[na] = NULL;
 142        ae[ne] = NULL;
 143
 144        r = nargs(argv, av);
 145        if (r < 0)
 146                goto out;
 147        r = nargs(envp, ae);
 148        if (r < 0)
 149                goto out;
 150
 151        old_map_base  = current->thread.map_base;
 152        old_task_size = current->thread.task_size;
 153        tssd = ia64_get_kr(IA64_KR_TSSD);
 154
 155        /* 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
 176static inline int
 177putstat (struct stat32 *ubuf, struct stat *kbuf)
 178{
 179        int err;
 180
 181        if (clear_user(ubuf, sizeof(*ubuf)))
 182                return 1;
 183
 184        err  = __put_user(kbuf->st_dev, &ubuf->st_dev);
 185        err |= __put_user(kbuf->st_ino, &ubuf->st_ino);
 186        err |= __put_user(kbuf->st_mode, &ubuf->st_mode);
 187        err |= __put_user(kbuf->st_nlink, &ubuf->st_nlink);
 188        err |= __put_user(kbuf->st_uid, &ubuf->st_uid);
 189        err |= __put_user(kbuf->st_gid, &ubuf->st_gid);
 190        err |= __put_user(kbuf->st_rdev, &ubuf->st_rdev);
 191        err |= __put_user(kbuf->st_size, &ubuf->st_size);
 192        err |= __put_user(kbuf->st_atime, &ubuf->st_atime);
 193        err |= __put_user(kbuf->st_mtime, &ubuf->st_mtime);
 194        err |= __put_user(kbuf->st_ctime, &ubuf->st_ctime);
 195        err |= __put_user(kbuf->st_blksize, &ubuf->st_blksize);
 196        err |= __put_user(kbuf->st_blocks, &ubuf->st_blocks);
 197        return err;
 198}
 199
 200extern asmlinkage long sys_newstat (char * filename, struct stat * statbuf);
 201
 202asmlinkage long
 203sys32_newstat (char *filename, struct stat32 *statbuf)
 204{
 205        char *name;
 206        int ret;
 207        struct stat s;
 208        mm_segment_t old_fs = get_fs();
 209
 210        name = getname(filename);
 211        if (IS_ERR(name))
 212                return PTR_ERR(name);
 213        set_fs(KERNEL_DS);
 214        ret = sys_newstat(name, &s);
 215        set_fs(old_fs);
 216        putname(name);
 217        if (putstat(statbuf, &s))
 218                return -EFAULT;
 219        return ret;
 220}
 221
 222extern asmlinkage long sys_newlstat(char * filename, struct stat * statbuf);
 223
 224asmlinkage long
 225sys32_newlstat (char *filename, struct stat32 *statbuf)
 226{
 227        char *name;
 228        mm_segment_t old_fs = get_fs();
 229        struct stat s;
 230        int ret;
 231
 232        name = getname(filename);
 233        if (IS_ERR(name))
 234                return PTR_ERR(name);
 235        set_fs(KERNEL_DS);
 236        ret = sys_newlstat(name, &s);
 237        set_fs(old_fs);
 238        putname(name);
 239        if (putstat(statbuf, &s))
 240                return -EFAULT;
 241        return ret;
 242}
 243
 244extern asmlinkage long sys_newfstat(unsigned int fd, struct stat * statbuf);
 245
 246asmlinkage long
 247sys32_newfstat (unsigned int fd, struct stat32 *statbuf)
 248{
 249        mm_segment_t old_fs = get_fs();
 250        struct stat s;
 251        int ret;
 252
 253        set_fs(KERNEL_DS);
 254        ret = sys_newfstat(fd, &s);
 255        set_fs(old_fs);
 256        if (putstat(statbuf, &s))
 257                return -EFAULT;
 258        return ret;
 259}
 260
 261#if PAGE_SHIFT > IA32_PAGE_SHIFT
 262
 263
 264static int
 265get_page_prot (struct vm_area_struct *vma, unsigned long addr)
 266{
 267        int prot = 0;
 268
 269        if (!vma || vma->vm_start > addr)
 270                return 0;
 271
 272        if (vma->vm_flags & VM_READ)
 273                prot |= PROT_READ;
 274        if (vma->vm_flags & VM_WRITE)
 275                prot |= PROT_WRITE;
 276        if (vma->vm_flags & VM_EXEC)
 277                prot |= PROT_EXEC;
 278        return prot;
 279}
 280
 281/*
 282 * Map a subpage by creating an anonymous page that contains the union of the old page and
 283 * the subpage.
 284 */
 285static unsigned long
 286mmap_subpage (struct file *file, unsigned long start, unsigned long end, int prot, int flags,
 287              loff_t off)
 288{
 289        void *page = NULL;
 290        struct inode *inode;
 291        unsigned long ret = 0;
 292        struct vm_area_struct *vma = find_vma(current->mm, start);
 293        int old_prot = get_page_prot(vma, start);
 294
 295        DBG("mmap_subpage(file=%p,start=0x%lx,end=0x%lx,prot=%x,flags=%x,off=0x%llx)\n",
 296            file, start, end, prot, flags, off);
 297
 298
 299        /* 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
 354static unsigned long
 355emulate_mmap (struct file *file, unsigned long start, unsigned long len, int prot, int flags,
 356              loff_t off)
 357{
 358        unsigned long tmp, end, pend, pstart, ret, is_congruent, fudge = 0;
 359        struct inode *inode;
 360        loff_t poff;
 361
 362        end = start + len;
 363        pstart = PAGE_START(start);
 364        pend = PAGE_ALIGN(end);
 365
 366        if (flags & MAP_FIXED) {
 367                if (start > pstart) {
 368                        if (flags & MAP_SHARED)
 369                                printk(KERN_INFO
 370                                       "%s(%d): emulate_mmap() can't share head (addr=0x%lx)\n",
 371                                       current->comm, current->pid, start);
 372                        ret = mmap_subpage(file, start, min(PAGE_ALIGN(start), end), prot, flags,
 373                                           off);
 374                        if (IS_ERR((void *) ret))
 375                                return ret;
 376                        pstart += PAGE_SIZE;
 377                        if (pstart >= pend)
 378                                return start;   /* 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
 450static inline unsigned int
 451get_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
 463unsigned long
 464ia32_do_mmap (struct file *file, unsigned long addr, unsigned long len, int prot, int flags,
 465              loff_t offset)
 466{
 467        DBG("ia32_do_mmap(file=%p,addr=0x%lx,len=0x%lx,prot=%x,flags=%x,offset=0x%llx)\n",
 468            file, addr, len, prot, flags, offset);
 469
 470        if (file && (!file->f_op || !file->f_op->mmap))
 471                return -ENODEV;
 472
 473        len = IA32_PAGE_ALIGN(len);
 474        if (len == 0)
 475                return addr;
 476
 477        if (len > IA32_PAGE_OFFSET || addr > IA32_PAGE_OFFSET - len)
 478        {
 479                if (flags & MAP_FIXED)
 480                        return -ENOMEM;
 481                else
 482                return -EINVAL;
 483        }
 484
 485        if (OFFSET4K(offset))
 486                return -EINVAL;
 487
 488        prot = get_prot32(prot);
 489
 490#if PAGE_SHIFT > IA32_PAGE_SHIFT
 491        down(&ia32_mmap_sem);
 492        {
 493                addr = emulate_mmap(file, addr, len, prot, flags, offset);
 494        }
 495        up(&ia32_mmap_sem);
 496#else
 497        down_write(&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
 512struct mmap_arg_struct {
 513        unsigned int addr;
 514        unsigned int len;
 515        unsigned int prot;
 516        unsigned int flags;
 517        unsigned int fd;
 518        unsigned int offset;
 519};
 520
 521asmlinkage long
 522sys32_mmap (struct mmap_arg_struct *arg)
 523{
 524        struct mmap_arg_struct a;
 525        struct file *file = NULL;
 526        unsigned long addr;
 527        int flags;
 528
 529        if (copy_from_user(&a, arg, sizeof(a)))
 530                return -EFAULT;
 531
 532        if (OFFSET4K(a.offset))
 533                return -EINVAL;
 534
 535        flags = a.flags;
 536
 537        flags &= ~(MAP_EXECUTABLE | MAP_DENYWRITE);
 538        if (!(flags & MAP_ANONYMOUS)) {
 539                file = fget(a.fd);
 540                if (!file)
 541                        return -EBADF;
 542        }
 543
 544        addr = ia32_do_mmap(file, a.addr, a.len, a.prot, flags, a.offset);
 545
 546        if (file)
 547                fput(file);
 548        return addr;
 549}
 550
 551asmlinkage long
 552sys32_mmap2 (unsigned int addr, unsigned int len, unsigned int prot, unsigned int flags,
 553             unsigned int fd, unsigned int pgoff)
 554{
 555        struct file *file = NULL;
 556        unsigned long retval;
 557
 558        flags &= ~(MAP_EXECUTABLE | MAP_DENYWRITE);
 559        if (!(flags & MAP_ANONYMOUS)) {
 560                file = fget(fd);
 561                if (!file)
 562                        return -EBADF;
 563        }
 564
 565        retval = ia32_do_mmap(file, addr, len, prot, flags,
 566                              (unsigned long) pgoff << IA32_PAGE_SHIFT);
 567
 568        if (file)
 569                fput(file);
 570        return retval;
 571}
 572
 573asmlinkage long
 574sys32_munmap (unsigned int start, unsigned int len)
 575{
 576        unsigned int end = start + len;
 577        long ret;
 578
 579#if PAGE_SHIFT <= IA32_PAGE_SHIFT
 580        ret = sys_munmap(start, end - start);
 581#else
 582        if (start >= end)
 583                return -EINVAL;
 584
 585        start = PAGE_ALIGN(start);
 586        end = PAGE_START(end);
 587
 588        if (start >= end)
 589                return 0;
 590
 591        down(&ia32_mmap_sem);
 592        {
 593                ret = sys_munmap(start, end - start);
 594        }
 595        up(&ia32_mmap_sem);
 596#endif
 597        return ret;
 598}
 599
 600#if PAGE_SHIFT > IA32_PAGE_SHIFT
 601
 602/*
 603 * 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 */
 607static long
 608mprotect_subpage (unsigned long address, int new_prot)
 609{
 610        int old_prot;
 611        struct vm_area_struct *vma;
 612
 613        if (new_prot == PROT_NONE)
 614                return 0;               /* 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
 622asmlinkage long
 623sys32_mprotect (unsigned int start, unsigned int len, int prot)
 624{
 625        unsigned long end = start + len;
 626#if PAGE_SHIFT > IA32_PAGE_SHIFT
 627        long retval = 0;
 628#endif
 629
 630        prot = get_prot32(prot);
 631
 632#if PAGE_SHIFT <= IA32_PAGE_SHIFT
 633        return sys_mprotect(start, end - start, prot);
 634#else
 635        if (OFFSET4K(start))
 636                return -EINVAL;
 637
 638        end = IA32_PAGE_ALIGN(end);
 639        if (end < start)
 640                return -EINVAL;
 641
 642        down(&ia32_mmap_sem);
 643        {
 644                if (PAGE_OFF(start)) {
 645                        /* 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
 671asmlinkage long
 672sys32_pipe (int *fd)
 673{
 674        int retval;
 675        int fds[2];
 676
 677        retval = do_pipe(fds);
 678        if (retval)
 679                goto out;
 680        if (copy_to_user(fd, fds, sizeof(fds)))
 681                retval = -EFAULT;
 682  out:
 683        return retval;
 684}
 685
 686static inline int
 687put_statfs (struct statfs32 *ubuf, struct statfs *kbuf)
 688{
 689        int err;
 690
 691        if (!access_ok(VERIFY_WRITE, ubuf, sizeof(*ubuf)))
 692                return -EFAULT;
 693
 694        err = __put_user(kbuf->f_type, &ubuf->f_type);
 695        err |= __put_user(kbuf->f_bsize, &ubuf->f_bsize);
 696        err |= __put_user(kbuf->f_blocks, &ubuf->f_blocks);
 697        err |= __put_user(kbuf->f_bfree, &ubuf->f_bfree);
 698        err |= __put_user(kbuf->f_bavail, &ubuf->f_bavail);
 699        err |= __put_user(kbuf->f_files, &ubuf->f_files);
 700        err |= __put_user(kbuf->f_ffree, &ubuf->f_ffree);
 701        err |= __put_user(kbuf->f_namelen, &ubuf->f_namelen);
 702        err |= __put_user(kbuf->f_fsid.val[0], &ubuf->f_fsid.val[0]);
 703        err |= __put_user(kbuf->f_fsid.val[1], &ubuf->f_fsid.val[1]);
 704        return err;
 705}
 706
 707extern asmlinkage long sys_statfs(const char * path, struct statfs * buf);
 708
 709asmlinkage long
 710sys32_statfs (const char *path, struct statfs32 *buf)
 711{
 712        const char *name;
 713        int ret;
 714        struct statfs s;
 715        mm_segment_t old_fs = get_fs();
 716
 717        name = getname(path);
 718        if (IS_ERR(name))
 719                return PTR_ERR(name);
 720        set_fs(KERNEL_DS);
 721        ret = sys_statfs(name, &s);
 722        set_fs(old_fs);
 723        putname(name);
 724        if (put_statfs(buf, &s))
 725                return -EFAULT;
 726        return ret;
 727}
 728
 729extern asmlinkage long sys_fstatfs(unsigned int fd, struct statfs * buf);
 730
 731asmlinkage long
 732sys32_fstatfs (unsigned int fd, struct statfs32 *buf)
 733{
 734        int ret;
 735        struct statfs s;
 736        mm_segment_t old_fs = get_fs();
 737
 738        set_fs(KERNEL_DS);
 739        ret = sys_fstatfs(fd, &s);
 740        set_fs(old_fs);
 741        if (put_statfs(buf, &s))
 742                return -EFAULT;
 743        return ret;
 744}
 745
 746struct timeval32
 747{
 748    int tv_sec, tv_usec;
 749};
 750
 751struct itimerval32
 752{
 753    struct timeval32 it_interval;
 754    struct timeval32 it_value;
 755};
 756
 757static inline long
 758get_tv32 (struct timeval *o, struct timeval32 *i)
 759{
 760        return (!access_ok(VERIFY_READ, i, sizeof(*i)) ||
 761                (__get_user(o->tv_sec, &i->tv_sec) | __get_user(o->tv_usec, &i->tv_usec)));
 762}
 763
 764static inline long
 765put_tv32 (struct timeval32 *o, struct timeval *i)
 766{
 767        return (!access_ok(VERIFY_WRITE, o, sizeof(*o)) ||
 768                (__put_user(i->tv_sec, &o->tv_sec) | __put_user(i->tv_usec, &o->tv_usec)));
 769}
 770
 771static inline long
 772get_it32 (struct itimerval *o, struct itimerval32 *i)
 773{
 774        return (!access_ok(VERIFY_READ, i, sizeof(*i)) ||
 775                (__get_user(o->it_interval.tv_sec, &i->it_interval.tv_sec) |
 776                 __get_user(o->it_interval.tv_usec, &i->it_interval.tv_usec) |
 777                 __get_user(o->it_value.tv_sec, &i->it_value.tv_sec) |
 778                 __get_user(o->it_value.tv_usec, &i->it_value.tv_usec)));
 779}
 780
 781static inline long
 782put_it32 (struct itimerval32 *o, struct itimerval *i)
 783{
 784        return (!access_ok(VERIFY_WRITE, o, sizeof(*o)) ||
 785                (__put_user(i->it_interval.tv_sec, &o->it_interval.tv_sec) |
 786                 __put_user(i->it_interval.tv_usec, &o->it_interval.tv_usec) |
 787                 __put_user(i->it_value.tv_sec, &o->it_value.tv_sec) |
 788                 __put_user(i->it_value.tv_usec, &o->it_value.tv_usec)));
 789}
 790
 791extern int do_getitimer (int which, struct itimerval *value);
 792
 793asmlinkage long
 794sys32_getitimer (int which, struct itimerval32 *it)
 795{
 796        struct itimerval kit;
 797        int error;
 798
 799        error = do_getitimer(which, &kit);
 800        if (!error && put_it32(it, &kit))
 801                error = -EFAULT;
 802
 803        return error;
 804}
 805
 806extern int do_setitimer (int which, struct itimerval *, struct itimerval *);
 807
 808asmlinkage long
 809sys32_setitimer (int which, struct itimerval32 *in, struct itimerval32 *out)
 810{
 811        struct itimerval kin, kout;
 812        int error;
 813
 814        if (in) {
 815                if (get_it32(&kin, in))
 816                        return -EFAULT;
 817        } else
 818                memset(&kin, 0, sizeof(kin));
 819
 820        error = do_setitimer(which, &kin, out ? &kout : NULL);
 821        if (error || !out)
 822                return error;
 823        if (put_it32(out, &kout))
 824                return -EFAULT;
 825
 826        return 0;
 827
 828}
 829
 830asmlinkage unsigned long
 831sys32_alarm (unsigned int seconds)
 832{
 833        struct itimerval it_new, it_old;
 834        unsigned int oldalarm;
 835
 836        it_new.it_interval.tv_sec = it_new.it_interval.tv_usec = 0;
 837        it_new.it_value.tv_sec = seconds;
 838        it_new.it_value.tv_usec = 0;
 839        do_setitimer(ITIMER_REAL, &it_new, &it_old);
 840        oldalarm = it_old.it_value.tv_sec;
 841        /* 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
 851struct utimbuf_32 {
 852        int     atime;
 853        int     mtime;
 854};
 855
 856extern asmlinkage long sys_utimes(char * filename, struct timeval * utimes);
 857extern asmlinkage long sys_gettimeofday (struct timeval *tv, struct timezone *tz);
 858
 859asmlinkage long
 860sys32_utime (char *filename, struct utimbuf_32 *times32)
 861{
 862        mm_segment_t old_fs = get_fs();
 863        struct timeval tv[2], *tvp;
 864        long ret;
 865
 866        if (times32) {
 867                if (get_user(tv[0].tv_sec, &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
 882extern struct timezone sys_tz;
 883extern int do_sys_settimeofday (struct timeval *tv, struct timezone *tz);
 884
 885asmlinkage long
 886sys32_gettimeofday (struct timeval32 *tv, struct timezone *tz)
 887{
 888        if (tv) {
 889                struct timeval ktv;
 890                do_gettimeofday(&ktv);
 891                if (put_tv32(tv, &ktv))
 892                        return -EFAULT;
 893        }
 894        if (tz) {
 895                if (copy_to_user(tz, &sys_tz, sizeof(sys_tz)))
 896                        return -EFAULT;
 897        }
 898        return 0;
 899}
 900
 901asmlinkage long
 902sys32_settimeofday (struct timeval32 *tv, struct timezone *tz)
 903{
 904        struct timeval ktv;
 905        struct timezone ktz;
 906
 907        if (tv) {
 908                if (get_tv32(&ktv, tv))
 909                        return -EFAULT;
 910        }
 911        if (tz) {
 912                if (copy_from_user(&ktz, tz, sizeof(ktz)))
 913                        return -EFAULT;
 914        }
 915
 916        return do_sys_settimeofday(tv ? &ktv : NULL, tz ? &ktz : NULL);
 917}
 918
 919struct getdents32_callback {
 920        struct linux32_dirent * current_dir;
 921        struct linux32_dirent * previous;
 922        int count;
 923        int error;
 924};
 925
 926struct readdir32_callback {
 927        struct old_linux32_dirent * dirent;
 928        int count;
 929};
 930
 931static int
 932filldir32 (void *__buf, const char *name, int namlen, loff_t offset, ino_t ino,
 933           unsigned int d_type)
 934{
 935        struct linux32_dirent * dirent;
 936        struct getdents32_callback * buf = (struct getdents32_callback *) __buf;
 937        int reclen = ROUND_UP(NAME_OFFSET(dirent) + namlen + 1, 4);
 938
 939        buf->error = -EINVAL;   /* 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
 960asmlinkage long
 961sys32_getdents (unsigned int fd, struct linux32_dirent *dirent, unsigned int count)
 962{
 963        struct file * file;
 964        struct linux32_dirent * lastdirent;
 965        struct getdents32_callback buf;
 966        int error;
 967
 968        error = -EBADF;
 969        file = fget(fd);
 970        if (!file)
 971                goto out;
 972
 973        buf.current_dir = dirent;
 974        buf.previous = NULL;
 975        buf.count = count;
 976        buf.error = 0;
 977
 978        error = vfs_readdir(file, filldir32, &buf);
 979        if (error < 0)
 980                goto out_putf;
 981        error = buf.error;
 982        lastdirent = buf.previous;
 983        if (lastdirent) {
 984                error = -EINVAL;
 985                if (put_user(file->f_pos, &lastdirent->d_off))
 986                        goto out_putf;
 987                error = count - buf.count;
 988        }
 989
 990out_putf:
 991        fput(file);
 992out:
 993        return error;
 994}
 995
 996static int
 997fillonedir32 (void * __buf, const char * name, int namlen, loff_t offset, ino_t ino,
 998              unsigned int d_type)
 999{
1000        struct readdir32_callback * buf = (struct readdir32_callback *) __buf;
1001        struct old_linux32_dirent * dirent;
1002
1003        if (buf->count)
1004                return -EINVAL;
1005        buf->count++;
1006        dirent = buf->dirent;
1007        if (put_user(ino, &dirent->d_ino)
1008            || put_user(offset, &dirent->d_offset)
1009            || put_user(namlen, &dirent->d_namlen)
1010            || copy_to_user(dirent->d_name, name, namlen)
1011            || put_user(0, dirent->d_name + namlen))
1012                return -EFAULT;
1013        return 0;
1014}
1015
1016asmlinkage long
1017sys32_readdir (unsigned int fd, void *dirent, unsigned int count)
1018{
1019        int error;
1020        struct file * file;
1021        struct readdir32_callback buf;
1022
1023        error = -EBADF;
1024        file = fget(fd);
1025        if (!file)
1026                goto out;
1027
1028        buf.count = 0;
1029        buf.dirent = dirent;
1030
1031        error = vfs_readdir(file, fillonedir32, &buf);
1032        if (error >= 0)
1033                error = buf.count;
1034        fput(file);
1035out:
1036        return error;
1037}
1038
1039/*
1040 * 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
1051asmlinkage long
1052sys32_select (int n, fd_set *inp, fd_set *outp, fd_set *exp, struct timeval32 *tvp32)
1053{
1054        fd_set_bits fds;
1055        char *bits;
1056        long timeout;
1057        int ret, size;
1058
1059        timeout = MAX_SCHEDULE_TIMEOUT;
1060        if (tvp32) {
1061                time_t sec, usec;
1062
1063                ret = -EFAULT;
1064                if (get_user(sec, &tvp32->tv_sec) || get_user(usec, &tvp32->tv_usec))
1065                        goto out_nofds;
1066
1067                ret = -EINVAL;
1068                if (sec < 0 || usec < 0)
1069                        goto out_nofds;
1070
1071                if ((unsigned long) sec < MAX_SELECT_SECONDS) {
1072                        timeout = ROUND_UP_TIME(usec, 1000000/HZ);
1073                        timeout += sec * (unsigned long) HZ;
1074                }
1075        }
1076
1077        ret = -EINVAL;
1078        if (n < 0)
1079                goto out_nofds;
1080
1081        if (n > current->files->max_fdset)
1082                n = current->files->max_fdset;
1083
1084        /*
1085         * 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
1137out:
1138        kfree(bits);
1139out_nofds:
1140        return ret;
1141}
1142
1143struct sel_arg_struct {
1144        unsigned int n;
1145        unsigned int inp;
1146        unsigned int outp;
1147        unsigned int exp;
1148        unsigned int tvp;
1149};
1150
1151asmlinkage long
1152sys32_old_select (struct sel_arg_struct *arg)
1153{
1154        struct sel_arg_struct a;
1155
1156        if (copy_from_user(&a, arg, sizeof(a)))
1157                return -EFAULT;
1158        return sys32_select(a.n, (fd_set *) A(a.inp), (fd_set *) A(a.outp), (fd_set *) A(a.exp),
1159                            (struct timeval32 *) A(a.tvp));
1160}
1161
1162extern asmlinkage long sys_nanosleep (struct timespec *rqtp, struct timespec *rmtp);
1163
1164asmlinkage long
1165sys32_nanosleep (struct timespec32 *rqtp, struct timespec32 *rmtp)
1166{
1167        struct timespec t;
1168        int ret;
1169        mm_segment_t old_fs = get_fs();
1170
1171        if (get_user (t.tv_sec, &rqtp->tv_sec) || get_user (t.tv_nsec, &rqtp->tv_nsec))
1172                return -EFAULT;
1173        set_fs(KERNEL_DS);
1174        ret = sys_nanosleep(&t, rmtp ? &t : NULL);
1175        set_fs(old_fs);
1176        if (rmtp && ret == -EINTR) {
1177                if (put_user(t.tv_sec, &rmtp->tv_sec) || put_user(t.tv_nsec, &rmtp->tv_nsec))
1178                        return -EFAULT;
1179        }
1180        return ret;
1181}
1182
1183struct iovec32 { unsigned int iov_base; int iov_len; };
1184asmlinkage ssize_t sys_readv (unsigned long,const struct iovec *,unsigned long);
1185asmlinkage ssize_t sys_writev (unsigned long,const struct iovec *,unsigned long);
1186
1187static struct iovec *
1188get_iovec32 (struct iovec32 *iov32, struct iovec *iov_buf, u32 count, int type)
1189{
1190        int i;
1191        u32 buf, len;
1192        struct iovec *ivp, *iov;
1193
1194        /* 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
1229asmlinkage long
1230sys32_readv (int fd, struct iovec32 *vector, u32 count)
1231{
1232        struct iovec iovstack[UIO_FASTIOV];
1233        struct iovec *iov;
1234        long ret;
1235        mm_segment_t old_fs = get_fs();
1236
1237        iov = get_iovec32(vector, iovstack, count, VERIFY_WRITE);
1238        if (!iov)
1239                return -EFAULT;
1240        set_fs(KERNEL_DS);
1241        ret = sys_readv(fd, iov, count);
1242        set_fs(old_fs);
1243        if (iov != iovstack)
1244                kfree(iov);
1245        return ret;
1246}
1247
1248asmlinkage long
1249sys32_writev (int fd, struct iovec32 *vector, u32 count)
1250{
1251        struct iovec iovstack[UIO_FASTIOV];
1252        struct iovec *iov;
1253        long ret;
1254        mm_segment_t old_fs = get_fs();
1255
1256        iov = get_iovec32(vector, iovstack, count, VERIFY_READ);
1257        if (!iov)
1258                return -EFAULT;
1259        set_fs(KERNEL_DS);
1260        ret = sys_writev(fd, iov, count);
1261        set_fs(old_fs);
1262        if (iov != iovstack)
1263                kfree(iov);
1264        return ret;
1265}
1266
1267#define RLIM_INFINITY32 0x7fffffff
1268#define RESOURCE32(x) ((x > RLIM_INFINITY32) ? RLIM_INFINITY32 : x)
1269
1270struct rlimit32 {
1271        unsigned int    rlim_cur;
1272        unsigned int    rlim_max;
1273};
1274
1275extern asmlinkage long sys_getrlimit (unsigned int resource, struct rlimit *rlim);
1276
1277asmlinkage long
1278sys32_old_getrlimit (unsigned int resource, struct rlimit32 *rlim)
1279{
1280        mm_segment_t old_fs = get_fs();
1281        struct rlimit r;
1282        int ret;
1283
1284        set_fs(KERNEL_DS);
1285        ret = sys_getrlimit(resource, &r);
1286        set_fs(old_fs);
1287        if (!ret) {
1288                ret = put_user(RESOURCE32(r.rlim_cur), &rlim->rlim_cur);
1289                ret |= put_user(RESOURCE32(r.rlim_max), &rlim->rlim_max);
1290        }
1291        return ret;
1292}
1293
1294asmlinkage long
1295sys32_getrlimit (unsigned int resource, struct rlimit32 *rlim)
1296{
1297        mm_segment_t old_fs = get_fs();
1298        struct rlimit r;
1299        int ret;
1300
1301        set_fs(KERNEL_DS);
1302        ret = sys_getrlimit(resource, &r);
1303        set_fs(old_fs);
1304        if (!ret) {
1305                if (r.rlim_cur >= 0xffffffff)
1306                        r.rlim_cur = 0xffffffff;
1307                if (r.rlim_max >= 0xffffffff)
1308                        r.rlim_max = 0xffffffff;
1309                ret = put_user(r.rlim_cur, &rlim->rlim_cur);
1310                ret |= put_user(r.rlim_max, &rlim->rlim_max);
1311        }
1312        return ret;
1313}
1314
1315extern asmlinkage long sys_setrlimit (unsigned int resource, struct rlimit *rlim);
1316
1317asmlinkage long
1318sys32_setrlimit (unsigned int resource, struct rlimit32 *rlim)
1319{
1320        struct rlimit r;
1321        int ret;
1322        mm_segment_t old_fs = get_fs();
1323
1324        if (resource >= RLIM_NLIMITS)
1325                return -EINVAL;
1326        if (get_user(r.rlim_cur, &rlim->rlim_cur) || get_user(r.rlim_max, &rlim->rlim_max))
1327                return -EFAULT;
1328        if (r.rlim_cur == RLIM_INFINITY32)
1329                r.rlim_cur = RLIM_INFINITY;
1330        if (r.rlim_max == RLIM_INFINITY32)
1331                r.rlim_max = RLIM_INFINITY;
1332        set_fs(KERNEL_DS);
1333        ret = sys_setrlimit(resource, &r);
1334        set_fs(old_fs);
1335        return ret;
1336}
1337
1338/*
1339 *  Declare the IA32 version of the msghdr
1340 */
1341
1342struct 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
1352struct 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
1371static inline struct cmsghdr32 *
1372__cmsg32_nxthdr (void *ctl, __kernel_size_t size, struct cmsghdr32 *cmsg, int cmsg_len)
1373{
1374        struct cmsghdr32 * ptr;
1375
1376        ptr = (struct cmsghdr32 *)(((unsigned char *) cmsg) + CMSG32_ALIGN(cmsg_len));
1377        if ((unsigned long)((char*)(ptr+1) - (char *) ctl) > size)
1378                return NULL;
1379        return ptr;
1380}
1381
1382static inline struct cmsghdr32 *
1383cmsg32_nxthdr (struct msghdr *msg, struct cmsghdr32 *cmsg, int cmsg_len)
1384{
1385        return __cmsg32_nxthdr(msg->msg_control, msg->msg_controllen, cmsg, cmsg_len);
1386}
1387
1388static inline int
1389get_msghdr32 (struct msghdr *mp, struct msghdr32 *mp32)
1390{
1391        int ret;
1392        unsigned int i;
1393
1394        if (!access_ok(VERIFY_READ, mp32, sizeof(*mp32)))
1395                return -EFAULT;
1396        ret = __get_user(i, &mp32->msg_name);
1397        mp->msg_name = (void *)A(i);
1398        ret |= __get_user(mp->msg_namelen, &mp32->msg_namelen);
1399        ret |= __get_user(i, &mp32->msg_iov);
1400        mp->msg_iov = (struct iovec *)A(i);
1401        ret |= __get_user(mp->msg_iovlen, &mp32->msg_iovlen);
1402        ret |= __get_user(i, &mp32->msg_control);
1403        mp->msg_control = (void *)A(i);
1404        ret |= __get_user(mp->msg_controllen, &mp32->msg_controllen);
1405        ret |= __get_user(mp->msg_flags, &mp32->msg_flags);
1406        return ret ? -EFAULT : 0;
1407}
1408
1409/*
1410 * 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 */
1413static int
1414get_cmsghdr32 (struct msghdr *kmsg, unsigned char *stackbuf, struct sock *sk, size_t *bufsize)
1415{
1416        struct cmsghdr *kcmsg, *kcmsg_base;
1417        __kernel_size_t kcmlen, tmp;
1418        __kernel_size_t32 ucmlen;
1419        struct cmsghdr32 *ucmsg;
1420        long err;
1421
1422        kcmlen = 0;
1423        kcmsg_base = kcmsg = (struct cmsghdr *)stackbuf;
1424        ucmsg = CMSG32_FIRSTHDR(kmsg);
1425        while (ucmsg != NULL) {
1426                if (get_user(ucmlen, &ucmsg->cmsg_len))
1427                        return -EFAULT;
1428
1429                /* 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
1483out_free_efault:
1484        if (kcmsg_base != (struct cmsghdr *)stackbuf)
1485                sock_kfree_s(sk, kcmsg_base, kcmlen);
1486        return -EFAULT;
1487}
1488
1489/*
1490 *      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
1500static inline int
1501verify_iovec32 (struct msghdr *m, struct iovec *iov, char *address, int mode)
1502{
1503        int size, err, ct;
1504        struct iovec32 *iov32;
1505
1506        if (m->msg_namelen) {
1507                if (mode == VERIFY_READ) {
1508                        err = move_addr_to_kernel(m->msg_name, m->msg_namelen, address);
1509                        if (err < 0)
1510                                goto out;
1511                }
1512                m->msg_name = address;
1513        } else
1514                m->msg_name = NULL;
1515
1516        err = -EFAULT;
1517        size = m->msg_iovlen * sizeof(struct iovec32);
1518        if (copy_from_user(iov, m->msg_iov, size))
1519                goto out;
1520        m->msg_iov = iov;
1521
1522        err = 0;
1523        iov32 = (struct iovec32 *)iov;
1524        for (ct = m->msg_iovlen; ct-- > 0; ) {
1525                iov[ct].iov_len = (__kernel_size_t)iov32[ct].iov_len;
1526                iov[ct].iov_base = (void *) A(iov32[ct].iov_base);
1527                err += iov[ct].iov_len;
1528        }
1529out:
1530        return err;
1531}
1532
1533static void
1534put_cmsg32(struct msghdr *kmsg, int level, int type, int len, void *data)
1535{
1536        struct cmsghdr32 *cm = (struct cmsghdr32 *) kmsg->msg_control;
1537        struct cmsghdr32 cmhdr;
1538        int cmlen = CMSG32_LEN(len);
1539
1540        if(cm == NULL || kmsg->msg_controllen < sizeof(*cm)) {
1541                kmsg->msg_flags |= MSG_CTRUNC;
1542                return;
1543        }
1544
1545        if(kmsg->msg_controllen < cmlen) {
1546                kmsg->msg_flags |= MSG_CTRUNC;
1547                cmlen = kmsg->msg_controllen;
1548        }
1549        cmhdr.cmsg_level = level;
1550        cmhdr.cmsg_type = type;
1551        cmhdr.cmsg_len = cmlen;
1552
1553        if(copy_to_user(cm, &cmhdr, sizeof cmhdr))
1554                return;
1555        if(copy_to_user(CMSG32_DATA(cm), data,
1556                        cmlen - sizeof(struct cmsghdr32)))
1557                return;
1558        cmlen = CMSG32_SPACE(len);
1559        kmsg->msg_control += cmlen;
1560        kmsg->msg_controllen -= cmlen;
1561}
1562
1563static void
1564scm_detach_fds32 (struct msghdr *kmsg, struct scm_cookie *scm)
1565{
1566        struct cmsghdr32 *cm = (struct cmsghdr32 *) kmsg->msg_control;
1567        int fdmax = (kmsg->msg_controllen - sizeof(struct cmsghdr32))
1568                / sizeof(int);
1569        int fdnum = scm->fp->count;
1570        struct file **fp = scm->fp->fp;
1571        int *cmfptr;
1572        int err = 0, i;
1573
1574        if (fdnum < fdmax)
1575                fdmax = fdnum;
1576
1577        for (i = 0, cmfptr = (int *) CMSG32_DATA(cm);
1578             i < fdmax;
1579             i++, cmfptr++) {
1580                int new_fd;
1581                err = get_unused_fd();
1582                if (err < 0)
1583                        break;
1584                new_fd = err;
1585                err = put_user(new_fd, cmfptr);
1586                if (err) {
1587                        put_unused_fd(new_fd);
1588                        break;
1589                }
1590                /* 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 */
1647static void
1648cmsg32_recvmsg_fixup (struct msghdr *kmsg, unsigned long orig_cmsg_uptr)
1649{
1650        unsigned char *workbuf, *wp;
1651        unsigned long bufsz, space_avail;
1652        struct cmsghdr *ucmsg;
1653        long err;
1654
1655        bufsz = ((unsigned long)kmsg->msg_control) - orig_cmsg_uptr;
1656        space_avail = kmsg->msg_controllen + bufsz;
1657        wp = workbuf = kmalloc(bufsz, GFP_KERNEL);
1658        if (workbuf == NULL)
1659                goto fail;
1660
1661        /* 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
1713static inline void
1714sockfd_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
1725extern struct socket *sockfd_lookup (int fd, int *err);
1726
1727/*
1728 *      BSD sendmsg interface
1729 */
1730
1731int
1732sys32_sendmsg (int fd, struct msghdr32 *msg, unsigned flags)
1733{
1734        struct socket *sock;
1735        char address[MAX_SOCK_ADDR];
1736        struct iovec iovstack[UIO_FASTIOV], *iov = iovstack;
1737        unsigned char ctl[sizeof(struct cmsghdr) + 20]; /* 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);
1790out_freeiov:
1791        if (iov != iovstack)
1792                sock_kfree_s(sock->sk, iov, iov_size);
1793out_put:
1794        sockfd_put(sock);
1795out:
1796        return err;
1797}
1798
1799/*
1800 *      BSD recvmsg interface
1801 */
1802
1803int
1804sys32_recvmsg (int fd, struct msghdr32 *msg, unsigned int flags)
1805{
1806        struct socket *sock;
1807        struct iovec iovstack[UIO_FASTIOV];
1808        struct iovec *iov=iovstack;
1809        struct msghdr msg_sys;
1810        unsigned long cmsg_ptr;
1811        int err, iov_size, total_len, len;
1812        struct scm_cookie scm;
1813
1814        /* 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))
1921static const unsigned char nas[18]={AL(0),AL(3),AL(3),AL(3),AL(2),AL(3),
1922                                    AL(3),AL(3),AL(4),AL(4),AL(4),AL(6),
1923                                    AL(6),AL(2),AL(5),AL(5),AL(3),AL(3)};
1924#undef AL
1925
1926extern asmlinkage long sys_bind(int fd, struct sockaddr *umyaddr, int addrlen);
1927extern asmlinkage long sys_connect(int fd, struct sockaddr *uservaddr,
1928                                  int addrlen);
1929extern asmlinkage long sys_accept(int fd, struct sockaddr *upeer_sockaddr,
1930                                 int *upeer_addrlen);
1931extern asmlinkage long sys_getsockname(int fd, struct sockaddr *usockaddr,
1932                                      int *usockaddr_len);
1933extern asmlinkage long sys_getpeername(int fd, struct sockaddr *usockaddr,
1934                                      int *usockaddr_len);
1935extern asmlinkage long sys_send(int fd, void *buff, size_t len, unsigned flags);
1936extern asmlinkage long sys_sendto(int fd, u32 buff, __kernel_size_t32 len,
1937                                   unsigned flags, u32 addr, int addr_len);
1938extern asmlinkage long sys_recv(int fd, void *ubuf, size_t size, unsigned flags);
1939extern asmlinkage long sys_recvfrom(int fd, u32 ubuf, __kernel_size_t32 size,
1940                                     unsigned flags, u32 addr, u32 addr_len);
1941extern asmlinkage long sys_setsockopt(int fd, int level, int optname,
1942                                     char *optval, int optlen);
1943extern asmlinkage long sys_getsockopt(int fd, int level, int optname,
1944                                       u32 optval, u32 optlen);
1945
1946extern asmlinkage long sys_socket(int family, int type, int protocol);
1947extern asmlinkage long sys_socketpair(int family, int type, int protocol,
1948                                     int usockvec[2]);
1949extern asmlinkage long sys_shutdown(int fd, int how);
1950extern asmlinkage long sys_listen(int fd, int backlog);
1951
1952asmlinkage long
1953sys32_socketcall (int call, u32 *args)
1954{
1955        int ret;
1956        u32 a[6];
1957        u32 a0,a1;
1958
1959        if (call<SYS_SOCKET||call>SYS_RECVMSG)
1960                return -EINVAL;
1961        if (copy_from_user(a, args, nas[call]))
1962                return -EFAULT;
1963        a0=a[0];
1964        a1=a[1];
1965
1966        switch(call)
1967        {
1968                case SYS_SOCKET:
1969                        ret = sys_socket(a0, a1, a[2]);
1970                        break;
1971                case SYS_BIND:
1972                        ret = sys_bind(a0, (struct sockaddr *)A(a1), a[2]);
1973                        break;
1974                case SYS_CONNECT:
1975                        ret = sys_connect(a0, (struct sockaddr *)A(a1), a[2]);
1976                        break;
1977                case SYS_LISTEN:
1978                        ret = sys_listen(a0, a1);
1979                        break;
1980                case SYS_ACCEPT:
1981                        ret = sys_accept(a0, (struct sockaddr *)A(a1), (int *)A(a[2]));
1982                        break;
1983                case SYS_GETSOCKNAME:
1984                        ret = sys_getsockname(a0, (struct sockaddr *)A(a1), (int *)A(a[2]));
1985                        break;
1986                case SYS_GETPEERNAME:
1987                        ret = sys_getpeername(a0, (struct sockaddr *)A(a1), (int *)A(a[2]));
1988                        break;
1989                case SYS_SOCKETPAIR:
1990                        ret = sys_socketpair(a0, a1, a[2], (int *)A(a[3]));
1991                        break;
1992                case SYS_SEND:
1993                        ret = sys_send(a0, (void *)A(a1), a[2], a[3]);
1994                        break;
1995                case SYS_SENDTO:
1996                        ret = sys_sendto(a0, a1, a[2], a[3], a[4], a[5]);
1997                        break;
1998                case SYS_RECV:
1999                        ret = sys_recv(a0, (void *)A(a1), a[2], a[3]);
2000                        break;
2001                case SYS_RECVFROM:
2002                        ret = sys_recvfrom(a0, a1, a[2], a[3], a[4], a[5]);
2003                        break;
2004                case SYS_SHUTDOWN:
2005                        ret = sys_shutdown(a0,a1);
2006                        break;
2007                case SYS_SETSOCKOPT:
2008                        ret = sys_setsockopt(a0, a1, a[2], (char *)A(a[3]),
2009                                              a[4]);
2010                        break;
2011                case SYS_GETSOCKOPT:
2012                        ret = sys_getsockopt(a0, a1, a[2], a[3], a[4]);
2013                        break;
2014                case SYS_SENDMSG:
2015                        ret = sys32_sendmsg(a0, (struct msghdr32 *) A(a1), a[2]);
2016                        break;
2017                case SYS_RECVMSG:
2018                        ret = sys32_recvmsg(a0, (struct msghdr32 *) A(a1), a[2]);
2019                        break;
2020                default:
2021                        ret = EINVAL;
2022                        break;
2023        }
2024        return ret;
2025}
2026
2027/*
2028 * sys32_ipc() is the de-multiplexer for the SysV IPC calls in 32bit emulation..
2029 *
2030 * This is really horribly ugly.
2031 */
2032
2033struct msgbuf32 { s32 mtype; char mtext[1]; };
2034
2035struct ipc_perm32 {
2036        key_t key;
2037        __kernel_uid_t32 uid;
2038        __kernel_gid_t32 gid;
2039        __kernel_uid_t32 cuid;
2040        __kernel_gid_t32 cgid;
2041        __kernel_mode_t32 mode;
2042        unsigned short seq;
2043};
2044
2045struct ipc64_perm32 {
2046        key_t key;
2047        __kernel_uid32_t32 uid;
2048        __kernel_gid32_t32 gid;
2049        __kernel_uid32_t32 cuid;
2050        __kernel_gid32_t32 cgid;
2051        __kernel_mode_t32 mode;
2052        unsigned short __pad1;
2053        unsigned short seq;
2054        unsigned short __pad2;
2055        unsigned int unused1;
2056        unsigned int unused2;
2057};
2058
2059struct semid_ds32 {
2060        struct ipc_perm32 sem_perm;               /* 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
2070struct semid64_ds32 {
2071        struct ipc64_perm32 sem_perm;
2072        __kernel_time_t32 sem_otime;
2073        unsigned int __unused1;
2074        __kernel_time_t32 sem_ctime;
2075        unsigned int __unused2;
2076        unsigned int sem_nsems;
2077        unsigned int __unused3;
2078        unsigned int __unused4;
2079};
2080
2081struct msqid_ds32 {
2082        struct ipc_perm32 msg_perm;
2083        u32 msg_first;
2084        u32 msg_last;
2085        __kernel_time_t32 msg_stime;
2086        __kernel_time_t32 msg_rtime;
2087        __kernel_time_t32 msg_ctime;
2088        u32 wwait;
2089        u32 rwait;
2090        unsigned short msg_cbytes;
2091        unsigned short msg_qnum;
2092        unsigned short msg_qbytes;
2093        __kernel_ipc_pid_t32 msg_lspid;
2094        __kernel_ipc_pid_t32 msg_lrpid;
2095};
2096
2097struct msqid64_ds32 {
2098        struct ipc64_perm32 msg_perm;
2099        __kernel_time_t32 msg_stime;
2100        unsigned int __unused1;
2101        __kernel_time_t32 msg_rtime;
2102        unsigned int __unused2;
2103        __kernel_time_t32 msg_ctime;
2104        unsigned int __unused3;
2105        unsigned int msg_cbytes;
2106        unsigned int msg_qnum;
2107        unsigned int msg_qbytes;
2108        __kernel_pid_t32 msg_lspid;
2109        __kernel_pid_t32 msg_lrpid;
2110        unsigned int __unused4;
2111        unsigned int __unused5;
2112};
2113
2114struct shmid_ds32 {
2115        struct ipc_perm32 shm_perm;
2116        int shm_segsz;
2117        __kernel_time_t32 shm_atime;
2118        __kernel_time_t32 shm_dtime;
2119        __kernel_time_t32 shm_ctime;
2120        __kernel_ipc_pid_t32 shm_cpid;
2121        __kernel_ipc_pid_t32 shm_lpid;
2122        unsigned short shm_nattch;
2123};
2124
2125struct shmid64_ds32 {
2126        struct ipc64_perm32 shm_perm;
2127        __kernel_size_t32 shm_segsz;
2128        __kernel_time_t32 shm_atime;
2129        unsigned int __unused1;
2130        __kernel_time_t32 shm_dtime;
2131        unsigned int __unused2;
2132        __kernel_time_t32 shm_ctime;
2133        unsigned int __unused3;
2134        __kernel_pid_t32 shm_cpid;
2135        __kernel_pid_t32 shm_lpid;
2136        unsigned int shm_nattch;
2137        unsigned int __unused4;
2138        unsigned int __unused5;
2139};
2140
2141struct shminfo64_32 {
2142        unsigned int shmmax;
2143        unsigned int shmmin;
2144        unsigned int shmmni;
2145        unsigned int shmseg;
2146        unsigned int shmall;
2147        unsigned int __unused1;
2148        unsigned int __unused2;
2149        unsigned int __unused3;
2150        unsigned int __unused4;
2151};
2152
2153struct shm_info32 {
2154        int used_ids;
2155        u32 shm_tot, shm_rss, shm_swp;
2156        u32 swap_attempts, swap_successes;
2157};
2158
2159struct ipc_kludge {
2160        u32 msgp;
2161        s32 msgtyp;
2162};
2163
2164#define SEMOP            1
2165#define SEMGET           2
2166#define SEMCTL           3
2167#define MSGSND          11
2168#define MSGRCV          12
2169#define MSGGET          13
2170#define MSGCTL          14
2171#define SHMAT           21
2172#define SHMDT           22
2173#define SHMGET          23
2174#define SHMCTL          24
2175
2176#define IPCOP_MASK(__x) (1UL << (__x))
2177
2178static int
2179ipc_parse_version32 (int *cmd)
2180{
2181        if (*cmd & IPC_64) {
2182                *cmd ^= IPC_64;
2183                return IPC_64;
2184        } else {
2185                return IPC_OLD;
2186        }
2187}
2188
2189static int
2190semctl32 (int first, int second, int third, void *uptr)
2191{
2192        union semun fourth;
2193        u32 pad;
2194        int err = 0, err2;
2195        struct semid64_ds s;
2196        mm_segment_t old_fs;
2197        int version = ipc_parse_version32(&third);
2198
2199        if (!uptr)
2200                return -EINVAL;
2201        if (get_user(pad, (u32 *)uptr))
2202                return -EFAULT;
2203        if (third == SETVAL)
2204                fourth.val = (int)pad;
2205        else
2206                fourth.__pad = (void *)A(pad);
2207        switch (third) {
2208              default:
2209                err = -EINVAL;
2210                break;
2211
2212              case IPC_INFO:
2213              case IPC_RMID:
2214              case IPC_SET:
2215              case SEM_INFO:
2216              case GETVAL:
2217              case GETPID:
2218              case GETNCNT:
2219              case GETZCNT:
2220              case GETALL:
2221              case SETVAL:
2222              case SETALL:
2223                err = sys_semctl(first, second, third, fourth);
2224                break;
2225
2226              case IPC_STAT:
2227              case SEM_STAT:
2228                fourth.__pad = &s;
2229                old_fs = get_fs();
2230                set_fs(KERNEL_DS);
2231                err = sys_semctl(first, second, third, fourth);
2232                set_fs(old_fs);
2233
2234                if (version == IPC_64) {
2235                        struct semid64_ds32 *usp64 = (struct semid64_ds32 *) A(pad);
2236
2237                        if (!access_ok(VERIFY_WRITE, usp64, sizeof(*usp64))) {
2238                                err = -EFAULT;
2239                                break;
2240                        }
2241                        err2 = __put_user(s.sem_perm.key, &usp64->sem_perm.key);
2242                        err2 |= __put_user(s.sem_perm.uid, &usp64->sem_perm.uid);
2243                        err2 |= __put_user(s.sem_perm.gid, &usp64->sem_perm.gid);
2244                        err2 |= __put_user(s.sem_perm.cuid, &usp64->sem_perm.cuid);
2245                        err2 |= __put_user(s.sem_perm.cgid, &usp64->sem_perm.cgid);
2246                        err2 |= __put_user(s.sem_perm.mode, &usp64->sem_perm.mode);
2247                        err2 |= __put_user(s.sem_perm.seq, &usp64->sem_perm.seq);
2248                        err2 |= __put_user(s.sem_otime, &usp64->sem_otime);
2249                        err2 |= __put_user(s.sem_ctime, &usp64->sem_ctime);
2250                        err2 |= __put_user(s.sem_nsems, &usp64->sem_nsems);
2251                } else {
2252                        struct semid_ds32 *usp32 = (struct semid_ds32 *) A(pad);
2253
2254                        if (!access_ok(VERIFY_WRITE, usp32, sizeof(*usp32))) {
2255                                err = -EFAULT;
2256                                break;
2257                        }
2258                        err2 = __put_user(s.sem_perm.key, &usp32->sem_perm.key);
2259                        err2 |= __put_user(s.sem_perm.uid, &usp32->sem_perm.uid);
2260                        err2 |= __put_user(s.sem_perm.gid, &usp32->sem_perm.gid);
2261                        err2 |= __put_user(s.sem_perm.cuid, &usp32->sem_perm.cuid);
2262                        err2 |= __put_user(s.sem_perm.cgid, &usp32->sem_perm.cgid);
2263                        err2 |= __put_user(s.sem_perm.mode, &usp32->sem_perm.mode);
2264                        err2 |= __put_user(s.sem_perm.seq, &usp32->sem_perm.seq);
2265                        err2 |= __put_user(s.sem_otime, &usp32->sem_otime);
2266                        err2 |= __put_user(s.sem_ctime, &usp32->sem_ctime);
2267                        err2 |= __put_user(s.sem_nsems, &usp32->sem_nsems);
2268                }
2269                if (err2)
2270                    err = -EFAULT;
2271                break;
2272        }
2273        return err;
2274}
2275
2276static int
2277do_sys32_msgsnd (int first, int second, int third, void *uptr)
2278{
2279        struct msgbuf *p = kmalloc(second + sizeof(struct msgbuf), GFP_USER);
2280        struct msgbuf32 *up = (struct msgbuf32 *)uptr;
2281        mm_segment_t old_fs;
2282        int err;
2283
2284        if (!p)
2285                return -ENOMEM;
2286        err = get_user(p->mtype, &up->mtype);
2287        err |= copy_from_user(p->mtext, &up->mtext, second);
2288        if (err)
2289                goto out;
2290        old_fs = get_fs();
2291        set_fs(KERNEL_DS);
2292        err = sys_msgsnd(first, p, second, third);
2293        set_fs(old_fs);
2294  out:
2295        kfree(p);
2296        return err;
2297}
2298
2299static int
2300do_sys32_msgrcv (int first, int second, int msgtyp, int third, int version, void *uptr)
2301{
2302        struct msgbuf32 *up;
2303        struct msgbuf *p;
2304        mm_segment_t old_fs;
2305        int err;
2306
2307        if (!version) {
2308                struct ipc_kludge *uipck = (struct ipc_kludge *)uptr;
2309                struct ipc_kludge ipck;
2310
2311                err = -EINVAL;
2312                if (!uptr)
2313                        goto out;
2314                err = -EFAULT;
2315                if (copy_from_user(&ipck, uipck, sizeof(struct ipc_kludge)))
2316                        goto out;
2317                uptr = (void *)A(ipck.msgp);
2318                msgtyp = ipck.msgtyp;
2319        }
2320        err = -ENOMEM;
2321        p = kmalloc(second + sizeof(struct msgbuf), GFP_USER);
2322        if (!p)
2323                goto out;
2324        old_fs = get_fs();
2325        set_fs(KERNEL_DS);
2326        err = sys_msgrcv(first, p, second, msgtyp, third);
2327        set_fs(old_fs);
2328        if (err < 0)
2329                goto free_then_out;
2330        up = (struct msgbuf32 *)uptr;
2331        if (put_user(p->mtype, &up->mtype) || copy_to_user(&up->mtext, p->mtext, err))
2332                err = -EFAULT;
2333free_then_out:
2334        kfree(p);
2335out:
2336        return err;
2337}
2338
2339static int
2340msgctl32 (int first, int second, void *uptr)
2341{
2342        int err = -EINVAL, err2;
2343        struct msqid_ds m;
2344        struct msqid64_ds m64;
2345        struct msqid_ds32 *up32 = (struct msqid_ds32 *)uptr;
2346        struct msqid64_ds32 *up64 = (struct msqid64_ds32 *)uptr;
2347        mm_segment_t old_fs;
2348        int version = ipc_parse_version32(&second);
2349
2350        switch (second) {
2351              case IPC_INFO:
2352              case IPC_RMID:
2353              case MSG_INFO:
2354                err = sys_msgctl(first, second, (struct msqid_ds *)uptr);
2355                break;
2356
2357              case IPC_SET:
2358                if (version == IPC_64) {
2359                        err = get_user(m64.msg_perm.uid, &up64->msg_perm.uid);
2360                        err |= get_user(m64.msg_perm.gid, &up64->msg_perm.gid);
2361                        err |= get_user(m64.msg_perm.mode, &up64->msg_perm.mode);
2362                        err |= get_user(m64.msg_qbytes, &up64->msg_qbytes);
2363                } else {
2364                        err = get_user(m64.msg_perm.uid, &up32->msg_perm.uid);
2365                        err |= get_user(m64.msg_perm.gid, &up32->msg_perm.gid);
2366                        err |= get_user(m64.msg_perm.mode, &up32->msg_perm.mode);
2367                        err |= get_user(m64.msg_qbytes, &up32->msg_qbytes);
2368                }
2369                if (err)
2370                        break;
2371                old_fs = get_fs();
2372                set_fs(KERNEL_DS);
2373                err = sys_msgctl(first, second, &m64);
2374                set_fs(old_fs);
2375                break;
2376
2377              case IPC_STAT:
2378              case MSG_STAT:
2379                old_fs = get_fs();
2380                set_fs(KERNEL_DS);
2381                err = sys_msgctl(first, second, (void *) &m64);
2382                set_fs(old_fs);
2383
2384                if (version == IPC_64) {
2385                        if (!access_ok(VERIFY_WRITE, up64, sizeof(*up64))) {
2386                                err = -EFAULT;
2387                                break;
2388                        }
2389                        err2 = __put_user(m64.msg_perm.key, &up64->msg_perm.key);
2390                        err2 |= __put_user(m64.msg_perm.uid, &up64->msg_perm.uid);
2391                        err2 |= __put_user(m64.msg_perm.gid, &up64->msg_perm.gid);
2392                        err2 |= __put_user(m64.msg_perm.cuid, &up64->msg_perm.cuid);
2393                        err2 |= __put_user(m64.msg_perm.cgid, &up64->msg_perm.cgid);
2394                        err2 |= __put_user(m64.msg_perm.mode, &up64->msg_perm.mode);
2395                        err2 |= __put_user(m64.msg_perm.seq, &up64->msg_perm.seq);
2396                        err2 |= __put_user(m64.msg_stime, &up64->msg_stime);
2397                        err2 |= __put_user(m64.msg_rtime, &up64->msg_rtime);
2398                        err2 |= __put_user(m64.msg_ctime, &up64->msg_ctime);
2399                        err2 |= __put_user(m64.msg_cbytes, &up64->msg_cbytes);
2400                        err2 |= __put_user(m64.msg_qnum, &up64->msg_qnum);
2401                        err2 |= __put_user(m64.msg_qbytes, &up64->msg_qbytes);
2402                        err2 |= __put_user(m64.msg_lspid, &up64->msg_lspid);
2403                        err2 |= __put_user(m64.msg_lrpid, &up64->msg_lrpid);
2404                        if (err2)
2405                                err = -EFAULT;
2406                } else {
2407                        if (!access_ok(VERIFY_WRITE, up32, sizeof(*up32))) {
2408                                err = -EFAULT;
2409                                break;
2410                        }
2411                        err2 = __put_user(m64.msg_perm.key, &up32->msg_perm.key);
2412                        err2 |= __put_user(m64.msg_perm.uid, &up32->msg_perm.uid);
2413                        err2 |= __put_user(m64.msg_perm.gid, &up32->msg_perm.gid);
2414                        err2 |= __put_user(m64.msg_perm.cuid, &up32->msg_perm.cuid);
2415                        err2 |= __put_user(m64.msg_perm.cgid, &up32->msg_perm.cgid);
2416                        err2 |= __put_user(m64.msg_perm.mode, &up32->msg_perm.mode);
2417                        err2 |= __put_user(m64.msg_perm.seq, &up32->msg_perm.seq);
2418                        err2 |= __put_user(m64.msg_stime, &up32->msg_stime);
2419                        err2 |= __put_user(m64.msg_rtime, &up32->msg_rtime);
2420                        err2 |= __put_user(m64.msg_ctime, &up32->msg_ctime);
2421                        err2 |= __put_user(m64.msg_cbytes, &up32->msg_cbytes);
2422                        err2 |= __put_user(m64.msg_qnum, &up32->msg_qnum);
2423                        err2 |= __put_user(m64.msg_qbytes, &up32->msg_qbytes);
2424                        err2 |= __put_user(m64.msg_lspid, &up32->msg_lspid);
2425                        err2 |= __put_user(m64.msg_lrpid, &up32->msg_lrpid);
2426                        if (err2)
2427                                err = -EFAULT;
2428                }
2429                break;
2430        }
2431        return err;
2432}
2433
2434static int
2435shmat32 (int first, int second, int third, int version, void *uptr)
2436{
2437        unsigned long raddr;
2438        u32 *uaddr = (u32 *)A((u32)third);
2439        int err;
2440
2441        if (version == 1)
2442                return -EINVAL; /* 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
2449static int
2450shmctl32 (int first, int second, void *uptr)
2451{
2452        int err = -EFAULT, err2;
2453
2454        struct shmid64_ds s64;
2455        struct shmid_ds32 *up32 = (struct shmid_ds32 *)uptr;
2456        struct shmid64_ds32 *up64 = (struct shmid64_ds32 *)uptr;
2457        mm_segment_t old_fs;
2458        struct shm_info32 *uip = (struct shm_info32 *)uptr;
2459        struct shm_info si;
2460        int version = ipc_parse_version32(&second);
2461        struct shminfo64 smi;
2462        struct shminfo *usi32 = (struct shminfo *) uptr;
2463        struct shminfo64_32 *usi64 = (struct shminfo64_32 *) uptr;
2464
2465        switch (second) {
2466              case IPC_INFO:
2467                old_fs = get_fs();
2468                set_fs(KERNEL_DS);
2469                err = sys_shmctl(first, second, (struct shmid_ds *)&smi);
2470                set_fs(old_fs);
2471
2472                if (version == IPC_64) {
2473                        if (!access_ok(VERIFY_WRITE, usi64, sizeof(*usi64))) {
2474                                err = -EFAULT;
2475                                break;
2476                        }
2477                        err2 = __put_user(smi.shmmax, &usi64->shmmax);
2478                        err2 |= __put_user(smi.shmmin, &usi64->shmmin);
2479                        err2 |= __put_user(smi.shmmni, &usi64->shmmni);
2480                        err2 |= __put_user(smi.shmseg, &usi64->shmseg);
2481                        err2 |= __put_user(smi.shmall, &usi64->shmall);
2482                } else {
2483                        if (!access_ok(VERIFY_WRITE, usi32, sizeof(*usi32))) {
2484                                err = -EFAULT;
2485                                break;
2486                        }
2487                        err2 = __put_user(smi.shmmax, &usi32->shmmax);
2488                        err2 |= __put_user(smi.shmmin, &usi32->shmmin);
2489                        err2 |= __put_user(smi.shmmni, &usi32->shmmni);
2490                        err2 |= __put_user(smi.shmseg, &usi32->shmseg);
2491                        err2 |= __put_user(smi.shmall, &usi32->shmall);
2492                }
2493                if (err2)
2494                        err = -EFAULT;
2495                break;
2496
2497              case IPC_RMID:
2498              case SHM_LOCK:
2499              case SHM_UNLOCK:
2500                err = sys_shmctl(first, second, (struct shmid_ds *)uptr);
2501                break;
2502
2503              case IPC_SET:
2504                if (version == IPC_64) {
2505                        err = get_user(s64.shm_perm.uid, &up64->shm_perm.uid);
2506                        err |= get_user(s64.shm_perm.gid, &up64->shm_perm.gid);
2507                        err |= get_user(s64.shm_perm.mode, &up64->shm_perm.mode);
2508                } else {
2509                        err = get_user(s64.shm_perm.uid, &up32->shm_perm.uid);
2510                        err |= get_user(s64.shm_perm.gid, &up32->shm_perm.gid);
2511                        err |= get_user(s64.shm_perm.mode, &up32->shm_perm.mode);
2512                }
2513                if (err)
2514                        break;
2515                old_fs = get_fs();
2516                set_fs(KERNEL_DS);
2517                err = sys_shmctl(first, second, &s64);
2518                set_fs(old_fs);
2519                break;
2520
2521              case IPC_STAT:
2522              case SHM_STAT:
2523                old_fs = get_fs();
2524                set_fs(KERNEL_DS);
2525                err = sys_shmctl(first, second, (void *) &s64);
2526                set_fs(old_fs);
2527                if (err < 0)
2528                        break;
2529                if (version == IPC_64) {
2530                        if (!access_ok(VERIFY_WRITE, up64, sizeof(*up64))) {
2531                                err = -EFAULT;
2532                                break;
2533                        }
2534                        err2 = __put_user(s64.shm_perm.key, &up64->shm_perm.key);
2535                        err2 |= __put_user(s64.shm_perm.uid, &up64->shm_perm.uid);
2536                        err2 |= __put_user(s64.shm_perm.gid, &up64->shm_perm.gid);
2537                        err2 |= __put_user(s64.shm_perm.cuid, &up64->shm_perm.cuid);
2538                        err2 |= __put_user(s64.shm_perm.cgid, &up64->shm_perm.cgid);
2539                        err2 |= __put_user(s64.shm_perm.mode, &up64->shm_perm.mode);
2540                        err2 |= __put_user(s64.shm_perm.seq, &up64->shm_perm.seq);
2541                        err2 |= __put_user(s64.shm_atime, &up64->shm_atime);
2542                        err2 |= __put_user(s64.shm_dtime, &up64->shm_dtime);
2543                        err2 |= __put_user(s64.shm_ctime, &up64->shm_ctime);
2544                        err2 |= __put_user(s64.shm_segsz, &up64->shm_segsz);
2545                        err2 |= __put_user(s64.shm_nattch, &up64->shm_nattch);
2546                        err2 |= __put_user(s64.shm_cpid, &up64->shm_cpid);
2547                        err2 |= __put_user(s64.shm_lpid, &up64->shm_lpid);
2548                } else {
2549                        if (!access_ok(VERIFY_WRITE, up32, sizeof(*up32))) {
2550                                err = -EFAULT;
2551                                break;
2552                        }
2553                        err2 = __put_user(s64.shm_perm.key, &up32->shm_perm.key);
2554                        err2 |= __put_user(s64.shm_perm.uid, &up32->shm_perm.uid);
2555                        err2 |= __put_user(s64.shm_perm.gid, &up32->shm_perm.gid);
2556                        err2 |= __put_user(s64.shm_perm.cuid, &up32->shm_perm.cuid);
2557                        err2 |= __put_user(s64.shm_perm.cgid, &up32->shm_perm.cgid);
2558                        err2 |= __put_user(s64.shm_perm.mode, &up32->shm_perm.mode);
2559                        err2 |= __put_user(s64.shm_perm.seq, &up32->shm_perm.seq);
2560                        err2 |= __put_user(s64.shm_atime, &up32->shm_atime);
2561                        err2 |= __put_user(s64.shm_dtime, &up32->shm_dtime);
2562                        err2 |= __put_user(s64.shm_ctime, &up32->shm_ctime);
2563                        err2 |= __put_user(s64.shm_segsz, &up32->shm_segsz);
2564                        err2 |= __put_user(s64.shm_nattch, &up32->shm_nattch);
2565                        err2 |= __put_user(s64.shm_cpid, &up32->shm_cpid);
2566                        err2 |= __put_user(s64.shm_lpid, &up32->shm_lpid);
2567                }
2568                if (err2)
2569                        err = -EFAULT;
2570                break;
2571
2572              case SHM_INFO:
2573                old_fs = get_fs();
2574                set_fs(KERNEL_DS);
2575                err = sys_shmctl(first, second, (void *)&si);
2576                set_fs(old_fs);
2577                if (err < 0)
2578                        break;
2579
2580                if (!access_ok(VERIFY_WRITE, uip, sizeof(*uip))) {
2581                        err = -EFAULT;
2582                        break;
2583                }
2584                err2 = __put_user(si.used_ids, &uip->used_ids);
2585                err2 |= __put_user(si.shm_tot, &uip->shm_tot);
2586                err2 |= __put_user(si.shm_rss, &uip->shm_rss);
2587                err2 |= __put_user(si.shm_swp, &uip->shm_swp);
2588                err2 |= __put_user(si.swap_attempts, &uip->swap_attempts);
2589                err2 |= __put_user(si.swap_successes, &uip->swap_successes);
2590                if (err2)
2591                        err = -EFAULT;
2592                break;
2593
2594        }
2595        return err;
2596}
2597
2598asmlinkage long
2599sys32_ipc (u32 call, int first, int second, int third, u32 ptr, u32 fifth)
2600{
2601        int version;
2602
2603        version = call >> 16; /* 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 */
2645asmlinkage long
2646sys32_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
2660struct rusage32 {
2661        struct timeval32 ru_utime;
2662        struct timeval32 ru_stime;
2663        int    ru_maxrss;
2664        int    ru_ixrss;
2665        int    ru_idrss;
2666        int    ru_isrss;
2667        int    ru_minflt;
2668        int    ru_majflt;
2669        int    ru_nswap;
2670        int    ru_inblock;
2671        int    ru_oublock;
2672        int    ru_msgsnd;
2673        int    ru_msgrcv;
2674        int    ru_nsignals;
2675        int    ru_nvcsw;
2676        int    ru_nivcsw;
2677};
2678
2679static int
2680put_rusage (struct rusage32 *ru, struct rusage *r)
2681{
2682        int err;
2683
2684        if (!access_ok(VERIFY_WRITE, ru, sizeof(*ru)))
2685                return -EFAULT;
2686
2687        err = __put_user (r->ru_utime.tv_sec, &ru->ru_utime.tv_sec);
2688        err |= __put_user (r->ru_utime.tv_usec, &ru->ru_utime.tv_usec);
2689        err |= __put_user (r->ru_stime.tv_sec, &ru->ru_stime.tv_sec);
2690        err |= __put_user (r->ru_stime.tv_usec, &ru->ru_stime.tv_usec);
2691        err |= __put_user (r->ru_maxrss, &ru->ru_maxrss);
2692        err |= __put_user (r->ru_ixrss, &ru->ru_ixrss);
2693        err |= __put_user (r->ru_idrss, &ru->ru_idrss);
2694        err |= __put_user (r->ru_isrss, &ru->ru_isrss);
2695        err |= __put_user (r->ru_minflt, &ru->ru_minflt);
2696        err |= __put_user (r->ru_majflt, &ru->ru_majflt);
2697        err |= __put_user (r->ru_nswap, &ru->ru_nswap);
2698        err |= __put_user (r->ru_inblock, &ru->ru_inblock);
2699        err |= __put_user (r->ru_oublock, &ru->ru_oublock);
2700        err |= __put_user (r->ru_msgsnd, &ru->ru_msgsnd);
2701        err |= __put_user (r->ru_msgrcv, &ru->ru_msgrcv);
2702        err |= __put_user (r->ru_nsignals, &ru->ru_nsignals);
2703        err |= __put_user (r->ru_nvcsw, &ru->ru_nvcsw);
2704        err |= __put_user (r->ru_nivcsw, &ru->ru_nivcsw);
2705        return err;
2706}
2707
2708asmlinkage long
2709sys32_wait4 (int pid, unsigned int *stat_addr, int options, struct rusage32 *ru)
2710{
2711        if (!ru)
2712                return sys_wait4(pid, stat_addr, options, NULL);
2713        else {
2714                struct rusage r;
2715                int ret;
2716                unsigned int status;
2717                mm_segment_t old_fs = get_fs();
2718
2719                set_fs(KERNEL_DS);
2720                ret = sys_wait4(pid, stat_addr ? &status : NULL, options, &r);
2721                set_fs(old_fs);
2722                if (put_rusage(ru, &r))
2723                        return -EFAULT;
2724                if (stat_addr && put_user(status, stat_addr))
2725                        return -EFAULT;
2726                return ret;
2727        }
2728}
2729
2730asmlinkage long
2731sys32_waitpid (int pid, unsigned int *stat_addr, int options)
2732{
2733        return sys32_wait4(pid, stat_addr, options, NULL);
2734}
2735
2736
2737extern asmlinkage long sys_getrusage (int who, struct rusage *ru);
2738
2739asmlinkage long
2740sys32_getrusage (int who, struct rusage32 *ru)
2741{
2742        struct rusage r;
2743        int ret;
2744        mm_segment_t old_fs = get_fs();
2745
2746        set_fs(KERNEL_DS);
2747        ret = sys_getrusage(who, &r);
2748        set_fs(old_fs);
2749        if (put_rusage (ru, &r))
2750                return -EFAULT;
2751        return ret;
2752}
2753
2754struct tms32 {
2755        __kernel_clock_t32 tms_utime;
2756        __kernel_clock_t32 tms_stime;
2757        __kernel_clock_t32 tms_cutime;
2758        __kernel_clock_t32 tms_cstime;
2759};
2760
2761extern asmlinkage long sys_times (struct tms * tbuf);
2762
2763asmlinkage long
2764sys32_times (struct tms32 *tbuf)
2765{
2766        mm_segment_t old_fs = get_fs();
2767        struct tms t;
2768        long ret;
2769        int err;
2770
2771        set_fs(KERNEL_DS);
2772        ret = sys_times(tbuf ? &t : NULL);
2773        set_fs(old_fs);
2774        if (tbuf) {
2775                err = put_user (IA32_TICK(t.tms_utime), &tbuf->tms_utime);
2776                err |= put_user (IA32_TICK(t.tms_stime), &tbuf->tms_stime);
2777                err |= put_user (IA32_TICK(t.tms_cutime), &tbuf->tms_cutime);
2778                err |= put_user (IA32_TICK(t.tms_cstime), &tbuf->tms_cstime);
2779                if (err)
2780                        ret = -EFAULT;
2781        }
2782        return IA32_TICK(ret);
2783}
2784
2785static unsigned int
2786ia32_peek (struct pt_regs *regs, struct task_struct *child, unsigned long addr, unsigned int *val)
2787{
2788        size_t copied;
2789        unsigned int ret;
2790
2791        copied = access_process_vm(child, addr, val, sizeof(*val), 0);
2792        return (copied != sizeof(ret)) ? -EIO : 0;
2793}
2794
2795static unsigned int
2796ia32_poke (struct pt_regs *regs, struct task_struct *child, unsigned long addr, unsigned int val)
2797{
2798
2799        if (access_process_vm(child, addr, &val, sizeof(val), 1) != sizeof(val))
2800                return -EIO;
2801        return 0;
2802}
2803
2804/*
2805 *  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
2825static unsigned int
2826getreg (struct task_struct *child, int regno)
2827{
2828        struct pt_regs *child_regs;
2829
2830        child_regs = ia64_task_regs(child);
2831        switch (regno / sizeof(int)) {
2832              case PT_EBX: return child_regs->r11;
2833              case PT_ECX: return child_regs->r9;
2834              case PT_EDX: return child_regs->r10;
2835              case PT_ESI: return child_regs->r14;
2836              case PT_EDI: return child_regs->r15;
2837              case PT_EBP: return child_regs->r13;
2838              case PT_EAX: return child_regs->r8;
2839              case PT_ORIG_EAX: return child_regs->r1; /* 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
2853static void
2854putreg (struct task_struct *child, int regno, unsigned int value)
2855{
2856        struct pt_regs *child_regs;
2857
2858        child_regs = ia64_task_regs(child);
2859        switch (regno / sizeof(int)) {
2860              case PT_EBX: child_regs->r11 = value; break;
2861              case PT_ECX: child_regs->r9 = value; break;
2862              case PT_EDX: child_regs->r10 = value; break;
2863              case PT_ESI: child_regs->r14 = value; break;
2864              case PT_EDI: child_regs->r15 = value; break;
2865              case PT_EBP: child_regs->r13 = value; break;
2866              case PT_EAX: child_regs->r8 = value; break;
2867              case PT_ORIG_EAX: child_regs->r1 = value; break;
2868              case PT_EIP: child_regs->cr_iip = value; break;
2869              case PT_UESP: child_regs->r12 = value; break;
2870              case PT_EFL: child->thread.eflag = value; break;
2871              case PT_DS: case PT_ES: case PT_FS: case PT_GS: case PT_SS:
2872                if (value != __USER_DS)
2873                        printk(KERN_ERR
2874                               "ia32.putreg: attempt to set invalid segment register %d = %x\n",
2875                               regno, value);
2876                break;
2877              case PT_CS:
2878                if (value != __USER_CS)
2879                        printk(KERN_ERR
2880                               "ia32.putreg: attempt to to set invalid segment register %d = %x\n",
2881                               regno, value);
2882                break;
2883              default:
2884                printk(KERN_ERR "ia32.putreg: unknown register %d\n", regno);
2885                break;
2886        }
2887}
2888
2889static void
2890put_fpreg (int regno, struct _fpreg_ia32 *reg, struct pt_regs *ptp, struct switch_stack *swp,
2891           int tos)
2892{
2893        struct _fpreg_ia32 *f;
2894        char buf[32];
2895
2896        f = (struct _fpreg_ia32 *)(((unsigned long)buf + 15) & ~15);
2897        if ((regno += tos) >= 8)
2898                regno -= 8;
2899        switch (regno) {
2900              case 0:
2901                ia64f2ia32f(f, &ptp->f8);
2902                break;
2903              case 1:
2904                ia64f2ia32f(f, &ptp->f9);
2905                break;
2906              case 2:
2907                ia64f2ia32f(f, &ptp->f10);
2908                break;
2909              case 3:
2910                ia64f2ia32f(f, &ptp->f11);
2911                break;
2912              case 4:
2913              case 5:
2914              case 6:
2915              case 7:
2916                ia64f2ia32f(f, &swp->f12 + (regno - 4));
2917                break;
2918        }
2919        copy_to_user(reg, f, sizeof(*reg));
2920}
2921
2922static void
2923get_fpreg (int regno, struct _fpreg_ia32 *reg, struct pt_regs *ptp, struct switch_stack *swp,
2924           int tos)
2925{
2926
2927        if ((regno += tos) >= 8)
2928                regno -= 8;
2929        switch (regno) {
2930              case 0:
2931                copy_from_user(&ptp->f8, reg, sizeof(*reg));
2932                break;
2933              case 1:
2934                copy_from_user(&ptp->f9, reg, sizeof(*reg));
2935                break;
2936              case 2:
2937                copy_from_user(&ptp->f10, reg, sizeof(*reg));
2938                break;
2939              case 3:
2940                copy_from_user(&ptp->f11, reg, sizeof(*reg));
2941                break;
2942              case 4:
2943              case 5:
2944              case 6:
2945              case 7:
2946                copy_from_user(&swp->f12 + (regno - 4), reg, sizeof(*reg));
2947                break;
2948        }
2949        return;
2950}
2951
2952int
2953save_ia32_fpstate (struct task_struct *tsk, struct ia32_user_i387_struct *save)
2954{
2955        struct switch_stack *swp;
2956        struct pt_regs *ptp;
2957        int i, tos;
2958
2959        if (!access_ok(VERIFY_WRITE, save, sizeof(*save)))
2960                return -EFAULT;
2961
2962        __put_user(tsk->thread.fcr & 0xffff, &save->cwd);
2963        __put_user(tsk->thread.fsr & 0xffff, &save->swd);
2964        __put_user((tsk->thread.fsr>>16) & 0xffff, &save->twd);
2965        __put_user(tsk->thread.fir, &save->fip);
2966        __put_user((tsk->thread.fir>>32) & 0xffff, &save->fcs);
2967        __put_user(tsk->thread.fdr, &save->foo);
2968        __put_user((tsk->thread.fdr>>32) & 0xffff, &save->fos);
2969
2970        /*
2971         *  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
2981static int
2982restore_ia32_fpstate (struct task_struct *tsk, struct ia32_user_i387_struct *save)
2983{
2984        struct switch_stack *swp;
2985        struct pt_regs *ptp;
2986        int i, tos;
2987        unsigned int fsrlo, fsrhi, num32;
2988
2989        if (!access_ok(VERIFY_READ, save, sizeof(*save)))
2990                return(-EFAULT);
2991
2992        __get_user(num32, (unsigned int *)&save->cwd);
2993        tsk->thread.fcr = (tsk->thread.fcr & (~0x1f3f)) | (num32 & 0x1f3f);
2994        __get_user(fsrlo, (unsigned int *)&save->swd);
2995        __get_user(fsrhi, (unsigned int *)&save->twd);
2996        num32 = (fsrhi << 16) | fsrlo;
2997        tsk->thread.fsr = (tsk->thread.fsr & (~0xffffffff)) | num32;
2998        __get_user(num32, (unsigned int *)&save->fip);
2999        tsk->thread.fir = (tsk->thread.fir & (~0xffffffff)) | num32;
3000        __get_user(num32, (unsigned int *)&save->foo);
3001        tsk->thread.fdr = (tsk->thread.fdr & (~0xffffffff)) | num32;
3002
3003        /*
3004         *  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
3014int
3015save_ia32_fpxstate (struct task_struct *tsk, struct ia32_user_fxsr_struct *save)
3016{
3017        struct switch_stack *swp;
3018        struct pt_regs *ptp;
3019        int i, tos;
3020        unsigned long mxcsr=0;
3021        unsigned long num128[2];
3022
3023        if (!access_ok(VERIFY_WRITE, save, sizeof(*save)))
3024                return -EFAULT;
3025
3026        __put_user(tsk->thread.fcr & 0xffff, &save->cwd);
3027        __put_user(tsk->thread.fsr & 0xffff, &save->swd);
3028        __put_user((tsk->thread.fsr>>16) & 0xffff, &save->twd);
3029        __put_user(tsk->thread.fir, &save->fip);
3030        __put_user((tsk->thread.fir>>32) & 0xffff, &save->fcs);
3031        __put_user(tsk->thread.fdr, &save->foo);
3032        __put_user((tsk->thread.fdr>>32) & 0xffff, &save->fos);
3033
3034        /*
3035         *  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
3053static int
3054restore_ia32_fpxstate (struct task_struct *tsk, struct ia32_user_fxsr_struct *save)
3055{
3056        struct switch_stack *swp;
3057        struct pt_regs *ptp;
3058        int i, tos;
3059        unsigned int fsrlo, fsrhi, num32;
3060        int mxcsr;
3061        unsigned long num64;
3062        unsigned long num128[2];
3063
3064        if (!access_ok(VERIFY_READ, save, sizeof(*save)))
3065                return(-EFAULT);
3066
3067        __get_user(num32, (unsigned int *)&save->cwd);
3068        tsk->thread.fcr = (tsk->thread.fcr & (~0x1f3f)) | (num32 & 0x1f3f);
3069        __get_user(fsrlo, (unsigned int *)&save->swd);
3070        __get_user(fsrhi, (unsigned int *)&save->twd);
3071        num32 = (fsrhi << 16) | fsrlo;
3072        tsk->thread.fsr = (tsk->thread.fsr & (~0xffffffff)) | num32;
3073        __get_user(num32, (unsigned int *)&save->fip);
3074        tsk->thread.fir = (tsk->thread.fir & (~0xffffffff)) | num32;
3075        __get_user(num32, (unsigned int *)&save->foo);
3076        tsk->thread.fdr = (tsk->thread.fdr & (~0xffffffff)) | num32;
3077
3078        /*
3079         *  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
3101extern 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 */
3111asmlinkage long
3112sys32_ptrace (int request, pid_t pid, unsigned int addr, unsigned int data,
3113              long arg4, long arg5, long arg6, long arg7, long stack)
3114{
3115        struct pt_regs *regs = (struct pt_regs *) &stack;
3116        struct task_struct *child;
3117        unsigned int value, tmp;
3118        long i, ret;
3119
3120        lock_kernel();
3121        if (request == PTRACE_TRACEME) {
3122                ret = sys_ptrace(request, pid, addr, data, arg4, arg5, arg6, arg7, stack);
3123                goto out;
3124        }
3125
3126        ret = -ESRCH;
3127        read_lock(&tasklist_lock);
3128        child = find_task_by_pid(pid);
3129        if (child)
3130                get_task_struct(child);
3131        read_unlock(&tasklist_lock);
3132        if (!child)
3133                goto out;
3134        ret = -EPERM;
3135        if (pid == 1)           /* 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
3242static inline int
3243get_flock32(struct flock *kfl, struct flock32 *ufl)
3244{
3245        int err;
3246
3247        if (!access_ok(VERIFY_READ, ufl, sizeof(*ufl)))
3248                return -EFAULT;
3249
3250        err = __get_user(kfl->l_type, &ufl->l_type);
3251        err |= __get_user(kfl->l_whence, &ufl->l_whence);
3252        err |= __get_user(kfl->l_start, &ufl->l_start);
3253        err |= __get_user(kfl->l_len, &ufl->l_len);
3254        err |= __get_user(kfl->l_pid, &ufl->l_pid);
3255        return err;
3256}
3257
3258static inline int
3259put_flock32(struct flock *kfl, struct flock32 *ufl)
3260{
3261        int err;
3262
3263        if (!access_ok(VERIFY_WRITE, ufl, sizeof(*ufl)))
3264                return -EFAULT;
3265
3266        err = __put_user(kfl->l_type, &ufl->l_type);
3267        err |= __put_user(kfl->l_whence, &ufl->l_whence);
3268        err |= __put_user(kfl->l_start, &ufl->l_start);
3269        err |= __put_user(kfl->l_len, &ufl->l_len);
3270        err |= __put_user(kfl->l_pid, &ufl->l_pid);
3271        return err;
3272}
3273
3274extern asmlinkage long sys_fcntl (unsigned int fd, unsigned int cmd, unsigned long arg);
3275
3276asmlinkage long
3277sys32_fcntl (unsigned int fd, unsigned int cmd, unsigned int arg)
3278{
3279        mm_segment_t old_fs;
3280        struct flock f;
3281        long ret;
3282
3283        switch (cmd) {
3284              case F_GETLK:
3285              case F_SETLK:
3286              case F_SETLKW:
3287                if (get_flock32(&f, (struct flock32 *) A(arg)))
3288                        return -EFAULT;
3289                old_fs = get_fs();
3290                set_fs(KERNEL_DS);
3291                ret = sys_fcntl(fd, cmd, (unsigned long) &f);
3292                set_fs(old_fs);
3293                if (cmd == F_GETLK && put_flock32(&f, (struct flock32 *) A(arg)))
3294                        return -EFAULT;
3295                return ret;
3296
3297              default:
3298                /*
3299                 *  `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
3306asmlinkage long sys_ni_syscall(void);
3307
3308asmlinkage long
3309sys32_ni_syscall (int dummy0, int dummy1, int dummy2, int dummy3, int dummy4, int dummy5,
3310                  int dummy6, int dummy7, int stack)
3311{
3312        struct pt_regs *regs = (struct pt_regs *)&stack;
3313
3314        printk(KERN_WARNING "IA32 syscall #%d issued, maybe we should implement it\n",
3315               (int)regs->r1);
3316        return(sys_ni_syscall());
3317}
3318
3319/*
3320 *  The IA64 maps 4 I/O ports for each 4K page
3321 */
3322#define IOLEN   ((65536 / 4) * 4096)
3323
3324asmlinkage long
3325sys32_iopl (int level)
3326{
3327        extern unsigned long ia64_iobase;
3328        int fd;
3329        struct file * file;
3330        unsigned int old;
3331        unsigned long addr;
3332        mm_segment_t old_fs = get_fs ();
3333
3334        if (level != 3)
3335                return(-EINVAL);
3336        /* 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
3369asmlinkage long
3370sys32_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
3386typedef struct {
3387        unsigned int    ss_sp;
3388        unsigned int    ss_flags;
3389        unsigned int    ss_size;
3390} ia32_stack_t;
3391
3392asmlinkage long
3393sys32_sigaltstack (ia32_stack_t *uss32, ia32_stack_t *uoss32,
3394                   long arg2, long arg3, long arg4, long arg5, long arg6, long arg7, long stack)
3395{
3396        struct pt_regs *pt = (struct pt_regs *) &stack;
3397        stack_t uss, uoss;
3398        ia32_stack_t buf32;
3399        int ret;
3400        mm_segment_t old_fs = get_fs();
3401
3402        if (uss32)
3403                if (copy_from_user(&buf32, uss32, sizeof(ia32_stack_t)))
3404                        return -EFAULT;
3405        uss.ss_sp = (void *) (long) buf32.ss_sp;
3406        uss.ss_flags = buf32.ss_flags;
3407        /* 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);
3418out:
3419        if (ret < 0)
3420                return(ret);
3421        if (uoss32) {
3422                buf32.ss_sp = (long) uoss.ss_sp;
3423                buf32.ss_flags = uoss.ss_flags;
3424                buf32.ss_size = uoss.ss_size;
3425                if (copy_to_user(uoss32, &buf32, sizeof(ia32_stack_t)))
3426                        return -EFAULT;
3427        }
3428        return ret;
3429}
3430
3431asmlinkage int
3432sys32_pause (void)
3433{
3434        current->state = TASK_INTERRUPTIBLE;
3435        schedule();
3436        return -ERESTARTNOHAND;
3437}
3438
3439asmlinkage long sys_msync (unsigned long start, size_t len, int flags);
3440
3441asmlinkage int
3442sys32_msync (unsigned int start, unsigned int len, int flags)
3443{
3444        unsigned int addr;
3445
3446        if (OFFSET4K(start))
3447                return -EINVAL;
3448        addr = PAGE_START(start);
3449        return sys_msync(addr, len + (start - addr), flags);
3450}
3451
3452struct sysctl32 {
3453        unsigned int    name;
3454        int             nlen;
3455        unsigned int    oldval;
3456        unsigned int    oldlenp;
3457        unsigned int    newval;
3458        unsigned int    newlen;
3459        unsigned int    __unused[4];
3460};
3461
3462extern asmlinkage long sys_sysctl(struct __sysctl_args *args);
3463
3464asmlinkage long
3465sys32_sysctl (struct sysctl32 *args)
3466{
3467#ifdef CONFIG_SYSCTL
3468        struct sysctl32 a32;
3469        mm_segment_t old_fs = get_fs ();
3470        void *oldvalp, *newvalp;
3471        size_t oldlen;
3472        int *namep;
3473        long ret;
3474
3475        if (copy_from_user(&a32, args, sizeof(a32)))
3476                return -EFAULT;
3477
3478        /*
3479         * 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
3510asmlinkage long
3511sys32_newuname (struct new_utsname *name)
3512{
3513        extern asmlinkage long sys_newuname(struct new_utsname * name);
3514        int ret = sys_newuname(name);
3515
3516        if (!ret)
3517                if (copy_to_user(name->machine, "i686\0\0\0", 8))
3518                        ret = -EFAULT;
3519        return ret;
3520}
3521
3522extern asmlinkage long sys_getresuid (uid_t *ruid, uid_t *euid, uid_t *suid);
3523
3524asmlinkage long
3525sys32_getresuid16 (u16 *ruid, u16 *euid, u16 *suid)
3526{
3527        uid_t a, b, c;
3528        int ret;
3529        mm_segment_t old_fs = get_fs();
3530
3531        set_fs(KERNEL_DS);
3532        ret = sys_getresuid(&a, &b, &c);
3533        set_fs(old_fs);
3534
3535        if (put_user(a, ruid) || put_user(b, euid) || put_user(c, suid))
3536                return -EFAULT;
3537        return ret;
3538}
3539
3540extern asmlinkage long sys_getresgid (gid_t *rgid, gid_t *egid, gid_t *sgid);
3541
3542asmlinkage long
3543sys32_getresgid16 (u16 *rgid, u16 *egid, u16 *sgid)
3544{
3545        gid_t a, b, c;
3546        int ret;
3547        mm_segment_t old_fs = get_fs();
3548
3549        set_fs(KERNEL_DS);
3550        ret = sys_getresgid(&a, &b, &c);
3551        set_fs(old_fs);
3552
3553        if (ret)
3554                return ret;
3555
3556        return put_user(a, rgid) | put_user(b, egid) | put_user(c, sgid);
3557}
3558
3559asmlinkage long
3560sys32_lseek (unsigned int fd, int offset, unsigned int whence)
3561{
3562        extern off_t sys_lseek (unsigned int fd, off_t offset, unsigned int origin);
3563
3564        /* Sign-extension of "offset" is important here... */
3565        return sys_lseek(fd, offset, whence);
3566}
3567
3568extern asmlinkage long sys_getgroups (int gidsetsize, gid_t *grouplist);
3569
3570asmlinkage long
3571sys32_getgroups16 (int gidsetsize, short *grouplist)
3572{
3573        mm_segment_t old_fs = get_fs();
3574        gid_t gl[NGROUPS];
3575        int ret, i;
3576
3577        set_fs(KERNEL_DS);
3578        ret = sys_getgroups(gidsetsize, gl);
3579        set_fs(old_fs);
3580
3581        if (gidsetsize && ret > 0 && ret <= NGROUPS)
3582                for (i = 0; i < ret; i++, grouplist++)
3583                        if (put_user(gl[i], grouplist))
3584                                return -EFAULT;
3585        return ret;
3586}
3587
3588extern asmlinkage long sys_setgroups (int gidsetsize, gid_t *grouplist);
3589
3590asmlinkage long
3591sys32_setgroups16 (int gidsetsize, short *grouplist)
3592{
3593        mm_segment_t old_fs = get_fs();
3594        gid_t gl[NGROUPS];
3595        int ret, i;
3596
3597        if ((unsigned) gidsetsize > NGROUPS)
3598                return -EINVAL;
3599        for (i = 0; i < gidsetsize; i++, grouplist++)
3600                if (get_user(gl[i], grouplist))
3601                        return -EFAULT;
3602        set_fs(KERNEL_DS);
3603        ret = sys_setgroups(gidsetsize, gl);
3604        set_fs(old_fs);
3605        return ret;
3606}
3607
3608/*
3609 * 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
3614static inline long
3615ia32_put_flock (struct flock *l, unsigned long addr)
3616{
3617        return (put_user(l->l_type, (short *) addr)
3618                | put_user(l->l_whence, (short *) (addr + 2))
3619                | put_user(l->l_start, (long *) (addr + 4))
3620                | put_user(l->l_len, (long *) (addr + 12))
3621                | put_user(l->l_pid, (int *) (addr + 20)));
3622}
3623
3624static inline long
3625ia32_get_flock (struct flock *l, unsigned long addr)
3626{
3627        unsigned int start_lo, start_hi, len_lo, len_hi;
3628        int err = (get_user(l->l_type, (short *) addr)
3629                   | get_user(l->l_whence, (short *) (addr + 2))
3630                   | get_user(start_lo, (int *) (addr + 4))
3631                   | get_user(start_hi, (int *) (addr + 8))
3632                   | get_user(len_lo, (int *) (addr + 12))
3633                   | get_user(len_hi, (int *) (addr + 16))
3634                   | get_user(l->l_pid, (int *) (addr + 20)));
3635        l->l_start = ((unsigned long) start_hi << 32) | start_lo;
3636        l->l_len = ((unsigned long) len_hi << 32) | len_lo;
3637        return err;
3638}
3639
3640asmlinkage long
3641sys32_fcntl64 (unsigned int fd, unsigned int cmd, unsigned int arg)
3642{
3643        mm_segment_t old_fs;
3644        struct flock f;
3645        long ret;
3646
3647        switch (cmd) {
3648              case F_GETLK64:
3649              case F_SETLK64:
3650              case F_SETLKW64:
3651                if (ia32_get_flock(&f, arg))
3652                        return -EFAULT;
3653                old_fs = get_fs();
3654                set_fs(KERNEL_DS);
3655                ret = sys_fcntl(fd, (cmd == F_GETLK64) ? F_GETLK :
3656                        ((cmd == F_SETLK64) ? F_SETLK : F_SETLKW),
3657                        (unsigned long) &f);
3658                set_fs(old_fs);
3659                if (cmd == F_GETLK64 && ia32_put_flock(&f, arg))
3660                        return -EFAULT;
3661                break;
3662
3663              default:
3664                ret = sys32_fcntl(fd, cmd, arg);
3665                break;
3666        }
3667        return ret;
3668}
3669
3670asmlinkage long
3671sys32_truncate64 (unsigned int path, unsigned int len_lo, unsigned int len_hi)
3672{
3673        extern asmlinkage long sys_truncate (const char *path, unsigned long length);
3674
3675        return sys_truncate((const char *) A(path), ((unsigned long) len_hi << 32) | len_lo);
3676}
3677
3678asmlinkage long
3679sys32_ftruncate64 (int fd, unsigned int len_lo, unsigned int len_hi)
3680{
3681        extern asmlinkage long sys_ftruncate (int fd, unsigned long length);
3682
3683        return sys_ftruncate(fd, ((unsigned long) len_hi << 32) | len_lo);
3684}
3685
3686static int
3687putstat64 (struct stat64 *ubuf, struct stat *kbuf)
3688{
3689        int err;
3690
3691        if (clear_user(ubuf, sizeof(*ubuf)))
3692                return 1;
3693
3694        err  = __put_user(kbuf->st_dev, &ubuf->st_dev);
3695        err |= __put_user(kbuf->st_ino, &ubuf->__st_ino);
3696        err |= __put_user(kbuf->st_ino, &ubuf->st_ino_lo);
3697        err |= __put_user(kbuf->st_ino >> 32, &ubuf->st_ino_hi);
3698        err |= __put_user(kbuf->st_mode, &ubuf->st_mode);
3699        err |= __put_user(kbuf->st_nlink, &ubuf->st_nlink);
3700        err |= __put_user(kbuf->st_uid, &ubuf->st_uid);
3701        err |= __put_user(kbuf->st_gid, &ubuf->st_gid);
3702        err |= __put_user(kbuf->st_rdev, &ubuf->st_rdev);
3703        err |= __put_user(kbuf->st_size, &ubuf->st_size_lo);
3704        err |= __put_user((kbuf->st_size >> 32), &ubuf->st_size_hi);
3705        err |= __put_user(kbuf->st_atime, &ubuf->st_atime);
3706        err |= __put_user(kbuf->st_mtime, &ubuf->st_mtime);
3707        err |= __put_user(kbuf->st_ctime, &ubuf->st_ctime);
3708        err |= __put_user(kbuf->st_blksize, &ubuf->st_blksize);
3709        err |= __put_user(kbuf->st_blocks, &ubuf->st_blocks);
3710        return err;
3711}
3712
3713asmlinkage long
3714sys32_stat64 (char *filename, struct stat64 *statbuf)
3715{
3716        char *name;
3717        mm_segment_t old_fs = get_fs();
3718        struct stat s;
3719        long ret;
3720
3721        name = getname(filename);
3722        if (IS_ERR(name))
3723                return PTR_ERR(name);
3724        set_fs(KERNEL_DS);
3725        ret = sys_newstat(name, &s);
3726        set_fs(old_fs);
3727        putname(name);
3728        if (putstat64(statbuf, &s))
3729                return -EFAULT;
3730        return ret;
3731}
3732
3733asmlinkage long
3734sys32_lstat64 (char *filename, struct stat64 *statbuf)
3735{
3736        char *name;
3737        mm_segment_t old_fs = get_fs();
3738        struct stat s;
3739        long ret;
3740
3741        name = getname(filename);
3742        if (IS_ERR(name))
3743                return PTR_ERR(name);
3744        set_fs(KERNEL_DS);
3745        ret = sys_newlstat(name, &s);
3746        set_fs(old_fs);
3747        putname(name);
3748        if (putstat64(statbuf, &s))
3749                return -EFAULT;
3750        return ret;
3751}
3752
3753asmlinkage long
3754sys32_fstat64 (unsigned int fd, struct stat64 *statbuf)
3755{
3756        mm_segment_t old_fs = get_fs();
3757        struct stat s;
3758        long ret;
3759
3760        set_fs(KERNEL_DS);
3761        ret = sys_newfstat(fd, &s);
3762        set_fs(old_fs);
3763        if (putstat64(statbuf, &s))
3764                return -EFAULT;
3765        return ret;
3766}
3767
3768asmlinkage long
3769sys32_sigpending (unsigned int *set)
3770{
3771        return do_sigpending(set, sizeof(*set));
3772}
3773
3774struct sysinfo32 {
3775        s32 uptime;
3776        u32 loads[3];
3777        u32 totalram;
3778        u32 freeram;
3779        u32 sharedram;
3780        u32 bufferram;
3781        u32 totalswap;
3782        u32 freeswap;
3783        u16 procs;
3784        u16 pad;
3785        u32 totalhigh;
3786        u32 freehigh;
3787        u32 mem_unit;
3788        char _f[8];
3789};
3790
3791asmlinkage long
3792sys32_sysinfo (struct sysinfo32 *info)
3793{
3794        extern asmlinkage long sys_sysinfo (struct sysinfo *);
3795        struct sysinfo s;
3796        long ret, err;
3797        int bitcount = 0;
3798        mm_segment_t old_fs = get_fs();
3799
3800        set_fs(KERNEL_DS);
3801        ret = sys_sysinfo(&s);
3802        set_fs(old_fs);
3803        /* 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 */
3849static inline int
3850do_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
3865static char *
3866getname32 (const char *filename)
3867{
3868        char *tmp, *result;
3869
3870        result = ERR_PTR(-ENOMEM);
3871        tmp = (char *)__get_free_page(GFP_KERNEL);
3872        if (tmp)  {
3873                int retval = do_getname32(filename, tmp);
3874
3875                result = tmp;
3876                if (retval < 0) {
3877                        putname(tmp);
3878                        result = ERR_PTR(retval);
3879                }
3880        }
3881        return result;
3882}
3883
3884struct user_dqblk32 {
3885        __u32 dqb_bhardlimit;
3886        __u32 dqb_bsoftlimit;
3887        __u32 dqb_curblocks;
3888        __u32 dqb_ihardlimit;
3889        __u32 dqb_isoftlimit;
3890        __u32 dqb_curinodes;
3891        __kernel_time_t32 dqb_btime;
3892        __kernel_time_t32 dqb_itime;
3893};
3894
3895asmlinkage long
3896sys32_quotactl(int cmd, unsigned int special, int id, caddr_t addr)
3897{
3898        extern asmlinkage long sys_quotactl (int, const char *, int, caddr_t);
3899        int cmds = cmd >> SUBCMDSHIFT;
3900        mm_segment_t old_fs;
3901        struct v1c_mem_dqblk d;
3902        char *spec;
3903        long err;
3904
3905        switch (cmds) {
3906        case Q_V1_GETQUOTA:
3907                break;
3908        case Q_V1_SETQUOTA:
3909        case Q_V1_SETUSE:
3910        case Q_V1_SETQLIM:
3911                if (copy_from_user(&d, addr, sizeof(struct user_dqblk32)))
3912                        return -EFAULT;
3913                d.dqb_itime = ((struct user_dqblk32 *)&d)->dqb_itime;
3914                d.dqb_btime = ((struct user_dqblk32 *)&d)->dqb_btime;
3915                break;
3916        default:
3917                return sys_quotactl(cmd, (void *)A(special), id, addr);
3918        }
3919        spec = getname32((void *) A(special));
3920        err = PTR_ERR(spec);
3921        if (IS_ERR(spec))
3922                return err;
3923        old_fs = get_fs();
3924        set_fs(KERNEL_DS);
3925        err = sys_quotactl(cmd, (const char *)spec, id, (caddr_t)&d);
3926        set_fs(old_fs);
3927        putname(spec);
3928        if (cmds == Q_V1_GETQUOTA) {
3929                __kernel_time_t b = d.dqb_btime, i = d.dqb_itime;
3930                ((struct user_dqblk32 *)&d)->dqb_itime = i;
3931                ((struct user_dqblk32 *)&d)->dqb_btime = b;
3932                if (copy_to_user(addr, &d, sizeof(struct user_dqblk32)))
3933                        return -EFAULT;
3934        }
3935        return err;
3936}
3937
3938asmlinkage long
3939sys32_sched_rr_get_interval (pid_t pid, struct timespec32 *interval)
3940{
3941        extern asmlinkage long sys_sched_rr_get_interval (pid_t, struct timespec *);
3942        mm_segment_t old_fs = get_fs();
3943        struct timespec t;
3944        long ret;
3945
3946        set_fs(KERNEL_DS);
3947        ret = sys_sched_rr_get_interval(pid, &t);
3948        set_fs(old_fs);
3949        if (put_user (t.tv_sec, &interval->tv_sec) || put_user (t.tv_nsec, &interval->tv_nsec))
3950                return -EFAULT;
3951        return ret;
3952}
3953
3954asmlinkage long
3955sys32_pread (unsigned int fd, void *buf, unsigned int count, u32 pos_lo, u32 pos_hi)
3956{
3957        extern asmlinkage long sys_pread (unsigned int, char *, size_t, loff_t);
3958        return sys_pread(fd, buf, count, ((unsigned long) pos_hi << 32) | pos_lo);
3959}
3960
3961asmlinkage long
3962sys32_pwrite (unsigned int fd, void *buf, unsigned int count, u32 pos_lo, u32 pos_hi)
3963{
3964        extern asmlinkage long sys_pwrite (unsigned int, const char *, size_t, loff_t);
3965        return sys_pwrite(fd, buf, count, ((unsigned long) pos_hi << 32) | pos_lo);
3966}
3967
3968asmlinkage long
3969sys32_sendfile (int out_fd, int in_fd, int *offset, unsigned int count)
3970{
3971        extern asmlinkage long sys_sendfile (int, int, off_t *, size_t);
3972        mm_segment_t old_fs = get_fs();
3973        long ret;
3974        off_t of;
3975
3976        if (offset && get_user(of, offset))
3977                return -EFAULT;
3978
3979        set_fs(KERNEL_DS);
3980        ret = sys_sendfile(out_fd, in_fd, offset ? &of : NULL, count);
3981        set_fs(old_fs);
3982
3983        if (!ret && offset && put_user(of, offset))
3984                return -EFAULT;
3985
3986        return ret;
3987}
3988
3989asmlinkage long
3990sys32_personality (unsigned int personality)
3991{
3992        extern asmlinkage long sys_personality (unsigned long);
3993        long ret;
3994
3995        if (current->personality == PER_LINUX32 && personality == PER_LINUX)
3996                personality = PER_LINUX32;
3997        ret = sys_personality(personality);
3998        if (ret == PER_LINUX32)
3999                ret = PER_LINUX;
4000        return ret;
4001}
4002
4003asmlinkage unsigned long
4004sys32_brk (unsigned int brk)
4005{
4006        unsigned long ret, obrk;
4007        struct mm_struct *mm = current->mm;
4008
4009        obrk = mm->brk;
4010        ret = sys_brk(brk);
4011        if (ret < obrk)
4012                clear_user((void *) ret, PAGE_ALIGN(ret) - ret);
4013        return ret;
4014}
4015
4016/*
4017 * Exactly like fs/open.c:sys_open(), except that it doesn't set the O_LARGEFILE flag.
4018 */
4019asmlinkage long
4020sys32_open (const char * filename, int flags, int mode)
4021{
4022        char * tmp;
4023        int fd, error;
4024
4025        tmp = getname(filename);
4026        fd = PTR_ERR(tmp);
4027        if (!IS_ERR(tmp)) {
4028                fd = get_unused_fd();
4029                if (fd >= 0) {
4030                        struct file *f = filp_open(tmp, flags, mode);
4031                        error = PTR_ERR(f);
4032                        if (IS_ERR(f))
4033                                goto out_error;
4034                        fd_install(fd, f);
4035                }
4036out:
4037                putname(tmp);
4038        }
4039        return fd;
4040
4041out_error:
4042        put_unused_fd(fd);
4043        fd = error;
4044        goto out;
4045}
4046
4047#ifdef  NOTYET  /* UNTESTED FOR IA64 FROM HERE DOWN */
4048
4049struct ncp_mount_data32 {
4050        int version;
4051        unsigned int ncp_fd;
4052        __kernel_uid_t32 mounted_uid;
4053        int wdog_pid;
4054        unsigned char mounted_vol[NCP_VOLNAME_LEN + 1];
4055        unsigned int time_out;
4056        unsigned int retry_count;
4057        unsigned int flags;
4058        __kernel_uid_t32 uid;
4059        __kernel_gid_t32 gid;
4060        __kernel_mode_t32 file_mode;
4061        __kernel_mode_t32 dir_mode;
4062};
4063
4064static void *
4065do_ncp_super_data_conv(void *raw_data)
4066{
4067        struct ncp_mount_data *n = (struct ncp_mount_data *)raw_data;
4068        struct ncp_mount_data32 *n32 = (struct ncp_mount_data32 *)raw_data;
4069
4070        n->dir_mode = n32->dir_mode;
4071        n->file_mode = n32->file_mode;
4072        n->gid = n32->gid;
4073        n->uid = n32->uid;
4074        memmove (n->mounted_vol, n32->mounted_vol,
4075                 (sizeof (n32->mounted_vol) + 3 * sizeof (unsigned int)));
4076        n->wdog_pid = n32->wdog_pid;
4077        n->mounted_uid = n32->mounted_uid;
4078        return raw_data;
4079}
4080
4081struct smb_mount_data32 {
4082        int version;
4083        __kernel_uid_t32 mounted_uid;
4084        __kernel_uid_t32 uid;
4085        __kernel_gid_t32 gid;
4086        __kernel_mode_t32 file_mode;
4087        __kernel_mode_t32 dir_mode;
4088};
4089
4090static void *
4091do_smb_super_data_conv(void *raw_data)
4092{
4093        struct smb_mount_data *s = (struct smb_mount_data *)raw_data;
4094        struct smb_mount_data32 *s32 = (struct smb_mount_data32 *)raw_data;
4095
4096        s->version = s32->version;
4097        s->mounted_uid = s32->mounted_uid;
4098        s->uid = s32->uid;
4099        s->gid = s32->gid;
4100        s->file_mode = s32->file_mode;
4101        s->dir_mode = s32->dir_mode;
4102        return raw_data;
4103}
4104
4105static int
4106copy_mount_stuff_to_kernel(const void *user, unsigned long *kernel)
4107{
4108        int i;
4109        unsigned long page;
4110        struct vm_area_struct *vma;
4111
4112        *kernel = 0;
4113        if(!user)
4114                return 0;
4115        vma = find_vma(current->mm, (unsigned long)user);
4116        if(!vma || (unsigned long)user < vma->vm_start)
4117                return -EFAULT;
4118        if(!(vma->vm_flags & VM_READ))
4119                return -EFAULT;
4120        i = vma->vm_end - (unsigned long) user;
4121        if(PAGE_SIZE <= (unsigned long) i)
4122                i = PAGE_SIZE - 1;
4123        if(!(page = __get_free_page(GFP_KERNEL)))
4124                return -ENOMEM;
4125        if(copy_from_user((void *) page, user, i)) {
4126                free_page(page);
4127                return -EFAULT;
4128        }
4129        *kernel = page;
4130        return 0;
4131}
4132
4133extern asmlinkage long sys_mount(char * dev_name, char * dir_name, char * type,
4134                                unsigned long new_flags, void *data);
4135
4136#define SMBFS_NAME      "smbfs"
4137#define NCPFS_NAME      "ncpfs"
4138
4139asmlinkage long
4140sys32_mount(char *dev_name, char *dir_name, char *type,
4141            unsigned long new_flags, u32 data)
4142{
4143        unsigned long type_page;
4144        int err, is_smb, is_ncp;
4145
4146        if(!capable(CAP_SYS_ADMIN))
4147                return -EPERM;
4148        is_smb = is_ncp = 0;
4149        err = copy_mount_stuff_to_kernel((const void *)type, &type_page);
4150        if(err)
4151                return err;
4152        if(type_page) {
4153                is_smb = !strcmp((char *)type_page, SMBFS_NAME);
4154                is_ncp = !strcmp((char *)type_page, NCPFS_NAME);
4155        }
4156        if(!is_smb && !is_ncp) {
4157                if(type_page)
4158                        free_page(type_page);
4159                return sys_mount(dev_name, dir_name, type, new_flags,
4160                                 (void *)AA(data));
4161        } else {
4162                unsigned long dev_page, dir_page, data_page;
4163
4164                err = copy_mount_stuff_to_kernel((const void *)dev_name,
4165                                                 &dev_page);
4166                if(err)
4167                        goto out;
4168                err = copy_mount_stuff_to_kernel((const void *)dir_name,
4169                                                 &dir_page);
4170                if(err)
4171                        goto dev_out;
4172                err = copy_mount_stuff_to_kernel((const void *)AA(data),
4173                                                 &data_page);
4174                if(err)
4175                        goto dir_out;
4176                if(is_ncp)
4177                        do_ncp_super_data_conv((void *)data_page);
4178                else if(is_smb)
4179                        do_smb_super_data_conv((void *)data_page);
4180                else
4181                        panic("The problem is here...");
4182                err = do_mount((char *)dev_page, (char *)dir_page,
4183                                (char *)type_page, new_flags,
4184                                (void *)data_page);
4185                if(data_page)
4186                        free_page(data_page);
4187        dir_out:
4188                if(dir_page)
4189                        free_page(dir_page);
4190        dev_out:
4191                if(dev_page)
4192                        free_page(dev_page);
4193        out:
4194                if(type_page)
4195                        free_page(type_page);
4196                return err;
4197        }
4198}
4199
4200extern asmlinkage long sys_setreuid(uid_t ruid, uid_t euid);
4201
4202asmlinkage long sys32_setreuid(__kernel_uid_t32 ruid, __kernel_uid_t32 euid)
4203{
4204        uid_t sruid, seuid;
4205
4206        sruid = (ruid == (__kernel_uid_t32)-1) ? ((uid_t)-1) : ((uid_t)ruid);
4207        seuid = (euid == (__kernel_uid_t32)-1) ? ((uid_t)-1) : ((uid_t)euid);
4208        return sys_setreuid(sruid, seuid);
4209}
4210
4211extern asmlinkage long sys_setresuid(uid_t ruid, uid_t euid, uid_t suid);
4212
4213asmlinkage long
4214sys32_setresuid(__kernel_uid_t32 ruid, __kernel_uid_t32 euid,
4215                __kernel_uid_t32 suid)
4216{
4217        uid_t sruid, seuid, ssuid;
4218
4219        sruid = (ruid == (__kernel_uid_t32)-1) ? ((uid_t)-1) : ((uid_t)ruid);
4220        seuid = (euid == (__kernel_uid_t32)-1) ? ((uid_t)-1) : ((uid_t)euid);
4221        ssuid = (suid == (__kernel_uid_t32)-1) ? ((uid_t)-1) : ((uid_t)suid);
4222        return sys_setresuid(sruid, seuid, ssuid);
4223}
4224
4225extern asmlinkage long sys_setregid(gid_t rgid, gid_t egid);
4226
4227asmlinkage long
4228sys32_setregid(__kernel_gid_t32 rgid, __kernel_gid_t32 egid)
4229{
4230        gid_t srgid, segid;
4231
4232        srgid = (rgid == (__kernel_gid_t32)-1) ? ((gid_t)-1) : ((gid_t)rgid);
4233        segid = (egid == (__kernel_gid_t32)-1) ? ((gid_t)-1) : ((gid_t)egid);
4234        return sys_setregid(srgid, segid);
4235}
4236
4237extern asmlinkage long sys_setresgid(gid_t rgid, gid_t egid, gid_t sgid);
4238
4239asmlinkage long
4240sys32_setresgid(__kernel_gid_t32 rgid, __kernel_gid_t32 egid,
4241                __kernel_gid_t32 sgid)
4242{
4243        gid_t srgid, segid, ssgid;
4244
4245        srgid = (rgid == (__kernel_gid_t32)-1) ? ((gid_t)-1) : ((gid_t)rgid);
4246        segid = (egid == (__kernel_gid_t32)-1) ? ((gid_t)-1) : ((gid_t)egid);
4247        ssgid = (sgid == (__kernel_gid_t32)-1) ? ((gid_t)-1) : ((gid_t)sgid);
4248        return sys_setresgid(srgid, segid, ssgid);
4249}
4250
4251/* Stuff for NFS server syscalls... */
4252struct nfsctl_svc32 {
4253        u16                     svc32_port;
4254        s32                     svc32_nthreads;
4255};
4256
4257struct nfsctl_client32 {
4258        s8                      cl32_ident[NFSCLNT_IDMAX+1];
4259        s32                     cl32_naddr;
4260        struct in_addr          cl32_addrlist[NFSCLNT_ADDRMAX];
4261        s32                     cl32_fhkeytype;
4262        s32                     cl32_fhkeylen;
4263        u8                      cl32_fhkey[NFSCLNT_KEYMAX];
4264};
4265
4266struct nfsctl_export32 {
4267        s8                      ex32_client[NFSCLNT_IDMAX+1];
4268        s8                      ex32_path[NFS_MAXPATHLEN+1];
4269        __kernel_dev_t32        ex32_dev;
4270        __kernel_ino_t32        ex32_ino;
4271        s32                     ex32_flags;
4272        __kernel_uid_t32        ex32_anon_uid;
4273        __kernel_gid_t32        ex32_anon_gid;
4274};
4275
4276struct nfsctl_uidmap32 {
4277        u32                     ug32_ident;   /* 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
4286struct nfsctl_fhparm32 {
4287        struct sockaddr         gf32_addr;
4288        __kernel_dev_t32        gf32_dev;
4289        __kernel_ino_t32        gf32_ino;
4290        s32                     gf32_version;
4291};
4292
4293struct nfsctl_arg32 {
4294        s32                     ca32_version;   /* 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
4312union nfsctl_res32 {
4313        struct knfs_fh          cr32_getfh;
4314        u32                     cr32_debug;
4315};
4316
4317static int
4318nfs_svc32_trans(struct nfsctl_arg *karg, struct nfsctl_arg32 *arg32)
4319{
4320        int err;
4321
4322        err = __get_user(karg->ca_version, &arg32->ca32_version);
4323        err |= __get_user(karg->ca_svc.svc_port, &arg32->ca32_svc.svc32_port);
4324        err |= __get_user(karg->ca_svc.svc_nthreads,
4325                          &arg32->ca32_svc.svc32_nthreads);
4326        return err;
4327}
4328
4329static int
4330nfs_clnt32_trans(struct nfsctl_arg *karg, struct nfsctl_arg32 *arg32)
4331{
4332        int err;
4333
4334        err = __get_user(karg->ca_version, &arg32->ca32_version);
4335        err |= copy_from_user(&karg->ca_client.cl_ident[0],
4336                          &arg32->ca32_client.cl32_ident[0],
4337                          NFSCLNT_IDMAX);
4338        err |= __get_user(karg->ca_client.cl_naddr,
4339                          &arg32->ca32_client.cl32_naddr);
4340        err |= copy_from_user(&karg->ca_client.cl_addrlist[0],
4341                          &arg32->ca32_client.cl32_addrlist[0],
4342                          (sizeof(struct in_addr) * NFSCLNT_ADDRMAX));
4343        err |= __get_user(karg->ca_client.cl_fhkeytype,
4344                      &arg32->ca32_client.cl32_fhkeytype);
4345        err |= __get_user(karg->ca_client.cl_fhkeylen,
4346                      &arg32->ca32_client.cl32_fhkeylen);
4347        err |= copy_from_user(&karg->ca_client.cl_fhkey[0],
4348                          &arg32->ca32_client.cl32_fhkey[0],
4349                          NFSCLNT_KEYMAX);
4350        return err;
4351}
4352
4353static int
4354nfs_exp32_trans(struct nfsctl_arg *karg, struct nfsctl_arg32 *arg32)
4355{
4356        int err;
4357
4358        err = __get_user(karg->ca_version, &arg32->ca32_version);
4359        err |= copy_from_user(&karg->ca_export.ex_client[0],
4360                          &arg32->ca32_export.ex32_client[0],
4361                          NFSCLNT_IDMAX);
4362        err |= copy_from_user(&karg->ca_export.ex_path[0],
4363                          &arg32->ca32_export.ex32_path[0],
4364                          NFS_MAXPATHLEN);
4365        err |= __get_user(karg->ca_export.ex_dev,
4366                      &arg32->ca32_export.ex32_dev);
4367        err |= __get_user(karg->ca_export.ex_ino,
4368                      &arg32->ca32_export.ex32_ino);
4369        err |= __get_user(karg->ca_export.ex_flags,
4370                      &arg32->ca32_export.ex32_flags);
4371        err |= __get_user(karg->ca_export.ex_anon_uid,
4372                      &arg32->ca32_export.ex32_anon_uid);
4373        err |= __get_user(karg->ca_export.ex_anon_gid,
4374                      &arg32->ca32_export.ex32_anon_gid);
4375        return err;
4376}
4377
4378static int
4379nfs_uud32_trans(struct nfsctl_arg *karg, struct nfsctl_arg32 *arg32)
4380{
4381        u32 uaddr;
4382        int i;
4383        int err;
4384
4385        memset(karg, 0, sizeof(*karg));
4386        if(__get_user(karg->ca_version, &arg32->ca32_version))
4387                return -EFAULT;
4388        karg->ca_umap.ug_ident = (char *)get_free_page(GFP_USER);
4389        if(!karg->ca_umap.ug_ident)
4390                return -ENOMEM;
4391        err = __get_user(uaddr, &arg32->ca32_umap.ug32_ident);
4392        if(strncpy_from_user(karg->ca_umap.ug_ident,
4393                             (char *)A(uaddr), PAGE_SIZE) <= 0)
4394                return -EFAULT;
4395        err |= __get_user(karg->ca_umap.ug_uidbase,
4396                      &arg32->ca32_umap.ug32_uidbase);
4397        err |= __get_user(karg->ca_umap.ug_uidlen,
4398                      &arg32->ca32_umap.ug32_uidlen);
4399        err |= __get_user(uaddr, &arg32->ca32_umap.ug32_udimap);
4400        if (err)
4401                return -EFAULT;
4402        karg->ca_umap.ug_udimap = kmalloc((sizeof(uid_t) *
4403                                           karg->ca_umap.ug_uidlen),
4404                                          GFP_USER);
4405        if(!karg->ca_umap.ug_udimap)
4406                return -ENOMEM;
4407        for(i = 0; i < karg->ca_umap.ug_uidlen; i++)
4408                err |= __get_user(karg->ca_umap.ug_udimap[i],
4409                              &(((__kernel_uid_t32 *)A(uaddr))[i]));
4410        err |= __get_user(karg->ca_umap.ug_gidbase,
4411                      &arg32->ca32_umap.ug32_gidbase);
4412        err |= __get_user(karg->ca_umap.ug_uidlen,
4413                      &arg32->ca32_umap.ug32_gidlen);
4414        err |= __get_user(uaddr, &arg32->ca32_umap.ug32_gdimap);
4415        if (err)
4416                return -EFAULT;
4417        karg->ca_umap.ug_gdimap = kmalloc((sizeof(gid_t) *
4418                                           karg->ca_umap.ug_uidlen),
4419                                          GFP_USER);
4420        if(!karg->ca_umap.ug_gdimap)
4421                return -ENOMEM;
4422        for(i = 0; i < karg->ca_umap.ug_gidlen; i++)
4423                err |= __get_user(karg->ca_umap.ug_gdimap[i],
4424                              &(((__kernel_gid_t32 *)A(uaddr))[i]));
4425
4426        return err;
4427}
4428
4429static int
4430nfs_getfh32_trans(struct nfsctl_arg *karg, struct nfsctl_arg32 *arg32)
4431{
4432        int err;
4433
4434        err = __get_user(karg->ca_version, &arg32->ca32_version);
4435        err |= copy_from_user(&karg->ca_getfh.gf_addr,
4436                          &arg32->ca32_getfh.gf32_addr,
4437                          (sizeof(struct sockaddr)));
4438        err |= __get_user(karg->ca_getfh.gf_dev,
4439                      &arg32->ca32_getfh.gf32_dev);
4440        err |= __get_user(karg->ca_getfh.gf_ino,
4441                      &arg32->ca32_getfh.gf32_ino);
4442        err |= __get_user(karg->ca_getfh.gf_version,
4443                      &arg32->ca32_getfh.gf32_version);
4444        return err;
4445}
4446
4447static int
4448nfs_getfh32_res_trans(union nfsctl_res *kres, union nfsctl_res32 *res32)
4449{
4450        int err;
4451
4452        err = copy_to_user(&res32->cr32_getfh,
4453                        &kres->cr_getfh,
4454                        sizeof(res32->cr32_getfh));
4455        err |= __put_user(kres->cr_debug, &res32->cr32_debug);
4456        return err;
4457}
4458
4459extern asmlinkage long sys_nfsservctl(int cmd, void *arg, void *resp);
4460
4461int asmlinkage
4462sys32_nfsservctl(int cmd, struct nfsctl_arg32 *arg32, union nfsctl_res32 *res32)
4463{
4464        struct nfsctl_arg *karg = NULL;
4465        union nfsctl_res *kres = NULL;
4466        mm_segment_t oldfs;
4467        int err;
4468
4469        karg = kmalloc(sizeof(*karg), GFP_USER);
4470        if(!karg)
4471                return -ENOMEM;
4472        if(res32) {
4473                kres = kmalloc(sizeof(*kres), GFP_USER);
4474                if(!kres) {
4475                        kfree(karg);
4476                        return -ENOMEM;
4477                }
4478        }
4479        switch(cmd) {
4480        case NFSCTL_SVC:
4481                err = nfs_svc32_trans(karg, arg32);
4482                break;
4483        case NFSCTL_ADDCLIENT:
4484                err = nfs_clnt32_trans(karg, arg32);
4485                break;
4486        case NFSCTL_DELCLIENT:
4487                err = nfs_clnt32_trans(karg, arg32);
4488                break;
4489        case NFSCTL_EXPORT:
4490                err = nfs_exp32_trans(karg, arg32);
4491                break;
4492        /* 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
4513done:
4514        if(karg) {
4515                if(cmd == NFSCTL_UGIDUPDATE) {
4516                        if(karg->ca_umap.ug_ident)
4517                                kfree(karg->ca_umap.ug_ident);
4518                        if(karg->ca_umap.ug_udimap)
4519                                kfree(karg->ca_umap.ug_udimap);
4520                        if(karg->ca_umap.ug_gdimap)
4521                                kfree(karg->ca_umap.ug_gdimap);
4522                }
4523                kfree(karg);
4524        }
4525        if(kres)
4526                kfree(kres);
4527        return err;
4528}
4529
4530/* Handle adjtimex compatability. */
4531
4532struct timex32 {
4533        u32 modes;
4534        s32 offset, freq, maxerror, esterror;
4535        s32 status, constant, precision, tolerance;
4536        struct timeval32 time;
4537        s32 tick;
4538        s32 ppsfreq, jitter, shift, stabil;
4539        s32 jitcnt, calcnt, errcnt, stbcnt;
4540        s32  :32; s32  :32; s32  :32; s32  :32;
4541        s32  :32; s32  :32; s32  :32; s32  :32;
4542        s32  :32; s32  :32; s32  :32; s32  :32;
4543};
4544
4545extern int do_adjtimex(struct timex *);
4546
4547asmlinkage long
4548sys32_adjtimex(struct timex32 *utp)
4549{
4550        struct timex txc;
4551        int ret;
4552
4553        memset(&txc, 0, sizeof(struct timex));
4554
4555        if(get_user(txc.modes, &utp->modes) ||
4556           __get_user(txc.offset, &utp->offset) ||
4557           __get_user(txc.freq, &utp->freq) ||
4558           __get_user(txc.maxerror, &utp->maxerror) ||
4559           __get_user(txc.esterror, &utp->esterror) ||
4560           __get_user(txc.status, &utp->status) ||
4561           __get_user(txc.constant, &utp->constant) ||
4562           __get_user(txc.precision, &utp->precision) ||
4563           __get_user(txc.tolerance, &utp->tolerance) ||
4564           __get_user(txc.time.tv_sec, &utp->time.tv_sec) ||
4565           __get_user(txc.time.tv_usec, &utp->time.tv_usec) ||
4566           __get_user(txc.tick, &utp->tick) ||
4567           __get_user(txc.ppsfreq, &utp->ppsfreq) ||
4568           __get_user(txc.jitter, &utp->jitter) ||
4569           __get_user(txc.shift, &utp->shift) ||
4570           __get_user(txc.stabil, &utp->stabil) ||
4571           __get_user(txc.jitcnt, &utp->jitcnt) ||
4572           __get_user(txc.calcnt, &utp->calcnt) ||
4573           __get_user(txc.errcnt, &utp->errcnt) ||
4574           __get_user(txc.stbcnt, &utp->stbcnt))
4575                return -EFAULT;
4576
4577        ret = do_adjtimex(&txc);
4578
4579        if(put_user(txc.modes, &utp->modes) ||
4580           __put_user(txc.offset, &utp->offset) ||
4581           __put_user(txc.freq, &utp->freq) ||
4582           __put_user(txc.maxerror, &utp->maxerror) ||
4583           __put_user(txc.esterror, &utp->esterror) ||
4584           __put_user(txc.status, &utp->status) ||
4585           __put_user(txc.constant, &utp->constant) ||
4586           __put_user(txc.precision, &utp->precision) ||
4587           __put_user(txc.tolerance, &utp->tolerance) ||
4588           __put_user(txc.time.tv_sec, &utp->time.tv_sec) ||
4589           __put_user(txc.time.tv_usec, &utp->time.tv_usec) ||
4590           __put_user(txc.tick, &utp->tick) ||
4591           __put_user(txc.ppsfreq, &utp->ppsfreq) ||
4592           __put_user(txc.jitter, &utp->jitter) ||
4593           __put_user(txc.shift, &utp->shift) ||
4594           __put_user(txc.stabil, &utp->stabil) ||
4595           __put_user(txc.jitcnt, &utp->jitcnt) ||
4596           __put_user(txc.calcnt, &utp->calcnt) ||
4597           __put_user(txc.errcnt, &utp->errcnt) ||
4598           __put_user(txc.stbcnt, &utp->stbcnt))
4599                ret = -EFAULT;
4600
4601        return ret;
4602}
4603#endif /* NOTYET */
4604
lxr.linux.no kindly hosted by Redpill Linpro AS, provider of Linux consulting and operations services since 1995.