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

Commit551d4b2

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 parent332b430 commit551d4b2

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
@@ -457,6 +457,7 @@ be_tls_open_server(Port *port)
457457
* per-thread error queue following another call to an OpenSSL I/O
458458
* routine.
459459
*/
460+
errno=0;
460461
ERR_clear_error();
461462
r=SSL_accept(port->ssl);
462463
if (r <=0)
@@ -493,7 +494,7 @@ be_tls_open_server(Port *port)
493494
WAIT_EVENT_SSL_OPEN_SERVER);
494495
gotoaloop;
495496
caseSSL_ERROR_SYSCALL:
496-
if (r<0)
497+
if (r<0&&errno!=0)
497498
ereport(COMMERROR,
498499
(errcode_for_socket_access(),
499500
errmsg("could not accept SSL connection: %m")));
@@ -727,7 +728,7 @@ be_tls_read(Port *port, void *ptr, size_t len, int *waitfor)
727728
break;
728729
caseSSL_ERROR_SYSCALL:
729730
/* leave it to caller to ereport the value of errno */
730-
if (n!=-1)
731+
if (n!=-1||errno==0)
731732
{
732733
errno=ECONNRESET;
733734
n=-1;
@@ -785,8 +786,14 @@ be_tls_write(Port *port, void *ptr, size_t len, int *waitfor)
785786
n=-1;
786787
break;
787788
caseSSL_ERROR_SYSCALL:
788-
/* leave it to caller to ereport the value of errno */
789-
if (n!=-1)
789+
790+
/*
791+
* Leave it to caller to ereport the value of errno. However, if
792+
* errno is still zero then assume it's a read EOF situation, and
793+
* report ECONNRESET. (This seems possible because SSL_write can
794+
* also do reads.)
795+
*/
796+
if (n!=-1||errno==0)
790797
{
791798
errno=ECONNRESET;
792799
n=-1;

‎src/backend/libpq/pqcomm.c

Lines changed: 16 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -954,6 +954,8 @@ pq_recvbuf(void)
954954
{
955955
intr;
956956

957+
errno=0;
958+
957959
r=secure_read(MyProcPort,PqRecvBuffer+PqRecvLength,
958960
PQ_RECV_BUFFER_SIZE-PqRecvLength);
959961

@@ -966,10 +968,13 @@ pq_recvbuf(void)
966968
* Careful: an ereport() that tries to write to the client would
967969
* cause recursion to here, leading to stack overflow and core
968970
* dump! This message must go *only* to the postmaster log.
971+
*
972+
* If errno is zero, assume it's EOF and let the caller complain.
969973
*/
970-
ereport(COMMERROR,
971-
(errcode_for_socket_access(),
972-
errmsg("could not receive data from client: %m")));
974+
if (errno!=0)
975+
ereport(COMMERROR,
976+
(errcode_for_socket_access(),
977+
errmsg("could not receive data from client: %m")));
973978
returnEOF;
974979
}
975980
if (r==0)
@@ -1046,6 +1051,8 @@ pq_getbyte_if_available(unsigned char *c)
10461051
/* Put the socket into non-blocking mode */
10471052
socket_set_nonblocking(true);
10481053

1054+
errno=0;
1055+
10491056
r=secure_read(MyProcPort,c,1);
10501057
if (r<0)
10511058
{
@@ -1062,10 +1069,13 @@ pq_getbyte_if_available(unsigned char *c)
10621069
* Careful: an ereport() that tries to write to the client would
10631070
* cause recursion to here, leading to stack overflow and core
10641071
* dump! This message must go *only* to the postmaster log.
1072+
*
1073+
* If errno is zero, assume it's EOF and let the caller complain.
10651074
*/
1066-
ereport(COMMERROR,
1067-
(errcode_for_socket_access(),
1068-
errmsg("could not receive data from client: %m")));
1075+
if (errno!=0)
1076+
ereport(COMMERROR,
1077+
(errcode_for_socket_access(),
1078+
errmsg("could not receive data from client: %m")));
10691079
r=EOF;
10701080
}
10711081
}

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

Lines changed: 12 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -209,7 +209,7 @@ pgtls_read(PGconn *conn, void *ptr, size_t len)
209209
*/
210210
gotorloop;
211211
caseSSL_ERROR_SYSCALL:
212-
if (n<0)
212+
if (n<0&&SOCK_ERRNO!=0)
213213
{
214214
result_errno=SOCK_ERRNO;
215215
if (result_errno==EPIPE||
@@ -317,7 +317,13 @@ pgtls_write(PGconn *conn, const void *ptr, size_t len)
317317
n=0;
318318
break;
319319
caseSSL_ERROR_SYSCALL:
320-
if (n<0)
320+
321+
/*
322+
* If errno is still zero then assume it's a read EOF situation,
323+
* and report EOF. (This seems possible because SSL_write can
324+
* also do reads.)
325+
*/
326+
if (n<0&&SOCK_ERRNO!=0)
321327
{
322328
result_errno=SOCK_ERRNO;
323329
if (result_errno==EPIPE||result_errno==ECONNRESET)
@@ -1479,10 +1485,12 @@ open_client_SSL(PGconn *conn)
14791485
{
14801486
intr;
14811487

1488+
SOCK_ERRNO_SET(0);
14821489
ERR_clear_error();
14831490
r=SSL_connect(conn->ssl);
14841491
if (r <=0)
14851492
{
1493+
intsave_errno=SOCK_ERRNO;
14861494
interr=SSL_get_error(conn->ssl,r);
14871495
unsigned longecode;
14881496

@@ -1499,10 +1507,10 @@ open_client_SSL(PGconn *conn)
14991507
{
15001508
charsebuf[PG_STRERROR_R_BUFLEN];
15011509

1502-
if (r==-1)
1510+
if (r==-1&&save_errno!=0)
15031511
appendPQExpBuffer(&conn->errorMessage,
15041512
libpq_gettext("SSL SYSCALL error: %s\n"),
1505-
SOCK_STRERROR(SOCK_ERRNO,sebuf,sizeof(sebuf)));
1513+
SOCK_STRERROR(save_errno,sebuf,sizeof(sebuf)));
15061514
else
15071515
appendPQExpBufferStr(&conn->errorMessage,
15081516
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
@@ -235,6 +235,8 @@ pqsecure_raw_read(PGconn *conn, void *ptr, size_t len)
235235
intresult_errno=0;
236236
charsebuf[PG_STRERROR_R_BUFLEN];
237237

238+
SOCK_ERRNO_SET(0);
239+
238240
n=recv(conn->sock,ptr,len,0);
239241

240242
if (n<0)
@@ -262,6 +264,11 @@ pqsecure_raw_read(PGconn *conn, void *ptr, size_t len)
262264
"\tbefore or while processing the request.\n"));
263265
break;
264266

267+
case0:
268+
/* If errno didn't get set, treat it as regular EOF */
269+
n=0;
270+
break;
271+
265272
default:
266273
appendPQExpBuffer(&conn->errorMessage,
267274
libpq_gettext("could not receive data from server: %s\n"),

0 commit comments

Comments
 (0)

[8]ページ先頭

©2009-2025 Movatter.jp