diff options
author | Andrea Bastoni <bastoni@cs.unc.edu> | 2010-05-30 19:16:45 -0400 |
---|---|---|
committer | Andrea Bastoni <bastoni@cs.unc.edu> | 2010-05-30 19:16:45 -0400 |
commit | ada47b5fe13d89735805b566185f4885f5a3f750 (patch) | |
tree | 644b88f8a71896307d71438e9b3af49126ffb22b /fs/proc/base.c | |
parent | 43e98717ad40a4ae64545b5ba047c7b86aa44f4f (diff) | |
parent | 3280f21d43ee541f97f8cda5792150d2dbec20d5 (diff) |
Merge branch 'wip-2.6.34' into old-private-masterarchived-private-master
Diffstat (limited to 'fs/proc/base.c')
-rw-r--r-- | fs/proc/base.c | 121 |
1 files changed, 101 insertions, 20 deletions
diff --git a/fs/proc/base.c b/fs/proc/base.c index af643b5aefe8..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; |
@@ -1265,6 +1265,72 @@ static const struct file_operations proc_pid_sched_operations = { | |||
1265 | 1265 | ||
1266 | #endif | 1266 | #endif |
1267 | 1267 | ||
1268 | static ssize_t comm_write(struct file *file, const char __user *buf, | ||
1269 | size_t count, loff_t *offset) | ||
1270 | { | ||
1271 | struct inode *inode = file->f_path.dentry->d_inode; | ||
1272 | struct task_struct *p; | ||
1273 | char buffer[TASK_COMM_LEN]; | ||
1274 | |||
1275 | memset(buffer, 0, sizeof(buffer)); | ||
1276 | if (count > sizeof(buffer) - 1) | ||
1277 | count = sizeof(buffer) - 1; | ||
1278 | if (copy_from_user(buffer, buf, count)) | ||
1279 | return -EFAULT; | ||
1280 | |||
1281 | p = get_proc_task(inode); | ||
1282 | if (!p) | ||
1283 | return -ESRCH; | ||
1284 | |||
1285 | if (same_thread_group(current, p)) | ||
1286 | set_task_comm(p, buffer); | ||
1287 | else | ||
1288 | count = -EINVAL; | ||
1289 | |||
1290 | put_task_struct(p); | ||
1291 | |||
1292 | return count; | ||
1293 | } | ||
1294 | |||
1295 | static int comm_show(struct seq_file *m, void *v) | ||
1296 | { | ||
1297 | struct inode *inode = m->private; | ||
1298 | struct task_struct *p; | ||
1299 | |||
1300 | p = get_proc_task(inode); | ||
1301 | if (!p) | ||
1302 | return -ESRCH; | ||
1303 | |||
1304 | task_lock(p); | ||
1305 | seq_printf(m, "%s\n", p->comm); | ||
1306 | task_unlock(p); | ||
1307 | |||
1308 | put_task_struct(p); | ||
1309 | |||
1310 | return 0; | ||
1311 | } | ||
1312 | |||
1313 | static int comm_open(struct inode *inode, struct file *filp) | ||
1314 | { | ||
1315 | int ret; | ||
1316 | |||
1317 | ret = single_open(filp, comm_show, NULL); | ||
1318 | if (!ret) { | ||
1319 | struct seq_file *m = filp->private_data; | ||
1320 | |||
1321 | m->private = inode; | ||
1322 | } | ||
1323 | return ret; | ||
1324 | } | ||
1325 | |||
1326 | static const struct file_operations proc_pid_set_comm_operations = { | ||
1327 | .open = comm_open, | ||
1328 | .read = seq_read, | ||
1329 | .write = comm_write, | ||
1330 | .llseek = seq_lseek, | ||
1331 | .release = single_release, | ||
1332 | }; | ||
1333 | |||
1268 | /* | 1334 | /* |
1269 | * We added or removed a vma mapping the executable. The vmas are only mapped | 1335 | * We added or removed a vma mapping the executable. The vmas are only mapped |
1270 | * during exec and are not mapped with the mmap system call. | 1336 | * during exec and are not mapped with the mmap system call. |
@@ -1353,7 +1419,6 @@ static void *proc_pid_follow_link(struct dentry *dentry, struct nameidata *nd) | |||
1353 | goto out; | 1419 | goto out; |
1354 | 1420 | ||
1355 | error = PROC_I(inode)->op.proc_get_link(inode, &nd->path); | 1421 | error = PROC_I(inode)->op.proc_get_link(inode, &nd->path); |
1356 | nd->last_type = LAST_BIND; | ||
1357 | out: | 1422 | out: |
1358 | return ERR_PTR(error); | 1423 | return ERR_PTR(error); |
1359 | } | 1424 | } |
@@ -2200,7 +2265,7 @@ static const struct inode_operations proc_attr_dir_inode_operations = { | |||
2200 | 2265 | ||
2201 | #endif | 2266 | #endif |
2202 | 2267 | ||
2203 | #if defined(USE_ELF_CORE_DUMP) && defined(CONFIG_ELF_CORE) | 2268 | #ifdef CONFIG_ELF_CORE |
2204 | static ssize_t proc_coredump_filter_read(struct file *file, char __user *buf, | 2269 | static ssize_t proc_coredump_filter_read(struct file *file, char __user *buf, |
2205 | size_t count, loff_t *ppos) | 2270 | size_t count, loff_t *ppos) |
2206 | { | 2271 | { |
@@ -2304,16 +2369,30 @@ static void *proc_self_follow_link(struct dentry *dentry, struct nameidata *nd) | |||
2304 | { | 2369 | { |
2305 | struct pid_namespace *ns = dentry->d_sb->s_fs_info; | 2370 | struct pid_namespace *ns = dentry->d_sb->s_fs_info; |
2306 | pid_t tgid = task_tgid_nr_ns(current, ns); | 2371 | pid_t tgid = task_tgid_nr_ns(current, ns); |
2307 | char tmp[PROC_NUMBUF]; | 2372 | char *name = ERR_PTR(-ENOENT); |
2308 | if (!tgid) | 2373 | if (tgid) { |
2309 | return ERR_PTR(-ENOENT); | 2374 | name = __getname(); |
2310 | sprintf(tmp, "%d", task_tgid_nr_ns(current, ns)); | 2375 | if (!name) |
2311 | 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); | ||
2312 | } | 2390 | } |
2313 | 2391 | ||
2314 | static const struct inode_operations proc_self_inode_operations = { | 2392 | static const struct inode_operations proc_self_inode_operations = { |
2315 | .readlink = proc_self_readlink, | 2393 | .readlink = proc_self_readlink, |
2316 | .follow_link = proc_self_follow_link, | 2394 | .follow_link = proc_self_follow_link, |
2395 | .put_link = proc_self_put_link, | ||
2317 | }; | 2396 | }; |
2318 | 2397 | ||
2319 | /* | 2398 | /* |
@@ -2504,6 +2583,7 @@ static const struct pid_entry tgid_base_stuff[] = { | |||
2504 | #ifdef CONFIG_SCHED_DEBUG | 2583 | #ifdef CONFIG_SCHED_DEBUG |
2505 | REG("sched", S_IRUGO|S_IWUSR, proc_pid_sched_operations), | 2584 | REG("sched", S_IRUGO|S_IWUSR, proc_pid_sched_operations), |
2506 | #endif | 2585 | #endif |
2586 | REG("comm", S_IRUGO|S_IWUSR, proc_pid_set_comm_operations), | ||
2507 | #ifdef CONFIG_HAVE_ARCH_TRACEHOOK | 2587 | #ifdef CONFIG_HAVE_ARCH_TRACEHOOK |
2508 | INF("syscall", S_IRUSR, proc_pid_syscall), | 2588 | INF("syscall", S_IRUSR, proc_pid_syscall), |
2509 | #endif | 2589 | #endif |
@@ -2556,7 +2636,7 @@ static const struct pid_entry tgid_base_stuff[] = { | |||
2556 | #ifdef CONFIG_FAULT_INJECTION | 2636 | #ifdef CONFIG_FAULT_INJECTION |
2557 | REG("make-it-fail", S_IRUGO|S_IWUSR, proc_fault_inject_operations), | 2637 | REG("make-it-fail", S_IRUGO|S_IWUSR, proc_fault_inject_operations), |
2558 | #endif | 2638 | #endif |
2559 | #if defined(USE_ELF_CORE_DUMP) && defined(CONFIG_ELF_CORE) | 2639 | #ifdef CONFIG_ELF_CORE |
2560 | REG("coredump_filter", S_IRUGO|S_IWUSR, proc_coredump_filter_operations), | 2640 | REG("coredump_filter", S_IRUGO|S_IWUSR, proc_coredump_filter_operations), |
2561 | #endif | 2641 | #endif |
2562 | #ifdef CONFIG_TASK_IO_ACCOUNTING | 2642 | #ifdef CONFIG_TASK_IO_ACCOUNTING |
@@ -2829,7 +2909,7 @@ out_no_task: | |||
2829 | */ | 2909 | */ |
2830 | static const struct pid_entry tid_base_stuff[] = { | 2910 | static const struct pid_entry tid_base_stuff[] = { |
2831 | 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), |
2832 | 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), |
2833 | REG("environ", S_IRUSR, proc_environ_operations), | 2913 | REG("environ", S_IRUSR, proc_environ_operations), |
2834 | INF("auxv", S_IRUSR, proc_pid_auxv), | 2914 | INF("auxv", S_IRUSR, proc_pid_auxv), |
2835 | ONE("status", S_IRUGO, proc_pid_status), | 2915 | ONE("status", S_IRUGO, proc_pid_status), |
@@ -2838,6 +2918,7 @@ static const struct pid_entry tid_base_stuff[] = { | |||
2838 | #ifdef CONFIG_SCHED_DEBUG | 2918 | #ifdef CONFIG_SCHED_DEBUG |
2839 | REG("sched", S_IRUGO|S_IWUSR, proc_pid_sched_operations), | 2919 | REG("sched", S_IRUGO|S_IWUSR, proc_pid_sched_operations), |
2840 | #endif | 2920 | #endif |
2921 | REG("comm", S_IRUGO|S_IWUSR, proc_pid_set_comm_operations), | ||
2841 | #ifdef CONFIG_HAVE_ARCH_TRACEHOOK | 2922 | #ifdef CONFIG_HAVE_ARCH_TRACEHOOK |
2842 | INF("syscall", S_IRUSR, proc_pid_syscall), | 2923 | INF("syscall", S_IRUSR, proc_pid_syscall), |
2843 | #endif | 2924 | #endif |