diff options
Diffstat (limited to 'fs/proc/base.c')
-rw-r--r-- | fs/proc/base.c | 49 |
1 files changed, 31 insertions, 18 deletions
diff --git a/fs/proc/base.c b/fs/proc/base.c index 18d5cc62d8ed..8418fcc0a6ab 100644 --- a/fs/proc/base.c +++ b/fs/proc/base.c | |||
@@ -81,6 +81,7 @@ | |||
81 | #include <linux/elf.h> | 81 | #include <linux/elf.h> |
82 | #include <linux/pid_namespace.h> | 82 | #include <linux/pid_namespace.h> |
83 | #include <linux/fs_struct.h> | 83 | #include <linux/fs_struct.h> |
84 | #include <linux/slab.h> | ||
84 | #include "internal.h" | 85 | #include "internal.h" |
85 | 86 | ||
86 | /* NOTE: | 87 | /* NOTE: |
@@ -442,12 +443,13 @@ static const struct file_operations proc_lstats_operations = { | |||
442 | unsigned long badness(struct task_struct *p, unsigned long uptime); | 443 | unsigned long badness(struct task_struct *p, unsigned long uptime); |
443 | static int proc_oom_score(struct task_struct *task, char *buffer) | 444 | static int proc_oom_score(struct task_struct *task, char *buffer) |
444 | { | 445 | { |
445 | unsigned long points; | 446 | unsigned long points = 0; |
446 | struct timespec uptime; | 447 | struct timespec uptime; |
447 | 448 | ||
448 | do_posix_clock_monotonic_gettime(&uptime); | 449 | do_posix_clock_monotonic_gettime(&uptime); |
449 | read_lock(&tasklist_lock); | 450 | read_lock(&tasklist_lock); |
450 | points = badness(task->group_leader, uptime.tv_sec); | 451 | if (pid_alive(task)) |
452 | points = badness(task, uptime.tv_sec); | ||
451 | read_unlock(&tasklist_lock); | 453 | read_unlock(&tasklist_lock); |
452 | return sprintf(buffer, "%lu\n", points); | 454 | return sprintf(buffer, "%lu\n", points); |
453 | } | 455 | } |
@@ -647,17 +649,11 @@ static int mounts_release(struct inode *inode, struct file *file) | |||
647 | static unsigned mounts_poll(struct file *file, poll_table *wait) | 649 | static unsigned mounts_poll(struct file *file, poll_table *wait) |
648 | { | 650 | { |
649 | struct proc_mounts *p = file->private_data; | 651 | struct proc_mounts *p = file->private_data; |
650 | struct mnt_namespace *ns = p->ns; | ||
651 | unsigned res = POLLIN | POLLRDNORM; | 652 | unsigned res = POLLIN | POLLRDNORM; |
652 | 653 | ||
653 | poll_wait(file, &ns->poll, wait); | 654 | poll_wait(file, &p->ns->poll, wait); |
654 | 655 | if (mnt_had_events(p)) | |
655 | spin_lock(&vfsmount_lock); | ||
656 | if (p->event != ns->event) { | ||
657 | p->event = ns->event; | ||
658 | res |= POLLERR | POLLPRI; | 656 | res |= POLLERR | POLLPRI; |
659 | } | ||
660 | spin_unlock(&vfsmount_lock); | ||
661 | 657 | ||
662 | return res; | 658 | return res; |
663 | } | 659 | } |
@@ -1095,8 +1091,12 @@ static ssize_t proc_loginuid_write(struct file * file, const char __user * buf, | |||
1095 | if (!capable(CAP_AUDIT_CONTROL)) | 1091 | if (!capable(CAP_AUDIT_CONTROL)) |
1096 | return -EPERM; | 1092 | return -EPERM; |
1097 | 1093 | ||
1098 | if (current != pid_task(proc_pid(inode), PIDTYPE_PID)) | 1094 | rcu_read_lock(); |
1095 | if (current != pid_task(proc_pid(inode), PIDTYPE_PID)) { | ||
1096 | rcu_read_unlock(); | ||
1099 | return -EPERM; | 1097 | return -EPERM; |
1098 | } | ||
1099 | rcu_read_unlock(); | ||
1100 | 1100 | ||
1101 | if (count >= PAGE_SIZE) | 1101 | if (count >= PAGE_SIZE) |
1102 | count = PAGE_SIZE - 1; | 1102 | count = PAGE_SIZE - 1; |
@@ -1419,7 +1419,6 @@ static void *proc_pid_follow_link(struct dentry *dentry, struct nameidata *nd) | |||
1419 | goto out; | 1419 | goto out; |
1420 | 1420 | ||
1421 | error = PROC_I(inode)->op.proc_get_link(inode, &nd->path); | 1421 | error = PROC_I(inode)->op.proc_get_link(inode, &nd->path); |
1422 | nd->last_type = LAST_BIND; | ||
1423 | out: | 1422 | out: |
1424 | return ERR_PTR(error); | 1423 | return ERR_PTR(error); |
1425 | } | 1424 | } |
@@ -2370,16 +2369,30 @@ static void *proc_self_follow_link(struct dentry *dentry, struct nameidata *nd) | |||
2370 | { | 2369 | { |
2371 | struct pid_namespace *ns = dentry->d_sb->s_fs_info; | 2370 | struct pid_namespace *ns = dentry->d_sb->s_fs_info; |
2372 | pid_t tgid = task_tgid_nr_ns(current, ns); | 2371 | pid_t tgid = task_tgid_nr_ns(current, ns); |
2373 | char tmp[PROC_NUMBUF]; | 2372 | char *name = ERR_PTR(-ENOENT); |
2374 | if (!tgid) | 2373 | if (tgid) { |
2375 | return ERR_PTR(-ENOENT); | 2374 | name = __getname(); |
2376 | sprintf(tmp, "%d", task_tgid_nr_ns(current, ns)); | 2375 | if (!name) |
2377 | return ERR_PTR(vfs_follow_link(nd,tmp)); | 2376 | name = ERR_PTR(-ENOMEM); |
2377 | else | ||
2378 | sprintf(name, "%d", tgid); | ||
2379 | } | ||
2380 | nd_set_link(nd, name); | ||
2381 | return NULL; | ||
2382 | } | ||
2383 | |||
2384 | static void proc_self_put_link(struct dentry *dentry, struct nameidata *nd, | ||
2385 | void *cookie) | ||
2386 | { | ||
2387 | char *s = nd_get_link(nd); | ||
2388 | if (!IS_ERR(s)) | ||
2389 | __putname(s); | ||
2378 | } | 2390 | } |
2379 | 2391 | ||
2380 | static const struct inode_operations proc_self_inode_operations = { | 2392 | static const struct inode_operations proc_self_inode_operations = { |
2381 | .readlink = proc_self_readlink, | 2393 | .readlink = proc_self_readlink, |
2382 | .follow_link = proc_self_follow_link, | 2394 | .follow_link = proc_self_follow_link, |
2395 | .put_link = proc_self_put_link, | ||
2383 | }; | 2396 | }; |
2384 | 2397 | ||
2385 | /* | 2398 | /* |
@@ -2896,7 +2909,7 @@ out_no_task: | |||
2896 | */ | 2909 | */ |
2897 | static const struct pid_entry tid_base_stuff[] = { | 2910 | static const struct pid_entry tid_base_stuff[] = { |
2898 | DIR("fd", S_IRUSR|S_IXUSR, proc_fd_inode_operations, proc_fd_operations), | 2911 | DIR("fd", S_IRUSR|S_IXUSR, proc_fd_inode_operations, proc_fd_operations), |
2899 | DIR("fdinfo", S_IRUSR|S_IXUSR, proc_fdinfo_inode_operations, proc_fd_operations), | 2912 | DIR("fdinfo", S_IRUSR|S_IXUSR, proc_fdinfo_inode_operations, proc_fdinfo_operations), |
2900 | REG("environ", S_IRUSR, proc_environ_operations), | 2913 | REG("environ", S_IRUSR, proc_environ_operations), |
2901 | INF("auxv", S_IRUSR, proc_pid_auxv), | 2914 | INF("auxv", S_IRUSR, proc_pid_auxv), |
2902 | ONE("status", S_IRUGO, proc_pid_status), | 2915 | ONE("status", S_IRUGO, proc_pid_status), |