From 066ac19f6bf6490a6a145c25c39068b4c844dfdb Mon Sep 17 00:00:00 2001 From: Miklos Szeredi Date: Tue, 16 Oct 2007 23:31:03 -0700 Subject: [PATCH] --- yaml --- r: 70757 b: refs/heads/master c: ebc14c4dbeb56195950058db9aa32de06c22de0d h: refs/heads/master i: 70755: 3351dfefac48ce43a153f2728eefc4a148f6f0bf v: v3 --- [refs] | 2 +- trunk/fs/fuse/dir.c | 4 +++- trunk/fs/fuse/fuse_i.h | 4 ++++ trunk/fs/fuse/inode.c | 12 +++++++++++- 4 files changed, 19 insertions(+), 3 deletions(-) diff --git a/[refs] b/[refs] index 018acda5dd63..f42abb50f9a4 100644 --- a/[refs] +++ b/[refs] @@ -1,2 +1,2 @@ --- -refs/heads/master: 244f6385c2891e366a7de5f6746ccc257efd8952 +refs/heads/master: ebc14c4dbeb56195950058db9aa32de06c22de0d diff --git a/trunk/fs/fuse/dir.c b/trunk/fs/fuse/dir.c index 9ee2a6bbfa37..8ea4ea13ec5f 100644 --- a/trunk/fs/fuse/dir.c +++ b/trunk/fs/fuse/dir.c @@ -1054,8 +1054,10 @@ static int fuse_getattr(struct vfsmount *mnt, struct dentry *entry, 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; } diff --git a/trunk/fs/fuse/fuse_i.h b/trunk/fs/fuse/fuse_i.h index e0555d68b4a7..1764506fdd11 100644 --- a/trunk/fs/fuse/fuse_i.h +++ b/trunk/fs/fuse/fuse_i.h @@ -63,6 +63,10 @@ struct fuse_inode { /** 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 */ diff --git a/trunk/fs/fuse/inode.c b/trunk/fs/fuse/inode.c index 951e760d5c5a..fd0735715c14 100644 --- a/trunk/fs/fuse/inode.c +++ b/trunk/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);