- add some Coverity identified fixes for bug 1078776.

This commit is contained in:
Ian Kent 2014-07-07 12:07:07 +08:00
parent b1acacad77
commit ff6f3ee6ef
37 changed files with 1375 additions and 2459 deletions

View File

@ -0,0 +1,82 @@
autofs-5.0.1 - fix FILE pointer check in defaults_read_config()
From: Ian Kent <raven@themaw.net>
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;
}

View File

@ -0,0 +1,34 @@
autofs-5.0.1 - fix memory leak in conf_amd_get_log_options()
From: Ian Kent <raven@themaw.net>
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)

View File

@ -1,62 +0,0 @@
autofs-5.0.8 - allow --with-systemd to take a path arg
From: Joe MacDonald <joe@deserted.net>
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 <joe@deserted.net>
---
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])
])

View File

@ -1,423 +0,0 @@
autofs-5.0.8 - amd lookup update lookup hesiod to handle amd keys
From: Ian Kent <raven@themaw.net>
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 <amu@alum.mit.edu> 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 <amu@alum.mit.edu> 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

View File

@ -1,954 +0,0 @@
autofs-5.0.8 - amd lookup update lookup ldap to handle amd keys
From: Ian Kent <raven@themaw.net>
---
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 <resolv.h>
#include <lber.h>
#include <libxml/tree.h>
+#include <stdlib.h>
#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;

View File

@ -1,49 +0,0 @@
autofs-5.0.8 - fix WITH_LIBTIRPC function name
From: Ian Kent <ikent@redhat.com>
autoconf function names AM_<name> 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)
#

View File

@ -1,37 +0,0 @@
autofs-5.0.8 - fix allow with systemd to take a path arg
From: Ian Kent <ikent@redhat.com>
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

View File

@ -1,34 +0,0 @@
autofs-5.0.8 - fix fix ipv6 libtirpc getport
From: Ian Kent <raven@themaw.net>
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,

View File

@ -1,32 +0,0 @@
autofs-5.0.8 - fix rpc_portmap_getport() proto not set
From: Ian Kent <raven@themaw.net>
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

View File

@ -1,345 +0,0 @@
autofs-5.0.8 - fix ipv6 libtirpc getport
From: Ian Kent <ikent@redhat.com>
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) {

View File

@ -1,41 +0,0 @@
autofs-5.0.8 - fix ipv6 link local address handling
From: Ian Kent <raven@themaw.net>
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;

View File

@ -1,58 +0,0 @@
autofs-5.0.8 - fix master map type check
From: Ian Kent <ikent@redhat.com>
Map type has format <type>[,<format>] but the master map type check
for old style map syntax doesn't allow for <format>.
---
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);
/*

View File

@ -1,59 +0,0 @@
autofs-5.0.8 - fix portmap not trying proto v2
From: Ian Kent <raven@themaw.net>
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

View File

@ -1,47 +0,0 @@
autofs-5.0.8 - fix task manager not getting signaled
From: Ian Kent <ikent@redhat.com>
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;
}

View File

@ -1,52 +0,0 @@
autofs-5.0.8 - fix undefined authtype_requires_creds err if ldap enabled but without sasl
From: Lan Yixun (dlan) <dennis.yxun@gmail.com>
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:

View File

@ -1,31 +0,0 @@
autofs-5.0.8 - get_nfs_info() should query portmapper if port is not given
From: Scott Mayhew <smayhew@redhat.com>
It shouldn't just assume it can use port 2049.
Signed-off-by: Scott Mayhew <smayhew@redhat.com>
---
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));

View File

@ -1,64 +0,0 @@
autofs-5.0.9 - check for non existent negative entries in lookup_ghost()
From: Ian Kent <raven@themaw.net>
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)

View File

@ -0,0 +1,52 @@
autofs-5.0.9 - fix race accessing qdn in get_query_dn()
From: Ian Kent <raven@themaw.net>
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;
}

View File

@ -0,0 +1,72 @@
autofs-5.1.0 - add return check in ldap check_map_indirect()
From: Ian Kent <ikent@redhat.com>
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);

View File

@ -0,0 +1,96 @@
autofs-5.1.0 - add serialization to sasl init
From: Ian Kent <ikent@redhat.com>
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;

View File

@ -1,170 +0,0 @@
autofs-5.1.0-beta1 - fix wildcard key lookup
From: Ian Kent <raven@themaw.net>
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);

View File

@ -0,0 +1,192 @@
autofs-5.1.0 - check amd lex buffer len before copy
From: Ian Kent <ikent@redhat.com>
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);

View File

@ -0,0 +1,38 @@
autofs-5.1.0 - check host macro is set before use
From: Ian Kent <ikent@redhat.com>
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));

View File

@ -0,0 +1,87 @@
autofs-5.1.0 - check options length before use in parse_amd.c
From: Ian Kent <ikent@redhat.com>
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);

View File

@ -0,0 +1,87 @@
autofs-5.1.0 - dont allocate dev_ctl_ops too early
From: Ian Kent <raven@themaw.net>
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;

View File

@ -0,0 +1,56 @@
autofs-5.1.0 - fix buffer size checks in get_network_proximity()
From: Ian Kent <raven@themaw.net>
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;

View File

@ -0,0 +1,109 @@
autofs-5.1.0 - fix buffer size checks in merge_options()
From: Ian Kent <raven@themaw.net>
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

View File

@ -0,0 +1,35 @@
autofs-5.1.0 - fix compile error in defaults.c
From: Ian Kent <raven@themaw.net>
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 <string.h>
#include <sys/utsname.h>
#include <sys/stat.h>
+#include <stdarg.h>
#include "config.h"
#include "list.h"

View File

@ -0,0 +1,49 @@
autofs-5.1.0 - fix config entry read buffer not checked
From: Ian Kent <raven@themaw.net>
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;

View File

@ -0,0 +1,35 @@
autofs-5.1.0 - fix copy and paste error in dup_defaults_entry()
From: Ian Kent <ikent@redhat.com>
---
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;

View File

@ -0,0 +1,35 @@
autofs-5.1.0 - fix incorrect round robin host detection
From: Ian Kent <raven@themaw.net>
---
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)

View File

@ -0,0 +1,36 @@
autofs-5.1.0 - fix leak in cache_push_mapent()
From: Ian Kent <raven@themaw.net>
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;

View File

@ -0,0 +1,39 @@
autofs-5.1.0 - fix leak in get_network_proximity()
From: Ian Kent <raven@themaw.net>
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;

View File

@ -0,0 +1,36 @@
autofs-5.1.0 - fix leak in parse_mount()
From: Ian Kent <ikent@redhat.com>
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);
}

View File

@ -0,0 +1,36 @@
autofs-5.1.0 - fix signed comparison in inet_fill_net()
From: Ian Kent <raven@themaw.net>
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;

View File

@ -0,0 +1,107 @@
autofs-5.1.0 - fix some out of order evaluations in parse_amd.c
From: Ian Kent <ikent@redhat.com>
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;
}

View File

@ -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 <ikent@redhat.com> - 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 <rel-eng@lists.fedoraproject.org> - 1:5.1.0-2
- Rebuilt for https://fedoraproject.org/wiki/Fedora_21_Mass_Rebuild