diff options
author | Jerome Forissier <jerome.forissier@linaro.org> | 2025-04-17 15:27:00 +0200 |
---|---|---|
committer | Jerome Forissier <jerome.forissier@linaro.org> | 2025-05-20 15:43:08 +0200 |
commit | 1bc91fa98c020c1f737680cc43a4c7584e17db15 (patch) | |
tree | 97ebd572dc6d684adc6928bd3c1ad9e3a54b82b6 /net/lwip/tftp.c | |
parent | e40c910e88a9a38ee1335ab1391dc2ee83993a65 (diff) |
net-lwip: tftp: add LMB and buffer checks
Legacy NET tftp invokes a store_block() function which performs buffer
validation (LMB, address wrapping). Do the same with NET_LWIP.
Signed-off-by: Jerome Forissier <jerome.forissier@linaro.org>
Suggested-by: Sughosh Ganu <sughosh.ganu@linaro.org>
Acked-by: Sughosh Ganu <sughosh.ganu@linaro.org>
Tested-by: Sughosh Ganu <sughosh.ganu@linaro.org>
Diffstat (limited to 'net/lwip/tftp.c')
-rw-r--r-- | net/lwip/tftp.c | 56 |
1 files changed, 45 insertions, 11 deletions
diff --git a/net/lwip/tftp.c b/net/lwip/tftp.c index 4f9b2049187..162c141105c 100644 --- a/net/lwip/tftp.c +++ b/net/lwip/tftp.c @@ -8,6 +8,7 @@ #include <efi_loader.h> #include <image.h> #include <linux/delay.h> +#include <linux/kconfig.h> #include <lwip/apps/tftp_client.h> #include <lwip/timeouts.h> #include <mapmem.h> @@ -31,6 +32,47 @@ struct tftp_ctx { enum done_state done; }; +/** + * store_block() - copy received data + * + * This function is called by the receive callback to copy a block of data + * into its final location (ctx->daddr). Before doing so, it checks if the copy + * is allowed. + * + * @ctx: the context for the current transfer + * @src: the data received from the TCP stack + * @len: the length of the data + */ +static int store_block(struct tftp_ctx *ctx, void *src, u16_t len) +{ + ulong store_addr = ctx->daddr; + void *ptr; + + if (CONFIG_IS_ENABLED(LMB)) { + if (store_addr + len < store_addr || + lmb_read_check(store_addr, len)) { + puts("\nTFTP error: "); + puts("trying to overwrite reserved memory...\n"); + return -1; + } + } + + ptr = map_sysmem(store_addr, len); + memcpy(ptr, src, len); + unmap_sysmem(ptr); + + ctx->daddr += len; + ctx->size += len; + ctx->block_count++; + if (ctx->block_count % 10 == 0) { + putc('#'); + if (ctx->block_count % (65 * 10) == 0) + puts("\n\t "); + } + + return 0; +} + static void *tftp_open(const char *fname, const char *mode, u8_t is_write) { return NULL; @@ -71,17 +113,9 @@ static int tftp_write(void *handle, struct pbuf *p) struct tftp_ctx *ctx = handle; struct pbuf *q; - for (q = p; q; q = q->next) { - memcpy((void *)ctx->daddr, q->payload, q->len); - ctx->daddr += q->len; - ctx->size += q->len; - ctx->block_count++; - if (ctx->block_count % 10 == 0) { - putc('#'); - if (ctx->block_count % (65 * 10) == 0) - puts("\n\t "); - } - } + for (q = p; q; q = q->next) + if (store_block(ctx, q->payload, q->len) < 0) + return -1; return 0; } |