Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

[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: Eric Van Hensbergen <ericvh@gmail.com>
Signed-off-by: Andrew Morton <akpm@osdl.org>
Signed-off-by: Linus Torvalds <torvalds@osdl.org>

authored by

Eric Van Hensbergen and committed by
Linus Torvalds
b501611a 5d58bec5

+30 -5
+30 -5
fs/9p/vfs_inode.c
··· 44 44 #include "fid.h" 45 45 46 46 static struct inode_operations v9fs_dir_inode_operations; 47 + static struct inode_operations v9fs_dir_inode_operations_ext; 47 48 static struct inode_operations v9fs_file_inode_operations; 48 49 static struct inode_operations v9fs_symlink_inode_operations; 49 50 ··· 233 232 struct inode *v9fs_get_inode(struct super_block *sb, int mode) 234 233 { 235 234 struct inode *inode = NULL; 235 + struct v9fs_session_info *v9ses = sb->s_fs_info; 236 236 237 237 dprintk(DEBUG_VFS, "super block: %p mode: %o\n", sb, mode); 238 238 ··· 252 250 case S_IFBLK: 253 251 case S_IFCHR: 254 252 case S_IFSOCK: 253 + if(!v9ses->extended) { 254 + dprintk(DEBUG_ERROR, "special files without extended mode\n"); 255 + return ERR_PTR(-EINVAL); 256 + } 255 257 init_special_inode(inode, inode->i_mode, 256 258 inode->i_rdev); 257 259 break; ··· 263 257 inode->i_op = &v9fs_file_inode_operations; 264 258 inode->i_fop = &v9fs_file_operations; 265 259 break; 260 + case S_IFLNK: 261 + if(!v9ses->extended) { 262 + dprintk(DEBUG_ERROR, "extended modes used w/o 9P2000.u\n"); 263 + return ERR_PTR(-EINVAL); 264 + } 265 + inode->i_op = &v9fs_symlink_inode_operations; 266 + break; 266 267 case S_IFDIR: 267 268 inode->i_nlink++; 268 - inode->i_op = &v9fs_dir_inode_operations; 269 + if(v9ses->extended) 270 + inode->i_op = &v9fs_dir_inode_operations_ext; 271 + else 272 + inode->i_op = &v9fs_dir_inode_operations; 269 273 inode->i_fop = &v9fs_dir_operations; 270 - break; 271 - case S_IFLNK: 272 - inode->i_op = &v9fs_symlink_inode_operations; 273 274 break; 274 275 default: 275 276 dprintk(DEBUG_ERROR, "BAD mode 0x%x S_IFMT 0x%x\n", ··· 1297 1284 return retval; 1298 1285 } 1299 1286 1300 - static struct inode_operations v9fs_dir_inode_operations = { 1287 + static struct inode_operations v9fs_dir_inode_operations_ext = { 1301 1288 .create = v9fs_vfs_create, 1302 1289 .lookup = v9fs_vfs_lookup, 1303 1290 .symlink = v9fs_vfs_symlink, ··· 1308 1295 .mknod = v9fs_vfs_mknod, 1309 1296 .rename = v9fs_vfs_rename, 1310 1297 .readlink = v9fs_vfs_readlink, 1298 + .getattr = v9fs_vfs_getattr, 1299 + .setattr = v9fs_vfs_setattr, 1300 + }; 1301 + 1302 + static struct inode_operations v9fs_dir_inode_operations = { 1303 + .create = v9fs_vfs_create, 1304 + .lookup = v9fs_vfs_lookup, 1305 + .unlink = v9fs_vfs_unlink, 1306 + .mkdir = v9fs_vfs_mkdir, 1307 + .rmdir = v9fs_vfs_rmdir, 1308 + .mknod = v9fs_vfs_mknod, 1309 + .rename = v9fs_vfs_rename, 1311 1310 .getattr = v9fs_vfs_getattr, 1312 1311 .setattr = v9fs_vfs_setattr, 1313 1312 };