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 */ |
