Skip to content

Commit 7c3f0d3

Browse files
committed
ALSA: seq: Check the conflicting port at port creation
We didn't check if a port with the given port number has been already present at creating a new port. Check it and return -EBUSY properly if the port number conflicts. Reviewed-by: Jaroslav Kysela <perex@perex.cz> Link: https://lore.kernel.org/r/20230523075358.9672-22-tiwai@suse.de Signed-off-by: Takashi Iwai <tiwai@suse.de>
1 parent 94c5b71 commit 7c3f0d3

File tree

3 files changed

+27
-15
lines changed

3 files changed

+27
-15
lines changed

sound/core/seq/seq_clientmgr.c

Lines changed: 8 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1194,15 +1194,19 @@ static int snd_seq_ioctl_create_port(struct snd_seq_client *client, void *arg)
11941194
struct snd_seq_port_info *info = arg;
11951195
struct snd_seq_client_port *port;
11961196
struct snd_seq_port_callback *callback;
1197-
int port_idx;
1197+
int port_idx, err;
11981198

11991199
/* it is not allowed to create the port for an another client */
12001200
if (info->addr.client != client->number)
12011201
return -EPERM;
12021202

1203-
port = snd_seq_create_port(client, (info->flags & SNDRV_SEQ_PORT_FLG_GIVEN_PORT) ? info->addr.port : -1);
1204-
if (port == NULL)
1205-
return -ENOMEM;
1203+
if (info->flags & SNDRV_SEQ_PORT_FLG_GIVEN_PORT)
1204+
port_idx = info->addr.port;
1205+
else
1206+
port_idx = -1;
1207+
err = snd_seq_create_port(client, port_idx, &port);
1208+
if (err < 0)
1209+
return err;
12061210

12071211
if (client->type == USER_CLIENT && info->kernel) {
12081212
port_idx = port->addr.port;

sound/core/seq/seq_ports.c

Lines changed: 16 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -107,33 +107,34 @@ static void port_subs_info_init(struct snd_seq_port_subs_info *grp)
107107
}
108108

109109

110-
/* create a port, port number is returned (-1 on failure);
110+
/* create a port, port number or a negative error code is returned
111111
* the caller needs to unref the port via snd_seq_port_unlock() appropriately
112112
*/
113-
struct snd_seq_client_port *snd_seq_create_port(struct snd_seq_client *client,
114-
int port)
113+
int snd_seq_create_port(struct snd_seq_client *client, int port,
114+
struct snd_seq_client_port **port_ret)
115115
{
116116
struct snd_seq_client_port *new_port, *p;
117-
int num = -1;
117+
int num;
118118

119+
*port_ret = NULL;
120+
119121
/* sanity check */
120122
if (snd_BUG_ON(!client))
121-
return NULL;
123+
return -EINVAL;
122124

123125
if (client->num_ports >= SNDRV_SEQ_MAX_PORTS) {
124126
pr_warn("ALSA: seq: too many ports for client %d\n", client->number);
125-
return NULL;
127+
return -EINVAL;
126128
}
127129

128130
/* create a new port */
129131
new_port = kzalloc(sizeof(*new_port), GFP_KERNEL);
130132
if (!new_port)
131-
return NULL; /* failure, out of memory */
133+
return -ENOMEM; /* failure, out of memory */
132134
/* init port data */
133135
new_port->addr.client = client->number;
134136
new_port->addr.port = -1;
135137
new_port->owner = THIS_MODULE;
136-
sprintf(new_port->name, "port-%d", num);
137138
snd_use_lock_init(&new_port->use_lock);
138139
port_subs_info_init(&new_port->c_src);
139140
port_subs_info_init(&new_port->c_dest);
@@ -143,6 +144,10 @@ struct snd_seq_client_port *snd_seq_create_port(struct snd_seq_client *client,
143144
mutex_lock(&client->ports_mutex);
144145
write_lock_irq(&client->ports_lock);
145146
list_for_each_entry(p, &client->ports_list_head, list) {
147+
if (p->addr.port == port) {
148+
num = -EBUSY;
149+
goto unlock;
150+
}
146151
if (p->addr.port > num)
147152
break;
148153
if (port < 0) /* auto-probe mode */
@@ -153,10 +158,12 @@ struct snd_seq_client_port *snd_seq_create_port(struct snd_seq_client *client,
153158
client->num_ports++;
154159
new_port->addr.port = num; /* store the port number in the port */
155160
sprintf(new_port->name, "port-%d", num);
161+
*port_ret = new_port;
162+
unlock:
156163
write_unlock_irq(&client->ports_lock);
157164
mutex_unlock(&client->ports_mutex);
158165

159-
return new_port;
166+
return num;
160167
}
161168

162169
/* */

sound/core/seq/seq_ports.h

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -86,8 +86,9 @@ struct snd_seq_client_port *snd_seq_port_query_nearest(struct snd_seq_client *cl
8686
/* unlock the port */
8787
#define snd_seq_port_unlock(port) snd_use_lock_free(&(port)->use_lock)
8888

89-
/* create a port, port number is returned (-1 on failure) */
90-
struct snd_seq_client_port *snd_seq_create_port(struct snd_seq_client *client, int port_index);
89+
/* create a port, port number or a negative error code is returned */
90+
int snd_seq_create_port(struct snd_seq_client *client, int port_index,
91+
struct snd_seq_client_port **port_ret);
9192

9293
/* delete a port */
9394
int snd_seq_delete_port(struct snd_seq_client *client, int port);

0 commit comments

Comments
 (0)