Skip to content

Commit cdef685

Browse files
robertosassumimizohar
authored andcommitted
evm: Allow xattr/attr operations for portable signatures
If files with portable signatures are copied from one location to another or are extracted from an archive, verification can temporarily fail until all xattrs/attrs are set in the destination. Only portable signatures may be moved or copied from one file to another, as they don't depend on system-specific information such as the inode generation. Instead portable signatures must include security.ima. Unlike other security.evm types, EVM portable signatures are also immutable. Thus, it wouldn't be a problem to allow xattr/attr operations when verification fails, as portable signatures will never be replaced with the HMAC on possibly corrupted xattrs/attrs. This patch first introduces a new integrity status called INTEGRITY_FAIL_IMMUTABLE, that allows callers of evm_verify_current_integrity() to detect that a portable signature didn't pass verification and then adds an exception in evm_protect_xattr() and evm_inode_setattr() for this status and returns 0 instead of -EPERM. Signed-off-by: Roberto Sassu <roberto.sassu@huawei.com> Signed-off-by: Mimi Zohar <zohar@linux.ibm.com>
1 parent 4a804b8 commit cdef685

3 files changed

Lines changed: 30 additions & 6 deletions

File tree

include/linux/integrity.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@ enum integrity_status {
1313
INTEGRITY_PASS = 0,
1414
INTEGRITY_PASS_IMMUTABLE,
1515
INTEGRITY_FAIL,
16+
INTEGRITY_FAIL_IMMUTABLE,
1617
INTEGRITY_NOLABEL,
1718
INTEGRITY_NOXATTRS,
1819
INTEGRITY_UNKNOWN,

security/integrity/evm/evm_main.c

Lines changed: 27 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -27,7 +27,8 @@
2727
int evm_initialized;
2828

2929
static const char * const integrity_status_msg[] = {
30-
"pass", "pass_immutable", "fail", "no_label", "no_xattrs", "unknown"
30+
"pass", "pass_immutable", "fail", "fail_immutable", "no_label",
31+
"no_xattrs", "unknown"
3132
};
3233
int evm_hmac_attrs;
3334

@@ -155,7 +156,7 @@ static enum integrity_status evm_verify_hmac(struct dentry *dentry,
155156
enum integrity_status evm_status = INTEGRITY_PASS;
156157
struct evm_digest digest;
157158
struct inode *inode;
158-
int rc, xattr_len;
159+
int rc, xattr_len, evm_immutable = 0;
159160

160161
if (iint && (iint->evm_status == INTEGRITY_PASS ||
161162
iint->evm_status == INTEGRITY_PASS_IMMUTABLE))
@@ -200,8 +201,10 @@ static enum integrity_status evm_verify_hmac(struct dentry *dentry,
200201
if (rc)
201202
rc = -EINVAL;
202203
break;
203-
case EVM_IMA_XATTR_DIGSIG:
204204
case EVM_XATTR_PORTABLE_DIGSIG:
205+
evm_immutable = 1;
206+
fallthrough;
207+
case EVM_IMA_XATTR_DIGSIG:
205208
/* accept xattr with non-empty signature field */
206209
if (xattr_len <= sizeof(struct signature_v2_hdr)) {
207210
evm_status = INTEGRITY_FAIL;
@@ -238,9 +241,14 @@ static enum integrity_status evm_verify_hmac(struct dentry *dentry,
238241
break;
239242
}
240243

241-
if (rc)
242-
evm_status = (rc == -ENODATA) ?
243-
INTEGRITY_NOXATTRS : INTEGRITY_FAIL;
244+
if (rc) {
245+
if (rc == -ENODATA)
246+
evm_status = INTEGRITY_NOXATTRS;
247+
else if (evm_immutable)
248+
evm_status = INTEGRITY_FAIL_IMMUTABLE;
249+
else
250+
evm_status = INTEGRITY_FAIL;
251+
}
244252
out:
245253
if (iint)
246254
iint->evm_status = evm_status;
@@ -380,6 +388,14 @@ static int evm_protect_xattr(struct dentry *dentry, const char *xattr_name,
380388
if (evm_hmac_disabled() && (evm_status == INTEGRITY_NOLABEL ||
381389
evm_status == INTEGRITY_UNKNOWN))
382390
return 0;
391+
392+
/*
393+
* Writing other xattrs is safe for portable signatures, as portable
394+
* signatures are immutable and can never be updated.
395+
*/
396+
if (evm_status == INTEGRITY_FAIL_IMMUTABLE)
397+
return 0;
398+
383399
if (evm_status != INTEGRITY_PASS)
384400
integrity_audit_msg(AUDIT_INTEGRITY_METADATA, d_backing_inode(dentry),
385401
dentry->d_name.name, "appraise_metadata",
@@ -553,8 +569,13 @@ int evm_inode_setattr(struct dentry *dentry, struct iattr *attr)
553569
if (!(ia_valid & (ATTR_MODE | ATTR_UID | ATTR_GID)))
554570
return 0;
555571
evm_status = evm_verify_current_integrity(dentry);
572+
/*
573+
* Writing attrs is safe for portable signatures, as portable signatures
574+
* are immutable and can never be updated.
575+
*/
556576
if ((evm_status == INTEGRITY_PASS) ||
557577
(evm_status == INTEGRITY_NOXATTRS) ||
578+
(evm_status == INTEGRITY_FAIL_IMMUTABLE) ||
558579
(evm_hmac_disabled() && (evm_status == INTEGRITY_NOLABEL ||
559580
evm_status == INTEGRITY_UNKNOWN)))
560581
return 0;

security/integrity/ima/ima_appraise.c

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -416,6 +416,8 @@ int ima_appraise_measurement(enum ima_hooks func,
416416
case INTEGRITY_NOLABEL: /* No security.evm xattr. */
417417
cause = "missing-HMAC";
418418
goto out;
419+
case INTEGRITY_FAIL_IMMUTABLE:
420+
fallthrough;
419421
case INTEGRITY_FAIL: /* Invalid HMAC/signature. */
420422
cause = "invalid-HMAC";
421423
goto out;

0 commit comments

Comments
 (0)