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/sed-opal.c | |
| 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/sed-opal.c')
| -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 */ |
