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 39 #include <net/sock.h> 40 #include <net/scm.h> 41 42 #include <asm/compat-signal.h> 43 #include <asm/ipc.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 asmlinkage long 315 sys32_ipc (u32 call, int first, int second, int third, u32 ptr, u32 fifth) 316 { 317 int version, err; 318 319 version = call >> 16; /* hack for backward compatibility */ 320 call &= 0xffff; 321 322 switch (call) { 323 case SEMOP: 324 /* struct sembuf is the same on 32 and 64bit :)) */ 325 err = sys_semtimedop(first, compat_ptr(ptr), second, NULL); 326 break; 327 case SEMTIMEDOP: 328 err = compat_sys_semtimedop(first, compat_ptr(ptr), second, 329 compat_ptr(fifth)); 330 break; 331 case SEMGET: 332 err = sys_semget(first, second, third); 333 break; 334 case SEMCTL: 335 err = compat_sys_semctl(first, second, third, compat_ptr(ptr)); 336 break; 337 case MSGSND: 338 err = compat_sys_msgsnd(first, second, third, compat_ptr(ptr)); 339 break; 340 case MSGRCV: 341 err = compat_sys_msgrcv(first, second, fifth, third, 342 version, compat_ptr(ptr)); 343 break; 344 case MSGGET: 345 err = sys_msgget((key_t) first, second); 346 break; 347 case MSGCTL: 348 err = compat_sys_msgctl(first, second, compat_ptr(ptr)); 349 break; 350 case SHMAT: 351 err = compat_sys_shmat(first, second, third, version, 352 compat_ptr(ptr)); 353 break; 354 case SHMDT: 355 err = sys_shmdt(compat_ptr(ptr)); 356 break; 357 case SHMGET: 358 err = sys_shmget(first, (unsigned)second, third); 359 break; 360 case SHMCTL: 361 err = compat_sys_shmctl(first, second, compat_ptr(ptr)); 362 break; 363 default: 364 err = -EINVAL; 365 break; 366 } 367 368 return err; 369 } 370 371 #ifdef CONFIG_MIPS32_N32 372 asmlinkage long sysn32_semctl(int semid, int semnum, int cmd, u32 arg) 373 { 374 /* compat_sys_semctl expects a pointer to union semun */ 375 u32 __user *uptr = compat_alloc_user_space(sizeof(u32)); 376 if (put_user(arg, uptr)) 377 return -EFAULT; 378 return compat_sys_semctl(semid, semnum, cmd, uptr); 379 } 380 381 asmlinkage long sysn32_msgsnd(int msqid, u32 msgp, unsigned msgsz, int msgflg) 382 { 383 return compat_sys_msgsnd(msqid, msgsz, msgflg, compat_ptr(msgp)); 384 } 385 386 asmlinkage long sysn32_msgrcv(int msqid, u32 msgp, size_t msgsz, int msgtyp, 387 int msgflg) 388 { 389 return compat_sys_msgrcv(msqid, msgsz, msgtyp, msgflg, IPC_64, 390 compat_ptr(msgp)); 391 } 392 #endif 393 394 struct sysctl_args32 395 { 396 compat_caddr_t name; 397 int nlen; 398 compat_caddr_t oldval; 399 compat_caddr_t oldlenp; 400 compat_caddr_t newval; 401 compat_size_t newlen; 402 unsigned int __unused[4]; 403 }; 404 405 #ifdef CONFIG_SYSCTL_SYSCALL 406 407 asmlinkage long sys32_sysctl(struct sysctl_args32 __user *args) 408 { 409 struct sysctl_args32 tmp; 410 int error; 411 size_t oldlen; 412 size_t __user *oldlenp = NULL; 413 unsigned long addr = (((unsigned long)&args->__unused[0]) + 7) & ~7; 414 415 if (copy_from_user(&tmp, args, sizeof(tmp))) 416 return -EFAULT; 417 418 if (tmp.oldval && tmp.oldlenp) { 419 /* Duh, this is ugly and might not work if sysctl_args 420 is in read-only memory, but do_sysctl does indirectly 421 a lot of uaccess in both directions and we'd have to 422 basically copy the whole sysctl.c here, and 423 glibc's __sysctl uses rw memory for the structure 424 anyway. */ 425 if (get_user(oldlen, (u32 __user *)A(tmp.oldlenp)) || 426 put_user(oldlen, (size_t __user *)addr)) 427 return -EFAULT; 428 oldlenp = (size_t __user *)addr; 429 } 430 431 lock_kernel(); 432 error = do_sysctl((int __user *)A(tmp.name), tmp.nlen, (void __user *)A(tmp.oldval), 433 oldlenp, (void __user *)A(tmp.newval), tmp.newlen); 434 unlock_kernel(); 435 if (oldlenp) { 436 if (!error) { 437 if (get_user(oldlen, (size_t __user *)addr) || 438 put_user(oldlen, (u32 __user *)A(tmp.oldlenp))) 439 error = -EFAULT; 440 } 441 copy_to_user(args->__unused, tmp.__unused, sizeof(tmp.__unused)); 442 } 443 return error; 444 } 445 446 #endif /* CONFIG_SYSCTL_SYSCALL */ 447 448 asmlinkage long sys32_newuname(struct new_utsname __user * name) 449 { 450 int ret = 0; 451 452 down_read(&uts_sem); 453 if (copy_to_user(name, utsname(), sizeof *name)) 454 ret = -EFAULT; 455 up_read(&uts_sem); 456 457 if (current->personality == PER_LINUX32 && !ret) 458 if (copy_to_user(name->machine, "mips\0\0\0", 8)) 459 ret = -EFAULT; 460 461 return ret; 462 } 463 464 asmlinkage int sys32_personality(unsigned long personality) 465 { 466 int ret; 467 personality &= 0xffffffff; 468 if (personality(current->personality) == PER_LINUX32 && 469 personality == PER_LINUX) 470 personality = PER_LINUX32; 471 ret = sys_personality(personality); 472 if (ret == PER_LINUX32) 473 ret = PER_LINUX; 474 return ret; 475 } 476 477 /* ustat compatibility */ 478 struct ustat32 { 479 compat_daddr_t f_tfree; 480 compat_ino_t f_tinode; 481 char f_fname[6]; 482 char f_fpack[6]; 483 }; 484 485 extern asmlinkage long sys_ustat(dev_t dev, struct ustat __user * ubuf); 486 487 asmlinkage int sys32_ustat(dev_t dev, struct ustat32 __user * ubuf32) 488 { 489 int err; 490 struct ustat tmp; 491 struct ustat32 tmp32; 492 mm_segment_t old_fs = get_fs(); 493 494 set_fs(KERNEL_DS); 495 err = sys_ustat(dev, (struct ustat __user *)&tmp); 496 set_fs (old_fs); 497 498 if (err) 499 goto out; 500 501 memset(&tmp32,0,sizeof(struct ustat32)); 502 tmp32.f_tfree = tmp.f_tfree; 503 tmp32.f_tinode = tmp.f_tinode; 504 505 err = copy_to_user(ubuf32,&tmp32,sizeof(struct ustat32)) ? -EFAULT : 0; 506 507 out: 508 return err; 509 } 510 511 asmlinkage int sys32_sendfile(int out_fd, int in_fd, compat_off_t __user *offset, 512 s32 count) 513 { 514 mm_segment_t old_fs = get_fs(); 515 int ret; 516 off_t of; 517 518 if (offset && get_user(of, offset)) 519 return -EFAULT; 520 521 set_fs(KERNEL_DS); 522 ret = sys_sendfile(out_fd, in_fd, offset ? (off_t __user *)&of : NULL, count); 523 set_fs(old_fs); 524 525 if (offset && put_user(of, offset)) 526 return -EFAULT; 527 528 return ret; 529 } 530 531 asmlinkage ssize_t sys32_readahead(int fd, u32 pad0, u64 a2, u64 a3, 532 size_t count) 533 { 534 return sys_readahead(fd, merge_64(a2, a3), count); 535 } 536 537 asmlinkage long sys32_sync_file_range(int fd, int __pad, 538 unsigned long a2, unsigned long a3, 539 unsigned long a4, unsigned long a5, 540 int flags) 541 { 542 return sys_sync_file_range(fd, 543 merge_64(a2, a3), merge_64(a4, a5), 544 flags); 545 } 546 547 save_static_function(sys32_clone); 548 __attribute_used__ noinline static int 549 _sys32_clone(nabi_no_regargs struct pt_regs regs) 550 { 551 unsigned long clone_flags; 552 unsigned long newsp; 553 int __user *parent_tidptr, *child_tidptr; 554 555 clone_flags = regs.regs[4]; 556 newsp = regs.regs[5]; 557 if (!newsp) 558 newsp = regs.regs[29]; 559 parent_tidptr = (int __user *) regs.regs[6]; 560 561 /* Use __dummy4 instead of getting it off the stack, so that 562 syscall() works. */ 563 child_tidptr = (int __user *) __dummy4; 564 return do_fork(clone_flags, newsp, ®s, 0, 565 parent_tidptr, child_tidptr); 566 } 567