Re: [PATCH] cifs: Allow mounts for paths for restricted intermediate paths

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



2013/11/19 Shirish Pargaonkar <shirishpargaonkar@xxxxxxxxx>:
> Pavel, Thanks, yes, 8950.
>
> Regards,
>
> Shirish
>
> On Tue, Nov 19, 2013 at 11:54 AM, Pavel Shilovsky <piastryyy@xxxxxxxxx> wrote:
>> 2013/11/19  <shirishpargaonkar@xxxxxxxxx>:
>>> From: Shirish Pargaonkar <shirishpargaonkar@xxxxxxxxx>
>>>
>>>
>>> Allow cifs mounts for a prefixpath with intermediate paths without access,
>>> so as to continue with the shared superblock model.
>>>
>>> For the intermediate path entries that do not allow access, create "placeholder"
>>> inodes and instantiate dentries with those inodes.
>>> If and when such a path entry becomes accessible it is filled with correct
>>> info.
>>>
>>> Reference: Samba bugzilla 6950
>>
>> I thinks it's 8950.
>>
>>>
>>> Signed-off-by: Shirish Pargaonkar <spargaonkar@xxxxxxxx>
>>>
>>> ---
>>>  fs/cifs/cifsfs.c    | 17 +++++++++++++++--
>>>  fs/cifs/cifsproto.h |  3 +++
>>>  fs/cifs/inode.c     | 16 ++++++++++++++++
>>>  3 files changed, 34 insertions(+), 2 deletions(-)
>>>
>>> diff --git a/fs/cifs/cifsfs.c b/fs/cifs/cifsfs.c
>>> index 849f613..bce185c 100644
>>> --- a/fs/cifs/cifsfs.c
>>> +++ b/fs/cifs/cifsfs.c
>>> @@ -584,6 +584,9 @@ cifs_get_root(struct smb_vol *vol, struct super_block *sb)
>>>         char *full_path = NULL;
>>>         char *s, *p;
>>>         char sep;
>>> +       struct inode *dir, *phinode;
>>> +       struct dentry *child;
>>> +       struct cifs_fattr phfattr;
>>>
>>>         full_path = cifs_build_path_to_root(vol, cifs_sb,
>>>                                             cifs_sb_master_tcon(cifs_sb));
>>> @@ -592,13 +595,13 @@ cifs_get_root(struct smb_vol *vol, struct super_block *sb)
>>>
>>>         cifs_dbg(FYI, "Get root dentry for %s\n", full_path);
>>>
>>> +       fill_phfattr(&phfattr, sb);
>>>         sep = CIFS_DIR_SEP(cifs_sb);
>>>         dentry = dget(sb->s_root);
>>>         p = s = full_path;
>>>
>>>         do {
>>> -               struct inode *dir = dentry->d_inode;
>>> -               struct dentry *child;
>>> +               dir = dentry->d_inode;
>>>
>>>                 if (!dir) {
>>>                         dput(dentry);
>>> @@ -626,6 +629,16 @@ cifs_get_root(struct smb_vol *vol, struct super_block *sb)
>>>                 mutex_unlock(&dir->i_mutex);
>>>                 dput(dentry);
>>>                 dentry = child;
>>> +               if (!IS_ERR(dentry)) {
>>> +                       if (*s) {
>>> +                               /* EACCESS on an intermediate dir */
>>> +                               if (!dentry->d_inode) {
>>> +                                       phinode = cifs_iget(sb, &phfattr);
>>> +                                       if (phinode)
>>> +                                               d_instantiate(dentry, phinode);
>>> +                               }
>>> +                       }
>>> +               }
>>>         } while (!IS_ERR(dentry));
>>>         kfree(full_path);
>>>         return dentry;
>>> diff --git a/fs/cifs/cifsproto.h b/fs/cifs/cifsproto.h
>>> index aa33976..9a84e5c 100644
>>> --- a/fs/cifs/cifsproto.h
>>> +++ b/fs/cifs/cifsproto.h
>>> @@ -498,4 +498,7 @@ void cifs_writedata_release(struct kref *refcount);
>>>  int open_query_close_cifs_symlink(const unsigned char *path, char *pbuf,
>>>                         unsigned int *pbytes_read, struct cifs_sb_info *cifs_sb,
>>>                         unsigned int xid);
>>> +
>>> +extern void fill_phfattr(struct cifs_fattr *, struct super_block *);
>>> +
>>>  #endif                 /* _CIFSPROTO_H */
>>> diff --git a/fs/cifs/inode.c b/fs/cifs/inode.c
>>> index 36f9ebb..4f5a09a 100644
>>> --- a/fs/cifs/inode.c
>>> +++ b/fs/cifs/inode.c
>>> @@ -322,6 +322,22 @@ cifs_create_dfs_fattr(struct cifs_fattr *fattr, struct super_block *sb)
>>>         fattr->cf_flags |= CIFS_FATTR_DFS_REFERRAL;
>>>  }
>>>
>>> +void
>>> +fill_phfattr(struct cifs_fattr *cf, struct super_block *sb)
>>> +{
>>> +       struct cifs_sb_info *cifs_sb = CIFS_SB(sb);
>>> +
>>> +       memset(cf, 0, sizeof(*cf));
>>> +       cf->cf_uniqueid = iunique(sb, ROOT_I);
>>> +       cf->cf_nlink = 1;
>>> +       cf->cf_atime = CURRENT_TIME;
>>> +       cf->cf_ctime = CURRENT_TIME;
>>> +       cf->cf_mtime = CURRENT_TIME;
>>> +       cf->cf_mode = S_IFDIR | S_IXUGO | S_IRWXU;
>>> +       cf->cf_uid = cifs_sb->mnt_uid;
>>> +       cf->cf_gid = cifs_sb->mnt_gid;
>>> +}
>>> +
>>>  static int
>>>  cifs_get_file_info_unix(struct file *filp)
>>>  {
>>> --
>>> 1.8.3.2
>>>
>>> --
>>> To unsubscribe from this list: send the line "unsubscribe linux-cifs" in
>>> the body of a message to majordomo@xxxxxxxxxxxxxxx
>>> More majordomo info at  http://vger.kernel.org/majordomo-info.html
>>
>> Looks ok at the first glance - will test further.
>>
>> --
>> Best regards,
>> Pavel Shilovsky.

I tested it with the following setup:

//server/share/dir/dir1/dir2

The user has a full access to //server/share and
//server/share/dir/dir1/dir2 and not to //server/share/dir and
//server/share/dir1. The mount of //server/share/dir/dir1/dir2 failed
whenever the patch is applied or not (3.12 kernel is used). I checked
it and found out that lookup_one_len returned EACCESS pointer but your
patch works for the case when negative dentry is returned.

-- 
Best regards,
Pavel Shilovsky.
--
To unsubscribe from this list: send the line "unsubscribe linux-cifs" in
the body of a message to majordomo@xxxxxxxxxxxxxxx
More majordomo info at  http://vger.kernel.org/majordomo-info.html




[Linux USB Devel]     [Video for Linux]     [Linux Audio Users]     [Yosemite News]     [Linux Kernel]     [Linux SCSI]

  Powered by Linux