[PATCH 7/9] procfs: add pid_entry_show() helper to handle /proc/<pid>/{stat|stack}

From: Djalal Harouni
Date: Mon May 26 2014 - 09:36:42 EST


This patch is preparation, it adds the pid_entry_show() helper function
which will be used to handle /proc/<pid>/{stat|stack} and to call their
internal handlers. This logic allows these files to continue to use
sequence iterators.

Currently ONE entries share the same code, and they do not perform
permission checks during ->open(). So adding these checks during open
will only disturb the ONE entries that do not need permission checks.

The ONE entries that need checks are:
/proc/<pid>/stat
/proc/<pid>/stack

So to have proper permission checks convert this ONE entries to REG
entries and use their open() and read() handlers to implement these
checks. To achieve this we add the following helper:

* pid_entry_show(): which will get the necessary info and passe it to the
appropriate handlers. The handlers are of the same type of the previous
ONE entries, so nothing changes for /proc/<pid>/{stat|stack} handlers.

The handler type is:
typedef int (*proc_show_fn_t)(struct seq_file *seq, struct pid_namespace *ns,
struct pid *pid, struct task_struct *task);

Which is the same type of:

/proc/<pid>/stat:
int proc_tid_stat(struct seq_file *m, struct pid_namespace *ns,
struct pid *pid, struct task_struct *task)

/proc/<pid>/stack:
static int proc_pid_stack(struct seq_file *m, struct pid_namespace *ns,
struct pid *pid, struct task_struct *task)

The 'seq_file->private' will contain the struct 'pid_seq_private' which
contains the inode and the cached permission checks.

Signed-off-by: Djalal Harouni <tixxdz@xxxxxxxxxx>
---
fs/proc/base.c | 21 +++++++++++++++++++++
fs/proc/internal.h | 3 +++
2 files changed, 24 insertions(+)

diff --git a/fs/proc/base.c b/fs/proc/base.c
index f0ce94a..b40345b 100644
--- a/fs/proc/base.c
+++ b/fs/proc/base.c
@@ -183,6 +183,27 @@ out_no_task:
return length;
}

+int pid_entry_show(struct seq_file *seq, proc_show_fn_t proc_show)
+{
+ int ret = -ESRCH;
+ struct pid *pid;
+ struct task_struct *task;
+ struct pid_namespace *ns;
+ struct pid_seq_private *priv = seq->private;
+ struct inode *inode = priv->inode;
+
+ ns = inode->i_sb->s_fs_info;
+ pid = proc_pid(inode);
+ task = get_pid_task(pid, PIDTYPE_PID);
+ if (!task)
+ return ret;
+
+ ret = proc_show(seq, ns, pid, task);
+
+ put_task_struct(task);
+ return ret;
+}
+
static int pid_entry_attach(struct file *filp)
{
int ret = pid_entry_access(filp, PTRACE_MODE_ATTACH);
diff --git a/fs/proc/internal.h b/fs/proc/internal.h
index f28e4f01..3c4bd73 100644
--- a/fs/proc/internal.h
+++ b/fs/proc/internal.h
@@ -91,6 +91,8 @@ struct pid_seq_private {

typedef int (*proc_read_fn_t)(char *page,
struct task_struct *task, int permitted);
+typedef int (*proc_show_fn_t)(struct seq_file *seq, struct pid_namespace *ns,
+ struct pid *pid, struct task_struct *task);

/*
* General functions
@@ -191,6 +193,7 @@ extern int pid_delete_dentry(const struct dentry *);
extern int proc_pid_readdir(struct file *, struct dir_context *);
extern struct dentry *proc_pid_lookup(struct inode *, struct dentry *, unsigned int);
extern loff_t mem_lseek(struct file *, loff_t, int);
+extern int pid_entry_show(struct seq_file *seq, proc_show_fn_t proc_show);

/* Lookups */
typedef int instantiate_t(struct inode *, struct dentry *,
--
1.7.11.7

--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majordomo@xxxxxxxxxxxxxxx
More majordomo info at http://vger.kernel.org/majordomo-info.html
Please read the FAQ at http://www.tux.org/lkml/