* [Qemu-devel] [PATCH v2 0/9] ccid-card-passthru: check buffer size parameter
@ 2019-02-14 20:19 Philippe Mathieu-Daudé
2019-02-14 20:19 ` [Qemu-devel] [PATCH v2 1/9] ccid-card-passthru: Move assertion in read() to can_read() Philippe Mathieu-Daudé
` (8 more replies)
0 siblings, 9 replies; 25+ messages in thread
From: Philippe Mathieu-Daudé @ 2019-02-14 20:19 UTC (permalink / raw)
To: Prasad J Pandit, Marc-André Lureau, qemu-devel, Paolo Bonzini
Cc: Gerd Hoffmann, Philippe Mathieu-Daudé
Hi,
This is the v2 of Prasad J Pandit first version [*], with Paolo's
review comment addressed.
This is a quick fix for CVE-2018-18438: "Integer overflow in
ccid_card_vscard_read() allows memory corruption".
Please review,
Phil.
[*] https://lists.gnu.org/archive/html/qemu-devel/2018-10/msg02200.html
Philippe Mathieu-Daudé (9):
ccid-card-passthru: Move assertion in read() to can_read()
ccid-card-passthru: Replace never trigger if statement by an assertion
ccid-card-passthru: Assert on a stricter expression
ccid-card-passthru: Let the chardev::read() be more generic
ccid-card-passthru: Replace assert() by QEMU_BUILD_BUG_ON()
ccid-card-passthru: Simplify the if() condition
ccid-card-passthru: Use QERR_MISSING_PARAMETER
ccid-card-passthru: Use size_t to hold size argument
ccid-card-passthru: Use size_t for index
hw/usb/ccid-card-passthru.c | 73 +++++++++++++++++--------------------
1 file changed, 34 insertions(+), 39 deletions(-)
--
2.20.1
^ permalink raw reply [flat|nested] 25+ messages in thread
* [Qemu-devel] [PATCH v2 1/9] ccid-card-passthru: Move assertion in read() to can_read()
2019-02-14 20:19 [Qemu-devel] [PATCH v2 0/9] ccid-card-passthru: check buffer size parameter Philippe Mathieu-Daudé
@ 2019-02-14 20:19 ` Philippe Mathieu-Daudé
2019-02-14 21:18 ` Eric Blake
` (2 more replies)
2019-02-14 20:19 ` [Qemu-devel] [PATCH v2 2/9] ccid-card-passthru: Replace never trigger if statement by an assertion Philippe Mathieu-Daudé
` (7 subsequent siblings)
8 siblings, 3 replies; 25+ messages in thread
From: Philippe Mathieu-Daudé @ 2019-02-14 20:19 UTC (permalink / raw)
To: Prasad J Pandit, Marc-André Lureau, qemu-devel, Paolo Bonzini
Cc: Gerd Hoffmann, Philippe Mathieu-Daudé
chardev::read() depends of what chardev::can_read() returns, move the
assertion to can_read().
Suggested-by: Paolo Bonzini <pbonzini@redhat.com>
Signed-off-by: Philippe Mathieu-Daudé <philmd@redhat.com>
---
hw/usb/ccid-card-passthru.c | 5 ++---
1 file changed, 2 insertions(+), 3 deletions(-)
diff --git a/hw/usb/ccid-card-passthru.c b/hw/usb/ccid-card-passthru.c
index 0a6c657228..8bb1314f49 100644
--- a/hw/usb/ccid-card-passthru.c
+++ b/hw/usb/ccid-card-passthru.c
@@ -116,8 +116,8 @@ static int ccid_card_vscard_can_read(void *opaque)
{
PassthruState *card = opaque;
- return VSCARD_IN_SIZE >= card->vscard_in_pos ?
- VSCARD_IN_SIZE - card->vscard_in_pos : 0;
+ assert(card->vscard_in_pos <= VSCARD_IN_SIZE);
+ return VSCARD_IN_SIZE - card->vscard_in_pos;
}
static void ccid_card_vscard_handle_init(
@@ -282,7 +282,6 @@ static void ccid_card_vscard_read(void *opaque, const uint8_t *buf, int size)
ccid_card_vscard_drop_connection(card);
return;
}
- assert(card->vscard_in_pos < VSCARD_IN_SIZE);
assert(card->vscard_in_hdr < VSCARD_IN_SIZE);
memcpy(card->vscard_in_data + card->vscard_in_pos, buf, size);
card->vscard_in_pos += size;
--
2.20.1
^ permalink raw reply related [flat|nested] 25+ messages in thread
* [Qemu-devel] [PATCH v2 2/9] ccid-card-passthru: Replace never trigger if statement by an assertion
2019-02-14 20:19 [Qemu-devel] [PATCH v2 0/9] ccid-card-passthru: check buffer size parameter Philippe Mathieu-Daudé
2019-02-14 20:19 ` [Qemu-devel] [PATCH v2 1/9] ccid-card-passthru: Move assertion in read() to can_read() Philippe Mathieu-Daudé
@ 2019-02-14 20:19 ` Philippe Mathieu-Daudé
2019-02-15 10:59 ` Marc-André Lureau
2019-02-14 20:19 ` [Qemu-devel] [PATCH v2 3/9] ccid-card-passthru: Assert on a stricter expression Philippe Mathieu-Daudé
` (6 subsequent siblings)
8 siblings, 1 reply; 25+ messages in thread
From: Philippe Mathieu-Daudé @ 2019-02-14 20:19 UTC (permalink / raw)
To: Prasad J Pandit, Marc-André Lureau, qemu-devel, Paolo Bonzini
Cc: Gerd Hoffmann, Philippe Mathieu-Daudé, Arash Tohidi Chafi
The right side of the comparison is the return value of can_read():
VSCARD_IN_SIZE - card->vscard_in_pos.
Since the 'size' argument of chardev::read() is bound to
what chardev::can_read() returns, this condition can never happen.
Add an assertion, which will always fail if card->vscard_in_pos >=
VSCARD_IN_SIZE), since size > 0.
This is a quick fix for CVE-2018-18438 "Integer overflow in
ccid_card_vscard_read() allows memory corruption".
Fixes: CVE-2018-18438
Reported-by: Arash Tohidi Chafi <tohidi.arash@gmail.com>
Suggested-by: Paolo Bonzini <pbonzini@redhat.com>
Signed-off-by: Philippe Mathieu-Daudé <philmd@redhat.com>
---
hw/usb/ccid-card-passthru.c | 14 +-------------
1 file changed, 1 insertion(+), 13 deletions(-)
diff --git a/hw/usb/ccid-card-passthru.c b/hw/usb/ccid-card-passthru.c
index 8bb1314f49..1676b5fc05 100644
--- a/hw/usb/ccid-card-passthru.c
+++ b/hw/usb/ccid-card-passthru.c
@@ -264,24 +264,12 @@ static void ccid_card_vscard_handle_message(PassthruState *card,
}
}
-static void ccid_card_vscard_drop_connection(PassthruState *card)
-{
- qemu_chr_fe_deinit(&card->cs, true);
- card->vscard_in_pos = card->vscard_in_hdr = 0;
-}
-
static void ccid_card_vscard_read(void *opaque, const uint8_t *buf, int size)
{
PassthruState *card = opaque;
VSCMsgHeader *hdr;
- if (card->vscard_in_pos + size > VSCARD_IN_SIZE) {
- error_report("no room for data: pos %u + size %d > %" PRId64 "."
- " dropping connection.",
- card->vscard_in_pos, size, VSCARD_IN_SIZE);
- ccid_card_vscard_drop_connection(card);
- return;
- }
+ assert(size <= VSCARD_IN_SIZE - card->vscard_in_pos);
assert(card->vscard_in_hdr < VSCARD_IN_SIZE);
memcpy(card->vscard_in_data + card->vscard_in_pos, buf, size);
card->vscard_in_pos += size;
--
2.20.1
^ permalink raw reply related [flat|nested] 25+ messages in thread
* [Qemu-devel] [PATCH v2 3/9] ccid-card-passthru: Assert on a stricter expression
2019-02-14 20:19 [Qemu-devel] [PATCH v2 0/9] ccid-card-passthru: check buffer size parameter Philippe Mathieu-Daudé
2019-02-14 20:19 ` [Qemu-devel] [PATCH v2 1/9] ccid-card-passthru: Move assertion in read() to can_read() Philippe Mathieu-Daudé
2019-02-14 20:19 ` [Qemu-devel] [PATCH v2 2/9] ccid-card-passthru: Replace never trigger if statement by an assertion Philippe Mathieu-Daudé
@ 2019-02-14 20:19 ` Philippe Mathieu-Daudé
2019-02-15 8:47 ` Wei Yang
2019-02-15 11:15 ` Marc-André Lureau
2019-02-14 20:19 ` [Qemu-devel] [PATCH v2 4/9] ccid-card-passthru: Let the chardev::read() be more generic Philippe Mathieu-Daudé
` (5 subsequent siblings)
8 siblings, 2 replies; 25+ messages in thread
From: Philippe Mathieu-Daudé @ 2019-02-14 20:19 UTC (permalink / raw)
To: Prasad J Pandit, Marc-André Lureau, qemu-devel, Paolo Bonzini
Cc: Gerd Hoffmann, Philippe Mathieu-Daudé
Suggested-by: Paolo Bonzini <pbonzini@redhat.com>
Signed-off-by: Philippe Mathieu-Daudé <philmd@redhat.com>
---
hw/usb/ccid-card-passthru.c | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/hw/usb/ccid-card-passthru.c b/hw/usb/ccid-card-passthru.c
index 1676b5fc05..0c44b38fc2 100644
--- a/hw/usb/ccid-card-passthru.c
+++ b/hw/usb/ccid-card-passthru.c
@@ -270,7 +270,7 @@ static void ccid_card_vscard_read(void *opaque, const uint8_t *buf, int size)
VSCMsgHeader *hdr;
assert(size <= VSCARD_IN_SIZE - card->vscard_in_pos);
- assert(card->vscard_in_hdr < VSCARD_IN_SIZE);
+ assert(card->vscard_in_hdr < card->vscard_in_pos);
memcpy(card->vscard_in_data + card->vscard_in_pos, buf, size);
card->vscard_in_pos += size;
hdr = (VSCMsgHeader *)(card->vscard_in_data + card->vscard_in_hdr);
--
2.20.1
^ permalink raw reply related [flat|nested] 25+ messages in thread
* [Qemu-devel] [PATCH v2 4/9] ccid-card-passthru: Let the chardev::read() be more generic
2019-02-14 20:19 [Qemu-devel] [PATCH v2 0/9] ccid-card-passthru: check buffer size parameter Philippe Mathieu-Daudé
` (2 preceding siblings ...)
2019-02-14 20:19 ` [Qemu-devel] [PATCH v2 3/9] ccid-card-passthru: Assert on a stricter expression Philippe Mathieu-Daudé
@ 2019-02-14 20:19 ` Philippe Mathieu-Daudé
2019-02-15 11:43 ` Marc-André Lureau
2019-02-14 20:19 ` [Qemu-devel] [PATCH v2 5/9] ccid-card-passthru: Replace assert() by QEMU_BUILD_BUG_ON() Philippe Mathieu-Daudé
` (4 subsequent siblings)
8 siblings, 1 reply; 25+ messages in thread
From: Philippe Mathieu-Daudé @ 2019-02-14 20:19 UTC (permalink / raw)
To: Prasad J Pandit, Marc-André Lureau, qemu-devel, Paolo Bonzini
Cc: Gerd Hoffmann, Philippe Mathieu-Daudé
Suggested-by: Paolo Bonzini <pbonzini@redhat.com>
Signed-off-by: Philippe Mathieu-Daudé <philmd@redhat.com>
---
hw/usb/ccid-card-passthru.c | 10 ++++++++--
1 file changed, 8 insertions(+), 2 deletions(-)
diff --git a/hw/usb/ccid-card-passthru.c b/hw/usb/ccid-card-passthru.c
index 0c44b38fc2..ba7c285ded 100644
--- a/hw/usb/ccid-card-passthru.c
+++ b/hw/usb/ccid-card-passthru.c
@@ -285,8 +285,14 @@ static void ccid_card_vscard_read(void *opaque, const uint8_t *buf, int size)
card->vscard_in_hdr += hdr->length + sizeof(VSCMsgHeader);
hdr = (VSCMsgHeader *)(card->vscard_in_data + card->vscard_in_hdr);
}
- if (card->vscard_in_hdr == card->vscard_in_pos) {
- card->vscard_in_pos = card->vscard_in_hdr = 0;
+
+ /* Drop any messages that were fully processed. */
+ if (card->vscard_in_hdr > 0) {
+ memmove(card->vscard_in_data,
+ card->vscard_in_data + card->vscard_in_hdr,
+ card->vscard_in_pos - card->vscard_in_hdr);
+ card->vscard_in_pos -= card->vscard_in_hdr;
+ card->vscard_in_hdr = 0;
}
}
--
2.20.1
^ permalink raw reply related [flat|nested] 25+ messages in thread
* [Qemu-devel] [PATCH v2 5/9] ccid-card-passthru: Replace assert() by QEMU_BUILD_BUG_ON()
2019-02-14 20:19 [Qemu-devel] [PATCH v2 0/9] ccid-card-passthru: check buffer size parameter Philippe Mathieu-Daudé
` (3 preceding siblings ...)
2019-02-14 20:19 ` [Qemu-devel] [PATCH v2 4/9] ccid-card-passthru: Let the chardev::read() be more generic Philippe Mathieu-Daudé
@ 2019-02-14 20:19 ` Philippe Mathieu-Daudé
2019-02-15 11:44 ` Marc-André Lureau
2019-02-14 20:19 ` [Qemu-devel] [PATCH v2 6/9] ccid-card-passthru: Simplify the if() condition Philippe Mathieu-Daudé
` (3 subsequent siblings)
8 siblings, 1 reply; 25+ messages in thread
From: Philippe Mathieu-Daudé @ 2019-02-14 20:19 UTC (permalink / raw)
To: Prasad J Pandit, Marc-André Lureau, qemu-devel, Paolo Bonzini
Cc: Gerd Hoffmann, Philippe Mathieu-Daudé
Signed-off-by: Philippe Mathieu-Daudé <philmd@redhat.com>
---
hw/usb/ccid-card-passthru.c | 9 +++++----
1 file changed, 5 insertions(+), 4 deletions(-)
diff --git a/hw/usb/ccid-card-passthru.c b/hw/usb/ccid-card-passthru.c
index ba7c285ded..ccc3ffa7fa 100644
--- a/hw/usb/ccid-card-passthru.c
+++ b/hw/usb/ccid-card-passthru.c
@@ -29,6 +29,9 @@ do { \
#define D_MORE_INFO 3
#define D_VERBOSE 4
+/* maximum size of ATR - from 7816-3 */
+#define MAX_ATR_SIZE 40
+
/* TODO: do we still need this? */
static const uint8_t DEFAULT_ATR[] = {
/*
@@ -41,10 +44,9 @@ static const uint8_t DEFAULT_ATR[] = {
0x13, 0x08
};
-#define VSCARD_IN_SIZE (64 * KiB)
+QEMU_BUILD_BUG_ON(sizeof(DEFAULT_ATR) > MAX_ATR_SIZE);
-/* maximum size of ATR - from 7816-3 */
-#define MAX_ATR_SIZE 40
+#define VSCARD_IN_SIZE (64 * KiB)
typedef struct PassthruState PassthruState;
@@ -351,7 +353,6 @@ static void passthru_realize(CCIDCardState *base, Error **errp)
}
card->debug = parse_debug_env("QEMU_CCID_PASSTHRU_DEBUG", D_VERBOSE,
card->debug);
- assert(sizeof(DEFAULT_ATR) <= MAX_ATR_SIZE);
memcpy(card->atr, DEFAULT_ATR, sizeof(DEFAULT_ATR));
card->atr_length = sizeof(DEFAULT_ATR);
}
--
2.20.1
^ permalink raw reply related [flat|nested] 25+ messages in thread
* [Qemu-devel] [PATCH v2 6/9] ccid-card-passthru: Simplify the if() condition
2019-02-14 20:19 [Qemu-devel] [PATCH v2 0/9] ccid-card-passthru: check buffer size parameter Philippe Mathieu-Daudé
` (4 preceding siblings ...)
2019-02-14 20:19 ` [Qemu-devel] [PATCH v2 5/9] ccid-card-passthru: Replace assert() by QEMU_BUILD_BUG_ON() Philippe Mathieu-Daudé
@ 2019-02-14 20:19 ` Philippe Mathieu-Daudé
2019-02-15 11:49 ` Marc-André Lureau
2019-02-14 20:19 ` [Qemu-devel] [PATCH v2 7/9] ccid-card-passthru: Use QERR_MISSING_PARAMETER Philippe Mathieu-Daudé
` (2 subsequent siblings)
8 siblings, 1 reply; 25+ messages in thread
From: Philippe Mathieu-Daudé @ 2019-02-14 20:19 UTC (permalink / raw)
To: Prasad J Pandit, Marc-André Lureau, qemu-devel, Paolo Bonzini
Cc: Gerd Hoffmann, Philippe Mathieu-Daudé
Simplify the if() condition so we can remove an indent layer
and the code is easier to review.
Signed-off-by: Philippe Mathieu-Daudé <philmd@redhat.com>
---
hw/usb/ccid-card-passthru.c | 18 ++++++++----------
1 file changed, 8 insertions(+), 10 deletions(-)
diff --git a/hw/usb/ccid-card-passthru.c b/hw/usb/ccid-card-passthru.c
index ccc3ffa7fa..6cb8b2d26b 100644
--- a/hw/usb/ccid-card-passthru.c
+++ b/hw/usb/ccid-card-passthru.c
@@ -338,19 +338,17 @@ static void passthru_realize(CCIDCardState *base, Error **errp)
{
PassthruState *card = PASSTHRU_CCID_CARD(base);
- card->vscard_in_pos = 0;
- card->vscard_in_hdr = 0;
- if (qemu_chr_fe_backend_connected(&card->cs)) {
- DPRINTF(card, D_INFO, "ccid-card-passthru: initing chardev");
- qemu_chr_fe_set_handlers(&card->cs,
- ccid_card_vscard_can_read,
- ccid_card_vscard_read,
- ccid_card_vscard_event, NULL, card, NULL, true);
- ccid_card_vscard_send_init(card);
- } else {
+ if (!qemu_chr_fe_backend_connected(&card->cs)) {
error_setg(errp, "missing chardev");
return;
}
+ card->vscard_in_pos = 0;
+ card->vscard_in_hdr = 0;
+ DPRINTF(card, D_INFO, "ccid-card-passthru: initing chardev");
+ qemu_chr_fe_set_handlers(&card->cs, ccid_card_vscard_can_read,
+ ccid_card_vscard_read, ccid_card_vscard_event,
+ NULL, card, NULL, true);
+ ccid_card_vscard_send_init(card);
card->debug = parse_debug_env("QEMU_CCID_PASSTHRU_DEBUG", D_VERBOSE,
card->debug);
memcpy(card->atr, DEFAULT_ATR, sizeof(DEFAULT_ATR));
--
2.20.1
^ permalink raw reply related [flat|nested] 25+ messages in thread
* [Qemu-devel] [PATCH v2 7/9] ccid-card-passthru: Use QERR_MISSING_PARAMETER
2019-02-14 20:19 [Qemu-devel] [PATCH v2 0/9] ccid-card-passthru: check buffer size parameter Philippe Mathieu-Daudé
` (5 preceding siblings ...)
2019-02-14 20:19 ` [Qemu-devel] [PATCH v2 6/9] ccid-card-passthru: Simplify the if() condition Philippe Mathieu-Daudé
@ 2019-02-14 20:19 ` Philippe Mathieu-Daudé
2019-02-14 21:22 ` Eric Blake
2019-02-14 20:19 ` [Qemu-devel] [PATCH v2 8/9] ccid-card-passthru: Use size_t to hold size argument Philippe Mathieu-Daudé
2019-02-14 20:19 ` [Qemu-devel] [PATCH v2 9/9] ccid-card-passthru: Use size_t for index Philippe Mathieu-Daudé
8 siblings, 1 reply; 25+ messages in thread
From: Philippe Mathieu-Daudé @ 2019-02-14 20:19 UTC (permalink / raw)
To: Prasad J Pandit, Marc-André Lureau, qemu-devel, Paolo Bonzini
Cc: Gerd Hoffmann, Philippe Mathieu-Daudé
Signed-off-by: Philippe Mathieu-Daudé <philmd@redhat.com>
---
hw/usb/ccid-card-passthru.c | 3 ++-
1 file changed, 2 insertions(+), 1 deletion(-)
diff --git a/hw/usb/ccid-card-passthru.c b/hw/usb/ccid-card-passthru.c
index 6cb8b2d26b..d63aa28584 100644
--- a/hw/usb/ccid-card-passthru.c
+++ b/hw/usb/ccid-card-passthru.c
@@ -16,6 +16,7 @@
#include "qemu/sockets.h"
#include "ccid.h"
#include "qapi/error.h"
+#include "qapi/qmp/qerror.h"
#define DPRINTF(card, lvl, fmt, ...) \
do { \
@@ -339,7 +340,7 @@ static void passthru_realize(CCIDCardState *base, Error **errp)
PassthruState *card = PASSTHRU_CCID_CARD(base);
if (!qemu_chr_fe_backend_connected(&card->cs)) {
- error_setg(errp, "missing chardev");
+ error_setg(errp, QERR_MISSING_PARAMETER, "chardev");
return;
}
card->vscard_in_pos = 0;
--
2.20.1
^ permalink raw reply related [flat|nested] 25+ messages in thread
* [Qemu-devel] [PATCH v2 8/9] ccid-card-passthru: Use size_t to hold size argument
2019-02-14 20:19 [Qemu-devel] [PATCH v2 0/9] ccid-card-passthru: check buffer size parameter Philippe Mathieu-Daudé
` (6 preceding siblings ...)
2019-02-14 20:19 ` [Qemu-devel] [PATCH v2 7/9] ccid-card-passthru: Use QERR_MISSING_PARAMETER Philippe Mathieu-Daudé
@ 2019-02-14 20:19 ` Philippe Mathieu-Daudé
2019-02-15 11:51 ` Marc-André Lureau
2019-02-14 20:19 ` [Qemu-devel] [PATCH v2 9/9] ccid-card-passthru: Use size_t for index Philippe Mathieu-Daudé
8 siblings, 1 reply; 25+ messages in thread
From: Philippe Mathieu-Daudé @ 2019-02-14 20:19 UTC (permalink / raw)
To: Prasad J Pandit, Marc-André Lureau, qemu-devel, Paolo Bonzini
Cc: Gerd Hoffmann, Philippe Mathieu-Daudé
check_atr() is called once with a unsigned argument.
Since there is no need to use a signed type, use a size_t.
Signed-off-by: Philippe Mathieu-Daudé <philmd@redhat.com>
---
hw/usb/ccid-card-passthru.c | 11 ++++++-----
1 file changed, 6 insertions(+), 5 deletions(-)
diff --git a/hw/usb/ccid-card-passthru.c b/hw/usb/ccid-card-passthru.c
index d63aa28584..083eb5ca08 100644
--- a/hw/usb/ccid-card-passthru.c
+++ b/hw/usb/ccid-card-passthru.c
@@ -149,9 +149,10 @@ static void ccid_card_vscard_handle_init(
ccid_card_vscard_send_init(card);
}
-static int check_atr(PassthruState *card, uint8_t *data, int len)
+static int check_atr(PassthruState *card, uint8_t *data, size_t len)
{
- int historical_length, opt_bytes;
+ size_t historical_length;
+ int opt_bytes;
int td_count = 0;
int td;
@@ -185,18 +186,18 @@ static int check_atr(PassthruState *card, uint8_t *data, int len)
}
if (len < 2 + historical_length + opt_bytes) {
DPRINTF(card, D_WARN,
- "atr too short: len %d, but historical_len %d, T1 0x%X\n",
+ "atr too short: len %zu, but historical_len %zu, T1 0x%X\n",
len, historical_length, data[1]);
return 0;
}
if (len > 2 + historical_length + opt_bytes) {
DPRINTF(card, D_WARN,
- "atr too long: len %d, but hist/opt %d/%d, T1 0x%X\n",
+ "atr too long: len %zu, but hist/opt %zu/%d, T1 0x%X\n",
len, historical_length, opt_bytes, data[1]);
/* let it through */
}
DPRINTF(card, D_VERBOSE,
- "atr passes check: %d total length, %d historical, %d optional\n",
+ "atr passes check: %zu total length, %zu historical, %d optional\n",
len, historical_length, opt_bytes);
return 1;
--
2.20.1
^ permalink raw reply related [flat|nested] 25+ messages in thread
* [Qemu-devel] [PATCH v2 9/9] ccid-card-passthru: Use size_t for index
2019-02-14 20:19 [Qemu-devel] [PATCH v2 0/9] ccid-card-passthru: check buffer size parameter Philippe Mathieu-Daudé
` (7 preceding siblings ...)
2019-02-14 20:19 ` [Qemu-devel] [PATCH v2 8/9] ccid-card-passthru: Use size_t to hold size argument Philippe Mathieu-Daudé
@ 2019-02-14 20:19 ` Philippe Mathieu-Daudé
2019-02-15 11:52 ` Marc-André Lureau
8 siblings, 1 reply; 25+ messages in thread
From: Philippe Mathieu-Daudé @ 2019-02-14 20:19 UTC (permalink / raw)
To: Prasad J Pandit, Marc-André Lureau, qemu-devel, Paolo Bonzini
Cc: Gerd Hoffmann, Philippe Mathieu-Daudé
The variable 'opt_bytes' is an index to the data[] array.
Use size_t for indexes.
Signed-off-by: Philippe Mathieu-Daudé <philmd@redhat.com>
---
hw/usb/ccid-card-passthru.c | 7 ++++---
1 file changed, 4 insertions(+), 3 deletions(-)
diff --git a/hw/usb/ccid-card-passthru.c b/hw/usb/ccid-card-passthru.c
index 083eb5ca08..664e8a1b54 100644
--- a/hw/usb/ccid-card-passthru.c
+++ b/hw/usb/ccid-card-passthru.c
@@ -152,7 +152,7 @@ static void ccid_card_vscard_handle_init(
static int check_atr(PassthruState *card, uint8_t *data, size_t len)
{
size_t historical_length;
- int opt_bytes;
+ size_t opt_bytes;
int td_count = 0;
int td;
@@ -192,12 +192,13 @@ static int check_atr(PassthruState *card, uint8_t *data, size_t len)
}
if (len > 2 + historical_length + opt_bytes) {
DPRINTF(card, D_WARN,
- "atr too long: len %zu, but hist/opt %zu/%d, T1 0x%X\n",
+ "atr too long: len %zu, but hist/opt %zu/%zu, T1 0x%X\n",
len, historical_length, opt_bytes, data[1]);
/* let it through */
}
DPRINTF(card, D_VERBOSE,
- "atr passes check: %zu total length, %zu historical, %d optional\n",
+ "atr passes check: %zu total length,"
+ " %zu historical, %zu optional\n",
len, historical_length, opt_bytes);
return 1;
--
2.20.1
^ permalink raw reply related [flat|nested] 25+ messages in thread
* Re: [Qemu-devel] [PATCH v2 1/9] ccid-card-passthru: Move assertion in read() to can_read()
2019-02-14 20:19 ` [Qemu-devel] [PATCH v2 1/9] ccid-card-passthru: Move assertion in read() to can_read() Philippe Mathieu-Daudé
@ 2019-02-14 21:18 ` Eric Blake
2019-02-15 8:44 ` Wei Yang
2019-02-15 11:02 ` Marc-André Lureau
2 siblings, 0 replies; 25+ messages in thread
From: Eric Blake @ 2019-02-14 21:18 UTC (permalink / raw)
To: Philippe Mathieu-Daudé,
Prasad J Pandit, Marc-André Lureau, qemu-devel,
Paolo Bonzini
Cc: Gerd Hoffmann
[-- Attachment #1: Type: text/plain, Size: 521 bytes --]
On 2/14/19 2:19 PM, Philippe Mathieu-Daudé wrote:
> chardev::read() depends of what chardev::can_read() returns, move the
s/of/on/
> assertion to can_read().
>
> Suggested-by: Paolo Bonzini <pbonzini@redhat.com>
> Signed-off-by: Philippe Mathieu-Daudé <philmd@redhat.com>
> ---
> hw/usb/ccid-card-passthru.c | 5 ++---
> 1 file changed, 2 insertions(+), 3 deletions(-)
>
--
Eric Blake, Principal Software Engineer
Red Hat, Inc. +1-919-301-3226
Virtualization: qemu.org | libvirt.org
[-- Attachment #2: OpenPGP digital signature --]
[-- Type: application/pgp-signature, Size: 488 bytes --]
^ permalink raw reply [flat|nested] 25+ messages in thread
* Re: [Qemu-devel] [PATCH v2 7/9] ccid-card-passthru: Use QERR_MISSING_PARAMETER
2019-02-14 20:19 ` [Qemu-devel] [PATCH v2 7/9] ccid-card-passthru: Use QERR_MISSING_PARAMETER Philippe Mathieu-Daudé
@ 2019-02-14 21:22 ` Eric Blake
0 siblings, 0 replies; 25+ messages in thread
From: Eric Blake @ 2019-02-14 21:22 UTC (permalink / raw)
To: Philippe Mathieu-Daudé,
Prasad J Pandit, Marc-André Lureau, qemu-devel,
Paolo Bonzini
Cc: Gerd Hoffmann, Markus Armbruster
[-- Attachment #1: Type: text/plain, Size: 1358 bytes --]
On 2/14/19 2:19 PM, Philippe Mathieu-Daudé wrote:
> Signed-off-by: Philippe Mathieu-Daudé <philmd@redhat.com>
> ---
> hw/usb/ccid-card-passthru.c | 3 ++-
> 1 file changed, 2 insertions(+), 1 deletion(-)
>
> diff --git a/hw/usb/ccid-card-passthru.c b/hw/usb/ccid-card-passthru.c
> index 6cb8b2d26b..d63aa28584 100644
> --- a/hw/usb/ccid-card-passthru.c
> +++ b/hw/usb/ccid-card-passthru.c
> @@ -16,6 +16,7 @@
> #include "qemu/sockets.h"
> #include "ccid.h"
> #include "qapi/error.h"
> +#include "qapi/qmp/qerror.h"
>
> #define DPRINTF(card, lvl, fmt, ...) \
> do { \
> @@ -339,7 +340,7 @@ static void passthru_realize(CCIDCardState *base, Error **errp)
> PassthruState *card = PASSTHRU_CCID_CARD(base);
>
> if (!qemu_chr_fe_backend_connected(&card->cs)) {
> - error_setg(errp, "missing chardev");
> + error_setg(errp, QERR_MISSING_PARAMETER, "chardev");
We're trying to get rid of QERR_ usage, not add more. But this
particular one seems to be a wash:
$ git grep '"missing ' | wc -l
24
$ git grep QERR_MISSING_P | wc -l
25
so I'd be interested if Markus has an opinion on this one.
--
Eric Blake, Principal Software Engineer
Red Hat, Inc. +1-919-301-3226
Virtualization: qemu.org | libvirt.org
[-- Attachment #2: OpenPGP digital signature --]
[-- Type: application/pgp-signature, Size: 488 bytes --]
^ permalink raw reply [flat|nested] 25+ messages in thread
* Re: [Qemu-devel] [PATCH v2 1/9] ccid-card-passthru: Move assertion in read() to can_read()
2019-02-14 20:19 ` [Qemu-devel] [PATCH v2 1/9] ccid-card-passthru: Move assertion in read() to can_read() Philippe Mathieu-Daudé
2019-02-14 21:18 ` Eric Blake
@ 2019-02-15 8:44 ` Wei Yang
2019-02-15 11:02 ` Marc-André Lureau
2 siblings, 0 replies; 25+ messages in thread
From: Wei Yang @ 2019-02-15 8:44 UTC (permalink / raw)
To: Philippe Mathieu-Daudé
Cc: Prasad J Pandit, Marc-André Lureau, qemu-devel,
Paolo Bonzini, Gerd Hoffmann
On Thu, Feb 14, 2019 at 09:19:31PM +0100, Philippe Mathieu-Daudé wrote:
>chardev::read() depends of what chardev::can_read() returns, move the
>assertion to can_read().
>
>Suggested-by: Paolo Bonzini <pbonzini@redhat.com>
>Signed-off-by: Philippe Mathieu-Daudé <philmd@redhat.com>
>---
> hw/usb/ccid-card-passthru.c | 5 ++---
> 1 file changed, 2 insertions(+), 3 deletions(-)
>
>diff --git a/hw/usb/ccid-card-passthru.c b/hw/usb/ccid-card-passthru.c
>index 0a6c657228..8bb1314f49 100644
>--- a/hw/usb/ccid-card-passthru.c
>+++ b/hw/usb/ccid-card-passthru.c
>@@ -116,8 +116,8 @@ static int ccid_card_vscard_can_read(void *opaque)
> {
> PassthruState *card = opaque;
>
>- return VSCARD_IN_SIZE >= card->vscard_in_pos ?
>- VSCARD_IN_SIZE - card->vscard_in_pos : 0;
>+ assert(card->vscard_in_pos <= VSCARD_IN_SIZE);
Do you have special reason change "<" to "<="?
>+ return VSCARD_IN_SIZE - card->vscard_in_pos;
> }
>
> static void ccid_card_vscard_handle_init(
>@@ -282,7 +282,6 @@ static void ccid_card_vscard_read(void *opaque, const uint8_t *buf, int size)
> ccid_card_vscard_drop_connection(card);
> return;
> }
>- assert(card->vscard_in_pos < VSCARD_IN_SIZE);
> assert(card->vscard_in_hdr < VSCARD_IN_SIZE);
> memcpy(card->vscard_in_data + card->vscard_in_pos, buf, size);
> card->vscard_in_pos += size;
>--
>2.20.1
>
--
Wei Yang
Help you, Help me
^ permalink raw reply [flat|nested] 25+ messages in thread
* Re: [Qemu-devel] [PATCH v2 3/9] ccid-card-passthru: Assert on a stricter expression
2019-02-14 20:19 ` [Qemu-devel] [PATCH v2 3/9] ccid-card-passthru: Assert on a stricter expression Philippe Mathieu-Daudé
@ 2019-02-15 8:47 ` Wei Yang
2019-02-15 11:15 ` Marc-André Lureau
1 sibling, 0 replies; 25+ messages in thread
From: Wei Yang @ 2019-02-15 8:47 UTC (permalink / raw)
To: Philippe Mathieu-Daudé
Cc: Prasad J Pandit, Marc-André Lureau, qemu-devel,
Paolo Bonzini, Gerd Hoffmann
Would it be better to have some description?
On Thu, Feb 14, 2019 at 09:19:33PM +0100, Philippe Mathieu-Daudé wrote:
>Suggested-by: Paolo Bonzini <pbonzini@redhat.com>
>Signed-off-by: Philippe Mathieu-Daudé <philmd@redhat.com>
>---
> hw/usb/ccid-card-passthru.c | 2 +-
> 1 file changed, 1 insertion(+), 1 deletion(-)
>
>diff --git a/hw/usb/ccid-card-passthru.c b/hw/usb/ccid-card-passthru.c
>index 1676b5fc05..0c44b38fc2 100644
>--- a/hw/usb/ccid-card-passthru.c
>+++ b/hw/usb/ccid-card-passthru.c
>@@ -270,7 +270,7 @@ static void ccid_card_vscard_read(void *opaque, const uint8_t *buf, int size)
> VSCMsgHeader *hdr;
>
> assert(size <= VSCARD_IN_SIZE - card->vscard_in_pos);
>- assert(card->vscard_in_hdr < VSCARD_IN_SIZE);
>+ assert(card->vscard_in_hdr < card->vscard_in_pos);
> memcpy(card->vscard_in_data + card->vscard_in_pos, buf, size);
> card->vscard_in_pos += size;
> hdr = (VSCMsgHeader *)(card->vscard_in_data + card->vscard_in_hdr);
>--
>2.20.1
>
--
Wei Yang
Help you, Help me
^ permalink raw reply [flat|nested] 25+ messages in thread
* Re: [Qemu-devel] [PATCH v2 2/9] ccid-card-passthru: Replace never trigger if statement by an assertion
2019-02-14 20:19 ` [Qemu-devel] [PATCH v2 2/9] ccid-card-passthru: Replace never trigger if statement by an assertion Philippe Mathieu-Daudé
@ 2019-02-15 10:59 ` Marc-André Lureau
2019-02-18 22:10 ` Philippe Mathieu-Daudé
0 siblings, 1 reply; 25+ messages in thread
From: Marc-André Lureau @ 2019-02-15 10:59 UTC (permalink / raw)
To: Philippe Mathieu-Daudé
Cc: Prasad J Pandit, qemu-devel, Paolo Bonzini, Gerd Hoffmann,
Arash Tohidi Chafi
Hi
On Thu, Feb 14, 2019 at 9:20 PM Philippe Mathieu-Daudé
<philmd@redhat.com> wrote:
>
> The right side of the comparison is the return value of can_read():
> VSCARD_IN_SIZE - card->vscard_in_pos.
> Since the 'size' argument of chardev::read() is bound to
> what chardev::can_read() returns, this condition can never happen.
I think so too, because vscard_in_pos is unchanged between the 2
callbacks (or set to 0 in break event).
>
> Add an assertion, which will always fail if card->vscard_in_pos >=
> VSCARD_IN_SIZE), since size > 0.
If "size > VSCARD_IN_SIZE - card->vscard_in_pos" this is a chardev
bug. But which backend does that?
Iow, did we ever reach the "no room for data" error?
>
> This is a quick fix for CVE-2018-18438 "Integer overflow in
> ccid_card_vscard_read() allows memory corruption".
I have a hard time to find how that memory corruption can happen. It
would be a broken chardev (one calling qemu_chr_be_write() with a size
bigger than qemu_chr_be_can_write()). It would need to be fixed. But
which one does that?
>
> Fixes: CVE-2018-18438
> Reported-by: Arash Tohidi Chafi <tohidi.arash@gmail.com>
> Suggested-by: Paolo Bonzini <pbonzini@redhat.com>
> Signed-off-by: Philippe Mathieu-Daudé <philmd@redhat.com>
> ---
> hw/usb/ccid-card-passthru.c | 14 +-------------
> 1 file changed, 1 insertion(+), 13 deletions(-)
>
> diff --git a/hw/usb/ccid-card-passthru.c b/hw/usb/ccid-card-passthru.c
> index 8bb1314f49..1676b5fc05 100644
> --- a/hw/usb/ccid-card-passthru.c
> +++ b/hw/usb/ccid-card-passthru.c
> @@ -264,24 +264,12 @@ static void ccid_card_vscard_handle_message(PassthruState *card,
> }
> }
>
> -static void ccid_card_vscard_drop_connection(PassthruState *card)
> -{
> - qemu_chr_fe_deinit(&card->cs, true);
> - card->vscard_in_pos = card->vscard_in_hdr = 0;
> -}
> -
> static void ccid_card_vscard_read(void *opaque, const uint8_t *buf, int size)
> {
> PassthruState *card = opaque;
> VSCMsgHeader *hdr;
>
> - if (card->vscard_in_pos + size > VSCARD_IN_SIZE) {
> - error_report("no room for data: pos %u + size %d > %" PRId64 "."
> - " dropping connection.",
> - card->vscard_in_pos, size, VSCARD_IN_SIZE);
> - ccid_card_vscard_drop_connection(card);
> - return;
> - }
> + assert(size <= VSCARD_IN_SIZE - card->vscard_in_pos);
> assert(card->vscard_in_hdr < VSCARD_IN_SIZE);
> memcpy(card->vscard_in_data + card->vscard_in_pos, buf, size);
> card->vscard_in_pos += size;
> --
> 2.20.1
>
^ permalink raw reply [flat|nested] 25+ messages in thread
* Re: [Qemu-devel] [PATCH v2 1/9] ccid-card-passthru: Move assertion in read() to can_read()
2019-02-14 20:19 ` [Qemu-devel] [PATCH v2 1/9] ccid-card-passthru: Move assertion in read() to can_read() Philippe Mathieu-Daudé
2019-02-14 21:18 ` Eric Blake
2019-02-15 8:44 ` Wei Yang
@ 2019-02-15 11:02 ` Marc-André Lureau
2 siblings, 0 replies; 25+ messages in thread
From: Marc-André Lureau @ 2019-02-15 11:02 UTC (permalink / raw)
To: Philippe Mathieu-Daudé
Cc: Prasad J Pandit, qemu-devel, Paolo Bonzini, Gerd Hoffmann
Hi
On Thu, Feb 14, 2019 at 9:19 PM Philippe Mathieu-Daudé
<philmd@redhat.com> wrote:
>
> chardev::read() depends of what chardev::can_read() returns, move the
> assertion to can_read().
>
> Suggested-by: Paolo Bonzini <pbonzini@redhat.com>
> Signed-off-by: Philippe Mathieu-Daudé <philmd@redhat.com>
Moving to can_read() makes sense, because nothing (except the chardev
BREAK event) should update vscard_in_pos between the can_read() and
read() callback.
Changing the condition from < to <= could use some explanation. The
can_read() callback should handle the case where the vscard_in buffer
is full (adding = is necessary). And the read() callback should not be
called with size == 0, when card->vscard_in_pos == VSCARD_IN_SIZE (no
data to read).
But it wouldn't harm to leave the existing assert().
Reviewed-by: Marc-André Lureau <marcandre.lureau@redhat.com>
> ---
> hw/usb/ccid-card-passthru.c | 5 ++---
> 1 file changed, 2 insertions(+), 3 deletions(-)
>
> diff --git a/hw/usb/ccid-card-passthru.c b/hw/usb/ccid-card-passthru.c
> index 0a6c657228..8bb1314f49 100644
> --- a/hw/usb/ccid-card-passthru.c
> +++ b/hw/usb/ccid-card-passthru.c
> @@ -116,8 +116,8 @@ static int ccid_card_vscard_can_read(void *opaque)
> {
> PassthruState *card = opaque;
>
> - return VSCARD_IN_SIZE >= card->vscard_in_pos ?
> - VSCARD_IN_SIZE - card->vscard_in_pos : 0;
> + assert(card->vscard_in_pos <= VSCARD_IN_SIZE);
> + return VSCARD_IN_SIZE - card->vscard_in_pos;
> }
>
> static void ccid_card_vscard_handle_init(
> @@ -282,7 +282,6 @@ static void ccid_card_vscard_read(void *opaque, const uint8_t *buf, int size)
> ccid_card_vscard_drop_connection(card);
> return;
> }
> - assert(card->vscard_in_pos < VSCARD_IN_SIZE);
> assert(card->vscard_in_hdr < VSCARD_IN_SIZE);
> memcpy(card->vscard_in_data + card->vscard_in_pos, buf, size);
> card->vscard_in_pos += size;
> --
> 2.20.1
>
^ permalink raw reply [flat|nested] 25+ messages in thread
* Re: [Qemu-devel] [PATCH v2 3/9] ccid-card-passthru: Assert on a stricter expression
2019-02-14 20:19 ` [Qemu-devel] [PATCH v2 3/9] ccid-card-passthru: Assert on a stricter expression Philippe Mathieu-Daudé
2019-02-15 8:47 ` Wei Yang
@ 2019-02-15 11:15 ` Marc-André Lureau
1 sibling, 0 replies; 25+ messages in thread
From: Marc-André Lureau @ 2019-02-15 11:15 UTC (permalink / raw)
To: Philippe Mathieu-Daudé
Cc: Prasad J Pandit, qemu-devel, Paolo Bonzini, Gerd Hoffmann
Hi
On Thu, Feb 14, 2019 at 9:20 PM Philippe Mathieu-Daudé
<philmd@redhat.com> wrote:
>
> Suggested-by: Paolo Bonzini <pbonzini@redhat.com>
> Signed-off-by: Philippe Mathieu-Daudé <philmd@redhat.com>
> ---
> hw/usb/ccid-card-passthru.c | 2 +-
> 1 file changed, 1 insertion(+), 1 deletion(-)
>
> diff --git a/hw/usb/ccid-card-passthru.c b/hw/usb/ccid-card-passthru.c
> index 1676b5fc05..0c44b38fc2 100644
> --- a/hw/usb/ccid-card-passthru.c
> +++ b/hw/usb/ccid-card-passthru.c
> @@ -270,7 +270,7 @@ static void ccid_card_vscard_read(void *opaque, const uint8_t *buf, int size)
> VSCMsgHeader *hdr;
>
> assert(size <= VSCARD_IN_SIZE - card->vscard_in_pos);
> - assert(card->vscard_in_hdr < VSCARD_IN_SIZE);
> + assert(card->vscard_in_hdr < card->vscard_in_pos);
I think you need "<=".
card->vscard_in_hdr is updated in the loop and may reach card->vscard_in_pos:
while ((card->vscard_in_pos - card->vscard_in_hdr >= sizeof(VSCMsgHeader))
&&(card->vscard_in_pos - card->vscard_in_hdr >=
sizeof(VSCMsgHeader) + ntohl(hdr->length))) {
...
card->vscard_in_hdr += hdr->length + sizeof(VSCMsgHeader);
...
}
if "hdr->length + sizeof(VSCMsgHeader)" == "card->vscard_in_pos -
card->vscard_in_hdr", card->vscard_in_hdr == card->vscard_in_pos after
the loop.
I think the existing assert() could also stay.
> memcpy(card->vscard_in_data + card->vscard_in_pos, buf, size);
> card->vscard_in_pos += size;
> hdr = (VSCMsgHeader *)(card->vscard_in_data + card->vscard_in_hdr);
> --
> 2.20.1
>
^ permalink raw reply [flat|nested] 25+ messages in thread
* Re: [Qemu-devel] [PATCH v2 4/9] ccid-card-passthru: Let the chardev::read() be more generic
2019-02-14 20:19 ` [Qemu-devel] [PATCH v2 4/9] ccid-card-passthru: Let the chardev::read() be more generic Philippe Mathieu-Daudé
@ 2019-02-15 11:43 ` Marc-André Lureau
0 siblings, 0 replies; 25+ messages in thread
From: Marc-André Lureau @ 2019-02-15 11:43 UTC (permalink / raw)
To: Philippe Mathieu-Daudé
Cc: Prasad J Pandit, qemu-devel, Paolo Bonzini, Gerd Hoffmann
Hi
On Thu, Feb 14, 2019 at 9:20 PM Philippe Mathieu-Daudé
<philmd@redhat.com> wrote:
>
> Suggested-by: Paolo Bonzini <pbonzini@redhat.com>
> Signed-off-by: Philippe Mathieu-Daudé <philmd@redhat.com>
> ---
> hw/usb/ccid-card-passthru.c | 10 ++++++++--
> 1 file changed, 8 insertions(+), 2 deletions(-)
>
> diff --git a/hw/usb/ccid-card-passthru.c b/hw/usb/ccid-card-passthru.c
> index 0c44b38fc2..ba7c285ded 100644
> --- a/hw/usb/ccid-card-passthru.c
> +++ b/hw/usb/ccid-card-passthru.c
> @@ -285,8 +285,14 @@ static void ccid_card_vscard_read(void *opaque, const uint8_t *buf, int size)
> card->vscard_in_hdr += hdr->length + sizeof(VSCMsgHeader);
> hdr = (VSCMsgHeader *)(card->vscard_in_data + card->vscard_in_hdr);
> }
> - if (card->vscard_in_hdr == card->vscard_in_pos) {
> - card->vscard_in_pos = card->vscard_in_hdr = 0;
Interesting, it looks like we could end in a blocking condition today.
card->vscard_in_pos - card->vscard_in_hdr could not have enough room
to process an incoming message. After filling the buffer, it would
stop reading.
> +
> + /* Drop any messages that were fully processed. */
> + if (card->vscard_in_hdr > 0) {
> + memmove(card->vscard_in_data,
> + card->vscard_in_data + card->vscard_in_hdr,
> + card->vscard_in_pos - card->vscard_in_hdr);
> + card->vscard_in_pos -= card->vscard_in_hdr;
> + card->vscard_in_hdr = 0;
> }
> }
At least, by moving data around, this would leave always enough space
for the header to be fully read.
But I think we should add a condition like
card->vscard_in_hdr + hdr->length + sizeof(VSCMsgHeader) <=
VSCARD_IN_SIZE, to make sure the incoming message fits in the
vscard_in_data buffer, else disconnect?
>
> --
> 2.20.1
>
^ permalink raw reply [flat|nested] 25+ messages in thread
* Re: [Qemu-devel] [PATCH v2 5/9] ccid-card-passthru: Replace assert() by QEMU_BUILD_BUG_ON()
2019-02-14 20:19 ` [Qemu-devel] [PATCH v2 5/9] ccid-card-passthru: Replace assert() by QEMU_BUILD_BUG_ON() Philippe Mathieu-Daudé
@ 2019-02-15 11:44 ` Marc-André Lureau
0 siblings, 0 replies; 25+ messages in thread
From: Marc-André Lureau @ 2019-02-15 11:44 UTC (permalink / raw)
To: Philippe Mathieu-Daudé
Cc: Prasad J Pandit, qemu-devel, Paolo Bonzini, Gerd Hoffmann
On Thu, Feb 14, 2019 at 9:20 PM Philippe Mathieu-Daudé
<philmd@redhat.com> wrote:
>
> Signed-off-by: Philippe Mathieu-Daudé <philmd@redhat.com>
Reviewed-by: Marc-André Lureau <marcandre.lureau@redhat.com>
> ---
> hw/usb/ccid-card-passthru.c | 9 +++++----
> 1 file changed, 5 insertions(+), 4 deletions(-)
>
> diff --git a/hw/usb/ccid-card-passthru.c b/hw/usb/ccid-card-passthru.c
> index ba7c285ded..ccc3ffa7fa 100644
> --- a/hw/usb/ccid-card-passthru.c
> +++ b/hw/usb/ccid-card-passthru.c
> @@ -29,6 +29,9 @@ do { \
> #define D_MORE_INFO 3
> #define D_VERBOSE 4
>
> +/* maximum size of ATR - from 7816-3 */
> +#define MAX_ATR_SIZE 40
> +
> /* TODO: do we still need this? */
> static const uint8_t DEFAULT_ATR[] = {
> /*
> @@ -41,10 +44,9 @@ static const uint8_t DEFAULT_ATR[] = {
> 0x13, 0x08
> };
>
> -#define VSCARD_IN_SIZE (64 * KiB)
> +QEMU_BUILD_BUG_ON(sizeof(DEFAULT_ATR) > MAX_ATR_SIZE);
>
> -/* maximum size of ATR - from 7816-3 */
> -#define MAX_ATR_SIZE 40
> +#define VSCARD_IN_SIZE (64 * KiB)
>
> typedef struct PassthruState PassthruState;
>
> @@ -351,7 +353,6 @@ static void passthru_realize(CCIDCardState *base, Error **errp)
> }
> card->debug = parse_debug_env("QEMU_CCID_PASSTHRU_DEBUG", D_VERBOSE,
> card->debug);
> - assert(sizeof(DEFAULT_ATR) <= MAX_ATR_SIZE);
> memcpy(card->atr, DEFAULT_ATR, sizeof(DEFAULT_ATR));
> card->atr_length = sizeof(DEFAULT_ATR);
> }
> --
> 2.20.1
>
^ permalink raw reply [flat|nested] 25+ messages in thread
* Re: [Qemu-devel] [PATCH v2 6/9] ccid-card-passthru: Simplify the if() condition
2019-02-14 20:19 ` [Qemu-devel] [PATCH v2 6/9] ccid-card-passthru: Simplify the if() condition Philippe Mathieu-Daudé
@ 2019-02-15 11:49 ` Marc-André Lureau
0 siblings, 0 replies; 25+ messages in thread
From: Marc-André Lureau @ 2019-02-15 11:49 UTC (permalink / raw)
To: Philippe Mathieu-Daudé
Cc: Prasad J Pandit, qemu-devel, Paolo Bonzini, Gerd Hoffmann
Hi
On Thu, Feb 14, 2019 at 9:20 PM Philippe Mathieu-Daudé
<philmd@redhat.com> wrote:
>
> Simplify the if() condition so we can remove an indent layer
> and the code is easier to review.
>
> Signed-off-by: Philippe Mathieu-Daudé <philmd@redhat.com>
Reviewed-by: Marc-André Lureau <marcandre.lureau@redhat.com>
> ---
> hw/usb/ccid-card-passthru.c | 18 ++++++++----------
> 1 file changed, 8 insertions(+), 10 deletions(-)
>
> diff --git a/hw/usb/ccid-card-passthru.c b/hw/usb/ccid-card-passthru.c
> index ccc3ffa7fa..6cb8b2d26b 100644
> --- a/hw/usb/ccid-card-passthru.c
> +++ b/hw/usb/ccid-card-passthru.c
> @@ -338,19 +338,17 @@ static void passthru_realize(CCIDCardState *base, Error **errp)
> {
> PassthruState *card = PASSTHRU_CCID_CARD(base);
>
> - card->vscard_in_pos = 0;
> - card->vscard_in_hdr = 0;
The 0 assignment are needless too (objects are memset 0), but not a
problem either.
> - if (qemu_chr_fe_backend_connected(&card->cs)) {
> - DPRINTF(card, D_INFO, "ccid-card-passthru: initing chardev");
> - qemu_chr_fe_set_handlers(&card->cs,
> - ccid_card_vscard_can_read,
> - ccid_card_vscard_read,
> - ccid_card_vscard_event, NULL, card, NULL, true);
> - ccid_card_vscard_send_init(card);
> - } else {
> + if (!qemu_chr_fe_backend_connected(&card->cs)) {
> error_setg(errp, "missing chardev");
> return;
> }
> + card->vscard_in_pos = 0;
> + card->vscard_in_hdr = 0;
> + DPRINTF(card, D_INFO, "ccid-card-passthru: initing chardev");
> + qemu_chr_fe_set_handlers(&card->cs, ccid_card_vscard_can_read,
> + ccid_card_vscard_read, ccid_card_vscard_event,
> + NULL, card, NULL, true);
> + ccid_card_vscard_send_init(card);
> card->debug = parse_debug_env("QEMU_CCID_PASSTHRU_DEBUG", D_VERBOSE,
> card->debug);
> memcpy(card->atr, DEFAULT_ATR, sizeof(DEFAULT_ATR));
> --
> 2.20.1
>
^ permalink raw reply [flat|nested] 25+ messages in thread
* Re: [Qemu-devel] [PATCH v2 8/9] ccid-card-passthru: Use size_t to hold size argument
2019-02-14 20:19 ` [Qemu-devel] [PATCH v2 8/9] ccid-card-passthru: Use size_t to hold size argument Philippe Mathieu-Daudé
@ 2019-02-15 11:51 ` Marc-André Lureau
0 siblings, 0 replies; 25+ messages in thread
From: Marc-André Lureau @ 2019-02-15 11:51 UTC (permalink / raw)
To: Philippe Mathieu-Daudé
Cc: Prasad J Pandit, QEMU, Paolo Bonzini, Gerd Hoffmann
Hi
On Thu, Feb 14, 2019 at 9:28 PM Philippe Mathieu-Daudé
<philmd@redhat.com> wrote:
>
> check_atr() is called once with a unsigned argument.
> Since there is no need to use a signed type, use a size_t.
>
> Signed-off-by: Philippe Mathieu-Daudé <philmd@redhat.com>
and make data const?
Reviewed-by: Marc-André Lureau <marcandre.lureau@redhat.com>
> ---
> hw/usb/ccid-card-passthru.c | 11 ++++++-----
> 1 file changed, 6 insertions(+), 5 deletions(-)
>
> diff --git a/hw/usb/ccid-card-passthru.c b/hw/usb/ccid-card-passthru.c
> index d63aa28584..083eb5ca08 100644
> --- a/hw/usb/ccid-card-passthru.c
> +++ b/hw/usb/ccid-card-passthru.c
> @@ -149,9 +149,10 @@ static void ccid_card_vscard_handle_init(
> ccid_card_vscard_send_init(card);
> }
>
> -static int check_atr(PassthruState *card, uint8_t *data, int len)
> +static int check_atr(PassthruState *card, uint8_t *data, size_t len)
> {
> - int historical_length, opt_bytes;
> + size_t historical_length;
> + int opt_bytes;
> int td_count = 0;
> int td;
>
> @@ -185,18 +186,18 @@ static int check_atr(PassthruState *card, uint8_t *data, int len)
> }
> if (len < 2 + historical_length + opt_bytes) {
> DPRINTF(card, D_WARN,
> - "atr too short: len %d, but historical_len %d, T1 0x%X\n",
> + "atr too short: len %zu, but historical_len %zu, T1 0x%X\n",
> len, historical_length, data[1]);
> return 0;
> }
> if (len > 2 + historical_length + opt_bytes) {
> DPRINTF(card, D_WARN,
> - "atr too long: len %d, but hist/opt %d/%d, T1 0x%X\n",
> + "atr too long: len %zu, but hist/opt %zu/%d, T1 0x%X\n",
> len, historical_length, opt_bytes, data[1]);
> /* let it through */
> }
> DPRINTF(card, D_VERBOSE,
> - "atr passes check: %d total length, %d historical, %d optional\n",
> + "atr passes check: %zu total length, %zu historical, %d optional\n",
> len, historical_length, opt_bytes);
>
> return 1;
> --
> 2.20.1
>
>
--
Marc-André Lureau
^ permalink raw reply [flat|nested] 25+ messages in thread
* Re: [Qemu-devel] [PATCH v2 9/9] ccid-card-passthru: Use size_t for index
2019-02-14 20:19 ` [Qemu-devel] [PATCH v2 9/9] ccid-card-passthru: Use size_t for index Philippe Mathieu-Daudé
@ 2019-02-15 11:52 ` Marc-André Lureau
0 siblings, 0 replies; 25+ messages in thread
From: Marc-André Lureau @ 2019-02-15 11:52 UTC (permalink / raw)
To: Philippe Mathieu-Daudé
Cc: Prasad J Pandit, QEMU, Paolo Bonzini, Gerd Hoffmann
On Thu, Feb 14, 2019 at 9:27 PM Philippe Mathieu-Daudé
<philmd@redhat.com> wrote:
>
> The variable 'opt_bytes' is an index to the data[] array.
> Use size_t for indexes.
>
> Signed-off-by: Philippe Mathieu-Daudé <philmd@redhat.com>
Reviewed-by: Marc-André Lureau <marcandre.lureau@redhat.com>
> ---
> hw/usb/ccid-card-passthru.c | 7 ++++---
> 1 file changed, 4 insertions(+), 3 deletions(-)
>
> diff --git a/hw/usb/ccid-card-passthru.c b/hw/usb/ccid-card-passthru.c
> index 083eb5ca08..664e8a1b54 100644
> --- a/hw/usb/ccid-card-passthru.c
> +++ b/hw/usb/ccid-card-passthru.c
> @@ -152,7 +152,7 @@ static void ccid_card_vscard_handle_init(
> static int check_atr(PassthruState *card, uint8_t *data, size_t len)
> {
> size_t historical_length;
> - int opt_bytes;
> + size_t opt_bytes;
> int td_count = 0;
> int td;
>
> @@ -192,12 +192,13 @@ static int check_atr(PassthruState *card, uint8_t *data, size_t len)
> }
> if (len > 2 + historical_length + opt_bytes) {
> DPRINTF(card, D_WARN,
> - "atr too long: len %zu, but hist/opt %zu/%d, T1 0x%X\n",
> + "atr too long: len %zu, but hist/opt %zu/%zu, T1 0x%X\n",
> len, historical_length, opt_bytes, data[1]);
> /* let it through */
> }
> DPRINTF(card, D_VERBOSE,
> - "atr passes check: %zu total length, %zu historical, %d optional\n",
> + "atr passes check: %zu total length,"
> + " %zu historical, %zu optional\n",
> len, historical_length, opt_bytes);
>
> return 1;
> --
> 2.20.1
>
>
--
Marc-André Lureau
^ permalink raw reply [flat|nested] 25+ messages in thread
* Re: [Qemu-devel] [PATCH v2 2/9] ccid-card-passthru: Replace never trigger if statement by an assertion
2019-02-15 10:59 ` Marc-André Lureau
@ 2019-02-18 22:10 ` Philippe Mathieu-Daudé
2019-02-21 11:04 ` P J P
0 siblings, 1 reply; 25+ messages in thread
From: Philippe Mathieu-Daudé @ 2019-02-18 22:10 UTC (permalink / raw)
To: Marc-André Lureau
Cc: Prasad J Pandit, qemu-devel, Paolo Bonzini, Gerd Hoffmann,
Arash Tohidi Chafi
On 2/15/19 11:59 AM, Marc-André Lureau wrote:
> Hi
>
> On Thu, Feb 14, 2019 at 9:20 PM Philippe Mathieu-Daudé
> <philmd@redhat.com> wrote:
>>
>> The right side of the comparison is the return value of can_read():
>> VSCARD_IN_SIZE - card->vscard_in_pos.
>> Since the 'size' argument of chardev::read() is bound to
>> what chardev::can_read() returns, this condition can never happen.
>
> I think so too, because vscard_in_pos is unchanged between the 2
> callbacks (or set to 0 in break event).
>
>>
>> Add an assertion, which will always fail if card->vscard_in_pos >=
>> VSCARD_IN_SIZE), since size > 0.
>
> If "size > VSCARD_IN_SIZE - card->vscard_in_pos" this is a chardev
> bug. But which backend does that?
>
> Iow, did we ever reach the "no room for data" error?
>
>>
>> This is a quick fix for CVE-2018-18438 "Integer overflow in
>> ccid_card_vscard_read() allows memory corruption".
>
> I have a hard time to find how that memory corruption can happen. It
> would be a broken chardev (one calling qemu_chr_be_write() with a size
> bigger than qemu_chr_be_can_write()). It would need to be fixed. But
It will :)
> which one does that?
Arash or Prasad can you help us here? Do you have a reproducer?
>>
>> Fixes: CVE-2018-18438
>> Reported-by: Arash Tohidi Chafi <tohidi.arash@gmail.com>
>> Suggested-by: Paolo Bonzini <pbonzini@redhat.com>
>> Signed-off-by: Philippe Mathieu-Daudé <philmd@redhat.com>
>> ---
>> hw/usb/ccid-card-passthru.c | 14 +-------------
>> 1 file changed, 1 insertion(+), 13 deletions(-)
>>
>> diff --git a/hw/usb/ccid-card-passthru.c b/hw/usb/ccid-card-passthru.c
>> index 8bb1314f49..1676b5fc05 100644
>> --- a/hw/usb/ccid-card-passthru.c
>> +++ b/hw/usb/ccid-card-passthru.c
>> @@ -264,24 +264,12 @@ static void ccid_card_vscard_handle_message(PassthruState *card,
>> }
>> }
>>
>> -static void ccid_card_vscard_drop_connection(PassthruState *card)
>> -{
>> - qemu_chr_fe_deinit(&card->cs, true);
>> - card->vscard_in_pos = card->vscard_in_hdr = 0;
>> -}
>> -
>> static void ccid_card_vscard_read(void *opaque, const uint8_t *buf, int size)
>> {
>> PassthruState *card = opaque;
>> VSCMsgHeader *hdr;
>>
>> - if (card->vscard_in_pos + size > VSCARD_IN_SIZE) {
>> - error_report("no room for data: pos %u + size %d > %" PRId64 "."
>> - " dropping connection.",
>> - card->vscard_in_pos, size, VSCARD_IN_SIZE);
>> - ccid_card_vscard_drop_connection(card);
>> - return;
>> - }
>> + assert(size <= VSCARD_IN_SIZE - card->vscard_in_pos);
>> assert(card->vscard_in_hdr < VSCARD_IN_SIZE);
>> memcpy(card->vscard_in_data + card->vscard_in_pos, buf, size);
>> card->vscard_in_pos += size;
>> --
>> 2.20.1
>>
^ permalink raw reply [flat|nested] 25+ messages in thread
* Re: [Qemu-devel] [PATCH v2 2/9] ccid-card-passthru: Replace never trigger if statement by an assertion
2019-02-18 22:10 ` Philippe Mathieu-Daudé
@ 2019-02-21 11:04 ` P J P
2019-02-21 11:09 ` Marc-André Lureau
0 siblings, 1 reply; 25+ messages in thread
From: P J P @ 2019-02-21 11:04 UTC (permalink / raw)
To: Philippe Mathieu-Daudé
Cc: Marc-André Lureau, Paolo Bonzini, Arash Tohidi Chafi,
Gerd Hoffmann, qemu-devel
+-- On Mon, 18 Feb 2019, Philippe Mathieu-Daudé wrote --+
| On 2/15/19 11:59 AM, Marc-André Lureau wrote:
| Arash or Prasad can you help us here? Do you have a reproducer?
No, we don't have a reproducer handy I'm afraid.
Thank you.
--
Prasad J Pandit / Red Hat Product Security Team
47AF CE69 3A90 54AA 9045 1053 DD13 3D32 FE5B 041F
^ permalink raw reply [flat|nested] 25+ messages in thread
* Re: [Qemu-devel] [PATCH v2 2/9] ccid-card-passthru: Replace never trigger if statement by an assertion
2019-02-21 11:04 ` P J P
@ 2019-02-21 11:09 ` Marc-André Lureau
0 siblings, 0 replies; 25+ messages in thread
From: Marc-André Lureau @ 2019-02-21 11:09 UTC (permalink / raw)
To: P J P
Cc: Philippe Mathieu-Daudé,
qemu-devel, Arash Tohidi Chafi, Gerd Hoffmann, Paolo Bonzini
Hi
On Thu, Feb 21, 2019 at 12:06 PM P J P <ppandit@redhat.com> wrote:
>
> +-- On Mon, 18 Feb 2019, Philippe Mathieu-Daudé wrote --+
> | On 2/15/19 11:59 AM, Marc-André Lureau wrote:
> | Arash or Prasad can you help us here? Do you have a reproducer?
>
> No, we don't have a reproducer handy I'm afraid.
Without a reproducer or convincing arguments, do we have a CVE?
--
Marc-André Lureau
^ permalink raw reply [flat|nested] 25+ messages in thread
end of thread, other threads:[~2019-02-21 11:09 UTC | newest]
Thread overview: 25+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2019-02-14 20:19 [Qemu-devel] [PATCH v2 0/9] ccid-card-passthru: check buffer size parameter Philippe Mathieu-Daudé
2019-02-14 20:19 ` [Qemu-devel] [PATCH v2 1/9] ccid-card-passthru: Move assertion in read() to can_read() Philippe Mathieu-Daudé
2019-02-14 21:18 ` Eric Blake
2019-02-15 8:44 ` Wei Yang
2019-02-15 11:02 ` Marc-André Lureau
2019-02-14 20:19 ` [Qemu-devel] [PATCH v2 2/9] ccid-card-passthru: Replace never trigger if statement by an assertion Philippe Mathieu-Daudé
2019-02-15 10:59 ` Marc-André Lureau
2019-02-18 22:10 ` Philippe Mathieu-Daudé
2019-02-21 11:04 ` P J P
2019-02-21 11:09 ` Marc-André Lureau
2019-02-14 20:19 ` [Qemu-devel] [PATCH v2 3/9] ccid-card-passthru: Assert on a stricter expression Philippe Mathieu-Daudé
2019-02-15 8:47 ` Wei Yang
2019-02-15 11:15 ` Marc-André Lureau
2019-02-14 20:19 ` [Qemu-devel] [PATCH v2 4/9] ccid-card-passthru: Let the chardev::read() be more generic Philippe Mathieu-Daudé
2019-02-15 11:43 ` Marc-André Lureau
2019-02-14 20:19 ` [Qemu-devel] [PATCH v2 5/9] ccid-card-passthru: Replace assert() by QEMU_BUILD_BUG_ON() Philippe Mathieu-Daudé
2019-02-15 11:44 ` Marc-André Lureau
2019-02-14 20:19 ` [Qemu-devel] [PATCH v2 6/9] ccid-card-passthru: Simplify the if() condition Philippe Mathieu-Daudé
2019-02-15 11:49 ` Marc-André Lureau
2019-02-14 20:19 ` [Qemu-devel] [PATCH v2 7/9] ccid-card-passthru: Use QERR_MISSING_PARAMETER Philippe Mathieu-Daudé
2019-02-14 21:22 ` Eric Blake
2019-02-14 20:19 ` [Qemu-devel] [PATCH v2 8/9] ccid-card-passthru: Use size_t to hold size argument Philippe Mathieu-Daudé
2019-02-15 11:51 ` Marc-André Lureau
2019-02-14 20:19 ` [Qemu-devel] [PATCH v2 9/9] ccid-card-passthru: Use size_t for index Philippe Mathieu-Daudé
2019-02-15 11:52 ` Marc-André Lureau
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.