summaryrefslogtreecommitdiffstats
path: root/block
diff options
context:
space:
mode:
authorJon Derrick <jonathan.derrick@intel.com>2017-02-21 13:59:15 -0500
committerJens Axboe <axboe@fb.com>2017-02-22 13:54:49 -0500
commit77039b96316d119cea23f48b617103d50e78b840 (patch)
treeaa9bef91b061b72beb2252fb325d6ea4bff7d9c8 /block
parentcccb92417d447172c4653876f6cd4b04c29d7905 (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.c35
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 */