summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDavid Henningsson <david.henningsson@canonical.com>2012-03-23 13:06:27 +0100
committerDavid Henningsson <david.henningsson@canonical.com>2012-03-28 13:19:47 +0200
commitb7fab75fdde21569ef0be4c7c52887031393d75c (patch)
treeb026c2596fd00b633a8a26148b430902d590cd01
parent311654766207b3776e2618ae63ac35115db48bbd (diff)
sink-input/source-output: Prevent filter sink/source cycles
Misbehaving clients can try to set a filter sink to output to itself, leading to crashes later on. This patch protects us from that. Thanks to Roman Beslik for testing and finding an error in the first version of this patch. Tested-by: Roman Beslik <rabeslik@gmail.com> BugLink: https://bugs.freedesktop.org/show_bug.cgi?id=44397 Signed-off-by: David Henningsson <david.henningsson@canonical.com>
-rw-r--r--src/pulsecore/sink-input.c17
-rw-r--r--src/pulsecore/source-output.c17
2 files changed, 34 insertions, 0 deletions
diff --git a/src/pulsecore/sink-input.c b/src/pulsecore/sink-input.c
index b8412bd0..f6f7324c 100644
--- a/src/pulsecore/sink-input.c
+++ b/src/pulsecore/sink-input.c
@@ -1383,6 +1383,17 @@ pa_bool_t pa_sink_input_may_move(pa_sink_input *i) {
return TRUE;
}
+static pa_bool_t find_filter_sink_input(pa_sink_input *target, pa_sink *s) {
+ int i = 0;
+ while (s && s->input_to_master) {
+ if (s->input_to_master == target)
+ return TRUE;
+ s = s->input_to_master->sink;
+ pa_assert(i++ < 100);
+ }
+ return FALSE;
+}
+
/* Called from main context */
pa_bool_t pa_sink_input_may_move_to(pa_sink_input *i, pa_sink *dest) {
pa_sink_input_assert_ref(i);
@@ -1396,6 +1407,12 @@ pa_bool_t pa_sink_input_may_move_to(pa_sink_input *i, pa_sink *dest) {
if (!pa_sink_input_may_move(i))
return FALSE;
+ /* Make sure we're not creating a filter sink cycle */
+ if (find_filter_sink_input(i, dest)) {
+ pa_log_debug("Can't connect input to %s, as that would create a cycle.", dest->name);
+ return FALSE;
+ }
+
if (pa_idxset_size(dest->inputs) >= PA_MAX_INPUTS_PER_SINK) {
pa_log_warn("Failed to move sink input: too many inputs per sink.");
return FALSE;
diff --git a/src/pulsecore/source-output.c b/src/pulsecore/source-output.c
index fbfea9c1..cd7981c9 100644
--- a/src/pulsecore/source-output.c
+++ b/src/pulsecore/source-output.c
@@ -1160,6 +1160,17 @@ pa_bool_t pa_source_output_may_move(pa_source_output *o) {
return TRUE;
}
+static pa_bool_t find_filter_source_output(pa_source_output *target, pa_source *s) {
+ int i = 0;
+ while (s && s->output_from_master) {
+ if (s->output_from_master == target)
+ return TRUE;
+ s = s->output_from_master->source;
+ pa_assert(i++ < 100);
+ }
+ return FALSE;
+}
+
/* Called from main context */
pa_bool_t pa_source_output_may_move_to(pa_source_output *o, pa_source *dest) {
pa_source_output_assert_ref(o);
@@ -1172,6 +1183,12 @@ pa_bool_t pa_source_output_may_move_to(pa_source_output *o, pa_source *dest) {
if (!pa_source_output_may_move(o))
return FALSE;
+ /* Make sure we're not creating a filter source cycle */
+ if (find_filter_source_output(o, dest)) {
+ pa_log_debug("Can't connect output to %s, as that would create a cycle.", dest->name);
+ return FALSE;
+ }
+
if (pa_idxset_size(dest->outputs) >= PA_MAX_OUTPUTS_PER_SOURCE) {
pa_log_warn("Failed to move source output: too many outputs per source.");
return FALSE;