diff options
-rw-r--r-- | fs/reiserfs/inode.c | 16 | ||||
-rw-r--r-- | fs/reiserfs/namei.c | 37 | ||||
-rw-r--r-- | fs/reiserfs/xattr_security.c | 54 | ||||
-rw-r--r-- | include/linux/reiserfs_fs.h | 4 | ||||
-rw-r--r-- | include/linux/reiserfs_xattr.h | 32 |
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 | ||
9 | static int | 10 | static 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. */ | ||
54 | int 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 | |||
80 | int 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 | |||
96 | void 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 | |||
50 | struct xattr_handler reiserfs_xattr_security_handler = { | 104 | struct 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); |
1916 | struct inode *reiserfs_iget(struct super_block *s, const struct cpu_key *key); | 1916 | struct inode *reiserfs_iget(struct super_block *s, const struct cpu_key *key); |
1917 | 1917 | ||
1918 | struct reiserfs_security_handle; | ||
1918 | int reiserfs_new_inode(struct reiserfs_transaction_handle *th, | 1919 | int 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 | ||
1923 | void reiserfs_update_sd_size(struct reiserfs_transaction_handle *th, | 1925 | void 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 | ||
18 | struct 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 *, | |||
54 | extern struct xattr_handler reiserfs_xattr_user_handler; | 60 | extern struct xattr_handler reiserfs_xattr_user_handler; |
55 | extern struct xattr_handler reiserfs_xattr_trusted_handler; | 61 | extern struct xattr_handler reiserfs_xattr_trusted_handler; |
56 | extern struct xattr_handler reiserfs_xattr_security_handler; | 62 | extern struct xattr_handler reiserfs_xattr_security_handler; |
63 | #ifdef CONFIG_REISERFS_FS_SECURITY | ||
64 | int reiserfs_security_init(struct inode *dir, struct inode *inode, | ||
65 | struct reiserfs_security_handle *sec); | ||
66 | int reiserfs_security_write(struct reiserfs_transaction_handle *th, | ||
67 | struct inode *inode, | ||
68 | struct reiserfs_security_handle *sec); | ||
69 | void 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)) |
59 | static inline loff_t reiserfs_xattr_nblocks(struct inode *inode, loff_t size) | 73 | static 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 | ||
127 | static inline int reiserfs_security_init(struct inode *dir, | ||
128 | struct inode *inode, | ||
129 | struct reiserfs_security_handle *sec) | ||
130 | { | ||
131 | return 0; | ||
132 | } | ||
133 | static inline int | ||
134 | reiserfs_security_write(struct reiserfs_transaction_handle *th, | ||
135 | struct inode *inode, | ||
136 | struct reiserfs_security_handle *sec) | ||
137 | { | ||
138 | return 0; | ||
139 | } | ||
140 | static 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 */ |