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

📄 base.c

📁 linux 内核源代码
💻 C
📖 第 1 页 / 共 5 页
字号:
/* *  linux/fs/proc/base.c * *  Copyright (C) 1991, 1992 Linus Torvalds * *  proc base directory handling functions * *  1999, Al Viro. Rewritten. Now it covers the whole per-process part. *  Instead of using magical inumbers to determine the kind of object *  we allocate and fill in-core inodes upon lookup. They don't even *  go into icache. We cache the reference to task_struct upon lookup too. *  Eventually it should become a filesystem in its own. We don't use the *  rest of procfs anymore. * * *  Changelog: *  17-Jan-2005 *  Allan Bezerra *  Bruna Moreira <bruna.moreira@indt.org.br> *  Edjard Mota <edjard.mota@indt.org.br> *  Ilias Biris <ilias.biris@indt.org.br> *  Mauricio Lin <mauricio.lin@indt.org.br> * *  Embedded Linux Lab - 10LE Instituto Nokia de Tecnologia - INdT * *  A new process specific entry (smaps) included in /proc. It shows the *  size of rss for each memory area. The maps entry lacks information *  about physical memory size (rss) for each mapped file, i.e., *  rss information for executables and library files. *  This additional information is useful for any tools that need to know *  about physical memory consumption for a process specific library. * *  Changelog: *  21-Feb-2005 *  Embedded Linux Lab - 10LE Instituto Nokia de Tecnologia - INdT *  Pud inclusion in the page table walking. * *  ChangeLog: *  10-Mar-2005 *  10LE Instituto Nokia de Tecnologia - INdT: *  A better way to walks through the page table as suggested by Hugh Dickins. * *  Simo Piiroinen <simo.piiroinen@nokia.com>: *  Smaps information related to shared, private, clean and dirty pages. * *  Paul Mundt <paul.mundt@nokia.com>: *  Overall revision about smaps. */#include <asm/uaccess.h>#include <linux/errno.h>#include <linux/time.h>#include <linux/proc_fs.h>#include <linux/stat.h>#include <linux/init.h>#include <linux/capability.h>#include <linux/file.h>#include <linux/string.h>#include <linux/seq_file.h>#include <linux/namei.h>#include <linux/mnt_namespace.h>#include <linux/mm.h>#include <linux/rcupdate.h>#include <linux/kallsyms.h>#include <linux/resource.h>#include <linux/module.h>#include <linux/mount.h>#include <linux/security.h>#include <linux/ptrace.h>#include <linux/cgroup.h>#include <linux/cpuset.h>#include <linux/audit.h>#include <linux/poll.h>#include <linux/nsproxy.h>#include <linux/oom.h>#include <linux/elf.h>#include <linux/pid_namespace.h>#include "internal.h"/* NOTE: *	Implementing inode permission operations in /proc is almost *	certainly an error.  Permission checks need to happen during *	each system call not at open time.  The reason is that most of *	what we wish to check for permissions in /proc varies at runtime. * *	The classic example of a problem is opening file descriptors *	in /proc for a task before it execs a suid executable. *//* Worst case buffer size needed for holding an integer. */#define PROC_NUMBUF 13struct pid_entry {	char *name;	int len;	mode_t mode;	const struct inode_operations *iop;	const struct file_operations *fop;	union proc_op op;};#define NOD(NAME, MODE, IOP, FOP, OP) {			\	.name = (NAME),					\	.len  = sizeof(NAME) - 1,			\	.mode = MODE,					\	.iop  = IOP,					\	.fop  = FOP,					\	.op   = OP,					\}#define DIR(NAME, MODE, OTYPE)							\	NOD(NAME, (S_IFDIR|(MODE)),						\		&proc_##OTYPE##_inode_operations, &proc_##OTYPE##_operations,	\		{} )#define LNK(NAME, OTYPE)					\	NOD(NAME, (S_IFLNK|S_IRWXUGO),				\		&proc_pid_link_inode_operations, NULL,		\		{ .proc_get_link = &proc_##OTYPE##_link } )#define REG(NAME, MODE, OTYPE)				\	NOD(NAME, (S_IFREG|(MODE)), NULL,		\		&proc_##OTYPE##_operations, {})#define INF(NAME, MODE, OTYPE)				\	NOD(NAME, (S_IFREG|(MODE)), 			\		NULL, &proc_info_file_operations,	\		{ .proc_read = &proc_##OTYPE } )int maps_protect;EXPORT_SYMBOL(maps_protect);static struct fs_struct *get_fs_struct(struct task_struct *task){	struct fs_struct *fs;	task_lock(task);	fs = task->fs;	if(fs)		atomic_inc(&fs->count);	task_unlock(task);	return fs;}static int get_nr_threads(struct task_struct *tsk){	/* Must be called with the rcu_read_lock held */	unsigned long flags;	int count = 0;	if (lock_task_sighand(tsk, &flags)) {		count = atomic_read(&tsk->signal->count);		unlock_task_sighand(tsk, &flags);	}	return count;}static int proc_cwd_link(struct inode *inode, struct dentry **dentry, struct vfsmount **mnt){	struct task_struct *task = get_proc_task(inode);	struct fs_struct *fs = NULL;	int result = -ENOENT;	if (task) {		fs = get_fs_struct(task);		put_task_struct(task);	}	if (fs) {		read_lock(&fs->lock);		*mnt = mntget(fs->pwdmnt);		*dentry = dget(fs->pwd);		read_unlock(&fs->lock);		result = 0;		put_fs_struct(fs);	}	return result;}static int proc_root_link(struct inode *inode, struct dentry **dentry, struct vfsmount **mnt){	struct task_struct *task = get_proc_task(inode);	struct fs_struct *fs = NULL;	int result = -ENOENT;	if (task) {		fs = get_fs_struct(task);		put_task_struct(task);	}	if (fs) {		read_lock(&fs->lock);		*mnt = mntget(fs->rootmnt);		*dentry = dget(fs->root);		read_unlock(&fs->lock);		result = 0;		put_fs_struct(fs);	}	return result;}#define MAY_PTRACE(task) \	(task == current || \	(task->parent == current && \	(task->ptrace & PT_PTRACED) && \	 (task->state == TASK_STOPPED || task->state == TASK_TRACED) && \	 security_ptrace(current,task) == 0))struct mm_struct *mm_for_maps(struct task_struct *task){	struct mm_struct *mm = get_task_mm(task);	if (!mm)		return NULL;	down_read(&mm->mmap_sem);	task_lock(task);	if (task->mm != mm)		goto out;	if (task->mm != current->mm && __ptrace_may_attach(task) < 0)		goto out;	task_unlock(task);	return mm;out:	task_unlock(task);	up_read(&mm->mmap_sem);	mmput(mm);	return NULL;}static int proc_pid_cmdline(struct task_struct *task, char * buffer){	int res = 0;	unsigned int len;	struct mm_struct *mm = get_task_mm(task);	if (!mm)		goto out;	if (!mm->arg_end)		goto out_mm;	/* Shh! No looking before we're done */ 	len = mm->arg_end - mm->arg_start; 	if (len > PAGE_SIZE)		len = PAGE_SIZE; 	res = access_process_vm(task, mm->arg_start, buffer, len, 0);	// If the nul at the end of args has been overwritten, then	// assume application is using setproctitle(3).	if (res > 0 && buffer[res-1] != '\0' && len < PAGE_SIZE) {		len = strnlen(buffer, res);		if (len < res) {		    res = len;		} else {			len = mm->env_end - mm->env_start;			if (len > PAGE_SIZE - res)				len = PAGE_SIZE - res;			res += access_process_vm(task, mm->env_start, buffer+res, len, 0);			res = strnlen(buffer, res);		}	}out_mm:	mmput(mm);out:	return res;}static int proc_pid_auxv(struct task_struct *task, char *buffer){	int res = 0;	struct mm_struct *mm = get_task_mm(task);	if (mm) {		unsigned int nwords = 0;		do			nwords += 2;		while (mm->saved_auxv[nwords - 2] != 0); /* AT_NULL */		res = nwords * sizeof(mm->saved_auxv[0]);		if (res > PAGE_SIZE)			res = PAGE_SIZE;		memcpy(buffer, mm->saved_auxv, res);		mmput(mm);	}	return res;}#ifdef CONFIG_KALLSYMS/* * Provides a wchan file via kallsyms in a proper one-value-per-file format. * Returns the resolved symbol.  If that fails, simply return the address. */static int proc_pid_wchan(struct task_struct *task, char *buffer){	unsigned long wchan;	char symname[KSYM_NAME_LEN];	wchan = get_wchan(task);	if (lookup_symbol_name(wchan, symname) < 0)		return sprintf(buffer, "%lu", wchan);	else		return sprintf(buffer, "%s", symname);}#endif /* CONFIG_KALLSYMS */#ifdef CONFIG_SCHEDSTATS/* * Provides /proc/PID/schedstat */static int proc_pid_schedstat(struct task_struct *task, char *buffer){	return sprintf(buffer, "%llu %llu %lu\n",			task->sched_info.cpu_time,			task->sched_info.run_delay,			task->sched_info.pcount);}#endif/* The badness from the OOM killer */unsigned long badness(struct task_struct *p, unsigned long uptime);static int proc_oom_score(struct task_struct *task, char *buffer){	unsigned long points;	struct timespec uptime;	do_posix_clock_monotonic_gettime(&uptime);	read_lock(&tasklist_lock);	points = badness(task, uptime.tv_sec);	read_unlock(&tasklist_lock);	return sprintf(buffer, "%lu\n", points);}struct limit_names {	char *name;	char *unit;};static const struct limit_names lnames[RLIM_NLIMITS] = {	[RLIMIT_CPU] = {"Max cpu time", "ms"},	[RLIMIT_FSIZE] = {"Max file size", "bytes"},	[RLIMIT_DATA] = {"Max data size", "bytes"},	[RLIMIT_STACK] = {"Max stack size", "bytes"},	[RLIMIT_CORE] = {"Max core file size", "bytes"},	[RLIMIT_RSS] = {"Max resident set", "bytes"},	[RLIMIT_NPROC] = {"Max processes", "processes"},	[RLIMIT_NOFILE] = {"Max open files", "files"},	[RLIMIT_MEMLOCK] = {"Max locked memory", "bytes"},	[RLIMIT_AS] = {"Max address space", "bytes"},	[RLIMIT_LOCKS] = {"Max file locks", "locks"},	[RLIMIT_SIGPENDING] = {"Max pending signals", "signals"},	[RLIMIT_MSGQUEUE] = {"Max msgqueue size", "bytes"},	[RLIMIT_NICE] = {"Max nice priority", NULL},	[RLIMIT_RTPRIO] = {"Max realtime priority", NULL},};/* Display limits for a process */static int proc_pid_limits(struct task_struct *task, char *buffer){	unsigned int i;	int count = 0;	unsigned long flags;	char *bufptr = buffer;	struct rlimit rlim[RLIM_NLIMITS];	rcu_read_lock();	if (!lock_task_sighand(task,&flags)) {		rcu_read_unlock();		return 0;	}	memcpy(rlim, task->signal->rlim, sizeof(struct rlimit) * RLIM_NLIMITS);	unlock_task_sighand(task, &flags);	rcu_read_unlock();	/*	 * print the file header	 */	count += sprintf(&bufptr[count], "%-25s %-20s %-20s %-10s\n",			"Limit", "Soft Limit", "Hard Limit", "Units");	for (i = 0; i < RLIM_NLIMITS; i++) {		if (rlim[i].rlim_cur == RLIM_INFINITY)			count += sprintf(&bufptr[count], "%-25s %-20s ",					 lnames[i].name, "unlimited");		else			count += sprintf(&bufptr[count], "%-25s %-20lu ",					 lnames[i].name, rlim[i].rlim_cur);		if (rlim[i].rlim_max == RLIM_INFINITY)			count += sprintf(&bufptr[count], "%-20s ", "unlimited");		else			count += sprintf(&bufptr[count], "%-20lu ",					 rlim[i].rlim_max);		if (lnames[i].unit)			count += sprintf(&bufptr[count], "%-10s\n",					 lnames[i].unit);		else			count += sprintf(&bufptr[count], "\n");	}	return count;}/************************************************************************//*                       Here the fs part begins                        *//************************************************************************//* permission checks */static int proc_fd_access_allowed(struct inode *inode){	struct task_struct *task;	int allowed = 0;	/* Allow access to a task's file descriptors if it is us or we	 * may use ptrace attach to the process and find out that	 * information.	 */	task = get_proc_task(inode);	if (task) {		allowed = ptrace_may_attach(task);		put_task_struct(task);	}	return allowed;}static int proc_setattr(struct dentry *dentry, struct iattr *attr){	int error;	struct inode *inode = dentry->d_inode;	if (attr->ia_valid & ATTR_MODE)		return -EPERM;	error = inode_change_ok(inode, attr);	if (!error)		error = inode_setattr(inode, attr);	return error;}static const struct inode_operations proc_def_inode_operations = {	.setattr	= proc_setattr,};extern struct seq_operations mounts_op;struct proc_mounts {	struct seq_file m;	int event;};static int mounts_open(struct inode *inode, struct file *file){	struct task_struct *task = get_proc_task(inode);	struct nsproxy *nsp;	struct mnt_namespace *ns = NULL;	struct proc_mounts *p;	int ret = -EINVAL;	if (task) {		rcu_read_lock();		nsp = task_nsproxy(task);		if (nsp) {			ns = nsp->mnt_ns;			if (ns)				get_mnt_ns(ns);		}		rcu_read_unlock();		put_task_struct(task);	}	if (ns) {		ret = -ENOMEM;		p = kmalloc(sizeof(struct proc_mounts), GFP_KERNEL);		if (p) {			file->private_data = &p->m;			ret = seq_open(file, &mounts_op);			if (!ret) {				p->m.private = ns;				p->event = ns->event;				return 0;			}			kfree(p);		}		put_mnt_ns(ns);	}	return ret;}static int mounts_release(struct inode *inode, struct file *file){	struct seq_file *m = file->private_data;	struct mnt_namespace *ns = m->private;	put_mnt_ns(ns);	return seq_release(inode, file);}static unsigned mounts_poll(struct file *file, poll_table *wait){	struct proc_mounts *p = file->private_data;	struct mnt_namespace *ns = p->m.private;	unsigned res = 0;	poll_wait(file, &ns->poll, wait);	spin_lock(&vfsmount_lock);	if (p->event != ns->event) {		p->event = ns->event;		res = POLLERR;	}	spin_unlock(&vfsmount_lock);	return res;}static const struct file_operations proc_mounts_operations = {	.open		= mounts_open,	.read		= seq_read,	.llseek		= seq_lseek,	.release	= mounts_release,	.poll		= mounts_poll,};extern struct seq_operations mountstats_op;static int mountstats_open(struct inode *inode, struct file *file){	int ret = seq_open(file, &mountstats_op);	if (!ret) {		struct seq_file *m = file->private_data;		struct nsproxy *nsp;		struct mnt_namespace *mnt_ns = NULL;		struct task_struct *task = get_proc_task(inode);		if (task) {			rcu_read_lock();			nsp = task_nsproxy(task);			if (nsp) {				mnt_ns = nsp->mnt_ns;				if (mnt_ns)					get_mnt_ns(mnt_ns);			}			rcu_read_unlock();			put_task_struct(task);		}		if (mnt_ns)			m->private = mnt_ns;		else {			seq_release(inode, file);			ret = -EINVAL;		}	}	return ret;}static const struct file_operations proc_mountstats_operations = {	.open		= mountstats_open,

⌨️ 快捷键说明

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