📄 base.c
字号:
.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 + -