138 lines
4.9 KiB
Diff
138 lines
4.9 KiB
Diff
From 459b0be7bef7551a4b901742336bdee41ed44bbe Mon Sep 17 00:00:00 2001
|
|
From: Lukas Slebodnik <lslebodn@redhat.com>
|
|
Date: Wed, 17 Feb 2016 15:21:55 +0100
|
|
Subject: [PATCH 104/108] CLIENT: Retry request after EPIPE
|
|
|
|
We have a function sss_cli_check_socket which checks
|
|
socket in client code. The socket is reopened in case of some
|
|
issues e.g. responder terminated connections ...
|
|
|
|
We use syscall poll for checking status of socket.
|
|
It's not 100% reliable method because there is still
|
|
chance that responder will terminate socket after this check.
|
|
|
|
Here is a schema of sss_*_make_request functions:
|
|
sss_cli_check_socket
|
|
sss_cli_make_request_nochecks {
|
|
sss_cli_send_req {
|
|
poll
|
|
send
|
|
}
|
|
sss_cli_recv_rep {
|
|
poll
|
|
read
|
|
}
|
|
}
|
|
|
|
The syscall pool does not return EPIPE directly but we convert
|
|
special revents from poll to EPIPE. As it was mentioned earlier,
|
|
checking of socket in the sss_cli_check_socket is not 100% reliable.
|
|
It can happen very rarely due to TOCTOU issue (Time of check to time of use)
|
|
|
|
We can return EPIPE from the sss_cli_make_request_nochecks function
|
|
in case of failure in poll in sss_cli_send_req. The send function
|
|
in sss_cli_send_req can also return EPIPE is responder close socket
|
|
in the same time. The send function can succeed in sss_cli_send_req
|
|
but it does not mean that responder read the message. It can happen
|
|
that timer for closing socket can be handled before reading a message.
|
|
Therefore there is a still a chance that we might return EPIPE in case
|
|
of failure in poll in sss_cli_recv_rep.
|
|
|
|
Therefore we need to reconnect to responder(sss_cli_check_socket)
|
|
in case of EPIPE returned from sss_cli_make_request_nochecks and
|
|
try to do the same request one more time.
|
|
|
|
Resolves:
|
|
https://fedorahosted.org/sssd/ticket/2626
|
|
|
|
Reviewed-by: Jakub Hrozek <jhrozek@redhat.com>
|
|
(cherry picked from commit 6748a4c9d75db997c724c1dcea541e0047742f52)
|
|
(cherry picked from commit 710d6a9e66b08990ce10cf72e7cc6c8c023806ea)
|
|
---
|
|
src/sss_client/common.c | 48 ++++++++++++++++++++++++++++++++++++++++++++++++
|
|
1 file changed, 48 insertions(+)
|
|
|
|
diff --git a/src/sss_client/common.c b/src/sss_client/common.c
|
|
index 827f0c2ac3fa12cbe5a282f25ff108fc83bab76c..20106b1b67e3cabe8dd4338b9358c8b2b5b86d57 100644
|
|
--- a/src/sss_client/common.c
|
|
+++ b/src/sss_client/common.c
|
|
@@ -734,6 +734,22 @@ enum nss_status sss_nss_make_request(enum sss_cli_command cmd,
|
|
}
|
|
|
|
ret = sss_cli_make_request_nochecks(cmd, rd, repbuf, replen, errnop);
|
|
+ if (ret == SSS_STATUS_UNAVAIL && *errnop == EPIPE) {
|
|
+ /* try reopen socket */
|
|
+ ret = sss_cli_check_socket(errnop, SSS_NSS_SOCKET_NAME);
|
|
+ if (ret != SSS_STATUS_SUCCESS) {
|
|
+#ifdef NONSTANDARD_SSS_NSS_BEHAVIOUR
|
|
+ *errnop = 0;
|
|
+ errno = 0;
|
|
+ return NSS_STATUS_NOTFOUND;
|
|
+#else
|
|
+ return NSS_STATUS_UNAVAIL;
|
|
+#endif
|
|
+ }
|
|
+
|
|
+ /* and make request one more time */
|
|
+ ret = sss_cli_make_request_nochecks(cmd, rd, repbuf, replen, errnop);
|
|
+ }
|
|
switch (ret) {
|
|
case SSS_STATUS_TRYAGAIN:
|
|
return NSS_STATUS_TRYAGAIN;
|
|
@@ -784,6 +800,16 @@ int sss_pac_make_request(enum sss_cli_command cmd,
|
|
}
|
|
|
|
ret = sss_cli_make_request_nochecks(cmd, rd, repbuf, replen, errnop);
|
|
+ if (ret == SSS_STATUS_UNAVAIL && *errnop == EPIPE) {
|
|
+ /* try reopen socket */
|
|
+ ret = sss_cli_check_socket(errnop, SSS_PAC_SOCKET_NAME);
|
|
+ if (ret != SSS_STATUS_SUCCESS) {
|
|
+ return NSS_STATUS_UNAVAIL;
|
|
+ }
|
|
+
|
|
+ /* and make request one more time */
|
|
+ ret = sss_cli_make_request_nochecks(cmd, rd, repbuf, replen, errnop);
|
|
+ }
|
|
switch (ret) {
|
|
case SSS_STATUS_TRYAGAIN:
|
|
return NSS_STATUS_TRYAGAIN;
|
|
@@ -888,6 +914,18 @@ int sss_pam_make_request(enum sss_cli_command cmd,
|
|
}
|
|
|
|
status = sss_cli_make_request_nochecks(cmd, rd, repbuf, replen, errnop);
|
|
+ if (status == SSS_STATUS_UNAVAIL && *errnop == EPIPE) {
|
|
+ /* try reopen socket */
|
|
+ status = sss_cli_check_socket(errnop, socket_name);
|
|
+ if (status != SSS_STATUS_SUCCESS) {
|
|
+ ret = PAM_SERVICE_ERR;
|
|
+ goto out;
|
|
+ }
|
|
+
|
|
+ /* and make request one more time */
|
|
+ status = sss_cli_make_request_nochecks(cmd, rd, repbuf, replen, errnop);
|
|
+ }
|
|
+
|
|
if (status == SSS_STATUS_SUCCESS) {
|
|
ret = PAM_SUCCESS;
|
|
} else {
|
|
@@ -926,6 +964,16 @@ sss_cli_make_request_with_checks(enum sss_cli_command cmd,
|
|
}
|
|
|
|
ret = sss_cli_make_request_nochecks(cmd, rd, repbuf, replen, errnop);
|
|
+ if (ret == SSS_STATUS_UNAVAIL && *errnop == EPIPE) {
|
|
+ /* try reopen socket */
|
|
+ ret = sss_cli_check_socket(errnop, socket_name);
|
|
+ if (ret != SSS_STATUS_SUCCESS) {
|
|
+ return SSS_STATUS_UNAVAIL;
|
|
+ }
|
|
+
|
|
+ /* and make request one more time */
|
|
+ ret = sss_cli_make_request_nochecks(cmd, rd, repbuf, replen, errnop);
|
|
+ }
|
|
|
|
return ret;
|
|
}
|
|
--
|
|
2.7.3
|
|
|