proc: calculate and initialize size of /proc/<PID>/auxv
Subsystems (2)
PATCH 1/1 proc: calculate and initialize size of /proc/<PID>/auxv
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.
--- fs/proc/base.c | 66 +++++++++++++++++++++++++++++++++++++++++++------------ 1 files changed, 51 insertions(+), 15 deletions(-)
fs/proc/base.c +51 -15
@@ -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), #endifREG ("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),
Signature · 1 line
1.7.4.4
Al Viro
maintainerQuoted 4 lines · Takayuki Nagata
An ls and a wc commands show 0 size for some of /proc/<PID>/* files, because getattr methods and
inode->i_sizevariables are not implemented for these files. These files are known pseudo, but some peoples may need size of the files.
"Some people may need" is far to vague...
Quoted 1 line
Containing unanswered question by mingo, again along the lines of "WTF is that needed at all?"...
fs/proc/base.c static int proc_pid_auxv(struct task_struct *task, char *buffer) · line 340
Quoted 10 lines
fs/proc/base.c +10
-0+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); + }
Oh, lovely - so we are allowing anybody to read it, suid exec be damned.
fs/proc/base.c static int proc_pid_auxv(struct task_struct *task, char *buffer) · line 347
Quoted 4 lines
fs/proc/base.c +4
-0+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);
... and that simply leaks.
fs/proc/base.c static int proc_pid_auxv(struct task_struct *task, char *buffer) · line 357
Quoted 8 lines
fs/proc/base.c +8
-0+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);
... and so does this, both mm and task.
Ancient bz entry with unanswered objections in it, broken patch, no rationale in sight... NAK with extreme prejudice.