Skip to content

Commit

Permalink
[CIFS] Can not mount with prefixpath if root directory of share is in…
Browse files Browse the repository at this point in the history
…accessible

Windows allows you to deny access to the top of a share, but permit access to
a directory lower in the path.  With the prefixpath feature of cifs
(ie mounting \\server\share\directory\subdirectory\etc.) this should have
worked if the user specified a prefixpath which put the root of the mount
at a directory to which he had access, but we still were doing a lookup
on the root of the share (null path) when we should have been doing it on
the prefixpath subdirectory.

This fixes Samba bug # 5925

Acked-by: Jeff Layton <jlayton@redhat.com>
Signed-off-by: Steve French <sfrench@us.ibm.com>
  • Loading branch information
Steve French committed Dec 26, 2008
1 parent 61e7480 commit 8be0ed4
Show file tree
Hide file tree
Showing 2 changed files with 56 additions and 6 deletions.
4 changes: 3 additions & 1 deletion fs/cifs/CHANGES
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,9 @@ Version 1.56
------------
Add "forcemandatorylock" mount option to allow user to use mandatory
rather than posix (advisory) byte range locks, even though server would
support posix byte range locks.
support posix byte range locks. Fix query of root inode when prefixpath
specified and user does not have access to query information about the
top of the share.

Version 1.55
------------
Expand Down
58 changes: 53 additions & 5 deletions fs/cifs/inode.c
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
/*
* fs/cifs/inode.c
*
* Copyright (C) International Business Machines Corp., 2002,2007
* Copyright (C) International Business Machines Corp., 2002,2008
* Author(s): Steve French (sfrench@us.ibm.com)
*
* This library is free software; you can redistribute it and/or modify
Expand Down Expand Up @@ -621,13 +621,55 @@ static const struct inode_operations cifs_ipc_inode_ops = {
.lookup = cifs_lookup,
};

static char *build_path_to_root(struct cifs_sb_info *cifs_sb)
{
int pplen = cifs_sb->prepathlen;
int dfsplen;
char *full_path = NULL;

/* if no prefix path, simply set path to the root of share to "" */
if (pplen == 0) {
full_path = kmalloc(1, GFP_KERNEL);
if (full_path)
full_path[0] = 0;
return full_path;
}

if (cifs_sb->tcon && (cifs_sb->tcon->Flags & SMB_SHARE_IS_IN_DFS))
dfsplen = strnlen(cifs_sb->tcon->treeName, MAX_TREE_SIZE + 1);
else
dfsplen = 0;

full_path = kmalloc(dfsplen + pplen + 1, GFP_KERNEL);
if (full_path == NULL)
return full_path;

if (dfsplen) {
strncpy(full_path, cifs_sb->tcon->treeName, dfsplen);
/* switch slash direction in prepath depending on whether
* windows or posix style path names
*/
if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_POSIX_PATHS) {
int i;
for (i = 0; i < dfsplen; i++) {
if (full_path[i] == '\\')
full_path[i] = '/';
}
}
}
strncpy(full_path + dfsplen, cifs_sb->prepath, pplen);
full_path[dfsplen + pplen] = 0; /* add trailing null */
return full_path;
}

/* gets root inode */
struct inode *cifs_iget(struct super_block *sb, unsigned long ino)
{
int xid;
struct cifs_sb_info *cifs_sb;
struct inode *inode;
long rc;
char *full_path;

inode = iget_locked(sb, ino);
if (!inode)
Expand All @@ -636,13 +678,17 @@ struct inode *cifs_iget(struct super_block *sb, unsigned long ino)
return inode;

cifs_sb = CIFS_SB(inode->i_sb);
xid = GetXid();
full_path = build_path_to_root(cifs_sb);
if (full_path == NULL)
return ERR_PTR(-ENOMEM);

xid = GetXid();
if (cifs_sb->tcon->unix_ext)
rc = cifs_get_inode_info_unix(&inode, "", inode->i_sb, xid);
rc = cifs_get_inode_info_unix(&inode, full_path, inode->i_sb,
xid);
else
rc = cifs_get_inode_info(&inode, "", NULL, inode->i_sb, xid,
NULL);
rc = cifs_get_inode_info(&inode, full_path, NULL, inode->i_sb,
xid, NULL);
if (rc && cifs_sb->tcon->ipc) {
cFYI(1, ("ipc connection - fake read inode"));
inode->i_mode |= S_IFDIR;
Expand All @@ -652,13 +698,15 @@ struct inode *cifs_iget(struct super_block *sb, unsigned long ino)
inode->i_uid = cifs_sb->mnt_uid;
inode->i_gid = cifs_sb->mnt_gid;
} else if (rc) {
kfree(full_path);
_FreeXid(xid);
iget_failed(inode);
return ERR_PTR(rc);
}

unlock_new_inode(inode);

kfree(full_path);
/* can not call macro FreeXid here since in a void func
* TODO: This is no longer true
*/
Expand Down

0 comments on commit 8be0ed4

Please sign in to comment.