diff options
Diffstat (limited to '')
-rw-r--r-- | sound/core/seq/seq_ports.c | 47 |
1 files changed, 31 insertions, 16 deletions
diff --git a/sound/core/seq/seq_ports.c b/sound/core/seq/seq_ports.c index 83be6b982a87..25fcf5a2c71c 100644 --- a/sound/core/seq/seq_ports.c +++ b/sound/core/seq/seq_ports.c @@ -139,7 +139,7 @@ struct snd_seq_client_port *snd_seq_create_port(struct snd_seq_client *client, port_subs_info_init(&new_port->c_dest); snd_use_lock_use(&new_port->use_lock); - num = port >= 0 ? port : 0; + num = max(port, 0); mutex_lock(&client->ports_mutex); write_lock_irq(&client->ports_lock); list_for_each_entry(p, &client->ports_list_head, list) { @@ -327,7 +327,7 @@ int snd_seq_set_port_info(struct snd_seq_client_port * port, /* set port name */ if (info->name[0]) - strlcpy(port->name, info->name, sizeof(port->name)); + strscpy(port->name, info->name, sizeof(port->name)); /* set capabilities */ port->capability = info->capability; @@ -356,7 +356,7 @@ int snd_seq_get_port_info(struct snd_seq_client_port * port, return -EINVAL; /* get port name */ - strlcpy(info->name, port->name, sizeof(info->name)); + strscpy(info->name, port->name, sizeof(info->name)); /* get capabilities */ info->capability = port->capability; @@ -514,10 +514,11 @@ static int check_and_subscribe_port(struct snd_seq_client *client, return err; } -static void delete_and_unsubscribe_port(struct snd_seq_client *client, - struct snd_seq_client_port *port, - struct snd_seq_subscribers *subs, - bool is_src, bool ack) +/* called with grp->list_mutex held */ +static void __delete_and_unsubscribe_port(struct snd_seq_client *client, + struct snd_seq_client_port *port, + struct snd_seq_subscribers *subs, + bool is_src, bool ack) { struct snd_seq_port_subs_info *grp; struct list_head *list; @@ -525,7 +526,6 @@ static void delete_and_unsubscribe_port(struct snd_seq_client *client, grp = is_src ? &port->c_src : &port->c_dest; list = is_src ? &subs->src_list : &subs->dest_list; - down_write(&grp->list_mutex); write_lock_irq(&grp->list_lock); empty = list_empty(list); if (!empty) @@ -535,6 +535,18 @@ static void delete_and_unsubscribe_port(struct snd_seq_client *client, if (!empty) unsubscribe_port(client, port, grp, &subs->info, ack); +} + +static void delete_and_unsubscribe_port(struct snd_seq_client *client, + struct snd_seq_client_port *port, + struct snd_seq_subscribers *subs, + bool is_src, bool ack) +{ + struct snd_seq_port_subs_info *grp; + + grp = is_src ? &port->c_src : &port->c_dest; + down_write(&grp->list_mutex); + __delete_and_unsubscribe_port(client, port, subs, is_src, ack); up_write(&grp->list_mutex); } @@ -590,27 +602,30 @@ int snd_seq_port_disconnect(struct snd_seq_client *connector, struct snd_seq_client_port *dest_port, struct snd_seq_port_subscribe *info) { - struct snd_seq_port_subs_info *src = &src_port->c_src; + struct snd_seq_port_subs_info *dest = &dest_port->c_dest; struct snd_seq_subscribers *subs; int err = -ENOENT; - down_write(&src->list_mutex); + /* always start from deleting the dest port for avoiding concurrent + * deletions + */ + down_write(&dest->list_mutex); /* look for the connection */ - list_for_each_entry(subs, &src->list_head, src_list) { + list_for_each_entry(subs, &dest->list_head, dest_list) { if (match_subs_info(info, &subs->info)) { - atomic_dec(&subs->ref_count); /* mark as not ready */ + __delete_and_unsubscribe_port(dest_client, dest_port, + subs, false, + connector->number != dest_client->number); err = 0; break; } } - up_write(&src->list_mutex); + up_write(&dest->list_mutex); if (err < 0) return err; delete_and_unsubscribe_port(src_client, src_port, subs, true, connector->number != src_client->number); - delete_and_unsubscribe_port(dest_client, dest_port, subs, false, - connector->number != dest_client->number); kfree(subs); return 0; } @@ -654,7 +669,7 @@ int snd_seq_event_port_attach(int client, /* Set up the port */ memset(&portinfo, 0, sizeof(portinfo)); portinfo.addr.client = client; - strlcpy(portinfo.name, portname ? portname : "Unnamed port", + strscpy(portinfo.name, portname ? portname : "Unnamed port", sizeof(portinfo.name)); portinfo.capability = cap; |