jack: add more port checks

Check if the port id and direction is valid before accessing the
port array.
Handle unknown and invalid ports in many methods.
Free the port item after we removed the item from pipewire because
more methods are being called while removing the port and we don't
want them to fail.
This commit is contained in:
Wim Taymans 2021-06-17 09:18:29 +02:00
parent 4c9ac08310
commit 3e52c6598b

View file

@ -252,9 +252,7 @@ struct context {
#define GET_DIRECTION(f) ((f) & JackPortIsInput ? SPA_DIRECTION_INPUT : SPA_DIRECTION_OUTPUT) #define GET_DIRECTION(f) ((f) & JackPortIsInput ? SPA_DIRECTION_INPUT : SPA_DIRECTION_OUTPUT)
#define GET_IN_PORT(c,p) (c->port_pool[SPA_DIRECTION_INPUT][p]) #define GET_PORT(c,d,p) ((d >= 0 && d <=1 && p < c->n_port_pool[d]) ? c->port_pool[d][p] : NULL)
#define GET_OUT_PORT(c,p) (c->port_pool[SPA_DIRECTION_OUTPUT][p])
#define GET_PORT(c,d,p) (d == SPA_DIRECTION_INPUT ? GET_IN_PORT(c,p) : GET_OUT_PORT(c,p))
struct metadata { struct metadata {
struct pw_metadata *proxy; struct pw_metadata *proxy;
@ -1836,6 +1834,9 @@ static int client_node_port_set_param(void *object,
uint8_t buffer[4096]; uint8_t buffer[4096];
struct spa_pod_builder b = SPA_POD_BUILDER_INIT(buffer, sizeof(buffer)); struct spa_pod_builder b = SPA_POD_BUILDER_INIT(buffer, sizeof(buffer));
if (p == NULL || !p->valid)
return -EINVAL;
pw_log_info("port %p: %d.%d id:%d %p", p, direction, port_id, id, param); pw_log_info("port %p: %d.%d id:%d %p", p, direction, port_id, id, param);
switch (id) { switch (id) {
@ -1843,8 +1844,7 @@ static int client_node_port_set_param(void *object,
port_set_format(c, p, flags, param); port_set_format(c, p, flags, param);
break; break;
case SPA_PARAM_Latency: case SPA_PARAM_Latency:
port_set_latency(c, p, flags, param); return port_set_latency(c, p, flags, param);
return 0;
default: default:
break; break;
} }
@ -1902,7 +1902,7 @@ static int client_node_port_use_buffers(void *object,
int res; int res;
struct mix *mix; struct mix *mix;
if (!p->valid) { if (p == NULL || !p->valid) {
res = -EINVAL; res = -EINVAL;
goto done; goto done;
} }
@ -2052,6 +2052,11 @@ static int client_node_port_set_io(void *object,
void *ptr; void *ptr;
int res = 0; int res = 0;
if (p == NULL || !p->valid) {
res = -EINVAL;
goto exit;
}
if ((mix = ensure_mix(c, p, mix_id)) == NULL) { if ((mix = ensure_mix(c, p, mix_id)) == NULL) {
res = -ENOMEM; res = -ENOMEM;
goto exit; goto exit;
@ -3768,8 +3773,10 @@ int jack_port_unregister (jack_client_t *client, jack_port_t *port)
pw_thread_loop_lock(c->context.loop); pw_thread_loop_lock(c->context.loop);
p = GET_PORT(c, GET_DIRECTION(o->port.flags), o->port.port_id); p = GET_PORT(c, GET_DIRECTION(o->port.flags), o->port.port_id);
if (p == NULL || !p->valid) {
free_port(c, p); res = -EINVAL;
goto done;
}
pw_client_node_port_update(c->node, pw_client_node_port_update(c->node,
p->direction, p->direction,
@ -3778,6 +3785,9 @@ int jack_port_unregister (jack_client_t *client, jack_port_t *port)
res = do_sync(c); res = do_sync(c);
free_port(c, p);
done:
pw_thread_loop_unlock(c->context.loop); pw_thread_loop_unlock(c->context.loop);
return res; return res;
@ -4095,6 +4105,7 @@ int jack_port_rename (jack_client_t* client, jack_port_t *port, const char *port
struct client *c = (struct client *) client; struct client *c = (struct client *) client;
struct object *o = (struct object *) port; struct object *o = (struct object *) port;
struct port *p; struct port *p;
int res = 0;
spa_return_val_if_fail(c != NULL, -EINVAL); spa_return_val_if_fail(c != NULL, -EINVAL);
spa_return_val_if_fail(o != NULL, -EINVAL); spa_return_val_if_fail(o != NULL, -EINVAL);
@ -4106,6 +4117,11 @@ int jack_port_rename (jack_client_t* client, jack_port_t *port, const char *port
client, port, o->port.name, c->name, port_name); client, port, o->port.name, c->name, port_name);
p = GET_PORT(c, GET_DIRECTION(o->port.flags), o->port.port_id); p = GET_PORT(c, GET_DIRECTION(o->port.flags), o->port.port_id);
if (p == NULL || !p->valid) {
res = -EINVAL;
goto done;
}
pw_properties_set(p->props, PW_KEY_PORT_NAME, port_name); pw_properties_set(p->props, PW_KEY_PORT_NAME, port_name);
snprintf(o->port.name, sizeof(o->port.name), "%s:%s", c->name, port_name); snprintf(o->port.name, sizeof(o->port.name), "%s:%s", c->name, port_name);
@ -4121,9 +4137,10 @@ int jack_port_rename (jack_client_t* client, jack_port_t *port, const char *port
&p->info); &p->info);
p->info.change_mask = 0; p->info.change_mask = 0;
done:
pw_thread_loop_unlock(c->context.loop); pw_thread_loop_unlock(c->context.loop);
return 0; return res;
} }
SPA_EXPORT SPA_EXPORT
@ -4133,6 +4150,7 @@ int jack_port_set_alias (jack_port_t *port, const char *alias)
struct client *c; struct client *c;
struct port *p; struct port *p;
const char *key; const char *key;
int res = 0;
spa_return_val_if_fail(o != NULL, -EINVAL); spa_return_val_if_fail(o != NULL, -EINVAL);
spa_return_val_if_fail(alias != NULL, -EINVAL); spa_return_val_if_fail(alias != NULL, -EINVAL);
@ -4149,10 +4167,16 @@ int jack_port_set_alias (jack_port_t *port, const char *alias)
key = PW_KEY_PORT_ALIAS; key = PW_KEY_PORT_ALIAS;
snprintf(o->port.alias2, sizeof(o->port.alias2), "%s", alias); snprintf(o->port.alias2, sizeof(o->port.alias2), "%s", alias);
} }
else else {
goto error; res = -1;
goto done;
}
p = GET_PORT(c, GET_DIRECTION(o->port.flags), o->port.port_id); p = GET_PORT(c, GET_DIRECTION(o->port.flags), o->port.port_id);
if (p == NULL || !p->valid) {
res = -EINVAL;
goto done;
}
pw_properties_set(p->props, key, alias); pw_properties_set(p->props, key, alias);
@ -4167,13 +4191,10 @@ int jack_port_set_alias (jack_port_t *port, const char *alias)
&p->info); &p->info);
p->info.change_mask = 0; p->info.change_mask = 0;
done:
pw_thread_loop_unlock(c->context.loop); pw_thread_loop_unlock(c->context.loop);
return 0; return res;
error:
pw_thread_loop_unlock(c->context.loop);
return -1;
} }
SPA_EXPORT SPA_EXPORT
@ -4183,6 +4204,7 @@ int jack_port_unset_alias (jack_port_t *port, const char *alias)
struct client *c; struct client *c;
struct port *p; struct port *p;
const char *key; const char *key;
int res = 0;
spa_return_val_if_fail(o != NULL, -EINVAL); spa_return_val_if_fail(o != NULL, -EINVAL);
spa_return_val_if_fail(alias != NULL, -EINVAL); spa_return_val_if_fail(alias != NULL, -EINVAL);
@ -4195,11 +4217,16 @@ int jack_port_unset_alias (jack_port_t *port, const char *alias)
key = PW_KEY_OBJECT_PATH; key = PW_KEY_OBJECT_PATH;
else if (spa_streq(o->port.alias2, alias)) else if (spa_streq(o->port.alias2, alias))
key = PW_KEY_PORT_ALIAS; key = PW_KEY_PORT_ALIAS;
else else {
goto error; res = -1;
goto done;
}
p = GET_PORT(c, GET_DIRECTION(o->port.flags), o->port.port_id); p = GET_PORT(c, GET_DIRECTION(o->port.flags), o->port.port_id);
if (p == NULL || !p->valid) {
res = -EINVAL;
goto done;
}
pw_properties_set(p->props, key, NULL); pw_properties_set(p->props, key, NULL);
@ -4214,13 +4241,10 @@ int jack_port_unset_alias (jack_port_t *port, const char *alias)
&p->info); &p->info);
p->info.change_mask = 0; p->info.change_mask = 0;
done:
pw_thread_loop_unlock(c->context.loop); pw_thread_loop_unlock(c->context.loop);
return 0; return res;
error:
pw_thread_loop_unlock(c->context.loop);
return -1;
} }
SPA_EXPORT SPA_EXPORT