Skip to content

Commit 7c46948

Browse files
committed
Merge tag 'fs.fuse.acl.v6.2-rc6' of git://git.kernel.org/pub/scm/linux/kernel/git/vfs/idmapping
Pull fuse ACL fix from Christian Brauner: "The new posix acl API doesn't depend on the xattr handler infrastructure anymore and instead only relies on the posix acl inode operations. As a result daemons without FUSE_POSIX_ACL are unable to use posix acls like they used to. Fix this by copying what we did for overlayfs during the posix acl api conversion. Make fuse implement a dedicated ->get_inode_acl() method as does overlayfs. Fuse can then also uses this to express different needs for vfs permission checking during lookup and acl based retrieval via the regular system call path. This allows fuse to continue to refuse retrieving posix acls for daemons that don't set FUSE_POSXI_ACL for permission checking while also allowing a fuse server to retrieve it via the usual system calls" * tag 'fs.fuse.acl.v6.2-rc6' of git://git.kernel.org/pub/scm/linux/kernel/git/vfs/idmapping: fuse: fixes after adapting to new posix acl api
2 parents 948ef7b + facd610 commit 7c46948

File tree

5 files changed

+78
-74
lines changed

5 files changed

+78
-74
lines changed

fs/fuse/acl.c

Lines changed: 61 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -11,9 +11,10 @@
1111
#include <linux/posix_acl.h>
1212
#include <linux/posix_acl_xattr.h>
1313

14-
struct posix_acl *fuse_get_acl(struct inode *inode, int type, bool rcu)
14+
static struct posix_acl *__fuse_get_acl(struct fuse_conn *fc,
15+
struct user_namespace *mnt_userns,
16+
struct inode *inode, int type, bool rcu)
1517
{
16-
struct fuse_conn *fc = get_fuse_conn(inode);
1718
int size;
1819
const char *name;
1920
void *value = NULL;
@@ -25,7 +26,7 @@ struct posix_acl *fuse_get_acl(struct inode *inode, int type, bool rcu)
2526
if (fuse_is_bad(inode))
2627
return ERR_PTR(-EIO);
2728

28-
if (!fc->posix_acl || fc->no_getxattr)
29+
if (fc->no_getxattr)
2930
return NULL;
3031

3132
if (type == ACL_TYPE_ACCESS)
@@ -53,6 +54,46 @@ struct posix_acl *fuse_get_acl(struct inode *inode, int type, bool rcu)
5354
return acl;
5455
}
5556

57+
static inline bool fuse_no_acl(const struct fuse_conn *fc,
58+
const struct inode *inode)
59+
{
60+
/*
61+
* Refuse interacting with POSIX ACLs for daemons that
62+
* don't support FUSE_POSIX_ACL and are not mounted on
63+
* the host to retain backwards compatibility.
64+
*/
65+
return !fc->posix_acl && (i_user_ns(inode) != &init_user_ns);
66+
}
67+
68+
struct posix_acl *fuse_get_acl(struct user_namespace *mnt_userns,
69+
struct dentry *dentry, int type)
70+
{
71+
struct inode *inode = d_inode(dentry);
72+
struct fuse_conn *fc = get_fuse_conn(inode);
73+
74+
if (fuse_no_acl(fc, inode))
75+
return ERR_PTR(-EOPNOTSUPP);
76+
77+
return __fuse_get_acl(fc, mnt_userns, inode, type, false);
78+
}
79+
80+
struct posix_acl *fuse_get_inode_acl(struct inode *inode, int type, bool rcu)
81+
{
82+
struct fuse_conn *fc = get_fuse_conn(inode);
83+
84+
/*
85+
* FUSE daemons before FUSE_POSIX_ACL was introduced could get and set
86+
* POSIX ACLs without them being used for permission checking by the
87+
* vfs. Retain that behavior for backwards compatibility as there are
88+
* filesystems that do all permission checking for acls in the daemon
89+
* and not in the kernel.
90+
*/
91+
if (!fc->posix_acl)
92+
return NULL;
93+
94+
return __fuse_get_acl(fc, &init_user_ns, inode, type, rcu);
95+
}
96+
5697
int fuse_set_acl(struct user_namespace *mnt_userns, struct dentry *dentry,
5798
struct posix_acl *acl, int type)
5899
{
@@ -64,7 +105,7 @@ int fuse_set_acl(struct user_namespace *mnt_userns, struct dentry *dentry,
64105
if (fuse_is_bad(inode))
65106
return -EIO;
66107

67-
if (!fc->posix_acl || fc->no_setxattr)
108+
if (fc->no_setxattr || fuse_no_acl(fc, inode))
68109
return -EOPNOTSUPP;
69110

70111
if (type == ACL_TYPE_ACCESS)
@@ -99,7 +140,13 @@ int fuse_set_acl(struct user_namespace *mnt_userns, struct dentry *dentry,
99140
return ret;
100141
}
101142

102-
if (!vfsgid_in_group_p(i_gid_into_vfsgid(&init_user_ns, inode)) &&
143+
/*
144+
* Fuse daemons without FUSE_POSIX_ACL never changed the passed
145+
* through POSIX ACLs. Such daemons don't expect setgid bits to
146+
* be stripped.
147+
*/
148+
if (fc->posix_acl &&
149+
!vfsgid_in_group_p(i_gid_into_vfsgid(&init_user_ns, inode)) &&
103150
!capable_wrt_inode_uidgid(&init_user_ns, inode, CAP_FSETID))
104151
extra_flags |= FUSE_SETXATTR_ACL_KILL_SGID;
105152

@@ -108,8 +155,15 @@ int fuse_set_acl(struct user_namespace *mnt_userns, struct dentry *dentry,
108155
} else {
109156
ret = fuse_removexattr(inode, name);
110157
}
111-
forget_all_cached_acls(inode);
112-
fuse_invalidate_attr(inode);
158+
159+
if (fc->posix_acl) {
160+
/*
161+
* Fuse daemons without FUSE_POSIX_ACL never cached POSIX ACLs
162+
* and didn't invalidate attributes. Retain that behavior.
163+
*/
164+
forget_all_cached_acls(inode);
165+
fuse_invalidate_attr(inode);
166+
}
113167

114168
return ret;
115169
}

fs/fuse/dir.c

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1942,7 +1942,8 @@ static const struct inode_operations fuse_dir_inode_operations = {
19421942
.permission = fuse_permission,
19431943
.getattr = fuse_getattr,
19441944
.listxattr = fuse_listxattr,
1945-
.get_inode_acl = fuse_get_acl,
1945+
.get_inode_acl = fuse_get_inode_acl,
1946+
.get_acl = fuse_get_acl,
19461947
.set_acl = fuse_set_acl,
19471948
.fileattr_get = fuse_fileattr_get,
19481949
.fileattr_set = fuse_fileattr_set,
@@ -1964,7 +1965,8 @@ static const struct inode_operations fuse_common_inode_operations = {
19641965
.permission = fuse_permission,
19651966
.getattr = fuse_getattr,
19661967
.listxattr = fuse_listxattr,
1967-
.get_inode_acl = fuse_get_acl,
1968+
.get_inode_acl = fuse_get_inode_acl,
1969+
.get_acl = fuse_get_acl,
19681970
.set_acl = fuse_set_acl,
19691971
.fileattr_get = fuse_fileattr_get,
19701972
.fileattr_set = fuse_fileattr_set,

fs/fuse/fuse_i.h

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1264,11 +1264,11 @@ ssize_t fuse_getxattr(struct inode *inode, const char *name, void *value,
12641264
ssize_t fuse_listxattr(struct dentry *entry, char *list, size_t size);
12651265
int fuse_removexattr(struct inode *inode, const char *name);
12661266
extern const struct xattr_handler *fuse_xattr_handlers[];
1267-
extern const struct xattr_handler *fuse_acl_xattr_handlers[];
1268-
extern const struct xattr_handler *fuse_no_acl_xattr_handlers[];
12691267

12701268
struct posix_acl;
1271-
struct posix_acl *fuse_get_acl(struct inode *inode, int type, bool rcu);
1269+
struct posix_acl *fuse_get_inode_acl(struct inode *inode, int type, bool rcu);
1270+
struct posix_acl *fuse_get_acl(struct user_namespace *mnt_userns,
1271+
struct dentry *dentry, int type);
12721272
int fuse_set_acl(struct user_namespace *mnt_userns, struct dentry *dentry,
12731273
struct posix_acl *acl, int type);
12741274

fs/fuse/inode.c

Lines changed: 10 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -311,7 +311,8 @@ void fuse_change_attributes(struct inode *inode, struct fuse_attr *attr,
311311
fuse_dax_dontcache(inode, attr->flags);
312312
}
313313

314-
static void fuse_init_inode(struct inode *inode, struct fuse_attr *attr)
314+
static void fuse_init_inode(struct inode *inode, struct fuse_attr *attr,
315+
struct fuse_conn *fc)
315316
{
316317
inode->i_mode = attr->mode & S_IFMT;
317318
inode->i_size = attr->size;
@@ -333,6 +334,12 @@ static void fuse_init_inode(struct inode *inode, struct fuse_attr *attr)
333334
new_decode_dev(attr->rdev));
334335
} else
335336
BUG();
337+
/*
338+
* Ensure that we don't cache acls for daemons without FUSE_POSIX_ACL
339+
* so they see the exact same behavior as before.
340+
*/
341+
if (!fc->posix_acl)
342+
inode->i_acl = inode->i_default_acl = ACL_DONT_CACHE;
336343
}
337344

338345
static int fuse_inode_eq(struct inode *inode, void *_nodeidp)
@@ -372,7 +379,7 @@ struct inode *fuse_iget(struct super_block *sb, u64 nodeid,
372379
if (!inode)
373380
return NULL;
374381

375-
fuse_init_inode(inode, attr);
382+
fuse_init_inode(inode, attr, fc);
376383
get_fuse_inode(inode)->nodeid = nodeid;
377384
inode->i_flags |= S_AUTOMOUNT;
378385
goto done;
@@ -388,7 +395,7 @@ struct inode *fuse_iget(struct super_block *sb, u64 nodeid,
388395
if (!fc->writeback_cache || !S_ISREG(attr->mode))
389396
inode->i_flags |= S_NOCMTIME;
390397
inode->i_generation = generation;
391-
fuse_init_inode(inode, attr);
398+
fuse_init_inode(inode, attr, fc);
392399
unlock_new_inode(inode);
393400
} else if (fuse_stale_inode(inode, generation, attr)) {
394401
/* nodeid was reused, any I/O on the old inode should fail */
@@ -1174,7 +1181,6 @@ static void process_init_reply(struct fuse_mount *fm, struct fuse_args *args,
11741181
if ((flags & FUSE_POSIX_ACL)) {
11751182
fc->default_permissions = 1;
11761183
fc->posix_acl = 1;
1177-
fm->sb->s_xattr = fuse_acl_xattr_handlers;
11781184
}
11791185
if (flags & FUSE_CACHE_SYMLINKS)
11801186
fc->cache_symlinks = 1;
@@ -1420,13 +1426,6 @@ static void fuse_sb_defaults(struct super_block *sb)
14201426
if (sb->s_user_ns != &init_user_ns)
14211427
sb->s_iflags |= SB_I_UNTRUSTED_MOUNTER;
14221428
sb->s_flags &= ~(SB_NOSEC | SB_I_VERSION);
1423-
1424-
/*
1425-
* If we are not in the initial user namespace posix
1426-
* acls must be translated.
1427-
*/
1428-
if (sb->s_user_ns != &init_user_ns)
1429-
sb->s_xattr = fuse_no_acl_xattr_handlers;
14301429
}
14311430

14321431
static int fuse_fill_super_submount(struct super_block *sb,

fs/fuse/xattr.c

Lines changed: 0 additions & 51 deletions
Original file line numberDiff line numberDiff line change
@@ -203,27 +203,6 @@ static int fuse_xattr_set(const struct xattr_handler *handler,
203203
return fuse_setxattr(inode, name, value, size, flags, 0);
204204
}
205205

206-
static bool no_xattr_list(struct dentry *dentry)
207-
{
208-
return false;
209-
}
210-
211-
static int no_xattr_get(const struct xattr_handler *handler,
212-
struct dentry *dentry, struct inode *inode,
213-
const char *name, void *value, size_t size)
214-
{
215-
return -EOPNOTSUPP;
216-
}
217-
218-
static int no_xattr_set(const struct xattr_handler *handler,
219-
struct user_namespace *mnt_userns,
220-
struct dentry *dentry, struct inode *nodee,
221-
const char *name, const void *value,
222-
size_t size, int flags)
223-
{
224-
return -EOPNOTSUPP;
225-
}
226-
227206
static const struct xattr_handler fuse_xattr_handler = {
228207
.prefix = "",
229208
.get = fuse_xattr_get,
@@ -234,33 +213,3 @@ const struct xattr_handler *fuse_xattr_handlers[] = {
234213
&fuse_xattr_handler,
235214
NULL
236215
};
237-
238-
const struct xattr_handler *fuse_acl_xattr_handlers[] = {
239-
&posix_acl_access_xattr_handler,
240-
&posix_acl_default_xattr_handler,
241-
&fuse_xattr_handler,
242-
NULL
243-
};
244-
245-
static const struct xattr_handler fuse_no_acl_access_xattr_handler = {
246-
.name = XATTR_NAME_POSIX_ACL_ACCESS,
247-
.flags = ACL_TYPE_ACCESS,
248-
.list = no_xattr_list,
249-
.get = no_xattr_get,
250-
.set = no_xattr_set,
251-
};
252-
253-
static const struct xattr_handler fuse_no_acl_default_xattr_handler = {
254-
.name = XATTR_NAME_POSIX_ACL_DEFAULT,
255-
.flags = ACL_TYPE_ACCESS,
256-
.list = no_xattr_list,
257-
.get = no_xattr_get,
258-
.set = no_xattr_set,
259-
};
260-
261-
const struct xattr_handler *fuse_no_acl_xattr_handlers[] = {
262-
&fuse_no_acl_access_xattr_handler,
263-
&fuse_no_acl_default_xattr_handler,
264-
&fuse_xattr_handler,
265-
NULL
266-
};

0 commit comments

Comments
 (0)