diff options
author | Tiger Yang <tiger.yang@oracle.com> | 2008-11-13 22:16:41 -0500 |
---|---|---|
committer | Mark Fasheh <mfasheh@suse.com> | 2009-01-05 11:34:20 -0500 |
commit | 534eadddc1de8754a227202c0e747af4973f82ce (patch) | |
tree | e044976da3644f020ed1da420211cc433dbc0a92 | |
parent | 923f7f3102b80403152e05aee3d55ecfce240440 (diff) |
ocfs2: add ocfs2_init_security in during file create
Security attributes must be set when creating a new inode.
We do this in three steps.
- First, get security xattr's name and value by security_operation
- Calculate and reserve the meta data and clusters needed by this security
xattr before starting transaction
- Finally, we set it before add_entry
Signed-off-by: Tiger Yang <tiger.yang@oracle.com>
Signed-off-by: Mark Fasheh <mfasheh@suse.com>
-rw-r--r-- | fs/ocfs2/namei.c | 107 | ||||
-rw-r--r-- | fs/ocfs2/xattr.c | 70 | ||||
-rw-r--r-- | fs/ocfs2/xattr.h | 17 |
3 files changed, 182 insertions, 12 deletions
diff --git a/fs/ocfs2/namei.c b/fs/ocfs2/namei.c index e8ff0bae179d..40da46b907fb 100644 --- a/fs/ocfs2/namei.c +++ b/fs/ocfs2/namei.c | |||
@@ -229,6 +229,12 @@ static int ocfs2_mknod(struct inode *dir, | |||
229 | struct inode *inode = NULL; | 229 | struct inode *inode = NULL; |
230 | struct ocfs2_alloc_context *inode_ac = NULL; | 230 | struct ocfs2_alloc_context *inode_ac = NULL; |
231 | struct ocfs2_alloc_context *data_ac = NULL; | 231 | struct ocfs2_alloc_context *data_ac = NULL; |
232 | struct ocfs2_alloc_context *xattr_ac = NULL; | ||
233 | int want_clusters = 0; | ||
234 | int xattr_credits = 0; | ||
235 | struct ocfs2_security_xattr_info si = { | ||
236 | .enable = 1, | ||
237 | }; | ||
232 | 238 | ||
233 | mlog_entry("(0x%p, 0x%p, %d, %lu, '%.*s')\n", dir, dentry, mode, | 239 | mlog_entry("(0x%p, 0x%p, %d, %lu, '%.*s')\n", dir, dentry, mode, |
234 | (unsigned long)dev, dentry->d_name.len, | 240 | (unsigned long)dev, dentry->d_name.len, |
@@ -285,17 +291,39 @@ static int ocfs2_mknod(struct inode *dir, | |||
285 | goto leave; | 291 | goto leave; |
286 | } | 292 | } |
287 | 293 | ||
288 | /* Reserve a cluster if creating an extent based directory. */ | 294 | /* get security xattr */ |
289 | if (S_ISDIR(mode) && !ocfs2_supports_inline_data(osb)) { | 295 | status = ocfs2_init_security_get(inode, dir, &si); |
290 | status = ocfs2_reserve_clusters(osb, 1, &data_ac); | 296 | if (status) { |
297 | if (status == -EOPNOTSUPP) | ||
298 | si.enable = 0; | ||
299 | else { | ||
300 | mlog_errno(status); | ||
301 | goto leave; | ||
302 | } | ||
303 | } | ||
304 | |||
305 | /* calculate meta data/clusters for setting security xattr */ | ||
306 | if (si.enable) { | ||
307 | status = ocfs2_calc_security_init(dir, &si, &want_clusters, | ||
308 | &xattr_credits, &xattr_ac); | ||
291 | if (status < 0) { | 309 | if (status < 0) { |
292 | if (status != -ENOSPC) | 310 | mlog_errno(status); |
293 | mlog_errno(status); | ||
294 | goto leave; | 311 | goto leave; |
295 | } | 312 | } |
296 | } | 313 | } |
297 | 314 | ||
298 | handle = ocfs2_start_trans(osb, OCFS2_MKNOD_CREDITS); | 315 | /* Reserve a cluster if creating an extent based directory. */ |
316 | if (S_ISDIR(mode) && !ocfs2_supports_inline_data(osb)) | ||
317 | want_clusters += 1; | ||
318 | |||
319 | status = ocfs2_reserve_clusters(osb, want_clusters, &data_ac); | ||
320 | if (status < 0) { | ||
321 | if (status != -ENOSPC) | ||
322 | mlog_errno(status); | ||
323 | goto leave; | ||
324 | } | ||
325 | |||
326 | handle = ocfs2_start_trans(osb, OCFS2_MKNOD_CREDITS + xattr_credits); | ||
299 | if (IS_ERR(handle)) { | 327 | if (IS_ERR(handle)) { |
300 | status = PTR_ERR(handle); | 328 | status = PTR_ERR(handle); |
301 | handle = NULL; | 329 | handle = NULL; |
@@ -335,6 +363,15 @@ static int ocfs2_mknod(struct inode *dir, | |||
335 | inc_nlink(dir); | 363 | inc_nlink(dir); |
336 | } | 364 | } |
337 | 365 | ||
366 | if (si.enable) { | ||
367 | status = ocfs2_init_security_set(handle, inode, new_fe_bh, &si, | ||
368 | xattr_ac, data_ac); | ||
369 | if (status < 0) { | ||
370 | mlog_errno(status); | ||
371 | goto leave; | ||
372 | } | ||
373 | } | ||
374 | |||
338 | status = ocfs2_add_entry(handle, dentry, inode, | 375 | status = ocfs2_add_entry(handle, dentry, inode, |
339 | OCFS2_I(inode)->ip_blkno, parent_fe_bh, | 376 | OCFS2_I(inode)->ip_blkno, parent_fe_bh, |
340 | de_bh); | 377 | de_bh); |
@@ -366,6 +403,8 @@ leave: | |||
366 | brelse(new_fe_bh); | 403 | brelse(new_fe_bh); |
367 | brelse(de_bh); | 404 | brelse(de_bh); |
368 | brelse(parent_fe_bh); | 405 | brelse(parent_fe_bh); |
406 | kfree(si.name); | ||
407 | kfree(si.value); | ||
369 | 408 | ||
370 | if ((status < 0) && inode) { | 409 | if ((status < 0) && inode) { |
371 | clear_nlink(inode); | 410 | clear_nlink(inode); |
@@ -378,6 +417,9 @@ leave: | |||
378 | if (data_ac) | 417 | if (data_ac) |
379 | ocfs2_free_alloc_context(data_ac); | 418 | ocfs2_free_alloc_context(data_ac); |
380 | 419 | ||
420 | if (xattr_ac) | ||
421 | ocfs2_free_alloc_context(xattr_ac); | ||
422 | |||
381 | mlog_exit(status); | 423 | mlog_exit(status); |
382 | 424 | ||
383 | return status; | 425 | return status; |
@@ -1508,6 +1550,12 @@ static int ocfs2_symlink(struct inode *dir, | |||
1508 | handle_t *handle = NULL; | 1550 | handle_t *handle = NULL; |
1509 | struct ocfs2_alloc_context *inode_ac = NULL; | 1551 | struct ocfs2_alloc_context *inode_ac = NULL; |
1510 | struct ocfs2_alloc_context *data_ac = NULL; | 1552 | struct ocfs2_alloc_context *data_ac = NULL; |
1553 | struct ocfs2_alloc_context *xattr_ac = NULL; | ||
1554 | int want_clusters = 0; | ||
1555 | int xattr_credits = 0; | ||
1556 | struct ocfs2_security_xattr_info si = { | ||
1557 | .enable = 1, | ||
1558 | }; | ||
1511 | 1559 | ||
1512 | mlog_entry("(0x%p, 0x%p, symname='%s' actual='%.*s')\n", dir, | 1560 | mlog_entry("(0x%p, 0x%p, symname='%s' actual='%.*s')\n", dir, |
1513 | dentry, symname, dentry->d_name.len, dentry->d_name.name); | 1561 | dentry, symname, dentry->d_name.len, dentry->d_name.name); |
@@ -1561,17 +1609,39 @@ static int ocfs2_symlink(struct inode *dir, | |||
1561 | goto bail; | 1609 | goto bail; |
1562 | } | 1610 | } |
1563 | 1611 | ||
1564 | /* don't reserve bitmap space for fast symlinks. */ | 1612 | /* get security xattr */ |
1565 | if (l > ocfs2_fast_symlink_chars(sb)) { | 1613 | status = ocfs2_init_security_get(inode, dir, &si); |
1566 | status = ocfs2_reserve_clusters(osb, 1, &data_ac); | 1614 | if (status) { |
1615 | if (status == -EOPNOTSUPP) | ||
1616 | si.enable = 0; | ||
1617 | else { | ||
1618 | mlog_errno(status); | ||
1619 | goto bail; | ||
1620 | } | ||
1621 | } | ||
1622 | |||
1623 | /* calculate meta data/clusters for setting security xattr */ | ||
1624 | if (si.enable) { | ||
1625 | status = ocfs2_calc_security_init(dir, &si, &want_clusters, | ||
1626 | &xattr_credits, &xattr_ac); | ||
1567 | if (status < 0) { | 1627 | if (status < 0) { |
1568 | if (status != -ENOSPC) | 1628 | mlog_errno(status); |
1569 | mlog_errno(status); | ||
1570 | goto bail; | 1629 | goto bail; |
1571 | } | 1630 | } |
1572 | } | 1631 | } |
1573 | 1632 | ||
1574 | handle = ocfs2_start_trans(osb, credits); | 1633 | /* don't reserve bitmap space for fast symlinks. */ |
1634 | if (l > ocfs2_fast_symlink_chars(sb)) | ||
1635 | want_clusters += 1; | ||
1636 | |||
1637 | status = ocfs2_reserve_clusters(osb, want_clusters, &data_ac); | ||
1638 | if (status < 0) { | ||
1639 | if (status != -ENOSPC) | ||
1640 | mlog_errno(status); | ||
1641 | goto bail; | ||
1642 | } | ||
1643 | |||
1644 | handle = ocfs2_start_trans(osb, credits + xattr_credits); | ||
1575 | if (IS_ERR(handle)) { | 1645 | if (IS_ERR(handle)) { |
1576 | status = PTR_ERR(handle); | 1646 | status = PTR_ERR(handle); |
1577 | handle = NULL; | 1647 | handle = NULL; |
@@ -1632,6 +1702,15 @@ static int ocfs2_symlink(struct inode *dir, | |||
1632 | } | 1702 | } |
1633 | } | 1703 | } |
1634 | 1704 | ||
1705 | if (si.enable) { | ||
1706 | status = ocfs2_init_security_set(handle, inode, new_fe_bh, &si, | ||
1707 | xattr_ac, data_ac); | ||
1708 | if (status < 0) { | ||
1709 | mlog_errno(status); | ||
1710 | goto bail; | ||
1711 | } | ||
1712 | } | ||
1713 | |||
1635 | status = ocfs2_add_entry(handle, dentry, inode, | 1714 | status = ocfs2_add_entry(handle, dentry, inode, |
1636 | le64_to_cpu(fe->i_blkno), parent_fe_bh, | 1715 | le64_to_cpu(fe->i_blkno), parent_fe_bh, |
1637 | de_bh); | 1716 | de_bh); |
@@ -1658,10 +1737,14 @@ bail: | |||
1658 | brelse(new_fe_bh); | 1737 | brelse(new_fe_bh); |
1659 | brelse(parent_fe_bh); | 1738 | brelse(parent_fe_bh); |
1660 | brelse(de_bh); | 1739 | brelse(de_bh); |
1740 | kfree(si.name); | ||
1741 | kfree(si.value); | ||
1661 | if (inode_ac) | 1742 | if (inode_ac) |
1662 | ocfs2_free_alloc_context(inode_ac); | 1743 | ocfs2_free_alloc_context(inode_ac); |
1663 | if (data_ac) | 1744 | if (data_ac) |
1664 | ocfs2_free_alloc_context(data_ac); | 1745 | ocfs2_free_alloc_context(data_ac); |
1746 | if (xattr_ac) | ||
1747 | ocfs2_free_alloc_context(xattr_ac); | ||
1665 | if ((status < 0) && inode) { | 1748 | if ((status < 0) && inode) { |
1666 | clear_nlink(inode); | 1749 | clear_nlink(inode); |
1667 | iput(inode); | 1750 | iput(inode); |
diff --git a/fs/ocfs2/xattr.c b/fs/ocfs2/xattr.c index db03162914cc..2cab0d6615f9 100644 --- a/fs/ocfs2/xattr.c +++ b/fs/ocfs2/xattr.c | |||
@@ -81,6 +81,9 @@ struct ocfs2_xattr_set_ctxt { | |||
81 | 81 | ||
82 | #define OCFS2_XATTR_ROOT_SIZE (sizeof(struct ocfs2_xattr_def_value_root)) | 82 | #define OCFS2_XATTR_ROOT_SIZE (sizeof(struct ocfs2_xattr_def_value_root)) |
83 | #define OCFS2_XATTR_INLINE_SIZE 80 | 83 | #define OCFS2_XATTR_INLINE_SIZE 80 |
84 | #define OCFS2_XATTR_FREE_IN_IBODY (OCFS2_MIN_XATTR_INLINE_SIZE \ | ||
85 | - sizeof(struct ocfs2_xattr_header) \ | ||
86 | - sizeof(__u32)) | ||
84 | 87 | ||
85 | static struct ocfs2_xattr_def_value_root def_xv = { | 88 | static struct ocfs2_xattr_def_value_root def_xv = { |
86 | .xv.xr_list.l_count = cpu_to_le16(1), | 89 | .xv.xr_list.l_count = cpu_to_le16(1), |
@@ -343,6 +346,52 @@ static void ocfs2_xattr_hash_entry(struct inode *inode, | |||
343 | return; | 346 | return; |
344 | } | 347 | } |
345 | 348 | ||
349 | static int ocfs2_xattr_entry_real_size(int name_len, size_t value_len) | ||
350 | { | ||
351 | int size = 0; | ||
352 | |||
353 | if (value_len <= OCFS2_XATTR_INLINE_SIZE) | ||
354 | size = OCFS2_XATTR_SIZE(name_len) + OCFS2_XATTR_SIZE(value_len); | ||
355 | else | ||
356 | size = OCFS2_XATTR_SIZE(name_len) + OCFS2_XATTR_ROOT_SIZE; | ||
357 | size += sizeof(struct ocfs2_xattr_entry); | ||
358 | |||
359 | return size; | ||
360 | } | ||
361 | |||
362 | int ocfs2_calc_security_init(struct inode *dir, | ||
363 | struct ocfs2_security_xattr_info *si, | ||
364 | int *want_clusters, | ||
365 | int *xattr_credits, | ||
366 | struct ocfs2_alloc_context **xattr_ac) | ||
367 | { | ||
368 | int ret = 0; | ||
369 | struct ocfs2_super *osb = OCFS2_SB(dir->i_sb); | ||
370 | int s_size = ocfs2_xattr_entry_real_size(strlen(si->name), | ||
371 | si->value_len); | ||
372 | |||
373 | /* | ||
374 | * The max space of security xattr taken inline is | ||
375 | * 256(name) + 80(value) + 16(entry) = 352 bytes, | ||
376 | * So reserve one metadata block for it is ok. | ||
377 | */ | ||
378 | if (dir->i_sb->s_blocksize == OCFS2_MIN_BLOCKSIZE || | ||
379 | s_size > OCFS2_XATTR_FREE_IN_IBODY) { | ||
380 | ret = ocfs2_reserve_new_metadata_blocks(osb, 1, xattr_ac); | ||
381 | if (ret) { | ||
382 | mlog_errno(ret); | ||
383 | return ret; | ||
384 | } | ||
385 | *xattr_credits += OCFS2_XATTR_BLOCK_CREATE_CREDITS; | ||
386 | } | ||
387 | |||
388 | /* reserve clusters for xattr value which will be set in B tree*/ | ||
389 | if (si->value_len > OCFS2_XATTR_INLINE_SIZE) | ||
390 | *want_clusters += ocfs2_clusters_for_bytes(dir->i_sb, | ||
391 | si->value_len); | ||
392 | return ret; | ||
393 | } | ||
394 | |||
346 | static int ocfs2_xattr_extend_allocation(struct inode *inode, | 395 | static int ocfs2_xattr_extend_allocation(struct inode *inode, |
347 | u32 clusters_to_add, | 396 | u32 clusters_to_add, |
348 | struct buffer_head *xattr_bh, | 397 | struct buffer_head *xattr_bh, |
@@ -5016,6 +5065,27 @@ static int ocfs2_xattr_security_set(struct inode *inode, const char *name, | |||
5016 | size, flags); | 5065 | size, flags); |
5017 | } | 5066 | } |
5018 | 5067 | ||
5068 | int ocfs2_init_security_get(struct inode *inode, | ||
5069 | struct inode *dir, | ||
5070 | struct ocfs2_security_xattr_info *si) | ||
5071 | { | ||
5072 | return security_inode_init_security(inode, dir, &si->name, &si->value, | ||
5073 | &si->value_len); | ||
5074 | } | ||
5075 | |||
5076 | int ocfs2_init_security_set(handle_t *handle, | ||
5077 | struct inode *inode, | ||
5078 | struct buffer_head *di_bh, | ||
5079 | struct ocfs2_security_xattr_info *si, | ||
5080 | struct ocfs2_alloc_context *xattr_ac, | ||
5081 | struct ocfs2_alloc_context *data_ac) | ||
5082 | { | ||
5083 | return ocfs2_xattr_set_handle(handle, inode, di_bh, | ||
5084 | OCFS2_XATTR_INDEX_SECURITY, | ||
5085 | si->name, si->value, si->value_len, 0, | ||
5086 | xattr_ac, data_ac); | ||
5087 | } | ||
5088 | |||
5019 | struct xattr_handler ocfs2_xattr_security_handler = { | 5089 | struct xattr_handler ocfs2_xattr_security_handler = { |
5020 | .prefix = XATTR_SECURITY_PREFIX, | 5090 | .prefix = XATTR_SECURITY_PREFIX, |
5021 | .list = ocfs2_xattr_security_list, | 5091 | .list = ocfs2_xattr_security_list, |
diff --git a/fs/ocfs2/xattr.h b/fs/ocfs2/xattr.h index 55c5256ff563..188ef6ba6836 100644 --- a/fs/ocfs2/xattr.h +++ b/fs/ocfs2/xattr.h | |||
@@ -30,6 +30,13 @@ enum ocfs2_xattr_type { | |||
30 | OCFS2_XATTR_MAX | 30 | OCFS2_XATTR_MAX |
31 | }; | 31 | }; |
32 | 32 | ||
33 | struct ocfs2_security_xattr_info { | ||
34 | int enable; | ||
35 | char *name; | ||
36 | void *value; | ||
37 | size_t value_len; | ||
38 | }; | ||
39 | |||
33 | extern struct xattr_handler ocfs2_xattr_user_handler; | 40 | extern struct xattr_handler ocfs2_xattr_user_handler; |
34 | extern struct xattr_handler ocfs2_xattr_trusted_handler; | 41 | extern struct xattr_handler ocfs2_xattr_trusted_handler; |
35 | extern struct xattr_handler ocfs2_xattr_security_handler; | 42 | extern struct xattr_handler ocfs2_xattr_security_handler; |
@@ -43,5 +50,15 @@ int ocfs2_xattr_set_handle(handle_t *, struct inode *, struct buffer_head *, | |||
43 | struct ocfs2_alloc_context *, | 50 | struct ocfs2_alloc_context *, |
44 | struct ocfs2_alloc_context *); | 51 | struct ocfs2_alloc_context *); |
45 | int ocfs2_xattr_remove(struct inode *, struct buffer_head *); | 52 | int ocfs2_xattr_remove(struct inode *, struct buffer_head *); |
53 | int ocfs2_init_security_get(struct inode *, struct inode *, | ||
54 | struct ocfs2_security_xattr_info *); | ||
55 | int ocfs2_init_security_set(handle_t *, struct inode *, | ||
56 | struct buffer_head *, | ||
57 | struct ocfs2_security_xattr_info *, | ||
58 | struct ocfs2_alloc_context *, | ||
59 | struct ocfs2_alloc_context *); | ||
60 | int ocfs2_calc_security_init(struct inode *, | ||
61 | struct ocfs2_security_xattr_info *, | ||
62 | int *, int *, struct ocfs2_alloc_context **); | ||
46 | 63 | ||
47 | #endif /* OCFS2_XATTR_H */ | 64 | #endif /* OCFS2_XATTR_H */ |