From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-9.1 required=3.0 tests=DKIMWL_WL_HIGH,DKIM_SIGNED, DKIM_VALID,DKIM_VALID_AU,INCLUDES_PATCH,MAILING_LIST_MULTI,SIGNED_OFF_BY, SPF_PASS,USER_AGENT_GIT autolearn=unavailable autolearn_force=no version=3.4.0 Received: from mail.kernel.org (mail.kernel.org [198.145.29.99]) by smtp.lore.kernel.org (Postfix) with ESMTP id BFB8AC43381 for ; Wed, 20 Mar 2019 18:40:22 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by mail.kernel.org (Postfix) with ESMTP id 98483218A3 for ; Wed, 20 Mar 2019 18:40:22 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=default; t=1553107222; bh=gw7hzL2AWULkDpqnra8Btn4G36d3e2QHfPxFEHxuM+Q=; h=From:To:Cc:Subject:Date:In-Reply-To:References:List-ID:From; b=v0KNitX5Dch/2CcdOcphmsPsdhuY48zFAKFdM0G0aDGgn82XKWGJrywWiHKSiWnEX BF82lCBE1OSK5rrfe/Ju0Tk6FjrRQL7DdzqV53Qa0C7tgl+ATiodElU/EIWskN45l5 /oRzUGN15opGlzLvtRC6Am5cbq2aiKMQJukhKhXs= Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1727515AbfCTSkQ (ORCPT ); Wed, 20 Mar 2019 14:40:16 -0400 Received: from mail.kernel.org ([198.145.29.99]:36580 "EHLO mail.kernel.org" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1727271AbfCTSkQ (ORCPT ); Wed, 20 Mar 2019 14:40:16 -0400 Received: from ebiggers-linuxstation.mtv.corp.google.com (unknown [104.132.1.77]) (using TLSv1.2 with cipher ECDHE-RSA-AES128-GCM-SHA256 (128/128 bits)) (No client certificate requested) by mail.kernel.org (Postfix) with ESMTPSA id 6FE002184D; Wed, 20 Mar 2019 18:40:14 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=default; t=1553107214; bh=gw7hzL2AWULkDpqnra8Btn4G36d3e2QHfPxFEHxuM+Q=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=Qye2SP4yuT5Mn/ZZSTmiWX1eRJQP2xdtgpmqL0MfroLwNJuTe0KmM5BHjAxFeQ6GS dueVl8MsoLVeMGaUZc3y+gRl9R5CqJltDFCcsy4uJBrCUYtZycfq/+HWHtxm1xO3X7 xODg9CUj76XYwKA0NZbwW9jxbvBq/M5BugWipLIE= From: Eric Biggers To: linux-fscrypt@vger.kernel.org Cc: linux-fsdevel@vger.kernel.org, linux-ext4@vger.kernel.org, linux-f2fs-devel@lists.sourceforge.net, linux-mtd@lists.infradead.org, linux-unionfs@vger.kernel.org, Sarthak Kukreti , Gao Xiang Subject: [PATCH v2 2/5] fscrypt: fix race allowing rename() and link() of ciphertext dentries Date: Wed, 20 Mar 2019 11:39:10 -0700 Message-Id: <20190320183913.12686-3-ebiggers@kernel.org> X-Mailer: git-send-email 2.21.0.225.g810b269d1ac-goog In-Reply-To: <20190320183913.12686-1-ebiggers@kernel.org> References: <20190320183913.12686-1-ebiggers@kernel.org> MIME-Version: 1.0 Content-Transfer-Encoding: 8bit Sender: linux-fsdevel-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-fsdevel@vger.kernel.org From: Eric Biggers Close some race conditions where fscrypt allowed rename() and link() on ciphertext dentries that had been looked up just prior to the key being concurrently added. It's better to return -ENOKEY in this case. This avoids doing the nonsensical thing of encrypting the names a second time when searching for the actual on-disk dir entries. It also guarantees that DCACHE_ENCRYPTED_NAME dentries are never rename()d, so the dcache won't have support all possible combinations of moving DCACHE_ENCRYPTED_NAME around during __d_move(). Signed-off-by: Eric Biggers --- fs/crypto/hooks.c | 12 +++++++++++- include/linux/fscrypt.h | 9 +++++---- 2 files changed, 16 insertions(+), 5 deletions(-) diff --git a/fs/crypto/hooks.c b/fs/crypto/hooks.c index a9492f75bbe13..2e7498a821a48 100644 --- a/fs/crypto/hooks.c +++ b/fs/crypto/hooks.c @@ -49,7 +49,8 @@ int fscrypt_file_open(struct inode *inode, struct file *filp) } EXPORT_SYMBOL_GPL(fscrypt_file_open); -int __fscrypt_prepare_link(struct inode *inode, struct inode *dir) +int __fscrypt_prepare_link(struct inode *inode, struct inode *dir, + struct dentry *dentry) { int err; @@ -57,6 +58,10 @@ int __fscrypt_prepare_link(struct inode *inode, struct inode *dir) if (err) return err; + /* ... in case we looked up ciphertext name before key was added */ + if (dentry->d_flags & DCACHE_ENCRYPTED_NAME) + return -ENOKEY; + if (!fscrypt_has_permitted_context(dir, inode)) return -EXDEV; @@ -78,6 +83,11 @@ int __fscrypt_prepare_rename(struct inode *old_dir, struct dentry *old_dentry, if (err) return err; + /* ... in case we looked up ciphertext name(s) before key was added */ + if ((old_dentry->d_flags | new_dentry->d_flags) & + DCACHE_ENCRYPTED_NAME) + return -ENOKEY; + if (old_dir != new_dir) { if (IS_ENCRYPTED(new_dir) && !fscrypt_has_permitted_context(new_dir, diff --git a/include/linux/fscrypt.h b/include/linux/fscrypt.h index 5a0c3fee1ea2b..4ad7a856e0f1c 100644 --- a/include/linux/fscrypt.h +++ b/include/linux/fscrypt.h @@ -214,7 +214,8 @@ extern int fscrypt_zeroout_range(const struct inode *, pgoff_t, sector_t, /* hooks.c */ extern int fscrypt_file_open(struct inode *inode, struct file *filp); -extern int __fscrypt_prepare_link(struct inode *inode, struct inode *dir); +extern int __fscrypt_prepare_link(struct inode *inode, struct inode *dir, + struct dentry *dentry); extern int __fscrypt_prepare_rename(struct inode *old_dir, struct dentry *old_dentry, struct inode *new_dir, @@ -401,8 +402,8 @@ static inline int fscrypt_file_open(struct inode *inode, struct file *filp) return 0; } -static inline int __fscrypt_prepare_link(struct inode *inode, - struct inode *dir) +static inline int __fscrypt_prepare_link(struct inode *inode, struct inode *dir, + struct dentry *dentry) { return -EOPNOTSUPP; } @@ -497,7 +498,7 @@ static inline int fscrypt_prepare_link(struct dentry *old_dentry, struct dentry *dentry) { if (IS_ENCRYPTED(dir)) - return __fscrypt_prepare_link(d_inode(old_dentry), dir); + return __fscrypt_prepare_link(d_inode(old_dentry), dir, dentry); return 0; } -- 2.21.0.225.g810b269d1ac-goog