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/resource.h> 15 #include <linux/highmem.h> 16 #include <linux/time.h> 17 #include <linux/times.h> 18 #include <linux/poll.h> 19 #include <linux/slab.h> 20 #include <linux/skbuff.h> 21 #include <linux/filter.h> 22 #include <linux/shm.h> 23 #include <linux/sem.h> 24 #include <linux/msg.h> 25 #include <linux/icmpv6.h> 26 #include <linux/syscalls.h> 27 #include <linux/sysctl.h> 28 #include <linux/utime.h> 29 #include <linux/utsname.h> 30 #include <linux/personality.h> 31 #include <linux/dnotify.h> 32 #include <linux/module.h> 33 #include <linux/binfmts.h> 34 #include <linux/security.h> 35 #include <linux/syscalls.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 SYSCALL_DEFINE6(32_mmap2, unsigned long, addr, unsigned long, len, 68 unsigned long, prot, unsigned long, flags, unsigned long, fd, 69 unsigned long, pgoff) 70 { 71 struct file * file = NULL; 72 unsigned long error; 73 74 error = -EINVAL; 75 if (pgoff & (~PAGE_MASK >> 12)) 76 goto out; 77 pgoff >>= PAGE_SHIFT-12; 78 79 if (!(flags & MAP_ANONYMOUS)) { 80 error = -EBADF; 81 file = fget(fd); 82 if (!file) 83 goto out; 84 } 85 flags &= ~(MAP_EXECUTABLE | MAP_DENYWRITE); 86 87 down_write(¤t->mm->mmap_sem); 88 error = do_mmap_pgoff(file, addr, len, prot, flags, pgoff); 89 up_write(¤t->mm->mmap_sem); 90 if (file) 91 fput(file); 92 93 out: 94 return error; 95 } 96 97 /* 98 * sys_execve() executes a new program. 99 */ 100 asmlinkage int sys32_execve(nabi_no_regargs struct pt_regs regs) 101 { 102 int error; 103 char * filename; 104 105 filename = getname(compat_ptr(regs.regs[4])); 106 error = PTR_ERR(filename); 107 if (IS_ERR(filename)) 108 goto out; 109 error = compat_do_execve(filename, compat_ptr(regs.regs[5]), 110 compat_ptr(regs.regs[6]), ®s); 111 putname(filename); 112 113 out: 114 return error; 115 } 116 117 #define RLIM_INFINITY32 0x7fffffff 118 #define RESOURCE32(x) ((x > RLIM_INFINITY32) ? RLIM_INFINITY32 : x) 119 120 struct rlimit32 { 121 int rlim_cur; 122 int rlim_max; 123 }; 124 125 SYSCALL_DEFINE4(32_truncate64, const char __user *, path, 126 unsigned long, __dummy, unsigned long, a2, unsigned long, a3) 127 { 128 return sys_truncate(path, merge_64(a2, a3)); 129 } 130 131 SYSCALL_DEFINE4(32_ftruncate64, unsigned long, fd, unsigned long, __dummy, 132 unsigned long, a2, unsigned long, a3) 133 { 134 return sys_ftruncate(fd, merge_64(a2, a3)); 135 } 136 137 SYSCALL_DEFINE5(32_llseek, unsigned long, fd, unsigned long, offset_high, 138 unsigned long, offset_low, loff_t __user *, result, 139 unsigned long, origin) 140 { 141 return sys_llseek(fd, offset_high, offset_low, result, origin); 142 } 143 144 /* From the Single Unix Spec: pread & pwrite act like lseek to pos + op + 145 lseek back to original location. They fail just like lseek does on 146 non-seekable files. */ 147 148 SYSCALL_DEFINE6(32_pread, unsigned long, fd, char __user *, buf, size_t, count, 149 unsigned long, unused, unsigned long, a4, unsigned long, a5) 150 { 151 return sys_pread64(fd, buf, count, merge_64(a4, a5)); 152 } 153 154 SYSCALL_DEFINE6(32_pwrite, unsigned int, fd, const char __user *, buf, 155 size_t, count, u32, unused, u64, a4, u64, a5) 156 { 157 return sys_pwrite64(fd, buf, count, merge_64(a4, a5)); 158 } 159 160 SYSCALL_DEFINE2(32_sched_rr_get_interval, compat_pid_t, pid, 161 struct compat_timespec __user *, interval) 162 { 163 struct timespec t; 164 int ret; 165 mm_segment_t old_fs = get_fs(); 166 167 set_fs(KERNEL_DS); 168 ret = sys_sched_rr_get_interval(pid, (struct timespec __user *)&t); 169 set_fs(old_fs); 170 if (put_user (t.tv_sec, &interval->tv_sec) || 171 __put_user(t.tv_nsec, &interval->tv_nsec)) 172 return -EFAULT; 173 return ret; 174 } 175 176 #ifdef CONFIG_SYSVIPC 177 178 SYSCALL_DEFINE6(32_ipc, u32, call, long, first, long, second, long, third, 179 unsigned long, ptr, unsigned long, fifth) 180 { 181 int version, err; 182 183 version = call >> 16; /* hack for backward compatibility */ 184 call &= 0xffff; 185 186 switch (call) { 187 case SEMOP: 188 /* struct sembuf is the same on 32 and 64bit :)) */ 189 err = sys_semtimedop(first, compat_ptr(ptr), second, NULL); 190 break; 191 case SEMTIMEDOP: 192 err = compat_sys_semtimedop(first, compat_ptr(ptr), second, 193 compat_ptr(fifth)); 194 break; 195 case SEMGET: 196 err = sys_semget(first, second, third); 197 break; 198 case SEMCTL: 199 err = compat_sys_semctl(first, second, third, compat_ptr(ptr)); 200 break; 201 case MSGSND: 202 err = compat_sys_msgsnd(first, second, third, compat_ptr(ptr)); 203 break; 204 case MSGRCV: 205 err = compat_sys_msgrcv(first, second, fifth, third, 206 version, compat_ptr(ptr)); 207 break; 208 case MSGGET: 209 err = sys_msgget((key_t) first, second); 210 break; 211 case MSGCTL: 212 err = compat_sys_msgctl(first, second, compat_ptr(ptr)); 213 break; 214 case SHMAT: 215 err = compat_sys_shmat(first, second, third, version, 216 compat_ptr(ptr)); 217 break; 218 case SHMDT: 219 err = sys_shmdt(compat_ptr(ptr)); 220 break; 221 case SHMGET: 222 err = sys_shmget(first, (unsigned)second, third); 223 break; 224 case SHMCTL: 225 err = compat_sys_shmctl(first, second, compat_ptr(ptr)); 226 break; 227 default: 228 err = -EINVAL; 229 break; 230 } 231 232 return err; 233 } 234 235 #else 236 237 SYSCALL_DEFINE6(32_ipc, u32, call, int, first, int, second, int, third, 238 u32, ptr, u32, fifth) 239 { 240 return -ENOSYS; 241 } 242 243 #endif /* CONFIG_SYSVIPC */ 244 245 #ifdef CONFIG_MIPS32_N32 246 SYSCALL_DEFINE4(n32_semctl, int, semid, int, semnum, int, cmd, u32, arg) 247 { 248 /* compat_sys_semctl expects a pointer to union semun */ 249 u32 __user *uptr = compat_alloc_user_space(sizeof(u32)); 250 if (put_user(arg, uptr)) 251 return -EFAULT; 252 return compat_sys_semctl(semid, semnum, cmd, uptr); 253 } 254 255 SYSCALL_DEFINE4(n32_msgsnd, int, msqid, u32, msgp, unsigned int, msgsz, 256 int, msgflg) 257 { 258 return compat_sys_msgsnd(msqid, msgsz, msgflg, compat_ptr(msgp)); 259 } 260 261 SYSCALL_DEFINE5(n32_msgrcv, int, msqid, u32, msgp, size_t, msgsz, 262 int, msgtyp, int, msgflg) 263 { 264 return compat_sys_msgrcv(msqid, msgsz, msgtyp, msgflg, IPC_64, 265 compat_ptr(msgp)); 266 } 267 #endif 268 269 struct sysctl_args32 270 { 271 compat_caddr_t name; 272 int nlen; 273 compat_caddr_t oldval; 274 compat_caddr_t oldlenp; 275 compat_caddr_t newval; 276 compat_size_t newlen; 277 unsigned int __unused[4]; 278 }; 279 280 #ifdef CONFIG_SYSCTL_SYSCALL 281 282 SYSCALL_DEFINE1(32_sysctl, struct sysctl_args32 __user *, args) 283 { 284 struct sysctl_args32 tmp; 285 int error; 286 size_t oldlen; 287 size_t __user *oldlenp = NULL; 288 unsigned long addr = (((unsigned long)&args->__unused[0]) + 7) & ~7; 289 290 if (copy_from_user(&tmp, args, sizeof(tmp))) 291 return -EFAULT; 292 293 if (tmp.oldval && tmp.oldlenp) { 294 /* Duh, this is ugly and might not work if sysctl_args 295 is in read-only memory, but do_sysctl does indirectly 296 a lot of uaccess in both directions and we'd have to 297 basically copy the whole sysctl.c here, and 298 glibc's __sysctl uses rw memory for the structure 299 anyway. */ 300 if (get_user(oldlen, (u32 __user *)A(tmp.oldlenp)) || 301 put_user(oldlen, (size_t __user *)addr)) 302 return -EFAULT; 303 oldlenp = (size_t __user *)addr; 304 } 305 306 lock_kernel(); 307 error = do_sysctl((int __user *)A(tmp.name), tmp.nlen, (void __user *)A(tmp.oldval), 308 oldlenp, (void __user *)A(tmp.newval), tmp.newlen); 309 unlock_kernel(); 310 if (oldlenp) { 311 if (!error) { 312 if (get_user(oldlen, (size_t __user *)addr) || 313 put_user(oldlen, (u32 __user *)A(tmp.oldlenp))) 314 error = -EFAULT; 315 } 316 copy_to_user(args->__unused, tmp.__unused, sizeof(tmp.__unused)); 317 } 318 return error; 319 } 320 321 #else 322 323 SYSCALL_DEFINE1(32_sysctl, struct sysctl_args32 __user *, args) 324 { 325 return -ENOSYS; 326 } 327 328 #endif /* CONFIG_SYSCTL_SYSCALL */ 329 330 SYSCALL_DEFINE1(32_newuname, struct new_utsname __user *, name) 331 { 332 int ret = 0; 333 334 down_read(&uts_sem); 335 if (copy_to_user(name, utsname(), sizeof *name)) 336 ret = -EFAULT; 337 up_read(&uts_sem); 338 339 if (current->personality == PER_LINUX32 && !ret) 340 if (copy_to_user(name->machine, "mips\0\0\0", 8)) 341 ret = -EFAULT; 342 343 return ret; 344 } 345 346 SYSCALL_DEFINE1(32_personality, unsigned long, personality) 347 { 348 int ret; 349 personality &= 0xffffffff; 350 if (personality(current->personality) == PER_LINUX32 && 351 personality == PER_LINUX) 352 personality = PER_LINUX32; 353 ret = sys_personality(personality); 354 if (ret == PER_LINUX32) 355 ret = PER_LINUX; 356 return ret; 357 } 358 359 /* ustat compatibility */ 360 struct ustat32 { 361 compat_daddr_t f_tfree; 362 compat_ino_t f_tinode; 363 char f_fname[6]; 364 char f_fpack[6]; 365 }; 366 367 extern asmlinkage long sys_ustat(dev_t dev, struct ustat __user * ubuf); 368 369 SYSCALL_DEFINE2(32_ustat, dev_t, dev, struct ustat32 __user *, ubuf32) 370 { 371 int err; 372 struct ustat tmp; 373 struct ustat32 tmp32; 374 mm_segment_t old_fs = get_fs(); 375 376 set_fs(KERNEL_DS); 377 err = sys_ustat(dev, (struct ustat __user *)&tmp); 378 set_fs(old_fs); 379 380 if (err) 381 goto out; 382 383 memset(&tmp32, 0, sizeof(struct ustat32)); 384 tmp32.f_tfree = tmp.f_tfree; 385 tmp32.f_tinode = tmp.f_tinode; 386 387 err = copy_to_user(ubuf32, &tmp32, sizeof(struct ustat32)) ? -EFAULT : 0; 388 389 out: 390 return err; 391 } 392 393 SYSCALL_DEFINE4(32_sendfile, long, out_fd, long, in_fd, 394 compat_off_t __user *, offset, s32, count) 395 { 396 mm_segment_t old_fs = get_fs(); 397 int ret; 398 off_t of; 399 400 if (offset && get_user(of, offset)) 401 return -EFAULT; 402 403 set_fs(KERNEL_DS); 404 ret = sys_sendfile(out_fd, in_fd, offset ? (off_t __user *)&of : NULL, count); 405 set_fs(old_fs); 406 407 if (offset && put_user(of, offset)) 408 return -EFAULT; 409 410 return ret; 411 } 412 413 asmlinkage ssize_t sys32_readahead(int fd, u32 pad0, u64 a2, u64 a3, 414 size_t count) 415 { 416 return sys_readahead(fd, merge_64(a2, a3), count); 417 } 418 419 asmlinkage long sys32_sync_file_range(int fd, int __pad, 420 unsigned long a2, unsigned long a3, 421 unsigned long a4, unsigned long a5, 422 int flags) 423 { 424 return sys_sync_file_range(fd, 425 merge_64(a2, a3), merge_64(a4, a5), 426 flags); 427 } 428 429 asmlinkage long sys32_fadvise64_64(int fd, int __pad, 430 unsigned long a2, unsigned long a3, 431 unsigned long a4, unsigned long a5, 432 int flags) 433 { 434 return sys_fadvise64_64(fd, 435 merge_64(a2, a3), merge_64(a4, a5), 436 flags); 437 } 438 439 asmlinkage long sys32_fallocate(int fd, int mode, unsigned offset_a2, 440 unsigned offset_a3, unsigned len_a4, unsigned len_a5) 441 { 442 return sys_fallocate(fd, mode, merge_64(offset_a2, offset_a3), 443 merge_64(len_a4, len_a5)); 444 } 445 446 save_static_function(sys32_clone); 447 static int noinline __used 448 _sys32_clone(nabi_no_regargs struct pt_regs regs) 449 { 450 unsigned long clone_flags; 451 unsigned long newsp; 452 int __user *parent_tidptr, *child_tidptr; 453 454 clone_flags = regs.regs[4]; 455 newsp = regs.regs[5]; 456 if (!newsp) 457 newsp = regs.regs[29]; 458 parent_tidptr = (int __user *) regs.regs[6]; 459 460 /* Use __dummy4 instead of getting it off the stack, so that 461 syscall() works. */ 462 child_tidptr = (int __user *) __dummy4; 463 return do_fork(clone_flags, newsp, ®s, 0, 464 parent_tidptr, child_tidptr); 465 } 466