All of lore.kernel.org
 help / color / mirror / Atom feed
From: Eric Biggers <ebiggers3@gmail.com>
To: linux-fscrypt@vger.kernel.org
Cc: "Theodore Y . Ts'o" <tytso@mit.edu>,
	Jaegeuk Kim <jaegeuk@kernel.org>,
	linux-ext4@vger.kernel.org,
	linux-f2fs-devel@lists.sourceforge.net,
	linux-mtd@lists.infradead.org, Eric Biggers <ebiggers@google.com>
Subject: [PATCH 23/24] fscrypt: fix up fscrypt_fname_encrypted_size() for internal use
Date: Fri, 15 Dec 2017 09:42:24 -0800	[thread overview]
Message-ID: <20171215174225.31583-24-ebiggers3@gmail.com> (raw)
In-Reply-To: <20171215174225.31583-1-ebiggers3@gmail.com>

From: Eric Biggers <ebiggers@google.com>

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 <ebiggers@google.com>
---
 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 *);
-- 
2.15.1

WARNING: multiple messages have this Message-ID (diff)
From: Eric Biggers <ebiggers3@gmail.com>
To: linux-fscrypt@vger.kernel.org
Cc: "Theodore Y . Ts'o" <tytso@mit.edu>,
	Eric Biggers <ebiggers@google.com>,
	linux-f2fs-devel@lists.sourceforge.net,
	linux-mtd@lists.infradead.org, Jaegeuk Kim <jaegeuk@kernel.org>,
	linux-ext4@vger.kernel.org
Subject: [PATCH 23/24] fscrypt: fix up fscrypt_fname_encrypted_size() for internal use
Date: Fri, 15 Dec 2017 09:42:24 -0800	[thread overview]
Message-ID: <20171215174225.31583-24-ebiggers3@gmail.com> (raw)
In-Reply-To: <20171215174225.31583-1-ebiggers3@gmail.com>

From: Eric Biggers <ebiggers@google.com>

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 <ebiggers@google.com>
---
 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 *);
-- 
2.15.1


------------------------------------------------------------------------------
Check out the vibrant tech community on one of the world's most
engaging tech sites, Slashdot.org! http://sdm.link/slashdot

  parent reply	other threads:[~2017-12-15 17:42 UTC|newest]

Thread overview: 42+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2017-12-15 17:42 [PATCH 00/24] fscrypt: symlink helpers and fscrypt.h cleanup Eric Biggers
2017-12-15 17:42 ` [PATCH 01/24] fscrypt: move fscrypt_has_encryption_key() to supp/notsupp headers Eric Biggers
2017-12-15 17:42 ` [PATCH 02/24] fscrypt: move fscrypt_control_page() " Eric Biggers
2017-12-15 17:42 ` [PATCH 03/24] fscrypt: move fscrypt_info_cachep declaration to fscrypt_private.h Eric Biggers
2017-12-15 17:42 ` [PATCH 04/24] fscrypt: move fscrypt_ctx declaration to fscrypt_supp.h Eric Biggers
2017-12-15 17:42 ` [PATCH 05/24] fscrypt: split fscrypt_dummy_context_enabled() into supp/notsupp versions Eric Biggers
2017-12-15 17:42 ` [PATCH 06/24] fscrypt: move fscrypt_operations declaration to fscrypt_supp.h Eric Biggers
2017-12-15 17:42   ` Eric Biggers
2017-12-15 17:42 ` [PATCH 07/24] fscrypt: move fscrypt_valid_enc_modes() to fscrypt_private.h Eric Biggers
2017-12-15 17:42   ` Eric Biggers
2017-12-15 17:42 ` [PATCH 08/24] fscrypt: move fscrypt_is_dot_dotdot() to fs/crypto/fname.c Eric Biggers
2017-12-15 17:42   ` Eric Biggers
2017-12-15 17:42 ` [PATCH 09/24] fscrypt: trim down fscrypt.h includes Eric Biggers
2017-12-15 17:42 ` [PATCH 10/24] fscrypt: new helper functions for ->symlink() Eric Biggers
2017-12-15 17:42   ` Eric Biggers
2017-12-15 17:42 ` [PATCH 11/24] fscrypt: new helper function - fscrypt_get_symlink() Eric Biggers
2017-12-15 17:42   ` Eric Biggers
2017-12-15 17:42 ` [PATCH 12/24] ext4: switch to fscrypt ->symlink() helper functions Eric Biggers
2017-12-15 17:42   ` Eric Biggers
2017-12-15 17:42 ` [PATCH 13/24] ext4: switch to fscrypt_get_symlink() Eric Biggers
2017-12-15 17:42   ` Eric Biggers
2017-12-15 17:42 ` [PATCH 14/24] f2fs: switch to fscrypt ->symlink() helper functions Eric Biggers
2017-12-15 17:42   ` Eric Biggers
2017-12-15 17:42 ` [PATCH 15/24] f2fs: switch to fscrypt_get_symlink() Eric Biggers
2017-12-15 17:42   ` Eric Biggers
2017-12-15 17:42 ` [PATCH 16/24] ubifs: free the encrypted symlink target Eric Biggers
2017-12-15 17:42 ` [PATCH 17/24] ubifs: switch to fscrypt ->symlink() helper functions Eric Biggers
2017-12-15 17:42   ` Eric Biggers
2017-12-15 17:42 ` [PATCH 18/24] ubifs: switch to fscrypt_get_symlink() Eric Biggers
2017-12-15 17:42   ` Eric Biggers
2017-12-15 17:42 ` [PATCH 19/24] fscrypt: remove fscrypt_fname_usr_to_disk() Eric Biggers
2017-12-15 17:42   ` Eric Biggers
2017-12-15 17:42 ` [PATCH 20/24] fscrypt: move fscrypt_symlink_data to fscrypt_private.h Eric Biggers
2017-12-15 17:42   ` Eric Biggers
2017-12-15 17:42 ` [PATCH 21/24] fscrypt: calculate NUL-padding length in one place only Eric Biggers
2017-12-15 17:42   ` Eric Biggers
2017-12-15 17:42 ` [PATCH 22/24] fscrypt: define fscrypt_fname_alloc_buffer() to be for presented names Eric Biggers
2017-12-15 17:42   ` Eric Biggers
2017-12-15 17:42 ` Eric Biggers [this message]
2017-12-15 17:42   ` [PATCH 23/24] fscrypt: fix up fscrypt_fname_encrypted_size() for internal use Eric Biggers
2017-12-15 17:42 ` [PATCH 24/24] fscrypt: document symlink length restriction Eric Biggers
2017-12-15 17:42   ` Eric Biggers

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=20171215174225.31583-24-ebiggers3@gmail.com \
    --to=ebiggers3@gmail.com \
    --cc=ebiggers@google.com \
    --cc=jaegeuk@kernel.org \
    --cc=linux-ext4@vger.kernel.org \
    --cc=linux-f2fs-devel@lists.sourceforge.net \
    --cc=linux-fscrypt@vger.kernel.org \
    --cc=linux-mtd@lists.infradead.org \
    --cc=tytso@mit.edu \
    /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 an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.