aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorChristoph Hellwig <hch@infradead.org>2013-12-20 08:16:52 -0500
committerAl Viro <viro@zeniv.linux.org.uk>2014-01-25 23:58:22 -0500
commite01580bf9e4d0e3bbaead44bd46cdbfe61957732 (patch)
tree1f853adc16d311670dbfba0cf6e2e7555d1d9b4b
parent2cc6a5a01cdbeb0e46f3aa144819d5d7cee458a1 (diff)
gfs2: use generic posix ACL infrastructure
This contains some major refactoring for the create path so that inodes are created with the right mode to start with instead of fixing it up later. Signed-off-by: Christoph Hellwig <hch@lst.de> Signed-off-by: Al Viro <viro@zeniv.linux.org.uk>
-rw-r--r--fs/gfs2/acl.c234
-rw-r--r--fs/gfs2/acl.h4
-rw-r--r--fs/gfs2/inode.c34
-rw-r--r--fs/gfs2/xattr.c4
4 files changed, 62 insertions, 214 deletions
diff --git a/fs/gfs2/acl.c b/fs/gfs2/acl.c
index e82e4ac574a6..ba9456685f47 100644
--- a/fs/gfs2/acl.c
+++ b/fs/gfs2/acl.c
@@ -49,10 +49,6 @@ struct posix_acl *gfs2_get_acl(struct inode *inode, int type)
49 if (!ip->i_eattr) 49 if (!ip->i_eattr)
50 return NULL; 50 return NULL;
51 51
52 acl = get_cached_acl(&ip->i_inode, type);
53 if (acl != ACL_NOT_CACHED)
54 return acl;
55
56 name = gfs2_acl_name(type); 52 name = gfs2_acl_name(type);
57 if (name == NULL) 53 if (name == NULL)
58 return ERR_PTR(-EINVAL); 54 return ERR_PTR(-EINVAL);
@@ -80,7 +76,7 @@ static int gfs2_set_mode(struct inode *inode, umode_t mode)
80 return error; 76 return error;
81} 77}
82 78
83static int gfs2_acl_set(struct inode *inode, int type, struct posix_acl *acl) 79int gfs2_set_acl(struct inode *inode, struct posix_acl *acl, int type)
84{ 80{
85 int error; 81 int error;
86 int len; 82 int len;
@@ -88,219 +84,49 @@ static int gfs2_acl_set(struct inode *inode, int type, struct posix_acl *acl)
88 const char *name = gfs2_acl_name(type); 84 const char *name = gfs2_acl_name(type);
89 85
90 BUG_ON(name == NULL); 86 BUG_ON(name == NULL);
91 len = posix_acl_to_xattr(&init_user_ns, acl, NULL, 0);
92 if (len == 0)
93 return 0;
94 data = kmalloc(len, GFP_NOFS);
95 if (data == NULL)
96 return -ENOMEM;
97 error = posix_acl_to_xattr(&init_user_ns, acl, data, len);
98 if (error < 0)
99 goto out;
100 error = __gfs2_xattr_set(inode, name, data, len, 0, GFS2_EATYPE_SYS);
101 if (!error)
102 set_cached_acl(inode, type, acl);
103out:
104 kfree(data);
105 return error;
106}
107
108int gfs2_acl_create(struct gfs2_inode *dip, struct inode *inode)
109{
110 struct gfs2_sbd *sdp = GFS2_SB(&dip->i_inode);
111 struct posix_acl *acl;
112 umode_t mode = inode->i_mode;
113 int error = 0;
114
115 if (!sdp->sd_args.ar_posix_acl)
116 return 0;
117 if (S_ISLNK(inode->i_mode))
118 return 0;
119
120 acl = gfs2_get_acl(&dip->i_inode, ACL_TYPE_DEFAULT);
121 if (IS_ERR(acl))
122 return PTR_ERR(acl);
123 if (!acl) {
124 mode &= ~current_umask();
125 return gfs2_set_mode(inode, mode);
126 }
127
128 if (S_ISDIR(inode->i_mode)) {
129 error = gfs2_acl_set(inode, ACL_TYPE_DEFAULT, acl);
130 if (error)
131 goto out;
132 }
133
134 error = __posix_acl_create(&acl, GFP_NOFS, &mode);
135 if (error < 0)
136 return error;
137 87
138 if (error == 0)
139 goto munge;
140
141 error = gfs2_acl_set(inode, ACL_TYPE_ACCESS, acl);
142 if (error)
143 goto out;
144munge:
145 error = gfs2_set_mode(inode, mode);
146out:
147 posix_acl_release(acl);
148 return error;
149}
150
151int gfs2_acl_chmod(struct gfs2_inode *ip, struct iattr *attr)
152{
153 struct inode *inode = &ip->i_inode;
154 struct posix_acl *acl;
155 char *data;
156 unsigned int len;
157 int error;
158
159 acl = gfs2_get_acl(&ip->i_inode, ACL_TYPE_ACCESS);
160 if (IS_ERR(acl))
161 return PTR_ERR(acl);
162 if (!acl)
163 return gfs2_setattr_simple(inode, attr);
164
165 error = __posix_acl_chmod(&acl, GFP_NOFS, attr->ia_mode);
166 if (error)
167 return error;
168
169 len = posix_acl_to_xattr(&init_user_ns, acl, NULL, 0);
170 data = kmalloc(len, GFP_NOFS);
171 error = -ENOMEM;
172 if (data == NULL)
173 goto out;
174 posix_acl_to_xattr(&init_user_ns, acl, data, len);
175 error = gfs2_xattr_acl_chmod(ip, attr, data);
176 kfree(data);
177 set_cached_acl(&ip->i_inode, ACL_TYPE_ACCESS, acl);
178
179out:
180 posix_acl_release(acl);
181 return error;
182}
183
184static int gfs2_acl_type(const char *name)
185{
186 if (strcmp(name, GFS2_POSIX_ACL_ACCESS) == 0)
187 return ACL_TYPE_ACCESS;
188 if (strcmp(name, GFS2_POSIX_ACL_DEFAULT) == 0)
189 return ACL_TYPE_DEFAULT;
190 return -EINVAL;
191}
192
193static int gfs2_xattr_system_get(struct dentry *dentry, const char *name,
194 void *buffer, size_t size, int xtype)
195{
196 struct inode *inode = dentry->d_inode;
197 struct gfs2_sbd *sdp = GFS2_SB(inode);
198 struct posix_acl *acl;
199 int type;
200 int error;
201
202 if (!sdp->sd_args.ar_posix_acl)
203 return -EOPNOTSUPP;
204
205 type = gfs2_acl_type(name);
206 if (type < 0)
207 return type;
208
209 acl = gfs2_get_acl(inode, type);
210 if (IS_ERR(acl))
211 return PTR_ERR(acl);
212 if (acl == NULL)
213 return -ENODATA;
214
215 error = posix_acl_to_xattr(&init_user_ns, acl, buffer, size);
216 posix_acl_release(acl);
217
218 return error;
219}
220
221static int gfs2_xattr_system_set(struct dentry *dentry, const char *name,
222 const void *value, size_t size, int flags,
223 int xtype)
224{
225 struct inode *inode = dentry->d_inode;
226 struct gfs2_sbd *sdp = GFS2_SB(inode);
227 struct posix_acl *acl = NULL;
228 int error = 0, type;
229
230 if (!sdp->sd_args.ar_posix_acl)
231 return -EOPNOTSUPP;
232
233 type = gfs2_acl_type(name);
234 if (type < 0)
235 return type;
236 if (flags & XATTR_CREATE)
237 return -EINVAL;
238 if (type == ACL_TYPE_DEFAULT && !S_ISDIR(inode->i_mode))
239 return value ? -EACCES : 0;
240 if (!uid_eq(current_fsuid(), inode->i_uid) && !capable(CAP_FOWNER))
241 return -EPERM;
242 if (S_ISLNK(inode->i_mode))
243 return -EOPNOTSUPP;
244
245 if (!value)
246 goto set_acl;
247
248 acl = posix_acl_from_xattr(&init_user_ns, value, size);
249 if (!acl) {
250 /*
251 * acl_set_file(3) may request that we set default ACLs with
252 * zero length -- defend (gracefully) against that here.
253 */
254 goto out;
255 }
256 if (IS_ERR(acl)) {
257 error = PTR_ERR(acl);
258 goto out;
259 }
260
261 error = posix_acl_valid(acl);
262 if (error)
263 goto out_release;
264
265 error = -EINVAL;
266 if (acl->a_count > GFS2_ACL_MAX_ENTRIES) 88 if (acl->a_count > GFS2_ACL_MAX_ENTRIES)
267 goto out_release; 89 return -EINVAL;
268 90
269 if (type == ACL_TYPE_ACCESS) { 91 if (type == ACL_TYPE_ACCESS) {
270 umode_t mode = inode->i_mode; 92 umode_t mode = inode->i_mode;
93
271 error = posix_acl_equiv_mode(acl, &mode); 94 error = posix_acl_equiv_mode(acl, &mode);
95 if (error < 0)
96 return error;
272 97
273 if (error <= 0) { 98 if (error == 0)
274 posix_acl_release(acl);
275 acl = NULL; 99 acl = NULL;
276 100
277 if (error < 0)
278 return error;
279 }
280
281 error = gfs2_set_mode(inode, mode); 101 error = gfs2_set_mode(inode, mode);
282 if (error) 102 if (error)
283 goto out_release; 103 return error;
284 } 104 }
285 105
286set_acl: 106 if (acl) {
287 error = __gfs2_xattr_set(inode, name, value, size, 0, GFS2_EATYPE_SYS); 107 len = posix_acl_to_xattr(&init_user_ns, acl, NULL, 0);
288 if (!error) { 108 if (len == 0)
289 if (acl) 109 return 0;
290 set_cached_acl(inode, type, acl); 110 data = kmalloc(len, GFP_NOFS);
291 else 111 if (data == NULL)
292 forget_cached_acl(inode, type); 112 return -ENOMEM;
113 error = posix_acl_to_xattr(&init_user_ns, acl, data, len);
114 if (error < 0)
115 goto out;
116 } else {
117 data = NULL;
118 len = 0;
293 } 119 }
294out_release: 120
295 posix_acl_release(acl); 121 error = __gfs2_xattr_set(inode, name, data, len, 0, GFS2_EATYPE_SYS);
122 if (error)
123 goto out;
124
125 if (acl)
126 set_cached_acl(inode, type, acl);
127 else
128 forget_cached_acl(inode, type);
296out: 129out:
130 kfree(data);
297 return error; 131 return error;
298} 132}
299
300const struct xattr_handler gfs2_xattr_system_handler = {
301 .prefix = XATTR_SYSTEM_PREFIX,
302 .flags = GFS2_EATYPE_SYS,
303 .get = gfs2_xattr_system_get,
304 .set = gfs2_xattr_system_set,
305};
306
diff --git a/fs/gfs2/acl.h b/fs/gfs2/acl.h
index 0da38dc7efec..301260c999ba 100644
--- a/fs/gfs2/acl.h
+++ b/fs/gfs2/acl.h
@@ -17,8 +17,6 @@
17#define GFS2_ACL_MAX_ENTRIES 25 17#define GFS2_ACL_MAX_ENTRIES 25
18 18
19extern struct posix_acl *gfs2_get_acl(struct inode *inode, int type); 19extern struct posix_acl *gfs2_get_acl(struct inode *inode, int type);
20extern int gfs2_acl_create(struct gfs2_inode *dip, struct inode *inode); 20extern int gfs2_set_acl(struct inode *inode, struct posix_acl *acl, int type);
21extern int gfs2_acl_chmod(struct gfs2_inode *ip, struct iattr *attr);
22extern const struct xattr_handler gfs2_xattr_system_handler;
23 21
24#endif /* __ACL_DOT_H__ */ 22#endif /* __ACL_DOT_H__ */
diff --git a/fs/gfs2/inode.c b/fs/gfs2/inode.c
index 7119504159f1..d573125d1021 100644
--- a/fs/gfs2/inode.c
+++ b/fs/gfs2/inode.c
@@ -552,6 +552,7 @@ static int gfs2_create_inode(struct inode *dir, struct dentry *dentry,
552 unsigned int size, int excl, int *opened) 552 unsigned int size, int excl, int *opened)
553{ 553{
554 const struct qstr *name = &dentry->d_name; 554 const struct qstr *name = &dentry->d_name;
555 struct posix_acl *default_acl, *acl;
555 struct gfs2_holder ghs[2]; 556 struct gfs2_holder ghs[2];
556 struct inode *inode = NULL; 557 struct inode *inode = NULL;
557 struct gfs2_inode *dip = GFS2_I(dir), *ip; 558 struct gfs2_inode *dip = GFS2_I(dir), *ip;
@@ -611,10 +612,14 @@ static int gfs2_create_inode(struct inode *dir, struct dentry *dentry,
611 if (!inode) 612 if (!inode)
612 goto fail_gunlock; 613 goto fail_gunlock;
613 614
615 error = posix_acl_create(dir, &mode, &default_acl, &acl);
616 if (error)
617 goto fail_free_vfs_inode;
618
614 ip = GFS2_I(inode); 619 ip = GFS2_I(inode);
615 error = gfs2_rs_alloc(ip); 620 error = gfs2_rs_alloc(ip);
616 if (error) 621 if (error)
617 goto fail_free_inode; 622 goto fail_free_acls;
618 623
619 inode->i_mode = mode; 624 inode->i_mode = mode;
620 set_nlink(inode, S_ISDIR(mode) ? 2 : 1); 625 set_nlink(inode, S_ISDIR(mode) ? 2 : 1);
@@ -682,7 +687,16 @@ static int gfs2_create_inode(struct inode *dir, struct dentry *dentry,
682 gfs2_set_iop(inode); 687 gfs2_set_iop(inode);
683 insert_inode_hash(inode); 688 insert_inode_hash(inode);
684 689
685 error = gfs2_acl_create(dip, inode); 690 if (default_acl) {
691 error = gfs2_set_acl(inode, default_acl, ACL_TYPE_DEFAULT);
692 posix_acl_release(default_acl);
693 }
694 if (acl) {
695 if (!error)
696 error = gfs2_set_acl(inode, acl, ACL_TYPE_ACCESS);
697 posix_acl_release(acl);
698 }
699
686 if (error) 700 if (error)
687 goto fail_gunlock3; 701 goto fail_gunlock3;
688 702
@@ -716,6 +730,12 @@ fail_free_inode:
716 if (ip->i_gl) 730 if (ip->i_gl)
717 gfs2_glock_put(ip->i_gl); 731 gfs2_glock_put(ip->i_gl);
718 gfs2_rs_delete(ip, NULL); 732 gfs2_rs_delete(ip, NULL);
733fail_free_acls:
734 if (default_acl)
735 posix_acl_release(default_acl);
736 if (acl)
737 posix_acl_release(acl);
738fail_free_vfs_inode:
719 free_inode_nonrcu(inode); 739 free_inode_nonrcu(inode);
720 inode = NULL; 740 inode = NULL;
721fail_gunlock: 741fail_gunlock:
@@ -1678,10 +1698,11 @@ static int gfs2_setattr(struct dentry *dentry, struct iattr *attr)
1678 error = gfs2_setattr_size(inode, attr->ia_size); 1698 error = gfs2_setattr_size(inode, attr->ia_size);
1679 else if (attr->ia_valid & (ATTR_UID | ATTR_GID)) 1699 else if (attr->ia_valid & (ATTR_UID | ATTR_GID))
1680 error = setattr_chown(inode, attr); 1700 error = setattr_chown(inode, attr);
1681 else if ((attr->ia_valid & ATTR_MODE) && IS_POSIXACL(inode)) 1701 else {
1682 error = gfs2_acl_chmod(ip, attr);
1683 else
1684 error = gfs2_setattr_simple(inode, attr); 1702 error = gfs2_setattr_simple(inode, attr);
1703 if (!error && attr->ia_valid & ATTR_MODE)
1704 error = posix_acl_chmod(inode, inode->i_mode);
1705 }
1685 1706
1686out: 1707out:
1687 if (!error) 1708 if (!error)
@@ -1841,6 +1862,7 @@ const struct inode_operations gfs2_file_iops = {
1841 .removexattr = gfs2_removexattr, 1862 .removexattr = gfs2_removexattr,
1842 .fiemap = gfs2_fiemap, 1863 .fiemap = gfs2_fiemap,
1843 .get_acl = gfs2_get_acl, 1864 .get_acl = gfs2_get_acl,
1865 .set_acl = gfs2_set_acl,
1844}; 1866};
1845 1867
1846const struct inode_operations gfs2_dir_iops = { 1868const struct inode_operations gfs2_dir_iops = {
@@ -1862,6 +1884,7 @@ const struct inode_operations gfs2_dir_iops = {
1862 .removexattr = gfs2_removexattr, 1884 .removexattr = gfs2_removexattr,
1863 .fiemap = gfs2_fiemap, 1885 .fiemap = gfs2_fiemap,
1864 .get_acl = gfs2_get_acl, 1886 .get_acl = gfs2_get_acl,
1887 .set_acl = gfs2_set_acl,
1865 .atomic_open = gfs2_atomic_open, 1888 .atomic_open = gfs2_atomic_open,
1866}; 1889};
1867 1890
@@ -1877,6 +1900,5 @@ const struct inode_operations gfs2_symlink_iops = {
1877 .listxattr = gfs2_listxattr, 1900 .listxattr = gfs2_listxattr,
1878 .removexattr = gfs2_removexattr, 1901 .removexattr = gfs2_removexattr,
1879 .fiemap = gfs2_fiemap, 1902 .fiemap = gfs2_fiemap,
1880 .get_acl = gfs2_get_acl,
1881}; 1903};
1882 1904
diff --git a/fs/gfs2/xattr.c b/fs/gfs2/xattr.c
index 8c6a6f6bdba9..0b81f783f787 100644
--- a/fs/gfs2/xattr.c
+++ b/fs/gfs2/xattr.c
@@ -13,6 +13,7 @@
13#include <linux/buffer_head.h> 13#include <linux/buffer_head.h>
14#include <linux/xattr.h> 14#include <linux/xattr.h>
15#include <linux/gfs2_ondisk.h> 15#include <linux/gfs2_ondisk.h>
16#include <linux/posix_acl_xattr.h>
16#include <asm/uaccess.h> 17#include <asm/uaccess.h>
17 18
18#include "gfs2.h" 19#include "gfs2.h"
@@ -1500,7 +1501,8 @@ static const struct xattr_handler gfs2_xattr_security_handler = {
1500const struct xattr_handler *gfs2_xattr_handlers[] = { 1501const struct xattr_handler *gfs2_xattr_handlers[] = {
1501 &gfs2_xattr_user_handler, 1502 &gfs2_xattr_user_handler,
1502 &gfs2_xattr_security_handler, 1503 &gfs2_xattr_security_handler,
1503 &gfs2_xattr_system_handler, 1504 &posix_acl_access_xattr_handler,
1505 &posix_acl_default_xattr_handler,
1504 NULL, 1506 NULL,
1505}; 1507};
1506 1508