📄 sys_sparc32.c
字号:
int ret; mm_segment_t old_fs = get_fs(); if (copy_siginfo_from_user32(&info, uinfo)) return -EFAULT; set_fs (KERNEL_DS); ret = sys_rt_sigqueueinfo(pid, sig, (siginfo_t __user *) &info); set_fs (old_fs); return ret;}asmlinkage long compat_sys_sigaction(int sig, struct old_sigaction32 __user *act, struct old_sigaction32 __user *oact){ struct k_sigaction new_ka, old_ka; int ret; if (sig < 0) { set_thread_flag(TIF_NEWSIGNALS); sig = -sig; } if (act) { compat_old_sigset_t mask; u32 u_handler, u_restorer; ret = get_user(u_handler, &act->sa_handler); new_ka.sa.sa_handler = compat_ptr(u_handler); ret |= __get_user(u_restorer, &act->sa_restorer); new_ka.sa.sa_restorer = compat_ptr(u_restorer); ret |= __get_user(new_ka.sa.sa_flags, &act->sa_flags); ret |= __get_user(mask, &act->sa_mask); if (ret) return ret; new_ka.ka_restorer = NULL; siginitset(&new_ka.sa.sa_mask, mask); } ret = do_sigaction(sig, act ? &new_ka : NULL, oact ? &old_ka : NULL); if (!ret && oact) { ret = put_user(ptr_to_compat(old_ka.sa.sa_handler), &oact->sa_handler); ret |= __put_user(ptr_to_compat(old_ka.sa.sa_restorer), &oact->sa_restorer); ret |= __put_user(old_ka.sa.sa_flags, &oact->sa_flags); ret |= __put_user(old_ka.sa.sa_mask.sig[0], &oact->sa_mask); } return ret;}asmlinkage long compat_sys_rt_sigaction(int sig, struct sigaction32 __user *act, struct sigaction32 __user *oact, void __user *restorer, compat_size_t sigsetsize){ struct k_sigaction new_ka, old_ka; int ret; compat_sigset_t set32; /* XXX: Don't preclude handling different sized sigset_t's. */ if (sigsetsize != sizeof(compat_sigset_t)) return -EINVAL; /* All tasks which use RT signals (effectively) use * new style signals. */ set_thread_flag(TIF_NEWSIGNALS); if (act) { u32 u_handler, u_restorer; new_ka.ka_restorer = restorer; ret = get_user(u_handler, &act->sa_handler); new_ka.sa.sa_handler = compat_ptr(u_handler); ret |= __copy_from_user(&set32, &act->sa_mask, sizeof(compat_sigset_t)); switch (_NSIG_WORDS) { case 4: new_ka.sa.sa_mask.sig[3] = set32.sig[6] | (((long)set32.sig[7]) << 32); case 3: new_ka.sa.sa_mask.sig[2] = set32.sig[4] | (((long)set32.sig[5]) << 32); case 2: new_ka.sa.sa_mask.sig[1] = set32.sig[2] | (((long)set32.sig[3]) << 32); case 1: new_ka.sa.sa_mask.sig[0] = set32.sig[0] | (((long)set32.sig[1]) << 32); } ret |= __get_user(new_ka.sa.sa_flags, &act->sa_flags); ret |= __get_user(u_restorer, &act->sa_restorer); new_ka.sa.sa_restorer = compat_ptr(u_restorer); if (ret) return -EFAULT; } ret = do_sigaction(sig, act ? &new_ka : NULL, oact ? &old_ka : NULL); if (!ret && oact) { switch (_NSIG_WORDS) { case 4: set32.sig[7] = (old_ka.sa.sa_mask.sig[3] >> 32); set32.sig[6] = old_ka.sa.sa_mask.sig[3]; case 3: set32.sig[5] = (old_ka.sa.sa_mask.sig[2] >> 32); set32.sig[4] = old_ka.sa.sa_mask.sig[2]; case 2: set32.sig[3] = (old_ka.sa.sa_mask.sig[1] >> 32); set32.sig[2] = old_ka.sa.sa_mask.sig[1]; case 1: set32.sig[1] = (old_ka.sa.sa_mask.sig[0] >> 32); set32.sig[0] = old_ka.sa.sa_mask.sig[0]; } ret = put_user(ptr_to_compat(old_ka.sa.sa_handler), &oact->sa_handler); ret |= __copy_to_user(&oact->sa_mask, &set32, sizeof(compat_sigset_t)); ret |= __put_user(old_ka.sa.sa_flags, &oact->sa_flags); ret |= __put_user(ptr_to_compat(old_ka.sa.sa_restorer), &oact->sa_restorer); if (ret) ret = -EFAULT; } return ret;}/* * sparc32_execve() executes a new program after the asm stub has set * things up for us. This should basically do what I want it to. */asmlinkage long sparc32_execve(struct pt_regs *regs){ int error, base = 0; char *filename; /* User register window flush is done by entry.S */ /* Check for indirect call. */ if ((u32)regs->u_regs[UREG_G1] == 0) base = 1; filename = getname(compat_ptr(regs->u_regs[base + UREG_I0])); error = PTR_ERR(filename); if (IS_ERR(filename)) goto out; error = compat_do_execve(filename, compat_ptr(regs->u_regs[base + UREG_I1]), compat_ptr(regs->u_regs[base + UREG_I2]), regs); putname(filename); if (!error) { fprs_write(0); current_thread_info()->xfsr[0] = 0; current_thread_info()->fpsaved[0] = 0; regs->tstate &= ~TSTATE_PEF; task_lock(current); current->ptrace &= ~PT_DTRACE; task_unlock(current); }out: return error;}#ifdef CONFIG_MODULESasmlinkage long sys32_init_module(void __user *umod, u32 len, const char __user *uargs){ return sys_init_module(umod, len, uargs);}asmlinkage long sys32_delete_module(const char __user *name_user, unsigned int flags){ return sys_delete_module(name_user, flags);}#else /* CONFIG_MODULES */asmlinkage long sys32_init_module(const char __user *name_user, struct module __user *mod_user){ return -ENOSYS;}asmlinkage long sys32_delete_module(const char __user *name_user){ return -ENOSYS;}#endif /* CONFIG_MODULES *//* Translations due to time_t size differences. Which affects all sorts of things, like timeval and itimerval. */extern struct timezone sys_tz;asmlinkage long sys32_gettimeofday(struct compat_timeval __user *tv, struct timezone __user *tz){ if (tv) { struct timeval ktv; do_gettimeofday(&ktv); if (put_tv32(tv, &ktv)) return -EFAULT; } if (tz) { if (copy_to_user(tz, &sys_tz, sizeof(sys_tz))) return -EFAULT; } return 0;}static inline long get_ts32(struct timespec *o, struct compat_timeval __user *i){ long usec; if (!access_ok(VERIFY_READ, i, sizeof(*i))) return -EFAULT; if (__get_user(o->tv_sec, &i->tv_sec)) return -EFAULT; if (__get_user(usec, &i->tv_usec)) return -EFAULT; o->tv_nsec = usec * 1000; return 0;}asmlinkage long sys32_settimeofday(struct compat_timeval __user *tv, struct timezone __user *tz){ struct timespec kts; struct timezone ktz; if (tv) { if (get_ts32(&kts, tv)) return -EFAULT; } if (tz) { if (copy_from_user(&ktz, tz, sizeof(ktz))) return -EFAULT; } return do_sys_settimeofday(tv ? &kts : NULL, tz ? &ktz : NULL);}asmlinkage long sys32_utimes(char __user *filename, struct compat_timeval __user *tvs){ struct timeval ktvs[2]; if (tvs) { if (get_tv32(&ktvs[0], tvs) || get_tv32(&ktvs[1], 1+tvs)) return -EFAULT; } return do_utimes(filename, (tvs ? &ktvs[0] : NULL));}/* These are here just in case some old sparc32 binary calls it. */asmlinkage long sys32_pause(void){ current->state = TASK_INTERRUPTIBLE; schedule(); return -ERESTARTNOHAND;}asmlinkage compat_ssize_t sys32_pread64(unsigned int fd, char __user *ubuf, compat_size_t count, unsigned long poshi, unsigned long poslo){ return sys_pread64(fd, ubuf, count, (poshi << 32) | poslo);}asmlinkage compat_ssize_t sys32_pwrite64(unsigned int fd, char __user *ubuf, compat_size_t count, unsigned long poshi, unsigned long poslo){ return sys_pwrite64(fd, ubuf, count, (poshi << 32) | poslo);}asmlinkage long compat_sys_readahead(int fd, unsigned long offhi, unsigned long offlo, compat_size_t count){ return sys_readahead(fd, (offhi << 32) | offlo, count);}long compat_sys_fadvise64(int fd, unsigned long offhi, unsigned long offlo, compat_size_t len, int advice){ return sys_fadvise64_64(fd, (offhi << 32) | offlo, len, advice);}long compat_sys_fadvise64_64(int fd, unsigned long offhi, unsigned long offlo, unsigned long lenhi, unsigned long lenlo, int advice){ return sys_fadvise64_64(fd, (offhi << 32) | offlo, (lenhi << 32) | lenlo, advice);}asmlinkage long compat_sys_sendfile(int out_fd, int in_fd, compat_off_t __user *offset, compat_size_t 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 ? (off_t __user *) &of : NULL, count); set_fs(old_fs); if (offset && put_user(of, offset)) return -EFAULT; return ret;}asmlinkage long compat_sys_sendfile64(int out_fd, int in_fd, compat_loff_t __user *offset, compat_size_t count){ mm_segment_t old_fs = get_fs(); int ret; loff_t lof; if (offset && get_user(lof, offset)) return -EFAULT; set_fs(KERNEL_DS); ret = sys_sendfile64(out_fd, in_fd, offset ? (loff_t __user *) &lof : NULL, count); set_fs(old_fs); if (offset && put_user(lof, offset)) return -EFAULT; return ret;}/* 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 long sys32_adjtimex(struct timex32 __user *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;}/* This is just a version for 32-bit applications which does * not force O_LARGEFILE on. */asmlinkage long sparc32_open(const char __user *filename, int flags, int mode){ return do_sys_open(filename, flags, mode);}extern unsigned long do_mremap(unsigned long addr, unsigned long old_len, unsigned long new_len, unsigned long flags, unsigned long new_addr); asmlinkage unsigned long sys32_mremap(unsigned long addr, unsigned long old_len, unsigned long new_len, unsigned long flags, u32 __new_addr){ struct vm_area_struct *vma; unsigned long ret = -EINVAL; unsigned long new_addr = __new_addr; if (old_len > 0xf0000000UL || new_len > 0xf0000000UL) goto out; if (addr > 0xf0000000UL - old_len) goto out; down_write(¤t->mm->mmap_sem); if (flags & MREMAP_FIXED) { if (new_addr > 0xf0000000UL - new_len) goto out_sem; } else if (addr > 0xf0000000UL - new_len) { unsigned long map_flags = 0; struct file *file = NULL; ret = -ENOMEM; if (!(flags & MREMAP_MAYMOVE)) goto out_sem; vma = find_vma(current->mm, addr); if (vma) { if (vma->vm_flags & VM_SHARED) map_flags |= MAP_SHARED; file = vma->vm_file; } /* MREMAP_FIXED checked above. */ new_addr = get_unmapped_area(file, addr, new_len, vma ? vma->vm_pgoff : 0, map_flags); ret = new_addr; if (new_addr & ~PAGE_MASK) goto out_sem; flags |= MREMAP_FIXED; } ret = do_mremap(addr, old_len, new_len, flags, new_addr);out_sem: up_write(¤t->mm->mmap_sem);out: return ret; }struct __sysctl_args32 { u32 name; int nlen; u32 oldval; u32 oldlenp; u32 newval; u32 newlen; u32 __unused[4];};asmlinkage long sys32_sysctl(struct __sysctl_args32 __user *args){#ifndef CONFIG_SYSCTL return -ENOSYS;#else struct __sysctl_args32 tmp; int error; size_t oldlen, __user *oldlenp = NULL; unsigned long addr = (((unsigned long)&args->__unused[0]) + 7UL) & ~7UL; 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 __user *)(unsigned long)tmp.oldlenp) || put_user(oldlen, (size_t __user *)addr)) return -EFAULT; oldlenp = (size_t __user *)addr; } lock_kernel(); error = do_sysctl((int __user *)(unsigned long) tmp.name, tmp.nlen, (void __user *)(unsigned long) tmp.oldval, oldlenp, (void __user *)(unsigned long) tmp.newval, tmp.newlen); unlock_kernel(); if (oldlenp) { if (!error) { if (get_user(oldlen, (size_t __user *)addr) || put_user(oldlen, (u32 __user *)(unsigned long) tmp.oldlenp)) error = -EFAULT; } if (copy_to_user(args->__unused, tmp.__unused, sizeof(tmp.__unused))) error = -EFAULT; } return error;#endif}long sys32_lookup_dcookie(unsigned long cookie_high, unsigned long cookie_low, char __user *buf, size_t len){ return sys_lookup_dcookie((cookie_high << 32) | cookie_low, buf, len);}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 compat_sigevent __user *se32, timer_t __user *timer_id){ struct sigevent se; mm_segment_t oldfs; timer_t t; long err; if (se32 == NULL) return sys_timer_create(clock, NULL, timer_id); if (get_compat_sigevent(&se, se32)) return -EFAULT; if (!access_ok(VERIFY_WRITE,timer_id,sizeof(timer_t))) return -EFAULT; oldfs = get_fs(); set_fs(KERNEL_DS); err = sys_timer_create(clock, (struct sigevent __user *) &se, (timer_t __user *) &t); set_fs(oldfs); if (!err) err = __put_user (t, timer_id); return err;}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -