From patchwork Mon Jun 27 13:48:44 2016 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Petko Manolov X-Patchwork-Id: 9200639 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 2F97A60757 for ; Mon, 27 Jun 2016 13:49:01 +0000 (UTC) Received: from mail.wl.linuxfoundation.org (localhost [127.0.0.1]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id 1EE7428591 for ; Mon, 27 Jun 2016 13:49:01 +0000 (UTC) Received: by mail.wl.linuxfoundation.org (Postfix, from userid 486) id 133CD2859C; Mon, 27 Jun 2016 13:49:01 +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=-6.8 required=2.0 tests=BAYES_00,DKIM_SIGNED, RCVD_IN_DNSWL_HI,T_DKIM_INVALID 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 4CB0F28591 for ; Mon, 27 Jun 2016 13:48:59 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1751639AbcF0Ns6 (ORCPT ); Mon, 27 Jun 2016 09:48:58 -0400 Received: from lan.nucleusys.com ([92.247.61.126]:37740 "EHLO zztop.nucleusys.com" rhost-flags-OK-OK-OK-FAIL) by vger.kernel.org with ESMTP id S1750870AbcF0Ns5 (ORCPT ); Mon, 27 Jun 2016 09:48:57 -0400 DKIM-Signature: v=1; a=rsa-sha256; q=dns/txt; c=relaxed/relaxed; d=mip-labs.com; s=x; h=In-Reply-To:Content-Type:MIME-Version:References:Message-ID:Subject:Cc:To:From:Date; bh=fZrpr+u0iqSm7z6QB58F75EtNHWx3mAuYoo8HaTpwp4=; b=nLyI5ijCVCpOoY7uQQ9/uccSLalEdiuwqmjGarLJvP+MGz/8ru+ctm7VSSlKHWyPThNOss8vILkcqJJHfAXC10va5SLJsJmfSKsGcauXQELFouFS1jrt7j3AHpiq1/cApv/lNbCvOyu5UX+yyosDuvEXBOAovYtk5cREJp9OSI4=; Received: from 78-83-74-100.spectrumnet.bg ([78.83.74.100] helo=p310) by zztop.nucleusys.com with esmtpsa (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.84_2) (envelope-from ) id 1bHWu7-0000Ah-Ie; Mon, 27 Jun 2016 16:48:48 +0300 Date: Mon, 27 Jun 2016 16:48:44 +0300 From: Petko Manolov To: David Howells Cc: linux-security-module@vger.kernel.org, zohar@linux.vnet.ibm.com, mdb@juniper.net Subject: Re: [IMA] [RFC] blacklist keyring Message-ID: <20160627134844.GA6417@p310> Mail-Followup-To: David Howells , linux-security-module@vger.kernel.org, zohar@linux.vnet.ibm.com, mdb@juniper.net References: <20160626163802.GA6230@localhost> <20160625101706.GD19933@p310> <32022.1466918601@warthog.procyon.org.uk> <22249.1466980601@warthog.procyon.org.uk> MIME-Version: 1.0 Content-Disposition: inline In-Reply-To: <22249.1466980601@warthog.procyon.org.uk> User-Agent: Mutt/1.6.0 (2016-04-01) Sender: owner-linux-security-module@vger.kernel.org Precedence: bulk List-ID: X-Virus-Scanned: ClamAV using ClamSMTP On 16-06-26 23:36:41, David Howells wrote: > Petko Manolov wrote: > > > Speaking from IMA perspective, the key (or rather the certificate) may be > > blacklisted at any time. Do you propose to keep the key into whatever > > keyring it has been put (.ima, .secondary_trusted_keys, etc.) and blacklist > > it's TBS hash? > > Note that you don't necessarily have to blacklist the TBS hash - that's why > the description is prefixed with "tbs:". You can prefix it with something > else to use some other attribute. It's just that's what the UEFI database > uses as its attribute of choice. I don't (yet) see a good reason not to comply with what UEFI is using as a prefix. In the future "ima:..." may be added for clarity where the key came from, but that's some time away. > > Isn't it easier to move the actual certificate from one keyring to another, > > since it is already taking space? Or maybe i am missing something important? > > That could be done also. There is no limitation that *only* blacklist-type > keys can be put on the blacklist keyring. So far i see no need to pollute the system blacklist. For keys used by the IMA subsystem i assume .ima_blacklist is the right place to go. > However, you're also potentially trading memory for lookup efficiency, and > when you permanently blacklist a asymmetric key, you could just ditch it and > merely remember the attribute by which it is blacklisted. The current patch looks up the key only once. If the key is blacklisted then the iint->flags gets updated so next time we walk the tree we fail early. I do like the idea of dumping 1~2KB of data in exchange for 32 bytes, assuming we use SHA256. However, as of now there is no such infrastructure. Maybe we should introduce a "blacklist" procedure where the key (or rather its payload) is kfree()-ed and only the digest (and/or the description) is kept around for reference. I am not entirely sure the above isn't an overkill. > > > to be a way to get the X.509 parser to generate blacklist type keys > > > instead of asymmetric keys. > > > > If i understand correctly you mean the x.509 parser should be taught to > > extract the TBSCertificate hash? If true then some poor bugger would have > > to implement the functionality. :) > > It has to do this already. "TBS" stands for "To Be Signed". That's the > element of the X.509 cert over which the signature is calculated and it's now > retained for trust calculation purposes. Yep, i got to realize this by looking at your code. Sometimes i am too slow. Below you'll find the two patches that i've applied on top of your most recent 'keys-next' branch. The first is the one i already sent for review, while the second is making use of the system blacklist keyring if it is configured. You can also take them from https://github.com/petkan/linux, branch 'keys'. I could not test them as your branch oopses with something like (stock -rc4 is fine): --- [ 0.000000] Linux version 4.7.0-rc2-ima+ (petkan@p310) (gcc version 6.1.1 20160620 (Debian 6.1.1-7) ) #74 SMP Mon Jun 27 14:33:54 EEST 2016 [ 0.000000] Command line: BOOT_IMAGE=/boot/vmlinuz-4.7.0-rc2-ima+ root=/dev/sda1 ro quiet ... [ 245.157373] audit: type=1805 audit(1467027525.416:2): action="dont_measure" fsmagic="0x9fa0" res=1 [ 245.157383] audit: type=1805 audit(1467027525.416:3): action="dont_appraise" fsmagic="0x9fa0" res=1 [ 245.157389] audit: type=1805 audit(1467027525.416:4): action="dont_measure" fsmagic="0x62656572" res=1 [ 245.157395] audit: type=1805 audit(1467027525.416:5): action="dont_appraise" fsmagic="0x62656572" res=1 [ 245.157401] audit: type=1805 audit(1467027525.416:6): action="dont_measure" fsmagic="0x64626720" res=1 [ 245.157407] audit: type=1805 audit(1467027525.416:7): action="dont_appraise" fsmagic="0x64626720" res=1 [ 245.157412] audit: type=1805 audit(1467027525.416:8): action="dont_measure" fsmagic="0x01021994" res=1 [ 245.157418] audit: type=1805 audit(1467027525.416:9): action="dont_appraise" fsmagic="0x01021994" res=1 [ 245.157423] audit: type=1805 audit(1467027525.416:10): action="dont_measure" fsmagic="0x858458f6" res=1 [ 245.157429] audit: type=1805 audit(1467027525.416:11): action="dont_appraise" fsmagic="0x858458f6" res=1 [ 245.157571] IMA: policy update completed [ 246.736871] IMA: policy update completed [ 250.409772] integrity: Request for unknown key 'id:ca52fbf2' err -11 [ 250.409901] audit_printk_skb: 18 callbacks suppressed [ 250.409902] audit: type=1800 audit(1467027530.666:18): pid=1319 uid=1001 auid=1001 ses=2 op="appraise_data" cause="invalid-signature" comm="busybox-a" name="/home/user/crap/busybox-a" dev="sda1" ino=1076 res=0 [ 250.936938] integrity: Request for unknown key 'id:ca52fbf2' err -11 [ 250.937319] audit: type=1800 audit(1467027531.196:19): pid=1320 uid=1001 auid=1001 ses=2 op="appraise_data" cause="invalid-signature" comm="busybox-a" name="/home/user/crap/busybox-a" dev="sda1" ino=1076 res=0 [ 251.470857] integrity: Request for unknown key 'id:ca52fbf2' err -11 [ 251.471238] audit: type=1800 audit(1467027531.726:20): pid=1321 uid=1001 auid=1001 ses=2 op="appraise_data" cause="invalid-signature" comm="busybox-a" name="/home/user/crap/busybox-a" dev="sda1" ino=1076 res=0 [ 253.099136] BUG: unable to handle kernel NULL pointer dereference at (null) [ 253.099395] IP: [] software_key_determine_akcipher.isra.0+0x19/0xb0 [ 253.099592] PGD 0 [ 253.099689] Oops: 0000 [#1] SMP [ 253.099760] Modules linked in: [ 253.099875] CPU: 0 PID: 1322 Comm: busybox-b Not tainted 4.7.0-rc2-ima+ #74 [ 253.100010] Hardware name: QEMU Standard PC (i440FX + PIIX, 1996), BIOS Debian-1.8.2-1 04/01/2014 [ 253.100176] task: ffff88003d771ec0 ti: ffff88003d950000 task.ti: ffff88003d950000 [ 253.100319] RIP: 0010:[] [] software_key_determine_akcipher.isra.0+0x19/0xb0 [ 253.100553] RSP: 0018:ffff88003d953b00 EFLAGS: 00010282 [ 253.100660] RAX: 0000000000000000 RBX: ffff88003d953c00 RCX: 0000000000000006 [ 253.100797] RDX: ffff88003e110198 RSI: 0000000000000000 RDI: ffffffff814cc22e [ 253.100935] RBP: ffff88003d953c80 R08: ffffffff814caaf6 R09: ffff88003d953b78 [ 253.101072] R10: ffffea0000f8e880 R11: ffff88003e001e00 R12: ffff88003d953c00 [ 253.101209] R13: ffff88003e110180 R14: ffff88003e21ea00 R15: ffff88003db60cc0 [ 253.101347] FS: 00007f4c2a806700(0000) GS:ffff88003fc00000(0000) knlGS:0000000000000000 [ 253.101500] CS: 0010 DS: 0000 ES: 0000 CR0: 0000000080050033 [ 253.101614] CR2: 0000000000000000 CR3: 000000003d4de000 CR4: 00000000000006b0 [ 253.101753] DR0: 0000000000000000 DR1: 0000000000000000 DR2: 0000000000000000 [ 253.101898] DR3: 0000000000000000 DR6: 00000000fffe0ff0 DR7: 0000000000000400 [ 253.102011] Stack: [ 253.102055] ffff88003d953c00 ffffffff812003e5 ffff88003e2da6c0 ffff88003daf5058 [ 253.102414] ffff88003e21ea00 ffff88003e2da6c0 ffffffff811dbcc1 ffff88003d953b60 [ 253.102773] ffff88003e2da6c1 ffff88003d953b60 ffffffff811dbd76 ffff88003db60cc1 [ 253.103137] Call Trace: [ 253.103282] [] ? public_key_verify_signature+0x55/0x200 [ 253.103487] [] ? keyring_search_aux+0x61/0x90 [ 253.103677] [] ? keyring_search+0x86/0xa0 [ 253.103864] [] ? asymmetric_key_id_partial+0x40/0x40 [ 253.104063] [] ? key_default_cmp+0x20/0x20 [ 253.104252] [] ? asymmetric_verify+0x172/0x2a0 [ 253.104445] [] ? ima_appraise_measurement+0x363/0x3d0 [ 253.104646] [] ? process_measurement+0x508/0x5c0 [ 253.104841] [] ? vm_mmap_pgoff+0x3d/0xd0 [ 253.105036] [] ? setup_arg_pages+0x1ab/0x210 [ 253.105221] [] ? load_elf_binary+0x5f6/0x1660 [ 253.105406] [] ? search_binary_handler+0x9b/0x1c0 [ 253.105595] [] ? do_execveat_common+0x4f4/0x640 [ 253.105782] [] ? SyS_execve+0x23/0x30 [ 253.105959] [] ? do_syscall_64+0x45/0x90 [ 253.106140] [] ? entry_SYSCALL64_slow_path+0x25/0x25 [ 253.106332] Code: 8b 50 10 e9 9a 67 f4 ff c3 66 0f 1f 84 00 00 00 00 00 48 89 f8 53 49 89 f0 49 89 c9 48 c7 c7 2e c2 4c 81 b9 06 00 00 00 48 89 c6 a6 0f 97 c3 0f 92 c1 29 cb 0f be db 85 db 75 2b 4d 85 c0 48 [ 253.109023] RIP [] software_key_determine_akcipher.isra.0+0x19/0xb0 [ 253.109260] RSP [ 253.109410] CR2: 0000000000000000 [ 253.109563] ---[ end trace ebb97510ccea56f8 ]--- --- patch one --- From b0d6a735884af6b7ef4d20730635aae8768e9b29 Mon Sep 17 00:00:00 2001 From: Petko Manolov Date: Sun, 26 Jun 2016 13:39:09 +0300 Subject: [PATCH 1/2] WIP: a stab at IMA blacklist functionality; Signed-off-by: Petko Manolov --- security/integrity/digsig.c | 5 ++- security/integrity/digsig_asymmetric.c | 9 ++++- security/integrity/evm/evm_main.c | 8 +++- security/integrity/iint.c | 69 +++++++++++++++++++++++++++++++++- security/integrity/ima/ima_appraise.c | 6 +-- security/integrity/ima/ima_main.c | 8 ++-- security/integrity/integrity.h | 19 ++++++++-- 7 files changed, 108 insertions(+), 16 deletions(-) diff --git a/security/integrity/digsig.c b/security/integrity/digsig.c index 4304372..483f870 100644 --- a/security/integrity/digsig.c +++ b/security/integrity/digsig.c @@ -49,7 +49,8 @@ static bool init_keyring __initdata; #endif int integrity_digsig_verify(const unsigned int id, const char *sig, int siglen, - const char *digest, int digestlen) + const char *digest, int digestlen, + struct integrity_iint_cache *iint) { if (id >= INTEGRITY_KEYRING_MAX) return -EINVAL; @@ -72,7 +73,7 @@ int integrity_digsig_verify(const unsigned int id, const char *sig, int siglen, digest, digestlen); case 2: return asymmetric_verify(keyring[id], sig, siglen, - digest, digestlen); + digest, digestlen, iint); } return -EOPNOTSUPP; diff --git a/security/integrity/digsig_asymmetric.c b/security/integrity/digsig_asymmetric.c index 80052ed..40657df 100644 --- a/security/integrity/digsig_asymmetric.c +++ b/security/integrity/digsig_asymmetric.c @@ -80,7 +80,8 @@ static struct key *request_asymmetric_key(struct key *keyring, uint32_t keyid) } int asymmetric_verify(struct key *keyring, const char *sig, - int siglen, const char *data, int datalen) + int siglen, const char *data, int datalen, + struct integrity_iint_cache *iint) { struct public_key_signature pks; struct signature_v2_hdr *hdr = (struct signature_v2_hdr *)sig; @@ -113,5 +114,11 @@ int asymmetric_verify(struct key *keyring, const char *sig, ret = verify_signature(key, &pks); key_put(key); pr_debug("%s() = %d\n", __func__, ret); +#ifdef CONFIG_IMA_BLACKLIST_KEYRING + if (!ret && iint) { + iint->key = key; + iint->last_time = current_kernel_time().tv_sec; + } +#endif return ret; } diff --git a/security/integrity/evm/evm_main.c b/security/integrity/evm/evm_main.c index b9e2628..0c0a93a 100644 --- a/security/integrity/evm/evm_main.c +++ b/security/integrity/evm/evm_main.c @@ -161,7 +161,7 @@ static enum integrity_status evm_verify_hmac(struct dentry *dentry, break; rc = integrity_digsig_verify(INTEGRITY_KEYRING_EVM, (const char *)xattr_data, xattr_len, - calc.digest, sizeof(calc.digest)); + calc.digest, sizeof(calc.digest), NULL); if (!rc) { /* Replace RSA with HMAC if not mounted readonly and * not immutable @@ -237,7 +237,7 @@ enum integrity_status evm_verifyxattr(struct dentry *dentry, if (!iint) { iint = integrity_iint_find(d_backing_inode(dentry)); - if (!iint) + if (!iint || IS_ERR(iint)) return INTEGRITY_UNKNOWN; } return evm_verify_hmac(dentry, xattr_name, xattr_value, @@ -295,6 +295,8 @@ static int evm_protect_xattr(struct dentry *dentry, const char *xattr_name, struct integrity_iint_cache *iint; iint = integrity_iint_find(d_backing_inode(dentry)); + if (IS_ERR(iint)) + return -EPERM; if (iint && (iint->flags & IMA_NEW_FILE)) return 0; @@ -364,6 +366,8 @@ static void evm_reset_status(struct inode *inode) struct integrity_iint_cache *iint; iint = integrity_iint_find(inode); + if (IS_ERR(iint)) + return; if (iint) iint->evm_status = INTEGRITY_UNKNOWN; } diff --git a/security/integrity/iint.c b/security/integrity/iint.c index 345b759..68f95f3 100644 --- a/security/integrity/iint.c +++ b/security/integrity/iint.c @@ -21,12 +21,62 @@ #include #include #include +#include +#include +#include #include "integrity.h" static struct rb_root integrity_iint_tree = RB_ROOT; static DEFINE_RWLOCK(integrity_iint_lock); static struct kmem_cache *iint_cache __read_mostly; +#ifdef CONFIG_IMA_BLACKLIST_KEYRING +static int keys_in_keyring(struct key *keyring) +{ + if (key_is_instantiated(keyring)) { + return keyring->keys.nr_leaves_on_tree; + } + + return -EINVAL; +} + +/* + * returns negative if the key is not blacklisted and 0 if it is; + */ +static int iint_bl_check(struct integrity_iint_cache *iint) +{ + struct key *bl; + key_ref_t bl_t, key=ERR_PTR(-ENOKEY); + + if (!iint) + return -1; + + if (iint->flags & IMA_IINT_BLACKLISTED) + return 0; + + bl = get_ima_blacklist_keyring(); + if (!bl) + return -2; + + if (!keys_in_keyring(bl)) + return -3; + + if (iint->last_time > bl->last_used_at) + return -4; + + bl_t = make_key_ref(bl, 1); + if (iint->key) + key = keyring_search(bl_t, &key_type_asymmetric, iint->key->description); + + if (IS_ERR(key)) + return -5; + + iint->flags |= IMA_IINT_BLACKLISTED; + + return 0; +} +#endif /* CONFIG_IMA_BLACKLIST_KEYRING */ + /* * __integrity_iint_find - return the iint associated with an inode */ @@ -52,7 +102,8 @@ static struct integrity_iint_cache *__integrity_iint_find(struct inode *inode) } /* - * integrity_iint_find - return the iint associated with an inode + * integrity_iint_find - return the iint associated with an inode, NULL or + * an error if the corrsponding key has been blacklisted in the meantime. */ struct integrity_iint_cache *integrity_iint_find(struct inode *inode) { @@ -65,6 +116,14 @@ struct integrity_iint_cache *integrity_iint_find(struct inode *inode) iint = __integrity_iint_find(inode); read_unlock(&integrity_iint_lock); +#ifdef CONFIG_IMA_BLACKLIST_KEYRING + if (!iint_bl_check(iint)) { + integrity_audit_msg(AUDIT_INTEGRITY_DATA, inode, NULL, + "appraise_data", "blacklisted-key", + -EINVAL, 0); + return ERR_PTR(-EINVAL); + } +#endif return iint; } @@ -79,6 +138,10 @@ static void iint_free(struct integrity_iint_cache *iint) iint->ima_bprm_status = INTEGRITY_UNKNOWN; iint->ima_read_status = INTEGRITY_UNKNOWN; iint->evm_status = INTEGRITY_UNKNOWN; +#ifdef CONFIG_IMA_BLACKLIST_KEYRING + iint->key = NULL; + iint->last_time = 0; +#endif kmem_cache_free(iint_cache, iint); } @@ -159,6 +222,10 @@ static void init_once(void *foo) iint->ima_bprm_status = INTEGRITY_UNKNOWN; iint->ima_read_status = INTEGRITY_UNKNOWN; iint->evm_status = INTEGRITY_UNKNOWN; +#ifdef CONFIG_IMA_BLACKLIST_KEYRING + iint->key = NULL; + iint->last_time = 0; +#endif } static int __init integrity_iintcache_init(void) diff --git a/security/integrity/ima/ima_appraise.c b/security/integrity/ima/ima_appraise.c index 1bcbc12..4c8bca2 100644 --- a/security/integrity/ima/ima_appraise.c +++ b/security/integrity/ima/ima_appraise.c @@ -252,7 +252,7 @@ int ima_appraise_measurement(enum ima_hooks func, rc = integrity_digsig_verify(INTEGRITY_KEYRING_IMA, (const char *)xattr_value, rc, iint->ima_hash->digest, - iint->ima_hash->length); + iint->ima_hash->length, iint); if (rc == -EOPNOTSUPP) { status = INTEGRITY_UNKNOWN; } else if (rc) { @@ -330,7 +330,7 @@ void ima_inode_post_setattr(struct dentry *dentry) must_appraise = ima_must_appraise(inode, MAY_ACCESS, POST_SETATTR); iint = integrity_iint_find(inode); - if (iint) { + if (iint && !IS_ERR(iint)) { iint->flags &= ~(IMA_APPRAISE | IMA_APPRAISED | IMA_APPRAISE_SUBMASK | IMA_APPRAISED_SUBMASK | IMA_ACTION_RULE_FLAGS); @@ -366,7 +366,7 @@ static void ima_reset_appraise_flags(struct inode *inode, int digsig) return; iint = integrity_iint_find(inode); - if (!iint) + if (!iint || IS_ERR(iint)) return; iint->flags &= ~IMA_DONE_MASK; diff --git a/security/integrity/ima/ima_main.c b/security/integrity/ima/ima_main.c index 68b26c3..7c866d8 100644 --- a/security/integrity/ima/ima_main.c +++ b/security/integrity/ima/ima_main.c @@ -90,6 +90,8 @@ static void ima_rdwr_violation_check(struct file *file, if (atomic_read(&inode->i_readcount) && IS_IMA(inode)) { if (!iint) iint = integrity_iint_find(inode); + if (IS_ERR(iint)) + return; /* IMA_MEASURE is set from reader side */ if (iint && (iint->flags & IMA_MEASURE)) send_tomtou = true; @@ -147,7 +149,7 @@ void ima_file_free(struct file *file) return; iint = integrity_iint_find(inode); - if (!iint) + if (!iint || IS_ERR(iint)) return; ima_check_last_writer(iint, inode, file); @@ -190,7 +192,7 @@ static int process_measurement(struct file *file, char *buf, loff_t size, if (action) { iint = integrity_inode_get(inode); - if (!iint) + if (!iint || IS_ERR(iint)) goto out; } @@ -334,7 +336,7 @@ void ima_post_path_mknod(struct dentry *dentry) return; iint = integrity_inode_get(inode); - if (iint) + if (iint && !IS_ERR(iint)) iint->flags |= IMA_NEW_FILE; } diff --git a/security/integrity/integrity.h b/security/integrity/integrity.h index 90bc57d..6076762 100644 --- a/security/integrity/integrity.h +++ b/security/integrity/integrity.h @@ -53,6 +53,9 @@ #define IMA_APPRAISED_SUBMASK (IMA_FILE_APPRAISED | IMA_MMAP_APPRAISED | \ IMA_BPRM_APPRAISED | IMA_READ_APPRAISED) +#define IMA_IINT_BLACKLISTED_BIT (BITS_PER_LONG - 1) +#define IMA_IINT_BLACKLISTED (1UL << IMA_IINT_BLACKLISTED_BIT) + enum evm_ima_xattr_type { IMA_XATTR_DIGEST = 0x01, EVM_XATTR_HMAC, @@ -109,6 +112,10 @@ struct integrity_iint_cache { enum integrity_status ima_read_status:4; enum integrity_status evm_status:4; struct ima_digest_data *ima_hash; +#ifdef CONFIG_IMA_BLACKLIST_KEYRING + struct key *key; + time_t last_time; +#endif }; /* rbtree tree calls to lookup, insert, delete @@ -128,7 +135,8 @@ int __init integrity_read_file(const char *path, char **data); #ifdef CONFIG_INTEGRITY_SIGNATURE int integrity_digsig_verify(const unsigned int id, const char *sig, int siglen, - const char *digest, int digestlen); + const char *digest, int digestlen, + struct integrity_iint_cache *iint); int __init integrity_init_keyring(const unsigned int id); int __init integrity_load_x509(const unsigned int id, const char *path); @@ -136,7 +144,8 @@ int __init integrity_load_x509(const unsigned int id, const char *path); static inline int integrity_digsig_verify(const unsigned int id, const char *sig, int siglen, - const char *digest, int digestlen) + const char *digest, int digestlen, + struct integrity_iint_cache *iint) { return -EOPNOTSUPP; } @@ -149,10 +158,12 @@ static inline int integrity_init_keyring(const unsigned int id) #ifdef CONFIG_INTEGRITY_ASYMMETRIC_KEYS int asymmetric_verify(struct key *keyring, const char *sig, - int siglen, const char *data, int datalen); + int siglen, const char *data, int datalen, + struct integrity_iint_cache *); #else static inline int asymmetric_verify(struct key *keyring, const char *sig, - int siglen, const char *data, int datalen) + int siglen, const char *data, int datalen, + struct integrity_iint_cache *) { return -EOPNOTSUPP; } -- 2.8.1 --- patch two --- From d80057badc1f987dc2ba244da43fbf0e3edd7294 Mon Sep 17 00:00:00 2001 From: Petko Manolov Date: Mon, 27 Jun 2016 15:21:17 +0300 Subject: [PATCH 2/2] make use of the system blacklist keyring, if available; Signed-off-by: Petko Manolov --- certs/blacklist.c | 4 ++-- include/keys/system_keyring.h | 2 ++ security/integrity/iint.c | 17 +++++++++++------ 3 files changed, 15 insertions(+), 8 deletions(-) diff --git a/certs/blacklist.c b/certs/blacklist.c index 3eddce0..bbabd86b 100644 --- a/certs/blacklist.c +++ b/certs/blacklist.c @@ -21,7 +21,7 @@ #include #include "blacklist.h" -static struct key *blacklist_keyring; +struct key *blacklist_keyring; /* * The description must be a type prefix, a colon and then an even number of @@ -71,7 +71,7 @@ static void blacklist_describe(const struct key *key, struct seq_file *m) seq_puts(m, key->description); } -static struct key_type key_type_blacklist = { +struct key_type key_type_blacklist = { .name = "blacklist", .vet_description = blacklist_vet_description, .preparse = blacklist_preparse, diff --git a/include/keys/system_keyring.h b/include/keys/system_keyring.h index 0d87626..8bc3ff4 100644 --- a/include/keys/system_keyring.h +++ b/include/keys/system_keyring.h @@ -34,6 +34,8 @@ extern int restrict_link_by_builtin_and_secondary_trusted( #endif #ifdef CONFIG_SYSTEM_BLACKLIST_KEYRING +extern struct key *blacklist_keyring; +extern struct key_type key_type_blacklist; extern int mark_hash_blacklisted(const char *hash); extern int is_hash_blacklisted(const u8 *hash, size_t hash_len, const char *type); diff --git a/security/integrity/iint.c b/security/integrity/iint.c index 68f95f3..e690873 100644 --- a/security/integrity/iint.c +++ b/security/integrity/iint.c @@ -46,7 +46,7 @@ static int keys_in_keyring(struct key *keyring) static int iint_bl_check(struct integrity_iint_cache *iint) { struct key *bl; - key_ref_t bl_t, key=ERR_PTR(-ENOKEY); + key_ref_t bl_t, ima=ERR_PTR(-ENOKEY), sys=ERR_PTR(-ENOKEY); if (!iint) return -1; @@ -64,11 +64,16 @@ static int iint_bl_check(struct integrity_iint_cache *iint) if (iint->last_time > bl->last_used_at) return -4; - bl_t = make_key_ref(bl, 1); - if (iint->key) - key = keyring_search(bl_t, &key_type_asymmetric, iint->key->description); - - if (IS_ERR(key)) + if (iint->key) { + bl_t = make_key_ref(bl, true); + ima = keyring_search(bl_t, &key_type_asymmetric, iint->key->description); +#ifdef CONFIG_SYSTEM_BLACKLIST_KEYRING + bl_t = make_key_ref(blacklist_keyring, true); + sys = keyring_search(bl_t, &key_type_blacklist, iint->key->description); +#endif + } + printk("%s: ima %p, sys %p\n", __func__, ima, sys); + if (IS_ERR(ima) && IS_ERR(sys)) return -5; iint->flags |= IMA_IINT_BLACKLISTED;