Movatterモバイル変換


[0]ホーム

URL:


Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up
Appearance settings

Commit87b46ad

Browse files
committed
Be more wary about OpenSSL not setting errno on error.
OpenSSL will sometimes return SSL_ERROR_SYSCALL without having seterrno; this is apparently a reflection of recv(2)'s habit of notsetting errno when reporting EOF. Ensure that we treat such casesthe same as read EOF. Previously, we'd frequently report them like"could not accept SSL connection: Success" which is confusing, orworse report them with an unrelated errno left over from someprevious syscall.To fix, ensure that errno is zeroed immediately before the call,and report its value only when it's not zero afterwards; otherwisereport EOF.For consistency, I've applied the same coding pattern in libpq'spqsecure_raw_read(). Bare recv(2) shouldn't really return -1 withoutsetting errno, but in case it does we might as well cope.Per report from Andres Freund. Back-patch to all supported versions.Discussion:https://postgr.es/m/20231208181451.deqnflwxqoehhxpe@awork3.anarazel.de
1 parentb47ea4f commit87b46ad

File tree

4 files changed

+46
-14
lines changed

4 files changed

+46
-14
lines changed

‎src/backend/libpq/be-secure-openssl.c

Lines changed: 11 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -424,6 +424,7 @@ be_tls_open_server(Port *port)
424424
* per-thread error queue following another call to an OpenSSL I/O
425425
* routine.
426426
*/
427+
errno=0;
427428
ERR_clear_error();
428429
r=SSL_accept(port->ssl);
429430
if (r <=0)
@@ -460,7 +461,7 @@ be_tls_open_server(Port *port)
460461
WAIT_EVENT_SSL_OPEN_SERVER);
461462
gotoaloop;
462463
caseSSL_ERROR_SYSCALL:
463-
if (r<0)
464+
if (r<0&&errno!=0)
464465
ereport(COMMERROR,
465466
(errcode_for_socket_access(),
466467
errmsg("could not accept SSL connection: %m")));
@@ -636,7 +637,7 @@ be_tls_read(Port *port, void *ptr, size_t len, int *waitfor)
636637
break;
637638
caseSSL_ERROR_SYSCALL:
638639
/* leave it to caller to ereport the value of errno */
639-
if (n!=-1)
640+
if (n!=-1||errno==0)
640641
{
641642
errno=ECONNRESET;
642643
n=-1;
@@ -694,8 +695,14 @@ be_tls_write(Port *port, void *ptr, size_t len, int *waitfor)
694695
n=-1;
695696
break;
696697
caseSSL_ERROR_SYSCALL:
697-
/* leave it to caller to ereport the value of errno */
698-
if (n!=-1)
698+
699+
/*
700+
* Leave it to caller to ereport the value of errno. However, if
701+
* errno is still zero then assume it's a read EOF situation, and
702+
* report ECONNRESET. (This seems possible because SSL_write can
703+
* also do reads.)
704+
*/
705+
if (n!=-1||errno==0)
699706
{
700707
errno=ECONNRESET;
701708
n=-1;

‎src/backend/libpq/pqcomm.c

Lines changed: 16 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -944,6 +944,8 @@ pq_recvbuf(void)
944944
{
945945
intr;
946946

947+
errno=0;
948+
947949
r=secure_read(MyProcPort,PqRecvBuffer+PqRecvLength,
948950
PQ_RECV_BUFFER_SIZE-PqRecvLength);
949951

@@ -956,10 +958,13 @@ pq_recvbuf(void)
956958
* Careful: an ereport() that tries to write to the client would
957959
* cause recursion to here, leading to stack overflow and core
958960
* dump! This message must go *only* to the postmaster log.
961+
*
962+
* If errno is zero, assume it's EOF and let the caller complain.
959963
*/
960-
ereport(COMMERROR,
961-
(errcode_for_socket_access(),
962-
errmsg("could not receive data from client: %m")));
964+
if (errno!=0)
965+
ereport(COMMERROR,
966+
(errcode_for_socket_access(),
967+
errmsg("could not receive data from client: %m")));
963968
returnEOF;
964969
}
965970
if (r==0)
@@ -1036,6 +1041,8 @@ pq_getbyte_if_available(unsigned char *c)
10361041
/* Put the socket into non-blocking mode */
10371042
socket_set_nonblocking(true);
10381043

1044+
errno=0;
1045+
10391046
r=secure_read(MyProcPort,c,1);
10401047
if (r<0)
10411048
{
@@ -1052,10 +1059,13 @@ pq_getbyte_if_available(unsigned char *c)
10521059
* Careful: an ereport() that tries to write to the client would
10531060
* cause recursion to here, leading to stack overflow and core
10541061
* dump! This message must go *only* to the postmaster log.
1062+
*
1063+
* If errno is zero, assume it's EOF and let the caller complain.
10551064
*/
1056-
ereport(COMMERROR,
1057-
(errcode_for_socket_access(),
1058-
errmsg("could not receive data from client: %m")));
1065+
if (errno!=0)
1066+
ereport(COMMERROR,
1067+
(errcode_for_socket_access(),
1068+
errmsg("could not receive data from client: %m")));
10591069
r=EOF;
10601070
}
10611071
}

‎src/interfaces/libpq/fe-secure-openssl.c

Lines changed: 12 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -200,7 +200,7 @@ pgtls_read(PGconn *conn, void *ptr, size_t len)
200200
*/
201201
gotorloop;
202202
caseSSL_ERROR_SYSCALL:
203-
if (n<0)
203+
if (n<0&&SOCK_ERRNO!=0)
204204
{
205205
result_errno=SOCK_ERRNO;
206206
if (result_errno==EPIPE||
@@ -308,7 +308,13 @@ pgtls_write(PGconn *conn, const void *ptr, size_t len)
308308
n=0;
309309
break;
310310
caseSSL_ERROR_SYSCALL:
311-
if (n<0)
311+
312+
/*
313+
* If errno is still zero then assume it's a read EOF situation,
314+
* and report EOF. (This seems possible because SSL_write can
315+
* also do reads.)
316+
*/
317+
if (n<0&&SOCK_ERRNO!=0)
312318
{
313319
result_errno=SOCK_ERRNO;
314320
if (result_errno==EPIPE||result_errno==ECONNRESET)
@@ -1305,10 +1311,12 @@ open_client_SSL(PGconn *conn)
13051311
{
13061312
intr;
13071313

1314+
SOCK_ERRNO_SET(0);
13081315
ERR_clear_error();
13091316
r=SSL_connect(conn->ssl);
13101317
if (r <=0)
13111318
{
1319+
intsave_errno=SOCK_ERRNO;
13121320
interr=SSL_get_error(conn->ssl,r);
13131321
unsigned longecode;
13141322

@@ -1325,10 +1333,10 @@ open_client_SSL(PGconn *conn)
13251333
{
13261334
charsebuf[PG_STRERROR_R_BUFLEN];
13271335

1328-
if (r==-1)
1336+
if (r==-1&&save_errno!=0)
13291337
printfPQExpBuffer(&conn->errorMessage,
13301338
libpq_gettext("SSL SYSCALL error: %s\n"),
1331-
SOCK_STRERROR(SOCK_ERRNO,sebuf,sizeof(sebuf)));
1339+
SOCK_STRERROR(save_errno,sebuf,sizeof(sebuf)));
13321340
else
13331341
printfPQExpBuffer(&conn->errorMessage,
13341342
libpq_gettext("SSL SYSCALL error: EOF detected\n"));

‎src/interfaces/libpq/fe-secure.c

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -242,6 +242,8 @@ pqsecure_raw_read(PGconn *conn, void *ptr, size_t len)
242242
intresult_errno=0;
243243
charsebuf[PG_STRERROR_R_BUFLEN];
244244

245+
SOCK_ERRNO_SET(0);
246+
245247
n=recv(conn->sock,ptr,len,0);
246248

247249
if (n<0)
@@ -270,6 +272,11 @@ pqsecure_raw_read(PGconn *conn, void *ptr, size_t len)
270272
break;
271273
#endif
272274

275+
case0:
276+
/* If errno didn't get set, treat it as regular EOF */
277+
n=0;
278+
break;
279+
273280
default:
274281
printfPQExpBuffer(&conn->errorMessage,
275282
libpq_gettext("could not receive data from server: %s\n"),

0 commit comments

Comments
 (0)

[8]ページ先頭

©2009-2025 Movatter.jp