| From foo@baz Sun Jun 17 12:07:34 CEST 2018 |
| From: David Howells <dhowells@redhat.com> |
| Date: Wed, 9 May 2018 22:03:18 +0100 |
| Subject: afs: Fix address list parsing |
| |
| From: David Howells <dhowells@redhat.com> |
| |
| [ 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> |
| --- |
| fs/afs/addr_list.c | 25 +++++++++++++++---------- |
| 1 file changed, 15 insertions(+), 10 deletions(-) |
| |
| --- a/fs/afs/addr_list.c |
| +++ b/fs/afs/addr_list.c |
| @@ -121,7 +121,7 @@ struct afs_addr_list *afs_parse_text_add |
| 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_add |
| |
| 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 == '+') { |