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 /net | |
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 'net')
-rw-r--r-- | net/Makefile | 2 | ||||
-rw-r--r-- | net/nonet.c | 26 | ||||
-rw-r--r-- | net/socket.c | 19 |
3 files changed, 0 insertions, 47 deletions
diff --git a/net/Makefile b/net/Makefile index 7ed1970074b0..1f6c3e4b36d5 100644 --- a/net/Makefile +++ b/net/Makefile | |||
@@ -5,8 +5,6 @@ | |||
5 | # Rewritten to use lists instead of if-statements. | 5 | # Rewritten to use lists instead of if-statements. |
6 | # | 6 | # |
7 | 7 | ||
8 | obj-y := nonet.o | ||
9 | |||
10 | obj-$(CONFIG_NET) := socket.o core/ | 8 | obj-$(CONFIG_NET) := socket.o core/ |
11 | 9 | ||
12 | tmp-$(CONFIG_COMPAT) := compat.o | 10 | tmp-$(CONFIG_COMPAT) := compat.o |
diff --git a/net/nonet.c b/net/nonet.c deleted file mode 100644 index b1a73fda9c12..000000000000 --- a/net/nonet.c +++ /dev/null | |||
@@ -1,26 +0,0 @@ | |||
1 | /* | ||
2 | * net/nonet.c | ||
3 | * | ||
4 | * Dummy functions to allow us to configure network support entirely | ||
5 | * out of the kernel. | ||
6 | * | ||
7 | * Distributed under the terms of the GNU GPL version 2. | ||
8 | * Copyright (c) Matthew Wilcox 2003 | ||
9 | */ | ||
10 | |||
11 | #include <linux/module.h> | ||
12 | #include <linux/errno.h> | ||
13 | #include <linux/fs.h> | ||
14 | #include <linux/init.h> | ||
15 | #include <linux/kernel.h> | ||
16 | |||
17 | static int sock_no_open(struct inode *irrelevant, struct file *dontcare) | ||
18 | { | ||
19 | return -ENXIO; | ||
20 | } | ||
21 | |||
22 | const struct file_operations bad_sock_fops = { | ||
23 | .owner = THIS_MODULE, | ||
24 | .open = sock_no_open, | ||
25 | .llseek = noop_llseek, | ||
26 | }; | ||
diff --git a/net/socket.c b/net/socket.c index fe20c319a0bb..850f6c383342 100644 --- a/net/socket.c +++ b/net/socket.c | |||
@@ -113,7 +113,6 @@ unsigned int sysctl_net_busy_read __read_mostly; | |||
113 | unsigned int sysctl_net_busy_poll __read_mostly; | 113 | unsigned int sysctl_net_busy_poll __read_mostly; |
114 | #endif | 114 | #endif |
115 | 115 | ||
116 | static int sock_no_open(struct inode *irrelevant, struct file *dontcare); | ||
117 | static ssize_t sock_aio_read(struct kiocb *iocb, const struct iovec *iov, | 116 | static ssize_t sock_aio_read(struct kiocb *iocb, const struct iovec *iov, |
118 | unsigned long nr_segs, loff_t pos); | 117 | unsigned long nr_segs, loff_t pos); |
119 | static ssize_t sock_aio_write(struct kiocb *iocb, const struct iovec *iov, | 118 | static ssize_t sock_aio_write(struct kiocb *iocb, const struct iovec *iov, |
@@ -151,7 +150,6 @@ static const struct file_operations socket_file_ops = { | |||
151 | .compat_ioctl = compat_sock_ioctl, | 150 | .compat_ioctl = compat_sock_ioctl, |
152 | #endif | 151 | #endif |
153 | .mmap = sock_mmap, | 152 | .mmap = sock_mmap, |
154 | .open = sock_no_open, /* special open code to disallow open via /proc */ | ||
155 | .release = sock_close, | 153 | .release = sock_close, |
156 | .fasync = sock_fasync, | 154 | .fasync = sock_fasync, |
157 | .sendpage = sock_sendpage, | 155 | .sendpage = sock_sendpage, |
@@ -559,23 +557,6 @@ static struct socket *sock_alloc(void) | |||
559 | return sock; | 557 | return sock; |
560 | } | 558 | } |
561 | 559 | ||
562 | /* | ||
563 | * In theory you can't get an open on this inode, but /proc provides | ||
564 | * a back door. Remember to keep it shut otherwise you'll let the | ||
565 | * creepy crawlies in. | ||
566 | */ | ||
567 | |||
568 | static int sock_no_open(struct inode *irrelevant, struct file *dontcare) | ||
569 | { | ||
570 | return -ENXIO; | ||
571 | } | ||
572 | |||
573 | const struct file_operations bad_sock_fops = { | ||
574 | .owner = THIS_MODULE, | ||
575 | .open = sock_no_open, | ||
576 | .llseek = noop_llseek, | ||
577 | }; | ||
578 | |||
579 | /** | 560 | /** |
580 | * sock_release - close a socket | 561 | * sock_release - close a socket |
581 | * @sock: socket to close | 562 | * @sock: socket to close |