aboutsummaryrefslogtreecommitdiffstats
path: root/fs/cifs/inode.c
diff options
context:
space:
mode:
authorSteve French <sfrench@us.ibm.com>2008-12-05 14:14:12 -0500
committerSteve French <sfrench@us.ibm.com>2008-12-25 21:29:11 -0500
commit8be0ed44c2fa4afcf2c6d2fb3102c926e9f989df (patch)
treed0d003c8c9f12b865f0bf8f2015134d7b7031ee5 /fs/cifs/inode.c
parent61e748015866e48aff91284e3d300c6e3035a87a (diff)
[CIFS] Can not mount with prefixpath if root directory of share is inaccessible
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>
Diffstat (limited to 'fs/cifs/inode.c')
-rw-r--r--fs/cifs/inode.c58
1 files changed, 53 insertions, 5 deletions
diff --git a/fs/cifs/inode.c b/fs/cifs/inode.c
index ff8c68de4a92..b8821b0e73de 100644
--- a/fs/cifs/inode.c
+++ b/fs/cifs/inode.c
@@ -1,7 +1,7 @@
1/* 1/*
2 * fs/cifs/inode.c 2 * fs/cifs/inode.c
3 * 3 *
4 * Copyright (C) International Business Machines Corp., 2002,2007 4 * Copyright (C) International Business Machines Corp., 2002,2008
5 * Author(s): Steve French (sfrench@us.ibm.com) 5 * Author(s): Steve French (sfrench@us.ibm.com)
6 * 6 *
7 * This library is free software; you can redistribute it and/or modify 7 * This library is free software; you can redistribute it and/or modify
@@ -621,6 +621,47 @@ static const struct inode_operations cifs_ipc_inode_ops = {
621 .lookup = cifs_lookup, 621 .lookup = cifs_lookup,
622}; 622};
623 623
624static char *build_path_to_root(struct cifs_sb_info *cifs_sb)
625{
626 int pplen = cifs_sb->prepathlen;
627 int dfsplen;
628 char *full_path = NULL;
629
630 /* if no prefix path, simply set path to the root of share to "" */
631 if (pplen == 0) {
632 full_path = kmalloc(1, GFP_KERNEL);
633 if (full_path)
634 full_path[0] = 0;
635 return full_path;
636 }
637
638 if (cifs_sb->tcon && (cifs_sb->tcon->Flags & SMB_SHARE_IS_IN_DFS))
639 dfsplen = strnlen(cifs_sb->tcon->treeName, MAX_TREE_SIZE + 1);
640 else
641 dfsplen = 0;
642
643 full_path = kmalloc(dfsplen + pplen + 1, GFP_KERNEL);
644 if (full_path == NULL)
645 return full_path;
646
647 if (dfsplen) {
648 strncpy(full_path, cifs_sb->tcon->treeName, dfsplen);
649 /* switch slash direction in prepath depending on whether
650 * windows or posix style path names
651 */
652 if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_POSIX_PATHS) {
653 int i;
654 for (i = 0; i < dfsplen; i++) {
655 if (full_path[i] == '\\')
656 full_path[i] = '/';
657 }
658 }
659 }
660 strncpy(full_path + dfsplen, cifs_sb->prepath, pplen);
661 full_path[dfsplen + pplen] = 0; /* add trailing null */
662 return full_path;
663}
664
624/* gets root inode */ 665/* gets root inode */
625struct inode *cifs_iget(struct super_block *sb, unsigned long ino) 666struct inode *cifs_iget(struct super_block *sb, unsigned long ino)
626{ 667{
@@ -628,6 +669,7 @@ struct inode *cifs_iget(struct super_block *sb, unsigned long ino)
628 struct cifs_sb_info *cifs_sb; 669 struct cifs_sb_info *cifs_sb;
629 struct inode *inode; 670 struct inode *inode;
630 long rc; 671 long rc;
672 char *full_path;
631 673
632 inode = iget_locked(sb, ino); 674 inode = iget_locked(sb, ino);
633 if (!inode) 675 if (!inode)
@@ -636,13 +678,17 @@ struct inode *cifs_iget(struct super_block *sb, unsigned long ino)
636 return inode; 678 return inode;
637 679
638 cifs_sb = CIFS_SB(inode->i_sb); 680 cifs_sb = CIFS_SB(inode->i_sb);
639 xid = GetXid(); 681 full_path = build_path_to_root(cifs_sb);
682 if (full_path == NULL)
683 return ERR_PTR(-ENOMEM);
640 684
685 xid = GetXid();
641 if (cifs_sb->tcon->unix_ext) 686 if (cifs_sb->tcon->unix_ext)
642 rc = cifs_get_inode_info_unix(&inode, "", inode->i_sb, xid); 687 rc = cifs_get_inode_info_unix(&inode, full_path, inode->i_sb,
688 xid);
643 else 689 else
644 rc = cifs_get_inode_info(&inode, "", NULL, inode->i_sb, xid, 690 rc = cifs_get_inode_info(&inode, full_path, NULL, inode->i_sb,
645 NULL); 691 xid, NULL);
646 if (rc && cifs_sb->tcon->ipc) { 692 if (rc && cifs_sb->tcon->ipc) {
647 cFYI(1, ("ipc connection - fake read inode")); 693 cFYI(1, ("ipc connection - fake read inode"));
648 inode->i_mode |= S_IFDIR; 694 inode->i_mode |= S_IFDIR;
@@ -652,6 +698,7 @@ struct inode *cifs_iget(struct super_block *sb, unsigned long ino)
652 inode->i_uid = cifs_sb->mnt_uid; 698 inode->i_uid = cifs_sb->mnt_uid;
653 inode->i_gid = cifs_sb->mnt_gid; 699 inode->i_gid = cifs_sb->mnt_gid;
654 } else if (rc) { 700 } else if (rc) {
701 kfree(full_path);
655 _FreeXid(xid); 702 _FreeXid(xid);
656 iget_failed(inode); 703 iget_failed(inode);
657 return ERR_PTR(rc); 704 return ERR_PTR(rc);
@@ -659,6 +706,7 @@ struct inode *cifs_iget(struct super_block *sb, unsigned long ino)
659 706
660 unlock_new_inode(inode); 707 unlock_new_inode(inode);
661 708
709 kfree(full_path);
662 /* can not call macro FreeXid here since in a void func 710 /* can not call macro FreeXid here since in a void func
663 * TODO: This is no longer true 711 * TODO: This is no longer true
664 */ 712 */