* [PATCH 01/24] fscrypt: move fscrypt_has_encryption_key() to supp/notsupp headers
2017-12-15 17:42 [PATCH 00/24] fscrypt: symlink helpers and fscrypt.h cleanup Eric Biggers
@ 2017-12-15 17:42 ` Eric Biggers
2017-12-15 17:42 ` [PATCH 02/24] fscrypt: move fscrypt_control_page() " Eric Biggers
` (22 subsequent siblings)
23 siblings, 0 replies; 25+ messages in thread
From: Eric Biggers @ 2017-12-15 17:42 UTC (permalink / raw)
To: linux-fscrypt
Cc: Theodore Y . Ts'o, Jaegeuk Kim, linux-ext4, linux-f2fs-devel,
linux-mtd, Eric Biggers
From: Eric Biggers <ebiggers@google.com>
fscrypt_has_encryption_key() is already split into two versions
depending on whether the filesystem is being built with encryption
support or not. Move them into the appropriate headers.
Signed-off-by: Eric Biggers <ebiggers@google.com>
---
include/linux/fscrypt.h | 10 ----------
include/linux/fscrypt_notsupp.h | 5 +++++
include/linux/fscrypt_supp.h | 5 +++++
3 files changed, 10 insertions(+), 10 deletions(-)
diff --git a/include/linux/fscrypt.h b/include/linux/fscrypt.h
index 08b4b40c5aa8..d1c891b5bd9c 100644
--- a/include/linux/fscrypt.h
+++ b/include/linux/fscrypt.h
@@ -129,11 +129,6 @@ static inline struct page *fscrypt_control_page(struct page *page)
return ((struct fscrypt_ctx *)page_private(page))->w.control_page;
}
-static inline bool fscrypt_has_encryption_key(const struct inode *inode)
-{
- return (inode->i_crypt_info != NULL);
-}
-
#include <linux/fscrypt_supp.h>
#else /* !__FS_HAS_ENCRYPTION */
@@ -144,11 +139,6 @@ static inline struct page *fscrypt_control_page(struct page *page)
return ERR_PTR(-EINVAL);
}
-static inline bool fscrypt_has_encryption_key(const struct inode *inode)
-{
- return 0;
-}
-
#include <linux/fscrypt_notsupp.h>
#endif /* __FS_HAS_ENCRYPTION */
diff --git a/include/linux/fscrypt_notsupp.h b/include/linux/fscrypt_notsupp.h
index 63e58808519a..52e330285457 100644
--- a/include/linux/fscrypt_notsupp.h
+++ b/include/linux/fscrypt_notsupp.h
@@ -14,6 +14,11 @@
#ifndef _LINUX_FSCRYPT_NOTSUPP_H
#define _LINUX_FSCRYPT_NOTSUPP_H
+static inline bool fscrypt_has_encryption_key(const struct inode *inode)
+{
+ return false;
+}
+
/* crypto.c */
static inline struct fscrypt_ctx *fscrypt_get_ctx(const struct inode *inode,
gfp_t gfp_flags)
diff --git a/include/linux/fscrypt_supp.h b/include/linux/fscrypt_supp.h
index cf9e9fc02f0a..79bb8beae018 100644
--- a/include/linux/fscrypt_supp.h
+++ b/include/linux/fscrypt_supp.h
@@ -11,6 +11,11 @@
#ifndef _LINUX_FSCRYPT_SUPP_H
#define _LINUX_FSCRYPT_SUPP_H
+static inline bool fscrypt_has_encryption_key(const struct inode *inode)
+{
+ return (inode->i_crypt_info != NULL);
+}
+
/* crypto.c */
extern struct kmem_cache *fscrypt_info_cachep;
extern struct fscrypt_ctx *fscrypt_get_ctx(const struct inode *, gfp_t);
--
2.15.1
^ permalink raw reply related [flat|nested] 25+ messages in thread* [PATCH 02/24] fscrypt: move fscrypt_control_page() to supp/notsupp headers
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 ` Eric Biggers
2017-12-15 17:42 ` [PATCH 03/24] fscrypt: move fscrypt_info_cachep declaration to fscrypt_private.h Eric Biggers
` (21 subsequent siblings)
23 siblings, 0 replies; 25+ messages in thread
From: Eric Biggers @ 2017-12-15 17:42 UTC (permalink / raw)
To: linux-fscrypt
Cc: Theodore Y . Ts'o, Jaegeuk Kim, linux-ext4, linux-f2fs-devel,
linux-mtd, Eric Biggers
From: Eric Biggers <ebiggers@google.com>
fscrypt_control_page() is already split into two versions depending on
whether the filesystem is being built with encryption support or not.
Move them into the appropriate headers.
Signed-off-by: Eric Biggers <ebiggers@google.com>
---
include/linux/fscrypt.h | 18 ++----------------
include/linux/fscrypt_notsupp.h | 5 +++++
include/linux/fscrypt_supp.h | 6 ++++++
3 files changed, 13 insertions(+), 16 deletions(-)
diff --git a/include/linux/fscrypt.h b/include/linux/fscrypt.h
index d1c891b5bd9c..c23b2f16129a 100644
--- a/include/linux/fscrypt.h
+++ b/include/linux/fscrypt.h
@@ -123,24 +123,10 @@ static inline bool fscrypt_is_dot_dotdot(const struct qstr *str)
}
#if __FS_HAS_ENCRYPTION
-
-static inline struct page *fscrypt_control_page(struct page *page)
-{
- return ((struct fscrypt_ctx *)page_private(page))->w.control_page;
-}
-
#include <linux/fscrypt_supp.h>
-
-#else /* !__FS_HAS_ENCRYPTION */
-
-static inline struct page *fscrypt_control_page(struct page *page)
-{
- WARN_ON_ONCE(1);
- return ERR_PTR(-EINVAL);
-}
-
+#else
#include <linux/fscrypt_notsupp.h>
-#endif /* __FS_HAS_ENCRYPTION */
+#endif
/**
* fscrypt_require_key - require an inode's encryption key
diff --git a/include/linux/fscrypt_notsupp.h b/include/linux/fscrypt_notsupp.h
index 52e330285457..812dc701a5b3 100644
--- a/include/linux/fscrypt_notsupp.h
+++ b/include/linux/fscrypt_notsupp.h
@@ -48,6 +48,11 @@ static inline int fscrypt_decrypt_page(const struct inode *inode,
return -EOPNOTSUPP;
}
+static inline struct page *fscrypt_control_page(struct page *page)
+{
+ WARN_ON_ONCE(1);
+ return ERR_PTR(-EINVAL);
+}
static inline void fscrypt_restore_control_page(struct page *page)
{
diff --git a/include/linux/fscrypt_supp.h b/include/linux/fscrypt_supp.h
index 79bb8beae018..ad40780d4653 100644
--- a/include/linux/fscrypt_supp.h
+++ b/include/linux/fscrypt_supp.h
@@ -25,6 +25,12 @@ extern struct page *fscrypt_encrypt_page(const struct inode *, struct page *,
u64, gfp_t);
extern int fscrypt_decrypt_page(const struct inode *, struct page *, unsigned int,
unsigned int, u64);
+
+static inline struct page *fscrypt_control_page(struct page *page)
+{
+ return ((struct fscrypt_ctx *)page_private(page))->w.control_page;
+}
+
extern void fscrypt_restore_control_page(struct page *);
extern const struct dentry_operations fscrypt_d_ops;
--
2.15.1
^ permalink raw reply related [flat|nested] 25+ messages in thread* [PATCH 03/24] fscrypt: move fscrypt_info_cachep declaration to fscrypt_private.h
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 ` Eric Biggers
2017-12-15 17:42 ` [PATCH 04/24] fscrypt: move fscrypt_ctx declaration to fscrypt_supp.h Eric Biggers
` (20 subsequent siblings)
23 siblings, 0 replies; 25+ messages in thread
From: Eric Biggers @ 2017-12-15 17:42 UTC (permalink / raw)
To: linux-fscrypt
Cc: Theodore Y . Ts'o, Jaegeuk Kim, linux-ext4, linux-f2fs-devel,
linux-mtd, Eric Biggers
From: Eric Biggers <ebiggers@google.com>
The fscrypt_info kmem_cache is internal to fscrypt; filesystems don't
need to access it. So move its declaration into fscrypt_private.h.
Signed-off-by: Eric Biggers <ebiggers@google.com>
---
fs/crypto/fscrypt_private.h | 1 +
include/linux/fscrypt_supp.h | 1 -
2 files changed, 1 insertion(+), 1 deletion(-)
diff --git a/fs/crypto/fscrypt_private.h b/fs/crypto/fscrypt_private.h
index c0b4f5597e1a..823c43a00bf7 100644
--- a/fs/crypto/fscrypt_private.h
+++ b/fs/crypto/fscrypt_private.h
@@ -72,6 +72,7 @@ typedef enum {
#define FS_CTX_HAS_BOUNCE_BUFFER_FL 0x00000002
/* crypto.c */
+extern struct kmem_cache *fscrypt_info_cachep;
extern int fscrypt_initialize(unsigned int cop_flags);
extern struct workqueue_struct *fscrypt_read_workqueue;
extern int fscrypt_do_page_crypto(const struct inode *inode,
diff --git a/include/linux/fscrypt_supp.h b/include/linux/fscrypt_supp.h
index ad40780d4653..33d641e27c18 100644
--- a/include/linux/fscrypt_supp.h
+++ b/include/linux/fscrypt_supp.h
@@ -17,7 +17,6 @@ static inline bool fscrypt_has_encryption_key(const struct inode *inode)
}
/* crypto.c */
-extern struct kmem_cache *fscrypt_info_cachep;
extern struct fscrypt_ctx *fscrypt_get_ctx(const struct inode *, gfp_t);
extern void fscrypt_release_ctx(struct fscrypt_ctx *);
extern struct page *fscrypt_encrypt_page(const struct inode *, struct page *,
--
2.15.1
^ permalink raw reply related [flat|nested] 25+ messages in thread* [PATCH 04/24] fscrypt: move fscrypt_ctx declaration to fscrypt_supp.h
2017-12-15 17:42 [PATCH 00/24] fscrypt: symlink helpers and fscrypt.h cleanup Eric Biggers
` (2 preceding siblings ...)
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 ` Eric Biggers
2017-12-15 17:42 ` [PATCH 05/24] fscrypt: split fscrypt_dummy_context_enabled() into supp/notsupp versions Eric Biggers
` (19 subsequent siblings)
23 siblings, 0 replies; 25+ messages in thread
From: Eric Biggers @ 2017-12-15 17:42 UTC (permalink / raw)
To: linux-fscrypt
Cc: Theodore Y . Ts'o, Jaegeuk Kim, linux-ext4, linux-f2fs-devel,
linux-mtd, Eric Biggers
From: Eric Biggers <ebiggers@google.com>
Filesystems only ever access 'struct fscrypt_ctx' through fscrypt
functions. But when a filesystem is built without encryption support,
these functions are all stubbed out, so the declaration of fscrypt_ctx
is unneeded. Therefore, move it from fscrypt.h to fscrypt_supp.h.
Signed-off-by: Eric Biggers <ebiggers@google.com>
---
include/linux/fscrypt.h | 16 +---------------
include/linux/fscrypt_supp.h | 15 +++++++++++++++
2 files changed, 16 insertions(+), 15 deletions(-)
diff --git a/include/linux/fscrypt.h b/include/linux/fscrypt.h
index c23b2f16129a..0f94d087a6d1 100644
--- a/include/linux/fscrypt.h
+++ b/include/linux/fscrypt.h
@@ -24,23 +24,9 @@
#define FS_CRYPTO_BLOCK_SIZE 16
+struct fscrypt_ctx;
struct fscrypt_info;
-struct fscrypt_ctx {
- union {
- struct {
- struct page *bounce_page; /* Ciphertext page */
- struct page *control_page; /* Original page */
- } w;
- struct {
- struct bio *bio;
- struct work_struct work;
- } r;
- struct list_head free_list; /* Free list */
- };
- u8 flags; /* Flags */
-};
-
/**
* For encrypted symlinks, the ciphertext length is stored at the beginning
* of the string in little-endian format.
diff --git a/include/linux/fscrypt_supp.h b/include/linux/fscrypt_supp.h
index 33d641e27c18..fd6ee089ced0 100644
--- a/include/linux/fscrypt_supp.h
+++ b/include/linux/fscrypt_supp.h
@@ -11,6 +11,21 @@
#ifndef _LINUX_FSCRYPT_SUPP_H
#define _LINUX_FSCRYPT_SUPP_H
+struct fscrypt_ctx {
+ union {
+ struct {
+ struct page *bounce_page; /* Ciphertext page */
+ struct page *control_page; /* Original page */
+ } w;
+ struct {
+ struct bio *bio;
+ struct work_struct work;
+ } r;
+ struct list_head free_list; /* Free list */
+ };
+ u8 flags; /* Flags */
+};
+
static inline bool fscrypt_has_encryption_key(const struct inode *inode)
{
return (inode->i_crypt_info != NULL);
--
2.15.1
^ permalink raw reply related [flat|nested] 25+ messages in thread* [PATCH 05/24] fscrypt: split fscrypt_dummy_context_enabled() into supp/notsupp versions
2017-12-15 17:42 [PATCH 00/24] fscrypt: symlink helpers and fscrypt.h cleanup Eric Biggers
` (3 preceding siblings ...)
2017-12-15 17:42 ` [PATCH 04/24] fscrypt: move fscrypt_ctx declaration to fscrypt_supp.h Eric Biggers
@ 2017-12-15 17:42 ` Eric Biggers
2017-12-15 17:42 ` [PATCH 06/24] fscrypt: move fscrypt_operations declaration to fscrypt_supp.h Eric Biggers
` (18 subsequent siblings)
23 siblings, 0 replies; 25+ messages in thread
From: Eric Biggers @ 2017-12-15 17:42 UTC (permalink / raw)
To: linux-fscrypt
Cc: Theodore Y . Ts'o, Jaegeuk Kim, linux-ext4, linux-f2fs-devel,
linux-mtd, Eric Biggers
From: Eric Biggers <ebiggers@google.com>
fscrypt_dummy_context_enabled() accesses ->s_cop, which now is only set
when the filesystem is built with encryption support. This didn't
actually matter because no filesystems called it. However, it will
start being used soon, so fix it by moving it from fscrypt.h to
fscrypt_supp.h and stubbing it out in fscrypt_notsupp.h.
Signed-off-by: Eric Biggers <ebiggers@google.com>
---
include/linux/fscrypt.h | 8 --------
include/linux/fscrypt_notsupp.h | 5 +++++
include/linux/fscrypt_supp.h | 6 ++++++
3 files changed, 11 insertions(+), 8 deletions(-)
diff --git a/include/linux/fscrypt.h b/include/linux/fscrypt.h
index 0f94d087a6d1..b671a4eef47f 100644
--- a/include/linux/fscrypt.h
+++ b/include/linux/fscrypt.h
@@ -75,14 +75,6 @@ struct fscrypt_operations {
/* Maximum value for the third parameter of fscrypt_operations.set_context(). */
#define FSCRYPT_SET_CONTEXT_MAX_SIZE 28
-static inline bool fscrypt_dummy_context_enabled(struct inode *inode)
-{
- if (inode->i_sb->s_cop->dummy_context &&
- inode->i_sb->s_cop->dummy_context(inode))
- return true;
- return false;
-}
-
static inline bool fscrypt_valid_enc_modes(u32 contents_mode,
u32 filenames_mode)
{
diff --git a/include/linux/fscrypt_notsupp.h b/include/linux/fscrypt_notsupp.h
index 812dc701a5b3..81e02201b215 100644
--- a/include/linux/fscrypt_notsupp.h
+++ b/include/linux/fscrypt_notsupp.h
@@ -19,6 +19,11 @@ static inline bool fscrypt_has_encryption_key(const struct inode *inode)
return false;
}
+static inline bool fscrypt_dummy_context_enabled(struct inode *inode)
+{
+ return false;
+}
+
/* crypto.c */
static inline struct fscrypt_ctx *fscrypt_get_ctx(const struct inode *inode,
gfp_t gfp_flags)
diff --git a/include/linux/fscrypt_supp.h b/include/linux/fscrypt_supp.h
index fd6ee089ced0..e7dfa2974906 100644
--- a/include/linux/fscrypt_supp.h
+++ b/include/linux/fscrypt_supp.h
@@ -31,6 +31,12 @@ static inline bool fscrypt_has_encryption_key(const struct inode *inode)
return (inode->i_crypt_info != NULL);
}
+static inline bool fscrypt_dummy_context_enabled(struct inode *inode)
+{
+ return inode->i_sb->s_cop->dummy_context &&
+ inode->i_sb->s_cop->dummy_context(inode);
+}
+
/* crypto.c */
extern struct fscrypt_ctx *fscrypt_get_ctx(const struct inode *, gfp_t);
extern void fscrypt_release_ctx(struct fscrypt_ctx *);
--
2.15.1
^ permalink raw reply related [flat|nested] 25+ messages in thread* [PATCH 06/24] fscrypt: move fscrypt_operations declaration to fscrypt_supp.h
2017-12-15 17:42 [PATCH 00/24] fscrypt: symlink helpers and fscrypt.h cleanup Eric Biggers
` (4 preceding siblings ...)
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 ` Eric Biggers
2017-12-15 17:42 ` [PATCH 07/24] fscrypt: move fscrypt_valid_enc_modes() to fscrypt_private.h Eric Biggers
` (17 subsequent siblings)
23 siblings, 0 replies; 25+ messages in thread
From: Eric Biggers @ 2017-12-15 17:42 UTC (permalink / raw)
To: linux-fscrypt
Cc: Theodore Y . Ts'o, Eric Biggers, linux-f2fs-devel, linux-mtd,
Jaegeuk Kim, linux-ext4
From: Eric Biggers <ebiggers@google.com>
Filesystems now only define their fscrypt_operations when they are
compiled with encryption support, so move the fscrypt_operations
declaration from fscrypt.h to fscrypt_supp.h.
Signed-off-by: Eric Biggers <ebiggers@google.com>
---
include/linux/fscrypt.h | 18 ------------------
include/linux/fscrypt_supp.h | 18 ++++++++++++++++++
2 files changed, 18 insertions(+), 18 deletions(-)
diff --git a/include/linux/fscrypt.h b/include/linux/fscrypt.h
index b671a4eef47f..33b95a91f720 100644
--- a/include/linux/fscrypt.h
+++ b/include/linux/fscrypt.h
@@ -54,24 +54,6 @@ struct fscrypt_name {
#define fname_name(p) ((p)->disk_name.name)
#define fname_len(p) ((p)->disk_name.len)
-/*
- * fscrypt superblock flags
- */
-#define FS_CFLG_OWN_PAGES (1U << 1)
-
-/*
- * crypto opertions for filesystems
- */
-struct fscrypt_operations {
- unsigned int flags;
- const char *key_prefix;
- int (*get_context)(struct inode *, void *, size_t);
- int (*set_context)(struct inode *, const void *, size_t, void *);
- bool (*dummy_context)(struct inode *);
- bool (*empty_dir)(struct inode *);
- unsigned (*max_namelen)(struct inode *);
-};
-
/* Maximum value for the third parameter of fscrypt_operations.set_context(). */
#define FSCRYPT_SET_CONTEXT_MAX_SIZE 28
diff --git a/include/linux/fscrypt_supp.h b/include/linux/fscrypt_supp.h
index e7dfa2974906..ce61caf26f40 100644
--- a/include/linux/fscrypt_supp.h
+++ b/include/linux/fscrypt_supp.h
@@ -11,6 +11,24 @@
#ifndef _LINUX_FSCRYPT_SUPP_H
#define _LINUX_FSCRYPT_SUPP_H
+/*
+ * fscrypt superblock flags
+ */
+#define FS_CFLG_OWN_PAGES (1U << 1)
+
+/*
+ * crypto operations for filesystems
+ */
+struct fscrypt_operations {
+ unsigned int flags;
+ const char *key_prefix;
+ int (*get_context)(struct inode *, void *, size_t);
+ int (*set_context)(struct inode *, const void *, size_t, void *);
+ bool (*dummy_context)(struct inode *);
+ bool (*empty_dir)(struct inode *);
+ unsigned (*max_namelen)(struct inode *);
+};
+
struct fscrypt_ctx {
union {
struct {
--
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
^ permalink raw reply related [flat|nested] 25+ messages in thread* [PATCH 07/24] fscrypt: move fscrypt_valid_enc_modes() to fscrypt_private.h
2017-12-15 17:42 [PATCH 00/24] fscrypt: symlink helpers and fscrypt.h cleanup Eric Biggers
` (5 preceding siblings ...)
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 08/24] fscrypt: move fscrypt_is_dot_dotdot() to fs/crypto/fname.c Eric Biggers
` (16 subsequent siblings)
23 siblings, 0 replies; 25+ messages in thread
From: Eric Biggers @ 2017-12-15 17:42 UTC (permalink / raw)
To: linux-fscrypt
Cc: Theodore Y . Ts'o, Jaegeuk Kim, linux-ext4, linux-f2fs-devel,
linux-mtd, Eric Biggers
From: Eric Biggers <ebiggers@google.com>
The encryption modes are validated by fs/crypto/, not by individual
filesystems. Therefore, move fscrypt_valid_enc_modes() from fscrypt.h
to fscrypt_private.h.
Signed-off-by: Eric Biggers <ebiggers@google.com>
---
fs/crypto/fscrypt_private.h | 14 ++++++++++++++
include/linux/fscrypt.h | 14 --------------
2 files changed, 14 insertions(+), 14 deletions(-)
diff --git a/fs/crypto/fscrypt_private.h b/fs/crypto/fscrypt_private.h
index 823c43a00bf7..2b848e7c92f0 100644
--- a/fs/crypto/fscrypt_private.h
+++ b/fs/crypto/fscrypt_private.h
@@ -71,6 +71,20 @@ typedef enum {
#define FS_CTX_REQUIRES_FREE_ENCRYPT_FL 0x00000001
#define FS_CTX_HAS_BOUNCE_BUFFER_FL 0x00000002
+static inline bool fscrypt_valid_enc_modes(u32 contents_mode,
+ u32 filenames_mode)
+{
+ if (contents_mode == FS_ENCRYPTION_MODE_AES_128_CBC &&
+ filenames_mode == FS_ENCRYPTION_MODE_AES_128_CTS)
+ return true;
+
+ if (contents_mode == FS_ENCRYPTION_MODE_AES_256_XTS &&
+ filenames_mode == FS_ENCRYPTION_MODE_AES_256_CTS)
+ return true;
+
+ return false;
+}
+
/* crypto.c */
extern struct kmem_cache *fscrypt_info_cachep;
extern int fscrypt_initialize(unsigned int cop_flags);
diff --git a/include/linux/fscrypt.h b/include/linux/fscrypt.h
index 33b95a91f720..2e4dce0365cf 100644
--- a/include/linux/fscrypt.h
+++ b/include/linux/fscrypt.h
@@ -57,20 +57,6 @@ struct fscrypt_name {
/* Maximum value for the third parameter of fscrypt_operations.set_context(). */
#define FSCRYPT_SET_CONTEXT_MAX_SIZE 28
-static inline bool fscrypt_valid_enc_modes(u32 contents_mode,
- u32 filenames_mode)
-{
- if (contents_mode == FS_ENCRYPTION_MODE_AES_128_CBC &&
- filenames_mode == FS_ENCRYPTION_MODE_AES_128_CTS)
- return true;
-
- if (contents_mode == FS_ENCRYPTION_MODE_AES_256_XTS &&
- filenames_mode == FS_ENCRYPTION_MODE_AES_256_CTS)
- return true;
-
- return false;
-}
^ permalink raw reply related [flat|nested] 25+ messages in thread* [PATCH 08/24] fscrypt: move fscrypt_is_dot_dotdot() to fs/crypto/fname.c
2017-12-15 17:42 [PATCH 00/24] fscrypt: symlink helpers and fscrypt.h cleanup Eric Biggers
` (6 preceding siblings ...)
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 09/24] fscrypt: trim down fscrypt.h includes Eric Biggers
` (15 subsequent siblings)
23 siblings, 0 replies; 25+ messages in thread
From: Eric Biggers @ 2017-12-15 17:42 UTC (permalink / raw)
To: linux-fscrypt
Cc: Theodore Y . Ts'o, Eric Biggers, linux-f2fs-devel, linux-mtd,
Jaegeuk Kim, linux-ext4
From: Eric Biggers <ebiggers@google.com>
Only fs/crypto/fname.c cares about treating the "." and ".." filenames
specially with regards to encryption, so move fscrypt_is_dot_dotdot()
from fscrypt.h to there.
Signed-off-by: Eric Biggers <ebiggers@google.com>
---
fs/crypto/fname.c | 11 +++++++++++
include/linux/fscrypt.h | 11 -----------
2 files changed, 11 insertions(+), 11 deletions(-)
diff --git a/fs/crypto/fname.c b/fs/crypto/fname.c
index 305541bcd108..b8c5061553b1 100644
--- a/fs/crypto/fname.c
+++ b/fs/crypto/fname.c
@@ -15,6 +15,17 @@
#include <linux/ratelimit.h>
#include "fscrypt_private.h"
+static inline bool fscrypt_is_dot_dotdot(const struct qstr *str)
+{
+ if (str->len == 1 && str->name[0] == '.')
+ return true;
+
+ if (str->len == 2 && str->name[0] == '.' && str->name[1] == '.')
+ return true;
+
+ return false;
+}
+
/**
* fname_encrypt() - encrypt a filename
*
diff --git a/include/linux/fscrypt.h b/include/linux/fscrypt.h
index 2e4dce0365cf..3045fc49d3ca 100644
--- a/include/linux/fscrypt.h
+++ b/include/linux/fscrypt.h
@@ -57,17 +57,6 @@ struct fscrypt_name {
/* Maximum value for the third parameter of fscrypt_operations.set_context(). */
#define FSCRYPT_SET_CONTEXT_MAX_SIZE 28
-static inline bool fscrypt_is_dot_dotdot(const struct qstr *str)
-{
- if (str->len == 1 && str->name[0] == '.')
- return true;
-
- if (str->len == 2 && str->name[0] == '.' && str->name[1] == '.')
- return true;
-
- return false;
-}
-
#if __FS_HAS_ENCRYPTION
#include <linux/fscrypt_supp.h>
#else
--
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
^ permalink raw reply related [flat|nested] 25+ messages in thread* [PATCH 09/24] fscrypt: trim down fscrypt.h includes
2017-12-15 17:42 [PATCH 00/24] fscrypt: symlink helpers and fscrypt.h cleanup Eric Biggers
` (7 preceding siblings ...)
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 10/24] fscrypt: new helper functions for ->symlink() Eric Biggers
` (14 subsequent siblings)
23 siblings, 0 replies; 25+ messages in thread
From: Eric Biggers @ 2017-12-15 17:42 UTC (permalink / raw)
To: linux-fscrypt
Cc: Theodore Y . Ts'o, Jaegeuk Kim, linux-ext4, linux-f2fs-devel,
linux-mtd, Eric Biggers
From: Eric Biggers <ebiggers@google.com>
fscrypt.h included way too many other headers, given that it is included
by filesystems both with and without encryption support. Trim down the
includes list by moving the needed includes into more appropriate
places, and removing the unneeded ones.
Signed-off-by: Eric Biggers <ebiggers@google.com>
---
fs/crypto/crypto.c | 1 +
fs/crypto/fname.c | 1 +
fs/crypto/keyinfo.c | 1 +
include/linux/fscrypt.h | 6 ------
include/linux/fscrypt_supp.h | 3 +++
5 files changed, 6 insertions(+), 6 deletions(-)
diff --git a/fs/crypto/crypto.c b/fs/crypto/crypto.c
index 732a786cce9d..ce654526c0fb 100644
--- a/fs/crypto/crypto.c
+++ b/fs/crypto/crypto.c
@@ -27,6 +27,7 @@
#include <linux/dcache.h>
#include <linux/namei.h>
#include <crypto/aes.h>
+#include <crypto/skcipher.h>
#include "fscrypt_private.h"
static unsigned int num_prealloc_crypto_pages = 32;
diff --git a/fs/crypto/fname.c b/fs/crypto/fname.c
index b8c5061553b1..52d4dbe1e8e7 100644
--- a/fs/crypto/fname.c
+++ b/fs/crypto/fname.c
@@ -13,6 +13,7 @@
#include <linux/scatterlist.h>
#include <linux/ratelimit.h>
+#include <crypto/skcipher.h>
#include "fscrypt_private.h"
static inline bool fscrypt_is_dot_dotdot(const struct qstr *str)
diff --git a/fs/crypto/keyinfo.c b/fs/crypto/keyinfo.c
index 5e6e846f5a24..c115eac4b4cf 100644
--- a/fs/crypto/keyinfo.c
+++ b/fs/crypto/keyinfo.c
@@ -14,6 +14,7 @@
#include <linux/ratelimit.h>
#include <crypto/aes.h>
#include <crypto/sha.h>
+#include <crypto/skcipher.h>
#include "fscrypt_private.h"
static struct crypto_shash *essiv_hash_tfm;
diff --git a/include/linux/fscrypt.h b/include/linux/fscrypt.h
index 3045fc49d3ca..071ebabfc287 100644
--- a/include/linux/fscrypt.h
+++ b/include/linux/fscrypt.h
@@ -14,13 +14,7 @@
#ifndef _LINUX_FSCRYPT_H
#define _LINUX_FSCRYPT_H
-#include <linux/key.h>
#include <linux/fs.h>
-#include <linux/mm.h>
-#include <linux/bio.h>
-#include <linux/dcache.h>
-#include <crypto/skcipher.h>
-#include <uapi/linux/fs.h>
#define FS_CRYPTO_BLOCK_SIZE 16
diff --git a/include/linux/fscrypt_supp.h b/include/linux/fscrypt_supp.h
index ce61caf26f40..562a9bc04560 100644
--- a/include/linux/fscrypt_supp.h
+++ b/include/linux/fscrypt_supp.h
@@ -11,6 +11,9 @@
#ifndef _LINUX_FSCRYPT_SUPP_H
#define _LINUX_FSCRYPT_SUPP_H
+#include <linux/mm.h>
+#include <linux/slab.h>
+
/*
* fscrypt superblock flags
*/
--
2.15.1
^ permalink raw reply related [flat|nested] 25+ messages in thread* [PATCH 10/24] fscrypt: new helper functions for ->symlink()
2017-12-15 17:42 [PATCH 00/24] fscrypt: symlink helpers and fscrypt.h cleanup Eric Biggers
` (8 preceding siblings ...)
2017-12-15 17:42 ` [PATCH 09/24] fscrypt: trim down fscrypt.h includes 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
` (13 subsequent siblings)
23 siblings, 0 replies; 25+ messages in thread
From: Eric Biggers @ 2017-12-15 17:42 UTC (permalink / raw)
To: linux-fscrypt
Cc: Theodore Y . Ts'o, Eric Biggers, linux-f2fs-devel, linux-mtd,
Jaegeuk Kim, linux-ext4
From: Eric Biggers <ebiggers@google.com>
Currently, filesystems supporting fscrypt need to implement some tricky
logic when creating encrypted symlinks, including handling a peculiar
on-disk format (struct fscrypt_symlink_data) and correctly calculating
the size of the encrypted symlink. Introduce helper functions to make
things a bit easier:
- fscrypt_prepare_symlink() computes and validates the size the symlink
target will require on-disk.
- fscrypt_encrypt_symlink() creates the encrypted target if needed.
The new helpers actually fix some subtle bugs. First, when checking
whether the symlink target was too long, filesystems didn't account for
the fact that the NUL padding is meant to be truncated if it would cause
the maximum length to be exceeded, as is done for filenames in
directories. Consequently users would receive ENAMETOOLONG when
creating symlinks close to what is supposed to be the maximum length.
For example, with EXT4 with a 4K block size, the maximum symlink target
length in an encrypted directory is supposed to be 4093 bytes (in
comparison to 4095 in an unencrypted directory), but in
FS_POLICY_FLAGS_PAD_32-mode only up to 4064 bytes were accepted.
Second, symlink targets of "." and ".." were not being encrypted, even
though they should be, as these names are special in *directory entries*
but not in symlink targets. Fortunately, we can fix this simply by
starting to encrypt them, as old kernels already accept them in
encrypted form.
Third, the output string length the filesystems were providing when
doing the actual encryption was incorrect, as it was forgotten to
exclude 'sizeof(struct fscrypt_symlink_data)'. Fortunately though, this
bug didn't make a difference.
Signed-off-by: Eric Biggers <ebiggers@google.com>
---
fs/crypto/fname.c | 8 ++--
fs/crypto/fscrypt_private.h | 4 ++
fs/crypto/hooks.c | 86 +++++++++++++++++++++++++++++++++++++++++
include/linux/fscrypt.h | 64 ++++++++++++++++++++++++++++++
include/linux/fscrypt_notsupp.h | 16 ++++++++
include/linux/fscrypt_supp.h | 6 +++
6 files changed, 181 insertions(+), 3 deletions(-)
diff --git a/fs/crypto/fname.c b/fs/crypto/fname.c
index 52d4dbe1e8e7..62f13d533439 100644
--- a/fs/crypto/fname.c
+++ b/fs/crypto/fname.c
@@ -34,8 +34,8 @@ static inline bool fscrypt_is_dot_dotdot(const struct qstr *str)
*
* Return: 0 on success, -errno on failure
*/
-static int fname_encrypt(struct inode *inode,
- const struct qstr *iname, struct fscrypt_str *oname)
+int fname_encrypt(struct inode *inode,
+ const struct qstr *iname, struct fscrypt_str *oname)
{
struct skcipher_request *req = NULL;
DECLARE_CRYPTO_WAIT(wait);
@@ -56,9 +56,11 @@ static int fname_encrypt(struct inode *inode,
* Copy the filename to the output buffer for encrypting in-place and
* pad it with the needed number of NUL bytes.
*/
+ if (WARN_ON(oname->len < iname->len))
+ return -ENOBUFS;
cryptlen = max_t(unsigned int, iname->len, FS_CRYPTO_BLOCK_SIZE);
cryptlen = round_up(cryptlen, padding);
- cryptlen = min(cryptlen, lim);
+ cryptlen = min3(cryptlen, lim, oname->len);
memcpy(oname->name, iname->name, iname->len);
memset(oname->name + iname->len, 0, cryptlen - iname->len);
diff --git a/fs/crypto/fscrypt_private.h b/fs/crypto/fscrypt_private.h
index 2b848e7c92f0..6995bca5006b 100644
--- a/fs/crypto/fscrypt_private.h
+++ b/fs/crypto/fscrypt_private.h
@@ -98,6 +98,10 @@ extern int fscrypt_do_page_crypto(const struct inode *inode,
extern struct page *fscrypt_alloc_bounce_page(struct fscrypt_ctx *ctx,
gfp_t gfp_flags);
+/* fname.c */
+extern int fname_encrypt(struct inode *inode,
+ const struct qstr *iname, struct fscrypt_str *oname);
+
/* keyinfo.c */
extern void __exit fscrypt_essiv_cleanup(void);
diff --git a/fs/crypto/hooks.c b/fs/crypto/hooks.c
index 9f5fb2eb9cf7..483e87d40f03 100644
--- a/fs/crypto/hooks.c
+++ b/fs/crypto/hooks.c
@@ -110,3 +110,89 @@ int __fscrypt_prepare_lookup(struct inode *dir, struct dentry *dentry)
return 0;
}
EXPORT_SYMBOL_GPL(__fscrypt_prepare_lookup);
+
+int __fscrypt_prepare_symlink(struct inode *dir, unsigned int len,
+ unsigned int max_len,
+ struct fscrypt_str *disk_link)
+{
+ int err;
+
+ /*
+ * To calculate the size of the encrypted symlink target we need to know
+ * the amount of NUL padding, which is determined by the flags set in
+ * the encryption policy which will be inherited from the directory.
+ * The easiest way to get access to this is to just load the directory's
+ * fscrypt_info, since we'll need it to create the dir_entry anyway.
+ */
+ err = fscrypt_require_key(dir);
+ if (err)
+ return err;
+
+ /*
+ * Calculate the size of the encrypted symlink and verify it won't
+ * exceed max_len. Note that for historical reasons, encrypted symlink
+ * targets are prefixed with the ciphertext length, despite this
+ * actually being redundant with i_size. This decreases by 2 bytes the
+ * longest symlink target we can accept.
+ *
+ * We could recover 1 byte by not counting a null terminator, but
+ * 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)
+ return -ENAMETOOLONG;
+ disk_link->len = min_t(unsigned int,
+ sizeof(struct fscrypt_symlink_data) +
+ fscrypt_fname_encrypted_size(dir, len),
+ max_len);
+ disk_link->name = NULL;
+ return 0;
+}
+EXPORT_SYMBOL_GPL(__fscrypt_prepare_symlink);
+
+int __fscrypt_encrypt_symlink(struct inode *inode, const char *target,
+ unsigned int len, struct fscrypt_str *disk_link)
+{
+ int err;
+ struct qstr iname = { .name = target, .len = len };
+ struct fscrypt_symlink_data *sd;
+ unsigned int ciphertext_len;
+ struct fscrypt_str oname;
+
+ err = fscrypt_require_key(inode);
+ if (err)
+ return err;
+
+ if (disk_link->name) {
+ /* filesystem-provided buffer */
+ sd = (struct fscrypt_symlink_data *)disk_link->name;
+ } else {
+ sd = kmalloc(disk_link->len, GFP_NOFS);
+ if (!sd)
+ return -ENOMEM;
+ }
+ ciphertext_len = disk_link->len - sizeof(*sd);
+ sd->len = cpu_to_le16(ciphertext_len);
+
+ oname.name = sd->encrypted_path;
+ oname.len = ciphertext_len;
+ err = fname_encrypt(inode, &iname, &oname);
+ if (err) {
+ if (!disk_link->name)
+ kfree(sd);
+ return err;
+ }
+ BUG_ON(oname.len != ciphertext_len);
+
+ /*
+ * Null-terminating the ciphertext doesn't make sense, but we still
+ * count the null terminator in the length, so we might as well
+ * initialize it just in case the filesystem writes it out.
+ */
+ sd->encrypted_path[ciphertext_len] = '\0';
+
+ if (!disk_link->name)
+ disk_link->name = (unsigned char *)sd;
+ return 0;
+}
+EXPORT_SYMBOL_GPL(__fscrypt_encrypt_symlink);
diff --git a/include/linux/fscrypt.h b/include/linux/fscrypt.h
index 071ebabfc287..6a678d0e956a 100644
--- a/include/linux/fscrypt.h
+++ b/include/linux/fscrypt.h
@@ -196,4 +196,68 @@ static inline int fscrypt_prepare_setattr(struct dentry *dentry,
return 0;
}
+/**
+ * fscrypt_prepare_symlink - prepare to create a possibly-encrypted symlink
+ * @dir: directory in which the symlink is being created
+ * @target: plaintext symlink target
+ * @len: length of @target excluding null terminator
+ * @max_len: space the filesystem has available to store the symlink target
+ * @disk_link: (out) the on-disk symlink target being prepared
+ *
+ * This function computes the size the symlink target will require on-disk,
+ * stores it in @disk_link->len, and validates it against @max_len. An
+ * encrypted symlink may be longer than the original.
+ *
+ * Additionally, @disk_link->name is set to @target if the symlink will be
+ * unencrypted, but left NULL if the symlink will be encrypted. For encrypted
+ * symlinks, the filesystem must call fscrypt_encrypt_symlink() to create the
+ * on-disk target later. (The reason for the two-step process is that some
+ * filesystems need to know the size of the symlink target before creating the
+ * inode, e.g. to determine whether it will be a "fast" or "slow" symlink.)
+ *
+ * Return: 0 on success, -ENAMETOOLONG if the symlink target is too long,
+ * -ENOKEY if the encryption key is missing, or another -errno code if a problem
+ * occurred while setting up the encryption key.
+ */
+static inline int fscrypt_prepare_symlink(struct inode *dir,
+ const char *target,
+ unsigned int len,
+ unsigned int max_len,
+ struct fscrypt_str *disk_link)
+{
+ if (IS_ENCRYPTED(dir) || fscrypt_dummy_context_enabled(dir))
+ return __fscrypt_prepare_symlink(dir, len, max_len, disk_link);
+
+ disk_link->name = (unsigned char *)target;
+ disk_link->len = len + 1;
+ if (disk_link->len > max_len)
+ return -ENAMETOOLONG;
+ return 0;
+}
+
+/**
+ * fscrypt_encrypt_symlink - encrypt the symlink target if needed
+ * @inode: symlink inode
+ * @target: plaintext symlink target
+ * @len: length of @target excluding null terminator
+ * @disk_link: (in/out) the on-disk symlink target being prepared
+ *
+ * If the symlink target needs to be encrypted, then this function encrypts it
+ * into @disk_link->name. fscrypt_prepare_symlink() must have been called
+ * previously to compute @disk_link->len. If the filesystem did not allocate a
+ * buffer for @disk_link->name after calling fscrypt_prepare_link(), then one
+ * will be kmalloc()'ed and the filesystem will be responsible for freeing it.
+ *
+ * Return: 0 on success, -errno on failure
+ */
+static inline int fscrypt_encrypt_symlink(struct inode *inode,
+ const char *target,
+ unsigned int len,
+ struct fscrypt_str *disk_link)
+{
+ if (IS_ENCRYPTED(inode))
+ return __fscrypt_encrypt_symlink(inode, target, len, disk_link);
+ return 0;
+}
+
#endif /* _LINUX_FSCRYPT_H */
diff --git a/include/linux/fscrypt_notsupp.h b/include/linux/fscrypt_notsupp.h
index 81e02201b215..02ec0aa894d8 100644
--- a/include/linux/fscrypt_notsupp.h
+++ b/include/linux/fscrypt_notsupp.h
@@ -223,4 +223,20 @@ static inline int __fscrypt_prepare_lookup(struct inode *dir,
return -EOPNOTSUPP;
}
+static inline int __fscrypt_prepare_symlink(struct inode *dir,
+ unsigned int len,
+ unsigned int max_len,
+ struct fscrypt_str *disk_link)
+{
+ return -EOPNOTSUPP;
+}
+
+static inline int __fscrypt_encrypt_symlink(struct inode *inode,
+ const char *target,
+ unsigned int len,
+ struct fscrypt_str *disk_link)
+{
+ return -EOPNOTSUPP;
+}
+
#endif /* _LINUX_FSCRYPT_NOTSUPP_H */
diff --git a/include/linux/fscrypt_supp.h b/include/linux/fscrypt_supp.h
index 562a9bc04560..7e0b67ccd816 100644
--- a/include/linux/fscrypt_supp.h
+++ b/include/linux/fscrypt_supp.h
@@ -205,5 +205,11 @@ extern int __fscrypt_prepare_rename(struct inode *old_dir,
struct dentry *new_dentry,
unsigned int flags);
extern int __fscrypt_prepare_lookup(struct inode *dir, struct dentry *dentry);
+extern int __fscrypt_prepare_symlink(struct inode *dir, unsigned int len,
+ unsigned int max_len,
+ struct fscrypt_str *disk_link);
+extern int __fscrypt_encrypt_symlink(struct inode *inode, const char *target,
+ unsigned int len,
+ struct fscrypt_str *disk_link);
#endif /* _LINUX_FSCRYPT_SUPP_H */
--
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
^ permalink raw reply related [flat|nested] 25+ messages in thread* [PATCH 11/24] fscrypt: new helper function - fscrypt_get_symlink()
2017-12-15 17:42 [PATCH 00/24] fscrypt: symlink helpers and fscrypt.h cleanup Eric Biggers
` (9 preceding siblings ...)
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 12/24] ext4: switch to fscrypt ->symlink() helper functions Eric Biggers
` (12 subsequent siblings)
23 siblings, 0 replies; 25+ messages in thread
From: Eric Biggers @ 2017-12-15 17:42 UTC (permalink / raw)
To: linux-fscrypt
Cc: Theodore Y . Ts'o, Eric Biggers, linux-f2fs-devel, linux-mtd,
Jaegeuk Kim, linux-ext4
From: Eric Biggers <ebiggers@google.com>
Filesystems also have duplicate code to support ->get_link() on
encrypted symlinks. Factor it out into a new function
fscrypt_get_symlink(). It takes in the contents of the encrypted
symlink on-disk and provides the target (decrypted or encoded) that
should be returned from ->get_link().
Signed-off-by: Eric Biggers <ebiggers@google.com>
---
fs/crypto/hooks.c | 73 +++++++++++++++++++++++++++++++++++++++++
include/linux/fscrypt_notsupp.h | 8 +++++
include/linux/fscrypt_supp.h | 3 ++
3 files changed, 84 insertions(+)
diff --git a/fs/crypto/hooks.c b/fs/crypto/hooks.c
index 483e87d40f03..0f103a5cb1aa 100644
--- a/fs/crypto/hooks.c
+++ b/fs/crypto/hooks.c
@@ -196,3 +196,76 @@ int __fscrypt_encrypt_symlink(struct inode *inode, const char *target,
return 0;
}
EXPORT_SYMBOL_GPL(__fscrypt_encrypt_symlink);
+
+/**
+ * fscrypt_get_symlink - get the target of an encrypted symlink
+ * @inode: the symlink inode
+ * @caddr: the on-disk contents of the symlink
+ * @max_size: size of @caddr buffer
+ * @done: if successful, will be set up to free the returned target
+ *
+ * If the symlink's encryption key is available, we decrypt its target.
+ * Otherwise, we encode its target for presentation.
+ *
+ * This may sleep, so the filesystem must have dropped out of RCU mode already.
+ *
+ * Return: the presentable symlink target or an ERR_PTR()
+ */
+const char *fscrypt_get_symlink(struct inode *inode, const void *caddr,
+ unsigned int max_size,
+ struct delayed_call *done)
+{
+ const struct fscrypt_symlink_data *sd;
+ struct fscrypt_str cstr, pstr;
+ int err;
+
+ /* This is for encrypted symlinks only */
+ if (WARN_ON(!IS_ENCRYPTED(inode)))
+ return ERR_PTR(-EINVAL);
+
+ /*
+ * Try to set up the symlink's encryption key, but we can continue
+ * regardless of whether the key is available or not.
+ */
+ err = fscrypt_get_encryption_info(inode);
+ if (err)
+ return ERR_PTR(err);
+
+ /*
+ * For historical reasons, encrypted symlink targets are prefixed with
+ * the ciphertext length, even though this is redundant with i_size.
+ */
+
+ if (max_size < sizeof(*sd))
+ return ERR_PTR(-EUCLEAN);
+ sd = caddr;
+ cstr.name = (unsigned char *)sd->encrypted_path;
+ cstr.len = le16_to_cpu(sd->len);
+
+ if (cstr.len == 0)
+ return ERR_PTR(-EUCLEAN);
+
+ if (cstr.len + sizeof(*sd) - 1 > max_size)
+ return ERR_PTR(-EUCLEAN);
+
+ err = fscrypt_fname_alloc_buffer(inode, cstr.len, &pstr);
+ if (err)
+ return ERR_PTR(err);
+
+ err = fscrypt_fname_disk_to_usr(inode, 0, 0, &cstr, &pstr);
+ if (err)
+ goto err_kfree;
+
+ err = -EUCLEAN;
+ if (pstr.name[0] == '\0')
+ goto err_kfree;
+
+ pstr.name[pstr.len] = '\0';
+ set_delayed_call(done, kfree_link, pstr.name);
+ return pstr.name;
+
+err_kfree:
+ kfree(pstr.name);
+ return ERR_PTR(err);
+}
+EXPORT_SYMBOL_GPL(fscrypt_get_symlink);
diff --git a/include/linux/fscrypt_notsupp.h b/include/linux/fscrypt_notsupp.h
index 02ec0aa894d8..dd106640c6ea 100644
--- a/include/linux/fscrypt_notsupp.h
+++ b/include/linux/fscrypt_notsupp.h
@@ -239,4 +239,12 @@ static inline int __fscrypt_encrypt_symlink(struct inode *inode,
return -EOPNOTSUPP;
}
+static inline const char *fscrypt_get_symlink(struct inode *inode,
+ const void *caddr,
+ unsigned int max_size,
+ struct delayed_call *done)
+{
+ return ERR_PTR(-EOPNOTSUPP);
+}
+
#endif /* _LINUX_FSCRYPT_NOTSUPP_H */
diff --git a/include/linux/fscrypt_supp.h b/include/linux/fscrypt_supp.h
index 7e0b67ccd816..dc2babf3f7d3 100644
--- a/include/linux/fscrypt_supp.h
+++ b/include/linux/fscrypt_supp.h
@@ -211,5 +211,8 @@ extern int __fscrypt_prepare_symlink(struct inode *dir, unsigned int len,
extern int __fscrypt_encrypt_symlink(struct inode *inode, const char *target,
unsigned int len,
struct fscrypt_str *disk_link);
+extern const char *fscrypt_get_symlink(struct inode *inode, const void *caddr,
+ unsigned int max_size,
+ struct delayed_call *done);
#endif /* _LINUX_FSCRYPT_SUPP_H */
--
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
^ permalink raw reply related [flat|nested] 25+ messages in thread* [PATCH 12/24] ext4: switch to fscrypt ->symlink() helper functions
2017-12-15 17:42 [PATCH 00/24] fscrypt: symlink helpers and fscrypt.h cleanup Eric Biggers
` (10 preceding siblings ...)
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 13/24] ext4: switch to fscrypt_get_symlink() Eric Biggers
` (11 subsequent siblings)
23 siblings, 0 replies; 25+ messages in thread
From: Eric Biggers @ 2017-12-15 17:42 UTC (permalink / raw)
To: linux-fscrypt
Cc: Theodore Y . Ts'o, Eric Biggers, linux-f2fs-devel, linux-mtd,
Jaegeuk Kim, linux-ext4
From: Eric Biggers <ebiggers@google.com>
Signed-off-by: Eric Biggers <ebiggers@google.com>
---
fs/ext4/namei.c | 58 +++++++++++++++------------------------------------------
1 file changed, 15 insertions(+), 43 deletions(-)
diff --git a/fs/ext4/namei.c b/fs/ext4/namei.c
index 798b3ac680db..e291bb90a233 100644
--- a/fs/ext4/namei.c
+++ b/fs/ext4/namei.c
@@ -3052,39 +3052,19 @@ static int ext4_symlink(struct inode *dir,
struct inode *inode;
int err, len = strlen(symname);
int credits;
- bool encryption_required;
struct fscrypt_str disk_link;
- struct fscrypt_symlink_data *sd = NULL;
if (unlikely(ext4_forced_shutdown(EXT4_SB(dir->i_sb))))
return -EIO;
- disk_link.len = len + 1;
- disk_link.name = (char *) symname;
-
- encryption_required = (ext4_encrypted_inode(dir) ||
- DUMMY_ENCRYPTION_ENABLED(EXT4_SB(dir->i_sb)));
- if (encryption_required) {
- err = fscrypt_get_encryption_info(dir);
- if (err)
- return err;
- if (!fscrypt_has_encryption_key(dir))
- return -ENOKEY;
- disk_link.len = (fscrypt_fname_encrypted_size(dir, len) +
- sizeof(struct fscrypt_symlink_data));
- sd = kzalloc(disk_link.len, GFP_KERNEL);
- if (!sd)
- return -ENOMEM;
- }
-
- if (disk_link.len > dir->i_sb->s_blocksize) {
- err = -ENAMETOOLONG;
- goto err_free_sd;
- }
+ err = fscrypt_prepare_symlink(dir, symname, len, dir->i_sb->s_blocksize,
+ &disk_link);
+ if (err)
+ return err;
err = dquot_initialize(dir);
if (err)
- goto err_free_sd;
+ return err;
if ((disk_link.len > EXT4_N_BLOCKS * 4)) {
/*
@@ -3113,27 +3093,18 @@ static int ext4_symlink(struct inode *dir,
if (IS_ERR(inode)) {
if (handle)
ext4_journal_stop(handle);
- err = PTR_ERR(inode);
- goto err_free_sd;
+ return PTR_ERR(inode);
}
- if (encryption_required) {
- struct qstr istr;
- struct fscrypt_str ostr =
- FSTR_INIT(sd->encrypted_path, disk_link.len);
-
- istr.name = (const unsigned char *) symname;
- istr.len = len;
- err = fscrypt_fname_usr_to_disk(inode, &istr, &ostr);
+ if (IS_ENCRYPTED(inode)) {
+ err = fscrypt_encrypt_symlink(inode, symname, len, &disk_link);
if (err)
goto err_drop_inode;
- sd->len = cpu_to_le16(ostr.len);
- disk_link.name = (char *) sd;
inode->i_op = &ext4_encrypted_symlink_inode_operations;
}
if ((disk_link.len > EXT4_N_BLOCKS * 4)) {
- if (!encryption_required)
+ if (!IS_ENCRYPTED(inode))
inode->i_op = &ext4_symlink_inode_operations;
inode_nohighmem(inode);
ext4_set_aops(inode);
@@ -3175,7 +3146,7 @@ static int ext4_symlink(struct inode *dir,
} else {
/* clear the extent format for fast symlink */
ext4_clear_inode_flag(inode, EXT4_INODE_EXTENTS);
- if (!encryption_required) {
+ if (!IS_ENCRYPTED(inode)) {
inode->i_op = &ext4_fast_symlink_inode_operations;
inode->i_link = (char *)&EXT4_I(inode)->i_data;
}
@@ -3190,16 +3161,17 @@ static int ext4_symlink(struct inode *dir,
if (handle)
ext4_journal_stop(handle);
- kfree(sd);
- return err;
+ goto out_free_encrypted_link;
+
err_drop_inode:
if (handle)
ext4_journal_stop(handle);
clear_nlink(inode);
unlock_new_inode(inode);
iput(inode);
-err_free_sd:
- kfree(sd);
+out_free_encrypted_link:
+ if (disk_link.name != (unsigned char *)symname)
+ kfree(disk_link.name);
return err;
}
--
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
^ permalink raw reply related [flat|nested] 25+ messages in thread* [PATCH 13/24] ext4: switch to fscrypt_get_symlink()
2017-12-15 17:42 [PATCH 00/24] fscrypt: symlink helpers and fscrypt.h cleanup Eric Biggers
` (11 preceding siblings ...)
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 14/24] f2fs: switch to fscrypt ->symlink() helper functions Eric Biggers
` (10 subsequent siblings)
23 siblings, 0 replies; 25+ messages in thread
From: Eric Biggers @ 2017-12-15 17:42 UTC (permalink / raw)
To: linux-fscrypt
Cc: Theodore Y . Ts'o, Eric Biggers, linux-f2fs-devel, linux-mtd,
Jaegeuk Kim, linux-ext4
From: Eric Biggers <ebiggers@google.com>
Signed-off-by: Eric Biggers <ebiggers@google.com>
---
fs/ext4/symlink.c | 43 ++++++-------------------------------------
1 file changed, 6 insertions(+), 37 deletions(-)
diff --git a/fs/ext4/symlink.c b/fs/ext4/symlink.c
index a2006c9af1d9..dd05af983092 100644
--- a/fs/ext4/symlink.c
+++ b/fs/ext4/symlink.c
@@ -28,59 +28,28 @@ static const char *ext4_encrypted_get_link(struct dentry *dentry,
struct delayed_call *done)
{
struct page *cpage = NULL;
- char *caddr, *paddr = NULL;
- struct fscrypt_str cstr, pstr;
- struct fscrypt_symlink_data *sd;
- int res;
- u32 max_size = inode->i_sb->s_blocksize;
+ const void *caddr;
+ unsigned int max_size;
+ const char *paddr;
if (!dentry)
return ERR_PTR(-ECHILD);
- res = fscrypt_get_encryption_info(inode);
- if (res)
- return ERR_PTR(res);
-
if (ext4_inode_is_fast_symlink(inode)) {
- caddr = (char *) EXT4_I(inode)->i_data;
+ caddr = EXT4_I(inode)->i_data;
max_size = sizeof(EXT4_I(inode)->i_data);
} else {
cpage = read_mapping_page(inode->i_mapping, 0, NULL);
if (IS_ERR(cpage))
return ERR_CAST(cpage);
caddr = page_address(cpage);
+ max_size = inode->i_sb->s_blocksize;
}
- /* Symlink is encrypted */
- sd = (struct fscrypt_symlink_data *)caddr;
- cstr.name = sd->encrypted_path;
- cstr.len = le16_to_cpu(sd->len);
- if ((cstr.len + sizeof(struct fscrypt_symlink_data) - 1) > max_size) {
- /* Symlink data on the disk is corrupted */
- res = -EFSCORRUPTED;
- goto errout;
- }
-
- res = fscrypt_fname_alloc_buffer(inode, cstr.len, &pstr);
- if (res)
- goto errout;
- paddr = pstr.name;
-
- res = fscrypt_fname_disk_to_usr(inode, 0, 0, &cstr, &pstr);
- if (res)
- goto errout;
-
- /* Null-terminate the name */
- paddr[pstr.len] = '\0';
+ paddr = fscrypt_get_symlink(inode, caddr, max_size, done);
if (cpage)
put_page(cpage);
- set_delayed_call(done, kfree_link, paddr);
return paddr;
-errout:
- if (cpage)
- put_page(cpage);
- kfree(paddr);
- return ERR_PTR(res);
}
const struct inode_operations ext4_encrypted_symlink_inode_operations = {
--
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
^ permalink raw reply related [flat|nested] 25+ messages in thread* [PATCH 14/24] f2fs: switch to fscrypt ->symlink() helper functions
2017-12-15 17:42 [PATCH 00/24] fscrypt: symlink helpers and fscrypt.h cleanup Eric Biggers
` (12 preceding siblings ...)
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 15/24] f2fs: switch to fscrypt_get_symlink() Eric Biggers
` (9 subsequent siblings)
23 siblings, 0 replies; 25+ messages in thread
From: Eric Biggers @ 2017-12-15 17:42 UTC (permalink / raw)
To: linux-fscrypt
Cc: Theodore Y . Ts'o, Eric Biggers, linux-f2fs-devel, linux-mtd,
Jaegeuk Kim, linux-ext4
From: Eric Biggers <ebiggers@google.com>
Signed-off-by: Eric Biggers <ebiggers@google.com>
---
fs/f2fs/namei.c | 66 ++++++++++++++-------------------------------------------
1 file changed, 16 insertions(+), 50 deletions(-)
diff --git a/fs/f2fs/namei.c b/fs/f2fs/namei.c
index 28bdf8828e73..5b114844806c 100644
--- a/fs/f2fs/namei.c
+++ b/fs/f2fs/namei.c
@@ -496,27 +496,16 @@ static int f2fs_symlink(struct inode *dir, struct dentry *dentry,
struct f2fs_sb_info *sbi = F2FS_I_SB(dir);
struct inode *inode;
size_t len = strlen(symname);
- struct fscrypt_str disk_link = FSTR_INIT((char *)symname, len + 1);
- struct fscrypt_symlink_data *sd = NULL;
+ struct fscrypt_str disk_link;
int err;
if (unlikely(f2fs_cp_error(sbi)))
return -EIO;
- if (f2fs_encrypted_inode(dir)) {
- err = fscrypt_get_encryption_info(dir);
- if (err)
- return err;
-
- if (!fscrypt_has_encryption_key(dir))
- return -ENOKEY;
-
- disk_link.len = (fscrypt_fname_encrypted_size(dir, len) +
- sizeof(struct fscrypt_symlink_data));
- }
-
- if (disk_link.len > dir->i_sb->s_blocksize)
- return -ENAMETOOLONG;
+ err = fscrypt_prepare_symlink(dir, symname, len, dir->i_sb->s_blocksize,
+ &disk_link);
+ if (err)
+ return err;
err = dquot_initialize(dir);
if (err)
@@ -526,7 +515,7 @@ static int f2fs_symlink(struct inode *dir, struct dentry *dentry,
if (IS_ERR(inode))
return PTR_ERR(inode);
- if (f2fs_encrypted_inode(inode))
+ if (IS_ENCRYPTED(inode))
inode->i_op = &f2fs_encrypted_symlink_inode_operations;
else
inode->i_op = &f2fs_symlink_inode_operations;
@@ -536,38 +525,13 @@ static int f2fs_symlink(struct inode *dir, struct dentry *dentry,
f2fs_lock_op(sbi);
err = f2fs_add_link(dentry, inode);
if (err)
- goto out;
+ goto out_handle_failed_inode;
f2fs_unlock_op(sbi);
alloc_nid_done(sbi, inode->i_ino);
- if (f2fs_encrypted_inode(inode)) {
- struct qstr istr = QSTR_INIT(symname, len);
- struct fscrypt_str ostr;
-
- sd = kzalloc(disk_link.len, GFP_NOFS);
- if (!sd) {
- err = -ENOMEM;
- goto err_out;
- }
-
- err = fscrypt_get_encryption_info(inode);
- if (err)
- goto err_out;
-
- if (!fscrypt_has_encryption_key(inode)) {
- err = -ENOKEY;
- goto err_out;
- }
-
- ostr.name = sd->encrypted_path;
- ostr.len = disk_link.len;
- err = fscrypt_fname_usr_to_disk(inode, &istr, &ostr);
- if (err)
- goto err_out;
-
- sd->len = cpu_to_le16(ostr.len);
- disk_link.name = (char *)sd;
- }
+ err = fscrypt_encrypt_symlink(inode, symname, len, &disk_link);
+ if (err)
+ goto err_out;
err = page_symlink(inode, disk_link.name, disk_link.len);
@@ -594,12 +558,14 @@ static int f2fs_symlink(struct inode *dir, struct dentry *dentry,
f2fs_unlink(dir, dentry);
}
- kfree(sd);
-
f2fs_balance_fs(sbi, true);
- return err;
-out:
+ goto out_free_encrypted_link;
+
+out_handle_failed_inode:
handle_failed_inode(inode);
+out_free_encrypted_link:
+ if (disk_link.name != (unsigned char *)symname)
+ kfree(disk_link.name);
return err;
}
--
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
^ permalink raw reply related [flat|nested] 25+ messages in thread* [PATCH 15/24] f2fs: switch to fscrypt_get_symlink()
2017-12-15 17:42 [PATCH 00/24] fscrypt: symlink helpers and fscrypt.h cleanup Eric Biggers
` (13 preceding siblings ...)
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 16/24] ubifs: free the encrypted symlink target Eric Biggers
` (8 subsequent siblings)
23 siblings, 0 replies; 25+ messages in thread
From: Eric Biggers @ 2017-12-15 17:42 UTC (permalink / raw)
To: linux-fscrypt
Cc: Theodore Y . Ts'o, Eric Biggers, linux-f2fs-devel, linux-mtd,
Jaegeuk Kim, linux-ext4
From: Eric Biggers <ebiggers@google.com>
Signed-off-by: Eric Biggers <ebiggers@google.com>
---
fs/f2fs/namei.c | 66 ++++++++-------------------------------------------------
1 file changed, 9 insertions(+), 57 deletions(-)
diff --git a/fs/f2fs/namei.c b/fs/f2fs/namei.c
index 5b114844806c..37816d2ebb93 100644
--- a/fs/f2fs/namei.c
+++ b/fs/f2fs/namei.c
@@ -1137,68 +1137,20 @@ static const char *f2fs_encrypted_get_link(struct dentry *dentry,
struct inode *inode,
struct delayed_call *done)
{
- struct page *cpage = NULL;
- char *caddr, *paddr = NULL;
- struct fscrypt_str cstr = FSTR_INIT(NULL, 0);
- struct fscrypt_str pstr = FSTR_INIT(NULL, 0);
- struct fscrypt_symlink_data *sd;
- u32 max_size = inode->i_sb->s_blocksize;
- int res;
+ struct page *page;
+ const char *target;
if (!dentry)
return ERR_PTR(-ECHILD);
- res = fscrypt_get_encryption_info(inode);
- if (res)
- return ERR_PTR(res);
-
- cpage = read_mapping_page(inode->i_mapping, 0, NULL);
- if (IS_ERR(cpage))
- return ERR_CAST(cpage);
- caddr = page_address(cpage);
-
- /* Symlink is encrypted */
- sd = (struct fscrypt_symlink_data *)caddr;
- cstr.name = sd->encrypted_path;
- cstr.len = le16_to_cpu(sd->len);
-
- /* this is broken symlink case */
- if (unlikely(cstr.len == 0)) {
- res = -ENOENT;
- goto errout;
- }
-
- if ((cstr.len + sizeof(struct fscrypt_symlink_data) - 1) > max_size) {
- /* Symlink data on the disk is corrupted */
- res = -EIO;
- goto errout;
- }
- res = fscrypt_fname_alloc_buffer(inode, cstr.len, &pstr);
- if (res)
- goto errout;
-
- res = fscrypt_fname_disk_to_usr(inode, 0, 0, &cstr, &pstr);
- if (res)
- goto errout;
-
- /* this is broken symlink case */
- if (unlikely(pstr.name[0] == 0)) {
- res = -ENOENT;
- goto errout;
- }
-
- paddr = pstr.name;
-
- /* Null-terminate the name */
- paddr[pstr.len] = '\0';
+ page = read_mapping_page(inode->i_mapping, 0, NULL);
+ if (IS_ERR(page))
+ return ERR_CAST(page);
- put_page(cpage);
- set_delayed_call(done, kfree_link, paddr);
- return paddr;
-errout:
- fscrypt_fname_free_buffer(&pstr);
- put_page(cpage);
- return ERR_PTR(res);
+ target = fscrypt_get_symlink(inode, page_address(page),
+ inode->i_sb->s_blocksize, done);
+ put_page(page);
+ return target;
}
const struct inode_operations f2fs_encrypted_symlink_inode_operations = {
--
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
^ permalink raw reply related [flat|nested] 25+ messages in thread* [PATCH 16/24] ubifs: free the encrypted symlink target
2017-12-15 17:42 [PATCH 00/24] fscrypt: symlink helpers and fscrypt.h cleanup Eric Biggers
` (14 preceding siblings ...)
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 17/24] ubifs: switch to fscrypt ->symlink() helper functions Eric Biggers
` (7 subsequent siblings)
23 siblings, 0 replies; 25+ messages in thread
From: Eric Biggers @ 2017-12-15 17:42 UTC (permalink / raw)
To: linux-fscrypt
Cc: Theodore Y . Ts'o, Jaegeuk Kim, linux-ext4, linux-f2fs-devel,
linux-mtd, Eric Biggers, stable
From: Eric Biggers <ebiggers@google.com>
ubifs_symlink() forgot to free the kmalloc()'ed buffer holding the
encrypted symlink target, creating a memory leak. Fix it.
(UBIFS could actually encrypt directly into ui->data, removing the
temporary buffer, but that is left for the patch that switches to use
the symlink helper functions.)
Fixes: ca7f85be8d6c ("ubifs: Add support for encrypted symlinks")
Cc: <stable@vger.kernel.org> # v4.10+
Signed-off-by: Eric Biggers <ebiggers@google.com>
---
fs/ubifs/dir.c | 10 ++++------
1 file changed, 4 insertions(+), 6 deletions(-)
diff --git a/fs/ubifs/dir.c b/fs/ubifs/dir.c
index 417fe0b29f23..ef820f803176 100644
--- a/fs/ubifs/dir.c
+++ b/fs/ubifs/dir.c
@@ -1216,10 +1216,8 @@ static int ubifs_symlink(struct inode *dir, struct dentry *dentry,
ostr.len = disk_link.len;
err = fscrypt_fname_usr_to_disk(inode, &istr, &ostr);
- if (err) {
- kfree(sd);
+ if (err)
goto out_inode;
- }
sd->len = cpu_to_le16(ostr.len);
disk_link.name = (char *)sd;
@@ -1251,11 +1249,10 @@ static int ubifs_symlink(struct inode *dir, struct dentry *dentry,
goto out_cancel;
mutex_unlock(&dir_ui->ui_mutex);
- ubifs_release_budget(c, &req);
insert_inode_hash(inode);
d_instantiate(dentry, inode);
- fscrypt_free_filename(&nm);
- return 0;
+ err = 0;
+ goto out_fname;
out_cancel:
dir->i_size -= sz_change;
@@ -1268,6 +1265,7 @@ static int ubifs_symlink(struct inode *dir, struct dentry *dentry,
fscrypt_free_filename(&nm);
out_budg:
ubifs_release_budget(c, &req);
+ kfree(sd);
return err;
}
--
2.15.1
^ permalink raw reply related [flat|nested] 25+ messages in thread* [PATCH 17/24] ubifs: switch to fscrypt ->symlink() helper functions
2017-12-15 17:42 [PATCH 00/24] fscrypt: symlink helpers and fscrypt.h cleanup Eric Biggers
` (15 preceding siblings ...)
2017-12-15 17:42 ` [PATCH 16/24] ubifs: free the encrypted symlink target 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
` (6 subsequent siblings)
23 siblings, 0 replies; 25+ messages in thread
From: Eric Biggers @ 2017-12-15 17:42 UTC (permalink / raw)
To: linux-fscrypt
Cc: Theodore Y . Ts'o, Eric Biggers, linux-f2fs-devel, linux-mtd,
Jaegeuk Kim, linux-ext4
From: Eric Biggers <ebiggers@google.com>
Signed-off-by: Eric Biggers <ebiggers@google.com>
---
fs/ubifs/dir.c | 55 ++++++++++++-------------------------------------------
1 file changed, 12 insertions(+), 43 deletions(-)
diff --git a/fs/ubifs/dir.c b/fs/ubifs/dir.c
index ef820f803176..518c10255881 100644
--- a/fs/ubifs/dir.c
+++ b/fs/ubifs/dir.c
@@ -1149,38 +1149,24 @@ static int ubifs_symlink(struct inode *dir, struct dentry *dentry,
struct ubifs_info *c = dir->i_sb->s_fs_info;
int err, len = strlen(symname);
int sz_change = CALC_DENT_SIZE(len);
- struct fscrypt_str disk_link = FSTR_INIT((char *)symname, len + 1);
- struct fscrypt_symlink_data *sd = NULL;
+ struct fscrypt_str disk_link;
struct ubifs_budget_req req = { .new_ino = 1, .new_dent = 1,
.new_ino_d = ALIGN(len, 8),
.dirtied_ino = 1 };
struct fscrypt_name nm;
- if (ubifs_crypt_is_encrypted(dir)) {
- err = fscrypt_get_encryption_info(dir);
- if (err)
- goto out_budg;
-
- if (!fscrypt_has_encryption_key(dir)) {
- err = -EPERM;
- goto out_budg;
- }
+ dbg_gen("dent '%pd', target '%s' in dir ino %lu", dentry,
+ symname, dir->i_ino);
- disk_link.len = (fscrypt_fname_encrypted_size(dir, len) +
- sizeof(struct fscrypt_symlink_data));
- }
+ err = fscrypt_prepare_symlink(dir, symname, len, UBIFS_MAX_INO_DATA,
+ &disk_link);
+ if (err)
+ return err;
/*
* Budget request settings: new inode, new direntry and changing parent
* directory inode.
*/
-
- dbg_gen("dent '%pd', target '%s' in dir ino %lu", dentry,
- symname, dir->i_ino);
-
- if (disk_link.len > UBIFS_MAX_INO_DATA)
- return -ENAMETOOLONG;
-
err = ubifs_budget_space(c, &req);
if (err)
return err;
@@ -1202,36 +1188,20 @@ static int ubifs_symlink(struct inode *dir, struct dentry *dentry,
goto out_inode;
}
- if (ubifs_crypt_is_encrypted(dir)) {
- struct qstr istr = QSTR_INIT(symname, len);
- struct fscrypt_str ostr;
-
- sd = kzalloc(disk_link.len, GFP_NOFS);
- if (!sd) {
- err = -ENOMEM;
- goto out_inode;
- }
-
- ostr.name = sd->encrypted_path;
- ostr.len = disk_link.len;
-
- err = fscrypt_fname_usr_to_disk(inode, &istr, &ostr);
+ if (IS_ENCRYPTED(inode)) {
+ disk_link.name = ui->data; /* encrypt directly into ui->data */
+ err = fscrypt_encrypt_symlink(inode, symname, len, &disk_link);
if (err)
goto out_inode;
-
- sd->len = cpu_to_le16(ostr.len);
- disk_link.name = (char *)sd;
} else {
+ memcpy(ui->data, disk_link.name, disk_link.len);
inode->i_link = ui->data;
}
- memcpy(ui->data, disk_link.name, disk_link.len);
- ((char *)ui->data)[disk_link.len - 1] = '\0';
-
/*
* The terminating zero byte is not written to the flash media and it
* is put just to make later in-memory string processing simpler. Thus,
- * data length is @len, not @len + %1.
+ * data length is @disk_link.len - 1, not @disk_link.len.
*/
ui->data_len = disk_link.len - 1;
inode->i_size = ubifs_inode(inode)->ui_size = disk_link.len - 1;
@@ -1265,7 +1235,6 @@ static int ubifs_symlink(struct inode *dir, struct dentry *dentry,
fscrypt_free_filename(&nm);
out_budg:
ubifs_release_budget(c, &req);
- kfree(sd);
return err;
}
--
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
^ permalink raw reply related [flat|nested] 25+ messages in thread* [PATCH 18/24] ubifs: switch to fscrypt_get_symlink()
2017-12-15 17:42 [PATCH 00/24] fscrypt: symlink helpers and fscrypt.h cleanup Eric Biggers
` (16 preceding siblings ...)
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 19/24] fscrypt: remove fscrypt_fname_usr_to_disk() Eric Biggers
` (5 subsequent siblings)
23 siblings, 0 replies; 25+ messages in thread
From: Eric Biggers @ 2017-12-15 17:42 UTC (permalink / raw)
To: linux-fscrypt
Cc: Theodore Y . Ts'o, Eric Biggers, linux-f2fs-devel, linux-mtd,
Jaegeuk Kim, linux-ext4
From: Eric Biggers <ebiggers@google.com>
Signed-off-by: Eric Biggers <ebiggers@google.com>
---
fs/ubifs/file.c | 36 ++----------------------------------
1 file changed, 2 insertions(+), 34 deletions(-)
diff --git a/fs/ubifs/file.c b/fs/ubifs/file.c
index dfe85069586e..3cfc578c42ea 100644
--- a/fs/ubifs/file.c
+++ b/fs/ubifs/file.c
@@ -1662,49 +1662,17 @@ static const char *ubifs_get_link(struct dentry *dentry,
struct inode *inode,
struct delayed_call *done)
{
- int err;
- struct fscrypt_symlink_data *sd;
struct ubifs_inode *ui = ubifs_inode(inode);
- struct fscrypt_str cstr;
- struct fscrypt_str pstr;
- if (!ubifs_crypt_is_encrypted(inode))
+ if (!IS_ENCRYPTED(inode))
return ui->data;
if (!dentry)
return ERR_PTR(-ECHILD);
- err = fscrypt_get_encryption_info(inode);
- if (err)
- return ERR_PTR(err);
-
- sd = (struct fscrypt_symlink_data *)ui->data;
- cstr.name = sd->encrypted_path;
- cstr.len = le16_to_cpu(sd->len);
-
- if (cstr.len == 0)
- return ERR_PTR(-ENOENT);
-
- if ((cstr.len + sizeof(struct fscrypt_symlink_data) - 1) > ui->data_len)
- return ERR_PTR(-EIO);
-
- err = fscrypt_fname_alloc_buffer(inode, cstr.len, &pstr);
- if (err)
- return ERR_PTR(err);
-
- err = fscrypt_fname_disk_to_usr(inode, 0, 0, &cstr, &pstr);
- if (err) {
- fscrypt_fname_free_buffer(&pstr);
- return ERR_PTR(err);
- }
-
- pstr.name[pstr.len] = '\0';
-
- set_delayed_call(done, kfree_link, pstr.name);
- return pstr.name;
+ return fscrypt_get_symlink(inode, ui->data, ui->data_len, done);
}
-
const struct address_space_operations ubifs_file_address_operations = {
.readpage = ubifs_readpage,
.writepage = ubifs_writepage,
--
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
^ permalink raw reply related [flat|nested] 25+ messages in thread* [PATCH 19/24] fscrypt: remove fscrypt_fname_usr_to_disk()
2017-12-15 17:42 [PATCH 00/24] fscrypt: symlink helpers and fscrypt.h cleanup Eric Biggers
` (17 preceding siblings ...)
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 20/24] fscrypt: move fscrypt_symlink_data to fscrypt_private.h Eric Biggers
` (4 subsequent siblings)
23 siblings, 0 replies; 25+ messages in thread
From: Eric Biggers @ 2017-12-15 17:42 UTC (permalink / raw)
To: linux-fscrypt
Cc: Theodore Y . Ts'o, Eric Biggers, linux-f2fs-devel, linux-mtd,
Jaegeuk Kim, linux-ext4
From: Eric Biggers <ebiggers@google.com>
fscrypt_fname_usr_to_disk() sounded very generic but was actually only
used to encrypt symlinks. Remove it now that all filesystems have been
switched over to fscrypt_encrypt_symlink().
Signed-off-by: Eric Biggers <ebiggers@google.com>
---
fs/crypto/fname.c | 29 -----------------------------
include/linux/fscrypt_notsupp.h | 7 -------
include/linux/fscrypt_supp.h | 2 --
3 files changed, 38 deletions(-)
diff --git a/fs/crypto/fname.c b/fs/crypto/fname.c
index 62f13d533439..cae7d1bcc8c5 100644
--- a/fs/crypto/fname.c
+++ b/fs/crypto/fname.c
@@ -311,35 +311,6 @@ int fscrypt_fname_disk_to_usr(struct inode *inode,
}
EXPORT_SYMBOL(fscrypt_fname_disk_to_usr);
-/**
- * fscrypt_fname_usr_to_disk() - converts a filename from user space to disk
- * space
- *
- * The caller must have allocated sufficient memory for the @oname string.
- *
- * Return: 0 on success, -errno on failure
- */
-int fscrypt_fname_usr_to_disk(struct inode *inode,
- const struct qstr *iname,
- struct fscrypt_str *oname)
-{
- if (fscrypt_is_dot_dotdot(iname)) {
- oname->name[0] = '.';
- oname->name[iname->len - 1] = '.';
- oname->len = iname->len;
- return 0;
- }
- if (inode->i_crypt_info)
- return fname_encrypt(inode, iname, oname);
- /*
- * Without a proper key, a user is not allowed to modify the filenames
- * in a directory. Consequently, a user space name cannot be mapped to
- * a disk-space name
- */
- return -ENOKEY;
-}
-EXPORT_SYMBOL(fscrypt_fname_usr_to_disk);
-
/**
* fscrypt_setup_filename() - prepare to search a possibly encrypted directory
* @dir: the directory that will be searched
diff --git a/include/linux/fscrypt_notsupp.h b/include/linux/fscrypt_notsupp.h
index dd106640c6ea..0962f504aa91 100644
--- a/include/linux/fscrypt_notsupp.h
+++ b/include/linux/fscrypt_notsupp.h
@@ -159,13 +159,6 @@ static inline int fscrypt_fname_disk_to_usr(struct inode *inode,
return -EOPNOTSUPP;
}
-static inline int fscrypt_fname_usr_to_disk(struct inode *inode,
- const struct qstr *iname,
- struct fscrypt_str *oname)
-{
- return -EOPNOTSUPP;
-}
-
static inline bool fscrypt_match_name(const struct fscrypt_name *fname,
const u8 *de_name, u32 de_name_len)
{
diff --git a/include/linux/fscrypt_supp.h b/include/linux/fscrypt_supp.h
index dc2babf3f7d3..e00191deb0d6 100644
--- a/include/linux/fscrypt_supp.h
+++ b/include/linux/fscrypt_supp.h
@@ -113,8 +113,6 @@ extern int fscrypt_fname_alloc_buffer(const struct inode *, u32,
extern void fscrypt_fname_free_buffer(struct fscrypt_str *);
extern int fscrypt_fname_disk_to_usr(struct inode *, u32, u32,
const struct fscrypt_str *, struct fscrypt_str *);
-extern int fscrypt_fname_usr_to_disk(struct inode *, const struct qstr *,
- struct fscrypt_str *);
#define FSCRYPT_FNAME_MAX_UNDIGESTED_SIZE 32
--
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
^ permalink raw reply related [flat|nested] 25+ messages in thread* [PATCH 20/24] fscrypt: move fscrypt_symlink_data to fscrypt_private.h
2017-12-15 17:42 [PATCH 00/24] fscrypt: symlink helpers and fscrypt.h cleanup Eric Biggers
` (18 preceding siblings ...)
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 21/24] fscrypt: calculate NUL-padding length in one place only Eric Biggers
` (3 subsequent siblings)
23 siblings, 0 replies; 25+ messages in thread
From: Eric Biggers @ 2017-12-15 17:42 UTC (permalink / raw)
To: linux-fscrypt
Cc: Theodore Y . Ts'o, Eric Biggers, linux-f2fs-devel, linux-mtd,
Jaegeuk Kim, linux-ext4
From: Eric Biggers <ebiggers@google.com>
Now that all filesystems have been converted to use the symlink helper
functions, they no longer need the declaration of 'struct
fscrypt_symlink_data'. Move it from fscrypt.h to fscrypt_private.h.
Signed-off-by: Eric Biggers <ebiggers@google.com>
---
fs/crypto/fscrypt_private.h | 9 +++++++++
include/linux/fscrypt.h | 9 ---------
2 files changed, 9 insertions(+), 9 deletions(-)
diff --git a/fs/crypto/fscrypt_private.h b/fs/crypto/fscrypt_private.h
index 6995bca5006b..cec9ce309f41 100644
--- a/fs/crypto/fscrypt_private.h
+++ b/fs/crypto/fscrypt_private.h
@@ -50,6 +50,15 @@ struct fscrypt_context {
#define FS_ENCRYPTION_CONTEXT_FORMAT_V1 1
+/**
+ * For encrypted symlinks, the ciphertext length is stored at the beginning
+ * of the string in little-endian format.
+ */
+struct fscrypt_symlink_data {
+ __le16 len;
+ char encrypted_path[1];
+} __packed;
+
/*
* A pointer to this structure is stored in the file system's in-core
* representation of an inode.
diff --git a/include/linux/fscrypt.h b/include/linux/fscrypt.h
index 6a678d0e956a..952ab97af325 100644
--- a/include/linux/fscrypt.h
+++ b/include/linux/fscrypt.h
@@ -21,15 +21,6 @@
struct fscrypt_ctx;
struct fscrypt_info;
-/**
- * For encrypted symlinks, the ciphertext length is stored at the beginning
- * of the string in little-endian format.
- */
-struct fscrypt_symlink_data {
- __le16 len;
- char encrypted_path[1];
-} __packed;
-
struct fscrypt_str {
unsigned char *name;
u32 len;
--
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
^ permalink raw reply related [flat|nested] 25+ messages in thread* [PATCH 21/24] fscrypt: calculate NUL-padding length in one place only
2017-12-15 17:42 [PATCH 00/24] fscrypt: symlink helpers and fscrypt.h cleanup Eric Biggers
` (19 preceding siblings ...)
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 22/24] fscrypt: define fscrypt_fname_alloc_buffer() to be for presented names Eric Biggers
` (2 subsequent siblings)
23 siblings, 0 replies; 25+ messages in thread
From: Eric Biggers @ 2017-12-15 17:42 UTC (permalink / raw)
To: linux-fscrypt
Cc: Theodore Y . Ts'o, Eric Biggers, linux-f2fs-devel, linux-mtd,
Jaegeuk Kim, linux-ext4
From: Eric Biggers <ebiggers@google.com>
Currently, when encrypting a filename (either a real filename or a
symlink target) we calculate the amount of NUL-padding twice: once
before encryption and once during encryption in fname_encrypt(). It is
needed before encryption to allocate the needed buffer size as well as
calculate the size the symlink target will take up on-disk before
creating the symlink inode. Calculating the size during encryption as
well is redundant.
Remove this redundancy by always calculating the exact size beforehand,
and making fname_encrypt() just add as much NUL padding as is needed to
fill the output buffer.
Signed-off-by: Eric Biggers <ebiggers@google.com>
---
fs/crypto/fname.c | 53 ++++++++++++++++++++++-----------------------
fs/crypto/fscrypt_private.h | 4 ++--
fs/crypto/hooks.c | 7 +-----
3 files changed, 29 insertions(+), 35 deletions(-)
diff --git a/fs/crypto/fname.c b/fs/crypto/fname.c
index cae7d1bcc8c5..65424b89a1d1 100644
--- a/fs/crypto/fname.c
+++ b/fs/crypto/fname.c
@@ -30,39 +30,29 @@ static inline bool fscrypt_is_dot_dotdot(const struct qstr *str)
/**
* fname_encrypt() - encrypt a filename
*
- * The caller must have allocated sufficient memory for the @oname string.
+ * The output buffer must be at least as large as the input buffer.
+ * Any extra space is filled with NUL padding before encryption.
*
* Return: 0 on success, -errno on failure
*/
-int fname_encrypt(struct inode *inode,
- const struct qstr *iname, struct fscrypt_str *oname)
+int fname_encrypt(struct inode *inode, const struct qstr *iname,
+ u8 *out, unsigned int olen)
{
struct skcipher_request *req = NULL;
DECLARE_CRYPTO_WAIT(wait);
- struct fscrypt_info *ci = inode->i_crypt_info;
- struct crypto_skcipher *tfm = ci->ci_ctfm;
+ struct crypto_skcipher *tfm = inode->i_crypt_info->ci_ctfm;
int res = 0;
char iv[FS_CRYPTO_BLOCK_SIZE];
struct scatterlist sg;
- int padding = 4 << (ci->ci_flags & FS_POLICY_FLAGS_PAD_MASK);
- unsigned int lim;
- unsigned int cryptlen;
-
- lim = inode->i_sb->s_cop->max_namelen(inode);
- if (iname->len <= 0 || iname->len > lim)
- return -EIO;
/*
* Copy the filename to the output buffer for encrypting in-place and
* pad it with the needed number of NUL bytes.
*/
- if (WARN_ON(oname->len < iname->len))
+ if (WARN_ON(olen < iname->len))
return -ENOBUFS;
- cryptlen = max_t(unsigned int, iname->len, FS_CRYPTO_BLOCK_SIZE);
- cryptlen = round_up(cryptlen, padding);
- cryptlen = min3(cryptlen, lim, oname->len);
- memcpy(oname->name, iname->name, iname->len);
- memset(oname->name + iname->len, 0, cryptlen - iname->len);
+ memcpy(out, iname->name, iname->len);
+ memset(out + iname->len, 0, olen - iname->len);
/* Initialize the IV */
memset(iv, 0, FS_CRYPTO_BLOCK_SIZE);
@@ -77,8 +67,8 @@ int fname_encrypt(struct inode *inode,
skcipher_request_set_callback(req,
CRYPTO_TFM_REQ_MAY_BACKLOG | CRYPTO_TFM_REQ_MAY_SLEEP,
crypto_req_done, &wait);
- sg_init_one(&sg, oname->name, cryptlen);
- skcipher_request_set_crypt(req, &sg, &sg, cryptlen, iv);
+ sg_init_one(&sg, out, olen);
+ skcipher_request_set_crypt(req, &sg, &sg, olen, iv);
/* Do the encryption */
res = crypto_wait_req(crypto_skcipher_encrypt(req), &wait);
@@ -89,7 +79,6 @@ int fname_encrypt(struct inode *inode,
return res;
}
- oname->len = cryptlen;
return 0;
}
@@ -354,11 +343,21 @@ int fscrypt_setup_filename(struct inode *dir, const struct qstr *iname,
return ret;
if (dir->i_crypt_info) {
- ret = fscrypt_fname_alloc_buffer(dir, iname->len,
- &fname->crypto_buf);
- if (ret)
- return ret;
- ret = fname_encrypt(dir, iname, &fname->crypto_buf);
+ unsigned int max_len = dir->i_sb->s_cop->max_namelen(dir);
+
+ if (iname->len > max_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)
+ return -ENOMEM;
+
+ ret = fname_encrypt(dir, iname, fname->crypto_buf.name,
+ fname->crypto_buf.len);
if (ret)
goto errout;
fname->disk_name.name = fname->crypto_buf.name;
@@ -410,7 +409,7 @@ int fscrypt_setup_filename(struct inode *dir, const struct qstr *iname,
return 0;
errout:
- fscrypt_fname_free_buffer(&fname->crypto_buf);
+ kfree(fname->crypto_buf.name);
return ret;
}
EXPORT_SYMBOL(fscrypt_setup_filename);
diff --git a/fs/crypto/fscrypt_private.h b/fs/crypto/fscrypt_private.h
index cec9ce309f41..053917587200 100644
--- a/fs/crypto/fscrypt_private.h
+++ b/fs/crypto/fscrypt_private.h
@@ -108,8 +108,8 @@ extern struct page *fscrypt_alloc_bounce_page(struct fscrypt_ctx *ctx,
gfp_t gfp_flags);
/* fname.c */
-extern int fname_encrypt(struct inode *inode,
- const struct qstr *iname, struct fscrypt_str *oname);
+extern int fname_encrypt(struct inode *inode, const struct qstr *iname,
+ u8 *out, unsigned int olen);
/* keyinfo.c */
extern void __exit fscrypt_essiv_cleanup(void);
diff --git a/fs/crypto/hooks.c b/fs/crypto/hooks.c
index 0f103a5cb1aa..ff20cacdea94 100644
--- a/fs/crypto/hooks.c
+++ b/fs/crypto/hooks.c
@@ -157,7 +157,6 @@ int __fscrypt_encrypt_symlink(struct inode *inode, const char *target,
struct qstr iname = { .name = target, .len = len };
struct fscrypt_symlink_data *sd;
unsigned int ciphertext_len;
- struct fscrypt_str oname;
err = fscrypt_require_key(inode);
if (err)
@@ -174,16 +173,12 @@ int __fscrypt_encrypt_symlink(struct inode *inode, const char *target,
ciphertext_len = disk_link->len - sizeof(*sd);
sd->len = cpu_to_le16(ciphertext_len);
- oname.name = sd->encrypted_path;
- oname.len = ciphertext_len;
- err = fname_encrypt(inode, &iname, &oname);
+ err = fname_encrypt(inode, &iname, sd->encrypted_path, ciphertext_len);
if (err) {
if (!disk_link->name)
kfree(sd);
return err;
}
- BUG_ON(oname.len != ciphertext_len);
-
/*
* Null-terminating the ciphertext doesn't make sense, but we still
* count the null terminator in the length, so we might as well
--
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
^ permalink raw reply related [flat|nested] 25+ messages in thread* [PATCH 22/24] fscrypt: define fscrypt_fname_alloc_buffer() to be for presented names
2017-12-15 17:42 [PATCH 00/24] fscrypt: symlink helpers and fscrypt.h cleanup Eric Biggers
` (20 preceding siblings ...)
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 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
23 siblings, 0 replies; 25+ messages in thread
From: Eric Biggers @ 2017-12-15 17:42 UTC (permalink / raw)
To: linux-fscrypt
Cc: Theodore Y . Ts'o, Eric Biggers, linux-f2fs-devel, linux-mtd,
Jaegeuk Kim, linux-ext4
From: Eric Biggers <ebiggers@google.com>
Previously fscrypt_fname_alloc_buffer() was used to allocate buffers for
both presented (decrypted or encoded) and encrypted filenames. That was
confusing, because it had to allocate the worst-case size for either,
e.g. including NUL-padding even when it was meaningless.
But now that fscrypt_setup_filename() no longer calls it, it is only
used in the ->get_link() and ->readdir() paths, which specifically want
a buffer for presented filenames. Therefore, switch the behavior over
to allocating the buffer for presented filenames only.
Signed-off-by: Eric Biggers <ebiggers@google.com>
---
fs/crypto/fname.c | 29 ++++++++++++++---------------
include/linux/fscrypt_notsupp.h | 2 +-
2 files changed, 15 insertions(+), 16 deletions(-)
diff --git a/fs/crypto/fname.c b/fs/crypto/fname.c
index 65424b89a1d1..44ddd094b7c5 100644
--- a/fs/crypto/fname.c
+++ b/fs/crypto/fname.c
@@ -204,37 +204,36 @@ u32 fscrypt_fname_encrypted_size(const struct inode *inode, u32 ilen)
EXPORT_SYMBOL(fscrypt_fname_encrypted_size);
/**
- * fscrypt_fname_crypto_alloc_obuff() -
+ * fscrypt_fname_alloc_buffer - allocate a buffer for presented filenames
*
- * Allocates an output buffer that is sufficient for the crypto operation
- * specified by the context and the direction.
+ * Allocate a buffer that is large enough to hold any decrypted or encoded
+ * filename (null-terminated), for the given maximum encrypted filename length.
+ *
+ * Return: 0 on success, -errno on failure
*/
int fscrypt_fname_alloc_buffer(const struct inode *inode,
- u32 ilen, struct fscrypt_str *crypto_str)
+ u32 max_encrypted_len,
+ struct fscrypt_str *crypto_str)
{
- u32 olen = fscrypt_fname_encrypted_size(inode, ilen);
const u32 max_encoded_len =
max_t(u32, BASE64_CHARS(FSCRYPT_FNAME_MAX_UNDIGESTED_SIZE),
1 + BASE64_CHARS(sizeof(struct fscrypt_digested_name)));
+ u32 max_presented_len;
- crypto_str->len = olen;
- olen = max(olen, max_encoded_len);
+ max_presented_len = max(max_encoded_len, max_encrypted_len);
- /*
- * Allocated buffer can hold one more character to null-terminate the
- * string
- */
- crypto_str->name = kmalloc(olen + 1, GFP_NOFS);
- if (!(crypto_str->name))
+ crypto_str->name = kmalloc(max_presented_len + 1, GFP_NOFS);
+ if (!crypto_str->name)
return -ENOMEM;
+ crypto_str->len = max_presented_len;
return 0;
}
EXPORT_SYMBOL(fscrypt_fname_alloc_buffer);
/**
- * fscrypt_fname_crypto_free_buffer() -
+ * fscrypt_fname_free_buffer - free the buffer for presented filenames
*
- * Frees the buffer allocated for crypto operation.
+ * Free the buffer allocated by fscrypt_fname_alloc_buffer().
*/
void fscrypt_fname_free_buffer(struct fscrypt_str *crypto_str)
{
diff --git a/include/linux/fscrypt_notsupp.h b/include/linux/fscrypt_notsupp.h
index 0962f504aa91..c9592e307df5 100644
--- a/include/linux/fscrypt_notsupp.h
+++ b/include/linux/fscrypt_notsupp.h
@@ -140,7 +140,7 @@ static inline u32 fscrypt_fname_encrypted_size(const struct inode *inode,
}
static inline int fscrypt_fname_alloc_buffer(const struct inode *inode,
- u32 ilen,
+ u32 max_encrypted_len,
struct fscrypt_str *crypto_str)
{
return -EOPNOTSUPP;
--
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
^ permalink raw reply related [flat|nested] 25+ messages in thread* [PATCH 23/24] fscrypt: fix up fscrypt_fname_encrypted_size() for internal use
2017-12-15 17:42 [PATCH 00/24] fscrypt: symlink helpers and fscrypt.h cleanup Eric Biggers
` (21 preceding siblings ...)
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 ` [PATCH 24/24] fscrypt: document symlink length restriction Eric Biggers
23 siblings, 0 replies; 25+ messages in thread
From: Eric Biggers @ 2017-12-15 17:42 UTC (permalink / raw)
To: linux-fscrypt
Cc: Theodore Y . Ts'o, Eric Biggers, linux-f2fs-devel, linux-mtd,
Jaegeuk Kim, linux-ext4
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
^ permalink raw reply related [flat|nested] 25+ messages in thread* [PATCH 24/24] fscrypt: document symlink length restriction
2017-12-15 17:42 [PATCH 00/24] fscrypt: symlink helpers and fscrypt.h cleanup Eric Biggers
` (22 preceding siblings ...)
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 ` Eric Biggers
23 siblings, 0 replies; 25+ messages in thread
From: Eric Biggers @ 2017-12-15 17:42 UTC (permalink / raw)
To: linux-fscrypt
Cc: Theodore Y . Ts'o, Eric Biggers, linux-f2fs-devel, linux-mtd,
Jaegeuk Kim, linux-ext4
From: Eric Biggers <ebiggers@google.com>
Document that encryption reduces the maximum length of a symlink target
slightly.
Signed-off-by: Eric Biggers <ebiggers@google.com>
---
Documentation/filesystems/fscrypt.rst | 10 ++++++++--
1 file changed, 8 insertions(+), 2 deletions(-)
diff --git a/Documentation/filesystems/fscrypt.rst b/Documentation/filesystems/fscrypt.rst
index 776ddc655f79..cfbc18f0d9c9 100644
--- a/Documentation/filesystems/fscrypt.rst
+++ b/Documentation/filesystems/fscrypt.rst
@@ -448,8 +448,14 @@ astute users may notice some differences in behavior:
- The st_size of an encrypted symlink will not necessarily give the
length of the symlink target as required by POSIX. It will actually
- give the length of the ciphertext, which may be slightly longer than
- the plaintext due to the NUL-padding.
+ give the length of the ciphertext, which will be slightly longer
+ than the plaintext due to NUL-padding and an extra 2-byte overhead.
+
+- The maximum length of an encrypted symlink is 2 bytes shorter than
+ the maximum length of an unencrypted symlink. For example, on an
+ EXT4 filesystem with a 4K block size, unencrypted symlinks can be up
+ to 4095 bytes long, while encrypted symlinks can only be up to 4093
+ bytes long (both lengths excluding the terminating null).
Note that mmap *is* supported. This is possible because the pagecache
for an encrypted file contains the plaintext, not the ciphertext.
--
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
^ permalink raw reply related [flat|nested] 25+ messages in thread