aboutsummaryrefslogtreecommitdiffstats
path: root/fs/jffs2/acl.c
diff options
context:
space:
mode:
authorKaiGai Kohei <kaigai@ak.jp.nec.com>2007-09-14 02:16:35 -0400
committerDavid Woodhouse <dwmw2@infradead.org>2007-10-20 09:10:54 -0400
commitcfc8dc6f6f69ede939e09c2af06a01adee577285 (patch)
treea37149d6353fb4b911beb5ad4ad18f2ec2b1468a /fs/jffs2/acl.c
parente8b8c977734193adedf2b0f607d6252c78e86394 (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.c101
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
231static 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
231static int jffs2_set_acl(struct inode *inode, int type, struct posix_acl *acl) 250static 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
315int jffs2_init_acl(struct inode *inode, struct posix_acl *acl) 322int 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
358int 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