Follow @Openwall on Twitter for new release announcements and other news
[<prev] [next>] [<thread-prev] [thread-next>] [day] [month] [year] [list]
Date: Thu, 28 Feb 2019 23:01:29 +0100
From: Sebastian Kemper <sebastian_ml@....net>
To: musl@...ts.openwall.com
Cc: Szabolcs Nagy <nsz@...t70.net>
Subject: Re: Asterisk 16 segmentation fault

On Thu, Feb 28, 2019 at 10:19:02PM +0100, Szabolcs Nagy wrote:
> * Sebastian Kemper <sebastian_ml@....net> [2019-02-28 21:27:51 +0100]:
> > I'm not a programmer so I have problems making sense of this. So I'm
> > hoping that maybe one of you can shine a light.
> 
> it means dlerror() returned 0 and ast_strdupa calls strlen on
> this return value which segfaults as expected.
> 
> it is entirely valid for dlerror() to return 0 if there was no
> error. did the dlopen("res_pjproject.so", flags) call succeed?
> i.e. mod->lib != 0 ?.

Hello Szabolcs,

Thanks for your reply. And thanks to Rich & Jeffrey as well, of course.
Again I'm blown away by how fast one gets a reply on the musl list :-)

I stepped through it again and tried to get the value of mod->lib:

952		if (resource_being_loaded) {
(gdb) step
951		mod->lib = dlopen(filename, flags);
(gdb) step
952		if (resource_being_loaded) {
(gdb) p mod->lib
$10 = (void *) 0x5fc210
(gdb) p mod->lib
$11 = (void *) 0x5fc210
(gdb) p mod->lib
$12 = (void *) 0x5fc210
(gdb) p mod->lib
$13 = (void *) 0x5fc210
(gdb) p (*mod).lib
$14 = (void *) 0x5fc210
(gdb) p (*mod).li
There is no member named li.
(gdb) p (*mod).lib
$15 = (void *) 0x5fc210
(gdb) step
955			const char *dlerror_msg = ast_strdupa(dlerror());
(gdb) step

Thread 1 "asterisk" received signal SIGSEGV, Segmentation fault.
strlen (s=0x0, s@...ry=0x48d79d <load_dynamic_module+120> "\t\360\"\223\f\234\200\353\216#\005\032\240z\364e") at src/string/strlen.c:17
17		for (w = (const void *)s; !HASZERO(*w); w++);
(gdb)

So if I'm not mistaken mod->lib is indeed != 0.

> e.g. the segfault can be avoided by
> 
> -                     const char *dlerror_msg = ast_strdupa(dlerror());
> +                     const char *dlerror_msg = dlerror(); dlerror_msg = ast_strdupa(dlerror_msg ? dlerror_msg : "");
> 
> but we would need to know what this code is trying to do
> (and how it worked before) for a proper fix.

astmm.h defines ast_strdupa() like this:

#if !defined(ast_strdupa) && defined(__GNUC__)
/*!
 * \brief duplicate a string in memory from the stack
 * \param s The string to duplicate
 *
 * This macro will duplicate the given string.  It returns a pointer to the stack
 * allocatted memory for the new string.
 */
#define ast_strdupa(s)                                                    \
        (__extension__                                                    \
        ({                                                                \
                const char *__old = (s);                                  \
                size_t __len = strlen(__old) + 1;                         \
                char *__new = __builtin_alloca(__len);                    \
                memcpy (__new, __old, __len);                             \
                __new;                                                    \
        }))
#endif

This define is the same in both Asterisk 15 and 16 (the define only has
moved from include/asterisk/utils.h to include/asterisk/astmm.h).

The 'static struct ast_module *load_dlopen()' in which it's used has
changed, though, between Asterisk 15 and 16:

@@ -569,13 +950,60 @@
        resource_being_loaded = mod;
        mod->lib = dlopen(filename, flags);
        if (resource_being_loaded) {
+               struct ast_str *list;
+               int c = 0;
+               const char *dlerror_msg = ast_strdupa(dlerror());
+
                resource_being_loaded = NULL;
                if (mod->lib) {
-                       ast_log(LOG_ERROR, "Module '%s' did not register itself during load\n", resource_in);
+                       module_load_error("Module '%s' did not register itself during load\n", resource_in);
                        logged_dlclose(resource_in, mod->lib);
-               } else if (!suppress_logging) {
-                       ast_log(LOG_WARNING, "Error loading module '%s': %s\n", resource_in, dlerror());
+
+                       goto error_return;
+               }
+
+               if (suppress_logging) {
+                       goto error_return;
                }
+
+               resource_being_loaded = mod;
+               mod->lib = dlopen(filename, RTLD_LAZY | RTLD_LOCAL);
+               if (resource_being_loaded) {
+                       resource_being_loaded = NULL;
+
+                       module_load_error("Error loading module '%s': %s\n", resource_in, dlerror_msg);
+                       logged_dlclose(resource_in, mod->lib);
+
+                       goto error_return;
+               }
+
+               list = ast_str_create(64);
+               if (list) {
+                       if (module_post_register(mod)) {
+                               goto loaded_error;
+                       }
+
+                       c = load_dlopen_missing(&list, &mod->requires);
+                       c += load_dlopen_missing(&list, &mod->enhances);
+#ifndef OPTIONAL_API
+                       c += load_dlopen_missing(&list, &mod->optional_modules);
+#endif
+               }
+
+               if (list && ast_str_strlen(list)) {
+                       module_load_error("Error loading module '%s', missing %s: %s\n",
+                               resource_in, c == 1 ? "dependency" : "dependencies", ast_str_buffer(list));
+               } else {
+                       module_load_error("Error loading module '%s': %s\n", resource_in, dlerror_msg);
+               }
+
+loaded_error:
+               ast_free(list);
+               unload_dynamic_module(mod);
+
+               return NULL;
+
+error_return:
                ast_free(mod);

                return NULL;
@@ -584,12 +1012,11 @@

So 'const char *dlerror_msg' seems to only be used for logging purposes.
Should I give the proposed change a spin?

I'm off to bed now. I would get back to you tomorrow evening.

Again thank you all, much appreciated!

With kind regards,
Seb

Powered by blists - more mailing lists

Confused about mailing lists and their use? Read about mailing lists on Wikipedia and check out these guidelines on proper formatting of your messages.