diff options
Diffstat (limited to 'security/security.c')
-rw-r--r-- | security/security.c | 77 |
1 files changed, 66 insertions, 11 deletions
diff --git a/security/security.c b/security/security.c index 0e4fccfef12c..0c6cc69c8f86 100644 --- a/security/security.c +++ b/security/security.c @@ -16,15 +16,16 @@ #include <linux/init.h> #include <linux/kernel.h> #include <linux/security.h> +#include <linux/integrity.h> #include <linux/ima.h> +#include <linux/evm.h> + +#define MAX_LSM_EVM_XATTR 2 /* Boot-time LSM user choice */ static __initdata char chosen_lsm[SECURITY_NAME_MAX + 1] = CONFIG_DEFAULT_SECURITY; -/* things that live in capability.c */ -extern void __init security_fixup_ops(struct security_operations *ops); - static struct security_operations *security_ops; static struct security_operations default_security_ops = { .name = "default", @@ -334,20 +335,57 @@ int security_inode_alloc(struct inode *inode) void security_inode_free(struct inode *inode) { - ima_inode_free(inode); + integrity_inode_free(inode); security_ops->inode_free_security(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, + const initxattrs initxattrs, void *fs_data) { + struct xattr new_xattrs[MAX_LSM_EVM_XATTR + 1]; + struct xattr *lsm_xattr, *evm_xattr, *xattr; + int ret; + if (unlikely(IS_PRIVATE(inode))) - return -EOPNOTSUPP; + return 0; + + memset(new_xattrs, 0, sizeof new_xattrs); + if (!initxattrs) + return security_ops->inode_init_security(inode, dir, qstr, + NULL, NULL, NULL); + lsm_xattr = new_xattrs; + ret = security_ops->inode_init_security(inode, dir, qstr, + &lsm_xattr->name, + &lsm_xattr->value, + &lsm_xattr->value_len); + if (ret) + goto out; + + evm_xattr = lsm_xattr + 1; + ret = evm_inode_init_security(inode, lsm_xattr, evm_xattr); + if (ret) + goto out; + ret = initxattrs(inode, new_xattrs, fs_data); +out: + for (xattr = new_xattrs; xattr->name != NULL; xattr++) { + kfree(xattr->name); + kfree(xattr->value); + } + return (ret == -EOPNOTSUPP) ? 0 : ret; +} +EXPORT_SYMBOL(security_inode_init_security); + +int security_old_inode_init_security(struct inode *inode, struct inode *dir, + const struct qstr *qstr, char **name, + void **value, size_t *len) +{ + if (unlikely(IS_PRIVATE(inode))) + return 0; return security_ops->inode_init_security(inode, dir, qstr, name, value, len); } -EXPORT_SYMBOL(security_inode_init_security); +EXPORT_SYMBOL(security_old_inode_init_security); #ifdef CONFIG_SECURITY_PATH int security_path_mknod(struct path *dir, struct dentry *dentry, int mode, @@ -523,9 +561,14 @@ int security_inode_permission(struct inode *inode, int mask) int security_inode_setattr(struct dentry *dentry, struct iattr *attr) { + int ret; + if (unlikely(IS_PRIVATE(dentry->d_inode))) return 0; - return security_ops->inode_setattr(dentry, attr); + ret = security_ops->inode_setattr(dentry, attr); + if (ret) + return ret; + return evm_inode_setattr(dentry, attr); } EXPORT_SYMBOL_GPL(security_inode_setattr); @@ -539,9 +582,14 @@ int security_inode_getattr(struct vfsmount *mnt, struct dentry *dentry) int security_inode_setxattr(struct dentry *dentry, const char *name, const void *value, size_t size, int flags) { + int ret; + if (unlikely(IS_PRIVATE(dentry->d_inode))) return 0; - return security_ops->inode_setxattr(dentry, name, value, size, flags); + ret = security_ops->inode_setxattr(dentry, name, value, size, flags); + if (ret) + return ret; + return evm_inode_setxattr(dentry, name, value, size); } void security_inode_post_setxattr(struct dentry *dentry, const char *name, @@ -550,6 +598,7 @@ void security_inode_post_setxattr(struct dentry *dentry, const char *name, if (unlikely(IS_PRIVATE(dentry->d_inode))) return; security_ops->inode_post_setxattr(dentry, name, value, size, flags); + evm_inode_post_setxattr(dentry, name, value, size); } int security_inode_getxattr(struct dentry *dentry, const char *name) @@ -568,9 +617,14 @@ int security_inode_listxattr(struct dentry *dentry) int security_inode_removexattr(struct dentry *dentry, const char *name) { + int ret; + if (unlikely(IS_PRIVATE(dentry->d_inode))) return 0; - return security_ops->inode_removexattr(dentry, name); + ret = security_ops->inode_removexattr(dentry, name); + if (ret) + return ret; + return evm_inode_removexattr(dentry, name); } int security_inode_need_killpriv(struct dentry *dentry) @@ -1097,6 +1151,7 @@ void security_sk_clone(const struct sock *sk, struct sock *newsk) { security_ops->sk_clone_security(sk, newsk); } +EXPORT_SYMBOL(security_sk_clone); void security_sk_classify_flow(struct sock *sk, struct flowi *fl) { |