aboutsummaryrefslogtreecommitdiff
path: root/fs/proc/base.c
diff options
context:
space:
mode:
Diffstat (limited to 'fs/proc/base.c')
-rw-r--r--fs/proc/base.c105
1 files changed, 49 insertions, 56 deletions
diff --git a/fs/proc/base.c b/fs/proc/base.c
index a891fe4cb43..01ed610f9b8 100644
--- a/fs/proc/base.c
+++ b/fs/proc/base.c
@@ -53,6 +53,7 @@
#include <linux/time.h>
#include <linux/proc_fs.h>
#include <linux/stat.h>
+#include <linux/task_io_accounting_ops.h>
#include <linux/init.h>
#include <linux/capability.h>
#include <linux/file.h>
@@ -69,6 +70,7 @@
#include <linux/mount.h>
#include <linux/security.h>
#include <linux/ptrace.h>
+#include <linux/tracehook.h>
#include <linux/cgroup.h>
#include <linux/cpuset.h>
#include <linux/audit.h>
@@ -231,10 +233,14 @@ static int check_mem_permission(struct task_struct *task)
* If current is actively ptrace'ing, and would also be
* permitted to freshly attach with ptrace now, permit it.
*/
- if (task->parent == current && (task->ptrace & PT_PTRACED) &&
- task_is_stopped_or_traced(task) &&
- ptrace_may_access(task, PTRACE_MODE_ATTACH))
- return 0;
+ if (task_is_stopped_or_traced(task)) {
+ int match;
+ rcu_read_lock();
+ match = (tracehook_tracer_task(task) == current);
+ rcu_read_unlock();
+ if (match && ptrace_may_access(task, PTRACE_MODE_ATTACH))
+ return 0;
+ }
/*
* Noone else is allowed.
@@ -504,6 +510,26 @@ static int proc_pid_limits(struct task_struct *task, char *buffer)
return count;
}
+#ifdef CONFIG_HAVE_ARCH_TRACEHOOK
+static int proc_pid_syscall(struct task_struct *task, char *buffer)
+{
+ long nr;
+ unsigned long args[6], sp, pc;
+
+ if (task_current_syscall(task, &nr, args, 6, &sp, &pc))
+ return sprintf(buffer, "running\n");
+
+ if (nr < 0)
+ return sprintf(buffer, "%ld 0x%lx 0x%lx\n", nr, sp, pc);
+
+ return sprintf(buffer,
+ "%ld 0x%lx 0x%lx 0x%lx 0x%lx 0x%lx 0x%lx 0x%lx 0x%lx\n",
+ nr,
+ args[0], args[1], args[2], args[3], args[4], args[5],
+ sp, pc);
+}
+#endif /* CONFIG_HAVE_ARCH_TRACEHOOK */
+
/************************************************************************/
/* Here the fs part begins */
/************************************************************************/
@@ -1834,8 +1860,7 @@ static const struct file_operations proc_fd_operations = {
* /proc/pid/fd needs a special permission handler so that a process can still
* access /proc/self/fd after it has executed a setuid().
*/
-static int proc_fd_permission(struct inode *inode, int mask,
- struct nameidata *nd)
+static int proc_fd_permission(struct inode *inode, int mask)
{
int rv;
@@ -2378,53 +2403,18 @@ static int proc_base_fill_cache(struct file *filp, void *dirent,
#ifdef CONFIG_TASK_IO_ACCOUNTING
static int do_io_accounting(struct task_struct *task, char *buffer, int whole)
{
- u64 rchar, wchar, syscr, syscw;
- struct task_io_accounting ioac;
-
- if (!whole) {
- rchar = task->rchar;
- wchar = task->wchar;
- syscr = task->syscr;
- syscw = task->syscw;
- memcpy(&ioac, &task->ioac, sizeof(ioac));
- } else {
- unsigned long flags;
- struct task_struct *t = task;
- rchar = wchar = syscr = syscw = 0;
- memset(&ioac, 0, sizeof(ioac));
-
- rcu_read_lock();
- do {
- rchar += t->rchar;
- wchar += t->wchar;
- syscr += t->syscr;
- syscw += t->syscw;
-
- ioac.read_bytes += t->ioac.read_bytes;
- ioac.write_bytes += t->ioac.write_bytes;
- ioac.cancelled_write_bytes +=
- t->ioac.cancelled_write_bytes;
- t = next_thread(t);
- } while (t != task);
- rcu_read_unlock();
-
- if (lock_task_sighand(task, &flags)) {
- struct signal_struct *sig = task->signal;
+ struct task_io_accounting acct = task->ioac;
+ unsigned long flags;
- rchar += sig->rchar;
- wchar += sig->wchar;
- syscr += sig->syscr;
- syscw += sig->syscw;
+ if (whole && lock_task_sighand(task, &flags)) {
+ struct task_struct *t = task;
- ioac.read_bytes += sig->ioac.read_bytes;
- ioac.write_bytes += sig->ioac.write_bytes;
- ioac.cancelled_write_bytes +=
- sig->ioac.cancelled_write_bytes;
+ task_io_accounting_add(&acct, &task->signal->ioac);
+ while_each_thread(task, t)
+ task_io_accounting_add(&acct, &t->ioac);
- unlock_task_sighand(task, &flags);
- }
+ unlock_task_sighand(task, &flags);
}
-
return sprintf(buffer,
"rchar: %llu\n"
"wchar: %llu\n"
@@ -2433,13 +2423,10 @@ static int do_io_accounting(struct task_struct *task, char *buffer, int whole)
"read_bytes: %llu\n"
"write_bytes: %llu\n"
"cancelled_write_bytes: %llu\n",
- (unsigned long long)rchar,
- (unsigned long long)wchar,
- (unsigned long long)syscr,
- (unsigned long long)syscw,
- (unsigned long long)ioac.read_bytes,
- (unsigned long long)ioac.write_bytes,
- (unsigned long long)ioac.cancelled_write_bytes);
+ acct.rchar, acct.wchar,
+ acct.syscr, acct.syscw,
+ acct.read_bytes, acct.write_bytes,
+ acct.cancelled_write_bytes);
}
static int proc_tid_io_accounting(struct task_struct *task, char *buffer)
@@ -2473,6 +2460,9 @@ static const struct pid_entry tgid_base_stuff[] = {
#ifdef CONFIG_SCHED_DEBUG
REG("sched", S_IRUGO|S_IWUSR, pid_sched),
#endif
+#ifdef CONFIG_HAVE_ARCH_TRACEHOOK
+ INF("syscall", S_IRUSR, pid_syscall),
+#endif
INF("cmdline", S_IRUGO, pid_cmdline),
ONE("stat", S_IRUGO, tgid_stat),
ONE("statm", S_IRUGO, pid_statm),
@@ -2805,6 +2795,9 @@ static const struct pid_entry tid_base_stuff[] = {
#ifdef CONFIG_SCHED_DEBUG
REG("sched", S_IRUGO|S_IWUSR, pid_sched),
#endif
+#ifdef CONFIG_HAVE_ARCH_TRACEHOOK
+ INF("syscall", S_IRUSR, pid_syscall),
+#endif
INF("cmdline", S_IRUGO, pid_cmdline),
ONE("stat", S_IRUGO, tid_stat),
ONE("statm", S_IRUGO, pid_statm),