From d0a150f1b30880f14a7c7769524fe23a3c65aa0b Mon Sep 17 00:00:00 2001 From: Dmitry Gladkov Date: Thu, 9 Feb 2017 14:08:37 +0300 Subject: [PATCH] The reproduction of "prov/socket segfaults in sock_ep_connect() when it tries to dereference dest_addr" issue https://github.com/ofiwg/libfabric/issues/2676 fi_msg_sockets: Add new test case that covers Issue #2676 Invokes fi_send when no connect is established and no destination addres:port pair is passed to fi_info Change-Id: I1a64131eafa882b9f60a725d055ede039ad2250b Signed-off-by: Gladkov, Dmitry --- common/shared.c | 4 +++ include/shared.h | 8 +++++- scripts/runfabtests.sh | 1 + simple/msg_sockets.c | 55 ++++++++++++++++++++++++++++++++++++++---- 4 files changed, 62 insertions(+), 6 deletions(-) diff --git a/common/shared.c b/common/shared.c index a6330105..23013104 100644 --- a/common/shared.c +++ b/common/shared.c @@ -1660,6 +1660,7 @@ void ft_csusage(char *name, char *desc) FT_PRINT_OPTS_USAGE("-m", "machine readable output"); FT_PRINT_OPTS_USAGE("-t ", "completion type [queue, counter]"); FT_PRINT_OPTS_USAGE("-c ", "completion method [spin, sread, fd]"); + FT_PRINT_OPTS_USAGE("-u", "set destination addr:port in fi_connect only"); FT_PRINT_OPTS_USAGE("-h", "display this help output"); return; @@ -1772,6 +1773,9 @@ void ft_parsecsopts(int op, char *optarg, struct ft_opts *opts) case 'l': opts->options |= FT_OPT_ALIGN; break; + case 'u': + opts->dest_mode = FT_DEST_ADDR_ONLY_IN_FI_CONN; + break; default: /* let getopt handle unknown opts*/ break; diff --git a/include/shared.h b/include/shared.h index dbd70d44..b419183e 100644 --- a/include/shared.h +++ b/include/shared.h @@ -123,6 +123,11 @@ enum ft_rma_opcodes { FT_RMA_WRITEDATA, }; +enum ft_dest_addr_mode { + FT_DEST_ADDR_IN_FI_INFO = 0, + FT_DEST_ADDR_ONLY_IN_FI_CONN = 1 +}; + struct ft_opts { int iterations; int warmup_iterations; @@ -140,6 +145,7 @@ struct ft_opts { enum ft_rma_opcodes rma_op; int argc; char **argv; + enum ft_dest_addr_mode dest_mode; }; extern struct fi_info *fi_pep, *fi, *hints; @@ -200,7 +206,7 @@ extern int listen_sock; #define ADDR_OPTS "B:P:s:a:" #define FAB_OPTS "f:d:p:" #define INFO_OPTS FAB_OPTS "e:" -#define CS_OPTS ADDR_OPTS "I:S:mc:t:w:l" +#define CS_OPTS ADDR_OPTS "I:S:mc:t:w:lu" extern char default_port[8]; diff --git a/scripts/runfabtests.sh b/scripts/runfabtests.sh index e0deca02..0adf4167 100755 --- a/scripts/runfabtests.sh +++ b/scripts/runfabtests.sh @@ -81,6 +81,7 @@ simple_tests=( "msg" "msg_epoll" "msg_sockets" + "msg_sockets -u" "poll -t queue" "poll -t counter" "rdm" diff --git a/simple/msg_sockets.c b/simple/msg_sockets.c index 3e9293bb..aaae2039 100644 --- a/simple/msg_sockets.c +++ b/simple/msg_sockets.c @@ -37,6 +37,7 @@ #include #include #include +#include #include #include @@ -239,8 +240,22 @@ static int client_connect(void) uint32_t event; ssize_t rd; int ret; + struct sockaddr_in *dest_addr = NULL; + char *opts_dest_addr = NULL; + char *opts_dest_port = NULL; + const char *sendBuf = "Some data to server"; - ret = fi_getinfo(FT_FIVERSION, opts.dst_addr, opts.dst_port, 0, hints, &fi); + switch (opts.dest_mode) { + case FT_DEST_ADDR_ONLY_IN_FI_CONN: + break; + case FT_DEST_ADDR_IN_FI_INFO: + default: + opts_dest_addr = opts.dst_addr; + opts_dest_port = opts.dst_port; + break; + } + + ret = fi_getinfo(FT_FIVERSION, opts_dest_addr, opts_dest_port, 0, hints, &fi); if (ret) { FT_PRINTERR("fi_getinfo", ret); return ret; @@ -273,18 +288,47 @@ static int client_connect(void) if (ret) return ret; + switch (opts.dest_mode) { + case FT_DEST_ADDR_ONLY_IN_FI_CONN: + ret = fi_send(ep, sendBuf, strlen(sendBuf) + 1, fi_mr_desc(mr), + remote_fi_addr, NULL); + if (ret >= 0) { + FT_ERR("Unexpected result of fi_send - %d (ep %p)", ret, ep); + return -FI_EOTHER; + } + /* Allocate and fill destination address of server */ + dest_addr = calloc(1, sizeof(struct sockaddr_in)); + if (!dest_addr) { + return -FI_ENOMEM; + } + dest_addr->sin_family = AF_INET; + dest_addr->sin_port = htons(atoi(opts.dst_port)); + inet_aton(opts.dst_addr, &dest_addr->sin_addr); + break; + case FT_DEST_ADDR_IN_FI_INFO: + default: + dest_addr = fi->dest_addr; + break; + } + /* Connect to server */ - ret = fi_connect(ep, fi->dest_addr, NULL, 0); + ret = fi_connect(ep, dest_addr, NULL, 0); if (ret) { FT_PRINTERR("fi_connect", ret); + free(dest_addr); return ret; } + /* Free destination address of server */ + if (opts.dest_mode == FT_DEST_ADDR_ONLY_IN_FI_CONN) { + free(dest_addr); + } + /* Wait for the connection to be established */ rd = fi_eq_sread(eq, &event, &entry, sizeof entry, -1, 0); if (rd != sizeof entry) { FT_PROCESS_EQ_ERR(rd, eq, "fi_eq_sread", "listen"); - return (int) rd; + return rd; } if (event != FI_CONNECTED || entry.fid != &ep->fid) { @@ -446,16 +490,17 @@ int main(int argc, char **argv) opts = INIT_OPTS; opts.options |= FT_OPT_SIZE; + opts.dest_mode = FT_DEST_ADDR_IN_FI_INFO; hints = fi_allocinfo(); if (!hints) return EXIT_FAILURE; - while ((op = getopt(argc, argv, "h" ADDR_OPTS INFO_OPTS)) != -1) { + while ((op = getopt(argc, argv, "h" CS_OPTS INFO_OPTS)) != -1) { switch (op) { default: - ft_parse_addr_opts(op, optarg, &opts); ft_parseinfo(op, optarg, hints); + ft_parsecsopts(op, optarg, &opts); break; case '?': case 'h':