diff options
Diffstat (limited to 'fs/proc/base.c')
| -rw-r--r-- | fs/proc/base.c | 122 |
1 files changed, 43 insertions, 79 deletions
diff --git a/fs/proc/base.c b/fs/proc/base.c index 08cba2c3b61..d49c4b5d2c3 100644 --- a/fs/proc/base.c +++ b/fs/proc/base.c | |||
| @@ -373,26 +373,20 @@ static int lstats_show_proc(struct seq_file *m, void *v) | |||
| 373 | return -ESRCH; | 373 | return -ESRCH; |
| 374 | seq_puts(m, "Latency Top version : v0.1\n"); | 374 | seq_puts(m, "Latency Top version : v0.1\n"); |
| 375 | for (i = 0; i < 32; i++) { | 375 | for (i = 0; i < 32; i++) { |
| 376 | if (task->latency_record[i].backtrace[0]) { | 376 | struct latency_record *lr = &task->latency_record[i]; |
| 377 | if (lr->backtrace[0]) { | ||
| 377 | int q; | 378 | int q; |
| 378 | seq_printf(m, "%i %li %li ", | 379 | seq_printf(m, "%i %li %li", |
| 379 | task->latency_record[i].count, | 380 | lr->count, lr->time, lr->max); |
| 380 | task->latency_record[i].time, | ||
| 381 | task->latency_record[i].max); | ||
| 382 | for (q = 0; q < LT_BACKTRACEDEPTH; q++) { | 381 | for (q = 0; q < LT_BACKTRACEDEPTH; q++) { |
| 383 | char sym[KSYM_SYMBOL_LEN]; | 382 | unsigned long bt = lr->backtrace[q]; |
| 384 | char *c; | 383 | if (!bt) |
| 385 | if (!task->latency_record[i].backtrace[q]) | ||
| 386 | break; | 384 | break; |
| 387 | if (task->latency_record[i].backtrace[q] == ULONG_MAX) | 385 | if (bt == ULONG_MAX) |
| 388 | break; | 386 | break; |
| 389 | sprint_symbol(sym, task->latency_record[i].backtrace[q]); | 387 | seq_printf(m, " %ps", (void *)bt); |
| 390 | c = strchr(sym, '+'); | ||
| 391 | if (c) | ||
| 392 | *c = 0; | ||
| 393 | seq_printf(m, "%s ", sym); | ||
| 394 | } | 388 | } |
| 395 | seq_printf(m, "\n"); | 389 | seq_putc(m, '\n'); |
| 396 | } | 390 | } |
| 397 | 391 | ||
| 398 | } | 392 | } |
| @@ -751,14 +745,7 @@ static int proc_single_show(struct seq_file *m, void *v) | |||
| 751 | 745 | ||
| 752 | static int proc_single_open(struct inode *inode, struct file *filp) | 746 | static int proc_single_open(struct inode *inode, struct file *filp) |
| 753 | { | 747 | { |
| 754 | int ret; | 748 | return single_open(filp, proc_single_show, inode); |
| 755 | ret = single_open(filp, proc_single_show, NULL); | ||
| 756 | if (!ret) { | ||
| 757 | struct seq_file *m = filp->private_data; | ||
| 758 | |||
| 759 | m->private = inode; | ||
| 760 | } | ||
| 761 | return ret; | ||
| 762 | } | 749 | } |
| 763 | 750 | ||
| 764 | static const struct file_operations proc_single_file_operations = { | 751 | static const struct file_operations proc_single_file_operations = { |
| @@ -1164,7 +1151,7 @@ static ssize_t oom_score_adj_write(struct file *file, const char __user *buf, | |||
| 1164 | goto err_task_lock; | 1151 | goto err_task_lock; |
| 1165 | } | 1152 | } |
| 1166 | 1153 | ||
| 1167 | if (oom_score_adj < task->signal->oom_score_adj && | 1154 | if (oom_score_adj < task->signal->oom_score_adj_min && |
| 1168 | !capable(CAP_SYS_RESOURCE)) { | 1155 | !capable(CAP_SYS_RESOURCE)) { |
| 1169 | err = -EACCES; | 1156 | err = -EACCES; |
| 1170 | goto err_sighand; | 1157 | goto err_sighand; |
| @@ -1177,6 +1164,8 @@ static ssize_t oom_score_adj_write(struct file *file, const char __user *buf, | |||
| 1177 | atomic_dec(&task->mm->oom_disable_count); | 1164 | atomic_dec(&task->mm->oom_disable_count); |
| 1178 | } | 1165 | } |
| 1179 | task->signal->oom_score_adj = oom_score_adj; | 1166 | task->signal->oom_score_adj = oom_score_adj; |
| 1167 | if (has_capability_noaudit(current, CAP_SYS_RESOURCE)) | ||
| 1168 | task->signal->oom_score_adj_min = oom_score_adj; | ||
| 1180 | /* | 1169 | /* |
| 1181 | * Scale /proc/pid/oom_adj appropriately ensuring that OOM_DISABLE is | 1170 | * Scale /proc/pid/oom_adj appropriately ensuring that OOM_DISABLE is |
| 1182 | * always attainable. | 1171 | * always attainable. |
| @@ -1386,15 +1375,7 @@ sched_write(struct file *file, const char __user *buf, | |||
| 1386 | 1375 | ||
| 1387 | static int sched_open(struct inode *inode, struct file *filp) | 1376 | static int sched_open(struct inode *inode, struct file *filp) |
| 1388 | { | 1377 | { |
| 1389 | int ret; | 1378 | return single_open(filp, sched_show, inode); |
| 1390 | |||
| 1391 | ret = single_open(filp, sched_show, NULL); | ||
| 1392 | if (!ret) { | ||
| 1393 | struct seq_file *m = filp->private_data; | ||
| 1394 | |||
| 1395 | m->private = inode; | ||
| 1396 | } | ||
| 1397 | return ret; | ||
| 1398 | } | 1379 | } |
| 1399 | 1380 | ||
| 1400 | static const struct file_operations proc_pid_sched_operations = { | 1381 | static const struct file_operations proc_pid_sched_operations = { |
| @@ -1530,15 +1511,7 @@ static int comm_show(struct seq_file *m, void *v) | |||
| 1530 | 1511 | ||
| 1531 | static int comm_open(struct inode *inode, struct file *filp) | 1512 | static int comm_open(struct inode *inode, struct file *filp) |
| 1532 | { | 1513 | { |
| 1533 | int ret; | 1514 | return single_open(filp, comm_show, inode); |
| 1534 | |||
| 1535 | ret = single_open(filp, comm_show, NULL); | ||
| 1536 | if (!ret) { | ||
| 1537 | struct seq_file *m = filp->private_data; | ||
| 1538 | |||
| 1539 | m->private = inode; | ||
| 1540 | } | ||
| 1541 | return ret; | ||
| 1542 | } | 1515 | } |
| 1543 | 1516 | ||
| 1544 | static const struct file_operations proc_pid_set_comm_operations = { | 1517 | static const struct file_operations proc_pid_set_comm_operations = { |
| @@ -1795,10 +1768,16 @@ static int pid_getattr(struct vfsmount *mnt, struct dentry *dentry, struct kstat | |||
| 1795 | */ | 1768 | */ |
| 1796 | static int pid_revalidate(struct dentry *dentry, struct nameidata *nd) | 1769 | static int pid_revalidate(struct dentry *dentry, struct nameidata *nd) |
| 1797 | { | 1770 | { |
| 1798 | struct inode *inode = dentry->d_inode; | 1771 | struct inode *inode; |
| 1799 | struct task_struct *task = get_proc_task(inode); | 1772 | struct task_struct *task; |
| 1800 | const struct cred *cred; | 1773 | const struct cred *cred; |
| 1801 | 1774 | ||
| 1775 | if (nd && nd->flags & LOOKUP_RCU) | ||
| 1776 | return -ECHILD; | ||
| 1777 | |||
| 1778 | inode = dentry->d_inode; | ||
| 1779 | task = get_proc_task(inode); | ||
| 1780 | |||
| 1802 | if (task) { | 1781 | if (task) { |
| 1803 | if ((inode->i_mode == (S_IFDIR|S_IRUGO|S_IXUGO)) || | 1782 | if ((inode->i_mode == (S_IFDIR|S_IRUGO|S_IXUGO)) || |
| 1804 | task_dumpable(task)) { | 1783 | task_dumpable(task)) { |
| @@ -1820,7 +1799,7 @@ static int pid_revalidate(struct dentry *dentry, struct nameidata *nd) | |||
| 1820 | return 0; | 1799 | return 0; |
| 1821 | } | 1800 | } |
| 1822 | 1801 | ||
| 1823 | static int pid_delete_dentry(struct dentry * dentry) | 1802 | static int pid_delete_dentry(const struct dentry * dentry) |
| 1824 | { | 1803 | { |
| 1825 | /* Is the task we represent dead? | 1804 | /* Is the task we represent dead? |
| 1826 | * If so, then don't put the dentry on the lru list, | 1805 | * If so, then don't put the dentry on the lru list, |
| @@ -1964,12 +1943,19 @@ static int proc_fd_link(struct inode *inode, struct path *path) | |||
| 1964 | 1943 | ||
| 1965 | static int tid_fd_revalidate(struct dentry *dentry, struct nameidata *nd) | 1944 | static int tid_fd_revalidate(struct dentry *dentry, struct nameidata *nd) |
| 1966 | { | 1945 | { |
| 1967 | struct inode *inode = dentry->d_inode; | 1946 | struct inode *inode; |
| 1968 | struct task_struct *task = get_proc_task(inode); | 1947 | struct task_struct *task; |
| 1969 | int fd = proc_fd(inode); | 1948 | int fd; |
| 1970 | struct files_struct *files; | 1949 | struct files_struct *files; |
| 1971 | const struct cred *cred; | 1950 | const struct cred *cred; |
| 1972 | 1951 | ||
| 1952 | if (nd && nd->flags & LOOKUP_RCU) | ||
| 1953 | return -ECHILD; | ||
| 1954 | |||
| 1955 | inode = dentry->d_inode; | ||
| 1956 | task = get_proc_task(inode); | ||
| 1957 | fd = proc_fd(inode); | ||
| 1958 | |||
| 1973 | if (task) { | 1959 | if (task) { |
| 1974 | files = get_files_struct(task); | 1960 | files = get_files_struct(task); |
| 1975 | if (files) { | 1961 | if (files) { |
| @@ -2045,7 +2031,7 @@ static struct dentry *proc_fd_instantiate(struct inode *dir, | |||
| 2045 | inode->i_op = &proc_pid_link_inode_operations; | 2031 | inode->i_op = &proc_pid_link_inode_operations; |
| 2046 | inode->i_size = 64; | 2032 | inode->i_size = 64; |
| 2047 | ei->op.proc_get_link = proc_fd_link; | 2033 | ei->op.proc_get_link = proc_fd_link; |
| 2048 | dentry->d_op = &tid_fd_dentry_operations; | 2034 | d_set_d_op(dentry, &tid_fd_dentry_operations); |
| 2049 | d_add(dentry, inode); | 2035 | d_add(dentry, inode); |
| 2050 | /* Close the race of the process dying before we return the dentry */ | 2036 | /* Close the race of the process dying before we return the dentry */ |
| 2051 | if (tid_fd_revalidate(dentry, NULL)) | 2037 | if (tid_fd_revalidate(dentry, NULL)) |
| @@ -2177,11 +2163,13 @@ static const struct file_operations proc_fd_operations = { | |||
| 2177 | * /proc/pid/fd needs a special permission handler so that a process can still | 2163 | * /proc/pid/fd needs a special permission handler so that a process can still |
| 2178 | * access /proc/self/fd after it has executed a setuid(). | 2164 | * access /proc/self/fd after it has executed a setuid(). |
| 2179 | */ | 2165 | */ |
| 2180 | static int proc_fd_permission(struct inode *inode, int mask) | 2166 | static int proc_fd_permission(struct inode *inode, int mask, unsigned int flags) |
| 2181 | { | 2167 | { |
| 2182 | int rv; | 2168 | int rv; |
| 2183 | 2169 | ||
| 2184 | rv = generic_permission(inode, mask, NULL); | 2170 | if (flags & IPERM_FLAG_RCU) |
| 2171 | return -ECHILD; | ||
| 2172 | rv = generic_permission(inode, mask, flags, NULL); | ||
| 2185 | if (rv == 0) | 2173 | if (rv == 0) |
| 2186 | return 0; | 2174 | return 0; |
| 2187 | if (task_pid(current) == proc_pid(inode)) | 2175 | if (task_pid(current) == proc_pid(inode)) |
| @@ -2213,7 +2201,7 @@ static struct dentry *proc_fdinfo_instantiate(struct inode *dir, | |||
| 2213 | ei->fd = fd; | 2201 | ei->fd = fd; |
| 2214 | inode->i_mode = S_IFREG | S_IRUSR; | 2202 | inode->i_mode = S_IFREG | S_IRUSR; |
| 2215 | inode->i_fop = &proc_fdinfo_file_operations; | 2203 | inode->i_fop = &proc_fdinfo_file_operations; |
| 2216 | dentry->d_op = &tid_fd_dentry_operations; | 2204 | d_set_d_op(dentry, &tid_fd_dentry_operations); |
| 2217 | d_add(dentry, inode); | 2205 | d_add(dentry, inode); |
| 2218 | /* Close the race of the process dying before we return the dentry */ | 2206 | /* Close the race of the process dying before we return the dentry */ |
| 2219 | if (tid_fd_revalidate(dentry, NULL)) | 2207 | if (tid_fd_revalidate(dentry, NULL)) |
| @@ -2272,7 +2260,7 @@ static struct dentry *proc_pident_instantiate(struct inode *dir, | |||
| 2272 | if (p->fop) | 2260 | if (p->fop) |
| 2273 | inode->i_fop = p->fop; | 2261 | inode->i_fop = p->fop; |
| 2274 | ei->op = p->op; | 2262 | ei->op = p->op; |
| 2275 | dentry->d_op = &pid_dentry_operations; | 2263 | d_set_d_op(dentry, &pid_dentry_operations); |
| 2276 | d_add(dentry, inode); | 2264 | d_add(dentry, inode); |
| 2277 | /* Close the race of the process dying before we return the dentry */ | 2265 | /* Close the race of the process dying before we return the dentry */ |
| 2278 | if (pid_revalidate(dentry, NULL)) | 2266 | if (pid_revalidate(dentry, NULL)) |
| @@ -2632,29 +2620,6 @@ static const struct pid_entry proc_base_stuff[] = { | |||
| 2632 | &proc_self_inode_operations, NULL, {}), | 2620 | &proc_self_inode_operations, NULL, {}), |
| 2633 | }; | 2621 | }; |
| 2634 | 2622 | ||
| 2635 | /* | ||
| 2636 | * Exceptional case: normally we are not allowed to unhash a busy | ||
| 2637 | * directory. In this case, however, we can do it - no aliasing problems | ||
| 2638 | * due to the way we treat inodes. | ||
| 2639 | */ | ||
| 2640 | static int proc_base_revalidate(struct dentry *dentry, struct nameidata *nd) | ||
| 2641 | { | ||
| 2642 | struct inode *inode = dentry->d_inode; | ||
| 2643 | struct task_struct *task = get_proc_task(inode); | ||
| 2644 | if (task) { | ||
| 2645 | put_task_struct(task); | ||
| 2646 | return 1; | ||
| 2647 | } | ||
| 2648 | d_drop(dentry); | ||
| 2649 | return 0; | ||
| 2650 | } | ||
| 2651 | |||
| 2652 | static const struct dentry_operations proc_base_dentry_operations = | ||
| 2653 | { | ||
| 2654 | .d_revalidate = proc_base_revalidate, | ||
| 2655 | .d_delete = pid_delete_dentry, | ||
| 2656 | }; | ||
| 2657 | |||
| 2658 | static struct dentry *proc_base_instantiate(struct inode *dir, | 2623 | static struct dentry *proc_base_instantiate(struct inode *dir, |
| 2659 | struct dentry *dentry, struct task_struct *task, const void *ptr) | 2624 | struct dentry *dentry, struct task_struct *task, const void *ptr) |
| 2660 | { | 2625 | { |
| @@ -2691,7 +2656,6 @@ static struct dentry *proc_base_instantiate(struct inode *dir, | |||
| 2691 | if (p->fop) | 2656 | if (p->fop) |
| 2692 | inode->i_fop = p->fop; | 2657 | inode->i_fop = p->fop; |
| 2693 | ei->op = p->op; | 2658 | ei->op = p->op; |
| 2694 | dentry->d_op = &proc_base_dentry_operations; | ||
| 2695 | d_add(dentry, inode); | 2659 | d_add(dentry, inode); |
| 2696 | error = NULL; | 2660 | error = NULL; |
| 2697 | out: | 2661 | out: |
| @@ -3005,7 +2969,7 @@ static struct dentry *proc_pid_instantiate(struct inode *dir, | |||
| 3005 | inode->i_nlink = 2 + pid_entry_count_dirs(tgid_base_stuff, | 2969 | inode->i_nlink = 2 + pid_entry_count_dirs(tgid_base_stuff, |
| 3006 | ARRAY_SIZE(tgid_base_stuff)); | 2970 | ARRAY_SIZE(tgid_base_stuff)); |
| 3007 | 2971 | ||
| 3008 | dentry->d_op = &pid_dentry_operations; | 2972 | d_set_d_op(dentry, &pid_dentry_operations); |
| 3009 | 2973 | ||
| 3010 | d_add(dentry, inode); | 2974 | d_add(dentry, inode); |
| 3011 | /* Close the race of the process dying before we return the dentry */ | 2975 | /* Close the race of the process dying before we return the dentry */ |
| @@ -3248,7 +3212,7 @@ static struct dentry *proc_task_instantiate(struct inode *dir, | |||
| 3248 | inode->i_nlink = 2 + pid_entry_count_dirs(tid_base_stuff, | 3212 | inode->i_nlink = 2 + pid_entry_count_dirs(tid_base_stuff, |
| 3249 | ARRAY_SIZE(tid_base_stuff)); | 3213 | ARRAY_SIZE(tid_base_stuff)); |
| 3250 | 3214 | ||
| 3251 | dentry->d_op = &pid_dentry_operations; | 3215 | d_set_d_op(dentry, &pid_dentry_operations); |
| 3252 | 3216 | ||
| 3253 | d_add(dentry, inode); | 3217 | d_add(dentry, inode); |
| 3254 | /* Close the race of the process dying before we return the dentry */ | 3218 | /* Close the race of the process dying before we return the dentry */ |
