Blob Blame History Raw
autofs-5.0.7 - fix potential null dereference in lookup_mount()

From: Ian Kent <raven@themaw.net>

Updating a negative cache entry should always find an entry but the entry
lookup return isn't checked and probably should be.

Since this code is duplicated in several modules add it as a function to
the cache handling code.
---
 include/automount.h   |    1 +
 lib/cache.c           |   20 ++++++++++++++++++++
 modules/lookup_file.c |   11 +----------
 modules/lookup_ldap.c |   12 +-----------
 modules/lookup_sss.c  |   12 +-----------
 modules/lookup_yp.c   |   12 ++----------
 6 files changed, 26 insertions(+), 42 deletions(-)

diff --git a/include/automount.h b/include/automount.h
index 6ced842..71787a5 100644
--- a/include/automount.h
+++ b/include/automount.h
@@ -189,6 +189,7 @@ struct mapent *cache_lookup_offset(const char *prefix, const char *offset, int s
 struct mapent *cache_partial_match(struct mapent_cache *mc, const char *prefix);
 int cache_add(struct mapent_cache *mc, struct map_source *ms, const char *key, const char *mapent, time_t age);
 int cache_update_offset(struct mapent_cache *mc, const char *mkey, const char *key, const char *mapent, time_t age);
+void cache_update_negative(struct mapent_cache *mc, struct map_source *ms, const char *key, time_t timeout);
 int cache_set_parents(struct mapent *mm);
 int cache_update(struct mapent_cache *mc, struct map_source *ms, const char *key, const char *mapent, time_t age);
 int cache_delete(struct mapent_cache *mc, const char *key);
diff --git a/lib/cache.c b/lib/cache.c
index ecace4a..be4917b 100644
--- a/lib/cache.c
+++ b/lib/cache.c
@@ -680,6 +680,26 @@ done:
 	return ret; 
 }
 
+void cache_update_negative(struct mapent_cache *mc,
+			   struct map_source *ms, const char *key,
+			   time_t timeout)
+{
+	time_t now = time(NULL);
+	struct mapent *me;
+	int rv = CHE_OK;
+
+	me = cache_lookup_distinct(mc, key);
+	if (!me)
+		rv = cache_update(mc, ms, key, NULL, now);
+	if (rv != CHE_FAIL) {
+		me = cache_lookup_distinct(mc, key);
+		if (me)
+			me->status = now + timeout;
+	}
+	return;
+}
+
+
 static struct mapent *get_parent(const char *key, struct list_head *head, struct list_head **pos)
 {
 	struct list_head *next;
diff --git a/modules/lookup_file.c b/modules/lookup_file.c
index 2836996..4b4ee89 100644
--- a/modules/lookup_file.c
+++ b/modules/lookup_file.c
@@ -1130,17 +1130,8 @@ do_cache_lookup:
 	ret = ctxt->parse->parse_mount(ap, key, key_len,
 				       mapent, ctxt->parse->context);
 	if (ret) {
-		time_t now = time(NULL);
-		int rv = CHE_OK;
-
 		cache_writelock(mc);
-		me = cache_lookup_distinct(mc, key);
-		if (!me)
-			rv = cache_update(mc, source, key, NULL, now);
-		if (rv != CHE_FAIL) {
-			me = cache_lookup_distinct(mc, key);
-			me->status = now + ap->negative_timeout;
-		}
+		cache_update_negative(mc, source, key, ap->negative_timeout);
 		cache_unlock(mc);
 		return NSS_STATUS_TRYAGAIN;
 	}
diff --git a/modules/lookup_ldap.c b/modules/lookup_ldap.c
index a59de92..26481a8 100644
--- a/modules/lookup_ldap.c
+++ b/modules/lookup_ldap.c
@@ -3011,18 +3011,8 @@ int lookup_mount(struct autofs_point *ap, const char *name, int name_len, void *
 	ret = ctxt->parse->parse_mount(ap, key, key_len,
 				       mapent, ctxt->parse->context);
 	if (ret) {
-		time_t now = time(NULL);
-		int rv = CHE_OK;
-
-		/* Record the the mount fail in the cache */
 		cache_writelock(mc);
-		me = cache_lookup_distinct(mc, key);
-		if (!me)
-			rv = cache_update(mc, source, key, NULL, now);
-		if (rv != CHE_FAIL) {
-			me = cache_lookup_distinct(mc, key);
-			me->status = now + ap->negative_timeout;
-		}
+		cache_update_negative(mc, source, key, ap->negative_timeout);
 		cache_unlock(mc);
 		return NSS_STATUS_TRYAGAIN;
 	}
diff --git a/modules/lookup_sss.c b/modules/lookup_sss.c
index 5c2ed0a..1fe740b 100644
--- a/modules/lookup_sss.c
+++ b/modules/lookup_sss.c
@@ -672,18 +672,8 @@ int lookup_mount(struct autofs_point *ap, const char *name, int name_len, void *
 	ret = ctxt->parse->parse_mount(ap, key, key_len,
 				       mapent, ctxt->parse->context);
 	if (ret) {
-		time_t now = time(NULL);
-		int rv = CHE_OK;
-
-		/* Record the the mount fail in the cache */
 		cache_writelock(mc);
-		me = cache_lookup_distinct(mc, key);
-		if (!me)
-			rv = cache_update(mc, source, key, NULL, now);
-		if (rv != CHE_FAIL) {
-			me = cache_lookup_distinct(mc, key);
-			me->status = now + ap->negative_timeout;
-		}
+		cache_update_negative(mc, source, key, ap->negative_timeout);
 		cache_unlock(mc);
 		return NSS_STATUS_TRYAGAIN;
 	}
diff --git a/modules/lookup_yp.c b/modules/lookup_yp.c
index a716e1f..e99e3c0 100644
--- a/modules/lookup_yp.c
+++ b/modules/lookup_yp.c
@@ -698,18 +698,10 @@ int lookup_mount(struct autofs_point *ap, const char *name, int name_len, void *
 		ret = ctxt->parse->parse_mount(ap, key, key_len,
 					       mapent, ctxt->parse->context);
 		if (ret) {
-			time_t now = time(NULL);
-			int rv = CHE_OK;
-
 			cache_writelock(mc);
-			me = cache_lookup_distinct(mc, key);
-			if (!me)
-				rv = cache_update(mc, source, key, NULL, now);
-			if (rv != CHE_FAIL) {
-				me = cache_lookup_distinct(mc, key);
-				me->status = now + ap->negative_timeout;
-			}
+			cache_update_negative(mc, source, key, ap->negative_timeout);
 			cache_unlock(mc);
+			return NSS_STATUS_TRYAGAIN;
 		}
 	 }