Received: by 2002:a25:4158:0:0:0:0:0 with SMTP id o85csp1077164yba; Wed, 24 Apr 2019 14:40:25 -0700 (PDT) X-Google-Smtp-Source: APXvYqyi7dL7P+w88kaXuTUoQaFFlOncNUDHihKclQgLXlSHWILkW/zKWGXH9hVro2m+E4aAfq+p X-Received: by 2002:a17:902:7e04:: with SMTP id b4mr12916195plm.211.1556142025176; Wed, 24 Apr 2019 14:40:25 -0700 (PDT) ARC-Seal: i=1; a=rsa-sha256; t=1556142025; cv=none; d=google.com; s=arc-20160816; b=G3EY3VBGz3O1ay3SaJEBfVO9M70e/j3lgxOfBm8QcBtZQ3KYTI1dhxtxC+5hEaLLs3 XCRKpDXj5bLO5b/sm0BL6r7h9qAyIUQ2cEXesTU3Y6ywLUgbqP1hXrQfLDbW6OzQBJoJ x0F5fx/Ax9i66UXEKA7NaioS0/9srGUUEHEQg8yDGVmEsJGdoufuT3bLYxmtnzgf4LJ7 uG3FPDWqgYck0D9RCR++7XHCJEKH8+rZI9qOQJKgfC9ITeGFm7DetfoBjthZGfYZFPgk ifuTAB9wUvLq9vYvjTtC7kgE1HwH9kx/i5dVlvkLFWVaFEBCC3conqbtClY2ehnK9zZv CQPg== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20160816; h=list-id:precedence:sender:content-transfer-encoding:mime-version :user-agent:references:in-reply-to:message-id:date:cc:to:from :subject:organization; bh=6EL1kZv4mUX6epXMaBsHkq2JzIoev0aRuvwefvOL/3k=; b=VwHai4ovzepV6tYwMhZsVRnoWsnN/xh6esEDzPMDpnZJKcNz4/dMKY9f/Vb5w7QnlU TzZZH6+yOMrmKwR8cK1yd6dy9wvNlAu5pTprXdwoTQ7fZbHcrVLinaKajecB8R2sJZNZ M1HO8e5KnEB6/SzRzRi7s3rjR/5+bhpart7GIwM0mgNVOM61W1h0xqb1mVcsyrHJ/jpl 4BwuTalX7ZXC/DKVHFWPjaf5ieNjS1BiwMiVxlQgLhp34X00tGdK9RBcn0MdgHGmlTfm 7A4zDpyKEx6gS3H0qTHv2o95kHtQbsijy9h+1O0xjutLwcAhEfbyx9MgI+/bP0pXijzQ hP6w== 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=redhat.com Return-Path: Received: from vger.kernel.org (vger.kernel.org. [209.132.180.67]) by mx.google.com with ESMTP id q190si21479039pfq.261.2019.04.24.14.40.09; Wed, 24 Apr 2019 14:40:25 -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=redhat.com Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1732408AbfDXQOQ (ORCPT + 99 others); Wed, 24 Apr 2019 12:14:16 -0400 Received: from mx1.redhat.com ([209.132.183.28]:38510 "EHLO mx1.redhat.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1730782AbfDXQOP (ORCPT ); Wed, 24 Apr 2019 12:14:15 -0400 Received: from smtp.corp.redhat.com (int-mx07.intmail.prod.int.phx2.redhat.com [10.5.11.22]) (using TLSv1.2 with cipher AECDH-AES256-SHA (256/256 bits)) (No client certificate requested) by mx1.redhat.com (Postfix) with ESMTPS id 7EB4A30A8185; Wed, 24 Apr 2019 16:14:14 +0000 (UTC) Received: from warthog.procyon.org.uk (ovpn-121-98.rdu2.redhat.com [10.10.121.98]) by smtp.corp.redhat.com (Postfix) with ESMTP id C37E61018A00; Wed, 24 Apr 2019 16:14:12 +0000 (UTC) Organization: Red Hat UK Ltd. Registered Address: Red Hat UK Ltd, Amberley Place, 107-111 Peascod Street, Windsor, Berkshire, SI4 1TE, United Kingdom. Registered in England and Wales under Company Registration No. 3798903 Subject: [PATCH 05/11] keys: Add a 'recurse' flag for keyring searches From: David Howells To: ebiederm@xmission.com Cc: keyrings@vger.kernel.org, dhowells@redhat.com, linux-security-module@vger.kernel.org, linux-fsdevel@vger.kernel.org, linux-kernel@vger.kernel.org, dwalsh@redhat.com, vgoyal@redhat.com Date: Wed, 24 Apr 2019 17:14:12 +0100 Message-ID: <155612245200.8564.4960129218705025182.stgit@warthog.procyon.org.uk> In-Reply-To: <155612240208.8564.13865046977065545591.stgit@warthog.procyon.org.uk> References: <155612240208.8564.13865046977065545591.stgit@warthog.procyon.org.uk> User-Agent: StGit/unknown-version MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" Content-Transfer-Encoding: 7bit X-Scanned-By: MIMEDefang 2.84 on 10.5.11.22 X-Greylist: Sender IP whitelisted, not delayed by milter-greylist-4.5.16 (mx1.redhat.com [10.5.110.44]); Wed, 24 Apr 2019 16:14:14 +0000 (UTC) Sender: linux-kernel-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-kernel@vger.kernel.org Add a 'recurse' flag for keyring searches so that the flag can be omitted and recursion disabled, thereby allowing just the nominated keyring to be searched and none of the children. Signed-off-by: David Howells --- Documentation/security/keys/core.rst | 10 ++++++---- certs/blacklist.c | 2 +- crypto/asymmetric_keys/asymmetric_type.c | 2 +- include/linux/key.h | 3 ++- lib/digsig.c | 2 +- net/rxrpc/security.c | 2 +- security/integrity/digsig_asymmetric.c | 4 ++-- security/keys/internal.h | 1 + security/keys/keyctl.c | 2 +- security/keys/keyring.c | 12 ++++++++++-- security/keys/proc.c | 3 ++- security/keys/process_keys.c | 3 ++- security/keys/request_key.c | 3 ++- security/keys/request_key_auth.c | 3 ++- 14 files changed, 34 insertions(+), 18 deletions(-) diff --git a/Documentation/security/keys/core.rst b/Documentation/security/keys/core.rst index 9521c4207f01..99079b664036 100644 --- a/Documentation/security/keys/core.rst +++ b/Documentation/security/keys/core.rst @@ -1159,11 +1159,13 @@ payload contents" for more information. key_ref_t keyring_search(key_ref_t keyring_ref, const struct key_type *type, - const char *description) + const char *description, + bool recurse) - This searches the keyring tree specified for a matching key. Error ENOKEY - is returned upon failure (use IS_ERR/PTR_ERR to determine). If successful, - the returned key will need to be released. + This searches the specified keyring only (recurse == false) or keyring tree + (recurse == true) specified for a matching key. Error ENOKEY is returned + upon failure (use IS_ERR/PTR_ERR to determine). If successful, the returned + key will need to be released. The possession attribute from the keyring reference is used to control access through the permissions mask and is propagated to the returned key diff --git a/certs/blacklist.c b/certs/blacklist.c index 3a507b9e2568..181cb7fa9540 100644 --- a/certs/blacklist.c +++ b/certs/blacklist.c @@ -128,7 +128,7 @@ int is_hash_blacklisted(const u8 *hash, size_t hash_len, const char *type) *p = 0; kref = keyring_search(make_key_ref(blacklist_keyring, true), - &key_type_blacklist, buffer); + &key_type_blacklist, buffer, false); if (!IS_ERR(kref)) { key_ref_put(kref); ret = -EKEYREJECTED; diff --git a/crypto/asymmetric_keys/asymmetric_type.c b/crypto/asymmetric_keys/asymmetric_type.c index 69a0788a7de5..084027ef3121 100644 --- a/crypto/asymmetric_keys/asymmetric_type.c +++ b/crypto/asymmetric_keys/asymmetric_type.c @@ -87,7 +87,7 @@ struct key *find_asymmetric_key(struct key *keyring, pr_debug("Look up: \"%s\"\n", req); ref = keyring_search(make_key_ref(keyring, 1), - &key_type_asymmetric, req); + &key_type_asymmetric, req, true); if (IS_ERR(ref)) pr_debug("Request for key '%s' err %ld\n", req, PTR_ERR(ref)); kfree(req); diff --git a/include/linux/key.h b/include/linux/key.h index b39f5876b66d..bdd179169508 100644 --- a/include/linux/key.h +++ b/include/linux/key.h @@ -333,7 +333,8 @@ extern int keyring_clear(struct key *keyring); extern key_ref_t keyring_search(key_ref_t keyring, struct key_type *type, - const char *description); + const char *description, + bool no_recurse); extern int keyring_add_key(struct key *keyring, struct key *key); diff --git a/lib/digsig.c b/lib/digsig.c index 6ba6fcd92dd1..abec995a0982 100644 --- a/lib/digsig.c +++ b/lib/digsig.c @@ -221,7 +221,7 @@ int digsig_verify(struct key *keyring, const char *sig, int siglen, /* search in specific keyring */ key_ref_t kref; kref = keyring_search(make_key_ref(keyring, 1UL), - &key_type_user, name); + &key_type_user, name, true); if (IS_ERR(kref)) key = ERR_CAST(kref); else diff --git a/net/rxrpc/security.c b/net/rxrpc/security.c index c4479afe8ae7..2cfc7125bc41 100644 --- a/net/rxrpc/security.c +++ b/net/rxrpc/security.c @@ -148,7 +148,7 @@ int rxrpc_init_server_conn_security(struct rxrpc_connection *conn) /* look through the service's keyring */ kref = keyring_search(make_key_ref(rx->securities, 1UL), - &key_type_rxrpc_s, kdesc); + &key_type_rxrpc_s, kdesc, true); if (IS_ERR(kref)) { read_unlock(&local->services_lock); _leave(" = %ld [search]", PTR_ERR(kref)); diff --git a/security/integrity/digsig_asymmetric.c b/security/integrity/digsig_asymmetric.c index d775e03fbbcc..fa52fbaef520 100644 --- a/security/integrity/digsig_asymmetric.c +++ b/security/integrity/digsig_asymmetric.c @@ -39,7 +39,7 @@ static struct key *request_asymmetric_key(struct key *keyring, uint32_t keyid) key_ref_t kref; kref = keyring_search(make_key_ref(key, 1), - &key_type_asymmetric, name); + &key_type_asymmetric, name, true); if (!IS_ERR(kref)) { pr_err("Key '%s' is in ima_blacklist_keyring\n", name); return ERR_PTR(-EKEYREJECTED); @@ -51,7 +51,7 @@ static struct key *request_asymmetric_key(struct key *keyring, uint32_t keyid) key_ref_t kref; kref = keyring_search(make_key_ref(keyring, 1), - &key_type_asymmetric, name); + &key_type_asymmetric, name, true); if (IS_ERR(kref)) key = ERR_CAST(kref); else diff --git a/security/keys/internal.h b/security/keys/internal.h index 3154ba59a2f0..8ac7573bf23b 100644 --- a/security/keys/internal.h +++ b/security/keys/internal.h @@ -123,6 +123,7 @@ struct keyring_search_context { #define KEYRING_SEARCH_NO_CHECK_PERM 0x0008 /* Don't check permissions */ #define KEYRING_SEARCH_DETECT_TOO_DEEP 0x0010 /* Give an error on excessive depth */ #define KEYRING_SEARCH_SKIP_EXPIRED 0x0020 /* Ignore expired keys (intention to replace) */ +#define KEYRING_SEARCH_RECURSE 0x0040 /* Search child keyrings also */ int (*iterator)(const void *object, void *iterator_data); diff --git a/security/keys/keyctl.c b/security/keys/keyctl.c index 3e4053a217c3..d2023d550bd6 100644 --- a/security/keys/keyctl.c +++ b/security/keys/keyctl.c @@ -704,7 +704,7 @@ long keyctl_keyring_search(key_serial_t ringid, } /* do the search */ - key_ref = keyring_search(keyring_ref, ktype, description); + key_ref = keyring_search(keyring_ref, ktype, description, true); if (IS_ERR(key_ref)) { ret = PTR_ERR(key_ref); diff --git a/security/keys/keyring.c b/security/keys/keyring.c index 7f5f8d76dd7d..29a6e3255157 100644 --- a/security/keys/keyring.c +++ b/security/keys/keyring.c @@ -685,6 +685,9 @@ static bool search_nested_keyrings(struct key *keyring, * Non-keyrings avoid the leftmost branch of the root entirely (root * slots 1-15). */ + if (!(ctx->flags & KEYRING_SEARCH_RECURSE)) + goto not_this_keyring; + ptr = READ_ONCE(keyring->keys.root); if (!ptr) goto not_this_keyring; @@ -885,13 +888,15 @@ key_ref_t keyring_search_aux(key_ref_t keyring_ref, * @keyring: The root of the keyring tree to be searched. * @type: The type of keyring we want to find. * @description: The name of the keyring we want to find. + * @recurse: True to search the children of @keyring also * * As keyring_search_aux() above, but using the current task's credentials and * type's default matching function and preferred search method. */ key_ref_t keyring_search(key_ref_t keyring, struct key_type *type, - const char *description) + const char *description, + bool recurse) { struct keyring_search_context ctx = { .index_key.type = type, @@ -906,6 +911,8 @@ key_ref_t keyring_search(key_ref_t keyring, key_ref_t key; int ret; + if (recurse) + ctx.flags |= KEYRING_SEARCH_RECURSE; if (type->match_preparse) { ret = type->match_preparse(&ctx.match_data); if (ret < 0) @@ -1170,7 +1177,8 @@ static int keyring_detect_cycle(struct key *A, struct key *B) .flags = (KEYRING_SEARCH_NO_STATE_CHECK | KEYRING_SEARCH_NO_UPDATE_TIME | KEYRING_SEARCH_NO_CHECK_PERM | - KEYRING_SEARCH_DETECT_TOO_DEEP), + KEYRING_SEARCH_DETECT_TOO_DEEP | + KEYRING_SEARCH_RECURSE), }; rcu_read_lock(); diff --git a/security/keys/proc.c b/security/keys/proc.c index 78ac305d715e..8695f6108da9 100644 --- a/security/keys/proc.c +++ b/security/keys/proc.c @@ -170,7 +170,8 @@ static int proc_keys_show(struct seq_file *m, void *v) .match_data.cmp = lookup_user_key_possessed, .match_data.raw_data = key, .match_data.lookup_type = KEYRING_SEARCH_LOOKUP_DIRECT, - .flags = KEYRING_SEARCH_NO_STATE_CHECK, + .flags = (KEYRING_SEARCH_NO_STATE_CHECK | + KEYRING_SEARCH_RECURSE), }; key_ref = make_key_ref(key, 0); diff --git a/security/keys/process_keys.c b/security/keys/process_keys.c index f05f7125a7d5..70fa20888ca8 100644 --- a/security/keys/process_keys.c +++ b/security/keys/process_keys.c @@ -540,7 +540,8 @@ key_ref_t lookup_user_key(key_serial_t id, unsigned long lflags, struct keyring_search_context ctx = { .match_data.cmp = lookup_user_key_possessed, .match_data.lookup_type = KEYRING_SEARCH_LOOKUP_DIRECT, - .flags = KEYRING_SEARCH_NO_STATE_CHECK, + .flags = (KEYRING_SEARCH_NO_STATE_CHECK | + KEYRING_SEARCH_RECURSE), }; struct request_key_auth *rka; struct key *key; diff --git a/security/keys/request_key.c b/security/keys/request_key.c index a5b74b7758f7..39802540ffff 100644 --- a/security/keys/request_key.c +++ b/security/keys/request_key.c @@ -537,7 +537,8 @@ struct key *request_key_and_link(struct key_type *type, .match_data.raw_data = description, .match_data.lookup_type = KEYRING_SEARCH_LOOKUP_DIRECT, .flags = (KEYRING_SEARCH_DO_STATE_CHECK | - KEYRING_SEARCH_SKIP_EXPIRED), + KEYRING_SEARCH_SKIP_EXPIRED | + KEYRING_SEARCH_RECURSE), }; struct key *key; key_ref_t key_ref; diff --git a/security/keys/request_key_auth.c b/security/keys/request_key_auth.c index bda6201c6c45..b83930581f4d 100644 --- a/security/keys/request_key_auth.c +++ b/security/keys/request_key_auth.c @@ -242,7 +242,8 @@ struct key *key_get_instantiation_authkey(key_serial_t target_id) .match_data.cmp = key_default_cmp, .match_data.raw_data = description, .match_data.lookup_type = KEYRING_SEARCH_LOOKUP_DIRECT, - .flags = KEYRING_SEARCH_DO_STATE_CHECK, + .flags = (KEYRING_SEARCH_DO_STATE_CHECK | + KEYRING_SEARCH_RECURSE), }; struct key *authkey; key_ref_t authkey_ref;