summaryrefslogtreecommitdiffstats
path: root/src/sss_client
diff options
context:
space:
mode:
authorStephen Gallagher <sgallagh@redhat.com>2010-06-08 15:47:34 -0400
committerStephen Gallagher <sgallagh@redhat.com>2010-06-10 10:17:21 -0400
commitcedc75748b155f7c1287de8796409dd79ef7aecd (patch)
tree68eab2b23f83565f0e293066c30aa339990d6c6a /src/sss_client
parentca95af6e15ddc8928684327ff05353b1e3a17acd (diff)
Properly handle read() and write() throughout the SSSD
We need to guarantee at all times that reads and writes complete successfully. This means that they must be checked for returning EINTR and EAGAIN, and all writes must be wrapped in a loop to ensure that they do not truncate their output.
Diffstat (limited to 'src/sss_client')
-rw-r--r--src/sss_client/common.c16
-rw-r--r--src/sss_client/pam_sss.c2
2 files changed, 17 insertions, 1 deletions
diff --git a/src/sss_client/common.c b/src/sss_client/common.c
index 237b90ab..a4856e08 100644
--- a/src/sss_client/common.c
+++ b/src/sss_client/common.c
@@ -123,6 +123,7 @@ static enum nss_status sss_nss_send_req(enum sss_cli_command cmd,
return NSS_STATUS_UNAVAIL;
}
+ errno = 0;
if (datasent < SSS_NSS_HEADER_SIZE) {
res = write(sss_cli_sd,
(char *)header + datasent,
@@ -133,8 +134,15 @@ static enum nss_status sss_nss_send_req(enum sss_cli_command cmd,
(const char *)rd->data + rdsent,
rd->len - rdsent);
}
+ error = errno;
if ((res == -1) || (res == 0)) {
+ if ((error == EINTR) || error == EAGAIN) {
+ /* If the write was interrupted, go back through
+ * the loop and try again
+ */
+ continue;
+ }
/* Write failed */
sss_cli_close_socket();
@@ -217,6 +225,7 @@ static enum nss_status sss_nss_recv_rep(enum sss_cli_command cmd,
return NSS_STATUS_UNAVAIL;
}
+ errno = 0;
if (datarecv < SSS_NSS_HEADER_SIZE) {
res = read(sss_cli_sd,
(char *)header + datarecv,
@@ -227,8 +236,15 @@ static enum nss_status sss_nss_recv_rep(enum sss_cli_command cmd,
(char *)(*buf) + bufrecv,
header[0] - datarecv);
}
+ error = errno;
if ((res == -1) || (res == 0)) {
+ if ((error == EINTR) || error == EAGAIN) {
+ /* If the read was interrupted, go back through
+ * the loop and try again
+ */
+ continue;
+ }
/* Read failed. I think the only useful thing
* we can do here is just return -1 and fail
diff --git a/src/sss_client/pam_sss.c b/src/sss_client/pam_sss.c
index 2faa3ad2..644073f5 100644
--- a/src/sss_client/pam_sss.c
+++ b/src/sss_client/pam_sss.c
@@ -489,7 +489,7 @@ static errno_t display_pw_reset_message(pam_handle_t *pamh,
while (total_len < stat_buf.st_size) {
ret = read(fd, msg_buf + total_len, stat_buf.st_size - total_len);
if (ret == -1) {
- if (errno == EINTR) continue;
+ if (errno == EINTR || errno == EAGAIN) continue;
ret = errno;
D(("read failed [%d][%s].", ret, strerror(ret)));
goto done;