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