diff options
author | KaiGai Kohei <kaigai@ak.jp.nec.com> | 2007-09-14 02:16:35 -0400 |
---|---|---|
committer | David Woodhouse <dwmw2@infradead.org> | 2007-10-20 09:10:54 -0400 |
commit | cfc8dc6f6f69ede939e09c2af06a01adee577285 (patch) | |
tree | a37149d6353fb4b911beb5ad4ad18f2ec2b1468a /fs/jffs2/acl.c | |
parent | e8b8c977734193adedf2b0f607d6252c78e86394 (diff) |
[JFFS2] Tidy up fix for ACL/permissions problem.
[In commit 9ed437c50d89eabae763dd422579f73fdebf288d we fixed a problem
with standard permissions on newly-created inodes, when POSIX ACLs are
enabled. This cleans it up...]
The attached patch separate jffs2_init_acl() into two parts.
The one is jffs2_init_acl_pre() called from jffs2_new_inode().
It compute ACL oriented inode->i_mode bits, and allocate in-memory ACL
objects associated with the new inode just before when inode meta
infomation is written to the medium.
The other is jffs2_init_acl_post() called from jffs2_symlink(),
jffs2_mkdir(), jffs2_mknod() and jffs2_do_create().
It actually writes in-memory ACL objects into the medium next to
the success of writing meta-information.
In the current implementation, we have to write a same inode meta
infomation twice when inode->i_mode is updated by the default ACL.
However, we can avoid the behavior by putting an updated i_mode
before it is written at first, as jffs2_init_acl_pre() doing.
Signed-off-by: KaiGai Kohei <kaigai@ak.jp.nec.com>
Signed-off-by: David Woodhouse <dwmw2@infradead.org>
Diffstat (limited to 'fs/jffs2/acl.c')
-rw-r--r-- | fs/jffs2/acl.c | 101 |
1 files changed, 65 insertions, 36 deletions
diff --git a/fs/jffs2/acl.c b/fs/jffs2/acl.c index 8ec9323e830a..9728614b8958 100644 --- a/fs/jffs2/acl.c +++ b/fs/jffs2/acl.c | |||
@@ -228,11 +228,28 @@ struct posix_acl *jffs2_get_acl(struct inode *inode, int type) | |||
228 | return acl; | 228 | return acl; |
229 | } | 229 | } |
230 | 230 | ||
231 | static int __jffs2_set_acl(struct inode *inode, int xprefix, struct posix_acl *acl) | ||
232 | { | ||
233 | char *value = NULL; | ||
234 | size_t size = 0; | ||
235 | int rc; | ||
236 | |||
237 | if (acl) { | ||
238 | value = jffs2_acl_to_medium(acl, &size); | ||
239 | if (IS_ERR(value)) | ||
240 | return PTR_ERR(value); | ||
241 | } | ||
242 | rc = do_jffs2_setxattr(inode, xprefix, "", value, size, 0); | ||
243 | if (!value && rc == -ENODATA) | ||
244 | rc = 0; | ||
245 | kfree(value); | ||
246 | |||
247 | return rc; | ||
248 | } | ||
249 | |||
231 | static int jffs2_set_acl(struct inode *inode, int type, struct posix_acl *acl) | 250 | static int jffs2_set_acl(struct inode *inode, int type, struct posix_acl *acl) |
232 | { | 251 | { |
233 | struct jffs2_inode_info *f = JFFS2_INODE_INFO(inode); | 252 | struct jffs2_inode_info *f = JFFS2_INODE_INFO(inode); |
234 | size_t size = 0; | ||
235 | char *value = NULL; | ||
236 | int rc, xprefix; | 253 | int rc, xprefix; |
237 | 254 | ||
238 | if (S_ISLNK(inode->i_mode)) | 255 | if (S_ISLNK(inode->i_mode)) |
@@ -267,17 +284,7 @@ static int jffs2_set_acl(struct inode *inode, int type, struct posix_acl *acl) | |||
267 | default: | 284 | default: |
268 | return -EINVAL; | 285 | return -EINVAL; |
269 | } | 286 | } |
270 | if (acl) { | 287 | rc = __jffs2_set_acl(inode, xprefix, acl); |
271 | value = jffs2_acl_to_medium(acl, &size); | ||
272 | if (IS_ERR(value)) | ||
273 | return PTR_ERR(value); | ||
274 | } | ||
275 | |||
276 | rc = do_jffs2_setxattr(inode, xprefix, "", value, size, 0); | ||
277 | if (!value && rc == -ENODATA) | ||
278 | rc = 0; | ||
279 | if (value) | ||
280 | kfree(value); | ||
281 | if (!rc) { | 288 | if (!rc) { |
282 | switch(type) { | 289 | switch(type) { |
283 | case ACL_TYPE_ACCESS: | 290 | case ACL_TYPE_ACCESS: |
@@ -312,37 +319,59 @@ int jffs2_permission(struct inode *inode, int mask, struct nameidata *nd) | |||
312 | return generic_permission(inode, mask, jffs2_check_acl); | 319 | return generic_permission(inode, mask, jffs2_check_acl); |
313 | } | 320 | } |
314 | 321 | ||
315 | int jffs2_init_acl(struct inode *inode, struct posix_acl *acl) | 322 | int jffs2_init_acl_pre(struct inode *dir_i, struct inode *inode, int *i_mode) |
316 | { | 323 | { |
317 | struct jffs2_inode_info *f = JFFS2_INODE_INFO(inode); | 324 | struct jffs2_inode_info *f = JFFS2_INODE_INFO(inode); |
318 | struct posix_acl *clone; | 325 | struct posix_acl *acl, *clone; |
319 | mode_t mode; | 326 | int rc; |
320 | int rc = 0; | ||
321 | 327 | ||
322 | f->i_acl_access = JFFS2_ACL_NOT_CACHED; | 328 | f->i_acl_default = NULL; |
323 | f->i_acl_default = JFFS2_ACL_NOT_CACHED; | 329 | f->i_acl_access = NULL; |
330 | |||
331 | if (S_ISLNK(*i_mode)) | ||
332 | return 0; /* Symlink always has no-ACL */ | ||
333 | |||
334 | acl = jffs2_get_acl(dir_i, ACL_TYPE_DEFAULT); | ||
335 | if (IS_ERR(acl)) | ||
336 | return PTR_ERR(acl); | ||
337 | |||
338 | if (!acl) { | ||
339 | *i_mode &= ~current->fs->umask; | ||
340 | } else { | ||
341 | if (S_ISDIR(*i_mode)) | ||
342 | jffs2_iset_acl(inode, &f->i_acl_default, acl); | ||
324 | 343 | ||
325 | if (acl) { | ||
326 | if (S_ISDIR(inode->i_mode)) { | ||
327 | rc = jffs2_set_acl(inode, ACL_TYPE_DEFAULT, acl); | ||
328 | if (rc) | ||
329 | goto cleanup; | ||
330 | } | ||
331 | clone = posix_acl_clone(acl, GFP_KERNEL); | 344 | clone = posix_acl_clone(acl, GFP_KERNEL); |
332 | rc = -ENOMEM; | ||
333 | if (!clone) | 345 | if (!clone) |
334 | goto cleanup; | 346 | return -ENOMEM; |
335 | mode = inode->i_mode; | 347 | rc = posix_acl_create_masq(clone, (mode_t *)i_mode); |
336 | rc = posix_acl_create_masq(clone, &mode); | 348 | if (rc < 0) |
337 | if (rc >= 0) { | 349 | return rc; |
338 | inode->i_mode = mode; | 350 | if (rc > 0) |
339 | if (rc > 0) | 351 | jffs2_iset_acl(inode, &f->i_acl_access, clone); |
340 | rc = jffs2_set_acl(inode, ACL_TYPE_ACCESS, clone); | 352 | |
341 | } | ||
342 | posix_acl_release(clone); | 353 | posix_acl_release(clone); |
343 | } | 354 | } |
344 | cleanup: | 355 | return 0; |
345 | posix_acl_release(acl); | 356 | } |
357 | |||
358 | int jffs2_init_acl_post(struct inode *inode) | ||
359 | { | ||
360 | struct jffs2_inode_info *f = JFFS2_INODE_INFO(inode); | ||
361 | int rc; | ||
362 | |||
363 | if (f->i_acl_default) { | ||
364 | rc = __jffs2_set_acl(inode, JFFS2_XPREFIX_ACL_DEFAULT, f->i_acl_default); | ||
365 | if (rc) | ||
366 | return rc; | ||
367 | } | ||
368 | |||
369 | if (f->i_acl_access) { | ||
370 | rc = __jffs2_set_acl(inode, JFFS2_XPREFIX_ACL_ACCESS, f->i_acl_access); | ||
371 | if (rc) | ||
372 | return rc; | ||
373 | } | ||
374 | |||
346 | return rc; | 375 | return rc; |
347 | } | 376 | } |
348 | 377 | ||