diff options
author | Jon Derrick <jonathan.derrick@intel.com> | 2017-02-21 13:59:15 -0500 |
---|---|---|
committer | Jens Axboe <axboe@fb.com> | 2017-02-22 13:54:49 -0500 |
commit | 77039b96316d119cea23f48b617103d50e78b840 (patch) | |
tree | aa9bef91b061b72beb2252fb325d6ea4bff7d9c8 /block | |
parent | cccb92417d447172c4653876f6cd4b04c29d7905 (diff) |
block/sed: Check received header lengths
Add a buffer size check against discovery and response header lengths
before we loop over their buffers.
Signed-off-by: Jon Derrick <jonathan.derrick@intel.com>
Reviewed-by: Scott Bauer <scott.bauer@intel.com>
Reviewed-by: Christoph Hellwig <hch@lst.de>
Signed-off-by: Jens Axboe <axboe@fb.com>
Diffstat (limited to 'block')
-rw-r--r-- | block/sed-opal.c | 35 |
1 files changed, 21 insertions, 14 deletions
diff --git a/block/sed-opal.c b/block/sed-opal.c index d3d6db2877b9..4fc4d7b441d5 100644 --- a/block/sed-opal.c +++ b/block/sed-opal.c | |||
@@ -411,10 +411,17 @@ static int opal_discovery0_end(struct opal_dev *dev) | |||
411 | const struct d0_header *hdr = (struct d0_header *)dev->resp; | 411 | const struct d0_header *hdr = (struct d0_header *)dev->resp; |
412 | const u8 *epos = dev->resp, *cpos = dev->resp; | 412 | const u8 *epos = dev->resp, *cpos = dev->resp; |
413 | u16 comid = 0; | 413 | u16 comid = 0; |
414 | u32 hlen = be32_to_cpu(hdr->length); | ||
414 | 415 | ||
415 | print_buffer(dev->resp, be32_to_cpu(hdr->length)); | 416 | print_buffer(dev->resp, hlen); |
416 | 417 | ||
417 | epos += be32_to_cpu(hdr->length); /* end of buffer */ | 418 | if (hlen > IO_BUFFER_LENGTH - sizeof(*hdr)) { |
419 | pr_warn("Discovery length overflows buffer (%zu+%u)/%u\n", | ||
420 | sizeof(*hdr), hlen, IO_BUFFER_LENGTH); | ||
421 | return -EFAULT; | ||
422 | } | ||
423 | |||
424 | epos += hlen; /* end of buffer */ | ||
418 | cpos += sizeof(*hdr); /* current position on buffer */ | 425 | cpos += sizeof(*hdr); /* current position on buffer */ |
419 | 426 | ||
420 | while (cpos < epos && supported) { | 427 | while (cpos < epos && supported) { |
@@ -784,6 +791,7 @@ static int response_parse(const u8 *buf, size_t length, | |||
784 | int total; | 791 | int total; |
785 | ssize_t token_length; | 792 | ssize_t token_length; |
786 | const u8 *pos; | 793 | const u8 *pos; |
794 | u32 clen, plen, slen; | ||
787 | 795 | ||
788 | if (!buf) | 796 | if (!buf) |
789 | return -EFAULT; | 797 | return -EFAULT; |
@@ -795,17 +803,16 @@ static int response_parse(const u8 *buf, size_t length, | |||
795 | pos = buf; | 803 | pos = buf; |
796 | pos += sizeof(*hdr); | 804 | pos += sizeof(*hdr); |
797 | 805 | ||
798 | pr_debug("Response size: cp: %d, pkt: %d, subpkt: %d\n", | 806 | clen = be32_to_cpu(hdr->cp.length); |
799 | be32_to_cpu(hdr->cp.length), | 807 | plen = be32_to_cpu(hdr->pkt.length); |
800 | be32_to_cpu(hdr->pkt.length), | 808 | slen = be32_to_cpu(hdr->subpkt.length); |
801 | be32_to_cpu(hdr->subpkt.length)); | 809 | pr_debug("Response size: cp: %u, pkt: %u, subpkt: %u\n", |
802 | 810 | clen, plen, slen); | |
803 | if (hdr->cp.length == 0 || hdr->pkt.length == 0 || | 811 | |
804 | hdr->subpkt.length == 0) { | 812 | if (clen == 0 || plen == 0 || slen == 0 || |
805 | pr_err("Bad header length. cp: %d, pkt: %d, subpkt: %d\n", | 813 | slen > IO_BUFFER_LENGTH - sizeof(*hdr)) { |
806 | be32_to_cpu(hdr->cp.length), | 814 | pr_err("Bad header length. cp: %u, pkt: %u, subpkt: %u\n", |
807 | be32_to_cpu(hdr->pkt.length), | 815 | clen, plen, slen); |
808 | be32_to_cpu(hdr->subpkt.length)); | ||
809 | print_buffer(pos, sizeof(*hdr)); | 816 | print_buffer(pos, sizeof(*hdr)); |
810 | return -EINVAL; | 817 | return -EINVAL; |
811 | } | 818 | } |
@@ -814,7 +821,7 @@ static int response_parse(const u8 *buf, size_t length, | |||
814 | return -EFAULT; | 821 | return -EFAULT; |
815 | 822 | ||
816 | iter = resp->toks; | 823 | iter = resp->toks; |
817 | total = be32_to_cpu(hdr->subpkt.length); | 824 | total = slen; |
818 | print_buffer(pos, total); | 825 | print_buffer(pos, total); |
819 | while (total > 0) { | 826 | while (total > 0) { |
820 | if (pos[0] <= TINY_ATOM_BYTE) /* tiny atom */ | 827 | if (pos[0] <= TINY_ATOM_BYTE) /* tiny atom */ |