📄 base.c
字号:
unsigned fd = *(unsigned *)ptr; struct inode *inode; struct proc_inode *ei; struct dentry *error = ERR_PTR(-ENOENT); inode = proc_pid_make_inode(dir->i_sb, task); if (!inode) goto out; ei = PROC_I(inode); ei->fd = fd; inode->i_mode = S_IFREG | S_IRUSR; inode->i_fop = &proc_fdinfo_file_operations; dentry->d_op = &tid_fd_dentry_operations; d_add(dentry, inode); /* Close the race of the process dying before we return the dentry */ if (tid_fd_revalidate(dentry, NULL)) error = NULL; out: return error;}static struct dentry *proc_lookupfdinfo(struct inode *dir, struct dentry *dentry, struct nameidata *nd){ return proc_lookupfd_common(dir, dentry, proc_fdinfo_instantiate);}static int proc_readfdinfo(struct file *filp, void *dirent, filldir_t filldir){ return proc_readfd_common(filp, dirent, filldir, proc_fdinfo_instantiate);}static const struct file_operations proc_fdinfo_operations = { .read = generic_read_dir, .readdir = proc_readfdinfo,};/* * proc directories can do almost nothing.. */static const struct inode_operations proc_fdinfo_inode_operations = { .lookup = proc_lookupfdinfo, .setattr = proc_setattr,};static struct dentry *proc_pident_instantiate(struct inode *dir, struct dentry *dentry, struct task_struct *task, const void *ptr){ const struct pid_entry *p = ptr; struct inode *inode; struct proc_inode *ei; struct dentry *error = ERR_PTR(-EINVAL); inode = proc_pid_make_inode(dir->i_sb, task); if (!inode) goto out; ei = PROC_I(inode); inode->i_mode = p->mode; if (S_ISDIR(inode->i_mode)) inode->i_nlink = 2; /* Use getattr to fix if necessary */ if (p->iop) inode->i_op = p->iop; if (p->fop) inode->i_fop = p->fop; ei->op = p->op; dentry->d_op = &pid_dentry_operations; d_add(dentry, inode); /* Close the race of the process dying before we return the dentry */ if (pid_revalidate(dentry, NULL)) error = NULL;out: return error;}static struct dentry *proc_pident_lookup(struct inode *dir, struct dentry *dentry, const struct pid_entry *ents, unsigned int nents){ struct inode *inode; struct dentry *error; struct task_struct *task = get_proc_task(dir); const struct pid_entry *p, *last; error = ERR_PTR(-ENOENT); inode = NULL; if (!task) goto out_no_task; /* * Yes, it does not scale. And it should not. Don't add * new entries into /proc/<tgid>/ without very good reasons. */ last = &ents[nents - 1]; for (p = ents; p <= last; p++) { if (p->len != dentry->d_name.len) continue; if (!memcmp(dentry->d_name.name, p->name, p->len)) break; } if (p > last) goto out; error = proc_pident_instantiate(dir, dentry, task, p);out: put_task_struct(task);out_no_task: return error;}static int proc_pident_fill_cache(struct file *filp, void *dirent, filldir_t filldir, struct task_struct *task, const struct pid_entry *p){ return proc_fill_cache(filp, dirent, filldir, p->name, p->len, proc_pident_instantiate, task, p);}static int proc_pident_readdir(struct file *filp, void *dirent, filldir_t filldir, const struct pid_entry *ents, unsigned int nents){ int i; struct dentry *dentry = filp->f_path.dentry; struct inode *inode = dentry->d_inode; struct task_struct *task = get_proc_task(inode); const struct pid_entry *p, *last; ino_t ino; int ret; ret = -ENOENT; if (!task) goto out_no_task; ret = 0; i = filp->f_pos; switch (i) { case 0: ino = inode->i_ino; if (filldir(dirent, ".", 1, i, ino, DT_DIR) < 0) goto out; i++; filp->f_pos++; /* fall through */ case 1: ino = parent_ino(dentry); if (filldir(dirent, "..", 2, i, ino, DT_DIR) < 0) goto out; i++; filp->f_pos++; /* fall through */ default: i -= 2; if (i >= nents) { ret = 1; goto out; } p = ents + i; last = &ents[nents - 1]; while (p <= last) { if (proc_pident_fill_cache(filp, dirent, filldir, task, p) < 0) goto out; filp->f_pos++; p++; } } ret = 1;out: put_task_struct(task);out_no_task: return ret;}#ifdef CONFIG_SECURITYstatic ssize_t proc_pid_attr_read(struct file * file, char __user * buf, size_t count, loff_t *ppos){ struct inode * inode = file->f_path.dentry->d_inode; char *p = NULL; ssize_t length; struct task_struct *task = get_proc_task(inode); if (!task) return -ESRCH; length = security_getprocattr(task, (char*)file->f_path.dentry->d_name.name, &p); put_task_struct(task); if (length > 0) length = simple_read_from_buffer(buf, count, ppos, p, length); kfree(p); return length;}static ssize_t proc_pid_attr_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; ssize_t length; struct task_struct *task = get_proc_task(inode); length = -ESRCH; if (!task) goto out_no_task; if (count > PAGE_SIZE) count = PAGE_SIZE; /* No partial writes. */ length = -EINVAL; if (*ppos != 0) goto out; length = -ENOMEM; page = (char*)__get_free_page(GFP_TEMPORARY); if (!page) goto out; length = -EFAULT; if (copy_from_user(page, buf, count)) goto out_free; length = security_setprocattr(task, (char*)file->f_path.dentry->d_name.name, (void*)page, count);out_free: free_page((unsigned long) page);out: put_task_struct(task);out_no_task: return length;}static const struct file_operations proc_pid_attr_operations = { .read = proc_pid_attr_read, .write = proc_pid_attr_write,};static const struct pid_entry attr_dir_stuff[] = { REG("current", S_IRUGO|S_IWUGO, pid_attr), REG("prev", S_IRUGO, pid_attr), REG("exec", S_IRUGO|S_IWUGO, pid_attr), REG("fscreate", S_IRUGO|S_IWUGO, pid_attr), REG("keycreate", S_IRUGO|S_IWUGO, pid_attr), REG("sockcreate", S_IRUGO|S_IWUGO, pid_attr),};static int proc_attr_dir_readdir(struct file * filp, void * dirent, filldir_t filldir){ return proc_pident_readdir(filp,dirent,filldir, attr_dir_stuff,ARRAY_SIZE(attr_dir_stuff));}static const struct file_operations proc_attr_dir_operations = { .read = generic_read_dir, .readdir = proc_attr_dir_readdir,};static struct dentry *proc_attr_dir_lookup(struct inode *dir, struct dentry *dentry, struct nameidata *nd){ return proc_pident_lookup(dir, dentry, attr_dir_stuff, ARRAY_SIZE(attr_dir_stuff));}static const struct inode_operations proc_attr_dir_inode_operations = { .lookup = proc_attr_dir_lookup, .getattr = pid_getattr, .setattr = proc_setattr,};#endif#if defined(USE_ELF_CORE_DUMP) && defined(CONFIG_ELF_CORE)static ssize_t proc_coredump_filter_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); struct mm_struct *mm; char buffer[PROC_NUMBUF]; size_t len; int ret; if (!task) return -ESRCH; ret = 0; mm = get_task_mm(task); if (mm) { len = snprintf(buffer, sizeof(buffer), "%08lx\n", ((mm->flags & MMF_DUMP_FILTER_MASK) >> MMF_DUMP_FILTER_SHIFT)); mmput(mm); ret = simple_read_from_buffer(buf, count, ppos, buffer, len); } put_task_struct(task); return ret;}static ssize_t proc_coredump_filter_write(struct file *file, const char __user *buf, size_t count, loff_t *ppos){ struct task_struct *task; struct mm_struct *mm; char buffer[PROC_NUMBUF], *end; unsigned int val; int ret; int i; unsigned long mask; ret = -EFAULT; memset(buffer, 0, sizeof(buffer)); if (count > sizeof(buffer) - 1) count = sizeof(buffer) - 1; if (copy_from_user(buffer, buf, count)) goto out_no_task; ret = -EINVAL; val = (unsigned int)simple_strtoul(buffer, &end, 0); if (*end == '\n') end++; if (end - buffer == 0) goto out_no_task; ret = -ESRCH; task = get_proc_task(file->f_dentry->d_inode); if (!task) goto out_no_task; ret = end - buffer; mm = get_task_mm(task); if (!mm) goto out_no_mm; for (i = 0, mask = 1; i < MMF_DUMP_FILTER_BITS; i++, mask <<= 1) { if (val & mask) set_bit(i + MMF_DUMP_FILTER_SHIFT, &mm->flags); else clear_bit(i + MMF_DUMP_FILTER_SHIFT, &mm->flags); } mmput(mm); out_no_mm: put_task_struct(task); out_no_task: return ret;}static const struct file_operations proc_coredump_filter_operations = { .read = proc_coredump_filter_read, .write = proc_coredump_filter_write,};#endif/* * /proc/self: */static int proc_self_readlink(struct dentry *dentry, char __user *buffer, int buflen){ char tmp[PROC_NUMBUF]; sprintf(tmp, "%d", task_tgid_vnr(current)); return vfs_readlink(dentry,buffer,buflen,tmp);}static void *proc_self_follow_link(struct dentry *dentry, struct nameidata *nd){ char tmp[PROC_NUMBUF]; sprintf(tmp, "%d", task_tgid_vnr(current)); return ERR_PTR(vfs_follow_link(nd,tmp));}static const struct inode_operations proc_self_inode_operations = { .readlink = proc_self_readlink, .follow_link = proc_self_follow_link,};/* * proc base * * These are the directory entries in the root directory of /proc * that properly belong to the /proc filesystem, as they describe * describe something that is process related. */static const struct pid_entry proc_base_stuff[] = { NOD("self", S_IFLNK|S_IRWXUGO, &proc_self_inode_operations, NULL, {}),};/* * Exceptional case: normally we are not allowed to unhash a busy * directory. In this case, however, we can do it - no aliasing problems * due to the way we treat inodes. */static int proc_base_revalidate(struct dentry *dentry, struct nameidata *nd){ struct inode *inode = dentry->d_inode; struct task_struct *task = get_proc_task(inode); if (task) { put_task_struct(task); return 1; } d_drop(dentry); return 0;}static struct dentry_operations proc_base_dentry_operations ={ .d_revalidate = proc_base_revalidate, .d_delete = pid_delete_dentry,};static struct dentry *proc_base_instantiate(struct inode *dir, struct dentry *dentry, struct task_struct *task, const void *ptr){ const struct pid_entry *p = ptr; struct inode *inode; struct proc_inode *ei; struct dentry *error = ERR_PTR(-EINVAL); /* Allocate the inode */ error = ERR_PTR(-ENOMEM); inode = new_inode(dir->i_sb); if (!inode) goto out; /* Initialize the inode */ ei = PROC_I(inode); inode->i_mtime = inode->i_atime = inode->i_ctime = CURRENT_TIME; /* * grab the reference to the task. */ ei->pid = get_task_pid(task, PIDTYPE_PID); if (!ei->pid) goto out_iput; inode->i_uid = 0; inode->i_gid = 0; inode->i_mode = p->mode; if (S_ISDIR(inode->i_mode)) inode->i_nlink = 2; if (S_ISLNK(inode->i_mode)) inode->i_size = 64; if (p->iop) inode->i_op = p->iop; if (p->fop) inode->i_fop = p->fop; ei->op = p->op; dentry->d_op = &proc_base_dentry_operations; d_add(dentry, inode); error = NULL;out: return error;out_iput: iput(inode); goto out;}static struct dentry *proc_base_lookup(struct inode *dir, struct dentry *dentry){ struct dentry *error; struct task_struct *task = get_proc_task(dir); const struct pid_entry *p, *last; error = ERR_PTR(-ENOENT); if (!task) goto out_no_task; /* Lookup the directory entry */ last = &proc_base_stuff[ARRAY_SIZE(proc_base_stuff) - 1]; for (p = proc_base_stuff; p <= last; p++) { if (p->len != dentry->d_name.len) continue; if (!memcmp(dentry->d_name.name, p->name, p->len)) break; } if (p > last) goto out; error = proc_base_instantiate(dir, dentry, task, p);out: put_task_struct(task);out_no_task: return error;}static int proc_base_fill_cache(struct file *filp, void *dirent, filldir_t filldir, struct task_struct *task, const struct pid_entry *p){ return proc_fill_cache(filp, dirent, filldir, p->name, p->len, proc_base_instantiate, task, p);}#ifdef CONFIG_TASK_IO_ACCOUNTINGstatic int proc_pid_io_accounting(struct task_struct *task, char *buffer){ return sprintf(buffer,#ifdef CONFIG_TASK_XACCT "rchar: %llu\n" "wchar: %llu\n" "syscr: %llu\n" "syscw: %llu\n"#endif "read_bytes: %llu\n" "write_bytes: %llu\n" "cancelled_write_bytes: %llu\n",#ifdef CONFIG_TASK_XACCT (unsigned long long)task->rchar, (unsigned long long)task->wchar, (unsigned long long)task->syscr, (unsigned long long)task->syscw,#endif (unsigned long long)task->ioac.read_bytes, (unsigned long long)task->ioac.write_bytes, (unsigned long long)task->ioac.cancelled_write_bytes);}#endif/* * Thread groups */static const struct file_operations proc_task_operations;static const struct inode_operations proc_task_inode_operations;static const struct pid_entry tgid_base_stuff[] = { DIR("task", S_IRUGO|S_IXUGO, task), DIR("fd", S_IRUSR|S_IXUSR, fd), DIR("fdinfo", S_IRUSR|S_IXUSR, fdinfo), REG("environ", S_IRUSR, environ), INF("auxv", S_IRUSR, pid_auxv), INF("status", S_IRUGO, pid_status), INF("limits", S_IRUSR, pid_limits),#ifdef CONFIG_SCHED_DEBUG REG("sched", S_IRUGO|S_IWUSR, pid_sched),#endif INF("cmdline", S_IRUGO, pid_cmdline), INF("stat", S_IRUGO, tgid_stat),
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -