if (fi->i_time < get_jiffies_64())
                err = fuse_do_getattr(inode);
 
-       if (!err)
+       if (!err) {
                generic_fillattr(inode, stat);
+               stat->mode = fi->orig_i_mode;
+       }
 
        return err;
 }
 
 
        /** Time in jiffies until the file attributes are valid */
        u64 i_time;
+
+       /** The sticky bit in inode->i_mode may have been removed, so
+           preserve the original mode */
+       mode_t orig_i_mode;
 };
 
 /** FUSE specific file data */
 
 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;
        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);