Received: by 10.213.65.68 with SMTP id h4csp626714imn; Fri, 16 Mar 2018 13:43:36 -0700 (PDT) X-Google-Smtp-Source: AG47ELu41R2CYiPJDQa0g1cb2LKCPcep/+Urswv4MBc8/vcYaGt5jVffxGA8hkJv7uLAa7VFkOXy X-Received: by 10.101.85.9 with SMTP id f9mr2534850pgr.189.1521233016799; Fri, 16 Mar 2018 13:43:36 -0700 (PDT) ARC-Seal: i=1; a=rsa-sha256; t=1521233016; cv=none; d=google.com; s=arc-20160816; b=oQpmz94HL1Ed83CifiXSwuJc6qgfDwUV56x/x7ywU0Wrn+rs95L2mSk88/JOazykmq ui5A8+rIU7CngQsMVUS/dAcwmLqRpfj2kIAcQy+7+JqsXTg1qGST58o6fqe4yhrHyjk6 1K01Em3OU0OvFlbNAp3eDK/Ed85JqN+IEhdVTG756N81E217sCHz1Kk/eRlON6S5dihr pPmpVlC/B5BCNKJfWWZ/Ah2btSjXyYYD8dSm8tEtO790Kl3aNC1UXfk6Tlh5/zIA9yax f5W6ReW4AogP3J6xv7qYCHT1r4aBp4lw6dS2ZX5tmDUfGRXPcGZbtX1OGWaC5ccRk3aM Bl6w== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20160816; h=list-id:precedence:sender:message-id:references:in-reply-to:date :subject:cc:to:from:arc-authentication-results; bh=8oTwFBvm+e2Sq/e0pDrcXhvML7gkHWmoKhLjsF/XNAg=; b=ULjorgQCWPuF0G9M/JJWohyJK20Wasx2/VgDgOGWhMcup2d8hdsO93zEIJHRXapxlW /Gd1wb4IgUYgAXk9MUvXM4q16Gf/TlpXC+PyD2OzGdUlV6FQ5nAFn2S1bhnNQctj8NzV i/GExl7XxC9OCkyCRvkfKRTKKnRx1n3XUwtNYFfJkqpL8K5QaMR646P6JlM9eyE3MQ5B 29nLNl4UIaBPxWs4unLhTjn+VrBkKquFLXoZSFxAQFZGsz82ZPKf6hJFuWPiGabFWA6V 0bRNZGmgwM9TQR/a3FWRY35NmmwkpeKngSaf/p3sOCkdOtII7Ws4uIToUk/UwV4qZQ9k V0RA== ARC-Authentication-Results: i=1; mx.google.com; spf=pass (google.com: best guess record for domain of linux-kernel-owner@vger.kernel.org designates 209.132.180.67 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org; dmarc=fail (p=NONE sp=NONE dis=NONE) header.from=ibm.com Return-Path: Received: from vger.kernel.org (vger.kernel.org. [209.132.180.67]) by mx.google.com with ESMTP id f3si5524400pgu.783.2018.03.16.13.43.20; Fri, 16 Mar 2018 13:43:36 -0700 (PDT) Received-SPF: pass (google.com: best guess record for domain of linux-kernel-owner@vger.kernel.org designates 209.132.180.67 as permitted sender) client-ip=209.132.180.67; Authentication-Results: mx.google.com; spf=pass (google.com: best guess record for domain of linux-kernel-owner@vger.kernel.org designates 209.132.180.67 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org; dmarc=fail (p=NONE sp=NONE dis=NONE) header.from=ibm.com Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S932229AbeCPUk3 (ORCPT + 99 others); Fri, 16 Mar 2018 16:40:29 -0400 Received: from mx0a-001b2d01.pphosted.com ([148.163.156.1]:39140 "EHLO mx0a-001b2d01.pphosted.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1753930AbeCPUkY (ORCPT ); Fri, 16 Mar 2018 16:40:24 -0400 Received: from pps.filterd (m0098404.ppops.net [127.0.0.1]) by mx0a-001b2d01.pphosted.com (8.16.0.22/8.16.0.22) with SMTP id w2GKe8mv138340 for ; Fri, 16 Mar 2018 16:40:24 -0400 Received: from e32.co.us.ibm.com (e32.co.us.ibm.com [32.97.110.150]) by mx0a-001b2d01.pphosted.com with ESMTP id 2grmbn9jp2-1 (version=TLSv1.2 cipher=AES256-SHA256 bits=256 verify=NOT) for ; Fri, 16 Mar 2018 16:40:23 -0400 Received: from localhost by e32.co.us.ibm.com with IBM ESMTP SMTP Gateway: Authorized Use Only! Violators will be prosecuted for from ; Fri, 16 Mar 2018 14:40:23 -0600 Received: from b03cxnp08027.gho.boulder.ibm.com (9.17.130.19) by e32.co.us.ibm.com (192.168.1.132) with IBM ESMTP SMTP Gateway: Authorized Use Only! Violators will be prosecuted; Fri, 16 Mar 2018 14:40:18 -0600 Received: from b03ledav004.gho.boulder.ibm.com (b03ledav004.gho.boulder.ibm.com [9.17.130.235]) by b03cxnp08027.gho.boulder.ibm.com (8.14.9/8.14.9/NCO v10.0) with ESMTP id w2GKeIrU10223978; Fri, 16 Mar 2018 13:40:18 -0700 Received: from b03ledav004.gho.boulder.ibm.com (unknown [127.0.0.1]) by IMSVA (Postfix) with ESMTP id DF22178057; Fri, 16 Mar 2018 14:40:17 -0600 (MDT) Received: from morokweng.localdomain.com (unknown [9.85.199.230]) by b03ledav004.gho.boulder.ibm.com (Postfix) with ESMTP id 3AEB578047; Fri, 16 Mar 2018 14:40:13 -0600 (MDT) From: Thiago Jung Bauermann To: linux-integrity@vger.kernel.org Cc: linux-security-module@vger.kernel.org, keyrings@vger.kernel.org, linux-crypto@vger.kernel.org, linuxppc-dev@lists.ozlabs.org, linux-kernel@vger.kernel.org, Mimi Zohar , Dmitry Kasatkin , James Morris , "Serge E. Hallyn" , David Howells , David Woodhouse , Jessica Yu , Herbert Xu , "David S. Miller" , "AKASHI, Takahiro" , Thiago Jung Bauermann Subject: [PATCH v6 11/12] ima: Implement support for module-style appended signatures Date: Fri, 16 Mar 2018 17:38:36 -0300 X-Mailer: git-send-email 2.16.2 In-Reply-To: <20180316203837.10174-1-bauerman@linux.vnet.ibm.com> References: <20180316203837.10174-1-bauerman@linux.vnet.ibm.com> X-TM-AS-GCONF: 00 x-cbid: 18031620-0004-0000-0000-000013CFE576 X-IBM-SpamModules-Scores: X-IBM-SpamModules-Versions: BY=3.00008686; HX=3.00000241; KW=3.00000007; PH=3.00000004; SC=3.00000254; SDB=6.01004028; UDB=6.00511020; IPR=6.00783318; MB=3.00020079; MTD=3.00000008; XFM=3.00000015; UTC=2018-03-16 20:40:21 X-IBM-AV-DETECTION: SAVI=unused REMOTE=unused XFE=unused x-cbparentid: 18031620-0005-0000-0000-0000867DDB88 Message-Id: <20180316203837.10174-12-bauerman@linux.vnet.ibm.com> X-Proofpoint-Virus-Version: vendor=fsecure engine=2.50.10432:,, definitions=2018-03-16_13:,, signatures=0 X-Proofpoint-Spam-Details: rule=outbound_notspam policy=outbound score=0 priorityscore=1501 malwarescore=0 suspectscore=3 phishscore=0 bulkscore=0 spamscore=0 clxscore=1015 lowpriorityscore=0 impostorscore=0 adultscore=0 classifier=spam adjust=0 reason=mlx scancount=1 engine=8.0.1-1709140000 definitions=main-1803160243 Sender: linux-kernel-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-kernel@vger.kernel.org This patch actually implements the appraise_type=imasig|modsig option, allowing IMA to read and verify modsig signatures. In case both are present in the same file, IMA will first check whether the key used by the xattr signature is present in the kernel keyring. If not, it will try the appended signature. Signed-off-by: Thiago Jung Bauermann --- security/integrity/ima/ima.h | 11 +++++++- security/integrity/ima/ima_appraise.c | 53 +++++++++++++++++++++++++++++++---- security/integrity/ima/ima_main.c | 21 +++++++++++--- 3 files changed, 74 insertions(+), 11 deletions(-) diff --git a/security/integrity/ima/ima.h b/security/integrity/ima/ima.h index 49aef56dc96d..c11ccb7c5bfb 100644 --- a/security/integrity/ima/ima.h +++ b/security/integrity/ima/ima.h @@ -157,7 +157,8 @@ void ima_init_template_list(void); static inline bool is_ima_sig(const struct evm_ima_xattr_data *xattr_value) { - return xattr_value && xattr_value->type == EVM_IMA_XATTR_DIGSIG; + return xattr_value && (xattr_value->type == EVM_IMA_XATTR_DIGSIG || + xattr_value->type == IMA_MODSIG); } /* @@ -253,6 +254,8 @@ enum integrity_status ima_get_cache_status(struct integrity_iint_cache *iint, enum ima_hooks func); enum hash_algo ima_get_hash_algo(struct evm_ima_xattr_data *xattr_value, int xattr_len); +bool ima_xattr_sig_known_key(const struct evm_ima_xattr_data *xattr_value, + int xattr_len); int ima_read_xattr(struct dentry *dentry, struct evm_ima_xattr_data **xattr_value); @@ -291,6 +294,12 @@ ima_get_hash_algo(struct evm_ima_xattr_data *xattr_value, int xattr_len) return ima_hash_algo; } +static inline bool ima_xattr_sig_known_key(const struct evm_ima_xattr_data + *xattr_value, int xattr_len) +{ + return false; +} + static inline int ima_read_xattr(struct dentry *dentry, struct evm_ima_xattr_data **xattr_value) { diff --git a/security/integrity/ima/ima_appraise.c b/security/integrity/ima/ima_appraise.c index 01172eab297b..84e0fd5a19c8 100644 --- a/security/integrity/ima/ima_appraise.c +++ b/security/integrity/ima/ima_appraise.c @@ -189,6 +189,22 @@ enum hash_algo ima_get_hash_algo(struct evm_ima_xattr_data *xattr_value, return ima_hash_algo; } +bool ima_xattr_sig_known_key(const struct evm_ima_xattr_data *xattr_value, + int xattr_len) +{ + struct key *keyring; + + if (xattr_value->type != EVM_IMA_XATTR_DIGSIG) + return false; + + keyring = integrity_keyring_from_id(INTEGRITY_KEYRING_IMA); + if (IS_ERR(keyring)) + return false; + + return asymmetric_sig_has_known_key(keyring, (const char *) xattr_value, + xattr_len); +} + int ima_read_xattr(struct dentry *dentry, struct evm_ima_xattr_data **xattr_value) { @@ -221,8 +237,12 @@ int ima_appraise_measurement(enum ima_hooks func, struct inode *inode = d_backing_inode(dentry); enum integrity_status status = INTEGRITY_UNKNOWN; int rc = xattr_len, hash_start = 0; + size_t xattr_contents_len; + void *xattr_contents; - if (!(inode->i_opflags & IOP_XATTR)) + /* If not appraising a modsig, we need an xattr. */ + if ((xattr_value == NULL || xattr_value->type != IMA_MODSIG) && + !(inode->i_opflags & IOP_XATTR)) return INTEGRITY_UNKNOWN; if (rc <= 0) { @@ -241,13 +261,29 @@ int ima_appraise_measurement(enum ima_hooks func, goto out; } - status = evm_verifyxattr(dentry, XATTR_NAME_IMA, xattr_value, rc, iint); + /* + * If it's a modsig, we don't have the xattr contents to pass to + * evm_verifyxattr(). + */ + if (xattr_value->type == IMA_MODSIG) { + xattr_contents = NULL; + xattr_contents_len = 0; + } else { + xattr_contents = xattr_value; + xattr_contents_len = xattr_len; + } + + status = evm_verifyxattr(dentry, XATTR_NAME_IMA, xattr_contents, + xattr_contents_len, iint); switch (status) { case INTEGRITY_PASS: case INTEGRITY_PASS_IMMUTABLE: case INTEGRITY_UNKNOWN: break; case INTEGRITY_NOXATTRS: /* No EVM protected xattrs. */ + /* It's fine not to have xattrs when using a modsig. */ + if (xattr_value->type == IMA_MODSIG) + break; case INTEGRITY_NOLABEL: /* No security.evm xattr. */ cause = "missing-HMAC"; goto out; @@ -288,11 +324,16 @@ int ima_appraise_measurement(enum ima_hooks func, status = INTEGRITY_PASS; break; case EVM_IMA_XATTR_DIGSIG: + case IMA_MODSIG: set_bit(IMA_DIGSIG, &iint->atomic_flags); - rc = integrity_digsig_verify(INTEGRITY_KEYRING_IMA, - (const char *)xattr_value, rc, - iint->ima_hash->digest, - iint->ima_hash->length); + if (xattr_value->type == EVM_IMA_XATTR_DIGSIG) + rc = integrity_digsig_verify(INTEGRITY_KEYRING_IMA, + (const char *)xattr_value, + rc, iint->ima_hash->digest, + iint->ima_hash->length); + else + rc = ima_modsig_verify(INTEGRITY_KEYRING_IMA, + xattr_value); if (rc == -EOPNOTSUPP) { status = INTEGRITY_UNKNOWN; } else if (rc) { diff --git a/security/integrity/ima/ima_main.c b/security/integrity/ima/ima_main.c index 5d122daf5c8a..1b11c10f09df 100644 --- a/security/integrity/ima/ima_main.c +++ b/security/integrity/ima/ima_main.c @@ -183,7 +183,7 @@ static int process_measurement(struct file *file, const struct cred *cred, struct evm_ima_xattr_data *xattr_value = NULL; int xattr_len = 0; bool violation_check; - enum hash_algo hash_algo; + enum hash_algo hash_algo = HASH_ALGO__LAST; if (!ima_policy_flag || !S_ISREG(inode->i_mode)) return 0; @@ -277,11 +277,24 @@ static int process_measurement(struct file *file, const struct cred *cred, template_desc = ima_template_desc_current(); if ((action & IMA_APPRAISE_SUBMASK) || - strcmp(template_desc->name, IMA_TEMPLATE_IMA_NAME) != 0) + strcmp(template_desc->name, IMA_TEMPLATE_IMA_NAME) != 0) { /* read 'security.ima' */ xattr_len = ima_read_xattr(file_dentry(file), &xattr_value); + if (iint->flags & IMA_MODSIG_ALLOWED && + (xattr_len <= 0 || !ima_xattr_sig_known_key(xattr_value, + xattr_len))) { + /* + * Even if we end up using a modsig, hash_algo should + * come from the xattr (or even the default hash algo). + */ + hash_algo = ima_get_hash_algo(xattr_value, xattr_len); + ima_read_modsig(func, buf, size, &xattr_value, + &xattr_len); + } + } - hash_algo = ima_get_hash_algo(xattr_value, xattr_len); + if (hash_algo == HASH_ALGO__LAST) + hash_algo = ima_get_hash_algo(xattr_value, xattr_len); rc = ima_collect_measurement(iint, file, buf, size, hash_algo); if (rc != 0 && rc != -EBADF && rc != -EINVAL) @@ -309,7 +322,7 @@ static int process_measurement(struct file *file, const struct cred *cred, !(iint->flags & IMA_NEW_FILE)) rc = -EACCES; mutex_unlock(&iint->mutex); - kfree(xattr_value); + ima_free_xattr_data(xattr_value); out: if (pathbuf) __putname(pathbuf);