mirror of
https://github.com/Fishwaldo/Star64_linux.git
synced 2025-05-05 14:53:45 +00:00
ALSA: seq: Protect racy pool manipulation from OSS sequencer
OSS sequencer emulation still allows to queue and issue the events that manipulate the client pool concurrently in a racy way. This patch serializes the access like the normal sequencer write / ioctl via taking the client ioctl_mutex. Since the access to the sequencer client is done indirectly via a client id number, a new helper to take/release the mutex is introduced. Signed-off-by: Takashi Iwai <tiwai@suse.de>
This commit is contained in:
parent
6740ea6776
commit
6b580f5231
3 changed files with 49 additions and 5 deletions
|
@ -30,6 +30,7 @@
|
||||||
#include <sound/rawmidi.h>
|
#include <sound/rawmidi.h>
|
||||||
#include <sound/seq_kernel.h>
|
#include <sound/seq_kernel.h>
|
||||||
#include <sound/info.h>
|
#include <sound/info.h>
|
||||||
|
#include "../seq_clientmgr.h"
|
||||||
|
|
||||||
/* max. applications */
|
/* max. applications */
|
||||||
#define SNDRV_SEQ_OSS_MAX_CLIENTS 16
|
#define SNDRV_SEQ_OSS_MAX_CLIENTS 16
|
||||||
|
@ -150,11 +151,16 @@ snd_seq_oss_dispatch(struct seq_oss_devinfo *dp, struct snd_seq_event *ev, int a
|
||||||
return snd_seq_kernel_client_dispatch(dp->cseq, ev, atomic, hop);
|
return snd_seq_kernel_client_dispatch(dp->cseq, ev, atomic, hop);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* ioctl */
|
/* ioctl for writeq */
|
||||||
static inline int
|
static inline int
|
||||||
snd_seq_oss_control(struct seq_oss_devinfo *dp, unsigned int type, void *arg)
|
snd_seq_oss_control(struct seq_oss_devinfo *dp, unsigned int type, void *arg)
|
||||||
{
|
{
|
||||||
return snd_seq_kernel_client_ctl(dp->cseq, type, arg);
|
int err;
|
||||||
|
|
||||||
|
snd_seq_client_ioctl_lock(dp->cseq);
|
||||||
|
err = snd_seq_kernel_client_ctl(dp->cseq, type, arg);
|
||||||
|
snd_seq_client_ioctl_unlock(dp->cseq);
|
||||||
|
return err;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* fill the addresses in header */
|
/* fill the addresses in header */
|
||||||
|
|
|
@ -179,6 +179,36 @@ struct snd_seq_client *snd_seq_client_use_ptr(int clientid)
|
||||||
return client;
|
return client;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Take refcount and perform ioctl_mutex lock on the given client;
|
||||||
|
* used only for OSS sequencer
|
||||||
|
* Unlock via snd_seq_client_ioctl_unlock() below
|
||||||
|
*/
|
||||||
|
bool snd_seq_client_ioctl_lock(int clientid)
|
||||||
|
{
|
||||||
|
struct snd_seq_client *client;
|
||||||
|
|
||||||
|
client = snd_seq_client_use_ptr(clientid);
|
||||||
|
if (!client)
|
||||||
|
return false;
|
||||||
|
mutex_lock(&client->ioctl_mutex);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
EXPORT_SYMBOL_GPL(snd_seq_client_ioctl_lock);
|
||||||
|
|
||||||
|
/* Unlock and unref the given client; for OSS sequencer use only */
|
||||||
|
void snd_seq_client_ioctl_unlock(int clientid)
|
||||||
|
{
|
||||||
|
struct snd_seq_client *client;
|
||||||
|
|
||||||
|
client = snd_seq_client_use_ptr(clientid);
|
||||||
|
if (WARN_ON(!client))
|
||||||
|
return;
|
||||||
|
mutex_unlock(&client->ioctl_mutex);
|
||||||
|
snd_use_lock_free(&client->use_lock);
|
||||||
|
snd_seq_client_unlock(client);
|
||||||
|
}
|
||||||
|
EXPORT_SYMBOL_GPL(snd_seq_client_ioctl_unlock);
|
||||||
|
|
||||||
static void usage_alloc(struct snd_seq_usage *res, int num)
|
static void usage_alloc(struct snd_seq_usage *res, int num)
|
||||||
{
|
{
|
||||||
res->cur += num;
|
res->cur += num;
|
||||||
|
@ -2247,11 +2277,15 @@ int snd_seq_kernel_client_enqueue(int client, struct snd_seq_event *ev,
|
||||||
if (cptr == NULL)
|
if (cptr == NULL)
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
|
|
||||||
if (! cptr->accept_output)
|
if (!cptr->accept_output) {
|
||||||
result = -EPERM;
|
result = -EPERM;
|
||||||
else /* send it */
|
} else { /* send it */
|
||||||
|
mutex_lock(&cptr->ioctl_mutex);
|
||||||
result = snd_seq_client_enqueue_event(cptr, ev, file, blocking,
|
result = snd_seq_client_enqueue_event(cptr, ev, file, blocking,
|
||||||
false, 0, NULL);
|
false, 0,
|
||||||
|
&cptr->ioctl_mutex);
|
||||||
|
mutex_unlock(&cptr->ioctl_mutex);
|
||||||
|
}
|
||||||
|
|
||||||
snd_seq_client_unlock(cptr);
|
snd_seq_client_unlock(cptr);
|
||||||
return result;
|
return result;
|
||||||
|
|
|
@ -97,6 +97,10 @@ int snd_seq_kernel_client_write_poll(int clientid, struct file *file, poll_table
|
||||||
int snd_seq_client_notify_subscription(int client, int port,
|
int snd_seq_client_notify_subscription(int client, int port,
|
||||||
struct snd_seq_port_subscribe *info, int evtype);
|
struct snd_seq_port_subscribe *info, int evtype);
|
||||||
|
|
||||||
|
/* only for OSS sequencer */
|
||||||
|
bool snd_seq_client_ioctl_lock(int clientid);
|
||||||
|
void snd_seq_client_ioctl_unlock(int clientid);
|
||||||
|
|
||||||
extern int seq_client_load[15];
|
extern int seq_client_load[15];
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
Loading…
Add table
Reference in a new issue