1 /* 2 * arch/s390x/kernel/linux32.c 3 * 4 * S390 version 5 * Copyright (C) 2000 IBM Deutschland Entwicklung GmbH, IBM Corporation 6 * Author(s): Martin Schwidefsky (schwidefsky@de.ibm.com), 7 * Gerhard Tonn (ton@de.ibm.com) 8 * Thomas Spatzier (tspat@de.ibm.com) 9 * 10 * Conversion between 31bit and 64bit native syscalls. 11 * 12 * Heavily inspired by the 32-bit Sparc compat code which is 13 * Copyright (C) 1997,1998 Jakub Jelinek (jj@sunsite.mff.cuni.cz) 14 * Copyright (C) 1997 David S. Miller (davem@caip.rutgers.edu) 15 * 16 */ 17 18 19 #include <linux/kernel.h> 20 #include <linux/sched.h> 21 #include <linux/fs.h> 22 #include <linux/mm.h> 23 #include <linux/file.h> 24 #include <linux/signal.h> 25 #include <linux/resource.h> 26 #include <linux/times.h> 27 #include <linux/utsname.h> 28 #include <linux/smp.h> 29 #include <linux/smp_lock.h> 30 #include <linux/sem.h> 31 #include <linux/msg.h> 32 #include <linux/shm.h> 33 #include <linux/slab.h> 34 #include <linux/uio.h> 35 #include <linux/nfs_fs.h> 36 #include <linux/quota.h> 37 #include <linux/module.h> 38 #include <linux/sunrpc/svc.h> 39 #include <linux/nfsd/nfsd.h> 40 #include <linux/nfsd/cache.h> 41 #include <linux/nfsd/xdr.h> 42 #include <linux/nfsd/syscall.h> 43 #include <linux/poll.h> 44 #include <linux/personality.h> 45 #include <linux/stat.h> 46 #include <linux/filter.h> 47 #include <linux/highmem.h> 48 #include <linux/highuid.h> 49 #include <linux/mman.h> 50 #include <linux/ipv6.h> 51 #include <linux/in.h> 52 #include <linux/icmpv6.h> 53 #include <linux/syscalls.h> 54 #include <linux/sysctl.h> 55 #include <linux/binfmts.h> 56 #include <linux/capability.h> 57 #include <linux/compat.h> 58 #include <linux/vfs.h> 59 #include <linux/ptrace.h> 60 #include <linux/fadvise.h> 61 #include <linux/ipc.h> 62 63 #include <asm/types.h> 64 #include <asm/uaccess.h> 65 66 #include <net/scm.h> 67 #include <net/sock.h> 68 69 #include "compat_linux.h" 70 71 long psw_user32_bits = (PSW_BASE32_BITS | PSW_MASK_DAT | PSW_ASC_HOME | 72 PSW_MASK_IO | PSW_MASK_EXT | PSW_MASK_MCHECK | 73 PSW_MASK_PSTATE | PSW_DEFAULT_KEY); 74 long psw32_user_bits = (PSW32_BASE_BITS | PSW32_MASK_DAT | PSW32_ASC_HOME | 75 PSW32_MASK_IO | PSW32_MASK_EXT | PSW32_MASK_MCHECK | 76 PSW32_MASK_PSTATE); 77 78 /* For this source file, we want overflow handling. */ 79 80 #undef high2lowuid 81 #undef high2lowgid 82 #undef low2highuid 83 #undef low2highgid 84 #undef SET_UID16 85 #undef SET_GID16 86 #undef NEW_TO_OLD_UID 87 #undef NEW_TO_OLD_GID 88 #undef SET_OLDSTAT_UID 89 #undef SET_OLDSTAT_GID 90 #undef SET_STAT_UID 91 #undef SET_STAT_GID 92 93 #define high2lowuid(uid) ((uid) > 65535) ? (u16)overflowuid : (u16)(uid) 94 #define high2lowgid(gid) ((gid) > 65535) ? (u16)overflowgid : (u16)(gid) 95 #define low2highuid(uid) ((uid) == (u16)-1) ? (uid_t)-1 : (uid_t)(uid) 96 #define low2highgid(gid) ((gid) == (u16)-1) ? (gid_t)-1 : (gid_t)(gid) 97 #define SET_UID16(var, uid) var = high2lowuid(uid) 98 #define SET_GID16(var, gid) var = high2lowgid(gid) 99 #define NEW_TO_OLD_UID(uid) high2lowuid(uid) 100 #define NEW_TO_OLD_GID(gid) high2lowgid(gid) 101 #define SET_OLDSTAT_UID(stat, uid) (stat).st_uid = high2lowuid(uid) 102 #define SET_OLDSTAT_GID(stat, gid) (stat).st_gid = high2lowgid(gid) 103 #define SET_STAT_UID(stat, uid) (stat).st_uid = high2lowuid(uid) 104 #define SET_STAT_GID(stat, gid) (stat).st_gid = high2lowgid(gid) 105 106 asmlinkage long sys32_chown16(const char __user * filename, u16 user, u16 group) 107 { 108 return sys_chown(filename, low2highuid(user), low2highgid(group)); 109 } 110 111 asmlinkage long sys32_lchown16(const char __user * filename, u16 user, u16 group) 112 { 113 return sys_lchown(filename, low2highuid(user), low2highgid(group)); 114 } 115 116 asmlinkage long sys32_fchown16(unsigned int fd, u16 user, u16 group) 117 { 118 return sys_fchown(fd, low2highuid(user), low2highgid(group)); 119 } 120 121 asmlinkage long sys32_setregid16(u16 rgid, u16 egid) 122 { 123 return sys_setregid(low2highgid(rgid), low2highgid(egid)); 124 } 125 126 asmlinkage long sys32_setgid16(u16 gid) 127 { 128 return sys_setgid((gid_t)gid); 129 } 130 131 asmlinkage long sys32_setreuid16(u16 ruid, u16 euid) 132 { 133 return sys_setreuid(low2highuid(ruid), low2highuid(euid)); 134 } 135 136 asmlinkage long sys32_setuid16(u16 uid) 137 { 138 return sys_setuid((uid_t)uid); 139 } 140 141 asmlinkage long sys32_setresuid16(u16 ruid, u16 euid, u16 suid) 142 { 143 return sys_setresuid(low2highuid(ruid), low2highuid(euid), 144 low2highuid(suid)); 145 } 146 147 asmlinkage long sys32_getresuid16(u16 __user *ruid, u16 __user *euid, u16 __user *suid) 148 { 149 int retval; 150 151 if (!(retval = put_user(high2lowuid(current->cred->uid), ruid)) && 152 !(retval = put_user(high2lowuid(current->cred->euid), euid))) 153 retval = put_user(high2lowuid(current->cred->suid), suid); 154 155 return retval; 156 } 157 158 asmlinkage long sys32_setresgid16(u16 rgid, u16 egid, u16 sgid) 159 { 160 return sys_setresgid(low2highgid(rgid), low2highgid(egid), 161 low2highgid(sgid)); 162 } 163 164 asmlinkage long sys32_getresgid16(u16 __user *rgid, u16 __user *egid, u16 __user *sgid) 165 { 166 int retval; 167 168 if (!(retval = put_user(high2lowgid(current->cred->gid), rgid)) && 169 !(retval = put_user(high2lowgid(current->cred->egid), egid))) 170 retval = put_user(high2lowgid(current->cred->sgid), sgid); 171 172 return retval; 173 } 174 175 asmlinkage long sys32_setfsuid16(u16 uid) 176 { 177 return sys_setfsuid((uid_t)uid); 178 } 179 180 asmlinkage long sys32_setfsgid16(u16 gid) 181 { 182 return sys_setfsgid((gid_t)gid); 183 } 184 185 static int groups16_to_user(u16 __user *grouplist, struct group_info *group_info) 186 { 187 int i; 188 u16 group; 189 190 for (i = 0; i < group_info->ngroups; i++) { 191 group = (u16)GROUP_AT(group_info, i); 192 if (put_user(group, grouplist+i)) 193 return -EFAULT; 194 } 195 196 return 0; 197 } 198 199 static int groups16_from_user(struct group_info *group_info, u16 __user *grouplist) 200 { 201 int i; 202 u16 group; 203 204 for (i = 0; i < group_info->ngroups; i++) { 205 if (get_user(group, grouplist+i)) 206 return -EFAULT; 207 GROUP_AT(group_info, i) = (gid_t)group; 208 } 209 210 return 0; 211 } 212 213 asmlinkage long sys32_getgroups16(int gidsetsize, u16 __user *grouplist) 214 { 215 int i; 216 217 if (gidsetsize < 0) 218 return -EINVAL; 219 220 get_group_info(current->cred->group_info); 221 i = current->cred->group_info->ngroups; 222 if (gidsetsize) { 223 if (i > gidsetsize) { 224 i = -EINVAL; 225 goto out; 226 } 227 if (groups16_to_user(grouplist, current->cred->group_info)) { 228 i = -EFAULT; 229 goto out; 230 } 231 } 232 out: 233 put_group_info(current->cred->group_info); 234 return i; 235 } 236 237 asmlinkage long sys32_setgroups16(int gidsetsize, u16 __user *grouplist) 238 { 239 struct group_info *group_info; 240 int retval; 241 242 if (!capable(CAP_SETGID)) 243 return -EPERM; 244 if ((unsigned)gidsetsize > NGROUPS_MAX) 245 return -EINVAL; 246 247 group_info = groups_alloc(gidsetsize); 248 if (!group_info) 249 return -ENOMEM; 250 retval = groups16_from_user(group_info, grouplist); 251 if (retval) { 252 put_group_info(group_info); 253 return retval; 254 } 255 256 retval = set_current_groups(group_info); 257 put_group_info(group_info); 258 259 return retval; 260 } 261 262 asmlinkage long sys32_getuid16(void) 263 { 264 return high2lowuid(current->cred->uid); 265 } 266 267 asmlinkage long sys32_geteuid16(void) 268 { 269 return high2lowuid(current->cred->euid); 270 } 271 272 asmlinkage long sys32_getgid16(void) 273 { 274 return high2lowgid(current->cred->gid); 275 } 276 277 asmlinkage long sys32_getegid16(void) 278 { 279 return high2lowgid(current->cred->egid); 280 } 281 282 /* 283 * sys32_ipc() is the de-multiplexer for the SysV IPC calls in 32bit emulation. 284 * 285 * This is really horribly ugly. 286 */ 287 #ifdef CONFIG_SYSVIPC 288 asmlinkage long sys32_ipc(u32 call, int first, int second, int third, u32 ptr) 289 { 290 if (call >> 16) /* hack for backward compatibility */ 291 return -EINVAL; 292 293 call &= 0xffff; 294 295 switch (call) { 296 case SEMTIMEDOP: 297 return compat_sys_semtimedop(first, compat_ptr(ptr), 298 second, compat_ptr(third)); 299 case SEMOP: 300 /* struct sembuf is the same on 32 and 64bit :)) */ 301 return sys_semtimedop(first, compat_ptr(ptr), 302 second, NULL); 303 case SEMGET: 304 return sys_semget(first, second, third); 305 case SEMCTL: 306 return compat_sys_semctl(first, second, third, 307 compat_ptr(ptr)); 308 case MSGSND: 309 return compat_sys_msgsnd(first, second, third, 310 compat_ptr(ptr)); 311 case MSGRCV: 312 return compat_sys_msgrcv(first, second, 0, third, 313 0, compat_ptr(ptr)); 314 case MSGGET: 315 return sys_msgget((key_t) first, second); 316 case MSGCTL: 317 return compat_sys_msgctl(first, second, compat_ptr(ptr)); 318 case SHMAT: 319 return compat_sys_shmat(first, second, third, 320 0, compat_ptr(ptr)); 321 case SHMDT: 322 return sys_shmdt(compat_ptr(ptr)); 323 case SHMGET: 324 return sys_shmget(first, (unsigned)second, third); 325 case SHMCTL: 326 return compat_sys_shmctl(first, second, compat_ptr(ptr)); 327 } 328 329 return -ENOSYS; 330 } 331 #endif 332 333 asmlinkage long sys32_truncate64(const char __user * path, unsigned long high, unsigned long low) 334 { 335 if ((int)high < 0) 336 return -EINVAL; 337 else 338 return sys_truncate(path, (high << 32) | low); 339 } 340 341 asmlinkage long sys32_ftruncate64(unsigned int fd, unsigned long high, unsigned long low) 342 { 343 if ((int)high < 0) 344 return -EINVAL; 345 else 346 return sys_ftruncate(fd, (high << 32) | low); 347 } 348 349 asmlinkage long sys32_sched_rr_get_interval(compat_pid_t pid, 350 struct compat_timespec __user *interval) 351 { 352 struct timespec t; 353 int ret; 354 mm_segment_t old_fs = get_fs (); 355 356 set_fs (KERNEL_DS); 357 ret = sys_sched_rr_get_interval(pid, 358 (struct timespec __force __user *) &t); 359 set_fs (old_fs); 360 if (put_compat_timespec(&t, interval)) 361 return -EFAULT; 362 return ret; 363 } 364 365 asmlinkage long sys32_rt_sigprocmask(int how, compat_sigset_t __user *set, 366 compat_sigset_t __user *oset, size_t sigsetsize) 367 { 368 sigset_t s; 369 compat_sigset_t s32; 370 int ret; 371 mm_segment_t old_fs = get_fs(); 372 373 if (set) { 374 if (copy_from_user (&s32, set, sizeof(compat_sigset_t))) 375 return -EFAULT; 376 switch (_NSIG_WORDS) { 377 case 4: s.sig[3] = s32.sig[6] | (((long)s32.sig[7]) << 32); 378 case 3: s.sig[2] = s32.sig[4] | (((long)s32.sig[5]) << 32); 379 case 2: s.sig[1] = s32.sig[2] | (((long)s32.sig[3]) << 32); 380 case 1: s.sig[0] = s32.sig[0] | (((long)s32.sig[1]) << 32); 381 } 382 } 383 set_fs (KERNEL_DS); 384 ret = sys_rt_sigprocmask(how, 385 set ? (sigset_t __force __user *) &s : NULL, 386 oset ? (sigset_t __force __user *) &s : NULL, 387 sigsetsize); 388 set_fs (old_fs); 389 if (ret) return ret; 390 if (oset) { 391 switch (_NSIG_WORDS) { 392 case 4: s32.sig[7] = (s.sig[3] >> 32); s32.sig[6] = s.sig[3]; 393 case 3: s32.sig[5] = (s.sig[2] >> 32); s32.sig[4] = s.sig[2]; 394 case 2: s32.sig[3] = (s.sig[1] >> 32); s32.sig[2] = s.sig[1]; 395 case 1: s32.sig[1] = (s.sig[0] >> 32); s32.sig[0] = s.sig[0]; 396 } 397 if (copy_to_user (oset, &s32, sizeof(compat_sigset_t))) 398 return -EFAULT; 399 } 400 return 0; 401 } 402 403 asmlinkage long sys32_rt_sigpending(compat_sigset_t __user *set, 404 size_t sigsetsize) 405 { 406 sigset_t s; 407 compat_sigset_t s32; 408 int ret; 409 mm_segment_t old_fs = get_fs(); 410 411 set_fs (KERNEL_DS); 412 ret = sys_rt_sigpending((sigset_t __force __user *) &s, sigsetsize); 413 set_fs (old_fs); 414 if (!ret) { 415 switch (_NSIG_WORDS) { 416 case 4: s32.sig[7] = (s.sig[3] >> 32); s32.sig[6] = s.sig[3]; 417 case 3: s32.sig[5] = (s.sig[2] >> 32); s32.sig[4] = s.sig[2]; 418 case 2: s32.sig[3] = (s.sig[1] >> 32); s32.sig[2] = s.sig[1]; 419 case 1: s32.sig[1] = (s.sig[0] >> 32); s32.sig[0] = s.sig[0]; 420 } 421 if (copy_to_user (set, &s32, sizeof(compat_sigset_t))) 422 return -EFAULT; 423 } 424 return ret; 425 } 426 427 asmlinkage long 428 sys32_rt_sigqueueinfo(int pid, int sig, compat_siginfo_t __user *uinfo) 429 { 430 siginfo_t info; 431 int ret; 432 mm_segment_t old_fs = get_fs(); 433 434 if (copy_siginfo_from_user32(&info, uinfo)) 435 return -EFAULT; 436 set_fs (KERNEL_DS); 437 ret = sys_rt_sigqueueinfo(pid, sig, (siginfo_t __force __user *) &info); 438 set_fs (old_fs); 439 return ret; 440 } 441 442 /* 443 * sys32_execve() executes a new program after the asm stub has set 444 * things up for us. This should basically do what I want it to. 445 */ 446 asmlinkage long sys32_execve(void) 447 { 448 struct pt_regs *regs = task_pt_regs(current); 449 char *filename; 450 unsigned long result; 451 int rc; 452 453 filename = getname(compat_ptr(regs->orig_gpr2)); 454 if (IS_ERR(filename)) { 455 result = PTR_ERR(filename); 456 goto out; 457 } 458 rc = compat_do_execve(filename, compat_ptr(regs->gprs[3]), 459 compat_ptr(regs->gprs[4]), regs); 460 if (rc) { 461 result = rc; 462 goto out_putname; 463 } 464 task_lock(current); 465 current->ptrace &= ~PT_DTRACE; 466 task_unlock(current); 467 current->thread.fp_regs.fpc=0; 468 asm volatile("sfpc %0,0" : : "d" (0)); 469 result = regs->gprs[2]; 470 out_putname: 471 putname(filename); 472 out: 473 return result; 474 } 475 476 477 #ifdef CONFIG_MODULES 478 479 asmlinkage long 480 sys32_init_module(void __user *umod, unsigned long len, 481 const char __user *uargs) 482 { 483 return sys_init_module(umod, len, uargs); 484 } 485 486 asmlinkage long 487 sys32_delete_module(const char __user *name_user, unsigned int flags) 488 { 489 return sys_delete_module(name_user, flags); 490 } 491 492 #else /* CONFIG_MODULES */ 493 494 asmlinkage long 495 sys32_init_module(void __user *umod, unsigned long len, 496 const char __user *uargs) 497 { 498 return -ENOSYS; 499 } 500 501 asmlinkage long 502 sys32_delete_module(const char __user *name_user, unsigned int flags) 503 { 504 return -ENOSYS; 505 } 506 507 #endif /* CONFIG_MODULES */ 508 509 asmlinkage long sys32_pread64(unsigned int fd, char __user *ubuf, 510 size_t count, u32 poshi, u32 poslo) 511 { 512 if ((compat_ssize_t) count < 0) 513 return -EINVAL; 514 return sys_pread64(fd, ubuf, count, ((loff_t)AA(poshi) << 32) | AA(poslo)); 515 } 516 517 asmlinkage long sys32_pwrite64(unsigned int fd, const char __user *ubuf, 518 size_t count, u32 poshi, u32 poslo) 519 { 520 if ((compat_ssize_t) count < 0) 521 return -EINVAL; 522 return sys_pwrite64(fd, ubuf, count, ((loff_t)AA(poshi) << 32) | AA(poslo)); 523 } 524 525 asmlinkage compat_ssize_t sys32_readahead(int fd, u32 offhi, u32 offlo, s32 count) 526 { 527 return sys_readahead(fd, ((loff_t)AA(offhi) << 32) | AA(offlo), count); 528 } 529 530 asmlinkage long sys32_sendfile(int out_fd, int in_fd, compat_off_t __user *offset, size_t count) 531 { 532 mm_segment_t old_fs = get_fs(); 533 int ret; 534 off_t of; 535 536 if (offset && get_user(of, offset)) 537 return -EFAULT; 538 539 set_fs(KERNEL_DS); 540 ret = sys_sendfile(out_fd, in_fd, 541 offset ? (off_t __force __user *) &of : NULL, count); 542 set_fs(old_fs); 543 544 if (offset && put_user(of, offset)) 545 return -EFAULT; 546 547 return ret; 548 } 549 550 asmlinkage long sys32_sendfile64(int out_fd, int in_fd, 551 compat_loff_t __user *offset, s32 count) 552 { 553 mm_segment_t old_fs = get_fs(); 554 int ret; 555 loff_t lof; 556 557 if (offset && get_user(lof, offset)) 558 return -EFAULT; 559 560 set_fs(KERNEL_DS); 561 ret = sys_sendfile64(out_fd, in_fd, 562 offset ? (loff_t __force __user *) &lof : NULL, 563 count); 564 set_fs(old_fs); 565 566 if (offset && put_user(lof, offset)) 567 return -EFAULT; 568 569 return ret; 570 } 571 572 #ifdef CONFIG_SYSCTL_SYSCALL 573 struct __sysctl_args32 { 574 u32 name; 575 int nlen; 576 u32 oldval; 577 u32 oldlenp; 578 u32 newval; 579 u32 newlen; 580 u32 __unused[4]; 581 }; 582 583 asmlinkage long sys32_sysctl(struct __sysctl_args32 __user *args) 584 { 585 struct __sysctl_args32 tmp; 586 int error; 587 size_t oldlen; 588 size_t __user *oldlenp = NULL; 589 unsigned long addr = (((unsigned long)&args->__unused[0]) + 7) & ~7; 590 591 if (copy_from_user(&tmp, args, sizeof(tmp))) 592 return -EFAULT; 593 594 if (tmp.oldval && tmp.oldlenp) { 595 /* Duh, this is ugly and might not work if sysctl_args 596 is in read-only memory, but do_sysctl does indirectly 597 a lot of uaccess in both directions and we'd have to 598 basically copy the whole sysctl.c here, and 599 glibc's __sysctl uses rw memory for the structure 600 anyway. */ 601 if (get_user(oldlen, (u32 __user *)compat_ptr(tmp.oldlenp)) || 602 put_user(oldlen, (size_t __user *)addr)) 603 return -EFAULT; 604 oldlenp = (size_t __user *)addr; 605 } 606 607 lock_kernel(); 608 error = do_sysctl(compat_ptr(tmp.name), tmp.nlen, compat_ptr(tmp.oldval), 609 oldlenp, compat_ptr(tmp.newval), tmp.newlen); 610 unlock_kernel(); 611 if (oldlenp) { 612 if (!error) { 613 if (get_user(oldlen, (size_t __user *)addr) || 614 put_user(oldlen, (u32 __user *)compat_ptr(tmp.oldlenp))) 615 error = -EFAULT; 616 } 617 if (copy_to_user(args->__unused, tmp.__unused, 618 sizeof(tmp.__unused))) 619 error = -EFAULT; 620 } 621 return error; 622 } 623 #endif 624 625 struct stat64_emu31 { 626 unsigned long long st_dev; 627 unsigned int __pad1; 628 #define STAT64_HAS_BROKEN_ST_INO 1 629 u32 __st_ino; 630 unsigned int st_mode; 631 unsigned int st_nlink; 632 u32 st_uid; 633 u32 st_gid; 634 unsigned long long st_rdev; 635 unsigned int __pad3; 636 long st_size; 637 u32 st_blksize; 638 unsigned char __pad4[4]; 639 u32 __pad5; /* future possible st_blocks high bits */ 640 u32 st_blocks; /* Number 512-byte blocks allocated. */ 641 u32 st_atime; 642 u32 __pad6; 643 u32 st_mtime; 644 u32 __pad7; 645 u32 st_ctime; 646 u32 __pad8; /* will be high 32 bits of ctime someday */ 647 unsigned long st_ino; 648 }; 649 650 static int cp_stat64(struct stat64_emu31 __user *ubuf, struct kstat *stat) 651 { 652 struct stat64_emu31 tmp; 653 654 memset(&tmp, 0, sizeof(tmp)); 655 656 tmp.st_dev = huge_encode_dev(stat->dev); 657 tmp.st_ino = stat->ino; 658 tmp.__st_ino = (u32)stat->ino; 659 tmp.st_mode = stat->mode; 660 tmp.st_nlink = (unsigned int)stat->nlink; 661 tmp.st_uid = stat->uid; 662 tmp.st_gid = stat->gid; 663 tmp.st_rdev = huge_encode_dev(stat->rdev); 664 tmp.st_size = stat->size; 665 tmp.st_blksize = (u32)stat->blksize; 666 tmp.st_blocks = (u32)stat->blocks; 667 tmp.st_atime = (u32)stat->atime.tv_sec; 668 tmp.st_mtime = (u32)stat->mtime.tv_sec; 669 tmp.st_ctime = (u32)stat->ctime.tv_sec; 670 671 return copy_to_user(ubuf,&tmp,sizeof(tmp)) ? -EFAULT : 0; 672 } 673 674 asmlinkage long sys32_stat64(char __user * filename, struct stat64_emu31 __user * statbuf) 675 { 676 struct kstat stat; 677 int ret = vfs_stat(filename, &stat); 678 if (!ret) 679 ret = cp_stat64(statbuf, &stat); 680 return ret; 681 } 682 683 asmlinkage long sys32_lstat64(char __user * filename, struct stat64_emu31 __user * statbuf) 684 { 685 struct kstat stat; 686 int ret = vfs_lstat(filename, &stat); 687 if (!ret) 688 ret = cp_stat64(statbuf, &stat); 689 return ret; 690 } 691 692 asmlinkage long sys32_fstat64(unsigned long fd, struct stat64_emu31 __user * statbuf) 693 { 694 struct kstat stat; 695 int ret = vfs_fstat(fd, &stat); 696 if (!ret) 697 ret = cp_stat64(statbuf, &stat); 698 return ret; 699 } 700 701 asmlinkage long sys32_fstatat64(unsigned int dfd, char __user *filename, 702 struct stat64_emu31 __user* statbuf, int flag) 703 { 704 struct kstat stat; 705 int error = -EINVAL; 706 707 if ((flag & ~AT_SYMLINK_NOFOLLOW) != 0) 708 goto out; 709 710 if (flag & AT_SYMLINK_NOFOLLOW) 711 error = vfs_lstat_fd(dfd, filename, &stat); 712 else 713 error = vfs_stat_fd(dfd, filename, &stat); 714 715 if (!error) 716 error = cp_stat64(statbuf, &stat); 717 out: 718 return error; 719 } 720 721 /* 722 * Linux/i386 didn't use to be able to handle more than 723 * 4 system call parameters, so these system calls used a memory 724 * block for parameter passing.. 725 */ 726 727 struct mmap_arg_struct_emu31 { 728 u32 addr; 729 u32 len; 730 u32 prot; 731 u32 flags; 732 u32 fd; 733 u32 offset; 734 }; 735 736 /* common code for old and new mmaps */ 737 static inline long do_mmap2( 738 unsigned long addr, unsigned long len, 739 unsigned long prot, unsigned long flags, 740 unsigned long fd, unsigned long pgoff) 741 { 742 struct file * file = NULL; 743 unsigned long error = -EBADF; 744 745 flags &= ~(MAP_EXECUTABLE | MAP_DENYWRITE); 746 if (!(flags & MAP_ANONYMOUS)) { 747 file = fget(fd); 748 if (!file) 749 goto out; 750 } 751 752 down_write(¤t->mm->mmap_sem); 753 error = do_mmap_pgoff(file, addr, len, prot, flags, pgoff); 754 if (!IS_ERR((void *) error) && error + len >= 0x80000000ULL) { 755 /* Result is out of bounds. */ 756 do_munmap(current->mm, addr, len); 757 error = -ENOMEM; 758 } 759 up_write(¤t->mm->mmap_sem); 760 761 if (file) 762 fput(file); 763 out: 764 return error; 765 } 766 767 768 asmlinkage unsigned long 769 old32_mmap(struct mmap_arg_struct_emu31 __user *arg) 770 { 771 struct mmap_arg_struct_emu31 a; 772 int error = -EFAULT; 773 774 if (copy_from_user(&a, arg, sizeof(a))) 775 goto out; 776 777 error = -EINVAL; 778 if (a.offset & ~PAGE_MASK) 779 goto out; 780 781 error = do_mmap2(a.addr, a.len, a.prot, a.flags, a.fd, a.offset >> PAGE_SHIFT); 782 out: 783 return error; 784 } 785 786 asmlinkage long 787 sys32_mmap2(struct mmap_arg_struct_emu31 __user *arg) 788 { 789 struct mmap_arg_struct_emu31 a; 790 int error = -EFAULT; 791 792 if (copy_from_user(&a, arg, sizeof(a))) 793 goto out; 794 error = do_mmap2(a.addr, a.len, a.prot, a.flags, a.fd, a.offset); 795 out: 796 return error; 797 } 798 799 asmlinkage long sys32_read(unsigned int fd, char __user * buf, size_t count) 800 { 801 if ((compat_ssize_t) count < 0) 802 return -EINVAL; 803 804 return sys_read(fd, buf, count); 805 } 806 807 asmlinkage long sys32_write(unsigned int fd, char __user * buf, size_t count) 808 { 809 if ((compat_ssize_t) count < 0) 810 return -EINVAL; 811 812 return sys_write(fd, buf, count); 813 } 814 815 asmlinkage long sys32_clone(void) 816 { 817 struct pt_regs *regs = task_pt_regs(current); 818 unsigned long clone_flags; 819 unsigned long newsp; 820 int __user *parent_tidptr, *child_tidptr; 821 822 clone_flags = regs->gprs[3] & 0xffffffffUL; 823 newsp = regs->orig_gpr2 & 0x7fffffffUL; 824 parent_tidptr = compat_ptr(regs->gprs[4]); 825 child_tidptr = compat_ptr(regs->gprs[5]); 826 if (!newsp) 827 newsp = regs->gprs[15]; 828 return do_fork(clone_flags, newsp, regs, 0, 829 parent_tidptr, child_tidptr); 830 } 831 832 /* 833 * 31 bit emulation wrapper functions for sys_fadvise64/fadvise64_64. 834 * These need to rewrite the advise values for POSIX_FADV_{DONTNEED,NOREUSE} 835 * because the 31 bit values differ from the 64 bit values. 836 */ 837 838 asmlinkage long 839 sys32_fadvise64(int fd, loff_t offset, size_t len, int advise) 840 { 841 if (advise == 4) 842 advise = POSIX_FADV_DONTNEED; 843 else if (advise == 5) 844 advise = POSIX_FADV_NOREUSE; 845 return sys_fadvise64(fd, offset, len, advise); 846 } 847 848 struct fadvise64_64_args { 849 int fd; 850 long long offset; 851 long long len; 852 int advice; 853 }; 854 855 asmlinkage long 856 sys32_fadvise64_64(struct fadvise64_64_args __user *args) 857 { 858 struct fadvise64_64_args a; 859 860 if ( copy_from_user(&a, args, sizeof(a)) ) 861 return -EFAULT; 862 if (a.advice == 4) 863 a.advice = POSIX_FADV_DONTNEED; 864 else if (a.advice == 5) 865 a.advice = POSIX_FADV_NOREUSE; 866 return sys_fadvise64_64(a.fd, a.offset, a.len, a.advice); 867 } 868