[PATCH] proc: calculate and initialize size of /proc/<PID>/auxv

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



An ls and a wc commands show 0 size for some of /proc/<PID>/*
files, because getattr methods and inode->i_size variables
are not implemented for these files. These files are known
pseudo, but some peoples may need size of the files.

To calculate and return the size of each /proc/<PID>/auxv,
proc_pid_auxv_getattr() is added. It is used when getattr()
system call for the /proc/<PID>/auxv is called.

To initialize inode->i_size of each /proc/<PID>/* file,
isize_initializer member of pid_entry and some macros are
added, and proc_pid_auxv_isize() is added for i_size of
each /proc/<PID>/auxv.

BugLink: https://bugzilla.redhat.com/show_bug.cgi?id=155943

Signed-off-by: Takayuki Nagata <tnagata@xxxxxxxxxx>
---
 fs/proc/base.c |   66 +++++++++++++++++++++++++++++++++++++++++++------------
 1 files changed, 51 insertions(+), 15 deletions(-)

diff --git a/fs/proc/base.c b/fs/proc/base.c
index fc5bc27..e45afd3 100644
--- a/fs/proc/base.c
+++ b/fs/proc/base.c
@@ -105,33 +105,37 @@ struct pid_entry {
 	const struct inode_operations *iop;
 	const struct file_operations *fop;
 	union proc_op op;
+	loff_t (*isize_initializer)(struct task_struct*);
 };
 
-#define NOD(NAME, MODE, IOP, FOP, OP) {			\
+#define NOD(NAME, MODE, IOP, FOP, OP, ISIZE) {		\
 	.name = (NAME),					\
 	.len  = sizeof(NAME) - 1,			\
 	.mode = MODE,					\
 	.iop  = IOP,					\
 	.fop  = FOP,					\
 	.op   = OP,					\
+	.isize_initializer = ISIZE,			\
 }
 
 #define DIR(NAME, MODE, iops, fops)	\
-	NOD(NAME, (S_IFDIR|(MODE)), &iops, &fops, {} )
+	NOD(NAME, (S_IFDIR|(MODE)), &iops, &fops, {}, NULL )
 #define LNK(NAME, get_link)					\
 	NOD(NAME, (S_IFLNK|S_IRWXUGO),				\
 		&proc_pid_link_inode_operations, NULL,		\
-		{ .proc_get_link = get_link } )
+		{ .proc_get_link = get_link }, NULL )
 #define REG(NAME, MODE, fops)				\
-	NOD(NAME, (S_IFREG|(MODE)), NULL, &fops, {})
+	NOD(NAME, (S_IFREG|(MODE)), NULL, &fops, {}, NULL )
+#define INF_WITH_IOP(NAME, MODE, read, iop, isize)	\
+	NOD(NAME, (S_IFREG|(MODE)),			\
+		iop, &proc_info_file_operations,	\
+		{ .proc_read = read }, isize )
 #define INF(NAME, MODE, read)				\
-	NOD(NAME, (S_IFREG|(MODE)), 			\
-		NULL, &proc_info_file_operations,	\
-		{ .proc_read = read } )
+	INF_WITH_IOP(NAME, MODE, read, NULL, NULL )
 #define ONE(NAME, MODE, show)				\
 	NOD(NAME, (S_IFREG|(MODE)), 			\
 		NULL, &proc_single_file_operations,	\
-		{ .proc_show = show } )
+		{ .proc_show = show }, NULL )
 
 /*
  * Count the number of hardlinks for the pid_entry table, excluding the .
@@ -309,9 +313,8 @@ out:
 	return res;
 }
 
-static int proc_pid_auxv(struct task_struct *task, char *buffer)
+inline static int count_mm_saved_auxv(struct mm_struct *mm)
 {
-	struct mm_struct *mm = mm_for_maps(task);
 	int res = PTR_ERR(mm);
 	if (mm && !IS_ERR(mm)) {
 		unsigned int nwords = 0;
@@ -321,12 +324,43 @@ static int proc_pid_auxv(struct task_struct *task, char *buffer)
 		res = nwords * sizeof(mm->saved_auxv[0]);
 		if (res > PAGE_SIZE)
 			res = PAGE_SIZE;
-		memcpy(buffer, mm->saved_auxv, res);
-		mmput(mm);
 	}
 	return res;
 }
 
+static int proc_pid_auxv(struct task_struct *task, char *buffer)
+{
+	int size;
+	struct mm_struct *mm = get_task_mm(task);
+	size = count_mm_saved_auxv(mm);
+	if (mm) {
+		if(buffer)
+			memcpy(buffer, mm->saved_auxv, size);
+		mmput(mm);
+	}
+	return size;
+}
+
+static loff_t proc_pid_auxv_isize(struct task_struct *task)
+{
+	struct mm_struct *mm = get_task_mm(task);
+	return count_mm_saved_auxv(mm);
+}
+
+static int proc_pid_auxv_getattr(struct vfsmount *mnt, struct dentry *dentry, struct kstat *stat)
+{
+	struct inode *inode = dentry->d_inode;
+	struct task_struct *task = get_proc_task(inode);
+	struct mm_struct *mm = get_task_mm(task);
+
+	generic_fillattr(inode, stat);
+	stat->size = count_mm_saved_auxv(mm);
+	return 0;
+}
+
+static struct inode_operations proc_pid_auxv_inode_operations = {
+	.getattr	= proc_pid_auxv_getattr,
+};
 
 #ifdef CONFIG_KALLSYMS
 /*
@@ -2253,6 +2287,8 @@ static struct dentry *proc_pident_instantiate(struct inode *dir,
 
 	ei = PROC_I(inode);
 	inode->i_mode = p->mode;
+	if (p->isize_initializer)
+		inode->i_size = p->isize_initializer(task);
 	if (S_ISDIR(inode->i_mode))
 		inode->i_nlink = 2;	/* Use getattr to fix if necessary */
 	if (p->iop)
@@ -2617,7 +2653,7 @@ static const struct inode_operations proc_self_inode_operations = {
  */
 static const struct pid_entry proc_base_stuff[] = {
 	NOD("self", S_IFLNK|S_IRWXUGO,
-		&proc_self_inode_operations, NULL, {}),
+		&proc_self_inode_operations, NULL, {}, NULL),
 };
 
 static struct dentry *proc_base_instantiate(struct inode *dir,
@@ -2774,7 +2810,7 @@ static const struct pid_entry tgid_base_stuff[] = {
 	DIR("net",        S_IRUGO|S_IXUGO, proc_net_inode_operations, proc_net_operations),
 #endif
 	REG("environ",    S_IRUSR, proc_environ_operations),
-	INF("auxv",       S_IRUSR, proc_pid_auxv),
+	INF_WITH_IOP("auxv",       S_IRUSR, proc_pid_auxv, &proc_pid_auxv_inode_operations, proc_pid_auxv_isize),
 	ONE("status",     S_IRUGO, proc_pid_status),
 	ONE("personality", S_IRUGO, proc_pid_personality),
 	INF("limits",	  S_IRUGO, proc_pid_limits),
@@ -3123,7 +3159,7 @@ static const struct pid_entry tid_base_stuff[] = {
 	DIR("fdinfo",    S_IRUSR|S_IXUSR, proc_fdinfo_inode_operations, proc_fdinfo_operations),
 	DIR("ns",	 S_IRUSR|S_IXUGO, proc_ns_dir_inode_operations, proc_ns_dir_operations),
 	REG("environ",   S_IRUSR, proc_environ_operations),
-	INF("auxv",      S_IRUSR, proc_pid_auxv),
+	INF_WITH_IOP("auxv",      S_IRUSR, proc_pid_auxv, &proc_pid_auxv_inode_operations, proc_pid_auxv_isize),
 	ONE("status",    S_IRUGO, proc_pid_status),
 	ONE("personality", S_IRUGO, proc_pid_personality),
 	INF("limits",	 S_IRUGO, proc_pid_limits),
-- 
1.7.4.4
--
To unsubscribe from this list: send the line "unsubscribe linux-fsdevel" in
the body of a message to majordomo@xxxxxxxxxxxxxxx
More majordomo info at  http://vger.kernel.org/majordomo-info.html


[Index of Archives]     [Linux Ext4 Filesystem]     [Union Filesystem]     [Filesystem Testing]     [Ceph Users]     [Ecryptfs]     [AutoFS]     [Kernel Newbies]     [Share Photos]     [Security]     [Netfilter]     [Bugtraq]     [Yosemite News]     [MIPS Linux]     [ARM Linux]     [Linux Security]     [Linux Cachefs]     [Reiser Filesystem]     [Linux RAID]     [Samba]     [Device Mapper]     [CEPH Development]
  Powered by Linux