Merge ~ubuntu-audio-dev/pulseaudio:snap-policy-xenial into ~ubuntu-audio-dev/pulseaudio:ubuntu-xenial

Proposed by James Henstridge on 2018-08-29
Status: Needs review
Proposed branch: ~ubuntu-audio-dev/pulseaudio:snap-policy-xenial
Merge into: ~ubuntu-audio-dev/pulseaudio:ubuntu-xenial
Diff against target: 597 lines (+532/-1)
7 files modified
debian/changelog (+13/-0)
debian/control (+1/-0)
debian/patches/0450-modules-add-snappy-policy-module.patch (+482/-0)
debian/patches/0451-enable-snap-policy-module.patch (+30/-0)
debian/patches/series (+4/-0)
debian/pulseaudio.install (+1/-0)
debian/rules (+1/-1)
Reviewer Review Type Date Requested Status
Ubuntu Audio Development Team 2018-08-29 Pending
Review via email: mp+353966@code.launchpad.net

Commit message

Backport the snap policy module changes to Xenial.

Description of the change

This is a backport of the changes in Cosmic's pulseaudio 1:12.2-0ubuntu2 and 1:12.2-0ubuntu3.

To post a comment you must log in.
James Henstridge (jamesh) wrote :

Testing on a VM, this isn't working correctly. I got the following trying to record when using a snap AppArmor label:

    I: [pulseaudio] client.c: Created 4 "Native client (UNIX socket client)"
    I: [pulseaudio] protocol-native.c: Got credentials: uid=1000 gid=1000 success=1
    I: [pulseaudio] module-snap-policy.c: Checking access for client 4 (skype)
    W: [snapd-glib] module-snap-policy.c: snapd_client_get_snap failed: Not connected to snapd
    I: [pulseaudio] module-snap-policy.c: Access check for client 4 (skype): 0
    I: [pulseaudio] client.c: Freed 4 "parecord"
    I: [pulseaudio] protocol-native.c: Connection died.

This looks like it is due to version skew of snapd-glib. The old version requires a snapd_client_connect_sync() call.

James Henstridge (jamesh) wrote :

Talking to Robert on IRC, this isn't as simple as adding a call to snapd_client_connect_sync().

As Pulse is a long running session service, there is a good chance it will be running across a snapd refresh and get disconnected. So simply adding a _connect_sync() call at module startup could lead to bug reports of microphone access breaking part way through a session.

I think the most reliable option would be to SRU a new snapd-glib together with this Pulse Audio update. That's assuming we want to go ahead with updating Xenial at all.

Unmerged commits

23da1cc... by James Henstridge on 2018-08-29

Backport the module-snap-policy changes from Cosmic (LP: #1781428).

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
1diff --git a/debian/changelog b/debian/changelog
2index bf3f7a0..d8b6243 100644
3--- a/debian/changelog
4+++ b/debian/changelog
5@@ -1,3 +1,16 @@
6+pulseaudio (1:8.0-0ubuntu3.11) xenial; urgency=medium
7+
8+ * Backport the snap policy module to make access to audio recording
9+ conditional on plugging the "pulseaudio" or "audio-record" interfaces
10+ (LP: #1781428):
11+ - 0450-modules-add-snappy-policy-module.patch: rewrite to query
12+ snapd for the client's plugged interfaces.
13+ - 0451-enable-snap-policy-module.patch: enable the module in the
14+ default configuration.
15+ - Build depend on libsnapd-glib-dev.
16+
17+ -- James Henstridge <james.henstridge@canonical.com> Wed, 29 Aug 2018 19:17:22 +0800
18+
19 pulseaudio (1:8.0-0ubuntu3.10) xenial; urgency=medium
20
21 * Revert Cherrypick fixes for checking profile availabilities
22diff --git a/debian/control b/debian/control
23index 66e1ce2..830b182 100644
24--- a/debian/control
25+++ b/debian/control
26@@ -38,6 +38,7 @@ Build-Depends: android-headers-19 (>= 23) [armhf i386 amd64],
27 libltdl-dev (>= 2.2.6a-2),
28 liborc-0.4-dev (>= 1:0.4.11),
29 libsamplerate0-dev,
30+ libsnapd-glib-dev,
31 libsndfile1-dev (>= 1.0.20),
32 libspeexdsp-dev (>= 1.2~rc1),
33 libssl-dev,
34diff --git a/debian/patches/0450-modules-add-snappy-policy-module.patch b/debian/patches/0450-modules-add-snappy-policy-module.patch
35new file mode 100644
36index 0000000..3b9a710
37--- /dev/null
38+++ b/debian/patches/0450-modules-add-snappy-policy-module.patch
39@@ -0,0 +1,482 @@
40+From: James Henstridge <james.henstridge@canonical.com>
41+Date: Tue, 7 Aug 2018 12:40:59 +0800
42+Subject: [PATCH] modules: add snap policy module
43+
44+Forwarded: not-needed
45+
46+This patch allows pulseaudio to limit audio recording to snaps with
47+the audio-recording interface connected. We will not pursue upstreaming
48+this patch as the longer term solution will probably use PipeWire.
49+
50+Co-authored-by: Simon Fels <simon.fels@canonical.com>
51+---
52+ configure.ac | 18 ++
53+ src/Makefile.am | 13 ++
54+ src/modules/module-snap-policy.c | 384 +++++++++++++++++++++++++++++++++++++++
55+ 3 files changed, 415 insertions(+)
56+ create mode 100644 src/modules/module-snap-policy.c
57+
58+diff --git a/configure.ac b/configure.ac
59+index 7783026..e308081 100644
60+--- a/configure.ac
61++++ b/configure.ac
62+@@ -1428,6 +1428,22 @@ AS_IF([test "x$enable_trust_store" = "xyes" && test "x$HAVE_TRUST_STORE" = "x0"]
63+
64+ AM_CONDITIONAL([HAVE_TRUST_STORE], [test "x$HAVE_TRUST_STORE" = "x1"])
65+
66++# Snappy support
67++
68++AC_ARG_ENABLE([snap],
69++ AS_HELP_STRING([--enable-snap], [Enable snap support]))
70++
71++have_apparmor=0
72++have_snapd_glib=0
73++AS_IF([test "x$enable_snap" != "xno"],
74++ [PKG_CHECK_MODULES(APPARMOR, [libapparmor], [have_apparmor=1])
75++ PKG_CHECK_MODULES(SNAPD_GLIB, [snapd-glib], [have_snapd_glib=1])])
76++
77++AS_IF([test "x$enable_snap" = "xyes" && test "x$have_apparmor" = "x0" -o "x$have-snapd_glib" = "x0"],
78++ [AC_MSG_ERROR([*** Snap module dependencies missing])])
79++
80++AM_CONDITIONAL([BUILD_SNAP], [test "x$enable_snap" = "xyes"])
81++
82+
83+ ###################################
84+ # Output #
85+@@ -1605,6 +1621,7 @@ AS_IF([test "x$HAVE_ESOUND" = "x1" -a "x$USE_PER_USER_ESOUND_SOCKET" = "x1"], EN
86+ AS_IF([test "x$HAVE_GCOV" = "x1"], ENABLE_GCOV=yes, ENABLE_GCOV=no)
87+ AS_IF([test "x$HAVE_LIBCHECK" = "x1"], ENABLE_TESTS=yes, ENABLE_TESTS=no)
88+ AS_IF([test "x$enable_legacy_database_entry_format" != "xno"], ENABLE_LEGACY_DATABASE_ENTRY_FORMAT=yes, ENABLE_LEGACY_DATABASE_ENTRY_FORMAT=no)
89++AS_IF([test "x$enable_snap" != "xno"], ENABLE_SNAP=yes, ENABLE_SNAP=no)
90+
91+ echo "
92+ ---{ $PACKAGE_NAME $VERSION }---
93+@@ -1662,6 +1679,7 @@ echo "
94+ Enable soxr (resampler): ${ENABLE_SOXR}
95+ Enable WebRTC echo canceller: ${ENABLE_WEBRTC}
96+ Enable Ubuntu trust store: ${ENABLE_TRUST_STORE}
97++ Enable Snap support: ${ENABLE_SNAP}
98+ Enable gcov coverage: ${ENABLE_GCOV}
99+ Enable unit tests: ${ENABLE_TESTS}
100+ Database
101+diff --git a/src/Makefile.am b/src/Makefile.am
102+index d8337a9..4046bca 100644
103+--- a/src/Makefile.am
104++++ b/src/Makefile.am
105+@@ -1216,6 +1216,11 @@ modlibexec_LTLIBRARIES += \
106+ module-esound-sink.la
107+ endif
108+
109++if BUILD_SNAP
110++modlibexec_LTLIBRARIES += \
111++ module-snap-policy.la
112++endif
113++
114+ # See comment at librtp.la above
115+ if !OS_IS_WIN32
116+ modlibexec_LTLIBRARIES += \
117+@@ -2143,6 +2148,14 @@ module_trust_store_la_LIBADD = $(MODULE_LIBADD) libtruststore-util.la
118+ module_trust_store_la_CFLAGS = $(AM_CFLAGS) -DHAVE_TRUST_STORE=1
119+ endif
120+
121++# Snappy
122++if BUILD_SNAP
123++module_snap_policy_la_SOURCES = modules/module-snap-policy.c
124++module_snap_policy_la_LDFLAGS = $(MODULE_LDFLAGS)
125++module_snap_policy_la_LIBADD = $(MODULE_LIBADD) $(APPARMOR_LIBS) $(SNAPD_GLIB_LIBS)
126++module_snap_policy_la_CFLAGS = $(AM_CFLAGS) $(APPARMOR_CFLAGS) $(SNAPD_GLIB_CFLAGS) -DPA_MODULE_NAME=module_snap_policy
127++endif
128++
129+ # RTP modules
130+ module_rtp_send_la_SOURCES = modules/rtp/module-rtp-send.c
131+ module_rtp_send_la_LDFLAGS = $(MODULE_LDFLAGS)
132+diff --git a/src/modules/module-snap-policy.c b/src/modules/module-snap-policy.c
133+new file mode 100644
134+index 0000000..0a1f5f4
135+--- /dev/null
136++++ b/src/modules/module-snap-policy.c
137+@@ -0,0 +1,384 @@
138++/***
139++ This file is part of PulseAudio.
140++
141++ Copyright 2018 Canonical Ltd.
142++ Authors:
143++ Simon Fels <simon.fels@canonical.com>
144++ James Henstridge <james.henstridge@canonical.com>
145++
146++ PulseAudio is free software; you can redistribute it and/or modify
147++ it under the terms of the GNU Lesser General Public License as published
148++ by the Free Software Foundation; either version 2.1 of the License,
149++ or (at your option) any later version.
150++
151++ PulseAudio is distributed in the hope that it will be useful, but
152++ WITHOUT ANY WARRANTY; without even the implied warranty of
153++ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
154++ General Public License for more details.
155++
156++ You should have received a copy of the GNU Lesser General Public License
157++ along with PulseAudio; if not, see <http://www.gnu.org/licenses/>.
158++***/
159++
160++#ifdef HAVE_CONFIG_H
161++#include <config.h>
162++#endif
163++
164++#include <sys/apparmor.h>
165++#include <glib.h>
166++#include <snapd-glib/snapd-glib.h>
167++
168++#include <pulsecore/asyncq.h>
169++#include <pulsecore/core.h>
170++#include <pulsecore/idxset.h>
171++#include <pulsecore/hashmap.h>
172++#include <pulsecore/module.h>
173++#include <pulsecore/mutex.h>
174++#include <pulsecore/thread.h>
175++#include <pulse/mainloop-api.h>
176++#include <pulse/xmalloc.h>
177++
178++#define SNAP_LABEL_PREFIX "snap."
179++#define SNAP_LABEL_PREFIX_LENGTH 5
180++
181++PA_MODULE_AUTHOR("Canonical Ltd");
182++PA_MODULE_DESCRIPTION("Ubuntu Snap policy management");
183++PA_MODULE_VERSION(PACKAGE_VERSION);
184++PA_MODULE_LOAD_ONCE(true);
185++
186++struct per_client {
187++ struct userdata *userdata;
188++ uint32_t index;
189++ char *snap_name;
190++ pa_dynarray *pending_requests; /* of pa_access_data */
191++ bool completed;
192++ bool grant_access;
193++};
194++
195++struct userdata {
196++ pa_io_event *io_event;
197++ pa_hook_slot *connect_hook_slot;
198++
199++ pa_thread *thread;
200++ pa_mutex *mutex;
201++ pa_cond *cond;
202++
203++ pa_hashmap *clients; /* int => struct per_client */
204++ pa_asyncq *results; /* of struct per_client */
205++
206++ /* Data owned by glib thread */
207++ GMainContext *main_context;
208++ GMainLoop *main_loop;
209++ GCancellable *cancellable;
210++ SnapdClient *snapd;
211++};
212++
213++/* ---- Code running in glib thread ---- */
214++
215++static void complete_check_access(struct per_client *pc, bool grant_access)
216++{
217++ struct userdata *u = pc->userdata;
218++
219++ pa_mutex_lock(u->mutex);
220++ pc->grant_access = grant_access;
221++ pc->completed = true;
222++ pa_asyncq_push(u->results, pc, true);
223++ pa_mutex_unlock(u->mutex);
224++}
225++
226++static void get_interfaces_finished(GObject *source_object,
227++ GAsyncResult *result,
228++ gpointer user_data)
229++{
230++ struct per_client *pc = user_data;
231++ struct userdata *u = pc->userdata;
232++ bool grant_access = false;
233++ g_autoptr(GError) error = NULL;
234++ g_autoptr(GPtrArray) plugs = NULL;
235++ unsigned i;
236++
237++ if (!snapd_client_get_interfaces_finish(u->snapd, result, &plugs, NULL, &error)) {
238++ pa_log_warn("snapd_client_get_interfaces failed: %s", error->message);
239++ goto end;
240++ }
241++
242++ /* determine pc->grant_access */
243++ for (i = 0; i < plugs->len; i++) {
244++ SnapdPlug *plug = plugs->pdata[i];
245++ const char *snap_name = snapd_plug_get_snap(plug);
246++ const char *iface = snapd_plug_get_interface(plug);
247++ const bool connected = snapd_plug_get_connections(plug)->len != 0;
248++
249++ /* We are only interested in connected plugs of our snap */
250++ if (!connected || strcmp(snap_name, pc->snap_name) != 0) {
251++ continue;
252++ }
253++ if (!strcmp(iface, "pulseaudio") || !strcmp(iface, "audio-record")) {
254++ grant_access = true;
255++ break;
256++ }
257++ }
258++
259++end:
260++ complete_check_access(pc, grant_access);
261++}
262++
263++static void get_snap_finished(GObject *source_object,
264++ GAsyncResult *result,
265++ gpointer user_data)
266++{
267++ struct per_client *pc = user_data;
268++ struct userdata *u = pc->userdata;
269++ g_autoptr(GError) error = NULL;
270++ g_autoptr(SnapdSnap) snap = NULL;
271++
272++ snap = snapd_client_list_one_finish(u->snapd, result, &error);
273++ if (!snap) {
274++ pa_log_warn("snapd_client_get_snap failed: %s", error->message);
275++ complete_check_access(pc, false);
276++ return;
277++ }
278++
279++ /* Snaps using classic confinement are granted access */
280++ if (snapd_snap_get_confinement(snap) == SNAPD_CONFINEMENT_CLASSIC) {
281++ complete_check_access(pc, true);
282++ return;
283++ }
284++
285++ /* We have a non-classic snap, we need to check its connected
286++ * interfaces */
287++ snapd_client_get_interfaces_async(u->snapd, u->cancellable,
288++ get_interfaces_finished, pc);
289++}
290++
291++
292++static gboolean check_access(void *data)
293++{
294++ struct per_client *pc = data;
295++ struct userdata *u = pc->userdata;
296++
297++ snapd_client_list_one_async(u->snapd, pc->snap_name, u->cancellable,
298++ get_snap_finished, pc);
299++ return G_SOURCE_REMOVE;
300++}
301++
302++
303++static void thread_main(void *data) {
304++ struct userdata *u = data;
305++
306++ pa_mutex_lock(u->mutex);
307++
308++ u->main_context = g_main_context_new();
309++ g_main_context_push_thread_default(u->main_context);
310++ u->main_loop = g_main_loop_new(u->main_context, false);
311++ u->cancellable = g_cancellable_new();
312++ u->snapd = snapd_client_new();
313++
314++ /* Signal main thread that we've finished initialisation */
315++ pa_cond_signal(u->cond, false);
316++ pa_mutex_unlock(u->mutex);
317++
318++ pa_log_info("Starting GLib main loop");
319++ g_main_loop_run(u->main_loop);
320++ pa_log_info("GLib main loop exited");
321++
322++ g_cancellable_cancel(u->cancellable);
323++
324++ g_clear_object(&u->snapd);
325++ g_clear_object(&u->cancellable);
326++ g_main_context_pop_thread_default(u->main_context);
327++ g_clear_pointer(&u->main_loop, g_main_loop_unref);
328++ g_clear_pointer(&u->main_context, g_main_context_unref);
329++}
330++
331++static gboolean thread_quit(void *data)
332++{
333++ struct userdata *u = data;
334++
335++ g_main_loop_quit(u->main_loop);
336++ return G_SOURCE_REMOVE;
337++}
338++
339++/* ---- Code running in main thread ---- */
340++
341++static struct per_client *per_client_new(struct userdata *u,
342++ uint32_t client_index,
343++ char *snap_name) {
344++ struct per_client *pc = pa_xnew0(struct per_client, 1);
345++ pc->userdata = u;
346++ pc->index = client_index;
347++ pc->snap_name = snap_name;
348++ pc->pending_requests = pa_dynarray_new(NULL);
349++ pc->completed = false;
350++ pc->grant_access = false;
351++ return pc;
352++}
353++
354++static void per_client_free(struct per_client *pc) {
355++ if (!pc) return;
356++ pa_xfree(pc->snap_name);
357++ pa_dynarray_free(pc->pending_requests);
358++ pa_xfree(pc);
359++}
360++
361++static char *client_get_snap_name(pa_core *core, uint32_t client_index) {
362++ pa_client *client;
363++ char *context = NULL;
364++ char *snap_name = NULL;
365++ char *dot;
366++
367++ client = pa_idxset_get_by_index(core->clients, client_index);
368++ pa_assert(client != NULL);
369++ if (!client->creds_valid) {
370++ pa_log_warn("Client %u has no creds, cannot authenticate", client_index);
371++ goto end;
372++ }
373++
374++ /* If AppArmor is not enabled, then we can't identify the client */
375++ if (!aa_is_enabled()) {
376++ goto end;
377++ }
378++ if (aa_gettaskcon(client->creds.pid, &context, NULL) < 0) {
379++ pa_log_error("AppArmor profile could not be retrieved.");
380++ goto end;
381++ }
382++
383++ /* If the AppArmor context does not begin with "snap.", then this
384++ * is not a snap */
385++ if (strncmp(context, SNAP_LABEL_PREFIX, SNAP_LABEL_PREFIX_LENGTH) != 0) {
386++ goto end;
387++ }
388++
389++ dot = strchr(context+SNAP_LABEL_PREFIX_LENGTH, '.');
390++ if (dot == NULL) {
391++ pa_log_warn("Malformed snapd AppArmor profile name: %s", context);
392++ goto end;
393++ }
394++ snap_name = pa_xstrndup(context+5, dot-context-SNAP_LABEL_PREFIX_LENGTH);
395++
396++end:
397++ free(context);
398++ return snap_name;
399++}
400++
401++static pa_hook_result_t connect_record_hook(pa_core *core, pa_access_data *d,
402++ struct userdata *u) {
403++ pa_hook_result_t result = PA_HOOK_STOP;
404++ struct per_client *pc = NULL;
405++ char *snap_name = NULL;
406++
407++ pa_mutex_lock(u->mutex);
408++ pc = pa_hashmap_get(u->clients, (void *)(size_t)d->client_index);
409++ if (pc) {
410++ if (pc->completed) {
411++ result = pc->grant_access ? PA_HOOK_OK : PA_HOOK_STOP;
412++ } else {
413++ /* A permission check for this snap is currently in progress */
414++ pa_dynarray_append(pc->pending_requests, d);
415++ result = PA_HOOK_CANCEL;
416++ }
417++ goto end;
418++ }
419++
420++ snap_name = client_get_snap_name(core, d->client_index);
421++ if (!snap_name) {
422++ /* Not a snap, so allow access */
423++ result = PA_HOOK_OK;
424++ goto end;
425++ }
426++
427++ /* create new per client struct, and submit to glib thread */
428++ pc = per_client_new(u, d->client_index, snap_name);
429++ pa_dynarray_append(pc->pending_requests, d);
430++ pa_hashmap_put(u->clients, (void *) (size_t) d->client_index, pc);
431++ pa_log_info("Checking access for client %d (%s)", pc->index, pc->snap_name);
432++ g_main_context_invoke(u->main_context, check_access, pc);
433++
434++ result = PA_HOOK_CANCEL;
435++
436++end:
437++ pa_mutex_unlock(u->mutex);
438++ return result;
439++}
440++
441++static void deliver_result(struct userdata *u, struct per_client *pc) {
442++ pa_access_data *ad;
443++ unsigned i;
444++
445++ pa_log_info("Access check for client %u (%s): %d",
446++ pc->index, pc->snap_name, pc->grant_access);
447++
448++ /* Call the hooks without holding the mutex, since this will
449++ * recurse into connect_record_hook. Access to pending_requests
450++ * should be safe here, since connect_record_hook wont alter the
451++ * array when the access check is complete. */
452++ PA_DYNARRAY_FOREACH(ad, pc->pending_requests, i) {
453++ ad->async_finish_cb(ad, pc->grant_access);
454++ }
455++ pa_mutex_lock(u->mutex);
456++ pa_hashmap_remove_and_free(u->clients, (void *) (size_t) pc->index);
457++ pa_mutex_unlock(u->mutex);
458++}
459++
460++static void check_result(pa_mainloop_api *a, pa_io_event *e, int fd, pa_io_event_flags_t flags, void *userdata) {
461++ struct userdata *u = userdata;
462++ struct per_client *pc;
463++
464++ pa_asyncq_read_after_poll(u->results);
465++ while ((pc = pa_asyncq_pop(u->results, false)) != NULL) {
466++ deliver_result(u, pc);
467++ }
468++ pa_asyncq_read_before_poll(u->results);
469++}
470++
471++int pa__init(pa_module *m) {
472++ struct userdata *u;
473++
474++ u = pa_xnew0(struct userdata, 1);
475++ m->userdata = u;
476++ u->mutex = pa_mutex_new(false, false);
477++ u->cond = pa_cond_new();
478++
479++ u->clients = pa_hashmap_new_full(pa_idxset_trivial_hash_func,
480++ pa_idxset_trivial_compare_func,
481++ NULL, (pa_free_cb_t) per_client_free);
482++
483++ u->results = pa_asyncq_new(0);
484++ u->io_event = m->core->mainloop->io_new(
485++ m->core->mainloop, pa_asyncq_read_fd(u->results), PA_IO_EVENT_INPUT,
486++ check_result, u);
487++ pa_asyncq_read_before_poll(u->results);
488++
489++ u->connect_hook_slot = pa_hook_connect(
490++ &m->core->access[PA_ACCESS_HOOK_CONNECT_RECORD], PA_HOOK_NORMAL,
491++ (pa_hook_cb_t) connect_record_hook, u);
492++
493++ /* Start glib thread and wait for it to finish initialising. */
494++ pa_mutex_lock(u->mutex);
495++ u->thread = pa_thread_new("snapd-glib", thread_main, u);
496++ pa_cond_wait(u->cond, u->mutex);
497++ pa_mutex_unlock(u->mutex);
498++
499++ return 0;
500++}
501++
502++void pa__done(pa_module *m) {
503++ struct userdata *u = m->userdata;
504++ if (!u) return;
505++
506++ pa_hook_slot_free(u->connect_hook_slot);
507++ m->core->mainloop->io_free(u->io_event);
508++
509++ /* Stop the glib thread and wait for it to exit */
510++ g_main_context_invoke(u->main_context, thread_quit, u);
511++ pa_thread_join(u->thread);
512++ pa_thread_free(u->thread);
513++
514++ pa_asyncq_free(u->results, NULL); /* items in queue owned by u->clients */
515++ g_clear_pointer(&u->clients, pa_hashmap_free);
516++
517++ g_clear_pointer(&u->cond, pa_cond_free);
518++ g_clear_pointer(&u->mutex, pa_mutex_free);
519++
520++ pa_xfree(u);
521++}
522diff --git a/debian/patches/0451-enable-snap-policy-module.patch b/debian/patches/0451-enable-snap-policy-module.patch
523new file mode 100644
524index 0000000..dc13a11
525--- /dev/null
526+++ b/debian/patches/0451-enable-snap-policy-module.patch
527@@ -0,0 +1,30 @@
528+From: James Henstridge <james.henstridge@canonical.com>
529+Date: Tue, 7 Aug 2018 16:54:00 +0800
530+Subject: daemon: enable module-snap-policy module
531+
532+Forwarded: not-needed
533+
534+This patch allows pulseaudio to limit audio recording to snaps with
535+the audio-recording interface connected. We will not pursue upstreaming
536+this patch as the longer term solution will probably use PipeWire.
537+---
538+ src/daemon/default.pa.in | 6 ++++++
539+ 1 file changed, 6 insertions(+)
540+
541+diff --git a/src/daemon/default.pa.in b/src/daemon/default.pa.in
542+index b770a4d..236b049 100755
543+--- a/src/daemon/default.pa.in
544++++ b/src/daemon/default.pa.in
545+@@ -166,6 +166,12 @@ load-module module-position-event-sounds
546+ ### Cork music/video streams when a phone stream is active
547+ #load-module module-role-cork
548+
549++### Block audio recording for snap confined packages unless they have
550++### the "pulseaudio" or "audio-record" interfaces plugged.
551++.ifexists module-snap-policy@PA_SOEXT@
552++load-module module-snap-policy
553++.endif
554++
555+ ### Modules to allow autoloading of filters (such as echo cancellation)
556+ ### on demand. module-filter-heuristics tries to determine what filters
557+ ### make sense, and module-filter-apply does the heavy-lifting of
558diff --git a/debian/patches/series b/debian/patches/series
559index ec479b1..d07e4cc 100644
560--- a/debian/patches/series
561+++ b/debian/patches/series
562@@ -33,6 +33,10 @@
563 0410-Add-thread-to-activate-trust-store-interface.patch
564 0417-increase-timeout-check-apparmor.patch
565
566+# Ubuntu Snap policy support
567+0450-modules-add-snappy-policy-module.patch
568+0451-enable-snap-policy-module.patch
569+
570 # Ubuntu touch: enable bluez5 HFP over ofono support
571 0501-bluetooth-bluez5-ofono-add-support-for-HFP-gateway-r.patch
572 0502-bluetooth-bluez5-bring-back-SCO-over-PCM-support.patch
573diff --git a/debian/pulseaudio.install b/debian/pulseaudio.install
574index b137241..78f7a78 100755
575--- a/debian/pulseaudio.install
576+++ b/debian/pulseaudio.install
577@@ -77,6 +77,7 @@ usr/lib/pulse-*/modules/module-virtual-sink.so
578 usr/lib/pulse-*/modules/module-virtual-source.so
579 usr/lib/pulse-*/modules/module-switch-on-port-available.so
580 usr/lib/pulse-*/modules/module-virtual-surround-sink.so
581+usr/lib/pulse-*/modules/module-snap-policy.so
582 [linux-any] usr/lib/pulse-*/modules/module-systemd-login.so
583 [linux-any] usr/lib/systemd/user/pulseaudio.*
584 usr/share/bash-completion/completions/*
585diff --git a/debian/rules b/debian/rules
586index 258494f..bcb18c1 100755
587--- a/debian/rules
588+++ b/debian/rules
589@@ -37,7 +37,7 @@ DEB_CONFIGURE_EXTRA_FLAGS = --enable-x11 --disable-hal-compat \
590 --with-zsh-completion-dir=\$${datadir}/zsh/vendor-completions \
591 --with-bash-completion-dir=\$${datadir}/bash-completion/completions \
592 --with-systemduserunitdir=\$${prefix}/lib/systemd/user \
593- --disable-bluez4
594+ --disable-bluez4 --enable-snap
595
596 ifeq ($(words $(sort $(filter stage1,$(DEB_BUILD_PROFILES)))),1)
597 DEB_CONFIGURE_EXTRA_FLAGS += --disable-bluez

Subscribers

People subscribed via source and target branches