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

Commitebbd499

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 parent01cc92f commitebbd499

File tree

4 files changed

+45
-14
lines changed

4 files changed

+45
-14
lines changed

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

Lines changed: 11 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -460,6 +460,7 @@ be_tls_open_server(Port *port)
460460
* per-thread error queue following another call to an OpenSSL I/O
461461
* routine.
462462
*/
463+
errno=0;
463464
ERR_clear_error();
464465
r=SSL_accept(port->ssl);
465466
if (r <=0)
@@ -496,7 +497,7 @@ be_tls_open_server(Port *port)
496497
WAIT_EVENT_SSL_OPEN_SERVER);
497498
gotoaloop;
498499
caseSSL_ERROR_SYSCALL:
499-
if (r<0)
500+
if (r<0&&errno!=0)
500501
ereport(COMMERROR,
501502
(errcode_for_socket_access(),
502503
errmsg("could not accept SSL connection: %m")));
@@ -732,7 +733,7 @@ be_tls_read(Port *port, void *ptr, size_t len, int *waitfor)
732733
break;
733734
caseSSL_ERROR_SYSCALL:
734735
/* leave it to caller to ereport the value of errno */
735-
if (n!=-1)
736+
if (n!=-1||errno==0)
736737
{
737738
errno=ECONNRESET;
738739
n=-1;
@@ -790,8 +791,14 @@ be_tls_write(Port *port, void *ptr, size_t len, int *waitfor)
790791
n=-1;
791792
break;
792793
caseSSL_ERROR_SYSCALL:
793-
/* leave it to caller to ereport the value of errno */
794-
if (n!=-1)
794+
795+
/*
796+
* Leave it to caller to ereport the value of errno. However, if
797+
* errno is still zero then assume it's a read EOF situation, and
798+
* report ECONNRESET. (This seems possible because SSL_write can
799+
* also do reads.)
800+
*/
801+
if (n!=-1||errno==0)
795802
{
796803
errno=ECONNRESET;
797804
n=-1;

‎src/backend/libpq/pqcomm.c

Lines changed: 16 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -936,6 +936,8 @@ pq_recvbuf(void)
936936
{
937937
intr;
938938

939+
errno=0;
940+
939941
r=secure_read(MyProcPort,PqRecvBuffer+PqRecvLength,
940942
PQ_RECV_BUFFER_SIZE-PqRecvLength);
941943

@@ -948,10 +950,13 @@ pq_recvbuf(void)
948950
* Careful: an ereport() that tries to write to the client would
949951
* cause recursion to here, leading to stack overflow and core
950952
* dump! This message must go *only* to the postmaster log.
953+
*
954+
* If errno is zero, assume it's EOF and let the caller complain.
951955
*/
952-
ereport(COMMERROR,
953-
(errcode_for_socket_access(),
954-
errmsg("could not receive data from client: %m")));
956+
if (errno!=0)
957+
ereport(COMMERROR,
958+
(errcode_for_socket_access(),
959+
errmsg("could not receive data from client: %m")));
955960
returnEOF;
956961
}
957962
if (r==0)
@@ -1028,6 +1033,8 @@ pq_getbyte_if_available(unsigned char *c)
10281033
/* Put the socket into non-blocking mode */
10291034
socket_set_nonblocking(true);
10301035

1036+
errno=0;
1037+
10311038
r=secure_read(MyProcPort,c,1);
10321039
if (r<0)
10331040
{
@@ -1044,10 +1051,13 @@ pq_getbyte_if_available(unsigned char *c)
10441051
* Careful: an ereport() that tries to write to the client would
10451052
* cause recursion to here, leading to stack overflow and core
10461053
* dump! This message must go *only* to the postmaster log.
1054+
*
1055+
* If errno is zero, assume it's EOF and let the caller complain.
10471056
*/
1048-
ereport(COMMERROR,
1049-
(errcode_for_socket_access(),
1050-
errmsg("could not receive data from client: %m")));
1057+
if (errno!=0)
1058+
ereport(COMMERROR,
1059+
(errcode_for_socket_access(),
1060+
errmsg("could not receive data from client: %m")));
10511061
r=EOF;
10521062
}
10531063
}

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

Lines changed: 11 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -207,7 +207,7 @@ pgtls_read(PGconn *conn, void *ptr, size_t len)
207207
*/
208208
gotorloop;
209209
caseSSL_ERROR_SYSCALL:
210-
if (n<0)
210+
if (n<0&&SOCK_ERRNO!=0)
211211
{
212212
result_errno=SOCK_ERRNO;
213213
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)
@@ -1523,11 +1529,12 @@ open_client_SSL(PGconn *conn)
15231529
* was using the system CA pool. For other errors, log
15241530
* them using the normal SYSCALL logging.
15251531
*/
1526-
if (!save_errno&&vcode==X509_V_ERR_UNABLE_TO_GET_ISSUER_CERT_LOCALLY&&
1532+
if (save_errno==0&&
1533+
vcode==X509_V_ERR_UNABLE_TO_GET_ISSUER_CERT_LOCALLY&&
15271534
strcmp(conn->sslrootcert,"system")==0)
15281535
libpq_append_conn_error(conn,"SSL error: certificate verify failed: %s",
15291536
X509_verify_cert_error_string(vcode));
1530-
elseif (r==-1)
1537+
elseif (r==-1&&save_errno!=0)
15311538
libpq_append_conn_error(conn,"SSL SYSCALL error: %s",
15321539
SOCK_STRERROR(save_errno,sebuf,sizeof(sebuf)));
15331540
else

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

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

236+
SOCK_ERRNO_SET(0);
237+
236238
n=recv(conn->sock,ptr,len,0);
237239

238240
if (n<0)
@@ -259,6 +261,11 @@ pqsecure_raw_read(PGconn *conn, void *ptr, size_t len)
259261
"\tbefore or while processing the request.");
260262
break;
261263

264+
case0:
265+
/* If errno didn't get set, treat it as regular EOF */
266+
n=0;
267+
break;
268+
262269
default:
263270
libpq_append_conn_error(conn,"could not receive data from server: %s",
264271
SOCK_STRERROR(result_errno,

0 commit comments

Comments
 (0)

[8]ページ先頭

©2009-2025 Movatter.jp