net: tftp: sanitize tftp block size, especially for TX
U-Boot does not support IP fragmentation on TX (and unless CONFIG_IP_DEFRAG is set, neither on RX). So the blocks we send must fit in a single ethernet packet. Currently, if tftpblocksize is set to something like 5000 and I tftpput a large enough file, U-Boot crashes because we overflow net_tx_packet (which only has room for 1500 bytes plus change). Similarly, if tftpblocksize is set to something larger than what we can actually receive (e.g. 50000, with NET_MAXDEFRAG being 16384), any tftp get just hangs because we never receive any packets. Signed-off-by: Rasmus Villemoes <rasmus.villemoes@prevas.dk> Reviewed-by: Ramon Fried <rfried.dev@gmail.com>
This commit is contained in:
parent
4b8c44e39c
commit
087648b5df
47
net/tftp.c
47
net/tftp.c
@ -708,9 +708,54 @@ static int tftp_init_load_addr(void)
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int saved_tftp_block_size_option;
|
||||
static void sanitize_tftp_block_size_option(enum proto_t protocol)
|
||||
{
|
||||
int cap, max_defrag;
|
||||
|
||||
switch (protocol) {
|
||||
case TFTPGET:
|
||||
max_defrag = config_opt_enabled(CONFIG_IP_DEFRAG, CONFIG_NET_MAXDEFRAG, 0);
|
||||
if (max_defrag) {
|
||||
/* Account for IP, UDP and TFTP headers. */
|
||||
cap = max_defrag - (20 + 8 + 4);
|
||||
/* RFC2348 sets a hard upper limit. */
|
||||
cap = min(cap, 65464);
|
||||
break;
|
||||
}
|
||||
/*
|
||||
* If not CONFIG_IP_DEFRAG, cap at the same value as
|
||||
* for tftp put, namely normal MTU minus protocol
|
||||
* overhead.
|
||||
*/
|
||||
fallthrough;
|
||||
case TFTPPUT:
|
||||
default:
|
||||
/*
|
||||
* U-Boot does not support IP fragmentation on TX, so
|
||||
* this must be small enough that it fits normal MTU
|
||||
* (and small enough that it fits net_tx_packet which
|
||||
* has room for PKTSIZE_ALIGN bytes).
|
||||
*/
|
||||
cap = 1468;
|
||||
}
|
||||
if (tftp_block_size_option > cap) {
|
||||
printf("Capping tftp block size option to %d (was %d)\n",
|
||||
cap, tftp_block_size_option);
|
||||
saved_tftp_block_size_option = tftp_block_size_option;
|
||||
tftp_block_size_option = cap;
|
||||
}
|
||||
}
|
||||
|
||||
void tftp_start(enum proto_t protocol)
|
||||
{
|
||||
__maybe_unused char *ep; /* Environment pointer */
|
||||
|
||||
if (saved_tftp_block_size_option) {
|
||||
tftp_block_size_option = saved_tftp_block_size_option;
|
||||
saved_tftp_block_size_option = 0;
|
||||
}
|
||||
|
||||
if (IS_ENABLED(CONFIG_NET_TFTP_VARS)) {
|
||||
|
||||
/*
|
||||
@ -747,6 +792,8 @@ void tftp_start(enum proto_t protocol)
|
||||
}
|
||||
}
|
||||
|
||||
sanitize_tftp_block_size_option(protocol);
|
||||
|
||||
debug("TFTP blocksize = %i, TFTP windowsize = %d timeout = %ld ms\n",
|
||||
tftp_block_size_option, tftp_window_size_option, timeout_ms);
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user