summaryrefslogtreecommitdiffstats
path: root/src/responder/nss/nsssrv_mmap_cache.c
diff options
context:
space:
mode:
authorMichal Zidek <mzidek@redhat.com>2013-03-06 16:46:32 +0100
committerJakub Hrozek <jhrozek@redhat.com>2013-03-07 18:47:58 +0100
commit04100112f48401a5453199e428b2a930e0bb9599 (patch)
tree2a53bf54fb1cfcfbdccfc3b3b6d1e5824b352bb6 /src/responder/nss/nsssrv_mmap_cache.c
parentcb4a3171bb208c919883971a86aa3830d47e5699 (diff)
downloadsssd-04100112f48401a5453199e428b2a930e0bb9599.tar.gz
sssd-04100112f48401a5453199e428b2a930e0bb9599.tar.xz
sssd-04100112f48401a5453199e428b2a930e0bb9599.zip
File descriptor leak in nss responder.
File descriptors leaked every time sss_mmap_cache_reinit was called and also the old memory cache was still maped in memory (munmap was not called). This patch adds destructor for memory cache context to call close() and munmap() automaticly. https://fedorahosted.org/sssd/ticket/1826
Diffstat (limited to 'src/responder/nss/nsssrv_mmap_cache.c')
-rw-r--r--src/responder/nss/nsssrv_mmap_cache.c61
1 files changed, 43 insertions, 18 deletions
diff --git a/src/responder/nss/nsssrv_mmap_cache.c b/src/responder/nss/nsssrv_mmap_cache.c
index 21346e588..6fb9c7e26 100644
--- a/src/responder/nss/nsssrv_mmap_cache.c
+++ b/src/responder/nss/nsssrv_mmap_cache.c
@@ -820,7 +820,7 @@ static errno_t sss_mc_create_file(struct sss_mc_ctx *mc_ctx)
errno = 0;
ret = unlink(mc_ctx->file);
- if (ret == -1) {
+ if (ret == -1 && errno != ENOENT) {
ret = errno;
DEBUG(SSSDBG_TRACE_FUNC, ("Failed to rm mmap file %s: %d(%s)\n",
mc_ctx->file, ret, strerror(ret)));
@@ -845,6 +845,7 @@ static errno_t sss_mc_create_file(struct sss_mc_ctx *mc_ctx)
DEBUG(SSSDBG_FATAL_FAILURE,
("Failed to lock file %s.\n", mc_ctx->file));
close(mc_ctx->fd);
+ mc_ctx->fd = -1;
/* Report on unlink failures but don't overwrite the errno
* from sss_br_lock_file
@@ -887,6 +888,36 @@ static void sss_mc_header_update(struct sss_mc_ctx *mc_ctx, int status)
MC_LOWER_BARRIER(h);
}
+static int mc_ctx_destructor(struct sss_mc_ctx *mc_ctx)
+{
+ int ret;
+
+ /* Print debug message to logs if munmap() or close()
+ * fail but always return 0 */
+
+ if (mc_ctx->mmap_base != NULL) {
+ ret = munmap(mc_ctx->mmap_base, mc_ctx->mmap_size);
+ if (ret == -1) {
+ ret = errno;
+ DEBUG(SSSDBG_CRIT_FAILURE,
+ ("Failed to unmap old memory cache file."
+ "[%d]: %s\n", ret, strerror(ret)));
+ }
+ }
+
+ if (mc_ctx->fd != -1) {
+ ret = close(mc_ctx->fd);
+ if (ret == -1) {
+ ret = errno;
+ DEBUG(SSSDBG_CRIT_FAILURE,
+ ("Failed to close old memory cache file."
+ "[%d]: %s\n", ret, strerror(ret)));
+ }
+ }
+
+ return 0;
+}
+
errno_t sss_mmap_cache_init(TALLOC_CTX *mem_ctx, const char *name,
enum sss_mc_type type, size_t n_elem,
time_t timeout, struct sss_mc_ctx **mcc)
@@ -894,7 +925,7 @@ errno_t sss_mmap_cache_init(TALLOC_CTX *mem_ctx, const char *name,
struct sss_mc_ctx *mc_ctx = NULL;
unsigned int rseed;
int payload;
- int ret;
+ int ret, dret;
switch (type) {
case SSS_MC_PASSWD:
@@ -912,6 +943,7 @@ errno_t sss_mmap_cache_init(TALLOC_CTX *mem_ctx, const char *name,
return ENOMEM;
}
mc_ctx->fd = -1;
+ talloc_set_destructor(mc_ctx, mc_ctx_destructor);
mc_ctx->name = talloc_strdup(mc_ctx, name);
if (!mc_ctx->name) {
@@ -993,15 +1025,14 @@ errno_t sss_mmap_cache_init(TALLOC_CTX *mem_ctx, const char *name,
done:
if (ret) {
- if (mc_ctx && mc_ctx->mmap_base) {
- munmap(mc_ctx->mmap_base, mc_ctx->mmap_size);
- }
- if (mc_ctx && mc_ctx->fd != -1) {
- close(mc_ctx->fd);
- ret = unlink(mc_ctx->file);
- if (ret == -1) {
- DEBUG(SSSDBG_CRIT_FAILURE, ("Failed to rm mmap file %s: %d(%s)\n",
- mc_ctx->file, ret, strerror(ret)));
+ /* Closing the file descriptor and ummaping the file
+ * from memory is done in the mc_ctx_destructor. */
+ if (mc_ctx && mc_ctx->file && mc_ctx->fd != -1) {
+ dret = unlink(mc_ctx->file);
+ if (dret == -1) {
+ DEBUG(SSSDBG_CRIT_FAILURE,
+ ("Failed to rm mmap file %s: %d(%s)\n", mc_ctx->file,
+ dret, strerror(dret)));
}
}
@@ -1049,13 +1080,7 @@ errno_t sss_mmap_cache_reinit(TALLOC_CTX *mem_ctx, size_t n_elem,
timeout = (*mc_ctx)->valid_time_slot;
}
- ret = talloc_free(*mc_ctx);
- if (ret != 0) {
- /* This can happen only if destructor is associated with this
- * context */
- DEBUG(SSSDBG_MINOR_FAILURE, ("Destructor asociated with memory"
- " context failed.\n"));
- }
+ talloc_free(*mc_ctx);
/* make sure we do not leave a potentially freed pointer around */
*mc_ctx = NULL;