autofs-5.1.0 - fix incorrect check in parse_mount() From: Ian Kent 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) == '/'));