linux/arch/powerpc/kernel/sys_ppc32.c
<<
>>
Prefs
   1/*
   2 * sys_ppc32.c: Conversion between 32bit and 64bit native syscalls.
   3 *
   4 * Copyright (C) 2001 IBM
   5 * Copyright (C) 1997,1998 Jakub Jelinek (jj@sunsite.mff.cuni.cz)
   6 * Copyright (C) 1997 David S. Miller (davem@caip.rutgers.edu)
   7 *
   8 * These routines maintain argument size conversion between 32bit and 64bit
   9 * environment.
  10 *
  11 *      This program is free software; you can redistribute it and/or
  12 *      modify it under the terms of the GNU General Public License
  13 *      as published by the Free Software Foundation; either version
  14 *      2 of the License, or (at your option) any later version.
  15 */
  16
  17#include <linux/kernel.h>
  18#include <linux/sched.h>
  19#include <linux/fs.h> 
  20#include <linux/mm.h> 
  21#include <linux/file.h> 
  22#include <linux/signal.h>
  23#include <linux/resource.h>
  24#include <linux/times.h>
  25#include <linux/utsname.h>
  26#include <linux/smp.h>
  27#include <linux/smp_lock.h>
  28#include <linux/sem.h>
  29#include <linux/msg.h>
  30#include <linux/shm.h>
  31#include <linux/poll.h>
  32#include <linux/personality.h>
  33#include <linux/stat.h>
  34#include <linux/mman.h>
  35#include <linux/in.h>
  36#include <linux/syscalls.h>
  37#include <linux/unistd.h>
  38#include <linux/sysctl.h>
  39#include <linux/binfmts.h>
  40#include <linux/security.h>
  41#include <linux/compat.h>
  42#include <linux/ptrace.h>
  43#include <linux/elf.h>
  44#include <linux/ipc.h>
  45
  46#include <asm/ptrace.h>
  47#include <asm/types.h>
  48#include <asm/uaccess.h>
  49#include <asm/unistd.h>
  50#include <asm/semaphore.h>
  51#include <asm/time.h>
  52#include <asm/mmu_context.h>
  53#include <asm/ppc-pci.h>
  54#include <asm/syscalls.h>
  55
  56struct old_linux_dirent32 {
  57        u32             d_ino;
  58        u32             d_offset;
  59        unsigned short  d_namlen;
  60        char            d_name[1];
  61};
  62
  63struct readdir_callback32 {
  64        struct old_linux_dirent32 __user * dirent;
  65        int count;
  66};
  67
  68static int fillonedir(void * __buf, const char * name, int namlen,
  69                                  off_t offset, u64 ino, unsigned int d_type)
  70{
  71        struct readdir_callback32 * buf = (struct readdir_callback32 *) __buf;
  72        struct old_linux_dirent32 __user * dirent;
  73        ino_t d_ino;
  74
  75        if (buf->count)
  76                return -EINVAL;
  77        d_ino = ino;
  78        if (sizeof(d_ino) < sizeof(ino) && d_ino != ino)
  79                return -EOVERFLOW;
  80        buf->count++;
  81        dirent = buf->dirent;
  82        put_user(d_ino, &dirent->d_ino);
  83        put_user(offset, &dirent->d_offset);
  84        put_user(namlen, &dirent->d_namlen);
  85        copy_to_user(dirent->d_name, name, namlen);
  86        put_user(0, dirent->d_name + namlen);
  87        return 0;
  88}
  89
  90asmlinkage int old32_readdir(unsigned int fd, struct old_linux_dirent32 __user *dirent, unsigned int count)
  91{
  92        int error = -EBADF;
  93        struct file * file;
  94        struct readdir_callback32 buf;
  95
  96        file = fget(fd);
  97        if (!file)
  98                goto out;
  99
 100        buf.count = 0;
 101        buf.dirent = dirent;
 102
 103        error = vfs_readdir(file, (filldir_t)fillonedir, &buf);
 104        if (error < 0)
 105                goto out_putf;
 106        error = buf.count;
 107
 108out_putf:
 109        fput(file);
 110out:
 111        return error;
 112}
 113
 114asmlinkage long ppc32_select(u32 n, compat_ulong_t __user *inp,
 115                compat_ulong_t __user *outp, compat_ulong_t __user *exp,
 116                compat_uptr_t tvp_x)
 117{
 118        /* sign extend n */
 119        return compat_sys_select((int)n, inp, outp, exp, compat_ptr(tvp_x));
 120}
 121
 122int cp_compat_stat(struct kstat *stat, struct compat_stat __user *statbuf)
 123{
 124        compat_ino_t ino;
 125        long err;
 126
 127        if (stat->size > MAX_NON_LFS || !new_valid_dev(stat->dev) ||
 128            !new_valid_dev(stat->rdev))
 129                return -EOVERFLOW;
 130
 131        ino = stat->ino;
 132        if (sizeof(ino) < sizeof(stat->ino) && ino != stat->ino)
 133                return -EOVERFLOW;
 134
 135        err  = access_ok(VERIFY_WRITE, statbuf, sizeof(*statbuf)) ? 0 : -EFAULT;
 136        err |= __put_user(new_encode_dev(stat->dev), &statbuf->st_dev);
 137        err |= __put_user(ino, &statbuf->st_ino);
 138        err |= __put_user(stat->mode, &statbuf->st_mode);
 139        err |= __put_user(stat->nlink, &statbuf->st_nlink);
 140        err |= __put_user(stat->uid, &statbuf->st_uid);
 141        err |= __put_user(stat->gid, &statbuf->st_gid);
 142        err |= __put_user(new_encode_dev(stat->rdev), &statbuf->st_rdev);
 143        err |= __put_user(stat->size, &statbuf->st_size);
 144        err |= __put_user(stat->atime.tv_sec, &statbuf->st_atime);
 145        err |= __put_user(stat->atime.tv_nsec, &statbuf->st_atime_nsec);
 146        err |= __put_user(stat->mtime.tv_sec, &statbuf->st_mtime);
 147        err |= __put_user(stat->mtime.tv_nsec, &statbuf->st_mtime_nsec);
 148        err |= __put_user(stat->ctime.tv_sec, &statbuf->st_ctime);
 149        err |= __put_user(stat->ctime.tv_nsec, &statbuf->st_ctime_nsec);
 150        err |= __put_user(stat->blksize, &statbuf->st_blksize);
 151        err |= __put_user(stat->blocks, &statbuf->st_blocks);
 152        err |= __put_user(0, &statbuf->__unused4[0]);
 153        err |= __put_user(0, &statbuf->__unused4[1]);
 154
 155        return err;
 156}
 157
 158/* Note: it is necessary to treat option as an unsigned int,
 159 * with the corresponding cast to a signed int to insure that the 
 160 * proper conversion (sign extension) between the register representation of a signed int (msr in 32-bit mode)
 161 * and the register representation of a signed int (msr in 64-bit mode) is performed.
 162 */
 163asmlinkage long compat_sys_sysfs(u32 option, u32 arg1, u32 arg2)
 164{
 165        return sys_sysfs((int)option, arg1, arg2);
 166}
 167
 168asmlinkage long compat_sys_pause(void)
 169{
 170        current->state = TASK_INTERRUPTIBLE;
 171        schedule();
 172        
 173        return -ERESTARTNOHAND;
 174}
 175
 176static inline long get_ts32(struct timespec *o, struct compat_timeval __user *i)
 177{
 178        long usec;
 179
 180        if (!access_ok(VERIFY_READ, i, sizeof(*i)))
 181                return -EFAULT;
 182        if (__get_user(o->tv_sec, &i->tv_sec))
 183                return -EFAULT;
 184        if (__get_user(usec, &i->tv_usec))
 185                return -EFAULT;
 186        o->tv_nsec = usec * 1000;
 187        return 0;
 188}
 189
 190static inline long put_tv32(struct compat_timeval __user *o, struct timeval *i)
 191{
 192        return (!access_ok(VERIFY_WRITE, o, sizeof(*o)) ||
 193                (__put_user(i->tv_sec, &o->tv_sec) |
 194                 __put_user(i->tv_usec, &o->tv_usec)));
 195}
 196
 197
 198
 199
 200/* Translations due to time_t size differences.  Which affects all
 201   sorts of things, like timeval and itimerval.  */
 202extern struct timezone sys_tz;
 203
 204asmlinkage long compat_sys_gettimeofday(struct compat_timeval __user *tv, struct timezone __user *tz)
 205{
 206        if (tv) {
 207                struct timeval ktv;
 208                do_gettimeofday(&ktv);
 209                if (put_tv32(tv, &ktv))
 210                        return -EFAULT;
 211        }
 212        if (tz) {
 213                if (copy_to_user(tz, &sys_tz, sizeof(sys_tz)))
 214                        return -EFAULT;
 215        }
 216        
 217        return 0;
 218}
 219
 220
 221
 222asmlinkage long compat_sys_settimeofday(struct compat_timeval __user *tv, struct timezone __user *tz)
 223{
 224        struct timespec kts;
 225        struct timezone ktz;
 226        
 227        if (tv) {
 228                if (get_ts32(&kts, tv))
 229                        return -EFAULT;
 230        }
 231        if (tz) {
 232                if (copy_from_user(&ktz, tz, sizeof(ktz)))
 233                        return -EFAULT;
 234        }
 235
 236        return do_sys_settimeofday(tv ? &kts : NULL, tz ? &ktz : NULL);
 237}
 238
 239#ifdef CONFIG_SYSVIPC
 240long compat_sys_ipc(u32 call, u32 first, u32 second, u32 third, compat_uptr_t ptr,
 241               u32 fifth)
 242{
 243        int version;
 244
 245        version = call >> 16; /* hack for backward compatibility */
 246        call &= 0xffff;
 247
 248        switch (call) {
 249
 250        case SEMTIMEDOP:
 251                if (fifth)
 252                        /* sign extend semid */
 253                        return compat_sys_semtimedop((int)first,
 254                                                     compat_ptr(ptr), second,
 255                                                     compat_ptr(fifth));
 256                /* else fall through for normal semop() */
 257        case SEMOP:
 258                /* struct sembuf is the same on 32 and 64bit :)) */
 259                /* sign extend semid */
 260                return sys_semtimedop((int)first, compat_ptr(ptr), second,
 261                                      NULL);
 262        case SEMGET:
 263                /* sign extend key, nsems */
 264                return sys_semget((int)first, (int)second, third);
 265        case SEMCTL:
 266                /* sign extend semid, semnum */
 267                return compat_sys_semctl((int)first, (int)second, third,
 268                                         compat_ptr(ptr));
 269
 270        case MSGSND:
 271                /* sign extend msqid */
 272                return compat_sys_msgsnd((int)first, (int)second, third,
 273                                         compat_ptr(ptr));
 274        case MSGRCV:
 275                /* sign extend msqid, msgtyp */
 276                return compat_sys_msgrcv((int)first, second, (int)fifth,
 277                                         third, version, compat_ptr(ptr));
 278        case MSGGET:
 279                /* sign extend key */
 280                return sys_msgget((int)first, second);
 281        case MSGCTL:
 282                /* sign extend msqid */
 283                return compat_sys_msgctl((int)first, second, compat_ptr(ptr));
 284
 285        case SHMAT:
 286                /* sign extend shmid */
 287                return compat_sys_shmat((int)first, second, third, version,
 288                                        compat_ptr(ptr));
 289        case SHMDT:
 290                return sys_shmdt(compat_ptr(ptr));
 291        case SHMGET:
 292                /* sign extend key_t */
 293                return sys_shmget((int)first, second, third);
 294        case SHMCTL:
 295                /* sign extend shmid */
 296                return compat_sys_shmctl((int)first, second, compat_ptr(ptr));
 297
 298        default:
 299                return -ENOSYS;
 300        }
 301
 302        return -ENOSYS;
 303}
 304#endif
 305
 306/* Note: it is necessary to treat out_fd and in_fd as unsigned ints, 
 307 * with the corresponding cast to a signed int to insure that the 
 308 * proper conversion (sign extension) between the register representation of a signed int (msr in 32-bit mode)
 309 * and the register representation of a signed int (msr in 64-bit mode) is performed.
 310 */
 311asmlinkage long compat_sys_sendfile(u32 out_fd, u32 in_fd, compat_off_t __user * offset, u32 count)
 312{
 313        mm_segment_t old_fs = get_fs();
 314        int ret;
 315        off_t of;
 316        off_t __user *up;
 317
 318        if (offset && get_user(of, offset))
 319                return -EFAULT;
 320
 321        /* The __user pointer cast is valid because of the set_fs() */          
 322        set_fs(KERNEL_DS);
 323        up = offset ? (off_t __user *) &of : NULL;
 324        ret = sys_sendfile((int)out_fd, (int)in_fd, up, count);
 325        set_fs(old_fs);
 326        
 327        if (offset && put_user(of, offset))
 328                return -EFAULT;
 329                
 330        return ret;
 331}
 332
 333asmlinkage int compat_sys_sendfile64(int out_fd, int in_fd, compat_loff_t __user *offset, s32 count)
 334{
 335        mm_segment_t old_fs = get_fs();
 336        int ret;
 337        loff_t lof;
 338        loff_t __user *up;
 339        
 340        if (offset && get_user(lof, offset))
 341                return -EFAULT;
 342                
 343        /* The __user pointer cast is valid because of the set_fs() */          
 344        set_fs(KERNEL_DS);
 345        up = offset ? (loff_t __user *) &lof : NULL;
 346        ret = sys_sendfile64(out_fd, in_fd, up, count);
 347        set_fs(old_fs);
 348        
 349        if (offset && put_user(lof, offset))
 350                return -EFAULT;
 351                
 352        return ret;
 353}
 354
 355long compat_sys_execve(unsigned long a0, unsigned long a1, unsigned long a2,
 356                  unsigned long a3, unsigned long a4, unsigned long a5,
 357                  struct pt_regs *regs)
 358{
 359        int error;
 360        char * filename;
 361        
 362        filename = getname((char __user *) a0);
 363        error = PTR_ERR(filename);
 364        if (IS_ERR(filename))
 365                goto out;
 366        flush_fp_to_thread(current);
 367        flush_altivec_to_thread(current);
 368
 369        error = compat_do_execve(filename, compat_ptr(a1), compat_ptr(a2), regs);
 370
 371        if (error == 0) {
 372                task_lock(current);
 373                current->ptrace &= ~PT_DTRACE;
 374                task_unlock(current);
 375        }
 376        putname(filename);
 377
 378out:
 379        return error;
 380}
 381
 382/* Note: it is necessary to treat option as an unsigned int, 
 383 * with the corresponding cast to a signed int to insure that the 
 384 * proper conversion (sign extension) between the register representation of a signed int (msr in 32-bit mode)
 385 * and the register representation of a signed int (msr in 64-bit mode) is performed.
 386 */
 387asmlinkage long compat_sys_prctl(u32 option, u32 arg2, u32 arg3, u32 arg4, u32 arg5)
 388{
 389        return sys_prctl((int)option,
 390                         (unsigned long) arg2,
 391                         (unsigned long) arg3,
 392                         (unsigned long) arg4,
 393                         (unsigned long) arg5);
 394}
 395
 396/* Note: it is necessary to treat pid as an unsigned int, 
 397 * with the corresponding cast to a signed int to insure that the 
 398 * proper conversion (sign extension) between the register representation of a signed int (msr in 32-bit mode)
 399 * and the register representation of a signed int (msr in 64-bit mode) is performed.
 400 */
 401asmlinkage long compat_sys_sched_rr_get_interval(u32 pid, struct compat_timespec __user *interval)
 402{
 403        struct timespec t;
 404        int ret;
 405        mm_segment_t old_fs = get_fs ();
 406
 407        /* The __user pointer cast is valid because of the set_fs() */
 408        set_fs (KERNEL_DS);
 409        ret = sys_sched_rr_get_interval((int)pid, (struct timespec __user *) &t);
 410        set_fs (old_fs);
 411        if (put_compat_timespec(&t, interval))
 412                return -EFAULT;
 413        return ret;
 414}
 415
 416/* Note: it is necessary to treat mode as an unsigned int,
 417 * with the corresponding cast to a signed int to insure that the 
 418 * proper conversion (sign extension) between the register representation of a signed int (msr in 32-bit mode)
 419 * and the register representation of a signed int (msr in 64-bit mode) is performed.
 420 */
 421asmlinkage long compat_sys_access(const char __user * filename, u32 mode)
 422{
 423        return sys_access(filename, (int)mode);
 424}
 425
 426
 427/* Note: it is necessary to treat mode as an unsigned int,
 428 * with the corresponding cast to a signed int to insure that the 
 429 * proper conversion (sign extension) between the register representation of a signed int (msr in 32-bit mode)
 430 * and the register representation of a signed int (msr in 64-bit mode) is performed.
 431 */
 432asmlinkage long compat_sys_creat(const char __user * pathname, u32 mode)
 433{
 434        return sys_creat(pathname, (int)mode);
 435}
 436
 437
 438/* Note: it is necessary to treat pid and options as unsigned ints,
 439 * with the corresponding cast to a signed int to insure that the 
 440 * proper conversion (sign extension) between the register representation of a signed int (msr in 32-bit mode)
 441 * and the register representation of a signed int (msr in 64-bit mode) is performed.
 442 */
 443asmlinkage long compat_sys_waitpid(u32 pid, unsigned int __user * stat_addr, u32 options)
 444{
 445        return sys_waitpid((int)pid, stat_addr, (int)options);
 446}
 447
 448
 449/* Note: it is necessary to treat gidsetsize as an unsigned int,
 450 * with the corresponding cast to a signed int to insure that the 
 451 * proper conversion (sign extension) between the register representation of a signed int (msr in 32-bit mode)
 452 * and the register representation of a signed int (msr in 64-bit mode) is performed.
 453 */
 454asmlinkage long compat_sys_getgroups(u32 gidsetsize, gid_t __user *grouplist)
 455{
 456        return sys_getgroups((int)gidsetsize, grouplist);
 457}
 458
 459
 460/* Note: it is necessary to treat pid as an unsigned int,
 461 * with the corresponding cast to a signed int to insure that the 
 462 * proper conversion (sign extension) between the register representation of a signed int (msr in 32-bit mode)
 463 * and the register representation of a signed int (msr in 64-bit mode) is performed.
 464 */
 465asmlinkage long compat_sys_getpgid(u32 pid)
 466{
 467        return sys_getpgid((int)pid);
 468}
 469
 470
 471
 472/* Note: it is necessary to treat pid as an unsigned int,
 473 * with the corresponding cast to a signed int to insure that the 
 474 * proper conversion (sign extension) between the register representation of a signed int (msr in 32-bit mode)
 475 * and the register representation of a signed int (msr in 64-bit mode) is performed.
 476 */
 477asmlinkage long compat_sys_getsid(u32 pid)
 478{
 479        return sys_getsid((int)pid);
 480}
 481
 482
 483/* Note: it is necessary to treat pid and sig as unsigned ints,
 484 * with the corresponding cast to a signed int to insure that the 
 485 * proper conversion (sign extension) between the register representation of a signed int (msr in 32-bit mode)
 486 * and the register representation of a signed int (msr in 64-bit mode) is performed.
 487 */
 488asmlinkage long compat_sys_kill(u32 pid, u32 sig)
 489{
 490        return sys_kill((int)pid, (int)sig);
 491}
 492
 493
 494/* Note: it is necessary to treat mode as an unsigned int,
 495 * with the corresponding cast to a signed int to insure that the 
 496 * proper conversion (sign extension) between the register representation of a signed int (msr in 32-bit mode)
 497 * and the register representation of a signed int (msr in 64-bit mode) is performed.
 498 */
 499asmlinkage long compat_sys_mkdir(const char __user * pathname, u32 mode)
 500{
 501        return sys_mkdir(pathname, (int)mode);
 502}
 503
 504long compat_sys_nice(u32 increment)
 505{
 506        /* sign extend increment */
 507        return sys_nice((int)increment);
 508}
 509
 510off_t ppc32_lseek(unsigned int fd, u32 offset, unsigned int origin)
 511{
 512        /* sign extend n */
 513        return sys_lseek(fd, (int)offset, origin);
 514}
 515
 516/* Note: it is necessary to treat bufsiz as an unsigned int,
 517 * with the corresponding cast to a signed int to insure that the 
 518 * proper conversion (sign extension) between the register representation of a signed int (msr in 32-bit mode)
 519 * and the register representation of a signed int (msr in 64-bit mode) is performed.
 520 */
 521asmlinkage long compat_sys_readlink(const char __user * path, char __user * buf, u32 bufsiz)
 522{
 523        return sys_readlink(path, buf, (int)bufsiz);
 524}
 525
 526/* Note: it is necessary to treat option as an unsigned int,
 527 * with the corresponding cast to a signed int to insure that the 
 528 * proper conversion (sign extension) between the register representation of a signed int (msr in 32-bit mode)
 529 * and the register representation of a signed int (msr in 64-bit mode) is performed.
 530 */
 531asmlinkage long compat_sys_sched_get_priority_max(u32 policy)
 532{
 533        return sys_sched_get_priority_max((int)policy);
 534}
 535
 536
 537/* Note: it is necessary to treat policy as an unsigned int,
 538 * with the corresponding cast to a signed int to insure that the 
 539 * proper conversion (sign extension) between the register representation of a signed int (msr in 32-bit mode)
 540 * and the register representation of a signed int (msr in 64-bit mode) is performed.
 541 */
 542asmlinkage long compat_sys_sched_get_priority_min(u32 policy)
 543{
 544        return sys_sched_get_priority_min((int)policy);
 545}
 546
 547
 548/* Note: it is necessary to treat pid as an unsigned int,
 549 * with the corresponding cast to a signed int to insure that the 
 550 * proper conversion (sign extension) between the register representation of a signed int (msr in 32-bit mode)
 551 * and the register representation of a signed int (msr in 64-bit mode) is performed.
 552 */
 553asmlinkage long compat_sys_sched_getparam(u32 pid, struct sched_param __user *param)
 554{
 555        return sys_sched_getparam((int)pid, param);
 556}
 557
 558
 559/* Note: it is necessary to treat pid as an unsigned int,
 560 * with the corresponding cast to a signed int to insure that the 
 561 * proper conversion (sign extension) between the register representation of a signed int (msr in 32-bit mode)
 562 * and the register representation of a signed int (msr in 64-bit mode) is performed.
 563 */
 564asmlinkage long compat_sys_sched_getscheduler(u32 pid)
 565{
 566        return sys_sched_getscheduler((int)pid);
 567}
 568
 569
 570/* Note: it is necessary to treat pid as an unsigned int,
 571 * with the corresponding cast to a signed int to insure that the 
 572 * proper conversion (sign extension) between the register representation of a signed int (msr in 32-bit mode)
 573 * and the register representation of a signed int (msr in 64-bit mode) is performed.
 574 */
 575asmlinkage long compat_sys_sched_setparam(u32 pid, struct sched_param __user *param)
 576{
 577        return sys_sched_setparam((int)pid, param);
 578}
 579
 580
 581/* Note: it is necessary to treat pid and policy as unsigned ints,
 582 * with the corresponding cast to a signed int to insure that the 
 583 * proper conversion (sign extension) between the register representation of a signed int (msr in 32-bit mode)
 584 * and the register representation of a signed int (msr in 64-bit mode) is performed.
 585 */
 586asmlinkage long compat_sys_sched_setscheduler(u32 pid, u32 policy, struct sched_param __user *param)
 587{
 588        return sys_sched_setscheduler((int)pid, (int)policy, param);
 589}
 590
 591
 592/* Note: it is necessary to treat len as an unsigned int,
 593 * with the corresponding cast to a signed int to insure that the 
 594 * proper conversion (sign extension) between the register representation of a signed int (msr in 32-bit mode)
 595 * and the register representation of a signed int (msr in 64-bit mode) is performed.
 596 */
 597asmlinkage long compat_sys_setdomainname(char __user *name, u32 len)
 598{
 599        return sys_setdomainname(name, (int)len);
 600}
 601
 602
 603/* Note: it is necessary to treat gidsetsize as an unsigned int,
 604 * with the corresponding cast to a signed int to insure that the 
 605 * proper conversion (sign extension) between the register representation of a signed int (msr in 32-bit mode)
 606 * and the register representation of a signed int (msr in 64-bit mode) is performed.
 607 */
 608asmlinkage long compat_sys_setgroups(u32 gidsetsize, gid_t __user *grouplist)
 609{
 610        return sys_setgroups((int)gidsetsize, grouplist);
 611}
 612
 613
 614asmlinkage long compat_sys_sethostname(char __user *name, u32 len)
 615{
 616        /* sign extend len */
 617        return sys_sethostname(name, (int)len);
 618}
 619
 620
 621/* Note: it is necessary to treat pid and pgid as unsigned ints,
 622 * with the corresponding cast to a signed int to insure that the 
 623 * proper conversion (sign extension) between the register representation of a signed int (msr in 32-bit mode)
 624 * and the register representation of a signed int (msr in 64-bit mode) is performed.
 625 */
 626asmlinkage long compat_sys_setpgid(u32 pid, u32 pgid)
 627{
 628        return sys_setpgid((int)pid, (int)pgid);
 629}
 630
 631long compat_sys_getpriority(u32 which, u32 who)
 632{
 633        /* sign extend which and who */
 634        return sys_getpriority((int)which, (int)who);
 635}
 636
 637long compat_sys_setpriority(u32 which, u32 who, u32 niceval)
 638{
 639        /* sign extend which, who and niceval */
 640        return sys_setpriority((int)which, (int)who, (int)niceval);
 641}
 642
 643long compat_sys_ioprio_get(u32 which, u32 who)
 644{
 645        /* sign extend which and who */
 646        return sys_ioprio_get((int)which, (int)who);
 647}
 648
 649long compat_sys_ioprio_set(u32 which, u32 who, u32 ioprio)
 650{
 651        /* sign extend which, who and ioprio */
 652        return sys_ioprio_set((int)which, (int)who, (int)ioprio);
 653}
 654
 655/* Note: it is necessary to treat newmask as an unsigned int,
 656 * with the corresponding cast to a signed int to insure that the 
 657 * proper conversion (sign extension) between the register representation of a signed int (msr in 32-bit mode)
 658 * and the register representation of a signed int (msr in 64-bit mode) is performed.
 659 */
 660asmlinkage long compat_sys_ssetmask(u32 newmask)
 661{
 662        return sys_ssetmask((int) newmask);
 663}
 664
 665asmlinkage long compat_sys_syslog(u32 type, char __user * buf, u32 len)
 666{
 667        /* sign extend len */
 668        return sys_syslog(type, buf, (int)len);
 669}
 670
 671
 672/* Note: it is necessary to treat mask as an unsigned int,
 673 * with the corresponding cast to a signed int to insure that the 
 674 * proper conversion (sign extension) between the register representation of a signed int (msr in 32-bit mode)
 675 * and the register representation of a signed int (msr in 64-bit mode) is performed.
 676 */
 677asmlinkage long compat_sys_umask(u32 mask)
 678{
 679        return sys_umask((int)mask);
 680}
 681
 682#ifdef CONFIG_SYSCTL_SYSCALL
 683struct __sysctl_args32 {
 684        u32 name;
 685        int nlen;
 686        u32 oldval;
 687        u32 oldlenp;
 688        u32 newval;
 689        u32 newlen;
 690        u32 __unused[4];
 691};
 692
 693asmlinkage long compat_sys_sysctl(struct __sysctl_args32 __user *args)
 694{
 695        struct __sysctl_args32 tmp;
 696        int error;
 697        size_t oldlen;
 698        size_t __user *oldlenp = NULL;
 699        unsigned long addr = (((unsigned long)&args->__unused[0]) + 7) & ~7;
 700
 701        if (copy_from_user(&tmp, args, sizeof(tmp)))
 702                return -EFAULT;
 703
 704        if (tmp.oldval && tmp.oldlenp) {
 705                /* Duh, this is ugly and might not work if sysctl_args
 706                   is in read-only memory, but do_sysctl does indirectly
 707                   a lot of uaccess in both directions and we'd have to
 708                   basically copy the whole sysctl.c here, and
 709                   glibc's __sysctl uses rw memory for the structure
 710                   anyway.  */
 711                oldlenp = (size_t __user *)addr;
 712                if (get_user(oldlen, (compat_size_t __user *)compat_ptr(tmp.oldlenp)) ||
 713                    put_user(oldlen, oldlenp))
 714                        return -EFAULT;
 715        }
 716
 717        lock_kernel();
 718        error = do_sysctl(compat_ptr(tmp.name), tmp.nlen,
 719                          compat_ptr(tmp.oldval), oldlenp,
 720                          compat_ptr(tmp.newval), tmp.newlen);
 721        unlock_kernel();
 722        if (oldlenp) {
 723                if (!error) {
 724                        if (get_user(oldlen, oldlenp) ||
 725                            put_user(oldlen, (compat_size_t __user *)compat_ptr(tmp.oldlenp)))
 726                                error = -EFAULT;
 727                }
 728                copy_to_user(args->__unused, tmp.__unused, sizeof(tmp.__unused));
 729        }
 730        return error;
 731}
 732#endif
 733
 734unsigned long compat_sys_mmap2(unsigned long addr, size_t len,
 735                          unsigned long prot, unsigned long flags,
 736                          unsigned long fd, unsigned long pgoff)
 737{
 738        /* This should remain 12 even if PAGE_SIZE changes */
 739        return sys_mmap(addr, len, prot, flags, fd, pgoff << 12);
 740}
 741
 742long compat_sys_tgkill(u32 tgid, u32 pid, int sig)
 743{
 744        /* sign extend tgid, pid */
 745        return sys_tgkill((int)tgid, (int)pid, sig);
 746}
 747
 748/* 
 749 * long long munging:
 750 * The 32 bit ABI passes long longs in an odd even register pair.
 751 */
 752
 753compat_ssize_t compat_sys_pread64(unsigned int fd, char __user *ubuf, compat_size_t count,
 754                             u32 reg6, u32 poshi, u32 poslo)
 755{
 756        return sys_pread64(fd, ubuf, count, ((loff_t)poshi << 32) | poslo);
 757}
 758
 759compat_ssize_t compat_sys_pwrite64(unsigned int fd, char __user *ubuf, compat_size_t count,
 760                              u32 reg6, u32 poshi, u32 poslo)
 761{
 762        return sys_pwrite64(fd, ubuf, count, ((loff_t)poshi << 32) | poslo);
 763}
 764
 765compat_ssize_t compat_sys_readahead(int fd, u32 r4, u32 offhi, u32 offlo, u32 count)
 766{
 767        return sys_readahead(fd, ((loff_t)offhi << 32) | offlo, count);
 768}
 769
 770asmlinkage int compat_sys_truncate64(const char __user * path, u32 reg4,
 771                                unsigned long high, unsigned long low)
 772{
 773        return sys_truncate(path, (high << 32) | low);
 774}
 775
 776asmlinkage long compat_sys_fallocate(int fd, int mode, u32 offhi, u32 offlo,
 777                                     u32 lenhi, u32 lenlo)
 778{
 779        return sys_fallocate(fd, mode, ((loff_t)offhi << 32) | offlo,
 780                             ((loff_t)lenhi << 32) | lenlo);
 781}
 782
 783asmlinkage int compat_sys_ftruncate64(unsigned int fd, u32 reg4, unsigned long high,
 784                                 unsigned long low)
 785{
 786        return sys_ftruncate(fd, (high << 32) | low);
 787}
 788
 789long ppc32_lookup_dcookie(u32 cookie_high, u32 cookie_low, char __user *buf,
 790                          size_t len)
 791{
 792        return sys_lookup_dcookie((u64)cookie_high << 32 | cookie_low,
 793                                  buf, len);
 794}
 795
 796long ppc32_fadvise64(int fd, u32 unused, u32 offset_high, u32 offset_low,
 797                     size_t len, int advice)
 798{
 799        return sys_fadvise64(fd, (u64)offset_high << 32 | offset_low, len,
 800                             advice);
 801}
 802
 803asmlinkage long compat_sys_add_key(const char __user *_type,
 804                              const char __user *_description,
 805                              const void __user *_payload,
 806                              u32 plen,
 807                              u32 ringid)
 808{
 809        return sys_add_key(_type, _description, _payload, plen, ringid);
 810}
 811
 812asmlinkage long compat_sys_request_key(const char __user *_type,
 813                                  const char __user *_description,
 814                                  const char __user *_callout_info,
 815                                  u32 destringid)
 816{
 817        return sys_request_key(_type, _description, _callout_info, destringid);
 818}
 819
 820asmlinkage long compat_sys_sync_file_range2(int fd, unsigned int flags,
 821                                   unsigned offset_hi, unsigned offset_lo,
 822                                   unsigned nbytes_hi, unsigned nbytes_lo)
 823{
 824        loff_t offset = ((loff_t)offset_hi << 32) | offset_lo;
 825        loff_t nbytes = ((loff_t)nbytes_hi << 32) | nbytes_lo;
 826
 827        return sys_sync_file_range(fd, offset, nbytes, flags);
 828}
 829
lxr.linux.no kindly hosted by Redpill Linpro AS, provider of Linux consulting and operations services since 1995.