From patchwork Fri Dec 15 17:42:24 2017 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Eric Biggers X-Patchwork-Id: 10115711 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 716FE6019C for ; Fri, 15 Dec 2017 17:47:13 +0000 (UTC) Received: from mail.wl.linuxfoundation.org (localhost [127.0.0.1]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id 5F45929EE1 for ; Fri, 15 Dec 2017 17:47:13 +0000 (UTC) Received: by mail.wl.linuxfoundation.org (Postfix, from userid 486) id 542AE2A024; Fri, 15 Dec 2017 17:47:13 +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.8 required=2.0 tests=BAYES_00, DKIM_ADSP_CUSTOM_MED, DKIM_SIGNED, FREEMAIL_FROM, RCVD_IN_DNSWL_HI, T_DKIM_INVALID autolearn=ham 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 3338529F27 for ; Fri, 15 Dec 2017 17:47:12 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1755927AbdLORrL (ORCPT ); Fri, 15 Dec 2017 12:47:11 -0500 Received: from mail-pg0-f66.google.com ([74.125.83.66]:32955 "EHLO mail-pg0-f66.google.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1756143AbdLORrF (ORCPT ); Fri, 15 Dec 2017 12:47:05 -0500 Received: by mail-pg0-f66.google.com with SMTP id g7so6264745pgs.0; Fri, 15 Dec 2017 09:47:04 -0800 (PST) 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=JAiOz/3QrE0rAodowH9PM2A5jkngLcjS2NkTU1O4YZ4=; b=eWoeLZa9c6SfB41X8dZixZ/a3uU42EGVlYmOPcPyTn+KN7+AYdIIbSCBmAWNPBBvkb LWwjzyc2JisEsc+GvRDwwI5dd40N0HvCZS78JS50IJZ0/xE9ah6mh0nNkfPxdBLus/Z3 Xyf/EaxZrP+L7dGCMZbXCXaDKvt+7xcHh5C+XIs07hZNX1tHCsb6rVedm0KaKGlfPIGE JzJxjxW/dBP+4Mj3/ioPHxIgQ5O/Mkix/PAC4QQPxpxfMPw4mQcpduokPZm1AHABAOwM nYCAFgOy18Bu3QCS/EhB7X3NiVUL1rRXn/tbxBL5h1BeVwgjw9KPGkjxTsZTeT6sImVw z+iw== 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=JAiOz/3QrE0rAodowH9PM2A5jkngLcjS2NkTU1O4YZ4=; b=iNnolrhW6NG80EfyaCSKjtkzilC+1qzBJAz9lbgsA6b5ve5XURfn5LQysiECzFBvWI iJGNQ3HpS5GSUAy9BgoIjZlpsRTCcYAqPTKnxOM0NU19oW/dVy1V4Dw1LNWH+RGsuybR t5O4Rwd5XpUrmuHVApPVaerCgT6jqb6rZmQiyRIhomuYd+/TTqGzqJ0Bm3etKlN921wF QiqiAPjv14m5ZrIkX9e25TFJPlH+4Zzjf44BNHbjEjdbW7DZGPjfIBesSS1qPdo6dTmE 21xkfo+THko+syzmwNSoNSp3960PWl8RW3dJU31XhMBWC2BxSL6F7wYBAdMGnemzNWw0 MJrQ== X-Gm-Message-State: AKGB3mJfaS1ZVq9grXHWtcuOvoVOk7zBgCeQv4ymdYr4MGGuRhJCa33Q JFNV2yF+fb9P4JMZo7LIPUKi0OzNbsQ= X-Google-Smtp-Source: ACJfBosJRXoFf0k3qNUOpKOQ9CAVMIMoGggA1RVvbWxMBJth3zm6konHDQpq1CuY37JxOvV+9qTYiQ== X-Received: by 10.84.242.69 with SMTP id c5mr14022880pll.73.1513360023980; Fri, 15 Dec 2017 09:47:03 -0800 (PST) Received: from zzz.localdomain (c-67-185-97-198.hsd1.wa.comcast.net. [67.185.97.198]) by smtp.gmail.com with ESMTPSA id j62sm12980149pfc.18.2017.12.15.09.47.03 (version=TLS1_2 cipher=ECDHE-RSA-AES128-GCM-SHA256 bits=128/128); Fri, 15 Dec 2017 09:47:03 -0800 (PST) From: Eric Biggers To: linux-fscrypt@vger.kernel.org Cc: "Theodore Y . Ts'o" , Jaegeuk Kim , linux-ext4@vger.kernel.org, linux-f2fs-devel@lists.sourceforge.net, linux-mtd@lists.infradead.org, Eric Biggers Subject: [PATCH 23/24] fscrypt: fix up fscrypt_fname_encrypted_size() for internal use Date: Fri, 15 Dec 2017 09:42:24 -0800 Message-Id: <20171215174225.31583-24-ebiggers3@gmail.com> X-Mailer: git-send-email 2.15.1 In-Reply-To: <20171215174225.31583-1-ebiggers3@gmail.com> References: <20171215174225.31583-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 Filesystems don't need fscrypt_fname_encrypted_size() anymore, so unexport it and move it to fscrypt_private.h. We also never calculate the encrypted size of a filename without having the fscrypt_info present since it is needed to know the amount of NUL-padding which is determined by the encryption policy, and also we will always truncate the NUL-padding to the maximum filename length. Therefore, also make fscrypt_fname_encrypted_size() assume that the fscrypt_info is present, and make it truncate the returned length to the specified max_len. Signed-off-by: Eric Biggers --- fs/crypto/fname.c | 31 +++++++++++++++---------------- fs/crypto/fscrypt_private.h | 3 +++ fs/crypto/hooks.c | 10 +++++----- include/linux/fscrypt_notsupp.h | 8 -------- include/linux/fscrypt_supp.h | 1 - 5 files changed, 23 insertions(+), 30 deletions(-) diff --git a/fs/crypto/fname.c b/fs/crypto/fname.c index 44ddd094b7c5..e33f3d3c5ade 100644 --- a/fs/crypto/fname.c +++ b/fs/crypto/fname.c @@ -191,17 +191,20 @@ static int digest_decode(const char *src, int len, char *dst) return cp - dst; } -u32 fscrypt_fname_encrypted_size(const struct inode *inode, u32 ilen) +bool fscrypt_fname_encrypted_size(const struct inode *inode, u32 orig_len, + u32 max_len, u32 *encrypted_len_ret) { - int padding = 32; - struct fscrypt_info *ci = inode->i_crypt_info; - - if (ci) - padding = 4 << (ci->ci_flags & FS_POLICY_FLAGS_PAD_MASK); - ilen = max(ilen, (u32)FS_CRYPTO_BLOCK_SIZE); - return round_up(ilen, padding); + int padding = 4 << (inode->i_crypt_info->ci_flags & + FS_POLICY_FLAGS_PAD_MASK); + u32 encrypted_len; + + if (orig_len > max_len) + return false; + encrypted_len = max(orig_len, (u32)FS_CRYPTO_BLOCK_SIZE); + encrypted_len = round_up(encrypted_len, padding); + *encrypted_len_ret = min(encrypted_len, max_len); + return true; } -EXPORT_SYMBOL(fscrypt_fname_encrypted_size); /** * fscrypt_fname_alloc_buffer - allocate a buffer for presented filenames @@ -342,14 +345,10 @@ int fscrypt_setup_filename(struct inode *dir, const struct qstr *iname, return ret; if (dir->i_crypt_info) { - unsigned int max_len = dir->i_sb->s_cop->max_namelen(dir); - - if (iname->len > max_len) + if (!fscrypt_fname_encrypted_size(dir, iname->len, + dir->i_sb->s_cop->max_namelen(dir), + &fname->crypto_buf.len)) return -ENAMETOOLONG; - - fname->crypto_buf.len = - min(fscrypt_fname_encrypted_size(dir, iname->len), - max_len); fname->crypto_buf.name = kmalloc(fname->crypto_buf.len, GFP_NOFS); if (!fname->crypto_buf.name) diff --git a/fs/crypto/fscrypt_private.h b/fs/crypto/fscrypt_private.h index 053917587200..ad6722bae8b7 100644 --- a/fs/crypto/fscrypt_private.h +++ b/fs/crypto/fscrypt_private.h @@ -110,6 +110,9 @@ extern struct page *fscrypt_alloc_bounce_page(struct fscrypt_ctx *ctx, /* fname.c */ extern int fname_encrypt(struct inode *inode, const struct qstr *iname, u8 *out, unsigned int olen); +extern bool fscrypt_fname_encrypted_size(const struct inode *inode, + u32 orig_len, u32 max_len, + u32 *encrypted_len_ret); /* keyinfo.c */ extern void __exit fscrypt_essiv_cleanup(void); diff --git a/fs/crypto/hooks.c b/fs/crypto/hooks.c index ff20cacdea94..3e84d92215a1 100644 --- a/fs/crypto/hooks.c +++ b/fs/crypto/hooks.c @@ -139,12 +139,12 @@ int __fscrypt_prepare_symlink(struct inode *dir, unsigned int len, * counting it (even though it is meaningless for ciphertext) is simpler * for now since filesystems will assume it is there and subtract it. */ - if (sizeof(struct fscrypt_symlink_data) + len > max_len) + if (!fscrypt_fname_encrypted_size(dir, len, + max_len - sizeof(struct fscrypt_symlink_data), + &disk_link->len)) return -ENAMETOOLONG; - disk_link->len = min_t(unsigned int, - sizeof(struct fscrypt_symlink_data) + - fscrypt_fname_encrypted_size(dir, len), - max_len); + disk_link->len += sizeof(struct fscrypt_symlink_data); + disk_link->name = NULL; return 0; } diff --git a/include/linux/fscrypt_notsupp.h b/include/linux/fscrypt_notsupp.h index c9592e307df5..342eb97e0476 100644 --- a/include/linux/fscrypt_notsupp.h +++ b/include/linux/fscrypt_notsupp.h @@ -131,14 +131,6 @@ static inline void fscrypt_free_filename(struct fscrypt_name *fname) return; } -static inline u32 fscrypt_fname_encrypted_size(const struct inode *inode, - u32 ilen) -{ - /* never happens */ - WARN_ON(1); - return 0; -} - static inline int fscrypt_fname_alloc_buffer(const struct inode *inode, u32 max_encrypted_len, struct fscrypt_str *crypto_str) diff --git a/include/linux/fscrypt_supp.h b/include/linux/fscrypt_supp.h index e00191deb0d6..2dd5767c77b0 100644 --- a/include/linux/fscrypt_supp.h +++ b/include/linux/fscrypt_supp.h @@ -107,7 +107,6 @@ static inline void fscrypt_free_filename(struct fscrypt_name *fname) kfree(fname->crypto_buf.name); } -extern u32 fscrypt_fname_encrypted_size(const struct inode *, u32); extern int fscrypt_fname_alloc_buffer(const struct inode *, u32, struct fscrypt_str *); extern void fscrypt_fname_free_buffer(struct fscrypt_str *);