]> git.proxmox.com Git - mirror_ubuntu-bionic-kernel.git/commitdiff
afs: Fix address list parsing
authorDavid Howells <dhowells@redhat.com>
Wed, 9 May 2018 21:03:18 +0000 (22:03 +0100)
committerStefan Bader <stefan.bader@canonical.com>
Mon, 1 Oct 2018 12:58:14 +0000 (14:58 +0200)
BugLink: http://bugs.launchpad.net/bugs/1794889
[ Upstream commit 01fd79e6de74a447c5657913a335d9ce6508cdb1 ]

The parsing of port specifiers in the address list obtained from the DNS
resolution upcall doesn't work as in4_pton() and in6_pton() will fail on
encountering an unexpected delimiter (in this case, the '+' marking the
port number).  However, in*_pton() can't be given multiple specifiers.

Fix this by finding the delimiter in advance and not relying on in*_pton()
to find the end of the address for us.

Fixes: 8b2a464ced77 ("afs: Add an address list concept")
Signed-off-by: David Howells <dhowells@redhat.com>
Signed-off-by: Sasha Levin <alexander.levin@microsoft.com>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
Signed-off-by: Kamal Mostafa <kamal@canonical.com>
Signed-off-by: Stefan Bader <stefan.bader@canonical.com>
fs/afs/addr_list.c

index fd9f28b8a933a9eacff9b17230581ff8bf37f64e..88391c7a84628195be312bc655902c004e7e0e75 100644 (file)
@@ -121,7 +121,7 @@ struct afs_addr_list *afs_parse_text_addrs(const char *text, size_t len,
        p = text;
        do {
                struct sockaddr_rxrpc *srx = &alist->addrs[alist->nr_addrs];
-               char tdelim = delim;
+               const char *q, *stop;
 
                if (*p == delim) {
                        p++;
@@ -130,28 +130,33 @@ struct afs_addr_list *afs_parse_text_addrs(const char *text, size_t len,
 
                if (*p == '[') {
                        p++;
-                       tdelim = ']';
+                       q = memchr(p, ']', end - p);
+               } else {
+                       for (q = p; q < end; q++)
+                               if (*q == '+' || *q == delim)
+                                       break;
                }
 
-               if (in4_pton(p, end - p,
+               if (in4_pton(p, q - p,
                             (u8 *)&srx->transport.sin6.sin6_addr.s6_addr32[3],
-                            tdelim, &p)) {
+                            -1, &stop)) {
                        srx->transport.sin6.sin6_addr.s6_addr32[0] = 0;
                        srx->transport.sin6.sin6_addr.s6_addr32[1] = 0;
                        srx->transport.sin6.sin6_addr.s6_addr32[2] = htonl(0xffff);
-               } else if (in6_pton(p, end - p,
+               } else if (in6_pton(p, q - p,
                                    srx->transport.sin6.sin6_addr.s6_addr,
-                                   tdelim, &p)) {
+                                   -1, &stop)) {
                        /* Nothing to do */
                } else {
                        goto bad_address;
                }
 
-               if (tdelim == ']') {
-                       if (p == end || *p != ']')
-                               goto bad_address;
+               if (stop != q)
+                       goto bad_address;
+
+               p = q;
+               if (q < end && *q == ']')
                        p++;
-               }
 
                if (p < end) {
                        if (*p == '+') {