aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorJeff Mahoney <jeffm@suse.com>2009-03-30 14:02:41 -0400
committerLinus Torvalds <torvalds@linux-foundation.org>2009-03-30 15:16:39 -0400
commit57fe60df62410f949da094d06ced1dda9575b69c (patch)
treef3ba5db112cd7d2a8865d16bece28c38a766145c
parenta41f1a4715f26f7bc4d047d0bc7710145c8e69c7 (diff)
reiserfs: add atomic addition of selinux attributes during inode creation
Some time ago, some changes were made to make security inode attributes be atomically written during inode creation. ReiserFS fell behind in this area, but with the reworking of the xattr code, it's now fairly easy to add. The following patch adds the ability for security attributes to be added automatically during inode creation. Signed-off-by: Jeff Mahoney <jeffm@suse.com> Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
-rw-r--r--fs/reiserfs/inode.c16
-rw-r--r--fs/reiserfs/namei.c37
-rw-r--r--fs/reiserfs/xattr_security.c54
-rw-r--r--include/linux/reiserfs_fs.h4
-rw-r--r--include/linux/reiserfs_xattr.h32
5 files changed, 137 insertions, 6 deletions
diff --git a/fs/reiserfs/inode.c b/fs/reiserfs/inode.c
index 995f6975cae1..fcd302d81447 100644
--- a/fs/reiserfs/inode.c
+++ b/fs/reiserfs/inode.c
@@ -1747,7 +1747,8 @@ int reiserfs_new_inode(struct reiserfs_transaction_handle *th,
1747 /* 0 for regular, EMTRY_DIR_SIZE for dirs, 1747 /* 0 for regular, EMTRY_DIR_SIZE for dirs,
1748 strlen (symname) for symlinks) */ 1748 strlen (symname) for symlinks) */
1749 loff_t i_size, struct dentry *dentry, 1749 loff_t i_size, struct dentry *dentry,
1750 struct inode *inode) 1750 struct inode *inode,
1751 struct reiserfs_security_handle *security)
1751{ 1752{
1752 struct super_block *sb; 1753 struct super_block *sb;
1753 struct reiserfs_iget_args args; 1754 struct reiserfs_iget_args args;
@@ -1929,6 +1930,19 @@ int reiserfs_new_inode(struct reiserfs_transaction_handle *th,
1929 } else if (IS_PRIVATE(dir)) 1930 } else if (IS_PRIVATE(dir))
1930 inode->i_flags |= S_PRIVATE; 1931 inode->i_flags |= S_PRIVATE;
1931 1932
1933 if (security->name) {
1934 retval = reiserfs_security_write(th, inode, security);
1935 if (retval) {
1936 err = retval;
1937 reiserfs_check_path(&path_to_key);
1938 retval = journal_end(th, th->t_super,
1939 th->t_blocks_allocated);
1940 if (retval)
1941 err = retval;
1942 goto out_inserted_sd;
1943 }
1944 }
1945
1932 reiserfs_update_sd(th, inode); 1946 reiserfs_update_sd(th, inode);
1933 reiserfs_check_path(&path_to_key); 1947 reiserfs_check_path(&path_to_key);
1934 1948
diff --git a/fs/reiserfs/namei.c b/fs/reiserfs/namei.c
index d9c1c8bd2950..cb1a9e977907 100644
--- a/fs/reiserfs/namei.c
+++ b/fs/reiserfs/namei.c
@@ -598,6 +598,7 @@ static int reiserfs_create(struct inode *dir, struct dentry *dentry, int mode,
598 2 * (REISERFS_QUOTA_INIT_BLOCKS(dir->i_sb) + 598 2 * (REISERFS_QUOTA_INIT_BLOCKS(dir->i_sb) +
599 REISERFS_QUOTA_TRANS_BLOCKS(dir->i_sb)); 599 REISERFS_QUOTA_TRANS_BLOCKS(dir->i_sb));
600 struct reiserfs_transaction_handle th; 600 struct reiserfs_transaction_handle th;
601 struct reiserfs_security_handle security;
601 602
602 if (!(inode = new_inode(dir->i_sb))) { 603 if (!(inode = new_inode(dir->i_sb))) {
603 return -ENOMEM; 604 return -ENOMEM;
@@ -605,6 +606,12 @@ static int reiserfs_create(struct inode *dir, struct dentry *dentry, int mode,
605 new_inode_init(inode, dir, mode); 606 new_inode_init(inode, dir, mode);
606 607
607 jbegin_count += reiserfs_cache_default_acl(dir); 608 jbegin_count += reiserfs_cache_default_acl(dir);
609 retval = reiserfs_security_init(dir, inode, &security);
610 if (retval < 0) {
611 drop_new_inode(inode);
612 return retval;
613 }
614 jbegin_count += retval;
608 reiserfs_write_lock(dir->i_sb); 615 reiserfs_write_lock(dir->i_sb);
609 616
610 retval = journal_begin(&th, dir->i_sb, jbegin_count); 617 retval = journal_begin(&th, dir->i_sb, jbegin_count);
@@ -615,7 +622,7 @@ static int reiserfs_create(struct inode *dir, struct dentry *dentry, int mode,
615 622
616 retval = 623 retval =
617 reiserfs_new_inode(&th, dir, mode, NULL, 0 /*i_size */ , dentry, 624 reiserfs_new_inode(&th, dir, mode, NULL, 0 /*i_size */ , dentry,
618 inode); 625 inode, &security);
619 if (retval) 626 if (retval)
620 goto out_failed; 627 goto out_failed;
621 628
@@ -655,6 +662,7 @@ static int reiserfs_mknod(struct inode *dir, struct dentry *dentry, int mode,
655 int retval; 662 int retval;
656 struct inode *inode; 663 struct inode *inode;
657 struct reiserfs_transaction_handle th; 664 struct reiserfs_transaction_handle th;
665 struct reiserfs_security_handle security;
658 /* We need blocks for transaction + (user+group)*(quotas for new inode + update of quota for directory owner) */ 666 /* We need blocks for transaction + (user+group)*(quotas for new inode + update of quota for directory owner) */
659 int jbegin_count = 667 int jbegin_count =
660 JOURNAL_PER_BALANCE_CNT * 3 + 668 JOURNAL_PER_BALANCE_CNT * 3 +
@@ -670,6 +678,12 @@ static int reiserfs_mknod(struct inode *dir, struct dentry *dentry, int mode,
670 new_inode_init(inode, dir, mode); 678 new_inode_init(inode, dir, mode);
671 679
672 jbegin_count += reiserfs_cache_default_acl(dir); 680 jbegin_count += reiserfs_cache_default_acl(dir);
681 retval = reiserfs_security_init(dir, inode, &security);
682 if (retval < 0) {
683 drop_new_inode(inode);
684 return retval;
685 }
686 jbegin_count += retval;
673 reiserfs_write_lock(dir->i_sb); 687 reiserfs_write_lock(dir->i_sb);
674 688
675 retval = journal_begin(&th, dir->i_sb, jbegin_count); 689 retval = journal_begin(&th, dir->i_sb, jbegin_count);
@@ -680,7 +694,7 @@ static int reiserfs_mknod(struct inode *dir, struct dentry *dentry, int mode,
680 694
681 retval = 695 retval =
682 reiserfs_new_inode(&th, dir, mode, NULL, 0 /*i_size */ , dentry, 696 reiserfs_new_inode(&th, dir, mode, NULL, 0 /*i_size */ , dentry,
683 inode); 697 inode, &security);
684 if (retval) { 698 if (retval) {
685 goto out_failed; 699 goto out_failed;
686 } 700 }
@@ -723,6 +737,7 @@ static int reiserfs_mkdir(struct inode *dir, struct dentry *dentry, int mode)
723 int retval; 737 int retval;
724 struct inode *inode; 738 struct inode *inode;
725 struct reiserfs_transaction_handle th; 739 struct reiserfs_transaction_handle th;
740 struct reiserfs_security_handle security;
726 /* We need blocks for transaction + (user+group)*(quotas for new inode + update of quota for directory owner) */ 741 /* We need blocks for transaction + (user+group)*(quotas for new inode + update of quota for directory owner) */
727 int jbegin_count = 742 int jbegin_count =
728 JOURNAL_PER_BALANCE_CNT * 3 + 743 JOURNAL_PER_BALANCE_CNT * 3 +
@@ -740,6 +755,12 @@ static int reiserfs_mkdir(struct inode *dir, struct dentry *dentry, int mode)
740 new_inode_init(inode, dir, mode); 755 new_inode_init(inode, dir, mode);
741 756
742 jbegin_count += reiserfs_cache_default_acl(dir); 757 jbegin_count += reiserfs_cache_default_acl(dir);
758 retval = reiserfs_security_init(dir, inode, &security);
759 if (retval < 0) {
760 drop_new_inode(inode);
761 return retval;
762 }
763 jbegin_count += retval;
743 reiserfs_write_lock(dir->i_sb); 764 reiserfs_write_lock(dir->i_sb);
744 765
745 retval = journal_begin(&th, dir->i_sb, jbegin_count); 766 retval = journal_begin(&th, dir->i_sb, jbegin_count);
@@ -756,7 +777,7 @@ static int reiserfs_mkdir(struct inode *dir, struct dentry *dentry, int mode)
756 retval = reiserfs_new_inode(&th, dir, mode, NULL /*symlink */ , 777 retval = reiserfs_new_inode(&th, dir, mode, NULL /*symlink */ ,
757 old_format_only(dir->i_sb) ? 778 old_format_only(dir->i_sb) ?
758 EMPTY_DIR_SIZE_V1 : EMPTY_DIR_SIZE, 779 EMPTY_DIR_SIZE_V1 : EMPTY_DIR_SIZE,
759 dentry, inode); 780 dentry, inode, &security);
760 if (retval) { 781 if (retval) {
761 dir->i_nlink--; 782 dir->i_nlink--;
762 goto out_failed; 783 goto out_failed;
@@ -999,6 +1020,7 @@ static int reiserfs_symlink(struct inode *parent_dir,
999 char *name; 1020 char *name;
1000 int item_len; 1021 int item_len;
1001 struct reiserfs_transaction_handle th; 1022 struct reiserfs_transaction_handle th;
1023 struct reiserfs_security_handle security;
1002 int mode = S_IFLNK | S_IRWXUGO; 1024 int mode = S_IFLNK | S_IRWXUGO;
1003 /* We need blocks for transaction + (user+group)*(quotas for new inode + update of quota for directory owner) */ 1025 /* We need blocks for transaction + (user+group)*(quotas for new inode + update of quota for directory owner) */
1004 int jbegin_count = 1026 int jbegin_count =
@@ -1011,6 +1033,13 @@ static int reiserfs_symlink(struct inode *parent_dir,
1011 } 1033 }
1012 new_inode_init(inode, parent_dir, mode); 1034 new_inode_init(inode, parent_dir, mode);
1013 1035
1036 retval = reiserfs_security_init(parent_dir, inode, &security);
1037 if (retval < 0) {
1038 drop_new_inode(inode);
1039 return retval;
1040 }
1041 jbegin_count += retval;
1042
1014 reiserfs_write_lock(parent_dir->i_sb); 1043 reiserfs_write_lock(parent_dir->i_sb);
1015 item_len = ROUND_UP(strlen(symname)); 1044 item_len = ROUND_UP(strlen(symname));
1016 if (item_len > MAX_DIRECT_ITEM_LEN(parent_dir->i_sb->s_blocksize)) { 1045 if (item_len > MAX_DIRECT_ITEM_LEN(parent_dir->i_sb->s_blocksize)) {
@@ -1037,7 +1066,7 @@ static int reiserfs_symlink(struct inode *parent_dir,
1037 1066
1038 retval = 1067 retval =
1039 reiserfs_new_inode(&th, parent_dir, mode, name, strlen(symname), 1068 reiserfs_new_inode(&th, parent_dir, mode, name, strlen(symname),
1040 dentry, inode); 1069 dentry, inode, &security);
1041 kfree(name); 1070 kfree(name);
1042 if (retval) { /* reiserfs_new_inode iputs for us */ 1071 if (retval) { /* reiserfs_new_inode iputs for us */
1043 goto out_failed; 1072 goto out_failed;
diff --git a/fs/reiserfs/xattr_security.c b/fs/reiserfs/xattr_security.c
index 2aacf1fe69fd..4d3c20e787c3 100644
--- a/fs/reiserfs/xattr_security.c
+++ b/fs/reiserfs/xattr_security.c
@@ -4,6 +4,7 @@
4#include <linux/pagemap.h> 4#include <linux/pagemap.h>
5#include <linux/xattr.h> 5#include <linux/xattr.h>
6#include <linux/reiserfs_xattr.h> 6#include <linux/reiserfs_xattr.h>
7#include <linux/security.h>
7#include <asm/uaccess.h> 8#include <asm/uaccess.h>
8 9
9static int 10static int
@@ -47,6 +48,59 @@ static size_t security_list(struct inode *inode, char *list, size_t list_len,
47 return len; 48 return len;
48} 49}
49 50
51/* Initializes the security context for a new inode and returns the number
52 * of blocks needed for the transaction. If successful, reiserfs_security
53 * must be released using reiserfs_security_free when the caller is done. */
54int reiserfs_security_init(struct inode *dir, struct inode *inode,
55 struct reiserfs_security_handle *sec)
56{
57 int blocks = 0;
58 int error = security_inode_init_security(inode, dir, &sec->name,
59 &sec->value, &sec->length);
60 if (error) {
61 if (error == -EOPNOTSUPP)
62 error = 0;
63
64 sec->name = NULL;
65 sec->value = NULL;
66 sec->length = 0;
67 return error;
68 }
69
70 if (sec->length) {
71 blocks = reiserfs_xattr_jcreate_nblocks(inode) +
72 reiserfs_xattr_nblocks(inode, sec->length);
73 /* We don't want to count the directories twice if we have
74 * a default ACL. */
75 REISERFS_I(inode)->i_flags |= i_has_xattr_dir;
76 }
77 return blocks;
78}
79
80int reiserfs_security_write(struct reiserfs_transaction_handle *th,
81 struct inode *inode,
82 struct reiserfs_security_handle *sec)
83{
84 int error;
85 if (strlen(sec->name) < sizeof(XATTR_SECURITY_PREFIX))
86 return -EINVAL;
87
88 error = reiserfs_xattr_set_handle(th, inode, sec->name, sec->value,
89 sec->length, XATTR_CREATE);
90 if (error == -ENODATA || error == -EOPNOTSUPP)
91 error = 0;
92
93 return error;
94}
95
96void reiserfs_security_free(struct reiserfs_security_handle *sec)
97{
98 kfree(sec->name);
99 kfree(sec->value);
100 sec->name = NULL;
101 sec->value = NULL;
102}
103
50struct xattr_handler reiserfs_xattr_security_handler = { 104struct xattr_handler reiserfs_xattr_security_handler = {
51 .prefix = XATTR_SECURITY_PREFIX, 105 .prefix = XATTR_SECURITY_PREFIX,
52 .get = security_get, 106 .get = security_get,
diff --git a/include/linux/reiserfs_fs.h b/include/linux/reiserfs_fs.h
index c0365e07fce6..eb4e912e6bd3 100644
--- a/include/linux/reiserfs_fs.h
+++ b/include/linux/reiserfs_fs.h
@@ -1915,10 +1915,12 @@ void make_le_item_head(struct item_head *ih, const struct cpu_key *key,
1915 loff_t offset, int type, int length, int entry_count); 1915 loff_t offset, int type, int length, int entry_count);
1916struct inode *reiserfs_iget(struct super_block *s, const struct cpu_key *key); 1916struct inode *reiserfs_iget(struct super_block *s, const struct cpu_key *key);
1917 1917
1918struct reiserfs_security_handle;
1918int reiserfs_new_inode(struct reiserfs_transaction_handle *th, 1919int reiserfs_new_inode(struct reiserfs_transaction_handle *th,
1919 struct inode *dir, int mode, 1920 struct inode *dir, int mode,
1920 const char *symname, loff_t i_size, 1921 const char *symname, loff_t i_size,
1921 struct dentry *dentry, struct inode *inode); 1922 struct dentry *dentry, struct inode *inode,
1923 struct reiserfs_security_handle *security);
1922 1924
1923void reiserfs_update_sd_size(struct reiserfs_transaction_handle *th, 1925void reiserfs_update_sd_size(struct reiserfs_transaction_handle *th,
1924 struct inode *inode, loff_t size); 1926 struct inode *inode, loff_t size);
diff --git a/include/linux/reiserfs_xattr.h b/include/linux/reiserfs_xattr.h
index 20eca09729a2..dcae01e63e40 100644
--- a/include/linux/reiserfs_xattr.h
+++ b/include/linux/reiserfs_xattr.h
@@ -15,6 +15,12 @@ struct reiserfs_xattr_header {
15 __le32 h_hash; /* hash of the value */ 15 __le32 h_hash; /* hash of the value */
16}; 16};
17 17
18struct reiserfs_security_handle {
19 char *name;
20 void *value;
21 size_t length;
22};
23
18#ifdef __KERNEL__ 24#ifdef __KERNEL__
19 25
20#include <linux/init.h> 26#include <linux/init.h>
@@ -54,6 +60,14 @@ int reiserfs_xattr_set_handle(struct reiserfs_transaction_handle *,
54extern struct xattr_handler reiserfs_xattr_user_handler; 60extern struct xattr_handler reiserfs_xattr_user_handler;
55extern struct xattr_handler reiserfs_xattr_trusted_handler; 61extern struct xattr_handler reiserfs_xattr_trusted_handler;
56extern struct xattr_handler reiserfs_xattr_security_handler; 62extern struct xattr_handler reiserfs_xattr_security_handler;
63#ifdef CONFIG_REISERFS_FS_SECURITY
64int reiserfs_security_init(struct inode *dir, struct inode *inode,
65 struct reiserfs_security_handle *sec);
66int reiserfs_security_write(struct reiserfs_transaction_handle *th,
67 struct inode *inode,
68 struct reiserfs_security_handle *sec);
69void reiserfs_security_free(struct reiserfs_security_handle *sec);
70#endif
57 71
58#define xattr_size(size) ((size) + sizeof(struct reiserfs_xattr_header)) 72#define xattr_size(size) ((size) + sizeof(struct reiserfs_xattr_header))
59static inline loff_t reiserfs_xattr_nblocks(struct inode *inode, loff_t size) 73static inline loff_t reiserfs_xattr_nblocks(struct inode *inode, loff_t size)
@@ -109,6 +123,24 @@ static inline void reiserfs_init_xattr_rwsem(struct inode *inode)
109} 123}
110#endif /* CONFIG_REISERFS_FS_XATTR */ 124#endif /* CONFIG_REISERFS_FS_XATTR */
111 125
126#ifndef CONFIG_REISERFS_FS_SECURITY
127static inline int reiserfs_security_init(struct inode *dir,
128 struct inode *inode,
129 struct reiserfs_security_handle *sec)
130{
131 return 0;
132}
133static inline int
134reiserfs_security_write(struct reiserfs_transaction_handle *th,
135 struct inode *inode,
136 struct reiserfs_security_handle *sec)
137{
138 return 0;
139}
140static inline void reiserfs_security_free(struct reiserfs_security_handle *sec)
141{}
142#endif
143
112#endif /* __KERNEL__ */ 144#endif /* __KERNEL__ */
113 145
114#endif /* _LINUX_REISERFS_XATTR_H */ 146#endif /* _LINUX_REISERFS_XATTR_H */