diff options
author | Michael Halcrow <mhalcrow@us.ibm.com> | 2007-10-16 04:27:57 -0400 |
---|---|---|
committer | Linus Torvalds <torvalds@woody.linux-foundation.org> | 2007-10-16 12:43:11 -0400 |
commit | f648104a0d44d7c551f8025ad7e50c4815d3b6eb (patch) | |
tree | f02a40f291c67171f86facc9e2fa80c01a0bd03b /fs | |
parent | c59becfceea8de57c35a3de5ee45a7bb883cf90a (diff) |
eCryptfs: fix Tag 11 parsing code
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>
Diffstat (limited to 'fs')
-rw-r--r-- | fs/ecryptfs/keystore.c | 76 |
1 files changed, 27 insertions, 49 deletions
diff --git a/fs/ecryptfs/keystore.c b/fs/ecryptfs/keystore.c index 72086141a6e8..aedff506899e 100644 --- a/fs/ecryptfs/keystore.c +++ b/fs/ecryptfs/keystore.c | |||
@@ -803,82 +803,60 @@ parse_tag_11_packet(unsigned char *data, unsigned char *contents, | |||
803 | 803 | ||
804 | (*packet_size) = 0; | 804 | (*packet_size) = 0; |
805 | (*tag_11_contents_size) = 0; | 805 | (*tag_11_contents_size) = 0; |
806 | 806 | /* This format is inspired by OpenPGP; see RFC 2440 | |
807 | /* check that: | 807 | * packet tag 11 |
808 | * one byte for the Tag 11 ID flag | 808 | * |
809 | * two bytes for the Tag 11 length | 809 | * Tag 11 identifier (1 byte) |
810 | * do not exceed the maximum_packet_size | 810 | * Max Tag 11 packet size (max 3 bytes) |
811 | * Binary format specifier (1 byte) | ||
812 | * Filename length (1 byte) | ||
813 | * Filename ("_CONSOLE") (8 bytes) | ||
814 | * Modification date (4 bytes) | ||
815 | * Literal data (arbitrary) | ||
816 | * | ||
817 | * We need at least 16 bytes of data for the packet to even be | ||
818 | * valid. | ||
811 | */ | 819 | */ |
812 | if (unlikely((*packet_size) + 3 > max_packet_size)) { | 820 | if (max_packet_size < 16) { |
813 | ecryptfs_printk(KERN_ERR, "Packet size exceeds max\n"); | 821 | printk(KERN_ERR "Maximum packet size too small\n"); |
814 | rc = -EINVAL; | 822 | rc = -EINVAL; |
815 | goto out; | 823 | goto out; |
816 | } | 824 | } |
817 | |||
818 | /* check for Tag 11 identifyer - one byte */ | ||
819 | if (data[(*packet_size)++] != ECRYPTFS_TAG_11_PACKET_TYPE) { | 825 | if (data[(*packet_size)++] != ECRYPTFS_TAG_11_PACKET_TYPE) { |
820 | ecryptfs_printk(KERN_WARNING, | 826 | printk(KERN_WARNING "Invalid tag 11 packet format\n"); |
821 | "Invalid tag 11 packet format\n"); | ||
822 | rc = -EINVAL; | 827 | rc = -EINVAL; |
823 | goto out; | 828 | goto out; |
824 | } | 829 | } |
825 | 830 | if ((rc = parse_packet_length(&data[(*packet_size)], &body_size, | |
826 | /* get Tag 11 content length - one or two bytes */ | 831 | &length_size))) { |
827 | rc = parse_packet_length(&data[(*packet_size)], &body_size, | 832 | printk(KERN_WARNING "Invalid tag 11 packet format\n"); |
828 | &length_size); | ||
829 | if (rc) { | ||
830 | ecryptfs_printk(KERN_WARNING, | ||
831 | "Invalid tag 11 packet format\n"); | ||
832 | goto out; | 833 | goto out; |
833 | } | 834 | } |
834 | (*packet_size) += length_size; | 835 | if (body_size < 14) { |
835 | 836 | printk(KERN_WARNING "Invalid body size ([%d])\n", body_size); | |
836 | if (body_size < 13) { | ||
837 | ecryptfs_printk(KERN_WARNING, "Invalid body size ([%d])\n", | ||
838 | body_size); | ||
839 | rc = -EINVAL; | 837 | rc = -EINVAL; |
840 | goto out; | 838 | goto out; |
841 | } | 839 | } |
842 | /* We have 13 bytes of surrounding packet values */ | 840 | (*packet_size) += length_size; |
843 | (*tag_11_contents_size) = (body_size - 13); | 841 | (*tag_11_contents_size) = (body_size - 14); |
844 | |||
845 | /* now we know the length of the remainting Tag 11 packet size: | ||
846 | * 14 fix bytes for: special flag one, special flag two, | ||
847 | * 12 skipped bytes | ||
848 | * body_size bytes minus the stuff above is the Tag 11 content | ||
849 | */ | ||
850 | /* FIXME why is the body size one byte smaller than the actual | ||
851 | * size of the body? | ||
852 | * this seems to be an error here as well as in | ||
853 | * write_tag_11_packet() */ | ||
854 | if (unlikely((*packet_size) + body_size + 1 > max_packet_size)) { | 842 | if (unlikely((*packet_size) + body_size + 1 > max_packet_size)) { |
855 | ecryptfs_printk(KERN_ERR, "Packet size exceeds max\n"); | 843 | printk(KERN_ERR "Packet size exceeds max\n"); |
856 | rc = -EINVAL; | 844 | rc = -EINVAL; |
857 | goto out; | 845 | goto out; |
858 | } | 846 | } |
859 | |||
860 | /* special flag one - one byte */ | ||
861 | if (data[(*packet_size)++] != 0x62) { | 847 | if (data[(*packet_size)++] != 0x62) { |
862 | ecryptfs_printk(KERN_WARNING, "Unrecognizable packet\n"); | 848 | printk(KERN_WARNING "Unrecognizable packet\n"); |
863 | rc = -EINVAL; | 849 | rc = -EINVAL; |
864 | goto out; | 850 | goto out; |
865 | } | 851 | } |
866 | |||
867 | /* special flag two - one byte */ | ||
868 | if (data[(*packet_size)++] != 0x08) { | 852 | if (data[(*packet_size)++] != 0x08) { |
869 | ecryptfs_printk(KERN_WARNING, "Unrecognizable packet\n"); | 853 | printk(KERN_WARNING "Unrecognizable packet\n"); |
870 | rc = -EINVAL; | 854 | rc = -EINVAL; |
871 | goto out; | 855 | goto out; |
872 | } | 856 | } |
873 | 857 | (*packet_size) += 12; /* Ignore filename and modification date */ | |
874 | /* skip the next 12 bytes */ | ||
875 | (*packet_size) += 12; /* We don't care about the filename or | ||
876 | * the timestamp */ | ||
877 | |||
878 | /* get the Tag 11 contents - tag_11_contents_size bytes */ | ||
879 | memcpy(contents, &data[(*packet_size)], (*tag_11_contents_size)); | 858 | memcpy(contents, &data[(*packet_size)], (*tag_11_contents_size)); |
880 | (*packet_size) += (*tag_11_contents_size); | 859 | (*packet_size) += (*tag_11_contents_size); |
881 | |||
882 | out: | 860 | out: |
883 | if (rc) { | 861 | if (rc) { |
884 | (*packet_size) = 0; | 862 | (*packet_size) = 0; |