diff options
author | Igor Mammedov <niallain@gmail.com> | 2009-02-10 14:10:26 +0300 |
---|---|---|
committer | Steve French <sfrench@us.ibm.com> | 2009-02-21 06:36:21 +0300 |
commit | e4cce94c9c8797b08faf6a79396df4d175e377fa (patch) | |
tree | 6eb306603652bf08ca10fef4f899332f30d71e09 /fs/cifs/connect.c | |
parent | e1f81c8a417be466e85a38b61679aa6860ec7331 (diff) | |
download | linux-e4cce94c9c8797b08faf6a79396df4d175e377fa.tar.xz |
[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>
Diffstat (limited to 'fs/cifs/connect.c')
-rw-r--r-- | fs/cifs/connect.c | 45 |
1 files changed, 45 insertions, 0 deletions
diff --git a/fs/cifs/connect.c b/fs/cifs/connect.c index 005df85219a8..da0f4ffa0613 100644 --- a/fs/cifs/connect.c +++ b/fs/cifs/connect.c @@ -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 |