aboutsummaryrefslogtreecommitdiffstats
path: root/fs/ext2
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/ext2
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/ext2')
-rw-r--r--fs/ext2/acl.c188
-rw-r--r--fs/ext2/acl.h8
-rw-r--r--fs/ext2/file.c1
-rw-r--r--fs/ext2/inode.c2
-rw-r--r--fs/ext2/namei.c2
-rw-r--r--fs/ext2/xattr.c8
-rw-r--r--fs/ext2/xattr.h2
7 files changed, 23 insertions, 188 deletions
diff --git a/fs/ext2/acl.c b/fs/ext2/acl.c
index 6e842a764ee7..1b8001bbe947 100644
--- a/fs/ext2/acl.c
+++ b/fs/ext2/acl.c
@@ -148,13 +148,6 @@ ext2_get_acl(struct inode *inode, int type)
148 struct posix_acl *acl; 148 struct posix_acl *acl;
149 int retval; 149 int retval;
150 150
151 if (!test_opt(inode->i_sb, POSIX_ACL))
152 return NULL;
153
154 acl = get_cached_acl(inode, type);
155 if (acl != ACL_NOT_CACHED)
156 return acl;
157
158 switch (type) { 151 switch (type) {
159 case ACL_TYPE_ACCESS: 152 case ACL_TYPE_ACCESS:
160 name_index = EXT2_XATTR_INDEX_POSIX_ACL_ACCESS; 153 name_index = EXT2_XATTR_INDEX_POSIX_ACL_ACCESS;
@@ -189,19 +182,14 @@ ext2_get_acl(struct inode *inode, int type)
189/* 182/*
190 * inode->i_mutex: down 183 * inode->i_mutex: down
191 */ 184 */
192static int 185int
193ext2_set_acl(struct inode *inode, int type, struct posix_acl *acl) 186ext2_set_acl(struct inode *inode, struct posix_acl *acl, int type)
194{ 187{
195 int name_index; 188 int name_index;
196 void *value = NULL; 189 void *value = NULL;
197 size_t size = 0; 190 size_t size = 0;
198 int error; 191 int error;
199 192
200 if (S_ISLNK(inode->i_mode))
201 return -EOPNOTSUPP;
202 if (!test_opt(inode->i_sb, POSIX_ACL))
203 return 0;
204
205 switch(type) { 193 switch(type) {
206 case ACL_TYPE_ACCESS: 194 case ACL_TYPE_ACCESS:
207 name_index = EXT2_XATTR_INDEX_POSIX_ACL_ACCESS; 195 name_index = EXT2_XATTR_INDEX_POSIX_ACL_ACCESS;
@@ -250,169 +238,21 @@ ext2_set_acl(struct inode *inode, int type, struct posix_acl *acl)
250int 238int
251ext2_init_acl(struct inode *inode, struct inode *dir) 239ext2_init_acl(struct inode *inode, struct inode *dir)
252{ 240{
253 struct posix_acl *acl = NULL; 241 struct posix_acl *default_acl, *acl;
254 int error = 0; 242 int error;
255
256 if (!S_ISLNK(inode->i_mode)) {
257 if (test_opt(dir->i_sb, POSIX_ACL)) {
258 acl = ext2_get_acl(dir, ACL_TYPE_DEFAULT);
259 if (IS_ERR(acl))
260 return PTR_ERR(acl);
261 }
262 if (!acl)
263 inode->i_mode &= ~current_umask();
264 }
265 if (test_opt(inode->i_sb, POSIX_ACL) && acl) {
266 if (S_ISDIR(inode->i_mode)) {
267 error = ext2_set_acl(inode, ACL_TYPE_DEFAULT, acl);
268 if (error)
269 goto cleanup;
270 }
271 error = __posix_acl_create(&acl, GFP_KERNEL, &inode->i_mode);
272 if (error < 0)
273 return error;
274 if (error > 0) {
275 /* This is an extended ACL */
276 error = ext2_set_acl(inode, ACL_TYPE_ACCESS, acl);
277 }
278 }
279cleanup:
280 posix_acl_release(acl);
281 return error;
282}
283
284/*
285 * Does chmod for an inode that may have an Access Control List. The
286 * inode->i_mode field must be updated to the desired value by the caller
287 * before calling this function.
288 * Returns 0 on success, or a negative error number.
289 *
290 * We change the ACL rather than storing some ACL entries in the file
291 * mode permission bits (which would be more efficient), because that
292 * would break once additional permissions (like ACL_APPEND, ACL_DELETE
293 * for directories) are added. There are no more bits available in the
294 * file mode.
295 *
296 * inode->i_mutex: down
297 */
298int
299ext2_acl_chmod(struct inode *inode)
300{
301 struct posix_acl *acl;
302 int error;
303 243
304 if (!test_opt(inode->i_sb, POSIX_ACL)) 244 error = posix_acl_create(dir, &inode->i_mode, &default_acl, &acl);
305 return 0;
306 if (S_ISLNK(inode->i_mode))
307 return -EOPNOTSUPP;
308 acl = ext2_get_acl(inode, ACL_TYPE_ACCESS);
309 if (IS_ERR(acl) || !acl)
310 return PTR_ERR(acl);
311 error = __posix_acl_chmod(&acl, GFP_KERNEL, inode->i_mode);
312 if (error) 245 if (error)
313 return error; 246 return error;
314 error = ext2_set_acl(inode, ACL_TYPE_ACCESS, acl);
315 posix_acl_release(acl);
316 return error;
317}
318 247
319/* 248 if (default_acl) {
320 * Extended attribut handlers 249 error = ext2_set_acl(inode, default_acl, ACL_TYPE_DEFAULT);
321 */ 250 posix_acl_release(default_acl);
322static size_t 251 }
323ext2_xattr_list_acl_access(struct dentry *dentry, char *list, size_t list_size, 252 if (acl) {
324 const char *name, size_t name_len, int type) 253 if (!error)
325{ 254 error = ext2_set_acl(inode, acl, ACL_TYPE_ACCESS);
326 const size_t size = sizeof(POSIX_ACL_XATTR_ACCESS); 255 posix_acl_release(acl);
327 256 }
328 if (!test_opt(dentry->d_sb, POSIX_ACL))
329 return 0;
330 if (list && size <= list_size)
331 memcpy(list, POSIX_ACL_XATTR_ACCESS, size);
332 return size;
333}
334
335static size_t
336ext2_xattr_list_acl_default(struct dentry *dentry, char *list, size_t list_size,
337 const char *name, size_t name_len, int type)
338{
339 const size_t size = sizeof(POSIX_ACL_XATTR_DEFAULT);
340
341 if (!test_opt(dentry->d_sb, POSIX_ACL))
342 return 0;
343 if (list && size <= list_size)
344 memcpy(list, POSIX_ACL_XATTR_DEFAULT, size);
345 return size;
346}
347
348static int
349ext2_xattr_get_acl(struct dentry *dentry, const char *name, void *buffer,
350 size_t size, int type)
351{
352 struct posix_acl *acl;
353 int error;
354
355 if (strcmp(name, "") != 0)
356 return -EINVAL;
357 if (!test_opt(dentry->d_sb, POSIX_ACL))
358 return -EOPNOTSUPP;
359
360 acl = ext2_get_acl(dentry->d_inode, type);
361 if (IS_ERR(acl))
362 return PTR_ERR(acl);
363 if (acl == NULL)
364 return -ENODATA;
365 error = posix_acl_to_xattr(&init_user_ns, acl, buffer, size);
366 posix_acl_release(acl);
367
368 return error;
369}
370
371static int
372ext2_xattr_set_acl(struct dentry *dentry, const char *name, const void *value,
373 size_t size, int flags, int type)
374{
375 struct posix_acl *acl;
376 int error;
377
378 if (strcmp(name, "") != 0)
379 return -EINVAL;
380 if (!test_opt(dentry->d_sb, POSIX_ACL))
381 return -EOPNOTSUPP;
382 if (!inode_owner_or_capable(dentry->d_inode))
383 return -EPERM;
384
385 if (value) {
386 acl = posix_acl_from_xattr(&init_user_ns, value, size);
387 if (IS_ERR(acl))
388 return PTR_ERR(acl);
389 else if (acl) {
390 error = posix_acl_valid(acl);
391 if (error)
392 goto release_and_out;
393 }
394 } else
395 acl = NULL;
396
397 error = ext2_set_acl(dentry->d_inode, type, acl);
398
399release_and_out:
400 posix_acl_release(acl);
401 return error; 257 return error;
402} 258}
403
404const struct xattr_handler ext2_xattr_acl_access_handler = {
405 .prefix = POSIX_ACL_XATTR_ACCESS,
406 .flags = ACL_TYPE_ACCESS,
407 .list = ext2_xattr_list_acl_access,
408 .get = ext2_xattr_get_acl,
409 .set = ext2_xattr_set_acl,
410};
411
412const struct xattr_handler ext2_xattr_acl_default_handler = {
413 .prefix = POSIX_ACL_XATTR_DEFAULT,
414 .flags = ACL_TYPE_DEFAULT,
415 .list = ext2_xattr_list_acl_default,
416 .get = ext2_xattr_get_acl,
417 .set = ext2_xattr_set_acl,
418};
diff --git a/fs/ext2/acl.h b/fs/ext2/acl.h
index 503bfb0ed79b..44937f9fcf32 100644
--- a/fs/ext2/acl.h
+++ b/fs/ext2/acl.h
@@ -55,7 +55,7 @@ static inline int ext2_acl_count(size_t size)
55 55
56/* acl.c */ 56/* acl.c */
57extern struct posix_acl *ext2_get_acl(struct inode *inode, int type); 57extern struct posix_acl *ext2_get_acl(struct inode *inode, int type);
58extern int ext2_acl_chmod (struct inode *); 58extern int ext2_set_acl(struct inode *inode, struct posix_acl *acl, int type);
59extern int ext2_init_acl (struct inode *, struct inode *); 59extern int ext2_init_acl (struct inode *, struct inode *);
60 60
61#else 61#else
@@ -63,12 +63,6 @@ extern int ext2_init_acl (struct inode *, struct inode *);
63#define ext2_get_acl NULL 63#define ext2_get_acl NULL
64#define ext2_set_acl NULL 64#define ext2_set_acl NULL
65 65
66static inline int
67ext2_acl_chmod (struct inode *inode)
68{
69 return 0;
70}
71
72static inline int ext2_init_acl (struct inode *inode, struct inode *dir) 66static inline int ext2_init_acl (struct inode *inode, struct inode *dir)
73{ 67{
74 return 0; 68 return 0;
diff --git a/fs/ext2/file.c b/fs/ext2/file.c
index a5b3a5db3120..44c36e590765 100644
--- a/fs/ext2/file.c
+++ b/fs/ext2/file.c
@@ -103,5 +103,6 @@ const struct inode_operations ext2_file_inode_operations = {
103#endif 103#endif
104 .setattr = ext2_setattr, 104 .setattr = ext2_setattr,
105 .get_acl = ext2_get_acl, 105 .get_acl = ext2_get_acl,
106 .set_acl = ext2_set_acl,
106 .fiemap = ext2_fiemap, 107 .fiemap = ext2_fiemap,
107}; 108};
diff --git a/fs/ext2/inode.c b/fs/ext2/inode.c
index 8a337640a46a..94ed36849b71 100644
--- a/fs/ext2/inode.c
+++ b/fs/ext2/inode.c
@@ -1566,7 +1566,7 @@ int ext2_setattr(struct dentry *dentry, struct iattr *iattr)
1566 } 1566 }
1567 setattr_copy(inode, iattr); 1567 setattr_copy(inode, iattr);
1568 if (iattr->ia_valid & ATTR_MODE) 1568 if (iattr->ia_valid & ATTR_MODE)
1569 error = ext2_acl_chmod(inode); 1569 error = posix_acl_chmod(inode, inode->i_mode);
1570 mark_inode_dirty(inode); 1570 mark_inode_dirty(inode);
1571 1571
1572 return error; 1572 return error;
diff --git a/fs/ext2/namei.c b/fs/ext2/namei.c
index 256dd5f4c1c4..c268d0af1db9 100644
--- a/fs/ext2/namei.c
+++ b/fs/ext2/namei.c
@@ -421,6 +421,7 @@ const struct inode_operations ext2_dir_inode_operations = {
421#endif 421#endif
422 .setattr = ext2_setattr, 422 .setattr = ext2_setattr,
423 .get_acl = ext2_get_acl, 423 .get_acl = ext2_get_acl,
424 .set_acl = ext2_set_acl,
424 .tmpfile = ext2_tmpfile, 425 .tmpfile = ext2_tmpfile,
425}; 426};
426 427
@@ -433,4 +434,5 @@ const struct inode_operations ext2_special_inode_operations = {
433#endif 434#endif
434 .setattr = ext2_setattr, 435 .setattr = ext2_setattr,
435 .get_acl = ext2_get_acl, 436 .get_acl = ext2_get_acl,
437 .set_acl = ext2_set_acl,
436}; 438};
diff --git a/fs/ext2/xattr.c b/fs/ext2/xattr.c
index 2d7557db3ae8..91426141c33a 100644
--- a/fs/ext2/xattr.c
+++ b/fs/ext2/xattr.c
@@ -103,8 +103,8 @@ static struct mb_cache *ext2_xattr_cache;
103static const struct xattr_handler *ext2_xattr_handler_map[] = { 103static const struct xattr_handler *ext2_xattr_handler_map[] = {
104 [EXT2_XATTR_INDEX_USER] = &ext2_xattr_user_handler, 104 [EXT2_XATTR_INDEX_USER] = &ext2_xattr_user_handler,
105#ifdef CONFIG_EXT2_FS_POSIX_ACL 105#ifdef CONFIG_EXT2_FS_POSIX_ACL
106 [EXT2_XATTR_INDEX_POSIX_ACL_ACCESS] = &ext2_xattr_acl_access_handler, 106 [EXT2_XATTR_INDEX_POSIX_ACL_ACCESS] = &posix_acl_access_xattr_handler,
107 [EXT2_XATTR_INDEX_POSIX_ACL_DEFAULT] = &ext2_xattr_acl_default_handler, 107 [EXT2_XATTR_INDEX_POSIX_ACL_DEFAULT] = &posix_acl_default_xattr_handler,
108#endif 108#endif
109 [EXT2_XATTR_INDEX_TRUSTED] = &ext2_xattr_trusted_handler, 109 [EXT2_XATTR_INDEX_TRUSTED] = &ext2_xattr_trusted_handler,
110#ifdef CONFIG_EXT2_FS_SECURITY 110#ifdef CONFIG_EXT2_FS_SECURITY
@@ -116,8 +116,8 @@ const struct xattr_handler *ext2_xattr_handlers[] = {
116 &ext2_xattr_user_handler, 116 &ext2_xattr_user_handler,
117 &ext2_xattr_trusted_handler, 117 &ext2_xattr_trusted_handler,
118#ifdef CONFIG_EXT2_FS_POSIX_ACL 118#ifdef CONFIG_EXT2_FS_POSIX_ACL
119 &ext2_xattr_acl_access_handler, 119 &posix_acl_access_xattr_handler,
120 &ext2_xattr_acl_default_handler, 120 &posix_acl_default_xattr_handler,
121#endif 121#endif
122#ifdef CONFIG_EXT2_FS_SECURITY 122#ifdef CONFIG_EXT2_FS_SECURITY
123 &ext2_xattr_security_handler, 123 &ext2_xattr_security_handler,
diff --git a/fs/ext2/xattr.h b/fs/ext2/xattr.h
index 5e41cccff762..60edf298644e 100644
--- a/fs/ext2/xattr.h
+++ b/fs/ext2/xattr.h
@@ -57,8 +57,6 @@ struct ext2_xattr_entry {
57 57
58extern const struct xattr_handler ext2_xattr_user_handler; 58extern const struct xattr_handler ext2_xattr_user_handler;
59extern const struct xattr_handler ext2_xattr_trusted_handler; 59extern const struct xattr_handler ext2_xattr_trusted_handler;
60extern const struct xattr_handler ext2_xattr_acl_access_handler;
61extern const struct xattr_handler ext2_xattr_acl_default_handler;
62extern const struct xattr_handler ext2_xattr_security_handler; 60extern const struct xattr_handler ext2_xattr_security_handler;
63 61
64extern ssize_t ext2_listxattr(struct dentry *, char *, size_t); 62extern ssize_t ext2_listxattr(struct dentry *, char *, size_t);