Re: [PATCH v4] fscrypt: Add support for AES-128-CBC

2017-06-15 Thread Michael Halcrow
On Tue, May 23, 2017 at 07:11:20AM +0200, David Gstir wrote:
> From: Daniel Walter 
> 
> fscrypt provides facilities to use different encryption algorithms which
> are selectable by userspace when setting the encryption policy. Currently,
> only AES-256-XTS for file contents and AES-256-CBC-CTS for file names are
> implemented. This is a clear case of kernel offers the mechanism and
> userspace selects a policy. Similar to what dm-crypt and ecryptfs have.
> 
> This patch adds support for using AES-128-CBC for file contents and
> AES-128-CBC-CTS for file name encryption. To mitigate watermarking
> attacks, IVs are generated using the ESSIV algorithm. While AES-CBC is
> actually slightly less secure than AES-XTS from a security point of view,
> there is more widespread hardware support. Using AES-CBC gives us the
> acceptable performance while still providing a moderate level of security
> for persistent storage.
> 
> Especially low-powered embedded devices with crypto accelerators such as
> CAAM or CESA often only support AES-CBC. Since using AES-CBC over AES-XTS
> is basically thought of a last resort, we use AES-128-CBC over AES-256-CBC
> since it has less encryption rounds and yields noticeable better
> performance starting from a file size of just a few kB.
> 
> Signed-off-by: Daniel Walter 
> [da...@sigma-star.at: addressed review comments]
> Signed-off-by: David Gstir 
> ---
>  fs/crypto/Kconfig  |   1 +
>  fs/crypto/crypto.c |  23 --
>  fs/crypto/fscrypt_private.h|   9 ++-
>  fs/crypto/keyinfo.c| 171 
> -
>  fs/crypto/policy.c |   8 +-
>  include/linux/fscrypt_common.h |  16 ++--
>  include/uapi/linux/fs.h|   2 +
>  7 files changed, 172 insertions(+), 58 deletions(-)
> 
> diff --git a/fs/crypto/Kconfig b/fs/crypto/Kconfig
> index 08b46e6e3995..02b7d91c9231 100644
> --- a/fs/crypto/Kconfig
> +++ b/fs/crypto/Kconfig
> @@ -7,6 +7,7 @@ config FS_ENCRYPTION
>   select CRYPTO_XTS
>   select CRYPTO_CTS
>   select CRYPTO_CTR
> + select CRYPTO_SHA256
>   select KEYS
>   help
> Enable encryption of files and directories.  This
> diff --git a/fs/crypto/crypto.c b/fs/crypto/crypto.c
> index 6d6eca394d4d..c7835df7e7b8 100644
> --- a/fs/crypto/crypto.c
> +++ b/fs/crypto/crypto.c
> @@ -26,6 +26,7 @@
>  #include 
>  #include 
>  #include 
> +#include 
>  #include "fscrypt_private.h"
>  
>  static unsigned int num_prealloc_crypto_pages = 32;
> @@ -147,8 +148,8 @@ int fscrypt_do_page_crypto(const struct inode *inode, 
> fscrypt_direction_t rw,
>  {
>   struct {
>   __le64 index;
> - u8 padding[FS_XTS_TWEAK_SIZE - sizeof(__le64)];
> - } xts_tweak;
> + u8 padding[FS_IV_SIZE - sizeof(__le64)];
> + } iv;
>   struct skcipher_request *req = NULL;
>   DECLARE_FS_COMPLETION_RESULT(ecr);
>   struct scatterlist dst, src;
> @@ -158,6 +159,16 @@ int fscrypt_do_page_crypto(const struct inode *inode, 
> fscrypt_direction_t rw,
>  
>   BUG_ON(len == 0);
>  
> + BUILD_BUG_ON(sizeof(iv) != FS_IV_SIZE);
> + BUILD_BUG_ON(AES_BLOCK_SIZE != FS_IV_SIZE);
> + iv.index = cpu_to_le64(lblk_num);
> + memset(iv.padding, 0, sizeof(iv.padding));
> +
> + if (ci->ci_essiv_tfm != NULL) {
> + crypto_cipher_encrypt_one(ci->ci_essiv_tfm, (u8 *),
> +   (u8 *));
> + }
> +
>   req = skcipher_request_alloc(tfm, gfp_flags);
>   if (!req) {
>   printk_ratelimited(KERN_ERR
> @@ -170,15 +181,11 @@ int fscrypt_do_page_crypto(const struct inode *inode, 
> fscrypt_direction_t rw,
>   req, CRYPTO_TFM_REQ_MAY_BACKLOG | CRYPTO_TFM_REQ_MAY_SLEEP,
>   page_crypt_complete, );
>  
> - BUILD_BUG_ON(sizeof(xts_tweak) != FS_XTS_TWEAK_SIZE);
> - xts_tweak.index = cpu_to_le64(lblk_num);
> - memset(xts_tweak.padding, 0, sizeof(xts_tweak.padding));
> -
>   sg_init_table(, 1);
>   sg_set_page(, dest_page, len, offs);
>   sg_init_table(, 1);
>   sg_set_page(, src_page, len, offs);
> - skcipher_request_set_crypt(req, , , len, _tweak);
> + skcipher_request_set_crypt(req, , , len, );
>   if (rw == FS_DECRYPT)
>   res = crypto_skcipher_decrypt(req);
>   else
> @@ -477,6 +484,8 @@ static void __exit fscrypt_exit(void)
>   destroy_workqueue(fscrypt_read_workqueue);
>   kmem_cache_destroy(fscrypt_ctx_cachep);
>   kmem_cache_destroy(fscrypt_info_cachep);
> +
> + fscrypt_essiv_cleanup();
>  }
>  module_exit(fscrypt_exit);
>  
> diff --git a/fs/crypto/fscrypt_private.h b/fs/crypto/fscrypt_private.h
> index 1e1f8a361b75..a1d5021c31ef 100644
> --- a/fs/crypto/fscrypt_private.h
> +++ b/fs/crypto/fscrypt_private.h
> @@ -12,10 +12,13 @@
>  #define _FSCRYPT_PRIVATE_H
>  
>  #include 
> +#include 
>  
>  /* Encryption parameters */
> 

Re: [PATCH v4] fscrypt: Add support for AES-128-CBC

2017-06-15 Thread Michael Halcrow
On Tue, May 23, 2017 at 07:11:20AM +0200, David Gstir wrote:
> From: Daniel Walter 
> 
> fscrypt provides facilities to use different encryption algorithms which
> are selectable by userspace when setting the encryption policy. Currently,
> only AES-256-XTS for file contents and AES-256-CBC-CTS for file names are
> implemented. This is a clear case of kernel offers the mechanism and
> userspace selects a policy. Similar to what dm-crypt and ecryptfs have.
> 
> This patch adds support for using AES-128-CBC for file contents and
> AES-128-CBC-CTS for file name encryption. To mitigate watermarking
> attacks, IVs are generated using the ESSIV algorithm. While AES-CBC is
> actually slightly less secure than AES-XTS from a security point of view,
> there is more widespread hardware support. Using AES-CBC gives us the
> acceptable performance while still providing a moderate level of security
> for persistent storage.
> 
> Especially low-powered embedded devices with crypto accelerators such as
> CAAM or CESA often only support AES-CBC. Since using AES-CBC over AES-XTS
> is basically thought of a last resort, we use AES-128-CBC over AES-256-CBC
> since it has less encryption rounds and yields noticeable better
> performance starting from a file size of just a few kB.
> 
> Signed-off-by: Daniel Walter 
> [da...@sigma-star.at: addressed review comments]
> Signed-off-by: David Gstir 
> ---
>  fs/crypto/Kconfig  |   1 +
>  fs/crypto/crypto.c |  23 --
>  fs/crypto/fscrypt_private.h|   9 ++-
>  fs/crypto/keyinfo.c| 171 
> -
>  fs/crypto/policy.c |   8 +-
>  include/linux/fscrypt_common.h |  16 ++--
>  include/uapi/linux/fs.h|   2 +
>  7 files changed, 172 insertions(+), 58 deletions(-)
> 
> diff --git a/fs/crypto/Kconfig b/fs/crypto/Kconfig
> index 08b46e6e3995..02b7d91c9231 100644
> --- a/fs/crypto/Kconfig
> +++ b/fs/crypto/Kconfig
> @@ -7,6 +7,7 @@ config FS_ENCRYPTION
>   select CRYPTO_XTS
>   select CRYPTO_CTS
>   select CRYPTO_CTR
> + select CRYPTO_SHA256
>   select KEYS
>   help
> Enable encryption of files and directories.  This
> diff --git a/fs/crypto/crypto.c b/fs/crypto/crypto.c
> index 6d6eca394d4d..c7835df7e7b8 100644
> --- a/fs/crypto/crypto.c
> +++ b/fs/crypto/crypto.c
> @@ -26,6 +26,7 @@
>  #include 
>  #include 
>  #include 
> +#include 
>  #include "fscrypt_private.h"
>  
>  static unsigned int num_prealloc_crypto_pages = 32;
> @@ -147,8 +148,8 @@ int fscrypt_do_page_crypto(const struct inode *inode, 
> fscrypt_direction_t rw,
>  {
>   struct {
>   __le64 index;
> - u8 padding[FS_XTS_TWEAK_SIZE - sizeof(__le64)];
> - } xts_tweak;
> + u8 padding[FS_IV_SIZE - sizeof(__le64)];
> + } iv;
>   struct skcipher_request *req = NULL;
>   DECLARE_FS_COMPLETION_RESULT(ecr);
>   struct scatterlist dst, src;
> @@ -158,6 +159,16 @@ int fscrypt_do_page_crypto(const struct inode *inode, 
> fscrypt_direction_t rw,
>  
>   BUG_ON(len == 0);
>  
> + BUILD_BUG_ON(sizeof(iv) != FS_IV_SIZE);
> + BUILD_BUG_ON(AES_BLOCK_SIZE != FS_IV_SIZE);
> + iv.index = cpu_to_le64(lblk_num);
> + memset(iv.padding, 0, sizeof(iv.padding));
> +
> + if (ci->ci_essiv_tfm != NULL) {
> + crypto_cipher_encrypt_one(ci->ci_essiv_tfm, (u8 *),
> +   (u8 *));
> + }
> +
>   req = skcipher_request_alloc(tfm, gfp_flags);
>   if (!req) {
>   printk_ratelimited(KERN_ERR
> @@ -170,15 +181,11 @@ int fscrypt_do_page_crypto(const struct inode *inode, 
> fscrypt_direction_t rw,
>   req, CRYPTO_TFM_REQ_MAY_BACKLOG | CRYPTO_TFM_REQ_MAY_SLEEP,
>   page_crypt_complete, );
>  
> - BUILD_BUG_ON(sizeof(xts_tweak) != FS_XTS_TWEAK_SIZE);
> - xts_tweak.index = cpu_to_le64(lblk_num);
> - memset(xts_tweak.padding, 0, sizeof(xts_tweak.padding));
> -
>   sg_init_table(, 1);
>   sg_set_page(, dest_page, len, offs);
>   sg_init_table(, 1);
>   sg_set_page(, src_page, len, offs);
> - skcipher_request_set_crypt(req, , , len, _tweak);
> + skcipher_request_set_crypt(req, , , len, );
>   if (rw == FS_DECRYPT)
>   res = crypto_skcipher_decrypt(req);
>   else
> @@ -477,6 +484,8 @@ static void __exit fscrypt_exit(void)
>   destroy_workqueue(fscrypt_read_workqueue);
>   kmem_cache_destroy(fscrypt_ctx_cachep);
>   kmem_cache_destroy(fscrypt_info_cachep);
> +
> + fscrypt_essiv_cleanup();
>  }
>  module_exit(fscrypt_exit);
>  
> diff --git a/fs/crypto/fscrypt_private.h b/fs/crypto/fscrypt_private.h
> index 1e1f8a361b75..a1d5021c31ef 100644
> --- a/fs/crypto/fscrypt_private.h
> +++ b/fs/crypto/fscrypt_private.h
> @@ -12,10 +12,13 @@
>  #define _FSCRYPT_PRIVATE_H
>  
>  #include 
> +#include 
>  
>  /* Encryption parameters */
> -#define FS_XTS_TWEAK_SIZE16
> +#define FS_IV_SIZE 

Re: [PATCH] fscrypt: remove broken support for detecting keyring key revocation

2017-03-13 Thread Michael Halcrow
On Tue, Feb 21, 2017 at 03:07:11PM -0800, Eric Biggers wrote:
> From: Eric Biggers <ebigg...@google.com>
> 
> Filesystem encryption ostensibly supported revoking a keyring key
> that had been used to "unlock" encrypted files, causing those files
> to become "locked" again. This was, however, buggy for several
> reasons, the most severe of which was that when key revocation
> happened to be detected for an inode, its fscrypt_info was
> immediately freed, even while other threads could be using it for
> encryption or decryption concurrently.  This could be exploited to
> crash the kernel or worse.

Removing the attempt at that functionality seems like the right
approach.

> This patch fixes the use-after-free by removing the code which
> detects the keyring key having been revoked, invalidated, or
> expired.  Instead, an encrypted inode that is "unlocked" now simply
> remains unlocked until it is evicted from memory.  Note that this is
> no worse than the case for block device-level encryption,
> e.g. dm-crypt, and it still remains possible for a privileged user
> to evict unused pages, inodes, and dentries by running 'sync; echo 3
> > /proc/sys/vm/drop_caches', or by simply unmounting the filesystem.
> In fact, one of those actions was already needed anyway for key
> revocation to work even somewhat sanely.  This change is not
> expected to break any applications.

I don't see any problem with this reasoning.

> In the future I'd like to implement a real API for fscrypt key
> revocation that interacts sanely with ongoing filesystem operations ---
> waiting for existing operations to complete and blocking new operations,
> and invalidating and sanitizing key material and plaintext from the VFS
> caches.  But this is a hard problem, and for now this bug must be fixed.
> 
> This bug affected almost all versions of ext4, f2fs, and ubifs
> encryption, and it was potentially reachable in any kernel configured
> with encryption support (CONFIG_EXT4_ENCRYPTION=y,
> CONFIG_EXT4_FS_ENCRYPTION=y, CONFIG_F2FS_FS_ENCRYPTION=y, or
> CONFIG_UBIFS_FS_ENCRYPTION=y).  Note that older kernels did not use the
> shared fs/crypto/ code, but due to the potential security implications
> of this bug, it may still be worthwhile to backport this fix to them.

Agreed.

> Fixes: b7236e21d55f ("ext4 crypto: reorganize how we store keys in the inode")
> Cc: sta...@vger.kernel.org # v4.2+
> Signed-off-by: Eric Biggers <ebigg...@google.com>

Acked-by: Michael Halcrow <mhalc...@google.com>

> ---
>  fs/crypto/crypto.c  | 10 +
>  fs/crypto/fname.c   |  2 +-
>  fs/crypto/fscrypt_private.h |  4 
>  fs/crypto/keyinfo.c | 52 
> -
>  4 files changed, 11 insertions(+), 57 deletions(-)
> 
> diff --git a/fs/crypto/crypto.c b/fs/crypto/crypto.c
> index 02a7a9286449..6d6eca394d4d 100644
> --- a/fs/crypto/crypto.c
> +++ b/fs/crypto/crypto.c
> @@ -327,7 +327,6 @@ EXPORT_SYMBOL(fscrypt_decrypt_page);
>  static int fscrypt_d_revalidate(struct dentry *dentry, unsigned int flags)
>  {
>   struct dentry *dir;
> - struct fscrypt_info *ci;
>   int dir_has_key, cached_with_key;
>  
>   if (flags & LOOKUP_RCU)
> @@ -339,18 +338,11 @@ static int fscrypt_d_revalidate(struct dentry *dentry, 
> unsigned int flags)
>   return 0;
>   }
>  
> - ci = d_inode(dir)->i_crypt_info;
> - if (ci && ci->ci_keyring_key &&
> - (ci->ci_keyring_key->flags & ((1 << KEY_FLAG_INVALIDATED) |
> -   (1 << KEY_FLAG_REVOKED) |
> -   (1 << KEY_FLAG_DEAD
> - ci = NULL;
> -
>   /* this should eventually be an flag in d_flags */
>   spin_lock(>d_lock);
>   cached_with_key = dentry->d_flags & DCACHE_ENCRYPTED_WITH_KEY;
>   spin_unlock(>d_lock);
> - dir_has_key = (ci != NULL);
> + dir_has_key = (d_inode(dir)->i_crypt_info != NULL);
>   dput(dir);
>  
>   /*
> diff --git a/fs/crypto/fname.c b/fs/crypto/fname.c
> index 13052b85c393..37b49894c762 100644
> --- a/fs/crypto/fname.c
> +++ b/fs/crypto/fname.c
> @@ -350,7 +350,7 @@ int fscrypt_setup_filename(struct inode *dir, const 
> struct qstr *iname,
>   fname->disk_name.len = iname->len;
>   return 0;
>   }
> - ret = fscrypt_get_crypt_info(dir);
> + ret = fscrypt_get_encryption_info(dir);
>   if (ret && ret != -EOPNOTSUPP)
>   return ret;
>  
> diff --git a/fs/crypto/fscrypt_private.h b/fs/crypto/fscrypt_private.h
> index fdbb8af32e

Re: [PATCH] fscrypt: remove broken support for detecting keyring key revocation

2017-03-13 Thread Michael Halcrow
On Tue, Feb 21, 2017 at 03:07:11PM -0800, Eric Biggers wrote:
> From: Eric Biggers 
> 
> Filesystem encryption ostensibly supported revoking a keyring key
> that had been used to "unlock" encrypted files, causing those files
> to become "locked" again. This was, however, buggy for several
> reasons, the most severe of which was that when key revocation
> happened to be detected for an inode, its fscrypt_info was
> immediately freed, even while other threads could be using it for
> encryption or decryption concurrently.  This could be exploited to
> crash the kernel or worse.

Removing the attempt at that functionality seems like the right
approach.

> This patch fixes the use-after-free by removing the code which
> detects the keyring key having been revoked, invalidated, or
> expired.  Instead, an encrypted inode that is "unlocked" now simply
> remains unlocked until it is evicted from memory.  Note that this is
> no worse than the case for block device-level encryption,
> e.g. dm-crypt, and it still remains possible for a privileged user
> to evict unused pages, inodes, and dentries by running 'sync; echo 3
> > /proc/sys/vm/drop_caches', or by simply unmounting the filesystem.
> In fact, one of those actions was already needed anyway for key
> revocation to work even somewhat sanely.  This change is not
> expected to break any applications.

I don't see any problem with this reasoning.

> In the future I'd like to implement a real API for fscrypt key
> revocation that interacts sanely with ongoing filesystem operations ---
> waiting for existing operations to complete and blocking new operations,
> and invalidating and sanitizing key material and plaintext from the VFS
> caches.  But this is a hard problem, and for now this bug must be fixed.
> 
> This bug affected almost all versions of ext4, f2fs, and ubifs
> encryption, and it was potentially reachable in any kernel configured
> with encryption support (CONFIG_EXT4_ENCRYPTION=y,
> CONFIG_EXT4_FS_ENCRYPTION=y, CONFIG_F2FS_FS_ENCRYPTION=y, or
> CONFIG_UBIFS_FS_ENCRYPTION=y).  Note that older kernels did not use the
> shared fs/crypto/ code, but due to the potential security implications
> of this bug, it may still be worthwhile to backport this fix to them.

Agreed.

> Fixes: b7236e21d55f ("ext4 crypto: reorganize how we store keys in the inode")
> Cc: sta...@vger.kernel.org # v4.2+
> Signed-off-by: Eric Biggers 

Acked-by: Michael Halcrow 

> ---
>  fs/crypto/crypto.c  | 10 +
>  fs/crypto/fname.c   |  2 +-
>  fs/crypto/fscrypt_private.h |  4 
>  fs/crypto/keyinfo.c | 52 
> -
>  4 files changed, 11 insertions(+), 57 deletions(-)
> 
> diff --git a/fs/crypto/crypto.c b/fs/crypto/crypto.c
> index 02a7a9286449..6d6eca394d4d 100644
> --- a/fs/crypto/crypto.c
> +++ b/fs/crypto/crypto.c
> @@ -327,7 +327,6 @@ EXPORT_SYMBOL(fscrypt_decrypt_page);
>  static int fscrypt_d_revalidate(struct dentry *dentry, unsigned int flags)
>  {
>   struct dentry *dir;
> - struct fscrypt_info *ci;
>   int dir_has_key, cached_with_key;
>  
>   if (flags & LOOKUP_RCU)
> @@ -339,18 +338,11 @@ static int fscrypt_d_revalidate(struct dentry *dentry, 
> unsigned int flags)
>   return 0;
>   }
>  
> - ci = d_inode(dir)->i_crypt_info;
> - if (ci && ci->ci_keyring_key &&
> - (ci->ci_keyring_key->flags & ((1 << KEY_FLAG_INVALIDATED) |
> -   (1 << KEY_FLAG_REVOKED) |
> -   (1 << KEY_FLAG_DEAD
> - ci = NULL;
> -
>   /* this should eventually be an flag in d_flags */
>   spin_lock(>d_lock);
>   cached_with_key = dentry->d_flags & DCACHE_ENCRYPTED_WITH_KEY;
>   spin_unlock(>d_lock);
> - dir_has_key = (ci != NULL);
> + dir_has_key = (d_inode(dir)->i_crypt_info != NULL);
>   dput(dir);
>  
>   /*
> diff --git a/fs/crypto/fname.c b/fs/crypto/fname.c
> index 13052b85c393..37b49894c762 100644
> --- a/fs/crypto/fname.c
> +++ b/fs/crypto/fname.c
> @@ -350,7 +350,7 @@ int fscrypt_setup_filename(struct inode *dir, const 
> struct qstr *iname,
>   fname->disk_name.len = iname->len;
>   return 0;
>   }
> - ret = fscrypt_get_crypt_info(dir);
> + ret = fscrypt_get_encryption_info(dir);
>   if (ret && ret != -EOPNOTSUPP)
>   return ret;
>  
> diff --git a/fs/crypto/fscrypt_private.h b/fs/crypto/fscrypt_private.h
> index fdbb8af32eaf..e39696e64494 100644
> --- a/fs/crypto/fscrypt_private.h
> +++ b/

Re: [PATCH 15/26] ubifs: Implement encrypt/decrypt for all IO

2016-10-21 Thread Michael Halcrow
On Fri, Oct 21, 2016 at 07:21:04PM +0200, Richard Weinberger wrote:
> On 21.10.2016 19:14, Michael Halcrow wrote:
> > Compress-before-encrypt is a hazard.
> > 
> > http://www.iacr.org/cryptodb/archive/2002/FSE/3091/3091.pdf
> 
> I'm fully aware of that. But as usual it depends on the use case.
> Compression is optional in UBIFS, paranoid users can disable it
> when encryption is enabled.

It's not the paranoid users I'm concerned about.  It's those building
systems with complexity and nuance on top of UBIFS who aren't paranoid
enough.

I suggest disabling compression by default when encryption is enabled,
unless the user explicitly enables both.

> 
> Thanks,
> //richard


Re: [PATCH 15/26] ubifs: Implement encrypt/decrypt for all IO

2016-10-21 Thread Michael Halcrow
On Fri, Oct 21, 2016 at 07:21:04PM +0200, Richard Weinberger wrote:
> On 21.10.2016 19:14, Michael Halcrow wrote:
> > Compress-before-encrypt is a hazard.
> > 
> > http://www.iacr.org/cryptodb/archive/2002/FSE/3091/3091.pdf
> 
> I'm fully aware of that. But as usual it depends on the use case.
> Compression is optional in UBIFS, paranoid users can disable it
> when encryption is enabled.

It's not the paranoid users I'm concerned about.  It's those building
systems with complexity and nuance on top of UBIFS who aren't paranoid
enough.

I suggest disabling compression by default when encryption is enabled,
unless the user explicitly enables both.

> 
> Thanks,
> //richard


Re: [PATCH 26/26] ubifs: Raise write version to 5

2016-10-21 Thread Michael Halcrow
On Fri, Oct 21, 2016 at 02:48:41PM +0200, Richard Weinberger wrote:
> Starting with version 5 the following properties change:
>  - UBIFS_FLG_DOUBLE_HASH is mandatory
>  - UBIFS_FLG_ENCRYPTION is optional but depdens on UBIFS_FLG_DOUBLE_HASH
>  - Filesystems with unknown super block flags will be rejected, this
>allows us in future to add new features without raising the UBIFS
>write version.
> 
> Signed-off-by: Richard Weinberger 
> ---
>  fs/ubifs/sb.c  | 17 +
>  fs/ubifs/ubifs-media.h |  4 +++-
>  2 files changed, 20 insertions(+), 1 deletion(-)
> 
> diff --git a/fs/ubifs/sb.c b/fs/ubifs/sb.c
> index 54cef70ea16f..7f1ead29e727 100644
> --- a/fs/ubifs/sb.c
> +++ b/fs/ubifs/sb.c
> @@ -466,6 +466,16 @@ static int validate_sb(struct ubifs_info *c, struct 
> ubifs_sb_node *sup)
>   goto failed;
>   }
>  
> + if (!c->double_hash && c->fmt_version >= 5) {
> + err = 16;
> + goto failed;
> + }
> +
> + if (c->encrypted && c->fmt_version < 5) {
> + err = 17;
> + goto failed;
> + }
> +
>   return 0;
>  
>  failed:
> @@ -624,6 +634,13 @@ int ubifs_read_superblock(struct ubifs_info *c)
>   c->double_hash = !!(sup_flags & UBIFS_FLG_DOUBLE_HASH);
>   c->encrypted = !!(sup_flags & UBIFS_FLG_ENCRYPTION);
>  
> + if ((sup_flags & ~UBIFS_FLG_MASK) != 0) {
> + ubifs_err(c, "Unknown feature flags found: %#x",
> +   sup_flags & ~UBIFS_FLG_MASK);
> + err = -EINVAL;
> + goto out;
> + }
> +
>  #ifndef CONFIG_UBIFS_FS_ENCRYPTION
>   if (c->encrypted) {
>   ubifs_err(c, "file system contains encrypted files but UBIFS"
> diff --git a/fs/ubifs/ubifs-media.h b/fs/ubifs/ubifs-media.h
> index bdc7935a5e41..e8c23c9d4f4a 100644
> --- a/fs/ubifs/ubifs-media.h
> +++ b/fs/ubifs/ubifs-media.h
> @@ -46,7 +46,7 @@
>   * UBIFS went into mainline kernel with format version 4. The older formats
>   * were development formats.
>   */
> -#define UBIFS_FORMAT_VERSION 4
> +#define UBIFS_FORMAT_VERSION 5

Alex Cope is working on a fix for file name encryption in ext4 so that
common plaintext prefixes don't result in common ciphertext prefixes.
Older kernels will not be able to read the new file names.

>  
>  /*
>   * Read-only compatibility version. If the UBIFS format is changed, older 
> UBIFS
> @@ -429,6 +429,8 @@ enum {
>   UBIFS_FLG_ENCRYPTION = 0x10,
>  };
>  
> +#define UBIFS_FLG_MASK 
> (UBIFS_FLG_BIGLPT|UBIFS_FLG_SPACE_FIXUP|UBIFS_FLG_DOUBLE_HASH|UBIFS_FLG_ENCRYPTION)
> +
>  /**
>   * struct ubifs_ch - common header node.
>   * @magic: UBIFS node magic number (%UBIFS_NODE_MAGIC)
> -- 
> 2.7.3
> 
> --
> To unsubscribe from this list: send the line "unsubscribe linux-fsdevel" in
> the body of a message to majord...@vger.kernel.org
> More majordomo info at  http://vger.kernel.org/majordomo-info.html


Re: [PATCH 26/26] ubifs: Raise write version to 5

2016-10-21 Thread Michael Halcrow
On Fri, Oct 21, 2016 at 02:48:41PM +0200, Richard Weinberger wrote:
> Starting with version 5 the following properties change:
>  - UBIFS_FLG_DOUBLE_HASH is mandatory
>  - UBIFS_FLG_ENCRYPTION is optional but depdens on UBIFS_FLG_DOUBLE_HASH
>  - Filesystems with unknown super block flags will be rejected, this
>allows us in future to add new features without raising the UBIFS
>write version.
> 
> Signed-off-by: Richard Weinberger 
> ---
>  fs/ubifs/sb.c  | 17 +
>  fs/ubifs/ubifs-media.h |  4 +++-
>  2 files changed, 20 insertions(+), 1 deletion(-)
> 
> diff --git a/fs/ubifs/sb.c b/fs/ubifs/sb.c
> index 54cef70ea16f..7f1ead29e727 100644
> --- a/fs/ubifs/sb.c
> +++ b/fs/ubifs/sb.c
> @@ -466,6 +466,16 @@ static int validate_sb(struct ubifs_info *c, struct 
> ubifs_sb_node *sup)
>   goto failed;
>   }
>  
> + if (!c->double_hash && c->fmt_version >= 5) {
> + err = 16;
> + goto failed;
> + }
> +
> + if (c->encrypted && c->fmt_version < 5) {
> + err = 17;
> + goto failed;
> + }
> +
>   return 0;
>  
>  failed:
> @@ -624,6 +634,13 @@ int ubifs_read_superblock(struct ubifs_info *c)
>   c->double_hash = !!(sup_flags & UBIFS_FLG_DOUBLE_HASH);
>   c->encrypted = !!(sup_flags & UBIFS_FLG_ENCRYPTION);
>  
> + if ((sup_flags & ~UBIFS_FLG_MASK) != 0) {
> + ubifs_err(c, "Unknown feature flags found: %#x",
> +   sup_flags & ~UBIFS_FLG_MASK);
> + err = -EINVAL;
> + goto out;
> + }
> +
>  #ifndef CONFIG_UBIFS_FS_ENCRYPTION
>   if (c->encrypted) {
>   ubifs_err(c, "file system contains encrypted files but UBIFS"
> diff --git a/fs/ubifs/ubifs-media.h b/fs/ubifs/ubifs-media.h
> index bdc7935a5e41..e8c23c9d4f4a 100644
> --- a/fs/ubifs/ubifs-media.h
> +++ b/fs/ubifs/ubifs-media.h
> @@ -46,7 +46,7 @@
>   * UBIFS went into mainline kernel with format version 4. The older formats
>   * were development formats.
>   */
> -#define UBIFS_FORMAT_VERSION 4
> +#define UBIFS_FORMAT_VERSION 5

Alex Cope is working on a fix for file name encryption in ext4 so that
common plaintext prefixes don't result in common ciphertext prefixes.
Older kernels will not be able to read the new file names.

>  
>  /*
>   * Read-only compatibility version. If the UBIFS format is changed, older 
> UBIFS
> @@ -429,6 +429,8 @@ enum {
>   UBIFS_FLG_ENCRYPTION = 0x10,
>  };
>  
> +#define UBIFS_FLG_MASK 
> (UBIFS_FLG_BIGLPT|UBIFS_FLG_SPACE_FIXUP|UBIFS_FLG_DOUBLE_HASH|UBIFS_FLG_ENCRYPTION)
> +
>  /**
>   * struct ubifs_ch - common header node.
>   * @magic: UBIFS node magic number (%UBIFS_NODE_MAGIC)
> -- 
> 2.7.3
> 
> --
> To unsubscribe from this list: send the line "unsubscribe linux-fsdevel" in
> the body of a message to majord...@vger.kernel.org
> More majordomo info at  http://vger.kernel.org/majordomo-info.html


Re: [PATCH 15/26] ubifs: Implement encrypt/decrypt for all IO

2016-10-21 Thread Michael Halcrow
On Fri, Oct 21, 2016 at 02:48:30PM +0200, Richard Weinberger wrote:
> Signed-off-by: Richard Weinberger 
> ---
>  fs/ubifs/file.c|  36 ++
>  fs/ubifs/journal.c | 105 
> +++--
>  fs/ubifs/super.c   |   6 ++-
>  fs/ubifs/ubifs.h   |   6 +++
>  4 files changed, 131 insertions(+), 22 deletions(-)
> 
> diff --git a/fs/ubifs/file.c b/fs/ubifs/file.c
> index bd0049788e24..60e089d50c82 100644
> --- a/fs/ubifs/file.c
> +++ b/fs/ubifs/file.c
> @@ -78,6 +78,24 @@ static int read_block(struct inode *inode, void *addr, 
> unsigned int block,
>   goto dump;
>  
>   dlen = le32_to_cpu(dn->ch.len) - UBIFS_DATA_NODE_SZ;
> +
> + if (ubifs_crypt_is_encrypted(inode)) {
> + int clen = le16_to_cpu(dn->compr_size);
> +
> + if (clen <= 0 || clen > UBIFS_BLOCK_SIZE || clen > dlen)
> + goto dump;
> +
> + ubifs_assert(dlen <= UBIFS_BLOCK_SIZE);
> + err = fscrypt_decrypt_buffer(inode, >data, >data, dlen, 
> block, GFP_NOFS);
> + if (err) {
> + ubifs_err(c, "fscrypt_decrypt_buffer failed: %i", err);
> + return err;
> + }
> +
> + ubifs_assert(clen <= dlen);
> + dlen = clen;
> + }
> +
>   out_len = UBIFS_BLOCK_SIZE;
>   err = ubifs_decompress(c, >data, dlen, addr, _len,
>  le16_to_cpu(dn->compr_type));
> @@ -650,6 +668,24 @@ static int populate_page(struct ubifs_info *c, struct 
> page *page,
>  
>   dlen = le32_to_cpu(dn->ch.len) - UBIFS_DATA_NODE_SZ;
>   out_len = UBIFS_BLOCK_SIZE;
> +
> + if (ubifs_crypt_is_encrypted(inode)) {
> + int clen = le16_to_cpu(dn->compr_size);
> +
> + if (clen <= 0 || clen > UBIFS_BLOCK_SIZE || 
> clen > dlen)
> + goto out_err;
> +
> + ubifs_assert(dlen <= UBIFS_BLOCK_SIZE);
> + err = fscrypt_decrypt_buffer(inode, >data, 
> >data, dlen, page_block, GFP_NOFS);
> + if (err) {
> + ubifs_err(c, "fscrypt_decrypt_buffer 
> failed: %i", err);
> + goto out_err;
> + }
> +
> + ubifs_assert(clen <= dlen);
> + dlen = clen;
> + }
> +
>   err = ubifs_decompress(c, >data, dlen, addr, 
> _len,
>  le16_to_cpu(dn->compr_type));
>   if (err || len != out_len)
> diff --git a/fs/ubifs/journal.c b/fs/ubifs/journal.c
> index a643de4e3d91..da694e520ec8 100644
> --- a/fs/ubifs/journal.c
> +++ b/fs/ubifs/journal.c
> @@ -691,11 +691,15 @@ int ubifs_jnl_write_data(struct ubifs_info *c, const 
> struct inode *inode,
>   int err, lnum, offs, compr_type, out_len;
>   int dlen = COMPRESSED_DATA_NODE_BUF_SZ, allocated = 1;
>   struct ubifs_inode *ui = ubifs_inode(inode);
> + bool encrypted = ubifs_crypt_is_encrypted(inode);
>  
>   dbg_jnlk(key, "ino %lu, blk %u, len %d, key ",
>   (unsigned long)key_inum(c, key), key_block(c, key), len);
>   ubifs_assert(len <= UBIFS_BLOCK_SIZE);
>  
> + if (encrypted)
> + dlen += UBIFS_CIPHER_BLOCK_SIZE;
> +
>   data = kmalloc(dlen, GFP_NOFS | __GFP_NOWARN);
>   if (!data) {
>   /*
> @@ -724,6 +728,26 @@ int ubifs_jnl_write_data(struct ubifs_info *c, const 
> struct inode *inode,
>   ubifs_compress(c, buf, len, >data, _len, _type);

Compress-before-encrypt is a hazard.

http://www.iacr.org/cryptodb/archive/2002/FSE/3091/3091.pdf

>   ubifs_assert(out_len <= UBIFS_BLOCK_SIZE);
>  
> + if (encrypted) {
> + void *p = >data;
> + int plen = round_up(out_len, UBIFS_CIPHER_BLOCK_SIZE);
> +
> + data->compr_size = cpu_to_le16(out_len);
> +
> + if (plen != out_len) {
> + memset(p + out_len, 0, plen - out_len);
> + out_len = plen;
> + }
> +
> + err = fscrypt_encrypt_buffer(inode, >data, >data, 
> out_len, key_block(c, key), GFP_NOFS);
> + if (err) {
> + ubifs_err(c, "fscrypt_encrypt_buffer failed: %i", err);
> + goto out_free;
> + }
> + } else {
> + data->compr_size = 0;
> + }
> +
>   dlen = UBIFS_DATA_NODE_SZ + out_len;
>   data->compr_type = cpu_to_le16(compr_type);
>  
> @@ -1083,31 +1107,79 @@ out_free:
>  }
>  
>  /**
> - * recomp_data_node - re-compress a truncated data node.
> + * truncate_data_node - re-compress/encrypt a truncated data node.
> + * @c: UBIFS file-system description object
> + * @inode: inode which referes to the data node
> + 

Re: [PATCH 15/26] ubifs: Implement encrypt/decrypt for all IO

2016-10-21 Thread Michael Halcrow
On Fri, Oct 21, 2016 at 02:48:30PM +0200, Richard Weinberger wrote:
> Signed-off-by: Richard Weinberger 
> ---
>  fs/ubifs/file.c|  36 ++
>  fs/ubifs/journal.c | 105 
> +++--
>  fs/ubifs/super.c   |   6 ++-
>  fs/ubifs/ubifs.h   |   6 +++
>  4 files changed, 131 insertions(+), 22 deletions(-)
> 
> diff --git a/fs/ubifs/file.c b/fs/ubifs/file.c
> index bd0049788e24..60e089d50c82 100644
> --- a/fs/ubifs/file.c
> +++ b/fs/ubifs/file.c
> @@ -78,6 +78,24 @@ static int read_block(struct inode *inode, void *addr, 
> unsigned int block,
>   goto dump;
>  
>   dlen = le32_to_cpu(dn->ch.len) - UBIFS_DATA_NODE_SZ;
> +
> + if (ubifs_crypt_is_encrypted(inode)) {
> + int clen = le16_to_cpu(dn->compr_size);
> +
> + if (clen <= 0 || clen > UBIFS_BLOCK_SIZE || clen > dlen)
> + goto dump;
> +
> + ubifs_assert(dlen <= UBIFS_BLOCK_SIZE);
> + err = fscrypt_decrypt_buffer(inode, >data, >data, dlen, 
> block, GFP_NOFS);
> + if (err) {
> + ubifs_err(c, "fscrypt_decrypt_buffer failed: %i", err);
> + return err;
> + }
> +
> + ubifs_assert(clen <= dlen);
> + dlen = clen;
> + }
> +
>   out_len = UBIFS_BLOCK_SIZE;
>   err = ubifs_decompress(c, >data, dlen, addr, _len,
>  le16_to_cpu(dn->compr_type));
> @@ -650,6 +668,24 @@ static int populate_page(struct ubifs_info *c, struct 
> page *page,
>  
>   dlen = le32_to_cpu(dn->ch.len) - UBIFS_DATA_NODE_SZ;
>   out_len = UBIFS_BLOCK_SIZE;
> +
> + if (ubifs_crypt_is_encrypted(inode)) {
> + int clen = le16_to_cpu(dn->compr_size);
> +
> + if (clen <= 0 || clen > UBIFS_BLOCK_SIZE || 
> clen > dlen)
> + goto out_err;
> +
> + ubifs_assert(dlen <= UBIFS_BLOCK_SIZE);
> + err = fscrypt_decrypt_buffer(inode, >data, 
> >data, dlen, page_block, GFP_NOFS);
> + if (err) {
> + ubifs_err(c, "fscrypt_decrypt_buffer 
> failed: %i", err);
> + goto out_err;
> + }
> +
> + ubifs_assert(clen <= dlen);
> + dlen = clen;
> + }
> +
>   err = ubifs_decompress(c, >data, dlen, addr, 
> _len,
>  le16_to_cpu(dn->compr_type));
>   if (err || len != out_len)
> diff --git a/fs/ubifs/journal.c b/fs/ubifs/journal.c
> index a643de4e3d91..da694e520ec8 100644
> --- a/fs/ubifs/journal.c
> +++ b/fs/ubifs/journal.c
> @@ -691,11 +691,15 @@ int ubifs_jnl_write_data(struct ubifs_info *c, const 
> struct inode *inode,
>   int err, lnum, offs, compr_type, out_len;
>   int dlen = COMPRESSED_DATA_NODE_BUF_SZ, allocated = 1;
>   struct ubifs_inode *ui = ubifs_inode(inode);
> + bool encrypted = ubifs_crypt_is_encrypted(inode);
>  
>   dbg_jnlk(key, "ino %lu, blk %u, len %d, key ",
>   (unsigned long)key_inum(c, key), key_block(c, key), len);
>   ubifs_assert(len <= UBIFS_BLOCK_SIZE);
>  
> + if (encrypted)
> + dlen += UBIFS_CIPHER_BLOCK_SIZE;
> +
>   data = kmalloc(dlen, GFP_NOFS | __GFP_NOWARN);
>   if (!data) {
>   /*
> @@ -724,6 +728,26 @@ int ubifs_jnl_write_data(struct ubifs_info *c, const 
> struct inode *inode,
>   ubifs_compress(c, buf, len, >data, _len, _type);

Compress-before-encrypt is a hazard.

http://www.iacr.org/cryptodb/archive/2002/FSE/3091/3091.pdf

>   ubifs_assert(out_len <= UBIFS_BLOCK_SIZE);
>  
> + if (encrypted) {
> + void *p = >data;
> + int plen = round_up(out_len, UBIFS_CIPHER_BLOCK_SIZE);
> +
> + data->compr_size = cpu_to_le16(out_len);
> +
> + if (plen != out_len) {
> + memset(p + out_len, 0, plen - out_len);
> + out_len = plen;
> + }
> +
> + err = fscrypt_encrypt_buffer(inode, >data, >data, 
> out_len, key_block(c, key), GFP_NOFS);
> + if (err) {
> + ubifs_err(c, "fscrypt_encrypt_buffer failed: %i", err);
> + goto out_free;
> + }
> + } else {
> + data->compr_size = 0;
> + }
> +
>   dlen = UBIFS_DATA_NODE_SZ + out_len;
>   data->compr_type = cpu_to_le16(compr_type);
>  
> @@ -1083,31 +1107,79 @@ out_free:
>  }
>  
>  /**
> - * recomp_data_node - re-compress a truncated data node.
> + * truncate_data_node - re-compress/encrypt a truncated data node.
> + * @c: UBIFS file-system description object
> + * @inode: inode which referes to the data node
> + * @block: data 

Re: [RFD] Common userspace tool for fscypto

2016-10-19 Thread Michael Halcrow
On Wed, Oct 19, 2016 at 4:35 AM, Richard Weinberger  wrote:
> Hi!
>
> Since file level encryption has more than one user, currently ext4, f2fs and 
> soon ubifs
> it would be nice to have a single tool to control fscrypto from userspace.
>
> For ext4 we have already at least two tools, one as part of e2fsprogs and 
> another
> one on github[0]. IMHO the latter one is much more user friendly and 
> intuitive to use.
> I as unable to find the userspace tool for f2fs.
>
> That said, what about implementing such a tool as part of util-linux to 
> control
> fscrypto? We (David and I) would volunteer.

While discussing several changes we have staged for release (we're
trying to minimize churn by batching a large set of format changes all
at once), we've recently recognized this need on my team and were
planning on starting work on exactly what you propose.

> Thanks,
> //richard
>
> [0] https://github.com/gdelugre/ext4-crypt


Re: [RFD] Common userspace tool for fscypto

2016-10-19 Thread Michael Halcrow
On Wed, Oct 19, 2016 at 4:35 AM, Richard Weinberger  wrote:
> Hi!
>
> Since file level encryption has more than one user, currently ext4, f2fs and 
> soon ubifs
> it would be nice to have a single tool to control fscrypto from userspace.
>
> For ext4 we have already at least two tools, one as part of e2fsprogs and 
> another
> one on github[0]. IMHO the latter one is much more user friendly and 
> intuitive to use.
> I as unable to find the userspace tool for f2fs.
>
> That said, what about implementing such a tool as part of util-linux to 
> control
> fscrypto? We (David and I) would volunteer.

While discussing several changes we have staged for release (we're
trying to minimize churn by batching a large set of format changes all
at once), we've recently recognized this need on my team and were
planning on starting work on exactly what you propose.

> Thanks,
> //richard
>
> [0] https://github.com/gdelugre/ext4-crypt


Re: [PATCH v1] eCryptfs: enhancing eCryptfs to be used with external crypto engine

2015-11-11 Thread Michael Halcrow
On Wed, Nov 11, 2015 at 12:03:35PM -, andr...@codeaurora.org wrote:
> > On 2015-11-10 15:20:59, andr...@codeaurora.org wrote:
> >> This is a hardware inline accelerator, meaning that it operates on much
> >> lower layer, block layer and device driver layer. The HW encrypts plain
> >> requests sent from block layer directly, thus doing it much more
> >> efficiently rather than using crypto API.
> >
> 
> > I feel like basing this on eCryptfs is an odd choice. The overhead of
> > setting up an eCryptfs mount (and requiring CAP_SYS_ADMIN) and the
> > duplication of page cache and dentry cache entries (for upper and lower
> > caches) seems like considerable baggage for such a nifty, new hardware
> > feature.
> >
> 
> First of all, one of the leading companies on the mobile market uses
> eCryptfs as a solution for their file-based-encryption feature and they
> use it along with HW crypto engine. I believe we will soon see interest
> from additional companies.
> 
> Secondly, eCryptfs is convenient in many ways for implementing
> file-based-encryption and there are not so many good alternatives as of
> today.

EXT4 and F2FS both have native file-based encryption capabilities.
They don't suffer from a lot of the overhead and page ballooning
issues that eCryptfs has. Nobody should be putting development effort
toward using eCryptfs on top of EXT4 or F2FS.

There's clear value in enabling inline hardware encryption on mobile
platforms. However I don't think trying to wedge it in via a stacked
file system is a good long-term strategy. We should be moving toward
integrating inline hardware encryption into file systems that are
deployed in those environments.

Given the amount of code duplication between EXT4 and F2FS encryption,
we should also be thinking about more general support for encryption
at the VFS/MM layer.

> You are right regarding overhead, page duplication, etc., however
> enabling eCryptfs to work with HW encryption still makes it a very
> efficient solution. Also, it is not just inline HW crypto engine,
> any HW crypto engine operates more efficiently while working on long
> chunks of data. Our suggested solution uses the existing block layer
> (that is part of the standard Linux storage stack) feature that
> gathers number of block to into one request and then encrypt/decrypt
> the data, whereas eCryptfs can only perform the crypto operation on
> single pages. This feature was tested on our platforms and
> demonstrated very significance performance improvement comparing to
> existing SW based solutions
> 
> >> In order to use such HW efficiently with eCryptfs, eCryptfs encryption
> >> has
> >> to be canceled and it will need to call for external module instead that
> >> will do the correct marking for the blocks to distinguish between those
> >> that need to be encrypted by the HW from those that do not need.
> >>
> >> We are considering posting the code that will call
> >> ecryptfs_register_to_events() as a separate patch, but haven't done so
> >> yet. It is HW specific.
> >> Currently we are only proposing framework change so that it can allow
> >> for
> >> external modules to be connected
> >
> > In that case, I cannot accept this patch. I will have no way to test the
> > external module functionality and will not be able to make changes to
> > that area of the code because it will not be possible for me to fix
> > anything that I've broken. I won't even be able to know if I've broken
> > anything.
> >
> > If you are able to upstream the external module code, then I'll do a
> > proper review of this patch. I should note that I've only glanced at the
> > patch but if feels like it should be broken up into smaller, easier to
> > review patches before it can be properly reviewed.
> >
> > Tyler
> 
> We can upstream the external module code, however as I mentioned this
> module is specific for our HW, so you won't be able to test it either.
> However we can pretty easily turn it into some dummy module for testing
> purposes only that will just do prints instead of HW specific calls. Would
> this be sufficient ? If so, where in project tree should I put it ?
> 
> >
> >>
> >> > On 2015-11-09 20:56:02, andr...@codeaurora.org wrote:
> >> >> Hello, Tyler
> >> >>
> >> >> I'll try to provide more detailed explanation, should it be
> >> satisfactory
> >> >> enough I will update the patch description.
> >> >>
> >> >> The problem with current eCryptfs is that it has total control on how
> >> >> and
> >> >> when the encryption is performed and this control can't be altered.
> >> One
> >> >> example when this can be a problem is when we want to utilize an
> >> >> underlying inline HW encryption engine which allows encrypting blocks
> >> >> 'on
> >> >> the fly' as they are being written to the storage. In such a case
> >> >> relevant
> >> >> blocks just need to be marked as 'should be encrypted'. No actual
> >> >> encryption should be done by eCryptfs as it will be much slower.
> >> >
> >> > Is this a hardware 

Re: [PATCH v1] eCryptfs: enhancing eCryptfs to be used with external crypto engine

2015-11-11 Thread Michael Halcrow
On Wed, Nov 11, 2015 at 12:03:35PM -, andr...@codeaurora.org wrote:
> > On 2015-11-10 15:20:59, andr...@codeaurora.org wrote:
> >> This is a hardware inline accelerator, meaning that it operates on much
> >> lower layer, block layer and device driver layer. The HW encrypts plain
> >> requests sent from block layer directly, thus doing it much more
> >> efficiently rather than using crypto API.
> >
> 
> > I feel like basing this on eCryptfs is an odd choice. The overhead of
> > setting up an eCryptfs mount (and requiring CAP_SYS_ADMIN) and the
> > duplication of page cache and dentry cache entries (for upper and lower
> > caches) seems like considerable baggage for such a nifty, new hardware
> > feature.
> >
> 
> First of all, one of the leading companies on the mobile market uses
> eCryptfs as a solution for their file-based-encryption feature and they
> use it along with HW crypto engine. I believe we will soon see interest
> from additional companies.
> 
> Secondly, eCryptfs is convenient in many ways for implementing
> file-based-encryption and there are not so many good alternatives as of
> today.

EXT4 and F2FS both have native file-based encryption capabilities.
They don't suffer from a lot of the overhead and page ballooning
issues that eCryptfs has. Nobody should be putting development effort
toward using eCryptfs on top of EXT4 or F2FS.

There's clear value in enabling inline hardware encryption on mobile
platforms. However I don't think trying to wedge it in via a stacked
file system is a good long-term strategy. We should be moving toward
integrating inline hardware encryption into file systems that are
deployed in those environments.

Given the amount of code duplication between EXT4 and F2FS encryption,
we should also be thinking about more general support for encryption
at the VFS/MM layer.

> You are right regarding overhead, page duplication, etc., however
> enabling eCryptfs to work with HW encryption still makes it a very
> efficient solution. Also, it is not just inline HW crypto engine,
> any HW crypto engine operates more efficiently while working on long
> chunks of data. Our suggested solution uses the existing block layer
> (that is part of the standard Linux storage stack) feature that
> gathers number of block to into one request and then encrypt/decrypt
> the data, whereas eCryptfs can only perform the crypto operation on
> single pages. This feature was tested on our platforms and
> demonstrated very significance performance improvement comparing to
> existing SW based solutions
> 
> >> In order to use such HW efficiently with eCryptfs, eCryptfs encryption
> >> has
> >> to be canceled and it will need to call for external module instead that
> >> will do the correct marking for the blocks to distinguish between those
> >> that need to be encrypted by the HW from those that do not need.
> >>
> >> We are considering posting the code that will call
> >> ecryptfs_register_to_events() as a separate patch, but haven't done so
> >> yet. It is HW specific.
> >> Currently we are only proposing framework change so that it can allow
> >> for
> >> external modules to be connected
> >
> > In that case, I cannot accept this patch. I will have no way to test the
> > external module functionality and will not be able to make changes to
> > that area of the code because it will not be possible for me to fix
> > anything that I've broken. I won't even be able to know if I've broken
> > anything.
> >
> > If you are able to upstream the external module code, then I'll do a
> > proper review of this patch. I should note that I've only glanced at the
> > patch but if feels like it should be broken up into smaller, easier to
> > review patches before it can be properly reviewed.
> >
> > Tyler
> 
> We can upstream the external module code, however as I mentioned this
> module is specific for our HW, so you won't be able to test it either.
> However we can pretty easily turn it into some dummy module for testing
> purposes only that will just do prints instead of HW specific calls. Would
> this be sufficient ? If so, where in project tree should I put it ?
> 
> >
> >>
> >> > On 2015-11-09 20:56:02, andr...@codeaurora.org wrote:
> >> >> Hello, Tyler
> >> >>
> >> >> I'll try to provide more detailed explanation, should it be
> >> satisfactory
> >> >> enough I will update the patch description.
> >> >>
> >> >> The problem with current eCryptfs is that it has total control on how
> >> >> and
> >> >> when the encryption is performed and this control can't be altered.
> >> One
> >> >> example when this can be a problem is when we want to utilize an
> >> >> underlying inline HW encryption engine which allows encrypting blocks
> >> >> 'on
> >> >> the fly' as they are being written to the storage. In such a case
> >> >> relevant
> >> >> blocks just need to be marked as 'should be encrypted'. No actual
> >> >> encryption should be done by eCryptfs as it will be much slower.
> >> >
> >> > Is this a hardware 

Re: [PATCH v1] eCryptfs: enhancing eCryptfs to be used with external crypto engine

2015-11-09 Thread Michael Halcrow
On Mon, Nov 09, 2015 at 08:56:02PM -, andr...@codeaurora.org wrote:
> Hello, Tyler
> 
> I'll try to provide more detailed explanation, should it be satisfactory
> enough I will update the patch description.
> 
> The problem with current eCryptfs is that it has total control on how and
> when the encryption is performed and this control can't be altered.

That's by design.

eCryptfs has received at least one audit in 2014, and the auditor
didn't find any serious security flaws. eCryptfs users have
expectations about its security because of that.

It looks like you are replacing the encryption mechanism with an
out-of-kernel mechanism that implements a different encryption
mode. Users on this platform who use "eCryptfs" are actually getting
something different than what has been reviewed and audited.

On a first glance through the patch, it's not clear to me what this
out-of-kernel encryption mechanism is supposed to do. Can you point to
any design documents? From this patch, I gather that it implements
AES-256-XTS. Does the implementation conform to guidance in NIST
Special Publication 800-38E and IEEE P1619/D16?

> One example when this can be a problem is when we want to utilize an
> underlying inline HW encryption engine which allows encrypting blocks 'on
> the fly' as they are being written to the storage. In such a case relevant
> blocks just need to be marked as 'should be encrypted'. No actual
> encryption should be done by eCryptfs as it will be much slower.

What's the motivation for exposing this functionality through
eCryptfs? If eCryptfs really is the best place for this, then what are
the plans for EXT4 and F2FS, which both have per-file encryption? What
do your usage scenarios look like? What's your adversarial model?

> The provided framework allows transferring this control (if needed) to
> some external module which will do the encryption itfelf or just mark the
> appropriate blocks.
> 
> There is no caller for ecryptfs_register_to_events() since this change
> only provides framework, it doesn't provide the module itself, the module
> could be HW dependent.
> 
> Regarding the mounting option, it merely serves as example of new cipher
> mode that can be served by registered module.

If anyone can just easily swap out encryption modes, it's harder to
make any meaningful security statements about eCryptfs. Especially
given that pressure to hit benchmark targets can motivate unsafe
choices.

> There is a special callback function that should be implemented by the
> registered module that tells whether a particular cipher is supported by
> it :
> is_cipher_supported_cb()
> 
> The mounting option itself is not necessary, I can remove it
> 
> > Hello Andrey!
> >
> > On 2015-11-08 10:10:00, Andrey Markovytch wrote:
> >> From: Andrey Markovytch 
> >>
> >> Currently eCryptfs is responsible for page encryption/decryption.
> >> This approach will not work when there is HW inline encryption.
> >> The proposed change allows external module to register with eCryptfs
> >> and provide alternative encryption mechanism and also decide whether
> >> encryption should be performed at all, or deferred to a later stage via
> >> the inline HW engine.
> >> Additional cipher option was introduced to support the HW/external mode
> >> under that name of "aes-xts". If no external module has registered
> >> to support this cipher, eCryptfs will fall back to the usual "aes"
> >
> > What is "HW/external mode"? There's no description in the commit message
> > and ecryptfs_register_to_events() does not have a caller so I'm not sure
> > of the purpose. Please provide more context.
> >
> > Despite not yet understanding the purpose of this patch, I think that I
> > can safely say that "aes-xts" is not an appropriate mount option to use
> > when enabling this mode. eCryptfs may support XTS mode one day, using
> > the Crypto API, so "HW/external mode" should not own the mount option.
> >
> > Tyler
> >
> >>
> >> Signed-off-by: Lina Zarivach 
> >> Signed-off-by: Andrey Markovytch 
> >> ---
> >>  fs/ecryptfs/Makefile  |   4 +-
> >>  fs/ecryptfs/caches_utils.c|  78 +
> >>  fs/ecryptfs/crypto.c  | 200 +++
> >>  fs/ecryptfs/debug.c   |  13 ++
> >>  fs/ecryptfs/ecryptfs_kernel.h |  78 +
> >>  fs/ecryptfs/events.c  | 361
> >> ++
> >>  fs/ecryptfs/file.c|  36 +
> >>  fs/ecryptfs/inode.c   |  11 ++
> >>  fs/ecryptfs/keystore.c| 101 
> >>  fs/ecryptfs/main.c|  60 +--
> >>  fs/ecryptfs/mmap.c|   6 +
> >>  fs/ecryptfs/super.c   |  14 +-
> >>  include/linux/ecryptfs.h  |  47 ++
> >>  13 files changed, 940 insertions(+), 69 deletions(-)
> >>  create mode 100644 fs/ecryptfs/caches_utils.c
> >>  create mode 100644 fs/ecryptfs/events.c
> >>
> >> diff --git a/fs/ecryptfs/Makefile b/fs/ecryptfs/Makefile
> >> index 49678a6..995719c 100644
> >> --- 

Re: [PATCH v1] eCryptfs: enhancing eCryptfs to be used with external crypto engine

2015-11-09 Thread Michael Halcrow
On Mon, Nov 09, 2015 at 08:56:02PM -, andr...@codeaurora.org wrote:
> Hello, Tyler
> 
> I'll try to provide more detailed explanation, should it be satisfactory
> enough I will update the patch description.
> 
> The problem with current eCryptfs is that it has total control on how and
> when the encryption is performed and this control can't be altered.

That's by design.

eCryptfs has received at least one audit in 2014, and the auditor
didn't find any serious security flaws. eCryptfs users have
expectations about its security because of that.

It looks like you are replacing the encryption mechanism with an
out-of-kernel mechanism that implements a different encryption
mode. Users on this platform who use "eCryptfs" are actually getting
something different than what has been reviewed and audited.

On a first glance through the patch, it's not clear to me what this
out-of-kernel encryption mechanism is supposed to do. Can you point to
any design documents? From this patch, I gather that it implements
AES-256-XTS. Does the implementation conform to guidance in NIST
Special Publication 800-38E and IEEE P1619/D16?

> One example when this can be a problem is when we want to utilize an
> underlying inline HW encryption engine which allows encrypting blocks 'on
> the fly' as they are being written to the storage. In such a case relevant
> blocks just need to be marked as 'should be encrypted'. No actual
> encryption should be done by eCryptfs as it will be much slower.

What's the motivation for exposing this functionality through
eCryptfs? If eCryptfs really is the best place for this, then what are
the plans for EXT4 and F2FS, which both have per-file encryption? What
do your usage scenarios look like? What's your adversarial model?

> The provided framework allows transferring this control (if needed) to
> some external module which will do the encryption itfelf or just mark the
> appropriate blocks.
> 
> There is no caller for ecryptfs_register_to_events() since this change
> only provides framework, it doesn't provide the module itself, the module
> could be HW dependent.
> 
> Regarding the mounting option, it merely serves as example of new cipher
> mode that can be served by registered module.

If anyone can just easily swap out encryption modes, it's harder to
make any meaningful security statements about eCryptfs. Especially
given that pressure to hit benchmark targets can motivate unsafe
choices.

> There is a special callback function that should be implemented by the
> registered module that tells whether a particular cipher is supported by
> it :
> is_cipher_supported_cb()
> 
> The mounting option itself is not necessary, I can remove it
> 
> > Hello Andrey!
> >
> > On 2015-11-08 10:10:00, Andrey Markovytch wrote:
> >> From: Andrey Markovytch 
> >>
> >> Currently eCryptfs is responsible for page encryption/decryption.
> >> This approach will not work when there is HW inline encryption.
> >> The proposed change allows external module to register with eCryptfs
> >> and provide alternative encryption mechanism and also decide whether
> >> encryption should be performed at all, or deferred to a later stage via
> >> the inline HW engine.
> >> Additional cipher option was introduced to support the HW/external mode
> >> under that name of "aes-xts". If no external module has registered
> >> to support this cipher, eCryptfs will fall back to the usual "aes"
> >
> > What is "HW/external mode"? There's no description in the commit message
> > and ecryptfs_register_to_events() does not have a caller so I'm not sure
> > of the purpose. Please provide more context.
> >
> > Despite not yet understanding the purpose of this patch, I think that I
> > can safely say that "aes-xts" is not an appropriate mount option to use
> > when enabling this mode. eCryptfs may support XTS mode one day, using
> > the Crypto API, so "HW/external mode" should not own the mount option.
> >
> > Tyler
> >
> >>
> >> Signed-off-by: Lina Zarivach 
> >> Signed-off-by: Andrey Markovytch 
> >> ---
> >>  fs/ecryptfs/Makefile  |   4 +-
> >>  fs/ecryptfs/caches_utils.c|  78 +
> >>  fs/ecryptfs/crypto.c  | 200 +++
> >>  fs/ecryptfs/debug.c   |  13 ++
> >>  fs/ecryptfs/ecryptfs_kernel.h |  78 +
> >>  fs/ecryptfs/events.c  | 361
> >> ++
> >>  fs/ecryptfs/file.c|  36 +
> >>  fs/ecryptfs/inode.c   |  11 ++
> >>  fs/ecryptfs/keystore.c| 101 
> >>  fs/ecryptfs/main.c|  60 +--
> >>  fs/ecryptfs/mmap.c|   6 +
> >>  fs/ecryptfs/super.c   |  14 +-
> >>  include/linux/ecryptfs.h  |  47 ++
> >>  13 files changed, 940 insertions(+), 69 deletions(-)
> >>  create mode 100644 fs/ecryptfs/caches_utils.c
> >>  create mode 100644 fs/ecryptfs/events.c
> >>
> >> diff --git 

Re: [PATCH 076/196] ecryptfs: remove version_str file from sysfs

2008-01-25 Thread Michael Halcrow
On Fri, Jan 25, 2008 at 09:54:21AM -0800, Greg KH wrote:
> I could not find any userspace tools or documentation that used it

The version_str handle is only there as a potential convenience for
users who need to figure out what their module can and cannot do. I
mentioned it in an article in LJ last year. It does not need to be
there for any tools to work right, and I do not think that anyone
really cares about it at this point, so I have no problem with just
ripping it out.

Mike
--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to [EMAIL PROTECTED]
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/


Re: [PATCH 076/196] ecryptfs: remove version_str file from sysfs

2008-01-25 Thread Michael Halcrow
On Fri, Jan 25, 2008 at 09:54:21AM -0800, Greg KH wrote:
 I could not find any userspace tools or documentation that used it

The version_str handle is only there as a potential convenience for
users who need to figure out what their module can and cannot do. I
mentioned it in an article in LJ last year. It does not need to be
there for any tools to work right, and I do not think that anyone
really cares about it at this point, so I have no problem with just
ripping it out.

Mike
--
To unsubscribe from this list: send the line unsubscribe linux-kernel in
the body of a message to [EMAIL PROTECTED]
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/


Re: [UNIONFS] 00/29 Unionfs and related patches pre-merge review (v2)

2008-01-16 Thread Michael Halcrow
On Thu, Jan 10, 2008 at 10:57:46AM -0500, Erez Zadok wrote:
> In message <[EMAIL PROTECTED]>, Christoph Hellwig
> writes:
> > On Thu, Jan 10, 2008 at 09:59:19AM -0500, Erez Zadok wrote:
> > > 
> > > Dear Linus, Al, Christoph, and Andrew,
> > > 
> > > As per your request, I'm posting for review the unionfs code
> > > (and related code) that's in my korg tree against mainline
> > > (v2.6.24-rc7-71-gfd0b45d).  This is in preparation for merge in
> > > 2.6.25.
> > 
> > Huh?  There's still aboslutely not fix to the underlying problems
> > of the whole idea.  I think we made it pretty clear that unionfs
> > is not the way to go, and that we'll get the union mount patches
> > clear once the per-mountpoint r/o and unprivilegued mount patches
> > series are in and stable.
> 
> I'll reiterate what I've said before: unionfs is used today by many
> users, it works, and is stable.  After years of working with
> unionfs, we've settled on a set of features that users actually use.
> This functionality can be in mainline today.

There are well-known distributions out there that are tacking Unionfs
onto their kernels; for instance, it is popular in the bootable
read-only media scene. When enough vendors are adding the code on
their own, it is generally a good indicator that it should just be
upstream, especially if it can be built as a non-invasive experimental
module with a caveat about its shortcomings in the config menu and
documentation.

> Unioning at the VFS level, will take a long time to reach the same level of
> maturity and support the same set of features.  Based on my years of
> practical experience with it, unioning directories seems like a simple idea,
> but in practice it's quite hard no matter the approach taken to implement
> it.
> 
> Existing users of unioning aren't likely to switch to Union Mounts
> unless it supports the same set of features.  How long will it
> realistically take to get whiteout support in every lower file
> system that's used by Unionfs users?

Well, depending on the amount of code that actually needs to get
pushed below the VFS layer itself, I think you would be surprised how
quickly something like this can be done. But I do agree that a
non-invasive stacked module is a reasonable intermediate step in the
meantime, so long as the users understand the potential shortcomings
and are able to substantially benefit from its present inclusion in
mainline.

> How will Union Mounts support persistent inode numbers at the VFS
> level?  Those are just a few of the questions.
> 
> I think a better approach would be to start with Unionfs (a
> standalone file system that doesn't touch the rest of the kernel).
> And as Linux gradually starts supporting more and more features that
> help unioning/stacking in general, to change Unionfs to use those
> features (e.g., native whiteout support).  Eventually there could be
> basic unioning support at the VFS level, and concurrently a
> file-system which offers the extra features (e.g., persistency).
> This can be done w/o affecting user-visible APIs.

Would the inclusion of Unionfs in mainline really slow down or damage
the union mount effort? If not, then I think the pragmatic approach
would be to make it available in mainline for all of the users who are
already successfully running it today. We can then focus future
efforts on the VFS-level modifications that address the remaining
issues, limiting Unionfs in the future to only those problems that are
best solved in a stacked filesystem layer.

Mike
--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to [EMAIL PROTECTED]
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/


Re: [UNIONFS] 00/29 Unionfs and related patches pre-merge review (v2)

2008-01-16 Thread Michael Halcrow
On Thu, Jan 10, 2008 at 10:57:46AM -0500, Erez Zadok wrote:
 In message [EMAIL PROTECTED], Christoph Hellwig
 writes:
  On Thu, Jan 10, 2008 at 09:59:19AM -0500, Erez Zadok wrote:
   
   Dear Linus, Al, Christoph, and Andrew,
   
   As per your request, I'm posting for review the unionfs code
   (and related code) that's in my korg tree against mainline
   (v2.6.24-rc7-71-gfd0b45d).  This is in preparation for merge in
   2.6.25.
  
  Huh?  There's still aboslutely not fix to the underlying problems
  of the whole idea.  I think we made it pretty clear that unionfs
  is not the way to go, and that we'll get the union mount patches
  clear once the per-mountpoint r/o and unprivilegued mount patches
  series are in and stable.
 
 I'll reiterate what I've said before: unionfs is used today by many
 users, it works, and is stable.  After years of working with
 unionfs, we've settled on a set of features that users actually use.
 This functionality can be in mainline today.

There are well-known distributions out there that are tacking Unionfs
onto their kernels; for instance, it is popular in the bootable
read-only media scene. When enough vendors are adding the code on
their own, it is generally a good indicator that it should just be
upstream, especially if it can be built as a non-invasive experimental
module with a caveat about its shortcomings in the config menu and
documentation.

 Unioning at the VFS level, will take a long time to reach the same level of
 maturity and support the same set of features.  Based on my years of
 practical experience with it, unioning directories seems like a simple idea,
 but in practice it's quite hard no matter the approach taken to implement
 it.
 
 Existing users of unioning aren't likely to switch to Union Mounts
 unless it supports the same set of features.  How long will it
 realistically take to get whiteout support in every lower file
 system that's used by Unionfs users?

Well, depending on the amount of code that actually needs to get
pushed below the VFS layer itself, I think you would be surprised how
quickly something like this can be done. But I do agree that a
non-invasive stacked module is a reasonable intermediate step in the
meantime, so long as the users understand the potential shortcomings
and are able to substantially benefit from its present inclusion in
mainline.

 How will Union Mounts support persistent inode numbers at the VFS
 level?  Those are just a few of the questions.
 
 I think a better approach would be to start with Unionfs (a
 standalone file system that doesn't touch the rest of the kernel).
 And as Linux gradually starts supporting more and more features that
 help unioning/stacking in general, to change Unionfs to use those
 features (e.g., native whiteout support).  Eventually there could be
 basic unioning support at the VFS level, and concurrently a
 file-system which offers the extra features (e.g., persistency).
 This can be done w/o affecting user-visible APIs.

Would the inclusion of Unionfs in mainline really slow down or damage
the union mount effort? If not, then I think the pragmatic approach
would be to make it available in mainline for all of the users who are
already successfully running it today. We can then focus future
efforts on the VFS-level modifications that address the remaining
issues, limiting Unionfs in the future to only those problems that are
best solved in a stacked filesystem layer.

Mike
--
To unsubscribe from this list: send the line unsubscribe linux-kernel in
the body of a message to [EMAIL PROTECTED]
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/


Re: [PATCH] eCryptfs: Fix dentry handling on create error, unlink, and inode destroy

2008-01-08 Thread Michael Halcrow
On Mon, Jan 07, 2008 at 09:45:17PM -0800, Andrew Morton wrote:
> On Mon, 7 Jan 2008 23:25:42 -0600 Michael Halcrow <[EMAIL PROTECTED]> wrote:
> 
> > --- a/fs/ecryptfs/inode.c
> > +++ b/fs/ecryptfs/inode.c
> > @@ -120,22 +120,9 @@ ecryptfs_do_create(struct inode *directory_inode,
> > rc = ecryptfs_create_underlying_file(lower_dir_dentry->d_inode,
> >  ecryptfs_dentry, mode, nd);
> > if (rc) {
> > -   struct inode *ecryptfs_inode = ecryptfs_dentry->d_inode;
> > -   struct ecryptfs_inode_info *inode_info =
> > -   ecryptfs_inode_to_private(ecryptfs_inode);
> > -
> > -   printk(KERN_WARNING "%s: Error creating underlying file; "
> > -  "rc = [%d]; checking for existing\n", __FUNCTION__, rc);
> > -   if (inode_info) {
> > -   mutex_lock(_info->lower_file_mutex);
> > -   if (!inode_info->lower_file) {
> > -   mutex_unlock(_info->lower_file_mutex);
> > -   printk(KERN_ERR "%s: Failure to set underlying "
> > -  "file; rc = [%d]\n", __FUNCTION__, rc);
> > -   goto out_lock;
> > -   }
> > -   mutex_unlock(_info->lower_file_mutex);
> > -   }
> > +   printk(KERN_ERR "%s: Failure to create dentry in lower fs; "
> > +  "rc = [%d]\n", __FUNCTION__, rc);
> > +   goto out_lock;
> > }
> > rc = ecryptfs_interpose(lower_dentry, ecryptfs_dentry,
> > directory_inode->i_sb, 0);
> 
> Will this cause an undesirable log storm if the underlying fs runs
> out of space?

When you're bumping up against the end of your storage space, you will
get a lot more that just this message in your logs. There are printk's
in ecryptfs_write_lower(), ecryptfs_encrypt_page(), ecryptfs_write(),
and ecryptfs_write_metadata_to_contents() that will get pretty
noisy. Is it worth wrapping those in a higher level of verbosity?

Mike
--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to [EMAIL PROTECTED]
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/


Re: [PATCH] eCryptfs: Load each file decryption key only once

2008-01-08 Thread Michael Halcrow
On Fri, Dec 21, 2007 at 08:05:30PM -0600, Trevor Highland wrote:
> eCryptfs: Load each file decryption key only once
> 
> There is no need to keep re-setting the same key for any given
> eCryptfs inode. This patch optimizes the use of the crypto API and
> helps performance a bit.

There is no reason for the crypt_stat->key value for any given
eCryptfs inode to change during the life of the inode, and each
crypt_stat gets its own crypto transform, so I do not see a problem
with Trevor's suggestion. It will save unnecessary calls to
crypto_blkcipher_setkey(), and I expect it will speed things up a
little.

I include an updated patch against 2.6.24-rc7.

Signed-off-by: Michael Halcrow <[EMAIL PROTECTED]>
---
 fs/ecryptfs/crypto.c  |   40 ++--
 fs/ecryptfs/ecryptfs_kernel.h |1 +
 2 files changed, 23 insertions(+), 18 deletions(-)

diff --git a/fs/ecryptfs/crypto.c b/fs/ecryptfs/crypto.c
index f8ef0af..40849cf 100644
--- a/fs/ecryptfs/crypto.c
+++ b/fs/ecryptfs/crypto.c
@@ -353,16 +353,18 @@ static int encrypt_scatterlist(struct ecryptfs_crypt_stat 
*crypt_stat,
ecryptfs_dump_hex(crypt_stat->key,
  crypt_stat->key_size);
}
-   /* Consider doing this once, when the file is opened */
mutex_lock(_stat->cs_tfm_mutex);
-   rc = crypto_blkcipher_setkey(crypt_stat->tfm, crypt_stat->key,
-crypt_stat->key_size);
-   if (rc) {
-   ecryptfs_printk(KERN_ERR, "Error setting key; rc = [%d]\n",
-   rc);
-   mutex_unlock(_stat->cs_tfm_mutex);
-   rc = -EINVAL;
-   goto out;
+   if (!(crypt_stat->flags & ECRYPTFS_TFM_KEY_SET)) {
+   rc = crypto_blkcipher_setkey(crypt_stat->tfm, crypt_stat->key,
+crypt_stat->key_size);
+   if (rc) {
+   printk(KERN_ERR "%s: Error setting key; rc = [%d]\n",
+  __FUNCTION__, rc);
+   mutex_unlock(_stat->cs_tfm_mutex);
+   rc = -EINVAL;
+   goto out;
+   }
+   crypt_stat->flags |= ECRYPTFS_TFM_KEY_SET;
}
ecryptfs_printk(KERN_DEBUG, "Encrypting [%d] bytes.\n", size);
crypto_blkcipher_encrypt_iv(, dest_sg, src_sg, size);
@@ -685,16 +687,18 @@ static int decrypt_scatterlist(struct ecryptfs_crypt_stat 
*crypt_stat,
};
int rc = 0;
 
-   /* Consider doing this once, when the file is opened */
mutex_lock(_stat->cs_tfm_mutex);
-   rc = crypto_blkcipher_setkey(crypt_stat->tfm, crypt_stat->key,
-crypt_stat->key_size);
-   if (rc) {
-   ecryptfs_printk(KERN_ERR, "Error setting key; rc = [%d]\n",
-   rc);
-   mutex_unlock(_stat->cs_tfm_mutex);
-   rc = -EINVAL;
-   goto out;
+   if (!(crypt_stat->flags & ECRYPTFS_TFM_KEY_SET)) {
+   rc = crypto_blkcipher_setkey(crypt_stat->tfm, crypt_stat->key,
+crypt_stat->key_size);
+   if (rc) {
+   printk(KERN_ERR "%s: Error setting key; rc = [%d]\n",
+  __FUNCTION__, rc);
+   mutex_unlock(_stat->cs_tfm_mutex);
+   rc = -EINVAL;
+   goto out;
+   }
+   crypt_stat->flags |= ECRYPTFS_TFM_KEY_SET;
}
ecryptfs_printk(KERN_DEBUG, "Decrypting [%d] bytes.\n", size);
rc = crypto_blkcipher_decrypt_iv(, dest_sg, src_sg, size);
diff --git a/fs/ecryptfs/ecryptfs_kernel.h b/fs/ecryptfs/ecryptfs_kernel.h
index ce7a5d4..2abb110 100644
--- a/fs/ecryptfs/ecryptfs_kernel.h
+++ b/fs/ecryptfs/ecryptfs_kernel.h
@@ -234,6 +234,7 @@ struct ecryptfs_crypt_stat {
 #define ECRYPTFS_KEY_VALID  0x0080
 #define ECRYPTFS_METADATA_IN_XATTR  0x0100
 #define ECRYPTFS_VIEW_AS_ENCRYPTED  0x0200
+#define ECRYPTFS_TFM_KEY_SET0x0400
u32 flags;
unsigned int file_version;
size_t iv_bytes;
-- 
1.5.0.6



> Signed-off-by: Trevor Highland <[EMAIL PROTECTED]>
> ---
>  fs/ecryptfs/crypto.c |9 +
>  1 files changed, 5 insertions(+), 4 deletions(-)
> 
> diff --git a/fs/ecryptfs/crypto.c b/fs/ecryptfs/crypto.c
> index 70f7aab..949fe44 100644
> --- a/fs/ecryptfs/crypto.c
> +++ b/fs/ecryptfs/crypto.c
> @@ -353,7 +353,6 @@ static int encrypt_scatterlist(struct ecryptfs_crypt_stat 
> *crypt_stat,
>   ecryptfs_dump_hex(crypt_stat->key,
> crypt_stat->key_size);
>   }
&g

Re: [PATCH] eCryptfs: Load each file decryption key only once

2008-01-08 Thread Michael Halcrow
On Fri, Dec 21, 2007 at 08:05:30PM -0600, Trevor Highland wrote:
 eCryptfs: Load each file decryption key only once
 
 There is no need to keep re-setting the same key for any given
 eCryptfs inode. This patch optimizes the use of the crypto API and
 helps performance a bit.

There is no reason for the crypt_stat-key value for any given
eCryptfs inode to change during the life of the inode, and each
crypt_stat gets its own crypto transform, so I do not see a problem
with Trevor's suggestion. It will save unnecessary calls to
crypto_blkcipher_setkey(), and I expect it will speed things up a
little.

I include an updated patch against 2.6.24-rc7.

Signed-off-by: Michael Halcrow [EMAIL PROTECTED]
---
 fs/ecryptfs/crypto.c  |   40 ++--
 fs/ecryptfs/ecryptfs_kernel.h |1 +
 2 files changed, 23 insertions(+), 18 deletions(-)

diff --git a/fs/ecryptfs/crypto.c b/fs/ecryptfs/crypto.c
index f8ef0af..40849cf 100644
--- a/fs/ecryptfs/crypto.c
+++ b/fs/ecryptfs/crypto.c
@@ -353,16 +353,18 @@ static int encrypt_scatterlist(struct ecryptfs_crypt_stat 
*crypt_stat,
ecryptfs_dump_hex(crypt_stat-key,
  crypt_stat-key_size);
}
-   /* Consider doing this once, when the file is opened */
mutex_lock(crypt_stat-cs_tfm_mutex);
-   rc = crypto_blkcipher_setkey(crypt_stat-tfm, crypt_stat-key,
-crypt_stat-key_size);
-   if (rc) {
-   ecryptfs_printk(KERN_ERR, Error setting key; rc = [%d]\n,
-   rc);
-   mutex_unlock(crypt_stat-cs_tfm_mutex);
-   rc = -EINVAL;
-   goto out;
+   if (!(crypt_stat-flags  ECRYPTFS_TFM_KEY_SET)) {
+   rc = crypto_blkcipher_setkey(crypt_stat-tfm, crypt_stat-key,
+crypt_stat-key_size);
+   if (rc) {
+   printk(KERN_ERR %s: Error setting key; rc = [%d]\n,
+  __FUNCTION__, rc);
+   mutex_unlock(crypt_stat-cs_tfm_mutex);
+   rc = -EINVAL;
+   goto out;
+   }
+   crypt_stat-flags |= ECRYPTFS_TFM_KEY_SET;
}
ecryptfs_printk(KERN_DEBUG, Encrypting [%d] bytes.\n, size);
crypto_blkcipher_encrypt_iv(desc, dest_sg, src_sg, size);
@@ -685,16 +687,18 @@ static int decrypt_scatterlist(struct ecryptfs_crypt_stat 
*crypt_stat,
};
int rc = 0;
 
-   /* Consider doing this once, when the file is opened */
mutex_lock(crypt_stat-cs_tfm_mutex);
-   rc = crypto_blkcipher_setkey(crypt_stat-tfm, crypt_stat-key,
-crypt_stat-key_size);
-   if (rc) {
-   ecryptfs_printk(KERN_ERR, Error setting key; rc = [%d]\n,
-   rc);
-   mutex_unlock(crypt_stat-cs_tfm_mutex);
-   rc = -EINVAL;
-   goto out;
+   if (!(crypt_stat-flags  ECRYPTFS_TFM_KEY_SET)) {
+   rc = crypto_blkcipher_setkey(crypt_stat-tfm, crypt_stat-key,
+crypt_stat-key_size);
+   if (rc) {
+   printk(KERN_ERR %s: Error setting key; rc = [%d]\n,
+  __FUNCTION__, rc);
+   mutex_unlock(crypt_stat-cs_tfm_mutex);
+   rc = -EINVAL;
+   goto out;
+   }
+   crypt_stat-flags |= ECRYPTFS_TFM_KEY_SET;
}
ecryptfs_printk(KERN_DEBUG, Decrypting [%d] bytes.\n, size);
rc = crypto_blkcipher_decrypt_iv(desc, dest_sg, src_sg, size);
diff --git a/fs/ecryptfs/ecryptfs_kernel.h b/fs/ecryptfs/ecryptfs_kernel.h
index ce7a5d4..2abb110 100644
--- a/fs/ecryptfs/ecryptfs_kernel.h
+++ b/fs/ecryptfs/ecryptfs_kernel.h
@@ -234,6 +234,7 @@ struct ecryptfs_crypt_stat {
 #define ECRYPTFS_KEY_VALID  0x0080
 #define ECRYPTFS_METADATA_IN_XATTR  0x0100
 #define ECRYPTFS_VIEW_AS_ENCRYPTED  0x0200
+#define ECRYPTFS_TFM_KEY_SET0x0400
u32 flags;
unsigned int file_version;
size_t iv_bytes;
-- 
1.5.0.6



 Signed-off-by: Trevor Highland [EMAIL PROTECTED]
 ---
  fs/ecryptfs/crypto.c |9 +
  1 files changed, 5 insertions(+), 4 deletions(-)
 
 diff --git a/fs/ecryptfs/crypto.c b/fs/ecryptfs/crypto.c
 index 70f7aab..949fe44 100644
 --- a/fs/ecryptfs/crypto.c
 +++ b/fs/ecryptfs/crypto.c
 @@ -353,7 +353,6 @@ static int encrypt_scatterlist(struct ecryptfs_crypt_stat 
 *crypt_stat,
   ecryptfs_dump_hex(crypt_stat-key,
 crypt_stat-key_size);
   }
 - /* Consider doing this once, when the file is opened */
   mutex_lock(crypt_stat-cs_tfm_mutex);
   if (!(crypt_stat-flags  ECRYPTFS_KEY_SET)) {
   rc = crypto_blkcipher_setkey(crypt_stat-tfm, crypt_stat-key,
 @@ -687,10

Re: [PATCH] eCryptfs: Fix dentry handling on create error, unlink, and inode destroy

2008-01-08 Thread Michael Halcrow
On Mon, Jan 07, 2008 at 09:45:17PM -0800, Andrew Morton wrote:
 On Mon, 7 Jan 2008 23:25:42 -0600 Michael Halcrow [EMAIL PROTECTED] wrote:
 
  --- a/fs/ecryptfs/inode.c
  +++ b/fs/ecryptfs/inode.c
  @@ -120,22 +120,9 @@ ecryptfs_do_create(struct inode *directory_inode,
  rc = ecryptfs_create_underlying_file(lower_dir_dentry-d_inode,
   ecryptfs_dentry, mode, nd);
  if (rc) {
  -   struct inode *ecryptfs_inode = ecryptfs_dentry-d_inode;
  -   struct ecryptfs_inode_info *inode_info =
  -   ecryptfs_inode_to_private(ecryptfs_inode);
  -
  -   printk(KERN_WARNING %s: Error creating underlying file; 
  -  rc = [%d]; checking for existing\n, __FUNCTION__, rc);
  -   if (inode_info) {
  -   mutex_lock(inode_info-lower_file_mutex);
  -   if (!inode_info-lower_file) {
  -   mutex_unlock(inode_info-lower_file_mutex);
  -   printk(KERN_ERR %s: Failure to set underlying 
  -  file; rc = [%d]\n, __FUNCTION__, rc);
  -   goto out_lock;
  -   }
  -   mutex_unlock(inode_info-lower_file_mutex);
  -   }
  +   printk(KERN_ERR %s: Failure to create dentry in lower fs; 
  +  rc = [%d]\n, __FUNCTION__, rc);
  +   goto out_lock;
  }
  rc = ecryptfs_interpose(lower_dentry, ecryptfs_dentry,
  directory_inode-i_sb, 0);
 
 Will this cause an undesirable log storm if the underlying fs runs
 out of space?

When you're bumping up against the end of your storage space, you will
get a lot more that just this message in your logs. There are printk's
in ecryptfs_write_lower(), ecryptfs_encrypt_page(), ecryptfs_write(),
and ecryptfs_write_metadata_to_contents() that will get pretty
noisy. Is it worth wrapping those in a higher level of verbosity?

Mike
--
To unsubscribe from this list: send the line unsubscribe linux-kernel in
the body of a message to [EMAIL PROTECTED]
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/


[PATCH] eCryptfs: Fix dentry handling on create error, unlink, and inode destroy

2008-01-07 Thread Michael Halcrow
This patch corrects some erroneous dentry handling in eCryptfs.

If there is a problem creating the lower file, then there is nothing
that the persistent lower file can do to really help us. This patch
makes a vfs_create() failure in the lower filesystem always lead to an
unconditional do_create failure in eCryptfs.

Under certain sequences of operations, the eCryptfs dentry can remain
in the dcache after an unlink. This patch calls d_drop() on the
eCryptfs dentry to correct this.

eCryptfs has no business calling d_delete() directly on a lower
filesystem's dentry. This patch removes the call to d_delete() on the
lower persistent file's dentry in ecryptfs_destroy_inode().

(Thanks to David Kleikamp, Eric Sandeen, and Jeff Moyer for helping
identify and resolve this issue)

Signed-off-by: Michael Halcrow <[EMAIL PROTECTED]>
---
 fs/ecryptfs/inode.c |   20 
 fs/ecryptfs/super.c |1 -
 2 files changed, 4 insertions(+), 17 deletions(-)

diff --git a/fs/ecryptfs/inode.c b/fs/ecryptfs/inode.c
index 0b1ab01..5a71918 100644
--- a/fs/ecryptfs/inode.c
+++ b/fs/ecryptfs/inode.c
@@ -120,22 +120,9 @@ ecryptfs_do_create(struct inode *directory_inode,
rc = ecryptfs_create_underlying_file(lower_dir_dentry->d_inode,
 ecryptfs_dentry, mode, nd);
if (rc) {
-   struct inode *ecryptfs_inode = ecryptfs_dentry->d_inode;
-   struct ecryptfs_inode_info *inode_info =
-   ecryptfs_inode_to_private(ecryptfs_inode);
-
-   printk(KERN_WARNING "%s: Error creating underlying file; "
-  "rc = [%d]; checking for existing\n", __FUNCTION__, rc);
-   if (inode_info) {
-   mutex_lock(_info->lower_file_mutex);
-   if (!inode_info->lower_file) {
-   mutex_unlock(_info->lower_file_mutex);
-   printk(KERN_ERR "%s: Failure to set underlying "
-  "file; rc = [%d]\n", __FUNCTION__, rc);
-   goto out_lock;
-   }
-   mutex_unlock(_info->lower_file_mutex);
-   }
+   printk(KERN_ERR "%s: Failure to create dentry in lower fs; "
+  "rc = [%d]\n", __FUNCTION__, rc);
+   goto out_lock;
}
rc = ecryptfs_interpose(lower_dentry, ecryptfs_dentry,
directory_inode->i_sb, 0);
@@ -451,6 +438,7 @@ static int ecryptfs_unlink(struct inode *dir, struct dentry 
*dentry)
dentry->d_inode->i_nlink =
ecryptfs_inode_to_lower(dentry->d_inode)->i_nlink;
dentry->d_inode->i_ctime = dir->i_ctime;
+   d_drop(dentry);
 out_unlock:
unlock_parent(lower_dentry);
return rc;
diff --git a/fs/ecryptfs/super.c b/fs/ecryptfs/super.c
index f8cdab2..4859c4e 100644
--- a/fs/ecryptfs/super.c
+++ b/fs/ecryptfs/super.c
@@ -86,7 +86,6 @@ static void ecryptfs_destroy_inode(struct inode *inode)
fput(inode_info->lower_file);
inode_info->lower_file = NULL;
d_drop(lower_dentry);
-   d_delete(lower_dentry);
}
}
mutex_unlock(_info->lower_file_mutex);
-- 
1.5.3.6

--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to [EMAIL PROTECTED]
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/


[PATCH] eCryptfs: Fix dentry handling on create error, unlink, and inode destroy

2008-01-07 Thread Michael Halcrow
This patch corrects some erroneous dentry handling in eCryptfs.

If there is a problem creating the lower file, then there is nothing
that the persistent lower file can do to really help us. This patch
makes a vfs_create() failure in the lower filesystem always lead to an
unconditional do_create failure in eCryptfs.

Under certain sequences of operations, the eCryptfs dentry can remain
in the dcache after an unlink. This patch calls d_drop() on the
eCryptfs dentry to correct this.

eCryptfs has no business calling d_delete() directly on a lower
filesystem's dentry. This patch removes the call to d_delete() on the
lower persistent file's dentry in ecryptfs_destroy_inode().

(Thanks to David Kleikamp, Eric Sandeen, and Jeff Moyer for helping
identify and resolve this issue)

Signed-off-by: Michael Halcrow [EMAIL PROTECTED]
---
 fs/ecryptfs/inode.c |   20 
 fs/ecryptfs/super.c |1 -
 2 files changed, 4 insertions(+), 17 deletions(-)

diff --git a/fs/ecryptfs/inode.c b/fs/ecryptfs/inode.c
index 0b1ab01..5a71918 100644
--- a/fs/ecryptfs/inode.c
+++ b/fs/ecryptfs/inode.c
@@ -120,22 +120,9 @@ ecryptfs_do_create(struct inode *directory_inode,
rc = ecryptfs_create_underlying_file(lower_dir_dentry-d_inode,
 ecryptfs_dentry, mode, nd);
if (rc) {
-   struct inode *ecryptfs_inode = ecryptfs_dentry-d_inode;
-   struct ecryptfs_inode_info *inode_info =
-   ecryptfs_inode_to_private(ecryptfs_inode);
-
-   printk(KERN_WARNING %s: Error creating underlying file; 
-  rc = [%d]; checking for existing\n, __FUNCTION__, rc);
-   if (inode_info) {
-   mutex_lock(inode_info-lower_file_mutex);
-   if (!inode_info-lower_file) {
-   mutex_unlock(inode_info-lower_file_mutex);
-   printk(KERN_ERR %s: Failure to set underlying 
-  file; rc = [%d]\n, __FUNCTION__, rc);
-   goto out_lock;
-   }
-   mutex_unlock(inode_info-lower_file_mutex);
-   }
+   printk(KERN_ERR %s: Failure to create dentry in lower fs; 
+  rc = [%d]\n, __FUNCTION__, rc);
+   goto out_lock;
}
rc = ecryptfs_interpose(lower_dentry, ecryptfs_dentry,
directory_inode-i_sb, 0);
@@ -451,6 +438,7 @@ static int ecryptfs_unlink(struct inode *dir, struct dentry 
*dentry)
dentry-d_inode-i_nlink =
ecryptfs_inode_to_lower(dentry-d_inode)-i_nlink;
dentry-d_inode-i_ctime = dir-i_ctime;
+   d_drop(dentry);
 out_unlock:
unlock_parent(lower_dentry);
return rc;
diff --git a/fs/ecryptfs/super.c b/fs/ecryptfs/super.c
index f8cdab2..4859c4e 100644
--- a/fs/ecryptfs/super.c
+++ b/fs/ecryptfs/super.c
@@ -86,7 +86,6 @@ static void ecryptfs_destroy_inode(struct inode *inode)
fput(inode_info-lower_file);
inode_info-lower_file = NULL;
d_drop(lower_dentry);
-   d_delete(lower_dentry);
}
}
mutex_unlock(inode_info-lower_file_mutex);
-- 
1.5.3.6

--
To unsubscribe from this list: send the line unsubscribe linux-kernel in
the body of a message to [EMAIL PROTECTED]
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/


Re: [PATCH] ecryptfs: check for existing key_tfm at mount time

2007-12-21 Thread Michael Halcrow
On Thu, Dec 20, 2007 at 11:18:49PM -0600, Eric Sandeen wrote:
> Jeff Moyer pointed out that a mount; umount loop of ecryptfs,
> with the same cipher & other mount options, created a new 
> ecryptfs_key_tfm_cache item each time, and the cache could
> grow quite large this way.
> 
> Looking at this with mhalcrow, we saw that ecryptfs_parse_options()
> unconditionally called ecryptfs_add_new_key_tfm(), which is what
> was adding these items.
> 
> Refactor ecryptfs_get_tfm_and_mutex_for_cipher_name() to create a 
> new helper function, ecryptfs_tfm_exists(), which checks for the 
> cipher on the cached key_tfm_list, and sets a pointer
> to it if it exists.  This can then be called from 
> ecryptfs_parse_options(), and new key_tfm's can be added only when
> a cached one is not found.
> 
> Signed-off-by: Eric Sandeen <[EMAIL PROTECTED]>

Acked-by: Mike Halcrow <[EMAIL PROTECTED]>

> ---
> 
> Index: linux-2.6.24-rc3/fs/ecryptfs/crypto.c
> ===
> --- linux-2.6.24-rc3.orig/fs/ecryptfs/crypto.c
> +++ linux-2.6.24-rc3/fs/ecryptfs/crypto.c
> @@ -1868,6 +1868,33 @@ out:
>   return rc;
>  }
> 
> +/**
> + * ecryptfs_tfm_exists - Search for existing tfm for cipher_name.
> + * @cipher_name: the name of the cipher to search for
> + * @key_tfm: set to corresponding tfm if found
> + *
> + * Returns 1 if found, with key_tfm set
> + * Returns 0 if not found, key_tfm set to NULL
> + */
> +int ecryptfs_tfm_exists(char *cipher_name, struct ecryptfs_key_tfm **key_tfm)
> +{
> + struct ecryptfs_key_tfm *tmp_key_tfm;
> +
> + mutex_lock(_tfm_list_mutex);
> + list_for_each_entry(tmp_key_tfm, _tfm_list, key_tfm_list) {
> + if (strcmp(tmp_key_tfm->cipher_name, cipher_name) == 0) {
> + mutex_unlock(_tfm_list_mutex);
> + if (key_tfm)
> + (*key_tfm) = tmp_key_tfm;
> + return 1;
> + }
> + }
> + mutex_unlock(_tfm_list_mutex);
> + if (key_tfm)
> + (*key_tfm) = NULL;
> + return 0;
> +}
> +
>  int ecryptfs_get_tfm_and_mutex_for_cipher_name(struct crypto_blkcipher **tfm,
>  struct mutex **tfm_mutex,
>  char *cipher_name)
> @@ -1877,22 +1904,15 @@ int ecryptfs_get_tfm_and_mutex_for_ciphe
> 
>   (*tfm) = NULL;
>   (*tfm_mutex) = NULL;
> - mutex_lock(_tfm_list_mutex);
> - list_for_each_entry(key_tfm, _tfm_list, key_tfm_list) {
> - if (strcmp(key_tfm->cipher_name, cipher_name) == 0) {
> - (*tfm) = key_tfm->key_tfm;
> - (*tfm_mutex) = _tfm->key_tfm_mutex;
> - mutex_unlock(_tfm_list_mutex);
> +
> + if (!ecryptfs_tfm_exists(cipher_name, _tfm)) {
> + rc = ecryptfs_add_new_key_tfm(_tfm, cipher_name, 0);
> + if (rc) {
> + printk(KERN_ERR "Error adding new key_tfm to list; "
> + "rc = [%d]\n", rc);
>   goto out;
>   }
>   }
> - mutex_unlock(_tfm_list_mutex);
> - rc = ecryptfs_add_new_key_tfm(_tfm, cipher_name, 0);
> - if (rc) {
> - printk(KERN_ERR "Error adding new key_tfm to list; rc = [%d]\n",
> -rc);
> - goto out;
> - }
>   (*tfm) = key_tfm->key_tfm;
>   (*tfm_mutex) = _tfm->key_tfm_mutex;
>  out:
> Index: linux-2.6.24-rc3/fs/ecryptfs/ecryptfs_kernel.h
> ===
> --- linux-2.6.24-rc3.orig/fs/ecryptfs/ecryptfs_kernel.h
> +++ linux-2.6.24-rc3/fs/ecryptfs/ecryptfs_kernel.h
> @@ -623,6 +623,7 @@ ecryptfs_add_new_key_tfm(struct ecryptfs
>size_t key_size);
>  int ecryptfs_init_crypto(void);
>  int ecryptfs_destroy_crypto(void);
> +int ecryptfs_tfm_exists(char *cipher_name, struct ecryptfs_key_tfm 
> **key_tfm);
>  int ecryptfs_get_tfm_and_mutex_for_cipher_name(struct crypto_blkcipher **tfm,
>  struct mutex **tfm_mutex,
>  char *cipher_name);
> Index: linux-2.6.24-rc3/fs/ecryptfs/main.c
> ===
> --- linux-2.6.24-rc3.orig/fs/ecryptfs/main.c
> +++ linux-2.6.24-rc3/fs/ecryptfs/main.c
> @@ -410,9 +410,11 @@ static int ecryptfs_parse_options(struct
>   if (!cipher_key_bytes_set) {
>   mount_crypt_stat->global_default_cipher_key_size = 0;
>   }
> - rc = ecryptfs_add_new_key_tfm(
> - NULL, mount_crypt_stat->global_default_cipher_name,
> - mount_crypt_stat->global_default_cipher_key_size);
> + if (!ecryptfs_tfm_exists(mount_crypt_stat->global_default_cipher_name,
> +  NULL))
> + rc = ecryptfs_add_new_key_tfm(
> + NULL, 

Re: [PATCH] ecryptfs: check for existing key_tfm at mount time

2007-12-21 Thread Michael Halcrow
On Thu, Dec 20, 2007 at 11:18:49PM -0600, Eric Sandeen wrote:
 Jeff Moyer pointed out that a mount; umount loop of ecryptfs,
 with the same cipher  other mount options, created a new 
 ecryptfs_key_tfm_cache item each time, and the cache could
 grow quite large this way.
 
 Looking at this with mhalcrow, we saw that ecryptfs_parse_options()
 unconditionally called ecryptfs_add_new_key_tfm(), which is what
 was adding these items.
 
 Refactor ecryptfs_get_tfm_and_mutex_for_cipher_name() to create a 
 new helper function, ecryptfs_tfm_exists(), which checks for the 
 cipher on the cached key_tfm_list, and sets a pointer
 to it if it exists.  This can then be called from 
 ecryptfs_parse_options(), and new key_tfm's can be added only when
 a cached one is not found.
 
 Signed-off-by: Eric Sandeen [EMAIL PROTECTED]

Acked-by: Mike Halcrow [EMAIL PROTECTED]

 ---
 
 Index: linux-2.6.24-rc3/fs/ecryptfs/crypto.c
 ===
 --- linux-2.6.24-rc3.orig/fs/ecryptfs/crypto.c
 +++ linux-2.6.24-rc3/fs/ecryptfs/crypto.c
 @@ -1868,6 +1868,33 @@ out:
   return rc;
  }
 
 +/**
 + * ecryptfs_tfm_exists - Search for existing tfm for cipher_name.
 + * @cipher_name: the name of the cipher to search for
 + * @key_tfm: set to corresponding tfm if found
 + *
 + * Returns 1 if found, with key_tfm set
 + * Returns 0 if not found, key_tfm set to NULL
 + */
 +int ecryptfs_tfm_exists(char *cipher_name, struct ecryptfs_key_tfm **key_tfm)
 +{
 + struct ecryptfs_key_tfm *tmp_key_tfm;
 +
 + mutex_lock(key_tfm_list_mutex);
 + list_for_each_entry(tmp_key_tfm, key_tfm_list, key_tfm_list) {
 + if (strcmp(tmp_key_tfm-cipher_name, cipher_name) == 0) {
 + mutex_unlock(key_tfm_list_mutex);
 + if (key_tfm)
 + (*key_tfm) = tmp_key_tfm;
 + return 1;
 + }
 + }
 + mutex_unlock(key_tfm_list_mutex);
 + if (key_tfm)
 + (*key_tfm) = NULL;
 + return 0;
 +}
 +
  int ecryptfs_get_tfm_and_mutex_for_cipher_name(struct crypto_blkcipher **tfm,
  struct mutex **tfm_mutex,
  char *cipher_name)
 @@ -1877,22 +1904,15 @@ int ecryptfs_get_tfm_and_mutex_for_ciphe
 
   (*tfm) = NULL;
   (*tfm_mutex) = NULL;
 - mutex_lock(key_tfm_list_mutex);
 - list_for_each_entry(key_tfm, key_tfm_list, key_tfm_list) {
 - if (strcmp(key_tfm-cipher_name, cipher_name) == 0) {
 - (*tfm) = key_tfm-key_tfm;
 - (*tfm_mutex) = key_tfm-key_tfm_mutex;
 - mutex_unlock(key_tfm_list_mutex);
 +
 + if (!ecryptfs_tfm_exists(cipher_name, key_tfm)) {
 + rc = ecryptfs_add_new_key_tfm(key_tfm, cipher_name, 0);
 + if (rc) {
 + printk(KERN_ERR Error adding new key_tfm to list; 
 + rc = [%d]\n, rc);
   goto out;
   }
   }
 - mutex_unlock(key_tfm_list_mutex);
 - rc = ecryptfs_add_new_key_tfm(key_tfm, cipher_name, 0);
 - if (rc) {
 - printk(KERN_ERR Error adding new key_tfm to list; rc = [%d]\n,
 -rc);
 - goto out;
 - }
   (*tfm) = key_tfm-key_tfm;
   (*tfm_mutex) = key_tfm-key_tfm_mutex;
  out:
 Index: linux-2.6.24-rc3/fs/ecryptfs/ecryptfs_kernel.h
 ===
 --- linux-2.6.24-rc3.orig/fs/ecryptfs/ecryptfs_kernel.h
 +++ linux-2.6.24-rc3/fs/ecryptfs/ecryptfs_kernel.h
 @@ -623,6 +623,7 @@ ecryptfs_add_new_key_tfm(struct ecryptfs
size_t key_size);
  int ecryptfs_init_crypto(void);
  int ecryptfs_destroy_crypto(void);
 +int ecryptfs_tfm_exists(char *cipher_name, struct ecryptfs_key_tfm 
 **key_tfm);
  int ecryptfs_get_tfm_and_mutex_for_cipher_name(struct crypto_blkcipher **tfm,
  struct mutex **tfm_mutex,
  char *cipher_name);
 Index: linux-2.6.24-rc3/fs/ecryptfs/main.c
 ===
 --- linux-2.6.24-rc3.orig/fs/ecryptfs/main.c
 +++ linux-2.6.24-rc3/fs/ecryptfs/main.c
 @@ -410,9 +410,11 @@ static int ecryptfs_parse_options(struct
   if (!cipher_key_bytes_set) {
   mount_crypt_stat-global_default_cipher_key_size = 0;
   }
 - rc = ecryptfs_add_new_key_tfm(
 - NULL, mount_crypt_stat-global_default_cipher_name,
 - mount_crypt_stat-global_default_cipher_key_size);
 + if (!ecryptfs_tfm_exists(mount_crypt_stat-global_default_cipher_name,
 +  NULL))
 + rc = ecryptfs_add_new_key_tfm(
 + NULL, mount_crypt_stat-global_default_cipher_name,
 + mount_crypt_stat-global_default_cipher_key_size);
   if (rc) 

[PATCH] eCryptfs: Minor fixes to printk messages

2007-12-19 Thread Michael Halcrow
The printk statements that result when the user does not have the
proper key available could use some refining.

Signed-off-by: Mike Halcrow <[EMAIL PROTECTED]>
---
diff --git a/fs/ecryptfs/crypto.c b/fs/ecryptfs/crypto.c
index f8ef0af..beba580 100644
--- a/fs/ecryptfs/crypto.c
+++ b/fs/ecryptfs/crypto.c
@@ -1552,9 +1552,10 @@ int ecryptfs_read_xattr_region(char *page_virt, struct 
inode *ecryptfs_inode)
size = ecryptfs_getxattr_lower(lower_dentry, ECRYPTFS_XATTR_NAME,
   page_virt, ECRYPTFS_DEFAULT_EXTENT_SIZE);
if (size < 0) {
-   printk(KERN_ERR "Error attempting to read the [%s] "
-  "xattr from the lower file; return value = [%zd]\n",
-  ECRYPTFS_XATTR_NAME, size);
+   if (unlikely(ecryptfs_verbosity > 0))
+   printk(KERN_INFO "Error attempting to read the [%s] "
+  "xattr from the lower file; return value = "
+  "[%zd]\n", ECRYPTFS_XATTR_NAME, size);
rc = -EINVAL;
goto out;
}
diff --git a/fs/ecryptfs/file.c b/fs/ecryptfs/file.c
index c98c469..2b8f5ed 100644
--- a/fs/ecryptfs/file.c
+++ b/fs/ecryptfs/file.c
@@ -209,9 +209,10 @@ static int ecryptfs_open(struct inode *inode, struct file 
*file)
if (!(mount_crypt_stat->flags
  & ECRYPTFS_PLAINTEXT_PASSTHROUGH_ENABLED)) {
rc = -EIO;
-   printk(KERN_WARNING "Attempt to read file that "
+   printk(KERN_WARNING "Either the lower file "
   "is not in a valid eCryptfs format, "
-  "and plaintext passthrough mode is not "
+  "or the key could not be retrieved. "
+  "Plaintext passthrough mode is not "
   "enabled; returning -EIO\n");
mutex_unlock(_stat->cs_mutex);
goto out_free;
diff --git a/fs/ecryptfs/inode.c b/fs/ecryptfs/inode.c
index 0b1ab01..2b29e2b 100644
--- a/fs/ecryptfs/inode.c
+++ b/fs/ecryptfs/inode.c
@@ -887,11 +887,11 @@ static int ecryptfs_setattr(struct dentry *dentry, struct 
iattr *ia)
if (!(mount_crypt_stat->flags
  & ECRYPTFS_PLAINTEXT_PASSTHROUGH_ENABLED)) {
rc = -EIO;
-   printk(KERN_WARNING "Attempt to read file that "
+   printk(KERN_WARNING "Either the lower file "
   "is not in a valid eCryptfs format, "
-  "and plaintext passthrough mode is not "
+  "or the key could not be retrieved. "
+  "Plaintext passthrough mode is not "
   "enabled; returning -EIO\n");
-
mutex_unlock(_stat->cs_mutex);
goto out;
}
--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to [EMAIL PROTECTED]
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/


Re: [PATCH] ecryptfs: redo dget,mntget on dentry_open failure

2007-12-19 Thread Michael Halcrow
On Wed, Dec 19, 2007 at 11:34:25AM -0600, Eric Sandeen wrote:
> Thanks to Jeff Moyer for pointing this out.
> 
> If the RDWR dentry_open() in ecryptfs_init_persistent_file fails,
> it will do a dput/mntput.  Need to re-take references if we
> retry as RDONLY.
> 
> Signed-off-by: Eric Sandeen <[EMAIL PROTECTED]>

Acked-by: Mike Halcrow <[EMAIL PROTECTED]>

> ---
> 
> Index: linux-2.6.24-rc3/fs/ecryptfs/main.c
> ===
> --- linux-2.6.24-rc3.orig/fs/ecryptfs/main.c
> +++ linux-2.6.24-rc3/fs/ecryptfs/main.c
> @@ -138,11 +138,14 @@ int ecryptfs_init_persistent_file(struct
>   inode_info->lower_file = dentry_open(lower_dentry,
>lower_mnt,
>(O_RDWR | O_LARGEFILE));
> - if (IS_ERR(inode_info->lower_file))
> + if (IS_ERR(inode_info->lower_file)) {
> + dget(lower_dentry);
> + mntget(lower_mnt);
>   inode_info->lower_file = dentry_open(lower_dentry,
>lower_mnt,
>(O_RDONLY
> | O_LARGEFILE));
> + }
>   if (IS_ERR(inode_info->lower_file)) {
>   printk(KERN_ERR "Error opening lower persistent file "
>  "for lower_dentry [0x%p] and lower_mnt [0x%p]\n",
> 
--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to [EMAIL PROTECTED]
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/


Re: [PATCH] ecryptfs: remove debug as mount option, and warn if set via modprobe

2007-12-19 Thread Michael Halcrow
On Wed, Dec 19, 2007 at 11:50:19AM -0600, Eric Sandeen wrote:
> ecryptfs_debug really should not be a mount option; it is not
> per-mount, but rather sets a global "ecryptfs_verbosity" variable
> which affects all mounted filesysytems.  It's already settable as a
> module load option, I think we can leave it at that.
> 
> Also, if set, since secret values come out in debug messages, kick
> things off with a stern warning.
> 
> Signed-off-by: Eric Sandeen <[EMAIL PROTECTED]>

Makes sense to me.

Acked-by: Mike Halcrow <[EMAIL PROTECTED]>

> ---
> 
> ndex: linux-2.6.24-rc3/fs/ecryptfs/main.c
> ===
> --- linux-2.6.24-rc3.orig/fs/ecryptfs/main.c
> +++ linux-2.6.24-rc3/fs/ecryptfs/main.c
> @@ -226,17 +226,15 @@ out:
>   return rc;
>  }
>  
> -enum { ecryptfs_opt_sig, ecryptfs_opt_ecryptfs_sig, ecryptfs_opt_debug,
> -   ecryptfs_opt_ecryptfs_debug, ecryptfs_opt_cipher,
> -   ecryptfs_opt_ecryptfs_cipher, ecryptfs_opt_ecryptfs_key_bytes,
> +enum { ecryptfs_opt_sig, ecryptfs_opt_ecryptfs_sig,
> +   ecryptfs_opt_cipher, ecryptfs_opt_ecryptfs_cipher,
> +   ecryptfs_opt_ecryptfs_key_bytes,
> ecryptfs_opt_passthrough, ecryptfs_opt_xattr_metadata,
> ecryptfs_opt_encrypted_view, ecryptfs_opt_err };
>  
>  static match_table_t tokens = {
>   {ecryptfs_opt_sig, "sig=%s"},
>   {ecryptfs_opt_ecryptfs_sig, "ecryptfs_sig=%s"},
> - {ecryptfs_opt_debug, "debug=%u"},
> - {ecryptfs_opt_ecryptfs_debug, "ecryptfs_debug=%u"},
>   {ecryptfs_opt_cipher, "cipher=%s"},
>   {ecryptfs_opt_ecryptfs_cipher, "ecryptfs_cipher=%s"},
>   {ecryptfs_opt_ecryptfs_key_bytes, "ecryptfs_key_bytes=%u"},
> @@ -313,7 +311,6 @@ static int ecryptfs_parse_options(struct
>   substring_t args[MAX_OPT_ARGS];
>   int token;
>   char *sig_src;
> - char *debug_src;
>   char *cipher_name_dst;
>   char *cipher_name_src;
>   char *cipher_key_bytes_src;
> @@ -341,16 +338,6 @@ static int ecryptfs_parse_options(struct
>   }
>   sig_set = 1;
>   break;
> - case ecryptfs_opt_debug:
> - case ecryptfs_opt_ecryptfs_debug:
> - debug_src = args[0].from;
> - ecryptfs_verbosity =
> - (int)simple_strtol(debug_src, _src,
> -0);
> - ecryptfs_printk(KERN_DEBUG,
> - "Verbosity set to [%d]" "\n",
> - ecryptfs_verbosity);
> - break;
>   case ecryptfs_opt_cipher:
>   case ecryptfs_opt_ecryptfs_cipher:
>   cipher_name_src = args[0].from;
> @@ -911,6 +898,10 @@ static int __init ecryptfs_init(void)
>  "rc = [%d]\n", rc);
>   goto out_release_messaging;
>   }
> + if (ecryptfs_verbosity > 0)
> + printk(KERN_CRIT "eCryptfs verbosity set to %d. Secret values "
> + "will be written to the syslog!\n", ecryptfs_verbosity);
> +
>   goto out;
>  out_release_messaging:
>   ecryptfs_release_messaging(ecryptfs_transport);
> Index: linux-2.6.24-rc3/fs/ecryptfs/super.c
> ===
> --- linux-2.6.24-rc3.orig/fs/ecryptfs/super.c
> +++ linux-2.6.24-rc3/fs/ecryptfs/super.c
> @@ -175,10 +175,6 @@ static int ecryptfs_show_options(struct 
>   }
>   mutex_unlock(_crypt_stat->global_auth_tok_list_mutex);
>  
> - /* Note this is global and probably shouldn't be a mount option */
> - if (ecryptfs_verbosity)
> - seq_printf(m, ",ecryptfs_debug=%d\n", ecryptfs_verbosity);
> -
>   seq_printf(m, ",ecryptfs_cipher=%s",
>   mount_crypt_stat->global_default_cipher_name);
>  
> 
--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to [EMAIL PROTECTED]
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/


Re: [PATCH] ecryptfs: redo dget,mntget on dentry_open failure

2007-12-19 Thread Michael Halcrow
On Wed, Dec 19, 2007 at 11:34:25AM -0600, Eric Sandeen wrote:
 Thanks to Jeff Moyer for pointing this out.
 
 If the RDWR dentry_open() in ecryptfs_init_persistent_file fails,
 it will do a dput/mntput.  Need to re-take references if we
 retry as RDONLY.
 
 Signed-off-by: Eric Sandeen [EMAIL PROTECTED]

Acked-by: Mike Halcrow [EMAIL PROTECTED]

 ---
 
 Index: linux-2.6.24-rc3/fs/ecryptfs/main.c
 ===
 --- linux-2.6.24-rc3.orig/fs/ecryptfs/main.c
 +++ linux-2.6.24-rc3/fs/ecryptfs/main.c
 @@ -138,11 +138,14 @@ int ecryptfs_init_persistent_file(struct
   inode_info-lower_file = dentry_open(lower_dentry,
lower_mnt,
(O_RDWR | O_LARGEFILE));
 - if (IS_ERR(inode_info-lower_file))
 + if (IS_ERR(inode_info-lower_file)) {
 + dget(lower_dentry);
 + mntget(lower_mnt);
   inode_info-lower_file = dentry_open(lower_dentry,
lower_mnt,
(O_RDONLY
 | O_LARGEFILE));
 + }
   if (IS_ERR(inode_info-lower_file)) {
   printk(KERN_ERR Error opening lower persistent file 
  for lower_dentry [0x%p] and lower_mnt [0x%p]\n,
 
--
To unsubscribe from this list: send the line unsubscribe linux-kernel in
the body of a message to [EMAIL PROTECTED]
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/


Re: [PATCH] ecryptfs: remove debug as mount option, and warn if set via modprobe

2007-12-19 Thread Michael Halcrow
On Wed, Dec 19, 2007 at 11:50:19AM -0600, Eric Sandeen wrote:
 ecryptfs_debug really should not be a mount option; it is not
 per-mount, but rather sets a global ecryptfs_verbosity variable
 which affects all mounted filesysytems.  It's already settable as a
 module load option, I think we can leave it at that.
 
 Also, if set, since secret values come out in debug messages, kick
 things off with a stern warning.
 
 Signed-off-by: Eric Sandeen [EMAIL PROTECTED]

Makes sense to me.

Acked-by: Mike Halcrow [EMAIL PROTECTED]

 ---
 
 ndex: linux-2.6.24-rc3/fs/ecryptfs/main.c
 ===
 --- linux-2.6.24-rc3.orig/fs/ecryptfs/main.c
 +++ linux-2.6.24-rc3/fs/ecryptfs/main.c
 @@ -226,17 +226,15 @@ out:
   return rc;
  }
  
 -enum { ecryptfs_opt_sig, ecryptfs_opt_ecryptfs_sig, ecryptfs_opt_debug,
 -   ecryptfs_opt_ecryptfs_debug, ecryptfs_opt_cipher,
 -   ecryptfs_opt_ecryptfs_cipher, ecryptfs_opt_ecryptfs_key_bytes,
 +enum { ecryptfs_opt_sig, ecryptfs_opt_ecryptfs_sig,
 +   ecryptfs_opt_cipher, ecryptfs_opt_ecryptfs_cipher,
 +   ecryptfs_opt_ecryptfs_key_bytes,
 ecryptfs_opt_passthrough, ecryptfs_opt_xattr_metadata,
 ecryptfs_opt_encrypted_view, ecryptfs_opt_err };
  
  static match_table_t tokens = {
   {ecryptfs_opt_sig, sig=%s},
   {ecryptfs_opt_ecryptfs_sig, ecryptfs_sig=%s},
 - {ecryptfs_opt_debug, debug=%u},
 - {ecryptfs_opt_ecryptfs_debug, ecryptfs_debug=%u},
   {ecryptfs_opt_cipher, cipher=%s},
   {ecryptfs_opt_ecryptfs_cipher, ecryptfs_cipher=%s},
   {ecryptfs_opt_ecryptfs_key_bytes, ecryptfs_key_bytes=%u},
 @@ -313,7 +311,6 @@ static int ecryptfs_parse_options(struct
   substring_t args[MAX_OPT_ARGS];
   int token;
   char *sig_src;
 - char *debug_src;
   char *cipher_name_dst;
   char *cipher_name_src;
   char *cipher_key_bytes_src;
 @@ -341,16 +338,6 @@ static int ecryptfs_parse_options(struct
   }
   sig_set = 1;
   break;
 - case ecryptfs_opt_debug:
 - case ecryptfs_opt_ecryptfs_debug:
 - debug_src = args[0].from;
 - ecryptfs_verbosity =
 - (int)simple_strtol(debug_src, debug_src,
 -0);
 - ecryptfs_printk(KERN_DEBUG,
 - Verbosity set to [%d] \n,
 - ecryptfs_verbosity);
 - break;
   case ecryptfs_opt_cipher:
   case ecryptfs_opt_ecryptfs_cipher:
   cipher_name_src = args[0].from;
 @@ -911,6 +898,10 @@ static int __init ecryptfs_init(void)
  rc = [%d]\n, rc);
   goto out_release_messaging;
   }
 + if (ecryptfs_verbosity  0)
 + printk(KERN_CRIT eCryptfs verbosity set to %d. Secret values 
 + will be written to the syslog!\n, ecryptfs_verbosity);
 +
   goto out;
  out_release_messaging:
   ecryptfs_release_messaging(ecryptfs_transport);
 Index: linux-2.6.24-rc3/fs/ecryptfs/super.c
 ===
 --- linux-2.6.24-rc3.orig/fs/ecryptfs/super.c
 +++ linux-2.6.24-rc3/fs/ecryptfs/super.c
 @@ -175,10 +175,6 @@ static int ecryptfs_show_options(struct 
   }
   mutex_unlock(mount_crypt_stat-global_auth_tok_list_mutex);
  
 - /* Note this is global and probably shouldn't be a mount option */
 - if (ecryptfs_verbosity)
 - seq_printf(m, ,ecryptfs_debug=%d\n, ecryptfs_verbosity);
 -
   seq_printf(m, ,ecryptfs_cipher=%s,
   mount_crypt_stat-global_default_cipher_name);
  
 
--
To unsubscribe from this list: send the line unsubscribe linux-kernel in
the body of a message to [EMAIL PROTECTED]
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/


[PATCH] eCryptfs: Minor fixes to printk messages

2007-12-19 Thread Michael Halcrow
The printk statements that result when the user does not have the
proper key available could use some refining.

Signed-off-by: Mike Halcrow [EMAIL PROTECTED]
---
diff --git a/fs/ecryptfs/crypto.c b/fs/ecryptfs/crypto.c
index f8ef0af..beba580 100644
--- a/fs/ecryptfs/crypto.c
+++ b/fs/ecryptfs/crypto.c
@@ -1552,9 +1552,10 @@ int ecryptfs_read_xattr_region(char *page_virt, struct 
inode *ecryptfs_inode)
size = ecryptfs_getxattr_lower(lower_dentry, ECRYPTFS_XATTR_NAME,
   page_virt, ECRYPTFS_DEFAULT_EXTENT_SIZE);
if (size  0) {
-   printk(KERN_ERR Error attempting to read the [%s] 
-  xattr from the lower file; return value = [%zd]\n,
-  ECRYPTFS_XATTR_NAME, size);
+   if (unlikely(ecryptfs_verbosity  0))
+   printk(KERN_INFO Error attempting to read the [%s] 
+  xattr from the lower file; return value = 
+  [%zd]\n, ECRYPTFS_XATTR_NAME, size);
rc = -EINVAL;
goto out;
}
diff --git a/fs/ecryptfs/file.c b/fs/ecryptfs/file.c
index c98c469..2b8f5ed 100644
--- a/fs/ecryptfs/file.c
+++ b/fs/ecryptfs/file.c
@@ -209,9 +209,10 @@ static int ecryptfs_open(struct inode *inode, struct file 
*file)
if (!(mount_crypt_stat-flags
   ECRYPTFS_PLAINTEXT_PASSTHROUGH_ENABLED)) {
rc = -EIO;
-   printk(KERN_WARNING Attempt to read file that 
+   printk(KERN_WARNING Either the lower file 
   is not in a valid eCryptfs format, 
-  and plaintext passthrough mode is not 
+  or the key could not be retrieved. 
+  Plaintext passthrough mode is not 
   enabled; returning -EIO\n);
mutex_unlock(crypt_stat-cs_mutex);
goto out_free;
diff --git a/fs/ecryptfs/inode.c b/fs/ecryptfs/inode.c
index 0b1ab01..2b29e2b 100644
--- a/fs/ecryptfs/inode.c
+++ b/fs/ecryptfs/inode.c
@@ -887,11 +887,11 @@ static int ecryptfs_setattr(struct dentry *dentry, struct 
iattr *ia)
if (!(mount_crypt_stat-flags
   ECRYPTFS_PLAINTEXT_PASSTHROUGH_ENABLED)) {
rc = -EIO;
-   printk(KERN_WARNING Attempt to read file that 
+   printk(KERN_WARNING Either the lower file 
   is not in a valid eCryptfs format, 
-  and plaintext passthrough mode is not 
+  or the key could not be retrieved. 
+  Plaintext passthrough mode is not 
   enabled; returning -EIO\n);
-
mutex_unlock(crypt_stat-cs_mutex);
goto out;
}
--
To unsubscribe from this list: send the line unsubscribe linux-kernel in
the body of a message to [EMAIL PROTECTED]
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/


Re: [PATCH] ecryptfs: fix string overflow on long cipher names

2007-12-18 Thread Michael Halcrow
On Tue, Dec 18, 2007 at 09:51:15AM -0600, Eric Sandeen wrote:
> Passing a cipher name > 32 chars on mount results in an overflow
> when the cipher name is printed, because the last character
> in the struct ecryptfs_key_tfm's cipher_name string was never 
> zeroed.
> 
> Signed-off-by: Eric Sandeen <[EMAIL PROTECTED]>

Acked-by: Michael Halcrow <[EMAIL PROTECTED]>

I don't think this causes any issues outside of a couple of printk's
on error paths, but this should definitely go into the next -rc.

> ---
> 
> Index: linux-2.6.24-rc3/fs/ecryptfs/crypto.c
> ===
> --- linux-2.6.24-rc3.orig/fs/ecryptfs/crypto.c
> +++ linux-2.6.24-rc3/fs/ecryptfs/crypto.c
> @@ -1847,6 +1847,7 @@ ecryptfs_add_new_key_tfm(struct ecryptfs
>   mutex_init(_tfm->key_tfm_mutex);
>   strncpy(tmp_tfm->cipher_name, cipher_name,
>   ECRYPTFS_MAX_CIPHER_NAME_SIZE);
> + tmp_tfm->cipher_name[ECRYPTFS_MAX_CIPHER_NAME_SIZE] = '\0';
>   tmp_tfm->key_size = key_size;
>   rc = ecryptfs_process_key_cipher(_tfm->key_tfm,
>tmp_tfm->cipher_name,
> 
> 
> 
--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to [EMAIL PROTECTED]
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/


Re: [PATCH] ecryptfs: fix string overflow on long cipher names

2007-12-18 Thread Michael Halcrow
On Tue, Dec 18, 2007 at 09:51:15AM -0600, Eric Sandeen wrote:
 Passing a cipher name  32 chars on mount results in an overflow
 when the cipher name is printed, because the last character
 in the struct ecryptfs_key_tfm's cipher_name string was never 
 zeroed.
 
 Signed-off-by: Eric Sandeen [EMAIL PROTECTED]

Acked-by: Michael Halcrow [EMAIL PROTECTED]

I don't think this causes any issues outside of a couple of printk's
on error paths, but this should definitely go into the next -rc.

 ---
 
 Index: linux-2.6.24-rc3/fs/ecryptfs/crypto.c
 ===
 --- linux-2.6.24-rc3.orig/fs/ecryptfs/crypto.c
 +++ linux-2.6.24-rc3/fs/ecryptfs/crypto.c
 @@ -1847,6 +1847,7 @@ ecryptfs_add_new_key_tfm(struct ecryptfs
   mutex_init(tmp_tfm-key_tfm_mutex);
   strncpy(tmp_tfm-cipher_name, cipher_name,
   ECRYPTFS_MAX_CIPHER_NAME_SIZE);
 + tmp_tfm-cipher_name[ECRYPTFS_MAX_CIPHER_NAME_SIZE] = '\0';
   tmp_tfm-key_size = key_size;
   rc = ecryptfs_process_key_cipher(tmp_tfm-key_tfm,
tmp_tfm-cipher_name,
 
 
 
--
To unsubscribe from this list: send the line unsubscribe linux-kernel in
the body of a message to [EMAIL PROTECTED]
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/


Re: [PATCH] ecryptfs: fix fsx data corruption problems

2007-12-17 Thread Michael Halcrow
On Sun, Dec 16, 2007 at 11:32:33PM -0600, Eric Sandeen wrote:
> ecryptfs in 2.6.24-rc3 wasn't surviving fsx for me at all,
> dying after 4 ops.  Generally, encountering problems with stale
> data and improperly zeroed pages.  An extending truncate + write
> for example would expose stale data.
> 
> With the changes below I got to a million ops and beyond with all
> mmap ops disabled - mmap still needs work.  (A version of this
> patch on a RHEL5 kernel ran for over 110 million fsx ops)
> 
> I added a few comments as well, to the best of my understanding
> as I read through the code.
> 
> Signed-off-by: Eric Sandeen <[EMAIL PROTECTED]>

Acked-by: Michael Halcrow <[EMAIL PROTECTED]>

I recommend this for the next -rc release.

> ---
> 
> 
> Index: linux-2.6.24-rc3/fs/ecryptfs/mmap.c
> ===
> --- linux-2.6.24-rc3.orig/fs/ecryptfs/mmap.c
> +++ linux-2.6.24-rc3/fs/ecryptfs/mmap.c
> @@ -263,14 +263,13 @@ out:
>   return 0;
>  }
>  
> +/* This function must zero any hole we create */
>  static int ecryptfs_prepare_write(struct file *file, struct page *page,
> unsigned from, unsigned to)
>  {
>   int rc = 0;
> + loff_t prev_page_end_size;
>  
> - if (from == 0 && to == PAGE_CACHE_SIZE)
> - goto out;   /* If we are writing a full page, it will be
> -up to date. */
>   if (!PageUptodate(page)) {
>   rc = ecryptfs_read_lower_page_segment(page, page->index, 0,
> PAGE_CACHE_SIZE,
> @@ -283,22 +282,32 @@ static int ecryptfs_prepare_write(struct
>   } else
>   SetPageUptodate(page);
>   }
> - if (page->index != 0) {
> - loff_t end_of_prev_pg_pos =
> - (((loff_t)page->index << PAGE_CACHE_SHIFT) - 1);
>  
> - if (end_of_prev_pg_pos > i_size_read(page->mapping->host)) {
> + prev_page_end_size = ((loff_t)page->index << PAGE_CACHE_SHIFT);
> +
> + /*
> +  * If creating a page or more of holes, zero them out via truncate.
> +  * Note, this will increase i_size.
> +  */
> + if (page->index != 0) {
> + if (prev_page_end_size > i_size_read(page->mapping->host)) {
>   rc = ecryptfs_truncate(file->f_path.dentry,
> -end_of_prev_pg_pos);
> +prev_page_end_size);
>   if (rc) {
>   printk(KERN_ERR "Error on attempt to "
>  "truncate to (higher) offset [%lld];"
> -" rc = [%d]\n", end_of_prev_pg_pos, rc);
> +" rc = [%d]\n", prev_page_end_size, rc);
>   goto out;
>   }
>   }
> - if (end_of_prev_pg_pos + 1 > i_size_read(page->mapping->host))
> - zero_user_page(page, 0, PAGE_CACHE_SIZE, KM_USER0);
> + }
> + /*
> +  * Writing to a new page, and creating a small hole from start of page?
> +  * Zero it out.
> +  */
> + if ((i_size_read(page->mapping->host) == prev_page_end_size) &&
> + (from != 0)) {
> + zero_user_page(page, 0, PAGE_CACHE_SIZE, KM_USER0);
>   }
>  out:
>   return rc;
> Index: linux-2.6.24-rc3/fs/ecryptfs/read_write.c
> ===
> --- linux-2.6.24-rc3.orig/fs/ecryptfs/read_write.c
> +++ linux-2.6.24-rc3/fs/ecryptfs/read_write.c
> @@ -124,6 +124,10 @@ int ecryptfs_write(struct file *ecryptfs
>   loff_t pos;
>   int rc = 0;
>  
> + /*
> +  * if we are writing beyond current size, then start pos
> +  * at the current size - we'll fill in zeros from there.
> +  */
>   if (offset > ecryptfs_file_size)
>   pos = ecryptfs_file_size;
>   else
> @@ -137,6 +141,7 @@ int ecryptfs_write(struct file *ecryptfs
>   if (num_bytes > total_remaining_bytes)
>   num_bytes = total_remaining_bytes;
>   if (pos < offset) {
> + /* remaining zeros to write, up to destination offset */
>   size_t total_remaining_zeros = (offset - pos);
>  
>   if (num_bytes > total_remaining_zeros)
> @@ -167,17 +172,27 @@ int ecryptfs_write(struct file *ecryptfs
&

Re: [PATCH] ecryptfs: fix fsx data corruption problems

2007-12-17 Thread Michael Halcrow
On Sun, Dec 16, 2007 at 11:32:33PM -0600, Eric Sandeen wrote:
 ecryptfs in 2.6.24-rc3 wasn't surviving fsx for me at all,
 dying after 4 ops.  Generally, encountering problems with stale
 data and improperly zeroed pages.  An extending truncate + write
 for example would expose stale data.
 
 With the changes below I got to a million ops and beyond with all
 mmap ops disabled - mmap still needs work.  (A version of this
 patch on a RHEL5 kernel ran for over 110 million fsx ops)
 
 I added a few comments as well, to the best of my understanding
 as I read through the code.
 
 Signed-off-by: Eric Sandeen [EMAIL PROTECTED]

Acked-by: Michael Halcrow [EMAIL PROTECTED]

I recommend this for the next -rc release.

 ---
 
 
 Index: linux-2.6.24-rc3/fs/ecryptfs/mmap.c
 ===
 --- linux-2.6.24-rc3.orig/fs/ecryptfs/mmap.c
 +++ linux-2.6.24-rc3/fs/ecryptfs/mmap.c
 @@ -263,14 +263,13 @@ out:
   return 0;
  }
  
 +/* This function must zero any hole we create */
  static int ecryptfs_prepare_write(struct file *file, struct page *page,
 unsigned from, unsigned to)
  {
   int rc = 0;
 + loff_t prev_page_end_size;
  
 - if (from == 0  to == PAGE_CACHE_SIZE)
 - goto out;   /* If we are writing a full page, it will be
 -up to date. */
   if (!PageUptodate(page)) {
   rc = ecryptfs_read_lower_page_segment(page, page-index, 0,
 PAGE_CACHE_SIZE,
 @@ -283,22 +282,32 @@ static int ecryptfs_prepare_write(struct
   } else
   SetPageUptodate(page);
   }
 - if (page-index != 0) {
 - loff_t end_of_prev_pg_pos =
 - (((loff_t)page-index  PAGE_CACHE_SHIFT) - 1);
  
 - if (end_of_prev_pg_pos  i_size_read(page-mapping-host)) {
 + prev_page_end_size = ((loff_t)page-index  PAGE_CACHE_SHIFT);
 +
 + /*
 +  * If creating a page or more of holes, zero them out via truncate.
 +  * Note, this will increase i_size.
 +  */
 + if (page-index != 0) {
 + if (prev_page_end_size  i_size_read(page-mapping-host)) {
   rc = ecryptfs_truncate(file-f_path.dentry,
 -end_of_prev_pg_pos);
 +prev_page_end_size);
   if (rc) {
   printk(KERN_ERR Error on attempt to 
  truncate to (higher) offset [%lld];
 - rc = [%d]\n, end_of_prev_pg_pos, rc);
 + rc = [%d]\n, prev_page_end_size, rc);
   goto out;
   }
   }
 - if (end_of_prev_pg_pos + 1  i_size_read(page-mapping-host))
 - zero_user_page(page, 0, PAGE_CACHE_SIZE, KM_USER0);
 + }
 + /*
 +  * Writing to a new page, and creating a small hole from start of page?
 +  * Zero it out.
 +  */
 + if ((i_size_read(page-mapping-host) == prev_page_end_size) 
 + (from != 0)) {
 + zero_user_page(page, 0, PAGE_CACHE_SIZE, KM_USER0);
   }
  out:
   return rc;
 Index: linux-2.6.24-rc3/fs/ecryptfs/read_write.c
 ===
 --- linux-2.6.24-rc3.orig/fs/ecryptfs/read_write.c
 +++ linux-2.6.24-rc3/fs/ecryptfs/read_write.c
 @@ -124,6 +124,10 @@ int ecryptfs_write(struct file *ecryptfs
   loff_t pos;
   int rc = 0;
  
 + /*
 +  * if we are writing beyond current size, then start pos
 +  * at the current size - we'll fill in zeros from there.
 +  */
   if (offset  ecryptfs_file_size)
   pos = ecryptfs_file_size;
   else
 @@ -137,6 +141,7 @@ int ecryptfs_write(struct file *ecryptfs
   if (num_bytes  total_remaining_bytes)
   num_bytes = total_remaining_bytes;
   if (pos  offset) {
 + /* remaining zeros to write, up to destination offset */
   size_t total_remaining_zeros = (offset - pos);
  
   if (num_bytes  total_remaining_zeros)
 @@ -167,17 +172,27 @@ int ecryptfs_write(struct file *ecryptfs
   }
   }
   ecryptfs_page_virt = kmap_atomic(ecryptfs_page, KM_USER0);
 +
 + /*
 +  * pos: where we're now writing, offset: where the request was
 +  * If current pos is before request, we are filling zeros
 +  * If we are at or beyond request, we are writing the *data*
 +  * If we're in a fresh page beyond eof, zero it in either case
 +  */
 + if (pos  offset || !start_offset_in_page) {
 + /* We are extending past the previous end of the file

Re: [PATCH] ecryptfs: set s_blocksize from lower fs in sb

2007-12-14 Thread Michael Halcrow
On Fri, Dec 14, 2007 at 09:30:26AM -0600, Eric Sandeen wrote:
> eCryptfs wasn't setting s_blocksize in it's superblock; just pick
> it up from the lower FS.  Having an s_blocksize of 0 made things
> like "filefrag" which call FIGETBSZ unhappy.
> 
> Signed-off-by: Eric Sandeen <[EMAIL PROTECTED]>

Acked-by: Mike Halcrow <[EMAIL PROTECTED]>

> 
> ---
> 
> Index: linux-2.6.24-rc3/fs/ecryptfs/main.c
> ===
> --- linux-2.6.24-rc3.orig/fs/ecryptfs/main.c
> +++ linux-2.6.24-rc3/fs/ecryptfs/main.c
> @@ -523,6 +523,7 @@ static int ecryptfs_read_super(struct su
>   lower_mnt = nd.mnt;
>   ecryptfs_set_superblock_lower(sb, lower_root->d_sb);
>   sb->s_maxbytes = lower_root->d_sb->s_maxbytes;
> + sb->s_blocksize = lower_root->d_sb->s_blocksize;
>   ecryptfs_set_dentry_lower(sb->s_root, lower_root);
>   ecryptfs_set_dentry_lower_mnt(sb->s_root, lower_mnt);
>   rc = ecryptfs_interpose(lower_root, sb->s_root, sb, 0);
> 
--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to [EMAIL PROTECTED]
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/


Re: [PATCH] ecryptfs: set s_blocksize from lower fs in sb

2007-12-14 Thread Michael Halcrow
On Fri, Dec 14, 2007 at 09:30:26AM -0600, Eric Sandeen wrote:
 eCryptfs wasn't setting s_blocksize in it's superblock; just pick
 it up from the lower FS.  Having an s_blocksize of 0 made things
 like filefrag which call FIGETBSZ unhappy.
 
 Signed-off-by: Eric Sandeen [EMAIL PROTECTED]

Acked-by: Mike Halcrow [EMAIL PROTECTED]

 
 ---
 
 Index: linux-2.6.24-rc3/fs/ecryptfs/main.c
 ===
 --- linux-2.6.24-rc3.orig/fs/ecryptfs/main.c
 +++ linux-2.6.24-rc3/fs/ecryptfs/main.c
 @@ -523,6 +523,7 @@ static int ecryptfs_read_super(struct su
   lower_mnt = nd.mnt;
   ecryptfs_set_superblock_lower(sb, lower_root-d_sb);
   sb-s_maxbytes = lower_root-d_sb-s_maxbytes;
 + sb-s_blocksize = lower_root-d_sb-s_blocksize;
   ecryptfs_set_dentry_lower(sb-s_root, lower_root);
   ecryptfs_set_dentry_lower_mnt(sb-s_root, lower_mnt);
   rc = ecryptfs_interpose(lower_root, sb-s_root, sb, 0);
 
--
To unsubscribe from this list: send the line unsubscribe linux-kernel in
the body of a message to [EMAIL PROTECTED]
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/


[PATCH] eCryptfs: Cast page->index to loff_t instead of off_t

2007-11-02 Thread Michael Halcrow
page->index should be cast to loff_t instead of off_t.

Signed-off-by: Michael Halcrow <[EMAIL PROTECTED]>
Reported-by: Eric Sandeen <[EMAIL PROTECTED]>
---
 fs/ecryptfs/read_write.c |2 +-
 1 files changed, 1 insertions(+), 1 deletions(-)

diff --git a/fs/ecryptfs/read_write.c b/fs/ecryptfs/read_write.c
index 2150edf..6b7474a 100644
--- a/fs/ecryptfs/read_write.c
+++ b/fs/ecryptfs/read_write.c
@@ -87,7 +87,7 @@ int ecryptfs_write_lower_page_segment(struct inode 
*ecryptfs_inode,
loff_t offset;
int rc;
 
-   offset = off_t)page_for_lower->index) << PAGE_CACHE_SHIFT)
+   offset = loff_t)page_for_lower->index) << PAGE_CACHE_SHIFT)
  + offset_in_page);
virt = kmap(page_for_lower);
rc = ecryptfs_write_lower(ecryptfs_inode, virt, offset, size);
-- 
1.5.1.6

-
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to [EMAIL PROTECTED]
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/


[PATCH] eCryptfs: Release mutex on hash error path

2007-11-02 Thread Michael Halcrow
On Mon, Oct 29, 2007 at 03:10:09PM +0900, Kazuki Ohta wrote:
> When IS_ERR(desc.tfm) is true, unlocking
> crypt_stat->cs_hash_tfm_mutex is forgotten.

Thanks for reporting this, Kazuki.
---

Release the crypt_stat hash mutex on allocation error. Check for error
conditions when doing crypto hash calls.

Signed-off-by: Michael Halcrow <[EMAIL PROTECTED]>
---
 fs/ecryptfs/crypto.c |   26 ++
 1 files changed, 22 insertions(+), 4 deletions(-)

diff --git a/fs/ecryptfs/crypto.c b/fs/ecryptfs/crypto.c
index a0f53aa..70f7aab 100644
--- a/fs/ecryptfs/crypto.c
+++ b/fs/ecryptfs/crypto.c
@@ -115,11 +115,29 @@ static int ecryptfs_calculate_md5(char *dst,
}
crypt_stat->hash_tfm = desc.tfm;
}
-   crypto_hash_init();
-   crypto_hash_update(, , len);
-   crypto_hash_final(, dst);
-   mutex_unlock(_stat->cs_hash_tfm_mutex);
+   rc = crypto_hash_init();
+   if (rc) {
+   printk(KERN_ERR
+  "%s: Error initializing crypto hash; rc = [%d]\n",
+  __FUNCTION__, rc);
+   goto out;
+   }
+   rc = crypto_hash_update(, , len);
+   if (rc) {
+   printk(KERN_ERR
+  "%s: Error updating crypto hash; rc = [%d]\n",
+  __FUNCTION__, rc);
+   goto out;
+   }
+   rc = crypto_hash_final(, dst);
+   if (rc) {
+   printk(KERN_ERR
+  "%s: Error finalizing crypto hash; rc = [%d]\n",
+  __FUNCTION__, rc);
+   goto out;
+   }
 out:
+   mutex_unlock(_stat->cs_hash_tfm_mutex);
return rc;
 }
 
-- 
1.5.0.6

-
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to [EMAIL PROTECTED]
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/


Re: [PATCH 3/3] eCryptfs: Set inode key only once per crypto operation

2007-11-02 Thread Michael Halcrow
On Fri, Nov 02, 2007 at 01:10:31PM -0700, Andrew Morton wrote:
> On Fri, 2 Nov 2007 13:53:08 -0500
> Michael Halcrow <[EMAIL PROTECTED]> wrote:
> 
> > There is no need to keep re-setting the same key for any given
> > eCryptfs inode. This patch optimizes the use of the crypto API and
> > helps performance a bit.
> > 
> > Signed-off-by: Trevor Highland <[EMAIL PROTECTED]>
> > Signed-off-by: Michael Halcrow <[EMAIL PROTECTED]>
> 
> I've inferred from this that Michael authored this patch.  Please
> let me know if that was incorrect.

Trevor Highland actually authored this one.

> The way in which we indicate authorship is to put a From: line right
> at the top of the changelog.  If no such line appears then the From:
> line from the mail headers is used.

Noted.

Mike


pgpEpeP8rGmGy.pgp
Description: PGP signature


[PATCH 3/3] eCryptfs: Set inode key only once per crypto operation

2007-11-02 Thread Michael Halcrow
There is no need to keep re-setting the same key for any given
eCryptfs inode. This patch optimizes the use of the crypto API and
helps performance a bit.

Signed-off-by: Trevor Highland <[EMAIL PROTECTED]>
Signed-off-by: Michael Halcrow <[EMAIL PROTECTED]>
---
 fs/ecryptfs/crypto.c  |7 +--
 fs/ecryptfs/ecryptfs_kernel.h |1 +
 2 files changed, 6 insertions(+), 2 deletions(-)

diff --git a/fs/ecryptfs/crypto.c b/fs/ecryptfs/crypto.c
index 4f14d4c..a0f53aa 100644
--- a/fs/ecryptfs/crypto.c
+++ b/fs/ecryptfs/crypto.c
@@ -337,8 +337,11 @@ static int encrypt_scatterlist(struct ecryptfs_crypt_stat 
*crypt_stat,
}
/* Consider doing this once, when the file is opened */
mutex_lock(_stat->cs_tfm_mutex);
-   rc = crypto_blkcipher_setkey(crypt_stat->tfm, crypt_stat->key,
-crypt_stat->key_size);
+   if (!(crypt_stat->flags & ECRYPTFS_KEY_SET)) {
+   rc = crypto_blkcipher_setkey(crypt_stat->tfm, crypt_stat->key,
+crypt_stat->key_size);
+   crypt_stat->flags |= ECRYPTFS_KEY_SET;
+   }
if (rc) {
ecryptfs_printk(KERN_ERR, "Error setting key; rc = [%d]\n",
rc);
diff --git a/fs/ecryptfs/ecryptfs_kernel.h b/fs/ecryptfs/ecryptfs_kernel.h
index 78b7916..114cb86 100644
--- a/fs/ecryptfs/ecryptfs_kernel.h
+++ b/fs/ecryptfs/ecryptfs_kernel.h
@@ -234,6 +234,7 @@ struct ecryptfs_crypt_stat {
 #define ECRYPTFS_KEY_VALID  0x0080
 #define ECRYPTFS_METADATA_IN_XATTR  0x0100
 #define ECRYPTFS_VIEW_AS_ENCRYPTED  0x0200
+#define ECRYPTFS_KEY_SET0x0400
u32 flags;
unsigned int file_version;
size_t iv_bytes;
-- 
1.5.0.6

-
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to [EMAIL PROTECTED]
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/


[PATCH 2/3] eCryptfs: Increment extent_offset once per loop interation

2007-11-02 Thread Michael Halcrow
The extent_offset is getting incremented twice per loop iteration
through any given page. It should only be getting incremented
once. This bug should only impact hosts with >4K page sizes.

Signed-off-by: Michael Halcrow <[EMAIL PROTECTED]>
---
 fs/ecryptfs/crypto.c |2 --
 1 files changed, 0 insertions(+), 2 deletions(-)

diff --git a/fs/ecryptfs/crypto.c b/fs/ecryptfs/crypto.c
index ca0dfea..4f14d4c 100644
--- a/fs/ecryptfs/crypto.c
+++ b/fs/ecryptfs/crypto.c
@@ -503,7 +503,6 @@ int ecryptfs_encrypt_page(struct page *page)
"\n", rc);
goto out;
}
-   extent_offset++;
}
 out:
kfree(enc_extent_virt);
@@ -639,7 +638,6 @@ int ecryptfs_decrypt_page(struct page *page)
   "rc = [%d]\n", __FUNCTION__, rc);
goto out;
}
-   extent_offset++;
}
 out:
kfree(enc_extent_virt);
-- 
1.5.0.6

-
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to [EMAIL PROTECTED]
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/


[PATCH 1/3] eCryptfs: Track header bytes rather than extents

2007-11-02 Thread Michael Halcrow
Remove internal references to header extents; just keep track of
header bytes instead. Headers can easily span multiple pages with the
recent persistent file changes.

Signed-off-by: Michael Halcrow <[EMAIL PROTECTED]>
---
 fs/ecryptfs/crypto.c  |   98 +++--
 fs/ecryptfs/ecryptfs_kernel.h |3 +-
 fs/ecryptfs/inode.c   |8 +--
 fs/ecryptfs/main.c|5 --
 fs/ecryptfs/mmap.c|   21 +
 5 files changed, 51 insertions(+), 84 deletions(-)

diff --git a/fs/ecryptfs/crypto.c b/fs/ecryptfs/crypto.c
index 9d70289..ca0dfea 100644
--- a/fs/ecryptfs/crypto.c
+++ b/fs/ecryptfs/crypto.c
@@ -361,8 +361,7 @@ out:
 void ecryptfs_lower_offset_for_extent(loff_t *offset, loff_t extent_num,
  struct ecryptfs_crypt_stat *crypt_stat)
 {
-   (*offset) = ((crypt_stat->extent_size
- * crypt_stat->num_header_extents_at_front)
+   (*offset) = (crypt_stat->num_header_bytes_at_front
 + (crypt_stat->extent_size * extent_num));
 }
 
@@ -826,15 +825,13 @@ void ecryptfs_set_default_sizes(struct 
ecryptfs_crypt_stat *crypt_stat)
set_extent_mask_and_shift(crypt_stat);
crypt_stat->iv_bytes = ECRYPTFS_DEFAULT_IV_BYTES;
if (crypt_stat->flags & ECRYPTFS_METADATA_IN_XATTR)
-   crypt_stat->num_header_extents_at_front = 0;
+   crypt_stat->num_header_bytes_at_front = 0;
else {
if (PAGE_CACHE_SIZE <= ECRYPTFS_MINIMUM_HEADER_EXTENT_SIZE)
-   crypt_stat->num_header_extents_at_front =
-   (ECRYPTFS_MINIMUM_HEADER_EXTENT_SIZE
-/ crypt_stat->extent_size);
+   crypt_stat->num_header_bytes_at_front =
+   ECRYPTFS_MINIMUM_HEADER_EXTENT_SIZE;
else
-   crypt_stat->num_header_extents_at_front =
-   (PAGE_CACHE_SIZE / crypt_stat->extent_size);
+   crypt_stat->num_header_bytes_at_front = PAGE_CACHE_SIZE;
}
 }
 
@@ -1220,7 +1217,8 @@ ecryptfs_write_header_metadata(char *virt,
 
header_extent_size = (u32)crypt_stat->extent_size;
num_header_extents_at_front =
-   (u16)crypt_stat->num_header_extents_at_front;
+   (u16)(crypt_stat->num_header_bytes_at_front
+ / crypt_stat->extent_size);
header_extent_size = cpu_to_be32(header_extent_size);
memcpy(virt, _extent_size, 4);
virt += 4;
@@ -1295,40 +1293,16 @@ static int ecryptfs_write_headers_virt(char *page_virt, 
size_t *size,
 static int
 ecryptfs_write_metadata_to_contents(struct ecryptfs_crypt_stat *crypt_stat,
struct dentry *ecryptfs_dentry,
-   char *page_virt)
+   char *virt)
 {
-   int current_header_page;
-   int header_pages;
int rc;
 
-   rc = ecryptfs_write_lower(ecryptfs_dentry->d_inode, page_virt,
- 0, PAGE_CACHE_SIZE);
-   if (rc) {
+   rc = ecryptfs_write_lower(ecryptfs_dentry->d_inode, virt,
+ 0, crypt_stat->num_header_bytes_at_front);
+   if (rc)
printk(KERN_ERR "%s: Error attempting to write header "
   "information to lower file; rc = [%d]\n", __FUNCTION__,
   rc);
-   goto out;
-   }
-   header_pages = ((crypt_stat->extent_size
-* crypt_stat->num_header_extents_at_front)
-   / PAGE_CACHE_SIZE);
-   memset(page_virt, 0, PAGE_CACHE_SIZE);
-   current_header_page = 1;
-   while (current_header_page < header_pages) {
-   loff_t offset;
-
-   offset = (((loff_t)current_header_page) << PAGE_CACHE_SHIFT);
-   if ((rc = ecryptfs_write_lower(ecryptfs_dentry->d_inode,
-  page_virt, offset,
-  PAGE_CACHE_SIZE))) {
-   printk(KERN_ERR "%s: Error attempting to write header "
-  "information to lower file; rc = [%d]\n",
-  __FUNCTION__, rc);
-   goto out;
-   }
-   current_header_page++;
-   }
-out:
return rc;
 }
 
@@ -1354,15 +1328,13 @@ ecryptfs_write_metadata_to_xattr(struct dentry 
*ecryptfs_dentry,
  * retrieved via a prompt.  Exactly what happens at this point should
  * be policy-dependent.
  *
- * TODO: Support header information spanning multiple pages
- *
  * Returns zero on success; non-zero on error
  */
 int ecryptfs_write_metadata(struct dentry *ecryptf

[PATCH 0/3] eCryptfs: extent offset fix, crypto performance, and larger header regions

2007-11-02 Thread Michael Halcrow
This patch set includes some minor fixes for eCryptfs, including:

 - An enhancement to allow larger header regions

 - A bugfix for hosts with page size >4K

 - An enhancement to reduce crypto overhead

I recommend merging at least the bugfix into 2.6.24.
-
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to [EMAIL PROTECTED]
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/


[PATCH 0/3] eCryptfs: extent offset fix, crypto performance, and larger header regions

2007-11-02 Thread Michael Halcrow
This patch set includes some minor fixes for eCryptfs, including:

 - An enhancement to allow larger header regions

 - A bugfix for hosts with page size 4K

 - An enhancement to reduce crypto overhead

I recommend merging at least the bugfix into 2.6.24.
-
To unsubscribe from this list: send the line unsubscribe linux-kernel in
the body of a message to [EMAIL PROTECTED]
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/


[PATCH 1/3] eCryptfs: Track header bytes rather than extents

2007-11-02 Thread Michael Halcrow
Remove internal references to header extents; just keep track of
header bytes instead. Headers can easily span multiple pages with the
recent persistent file changes.

Signed-off-by: Michael Halcrow [EMAIL PROTECTED]
---
 fs/ecryptfs/crypto.c  |   98 +++--
 fs/ecryptfs/ecryptfs_kernel.h |3 +-
 fs/ecryptfs/inode.c   |8 +--
 fs/ecryptfs/main.c|5 --
 fs/ecryptfs/mmap.c|   21 +
 5 files changed, 51 insertions(+), 84 deletions(-)

diff --git a/fs/ecryptfs/crypto.c b/fs/ecryptfs/crypto.c
index 9d70289..ca0dfea 100644
--- a/fs/ecryptfs/crypto.c
+++ b/fs/ecryptfs/crypto.c
@@ -361,8 +361,7 @@ out:
 void ecryptfs_lower_offset_for_extent(loff_t *offset, loff_t extent_num,
  struct ecryptfs_crypt_stat *crypt_stat)
 {
-   (*offset) = ((crypt_stat-extent_size
- * crypt_stat-num_header_extents_at_front)
+   (*offset) = (crypt_stat-num_header_bytes_at_front
 + (crypt_stat-extent_size * extent_num));
 }
 
@@ -826,15 +825,13 @@ void ecryptfs_set_default_sizes(struct 
ecryptfs_crypt_stat *crypt_stat)
set_extent_mask_and_shift(crypt_stat);
crypt_stat-iv_bytes = ECRYPTFS_DEFAULT_IV_BYTES;
if (crypt_stat-flags  ECRYPTFS_METADATA_IN_XATTR)
-   crypt_stat-num_header_extents_at_front = 0;
+   crypt_stat-num_header_bytes_at_front = 0;
else {
if (PAGE_CACHE_SIZE = ECRYPTFS_MINIMUM_HEADER_EXTENT_SIZE)
-   crypt_stat-num_header_extents_at_front =
-   (ECRYPTFS_MINIMUM_HEADER_EXTENT_SIZE
-/ crypt_stat-extent_size);
+   crypt_stat-num_header_bytes_at_front =
+   ECRYPTFS_MINIMUM_HEADER_EXTENT_SIZE;
else
-   crypt_stat-num_header_extents_at_front =
-   (PAGE_CACHE_SIZE / crypt_stat-extent_size);
+   crypt_stat-num_header_bytes_at_front = PAGE_CACHE_SIZE;
}
 }
 
@@ -1220,7 +1217,8 @@ ecryptfs_write_header_metadata(char *virt,
 
header_extent_size = (u32)crypt_stat-extent_size;
num_header_extents_at_front =
-   (u16)crypt_stat-num_header_extents_at_front;
+   (u16)(crypt_stat-num_header_bytes_at_front
+ / crypt_stat-extent_size);
header_extent_size = cpu_to_be32(header_extent_size);
memcpy(virt, header_extent_size, 4);
virt += 4;
@@ -1295,40 +1293,16 @@ static int ecryptfs_write_headers_virt(char *page_virt, 
size_t *size,
 static int
 ecryptfs_write_metadata_to_contents(struct ecryptfs_crypt_stat *crypt_stat,
struct dentry *ecryptfs_dentry,
-   char *page_virt)
+   char *virt)
 {
-   int current_header_page;
-   int header_pages;
int rc;
 
-   rc = ecryptfs_write_lower(ecryptfs_dentry-d_inode, page_virt,
- 0, PAGE_CACHE_SIZE);
-   if (rc) {
+   rc = ecryptfs_write_lower(ecryptfs_dentry-d_inode, virt,
+ 0, crypt_stat-num_header_bytes_at_front);
+   if (rc)
printk(KERN_ERR %s: Error attempting to write header 
   information to lower file; rc = [%d]\n, __FUNCTION__,
   rc);
-   goto out;
-   }
-   header_pages = ((crypt_stat-extent_size
-* crypt_stat-num_header_extents_at_front)
-   / PAGE_CACHE_SIZE);
-   memset(page_virt, 0, PAGE_CACHE_SIZE);
-   current_header_page = 1;
-   while (current_header_page  header_pages) {
-   loff_t offset;
-
-   offset = (((loff_t)current_header_page)  PAGE_CACHE_SHIFT);
-   if ((rc = ecryptfs_write_lower(ecryptfs_dentry-d_inode,
-  page_virt, offset,
-  PAGE_CACHE_SIZE))) {
-   printk(KERN_ERR %s: Error attempting to write header 
-  information to lower file; rc = [%d]\n,
-  __FUNCTION__, rc);
-   goto out;
-   }
-   current_header_page++;
-   }
-out:
return rc;
 }
 
@@ -1354,15 +1328,13 @@ ecryptfs_write_metadata_to_xattr(struct dentry 
*ecryptfs_dentry,
  * retrieved via a prompt.  Exactly what happens at this point should
  * be policy-dependent.
  *
- * TODO: Support header information spanning multiple pages
- *
  * Returns zero on success; non-zero on error
  */
 int ecryptfs_write_metadata(struct dentry *ecryptfs_dentry)
 {
struct ecryptfs_crypt_stat *crypt_stat =

ecryptfs_inode_to_private(ecryptfs_dentry-d_inode)-crypt_stat;
-   char *page_virt

[PATCH 2/3] eCryptfs: Increment extent_offset once per loop interation

2007-11-02 Thread Michael Halcrow
The extent_offset is getting incremented twice per loop iteration
through any given page. It should only be getting incremented
once. This bug should only impact hosts with 4K page sizes.

Signed-off-by: Michael Halcrow [EMAIL PROTECTED]
---
 fs/ecryptfs/crypto.c |2 --
 1 files changed, 0 insertions(+), 2 deletions(-)

diff --git a/fs/ecryptfs/crypto.c b/fs/ecryptfs/crypto.c
index ca0dfea..4f14d4c 100644
--- a/fs/ecryptfs/crypto.c
+++ b/fs/ecryptfs/crypto.c
@@ -503,7 +503,6 @@ int ecryptfs_encrypt_page(struct page *page)
\n, rc);
goto out;
}
-   extent_offset++;
}
 out:
kfree(enc_extent_virt);
@@ -639,7 +638,6 @@ int ecryptfs_decrypt_page(struct page *page)
   rc = [%d]\n, __FUNCTION__, rc);
goto out;
}
-   extent_offset++;
}
 out:
kfree(enc_extent_virt);
-- 
1.5.0.6

-
To unsubscribe from this list: send the line unsubscribe linux-kernel in
the body of a message to [EMAIL PROTECTED]
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/


[PATCH 3/3] eCryptfs: Set inode key only once per crypto operation

2007-11-02 Thread Michael Halcrow
There is no need to keep re-setting the same key for any given
eCryptfs inode. This patch optimizes the use of the crypto API and
helps performance a bit.

Signed-off-by: Trevor Highland [EMAIL PROTECTED]
Signed-off-by: Michael Halcrow [EMAIL PROTECTED]
---
 fs/ecryptfs/crypto.c  |7 +--
 fs/ecryptfs/ecryptfs_kernel.h |1 +
 2 files changed, 6 insertions(+), 2 deletions(-)

diff --git a/fs/ecryptfs/crypto.c b/fs/ecryptfs/crypto.c
index 4f14d4c..a0f53aa 100644
--- a/fs/ecryptfs/crypto.c
+++ b/fs/ecryptfs/crypto.c
@@ -337,8 +337,11 @@ static int encrypt_scatterlist(struct ecryptfs_crypt_stat 
*crypt_stat,
}
/* Consider doing this once, when the file is opened */
mutex_lock(crypt_stat-cs_tfm_mutex);
-   rc = crypto_blkcipher_setkey(crypt_stat-tfm, crypt_stat-key,
-crypt_stat-key_size);
+   if (!(crypt_stat-flags  ECRYPTFS_KEY_SET)) {
+   rc = crypto_blkcipher_setkey(crypt_stat-tfm, crypt_stat-key,
+crypt_stat-key_size);
+   crypt_stat-flags |= ECRYPTFS_KEY_SET;
+   }
if (rc) {
ecryptfs_printk(KERN_ERR, Error setting key; rc = [%d]\n,
rc);
diff --git a/fs/ecryptfs/ecryptfs_kernel.h b/fs/ecryptfs/ecryptfs_kernel.h
index 78b7916..114cb86 100644
--- a/fs/ecryptfs/ecryptfs_kernel.h
+++ b/fs/ecryptfs/ecryptfs_kernel.h
@@ -234,6 +234,7 @@ struct ecryptfs_crypt_stat {
 #define ECRYPTFS_KEY_VALID  0x0080
 #define ECRYPTFS_METADATA_IN_XATTR  0x0100
 #define ECRYPTFS_VIEW_AS_ENCRYPTED  0x0200
+#define ECRYPTFS_KEY_SET0x0400
u32 flags;
unsigned int file_version;
size_t iv_bytes;
-- 
1.5.0.6

-
To unsubscribe from this list: send the line unsubscribe linux-kernel in
the body of a message to [EMAIL PROTECTED]
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/


Re: [PATCH 3/3] eCryptfs: Set inode key only once per crypto operation

2007-11-02 Thread Michael Halcrow
On Fri, Nov 02, 2007 at 01:10:31PM -0700, Andrew Morton wrote:
 On Fri, 2 Nov 2007 13:53:08 -0500
 Michael Halcrow [EMAIL PROTECTED] wrote:
 
  There is no need to keep re-setting the same key for any given
  eCryptfs inode. This patch optimizes the use of the crypto API and
  helps performance a bit.
  
  Signed-off-by: Trevor Highland [EMAIL PROTECTED]
  Signed-off-by: Michael Halcrow [EMAIL PROTECTED]
 
 I've inferred from this that Michael authored this patch.  Please
 let me know if that was incorrect.

Trevor Highland actually authored this one.

 The way in which we indicate authorship is to put a From: line right
 at the top of the changelog.  If no such line appears then the From:
 line from the mail headers is used.

Noted.

Mike


pgpEpeP8rGmGy.pgp
Description: PGP signature


[PATCH] eCryptfs: Release mutex on hash error path

2007-11-02 Thread Michael Halcrow
On Mon, Oct 29, 2007 at 03:10:09PM +0900, Kazuki Ohta wrote:
 When IS_ERR(desc.tfm) is true, unlocking
 crypt_stat-cs_hash_tfm_mutex is forgotten.

Thanks for reporting this, Kazuki.
---

Release the crypt_stat hash mutex on allocation error. Check for error
conditions when doing crypto hash calls.

Signed-off-by: Michael Halcrow [EMAIL PROTECTED]
---
 fs/ecryptfs/crypto.c |   26 ++
 1 files changed, 22 insertions(+), 4 deletions(-)

diff --git a/fs/ecryptfs/crypto.c b/fs/ecryptfs/crypto.c
index a0f53aa..70f7aab 100644
--- a/fs/ecryptfs/crypto.c
+++ b/fs/ecryptfs/crypto.c
@@ -115,11 +115,29 @@ static int ecryptfs_calculate_md5(char *dst,
}
crypt_stat-hash_tfm = desc.tfm;
}
-   crypto_hash_init(desc);
-   crypto_hash_update(desc, sg, len);
-   crypto_hash_final(desc, dst);
-   mutex_unlock(crypt_stat-cs_hash_tfm_mutex);
+   rc = crypto_hash_init(desc);
+   if (rc) {
+   printk(KERN_ERR
+  %s: Error initializing crypto hash; rc = [%d]\n,
+  __FUNCTION__, rc);
+   goto out;
+   }
+   rc = crypto_hash_update(desc, sg, len);
+   if (rc) {
+   printk(KERN_ERR
+  %s: Error updating crypto hash; rc = [%d]\n,
+  __FUNCTION__, rc);
+   goto out;
+   }
+   rc = crypto_hash_final(desc, dst);
+   if (rc) {
+   printk(KERN_ERR
+  %s: Error finalizing crypto hash; rc = [%d]\n,
+  __FUNCTION__, rc);
+   goto out;
+   }
 out:
+   mutex_unlock(crypt_stat-cs_hash_tfm_mutex);
return rc;
 }
 
-- 
1.5.0.6

-
To unsubscribe from this list: send the line unsubscribe linux-kernel in
the body of a message to [EMAIL PROTECTED]
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/


[PATCH] eCryptfs: Cast page-index to loff_t instead of off_t

2007-11-02 Thread Michael Halcrow
page-index should be cast to loff_t instead of off_t.

Signed-off-by: Michael Halcrow [EMAIL PROTECTED]
Reported-by: Eric Sandeen [EMAIL PROTECTED]
---
 fs/ecryptfs/read_write.c |2 +-
 1 files changed, 1 insertions(+), 1 deletions(-)

diff --git a/fs/ecryptfs/read_write.c b/fs/ecryptfs/read_write.c
index 2150edf..6b7474a 100644
--- a/fs/ecryptfs/read_write.c
+++ b/fs/ecryptfs/read_write.c
@@ -87,7 +87,7 @@ int ecryptfs_write_lower_page_segment(struct inode 
*ecryptfs_inode,
loff_t offset;
int rc;
 
-   offset = off_t)page_for_lower-index)  PAGE_CACHE_SHIFT)
+   offset = loff_t)page_for_lower-index)  PAGE_CACHE_SHIFT)
  + offset_in_page);
virt = kmap(page_for_lower);
rc = ecryptfs_write_lower(ecryptfs_inode, virt, offset, size);
-- 
1.5.1.6

-
To unsubscribe from this list: send the line unsubscribe linux-kernel in
the body of a message to [EMAIL PROTECTED]
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/


Re: ecryptfs-kmem_cache-objects-for-multiple-keys-init-exit-functions.patch

2007-09-27 Thread Michael Halcrow
On Fri, Aug 03, 2007 at 11:42:49AM -0700, Andrew Morton wrote:
> ecryptfs_init() should be converted to the usual `goto out_foo' unwinding
> so we don't need N duplicated copies of the error recovery code.
> 
>   if (foo())
>   goto out;
>   if (bar())
>   goto out_foo;
>   if (zot())
>   goto out_bar;
>   ...
> out_bar:
>   undo_bar();
> out_foo:
>   undo_foo();
> out:
>   return err;

The error paths and the module exit code need work. sysfs
unregistration is not the right place to tear down the crypto
subsystem, and the code to undo subsystem initializations on various
error paths is unnecessarily duplicated. This patch addresses those
issues.

Signed-off-by: Michael Halcrow <[EMAIL PROTECTED]>
---
diff --git a/fs/ecryptfs/main.c b/fs/ecryptfs/main.c
index 92b1e6c..f944d94 100644
--- a/fs/ecryptfs/main.c
+++ b/fs/ecryptfs/main.c
@@ -858,13 +858,6 @@ out:
 
 static void do_sysfs_unregistration(void)
 {
-   int rc;
-
-   rc = ecryptfs_destroy_crypto();
-   if (rc) {
-   printk(KERN_ERR "Failure whilst attempting to destroy crypto; "
-  "rc = [%d]\n", rc);
-   }
sysfs_remove_file(_subsys.kobj,
  _attr_version.attr);
sysfs_remove_file(_subsys.kobj,
@@ -895,43 +888,49 @@ static int __init ecryptfs_init(void)
rc = register_filesystem(_fs_type);
if (rc) {
printk(KERN_ERR "Failed to register filesystem\n");
-   ecryptfs_free_kmem_caches();
-   goto out;
+   goto out_free_kmem_caches;
}
kobj_set_kset_s(_subsys, fs_subsys);
rc = do_sysfs_registration();
if (rc) {
printk(KERN_ERR "sysfs registration failed\n");
-   unregister_filesystem(_fs_type);
-   ecryptfs_free_kmem_caches();
-   goto out;
+   goto out_unregister_filesystem;
}
rc = ecryptfs_init_messaging(ecryptfs_transport);
if (rc) {
ecryptfs_printk(KERN_ERR, "Failure occured while attempting to "
"initialize the eCryptfs netlink socket\n");
-   do_sysfs_unregistration();
-   unregister_filesystem(_fs_type);
-   ecryptfs_free_kmem_caches();
-   goto out;
+   goto out_do_sysfs_unregistration;
}
rc = ecryptfs_init_crypto();
if (rc) {
printk(KERN_ERR "Failure whilst attempting to init crypto; "
   "rc = [%d]\n", rc);
-   do_sysfs_unregistration();
-   unregister_filesystem(_fs_type);
-   ecryptfs_free_kmem_caches();
-   goto out;
+   goto out_release_messaging;
}
+   goto out;
+out_release_messaging:
+   ecryptfs_release_messaging(ecryptfs_transport);
+out_do_sysfs_unregistration:
+   do_sysfs_unregistration();
+out_unregister_filesystem:
+   unregister_filesystem(_fs_type);
+out_free_kmem_caches:
+   ecryptfs_free_kmem_caches();
 out:
return rc;
 }
 
 static void __exit ecryptfs_exit(void)
 {
-   do_sysfs_unregistration();
+   int rc;
+
+   rc = ecryptfs_destroy_crypto();
+   if (rc)
+   printk(KERN_ERR "Failure whilst attempting to destroy crypto; "
+  "rc = [%d]\n", rc);
ecryptfs_release_messaging(ecryptfs_transport);
+   do_sysfs_unregistration();
unregister_filesystem(_fs_type);
ecryptfs_free_kmem_caches();
 }

-
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to [EMAIL PROTECTED]
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/


Re: ecryptfs-kmem_cache-objects-for-multiple-keys-init-exit-functions.patch

2007-09-27 Thread Michael Halcrow
On Fri, Aug 03, 2007 at 11:42:49AM -0700, Andrew Morton wrote:
 ecryptfs_init() should be converted to the usual `goto out_foo' unwinding
 so we don't need N duplicated copies of the error recovery code.
 
   if (foo())
   goto out;
   if (bar())
   goto out_foo;
   if (zot())
   goto out_bar;
   ...
 out_bar:
   undo_bar();
 out_foo:
   undo_foo();
 out:
   return err;

The error paths and the module exit code need work. sysfs
unregistration is not the right place to tear down the crypto
subsystem, and the code to undo subsystem initializations on various
error paths is unnecessarily duplicated. This patch addresses those
issues.

Signed-off-by: Michael Halcrow [EMAIL PROTECTED]
---
diff --git a/fs/ecryptfs/main.c b/fs/ecryptfs/main.c
index 92b1e6c..f944d94 100644
--- a/fs/ecryptfs/main.c
+++ b/fs/ecryptfs/main.c
@@ -858,13 +858,6 @@ out:
 
 static void do_sysfs_unregistration(void)
 {
-   int rc;
-
-   rc = ecryptfs_destroy_crypto();
-   if (rc) {
-   printk(KERN_ERR Failure whilst attempting to destroy crypto; 
-  rc = [%d]\n, rc);
-   }
sysfs_remove_file(ecryptfs_subsys.kobj,
  sysfs_attr_version.attr);
sysfs_remove_file(ecryptfs_subsys.kobj,
@@ -895,43 +888,49 @@ static int __init ecryptfs_init(void)
rc = register_filesystem(ecryptfs_fs_type);
if (rc) {
printk(KERN_ERR Failed to register filesystem\n);
-   ecryptfs_free_kmem_caches();
-   goto out;
+   goto out_free_kmem_caches;
}
kobj_set_kset_s(ecryptfs_subsys, fs_subsys);
rc = do_sysfs_registration();
if (rc) {
printk(KERN_ERR sysfs registration failed\n);
-   unregister_filesystem(ecryptfs_fs_type);
-   ecryptfs_free_kmem_caches();
-   goto out;
+   goto out_unregister_filesystem;
}
rc = ecryptfs_init_messaging(ecryptfs_transport);
if (rc) {
ecryptfs_printk(KERN_ERR, Failure occured while attempting to 
initialize the eCryptfs netlink socket\n);
-   do_sysfs_unregistration();
-   unregister_filesystem(ecryptfs_fs_type);
-   ecryptfs_free_kmem_caches();
-   goto out;
+   goto out_do_sysfs_unregistration;
}
rc = ecryptfs_init_crypto();
if (rc) {
printk(KERN_ERR Failure whilst attempting to init crypto; 
   rc = [%d]\n, rc);
-   do_sysfs_unregistration();
-   unregister_filesystem(ecryptfs_fs_type);
-   ecryptfs_free_kmem_caches();
-   goto out;
+   goto out_release_messaging;
}
+   goto out;
+out_release_messaging:
+   ecryptfs_release_messaging(ecryptfs_transport);
+out_do_sysfs_unregistration:
+   do_sysfs_unregistration();
+out_unregister_filesystem:
+   unregister_filesystem(ecryptfs_fs_type);
+out_free_kmem_caches:
+   ecryptfs_free_kmem_caches();
 out:
return rc;
 }
 
 static void __exit ecryptfs_exit(void)
 {
-   do_sysfs_unregistration();
+   int rc;
+
+   rc = ecryptfs_destroy_crypto();
+   if (rc)
+   printk(KERN_ERR Failure whilst attempting to destroy crypto; 
+  rc = [%d]\n, rc);
ecryptfs_release_messaging(ecryptfs_transport);
+   do_sysfs_unregistration();
unregister_filesystem(ecryptfs_fs_type);
ecryptfs_free_kmem_caches();
 }

-
To unsubscribe from this list: send the line unsubscribe linux-kernel in
the body of a message to [EMAIL PROTECTED]
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/


Re: [Ecryptfs-devel] [PATCH 3/11] eCryptfs: read_write.c routines

2007-09-25 Thread Michael Halcrow
On Fri, Sep 21, 2007 at 03:05:40PM -0700, Andrew Morton wrote:
> btw, I'm not really a great admirer of the whole patchset: it does
> some pretty nasty-looking things: allocating dynamic memory,
> grabbing the underlying pageframes with virt_to_page(), passing them
> back into kernel APIs which are supposed to be called from
> userspace, etc.  It's all rather ugly and abusive-looking.

Functions higher up the execution stack should be the ones mucking
with the Uptodate flag. The patch below addresses some of these
issues. I also whipped up a post-patch partial call graph to help
illustrate what is going on with the page mapping and Uptodate status
in the various eCryptfs read/write paths:

http://ecryptfs.sourceforge.net/ecryptfs-pageuptodate-call-graph.png

---

The functions that eventually call down to ecryptfs_read_lower(),
ecryptfs_decrypt_page(), and ecryptfs_copy_up_encrypted_with_header()
should have the responsibility of managing the page Uptodate
status. This patch gets rid of some of the ugliness that resulted from
trying to push some of the page flag setting too far down the stack.

Signed-off-by: Michael Halcrow <[EMAIL PROTECTED]>
---
diff --git a/fs/ecryptfs/crypto.c b/fs/ecryptfs/crypto.c
index b3795f6..bbec711 100644
--- a/fs/ecryptfs/crypto.c
+++ b/fs/ecryptfs/crypto.c
@@ -605,14 +605,14 @@ int ecryptfs_decrypt_page(struct page *page)
printk(KERN_ERR "%s: Error attempting to copy "
   "page at index [%ld]\n", __FUNCTION__,
   page->index);
-   goto out_clear_uptodate;
+   goto out;
}
enc_extent_virt = kmalloc(PAGE_CACHE_SIZE, GFP_USER);
if (!enc_extent_virt) {
rc = -ENOMEM;
ecryptfs_printk(KERN_ERR, "Error allocating memory for "
"encrypted extent\n");
-   goto out_clear_uptodate;
+   goto out;
}
enc_extent_page = virt_to_page(enc_extent_virt);
for (extent_offset = 0;
@@ -631,21 +631,17 @@ int ecryptfs_decrypt_page(struct page *page)
ecryptfs_printk(KERN_ERR, "Error attempting "
"to read lower page; rc = [%d]"
"\n", rc);
-   goto out_clear_uptodate;
+   goto out;
}
rc = ecryptfs_decrypt_extent(page, crypt_stat, enc_extent_page,
 extent_offset);
if (rc) {
printk(KERN_ERR "%s: Error encrypting extent; "
   "rc = [%d]\n", __FUNCTION__, rc);
-   goto out_clear_uptodate;
+   goto out;
}
extent_offset++;
}
-   SetPageUptodate(page);
-   goto out;
-out_clear_uptodate:
-   ClearPageUptodate(page);
 out:
kfree(enc_extent_virt);
return rc;
diff --git a/fs/ecryptfs/ecryptfs_kernel.h b/fs/ecryptfs/ecryptfs_kernel.h
index bb92b74..ce7a5d4 100644
--- a/fs/ecryptfs/ecryptfs_kernel.h
+++ b/fs/ecryptfs/ecryptfs_kernel.h
@@ -648,6 +648,6 @@ int ecryptfs_read_lower_page_segment(struct page 
*page_for_ecryptfs,
 struct inode *ecryptfs_inode);
 int ecryptfs_read(char *data, loff_t offset, size_t size,
  struct file *ecryptfs_file);
-struct page *ecryptfs_get1page(struct file *file, loff_t index);
+struct page *ecryptfs_get_locked_page(struct file *file, loff_t index);
 
 #endif /* #ifndef ECRYPTFS_KERNEL_H */
diff --git a/fs/ecryptfs/mmap.c b/fs/ecryptfs/mmap.c
index 4eb09c1..16a7a55 100644
--- a/fs/ecryptfs/mmap.c
+++ b/fs/ecryptfs/mmap.c
@@ -37,23 +37,27 @@
 struct kmem_cache *ecryptfs_lower_page_cache;
 
 /**
- * ecryptfs_get1page
+ * ecryptfs_get_locked_page
  *
  * Get one page from cache or lower f/s, return error otherwise.
  *
- * Returns unlocked and up-to-date page (if ok), with increased
+ * Returns locked and up-to-date page (if ok), with increased
  * refcnt.
  */
-struct page *ecryptfs_get1page(struct file *file, loff_t index)
+struct page *ecryptfs_get_locked_page(struct file *file, loff_t index)
 {
struct dentry *dentry;
struct inode *inode;
struct address_space *mapping;
+   struct page *page;
 
dentry = file->f_path.dentry;
inode = dentry->d_inode;
mapping = inode->i_mapping;
-   return read_mapping_page(mapping, index, (void *)file);
+   page = read_mapping_page(mapping, index, (void *)file);
+   if (!IS_ERR(page))
+   lock_page(page);
+   return page;
 }
 
 /**
@@ -146,12 +150,10 @@ ecryptfs_copy_up_encrypted_with_header(struct page *page,
kunmap_atomic(page_virt, KM_USER0);
  

Re: [Ecryptfs-devel] [PATCH 3/11] eCryptfs: read_write.c routines

2007-09-25 Thread Michael Halcrow
On Fri, Sep 21, 2007 at 03:05:40PM -0700, Andrew Morton wrote:
 btw, I'm not really a great admirer of the whole patchset: it does
 some pretty nasty-looking things: allocating dynamic memory,
 grabbing the underlying pageframes with virt_to_page(), passing them
 back into kernel APIs which are supposed to be called from
 userspace, etc.  It's all rather ugly and abusive-looking.

Functions higher up the execution stack should be the ones mucking
with the Uptodate flag. The patch below addresses some of these
issues. I also whipped up a post-patch partial call graph to help
illustrate what is going on with the page mapping and Uptodate status
in the various eCryptfs read/write paths:

http://ecryptfs.sourceforge.net/ecryptfs-pageuptodate-call-graph.png

---

The functions that eventually call down to ecryptfs_read_lower(),
ecryptfs_decrypt_page(), and ecryptfs_copy_up_encrypted_with_header()
should have the responsibility of managing the page Uptodate
status. This patch gets rid of some of the ugliness that resulted from
trying to push some of the page flag setting too far down the stack.

Signed-off-by: Michael Halcrow [EMAIL PROTECTED]
---
diff --git a/fs/ecryptfs/crypto.c b/fs/ecryptfs/crypto.c
index b3795f6..bbec711 100644
--- a/fs/ecryptfs/crypto.c
+++ b/fs/ecryptfs/crypto.c
@@ -605,14 +605,14 @@ int ecryptfs_decrypt_page(struct page *page)
printk(KERN_ERR %s: Error attempting to copy 
   page at index [%ld]\n, __FUNCTION__,
   page-index);
-   goto out_clear_uptodate;
+   goto out;
}
enc_extent_virt = kmalloc(PAGE_CACHE_SIZE, GFP_USER);
if (!enc_extent_virt) {
rc = -ENOMEM;
ecryptfs_printk(KERN_ERR, Error allocating memory for 
encrypted extent\n);
-   goto out_clear_uptodate;
+   goto out;
}
enc_extent_page = virt_to_page(enc_extent_virt);
for (extent_offset = 0;
@@ -631,21 +631,17 @@ int ecryptfs_decrypt_page(struct page *page)
ecryptfs_printk(KERN_ERR, Error attempting 
to read lower page; rc = [%d]
\n, rc);
-   goto out_clear_uptodate;
+   goto out;
}
rc = ecryptfs_decrypt_extent(page, crypt_stat, enc_extent_page,
 extent_offset);
if (rc) {
printk(KERN_ERR %s: Error encrypting extent; 
   rc = [%d]\n, __FUNCTION__, rc);
-   goto out_clear_uptodate;
+   goto out;
}
extent_offset++;
}
-   SetPageUptodate(page);
-   goto out;
-out_clear_uptodate:
-   ClearPageUptodate(page);
 out:
kfree(enc_extent_virt);
return rc;
diff --git a/fs/ecryptfs/ecryptfs_kernel.h b/fs/ecryptfs/ecryptfs_kernel.h
index bb92b74..ce7a5d4 100644
--- a/fs/ecryptfs/ecryptfs_kernel.h
+++ b/fs/ecryptfs/ecryptfs_kernel.h
@@ -648,6 +648,6 @@ int ecryptfs_read_lower_page_segment(struct page 
*page_for_ecryptfs,
 struct inode *ecryptfs_inode);
 int ecryptfs_read(char *data, loff_t offset, size_t size,
  struct file *ecryptfs_file);
-struct page *ecryptfs_get1page(struct file *file, loff_t index);
+struct page *ecryptfs_get_locked_page(struct file *file, loff_t index);
 
 #endif /* #ifndef ECRYPTFS_KERNEL_H */
diff --git a/fs/ecryptfs/mmap.c b/fs/ecryptfs/mmap.c
index 4eb09c1..16a7a55 100644
--- a/fs/ecryptfs/mmap.c
+++ b/fs/ecryptfs/mmap.c
@@ -37,23 +37,27 @@
 struct kmem_cache *ecryptfs_lower_page_cache;
 
 /**
- * ecryptfs_get1page
+ * ecryptfs_get_locked_page
  *
  * Get one page from cache or lower f/s, return error otherwise.
  *
- * Returns unlocked and up-to-date page (if ok), with increased
+ * Returns locked and up-to-date page (if ok), with increased
  * refcnt.
  */
-struct page *ecryptfs_get1page(struct file *file, loff_t index)
+struct page *ecryptfs_get_locked_page(struct file *file, loff_t index)
 {
struct dentry *dentry;
struct inode *inode;
struct address_space *mapping;
+   struct page *page;
 
dentry = file-f_path.dentry;
inode = dentry-d_inode;
mapping = inode-i_mapping;
-   return read_mapping_page(mapping, index, (void *)file);
+   page = read_mapping_page(mapping, index, (void *)file);
+   if (!IS_ERR(page))
+   lock_page(page);
+   return page;
 }
 
 /**
@@ -146,12 +150,10 @@ ecryptfs_copy_up_encrypted_with_header(struct page *page,
kunmap_atomic(page_virt, KM_USER0);
flush_dcache_page(page);
if (rc) {
-   ClearPageUptodate(page

Re: [PATCH 6/11] eCryptfs: Update metadata read/write functions

2007-09-24 Thread Michael Halcrow
On Wed, Sep 19, 2007 at 10:48:17PM -0700, Andrew Morton wrote:
> On Mon, 17 Sep 2007 16:48:44 -0500 Michael Halcrow <[EMAIL PROTECTED]> wrote:
> > +   if ((rc = ecryptfs_write_lower(ecryptfs_dentry->d_inode,
> 
> checkpatch missed the assignment-in-an-if here.

Fix an assignment-in-an-if.

Signed-off-by: Michael Halcrow <[EMAIL PROTECTED]>
---
diff --git a/fs/ecryptfs/crypto.c b/fs/ecryptfs/crypto.c
index 4bf1a95..b3795f6 100644
--- a/fs/ecryptfs/crypto.c
+++ b/fs/ecryptfs/crypto.c
@@ -1306,8 +1306,9 @@ ecryptfs_write_metadata_to_contents(struct 
ecryptfs_crypt_stat *crypt_stat,
int header_pages;
int rc;
 
-   if ((rc = ecryptfs_write_lower(ecryptfs_dentry->d_inode, page_virt,
-  0, PAGE_CACHE_SIZE))) {
+   rc = ecryptfs_write_lower(ecryptfs_dentry->d_inode, page_virt,
+ 0, PAGE_CACHE_SIZE);
+   if (rc) {
printk(KERN_ERR "%s: Error attempting to write header "
   "information to lower file; rc = [%d]\n", __FUNCTION__,
   rc);
-
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to [EMAIL PROTECTED]
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/


Re: [PATCH 3/11] eCryptfs: read_write.c routines

2007-09-24 Thread Michael Halcrow
On Wed, Sep 19, 2007 at 10:38:50PM -0700, Andrew Morton wrote:
> > +   offset = (page_for_lower->index << PAGE_CACHE_SHIFT) + offset_in_page;
> 
> bug.  You need to cast page.index to loff_t before shifting.
> 
> I'd fix it on the spot, but this would be a good time to review the
> whole patchset and perhaps the whole fs for this easy-to-do,
> hard-to-find bug.

Update data types and add casts in order to avoid potential overflow
issues.

Signed-off-by: Michael Halcrow <[EMAIL PROTECTED]>
---
diff --git a/fs/ecryptfs/crypto.c b/fs/ecryptfs/crypto.c
index 5d27cf9..4bf1a95 100644
--- a/fs/ecryptfs/crypto.c
+++ b/fs/ecryptfs/crypto.c
@@ -149,7 +149,7 @@ out:
  * ecryptfs_derive_iv
  * @iv: destination for the derived iv vale
  * @crypt_stat: Pointer to crypt_stat struct for the current inode
- * @offset: Offset of the page whose's iv we are to derive
+ * @offset: Offset of the extent whose IV we are to derive
  *
  * Generate the initialization vector from the given root IV and page
  * offset.
@@ -157,7 +157,7 @@ out:
  * Returns zero on success; non-zero on error.
  */
 static int ecryptfs_derive_iv(char *iv, struct ecryptfs_crypt_stat *crypt_stat,
- pgoff_t offset)
+ loff_t offset)
 {
int rc = 0;
char dst[MD5_DIGEST_SIZE];
@@ -173,7 +173,7 @@ static int ecryptfs_derive_iv(char *iv, struct 
ecryptfs_crypt_stat *crypt_stat,
 * hashing business. -Halcrow */
memcpy(src, crypt_stat->root_iv, crypt_stat->iv_bytes);
memset((src + crypt_stat->iv_bytes), 0, 16);
-   snprintf((src + crypt_stat->iv_bytes), 16, "%ld", offset);
+   snprintf((src + crypt_stat->iv_bytes), 16, "%lld", offset);
if (unlikely(ecryptfs_verbosity > 0)) {
ecryptfs_printk(KERN_DEBUG, "source:\n");
ecryptfs_dump_hex(src, (crypt_stat->iv_bytes + 16));
@@ -384,11 +384,11 @@ static int ecryptfs_encrypt_extent(struct page 
*enc_extent_page,
   struct page *page,
   unsigned long extent_offset)
 {
-   unsigned long extent_base;
+   loff_t extent_base;
char extent_iv[ECRYPTFS_MAX_IV_BYTES];
int rc;
 
-   extent_base = (page->index
+   extent_base = (((loff_t)page->index)
   * (PAGE_CACHE_SIZE / crypt_stat->extent_size));
rc = ecryptfs_derive_iv(extent_iv, crypt_stat,
(extent_base + extent_offset));
@@ -492,8 +492,9 @@ int ecryptfs_encrypt_page(struct page *page)
goto out;
}
ecryptfs_lower_offset_for_extent(
-   , ((page->index * (PAGE_CACHE_SIZE
- / crypt_stat->extent_size))
+   , loff_t)page->index)
+  * (PAGE_CACHE_SIZE
+ / crypt_stat->extent_size))
  + extent_offset), crypt_stat);
rc = ecryptfs_write_lower(ecryptfs_inode, enc_extent_virt,
  offset, crypt_stat->extent_size);
@@ -515,11 +516,11 @@ static int ecryptfs_decrypt_extent(struct page *page,
   struct page *enc_extent_page,
   unsigned long extent_offset)
 {
-   unsigned long extent_base;
+   loff_t extent_base;
char extent_iv[ECRYPTFS_MAX_IV_BYTES];
int rc;
 
-   extent_base = (page->index
+   extent_base = (((loff_t)page->index)
   * (PAGE_CACHE_SIZE / crypt_stat->extent_size));
rc = ecryptfs_derive_iv(extent_iv, crypt_stat,
(extent_base + extent_offset));
@@ -1320,7 +1321,7 @@ ecryptfs_write_metadata_to_contents(struct 
ecryptfs_crypt_stat *crypt_stat,
while (current_header_page < header_pages) {
loff_t offset;
 
-   offset = (current_header_page << PAGE_CACHE_SHIFT);
+   offset = (((loff_t)current_header_page) << PAGE_CACHE_SHIFT);
if ((rc = ecryptfs_write_lower(ecryptfs_dentry->d_inode,
   page_virt, offset,
   PAGE_CACHE_SIZE))) {
diff --git a/fs/ecryptfs/mmap.c b/fs/ecryptfs/mmap.c
index c6a8a33..4eb09c1 100644
--- a/fs/ecryptfs/mmap.c
+++ b/fs/ecryptfs/mmap.c
@@ -127,7 +127,8 @@ ecryptfs_copy_up_encrypted_with_header(struct page *page,
int rc = 0;
 
while (extent_num_in_page < num_extents_per_page) {
-   loff_t view_extent_num = ((page->index * num_extents_per_page)
+   loff_t view_extent_num = loff_t)page->index)
+  * num_extents_per_page)
  

Re: [PATCH 3/11] eCryptfs: read_write.c routines

2007-09-24 Thread Michael Halcrow
On Wed, Sep 19, 2007 at 10:38:50PM -0700, Andrew Morton wrote:
  +   offset = (page_for_lower-index  PAGE_CACHE_SHIFT) + offset_in_page;
 
 bug.  You need to cast page.index to loff_t before shifting.
 
 I'd fix it on the spot, but this would be a good time to review the
 whole patchset and perhaps the whole fs for this easy-to-do,
 hard-to-find bug.

Update data types and add casts in order to avoid potential overflow
issues.

Signed-off-by: Michael Halcrow [EMAIL PROTECTED]
---
diff --git a/fs/ecryptfs/crypto.c b/fs/ecryptfs/crypto.c
index 5d27cf9..4bf1a95 100644
--- a/fs/ecryptfs/crypto.c
+++ b/fs/ecryptfs/crypto.c
@@ -149,7 +149,7 @@ out:
  * ecryptfs_derive_iv
  * @iv: destination for the derived iv vale
  * @crypt_stat: Pointer to crypt_stat struct for the current inode
- * @offset: Offset of the page whose's iv we are to derive
+ * @offset: Offset of the extent whose IV we are to derive
  *
  * Generate the initialization vector from the given root IV and page
  * offset.
@@ -157,7 +157,7 @@ out:
  * Returns zero on success; non-zero on error.
  */
 static int ecryptfs_derive_iv(char *iv, struct ecryptfs_crypt_stat *crypt_stat,
- pgoff_t offset)
+ loff_t offset)
 {
int rc = 0;
char dst[MD5_DIGEST_SIZE];
@@ -173,7 +173,7 @@ static int ecryptfs_derive_iv(char *iv, struct 
ecryptfs_crypt_stat *crypt_stat,
 * hashing business. -Halcrow */
memcpy(src, crypt_stat-root_iv, crypt_stat-iv_bytes);
memset((src + crypt_stat-iv_bytes), 0, 16);
-   snprintf((src + crypt_stat-iv_bytes), 16, %ld, offset);
+   snprintf((src + crypt_stat-iv_bytes), 16, %lld, offset);
if (unlikely(ecryptfs_verbosity  0)) {
ecryptfs_printk(KERN_DEBUG, source:\n);
ecryptfs_dump_hex(src, (crypt_stat-iv_bytes + 16));
@@ -384,11 +384,11 @@ static int ecryptfs_encrypt_extent(struct page 
*enc_extent_page,
   struct page *page,
   unsigned long extent_offset)
 {
-   unsigned long extent_base;
+   loff_t extent_base;
char extent_iv[ECRYPTFS_MAX_IV_BYTES];
int rc;
 
-   extent_base = (page-index
+   extent_base = (((loff_t)page-index)
   * (PAGE_CACHE_SIZE / crypt_stat-extent_size));
rc = ecryptfs_derive_iv(extent_iv, crypt_stat,
(extent_base + extent_offset));
@@ -492,8 +492,9 @@ int ecryptfs_encrypt_page(struct page *page)
goto out;
}
ecryptfs_lower_offset_for_extent(
-   offset, ((page-index * (PAGE_CACHE_SIZE
- / crypt_stat-extent_size))
+   offset, loff_t)page-index)
+  * (PAGE_CACHE_SIZE
+ / crypt_stat-extent_size))
  + extent_offset), crypt_stat);
rc = ecryptfs_write_lower(ecryptfs_inode, enc_extent_virt,
  offset, crypt_stat-extent_size);
@@ -515,11 +516,11 @@ static int ecryptfs_decrypt_extent(struct page *page,
   struct page *enc_extent_page,
   unsigned long extent_offset)
 {
-   unsigned long extent_base;
+   loff_t extent_base;
char extent_iv[ECRYPTFS_MAX_IV_BYTES];
int rc;
 
-   extent_base = (page-index
+   extent_base = (((loff_t)page-index)
   * (PAGE_CACHE_SIZE / crypt_stat-extent_size));
rc = ecryptfs_derive_iv(extent_iv, crypt_stat,
(extent_base + extent_offset));
@@ -1320,7 +1321,7 @@ ecryptfs_write_metadata_to_contents(struct 
ecryptfs_crypt_stat *crypt_stat,
while (current_header_page  header_pages) {
loff_t offset;
 
-   offset = (current_header_page  PAGE_CACHE_SHIFT);
+   offset = (((loff_t)current_header_page)  PAGE_CACHE_SHIFT);
if ((rc = ecryptfs_write_lower(ecryptfs_dentry-d_inode,
   page_virt, offset,
   PAGE_CACHE_SIZE))) {
diff --git a/fs/ecryptfs/mmap.c b/fs/ecryptfs/mmap.c
index c6a8a33..4eb09c1 100644
--- a/fs/ecryptfs/mmap.c
+++ b/fs/ecryptfs/mmap.c
@@ -127,7 +127,8 @@ ecryptfs_copy_up_encrypted_with_header(struct page *page,
int rc = 0;
 
while (extent_num_in_page  num_extents_per_page) {
-   loff_t view_extent_num = ((page-index * num_extents_per_page)
+   loff_t view_extent_num = loff_t)page-index)
+  * num_extents_per_page)
  + extent_num_in_page);
 
if (view_extent_num  crypt_stat-num_header_extents_at_front) {
@@ -418,7 +419,7 @@ static int ecryptfs_commit_write

Re: [PATCH 6/11] eCryptfs: Update metadata read/write functions

2007-09-24 Thread Michael Halcrow
On Wed, Sep 19, 2007 at 10:48:17PM -0700, Andrew Morton wrote:
 On Mon, 17 Sep 2007 16:48:44 -0500 Michael Halcrow [EMAIL PROTECTED] wrote:
  +   if ((rc = ecryptfs_write_lower(ecryptfs_dentry-d_inode,
 
 checkpatch missed the assignment-in-an-if here.

Fix an assignment-in-an-if.

Signed-off-by: Michael Halcrow [EMAIL PROTECTED]
---
diff --git a/fs/ecryptfs/crypto.c b/fs/ecryptfs/crypto.c
index 4bf1a95..b3795f6 100644
--- a/fs/ecryptfs/crypto.c
+++ b/fs/ecryptfs/crypto.c
@@ -1306,8 +1306,9 @@ ecryptfs_write_metadata_to_contents(struct 
ecryptfs_crypt_stat *crypt_stat,
int header_pages;
int rc;
 
-   if ((rc = ecryptfs_write_lower(ecryptfs_dentry-d_inode, page_virt,
-  0, PAGE_CACHE_SIZE))) {
+   rc = ecryptfs_write_lower(ecryptfs_dentry-d_inode, page_virt,
+ 0, PAGE_CACHE_SIZE);
+   if (rc) {
printk(KERN_ERR %s: Error attempting to write header 
   information to lower file; rc = [%d]\n, __FUNCTION__,
   rc);
-
To unsubscribe from this list: send the line unsubscribe linux-kernel in
the body of a message to [EMAIL PROTECTED]
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/


Re: [Ecryptfs-devel] [PATCH 3/11] eCryptfs: read_write.c routines

2007-09-21 Thread Michael Halcrow
On Wed, Sep 19, 2007 at 10:38:50PM -0700, Andrew Morton wrote:
> > +   virt = kmap(page_for_lower);
> > +   rc = ecryptfs_write_lower(ecryptfs_inode, virt, offset, size);
> > +   kunmap(page_for_lower);
> > +   return rc;
> > +}
> 
> argh, kmap.  http://lkml.org/lkml/2007/9/15/55

Here is a patch that moves to kmap_atomic(), adding an intermediate
copy. Although I would really like to find a way to avoid having to do
this extra copy.

---

Replace kmap() with kmap_atomic() for read_write.c routines

kmap() can lead to deadlock when multiple tasks attempt to take more
than one simultaneously:

http://lkml.org/lkml/2007/9/15/55

In order to avoid this possibility, eCryptfs must allocate an
intermediate block of memory to use with vfs_read() and vfs_write(),
copying the data through this memory region, since kmap_atomic()
cannot be held during calls which may block.

Signed-off-by: Michael Halcrow <[EMAIL PROTECTED]>
---
diff --git a/fs/ecryptfs/ecryptfs_kernel.h b/fs/ecryptfs/ecryptfs_kernel.h
index bb92b74..ce7a5d4 100644
--- a/fs/ecryptfs/ecryptfs_kernel.h
+++ b/fs/ecryptfs/ecryptfs_kernel.h
@@ -648,6 +648,6 @@ int ecryptfs_read_lower_page_segment(struct page 
*page_for_ecryptfs,
 struct inode *ecryptfs_inode);
 int ecryptfs_read(char *data, loff_t offset, size_t size,
  struct file *ecryptfs_file);
-struct page *ecryptfs_get1page(struct file *file, loff_t index);
+struct page *ecryptfs_get_locked_page(struct file *file, loff_t index);
 
 #endif /* #ifndef ECRYPTFS_KERNEL_H */
diff --git a/fs/ecryptfs/mmap.c b/fs/ecryptfs/mmap.c
index c6a8a33..6abf805 100644
--- a/fs/ecryptfs/mmap.c
+++ b/fs/ecryptfs/mmap.c
@@ -37,23 +37,30 @@
 struct kmem_cache *ecryptfs_lower_page_cache;
 
 /**
- * ecryptfs_get1page
+ * ecryptfs_get_locked_page
  *
  * Get one page from cache or lower f/s, return error otherwise.
  *
- * Returns unlocked and up-to-date page (if ok), with increased
+ * Returns a locked and up-to-date page (if ok), with increased
  * refcnt.
  */
-struct page *ecryptfs_get1page(struct file *file, loff_t index)
+struct page *ecryptfs_get_locked_page(struct file *file, loff_t index)
 {
struct dentry *dentry;
struct inode *inode;
struct address_space *mapping;
+   struct page *page;
 
dentry = file->f_path.dentry;
inode = dentry->d_inode;
mapping = inode->i_mapping;
-   return read_mapping_page(mapping, index, (void *)file);
+   page = read_mapping_page(mapping, index, (void *)file);
+   if (!IS_ERR(page))
+   lock_page(page);
+   else
+   printk(KERN_ERR "%s: Error from read_mapping_page()\n",
+  __FUNCTION__);
+   return page;
 }
 
 /**
diff --git a/fs/ecryptfs/read_write.c b/fs/ecryptfs/read_write.c
index ccd2599..6732a4c 100644
--- a/fs/ecryptfs/read_write.c
+++ b/fs/ecryptfs/read_write.c
@@ -83,14 +83,24 @@ int ecryptfs_write_lower_page_segment(struct inode 
*ecryptfs_inode,
  struct page *page_for_lower,
  size_t offset_in_page, size_t size)
 {
-   char *virt;
+   char *page_for_lower_virt;
+   char *tmp_virt;
loff_t offset;
int rc;
 
-   offset = (page_for_lower->index << PAGE_CACHE_SHIFT) + offset_in_page;
-   virt = kmap(page_for_lower);
-   rc = ecryptfs_write_lower(ecryptfs_inode, virt, offset, size);
-   kunmap(page_for_lower);
+   tmp_virt = kmalloc(PAGE_CACHE_SIZE, GFP_KERNEL);
+   if (!tmp_virt) {
+   rc = -ENOMEM;
+   goto out;
+   }
+   offset = loff_t)page_for_lower->index) << PAGE_CACHE_SHIFT)
+ + offset_in_page);
+   page_for_lower_virt = kmap_atomic(page_for_lower, KM_USER0);
+   memcpy(tmp_virt, page_for_lower_virt, PAGE_CACHE_SIZE);
+   kunmap_atomic(page_for_lower_virt, KM_USER0);
+   rc = ecryptfs_write_lower(ecryptfs_inode, tmp_virt, offset, size);
+   kfree(tmp_virt);
+out:
return rc;
 }
 
@@ -140,8 +150,8 @@ int ecryptfs_write(struct file *ecryptfs_file, char *data, 
loff_t offset,
if (num_bytes > total_remaining_zeros)
num_bytes = total_remaining_zeros;
}
-   ecryptfs_page = ecryptfs_get1page(ecryptfs_file,
- ecryptfs_page_idx);
+   ecryptfs_page = ecryptfs_get_locked_page(ecryptfs_file,
+ecryptfs_page_idx);
if (IS_ERR(ecryptfs_page)) {
rc = PTR_ERR(ecryptfs_page);
printk(KERN_ERR "%s: Error getting page at "
@@ -159,6 +169,7 @@ int ecryptfs_write(struct file *ecryptfs_file, char *data, 
loff_t offset,
print

Re: [Ecryptfs-devel] [PATCH 3/11] eCryptfs: read_write.c routines

2007-09-21 Thread Michael Halcrow
On Wed, Sep 19, 2007 at 10:38:50PM -0700, Andrew Morton wrote:
  +   virt = kmap(page_for_lower);
  +   rc = ecryptfs_write_lower(ecryptfs_inode, virt, offset, size);
  +   kunmap(page_for_lower);
  +   return rc;
  +}
 
 argh, kmap.  http://lkml.org/lkml/2007/9/15/55

Here is a patch that moves to kmap_atomic(), adding an intermediate
copy. Although I would really like to find a way to avoid having to do
this extra copy.

---

Replace kmap() with kmap_atomic() for read_write.c routines

kmap() can lead to deadlock when multiple tasks attempt to take more
than one simultaneously:

http://lkml.org/lkml/2007/9/15/55

In order to avoid this possibility, eCryptfs must allocate an
intermediate block of memory to use with vfs_read() and vfs_write(),
copying the data through this memory region, since kmap_atomic()
cannot be held during calls which may block.

Signed-off-by: Michael Halcrow [EMAIL PROTECTED]
---
diff --git a/fs/ecryptfs/ecryptfs_kernel.h b/fs/ecryptfs/ecryptfs_kernel.h
index bb92b74..ce7a5d4 100644
--- a/fs/ecryptfs/ecryptfs_kernel.h
+++ b/fs/ecryptfs/ecryptfs_kernel.h
@@ -648,6 +648,6 @@ int ecryptfs_read_lower_page_segment(struct page 
*page_for_ecryptfs,
 struct inode *ecryptfs_inode);
 int ecryptfs_read(char *data, loff_t offset, size_t size,
  struct file *ecryptfs_file);
-struct page *ecryptfs_get1page(struct file *file, loff_t index);
+struct page *ecryptfs_get_locked_page(struct file *file, loff_t index);
 
 #endif /* #ifndef ECRYPTFS_KERNEL_H */
diff --git a/fs/ecryptfs/mmap.c b/fs/ecryptfs/mmap.c
index c6a8a33..6abf805 100644
--- a/fs/ecryptfs/mmap.c
+++ b/fs/ecryptfs/mmap.c
@@ -37,23 +37,30 @@
 struct kmem_cache *ecryptfs_lower_page_cache;
 
 /**
- * ecryptfs_get1page
+ * ecryptfs_get_locked_page
  *
  * Get one page from cache or lower f/s, return error otherwise.
  *
- * Returns unlocked and up-to-date page (if ok), with increased
+ * Returns a locked and up-to-date page (if ok), with increased
  * refcnt.
  */
-struct page *ecryptfs_get1page(struct file *file, loff_t index)
+struct page *ecryptfs_get_locked_page(struct file *file, loff_t index)
 {
struct dentry *dentry;
struct inode *inode;
struct address_space *mapping;
+   struct page *page;
 
dentry = file-f_path.dentry;
inode = dentry-d_inode;
mapping = inode-i_mapping;
-   return read_mapping_page(mapping, index, (void *)file);
+   page = read_mapping_page(mapping, index, (void *)file);
+   if (!IS_ERR(page))
+   lock_page(page);
+   else
+   printk(KERN_ERR %s: Error from read_mapping_page()\n,
+  __FUNCTION__);
+   return page;
 }
 
 /**
diff --git a/fs/ecryptfs/read_write.c b/fs/ecryptfs/read_write.c
index ccd2599..6732a4c 100644
--- a/fs/ecryptfs/read_write.c
+++ b/fs/ecryptfs/read_write.c
@@ -83,14 +83,24 @@ int ecryptfs_write_lower_page_segment(struct inode 
*ecryptfs_inode,
  struct page *page_for_lower,
  size_t offset_in_page, size_t size)
 {
-   char *virt;
+   char *page_for_lower_virt;
+   char *tmp_virt;
loff_t offset;
int rc;
 
-   offset = (page_for_lower-index  PAGE_CACHE_SHIFT) + offset_in_page;
-   virt = kmap(page_for_lower);
-   rc = ecryptfs_write_lower(ecryptfs_inode, virt, offset, size);
-   kunmap(page_for_lower);
+   tmp_virt = kmalloc(PAGE_CACHE_SIZE, GFP_KERNEL);
+   if (!tmp_virt) {
+   rc = -ENOMEM;
+   goto out;
+   }
+   offset = loff_t)page_for_lower-index)  PAGE_CACHE_SHIFT)
+ + offset_in_page);
+   page_for_lower_virt = kmap_atomic(page_for_lower, KM_USER0);
+   memcpy(tmp_virt, page_for_lower_virt, PAGE_CACHE_SIZE);
+   kunmap_atomic(page_for_lower_virt, KM_USER0);
+   rc = ecryptfs_write_lower(ecryptfs_inode, tmp_virt, offset, size);
+   kfree(tmp_virt);
+out:
return rc;
 }
 
@@ -140,8 +150,8 @@ int ecryptfs_write(struct file *ecryptfs_file, char *data, 
loff_t offset,
if (num_bytes  total_remaining_zeros)
num_bytes = total_remaining_zeros;
}
-   ecryptfs_page = ecryptfs_get1page(ecryptfs_file,
- ecryptfs_page_idx);
+   ecryptfs_page = ecryptfs_get_locked_page(ecryptfs_file,
+ecryptfs_page_idx);
if (IS_ERR(ecryptfs_page)) {
rc = PTR_ERR(ecryptfs_page);
printk(KERN_ERR %s: Error getting page at 
@@ -159,6 +169,7 @@ int ecryptfs_write(struct file *ecryptfs_file, char *data, 
loff_t offset,
printk(KERN_ERR %s: Error decrypting 
   page; rc = [%d]\n,
   __FUNCTION__, rc

Re: [PATCH 8/11] eCryptfs: Convert mmap functions to use persistent file

2007-09-20 Thread Michael Halcrow
On Wed, Sep 19, 2007 at 10:50:57PM -0700, Andrew Morton wrote:
> On Mon, 17 Sep 2007 16:50:16 -0500 Michael Halcrow <[EMAIL PROTECTED]> wrote:
> > +ecryptfs_copy_up_encrypted_with_header(struct page *page,
> > +  struct ecryptfs_crypt_stat *crypt_stat)
> > +{
...
> > +   flush_dcache_page(page);
> > +   if (rc) {
> > +   ClearPageUptodate(page);
> > +   printk(KERN_ERR "%s: Error reading xattr "
> > +  "region; rc = [%d]\n", __FUNCTION__, rc);
> > +   goto out;
> > +   }
> > +   SetPageUptodate(page);
> 
> I don't know what sort of page `page' refers to here, but normally we only
> manipulate the page uptodate status under lock_page().

This is the page that eCryptfs gets via
ecryptfs_aops->ecryptfs_readpage(), so this should be okay. The
comment should make the fact that the page is locked explicit.

Signed-off-by: Michael Halcrow <[EMAIL PROTECTED]>

---
diff --git a/fs/ecryptfs/mmap.c b/fs/ecryptfs/mmap.c
index 04103ff..c6a8a33 100644
--- a/fs/ecryptfs/mmap.c
+++ b/fs/ecryptfs/mmap.c
@@ -111,7 +111,7 @@ static void set_header_info(char *page_virt,
  * ecryptfs_copy_up_encrypted_with_header
  * @page: Sort of a ``virtual'' representation of the encrypted lower
  *file. The actual lower file does not have the metadata in
- *the header.
+ *the header. This is locked.
  * @crypt_stat: The eCryptfs inode's cryptographic context
  *
  * The ``view'' is the version of the file that userspace winds up
-
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to [EMAIL PROTECTED]
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/


Re: [PATCH 4/11] eCryptfs: Replace encrypt, decrypt, and inode size write

2007-09-20 Thread Michael Halcrow
On Wed, Sep 19, 2007 at 10:46:26PM -0700, Andrew Morton wrote:
(from ecryptfs_encrypt_page()):
> > +   enc_extent_virt = kmalloc(PAGE_CACHE_SIZE, GFP_USER);
> 
> I'd have thought that alloc_page() would be nicer.  After all, we _are_
> treating it as a page, and not as a random piece of memry.
>
> > +   if (!enc_extent_virt) {
> > +   rc = -ENOMEM;
> > +   ecryptfs_printk(KERN_ERR, "Error allocating memory for "
> > +   "encrypted extent\n");
> > +   goto out;
> > +   }
> > +   enc_extent_page = virt_to_page(enc_extent_virt);
> 
> And then we don't need this.

If neither kmap() nor kmap_atomic() can be safely used to get a
virtual address to pass to vfs_write(), then I do not know what my
other options are here.
-
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to [EMAIL PROTECTED]
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/


Re: [PATCH 4/11] eCryptfs: Replace encrypt, decrypt, and inode size write

2007-09-20 Thread Michael Halcrow
On Wed, Sep 19, 2007 at 10:46:26PM -0700, Andrew Morton wrote:
(from ecryptfs_encrypt_page()):
  +   enc_extent_virt = kmalloc(PAGE_CACHE_SIZE, GFP_USER);
 
 I'd have thought that alloc_page() would be nicer.  After all, we _are_
 treating it as a page, and not as a random piece of memry.

  +   if (!enc_extent_virt) {
  +   rc = -ENOMEM;
  +   ecryptfs_printk(KERN_ERR, Error allocating memory for 
  +   encrypted extent\n);
  +   goto out;
  +   }
  +   enc_extent_page = virt_to_page(enc_extent_virt);
 
 And then we don't need this.

If neither kmap() nor kmap_atomic() can be safely used to get a
virtual address to pass to vfs_write(), then I do not know what my
other options are here.
-
To unsubscribe from this list: send the line unsubscribe linux-kernel in
the body of a message to [EMAIL PROTECTED]
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/


Re: [PATCH 8/11] eCryptfs: Convert mmap functions to use persistent file

2007-09-20 Thread Michael Halcrow
On Wed, Sep 19, 2007 at 10:50:57PM -0700, Andrew Morton wrote:
 On Mon, 17 Sep 2007 16:50:16 -0500 Michael Halcrow [EMAIL PROTECTED] wrote:
  +ecryptfs_copy_up_encrypted_with_header(struct page *page,
  +  struct ecryptfs_crypt_stat *crypt_stat)
  +{
...
  +   flush_dcache_page(page);
  +   if (rc) {
  +   ClearPageUptodate(page);
  +   printk(KERN_ERR %s: Error reading xattr 
  +  region; rc = [%d]\n, __FUNCTION__, rc);
  +   goto out;
  +   }
  +   SetPageUptodate(page);
 
 I don't know what sort of page `page' refers to here, but normally we only
 manipulate the page uptodate status under lock_page().

This is the page that eCryptfs gets via
ecryptfs_aops-ecryptfs_readpage(), so this should be okay. The
comment should make the fact that the page is locked explicit.

Signed-off-by: Michael Halcrow [EMAIL PROTECTED]

---
diff --git a/fs/ecryptfs/mmap.c b/fs/ecryptfs/mmap.c
index 04103ff..c6a8a33 100644
--- a/fs/ecryptfs/mmap.c
+++ b/fs/ecryptfs/mmap.c
@@ -111,7 +111,7 @@ static void set_header_info(char *page_virt,
  * ecryptfs_copy_up_encrypted_with_header
  * @page: Sort of a ``virtual'' representation of the encrypted lower
  *file. The actual lower file does not have the metadata in
- *the header.
+ *the header. This is locked.
  * @crypt_stat: The eCryptfs inode's cryptographic context
  *
  * The ``view'' is the version of the file that userspace winds up
-
To unsubscribe from this list: send the line unsubscribe linux-kernel in
the body of a message to [EMAIL PROTECTED]
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/


[PATCH 11/11] eCryptfs: Replace magic numbers

2007-09-17 Thread Michael Halcrow
Replace some magic numbers with sizeof() equivalents.

Signed-off-by: Michael Halcrow <[EMAIL PROTECTED]>
---
 fs/ecryptfs/crypto.c |6 +++---
 1 files changed, 3 insertions(+), 3 deletions(-)

diff --git a/fs/ecryptfs/crypto.c b/fs/ecryptfs/crypto.c
index 3b3cf27..425a144 100644
--- a/fs/ecryptfs/crypto.c
+++ b/fs/ecryptfs/crypto.c
@@ -1426,10 +1426,10 @@ static int parse_header_metadata(struct 
ecryptfs_crypt_stat *crypt_stat,
u32 header_extent_size;
u16 num_header_extents_at_front;
 
-   memcpy(_extent_size, virt, 4);
+   memcpy(_extent_size, virt, sizeof(u32));
header_extent_size = be32_to_cpu(header_extent_size);
-   virt += 4;
-   memcpy(_header_extents_at_front, virt, 2);
+   virt += sizeof(u32);
+   memcpy(_header_extents_at_front, virt, sizeof(u16));
num_header_extents_at_front = be16_to_cpu(num_header_extents_at_front);
crypt_stat->num_header_extents_at_front =
(int)num_header_extents_at_front;
-- 
1.5.1.6

-
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to [EMAIL PROTECTED]
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/


[PATCH 10/11] eCryptfs: Remove unused functions and kmem_cache

2007-09-17 Thread Michael Halcrow
The switch to read_write.c routines and the persistent file make a
number of functions unnecessary. This patch removes them.

Signed-off-by: Michael Halcrow <[EMAIL PROTECTED]>
---
 fs/ecryptfs/crypto.c  |  150 --
 fs/ecryptfs/ecryptfs_kernel.h |   21 +---
 fs/ecryptfs/file.c|   28 
 fs/ecryptfs/main.c|5 -
 fs/ecryptfs/mmap.c|  336 -
 5 files changed, 1 insertions(+), 539 deletions(-)

diff --git a/fs/ecryptfs/crypto.c b/fs/ecryptfs/crypto.c
index b3014d7..3b3cf27 100644
--- a/fs/ecryptfs/crypto.c
+++ b/fs/ecryptfs/crypto.c
@@ -353,119 +353,6 @@ out:
return rc;
 }
 
-static void
-ecryptfs_extent_to_lwr_pg_idx_and_offset(unsigned long *lower_page_idx,
-int *byte_offset,
-struct ecryptfs_crypt_stat *crypt_stat,
-unsigned long extent_num)
-{
-   unsigned long lower_extent_num;
-   int extents_occupied_by_headers_at_front;
-   int bytes_occupied_by_headers_at_front;
-   int extent_offset;
-   int extents_per_page;
-
-   bytes_occupied_by_headers_at_front =
-   (crypt_stat->extent_size
-* crypt_stat->num_header_extents_at_front);
-   extents_occupied_by_headers_at_front =
-   ( bytes_occupied_by_headers_at_front
- / crypt_stat->extent_size );
-   lower_extent_num = extents_occupied_by_headers_at_front + extent_num;
-   extents_per_page = PAGE_CACHE_SIZE / crypt_stat->extent_size;
-   (*lower_page_idx) = lower_extent_num / extents_per_page;
-   extent_offset = lower_extent_num % extents_per_page;
-   (*byte_offset) = extent_offset * crypt_stat->extent_size;
-   ecryptfs_printk(KERN_DEBUG, " * crypt_stat->extent_size = "
-   "[%d]\n", crypt_stat->extent_size);
-   ecryptfs_printk(KERN_DEBUG, " * crypt_stat->"
-   "num_header_extents_at_front = [%d]\n",
-   crypt_stat->num_header_extents_at_front);
-   ecryptfs_printk(KERN_DEBUG, " * extents_occupied_by_headers_at_"
-   "front = [%d]\n", extents_occupied_by_headers_at_front);
-   ecryptfs_printk(KERN_DEBUG, " * lower_extent_num = [0x%.16x]\n",
-   lower_extent_num);
-   ecryptfs_printk(KERN_DEBUG, " * extents_per_page = [%d]\n",
-   extents_per_page);
-   ecryptfs_printk(KERN_DEBUG, " * (*lower_page_idx) = [0x%.16x]\n",
-   (*lower_page_idx));
-   ecryptfs_printk(KERN_DEBUG, " * extent_offset = [%d]\n",
-   extent_offset);
-   ecryptfs_printk(KERN_DEBUG, " * (*byte_offset) = [%d]\n",
-   (*byte_offset));
-}
-
-static int ecryptfs_write_out_page(struct ecryptfs_page_crypt_context *ctx,
-  struct page *lower_page,
-  struct inode *lower_inode,
-  int byte_offset_in_page, int bytes_to_write)
-{
-   int rc = 0;
-
-   if (ctx->mode == ECRYPTFS_PREPARE_COMMIT_MODE) {
-   rc = ecryptfs_commit_lower_page(lower_page, lower_inode,
-   ctx->param.lower_file,
-   byte_offset_in_page,
-   bytes_to_write);
-   if (rc) {
-   ecryptfs_printk(KERN_ERR, "Error calling lower "
-   "commit; rc = [%d]\n", rc);
-   goto out;
-   }
-   } else {
-   rc = ecryptfs_writepage_and_release_lower_page(lower_page,
-  lower_inode,
-  ctx->param.wbc);
-   if (rc) {
-   ecryptfs_printk(KERN_ERR, "Error calling lower "
-   "writepage(); rc = [%d]\n", rc);
-   goto out;
-   }
-   }
-out:
-   return rc;
-}
-
-static int ecryptfs_read_in_page(struct ecryptfs_page_crypt_context *ctx,
-struct page **lower_page,
-struct inode *lower_inode,
-unsigned long lower_page_idx,
-int byte_offset_in_page)
-{
-   int rc = 0;
-
-   if (ctx->mode == ECRYPTFS_PREPARE_COMMIT_MODE) {
-   /* TODO: Limit this to only the data extents that are
-* needed */
-   rc = ecryptfs_get_lower_page(lower_page, lower_inode

[PATCH 9/11] eCryptfs: Initialize persistent lower file on inode create

2007-09-17 Thread Michael Halcrow
Initialize persistent lower file on inode create.

Signed-off-by: Michael Halcrow <[EMAIL PROTECTED]>
---
 fs/ecryptfs/super.c |   13 +++--
 1 files changed, 7 insertions(+), 6 deletions(-)

diff --git a/fs/ecryptfs/super.c b/fs/ecryptfs/super.c
index b97e210..f8cdab2 100644
--- a/fs/ecryptfs/super.c
+++ b/fs/ecryptfs/super.c
@@ -47,15 +47,16 @@ struct kmem_cache *ecryptfs_inode_info_cache;
  */
 static struct inode *ecryptfs_alloc_inode(struct super_block *sb)
 {
-   struct ecryptfs_inode_info *ecryptfs_inode;
+   struct ecryptfs_inode_info *inode_info;
struct inode *inode = NULL;
 
-   ecryptfs_inode = kmem_cache_alloc(ecryptfs_inode_info_cache,
- GFP_KERNEL);
-   if (unlikely(!ecryptfs_inode))
+   inode_info = kmem_cache_alloc(ecryptfs_inode_info_cache, GFP_KERNEL);
+   if (unlikely(!inode_info))
goto out;
-   ecryptfs_init_crypt_stat(_inode->crypt_stat);
-   inode = _inode->vfs_inode;
+   ecryptfs_init_crypt_stat(_info->crypt_stat);
+   mutex_init(_info->lower_file_mutex);
+   inode_info->lower_file = NULL;
+   inode = _info->vfs_inode;
 out:
return inode;
 }
-- 
1.5.1.6

-
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to [EMAIL PROTECTED]
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/


[PATCH 8/11] eCryptfs: Convert mmap functions to use persistent file

2007-09-17 Thread Michael Halcrow
Convert readpage, prepare_write, and commit_write to use read_write.c
routines. Remove sync_page; I cannot think of a good reason for
implementing that in eCryptfs.

Signed-off-by: Michael Halcrow <[EMAIL PROTECTED]>
---
 fs/ecryptfs/mmap.c |  199 +++-
 1 files changed, 103 insertions(+), 96 deletions(-)

diff --git a/fs/ecryptfs/mmap.c b/fs/ecryptfs/mmap.c
index 60e635e..dd68dd3 100644
--- a/fs/ecryptfs/mmap.c
+++ b/fs/ecryptfs/mmap.c
@@ -267,9 +267,78 @@ static void set_header_info(char *page_virt,
 }
 
 /**
+ * ecryptfs_copy_up_encrypted_with_header
+ * @page: Sort of a ``virtual'' representation of the encrypted lower
+ *file. The actual lower file does not have the metadata in
+ *the header.
+ * @crypt_stat: The eCryptfs inode's cryptographic context
+ *
+ * The ``view'' is the version of the file that userspace winds up
+ * seeing, with the header information inserted.
+ */
+static int
+ecryptfs_copy_up_encrypted_with_header(struct page *page,
+  struct ecryptfs_crypt_stat *crypt_stat)
+{
+   loff_t extent_num_in_page = 0;
+   loff_t num_extents_per_page = (PAGE_CACHE_SIZE
+  / crypt_stat->extent_size);
+   int rc = 0;
+
+   while (extent_num_in_page < num_extents_per_page) {
+   loff_t view_extent_num = ((page->index * num_extents_per_page)
+ + extent_num_in_page);
+
+   if (view_extent_num < crypt_stat->num_header_extents_at_front) {
+   /* This is a header extent */
+   char *page_virt;
+
+   page_virt = kmap_atomic(page, KM_USER0);
+   memset(page_virt, 0, PAGE_CACHE_SIZE);
+   /* TODO: Support more than one header extent */
+   if (view_extent_num == 0) {
+   rc = ecryptfs_read_xattr_region(
+   page_virt, page->mapping->host);
+   set_header_info(page_virt, crypt_stat);
+   }
+   kunmap_atomic(page_virt, KM_USER0);
+   flush_dcache_page(page);
+   if (rc) {
+   ClearPageUptodate(page);
+   printk(KERN_ERR "%s: Error reading xattr "
+  "region; rc = [%d]\n", __FUNCTION__, rc);
+   goto out;
+   }
+   SetPageUptodate(page);
+   } else {
+   /* This is an encrypted data extent */
+   loff_t lower_offset =
+   ((view_extent_num -
+ crypt_stat->num_header_extents_at_front)
+* crypt_stat->extent_size);
+
+   rc = ecryptfs_read_lower_page_segment(
+   page, (lower_offset >> PAGE_CACHE_SHIFT),
+   (lower_offset & ~PAGE_CACHE_MASK),
+   crypt_stat->extent_size, page->mapping->host);
+   if (rc) {
+   printk(KERN_ERR "%s: Error attempting to read "
+  "extent at offset [%lld] in the lower "
+  "file; rc = [%d]\n", __FUNCTION__,
+  lower_offset, rc);
+   goto out;
+   }
+   }
+   extent_num_in_page++;
+   }
+out:
+   return rc;
+}
+
+/**
  * ecryptfs_readpage
- * @file: This is an ecryptfs file
- * @page: ecryptfs associated page to stick the read data into
+ * @file: An eCryptfs file
+ * @page: Page from eCryptfs inode mapping into which to stick the read data
  *
  * Read in a page, decrypting if necessary.
  *
@@ -277,59 +346,35 @@ static void set_header_info(char *page_virt,
  */
 static int ecryptfs_readpage(struct file *file, struct page *page)
 {
+   struct ecryptfs_crypt_stat *crypt_stat =
+   
_inode_to_private(file->f_path.dentry->d_inode)->crypt_stat;
int rc = 0;
-   struct ecryptfs_crypt_stat *crypt_stat;
 
-   BUG_ON(!(file && file->f_path.dentry && file->f_path.dentry->d_inode));
-   crypt_stat = _inode_to_private(file->f_path.dentry->d_inode)
-   ->crypt_stat;
if (!crypt_stat
|| !(crypt_stat->flags & ECRYPTFS_ENCRYPTED)
|| (crypt_stat->flags & ECRYPTFS_NEW_FILE)) {
ecryptfs_printk(KERN_DEBUG,
"Passing through unencrypted page\n")

[PATCH 7/11] eCryptfs: Make open, truncate, and setattr use persistent file

2007-09-17 Thread Michael Halcrow
Rather than open a new lower file for every eCryptfs file that is
opened, truncated, or setattr'd, instead use the existing lower
persistent file for the eCryptfs inode. Change truncate to use
read_write.c functions. Change ecryptfs_getxattr() to use the common
ecryptfs_getxattr_lower() function.

Signed-off-by: Michael Halcrow <[EMAIL PROTECTED]>
---
 fs/ecryptfs/crypto.c |2 +-
 fs/ecryptfs/file.c   |   50 --
 fs/ecryptfs/inode.c  |  113 +++---
 3 files changed, 44 insertions(+), 121 deletions(-)

diff --git a/fs/ecryptfs/crypto.c b/fs/ecryptfs/crypto.c
index 6b4d310..b3014d7 100644
--- a/fs/ecryptfs/crypto.c
+++ b/fs/ecryptfs/crypto.c
@@ -1674,7 +1674,7 @@ out:
 /**
  * ecryptfs_read_xattr_region
  * @page_virt: The vitual address into which to read the xattr data
- * @ecryptfs_dentry: The eCryptfs dentry
+ * @ecryptfs_inode: The eCryptfs inode
  *
  * Attempts to read the crypto metadata from the extended attribute
  * region of the lower file.
diff --git a/fs/ecryptfs/file.c b/fs/ecryptfs/file.c
index df70bfa..95be9a9 100644
--- a/fs/ecryptfs/file.c
+++ b/fs/ecryptfs/file.c
@@ -187,11 +187,7 @@ static int ecryptfs_open(struct inode *inode, struct file 
*file)
/* Private value of ecryptfs_dentry allocated in
 * ecryptfs_lookup() */
struct dentry *lower_dentry = ecryptfs_dentry_to_lower(ecryptfs_dentry);
-   struct inode *lower_inode = NULL;
-   struct file *lower_file = NULL;
-   struct vfsmount *lower_mnt;
struct ecryptfs_file_info *file_info;
-   int lower_flags;
 
mount_crypt_stat = _superblock_to_private(
ecryptfs_dentry->d_sb)->mount_crypt_stat;
@@ -219,26 +215,12 @@ static int ecryptfs_open(struct inode *inode, struct file 
*file)
if (!(crypt_stat->flags & ECRYPTFS_POLICY_APPLIED)) {
ecryptfs_printk(KERN_DEBUG, "Setting flags for stat...\n");
/* Policy code enabled in future release */
-   crypt_stat->flags |= ECRYPTFS_POLICY_APPLIED;
-   crypt_stat->flags |= ECRYPTFS_ENCRYPTED;
+   crypt_stat->flags |= (ECRYPTFS_POLICY_APPLIED
+ | ECRYPTFS_ENCRYPTED);
}
mutex_unlock(_stat->cs_mutex);
-   lower_flags = file->f_flags;
-   if ((lower_flags & O_ACCMODE) == O_WRONLY)
-   lower_flags = (lower_flags & O_ACCMODE) | O_RDWR;
-   if (file->f_flags & O_APPEND)
-   lower_flags &= ~O_APPEND;
-   lower_mnt = ecryptfs_dentry_to_lower_mnt(ecryptfs_dentry);
-   /* Corresponding fput() in ecryptfs_release() */
-   rc = ecryptfs_open_lower_file(_file, lower_dentry, lower_mnt,
- lower_flags);
-   if (rc) {
-   ecryptfs_printk(KERN_ERR, "Error opening lower file\n");
-   goto out_puts;
-   }
-   ecryptfs_set_file_lower(file, lower_file);
-   /* Isn't this check the same as the one in lookup? */
-   lower_inode = lower_dentry->d_inode;
+   ecryptfs_set_file_lower(
+   file, ecryptfs_inode_to_private(inode)->lower_file);
if (S_ISDIR(ecryptfs_dentry->d_inode->i_mode)) {
ecryptfs_printk(KERN_DEBUG, "This is a directory\n");
crypt_stat->flags &= ~(ECRYPTFS_ENCRYPTED);
@@ -260,7 +242,7 @@ static int ecryptfs_open(struct inode *inode, struct file 
*file)
   "and plaintext passthrough mode is not "
   "enabled; returning -EIO\n");
mutex_unlock(_stat->cs_mutex);
-   goto out_puts;
+   goto out_free;
}
rc = 0;
crypt_stat->flags &= ~(ECRYPTFS_ENCRYPTED);
@@ -272,11 +254,8 @@ static int ecryptfs_open(struct inode *inode, struct file 
*file)
ecryptfs_printk(KERN_DEBUG, "inode w/ addr = [0x%p], i_ino = [0x%.16x] "
"size: [0x%.16x]\n", inode, inode->i_ino,
i_size_read(inode));
-   ecryptfs_set_file_lower(file, lower_file);
goto out;
-out_puts:
-   mntput(lower_mnt);
-   dput(lower_dentry);
+out_free:
kmem_cache_free(ecryptfs_file_info_cache,
ecryptfs_file_to_private(file));
 out:
@@ -296,20 +275,9 @@ static int ecryptfs_flush(struct file *file, fl_owner_t td)
 
 static int ecryptfs_release(struct inode *inode, struct file *file)
 {
-   struct file *lower_file = ecryptfs_file_to_lower(file);
-   struct ecryptfs_file_info *file_info = ecryptfs_file_to_private(file);
-   struct inode *lower_inode = ecryptfs_inode_to_lower(inode);
-   int rc;
-
-   rc = ecryptfs_close_lower_fil

[PATCH 6/11] eCryptfs: Update metadata read/write functions

2007-09-17 Thread Michael Halcrow
Update the metadata read/write functions and grow_file() to use the
read_write.c routines. Do not open another lower file; use the
persistent lower file instead. Provide a separate function for
crypto.c::ecryptfs_read_xattr_region() to get to the lower xattr
without having to go through the eCryptfs getxattr.

Signed-off-by: Michael Halcrow <[EMAIL PROTECTED]>
---
 fs/ecryptfs/crypto.c  |  126 +++--
 fs/ecryptfs/ecryptfs_kernel.h |   15 +++--
 fs/ecryptfs/file.c|2 +-
 fs/ecryptfs/inode.c   |  101 +++--
 fs/ecryptfs/mmap.c|2 +-
 5 files changed, 113 insertions(+), 133 deletions(-)

diff --git a/fs/ecryptfs/crypto.c b/fs/ecryptfs/crypto.c
index d6a0680..6b4d310 100644
--- a/fs/ecryptfs/crypto.c
+++ b/fs/ecryptfs/crypto.c
@@ -1344,21 +1344,28 @@ out:
return rc;
 }
 
-int ecryptfs_read_and_validate_header_region(char *data, struct dentry *dentry,
-struct vfsmount *mnt)
+int ecryptfs_read_and_validate_header_region(char *data,
+struct inode *ecryptfs_inode)
 {
+   struct ecryptfs_crypt_stat *crypt_stat =
+   &(ecryptfs_inode_to_private(ecryptfs_inode)->crypt_stat);
int rc;
 
-   rc = ecryptfs_read_header_region(data, dentry, mnt);
-   if (rc)
+   rc = ecryptfs_read_lower(data, 0, crypt_stat->extent_size,
+ecryptfs_inode);
+   if (rc) {
+   printk(KERN_ERR "%s: Error reading header region; rc = [%d]\n",
+  __FUNCTION__, rc);
goto out;
-   if (!contains_ecryptfs_marker(data + ECRYPTFS_FILE_SIZE_BYTES))
+   }
+   if (!contains_ecryptfs_marker(data + ECRYPTFS_FILE_SIZE_BYTES)) {
rc = -EINVAL;
+   ecryptfs_printk(KERN_DEBUG, "Valid marker not found\n");
+   }
 out:
return rc;
 }
 
-
 void
 ecryptfs_write_header_metadata(char *virt,
   struct ecryptfs_crypt_stat *crypt_stat,
@@ -1443,24 +1450,18 @@ static int ecryptfs_write_headers_virt(char *page_virt, 
size_t *size,
 
 static int
 ecryptfs_write_metadata_to_contents(struct ecryptfs_crypt_stat *crypt_stat,
-   struct file *lower_file, char *page_virt)
+   struct dentry *ecryptfs_dentry,
+   char *page_virt)
 {
-   mm_segment_t oldfs;
int current_header_page;
int header_pages;
-   ssize_t size;
-   int rc = 0;
+   int rc;
 
-   lower_file->f_pos = 0;
-   oldfs = get_fs();
-   set_fs(get_ds());
-   size = vfs_write(lower_file, (char __user *)page_virt, PAGE_CACHE_SIZE,
-_file->f_pos);
-   if (size < 0) {
-   rc = (int)size;
-   printk(KERN_ERR "Error attempting to write lower page; "
-  "rc = [%d]\n", rc);
-   set_fs(oldfs);
+   if ((rc = ecryptfs_write_lower(ecryptfs_dentry->d_inode, page_virt,
+  0, PAGE_CACHE_SIZE))) {
+   printk(KERN_ERR "%s: Error attempting to write header "
+  "information to lower file; rc = [%d]\n", __FUNCTION__,
+  rc);
goto out;
}
header_pages = ((crypt_stat->extent_size
@@ -1469,18 +1470,19 @@ ecryptfs_write_metadata_to_contents(struct 
ecryptfs_crypt_stat *crypt_stat,
memset(page_virt, 0, PAGE_CACHE_SIZE);
current_header_page = 1;
while (current_header_page < header_pages) {
-   size = vfs_write(lower_file, (char __user *)page_virt,
-PAGE_CACHE_SIZE, _file->f_pos);
-   if (size < 0) {
-   rc = (int)size;
-   printk(KERN_ERR "Error attempting to write lower page; "
-  "rc = [%d]\n", rc);
-   set_fs(oldfs);
+   loff_t offset;
+
+   offset = (current_header_page << PAGE_CACHE_SHIFT);
+   if ((rc = ecryptfs_write_lower(ecryptfs_dentry->d_inode,
+  page_virt, offset,
+  PAGE_CACHE_SIZE))) {
+   printk(KERN_ERR "%s: Error attempting to write header "
+  "information to lower file; rc = [%d]\n",
+  __FUNCTION__, rc);
goto out;
}
current_header_page++;
}
-   set_fs(oldfs);
 out:
return rc;
 }
@@ -1500,7 +1502,6 @@ ecryptfs_write_metadata_to_xattr(struct dentry 
*ecryptfs_dentry,
 /**
  * ecryptfs_write_metadata
  *

[PATCH 5/11] eCryptfs: Set up and destroy persistent lower file

2007-09-17 Thread Michael Halcrow
This patch sets up and destroys the persistent lower file for each
eCryptfs inode.

Signed-off-by: Michael Halcrow <[EMAIL PROTECTED]>
---
 fs/ecryptfs/inode.c |   23 +++---
 fs/ecryptfs/main.c  |   65 +++
 fs/ecryptfs/super.c |   22 +++--
 3 files changed, 103 insertions(+), 7 deletions(-)

diff --git a/fs/ecryptfs/inode.c b/fs/ecryptfs/inode.c
index 7192a81..c746b5d 100644
--- a/fs/ecryptfs/inode.c
+++ b/fs/ecryptfs/inode.c
@@ -119,10 +119,23 @@ ecryptfs_do_create(struct inode *directory_inode,
}
rc = ecryptfs_create_underlying_file(lower_dir_dentry->d_inode,
 ecryptfs_dentry, mode, nd);
-   if (unlikely(rc)) {
-   ecryptfs_printk(KERN_ERR,
-   "Failure to create underlying file\n");
-   goto out_lock;
+   if (rc) {
+   struct inode *ecryptfs_inode = ecryptfs_dentry->d_inode;
+   struct ecryptfs_inode_info *inode_info =
+   ecryptfs_inode_to_private(ecryptfs_inode);
+
+   printk(KERN_WARNING "%s: Error creating underlying file; "
+  "rc = [%d]; checking for existing\n", __FUNCTION__, rc);
+   if (inode_info) {
+   mutex_lock(_info->lower_file_mutex);
+   if (!inode_info->lower_file) {
+   mutex_unlock(_info->lower_file_mutex);
+   printk(KERN_ERR "%s: Failure to set underlying "
+  "file; rc = [%d]\n", __FUNCTION__, rc);
+   goto out_lock;
+   }
+   mutex_unlock(_info->lower_file_mutex);
+   }
}
rc = ecryptfs_interpose(lower_dentry, ecryptfs_dentry,
directory_inode->i_sb, 0);
@@ -252,6 +265,8 @@ ecryptfs_create(struct inode *directory_inode, struct 
dentry *ecryptfs_dentry,
 {
int rc;
 
+   /* ecryptfs_do_create() calls ecryptfs_interpose(), which opens
+* the crypt_stat->lower_file (persistent file) */
rc = ecryptfs_do_create(directory_inode, ecryptfs_dentry, mode, nd);
if (unlikely(rc)) {
ecryptfs_printk(KERN_WARNING, "Failed to create file in"
diff --git a/fs/ecryptfs/main.c b/fs/ecryptfs/main.c
index 967bad0..3e324f8 100644
--- a/fs/ecryptfs/main.c
+++ b/fs/ecryptfs/main.c
@@ -98,6 +98,64 @@ void __ecryptfs_printk(const char *fmt, ...)
 }
 
 /**
+ * ecryptfs_init_persistent_file
+ * @ecryptfs_dentry: Fully initialized eCryptfs dentry object, with
+ *   the lower dentry and the lower mount set
+ *
+ * eCryptfs only ever keeps a single open file for every lower
+ * inode. All I/O operations to the lower inode occur through that
+ * file. When the first eCryptfs dentry that interposes with the first
+ * lower dentry for that inode is created, this function creates the
+ * persistent file struct and associates it with the eCryptfs
+ * inode. When the eCryptfs inode is destroyed, the file is closed.
+ *
+ * The persistent file will be opened with read/write permissions, if
+ * possible. Otherwise, it is opened read-only.
+ *
+ * This function does nothing if a lower persistent file is already
+ * associated with the eCryptfs inode.
+ *
+ * Returns zero on success; non-zero otherwise
+ */
+int ecryptfs_init_persistent_file(struct dentry *ecryptfs_dentry)
+{
+   struct ecryptfs_inode_info *inode_info =
+   ecryptfs_inode_to_private(ecryptfs_dentry->d_inode);
+   int rc = 0;
+
+   mutex_lock(_info->lower_file_mutex);
+   if (!inode_info->lower_file) {
+   struct dentry *lower_dentry;
+   struct vfsmount *lower_mnt =
+   ecryptfs_dentry_to_lower_mnt(ecryptfs_dentry);
+
+   lower_dentry = ecryptfs_dentry_to_lower(ecryptfs_dentry);
+   /* Corresponding dput() and mntput() are done when the
+* persistent file is fput() when the eCryptfs inode
+* is destroyed. */
+   dget(lower_dentry);
+   mntget(lower_mnt);
+   inode_info->lower_file = dentry_open(lower_dentry,
+lower_mnt,
+(O_RDWR | O_LARGEFILE));
+   if (IS_ERR(inode_info->lower_file))
+   inode_info->lower_file = dentry_open(lower_dentry,
+lower_mnt,
+(O_RDONLY
+ | O_LARGEFILE));
+   if (IS_ERR(inode_info->lower_file)) {
+   printk(KERN_ERR "

[PATCH 4/11] eCryptfs: Replace encrypt, decrypt, and inode size write

2007-09-17 Thread Michael Halcrow
Replace page encryption and decryption routines and inode size write
routine with versions that utilize the read_write.c functions.

Signed-off-by: Michael Halcrow <[EMAIL PROTECTED]>
---
 fs/ecryptfs/crypto.c  |  427 ++--
 fs/ecryptfs/ecryptfs_kernel.h |   14 +-
 fs/ecryptfs/inode.c   |   12 +-
 fs/ecryptfs/mmap.c|  131 -
 fs/ecryptfs/read_write.c  |   12 +-
 5 files changed, 290 insertions(+), 306 deletions(-)

diff --git a/fs/ecryptfs/crypto.c b/fs/ecryptfs/crypto.c
index 5d8a553..b829d3c 100644
--- a/fs/ecryptfs/crypto.c
+++ b/fs/ecryptfs/crypto.c
@@ -467,8 +467,91 @@ out:
 }
 
 /**
+ * ecryptfs_lower_offset_for_extent
+ *
+ * Convert an eCryptfs page index into a lower byte offset
+ */
+void ecryptfs_lower_offset_for_extent(loff_t *offset, loff_t extent_num,
+ struct ecryptfs_crypt_stat *crypt_stat)
+{
+   (*offset) = ((crypt_stat->extent_size
+ * crypt_stat->num_header_extents_at_front)
++ (crypt_stat->extent_size * extent_num));
+}
+
+/**
+ * ecryptfs_encrypt_extent
+ * @enc_extent_page: Allocated page into which to encrypt the data in
+ *   @page
+ * @crypt_stat: crypt_stat containing cryptographic context for the
+ *  encryption operation
+ * @page: Page containing plaintext data extent to encrypt
+ * @extent_offset: Page extent offset for use in generating IV
+ *
+ * Encrypts one extent of data.
+ *
+ * Return zero on success; non-zero otherwise
+ */
+static int ecryptfs_encrypt_extent(struct page *enc_extent_page,
+  struct ecryptfs_crypt_stat *crypt_stat,
+  struct page *page,
+  unsigned long extent_offset)
+{
+   unsigned long extent_base;
+   char extent_iv[ECRYPTFS_MAX_IV_BYTES];
+   int rc;
+
+   extent_base = (page->index
+  * (PAGE_CACHE_SIZE / crypt_stat->extent_size));
+   rc = ecryptfs_derive_iv(extent_iv, crypt_stat,
+   (extent_base + extent_offset));
+   if (rc) {
+   ecryptfs_printk(KERN_ERR, "Error attempting to "
+   "derive IV for extent [0x%.16x]; "
+   "rc = [%d]\n", (extent_base + extent_offset),
+   rc);
+   goto out;
+   }
+   if (unlikely(ecryptfs_verbosity > 0)) {
+   ecryptfs_printk(KERN_DEBUG, "Encrypting extent "
+   "with iv:\n");
+   ecryptfs_dump_hex(extent_iv, crypt_stat->iv_bytes);
+   ecryptfs_printk(KERN_DEBUG, "First 8 bytes before "
+   "encryption:\n");
+   ecryptfs_dump_hex((char *)
+ (page_address(page)
+  + (extent_offset * crypt_stat->extent_size)),
+ 8);
+   }
+   rc = ecryptfs_encrypt_page_offset(crypt_stat, enc_extent_page, 0,
+ page, (extent_offset
+* crypt_stat->extent_size),
+ crypt_stat->extent_size, extent_iv);
+   if (rc < 0) {
+   printk(KERN_ERR "%s: Error attempting to encrypt page with "
+  "page->index = [%ld], extent_offset = [%ld]; "
+  "rc = [%d]\n", __FUNCTION__, page->index, extent_offset,
+  rc);
+   goto out;
+   }
+   rc = 0;
+   if (unlikely(ecryptfs_verbosity > 0)) {
+   ecryptfs_printk(KERN_DEBUG, "Encrypt extent [0x%.16x]; "
+   "rc = [%d]\n", (extent_base + extent_offset),
+   rc);
+   ecryptfs_printk(KERN_DEBUG, "First 8 bytes after "
+   "encryption:\n");
+   ecryptfs_dump_hex((char *)(page_address(enc_extent_page)), 8);
+   }
+out:
+   return rc;
+}
+
+/**
  * ecryptfs_encrypt_page
- * @ctx: The context of the page
+ * @page: Page mapped from the eCryptfs inode for the file; contains
+ *decrypted content that needs to be encrypted (to a temporary
+ *page; not in place) and written out to the lower file
  *
  * Encrypt an eCryptfs page. This is done on a per-extent basis. Note
  * that eCryptfs pages may straddle the lower pages -- for instance,
@@ -478,128 +561,121 @@ out:
  * file, 24K of page 0 of the lower file will be read and decrypted,
  * and then 8K of page 1 of the lower file will be read and decrypted.
  *
- * The actual operations performed on each page depends on the
- * contents of the ecryp

[PATCH 3/11] eCryptfs: read_write.c routines

2007-09-17 Thread Michael Halcrow
Add a set of functions through which all I/O to lower files is
consolidated. This patch adds a new inode_info reference to a
persistent lower file for each eCryptfs inode; another patch later in
this series will set that up. This persistent lower file is what the
read_write.c functions use to call vfs_read() and vfs_write() on the
lower filesystem, so even when reads and writes come in through
aops->readpage and aops->writepage, we can satisfy them without
resorting to direct access to the lower inode's address space.
Several function declarations are going to be changing with this
patchset. For now, in order to keep from breaking the build, I am
putting dummy parameters in for those functions.

Signed-off-by: Michael Halcrow <[EMAIL PROTECTED]>
---
 fs/ecryptfs/Makefile  |2 +-
 fs/ecryptfs/ecryptfs_kernel.h |   18 ++
 fs/ecryptfs/mmap.c|2 +-
 fs/ecryptfs/read_write.c  |  359 +
 4 files changed, 379 insertions(+), 2 deletions(-)
 create mode 100644 fs/ecryptfs/read_write.c

diff --git a/fs/ecryptfs/Makefile b/fs/ecryptfs/Makefile
index 1f11072..7688570 100644
--- a/fs/ecryptfs/Makefile
+++ b/fs/ecryptfs/Makefile
@@ -4,4 +4,4 @@
 
 obj-$(CONFIG_ECRYPT_FS) += ecryptfs.o
 
-ecryptfs-objs := dentry.o file.o inode.o main.o super.o mmap.o crypto.o 
keystore.o messaging.o netlink.o debug.o
+ecryptfs-objs := dentry.o file.o inode.o main.o super.o mmap.o read_write.o 
crypto.o keystore.o messaging.o netlink.o debug.o
diff --git a/fs/ecryptfs/ecryptfs_kernel.h b/fs/ecryptfs/ecryptfs_kernel.h
index a618ab7..e6a68a8 100644
--- a/fs/ecryptfs/ecryptfs_kernel.h
+++ b/fs/ecryptfs/ecryptfs_kernel.h
@@ -260,6 +260,8 @@ struct ecryptfs_crypt_stat {
 struct ecryptfs_inode_info {
struct inode vfs_inode;
struct inode *wii_inode;
+   struct file *lower_file;
+   struct mutex lower_file_mutex;
struct ecryptfs_crypt_stat crypt_stat;
 };
 
@@ -653,5 +655,21 @@ int ecryptfs_keyring_auth_tok_for_sig(struct key 
**auth_tok_key,
  char *sig);
 int ecryptfs_write_zeros(struct file *file, pgoff_t index, int start,
 int num_zeros);
+int ecryptfs_write_lower(struct inode *ecryptfs_inode, char *data,
+loff_t offset, size_t size);
+int ecryptfs_write_lower_page_segment(struct inode *ecryptfs_inode,
+ struct page *page_for_lower,
+ size_t offset_in_page, size_t size);
+int ecryptfs_write(struct file *ecryptfs_file, char *data, loff_t offset,
+  size_t size);
+int ecryptfs_read_lower(char *data, loff_t offset, size_t size,
+   struct inode *ecryptfs_inode);
+int ecryptfs_read_lower_page_segment(struct page *page_for_ecryptfs,
+pgoff_t page_index,
+size_t offset_in_page, size_t size,
+struct inode *ecryptfs_inode);
+int ecryptfs_read(char *data, loff_t offset, size_t size,
+ struct file *ecryptfs_file);
+struct page *ecryptfs_get1page(struct file *file, loff_t index);
 
 #endif /* #ifndef ECRYPTFS_KERNEL_H */
diff --git a/fs/ecryptfs/mmap.c b/fs/ecryptfs/mmap.c
index 307f7ee..0c53320 100644
--- a/fs/ecryptfs/mmap.c
+++ b/fs/ecryptfs/mmap.c
@@ -44,7 +44,7 @@ struct kmem_cache *ecryptfs_lower_page_cache;
  * Returns unlocked and up-to-date page (if ok), with increased
  * refcnt.
  */
-static struct page *ecryptfs_get1page(struct file *file, int index)
+struct page *ecryptfs_get1page(struct file *file, loff_t index)
 {
struct dentry *dentry;
struct inode *inode;
diff --git a/fs/ecryptfs/read_write.c b/fs/ecryptfs/read_write.c
new file mode 100644
index 000..e59c94a
--- /dev/null
+++ b/fs/ecryptfs/read_write.c
@@ -0,0 +1,359 @@
+/**
+ * eCryptfs: Linux filesystem encryption layer
+ *
+ * Copyright (C) 2007 International Business Machines Corp.
+ *   Author(s): Michael A. Halcrow <[EMAIL PROTECTED]>
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of the
+ * License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
+ * 02111-1307, USA.
+ */
+
+#include 
+#include 
+#include "ecryptfs_kernel.h"
+
+/**
+ * ecryptfs_write_lower
+ * @ecryptfs_inode: The eCryptfs inode
+ * @data: Data to write
+ * @offset: B

[PATCH 2/11] eCryptfs: Remove assignments in if-statements

2007-09-17 Thread Michael Halcrow
Remove assignments in if-statements.

Signed-off-by: Michael Halcrow <[EMAIL PROTECTED]>
---
 fs/ecryptfs/crypto.c|   17 --
 fs/ecryptfs/file.c  |8 --
 fs/ecryptfs/inode.c |   35 ++
 fs/ecryptfs/keystore.c  |   55 +-
 fs/ecryptfs/main.c  |   28 ++-
 fs/ecryptfs/messaging.c |5 ++-
 fs/ecryptfs/mmap.c  |5 ++-
 7 files changed, 89 insertions(+), 64 deletions(-)

diff --git a/fs/ecryptfs/crypto.c b/fs/ecryptfs/crypto.c
index 3dbb21a..5d8a553 100644
--- a/fs/ecryptfs/crypto.c
+++ b/fs/ecryptfs/crypto.c
@@ -1277,8 +1277,8 @@ static int ecryptfs_read_header_region(char *data, struct 
dentry *dentry,
mm_segment_t oldfs;
int rc;
 
-   if ((rc = ecryptfs_open_lower_file(_file, dentry, mnt,
-  O_RDONLY))) {
+   rc = ecryptfs_open_lower_file(_file, dentry, mnt, O_RDONLY);
+   if (rc) {
printk(KERN_ERR
   "Error opening lower_file to read header region\n");
goto out;
@@ -1289,7 +1289,8 @@ static int ecryptfs_read_header_region(char *data, struct 
dentry *dentry,
rc = lower_file->f_op->read(lower_file, (char __user *)data,
  ECRYPTFS_DEFAULT_EXTENT_SIZE, _file->f_pos);
set_fs(oldfs);
-   if ((rc = ecryptfs_close_lower_file(lower_file))) {
+   rc = ecryptfs_close_lower_file(lower_file);
+   if (rc) {
printk(KERN_ERR "Error closing lower_file\n");
goto out;
}
@@ -1951,9 +1952,10 @@ ecryptfs_add_new_key_tfm(struct ecryptfs_key_tfm 
**key_tfm, char *cipher_name,
strncpy(tmp_tfm->cipher_name, cipher_name,
ECRYPTFS_MAX_CIPHER_NAME_SIZE);
tmp_tfm->key_size = key_size;
-   if ((rc = ecryptfs_process_key_cipher(_tfm->key_tfm,
- tmp_tfm->cipher_name,
- _tfm->key_size))) {
+   rc = ecryptfs_process_key_cipher(_tfm->key_tfm,
+tmp_tfm->cipher_name,
+_tfm->key_size);
+   if (rc) {
printk(KERN_ERR "Error attempting to initialize key TFM "
   "cipher with name = [%s]; rc = [%d]\n",
   tmp_tfm->cipher_name, rc);
@@ -1988,7 +1990,8 @@ int ecryptfs_get_tfm_and_mutex_for_cipher_name(struct 
crypto_blkcipher **tfm,
}
}
mutex_unlock(_tfm_list_mutex);
-   if ((rc = ecryptfs_add_new_key_tfm(_tfm, cipher_name, 0))) {
+   rc = ecryptfs_add_new_key_tfm(_tfm, cipher_name, 0);
+   if (rc) {
printk(KERN_ERR "Error adding new key_tfm to list; rc = [%d]\n",
   rc);
goto out;
diff --git a/fs/ecryptfs/file.c b/fs/ecryptfs/file.c
index 12ba7e3..59c846d 100644
--- a/fs/ecryptfs/file.c
+++ b/fs/ecryptfs/file.c
@@ -230,8 +230,9 @@ static int ecryptfs_open(struct inode *inode, struct file 
*file)
lower_flags &= ~O_APPEND;
lower_mnt = ecryptfs_dentry_to_lower_mnt(ecryptfs_dentry);
/* Corresponding fput() in ecryptfs_release() */
-   if ((rc = ecryptfs_open_lower_file(_file, lower_dentry, lower_mnt,
-  lower_flags))) {
+   rc = ecryptfs_open_lower_file(_file, lower_dentry, lower_mnt,
+ lower_flags);
+   if (rc) {
ecryptfs_printk(KERN_ERR, "Error opening lower file\n");
goto out_puts;
}
@@ -300,7 +301,8 @@ static int ecryptfs_release(struct inode *inode, struct 
file *file)
struct inode *lower_inode = ecryptfs_inode_to_lower(inode);
int rc;
 
-   if ((rc = ecryptfs_close_lower_file(lower_file))) {
+   rc = ecryptfs_close_lower_file(lower_file);
+   if (rc) {
printk(KERN_ERR "Error closing lower_file\n");
goto out;
}
diff --git a/fs/ecryptfs/inode.c b/fs/ecryptfs/inode.c
index abac91c..d70f599 100644
--- a/fs/ecryptfs/inode.c
+++ b/fs/ecryptfs/inode.c
@@ -202,8 +202,9 @@ static int ecryptfs_initialize_file(struct dentry 
*ecryptfs_dentry)
lower_flags = ((O_CREAT | O_TRUNC) & O_ACCMODE) | O_RDWR;
lower_mnt = ecryptfs_dentry_to_lower_mnt(ecryptfs_dentry);
/* Corresponding fput() at end of this function */
-   if ((rc = ecryptfs_open_lower_file(_file, lower_dentry, lower_mnt,
-  lower_flags))) {
+   rc = ecryptfs_open_lower_file(_file, lower_dentry, lower_mnt,
+ lower_flags);
+   if (rc) {
ecryptfs_printk(KERN_ERR,
"Error opening dentry; rc = [%

[PATCH 1/11] eCryptfs: Remove header_extent_size

2007-09-17 Thread Michael Halcrow
There is no point to keeping a separate header_extent_size and an
extent_size. The total size of the header can always be represented as
some multiple of the regular data extent size.

Signed-off-by: Michael Halcrow <[EMAIL PROTECTED]>
---
 fs/ecryptfs/crypto.c  |   40 
 fs/ecryptfs/ecryptfs_kernel.h |   39 +++
 fs/ecryptfs/inode.c   |7 ---
 fs/ecryptfs/mmap.c|2 +-
 4 files changed, 52 insertions(+), 36 deletions(-)

diff --git a/fs/ecryptfs/crypto.c b/fs/ecryptfs/crypto.c
index 8e9b36d..3dbb21a 100644
--- a/fs/ecryptfs/crypto.c
+++ b/fs/ecryptfs/crypto.c
@@ -366,8 +366,8 @@ ecryptfs_extent_to_lwr_pg_idx_and_offset(unsigned long 
*lower_page_idx,
int extents_per_page;
 
bytes_occupied_by_headers_at_front =
-   ( crypt_stat->header_extent_size
- * crypt_stat->num_header_extents_at_front );
+   (crypt_stat->extent_size
+* crypt_stat->num_header_extents_at_front);
extents_occupied_by_headers_at_front =
( bytes_occupied_by_headers_at_front
  / crypt_stat->extent_size );
@@ -376,8 +376,8 @@ ecryptfs_extent_to_lwr_pg_idx_and_offset(unsigned long 
*lower_page_idx,
(*lower_page_idx) = lower_extent_num / extents_per_page;
extent_offset = lower_extent_num % extents_per_page;
(*byte_offset) = extent_offset * crypt_stat->extent_size;
-   ecryptfs_printk(KERN_DEBUG, " * crypt_stat->header_extent_size = "
-   "[%d]\n", crypt_stat->header_extent_size);
+   ecryptfs_printk(KERN_DEBUG, " * crypt_stat->extent_size = "
+   "[%d]\n", crypt_stat->extent_size);
ecryptfs_printk(KERN_DEBUG, " * crypt_stat->"
"num_header_extents_at_front = [%d]\n",
crypt_stat->num_header_extents_at_front);
@@ -899,15 +899,17 @@ void ecryptfs_set_default_sizes(struct 
ecryptfs_crypt_stat *crypt_stat)
crypt_stat->extent_size = ECRYPTFS_DEFAULT_EXTENT_SIZE;
set_extent_mask_and_shift(crypt_stat);
crypt_stat->iv_bytes = ECRYPTFS_DEFAULT_IV_BYTES;
-   if (PAGE_CACHE_SIZE <= ECRYPTFS_MINIMUM_HEADER_EXTENT_SIZE) {
-   crypt_stat->header_extent_size =
-   ECRYPTFS_MINIMUM_HEADER_EXTENT_SIZE;
-   } else
-   crypt_stat->header_extent_size = PAGE_CACHE_SIZE;
if (crypt_stat->flags & ECRYPTFS_METADATA_IN_XATTR)
crypt_stat->num_header_extents_at_front = 0;
-   else
-   crypt_stat->num_header_extents_at_front = 1;
+   else {
+   if (PAGE_CACHE_SIZE <= ECRYPTFS_MINIMUM_HEADER_EXTENT_SIZE)
+   crypt_stat->num_header_extents_at_front =
+   (ECRYPTFS_MINIMUM_HEADER_EXTENT_SIZE
+/ crypt_stat->extent_size);
+   else
+   crypt_stat->num_header_extents_at_front =
+   (PAGE_CACHE_SIZE / crypt_stat->extent_size);
+   }
 }
 
 /**
@@ -1319,7 +1321,7 @@ ecryptfs_write_header_metadata(char *virt,
u32 header_extent_size;
u16 num_header_extents_at_front;
 
-   header_extent_size = (u32)crypt_stat->header_extent_size;
+   header_extent_size = (u32)crypt_stat->extent_size;
num_header_extents_at_front =
(u16)crypt_stat->num_header_extents_at_front;
header_extent_size = cpu_to_be32(header_extent_size);
@@ -1415,7 +1417,7 @@ ecryptfs_write_metadata_to_contents(struct 
ecryptfs_crypt_stat *crypt_stat,
set_fs(oldfs);
goto out;
}
-   header_pages = ((crypt_stat->header_extent_size
+   header_pages = ((crypt_stat->extent_size
 * crypt_stat->num_header_extents_at_front)
/ PAGE_CACHE_SIZE);
memset(page_virt, 0, PAGE_CACHE_SIZE);
@@ -1532,17 +1534,16 @@ static int parse_header_metadata(struct 
ecryptfs_crypt_stat *crypt_stat,
virt += 4;
memcpy(_header_extents_at_front, virt, 2);
num_header_extents_at_front = be16_to_cpu(num_header_extents_at_front);
-   crypt_stat->header_extent_size = (int)header_extent_size;
crypt_stat->num_header_extents_at_front =
(int)num_header_extents_at_front;
-   (*bytes_read) = 6;
+   (*bytes_read) = (sizeof(u32) + sizeof(u16));
if ((validate_header_size == ECRYPTFS_VALIDATE_HEADER_SIZE)
-   && ((crypt_stat->header_extent_size
+   && ((crypt_stat->extent_size
 * crypt_stat->num_header_extents_at_front)
< ECRYPTFS_MINIMUM_HEADER_EXTENT_SIZE)) {
rc = -EINVAL;
- 

[PATCH 0/11] eCryptfs: Introduce persistent lower files for each eCryptfs inode

2007-09-17 Thread Michael Halcrow
Currently, eCryptfs directly accesses the lower inode address space,
doing things like grab_cache_page() on lower_inode->i_mapping. It
really should not do that. The main point of this patch set is to make
all I/O with the lower files go through vfs_read() and vfs_write()
instead.

In order to accomplish this, eCryptfs needs a way to call vfs_read()
and vfs_write() on the lower file when ecryptfs_aops->readpage() and
ecryptfs_aops->writepage() are called. I propose keeping a persistent
lower file around for each eCryptfs inode. This is the only lower file
that eCryptfs will open for any given eCryptfs inode; multiple
eCryptfs files may map to this one persistent lower file. When the
eCrypfs inode is destroyed, this persistent lower file is closed.

Consolidating all reads and writes to the lower file to a single
execution path simplifies the code. This should also make it easier to
port eCryptfs to use the asynchronous crypto API functions. Note that
this patch set also removes all direct calls to lower prepare_write()
and commite_write(), fixing an oops when mounted on NFS.

Mike
-
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to [EMAIL PROTECTED]
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/


[PATCH 0/11] eCryptfs: Introduce persistent lower files for each eCryptfs inode

2007-09-17 Thread Michael Halcrow
Currently, eCryptfs directly accesses the lower inode address space,
doing things like grab_cache_page() on lower_inode-i_mapping. It
really should not do that. The main point of this patch set is to make
all I/O with the lower files go through vfs_read() and vfs_write()
instead.

In order to accomplish this, eCryptfs needs a way to call vfs_read()
and vfs_write() on the lower file when ecryptfs_aops-readpage() and
ecryptfs_aops-writepage() are called. I propose keeping a persistent
lower file around for each eCryptfs inode. This is the only lower file
that eCryptfs will open for any given eCryptfs inode; multiple
eCryptfs files may map to this one persistent lower file. When the
eCrypfs inode is destroyed, this persistent lower file is closed.

Consolidating all reads and writes to the lower file to a single
execution path simplifies the code. This should also make it easier to
port eCryptfs to use the asynchronous crypto API functions. Note that
this patch set also removes all direct calls to lower prepare_write()
and commite_write(), fixing an oops when mounted on NFS.

Mike
-
To unsubscribe from this list: send the line unsubscribe linux-kernel in
the body of a message to [EMAIL PROTECTED]
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/


[PATCH 1/11] eCryptfs: Remove header_extent_size

2007-09-17 Thread Michael Halcrow
There is no point to keeping a separate header_extent_size and an
extent_size. The total size of the header can always be represented as
some multiple of the regular data extent size.

Signed-off-by: Michael Halcrow [EMAIL PROTECTED]
---
 fs/ecryptfs/crypto.c  |   40 
 fs/ecryptfs/ecryptfs_kernel.h |   39 +++
 fs/ecryptfs/inode.c   |7 ---
 fs/ecryptfs/mmap.c|2 +-
 4 files changed, 52 insertions(+), 36 deletions(-)

diff --git a/fs/ecryptfs/crypto.c b/fs/ecryptfs/crypto.c
index 8e9b36d..3dbb21a 100644
--- a/fs/ecryptfs/crypto.c
+++ b/fs/ecryptfs/crypto.c
@@ -366,8 +366,8 @@ ecryptfs_extent_to_lwr_pg_idx_and_offset(unsigned long 
*lower_page_idx,
int extents_per_page;
 
bytes_occupied_by_headers_at_front =
-   ( crypt_stat-header_extent_size
- * crypt_stat-num_header_extents_at_front );
+   (crypt_stat-extent_size
+* crypt_stat-num_header_extents_at_front);
extents_occupied_by_headers_at_front =
( bytes_occupied_by_headers_at_front
  / crypt_stat-extent_size );
@@ -376,8 +376,8 @@ ecryptfs_extent_to_lwr_pg_idx_and_offset(unsigned long 
*lower_page_idx,
(*lower_page_idx) = lower_extent_num / extents_per_page;
extent_offset = lower_extent_num % extents_per_page;
(*byte_offset) = extent_offset * crypt_stat-extent_size;
-   ecryptfs_printk(KERN_DEBUG,  * crypt_stat-header_extent_size = 
-   [%d]\n, crypt_stat-header_extent_size);
+   ecryptfs_printk(KERN_DEBUG,  * crypt_stat-extent_size = 
+   [%d]\n, crypt_stat-extent_size);
ecryptfs_printk(KERN_DEBUG,  * crypt_stat-
num_header_extents_at_front = [%d]\n,
crypt_stat-num_header_extents_at_front);
@@ -899,15 +899,17 @@ void ecryptfs_set_default_sizes(struct 
ecryptfs_crypt_stat *crypt_stat)
crypt_stat-extent_size = ECRYPTFS_DEFAULT_EXTENT_SIZE;
set_extent_mask_and_shift(crypt_stat);
crypt_stat-iv_bytes = ECRYPTFS_DEFAULT_IV_BYTES;
-   if (PAGE_CACHE_SIZE = ECRYPTFS_MINIMUM_HEADER_EXTENT_SIZE) {
-   crypt_stat-header_extent_size =
-   ECRYPTFS_MINIMUM_HEADER_EXTENT_SIZE;
-   } else
-   crypt_stat-header_extent_size = PAGE_CACHE_SIZE;
if (crypt_stat-flags  ECRYPTFS_METADATA_IN_XATTR)
crypt_stat-num_header_extents_at_front = 0;
-   else
-   crypt_stat-num_header_extents_at_front = 1;
+   else {
+   if (PAGE_CACHE_SIZE = ECRYPTFS_MINIMUM_HEADER_EXTENT_SIZE)
+   crypt_stat-num_header_extents_at_front =
+   (ECRYPTFS_MINIMUM_HEADER_EXTENT_SIZE
+/ crypt_stat-extent_size);
+   else
+   crypt_stat-num_header_extents_at_front =
+   (PAGE_CACHE_SIZE / crypt_stat-extent_size);
+   }
 }
 
 /**
@@ -1319,7 +1321,7 @@ ecryptfs_write_header_metadata(char *virt,
u32 header_extent_size;
u16 num_header_extents_at_front;
 
-   header_extent_size = (u32)crypt_stat-header_extent_size;
+   header_extent_size = (u32)crypt_stat-extent_size;
num_header_extents_at_front =
(u16)crypt_stat-num_header_extents_at_front;
header_extent_size = cpu_to_be32(header_extent_size);
@@ -1415,7 +1417,7 @@ ecryptfs_write_metadata_to_contents(struct 
ecryptfs_crypt_stat *crypt_stat,
set_fs(oldfs);
goto out;
}
-   header_pages = ((crypt_stat-header_extent_size
+   header_pages = ((crypt_stat-extent_size
 * crypt_stat-num_header_extents_at_front)
/ PAGE_CACHE_SIZE);
memset(page_virt, 0, PAGE_CACHE_SIZE);
@@ -1532,17 +1534,16 @@ static int parse_header_metadata(struct 
ecryptfs_crypt_stat *crypt_stat,
virt += 4;
memcpy(num_header_extents_at_front, virt, 2);
num_header_extents_at_front = be16_to_cpu(num_header_extents_at_front);
-   crypt_stat-header_extent_size = (int)header_extent_size;
crypt_stat-num_header_extents_at_front =
(int)num_header_extents_at_front;
-   (*bytes_read) = 6;
+   (*bytes_read) = (sizeof(u32) + sizeof(u16));
if ((validate_header_size == ECRYPTFS_VALIDATE_HEADER_SIZE)
-((crypt_stat-header_extent_size
+((crypt_stat-extent_size
 * crypt_stat-num_header_extents_at_front)
 ECRYPTFS_MINIMUM_HEADER_EXTENT_SIZE)) {
rc = -EINVAL;
-   ecryptfs_printk(KERN_WARNING, Invalid header extent size: 
-   [%d]\n, crypt_stat-header_extent_size);
+   printk(KERN_WARNING Invalid number of header extents: [%d]\n

[PATCH 2/11] eCryptfs: Remove assignments in if-statements

2007-09-17 Thread Michael Halcrow
Remove assignments in if-statements.

Signed-off-by: Michael Halcrow [EMAIL PROTECTED]
---
 fs/ecryptfs/crypto.c|   17 --
 fs/ecryptfs/file.c  |8 --
 fs/ecryptfs/inode.c |   35 ++
 fs/ecryptfs/keystore.c  |   55 +-
 fs/ecryptfs/main.c  |   28 ++-
 fs/ecryptfs/messaging.c |5 ++-
 fs/ecryptfs/mmap.c  |5 ++-
 7 files changed, 89 insertions(+), 64 deletions(-)

diff --git a/fs/ecryptfs/crypto.c b/fs/ecryptfs/crypto.c
index 3dbb21a..5d8a553 100644
--- a/fs/ecryptfs/crypto.c
+++ b/fs/ecryptfs/crypto.c
@@ -1277,8 +1277,8 @@ static int ecryptfs_read_header_region(char *data, struct 
dentry *dentry,
mm_segment_t oldfs;
int rc;
 
-   if ((rc = ecryptfs_open_lower_file(lower_file, dentry, mnt,
-  O_RDONLY))) {
+   rc = ecryptfs_open_lower_file(lower_file, dentry, mnt, O_RDONLY);
+   if (rc) {
printk(KERN_ERR
   Error opening lower_file to read header region\n);
goto out;
@@ -1289,7 +1289,8 @@ static int ecryptfs_read_header_region(char *data, struct 
dentry *dentry,
rc = lower_file-f_op-read(lower_file, (char __user *)data,
  ECRYPTFS_DEFAULT_EXTENT_SIZE, lower_file-f_pos);
set_fs(oldfs);
-   if ((rc = ecryptfs_close_lower_file(lower_file))) {
+   rc = ecryptfs_close_lower_file(lower_file);
+   if (rc) {
printk(KERN_ERR Error closing lower_file\n);
goto out;
}
@@ -1951,9 +1952,10 @@ ecryptfs_add_new_key_tfm(struct ecryptfs_key_tfm 
**key_tfm, char *cipher_name,
strncpy(tmp_tfm-cipher_name, cipher_name,
ECRYPTFS_MAX_CIPHER_NAME_SIZE);
tmp_tfm-key_size = key_size;
-   if ((rc = ecryptfs_process_key_cipher(tmp_tfm-key_tfm,
- tmp_tfm-cipher_name,
- tmp_tfm-key_size))) {
+   rc = ecryptfs_process_key_cipher(tmp_tfm-key_tfm,
+tmp_tfm-cipher_name,
+tmp_tfm-key_size);
+   if (rc) {
printk(KERN_ERR Error attempting to initialize key TFM 
   cipher with name = [%s]; rc = [%d]\n,
   tmp_tfm-cipher_name, rc);
@@ -1988,7 +1990,8 @@ int ecryptfs_get_tfm_and_mutex_for_cipher_name(struct 
crypto_blkcipher **tfm,
}
}
mutex_unlock(key_tfm_list_mutex);
-   if ((rc = ecryptfs_add_new_key_tfm(key_tfm, cipher_name, 0))) {
+   rc = ecryptfs_add_new_key_tfm(key_tfm, cipher_name, 0);
+   if (rc) {
printk(KERN_ERR Error adding new key_tfm to list; rc = [%d]\n,
   rc);
goto out;
diff --git a/fs/ecryptfs/file.c b/fs/ecryptfs/file.c
index 12ba7e3..59c846d 100644
--- a/fs/ecryptfs/file.c
+++ b/fs/ecryptfs/file.c
@@ -230,8 +230,9 @@ static int ecryptfs_open(struct inode *inode, struct file 
*file)
lower_flags = ~O_APPEND;
lower_mnt = ecryptfs_dentry_to_lower_mnt(ecryptfs_dentry);
/* Corresponding fput() in ecryptfs_release() */
-   if ((rc = ecryptfs_open_lower_file(lower_file, lower_dentry, lower_mnt,
-  lower_flags))) {
+   rc = ecryptfs_open_lower_file(lower_file, lower_dentry, lower_mnt,
+ lower_flags);
+   if (rc) {
ecryptfs_printk(KERN_ERR, Error opening lower file\n);
goto out_puts;
}
@@ -300,7 +301,8 @@ static int ecryptfs_release(struct inode *inode, struct 
file *file)
struct inode *lower_inode = ecryptfs_inode_to_lower(inode);
int rc;
 
-   if ((rc = ecryptfs_close_lower_file(lower_file))) {
+   rc = ecryptfs_close_lower_file(lower_file);
+   if (rc) {
printk(KERN_ERR Error closing lower_file\n);
goto out;
}
diff --git a/fs/ecryptfs/inode.c b/fs/ecryptfs/inode.c
index abac91c..d70f599 100644
--- a/fs/ecryptfs/inode.c
+++ b/fs/ecryptfs/inode.c
@@ -202,8 +202,9 @@ static int ecryptfs_initialize_file(struct dentry 
*ecryptfs_dentry)
lower_flags = ((O_CREAT | O_TRUNC)  O_ACCMODE) | O_RDWR;
lower_mnt = ecryptfs_dentry_to_lower_mnt(ecryptfs_dentry);
/* Corresponding fput() at end of this function */
-   if ((rc = ecryptfs_open_lower_file(lower_file, lower_dentry, lower_mnt,
-  lower_flags))) {
+   rc = ecryptfs_open_lower_file(lower_file, lower_dentry, lower_mnt,
+ lower_flags);
+   if (rc) {
ecryptfs_printk(KERN_ERR,
Error opening dentry; rc = [%i]\n, rc);
goto out;
@@ -229,7 +230,8 @@ static int ecryptfs_initialize_file(struct dentry

[PATCH 3/11] eCryptfs: read_write.c routines

2007-09-17 Thread Michael Halcrow
Add a set of functions through which all I/O to lower files is
consolidated. This patch adds a new inode_info reference to a
persistent lower file for each eCryptfs inode; another patch later in
this series will set that up. This persistent lower file is what the
read_write.c functions use to call vfs_read() and vfs_write() on the
lower filesystem, so even when reads and writes come in through
aops-readpage and aops-writepage, we can satisfy them without
resorting to direct access to the lower inode's address space.
Several function declarations are going to be changing with this
patchset. For now, in order to keep from breaking the build, I am
putting dummy parameters in for those functions.

Signed-off-by: Michael Halcrow [EMAIL PROTECTED]
---
 fs/ecryptfs/Makefile  |2 +-
 fs/ecryptfs/ecryptfs_kernel.h |   18 ++
 fs/ecryptfs/mmap.c|2 +-
 fs/ecryptfs/read_write.c  |  359 +
 4 files changed, 379 insertions(+), 2 deletions(-)
 create mode 100644 fs/ecryptfs/read_write.c

diff --git a/fs/ecryptfs/Makefile b/fs/ecryptfs/Makefile
index 1f11072..7688570 100644
--- a/fs/ecryptfs/Makefile
+++ b/fs/ecryptfs/Makefile
@@ -4,4 +4,4 @@
 
 obj-$(CONFIG_ECRYPT_FS) += ecryptfs.o
 
-ecryptfs-objs := dentry.o file.o inode.o main.o super.o mmap.o crypto.o 
keystore.o messaging.o netlink.o debug.o
+ecryptfs-objs := dentry.o file.o inode.o main.o super.o mmap.o read_write.o 
crypto.o keystore.o messaging.o netlink.o debug.o
diff --git a/fs/ecryptfs/ecryptfs_kernel.h b/fs/ecryptfs/ecryptfs_kernel.h
index a618ab7..e6a68a8 100644
--- a/fs/ecryptfs/ecryptfs_kernel.h
+++ b/fs/ecryptfs/ecryptfs_kernel.h
@@ -260,6 +260,8 @@ struct ecryptfs_crypt_stat {
 struct ecryptfs_inode_info {
struct inode vfs_inode;
struct inode *wii_inode;
+   struct file *lower_file;
+   struct mutex lower_file_mutex;
struct ecryptfs_crypt_stat crypt_stat;
 };
 
@@ -653,5 +655,21 @@ int ecryptfs_keyring_auth_tok_for_sig(struct key 
**auth_tok_key,
  char *sig);
 int ecryptfs_write_zeros(struct file *file, pgoff_t index, int start,
 int num_zeros);
+int ecryptfs_write_lower(struct inode *ecryptfs_inode, char *data,
+loff_t offset, size_t size);
+int ecryptfs_write_lower_page_segment(struct inode *ecryptfs_inode,
+ struct page *page_for_lower,
+ size_t offset_in_page, size_t size);
+int ecryptfs_write(struct file *ecryptfs_file, char *data, loff_t offset,
+  size_t size);
+int ecryptfs_read_lower(char *data, loff_t offset, size_t size,
+   struct inode *ecryptfs_inode);
+int ecryptfs_read_lower_page_segment(struct page *page_for_ecryptfs,
+pgoff_t page_index,
+size_t offset_in_page, size_t size,
+struct inode *ecryptfs_inode);
+int ecryptfs_read(char *data, loff_t offset, size_t size,
+ struct file *ecryptfs_file);
+struct page *ecryptfs_get1page(struct file *file, loff_t index);
 
 #endif /* #ifndef ECRYPTFS_KERNEL_H */
diff --git a/fs/ecryptfs/mmap.c b/fs/ecryptfs/mmap.c
index 307f7ee..0c53320 100644
--- a/fs/ecryptfs/mmap.c
+++ b/fs/ecryptfs/mmap.c
@@ -44,7 +44,7 @@ struct kmem_cache *ecryptfs_lower_page_cache;
  * Returns unlocked and up-to-date page (if ok), with increased
  * refcnt.
  */
-static struct page *ecryptfs_get1page(struct file *file, int index)
+struct page *ecryptfs_get1page(struct file *file, loff_t index)
 {
struct dentry *dentry;
struct inode *inode;
diff --git a/fs/ecryptfs/read_write.c b/fs/ecryptfs/read_write.c
new file mode 100644
index 000..e59c94a
--- /dev/null
+++ b/fs/ecryptfs/read_write.c
@@ -0,0 +1,359 @@
+/**
+ * eCryptfs: Linux filesystem encryption layer
+ *
+ * Copyright (C) 2007 International Business Machines Corp.
+ *   Author(s): Michael A. Halcrow [EMAIL PROTECTED]
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of the
+ * License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
+ * 02111-1307, USA.
+ */
+
+#include linux/fs.h
+#include linux/pagemap.h
+#include ecryptfs_kernel.h
+
+/**
+ * ecryptfs_write_lower
+ * @ecryptfs_inode: The eCryptfs inode
+ * @data: Data to write
+ * @offset: Byte offset

[PATCH 4/11] eCryptfs: Replace encrypt, decrypt, and inode size write

2007-09-17 Thread Michael Halcrow
Replace page encryption and decryption routines and inode size write
routine with versions that utilize the read_write.c functions.

Signed-off-by: Michael Halcrow [EMAIL PROTECTED]
---
 fs/ecryptfs/crypto.c  |  427 ++--
 fs/ecryptfs/ecryptfs_kernel.h |   14 +-
 fs/ecryptfs/inode.c   |   12 +-
 fs/ecryptfs/mmap.c|  131 -
 fs/ecryptfs/read_write.c  |   12 +-
 5 files changed, 290 insertions(+), 306 deletions(-)

diff --git a/fs/ecryptfs/crypto.c b/fs/ecryptfs/crypto.c
index 5d8a553..b829d3c 100644
--- a/fs/ecryptfs/crypto.c
+++ b/fs/ecryptfs/crypto.c
@@ -467,8 +467,91 @@ out:
 }
 
 /**
+ * ecryptfs_lower_offset_for_extent
+ *
+ * Convert an eCryptfs page index into a lower byte offset
+ */
+void ecryptfs_lower_offset_for_extent(loff_t *offset, loff_t extent_num,
+ struct ecryptfs_crypt_stat *crypt_stat)
+{
+   (*offset) = ((crypt_stat-extent_size
+ * crypt_stat-num_header_extents_at_front)
++ (crypt_stat-extent_size * extent_num));
+}
+
+/**
+ * ecryptfs_encrypt_extent
+ * @enc_extent_page: Allocated page into which to encrypt the data in
+ *   @page
+ * @crypt_stat: crypt_stat containing cryptographic context for the
+ *  encryption operation
+ * @page: Page containing plaintext data extent to encrypt
+ * @extent_offset: Page extent offset for use in generating IV
+ *
+ * Encrypts one extent of data.
+ *
+ * Return zero on success; non-zero otherwise
+ */
+static int ecryptfs_encrypt_extent(struct page *enc_extent_page,
+  struct ecryptfs_crypt_stat *crypt_stat,
+  struct page *page,
+  unsigned long extent_offset)
+{
+   unsigned long extent_base;
+   char extent_iv[ECRYPTFS_MAX_IV_BYTES];
+   int rc;
+
+   extent_base = (page-index
+  * (PAGE_CACHE_SIZE / crypt_stat-extent_size));
+   rc = ecryptfs_derive_iv(extent_iv, crypt_stat,
+   (extent_base + extent_offset));
+   if (rc) {
+   ecryptfs_printk(KERN_ERR, Error attempting to 
+   derive IV for extent [0x%.16x]; 
+   rc = [%d]\n, (extent_base + extent_offset),
+   rc);
+   goto out;
+   }
+   if (unlikely(ecryptfs_verbosity  0)) {
+   ecryptfs_printk(KERN_DEBUG, Encrypting extent 
+   with iv:\n);
+   ecryptfs_dump_hex(extent_iv, crypt_stat-iv_bytes);
+   ecryptfs_printk(KERN_DEBUG, First 8 bytes before 
+   encryption:\n);
+   ecryptfs_dump_hex((char *)
+ (page_address(page)
+  + (extent_offset * crypt_stat-extent_size)),
+ 8);
+   }
+   rc = ecryptfs_encrypt_page_offset(crypt_stat, enc_extent_page, 0,
+ page, (extent_offset
+* crypt_stat-extent_size),
+ crypt_stat-extent_size, extent_iv);
+   if (rc  0) {
+   printk(KERN_ERR %s: Error attempting to encrypt page with 
+  page-index = [%ld], extent_offset = [%ld]; 
+  rc = [%d]\n, __FUNCTION__, page-index, extent_offset,
+  rc);
+   goto out;
+   }
+   rc = 0;
+   if (unlikely(ecryptfs_verbosity  0)) {
+   ecryptfs_printk(KERN_DEBUG, Encrypt extent [0x%.16x]; 
+   rc = [%d]\n, (extent_base + extent_offset),
+   rc);
+   ecryptfs_printk(KERN_DEBUG, First 8 bytes after 
+   encryption:\n);
+   ecryptfs_dump_hex((char *)(page_address(enc_extent_page)), 8);
+   }
+out:
+   return rc;
+}
+
+/**
  * ecryptfs_encrypt_page
- * @ctx: The context of the page
+ * @page: Page mapped from the eCryptfs inode for the file; contains
+ *decrypted content that needs to be encrypted (to a temporary
+ *page; not in place) and written out to the lower file
  *
  * Encrypt an eCryptfs page. This is done on a per-extent basis. Note
  * that eCryptfs pages may straddle the lower pages -- for instance,
@@ -478,128 +561,121 @@ out:
  * file, 24K of page 0 of the lower file will be read and decrypted,
  * and then 8K of page 1 of the lower file will be read and decrypted.
  *
- * The actual operations performed on each page depends on the
- * contents of the ecryptfs_page_crypt_context struct.
- *
  * Returns zero on success; negative on error
  */
-int ecryptfs_encrypt_page(struct ecryptfs_page_crypt_context *ctx)
+int ecryptfs_encrypt_page(struct page *page)
 {
-   char extent_iv

[PATCH 5/11] eCryptfs: Set up and destroy persistent lower file

2007-09-17 Thread Michael Halcrow
This patch sets up and destroys the persistent lower file for each
eCryptfs inode.

Signed-off-by: Michael Halcrow [EMAIL PROTECTED]
---
 fs/ecryptfs/inode.c |   23 +++---
 fs/ecryptfs/main.c  |   65 +++
 fs/ecryptfs/super.c |   22 +++--
 3 files changed, 103 insertions(+), 7 deletions(-)

diff --git a/fs/ecryptfs/inode.c b/fs/ecryptfs/inode.c
index 7192a81..c746b5d 100644
--- a/fs/ecryptfs/inode.c
+++ b/fs/ecryptfs/inode.c
@@ -119,10 +119,23 @@ ecryptfs_do_create(struct inode *directory_inode,
}
rc = ecryptfs_create_underlying_file(lower_dir_dentry-d_inode,
 ecryptfs_dentry, mode, nd);
-   if (unlikely(rc)) {
-   ecryptfs_printk(KERN_ERR,
-   Failure to create underlying file\n);
-   goto out_lock;
+   if (rc) {
+   struct inode *ecryptfs_inode = ecryptfs_dentry-d_inode;
+   struct ecryptfs_inode_info *inode_info =
+   ecryptfs_inode_to_private(ecryptfs_inode);
+
+   printk(KERN_WARNING %s: Error creating underlying file; 
+  rc = [%d]; checking for existing\n, __FUNCTION__, rc);
+   if (inode_info) {
+   mutex_lock(inode_info-lower_file_mutex);
+   if (!inode_info-lower_file) {
+   mutex_unlock(inode_info-lower_file_mutex);
+   printk(KERN_ERR %s: Failure to set underlying 
+  file; rc = [%d]\n, __FUNCTION__, rc);
+   goto out_lock;
+   }
+   mutex_unlock(inode_info-lower_file_mutex);
+   }
}
rc = ecryptfs_interpose(lower_dentry, ecryptfs_dentry,
directory_inode-i_sb, 0);
@@ -252,6 +265,8 @@ ecryptfs_create(struct inode *directory_inode, struct 
dentry *ecryptfs_dentry,
 {
int rc;
 
+   /* ecryptfs_do_create() calls ecryptfs_interpose(), which opens
+* the crypt_stat-lower_file (persistent file) */
rc = ecryptfs_do_create(directory_inode, ecryptfs_dentry, mode, nd);
if (unlikely(rc)) {
ecryptfs_printk(KERN_WARNING, Failed to create file in
diff --git a/fs/ecryptfs/main.c b/fs/ecryptfs/main.c
index 967bad0..3e324f8 100644
--- a/fs/ecryptfs/main.c
+++ b/fs/ecryptfs/main.c
@@ -98,6 +98,64 @@ void __ecryptfs_printk(const char *fmt, ...)
 }
 
 /**
+ * ecryptfs_init_persistent_file
+ * @ecryptfs_dentry: Fully initialized eCryptfs dentry object, with
+ *   the lower dentry and the lower mount set
+ *
+ * eCryptfs only ever keeps a single open file for every lower
+ * inode. All I/O operations to the lower inode occur through that
+ * file. When the first eCryptfs dentry that interposes with the first
+ * lower dentry for that inode is created, this function creates the
+ * persistent file struct and associates it with the eCryptfs
+ * inode. When the eCryptfs inode is destroyed, the file is closed.
+ *
+ * The persistent file will be opened with read/write permissions, if
+ * possible. Otherwise, it is opened read-only.
+ *
+ * This function does nothing if a lower persistent file is already
+ * associated with the eCryptfs inode.
+ *
+ * Returns zero on success; non-zero otherwise
+ */
+int ecryptfs_init_persistent_file(struct dentry *ecryptfs_dentry)
+{
+   struct ecryptfs_inode_info *inode_info =
+   ecryptfs_inode_to_private(ecryptfs_dentry-d_inode);
+   int rc = 0;
+
+   mutex_lock(inode_info-lower_file_mutex);
+   if (!inode_info-lower_file) {
+   struct dentry *lower_dentry;
+   struct vfsmount *lower_mnt =
+   ecryptfs_dentry_to_lower_mnt(ecryptfs_dentry);
+
+   lower_dentry = ecryptfs_dentry_to_lower(ecryptfs_dentry);
+   /* Corresponding dput() and mntput() are done when the
+* persistent file is fput() when the eCryptfs inode
+* is destroyed. */
+   dget(lower_dentry);
+   mntget(lower_mnt);
+   inode_info-lower_file = dentry_open(lower_dentry,
+lower_mnt,
+(O_RDWR | O_LARGEFILE));
+   if (IS_ERR(inode_info-lower_file))
+   inode_info-lower_file = dentry_open(lower_dentry,
+lower_mnt,
+(O_RDONLY
+ | O_LARGEFILE));
+   if (IS_ERR(inode_info-lower_file)) {
+   printk(KERN_ERR Error opening lower persistent file 
+  for lower_dentry [0x%p] and lower_mnt [0x%p]\n

[PATCH 6/11] eCryptfs: Update metadata read/write functions

2007-09-17 Thread Michael Halcrow
Update the metadata read/write functions and grow_file() to use the
read_write.c routines. Do not open another lower file; use the
persistent lower file instead. Provide a separate function for
crypto.c::ecryptfs_read_xattr_region() to get to the lower xattr
without having to go through the eCryptfs getxattr.

Signed-off-by: Michael Halcrow [EMAIL PROTECTED]
---
 fs/ecryptfs/crypto.c  |  126 +++--
 fs/ecryptfs/ecryptfs_kernel.h |   15 +++--
 fs/ecryptfs/file.c|2 +-
 fs/ecryptfs/inode.c   |  101 +++--
 fs/ecryptfs/mmap.c|2 +-
 5 files changed, 113 insertions(+), 133 deletions(-)

diff --git a/fs/ecryptfs/crypto.c b/fs/ecryptfs/crypto.c
index d6a0680..6b4d310 100644
--- a/fs/ecryptfs/crypto.c
+++ b/fs/ecryptfs/crypto.c
@@ -1344,21 +1344,28 @@ out:
return rc;
 }
 
-int ecryptfs_read_and_validate_header_region(char *data, struct dentry *dentry,
-struct vfsmount *mnt)
+int ecryptfs_read_and_validate_header_region(char *data,
+struct inode *ecryptfs_inode)
 {
+   struct ecryptfs_crypt_stat *crypt_stat =
+   (ecryptfs_inode_to_private(ecryptfs_inode)-crypt_stat);
int rc;
 
-   rc = ecryptfs_read_header_region(data, dentry, mnt);
-   if (rc)
+   rc = ecryptfs_read_lower(data, 0, crypt_stat-extent_size,
+ecryptfs_inode);
+   if (rc) {
+   printk(KERN_ERR %s: Error reading header region; rc = [%d]\n,
+  __FUNCTION__, rc);
goto out;
-   if (!contains_ecryptfs_marker(data + ECRYPTFS_FILE_SIZE_BYTES))
+   }
+   if (!contains_ecryptfs_marker(data + ECRYPTFS_FILE_SIZE_BYTES)) {
rc = -EINVAL;
+   ecryptfs_printk(KERN_DEBUG, Valid marker not found\n);
+   }
 out:
return rc;
 }
 
-
 void
 ecryptfs_write_header_metadata(char *virt,
   struct ecryptfs_crypt_stat *crypt_stat,
@@ -1443,24 +1450,18 @@ static int ecryptfs_write_headers_virt(char *page_virt, 
size_t *size,
 
 static int
 ecryptfs_write_metadata_to_contents(struct ecryptfs_crypt_stat *crypt_stat,
-   struct file *lower_file, char *page_virt)
+   struct dentry *ecryptfs_dentry,
+   char *page_virt)
 {
-   mm_segment_t oldfs;
int current_header_page;
int header_pages;
-   ssize_t size;
-   int rc = 0;
+   int rc;
 
-   lower_file-f_pos = 0;
-   oldfs = get_fs();
-   set_fs(get_ds());
-   size = vfs_write(lower_file, (char __user *)page_virt, PAGE_CACHE_SIZE,
-lower_file-f_pos);
-   if (size  0) {
-   rc = (int)size;
-   printk(KERN_ERR Error attempting to write lower page; 
-  rc = [%d]\n, rc);
-   set_fs(oldfs);
+   if ((rc = ecryptfs_write_lower(ecryptfs_dentry-d_inode, page_virt,
+  0, PAGE_CACHE_SIZE))) {
+   printk(KERN_ERR %s: Error attempting to write header 
+  information to lower file; rc = [%d]\n, __FUNCTION__,
+  rc);
goto out;
}
header_pages = ((crypt_stat-extent_size
@@ -1469,18 +1470,19 @@ ecryptfs_write_metadata_to_contents(struct 
ecryptfs_crypt_stat *crypt_stat,
memset(page_virt, 0, PAGE_CACHE_SIZE);
current_header_page = 1;
while (current_header_page  header_pages) {
-   size = vfs_write(lower_file, (char __user *)page_virt,
-PAGE_CACHE_SIZE, lower_file-f_pos);
-   if (size  0) {
-   rc = (int)size;
-   printk(KERN_ERR Error attempting to write lower page; 
-  rc = [%d]\n, rc);
-   set_fs(oldfs);
+   loff_t offset;
+
+   offset = (current_header_page  PAGE_CACHE_SHIFT);
+   if ((rc = ecryptfs_write_lower(ecryptfs_dentry-d_inode,
+  page_virt, offset,
+  PAGE_CACHE_SIZE))) {
+   printk(KERN_ERR %s: Error attempting to write header 
+  information to lower file; rc = [%d]\n,
+  __FUNCTION__, rc);
goto out;
}
current_header_page++;
}
-   set_fs(oldfs);
 out:
return rc;
 }
@@ -1500,7 +1502,6 @@ ecryptfs_write_metadata_to_xattr(struct dentry 
*ecryptfs_dentry,
 /**
  * ecryptfs_write_metadata
  * @ecryptfs_dentry: The eCryptfs dentry
- * @lower_file: The lower file struct, which was returned from dentry_open
  *
  * Write the file headers out.  This will likely involve

[PATCH 7/11] eCryptfs: Make open, truncate, and setattr use persistent file

2007-09-17 Thread Michael Halcrow
Rather than open a new lower file for every eCryptfs file that is
opened, truncated, or setattr'd, instead use the existing lower
persistent file for the eCryptfs inode. Change truncate to use
read_write.c functions. Change ecryptfs_getxattr() to use the common
ecryptfs_getxattr_lower() function.

Signed-off-by: Michael Halcrow [EMAIL PROTECTED]
---
 fs/ecryptfs/crypto.c |2 +-
 fs/ecryptfs/file.c   |   50 --
 fs/ecryptfs/inode.c  |  113 +++---
 3 files changed, 44 insertions(+), 121 deletions(-)

diff --git a/fs/ecryptfs/crypto.c b/fs/ecryptfs/crypto.c
index 6b4d310..b3014d7 100644
--- a/fs/ecryptfs/crypto.c
+++ b/fs/ecryptfs/crypto.c
@@ -1674,7 +1674,7 @@ out:
 /**
  * ecryptfs_read_xattr_region
  * @page_virt: The vitual address into which to read the xattr data
- * @ecryptfs_dentry: The eCryptfs dentry
+ * @ecryptfs_inode: The eCryptfs inode
  *
  * Attempts to read the crypto metadata from the extended attribute
  * region of the lower file.
diff --git a/fs/ecryptfs/file.c b/fs/ecryptfs/file.c
index df70bfa..95be9a9 100644
--- a/fs/ecryptfs/file.c
+++ b/fs/ecryptfs/file.c
@@ -187,11 +187,7 @@ static int ecryptfs_open(struct inode *inode, struct file 
*file)
/* Private value of ecryptfs_dentry allocated in
 * ecryptfs_lookup() */
struct dentry *lower_dentry = ecryptfs_dentry_to_lower(ecryptfs_dentry);
-   struct inode *lower_inode = NULL;
-   struct file *lower_file = NULL;
-   struct vfsmount *lower_mnt;
struct ecryptfs_file_info *file_info;
-   int lower_flags;
 
mount_crypt_stat = ecryptfs_superblock_to_private(
ecryptfs_dentry-d_sb)-mount_crypt_stat;
@@ -219,26 +215,12 @@ static int ecryptfs_open(struct inode *inode, struct file 
*file)
if (!(crypt_stat-flags  ECRYPTFS_POLICY_APPLIED)) {
ecryptfs_printk(KERN_DEBUG, Setting flags for stat...\n);
/* Policy code enabled in future release */
-   crypt_stat-flags |= ECRYPTFS_POLICY_APPLIED;
-   crypt_stat-flags |= ECRYPTFS_ENCRYPTED;
+   crypt_stat-flags |= (ECRYPTFS_POLICY_APPLIED
+ | ECRYPTFS_ENCRYPTED);
}
mutex_unlock(crypt_stat-cs_mutex);
-   lower_flags = file-f_flags;
-   if ((lower_flags  O_ACCMODE) == O_WRONLY)
-   lower_flags = (lower_flags  O_ACCMODE) | O_RDWR;
-   if (file-f_flags  O_APPEND)
-   lower_flags = ~O_APPEND;
-   lower_mnt = ecryptfs_dentry_to_lower_mnt(ecryptfs_dentry);
-   /* Corresponding fput() in ecryptfs_release() */
-   rc = ecryptfs_open_lower_file(lower_file, lower_dentry, lower_mnt,
- lower_flags);
-   if (rc) {
-   ecryptfs_printk(KERN_ERR, Error opening lower file\n);
-   goto out_puts;
-   }
-   ecryptfs_set_file_lower(file, lower_file);
-   /* Isn't this check the same as the one in lookup? */
-   lower_inode = lower_dentry-d_inode;
+   ecryptfs_set_file_lower(
+   file, ecryptfs_inode_to_private(inode)-lower_file);
if (S_ISDIR(ecryptfs_dentry-d_inode-i_mode)) {
ecryptfs_printk(KERN_DEBUG, This is a directory\n);
crypt_stat-flags = ~(ECRYPTFS_ENCRYPTED);
@@ -260,7 +242,7 @@ static int ecryptfs_open(struct inode *inode, struct file 
*file)
   and plaintext passthrough mode is not 
   enabled; returning -EIO\n);
mutex_unlock(crypt_stat-cs_mutex);
-   goto out_puts;
+   goto out_free;
}
rc = 0;
crypt_stat-flags = ~(ECRYPTFS_ENCRYPTED);
@@ -272,11 +254,8 @@ static int ecryptfs_open(struct inode *inode, struct file 
*file)
ecryptfs_printk(KERN_DEBUG, inode w/ addr = [0x%p], i_ino = [0x%.16x] 
size: [0x%.16x]\n, inode, inode-i_ino,
i_size_read(inode));
-   ecryptfs_set_file_lower(file, lower_file);
goto out;
-out_puts:
-   mntput(lower_mnt);
-   dput(lower_dentry);
+out_free:
kmem_cache_free(ecryptfs_file_info_cache,
ecryptfs_file_to_private(file));
 out:
@@ -296,20 +275,9 @@ static int ecryptfs_flush(struct file *file, fl_owner_t td)
 
 static int ecryptfs_release(struct inode *inode, struct file *file)
 {
-   struct file *lower_file = ecryptfs_file_to_lower(file);
-   struct ecryptfs_file_info *file_info = ecryptfs_file_to_private(file);
-   struct inode *lower_inode = ecryptfs_inode_to_lower(inode);
-   int rc;
-
-   rc = ecryptfs_close_lower_file(lower_file);
-   if (rc) {
-   printk(KERN_ERR Error closing lower_file\n);
-   goto out;
-   }
-   inode-i_blocks = lower_inode-i_blocks

[PATCH 8/11] eCryptfs: Convert mmap functions to use persistent file

2007-09-17 Thread Michael Halcrow
Convert readpage, prepare_write, and commit_write to use read_write.c
routines. Remove sync_page; I cannot think of a good reason for
implementing that in eCryptfs.

Signed-off-by: Michael Halcrow [EMAIL PROTECTED]
---
 fs/ecryptfs/mmap.c |  199 +++-
 1 files changed, 103 insertions(+), 96 deletions(-)

diff --git a/fs/ecryptfs/mmap.c b/fs/ecryptfs/mmap.c
index 60e635e..dd68dd3 100644
--- a/fs/ecryptfs/mmap.c
+++ b/fs/ecryptfs/mmap.c
@@ -267,9 +267,78 @@ static void set_header_info(char *page_virt,
 }
 
 /**
+ * ecryptfs_copy_up_encrypted_with_header
+ * @page: Sort of a ``virtual'' representation of the encrypted lower
+ *file. The actual lower file does not have the metadata in
+ *the header.
+ * @crypt_stat: The eCryptfs inode's cryptographic context
+ *
+ * The ``view'' is the version of the file that userspace winds up
+ * seeing, with the header information inserted.
+ */
+static int
+ecryptfs_copy_up_encrypted_with_header(struct page *page,
+  struct ecryptfs_crypt_stat *crypt_stat)
+{
+   loff_t extent_num_in_page = 0;
+   loff_t num_extents_per_page = (PAGE_CACHE_SIZE
+  / crypt_stat-extent_size);
+   int rc = 0;
+
+   while (extent_num_in_page  num_extents_per_page) {
+   loff_t view_extent_num = ((page-index * num_extents_per_page)
+ + extent_num_in_page);
+
+   if (view_extent_num  crypt_stat-num_header_extents_at_front) {
+   /* This is a header extent */
+   char *page_virt;
+
+   page_virt = kmap_atomic(page, KM_USER0);
+   memset(page_virt, 0, PAGE_CACHE_SIZE);
+   /* TODO: Support more than one header extent */
+   if (view_extent_num == 0) {
+   rc = ecryptfs_read_xattr_region(
+   page_virt, page-mapping-host);
+   set_header_info(page_virt, crypt_stat);
+   }
+   kunmap_atomic(page_virt, KM_USER0);
+   flush_dcache_page(page);
+   if (rc) {
+   ClearPageUptodate(page);
+   printk(KERN_ERR %s: Error reading xattr 
+  region; rc = [%d]\n, __FUNCTION__, rc);
+   goto out;
+   }
+   SetPageUptodate(page);
+   } else {
+   /* This is an encrypted data extent */
+   loff_t lower_offset =
+   ((view_extent_num -
+ crypt_stat-num_header_extents_at_front)
+* crypt_stat-extent_size);
+
+   rc = ecryptfs_read_lower_page_segment(
+   page, (lower_offset  PAGE_CACHE_SHIFT),
+   (lower_offset  ~PAGE_CACHE_MASK),
+   crypt_stat-extent_size, page-mapping-host);
+   if (rc) {
+   printk(KERN_ERR %s: Error attempting to read 
+  extent at offset [%lld] in the lower 
+  file; rc = [%d]\n, __FUNCTION__,
+  lower_offset, rc);
+   goto out;
+   }
+   }
+   extent_num_in_page++;
+   }
+out:
+   return rc;
+}
+
+/**
  * ecryptfs_readpage
- * @file: This is an ecryptfs file
- * @page: ecryptfs associated page to stick the read data into
+ * @file: An eCryptfs file
+ * @page: Page from eCryptfs inode mapping into which to stick the read data
  *
  * Read in a page, decrypting if necessary.
  *
@@ -277,59 +346,35 @@ static void set_header_info(char *page_virt,
  */
 static int ecryptfs_readpage(struct file *file, struct page *page)
 {
+   struct ecryptfs_crypt_stat *crypt_stat =
+   
ecryptfs_inode_to_private(file-f_path.dentry-d_inode)-crypt_stat;
int rc = 0;
-   struct ecryptfs_crypt_stat *crypt_stat;
 
-   BUG_ON(!(file  file-f_path.dentry  file-f_path.dentry-d_inode));
-   crypt_stat = ecryptfs_inode_to_private(file-f_path.dentry-d_inode)
-   -crypt_stat;
if (!crypt_stat
|| !(crypt_stat-flags  ECRYPTFS_ENCRYPTED)
|| (crypt_stat-flags  ECRYPTFS_NEW_FILE)) {
ecryptfs_printk(KERN_DEBUG,
Passing through unencrypted page\n);
-   rc = ecryptfs_do_readpage(file, page, page-index);
-   if (rc) {
-   ecryptfs_printk(KERN_ERR, Error reading page; rc = 
-   [%d]\n, rc

[PATCH 9/11] eCryptfs: Initialize persistent lower file on inode create

2007-09-17 Thread Michael Halcrow
Initialize persistent lower file on inode create.

Signed-off-by: Michael Halcrow [EMAIL PROTECTED]
---
 fs/ecryptfs/super.c |   13 +++--
 1 files changed, 7 insertions(+), 6 deletions(-)

diff --git a/fs/ecryptfs/super.c b/fs/ecryptfs/super.c
index b97e210..f8cdab2 100644
--- a/fs/ecryptfs/super.c
+++ b/fs/ecryptfs/super.c
@@ -47,15 +47,16 @@ struct kmem_cache *ecryptfs_inode_info_cache;
  */
 static struct inode *ecryptfs_alloc_inode(struct super_block *sb)
 {
-   struct ecryptfs_inode_info *ecryptfs_inode;
+   struct ecryptfs_inode_info *inode_info;
struct inode *inode = NULL;
 
-   ecryptfs_inode = kmem_cache_alloc(ecryptfs_inode_info_cache,
- GFP_KERNEL);
-   if (unlikely(!ecryptfs_inode))
+   inode_info = kmem_cache_alloc(ecryptfs_inode_info_cache, GFP_KERNEL);
+   if (unlikely(!inode_info))
goto out;
-   ecryptfs_init_crypt_stat(ecryptfs_inode-crypt_stat);
-   inode = ecryptfs_inode-vfs_inode;
+   ecryptfs_init_crypt_stat(inode_info-crypt_stat);
+   mutex_init(inode_info-lower_file_mutex);
+   inode_info-lower_file = NULL;
+   inode = inode_info-vfs_inode;
 out:
return inode;
 }
-- 
1.5.1.6

-
To unsubscribe from this list: send the line unsubscribe linux-kernel in
the body of a message to [EMAIL PROTECTED]
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/


[PATCH 10/11] eCryptfs: Remove unused functions and kmem_cache

2007-09-17 Thread Michael Halcrow
The switch to read_write.c routines and the persistent file make a
number of functions unnecessary. This patch removes them.

Signed-off-by: Michael Halcrow [EMAIL PROTECTED]
---
 fs/ecryptfs/crypto.c  |  150 --
 fs/ecryptfs/ecryptfs_kernel.h |   21 +---
 fs/ecryptfs/file.c|   28 
 fs/ecryptfs/main.c|5 -
 fs/ecryptfs/mmap.c|  336 -
 5 files changed, 1 insertions(+), 539 deletions(-)

diff --git a/fs/ecryptfs/crypto.c b/fs/ecryptfs/crypto.c
index b3014d7..3b3cf27 100644
--- a/fs/ecryptfs/crypto.c
+++ b/fs/ecryptfs/crypto.c
@@ -353,119 +353,6 @@ out:
return rc;
 }
 
-static void
-ecryptfs_extent_to_lwr_pg_idx_and_offset(unsigned long *lower_page_idx,
-int *byte_offset,
-struct ecryptfs_crypt_stat *crypt_stat,
-unsigned long extent_num)
-{
-   unsigned long lower_extent_num;
-   int extents_occupied_by_headers_at_front;
-   int bytes_occupied_by_headers_at_front;
-   int extent_offset;
-   int extents_per_page;
-
-   bytes_occupied_by_headers_at_front =
-   (crypt_stat-extent_size
-* crypt_stat-num_header_extents_at_front);
-   extents_occupied_by_headers_at_front =
-   ( bytes_occupied_by_headers_at_front
- / crypt_stat-extent_size );
-   lower_extent_num = extents_occupied_by_headers_at_front + extent_num;
-   extents_per_page = PAGE_CACHE_SIZE / crypt_stat-extent_size;
-   (*lower_page_idx) = lower_extent_num / extents_per_page;
-   extent_offset = lower_extent_num % extents_per_page;
-   (*byte_offset) = extent_offset * crypt_stat-extent_size;
-   ecryptfs_printk(KERN_DEBUG,  * crypt_stat-extent_size = 
-   [%d]\n, crypt_stat-extent_size);
-   ecryptfs_printk(KERN_DEBUG,  * crypt_stat-
-   num_header_extents_at_front = [%d]\n,
-   crypt_stat-num_header_extents_at_front);
-   ecryptfs_printk(KERN_DEBUG,  * extents_occupied_by_headers_at_
-   front = [%d]\n, extents_occupied_by_headers_at_front);
-   ecryptfs_printk(KERN_DEBUG,  * lower_extent_num = [0x%.16x]\n,
-   lower_extent_num);
-   ecryptfs_printk(KERN_DEBUG,  * extents_per_page = [%d]\n,
-   extents_per_page);
-   ecryptfs_printk(KERN_DEBUG,  * (*lower_page_idx) = [0x%.16x]\n,
-   (*lower_page_idx));
-   ecryptfs_printk(KERN_DEBUG,  * extent_offset = [%d]\n,
-   extent_offset);
-   ecryptfs_printk(KERN_DEBUG,  * (*byte_offset) = [%d]\n,
-   (*byte_offset));
-}
-
-static int ecryptfs_write_out_page(struct ecryptfs_page_crypt_context *ctx,
-  struct page *lower_page,
-  struct inode *lower_inode,
-  int byte_offset_in_page, int bytes_to_write)
-{
-   int rc = 0;
-
-   if (ctx-mode == ECRYPTFS_PREPARE_COMMIT_MODE) {
-   rc = ecryptfs_commit_lower_page(lower_page, lower_inode,
-   ctx-param.lower_file,
-   byte_offset_in_page,
-   bytes_to_write);
-   if (rc) {
-   ecryptfs_printk(KERN_ERR, Error calling lower 
-   commit; rc = [%d]\n, rc);
-   goto out;
-   }
-   } else {
-   rc = ecryptfs_writepage_and_release_lower_page(lower_page,
-  lower_inode,
-  ctx-param.wbc);
-   if (rc) {
-   ecryptfs_printk(KERN_ERR, Error calling lower 
-   writepage(); rc = [%d]\n, rc);
-   goto out;
-   }
-   }
-out:
-   return rc;
-}
-
-static int ecryptfs_read_in_page(struct ecryptfs_page_crypt_context *ctx,
-struct page **lower_page,
-struct inode *lower_inode,
-unsigned long lower_page_idx,
-int byte_offset_in_page)
-{
-   int rc = 0;
-
-   if (ctx-mode == ECRYPTFS_PREPARE_COMMIT_MODE) {
-   /* TODO: Limit this to only the data extents that are
-* needed */
-   rc = ecryptfs_get_lower_page(lower_page, lower_inode,
-ctx-param.lower_file,
-lower_page_idx,
-byte_offset_in_page,
-(PAGE_CACHE_SIZE

[PATCH 11/11] eCryptfs: Replace magic numbers

2007-09-17 Thread Michael Halcrow
Replace some magic numbers with sizeof() equivalents.

Signed-off-by: Michael Halcrow [EMAIL PROTECTED]
---
 fs/ecryptfs/crypto.c |6 +++---
 1 files changed, 3 insertions(+), 3 deletions(-)

diff --git a/fs/ecryptfs/crypto.c b/fs/ecryptfs/crypto.c
index 3b3cf27..425a144 100644
--- a/fs/ecryptfs/crypto.c
+++ b/fs/ecryptfs/crypto.c
@@ -1426,10 +1426,10 @@ static int parse_header_metadata(struct 
ecryptfs_crypt_stat *crypt_stat,
u32 header_extent_size;
u16 num_header_extents_at_front;
 
-   memcpy(header_extent_size, virt, 4);
+   memcpy(header_extent_size, virt, sizeof(u32));
header_extent_size = be32_to_cpu(header_extent_size);
-   virt += 4;
-   memcpy(num_header_extents_at_front, virt, 2);
+   virt += sizeof(u32);
+   memcpy(num_header_extents_at_front, virt, sizeof(u16));
num_header_extents_at_front = be16_to_cpu(num_header_extents_at_front);
crypt_stat-num_header_extents_at_front =
(int)num_header_extents_at_front;
-- 
1.5.1.6

-
To unsubscribe from this list: send the line unsubscribe linux-kernel in
the body of a message to [EMAIL PROTECTED]
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/


[PATCH] eCryptfs: Use generic_file_splice_read()

2007-09-11 Thread Michael Halcrow
eCryptfs is currently just passing through splice reads to the lower
filesystem. This is obviously incorrect behavior; the decrypted data
is what needs to be read, not the lower encrypted data. I cannot think
of any good reason for eCryptfs to implement splice_read, so this
patch points the eCryptfs fops splice_read to use
generic_file_splice_read.

Signed-off-by: Michael Halcrow <[EMAIL PROTECTED]>

--- linux-2.6.23-rc4-mm1.orig/fs/ecryptfs/file.c
+++ linux-2.6.23-rc4-mm1/fs/ecryptfs/file.c
@@ -338,21 +338,6 @@ static int ecryptfs_fasync(int fd, struc
return rc;
 }
 
-static ssize_t ecryptfs_splice_read(struct file *file, loff_t * ppos,
-   struct pipe_inode_info *pipe, size_t count,
-   unsigned int flags)
-{
-   struct file *lower_file = NULL;
-   int rc = -EINVAL;
-
-   lower_file = ecryptfs_file_to_lower(file);
-   if (lower_file->f_op && lower_file->f_op->splice_read)
-   rc = lower_file->f_op->splice_read(lower_file, ppos, pipe,
-   count, flags);
-
-   return rc;
-}
-
 static int ecryptfs_ioctl(struct inode *inode, struct file *file,
  unsigned int cmd, unsigned long arg);
 
@@ -365,7 +350,7 @@ const struct file_operations ecryptfs_di
.release = ecryptfs_release,
.fsync = ecryptfs_fsync,
.fasync = ecryptfs_fasync,
-   .splice_read = ecryptfs_splice_read,
+   .splice_read = generic_file_splice_read,
 };
 
 const struct file_operations ecryptfs_main_fops = {
@@ -382,7 +367,7 @@ const struct file_operations ecryptfs_ma
.release = ecryptfs_release,
.fsync = ecryptfs_fsync,
.fasync = ecryptfs_fasync,
-   .splice_read = ecryptfs_splice_read,
+   .splice_read = generic_file_splice_read,
 };
 
 static int
-
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to [EMAIL PROTECTED]
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/


[PATCH] eCryptfs: Use generic_file_splice_read()

2007-09-11 Thread Michael Halcrow
eCryptfs is currently just passing through splice reads to the lower
filesystem. This is obviously incorrect behavior; the decrypted data
is what needs to be read, not the lower encrypted data. I cannot think
of any good reason for eCryptfs to implement splice_read, so this
patch points the eCryptfs fops splice_read to use
generic_file_splice_read.

Signed-off-by: Michael Halcrow [EMAIL PROTECTED]

--- linux-2.6.23-rc4-mm1.orig/fs/ecryptfs/file.c
+++ linux-2.6.23-rc4-mm1/fs/ecryptfs/file.c
@@ -338,21 +338,6 @@ static int ecryptfs_fasync(int fd, struc
return rc;
 }
 
-static ssize_t ecryptfs_splice_read(struct file *file, loff_t * ppos,
-   struct pipe_inode_info *pipe, size_t count,
-   unsigned int flags)
-{
-   struct file *lower_file = NULL;
-   int rc = -EINVAL;
-
-   lower_file = ecryptfs_file_to_lower(file);
-   if (lower_file-f_op  lower_file-f_op-splice_read)
-   rc = lower_file-f_op-splice_read(lower_file, ppos, pipe,
-   count, flags);
-
-   return rc;
-}
-
 static int ecryptfs_ioctl(struct inode *inode, struct file *file,
  unsigned int cmd, unsigned long arg);
 
@@ -365,7 +350,7 @@ const struct file_operations ecryptfs_di
.release = ecryptfs_release,
.fsync = ecryptfs_fsync,
.fasync = ecryptfs_fasync,
-   .splice_read = ecryptfs_splice_read,
+   .splice_read = generic_file_splice_read,
 };
 
 const struct file_operations ecryptfs_main_fops = {
@@ -382,7 +367,7 @@ const struct file_operations ecryptfs_ma
.release = ecryptfs_release,
.fsync = ecryptfs_fsync,
.fasync = ecryptfs_fasync,
-   .splice_read = ecryptfs_splice_read,
+   .splice_read = generic_file_splice_read,
 };
 
 static int
-
To unsubscribe from this list: send the line unsubscribe linux-kernel in
the body of a message to [EMAIL PROTECTED]
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/


Re: [Ecryptfs-devel] [PATCH] eCryptfs: fix possible fault in ecryptfs_sync_page

2007-08-23 Thread Michael Halcrow
On Thu, Aug 23, 2007 at 04:42:59PM +0900, Ryusuke Konishi wrote:
> This will avoid a possible fault in ecryptfs_sync_page().

Acked-by: Michael Halcrow <[EMAIL PROTECTED]>

Note that there are other outstanding issues with eCryptfs on NFS. For
instance, prepare_write()/commit_write() have gone away in -mm,
leading to an oops when eCryptfs tries to call them directly, which is
well deserved, since eCryptfs really should not be doing that. Unionfs
has just two places where it calls vfs_read() and vfs_write()
respectively; eCryptfs is a bit more complex, with multiple write
paths that end up writing encrypted data and updating metadata in the
header. I am currently trying to find a way to convert everything over
to vfs_read() and vfs_write() in eCryptfs, in a way that does not
ultimately result in a kernel hang.

> In the function, eCryptfs calls sync_page() method of a lower 
> filesystem without checking its existence.  However, there 
> are many filesystems that don't have this method including
> network filesystems such as NFS, AFS, and so forth.
> They may fail when an eCryptfs page is waiting for lock.
> 
> Signed-off-by: Ryusuke Konishi <[EMAIL PROTECTED]>
> ---
>  fs/ecryptfs/mmap.c |3 ++-
>  1 files changed, 2 insertions(+), 1 deletions(-)
> 
> diff --git a/fs/ecryptfs/mmap.c b/fs/ecryptfs/mmap.c
> index e4ab7bc..fd3f94d 100644
> --- a/fs/ecryptfs/mmap.c
> +++ b/fs/ecryptfs/mmap.c
> @@ -834,7 +834,8 @@ static void ecryptfs_sync_page(struct page *page)
>   ecryptfs_printk(KERN_DEBUG, "find_lock_page failed\n");
>   return;
>   }
> - lower_page->mapping->a_ops->sync_page(lower_page);
> + if (lower_page->mapping->a_ops->sync_page)
> + lower_page->mapping->a_ops->sync_page(lower_page);
>   ecryptfs_printk(KERN_DEBUG, "Unlocking page with index = [0x%.16x]\n",
>   lower_page->index);
>   unlock_page(lower_page);
> 
> -
> This SF.net email is sponsored by: Splunk Inc.
> Still grepping through log files to find problems?  Stop.
> Now Search log events and configuration files using AJAX and a browser.
> Download your FREE copy of Splunk now >>  http://get.splunk.com/
> ___
> eCryptfs-devel mailing list
> [EMAIL PROTECTED]
> https://lists.sourceforge.net/lists/listinfo/ecryptfs-devel
-
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to [EMAIL PROTECTED]
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/


Re: [Ecryptfs-devel] [PATCH] eCryptfs: fix possible fault in ecryptfs_sync_page

2007-08-23 Thread Michael Halcrow
On Thu, Aug 23, 2007 at 04:42:59PM +0900, Ryusuke Konishi wrote:
 This will avoid a possible fault in ecryptfs_sync_page().

Acked-by: Michael Halcrow [EMAIL PROTECTED]

Note that there are other outstanding issues with eCryptfs on NFS. For
instance, prepare_write()/commit_write() have gone away in -mm,
leading to an oops when eCryptfs tries to call them directly, which is
well deserved, since eCryptfs really should not be doing that. Unionfs
has just two places where it calls vfs_read() and vfs_write()
respectively; eCryptfs is a bit more complex, with multiple write
paths that end up writing encrypted data and updating metadata in the
header. I am currently trying to find a way to convert everything over
to vfs_read() and vfs_write() in eCryptfs, in a way that does not
ultimately result in a kernel hang.

 In the function, eCryptfs calls sync_page() method of a lower 
 filesystem without checking its existence.  However, there 
 are many filesystems that don't have this method including
 network filesystems such as NFS, AFS, and so forth.
 They may fail when an eCryptfs page is waiting for lock.
 
 Signed-off-by: Ryusuke Konishi [EMAIL PROTECTED]
 ---
  fs/ecryptfs/mmap.c |3 ++-
  1 files changed, 2 insertions(+), 1 deletions(-)
 
 diff --git a/fs/ecryptfs/mmap.c b/fs/ecryptfs/mmap.c
 index e4ab7bc..fd3f94d 100644
 --- a/fs/ecryptfs/mmap.c
 +++ b/fs/ecryptfs/mmap.c
 @@ -834,7 +834,8 @@ static void ecryptfs_sync_page(struct page *page)
   ecryptfs_printk(KERN_DEBUG, find_lock_page failed\n);
   return;
   }
 - lower_page-mapping-a_ops-sync_page(lower_page);
 + if (lower_page-mapping-a_ops-sync_page)
 + lower_page-mapping-a_ops-sync_page(lower_page);
   ecryptfs_printk(KERN_DEBUG, Unlocking page with index = [0x%.16x]\n,
   lower_page-index);
   unlock_page(lower_page);
 
 -
 This SF.net email is sponsored by: Splunk Inc.
 Still grepping through log files to find problems?  Stop.
 Now Search log events and configuration files using AJAX and a browser.
 Download your FREE copy of Splunk now   http://get.splunk.com/
 ___
 eCryptfs-devel mailing list
 [EMAIL PROTECTED]
 https://lists.sourceforge.net/lists/listinfo/ecryptfs-devel
-
To unsubscribe from this list: send the line unsubscribe linux-kernel in
the body of a message to [EMAIL PROTECTED]
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/


Re: [PATCH 2.6.23-rc1] eCryptfs: fix error handling in ecryptfs_init

2007-08-02 Thread Michael Halcrow
On Thu, Aug 02, 2007 at 10:06:19PM +0900, Ryusuke Konishi wrote:
> ecryptfs_init() exits without doing any cleanup jobs if
> ecryptfs_init_messaging() fails.  In that case, eCryptfs leaves
> sysfs entries, leaks memory, and causes an invalid page fault.
> This patch fixes the problem.
> 
> Signed-off-by: Ryusuke Konishi <[EMAIL PROTECTED]>

Acked-by: Michael Halcrow <[EMAIL PROTECTED]>

> ---
>  fs/ecryptfs/main.c |   18 +-
>  1 files changed, 13 insertions(+), 5 deletions(-)
> 
> diff --git a/fs/ecryptfs/main.c b/fs/ecryptfs/main.c
> index e557a67..a984972 100644
> --- a/fs/ecryptfs/main.c
> +++ b/fs/ecryptfs/main.c
> @@ -813,6 +813,15 @@ out:
>   return rc;
>  }
> 
> +static void do_sysfs_unregistration(void)
> +{
> + sysfs_remove_file(_subsys.kobj,
> +   _attr_version.attr);
> + sysfs_remove_file(_subsys.kobj,
> +   _attr_version_str.attr);
> + subsystem_unregister(_subsys);
> +}
> +
>  static int __init ecryptfs_init(void)
>  {
>   int rc;
> @@ -851,6 +860,9 @@ static int __init ecryptfs_init(void)
>   if (rc) {
>   ecryptfs_printk(KERN_ERR, "Failure occured while attempting to "
>   "initialize the eCryptfs netlink socket\n");
> + do_sysfs_unregistration();
> + unregister_filesystem(_fs_type);
> + ecryptfs_free_kmem_caches();
>   }
>  out:
>   return rc;
> @@ -858,11 +870,7 @@ out:
> 
>  static void __exit ecryptfs_exit(void)
>  {
> - sysfs_remove_file(_subsys.kobj,
> -   _attr_version.attr);
> - sysfs_remove_file(_subsys.kobj,
> -   _attr_version_str.attr);
> - subsystem_unregister(_subsys);
> + do_sysfs_unregistration();
>   ecryptfs_release_messaging(ecryptfs_transport);
>   unregister_filesystem(_fs_type);
>   ecryptfs_free_kmem_caches();
-
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to [EMAIL PROTECTED]
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/


Re: [PATCH 2.6.23-rc1] eCryptfs: fix error handling in ecryptfs_init

2007-08-02 Thread Michael Halcrow
On Thu, Aug 02, 2007 at 10:06:19PM +0900, Ryusuke Konishi wrote:
 ecryptfs_init() exits without doing any cleanup jobs if
 ecryptfs_init_messaging() fails.  In that case, eCryptfs leaves
 sysfs entries, leaks memory, and causes an invalid page fault.
 This patch fixes the problem.
 
 Signed-off-by: Ryusuke Konishi [EMAIL PROTECTED]

Acked-by: Michael Halcrow [EMAIL PROTECTED]

 ---
  fs/ecryptfs/main.c |   18 +-
  1 files changed, 13 insertions(+), 5 deletions(-)
 
 diff --git a/fs/ecryptfs/main.c b/fs/ecryptfs/main.c
 index e557a67..a984972 100644
 --- a/fs/ecryptfs/main.c
 +++ b/fs/ecryptfs/main.c
 @@ -813,6 +813,15 @@ out:
   return rc;
  }
 
 +static void do_sysfs_unregistration(void)
 +{
 + sysfs_remove_file(ecryptfs_subsys.kobj,
 +   sysfs_attr_version.attr);
 + sysfs_remove_file(ecryptfs_subsys.kobj,
 +   sysfs_attr_version_str.attr);
 + subsystem_unregister(ecryptfs_subsys);
 +}
 +
  static int __init ecryptfs_init(void)
  {
   int rc;
 @@ -851,6 +860,9 @@ static int __init ecryptfs_init(void)
   if (rc) {
   ecryptfs_printk(KERN_ERR, Failure occured while attempting to 
   initialize the eCryptfs netlink socket\n);
 + do_sysfs_unregistration();
 + unregister_filesystem(ecryptfs_fs_type);
 + ecryptfs_free_kmem_caches();
   }
  out:
   return rc;
 @@ -858,11 +870,7 @@ out:
 
  static void __exit ecryptfs_exit(void)
  {
 - sysfs_remove_file(ecryptfs_subsys.kobj,
 -   sysfs_attr_version.attr);
 - sysfs_remove_file(ecryptfs_subsys.kobj,
 -   sysfs_attr_version_str.attr);
 - subsystem_unregister(ecryptfs_subsys);
 + do_sysfs_unregistration();
   ecryptfs_release_messaging(ecryptfs_transport);
   unregister_filesystem(ecryptfs_fs_type);
   ecryptfs_free_kmem_caches();
-
To unsubscribe from this list: send the line unsubscribe linux-kernel in
the body of a message to [EMAIL PROTECTED]
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/


Re: [PATCH 2.6.23-rc1] eCryptfs: fix lookup error for special files

2007-08-01 Thread Michael Halcrow
On Wed, Aug 01, 2007 at 10:01:14PM +0900, Ryusuke Konishi wrote:
> When ecryptfs_lookup() is called against special files, eCryptfs
> generates the following errors because it tries to treat them like
> regular eCryptfs files.
> 
> Error opening lower file for lower_dentry [0x810233a6f150], lower_mnt 
> [0x810235bb4c80], and flags 
> [0x8000]
> Error opening lower_file to read header region
> Error attempting to read the [user.ecryptfs] xattr from the lower file; 
> return value = [-95]
> Valid metadata not found in header region or xattr region; treating file as 
> unencrypted
> 
> For instance, the problem can be reproduced by the steps below.
> 
>   # mkdir /root/crypt /mnt/crypt
>   # mount -t ecryptfs /root/crypt /mnt/crypt
>   # mknod /mnt/crypt/c0 c 0 0
>   # umount /mnt/crypt
>   # mount -t ecryptfs /root/crypt /mnt/crypt
>   # ls -l /mnt/crypt
> 
> This patch fixes it by adding a check similar to directories and
> symlinks.
> 
> Signed-off-by: Ryusuke Konishi <[EMAIL PROTECTED]>

Acked-by: Michael Halcrow <[EMAIL PROTECTED]>

> ---
>  fs/ecryptfs/inode.c |4 
>  1 files changed, 4 insertions(+), 0 deletions(-)
> 
> diff --git a/fs/ecryptfs/inode.c b/fs/ecryptfs/inode.c
> index 0a50942..131954b 100644
> --- a/fs/ecryptfs/inode.c
> +++ b/fs/ecryptfs/inode.c
> @@ -353,6 +353,10 @@ static struct dentry *ecryptfs_lookup(struct inode *dir, 
> struct dentry *dentry,
>   ecryptfs_printk(KERN_DEBUG, "Is a symlink; returning\n");
>   goto out;
>   }
> + if (special_file(lower_inode->i_mode)) {
> + ecryptfs_printk(KERN_DEBUG, "Is a special file; returning\n");
> + goto out;
> + }
>   if (!nd) {
>   ecryptfs_printk(KERN_DEBUG, "We have a NULL nd, just leave"
>   "as we *think* we are about to unlink\n");
-
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to [EMAIL PROTECTED]
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/


Re: [PATCH 2.6.23-rc1] eCryptfs: fix lookup error for special files

2007-08-01 Thread Michael Halcrow
On Wed, Aug 01, 2007 at 10:01:14PM +0900, Ryusuke Konishi wrote:
 When ecryptfs_lookup() is called against special files, eCryptfs
 generates the following errors because it tries to treat them like
 regular eCryptfs files.
 
 Error opening lower file for lower_dentry [0x810233a6f150], lower_mnt 
 [0x810235bb4c80], and flags 
 [0x8000]
 Error opening lower_file to read header region
 Error attempting to read the [user.ecryptfs] xattr from the lower file; 
 return value = [-95]
 Valid metadata not found in header region or xattr region; treating file as 
 unencrypted
 
 For instance, the problem can be reproduced by the steps below.
 
   # mkdir /root/crypt /mnt/crypt
   # mount -t ecryptfs /root/crypt /mnt/crypt
   # mknod /mnt/crypt/c0 c 0 0
   # umount /mnt/crypt
   # mount -t ecryptfs /root/crypt /mnt/crypt
   # ls -l /mnt/crypt
 
 This patch fixes it by adding a check similar to directories and
 symlinks.
 
 Signed-off-by: Ryusuke Konishi [EMAIL PROTECTED]

Acked-by: Michael Halcrow [EMAIL PROTECTED]

 ---
  fs/ecryptfs/inode.c |4 
  1 files changed, 4 insertions(+), 0 deletions(-)
 
 diff --git a/fs/ecryptfs/inode.c b/fs/ecryptfs/inode.c
 index 0a50942..131954b 100644
 --- a/fs/ecryptfs/inode.c
 +++ b/fs/ecryptfs/inode.c
 @@ -353,6 +353,10 @@ static struct dentry *ecryptfs_lookup(struct inode *dir, 
 struct dentry *dentry,
   ecryptfs_printk(KERN_DEBUG, Is a symlink; returning\n);
   goto out;
   }
 + if (special_file(lower_inode-i_mode)) {
 + ecryptfs_printk(KERN_DEBUG, Is a special file; returning\n);
 + goto out;
 + }
   if (!nd) {
   ecryptfs_printk(KERN_DEBUG, We have a NULL nd, just leave
   as we *think* we are about to unlink\n);
-
To unsubscribe from this list: send the line unsubscribe linux-kernel in
the body of a message to [EMAIL PROTECTED]
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/


  1   2   3   >