linux/arch/sparc/kernel/sys_sparc32.c
<<
>>
Prefs
   1/* sys_sparc32.c: Conversion between 32bit and 64bit native syscalls.
   2 *
   3 * Copyright (C) 1997,1998 Jakub Jelinek (jj@sunsite.mff.cuni.cz)
   4 * Copyright (C) 1997, 2007 David S. Miller (davem@davemloft.net)
   5 *
   6 * These routines maintain argument size conversion between 32bit and 64bit
   7 * environment.
   8 */
   9
  10#include <linux/kernel.h>
  11#include <linux/sched.h>
  12#include <linux/capability.h>
  13#include <linux/fs.h> 
  14#include <linux/mm.h> 
  15#include <linux/file.h> 
  16#include <linux/signal.h>
  17#include <linux/resource.h>
  18#include <linux/times.h>
  19#include <linux/smp.h>
  20#include <linux/smp_lock.h>
  21#include <linux/sem.h>
  22#include <linux/msg.h>
  23#include <linux/shm.h>
  24#include <linux/slab.h>
  25#include <linux/uio.h>
  26#include <linux/nfs_fs.h>
  27#include <linux/quota.h>
  28#include <linux/module.h>
  29#include <linux/sunrpc/svc.h>
  30#include <linux/nfsd/nfsd.h>
  31#include <linux/nfsd/cache.h>
  32#include <linux/nfsd/xdr.h>
  33#include <linux/nfsd/syscall.h>
  34#include <linux/poll.h>
  35#include <linux/personality.h>
  36#include <linux/stat.h>
  37#include <linux/filter.h>
  38#include <linux/highmem.h>
  39#include <linux/highuid.h>
  40#include <linux/mman.h>
  41#include <linux/ipv6.h>
  42#include <linux/in.h>
  43#include <linux/icmpv6.h>
  44#include <linux/syscalls.h>
  45#include <linux/sysctl.h>
  46#include <linux/binfmts.h>
  47#include <linux/dnotify.h>
  48#include <linux/security.h>
  49#include <linux/compat.h>
  50#include <linux/vfs.h>
  51#include <linux/netfilter_ipv4/ip_tables.h>
  52#include <linux/ptrace.h>
  53
  54#include <asm/types.h>
  55#include <asm/uaccess.h>
  56#include <asm/fpumacro.h>
  57#include <asm/mmu_context.h>
  58#include <asm/compat_signal.h>
  59
  60#ifdef CONFIG_SYSVIPC                                                        
  61asmlinkage long compat_sys_ipc(u32 call, u32 first, u32 second, u32 third, compat_uptr_t ptr, u32 fifth)
  62{
  63        int version;
  64
  65        version = call >> 16; /* hack for backward compatibility */
  66        call &= 0xffff;
  67
  68        switch (call) {
  69        case SEMTIMEDOP:
  70                if (fifth)
  71                        /* sign extend semid */
  72                        return compat_sys_semtimedop((int)first,
  73                                                     compat_ptr(ptr), second,
  74                                                     compat_ptr(fifth));
  75                /* else fall through for normal semop() */
  76        case SEMOP:
  77                /* struct sembuf is the same on 32 and 64bit :)) */
  78                /* sign extend semid */
  79                return sys_semtimedop((int)first, compat_ptr(ptr), second,
  80                                      NULL);
  81        case SEMGET:
  82                /* sign extend key, nsems */
  83                return sys_semget((int)first, (int)second, third);
  84        case SEMCTL:
  85                /* sign extend semid, semnum */
  86                return compat_sys_semctl((int)first, (int)second, third,
  87                                         compat_ptr(ptr));
  88
  89        case MSGSND:
  90                /* sign extend msqid */
  91                return compat_sys_msgsnd((int)first, (int)second, third,
  92                                         compat_ptr(ptr));
  93        case MSGRCV:
  94                /* sign extend msqid, msgtyp */
  95                return compat_sys_msgrcv((int)first, second, (int)fifth,
  96                                         third, version, compat_ptr(ptr));
  97        case MSGGET:
  98                /* sign extend key */
  99                return sys_msgget((int)first, second);
 100        case MSGCTL:
 101                /* sign extend msqid */
 102                return compat_sys_msgctl((int)first, second, compat_ptr(ptr));
 103
 104        case SHMAT:
 105                /* sign extend shmid */
 106                return compat_sys_shmat((int)first, second, third, version,
 107                                        compat_ptr(ptr));
 108        case SHMDT:
 109                return sys_shmdt(compat_ptr(ptr));
 110        case SHMGET:
 111                /* sign extend key_t */
 112                return sys_shmget((int)first, second, third);
 113        case SHMCTL:
 114                /* sign extend shmid */
 115                return compat_sys_shmctl((int)first, second, compat_ptr(ptr));
 116
 117        default:
 118                return -ENOSYS;
 119        };
 120
 121        return -ENOSYS;
 122}
 123#endif
 124
 125asmlinkage long sys32_truncate64(const char __user * path, unsigned long high, unsigned long low)
 126{
 127        if ((int)high < 0)
 128                return -EINVAL;
 129        else
 130                return sys_truncate(path, (high << 32) | low);
 131}
 132
 133asmlinkage long sys32_ftruncate64(unsigned int fd, unsigned long high, unsigned long low)
 134{
 135        if ((int)high < 0)
 136                return -EINVAL;
 137        else
 138                return sys_ftruncate(fd, (high << 32) | low);
 139}
 140
 141static int cp_compat_stat64(struct kstat *stat,
 142                            struct compat_stat64 __user *statbuf)
 143{
 144        int err;
 145
 146        err  = put_user(huge_encode_dev(stat->dev), &statbuf->st_dev);
 147        err |= put_user(stat->ino, &statbuf->st_ino);
 148        err |= put_user(stat->mode, &statbuf->st_mode);
 149        err |= put_user(stat->nlink, &statbuf->st_nlink);
 150        err |= put_user(stat->uid, &statbuf->st_uid);
 151        err |= put_user(stat->gid, &statbuf->st_gid);
 152        err |= put_user(huge_encode_dev(stat->rdev), &statbuf->st_rdev);
 153        err |= put_user(0, (unsigned long __user *) &statbuf->__pad3[0]);
 154        err |= put_user(stat->size, &statbuf->st_size);
 155        err |= put_user(stat->blksize, &statbuf->st_blksize);
 156        err |= put_user(0, (unsigned int __user *) &statbuf->__pad4[0]);
 157        err |= put_user(0, (unsigned int __user *) &statbuf->__pad4[4]);
 158        err |= put_user(stat->blocks, &statbuf->st_blocks);
 159        err |= put_user(stat->atime.tv_sec, &statbuf->st_atime);
 160        err |= put_user(stat->atime.tv_nsec, &statbuf->st_atime_nsec);
 161        err |= put_user(stat->mtime.tv_sec, &statbuf->st_mtime);
 162        err |= put_user(stat->mtime.tv_nsec, &statbuf->st_mtime_nsec);
 163        err |= put_user(stat->ctime.tv_sec, &statbuf->st_ctime);
 164        err |= put_user(stat->ctime.tv_nsec, &statbuf->st_ctime_nsec);
 165        err |= put_user(0, &statbuf->__unused4);
 166        err |= put_user(0, &statbuf->__unused5);
 167
 168        return err;
 169}
 170
 171asmlinkage long compat_sys_stat64(char __user * filename,
 172                struct compat_stat64 __user *statbuf)
 173{
 174        struct kstat stat;
 175        int error = vfs_stat(filename, &stat);
 176
 177        if (!error)
 178                error = cp_compat_stat64(&stat, statbuf);
 179        return error;
 180}
 181
 182asmlinkage long compat_sys_lstat64(char __user * filename,
 183                struct compat_stat64 __user *statbuf)
 184{
 185        struct kstat stat;
 186        int error = vfs_lstat(filename, &stat);
 187
 188        if (!error)
 189                error = cp_compat_stat64(&stat, statbuf);
 190        return error;
 191}
 192
 193asmlinkage long compat_sys_fstat64(unsigned int fd,
 194                struct compat_stat64 __user * statbuf)
 195{
 196        struct kstat stat;
 197        int error = vfs_fstat(fd, &stat);
 198
 199        if (!error)
 200                error = cp_compat_stat64(&stat, statbuf);
 201        return error;
 202}
 203
 204asmlinkage long compat_sys_fstatat64(unsigned int dfd, char __user *filename,
 205                struct compat_stat64 __user * statbuf, int flag)
 206{
 207        struct kstat stat;
 208        int error;
 209
 210        error = vfs_fstatat(dfd, filename, &stat, flag);
 211        if (error)
 212                return error;
 213        return cp_compat_stat64(&stat, statbuf);
 214}
 215
 216asmlinkage long compat_sys_sysfs(int option, u32 arg1, u32 arg2)
 217{
 218        return sys_sysfs(option, arg1, arg2);
 219}
 220
 221asmlinkage long compat_sys_sched_rr_get_interval(compat_pid_t pid, struct compat_timespec __user *interval)
 222{
 223        struct timespec t;
 224        int ret;
 225        mm_segment_t old_fs = get_fs ();
 226        
 227        set_fs (KERNEL_DS);
 228        ret = sys_sched_rr_get_interval(pid, (struct timespec __user *) &t);
 229        set_fs (old_fs);
 230        if (put_compat_timespec(&t, interval))
 231                return -EFAULT;
 232        return ret;
 233}
 234
 235asmlinkage long compat_sys_rt_sigprocmask(int how,
 236                                          compat_sigset_t __user *set,
 237                                          compat_sigset_t __user *oset,
 238                                          compat_size_t sigsetsize)
 239{
 240        sigset_t s;
 241        compat_sigset_t s32;
 242        int ret;
 243        mm_segment_t old_fs = get_fs();
 244        
 245        if (set) {
 246                if (copy_from_user (&s32, set, sizeof(compat_sigset_t)))
 247                        return -EFAULT;
 248                switch (_NSIG_WORDS) {
 249                case 4: s.sig[3] = s32.sig[6] | (((long)s32.sig[7]) << 32);
 250                case 3: s.sig[2] = s32.sig[4] | (((long)s32.sig[5]) << 32);
 251                case 2: s.sig[1] = s32.sig[2] | (((long)s32.sig[3]) << 32);
 252                case 1: s.sig[0] = s32.sig[0] | (((long)s32.sig[1]) << 32);
 253                }
 254        }
 255        set_fs (KERNEL_DS);
 256        ret = sys_rt_sigprocmask(how,
 257                                 set ? (sigset_t __user *) &s : NULL,
 258                                 oset ? (sigset_t __user *) &s : NULL,
 259                                 sigsetsize);
 260        set_fs (old_fs);
 261        if (ret) return ret;
 262        if (oset) {
 263                switch (_NSIG_WORDS) {
 264                case 4: s32.sig[7] = (s.sig[3] >> 32); s32.sig[6] = s.sig[3];
 265                case 3: s32.sig[5] = (s.sig[2] >> 32); s32.sig[4] = s.sig[2];
 266                case 2: s32.sig[3] = (s.sig[1] >> 32); s32.sig[2] = s.sig[1];
 267                case 1: s32.sig[1] = (s.sig[0] >> 32); s32.sig[0] = s.sig[0];
 268                }
 269                if (copy_to_user (oset, &s32, sizeof(compat_sigset_t)))
 270                        return -EFAULT;
 271        }
 272        return 0;
 273}
 274
 275asmlinkage long sys32_rt_sigpending(compat_sigset_t __user *set,
 276                                    compat_size_t sigsetsize)
 277{
 278        sigset_t s;
 279        compat_sigset_t s32;
 280        int ret;
 281        mm_segment_t old_fs = get_fs();
 282                
 283        set_fs (KERNEL_DS);
 284        ret = sys_rt_sigpending((sigset_t __user *) &s, sigsetsize);
 285        set_fs (old_fs);
 286        if (!ret) {
 287                switch (_NSIG_WORDS) {
 288                case 4: s32.sig[7] = (s.sig[3] >> 32); s32.sig[6] = s.sig[3];
 289                case 3: s32.sig[5] = (s.sig[2] >> 32); s32.sig[4] = s.sig[2];
 290                case 2: s32.sig[3] = (s.sig[1] >> 32); s32.sig[2] = s.sig[1];
 291                case 1: s32.sig[1] = (s.sig[0] >> 32); s32.sig[0] = s.sig[0];
 292                }
 293                if (copy_to_user (set, &s32, sizeof(compat_sigset_t)))
 294                        return -EFAULT;
 295        }
 296        return ret;
 297}
 298
 299asmlinkage long compat_sys_rt_sigqueueinfo(int pid, int sig,
 300                                           struct compat_siginfo __user *uinfo)
 301{
 302        siginfo_t info;
 303        int ret;
 304        mm_segment_t old_fs = get_fs();
 305        
 306        if (copy_siginfo_from_user32(&info, uinfo))
 307                return -EFAULT;
 308
 309        set_fs (KERNEL_DS);
 310        ret = sys_rt_sigqueueinfo(pid, sig, (siginfo_t __user *) &info);
 311        set_fs (old_fs);
 312        return ret;
 313}
 314
 315asmlinkage long compat_sys_sigaction(int sig, struct old_sigaction32 __user *act,
 316                                     struct old_sigaction32 __user *oact)
 317{
 318        struct k_sigaction new_ka, old_ka;
 319        int ret;
 320
 321        WARN_ON_ONCE(sig >= 0);
 322        sig = -sig;
 323
 324        if (act) {
 325                compat_old_sigset_t mask;
 326                u32 u_handler, u_restorer;
 327                
 328                ret = get_user(u_handler, &act->sa_handler);
 329                new_ka.sa.sa_handler =  compat_ptr(u_handler);
 330                ret |= __get_user(u_restorer, &act->sa_restorer);
 331                new_ka.sa.sa_restorer = compat_ptr(u_restorer);
 332                ret |= __get_user(new_ka.sa.sa_flags, &act->sa_flags);
 333                ret |= __get_user(mask, &act->sa_mask);
 334                if (ret)
 335                        return ret;
 336                new_ka.ka_restorer = NULL;
 337                siginitset(&new_ka.sa.sa_mask, mask);
 338        }
 339
 340        ret = do_sigaction(sig, act ? &new_ka : NULL, oact ? &old_ka : NULL);
 341
 342        if (!ret && oact) {
 343                ret = put_user(ptr_to_compat(old_ka.sa.sa_handler), &oact->sa_handler);
 344                ret |= __put_user(ptr_to_compat(old_ka.sa.sa_restorer), &oact->sa_restorer);
 345                ret |= __put_user(old_ka.sa.sa_flags, &oact->sa_flags);
 346                ret |= __put_user(old_ka.sa.sa_mask.sig[0], &oact->sa_mask);
 347        }
 348
 349        return ret;
 350}
 351
 352asmlinkage long compat_sys_rt_sigaction(int sig,
 353                                        struct sigaction32 __user *act,
 354                                        struct sigaction32 __user *oact,
 355                                        void __user *restorer,
 356                                        compat_size_t sigsetsize)
 357{
 358        struct k_sigaction new_ka, old_ka;
 359        int ret;
 360        compat_sigset_t set32;
 361
 362        /* XXX: Don't preclude handling different sized sigset_t's.  */
 363        if (sigsetsize != sizeof(compat_sigset_t))
 364                return -EINVAL;
 365
 366        if (act) {
 367                u32 u_handler, u_restorer;
 368
 369                new_ka.ka_restorer = restorer;
 370                ret = get_user(u_handler, &act->sa_handler);
 371                new_ka.sa.sa_handler =  compat_ptr(u_handler);
 372                ret |= __copy_from_user(&set32, &act->sa_mask, sizeof(compat_sigset_t));
 373                switch (_NSIG_WORDS) {
 374                case 4: new_ka.sa.sa_mask.sig[3] = set32.sig[6] | (((long)set32.sig[7]) << 32);
 375                case 3: new_ka.sa.sa_mask.sig[2] = set32.sig[4] | (((long)set32.sig[5]) << 32);
 376                case 2: new_ka.sa.sa_mask.sig[1] = set32.sig[2] | (((long)set32.sig[3]) << 32);
 377                case 1: new_ka.sa.sa_mask.sig[0] = set32.sig[0] | (((long)set32.sig[1]) << 32);
 378                }
 379                ret |= __get_user(new_ka.sa.sa_flags, &act->sa_flags);
 380                ret |= __get_user(u_restorer, &act->sa_restorer);
 381                new_ka.sa.sa_restorer = compat_ptr(u_restorer);
 382                if (ret)
 383                        return -EFAULT;
 384        }
 385
 386        ret = do_sigaction(sig, act ? &new_ka : NULL, oact ? &old_ka : NULL);
 387
 388        if (!ret && oact) {
 389                switch (_NSIG_WORDS) {
 390                case 4: set32.sig[7] = (old_ka.sa.sa_mask.sig[3] >> 32); set32.sig[6] = old_ka.sa.sa_mask.sig[3];
 391                case 3: set32.sig[5] = (old_ka.sa.sa_mask.sig[2] >> 32); set32.sig[4] = old_ka.sa.sa_mask.sig[2];
 392                case 2: set32.sig[3] = (old_ka.sa.sa_mask.sig[1] >> 32); set32.sig[2] = old_ka.sa.sa_mask.sig[1];
 393                case 1: set32.sig[1] = (old_ka.sa.sa_mask.sig[0] >> 32); set32.sig[0] = old_ka.sa.sa_mask.sig[0];
 394                }
 395                ret = put_user(ptr_to_compat(old_ka.sa.sa_handler), &oact->sa_handler);
 396                ret |= __copy_to_user(&oact->sa_mask, &set32, sizeof(compat_sigset_t));
 397                ret |= __put_user(old_ka.sa.sa_flags, &oact->sa_flags);
 398                ret |= __put_user(ptr_to_compat(old_ka.sa.sa_restorer), &oact->sa_restorer);
 399                if (ret)
 400                        ret = -EFAULT;
 401        }
 402
 403        return ret;
 404}
 405
 406/*
 407 * sparc32_execve() executes a new program after the asm stub has set
 408 * things up for us.  This should basically do what I want it to.
 409 */
 410asmlinkage long sparc32_execve(struct pt_regs *regs)
 411{
 412        int error, base = 0;
 413        char *filename;
 414
 415        /* User register window flush is done by entry.S */
 416
 417        /* Check for indirect call. */
 418        if ((u32)regs->u_regs[UREG_G1] == 0)
 419                base = 1;
 420
 421        filename = getname(compat_ptr(regs->u_regs[base + UREG_I0]));
 422        error = PTR_ERR(filename);
 423        if (IS_ERR(filename))
 424                goto out;
 425
 426        error = compat_do_execve(filename,
 427                                 compat_ptr(regs->u_regs[base + UREG_I1]),
 428                                 compat_ptr(regs->u_regs[base + UREG_I2]), regs);
 429
 430        putname(filename);
 431
 432        if (!error) {
 433                fprs_write(0);
 434                current_thread_info()->xfsr[0] = 0;
 435                current_thread_info()->fpsaved[0] = 0;
 436                regs->tstate &= ~TSTATE_PEF;
 437        }
 438out:
 439        return error;
 440}
 441
 442#ifdef CONFIG_MODULES
 443
 444asmlinkage long sys32_init_module(void __user *umod, u32 len,
 445                                  const char __user *uargs)
 446{
 447        return sys_init_module(umod, len, uargs);
 448}
 449
 450asmlinkage long sys32_delete_module(const char __user *name_user,
 451                                    unsigned int flags)
 452{
 453        return sys_delete_module(name_user, flags);
 454}
 455
 456#else /* CONFIG_MODULES */
 457
 458asmlinkage long sys32_init_module(const char __user *name_user,
 459                                  struct module __user *mod_user)
 460{
 461        return -ENOSYS;
 462}
 463
 464asmlinkage long sys32_delete_module(const char __user *name_user)
 465{
 466        return -ENOSYS;
 467}
 468
 469#endif  /* CONFIG_MODULES */
 470
 471asmlinkage compat_ssize_t sys32_pread64(unsigned int fd,
 472                                        char __user *ubuf,
 473                                        compat_size_t count,
 474                                        unsigned long poshi,
 475                                        unsigned long poslo)
 476{
 477        return sys_pread64(fd, ubuf, count, (poshi << 32) | poslo);
 478}
 479
 480asmlinkage compat_ssize_t sys32_pwrite64(unsigned int fd,
 481                                         char __user *ubuf,
 482                                         compat_size_t count,
 483                                         unsigned long poshi,
 484                                         unsigned long poslo)
 485{
 486        return sys_pwrite64(fd, ubuf, count, (poshi << 32) | poslo);
 487}
 488
 489asmlinkage long compat_sys_readahead(int fd,
 490                                     unsigned long offhi,
 491                                     unsigned long offlo,
 492                                     compat_size_t count)
 493{
 494        return sys_readahead(fd, (offhi << 32) | offlo, count);
 495}
 496
 497long compat_sys_fadvise64(int fd,
 498                          unsigned long offhi,
 499                          unsigned long offlo,
 500                          compat_size_t len, int advice)
 501{
 502        return sys_fadvise64_64(fd, (offhi << 32) | offlo, len, advice);
 503}
 504
 505long compat_sys_fadvise64_64(int fd,
 506                             unsigned long offhi, unsigned long offlo,
 507                             unsigned long lenhi, unsigned long lenlo,
 508                             int advice)
 509{
 510        return sys_fadvise64_64(fd,
 511                                (offhi << 32) | offlo,
 512                                (lenhi << 32) | lenlo,
 513                                advice);
 514}
 515
 516asmlinkage long compat_sys_sendfile(int out_fd, int in_fd,
 517                                    compat_off_t __user *offset,
 518                                    compat_size_t count)
 519{
 520        mm_segment_t old_fs = get_fs();
 521        int ret;
 522        off_t of;
 523        
 524        if (offset && get_user(of, offset))
 525                return -EFAULT;
 526                
 527        set_fs(KERNEL_DS);
 528        ret = sys_sendfile(out_fd, in_fd,
 529                           offset ? (off_t __user *) &of : NULL,
 530                           count);
 531        set_fs(old_fs);
 532        
 533        if (offset && put_user(of, offset))
 534                return -EFAULT;
 535                
 536        return ret;
 537}
 538
 539asmlinkage long compat_sys_sendfile64(int out_fd, int in_fd,
 540                                      compat_loff_t __user *offset,
 541                                      compat_size_t count)
 542{
 543        mm_segment_t old_fs = get_fs();
 544        int ret;
 545        loff_t lof;
 546        
 547        if (offset && get_user(lof, offset))
 548                return -EFAULT;
 549                
 550        set_fs(KERNEL_DS);
 551        ret = sys_sendfile64(out_fd, in_fd,
 552                             offset ? (loff_t __user *) &lof : NULL,
 553                             count);
 554        set_fs(old_fs);
 555        
 556        if (offset && put_user(lof, offset))
 557                return -EFAULT;
 558                
 559        return ret;
 560}
 561
 562/* This is just a version for 32-bit applications which does
 563 * not force O_LARGEFILE on.
 564 */
 565
 566asmlinkage long sparc32_open(const char __user *filename,
 567                             int flags, int mode)
 568{
 569        return do_sys_open(AT_FDCWD, filename, flags, mode);
 570}
 571
 572extern unsigned long do_mremap(unsigned long addr,
 573        unsigned long old_len, unsigned long new_len,
 574        unsigned long flags, unsigned long new_addr);
 575                
 576asmlinkage unsigned long sys32_mremap(unsigned long addr,
 577        unsigned long old_len, unsigned long new_len,
 578        unsigned long flags, u32 __new_addr)
 579{
 580        unsigned long ret = -EINVAL;
 581        unsigned long new_addr = __new_addr;
 582
 583        if (unlikely(sparc_mmap_check(addr, old_len)))
 584                goto out;
 585        if (unlikely(sparc_mmap_check(new_addr, new_len)))
 586                goto out;
 587        down_write(&current->mm->mmap_sem);
 588        ret = do_mremap(addr, old_len, new_len, flags, new_addr);
 589        up_write(&current->mm->mmap_sem);
 590out:
 591        return ret;       
 592}
 593
 594struct __sysctl_args32 {
 595        u32 name;
 596        int nlen;
 597        u32 oldval;
 598        u32 oldlenp;
 599        u32 newval;
 600        u32 newlen;
 601        u32 __unused[4];
 602};
 603
 604asmlinkage long sys32_sysctl(struct __sysctl_args32 __user *args)
 605{
 606#ifndef CONFIG_SYSCTL_SYSCALL
 607        return -ENOSYS;
 608#else
 609        struct __sysctl_args32 tmp;
 610        int error;
 611        size_t oldlen, __user *oldlenp = NULL;
 612        unsigned long addr = (((unsigned long)&args->__unused[0]) + 7UL) & ~7UL;
 613
 614        if (copy_from_user(&tmp, args, sizeof(tmp)))
 615                return -EFAULT;
 616
 617        if (tmp.oldval && tmp.oldlenp) {
 618                /* Duh, this is ugly and might not work if sysctl_args
 619                   is in read-only memory, but do_sysctl does indirectly
 620                   a lot of uaccess in both directions and we'd have to
 621                   basically copy the whole sysctl.c here, and
 622                   glibc's __sysctl uses rw memory for the structure
 623                   anyway.  */
 624                if (get_user(oldlen, (u32 __user *)(unsigned long)tmp.oldlenp) ||
 625                    put_user(oldlen, (size_t __user *)addr))
 626                        return -EFAULT;
 627                oldlenp = (size_t __user *)addr;
 628        }
 629
 630        lock_kernel();
 631        error = do_sysctl((int __user *)(unsigned long) tmp.name,
 632                          tmp.nlen,
 633                          (void __user *)(unsigned long) tmp.oldval,
 634                          oldlenp,
 635                          (void __user *)(unsigned long) tmp.newval,
 636                          tmp.newlen);
 637        unlock_kernel();
 638        if (oldlenp) {
 639                if (!error) {
 640                        if (get_user(oldlen, (size_t __user *)addr) ||
 641                            put_user(oldlen, (u32 __user *)(unsigned long) tmp.oldlenp))
 642                                error = -EFAULT;
 643                }
 644                if (copy_to_user(args->__unused, tmp.__unused, sizeof(tmp.__unused)))
 645                        error = -EFAULT;
 646        }
 647        return error;
 648#endif
 649}
 650
 651long sys32_lookup_dcookie(unsigned long cookie_high,
 652                          unsigned long cookie_low,
 653                          char __user *buf, size_t len)
 654{
 655        return sys_lookup_dcookie((cookie_high << 32) | cookie_low,
 656                                  buf, len);
 657}
 658
 659long compat_sync_file_range(int fd, unsigned long off_high, unsigned long off_low, unsigned long nb_high, unsigned long nb_low, int flags)
 660{
 661        return sys_sync_file_range(fd,
 662                                   (off_high << 32) | off_low,
 663                                   (nb_high << 32) | nb_low,
 664                                   flags);
 665}
 666
 667asmlinkage long compat_sys_fallocate(int fd, int mode, u32 offhi, u32 offlo,
 668                                     u32 lenhi, u32 lenlo)
 669{
 670        return sys_fallocate(fd, mode, ((loff_t)offhi << 32) | offlo,
 671                             ((loff_t)lenhi << 32) | lenlo);
 672}
 673