From ff6f3ee6ef3c1ba9ecf3b4b619294bd00ff02d95 Mon Sep 17 00:00:00 2001 From: Ian Kent Date: Jul 07 2014 04:07:07 +0000 Subject: - add some Coverity identified fixes for bug 1078776. --- diff --git a/autofs-5.0.1-fix-FILE-pointer-check-in-defaults_read_config.patch b/autofs-5.0.1-fix-FILE-pointer-check-in-defaults_read_config.patch new file mode 100644 index 0000000..c69ef73 --- /dev/null +++ b/autofs-5.0.1-fix-FILE-pointer-check-in-defaults_read_config.patch @@ -0,0 +1,82 @@ +autofs-5.0.1 - fix FILE pointer check in defaults_read_config() + +From: Ian Kent + +Fix possible use after free usage of FILE pointer in defaults_read_config(). +--- + CHANGELOG | 1 + + lib/defaults.c | 15 +++++++-------- + 2 files changed, 8 insertions(+), 8 deletions(-) + +diff --git a/CHANGELOG b/CHANGELOG +index 21c3ecd..d978529 100644 +--- a/CHANGELOG ++++ b/CHANGELOG +@@ -7,6 +7,7 @@ + - fix race accessing qdn in get_query_dn(). + - fix leak in cache_push_mapent(). + - fix config entry read buffer not checked. ++- fix FILE pointer check in defaults_read_config(). + + 04/06/2014 autofs-5.1.0 + ======================= +diff --git a/lib/defaults.c b/lib/defaults.c +index a83dcee..1c3df56 100644 +--- a/lib/defaults.c ++++ b/lib/defaults.c +@@ -1056,6 +1056,8 @@ unsigned int defaults_read_config(unsigned int to_syslog) + + ret = 1; + ++ conf = oldconf = NULL; ++ + pthread_mutex_lock(&conf_mutex); + if (!config) { + if (conf_init()) { +@@ -1082,15 +1084,11 @@ unsigned int defaults_read_config(unsigned int to_syslog) + stb.st_mtime <= config->modified && + (oldstat = fstat(fileno(oldconf), &oldstb) == -1) && + oldstb.st_mtime <= config->modified) { +- fclose(conf); +- fclose(oldconf); + goto out; + } + + if (conf || oldconf) { + if (!reset_defaults(to_syslog)) { +- fclose(conf); +- fclose(oldconf); + ret = 0; + goto out; + } +@@ -1108,10 +1106,8 @@ unsigned int defaults_read_config(unsigned int to_syslog) + } + } + +- if (conf) { ++ if (conf) + read_config(to_syslog, conf, DEFAULT_CONFIG_FILE); +- fclose(conf); +- } + + /* + * Read the old config file and override the installed +@@ -1132,7 +1128,6 @@ unsigned int defaults_read_config(unsigned int to_syslog) + clean_ldap_multi_option(NAME_LDAP_URI); + + read_config(to_syslog, oldconf, OLD_CONFIG_FILE); +- fclose(oldconf); + + if (ldap_search_base) { + co = conf_lookup(sec, NAME_SEARCH_BASE); +@@ -1151,6 +1146,10 @@ unsigned int defaults_read_config(unsigned int to_syslog) + } + } + out: ++ if (conf) ++ fclose(conf); ++ if (oldconf) ++ fclose(oldconf); + pthread_mutex_unlock(&conf_mutex); + return ret; + } diff --git a/autofs-5.0.1-fix-memory-leak-in-conf_amd_get_log_options.patch b/autofs-5.0.1-fix-memory-leak-in-conf_amd_get_log_options.patch new file mode 100644 index 0000000..7809b51 --- /dev/null +++ b/autofs-5.0.1-fix-memory-leak-in-conf_amd_get_log_options.patch @@ -0,0 +1,34 @@ +autofs-5.0.1 - fix memory leak in conf_amd_get_log_options() + +From: Ian Kent + +Fix obvious memory leak in conf_amd_get_log_options(). +--- + CHANGELOG | 1 + + lib/defaults.c | 1 + + 2 files changed, 2 insertions(+) + +diff --git a/CHANGELOG b/CHANGELOG +index d978529..f5bbb34 100644 +--- a/CHANGELOG ++++ b/CHANGELOG +@@ -8,6 +8,7 @@ + - fix leak in cache_push_mapent(). + - fix config entry read buffer not checked. + - fix FILE pointer check in defaults_read_config(). ++- fix memory leak in conf_amd_get_log_options(). + + 04/06/2014 autofs-5.1.0 + ======================= +diff --git a/lib/defaults.c b/lib/defaults.c +index 1c3df56..4e09c19 100644 +--- a/lib/defaults.c ++++ b/lib/defaults.c +@@ -1795,6 +1795,7 @@ unsigned int conf_amd_get_log_options(void) + if (log_level < LOG_CRIT) + log_level = LOG_CRIT; + } ++ free(tmp); + } + + if (log_level == -1) diff --git a/autofs-5.0.8-allow-with-systemd-to-take-a-path-arg.patch b/autofs-5.0.8-allow-with-systemd-to-take-a-path-arg.patch deleted file mode 100644 index c08799c..0000000 --- a/autofs-5.0.8-allow-with-systemd-to-take-a-path-arg.patch +++ /dev/null @@ -1,62 +0,0 @@ -autofs-5.0.8 - allow --with-systemd to take a path arg - -From: Joe MacDonald - -If building for a cross-compile environment with systemd it is convenient -to be able to specify a systemd path for the target that may not be the -same as that on the host. - -I encountered a problem while working with autofs in a cross-compile -environment where the host and target have either differing systemd paths -or where one may not have systemd support at all. The common solution -I've seen in other projects is to have a --with-systemddir=[path] option, -but I thought it'd be simpler to add an optional path argument to the -extant '--with-systemd' configure parameter and leave the default =y+probe -for path logic in place. - -Signed-off-by: Joe MacDonald ---- - CHANGELOG | 1 + - aclocal.m4 | 10 ++++++++-- - 2 files changed, 9 insertions(+), 2 deletions(-) - -diff --git a/CHANGELOG b/CHANGELOG -index a01393c..565153d 100644 ---- a/CHANGELOG -+++ b/CHANGELOG -@@ -3,6 +3,7 @@ - - fix undefined authtype_requires_creds err if ldap enabled but without sasl. - - fix master map type check. - - fix task manager not getting signaled. -+- allow --with-systemd to take a path arg. - - 17/10/2013 autofs-5.0.8 - ======================= -diff --git a/aclocal.m4 b/aclocal.m4 -index 3e6f223..105e3e9 100644 ---- a/aclocal.m4 -+++ b/aclocal.m4 -@@ -229,8 +229,10 @@ dnl Check the location of the systemd unit files directory - dnl -------------------------------------------------------------------------- - AC_DEFUN([AF_WITH_SYSTEMD], - [AC_ARG_WITH(systemd, --[ --with-systemd install systemd unit file if systemd unit directory -- is found on system], -+[ --with-systemd@<:@=systemddir@:>@ install systemd unit file. If 'yes' -+ probe the system for unit directory. -+ If a path is specified, assume that -+ is a valid install path.], - [if test "$withval" = yes; then - if test -z "$systemddir"; then - AC_MSG_CHECKING([location of the systemd unit files directory]) -@@ -247,6 +249,10 @@ AC_DEFUN([AF_WITH_SYSTEMD], - else - AC_MSG_RESULT(not found) - fi -+else -+ if test "$withval" != no; then -+ systemddir=$withval -+ fi - fi]) - ]) - diff --git a/autofs-5.0.8-amd-lookup-update-lookup-hesiod-to-handle-amd-keys.patch b/autofs-5.0.8-amd-lookup-update-lookup-hesiod-to-handle-amd-keys.patch deleted file mode 100644 index aae211d..0000000 --- a/autofs-5.0.8-amd-lookup-update-lookup-hesiod-to-handle-amd-keys.patch +++ /dev/null @@ -1,423 +0,0 @@ -autofs-5.0.8 - amd lookup update lookup hesiod to handle amd keys - -From: Ian Kent - -Warning, this is completely untested. - -I don't have a hesiod test environment so I can't test this at all. -If we do in fact have hesiod users then I'll need to work with them -to fix any reported problems. ---- - CHANGELOG | 3 - modules/lookup_hesiod.c | 330 ++++++++++++++++++++++++++++++++++++++--------- - 2 files changed, 272 insertions(+), 61 deletions(-) - -diff --git a/CHANGELOG b/CHANGELOG -index 16a8ab4..f44f6f5 100644 ---- a/CHANGELOG -+++ b/CHANGELOG -@@ -4,7 +4,8 @@ - - add amd map format parser. - - amd lookup update lookup ldap to handle amd keys - - inadvertantly drop from initial series. -- -+- amd lookup update lookup hesiod to handle amd keys -+ - inadvertantly drop from initial series. - - 28/03/2014 autofs-5.0.9 - ======================= -diff --git a/modules/lookup_hesiod.c b/modules/lookup_hesiod.c -index c4f3558..526f294 100644 ---- a/modules/lookup_hesiod.c -+++ b/modules/lookup_hesiod.c -@@ -20,12 +20,15 @@ - #include "automount.h" - #include "nsswitch.h" - --#define MAPFMT_DEFAULT "hesiod" -+#define MAPFMT_DEFAULT "hesiod" -+#define AMD_MAP_PREFIX "hesiod." -+#define AMD_MAP_PREFIX_LEN 7 - - #define MODPREFIX "lookup(hesiod): " - #define HESIOD_LEN 512 - - struct lookup_context { -+ const char *mapname; - struct parse_mod *parser; - void *hesiod_context; - }; -@@ -50,6 +53,7 @@ int lookup_init(const char *mapfmt, int argc, const char *const *argv, void **co - logerr(MODPREFIX "malloc: %s", estr); - return 1; - } -+ memset(ctxt, 0, sizeof(struct lookup_context)); - - /* Initialize the resolver. */ - res_init(); -@@ -66,6 +70,20 @@ int lookup_init(const char *mapfmt, int argc, const char *const *argv, void **co - if (!mapfmt) - mapfmt = MAPFMT_DEFAULT; - -+ if (!strcmp(mapfmt, "amd")) { -+ /* amd formated hesiod maps have a map name */ -+ const char *mapname = argv[0]; -+ if (strncmp(mapname, AMD_MAP_PREFIX, AMD_MAP_PREFIX_LEN)) { -+ logerr(MODPREFIX -+ "incorrect prefix for hesiod map %s", mapname); -+ free(ctxt); -+ return 1; -+ } -+ ctxt->mapname = mapname; -+ argc--; -+ argv++; -+ } -+ - /* Open the parser, if we can. */ - ctxt->parser = open_parse(mapfmt, MODPREFIX, argc - 1, argv + 1); - if (!ctxt->parser) { -@@ -97,16 +115,203 @@ int lookup_read_map(struct autofs_point *ap, time_t age, void *context) - * it's an ERR filesystem, it's an error message we should log. Otherwise, - * assume it's something we know how to deal with already (generic). - */ -+static int lookup_one(struct autofs_point *ap, -+ struct map_source *source, -+ const char *key, int key_len, -+ struct lookup_context *ctxt) -+{ -+ struct mapent_cache *mc; -+ char **hes_result; -+ char **record, *best_record = NULL, *p; -+ int priority, lowest_priority = INT_MAX; -+ int ret, status; -+ -+ mc = source->mc; -+ -+ status = pthread_mutex_lock(&hesiod_mutex); -+ if (status) -+ fatal(status); -+ -+ hes_result = hesiod_resolve(ctxt->hesiod_context, key, "filsys"); -+ if (!hes_result || !hes_result[0]) { -+ int err = errno; -+ error(ap->logopt, -+ MODPREFIX "key \"%s\" not found in map", key); -+ status = pthread_mutex_unlock(&hesiod_mutex); -+ if (status) -+ fatal(status); -+ if (err == HES_ER_NOTFOUND) -+ return CHE_MISSING; -+ else -+ return CHE_FAIL; -+ } -+ -+ /* autofs doesn't support falling back to alternate records, so just -+ find the record with the lowest priority and hope it works. -+ -- Aaron Ucko 2002-03-11 */ -+ for (record = hes_result; *record; ++record) { -+ p = strrchr(*record, ' '); -+ if ( p && isdigit(p[1]) ) { -+ priority = atoi(p+1); -+ } else { -+ priority = INT_MAX - 1; -+ } -+ if (priority < lowest_priority) { -+ lowest_priority = priority; -+ best_record = *record; -+ } -+ } -+ -+ cache_writelock(mc); -+ ret = cache_update(mc, source, key, best_record, time(NULL)); -+ cache_unlock(mc); -+ if (ret == CHE_FAIL) { -+ hesiod_free_list(ctxt->hesiod_context, hes_result); -+ status = pthread_mutex_unlock(&hesiod_mutex); -+ if (status) -+ fatal(status); -+ return ret; -+ } -+ -+ debug(ap->logopt, -+ MODPREFIX "lookup for \"%s\" gave \"%s\"", -+ key, best_record); -+ -+ hesiod_free_list(ctxt->hesiod_context, hes_result); -+ -+ status = pthread_mutex_unlock(&hesiod_mutex); -+ if (status) -+ fatal(status); -+ -+ return ret; -+} -+ -+static int lookup_one_amd(struct autofs_point *ap, -+ struct map_source *source, -+ const char *key, int key_len, -+ struct lookup_context *ctxt) -+{ -+ struct mapent_cache *mc; -+ char *hesiod_base; -+ char **hes_result; -+ char *lkp_key; -+ int status, ret; -+ -+ mc = source->mc; -+ -+ hesiod_base = conf_amd_get_hesiod_base(); -+ if (!hesiod_base) -+ return CHE_FAIL; -+ -+ lkp_key = malloc(key_len + strlen(ctxt->mapname) - 7 + 2); -+ if (!lkp_key) { -+ free(hesiod_base); -+ return CHE_FAIL; -+ } -+ -+ strcpy(lkp_key, key); -+ strcat(lkp_key, "."); -+ strcat(lkp_key, ctxt->mapname + AMD_MAP_PREFIX_LEN); -+ -+ status = pthread_mutex_lock(&hesiod_mutex); -+ if (status) -+ fatal(status); -+ -+ hes_result = hesiod_resolve(ctxt->hesiod_context, lkp_key, hesiod_base); -+ if (!hes_result || !hes_result[0]) { -+ int err = errno; -+ if (err == HES_ER_NOTFOUND) -+ ret = CHE_MISSING; -+ else -+ ret = CHE_FAIL; -+ goto done; -+ } -+ -+ cache_writelock(mc); -+ ret = cache_update(mc, source, lkp_key, *hes_result, time(NULL)); -+ cache_unlock(mc); -+ -+ if (hes_result) -+ hesiod_free_list(ctxt->hesiod_context, hes_result); -+done: -+ free(lkp_key); -+ -+ status = pthread_mutex_unlock(&hesiod_mutex); -+ if (status) -+ fatal(status); -+ -+ return ret; -+} -+ -+static int match_amd_key(struct autofs_point *ap, -+ struct map_source *source, -+ const char *key, int key_len, -+ struct lookup_context *ctxt) -+{ -+ char buf[MAX_ERR_BUF]; -+ char *lkp_key; -+ char *prefix; -+ int ret; -+ -+ ret = lookup_one_amd(ap, source, key, key_len, ctxt); -+ if (ret == CHE_OK || ret == CHE_UPDATED) -+ return ret; -+ -+ lkp_key = strdup(key); -+ if (!lkp_key) { -+ char *estr = strerror_r(errno, buf, MAX_ERR_BUF); -+ error(ap->logopt, MODPREFIX "strdup: %s", estr); -+ return CHE_FAIL; -+ } -+ -+ ret = CHE_MISSING; -+ -+ /* -+ * Now strip successive directory components and try a -+ * match against map entries ending with a wildcard and -+ * finally try the wilcard entry itself. -+ */ -+ while ((prefix = strrchr(lkp_key, '/'))) { -+ char *match; -+ size_t len; -+ *prefix = '\0'; -+ len = strlen(lkp_key) + 3; -+ match = malloc(len); -+ if (!match) { -+ char *estr = strerror_r(errno, buf, MAX_ERR_BUF); -+ error(ap->logopt, MODPREFIX "malloc: %s", estr); -+ ret = CHE_FAIL; -+ goto done; -+ } -+ len--; -+ strcpy(match, lkp_key); -+ strcat(match, "/*"); -+ ret = lookup_one_amd(ap, source, match, len, ctxt); -+ free(match); -+ if (ret == CHE_OK || ret == CHE_UPDATED) -+ goto done; -+ } -+ -+ /* Lastly try the wildcard */ -+ ret = lookup_one_amd(ap, source, "*", 1, ctxt); -+done: -+ free(lkp_key); -+ return ret; -+} -+ - int lookup_mount(struct autofs_point *ap, const char *name, int name_len, void *context) - { - struct lookup_context *ctxt = (struct lookup_context *) context; -- struct map_source *source; - struct mapent_cache *mc; -+ char buf[MAX_ERR_BUF]; -+ struct map_source *source; - struct mapent *me; -- char **hes_result; -- int status, rv; -- char **record, *best_record = NULL, *p; -- int priority, lowest_priority = INT_MAX; -+ char key[KEY_MAX_LEN + 1]; -+ size_t key_len; -+ char *lkp_key; -+ size_t len; -+ char *mapent; -+ int rv; - - source = ap->entry->current; - ap->entry->current = NULL; -@@ -118,6 +323,19 @@ int lookup_mount(struct autofs_point *ap, const char *name, int name_len, void * - MODPREFIX "looking up root=\"%s\", name=\"%s\"", - ap->path, name); - -+ if (!(source->flags & MAP_FLAG_FORMAT_AMD)) { -+ key_len = snprintf(key, KEY_MAX_LEN + 1, "%s", name); -+ if (key_len > KEY_MAX_LEN) -+ return NSS_STATUS_NOTFOUND; -+ } else { -+ key_len = expandamdent(name, NULL, NULL); -+ if (key_len > KEY_MAX_LEN) -+ return NSS_STATUS_NOTFOUND; -+ expandamdent(name, key, NULL); -+ key[key_len] = '\0'; -+ debug(ap->logopt, MODPREFIX "expanded key: \"%s\"", key); -+ } -+ - /* Check if we recorded a mount fail for this key anywhere */ - me = lookup_source_mapent(ap, name, LKP_DISTINCT); - if (me) { -@@ -144,69 +362,61 @@ int lookup_mount(struct autofs_point *ap, const char *name, int name_len, void * - } - } - -- chdir("/"); /* If this is not here the filesystem stays -- busy, for some reason... */ -- -- status = pthread_mutex_lock(&hesiod_mutex); -- if (status) -- fatal(status); -- -- hes_result = hesiod_resolve(ctxt->hesiod_context, name, "filsys"); -- if (!hes_result || !hes_result[0]) { -- /* Note: it is not clear to me how to distinguish between -- * the "no search results" case and other failures. --JM */ -- error(ap->logopt, -- MODPREFIX "key \"%s\" not found in map", name); -- status = pthread_mutex_unlock(&hesiod_mutex); -- if (status) -- fatal(status); -- return NSS_STATUS_NOTFOUND; -+ /* If this is not here the filesystem stays busy, for some reason... */ -+ if (chdir("/")) -+ warn(ap->logopt, -+ MODPREFIX "failed to set working directory to \"/\""); -+ -+ len = key_len; -+ if (!(source->flags & MAP_FLAG_FORMAT_AMD)) -+ lkp_key = strdup(key); -+ else { -+ rv = lookup_one_amd(ap, source, "/defaults", 9, ctxt); -+ if (rv == CHE_FAIL) -+ warn(ap->logopt, -+ MODPREFIX "failed to lookup \"/defaults\" entry"); -+ -+ if (!ap->pref) -+ lkp_key = strdup(key); -+ else { -+ len += strlen(ap->pref); -+ lkp_key = malloc(len + 1); -+ if (lkp_key) { -+ strcpy(lkp_key, ap->pref); -+ strcat(lkp_key, name); -+ } -+ } - } - -- /* autofs doesn't support falling back to alternate records, so just -- find the record with the lowest priority and hope it works. -- -- Aaron Ucko 2002-03-11 */ -- for (record = hes_result; *record; ++record) { -- p = strrchr(*record, ' '); -- if ( p && isdigit(p[1]) ) { -- priority = atoi(p+1); -- } else { -- priority = INT_MAX - 1; -- } -- if (priority < lowest_priority) { -- lowest_priority = priority; -- best_record = *record; -- } -+ if (!lkp_key) { -+ char *estr = strerror_r(errno, buf, MAX_ERR_BUF); -+ error(ap->logopt, "malloc: %s", estr); -+ return NSS_STATUS_UNKNOWN; - } - -- cache_writelock(mc); -- rv = cache_update(mc, source, name, best_record, time(NULL)); -- cache_unlock(mc); -- if (rv == CHE_FAIL) -- return NSS_STATUS_UNAVAIL; -+ if (source->flags & MAP_FLAG_FORMAT_AMD) -+ rv = match_amd_key(ap, source, lkp_key, len, ctxt); -+ else -+ rv = lookup_one(ap, source, lkp_key, len, ctxt); - -- debug(ap->logopt, -- MODPREFIX "lookup for \"%s\" gave \"%s\"", -- name, best_record); -+ if (rv == CHE_FAIL) { -+ free(lkp_key); -+ return NSS_STATUS_UNAVAIL; -+ } - -- rv = ctxt->parser->parse_mount(ap, name, name_len, best_record, -- ctxt->parser->context); -+ me = match_cached_key(ap, MODPREFIX, source, lkp_key); -+ free(lkp_key); -+ if (!me) -+ return NSS_STATUS_NOTFOUND; - -- hesiod_free_list(ctxt->hesiod_context, hes_result); -+ if (!me->mapent) -+ return NSS_STATUS_UNAVAIL; - -- status = pthread_mutex_unlock(&hesiod_mutex); -- if (status) -- fatal(status); -+ mapent = strdup(me->mapent); - -- if (rv) { -- /* Don't update negative cache when re-connecting */ -- if (ap->flags & MOUNT_FLAG_REMOUNT) -- return NSS_STATUS_TRYAGAIN; -- cache_writelock(mc); -- cache_update_negative(mc, source, name, ap->negative_timeout); -- cache_unlock(mc); -- return NSS_STATUS_TRYAGAIN; -- } -+ rv = ctxt->parser->parse_mount(ap, key, key_len, -+ mapent, ctxt->parser->context); -+ free(mapent); - - /* - * Unavailable due to error such as module load fail diff --git a/autofs-5.0.8-amd-lookup-update-lookup-ldap-to-handle-amd-keys.patch b/autofs-5.0.8-amd-lookup-update-lookup-ldap-to-handle-amd-keys.patch deleted file mode 100644 index a40d4ce..0000000 --- a/autofs-5.0.8-amd-lookup-update-lookup-ldap-to-handle-amd-keys.patch +++ /dev/null @@ -1,954 +0,0 @@ -autofs-5.0.8 - amd lookup update lookup ldap to handle amd keys - -From: Ian Kent - - ---- - CHANGELOG | 3 - include/lookup_ldap.h | 3 - modules/lookup_ldap.c | 707 +++++++++++++++++++++++++++++++++++++++++++++---- - 3 files changed, 654 insertions(+), 59 deletions(-) - -diff --git a/CHANGELOG b/CHANGELOG -index 5cc1506..16a8ab4 100644 ---- a/CHANGELOG -+++ b/CHANGELOG -@@ -2,6 +2,9 @@ - ======================= - - fix mistake in assignment. - - add amd map format parser. -+- amd lookup update lookup ldap to handle amd keys -+ - inadvertantly drop from initial series. -+ - - 28/03/2014 autofs-5.0.9 - ======================= -diff --git a/include/lookup_ldap.h b/include/lookup_ldap.h -index f34c029..ba817aa 100644 ---- a/include/lookup_ldap.h -+++ b/include/lookup_ldap.h -@@ -36,6 +36,7 @@ struct ldap_searchdn { - - struct lookup_context { - char *mapname; -+ unsigned int format; - - char *server; - int port; -@@ -43,6 +44,8 @@ struct lookup_context { - char *qdn; - unsigned int timeout; - unsigned int network_timeout; -+ unsigned long timestamp; -+ unsigned int check_defaults; - - /* LDAP version 2 or 3 */ - int version; -diff --git a/modules/lookup_ldap.c b/modules/lookup_ldap.c -index c22d100..833cb86 100644 ---- a/modules/lookup_ldap.c -+++ b/modules/lookup_ldap.c -@@ -29,6 +29,7 @@ - #include - #include - #include -+#include - - #define MODULE_LOOKUP - #include "automount.h" -@@ -52,6 +53,14 @@ static struct ldap_schema common_schema[] = { - }; - static unsigned int common_schema_count = sizeof(common_schema)/sizeof(struct ldap_schema); - -+static struct ldap_schema amd_timestamp = { -+ "madmap", "amdmapName", "amdmapTimestamp", NULL, "amdmapTimestamp" -+}; -+ -+static struct ldap_schema amd_schema = { -+ "amdmap", "amdmapName", "amdmap", "amdmapKey", "amdmapValue" -+}; -+ - /* - * Initialization and de-initialization of LDAP and OpenSSL must be - * always serialized to avoid corruption of context structures inside -@@ -62,6 +71,7 @@ pthread_mutex_t ldapinit_mutex = PTHREAD_MUTEX_INITIALIZER; - struct ldap_search_params { - struct autofs_point *ap; - LDAP *ldap; -+ char *base; - char *query, **attrs; - struct berval *cookie; - ber_int_t pageSize; -@@ -531,6 +541,16 @@ static int find_query_dn(unsigned logopt, LDAP *ldap, struct lookup_context *ctx - if (ctxt->schema) - return 0; - -+ if (ctxt->format & MAP_FLAG_FORMAT_AMD) { -+ schema = alloc_common_schema(&amd_schema); -+ if (!schema) { -+ error(logopt, MODPREFIX "failed to allocate schema"); -+ return 0; -+ } -+ ctxt->schema = schema; -+ return 1; -+ } -+ - for (i = 0; i < common_schema_count; i++) { - const char *class = common_schema[i].map_class; - const char *key = common_schema[i].map_attr; -@@ -587,8 +607,10 @@ static int do_bind(unsigned logopt, LDAP *ldap, const char *uri, struct lookup_c - - if (!ctxt->cur_host) { - ctxt->cur_host = nhost; -- /* Check if schema defined in conf first time only */ -- ctxt->schema = defaults_get_schema(); -+ if (!(ctxt->format & MAP_FLAG_FORMAT_AMD)) { -+ /* Check if schema defined in conf first time only */ -+ ctxt->schema = defaults_get_schema(); -+ } - } else { - /* If connection host has changed update */ - if (strcmp(ctxt->cur_host, nhost)) { -@@ -614,7 +636,7 @@ static int do_bind(unsigned logopt, LDAP *ldap, const char *uri, struct lookup_c - MODPREFIX "failed to find valid query dn"); - return 0; - } -- } else { -+ } else if (!(ctxt->format & MAP_FLAG_FORMAT_AMD)) { - const char *class = ctxt->schema->map_class; - const char *key = ctxt->schema->map_attr; - if (!get_query_dn(logopt, ldap, ctxt, class, key)) { -@@ -648,6 +670,126 @@ static LDAP *do_connect(unsigned logopt, const char *uri, struct lookup_context - return ldap; - } - -+static unsigned long get_amd_timestamp(struct lookup_context *ctxt) -+{ -+ LDAP *ldap; -+ LDAPMessage *result = NULL, *e; -+ char *query; -+ int scope = LDAP_SCOPE_SUBTREE; -+ char *map, *class, *value; -+ char *attrs[2]; -+ struct berval **bvValues; -+ unsigned long timestamp = 0; -+ int rv, l, ql; -+ -+ ldap = do_connect(LOGOPT_ANY, ctxt->server, ctxt); -+ if (!ldap) -+ return 0; -+ -+ map = amd_timestamp.map_attr; -+ class = amd_timestamp.entry_class; -+ value = amd_timestamp.value_attr; -+ -+ attrs[0] = value; -+ attrs[1] = NULL; -+ -+ /* Build a query string. */ -+ l = strlen(class) + -+ strlen(map) + strlen(ctxt->mapname) + 21; -+ -+ query = malloc(l); -+ if (query == NULL) { -+ char buf[MAX_ERR_BUF]; -+ char *estr = strerror_r(errno, buf, sizeof(buf)); -+ crit(LOGOPT_ANY, MODPREFIX "malloc: %s", estr); -+ return 0; -+ } -+ -+ /* -+ * Look for an entry in class under ctxt-base -+ * whose entry is equal to qKey. -+ */ -+ ql = sprintf(query, "(&(objectclass=%s)(%s=%s))", -+ class, map, ctxt->mapname); -+ if (ql >= l) { -+ error(LOGOPT_ANY, -+ MODPREFIX "error forming query string"); -+ free(query); -+ return 0; -+ } -+ -+ rv = ldap_search_s(ldap, ctxt->base, scope, query, attrs, 0, &result); -+ if ((rv != LDAP_SUCCESS) || !result) { -+ crit(LOGOPT_ANY, MODPREFIX "timestamp query failed %s", query); -+ unbind_ldap_connection(LOGOPT_ANY, ldap, ctxt); -+ if (result) -+ ldap_msgfree(result); -+ free(query); -+ return 0; -+ } -+ -+ e = ldap_first_entry(ldap, result); -+ if (!e) { -+ debug(LOGOPT_ANY, -+ MODPREFIX "got answer, but no entry for timestamp"); -+ ldap_msgfree(result); -+ unbind_ldap_connection(LOGOPT_ANY, ldap, ctxt); -+ free(query); -+ return CHE_MISSING; -+ } -+ -+ while (e) { -+ char *v_val; -+ char *endptr; -+ -+ bvValues = ldap_get_values_len(ldap, e, value); -+ if (!bvValues || !*bvValues) { -+ debug(LOGOPT_ANY, -+ MODPREFIX "no value found in timestamp"); -+ goto next; -+ } -+ -+ /* There should be one value for a timestamp */ -+ v_val = bvValues[0]->bv_val; -+ -+ timestamp = strtol(v_val, &endptr, 0); -+ if ((errno == ERANGE && -+ (timestamp == LONG_MAX || timestamp == LONG_MIN)) || -+ (errno != 0 && timestamp == 0)) { -+ debug(LOGOPT_ANY, -+ MODPREFIX "invalid value in timestamp"); -+ free(query); -+ return 0; -+ } -+ -+ if (endptr == v_val) { -+ debug(LOGOPT_ANY, -+ MODPREFIX "no digits found in timestamp"); -+ free(query); -+ return 0; -+ } -+ -+ if (*endptr != '\0') { -+ warn(LOGOPT_ANY, MODPREFIX -+ "characters found after number: %s", endptr); -+ warn(LOGOPT_ANY, -+ MODPREFIX "timestamp may be invalid"); -+ } -+ -+ ldap_value_free_len(bvValues); -+ break; -+next: -+ ldap_value_free_len(bvValues); -+ e = ldap_next_entry(ldap, e); -+ } -+ -+ ldap_msgfree(result); -+ unbind_ldap_connection(LOGOPT_ANY, ldap, ctxt); -+ free(query); -+ -+ return timestamp; -+} -+ - static LDAP *connect_to_server(unsigned logopt, const char *uri, struct lookup_context *ctxt) - { - LDAP *ldap; -@@ -1215,7 +1357,7 @@ static int parse_server_string(unsigned logopt, const char *url, struct lookup_c - const char *q = NULL; - - /* Isolate the server(s). */ -- if ((q = strchr(s, '/'))) { -+ if ((q = strchr(s, '/')) || (q = strchr(s, '\0'))) { - l = q - s; - if (*proto) { - al_len = l + strlen(proto) + 2; -@@ -1318,8 +1460,7 @@ static int parse_server_string(unsigned logopt, const char *url, struct lookup_c - ptr += l + 1; - } - -- /* TODO: why did I do this - how can the map name "and" base dn be missing? */ -- if (!ptr) -+ if (!ptr || ctxt->format & MAP_FLAG_FORMAT_AMD) - goto done; - - /* -@@ -1505,36 +1646,83 @@ int lookup_init(const char *mapfmt, int argc, const char *const *argv, void **co - /* If a map type isn't explicitly given, parse it like sun entries. */ - if (mapfmt == NULL) - mapfmt = MAPFMT_DEFAULT; -- -- /* -- * Parse out the server name and base dn, and fill them -- * into the proper places in the lookup context structure. -- */ -- if (!parse_server_string(LOGOPT_NONE, argv[0], ctxt)) { -- error(LOGOPT_ANY, MODPREFIX "cannot parse server string"); -- free_context(ctxt); -- return 1; -+ if (!strcmp(mapfmt, "amd")) { -+ ctxt->format = MAP_FLAG_FORMAT_AMD; -+ ctxt->check_defaults = 1; - } - -- if (!ctxt->base) -- ctxt->sdns = defaults_get_searchdns(); -- - ctxt->timeout = defaults_get_ldap_timeout(); - ctxt->network_timeout = defaults_get_ldap_network_timeout(); - -- if (!ctxt->server) { -- struct list_head *uris = defaults_get_uris(); -- if (uris) { -- validate_uris(uris); -- if (!list_empty(uris)) -- ctxt->uris = uris; -- else { -- error(LOGOPT_ANY, -- "no valid uris found in config list" -- ", using default system config"); -- free(uris); -+ if (!(ctxt->format & MAP_FLAG_FORMAT_AMD)) { -+ /* -+ * Parse out the server name and base dn, and fill them -+ * into the proper places in the lookup context structure. -+ */ -+ if (!parse_server_string(LOGOPT_NONE, argv[0], ctxt)) { -+ error(LOGOPT_ANY, MODPREFIX "cannot parse server string"); -+ free_context(ctxt); -+ return 1; -+ } -+ -+ if (!ctxt->base) -+ ctxt->sdns = defaults_get_searchdns(); -+ -+ if (!ctxt->server) { -+ struct list_head *uris = defaults_get_uris(); -+ if (uris) { -+ validate_uris(uris); -+ if (!list_empty(uris)) -+ ctxt->uris = uris; -+ else { -+ error(LOGOPT_ANY, MODPREFIX -+ "no valid uris found in config list" -+ ", using default system config"); -+ free(uris); -+ } - } - } -+ } else { -+ char *tmp = conf_amd_get_ldap_base(); -+ if (!tmp) { -+ error(LOGOPT_ANY, MODPREFIX "failed to get base dn"); -+ free_context(ctxt); -+ return 1; -+ } -+ ctxt->base = tmp; -+ -+ tmp = conf_amd_get_ldap_hostports(); -+ if (!tmp) { -+ error(LOGOPT_ANY, -+ MODPREFIX "failed to get ldap_hostports"); -+ free_context(ctxt); -+ return 1; -+ } -+ -+ /* -+ * Parse out the server name and port, and save them in -+ * the proper places in the lookup context structure. -+ */ -+ if (!parse_server_string(LOGOPT_NONE, tmp, ctxt)) { -+ error(LOGOPT_ANY, MODPREFIX "cannot parse server string"); -+ free_context(ctxt); -+ return 1; -+ } -+ free(tmp); -+ -+ if (!ctxt->server) { -+ error(LOGOPT_ANY, MODPREFIX "ldap_hostports not valid"); -+ free_context(ctxt); -+ return 1; -+ } -+ -+ tmp = strdup(argv[0]); -+ if (!tmp) { -+ error(LOGOPT_ANY, MODPREFIX "failed to set mapname"); -+ free_context(ctxt); -+ return 1; -+ } -+ ctxt->mapname = tmp; - } - - /* -@@ -1558,6 +1746,8 @@ int lookup_init(const char *mapfmt, int argc, const char *const *argv, void **co - } - #endif - -+ ctxt->timestamp = get_amd_timestamp(ctxt); -+ - /* Open the parser, if we can. */ - ctxt->parse = open_parse(mapfmt, MODPREFIX, argc - 1, argv + 1); - if (!ctxt->parse) { -@@ -2029,7 +2219,7 @@ static int do_paged_query(struct ldap_search_params *sp, struct lookup_context * - if (sp->morePages == TRUE) - goto do_paged; - -- rv = ldap_search_s(sp->ldap, ctxt->qdn, scope, sp->query, sp->attrs, 0, &sp->result); -+ rv = ldap_search_s(sp->ldap, sp->base, scope, sp->query, sp->attrs, 0, &sp->result); - if ((rv != LDAP_SUCCESS) || !sp->result) { - /* - * Check for Size Limit exceeded and force run through loop -@@ -2063,7 +2253,7 @@ do_paged: - - /* Search for entries in the directory using the parmeters. */ - rv = ldap_search_ext_s(sp->ldap, -- ctxt->qdn, scope, sp->query, sp->attrs, -+ sp->base, scope, sp->query, sp->attrs, - 0, controls, NULL, NULL, 0, &sp->result); - if ((rv != LDAP_SUCCESS) && (rv != LDAP_PARTIAL_RESULTS)) { - ldap_control_free(pageControl); -@@ -2364,6 +2554,115 @@ next: - return LDAP_SUCCESS; - } - -+static int do_get_amd_entries(struct ldap_search_params *sp, -+ struct map_source *source, -+ struct lookup_context *ctxt) -+{ -+ struct autofs_point *ap = sp->ap; -+ struct mapent_cache *mc = source->mc; -+ struct berval **bvKey; -+ struct berval **bvValues; -+ LDAPMessage *e; -+ char *entry, *value; -+ int rv, ret, count; -+ -+ entry = ctxt->schema->entry_attr; -+ value = ctxt->schema->value_attr; -+ -+ e = ldap_first_entry(sp->ldap, sp->result); -+ if (!e) { -+ debug(ap->logopt, -+ MODPREFIX "query succeeded, no matches for %s", -+ sp->query); -+ ret = ldap_parse_result(sp->ldap, sp->result, -+ &rv, NULL, NULL, NULL, NULL, 0); -+ if (ret == LDAP_SUCCESS) -+ return rv; -+ else -+ return LDAP_OPERATIONS_ERROR; -+ } else -+ debug(ap->logopt, MODPREFIX "examining entries"); -+ -+ while (e) { -+ char *k_val, *v_val; -+ ber_len_t k_len; -+ char *s_key; -+ -+ bvKey = ldap_get_values_len(sp->ldap, e, entry); -+ if (!bvKey || !*bvKey) { -+ e = ldap_next_entry(sp->ldap, e); -+ if (!e) { -+ debug(ap->logopt, MODPREFIX -+ "failed to get next entry for query %s", -+ sp->query); -+ ret = ldap_parse_result(sp->ldap, -+ sp->result, &rv, -+ NULL, NULL, NULL, NULL, 0); -+ if (ret == LDAP_SUCCESS) -+ return rv; -+ else -+ return LDAP_OPERATIONS_ERROR; -+ } -+ continue; -+ } -+ -+ /* By definition keys should be unique within each map entry */ -+ k_val = NULL; -+ k_len = 0; -+ -+ count = ldap_count_values_len(bvKey); -+ if (count > 1) -+ warn(ap->logopt, MODPREFIX -+ "more than one %s, using first", entry); -+ -+ k_val = bvKey[0]->bv_val; -+ k_len = bvKey[0]->bv_len; -+ -+ bvValues = ldap_get_values_len(sp->ldap, e, value); -+ if (!bvValues || !*bvValues) { -+ debug(ap->logopt, -+ MODPREFIX "no %s defined for %s", -+ value, sp->query); -+ goto next; -+ } -+ -+ count = ldap_count_values_len(bvValues); -+ if (count > 1) -+ warn(ap->logopt, MODPREFIX -+ "more than one %s, using first", value); -+ -+ v_val = bvValues[0]->bv_val; -+ -+ /* Don't fail on "/" in key => type == 0 */ -+ s_key = sanitize_path(k_val, k_len, 0, ap->logopt); -+ if (!s_key) -+ goto next; -+ -+ cache_writelock(mc); -+ cache_update(mc, source, s_key, v_val, sp->age); -+ cache_unlock(mc); -+ -+ free(s_key); -+next: -+ ldap_value_free_len(bvValues); -+ ldap_value_free_len(bvKey); -+ e = ldap_next_entry(sp->ldap, e); -+ if (!e) { -+ debug(ap->logopt, MODPREFIX -+ "failed to get next entry for query %s", -+ sp->query); -+ ret = ldap_parse_result(sp->ldap, -+ sp->result, &rv, -+ NULL, NULL, NULL, NULL, 0); -+ if (ret == LDAP_SUCCESS) -+ return rv; -+ else -+ return LDAP_OPERATIONS_ERROR; -+ } -+ } -+ -+ return LDAP_SUCCESS; -+} - - static int read_one_map(struct autofs_point *ap, - struct map_source *source, -@@ -2419,9 +2718,14 @@ static int read_one_map(struct autofs_point *ap, - return NSS_STATUS_UNAVAIL; - } - -+ if (ctxt->format & MAP_FLAG_FORMAT_AMD) -+ sp.base = ctxt->base; -+ else -+ sp.base = ctxt->qdn; -+ - /* Look around. */ - debug(ap->logopt, -- MODPREFIX "searching for \"%s\" under \"%s\"", sp.query, ctxt->qdn); -+ MODPREFIX "searching for \"%s\" under \"%s\"", sp.query, sp.base); - - sp.cookie = NULL; - sp.pageSize = 2000; -@@ -2465,7 +2769,10 @@ static int read_one_map(struct autofs_point *ap, - return NSS_STATUS_UNAVAIL; - } - -- rv = do_get_entries(&sp, source, ctxt); -+ if (source->flags & MAP_FLAG_FORMAT_AMD) -+ rv = do_get_amd_entries(&sp, source, ctxt); -+ else -+ rv = do_get_entries(&sp, source, ctxt); - if (rv != LDAP_SUCCESS) { - ldap_msgfree(sp.result); - unbind_ldap_connection(ap->logopt, sp.ldap, ctxt); -@@ -2874,6 +3181,219 @@ next: - return ret; - } - -+static int lookup_one_amd(struct autofs_point *ap, -+ struct map_source *source, -+ char *qKey, int qKey_len, -+ struct lookup_context *ctxt) -+{ -+ struct mapent_cache *mc = source->mc; -+ LDAP *ldap; -+ LDAPMessage *result = NULL, *e; -+ char *query; -+ int scope = LDAP_SCOPE_SUBTREE; -+ char *map, *class, *entry, *value; -+ char *attrs[3]; -+ struct berval **bvKey; -+ struct berval **bvValues; -+ char buf[MAX_ERR_BUF]; -+ time_t age = time(NULL); -+ int rv, l, ql, count; -+ int ret = CHE_MISSING; -+ -+ if (ctxt == NULL) { -+ crit(ap->logopt, MODPREFIX "context was NULL"); -+ return CHE_FAIL; -+ } -+ -+ /* Initialize the LDAP context. */ -+ ldap = do_reconnect(ap->logopt, ctxt); -+ if (!ldap) -+ return CHE_UNAVAIL; -+ -+ map = ctxt->schema->map_attr; -+ class = ctxt->schema->entry_class; -+ entry = ctxt->schema->entry_attr; -+ value = ctxt->schema->value_attr; -+ -+ attrs[0] = entry; -+ attrs[1] = value; -+ attrs[2] = NULL; -+ -+ /* Build a query string. */ -+ l = strlen(class) + -+ strlen(map) + strlen(ctxt->mapname) + -+ strlen(entry) + strlen(qKey) + 24; -+ -+ query = malloc(l); -+ if (query == NULL) { -+ char *estr = strerror_r(errno, buf, sizeof(buf)); -+ crit(ap->logopt, MODPREFIX "malloc: %s", estr); -+ return CHE_FAIL; -+ } -+ -+ /* -+ * Look for an entry in class under ctxt-base -+ * whose entry is equal to qKey. -+ */ -+ ql = sprintf(query, "(&(objectclass=%s)(%s=%s)(%s=%s))", -+ class, map, ctxt->mapname, entry, qKey); -+ if (ql >= l) { -+ error(ap->logopt, -+ MODPREFIX "error forming query string"); -+ free(query); -+ return CHE_FAIL; -+ } -+ -+ debug(ap->logopt, -+ MODPREFIX "searching for \"%s\" under \"%s\"", query, ctxt->base); -+ -+ rv = ldap_search_s(ldap, ctxt->base, scope, query, attrs, 0, &result); -+ if ((rv != LDAP_SUCCESS) || !result) { -+ crit(ap->logopt, MODPREFIX "query failed for %s", query); -+ unbind_ldap_connection(ap->logopt, ldap, ctxt); -+ if (result) -+ ldap_msgfree(result); -+ free(query); -+ return CHE_FAIL; -+ } -+ -+ debug(ap->logopt, -+ MODPREFIX "getting first entry for %s=\"%s\"", entry, qKey); -+ -+ e = ldap_first_entry(ldap, result); -+ if (!e) { -+ debug(ap->logopt, -+ MODPREFIX "got answer, but no entry for %s", query); -+ ldap_msgfree(result); -+ unbind_ldap_connection(ap->logopt, ldap, ctxt); -+ free(query); -+ return CHE_MISSING; -+ } -+ -+ while (e) { -+ char *k_val, *v_val; -+ ber_len_t k_len; -+ char *s_key; -+ -+ bvKey = ldap_get_values_len(ldap, e, entry); -+ if (!bvKey || !*bvKey) { -+ e = ldap_next_entry(ldap, e); -+ continue; -+ } -+ -+ /* By definition keys should be unique within each map entry */ -+ k_val = NULL; -+ k_len = 0; -+ -+ count = ldap_count_values_len(bvKey); -+ if (count > 1) -+ warn(ap->logopt, MODPREFIX -+ "more than one %s, using first", entry); -+ -+ k_val = bvKey[0]->bv_val; -+ k_len = bvKey[0]->bv_len; -+ -+ debug(ap->logopt, MODPREFIX "examining first entry"); -+ -+ bvValues = ldap_get_values_len(ldap, e, value); -+ if (!bvValues || !*bvValues) { -+ debug(ap->logopt, -+ MODPREFIX "no %s defined for %s", value, query); -+ goto next; -+ } -+ -+ count = ldap_count_values_len(bvValues); -+ if (count > 1) -+ warn(ap->logopt, MODPREFIX -+ "more than one %s, using first", value); -+ -+ /* There should be one value for a key, use first value */ -+ v_val = bvValues[0]->bv_val; -+ -+ /* Don't fail on "/" in key => type == 0 */ -+ s_key = sanitize_path(k_val, k_len, 0, ap->logopt); -+ if (!s_key) -+ goto next; -+ -+ cache_writelock(mc); -+ ret = cache_update(mc, source, s_key, v_val, age); -+ cache_unlock(mc); -+ -+ free(s_key); -+next: -+ ldap_value_free_len(bvValues); -+ ldap_value_free_len(bvKey); -+ e = ldap_next_entry(ldap, e); -+ } -+ -+ ldap_msgfree(result); -+ unbind_ldap_connection(ap->logopt, ldap, ctxt); -+ free(query); -+ -+ return ret; -+} -+ -+static int match_key(struct autofs_point *ap, -+ struct map_source *source, -+ char *key, int key_len, -+ struct lookup_context *ctxt) -+{ -+ unsigned int is_amd_format = source->flags & MAP_FLAG_FORMAT_AMD; -+ char buf[MAX_ERR_BUF]; -+ char *lkp_key; -+ char *prefix; -+ int ret; -+ -+ if (is_amd_format) -+ ret = lookup_one_amd(ap, source, key, key_len, ctxt); -+ else -+ ret = lookup_one(ap, source, key, key_len, ctxt); -+ -+ if (ret == CHE_OK || ret == CHE_UPDATED) -+ return ret; -+ -+ if (!is_amd_format) -+ return CHE_FAIL; -+ -+ lkp_key = strdup(key); -+ if (!lkp_key) { -+ char *estr = strerror_r(errno, buf, MAX_ERR_BUF); -+ error(ap->logopt, MODPREFIX "strdup: %s", estr); -+ return CHE_FAIL; -+ } -+ -+ ret = CHE_MISSING; -+ -+ /* -+ * Now strip successive directory components and try a -+ * match against map entries ending with a wildcard and -+ * finally try the wilcard entry itself. -+ */ -+ while ((prefix = strrchr(lkp_key, '/'))) { -+ char *match; -+ size_t len; -+ *prefix = '\0'; -+ len = strlen(lkp_key + 3); -+ match = malloc(len); -+ if (!match) { -+ char *estr = strerror_r(errno, buf, MAX_ERR_BUF); -+ error(ap->logopt, MODPREFIX "malloc: %s", estr); -+ ret = CHE_FAIL; -+ goto done; -+ } -+ len--; -+ strcpy(match, lkp_key); -+ strcat(match, "/*"); -+ ret = lookup_one_amd(ap, source, match, len, ctxt); -+ free(match); -+ if (ret == CHE_OK || ret == CHE_UPDATED) -+ goto done; -+ } -+done: -+ free(lkp_key); -+ return ret; -+} -+ - static int check_map_indirect(struct autofs_point *ap, - struct map_source *source, - char *key, int key_len, -@@ -2888,16 +3408,43 @@ static int check_map_indirect(struct autofs_point *ap, - mc = source->mc; - - pthread_setcancelstate(PTHREAD_CANCEL_DISABLE, &cur_state); -- ret = lookup_one(ap, source, key, key_len, ctxt); -+ -+ pthread_mutex_lock(&ap->entry->current_mutex); -+ if (source->flags & MAP_FLAG_FORMAT_AMD) { -+ unsigned long timestamp = get_amd_timestamp(ctxt); -+ if (timestamp > ctxt->timestamp) { -+ ctxt->timestamp = timestamp; -+ source->stale = 1; -+ ctxt->check_defaults = 1; -+ } -+ -+ if (ctxt->check_defaults) { -+ /* Check for a /defaults entry */ -+ ret = lookup_one_amd(ap, source, "/defaults", 9, ctxt); -+ if (ret == CHE_FAIL) { -+ warn(ap->logopt, MODPREFIX -+ "error getting /defaults from map %s", -+ ctxt->mapname); -+ } else -+ ctxt->check_defaults = 0; -+ } -+ } -+ pthread_mutex_unlock(&ap->entry->current_mutex); -+ -+ ret = match_key(ap, source, key, key_len, ctxt); - if (ret == CHE_FAIL) { - pthread_setcancelstate(cur_state, NULL); - return NSS_STATUS_NOTFOUND; - } else if (ret == CHE_UNAVAIL) { -+ struct mapent *exists; - /* - * If the server is down and the entry exists in the cache - * and belongs to this map return success and use the entry. - */ -- struct mapent *exists = cache_lookup(mc, key); -+ if (source->flags & MAP_FLAG_FORMAT_AMD) -+ exists = match_cached_key(ap, MODPREFIX, source, key); -+ else -+ exists = cache_lookup(mc, key); - if (exists && exists->source == source) { - pthread_setcancelstate(cur_state, NULL); - return NSS_STATUS_SUCCESS; -@@ -2910,24 +3457,28 @@ static int check_map_indirect(struct autofs_point *ap, - } - pthread_setcancelstate(cur_state, NULL); - -- /* -- * Check for map change and update as needed for -- * following cache lookup. -- */ -- cache_readlock(mc); -- t_last_read = ap->exp_runfreq + 1; -- me = cache_lookup_first(mc); -- while (me) { -- if (me->source == source) { -- t_last_read = now - me->age; -- break; -+ if (!(source->flags & MAP_FLAG_FORMAT_AMD)) { -+ /* -+ * Check for map change and update as needed for -+ * following cache lookup. -+ */ -+ cache_readlock(mc); -+ t_last_read = ap->exp_runfreq + 1; -+ me = cache_lookup_first(mc); -+ while (me) { -+ if (me->source == source) { -+ t_last_read = now - me->age; -+ break; -+ } -+ me = cache_lookup_next(mc, me); - } -- me = cache_lookup_next(mc, me); -- } -- cache_unlock(mc); -+ cache_unlock(mc); - -- if (t_last_read > ap->exp_runfreq && ret & CHE_UPDATED) -- source->stale = 1; -+ pthread_mutex_lock(&ap->entry->current_mutex); -+ if (t_last_read > ap->exp_runfreq && ret & CHE_UPDATED) -+ source->stale = 1; -+ pthread_mutex_unlock(&ap->entry->current_mutex); -+ } - - cache_readlock(mc); - me = cache_lookup_distinct(mc, "*"); -@@ -2948,8 +3499,10 @@ int lookup_mount(struct autofs_point *ap, const char *name, int name_len, void * - struct mapent *me; - char key[KEY_MAX_LEN + 1]; - int key_len; -+ char *lkp_key; - char *mapent = NULL; - char mapent_buf[MAPENT_MAX_LEN + 1]; -+ char buf[MAX_ERR_BUF]; - int status = 0; - int ret = 1; - -@@ -2961,9 +3514,18 @@ int lookup_mount(struct autofs_point *ap, const char *name, int name_len, void * - - debug(ap->logopt, MODPREFIX "looking up %s", name); - -- key_len = snprintf(key, KEY_MAX_LEN + 1, "%s", name); -- if (key_len > KEY_MAX_LEN) -- return NSS_STATUS_NOTFOUND; -+ if (!(source->flags & MAP_FLAG_FORMAT_AMD)) { -+ key_len = snprintf(key, KEY_MAX_LEN + 1, "%s", name); -+ if (key_len > KEY_MAX_LEN) -+ return NSS_STATUS_NOTFOUND; -+ } else { -+ key_len = expandamdent(name, NULL, NULL); -+ if (key_len > KEY_MAX_LEN) -+ return NSS_STATUS_NOTFOUND; -+ expandamdent(name, key, NULL); -+ key[key_len] = '\0'; -+ debug(ap->logopt, MODPREFIX "expanded key: \"%s\"", key); -+ } - - /* Check if we recorded a mount fail for this key anywhere */ - me = lookup_source_mapent(ap, key, LKP_DISTINCT); -@@ -2997,18 +3559,26 @@ int lookup_mount(struct autofs_point *ap, const char *name, int name_len, void * - * we never know about it. - */ - if (ap->type == LKP_INDIRECT && *key != '/') { -- char *lkp_key; -- - cache_readlock(mc); - me = cache_lookup_distinct(mc, key); - if (me && me->multi) - lkp_key = strdup(me->multi->key); -- else -+ else if (!ap->pref) - lkp_key = strdup(key); -+ else { -+ lkp_key = malloc(strlen(ap->pref) + strlen(key) + 1); -+ if (lkp_key) { -+ strcpy(lkp_key, ap->pref); -+ strcat(lkp_key, key); -+ } -+ } - cache_unlock(mc); - -- if (!lkp_key) -+ if (!lkp_key) { -+ char *estr = strerror_r(errno, buf, MAX_ERR_BUF); -+ error(ap->logopt, MODPREFIX "malloc: %s", estr); - return NSS_STATUS_UNKNOWN; -+ } - - status = check_map_indirect(ap, source, - lkp_key, strlen(lkp_key), ctxt); -@@ -3029,7 +3599,25 @@ int lookup_mount(struct autofs_point *ap, const char *name, int name_len, void * - cache_readlock(mc); - else - cache_writelock(mc); -- me = cache_lookup(mc, key); -+ -+ if (!ap->pref) -+ lkp_key = strdup(key); -+ else { -+ lkp_key = malloc(strlen(ap->pref) + strlen(key) + 1); -+ if (lkp_key) { -+ strcpy(lkp_key, ap->pref); -+ strcat(lkp_key, key); -+ } -+ } -+ -+ if (!lkp_key) { -+ char *estr = strerror_r(errno, buf, MAX_ERR_BUF); -+ error(ap->logopt, MODPREFIX "malloc: %s", estr); -+ cache_unlock(mc); -+ return NSS_STATUS_UNKNOWN; -+ } -+ -+ me = match_cached_key(ap, MODPREFIX, source, lkp_key); - /* Stale mapent => check for entry in alternate source or wildcard */ - if (me && !me->mapent) { - while ((me = cache_lookup_key_next(me))) -@@ -3055,6 +3643,7 @@ int lookup_mount(struct autofs_point *ap, const char *name, int name_len, void * - } - } - cache_unlock(mc); -+ free(lkp_key); - - if (!mapent) - return NSS_STATUS_TRYAGAIN; diff --git a/autofs-5.0.8-fix-WITH_LIBTIRPC-function-name.patch b/autofs-5.0.8-fix-WITH_LIBTIRPC-function-name.patch deleted file mode 100644 index d62b028..0000000 --- a/autofs-5.0.8-fix-WITH_LIBTIRPC-function-name.patch +++ /dev/null @@ -1,49 +0,0 @@ -autofs-5.0.8 - fix WITH_LIBTIRPC function name - -From: Ian Kent - -autoconf function names AM_ are reserved so don't use them. ---- - CHANGELOG | 1 + - aclocal.m4 | 2 +- - configure.in | 2 +- - 3 files changed, 3 insertions(+), 2 deletions(-) - -diff --git a/CHANGELOG b/CHANGELOG -index 565153d..68db340 100644 ---- a/CHANGELOG -+++ b/CHANGELOG -@@ -4,6 +4,7 @@ - - fix master map type check. - - fix task manager not getting signaled. - - allow --with-systemd to take a path arg. -+- fix WITH_LIBTIRPC function name. - - 17/10/2013 autofs-5.0.8 - ======================= -diff --git a/aclocal.m4 b/aclocal.m4 -index 105e3e9..2115204 100644 ---- a/aclocal.m4 -+++ b/aclocal.m4 -@@ -441,7 +441,7 @@ CFLAGS="$af_check_libtirpc_save_cflags" - LDFLAGS="$af_check_libtirpc_save_ldflags" - ]) - --AC_DEFUN([AM_WITH_LIBTIRPC], -+AC_DEFUN([AF_WITH_LIBTIRPC], - [AC_MSG_CHECKING([if libtirpc is requested and available]) - AC_ARG_WITH(libtirpc, - [ --with-libtirpc use libtirpc if available], -diff --git a/configure.in b/configure.in -index 5f29163..1eeb8dc 100644 ---- a/configure.in -+++ b/configure.in -@@ -124,7 +124,7 @@ AC_SUBST(flagdir) - # - # Use libtirpc - # --AM_WITH_LIBTIRPC() -+AF_WITH_LIBTIRPC() - AC_SUBST(TIRPCLIB) - - # diff --git a/autofs-5.0.8-fix-allow-with-systemd-to-take-a-path-arg.patch b/autofs-5.0.8-fix-allow-with-systemd-to-take-a-path-arg.patch deleted file mode 100644 index d49cb59..0000000 --- a/autofs-5.0.8-fix-allow-with-systemd-to-take-a-path-arg.patch +++ /dev/null @@ -1,37 +0,0 @@ -autofs-5.0.8 - fix allow with systemd to take a path arg - -From: Ian Kent - -And update configure .. ---- - configure | 10 ++++++++-- - 1 file changed, 8 insertions(+), 2 deletions(-) - -diff --git a/configure b/configure -index 2c2e312..4e1743d 100755 ---- a/configure -+++ b/configure -@@ -1372,8 +1372,10 @@ Optional Packages: - --with-PACKAGE[=ARG] use PACKAGE [ARG=yes] - --without-PACKAGE do not use PACKAGE (same as --with-PACKAGE=no) - --with-path=PATH look in PATH for binaries needed by the automounter -- --with-systemd install systemd unit file if systemd unit directory -- is found on system -+ --with-systemd[=systemddir] install systemd unit file. If 'yes' -+ probe the system for unit directory. -+ If a path is specified, assume that -+ is a valid install path. - --with-confdir=DIR use DIR for autofs configuration files - --with-mapdir=PATH look in PATH for mount maps used by the automounter - --with-fifodir=PATH use PATH as the directory for fifos used by the automounter -@@ -2260,6 +2262,10 @@ $as_echo "$systemddir" >&6; } - { $as_echo "$as_me:${as_lineno-$LINENO}: result: not found" >&5 - $as_echo "not found" >&6; } - fi -+else -+ if test "$withval" != no; then -+ systemddir=$withval -+ fi - fi - fi - diff --git a/autofs-5.0.8-fix-fix-ipv6-libtirpc-getport.patch b/autofs-5.0.8-fix-fix-ipv6-libtirpc-getport.patch deleted file mode 100644 index 70877ca..0000000 --- a/autofs-5.0.8-fix-fix-ipv6-libtirpc-getport.patch +++ /dev/null @@ -1,34 +0,0 @@ -autofs-5.0.8 - fix fix ipv6 libtirpc getport - -From: Ian Kent - -Remove a duplicated case entry and remove redundant check, since it -can never be reached, in rpc_rpcb_getport(). ---- - lib/rpc_subs.c | 6 +----- - 1 file changed, 1 insertion(+), 5 deletions(-) - -diff --git a/lib/rpc_subs.c b/lib/rpc_subs.c -index 9d5b2f5..cfb63d2 100644 ---- a/lib/rpc_subs.c -+++ b/lib/rpc_subs.c -@@ -524,7 +524,6 @@ static enum clnt_stat rpc_rpcb_getport(CLIENT *client, - if (rpcerr.re_vers.low > RPCBVERS4) - return status; - continue; -- case RPC_PROCUNAVAIL: - case RPC_PROGUNAVAIL: - continue; - default: -@@ -533,10 +532,7 @@ static enum clnt_stat rpc_rpcb_getport(CLIENT *client, - } - } - -- if (s_port == 0) -- return RPC_PROGNOTREGISTERED; -- -- return RPC_PROCUNAVAIL; -+ return RPC_PROGNOTREGISTERED; - } - - static enum clnt_stat rpc_getport(struct conn_info *info, diff --git a/autofs-5.0.8-fix-ipv6-libtirpc-getport-proto-not-set.patch b/autofs-5.0.8-fix-ipv6-libtirpc-getport-proto-not-set.patch deleted file mode 100644 index f335fa5..0000000 --- a/autofs-5.0.8-fix-ipv6-libtirpc-getport-proto-not-set.patch +++ /dev/null @@ -1,32 +0,0 @@ -autofs-5.0.8 - fix rpc_portmap_getport() proto not set - -From: Ian Kent - -Recent changes to fix libtirpc usage problems when getting a server -exports list cause later server probing to fail. - -When getting an exports list a new rpc client is always created for -the query, which includes setting the protocol in the parameters -structure. But when probing availability the client is reused where -possible and the protocol is not set in the parameters structure in -this case. - -The rpc_portmap_getport() changes require that the protocol is set -in oder to function. ---- - lib/rpc_subs.c | 2 ++ - 1 file changed, 2 insertions(+) - -diff --git a/lib/rpc_subs.c b/lib/rpc_subs.c -index cfb63d2..7c99ea8 100644 ---- a/lib/rpc_subs.c -+++ b/lib/rpc_subs.c -@@ -877,6 +877,8 @@ int rpc_portmap_getport(struct conn_info *info, - - memset(&pmap_info, 0, sizeof(struct conn_info)); - -+ pmap_info.proto = proto; -+ - if (proto == IPPROTO_TCP) - pmap_info.timeout.tv_sec = PMAP_TOUT_TCP; - else diff --git a/autofs-5.0.8-fix-ipv6-libtirpc-getport.patch b/autofs-5.0.8-fix-ipv6-libtirpc-getport.patch deleted file mode 100644 index eee6c5c..0000000 --- a/autofs-5.0.8-fix-ipv6-libtirpc-getport.patch +++ /dev/null @@ -1,345 +0,0 @@ -autofs-5.0.8 - fix ipv6 libtirpc getport - -From: Ian Kent - -The method that was being used to obtain a service port number -when using libtirpc was wrong. ---- - CHANGELOG | 1 - lib/rpc_subs.c | 283 +++++++++++++++++++++++++++++++++++++++++++++++++++++--- - 2 files changed, 267 insertions(+), 17 deletions(-) - -diff --git a/CHANGELOG b/CHANGELOG -index 68db340..9c87373 100644 ---- a/CHANGELOG -+++ b/CHANGELOG -@@ -5,6 +5,7 @@ - - fix task manager not getting signaled. - - allow --with-systemd to take a path arg. - - fix WITH_LIBTIRPC function name. -+- fix ipv6 libtirpc getport. - - 17/10/2013 autofs-5.0.8 - ======================= -diff --git a/lib/rpc_subs.c b/lib/rpc_subs.c -index 46b3e8d..2365b6e 100644 ---- a/lib/rpc_subs.c -+++ b/lib/rpc_subs.c -@@ -234,6 +234,28 @@ static int rpc_do_create_client(struct sockaddr *addr, struct conn_info *info, i - - return 0; - } -+static int rpc_getport(struct conn_info *info, -+ struct pmap *parms, CLIENT *client) -+{ -+ enum clnt_stat status; -+ -+ /* -+ * Check to see if server is up otherwise a getport will take -+ * forever to timeout. -+ */ -+ status = clnt_call(client, PMAPPROC_NULL, -+ (xdrproc_t) xdr_void, 0, (xdrproc_t) xdr_void, 0, -+ info->timeout); -+ -+ if (status == RPC_SUCCESS) { -+ status = clnt_call(client, PMAPPROC_GETPORT, -+ (xdrproc_t) xdr_pmap, (caddr_t) parms, -+ (xdrproc_t) xdr_u_short, (caddr_t) port, -+ info->timeout); -+ } -+ -+ return status; -+} - #else - static int rpc_do_create_client(struct sockaddr *addr, struct conn_info *info, int *fd, CLIENT **client) - { -@@ -267,9 +289,6 @@ static int rpc_do_create_client(struct sockaddr *addr, struct conn_info *info, i - laddr = (struct sockaddr *) &in4_laddr; - in4_raddr->sin_port = htons(info->port); - slen = sizeof(struct sockaddr_in); -- /* Use rpcbind v2 for AF_INET */ -- if (info->program == rpcb_prog) -- info->version = PMAPVERS; - } else if (addr->sa_family == AF_INET6) { - struct sockaddr_in6 *in6_raddr = (struct sockaddr_in6 *) addr; - in6_laddr.sin6_family = AF_INET6; -@@ -324,6 +343,244 @@ static int rpc_do_create_client(struct sockaddr *addr, struct conn_info *info, i - - return 0; - } -+ -+/* -+ * Thankfully nfs-utils had already dealt with this. -+ * Thanks to Chuck Lever for his nfs-utils patch series, much of -+ * which is used here. -+ */ -+static pthread_mutex_t proto_mutex = PTHREAD_MUTEX_INITIALIZER; -+ -+static enum clnt_stat rpc_get_netid(const sa_family_t family, -+ const int protocol, char **netid) -+{ -+ char *nc_protofmly, *nc_proto, *nc_netid; -+ struct netconfig *nconf; -+ struct protoent *proto; -+ void *handle; -+ -+ switch (family) { -+ case AF_LOCAL: -+ case AF_INET: -+ nc_protofmly = NC_INET; -+ break; -+ case AF_INET6: -+ nc_protofmly = NC_INET6; -+ break; -+ default: -+ return RPC_UNKNOWNPROTO; -+ } -+ -+ pthread_mutex_lock(&proto_mutex); -+ proto = getprotobynumber(protocol); -+ if (!proto) { -+ pthread_mutex_unlock(&proto_mutex); -+ return RPC_UNKNOWNPROTO; -+ } -+ nc_proto = strdup(proto->p_name); -+ pthread_mutex_unlock(&proto_mutex); -+ if (!nc_proto) -+ return RPC_SYSTEMERROR; -+ -+ handle = setnetconfig(); -+ while ((nconf = getnetconfig(handle)) != NULL) { -+ if (nconf->nc_protofmly != NULL && -+ strcmp(nconf->nc_protofmly, nc_protofmly) != 0) -+ continue; -+ if (nconf->nc_proto != NULL && -+ strcmp(nconf->nc_proto, nc_proto) != 0) -+ continue; -+ -+ nc_netid = strdup(nconf->nc_netid); -+ if (!nc_netid) { -+ free(nc_proto); -+ return RPC_SYSTEMERROR; -+ } -+ -+ *netid = nc_netid; -+ } -+ endnetconfig(handle); -+ free(nc_proto); -+ -+ return RPC_SUCCESS; -+} -+ -+static char *rpc_sockaddr2universal(const struct sockaddr *addr) -+{ -+ const struct sockaddr_in6 *sin6 = (const struct sockaddr_in6 *) addr; -+ const struct sockaddr_un *sun = (const struct sockaddr_un *) addr; -+ const struct sockaddr_in *sin = (const struct sockaddr_in *) addr; -+ char buf[INET6_ADDRSTRLEN + 8 /* for port information */]; -+ uint16_t port; -+ size_t count; -+ char *result; -+ int len; -+ -+ switch (addr->sa_family) { -+ case AF_LOCAL: -+ return strndup(sun->sun_path, sizeof(sun->sun_path)); -+ case AF_INET: -+ if (inet_ntop(AF_INET, (const void *)&sin->sin_addr.s_addr, -+ buf, (socklen_t)sizeof(buf)) == NULL) -+ goto out_err; -+ port = ntohs(sin->sin_port); -+ break; -+ case AF_INET6: -+ if (inet_ntop(AF_INET6, (const void *)&sin6->sin6_addr, -+ buf, (socklen_t)sizeof(buf)) == NULL) -+ goto out_err; -+ port = ntohs(sin6->sin6_port); -+ break; -+ default: -+ goto out_err; -+ } -+ -+ count = sizeof(buf) - strlen(buf); -+ len = snprintf(buf + strlen(buf), count, ".%u.%u", -+ (unsigned)(port >> 8), (unsigned)(port & 0xff)); -+ /* before glibc 2.0.6, snprintf(3) could return -1 */ -+ if (len < 0 || (size_t)len > count) -+ goto out_err; -+ -+ result = strdup(buf); -+ return result; -+ -+out_err: -+ return NULL; -+} -+ -+static int rpc_universal2port(const char *uaddr) -+{ -+ char *addrstr; -+ char *p, *endptr; -+ unsigned long portlo, porthi; -+ int port = -1; -+ -+ addrstr = strdup(uaddr); -+ if (!addrstr) -+ return -1; -+ -+ p = strrchr(addrstr, '.'); -+ if (!p) -+ goto out; -+ -+ portlo = strtoul(p + 1, &endptr, 10); -+ if (*endptr != '\0' || portlo > 255) -+ goto out; -+ *p = '\0'; -+ -+ p = strrchr(addrstr, '.'); -+ if (!p) -+ goto out; -+ -+ porthi = strtoul(p + 1, &endptr, 10); -+ if (*endptr != '\0' || porthi > 255) -+ goto out; -+ *p = '\0'; -+ -+ port = (porthi << 8) | portlo; -+ -+out: -+ free(addrstr); -+ return port; -+} -+ -+static enum clnt_stat rpc_rpcb_getport(CLIENT *client, -+ struct rpcb *parms, -+ struct timeval timeout, -+ unsigned short *port) -+{ -+ rpcvers_t rpcb_version; -+ struct rpc_err rpcerr; -+ int s_port = 0; -+ -+ for (rpcb_version = RPCBVERS_4; -+ rpcb_version >= RPCBVERS_3; -+ rpcb_version--) { -+ enum clnt_stat status; -+ char *uaddr = NULL; -+ -+ CLNT_CONTROL(client, CLSET_VERS, (void *) &rpcb_version); -+ status = CLNT_CALL(client, (rpcproc_t) RPCBPROC_GETADDR, -+ (xdrproc_t) xdr_rpcb, (void *) parms, -+ (xdrproc_t) xdr_wrapstring, (void *) &uaddr, -+ timeout); -+ -+ switch (status) { -+ case RPC_SUCCESS: -+ if ((uaddr == NULL) || (uaddr[0] == '\0')) -+ return RPC_PROGNOTREGISTERED; -+ -+ s_port = rpc_universal2port(uaddr); -+ xdr_free((xdrproc_t) xdr_wrapstring, (char *) &uaddr); -+ if (s_port == -1) { -+ return RPC_N2AXLATEFAILURE; -+ } -+ *port = s_port; -+ return RPC_SUCCESS; -+ -+ case RPC_PROGVERSMISMATCH: -+ clnt_geterr(client, &rpcerr); -+ if (rpcerr.re_vers.low > RPCBVERS4) -+ return status; -+ continue; -+ case RPC_PROCUNAVAIL: -+ case RPC_PROGUNAVAIL: -+ continue; -+ default: -+ /* Most likely RPC_TIMEDOUT or RPC_CANTRECV */ -+ return status; -+ } -+ } -+ -+ if (s_port == 0) -+ return RPC_PROGNOTREGISTERED; -+ -+ return RPC_PROCUNAVAIL; -+} -+ -+static enum clnt_stat rpc_getport(struct conn_info *info, -+ struct pmap *parms, CLIENT *client, -+ unsigned short *port) -+{ -+ enum clnt_stat status; -+ struct sockaddr *paddr, addr; -+ struct rpcb rpcb_parms; -+ char *netid, *raddr; -+ -+ if (info->addr) -+ paddr = info->addr; -+ else { -+ if (!clnt_control(client, CLGET_SERVER_ADDR, (char *) &addr)) -+ return RPC_UNKNOWNADDR; -+ paddr = &addr; -+ } -+ -+ netid = NULL; -+ status = rpc_get_netid(paddr->sa_family, info->proto, &netid); -+ if (status != RPC_SUCCESS) -+ return status; -+ -+ raddr = rpc_sockaddr2universal(paddr); -+ if (!raddr) { -+ free(netid); -+ return RPC_UNKNOWNADDR; -+ } -+ -+ memset(&rpcb_parms, 0, sizeof(rpcb_parms)); -+ rpcb_parms.r_prog = parms->pm_prog; -+ rpcb_parms.r_vers = parms->pm_vers; -+ rpcb_parms.r_netid = netid; -+ rpcb_parms.r_addr = raddr; -+ rpcb_parms.r_owner = ""; -+ -+ status = rpc_rpcb_getport(client, &rpcb_parms, info->timeout, port); -+ -+ free(netid); -+ free(raddr); -+ -+ return status; -+} - #endif - - #if defined(HAVE_GETRPCBYNAME) || defined(HAVE_GETSERVBYNAME) -@@ -647,20 +904,7 @@ int rpc_portmap_getport(struct conn_info *info, - return ret; - } - -- /* -- * Check to see if server is up otherwise a getport will take -- * forever to timeout. -- */ -- status = clnt_call(client, PMAPPROC_NULL, -- (xdrproc_t) xdr_void, 0, (xdrproc_t) xdr_void, 0, -- pmap_info.timeout); -- -- if (status == RPC_SUCCESS) { -- status = clnt_call(client, PMAPPROC_GETPORT, -- (xdrproc_t) xdr_pmap, (caddr_t) parms, -- (xdrproc_t) xdr_u_short, (caddr_t) port, -- pmap_info.timeout); -- } -+ status = rpc_getport(&pmap_info, parms, client, port); - - if (!info->client) { - /* -@@ -867,6 +1111,11 @@ static int rpc_get_exports_proto(struct conn_info *info, exports *exp) - clnt_control(client, CLSET_RETRY_TIMEOUT, (char *) &info->timeout); - - client->cl_auth = authunix_create_default(); -+ if (client->cl_auth == NULL) { -+ error(LOGOPT_ANY, "auth create failed"); -+ clnt_destroy(client); -+ return 0; -+ } - - vers_entry = 0; - while (1) { diff --git a/autofs-5.0.8-fix-ipv6-link-local-address-handling.patch b/autofs-5.0.8-fix-ipv6-link-local-address-handling.patch deleted file mode 100644 index d04158c..0000000 --- a/autofs-5.0.8-fix-ipv6-link-local-address-handling.patch +++ /dev/null @@ -1,41 +0,0 @@ -autofs-5.0.8 - fix ipv6 link local address handling - -From: Ian Kent - -Stop the validate_location() function from choking on link local -ipv6 addresses. ---- - lib/rpc_subs.c | 6 ++++++ - modules/parse_sun.c | 2 +- - 2 files changed, 7 insertions(+), 1 deletion(-) - -diff --git a/lib/rpc_subs.c b/lib/rpc_subs.c -index 2365b6e..9d5b2f5 100644 ---- a/lib/rpc_subs.c -+++ b/lib/rpc_subs.c -@@ -669,6 +669,12 @@ static int create_client(struct conn_info *info, CLIENT **client) - goto done; - if (ret == -EHOSTUNREACH) - goto out_close; -+ if (ret == -EINVAL) { -+ char buf[MAX_ERR_BUF]; -+ char *estr = strerror_r(-ret, buf, MAX_ERR_BUF); -+ error(LOGOPT_ANY, "connect() failed: %s", estr); -+ goto out_close; -+ } - - if (!info->client && fd != RPC_ANYSOCK) { - close(fd); -diff --git a/modules/parse_sun.c b/modules/parse_sun.c -index 30820b5..e5a4def 100644 ---- a/modules/parse_sun.c -+++ b/modules/parse_sun.c -@@ -862,7 +862,7 @@ static int validate_location(unsigned int logopt, char *loc) - *ptr == '-' || *ptr == '.' || *ptr == '_' || - *ptr == ',' || *ptr == '(' || *ptr == ')' || - *ptr == '#' || *ptr == '@' || *ptr == ':' || -- *ptr == '[' || *ptr == ']')) { -+ *ptr == '[' || *ptr == ']' || *ptr == '%')) { - error(logopt, "invalid character \"%c\" " - "found in location %s", *ptr, loc); - return 0; diff --git a/autofs-5.0.8-fix-master-map-type-check.patch b/autofs-5.0.8-fix-master-map-type-check.patch deleted file mode 100644 index 5d96325..0000000 --- a/autofs-5.0.8-fix-master-map-type-check.patch +++ /dev/null @@ -1,58 +0,0 @@ -autofs-5.0.8 - fix master map type check - -From: Ian Kent - -Map type has format [,] but the master map type check -for old style map syntax doesn't allow for . ---- - CHANGELOG | 1 + - daemon/lookup.c | 24 ++++++++++++++++-------- - 2 files changed, 17 insertions(+), 8 deletions(-) - -diff --git a/CHANGELOG b/CHANGELOG -index a45ca6a..fb2f2d6 100644 ---- a/CHANGELOG -+++ b/CHANGELOG -@@ -1,6 +1,7 @@ - ??/??/20?? autofs-5.0.9 - ======================= - - fix undefined authtype_requires_creds err if ldap enabled but without sasl. -+- fix master map type check. - - 17/10/2013 autofs-5.0.8 - ======================= -diff --git a/daemon/lookup.c b/daemon/lookup.c -index e3d9536..7fea942 100644 ---- a/daemon/lookup.c -+++ b/daemon/lookup.c -@@ -171,14 +171,22 @@ int lookup_nss_read_master(struct master *master, time_t age) - char source[10]; - - memset(source, 0, 10); -- if (!strncmp(name, "file:", 5) || -- !strncmp(name, "yp:", 3) || -- !strncmp(name, "nis:", 4) || -- !strncmp(name, "nisplus:", 8) || -- !strncmp(name, "ldap:", 5) || -- !strncmp(name, "ldaps:", 6) || -- !strncmp(name, "sss:", 4) || -- !strncmp(name, "dir:", 4)) { -+ if ((!strncmp(name, "file", 4) && -+ (name[4] == ',' || name[4] == ':')) || -+ (!strncmp(name, "yp", 3) && -+ (name[3] == ',' || name[3] == ':')) || -+ (!strncmp(name, "nis", 3) && -+ (name[3] == ',' || name[3] == ':')) || -+ (!strncmp(name, "nisplus", 7) && -+ (name[7] == ',' || name[7] == ':')) || -+ (!strncmp(name, "ldap", 4) && -+ (name[4] == ',' || name[4] == ':')) || -+ (!strncmp(name, "ldaps", 5) && -+ (name[5] == ',' || name[5] == ':')) || -+ (!strncmp(name, "sss", 3) || -+ (name[3] == ',' || name[3] == ':')) || -+ (!strncmp(name, "dir", 3) && -+ (name[3] == ',' || name[3] == ':'))) { - strncpy(source, name, tmp - name); - - /* diff --git a/autofs-5.0.8-fix-portmap-not-trying-proto-v2.patch b/autofs-5.0.8-fix-portmap-not-trying-proto-v2.patch deleted file mode 100644 index 73b7b6b..0000000 --- a/autofs-5.0.8-fix-portmap-not-trying-proto-v2.patch +++ /dev/null @@ -1,59 +0,0 @@ -autofs-5.0.8 - fix portmap not trying proto v2 - -From: Ian Kent - -The latest change to fix a problem with getting an exports list -from a server doesn't try portmap version 2 when trying to get -a service port number. This causes servers that offer only -version 2 to not be able to provide a service port number. ---- - CHANGELOG | 1 + - lib/rpc_subs.c | 17 ++++++++++++++++- - 2 files changed, 17 insertions(+), 1 deletion(-) - ---- autofs-5.0.8.orig/CHANGELOG -+++ autofs-5.0.8/CHANGELOG -@@ -6,6 +6,7 @@ - - allow --with-systemd to take a path arg. - - fix WITH_LIBTIRPC function name. - - fix ipv6 libtirpc getport. -+- fix protmap not trying proto v2. - - 17/10/2013 autofs-5.0.8 - ======================= ---- autofs-5.0.8.orig/lib/rpc_subs.c -+++ autofs-5.0.8/lib/rpc_subs.c -@@ -524,10 +524,15 @@ static enum clnt_stat rpc_rpcb_getport(C - if (rpcerr.re_vers.low > RPCBVERS4) - return status; - continue; -+ - case RPC_PROGUNAVAIL: - continue; -+ -+ case RPC_PROGNOTREGISTERED: -+ continue; -+ - default: -- /* Most likely RPC_TIMEDOUT or RPC_CANTRECV */ -+ /* Most likely RPC_TIMEDOUT or RPC_CANTRECV */ - return status; - } - } -@@ -575,6 +580,16 @@ static enum clnt_stat rpc_getport(struct - free(netid); - free(raddr); - -+ if (status == RPC_PROGNOTREGISTERED) { -+ /* Last chance, version 2 uses a different procedure */ -+ rpcvers_t rpcb_version = PMAPVERS; -+ CLNT_CONTROL(client, CLSET_VERS, (void *) &rpcb_version); -+ status = clnt_call(client, PMAPPROC_GETPORT, -+ (xdrproc_t) xdr_pmap, (caddr_t) parms, -+ (xdrproc_t) xdr_u_short, (caddr_t) port, -+ info->timeout); -+ } -+ - return status; - } - #endif diff --git a/autofs-5.0.8-fix-task-manager-not-getting-signaled.patch b/autofs-5.0.8-fix-task-manager-not-getting-signaled.patch deleted file mode 100644 index d189820..0000000 --- a/autofs-5.0.8-fix-task-manager-not-getting-signaled.patch +++ /dev/null @@ -1,47 +0,0 @@ -autofs-5.0.8 - fix task manager not getting signaled - -From: Ian Kent - -If a task is added and the task list isn't empty and in progress -tasks depend on the new task completion the task manager doesn't -get signaled. ---- - CHANGELOG | 1 + - daemon/state.c | 10 +++++----- - 2 files changed, 6 insertions(+), 5 deletions(-) - -diff --git a/CHANGELOG b/CHANGELOG -index fb2f2d6..a01393c 100644 ---- a/CHANGELOG -+++ b/CHANGELOG -@@ -2,6 +2,7 @@ - ======================= - - fix undefined authtype_requires_creds err if ldap enabled but without sasl. - - fix master map type check. -+- fix task manager not getting signaled. - - 17/10/2013 autofs-5.0.8 - ======================= -diff --git a/daemon/state.c b/daemon/state.c -index 8d81788..3174a9c 100644 ---- a/daemon/state.c -+++ b/daemon/state.c -@@ -818,13 +818,13 @@ done: - new = st_alloc_task(ap, state); - if (new) - list_add(&new->list, head); -- /* Added to empty state queue, kick state machine */ -- signaled = 1; -- status = pthread_cond_signal(&cond); -- if (status) -- fatal(status); - } - -+ signaled = 1; -+ status = pthread_cond_signal(&cond); -+ if (status) -+ fatal(status); -+ - return 1; - } - diff --git a/autofs-5.0.8-fix-undefined-authtype_requires_creds-err-if-ldap-en.patch b/autofs-5.0.8-fix-undefined-authtype_requires_creds-err-if-ldap-en.patch deleted file mode 100644 index bf50ab9..0000000 --- a/autofs-5.0.8-fix-undefined-authtype_requires_creds-err-if-ldap-en.patch +++ /dev/null @@ -1,52 +0,0 @@ -autofs-5.0.8 - fix undefined authtype_requires_creds err if ldap enabled but without sasl - -From: Lan Yixun (dlan) - -This patch is moving "WITH_SASL" into authtype_requires_creds function -make it return 0 if sasl not enabled, which mean authtype_requires_creds is not enabled - -https://bugs.gentoo.org/show_bug.cgi?id=489128 ---- - CHANGELOG | 4 ++++ - modules/lookup_ldap.c | 4 ++-- - 2 files changed, 6 insertions(+), 2 deletions(-) - -diff --git a/CHANGELOG b/CHANGELOG -index 62dac81..a45ca6a 100644 ---- a/CHANGELOG -+++ b/CHANGELOG -@@ -1,3 +1,7 @@ -+??/??/20?? autofs-5.0.9 -+======================= -+- fix undefined authtype_requires_creds err if ldap enabled but without sasl. -+ - 17/10/2013 autofs-5.0.8 - ======================= - - fix nobind sun escaped map entries. -diff --git a/modules/lookup_ldap.c b/modules/lookup_ldap.c -index 2ab1e8c..04b1da7 100644 ---- a/modules/lookup_ldap.c -+++ b/modules/lookup_ldap.c -@@ -846,20 +846,20 @@ int get_property(unsigned logopt, xmlNodePtr node, const char *prop, char **valu - return 0; - } - --#ifdef WITH_SASL - /* - * For plain text, login and digest-md5 authentication types, we need - * user and password credentials. - */ - int authtype_requires_creds(const char *authtype) - { -+#ifdef WITH_SASL - if (!strncmp(authtype, "PLAIN", strlen("PLAIN")) || - !strncmp(authtype, "DIGEST-MD5", strlen("DIGEST-MD5")) || - !strncmp(authtype, "LOGIN", strlen("LOGIN"))) - return 1; -+#endif - return 0; - } --#endif - - /* - * Returns: diff --git a/autofs-5.0.8-get_nfs_info-should-query-portmapper-if-port-is-not-given.patch b/autofs-5.0.8-get_nfs_info-should-query-portmapper-if-port-is-not-given.patch deleted file mode 100644 index 8b8a7f2..0000000 --- a/autofs-5.0.8-get_nfs_info-should-query-portmapper-if-port-is-not-given.patch +++ /dev/null @@ -1,31 +0,0 @@ -autofs-5.0.8 - get_nfs_info() should query portmapper if port is not given - -From: Scott Mayhew - -It shouldn't just assume it can use port 2049. - -Signed-off-by: Scott Mayhew ---- - modules/replicated.c | 9 ++++++--- - 1 file changed, 6 insertions(+), 3 deletions(-) - -diff --git a/modules/replicated.c b/modules/replicated.c -index 5fdd9d9..2463235 100644 ---- a/modules/replicated.c -+++ b/modules/replicated.c -@@ -444,9 +444,12 @@ static unsigned int get_nfs_info(unsigned logopt, struct host *host, - host->name, proto, version); - - rpc_info->proto = proto; -- if (port < 0) -- rpc_info->port = NFS_PORT; -- else if (port > 0) -+ if (port < 0) { -+ if (version & NFS4_REQUESTED) -+ rpc_info->port = NFS_PORT; -+ else -+ port = 0; -+ } else if (port > 0) - rpc_info->port = port; - - memset(&parms, 0, sizeof(struct pmap)); diff --git a/autofs-5.0.9-check-for-non-existent-negative-entries-in-lookup_ghost.patch b/autofs-5.0.9-check-for-non-existent-negative-entries-in-lookup_ghost.patch deleted file mode 100644 index f313140..0000000 --- a/autofs-5.0.9-check-for-non-existent-negative-entries-in-lookup_ghost.patch +++ /dev/null @@ -1,64 +0,0 @@ -autofs-5.0.9 - check for non existent negative entries in lookup_ghost() - -From: Ian Kent - -Map entries that have been created in the cache due to a negative lookup -but don't exist in the map source shouldn't have directories created. - -This can be detected by checking me->status. - -For negative entries that are present in the map source me->status will -have been set to 0 in lookup_prune_one_cache() and negavive entries that -have been created in the same second as the map read will always have -me->status > 0 and so will also be skipped by lookup_ghost(). ---- - CHANGELOG | 1 + - daemon/lookup.c | 16 +++++++++++++++- - 2 files changed, 16 insertions(+), 1 deletion(-) - -diff --git a/CHANGELOG b/CHANGELOG -index 8c1da44..113dfb8 100644 ---- a/CHANGELOG -+++ b/CHANGELOG -@@ -7,6 +7,7 @@ - - amd lookup update lookup hesiod to handle amd keys - - inadvertantly drop from initial series. - - fix wildcard key lookup. -+- check for non existent negative entries in lookup_ghost(). - - 28/03/2014 autofs-5.0.9 - ======================= -diff --git a/daemon/lookup.c b/daemon/lookup.c -index 999be9d..b4cdcce 100644 ---- a/daemon/lookup.c -+++ b/daemon/lookup.c -@@ -716,6 +716,17 @@ int lookup_ghost(struct autofs_point *ap, const char *root) - cache_readlock(mc); - me = cache_enumerate(mc, NULL); - while (me) { -+ /* -+ * Map entries that have been created in the cache -+ * due to a negative lookup but don't exist in the -+ * map source shouldn't have directories created. -+ * me->status of negative entries that are present -+ * in the map source will have me->status set to 0 -+ * in lookup_prune_one_cache(). -+ */ -+ if (me->status && !me->mapent) -+ goto next; -+ - if (!strcmp(me->key, "*")) - goto next; - -@@ -1339,7 +1350,10 @@ void lookup_prune_one_cache(struct autofs_point *ap, struct mapent_cache *mc, ti - - if (valid) - cache_delete(mc, key); -- else if (!is_mounted(_PROC_MOUNTS, path, MNTS_AUTOFS)) { -+ else if (this->status) { -+ cache_unlock(mc); -+ goto next; -+ } else if (!is_mounted(_PROC_MOUNTS, path, MNTS_AUTOFS)) { - dev_t devid = ap->dev; - status = CHE_FAIL; - if (ap->type == LKP_DIRECT) diff --git a/autofs-5.0.9-fix-race-accessing-qdn-in-get_query_dn.patch b/autofs-5.0.9-fix-race-accessing-qdn-in-get_query_dn.patch new file mode 100644 index 0000000..6cdf18f --- /dev/null +++ b/autofs-5.0.9-fix-race-accessing-qdn-in-get_query_dn.patch @@ -0,0 +1,52 @@ +autofs-5.0.9 - fix race accessing qdn in get_query_dn() + +From: Ian Kent + +Fix a couple of obvious problems in get_query_dn(). + +First, check dn is not NULL before attempting to duplicate it. +And also protect the update of qdn in the context by a mutex. +--- + CHANGELOG | 1 + + modules/lookup_ldap.c | 9 ++++++--- + 2 files changed, 7 insertions(+), 3 deletions(-) + +diff --git a/CHANGELOG b/CHANGELOG +index 1b4e2fe..e911682 100644 +--- a/CHANGELOG ++++ b/CHANGELOG +@@ -4,6 +4,7 @@ + - add serialization to sasl init. + - dont allocate dev_ctl_ops too early. + - fix incorrect round robin host detection. ++- fix race accessing qdn in get_query_dn(). + + 04/06/2014 autofs-5.1.0 + ======================= +diff --git a/modules/lookup_ldap.c b/modules/lookup_ldap.c +index aca3e05..5c16063 100644 +--- a/modules/lookup_ldap.c ++++ b/modules/lookup_ldap.c +@@ -461,16 +461,19 @@ static int get_query_dn(unsigned logopt, LDAP *ldap, struct lookup_context *ctxt + } + + free(query); +- qdn = strdup(dn); +- ldap_memfree(dn); ++ if (dn) { ++ qdn = strdup(dn); ++ ldap_memfree(dn); ++ } + ldap_msgfree(result); + if (!qdn) + return 0; + ++ uris_mutex_lock(ctxt); + if (ctxt->qdn) + free(ctxt->qdn); +- + ctxt->qdn = qdn; ++ uris_mutex_unlock(ctxt); + + return 1; + } diff --git a/autofs-5.1.0-add-return-check-in-ldap-check_map_indirect.patch b/autofs-5.1.0-add-return-check-in-ldap-check_map_indirect.patch new file mode 100644 index 0000000..14f766e --- /dev/null +++ b/autofs-5.1.0-add-return-check-in-ldap-check_map_indirect.patch @@ -0,0 +1,72 @@ +autofs-5.1.0 - add return check in ldap check_map_indirect() + +From: Ian Kent + +Fix not checking return from pthread_mutex_lock/pthread_mutex_unlock in +modules/lookup_ldap.c:check_map_indirect(). +--- + CHANGELOG | 1 + + modules/lookup_ldap.c | 17 +++++++++++++---- + 2 files changed, 14 insertions(+), 4 deletions(-) + +diff --git a/CHANGELOG b/CHANGELOG +index dfbaeb1..d7d161f 100644 +--- a/CHANGELOG ++++ b/CHANGELOG +@@ -14,6 +14,7 @@ + - fix leak in get_network_proximity(). + - fix buffer size checks in merge_options(). + - check amd lex buffer len before copy. ++- add return check in ldap check_map_indirect(). + + 04/06/2014 autofs-5.1.0 + ======================= +diff --git a/modules/lookup_ldap.c b/modules/lookup_ldap.c +index 5c16063..ac2ef30 100644 +--- a/modules/lookup_ldap.c ++++ b/modules/lookup_ldap.c +@@ -3420,12 +3420,15 @@ static int check_map_indirect(struct autofs_point *ap, + time_t now = time(NULL); + time_t t_last_read; + int ret, cur_state; ++ int status; + + mc = source->mc; + + pthread_setcancelstate(PTHREAD_CANCEL_DISABLE, &cur_state); + +- pthread_mutex_lock(&ap->entry->current_mutex); ++ status = pthread_mutex_lock(&ap->entry->current_mutex); ++ if (status) ++ fatal(status); + if (is_amd_format) { + unsigned long timestamp = get_amd_timestamp(ctxt); + if (timestamp > ctxt->timestamp) { +@@ -3445,7 +3448,9 @@ static int check_map_indirect(struct autofs_point *ap, + ctxt->check_defaults = 0; + } + } +- pthread_mutex_unlock(&ap->entry->current_mutex); ++ status = pthread_mutex_unlock(&ap->entry->current_mutex); ++ if (status) ++ fatal(status); + + ret = match_key(ap, source, key, key_len, ctxt); + if (ret == CHE_FAIL) { +@@ -3490,10 +3495,14 @@ static int check_map_indirect(struct autofs_point *ap, + } + cache_unlock(mc); + +- pthread_mutex_lock(&ap->entry->current_mutex); ++ status = pthread_mutex_lock(&ap->entry->current_mutex); ++ if (status) ++ fatal(status); + if (t_last_read > ap->exp_runfreq && ret & CHE_UPDATED) + source->stale = 1; +- pthread_mutex_unlock(&ap->entry->current_mutex); ++ status = pthread_mutex_unlock(&ap->entry->current_mutex); ++ if (status) ++ fatal(status); + } + + cache_readlock(mc); diff --git a/autofs-5.1.0-add-serialization-to-sasl-init.patch b/autofs-5.1.0-add-serialization-to-sasl-init.patch new file mode 100644 index 0000000..f2607a5 --- /dev/null +++ b/autofs-5.1.0-add-serialization-to-sasl-init.patch @@ -0,0 +1,96 @@ +autofs-5.1.0 - add serialization to sasl init + +From: Ian Kent + +Attempt to resolve crash in sasl initialization. We know that the +initial connection calls to connect to an LDAP server are not +thread safe and it looks like the sasl code doesn't take that into +consideration so adding serialization with a mutex is probably a +sensible thing to do. +--- + CHANGELOG | 1 + + modules/lookup_ldap.c | 13 +++++++++++++ + 2 files changed, 14 insertions(+) + +diff --git a/CHANGELOG b/CHANGELOG +index 58b94dc..92ee83b 100644 +--- a/CHANGELOG ++++ b/CHANGELOG +@@ -1,6 +1,7 @@ + ??/??/2014 autofs-5.1.1 + ======================= + - fix compile error in defaults.c. ++- add serialization to sasl init. + + 04/06/2014 autofs-5.1.0 + ======================= +diff --git a/modules/lookup_ldap.c b/modules/lookup_ldap.c +index 8091ed2..aca3e05 100644 +--- a/modules/lookup_ldap.c ++++ b/modules/lookup_ldap.c +@@ -578,7 +578,9 @@ static int do_bind(unsigned logopt, LDAP *ldap, const char *uri, struct lookup_c + ctxt->auth_required, ctxt->sasl_mech); + + if (ctxt->auth_required & LDAP_NEED_AUTH) { ++ ldapinit_mutex_lock(); + rv = autofs_sasl_bind(logopt, ldap, ctxt); ++ ldapinit_mutex_unlock(); + debug(logopt, MODPREFIX "autofs_sasl_bind returned %d", rv); + } else { + rv = bind_ldap_simple(logopt, ldap, uri, ctxt); +@@ -922,7 +924,9 @@ static LDAP *do_reconnect(unsigned logopt, struct lookup_context *ctxt) + #ifdef WITH_SASL + /* Dispose of the sasl authentication connection and try again. */ + if (!ldap && ctxt->auth_required & LDAP_NEED_AUTH) { ++ ldapinit_mutex_lock(); + autofs_sasl_dispose(ctxt); ++ ldapinit_mutex_unlock(); + ldap = connect_to_server(logopt, ctxt->server, ctxt); + } + #endif +@@ -958,7 +962,9 @@ static LDAP *do_reconnect(unsigned logopt, struct lookup_context *ctxt) + * current server again before trying other servers in the list. + */ + if (!ldap && ctxt->auth_required & LDAP_NEED_AUTH) { ++ ldapinit_mutex_lock(); + autofs_sasl_dispose(ctxt); ++ ldapinit_mutex_unlock(); + ldap = connect_to_server(logopt, ctxt->uri->uri, ctxt); + } + #endif +@@ -969,7 +975,9 @@ static LDAP *do_reconnect(unsigned logopt, struct lookup_context *ctxt) + + find_server: + #ifdef WITH_SASL ++ ldapinit_mutex_lock(); + autofs_sasl_dispose(ctxt); ++ ldapinit_mutex_unlock(); + #endif + + /* Current server failed, try the rest or dc connection */ +@@ -1742,11 +1750,14 @@ int lookup_init(const char *mapfmt, int argc, const char *const *argv, void **co + + #ifdef WITH_SASL + /* Init the sasl callbacks */ ++ ldapinit_mutex_lock(); + if (!autofs_sasl_client_init(LOGOPT_NONE)) { + error(LOGOPT_ANY, "failed to init sasl client"); ++ ldapinit_mutex_unlock(); + free_context(ctxt); + return 1; + } ++ ldapinit_mutex_unlock(); + #endif + + if (is_amd_format) +@@ -3678,8 +3689,10 @@ int lookup_done(void *context) + struct lookup_context *ctxt = (struct lookup_context *) context; + int rv = close_parse(ctxt->parse); + #ifdef WITH_SASL ++ ldapinit_mutex_lock(); + autofs_sasl_dispose(ctxt); + autofs_sasl_done(); ++ ldapinit_mutex_unlock(); + #endif + free_context(ctxt); + return rv; diff --git a/autofs-5.1.0-beta1-fix-wildcard-key-lookup.patch b/autofs-5.1.0-beta1-fix-wildcard-key-lookup.patch deleted file mode 100644 index 3b50780..0000000 --- a/autofs-5.1.0-beta1-fix-wildcard-key-lookup.patch +++ /dev/null @@ -1,170 +0,0 @@ -autofs-5.1.0-beta1 - fix wildcard key lookup - -From: Ian Kent - -The changes to key matching caused wildcard key lookups for autofs -format maps to fail. ---- - CHANGELOG | 1 + - modules/lookup_ldap.c | 10 ++++------ - modules/lookup_nisplus.c | 11 +++++------ - modules/lookup_program.c | 4 ++-- - modules/lookup_yp.c | 6 ++---- - 5 files changed, 14 insertions(+), 18 deletions(-) - -diff --git a/CHANGELOG b/CHANGELOG -index f44f6f5..8c1da44 100644 ---- a/CHANGELOG -+++ b/CHANGELOG -@@ -6,6 +6,7 @@ - - inadvertantly drop from initial series. - - amd lookup update lookup hesiod to handle amd keys - - inadvertantly drop from initial series. -+- fix wildcard key lookup. - - 28/03/2014 autofs-5.0.9 - ======================= -diff --git a/modules/lookup_ldap.c b/modules/lookup_ldap.c -index 833cb86..dac346c 100644 ---- a/modules/lookup_ldap.c -+++ b/modules/lookup_ldap.c -@@ -3349,12 +3349,9 @@ static int match_key(struct autofs_point *ap, - else - ret = lookup_one(ap, source, key, key_len, ctxt); - -- if (ret == CHE_OK || ret == CHE_UPDATED) -+ if (ret == CHE_OK || ret == CHE_UPDATED || !is_amd_format) - return ret; - -- if (!is_amd_format) -- return CHE_FAIL; -- - lkp_key = strdup(key); - if (!lkp_key) { - char *estr = strerror_r(errno, buf, MAX_ERR_BUF); -@@ -3399,6 +3396,7 @@ static int check_map_indirect(struct autofs_point *ap, - char *key, int key_len, - struct lookup_context *ctxt) - { -+ unsigned int is_amd_format = source->flags & MAP_FLAG_FORMAT_AMD; - struct mapent_cache *mc; - struct mapent *me; - time_t now = time(NULL); -@@ -3410,7 +3408,7 @@ static int check_map_indirect(struct autofs_point *ap, - pthread_setcancelstate(PTHREAD_CANCEL_DISABLE, &cur_state); - - pthread_mutex_lock(&ap->entry->current_mutex); -- if (source->flags & MAP_FLAG_FORMAT_AMD) { -+ if (is_amd_format) { - unsigned long timestamp = get_amd_timestamp(ctxt); - if (timestamp > ctxt->timestamp) { - ctxt->timestamp = timestamp; -@@ -3457,7 +3455,7 @@ static int check_map_indirect(struct autofs_point *ap, - } - pthread_setcancelstate(cur_state, NULL); - -- if (!(source->flags & MAP_FLAG_FORMAT_AMD)) { -+ if (!is_amd_format) { - /* - * Check for map change and update as needed for - * following cache lookup. -diff --git a/modules/lookup_nisplus.c b/modules/lookup_nisplus.c -index e9444c9..db1b162 100644 ---- a/modules/lookup_nisplus.c -+++ b/modules/lookup_nisplus.c -@@ -339,6 +339,7 @@ static int match_key(struct autofs_point *ap, - const char *key, int key_len, - struct lookup_context *ctxt) - { -+ unsigned int is_amd_format = source->flags & MAP_FLAG_FORMAT_AMD; - char buf[MAX_ERR_BUF]; - char *lkp_key; - char *prefix; -@@ -347,12 +348,9 @@ static int match_key(struct autofs_point *ap, - ret = lookup_one(ap, source, key, key_len, ctxt); - if (ret < 0) - return ret; -- if (ret == CHE_OK || ret == CHE_UPDATED) -+ if (ret == CHE_OK || ret == CHE_UPDATED || is_amd_format) - return ret; - -- if (!(source->flags & MAP_FLAG_FORMAT_AMD)) -- return CHE_FAIL; -- - lkp_key = strdup(key); - if (!lkp_key) { - char *estr = strerror_r(errno, buf, MAX_ERR_BUF); -@@ -504,6 +502,7 @@ static int check_map_indirect(struct autofs_point *ap, - char *key, int key_len, - struct lookup_context *ctxt) - { -+ unsigned int is_amd_format = source->flags & MAP_FLAG_FORMAT_AMD; - struct mapent_cache *mc; - struct mapent *me, *exists; - time_t now = time(NULL); -@@ -512,7 +511,7 @@ static int check_map_indirect(struct autofs_point *ap, - - mc = source->mc; - -- if (source->flags & MAP_FLAG_FORMAT_AMD) { -+ if (is_amd_format) { - /* Check for a /defaults entry to update the map source */ - if (lookup_amd_defaults(ap, source, ctxt) == CHE_FAIL) { - warn(ap->logopt, MODPREFIX -@@ -559,7 +558,7 @@ static int check_map_indirect(struct autofs_point *ap, - } - me = cache_lookup_next(mc, me); - } -- if (source->flags & MAP_FLAG_FORMAT_AMD) -+ if (is_amd_format) - exists = match_cached_key(ap, MODPREFIX, source, key); - else - exists = cache_lookup_distinct(mc, key); -diff --git a/modules/lookup_program.c b/modules/lookup_program.c -index 08d14ff..aae0ec0 100644 ---- a/modules/lookup_program.c -+++ b/modules/lookup_program.c -@@ -382,7 +382,7 @@ static int match_key(struct autofs_point *ap, - char *prefix; - int ret; - -- if (source->flags & MAP_FLAG_FORMAT_AMD) { -+ if (is_amd_format) { - ret = lookup_amd_defaults(ap, source, ctxt); - if (ret != NSS_STATUS_SUCCESS) { - warn(ap->logopt, -@@ -420,7 +420,7 @@ static int match_key(struct autofs_point *ap, - ment = lookup_one(ap, lkp_key, lkp_len, ctxt); - if (ment) { - char *start = ment; -- if (source->flags & MAP_FLAG_FORMAT_AMD) { -+ if (is_amd_format) { - start = ment + lkp_len; - while (isblank(*start)) - start++; -diff --git a/modules/lookup_yp.c b/modules/lookup_yp.c -index 146e39e..fcf470a 100644 ---- a/modules/lookup_yp.c -+++ b/modules/lookup_yp.c -@@ -457,6 +457,7 @@ static int match_key(struct autofs_point *ap, - const char *key, int key_len, - struct lookup_context *ctxt) - { -+ unsigned int is_amd_format = source->flags & MAP_FLAG_FORMAT_AMD; - char buf[MAX_ERR_BUF]; - char *lkp_key; - char *prefix; -@@ -465,12 +466,9 @@ static int match_key(struct autofs_point *ap, - ret = lookup_one(ap, source, key, strlen(key), ctxt); - if (ret < 0) - return ret; -- if (ret == CHE_OK || ret == CHE_UPDATED) -+ if (ret == CHE_OK || ret == CHE_UPDATED || !is_amd_format) - return ret; - -- if (!(source->flags & MAP_FLAG_FORMAT_AMD)) -- return CHE_FAIL; -- - lkp_key = strdup(key); - if (!lkp_key) { - char *estr = strerror_r(errno, buf, MAX_ERR_BUF); diff --git a/autofs-5.1.0-check-amd-lex-buffer-len-before-copy.patch b/autofs-5.1.0-check-amd-lex-buffer-len-before-copy.patch new file mode 100644 index 0000000..43bbfda --- /dev/null +++ b/autofs-5.1.0-check-amd-lex-buffer-len-before-copy.patch @@ -0,0 +1,192 @@ +autofs-5.1.0 - check amd lex buffer len before copy + +From: Ian Kent + +Guard against lex to yacc communication buffer overflow. +--- + CHANGELOG | 1 + + modules/amd_tok.l | 49 +++++++++++++++++++++++++++++++------------------ + 2 files changed, 32 insertions(+), 18 deletions(-) + +diff --git a/CHANGELOG b/CHANGELOG +index 840e099..dfbaeb1 100644 +--- a/CHANGELOG ++++ b/CHANGELOG +@@ -13,6 +13,7 @@ + - fix buffer size checks in get_network_proximity(). + - fix leak in get_network_proximity(). + - fix buffer size checks in merge_options(). ++- check amd lex buffer len before copy. + + 04/06/2014 autofs-5.1.0 + ======================= +diff --git a/modules/amd_tok.l b/modules/amd_tok.l +index 5664f67..1d9c234 100644 +--- a/modules/amd_tok.l ++++ b/modules/amd_tok.l +@@ -22,6 +22,7 @@ + # undef ECHO + #endif + static void amd_echo(void); /* forward definition */ ++static void amd_copy_buffer(void); + #define ECHO amd_echo() + int amd_wrap(void); + +@@ -125,26 +126,26 @@ CUTSEP (\|\||\/) + + {MAPOPT} { + BEGIN(MAPOPTVAL); +- strcpy(amd_lval.strtype, amd_text); ++ amd_copy_buffer(); + return MAP_OPTION; + + } + + {FSOPTS} { + BEGIN(FSOPTVAL); +- strcpy(amd_lval.strtype, amd_text); ++ amd_copy_buffer(); + return FS_OPTION; + } + + {MNTOPT} { + BEGIN(MNTOPTVAL); +- strcpy(amd_lval.strtype, amd_text); ++ amd_copy_buffer(); + return MNT_OPTION; + } + + {SELOPT} { + BEGIN(SELOPTVAL); +- strcpy(amd_lval.strtype, amd_text); ++ amd_copy_buffer(); + return SELECTOR; + } + +@@ -152,13 +153,13 @@ CUTSEP (\|\||\/) + + {SEL1ARG} { + BEGIN(SELARGVAL); +- strcpy(amd_lval.strtype, amd_text); ++ amd_copy_buffer(); + return SELECTOR; + } + + {SEL2ARG} { + BEGIN(SELARGVAL); +- strcpy(amd_lval.strtype, amd_text); ++ amd_copy_buffer(); + return SELECTOR; + } + +@@ -171,7 +172,7 @@ CUTSEP (\|\||\/) + #.* { return COMMENT; } + + {OTHR} { +- strcpy(amd_lval.strtype, amd_text); ++ amd_copy_buffer(); + return OTHER; + } + } +@@ -201,22 +202,22 @@ CUTSEP (\|\||\/) + ":=" { return OPTION_ASSIGN; } + + {FSTYPE} { +- strcpy(amd_lval.strtype, amd_text); ++ amd_copy_buffer(); + return FS_TYPE; + } + + {MAPTYPE} { +- strcpy(amd_lval.strtype, amd_text); ++ amd_copy_buffer(); + return MAP_TYPE; + } + + {CHEOPT} { +- strcpy(amd_lval.strtype, amd_text); ++ amd_copy_buffer(); + return CACHE_OPTION; + } + + {FOPT} { +- strcpy(amd_lval.strtype, amd_text); ++ amd_copy_buffer(); + return FS_OPT_VALUE; + } + } +@@ -246,7 +247,7 @@ CUTSEP (\|\||\/) + ":=" { return OPTION_ASSIGN; } + + {FOPT} { +- strcpy(amd_lval.strtype, amd_text); ++ amd_copy_buffer(); + return FS_OPT_VALUE; + } + } +@@ -278,7 +279,7 @@ CUTSEP (\|\||\/) + "," { return COMMA; } + + {OPTS} { +- strcpy(amd_lval.strtype, amd_text); ++ amd_copy_buffer(); + return OPTION; + } + } +@@ -310,7 +311,7 @@ CUTSEP (\|\||\/) + "!=" { return NOT_EQUAL; } + + {SOPT} { +- strcpy(amd_lval.strtype, amd_text); ++ amd_copy_buffer(); + return SELECTOR_VALUE; + } + } +@@ -335,24 +336,24 @@ CUTSEP (\|\||\/) + "(" { return LBRACKET; } + + {NOPT} { +- strcpy(amd_lval.strtype, amd_text); ++ amd_copy_buffer(); + return SEL_ARG_VALUE; + } + + {SOPT}/"," { +- strcpy(amd_lval.strtype, amd_text); ++ amd_copy_buffer(); + return SEL_ARG_VALUE; + } + + "," { return COMMA; } + + {SOPT} { +- strcpy(amd_lval.strtype, amd_text); ++ amd_copy_buffer(); + return SEL_ARG_VALUE; + } + + {FOPT} { +- strcpy(amd_lval.strtype, amd_text); ++ amd_copy_buffer(); + return SEL_ARG_VALUE; + } + +@@ -368,6 +369,18 @@ int amd_wrap(void) + return 1; + } + ++static void amd_copy_buffer(void) ++{ ++ if (amd_leng < 2048) ++ strcpy(amd_lval.strtype, amd_text); ++ else { ++ strncpy(amd_lval.strtype, amd_text, 2047); ++ amd_lval.strtype[2047] = '\0'; ++ logmsg("warning: truncated option near %s\n", ++ &amd_lval.strtype[2030]); ++ } ++} ++ + static void amd_echo(void) + { + logmsg("%s\n", amd_text); diff --git a/autofs-5.1.0-check-host-macro-is-set-before-use.patch b/autofs-5.1.0-check-host-macro-is-set-before-use.patch new file mode 100644 index 0000000..67773d4 --- /dev/null +++ b/autofs-5.1.0-check-host-macro-is-set-before-use.patch @@ -0,0 +1,38 @@ +autofs-5.1.0 - check host macro is set before use + +From: Ian Kent + +Check marco lookup return for ${host} in match_my_name() before using it. +--- + CHANGELOG | 1 + + modules/parse_amd.c | 5 +++++ + 2 files changed, 6 insertions(+) + +diff --git a/CHANGELOG b/CHANGELOG +index d7d161f..20290fc 100644 +--- a/CHANGELOG ++++ b/CHANGELOG +@@ -15,6 +15,7 @@ + - fix buffer size checks in merge_options(). + - check amd lex buffer len before copy. + - add return check in ldap check_map_indirect(). ++- check host macro is set before use. + + 04/06/2014 autofs-5.1.0 + ======================= +diff --git a/modules/parse_amd.c b/modules/parse_amd.c +index 26d01ed..25fe4aa 100644 +--- a/modules/parse_amd.c ++++ b/modules/parse_amd.c +@@ -238,6 +238,11 @@ static int match_my_name(unsigned int logopt, const char *name, struct substvar + return 1; + } + ++ if (!v || !v->val) { ++ error(logopt, "error: ${host} not set"); ++ goto out; ++ } ++ + /* Check if comparison value is an alias */ + + memset(&hints, 0, sizeof(hints)); diff --git a/autofs-5.1.0-check-options-length-before-use-in-parse_amd_c.patch b/autofs-5.1.0-check-options-length-before-use-in-parse_amd_c.patch new file mode 100644 index 0000000..be3872e --- /dev/null +++ b/autofs-5.1.0-check-options-length-before-use-in-parse_amd_c.patch @@ -0,0 +1,87 @@ +autofs-5.1.0 - check options length before use in parse_amd.c + +From: Ian Kent + +Check for temporary buffer overflow before copy at several places in +modules/parse_amd.c. +--- + CHANGELOG | 1 + + modules/parse_amd.c | 36 ++++++++++++++++++++++++++++++++---- + 2 files changed, 33 insertions(+), 4 deletions(-) + +diff --git a/CHANGELOG b/CHANGELOG +index 20290fc..81aadca 100644 +--- a/CHANGELOG ++++ b/CHANGELOG +@@ -16,6 +16,7 @@ + - check amd lex buffer len before copy. + - add return check in ldap check_map_indirect(). + - check host macro is set before use. ++- check options length before use in parse_amd.c. + + 04/06/2014 autofs-5.1.0 + ======================= +diff --git a/modules/parse_amd.c b/modules/parse_amd.c +index 25fe4aa..6764152 100644 +--- a/modules/parse_amd.c ++++ b/modules/parse_amd.c +@@ -906,9 +906,20 @@ static int do_auto_mount(struct autofs_point *ap, const char *name, + { + char target[PATH_MAX + 1]; + +- if (!entry->map_type) ++ if (!entry->map_type) { ++ if (strlen(entry->fs) > PATH_MAX) { ++ error(ap->logopt, MODPREFIX ++ "error: fs option length is too long"); ++ return 0; ++ } + strcpy(target, entry->fs); +- else { ++ } else { ++ if (strlen(entry->fs) + ++ strlen(entry->map_type) + 5 > PATH_MAX) { ++ error(ap->logopt, MODPREFIX ++ "error: fs + maptype options length is too long"); ++ return 0; ++ } + strcpy(target, entry->map_type); + strcat(target, ",amd:"); + strcat(target, entry->fs); +@@ -925,10 +936,21 @@ static int do_link_mount(struct autofs_point *ap, const char *name, + const char *opts = (entry->opts && *entry->opts) ? entry->opts : NULL; + int ret; + +- if (entry->sublink) ++ if (entry->sublink) { ++ if (strlen(entry->sublink) > PATH_MAX) { ++ error(ap->logopt, MODPREFIX ++ "error: sublink option length is too long"); ++ return 0; ++ } + strcpy(target, entry->sublink); +- else ++ } else { ++ if (strlen(entry->fs) > PATH_MAX) { ++ error(ap->logopt, MODPREFIX ++ "error: fs option length is too long"); ++ return 0; ++ } + strcpy(target, entry->fs); ++ } + + if (!(flags & CONF_AUTOFS_USE_LOFS)) + goto symlink; +@@ -1017,6 +1039,12 @@ static int do_nfs_mount(struct autofs_point *ap, const char *name, + unsigned int umount = 0; + int ret = 0; + ++ if (strlen(entry->rhost) + strlen(entry->rfs) + 1 > PATH_MAX) { ++ error(ap->logopt, MODPREFIX ++ "error: rhost + rfs options length is too long"); ++ return 0; ++ } ++ + strcpy(target, entry->rhost); + strcat(target, ":"); + strcat(target, entry->rfs); diff --git a/autofs-5.1.0-dont-allocate-dev_ctl_ops-too-early.patch b/autofs-5.1.0-dont-allocate-dev_ctl_ops-too-early.patch new file mode 100644 index 0000000..69b846f --- /dev/null +++ b/autofs-5.1.0-dont-allocate-dev_ctl_ops-too-early.patch @@ -0,0 +1,87 @@ +autofs-5.1.0 - dont allocate dev_ctl_ops too early + +From: Ian Kent + +If the standard io file descriptors have been closed by the cloning +process the file handle for autofs device control can correspond to +a descriptor number of one of the standard io descriptors which will +be closed when the process is daemonized. + +Avoid this by closing the device control descriptor opened when +performing sanity checks at startup so that it can be opened +on a higher numbered file descriptor after the process has switched +to daemon mode. +--- + CHANGELOG | 1 + + lib/mounts.c | 14 +++++++++++++- + 2 files changed, 14 insertions(+), 1 deletion(-) + +diff --git a/CHANGELOG b/CHANGELOG +index 92ee83b..ece8c5c 100644 +--- a/CHANGELOG ++++ b/CHANGELOG +@@ -2,6 +2,7 @@ + ======================= + - fix compile error in defaults.c. + - add serialization to sasl init. ++- dont allocate dev_ctl_ops too early. + + 04/06/2014 autofs-5.1.0 + ======================= +diff --git a/lib/mounts.c b/lib/mounts.c +index c9e1237..f635371 100644 +--- a/lib/mounts.c ++++ b/lib/mounts.c +@@ -90,7 +90,7 @@ unsigned int linux_version_code(void) + + unsigned int query_kproto_ver(void) + { +- struct ioctl_ops *ops = get_ioctl_ops(); ++ struct ioctl_ops *ops; + char dir[] = "/tmp/autoXXXXXX", *t_dir; + char options[MAX_OPTIONS_LEN + 1]; + pid_t pgrp = getpgrp(); +@@ -131,10 +131,19 @@ unsigned int query_kproto_ver(void) + return 0; + } + ++ ops = get_ioctl_ops(); ++ if (!ops) { ++ umount(t_dir); ++ close(pipefd[0]); ++ rmdir(t_dir); ++ return 0; ++ } ++ + ops->open(LOGOPT_NONE, &ioctlfd, st.st_dev, t_dir); + if (ioctlfd == -1) { + umount(t_dir); + close(pipefd[0]); ++ close_ioctl_ctl(); + rmdir(t_dir); + return 0; + } +@@ -146,6 +155,7 @@ unsigned int query_kproto_ver(void) + ops->close(LOGOPT_NONE, ioctlfd); + umount(t_dir); + close(pipefd[0]); ++ close_ioctl_ctl(); + rmdir(t_dir); + return 0; + } +@@ -155,6 +165,7 @@ unsigned int query_kproto_ver(void) + ops->close(LOGOPT_NONE, ioctlfd); + umount(t_dir); + close(pipefd[0]); ++ close_ioctl_ctl(); + rmdir(t_dir); + return 0; + } +@@ -162,6 +173,7 @@ unsigned int query_kproto_ver(void) + ops->close(LOGOPT_NONE, ioctlfd); + umount(t_dir); + close(pipefd[0]); ++ close_ioctl_ctl(); + rmdir(t_dir); + + return 1; diff --git a/autofs-5.1.0-fix-buffer-size-checks-in-get_network_proximity.patch b/autofs-5.1.0-fix-buffer-size-checks-in-get_network_proximity.patch new file mode 100644 index 0000000..d94daad --- /dev/null +++ b/autofs-5.1.0-fix-buffer-size-checks-in-get_network_proximity.patch @@ -0,0 +1,56 @@ +autofs-5.1.0 - fix buffer size checks in get_network_proximity() + +From: Ian Kent + +Add several buffer size checks in get_network_proximity(). +--- + CHANGELOG | 1 + + lib/parse_subs.c | 8 +++++--- + 2 files changed, 6 insertions(+), 3 deletions(-) + +diff --git a/CHANGELOG b/CHANGELOG +index 6977443..86166d7 100644 +--- a/CHANGELOG ++++ b/CHANGELOG +@@ -10,6 +10,7 @@ + - fix FILE pointer check in defaults_read_config(). + - fix memory leak in conf_amd_get_log_options(). + - fix signed comparison in inet_fill_net(). ++- fix buffer size checks in get_network_proximity(). + + 04/06/2014 autofs-5.1.0 + ======================= +diff --git a/lib/parse_subs.c b/lib/parse_subs.c +index c1648c2..9af5106 100644 +--- a/lib/parse_subs.c ++++ b/lib/parse_subs.c +@@ -437,7 +437,7 @@ unsigned int get_network_proximity(const char *name) + { + struct addrinfo hints; + struct addrinfo *ni, *this; +- char name_or_num[NI_MAXHOST]; ++ char name_or_num[NI_MAXHOST + 1]; + unsigned int proximity; + char *net; + int ret; +@@ -449,16 +449,18 @@ unsigned int get_network_proximity(const char *name) + if (net) + strcpy(name_or_num, net); + else { +- char this[NI_MAXHOST]; ++ char this[NI_MAXHOST + 1]; + char *mask; + ++ if (strlen(name) > NI_MAXHOST) ++ return PROXIMITY_ERROR; + strcpy(this, name); + if ((mask = strchr(this, '/'))) + *mask++ = '\0'; + if (!strchr(this, '.')) + strcpy(name_or_num, this); + else { +- char buf[NI_MAXHOST], *new; ++ char buf[NI_MAXHOST + 1], *new; + new = inet_fill_net(this, buf); + if (!new) + return PROXIMITY_ERROR; diff --git a/autofs-5.1.0-fix-buffer-size-checks-in-merge_options.patch b/autofs-5.1.0-fix-buffer-size-checks-in-merge_options.patch new file mode 100644 index 0000000..6e3d00f --- /dev/null +++ b/autofs-5.1.0-fix-buffer-size-checks-in-merge_options.patch @@ -0,0 +1,109 @@ +autofs-5.1.0 - fix buffer size checks in merge_options() + +From: Ian Kent + +Fix some buffer size overflow checks in merge_options(). +--- + CHANGELOG | 1 + + lib/parse_subs.c | 25 +++++++++++++++++++++---- + 2 files changed, 22 insertions(+), 4 deletions(-) + +diff --git a/CHANGELOG b/CHANGELOG +index 92657c3..840e099 100644 +--- a/CHANGELOG ++++ b/CHANGELOG +@@ -12,6 +12,7 @@ + - fix signed comparison in inet_fill_net(). + - fix buffer size checks in get_network_proximity(). + - fix leak in get_network_proximity(). ++- fix buffer size checks in merge_options(). + + 04/06/2014 autofs-5.1.0 + ======================= +diff --git a/lib/parse_subs.c b/lib/parse_subs.c +index 6e9f2d7..6145828 100644 +--- a/lib/parse_subs.c ++++ b/lib/parse_subs.c +@@ -886,11 +886,11 @@ static char *hasopt(const char *str, const char *opt) + + char *merge_options(const char *opt1, const char *opt2) + { +- char str[MAX_OPTIONS_LEN]; +- char result[MAX_OPTIONS_LEN]; +- char neg[MAX_OPTION_LEN]; ++ char str[MAX_OPTIONS_LEN + 1]; ++ char result[MAX_OPTIONS_LEN + 1]; ++ char neg[MAX_OPTION_LEN + 1]; + char *tok, *ptr = NULL; +- size_t len; ++ size_t resultlen, len; + + if ((!opt1 || !*opt1) && (!opt2 || !*opt2)) + return NULL; +@@ -910,9 +910,12 @@ char *merge_options(const char *opt1, const char *opt2) + if (!strcmp(opt1, opt2)) + return strdup(opt1); + ++ if (strlen(str) > MAX_OPTIONS_LEN) ++ return NULL; + memset(result, 0, sizeof(result)); + strcpy(str, opt1); + ++ resultlen = 0; + tok = strtok_r(str, ",", &ptr); + while (tok) { + const char *this = (const char *) tok; +@@ -920,12 +923,15 @@ char *merge_options(const char *opt1, const char *opt2) + if (eq) { + *eq = '\0'; + if (!hasopt(opt2, this)) { ++ if (resultlen + strlen(this) > MAX_OPTIONS_LEN) ++ return NULL; + *eq = '='; + if (!*result) + strcpy(result, this); + else + strcat(result, this); + strcat(result, ","); ++ resultlen += strlen(this) + 1; + goto next; + } + } +@@ -946,10 +952,14 @@ char *merge_options(const char *opt1, const char *opt2) + goto next; + + if (!strncmp(this, "no", 2)) { ++ if (strlen(this + 2) > MAX_OPTION_LEN) ++ return NULL; + strcpy(neg, this + 2); + if (hasopt(opt2, neg)) + goto next; + } else { ++ if ((strlen(this) + 2) > MAX_OPTION_LEN) ++ return NULL; + strcpy(neg, "no"); + strcat(neg, this); + if (hasopt(opt2, neg)) +@@ -959,15 +969,22 @@ char *merge_options(const char *opt1, const char *opt2) + if (hasopt(opt2, tok)) + goto next; + ++ if (resultlen + strlen(this) + 1 > MAX_OPTIONS_LEN) ++ return NULL; ++ + if (!*result) + strcpy(result, this); + else + strcat(result, this); + strcat(result, ","); ++ resultlen =+ strlen(this) + 1; + next: + tok = strtok_r(NULL, ",", &ptr); + } + ++ if (resultlen + strlen(opt2) > MAX_OPTIONS_LEN) ++ return NULL; ++ + if (!*result) + strcpy(result, opt2); + else diff --git a/autofs-5.1.0-fix-compile-error-in-defaults_c.patch b/autofs-5.1.0-fix-compile-error-in-defaults_c.patch new file mode 100644 index 0000000..cba6f72 --- /dev/null +++ b/autofs-5.1.0-fix-compile-error-in-defaults_c.patch @@ -0,0 +1,35 @@ +autofs-5.1.0 - fix compile error in defaults.c + +From: Ian Kent + +Puzzling, suddenly I'm getting a compile error for defaults.c due +to a lack of including stdarg.h. +--- + CHANGELOG | 4 ++++ + lib/defaults.c | 1 + + 2 files changed, 5 insertions(+) + +diff --git a/CHANGELOG b/CHANGELOG +index 5a5964d..58b94dc 100644 +--- a/CHANGELOG ++++ b/CHANGELOG +@@ -1,3 +1,7 @@ ++??/??/2014 autofs-5.1.1 ++======================= ++- fix compile error in defaults.c. ++ + 04/06/2014 autofs-5.1.0 + ======================= + - fix mistake in assignment. +diff --git a/lib/defaults.c b/lib/defaults.c +index 2b03ea2..d29a976 100644 +--- a/lib/defaults.c ++++ b/lib/defaults.c +@@ -20,6 +20,7 @@ + #include + #include + #include ++#include + + #include "config.h" + #include "list.h" diff --git a/autofs-5.1.0-fix-config-entry-read-buffer-not-checked.patch b/autofs-5.1.0-fix-config-entry-read-buffer-not-checked.patch new file mode 100644 index 0000000..edb931a --- /dev/null +++ b/autofs-5.1.0-fix-config-entry-read-buffer-not-checked.patch @@ -0,0 +1,49 @@ +autofs-5.1.0 - fix config entry read buffer not checked + +From: Ian Kent + +Check the length of config file line read in and report truncation +if it was too long. +--- + CHANGELOG | 1 + + lib/defaults.c | 8 +++++++- + 2 files changed, 8 insertions(+), 1 deletion(-) + +diff --git a/CHANGELOG b/CHANGELOG +index bc8b9d1..21c3ecd 100644 +--- a/CHANGELOG ++++ b/CHANGELOG +@@ -6,6 +6,7 @@ + - fix incorrect round robin host detection. + - fix race accessing qdn in get_query_dn(). + - fix leak in cache_push_mapent(). ++- fix config entry read buffer not checked. + + 04/06/2014 autofs-5.1.0 + ======================= +diff --git a/lib/defaults.c b/lib/defaults.c +index d29a976..a83dcee 100644 +--- a/lib/defaults.c ++++ b/lib/defaults.c +@@ -835,7 +835,7 @@ static int parse_line(char *line, char **sec, char **res, char **value) + + static int read_config(unsigned int to_syslog, FILE *f, const char *name) + { +- char buf[MAX_LINE_LEN]; ++ char buf[MAX_LINE_LEN + 2]; + char secbuf[MAX_SECTION_NAME]; + char *new_sec; + char *res; +@@ -843,6 +843,12 @@ static int read_config(unsigned int to_syslog, FILE *f, const char *name) + new_sec = NULL; + while ((res = fgets(buf, MAX_LINE_LEN, f))) { + char *sec, *key, *value; ++ ++ if (strlen(res) > MAX_LINE_LEN) { ++ message(to_syslog, "%s was truncated, ignored", res); ++ continue; ++ } ++ + sec = key = value = NULL; + if (!parse_line(res, &sec, &key, &value)) + continue; diff --git a/autofs-5.1.0-fix-copy-and-paste-error-in-dup_defaults_entry.patch b/autofs-5.1.0-fix-copy-and-paste-error-in-dup_defaults_entry.patch new file mode 100644 index 0000000..353ff99 --- /dev/null +++ b/autofs-5.1.0-fix-copy-and-paste-error-in-dup_defaults_entry.patch @@ -0,0 +1,35 @@ +autofs-5.1.0 - fix copy and paste error in dup_defaults_entry() + +From: Ian Kent + + +--- + CHANGELOG | 1 + + modules/parse_amd.c | 2 +- + 2 files changed, 2 insertions(+), 1 deletion(-) + +diff --git a/CHANGELOG b/CHANGELOG +index 4e00929..cb74c60 100644 +--- a/CHANGELOG ++++ b/CHANGELOG +@@ -18,6 +18,7 @@ + - check host macro is set before use. + - check options length before use in parse_amd.c. + - fix some out of order evaluations in parse_amd.c. ++- fix copy and paste error in dup_defaults_entry(). + + 04/06/2014 autofs-5.1.0 + ======================= +diff --git a/modules/parse_amd.c b/modules/parse_amd.c +index c4992c1..a912385 100644 +--- a/modules/parse_amd.c ++++ b/modules/parse_amd.c +@@ -1631,7 +1631,7 @@ static struct amd_entry *dup_defaults_entry(struct amd_entry *defaults) + entry->rfs = tmp; + } + +- if (defaults->rhost && *defaults->rfs) { ++ if (defaults->rhost && *defaults->rhost) { + tmp = strdup(defaults->rhost); + if (tmp) + entry->rhost = tmp; diff --git a/autofs-5.1.0-fix-incorrect-round-robin-host-detection.patch b/autofs-5.1.0-fix-incorrect-round-robin-host-detection.patch new file mode 100644 index 0000000..b3f05cf --- /dev/null +++ b/autofs-5.1.0-fix-incorrect-round-robin-host-detection.patch @@ -0,0 +1,35 @@ +autofs-5.1.0 - fix incorrect round robin host detection + +From: Ian Kent + + +--- + CHANGELOG | 1 + + modules/replicated.c | 2 +- + 2 files changed, 2 insertions(+), 1 deletion(-) + +diff --git a/CHANGELOG b/CHANGELOG +index ece8c5c..1b4e2fe 100644 +--- a/CHANGELOG ++++ b/CHANGELOG +@@ -3,6 +3,7 @@ + - fix compile error in defaults.c. + - add serialization to sasl init. + - dont allocate dev_ctl_ops too early. ++- fix incorrect round robin host detection. + + 04/06/2014 autofs-5.1.0 + ======================= +diff --git a/modules/replicated.c b/modules/replicated.c +index 0c1a8a7..32860d5 100644 +--- a/modules/replicated.c ++++ b/modules/replicated.c +@@ -946,7 +946,7 @@ try_name: + } + + this = ni; +- while (this->ai_next) { ++ while (this) { + if (this->ai_family == AF_INET) { + struct sockaddr_in *addr = (struct sockaddr_in *) this->ai_addr; + if (addr->sin_addr.s_addr != INADDR_LOOPBACK) diff --git a/autofs-5.1.0-fix-leak-in-cache_push_mapent.patch b/autofs-5.1.0-fix-leak-in-cache_push_mapent.patch new file mode 100644 index 0000000..232de8a --- /dev/null +++ b/autofs-5.1.0-fix-leak-in-cache_push_mapent.patch @@ -0,0 +1,36 @@ +autofs-5.1.0 - fix leak in cache_push_mapent() + +From: Ian Kent + +cache_push_mapent() incorectly sets the cache entry mapent to the old +value which causes a memory leak when the new map entry isn't NULL. +--- + CHANGELOG | 1 + + lib/cache.c | 2 +- + 2 files changed, 2 insertions(+), 1 deletion(-) + +diff --git a/CHANGELOG b/CHANGELOG +index e911682..bc8b9d1 100644 +--- a/CHANGELOG ++++ b/CHANGELOG +@@ -5,6 +5,7 @@ + - dont allocate dev_ctl_ops too early. + - fix incorrect round robin host detection. + - fix race accessing qdn in get_query_dn(). ++- fix leak in cache_push_mapent(). + + 04/06/2014 autofs-5.1.0 + ======================= +diff --git a/lib/cache.c b/lib/cache.c +index 8d08094..4bab5a3 100644 +--- a/lib/cache.c ++++ b/lib/cache.c +@@ -203,7 +203,7 @@ int cache_push_mapent(struct mapent *me, char *mapent) + + s->mapent = me->mapent; + s->age = me->age; +- me->mapent = mapent; ++ me->mapent = new; + + if (me->stack) + s->next = me->stack; diff --git a/autofs-5.1.0-fix-leak-in-get_network_proximity.patch b/autofs-5.1.0-fix-leak-in-get_network_proximity.patch new file mode 100644 index 0000000..2cdca78 --- /dev/null +++ b/autofs-5.1.0-fix-leak-in-get_network_proximity.patch @@ -0,0 +1,39 @@ +autofs-5.1.0 - fix leak in get_network_proximity() + +From: Ian Kent + +Fix variable net not freed after use in get_network_proximity(). +--- + CHANGELOG | 1 + + lib/parse_subs.c | 5 +++-- + 2 files changed, 4 insertions(+), 2 deletions(-) + +diff --git a/CHANGELOG b/CHANGELOG +index 86166d7..92657c3 100644 +--- a/CHANGELOG ++++ b/CHANGELOG +@@ -11,6 +11,7 @@ + - fix memory leak in conf_amd_get_log_options(). + - fix signed comparison in inet_fill_net(). + - fix buffer size checks in get_network_proximity(). ++- fix leak in get_network_proximity(). + + 04/06/2014 autofs-5.1.0 + ======================= +diff --git a/lib/parse_subs.c b/lib/parse_subs.c +index 9af5106..6e9f2d7 100644 +--- a/lib/parse_subs.c ++++ b/lib/parse_subs.c +@@ -446,9 +446,10 @@ unsigned int get_network_proximity(const char *name) + return PROXIMITY_ERROR; + + net = get_network_number(name); +- if (net) ++ if (net) { + strcpy(name_or_num, net); +- else { ++ free(net); ++ } else { + char this[NI_MAXHOST + 1]; + char *mask; + diff --git a/autofs-5.1.0-fix-leak-in-parse_mount.patch b/autofs-5.1.0-fix-leak-in-parse_mount.patch new file mode 100644 index 0000000..a72b02a --- /dev/null +++ b/autofs-5.1.0-fix-leak-in-parse_mount.patch @@ -0,0 +1,36 @@ +autofs-5.1.0 - fix leak in parse_mount() + +From: Ian Kent + +Fix a potential memory leak of the allocated mount location +in modules/parse_sun.c:parse_mount(). +--- + modules/parse_sun.c | 8 ++++++-- + 1 file changed, 6 insertions(+), 2 deletions(-) + +diff --git a/modules/parse_sun.c b/modules/parse_sun.c +index 1fdea0b..b881ee9 100644 +--- a/modules/parse_sun.c ++++ b/modules/parse_sun.c +@@ -1567,7 +1567,10 @@ int parse_mount(struct autofs_point *ap, const char *name, + */ + if ((strstr(options, "fstype=autofs") && + strstr(options, "hosts"))) { +- loc = NULL; ++ if (loc) { ++ free(loc); ++ loc = NULL; ++ } + loclen = 0; + } else { + loclen = strlen(loc); +@@ -1591,7 +1594,8 @@ int parse_mount(struct autofs_point *ap, const char *name, + rv = sun_mount(ap, ap->path, name, name_len, + loc, loclen, options, ctxt); + +- free(loc); ++ if (loc) ++ free(loc); + free(options); + pthread_setcancelstate(cur_state, NULL); + } diff --git a/autofs-5.1.0-fix-signed-comparison-in-inet_fill_net.patch b/autofs-5.1.0-fix-signed-comparison-in-inet_fill_net.patch new file mode 100644 index 0000000..5d447db --- /dev/null +++ b/autofs-5.1.0-fix-signed-comparison-in-inet_fill_net.patch @@ -0,0 +1,36 @@ +autofs-5.1.0 - fix signed comparison in inet_fill_net() + +From: Ian Kent + +Fix the less than 0 comparison of an incorrectly declared var in +inet_fill_net(). +--- + CHANGELOG | 1 + + lib/parse_subs.c | 2 +- + 2 files changed, 2 insertions(+), 1 deletion(-) + +diff --git a/CHANGELOG b/CHANGELOG +index f5bbb34..6977443 100644 +--- a/CHANGELOG ++++ b/CHANGELOG +@@ -9,6 +9,7 @@ + - fix config entry read buffer not checked. + - fix FILE pointer check in defaults_read_config(). + - fix memory leak in conf_amd_get_log_options(). ++- fix signed comparison in inet_fill_net(). + + 04/06/2014 autofs-5.1.0 + ======================= +diff --git a/lib/parse_subs.c b/lib/parse_subs.c +index d3dfa57..c1648c2 100644 +--- a/lib/parse_subs.c ++++ b/lib/parse_subs.c +@@ -378,7 +378,7 @@ unsigned int get_proximity(struct sockaddr *host_addr) + static char *inet_fill_net(const char *net_num, char *net) + { + char *np; +- unsigned int dots = 3; ++ int dots = 3; + + if (strlen(net_num) > INET_ADDRSTRLEN) + return NULL; diff --git a/autofs-5.1.0-fix-some-out-of-order-evaluations-in-parse_amd_c.patch b/autofs-5.1.0-fix-some-out-of-order-evaluations-in-parse_amd_c.patch new file mode 100644 index 0000000..1edd0dc --- /dev/null +++ b/autofs-5.1.0-fix-some-out-of-order-evaluations-in-parse_amd_c.patch @@ -0,0 +1,107 @@ +autofs-5.1.0 - fix some out of order evaluations in parse_amd.c + +From: Ian Kent + +Fix some check contents before NULL check ordering in modules/parse_amd.c. +--- + CHANGELOG | 1 + + modules/parse_amd.c | 33 ++++++++++++++------------------- + 2 files changed, 15 insertions(+), 19 deletions(-) + +diff --git a/CHANGELOG b/CHANGELOG +index 81aadca..4e00929 100644 +--- a/CHANGELOG ++++ b/CHANGELOG +@@ -17,6 +17,7 @@ + - add return check in ldap check_map_indirect(). + - check host macro is set before use. + - check options length before use in parse_amd.c. ++- fix some out of order evaluations in parse_amd.c. + + 04/06/2014 autofs-5.1.0 + ======================= +diff --git a/modules/parse_amd.c b/modules/parse_amd.c +index 6764152..c4992c1 100644 +--- a/modules/parse_amd.c ++++ b/modules/parse_amd.c +@@ -1226,13 +1226,12 @@ static unsigned int validate_auto_options(unsigned int logopt, + * left blank the mount must be expected to fail so don't + * report the error. + */ +- if (!*entry->fs) +- return 0; +- else if (!entry->fs) { ++ if (!entry->fs) { + error(logopt, MODPREFIX + "%s: file system not given", entry->type); + return 0; +- } ++ } else if (!*entry->fs) ++ return 0; + return 1; + } + +@@ -1255,13 +1254,12 @@ static unsigned int validate_nfs_options(unsigned int logopt, + * expected to fail. + */ + if (!entry->rfs || !*entry->rfs) { +- if (!*entry->rfs) ++ if (entry->rfs && !*entry->rfs) + return 0; + /* Map option fs has been intentionally left blank */ + if (entry->fs && !*entry->fs) + return 0; +- if (entry->fs) +- entry->rfs = strdup(entry->fs); ++ entry->rfs = strdup(entry->fs); + if (!entry->rfs) { + error(logopt, MODPREFIX + "%s: remote file system not given", entry->type); +@@ -1285,24 +1283,22 @@ static unsigned int validate_generic_options(unsigned int logopt, + * expected to fail so don't report the error. + */ + if (fstype != AMD_MOUNT_TYPE_LOFS) { +- if (!*entry->dev) +- return 0; +- else if (!entry->dev) { ++ if (!entry->dev) { + error(logopt, MODPREFIX + "%s: mount device not given", entry->type); + return 0; +- } +- } else { +- if (!*entry->rfs) ++ } else if (!*entry->dev) + return 0; +- else if (!entry->rfs) { ++ } else { ++ if (!entry->rfs) { + /* + * Can't use entry->type as the mount type to reprot + * the error since entry->type == "bind" not "lofs". + */ + error(logopt, "lofs: mount device not given"); + return 0; +- } ++ } else if (!*entry->rfs) ++ return 0; + } + if (entry->sublink && !entry->fs) { + error(logopt, MODPREFIX +@@ -1337,13 +1333,12 @@ static unsigned int validate_host_options(unsigned int logopt, + * if it isn't given in the map entry. Don't report an error + * if it has been left empty since it's expected to fail. + */ +- if (!*entry->rhost) +- return 0; +- else if (!entry->rhost) { ++ if (!entry->rhost) { + error(logopt, MODPREFIX + "%s: remote host name not given", entry->type); + return 0; +- } ++ } else if (!*entry->rhost) ++ return 0; + return 1; + } + diff --git a/autofs.spec b/autofs.spec index 506a0ce..37838c9 100644 --- a/autofs.spec +++ b/autofs.spec @@ -8,11 +8,31 @@ Summary: A tool for automatically mounting and unmounting filesystems Name: autofs Version: 5.1.0 -Release: 2%{?dist} +Release: 3%{?dist} Epoch: 1 License: GPLv2+ Group: System Environment/Daemons Source: ftp://ftp.kernel.org/pub/linux/daemons/autofs/v5/autofs-%{version}.tar.gz +Patch1: autofs-5.1.0-fix-compile-error-in-defaults_c.patch +Patch2: autofs-5.1.0-add-serialization-to-sasl-init.patch +Patch3: autofs-5.1.0-dont-allocate-dev_ctl_ops-too-early.patch +Patch4: autofs-5.1.0-fix-incorrect-round-robin-host-detection.patch +Patch5: autofs-5.0.9-fix-race-accessing-qdn-in-get_query_dn.patch +Patch6: autofs-5.1.0-fix-leak-in-cache_push_mapent.patch +Patch7: autofs-5.1.0-fix-config-entry-read-buffer-not-checked.patch +Patch8: autofs-5.0.1-fix-FILE-pointer-check-in-defaults_read_config.patch +Patch9: autofs-5.0.1-fix-memory-leak-in-conf_amd_get_log_options.patch +Patch10: autofs-5.1.0-fix-signed-comparison-in-inet_fill_net.patch +Patch11: autofs-5.1.0-fix-buffer-size-checks-in-get_network_proximity.patch +Patch12: autofs-5.1.0-fix-leak-in-get_network_proximity.patch +Patch13: autofs-5.1.0-fix-buffer-size-checks-in-merge_options.patch +Patch14: autofs-5.1.0-check-amd-lex-buffer-len-before-copy.patch +Patch15: autofs-5.1.0-add-return-check-in-ldap-check_map_indirect.patch +Patch16: autofs-5.1.0-check-host-macro-is-set-before-use.patch +Patch17: autofs-5.1.0-check-options-length-before-use-in-parse_amd_c.patch +Patch18: autofs-5.1.0-fix-some-out-of-order-evaluations-in-parse_amd_c.patch +Patch19: autofs-5.1.0-fix-copy-and-paste-error-in-dup_defaults_entry.patch +Patch20: autofs-5.1.0-fix-leak-in-parse_mount.patch Buildroot: %{_tmppath}/%{name}-%{version}-%{release}-root-%(%{__id_u} -n) %if %{with_systemd} BuildRequires: systemd-units @@ -70,6 +90,26 @@ echo %{version}-%{release} > .version %define unitdir %{?_unitdir:/usr/lib/systemd/system} %define systemd_configure_arg --with-systemd %endif +%patch1 -p1 +%patch2 -p1 +%patch3 -p1 +%patch4 -p1 +%patch5 -p1 +%patch6 -p1 +%patch7 -p1 +%patch8 -p1 +%patch9 -p1 +%patch10 -p1 +%patch11 -p1 +%patch12 -p1 +%patch13 -p1 +%patch14 -p1 +%patch15 -p1 +%patch16 -p1 +%patch17 -p1 +%patch18 -p1 +%patch19 -p1 +%patch20 -p1 %build LDFLAGS=-Wl,-z,now @@ -162,6 +202,27 @@ fi %dir /etc/auto.master.d %changelog +* Mon Jul 7 2014 Ian Kent - 1:5.1.0-3 +- fix compile error in defaults.c. +- add serialization to sasl init. +- dont allocate dev_ctl_ops too early. +- fix incorrect round robin host detection. +- fix race accessing qdn in get_query_dn(). +- fix leak in cache_push_mapent(). +- fix config entry read buffer not checked. +- fix FILE pointer check in defaults_read_config(). +- fix memory leak in conf_amd_get_log_options(). +- fix signed comparison in inet_fill_net(). +- fix buffer size checks in get_network_proximity(). +- fix leak in get_network_proximity(). +- fix buffer size checks in merge_options(). +- check amd lex buffer len before copy. +- add return check in ldap check_map_indirect(). +- check host macro is set before use. +- check options length before use in parse_amd.c. +- fix some out of order evaluations in parse_amd.c. +- fix copy and paste error in dup_defaults_entry(). + * Sat Jun 07 2014 Fedora Release Engineering - 1:5.1.0-2 - Rebuilt for https://fedoraproject.org/wiki/Fedora_21_Mass_Rebuild