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

📄 base.c

📁 linux 内核源代码
💻 C
📖 第 1 页 / 共 5 页
字号:
	.read		= seq_read,	.llseek		= seq_lseek,	.release	= mounts_release,};#define PROC_BLOCK_SIZE	(3*1024)		/* 4K page size but our output routines use some slack for overruns */static ssize_t proc_info_read(struct file * file, char __user * buf,			  size_t count, loff_t *ppos){	struct inode * inode = file->f_path.dentry->d_inode;	unsigned long page;	ssize_t length;	struct task_struct *task = get_proc_task(inode);	length = -ESRCH;	if (!task)		goto out_no_task;	if (count > PROC_BLOCK_SIZE)		count = PROC_BLOCK_SIZE;	length = -ENOMEM;	if (!(page = __get_free_page(GFP_TEMPORARY)))		goto out;	length = PROC_I(inode)->op.proc_read(task, (char*)page);	if (length >= 0)		length = simple_read_from_buffer(buf, count, ppos, (char *)page, length);	free_page(page);out:	put_task_struct(task);out_no_task:	return length;}static const struct file_operations proc_info_file_operations = {	.read		= proc_info_read,};static int mem_open(struct inode* inode, struct file* file){	file->private_data = (void*)((long)current->self_exec_id);	return 0;}static ssize_t mem_read(struct file * file, char __user * buf,			size_t count, loff_t *ppos){	struct task_struct *task = get_proc_task(file->f_path.dentry->d_inode);	char *page;	unsigned long src = *ppos;	int ret = -ESRCH;	struct mm_struct *mm;	if (!task)		goto out_no_task;	if (!MAY_PTRACE(task) || !ptrace_may_attach(task))		goto out;	ret = -ENOMEM;	page = (char *)__get_free_page(GFP_TEMPORARY);	if (!page)		goto out;	ret = 0; 	mm = get_task_mm(task);	if (!mm)		goto out_free;	ret = -EIO; 	if (file->private_data != (void*)((long)current->self_exec_id))		goto out_put;	ret = 0; 	while (count > 0) {		int this_len, retval;		this_len = (count > PAGE_SIZE) ? PAGE_SIZE : count;		retval = access_process_vm(task, src, page, this_len, 0);		if (!retval || !MAY_PTRACE(task) || !ptrace_may_attach(task)) {			if (!ret)				ret = -EIO;			break;		}		if (copy_to_user(buf, page, retval)) {			ret = -EFAULT;			break;		} 		ret += retval;		src += retval;		buf += retval;		count -= retval;	}	*ppos = src;out_put:	mmput(mm);out_free:	free_page((unsigned long) page);out:	put_task_struct(task);out_no_task:	return ret;}#define mem_write NULL#ifndef mem_write/* This is a security hazard */static ssize_t mem_write(struct file * file, const char __user *buf,			 size_t count, loff_t *ppos){	int copied;	char *page;	struct task_struct *task = get_proc_task(file->f_path.dentry->d_inode);	unsigned long dst = *ppos;	copied = -ESRCH;	if (!task)		goto out_no_task;	if (!MAY_PTRACE(task) || !ptrace_may_attach(task))		goto out;	copied = -ENOMEM;	page = (char *)__get_free_page(GFP_TEMPORARY);	if (!page)		goto out;	copied = 0;	while (count > 0) {		int this_len, retval;		this_len = (count > PAGE_SIZE) ? PAGE_SIZE : count;		if (copy_from_user(page, buf, this_len)) {			copied = -EFAULT;			break;		}		retval = access_process_vm(task, dst, page, this_len, 1);		if (!retval) {			if (!copied)				copied = -EIO;			break;		}		copied += retval;		buf += retval;		dst += retval;		count -= retval;				}	*ppos = dst;	free_page((unsigned long) page);out:	put_task_struct(task);out_no_task:	return copied;}#endifstatic loff_t mem_lseek(struct file * file, loff_t offset, int orig){	switch (orig) {	case 0:		file->f_pos = offset;		break;	case 1:		file->f_pos += offset;		break;	default:		return -EINVAL;	}	force_successful_syscall_return();	return file->f_pos;}static const struct file_operations proc_mem_operations = {	.llseek		= mem_lseek,	.read		= mem_read,	.write		= mem_write,	.open		= mem_open,};static ssize_t environ_read(struct file *file, char __user *buf,			size_t count, loff_t *ppos){	struct task_struct *task = get_proc_task(file->f_dentry->d_inode);	char *page;	unsigned long src = *ppos;	int ret = -ESRCH;	struct mm_struct *mm;	if (!task)		goto out_no_task;	if (!ptrace_may_attach(task))		goto out;	ret = -ENOMEM;	page = (char *)__get_free_page(GFP_TEMPORARY);	if (!page)		goto out;	ret = 0;	mm = get_task_mm(task);	if (!mm)		goto out_free;	while (count > 0) {		int this_len, retval, max_len;		this_len = mm->env_end - (mm->env_start + src);		if (this_len <= 0)			break;		max_len = (count > PAGE_SIZE) ? PAGE_SIZE : count;		this_len = (this_len > max_len) ? max_len : this_len;		retval = access_process_vm(task, (mm->env_start + src),			page, this_len, 0);		if (retval <= 0) {			ret = retval;			break;		}		if (copy_to_user(buf, page, retval)) {			ret = -EFAULT;			break;		}		ret += retval;		src += retval;		buf += retval;		count -= retval;	}	*ppos = src;	mmput(mm);out_free:	free_page((unsigned long) page);out:	put_task_struct(task);out_no_task:	return ret;}static const struct file_operations proc_environ_operations = {	.read		= environ_read,};static ssize_t oom_adjust_read(struct file *file, char __user *buf,				size_t count, loff_t *ppos){	struct task_struct *task = get_proc_task(file->f_path.dentry->d_inode);	char buffer[PROC_NUMBUF];	size_t len;	int oom_adjust;	if (!task)		return -ESRCH;	oom_adjust = task->oomkilladj;	put_task_struct(task);	len = snprintf(buffer, sizeof(buffer), "%i\n", oom_adjust);	return simple_read_from_buffer(buf, count, ppos, buffer, len);}static ssize_t oom_adjust_write(struct file *file, const char __user *buf,				size_t count, loff_t *ppos){	struct task_struct *task;	char buffer[PROC_NUMBUF], *end;	int oom_adjust;	memset(buffer, 0, sizeof(buffer));	if (count > sizeof(buffer) - 1)		count = sizeof(buffer) - 1;	if (copy_from_user(buffer, buf, count))		return -EFAULT;	oom_adjust = simple_strtol(buffer, &end, 0);	if ((oom_adjust < OOM_ADJUST_MIN || oom_adjust > OOM_ADJUST_MAX) &&	     oom_adjust != OOM_DISABLE)		return -EINVAL;	if (*end == '\n')		end++;	task = get_proc_task(file->f_path.dentry->d_inode);	if (!task)		return -ESRCH;	if (oom_adjust < task->oomkilladj && !capable(CAP_SYS_RESOURCE)) {		put_task_struct(task);		return -EACCES;	}	task->oomkilladj = oom_adjust;	put_task_struct(task);	if (end - buffer == 0)		return -EIO;	return end - buffer;}static const struct file_operations proc_oom_adjust_operations = {	.read		= oom_adjust_read,	.write		= oom_adjust_write,};#ifdef CONFIG_MMUstatic ssize_t clear_refs_write(struct file *file, const char __user *buf,				size_t count, loff_t *ppos){	struct task_struct *task;	char buffer[PROC_NUMBUF], *end;	struct mm_struct *mm;	memset(buffer, 0, sizeof(buffer));	if (count > sizeof(buffer) - 1)		count = sizeof(buffer) - 1;	if (copy_from_user(buffer, buf, count))		return -EFAULT;	if (!simple_strtol(buffer, &end, 0))		return -EINVAL;	if (*end == '\n')		end++;	task = get_proc_task(file->f_path.dentry->d_inode);	if (!task)		return -ESRCH;	mm = get_task_mm(task);	if (mm) {		clear_refs_smap(mm);		mmput(mm);	}	put_task_struct(task);	if (end - buffer == 0)		return -EIO;	return end - buffer;}static struct file_operations proc_clear_refs_operations = {	.write		= clear_refs_write,};#endif#ifdef CONFIG_AUDITSYSCALL#define TMPBUFLEN 21static ssize_t proc_loginuid_read(struct file * file, char __user * buf,				  size_t count, loff_t *ppos){	struct inode * inode = file->f_path.dentry->d_inode;	struct task_struct *task = get_proc_task(inode);	ssize_t length;	char tmpbuf[TMPBUFLEN];	if (!task)		return -ESRCH;	length = scnprintf(tmpbuf, TMPBUFLEN, "%u",				audit_get_loginuid(task->audit_context));	put_task_struct(task);	return simple_read_from_buffer(buf, count, ppos, tmpbuf, length);}static ssize_t proc_loginuid_write(struct file * file, const char __user * buf,				   size_t count, loff_t *ppos){	struct inode * inode = file->f_path.dentry->d_inode;	char *page, *tmp;	ssize_t length;	uid_t loginuid;	if (!capable(CAP_AUDIT_CONTROL))		return -EPERM;	if (current != pid_task(proc_pid(inode), PIDTYPE_PID))		return -EPERM;	if (count >= PAGE_SIZE)		count = PAGE_SIZE - 1;	if (*ppos != 0) {		/* No partial writes. */		return -EINVAL;	}	page = (char*)__get_free_page(GFP_TEMPORARY);	if (!page)		return -ENOMEM;	length = -EFAULT;	if (copy_from_user(page, buf, count))		goto out_free_page;	page[count] = '\0';	loginuid = simple_strtoul(page, &tmp, 10);	if (tmp == page) {		length = -EINVAL;		goto out_free_page;	}	length = audit_set_loginuid(current, loginuid);	if (likely(length == 0))		length = count;out_free_page:	free_page((unsigned long) page);	return length;}static const struct file_operations proc_loginuid_operations = {	.read		= proc_loginuid_read,	.write		= proc_loginuid_write,};#endif#ifdef CONFIG_FAULT_INJECTIONstatic ssize_t proc_fault_inject_read(struct file * file, char __user * buf,				      size_t count, loff_t *ppos){	struct task_struct *task = get_proc_task(file->f_dentry->d_inode);	char buffer[PROC_NUMBUF];	size_t len;	int make_it_fail;	if (!task)		return -ESRCH;	make_it_fail = task->make_it_fail;	put_task_struct(task);	len = snprintf(buffer, sizeof(buffer), "%i\n", make_it_fail);	return simple_read_from_buffer(buf, count, ppos, buffer, len);}static ssize_t proc_fault_inject_write(struct file * file,			const char __user * buf, size_t count, loff_t *ppos){	struct task_struct *task;	char buffer[PROC_NUMBUF], *end;	int make_it_fail;	if (!capable(CAP_SYS_RESOURCE))		return -EPERM;	memset(buffer, 0, sizeof(buffer));	if (count > sizeof(buffer) - 1)		count = sizeof(buffer) - 1;	if (copy_from_user(buffer, buf, count))		return -EFAULT;	make_it_fail = simple_strtol(buffer, &end, 0);	if (*end == '\n')		end++;	task = get_proc_task(file->f_dentry->d_inode);	if (!task)		return -ESRCH;	task->make_it_fail = make_it_fail;	put_task_struct(task);	if (end - buffer == 0)		return -EIO;	return end - buffer;}static const struct file_operations proc_fault_inject_operations = {	.read		= proc_fault_inject_read,	.write		= proc_fault_inject_write,};#endif#ifdef CONFIG_SCHED_DEBUG/* * Print out various scheduling related per-task fields: */static int sched_show(struct seq_file *m, void *v){	struct inode *inode = m->private;	struct task_struct *p;	WARN_ON(!inode);	p = get_proc_task(inode);	if (!p)		return -ESRCH;	proc_sched_show_task(p, m);	put_task_struct(p);	return 0;}static ssize_tsched_write(struct file *file, const char __user *buf,	    size_t count, loff_t *offset){	struct inode *inode = file->f_path.dentry->d_inode;	struct task_struct *p;	WARN_ON(!inode);	p = get_proc_task(inode);	if (!p)		return -ESRCH;	proc_sched_set_task(p);	put_task_struct(p);	return count;}static int sched_open(struct inode *inode, struct file *filp){	int ret;	ret = single_open(filp, sched_show, NULL);	if (!ret) {		struct seq_file *m = filp->private_data;		m->private = inode;	}	return ret;}static const struct file_operations proc_pid_sched_operations = {	.open		= sched_open,	.read		= seq_read,	.write		= sched_write,	.llseek		= seq_lseek,	.release	= single_release,};#endifstatic void *proc_pid_follow_link(struct dentry *dentry, struct nameidata *nd){	struct inode *inode = dentry->d_inode;	int error = -EACCES;	/* We don't need a base pointer in the /proc filesystem */	path_release(nd);	/* Are we allowed to snoop on the tasks file descriptors? */	if (!proc_fd_access_allowed(inode))		goto out;	error = PROC_I(inode)->op.proc_get_link(inode, &nd->dentry, &nd->mnt);	nd->last_type = LAST_BIND;out:	return ERR_PTR(error);}static int do_proc_readlink(struct dentry *dentry, struct vfsmount *mnt,

⌨️ 快捷键说明

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