mirror of https://gitee.com/openkylin/qemu.git
9pfs: handle transport errors in pdu_complete()
Contrary to what is written in the comment, a buggy guest can misconfigure the transport buffers and pdu_marshal() may return an error. If this ever happens, it is up to the transport layer to handle the situation (9P is transport agnostic). This fixes Coverity issue CID1348518. Signed-off-by: Greg Kurz <groug@kaod.org> Reviewed-by: Stefano Stabellini <sstabellini@kernel.org>
This commit is contained in:
parent
e08d1e11ed
commit
06a37db7b1
23
hw/9pfs/9p.c
23
hw/9pfs/9p.c
|
@ -624,15 +624,11 @@ void pdu_free(V9fsPDU *pdu)
|
||||||
QLIST_INSERT_HEAD(&s->free_list, pdu, next);
|
QLIST_INSERT_HEAD(&s->free_list, pdu, next);
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
|
||||||
* We don't do error checking for pdu_marshal/unmarshal here
|
|
||||||
* because we always expect to have enough space to encode
|
|
||||||
* error details
|
|
||||||
*/
|
|
||||||
static void coroutine_fn pdu_complete(V9fsPDU *pdu, ssize_t len)
|
static void coroutine_fn pdu_complete(V9fsPDU *pdu, ssize_t len)
|
||||||
{
|
{
|
||||||
int8_t id = pdu->id + 1; /* Response */
|
int8_t id = pdu->id + 1; /* Response */
|
||||||
V9fsState *s = pdu->s;
|
V9fsState *s = pdu->s;
|
||||||
|
int ret;
|
||||||
|
|
||||||
if (len < 0) {
|
if (len < 0) {
|
||||||
int err = -len;
|
int err = -len;
|
||||||
|
@ -644,11 +640,19 @@ static void coroutine_fn pdu_complete(V9fsPDU *pdu, ssize_t len)
|
||||||
str.data = strerror(err);
|
str.data = strerror(err);
|
||||||
str.size = strlen(str.data);
|
str.size = strlen(str.data);
|
||||||
|
|
||||||
len += pdu_marshal(pdu, len, "s", &str);
|
ret = pdu_marshal(pdu, len, "s", &str);
|
||||||
|
if (ret < 0) {
|
||||||
|
goto out_notify;
|
||||||
|
}
|
||||||
|
len += ret;
|
||||||
id = P9_RERROR;
|
id = P9_RERROR;
|
||||||
}
|
}
|
||||||
|
|
||||||
len += pdu_marshal(pdu, len, "d", err);
|
ret = pdu_marshal(pdu, len, "d", err);
|
||||||
|
if (ret < 0) {
|
||||||
|
goto out_notify;
|
||||||
|
}
|
||||||
|
len += ret;
|
||||||
|
|
||||||
if (s->proto_version == V9FS_PROTO_2000L) {
|
if (s->proto_version == V9FS_PROTO_2000L) {
|
||||||
id = P9_RLERROR;
|
id = P9_RLERROR;
|
||||||
|
@ -657,12 +661,15 @@ static void coroutine_fn pdu_complete(V9fsPDU *pdu, ssize_t len)
|
||||||
}
|
}
|
||||||
|
|
||||||
/* fill out the header */
|
/* fill out the header */
|
||||||
pdu_marshal(pdu, 0, "dbw", (int32_t)len, id, pdu->tag);
|
if (pdu_marshal(pdu, 0, "dbw", (int32_t)len, id, pdu->tag) < 0) {
|
||||||
|
goto out_notify;
|
||||||
|
}
|
||||||
|
|
||||||
/* keep these in sync */
|
/* keep these in sync */
|
||||||
pdu->size = len;
|
pdu->size = len;
|
||||||
pdu->id = id;
|
pdu->id = id;
|
||||||
|
|
||||||
|
out_notify:
|
||||||
pdu->s->transport->push_and_notify(pdu);
|
pdu->s->transport->push_and_notify(pdu);
|
||||||
|
|
||||||
/* Now wakeup anybody waiting in flush for this request */
|
/* Now wakeup anybody waiting in flush for this request */
|
||||||
|
|
Loading…
Reference in New Issue