]> git.ipfire.org Git - thirdparty/haproxy.git/commitdiff
MEDIUM: tools: make str2sa_range() check for the sockpair's FD usability
authorWilly Tarreau <w@1wt.eu>
Wed, 16 Sep 2020 08:14:16 +0000 (10:14 +0200)
committerWilly Tarreau <w@1wt.eu>
Wed, 16 Sep 2020 20:08:08 +0000 (22:08 +0200)
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).

src/cfgparse.c
src/tools.c

index 7b5102452decc634d5bcdcae3f73893181d9c303..392a2bd1aebbf1f1f313ca10e1a2c493887d42b7 100644 (file)
@@ -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);
index db17fda0c213adefb766249e2869fae90040c848..e543fd6cd3a5bd94b4d14de62d6def1c4e70adfe 100644 (file)
@@ -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;
        }