Commit b501611a authored by Eric Van Hensbergen's avatar Eric Van Hensbergen Committed by Linus Torvalds

[PATCH] v9fs: readlink extended mode check

LANL reported some issues with random crashes during mount of legacy protocol
servers (9P2000 versus 9P2000.u) -- crash was always happening in readlink
(which should never happen in legacy mode).  Added some sanity conditionals to
the get_inode code which should prevent the errors LANL was seeing.  Code
tested benign through regression.
Signed-off-by: default avatarEric Van Hensbergen <ericvh@gmail.com>
Signed-off-by: default avatarAndrew Morton <akpm@osdl.org>
Signed-off-by: default avatarLinus Torvalds <torvalds@osdl.org>
parent 5d58bec5
...@@ -44,6 +44,7 @@ ...@@ -44,6 +44,7 @@
#include "fid.h" #include "fid.h"
static struct inode_operations v9fs_dir_inode_operations; static struct inode_operations v9fs_dir_inode_operations;
static struct inode_operations v9fs_dir_inode_operations_ext;
static struct inode_operations v9fs_file_inode_operations; static struct inode_operations v9fs_file_inode_operations;
static struct inode_operations v9fs_symlink_inode_operations; static struct inode_operations v9fs_symlink_inode_operations;
...@@ -232,6 +233,7 @@ v9fs_mistat2unix(struct v9fs_stat *mistat, struct stat *buf, ...@@ -232,6 +233,7 @@ v9fs_mistat2unix(struct v9fs_stat *mistat, struct stat *buf,
struct inode *v9fs_get_inode(struct super_block *sb, int mode) struct inode *v9fs_get_inode(struct super_block *sb, int mode)
{ {
struct inode *inode = NULL; struct inode *inode = NULL;
struct v9fs_session_info *v9ses = sb->s_fs_info;
dprintk(DEBUG_VFS, "super block: %p mode: %o\n", sb, mode); dprintk(DEBUG_VFS, "super block: %p mode: %o\n", sb, mode);
...@@ -250,6 +252,10 @@ struct inode *v9fs_get_inode(struct super_block *sb, int mode) ...@@ -250,6 +252,10 @@ struct inode *v9fs_get_inode(struct super_block *sb, int mode)
case S_IFBLK: case S_IFBLK:
case S_IFCHR: case S_IFCHR:
case S_IFSOCK: case S_IFSOCK:
if(!v9ses->extended) {
dprintk(DEBUG_ERROR, "special files without extended mode\n");
return ERR_PTR(-EINVAL);
}
init_special_inode(inode, inode->i_mode, init_special_inode(inode, inode->i_mode,
inode->i_rdev); inode->i_rdev);
break; break;
...@@ -257,14 +263,21 @@ struct inode *v9fs_get_inode(struct super_block *sb, int mode) ...@@ -257,14 +263,21 @@ struct inode *v9fs_get_inode(struct super_block *sb, int mode)
inode->i_op = &v9fs_file_inode_operations; inode->i_op = &v9fs_file_inode_operations;
inode->i_fop = &v9fs_file_operations; inode->i_fop = &v9fs_file_operations;
break; break;
case S_IFLNK:
if(!v9ses->extended) {
dprintk(DEBUG_ERROR, "extended modes used w/o 9P2000.u\n");
return ERR_PTR(-EINVAL);
}
inode->i_op = &v9fs_symlink_inode_operations;
break;
case S_IFDIR: case S_IFDIR:
inode->i_nlink++; inode->i_nlink++;
if(v9ses->extended)
inode->i_op = &v9fs_dir_inode_operations_ext;
else
inode->i_op = &v9fs_dir_inode_operations; inode->i_op = &v9fs_dir_inode_operations;
inode->i_fop = &v9fs_dir_operations; inode->i_fop = &v9fs_dir_operations;
break; break;
case S_IFLNK:
inode->i_op = &v9fs_symlink_inode_operations;
break;
default: default:
dprintk(DEBUG_ERROR, "BAD mode 0x%x S_IFMT 0x%x\n", dprintk(DEBUG_ERROR, "BAD mode 0x%x S_IFMT 0x%x\n",
mode, mode & S_IFMT); mode, mode & S_IFMT);
...@@ -1284,7 +1297,7 @@ v9fs_vfs_mknod(struct inode *dir, struct dentry *dentry, int mode, dev_t rdev) ...@@ -1284,7 +1297,7 @@ v9fs_vfs_mknod(struct inode *dir, struct dentry *dentry, int mode, dev_t rdev)
return retval; return retval;
} }
static struct inode_operations v9fs_dir_inode_operations = { static struct inode_operations v9fs_dir_inode_operations_ext = {
.create = v9fs_vfs_create, .create = v9fs_vfs_create,
.lookup = v9fs_vfs_lookup, .lookup = v9fs_vfs_lookup,
.symlink = v9fs_vfs_symlink, .symlink = v9fs_vfs_symlink,
...@@ -1299,6 +1312,18 @@ static struct inode_operations v9fs_dir_inode_operations = { ...@@ -1299,6 +1312,18 @@ static struct inode_operations v9fs_dir_inode_operations = {
.setattr = v9fs_vfs_setattr, .setattr = v9fs_vfs_setattr,
}; };
static struct inode_operations v9fs_dir_inode_operations = {
.create = v9fs_vfs_create,
.lookup = v9fs_vfs_lookup,
.unlink = v9fs_vfs_unlink,
.mkdir = v9fs_vfs_mkdir,
.rmdir = v9fs_vfs_rmdir,
.mknod = v9fs_vfs_mknod,
.rename = v9fs_vfs_rename,
.getattr = v9fs_vfs_getattr,
.setattr = v9fs_vfs_setattr,
};
static struct inode_operations v9fs_file_inode_operations = { static struct inode_operations v9fs_file_inode_operations = {
.getattr = v9fs_vfs_getattr, .getattr = v9fs_vfs_getattr,
.setattr = v9fs_vfs_setattr, .setattr = v9fs_vfs_setattr,
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment