Received: by 10.223.176.46 with SMTP id f43csp19323wra; Thu, 25 Jan 2018 16:39:48 -0800 (PST) X-Google-Smtp-Source: AH8x226jXc+feImcrf0zI4NDtzmKuwy1QpacnOhWhEAB/W3wP9ORVqoUB+kkmk+3/Abyl454aTv9 X-Received: by 10.98.130.142 with SMTP id w136mr15273140pfd.236.1516927188139; Thu, 25 Jan 2018 16:39:48 -0800 (PST) ARC-Seal: i=1; a=rsa-sha256; t=1516927188; cv=none; d=google.com; s=arc-20160816; b=P0oTQqhtl0vmFgGJ8fK3pEUAbkz5UlqHyS/8HTYbHxW4Jaz/MBJYQysG9mnaFRyoHn 5l8uJwBBP2QjNSFv8OHJrAKjqr0VbOuJVU+H2awMM35D2oHoXDCT00m5dMJPpUX0eTDj e0S4i74LZ0N+tkK+CndK5i32rrId84xogbN58R0V73Y3AUzYMS9A8k9CuWjs7cLCkJJ/ 6oMFLsusVagMv9rQOvqqscWmTioFZaj+XffO9HU/AfJnFyqGYaqVtdtgATOQU9Ldo4bR Y2aBmPvRAU0Xg75cYgGd+J6Fj+vNNKJkTgeEZac6zXupYI53JTvAmszGk+4LVVUg+DPS sX8g== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20160816; h=list-id:precedence:sender:user-agent:in-reply-to :content-transfer-encoding:content-disposition:mime-version :references:message-id:subject:cc:to:from:date:dkim-signature :arc-authentication-results; bh=Cq1QSGE5+BTxBUWn6r2o1HLH54lFP/o3jdMIeu9+XN8=; b=KCzwsE6Dhi2FUQtxuQ4WfDd0sUHzW9aCIbXxiIdFfXgOwZcYmmt1iTI662Ekzer/fD QeuKZTJTgZ/Sfkz1QjJAezxtHSkX/uO7l12dfiA0MJA9bdBLRS/q+5UU2QJ7i+vw2PSr Wcv/8vVbgEktQ9fSUn4RHhqMjdK5cDg09k8Nb2HuHWfPYhEcJVdFGocYmiYmzcLzf03T XodUevMpvOx7HD/8cDVtjDC8M420xvVeuKTj8/UhTkocLT1DwPTHQ3C+447RRawEt4u9 bdMBBReP3ZJwcuxbg6O2P5jwp0+ELhTJK/rvAFpWBPJU6mvMXvaUKzyJIy2AmoS2Foo1 CJXA== ARC-Authentication-Results: i=1; mx.google.com; dkim=pass header.i=@gmail.com header.s=20161025 header.b=OC5BNJCm; 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=pass (p=NONE sp=NONE dis=NONE) header.from=gmail.com Return-Path: Received: from vger.kernel.org (vger.kernel.org. [209.132.180.67]) by mx.google.com with ESMTP id z22-v6si2207077pll.703.2018.01.25.16.39.33; Thu, 25 Jan 2018 16:39:48 -0800 (PST) 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; dkim=pass header.i=@gmail.com header.s=20161025 header.b=OC5BNJCm; 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=pass (p=NONE sp=NONE dis=NONE) header.from=gmail.com Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1751898AbeAZAh4 (ORCPT + 99 others); Thu, 25 Jan 2018 19:37:56 -0500 Received: from mail-it0-f67.google.com ([209.85.214.67]:42761 "EHLO mail-it0-f67.google.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1751375AbeAZAhw (ORCPT ); Thu, 25 Jan 2018 19:37:52 -0500 Received: by mail-it0-f67.google.com with SMTP id p139so154376itb.1; Thu, 25 Jan 2018 16:37:52 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20161025; h=date:from:to:cc:subject:message-id:references:mime-version :content-disposition:content-transfer-encoding:in-reply-to :user-agent; bh=Cq1QSGE5+BTxBUWn6r2o1HLH54lFP/o3jdMIeu9+XN8=; b=OC5BNJCmeGl/v+f2DUa3wCnAlnKo/008UVRuxeTkpbcN+H1TAuo6xCR47EQsfdNilh +5YPLi04YQHcnQTJ6x7A9eAwSXSrBO/SJQO/z985+46sOyvSfBGvd9++noeAp+I2FA/y D9hluLPFIvVYWa2wlFYcfYVjru2IKlOaZI+se1AKIJuWsnHR3YIVpLeQRLlexaPOCyhL F1SMEmW68FVVKPhpxMRQdwXa68g2zI7Q3io3YsA5RFB078CdwbFdaQ4xEQf3tJDoWMXR DUkwMhc0oqE/TYTq7MeLWNuFI0iDcU3JMVcS2bXvj+x5SMKGf4pnLZqsTzVN8ia2OyDr h1Fg== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:date:from:to:cc:subject:message-id:references :mime-version:content-disposition:content-transfer-encoding :in-reply-to:user-agent; bh=Cq1QSGE5+BTxBUWn6r2o1HLH54lFP/o3jdMIeu9+XN8=; b=ZXgnBq9YwMGCLu53aGFm1gGvNPkyqs8x+NHpSvjTUxcNNMegdIIQOD2q/Pib21TYjl BrOt3DUakJdSrotLNFuLxk4voHE3+qKvjfhF+U4cE92Y6WFn5pmp3JblapcopI8OEgnB qIA93LXTPYkk+o55mgPrEkXe4NvqVAZOAaOZXcc1nXNyCElI9JqOa5oFeuDqCgNl49To rn/VPWLcov0agKn9ZqpeD4Mn4Isf13vIWdqd8QcK4K4hQPrN4uiWS01KM2xYybtPJKYA Sk/5eRX3qxQ4xmUxnzyCUe6TNpPrllSSRnkT8tt5kaa7VTgiblZfYDAOeqqJHZ0EQjKv rVTQ== X-Gm-Message-State: AKwxytd5S0K4p7dzsj7H7cWBg2WVLl63CL8mmgsuVxCsA3R9WD4JhsZX GkEFXCPYNUXkjm7APi/Xj6+3ISHH X-Received: by 10.36.86.20 with SMTP id o20mr15081277itb.53.1516927071682; Thu, 25 Jan 2018 16:37:51 -0800 (PST) Received: from gmail.com ([2620:15c:17:3:dc28:5c82:b905:e8a8]) by smtp.gmail.com with ESMTPSA id s70sm3071675itb.0.2018.01.25.16.37.50 (version=TLS1_2 cipher=ECDHE-RSA-CHACHA20-POLY1305 bits=256/256); Thu, 25 Jan 2018 16:37:51 -0800 (PST) Date: Thu, 25 Jan 2018 16:37:48 -0800 From: Eric Biggers To: =?iso-8859-1?Q?Andr=E9?= Draszik Cc: linux-kernel@vger.kernel.org, Mimi Zohar , David Howells , James Morris , "Serge E. Hallyn" , "Theodore Y. Ts'o" , Jaegeuk Kim , Kees Cook , Eric Biggers , linux-integrity@vger.kernel.org, keyrings@vger.kernel.org, linux-security-module@vger.kernel.org, linux-fscrypt@vger.kernel.org Subject: Re: [PATCH v3] fscrypt: add support for the encrypted key type Message-ID: <20180126003748.f2uhgwhulcltyok6@gmail.com> References: <20180118131359.8365-1-git@andred.net> MIME-Version: 1.0 Content-Type: text/plain; charset=iso-8859-1 Content-Disposition: inline Content-Transfer-Encoding: 8bit In-Reply-To: <20180118131359.8365-1-git@andred.net> User-Agent: NeoMutt/20170609 (1.8.3) Sender: linux-kernel-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-kernel@vger.kernel.org On Thu, Jan 18, 2018 at 01:13:59PM +0000, Andr? Draszik wrote: > -static int validate_user_key(struct fscrypt_info *crypt_info, > +static inline struct key *fscrypt_get_encrypted_key(const char *description) > +{ > + if (IS_ENABLED(CONFIG_ENCRYPTED_KEYS)) > + return request_key(&key_type_encrypted, description, NULL); > + return ERR_PTR(-ENOKEY); > +} > + > +static int validate_keyring_key(struct fscrypt_info *crypt_info, > struct fscrypt_context *ctx, u8 *raw_key, > const char *prefix, int min_keysize) > { > char *description; > struct key *keyring_key; > - struct fscrypt_key *master_key; > - const struct user_key_payload *ukp; > + const u8 *master_key; > + u32 master_key_len; > int res; > > description = kasprintf(GFP_NOFS, "%s%*phN", prefix, > @@ -83,39 +93,55 @@ static int validate_user_key(struct fscrypt_info *crypt_info, > return -ENOMEM; > > keyring_key = request_key(&key_type_logon, description, NULL); > + if (keyring_key == ERR_PTR(-ENOKEY)) > + keyring_key = fscrypt_get_encrypted_key(description); > kfree(description); > if (IS_ERR(keyring_key)) > return PTR_ERR(keyring_key); > down_read(&keyring_key->sem); > > - if (keyring_key->type != &key_type_logon) { > + if (keyring_key->type == &key_type_logon) { > + const struct user_key_payload *ukp; > + const struct fscrypt_key *fk; > + > + ukp = user_key_payload_locked(keyring_key); > + if (!ukp) { > + /* key was revoked before we acquired its semaphore */ > + res = -EKEYREVOKED; > + goto out; > + } > + if (ukp->datalen != sizeof(struct fscrypt_key)) { > + res = -EINVAL; > + goto out; > + } > + fk = (struct fscrypt_key *)ukp->data; > + master_key = fk->raw; > + master_key_len = fk->size; > + } else if (keyring_key->type == &key_type_encrypted) { > + const struct encrypted_key_payload *ekp; > + > + ekp = keyring_key->payload.data[0]; > + master_key = ekp->decrypted_data; > + master_key_len = ekp->decrypted_datalen; > + } else { > printk_once(KERN_WARNING > - "%s: key type must be logon\n", __func__); > + "%s: key type must be logon or encrypted\n", > + __func__); > res = -ENOKEY; > goto out; > } > - ukp = user_key_payload_locked(keyring_key); > - if (!ukp) { > - /* key was revoked before we acquired its semaphore */ > - res = -EKEYREVOKED; > - goto out; > - } > - if (ukp->datalen != sizeof(struct fscrypt_key)) { > - res = -EINVAL; > - goto out; > - } > - master_key = (struct fscrypt_key *)ukp->data; > BUILD_BUG_ON(FS_AES_128_ECB_KEY_SIZE != FS_KEY_DERIVATION_NONCE_SIZE); > > - if (master_key->size < min_keysize || master_key->size > FS_MAX_KEY_SIZE > - || master_key->size % AES_BLOCK_SIZE != 0) { > + if (master_key_len < min_keysize || master_key_len > FS_MAX_KEY_SIZE > + || master_key_len % AES_BLOCK_SIZE != 0) { > printk_once(KERN_WARNING > - "%s: key size incorrect: %d\n", > - __func__, master_key->size); > + "%s: key size incorrect: %u\n", > + __func__, master_key_len); > res = -ENOKEY; > goto out; > } > - res = derive_key_aes(ctx->nonce, master_key, raw_key); > + res = derive_key_aes(ctx->nonce, master_key, master_key_len, raw_key); > + > out: > up_read(&keyring_key->sem); > key_put(keyring_key); > @@ -302,12 +328,12 @@ int fscrypt_get_encryption_info(struct inode *inode) > if (!raw_key) > goto out; > > - res = validate_user_key(crypt_info, &ctx, raw_key, FS_KEY_DESC_PREFIX, > - keysize); > + res = validate_keyring_key(crypt_info, &ctx, raw_key, > + FS_KEY_DESC_PREFIX, keysize); > if (res && inode->i_sb->s_cop->key_prefix) { > - int res2 = validate_user_key(crypt_info, &ctx, raw_key, > - inode->i_sb->s_cop->key_prefix, > - keysize); > + int res2 = validate_keyring_key(crypt_info, &ctx, raw_key, > + inode->i_sb->s_cop->key_prefix, > + keysize); > if (res2) { > if (res2 == -ENOKEY) > res = -ENOKEY; > -- > 2.15.1 > > -- > To unsubscribe from this list: send the line "unsubscribe keyrings" in > the body of a message to majordomo@vger.kernel.org > More majordomo info at http://vger.kernel.org/majordomo-info.html The code changes here look fine, but unfortunately there is a lock ordering problem exposed by using a key type that implements the key_type ->read() method. The problem is that encrypted_read() can take a page fault during copy_to_user() while holding the key semaphore, which then (with ext4) can trigger the start of a jbd2 transaction. Meanwhile fscrypt_get_encryption_info() can be called from within a jbd2 transaction via fscrypt_inherit_context(), which results in a different locking order. We probably will need to fix this by removing the call to fscrypt_get_encryption_info() from fscrypt_inherit_context(). I've pasted the lockdep report I got below: [ 432.705339] [ 432.705681] ====================================================== [ 432.707015] WARNING: possible circular locking dependency detected [ 432.708155] 4.15.0-rc8-next-20180119-00019-gab7ec46b6936 #31 Not tainted [ 432.709365] ------------------------------------------------------ [ 432.710482] keyctl/877 is trying to acquire lock: [ 432.711286] (&mm->mmap_sem){++++}, at: [<00000000e8bba1c7>] __might_fault+0xce/0x1a0 [ 432.712688] [ 432.712688] but task is already holding lock: [ 432.713684] (&type->lock_class#2){++++}, at: [<000000008ccfa156>] keyctl_read_key+0x174/0x240 [ 432.715176] [ 432.715176] which lock already depends on the new lock. [ 432.715176] [ 432.716601] [ 432.716601] the existing dependency chain (in reverse order) is: [ 432.717901] [ 432.717901] -> #3 (&type->lock_class#2){++++}: [ 432.718924] lock_acquire+0xaa/0x170 [ 432.719632] down_read+0x37/0xa0 [ 432.720298] validate_keyring_key.isra.1+0x97/0x410 [ 432.721218] fscrypt_get_encryption_info+0x724/0x1200 [ 432.722233] fscrypt_inherit_context+0x2c1/0x330 [ 432.723067] __ext4_new_inode+0x34f5/0x44d0 [ 432.723830] ext4_create+0x195/0x4a0 [ 432.724499] lookup_open+0xbe2/0x1400 [ 432.725185] path_openat+0xb31/0x1e50 [ 432.725876] do_filp_open+0x175/0x250 [ 432.726572] do_sys_open+0x219/0x3f0 [ 432.727312] entry_SYSCALL_64_fastpath+0x1e/0x8b [ 432.728153] [ 432.728153] -> #2 (jbd2_handle){.+.+}: [ 432.729008] lock_acquire+0xaa/0x170 [ 432.729680] start_this_handle+0x47b/0x1020 [ 432.730463] jbd2__journal_start+0x32e/0x5c0 [ 432.731276] __ext4_journal_start_sb+0xa8/0x190 [ 432.732183] ext4_truncate+0x4dd/0xd00 [ 432.732868] ext4_setattr+0xa62/0x1ac0 [ 432.733528] notify_change+0x672/0xdb0 [ 432.734198] do_truncate+0x111/0x1c0 [ 432.734831] path_openat+0xee6/0x1e50 [ 432.735476] do_filp_open+0x175/0x250 [ 432.736149] do_sys_open+0x219/0x3f0 [ 432.736785] entry_SYSCALL_64_fastpath+0x1e/0x8b [ 432.737576] [ 432.737576] -> #1 (&ei->i_mmap_sem){++++}: [ 432.738508] lock_acquire+0xaa/0x170 [ 432.739148] down_read+0x37/0xa0 [ 432.739735] ext4_filemap_fault+0x7b/0xb0 [ 432.740446] __do_fault+0x7a/0x200 [ 432.741060] __handle_mm_fault+0x6e0/0x2040 [ 432.741801] handle_mm_fault+0x194/0x320 [ 432.742494] __do_page_fault+0x4e1/0xa70 [ 432.743184] page_fault+0x2c/0x60 [ 432.743784] __clear_user+0x3d/0x60 [ 432.744409] clear_user+0x76/0xa0 [ 432.745009] load_elf_binary+0x2bf6/0x2f10 [ 432.745753] search_binary_handler+0x136/0x450 [ 432.746522] do_execveat_common.isra.12+0x1241/0x19c0 [ 432.747339] do_execve+0x2c/0x40 [ 432.747881] try_to_run_init_process+0x12/0x40 [ 432.748611] kernel_init+0xf2/0x180 [ 432.749190] ret_from_fork+0x3a/0x50 [ 432.749785] [ 432.749785] -> #0 (&mm->mmap_sem){++++}: [ 432.750576] __lock_acquire+0x8d1/0x12d0 [ 432.751232] lock_acquire+0xaa/0x170 [ 432.751848] __might_fault+0x12b/0x1a0 [ 432.752478] _copy_to_user+0x27/0xc0 [ 432.753080] encrypted_read+0x54d/0x7b0 [ 432.753734] keyctl_read_key+0x1f2/0x240 [ 432.754396] SyS_keyctl+0x184/0x2a0 [ 432.754995] entry_SYSCALL_64_fastpath+0x1e/0x8b [ 432.755778] [ 432.755778] other info that might help us debug this: [ 432.755778] [ 432.756972] Chain exists of: [ 432.756972] &mm->mmap_sem --> jbd2_handle --> &type->lock_class#2 [ 432.756972] [ 432.758498] Possible unsafe locking scenario: [ 432.758498] [ 432.759302] CPU0 CPU1 [ 432.759919] ---- ---- [ 432.760536] lock(&type->lock_class#2); [ 432.761100] lock(jbd2_handle); [ 432.761926] lock(&type->lock_class#2); [ 432.762836] lock(&mm->mmap_sem); [ 432.763348] [ 432.763348] *** DEADLOCK *** [ 432.763348] [ 432.764209] 1 lock held by keyctl/877: [ 432.764765] #0: (&type->lock_class#2){++++}, at: [<000000008ccfa156>] keyctl_read_key+0x174/0x240 [ 432.766045] [ 432.766045] stack backtrace: [ 432.766671] CPU: 1 PID: 877 Comm: keyctl Not tainted 4.15.0-rc8-next-20180119-00019-gab7ec46b6936 #31 [ 432.768021] Hardware name: QEMU Standard PC (i440FX + PIIX, 1996), BIOS 1.10.2-1 04/01/2014 [ 432.769211] Call Trace: [ 432.769559] dump_stack+0x8d/0xd5 [ 432.770041] print_circular_bug.isra.20+0x321/0x5e0 [ 432.770712] ? save_trace+0xd6/0x250 [ 432.771185] check_prev_add.constprop.27+0xa2a/0x1670 [ 432.771867] ? depot_save_stack+0x2d5/0x490 [ 432.772504] ? check_usage+0x13c0/0x13c0 [ 432.773047] ? trace_hardirqs_on_caller+0x3dc/0x550 [ 432.773712] ? _raw_spin_unlock_irqrestore+0x39/0x60 [ 432.774401] ? depot_save_stack+0x2d5/0x490 [ 432.774979] ? kasan_kmalloc+0x13a/0x170 [ 432.775522] ? validate_chain.isra.24+0x13ee/0x2410 [ 432.776187] validate_chain.isra.24+0x13ee/0x2410 [ 432.776831] ? check_prev_add.constprop.27+0x1670/0x1670 [ 432.777546] __lock_acquire+0x8d1/0x12d0 [ 432.778088] lock_acquire+0xaa/0x170 [ 432.778576] ? __might_fault+0xce/0x1a0 [ 432.779096] __might_fault+0x12b/0x1a0 [ 432.779608] ? __might_fault+0xce/0x1a0 [ 432.780029] _copy_to_user+0x27/0xc0 [ 432.780438] encrypted_read+0x54d/0x7b0 [ 432.780858] ? key_task_permission+0x16e/0x3b0 [ 432.781340] ? encrypted_instantiate+0x8b0/0x8b0 [ 432.781851] ? creds_are_invalid+0x9/0x50 [ 432.782287] ? lookup_user_key+0x19a/0xf50 [ 432.782736] ? __lock_acquire+0x8d1/0x12d0 [ 432.783182] ? key_validate+0xb0/0xb0 [ 432.783602] ? keyctl_read_key+0x174/0x240 [ 432.784058] keyctl_read_key+0x1f2/0x240 [ 432.784486] SyS_keyctl+0x184/0x2a0 [ 432.784875] entry_SYSCALL_64_fastpath+0x1e/0x8b [ 432.785374] RIP: 0033:0x7f812b6c8259