diff options
author | Shan Hai <shan.hai@windriver.com> | 2015-11-02 08:03:24 -0500 |
---|---|---|
committer | Steve Dickson <steved@redhat.com> | 2015-11-02 08:55:04 -0500 |
commit | 7f62e37fcd25f09949a547b93c35d9e324211102 (patch) | |
tree | 39637dc1357db85d5e15025e1ea0db4777cc8143 | |
parent | c31fef7f4beb736f6cfe29a2de6d769c7c1e780d (diff) | |
download | nfs-utils-7f62e37fcd25f09949a547b93c35d9e324211102.tar.gz nfs-utils-7f62e37fcd25f09949a547b93c35d9e324211102.tar.xz nfs-utils-7f62e37fcd25f09949a547b93c35d9e324211102.zip |
statd: fix a segfault caused by improper usage of RPC interface
There is a hack which uses the bottom-level RPC improperly as below
in the current statd implementation: insert a socket in the
svc_fdset without a corresponding transport handle
and passes the socket to the svc_getreqset subroutine,
this usage causes a segfault of statd on a huge amount of sm-notifications.
Fix the issue by separating the non-RPC-server socket from RPC
dispatcher.
Signed-off-by: Shan Hai <shan.hai@windriver.com>
Signed-off-by: Steve Dickson <steved@redhat.com>
-rw-r--r-- | utils/statd/rmtcall.c | 1 | ||||
-rw-r--r-- | utils/statd/statd.c | 5 | ||||
-rw-r--r-- | utils/statd/statd.h | 2 | ||||
-rw-r--r-- | utils/statd/svc_run.c | 8 |
4 files changed, 10 insertions, 6 deletions
diff --git a/utils/statd/rmtcall.c b/utils/statd/rmtcall.c index 45c84f9..c4f6364 100644 --- a/utils/statd/rmtcall.c +++ b/utils/statd/rmtcall.c @@ -113,7 +113,6 @@ statd_get_socket(void) if (sockfd < 0) return -1; - FD_SET(sockfd, &SVC_FDSET); return sockfd; } diff --git a/utils/statd/statd.c b/utils/statd/statd.c index 2b7a167..e5b4c98 100644 --- a/utils/statd/statd.c +++ b/utils/statd/statd.c @@ -247,6 +247,7 @@ int main (int argc, char **argv) int port = 0, out_port = 0; int nlm_udp = 0, nlm_tcp = 0; struct rlimit rlim; + int notify_sockfd; /* Default: daemon mode, no other options */ run_mode = 0; @@ -437,7 +438,7 @@ int main (int argc, char **argv) } /* Make sure we have a privilege port for calling into the kernel */ - if (statd_get_socket() < 0) + if ((notify_sockfd = statd_get_socket()) < 0) exit(1); /* If sm-notify didn't take all the state files, load @@ -484,7 +485,7 @@ int main (int argc, char **argv) * Handle incoming requests: SM_NOTIFY socket requests, as * well as callbacks from lockd. */ - my_svc_run(); /* I rolled my own, Olaf made it better... */ + my_svc_run(notify_sockfd); /* I rolled my own, Olaf made it better... */ /* Only get here when simulating a crash so we should probably * start sm-notify running again. As we have already dropped diff --git a/utils/statd/statd.h b/utils/statd/statd.h index a1d8035..231ac7e 100644 --- a/utils/statd/statd.h +++ b/utils/statd/statd.h @@ -28,7 +28,7 @@ extern _Bool statd_present_address(const struct sockaddr *sap, char *buf, __attribute__((__malloc__)) extern char * statd_canonical_name(const char *hostname); -extern void my_svc_run(void); +extern void my_svc_run(int); extern void notify_hosts(void); extern void shuffle_dirs(void); extern int statd_get_socket(void); diff --git a/utils/statd/svc_run.c b/utils/statd/svc_run.c index d98ecee..28c1ad6 100644 --- a/utils/statd/svc_run.c +++ b/utils/statd/svc_run.c @@ -78,7 +78,7 @@ my_svc_exit(void) * The heart of the server. A crib from libc for the most part... */ void -my_svc_run(void) +my_svc_run(int sockfd) { FD_SET_TYPE readfds; int selret; @@ -96,6 +96,8 @@ my_svc_run(void) } readfds = SVC_FDSET; + /* Set notify sockfd for waiting for reply */ + FD_SET(sockfd, &readfds); if (notify) { struct timeval tv; @@ -125,8 +127,10 @@ my_svc_run(void) default: selret -= process_reply(&readfds); - if (selret) + if (selret) { + FD_CLR(sockfd, &readfds); svc_getreqset(&readfds); + } } } } |