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

Commit271d24f

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 parentc922b24 commit271d24f

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
@@ -417,6 +417,7 @@ be_tls_open_server(Port *port)
417417
* per-thread error queue following another call to an OpenSSL I/O
418418
* routine.
419419
*/
420+
errno=0;
420421
ERR_clear_error();
421422
r=SSL_accept(port->ssl);
422423
if (r <=0)
@@ -453,7 +454,7 @@ be_tls_open_server(Port *port)
453454
WAIT_EVENT_SSL_OPEN_SERVER);
454455
gotoaloop;
455456
caseSSL_ERROR_SYSCALL:
456-
if (r<0)
457+
if (r<0&&errno!=0)
457458
ereport(COMMERROR,
458459
(errcode_for_socket_access(),
459460
errmsg("could not accept SSL connection: %m")));
@@ -587,7 +588,7 @@ be_tls_read(Port *port, void *ptr, size_t len, int *waitfor)
587588
break;
588589
caseSSL_ERROR_SYSCALL:
589590
/* leave it to caller to ereport the value of errno */
590-
if (n!=-1)
591+
if (n!=-1||errno==0)
591592
{
592593
errno=ECONNRESET;
593594
n=-1;
@@ -645,8 +646,14 @@ be_tls_write(Port *port, void *ptr, size_t len, int *waitfor)
645646
n=-1;
646647
break;
647648
caseSSL_ERROR_SYSCALL:
648-
/* leave it to caller to ereport the value of errno */
649-
if (n!=-1)
649+
650+
/*
651+
* Leave it to caller to ereport the value of errno. However, if
652+
* errno is still zero then assume it's a read EOF situation, and
653+
* report ECONNRESET. (This seems possible because SSL_write can
654+
* also do reads.)
655+
*/
656+
if (n!=-1||errno==0)
650657
{
651658
errno=ECONNRESET;
652659
n=-1;

‎src/backend/libpq/pqcomm.c

Lines changed: 16 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -958,6 +958,8 @@ pq_recvbuf(void)
958958
{
959959
intr;
960960

961+
errno=0;
962+
961963
r=secure_read(MyProcPort,PqRecvBuffer+PqRecvLength,
962964
PQ_RECV_BUFFER_SIZE-PqRecvLength);
963965

@@ -970,10 +972,13 @@ pq_recvbuf(void)
970972
* Careful: an ereport() that tries to write to the client would
971973
* cause recursion to here, leading to stack overflow and core
972974
* dump! This message must go *only* to the postmaster log.
975+
*
976+
* If errno is zero, assume it's EOF and let the caller complain.
973977
*/
974-
ereport(COMMERROR,
975-
(errcode_for_socket_access(),
976-
errmsg("could not receive data from client: %m")));
978+
if (errno!=0)
979+
ereport(COMMERROR,
980+
(errcode_for_socket_access(),
981+
errmsg("could not receive data from client: %m")));
977982
returnEOF;
978983
}
979984
if (r==0)
@@ -1050,6 +1055,8 @@ pq_getbyte_if_available(unsigned char *c)
10501055
/* Put the socket into non-blocking mode */
10511056
socket_set_nonblocking(true);
10521057

1058+
errno=0;
1059+
10531060
r=secure_read(MyProcPort,c,1);
10541061
if (r<0)
10551062
{
@@ -1066,10 +1073,13 @@ pq_getbyte_if_available(unsigned char *c)
10661073
* Careful: an ereport() that tries to write to the client would
10671074
* cause recursion to here, leading to stack overflow and core
10681075
* dump! This message must go *only* to the postmaster log.
1076+
*
1077+
* If errno is zero, assume it's EOF and let the caller complain.
10691078
*/
1070-
ereport(COMMERROR,
1071-
(errcode_for_socket_access(),
1072-
errmsg("could not receive data from client: %m")));
1079+
if (errno!=0)
1080+
ereport(COMMERROR,
1081+
(errcode_for_socket_access(),
1082+
errmsg("could not receive data from client: %m")));
10731083
r=EOF;
10741084
}
10751085
}

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

Lines changed: 12 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -196,7 +196,7 @@ pgtls_read(PGconn *conn, void *ptr, size_t len)
196196
*/
197197
gotorloop;
198198
caseSSL_ERROR_SYSCALL:
199-
if (n<0)
199+
if (n<0&&SOCK_ERRNO!=0)
200200
{
201201
result_errno=SOCK_ERRNO;
202202
if (result_errno==EPIPE||
@@ -305,7 +305,13 @@ pgtls_write(PGconn *conn, const void *ptr, size_t len)
305305
n=0;
306306
break;
307307
caseSSL_ERROR_SYSCALL:
308-
if (n<0)
308+
309+
/*
310+
* If errno is still zero then assume it's a read EOF situation,
311+
* and report EOF. (This seems possible because SSL_write can
312+
* also do reads.)
313+
*/
314+
if (n<0&&SOCK_ERRNO!=0)
309315
{
310316
result_errno=SOCK_ERRNO;
311317
if (result_errno==EPIPE||result_errno==ECONNRESET)
@@ -1233,10 +1239,12 @@ open_client_SSL(PGconn *conn)
12331239
{
12341240
intr;
12351241

1242+
SOCK_ERRNO_SET(0);
12361243
ERR_clear_error();
12371244
r=SSL_connect(conn->ssl);
12381245
if (r <=0)
12391246
{
1247+
intsave_errno=SOCK_ERRNO;
12401248
interr=SSL_get_error(conn->ssl,r);
12411249
unsigned longecode;
12421250

@@ -1253,10 +1261,10 @@ open_client_SSL(PGconn *conn)
12531261
{
12541262
charsebuf[PG_STRERROR_R_BUFLEN];
12551263

1256-
if (r==-1)
1264+
if (r==-1&&save_errno!=0)
12571265
printfPQExpBuffer(&conn->errorMessage,
12581266
libpq_gettext("SSL SYSCALL error: %s\n"),
1259-
SOCK_STRERROR(SOCK_ERRNO,sebuf,sizeof(sebuf)));
1267+
SOCK_STRERROR(save_errno,sebuf,sizeof(sebuf)));
12601268
else
12611269
printfPQExpBuffer(&conn->errorMessage,
12621270
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)
@@ -271,6 +273,11 @@ pqsecure_raw_read(PGconn *conn, void *ptr, size_t len)
271273
break;
272274
#endif
273275

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

0 commit comments

Comments
 (0)

[8]ページ先頭

©2009-2025 Movatter.jp