Received: by 10.223.176.5 with SMTP id f5csp3217732wra; Mon, 29 Jan 2018 10:20:31 -0800 (PST) X-Google-Smtp-Source: AH8x225xtQu0Exlk/6zuR5kEoFyAKm3HfGjx/yRCMcwhsAt9UB7T3nkXNurCR78AmxZzYxDPi/za X-Received: by 10.99.114.27 with SMTP id n27mr22475510pgc.424.1517250031496; Mon, 29 Jan 2018 10:20:31 -0800 (PST) ARC-Seal: i=1; a=rsa-sha256; t=1517250031; cv=none; d=google.com; s=arc-20160816; b=CKj3r+kB5cr07m5C1xWMSH3oXMLihBB5yWtKZIhd1gq6xhc9zdFr9DbKhGZ5eG5jka lhR3YkHhYxN/tJELIzFRxDhgoFiL0FjtURxmuSsuZfAuFb7KPv910cECcOx7S1WzSvK0 LqeFS1CAn7GJ60DURAbwVkaaiXpD6G0MMcBRxnGVOnUZCzThCvGYLujTRv/+Z0RwA968 ywN++uetyjiKr4ONaZRpbBo1n1HAHRsL4vPz/13U3ek2dffDHkJw9Ot0nXpf3LuSUEsl Tt0hgKLtJ71Hg8RRRq0upr8eu8tuHU6JGdqtBR5TJ1RFHPvnE4E/NbSfsGaExPemscBf NPEQ== 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=thhamcum9WliOnXP4QIxExqO0ppuCb4R58XnWc+XaNo=; b=EoWcqYOk1ghh0XoFZsBXZLczJzbFh6+0USYhf7696cGlFmjm7MlrQbpz7OPQ/QXoKB fpcI5kYwORahBgsO6o0BvstNbV4ee9mDIiffTqvJCK3BQ9q202MQgBT2Qfy5tt3nKedj KjJWM6/bXSOGWJQ/zJrf9Sfu6C9pUVgEaCFdIOWVMo9/kSfeDm91LrRSo+mQWTgnQLwV b6SdGvhX6kbpDp661XNChtB1N9drYIPIXDly7Y3SrYLCwlR6ARTuzjj8hbmPkb8pZxKm uH+2m7SfYmqKac2wAWwW19y+yv937kuynGX5ptBTNogAf5QdaNKFbSfHiG5NrKIR0lY2 +MjA== ARC-Authentication-Results: i=1; mx.google.com; dkim=pass header.i=@gmail.com header.s=20161025 header.b=ZC2h6T7s; 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 v8si12339446pfe.266.2018.01.29.10.20.16; Mon, 29 Jan 2018 10:20:31 -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=ZC2h6T7s; 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 S1751586AbeA2STm (ORCPT + 99 others); Mon, 29 Jan 2018 13:19:42 -0500 Received: from mail-it0-f66.google.com ([209.85.214.66]:54502 "EHLO mail-it0-f66.google.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1751249AbeA2STj (ORCPT ); Mon, 29 Jan 2018 13:19:39 -0500 Received: by mail-it0-f66.google.com with SMTP id k131so9445266ith.4; Mon, 29 Jan 2018 10:19:39 -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=thhamcum9WliOnXP4QIxExqO0ppuCb4R58XnWc+XaNo=; b=ZC2h6T7sX0Nl5undXWYq3wkXoLgBG3q8/tFWAD0s4xm33WwzsNEdkhWuqNtFYmW3E9 XeQGh6pE4xu9I2WC38jVm77hkPrMPafCRyVpw/70d4fjkYwiE/fVISuZPwfnyL4NrD8E LXmYm7xfMmobblYK8kl3PaCrUYbH2/ZVqjckArG1gaCyPUW1HkOyxtuAVKLEMPER3OiH 68AALtF2IlqGkwXYod1b4h4omARY4rUPdM2L6VGO8DKM6Gu/SPxP4lQlbSMs66sARNa/ bRG9aTupBbe9wS2mgUsrLe+mzRqme6+IUJriEMsYXWBgeK29KwmUs3WrHlvDfbpRqeLz Az/A== 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=thhamcum9WliOnXP4QIxExqO0ppuCb4R58XnWc+XaNo=; b=nD/M1Kh1oSl/wbCGsBumNEaALOWkResLDX/fU77Z9z11KkohAIuCFmGFT3C8m98shT Fku/JlaGrt8VuXON/GJC8SuDz1ektW+eJ00BmVqtDZp0DvaNOlDzGWwKbuStMYCWhm1Y XpLSzvsJ+6XLu6OIWSja6RUvhoUsprs7ljG5LqE9Q8Q2D/NEwUTdyF6dg883W6xP+V5C eK3ShEpcUkItckHRE7SlkN9XCjnLa4692KaHWOUz+rmAWOWU01b+f2aKsCu73o/cqmdh FU0E6zzzPK04Qmq6LrrE+10fKupDetVCnPCH1/GUkEqfyAZw81HUIxcwIYfwpa8J+Nhw LkKw== X-Gm-Message-State: AKwxytf+HaAyVjxfMVLc1t/jaTk99VPFv2uZujHgAlaDa5oFLA8ubzUy xx8YsZAp0qgc0HOPLRzpxZQ= X-Received: by 10.36.110.143 with SMTP id w137mr26264144itc.119.1517249978564; Mon, 29 Jan 2018 10:19:38 -0800 (PST) Received: from gmail.com ([2620:15c:17:3:dc28:5c82:b905:e8a8]) by smtp.gmail.com with ESMTPSA id d11sm4391505iob.8.2018.01.29.10.19.37 (version=TLS1_2 cipher=ECDHE-RSA-CHACHA20-POLY1305 bits=256/256); Mon, 29 Jan 2018 10:19:38 -0800 (PST) Date: Mon, 29 Jan 2018 10:19:35 -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: <20180129181935.qaec5n7w6jsk6gso@gmail.com> References: <20180118131359.8365-1-git@andred.net> <20180126003748.f2uhgwhulcltyok6@gmail.com> MIME-Version: 1.0 Content-Type: text/plain; charset=iso-8859-1 Content-Disposition: inline Content-Transfer-Encoding: 8bit In-Reply-To: <20180126003748.f2uhgwhulcltyok6@gmail.com> 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 25, 2018 at 04:37:48PM -0800, Eric Biggers wrote: > 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; > > } > > 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(). > Actually, a better idea might be to access the key payload under rcu_read_lock() rather than the key semaphore. It looks like that's possible with both the "logon" and "encrypted" key types. Note that derive_key_aes() can sleep, so the part under the rcu_read_lock() would have to just copy the payload to a temporary buffer, and derive_key_aes() would be done after rcu_read_unlock(), using the temporary buffer. But I think you can just reuse the 'raw_key' buffer, so that the encryption operation in derive_key_aes() is done in-place. Eric