evm: Move to LSM infrastructure
[linux-2.6-block.git] / security / integrity / evm / evm_main.c
index d351431796991e3dfbb416f12f4fb011d72fb630..0a089af83a45d846a830f8fd01691e579a439530 100644 (file)
@@ -589,9 +589,9 @@ out:
  * userspace from writing HMAC value.  Writing 'security.evm' requires
  * requires CAP_SYS_ADMIN privileges.
  */
-int evm_inode_setxattr(struct mnt_idmap *idmap, struct dentry *dentry,
-                      const char *xattr_name, const void *xattr_value,
-                      size_t xattr_value_len, int flags)
+static int evm_inode_setxattr(struct mnt_idmap *idmap, struct dentry *dentry,
+                             const char *xattr_name, const void *xattr_value,
+                             size_t xattr_value_len, int flags)
 {
        const struct evm_ima_xattr_data *xattr_data = xattr_value;
 
@@ -621,8 +621,8 @@ int evm_inode_setxattr(struct mnt_idmap *idmap, struct dentry *dentry,
  * Removing 'security.evm' requires CAP_SYS_ADMIN privileges and that
  * the current value is valid.
  */
-int evm_inode_removexattr(struct mnt_idmap *idmap,
-                         struct dentry *dentry, const char *xattr_name)
+static int evm_inode_removexattr(struct mnt_idmap *idmap, struct dentry *dentry,
+                                const char *xattr_name)
 {
        /* Policy permits modification of the protected xattrs even though
         * there's no HMAC key loaded
@@ -672,9 +672,11 @@ static inline int evm_inode_set_acl_change(struct mnt_idmap *idmap,
  * Prevent modifying posix acls causing the EVM HMAC to be re-calculated
  * and 'security.evm' xattr updated, unless the existing 'security.evm' is
  * valid.
+ *
+ * Return: zero on success, -EPERM on failure.
  */
-int evm_inode_set_acl(struct mnt_idmap *idmap, struct dentry *dentry,
-                     const char *acl_name, struct posix_acl *kacl)
+static int evm_inode_set_acl(struct mnt_idmap *idmap, struct dentry *dentry,
+                            const char *acl_name, struct posix_acl *kacl)
 {
        enum integrity_status evm_status;
 
@@ -713,6 +715,24 @@ int evm_inode_set_acl(struct mnt_idmap *idmap, struct dentry *dentry,
        return -EPERM;
 }
 
+/**
+ * evm_inode_remove_acl - Protect the EVM extended attribute from posix acls
+ * @idmap: idmap of the mount
+ * @dentry: pointer to the affected dentry
+ * @acl_name: name of the posix acl
+ *
+ * Prevent removing posix acls causing the EVM HMAC to be re-calculated
+ * and 'security.evm' xattr updated, unless the existing 'security.evm' is
+ * valid.
+ *
+ * Return: zero on success, -EPERM on failure.
+ */
+static int evm_inode_remove_acl(struct mnt_idmap *idmap, struct dentry *dentry,
+                               const char *acl_name)
+{
+       return evm_inode_set_acl(idmap, dentry, acl_name, NULL);
+}
+
 static void evm_reset_status(struct inode *inode)
 {
        struct integrity_iint_cache *iint;
@@ -761,9 +781,11 @@ bool evm_revalidate_status(const char *xattr_name)
  * __vfs_setxattr_noperm().  The caller of which has taken the inode's
  * i_mutex lock.
  */
-void evm_inode_post_setxattr(struct dentry *dentry, const char *xattr_name,
-                            const void *xattr_value, size_t xattr_value_len,
-                            int flags)
+static void evm_inode_post_setxattr(struct dentry *dentry,
+                                   const char *xattr_name,
+                                   const void *xattr_value,
+                                   size_t xattr_value_len,
+                                   int flags)
 {
        if (!evm_revalidate_status(xattr_name))
                return;
@@ -782,6 +804,21 @@ void evm_inode_post_setxattr(struct dentry *dentry, const char *xattr_name,
        evm_update_evmxattr(dentry, xattr_name, xattr_value, xattr_value_len);
 }
 
+/**
+ * evm_inode_post_set_acl - Update the EVM extended attribute from posix acls
+ * @dentry: pointer to the affected dentry
+ * @acl_name: name of the posix acl
+ * @kacl: pointer to the posix acls
+ *
+ * Update the 'security.evm' xattr with the EVM HMAC re-calculated after setting
+ * posix acls.
+ */
+static void evm_inode_post_set_acl(struct dentry *dentry, const char *acl_name,
+                                  struct posix_acl *kacl)
+{
+       return evm_inode_post_setxattr(dentry, acl_name, NULL, 0, 0);
+}
+
 /**
  * evm_inode_post_removexattr - update 'security.evm' after removing the xattr
  * @dentry: pointer to the affected dentry
@@ -792,7 +829,8 @@ void evm_inode_post_setxattr(struct dentry *dentry, const char *xattr_name,
  * No need to take the i_mutex lock here, as this function is called from
  * vfs_removexattr() which takes the i_mutex.
  */
-void evm_inode_post_removexattr(struct dentry *dentry, const char *xattr_name)
+static void evm_inode_post_removexattr(struct dentry *dentry,
+                                      const char *xattr_name)
 {
        if (!evm_revalidate_status(xattr_name))
                return;
@@ -808,6 +846,22 @@ void evm_inode_post_removexattr(struct dentry *dentry, const char *xattr_name)
        evm_update_evmxattr(dentry, xattr_name, NULL, 0);
 }
 
+/**
+ * evm_inode_post_remove_acl - Update the EVM extended attribute from posix acls
+ * @idmap: idmap of the mount
+ * @dentry: pointer to the affected dentry
+ * @acl_name: name of the posix acl
+ *
+ * Update the 'security.evm' xattr with the EVM HMAC re-calculated after
+ * removing posix acls.
+ */
+static inline void evm_inode_post_remove_acl(struct mnt_idmap *idmap,
+                                            struct dentry *dentry,
+                                            const char *acl_name)
+{
+       evm_inode_post_removexattr(dentry, acl_name);
+}
+
 static int evm_attr_change(struct mnt_idmap *idmap,
                           struct dentry *dentry, struct iattr *attr)
 {
@@ -831,8 +885,8 @@ static int evm_attr_change(struct mnt_idmap *idmap,
  * Permit update of file attributes when files have a valid EVM signature,
  * except in the case of them having an immutable portable signature.
  */
-int evm_inode_setattr(struct mnt_idmap *idmap, struct dentry *dentry,
-                     struct iattr *attr)
+static int evm_inode_setattr(struct mnt_idmap *idmap, struct dentry *dentry,
+                            struct iattr *attr)
 {
        unsigned int ia_valid = attr->ia_valid;
        enum integrity_status evm_status;
@@ -883,8 +937,8 @@ int evm_inode_setattr(struct mnt_idmap *idmap, struct dentry *dentry,
  * This function is called from notify_change(), which expects the caller
  * to lock the inode's i_mutex.
  */
-void evm_inode_post_setattr(struct mnt_idmap *idmap, struct dentry *dentry,
-                           int ia_valid)
+static void evm_inode_post_setattr(struct mnt_idmap *idmap,
+                                  struct dentry *dentry, int ia_valid)
 {
        if (!evm_revalidate_status(NULL))
                return;
@@ -901,7 +955,7 @@ void evm_inode_post_setattr(struct mnt_idmap *idmap, struct dentry *dentry,
                evm_update_evmxattr(dentry, NULL, NULL, 0);
 }
 
-int evm_inode_copy_up_xattr(const char *name)
+static int evm_inode_copy_up_xattr(const char *name)
 {
        if (strcmp(name, XATTR_NAME_EVM) == 0)
                return 1; /* Discard */
@@ -1004,4 +1058,36 @@ error:
        return error;
 }
 
+static struct security_hook_list evm_hooks[] __ro_after_init = {
+       LSM_HOOK_INIT(inode_setattr, evm_inode_setattr),
+       LSM_HOOK_INIT(inode_post_setattr, evm_inode_post_setattr),
+       LSM_HOOK_INIT(inode_copy_up_xattr, evm_inode_copy_up_xattr),
+       LSM_HOOK_INIT(inode_setxattr, evm_inode_setxattr),
+       LSM_HOOK_INIT(inode_post_setxattr, evm_inode_post_setxattr),
+       LSM_HOOK_INIT(inode_set_acl, evm_inode_set_acl),
+       LSM_HOOK_INIT(inode_post_set_acl, evm_inode_post_set_acl),
+       LSM_HOOK_INIT(inode_remove_acl, evm_inode_remove_acl),
+       LSM_HOOK_INIT(inode_post_remove_acl, evm_inode_post_remove_acl),
+       LSM_HOOK_INIT(inode_removexattr, evm_inode_removexattr),
+       LSM_HOOK_INIT(inode_post_removexattr, evm_inode_post_removexattr),
+       LSM_HOOK_INIT(inode_init_security, evm_inode_init_security),
+};
+
+static const struct lsm_id evm_lsmid = {
+       .name = "evm",
+       .id = LSM_ID_EVM,
+};
+
+static int __init init_evm_lsm(void)
+{
+       security_add_hooks(evm_hooks, ARRAY_SIZE(evm_hooks), &evm_lsmid);
+       return 0;
+}
+
+DEFINE_LSM(evm) = {
+       .name = "evm",
+       .init = init_evm_lsm,
+       .order = LSM_ORDER_LAST,
+};
+
 late_initcall(init_evm);