From patchwork Thu May 30 17:25:19 2019 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: David Howells X-Patchwork-Id: 10969115 Return-Path: Received: from mail.wl.linuxfoundation.org (pdx-wl-mail.web.codeaurora.org [172.30.200.125]) by pdx-korg-patchwork-2.web.codeaurora.org (Postfix) with ESMTP id EA6AE912 for ; Thu, 30 May 2019 17:25:26 +0000 (UTC) Received: from mail.wl.linuxfoundation.org (localhost [127.0.0.1]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id D91C9287E6 for ; Thu, 30 May 2019 17:25:26 +0000 (UTC) Received: by mail.wl.linuxfoundation.org (Postfix, from userid 486) id CCFB72883C; Thu, 30 May 2019 17:25:26 +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.9 required=2.0 tests=BAYES_00,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 5D983287E6 for ; Thu, 30 May 2019 17:25:26 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1726590AbfE3RZW (ORCPT ); Thu, 30 May 2019 13:25:22 -0400 Received: from mx1.redhat.com ([209.132.183.28]:42860 "EHLO mx1.redhat.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1725961AbfE3RZV (ORCPT ); Thu, 30 May 2019 13:25:21 -0400 Received: from smtp.corp.redhat.com (int-mx08.intmail.prod.int.phx2.redhat.com [10.5.11.23]) (using TLSv1.2 with cipher AECDH-AES256-SHA (256/256 bits)) (No client certificate requested) by mx1.redhat.com (Postfix) with ESMTPS id 9AAD030A6986; Thu, 30 May 2019 17:25:21 +0000 (UTC) Received: from warthog.procyon.org.uk (ovpn-120-173.rdu2.redhat.com [10.10.120.173]) by smtp.corp.redhat.com (Postfix) with ESMTP id 4AB1938E3A; Thu, 30 May 2019 17:25:20 +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 01/10] keys: sparse: Fix key_fs[ug]id_changed() [ver #2] From: David Howells To: keyrings@vger.kernel.org Cc: James Morris , dhowells@redhat.com, linux-security-module@vger.kernel.org, linux-kernel@vger.kernel.org, ebiggers@kernel.org Date: Thu, 30 May 2019 18:25:19 +0100 Message-ID: <155923711951.949.17453975846850465292.stgit@warthog.procyon.org.uk> In-Reply-To: <155923711088.949.14909672457214372214.stgit@warthog.procyon.org.uk> References: <155923711088.949.14909672457214372214.stgit@warthog.procyon.org.uk> User-Agent: StGit/unknown-version MIME-Version: 1.0 X-Scanned-By: MIMEDefang 2.84 on 10.5.11.23 X-Greylist: Sender IP whitelisted, not delayed by milter-greylist-4.5.16 (mx1.redhat.com [10.5.110.46]); Thu, 30 May 2019 17:25:21 +0000 (UTC) Sender: owner-linux-security-module@vger.kernel.org Precedence: bulk List-ID: X-Virus-Scanned: ClamAV using ClamSMTP Sparse warnings are incurred by key_fs[ug]id_changed() due to unprotected accesses of tsk->cred, which is marked __rcu. Fix this by passing the new cred struct to these functions from commit_creds() rather than the task pointer. Signed-off-by: David Howells Reviewed-by: James Morris --- include/linux/key.h | 8 ++++---- kernel/cred.c | 4 ++-- security/keys/process_keys.c | 22 ++++++++++------------ 3 files changed, 16 insertions(+), 18 deletions(-) diff --git a/include/linux/key.h b/include/linux/key.h index 7099985e35a9..1f09aad1c98c 100644 --- a/include/linux/key.h +++ b/include/linux/key.h @@ -402,8 +402,8 @@ extern struct ctl_table key_sysctls[]; * the userspace interface */ extern int install_thread_keyring_to_cred(struct cred *cred); -extern void key_fsuid_changed(struct task_struct *tsk); -extern void key_fsgid_changed(struct task_struct *tsk); +extern void key_fsuid_changed(struct cred *new_cred); +extern void key_fsgid_changed(struct cred *new_cred); extern void key_init(void); #else /* CONFIG_KEYS */ @@ -418,8 +418,8 @@ extern void key_init(void); #define make_key_ref(k, p) NULL #define key_ref_to_ptr(k) NULL #define is_key_possessed(k) 0 -#define key_fsuid_changed(t) do { } while(0) -#define key_fsgid_changed(t) do { } while(0) +#define key_fsuid_changed(c) do { } while(0) +#define key_fsgid_changed(c) do { } while(0) #define key_init() do { } while(0) #endif /* CONFIG_KEYS */ diff --git a/kernel/cred.c b/kernel/cred.c index 45d77284aed0..3bd40de9e192 100644 --- a/kernel/cred.c +++ b/kernel/cred.c @@ -455,9 +455,9 @@ int commit_creds(struct cred *new) /* alter the thread keyring */ if (!uid_eq(new->fsuid, old->fsuid)) - key_fsuid_changed(task); + key_fsuid_changed(new); if (!gid_eq(new->fsgid, old->fsgid)) - key_fsgid_changed(task); + key_fsgid_changed(new); /* do it * RLIMIT_NPROC limits on user->processes have already been checked diff --git a/security/keys/process_keys.c b/security/keys/process_keys.c index f05f7125a7d5..ba5d3172cafe 100644 --- a/security/keys/process_keys.c +++ b/security/keys/process_keys.c @@ -293,28 +293,26 @@ static int install_session_keyring(struct key *keyring) /* * Handle the fsuid changing. */ -void key_fsuid_changed(struct task_struct *tsk) +void key_fsuid_changed(struct cred *new_cred) { /* update the ownership of the thread keyring */ - BUG_ON(!tsk->cred); - if (tsk->cred->thread_keyring) { - down_write(&tsk->cred->thread_keyring->sem); - tsk->cred->thread_keyring->uid = tsk->cred->fsuid; - up_write(&tsk->cred->thread_keyring->sem); + if (new_cred->thread_keyring) { + down_write(&new_cred->thread_keyring->sem); + new_cred->thread_keyring->uid = new_cred->fsuid; + up_write(&new_cred->thread_keyring->sem); } } /* * Handle the fsgid changing. */ -void key_fsgid_changed(struct task_struct *tsk) +void key_fsgid_changed(struct cred *new_cred) { /* update the ownership of the thread keyring */ - BUG_ON(!tsk->cred); - if (tsk->cred->thread_keyring) { - down_write(&tsk->cred->thread_keyring->sem); - tsk->cred->thread_keyring->gid = tsk->cred->fsgid; - up_write(&tsk->cred->thread_keyring->sem); + if (new_cred->thread_keyring) { + down_write(&new_cred->thread_keyring->sem); + new_cred->thread_keyring->gid = new_cred->fsgid; + up_write(&new_cred->thread_keyring->sem); } } From patchwork Thu May 30 17:25:26 2019 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: David Howells X-Patchwork-Id: 10969119 Return-Path: Received: from mail.wl.linuxfoundation.org (pdx-wl-mail.web.codeaurora.org [172.30.200.125]) by pdx-korg-patchwork-2.web.codeaurora.org (Postfix) with ESMTP id D6D6713AD for ; Thu, 30 May 2019 17:25:33 +0000 (UTC) Received: from mail.wl.linuxfoundation.org (localhost [127.0.0.1]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id C4D08287E6 for ; Thu, 30 May 2019 17:25:33 +0000 (UTC) Received: by mail.wl.linuxfoundation.org (Postfix, from userid 486) id B6F562883C; Thu, 30 May 2019 17:25:33 +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.9 required=2.0 tests=BAYES_00,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 6650E287E6 for ; Thu, 30 May 2019 17:25:33 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1726674AbfE3RZ3 (ORCPT ); Thu, 30 May 2019 13:25:29 -0400 Received: from mx1.redhat.com ([209.132.183.28]:50268 "EHLO mx1.redhat.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1725961AbfE3RZ3 (ORCPT ); Thu, 30 May 2019 13:25:29 -0400 Received: from smtp.corp.redhat.com (int-mx05.intmail.prod.int.phx2.redhat.com [10.5.11.15]) (using TLSv1.2 with cipher AECDH-AES256-SHA (256/256 bits)) (No client certificate requested) by mx1.redhat.com (Postfix) with ESMTPS id DD1432E95BE; Thu, 30 May 2019 17:25:28 +0000 (UTC) Received: from warthog.procyon.org.uk (ovpn-120-173.rdu2.redhat.com [10.10.120.173]) by smtp.corp.redhat.com (Postfix) with ESMTP id B33917A40E; Thu, 30 May 2019 17:25:27 +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 02/10] keys: sparse: Fix incorrect RCU accesses [ver #2] From: David Howells To: keyrings@vger.kernel.org Cc: James Morris , dhowells@redhat.com, linux-security-module@vger.kernel.org, linux-kernel@vger.kernel.org, ebiggers@kernel.org Date: Thu, 30 May 2019 18:25:26 +0100 Message-ID: <155923712685.949.15444189913653209060.stgit@warthog.procyon.org.uk> In-Reply-To: <155923711088.949.14909672457214372214.stgit@warthog.procyon.org.uk> References: <155923711088.949.14909672457214372214.stgit@warthog.procyon.org.uk> User-Agent: StGit/unknown-version MIME-Version: 1.0 X-Scanned-By: MIMEDefang 2.79 on 10.5.11.15 X-Greylist: Sender IP whitelisted, not delayed by milter-greylist-4.5.16 (mx1.redhat.com [10.5.110.29]); Thu, 30 May 2019 17:25:28 +0000 (UTC) Sender: owner-linux-security-module@vger.kernel.org Precedence: bulk List-ID: X-Virus-Scanned: ClamAV using ClamSMTP Fix a pair of accesses that should be using RCU protection. rcu_dereference_protected() is needed to access task_struct::real_parent. current_cred() should be used to access current->cred. Signed-off-by: David Howells Reviewed-by: James Morris --- security/keys/keyctl.c | 3 ++- security/keys/request_key_auth.c | 2 +- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/security/keys/keyctl.c b/security/keys/keyctl.c index 3e4053a217c3..0f947bcbad46 100644 --- a/security/keys/keyctl.c +++ b/security/keys/keyctl.c @@ -1524,7 +1524,8 @@ long keyctl_session_to_parent(void) ret = -EPERM; oldwork = NULL; - parent = me->real_parent; + parent = rcu_dereference_protected(me->real_parent, + lockdep_is_held(&tasklist_lock)); /* the parent mustn't be init and mustn't be a kernel thread */ if (parent->pid <= 1 || !parent->mm) diff --git a/security/keys/request_key_auth.c b/security/keys/request_key_auth.c index bda6201c6c45..572c7a60473a 100644 --- a/security/keys/request_key_auth.c +++ b/security/keys/request_key_auth.c @@ -152,7 +152,7 @@ struct key *request_key_auth_new(struct key *target, const char *op, struct key *dest_keyring) { struct request_key_auth *rka, *irka; - const struct cred *cred = current->cred; + const struct cred *cred = current_cred(); struct key *authkey = NULL; char desc[20]; int ret = -ENOMEM; From patchwork Thu May 30 17:25:34 2019 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: David Howells X-Patchwork-Id: 10969121 Return-Path: Received: from mail.wl.linuxfoundation.org (pdx-wl-mail.web.codeaurora.org [172.30.200.125]) by pdx-korg-patchwork-2.web.codeaurora.org (Postfix) with ESMTP id F28B913AD for ; Thu, 30 May 2019 17:25:42 +0000 (UTC) Received: from mail.wl.linuxfoundation.org (localhost [127.0.0.1]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id E256B287E6 for ; Thu, 30 May 2019 17:25:42 +0000 (UTC) Received: by mail.wl.linuxfoundation.org (Postfix, from userid 486) id D66B92883C; Thu, 30 May 2019 17:25:42 +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.9 required=2.0 tests=BAYES_00,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 7C2D8287E6 for ; Thu, 30 May 2019 17:25:42 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1726735AbfE3RZl (ORCPT ); Thu, 30 May 2019 13:25:41 -0400 Received: from mx1.redhat.com ([209.132.183.28]:54754 "EHLO mx1.redhat.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1726546AbfE3RZl (ORCPT ); Thu, 30 May 2019 13:25:41 -0400 Received: from smtp.corp.redhat.com (int-mx02.intmail.prod.int.phx2.redhat.com [10.5.11.12]) (using TLSv1.2 with cipher AECDH-AES256-SHA (256/256 bits)) (No client certificate requested) by mx1.redhat.com (Postfix) with ESMTPS id 2EE2E3003A5A; Thu, 30 May 2019 17:25:36 +0000 (UTC) Received: from warthog.procyon.org.uk (ovpn-120-173.rdu2.redhat.com [10.10.120.173]) by smtp.corp.redhat.com (Postfix) with ESMTP id D3B3460C43; Thu, 30 May 2019 17:25:34 +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 03/10] keys: sparse: Fix kdoc mismatches [ver #2] From: David Howells To: keyrings@vger.kernel.org Cc: James Morris , Mat Martineau , dhowells@redhat.com, linux-security-module@vger.kernel.org, linux-kernel@vger.kernel.org, ebiggers@kernel.org Date: Thu, 30 May 2019 18:25:34 +0100 Message-ID: <155923713411.949.11422022582308560167.stgit@warthog.procyon.org.uk> In-Reply-To: <155923711088.949.14909672457214372214.stgit@warthog.procyon.org.uk> References: <155923711088.949.14909672457214372214.stgit@warthog.procyon.org.uk> User-Agent: StGit/unknown-version MIME-Version: 1.0 X-Scanned-By: MIMEDefang 2.79 on 10.5.11.12 X-Greylist: Sender IP whitelisted, not delayed by milter-greylist-4.5.16 (mx1.redhat.com [10.5.110.42]); Thu, 30 May 2019 17:25:41 +0000 (UTC) Sender: owner-linux-security-module@vger.kernel.org Precedence: bulk List-ID: X-Virus-Scanned: ClamAV using ClamSMTP Fix some kdoc argument description mismatches reported by sparse and give keyring_restrict() a description. Signed-off-by: David Howells Reviewed-by: James Morris cc: Mat Martineau --- security/keys/keyring.c | 10 +++++++--- security/keys/request_key.c | 2 +- 2 files changed, 8 insertions(+), 4 deletions(-) diff --git a/security/keys/keyring.c b/security/keys/keyring.c index e14f09e3a4b0..5b218b270598 100644 --- a/security/keys/keyring.c +++ b/security/keys/keyring.c @@ -520,7 +520,7 @@ EXPORT_SYMBOL(keyring_alloc); * @keyring: The keyring being added to. * @type: The type of key being added. * @payload: The payload of the key intended to be added. - * @data: Additional data for evaluating restriction. + * @restriction_key: Keys providing additional data for evaluating restriction. * * Reject the addition of any links to a keyring. It can be overridden by * passing KEY_ALLOC_BYPASS_RESTRICTION to key_instantiate_and_link() when @@ -976,9 +976,13 @@ static bool keyring_detect_restriction_cycle(const struct key *dest_keyring, /** * keyring_restrict - Look up and apply a restriction to a keyring - * - * @keyring: The keyring to be restricted + * @keyring_ref: The keyring to be restricted + * @type: The key type that will provide the restriction checker. * @restriction: The restriction options to apply to the keyring + * + * Look up a keyring and apply a restriction to it. The restriction is managed + * by the specific key type, but can be configured by the options specified in + * the restriction string. */ int keyring_restrict(key_ref_t keyring_ref, const char *type, const char *restriction) diff --git a/security/keys/request_key.c b/security/keys/request_key.c index 75d87f9e0f49..1f234b019437 100644 --- a/security/keys/request_key.c +++ b/security/keys/request_key.c @@ -24,7 +24,7 @@ /** * complete_request_key - Complete the construction of a key. - * @auth_key: The authorisation key. + * @authkey: The authorisation key. * @error: The success or failute of the construction. * * Complete the attempt to construct a key. The key will be negated From patchwork Thu May 30 17:25:41 2019 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: David Howells X-Patchwork-Id: 10969123 Return-Path: Received: from mail.wl.linuxfoundation.org (pdx-wl-mail.web.codeaurora.org [172.30.200.125]) by pdx-korg-patchwork-2.web.codeaurora.org (Postfix) with ESMTP id 498F2912 for ; Thu, 30 May 2019 17:25:54 +0000 (UTC) Received: from mail.wl.linuxfoundation.org (localhost [127.0.0.1]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id 3818528BF7 for ; Thu, 30 May 2019 17:25:54 +0000 (UTC) Received: by mail.wl.linuxfoundation.org (Postfix, from userid 486) id 28F8E28BF9; Thu, 30 May 2019 17:25:54 +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.9 required=2.0 tests=BAYES_00,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 C56B028BF7 for ; Thu, 30 May 2019 17:25:53 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1726818AbfE3RZp (ORCPT ); Thu, 30 May 2019 13:25:45 -0400 Received: from mx1.redhat.com ([209.132.183.28]:51058 "EHLO mx1.redhat.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1726546AbfE3RZn (ORCPT ); Thu, 30 May 2019 13:25:43 -0400 Received: from smtp.corp.redhat.com (int-mx04.intmail.prod.int.phx2.redhat.com [10.5.11.14]) (using TLSv1.2 with cipher AECDH-AES256-SHA (256/256 bits)) (No client certificate requested) by mx1.redhat.com (Postfix) with ESMTPS id 441B59FFC0; Thu, 30 May 2019 17:25:43 +0000 (UTC) Received: from warthog.procyon.org.uk (ovpn-120-173.rdu2.redhat.com [10.10.120.173]) by smtp.corp.redhat.com (Postfix) with ESMTP id 41FF75DD9E; Thu, 30 May 2019 17:25:42 +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 04/10] keys: Change keyring_serialise_link_sem to a mutex [ver #2] From: David Howells To: keyrings@vger.kernel.org Cc: dhowells@redhat.com, linux-security-module@vger.kernel.org, linux-kernel@vger.kernel.org, ebiggers@kernel.org Date: Thu, 30 May 2019 18:25:41 +0100 Message-ID: <155923714140.949.13143637354252349694.stgit@warthog.procyon.org.uk> In-Reply-To: <155923711088.949.14909672457214372214.stgit@warthog.procyon.org.uk> References: <155923711088.949.14909672457214372214.stgit@warthog.procyon.org.uk> User-Agent: StGit/unknown-version MIME-Version: 1.0 X-Scanned-By: MIMEDefang 2.79 on 10.5.11.14 X-Greylist: Sender IP whitelisted, not delayed by milter-greylist-4.5.16 (mx1.redhat.com [10.5.110.39]); Thu, 30 May 2019 17:25:43 +0000 (UTC) Sender: owner-linux-security-module@vger.kernel.org Precedence: bulk List-ID: X-Virus-Scanned: ClamAV using ClamSMTP Change keyring_serialise_link_sem to a mutex as it's only ever write-locked. Signed-off-by: David Howells --- security/keys/keyring.c | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/security/keys/keyring.c b/security/keys/keyring.c index 5b218b270598..ca6694ba1773 100644 --- a/security/keys/keyring.c +++ b/security/keys/keyring.c @@ -100,7 +100,7 @@ EXPORT_SYMBOL(key_type_keyring); * Semaphore to serialise link/link calls to prevent two link calls in parallel * introducing a cycle. */ -static DECLARE_RWSEM(keyring_serialise_link_sem); +static DEFINE_MUTEX(keyring_serialise_link_lock); /* * Publish the name of a keyring so that it can be found by name (if it has @@ -1206,7 +1206,7 @@ int __key_link_begin(struct key *keyring, const struct keyring_index_key *index_key, struct assoc_array_edit **_edit) __acquires(&keyring->sem) - __acquires(&keyring_serialise_link_sem) + __acquires(&keyring_serialise_link_lock) { struct assoc_array_edit *edit; int ret; @@ -1228,7 +1228,7 @@ int __key_link_begin(struct key *keyring, /* serialise link/link calls to prevent parallel calls causing a cycle * when linking two keyring in opposite orders */ if (index_key->type == &key_type_keyring) - down_write(&keyring_serialise_link_sem); + mutex_lock(&keyring_serialise_link_lock); /* Create an edit script that will insert/replace the key in the * keyring tree. @@ -1260,7 +1260,7 @@ int __key_link_begin(struct key *keyring, assoc_array_cancel_edit(edit); error_sem: if (index_key->type == &key_type_keyring) - up_write(&keyring_serialise_link_sem); + mutex_unlock(&keyring_serialise_link_lock); error_krsem: up_write(&keyring->sem); kleave(" = %d", ret); @@ -1307,13 +1307,13 @@ void __key_link_end(struct key *keyring, const struct keyring_index_key *index_key, struct assoc_array_edit *edit) __releases(&keyring->sem) - __releases(&keyring_serialise_link_sem) + __releases(&keyring_serialise_link_lock) { BUG_ON(index_key->type == NULL); kenter("%d,%s,", keyring->serial, index_key->type->name); if (index_key->type == &key_type_keyring) - up_write(&keyring_serialise_link_sem); + mutex_unlock(&keyring_serialise_link_lock); if (edit) { if (!edit->dead_leaf) { From patchwork Thu May 30 17:25:48 2019 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: David Howells X-Patchwork-Id: 10969125 Return-Path: Received: from mail.wl.linuxfoundation.org (pdx-wl-mail.web.codeaurora.org [172.30.200.125]) by pdx-korg-patchwork-2.web.codeaurora.org (Postfix) with ESMTP id 73196912 for ; Thu, 30 May 2019 17:25:59 +0000 (UTC) Received: from mail.wl.linuxfoundation.org (localhost [127.0.0.1]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id 622A628BF7 for ; Thu, 30 May 2019 17:25:59 +0000 (UTC) Received: by mail.wl.linuxfoundation.org (Postfix, from userid 486) id 5536528BF9; Thu, 30 May 2019 17:25:59 +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.9 required=2.0 tests=BAYES_00,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 ED41528BF7 for ; Thu, 30 May 2019 17:25:58 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1726684AbfE3RZx (ORCPT ); Thu, 30 May 2019 13:25:53 -0400 Received: from mx1.redhat.com ([209.132.183.28]:8525 "EHLO mx1.redhat.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1726902AbfE3RZu (ORCPT ); Thu, 30 May 2019 13:25:50 -0400 Received: from smtp.corp.redhat.com (int-mx06.intmail.prod.int.phx2.redhat.com [10.5.11.16]) (using TLSv1.2 with cipher AECDH-AES256-SHA (256/256 bits)) (No client certificate requested) by mx1.redhat.com (Postfix) with ESMTPS id 5A1697E421; Thu, 30 May 2019 17:25:50 +0000 (UTC) Received: from warthog.procyon.org.uk (ovpn-120-173.rdu2.redhat.com [10.10.120.173]) by smtp.corp.redhat.com (Postfix) with ESMTP id 4941A17147; Thu, 30 May 2019 17:25:49 +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/10] keys: Break bits out of key_unlink() [ver #2] From: David Howells To: keyrings@vger.kernel.org Cc: dhowells@redhat.com, linux-security-module@vger.kernel.org, linux-kernel@vger.kernel.org, ebiggers@kernel.org Date: Thu, 30 May 2019 18:25:48 +0100 Message-ID: <155923714849.949.7899104828390484410.stgit@warthog.procyon.org.uk> In-Reply-To: <155923711088.949.14909672457214372214.stgit@warthog.procyon.org.uk> References: <155923711088.949.14909672457214372214.stgit@warthog.procyon.org.uk> User-Agent: StGit/unknown-version MIME-Version: 1.0 X-Scanned-By: MIMEDefang 2.79 on 10.5.11.16 X-Greylist: Sender IP whitelisted, not delayed by milter-greylist-4.5.16 (mx1.redhat.com [10.5.110.27]); Thu, 30 May 2019 17:25:50 +0000 (UTC) Sender: owner-linux-security-module@vger.kernel.org Precedence: bulk List-ID: X-Virus-Scanned: ClamAV using ClamSMTP Break bits out of key_unlink() into helper functions so that they can be used in implementing key_move(). Signed-off-by: David Howells --- security/keys/keyring.c | 86 ++++++++++++++++++++++++++++++++++++----------- 1 file changed, 65 insertions(+), 21 deletions(-) diff --git a/security/keys/keyring.c b/security/keys/keyring.c index ca6694ba1773..2f91b9a699ef 100644 --- a/security/keys/keyring.c +++ b/security/keys/keyring.c @@ -1382,6 +1382,63 @@ int key_link(struct key *keyring, struct key *key) } EXPORT_SYMBOL(key_link); +/* + * Lock a keyring for unlink. + */ +static int __key_unlink_lock(struct key *keyring) + __acquires(&keyring->sem) +{ + if (keyring->type != &key_type_keyring) + return -ENOTDIR; + + down_write(&keyring->sem); + return 0; +} + +/* + * Begin the process of unlinking a key from a keyring. + */ +static int __key_unlink_begin(struct key *keyring, struct key *key, + struct assoc_array_edit **_edit) +{ + struct assoc_array_edit *edit; + + edit = assoc_array_delete(&keyring->keys, &keyring_assoc_array_ops, + &key->index_key); + if (IS_ERR(edit)) + return PTR_ERR(edit); + + if (!edit) + return -ENOENT; + + *_edit = edit; + return 0; +} + +/* + * Apply an unlink change. + */ +static void __key_unlink(struct key *keyring, struct key *key, + struct assoc_array_edit **_edit) +{ + assoc_array_apply_edit(*_edit); + *_edit = NULL; + key_payload_reserve(keyring, keyring->datalen - KEYQUOTA_LINK_BYTES); +} + +/* + * Finish unlinking a key from to a keyring. + */ +static void __key_unlink_end(struct key *keyring, + struct key *key, + struct assoc_array_edit *edit) + __releases(&keyring->sem) +{ + if (edit) + assoc_array_cancel_edit(edit); + up_write(&keyring->sem); +} + /** * key_unlink - Unlink the first link to a key from a keyring. * @keyring: The keyring to remove the link from. @@ -1401,33 +1458,20 @@ EXPORT_SYMBOL(key_link); */ int key_unlink(struct key *keyring, struct key *key) { - struct assoc_array_edit *edit; + struct assoc_array_edit *edit = NULL; int ret; key_check(keyring); key_check(key); - if (keyring->type != &key_type_keyring) - return -ENOTDIR; - - down_write(&keyring->sem); - - edit = assoc_array_delete(&keyring->keys, &keyring_assoc_array_ops, - &key->index_key); - if (IS_ERR(edit)) { - ret = PTR_ERR(edit); - goto error; - } - ret = -ENOENT; - if (edit == NULL) - goto error; - - assoc_array_apply_edit(edit); - key_payload_reserve(keyring, keyring->datalen - KEYQUOTA_LINK_BYTES); - ret = 0; + ret = __key_unlink_lock(keyring); + if (ret < 0) + return ret; -error: - up_write(&keyring->sem); + ret = __key_unlink_begin(keyring, key, &edit); + if (ret == 0) + __key_unlink(keyring, key, &edit); + __key_unlink_end(keyring, key, edit); return ret; } EXPORT_SYMBOL(key_unlink); From patchwork Thu May 30 17:25:55 2019 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: David Howells X-Patchwork-Id: 10969127 Return-Path: Received: from mail.wl.linuxfoundation.org (pdx-wl-mail.web.codeaurora.org [172.30.200.125]) by pdx-korg-patchwork-2.web.codeaurora.org (Postfix) with ESMTP id 28CB613AD for ; Thu, 30 May 2019 17:26:04 +0000 (UTC) Received: from mail.wl.linuxfoundation.org (localhost [127.0.0.1]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id 176FD28BF7 for ; Thu, 30 May 2019 17:26:04 +0000 (UTC) Received: by mail.wl.linuxfoundation.org (Postfix, from userid 486) id 0B43D28BF9; Thu, 30 May 2019 17:26:04 +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.9 required=2.0 tests=BAYES_00,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 C6AAB28BF7 for ; Thu, 30 May 2019 17:26:02 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1726912AbfE3RZ6 (ORCPT ); Thu, 30 May 2019 13:25:58 -0400 Received: from mx1.redhat.com ([209.132.183.28]:45612 "EHLO mx1.redhat.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1726902AbfE3RZ5 (ORCPT ); Thu, 30 May 2019 13:25:57 -0400 Received: from smtp.corp.redhat.com (int-mx05.intmail.prod.int.phx2.redhat.com [10.5.11.15]) (using TLSv1.2 with cipher AECDH-AES256-SHA (256/256 bits)) (No client certificate requested) by mx1.redhat.com (Postfix) with ESMTPS id 71E786EB8E; Thu, 30 May 2019 17:25:57 +0000 (UTC) Received: from warthog.procyon.org.uk (ovpn-120-173.rdu2.redhat.com [10.10.120.173]) by smtp.corp.redhat.com (Postfix) with ESMTP id 512247A000; Thu, 30 May 2019 17:25:56 +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 06/10] keys: Hoist locking out of __key_link_begin() [ver #2] From: David Howells To: keyrings@vger.kernel.org Cc: dhowells@redhat.com, linux-security-module@vger.kernel.org, linux-kernel@vger.kernel.org, ebiggers@kernel.org Date: Thu, 30 May 2019 18:25:55 +0100 Message-ID: <155923715560.949.7666210207871593907.stgit@warthog.procyon.org.uk> In-Reply-To: <155923711088.949.14909672457214372214.stgit@warthog.procyon.org.uk> References: <155923711088.949.14909672457214372214.stgit@warthog.procyon.org.uk> User-Agent: StGit/unknown-version MIME-Version: 1.0 X-Scanned-By: MIMEDefang 2.79 on 10.5.11.15 X-Greylist: Sender IP whitelisted, not delayed by milter-greylist-4.5.16 (mx1.redhat.com [10.5.110.25]); Thu, 30 May 2019 17:25:57 +0000 (UTC) Sender: owner-linux-security-module@vger.kernel.org Precedence: bulk List-ID: X-Virus-Scanned: ClamAV using ClamSMTP Hoist the locking of out of __key_link_begin() and into its callers. This is necessary to allow the upcoming key_move() operation to correctly order taking of the source keyring semaphore, the destination keyring semaphore and the keyring serialisation lock. Signed-off-by: David Howells --- security/keys/internal.h | 2 + security/keys/key.c | 23 +++++++++++-- security/keys/keyring.c | 77 +++++++++++++++++++++++++------------------ security/keys/request_key.c | 5 +++ 4 files changed, 71 insertions(+), 36 deletions(-) diff --git a/security/keys/internal.h b/security/keys/internal.h index 8f533c81aa8d..25cdd0cbdc06 100644 --- a/security/keys/internal.h +++ b/security/keys/internal.h @@ -93,6 +93,8 @@ extern wait_queue_head_t request_key_conswq; extern struct key_type *key_type_lookup(const char *type); extern void key_type_put(struct key_type *ktype); +extern int __key_link_lock(struct key *keyring, + const struct keyring_index_key *index_key); extern int __key_link_begin(struct key *keyring, const struct keyring_index_key *index_key, struct assoc_array_edit **_edit); diff --git a/security/keys/key.c b/security/keys/key.c index 696f1c092c50..591b88f9a51d 100644 --- a/security/keys/key.c +++ b/security/keys/key.c @@ -515,10 +515,14 @@ int key_instantiate_and_link(struct key *key, } if (keyring) { - ret = __key_link_begin(keyring, &key->index_key, &edit); + ret = __key_link_lock(keyring, &key->index_key); if (ret < 0) goto error; + ret = __key_link_begin(keyring, &key->index_key, &edit); + if (ret < 0) + goto error_link_end; + if (keyring->restrict_link && keyring->restrict_link->check) { struct key_restriction *keyres = keyring->restrict_link; @@ -570,7 +574,7 @@ int key_reject_and_link(struct key *key, struct key *keyring, struct key *authkey) { - struct assoc_array_edit *edit; + struct assoc_array_edit *edit = NULL; int ret, awaken, link_ret = 0; key_check(key); @@ -583,7 +587,12 @@ int key_reject_and_link(struct key *key, if (keyring->restrict_link) return -EPERM; - link_ret = __key_link_begin(keyring, &key->index_key, &edit); + link_ret = __key_link_lock(keyring, &key->index_key); + if (link_ret == 0) { + link_ret = __key_link_begin(keyring, &key->index_key, &edit); + if (link_ret < 0) + __key_link_end(keyring, &key->index_key, edit); + } } mutex_lock(&key_construction_mutex); @@ -860,12 +869,18 @@ key_ref_t key_create_or_update(key_ref_t keyring_ref, } index_key.desc_len = strlen(index_key.description); - ret = __key_link_begin(keyring, &index_key, &edit); + ret = __key_link_lock(keyring, &index_key); if (ret < 0) { key_ref = ERR_PTR(ret); goto error_free_prep; } + ret = __key_link_begin(keyring, &index_key, &edit); + if (ret < 0) { + key_ref = ERR_PTR(ret); + goto error_link_end; + } + if (restrict_link && restrict_link->check) { ret = restrict_link->check(keyring, index_key.type, &prep.payload, restrict_link->key); diff --git a/security/keys/keyring.c b/security/keys/keyring.c index 2f91b9a699ef..8838c300ea7b 100644 --- a/security/keys/keyring.c +++ b/security/keys/keyring.c @@ -1199,14 +1199,34 @@ static int keyring_detect_cycle(struct key *A, struct key *B) return PTR_ERR(ctx.result) == -EAGAIN ? 0 : PTR_ERR(ctx.result); } +/* + * Lock keyring for link. + */ +int __key_link_lock(struct key *keyring, + const struct keyring_index_key *index_key) + __acquires(&keyring->sem) + __acquires(&keyring_serialise_link_lock) +{ + if (keyring->type != &key_type_keyring) + return -ENOTDIR; + + down_write(&keyring->sem); + + /* Serialise link/link calls to prevent parallel calls causing a cycle + * when linking two keyring in opposite orders. + */ + if (index_key->type == &key_type_keyring) + mutex_lock(&keyring_serialise_link_lock); + + return 0; +} + /* * Preallocate memory so that a key can be linked into to a keyring. */ int __key_link_begin(struct key *keyring, const struct keyring_index_key *index_key, struct assoc_array_edit **_edit) - __acquires(&keyring->sem) - __acquires(&keyring_serialise_link_lock) { struct assoc_array_edit *edit; int ret; @@ -1216,19 +1236,9 @@ int __key_link_begin(struct key *keyring, BUG_ON(index_key->desc_len == 0); - if (keyring->type != &key_type_keyring) - return -ENOTDIR; - - down_write(&keyring->sem); - ret = -EKEYREVOKED; if (test_bit(KEY_FLAG_REVOKED, &keyring->flags)) - goto error_krsem; - - /* serialise link/link calls to prevent parallel calls causing a cycle - * when linking two keyring in opposite orders */ - if (index_key->type == &key_type_keyring) - mutex_lock(&keyring_serialise_link_lock); + goto error; /* Create an edit script that will insert/replace the key in the * keyring tree. @@ -1239,7 +1249,7 @@ int __key_link_begin(struct key *keyring, NULL); if (IS_ERR(edit)) { ret = PTR_ERR(edit); - goto error_sem; + goto error; } /* If we're not replacing a link in-place then we're going to need some @@ -1258,11 +1268,7 @@ int __key_link_begin(struct key *keyring, error_cancel: assoc_array_cancel_edit(edit); -error_sem: - if (index_key->type == &key_type_keyring) - mutex_unlock(&keyring_serialise_link_lock); -error_krsem: - up_write(&keyring->sem); +error: kleave(" = %d", ret); return ret; } @@ -1312,9 +1318,6 @@ void __key_link_end(struct key *keyring, BUG_ON(index_key->type == NULL); kenter("%d,%s,", keyring->serial, index_key->type->name); - if (index_key->type == &key_type_keyring) - mutex_unlock(&keyring_serialise_link_lock); - if (edit) { if (!edit->dead_leaf) { key_payload_reserve(keyring, @@ -1323,6 +1326,9 @@ void __key_link_end(struct key *keyring, assoc_array_cancel_edit(edit); } up_write(&keyring->sem); + + if (index_key->type == &key_type_keyring) + mutex_unlock(&keyring_serialise_link_lock); } /* @@ -1358,7 +1364,7 @@ static int __key_link_check_restriction(struct key *keyring, struct key *key) */ int key_link(struct key *keyring, struct key *key) { - struct assoc_array_edit *edit; + struct assoc_array_edit *edit = NULL; int ret; kenter("{%d,%d}", keyring->serial, refcount_read(&keyring->usage)); @@ -1366,17 +1372,24 @@ int key_link(struct key *keyring, struct key *key) key_check(keyring); key_check(key); + ret = __key_link_lock(keyring, &key->index_key); + if (ret < 0) + goto error; + ret = __key_link_begin(keyring, &key->index_key, &edit); - if (ret == 0) { - kdebug("begun {%d,%d}", keyring->serial, refcount_read(&keyring->usage)); - ret = __key_link_check_restriction(keyring, key); - if (ret == 0) - ret = __key_link_check_live_key(keyring, key); - if (ret == 0) - __key_link(key, &edit); - __key_link_end(keyring, &key->index_key, edit); - } + if (ret < 0) + goto error_end; + + kdebug("begun {%d,%d}", keyring->serial, refcount_read(&keyring->usage)); + ret = __key_link_check_restriction(keyring, key); + if (ret == 0) + ret = __key_link_check_live_key(keyring, key); + if (ret == 0) + __key_link(key, &edit); +error_end: + __key_link_end(keyring, &key->index_key, edit); +error: kleave(" = %d {%d,%d}", ret, keyring->serial, refcount_read(&keyring->usage)); return ret; } diff --git a/security/keys/request_key.c b/security/keys/request_key.c index 1f234b019437..232505d591dd 100644 --- a/security/keys/request_key.c +++ b/security/keys/request_key.c @@ -372,6 +372,9 @@ static int construct_alloc_key(struct keyring_search_context *ctx, set_bit(KEY_FLAG_USER_CONSTRUCT, &key->flags); if (dest_keyring) { + ret = __key_link_lock(dest_keyring, &ctx->index_key); + if (ret < 0) + goto link_lock_failed; ret = __key_link_begin(dest_keyring, &ctx->index_key, &edit); if (ret < 0) goto link_prealloc_failed; @@ -423,6 +426,8 @@ static int construct_alloc_key(struct keyring_search_context *ctx, return ret; link_prealloc_failed: + __key_link_end(dest_keyring, &ctx->index_key, edit); +link_lock_failed: mutex_unlock(&user->cons_lock); key_put(key); kleave(" = %d [prelink]", ret); From patchwork Thu May 30 17:26:02 2019 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: David Howells X-Patchwork-Id: 10969129 Return-Path: Received: from mail.wl.linuxfoundation.org (pdx-wl-mail.web.codeaurora.org [172.30.200.125]) by pdx-korg-patchwork-2.web.codeaurora.org (Postfix) with ESMTP id B38B713AD for ; Thu, 30 May 2019 17:26:06 +0000 (UTC) Received: from mail.wl.linuxfoundation.org (localhost [127.0.0.1]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id A31BD28BF7 for ; Thu, 30 May 2019 17:26:06 +0000 (UTC) Received: by mail.wl.linuxfoundation.org (Postfix, from userid 486) id 96E4428BF9; Thu, 30 May 2019 17:26:06 +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.9 required=2.0 tests=BAYES_00,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 BFD6328BF7 for ; Thu, 30 May 2019 17:26:05 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1726590AbfE3R0F (ORCPT ); Thu, 30 May 2019 13:26:05 -0400 Received: from mx1.redhat.com ([209.132.183.28]:59380 "EHLO mx1.redhat.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1726550AbfE3R0F (ORCPT ); Thu, 30 May 2019 13:26:05 -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 B33D630C318A; Thu, 30 May 2019 17:26:04 +0000 (UTC) Received: from warthog.procyon.org.uk (ovpn-120-173.rdu2.redhat.com [10.10.120.173]) by smtp.corp.redhat.com (Postfix) with ESMTP id 619B21001DD8; Thu, 30 May 2019 17:26:03 +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 07/10] keys: Add a keyctl to move a key between keyrings [ver #2] From: David Howells To: keyrings@vger.kernel.org Cc: dhowells@redhat.com, linux-security-module@vger.kernel.org, linux-kernel@vger.kernel.org, ebiggers@kernel.org Date: Thu, 30 May 2019 18:26:02 +0100 Message-ID: <155923716263.949.7977631596353440372.stgit@warthog.procyon.org.uk> In-Reply-To: <155923711088.949.14909672457214372214.stgit@warthog.procyon.org.uk> References: <155923711088.949.14909672457214372214.stgit@warthog.procyon.org.uk> User-Agent: StGit/unknown-version MIME-Version: 1.0 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.40]); Thu, 30 May 2019 17:26:04 +0000 (UTC) Sender: owner-linux-security-module@vger.kernel.org Precedence: bulk List-ID: X-Virus-Scanned: ClamAV using ClamSMTP Add a keyctl to atomically move a link to a key from one keyring to another. The key must exist in "from" keyring and a flag can be given to cause the operation to fail if there's a matching key already in the "to" keyring. This can be done with: keyctl(KEYCTL_MOVE, key_serial_t key, key_serial_t from_keyring, key_serial_t to_keyring, unsigned int flags); The key being moved must grant Link permission and both keyrings must grant Write permission. flags should be 0 or KEYCTL_MOVE_EXCL, with the latter preventing displacement of a matching key from the "to" keyring. Signed-off-by: David Howells --- Documentation/security/keys/core.rst | 21 +++++++ include/linux/key.h | 5 ++ include/uapi/linux/keyctl.h | 3 + security/keys/compat.c | 3 + security/keys/internal.h | 3 + security/keys/keyctl.c | 52 ++++++++++++++++ security/keys/keyring.c | 108 ++++++++++++++++++++++++++++++++++ 7 files changed, 195 insertions(+) diff --git a/Documentation/security/keys/core.rst b/Documentation/security/keys/core.rst index 9521c4207f01..823d29bf44f7 100644 --- a/Documentation/security/keys/core.rst +++ b/Documentation/security/keys/core.rst @@ -577,6 +577,27 @@ The keyctl syscall functions are: added. + * Move a key from one keyring to another:: + + long keyctl(KEYCTL_MOVE, + key_serial_t id, + key_serial_t from_ring_id, + key_serial_t to_ring_id, + unsigned int flags); + + Move the key specified by "id" from the keyring specified by + "from_ring_id" to the keyring specified by "to_ring_id". If the two + keyrings are the same, nothing is done. + + "flags" can have KEYCTL_MOVE_EXCL set in it to cause the operation to fail + with EEXIST if a matching key exists in the destination keyring, otherwise + such a key will be replaced. + + A process must have link permission on the key for this function to be + successful and write permission on both keyrings. Any errors that can + occur from KEYCTL_LINK also apply on the destination keyring here. + + * Unlink a key or keyring from another keyring:: long keyctl(KEYCTL_UNLINK, key_serial_t keyring, key_serial_t key); diff --git a/include/linux/key.h b/include/linux/key.h index 1f09aad1c98c..612e1cf84049 100644 --- a/include/linux/key.h +++ b/include/linux/key.h @@ -310,6 +310,11 @@ extern int key_update(key_ref_t key, extern int key_link(struct key *keyring, struct key *key); +extern int key_move(struct key *key, + struct key *from_keyring, + struct key *to_keyring, + unsigned int flags); + extern int key_unlink(struct key *keyring, struct key *key); diff --git a/include/uapi/linux/keyctl.h b/include/uapi/linux/keyctl.h index f45ee0f69c0c..fd9fb11b312b 100644 --- a/include/uapi/linux/keyctl.h +++ b/include/uapi/linux/keyctl.h @@ -67,6 +67,7 @@ #define KEYCTL_PKEY_SIGN 27 /* Create a public key signature */ #define KEYCTL_PKEY_VERIFY 28 /* Verify a public key signature */ #define KEYCTL_RESTRICT_KEYRING 29 /* Restrict keys allowed to link to a keyring */ +#define KEYCTL_MOVE 30 /* Move keys between keyrings */ /* keyctl structures */ struct keyctl_dh_params { @@ -112,4 +113,6 @@ struct keyctl_pkey_params { __u32 __spare[7]; }; +#define KEYCTL_MOVE_EXCL 0x00000001 /* Do not displace from the to-keyring */ + #endif /* _LINUX_KEYCTL_H */ diff --git a/security/keys/compat.c b/security/keys/compat.c index 9482df601dc3..b326bc4f84d7 100644 --- a/security/keys/compat.c +++ b/security/keys/compat.c @@ -159,6 +159,9 @@ COMPAT_SYSCALL_DEFINE5(keyctl, u32, option, return keyctl_pkey_verify(compat_ptr(arg2), compat_ptr(arg3), compat_ptr(arg4), compat_ptr(arg5)); + case KEYCTL_MOVE: + return keyctl_keyring_move(arg2, arg3, arg4, arg5); + default: return -EOPNOTSUPP; } diff --git a/security/keys/internal.h b/security/keys/internal.h index 25cdd0cbdc06..b54a58c025ae 100644 --- a/security/keys/internal.h +++ b/security/keys/internal.h @@ -95,6 +95,8 @@ extern void key_type_put(struct key_type *ktype); extern int __key_link_lock(struct key *keyring, const struct keyring_index_key *index_key); +extern int __key_move_lock(struct key *l_keyring, struct key *u_keyring, + const struct keyring_index_key *index_key); extern int __key_link_begin(struct key *keyring, const struct keyring_index_key *index_key, struct assoc_array_edit **_edit); @@ -217,6 +219,7 @@ extern long keyctl_update_key(key_serial_t, const void __user *, size_t); extern long keyctl_revoke_key(key_serial_t); extern long keyctl_keyring_clear(key_serial_t); extern long keyctl_keyring_link(key_serial_t, key_serial_t); +extern long keyctl_keyring_move(key_serial_t, key_serial_t, key_serial_t, unsigned int); extern long keyctl_keyring_unlink(key_serial_t, key_serial_t); extern long keyctl_describe_key(key_serial_t, char __user *, size_t); extern long keyctl_keyring_search(key_serial_t, const char __user *, diff --git a/security/keys/keyctl.c b/security/keys/keyctl.c index 0f947bcbad46..bbfe7d92d41c 100644 --- a/security/keys/keyctl.c +++ b/security/keys/keyctl.c @@ -572,6 +572,52 @@ long keyctl_keyring_unlink(key_serial_t id, key_serial_t ringid) return ret; } +/* + * Move a link to a key from one keyring to another, displacing any matching + * key from the destination keyring. + * + * The key must grant the caller Link permission and both keyrings must grant + * the caller Write permission. There must also be a link in the from keyring + * to the key. If both keyrings are the same, nothing is done. + * + * If successful, 0 will be returned. + */ +long keyctl_keyring_move(key_serial_t id, key_serial_t from_ringid, + key_serial_t to_ringid, unsigned int flags) +{ + key_ref_t key_ref, from_ref, to_ref; + long ret; + + if (flags & ~KEYCTL_MOVE_EXCL) + return -EINVAL; + + key_ref = lookup_user_key(id, KEY_LOOKUP_CREATE, KEY_NEED_LINK); + if (IS_ERR(key_ref)) + return PTR_ERR(key_ref); + + from_ref = lookup_user_key(from_ringid, 0, KEY_NEED_WRITE); + if (IS_ERR(from_ref)) { + ret = PTR_ERR(from_ref); + goto error2; + } + + to_ref = lookup_user_key(to_ringid, KEY_LOOKUP_CREATE, KEY_NEED_WRITE); + if (IS_ERR(to_ref)) { + ret = PTR_ERR(to_ref); + goto error3; + } + + ret = key_move(key_ref_to_ptr(key_ref), key_ref_to_ptr(from_ref), + key_ref_to_ptr(to_ref), flags); + + key_ref_put(to_ref); +error3: + key_ref_put(from_ref); +error2: + key_ref_put(key_ref); + return ret; +} + /* * Return a description of a key to userspace. * @@ -1772,6 +1818,12 @@ SYSCALL_DEFINE5(keyctl, int, option, unsigned long, arg2, unsigned long, arg3, (const void __user *)arg4, (const void __user *)arg5); + case KEYCTL_MOVE: + return keyctl_keyring_move((key_serial_t)arg2, + (key_serial_t)arg3, + (key_serial_t)arg4, + (unsigned int)arg5); + default: return -EOPNOTSUPP; } diff --git a/security/keys/keyring.c b/security/keys/keyring.c index 8838c300ea7b..dc7397998ba5 100644 --- a/security/keys/keyring.c +++ b/security/keys/keyring.c @@ -1221,6 +1221,40 @@ int __key_link_lock(struct key *keyring, return 0; } +/* + * Lock keyrings for move (link/unlink combination). + */ +int __key_move_lock(struct key *l_keyring, struct key *u_keyring, + const struct keyring_index_key *index_key) + __acquires(&l_keyring->sem) + __acquires(&u_keyring->sem) + __acquires(&keyring_serialise_link_lock) +{ + if (l_keyring->type != &key_type_keyring || + u_keyring->type != &key_type_keyring) + return -ENOTDIR; + + /* We have to be very careful here to take the keyring locks in the + * right order, lest we open ourselves to deadlocking against another + * move operation. + */ + if (l_keyring < u_keyring) { + down_write(&l_keyring->sem); + down_write_nested(&u_keyring->sem, 1); + } else { + down_write(&u_keyring->sem); + down_write_nested(&l_keyring->sem, 1); + } + + /* Serialise link/link calls to prevent parallel calls causing a cycle + * when linking two keyring in opposite orders. + */ + if (index_key->type == &key_type_keyring) + mutex_lock(&keyring_serialise_link_lock); + + return 0; +} + /* * Preallocate memory so that a key can be linked into to a keyring. */ @@ -1489,6 +1523,80 @@ int key_unlink(struct key *keyring, struct key *key) } EXPORT_SYMBOL(key_unlink); +/** + * key_move - Move a key from one keyring to another + * @key: The key to move + * @from_keyring: The keyring to remove the link from. + * @to_keyring: The keyring to make the link in. + * @flags: Qualifying flags, such as KEYCTL_MOVE_EXCL. + * + * Make a link in @to_keyring to a key, such that the keyring holds a reference + * on that key and the key can potentially be found by searching that keyring + * whilst simultaneously removing a link to the key from @from_keyring. + * + * This function will write-lock both keyring's semaphores and will consume + * some of the user's key data quota to hold the link on @to_keyring. + * + * Returns 0 if successful, -ENOTDIR if either keyring isn't a keyring, + * -EKEYREVOKED if either keyring has been revoked, -ENFILE if the second + * keyring is full, -EDQUOT if there is insufficient key data quota remaining + * to add another link or -ENOMEM if there's insufficient memory. If + * KEYCTL_MOVE_EXCL is set, then -EEXIST will be returned if there's already a + * matching key in @to_keyring. + * + * It is assumed that the caller has checked that it is permitted for a link to + * be made (the keyring should have Write permission and the key Link + * permission). + */ +int key_move(struct key *key, + struct key *from_keyring, + struct key *to_keyring, + unsigned int flags) +{ + struct assoc_array_edit *from_edit = NULL, *to_edit = NULL; + int ret; + + kenter("%d,%d,%d", key->serial, from_keyring->serial, to_keyring->serial); + + if (from_keyring == to_keyring) + return 0; + + key_check(key); + key_check(from_keyring); + key_check(to_keyring); + + ret = __key_move_lock(from_keyring, to_keyring, &key->index_key); + if (ret < 0) + goto out; + ret = __key_unlink_begin(from_keyring, key, &from_edit); + if (ret < 0) + goto error; + ret = __key_link_begin(to_keyring, &key->index_key, &to_edit); + if (ret < 0) + goto error; + + ret = -EEXIST; + if (to_edit->dead_leaf && (flags & KEYCTL_MOVE_EXCL)) + goto error; + + ret = __key_link_check_restriction(to_keyring, key); + if (ret < 0) + goto error; + ret = __key_link_check_live_key(to_keyring, key); + if (ret < 0) + goto error; + + __key_unlink(from_keyring, key, &from_edit); + __key_link(key, &to_edit); +error: + __key_link_end(to_keyring, &key->index_key, to_edit); + __key_unlink_end(from_keyring, key, from_edit); +out: + kleave(" = %d", ret); + return ret; +} +EXPORT_SYMBOL(key_move); + /** * keyring_clear - Clear a keyring * @keyring: The keyring to clear. From patchwork Thu May 30 17:26:09 2019 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: David Howells X-Patchwork-Id: 10969131 Return-Path: Received: from mail.wl.linuxfoundation.org (pdx-wl-mail.web.codeaurora.org [172.30.200.125]) by pdx-korg-patchwork-2.web.codeaurora.org (Postfix) with ESMTP id C5BA5912 for ; Thu, 30 May 2019 17:26:13 +0000 (UTC) Received: from mail.wl.linuxfoundation.org (localhost [127.0.0.1]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id B5E5928BF7 for ; Thu, 30 May 2019 17:26:13 +0000 (UTC) Received: by mail.wl.linuxfoundation.org (Postfix, from userid 486) id A9F2028BF9; Thu, 30 May 2019 17:26:13 +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.9 required=2.0 tests=BAYES_00,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 60A0E28BF7 for ; Thu, 30 May 2019 17:26:13 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1726965AbfE3R0M (ORCPT ); Thu, 30 May 2019 13:26:12 -0400 Received: from mx1.redhat.com ([209.132.183.28]:43504 "EHLO mx1.redhat.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1726550AbfE3R0M (ORCPT ); Thu, 30 May 2019 13:26:12 -0400 Received: from smtp.corp.redhat.com (int-mx02.intmail.prod.int.phx2.redhat.com [10.5.11.12]) (using TLSv1.2 with cipher AECDH-AES256-SHA (256/256 bits)) (No client certificate requested) by mx1.redhat.com (Postfix) with ESMTPS id D973030C543E; Thu, 30 May 2019 17:26:11 +0000 (UTC) Received: from warthog.procyon.org.uk (ovpn-120-173.rdu2.redhat.com [10.10.120.173]) by smtp.corp.redhat.com (Postfix) with ESMTP id AFB5C60C43; Thu, 30 May 2019 17:26:10 +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 08/10] keys: Grant Link permission to possessers of request_key auth keys [ver #2] From: David Howells To: keyrings@vger.kernel.org Cc: James Morris , dhowells@redhat.com, linux-security-module@vger.kernel.org, linux-kernel@vger.kernel.org, ebiggers@kernel.org Date: Thu, 30 May 2019 18:26:09 +0100 Message-ID: <155923716995.949.7037346392947998625.stgit@warthog.procyon.org.uk> In-Reply-To: <155923711088.949.14909672457214372214.stgit@warthog.procyon.org.uk> References: <155923711088.949.14909672457214372214.stgit@warthog.procyon.org.uk> User-Agent: StGit/unknown-version MIME-Version: 1.0 X-Scanned-By: MIMEDefang 2.79 on 10.5.11.12 X-Greylist: Sender IP whitelisted, not delayed by milter-greylist-4.5.16 (mx1.redhat.com [10.5.110.46]); Thu, 30 May 2019 17:26:11 +0000 (UTC) Sender: owner-linux-security-module@vger.kernel.org Precedence: bulk List-ID: X-Virus-Scanned: ClamAV using ClamSMTP Grant Link permission to the possessers of request_key authentication keys, thereby allowing a daemon that is servicing upcalls to arrange things such that only the necessary auth key is passed to the actual service program and not all the daemon's pending auth keys. Signed-off-by: David Howells Reviewed-by: James Morris --- security/keys/request_key_auth.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/security/keys/request_key_auth.c b/security/keys/request_key_auth.c index 572c7a60473a..ec5226557023 100644 --- a/security/keys/request_key_auth.c +++ b/security/keys/request_key_auth.c @@ -204,7 +204,7 @@ struct key *request_key_auth_new(struct key *target, const char *op, authkey = key_alloc(&key_type_request_key_auth, desc, cred->fsuid, cred->fsgid, cred, - KEY_POS_VIEW | KEY_POS_READ | KEY_POS_SEARCH | + KEY_POS_VIEW | KEY_POS_READ | KEY_POS_SEARCH | KEY_POS_LINK | KEY_USR_VIEW, KEY_ALLOC_NOT_IN_QUOTA, NULL); if (IS_ERR(authkey)) { ret = PTR_ERR(authkey); From patchwork Thu May 30 17:26:17 2019 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: David Howells X-Patchwork-Id: 10969133 Return-Path: Received: from mail.wl.linuxfoundation.org (pdx-wl-mail.web.codeaurora.org [172.30.200.125]) by pdx-korg-patchwork-2.web.codeaurora.org (Postfix) with ESMTP id F224C13AD for ; Thu, 30 May 2019 17:26:21 +0000 (UTC) Received: from mail.wl.linuxfoundation.org (localhost [127.0.0.1]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id DF94928BF8 for ; Thu, 30 May 2019 17:26:21 +0000 (UTC) Received: by mail.wl.linuxfoundation.org (Postfix, from userid 486) id D04CC28BF7; Thu, 30 May 2019 17:26:21 +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.9 required=2.0 tests=BAYES_00,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 7EE6428BF7 for ; Thu, 30 May 2019 17:26:21 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1726757AbfE3R0U (ORCPT ); Thu, 30 May 2019 13:26:20 -0400 Received: from mx1.redhat.com ([209.132.183.28]:51680 "EHLO mx1.redhat.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1726538AbfE3R0U (ORCPT ); Thu, 30 May 2019 13:26:20 -0400 Received: from smtp.corp.redhat.com (int-mx08.intmail.prod.int.phx2.redhat.com [10.5.11.23]) (using TLSv1.2 with cipher AECDH-AES256-SHA (256/256 bits)) (No client certificate requested) by mx1.redhat.com (Postfix) with ESMTPS id 3A9699FFD4; Thu, 30 May 2019 17:26:20 +0000 (UTC) Received: from warthog.procyon.org.uk (ovpn-120-173.rdu2.redhat.com [10.10.120.173]) by smtp.corp.redhat.com (Postfix) with ESMTP id DD87D38E20; Thu, 30 May 2019 17:26:17 +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 09/10] KEYS: reuse keyring_index_key::desc_len in lookup_user_key() [ver #2] From: David Howells To: keyrings@vger.kernel.org Cc: Eric Biggers , James Morris , dhowells@redhat.com, linux-security-module@vger.kernel.org, linux-kernel@vger.kernel.org, ebiggers@kernel.org Date: Thu, 30 May 2019 18:26:17 +0100 Message-ID: <155923717710.949.2790063022835028361.stgit@warthog.procyon.org.uk> In-Reply-To: <155923711088.949.14909672457214372214.stgit@warthog.procyon.org.uk> References: <155923711088.949.14909672457214372214.stgit@warthog.procyon.org.uk> User-Agent: StGit/unknown-version MIME-Version: 1.0 X-Scanned-By: MIMEDefang 2.84 on 10.5.11.23 X-Greylist: Sender IP whitelisted, not delayed by milter-greylist-4.5.16 (mx1.redhat.com [10.5.110.39]); Thu, 30 May 2019 17:26:20 +0000 (UTC) Sender: owner-linux-security-module@vger.kernel.org Precedence: bulk List-ID: X-Virus-Scanned: ClamAV using ClamSMTP From: Eric Biggers When lookup_user_key() checks whether the key is possessed, it should use the key's existing index_key including the 'desc_len' field, rather than recomputing the 'desc_len'. This doesn't change the behavior; this way is just simpler and faster. Signed-off-by: Eric Biggers Signed-off-by: David Howells Reviewed-by: James Morris --- security/keys/process_keys.c | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/security/keys/process_keys.c b/security/keys/process_keys.c index ba5d3172cafe..39aaa21462bf 100644 --- a/security/keys/process_keys.c +++ b/security/keys/process_keys.c @@ -688,9 +688,7 @@ key_ref_t lookup_user_key(key_serial_t id, unsigned long lflags, key_ref = make_key_ref(key, 0); /* check to see if we possess the key */ - ctx.index_key.type = key->type; - ctx.index_key.description = key->description; - ctx.index_key.desc_len = strlen(key->description); + ctx.index_key = key->index_key; ctx.match_data.raw_data = key; kdebug("check possessed"); skey_ref = search_process_keyrings(&ctx); From patchwork Thu May 30 17:26:25 2019 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: David Howells X-Patchwork-Id: 10969135 Return-Path: Received: from mail.wl.linuxfoundation.org (pdx-wl-mail.web.codeaurora.org [172.30.200.125]) by pdx-korg-patchwork-2.web.codeaurora.org (Postfix) with ESMTP id 72D0313AD for ; Thu, 30 May 2019 17:26:29 +0000 (UTC) Received: from mail.wl.linuxfoundation.org (localhost [127.0.0.1]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id 612F428BF7 for ; Thu, 30 May 2019 17:26:29 +0000 (UTC) Received: by mail.wl.linuxfoundation.org (Postfix, from userid 486) id 54EFE28BF9; Thu, 30 May 2019 17:26:29 +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.9 required=2.0 tests=BAYES_00,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 CE77A28BF7 for ; Thu, 30 May 2019 17:26:28 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1727003AbfE3R02 (ORCPT ); Thu, 30 May 2019 13:26:28 -0400 Received: from mx1.redhat.com ([209.132.183.28]:60360 "EHLO mx1.redhat.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1726538AbfE3R02 (ORCPT ); Thu, 30 May 2019 13:26:28 -0400 Received: from smtp.corp.redhat.com (int-mx05.intmail.prod.int.phx2.redhat.com [10.5.11.15]) (using TLSv1.2 with cipher AECDH-AES256-SHA (256/256 bits)) (No client certificate requested) by mx1.redhat.com (Postfix) with ESMTPS id 7FBB7305D799; Thu, 30 May 2019 17:26:27 +0000 (UTC) Received: from warthog.procyon.org.uk (ovpn-120-173.rdu2.redhat.com [10.10.120.173]) by smtp.corp.redhat.com (Postfix) with ESMTP id 452387E304; Thu, 30 May 2019 17:26:26 +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 10/10] keys: Add capability-checking keyctl function [ver #2] From: David Howells To: keyrings@vger.kernel.org Cc: dhowells@redhat.com, linux-security-module@vger.kernel.org, linux-kernel@vger.kernel.org, ebiggers@kernel.org Date: Thu, 30 May 2019 18:26:25 +0100 Message-ID: <155923718546.949.13039266815245271686.stgit@warthog.procyon.org.uk> In-Reply-To: <155923711088.949.14909672457214372214.stgit@warthog.procyon.org.uk> References: <155923711088.949.14909672457214372214.stgit@warthog.procyon.org.uk> User-Agent: StGit/unknown-version MIME-Version: 1.0 X-Scanned-By: MIMEDefang 2.79 on 10.5.11.15 X-Greylist: Sender IP whitelisted, not delayed by milter-greylist-4.5.16 (mx1.redhat.com [10.5.110.44]); Thu, 30 May 2019 17:26:27 +0000 (UTC) Sender: owner-linux-security-module@vger.kernel.org Precedence: bulk List-ID: X-Virus-Scanned: ClamAV using ClamSMTP Add a keyctl function that requests a set of capability bits to find out what features are supported. Signed-off-by: David Howells --- include/uapi/linux/keyctl.h | 14 ++++++++++++++ security/keys/compat.c | 3 +++ security/keys/internal.h | 2 ++ security/keys/keyctl.c | 37 +++++++++++++++++++++++++++++++++++++ 4 files changed, 56 insertions(+) diff --git a/include/uapi/linux/keyctl.h b/include/uapi/linux/keyctl.h index fd9fb11b312b..aa4972163442 100644 --- a/include/uapi/linux/keyctl.h +++ b/include/uapi/linux/keyctl.h @@ -68,6 +68,7 @@ #define KEYCTL_PKEY_VERIFY 28 /* Verify a public key signature */ #define KEYCTL_RESTRICT_KEYRING 29 /* Restrict keys allowed to link to a keyring */ #define KEYCTL_MOVE 30 /* Move keys between keyrings */ +#define KEYCTL_CAPABILITIES 31 /* Find capabilities of keyrings subsystem */ /* keyctl structures */ struct keyctl_dh_params { @@ -115,4 +116,17 @@ struct keyctl_pkey_params { #define KEYCTL_MOVE_EXCL 0x00000001 /* Do not displace from the to-keyring */ +/* + * Capabilities flags. The capabilities list is an array of 32-bit integers; + * each integer can carry up to 32 flags. + */ +#define KEYCTL_CAPS0_CAPABILITIES 0x00000001 /* KEYCTL_CAPABILITIES supported */ +#define KEYCTL_CAPS0_PERSISTENT_KEYRINGS 0x00000002 /* Persistent keyrings enabled */ +#define KEYCTL_CAPS0_DIFFIE_HELLMAN 0x00000004 /* Diffie-Hellman computation enabled */ +#define KEYCTL_CAPS0_PUBLIC_KEY 0x00000008 /* Public key ops enabled */ +#define KEYCTL_CAPS0_BIG_KEY 0x00000010 /* big_key-type enabled */ +#define KEYCTL_CAPS0_INVALIDATE 0x00000020 /* KEYCTL_INVALIDATE supported */ +#define KEYCTL_CAPS0_RESTRICT_KEYRING 0x00000040 /* KEYCTL_RESTRICT_KEYRING supported */ +#define KEYCTL_CAPS0_MOVE 0x00000080 /* KEYCTL_MOVE supported */ + #endif /* _LINUX_KEYCTL_H */ diff --git a/security/keys/compat.c b/security/keys/compat.c index b326bc4f84d7..a53e30da20c5 100644 --- a/security/keys/compat.c +++ b/security/keys/compat.c @@ -162,6 +162,9 @@ COMPAT_SYSCALL_DEFINE5(keyctl, u32, option, case KEYCTL_MOVE: return keyctl_keyring_move(arg2, arg3, arg4, arg5); + case KEYCTL_CAPABILITIES: + return keyctl_capabilities(compat_ptr(arg2), arg3); + default: return -EOPNOTSUPP; } diff --git a/security/keys/internal.h b/security/keys/internal.h index b54a58c025ae..884fd796f668 100644 --- a/security/keys/internal.h +++ b/security/keys/internal.h @@ -329,6 +329,8 @@ static inline long keyctl_pkey_e_d_s(int op, } #endif +extern long keyctl_capabilities(unsigned int __user *_buffer, size_t buflen); + /* * Debugging key validation */ diff --git a/security/keys/keyctl.c b/security/keys/keyctl.c index bbfe7d92d41c..b3db363e0b25 100644 --- a/security/keys/keyctl.c +++ b/security/keys/keyctl.c @@ -30,6 +30,18 @@ #define KEY_MAX_DESC_SIZE 4096 +static const u32 keyrings_capabilities[1] = { + [0] = (KEYCTL_CAPS0_CAPABILITIES | + (IS_ENABLED(CONFIG_PERSISTENT_KEYRINGS) ? KEYCTL_CAPS0_PERSISTENT_KEYRINGS : 0) | + (IS_ENABLED(CONFIG_KEY_DH_OPERATIONS) ? KEYCTL_CAPS0_DIFFIE_HELLMAN : 0) | + (IS_ENABLED(CONFIG_ASYMMETRIC_KEY_TYPE) ? KEYCTL_CAPS0_PUBLIC_KEY : 0) | + (IS_ENABLED(CONFIG_BIG_KEYS) ? KEYCTL_CAPS0_BIG_KEY : 0) | + KEYCTL_CAPS0_INVALIDATE | + KEYCTL_CAPS0_RESTRICT_KEYRING | + KEYCTL_CAPS0_MOVE + ), +}; + static int key_get_type_from_user(char *type, const char __user *_type, unsigned len) @@ -1678,6 +1690,28 @@ long keyctl_restrict_keyring(key_serial_t id, const char __user *_type, return ret; } +/* + * Get keyrings subsystem capabilities. + */ +long keyctl_capabilities(unsigned int __user *_buffer, size_t buflen) +{ + size_t size = buflen; + + if (size == 0) + return sizeof(keyrings_capabilities); + if (size & 3) + return -EINVAL; + if (size > sizeof(keyrings_capabilities)) + size = sizeof(keyrings_capabilities); + if (copy_to_user(_buffer, keyrings_capabilities, size) != 0) + return -EFAULT; + if (size < buflen && + clear_user(_buffer + size, buflen - size) != 0) + return -EFAULT; + + return sizeof(keyrings_capabilities); +} + /* * The key control system call */ @@ -1824,6 +1858,9 @@ SYSCALL_DEFINE5(keyctl, int, option, unsigned long, arg2, unsigned long, arg3, (key_serial_t)arg4, (unsigned int)arg5); + case KEYCTL_CAPABILITIES: + return keyctl_capabilities((unsigned int __user *)arg2, (size_t)arg3); + default: return -EOPNOTSUPP; }