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 45 #include <asm/ptrace.h> 46 #include <asm/types.h> 47 #include <asm/ipc.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 56 struct old_linux_dirent32 { 57 u32 d_ino; 58 u32 d_offset; 59 unsigned short d_namlen; 60 char d_name[1]; 61 }; 62 63 struct readdir_callback32 { 64 struct old_linux_dirent32 __user * dirent; 65 int count; 66 }; 67 68 static 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 90 asmlinkage 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 108 out_putf: 109 fput(file); 110 out: 111 return error; 112 } 113 114 asmlinkage 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 122 int 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 */ 163 asmlinkage long compat_sys_sysfs(u32 option, u32 arg1, u32 arg2) 164 { 165 return sys_sysfs((int)option, arg1, arg2); 166 } 167 168 asmlinkage long compat_sys_pause(void) 169 { 170 current->state = TASK_INTERRUPTIBLE; 171 schedule(); 172 173 return -ERESTARTNOHAND; 174 } 175 176 static 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 190 static 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. */ 202 extern struct timezone sys_tz; 203 204 asmlinkage 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 222 asmlinkage 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 240 long 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 */ 311 asmlinkage 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 333 asmlinkage 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 355 long 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 378 out: 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 */ 387 asmlinkage 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 */ 401 asmlinkage 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 */ 421 asmlinkage 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 */ 432 asmlinkage 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 */ 443 asmlinkage 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 */ 454 asmlinkage 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 */ 465 asmlinkage 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 */ 477 asmlinkage 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 */ 488 asmlinkage 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 */ 499 asmlinkage long compat_sys_mkdir(const char __user * pathname, u32 mode) 500 { 501 return sys_mkdir(pathname, (int)mode); 502 } 503 504 long compat_sys_nice(u32 increment) 505 { 506 /* sign extend increment */ 507 return sys_nice((int)increment); 508 } 509 510 off_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 */ 521 asmlinkage 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 */ 531 asmlinkage 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 */ 542 asmlinkage 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 */ 553 asmlinkage 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 */ 564 asmlinkage 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 */ 575 asmlinkage 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 */ 586 asmlinkage 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 */ 597 asmlinkage 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 */ 608 asmlinkage long compat_sys_setgroups(u32 gidsetsize, gid_t __user *grouplist) 609 { 610 return sys_setgroups((int)gidsetsize, grouplist); 611 } 612 613 614 asmlinkage 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 */ 626 asmlinkage long compat_sys_setpgid(u32 pid, u32 pgid) 627 { 628 return sys_setpgid((int)pid, (int)pgid); 629 } 630 631 long compat_sys_getpriority(u32 which, u32 who) 632 { 633 /* sign extend which and who */ 634 return sys_getpriority((int)which, (int)who); 635 } 636 637 long 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 643 long 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 649 long 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 */ 660 asmlinkage long compat_sys_ssetmask(u32 newmask) 661 { 662 return sys_ssetmask((int) newmask); 663 } 664 665 asmlinkage 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 */ 677 asmlinkage long compat_sys_umask(u32 mask) 678 { 679 return sys_umask((int)mask); 680 } 681 682 #ifdef CONFIG_SYSCTL_SYSCALL 683 struct __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 693 asmlinkage 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 734 unsigned 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 742 long 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 753 compat_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 759 compat_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 765 compat_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 770 asmlinkage 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 776 asmlinkage 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 783 asmlinkage 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 789 long 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 796 long 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 803 asmlinkage 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 812 asmlinkage 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 820 asmlinkage 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