From patchwork Wed Sep 20 22:45:48 2017 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Eric Biggers X-Patchwork-Id: 9962841 Return-Path: Received: from mail.wl.linuxfoundation.org (pdx-wl-mail.web.codeaurora.org [172.30.200.125]) by pdx-korg-patchwork.web.codeaurora.org (Postfix) with ESMTP id 3834560208 for ; Wed, 20 Sep 2017 22:49:23 +0000 (UTC) Received: from mail.wl.linuxfoundation.org (localhost [127.0.0.1]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id 2438728925 for ; Wed, 20 Sep 2017 22:49:23 +0000 (UTC) Received: by mail.wl.linuxfoundation.org (Postfix, from userid 486) id 18F4729158; Wed, 20 Sep 2017 22:49:23 +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.3 required=2.0 tests=BAYES_00, DKIM_ADSP_CUSTOM_MED, DKIM_SIGNED, FREEMAIL_FROM, RCVD_IN_DNSWL_HI, RCVD_IN_SORBS_SPAM, T_DKIM_INVALID autolearn=unavailable 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 A5FBF28925 for ; Wed, 20 Sep 2017 22:49:22 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1751933AbdITWrE (ORCPT ); Wed, 20 Sep 2017 18:47:04 -0400 Received: from mail-pf0-f195.google.com ([209.85.192.195]:36358 "EHLO mail-pf0-f195.google.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1751795AbdITWrB (ORCPT ); Wed, 20 Sep 2017 18:47:01 -0400 Received: by mail-pf0-f195.google.com with SMTP id f84so1721589pfj.3; Wed, 20 Sep 2017 15:47:00 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20161025; h=from:to:cc:subject:date:message-id:in-reply-to:references; bh=LIzTb5n2r4dfk1Ti+uU565uMFd5VD5WWvUSIFbLU2EE=; b=GPUdoFZtIZ8WcYf+/qY+QVnNkcLjP1n38O5ryAYfXBQO/GT2e9fepYu12dNwMF8VO2 1kXx8y4d8npeZAhrBDt5sRbY3rIsZUi9imvZ+PEgOALjGfhIXEZzGNc9e0e8mIyaJqMp gxVxSyiDkI6Lij2mEyVfKvb/icwT9qtceUcveVOrT5fs7q3f30DTTCKKUlZHi/LKM+qr OPbUA9zpiD1NFdg6lnqE7jMwrQj0V43hhhUP4vS96+S1rKa+4aTTANZxorJM+M+kXGjN SngY5csccM8cUzGFE/UZE20BQ7v2YMlP06GsIMunTwzIpIRoa8ILk+O5rHV7f41MPwvx /oAg== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:from:to:cc:subject:date:message-id:in-reply-to :references; bh=LIzTb5n2r4dfk1Ti+uU565uMFd5VD5WWvUSIFbLU2EE=; b=uk1hqmwVPmvIoEzZVBIhkV9zCatzEtXNFq8OUrP0O8ycQveHXeaZ6Qr487X0F/PbpX 1P9gltcuWnGohofK8kRGXHGmFH3BTTvX72kezvfxuP7oOOis4sEVYc6iNVCP6Tn3/GsV HErhVXa7hr13xPzSE8iTcLkVyRcU5E9v+pE6jfKGee6fIqo3z9LxEdg0kP30Cx6HYfoH GWnjuTDxDyBUyHAw9mhQ8ZoEd9dXbuk9yxw++NEtBUZETeHghTcOCggfgbCymy6qQyVy FgZvVvlMT8sNilXMQ8zWqk4ZH/JFCq2I+RLlZrpBkW4eIv6ChmKbEEVv5f/Bmsy7pYFM PZ3w== X-Gm-Message-State: AHPjjUhftry4Fq350aDlEY29ku17LC8noaQQ530KTIPifx9ySH9DnZfK kUcYT2Plvo9FA/R1uyVYABMNLrVCPrY= X-Google-Smtp-Source: AOwi7QC83S6eS4o6GgU7jjtBLG6dRcHNS4E4tYs8rki2TrXkC7F5HVyPo7SlsQoFUULiKUR584BWmQ== X-Received: by 10.84.130.35 with SMTP id 32mr3481695plc.368.1505947620333; Wed, 20 Sep 2017 15:47:00 -0700 (PDT) Received: from ebiggers-linuxstation.kir.corp.google.com ([100.66.174.81]) by smtp.gmail.com with ESMTPSA id j2sm6249pgn.26.2017.09.20.15.46.59 (version=TLS1_2 cipher=ECDHE-RSA-AES128-SHA bits=128/128); Wed, 20 Sep 2017 15:46:59 -0700 (PDT) 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, "Theodore Y . Ts'o" , Jaegeuk Kim , Michael Halcrow , Eric Biggers Subject: [PATCH 08/25] fscrypt: new helper function - fscrypt_prepare_rename() Date: Wed, 20 Sep 2017 15:45:48 -0700 Message-Id: <20170920224605.22030-9-ebiggers3@gmail.com> X-Mailer: git-send-email 2.14.1.821.g8fa685d3b7-goog In-Reply-To: <20170920224605.22030-1-ebiggers3@gmail.com> References: <20170920224605.22030-1-ebiggers3@gmail.com> Sender: linux-fscrypt-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-fscrypt@vger.kernel.org X-Virus-Scanned: ClamAV using ClamSMTP From: Eric Biggers Introduce a helper function which prepares to rename a file into a possibly encrypted directory. It handles loading the encryption keys for the source and target directories if needed, and it handles enforcing that if the target directory (and the source directory for a cross-rename) is encrypted, then the file being moved into the directory has the same encryption policy as its containing directory. Signed-off-by: Eric Biggers --- fs/crypto/hooks.c | 30 ++++++++++++++++++++++++++++++ include/linux/fscrypt_notsupp.h | 11 +++++++++++ include/linux/fscrypt_supp.h | 39 +++++++++++++++++++++++++++++++++++++++ 3 files changed, 80 insertions(+) diff --git a/fs/crypto/hooks.c b/fs/crypto/hooks.c index 8b90217320dd..822cb78f9b45 100644 --- a/fs/crypto/hooks.c +++ b/fs/crypto/hooks.c @@ -62,3 +62,33 @@ int __fscrypt_prepare_link(struct inode *inode, struct inode *dir) return 0; } EXPORT_SYMBOL_GPL(__fscrypt_prepare_link); + +int __fscrypt_prepare_rename(struct inode *old_dir, struct dentry *old_dentry, + struct inode *new_dir, struct dentry *new_dentry, + unsigned int flags) +{ + int err; + + err = fscrypt_require_key(old_dir); + if (err) + return err; + + err = fscrypt_require_key(new_dir); + if (err) + return err; + + if (old_dir != new_dir) { + if (IS_ENCRYPTED(new_dir) && + !fscrypt_has_permitted_context(new_dir, + d_inode(old_dentry))) + return -EPERM; + + if ((flags & RENAME_EXCHANGE) && + IS_ENCRYPTED(old_dir) && + !fscrypt_has_permitted_context(old_dir, + d_inode(new_dentry))) + return -EPERM; + } + return 0; +} +EXPORT_SYMBOL_GPL(__fscrypt_prepare_rename); diff --git a/include/linux/fscrypt_notsupp.h b/include/linux/fscrypt_notsupp.h index 2cb400440be3..a88a2959cd8c 100644 --- a/include/linux/fscrypt_notsupp.h +++ b/include/linux/fscrypt_notsupp.h @@ -198,4 +198,15 @@ static inline int fscrypt_prepare_link(struct dentry *old_dentry, return 0; } +static inline int fscrypt_prepare_rename(struct inode *old_dir, + struct dentry *old_dentry, + struct inode *new_dir, + struct dentry *new_dentry, + unsigned int flags) +{ + if (IS_ENCRYPTED(old_dir) || IS_ENCRYPTED(new_dir)) + return -EOPNOTSUPP; + return 0; +} + #endif /* _LINUX_FSCRYPT_NOTSUPP_H */ diff --git a/include/linux/fscrypt_supp.h b/include/linux/fscrypt_supp.h index ebc0cc41aaf9..fa062d41b39a 100644 --- a/include/linux/fscrypt_supp.h +++ b/include/linux/fscrypt_supp.h @@ -201,4 +201,43 @@ static inline int fscrypt_prepare_link(struct dentry *old_dentry, return 0; } +extern int __fscrypt_prepare_rename(struct inode *old_dir, + struct dentry *old_dentry, + struct inode *new_dir, + struct dentry *new_dentry, + unsigned int flags); + +/** + * fscrypt_prepare_rename - prepare for a rename between possibly-encrypted directories + * @old_dir: source directory + * @old_dentry: dentry for source file + * @new_dir: target directory + * @new_dentry: dentry for target location (may be negative unless exchanging) + * @flags: rename flags (we care at least about %RENAME_EXCHANGE) + * + * Prepare for ->rename() where the source and/or target directories may be + * encrypted. A new link can only be added to an encrypted directory if the + * directory's encryption key is available --- since otherwise we'd have no way + * to encrypt the filename. A rename to an existing name, on the other hand, + * *is* cryptographically possible without the key. However, we take the more + * conservative approach and just forbid all no-key renames. + * + * We also verify that the rename will not violate the constraint that all files + * in an encrypted directory tree use the same encryption policy. + * + * Return: 0 on success, -ENOKEY if an encryption key is missing, -EPERM if the + * rename would cause inconsistent encryption policies, or another -errno code. + */ +static inline int fscrypt_prepare_rename(struct inode *old_dir, + struct dentry *old_dentry, + struct inode *new_dir, + struct dentry *new_dentry, + unsigned int flags) +{ + if (IS_ENCRYPTED(old_dir) || IS_ENCRYPTED(new_dir)) + return __fscrypt_prepare_rename(old_dir, old_dentry, + new_dir, new_dentry, flags); + return 0; +} + #endif /* _LINUX_FSCRYPT_SUPP_H */