[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
Re: [PATCH v3 1/1] audio/jack: fix use after free segfault
From: |
Philippe Mathieu-Daudé |
Subject: |
Re: [PATCH v3 1/1] audio/jack: fix use after free segfault |
Date: |
Wed, 19 Aug 2020 05:32:42 +0200 |
User-agent: |
Mozilla/5.0 (X11; Linux x86_64; rv:68.0) Gecko/20100101 Thunderbird/68.11.0 |
Hi Geoffrey,
On 8/19/20 3:18 AM, Geoffrey McRae wrote:
> The client may have been freed already by a secondary audio device
> recovering its session as JACK2 has some cleanup code to work around
> broken clients, which doesn't account for well behaved clients.
>
> https://github.com/jackaudio/jack2/issues/627
>
> As JACK1 and JACK2 are interchangeable and JACK2 has "cleanup" routine
> that JACK1 does not have, we need to determine which version is in use
> at runtime. Unfortunatly there is no way to determine which is in use
> other then to look for symbols that are missing in JACK1, which in this
> case is `jack_get_version`.
>
> An issue has been raised over this, but to be compatible with older
> versions we must use this method to determine which library is in use.
> If at some time the jack developers implement `jack_get_version` in
> JACK1, this code will need to be revisited.
>
> At worst the workaround will be enabled and this will introduce a small
> memory leak if the jack server is restarted. This however is better then
> the alternative which would be a use after free segfault.
>
> Signed-off-by: Geoffrey McRae <geoff@hostfission.com>
> ---
> audio/jackaudio.c | 37 ++++++++++++++++++++++++++++++++++++-
> configure | 4 +++-
> 2 files changed, 39 insertions(+), 2 deletions(-)
>
> diff --git a/audio/jackaudio.c b/audio/jackaudio.c
> index 72ed7c4929..d1685999c3 100644
> --- a/audio/jackaudio.c
> +++ b/audio/jackaudio.c
> @@ -31,6 +31,7 @@
> #define AUDIO_CAP "jack"
> #include "audio_int.h"
>
> +#include <dlfcn.h>
> #include <jack/jack.h>
> #include <jack/thread.h>
>
> @@ -84,6 +85,7 @@ typedef struct QJackIn {
> }
> QJackIn;
>
> +static int QJackWorkaroundCloseBug;
> static int qjack_client_init(QJackClient *c);
> static void qjack_client_connect_ports(QJackClient *c);
> static void qjack_client_fini(QJackClient *c);
> @@ -563,7 +565,10 @@ static void qjack_client_fini(QJackClient *c)
> /* fallthrough */
>
> case QJACK_STATE_SHUTDOWN:
> - jack_client_close(c->client);
> + if (!QJackWorkaroundCloseBug) {
> + jack_client_close(c->client);
> + }
> + c->client = NULL;
> /* fallthrough */
>
> case QJACK_STATE_DISCONNECTED:
> @@ -662,6 +667,36 @@ static void qjack_info(const char *msg)
>
> static void register_audio_jack(void)
> {
> + void *handle;
> +
> + /*
> + * As JACK1 and JACK2 are interchangeable and JACK2 has "cleanup" routine
> + * that JACK1 does not have, we need to determine which version is in
> use at
> + * runtime. Unfortunatly there is no way to determine which is in use
> other
> + * then to look for symbols that are missing in JACK1, which in this
> case is
> + * `jack_get_version`. An issue has been raised over this, but to be
> + * compatible with older versions we must use this method to determine
> which
> + * library is in use. If at some time the jack developers implement
> + * `jack_get_version` in JACK1, this code will need to be revisited.
> + *
> + * At worst the workaround will be enabled and we will introduce a small
> + * memory leak if the jack server is restarted. This is better then the
> + * alternative which would be a use after free segfault.
> + */
> +
> + handle = dlopen("libjack.so", RTLD_LAZY | RTLD_NOLOAD);
> + if (!handle) {
> + dolog("unable to open libjack.so to determine version\n");
> + dolog("assuming JACK2 and enabling the close bug workaround\n");
> + QJackWorkaroundCloseBug = 1;
> + } else {
> + if (dlsym(handle, "jack_get_version")) {
> + dolog("JACK2 detected, enabling close bug workaround\n");
> + QJackWorkaroundCloseBug = 1;
> + }
> + dlclose(handle);
> + }
> +
> audio_driver_register(&jack_driver);
> jack_set_thread_creator(qjack_thread_creator);
> jack_set_error_function(qjack_error);
> diff --git a/configure b/configure
> index 2acc4d1465..43d2893fbb 100755
> --- a/configure
> +++ b/configure
> @@ -3754,7 +3754,8 @@ for drv in $audio_drv_list; do
>
> jack | try-jack)
> if $pkg_config jack --exists; then
> - jack_libs=$($pkg_config jack --libs)
> + # dl is needed to check at runtime if jack1 or jack2 is in use
> + jack_libs="$($pkg_config jack --libs) -ldl"
> if test "$drv" = "try-jack"; then
> audio_drv_list=$(echo "$audio_drv_list" | sed -e
> 's/try-jack/jack/')
> fi
Why not checking jack_get_version() using compile_prog here?
Thanks,
Phil.