avoid fifo overflow on read() with small buffer sizes. Signed-off-by: Enrico Scholz <enrico.scholz@xxxxxxxxxxxxxxxxx> --- fs/tftp.c | 13 +++++++++++-- 1 file changed, 11 insertions(+), 2 deletions(-) diff --git a/fs/tftp.c b/fs/tftp.c index 2bffae2bf36e..a3fe7dfd590e 100644 --- a/fs/tftp.c +++ b/fs/tftp.c @@ -78,6 +78,9 @@ /* size of cache which deals with udp reordering */ #define TFTP_WINDOW_CACHE_NUM CONFIG_FS_TFTP_REORDER_CACHE_SIZE +/* allocate this number of blocks more than needed in the fifo */ +#define TFTP_EXTRA_BLOCKS 2 + /* marker for an emtpy 'tftp_cache' */ #define TFTP_CACHE_NO_ID (-1) @@ -546,7 +549,8 @@ static int tftp_allocate_transfer(struct file_priv *priv) /* multiplication is safe; both operands were checked in tftp_parse_oack() and are small integers */ - priv->fifo = kfifo_alloc(priv->blocksize * priv->windowsize); + priv->fifo = kfifo_alloc(priv->blocksize * + (priv->windowsize + TFTP_EXTRA_BLOCKS)); if (!priv->fifo) goto err; @@ -1025,7 +1029,12 @@ static int tftp_read(struct device_d *dev, FILE *f, void *buf, size_t insize) if (priv->state == STATE_DONE) return outsize; - if (priv->last_block == priv->ack_block) + /* send the ACK only when fifo has been nearly depleted; else, + when tftp_read() is called with small 'insize' values, it + is possible that there is read more data from the network + than consumed by kfifo_get() and the fifo overflows */ + if (priv->last_block == priv->ack_block && + kfifo_len(priv->fifo) <= TFTP_EXTRA_BLOCKS * priv->blocksize) tftp_send(priv); ret = tftp_poll(priv); -- 2.37.2