Option 1: In preparation for supporting the initialization of multiple LSM xattrs and the EVM xattr, this patch defines an xattr structure and changes the security_inode_init_security() API to return an array of xattrs. Until multiple LSM support is upstreamed, to avoid allocating/freeing the xattr array, define the xattr array in the security_inode_init_security() caller, not security_inode_init_security. Signed-off-by: Mimi Zohar <zohar@xxxxxxxxxx> --- fs/ext3/xattr_security.c | 33 ++++++++++++++++++++------------- fs/ext4/xattr_security.c | 33 ++++++++++++++++++++------------- include/linux/security.h | 10 +++++----- include/linux/xattr.h | 6 ++++++ mm/shmem.c | 7 +++---- security/security.c | 17 +++++++++++++---- 6 files changed, 67 insertions(+), 39 deletions(-) diff --git a/fs/ext3/xattr_security.c b/fs/ext3/xattr_security.c index b8d9f83..cb26a02 100644 --- a/fs/ext3/xattr_security.c +++ b/fs/ext3/xattr_security.c @@ -52,22 +52,29 @@ int ext3_init_security(handle_t *handle, struct inode *inode, struct inode *dir, const struct qstr *qstr) { + struct xattr new_xattrs[MAX_LSM_XATTR + 1]; + struct xattr *xattr_array = &new_xattrs[0], *xattr; int err; - size_t len; - void *value; - char *name; - err = security_inode_init_security(inode, dir, qstr, &name, &value, &len); - if (err) { - if (err == -EOPNOTSUPP) - return 0; - return err; + memset(new_xattrs, 0, sizeof new_xattrs); + err = security_inode_init_security(inode, dir, qstr, &xattr_array); + if (err) + goto out; + + for (xattr = new_xattrs; xattr->name != NULL; xattr++) { + err = ext3_xattr_set_handle(handle, inode, + EXT3_XATTR_INDEX_SECURITY, + xattr->name, xattr->value, + xattr->value_len, 0); + if (err < 0) + break; + } +out: + for (xattr = new_xattrs; xattr->name != NULL; xattr++) { + kfree(xattr->value); + kfree(xattr->name); } - err = ext3_xattr_set_handle(handle, inode, EXT3_XATTR_INDEX_SECURITY, - name, value, len, 0); - kfree(name); - kfree(value); - return err; + return (err == -EOPNOTSUPP) ? 0 : err; } const struct xattr_handler ext3_xattr_security_handler = { diff --git a/fs/ext4/xattr_security.c b/fs/ext4/xattr_security.c index 007c3bf..ccf3347 100644 --- a/fs/ext4/xattr_security.c +++ b/fs/ext4/xattr_security.c @@ -52,22 +52,29 @@ int ext4_init_security(handle_t *handle, struct inode *inode, struct inode *dir, const struct qstr *qstr) { + struct xattr new_xattrs[MAX_LSM_XATTR + 1]; + struct xattr *xattr_array = &new_xattrs[0], *xattr; int err; - size_t len; - void *value; - char *name; - err = security_inode_init_security(inode, dir, qstr, &name, &value, &len); - if (err) { - if (err == -EOPNOTSUPP) - return 0; - return err; + memset(new_xattrs, 0, sizeof new_xattrs); + err = security_inode_init_security(inode, dir, qstr, &xattr_array); + if (err) + goto out; + + for (xattr = new_xattrs; xattr->name != NULL; xattr++) { + err = ext4_xattr_set_handle(handle, inode, + EXT4_XATTR_INDEX_SECURITY, + xattr->name, xattr->value, + xattr->value_len, 0); + if (err < 0) + break; + } +out: + for (xattr = new_xattrs; xattr->name != NULL; xattr++) { + kfree(xattr->name); + kfree(xattr->value); } - err = ext4_xattr_set_handle(handle, inode, EXT4_XATTR_INDEX_SECURITY, - name, value, len, 0); - kfree(name); - kfree(value); - return err; + return (err == -EOPNOTSUPP) ? 0 : err; } const struct xattr_handler ext4_xattr_security_handler = { diff --git a/include/linux/security.h b/include/linux/security.h index 8ce59ef..bf593c1 100644 --- a/include/linux/security.h +++ b/include/linux/security.h @@ -36,10 +36,12 @@ #include <linux/key.h> #include <linux/xfrm.h> #include <linux/slab.h> +#include <linux/xattr.h> #include <net/flow.h> /* Maximum number of letters for an LSM name string */ #define SECURITY_NAME_MAX 10 +#define MAX_LSM_XATTR 1 /* If capable should audit the security request */ #define SECURITY_CAP_NOAUDIT 0 @@ -1704,8 +1706,8 @@ int security_sb_parse_opts_str(char *options, struct security_mnt_opts *opts); int security_inode_alloc(struct inode *inode); void security_inode_free(struct inode *inode); int security_inode_init_security(struct inode *inode, struct inode *dir, - const struct qstr *qstr, char **name, - void **value, size_t *len); + const struct qstr *qstr, + struct xattr **xattr_array); int security_inode_create(struct inode *dir, struct dentry *dentry, int mode); int security_inode_link(struct dentry *old_dentry, struct inode *dir, struct dentry *new_dentry); @@ -2035,9 +2037,7 @@ static inline void security_inode_free(struct inode *inode) static inline int security_inode_init_security(struct inode *inode, struct inode *dir, const struct qstr *qstr, - char **name, - void **value, - size_t *len) + struct xattr **xattr_array) { return -EOPNOTSUPP; } diff --git a/include/linux/xattr.h b/include/linux/xattr.h index aed54c5..7a37866 100644 --- a/include/linux/xattr.h +++ b/include/linux/xattr.h @@ -67,6 +67,12 @@ struct xattr_handler { size_t size, int flags, int handler_flags); }; +struct xattr { + char *name; + void *value; + size_t value_len; +}; + ssize_t xattr_getsecurity(struct inode *, const char *, void *, size_t); ssize_t vfs_getxattr(struct dentry *, const char *, void *, size_t); ssize_t vfs_listxattr(struct dentry *d, char *list, size_t size); diff --git a/mm/shmem.c b/mm/shmem.c index d221a1c..1d585b3 100644 --- a/mm/shmem.c +++ b/mm/shmem.c @@ -1877,8 +1877,7 @@ shmem_mknod(struct inode *dir, struct dentry *dentry, int mode, dev_t dev) inode = shmem_get_inode(dir->i_sb, dir, mode, dev, VM_NORESERVE); if (inode) { error = security_inode_init_security(inode, dir, - &dentry->d_name, NULL, - NULL, NULL); + &dentry->d_name, NULL); if (error) { if (error != -EOPNOTSUPP) { iput(inode); @@ -2017,8 +2016,8 @@ static int shmem_symlink(struct inode *dir, struct dentry *dentry, const char *s if (!inode) return -ENOSPC; - error = security_inode_init_security(inode, dir, &dentry->d_name, NULL, - NULL, NULL); + error = security_inode_init_security(inode, dir, &dentry->d_name, + NULL); if (error) { if (error != -EOPNOTSUPP) { iput(inode); diff --git a/security/security.c b/security/security.c index 4ba6d4c..28842f2 100644 --- a/security/security.c +++ b/security/security.c @@ -339,13 +339,22 @@ void security_inode_free(struct inode *inode) } int security_inode_init_security(struct inode *inode, struct inode *dir, - const struct qstr *qstr, char **name, - void **value, size_t *len) + const struct qstr *qstr, + struct xattr **xattr_array) { + struct xattr *lsm_xattr; + if (unlikely(IS_PRIVATE(inode))) return -EOPNOTSUPP; - return security_ops->inode_init_security(inode, dir, qstr, name, value, - len); + + if (!xattr_array) + return security_ops->inode_init_security(inode, dir, qstr, + NULL, NULL, NULL); + lsm_xattr = *xattr_array; + return security_ops->inode_init_security(inode, dir, qstr, + &lsm_xattr->name, + &lsm_xattr->value, + &lsm_xattr->value_len); } EXPORT_SYMBOL(security_inode_init_security); -- 1.7.3.4 -- To unsubscribe from this list: send the line "unsubscribe linux-fsdevel" in the body of a message to majordomo@xxxxxxxxxxxxxxx More majordomo info at http://vger.kernel.org/majordomo-info.html