linux-fscrypt.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
From: Eric Biggers <ebiggers3@gmail.com>
To: "André Draszik" <git@andred.net>
Cc: linux-kernel@vger.kernel.org,
	Mimi Zohar <zohar@linux.vnet.ibm.com>,
	David Howells <dhowells@redhat.com>,
	James Morris <james.l.morris@oracle.com>,
	"Serge E. Hallyn" <serge@hallyn.com>,
	"Theodore Y. Ts'o" <tytso@mit.edu>,
	Jaegeuk Kim <jaegeuk@kernel.org>,
	Kees Cook <keescook@chromium.org>,
	Eric Biggers <ebiggers@google.com>,
	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
Date: Mon, 29 Jan 2018 10:19:35 -0800	[thread overview]
Message-ID: <20180129181935.qaec5n7w6jsk6gso@gmail.com> (raw)
In-Reply-To: <20180126003748.f2uhgwhulcltyok6@gmail.com>

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

      reply	other threads:[~2018-01-29 18:19 UTC|newest]

Thread overview: 4+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2018-01-18 13:13 [PATCH v3] fscrypt: add support for the encrypted key type André Draszik
2018-01-26  0:36 ` Eric Biggers
2018-01-26  0:37 ` Eric Biggers
2018-01-29 18:19   ` Eric Biggers [this message]

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=20180129181935.qaec5n7w6jsk6gso@gmail.com \
    --to=ebiggers3@gmail.com \
    --cc=dhowells@redhat.com \
    --cc=ebiggers@google.com \
    --cc=git@andred.net \
    --cc=jaegeuk@kernel.org \
    --cc=james.l.morris@oracle.com \
    --cc=keescook@chromium.org \
    --cc=keyrings@vger.kernel.org \
    --cc=linux-fscrypt@vger.kernel.org \
    --cc=linux-integrity@vger.kernel.org \
    --cc=linux-kernel@vger.kernel.org \
    --cc=linux-security-module@vger.kernel.org \
    --cc=serge@hallyn.com \
    --cc=tytso@mit.edu \
    --cc=zohar@linux.vnet.ibm.com \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).