aboutsummaryrefslogtreecommitdiffstats
path: root/fs/ext3
diff options
context:
space:
mode:
authorChristoph Hellwig <hch@infradead.org>2013-12-20 08:16:44 -0500
committerAl Viro <viro@zeniv.linux.org.uk>2014-01-25 23:58:19 -0500
commit64e178a7118b1cf7648391755e44dcc209091003 (patch)
treef06ee5408a04ee86c7a79dfd885aaab3c5f3f070 /fs/ext3
parent996a710d46418cacb5b4a519ab9341a74066551d (diff)
ext2/3/4: use generic posix ACL infrastructure
Signed-off-by: Christoph Hellwig <hch@lst.de> Reviewed-by: Jan Kara <jack@suse.cz> Signed-off-by: Al Viro <viro@zeniv.linux.org.uk>
Diffstat (limited to 'fs/ext3')
-rw-r--r--fs/ext3/acl.c223
-rw-r--r--fs/ext3/acl.h9
-rw-r--r--fs/ext3/file.c1
-rw-r--r--fs/ext3/inode.c2
-rw-r--r--fs/ext3/namei.c2
-rw-r--r--fs/ext3/xattr.c8
-rw-r--r--fs/ext3/xattr.h2
7 files changed, 39 insertions, 208 deletions
diff --git a/fs/ext3/acl.c b/fs/ext3/acl.c
index 4f3d8fa0c0a3..8bbaf5bcf982 100644
--- a/fs/ext3/acl.c
+++ b/fs/ext3/acl.c
@@ -145,13 +145,6 @@ ext3_get_acl(struct inode *inode, int type)
145 struct posix_acl *acl; 145 struct posix_acl *acl;
146 int retval; 146 int retval;
147 147
148 if (!test_opt(inode->i_sb, POSIX_ACL))
149 return NULL;
150
151 acl = get_cached_acl(inode, type);
152 if (acl != ACL_NOT_CACHED)
153 return acl;
154
155 switch (type) { 148 switch (type) {
156 case ACL_TYPE_ACCESS: 149 case ACL_TYPE_ACCESS:
157 name_index = EXT3_XATTR_INDEX_POSIX_ACL_ACCESS; 150 name_index = EXT3_XATTR_INDEX_POSIX_ACL_ACCESS;
@@ -190,7 +183,7 @@ ext3_get_acl(struct inode *inode, int type)
190 * inode->i_mutex: down unless called from ext3_new_inode 183 * inode->i_mutex: down unless called from ext3_new_inode
191 */ 184 */
192static int 185static int
193ext3_set_acl(handle_t *handle, struct inode *inode, int type, 186__ext3_set_acl(handle_t *handle, struct inode *inode, int type,
194 struct posix_acl *acl) 187 struct posix_acl *acl)
195{ 188{
196 int name_index; 189 int name_index;
@@ -198,9 +191,6 @@ ext3_set_acl(handle_t *handle, struct inode *inode, int type,
198 size_t size = 0; 191 size_t size = 0;
199 int error; 192 int error;
200 193
201 if (S_ISLNK(inode->i_mode))
202 return -EOPNOTSUPP;
203
204 switch(type) { 194 switch(type) {
205 case ACL_TYPE_ACCESS: 195 case ACL_TYPE_ACCESS:
206 name_index = EXT3_XATTR_INDEX_POSIX_ACL_ACCESS; 196 name_index = EXT3_XATTR_INDEX_POSIX_ACL_ACCESS;
@@ -243,204 +233,49 @@ ext3_set_acl(handle_t *handle, struct inode *inode, int type,
243 return error; 233 return error;
244} 234}
245 235
246/*
247 * Initialize the ACLs of a new inode. Called from ext3_new_inode.
248 *
249 * dir->i_mutex: down
250 * inode->i_mutex: up (access to inode is still exclusive)
251 */
252int 236int
253ext3_init_acl(handle_t *handle, struct inode *inode, struct inode *dir) 237ext3_set_acl(struct inode *inode, struct posix_acl *acl, int type)
254{ 238{
255 struct posix_acl *acl = NULL;
256 int error = 0;
257
258 if (!S_ISLNK(inode->i_mode)) {
259 if (test_opt(dir->i_sb, POSIX_ACL)) {
260 acl = ext3_get_acl(dir, ACL_TYPE_DEFAULT);
261 if (IS_ERR(acl))
262 return PTR_ERR(acl);
263 }
264 if (!acl)
265 inode->i_mode &= ~current_umask();
266 }
267 if (test_opt(inode->i_sb, POSIX_ACL) && acl) {
268 if (S_ISDIR(inode->i_mode)) {
269 error = ext3_set_acl(handle, inode,
270 ACL_TYPE_DEFAULT, acl);
271 if (error)
272 goto cleanup;
273 }
274 error = __posix_acl_create(&acl, GFP_NOFS, &inode->i_mode);
275 if (error < 0)
276 return error;
277
278 if (error > 0) {
279 /* This is an extended ACL */
280 error = ext3_set_acl(handle, inode, ACL_TYPE_ACCESS, acl);
281 }
282 }
283cleanup:
284 posix_acl_release(acl);
285 return error;
286}
287
288/*
289 * Does chmod for an inode that may have an Access Control List. The
290 * inode->i_mode field must be updated to the desired value by the caller
291 * before calling this function.
292 * Returns 0 on success, or a negative error number.
293 *
294 * We change the ACL rather than storing some ACL entries in the file
295 * mode permission bits (which would be more efficient), because that
296 * would break once additional permissions (like ACL_APPEND, ACL_DELETE
297 * for directories) are added. There are no more bits available in the
298 * file mode.
299 *
300 * inode->i_mutex: down
301 */
302int
303ext3_acl_chmod(struct inode *inode)
304{
305 struct posix_acl *acl;
306 handle_t *handle; 239 handle_t *handle;
307 int retries = 0; 240 int error, retries = 0;
308 int error;
309 241
310 if (S_ISLNK(inode->i_mode))
311 return -EOPNOTSUPP;
312 if (!test_opt(inode->i_sb, POSIX_ACL))
313 return 0;
314 acl = ext3_get_acl(inode, ACL_TYPE_ACCESS);
315 if (IS_ERR(acl) || !acl)
316 return PTR_ERR(acl);
317 error = __posix_acl_chmod(&acl, GFP_KERNEL, inode->i_mode);
318 if (error)
319 return error;
320retry: 242retry:
321 handle = ext3_journal_start(inode, 243 handle = ext3_journal_start(inode, EXT3_DATA_TRANS_BLOCKS(inode->i_sb));
322 EXT3_DATA_TRANS_BLOCKS(inode->i_sb)); 244 if (IS_ERR(handle))
323 if (IS_ERR(handle)) { 245 return PTR_ERR(handle);
324 error = PTR_ERR(handle); 246 error = __ext3_set_acl(handle, inode, type, acl);
325 ext3_std_error(inode->i_sb, error);
326 goto out;
327 }
328 error = ext3_set_acl(handle, inode, ACL_TYPE_ACCESS, acl);
329 ext3_journal_stop(handle); 247 ext3_journal_stop(handle);
330 if (error == -ENOSPC && 248 if (error == -ENOSPC && ext3_should_retry_alloc(inode->i_sb, &retries))
331 ext3_should_retry_alloc(inode->i_sb, &retries))
332 goto retry; 249 goto retry;
333out:
334 posix_acl_release(acl);
335 return error; 250 return error;
336} 251}
337 252
338/* 253/*
339 * Extended attribute handlers 254 * Initialize the ACLs of a new inode. Called from ext3_new_inode.
255 *
256 * dir->i_mutex: down
257 * inode->i_mutex: up (access to inode is still exclusive)
340 */ 258 */
341static size_t 259int
342ext3_xattr_list_acl_access(struct dentry *dentry, char *list, size_t list_len, 260ext3_init_acl(handle_t *handle, struct inode *inode, struct inode *dir)
343 const char *name, size_t name_len, int type)
344{
345 const size_t size = sizeof(POSIX_ACL_XATTR_ACCESS);
346
347 if (!test_opt(dentry->d_sb, POSIX_ACL))
348 return 0;
349 if (list && size <= list_len)
350 memcpy(list, POSIX_ACL_XATTR_ACCESS, size);
351 return size;
352}
353
354static size_t
355ext3_xattr_list_acl_default(struct dentry *dentry, char *list, size_t list_len,
356 const char *name, size_t name_len, int type)
357{
358 const size_t size = sizeof(POSIX_ACL_XATTR_DEFAULT);
359
360 if (!test_opt(dentry->d_sb, POSIX_ACL))
361 return 0;
362 if (list && size <= list_len)
363 memcpy(list, POSIX_ACL_XATTR_DEFAULT, size);
364 return size;
365}
366
367static int
368ext3_xattr_get_acl(struct dentry *dentry, const char *name, void *buffer,
369 size_t size, int type)
370{ 261{
371 struct posix_acl *acl; 262 struct posix_acl *default_acl, *acl;
372 int error; 263 int error;
373 264
374 if (strcmp(name, "") != 0) 265 error = posix_acl_create(dir, &inode->i_mode, &default_acl, &acl);
375 return -EINVAL; 266 if (error)
376 if (!test_opt(dentry->d_sb, POSIX_ACL)) 267 return error;
377 return -EOPNOTSUPP;
378
379 acl = ext3_get_acl(dentry->d_inode, type);
380 if (IS_ERR(acl))
381 return PTR_ERR(acl);
382 if (acl == NULL)
383 return -ENODATA;
384 error = posix_acl_to_xattr(&init_user_ns, acl, buffer, size);
385 posix_acl_release(acl);
386
387 return error;
388}
389
390static int
391ext3_xattr_set_acl(struct dentry *dentry, const char *name, const void *value,
392 size_t size, int flags, int type)
393{
394 struct inode *inode = dentry->d_inode;
395 handle_t *handle;
396 struct posix_acl *acl;
397 int error, retries = 0;
398
399 if (strcmp(name, "") != 0)
400 return -EINVAL;
401 if (!test_opt(inode->i_sb, POSIX_ACL))
402 return -EOPNOTSUPP;
403 if (!inode_owner_or_capable(inode))
404 return -EPERM;
405
406 if (value) {
407 acl = posix_acl_from_xattr(&init_user_ns, value, size);
408 if (IS_ERR(acl))
409 return PTR_ERR(acl);
410 else if (acl) {
411 error = posix_acl_valid(acl);
412 if (error)
413 goto release_and_out;
414 }
415 } else
416 acl = NULL;
417
418retry:
419 handle = ext3_journal_start(inode, EXT3_DATA_TRANS_BLOCKS(inode->i_sb));
420 if (IS_ERR(handle))
421 return PTR_ERR(handle);
422 error = ext3_set_acl(handle, inode, type, acl);
423 ext3_journal_stop(handle);
424 if (error == -ENOSPC && ext3_should_retry_alloc(inode->i_sb, &retries))
425 goto retry;
426 268
427release_and_out: 269 if (default_acl) {
428 posix_acl_release(acl); 270 error = __ext3_set_acl(handle, inode, ACL_TYPE_DEFAULT,
271 default_acl);
272 posix_acl_release(default_acl);
273 }
274 if (acl) {
275 if (!error)
276 error = __ext3_set_acl(handle, inode, ACL_TYPE_ACCESS,
277 acl);
278 posix_acl_release(acl);
279 }
429 return error; 280 return error;
430} 281}
431
432const struct xattr_handler ext3_xattr_acl_access_handler = {
433 .prefix = POSIX_ACL_XATTR_ACCESS,
434 .flags = ACL_TYPE_ACCESS,
435 .list = ext3_xattr_list_acl_access,
436 .get = ext3_xattr_get_acl,
437 .set = ext3_xattr_set_acl,
438};
439
440const struct xattr_handler ext3_xattr_acl_default_handler = {
441 .prefix = POSIX_ACL_XATTR_DEFAULT,
442 .flags = ACL_TYPE_DEFAULT,
443 .list = ext3_xattr_list_acl_default,
444 .get = ext3_xattr_get_acl,
445 .set = ext3_xattr_set_acl,
446};
diff --git a/fs/ext3/acl.h b/fs/ext3/acl.h
index dbc921e458c5..ea1c69edab9e 100644
--- a/fs/ext3/acl.h
+++ b/fs/ext3/acl.h
@@ -55,18 +55,13 @@ static inline int ext3_acl_count(size_t size)
55 55
56/* acl.c */ 56/* acl.c */
57extern struct posix_acl *ext3_get_acl(struct inode *inode, int type); 57extern struct posix_acl *ext3_get_acl(struct inode *inode, int type);
58extern int ext3_acl_chmod (struct inode *); 58extern int ext3_set_acl(struct inode *inode, struct posix_acl *acl, int type);
59extern int ext3_init_acl (handle_t *, struct inode *, struct inode *); 59extern int ext3_init_acl (handle_t *, struct inode *, struct inode *);
60 60
61#else /* CONFIG_EXT3_FS_POSIX_ACL */ 61#else /* CONFIG_EXT3_FS_POSIX_ACL */
62#include <linux/sched.h> 62#include <linux/sched.h>
63#define ext3_get_acl NULL 63#define ext3_get_acl NULL
64 64#define ext3_set_acl NULL
65static inline int
66ext3_acl_chmod(struct inode *inode)
67{
68 return 0;
69}
70 65
71static inline int 66static inline int
72ext3_init_acl(handle_t *handle, struct inode *inode, struct inode *dir) 67ext3_init_acl(handle_t *handle, struct inode *inode, struct inode *dir)
diff --git a/fs/ext3/file.c b/fs/ext3/file.c
index 25cb413277e9..aad05311392a 100644
--- a/fs/ext3/file.c
+++ b/fs/ext3/file.c
@@ -75,6 +75,7 @@ const struct inode_operations ext3_file_inode_operations = {
75 .removexattr = generic_removexattr, 75 .removexattr = generic_removexattr,
76#endif 76#endif
77 .get_acl = ext3_get_acl, 77 .get_acl = ext3_get_acl,
78 .set_acl = ext3_set_acl,
78 .fiemap = ext3_fiemap, 79 .fiemap = ext3_fiemap,
79}; 80};
80 81
diff --git a/fs/ext3/inode.c b/fs/ext3/inode.c
index 2bd85486b879..384b6ebb655f 100644
--- a/fs/ext3/inode.c
+++ b/fs/ext3/inode.c
@@ -3365,7 +3365,7 @@ int ext3_setattr(struct dentry *dentry, struct iattr *attr)
3365 mark_inode_dirty(inode); 3365 mark_inode_dirty(inode);
3366 3366
3367 if (ia_valid & ATTR_MODE) 3367 if (ia_valid & ATTR_MODE)
3368 rc = ext3_acl_chmod(inode); 3368 rc = posix_acl_chmod(inode, inode->i_mode);
3369 3369
3370err_out: 3370err_out:
3371 ext3_std_error(inode->i_sb, error); 3371 ext3_std_error(inode->i_sb, error);
diff --git a/fs/ext3/namei.c b/fs/ext3/namei.c
index f8cde46de9cd..f197736dccfa 100644
--- a/fs/ext3/namei.c
+++ b/fs/ext3/namei.c
@@ -2569,6 +2569,7 @@ const struct inode_operations ext3_dir_inode_operations = {
2569 .removexattr = generic_removexattr, 2569 .removexattr = generic_removexattr,
2570#endif 2570#endif
2571 .get_acl = ext3_get_acl, 2571 .get_acl = ext3_get_acl,
2572 .set_acl = ext3_set_acl,
2572}; 2573};
2573 2574
2574const struct inode_operations ext3_special_inode_operations = { 2575const struct inode_operations ext3_special_inode_operations = {
@@ -2580,4 +2581,5 @@ const struct inode_operations ext3_special_inode_operations = {
2580 .removexattr = generic_removexattr, 2581 .removexattr = generic_removexattr,
2581#endif 2582#endif
2582 .get_acl = ext3_get_acl, 2583 .get_acl = ext3_get_acl,
2584 .set_acl = ext3_set_acl,
2583}; 2585};
diff --git a/fs/ext3/xattr.c b/fs/ext3/xattr.c
index b1fc96383e08..c6874be6d58b 100644
--- a/fs/ext3/xattr.c
+++ b/fs/ext3/xattr.c
@@ -102,8 +102,8 @@ static struct mb_cache *ext3_xattr_cache;
102static const struct xattr_handler *ext3_xattr_handler_map[] = { 102static const struct xattr_handler *ext3_xattr_handler_map[] = {
103 [EXT3_XATTR_INDEX_USER] = &ext3_xattr_user_handler, 103 [EXT3_XATTR_INDEX_USER] = &ext3_xattr_user_handler,
104#ifdef CONFIG_EXT3_FS_POSIX_ACL 104#ifdef CONFIG_EXT3_FS_POSIX_ACL
105 [EXT3_XATTR_INDEX_POSIX_ACL_ACCESS] = &ext3_xattr_acl_access_handler, 105 [EXT3_XATTR_INDEX_POSIX_ACL_ACCESS] = &posix_acl_access_xattr_handler,
106 [EXT3_XATTR_INDEX_POSIX_ACL_DEFAULT] = &ext3_xattr_acl_default_handler, 106 [EXT3_XATTR_INDEX_POSIX_ACL_DEFAULT] = &posix_acl_default_xattr_handler,
107#endif 107#endif
108 [EXT3_XATTR_INDEX_TRUSTED] = &ext3_xattr_trusted_handler, 108 [EXT3_XATTR_INDEX_TRUSTED] = &ext3_xattr_trusted_handler,
109#ifdef CONFIG_EXT3_FS_SECURITY 109#ifdef CONFIG_EXT3_FS_SECURITY
@@ -115,8 +115,8 @@ const struct xattr_handler *ext3_xattr_handlers[] = {
115 &ext3_xattr_user_handler, 115 &ext3_xattr_user_handler,
116 &ext3_xattr_trusted_handler, 116 &ext3_xattr_trusted_handler,
117#ifdef CONFIG_EXT3_FS_POSIX_ACL 117#ifdef CONFIG_EXT3_FS_POSIX_ACL
118 &ext3_xattr_acl_access_handler, 118 &posix_acl_access_xattr_handler,
119 &ext3_xattr_acl_default_handler, 119 &posix_acl_default_xattr_handler,
120#endif 120#endif
121#ifdef CONFIG_EXT3_FS_SECURITY 121#ifdef CONFIG_EXT3_FS_SECURITY
122 &ext3_xattr_security_handler, 122 &ext3_xattr_security_handler,
diff --git a/fs/ext3/xattr.h b/fs/ext3/xattr.h
index 2be4f69bfa64..32e93ebf8031 100644
--- a/fs/ext3/xattr.h
+++ b/fs/ext3/xattr.h
@@ -60,8 +60,6 @@ struct ext3_xattr_entry {
60 60
61extern const struct xattr_handler ext3_xattr_user_handler; 61extern const struct xattr_handler ext3_xattr_user_handler;
62extern const struct xattr_handler ext3_xattr_trusted_handler; 62extern const struct xattr_handler ext3_xattr_trusted_handler;
63extern const struct xattr_handler ext3_xattr_acl_access_handler;
64extern const struct xattr_handler ext3_xattr_acl_default_handler;
65extern const struct xattr_handler ext3_xattr_security_handler; 63extern const struct xattr_handler ext3_xattr_security_handler;
66 64
67extern ssize_t ext3_listxattr(struct dentry *, char *, size_t); 65extern ssize_t ext3_listxattr(struct dentry *, char *, size_t);