📄 sys_ia32.c
字号:
set_fs (old_fs); if (verify_area(VERIFY_WRITE, interval, sizeof(struct timespec32)) || __put_user (t.tv_sec, &interval->tv_sec) || __put_user (t.tv_nsec, &interval->tv_nsec)) return -EFAULT; return ret;}extern asmlinkage long sys_sigprocmask(int how, old_sigset_t *set, old_sigset_t *oset);asmlinkage longsys32_sigprocmask(int how, old_sigset32_t *set, old_sigset32_t *oset){ old_sigset_t s; int ret; mm_segment_t old_fs = get_fs(); if (set && get_user (s, set)) return -EFAULT; set_fs (KERNEL_DS); ret = sys_sigprocmask(how, set ? &s : NULL, oset ? &s : NULL); set_fs (old_fs); if (ret) return ret; if (oset && put_user (s, oset)) return -EFAULT; return 0;}extern asmlinkage long sys_sigpending(old_sigset_t *set);asmlinkage longsys32_sigpending(old_sigset32_t *set){ old_sigset_t s; int ret; mm_segment_t old_fs = get_fs(); set_fs (KERNEL_DS); ret = sys_sigpending(&s); set_fs (old_fs); if (put_user (s, set)) return -EFAULT; return ret;}extern asmlinkage long sys_rt_sigpending(sigset_t *set, size_t sigsetsize);asmlinkage longsys32_rt_sigpending(sigset32_t *set, __kernel_size_t32 sigsetsize){ sigset_t s; sigset32_t s32; int ret; mm_segment_t old_fs = get_fs(); set_fs (KERNEL_DS); ret = sys_rt_sigpending(&s, sigsetsize); set_fs (old_fs); if (!ret) { switch (_NSIG_WORDS) { case 4: s32.sig[7] = (s.sig[3] >> 32); s32.sig[6] = s.sig[3]; case 3: s32.sig[5] = (s.sig[2] >> 32); s32.sig[4] = s.sig[2]; case 2: s32.sig[3] = (s.sig[1] >> 32); s32.sig[2] = s.sig[1]; case 1: s32.sig[1] = (s.sig[0] >> 32); s32.sig[0] = s.sig[0]; } if (copy_to_user (set, &s32, sizeof(sigset32_t))) return -EFAULT; } return ret;}siginfo_t32 *siginfo64to32(siginfo_t32 *d, siginfo_t *s){ memset (d, 0, sizeof(siginfo_t32)); d->si_signo = s->si_signo; d->si_errno = s->si_errno; d->si_code = s->si_code; if (s->si_signo >= SIGRTMIN) { d->si_pid = s->si_pid; d->si_uid = s->si_uid; memcpy(&d->si_int, &s->si_int, sizeof(siginfo_t) - offsetof(siginfo_t,si_int)); } else switch (s->si_signo) { /* XXX: What about POSIX1.b timers */ case SIGCHLD: d->si_pid = s->si_pid; d->si_status = s->si_status; d->si_utime = s->si_utime; d->si_stime = s->si_stime; break; case SIGSEGV: case SIGBUS: case SIGFPE: case SIGILL: d->si_addr = (long)(s->si_addr);// d->si_trapno = s->si_trapno; break; case SIGPOLL: d->si_band = s->si_band; d->si_fd = s->si_fd; break; default: d->si_pid = s->si_pid; d->si_uid = s->si_uid; break; } return d;}siginfo_t *siginfo32to64(siginfo_t *d, siginfo_t32 *s){ d->si_signo = s->si_signo; d->si_errno = s->si_errno; d->si_code = s->si_code; if (s->si_signo >= SIGRTMIN) { d->si_pid = s->si_pid; d->si_uid = s->si_uid; memcpy(&d->si_int, &s->si_int, sizeof(siginfo_t) - offsetof(siginfo_t, si_int)); } else switch (s->si_signo) { /* XXX: What about POSIX1.b timers */ case SIGCHLD: d->si_pid = s->si_pid; d->si_status = s->si_status; d->si_utime = s->si_utime; d->si_stime = s->si_stime; break; case SIGSEGV: case SIGBUS: case SIGFPE: case SIGILL: d->si_addr = (void *)A(s->si_addr);// d->si_trapno = s->si_trapno; break; case SIGPOLL: d->si_band = s->si_band; d->si_fd = s->si_fd; break; default: d->si_pid = s->si_pid; d->si_uid = s->si_uid; break; } return d;}extern asmlinkage longsys_rt_sigtimedwait(const sigset_t *uthese, siginfo_t *uinfo, const struct timespec *uts, size_t sigsetsize);asmlinkage longsys32_rt_sigtimedwait(sigset32_t *uthese, siginfo_t32 *uinfo, struct timespec32 *uts, __kernel_size_t32 sigsetsize){ sigset_t s; sigset32_t s32; struct timespec t; int ret; mm_segment_t old_fs = get_fs(); siginfo_t info; siginfo_t32 info32; if (copy_from_user (&s32, uthese, sizeof(sigset32_t))) return -EFAULT; switch (_NSIG_WORDS) { case 4: s.sig[3] = s32.sig[6] | (((long)s32.sig[7]) << 32); case 3: s.sig[2] = s32.sig[4] | (((long)s32.sig[5]) << 32); case 2: s.sig[1] = s32.sig[2] | (((long)s32.sig[3]) << 32); case 1: s.sig[0] = s32.sig[0] | (((long)s32.sig[1]) << 32); } if (uts) { if (verify_area(VERIFY_READ, uts, sizeof(struct timespec32)) || __get_user (t.tv_sec, &uts->tv_sec) || __get_user (t.tv_nsec, &uts->tv_nsec)) return -EFAULT; } set_fs (KERNEL_DS); ret = sys_rt_sigtimedwait(&s, &info, &t, sigsetsize); set_fs (old_fs); if (ret >= 0 && uinfo) { if (copy_to_user (uinfo, siginfo64to32(&info32, &info), sizeof(siginfo_t32))) return -EFAULT; } return ret;}extern asmlinkage longsys_rt_sigqueueinfo(int pid, int sig, siginfo_t *uinfo);asmlinkage longsys32_rt_sigqueueinfo(int pid, int sig, siginfo_t32 *uinfo){ siginfo_t info; siginfo_t32 info32; int ret; mm_segment_t old_fs = get_fs(); if (copy_from_user (&info32, uinfo, sizeof(siginfo_t32))) return -EFAULT; /* XXX: Is this correct? */ siginfo32to64(&info, &info32); set_fs (KERNEL_DS); ret = sys_rt_sigqueueinfo(pid, sig, &info); set_fs (old_fs); return ret;}extern void check_pending(int signum);asmlinkage long sys_utimes(char *, struct timeval *);asmlinkage longsys32_utimes(char *filename, struct timeval32 *tvs){ char *kfilename; struct timeval ktvs[2]; mm_segment_t old_fs; int ret; kfilename = getname(filename); ret = PTR_ERR(kfilename); if (!IS_ERR(kfilename)) { if (tvs) { if (get_tv32(&ktvs[0], tvs) || get_tv32(&ktvs[1], 1+tvs)) return -EFAULT; } old_fs = get_fs(); set_fs(KERNEL_DS); ret = sys_utimes(kfilename, &ktvs[0]); set_fs(old_fs); putname(kfilename); } return ret;}/* These are here just in case some old ia32 binary calls it. */asmlinkage longsys32_pause(void){ current->state = TASK_INTERRUPTIBLE; schedule(); return -ERESTARTNOHAND;}struct sysctl_ia32 { unsigned int name; int nlen; unsigned int oldval; unsigned int oldlenp; unsigned int newval; unsigned int newlen; unsigned int __unused[4];};asmlinkage longsys32_sysctl(struct sysctl_ia32 *args32){#ifndef CONFIG_SYSCTL return -ENOSYS; #else struct sysctl_ia32 a32; mm_segment_t old_fs = get_fs (); void *oldvalp, *newvalp; size_t oldlen; int *namep; long ret; extern int do_sysctl(int *name, int nlen, void *oldval, size_t *oldlenp, void *newval, size_t newlen); if (copy_from_user(&a32, args32, sizeof (a32))) return -EFAULT; /* * We need to pre-validate these because we have to disable address checking * before calling do_sysctl() because of OLDLEN but we can't run the risk of the * user specifying bad addresses here. Well, since we're dealing with 32 bit * addresses, we KNOW that access_ok() will always succeed, so this is an * expensive NOP, but so what... */ namep = (int *) A(a32.name); oldvalp = (void *) A(a32.oldval); newvalp = (void *) A(a32.newval); if ((oldvalp && get_user(oldlen, (int *) A(a32.oldlenp))) || !access_ok(VERIFY_WRITE, namep, 0) || !access_ok(VERIFY_WRITE, oldvalp, 0) || !access_ok(VERIFY_WRITE, newvalp, 0)) return -EFAULT; set_fs(KERNEL_DS); lock_kernel(); ret = do_sysctl(namep, a32.nlen, oldvalp, &oldlen, newvalp, (size_t) a32.newlen); unlock_kernel(); set_fs(old_fs); if (oldvalp && put_user (oldlen, (int *) A(a32.oldlenp))) return -EFAULT; return ret;#endif}extern asmlinkage ssize_t sys_pread(unsigned int fd, char * buf, size_t count, loff_t pos);extern asmlinkage ssize_t sys_pwrite(unsigned int fd, const char * buf, size_t count, loff_t pos);typedef __kernel_ssize_t32 ssize_t32;/* warning: next two assume little endian */ asmlinkage longsys32_pread(unsigned int fd, char *ubuf, __kernel_size_t32 count, u32 poslo, u32 poshi){ return sys_pread(fd, ubuf, count, ((loff_t)AA(poshi) << 32) | AA(poslo));}asmlinkage longsys32_pwrite(unsigned int fd, char *ubuf, __kernel_size_t32 count, u32 poslo, u32 poshi){ return sys_pwrite(fd, ubuf, count, ((loff_t)AA(poshi) << 32) | AA(poslo));}extern asmlinkage long sys_personality(unsigned long);asmlinkage longsys32_personality(unsigned long personality){ int ret; if (personality(current->personality) == PER_LINUX32 && personality == PER_LINUX) personality = PER_LINUX32; ret = sys_personality(personality); if (ret == PER_LINUX32) ret = PER_LINUX; return ret;}extern asmlinkage ssize_t sys_sendfile(int out_fd, int in_fd, off_t *offset, size_t count); asmlinkage longsys32_sendfile(int out_fd, int in_fd, __kernel_off_t32 *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 (!ret && offset && put_user(of, offset)) return -EFAULT; return ret;}extern long sys_modify_ldt(int,void*,unsigned long);asmlinkage long sys32_modify_ldt(int func, void *ptr, unsigned long bytecount){ long ret; if (func == 0x1 || func == 0x11) { struct modify_ldt_ldt_s info; mm_segment_t old_fs = get_fs(); if (bytecount != sizeof(struct modify_ldt_ldt_s)) return -EINVAL; if (copy_from_user(&info, ptr, sizeof(struct modify_ldt_ldt_s))) return -EFAULT; /* lm bit was undefined in the 32bit ABI and programs give it random values. Force it to zero here. */ info.lm = 0; set_fs(KERNEL_DS); ret = sys_modify_ldt(func, &info, bytecount); set_fs(old_fs); } else { ret = sys_modify_ldt(func, ptr, bytecount); } return ret;}/* Handle adjtimex compatability. */struct timex32 { u32 modes; s32 offset, freq, maxerror, esterror; s32 status, constant, precision, tolerance; struct timeval32 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 longsys32_adjtimex(struct timex32 *utp){ struct timex txc; int ret; memset(&txc, 0, sizeof(struct timex)); if(verify_area(VERIFY_READ, utp, sizeof(struct timex32)) || __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(verify_area(VERIFY_WRITE, utp, sizeof(struct timex32)) || __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 long sys32_mmap2(unsigned long addr, unsigned long len, unsigned long prot, unsigned long flags, unsigned long fd, unsigned long pgoff){ struct mm_struct *mm = current->mm; unsigned long error; struct file * file = NULL; flags &= ~(MAP_EXECUTABLE | MAP_DENYWRITE); if (!(flags & MAP_ANONYMOUS)) { file = fget(fd); if (!file) return -EBADF; } if (prot & PROT_READ) prot |= PROT_EXEC; down_write(&mm->mmap_sem); error = do_mmap_pgoff(file, addr, len, prot, flags|MAP_32BIT, pgoff); up_write(&mm->mmap_sem); if (file) fput(file); return error;}asmlinkage long sys32_olduname(struct oldold_utsname * name){ int error; if (!name) return -EFAULT; if (!access_ok(VERIFY_WRITE,name,sizeof(struct oldold_utsname))) return -EFAULT; down_read(&uts_sem);
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -