summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorSimo Sorce <ssorce@redhat.com>2011-02-07 08:54:42 -0500
committerStephen Gallagher <sgallagh@redhat.com>2011-02-15 07:34:55 -0500
commit480735cddc41159344b3e9f65b3e808fe44c82ce (patch)
tree173de491ee23d089a59a37fd0e84c90d9cf02a97
parentea55de9f3b97b57af586257f94733b6d00b10dc9 (diff)
downloadsssd-480735cddc41159344b3e9f65b3e808fe44c82ce.tar.gz
sssd-480735cddc41159344b3e9f65b3e808fe44c82ce.tar.xz
sssd-480735cddc41159344b3e9f65b3e808fe44c82ce.zip
Check that the socket is really ours before attempting to close it.
Fixes: https://fedorahosted.org/sssd/ticket/790
-rw-r--r--src/sss_client/common.c55
1 files changed, 42 insertions, 13 deletions
diff --git a/src/sss_client/common.c b/src/sss_client/common.c
index 20def9be0..d4b230889 100644
--- a/src/sss_client/common.c
+++ b/src/sss_client/common.c
@@ -35,6 +35,7 @@
#include <sys/stat.h>
#include <unistd.h>
#include <stdlib.h>
+#include <stdbool.h>
#include <stdint.h>
#include <string.h>
#include <fcntl.h>
@@ -52,6 +53,7 @@
/* common functions */
int sss_cli_sd = -1; /* the sss client socket descriptor */
+struct stat sss_cli_sb; /* the sss client stat buffer */
static void sss_cli_close_socket(void)
{
@@ -495,8 +497,11 @@ static int make_safe_fd(int fd)
static int sss_nss_open_socket(int *errnop, const char *socket_name)
{
struct sockaddr_un nssaddr;
- int inprogress = 1;
- int wait_time, sleep_time;
+ bool inprogress = true;
+ bool connected = false;
+ unsigned int wait_time;
+ unsigned int sleep_time;
+ int ret;
int sd;
memset(&nssaddr, 0, sizeof(struct sockaddr_un));
@@ -521,19 +526,19 @@ static int sss_nss_open_socket(int *errnop, const char *socket_name)
/* this piece is adapted from winbind client code */
wait_time = 0;
sleep_time = 0;
- while(inprogress) {
+ while (inprogress) {
int connect_errno = 0;
socklen_t errnosize;
struct timeval tv;
fd_set w_fds;
- int ret;
wait_time += sleep_time;
ret = connect(sd, (struct sockaddr *)&nssaddr,
sizeof(nssaddr));
if (ret == 0) {
- return sd;
+ connected = true;
+ break;
}
switch(errno) {
@@ -550,10 +555,12 @@ static int sss_nss_open_socket(int *errnop, const char *socket_name)
ret = getsockopt(sd, SOL_SOCKET, SO_ERROR,
&connect_errno, &errnosize);
if (ret >= 0 && connect_errno == 0) {
- return sd;
+ connected = true;
+ break;
}
}
- wait_time += SSS_CLI_SOCKET_TIMEOUT;
+ wait_time += tv.tv_sec;
+ if (tv.tv_usec != 0) wait_time++;
break;
case EAGAIN:
if (wait_time < SSS_CLI_SOCKET_TIMEOUT) {
@@ -563,28 +570,50 @@ static int sss_nss_open_socket(int *errnop, const char *socket_name)
break;
default:
*errnop = errno;
- inprogress = 0;
+ inprogress = false;
break;
}
if (wait_time >= SSS_CLI_SOCKET_TIMEOUT) {
- inprogress = 0;
+ inprogress = false;
+ }
+
+ if (connected) {
+ inprogress = false;
}
}
- /* if we get here connect() failed or we timed out */
+ if (!connected) {
+ close(sd);
+ return -1;
+ }
- close(sd);
- return -1;
+ ret = fstat(sd, &sss_cli_sb);
+ if (ret != 0) {
+ close(sd);
+ return -1;
+ }
+
+ return sd;
}
static enum sss_status sss_cli_check_socket(int *errnop, const char *socket_name)
{
static pid_t mypid;
+ struct stat mysb;
int mysd;
+ int ret;
if (getpid() != mypid) {
- sss_cli_close_socket();
+ ret = fstat(sss_cli_sd, &mysb);
+ if (ret == 0) {
+ if (S_ISSOCK(mysb.st_mode) &&
+ mysb.st_dev == sss_cli_sb.st_dev &&
+ mysb.st_ino == sss_cli_sb.st_ino) {
+ sss_cli_close_socket();
+ }
+ }
+ sss_cli_sd = -1;
mypid = getpid();
}