]> git.proxmox.com Git - mirror_ubuntu-zesty-kernel.git/blobdiff - fs/fuse/inode.c
fuse: fix permission checking on sticky directories
[mirror_ubuntu-zesty-kernel.git] / fs / fuse / inode.c
index 951e760d5c5a66d5b25bb4c5cd2dfcab23013805..fd0735715c14e7f1943c905cb104f101fac73139 100644 (file)
@@ -120,10 +120,11 @@ static void fuse_truncate(struct address_space *mapping, loff_t offset)
 void fuse_change_attributes(struct inode *inode, struct fuse_attr *attr)
 {
        struct fuse_conn *fc = get_fuse_conn(inode);
+       struct fuse_inode *fi = get_fuse_inode(inode);
        loff_t oldsize;
 
        inode->i_ino     = attr->ino;
-       inode->i_mode    = (inode->i_mode & S_IFMT) + (attr->mode & 07777);
+       inode->i_mode    = (inode->i_mode & S_IFMT) | (attr->mode & 07777);
        inode->i_nlink   = attr->nlink;
        inode->i_uid     = attr->uid;
        inode->i_gid     = attr->gid;
@@ -135,6 +136,15 @@ void fuse_change_attributes(struct inode *inode, struct fuse_attr *attr)
        inode->i_ctime.tv_sec   = attr->ctime;
        inode->i_ctime.tv_nsec  = attr->ctimensec;
 
+       /*
+        * Don't set the sticky bit in i_mode, unless we want the VFS
+        * to check permissions.  This prevents failures due to the
+        * check in may_delete().
+        */
+       fi->orig_i_mode = inode->i_mode;
+       if (!(fc->flags & FUSE_DEFAULT_PERMISSIONS))
+               inode->i_mode &= ~S_ISVTX;
+
        spin_lock(&fc->lock);
        oldsize = inode->i_size;
        i_size_write(inode, attr->size);