Merge branch 'for-linus' of git://selinuxproject.org/~jmorris/linux-security
[GitHub/mt8127/android_kernel_alcatel_ttab.git] / security / security.c
index 85481a9c5632ac4a771ce7368017ea558f6f3c27..d7542493454d457ac15118bbd3e126e8b104043f 100644 (file)
 #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",
@@ -315,23 +316,60 @@ 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 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 -EOPNOTSUPP;
        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,
+int security_path_mknod(struct path *dir, struct dentry *dentry, umode_t mode,
                        unsigned int dev)
 {
        if (unlikely(IS_PRIVATE(dir->dentry->d_inode)))
@@ -340,7 +378,7 @@ int security_path_mknod(struct path *dir, struct dentry *dentry, int mode,
 }
 EXPORT_SYMBOL(security_path_mknod);
 
-int security_path_mkdir(struct path *dir, struct dentry *dentry, int mode)
+int security_path_mkdir(struct path *dir, struct dentry *dentry, umode_t mode)
 {
        if (unlikely(IS_PRIVATE(dir->dentry->d_inode)))
                return 0;
@@ -397,12 +435,11 @@ int security_path_truncate(struct path *path)
        return security_ops->path_truncate(path);
 }
 
-int security_path_chmod(struct dentry *dentry, struct vfsmount *mnt,
-                       mode_t mode)
+int security_path_chmod(struct path *path, umode_t mode)
 {
-       if (unlikely(IS_PRIVATE(dentry->d_inode)))
+       if (unlikely(IS_PRIVATE(path->dentry->d_inode)))
                return 0;
-       return security_ops->path_chmod(dentry, mnt, mode);
+       return security_ops->path_chmod(path, mode);
 }
 
 int security_path_chown(struct path *path, uid_t uid, gid_t gid)
@@ -418,7 +455,7 @@ int security_path_chroot(struct path *path)
 }
 #endif
 
-int security_inode_create(struct inode *dir, struct dentry *dentry, int mode)
+int security_inode_create(struct inode *dir, struct dentry *dentry, umode_t mode)
 {
        if (unlikely(IS_PRIVATE(dir)))
                return 0;
@@ -449,7 +486,7 @@ int security_inode_symlink(struct inode *dir, struct dentry *dentry,
        return security_ops->inode_symlink(dir, dentry, old_name);
 }
 
-int security_inode_mkdir(struct inode *dir, struct dentry *dentry, int mode)
+int security_inode_mkdir(struct inode *dir, struct dentry *dentry, umode_t mode)
 {
        if (unlikely(IS_PRIVATE(dir)))
                return 0;
@@ -464,7 +501,7 @@ int security_inode_rmdir(struct inode *dir, struct dentry *dentry)
        return security_ops->inode_rmdir(dir, dentry);
 }
 
-int security_inode_mknod(struct inode *dir, struct dentry *dentry, int mode, dev_t dev)
+int security_inode_mknod(struct inode *dir, struct dentry *dentry, umode_t mode, dev_t dev)
 {
        if (unlikely(IS_PRIVATE(dir)))
                return 0;
@@ -504,9 +541,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);
 
@@ -520,9 +562,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,
@@ -531,6 +578,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)
@@ -549,9 +597,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)