Commit 1a5cf580 authored by Andrew Morton's avatar Andrew Morton Committed by Greg Kroah-Hartman

[PATCH] workaround for smb_proc_getattr oops

From: Zwane Mwaikambo <zwane@linuxpower.ca>

smbfs tends to oops over a null server->ops->getattr in smb_proc_getattr().

Urban says:

 In 2.5 the server->ops is initialized when smbfs gets a connection, to
 match whatever the server is capable of or not. This happens after the
 mount syscall so smbfs is then mounted but not usable.

 Not sure if smb_lookup is always called before any other operation that
 uses server->ops. If it is then it would be enough to have a test there.

 Otherwise I will just change all users of server->ops to verify the
 pointer first and return -EIO or something.

Al Viro says (paraphrasing)

 ugh, we need mount2().

It doesn't look to me like we'll be getting mount2() in the 2.6 timeframe.
Zwane's patch implement's Urban's workaround.
parent 06171a48
...@@ -526,6 +526,7 @@ int smb_fill_super(struct super_block *sb, void *raw_data, int silent) ...@@ -526,6 +526,7 @@ int smb_fill_super(struct super_block *sb, void *raw_data, int silent)
goto out_no_mem; goto out_no_mem;
server->ops = mem; server->ops = mem;
smb_install_null_ops(server->ops);
server->mnt = mem + sizeof(struct smb_ops); server->mnt = mem + sizeof(struct smb_ops);
/* Setup NLS stuff */ /* Setup NLS stuff */
......
...@@ -2802,6 +2802,13 @@ smb_proc_getattr_95(struct smb_sb_info *server, struct dentry *dir, ...@@ -2802,6 +2802,13 @@ smb_proc_getattr_95(struct smb_sb_info *server, struct dentry *dir,
return result; return result;
} }
static int
smb_proc_getattr_null(struct smb_sb_info *server, struct dentry *dir,
struct smb_fattr *attr)
{
return -EIO;
}
int int
smb_proc_getattr(struct dentry *dir, struct smb_fattr *fattr) smb_proc_getattr(struct dentry *dir, struct smb_fattr *fattr)
{ {
...@@ -3429,3 +3436,14 @@ static struct smb_ops smb_ops_unix = ...@@ -3429,3 +3436,14 @@ static struct smb_ops smb_ops_unix =
/* .setattr = smb_proc_setattr_unix, */ /* .setattr = smb_proc_setattr_unix, */
.truncate = smb_proc_trunc64, .truncate = smb_proc_trunc64,
}; };
/* Place holder until real ops are in place */
static struct smb_ops smb_ops_null =
{
.getattr = smb_proc_getattr_null,
};
void smb_install_null_ops(struct smb_ops *ops)
{
install_ops(ops, &smb_ops_null);
}
...@@ -198,7 +198,7 @@ smb_is_open(struct inode *i) ...@@ -198,7 +198,7 @@ smb_is_open(struct inode *i)
return (SMB_I(i)->open == server_from_inode(i)->generation); return (SMB_I(i)->open == server_from_inode(i)->generation);
} }
extern void smb_install_null_ops(struct smb_ops *);
#endif /* __KERNEL__ */ #endif /* __KERNEL__ */
#endif /* _LINUX_SMB_FS_H */ #endif /* _LINUX_SMB_FS_H */
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