]> git.kernelconcepts.de Git - karo-tx-linux.git/commitdiff
Merge tag 'ecryptfs-3.6-rc1-fixes' of git://git.kernel.org/pub/scm/linux/kernel/git...
authorLinus Torvalds <torvalds@linux-foundation.org>
Thu, 2 Aug 2012 17:56:34 +0000 (10:56 -0700)
committerLinus Torvalds <torvalds@linux-foundation.org>
Thu, 2 Aug 2012 17:56:34 +0000 (10:56 -0700)
Pull ecryptfs fixes from Tyler Hicks:
 - Fixes a bug when the lower filesystem mount options include 'acl',
   but the eCryptfs mount options do not
 - Cleanups in the messaging code
 - Better handling of empty files in the lower filesystem to improve
   usability.  Failed file creations are now cleaned up and empty lower
   files are converted into eCryptfs during open().
 - The write-through cache changes are being reverted due to bugs that
   are not easy to fix.  Stability outweighs the performance
   enhancements here.
 - Improvement to the mount code to catch unsupported ciphers specified
   in the mount options

* tag 'ecryptfs-3.6-rc1-fixes' of git://git.kernel.org/pub/scm/linux/kernel/git/tyhicks/ecryptfs:
  eCryptfs: check for eCryptfs cipher support at mount
  eCryptfs: Revert to a writethrough cache model
  eCryptfs: Initialize empty lower files when opening them
  eCryptfs: Unlink lower inode when ecryptfs_create() fails
  eCryptfs: Make all miscdev functions use daemon ptr in file private_data
  eCryptfs: Remove unused messaging declarations and function
  eCryptfs: Copy up POSIX ACL and read-only flags from lower mount

1  2 
fs/ecryptfs/ecryptfs_kernel.h
fs/ecryptfs/inode.c
fs/ecryptfs/main.c

index 989e034f02bdfa69e2c22994ceef7b06a8b61748,9f77ff818173b4a6f8370c9d404bbeb782871788..cfb4b9fed520144579c9f9de0a59bcfc5ceced34
@@@ -385,8 -385,6 +385,6 @@@ struct ecryptfs_msg_ctx 
        struct mutex mux;
  };
  
- struct ecryptfs_daemon;
  struct ecryptfs_daemon {
  #define ECRYPTFS_DAEMON_IN_READ      0x00000001
  #define ECRYPTFS_DAEMON_IN_POLL      0x00000002
  #define ECRYPTFS_DAEMON_MISCDEV_OPEN 0x00000008
        u32 flags;
        u32 num_queued_msg_ctx;
-       struct pid *pid;
-       uid_t euid;
-       struct user_namespace *user_ns;
-       struct task_struct *task;
+       struct file *file;
        struct mutex mux;
        struct list_head msg_ctx_out_queue;
        wait_queue_head_t wait;
@@@ -550,10 -545,26 +545,12 @@@ extern struct kmem_cache *ecryptfs_key_
  extern struct kmem_cache *ecryptfs_key_sig_cache;
  extern struct kmem_cache *ecryptfs_global_auth_tok_cache;
  extern struct kmem_cache *ecryptfs_key_tfm_cache;
 -extern struct kmem_cache *ecryptfs_open_req_cache;
 -
 -struct ecryptfs_open_req {
 -#define ECRYPTFS_REQ_PROCESSED 0x00000001
 -#define ECRYPTFS_REQ_DROPPED   0x00000002
 -#define ECRYPTFS_REQ_ZOMBIE    0x00000004
 -      u32 flags;
 -      struct file **lower_file;
 -      struct dentry *lower_dentry;
 -      struct vfsmount *lower_mnt;
 -      wait_queue_head_t wait;
 -      struct mutex mux;
 -      struct list_head kthread_ctl_list;
 -};
  
  struct inode *ecryptfs_get_inode(struct inode *lower_inode,
                                 struct super_block *sb);
  void ecryptfs_i_size_init(const char *page_virt, struct inode *inode);
+ int ecryptfs_initialize_file(struct dentry *ecryptfs_dentry,
+                            struct inode *ecryptfs_inode);
  int ecryptfs_decode_and_decrypt_filename(char **decrypted_name,
                                         size_t *decrypted_name_size,
                                         struct dentry *ecryptfs_dentry,
@@@ -607,13 -618,8 +604,8 @@@ in
  ecryptfs_setxattr(struct dentry *dentry, const char *name, const void *value,
                  size_t size, int flags);
  int ecryptfs_read_xattr_region(char *page_virt, struct inode *ecryptfs_inode);
- int ecryptfs_process_helo(uid_t euid, struct user_namespace *user_ns,
-                         struct pid *pid);
- int ecryptfs_process_quit(uid_t euid, struct user_namespace *user_ns,
-                         struct pid *pid);
- int ecryptfs_process_response(struct ecryptfs_message *msg, uid_t euid,
-                             struct user_namespace *user_ns, struct pid *pid,
-                             u32 seq);
+ int ecryptfs_process_response(struct ecryptfs_daemon *daemon,
+                             struct ecryptfs_message *msg, u32 seq);
  int ecryptfs_send_message(char *data, int data_len,
                          struct ecryptfs_msg_ctx **msg_ctx);
  int ecryptfs_wait_for_response(struct ecryptfs_msg_ctx *msg_ctx,
@@@ -658,8 -664,7 +650,7 @@@ int ecryptfs_read_lower_page_segment(st
                                     struct inode *ecryptfs_inode);
  struct page *ecryptfs_get_locked_page(struct inode *inode, loff_t index);
  int ecryptfs_exorcise_daemon(struct ecryptfs_daemon *daemon);
- int ecryptfs_find_daemon_by_euid(struct ecryptfs_daemon **daemon, uid_t euid,
-                                struct user_namespace *user_ns);
+ int ecryptfs_find_daemon_by_euid(struct ecryptfs_daemon **daemon);
  int ecryptfs_parse_packet_length(unsigned char *data, size_t *size,
                                 size_t *length_size);
  int ecryptfs_write_packet_length(char *dest, size_t size,
@@@ -671,8 -676,7 +662,7 @@@ int ecryptfs_send_miscdev(char *data, s
                          u16 msg_flags, struct ecryptfs_daemon *daemon);
  void ecryptfs_msg_ctx_alloc_to_free(struct ecryptfs_msg_ctx *msg_ctx);
  int
- ecryptfs_spawn_daemon(struct ecryptfs_daemon **daemon, uid_t euid,
-                     struct user_namespace *user_ns, struct pid *pid);
+ ecryptfs_spawn_daemon(struct ecryptfs_daemon **daemon, struct file *file);
  int ecryptfs_init_kthread(void);
  void ecryptfs_destroy_kthread(void);
  int ecryptfs_privileged_open(struct file **lower_file,
diff --combined fs/ecryptfs/inode.c
index c3ca12c33ca2aa3c504bcc3e415595d72b96c5d4,769fb8524aebcf3e93d6d13980eb646c9efabb0f..534b129ea676500c4df149d95cb9bd5be517dc54
@@@ -143,6 -143,31 +143,31 @@@ static int ecryptfs_interpose(struct de
        return 0;
  }
  
+ static int ecryptfs_do_unlink(struct inode *dir, struct dentry *dentry,
+                             struct inode *inode)
+ {
+       struct dentry *lower_dentry = ecryptfs_dentry_to_lower(dentry);
+       struct inode *lower_dir_inode = ecryptfs_inode_to_lower(dir);
+       struct dentry *lower_dir_dentry;
+       int rc;
+       dget(lower_dentry);
+       lower_dir_dentry = lock_parent(lower_dentry);
+       rc = vfs_unlink(lower_dir_inode, lower_dentry);
+       if (rc) {
+               printk(KERN_ERR "Error in vfs_unlink; rc = [%d]\n", rc);
+               goto out_unlock;
+       }
+       fsstack_copy_attr_times(dir, lower_dir_inode);
+       set_nlink(inode, ecryptfs_inode_to_lower(inode)->i_nlink);
+       inode->i_ctime = dir->i_ctime;
+       d_drop(dentry);
+ out_unlock:
+       unlock_dir(lower_dir_dentry);
+       dput(lower_dentry);
+       return rc;
+ }
  /**
   * ecryptfs_do_create
   * @directory_inode: inode of the new file's dentry's parent in ecryptfs
@@@ -173,7 -198,7 +198,7 @@@ ecryptfs_do_create(struct inode *direct
                inode = ERR_CAST(lower_dir_dentry);
                goto out;
        }
 -      rc = vfs_create(lower_dir_dentry->d_inode, lower_dentry, mode, NULL);
 +      rc = vfs_create(lower_dir_dentry->d_inode, lower_dentry, mode, true);
        if (rc) {
                printk(KERN_ERR "%s: Failure to create dentry in lower fs; "
                       "rc = [%d]\n", __func__, rc);
        }
        inode = __ecryptfs_get_inode(lower_dentry->d_inode,
                                     directory_inode->i_sb);
-       if (IS_ERR(inode))
+       if (IS_ERR(inode)) {
+               vfs_unlink(lower_dir_dentry->d_inode, lower_dentry);
                goto out_lock;
+       }
        fsstack_copy_attr_times(directory_inode, lower_dir_dentry->d_inode);
        fsstack_copy_inode_size(directory_inode, lower_dir_dentry->d_inode);
  out_lock:
@@@ -200,8 -227,8 +227,8 @@@ out
   *
   * Returns zero on success
   */
static int ecryptfs_initialize_file(struct dentry *ecryptfs_dentry,
-                                   struct inode *ecryptfs_inode)
+ int ecryptfs_initialize_file(struct dentry *ecryptfs_dentry,
+                            struct inode *ecryptfs_inode)
  {
        struct ecryptfs_crypt_stat *crypt_stat =
                &ecryptfs_inode_to_private(ecryptfs_inode)->crypt_stat;
@@@ -240,6 -267,7 +267,6 @@@ out
   * @dir: The inode of the directory in which to create the file.
   * @dentry: The eCryptfs dentry
   * @mode: The mode of the new file.
 - * @nd: nameidata
   *
   * Creates a new file.
   *
   */
  static int
  ecryptfs_create(struct inode *directory_inode, struct dentry *ecryptfs_dentry,
 -              umode_t mode, struct nameidata *nd)
 +              umode_t mode, bool excl)
  {
        struct inode *ecryptfs_inode;
        int rc;
         * that this on disk file is prepared to be an ecryptfs file */
        rc = ecryptfs_initialize_file(ecryptfs_dentry, ecryptfs_inode);
        if (rc) {
-               drop_nlink(ecryptfs_inode);
+               ecryptfs_do_unlink(directory_inode, ecryptfs_dentry,
+                                  ecryptfs_inode);
+               make_bad_inode(ecryptfs_inode);
                unlock_new_inode(ecryptfs_inode);
                iput(ecryptfs_inode);
                goto out;
        }
 -      d_instantiate(ecryptfs_dentry, ecryptfs_inode);
        unlock_new_inode(ecryptfs_inode);
 +      d_instantiate(ecryptfs_dentry, ecryptfs_inode);
  out:
        return rc;
  }
@@@ -318,20 -348,21 +347,20 @@@ static int ecryptfs_lookup_interpose(st
        struct vfsmount *lower_mnt;
        int rc = 0;
  
 -      lower_mnt = mntget(ecryptfs_dentry_to_lower_mnt(dentry->d_parent));
 -      fsstack_copy_attr_atime(dir_inode, lower_dentry->d_parent->d_inode);
 -      BUG_ON(!lower_dentry->d_count);
 -
        dentry_info = kmem_cache_alloc(ecryptfs_dentry_info_cache, GFP_KERNEL);
 -      ecryptfs_set_dentry_private(dentry, dentry_info);
        if (!dentry_info) {
                printk(KERN_ERR "%s: Out of memory whilst attempting "
                       "to allocate ecryptfs_dentry_info struct\n",
                        __func__);
                dput(lower_dentry);
 -              mntput(lower_mnt);
 -              d_drop(dentry);
                return -ENOMEM;
        }
 +
 +      lower_mnt = mntget(ecryptfs_dentry_to_lower_mnt(dentry->d_parent));
 +      fsstack_copy_attr_atime(dir_inode, lower_dentry->d_parent->d_inode);
 +      BUG_ON(!lower_dentry->d_count);
 +
 +      ecryptfs_set_dentry_private(dentry, dentry_info);
        ecryptfs_set_dentry_lower(dentry, lower_dentry);
        ecryptfs_set_dentry_lower_mnt(dentry, lower_mnt);
  
   */
  static struct dentry *ecryptfs_lookup(struct inode *ecryptfs_dir_inode,
                                      struct dentry *ecryptfs_dentry,
 -                                    struct nameidata *ecryptfs_nd)
 +                                    unsigned int flags)
  {
        char *encrypted_and_encoded_name = NULL;
        size_t encrypted_and_encoded_name_size;
        struct dentry *lower_dir_dentry, *lower_dentry;
        int rc = 0;
  
 -      if ((ecryptfs_dentry->d_name.len == 1
 -           && !strcmp(ecryptfs_dentry->d_name.name, "."))
 -          || (ecryptfs_dentry->d_name.len == 2
 -              && !strcmp(ecryptfs_dentry->d_name.name, ".."))) {
 -              goto out_d_drop;
 -      }
        lower_dir_dentry = ecryptfs_dentry_to_lower(ecryptfs_dentry->d_parent);
        mutex_lock(&lower_dir_dentry->d_inode->i_mutex);
        lower_dentry = lookup_one_len(ecryptfs_dentry->d_name.name,
                rc = PTR_ERR(lower_dentry);
                ecryptfs_printk(KERN_DEBUG, "%s: lookup_one_len() returned "
                                "[%d] on lower_dentry = [%s]\n", __func__, rc,
 -                              encrypted_and_encoded_name);
 -              goto out_d_drop;
 +                              ecryptfs_dentry->d_name.name);
 +              goto out;
        }
        if (lower_dentry->d_inode)
                goto interpose;
        if (rc) {
                printk(KERN_ERR "%s: Error attempting to encrypt and encode "
                       "filename; rc = [%d]\n", __func__, rc);
 -              goto out_d_drop;
 +              goto out;
        }
        mutex_lock(&lower_dir_dentry->d_inode->i_mutex);
        lower_dentry = lookup_one_len(encrypted_and_encoded_name,
                ecryptfs_printk(KERN_DEBUG, "%s: lookup_one_len() returned "
                                "[%d] on lower_dentry = [%s]\n", __func__, rc,
                                encrypted_and_encoded_name);
 -              goto out_d_drop;
 +              goto out;
        }
  interpose:
        rc = ecryptfs_lookup_interpose(ecryptfs_dentry, lower_dentry,
                                       ecryptfs_dir_inode);
 -      goto out;
 -out_d_drop:
 -      d_drop(ecryptfs_dentry);
  out:
        kfree(encrypted_and_encoded_name);
        return ERR_PTR(rc);
@@@ -466,27 -506,7 +495,7 @@@ out_lock
  
  static int ecryptfs_unlink(struct inode *dir, struct dentry *dentry)
  {
-       int rc = 0;
-       struct dentry *lower_dentry = ecryptfs_dentry_to_lower(dentry);
-       struct inode *lower_dir_inode = ecryptfs_inode_to_lower(dir);
-       struct dentry *lower_dir_dentry;
-       dget(lower_dentry);
-       lower_dir_dentry = lock_parent(lower_dentry);
-       rc = vfs_unlink(lower_dir_inode, lower_dentry);
-       if (rc) {
-               printk(KERN_ERR "Error in vfs_unlink; rc = [%d]\n", rc);
-               goto out_unlock;
-       }
-       fsstack_copy_attr_times(dir, lower_dir_inode);
-       set_nlink(dentry->d_inode,
-                 ecryptfs_inode_to_lower(dentry->d_inode)->i_nlink);
-       dentry->d_inode->i_ctime = dir->i_ctime;
-       d_drop(dentry);
- out_unlock:
-       unlock_dir(lower_dir_dentry);
-       dput(lower_dentry);
-       return rc;
+       return ecryptfs_do_unlink(dir, dentry, dentry->d_inode);
  }
  
  static int ecryptfs_symlink(struct inode *dir, struct dentry *dentry,
@@@ -961,12 -981,6 +970,6 @@@ static int ecryptfs_setattr(struct dent
                        goto out;
        }
  
-       if (S_ISREG(inode->i_mode)) {
-               rc = filemap_write_and_wait(inode->i_mapping);
-               if (rc)
-                       goto out;
-               fsstack_copy_attr_all(inode, lower_inode);
-       }
        memcpy(&lower_ia, ia, sizeof(lower_ia));
        if (ia->ia_valid & ATTR_FILE)
                lower_ia.ia_file = ecryptfs_file_to_lower(ia->ia_file);
diff --combined fs/ecryptfs/main.c
index 1c0b3b6b75c6a777948dc80338d5765345d74e95,923f6aa09cb371bd7169483ed8cada69bf08df0b..2768138eefeef85707f9ee29652532b25d50dfcb
@@@ -279,6 -279,7 +279,7 @@@ static int ecryptfs_parse_options(struc
        char *fnek_src;
        char *cipher_key_bytes_src;
        char *fn_cipher_key_bytes_src;
+       u8 cipher_code;
  
        *check_ruid = 0;
  
            && !fn_cipher_key_bytes_set)
                mount_crypt_stat->global_default_fn_cipher_key_bytes =
                        mount_crypt_stat->global_default_cipher_key_size;
+       cipher_code = ecryptfs_code_for_cipher_string(
+               mount_crypt_stat->global_default_cipher_name,
+               mount_crypt_stat->global_default_cipher_key_size);
+       if (!cipher_code) {
+               ecryptfs_printk(KERN_ERR,
+                               "eCryptfs doesn't support cipher: %s",
+                               mount_crypt_stat->global_default_cipher_name);
+               rc = -EINVAL;
+               goto out;
+       }
        mutex_lock(&key_tfm_list_mutex);
        if (!ecryptfs_tfm_exists(mount_crypt_stat->global_default_cipher_name,
                                 NULL)) {
@@@ -499,7 -512,7 +512,7 @@@ static struct dentry *ecryptfs_mount(st
                goto out;
        }
  
 -      s = sget(fs_type, NULL, set_anon_super, NULL);
 +      s = sget(fs_type, NULL, set_anon_super, flags, NULL);
        if (IS_ERR(s)) {
                rc = PTR_ERR(s);
                goto out;
        }
  
        ecryptfs_set_superblock_lower(s, path.dentry->d_sb);
+       /**
+        * Set the POSIX ACL flag based on whether they're enabled in the lower
+        * mount. Force a read-only eCryptfs mount if the lower mount is ro.
+        * Allow a ro eCryptfs mount even when the lower mount is rw.
+        */
+       s->s_flags = flags & ~MS_POSIXACL;
+       s->s_flags |= path.dentry->d_sb->s_flags & (MS_RDONLY | MS_POSIXACL);
        s->s_maxbytes = path.dentry->d_sb->s_maxbytes;
        s->s_blocksize = path.dentry->d_sb->s_blocksize;
        s->s_magic = ECRYPTFS_SUPER_MAGIC;
@@@ -681,6 -703,11 +703,6 @@@ static struct ecryptfs_cache_info 
                .name = "ecryptfs_key_tfm_cache",
                .size = sizeof(struct ecryptfs_key_tfm),
        },
 -      {
 -              .cache = &ecryptfs_open_req_cache,
 -              .name = "ecryptfs_open_req_cache",
 -              .size = sizeof(struct ecryptfs_open_req),
 -      },
  };
  
  static void ecryptfs_free_kmem_caches(void)