From b6cdc7310338e204224f865918f774eb6db0b75d Mon Sep 17 00:00:00 2001 From: Al Viro Date: Sat, 30 Mar 2013 21:20:14 -0400 Subject: [PATCH] procfs: don't allow to use proc_create, create_proc_entry, etc. for directories Signed-off-by: Al Viro --- fs/proc/generic.c | 57 +++++++++++++++++++++-------------------------- fs/proc/inode.c | 4 ++-- 2 files changed, 27 insertions(+), 34 deletions(-) diff --git a/fs/proc/generic.c b/fs/proc/generic.c index 21e1a8f1659d..6bce60703c76 100644 --- a/fs/proc/generic.c +++ b/fs/proc/generic.c @@ -541,19 +541,18 @@ static int proc_register(struct proc_dir_entry * dir, struct proc_dir_entry * dp return ret; if (S_ISDIR(dp->mode)) { - if (dp->proc_iops == NULL) { - dp->proc_fops = &proc_dir_operations; - dp->proc_iops = &proc_dir_inode_operations; - } + dp->proc_fops = &proc_dir_operations; + dp->proc_iops = &proc_dir_inode_operations; dir->nlink++; } else if (S_ISLNK(dp->mode)) { - if (dp->proc_iops == NULL) - dp->proc_iops = &proc_link_inode_operations; + dp->proc_iops = &proc_link_inode_operations; } else if (S_ISREG(dp->mode)) { if (dp->proc_fops == NULL) dp->proc_fops = &proc_file_operations; - if (dp->proc_iops == NULL) - dp->proc_iops = &proc_file_inode_operations; + dp->proc_iops = &proc_file_inode_operations; + } else { + WARN_ON(1); + return -EINVAL; } spin_lock(&proc_subdir_lock); @@ -680,21 +679,19 @@ struct proc_dir_entry *create_proc_entry(const char *name, umode_t mode, struct proc_dir_entry *parent) { struct proc_dir_entry *ent; - nlink_t nlink; - if (S_ISDIR(mode)) { - if ((mode & S_IALLUGO) == 0) - mode |= S_IRUGO | S_IXUGO; - nlink = 2; - } else { - if ((mode & S_IFMT) == 0) - mode |= S_IFREG; - if ((mode & S_IALLUGO) == 0) - mode |= S_IRUGO; - nlink = 1; + if ((mode & S_IFMT) == 0) + mode |= S_IFREG; + + if (!S_ISREG(mode)) { + WARN_ON(1); /* use proc_mkdir(), damnit */ + return NULL; } - ent = __proc_create(&parent, name, mode, nlink); + if ((mode & S_IALLUGO) == 0) + mode |= S_IRUGO; + + ent = __proc_create(&parent, name, mode, 1); if (ent) { if (proc_register(parent, ent) < 0) { kfree(ent); @@ -711,21 +708,17 @@ struct proc_dir_entry *proc_create_data(const char *name, umode_t mode, void *data) { struct proc_dir_entry *pde; - nlink_t nlink; + if ((mode & S_IFMT) == 0) + mode |= S_IFREG; - if (S_ISDIR(mode)) { - if ((mode & S_IALLUGO) == 0) - mode |= S_IRUGO | S_IXUGO; - nlink = 2; - } else { - if ((mode & S_IFMT) == 0) - mode |= S_IFREG; - if ((mode & S_IALLUGO) == 0) - mode |= S_IRUGO; - nlink = 1; + if (!S_ISREG(mode)) { + WARN_ON(1); /* use proc_mkdir() */ + return NULL; } - pde = __proc_create(&parent, name, mode, nlink); + if ((mode & S_IALLUGO) == 0) + mode |= S_IRUGO; + pde = __proc_create(&parent, name, mode, 1); if (!pde) goto out; pde->proc_fops = proc_fops; diff --git a/fs/proc/inode.c b/fs/proc/inode.c index 908e97457319..a4aaaeee3342 100644 --- a/fs/proc/inode.c +++ b/fs/proc/inode.c @@ -462,8 +462,8 @@ struct inode *proc_get_inode(struct super_block *sb, struct proc_dir_entry *de) inode->i_size = de->size; if (de->nlink) set_nlink(inode, de->nlink); - if (de->proc_iops) - inode->i_op = de->proc_iops; + WARN_ON(!de->proc_iops); + inode->i_op = de->proc_iops; if (de->proc_fops) { if (S_ISREG(inode->i_mode)) { #ifdef CONFIG_COMPAT -- 2.20.1