autofs-5.1.0 - fix incorrect check in parse_mount()
From: Ian Kent <ikent@redhat.com>
The change to allow the use of the hosts map in map entries introduced
an invalid check into parse_mount(). The case attempts to check the
contents of an options string that is always invalid for the return
value case in which it is checked, not to mention the check itself is
incorrect.
---
CHANGELOG | 1
modules/parse_sun.c | 70 ++++++++++++++++++++++++++++++++--------------------
2 files changed, 45 insertions(+), 26 deletions(-)
--- autofs-5.0.7.orig/CHANGELOG
+++ autofs-5.0.7/CHANGELOG
@@ -164,6 +164,7 @@
- dont add wildcard to negative cache.
- add a prefix to program map stdvars.
- add config option to force use of program map stdvars.
+- fix incorrect check in parse_mount().
25/07/2012 autofs-5.0.7
=======================
--- autofs-5.0.7.orig/modules/parse_sun.c
+++ autofs-5.0.7/modules/parse_sun.c
@@ -756,6 +756,8 @@ update_offset_entry(struct autofs_point
mc = source->mc;
+ memset(m_mapent, 0, MAPENT_MAX_LEN + 1);
+
/* Internal hosts map may have loc == NULL */
if (!*path) {
error(ap->logopt,
@@ -782,7 +784,7 @@ update_offset_entry(struct autofs_point
if (*myoptions)
m_options_len = strlen(myoptions) + 2;
- m_mapent_len = strlen(loc);
+ m_mapent_len = loc ? strlen(loc) : 0;
if (m_mapent_len + m_options_len > MAPENT_MAX_LEN) {
error(ap->logopt, MODPREFIX "multi mount mapent too long");
return CHE_FAIL;
@@ -793,10 +795,13 @@ update_offset_entry(struct autofs_point
strcat(m_mapent, myoptions);
if (loc) {
strcat(m_mapent, " ");
- strcat(m_mapent, loc);
+ if (loc)
+ strcat(m_mapent, loc);
}
- } else
- strcpy(m_mapent, loc);
+ } else {
+ if (loc)
+ strcpy(m_mapent, loc);
+ }
ret = cache_update_offset(mc, name, m_key, m_mapent, age);
if (ret == CHE_DUPLICATE)
@@ -923,9 +928,15 @@ static int parse_mapent(const char *ent,
l = chunklen(p, check_colon(p));
loc = dequote(p, l, logopt);
if (!loc) {
- warn(logopt, MODPREFIX "possible missing location");
- free(myoptions);
- return 0;
+ if (strstr(myoptions, "fstype=autofs") &&
+ strstr(myoptions, "hosts")) {
+ warn(logopt, MODPREFIX "possible missing location");
+ free(myoptions);
+ return 0;
+ }
+ *options = myoptions;
+ *location = NULL;
+ return (p - ent);
}
/* Location can't begin with a '/' */
@@ -953,10 +964,15 @@ static int parse_mapent(const char *ent,
l = chunklen(p, check_colon(p));
ent_chunk = dequote(p, l, logopt);
if (!ent_chunk) {
- warn(logopt, MODPREFIX "null location or out of memory");
- free(myoptions);
- free(loc);
- return 0;
+ if (strstr(myoptions, "fstype=autofs") &&
+ strstr(myoptions, "hosts")) {
+ warn(logopt, MODPREFIX
+ "null location or out of memory");
+ free(myoptions);
+ free(loc);
+ return 0;
+ }
+ goto next;
}
/* Location can't begin with a '/' */
@@ -992,7 +1008,7 @@ static int parse_mapent(const char *ent,
strcat(loc, ent_chunk);
free(ent_chunk);
-
+next:
p += l;
p = skipspace(p);
}
@@ -1093,7 +1109,9 @@ static int mount_subtree(struct autofs_p
cache_delete_offset_list(me->mc, name);
return 1;
}
- ro_len = strlen(ro_loc);
+ ro_len = 0;
+ if (ro_loc)
+ ro_len = strlen(ro_loc);
tmp = alloca(mnt_root_len + 2);
strcpy(tmp, mnt_root);
@@ -1104,7 +1122,8 @@ static int mount_subtree(struct autofs_p
rv = sun_mount(ap, root, name, namelen, ro_loc, ro_len, myoptions, ctxt);
free(myoptions);
- free(ro_loc);
+ if (ro_loc)
+ free(ro_loc);
}
if (ro && rv == 0) {
@@ -1420,16 +1439,13 @@ int parse_mount(struct autofs_point *ap,
l = parse_mapent(p, options, &myoptions, &loc, ap->logopt);
if (!l) {
- if (!(strstr(myoptions, "fstype=autofs") &&
- strstr(myoptions, "hosts"))) {
- cache_delete_offset_list(mc, name);
- cache_multi_unlock(me);
- cache_unlock(mc);
- free(path);
- free(options);
- pthread_setcancelstate(cur_state, NULL);
- return 1;
- }
+ cache_delete_offset_list(mc, name);
+ cache_multi_unlock(me);
+ cache_unlock(mc);
+ free(path);
+ free(options);
+ pthread_setcancelstate(cur_state, NULL);
+ return 1;
}
p += l;
@@ -1450,12 +1466,14 @@ int parse_mount(struct autofs_point *ap,
free(path);
free(options);
free(myoptions);
- free(loc);
+ if (loc)
+ free(loc);
pthread_setcancelstate(cur_state, NULL);
return 1;
}
- free(loc);
+ if (loc)
+ free(loc);
free(path);
free(myoptions);
} while (*p == '/' || (*p == '"' && *(p + 1) == '/'));