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

📄 ia32_ldt.c

📁 上传linux-jx2410的源代码
💻 C
字号:
/* * Copyright (C) 2001 Hewlett-Packard Co *	David Mosberger-Tang <davidm@hpl.hp.com> * * Adapted from arch/i386/kernel/ldt.c */#include <linux/errno.h>#include <linux/sched.h>#include <linux/string.h>#include <linux/mm.h>#include <linux/smp.h>#include <linux/smp_lock.h>#include <linux/vmalloc.h>#include <asm/uaccess.h>#include <asm/ia32.h>#define P(p)	((void *) (unsigned long) (p))/* * read_ldt() is not really atomic - this is not a problem since synchronization of reads * and writes done to the LDT has to be assured by user-space anyway. Writes are atomic, * to protect the security checks done on new descriptors. */static intread_ldt (void *ptr, unsigned long bytecount){	char *src, *dst, buf[256];	/* temporary buffer (don't overflow kernel stack!) */	unsigned long bytes_left, n;	if (bytecount > IA32_LDT_ENTRIES*IA32_LDT_ENTRY_SIZE)		bytecount = IA32_LDT_ENTRIES*IA32_LDT_ENTRY_SIZE;	bytes_left = bytecount;	src = (void *) IA32_LDT_OFFSET;	dst = ptr;	while (bytes_left) {		n = sizeof(buf);		if (n > bytes_left)			n = bytes_left;		/*		 * We know we're reading valid memory, but we still must guard against		 * running out of memory.		 */		if (__copy_from_user(buf, src, n))			return -EFAULT;		if (copy_to_user(dst, buf, n))			return -EFAULT;		src += n;		dst += n;		bytes_left -= n;	}	return bytecount;}static intread_default_ldt (void * ptr, unsigned long bytecount){	unsigned long size;	int err;	/* XXX fix me: should return equivalent of default_ldt[0] */	err = 0;	size = 8;	if (size > bytecount)		size = bytecount;	err = size;	if (clear_user(ptr, size))		err = -EFAULT;	return err;}static intwrite_ldt (void * ptr, unsigned long bytecount, int oldmode){	struct ia32_modify_ldt_ldt_s ldt_info;	__u64 entry;	int ret;	if (bytecount != sizeof(ldt_info))		return -EINVAL;	if (copy_from_user(&ldt_info, ptr, sizeof(ldt_info)))		return -EFAULT;	if (ldt_info.entry_number >= IA32_LDT_ENTRIES)		return -EINVAL;	if (ldt_info.contents == 3) {		if (oldmode)			return -EINVAL;		if (ldt_info.seg_not_present == 0)			return -EINVAL;	}	if (ldt_info.base_addr == 0 && ldt_info.limit == 0	    && (oldmode || (ldt_info.contents == 0 && ldt_info.read_exec_only == 1			    && ldt_info.seg_32bit == 0 && ldt_info.limit_in_pages == 0			    && ldt_info.seg_not_present == 1 && ldt_info.useable == 0)))		/* allow LDTs to be cleared by the user */		entry = 0;	else		/* we must set the "Accessed" bit as IVE doesn't emulate it */		entry = IA32_SEG_DESCRIPTOR(ldt_info.base_addr, ldt_info.limit,					    (((ldt_info.read_exec_only ^ 1) << 1)					     | (ldt_info.contents << 2)) | 1,					    1, 3, ldt_info.seg_not_present ^ 1,					    (oldmode ? 0 : ldt_info.useable),					    ldt_info.seg_32bit,					    ldt_info.limit_in_pages);	/*	 * Install the new entry.  We know we're accessing valid (mapped) user-level	 * memory, but we still need to guard against out-of-memory, hence we must use	 * put_user().	 */	ret = __put_user(entry, (__u64 *) IA32_LDT_OFFSET + ldt_info.entry_number);	ia32_load_segment_descriptors(current);	return ret;}asmlinkage intsys32_modify_ldt (int func, unsigned int ptr, unsigned int bytecount){	int ret = -ENOSYS;	switch (func) {	      case 0:		ret = read_ldt(P(ptr), bytecount);		break;	      case 1:		ret = write_ldt(P(ptr), bytecount, 1);		break;	      case 2:		ret = read_default_ldt(P(ptr), bytecount);		break;	      case 0x11:		ret = write_ldt(P(ptr), bytecount, 0);		break;	}	return ret;}

⌨️ 快捷键说明

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