Hello,
A customer reported a segmentation fault in automount (one occurrence
so far, but we have a core dump). More information about the exact
autofs version and included patches below.
Call trace:
Thread 7 (Thread 4254):
#0 do_sigwait (set=0x7fff9eb877c0, sig=0x7fff9eb878dc)
at ../sysdeps/unix/sysv/linux/sigwait.c:65
#1 __sigwait (set=0x7fff9eb877c0, sig=0x7fff9eb878dc)
at ../sysdeps/unix/sysv/linux/sigwait.c:100
#2 statemachine (argc=<value optimized out>,
argv=<value optimized out>) at automount.c:1327
#3 main (argc=<value optimized out>, argv=<value optimized out>)
at automount.c:2142
Thread 6 (Thread 4255):
#0 pthread_cond_timedwait@@GLIBC_2.3.2 () from /lib64/libpthread.so.0
#1 alarm_handler (arg=<value optimized out>) at alarm.c:206
#2 start_thread (arg=<value optimized out>) at pthread_create.c:306
#3 clone () from /lib64/libc.so.6
Thread 5 (Thread 4256):
#0 pthread_cond_wait@@GLIBC_2.3.2 () from /lib64/libpthread.so.0
#1 st_queue_handler (arg=<value optimized out>) at state.c:1103
#2 start_thread (arg=<value optimized out>) at pthread_create.c:306
#3 clone () from /lib64/libc.so.6
Thread 4 (Thread 4259):
#0 __poll (fds=0x40822150, nfds=3, timeout=-1)
at ../sysdeps/unix/sysv/linux/poll.c:87
#1 get_pkt (arg=<value optimized out>) at automount.c:882
#2 handle_packet (arg=<value optimized out>) at automount.c:1019
#3 handle_mounts (arg=<value optimized out>) at automount.c:1551
#4 start_thread (arg=<value optimized out>) at pthread_create.c:306
#5 clone () from /lib64/libc.so.6
Thread 3 (Thread 4262):
#0 __poll (fds=0x41023150, nfds=3, timeout=-1)
at ../sysdeps/unix/sysv/linux/poll.c:87
#1 get_pkt (arg=<value optimized out>) at automount.c:882
#2 handle_packet (arg=<value optimized out>) at automount.c:1019
#3 handle_mounts (arg=<value optimized out>) at automount.c:1551
#4 start_thread (arg=<value optimized out>) at pthread_create.c:306
#5 clone () from /lib64/libc.so.6
Thread 2 (Thread 4263):
#0 __poll (fds=0x41824150, nfds=3, timeout=-1)
at ../sysdeps/unix/sysv/linux/poll.c:87
#1 get_pkt (arg=<value optimized out>) at automount.c:882
#2 handle_packet (arg=<value optimized out>) at automount.c:1019
#3 handle_mounts (arg=<value optimized out>) at automount.c:1551
#4 start_thread (arg=<value optimized out>) at pthread_create.c:306
#5 clone () from /lib64/libc.so.6
Thread 1 (Thread 18996):
#0 __libc_free (mem=0x5555556a0498) at malloc.c:3461
#1 ber_free_buf (ber=0x5555556a0460) at io.c:177
#2 ber_free (ber=0x5555556a0460, freebuf=0) at io.c:196
#3 ldap_msgfree (lm=0x555555e4ddc0) at result.c:1151
#4 read_one_map (ap=0x55555569c120, age=1311189199,
context=0x5555556a0040) at lookup_ldap.c:2341
#5 lookup_read_map (ap=0x55555569c120, age=1311189199, context=0x5555556a0040)
at lookup_ldap.c:2361
#6 do_read_map (ap=0x55555569c120, map=0x55555568d1c0,
age=1311189199) at lookup.c:296
#7 read_source_instance (this=<value optimized out>,
ap=0x55555569c120, map=0x55555569c220, age=1311189199) at lookup.c:374
#8 read_map_source (this=<value optimized out>, ap=0x55555569c120,
map=0x55555569c220, age=1311189199) at lookup.c:393
#9 lookup_nss_read_map (ap=0x55555569c120,
source=<value optimized out>, age=1311189199) at lookup.c:534
#10 do_readmap (arg=<value optimized out>) at state.c:463
#11 start_thread (arg=<value optimized out>) at pthread_create.c:306
#12 clone () from /lib64/libc.so.6
The crash happens because we're passing an invalid (already freed?)
LDAPMessage structure to ldap_msgfree() in read_one_map():
static int read_one_map(struct autofs_point *ap,
struct lookup_context *ctxt,
time_t age, int *result_ldap)
{
(...)
rv = do_get_entries(&sp, source, ctxt);
if (rv != LDAP_SUCCESS) {
ldap_msgfree(sp.result);
unbind_ldap_connection(ap->logopt, sp.ldap, ctxt);
*result_ldap = rv;
free(sp.query);
return NSS_STATUS_NOTFOUND;
}
ldap_msgfree(sp.result); <===
} while (sp.morePages == TRUE);
(gdb) frame 4
#4 0x00002aaaaaab8c74 in read_one_map (ap=0x55555569c120, age=1311189199,
context=0x5555556a0040) at lookup_ldap.c:2341
2341 ldap_msgfree(sp.result);
(gdb) print sp
$1 = {ap = 0x55555569c120, ldap = 0x555555769c10, query = 0x55555569ef00
"(objectclass=automount)", attrs = 0x41a25c80, cookie = 0x0, pageSize = 2000,
morePages = 0, totalCount = 0, result = 0x5555556a8e40, age = 1311189199}
I'm staring at the code for some time now, and still can't figure out how
that could happen. Is it somehow possible that do_get_entries() return
LDAP_SUCCESS but keep an invalid/outdated query result in sp.result?
I'd also like to suggest the patch below. I believe it can potentially
avoid the crash.
Thanks,
Leonardo
AutoFS version is 5.0.5 plus all upstream patches up and including
autofs-5.0.5-fix-submount-shutdown-wait.patch plus these assorted
bug fixes:
autofs-5.0.5-auto-adjust-ldap-page-size.patch
autofs-5.0.5-replace-gplv3-code.patch
autofs-5.0.5-fix-paged-ldap-map-read.patch
autofs-5.0.5-fix-next-task-list-update.patch
autofs-5.0.5-fix-stale-map-read.patch
autofs-5.0.5-fix-out-of-order-locking-in-readmap.patch
autofs-5.0.5-remove-master_mutex_unlock-leftover.patch
autofs-5.0.5-fix-null-cache-deadlock.patch
Index: autofs/modules/lookup_ldap.c
===================================================================
--- autofs.orig/modules/lookup_ldap.c
+++ autofs/modules/lookup_ldap.c
@@ -361,6 +361,7 @@ static int get_query_dn(unsigned logopt,
MODPREFIX "query succeeded, no matches for %s",
query);
ldap_msgfree(result);
+ result = NULL;
free(query);
return 0;
}
@@ -1583,6 +1584,7 @@ int lookup_read_master(struct master *ma
MODPREFIX "query succeeded, no matches for %s",
query);
ldap_msgfree(result);
+ result = NULL;
unbind_ldap_connection(logging, ldap, ctxt);
free(query);
return NSS_STATUS_NOTFOUND;
@@ -2380,8 +2382,8 @@ static int read_one_map(struct autofs_po
if (rv == LDAP_ADMINLIMIT_EXCEEDED ||
rv == LDAP_SIZELIMIT_EXCEEDED) {
- if (sp.result)
- ldap_msgfree(sp.result);
+ ldap_msgfree(sp.result);
+ sp.result = NULL;
sp.pageSize = sp.pageSize / 2;
if (sp.pageSize < 5) {
debug(ap->logopt, MODPREFIX
@@ -2404,12 +2406,14 @@ static int read_one_map(struct autofs_po
rv = do_get_entries(&sp, source, ctxt);
if (rv != LDAP_SUCCESS) {
ldap_msgfree(sp.result);
+ sp.result = NULL;
unbind_ldap_connection(ap->logopt, sp.ldap, ctxt);
*result_ldap = rv;
free(sp.query);
return NSS_STATUS_NOTFOUND;
}
ldap_msgfree(sp.result);
+ sp.result = NULL;
} while (sp.morePages == TRUE);
debug(ap->logopt, MODPREFIX "done updating map");
@@ -2582,6 +2586,7 @@ static int lookup_one(struct autofs_poin
debug(ap->logopt,
MODPREFIX "got answer, but no entry for %s", query);
ldap_msgfree(result);
+ result = NULL;
unbind_ldap_connection(ap->logopt, ldap, ctxt);
free(query);
return CHE_MISSING;
@@ -2768,6 +2773,7 @@ next:
}
ldap_msgfree(result);
+ result = NULL;
unbind_ldap_connection(ap->logopt, ldap, ctxt);
/* Failed to find wild entry, update cache if needed */
_______________________________________________
autofs mailing list
[email protected]
http://linux.kernel.org/mailman/listinfo/autofs