+++ /dev/null
-From: Jeff Mahoney <jeffm@suse.com>
-Subject: 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>
-
---
- fs/reiserfs/inode.c | 16 +++++++++++-
- fs/reiserfs/namei.c | 37 +++++++++++++++++++++++++---
- fs/reiserfs/xattr_security.c | 54 +++++++++++++++++++++++++++++++++++++++++
- include/linux/reiserfs_fs.h | 4 ++-
- include/linux/reiserfs_xattr.h | 32 ++++++++++++++++++++++++
- 5 files changed, 137 insertions(+), 6 deletions(-)
-
---- a/fs/reiserfs/inode.c
-+++ b/fs/reiserfs/inode.c
-@@ -1756,7 +1756,8 @@ int reiserfs_new_inode(struct reiserfs_t
- /* 0 for regular, EMTRY_DIR_SIZE for dirs,
- strlen (symname) for symlinks) */
- loff_t i_size, struct dentry *dentry,
-- struct inode *inode)
-+ struct inode *inode,
-+ struct reiserfs_security_handle *security)
- {
- struct super_block *sb;
- INITIALIZE_PATH(path_to_key);
-@@ -1934,6 +1935,19 @@ int reiserfs_new_inode(struct reiserfs_t
- } else if (IS_PRIVATE(dir))
- inode->i_flags |= S_PRIVATE;
-
-+ if (security->name) {
-+ retval = reiserfs_security_write(th, inode, security);
-+ if (retval) {
-+ err = retval;
-+ reiserfs_check_path(&path_to_key);
-+ retval = journal_end(th, th->t_super,
-+ th->t_blocks_allocated);
-+ if (retval)
-+ err = retval;
-+ goto out_inserted_sd;
-+ }
-+ }
-+
- insert_inode_hash(inode);
- reiserfs_update_sd(th, inode);
- reiserfs_check_path(&path_to_key);
---- a/fs/reiserfs/namei.c
-+++ b/fs/reiserfs/namei.c
-@@ -607,6 +607,7 @@ static int reiserfs_create(struct inode
- 2 * (REISERFS_QUOTA_INIT_BLOCKS(dir->i_sb) +
- REISERFS_QUOTA_TRANS_BLOCKS(dir->i_sb));
- struct reiserfs_transaction_handle th;
-+ struct reiserfs_security_handle security;
-
- if (!(inode = new_inode(dir->i_sb))) {
- return -ENOMEM;
-@@ -614,6 +615,12 @@ static int reiserfs_create(struct inode
- new_inode_init(inode, dir, mode);
-
- jbegin_count += reiserfs_cache_default_acl(dir);
-+ retval = reiserfs_security_init(dir, inode, &security);
-+ if (retval < 0) {
-+ drop_new_inode(inode);
-+ return retval;
-+ }
-+ jbegin_count += retval;
- reiserfs_write_lock(dir->i_sb);
-
- retval = journal_begin(&th, dir->i_sb, jbegin_count);
-@@ -624,7 +631,7 @@ static int reiserfs_create(struct inode
-
- retval =
- reiserfs_new_inode(&th, dir, mode, NULL, 0 /*i_size */ , dentry,
-- inode);
-+ inode, &security);
- if (retval)
- goto out_failed;
-
-@@ -662,6 +669,7 @@ static int reiserfs_mknod(struct inode *
- int retval;
- struct inode *inode;
- struct reiserfs_transaction_handle th;
-+ struct reiserfs_security_handle security;
- /* We need blocks for transaction + (user+group)*(quotas for new inode + update of quota for directory owner) */
- int jbegin_count =
- JOURNAL_PER_BALANCE_CNT * 3 +
-@@ -677,6 +685,12 @@ static int reiserfs_mknod(struct inode *
- new_inode_init(inode, dir, mode);
-
- jbegin_count += reiserfs_cache_default_acl(dir);
-+ retval = reiserfs_security_init(dir, inode, &security);
-+ if (retval < 0) {
-+ drop_new_inode(inode);
-+ return retval;
-+ }
-+ jbegin_count += retval;
- reiserfs_write_lock(dir->i_sb);
-
- retval = journal_begin(&th, dir->i_sb, jbegin_count);
-@@ -687,7 +701,7 @@ static int reiserfs_mknod(struct inode *
-
- retval =
- reiserfs_new_inode(&th, dir, mode, NULL, 0 /*i_size */ , dentry,
-- inode);
-+ inode, &security);
- if (retval) {
- goto out_failed;
- }
-@@ -728,6 +742,7 @@ static int reiserfs_mkdir(struct inode *
- int retval;
- struct inode *inode;
- struct reiserfs_transaction_handle th;
-+ struct reiserfs_security_handle security;
- /* We need blocks for transaction + (user+group)*(quotas for new inode + update of quota for directory owner) */
- int jbegin_count =
- JOURNAL_PER_BALANCE_CNT * 3 +
-@@ -745,6 +760,12 @@ static int reiserfs_mkdir(struct inode *
- new_inode_init(inode, dir, mode);
-
- jbegin_count += reiserfs_cache_default_acl(dir);
-+ retval = reiserfs_security_init(dir, inode, &security);
-+ if (retval < 0) {
-+ drop_new_inode(inode);
-+ return retval;
-+ }
-+ jbegin_count += retval;
- reiserfs_write_lock(dir->i_sb);
-
- retval = journal_begin(&th, dir->i_sb, jbegin_count);
-@@ -761,7 +782,7 @@ static int reiserfs_mkdir(struct inode *
- retval = reiserfs_new_inode(&th, dir, mode, NULL /*symlink */ ,
- old_format_only(dir->i_sb) ?
- EMPTY_DIR_SIZE_V1 : EMPTY_DIR_SIZE,
-- dentry, inode);
-+ dentry, inode, &security);
- if (retval) {
- dir->i_nlink--;
- goto out_failed;
-@@ -1002,6 +1023,7 @@ static int reiserfs_symlink(struct inode
- char *name;
- int item_len;
- struct reiserfs_transaction_handle th;
-+ struct reiserfs_security_handle security;
- int mode = S_IFLNK | S_IRWXUGO;
- /* We need blocks for transaction + (user+group)*(quotas for new inode + update of quota for directory owner) */
- int jbegin_count =
-@@ -1014,6 +1036,13 @@ static int reiserfs_symlink(struct inode
- }
- new_inode_init(inode, parent_dir, mode);
-
-+ retval = reiserfs_security_init(parent_dir, inode, &security);
-+ if (retval < 0) {
-+ drop_new_inode(inode);
-+ return retval;
-+ }
-+ jbegin_count += retval;
-+
- reiserfs_write_lock(parent_dir->i_sb);
- item_len = ROUND_UP(strlen(symname));
- if (item_len > MAX_DIRECT_ITEM_LEN(parent_dir->i_sb->s_blocksize)) {
-@@ -1040,7 +1069,7 @@ static int reiserfs_symlink(struct inode
-
- retval =
- reiserfs_new_inode(&th, parent_dir, mode, name, strlen(symname),
-- dentry, inode);
-+ dentry, inode, &security);
- kfree(name);
- if (retval) { /* reiserfs_new_inode iputs for us */
- goto out_failed;
---- a/fs/reiserfs/xattr_security.c
-+++ b/fs/reiserfs/xattr_security.c
-@@ -4,6 +4,7 @@
- #include <linux/pagemap.h>
- #include <linux/xattr.h>
- #include <linux/reiserfs_xattr.h>
-+#include <linux/security.h>
- #include <asm/uaccess.h>
-
- static int
-@@ -47,6 +48,59 @@ static size_t security_list(struct inode
- return len;
- }
-
-+/* Initializes the security context for a new inode and returns the number
-+ * of blocks needed for the transaction. If successful, reiserfs_security
-+ * must be released using reiserfs_security_free when the caller is done. */
-+int reiserfs_security_init(struct inode *dir, struct inode *inode,
-+ struct reiserfs_security_handle *sec)
-+{
-+ int blocks = 0;
-+ int error = security_inode_init_security(inode, dir, &sec->name,
-+ &sec->value, &sec->length);
-+ if (error) {
-+ if (error == -EOPNOTSUPP)
-+ error = 0;
-+
-+ sec->name = NULL;
-+ sec->value = NULL;
-+ sec->length = 0;
-+ return error;
-+ }
-+
-+ if (sec->length) {
-+ blocks = reiserfs_xattr_jcreate_nblocks(inode) +
-+ reiserfs_xattr_nblocks(inode, sec->length);
-+ /* We don't want to count the directories twice if we have
-+ * a default ACL. */
-+ REISERFS_I(inode)->i_flags |= i_has_xattr_dir;
-+ }
-+ return blocks;
-+}
-+
-+int reiserfs_security_write(struct reiserfs_transaction_handle *th,
-+ struct inode *inode,
-+ struct reiserfs_security_handle *sec)
-+{
-+ int error;
-+ if (strlen(sec->name) < sizeof(XATTR_SECURITY_PREFIX))
-+ return -EINVAL;
-+
-+ error = reiserfs_xattr_set_handle(th, inode, sec->name, sec->value,
-+ sec->length, XATTR_CREATE);
-+ if (error == -ENODATA || error == -EOPNOTSUPP)
-+ error = 0;
-+
-+ return error;
-+}
-+
-+void reiserfs_security_free(struct reiserfs_security_handle *sec)
-+{
-+ kfree(sec->name);
-+ kfree(sec->value);
-+ sec->name = NULL;
-+ sec->value = NULL;
-+}
-+
- struct xattr_handler reiserfs_xattr_security_handler = {
- .prefix = XATTR_SECURITY_PREFIX,
- .get = security_get,
---- a/include/linux/reiserfs_fs.h
-+++ b/include/linux/reiserfs_fs.h
-@@ -1915,10 +1915,12 @@ void make_le_item_head(struct item_head
- loff_t offset, int type, int length, int entry_count);
- struct inode *reiserfs_iget(struct super_block *s, const struct cpu_key *key);
-
-+struct reiserfs_security_handle;
- int reiserfs_new_inode(struct reiserfs_transaction_handle *th,
- struct inode *dir, int mode,
- const char *symname, loff_t i_size,
-- struct dentry *dentry, struct inode *inode);
-+ struct dentry *dentry, struct inode *inode,
-+ struct reiserfs_security_handle *security);
-
- void reiserfs_update_sd_size(struct reiserfs_transaction_handle *th,
- struct inode *inode, loff_t size);
---- a/include/linux/reiserfs_xattr.h
-+++ b/include/linux/reiserfs_xattr.h
-@@ -15,6 +15,12 @@ struct reiserfs_xattr_header {
- __le32 h_hash; /* hash of the value */
- };
-
-+struct reiserfs_security_handle {
-+ char *name;
-+ void *value;
-+ size_t length;
-+};
-+
- #ifdef __KERNEL__
-
- #include <linux/init.h>
-@@ -54,6 +60,14 @@ int reiserfs_xattr_set_handle(struct rei
- extern struct xattr_handler reiserfs_xattr_user_handler;
- extern struct xattr_handler reiserfs_xattr_trusted_handler;
- extern struct xattr_handler reiserfs_xattr_security_handler;
-+#ifdef CONFIG_REISERFS_FS_SECURITY
-+int reiserfs_security_init(struct inode *dir, struct inode *inode,
-+ struct reiserfs_security_handle *sec);
-+int reiserfs_security_write(struct reiserfs_transaction_handle *th,
-+ struct inode *inode,
-+ struct reiserfs_security_handle *sec);
-+void reiserfs_security_free(struct reiserfs_security_handle *sec);
-+#endif
-
- #define xattr_size(size) ((size) + sizeof(struct reiserfs_xattr_header))
- static inline loff_t reiserfs_xattr_nblocks(struct inode *inode, loff_t size)
-@@ -109,6 +123,24 @@ static inline void reiserfs_init_xattr_r
- }
- #endif /* CONFIG_REISERFS_FS_XATTR */
-
-+#ifndef CONFIG_REISERFS_FS_SECURITY
-+static inline int reiserfs_security_init(struct inode *dir,
-+ struct inode *inode,
-+ struct reiserfs_security_handle *sec)
-+{
-+ return 0;
-+}
-+static inline int
-+reiserfs_security_write(struct reiserfs_transaction_handle *th,
-+ struct inode *inode,
-+ struct reiserfs_security_handle *sec)
-+{
-+ return 0;
-+}
-+static inline void reiserfs_security_free(struct reiserfs_security_handle *sec)
-+{}
-+#endif
-+
- #endif /* __KERNEL__ */
-
- #endif /* _LINUX_REISERFS_XATTR_H */