Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit bd9b51e7 authored by Al Viro's avatar Al Viro
Browse files

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: default avatarAl Viro <viro@zeniv.linux.org.uk>
parent 1f55a6ec
Loading
Loading
Loading
Loading
+0 −10
Original line number Original line Diff line number Diff line
@@ -2145,22 +2145,12 @@ doit:
	return 0;
	return 0;
}
}


static int
pfm_no_open(struct inode *irrelevant, struct file *dontcare)
{
	DPRINT(("pfm_no_open called\n"));
	return -ENXIO;
}



static const struct file_operations pfm_file_ops = {
static const struct file_operations pfm_file_ops = {
	.llseek		= no_llseek,
	.llseek		= no_llseek,
	.read		= pfm_read,
	.read		= pfm_read,
	.write		= pfm_write,
	.write		= pfm_write,
	.poll		= pfm_poll,
	.poll		= pfm_poll,
	.unlocked_ioctl = pfm_ioctl,
	.unlocked_ioctl = pfm_ioctl,
	.open		= pfm_no_open,	/* special open code to disallow open via /proc */
	.fasync		= pfm_fasync,
	.fasync		= pfm_fasync,
	.release	= pfm_close,
	.release	= pfm_close,
	.flush		= pfm_flush
	.flush		= pfm_flush
+8 −3
Original line number Original line Diff line number Diff line
@@ -114,6 +114,11 @@ int proc_nr_inodes(struct ctl_table *table, int write,
}
}
#endif
#endif


static int no_open(struct inode *inode, struct file *file)
{
	return -ENXIO;
}

/**
/**
 * inode_init_always - perform inode structure intialisation
 * inode_init_always - perform inode structure intialisation
 * @sb: superblock inode belongs to
 * @sb: superblock inode belongs to
@@ -125,7 +130,7 @@ int proc_nr_inodes(struct ctl_table *table, int write,
int inode_init_always(struct super_block *sb, struct inode *inode)
int inode_init_always(struct super_block *sb, struct inode *inode)
{
{
	static const struct inode_operations empty_iops;
	static const struct inode_operations empty_iops;
	static const struct file_operations empty_fops;
	static const struct file_operations no_open_fops = {.open = no_open};
	struct address_space *const mapping = &inode->i_data;
	struct address_space *const mapping = &inode->i_data;


	inode->i_sb = sb;
	inode->i_sb = sb;
@@ -133,7 +138,7 @@ int inode_init_always(struct super_block *sb, struct inode *inode)
	inode->i_flags = 0;
	inode->i_flags = 0;
	atomic_set(&inode->i_count, 1);
	atomic_set(&inode->i_count, 1);
	inode->i_op = &empty_iops;
	inode->i_op = &empty_iops;
	inode->i_fop = &empty_fops;
	inode->i_fop = &no_open_fops;
	inode->__i_nlink = 1;
	inode->__i_nlink = 1;
	inode->i_opflags = 0;
	inode->i_opflags = 0;
	i_uid_write(inode, 0);
	i_uid_write(inode, 0);
@@ -1801,7 +1806,7 @@ void init_special_inode(struct inode *inode, umode_t mode, dev_t rdev)
	} else if (S_ISFIFO(mode))
	} else if (S_ISFIFO(mode))
		inode->i_fop = &pipefifo_fops;
		inode->i_fop = &pipefifo_fops;
	else if (S_ISSOCK(mode))
	else if (S_ISSOCK(mode))
		inode->i_fop = &bad_sock_fops;
		;	/* leave it no_open_fops */
	else
	else
		printk(KERN_DEBUG "init_special_inode: bogus i_mode (%o) for"
		printk(KERN_DEBUG "init_special_inode: bogus i_mode (%o) for"
				  " inode %s:%lu\n", mode, inode->i_sb->s_id,
				  " inode %s:%lu\n", mode, inode->i_sb->s_id,
+0 −1
Original line number Original line Diff line number Diff line
@@ -2151,7 +2151,6 @@ static inline int sb_is_blkdev_sb(struct super_block *sb)
extern int sync_filesystem(struct super_block *);
extern int sync_filesystem(struct super_block *);
extern const struct file_operations def_blk_fops;
extern const struct file_operations def_blk_fops;
extern const struct file_operations def_chr_fops;
extern const struct file_operations def_chr_fops;
extern const struct file_operations bad_sock_fops;
#ifdef CONFIG_BLOCK
#ifdef CONFIG_BLOCK
extern int ioctl_by_bdev(struct block_device *, unsigned, unsigned long);
extern int ioctl_by_bdev(struct block_device *, unsigned, unsigned long);
extern int blkdev_ioctl(struct block_device *, fmode_t, unsigned, unsigned long);
extern int blkdev_ioctl(struct block_device *, fmode_t, unsigned, unsigned long);
+0 −2
Original line number Original line Diff line number Diff line
@@ -5,8 +5,6 @@
# Rewritten to use lists instead of if-statements.
# Rewritten to use lists instead of if-statements.
#
#


obj-y	:= nonet.o

obj-$(CONFIG_NET)		:= socket.o core/
obj-$(CONFIG_NET)		:= socket.o core/


tmp-$(CONFIG_COMPAT) 		:= compat.o
tmp-$(CONFIG_COMPAT) 		:= compat.o

net/nonet.c

deleted100644 → 0
+0 −26
Original line number Original line Diff line number Diff line
/*
 * net/nonet.c
 *
 * Dummy functions to allow us to configure network support entirely
 * out of the kernel.
 *
 * Distributed under the terms of the GNU GPL version 2.
 * Copyright (c) Matthew Wilcox 2003
 */

#include <linux/module.h>
#include <linux/errno.h>
#include <linux/fs.h>
#include <linux/init.h>
#include <linux/kernel.h>

static int sock_no_open(struct inode *irrelevant, struct file *dontcare)
{
	return -ENXIO;
}

const struct file_operations bad_sock_fops = {
	.owner = THIS_MODULE,
	.open = sock_no_open,
	.llseek = noop_llseek,
};
Loading