sys_ia32.c
来自「该文件是rt_linux」· C语言 代码 · 共 2,528 行 · 第 1/5 页
C
2,528 行
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; /* XXX: Ouch, how to find this out??? */ d->si_int = s->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; /* XXX: Ouch, how to find this out??? */ d->si_int = s->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 ssize_t32sys32_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 ssize_t32sys32_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;}/* 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;}/* common code for old and new mmaps */static inline long do_mmap2( unsigned long addr, unsigned long len, unsigned long prot, unsigned long flags, unsigned long fd, unsigned long pgoff){ int error = -EBADF; struct file * file = NULL; flags &= ~(MAP_EXECUTABLE | MAP_DENYWRITE); if (!(flags & MAP_ANONYMOUS)) { file = fget(fd); if (!file) goto out; } down_write(¤t->mm->mmap_sem); error = do_mmap_pgoff(file, addr, len, prot, flags, pgoff); up_write(¤t->mm->mmap_sem); if (file) fput(file);out: return error;}asmlinkage long sys32_mmap2(unsigned long addr, unsigned long len, unsigned long prot, unsigned long flags, unsigned long fd, unsigned long pgoff){ return do_mmap2(addr, len, prot, flags, fd, pgoff);}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); error = __copy_to_user(&name->sysname,&system_utsname.sysname,__OLD_UTS_LEN); __put_user(0,name->sysname+__OLD_UTS_LEN); __copy_to_user(&name->nodename,&system_utsname.nodename,__OLD_UTS_LEN); __put_user(0,name->nodename+__OLD_UTS_LEN); __copy_to_user(&name->release,&system_utsname.release,__OLD_UTS_LEN); __put_user(0,name->release+__OLD_UTS_LEN); __copy_to_user(&name->version,&system_utsname.version,__OLD_UTS_LEN); __put_user(0,name->version+__OLD_UTS_LEN); { char *arch = (personality(current->personality) == PER_LINUX32) ? "i686" : "x86_64"; __copy_to_user(&name->machine,arch,strlen(arch)+1); } up_read(&uts_sem); error = error ? -EFAULT : 0; return error;}asmlinkage long sys32_uname(struct old_utsname * name){ int err; down_read(&uts_sem); err=copy_to_user(name, &system_utsname, sizeof (*name)); up_read(&uts_sem); if (personality(current->personality) == PER_LINUX32) err = copy_to_user(name->machine, "i686", 5); return err?-EFAULT:0;}
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?