diff options
| -rw-r--r-- | sound/core/seq/seq_clientmgr.c | 32 |
1 files changed, 27 insertions, 5 deletions
diff --git a/sound/core/seq/seq_clientmgr.c b/sound/core/seq/seq_clientmgr.c index 4dda8268018e..0ac6d92058d9 100644 --- a/sound/core/seq/seq_clientmgr.c +++ b/sound/core/seq/seq_clientmgr.c @@ -538,16 +538,38 @@ static int bounce_error_event(struct snd_seq_client *client, /* set up quoted error */ memset(&bounce_ev, 0, sizeof(bounce_ev)); - bounce_ev.type = SNDRV_SEQ_EVENT_KERNEL_ERROR; - bounce_ev.flags = SNDRV_SEQ_EVENT_LENGTH_FIXED; + + if (client->type == USER_CLIENT) { + /* + * For user clients, send SNDRV_SEQ_EVENT_BOUNCE with the + * original event embedded as variable-length data. This + * avoids exposing data.quote.event (a kernel pointer) to + * userspace. The variable-length path in snd_seq_event_dup() + * copies the event data from data.ext.ptr into chained cells, + * and snd_seq_expand_var_event() copies only the data content + * -- never the pointer -- to userspace. + */ + bounce_ev.type = SNDRV_SEQ_EVENT_BOUNCE; + bounce_ev.flags = SNDRV_SEQ_EVENT_LENGTH_VARIABLE; + bounce_ev.data.ext.len = sizeof(struct snd_seq_event); + bounce_ev.data.ext.ptr = (char *)event; + } else { + /* + * For kernel clients, quote the event pointer directly. + * Kernel consumers can safely dereference the pointer. + */ + bounce_ev.type = SNDRV_SEQ_EVENT_KERNEL_ERROR; + bounce_ev.flags = SNDRV_SEQ_EVENT_LENGTH_FIXED; + bounce_ev.data.quote.origin = event->dest; + bounce_ev.data.quote.event = event; + bounce_ev.data.quote.value = -err; /* use positive value */ + } + bounce_ev.queue = SNDRV_SEQ_QUEUE_DIRECT; bounce_ev.source.client = SNDRV_SEQ_CLIENT_SYSTEM; bounce_ev.source.port = SNDRV_SEQ_PORT_SYSTEM_ANNOUNCE; bounce_ev.dest.client = client->number; bounce_ev.dest.port = event->source.port; - bounce_ev.data.quote.origin = event->dest; - bounce_ev.data.quote.event = event; - bounce_ev.data.quote.value = -err; /* use positive value */ result = snd_seq_deliver_single_event(NULL, &bounce_ev, atomic, hop + 1); if (result < 0) { client->event_lost++; |
