diff options
author | Al Viro <viro@zeniv.linux.org.uk> | 2014-11-18 23:38:21 -0500 |
---|---|---|
committer | Al Viro <viro@zeniv.linux.org.uk> | 2014-12-10 21:32:15 -0500 |
commit | bd9b51e79cb0b8bc00a7e0076a4a8963ca4a797c (patch) | |
tree | bee3cc60bfbe1d7f837826bf495c0cf92747404b /fs | |
parent | 1f55a6ec940fb45e3edaa52b6e9fc40cf8e18dcb (diff) |
make default ->i_fop have ->open() fail with ENXIO
As it is, default ->i_fop has NULL ->open() (along with all other methods).
The only case where it matters is reopening (via procfs symlink) a file that
didn't get its ->f_op from ->i_fop - anything else will have ->i_fop assigned
to something sane (default would fail on read/write/ioctl/etc.).
Unfortunately, such case exists - alloc_file() users, especially
anon_get_file() ones. There we have tons of opened files of very different
kinds sharing the same inode. As the result, attempt to reopen those via
procfs succeeds and you get a descriptor you can't do anything with.
Moreover, in case of sockets we set ->i_fop that will only be used
on such reopen attempts - and put a failing ->open() into it to make sure
those do not succeed.
It would be simpler to put such ->open() into default ->i_fop and leave
it unchanged both for anon inode (as we do anyway) and for socket ones. Result:
* everything going through do_dentry_open() works as it used to
* sock_no_open() kludge is gone
* attempts to reopen anon-inode files fail as they really ought to
* ditto for aio_private_file()
* ditto for perfmon - this one actually tried to imitate sock_no_open()
trick, but failed to set ->i_fop, so in the current tree reopens succeed and
yield completely useless descriptor. Intent clearly had been to fail with
-ENXIO on such reopens; now it actually does.
* everything else that used alloc_file() keeps working - it has ->i_fop
set for its inodes anyway
Signed-off-by: Al Viro <viro@zeniv.linux.org.uk>
Diffstat (limited to 'fs')
-rw-r--r-- | fs/inode.c | 11 |
1 files changed, 8 insertions, 3 deletions
diff --git a/fs/inode.c b/fs/inode.c index 26753ba7b6d6..5b83ef7fc8d5 100644 --- a/fs/inode.c +++ b/fs/inode.c | |||
@@ -114,6 +114,11 @@ int proc_nr_inodes(struct ctl_table *table, int write, | |||
114 | } | 114 | } |
115 | #endif | 115 | #endif |
116 | 116 | ||
117 | static int no_open(struct inode *inode, struct file *file) | ||
118 | { | ||
119 | return -ENXIO; | ||
120 | } | ||
121 | |||
117 | /** | 122 | /** |
118 | * inode_init_always - perform inode structure intialisation | 123 | * inode_init_always - perform inode structure intialisation |
119 | * @sb: superblock inode belongs to | 124 | * @sb: superblock inode belongs to |
@@ -125,7 +130,7 @@ int proc_nr_inodes(struct ctl_table *table, int write, | |||
125 | int inode_init_always(struct super_block *sb, struct inode *inode) | 130 | int inode_init_always(struct super_block *sb, struct inode *inode) |
126 | { | 131 | { |
127 | static const struct inode_operations empty_iops; | 132 | static const struct inode_operations empty_iops; |
128 | static const struct file_operations empty_fops; | 133 | static const struct file_operations no_open_fops = {.open = no_open}; |
129 | struct address_space *const mapping = &inode->i_data; | 134 | struct address_space *const mapping = &inode->i_data; |
130 | 135 | ||
131 | inode->i_sb = sb; | 136 | inode->i_sb = sb; |
@@ -133,7 +138,7 @@ int inode_init_always(struct super_block *sb, struct inode *inode) | |||
133 | inode->i_flags = 0; | 138 | inode->i_flags = 0; |
134 | atomic_set(&inode->i_count, 1); | 139 | atomic_set(&inode->i_count, 1); |
135 | inode->i_op = &empty_iops; | 140 | inode->i_op = &empty_iops; |
136 | inode->i_fop = &empty_fops; | 141 | inode->i_fop = &no_open_fops; |
137 | inode->__i_nlink = 1; | 142 | inode->__i_nlink = 1; |
138 | inode->i_opflags = 0; | 143 | inode->i_opflags = 0; |
139 | i_uid_write(inode, 0); | 144 | i_uid_write(inode, 0); |
@@ -1801,7 +1806,7 @@ void init_special_inode(struct inode *inode, umode_t mode, dev_t rdev) | |||
1801 | } else if (S_ISFIFO(mode)) | 1806 | } else if (S_ISFIFO(mode)) |
1802 | inode->i_fop = &pipefifo_fops; | 1807 | inode->i_fop = &pipefifo_fops; |
1803 | else if (S_ISSOCK(mode)) | 1808 | else if (S_ISSOCK(mode)) |
1804 | inode->i_fop = &bad_sock_fops; | 1809 | ; /* leave it no_open_fops */ |
1805 | else | 1810 | else |
1806 | printk(KERN_DEBUG "init_special_inode: bogus i_mode (%o) for" | 1811 | printk(KERN_DEBUG "init_special_inode: bogus i_mode (%o) for" |
1807 | " inode %s:%lu\n", mode, inode->i_sb->s_id, | 1812 | " inode %s:%lu\n", mode, inode->i_sb->s_id, |