📄 linux32.c
字号:
return err;}static int sys32_semtimedop(int semid, struct sembuf *tsems, int nsems, const struct compat_timespec *timeout32){ struct compat_timespec t32; struct timespec *t64 = compat_alloc_user_space(sizeof(*t64)); if (copy_from_user(&t32, timeout32, sizeof(t32))) return -EFAULT; if (put_user(t32.tv_sec, &t64->tv_sec) || put_user(t32.tv_nsec, &t64->tv_nsec)) return -EFAULT; return sys_semtimedop(semid, tsems, nsems, t64);}asmlinkage longsys32_ipc (u32 call, int first, int second, int third, u32 ptr, u32 fifth){ int version, err; version = call >> 16; /* hack for backward compatibility */ call &= 0xffff; switch (call) { case SEMOP: /* struct sembuf is the same on 32 and 64bit :)) */ err = sys_semtimedop (first, (struct sembuf *)AA(ptr), second, NULL); break; case SEMTIMEDOP: err = sys32_semtimedop (first, (struct sembuf *)AA(ptr), second, (const struct compat_timespec __user *)AA(fifth)); break; case SEMGET: err = sys_semget (first, second, third); break; case SEMCTL: err = do_sys32_semctl (first, second, third, (void *)AA(ptr)); break; case MSGSND: err = do_sys32_msgsnd (first, second, third, (void *)AA(ptr)); break; case MSGRCV: err = do_sys32_msgrcv (first, second, fifth, third, version, (void *)AA(ptr)); break; case MSGGET: err = sys_msgget ((key_t) first, second); break; case MSGCTL: err = do_sys32_msgctl (first, second, (void *)AA(ptr)); break; case SHMAT: err = do_sys32_shmat (first, second, third, version, (void *)AA(ptr)); break; case SHMDT: err = sys_shmdt ((char *)A(ptr)); break; case SHMGET: err = sys_shmget (first, (unsigned)second, third); break; case SHMCTL: err = do_sys32_shmctl (first, second, (void *)AA(ptr)); break; default: err = -EINVAL; break; } return err;}asmlinkage long sys32_shmat(int shmid, char __user *shmaddr, int shmflg, int32_t *addr){ unsigned long raddr; int err; err = do_shmat(shmid, shmaddr, shmflg, &raddr); if (err) return err; return put_user(raddr, addr);}struct sysctl_args32{ compat_caddr_t name; int nlen; compat_caddr_t oldval; compat_caddr_t oldlenp; compat_caddr_t newval; compat_size_t newlen; unsigned int __unused[4];};#ifdef CONFIG_SYSCTLasmlinkage long sys32_sysctl(struct sysctl_args32 *args){ struct sysctl_args32 tmp; int error; size_t oldlen, *oldlenp = NULL; unsigned long addr = (((long)&args->__unused[0]) + 7) & ~7; if (copy_from_user(&tmp, args, sizeof(tmp))) return -EFAULT; if (tmp.oldval && tmp.oldlenp) { /* Duh, this is ugly and might not work if sysctl_args is in read-only memory, but do_sysctl does indirectly a lot of uaccess in both directions and we'd have to basically copy the whole sysctl.c here, and glibc's __sysctl uses rw memory for the structure anyway. */ if (get_user(oldlen, (u32 *)A(tmp.oldlenp)) || put_user(oldlen, (size_t *)addr)) return -EFAULT; oldlenp = (size_t *)addr; } lock_kernel(); error = do_sysctl((int *)A(tmp.name), tmp.nlen, (void *)A(tmp.oldval), oldlenp, (void *)A(tmp.newval), tmp.newlen); unlock_kernel(); if (oldlenp) { if (!error) { if (get_user(oldlen, (size_t *)addr) || put_user(oldlen, (u32 *)A(tmp.oldlenp))) error = -EFAULT; } copy_to_user(args->__unused, tmp.__unused, sizeof(tmp.__unused)); } return error;}#endif /* CONFIG_SYSCTL */asmlinkage long sys32_newuname(struct new_utsname * name){ int ret = 0; down_read(&uts_sem); if (copy_to_user(name,&system_utsname,sizeof *name)) ret = -EFAULT; up_read(&uts_sem); if (current->personality == PER_LINUX32 && !ret) if (copy_to_user(name->machine, "mips\0\0\0", 8)) ret = -EFAULT; return ret;}asmlinkage int sys32_personality(unsigned long personality){ int ret; if (current->personality == PER_LINUX32 && personality == PER_LINUX) personality = PER_LINUX32; ret = sys_personality(personality); if (ret == PER_LINUX32) ret = PER_LINUX; return ret;}/* ustat compatibility */struct ustat32 { compat_daddr_t f_tfree; compat_ino_t f_tinode; char f_fname[6]; char f_fpack[6];};extern asmlinkage long sys_ustat(dev_t dev, struct ustat * ubuf);asmlinkage int sys32_ustat(dev_t dev, struct ustat32 * ubuf32){ int err; struct ustat tmp; struct ustat32 tmp32; mm_segment_t old_fs = get_fs(); set_fs(KERNEL_DS); err = sys_ustat(dev, &tmp); set_fs (old_fs); if (err) goto out; memset(&tmp32,0,sizeof(struct ustat32)); tmp32.f_tfree = tmp.f_tfree; tmp32.f_tinode = tmp.f_tinode; err = copy_to_user(ubuf32,&tmp32,sizeof(struct ustat32)) ? -EFAULT : 0;out: return err;}/* Handle adjtimex compatibility. */struct timex32 { u32 modes; s32 offset, freq, maxerror, esterror; s32 status, constant, precision, tolerance; struct compat_timeval time; s32 tick; s32 ppsfreq, jitter, shift, stabil; s32 jitcnt, calcnt, errcnt, stbcnt; s32 :32; s32 :32; s32 :32; s32 :32; s32 :32; s32 :32; s32 :32; s32 :32; s32 :32; s32 :32; s32 :32; s32 :32;};extern int do_adjtimex(struct timex *);asmlinkage int sys32_adjtimex(struct timex32 *utp){ struct timex txc; int ret; memset(&txc, 0, sizeof(struct timex)); if (get_user(txc.modes, &utp->modes) || __get_user(txc.offset, &utp->offset) || __get_user(txc.freq, &utp->freq) || __get_user(txc.maxerror, &utp->maxerror) || __get_user(txc.esterror, &utp->esterror) || __get_user(txc.status, &utp->status) || __get_user(txc.constant, &utp->constant) || __get_user(txc.precision, &utp->precision) || __get_user(txc.tolerance, &utp->tolerance) || __get_user(txc.time.tv_sec, &utp->time.tv_sec) || __get_user(txc.time.tv_usec, &utp->time.tv_usec) || __get_user(txc.tick, &utp->tick) || __get_user(txc.ppsfreq, &utp->ppsfreq) || __get_user(txc.jitter, &utp->jitter) || __get_user(txc.shift, &utp->shift) || __get_user(txc.stabil, &utp->stabil) || __get_user(txc.jitcnt, &utp->jitcnt) || __get_user(txc.calcnt, &utp->calcnt) || __get_user(txc.errcnt, &utp->errcnt) || __get_user(txc.stbcnt, &utp->stbcnt)) return -EFAULT; ret = do_adjtimex(&txc); if (put_user(txc.modes, &utp->modes) || __put_user(txc.offset, &utp->offset) || __put_user(txc.freq, &utp->freq) || __put_user(txc.maxerror, &utp->maxerror) || __put_user(txc.esterror, &utp->esterror) || __put_user(txc.status, &utp->status) || __put_user(txc.constant, &utp->constant) || __put_user(txc.precision, &utp->precision) || __put_user(txc.tolerance, &utp->tolerance) || __put_user(txc.time.tv_sec, &utp->time.tv_sec) || __put_user(txc.time.tv_usec, &utp->time.tv_usec) || __put_user(txc.tick, &utp->tick) || __put_user(txc.ppsfreq, &utp->ppsfreq) || __put_user(txc.jitter, &utp->jitter) || __put_user(txc.shift, &utp->shift) || __put_user(txc.stabil, &utp->stabil) || __put_user(txc.jitcnt, &utp->jitcnt) || __put_user(txc.calcnt, &utp->calcnt) || __put_user(txc.errcnt, &utp->errcnt) || __put_user(txc.stbcnt, &utp->stbcnt)) ret = -EFAULT; return ret;}asmlinkage int sys32_sendfile(int out_fd, int in_fd, compat_off_t *offset, s32 count){ mm_segment_t old_fs = get_fs(); int ret; off_t of; if (offset && get_user(of, offset)) return -EFAULT; set_fs(KERNEL_DS); ret = sys_sendfile(out_fd, in_fd, offset ? &of : NULL, count); set_fs(old_fs); if (offset && put_user(of, offset)) return -EFAULT; return ret;}asmlinkage ssize_t sys32_readahead(int fd, u32 pad0, u64 a2, u64 a3, size_t count){ return sys_readahead(fd, merge_64(a2, a3), count);}/* Argument list sizes for sys_socketcall */#define AL(x) ((x) * sizeof(unsigned int))static unsigned char socketcall_nargs[18]={AL(0),AL(3),AL(3),AL(3),AL(2),AL(3), AL(3),AL(3),AL(4),AL(4),AL(4),AL(6), AL(6),AL(2),AL(5),AL(5),AL(3),AL(3)};#undef AL/* * System call vectors. * * Argument checking cleaned up. Saved 20% in size. * This function doesn't need to set the kernel lock because * it is set by the callees. */asmlinkage long sys32_socketcall(int call, unsigned int *args32){ unsigned int a[6]; unsigned int a0,a1; int err; extern asmlinkage long sys_socket(int family, int type, int protocol); extern asmlinkage long sys_bind(int fd, struct sockaddr __user *umyaddr, int addrlen); extern asmlinkage long sys_connect(int fd, struct sockaddr __user *uservaddr, int addrlen); extern asmlinkage long sys_listen(int fd, int backlog); extern asmlinkage long sys_accept(int fd, struct sockaddr __user *upeer_sockaddr, int __user *upeer_addrlen); extern asmlinkage long sys_getsockname(int fd, struct sockaddr __user *usockaddr, int __user *usockaddr_len); extern asmlinkage long sys_getpeername(int fd, struct sockaddr __user *usockaddr, int __user *usockaddr_len); extern asmlinkage long sys_socketpair(int family, int type, int protocol, int __user *usockvec); extern asmlinkage long sys_send(int fd, void __user * buff, size_t len, unsigned flags); extern asmlinkage long sys_sendto(int fd, void __user * buff, size_t len, unsigned flags, struct sockaddr __user *addr, int addr_len); extern asmlinkage long sys_recv(int fd, void __user * ubuf, size_t size, unsigned flags); extern asmlinkage long sys_recvfrom(int fd, void __user * ubuf, size_t size, unsigned flags, struct sockaddr __user *addr, int __user *addr_len); extern asmlinkage long sys_shutdown(int fd, int how); extern asmlinkage long sys_setsockopt(int fd, int level, int optname, char __user *optval, int optlen); extern asmlinkage long sys_getsockopt(int fd, int level, int optname, char __user *optval, int *optlen); extern asmlinkage long sys_sendmsg(int fd, struct msghdr __user *msg, unsigned flags); extern asmlinkage long sys_recvmsg(int fd, struct msghdr __user *msg, unsigned int flags); if(call<1||call>SYS_RECVMSG) return -EINVAL; /* copy_from_user should be SMP safe. */ if (copy_from_user(a, args32, socketcall_nargs[call])) return -EFAULT; a0=a[0]; a1=a[1]; switch(call) { case SYS_SOCKET: err = sys_socket(a0,a1,a[2]); break; case SYS_BIND: err = sys_bind(a0,(struct sockaddr __user *)A(a1), a[2]); break; case SYS_CONNECT: err = sys_connect(a0, (struct sockaddr __user *)A(a1), a[2]); break; case SYS_LISTEN: err = sys_listen(a0,a1); break; case SYS_ACCEPT: err = sys_accept(a0,(struct sockaddr __user *)A(a1), (int __user *)A(a[2])); break; case SYS_GETSOCKNAME: err = sys_getsockname(a0,(struct sockaddr __user *)A(a1), (int __user *)A(a[2])); break; case SYS_GETPEERNAME: err = sys_getpeername(a0, (struct sockaddr __user *)A(a1), (int __user *)A(a[2])); break; case SYS_SOCKETPAIR: err = sys_socketpair(a0,a1, a[2], (int __user *)A(a[3])); break; case SYS_SEND: err = sys_send(a0, (void __user *)A(a1), a[2], a[3]); break; case SYS_SENDTO: err = sys_sendto(a0,(void __user *)A(a1), a[2], a[3], (struct sockaddr __user *)A(a[4]), a[5]); break; case SYS_RECV: err = sys_recv(a0, (void __user *)A(a1), a[2], a[3]); break; case SYS_RECVFROM: err = sys_recvfrom(a0, (void __user *)A(a1), a[2], a[3], (struct sockaddr __user *)A(a[4]), (int __user *)A(a[5])); break; case SYS_SHUTDOWN: err = sys_shutdown(a0,a1); break; case SYS_SETSOCKOPT: err = sys_setsockopt(a0, a1, a[2], (char __user *)A(a[3]), a[4]); break; case SYS_GETSOCKOPT: err = sys_getsockopt(a0, a1, a[2], (char __user *)A(a[3]), (int __user *)A(a[4])); break; case SYS_SENDMSG: err = sys_sendmsg(a0, (struct msghdr __user *) A(a1), a[2]); break; case SYS_RECVMSG: err = sys_recvmsg(a0, (struct msghdr __user *) A(a1), a[2]); break; default: err = -EINVAL; break; } return err;}struct sigevent32 { u32 sigev_value; u32 sigev_signo; u32 sigev_notify; u32 payload[(64 / 4) - 3];};extern asmlinkage longsys_timer_create(clockid_t which_clock, struct sigevent __user *timer_event_spec, timer_t __user * created_timer_id);longsys32_timer_create(u32 clock, struct sigevent32 __user *se32, timer_t __user *timer_id){ struct sigevent __user *p = NULL; if (se32) { struct sigevent se; p = compat_alloc_user_space(sizeof(struct sigevent)); memset(&se, 0, sizeof(struct sigevent)); if (get_user(se.sigev_value.sival_int, &se32->sigev_value) || __get_user(se.sigev_signo, &se32->sigev_signo) || __get_user(se.sigev_notify, &se32->sigev_notify) || __copy_from_user(&se._sigev_un._pad, &se32->payload, sizeof(se32->payload)) || copy_to_user(p, &se, sizeof(se))) return -EFAULT; } return sys_timer_create(clock, p, timer_id);}asmlinkage longsysn32_rt_sigtimedwait(const sigset_t __user *uthese, siginfo_t __user *uinfo, const struct compat_timespec __user *uts32, size_t sigsetsize){ struct timespec __user *uts = NULL; if (uts32) { struct timespec ts; uts = compat_alloc_user_space(sizeof(struct timespec)); if (get_user(ts.tv_sec, &uts32->tv_sec) || get_user(ts.tv_nsec, &uts32->tv_nsec) || copy_to_user (uts, &ts, sizeof (ts))) return -EFAULT; } return sys_rt_sigtimedwait(uthese, uinfo, uts, sigsetsize);}save_static_function(sys32_clone);__attribute_used__ noinline static int_sys32_clone(nabi_no_regargs struct pt_regs regs){ unsigned long clone_flags; unsigned long newsp; int __user *parent_tidptr, *child_tidptr; clone_flags = regs.regs[4]; newsp = regs.regs[5]; if (!newsp) newsp = regs.regs[29]; parent_tidptr = (int *) regs.regs[6]; /* Use __dummy4 instead of getting it off the stack, so that syscall() works. */ child_tidptr = (int __user *) __dummy4; return do_fork(clone_flags, newsp, ®s, 0, parent_tidptr, child_tidptr);}extern asmlinkage void sys_set_thread_area(u32 addr);asmlinkage void sys32_set_thread_area(u32 addr){ sys_set_thread_area(AA(addr));}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -