evm: permit mode bits to be updated
authorMimi Zohar <zohar@linux.vnet.ibm.com>
Mon, 22 Aug 2011 13:14:18 +0000 (09:14 -0400)
committerMimi Zohar <zohar@linux.vnet.ibm.com>
Wed, 14 Sep 2011 19:24:52 +0000 (15:24 -0400)
Before permitting 'security.evm' to be updated, 'security.evm' must
exist and be valid.  In the case that there are no existing EVM protected
xattrs, it is safe for posix acls to update the mode bits.

To differentiate between no 'security.evm' xattr and no xattrs used to
calculate 'security.evm', this patch defines INTEGRITY_NOXATTR.

Signed-off-by: Mimi Zohar <zohar@us.ibm.com>
include/linux/integrity.h
security/integrity/evm/evm_main.c

index 968443385678701ebca4c4ea0453499692536327..a0c41256cb923d5ffb21d9f4acd20680d3fc54a0 100644 (file)
@@ -16,6 +16,7 @@ enum integrity_status {
        INTEGRITY_PASS = 0,
        INTEGRITY_FAIL,
        INTEGRITY_NOLABEL,
+       INTEGRITY_NOXATTRS,
        INTEGRITY_UNKNOWN,
 };
 
index 73c008d047c726e53e987db8b2b2b9337b9b5f08..92d3d99a9f7b8efd96a1659c5dbb170376c28908 100644 (file)
@@ -66,7 +66,7 @@ static enum integrity_status evm_verify_hmac(struct dentry *dentry,
                                             struct integrity_iint_cache *iint)
 {
        struct evm_ima_xattr_data xattr_data;
-       enum integrity_status evm_status;
+       enum integrity_status evm_status = INTEGRITY_PASS;
        int rc;
 
        if (iint && iint->evm_status == INTEGRITY_PASS)
@@ -76,25 +76,18 @@ static enum integrity_status evm_verify_hmac(struct dentry *dentry,
 
        rc = evm_calc_hmac(dentry, xattr_name, xattr_value,
                           xattr_value_len, xattr_data.digest);
-       if (rc < 0)
-               goto err_out;
+       if (rc < 0) {
+               evm_status = (rc == -ENODATA)
+                   ? INTEGRITY_NOXATTRS : INTEGRITY_FAIL;
+               goto out;
+       }
 
        xattr_data.type = EVM_XATTR_HMAC;
        rc = vfs_xattr_cmp(dentry, XATTR_NAME_EVM, (u8 *)&xattr_data,
                           sizeof xattr_data, GFP_NOFS);
        if (rc < 0)
-               goto err_out;
-       evm_status = INTEGRITY_PASS;
-       goto out;
-
-err_out:
-       switch (rc) {
-       case -ENODATA:          /* file not labelled */
-               evm_status = INTEGRITY_NOLABEL;
-               break;
-       default:
-               evm_status = INTEGRITY_FAIL;
-       }
+               evm_status = (rc == -ENODATA)
+                   ? INTEGRITY_NOLABEL : INTEGRITY_FAIL;
 out:
        if (iint)
                iint->evm_status = evm_status;
@@ -199,7 +192,7 @@ static int evm_protect_xattr(struct dentry *dentry, const char *xattr_name,
                        return 0;
                evm_status = evm_verify_current_integrity(dentry);
                if ((evm_status == INTEGRITY_PASS) ||
-                       (evm_status == INTEGRITY_NOLABEL))
+                   (evm_status == INTEGRITY_NOXATTRS))
                        return 0;
                return -EPERM;
        }
@@ -293,7 +286,10 @@ int evm_inode_setattr(struct dentry *dentry, struct iattr *attr)
        if (!(ia_valid & (ATTR_MODE | ATTR_UID | ATTR_GID)))
                return 0;
        evm_status = evm_verify_current_integrity(dentry);
-       return evm_status == INTEGRITY_PASS ? 0 : -EPERM;
+       if ((evm_status == INTEGRITY_PASS) ||
+           (evm_status == INTEGRITY_NOXATTRS))
+               return 0;
+       return -EPERM;
 }
 
 /**