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

📄 sys_ia32.c

📁 linux 内核源代码
💻 C
📖 第 1 页 / 共 5 页
字号:
	gid_t a, b, c;	int ret;	mm_segment_t old_fs = get_fs();	set_fs(KERNEL_DS);	ret = sys_getresgid((gid_t __user *) &a, (gid_t __user *) &b, (gid_t __user *) &c);	set_fs(old_fs);	if (ret)		return ret;	return put_user(a, rgid) | put_user(b, egid) | put_user(c, sgid);}asmlinkage longsys32_lseek (unsigned int fd, int offset, unsigned int whence){	/* Sign-extension of "offset" is important here... */	return sys_lseek(fd, offset, whence);}static intgroups16_to_user(short __user *grouplist, struct group_info *group_info){	int i;	short group;	for (i = 0; i < group_info->ngroups; i++) {		group = (short)GROUP_AT(group_info, i);		if (put_user(group, grouplist+i))			return -EFAULT;	}	return 0;}static intgroups16_from_user(struct group_info *group_info, short __user *grouplist){	int i;	short group;	for (i = 0; i < group_info->ngroups; i++) {		if (get_user(group, grouplist+i))			return  -EFAULT;		GROUP_AT(group_info, i) = (gid_t)group;	}	return 0;}asmlinkage longsys32_getgroups16 (int gidsetsize, short __user *grouplist){	int i;	if (gidsetsize < 0)		return -EINVAL;	get_group_info(current->group_info);	i = current->group_info->ngroups;	if (gidsetsize) {		if (i > gidsetsize) {			i = -EINVAL;			goto out;		}		if (groups16_to_user(grouplist, current->group_info)) {			i = -EFAULT;			goto out;		}	}out:	put_group_info(current->group_info);	return i;}asmlinkage longsys32_setgroups16 (int gidsetsize, short __user *grouplist){	struct group_info *group_info;	int retval;	if (!capable(CAP_SETGID))		return -EPERM;	if ((unsigned)gidsetsize > NGROUPS_MAX)		return -EINVAL;	group_info = groups_alloc(gidsetsize);	if (!group_info)		return -ENOMEM;	retval = groups16_from_user(group_info, grouplist);	if (retval) {		put_group_info(group_info);		return retval;	}	retval = set_current_groups(group_info);	put_group_info(group_info);	return retval;}asmlinkage longsys32_truncate64 (unsigned int path, unsigned int len_lo, unsigned int len_hi){	return sys_truncate(compat_ptr(path), ((unsigned long) len_hi << 32) | len_lo);}asmlinkage longsys32_ftruncate64 (int fd, unsigned int len_lo, unsigned int len_hi){	return sys_ftruncate(fd, ((unsigned long) len_hi << 32) | len_lo);}static intputstat64 (struct stat64 __user *ubuf, struct kstat *kbuf){	int err;	u64 hdev;	if (clear_user(ubuf, sizeof(*ubuf)))		return -EFAULT;	hdev = huge_encode_dev(kbuf->dev);	err  = __put_user(hdev, (u32 __user*)&ubuf->st_dev);	err |= __put_user(hdev >> 32, ((u32 __user*)&ubuf->st_dev) + 1);	err |= __put_user(kbuf->ino, &ubuf->__st_ino);	err |= __put_user(kbuf->ino, &ubuf->st_ino_lo);	err |= __put_user(kbuf->ino >> 32, &ubuf->st_ino_hi);	err |= __put_user(kbuf->mode, &ubuf->st_mode);	err |= __put_user(kbuf->nlink, &ubuf->st_nlink);	err |= __put_user(kbuf->uid, &ubuf->st_uid);	err |= __put_user(kbuf->gid, &ubuf->st_gid);	hdev = huge_encode_dev(kbuf->rdev);	err  = __put_user(hdev, (u32 __user*)&ubuf->st_rdev);	err |= __put_user(hdev >> 32, ((u32 __user*)&ubuf->st_rdev) + 1);	err |= __put_user(kbuf->size, &ubuf->st_size_lo);	err |= __put_user((kbuf->size >> 32), &ubuf->st_size_hi);	err |= __put_user(kbuf->atime.tv_sec, &ubuf->st_atime);	err |= __put_user(kbuf->atime.tv_nsec, &ubuf->st_atime_nsec);	err |= __put_user(kbuf->mtime.tv_sec, &ubuf->st_mtime);	err |= __put_user(kbuf->mtime.tv_nsec, &ubuf->st_mtime_nsec);	err |= __put_user(kbuf->ctime.tv_sec, &ubuf->st_ctime);	err |= __put_user(kbuf->ctime.tv_nsec, &ubuf->st_ctime_nsec);	err |= __put_user(kbuf->blksize, &ubuf->st_blksize);	err |= __put_user(kbuf->blocks, &ubuf->st_blocks);	return err;}asmlinkage longsys32_stat64 (char __user *filename, struct stat64 __user *statbuf){	struct kstat s;	long ret = vfs_stat(filename, &s);	if (!ret)		ret = putstat64(statbuf, &s);	return ret;}asmlinkage longsys32_lstat64 (char __user *filename, struct stat64 __user *statbuf){	struct kstat s;	long ret = vfs_lstat(filename, &s);	if (!ret)		ret = putstat64(statbuf, &s);	return ret;}asmlinkage longsys32_fstat64 (unsigned int fd, struct stat64 __user *statbuf){	struct kstat s;	long ret = vfs_fstat(fd, &s);	if (!ret)		ret = putstat64(statbuf, &s);	return ret;}asmlinkage longsys32_sched_rr_get_interval (pid_t pid, struct compat_timespec __user *interval){	mm_segment_t old_fs = get_fs();	struct timespec t;	long ret;	set_fs(KERNEL_DS);	ret = sys_sched_rr_get_interval(pid, (struct timespec __user *) &t);	set_fs(old_fs);	if (put_compat_timespec(&t, interval))		return -EFAULT;	return ret;}asmlinkage longsys32_pread (unsigned int fd, void __user *buf, unsigned int count, u32 pos_lo, u32 pos_hi){	return sys_pread64(fd, buf, count, ((unsigned long) pos_hi << 32) | pos_lo);}asmlinkage longsys32_pwrite (unsigned int fd, void __user *buf, unsigned int count, u32 pos_lo, u32 pos_hi){	return sys_pwrite64(fd, buf, count, ((unsigned long) pos_hi << 32) | pos_lo);}asmlinkage longsys32_sendfile (int out_fd, int in_fd, int __user *offset, unsigned int count){	mm_segment_t old_fs = get_fs();	long 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 longsys32_personality (unsigned int personality){	long 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;}asmlinkage unsigned longsys32_brk (unsigned int brk){	unsigned long ret, obrk;	struct mm_struct *mm = current->mm;	obrk = mm->brk;	ret = sys_brk(brk);	if (ret < obrk)		clear_user(compat_ptr(ret), PAGE_ALIGN(ret) - ret);	return ret;}/* Structure for ia32 emulation on ia64 */struct epoll_event32{	u32 events;	u32 data[2];};asmlinkage longsys32_epoll_ctl(int epfd, int op, int fd, struct epoll_event32 __user *event){	mm_segment_t old_fs = get_fs();	struct epoll_event event64;	int error;	u32 data_halfword;	if (!access_ok(VERIFY_READ, event, sizeof(struct epoll_event32)))		return -EFAULT;	__get_user(event64.events, &event->events);	__get_user(data_halfword, &event->data[0]);	event64.data = data_halfword;	__get_user(data_halfword, &event->data[1]); 	event64.data |= (u64)data_halfword << 32;	set_fs(KERNEL_DS);	error = sys_epoll_ctl(epfd, op, fd, (struct epoll_event __user *) &event64);	set_fs(old_fs);	return error;}asmlinkage longsys32_epoll_wait(int epfd, struct epoll_event32 __user * events, int maxevents,		 int timeout){	struct epoll_event *events64 = NULL;	mm_segment_t old_fs = get_fs();	int numevents, size;	int evt_idx;	int do_free_pages = 0;	if (maxevents <= 0) {		return -EINVAL;	}	/* Verify that the area passed by the user is writeable */	if (!access_ok(VERIFY_WRITE, events, maxevents * sizeof(struct epoll_event32)))		return -EFAULT;	/* 	 * Allocate space for the intermediate copy.  If the space needed	 * is large enough to cause kmalloc to fail, then try again with	 * __get_free_pages.	 */	size = maxevents * sizeof(struct epoll_event);	events64 = kmalloc(size, GFP_KERNEL);	if (events64 == NULL) {		events64 = (struct epoll_event *)				__get_free_pages(GFP_KERNEL, get_order(size));		if (events64 == NULL)			return -ENOMEM;		do_free_pages = 1;	}	/* Do the system call */	set_fs(KERNEL_DS); /* copy_to/from_user should work on kernel mem*/	numevents = sys_epoll_wait(epfd, (struct epoll_event __user *) events64,				   maxevents, timeout);	set_fs(old_fs);	/* Don't modify userspace memory if we're returning an error */	if (numevents > 0) {		/* Translate the 64-bit structures back into the 32-bit		   structures */		for (evt_idx = 0; evt_idx < numevents; evt_idx++) {			__put_user(events64[evt_idx].events,				   &events[evt_idx].events);			__put_user((u32)events64[evt_idx].data,				   &events[evt_idx].data[0]);			__put_user((u32)(events64[evt_idx].data >> 32),				   &events[evt_idx].data[1]);		}	}	if (do_free_pages)		free_pages((unsigned long) events64, get_order(size));	else		kfree(events64);	return numevents;}/* * Get a yet unused TLS descriptor index. */static intget_free_idx (void){	struct thread_struct *t = &current->thread;	int idx;	for (idx = 0; idx < GDT_ENTRY_TLS_ENTRIES; idx++)		if (desc_empty(t->tls_array + idx))			return idx + GDT_ENTRY_TLS_MIN;	return -ESRCH;}/* * Set a given TLS descriptor: */asmlinkage intsys32_set_thread_area (struct ia32_user_desc __user *u_info){	struct thread_struct *t = &current->thread;	struct ia32_user_desc info;	struct desc_struct *desc;	int cpu, idx;	if (copy_from_user(&info, u_info, sizeof(info)))		return -EFAULT;	idx = info.entry_number;	/*	 * index -1 means the kernel should try to find and allocate an empty descriptor:	 */	if (idx == -1) {		idx = get_free_idx();		if (idx < 0)			return idx;		if (put_user(idx, &u_info->entry_number))			return -EFAULT;	}	if (idx < GDT_ENTRY_TLS_MIN || idx > GDT_ENTRY_TLS_MAX)		return -EINVAL;	desc = t->tls_array + idx - GDT_ENTRY_TLS_MIN;	cpu = smp_processor_id();	if (LDT_empty(&info)) {		desc->a = 0;		desc->b = 0;	} else {		desc->a = LDT_entry_a(&info);		desc->b = LDT_entry_b(&info);	}	load_TLS(t, cpu);	return 0;}/* * Get the current Thread-Local Storage area: */#define GET_BASE(desc) (			\	(((desc)->a >> 16) & 0x0000ffff) |	\	(((desc)->b << 16) & 0x00ff0000) |	\	( (desc)->b        & 0xff000000)   )#define GET_LIMIT(desc) (			\	((desc)->a & 0x0ffff) |			\	 ((desc)->b & 0xf0000) )#define GET_32BIT(desc)		(((desc)->b >> 22) & 1)#define GET_CONTENTS(desc)	(((desc)->b >> 10) & 3)#define GET_WRITABLE(desc)	(((desc)->b >>  9) & 1)#define GET_LIMIT_PAGES(desc)	(((desc)->b >> 23) & 1)#define GET_PRESENT(desc)	(((desc)->b >> 15) & 1)#define GET_USEABLE(desc)	(((desc)->b >> 20) & 1)asmlinkage intsys32_get_thread_area (struct ia32_user_desc __user *u_info){	struct ia32_user_desc info;	struct desc_struct *desc;	int idx;	if (get_user(idx, &u_info->entry_number))		return -EFAULT;	if (idx < GDT_ENTRY_TLS_MIN || idx > GDT_ENTRY_TLS_MAX)		return -EINVAL;	desc = current->thread.tls_array + idx - GDT_ENTRY_TLS_MIN;	info.entry_number = idx;	info.base_addr = GET_BASE(desc);	info.limit = GET_LIMIT(desc);	info.seg_32bit = GET_32BIT(desc);	info.contents = GET_CONTENTS(desc);	info.read_exec_only = !GET_WRITABLE(desc);	info.limit_in_pages = GET_LIMIT_PAGES(desc);	info.seg_not_present = !GET_PRESENT(desc);	info.useable = GET_USEABLE(desc);	if (copy_to_user(u_info, &info, sizeof(info)))		return -EFAULT;	return 0;}long sys32_fadvise64_64(int fd, __u32 offset_low, __u32 offset_high, 			__u32 len_low, __u32 len_high, int advice){ 	return sys_fadvise64_64(fd,			       (((u64)offset_high)<<32) | offset_low,			       (((u64)len_high)<<32) | len_low,			       advice); } #ifdef	NOTYET  /* UNTESTED FOR IA64 FROM HERE DOWN */asmlinkage long sys32_setreuid(compat_uid_t ruid, compat_uid_t euid){	uid_t sruid, seuid;	sruid = (ruid == (compat_uid_t)-1) ? ((uid_t)-1) : ((uid_t)ruid);	seuid = (euid == (compat_uid_t)-1) ? ((uid_t)-1) : ((uid_t)euid);	return sys_setreuid(sruid, seuid);}asmlinkage longsys32_setresuid(compat_uid_t ruid, compat_uid_t euid,		compat_uid_t suid){	uid_t sruid, seuid, ssuid;	sruid = (ruid == (compat_uid_t)-1) ? ((uid_t)-1) : ((uid_t)ruid);	seuid = (euid == (compat_uid_t)-1) ? ((uid_t)-1) : ((uid_t)euid);	ssuid = (suid == (compat_uid_t)-1) ? ((uid_t)-1) : ((uid_t)suid);	return sys_setresuid(sruid, seuid, ssuid);}asmlinkage longsys32_setregid(compat_gid_t rgid, compat_gid_t egid){	gid_t srgid, segid;	srgid = (rgid == (compat_gid_t)-1) ? ((gid_t)-1) : ((gid_t)rgid);	segid = (egid == (compat_gid_t)-1) ? ((gid_t)-1) : ((gid_t)egid);	return sys_setregid(srgid, segid);}asmlinkage longsys32_setresgid(compat_gid_t rgid, compat_gid_t egid,		compat_gid_t sgid){	gid_t srgid, segid, ssgid;	srgid = (rgid == (compat_gid_t)-1) ? ((gid_t)-1) : ((gid_t)rgid);	segid = (egid == (compat_gid_t)-1) ? ((gid_t)-1) : ((gid_t)egid);	ssgid = (sgid == (compat_gid_t)-1) ? ((gid_t)-1) : ((gid_t)sgid);	return sys_setresgid(srgid, segid, ssgid);}#endif /* NOTYET */

⌨️ 快捷键说明

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