summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorRobert Mustacchi <rm@joyent.com>2017-11-09 18:24:48 +0000
committerRobert Mustacchi <rm@joyent.com>2017-11-10 15:52:17 +0000
commit7dd996f96ad1fff4ba9219b2ff8108c83c73e67e (patch)
treeeb9f3ed723c26c1a4dd9a1623d3220de5cafd161
parent44b5ab54b5bebdc643de52d180fd22b826289f02 (diff)
downloadillumos-joyent-7dd996f96ad1fff4ba9219b2ff8108c83c73e67e.tar.gz
OS-6449 nss_files exec attr search leaks memory on dlclose
Reviewed by: Tim Kordas <tim.kordas@joyent.com> Reviewed by: Jerry Jelinek <jerry.jelinek@joyent.com> Reviewed by: Dan McDonald <danmcd@joyent.com> Approved by: Jerry Jelinek <jerry.jelinek@joyent.com>
-rw-r--r--usr/src/lib/nsswitch/files/common/files_common.c13
-rw-r--r--usr/src/lib/nsswitch/files/common/files_common.h8
-rw-r--r--usr/src/lib/nsswitch/files/common/getexecattr.c39
3 files changed, 48 insertions, 12 deletions
diff --git a/usr/src/lib/nsswitch/files/common/files_common.c b/usr/src/lib/nsswitch/files/common/files_common.c
index 4755aec86b..5892ed1430 100644
--- a/usr/src/lib/nsswitch/files/common/files_common.c
+++ b/usr/src/lib/nsswitch/files/common/files_common.c
@@ -24,6 +24,7 @@
*/
/*
* Copyright 2014 Nexenta Systems, Inc. All rights reserved.
+ * Copyright (c) 2017, Joyent, Inc.
*/
/*
@@ -738,3 +739,15 @@ _nss_files_check_name_aliases(nss_XbyY_args_t *argp, const char *line,
}
return (0);
}
+
+/*
+ * A few NSS modules hold onto data for the duration of their module. In this
+ * case, when that module goes away, we must free that data. This is a place
+ * that allows for modules to register items to take care of.
+ */
+#pragma fini(_nss_files_fini)
+static void
+_nss_files_fini(void)
+{
+ getexecattr_fini();
+}
diff --git a/usr/src/lib/nsswitch/files/common/files_common.h b/usr/src/lib/nsswitch/files/common/files_common.h
index 2138d7180e..b08a666eb6 100644
--- a/usr/src/lib/nsswitch/files/common/files_common.h
+++ b/usr/src/lib/nsswitch/files/common/files_common.h
@@ -23,6 +23,9 @@
* Copyright 2008 Sun Microsystems, Inc. All rights reserved.
* Use is subject to license terms.
*/
+/*
+ * Copyright (c) 2017, Joyent, INc.
+ */
/*
* Common code and structures used by name-service-switch "files" backends.
@@ -140,6 +143,11 @@ extern int validate_group_ids(char *line, int *linelenp, int buflen,
extern int validate_passwd_ids(char *line, int *linelenp, int buflen,
int extra_chars);
+/*
+ * Destructors used by different bits.
+ */
+extern void getexecattr_fini(void);
+
#ifdef __cplusplus
}
#endif
diff --git a/usr/src/lib/nsswitch/files/common/getexecattr.c b/usr/src/lib/nsswitch/files/common/getexecattr.c
index c0b47ea419..04ecc445bc 100644
--- a/usr/src/lib/nsswitch/files/common/getexecattr.c
+++ b/usr/src/lib/nsswitch/files/common/getexecattr.c
@@ -20,6 +20,7 @@
*/
/*
* Copyright (c) 1999, 2010, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2017, Joyent, Inc.
*/
#include <stdlib.h>
@@ -49,6 +50,19 @@ extern int _readbufline(char *, int, char *, int, int *);
extern char *_exec_wild_id(char *, const char *);
extern void _exec_cleanup(nss_status_t, nss_XbyY_args_t *);
+/*
+ * _exec_files_XY_all wants to cache data from the attribute file.
+ */
+static char *exec_f_buf;
+static time_t exec_read_time;
+
+void
+getexecattr_fini(void)
+{
+ free(exec_f_buf);
+ exec_f_buf = NULL;
+}
+
/*
* check_match: returns 1 if matching entry found, else returns 0.
@@ -104,10 +118,8 @@ _exec_files_XY_all(files_backend_ptr_t be,
int exec_fd = 0;
int f_size = 0;
time_t f_time = 0;
- static time_t read_time = 0;
char *first;
char *last;
- static char *f_buf = NULL;
struct stat f_stat;
nss_status_t res = NSS_NOTFOUND;
_priv_execattr *_priv_exec = (_priv_execattr *)(argp->key.attrp);
@@ -132,7 +144,7 @@ _exec_files_XY_all(files_backend_ptr_t be,
f_size = f_stat.st_size;
f_time = f_stat.st_mtime;
- while (f_time > read_time || f_buf == NULL) {
+ while (f_time > exec_read_time || exec_f_buf == NULL) {
/*
* file has been modified since we last read it
* or we never read it or memory allocation
@@ -150,32 +162,35 @@ _exec_files_XY_all(files_backend_ptr_t be,
return (NSS_UNAVAIL);
}
exec_fd = fileno(be->f);
- if (f_buf != NULL)
- free(f_buf);
- if ((f_buf = malloc(f_size)) == NULL) {
+ if (exec_f_buf != NULL)
+ free(exec_f_buf);
+ if ((exec_f_buf = malloc(f_size)) == NULL) {
(void) _nss_files_endent(be, 0);
(void) rw_unlock(&exec_lock);
return (NSS_UNAVAIL);
}
- if (read(exec_fd, f_buf, f_size) < f_size) {
- free(f_buf);
+ if (read(exec_fd, exec_f_buf, f_size) < f_size) {
+ free(exec_f_buf);
+ exec_f_buf = NULL;
(void) _nss_files_endent(be, 0);
(void) rw_unlock(&exec_lock);
return (NSS_UNAVAIL);
}
- read_time = f_time;
+ exec_read_time = f_time;
(void) rw_unlock(&exec_lock);
/*
* verify that the file did not change after
* we read it.
*/
if (rw_rdlock(&exec_lock) != 0) {
- free(f_buf);
+ free(exec_f_buf);
+ exec_f_buf = NULL;
(void) _nss_files_endent(be, 0);
return (NSS_UNAVAIL);
}
if (stat(be->filename, &f_stat) != 0) {
- free(f_buf);
+ free(exec_f_buf);
+ exec_f_buf = NULL;
(void) _nss_files_endent(be, 0);
(void) rw_unlock(&exec_lock);
return (NSS_UNAVAIL);
@@ -190,7 +205,7 @@ _exec_files_XY_all(files_backend_ptr_t be,
int linelen = 0;
char *instr = be->buf;
- linelen = _readbufline(f_buf, f_size, instr, be->minbuf,
+ linelen = _readbufline(exec_f_buf, f_size, instr, be->minbuf,
&lastlen);
if (linelen < 0) {
/* End of file */