Skip to content

Commit 2401dc2

Browse files
Christoph HellwigAl Viro
authored andcommitted
xfs: use generic posix ACL infrastructure
Also don't bother to set up a .get_acl method for symlinks as we do not support access control (ACLs or even mode bits) for symlinks in Linux, and create inodes with the proper mode instead of fixing it up later. Signed-off-by: Christoph Hellwig <hch@lst.de> Reviewed-by: Dave Chinner <dchinner@redhat.com> Signed-off-by: Al Viro <viro@zeniv.linux.org.uk>
1 parent 47f70d0 commit 2401dc2

File tree

5 files changed

+36
-171
lines changed

5 files changed

+36
-171
lines changed

fs/xfs/xfs_acl.c

Lines changed: 8 additions & 143 deletions
Original file line numberDiff line numberDiff line change
@@ -124,16 +124,12 @@ struct posix_acl *
124124
xfs_get_acl(struct inode *inode, int type)
125125
{
126126
struct xfs_inode *ip = XFS_I(inode);
127-
struct posix_acl *acl;
127+
struct posix_acl *acl = NULL;
128128
struct xfs_acl *xfs_acl;
129129
unsigned char *ea_name;
130130
int error;
131131
int len;
132132

133-
acl = get_cached_acl(inode, type);
134-
if (acl != ACL_NOT_CACHED)
135-
return acl;
136-
137133
trace_xfs_get_acl(ip);
138134

139135
switch (type) {
@@ -164,10 +160,8 @@ xfs_get_acl(struct inode *inode, int type)
164160
* cache entry, for any other error assume it is transient and
165161
* leave the cache entry as ACL_NOT_CACHED.
166162
*/
167-
if (error == -ENOATTR) {
168-
acl = NULL;
163+
if (error == -ENOATTR)
169164
goto out_update_cache;
170-
}
171165
goto out;
172166
}
173167

@@ -183,15 +177,12 @@ xfs_get_acl(struct inode *inode, int type)
183177
}
184178

185179
STATIC int
186-
xfs_set_acl(struct inode *inode, int type, struct posix_acl *acl)
180+
__xfs_set_acl(struct inode *inode, int type, struct posix_acl *acl)
187181
{
188182
struct xfs_inode *ip = XFS_I(inode);
189183
unsigned char *ea_name;
190184
int error;
191185

192-
if (S_ISLNK(inode->i_mode))
193-
return -EOPNOTSUPP;
194-
195186
switch (type) {
196187
case ACL_TYPE_ACCESS:
197188
ea_name = SGI_ACL_FILE;
@@ -282,131 +273,23 @@ posix_acl_default_exists(struct inode *inode)
282273
return xfs_acl_exists(inode, SGI_ACL_DEFAULT);
283274
}
284275

285-
/*
286-
* No need for i_mutex because the inode is not yet exposed to the VFS.
287-
*/
288276
int
289-
xfs_inherit_acl(struct inode *inode, struct posix_acl *acl)
277+
xfs_set_acl(struct inode *inode, struct posix_acl *acl, int type)
290278
{
291-
umode_t mode = inode->i_mode;
292-
int error = 0, inherit = 0;
293-
294-
if (S_ISDIR(inode->i_mode)) {
295-
error = xfs_set_acl(inode, ACL_TYPE_DEFAULT, acl);
296-
if (error)
297-
goto out;
298-
}
299-
300-
error = __posix_acl_create(&acl, GFP_KERNEL, &mode);
301-
if (error < 0)
302-
return error;
303-
304-
/*
305-
* If __posix_acl_create returns a positive value we need to
306-
* inherit a permission that can't be represented using the Unix
307-
* mode bits and we actually need to set an ACL.
308-
*/
309-
if (error > 0)
310-
inherit = 1;
311-
312-
error = xfs_set_mode(inode, mode);
313-
if (error)
314-
goto out;
315-
316-
if (inherit)
317-
error = xfs_set_acl(inode, ACL_TYPE_ACCESS, acl);
318-
319-
out:
320-
posix_acl_release(acl);
321-
return error;
322-
}
323-
324-
int
325-
xfs_acl_chmod(struct inode *inode)
326-
{
327-
struct posix_acl *acl;
328-
int error;
329-
330-
if (S_ISLNK(inode->i_mode))
331-
return -EOPNOTSUPP;
332-
333-
acl = xfs_get_acl(inode, ACL_TYPE_ACCESS);
334-
if (IS_ERR(acl) || !acl)
335-
return PTR_ERR(acl);
336-
337-
error = __posix_acl_chmod(&acl, GFP_KERNEL, inode->i_mode);
338-
if (error)
339-
return error;
340-
341-
error = xfs_set_acl(inode, ACL_TYPE_ACCESS, acl);
342-
posix_acl_release(acl);
343-
return error;
344-
}
345-
346-
static int
347-
xfs_xattr_acl_get(struct dentry *dentry, const char *name,
348-
void *value, size_t size, int type)
349-
{
350-
struct posix_acl *acl;
351-
int error;
352-
353-
acl = xfs_get_acl(dentry->d_inode, type);
354-
if (IS_ERR(acl))
355-
return PTR_ERR(acl);
356-
if (acl == NULL)
357-
return -ENODATA;
358-
359-
error = posix_acl_to_xattr(&init_user_ns, acl, value, size);
360-
posix_acl_release(acl);
361-
362-
return error;
363-
}
364-
365-
static int
366-
xfs_xattr_acl_set(struct dentry *dentry, const char *name,
367-
const void *value, size_t size, int flags, int type)
368-
{
369-
struct inode *inode = dentry->d_inode;
370-
struct posix_acl *acl = NULL;
371279
int error = 0;
372280

373-
if (flags & XATTR_CREATE)
374-
return -EINVAL;
375-
if (type == ACL_TYPE_DEFAULT && !S_ISDIR(inode->i_mode))
376-
return value ? -EACCES : 0;
377-
if (!inode_owner_or_capable(inode))
378-
return -EPERM;
379-
380-
if (!value)
281+
if (!acl)
381282
goto set_acl;
382283

383-
acl = posix_acl_from_xattr(&init_user_ns, value, size);
384-
if (!acl) {
385-
/*
386-
* acl_set_file(3) may request that we set default ACLs with
387-
* zero length -- defend (gracefully) against that here.
388-
*/
389-
goto out;
390-
}
391-
if (IS_ERR(acl)) {
392-
error = PTR_ERR(acl);
393-
goto out;
394-
}
395-
396-
error = posix_acl_valid(acl);
397-
if (error)
398-
goto out_release;
399-
400284
error = -EINVAL;
401285
if (acl->a_count > XFS_ACL_MAX_ENTRIES(XFS_M(inode->i_sb)))
402-
goto out_release;
286+
return error;
403287

404288
if (type == ACL_TYPE_ACCESS) {
405289
umode_t mode = inode->i_mode;
406290
error = posix_acl_equiv_mode(acl, &mode);
407291

408292
if (error <= 0) {
409-
posix_acl_release(acl);
410293
acl = NULL;
411294

412295
if (error < 0)
@@ -415,27 +298,9 @@ xfs_xattr_acl_set(struct dentry *dentry, const char *name,
415298

416299
error = xfs_set_mode(inode, mode);
417300
if (error)
418-
goto out_release;
301+
return error;
419302
}
420303

421304
set_acl:
422-
error = xfs_set_acl(inode, type, acl);
423-
out_release:
424-
posix_acl_release(acl);
425-
out:
426-
return error;
305+
return __xfs_set_acl(inode, type, acl);
427306
}
428-
429-
const struct xattr_handler xfs_xattr_acl_access_handler = {
430-
.prefix = POSIX_ACL_XATTR_ACCESS,
431-
.flags = ACL_TYPE_ACCESS,
432-
.get = xfs_xattr_acl_get,
433-
.set = xfs_xattr_acl_set,
434-
};
435-
436-
const struct xattr_handler xfs_xattr_acl_default_handler = {
437-
.prefix = POSIX_ACL_XATTR_DEFAULT,
438-
.flags = ACL_TYPE_DEFAULT,
439-
.get = xfs_xattr_acl_get,
440-
.set = xfs_xattr_acl_set,
441-
};

fs/xfs/xfs_acl.h

Lines changed: 2 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -60,20 +60,15 @@ struct xfs_acl {
6060

6161
#ifdef CONFIG_XFS_POSIX_ACL
6262
extern struct posix_acl *xfs_get_acl(struct inode *inode, int type);
63-
extern int xfs_inherit_acl(struct inode *inode, struct posix_acl *default_acl);
64-
extern int xfs_acl_chmod(struct inode *inode);
63+
extern int xfs_set_acl(struct inode *inode, struct posix_acl *acl, int type);
6564
extern int posix_acl_access_exists(struct inode *inode);
6665
extern int posix_acl_default_exists(struct inode *inode);
67-
68-
extern const struct xattr_handler xfs_xattr_acl_access_handler;
69-
extern const struct xattr_handler xfs_xattr_acl_default_handler;
7066
#else
7167
static inline struct posix_acl *xfs_get_acl(struct inode *inode, int type)
7268
{
7369
return NULL;
7470
}
75-
# define xfs_inherit_acl(inode, default_acl) 0
76-
# define xfs_acl_chmod(inode) 0
71+
# define xfs_set_acl NULL
7772
# define posix_acl_access_exists(inode) 0
7873
# define posix_acl_default_exists(inode) 0
7974
#endif /* CONFIG_XFS_POSIX_ACL */

fs/xfs/xfs_iops.c

Lines changed: 23 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -123,7 +123,7 @@ xfs_vn_mknod(
123123
{
124124
struct inode *inode;
125125
struct xfs_inode *ip = NULL;
126-
struct posix_acl *default_acl = NULL;
126+
struct posix_acl *default_acl, *acl;
127127
struct xfs_name name;
128128
int error;
129129

@@ -139,14 +139,9 @@ xfs_vn_mknod(
139139
rdev = 0;
140140
}
141141

142-
if (IS_POSIXACL(dir)) {
143-
default_acl = xfs_get_acl(dir, ACL_TYPE_DEFAULT);
144-
if (IS_ERR(default_acl))
145-
return PTR_ERR(default_acl);
146-
147-
if (!default_acl)
148-
mode &= ~current_umask();
149-
}
142+
error = posix_acl_create(dir, &mode, &default_acl, &acl);
143+
if (error)
144+
return error;
150145

151146
xfs_dentry_to_name(&name, dentry, mode);
152147
error = xfs_create(XFS_I(dir), &name, mode, rdev, &ip);
@@ -159,22 +154,30 @@ xfs_vn_mknod(
159154
if (unlikely(error))
160155
goto out_cleanup_inode;
161156

157+
#ifdef CONFIG_XFS_POSIX_ACL
162158
if (default_acl) {
163-
error = -xfs_inherit_acl(inode, default_acl);
164-
default_acl = NULL;
165-
if (unlikely(error))
159+
error = xfs_set_acl(inode, default_acl, ACL_TYPE_DEFAULT);
160+
if (error)
166161
goto out_cleanup_inode;
167162
}
168-
163+
if (acl) {
164+
error = xfs_set_acl(inode, acl, ACL_TYPE_ACCESS);
165+
if (error)
166+
goto out_cleanup_inode;
167+
}
168+
#endif
169169

170170
d_instantiate(dentry, inode);
171+
out_free_acl:
172+
if (default_acl)
173+
posix_acl_release(default_acl);
174+
if (acl)
175+
posix_acl_release(acl);
171176
return -error;
172177

173178
out_cleanup_inode:
174179
xfs_cleanup_inode(dir, inode, dentry);
175-
out_free_acl:
176-
posix_acl_release(default_acl);
177-
return -error;
180+
goto out_free_acl;
178181
}
179182

180183
STATIC int
@@ -672,7 +675,7 @@ xfs_setattr_nonsize(
672675
* Posix ACL code seems to care about this issue either.
673676
*/
674677
if ((mask & ATTR_MODE) && !(flags & XFS_ATTR_NOACL)) {
675-
error = -xfs_acl_chmod(inode);
678+
error = -posix_acl_chmod(inode, inode->i_mode);
676679
if (error)
677680
return XFS_ERROR(error);
678681
}
@@ -1041,6 +1044,7 @@ xfs_vn_fiemap(
10411044

10421045
static const struct inode_operations xfs_inode_operations = {
10431046
.get_acl = xfs_get_acl,
1047+
.set_acl = xfs_set_acl,
10441048
.getattr = xfs_vn_getattr,
10451049
.setattr = xfs_vn_setattr,
10461050
.setxattr = generic_setxattr,
@@ -1068,6 +1072,7 @@ static const struct inode_operations xfs_dir_inode_operations = {
10681072
.mknod = xfs_vn_mknod,
10691073
.rename = xfs_vn_rename,
10701074
.get_acl = xfs_get_acl,
1075+
.set_acl = xfs_set_acl,
10711076
.getattr = xfs_vn_getattr,
10721077
.setattr = xfs_vn_setattr,
10731078
.setxattr = generic_setxattr,
@@ -1094,6 +1099,7 @@ static const struct inode_operations xfs_dir_ci_inode_operations = {
10941099
.mknod = xfs_vn_mknod,
10951100
.rename = xfs_vn_rename,
10961101
.get_acl = xfs_get_acl,
1102+
.set_acl = xfs_set_acl,
10971103
.getattr = xfs_vn_getattr,
10981104
.setattr = xfs_vn_setattr,
10991105
.setxattr = generic_setxattr,
@@ -1107,7 +1113,6 @@ static const struct inode_operations xfs_symlink_inode_operations = {
11071113
.readlink = generic_readlink,
11081114
.follow_link = xfs_vn_follow_link,
11091115
.put_link = kfree_put_link,
1110-
.get_acl = xfs_get_acl,
11111116
.getattr = xfs_vn_getattr,
11121117
.setattr = xfs_vn_setattr,
11131118
.setxattr = generic_setxattr,

fs/xfs/xfs_iops.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -30,7 +30,7 @@ extern void xfs_setup_inode(struct xfs_inode *);
3030
/*
3131
* Internal setattr interfaces.
3232
*/
33-
#define XFS_ATTR_NOACL 0x01 /* Don't call xfs_acl_chmod */
33+
#define XFS_ATTR_NOACL 0x01 /* Don't call posix_acl_chmod */
3434

3535
extern int xfs_setattr_nonsize(struct xfs_inode *ip, struct iattr *vap,
3636
int flags);

fs/xfs/xfs_xattr.c

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -102,8 +102,8 @@ const struct xattr_handler *xfs_xattr_handlers[] = {
102102
&xfs_xattr_trusted_handler,
103103
&xfs_xattr_security_handler,
104104
#ifdef CONFIG_XFS_POSIX_ACL
105-
&xfs_xattr_acl_access_handler,
106-
&xfs_xattr_acl_default_handler,
105+
&posix_acl_access_xattr_handler,
106+
&posix_acl_default_xattr_handler,
107107
#endif
108108
NULL
109109
};

0 commit comments

Comments
 (0)