diff options
author | Christian Schoenebeck <qemu_oss@crudebyte.com> | 2020-02-08 09:24:19 +0100 |
---|---|---|
committer | Greg Kurz <groug@kaod.org> | 2020-02-08 09:28:54 +0100 |
commit | d36a5c227099f3f74da27a730350b012b6e99cdd (patch) | |
tree | c69044602bbfae2ccc16001ee0fab8b8752dba95 /hw | |
parent | e16453a31a00c1c0a199cab0617e8aa888f6419a (diff) |
9pfs: validate count sent by client with T_readdir
A good 9p client sends T_readdir with "count" parameter that's sufficiently
smaller than client's initially negotiated msize (maximum message size).
We perform a check for that though to avoid the server to be interrupted
with a "Failed to encode VirtFS reply type 41" transport error message by
bad clients. This count value constraint uses msize - 11, because 11 is the
header size of R_readdir.
Signed-off-by: Christian Schoenebeck <qemu_oss@crudebyte.com>
Reviewed-by: Greg Kurz <groug@kaod.org>
Message-Id: <3990d3891e8ae2074709b56449e96ab4b4b93b7d.1579567020.git.qemu_oss@crudebyte.com>
[groug: added comment ]
Signed-off-by: Greg Kurz <groug@kaod.org>
Diffstat (limited to 'hw')
-rw-r--r-- | hw/9pfs/9p.c | 9 |
1 files changed, 9 insertions, 0 deletions
diff --git a/hw/9pfs/9p.c b/hw/9pfs/9p.c index c63f549f39..9e046f7acb 100644 --- a/hw/9pfs/9p.c +++ b/hw/9pfs/9p.c @@ -2434,6 +2434,7 @@ static void coroutine_fn v9fs_readdir(void *opaque) int32_t count; uint32_t max_count; V9fsPDU *pdu = opaque; + V9fsState *s = pdu->s; retval = pdu_unmarshal(pdu, offset, "dqd", &fid, &initial_offset, &max_count); @@ -2442,6 +2443,14 @@ static void coroutine_fn v9fs_readdir(void *opaque) } trace_v9fs_readdir(pdu->tag, pdu->id, fid, initial_offset, max_count); + /* Enough space for a R_readdir header: size[4] Rreaddir tag[2] count[4] */ + if (max_count > s->msize - 11) { + max_count = s->msize - 11; + warn_report_once( + "9p: bad client: T_readdir with count > msize - 11" + ); + } + fidp = get_fid(pdu, fid); if (fidp == NULL) { retval = -EINVAL; |