eCryptfs: fix Tag 11 parsing code
Michael Halcrow [Tue, 16 Oct 2007 08:27:57 +0000 (01:27 -0700)]
Fix up the Tag 11 parsing code to handle size limits and boundaries more
explicitly.  Pay attention to *8* bytes for the key identifier (literal data),
no more, no less.

Signed-off-by: Michael Halcrow <mhalcrow@us.ibm.com>
Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>

fs/ecryptfs/keystore.c

index 7208614..aedff50 100644 (file)
@@ -803,82 +803,60 @@ parse_tag_11_packet(unsigned char *data, unsigned char *contents,
 
        (*packet_size) = 0;
        (*tag_11_contents_size) = 0;
-
-       /* check that:
-        *   one byte for the Tag 11 ID flag
-        *   two bytes for the Tag 11 length
-        * do not exceed the maximum_packet_size
+       /* This format is inspired by OpenPGP; see RFC 2440
+        * packet tag 11
+        *
+        * Tag 11 identifier (1 byte)
+        * Max Tag 11 packet size (max 3 bytes)
+        * Binary format specifier (1 byte)
+        * Filename length (1 byte)
+        * Filename ("_CONSOLE") (8 bytes)
+        * Modification date (4 bytes)
+        * Literal data (arbitrary)
+        *
+        * We need at least 16 bytes of data for the packet to even be
+        * valid.
         */
-       if (unlikely((*packet_size) + 3 > max_packet_size)) {
-               ecryptfs_printk(KERN_ERR, "Packet size exceeds max\n");
+       if (max_packet_size < 16) {
+               printk(KERN_ERR "Maximum packet size too small\n");
                rc = -EINVAL;
                goto out;
        }
-
-       /* check for Tag 11 identifyer - one byte */
        if (data[(*packet_size)++] != ECRYPTFS_TAG_11_PACKET_TYPE) {
-               ecryptfs_printk(KERN_WARNING,
-                               "Invalid tag 11 packet format\n");
+               printk(KERN_WARNING "Invalid tag 11 packet format\n");
                rc = -EINVAL;
                goto out;
        }
-
-       /* get Tag 11 content length - one or two bytes */
-       rc = parse_packet_length(&data[(*packet_size)], &body_size,
-                                &length_size);
-       if (rc) {
-               ecryptfs_printk(KERN_WARNING,
-                               "Invalid tag 11 packet format\n");
+       if ((rc = parse_packet_length(&data[(*packet_size)], &body_size,
+                                     &length_size))) {
+               printk(KERN_WARNING "Invalid tag 11 packet format\n");
                goto out;
        }
-       (*packet_size) += length_size;
-
-       if (body_size < 13) {
-               ecryptfs_printk(KERN_WARNING, "Invalid body size ([%d])\n",
-                               body_size);
+       if (body_size < 14) {
+               printk(KERN_WARNING "Invalid body size ([%d])\n", body_size);
                rc = -EINVAL;
                goto out;
        }
-       /* We have 13 bytes of surrounding packet values */
-       (*tag_11_contents_size) = (body_size - 13);
-
-       /* now we know the length of the remainting Tag 11 packet size:
-        *   14 fix bytes for: special flag one, special flag two,
-        *                     12 skipped bytes
-        *   body_size bytes minus the stuff above is the Tag 11 content
-        */
-       /* FIXME why is the body size one byte smaller than the actual
-        * size of the body?
-        * this seems to be an error here as well as in
-        * write_tag_11_packet() */
+       (*packet_size) += length_size;
+       (*tag_11_contents_size) = (body_size - 14);
        if (unlikely((*packet_size) + body_size + 1 > max_packet_size)) {
-               ecryptfs_printk(KERN_ERR, "Packet size exceeds max\n");
+               printk(KERN_ERR "Packet size exceeds max\n");
                rc = -EINVAL;
                goto out;
        }
-
-       /* special flag one - one byte */
        if (data[(*packet_size)++] != 0x62) {
-               ecryptfs_printk(KERN_WARNING, "Unrecognizable packet\n");
+               printk(KERN_WARNING "Unrecognizable packet\n");
                rc = -EINVAL;
                goto out;
        }
-
-       /* special flag two - one byte */
        if (data[(*packet_size)++] != 0x08) {
-               ecryptfs_printk(KERN_WARNING, "Unrecognizable packet\n");
+               printk(KERN_WARNING "Unrecognizable packet\n");
                rc = -EINVAL;
                goto out;
        }
-
-       /* skip the next 12 bytes */
-       (*packet_size) += 12; /* We don't care about the filename or
-                              * the timestamp */
-
-       /* get the Tag 11 contents - tag_11_contents_size bytes */
+       (*packet_size) += 12; /* Ignore filename and modification date */
        memcpy(contents, &data[(*packet_size)], (*tag_11_contents_size));
        (*packet_size) += (*tag_11_contents_size);
-
 out:
        if (rc) {
                (*packet_size) = 0;