1 autofs-5.0.4 - code analysis corrections
3 From: Ian Kent <raven@themaw.net>
5 Several mistakes have been reported by Paul Wankadia <junyer@google.com>:
6 - a malloc(3) allocation return was not being checked in make_fullpath().
7 - a double free and a use after free was identified in lookup_prune_cache().
8 - off-by-one buffer overflow in lib/macros.c:macro_parse_globalvar().
9 - several potential buffer overflows in modules/parse_hesiod.c.
10 - double free in daemon/indirect.c:do_mount_autofs_indirect().
11 - bogus struct name used for sizeof in lib/cache.c:cache_init() and
12 lib/cache.c:cache_init_null_cache().
13 - in daemon/direct.c:handle_packet_expire_direct master_unlock_mutex() not
14 needed and mutexes not unlocked for file descriptor fail case.
15 - in modules/lookup_multi.c:lookup_init() struct module_info array not
16 checked before free for allocation failure case.
17 - in modules/lookup_program.c:lookup_mount() mapent not freed on cache update failure.
18 - in modules/mount_nfs.c allocation of mount location not checked.
19 - in modules/parse_sun.c:parse_mapent() mount location not freed on syntax error.
20 - in modules/parse_sun.c:parse_mount() mount location not freed on syntax error.
21 - in modules/parse_sun.c:parse_init() a malloc is not checked and the
22 handling of the fail case is poor.
23 - in lib/mounts.c:tree_make_mnt_tree() variable ent is not freed on ent->path
25 - in modules/replicated.c:add_host() NULL pointer dereference.
26 - add missing pthread_attr_destroy() in lib/alarm.c:alarm_start_handler().
27 - add missing pthread_attr_destroy() in daemon/state.c:st_start_handler().
28 - add missing fclose() in lib/defaults.c:*defaults_get_searchdns().
29 - add missing close()es in modules/mount_changer.c:swapCD().
32 daemon/direct.c | 6 ++-
33 daemon/indirect.c | 3 +-
34 daemon/lookup.c | 20 +++++-------
35 daemon/state.c | 6 ++-
41 modules/lookup_multi.c | 15 +++++----
42 modules/lookup_program.c | 4 ++
43 modules/mount_changer.c | 2 +
44 modules/mount_nfs.c | 5 +++
45 modules/parse_hesiod.c | 79 ++++++++++++++++++++++++++++++++++++++++------
46 modules/parse_sun.c | 18 ++++++----
47 modules/replicated.c | 2 +
48 16 files changed, 123 insertions(+), 55 deletions(-)
51 diff --git a/daemon/direct.c b/daemon/direct.c
52 index 2d979f1..fc3c969 100644
55 @@ -1088,7 +1088,6 @@ int handle_packet_expire_direct(struct autofs_point *ap, autofs_packet_expire_di
56 crit(ap->logopt, "can't find map entry for (%lu,%lu)",
57 (unsigned long) pkt->dev, (unsigned long) pkt->ino);
58 master_source_unlock(ap->entry);
59 - master_mutex_unlock();
60 pthread_setcancelstate(state, NULL);
63 @@ -1098,8 +1097,9 @@ int handle_packet_expire_direct(struct autofs_point *ap, autofs_packet_expire_di
65 ops->open(ap->logopt, &ioctlfd, me->dev, me->key);
67 - crit(ap->logopt, "can't open ioctlfd for %s",
69 + crit(ap->logopt, "can't open ioctlfd for %s", me->key);
71 + master_source_unlock(ap->entry);
72 pthread_setcancelstate(state, NULL);
75 diff --git a/daemon/indirect.c b/daemon/indirect.c
76 index 2ccbc53..f40c393 100644
77 --- a/daemon/indirect.c
78 +++ b/daemon/indirect.c
79 @@ -159,6 +159,7 @@ static int do_mount_autofs_indirect(struct autofs_point *ap, const char *root)
85 ret = stat(root, &st);
87 @@ -167,8 +168,6 @@ static int do_mount_autofs_indirect(struct autofs_point *ap, const char *root)
93 if (ops->open(ap->logopt, &ap->ioctlfd, st.st_dev, root)) {
95 "failed to create ioctl fd for autofs path %s", ap->path);
96 diff --git a/daemon/lookup.c b/daemon/lookup.c
97 index e034348..fd2ce55 100644
100 @@ -1001,12 +1001,16 @@ static char *make_fullpath(const char *root, const char *key)
108 l = strlen(key) + 1 + strlen(root) + 1;
114 sprintf(path, "%s/%s", root, key);
117 @@ -1076,10 +1080,6 @@ int lookup_prune_cache(struct autofs_point *ap, time_t age)
118 this = cache_lookup_distinct(mc, key);
128 @@ -1097,18 +1097,14 @@ int lookup_prune_cache(struct autofs_point *ap, time_t age)
135 - cache_readlock(mc);
140 - me = cache_lookup_distinct(mc, next_key);
142 + me = cache_lookup_distinct(mc, next_key);
149 pthread_cleanup_pop(1);
151 diff --git a/daemon/state.c b/daemon/state.c
152 index cd63be1..606743b 100644
155 @@ -1140,9 +1140,9 @@ int st_start_handler(void)
158 status = pthread_create(&thid, pattrs, st_queue_handler, NULL);
163 + pthread_attr_destroy(pattrs);
168 diff --git a/lib/alarm.c b/lib/alarm.c
169 index 1e32291..46df38a 100755
172 @@ -238,9 +238,9 @@ int alarm_start_handler(void)
175 status = pthread_create(&thid, pattrs, alarm_handler, NULL);
180 + pthread_attr_destroy(pattrs);
185 diff --git a/lib/cache.c b/lib/cache.c
186 index edb3192..4cb4582 100644
189 @@ -192,7 +192,7 @@ struct mapent_cache *cache_init(struct autofs_point *ap, struct map_source *map)
191 mc->size = defaults_get_map_hash_table_size();
193 - mc->hash = malloc(mc->size * sizeof(struct entry *));
194 + mc->hash = malloc(mc->size * sizeof(struct mapent *));
198 @@ -243,7 +243,7 @@ struct mapent_cache *cache_init_null_cache(struct master *master)
200 mc->size = NULL_MAP_HASHSIZE;
202 - mc->hash = malloc(mc->size * sizeof(struct entry *));
203 + mc->hash = malloc(mc->size * sizeof(struct mapent *));
207 diff --git a/lib/defaults.c b/lib/defaults.c
208 index 0d39716..e507a59 100644
211 @@ -565,6 +565,7 @@ struct ldap_searchdn *defaults_get_searchdns(void)
214 defaults_free_searchdns(sdn);
219 diff --git a/lib/macros.c b/lib/macros.c
220 index 85f9cd3..32b70bf 100644
223 @@ -165,7 +165,7 @@ int macro_parse_globalvar(const char *define)
224 char buf[MAX_MACRO_STRING];
227 - if (strlen(define) > MAX_MACRO_STRING)
228 + if (strlen(define) >= MAX_MACRO_STRING)
232 diff --git a/lib/mounts.c b/lib/mounts.c
233 index b98e1a4..08ca4e3 100644
236 @@ -257,10 +257,10 @@ struct mnt_list *get_mnt_list(const char *table, const char *path, int include)
247 ent->path = malloc(len + 1);
249 @@ -705,6 +705,7 @@ struct mnt_list *tree_make_mnt_tree(const char *table, const char *path)
250 ent->path = malloc(len + 1);
254 tree_free_mnt_tree(tree);
257 diff --git a/modules/lookup_multi.c b/modules/lookup_multi.c
258 index 1bf2e0a..6ec8434 100644
259 --- a/modules/lookup_multi.c
260 +++ b/modules/lookup_multi.c
261 @@ -212,14 +212,15 @@ nomem:
262 logerr(MODPREFIX "error: %s", estr);
265 - for (i = 0; i < ctxt->n; i++) {
266 - if (ctxt->m[i].mod)
267 - close_lookup(ctxt->m[i].mod);
268 - if (ctxt->m[i].argv)
269 - free_argv(ctxt->m[i].argc, ctxt->m[i].argv);
273 + for (i = 0; i < ctxt->n; i++) {
274 + if (ctxt->m[i].mod)
275 + close_lookup(ctxt->m[i].mod);
276 + if (ctxt->m[i].argv)
277 + free_argv(ctxt->m[i].argc, ctxt->m[i].argv);
284 diff --git a/modules/lookup_program.c b/modules/lookup_program.c
285 index 9878936..5b295a5 100644
286 --- a/modules/lookup_program.c
287 +++ b/modules/lookup_program.c
288 @@ -396,8 +396,10 @@ next:
290 ret = cache_update(mc, source, name, mapent, time(NULL));
292 - if (ret == CHE_FAIL)
293 + if (ret == CHE_FAIL) {
295 return NSS_STATUS_UNAVAIL;
298 debug(ap->logopt, MODPREFIX "%s -> %s", name, mapent);
300 diff --git a/modules/mount_changer.c b/modules/mount_changer.c
301 index 92bb72b..c30190d 100644
302 --- a/modules/mount_changer.c
303 +++ b/modules/mount_changer.c
304 @@ -162,6 +162,7 @@ int swapCD(const char *device, const char *slotName)
306 "Device %s is not an ATAPI compliant CD changer.",
312 @@ -169,6 +170,7 @@ int swapCD(const char *device, const char *slotName)
313 slot = ioctl(fd, CDROM_SELECT_DISC, slot);
315 logerr(MODPREFIX "CDROM_SELECT_DISC failed");
320 diff --git a/modules/mount_nfs.c b/modules/mount_nfs.c
321 index 20732f8..6f54f47 100644
322 --- a/modules/mount_nfs.c
323 +++ b/modules/mount_nfs.c
324 @@ -221,6 +221,11 @@ int mount_mount(struct autofs_point *ap, const char *root, const char *name, int
325 /* Not a local host - do an NFS mount */
327 loc = malloc(strlen(this->name) + 1 + strlen(this->path) + 1);
329 + char *estr = strerror_r(errno, buf, MAX_ERR_BUF);
330 + error(ap->logopt, "malloc: %s", estr);
333 strcpy(loc, this->name);
335 strcat(loc, this->path);
336 diff --git a/modules/parse_hesiod.c b/modules/parse_hesiod.c
337 index d5bb0f4..7a6a57d 100644
338 --- a/modules/parse_hesiod.c
339 +++ b/modules/parse_hesiod.c
340 @@ -46,6 +46,12 @@ static int parse_afs(struct autofs_point *ap,
342 /* Isolate the source for this AFS fs. */
343 for (i = 0; (!isspace(p[i]) && i < source_len); i++) {
345 + error(ap->logopt, MODPREFIX
346 + "unexpeced end of input looking for AFS "
353 @@ -56,8 +62,14 @@ static int parse_afs(struct autofs_point *ap,
354 while ((*p) && (isspace(*p)))
357 - /* Isolate the source for this AFS fs. */
358 + /* Isolate the options for this AFS fs. */
359 for (i = 0; (!isspace(p[i]) && i < options_len); i++) {
361 + error(ap->logopt, MODPREFIX
362 + "unexpeced end of input looking for AFS "
369 @@ -106,6 +118,12 @@ static int parse_nfs(struct autofs_point *ap,
371 /* Isolate the remote mountpoint for this NFS fs. */
372 for (i = 0; (!isspace(p[i]) && i < (int) sizeof(mount)); i++) {
374 + error(ap->logopt, MODPREFIX
375 + "unexpeced end of input looking for NFS "
376 + "mountpoint: %s", p);
382 @@ -118,15 +136,26 @@ static int parse_nfs(struct autofs_point *ap,
384 /* Isolate the remote host. */
385 for (i = 0; (!isspace(p[i]) && i < source_len); i++) {
387 + error(ap->logopt, MODPREFIX
388 + "unexpeced end of input looking for NFS "
398 + if (strlen(source) + strlen(mount) + 2 > source_len) {
399 + error(ap->logopt, MODPREFIX "entry too log for mount source");
403 /* Append ":mountpoint" to the source to get "host:mountpoint". */
404 - strncat(source, ":", source_len);
405 - strncat(source, mount, source_len);
406 + strcat(source, ":");
407 + strcat(source, mount);
409 /* Skip whitespace. */
410 while ((*p) && (isspace(*p)))
411 @@ -134,6 +163,12 @@ static int parse_nfs(struct autofs_point *ap,
413 /* Isolate the mount options. */
414 for (i = 0; (!isspace(p[i]) && i < options_len); i++) {
416 + error(ap->logopt, MODPREFIX
417 + "unexpeced end of input looking for NFS "
418 + "mount options: %s", p);
424 @@ -178,6 +213,12 @@ static int parse_generic(struct autofs_point *ap,
426 /* Isolate the source for this fs. */
427 for (i = 0; (!isspace(p[i]) && i < source_len); i++) {
429 + error(ap->logopt, MODPREFIX
430 + "unexpeced end of input looking for generic "
431 + "mount source: %s", p);
437 @@ -190,6 +231,12 @@ static int parse_generic(struct autofs_point *ap,
439 /* Isolate the mount options. */
440 for (i = 0; (!isspace(p[i]) && i < options_len); i++) {
442 + error(ap->logopt, MODPREFIX
443 + "unexpeced end of input looking for generic "
444 + "mount options: %s", p);
450 @@ -227,6 +274,7 @@ int parse_mount(struct autofs_point *ap, const char *name,
451 char options[HESIOD_LEN + 1];
456 ap->entry->current = NULL;
457 master_source_current_signal(ap->entry);
458 @@ -250,19 +298,28 @@ int parse_mount(struct autofs_point *ap, const char *name,
460 /* If it's an AFS fs... */
461 } else if (!strcasecmp(fstype, "afs"))
462 - parse_afs(ap, mapent, name, name_len,
463 - source, sizeof(source), options, sizeof(options));
464 + ret = parse_afs(ap, mapent, name, name_len,
465 + source, sizeof(source), options,
468 else if (!strcasecmp(fstype, "nfs"))
469 - parse_nfs(ap, mapent, name, name_len,
470 - source, sizeof(source), options, sizeof(options));
471 + ret = parse_nfs(ap, mapent, name, name_len,
472 + source, sizeof(source), options,
476 - parse_generic(ap, mapent, name, name_len, source, sizeof(source),
477 - options, sizeof(options));
478 + ret = parse_generic(ap, mapent, name, name_len,
479 + source, sizeof(source), options,
483 - MODPREFIX "mount %s is type %s from %s", name, fstype, source);
485 + error(ap->logopt, MODPREFIX "failed to parse entry");
489 + MODPREFIX "mount %s is type %s from %s",
490 + name, fstype, source);
493 return do_mount(ap, ap->path, name, name_len, source, fstype, options);
495 diff --git a/modules/parse_sun.c b/modules/parse_sun.c
496 index 72e51e2..ed73e46 100644
497 --- a/modules/parse_sun.c
498 +++ b/modules/parse_sun.c
499 @@ -379,15 +379,17 @@ int parse_init(int argc, const char *const *argv, void **context)
502 (char *) realloc(ctxt->optstr, optlen + len + 2);
505 - noptstr[optlen] = ',';
506 - strcpy(noptstr + optlen + 1, argv[i] + offset);
509 + noptstr[optlen] = ',';
510 + strcpy(noptstr + optlen + 1, argv[i] + offset);
514 noptstr = (char *) malloc(len + 1);
515 - strcpy(noptstr, argv[i] + offset);
518 + strcpy(noptstr, argv[i] + offset);
523 char *estr = strerror_r(errno, buf, MAX_ERR_BUF);
524 @@ -895,6 +897,7 @@ static int parse_mapent(const char *ent, char *g_options, char **options, char *
526 warn(logopt, MODPREFIX "error location begins with \"/\"");
532 @@ -1636,6 +1639,7 @@ int parse_mount(struct autofs_point *ap, const char *name,
533 /* Location can't begin with a '/' */
538 MODPREFIX "error location begins with \"/\"");
540 diff --git a/modules/replicated.c b/modules/replicated.c
541 index 63829a2..835af97 100644
542 --- a/modules/replicated.c
543 +++ b/modules/replicated.c
544 @@ -304,7 +304,7 @@ static int add_host(struct host **list, struct host *host)
546 struct host *this, *last;