From: Christian Schoenebeck <qemu_oss@crudebyte.com>
To: qemu-devel@nongnu.org
Cc: Geoffrey McRae <geoff@hostfission.com>,
kraxel@redhat.com, pbonzini@redhat.com
Subject: Re: [PATCH v10 1/1] audio/jack: fix use after free segfault
Date: Sun, 08 Nov 2020 12:09:59 +0100 [thread overview]
Message-ID: <4202934.l4obcem48q@silver> (raw)
In-Reply-To: <20201108063351.35804-2-geoff@hostfission.com>
On Sonntag, 8. November 2020 07:33:50 CET Geoffrey McRae wrote:
> This change registers a bottom handler to close the JACK client
> connection when a server shutdown signal is received. Without this
> libjack2 attempts to "clean up" old clients and causes a use after free
> segfault.
>
> Signed-off-by: Geoffrey McRae <geoff@hostfission.com>
Reviewed-by: Christian Schoenebeck <qemu_oss@crudebyte.com>
Gerd, I think it would be Ok to queue this as fix for 5.2.
> ---
> audio/jackaudio.c | 50 +++++++++++++++++++++++++++++++++++------------
> 1 file changed, 37 insertions(+), 13 deletions(-)
>
> diff --git a/audio/jackaudio.c b/audio/jackaudio.c
> index 1e714b30bc..3b7c18443d 100644
> --- a/audio/jackaudio.c
> +++ b/audio/jackaudio.c
> @@ -25,6 +25,7 @@
> #include "qemu/osdep.h"
> #include "qemu/module.h"
> #include "qemu/atomic.h"
> +#include "qemu/main-loop.h"
> #include "qemu-common.h"
> #include "audio.h"
>
> @@ -63,6 +64,7 @@ typedef struct QJackClient {
> QJackState state;
> jack_client_t *client;
> jack_nframes_t freq;
> + QEMUBH *shutdown_bh;
>
> struct QJack *j;
> int nchannels;
> @@ -87,6 +89,7 @@ QJackIn;
> static int qjack_client_init(QJackClient *c);
> static void qjack_client_connect_ports(QJackClient *c);
> static void qjack_client_fini(QJackClient *c);
> +static QemuMutex qjack_shutdown_lock;
>
> static void qjack_buffer_create(QJackBuffer *buffer, int channels, int
> frames) {
> @@ -306,21 +309,27 @@ static int qjack_xrun(void *arg)
> return 0;
> }
>
> +static void qjack_shutdown_bh(void *opaque)
> +{
> + QJackClient *c = (QJackClient *)opaque;
> + qjack_client_fini(c);
> +}
> +
> static void qjack_shutdown(void *arg)
> {
> QJackClient *c = (QJackClient *)arg;
> c->state = QJACK_STATE_SHUTDOWN;
> + qemu_bh_schedule(c->shutdown_bh);
> }
>
> static void qjack_client_recover(QJackClient *c)
> {
> - if (c->state == QJACK_STATE_SHUTDOWN) {
> - qjack_client_fini(c);
> + if (c->state != QJACK_STATE_DISCONNECTED) {
> + return;
> }
>
> /* packets is used simply to throttle this */
> - if (c->state == QJACK_STATE_DISCONNECTED &&
> - c->packets % 100 == 0) {
> + if (c->packets % 100 == 0) {
>
> /* if enabled then attempt to recover */
> if (c->enabled) {
> @@ -489,15 +498,16 @@ static int qjack_init_out(HWVoiceOut *hw, struct
> audsettings *as, QJackOut *jo = (QJackOut *)hw;
> Audiodev *dev = (Audiodev *)drv_opaque;
>
> - qjack_client_fini(&jo->c);
> -
> jo->c.out = true;
> jo->c.enabled = false;
> jo->c.nchannels = as->nchannels;
> jo->c.opt = dev->u.jack.out;
>
> + jo->c.shutdown_bh = qemu_bh_new(qjack_shutdown_bh, &jo->c);
> +
> int ret = qjack_client_init(&jo->c);
> if (ret != 0) {
> + qemu_bh_delete(jo->c.shutdown_bh);
> return ret;
> }
>
> @@ -525,15 +535,16 @@ static int qjack_init_in(HWVoiceIn *hw, struct
> audsettings *as, QJackIn *ji = (QJackIn *)hw;
> Audiodev *dev = (Audiodev *)drv_opaque;
>
> - qjack_client_fini(&ji->c);
> -
> ji->c.out = false;
> ji->c.enabled = false;
> ji->c.nchannels = as->nchannels;
> ji->c.opt = dev->u.jack.in;
>
> + ji->c.shutdown_bh = qemu_bh_new(qjack_shutdown_bh, &ji->c);
> +
> int ret = qjack_client_init(&ji->c);
> if (ret != 0) {
> + qemu_bh_delete(ji->c.shutdown_bh);
> return ret;
> }
>
> @@ -555,7 +566,7 @@ static int qjack_init_in(HWVoiceIn *hw, struct
> audsettings *as, return 0;
> }
>
> -static void qjack_client_fini(QJackClient *c)
> +static void qjack_client_fini_locked(QJackClient *c)
> {
> switch (c->state) {
> case QJACK_STATE_RUNNING:
> @@ -564,28 +575,40 @@ static void qjack_client_fini(QJackClient *c)
>
> case QJACK_STATE_SHUTDOWN:
> jack_client_close(c->client);
> + c->client = NULL;
> +
> + qjack_buffer_free(&c->fifo);
> + g_free(c->port);
> +
> + c->state = QJACK_STATE_DISCONNECTED;
> /* fallthrough */
>
> case QJACK_STATE_DISCONNECTED:
> break;
> }
> +}
>
> - qjack_buffer_free(&c->fifo);
> - g_free(c->port);
> -
> - c->state = QJACK_STATE_DISCONNECTED;
> +static void qjack_client_fini(QJackClient *c)
> +{
> + qemu_mutex_lock(&qjack_shutdown_lock);
> + qjack_client_fini_locked(c);
> + qemu_mutex_unlock(&qjack_shutdown_lock);
> }
>
> static void qjack_fini_out(HWVoiceOut *hw)
> {
> QJackOut *jo = (QJackOut *)hw;
> qjack_client_fini(&jo->c);
> +
> + qemu_bh_delete(jo->c.shutdown_bh);
> }
>
> static void qjack_fini_in(HWVoiceIn *hw)
> {
> QJackIn *ji = (QJackIn *)hw;
> qjack_client_fini(&ji->c);
> +
> + qemu_bh_delete(ji->c.shutdown_bh);
> }
>
> static void qjack_enable_out(HWVoiceOut *hw, bool enable)
> @@ -662,6 +685,7 @@ static void qjack_info(const char *msg)
>
> static void register_audio_jack(void)
> {
> + qemu_mutex_init(&qjack_shutdown_lock);
> audio_driver_register(&jack_driver);
> jack_set_thread_creator(qjack_thread_creator);
> jack_set_error_function(qjack_error);
Best regards,
Christian Schoenebeck
prev parent reply other threads:[~2020-11-08 11:11 UTC|newest]
Thread overview: 13+ messages / expand[flat|nested] mbox.gz Atom feed top
2020-08-21 13:45 [PATCH v8 0/1] audio/jack: fix use after free segfault Geoffrey McRae
2020-08-21 13:45 ` [PATCH v8 1/1] " Geoffrey McRae
2020-08-21 17:34 ` Christian Schoenebeck
2020-08-21 17:47 ` Paolo Bonzini
2020-08-22 0:16 ` Geoffrey McRae
2020-08-22 6:58 ` Christian Schoenebeck
2020-11-07 0:04 ` [PATCH v8 0/1] " Geoffrey McRae
2020-11-07 0:04 ` [PATCH v9 1/1] " Geoffrey McRae
2020-11-07 9:58 ` Christian Schoenebeck
2020-11-07 10:09 ` Christian Schoenebeck
2020-11-08 6:33 ` [PATCH v10 0/1] " Geoffrey McRae
2020-11-08 6:33 ` [PATCH v10 1/1] " Geoffrey McRae
2020-11-08 11:09 ` Christian Schoenebeck [this message]
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=4202934.l4obcem48q@silver \
--to=qemu_oss@crudebyte.com \
--cc=geoff@hostfission.com \
--cc=kraxel@redhat.com \
--cc=pbonzini@redhat.com \
--cc=qemu-devel@nongnu.org \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.