From patchwork Wed Oct 18 18:01:11 2017 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Matthew Garrett X-Patchwork-Id: 10015147 Return-Path: Received: from mail.wl.linuxfoundation.org (pdx-wl-mail.web.codeaurora.org [172.30.200.125]) by pdx-korg-patchwork.web.codeaurora.org (Postfix) with ESMTP id 8778D602C8 for ; Wed, 18 Oct 2017 18:01:23 +0000 (UTC) Received: from mail.wl.linuxfoundation.org (localhost [127.0.0.1]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id 6CC6B29121 for ; Wed, 18 Oct 2017 18:01:23 +0000 (UTC) Received: by mail.wl.linuxfoundation.org (Postfix, from userid 486) id 5EB0929143; Wed, 18 Oct 2017 18:01:23 +0000 (UTC) X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on pdx-wl-mail.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-7.0 required=2.0 tests=BAYES_00,DKIM_SIGNED, DKIM_VALID, DKIM_VALID_AU, RCVD_IN_DNSWL_HI autolearn=ham version=3.3.1 Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id B55B629121 for ; Wed, 18 Oct 2017 18:01:22 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1750800AbdJRSBW (ORCPT ); Wed, 18 Oct 2017 14:01:22 -0400 Received: from mail-qt0-f201.google.com ([209.85.216.201]:61991 "EHLO mail-qt0-f201.google.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1750782AbdJRSBV (ORCPT ); Wed, 18 Oct 2017 14:01:21 -0400 Received: by mail-qt0-f201.google.com with SMTP id 31so6563576qtz.20 for ; Wed, 18 Oct 2017 11:01:21 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=20161025; h=mime-version:date:message-id:subject:from:to:cc; bh=SN7mITmOfyKobimQOl1EwGP8kcHAPDiTg7mdaN4Np7U=; b=sOX2UXApsYzKQ7wh7xiLbFxW+QHfqeEUS7vdKg/+3So6paAalIF5z8j8UwSkPktT3w 0+Alm4oOWIMhCdM65qvEciQVbyEgpX6IPpZ4bkgjHYo4eAguqXNcvWCfjwrD4X8/3wOH CTt+9LAcOp3gp+xKBAdW6dpp6NtzwHtadt+lOpa7XKMqRU/VMVJoSNQ9bg13uyrg8aYM 3H9DkgLpaGaYao/1vOv8l94CRUrQm77czGzXRvrrwA/r0CMn8uVuafQyvA8bauFDJPzz 80PEVvMwwlhuMGpM6aC/BIGNXDYmq+LfvXYex9Cw8UoRcXrUhpTd5AVRJmxvVOM+Rm3l /Iqw== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:mime-version:date:message-id:subject:from:to:cc; bh=SN7mITmOfyKobimQOl1EwGP8kcHAPDiTg7mdaN4Np7U=; b=Fks1rD8CL85E7eZu1aUztnSJ26Hal8RmJ8RofaB+QLmQW+c/VLGRZ/CqbnAUNqtJlp 8bcKi2QLtiSWCxq0y6mnCq8a4qf2MeHaBSIQaFGbaAzGrHL6S/456OivNMcb3AtJG643 QhMgIS+3NHt8DJBDVQCMDvmH3YH94wavEoADqhN+B5958uE7UyZsIx259239nTt8Cr+/ lPZGZ3XP94xUKoP65FdbhqUac05Z9G0dpDMfCSr16kD+/rRzsQOHJ83o7nGSRQX8I6Ho dTwOPgSKmg4DHX9jA1/nMzYXKHgg+D6Tp2sZ8QUzbXrjhZx6HMaBvlG68UDN+1Wja4dD NbWg== X-Gm-Message-State: AMCzsaV49+v8d8wWd4W95IIMISq5873eM3cvYfyG4EF7yBuDJK75NA34 SX7WNw9OvdOfMZPke/mY989apLpnJu4o3rzMcdv6/4YtsBRYPOrb2xZuJqsk1ZxMApfnHfImRda XsP+poON4r3PEUVAhmY9vMli6UuMyxFvFJt0= X-Google-Smtp-Source: AOwi7QBibugFPru3MsLRiFpnw7T+2q/+NWelG2m4MveHAvRzVLW8875KtbBOssYiXDXeIgtSdj6Rqoy1Ex+Fds9MMVr7sg== MIME-Version: 1.0 X-Received: by 10.55.215.4 with SMTP id m4mr13899525qki.36.1508349680855; Wed, 18 Oct 2017 11:01:20 -0700 (PDT) Date: Wed, 18 Oct 2017 11:01:11 -0700 Message-Id: <20171018180111.13021-1-mjg59@google.com> X-Mailer: git-send-email 2.15.0.rc1.287.g2b38de12cc-goog Subject: [PATCH] EVM: Add support for portable signature format From: Matthew Garrett To: linux-integrity@vger.kernel.org Cc: zohar@linux.vnet.ibm.com, Matthew Garrett , Dmitry Kasatkin , Mikhail Kurinnoi Sender: linux-integrity-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-integrity@vger.kernel.org X-Virus-Scanned: ClamAV using ClamSMTP The EVM signature includes the inode number and (optionally) the filesystem UUID, making it impractical to ship EVM signatures in packages. This patch adds a new portable format intended to allow distributions to include EVM signatures. It is identical to the existing format but hardcodes the inode and generation numbers to 0 and does not include the filesystem UUID even if the kernel is configured to do so. Admins should note that creating portable signatures that do not include the security.ima xattr would allow these signatures to be applied to any file with the same owners and security labels, which would allow subversion of EVM's security guarantees. The kernel does not attempt to enforce this. Based on earlier work by Dmitry Kasatkin and Mikhail Kurinnoi. Signed-off-by: Matthew Garrett Cc: Dmitry Kasatkin Cc: Mikhail Kurinnoi --- security/integrity/evm/evm.h | 2 +- security/integrity/evm/evm_crypto.c | 24 +++++++++++++++--------- security/integrity/evm/evm_main.c | 7 +++++-- security/integrity/integrity.h | 1 + 4 files changed, 22 insertions(+), 12 deletions(-) diff --git a/security/integrity/evm/evm.h b/security/integrity/evm/evm.h index f5f12727771a..2ff02459fcfd 100644 --- a/security/integrity/evm/evm.h +++ b/security/integrity/evm/evm.h @@ -48,7 +48,7 @@ int evm_calc_hmac(struct dentry *dentry, const char *req_xattr_name, size_t req_xattr_value_len, char *digest); int evm_calc_hash(struct dentry *dentry, const char *req_xattr_name, const char *req_xattr_value, - size_t req_xattr_value_len, char *digest); + size_t req_xattr_value_len, char type, char *digest); int evm_init_hmac(struct inode *inode, const struct xattr *xattr, char *hmac_val); int evm_init_secfs(void); diff --git a/security/integrity/evm/evm_crypto.c b/security/integrity/evm/evm_crypto.c index 1d32cd20009a..6435f12b0067 100644 --- a/security/integrity/evm/evm_crypto.c +++ b/security/integrity/evm/evm_crypto.c @@ -138,7 +138,7 @@ static struct shash_desc *init_desc(char type) * protection.) */ static void hmac_add_misc(struct shash_desc *desc, struct inode *inode, - char *digest) + char type, char *digest) { struct h_misc { unsigned long ino; @@ -149,8 +149,13 @@ static void hmac_add_misc(struct shash_desc *desc, struct inode *inode, } hmac_misc; memset(&hmac_misc, 0, sizeof(hmac_misc)); - hmac_misc.ino = inode->i_ino; - hmac_misc.generation = inode->i_generation; + /* Don't include the inode or generation number in portable + * signatures + */ + if (type != EVM_IMA_XATTR_PORTABLE_DIGSIG) { + hmac_misc.ino = inode->i_ino; + hmac_misc.generation = inode->i_generation; + } /* The hmac uid and gid must be encoded in the initial user * namespace (not the filesystems user namespace) as encoding * them in the filesystems user namespace allows an attack @@ -163,7 +168,8 @@ static void hmac_add_misc(struct shash_desc *desc, struct inode *inode, hmac_misc.gid = from_kgid(&init_user_ns, inode->i_gid); hmac_misc.mode = inode->i_mode; crypto_shash_update(desc, (const u8 *)&hmac_misc, sizeof(hmac_misc)); - if (evm_hmac_attrs & EVM_ATTR_FSUUID) + if ((evm_hmac_attrs & EVM_ATTR_FSUUID) && + type != EVM_IMA_XATTR_PORTABLE_DIGSIG) crypto_shash_update(desc, &inode->i_sb->s_uuid.b[0], sizeof(inode->i_sb->s_uuid)); crypto_shash_final(desc, digest); @@ -219,7 +225,7 @@ static int evm_calc_hmac_or_hash(struct dentry *dentry, xattr_size = size; crypto_shash_update(desc, (const u8 *)xattr_value, xattr_size); } - hmac_add_misc(desc, inode, digest); + hmac_add_misc(desc, inode, type, digest); out: kfree(xattr_value); @@ -232,15 +238,15 @@ int evm_calc_hmac(struct dentry *dentry, const char *req_xattr_name, char *digest) { return evm_calc_hmac_or_hash(dentry, req_xattr_name, req_xattr_value, - req_xattr_value_len, EVM_XATTR_HMAC, digest); + req_xattr_value_len, EVM_XATTR_HMAC, digest); } int evm_calc_hash(struct dentry *dentry, const char *req_xattr_name, const char *req_xattr_value, size_t req_xattr_value_len, - char *digest) + char type, char *digest) { return evm_calc_hmac_or_hash(dentry, req_xattr_name, req_xattr_value, - req_xattr_value_len, IMA_XATTR_DIGEST, digest); + req_xattr_value_len, type, digest); } /* @@ -280,7 +286,7 @@ int evm_init_hmac(struct inode *inode, const struct xattr *lsm_xattr, } crypto_shash_update(desc, lsm_xattr->value, lsm_xattr->value_len); - hmac_add_misc(desc, inode, hmac_val); + hmac_add_misc(desc, inode, EVM_XATTR_HMAC, hmac_val); kfree(desc); return 0; } diff --git a/security/integrity/evm/evm_main.c b/security/integrity/evm/evm_main.c index 063d38aef64e..ff3c35a7058c 100644 --- a/security/integrity/evm/evm_main.c +++ b/security/integrity/evm/evm_main.c @@ -161,8 +161,10 @@ static enum integrity_status evm_verify_hmac(struct dentry *dentry, rc = -EINVAL; break; case EVM_IMA_XATTR_DIGSIG: + case EVM_IMA_XATTR_PORTABLE_DIGSIG: rc = evm_calc_hash(dentry, xattr_name, xattr_value, - xattr_value_len, calc.digest); + xattr_value_len, xattr_data->type, + calc.digest); if (rc) break; rc = integrity_digsig_verify(INTEGRITY_KEYRING_EVM, @@ -345,7 +347,8 @@ int evm_inode_setxattr(struct dentry *dentry, const char *xattr_name, if (strcmp(xattr_name, XATTR_NAME_EVM) == 0) { if (!xattr_value_len) return -EINVAL; - if (xattr_data->type != EVM_IMA_XATTR_DIGSIG) + if (xattr_data->type != EVM_IMA_XATTR_DIGSIG && + xattr_data->type != EVM_IMA_XATTR_PORTABLE_DIGSIG) return -EPERM; } return evm_protect_xattr(dentry, xattr_name, xattr_value, diff --git a/security/integrity/integrity.h b/security/integrity/integrity.h index a53e7e4ab06c..0a721c110e92 100644 --- a/security/integrity/integrity.h +++ b/security/integrity/integrity.h @@ -58,6 +58,7 @@ enum evm_ima_xattr_type { EVM_XATTR_HMAC, EVM_IMA_XATTR_DIGSIG, IMA_XATTR_DIGEST_NG, + EVM_IMA_XATTR_PORTABLE_DIGSIG, IMA_XATTR_LAST };