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->uid), ruid)) && 152 !(retval = put_user(high2lowuid(current->euid), euid))) 153 retval = put_user(high2lowuid(current->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->gid), rgid)) && 169 !(retval = put_user(high2lowgid(current->egid), egid))) 170 retval = put_user(high2lowgid(current->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->group_info); 221 i = current->group_info->ngroups; 222 if (gidsetsize) { 223 if (i > gidsetsize) { 224 i = -EINVAL; 225 goto out; 226 } 227 if (groups16_to_user(grouplist, current->group_info)) { 228 i = -EFAULT; 229 goto out; 230 } 231 } 232 out: 233 put_group_info(current->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->uid); 265 } 266 267 asmlinkage long sys32_geteuid16(void) 268 { 269 return high2lowuid(current->euid); 270 } 271 272 asmlinkage long sys32_getgid16(void) 273 { 274 return high2lowgid(current->gid); 275 } 276 277 asmlinkage long sys32_getegid16(void) 278 { 279 return high2lowgid(current->egid); 280 } 281 282 /* 32-bit timeval and related flotsam. */ 283 284 static inline long get_tv32(struct timeval *o, struct compat_timeval __user *i) 285 { 286 return (!access_ok(VERIFY_READ, o, sizeof(*o)) || 287 (__get_user(o->tv_sec, &i->tv_sec) || 288 __get_user(o->tv_usec, &i->tv_usec))); 289 } 290 291 static inline long put_tv32(struct compat_timeval __user *o, struct timeval *i) 292 { 293 return (!access_ok(VERIFY_WRITE, o, sizeof(*o)) || 294 (__put_user(i->tv_sec, &o->tv_sec) || 295 __put_user(i->tv_usec, &o->tv_usec))); 296 } 297 298 /* 299 * sys32_ipc() is the de-multiplexer for the SysV IPC calls in 32bit emulation. 300 * 301 * This is really horribly ugly. 302 */ 303 #ifdef CONFIG_SYSVIPC 304 asmlinkage long sys32_ipc(u32 call, int first, int second, int third, u32 ptr) 305 { 306 if (call >> 16) /* hack for backward compatibility */ 307 return -EINVAL; 308 309 call &= 0xffff; 310 311 switch (call) { 312 case SEMTIMEDOP: 313 return compat_sys_semtimedop(first, compat_ptr(ptr), 314 second, compat_ptr(third)); 315 case SEMOP: 316 /* struct sembuf is the same on 32 and 64bit :)) */ 317 return sys_semtimedop(first, compat_ptr(ptr), 318 second, NULL); 319 case SEMGET: 320 return sys_semget(first, second, third); 321 case SEMCTL: 322 return compat_sys_semctl(first, second, third, 323 compat_ptr(ptr)); 324 case MSGSND: 325 return compat_sys_msgsnd(first, second, third, 326 compat_ptr(ptr)); 327 case MSGRCV: 328 return compat_sys_msgrcv(first, second, 0, third, 329 0, compat_ptr(ptr)); 330 case MSGGET: 331 return sys_msgget((key_t) first, second); 332 case MSGCTL: 333 return compat_sys_msgctl(first, second, compat_ptr(ptr)); 334 case SHMAT: 335 return compat_sys_shmat(first, second, third, 336 0, compat_ptr(ptr)); 337 case SHMDT: 338 return sys_shmdt(compat_ptr(ptr)); 339 case SHMGET: 340 return sys_shmget(first, (unsigned)second, third); 341 case SHMCTL: 342 return compat_sys_shmctl(first, second, compat_ptr(ptr)); 343 } 344 345 return -ENOSYS; 346 } 347 #endif 348 349 asmlinkage long sys32_truncate64(const char __user * path, unsigned long high, unsigned long low) 350 { 351 if ((int)high < 0) 352 return -EINVAL; 353 else 354 return sys_truncate(path, (high << 32) | low); 355 } 356 357 asmlinkage long sys32_ftruncate64(unsigned int fd, unsigned long high, unsigned long low) 358 { 359 if ((int)high < 0) 360 return -EINVAL; 361 else 362 return sys_ftruncate(fd, (high << 32) | low); 363 } 364 365 int cp_compat_stat(struct kstat *stat, struct compat_stat __user *statbuf) 366 { 367 compat_ino_t ino; 368 int err; 369 370 if (!old_valid_dev(stat->dev) || !old_valid_dev(stat->rdev)) 371 return -EOVERFLOW; 372 373 ino = stat->ino; 374 if (sizeof(ino) < sizeof(stat->ino) && ino != stat->ino) 375 return -EOVERFLOW; 376 377 err = put_user(old_encode_dev(stat->dev), &statbuf->st_dev); 378 err |= put_user(stat->ino, &statbuf->st_ino); 379 err |= put_user(stat->mode, &statbuf->st_mode); 380 err |= put_user(stat->nlink, &statbuf->st_nlink); 381 err |= put_user(high2lowuid(stat->uid), &statbuf->st_uid); 382 err |= put_user(high2lowgid(stat->gid), &statbuf->st_gid); 383 err |= put_user(old_encode_dev(stat->rdev), &statbuf->st_rdev); 384 err |= put_user(stat->size, &statbuf->st_size); 385 err |= put_user(stat->atime.tv_sec, &statbuf->st_atime); 386 err |= put_user(stat->atime.tv_nsec, &statbuf->st_atime_nsec); 387 err |= put_user(stat->mtime.tv_sec, &statbuf->st_mtime); 388 err |= put_user(stat->mtime.tv_nsec, &statbuf->st_mtime_nsec); 389 err |= put_user(stat->ctime.tv_sec, &statbuf->st_ctime); 390 err |= put_user(stat->ctime.tv_nsec, &statbuf->st_ctime_nsec); 391 err |= put_user(stat->blksize, &statbuf->st_blksize); 392 err |= put_user(stat->blocks, &statbuf->st_blocks); 393 /* fixme 394 err |= put_user(0, &statbuf->__unused4[0]); 395 err |= put_user(0, &statbuf->__unused4[1]); 396 */ 397 return err; 398 } 399 400 asmlinkage long sys32_sched_rr_get_interval(compat_pid_t pid, 401 struct compat_timespec __user *interval) 402 { 403 struct timespec t; 404 int ret; 405 mm_segment_t old_fs = get_fs (); 406 407 set_fs (KERNEL_DS); 408 ret = sys_sched_rr_get_interval(pid, 409 (struct timespec __force __user *) &t); 410 set_fs (old_fs); 411 if (put_compat_timespec(&t, interval)) 412 return -EFAULT; 413 return ret; 414 } 415 416 asmlinkage long sys32_rt_sigprocmask(int how, compat_sigset_t __user *set, 417 compat_sigset_t __user *oset, size_t sigsetsize) 418 { 419 sigset_t s; 420 compat_sigset_t s32; 421 int ret; 422 mm_segment_t old_fs = get_fs(); 423 424 if (set) { 425 if (copy_from_user (&s32, set, sizeof(compat_sigset_t))) 426 return -EFAULT; 427 switch (_NSIG_WORDS) { 428 case 4: s.sig[3] = s32.sig[6] | (((long)s32.sig[7]) << 32); 429 case 3: s.sig[2] = s32.sig[4] | (((long)s32.sig[5]) << 32); 430 case 2: s.sig[1] = s32.sig[2] | (((long)s32.sig[3]) << 32); 431 case 1: s.sig[0] = s32.sig[0] | (((long)s32.sig[1]) << 32); 432 } 433 } 434 set_fs (KERNEL_DS); 435 ret = sys_rt_sigprocmask(how, 436 set ? (sigset_t __force __user *) &s : NULL, 437 oset ? (sigset_t __force __user *) &s : NULL, 438 sigsetsize); 439 set_fs (old_fs); 440 if (ret) return ret; 441 if (oset) { 442 switch (_NSIG_WORDS) { 443 case 4: s32.sig[7] = (s.sig[3] >> 32); s32.sig[6] = s.sig[3]; 444 case 3: s32.sig[5] = (s.sig[2] >> 32); s32.sig[4] = s.sig[2]; 445 case 2: s32.sig[3] = (s.sig[1] >> 32); s32.sig[2] = s.sig[1]; 446 case 1: s32.sig[1] = (s.sig[0] >> 32); s32.sig[0] = s.sig[0]; 447 } 448 if (copy_to_user (oset, &s32, sizeof(compat_sigset_t))) 449 return -EFAULT; 450 } 451 return 0; 452 } 453 454 asmlinkage long sys32_rt_sigpending(compat_sigset_t __user *set, 455 size_t sigsetsize) 456 { 457 sigset_t s; 458 compat_sigset_t s32; 459 int ret; 460 mm_segment_t old_fs = get_fs(); 461 462 set_fs (KERNEL_DS); 463 ret = sys_rt_sigpending((sigset_t __force __user *) &s, sigsetsize); 464 set_fs (old_fs); 465 if (!ret) { 466 switch (_NSIG_WORDS) { 467 case 4: s32.sig[7] = (s.sig[3] >> 32); s32.sig[6] = s.sig[3]; 468 case 3: s32.sig[5] = (s.sig[2] >> 32); s32.sig[4] = s.sig[2]; 469 case 2: s32.sig[3] = (s.sig[1] >> 32); s32.sig[2] = s.sig[1]; 470 case 1: s32.sig[1] = (s.sig[0] >> 32); s32.sig[0] = s.sig[0]; 471 } 472 if (copy_to_user (set, &s32, sizeof(compat_sigset_t))) 473 return -EFAULT; 474 } 475 return ret; 476 } 477 478 asmlinkage long 479 sys32_rt_sigqueueinfo(int pid, int sig, compat_siginfo_t __user *uinfo) 480 { 481 siginfo_t info; 482 int ret; 483 mm_segment_t old_fs = get_fs(); 484 485 if (copy_siginfo_from_user32(&info, uinfo)) 486 return -EFAULT; 487 set_fs (KERNEL_DS); 488 ret = sys_rt_sigqueueinfo(pid, sig, (siginfo_t __force __user *) &info); 489 set_fs (old_fs); 490 return ret; 491 } 492 493 /* 494 * sys32_execve() executes a new program after the asm stub has set 495 * things up for us. This should basically do what I want it to. 496 */ 497 asmlinkage long sys32_execve(void) 498 { 499 struct pt_regs *regs = task_pt_regs(current); 500 char *filename; 501 unsigned long result; 502 int rc; 503 504 filename = getname(compat_ptr(regs->orig_gpr2)); 505 if (IS_ERR(filename)) { 506 result = PTR_ERR(filename); 507 goto out; 508 } 509 rc = compat_do_execve(filename, compat_ptr(regs->gprs[3]), 510 compat_ptr(regs->gprs[4]), regs); 511 if (rc) { 512 result = rc; 513 goto out_putname; 514 } 515 task_lock(current); 516 current->ptrace &= ~PT_DTRACE; 517 task_unlock(current); 518 current->thread.fp_regs.fpc=0; 519 asm volatile("sfpc %0,0" : : "d" (0)); 520 result = regs->gprs[2]; 521 out_putname: 522 putname(filename); 523 out: 524 return result; 525 } 526 527 528 #ifdef CONFIG_MODULES 529 530 asmlinkage long 531 sys32_init_module(void __user *umod, unsigned long len, 532 const char __user *uargs) 533 { 534 return sys_init_module(umod, len, uargs); 535 } 536 537 asmlinkage long 538 sys32_delete_module(const char __user *name_user, unsigned int flags) 539 { 540 return sys_delete_module(name_user, flags); 541 } 542 543 #else /* CONFIG_MODULES */ 544 545 asmlinkage long 546 sys32_init_module(void __user *umod, unsigned long len, 547 const char __user *uargs) 548 { 549 return -ENOSYS; 550 } 551 552 asmlinkage long 553 sys32_delete_module(const char __user *name_user, unsigned int flags) 554 { 555 return -ENOSYS; 556 } 557 558 #endif /* CONFIG_MODULES */ 559 560 /* Translations due to time_t size differences. Which affects all 561 sorts of things, like timeval and itimerval. */ 562 563 extern struct timezone sys_tz; 564 565 asmlinkage long sys32_gettimeofday(struct compat_timeval __user *tv, struct timezone __user *tz) 566 { 567 if (tv) { 568 struct timeval ktv; 569 do_gettimeofday(&ktv); 570 if (put_tv32(tv, &ktv)) 571 return -EFAULT; 572 } 573 if (tz) { 574 if (copy_to_user(tz, &sys_tz, sizeof(sys_tz))) 575 return -EFAULT; 576 } 577 return 0; 578 } 579 580 static inline long get_ts32(struct timespec *o, struct compat_timeval __user *i) 581 { 582 long usec; 583 584 if (!access_ok(VERIFY_READ, i, sizeof(*i))) 585 return -EFAULT; 586 if (__get_user(o->tv_sec, &i->tv_sec)) 587 return -EFAULT; 588 if (__get_user(usec, &i->tv_usec)) 589 return -EFAULT; 590 o->tv_nsec = usec * 1000; 591 return 0; 592 } 593 594 asmlinkage long sys32_settimeofday(struct compat_timeval __user *tv, struct timezone __user *tz) 595 { 596 struct timespec kts; 597 struct timezone ktz; 598 599 if (tv) { 600 if (get_ts32(&kts, tv)) 601 return -EFAULT; 602 } 603 if (tz) { 604 if (copy_from_user(&ktz, tz, sizeof(ktz))) 605 return -EFAULT; 606 } 607 608 return do_sys_settimeofday(tv ? &kts : NULL, tz ? &ktz : NULL); 609 } 610 611 /* These are here just in case some old sparc32 binary calls it. */ 612 asmlinkage long sys32_pause(void) 613 { 614 current->state = TASK_INTERRUPTIBLE; 615 schedule(); 616 return -ERESTARTNOHAND; 617 } 618 619 asmlinkage long sys32_pread64(unsigned int fd, char __user *ubuf, 620 size_t count, u32 poshi, u32 poslo) 621 { 622 if ((compat_ssize_t) count < 0) 623 return -EINVAL; 624 return sys_pread64(fd, ubuf, count, ((loff_t)AA(poshi) << 32) | AA(poslo)); 625 } 626 627 asmlinkage long sys32_pwrite64(unsigned int fd, const char __user *ubuf, 628 size_t count, u32 poshi, u32 poslo) 629 { 630 if ((compat_ssize_t) count < 0) 631 return -EINVAL; 632 return sys_pwrite64(fd, ubuf, count, ((loff_t)AA(poshi) << 32) | AA(poslo)); 633 } 634 635 asmlinkage compat_ssize_t sys32_readahead(int fd, u32 offhi, u32 offlo, s32 count) 636 { 637 return sys_readahead(fd, ((loff_t)AA(offhi) << 32) | AA(offlo), count); 638 } 639 640 asmlinkage long sys32_sendfile(int out_fd, int in_fd, compat_off_t __user *offset, size_t count) 641 { 642 mm_segment_t old_fs = get_fs(); 643 int ret; 644 off_t of; 645 646 if (offset && get_user(of, offset)) 647 return -EFAULT; 648 649 set_fs(KERNEL_DS); 650 ret = sys_sendfile(out_fd, in_fd, 651 offset ? (off_t __force __user *) &of : NULL, count); 652 set_fs(old_fs); 653 654 if (offset && put_user(of, offset)) 655 return -EFAULT; 656 657 return ret; 658 } 659 660 asmlinkage long sys32_sendfile64(int out_fd, int in_fd, 661 compat_loff_t __user *offset, s32 count) 662 { 663 mm_segment_t old_fs = get_fs(); 664 int ret; 665 loff_t lof; 666 667 if (offset && get_user(lof, offset)) 668 return -EFAULT; 669 670 set_fs(KERNEL_DS); 671 ret = sys_sendfile64(out_fd, in_fd, 672 offset ? (loff_t __force __user *) &lof : NULL, 673 count); 674 set_fs(old_fs); 675 676 if (offset && put_user(lof, offset)) 677 return -EFAULT; 678 679 return ret; 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 sys32_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 if (get_user(oldlen, (u32 __user *)compat_ptr(tmp.oldlenp)) || 712 put_user(oldlen, (size_t __user *)addr)) 713 return -EFAULT; 714 oldlenp = (size_t __user *)addr; 715 } 716 717 lock_kernel(); 718 error = do_sysctl(compat_ptr(tmp.name), tmp.nlen, compat_ptr(tmp.oldval), 719 oldlenp, compat_ptr(tmp.newval), tmp.newlen); 720 unlock_kernel(); 721 if (oldlenp) { 722 if (!error) { 723 if (get_user(oldlen, (size_t __user *)addr) || 724 put_user(oldlen, (u32 __user *)compat_ptr(tmp.oldlenp))) 725 error = -EFAULT; 726 } 727 if (copy_to_user(args->__unused, tmp.__unused, 728 sizeof(tmp.__unused))) 729 error = -EFAULT; 730 } 731 return error; 732 } 733 #endif 734 735 struct stat64_emu31 { 736 unsigned long long st_dev; 737 unsigned int __pad1; 738 #define STAT64_HAS_BROKEN_ST_INO 1 739 u32 __st_ino; 740 unsigned int st_mode; 741 unsigned int st_nlink; 742 u32 st_uid; 743 u32 st_gid; 744 unsigned long long st_rdev; 745 unsigned int __pad3; 746 long st_size; 747 u32 st_blksize; 748 unsigned char __pad4[4]; 749 u32 __pad5; /* future possible st_blocks high bits */ 750 u32 st_blocks; /* Number 512-byte blocks allocated. */ 751 u32 st_atime; 752 u32 __pad6; 753 u32 st_mtime; 754 u32 __pad7; 755 u32 st_ctime; 756 u32 __pad8; /* will be high 32 bits of ctime someday */ 757 unsigned long st_ino; 758 }; 759 760 static int cp_stat64(struct stat64_emu31 __user *ubuf, struct kstat *stat) 761 { 762 struct stat64_emu31 tmp; 763 764 memset(&tmp, 0, sizeof(tmp)); 765 766 tmp.st_dev = huge_encode_dev(stat->dev); 767 tmp.st_ino = stat->ino; 768 tmp.__st_ino = (u32)stat->ino; 769 tmp.st_mode = stat->mode; 770 tmp.st_nlink = (unsigned int)stat->nlink; 771 tmp.st_uid = stat->uid; 772 tmp.st_gid = stat->gid; 773 tmp.st_rdev = huge_encode_dev(stat->rdev); 774 tmp.st_size = stat->size; 775 tmp.st_blksize = (u32)stat->blksize; 776 tmp.st_blocks = (u32)stat->blocks; 777 tmp.st_atime = (u32)stat->atime.tv_sec; 778 tmp.st_mtime = (u32)stat->mtime.tv_sec; 779 tmp.st_ctime = (u32)stat->ctime.tv_sec; 780 781 return copy_to_user(ubuf,&tmp,sizeof(tmp)) ? -EFAULT : 0; 782 } 783 784 asmlinkage long sys32_stat64(char __user * filename, struct stat64_emu31 __user * statbuf) 785 { 786 struct kstat stat; 787 int ret = vfs_stat(filename, &stat); 788 if (!ret) 789 ret = cp_stat64(statbuf, &stat); 790 return ret; 791 } 792 793 asmlinkage long sys32_lstat64(char __user * filename, struct stat64_emu31 __user * statbuf) 794 { 795 struct kstat stat; 796 int ret = vfs_lstat(filename, &stat); 797 if (!ret) 798 ret = cp_stat64(statbuf, &stat); 799 return ret; 800 } 801 802 asmlinkage long sys32_fstat64(unsigned long fd, struct stat64_emu31 __user * statbuf) 803 { 804 struct kstat stat; 805 int ret = vfs_fstat(fd, &stat); 806 if (!ret) 807 ret = cp_stat64(statbuf, &stat); 808 return ret; 809 } 810 811 asmlinkage long sys32_fstatat64(unsigned int dfd, char __user *filename, 812 struct stat64_emu31 __user* statbuf, int flag) 813 { 814 struct kstat stat; 815 int error = -EINVAL; 816 817 if ((flag & ~AT_SYMLINK_NOFOLLOW) != 0) 818 goto out; 819 820 if (flag & AT_SYMLINK_NOFOLLOW) 821 error = vfs_lstat_fd(dfd, filename, &stat); 822 else 823 error = vfs_stat_fd(dfd, filename, &stat); 824 825 if (!error) 826 error = cp_stat64(statbuf, &stat); 827 out: 828 return error; 829 } 830 831 /* 832 * Linux/i386 didn't use to be able to handle more than 833 * 4 system call parameters, so these system calls used a memory 834 * block for parameter passing.. 835 */ 836 837 struct mmap_arg_struct_emu31 { 838 u32 addr; 839 u32 len; 840 u32 prot; 841 u32 flags; 842 u32 fd; 843 u32 offset; 844 }; 845 846 /* common code for old and new mmaps */ 847 static inline long do_mmap2( 848 unsigned long addr, unsigned long len, 849 unsigned long prot, unsigned long flags, 850 unsigned long fd, unsigned long pgoff) 851 { 852 struct file * file = NULL; 853 unsigned long error = -EBADF; 854 855 flags &= ~(MAP_EXECUTABLE | MAP_DENYWRITE); 856 if (!(flags & MAP_ANONYMOUS)) { 857 file = fget(fd); 858 if (!file) 859 goto out; 860 } 861 862 down_write(¤t->mm->mmap_sem); 863 error = do_mmap_pgoff(file, addr, len, prot, flags, pgoff); 864 if (!IS_ERR((void *) error) && error + len >= 0x80000000ULL) { 865 /* Result is out of bounds. */ 866 do_munmap(current->mm, addr, len); 867 error = -ENOMEM; 868 } 869 up_write(¤t->mm->mmap_sem); 870 871 if (file) 872 fput(file); 873 out: 874 return error; 875 } 876 877 878 asmlinkage unsigned long 879 old32_mmap(struct mmap_arg_struct_emu31 __user *arg) 880 { 881 struct mmap_arg_struct_emu31 a; 882 int error = -EFAULT; 883 884 if (copy_from_user(&a, arg, sizeof(a))) 885 goto out; 886 887 error = -EINVAL; 888 if (a.offset & ~PAGE_MASK) 889 goto out; 890 891 error = do_mmap2(a.addr, a.len, a.prot, a.flags, a.fd, a.offset >> PAGE_SHIFT); 892 out: 893 return error; 894 } 895 896 asmlinkage long 897 sys32_mmap2(struct mmap_arg_struct_emu31 __user *arg) 898 { 899 struct mmap_arg_struct_emu31 a; 900 int error = -EFAULT; 901 902 if (copy_from_user(&a, arg, sizeof(a))) 903 goto out; 904 error = do_mmap2(a.addr, a.len, a.prot, a.flags, a.fd, a.offset); 905 out: 906 return error; 907 } 908 909 asmlinkage long sys32_read(unsigned int fd, char __user * buf, size_t count) 910 { 911 if ((compat_ssize_t) count < 0) 912 return -EINVAL; 913 914 return sys_read(fd, buf, count); 915 } 916 917 asmlinkage long sys32_write(unsigned int fd, char __user * buf, size_t count) 918 { 919 if ((compat_ssize_t) count < 0) 920 return -EINVAL; 921 922 return sys_write(fd, buf, count); 923 } 924 925 asmlinkage long sys32_clone(void) 926 { 927 struct pt_regs *regs = task_pt_regs(current); 928 unsigned long clone_flags; 929 unsigned long newsp; 930 int __user *parent_tidptr, *child_tidptr; 931 932 clone_flags = regs->gprs[3] & 0xffffffffUL; 933 newsp = regs->orig_gpr2 & 0x7fffffffUL; 934 parent_tidptr = compat_ptr(regs->gprs[4]); 935 child_tidptr = compat_ptr(regs->gprs[5]); 936 if (!newsp) 937 newsp = regs->gprs[15]; 938 return do_fork(clone_flags, newsp, regs, 0, 939 parent_tidptr, child_tidptr); 940 } 941 942 /* 943 * 31 bit emulation wrapper functions for sys_fadvise64/fadvise64_64. 944 * These need to rewrite the advise values for POSIX_FADV_{DONTNEED,NOREUSE} 945 * because the 31 bit values differ from the 64 bit values. 946 */ 947 948 asmlinkage long 949 sys32_fadvise64(int fd, loff_t offset, size_t len, int advise) 950 { 951 if (advise == 4) 952 advise = POSIX_FADV_DONTNEED; 953 else if (advise == 5) 954 advise = POSIX_FADV_NOREUSE; 955 return sys_fadvise64(fd, offset, len, advise); 956 } 957 958 struct fadvise64_64_args { 959 int fd; 960 long long offset; 961 long long len; 962 int advice; 963 }; 964 965 asmlinkage long 966 sys32_fadvise64_64(struct fadvise64_64_args __user *args) 967 { 968 struct fadvise64_64_args a; 969 970 if ( copy_from_user(&a, args, sizeof(a)) ) 971 return -EFAULT; 972 if (a.advice == 4) 973 a.advice = POSIX_FADV_DONTNEED; 974 else if (a.advice == 5) 975 a.advice = POSIX_FADV_NOREUSE; 976 return sys_fadvise64_64(a.fd, a.offset, a.len, a.advice); 977 } 978