qemu/scsi-qemu-pr-helper-Fix-out-of-bounds-ac.patch
Bruce Rogers 22b3f26e04 Accepting request 788690 from home:bfrogers:branches:Virtualization
- Include upstream patches targeted for the next stable release
  (bug fixes only)
  block-Avoid-memleak-on-qcow2-image-info-.patch
  block-bdrv_set_backing_bs-fix-use-after-.patch
  hmp-vnc-Fix-info-vnc-list-leak.patch
  migration-colo-fix-use-after-free-of-loc.patch
  migration-ram-fix-use-after-free-of-loca.patch
  ppc-ppc405_boards-Remove-unnecessary-NUL.patch
  qcow2-List-autoclear-bit-names-in-header.patch
  scsi-qemu-pr-helper-Fix-out-of-bounds-ac.patch
  sheepdog-Consistently-set-bdrv_has_zero_.patch

OBS-URL: https://build.opensuse.org/request/show/788690
OBS-URL: https://build.opensuse.org/package/show/Virtualization/qemu?expand=0&rev=541
2020-03-26 22:01:41 +00:00

94 lines
3.8 KiB
Diff
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

From: Christophe de Dinechin <dinechin@redhat.com>
Date: Fri, 28 Feb 2020 16:00:59 +0100
Subject: scsi/qemu-pr-helper: Fix out-of-bounds access to trnptid_list[]
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
Git-commit: 4ce1e15fbc7266a108a7c77a3962644b3935346e
Compile error reported by gcc 10.0.1:
scsi/qemu-pr-helper.c: In function multipath_pr_out:
scsi/qemu-pr-helper.c:523:32: error: array subscript <unknown> is outside array bounds of struct transportid *[0] [-Werror=array-bounds]
523 | paramp.trnptid_list[paramp.num_transportid++] = id;
| ~~~~~~~~~~~~~~~~~~~^~~~~~~~~~~~~~~~~~~~~~~~~~
In file included from scsi/qemu-pr-helper.c:36:
/usr/include/mpath_persist.h:168:22: note: while referencing trnptid_list
168 | struct transportid *trnptid_list[];
| ^~~~~~~~~~~~
scsi/qemu-pr-helper.c:424:35: note: defined here paramp
424 | struct prout_param_descriptor paramp;
| ^~~~~~
This highlights an actual implementation issue in function multipath_pr_out.
The variable paramp is declared with type `struct prout_param_descriptor`,
which is a struct terminated by an empty array in mpath_persist.h:
struct transportid *trnptid_list[];
That empty array was filled with code that looked like that:
trnptid_list[paramp.descr.num_transportid++] = id;
This is an actual out-of-bounds access.
The fix is to malloc `paramp`.
Signed-off-by: Christophe de Dinechin <dinechin@redhat.com>
Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
Signed-off-by: Bruce Rogers <brogers@suse.com>
---
scsi/qemu-pr-helper.c | 17 ++++++++++-------
1 file changed, 10 insertions(+), 7 deletions(-)
diff --git a/scsi/qemu-pr-helper.c b/scsi/qemu-pr-helper.c
index debb18f4aa5d55a1720587cf82ea..38c273de19573ad8421da6439153 100644
--- a/scsi/qemu-pr-helper.c
+++ b/scsi/qemu-pr-helper.c
@@ -421,10 +421,13 @@ static int multipath_pr_out(int fd, const uint8_t *cdb, uint8_t *sense,
int rq_servact = cdb[1];
int rq_scope = cdb[2] >> 4;
int rq_type = cdb[2] & 0xf;
- struct prout_param_descriptor paramp;
+ g_autofree struct prout_param_descriptor *paramp = NULL;
char transportids[PR_HELPER_DATA_SIZE];
int r;
+ paramp = g_malloc0(sizeof(struct prout_param_descriptor)
+ + sizeof(struct transportid *) * MPATH_MX_TIDS);
+
if (sz < PR_OUT_FIXED_PARAM_SIZE) {
/* Illegal request, Parameter list length error. This isn't fatal;
* we have read the data, send an error without closing the socket.
@@ -454,10 +457,9 @@ static int multipath_pr_out(int fd, const uint8_t *cdb, uint8_t *sense,
* used by libmpathpersist (which, of course, will immediately
* do the opposite).
*/
- memset(&paramp, 0, sizeof(paramp));
- memcpy(&paramp.key, &param[0], 8);
- memcpy(&paramp.sa_key, &param[8], 8);
- paramp.sa_flags = param[20];
+ memcpy(&paramp->key, &param[0], 8);
+ memcpy(&paramp->sa_key, &param[8], 8);
+ paramp->sa_flags = param[20];
if (sz > PR_OUT_FIXED_PARAM_SIZE) {
size_t transportid_len;
int i, j;
@@ -520,12 +522,13 @@ static int multipath_pr_out(int fd, const uint8_t *cdb, uint8_t *sense,
return CHECK_CONDITION;
}
- paramp.trnptid_list[paramp.num_transportid++] = id;
+ assert(paramp->num_transportid < MPATH_MX_TIDS);
+ paramp->trnptid_list[paramp->num_transportid++] = id;
}
}
r = mpath_persistent_reserve_out(fd, rq_servact, rq_scope, rq_type,
- &paramp, noisy, verbose);
+ paramp, noisy, verbose);
return mpath_reconstruct_sense(fd, r, sense);
}
#endif