From 53af9905e023c89c9d7c30c22eb25f2b0105026c Mon Sep 17 00:00:00 2001 From: Michael Brown Date: Fri, 13 Dec 2019 14:44:22 +0000 Subject: [peerdist] Allow PeerDist to be globally enabled or disabled Allow the use of PeerDist content encoding to be enabled or disabled via the ${peerdist} setting, e.g.: # Disable PeerDist set peerdist 0 Signed-off-by: Michael Brown --- src/net/peerdist.c | 38 ++++++++++++++++++++++++++++++++++++++ 1 file changed, 38 insertions(+) (limited to 'src') diff --git a/src/net/peerdist.c b/src/net/peerdist.c index 48933f951..3210ac0ec 100644 --- a/src/net/peerdist.c +++ b/src/net/peerdist.c @@ -25,6 +25,7 @@ FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL ); #include #include +#include #include /** @file @@ -35,6 +36,9 @@ FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL ); * misfortune to encounter, and I've encountered multicast TFTP. */ +/** PeerDist is globally enabled */ +static long peerdist_enabled = 1; + /** * Check whether or not to support PeerDist encoding for this request * @@ -43,6 +47,10 @@ FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL ); */ static int http_peerdist_supported ( struct http_transaction *http ) { + /* Allow PeerDist to be globally enabled/disabled */ + if ( ! peerdist_enabled ) + return 0; + /* Support PeerDist encoding only if we can directly access an * underlying data transfer buffer. Direct access is required * in order to support decryption of data received via the @@ -143,3 +151,33 @@ struct http_content_encoding peerdist_encoding __http_content_encoding = { .supported = http_peerdist_supported, .init = http_peerdist_init, }; + +/** PeerDist enabled setting */ +const struct setting peerdist_setting __setting ( SETTING_MISC, peerdist ) = { + .name = "peerdist", + .description = "PeerDist enabled", + .type = &setting_type_int8, +}; + +/** + * Apply PeerDist settings + * + * @ret rc Return status code + */ +static int apply_peerdist_settings ( void ) { + + /* Fetch global PeerDist enabled setting */ + if ( fetch_int_setting ( NULL, &peerdist_setting, + &peerdist_enabled ) < 0 ) { + peerdist_enabled = 1; + } + DBGC ( &peerdist_enabled, "PEERDIST is %s\n", + ( peerdist_enabled ? "enabled" : "disabled" ) ); + + return 0; +} + +/** PeerDist settings applicator */ +struct settings_applicator peerdist_applicator __settings_applicator = { + .apply = apply_peerdist_settings, +}; -- cgit v1.2.3-55-g7522 From a2d3bedf1f1548c49dd3ad68b4d9719f61a27c3a Mon Sep 17 00:00:00 2001 From: Michael Brown Date: Sun, 15 Dec 2019 23:26:02 +0000 Subject: [peerdist] Allow for the use of a hosted cache server Allow a PeerDist hosted cache server to be specified via the ${peerhost} setting, e.g.: # Use 192.168.0.1 as hosted cache server set peerhost 192.168.0.1 Note that this simply treats the hosted cache server as a permanently discovered peer for all segments. Signed-off-by: Michael Brown --- src/net/peerdisc.c | 69 ++++++++++++++++++++++++++++++++++++++++++++++++++---- 1 file changed, 65 insertions(+), 4 deletions(-) (limited to 'src') diff --git a/src/net/peerdisc.c b/src/net/peerdisc.c index 20ac2427b..55e3f7fa7 100644 --- a/src/net/peerdisc.c +++ b/src/net/peerdisc.c @@ -37,6 +37,7 @@ FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL ); #include #include #include +#include #include #include @@ -72,6 +73,9 @@ static LIST_HEAD ( peerdisc_segments ); */ unsigned int peerdisc_timeout_secs = PEERDISC_DEFAULT_TIMEOUT_SECS; +/** Hosted cache server */ +static char *peerhost; + static struct peerdisc_segment * peerdisc_find ( const char *id ); static int peerdisc_discovered ( struct peerdisc_segment *segment, const char *location ); @@ -442,6 +446,7 @@ static struct peerdisc_segment * peerdisc_create ( const char *id ) { char *uuid_copy; char *id_copy; unsigned int i; + int rc; /* Generate a random message UUID. This does not require high * quality randomness. @@ -458,7 +463,7 @@ static struct peerdisc_segment * peerdisc_create ( const char *id ) { /* Allocate and initialise structure */ segment = zalloc ( sizeof ( *segment ) + id_len + uuid_len ); if ( ! segment ) - return NULL; + goto err_alloc; id_copy = ( ( ( void * ) segment ) + sizeof ( *segment ) ); memcpy ( id_copy, id, id_len ); uuid_copy = ( ( ( void * ) id_copy ) + id_len ); @@ -469,14 +474,30 @@ static struct peerdisc_segment * peerdisc_create ( const char *id ) { INIT_LIST_HEAD ( &segment->peers ); INIT_LIST_HEAD ( &segment->clients ); timer_init ( &segment->timer, peerdisc_expired, &segment->refcnt ); - DBGC2 ( segment, "PEERDISC %p discovering %s\n", segment, segment->id ); - /* Start discovery timer */ - start_timer_nodelay ( &segment->timer ); + /* Add hosted cache server or initiate discovery */ + if ( peerhost ) { + + /* Add hosted cache server to list of peers */ + if ( ( rc = peerdisc_discovered ( segment, peerhost ) ) != 0 ) + goto err_peerhost; + + } else { + + /* Start discovery timer */ + start_timer_nodelay ( &segment->timer ); + DBGC2 ( segment, "PEERDISC %p discovering %s\n", + segment, segment->id ); + } /* Add to list of segments, transfer reference to list, and return */ list_add_tail ( &segment->list, &peerdisc_segments ); return segment; + + err_peerhost: + ref_put ( &segment->refcnt ); + err_alloc: + return NULL; } /** @@ -579,3 +600,43 @@ void peerdisc_close ( struct peerdisc_client *peerdisc ) { if ( list_empty ( &peerdisc_segments ) ) peerdisc_socket_close ( 0 ); } + +/****************************************************************************** + * + * Settings + * + ****************************************************************************** + */ + +/** PeerDist hosted cache server setting */ +const struct setting peerhost_setting __setting ( SETTING_MISC, peerhost ) = { + .name = "peerhost", + .description = "PeerDist hosted cache", + .type = &setting_type_string, +}; + +/** + * Apply PeerDist discovery settings + * + * @ret rc Return status code + */ +static int apply_peerdisc_settings ( void ) { + + /* Free any existing hosted cache server */ + free ( peerhost ); + peerhost = NULL; + + /* Fetch hosted cache server */ + fetch_string_setting_copy ( NULL, &peerhost_setting, &peerhost ); + if ( peerhost ) { + DBGC ( &peerhost, "PEERDISC using hosted cache %s\n", + peerhost ); + } + + return 0; +} + +/** PeerDist discovery settings applicator */ +struct settings_applicator peerdisc_applicator __settings_applicator = { + .apply = apply_peerdisc_settings, +}; -- cgit v1.2.3-55-g7522 From ed4a82e239dbdc3b60840d792fca9ceb269953e4 Mon Sep 17 00:00:00 2001 From: Ignat Korchagin Date: Fri, 13 Dec 2019 16:17:58 +0000 Subject: [snp] Try promiscuous multicast receive filter if the regular one fails Currently, if the SNP driver for whatever reason fails to enable receive filters for multicast frames, it falls back to enabling just unicast and broadcast filters. This breaks some IPv6 functionality as the network card does not respond to neighbour solicitation requests. Some cards refuse to enable EFI_SIMPLE_NETWORK_RECEIVE_MULTICAST, but do support enabling EFI_SIMPLE_NETWORK_RECEIVE_PROMISCUOUS_MULTICAST, so try it before falling back to just unicast+broadcast. Signed-off-by: Ignat Korchagin Split-by: Michael Brown Signed-off-by: Michael Brown --- src/drivers/net/efi/snpnet.c | 3 +++ 1 file changed, 3 insertions(+) (limited to 'src') diff --git a/src/drivers/net/efi/snpnet.c b/src/drivers/net/efi/snpnet.c index 88474b0be..44bc83282 100644 --- a/src/drivers/net/efi/snpnet.c +++ b/src/drivers/net/efi/snpnet.c @@ -299,6 +299,9 @@ static int snpnet_rx_filters ( struct net_device *netdev ) { ( EFI_SIMPLE_NETWORK_RECEIVE_UNICAST | EFI_SIMPLE_NETWORK_RECEIVE_MULTICAST | EFI_SIMPLE_NETWORK_RECEIVE_BROADCAST ), + ( EFI_SIMPLE_NETWORK_RECEIVE_UNICAST | + EFI_SIMPLE_NETWORK_RECEIVE_PROMISCUOUS_MULTICAST | + EFI_SIMPLE_NETWORK_RECEIVE_BROADCAST ), ( EFI_SIMPLE_NETWORK_RECEIVE_UNICAST | EFI_SIMPLE_NETWORK_RECEIVE_BROADCAST ), ( EFI_SIMPLE_NETWORK_RECEIVE_UNICAST ), -- cgit v1.2.3-55-g7522 From ea832529a5d2ac7c82f68b1ce86cf272f0cdf2cb Mon Sep 17 00:00:00 2001 From: Ignat Korchagin Date: Fri, 13 Dec 2019 16:17:58 +0000 Subject: [snp] Set EFI_SIMPLE_NETWORK_RECEIVE_MULTICAST bit as per UEFI spec According to UEFI specification 2.8 p 24.1 we must set the EFI_SIMPLE_NETWORK_RECEIVE_MULTICAST bit in the "Disable" mask, when "ResetMCastFilter" is TRUE. Signed-off-by: Ignat Korchagin Split-by: Michael Brown Signed-off-by: Michael Brown --- src/drivers/net/efi/snpnet.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'src') diff --git a/src/drivers/net/efi/snpnet.c b/src/drivers/net/efi/snpnet.c index 44bc83282..536248bca 100644 --- a/src/drivers/net/efi/snpnet.c +++ b/src/drivers/net/efi/snpnet.c @@ -313,7 +313,8 @@ static int snpnet_rx_filters ( struct net_device *netdev ) { /* Try possible receive filters in turn */ for ( i = 0; i < ( sizeof ( filters ) / sizeof ( filters[0] ) ); i++ ) { efirc = snp->snp->ReceiveFilters ( snp->snp, filters[i], - 0, TRUE, 0, NULL ); + EFI_SIMPLE_NETWORK_RECEIVE_MULTICAST, TRUE, + 0, NULL ); if ( efirc == 0 ) return 0; rc = -EEFI ( efirc ); -- cgit v1.2.3-55-g7522 From 8f1514a00450119b04b08642c55aa674bdf5a4ef Mon Sep 17 00:00:00 2001 From: Michael Brown Date: Thu, 2 Jan 2020 23:43:15 +0100 Subject: [build] Construct full version number automatically from git revision Signed-off-by: Michael Brown --- src/Makefile | 17 +++++++++++++++-- 1 file changed, 15 insertions(+), 2 deletions(-) (limited to 'src') diff --git a/src/Makefile b/src/Makefile index c0bc45fa6..a84efd6d6 100644 --- a/src/Makefile +++ b/src/Makefile @@ -207,14 +207,27 @@ install : # # Version number calculations # +ifneq ($(wildcard ../.git),) +VERSIONS := $(shell git describe --tags --always --long --abbrev=1 --match "v*") +VERSION_TUPLE := $(subst ., ,$(subst -, ,$(patsubst v%,%,$(VERSIONS)))) +VERSION_MAJOR := $(word 1,$(VERSION_TUPLE)) +VERSION_MINOR := $(word 2,$(VERSION_TUPLE)) +VERSION_PATCH := $(word 3,$(VERSION_TUPLE)) +ifeq ($(word 4,$(VERSION_TUPLE)),0) +EXTRAVERSION := +else +EXTRAVERSION := + +endif +GITVERSION = $(word 5,$(VERSION_TUPLE)) +else VERSION_MAJOR = 1 VERSION_MINOR = 0 VERSION_PATCH = 0 EXTRAVERSION = + +endif MM_VERSION = $(VERSION_MAJOR).$(VERSION_MINOR) VERSION = $(MM_VERSION).$(VERSION_PATCH)$(EXTRAVERSION) -ifneq ($(wildcard ../.git),) -GITVERSION := $(shell git describe --always --abbrev=1 --match "" 2>/dev/null) +ifneq ($(GITVERSION),) VERSION += ($(GITVERSION)) endif version : -- cgit v1.2.3-55-g7522 From c625681ca185849d58f2f848de22d6733ff77786 Mon Sep 17 00:00:00 2001 From: Michael Brown Date: Sun, 16 Feb 2020 20:08:20 +0000 Subject: [tftp] Eliminate unnecessary variable-length stack allocation Eliminate an unnecessary variable-length stack allocation and memory copy by allowing TFTP option processors to modify the option string in-place. Signed-off-by: Michael Brown --- src/net/udp/tftp.c | 17 ++++++----------- 1 file changed, 6 insertions(+), 11 deletions(-) (limited to 'src') diff --git a/src/net/udp/tftp.c b/src/net/udp/tftp.c index 6ce27497c..a0dac1ec5 100644 --- a/src/net/udp/tftp.c +++ b/src/net/udp/tftp.c @@ -545,8 +545,7 @@ static void tftp_timer_expired ( struct retry_timer *timer, int fail ) { * @v value Option value * @ret rc Return status code */ -static int tftp_process_blksize ( struct tftp_request *tftp, - const char *value ) { +static int tftp_process_blksize ( struct tftp_request *tftp, char *value ) { char *end; tftp->blksize = strtoul ( value, &end, 10 ); @@ -567,8 +566,7 @@ static int tftp_process_blksize ( struct tftp_request *tftp, * @v value Option value * @ret rc Return status code */ -static int tftp_process_tsize ( struct tftp_request *tftp, - const char *value ) { +static int tftp_process_tsize ( struct tftp_request *tftp, char *value ) { char *end; tftp->tsize = strtoul ( value, &end, 10 ); @@ -589,13 +587,11 @@ static int tftp_process_tsize ( struct tftp_request *tftp, * @v value Option value * @ret rc Return status code */ -static int tftp_process_multicast ( struct tftp_request *tftp, - const char *value ) { +static int tftp_process_multicast ( struct tftp_request *tftp, char *value ) { union { struct sockaddr sa; struct sockaddr_in sin; } socket; - char buf[ strlen ( value ) + 1 ]; char *addr; char *port; char *port_end; @@ -604,8 +600,7 @@ static int tftp_process_multicast ( struct tftp_request *tftp, int rc; /* Split value into "addr,port,mc" fields */ - memcpy ( buf, value, sizeof ( buf ) ); - addr = buf; + addr = value; port = strchr ( addr, ',' ); if ( ! port ) { DBGC ( tftp, "TFTP %p multicast missing port,mc\n", tftp ); @@ -662,7 +657,7 @@ struct tftp_option { * @v value Option value * @ret rc Return status code */ - int ( * process ) ( struct tftp_request *tftp, const char *value ); + int ( * process ) ( struct tftp_request *tftp, char *value ); }; /** Recognised TFTP options */ @@ -682,7 +677,7 @@ static struct tftp_option tftp_options[] = { * @ret rc Return status code */ static int tftp_process_option ( struct tftp_request *tftp, - const char *name, const char *value ) { + const char *name, char *value ) { struct tftp_option *option; for ( option = tftp_options ; option->name ; option++ ) { -- cgit v1.2.3-55-g7522 From 6248ac396aaf9ccff7cda91080305ad2dc08d8cc Mon Sep 17 00:00:00 2001 From: Michael Brown Date: Sun, 16 Feb 2020 21:25:27 +0000 Subject: [infiniband] Eliminate variable-length stack allocation Signed-off-by: Michael Brown --- src/net/infiniband/ib_srp.c | 24 ++++++++++++++++++------ 1 file changed, 18 insertions(+), 6 deletions(-) (limited to 'src') diff --git a/src/net/infiniband/ib_srp.c b/src/net/infiniband/ib_srp.c index cf1ef3bfd..4913f449c 100644 --- a/src/net/infiniband/ib_srp.c +++ b/src/net/infiniband/ib_srp.c @@ -498,14 +498,21 @@ static struct ib_srp_root_path_parser ib_srp_rp_parser[] = { static int ib_srp_parse_root_path ( const char *rp_string, struct ib_srp_root_path *rp ) { struct ib_srp_root_path_parser *parser; - char rp_string_copy[ strlen ( rp_string ) + 1 ]; char *rp_comp[IB_SRP_NUM_RP_COMPONENTS]; - char *rp_string_tmp = rp_string_copy; + char *rp_string_copy; + char *rp_string_tmp; unsigned int i = 0; int rc; + /* Create modifiable copy of root path */ + rp_string_copy = strdup ( rp_string ); + if ( ! rp_string_copy ) { + rc = -ENOMEM; + goto err_strdup; + } + rp_string_tmp = rp_string_copy; + /* Split root path into component parts */ - strcpy ( rp_string_copy, rp_string ); while ( 1 ) { rp_comp[i++] = rp_string_tmp; if ( i == IB_SRP_NUM_RP_COMPONENTS ) @@ -514,7 +521,8 @@ static int ib_srp_parse_root_path ( const char *rp_string, if ( ! *rp_string_tmp ) { DBG ( "IBSRP root path \"%s\" too short\n", rp_string ); - return -EINVAL_RP_TOO_SHORT; + rc = -EINVAL_RP_TOO_SHORT; + goto err_split; } } *(rp_string_tmp++) = '\0'; @@ -527,11 +535,15 @@ static int ib_srp_parse_root_path ( const char *rp_string, DBG ( "IBSRP could not parse \"%s\" in root path " "\"%s\": %s\n", rp_comp[i], rp_string, strerror ( rc ) ); - return rc; + goto err_parse; } } - return 0; + err_parse: + err_split: + free ( rp_string_copy ); + err_strdup: + return rc; } /** -- cgit v1.2.3-55-g7522 From c5306bcfa5ca477a88c921d03c2301f7393ba480 Mon Sep 17 00:00:00 2001 From: Michael Brown Date: Sun, 16 Feb 2020 21:55:59 +0000 Subject: [slam] Eliminate variable-length stack allocation Signed-off-by: Michael Brown --- src/net/udp/slam.c | 24 +++++++++++++++++++----- 1 file changed, 19 insertions(+), 5 deletions(-) (limited to 'src') diff --git a/src/net/udp/slam.c b/src/net/udp/slam.c index c165b4fb9..d9e91dd1c 100644 --- a/src/net/udp/slam.c +++ b/src/net/udp/slam.c @@ -656,13 +656,18 @@ static struct interface_descriptor slam_xfer_desc = static int slam_parse_multicast_address ( struct slam_request *slam, const char *path, struct sockaddr_in *address ) { - char path_dup[ strlen ( path ) /* no +1 */ ]; + char *path_dup; char *sep; char *end; + int rc; /* Create temporary copy of path, minus the leading '/' */ assert ( *path == '/' ); - memcpy ( path_dup, ( path + 1 ) , sizeof ( path_dup ) ); + path_dup = strdup ( path + 1 ); + if ( ! path_dup ) { + rc = -ENOMEM; + goto err_strdup; + } /* Parse port, if present */ sep = strchr ( path_dup, ':' ); @@ -672,7 +677,8 @@ static int slam_parse_multicast_address ( struct slam_request *slam, if ( *end != '\0' ) { DBGC ( slam, "SLAM %p invalid multicast port " "\"%s\"\n", slam, sep ); - return -EINVAL; + rc = -EINVAL; + goto err_port; } } @@ -680,10 +686,18 @@ static int slam_parse_multicast_address ( struct slam_request *slam, if ( inet_aton ( path_dup, &address->sin_addr ) == 0 ) { DBGC ( slam, "SLAM %p invalid multicast address \"%s\"\n", slam, path_dup ); - return -EINVAL; + rc = -EINVAL; + goto err_addr; } - return 0; + /* Success */ + rc = 0; + + err_addr: + err_port: + free ( path_dup ); + err_strdup: + return rc; } /** -- cgit v1.2.3-55-g7522 From 0a74321915f6eca36ada1e5566b9c7d59ff93746 Mon Sep 17 00:00:00 2001 From: Michael Brown Date: Sun, 16 Feb 2020 22:02:25 +0000 Subject: [slam] Allow for the possibility of IPv6 multicast addresses Signed-off-by: Michael Brown --- src/net/udp/slam.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) (limited to 'src') diff --git a/src/net/udp/slam.c b/src/net/udp/slam.c index d9e91dd1c..47f60080b 100644 --- a/src/net/udp/slam.c +++ b/src/net/udp/slam.c @@ -655,7 +655,7 @@ static struct interface_descriptor slam_xfer_desc = */ static int slam_parse_multicast_address ( struct slam_request *slam, const char *path, - struct sockaddr_in *address ) { + struct sockaddr_tcpip *address ) { char *path_dup; char *sep; char *end; @@ -673,7 +673,7 @@ static int slam_parse_multicast_address ( struct slam_request *slam, sep = strchr ( path_dup, ':' ); if ( sep ) { *(sep++) = '\0'; - address->sin_port = htons ( strtoul ( sep, &end, 0 ) ); + address->st_port = htons ( strtoul ( sep, &end, 0 ) ); if ( *end != '\0' ) { DBGC ( slam, "SLAM %p invalid multicast port " "\"%s\"\n", slam, sep ); @@ -683,7 +683,7 @@ static int slam_parse_multicast_address ( struct slam_request *slam, } /* Parse address */ - if ( inet_aton ( path_dup, &address->sin_addr ) == 0 ) { + if ( sock_aton ( path_dup, ( ( struct sockaddr * ) address ) ) == 0 ) { DBGC ( slam, "SLAM %p invalid multicast address \"%s\"\n", slam, path_dup ); rc = -EINVAL; @@ -715,7 +715,7 @@ static int slam_open ( struct interface *xfer, struct uri *uri ) { }; struct slam_request *slam; struct sockaddr_tcpip server; - struct sockaddr_in multicast; + struct sockaddr_tcpip multicast; int rc; /* Sanity checks */ -- cgit v1.2.3-55-g7522 From 446e8f14e8a22731b52bad45d94b09f6f1672bd9 Mon Sep 17 00:00:00 2001 From: Michael Brown Date: Sun, 16 Feb 2020 22:30:38 +0000 Subject: [settings] Eliminate variable-length stack allocation Signed-off-by: Michael Brown --- src/core/settings.c | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) (limited to 'src') diff --git a/src/core/settings.c b/src/core/settings.c index 3e5d416e7..430cdc84b 100644 --- a/src/core/settings.c +++ b/src/core/settings.c @@ -370,12 +370,14 @@ const char * settings_name ( struct settings *settings ) { static struct settings * parse_settings_name ( const char *name, get_child_settings_t get_child ) { struct settings *settings = &settings_root; - char name_copy[ strlen ( name ) + 1 ]; + char *name_copy; char *subname; char *remainder; /* Create modifiable copy of name */ - memcpy ( name_copy, name, sizeof ( name_copy ) ); + name_copy = strdup ( name ); + if ( ! name_copy ) + return NULL; remainder = name_copy; /* Parse each name component in turn */ @@ -389,6 +391,9 @@ parse_settings_name ( const char *name, get_child_settings_t get_child ) { break; } + /* Free modifiable copy of name */ + free ( name_copy ); + return settings; } -- cgit v1.2.3-55-g7522 From e2e29e7ae3608261314feab118f887f13d60b5c6 Mon Sep 17 00:00:00 2001 From: Michael Brown Date: Sun, 16 Feb 2020 23:19:03 +0000 Subject: [iscsi] Eliminate variable-length stack allocations in CHAP handlers Signed-off-by: Michael Brown --- src/net/tcp/iscsi.c | 52 +++++++++++++++++++++++++++++++++++++++++----------- 1 file changed, 41 insertions(+), 11 deletions(-) (limited to 'src') diff --git a/src/net/tcp/iscsi.c b/src/net/tcp/iscsi.c index f8379b285..4be9c1c04 100644 --- a/src/net/tcp/iscsi.c +++ b/src/net/tcp/iscsi.c @@ -980,18 +980,26 @@ static int iscsi_handle_chap_i_value ( struct iscsi_session *iscsi, */ static int iscsi_handle_chap_c_value ( struct iscsi_session *iscsi, const char *value ) { - uint8_t buf[ strlen ( value ) ]; /* Decoding never expands data */ + uint8_t *buf; unsigned int i; int len; int rc; + /* Allocate decoding buffer */ + len = strlen ( value ); /* Decoding never expands data */ + buf = malloc ( len ); + if ( ! buf ) { + rc = -ENOMEM; + goto err_alloc; + } + /* Process challenge */ - len = iscsi_large_binary_decode ( value, buf, sizeof ( buf ) ); + len = iscsi_large_binary_decode ( value, buf, len ); if ( len < 0 ) { rc = len; DBGC ( iscsi, "iSCSI %p invalid CHAP challenge \"%s\": %s\n", iscsi, value, strerror ( rc ) ); - return rc; + goto err_decode; } chap_update ( &iscsi->chap, buf, len ); @@ -1009,7 +1017,13 @@ static int iscsi_handle_chap_c_value ( struct iscsi_session *iscsi, } } - return 0; + /* Success */ + rc = 0; + + err_decode: + free ( buf ); + err_alloc: + return rc; } /** @@ -1050,7 +1064,7 @@ static int iscsi_handle_chap_n_value ( struct iscsi_session *iscsi, */ static int iscsi_handle_chap_r_value ( struct iscsi_session *iscsi, const char *value ) { - uint8_t buf[ strlen ( value ) ]; /* Decoding never expands data */ + uint8_t *buf; int len; int rc; @@ -1059,7 +1073,7 @@ static int iscsi_handle_chap_r_value ( struct iscsi_session *iscsi, if ( ( rc = chap_init ( &iscsi->chap, &md5_algorithm ) ) != 0 ) { DBGC ( iscsi, "iSCSI %p could not initialise CHAP: %s\n", iscsi, strerror ( rc ) ); - return rc; + goto err_chap_init; } chap_set_identifier ( &iscsi->chap, iscsi->chap_challenge[0] ); if ( iscsi->target_password ) { @@ -1070,31 +1084,47 @@ static int iscsi_handle_chap_r_value ( struct iscsi_session *iscsi, ( sizeof ( iscsi->chap_challenge ) - 1 ) ); chap_respond ( &iscsi->chap ); + /* Allocate decoding buffer */ + len = strlen ( value ); /* Decoding never expands data */ + buf = malloc ( len ); + if ( ! buf ) { + rc = -ENOMEM; + goto err_alloc; + } + /* Process response */ - len = iscsi_large_binary_decode ( value, buf, sizeof ( buf ) ); + len = iscsi_large_binary_decode ( value, buf, len ); if ( len < 0 ) { rc = len; DBGC ( iscsi, "iSCSI %p invalid CHAP response \"%s\": %s\n", iscsi, value, strerror ( rc ) ); - return rc; + goto err_decode; } /* Check CHAP response */ if ( len != ( int ) iscsi->chap.response_len ) { DBGC ( iscsi, "iSCSI %p invalid CHAP response length\n", iscsi ); - return -EPROTO_INVALID_CHAP_RESPONSE; + rc = -EPROTO_INVALID_CHAP_RESPONSE; + goto err_response_len; } if ( memcmp ( buf, iscsi->chap.response, len ) != 0 ) { DBGC ( iscsi, "iSCSI %p incorrect CHAP response \"%s\"\n", iscsi, value ); - return -EACCES_INCORRECT_TARGET_PASSWORD; + rc = -EACCES_INCORRECT_TARGET_PASSWORD; + goto err_response; } /* Mark session as authenticated */ iscsi->status |= ISCSI_STATUS_AUTH_REVERSE_OK; - return 0; + err_response: + err_response_len: + err_decode: + free ( buf ); + err_alloc: + err_chap_init: + return rc; } /** An iSCSI text string that we want to handle */ -- cgit v1.2.3-55-g7522 From e3ca2110712f6472465c70f2e83b745ff8a25fcc Mon Sep 17 00:00:00 2001 From: Michael Brown Date: Sun, 16 Feb 2020 23:46:33 +0000 Subject: [iscsi] Eliminate variable-length stack allocation in URI parsing Signed-off-by: Michael Brown --- src/net/tcp/iscsi.c | 38 ++++++++++++++++++++++++++++---------- 1 file changed, 28 insertions(+), 10 deletions(-) (limited to 'src') diff --git a/src/net/tcp/iscsi.c b/src/net/tcp/iscsi.c index 4be9c1c04..3a44b90f0 100644 --- a/src/net/tcp/iscsi.c +++ b/src/net/tcp/iscsi.c @@ -1948,15 +1948,22 @@ const struct setting reverse_password_setting __setting ( SETTING_AUTH_EXTRA, */ static int iscsi_parse_root_path ( struct iscsi_session *iscsi, const char *root_path ) { - char rp_copy[ strlen ( root_path ) + 1 ]; + char *rp_copy; char *rp_comp[NUM_RP_COMPONENTS]; - char *rp = rp_copy; + char *rp; int skip = 0; int i = 0; int rc; + /* Create modifiable copy of root path */ + rp_copy = strdup ( root_path ); + if ( ! rp_copy ) { + rc = -ENOMEM; + goto err_strdup; + } + rp = rp_copy; + /* Split root path into component parts */ - strcpy ( rp_copy, root_path ); while ( 1 ) { rp_comp[i++] = rp; if ( i == NUM_RP_COMPONENTS ) @@ -1965,7 +1972,8 @@ static int iscsi_parse_root_path ( struct iscsi_session *iscsi, if ( ! *rp ) { DBGC ( iscsi, "iSCSI %p root path \"%s\" " "too short\n", iscsi, root_path ); - return -EINVAL_ROOT_PATH_TOO_SHORT; + rc = -EINVAL_ROOT_PATH_TOO_SHORT; + goto err_split; } else if ( *rp == '[' ) { skip = 1; } else if ( *rp == ']' ) { @@ -1977,21 +1985,31 @@ static int iscsi_parse_root_path ( struct iscsi_session *iscsi, /* Use root path components to configure iSCSI session */ iscsi->target_address = strdup ( rp_comp[RP_SERVERNAME] ); - if ( ! iscsi->target_address ) - return -ENOMEM; + if ( ! iscsi->target_address ) { + rc = -ENOMEM; + goto err_servername; + } iscsi->target_port = strtoul ( rp_comp[RP_PORT], NULL, 10 ); if ( ! iscsi->target_port ) iscsi->target_port = ISCSI_PORT; if ( ( rc = scsi_parse_lun ( rp_comp[RP_LUN], &iscsi->lun ) ) != 0 ) { DBGC ( iscsi, "iSCSI %p invalid LUN \"%s\"\n", iscsi, rp_comp[RP_LUN] ); - return rc; + goto err_lun; } iscsi->target_iqn = strdup ( rp_comp[RP_TARGETNAME] ); - if ( ! iscsi->target_iqn ) - return -ENOMEM; + if ( ! iscsi->target_iqn ) { + rc = -ENOMEM; + goto err_targetname; + } - return 0; + err_targetname: + err_lun: + err_servername: + err_split: + free ( rp_copy ); + err_strdup: + return rc; } /** -- cgit v1.2.3-55-g7522