Skip to content

Commit f28b089

Browse files
committed
Fix unportable use of getnameinfo() in pg_hba_file_rules view.
fill_hba_line() thought it could get away with passing sizeof(struct sockaddr_storage) rather than the actual addrlen previously returned by getaddrinfo(). While that appears to work on many platforms, it does not work on FreeBSD 11: you get back a failure, which leads to the view showing NULL for the address and netmask columns in all rows. The POSIX spec for getnameinfo() is pretty clearly on FreeBSD's side here: you should pass the actual address length. So it seems plausible that there are other platforms where this coding also fails, and we just hadn't noticed. Also, IMO the fact that getnameinfo() failure leads to a NULL output is pretty bogus in itself. Our pg_getnameinfo_all() wrapper is careful to emit "???" on failure, and we should use that in such cases. NULL should only be emitted in rows that don't have IP addresses. Per bug #16695 from Peter Vandivier. Back-patch to v10 where this code was added. Discussion: https://postgr.es/m/16695-a665558e2f630be7@postgresql.org
1 parent fc5b220 commit f28b089

File tree

2 files changed

+27
-10
lines changed

2 files changed

+27
-10
lines changed

src/backend/libpq/hba.c

Lines changed: 21 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -1151,8 +1151,11 @@ parse_hba_line(TokenizedLine *tok_line, int elevel)
11511151

11521152
ret = pg_getaddrinfo_all(str, NULL, &hints, &gai_result);
11531153
if (ret == 0 && gai_result)
1154+
{
11541155
memcpy(&parsedline->addr, gai_result->ai_addr,
11551156
gai_result->ai_addrlen);
1157+
parsedline->addrlen = gai_result->ai_addrlen;
1158+
}
11561159
else if (ret == EAI_NONAME)
11571160
parsedline->hostname = str;
11581161
else
@@ -1201,6 +1204,7 @@ parse_hba_line(TokenizedLine *tok_line, int elevel)
12011204
token->string);
12021205
return NULL;
12031206
}
1207+
parsedline->masklen = parsedline->addrlen;
12041208
pfree(str);
12051209
}
12061210
else if (!parsedline->hostname)
@@ -1251,6 +1255,7 @@ parse_hba_line(TokenizedLine *tok_line, int elevel)
12511255

12521256
memcpy(&parsedline->mask, gai_result->ai_addr,
12531257
gai_result->ai_addrlen);
1258+
parsedline->masklen = gai_result->ai_addrlen;
12541259
pg_freeaddrinfo_all(hints.ai_family, gai_result);
12551260

12561261
if (parsedline->addr.ss_family != parsedline->mask.ss_family)
@@ -2455,20 +2460,26 @@ fill_hba_line(Tuplestorestate *tuple_store, TupleDesc tupdesc,
24552460
}
24562461
else
24572462
{
2458-
if (pg_getnameinfo_all(&hba->addr, sizeof(hba->addr),
2459-
buffer, sizeof(buffer),
2460-
NULL, 0,
2461-
NI_NUMERICHOST) == 0)
2463+
/*
2464+
* Note: if pg_getnameinfo_all fails, it'll set buffer to
2465+
* "???", which we want to return.
2466+
*/
2467+
if (hba->addrlen > 0)
24622468
{
2463-
clean_ipv6_addr(hba->addr.ss_family, buffer);
2469+
if (pg_getnameinfo_all(&hba->addr, hba->addrlen,
2470+
buffer, sizeof(buffer),
2471+
NULL, 0,
2472+
NI_NUMERICHOST) == 0)
2473+
clean_ipv6_addr(hba->addr.ss_family, buffer);
24642474
addrstr = pstrdup(buffer);
24652475
}
2466-
if (pg_getnameinfo_all(&hba->mask, sizeof(hba->mask),
2467-
buffer, sizeof(buffer),
2468-
NULL, 0,
2469-
NI_NUMERICHOST) == 0)
2476+
if (hba->masklen > 0)
24702477
{
2471-
clean_ipv6_addr(hba->mask.ss_family, buffer);
2478+
if (pg_getnameinfo_all(&hba->mask, hba->masklen,
2479+
buffer, sizeof(buffer),
2480+
NULL, 0,
2481+
NI_NUMERICHOST) == 0)
2482+
clean_ipv6_addr(hba->mask.ss_family, buffer);
24722483
maskstr = pstrdup(buffer);
24732484
}
24742485
}

src/include/libpq/hba.h

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -42,6 +42,10 @@ typedef enum UserAuth
4242
#define USER_AUTH_LAST uaPeer /* Must be last value of this enum */
4343
} UserAuth;
4444

45+
/*
46+
* Data structures representing pg_hba.conf entries
47+
*/
48+
4549
typedef enum IPCompareMethod
4650
{
4751
ipCmpMask,
@@ -99,6 +103,8 @@ typedef struct HbaLine
99103
char *radiusidentifiers_s;
100104
List *radiusports;
101105
char *radiusports_s;
106+
int addrlen; /* zero if we don't have a valid addr */
107+
int masklen; /* zero if we don't have a valid mask */
102108
} HbaLine;
103109

104110
typedef struct IdentLine

0 commit comments

Comments
 (0)