Re: [PATCH 10/15] cifs: have find_readable/writable_file filter by fsuid

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

 



This one looked ok (other than the earlier comment that
the series is bigger change than I expected).

On Mon, Sep 20, 2010 at 6:01 PM, Jeff Layton <jlayton@xxxxxxxxxx> wrote:
> When we implement multiuser mounts, we'll need to filter filehandles
> by fsuid. Add a flag for multiuser mounts and code to filter by
> fsuid when it's set.
>
> Signed-off-by: Jeff Layton <jlayton@xxxxxxxxxx>
> ---
>  fs/cifs/cifs_fs_sb.h |    3 ++-
>  fs/cifs/cifsacl.c    |    4 ++--
>  fs/cifs/cifsproto.h  |    4 ++--
>  fs/cifs/dir.c        |    1 +
>  fs/cifs/file.c       |   30 +++++++++++++++++++++++-------
>  fs/cifs/inode.c      |    6 +++---
>  6 files changed, 33 insertions(+), 15 deletions(-)
>
> diff --git a/fs/cifs/cifs_fs_sb.h b/fs/cifs/cifs_fs_sb.h
> index ba0afd3..e04e692 100644
> --- a/fs/cifs/cifs_fs_sb.h
> +++ b/fs/cifs/cifs_fs_sb.h
> @@ -37,6 +37,7 @@
>  #define CIFS_MOUNT_NOSSYNC      0x4000 /* don't do slow SMBflush on every sync*/
>  #define CIFS_MOUNT_FSCACHE     0x8000 /* local caching enabled */
>  #define CIFS_MOUNT_MF_SYMLINKS 0x10000 /* Minshall+French Symlinks enabled */
> +#define CIFS_MOUNT_MULTIUSER   0x20000 /* multiuser mount */
>
>  struct cifs_sb_info {
>        struct cifsTconInfo *ptcon;     /* primary mount */
> @@ -48,7 +49,7 @@ struct cifs_sb_info {
>        gid_t   mnt_gid;
>        mode_t  mnt_file_mode;
>        mode_t  mnt_dir_mode;
> -       int     mnt_cifs_flags;
> +       unsigned int mnt_cifs_flags;
>        int     prepathlen;
>        char   *prepath; /* relative path under the share to mount to */
>  #ifdef CONFIG_CIFS_DFS_UPCALL
> diff --git a/fs/cifs/cifsacl.c b/fs/cifs/cifsacl.c
> index 2647ea4..c9b4792 100644
> --- a/fs/cifs/cifsacl.c
> +++ b/fs/cifs/cifsacl.c
> @@ -615,7 +615,7 @@ static struct cifs_ntsd *get_cifs_acl(struct cifs_sb_info *cifs_sb,
>        struct cifsFileInfo *open_file = NULL;
>
>        if (inode)
> -               open_file = find_readable_file(CIFS_I(inode));
> +               open_file = find_readable_file(CIFS_I(inode), true);
>        if (!open_file)
>                return get_cifs_acl_by_path(cifs_sb, path, pacllen);
>
> @@ -685,7 +685,7 @@ static int set_cifs_acl(struct cifs_ntsd *pnntsd, __u32 acllen,
>
>        cFYI(DBG2, "set ACL for %s from mode 0x%x", path, inode->i_mode);
>
> -       open_file = find_readable_file(CIFS_I(inode));
> +       open_file = find_readable_file(CIFS_I(inode), true);
>        if (!open_file)
>                return set_cifs_acl_by_path(cifs_sb, path, pnntsd, acllen);
>
> diff --git a/fs/cifs/cifsproto.h b/fs/cifs/cifsproto.h
> index 18ee991..0e76b20 100644
> --- a/fs/cifs/cifsproto.h
> +++ b/fs/cifs/cifsproto.h
> @@ -78,9 +78,9 @@ extern int checkSMB(struct smb_hdr *smb, __u16 mid, unsigned int length);
>  extern bool is_valid_oplock_break(struct smb_hdr *smb,
>                                  struct TCP_Server_Info *);
>  extern bool is_size_safe_to_change(struct cifsInodeInfo *, __u64 eof);
> -extern struct cifsFileInfo *find_writable_file(struct cifsInodeInfo *);
> +extern struct cifsFileInfo *find_writable_file(struct cifsInodeInfo *, bool);
>  #ifdef CONFIG_CIFS_EXPERIMENTAL
> -extern struct cifsFileInfo *find_readable_file(struct cifsInodeInfo *);
> +extern struct cifsFileInfo *find_readable_file(struct cifsInodeInfo *, bool);
>  #endif
>  extern unsigned int smbCalcSize(struct smb_hdr *ptr);
>  extern unsigned int smbCalcSize_LE(struct smb_hdr *ptr);
> diff --git a/fs/cifs/dir.c b/fs/cifs/dir.c
> index 5adf47f..e249b56 100644
> --- a/fs/cifs/dir.c
> +++ b/fs/cifs/dir.c
> @@ -144,6 +144,7 @@ cifs_new_fileinfo(struct inode *newinode, __u16 fileHandle, struct file *file,
>
>        pCifsFile->netfid = fileHandle;
>        pCifsFile->pid = current->tgid;
> +       pCifsFile->uid = current_fsuid();
>        pCifsFile->pInode = igrab(newinode);
>        pCifsFile->mnt = mnt;
>        pCifsFile->pfile = file;
> diff --git a/fs/cifs/file.c b/fs/cifs/file.c
> index 023d348..d9b8652 100644
> --- a/fs/cifs/file.c
> +++ b/fs/cifs/file.c
> @@ -1168,9 +1168,15 @@ static ssize_t cifs_write(struct file *file, const char *write_data,
>  }
>
>  #ifdef CONFIG_CIFS_EXPERIMENTAL
> -struct cifsFileInfo *find_readable_file(struct cifsInodeInfo *cifs_inode)
> +struct cifsFileInfo *find_readable_file(struct cifsInodeInfo *cifs_inode,
> +                                       bool fsuid_only)
>  {
>        struct cifsFileInfo *open_file = NULL;
> +       struct cifs_sb_info *cifs_sb = CIFS_SB(cifs_inode->vfs_inode.i_sb);
> +
> +       /* only filter by fsuid on multiuser mounts */
> +       if (!(cifs_sb->mnt_cifs_flags & CIFS_MOUNT_MULTIUSER))
> +               fsuid_only = false;
>
>        read_lock(&GlobalSMBSeslock);
>        /* we could simply get the first_list_entry since write-only entries
> @@ -1179,6 +1185,8 @@ struct cifsFileInfo *find_readable_file(struct cifsInodeInfo *cifs_inode)
>        list_for_each_entry(open_file, &cifs_inode->openFileList, flist) {
>                if (open_file->closePend)
>                        continue;
> +               if (fsuid_only && open_file->uid != current_fsuid())
> +                       continue;
>                if (open_file->pfile && ((open_file->pfile->f_flags & O_RDWR) ||
>                    (open_file->pfile->f_flags & O_RDONLY))) {
>                        if (!open_file->invalidHandle) {
> @@ -1198,9 +1206,11 @@ struct cifsFileInfo *find_readable_file(struct cifsInodeInfo *cifs_inode)
>  }
>  #endif
>
> -struct cifsFileInfo *find_writable_file(struct cifsInodeInfo *cifs_inode)
> +struct cifsFileInfo *find_writable_file(struct cifsInodeInfo *cifs_inode,
> +                                       bool fsuid_only)
>  {
>        struct cifsFileInfo *open_file;
> +       struct cifs_sb_info *cifs_sb = CIFS_SB(cifs_inode->vfs_inode.i_sb);
>        bool any_available = false;
>        int rc;
>
> @@ -1214,13 +1224,19 @@ struct cifsFileInfo *find_writable_file(struct cifsInodeInfo *cifs_inode)
>                return NULL;
>        }
>
> +       /* only filter by fsuid on multiuser mounts */
> +       if (!(cifs_sb->mnt_cifs_flags & CIFS_MOUNT_MULTIUSER))
> +               fsuid_only = false;
> +
>        read_lock(&GlobalSMBSeslock);
>  refind_writable:
>        list_for_each_entry(open_file, &cifs_inode->openFileList, flist) {
> -               if (open_file->closePend ||
> -                   (!any_available && open_file->pid != current->tgid))
> +               if (open_file->closePend)
> +                       continue;
> +               if (!any_available && open_file->pid != current->tgid)
> +                       continue;
> +               if (fsuid_only && open_file->uid != current_fsuid())
>                        continue;
> -
>                if (open_file->pfile &&
>                    ((open_file->pfile->f_flags & O_RDWR) ||
>                     (open_file->pfile->f_flags & O_WRONLY))) {
> @@ -1315,7 +1331,7 @@ static int cifs_partialpagewrite(struct page *page, unsigned from, unsigned to)
>        if (mapping->host->i_size - offset < (loff_t)to)
>                to = (unsigned)(mapping->host->i_size - offset);
>
> -       open_file = find_writable_file(CIFS_I(mapping->host));
> +       open_file = find_writable_file(CIFS_I(mapping->host), false);
>        if (open_file) {
>                bytes_written = cifs_write(open_file->pfile, write_data,
>                                           to-from, &offset);
> @@ -1388,7 +1404,7 @@ static int cifs_writepages(struct address_space *mapping,
>         * but it'll at least handle the return. Maybe it should be
>         * a BUG() instead?
>         */
> -       open_file = find_writable_file(CIFS_I(mapping->host));
> +       open_file = find_writable_file(CIFS_I(mapping->host), false);
>        if (!open_file) {
>                kfree(iov);
>                return generic_writepages(mapping, wbc);
> diff --git a/fs/cifs/inode.c b/fs/cifs/inode.c
> index cca0d52..dcd0886 100644
> --- a/fs/cifs/inode.c
> +++ b/fs/cifs/inode.c
> @@ -969,7 +969,7 @@ cifs_set_file_info(struct inode *inode, struct iattr *attrs, int xid,
>        /*
>         * If the file is already open for write, just use that fileid
>         */
> -       open_file = find_writable_file(cifsInode);
> +       open_file = find_writable_file(cifsInode, true);
>        if (open_file) {
>                netfid = open_file->netfid;
>                netpid = open_file->pid;
> @@ -1819,7 +1819,7 @@ cifs_set_file_size(struct inode *inode, struct iattr *attrs,
>         * writebehind data than the SMB timeout for the SetPathInfo
>         * request would allow
>         */
> -       open_file = find_writable_file(cifsInode);
> +       open_file = find_writable_file(cifsInode, true);
>        if (open_file) {
>                __u16 nfid = open_file->netfid;
>                __u32 npid = open_file->pid;
> @@ -1984,7 +1984,7 @@ cifs_setattr_unix(struct dentry *direntry, struct iattr *attrs)
>                args->ctime = NO_CHANGE_64;
>
>        args->device = 0;
> -       open_file = find_writable_file(cifsInode);
> +       open_file = find_writable_file(cifsInode, true);
>        if (open_file) {
>                u16 nfid = open_file->netfid;
>                u32 npid = open_file->pid;
> --
> 1.7.2.3
>
>



-- 
Thanks,

Steve
--
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