summaryrefslogtreecommitdiff
path: root/fs/fuse/inode.c
diff options
context:
space:
mode:
Diffstat (limited to 'fs/fuse/inode.c')
-rw-r--r--fs/fuse/inode.c12
1 files changed, 11 insertions, 1 deletions
diff --git a/fs/fuse/inode.c b/fs/fuse/inode.c
index 951e760d5c5a..fd0735715c14 100644
--- a/fs/fuse/inode.c
+++ b/fs/fuse/inode.c
@@ -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);