fs: limit filesystem stacking depth
[pandora-kernel.git] / fs / ecryptfs / main.c
index b4a6bef..b53a97e 100644 (file)
@@ -162,6 +162,7 @@ void ecryptfs_put_lower_file(struct inode *inode)
        inode_info = ecryptfs_inode_to_private(inode);
        if (atomic_dec_and_mutex_lock(&inode_info->lower_file_count,
                                      &inode_info->lower_file_mutex)) {
+               filemap_write_and_wait(inode->i_mapping);
                fput(inode_info->lower_file);
                inode_info->lower_file = NULL;
                mutex_unlock(&inode_info->lower_file_mutex);
@@ -279,6 +280,7 @@ static int ecryptfs_parse_options(struct ecryptfs_sb_info *sbi, char *options,
        char *fnek_src;
        char *cipher_key_bytes_src;
        char *fn_cipher_key_bytes_src;
+       u8 cipher_code;
 
        *check_ruid = 0;
 
@@ -420,6 +422,18 @@ static int ecryptfs_parse_options(struct ecryptfs_sb_info *sbi, char *options,
            && !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)) {
@@ -480,6 +494,7 @@ static struct dentry *ecryptfs_mount(struct file_system_type *fs_type, int flags
 {
        struct super_block *s;
        struct ecryptfs_sb_info *sbi;
+       struct ecryptfs_mount_crypt_stat *mount_crypt_stat;
        struct ecryptfs_dentry_info *root_info;
        const char *err = "Getting sb failed";
        struct inode *inode;
@@ -498,6 +513,7 @@ static struct dentry *ecryptfs_mount(struct file_system_type *fs_type, int flags
                err = "Error parsing options";
                goto out;
        }
+       mount_crypt_stat = &sbi->mount_crypt_stat;
 
        s = sget(fs_type, NULL, set_anon_super, NULL);
        if (IS_ERR(s)) {
@@ -505,7 +521,6 @@ static struct dentry *ecryptfs_mount(struct file_system_type *fs_type, int flags
                goto out;
        }
 
-       s->s_flags = flags;
        rc = bdi_setup_and_register(&sbi->bdi, "ecryptfs", BDI_CAP_MAP_COPY);
        if (rc)
                goto out1;
@@ -541,9 +556,33 @@ static struct dentry *ecryptfs_mount(struct file_system_type *fs_type, int flags
        }
 
        ecryptfs_set_superblock_lower(s, path.dentry->d_sb);
+
+       /**
+        * Set the POSIX ACL flag based on whether they're enabled in the lower
+        * mount.
+        */
+       s->s_flags = flags & ~MS_POSIXACL;
+       s->s_flags |= path.dentry->d_sb->s_flags & MS_POSIXACL;
+
+       /**
+        * Force a read-only eCryptfs mount when:
+        *   1) The lower mount is ro
+        *   2) The ecryptfs_encrypted_view mount option is specified
+        */
+       if (path.dentry->d_sb->s_flags & MS_RDONLY ||
+           mount_crypt_stat->flags & ECRYPTFS_ENCRYPTED_VIEW_ENABLED)
+               s->s_flags |= MS_RDONLY;
+
        s->s_maxbytes = path.dentry->d_sb->s_maxbytes;
        s->s_blocksize = path.dentry->d_sb->s_blocksize;
        s->s_magic = ECRYPTFS_SUPER_MAGIC;
+       s->s_stack_depth = path.dentry->d_sb->s_stack_depth + 1;
+
+       rc = -EINVAL;
+       if (s->s_stack_depth > FILESYSTEM_MAX_STACK_DEPTH) {
+               pr_err("eCryptfs: maximum fs stacking depth exceeded\n");
+               goto out_free;
+       }
 
        inode = ecryptfs_get_inode(path.dentry->d_inode, s);
        rc = PTR_ERR(inode);