1 /* 2 * Conversion between 32-bit and 64-bit native system calls. 3 * 4 * Copyright (C) 2000 Silicon Graphics, Inc. 5 * Written by Ulf Carlsson (ulfc@engr.sgi.com) 6 * sys32_execve from ia64/ia32 code, Feb 2000, Kanoj Sarcar (kanoj@sgi.com) 7 */ 8 #include <linux/compiler.h> 9 #include <linux/mm.h> 10 #include <linux/errno.h> 11 #include <linux/file.h> 12 #include <linux/smp_lock.h> 13 #include <linux/highuid.h> 14 #include <linux/dirent.h> 15 #include <linux/resource.h> 16 #include <linux/highmem.h> 17 #include <linux/time.h> 18 #include <linux/times.h> 19 #include <linux/poll.h> 20 #include <linux/slab.h> 21 #include <linux/skbuff.h> 22 #include <linux/filter.h> 23 #include <linux/shm.h> 24 #include <linux/sem.h> 25 #include <linux/msg.h> 26 #include <linux/icmpv6.h> 27 #include <linux/syscalls.h> 28 #include <linux/sysctl.h> 29 #include <linux/utime.h> 30 #include <linux/utsname.h> 31 #include <linux/personality.h> 32 #include <linux/dnotify.h> 33 #include <linux/module.h> 34 #include <linux/binfmts.h> 35 #include <linux/security.h> 36 #include <linux/compat.h> 37 #include <linux/vfs.h> 38 #include <linux/ipc.h> 39 40 #include <net/sock.h> 41 #include <net/scm.h> 42 43 #include <asm/compat-signal.h> 44 #include <asm/sim.h> 45 #include <asm/uaccess.h> 46 #include <asm/mmu_context.h> 47 #include <asm/mman.h> 48 49 /* Use this to get at 32-bit user passed pointers. */ 50 /* A() macro should be used for places where you e.g. 51 have some internal variable u32 and just want to get 52 rid of a compiler warning. AA() has to be used in 53 places where you want to convert a function argument 54 to 32bit pointer or when you e.g. access pt_regs 55 structure and want to consider 32bit registers only. 56 */ 57 #define A(__x) ((unsigned long)(__x)) 58 #define AA(__x) ((unsigned long)((int)__x)) 59 60 #ifdef __MIPSEB__ 61 #define merge_64(r1, r2) ((((r1) & 0xffffffffUL) << 32) + ((r2) & 0xffffffffUL)) 62 #endif 63 #ifdef __MIPSEL__ 64 #define merge_64(r1, r2) ((((r2) & 0xffffffffUL) << 32) + ((r1) & 0xffffffffUL)) 65 #endif 66 67 /* 68 * Revalidate the inode. This is required for proper NFS attribute caching. 69 */ 70 71 int cp_compat_stat(struct kstat *stat, struct compat_stat __user *statbuf) 72 { 73 struct compat_stat tmp; 74 75 if (!new_valid_dev(stat->dev) || !new_valid_dev(stat->rdev)) 76 return -EOVERFLOW; 77 78 memset(&tmp, 0, sizeof(tmp)); 79 tmp.st_dev = new_encode_dev(stat->dev); 80 tmp.st_ino = stat->ino; 81 if (sizeof(tmp.st_ino) < sizeof(stat->ino) && tmp.st_ino != stat->ino) 82 return -EOVERFLOW; 83 tmp.st_mode = stat->mode; 84 tmp.st_nlink = stat->nlink; 85 SET_UID(tmp.st_uid, stat->uid); 86 SET_GID(tmp.st_gid, stat->gid); 87 tmp.st_rdev = new_encode_dev(stat->rdev); 88 tmp.st_size = stat->size; 89 tmp.st_atime = stat->atime.tv_sec; 90 tmp.st_mtime = stat->mtime.tv_sec; 91 tmp.st_ctime = stat->ctime.tv_sec; 92 #ifdef STAT_HAVE_NSEC 93 tmp.st_atime_nsec = stat->atime.tv_nsec; 94 tmp.st_mtime_nsec = stat->mtime.tv_nsec; 95 tmp.st_ctime_nsec = stat->ctime.tv_nsec; 96 #endif 97 tmp.st_blocks = stat->blocks; 98 tmp.st_blksize = stat->blksize; 99 return copy_to_user(statbuf, &tmp, sizeof(tmp)) ? -EFAULT : 0; 100 } 101 102 asmlinkage unsigned long 103 sys32_mmap2(unsigned long addr, unsigned long len, unsigned long prot, 104 unsigned long flags, unsigned long fd, unsigned long pgoff) 105 { 106 struct file * file = NULL; 107 unsigned long error; 108 109 error = -EINVAL; 110 if (pgoff & (~PAGE_MASK >> 12)) 111 goto out; 112 pgoff >>= PAGE_SHIFT-12; 113 114 if (!(flags & MAP_ANONYMOUS)) { 115 error = -EBADF; 116 file = fget(fd); 117 if (!file) 118 goto out; 119 } 120 flags &= ~(MAP_EXECUTABLE | MAP_DENYWRITE); 121 122 down_write(¤t->mm->mmap_sem); 123 error = do_mmap_pgoff(file, addr, len, prot, flags, pgoff); 124 up_write(¤t->mm->mmap_sem); 125 if (file) 126 fput(file); 127 128 out: 129 return error; 130 } 131 132 133 asmlinkage int sys_truncate64(const char __user *path, unsigned int high, 134 unsigned int low) 135 { 136 if ((int)high < 0) 137 return -EINVAL; 138 return sys_truncate(path, ((long) high << 32) | low); 139 } 140 141 asmlinkage int sys_ftruncate64(unsigned int fd, unsigned int high, 142 unsigned int low) 143 { 144 if ((int)high < 0) 145 return -EINVAL; 146 return sys_ftruncate(fd, ((long) high << 32) | low); 147 } 148 149 /* 150 * sys_execve() executes a new program. 151 */ 152 asmlinkage int sys32_execve(nabi_no_regargs struct pt_regs regs) 153 { 154 int error; 155 char * filename; 156 157 filename = getname(compat_ptr(regs.regs[4])); 158 error = PTR_ERR(filename); 159 if (IS_ERR(filename)) 160 goto out; 161 error = compat_do_execve(filename, compat_ptr(regs.regs[5]), 162 compat_ptr(regs.regs[6]), ®s); 163 putname(filename); 164 165 out: 166 return error; 167 } 168 169 #define RLIM_INFINITY32 0x7fffffff 170 #define RESOURCE32(x) ((x > RLIM_INFINITY32) ? RLIM_INFINITY32 : x) 171 172 struct rlimit32 { 173 int rlim_cur; 174 int rlim_max; 175 }; 176 177 #ifdef __MIPSEB__ 178 asmlinkage long sys32_truncate64(const char __user * path, unsigned long __dummy, 179 int length_hi, int length_lo) 180 #endif 181 #ifdef __MIPSEL__ 182 asmlinkage long sys32_truncate64(const char __user * path, unsigned long __dummy, 183 int length_lo, int length_hi) 184 #endif 185 { 186 loff_t length; 187 188 length = ((unsigned long) length_hi << 32) | (unsigned int) length_lo; 189 190 return sys_truncate(path, length); 191 } 192 193 #ifdef __MIPSEB__ 194 asmlinkage long sys32_ftruncate64(unsigned int fd, unsigned long __dummy, 195 int length_hi, int length_lo) 196 #endif 197 #ifdef __MIPSEL__ 198 asmlinkage long sys32_ftruncate64(unsigned int fd, unsigned long __dummy, 199 int length_lo, int length_hi) 200 #endif 201 { 202 loff_t length; 203 204 length = ((unsigned long) length_hi << 32) | (unsigned int) length_lo; 205 206 return sys_ftruncate(fd, length); 207 } 208 209 static inline long 210 get_tv32(struct timeval *o, struct compat_timeval __user *i) 211 { 212 return (!access_ok(VERIFY_READ, i, sizeof(*i)) || 213 (__get_user(o->tv_sec, &i->tv_sec) | 214 __get_user(o->tv_usec, &i->tv_usec))); 215 } 216 217 static inline long 218 put_tv32(struct compat_timeval __user *o, struct timeval *i) 219 { 220 return (!access_ok(VERIFY_WRITE, o, sizeof(*o)) || 221 (__put_user(i->tv_sec, &o->tv_sec) | 222 __put_user(i->tv_usec, &o->tv_usec))); 223 } 224 225 extern struct timezone sys_tz; 226 227 asmlinkage int 228 sys32_gettimeofday(struct compat_timeval __user *tv, struct timezone __user *tz) 229 { 230 if (tv) { 231 struct timeval ktv; 232 do_gettimeofday(&ktv); 233 if (put_tv32(tv, &ktv)) 234 return -EFAULT; 235 } 236 if (tz) { 237 if (copy_to_user(tz, &sys_tz, sizeof(sys_tz))) 238 return -EFAULT; 239 } 240 return 0; 241 } 242 243 static inline long get_ts32(struct timespec *o, struct compat_timeval __user *i) 244 { 245 long usec; 246 247 if (!access_ok(VERIFY_READ, i, sizeof(*i))) 248 return -EFAULT; 249 if (__get_user(o->tv_sec, &i->tv_sec)) 250 return -EFAULT; 251 if (__get_user(usec, &i->tv_usec)) 252 return -EFAULT; 253 o->tv_nsec = usec * 1000; 254 return 0; 255 } 256 257 asmlinkage int 258 sys32_settimeofday(struct compat_timeval __user *tv, struct timezone __user *tz) 259 { 260 struct timespec kts; 261 struct timezone ktz; 262 263 if (tv) { 264 if (get_ts32(&kts, tv)) 265 return -EFAULT; 266 } 267 if (tz) { 268 if (copy_from_user(&ktz, tz, sizeof(ktz))) 269 return -EFAULT; 270 } 271 272 return do_sys_settimeofday(tv ? &kts : NULL, tz ? &ktz : NULL); 273 } 274 275 asmlinkage int sys32_llseek(unsigned int fd, unsigned int offset_high, 276 unsigned int offset_low, loff_t __user * result, 277 unsigned int origin) 278 { 279 return sys_llseek(fd, offset_high, offset_low, result, origin); 280 } 281 282 /* From the Single Unix Spec: pread & pwrite act like lseek to pos + op + 283 lseek back to original location. They fail just like lseek does on 284 non-seekable files. */ 285 286 asmlinkage ssize_t sys32_pread(unsigned int fd, char __user * buf, 287 size_t count, u32 unused, u64 a4, u64 a5) 288 { 289 return sys_pread64(fd, buf, count, merge_64(a4, a5)); 290 } 291 292 asmlinkage ssize_t sys32_pwrite(unsigned int fd, const char __user * buf, 293 size_t count, u32 unused, u64 a4, u64 a5) 294 { 295 return sys_pwrite64(fd, buf, count, merge_64(a4, a5)); 296 } 297 298 asmlinkage int sys32_sched_rr_get_interval(compat_pid_t pid, 299 struct compat_timespec __user *interval) 300 { 301 struct timespec t; 302 int ret; 303 mm_segment_t old_fs = get_fs(); 304 305 set_fs(KERNEL_DS); 306 ret = sys_sched_rr_get_interval(pid, (struct timespec __user *)&t); 307 set_fs(old_fs); 308 if (put_user (t.tv_sec, &interval->tv_sec) || 309 __put_user(t.tv_nsec, &interval->tv_nsec)) 310 return -EFAULT; 311 return ret; 312 } 313 314 #ifdef CONFIG_SYSVIPC 315 316 asmlinkage long 317 sys32_ipc(u32 call, int first, int second, int third, u32 ptr, u32 fifth) 318 { 319 int version, err; 320 321 version = call >> 16; /* hack for backward compatibility */ 322 call &= 0xffff; 323 324 switch (call) { 325 case SEMOP: 326 /* struct sembuf is the same on 32 and 64bit :)) */ 327 err = sys_semtimedop(first, compat_ptr(ptr), second, NULL); 328 break; 329 case SEMTIMEDOP: 330 err = compat_sys_semtimedop(first, compat_ptr(ptr), second, 331 compat_ptr(fifth)); 332 break; 333 case SEMGET: 334 err = sys_semget(first, second, third); 335 break; 336 case SEMCTL: 337 err = compat_sys_semctl(first, second, third, compat_ptr(ptr)); 338 break; 339 case MSGSND: 340 err = compat_sys_msgsnd(first, second, third, compat_ptr(ptr)); 341 break; 342 case MSGRCV: 343 err = compat_sys_msgrcv(first, second, fifth, third, 344 version, compat_ptr(ptr)); 345 break; 346 case MSGGET: 347 err = sys_msgget((key_t) first, second); 348 break; 349 case MSGCTL: 350 err = compat_sys_msgctl(first, second, compat_ptr(ptr)); 351 break; 352 case SHMAT: 353 err = compat_sys_shmat(first, second, third, version, 354 compat_ptr(ptr)); 355 break; 356 case SHMDT: 357 err = sys_shmdt(compat_ptr(ptr)); 358 break; 359 case SHMGET: 360 err = sys_shmget(first, (unsigned)second, third); 361 break; 362 case SHMCTL: 363 err = compat_sys_shmctl(first, second, compat_ptr(ptr)); 364 break; 365 default: 366 err = -EINVAL; 367 break; 368 } 369 370 return err; 371 } 372 373 #else 374 375 asmlinkage long 376 sys32_ipc(u32 call, int first, int second, int third, u32 ptr, u32 fifth) 377 { 378 return -ENOSYS; 379 } 380 381 #endif /* CONFIG_SYSVIPC */ 382 383 #ifdef CONFIG_MIPS32_N32 384 asmlinkage long sysn32_semctl(int semid, int semnum, int cmd, u32 arg) 385 { 386 /* compat_sys_semctl expects a pointer to union semun */ 387 u32 __user *uptr = compat_alloc_user_space(sizeof(u32)); 388 if (put_user(arg, uptr)) 389 return -EFAULT; 390 return compat_sys_semctl(semid, semnum, cmd, uptr); 391 } 392 393 asmlinkage long sysn32_msgsnd(int msqid, u32 msgp, unsigned msgsz, int msgflg) 394 { 395 return compat_sys_msgsnd(msqid, msgsz, msgflg, compat_ptr(msgp)); 396 } 397 398 asmlinkage long sysn32_msgrcv(int msqid, u32 msgp, size_t msgsz, int msgtyp, 399 int msgflg) 400 { 401 return compat_sys_msgrcv(msqid, msgsz, msgtyp, msgflg, IPC_64, 402 compat_ptr(msgp)); 403 } 404 #endif 405 406 struct sysctl_args32 407 { 408 compat_caddr_t name; 409 int nlen; 410 compat_caddr_t oldval; 411 compat_caddr_t oldlenp; 412 compat_caddr_t newval; 413 compat_size_t newlen; 414 unsigned int __unused[4]; 415 }; 416 417 #ifdef CONFIG_SYSCTL_SYSCALL 418 419 asmlinkage long sys32_sysctl(struct sysctl_args32 __user *args) 420 { 421 struct sysctl_args32 tmp; 422 int error; 423 size_t oldlen; 424 size_t __user *oldlenp = NULL; 425 unsigned long addr = (((unsigned long)&args->__unused[0]) + 7) & ~7; 426 427 if (copy_from_user(&tmp, args, sizeof(tmp))) 428 return -EFAULT; 429 430 if (tmp.oldval && tmp.oldlenp) { 431 /* Duh, this is ugly and might not work if sysctl_args 432 is in read-only memory, but do_sysctl does indirectly 433 a lot of uaccess in both directions and we'd have to 434 basically copy the whole sysctl.c here, and 435 glibc's __sysctl uses rw memory for the structure 436 anyway. */ 437 if (get_user(oldlen, (u32 __user *)A(tmp.oldlenp)) || 438 put_user(oldlen, (size_t __user *)addr)) 439 return -EFAULT; 440 oldlenp = (size_t __user *)addr; 441 } 442 443 lock_kernel(); 444 error = do_sysctl((int __user *)A(tmp.name), tmp.nlen, (void __user *)A(tmp.oldval), 445 oldlenp, (void __user *)A(tmp.newval), tmp.newlen); 446 unlock_kernel(); 447 if (oldlenp) { 448 if (!error) { 449 if (get_user(oldlen, (size_t __user *)addr) || 450 put_user(oldlen, (u32 __user *)A(tmp.oldlenp))) 451 error = -EFAULT; 452 } 453 copy_to_user(args->__unused, tmp.__unused, sizeof(tmp.__unused)); 454 } 455 return error; 456 } 457 458 #endif /* CONFIG_SYSCTL_SYSCALL */ 459 460 asmlinkage long sys32_newuname(struct new_utsname __user * name) 461 { 462 int ret = 0; 463 464 down_read(&uts_sem); 465 if (copy_to_user(name, utsname(), sizeof *name)) 466 ret = -EFAULT; 467 up_read(&uts_sem); 468 469 if (current->personality == PER_LINUX32 && !ret) 470 if (copy_to_user(name->machine, "mips\0\0\0", 8)) 471 ret = -EFAULT; 472 473 return ret; 474 } 475 476 asmlinkage int sys32_personality(unsigned long personality) 477 { 478 int ret; 479 personality &= 0xffffffff; 480 if (personality(current->personality) == PER_LINUX32 && 481 personality == PER_LINUX) 482 personality = PER_LINUX32; 483 ret = sys_personality(personality); 484 if (ret == PER_LINUX32) 485 ret = PER_LINUX; 486 return ret; 487 } 488 489 /* ustat compatibility */ 490 struct ustat32 { 491 compat_daddr_t f_tfree; 492 compat_ino_t f_tinode; 493 char f_fname[6]; 494 char f_fpack[6]; 495 }; 496 497 extern asmlinkage long sys_ustat(dev_t dev, struct ustat __user * ubuf); 498 499 asmlinkage int sys32_ustat(dev_t dev, struct ustat32 __user * ubuf32) 500 { 501 int err; 502 struct ustat tmp; 503 struct ustat32 tmp32; 504 mm_segment_t old_fs = get_fs(); 505 506 set_fs(KERNEL_DS); 507 err = sys_ustat(dev, (struct ustat __user *)&tmp); 508 set_fs(old_fs); 509 510 if (err) 511 goto out; 512 513 memset(&tmp32, 0, sizeof(struct ustat32)); 514 tmp32.f_tfree = tmp.f_tfree; 515 tmp32.f_tinode = tmp.f_tinode; 516 517 err = copy_to_user(ubuf32, &tmp32, sizeof(struct ustat32)) ? -EFAULT : 0; 518 519 out: 520 return err; 521 } 522 523 asmlinkage int sys32_sendfile(int out_fd, int in_fd, compat_off_t __user *offset, 524 s32 count) 525 { 526 mm_segment_t old_fs = get_fs(); 527 int ret; 528 off_t of; 529 530 if (offset && get_user(of, offset)) 531 return -EFAULT; 532 533 set_fs(KERNEL_DS); 534 ret = sys_sendfile(out_fd, in_fd, offset ? (off_t __user *)&of : NULL, count); 535 set_fs(old_fs); 536 537 if (offset && put_user(of, offset)) 538 return -EFAULT; 539 540 return ret; 541 } 542 543 asmlinkage ssize_t sys32_readahead(int fd, u32 pad0, u64 a2, u64 a3, 544 size_t count) 545 { 546 return sys_readahead(fd, merge_64(a2, a3), count); 547 } 548 549 asmlinkage long sys32_sync_file_range(int fd, int __pad, 550 unsigned long a2, unsigned long a3, 551 unsigned long a4, unsigned long a5, 552 int flags) 553 { 554 return sys_sync_file_range(fd, 555 merge_64(a2, a3), merge_64(a4, a5), 556 flags); 557 } 558 559 asmlinkage long sys32_fadvise64_64(int fd, int __pad, 560 unsigned long a2, unsigned long a3, 561 unsigned long a4, unsigned long a5, 562 int flags) 563 { 564 return sys_fadvise64_64(fd, 565 merge_64(a2, a3), merge_64(a4, a5), 566 flags); 567 } 568 569 asmlinkage long sys32_fallocate(int fd, int mode, unsigned offset_a2, 570 unsigned offset_a3, unsigned len_a4, unsigned len_a5) 571 { 572 return sys_fallocate(fd, mode, merge_64(offset_a2, offset_a3), 573 merge_64(len_a4, len_a5)); 574 } 575 576 save_static_function(sys32_clone); 577 static int noinline __used 578 _sys32_clone(nabi_no_regargs struct pt_regs regs) 579 { 580 unsigned long clone_flags; 581 unsigned long newsp; 582 int __user *parent_tidptr, *child_tidptr; 583 584 clone_flags = regs.regs[4]; 585 newsp = regs.regs[5]; 586 if (!newsp) 587 newsp = regs.regs[29]; 588 parent_tidptr = (int __user *) regs.regs[6]; 589 590 /* Use __dummy4 instead of getting it off the stack, so that 591 syscall() works. */ 592 child_tidptr = (int __user *) __dummy4; 593 return do_fork(clone_flags, newsp, ®s, 0, 594 parent_tidptr, child_tidptr); 595 } 596