From: Willy Tarreau Date: Wed, 16 Sep 2020 08:14:16 +0000 (+0200) Subject: MEDIUM: tools: make str2sa_range() check for the sockpair's FD usability X-Git-Tag: v2.3-dev5~31 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=a215be282d4467a01c962b10bf4132101794557c;p=thirdparty%2Fhaproxy.git MEDIUM: tools: make str2sa_range() check for the sockpair's FD usability Just like for inherited sockets, we want to make sure that FDs that are mentioned in "sockpair@" are actually usable. Right now this test is performed by the callers, but not everywhere. Typically, the following config will fail if fd #5 is not bound: frontend bind sockpair@5 But this one will pass if fd #6 is not bound: backend server s1 sockpair@6 Now both will return an error in such a case: - 'bind' : cannot use file descriptor '5' : Bad file descriptor. - 'server s1' : cannot use file descriptor '6' : Bad file descriptor. As such the test in str2listener() is not needed anymore (and it was wrong by the way, as it used to test for the socket by overwriting the local address with a new address that's made of the FD encoded on 16 bits and happens to still be at the same place, but that strictly depends on whatever the kernel wants to put there). --- diff --git a/src/cfgparse.c b/src/cfgparse.c index 7b5102452d..392a2bd1ae 100644 --- a/src/cfgparse.c +++ b/src/cfgparse.c @@ -133,20 +133,6 @@ int str2listener(char *str, struct proxy *curproxy, struct bind_conf *bind_conf, if (!ss2) goto fail; - if (ss2->ss_family == AF_CUST_SOCKPAIR) { - socklen_t addr_len; - - fd = ((struct sockaddr_in *)ss2)->sin_addr.s_addr; - addr_len = sizeof(*ss2); - if (getsockname(fd, (struct sockaddr *)ss2, &addr_len) == -1) { - memprintf(err, "cannot use file descriptor '%d' : %s.\n", fd, strerror(errno)); - goto fail; - } - - ss2->ss_family = AF_CUST_SOCKPAIR; /* reassign AF_CUST_SOCKPAIR because of getsockname */ - port = end = 0; - } - /* OK the address looks correct */ if (!create_listeners(bind_conf, ss2, port, end, fd, err)) { memprintf(err, "%s for address '%s'.\n", *err, str); diff --git a/src/tools.c b/src/tools.c index db17fda0c2..e543fd6cd3 100644 --- a/src/tools.c +++ b/src/tools.c @@ -943,6 +943,8 @@ struct sockaddr_storage *str2sa_range(const char *str, int *port, int *low, int ss.ss_family = AF_UNSPEC; if (ss.ss_family == AF_CUST_SOCKPAIR) { + struct sockaddr_storage ss2; + socklen_t addr_len; char *endptr; new_fd = strtol(str2, &endptr, 10); @@ -951,6 +953,13 @@ struct sockaddr_storage *str2sa_range(const char *str, int *port, int *low, int goto out; } + /* just verify that it's a socket */ + addr_len = sizeof(ss2); + if (getsockname(new_fd, (struct sockaddr *)&ss2, &addr_len) == -1) { + memprintf(err, "cannot use file descriptor '%d' : %s.\n", new_fd, strerror(errno)); + goto out; + } + ((struct sockaddr_in *)&ss)->sin_addr.s_addr = new_fd; ((struct sockaddr_in *)&ss)->sin_port = 0; }