vfs: introduce noop_llseek()
[safe/jmp/linux-2.6] / fs / ecryptfs / keystore.c
index e4a6223..89c5476 100644 (file)
@@ -32,6 +32,7 @@
 #include <linux/random.h>
 #include <linux/crypto.h>
 #include <linux/scatterlist.h>
+#include <linux/slab.h>
 #include "ecryptfs_kernel.h"
 
 /**
@@ -416,7 +417,9 @@ ecryptfs_find_global_auth_tok_for_sig(
                            &mount_crypt_stat->global_auth_tok_list,
                            mount_crypt_stat_list) {
                if (memcmp(walker->sig, sig, ECRYPTFS_SIG_SIZE_HEX) == 0) {
-                       (*global_auth_tok) = walker;
+                       rc = key_validate(walker->global_auth_tok_key);
+                       if (!rc)
+                               (*global_auth_tok) = walker;
                        goto out;
                }
        }
@@ -612,7 +615,12 @@ ecryptfs_write_tag_70_packet(char *dest, size_t *remaining_bytes,
        }
        /* TODO: Support other key modules than passphrase for
         * filename encryption */
-       BUG_ON(s->auth_tok->token_type != ECRYPTFS_PASSWORD);
+       if (s->auth_tok->token_type != ECRYPTFS_PASSWORD) {
+               rc = -EOPNOTSUPP;
+               printk(KERN_INFO "%s: Filename encryption only supports "
+                      "password tokens\n", __func__);
+               goto out_free_unlock;
+       }
        sg_init_one(
                &s->hash_sg,
                (u8 *)s->auth_tok->token.password.session_key_encryption_key,
@@ -740,8 +748,7 @@ ecryptfs_write_tag_70_packet(char *dest, size_t *remaining_bytes,
 out_release_free_unlock:
        crypto_free_hash(s->hash_desc.tfm);
 out_free_unlock:
-       memset(s->block_aligned_filename, 0, s->block_aligned_filename_size);
-       kfree(s->block_aligned_filename);
+       kzfree(s->block_aligned_filename);
 out_unlock:
        mutex_unlock(s->tfm_mutex);
 out:
@@ -911,7 +918,12 @@ ecryptfs_parse_tag_70_packet(char **filename, size_t *filename_size,
        }
        /* TODO: Support other key modules than passphrase for
         * filename encryption */
-       BUG_ON(s->auth_tok->token_type != ECRYPTFS_PASSWORD);
+       if (s->auth_tok->token_type != ECRYPTFS_PASSWORD) {
+               rc = -EOPNOTSUPP;
+               printk(KERN_INFO "%s: Filename encryption only supports "
+                      "password tokens\n", __func__);
+               goto out_free_unlock;
+       }
        rc = crypto_blkcipher_setkey(
                s->desc.tfm,
                s->auth_tok->token.password.session_key_encryption_key,
@@ -1304,14 +1316,23 @@ parse_tag_3_packet(struct ecryptfs_crypt_stat *crypt_stat,
        }
        (*new_auth_tok)->session_key.encrypted_key_size =
                (body_size - (ECRYPTFS_SALT_SIZE + 5));
+       if ((*new_auth_tok)->session_key.encrypted_key_size
+           > ECRYPTFS_MAX_ENCRYPTED_KEY_BYTES) {
+               printk(KERN_WARNING "Tag 3 packet contains key larger "
+                      "than ECRYPTFS_MAX_ENCRYPTED_KEY_BYTES\n");
+               rc = -EINVAL;
+               goto out_free;
+       }
        if (unlikely(data[(*packet_size)++] != 0x04)) {
                printk(KERN_WARNING "Unknown version number [%d]\n",
                       data[(*packet_size) - 1]);
                rc = -EINVAL;
                goto out_free;
        }
-       ecryptfs_cipher_code_to_string(crypt_stat->cipher,
-                                      (u16)data[(*packet_size)]);
+       rc = ecryptfs_cipher_code_to_string(crypt_stat->cipher,
+                                           (u16)data[(*packet_size)]);
+       if (rc)
+               goto out_free;
        /* A little extra work to differentiate among the AES key
         * sizes; see RFC2440 */
        switch(data[(*packet_size)++]) {
@@ -1322,7 +1343,9 @@ parse_tag_3_packet(struct ecryptfs_crypt_stat *crypt_stat,
                crypt_stat->key_size =
                        (*new_auth_tok)->session_key.encrypted_key_size;
        }
-       ecryptfs_init_crypt_ctx(crypt_stat);
+       rc = ecryptfs_init_crypt_ctx(crypt_stat);
+       if (rc)
+               goto out_free;
        if (unlikely(data[(*packet_size)++] != 0x03)) {
                printk(KERN_WARNING "Only S2K ID 3 is currently supported\n");
                rc = -ENOSYS;
@@ -1450,6 +1473,12 @@ parse_tag_11_packet(unsigned char *data, unsigned char *contents,
                rc = -EINVAL;
                goto out;
        }
+       if (unlikely((*tag_11_contents_size) > max_contents_bytes)) {
+               printk(KERN_ERR "Literal data section in tag 11 packet exceeds "
+                      "expected size\n");
+               rc = -EINVAL;
+               goto out;
+       }
        if (data[(*packet_size)++] != 0x62) {
                printk(KERN_WARNING "Unrecognizable packet\n");
                rc = -EINVAL;
@@ -2354,21 +2383,18 @@ struct kmem_cache *ecryptfs_key_sig_cache;
 int ecryptfs_add_keysig(struct ecryptfs_crypt_stat *crypt_stat, char *sig)
 {
        struct ecryptfs_key_sig *new_key_sig;
-       int rc = 0;
 
        new_key_sig = kmem_cache_alloc(ecryptfs_key_sig_cache, GFP_KERNEL);
        if (!new_key_sig) {
-               rc = -ENOMEM;
                printk(KERN_ERR
                       "Error allocating from ecryptfs_key_sig_cache\n");
-               goto out;
+               return -ENOMEM;
        }
        memcpy(new_key_sig->keysig, sig, ECRYPTFS_SIG_SIZE_HEX);
-       mutex_lock(&crypt_stat->keysig_list_mutex);
+       /* Caller must hold keysig_list_mutex */
        list_add(&new_key_sig->crypt_stat_list, &crypt_stat->keysig_list);
-       mutex_unlock(&crypt_stat->keysig_list_mutex);
-out:
-       return rc;
+
+       return 0;
 }
 
 struct kmem_cache *ecryptfs_global_auth_tok_cache;