mirror of
https://github.com/torvalds/linux.git
synced 2024-11-28 07:01:32 +00:00
[CIFS] Prevent OOPs when mounting with remote prefixpath.
Fixes OOPs with message 'kernel BUG at fs/cifs/cifs_dfs_ref.c:274!'. Checks if the prefixpath in an accesible while we are still in cifs_mount and fails with reporting a error if we can't access the prefixpath Should fix Samba bugs 6086 and 5861 and kernel bug 12192 Signed-off-by: Igor Mammedov <niallain@gmail.com> Acked-by: Jeff Layton <jlayton@redhat.com> Signed-off-by: Steve French <sfrench@us.ibm.com>
This commit is contained in:
parent
e1f81c8a41
commit
e4cce94c9c
@ -42,6 +42,7 @@ extern void _FreeXid(unsigned int);
|
||||
#define GetXid() (int)_GetXid(); cFYI(1,("CIFS VFS: in %s as Xid: %d with uid: %d",__func__, xid,current_fsuid()));
|
||||
#define FreeXid(curr_xid) {_FreeXid(curr_xid); cFYI(1,("CIFS VFS: leaving %s (xid = %d) rc = %d",__func__,curr_xid,(int)rc));}
|
||||
extern char *build_path_from_dentry(struct dentry *);
|
||||
extern char *cifs_build_path_to_root(struct cifs_sb_info *cifs_sb);
|
||||
extern char *build_wildcard_path_from_dentry(struct dentry *direntry);
|
||||
/* extern void renew_parental_timestamps(struct dentry *direntry);*/
|
||||
extern int SendReceive(const unsigned int /* xid */ , struct cifsSesInfo *,
|
||||
|
@ -2180,6 +2180,33 @@ static void setup_cifs_sb(struct smb_vol *pvolume_info,
|
||||
"mount option supported"));
|
||||
}
|
||||
|
||||
static int
|
||||
is_path_accessible(int xid, struct cifsTconInfo *tcon,
|
||||
struct cifs_sb_info *cifs_sb, const char *full_path)
|
||||
{
|
||||
int rc;
|
||||
__u64 inode_num;
|
||||
FILE_ALL_INFO *pfile_info;
|
||||
|
||||
rc = CIFSGetSrvInodeNumber(xid, tcon, full_path, &inode_num,
|
||||
cifs_sb->local_nls,
|
||||
cifs_sb->mnt_cifs_flags &
|
||||
CIFS_MOUNT_MAP_SPECIAL_CHR);
|
||||
if (rc != -EOPNOTSUPP)
|
||||
return rc;
|
||||
|
||||
pfile_info = kmalloc(sizeof(FILE_ALL_INFO), GFP_KERNEL);
|
||||
if (pfile_info == NULL)
|
||||
return -ENOMEM;
|
||||
|
||||
rc = CIFSSMBQPathInfo(xid, tcon, full_path, pfile_info,
|
||||
0 /* not legacy */, cifs_sb->local_nls,
|
||||
cifs_sb->mnt_cifs_flags &
|
||||
CIFS_MOUNT_MAP_SPECIAL_CHR);
|
||||
kfree(pfile_info);
|
||||
return rc;
|
||||
}
|
||||
|
||||
int
|
||||
cifs_mount(struct super_block *sb, struct cifs_sb_info *cifs_sb,
|
||||
char *mount_data, const char *devname)
|
||||
@ -2190,6 +2217,7 @@ cifs_mount(struct super_block *sb, struct cifs_sb_info *cifs_sb,
|
||||
struct cifsSesInfo *pSesInfo = NULL;
|
||||
struct cifsTconInfo *tcon = NULL;
|
||||
struct TCP_Server_Info *srvTcp = NULL;
|
||||
char *full_path;
|
||||
|
||||
xid = GetXid();
|
||||
|
||||
@ -2426,6 +2454,23 @@ mount_fail_check:
|
||||
cifs_sb->rsize = min(cifs_sb->rsize,
|
||||
(tcon->ses->server->maxBuf - MAX_CIFS_HDR_SIZE));
|
||||
|
||||
if (!rc && cifs_sb->prepathlen) {
|
||||
/* build_path_to_root works only when we have a valid tcon */
|
||||
full_path = cifs_build_path_to_root(cifs_sb);
|
||||
if (full_path == NULL) {
|
||||
rc = -ENOMEM;
|
||||
goto mount_fail_check;
|
||||
}
|
||||
rc = is_path_accessible(xid, tcon, cifs_sb, full_path);
|
||||
if (rc) {
|
||||
cERROR(1, ("Path %s in not accessible: %d",
|
||||
full_path, rc));
|
||||
kfree(full_path);
|
||||
goto mount_fail_check;
|
||||
}
|
||||
kfree(full_path);
|
||||
}
|
||||
|
||||
/* volume_info->password is freed above when existing session found
|
||||
(in which case it is not needed anymore) but when new sesion is created
|
||||
the password ptr is put in the new session structure (in which case the
|
||||
|
@ -621,7 +621,7 @@ static const struct inode_operations cifs_ipc_inode_ops = {
|
||||
.lookup = cifs_lookup,
|
||||
};
|
||||
|
||||
static char *build_path_to_root(struct cifs_sb_info *cifs_sb)
|
||||
char *cifs_build_path_to_root(struct cifs_sb_info *cifs_sb)
|
||||
{
|
||||
int pplen = cifs_sb->prepathlen;
|
||||
int dfsplen;
|
||||
@ -678,7 +678,7 @@ struct inode *cifs_iget(struct super_block *sb, unsigned long ino)
|
||||
return inode;
|
||||
|
||||
cifs_sb = CIFS_SB(inode->i_sb);
|
||||
full_path = build_path_to_root(cifs_sb);
|
||||
full_path = cifs_build_path_to_root(cifs_sb);
|
||||
if (full_path == NULL)
|
||||
return ERR_PTR(-ENOMEM);
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user