@@ -440,7 +440,8 @@ int ima_check_blacklist(struct ima_iint_cache *iint,
int ima_appraise_measurement(enum ima_hooks func, struct ima_iint_cache *iint,
struct file *file, const unsigned char *filename,
struct evm_ima_xattr_data *xattr_value,
- int xattr_len, const struct modsig *modsig);
+ int xattr_len, const struct modsig *modsig,
+ u64 allowed_usage);
int ima_must_appraise(struct mnt_idmap *idmap, struct inode *inode,
int mask, enum ima_hooks func);
void ima_update_xattr(struct ima_iint_cache *iint, struct file *file);
@@ -465,7 +466,8 @@ static inline int ima_appraise_measurement(enum ima_hooks func,
const unsigned char *filename,
struct evm_ima_xattr_data *xattr_value,
int xattr_len,
- const struct modsig *modsig)
+ const struct modsig *modsig,
+ u64 allowed_usage)
{
return INTEGRITY_UNKNOWN;
}
@@ -480,7 +480,8 @@ int ima_check_blacklist(struct ima_iint_cache *iint,
int ima_appraise_measurement(enum ima_hooks func, struct ima_iint_cache *iint,
struct file *file, const unsigned char *filename,
struct evm_ima_xattr_data *xattr_value,
- int xattr_len, const struct modsig *modsig)
+ int xattr_len, const struct modsig *modsig,
+ u64 allowed_usage)
{
static const char op[] = "appraise_data";
const char *cause = "unknown";
@@ -489,13 +490,20 @@ int ima_appraise_measurement(enum ima_hooks func, struct ima_iint_cache *iint,
enum integrity_status status = INTEGRITY_UNKNOWN;
int rc = xattr_len;
bool try_modsig = iint->flags & IMA_MODSIG_ALLOWED && modsig;
+ bool cache_pass = (allowed_usage & IMA_DIGEST_CACHE_APPRAISE_DATA);
- /* If not appraising a modsig, we need an xattr. */
- if (!(inode->i_opflags & IOP_XATTR) && !try_modsig)
+ /*
+ * If not appraising a modsig/there is no digest cache match, we need
+ * an xattr.
+ */
+ if (!(inode->i_opflags & IOP_XATTR) && !try_modsig && !cache_pass)
return INTEGRITY_UNKNOWN;
- /* If reading the xattr failed and there's no modsig, error out. */
- if (rc <= 0 && !try_modsig) {
+ /*
+ * If reading the xattr failed and there's no modsig/digest cache match,
+ * error out.
+ */
+ if (rc <= 0 && !try_modsig && !cache_pass) {
if (rc && rc != -ENODATA)
goto out;
@@ -526,8 +534,11 @@ int ima_appraise_measurement(enum ima_hooks func, struct ima_iint_cache *iint,
case INTEGRITY_UNKNOWN:
break;
case INTEGRITY_NOXATTRS: /* No EVM protected xattrs. */
- /* It's fine not to have xattrs when using a modsig. */
- if (try_modsig)
+ /*
+ * It's fine not to have xattrs when using a modsig or there
+ * is a digest cache match.
+ */
+ if (try_modsig || cache_pass)
break;
fallthrough;
case INTEGRITY_NOLABEL: /* No security.evm xattr. */
@@ -544,6 +555,12 @@ int ima_appraise_measurement(enum ima_hooks func, struct ima_iint_cache *iint,
WARN_ONCE(true, "Unexpected integrity status %d\n", status);
}
+ if (cache_pass) {
+ status = INTEGRITY_PASS;
+ rc = 0;
+ goto out;
+ }
+
if (xattr_value)
rc = xattr_verify(func, iint, xattr_value, xattr_len, &status,
&cause);
@@ -398,7 +398,9 @@ static int process_measurement(struct file *file, const struct cred *cred,
inode_lock(inode);
rc = ima_appraise_measurement(func, iint, file,
pathname, xattr_value,
- xattr_len, modsig);
+ xattr_len, modsig,
+ (policy_usage &
+ verified_usage));
inode_unlock(inode);
}
if (!rc)