diff options
Diffstat (limited to 'fs/proc/base.c')
| -rw-r--r-- | fs/proc/base.c | 92 |
1 files changed, 72 insertions, 20 deletions
diff --git a/fs/proc/base.c b/fs/proc/base.c index 58c3e6a8e15e..a28840b11b89 100644 --- a/fs/proc/base.c +++ b/fs/proc/base.c | |||
| @@ -53,6 +53,7 @@ | |||
| 53 | #include <linux/time.h> | 53 | #include <linux/time.h> |
| 54 | #include <linux/proc_fs.h> | 54 | #include <linux/proc_fs.h> |
| 55 | #include <linux/stat.h> | 55 | #include <linux/stat.h> |
| 56 | #include <linux/task_io_accounting_ops.h> | ||
| 56 | #include <linux/init.h> | 57 | #include <linux/init.h> |
| 57 | #include <linux/capability.h> | 58 | #include <linux/capability.h> |
| 58 | #include <linux/file.h> | 59 | #include <linux/file.h> |
| @@ -69,6 +70,7 @@ | |||
| 69 | #include <linux/mount.h> | 70 | #include <linux/mount.h> |
| 70 | #include <linux/security.h> | 71 | #include <linux/security.h> |
| 71 | #include <linux/ptrace.h> | 72 | #include <linux/ptrace.h> |
| 73 | #include <linux/tracehook.h> | ||
| 72 | #include <linux/cgroup.h> | 74 | #include <linux/cgroup.h> |
| 73 | #include <linux/cpuset.h> | 75 | #include <linux/cpuset.h> |
| 74 | #include <linux/audit.h> | 76 | #include <linux/audit.h> |
| @@ -231,10 +233,14 @@ static int check_mem_permission(struct task_struct *task) | |||
| 231 | * If current is actively ptrace'ing, and would also be | 233 | * If current is actively ptrace'ing, and would also be |
| 232 | * permitted to freshly attach with ptrace now, permit it. | 234 | * permitted to freshly attach with ptrace now, permit it. |
| 233 | */ | 235 | */ |
| 234 | if (task->parent == current && (task->ptrace & PT_PTRACED) && | 236 | if (task_is_stopped_or_traced(task)) { |
| 235 | task_is_stopped_or_traced(task) && | 237 | int match; |
| 236 | ptrace_may_access(task, PTRACE_MODE_ATTACH)) | 238 | rcu_read_lock(); |
| 237 | return 0; | 239 | match = (tracehook_tracer_task(task) == current); |
| 240 | rcu_read_unlock(); | ||
| 241 | if (match && ptrace_may_access(task, PTRACE_MODE_ATTACH)) | ||
| 242 | return 0; | ||
| 243 | } | ||
| 238 | 244 | ||
| 239 | /* | 245 | /* |
| 240 | * Noone else is allowed. | 246 | * Noone else is allowed. |
| @@ -504,6 +510,26 @@ static int proc_pid_limits(struct task_struct *task, char *buffer) | |||
| 504 | return count; | 510 | return count; |
| 505 | } | 511 | } |
| 506 | 512 | ||
| 513 | #ifdef CONFIG_HAVE_ARCH_TRACEHOOK | ||
| 514 | static int proc_pid_syscall(struct task_struct *task, char *buffer) | ||
| 515 | { | ||
| 516 | long nr; | ||
| 517 | unsigned long args[6], sp, pc; | ||
| 518 | |||
| 519 | if (task_current_syscall(task, &nr, args, 6, &sp, &pc)) | ||
| 520 | return sprintf(buffer, "running\n"); | ||
| 521 | |||
| 522 | if (nr < 0) | ||
| 523 | return sprintf(buffer, "%ld 0x%lx 0x%lx\n", nr, sp, pc); | ||
| 524 | |||
| 525 | return sprintf(buffer, | ||
| 526 | "%ld 0x%lx 0x%lx 0x%lx 0x%lx 0x%lx 0x%lx 0x%lx 0x%lx\n", | ||
| 527 | nr, | ||
| 528 | args[0], args[1], args[2], args[3], args[4], args[5], | ||
| 529 | sp, pc); | ||
| 530 | } | ||
| 531 | #endif /* CONFIG_HAVE_ARCH_TRACEHOOK */ | ||
| 532 | |||
| 507 | /************************************************************************/ | 533 | /************************************************************************/ |
| 508 | /* Here the fs part begins */ | 534 | /* Here the fs part begins */ |
| 509 | /************************************************************************/ | 535 | /************************************************************************/ |
| @@ -1834,8 +1860,7 @@ static const struct file_operations proc_fd_operations = { | |||
| 1834 | * /proc/pid/fd needs a special permission handler so that a process can still | 1860 | * /proc/pid/fd needs a special permission handler so that a process can still |
| 1835 | * access /proc/self/fd after it has executed a setuid(). | 1861 | * access /proc/self/fd after it has executed a setuid(). |
| 1836 | */ | 1862 | */ |
| 1837 | static int proc_fd_permission(struct inode *inode, int mask, | 1863 | static int proc_fd_permission(struct inode *inode, int mask) |
| 1838 | struct nameidata *nd) | ||
| 1839 | { | 1864 | { |
| 1840 | int rv; | 1865 | int rv; |
| 1841 | 1866 | ||
| @@ -2376,29 +2401,47 @@ static int proc_base_fill_cache(struct file *filp, void *dirent, | |||
| 2376 | } | 2401 | } |
| 2377 | 2402 | ||
| 2378 | #ifdef CONFIG_TASK_IO_ACCOUNTING | 2403 | #ifdef CONFIG_TASK_IO_ACCOUNTING |
| 2379 | static int proc_pid_io_accounting(struct task_struct *task, char *buffer) | 2404 | static int do_io_accounting(struct task_struct *task, char *buffer, int whole) |
| 2380 | { | 2405 | { |
| 2406 | struct task_io_accounting acct = task->ioac; | ||
| 2407 | unsigned long flags; | ||
| 2408 | |||
| 2409 | if (whole && lock_task_sighand(task, &flags)) { | ||
| 2410 | struct task_struct *t = task; | ||
| 2411 | |||
| 2412 | task_io_accounting_add(&acct, &task->signal->ioac); | ||
| 2413 | while_each_thread(task, t) | ||
| 2414 | task_io_accounting_add(&acct, &t->ioac); | ||
| 2415 | |||
| 2416 | unlock_task_sighand(task, &flags); | ||
| 2417 | } | ||
| 2381 | return sprintf(buffer, | 2418 | return sprintf(buffer, |
| 2382 | #ifdef CONFIG_TASK_XACCT | ||
| 2383 | "rchar: %llu\n" | 2419 | "rchar: %llu\n" |
| 2384 | "wchar: %llu\n" | 2420 | "wchar: %llu\n" |
| 2385 | "syscr: %llu\n" | 2421 | "syscr: %llu\n" |
| 2386 | "syscw: %llu\n" | 2422 | "syscw: %llu\n" |
| 2387 | #endif | ||
| 2388 | "read_bytes: %llu\n" | 2423 | "read_bytes: %llu\n" |
| 2389 | "write_bytes: %llu\n" | 2424 | "write_bytes: %llu\n" |
| 2390 | "cancelled_write_bytes: %llu\n", | 2425 | "cancelled_write_bytes: %llu\n", |
| 2391 | #ifdef CONFIG_TASK_XACCT | 2426 | (unsigned long long)acct.rchar, |
| 2392 | (unsigned long long)task->rchar, | 2427 | (unsigned long long)acct.wchar, |
| 2393 | (unsigned long long)task->wchar, | 2428 | (unsigned long long)acct.syscr, |
| 2394 | (unsigned long long)task->syscr, | 2429 | (unsigned long long)acct.syscw, |
| 2395 | (unsigned long long)task->syscw, | 2430 | (unsigned long long)acct.read_bytes, |
| 2396 | #endif | 2431 | (unsigned long long)acct.write_bytes, |
| 2397 | (unsigned long long)task->ioac.read_bytes, | 2432 | (unsigned long long)acct.cancelled_write_bytes); |
| 2398 | (unsigned long long)task->ioac.write_bytes, | 2433 | } |
| 2399 | (unsigned long long)task->ioac.cancelled_write_bytes); | 2434 | |
| 2435 | static int proc_tid_io_accounting(struct task_struct *task, char *buffer) | ||
| 2436 | { | ||
| 2437 | return do_io_accounting(task, buffer, 0); | ||
| 2400 | } | 2438 | } |
| 2401 | #endif | 2439 | |
| 2440 | static int proc_tgid_io_accounting(struct task_struct *task, char *buffer) | ||
| 2441 | { | ||
| 2442 | return do_io_accounting(task, buffer, 1); | ||
| 2443 | } | ||
| 2444 | #endif /* CONFIG_TASK_IO_ACCOUNTING */ | ||
| 2402 | 2445 | ||
| 2403 | /* | 2446 | /* |
| 2404 | * Thread groups | 2447 | * Thread groups |
| @@ -2420,6 +2463,9 @@ static const struct pid_entry tgid_base_stuff[] = { | |||
| 2420 | #ifdef CONFIG_SCHED_DEBUG | 2463 | #ifdef CONFIG_SCHED_DEBUG |
| 2421 | REG("sched", S_IRUGO|S_IWUSR, pid_sched), | 2464 | REG("sched", S_IRUGO|S_IWUSR, pid_sched), |
| 2422 | #endif | 2465 | #endif |
| 2466 | #ifdef CONFIG_HAVE_ARCH_TRACEHOOK | ||
| 2467 | INF("syscall", S_IRUSR, pid_syscall), | ||
| 2468 | #endif | ||
| 2423 | INF("cmdline", S_IRUGO, pid_cmdline), | 2469 | INF("cmdline", S_IRUGO, pid_cmdline), |
| 2424 | ONE("stat", S_IRUGO, tgid_stat), | 2470 | ONE("stat", S_IRUGO, tgid_stat), |
| 2425 | ONE("statm", S_IRUGO, pid_statm), | 2471 | ONE("statm", S_IRUGO, pid_statm), |
| @@ -2470,7 +2516,7 @@ static const struct pid_entry tgid_base_stuff[] = { | |||
| 2470 | REG("coredump_filter", S_IRUGO|S_IWUSR, coredump_filter), | 2516 | REG("coredump_filter", S_IRUGO|S_IWUSR, coredump_filter), |
| 2471 | #endif | 2517 | #endif |
| 2472 | #ifdef CONFIG_TASK_IO_ACCOUNTING | 2518 | #ifdef CONFIG_TASK_IO_ACCOUNTING |
| 2473 | INF("io", S_IRUGO, pid_io_accounting), | 2519 | INF("io", S_IRUGO, tgid_io_accounting), |
| 2474 | #endif | 2520 | #endif |
| 2475 | }; | 2521 | }; |
| 2476 | 2522 | ||
| @@ -2752,6 +2798,9 @@ static const struct pid_entry tid_base_stuff[] = { | |||
| 2752 | #ifdef CONFIG_SCHED_DEBUG | 2798 | #ifdef CONFIG_SCHED_DEBUG |
| 2753 | REG("sched", S_IRUGO|S_IWUSR, pid_sched), | 2799 | REG("sched", S_IRUGO|S_IWUSR, pid_sched), |
| 2754 | #endif | 2800 | #endif |
| 2801 | #ifdef CONFIG_HAVE_ARCH_TRACEHOOK | ||
| 2802 | INF("syscall", S_IRUSR, pid_syscall), | ||
| 2803 | #endif | ||
| 2755 | INF("cmdline", S_IRUGO, pid_cmdline), | 2804 | INF("cmdline", S_IRUGO, pid_cmdline), |
| 2756 | ONE("stat", S_IRUGO, tid_stat), | 2805 | ONE("stat", S_IRUGO, tid_stat), |
| 2757 | ONE("statm", S_IRUGO, pid_statm), | 2806 | ONE("statm", S_IRUGO, pid_statm), |
| @@ -2797,6 +2846,9 @@ static const struct pid_entry tid_base_stuff[] = { | |||
| 2797 | #ifdef CONFIG_FAULT_INJECTION | 2846 | #ifdef CONFIG_FAULT_INJECTION |
| 2798 | REG("make-it-fail", S_IRUGO|S_IWUSR, fault_inject), | 2847 | REG("make-it-fail", S_IRUGO|S_IWUSR, fault_inject), |
| 2799 | #endif | 2848 | #endif |
| 2849 | #ifdef CONFIG_TASK_IO_ACCOUNTING | ||
| 2850 | INF("io", S_IRUGO, tid_io_accounting), | ||
| 2851 | #endif | ||
| 2800 | }; | 2852 | }; |
| 2801 | 2853 | ||
| 2802 | static int proc_tid_base_readdir(struct file * filp, | 2854 | static int proc_tid_base_readdir(struct file * filp, |
