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/config.h> 9 #include <linux/compiler.h> 10 #include <linux/mm.h> 11 #include <linux/errno.h> 12 #include <linux/file.h> 13 #include <linux/smp_lock.h> 14 #include <linux/highuid.h> 15 #include <linux/dirent.h> 16 #include <linux/resource.h> 17 #include <linux/highmem.h> 18 #include <linux/time.h> 19 #include <linux/times.h> 20 #include <linux/poll.h> 21 #include <linux/slab.h> 22 #include <linux/skbuff.h> 23 #include <linux/filter.h> 24 #include <linux/shm.h> 25 #include <linux/sem.h> 26 #include <linux/msg.h> 27 #include <linux/icmpv6.h> 28 #include <linux/syscalls.h> 29 #include <linux/sysctl.h> 30 #include <linux/utime.h> 31 #include <linux/utsname.h> 32 #include <linux/personality.h> 33 #include <linux/timex.h> 34 #include <linux/dnotify.h> 35 #include <linux/module.h> 36 #include <linux/binfmts.h> 37 #include <linux/security.h> 38 #include <linux/compat.h> 39 #include <linux/vfs.h> 40 41 #include <net/sock.h> 42 #include <net/scm.h> 43 44 #include <asm/ipc.h> 45 #include <asm/sim.h> 46 #include <asm/uaccess.h> 47 #include <asm/mmu_context.h> 48 #include <asm/mman.h> 49 50 /* Use this to get at 32-bit user passed pointers. */ 51 /* A() macro should be used for places where you e.g. 52 have some internal variable u32 and just want to get 53 rid of a compiler warning. AA() has to be used in 54 places where you want to convert a function argument 55 to 32bit pointer or when you e.g. access pt_regs 56 structure and want to consider 32bit registers only. 57 */ 58 #define A(__x) ((unsigned long)(__x)) 59 #define AA(__x) ((unsigned long)((int)__x)) 60 61 #ifdef __MIPSEB__ 62 #define merge_64(r1,r2) ((((r1) & 0xffffffffUL) << 32) + ((r2) & 0xffffffffUL)) 63 #endif 64 #ifdef __MIPSEL__ 65 #define merge_64(r1,r2) ((((r2) & 0xffffffffUL) << 32) + ((r1) & 0xffffffffUL)) 66 #endif 67 68 /* 69 * Revalidate the inode. This is required for proper NFS attribute caching. 70 */ 71 72 int cp_compat_stat(struct kstat *stat, struct compat_stat *statbuf) 73 { 74 struct compat_stat tmp; 75 76 if (!new_valid_dev(stat->dev) || !new_valid_dev(stat->rdev)) 77 return -EOVERFLOW; 78 79 memset(&tmp, 0, sizeof(tmp)); 80 tmp.st_dev = new_encode_dev(stat->dev); 81 tmp.st_ino = stat->ino; 82 tmp.st_mode = stat->mode; 83 tmp.st_nlink = stat->nlink; 84 SET_UID(tmp.st_uid, stat->uid); 85 SET_GID(tmp.st_gid, stat->gid); 86 tmp.st_rdev = new_encode_dev(stat->rdev); 87 tmp.st_size = stat->size; 88 tmp.st_atime = stat->atime.tv_sec; 89 tmp.st_mtime = stat->mtime.tv_sec; 90 tmp.st_ctime = stat->ctime.tv_sec; 91 #ifdef STAT_HAVE_NSEC 92 tmp.st_atime_nsec = stat->atime.tv_nsec; 93 tmp.st_mtime_nsec = stat->mtime.tv_nsec; 94 tmp.st_ctime_nsec = stat->ctime.tv_nsec; 95 #endif 96 tmp.st_blocks = stat->blocks; 97 tmp.st_blksize = stat->blksize; 98 return copy_to_user(statbuf,&tmp,sizeof(tmp)) ? -EFAULT : 0; 99 } 100 101 asmlinkage unsigned long 102 sys32_mmap2(unsigned long addr, unsigned long len, unsigned long prot, 103 unsigned long flags, unsigned long fd, unsigned long pgoff) 104 { 105 struct file * file = NULL; 106 unsigned long error; 107 108 error = -EINVAL; 109 if (!(flags & MAP_ANONYMOUS)) { 110 error = -EBADF; 111 file = fget(fd); 112 if (!file) 113 goto out; 114 } 115 flags &= ~(MAP_EXECUTABLE | MAP_DENYWRITE); 116 117 down_write(¤t->mm->mmap_sem); 118 error = do_mmap_pgoff(file, addr, len, prot, flags, pgoff); 119 up_write(¤t->mm->mmap_sem); 120 if (file) 121 fput(file); 122 123 out: 124 return error; 125 } 126 127 128 asmlinkage int sys_truncate64(const char *path, unsigned int high, 129 unsigned int low) 130 { 131 if ((int)high < 0) 132 return -EINVAL; 133 return sys_truncate(path, ((long) high << 32) | low); 134 } 135 136 asmlinkage int sys_ftruncate64(unsigned int fd, unsigned int high, 137 unsigned int low) 138 { 139 if ((int)high < 0) 140 return -EINVAL; 141 return sys_ftruncate(fd, ((long) high << 32) | low); 142 } 143 144 /* 145 * sys_execve() executes a new program. 146 */ 147 asmlinkage int sys32_execve(nabi_no_regargs struct pt_regs regs) 148 { 149 int error; 150 char * filename; 151 152 filename = getname(compat_ptr(regs.regs[4])); 153 error = PTR_ERR(filename); 154 if (IS_ERR(filename)) 155 goto out; 156 error = compat_do_execve(filename, compat_ptr(regs.regs[5]), 157 compat_ptr(regs.regs[6]), ®s); 158 putname(filename); 159 160 out: 161 return error; 162 } 163 164 struct dirent32 { 165 unsigned int d_ino; 166 unsigned int d_off; 167 unsigned short d_reclen; 168 char d_name[NAME_MAX + 1]; 169 }; 170 171 static void 172 xlate_dirent(void *dirent64, void *dirent32, long n) 173 { 174 long off; 175 struct dirent *dirp; 176 struct dirent32 *dirp32; 177 178 off = 0; 179 while (off < n) { 180 dirp = (struct dirent *)(dirent64 + off); 181 dirp32 = (struct dirent32 *)(dirent32 + off); 182 off += dirp->d_reclen; 183 dirp32->d_ino = dirp->d_ino; 184 dirp32->d_off = (unsigned int)dirp->d_off; 185 dirp32->d_reclen = dirp->d_reclen; 186 strncpy(dirp32->d_name, dirp->d_name, dirp->d_reclen - ((3 * 4) + 2)); 187 } 188 return; 189 } 190 191 asmlinkage long 192 sys32_getdents(unsigned int fd, void * dirent32, unsigned int count) 193 { 194 long n; 195 void *dirent64; 196 197 dirent64 = (void *)((unsigned long)(dirent32 + (sizeof(long) - 1)) & ~(sizeof(long) - 1)); 198 if ((n = sys_getdents(fd, dirent64, count - (dirent64 - dirent32))) < 0) 199 return(n); 200 xlate_dirent(dirent64, dirent32, n); 201 return(n); 202 } 203 204 asmlinkage int old_readdir(unsigned int fd, void * dirent, unsigned int count); 205 206 asmlinkage int 207 sys32_readdir(unsigned int fd, void * dirent32, unsigned int count) 208 { 209 int n; 210 struct dirent dirent64; 211 212 if ((n = old_readdir(fd, &dirent64, count)) < 0) 213 return(n); 214 xlate_dirent(&dirent64, dirent32, dirent64.d_reclen); 215 return(n); 216 } 217 218 asmlinkage int 219 sys32_waitpid(compat_pid_t pid, unsigned int *stat_addr, int options) 220 { 221 return compat_sys_wait4(pid, stat_addr, options, NULL); 222 } 223 224 asmlinkage long 225 sysn32_waitid(int which, compat_pid_t pid, 226 siginfo_t __user *uinfo, int options, 227 struct compat_rusage __user *uru) 228 { 229 struct rusage ru; 230 long ret; 231 mm_segment_t old_fs = get_fs(); 232 233 set_fs (KERNEL_DS); 234 ret = sys_waitid(which, pid, uinfo, options, 235 uru ? (struct rusage __user *) &ru : NULL); 236 set_fs (old_fs); 237 238 if (ret < 0 || uinfo->si_signo == 0) 239 return ret; 240 241 if (uru) 242 ret = put_compat_rusage(&ru, uru); 243 return ret; 244 } 245 246 struct sysinfo32 { 247 s32 uptime; 248 u32 loads[3]; 249 u32 totalram; 250 u32 freeram; 251 u32 sharedram; 252 u32 bufferram; 253 u32 totalswap; 254 u32 freeswap; 255 u16 procs; 256 u32 totalhigh; 257 u32 freehigh; 258 u32 mem_unit; 259 char _f[8]; 260 }; 261 262 asmlinkage int sys32_sysinfo(struct sysinfo32 *info) 263 { 264 struct sysinfo s; 265 int ret, err; 266 mm_segment_t old_fs = get_fs (); 267 268 set_fs (KERNEL_DS); 269 ret = sys_sysinfo(&s); 270 set_fs (old_fs); 271 err = put_user (s.uptime, &info->uptime); 272 err |= __put_user (s.loads[0], &info->loads[0]); 273 err |= __put_user (s.loads[1], &info->loads[1]); 274 err |= __put_user (s.loads[2], &info->loads[2]); 275 err |= __put_user (s.totalram, &info->totalram); 276 err |= __put_user (s.freeram, &info->freeram); 277 err |= __put_user (s.sharedram, &info->sharedram); 278 err |= __put_user (s.bufferram, &info->bufferram); 279 err |= __put_user (s.totalswap, &info->totalswap); 280 err |= __put_user (s.freeswap, &info->freeswap); 281 err |= __put_user (s.procs, &info->procs); 282 err |= __put_user (s.totalhigh, &info->totalhigh); 283 err |= __put_user (s.freehigh, &info->freehigh); 284 err |= __put_user (s.mem_unit, &info->mem_unit); 285 if (err) 286 return -EFAULT; 287 return ret; 288 } 289 290 #define RLIM_INFINITY32 0x7fffffff 291 #define RESOURCE32(x) ((x > RLIM_INFINITY32) ? RLIM_INFINITY32 : x) 292 293 struct rlimit32 { 294 int rlim_cur; 295 int rlim_max; 296 }; 297 298 #ifdef __MIPSEB__ 299 asmlinkage long sys32_truncate64(const char * path, unsigned long __dummy, 300 int length_hi, int length_lo) 301 #endif 302 #ifdef __MIPSEL__ 303 asmlinkage long sys32_truncate64(const char * path, unsigned long __dummy, 304 int length_lo, int length_hi) 305 #endif 306 { 307 loff_t length; 308 309 length = ((unsigned long) length_hi << 32) | (unsigned int) length_lo; 310 311 return sys_truncate(path, length); 312 } 313 314 #ifdef __MIPSEB__ 315 asmlinkage long sys32_ftruncate64(unsigned int fd, unsigned long __dummy, 316 int length_hi, int length_lo) 317 #endif 318 #ifdef __MIPSEL__ 319 asmlinkage long sys32_ftruncate64(unsigned int fd, unsigned long __dummy, 320 int length_lo, int length_hi) 321 #endif 322 { 323 loff_t length; 324 325 length = ((unsigned long) length_hi << 32) | (unsigned int) length_lo; 326 327 return sys_ftruncate(fd, length); 328 } 329 330 static inline long 331 get_tv32(struct timeval *o, struct compat_timeval *i) 332 { 333 return (!access_ok(VERIFY_READ, i, sizeof(*i)) || 334 (__get_user(o->tv_sec, &i->tv_sec) | 335 __get_user(o->tv_usec, &i->tv_usec))); 336 } 337 338 static inline long 339 put_tv32(struct compat_timeval *o, struct timeval *i) 340 { 341 return (!access_ok(VERIFY_WRITE, o, sizeof(*o)) || 342 (__put_user(i->tv_sec, &o->tv_sec) | 343 __put_user(i->tv_usec, &o->tv_usec))); 344 } 345 346 extern struct timezone sys_tz; 347 348 asmlinkage int 349 sys32_gettimeofday(struct compat_timeval *tv, struct timezone *tz) 350 { 351 if (tv) { 352 struct timeval ktv; 353 do_gettimeofday(&ktv); 354 if (put_tv32(tv, &ktv)) 355 return -EFAULT; 356 } 357 if (tz) { 358 if (copy_to_user(tz, &sys_tz, sizeof(sys_tz))) 359 return -EFAULT; 360 } 361 return 0; 362 } 363 364 static inline long get_ts32(struct timespec *o, struct compat_timeval *i) 365 { 366 long usec; 367 368 if (!access_ok(VERIFY_READ, i, sizeof(*i))) 369 return -EFAULT; 370 if (__get_user(o->tv_sec, &i->tv_sec)) 371 return -EFAULT; 372 if (__get_user(usec, &i->tv_usec)) 373 return -EFAULT; 374 o->tv_nsec = usec * 1000; 375 return 0; 376 } 377 378 asmlinkage int 379 sys32_settimeofday(struct compat_timeval *tv, struct timezone *tz) 380 { 381 struct timespec kts; 382 struct timezone ktz; 383 384 if (tv) { 385 if (get_ts32(&kts, tv)) 386 return -EFAULT; 387 } 388 if (tz) { 389 if (copy_from_user(&ktz, tz, sizeof(ktz))) 390 return -EFAULT; 391 } 392 393 return do_sys_settimeofday(tv ? &kts : NULL, tz ? &ktz : NULL); 394 } 395 396 asmlinkage int sys32_llseek(unsigned int fd, unsigned int offset_high, 397 unsigned int offset_low, loff_t * result, 398 unsigned int origin) 399 { 400 return sys_llseek(fd, offset_high, offset_low, result, origin); 401 } 402 403 /* From the Single Unix Spec: pread & pwrite act like lseek to pos + op + 404 lseek back to original location. They fail just like lseek does on 405 non-seekable files. */ 406 407 asmlinkage ssize_t sys32_pread(unsigned int fd, char * buf, 408 size_t count, u32 unused, u64 a4, u64 a5) 409 { 410 ssize_t ret; 411 struct file * file; 412 ssize_t (*read)(struct file *, char *, size_t, loff_t *); 413 loff_t pos; 414 415 ret = -EBADF; 416 file = fget(fd); 417 if (!file) 418 goto bad_file; 419 if (!(file->f_mode & FMODE_READ)) 420 goto out; 421 pos = merge_64(a4, a5); 422 ret = rw_verify_area(READ, file, &pos, count); 423 if (ret) 424 goto out; 425 ret = -EINVAL; 426 if (!file->f_op || !(read = file->f_op->read)) 427 goto out; 428 if (pos < 0) 429 goto out; 430 ret = -ESPIPE; 431 if (!(file->f_mode & FMODE_PREAD)) 432 goto out; 433 ret = read(file, buf, count, &pos); 434 if (ret > 0) 435 dnotify_parent(file->f_dentry, DN_ACCESS); 436 out: 437 fput(file); 438 bad_file: 439 return ret; 440 } 441 442 asmlinkage ssize_t sys32_pwrite(unsigned int fd, const char * buf, 443 size_t count, u32 unused, u64 a4, u64 a5) 444 { 445 ssize_t ret; 446 struct file * file; 447 ssize_t (*write)(struct file *, const char *, size_t, loff_t *); 448 loff_t pos; 449 450 ret = -EBADF; 451 file = fget(fd); 452 if (!file) 453 goto bad_file; 454 if (!(file->f_mode & FMODE_WRITE)) 455 goto out; 456 pos = merge_64(a4, a5); 457 ret = rw_verify_area(WRITE, file, &pos, count); 458 if (ret) 459 goto out; 460 ret = -EINVAL; 461 if (!file->f_op || !(write = file->f_op->write)) 462 goto out; 463 if (pos < 0) 464 goto out; 465 466 ret = -ESPIPE; 467 if (!(file->f_mode & FMODE_PWRITE)) 468 goto out; 469 470 ret = write(file, buf, count, &pos); 471 if (ret > 0) 472 dnotify_parent(file->f_dentry, DN_MODIFY); 473 out: 474 fput(file); 475 bad_file: 476 return ret; 477 } 478 479 asmlinkage int sys32_sched_rr_get_interval(compat_pid_t pid, 480 struct compat_timespec *interval) 481 { 482 struct timespec t; 483 int ret; 484 mm_segment_t old_fs = get_fs (); 485 486 set_fs (KERNEL_DS); 487 ret = sys_sched_rr_get_interval(pid, &t); 488 set_fs (old_fs); 489 if (put_user (t.tv_sec, &interval->tv_sec) || 490 __put_user (t.tv_nsec, &interval->tv_nsec)) 491 return -EFAULT; 492 return ret; 493 } 494 495 struct msgbuf32 { s32 mtype; char mtext[1]; }; 496 497 struct ipc_perm32 498 { 499 key_t key; 500 __compat_uid_t uid; 501 __compat_gid_t gid; 502 __compat_uid_t cuid; 503 __compat_gid_t cgid; 504 compat_mode_t mode; 505 unsigned short seq; 506 }; 507 508 struct ipc64_perm32 { 509 key_t key; 510 __compat_uid_t uid; 511 __compat_gid_t gid; 512 __compat_uid_t cuid; 513 __compat_gid_t cgid; 514 compat_mode_t mode; 515 unsigned short seq; 516 unsigned short __pad1; 517 unsigned int __unused1; 518 unsigned int __unused2; 519 }; 520 521 struct semid_ds32 { 522 struct ipc_perm32 sem_perm; /* permissions .. see ipc.h */ 523 compat_time_t sem_otime; /* last semop time */ 524 compat_time_t sem_ctime; /* last change time */ 525 u32 sem_base; /* ptr to first semaphore in array */ 526 u32 sem_pending; /* pending operations to be processed */ 527 u32 sem_pending_last; /* last pending operation */ 528 u32 undo; /* undo requests on this array */ 529 unsigned short sem_nsems; /* no. of semaphores in array */ 530 }; 531 532 struct semid64_ds32 { 533 struct ipc64_perm32 sem_perm; 534 compat_time_t sem_otime; 535 compat_time_t sem_ctime; 536 unsigned int sem_nsems; 537 unsigned int __unused1; 538 unsigned int __unused2; 539 }; 540 541 struct msqid_ds32 542 { 543 struct ipc_perm32 msg_perm; 544 u32 msg_first; 545 u32 msg_last; 546 compat_time_t msg_stime; 547 compat_time_t msg_rtime; 548 compat_time_t msg_ctime; 549 u32 wwait; 550 u32 rwait; 551 unsigned short msg_cbytes; 552 unsigned short msg_qnum; 553 unsigned short msg_qbytes; 554 compat_ipc_pid_t msg_lspid; 555 compat_ipc_pid_t msg_lrpid; 556 }; 557 558 struct msqid64_ds32 { 559 struct ipc64_perm32 msg_perm; 560 compat_time_t msg_stime; 561 unsigned int __unused1; 562 compat_time_t msg_rtime; 563 unsigned int __unused2; 564 compat_time_t msg_ctime; 565 unsigned int __unused3; 566 unsigned int msg_cbytes; 567 unsigned int msg_qnum; 568 unsigned int msg_qbytes; 569 compat_pid_t msg_lspid; 570 compat_pid_t msg_lrpid; 571 unsigned int __unused4; 572 unsigned int __unused5; 573 }; 574 575 struct shmid_ds32 { 576 struct ipc_perm32 shm_perm; 577 int shm_segsz; 578 compat_time_t shm_atime; 579 compat_time_t shm_dtime; 580 compat_time_t shm_ctime; 581 compat_ipc_pid_t shm_cpid; 582 compat_ipc_pid_t shm_lpid; 583 unsigned short shm_nattch; 584 }; 585 586 struct shmid64_ds32 { 587 struct ipc64_perm32 shm_perm; 588 compat_size_t shm_segsz; 589 compat_time_t shm_atime; 590 compat_time_t shm_dtime; 591 compat_time_t shm_ctime; 592 compat_pid_t shm_cpid; 593 compat_pid_t shm_lpid; 594 unsigned int shm_nattch; 595 unsigned int __unused1; 596 unsigned int __unused2; 597 }; 598 599 struct ipc_kludge32 { 600 u32 msgp; 601 s32 msgtyp; 602 }; 603 604 static int 605 do_sys32_semctl(int first, int second, int third, void *uptr) 606 { 607 union semun fourth; 608 u32 pad; 609 int err, err2; 610 struct semid64_ds s; 611 mm_segment_t old_fs; 612 613 if (!uptr) 614 return -EINVAL; 615 err = -EFAULT; 616 if (get_user (pad, (u32 *)uptr)) 617 return err; 618 if ((third & ~IPC_64) == SETVAL) 619 fourth.val = (int)pad; 620 else 621 fourth.__pad = (void *)A(pad); 622 switch (third & ~IPC_64) { 623 case IPC_INFO: 624 case IPC_RMID: 625 case IPC_SET: 626 case SEM_INFO: 627 case GETVAL: 628 case GETPID: 629 case GETNCNT: 630 case GETZCNT: 631 case GETALL: 632 case SETVAL: 633 case SETALL: 634 err = sys_semctl (first, second, third, fourth); 635 break; 636 637 case IPC_STAT: 638 case SEM_STAT: 639 fourth.__pad = &s; 640 old_fs = get_fs(); 641 set_fs(KERNEL_DS); 642 err = sys_semctl(first, second, third | IPC_64, fourth); 643 set_fs(old_fs); 644 645 if (third & IPC_64) { 646 struct semid64_ds32 *usp64 = (struct semid64_ds32 *) A(pad); 647 648 if (!access_ok(VERIFY_WRITE, usp64, sizeof(*usp64))) { 649 err = -EFAULT; 650 break; 651 } 652 err2 = __put_user(s.sem_perm.key, &usp64->sem_perm.key); 653 err2 |= __put_user(s.sem_perm.uid, &usp64->sem_perm.uid); 654 err2 |= __put_user(s.sem_perm.gid, &usp64->sem_perm.gid); 655 err2 |= __put_user(s.sem_perm.cuid, &usp64->sem_perm.cuid); 656 err2 |= __put_user(s.sem_perm.cgid, &usp64->sem_perm.cgid); 657 err2 |= __put_user(s.sem_perm.mode, &usp64->sem_perm.mode); 658 err2 |= __put_user(s.sem_perm.seq, &usp64->sem_perm.seq); 659 err2 |= __put_user(s.sem_otime, &usp64->sem_otime); 660 err2 |= __put_user(s.sem_ctime, &usp64->sem_ctime); 661 err2 |= __put_user(s.sem_nsems, &usp64->sem_nsems); 662 } else { 663 struct semid_ds32 *usp32 = (struct semid_ds32 *) A(pad); 664 665 if (!access_ok(VERIFY_WRITE, usp32, sizeof(*usp32))) { 666 err = -EFAULT; 667 break; 668 } 669 err2 = __put_user(s.sem_perm.key, &usp32->sem_perm.key); 670 err2 |= __put_user(s.sem_perm.uid, &usp32->sem_perm.uid); 671 err2 |= __put_user(s.sem_perm.gid, &usp32->sem_perm.gid); 672 err2 |= __put_user(s.sem_perm.cuid, &usp32->sem_perm.cuid); 673 err2 |= __put_user(s.sem_perm.cgid, &usp32->sem_perm.cgid); 674 err2 |= __put_user(s.sem_perm.mode, &usp32->sem_perm.mode); 675 err2 |= __put_user(s.sem_perm.seq, &usp32->sem_perm.seq); 676 err2 |= __put_user(s.sem_otime, &usp32->sem_otime); 677 err2 |= __put_user(s.sem_ctime, &usp32->sem_ctime); 678 err2 |= __put_user(s.sem_nsems, &usp32->sem_nsems); 679 } 680 if (err2) 681 err = -EFAULT; 682 break; 683 684 default: 685 err = - EINVAL; 686 break; 687 } 688 689 return err; 690 } 691 692 static int 693 do_sys32_msgsnd (int first, int second, int third, void *uptr) 694 { 695 struct msgbuf32 *up = (struct msgbuf32 *)uptr; 696 struct msgbuf *p; 697 mm_segment_t old_fs; 698 int err; 699 700 if (second < 0) 701 return -EINVAL; 702 p = kmalloc (second + sizeof (struct msgbuf) 703 + 4, GFP_USER); 704 if (!p) 705 return -ENOMEM; 706 err = get_user (p->mtype, &up->mtype); 707 if (err) 708 goto out; 709 err |= __copy_from_user (p->mtext, &up->mtext, second); 710 if (err) 711 goto out; 712 old_fs = get_fs (); 713 set_fs (KERNEL_DS); 714 err = sys_msgsnd (first, p, second, third); 715 set_fs (old_fs); 716 out: 717 kfree (p); 718 719 return err; 720 } 721 722 static int 723 do_sys32_msgrcv (int first, int second, int msgtyp, int third, 724 int version, void *uptr) 725 { 726 struct msgbuf32 *up; 727 struct msgbuf *p; 728 mm_segment_t old_fs; 729 int err; 730 731 if (!version) { 732 struct ipc_kludge32 *uipck = (struct ipc_kludge32 *)uptr; 733 struct ipc_kludge32 ipck; 734 735 err = -EINVAL; 736 if (!uptr) 737 goto out; 738 err = -EFAULT; 739 if (copy_from_user (&ipck, uipck, sizeof (struct ipc_kludge32))) 740 goto out; 741 uptr = (void *)AA(ipck.msgp); 742 msgtyp = ipck.msgtyp; 743 } 744 745 if (second < 0) 746 return -EINVAL; 747 err = -ENOMEM; 748 p = kmalloc (second + sizeof (struct msgbuf) + 4, GFP_USER); 749 if (!p) 750 goto out; 751 old_fs = get_fs (); 752 set_fs (KERNEL_DS); 753 err = sys_msgrcv (first, p, second + 4, msgtyp, third); 754 set_fs (old_fs); 755 if (err < 0) 756 goto free_then_out; 757 up = (struct msgbuf32 *)uptr; 758 if (put_user (p->mtype, &up->mtype) || 759 __copy_to_user (&up->mtext, p->mtext, err)) 760 err = -EFAULT; 761 free_then_out: 762 kfree (p); 763 out: 764 return err; 765 } 766 767 static int 768 do_sys32_msgctl (int first, int second, void *uptr) 769 { 770 int err = -EINVAL, err2; 771 struct msqid64_ds m; 772 struct msqid_ds32 *up32 = (struct msqid_ds32 *)uptr; 773 struct msqid64_ds32 *up64 = (struct msqid64_ds32 *)uptr; 774 mm_segment_t old_fs; 775 776 switch (second & ~IPC_64) { 777 case IPC_INFO: 778 case IPC_RMID: 779 case MSG_INFO: 780 err = sys_msgctl (first, second, (struct msqid_ds *)uptr); 781 break; 782 783 case IPC_SET: 784 if (second & IPC_64) { 785 if (!access_ok(VERIFY_READ, up64, sizeof(*up64))) { 786 err = -EFAULT; 787 break; 788 } 789 err = __get_user(m.msg_perm.uid, &up64->msg_perm.uid); 790 err |= __get_user(m.msg_perm.gid, &up64->msg_perm.gid); 791 err |= __get_user(m.msg_perm.mode, &up64->msg_perm.mode); 792 err |= __get_user(m.msg_qbytes, &up64->msg_qbytes); 793 } else { 794 if (!access_ok(VERIFY_READ, up32, sizeof(*up32))) { 795 err = -EFAULT; 796 break; 797 } 798 err = __get_user(m.msg_perm.uid, &up32->msg_perm.uid); 799 err |= __get_user(m.msg_perm.gid, &up32->msg_perm.gid); 800 err |= __get_user(m.msg_perm.mode, &up32->msg_perm.mode); 801 err |= __get_user(m.msg_qbytes, &up32->msg_qbytes); 802 } 803 if (err) 804 break; 805 old_fs = get_fs(); 806 set_fs(KERNEL_DS); 807 err = sys_msgctl(first, second | IPC_64, (struct msqid_ds *)&m); 808 set_fs(old_fs); 809 break; 810 811 case IPC_STAT: 812 case MSG_STAT: 813 old_fs = get_fs(); 814 set_fs(KERNEL_DS); 815 err = sys_msgctl(first, second | IPC_64, (struct msqid_ds *)&m); 816 set_fs(old_fs); 817 if (second & IPC_64) { 818 if (!access_ok(VERIFY_WRITE, up64, sizeof(*up64))) { 819 err = -EFAULT; 820 break; 821 } 822 err2 = __put_user(m.msg_perm.key, &up64->msg_perm.key); 823 err2 |= __put_user(m.msg_perm.uid, &up64->msg_perm.uid); 824 err2 |= __put_user(m.msg_perm.gid, &up64->msg_perm.gid); 825 err2 |= __put_user(m.msg_perm.cuid, &up64->msg_perm.cuid); 826 err2 |= __put_user(m.msg_perm.cgid, &up64->msg_perm.cgid); 827 err2 |= __put_user(m.msg_perm.mode, &up64->msg_perm.mode); 828 err2 |= __put_user(m.msg_perm.seq, &up64->msg_perm.seq); 829 err2 |= __put_user(m.msg_stime, &up64->msg_stime); 830 err2 |= __put_user(m.msg_rtime, &up64->msg_rtime); 831 err2 |= __put_user(m.msg_ctime, &up64->msg_ctime); 832 err2 |= __put_user(m.msg_cbytes, &up64->msg_cbytes); 833 err2 |= __put_user(m.msg_qnum, &up64->msg_qnum); 834 err2 |= __put_user(m.msg_qbytes, &up64->msg_qbytes); 835 err2 |= __put_user(m.msg_lspid, &up64->msg_lspid); 836 err2 |= __put_user(m.msg_lrpid, &up64->msg_lrpid); 837 if (err2) 838 err = -EFAULT; 839 } else { 840 if (!access_ok(VERIFY_WRITE, up32, sizeof(*up32))) { 841 err = -EFAULT; 842 break; 843 } 844 err2 = __put_user(m.msg_perm.key, &up32->msg_perm.key); 845 err2 |= __put_user(m.msg_perm.uid, &up32->msg_perm.uid); 846 err2 |= __put_user(m.msg_perm.gid, &up32->msg_perm.gid); 847 err2 |= __put_user(m.msg_perm.cuid, &up32->msg_perm.cuid); 848 err2 |= __put_user(m.msg_perm.cgid, &up32->msg_perm.cgid); 849 err2 |= __put_user(m.msg_perm.mode, &up32->msg_perm.mode); 850 err2 |= __put_user(m.msg_perm.seq, &up32->msg_perm.seq); 851 err2 |= __put_user(m.msg_stime, &up32->msg_stime); 852 err2 |= __put_user(m.msg_rtime, &up32->msg_rtime); 853 err2 |= __put_user(m.msg_ctime, &up32->msg_ctime); 854 err2 |= __put_user(m.msg_cbytes, &up32->msg_cbytes); 855 err2 |= __put_user(m.msg_qnum, &up32->msg_qnum); 856 err2 |= __put_user(m.msg_qbytes, &up32->msg_qbytes); 857 err2 |= __put_user(m.msg_lspid, &up32->msg_lspid); 858 err2 |= __put_user(m.msg_lrpid, &up32->msg_lrpid); 859 if (err2) 860 err = -EFAULT; 861 } 862 break; 863 } 864 865 return err; 866 } 867 868 static int 869 do_sys32_shmat (int first, int second, int third, int version, void *uptr) 870 { 871 unsigned long raddr; 872 u32 *uaddr = (u32 *)A((u32)third); 873 int err = -EINVAL; 874 875 if (version == 1) 876 return err; 877 err = do_shmat (first, uptr, second, &raddr); 878 if (err) 879 return err; 880 err = put_user (raddr, uaddr); 881 return err; 882 } 883 884 struct shm_info32 { 885 int used_ids; 886 u32 shm_tot, shm_rss, shm_swp; 887 u32 swap_attempts, swap_successes; 888 }; 889 890 static int 891 do_sys32_shmctl (int first, int second, void *uptr) 892 { 893 struct shmid64_ds32 *up64 = (struct shmid64_ds32 *)uptr; 894 struct shmid_ds32 *up32 = (struct shmid_ds32 *)uptr; 895 struct shm_info32 *uip = (struct shm_info32 *)uptr; 896 int err = -EFAULT, err2; 897 struct shmid64_ds s64; 898 mm_segment_t old_fs; 899 struct shm_info si; 900 struct shmid_ds s; 901 902 switch (second & ~IPC_64) { 903 case IPC_INFO: 904 second = IPC_INFO; /* So that we don't have to translate it */ 905 case IPC_RMID: 906 case SHM_LOCK: 907 case SHM_UNLOCK: 908 err = sys_shmctl(first, second, (struct shmid_ds *)uptr); 909 break; 910 case IPC_SET: 911 if (second & IPC_64) { 912 err = get_user(s.shm_perm.uid, &up64->shm_perm.uid); 913 err |= get_user(s.shm_perm.gid, &up64->shm_perm.gid); 914 err |= get_user(s.shm_perm.mode, &up64->shm_perm.mode); 915 } else { 916 err = get_user(s.shm_perm.uid, &up32->shm_perm.uid); 917 err |= get_user(s.shm_perm.gid, &up32->shm_perm.gid); 918 err |= get_user(s.shm_perm.mode, &up32->shm_perm.mode); 919 } 920 if (err) 921 break; 922 old_fs = get_fs(); 923 set_fs(KERNEL_DS); 924 err = sys_shmctl(first, second & ~IPC_64, &s); 925 set_fs(old_fs); 926 break; 927 928 case IPC_STAT: 929 case SHM_STAT: 930 old_fs = get_fs(); 931 set_fs(KERNEL_DS); 932 err = sys_shmctl(first, second | IPC_64, (void *) &s64); 933 set_fs(old_fs); 934 if (err < 0) 935 break; 936 if (second & IPC_64) { 937 if (!access_ok(VERIFY_WRITE, up64, sizeof(*up64))) { 938 err = -EFAULT; 939 break; 940 } 941 err2 = __put_user(s64.shm_perm.key, &up64->shm_perm.key); 942 err2 |= __put_user(s64.shm_perm.uid, &up64->shm_perm.uid); 943 err2 |= __put_user(s64.shm_perm.gid, &up64->shm_perm.gid); 944 err2 |= __put_user(s64.shm_perm.cuid, &up64->shm_perm.cuid); 945 err2 |= __put_user(s64.shm_perm.cgid, &up64->shm_perm.cgid); 946 err2 |= __put_user(s64.shm_perm.mode, &up64->shm_perm.mode); 947 err2 |= __put_user(s64.shm_perm.seq, &up64->shm_perm.seq); 948 err2 |= __put_user(s64.shm_atime, &up64->shm_atime); 949 err2 |= __put_user(s64.shm_dtime, &up64->shm_dtime); 950 err2 |= __put_user(s64.shm_ctime, &up64->shm_ctime); 951 err2 |= __put_user(s64.shm_segsz, &up64->shm_segsz); 952 err2 |= __put_user(s64.shm_nattch, &up64->shm_nattch); 953 err2 |= __put_user(s64.shm_cpid, &up64->shm_cpid); 954 err2 |= __put_user(s64.shm_lpid, &up64->shm_lpid); 955 } else { 956 if (!access_ok(VERIFY_WRITE, up32, sizeof(*up32))) { 957 err = -EFAULT; 958 break; 959 } 960 err2 = __put_user(s64.shm_perm.key, &up32->shm_perm.key); 961 err2 |= __put_user(s64.shm_perm.uid, &up32->shm_perm.uid); 962 err2 |= __put_user(s64.shm_perm.gid, &up32->shm_perm.gid); 963 err2 |= __put_user(s64.shm_perm.cuid, &up32->shm_perm.cuid); 964 err2 |= __put_user(s64.shm_perm.cgid, &up32->shm_perm.cgid); 965 err2 |= __put_user(s64.shm_perm.mode, &up32->shm_perm.mode); 966 err2 |= __put_user(s64.shm_perm.seq, &up32->shm_perm.seq); 967 err2 |= __put_user(s64.shm_atime, &up32->shm_atime); 968 err2 |= __put_user(s64.shm_dtime, &up32->shm_dtime); 969 err2 |= __put_user(s64.shm_ctime, &up32->shm_ctime); 970 err2 |= __put_user(s64.shm_segsz, &up32->shm_segsz); 971 err2 |= __put_user(s64.shm_nattch, &up32->shm_nattch); 972 err2 |= __put_user(s64.shm_cpid, &up32->shm_cpid); 973 err2 |= __put_user(s64.shm_lpid, &up32->shm_lpid); 974 } 975 if (err2) 976 err = -EFAULT; 977 break; 978 979 case SHM_INFO: 980 old_fs = get_fs(); 981 set_fs(KERNEL_DS); 982 err = sys_shmctl(first, second, (void *)&si); 983 set_fs(old_fs); 984 if (err < 0) 985 break; 986 err2 = put_user(si.used_ids, &uip->used_ids); 987 err2 |= __put_user(si.shm_tot, &uip->shm_tot); 988 err2 |= __put_user(si.shm_rss, &uip->shm_rss); 989 err2 |= __put_user(si.shm_swp, &uip->shm_swp); 990 err2 |= __put_user(si.swap_attempts, &uip->swap_attempts); 991 err2 |= __put_user (si.swap_successes, &uip->swap_successes); 992 if (err2) 993 err = -EFAULT; 994 break; 995 996 default: 997 err = -EINVAL; 998 break; 999 } 1000 1001 return err; 1002 } 1003 1004 static int sys32_semtimedop(int semid, struct sembuf *tsems, int nsems, 1005 const struct compat_timespec *timeout32) 1006 { 1007 struct compat_timespec t32; 1008 struct timespec *t64 = compat_alloc_user_space(sizeof(*t64)); 1009 1010 if (copy_from_user(&t32, timeout32, sizeof(t32))) 1011 return -EFAULT; 1012 1013 if (put_user(t32.tv_sec, &t64->tv_sec) || 1014 put_user(t32.tv_nsec, &t64->tv_nsec)) 1015 return -EFAULT; 1016 1017 return sys_semtimedop(semid, tsems, nsems, t64); 1018 } 1019 1020 asmlinkage long 1021 sys32_ipc (u32 call, int first, int second, int third, u32 ptr, u32 fifth) 1022 { 1023 int version, err; 1024 1025 version = call >> 16; /* hack for backward compatibility */ 1026 call &= 0xffff; 1027 1028 switch (call) { 1029 case SEMOP: 1030 /* struct sembuf is the same on 32 and 64bit :)) */ 1031 err = sys_semtimedop (first, (struct sembuf *)AA(ptr), second, 1032 NULL); 1033 break; 1034 case SEMTIMEDOP: 1035 err = sys32_semtimedop (first, (struct sembuf *)AA(ptr), second, 1036 (const struct compat_timespec __user *)AA(fifth)); 1037 break; 1038 case SEMGET: 1039 err = sys_semget (first, second, third); 1040 break; 1041 case SEMCTL: 1042 err = do_sys32_semctl (first, second, third, 1043 (void *)AA(ptr)); 1044 break; 1045 1046 case MSGSND: 1047 err = do_sys32_msgsnd (first, second, third, 1048 (void *)AA(ptr)); 1049 break; 1050 case MSGRCV: 1051 err = do_sys32_msgrcv (first, second, fifth, third, 1052 version, (void *)AA(ptr)); 1053 break; 1054 case MSGGET: 1055 err = sys_msgget ((key_t) first, second); 1056 break; 1057 case MSGCTL: 1058 err = do_sys32_msgctl (first, second, (void *)AA(ptr)); 1059 break; 1060 1061 case SHMAT: 1062 err = do_sys32_shmat (first, second, third, 1063 version, (void *)AA(ptr)); 1064 break; 1065 case SHMDT: 1066 err = sys_shmdt ((char *)A(ptr)); 1067 break; 1068 case SHMGET: 1069 err = sys_shmget (first, (unsigned)second, third); 1070 break; 1071 case SHMCTL: 1072 err = do_sys32_shmctl (first, second, (void *)AA(ptr)); 1073 break; 1074 default: 1075 err = -EINVAL; 1076 break; 1077 } 1078 1079 return err; 1080 } 1081 1082 asmlinkage long sys32_shmat(int shmid, char __user *shmaddr, 1083 int shmflg, int32_t *addr) 1084 { 1085 unsigned long raddr; 1086 int err; 1087 1088 err = do_shmat(shmid, shmaddr, shmflg, &raddr); 1089 if (err) 1090 return err; 1091 1092 return put_user(raddr, addr); 1093 } 1094 1095 struct sysctl_args32 1096 { 1097 compat_caddr_t name; 1098 int nlen; 1099 compat_caddr_t oldval; 1100 compat_caddr_t oldlenp; 1101 compat_caddr_t newval; 1102 compat_size_t newlen; 1103 unsigned int __unused[4]; 1104 }; 1105 1106 #ifdef CONFIG_SYSCTL 1107 1108 asmlinkage long sys32_sysctl(struct sysctl_args32 *args) 1109 { 1110 struct sysctl_args32 tmp; 1111 int error; 1112 size_t oldlen, *oldlenp = NULL; 1113 unsigned long addr = (((long)&args->__unused[0]) + 7) & ~7; 1114 1115 if (copy_from_user(&tmp, args, sizeof(tmp))) 1116 return -EFAULT; 1117 1118 if (tmp.oldval && tmp.oldlenp) { 1119 /* Duh, this is ugly and might not work if sysctl_args 1120 is in read-only memory, but do_sysctl does indirectly 1121 a lot of uaccess in both directions and we'd have to 1122 basically copy the whole sysctl.c here, and 1123 glibc's __sysctl uses rw memory for the structure 1124 anyway. */ 1125 if (get_user(oldlen, (u32 *)A(tmp.oldlenp)) || 1126 put_user(oldlen, (size_t *)addr)) 1127 return -EFAULT; 1128 oldlenp = (size_t *)addr; 1129 } 1130 1131 lock_kernel(); 1132 error = do_sysctl((int *)A(tmp.name), tmp.nlen, (void *)A(tmp.oldval), 1133 oldlenp, (void *)A(tmp.newval), tmp.newlen); 1134 unlock_kernel(); 1135 if (oldlenp) { 1136 if (!error) { 1137 if (get_user(oldlen, (size_t *)addr) || 1138 put_user(oldlen, (u32 *)A(tmp.oldlenp))) 1139 error = -EFAULT; 1140 } 1141 copy_to_user(args->__unused, tmp.__unused, sizeof(tmp.__unused)); 1142 } 1143 return error; 1144 } 1145 1146 #endif /* CONFIG_SYSCTL */ 1147 1148 asmlinkage long sys32_newuname(struct new_utsname * name) 1149 { 1150 int ret = 0; 1151 1152 down_read(&uts_sem); 1153 if (copy_to_user(name,&system_utsname,sizeof *name)) 1154 ret = -EFAULT; 1155 up_read(&uts_sem); 1156 1157 if (current->personality == PER_LINUX32 && !ret) 1158 if (copy_to_user(name->machine, "mips\0\0\0", 8)) 1159 ret = -EFAULT; 1160 1161 return ret; 1162 } 1163 1164 asmlinkage int sys32_personality(unsigned long personality) 1165 { 1166 int ret; 1167 if (current->personality == PER_LINUX32 && personality == PER_LINUX) 1168 personality = PER_LINUX32; 1169 ret = sys_personality(personality); 1170 if (ret == PER_LINUX32) 1171 ret = PER_LINUX; 1172 return ret; 1173 } 1174 1175 /* ustat compatibility */ 1176 struct ustat32 { 1177 compat_daddr_t f_tfree; 1178 compat_ino_t f_tinode; 1179 char f_fname[6]; 1180 char f_fpack[6]; 1181 }; 1182 1183 extern asmlinkage long sys_ustat(dev_t dev, struct ustat * ubuf); 1184 1185 asmlinkage int sys32_ustat(dev_t dev, struct ustat32 * ubuf32) 1186 { 1187 int err; 1188 struct ustat tmp; 1189 struct ustat32 tmp32; 1190 mm_segment_t old_fs = get_fs(); 1191 1192 set_fs(KERNEL_DS); 1193 err = sys_ustat(dev, &tmp); 1194 set_fs (old_fs); 1195 1196 if (err) 1197 goto out; 1198 1199 memset(&tmp32,0,sizeof(struct ustat32)); 1200 tmp32.f_tfree = tmp.f_tfree; 1201 tmp32.f_tinode = tmp.f_tinode; 1202 1203 err = copy_to_user(ubuf32,&tmp32,sizeof(struct ustat32)) ? -EFAULT : 0; 1204 1205 out: 1206 return err; 1207 } 1208 1209 /* Handle adjtimex compatibility. */ 1210 1211 struct timex32 { 1212 u32 modes; 1213 s32 offset, freq, maxerror, esterror; 1214 s32 status, constant, precision, tolerance; 1215 struct compat_timeval time; 1216 s32 tick; 1217 s32 ppsfreq, jitter, shift, stabil; 1218 s32 jitcnt, calcnt, errcnt, stbcnt; 1219 s32 :32; s32 :32; s32 :32; s32 :32; 1220 s32 :32; s32 :32; s32 :32; s32 :32; 1221 s32 :32; s32 :32; s32 :32; s32 :32; 1222 }; 1223 1224 extern int do_adjtimex(struct timex *); 1225 1226 asmlinkage int sys32_adjtimex(struct timex32 *utp) 1227 { 1228 struct timex txc; 1229 int ret; 1230 1231 memset(&txc, 0, sizeof(struct timex)); 1232 1233 if (get_user(txc.modes, &utp->modes) || 1234 __get_user(txc.offset, &utp->offset) || 1235 __get_user(txc.freq, &utp->freq) || 1236 __get_user(txc.maxerror, &utp->maxerror) || 1237 __get_user(txc.esterror, &utp->esterror) || 1238 __get_user(txc.status, &utp->status) || 1239 __get_user(txc.constant, &utp->constant) || 1240 __get_user(txc.precision, &utp->precision) || 1241 __get_user(txc.tolerance, &utp->tolerance) || 1242 __get_user(txc.time.tv_sec, &utp->time.tv_sec) || 1243 __get_user(txc.time.tv_usec, &utp->time.tv_usec) || 1244 __get_user(txc.tick, &utp->tick) || 1245 __get_user(txc.ppsfreq, &utp->ppsfreq) || 1246 __get_user(txc.jitter, &utp->jitter) || 1247 __get_user(txc.shift, &utp->shift) || 1248 __get_user(txc.stabil, &utp->stabil) || 1249 __get_user(txc.jitcnt, &utp->jitcnt) || 1250 __get_user(txc.calcnt, &utp->calcnt) || 1251 __get_user(txc.errcnt, &utp->errcnt) || 1252 __get_user(txc.stbcnt, &utp->stbcnt)) 1253 return -EFAULT; 1254 1255 ret = do_adjtimex(&txc); 1256 1257 if (put_user(txc.modes, &utp->modes) || 1258 __put_user(txc.offset, &utp->offset) || 1259 __put_user(txc.freq, &utp->freq) || 1260 __put_user(txc.maxerror, &utp->maxerror) || 1261 __put_user(txc.esterror, &utp->esterror) || 1262 __put_user(txc.status, &utp->status) || 1263 __put_user(txc.constant, &utp->constant) || 1264 __put_user(txc.precision, &utp->precision) || 1265 __put_user(txc.tolerance, &utp->tolerance) || 1266 __put_user(txc.time.tv_sec, &utp->time.tv_sec) || 1267 __put_user(txc.time.tv_usec, &utp->time.tv_usec) || 1268 __put_user(txc.tick, &utp->tick) || 1269 __put_user(txc.ppsfreq, &utp->ppsfreq) || 1270 __put_user(txc.jitter, &utp->jitter) || 1271 __put_user(txc.shift, &utp->shift) || 1272 __put_user(txc.stabil, &utp->stabil) || 1273 __put_user(txc.jitcnt, &utp->jitcnt) || 1274 __put_user(txc.calcnt, &utp->calcnt) || 1275 __put_user(txc.errcnt, &utp->errcnt) || 1276 __put_user(txc.stbcnt, &utp->stbcnt)) 1277 ret = -EFAULT; 1278 1279 return ret; 1280 } 1281 1282 asmlinkage int sys32_sendfile(int out_fd, int in_fd, compat_off_t *offset, 1283 s32 count) 1284 { 1285 mm_segment_t old_fs = get_fs(); 1286 int ret; 1287 off_t of; 1288 1289 if (offset && get_user(of, offset)) 1290 return -EFAULT; 1291 1292 set_fs(KERNEL_DS); 1293 ret = sys_sendfile(out_fd, in_fd, offset ? &of : NULL, count); 1294 set_fs(old_fs); 1295 1296 if (offset && put_user(of, offset)) 1297 return -EFAULT; 1298 1299 return ret; 1300 } 1301 1302 asmlinkage ssize_t sys32_readahead(int fd, u32 pad0, u64 a2, u64 a3, 1303 size_t count) 1304 { 1305 return sys_readahead(fd, merge_64(a2, a3), count); 1306 } 1307 1308 /* Argument list sizes for sys_socketcall */ 1309 #define AL(x) ((x) * sizeof(unsigned int)) 1310 static unsigned char socketcall_nargs[18]={AL(0),AL(3),AL(3),AL(3),AL(2),AL(3), 1311 AL(3),AL(3),AL(4),AL(4),AL(4),AL(6), 1312 AL(6),AL(2),AL(5),AL(5),AL(3),AL(3)}; 1313 #undef AL 1314 1315 /* 1316 * System call vectors. 1317 * 1318 * Argument checking cleaned up. Saved 20% in size. 1319 * This function doesn't need to set the kernel lock because 1320 * it is set by the callees. 1321 */ 1322 1323 asmlinkage long sys32_socketcall(int call, unsigned int *args32) 1324 { 1325 unsigned int a[6]; 1326 unsigned int a0,a1; 1327 int err; 1328 1329 extern asmlinkage long sys_socket(int family, int type, int protocol); 1330 extern asmlinkage long sys_bind(int fd, struct sockaddr __user *umyaddr, int addrlen); 1331 extern asmlinkage long sys_connect(int fd, struct sockaddr __user *uservaddr, int addrlen); 1332 extern asmlinkage long sys_listen(int fd, int backlog); 1333 extern asmlinkage long sys_accept(int fd, struct sockaddr __user *upeer_sockaddr, int __user *upeer_addrlen); 1334 extern asmlinkage long sys_getsockname(int fd, struct sockaddr __user *usockaddr, int __user *usockaddr_len); 1335 extern asmlinkage long sys_getpeername(int fd, struct sockaddr __user *usockaddr, int __user *usockaddr_len); 1336 extern asmlinkage long sys_socketpair(int family, int type, int protocol, int __user *usockvec); 1337 extern asmlinkage long sys_send(int fd, void __user * buff, size_t len, unsigned flags); 1338 extern asmlinkage long sys_sendto(int fd, void __user * buff, size_t len, unsigned flags, 1339 struct sockaddr __user *addr, int addr_len); 1340 extern asmlinkage long sys_recv(int fd, void __user * ubuf, size_t size, unsigned flags); 1341 extern asmlinkage long sys_recvfrom(int fd, void __user * ubuf, size_t size, unsigned flags, 1342 struct sockaddr __user *addr, int __user *addr_len); 1343 extern asmlinkage long sys_shutdown(int fd, int how); 1344 extern asmlinkage long sys_setsockopt(int fd, int level, int optname, char __user *optval, int optlen); 1345 extern asmlinkage long sys_getsockopt(int fd, int level, int optname, char __user *optval, int *optlen); 1346 extern asmlinkage long sys_sendmsg(int fd, struct msghdr __user *msg, unsigned flags); 1347 extern asmlinkage long sys_recvmsg(int fd, struct msghdr __user *msg, unsigned int flags); 1348 1349 1350 if(call<1||call>SYS_RECVMSG) 1351 return -EINVAL; 1352 1353 /* copy_from_user should be SMP safe. */ 1354 if (copy_from_user(a, args32, socketcall_nargs[call])) 1355 return -EFAULT; 1356 1357 a0=a[0]; 1358 a1=a[1]; 1359 1360 switch(call) 1361 { 1362 case SYS_SOCKET: 1363 err = sys_socket(a0,a1,a[2]); 1364 break; 1365 case SYS_BIND: 1366 err = sys_bind(a0,(struct sockaddr __user *)A(a1), a[2]); 1367 break; 1368 case SYS_CONNECT: 1369 err = sys_connect(a0, (struct sockaddr __user *)A(a1), a[2]); 1370 break; 1371 case SYS_LISTEN: 1372 err = sys_listen(a0,a1); 1373 break; 1374 case SYS_ACCEPT: 1375 err = sys_accept(a0,(struct sockaddr __user *)A(a1), (int __user *)A(a[2])); 1376 break; 1377 case SYS_GETSOCKNAME: 1378 err = sys_getsockname(a0,(struct sockaddr __user *)A(a1), (int __user *)A(a[2])); 1379 break; 1380 case SYS_GETPEERNAME: 1381 err = sys_getpeername(a0, (struct sockaddr __user *)A(a1), (int __user *)A(a[2])); 1382 break; 1383 case SYS_SOCKETPAIR: 1384 err = sys_socketpair(a0,a1, a[2], (int __user *)A(a[3])); 1385 break; 1386 case SYS_SEND: 1387 err = sys_send(a0, (void __user *)A(a1), a[2], a[3]); 1388 break; 1389 case SYS_SENDTO: 1390 err = sys_sendto(a0,(void __user *)A(a1), a[2], a[3], 1391 (struct sockaddr __user *)A(a[4]), a[5]); 1392 break; 1393 case SYS_RECV: 1394 err = sys_recv(a0, (void __user *)A(a1), a[2], a[3]); 1395 break; 1396 case SYS_RECVFROM: 1397 err = sys_recvfrom(a0, (void __user *)A(a1), a[2], a[3], 1398 (struct sockaddr __user *)A(a[4]), (int __user *)A(a[5])); 1399 break; 1400 case SYS_SHUTDOWN: 1401 err = sys_shutdown(a0,a1); 1402 break; 1403 case SYS_SETSOCKOPT: 1404 err = sys_setsockopt(a0, a1, a[2], (char __user *)A(a[3]), a[4]); 1405 break; 1406 case SYS_GETSOCKOPT: 1407 err = sys_getsockopt(a0, a1, a[2], (char __user *)A(a[3]), (int __user *)A(a[4])); 1408 break; 1409 case SYS_SENDMSG: 1410 err = sys_sendmsg(a0, (struct msghdr __user *) A(a1), a[2]); 1411 break; 1412 case SYS_RECVMSG: 1413 err = sys_recvmsg(a0, (struct msghdr __user *) A(a1), a[2]); 1414 break; 1415 default: 1416 err = -EINVAL; 1417 break; 1418 } 1419 return err; 1420 } 1421 1422 struct sigevent32 { 1423 u32 sigev_value; 1424 u32 sigev_signo; 1425 u32 sigev_notify; 1426 u32 payload[(64 / 4) - 3]; 1427 }; 1428 1429 extern asmlinkage long 1430 sys_timer_create(clockid_t which_clock, 1431 struct sigevent __user *timer_event_spec, 1432 timer_t __user * created_timer_id); 1433 1434 long 1435 sys32_timer_create(u32 clock, struct sigevent32 __user *se32, timer_t __user *timer_id) 1436 { 1437 struct sigevent __user *p = NULL; 1438 if (se32) { 1439 struct sigevent se; 1440 p = compat_alloc_user_space(sizeof(struct sigevent)); 1441 memset(&se, 0, sizeof(struct sigevent)); 1442 if (get_user(se.sigev_value.sival_int, &se32->sigev_value) || 1443 __get_user(se.sigev_signo, &se32->sigev_signo) || 1444 __get_user(se.sigev_notify, &se32->sigev_notify) || 1445 __copy_from_user(&se._sigev_un._pad, &se32->payload, 1446 sizeof(se32->payload)) || 1447 copy_to_user(p, &se, sizeof(se))) 1448 return -EFAULT; 1449 } 1450 return sys_timer_create(clock, p, timer_id); 1451 } 1452 1453 asmlinkage long 1454 sysn32_rt_sigtimedwait(const sigset_t __user *uthese, 1455 siginfo_t __user *uinfo, 1456 const struct compat_timespec __user *uts32, 1457 size_t sigsetsize) 1458 { 1459 struct timespec __user *uts = NULL; 1460 1461 if (uts32) { 1462 struct timespec ts; 1463 uts = compat_alloc_user_space(sizeof(struct timespec)); 1464 if (get_user(ts.tv_sec, &uts32->tv_sec) || 1465 get_user(ts.tv_nsec, &uts32->tv_nsec) || 1466 copy_to_user (uts, &ts, sizeof (ts))) 1467 return -EFAULT; 1468 } 1469 return sys_rt_sigtimedwait(uthese, uinfo, uts, sigsetsize); 1470 } 1471 1472 save_static_function(sys32_clone); 1473 __attribute_used__ noinline static int 1474 _sys32_clone(nabi_no_regargs struct pt_regs regs) 1475 { 1476 unsigned long clone_flags; 1477 unsigned long newsp; 1478 int __user *parent_tidptr, *child_tidptr; 1479 1480 clone_flags = regs.regs[4]; 1481 newsp = regs.regs[5]; 1482 if (!newsp) 1483 newsp = regs.regs[29]; 1484 parent_tidptr = (int *) regs.regs[6]; 1485 1486 /* Use __dummy4 instead of getting it off the stack, so that 1487 syscall() works. */ 1488 child_tidptr = (int __user *) __dummy4; 1489 return do_fork(clone_flags, newsp, ®s, 0, 1490 parent_tidptr, child_tidptr); 1491 } 1492 1493 extern asmlinkage void sys_set_thread_area(u32 addr); 1494 asmlinkage void sys32_set_thread_area(u32 addr) 1495 { 1496 sys_set_thread_area(AA(addr)); 1497 } 1498