⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 compat.c

📁 linux 2.6.19 kernel source code before patching
💻 C
📖 第 1 页 / 共 2 页
字号:
	oldfs = get_fs();	set_fs(KERNEL_DS);	err = sys_timer_gettime(timer_id,				(struct itimerspec __user *) &ts); 	set_fs(oldfs); 	if (!err && put_compat_itimerspec(setting, &ts))		return -EFAULT;	return err;} long compat_sys_clock_settime(clockid_t which_clock,		struct compat_timespec __user *tp){	long err;	mm_segment_t oldfs;	struct timespec ts; 	if (get_compat_timespec(&ts, tp))		return -EFAULT; 	oldfs = get_fs();	set_fs(KERNEL_DS);		err = sys_clock_settime(which_clock,				(struct timespec __user *) &ts);	set_fs(oldfs);	return err;} long compat_sys_clock_gettime(clockid_t which_clock,		struct compat_timespec __user *tp){	long err;	mm_segment_t oldfs;	struct timespec ts; 	oldfs = get_fs();	set_fs(KERNEL_DS);	err = sys_clock_gettime(which_clock,				(struct timespec __user *) &ts);	set_fs(oldfs);	if (!err && put_compat_timespec(&ts, tp))		return -EFAULT; 	return err;} long compat_sys_clock_getres(clockid_t which_clock,		struct compat_timespec __user *tp){	long err;	mm_segment_t oldfs;	struct timespec ts; 	oldfs = get_fs();	set_fs(KERNEL_DS);	err = sys_clock_getres(which_clock,			       (struct timespec __user *) &ts);	set_fs(oldfs);	if (!err && tp && put_compat_timespec(&ts, tp))		return -EFAULT; 	return err;} static long compat_clock_nanosleep_restart(struct restart_block *restart){	long err;	mm_segment_t oldfs;	struct timespec tu;	struct compat_timespec *rmtp = (struct compat_timespec *)(restart->arg1);	restart->arg1 = (unsigned long) &tu;	oldfs = get_fs();	set_fs(KERNEL_DS);	err = clock_nanosleep_restart(restart);	set_fs(oldfs);	if ((err == -ERESTART_RESTARTBLOCK) && rmtp &&	    put_compat_timespec(&tu, rmtp))		return -EFAULT;	if (err == -ERESTART_RESTARTBLOCK) {		restart->fn = compat_clock_nanosleep_restart;		restart->arg1 = (unsigned long) rmtp;	}	return err;}long compat_sys_clock_nanosleep(clockid_t which_clock, int flags,			    struct compat_timespec __user *rqtp,			    struct compat_timespec __user *rmtp){	long err;	mm_segment_t oldfs;	struct timespec in, out; 	struct restart_block *restart;	if (get_compat_timespec(&in, rqtp)) 		return -EFAULT;	oldfs = get_fs();	set_fs(KERNEL_DS);	err = sys_clock_nanosleep(which_clock, flags,				  (struct timespec __user *) &in,				  (struct timespec __user *) &out);	set_fs(oldfs);	if ((err == -ERESTART_RESTARTBLOCK) && rmtp &&	    put_compat_timespec(&out, rmtp))		return -EFAULT;	if (err == -ERESTART_RESTARTBLOCK) {		restart = &current_thread_info()->restart_block;		restart->fn = compat_clock_nanosleep_restart;		restart->arg1 = (unsigned long) rmtp;	}	return err;	} /* * We currently only need the following fields from the sigevent * structure: sigev_value, sigev_signo, sig_notify and (sometimes * sigev_notify_thread_id).  The others are handled in user mode. * We also assume that copying sigev_value.sival_int is sufficient * to keep all the bits of sigev_value.sival_ptr intact. */int get_compat_sigevent(struct sigevent *event,		const struct compat_sigevent __user *u_event){	memset(event, 0, sizeof(*event));	return (!access_ok(VERIFY_READ, u_event, sizeof(*u_event)) ||		__get_user(event->sigev_value.sival_int,			&u_event->sigev_value.sival_int) ||		__get_user(event->sigev_signo, &u_event->sigev_signo) ||		__get_user(event->sigev_notify, &u_event->sigev_notify) ||		__get_user(event->sigev_notify_thread_id,			&u_event->sigev_notify_thread_id))		? -EFAULT : 0;}long compat_get_bitmap(unsigned long *mask, const compat_ulong_t __user *umask,		       unsigned long bitmap_size){	int i, j;	unsigned long m;	compat_ulong_t um;	unsigned long nr_compat_longs;	/* align bitmap up to nearest compat_long_t boundary */	bitmap_size = ALIGN(bitmap_size, BITS_PER_COMPAT_LONG);	if (!access_ok(VERIFY_READ, umask, bitmap_size / 8))		return -EFAULT;	nr_compat_longs = BITS_TO_COMPAT_LONGS(bitmap_size);	for (i = 0; i < BITS_TO_LONGS(bitmap_size); i++) {		m = 0;		for (j = 0; j < sizeof(m)/sizeof(um); j++) {			/*			 * We dont want to read past the end of the userspace			 * bitmap. We must however ensure the end of the			 * kernel bitmap is zeroed.			 */			if (nr_compat_longs-- > 0) {				if (__get_user(um, umask))					return -EFAULT;			} else {				um = 0;			}			umask++;			m |= (long)um << (j * BITS_PER_COMPAT_LONG);		}		*mask++ = m;	}	return 0;}long compat_put_bitmap(compat_ulong_t __user *umask, unsigned long *mask,		       unsigned long bitmap_size){	int i, j;	unsigned long m;	compat_ulong_t um;	unsigned long nr_compat_longs;	/* align bitmap up to nearest compat_long_t boundary */	bitmap_size = ALIGN(bitmap_size, BITS_PER_COMPAT_LONG);	if (!access_ok(VERIFY_WRITE, umask, bitmap_size / 8))		return -EFAULT;	nr_compat_longs = BITS_TO_COMPAT_LONGS(bitmap_size);	for (i = 0; i < BITS_TO_LONGS(bitmap_size); i++) {		m = *mask++;		for (j = 0; j < sizeof(m)/sizeof(um); j++) {			um = m;			/*			 * We dont want to write past the end of the userspace			 * bitmap.			 */			if (nr_compat_longs-- > 0) {				if (__put_user(um, umask))					return -EFAULT;			}			umask++;			m >>= 4*sizeof(um);			m >>= 4*sizeof(um);		}	}	return 0;}voidsigset_from_compat (sigset_t *set, compat_sigset_t *compat){	switch (_NSIG_WORDS) {	case 4: set->sig[3] = compat->sig[6] | (((long)compat->sig[7]) << 32 );	case 3: set->sig[2] = compat->sig[4] | (((long)compat->sig[5]) << 32 );	case 2: set->sig[1] = compat->sig[2] | (((long)compat->sig[3]) << 32 );	case 1: set->sig[0] = compat->sig[0] | (((long)compat->sig[1]) << 32 );	}}asmlinkage longcompat_sys_rt_sigtimedwait (compat_sigset_t __user *uthese,		struct compat_siginfo __user *uinfo,		struct compat_timespec __user *uts, compat_size_t sigsetsize){	compat_sigset_t s32;	sigset_t s;	int sig;	struct timespec t;	siginfo_t info;	long ret, timeout = 0;	if (sigsetsize != sizeof(sigset_t))		return -EINVAL;	if (copy_from_user(&s32, uthese, sizeof(compat_sigset_t)))		return -EFAULT;	sigset_from_compat(&s, &s32);	sigdelsetmask(&s,sigmask(SIGKILL)|sigmask(SIGSTOP));	signotset(&s);	if (uts) {		if (get_compat_timespec (&t, uts))			return -EFAULT;		if (t.tv_nsec >= 1000000000L || t.tv_nsec < 0				|| t.tv_sec < 0)			return -EINVAL;	}	spin_lock_irq(&current->sighand->siglock);	sig = dequeue_signal(current, &s, &info);	if (!sig) {		timeout = MAX_SCHEDULE_TIMEOUT;		if (uts)			timeout = timespec_to_jiffies(&t)				+(t.tv_sec || t.tv_nsec);		if (timeout) {			current->real_blocked = current->blocked;			sigandsets(&current->blocked, &current->blocked, &s);			recalc_sigpending();			spin_unlock_irq(&current->sighand->siglock);			timeout = schedule_timeout_interruptible(timeout);			spin_lock_irq(&current->sighand->siglock);			sig = dequeue_signal(current, &s, &info);			current->blocked = current->real_blocked;			siginitset(&current->real_blocked, 0);			recalc_sigpending();		}	}	spin_unlock_irq(&current->sighand->siglock);	if (sig) {		ret = sig;		if (uinfo) {			if (copy_siginfo_to_user32(uinfo, &info))				ret = -EFAULT;		}	}else {		ret = timeout?-EINTR:-EAGAIN;	}	return ret;}#ifdef __ARCH_WANT_COMPAT_SYS_TIME/* compat_time_t is a 32 bit "long" and needs to get converted. */asmlinkage long compat_sys_time(compat_time_t __user * tloc){	compat_time_t i;	struct timeval tv;	do_gettimeofday(&tv);	i = tv.tv_sec;	if (tloc) {		if (put_user(i,tloc))			i = -EFAULT;	}	return i;}asmlinkage long compat_sys_stime(compat_time_t __user *tptr){	struct timespec tv;	int err;	if (get_user(tv.tv_sec, tptr))		return -EFAULT;	tv.tv_nsec = 0;	err = security_settime(&tv, NULL);	if (err)		return err;	do_settimeofday(&tv);	return 0;}#endif /* __ARCH_WANT_COMPAT_SYS_TIME */#ifdef __ARCH_WANT_COMPAT_SYS_RT_SIGSUSPENDasmlinkage long compat_sys_rt_sigsuspend(compat_sigset_t __user *unewset, compat_size_t sigsetsize){	sigset_t newset;	compat_sigset_t newset32;	/* XXX: Don't preclude handling different sized sigset_t's.  */	if (sigsetsize != sizeof(sigset_t))		return -EINVAL;	if (copy_from_user(&newset32, unewset, sizeof(compat_sigset_t)))		return -EFAULT;	sigset_from_compat(&newset, &newset32);	sigdelsetmask(&newset, sigmask(SIGKILL)|sigmask(SIGSTOP));	spin_lock_irq(&current->sighand->siglock);	current->saved_sigmask = current->blocked;	current->blocked = newset;	recalc_sigpending();	spin_unlock_irq(&current->sighand->siglock);	current->state = TASK_INTERRUPTIBLE;	schedule();	set_thread_flag(TIF_RESTORE_SIGMASK);	return -ERESTARTNOHAND;}#endif /* __ARCH_WANT_COMPAT_SYS_RT_SIGSUSPEND */asmlinkage long compat_sys_adjtimex(struct compat_timex __user *utp){	struct timex txc;	int ret;	memset(&txc, 0, sizeof(struct timex));	if (!access_ok(VERIFY_READ, utp, sizeof(struct compat_timex)) ||			__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 (!access_ok(VERIFY_WRITE, utp, sizeof(struct compat_timex)) ||			__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;}#ifdef CONFIG_NUMAasmlinkage long compat_sys_move_pages(pid_t pid, unsigned long nr_pages,		compat_uptr_t __user *pages32,		const int __user *nodes,		int __user *status,		int flags){	const void __user * __user *pages;	int i;	pages = compat_alloc_user_space(nr_pages * sizeof(void *));	for (i = 0; i < nr_pages; i++) {		compat_uptr_t p;		if (get_user(p, pages32 + i) ||			put_user(compat_ptr(p), pages + i))			return -EFAULT;	}	return sys_move_pages(pid, nr_pages, pages, nodes, status, flags);}asmlinkage long compat_sys_migrate_pages(compat_pid_t pid,			compat_ulong_t maxnode,			const compat_ulong_t __user *old_nodes,			const compat_ulong_t __user *new_nodes){	unsigned long __user *old = NULL;	unsigned long __user *new = NULL;	nodemask_t tmp_mask;	unsigned long nr_bits;	unsigned long size;	nr_bits = min_t(unsigned long, maxnode - 1, MAX_NUMNODES);	size = ALIGN(nr_bits, BITS_PER_LONG) / 8;	if (old_nodes) {		if (compat_get_bitmap(nodes_addr(tmp_mask), old_nodes, nr_bits))			return -EFAULT;		old = compat_alloc_user_space(new_nodes ? size * 2 : size);		if (new_nodes)			new = old + size / sizeof(unsigned long);		if (copy_to_user(old, nodes_addr(tmp_mask), size))			return -EFAULT;	}	if (new_nodes) {		if (compat_get_bitmap(nodes_addr(tmp_mask), new_nodes, nr_bits))			return -EFAULT;		if (new == NULL)			new = compat_alloc_user_space(size);		if (copy_to_user(new, nodes_addr(tmp_mask), size))			return -EFAULT;	}	return sys_migrate_pages(pid, nr_bits + 1, old, new);}#endifstruct compat_sysinfo {	s32 uptime;	u32 loads[3];	u32 totalram;	u32 freeram;	u32 sharedram;	u32 bufferram;	u32 totalswap;	u32 freeswap;	u16 procs;	u16 pad;	u32 totalhigh;	u32 freehigh;	u32 mem_unit;	char _f[20-2*sizeof(u32)-sizeof(int)];};asmlinkage longcompat_sys_sysinfo(struct compat_sysinfo __user *info){	struct sysinfo s;	do_sysinfo(&s);	/* Check to see if any memory value is too large for 32-bit and scale	 *  down if needed	 */	if ((s.totalram >> 32) || (s.totalswap >> 32)) {		int bitcount = 0;		while (s.mem_unit < PAGE_SIZE) {			s.mem_unit <<= 1;			bitcount++;		}		s.totalram >>= bitcount;		s.freeram >>= bitcount;		s.sharedram >>= bitcount;		s.bufferram >>= bitcount;		s.totalswap >>= bitcount;		s.freeswap >>= bitcount;		s.totalhigh >>= bitcount;		s.freehigh >>= bitcount;	}	if (!access_ok(VERIFY_WRITE, info, sizeof(struct compat_sysinfo)) ||	    __put_user (s.uptime, &info->uptime) ||	    __put_user (s.loads[0], &info->loads[0]) ||	    __put_user (s.loads[1], &info->loads[1]) ||	    __put_user (s.loads[2], &info->loads[2]) ||	    __put_user (s.totalram, &info->totalram) ||	    __put_user (s.freeram, &info->freeram) ||	    __put_user (s.sharedram, &info->sharedram) ||	    __put_user (s.bufferram, &info->bufferram) ||	    __put_user (s.totalswap, &info->totalswap) ||	    __put_user (s.freeswap, &info->freeswap) ||	    __put_user (s.procs, &info->procs) ||	    __put_user (s.totalhigh, &info->totalhigh) ||	    __put_user (s.freehigh, &info->freehigh) ||	    __put_user (s.mem_unit, &info->mem_unit))		return -EFAULT;	return 0;}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -