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

Proposed by James Henstridge
Status: Merged
Merged at revision: c3261bbec962194c4e62b40874fbc0fe7f9b6a55
Proposed branch: ~jamesh/pulseaudio:module-snap-policy
Merge into: ~ubuntu-audio-dev/pulseaudio:ubuntu
Prerequisite: ~ubuntu-audio-dev/pulseaudio:ubuntu-pulse12.2-proposed
Diff against target: 1555 lines (+504/-215)
9 files modified
debian/changelog (+12/-0)
debian/control (+1/-0)
debian/patches/0409-pa-client-peer-credentials.patch (+104/-0)
debian/patches/0700-modules-add-snappy-policy-module.patch (+357/-105)
debian/patches/0701-enable-snap-policy-module.patch (+25/-0)
debian/patches/series (+3/-6)
debian/pulseaudio.install (+1/-1)
debian/rules (+1/-1)
dev/null (+0/-102)
Reviewer Review Type Date Requested Status
Ken VanDine Approve
Daniel van Vugt Needs Fixing
Review via email: mp+352558@code.launchpad.net

Commit message

Update snap policy to make access to audio recording conditional on plugging the "pulseaudio" or "audio-record" interfaces.

Description of the change

The current snap policy module cannot be enabled on desktop Ubuntu systems because it blocks audio recording to all snap confined applications, which breaks many of the snaps available on the store (e.g. Skype is not particularly useful if it can't access the microphone).

On the snapd side, the plan is to introduce new "audio-playback" and "audio-record" interfaces so we can identify apps that actually require microphone access.

On the PulseAudio side, the snap policy module needs to check what interfaces the client has plugged. We use snapd-glib to check whether either of the legacy "pulseaudio" or "audio-record" interfaces are plugged.

The implementation is complicated by the fact that snapd-glib depends on the GLib main loop, while pulse audio has its own incompatible event loop. So we instead run the GLib main loop in a separate thread and pass messages back and forward as needed.

I've also updated the default configuration file to actually enable the module too, since it should now function correctly.

To post a comment you must log in.
Revision history for this message
Daniel van Vugt (vanvugt) wrote :

(1) You can drop the prereq branch if it's convenient. It doesn't exist any more because 'ubuntu' is identical.

(2) I get a build failure using this branch:

modules/module-snap-policy.c: In function ‘module_snap_policy_LTX_pa__done’:
/usr/include/glib-2.0/glib/gmem.h:120:7: error: too few arguments to function ‘pa_asyncq_free’
       (destroy) (_ptr); \
       ^
modules/module-snap-policy.c:340:5: note: in expansion of macro ‘g_clear_pointer’
     g_clear_pointer(&u->results, pa_asyncq_free);
     ^~~~~~~~~~~~~~~
In file included from modules/module-snap-policy.c:31:
./pulsecore/asyncq.h:44:6: note: declared here
 void pa_asyncq_free(pa_asyncq* q, pa_free_cb_t free_cb);
      ^~~~~~~~~~~~~~

(3) You're now a member of ~ubuntu-audio-dev so no need to ask for a review next time.

review: Needs Fixing
Revision history for this message
Daniel van Vugt (vanvugt) wrote :

(4) Just make sure module-snap-policy doesn't affect deb users negatively at all.

Revision history for this message
James Henstridge (jamesh) wrote :

As discussed on IRC, I've dropped the trust-store specific patches (which haven't been built since February according to bug 1739469), keeping the patches necessary for the snap policy module to hook in.

Revision history for this message
Daniel van Vugt (vanvugt) wrote :

(5) changelog needs to now mention the removal of trust store patches :)

review: Needs Fixing
Revision history for this message
Ken VanDine (ken-vandine) wrote :

jamesh had fixed the changelog, it's been uploaded and merged

review: Approve

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 c797d51..e68a037 100644
3--- a/debian/changelog
4+++ b/debian/changelog
5@@ -1,3 +1,15 @@
6+pulseaudio (1:12.2-0ubuntu2) UNRELEASED; urgency=medium
7+
8+ * Update snap policy to make access to audio recording conditional on
9+ plugging the "pulseaudio" or "audio-record" interfaces (LP: #1781428):
10+ - 0700-modules-add-snappy-policy-module.patch: rewrite to query
11+ snapd for the client's plugged interfaces.
12+ - 0701-enable-snap-policy-module.patch: enable the module in the
13+ default configuration.
14+ - Build depend on libsnapd-glib-dev.
15+
16+ -- James Henstridge <james.henstridge@canonical.com> Tue, 07 Aug 2018 17:01:22 +0800
17+
18 pulseaudio (1:12.2-0ubuntu1) cosmic; urgency=medium
19
20 * New upstream release 12.2 (LP: #1785551):
21diff --git a/debian/control b/debian/control
22index 3b2a1f4..e724169 100644
23--- a/debian/control
24+++ b/debian/control
25@@ -33,6 +33,7 @@ Build-Depends: debhelper (>= 10),
26 libltdl-dev,
27 liborc-0.4-dev,
28 libsamplerate0-dev,
29+ libsnapd-glib-dev,
30 libsndfile1-dev,
31 libsoxr-dev (>= 0.1.1),
32 libspeexdsp-dev (>= 1.2~rc1),
33diff --git a/debian/patches/0409-Trust-store-patch.patch b/debian/patches/0409-Trust-store-patch.patch
34deleted file mode 100644
35index 1607c62..0000000
36--- a/debian/patches/0409-Trust-store-patch.patch
37+++ /dev/null
38@@ -1,572 +0,0 @@
39-From ff36148e002232842ea0f07b148e5844c5d44ceb Mon Sep 17 00:00:00 2001
40-From: David Henningsson <david.henningsson@canonical.com>
41-Date: Wed, 22 Jul 2015 16:37:19 +0200
42-Subject: [PATCH 4/5] Trust-store patch
43-
44-...includes some fixes elsewhere as well.
45-
46-Signed-off-by: David Henningsson <david.henningsson@canonical.com>
47----
48- configure.ac | 15 ++
49- src/Makefile.am | 24 +++
50- src/modules/trust-store/module-trust-store.c | 221 +++++++++++++++++++++++++++
51- src/modules/trust-store/truststore.cc | 74 +++++++++
52- src/modules/trust-store/truststore.h | 41 +++++
53- src/pulsecore/client.h | 4 +
54- src/pulsecore/creds.h | 1 +
55- src/pulsecore/iochannel.c | 2 +
56- src/pulsecore/protocol-native.c | 13 ++
57- src/pulsecore/tagstruct.c | 1 +
58- 12 files changed, 399 insertions(+), 7 deletions(-)
59- create mode 100644 src/modules/trust-store/module-trust-store.c
60- create mode 100644 src/modules/trust-store/truststore.cc
61- create mode 100644 src/modules/trust-store/truststore.h
62-
63-Index: pulseaudio/configure.ac
64-===================================================================
65---- pulseaudio.orig/configure.ac
66-+++ pulseaudio/configure.ac
67-@@ -1447,6 +1447,19 @@ AS_IF([test "x$ax_pthread_ok" = "xyes"],
68- AC_DEFINE([_POSIX_PTHREAD_SEMANTICS], 1, [Needed on Solaris]))
69-
70-
71-+# Ubuntu touch trust store
72-+
73-+AC_ARG_ENABLE([trust-store],
74-+ AS_HELP_STRING([--enable-trust-store], [Enable Ubuntu touch trust store]))
75-+
76-+AS_IF([test "x$enable_trust_store" != "xno"],
77-+ [PKG_CHECK_MODULES(TRUST_STORE, [ trust-store ], [HAVE_TRUST_STORE=1], [HAVE_TRUST_STORE=0])],
78-+ [HAVE_WEBRTC=0])
79-+
80-+AS_IF([test "x$enable_trust_store" = "xyes" && test "x$HAVE_TRUST_STORE" = "x0"],
81-+ [AC_MSG_ERROR([*** Ubuntu touch trust store library not found])])
82-+
83-+AM_CONDITIONAL([HAVE_TRUST_STORE], [test "x$HAVE_TRUST_STORE" = "x1"])
84-
85- ###################################
86- # Output #
87-@@ -1619,6 +1632,7 @@ AS_IF([test "x$HAVE_ADRIAN_EC" = "x1"],
88- AS_IF([test "x$HAVE_SPEEX" = "x1"], ENABLE_SPEEX=yes, ENABLE_SPEEX=no)
89- AS_IF([test "x$HAVE_SOXR" = "x1"], ENABLE_SOXR=yes, ENABLE_SOXR=no)
90- AS_IF([test "x$HAVE_WEBRTC" = "x1"], ENABLE_WEBRTC=yes, ENABLE_WEBRTC=no)
91-+AS_IF([test "x$HAVE_TRUST_STORE" = "x1"], ENABLE_TRUST_STORE=yes, ENABLE_TRUST_STORE=no)
92- AS_IF([test "x$HAVE_TDB" = "x1"], ENABLE_TDB=yes, ENABLE_TDB=no)
93- AS_IF([test "x$HAVE_GDBM" = "x1"], ENABLE_GDBM=yes, ENABLE_GDBM=no)
94- AS_IF([test "x$HAVE_SIMPLEDB" = "x1"], ENABLE_SIMPLEDB=yes, ENABLE_SIMPLEDB=no)
95-@@ -1683,6 +1697,7 @@ echo "
96- Enable speex (resampler, AEC): ${ENABLE_SPEEX}
97- Enable soxr (resampler): ${ENABLE_SOXR}
98- Enable WebRTC echo canceller: ${ENABLE_WEBRTC}
99-+ Enable Ubuntu trust store: ${ENABLE_TRUST_STORE}
100- Enable gcov coverage: ${ENABLE_GCOV}
101- Enable unit tests: ${ENABLE_TESTS}
102- Database
103-Index: pulseaudio/src/Makefile.am
104-===================================================================
105---- pulseaudio.orig/src/Makefile.am
106-+++ pulseaudio/src/Makefile.am
107-@@ -1105,6 +1105,10 @@ if HAVE_WEBRTC
108- modlibexec_LTLIBRARIES += libwebrtc-util.la
109- endif
110-
111-+if HAVE_TRUST_STORE
112-+modlibexec_LTLIBRARIES += libtruststore-util.la
113-+endif
114-+
115- if HAVE_ESOUND
116- modlibexec_LTLIBRARIES += \
117- libprotocol-esound.la
118-@@ -1235,6 +1239,11 @@ modlibexec_LTLIBRARIES += \
119- module-role-ducking.la \
120- module-allow-passthrough.la
121-
122-+if HAVE_TRUST_STORE
123-+modlibexec_LTLIBRARIES += \
124-+ module-trust-store.la
125-+endif
126-+
127- if HAVE_ESOUND
128- modlibexec_LTLIBRARIES += \
129- module-esound-protocol-tcp.la \
130-@@ -2025,6 +2034,20 @@ module_echo_cancel_la_CFLAGS += -DHAVE_W
131- module_echo_cancel_la_LIBADD += libwebrtc-util.la
132- endif
133-
134-+if HAVE_TRUST_STORE
135-+# Separate helper library to keep C and C++ code apart, like we do for webrtc
136-+libtruststore_util_la_SOURCES = modules/trust-store/truststore.cc
137-+libtruststore_util_la_CXXFLAGS = $(AM_CXXFLAGS) -std=c++11 $(SERVER_CFLAGS) $(TRUST_STORE_CFLAGS) \
138-+ $(DBUS_CFLAGS) -DHAVE_TRUST_STORE=1
139-+libtruststore_util_la_LIBADD = libpulsecore-@PA_MAJORMINOR@.la $(TRUST_STORE_LIBS) $(DBUS_LIBS)
140-+libtruststore_util_la_LDFLAGS = -avoid-version
141-+
142-+module_trust_store_la_SOURCES = modules/trust-store/module-trust-store.c
143-+module_trust_store_la_LDFLAGS = $(MODULE_LDFLAGS)
144-+module_trust_store_la_LIBADD = $(MODULE_LIBADD) libtruststore-util.la
145-+module_trust_store_la_CFLAGS = $(AM_CFLAGS) -DHAVE_TRUST_STORE=1
146-+endif
147-+
148- # RTP modules
149- module_rtp_send_la_SOURCES = modules/rtp/module-rtp-send.c
150- module_rtp_send_la_LDFLAGS = $(MODULE_LDFLAGS)
151-Index: pulseaudio/src/modules/trust-store/module-trust-store.c
152-===================================================================
153---- /dev/null
154-+++ pulseaudio/src/modules/trust-store/module-trust-store.c
155-@@ -0,0 +1,226 @@
156-+/***
157-+ This file is part of PulseAudio.
158-+
159-+ Copyright 2015 Canonical Ltd.
160-+ Written by David Henningsson <david.henningsson@canonical.com>
161-+
162-+ PulseAudio is free software; you can redistribute it and/or modify
163-+ it under the terms of the GNU Lesser General Public License as published
164-+ by the Free Software Foundation; either version 2.1 of the License,
165-+ or (at your option) any later version.
166-+
167-+ PulseAudio is distributed in the hope that it will be useful, but
168-+ WITHOUT ANY WARRANTY; without even the implied warranty of
169-+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
170-+ General Public License for more details.
171-+
172-+ You should have received a copy of the GNU Lesser General Public License
173-+ along with PulseAudio; if not, see <http://www.gnu.org/licenses/>.
174-+***/
175-+#ifdef HAVE_CONFIG_H
176-+#include <config.h>
177-+#endif
178-+
179-+#include <pulsecore/i18n.h>
180-+#include <pulsecore/core.h>
181-+#include <pulsecore/module.h>
182-+#include <pulse/xmalloc.h>
183-+#include <pulsecore/fdsem.h>
184-+#include <pulsecore/thread.h>
185-+#include <pulsecore/core-util.h>
186-+#include <pulse/mainloop-api.h>
187-+
188-+PA_MODULE_AUTHOR("David Henningsson");
189-+PA_MODULE_DESCRIPTION("Ubuntu touch trust store integration");
190-+PA_MODULE_VERSION(PACKAGE_VERSION);
191-+PA_MODULE_LOAD_ONCE(true);
192-+
193-+#include "truststore.h"
194-+
195-+#define REQUEST_GRANTED 1
196-+#define REQUEST_DENIED -1
197-+#define REQUEST_PENDING 0
198-+
199-+struct userdata;
200-+
201-+struct per_client {
202-+ uint32_t index;
203-+ char *appname;
204-+ uid_t uid;
205-+ pid_t pid;
206-+ struct userdata *userdata;
207-+ pa_dynarray *pending_requests;
208-+ pa_atomic_t result;
209-+};
210-+
211-+struct userdata {
212-+ pa_core *core;
213-+ pa_trust_store *ts;
214-+ pa_hashmap *per_clients;
215-+ pa_thread *thread;
216-+ pa_fdsem *fdsem;
217-+ pa_io_event *io_event;
218-+ pa_hook_slot *connect_hook_slot;
219-+};
220-+
221-+static struct per_client *per_client_new(struct userdata *u, uint32_t client_index) {
222-+ struct per_client *pc;
223-+ pa_client *client = pa_idxset_get_by_index(u->core->clients, client_index);
224-+
225-+ pa_assert(client);
226-+ if (!client->creds_valid) {
227-+ pa_log_warn("Client %d has no creds, cannot authenticate", client_index);
228-+ return NULL;
229-+ }
230-+
231-+ pc = pa_xnew0(struct per_client, 1);
232-+ // TODO: Do we need something else than the application name here -
233-+ // the application can probably spoof it
234-+ pc->appname = pa_xstrdup(pa_proplist_gets(client->proplist, PA_PROP_APPLICATION_NAME));
235-+ pc->index = client_index;
236-+ pc->uid = client->creds.uid;
237-+ pc->pid = client->creds.pid;
238-+ pc->pending_requests = pa_dynarray_new(NULL);
239-+ pc->userdata = u;
240-+
241-+ pa_hashmap_put(u->per_clients, (void *) (size_t) client_index, pc);
242-+
243-+ return pc;
244-+}
245-+
246-+static void per_client_free_from_hashmap(void *data) {
247-+ struct per_client *pc = data;
248-+ if (!pc)
249-+ return;
250-+ pa_xfree(pc->appname);
251-+ pa_dynarray_free(pc->pending_requests);
252-+ pa_xfree(pc);
253-+}
254-+
255-+static void thread_func(void *data) {
256-+ struct per_client *pc = data;
257-+
258-+ bool result = pa_trust_store_check(pc->userdata->ts, pc->appname, pc->uid, pc->pid,
259-+ /// TRANSLATORS: The app icon and name appears above this string. If the phrase
260-+ /// can't be translated in this language, translate the whole sentence
261-+ /// 'This app wants to record audio.'
262-+ _("wants to record audio."));
263-+
264-+ pa_atomic_store(&pc->result, result ? REQUEST_GRANTED : REQUEST_DENIED);
265-+ pa_fdsem_post(pc->userdata->fdsem);
266-+}
267-+
268-+static void check_queue(struct userdata *u) {
269-+ struct per_client *pc;
270-+ void *dummy;
271-+
272-+ pa_log_debug("Checking queue, size: %d, thread object: %s",
273-+ pa_hashmap_size(u->per_clients), pa_yes_no(u->thread));
274-+ if (u->thread) {
275-+ pa_access_data *ad;
276-+ unsigned i;
277-+ int result;
278-+ pc = pa_thread_get_data(u->thread);
279-+ result = pa_atomic_load(&pc->result);
280-+ if (result == REQUEST_PENDING)
281-+ return; /* Still processing */
282-+ pa_thread_free(u->thread);
283-+ u->thread = NULL;
284-+
285-+ pa_log_debug("Letting client %d (%s) know the result (%s)",
286-+ pc->index, pc->appname, result == REQUEST_GRANTED ? "granted" : "rejected");
287-+ PA_DYNARRAY_FOREACH(ad, pc->pending_requests, i) {
288-+ ad->async_finish_cb(ad, result == REQUEST_GRANTED);
289-+ }
290-+ pa_hashmap_remove(u->per_clients, (void*) (size_t) pc->index);
291-+ }
292-+
293-+ /* Find a client that needs asking */
294-+ PA_HASHMAP_FOREACH(pc, u->per_clients, dummy) {
295-+ if (u->thread)
296-+ return;
297-+ pa_assert(pa_atomic_load(&pc->result) == REQUEST_PENDING);
298-+ pa_log_debug("Starting thread to ask about client %d (%s)", pc->index,
299-+ pc->appname);
300-+ u->thread = pa_thread_new("trust-store", thread_func, pc);
301-+ }
302-+}
303-+
304-+static void check_fdsem(pa_mainloop_api *a, pa_io_event *e, int fd, pa_io_event_flags_t ee,
305-+ void *userdata) {
306-+ struct userdata *u = userdata;
307-+ pa_fdsem_after_poll(u->fdsem);
308-+ check_queue(u);
309-+ pa_fdsem_before_poll(u->fdsem);
310-+}
311-+
312-+static pa_hook_result_t connect_record_hook(pa_core *core, pa_access_data *d, struct userdata *u) {
313-+ struct per_client *pc = pa_hashmap_get(u->per_clients, (void*) (size_t) d->client_index);
314-+ int r;
315-+ if (!pc)
316-+ pc = per_client_new(u, d->client_index);
317-+
318-+ r = pa_atomic_load(&pc->result);
319-+ pa_log_debug("Checking permission to record for client %d (%s) ", d->client_index,
320-+ r == REQUEST_GRANTED ? "granted" : r != REQUEST_PENDING ? "rejected" : "unknown");
321-+ if (r == REQUEST_GRANTED) return PA_HOOK_OK;
322-+ if (r != REQUEST_PENDING) return PA_HOOK_STOP;
323-+
324-+ pa_dynarray_append(pc->pending_requests, d);
325-+ check_queue(u);
326-+ return PA_HOOK_CANCEL;
327-+}
328-+
329-+/* Test code - remove from final product */
330-+static void test(struct userdata *u) {
331-+ uint32_t dummy;
332-+ pa_client *client;
333-+
334-+ PA_IDXSET_FOREACH(client, u->core->clients, dummy) {
335-+ if (client->creds_valid)
336-+ pa_trust_store_check(u->ts, "The evil app", client->creds.uid,
337-+ client->creds.pid, "%1% wants to eat your laundry.");
338-+ }
339-+}
340-+
341-+int pa__init(pa_module *m) {
342-+ struct userdata *u;
343-+ pa_trust_store *ts = pa_trust_store_new();
344-+ if (ts == NULL)
345-+ return -1;
346-+ u = pa_xnew0(struct userdata, 1);
347-+ u->ts = ts;
348-+ u->core = m->core;
349-+ u->per_clients = pa_hashmap_new_full(pa_idxset_trivial_hash_func, pa_idxset_trivial_compare_func,
350-+ NULL, per_client_free_from_hashmap);
351-+ m->userdata = u;
352-+ u->connect_hook_slot = pa_hook_connect(&m->core->access[PA_ACCESS_HOOK_CONNECT_RECORD],
353-+ PA_HOOK_NORMAL, (pa_hook_cb_t) connect_record_hook, u);
354-+
355-+ pa_assert_se(u->fdsem = pa_fdsem_new());
356-+ pa_assert_se(u->io_event = m->core->mainloop->io_new(m->core->mainloop,
357-+ pa_fdsem_get(u->fdsem), PA_IO_EVENT_INPUT, check_fdsem, u));
358-+ pa_fdsem_before_poll(u->fdsem);
359-+
360-+ test(u);
361-+ return 0;
362-+}
363-+
364-+void pa__done(pa_module *m) {
365-+ struct userdata *u = m->userdata;
366-+ if (u) {
367-+ if (u->connect_hook_slot)
368-+ pa_hook_slot_free(u->connect_hook_slot);
369-+ if (u->thread)
370-+ pa_thread_free(u->thread);
371-+ if (u->io_event)
372-+ m->core->mainloop->io_free(u->io_event);
373-+ if (u->fdsem)
374-+ pa_fdsem_free(u->fdsem);
375-+ if (u->per_clients)
376-+ pa_hashmap_free(u->per_clients);
377-+ if (u->ts)
378-+ pa_trust_store_free(u->ts);
379-+ pa_xfree(u);
380-+ }
381-+}
382-Index: pulseaudio/src/modules/trust-store/truststore.cc
383-===================================================================
384---- /dev/null
385-+++ pulseaudio/src/modules/trust-store/truststore.cc
386-@@ -0,0 +1,74 @@
387-+#ifdef HAVE_CONFIG_H
388-+#include <config.h>
389-+#endif
390-+
391-+#include <memory>
392-+#include <core/dbus/bus.h>
393-+#include <core/trust/dbus_agent.h>
394-+#include <core/trust/agent.h>
395-+
396-+#include <pulse/cdecl.h>
397-+
398-+PA_C_DECL_BEGIN
399-+#include <pulsecore/core-util.h>
400-+#include <pulse/xmalloc.h>
401-+#include <pulsecore/log.h>
402-+
403-+#include "truststore.h"
404-+PA_C_DECL_END
405-+
406-+class TrustStore {
407-+public:
408-+ std::shared_ptr<core::trust::Agent> agent;
409-+};
410-+
411-+pa_trust_store* pa_trust_store_new() {
412-+ try {
413-+ auto bus = std::make_shared<core::dbus::Bus>(core::dbus::WellKnownBus::session);
414-+ auto agent = core::trust::dbus::create_multi_user_agent_for_bus_connection(bus, "PulseAudio");
415-+ auto ts = new TrustStore();
416-+ ts->agent = agent;
417-+ return (pa_trust_store *) ts;
418-+ } catch(const std::exception &e) {
419-+ pa_log_error("Could not create Ubuntu touch trust store connection: %s",
420-+ e.what());
421-+ } catch(...) {
422-+ pa_log_error("Could not create Ubuntu touch trust store connection");
423-+ return NULL;
424-+ }
425-+}
426-+
427-+void pa_trust_store_free(pa_trust_store *t) {
428-+ pa_assert(t != NULL);
429-+ auto ts = (TrustStore*) t;
430-+ delete ts;
431-+}
432-+
433-+bool pa_trust_store_check(pa_trust_store *t, const char *appname,
434-+ uid_t uid, pid_t pid, const char *description) {
435-+ auto ts = (TrustStore*) t;
436-+ try {
437-+
438-+ core::trust::Agent::RequestParameters params {
439-+ core::trust::Uid{uid},
440-+ core::trust::Pid{pid},
441-+ appname,
442-+ core::trust::Feature{0},
443-+ description
444-+ };
445-+ pa_log_debug("Asking Ubuntu touch trust store for permission (app: %s)",
446-+ params.application.id.c_str());
447-+ auto answer = ts->agent->authenticate_request_with_parameters(params);
448-+ if (answer == core::trust::Request::Answer::granted) {
449-+ pa_log_debug("Request granted.");
450-+ return true;
451-+ }
452-+ pa_log_info("Request denied.");
453-+ } catch(const std::exception &e) {
454-+ pa_log_error("Could not ask Ubuntu touch trust store for permission: %s",
455-+ e.what());
456-+ } catch(...) {
457-+ pa_log_error("Could not ask Ubuntu touch trust store for permission");
458-+ }
459-+ return false;
460-+}
461-Index: pulseaudio/src/modules/trust-store/truststore.h
462-===================================================================
463---- /dev/null
464-+++ pulseaudio/src/modules/trust-store/truststore.h
465-@@ -0,0 +1,41 @@
466-+/***
467-+ This file is part of PulseAudio.
468-+
469-+ Copyright 2015 Canonical Ltd.
470-+ Written by David Henningsson <david.henningsson@canonical.com>
471-+
472-+ PulseAudio is free software; you can redistribute it and/or modify
473-+ it under the terms of the GNU Lesser General Public License as published
474-+ by the Free Software Foundation; either version 2.1 of the License,
475-+ or (at your option) any later version.
476-+
477-+ PulseAudio is distributed in the hope that it will be useful, but
478-+ WITHOUT ANY WARRANTY; without even the implied warranty of
479-+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
480-+ General Public License for more details.
481-+
482-+ You should have received a copy of the GNU Lesser General Public License
483-+ along with PulseAudio; if not, see <http://www.gnu.org/licenses/>.
484-+***/
485-+
486-+#ifndef footruststorehfoo
487-+#define footruststorehfoo
488-+
489-+#ifdef HAVE_CONFIG_H
490-+#include <config.h>
491-+#endif
492-+
493-+#include <pulsecore/creds.h>
494-+
495-+#ifdef HAVE_TRUST_STORE
496-+PA_C_DECL_BEGIN
497-+typedef struct pa_trust_store pa_trust_store;
498-+
499-+pa_trust_store* pa_trust_store_new();
500-+void pa_trust_store_free(pa_trust_store *ts);
501-+bool pa_trust_store_check(pa_trust_store *ts, const char *appname,
502-+ uid_t uid, pid_t pid, const char *description);
503-+PA_C_DECL_END
504-+#endif
505-+
506-+#endif
507-Index: pulseaudio/src/pulsecore/client.h
508-===================================================================
509---- pulseaudio.orig/src/pulsecore/client.h
510-+++ pulseaudio/src/pulsecore/client.h
511-@@ -26,6 +26,7 @@
512- #include <pulse/proplist.h>
513- #include <pulsecore/core.h>
514- #include <pulsecore/module.h>
515-+#include <pulsecore/creds.h>
516-
517- /* Every connection to the server should have a pa_client
518- * attached. That way the user may generate a listing of all connected
519-@@ -35,6 +36,9 @@ struct pa_client {
520- uint32_t index;
521- pa_core *core;
522-
523-+ pa_creds creds;
524-+ bool creds_valid;
525-+
526- pa_proplist *proplist;
527- pa_module *module;
528- char *driver;
529-Index: pulseaudio/src/pulsecore/creds.h
530-===================================================================
531---- pulseaudio.orig/src/pulsecore/creds.h
532-+++ pulseaudio/src/pulsecore/creds.h
533-@@ -41,6 +41,7 @@ typedef struct pa_cmsg_ancil_data pa_cms
534- struct pa_creds {
535- gid_t gid;
536- uid_t uid;
537-+ pid_t pid;
538- };
539-
540- /* Struct for handling ancillary data, i e, extra data that can be sent together with a message
541-Index: pulseaudio/src/pulsecore/iochannel.c
542-===================================================================
543---- pulseaudio.orig/src/pulsecore/iochannel.c
544-+++ pulseaudio/src/pulsecore/iochannel.c
545-@@ -323,6 +323,7 @@ ssize_t pa_iochannel_write_with_creds(pa
546-
547- u = (struct ucred*) CMSG_DATA(&cmsg.hdr);
548-
549-+ /* FIXME: Check whether ucred->pid should be used */
550- u->pid = getpid();
551- if (ucred) {
552- u->uid = ucred->uid;
553-@@ -445,6 +446,7 @@ ssize_t pa_iochannel_read_with_ancil_dat
554-
555- ancil_data->creds.gid = u.gid;
556- ancil_data->creds.uid = u.uid;
557-+ ancil_data->creds.pid = u.pid;
558- ancil_data->creds_valid = true;
559- }
560- else if (cmh->cmsg_type == SCM_RIGHTS) {
561-Index: pulseaudio/src/pulsecore/protocol-native.c
562-===================================================================
563---- pulseaudio.orig/src/pulsecore/protocol-native.c
564-+++ pulseaudio/src/pulsecore/protocol-native.c
565-@@ -2668,6 +2668,13 @@ static void command_auth(pa_pdispatch *p
566- do_shm = false;
567-
568- #ifdef HAVE_CREDS
569-+ {
570-+ const pa_creds *creds;
571-+ if ((creds = pa_pdispatch_creds(pd))) {
572-+ c->client->creds = *creds;
573-+ c->client->creds_valid = true;
574-+ }
575-+ }
576- if (do_shm) {
577- /* Only enable SHM if both sides are owned by the same
578- * user. This is a security measure because otherwise data
579-@@ -5631,6 +5638,7 @@ typedef struct pa_protocol_native_access
580- } pa_protocol_native_access_data;
581-
582- static void check_access_finish_cb(pa_access_data *data, bool res) {
583-+ uint32_t command, tag;
584- pa_protocol_native_access_data *d = (pa_protocol_native_access_data *) data;
585- pa_native_connection *c = PA_NATIVE_CONNECTION(d->userdata);
586-
587-@@ -5639,6 +5647,11 @@ static void check_access_finish_cb(pa_ac
588- goto finish;
589- }
590-
591-+ pa_assert_se(pa_tagstruct_getu32(d->tc, &command) >= 0);
592-+ pa_assert_se(pa_tagstruct_getu32(d->tc, &tag) >= 0);
593-+ pa_assert(command == d->command);
594-+ pa_assert(tag == d->tag);
595-+
596- /* call the dispatcher again, hopefully this time, the access check will
597- * fail or succeed immediately */
598- command_table[d->command](d->pd, d->command, d->tag, d->tc, d->userdata);
599-Index: pulseaudio/po/POTFILES.in
600-===================================================================
601---- pulseaudio.orig/po/POTFILES.in
602-+++ pulseaudio/po/POTFILES.in
603-@@ -23,6 +23,7 @@ src/modules/jack/module-jack-sink.c
604- src/modules/jack/module-jack-source.c
605- src/modules/macosx/module-coreaudio-device.c
606- src/modules/module-allow-passthrough.c
607-+src/modules/trust-store/module-trust-store.c
608- src/modules/module-always-sink.c
609- src/modules/module-always-source.c
610- src/modules/module-cli.c
611diff --git a/debian/patches/0409-pa-client-peer-credentials.patch b/debian/patches/0409-pa-client-peer-credentials.patch
612new file mode 100644
613index 0000000..d6d7ff6
614--- /dev/null
615+++ b/debian/patches/0409-pa-client-peer-credentials.patch
616@@ -0,0 +1,104 @@
617+From: David Henningsson <david.henningsson@canonical.com>
618+Date: Wed, 22 Jul 2015 16:37:19 +0200
619+Subject: [PATCH 4/5] Expose peer credentials on pa_client
620+
621+Signed-off-by: David Henningsson <david.henningsson@canonical.com>
622+---
623+ src/pulsecore/client.h | 4 ++++
624+ src/pulsecore/creds.h | 1 +
625+ src/pulsecore/iochannel.c | 2 ++
626+ src/pulsecore/protocol-native.c | 13 +++++++++++++
627+ 4 files changed, 20 insertions(+)
628+
629+diff --git a/src/pulsecore/client.h b/src/pulsecore/client.h
630+index eb8173d..a038a0c 100644
631+--- a/src/pulsecore/client.h
632++++ b/src/pulsecore/client.h
633+@@ -26,6 +26,7 @@
634+ #include <pulse/proplist.h>
635+ #include <pulsecore/core.h>
636+ #include <pulsecore/module.h>
637++#include <pulsecore/creds.h>
638+
639+ /* Every connection to the server should have a pa_client
640+ * attached. That way the user may generate a listing of all connected
641+@@ -35,6 +36,9 @@ struct pa_client {
642+ uint32_t index;
643+ pa_core *core;
644+
645++ pa_creds creds;
646++ bool creds_valid;
647++
648+ pa_proplist *proplist;
649+ pa_module *module;
650+ char *driver;
651+diff --git a/src/pulsecore/creds.h b/src/pulsecore/creds.h
652+index 9fdbb4f..8bcf636 100644
653+--- a/src/pulsecore/creds.h
654++++ b/src/pulsecore/creds.h
655+@@ -41,6 +41,7 @@ typedef struct pa_cmsg_ancil_data pa_cmsg_ancil_data;
656+ struct pa_creds {
657+ gid_t gid;
658+ uid_t uid;
659++ pid_t pid;
660+ };
661+
662+ /* Struct for handling ancillary data, i e, extra data that can be sent together with a message
663+diff --git a/src/pulsecore/iochannel.c b/src/pulsecore/iochannel.c
664+index e25824b..3c83092 100644
665+--- a/src/pulsecore/iochannel.c
666++++ b/src/pulsecore/iochannel.c
667+@@ -323,6 +323,7 @@ ssize_t pa_iochannel_write_with_creds(pa_iochannel*io, const void*data, size_t l
668+
669+ u = (struct ucred*) CMSG_DATA(&cmsg.hdr);
670+
671++ /* FIXME: Check whether ucred->pid should be used */
672+ u->pid = getpid();
673+ if (ucred) {
674+ u->uid = ucred->uid;
675+@@ -445,6 +446,7 @@ ssize_t pa_iochannel_read_with_ancil_data(pa_iochannel*io, void*data, size_t l,
676+
677+ ancil_data->creds.gid = u.gid;
678+ ancil_data->creds.uid = u.uid;
679++ ancil_data->creds.pid = u.pid;
680+ ancil_data->creds_valid = true;
681+ }
682+ else if (cmh->cmsg_type == SCM_RIGHTS) {
683+diff --git a/src/pulsecore/protocol-native.c b/src/pulsecore/protocol-native.c
684+index f7dc338..baaa952 100644
685+--- a/src/pulsecore/protocol-native.c
686++++ b/src/pulsecore/protocol-native.c
687+@@ -2668,6 +2668,13 @@ static void command_auth(pa_pdispatch *pd, uint32_t command, uint32_t tag, pa_ta
688+ do_shm = false;
689+
690+ #ifdef HAVE_CREDS
691++ {
692++ const pa_creds *creds;
693++ if ((creds = pa_pdispatch_creds(pd))) {
694++ c->client->creds = *creds;
695++ c->client->creds_valid = true;
696++ }
697++ }
698+ if (do_shm) {
699+ /* Only enable SHM if both sides are owned by the same
700+ * user. This is a security measure because otherwise data
701+@@ -5631,6 +5638,7 @@ typedef struct pa_protocol_native_access_data {
702+ } pa_protocol_native_access_data;
703+
704+ static void check_access_finish_cb(pa_access_data *data, bool res) {
705++ uint32_t command, tag;
706+ pa_protocol_native_access_data *d = (pa_protocol_native_access_data *) data;
707+ pa_native_connection *c = PA_NATIVE_CONNECTION(d->userdata);
708+
709+@@ -5639,6 +5647,11 @@ static void check_access_finish_cb(pa_access_data *data, bool res) {
710+ goto finish;
711+ }
712+
713++ pa_assert_se(pa_tagstruct_getu32(d->tc, &command) >= 0);
714++ pa_assert_se(pa_tagstruct_getu32(d->tc, &tag) >= 0);
715++ pa_assert(command == d->command);
716++ pa_assert(tag == d->tag);
717++
718+ /* call the dispatcher again, hopefully this time, the access check will
719+ * fail or succeed immediately */
720+ command_table[d->command](d->pd, d->command, d->tag, d->tc, d->userdata);
721diff --git a/debian/patches/0410-Add-thread-to-activate-trust-store-interface.patch b/debian/patches/0410-Add-thread-to-activate-trust-store-interface.patch
722deleted file mode 100644
723index 721ce11..0000000
724--- a/debian/patches/0410-Add-thread-to-activate-trust-store-interface.patch
725+++ /dev/null
726@@ -1,108 +0,0 @@
727-From 90dbf1d25e12b9cfc86aecbd02f14a05fd5dca8c Mon Sep 17 00:00:00 2001
728-From: Alfonso Sanchez-Beato <alfonso.sanchez-beato@canonical.com>
729-Date: Fri, 7 Aug 2015 09:08:02 +0200
730-Subject: [PATCH] Add thread to activate trust-store interface
731-
732----
733- src/modules/trust-store/module-trust-store.c | 14 +-------------
734- src/modules/trust-store/truststore.cc | 19 +++++++++++++++++++
735- 2 files changed, 20 insertions(+), 13 deletions(-)
736-
737-Index: pulseaudio/src/modules/trust-store/module-trust-store.c
738-===================================================================
739---- pulseaudio.orig/src/modules/trust-store/module-trust-store.c
740-+++ pulseaudio/src/modules/trust-store/module-trust-store.c
741-@@ -28,6 +28,7 @@
742- #include <pulsecore/fdsem.h>
743- #include <pulsecore/thread.h>
744- #include <pulsecore/core-util.h>
745-+#include <pulsecore/dynarray.h>
746- #include <pulse/mainloop-api.h>
747-
748- PA_MODULE_AUTHOR("David Henningsson");
749-@@ -171,18 +172,6 @@ static pa_hook_result_t connect_record_h
750- return PA_HOOK_CANCEL;
751- }
752-
753--/* Test code - remove from final product */
754--static void test(struct userdata *u) {
755-- uint32_t dummy;
756-- pa_client *client;
757--
758-- PA_IDXSET_FOREACH(client, u->core->clients, dummy) {
759-- if (client->creds_valid)
760-- pa_trust_store_check(u->ts, "The evil app", client->creds.uid,
761-- client->creds.pid, "%1% wants to eat your laundry.");
762-- }
763--}
764--
765- int pa__init(pa_module *m) {
766- struct userdata *u;
767- pa_trust_store *ts = pa_trust_store_new();
768-@@ -202,7 +191,6 @@ int pa__init(pa_module *m) {
769- pa_fdsem_get(u->fdsem), PA_IO_EVENT_INPUT, check_fdsem, u));
770- pa_fdsem_before_poll(u->fdsem);
771-
772-- test(u);
773- return 0;
774- }
775-
776-Index: pulseaudio/src/modules/trust-store/truststore.cc
777-===================================================================
778---- pulseaudio.orig/src/modules/trust-store/truststore.cc
779-+++ pulseaudio/src/modules/trust-store/truststore.cc
780-@@ -4,6 +4,7 @@
781-
782- #include <memory>
783- #include <core/dbus/bus.h>
784-+#include <core/dbus/asio/executor.h>
785- #include <core/trust/dbus_agent.h>
786- #include <core/trust/agent.h>
787-
788-@@ -13,6 +14,7 @@ PA_C_DECL_BEGIN
789- #include <pulsecore/core-util.h>
790- #include <pulse/xmalloc.h>
791- #include <pulsecore/log.h>
792-+#include <pulsecore/thread.h>
793-
794- #include "truststore.h"
795- PA_C_DECL_END
796-@@ -20,14 +22,27 @@ PA_C_DECL_END
797- class TrustStore {
798- public:
799- std::shared_ptr<core::trust::Agent> agent;
800-+ std::shared_ptr<core::dbus::Bus> bus;
801-+ pa_thread *thread;
802- };
803-
804-+static void thread_func(void *data) {
805-+ class TrustStore *ts = (class TrustStore *) data;
806-+
807-+ ts->bus->run();
808-+}
809-+
810- pa_trust_store* pa_trust_store_new() {
811- try {
812- auto bus = std::make_shared<core::dbus::Bus>(core::dbus::WellKnownBus::session);
813-+ bus->install_executor(core::dbus::asio::make_executor(bus));
814-+
815- auto agent = core::trust::dbus::create_multi_user_agent_for_bus_connection(bus, "PulseAudio");
816- auto ts = new TrustStore();
817- ts->agent = agent;
818-+ ts->bus = bus;
819-+ ts->thread = pa_thread_new("trust-store-bus", thread_func, ts);
820-+
821- return (pa_trust_store *) ts;
822- } catch(const std::exception &e) {
823- pa_log_error("Could not create Ubuntu touch trust store connection: %s",
824-@@ -41,6 +56,10 @@ pa_trust_store* pa_trust_store_new() {
825- void pa_trust_store_free(pa_trust_store *t) {
826- pa_assert(t != NULL);
827- auto ts = (TrustStore*) t;
828-+ if (ts->thread) {
829-+ ts->bus->stop();
830-+ pa_thread_free(ts->thread);
831-+ }
832- delete ts;
833- }
834-
835diff --git a/debian/patches/0417-increase-timeout-check-apparmor.patch b/debian/patches/0417-increase-timeout-check-apparmor.patch
836deleted file mode 100644
837index 2c746f7..0000000
838--- a/debian/patches/0417-increase-timeout-check-apparmor.patch
839+++ /dev/null
840@@ -1,102 +0,0 @@
841-Index: pulseaudio/src/modules/trust-store/module-trust-store.c
842-===================================================================
843---- pulseaudio.orig/src/modules/trust-store/module-trust-store.c
844-+++ pulseaudio/src/modules/trust-store/module-trust-store.c
845-@@ -31,6 +31,8 @@
846- #include <pulsecore/dynarray.h>
847- #include <pulse/mainloop-api.h>
848-
849-+#include <sys/apparmor.h>
850-+
851- PA_MODULE_AUTHOR("David Henningsson");
852- PA_MODULE_DESCRIPTION("Ubuntu touch trust store integration");
853- PA_MODULE_VERSION(PACKAGE_VERSION);
854-@@ -75,9 +77,37 @@ static struct per_client *per_client_new
855- }
856-
857- pc = pa_xnew0(struct per_client, 1);
858-- // TODO: Do we need something else than the application name here -
859-- // the application can probably spoof it
860-- pc->appname = pa_xstrdup(pa_proplist_gets(client->proplist, PA_PROP_APPLICATION_NAME));
861-+
862-+ pa_log_info("Client application name is: '%s'", pa_proplist_gets(client->proplist, PA_PROP_APPLICATION_NAME));
863-+
864-+ // ask apparmor about the context of the client, later this will be used to decide if the
865-+ // app should be or not using the trust store
866-+
867-+ if (aa_is_enabled()) {
868-+ char *context = NULL;
869-+ char *mode = NULL;
870-+
871-+ /* XXX: The mode string is *NOT* be freed since it forms
872-+ * part of the allocation returned in context.
873-+ *
874-+ * See aa_gettaskcon(2) for details.
875-+ */
876-+ if (aa_gettaskcon (client->creds.pid, &context, &mode) >= 0) {
877-+ pc->appname = pa_xstrdup(context);
878-+ pa_log_info("Client apparmor profile is: '%s'", context);
879-+ } else {
880-+ pa_log_error("AppArmo profile could not be retrieved.");
881-+ }
882-+
883-+ if (context)
884-+ free(context);
885-+
886-+ } else {
887-+ // while we do leave the appname as empty if we fail, if apparmor is not present we should
888-+ // assume that the app is not confined
889-+ pc->appname = pa_xstrdup("unconfined");
890-+ }
891-+
892- pc->index = client_index;
893- pc->uid = client->creds.uid;
894- pc->pid = client->creds.pid;
895-@@ -101,13 +131,28 @@ static void per_client_free_from_hashmap
896- static void thread_func(void *data) {
897- struct per_client *pc = data;
898-
899-- bool result = pa_trust_store_check(pc->userdata->ts, pc->appname, pc->uid, pc->pid,
900-- /// TRANSLATORS: The app icon and name appears above this string. If the phrase
901-- /// can't be translated in this language, translate the whole sentence
902-- /// 'This app wants to record audio.'
903-- _("wants to record audio."));
904-+ // there are 3 possible values for the app name that we will consider at this point
905-+ // * empty string: there was an error when retrieving the value and therefore we will
906-+ // automatically deny access
907-+ // * unconfined: the app is unconfined and therefore we will automatically grant access
908-+ // * appname: we need the user to decide what to do.
909-+
910-+ if (pc->appname == NULL) {
911-+ pa_log_info("Client apparmor could not retrieved.");
912-+ pa_atomic_store(&pc->result, REQUEST_DENIED);
913-+ } else if (pa_streq(pc->appname, "unconfined")) {
914-+ pa_log_info("Connected client is unconfined.");
915-+ pa_atomic_store(&pc->result, REQUEST_GRANTED);
916-+ } else {
917-+ pa_log_info("User needs to authorize the application..");
918-+ bool result = pa_trust_store_check(pc->userdata->ts, pc->appname, pc->uid, pc->pid,
919-+ /// TRANSLATORS: The app icon and name appears above this string. If the phrase
920-+ /// can't be translated in this language, translate the whole sentence
921-+ /// 'This app wants to record audio.'
922-+ _("wants to record audio."));
923-+ pa_atomic_store(&pc->result, result ? REQUEST_GRANTED : REQUEST_DENIED);
924-+ }
925-
926-- pa_atomic_store(&pc->result, result ? REQUEST_GRANTED : REQUEST_DENIED);
927- pa_fdsem_post(pc->userdata->fdsem);
928- }
929-
930-Index: pulseaudio/src/Makefile.am
931-===================================================================
932---- pulseaudio.orig/src/Makefile.am
933-+++ pulseaudio/src/Makefile.am
934-@@ -2043,7 +2043,7 @@ libtruststore_util_la_LIBADD = libpulsec
935- libtruststore_util_la_LDFLAGS = -avoid-version
936-
937- module_trust_store_la_SOURCES = modules/trust-store/module-trust-store.c
938--module_trust_store_la_LDFLAGS = $(MODULE_LDFLAGS)
939-+module_trust_store_la_LDFLAGS = $(MODULE_LDFLAGS) -lapparmor
940- module_trust_store_la_LIBADD = $(MODULE_LIBADD) libtruststore-util.la
941- module_trust_store_la_CFLAGS = $(AM_CFLAGS) -DHAVE_TRUST_STORE=1
942- endif
943diff --git a/debian/patches/0700-modules-add-snappy-policy-module.patch b/debian/patches/0700-modules-add-snappy-policy-module.patch
944index 2425ec7..6ac2da7 100644
945--- a/debian/patches/0700-modules-add-snappy-policy-module.patch
946+++ b/debian/patches/0700-modules-add-snappy-policy-module.patch
947@@ -1,56 +1,101 @@
948-From a430ebc2271f5a07389ee25631a8ba5524371764 Mon Sep 17 00:00:00 2001
949-From: Simon Fels <simon.fels@canonical.com>
950-Date: Tue, 17 May 2016 17:29:31 +0200
951-Subject: [PATCH] modules: add snappy policy module
952+From: James Henstridge <james.henstridge@canonical.com>
953+Date: Tue, 7 Aug 2018 12:40:59 +0800
954+Subject: [PATCH] modules: add snap policy module
955
956+Co-authored-by: Simon Fels <simon.fels@canonical.com>
957 ---
958- configure.ac | 18 +++++++-
959- src/Makefile.am | 18 ++++++++
960- src/modules/module-snappy-policy.c | 94 ++++++++++++++++++++++++++++++++++++++
961- 3 files changed, 129 insertions(+), 1 deletion(-)
962- create mode 100644 src/modules/module-snappy-policy.c
963+ configure.ac | 17 ++
964+ src/Makefile.am | 13 ++
965+ src/modules/module-snap-policy.c | 347 +++++++++++++++++++++++++++++++++++++++
966+ 3 files changed, 377 insertions(+)
967+ create mode 100644 src/modules/module-snap-policy.c
968
969-Index: pulseaudio/src/Makefile.am
970-===================================================================
971---- pulseaudio.orig/src/Makefile.am
972-+++ pulseaudio/src/Makefile.am
973-@@ -1250,6 +1250,11 @@ modlibexec_LTLIBRARIES += \
974+diff --git a/configure.ac b/configure.ac
975+index c9c414f..97c2d9d 100644
976+--- a/configure.ac
977++++ b/configure.ac
978+@@ -1446,6 +1446,21 @@ AS_IF([test "x$os_is_win32" != "x1"],
979+ AS_IF([test "x$ax_pthread_ok" = "xyes"],
980+ AC_DEFINE([_POSIX_PTHREAD_SEMANTICS], 1, [Needed on Solaris]))
981+
982++# Snappy support
983++
984++AC_ARG_ENABLE([snap],
985++ AS_HELP_STRING([--enable-snap], [Enable snap support]))
986++
987++have_apparmor=0
988++have_snapd_glib=0
989++AS_IF([test "x$enable_snap" != "xno"],
990++ [PKG_CHECK_MODULES(APPARMOR, [libapparmor], [have_apparmor=1])
991++ PKG_CHECK_MODULES(SNAPD_GLIB, [snapd-glib], [have_snapd_glib=1])])
992++
993++AS_IF([test "x$enable_snap" = "xyes" && test "x$have_apparmor" = "x0" -o "x$have-snapd_glib" = "x0"],
994++ [AC_MSG_ERROR([*** Snap module dependencies missing])])
995++
996++AM_CONDITIONAL([BUILD_SNAP], [test "x$enable_snap" = "xyes"])
997+
998+
999+ ###################################
1000+@@ -1627,6 +1642,7 @@ AS_IF([test "x$HAVE_ESOUND" = "x1" -a "x$USE_PER_USER_ESOUND_SOCKET" = "x1"], EN
1001+ AS_IF([test "x$HAVE_GCOV" = "x1"], ENABLE_GCOV=yes, ENABLE_GCOV=no)
1002+ AS_IF([test "x$HAVE_LIBCHECK" = "x1"], ENABLE_TESTS=yes, ENABLE_TESTS=no)
1003+ AS_IF([test "x$enable_legacy_database_entry_format" != "xno"], ENABLE_LEGACY_DATABASE_ENTRY_FORMAT=yes, ENABLE_LEGACY_DATABASE_ENTRY_FORMAT=no)
1004++AS_IF([test "x$enable_snap" != "xno"], ENABLE_SNAP=yes, ENABLE_SNAP=no)
1005+
1006+ echo "
1007+ ---{ $PACKAGE_NAME $VERSION }---
1008+@@ -1683,6 +1699,7 @@ echo "
1009+ Enable speex (resampler, AEC): ${ENABLE_SPEEX}
1010+ Enable soxr (resampler): ${ENABLE_SOXR}
1011+ Enable WebRTC echo canceller: ${ENABLE_WEBRTC}
1012++ Enable Snap support: ${ENABLE_SNAP}
1013+ Enable gcov coverage: ${ENABLE_GCOV}
1014+ Enable unit tests: ${ENABLE_TESTS}
1015+ Database
1016+diff --git a/src/Makefile.am b/src/Makefile.am
1017+index d623d0a..16b4d5d 100644
1018+--- a/src/Makefile.am
1019++++ b/src/Makefile.am
1020+@@ -1240,6 +1240,11 @@ modlibexec_LTLIBRARIES += \
1021 module-esound-sink.la
1022 endif
1023
1024-+if HAVE_APPARMOR
1025++if BUILD_SNAP
1026 +modlibexec_LTLIBRARIES += \
1027-+ module-snappy-policy.la
1028++ module-snap-policy.la
1029 +endif
1030 +
1031 # See comment at librtp.la above
1032 if !OS_IS_WIN32
1033 modlibexec_LTLIBRARIES += \
1034-@@ -2048,6 +2053,14 @@ module_trust_store_la_LIBADD = $(MODULE_
1035- module_trust_store_la_CFLAGS = $(AM_CFLAGS) -DHAVE_TRUST_STORE=1
1036+@@ -2024,6 +2029,14 @@ module_echo_cancel_la_CFLAGS += -DHAVE_WEBRTC=1
1037+ module_echo_cancel_la_LIBADD += libwebrtc-util.la
1038 endif
1039
1040 +# Snappy
1041-+if HAVE_APPARMOR
1042-+module_snappy_policy_la_SOURCES = modules/module-snappy-policy.c
1043-+module_snappy_policy_la_LDFLAGS = $(MODULE_LDFLAGS) -lapparmor
1044-+module_snappy_policy_la_LIBADD = $(MODULE_LIBADD)
1045-+module_snappy_policy_la_CFLAGS = $(AM_CFLAGS) -DHAVE_SNAPPY=1
1046++if BUILD_SNAP
1047++module_snap_policy_la_SOURCES = modules/module-snap-policy.c
1048++module_snap_policy_la_LDFLAGS = $(MODULE_LDFLAGS)
1049++module_snap_policy_la_LIBADD = $(MODULE_LIBADD) $(APPARMOR_LIBS) $(SNAPD_GLIB_LIBS)
1050++module_snap_policy_la_CFLAGS = $(AM_CFLAGS) $(APPARMOR_CFLAGS) $(SNAPD_GLIB_CFLAGS) -DPA_MODULE_NAME=module_snap_policy
1051 +endif
1052 +
1053 # RTP modules
1054 module_rtp_send_la_SOURCES = modules/rtp/module-rtp-send.c
1055 module_rtp_send_la_LDFLAGS = $(MODULE_LDFLAGS)
1056-Index: pulseaudio/src/modules/module-snappy-policy.c
1057-===================================================================
1058+diff --git a/src/modules/module-snap-policy.c b/src/modules/module-snap-policy.c
1059+new file mode 100644
1060+index 0000000..8660476
1061 --- /dev/null
1062-+++ pulseaudio/src/modules/module-snappy-policy.c
1063-@@ -0,0 +1,96 @@
1064++++ b/src/modules/module-snap-policy.c
1065+@@ -0,0 +1,347 @@
1066 +/***
1067 + This file is part of PulseAudio.
1068 +
1069-+ Copyright 2016 Canonical Ltd.
1070-+ Written by Simon Fels <simon.fels@canonical.com>
1071++ Copyright 2018 Canonical Ltd.
1072++ Authors:
1073++ Simon Fels <simon.fels@canonical.com>
1074++ James Henstridge <james.henstridge@canonical.com>
1075 +
1076 + PulseAudio is free software; you can redistribute it and/or modify
1077 + it under the terms of the GNU Lesser General Public License as published
1078@@ -71,116 +116,323 @@ Index: pulseaudio/src/modules/module-snappy-policy.c
1079 +#endif
1080 +
1081 +#include <sys/apparmor.h>
1082-+#include <errno.h>
1083++#include <glib.h>
1084++#include <snapd-glib/snapd-glib.h>
1085 +
1086-+#include <pulsecore/i18n.h>
1087++#include <pulsecore/asyncq.h>
1088 +#include <pulsecore/core.h>
1089++#include <pulsecore/idxset.h>
1090++#include <pulsecore/hashmap.h>
1091 +#include <pulsecore/module.h>
1092-+#include <pulse/xmalloc.h>
1093-+#include <pulsecore/fdsem.h>
1094++#include <pulsecore/mutex.h>
1095 +#include <pulsecore/thread.h>
1096-+#include <pulsecore/core-util.h>
1097 +#include <pulse/mainloop-api.h>
1098++#include <pulse/xmalloc.h>
1099 +
1100 +#define SNAP_LABEL_PREFIX "snap."
1101 +#define SNAP_LABEL_PREFIX_LENGTH 5
1102 +
1103-+PA_MODULE_AUTHOR("Simon Fels");
1104-+PA_MODULE_DESCRIPTION("Ubuntu Snappy policy management");
1105++PA_MODULE_AUTHOR("Canonical Ltd");
1106++PA_MODULE_DESCRIPTION("Ubuntu Snap policy management");
1107 +PA_MODULE_VERSION(PACKAGE_VERSION);
1108 +PA_MODULE_LOAD_ONCE(true);
1109 +
1110++struct per_client {
1111++ struct userdata *userdata;
1112++ uint32_t index;
1113++ char *snap_name;
1114++ pa_dynarray *pending_requests; /* of pa_access_data */
1115++ bool completed;
1116++ bool grant_access;
1117++};
1118++
1119 +struct userdata {
1120-+ pa_core *core;
1121++ pa_io_event *io_event;
1122 + pa_hook_slot *connect_hook_slot;
1123++
1124++ pa_thread *thread;
1125++ pa_mutex *mutex;
1126++ pa_cond *cond;
1127++
1128++ pa_hashmap *clients; /* int => struct per_client */
1129++ pa_asyncq *results; /* of struct per_client */
1130++
1131++ /* Data owned by glib thread */
1132++ GMainContext *main_context;
1133++ GMainLoop *main_loop;
1134++ GCancellable *cancellable;
1135++ SnapdClient *snapd;
1136 +};
1137 +
1138-+static pa_hook_result_t connect_record_hook(pa_core *core, pa_access_data *d, struct userdata *u) {
1139-+ pa_client *client = pa_idxset_get_by_index(u->core->clients, d->client_index);
1140-+ if (!client)
1141-+ return PA_HOOK_OK;
1142-+
1143-+ char *label = NULL;
1144-+ char *mode = NULL;
1145-+ if (aa_gettaskcon(client->creds.pid, &label, &mode) < 0) {
1146-+ pa_log_warn("Failed to retrieve apparmor security label for pid %u: %s",
1147-+ client->creds.pid, strerror(-errno));
1148-+ return PA_HOOK_OK;
1149++/* ---- Code running in glib thread ---- */
1150++
1151++static void check_interfaces_finish(GObject *source_object,
1152++ GAsyncResult *result,
1153++ gpointer user_data)
1154++{
1155++ struct per_client *pc = user_data;
1156++ struct userdata *u = pc->userdata;
1157++ g_autoptr(GError) error = NULL;
1158++ g_autoptr(GPtrArray) plugs = NULL;
1159++ unsigned i;
1160++
1161++ pa_mutex_lock(u->mutex);
1162++
1163++ if (!snapd_client_get_interfaces_finish(u->snapd, result, &plugs, NULL, &error)) {
1164++ pa_log_warn("snapd_client_get_interfaces failed: %s", error->message);
1165++ goto end;
1166++ }
1167++
1168++ /* determine pc->grant_access */
1169++ for (i = 0; i < plugs->len; i++) {
1170++ SnapdPlug *plug = plugs->pdata[i];
1171++ const char *snap_name = snapd_plug_get_snap(plug);
1172++ const char *iface = snapd_plug_get_interface(plug);
1173++ const bool connected = snapd_plug_get_connections(plug)->len != 0;
1174++
1175++ /* We are only interested in connected plugs of our snap */
1176++ if (!connected || strcmp(snap_name, pc->snap_name) != 0) {
1177++ continue;
1178++ }
1179++ if (!strcmp(iface, "pulseaudio") || !strcmp(iface, "audio-record")) {
1180++ pc->grant_access = true;
1181++ break;
1182++ }
1183++ }
1184++
1185++end:
1186++ pc->completed = true;
1187++ pa_asyncq_push(u->results, pc, true);
1188++ pa_mutex_unlock(u->mutex);
1189++}
1190++
1191++static gboolean check_interfaces(void *data)
1192++{
1193++ struct per_client *pc = data;
1194++ struct userdata *u = pc->userdata;
1195++
1196++ snapd_client_get_interfaces_async(u->snapd, u->cancellable,
1197++ check_interfaces_finish, pc);
1198++ return G_SOURCE_REMOVE;
1199++}
1200++
1201++
1202++static void thread_main(void *data) {
1203++ struct userdata *u = data;
1204++
1205++ pa_mutex_lock(u->mutex);
1206++
1207++ u->main_context = g_main_context_new();
1208++ g_main_context_push_thread_default(u->main_context);
1209++ u->main_loop = g_main_loop_new(u->main_context, false);
1210++ u->cancellable = g_cancellable_new();
1211++ u->snapd = snapd_client_new();
1212++
1213++ /* Signal main thread that we've finished initialisation */
1214++ pa_cond_signal(u->cond, false);
1215++ pa_mutex_unlock(u->mutex);
1216++
1217++ pa_log_info("Starting GLib main loop");
1218++ g_main_loop_run(u->main_loop);
1219++ pa_log_info("GLib main loop exited");
1220++
1221++ g_cancellable_cancel(u->cancellable);
1222++
1223++ g_clear_object(&u->snapd);
1224++ g_clear_object(&u->cancellable);
1225++ g_main_context_pop_thread_default(u->main_context);
1226++ g_clear_pointer(&u->main_loop, g_main_loop_unref);
1227++ g_clear_pointer(&u->main_context, g_main_context_unref);
1228++}
1229++
1230++static gboolean thread_quit(void *data)
1231++{
1232++ struct userdata *u = data;
1233++
1234++ g_main_loop_quit(u->main_loop);
1235++ return G_SOURCE_REMOVE;
1236++}
1237++
1238++/* ---- Code running in main thread ---- */
1239++
1240++static struct per_client *per_client_new(struct userdata *u,
1241++ uint32_t client_index,
1242++ char *snap_name) {
1243++ struct per_client *pc = pa_xnew0(struct per_client, 1);
1244++ pc->userdata = u;
1245++ pc->index = client_index;
1246++ pc->snap_name = snap_name;
1247++ pc->pending_requests = pa_dynarray_new(NULL);
1248++ pc->completed = false;
1249++ pc->grant_access = false;
1250++ return pc;
1251++}
1252++
1253++static void per_client_free(struct per_client *pc) {
1254++ if (!pc) return;
1255++ pa_xfree(pc->snap_name);
1256++ pa_dynarray_free(pc->pending_requests);
1257++ pa_xfree(pc);
1258++}
1259++
1260++static char *client_get_snap_name(pa_core *core, uint32_t client_index) {
1261++ pa_client *client;
1262++ char *context = NULL;
1263++ char *snap_name = NULL;
1264++ char *dot;
1265++
1266++ client = pa_idxset_get_by_index(core->clients, client_index);
1267++ pa_assert(client != NULL);
1268++ if (!client->creds_valid) {
1269++ pa_log_warn("Client %u has no creds, cannot authenticate", client_index);
1270++ goto end;
1271++ }
1272++
1273++ /* If AppArmor is not enabled, then we can't identify the client */
1274++ if (!aa_is_enabled()) {
1275++ goto end;
1276++ }
1277++ if (aa_gettaskcon(client->creds.pid, &context, NULL) < 0) {
1278++ pa_log_error("AppArmor profile could not be retrieved.");
1279++ goto end;
1280 + }
1281 +
1282-+ pa_hook_result_t decision = PA_HOOK_OK;
1283++ /* If the AppArmor context does not begin with "snap.", then this
1284++ * is not a snap */
1285++ if (strncmp(context, SNAP_LABEL_PREFIX, SNAP_LABEL_PREFIX_LENGTH) != 0) {
1286++ goto end;
1287++ }
1288 +
1289-+ // We only cancel the attempt of the client to start audio recording
1290-+ // when we could successfully determine that the request is coming
1291-+ // from an app which is part of a snap. Otherwise we continue to
1292-+ // work as normal.
1293-+ if (label && strncmp(SNAP_LABEL_PREFIX, label, SNAP_LABEL_PREFIX_LENGTH) == 0)
1294-+ decision = PA_HOOK_CANCEL;
1295++ dot = strchr(context+SNAP_LABEL_PREFIX_LENGTH, '.');
1296++ if (dot == NULL) {
1297++ pa_log_warn("Malformed snapd AppArmor profile name: %s", context);
1298++ goto end;
1299++ }
1300++ snap_name = pa_xstrndup(context+5, dot-context-SNAP_LABEL_PREFIX_LENGTH);
1301 +
1302-+ free(label);
1303++end:
1304++ free(context);
1305++ return snap_name;
1306++}
1307++
1308++static pa_hook_result_t connect_record_hook(pa_core *core, pa_access_data *d,
1309++ struct userdata *u) {
1310++ pa_hook_result_t result = PA_HOOK_STOP;
1311++ struct per_client *pc = NULL;
1312++ char *snap_name = NULL;
1313++
1314++ pa_mutex_lock(u->mutex);
1315++ pc = pa_hashmap_get(u->clients, (void *)(size_t)d->client_index);
1316++ if (pc) {
1317++ if (pc->completed) {
1318++ result = pc->grant_access ? PA_HOOK_OK : PA_HOOK_STOP;
1319++ } else {
1320++ /* A permission check for this snap is currently in progress */
1321++ pa_dynarray_append(pc->pending_requests, d);
1322++ result = PA_HOOK_CANCEL;
1323++ }
1324++ goto end;
1325++ }
1326 +
1327-+ return decision;
1328++ snap_name = client_get_snap_name(core, d->client_index);
1329++ if (!snap_name) {
1330++ /* Not a snap, so allow access */
1331++ result = PA_HOOK_OK;
1332++ goto end;
1333++ }
1334++
1335++ /* create new per client struct, and submit to glib thread */
1336++ pc = per_client_new(u, d->client_index, snap_name);
1337++ pa_dynarray_append(pc->pending_requests, d);
1338++ pa_hashmap_put(u->clients, (void *) (size_t) d->client_index, pc);
1339++ pa_log_info("Checking access for client %d (%s)", pc->index, pc->snap_name);
1340++ g_main_context_invoke(u->main_context, check_interfaces, pc);
1341++
1342++ result = PA_HOOK_CANCEL;
1343++
1344++end:
1345++ pa_mutex_unlock(u->mutex);
1346++ return result;
1347++}
1348++
1349++static void deliver_result(struct userdata *u, struct per_client *pc) {
1350++ pa_access_data *ad;
1351++ unsigned i;
1352++
1353++ pa_log_info("Access check for client %u (%s): %d",
1354++ pc->index, pc->snap_name, pc->grant_access);
1355++
1356++ /* Call the hooks without holding the mutex, since this will
1357++ * recurse into connect_record_hook. Access to pending_requests
1358++ * should be safe here, since connect_record_hook wont alter the
1359++ * array when the access check is complete. */
1360++ PA_DYNARRAY_FOREACH(ad, pc->pending_requests, i) {
1361++ ad->async_finish_cb(ad, pc->grant_access);
1362++ }
1363++ pa_mutex_lock(u->mutex);
1364++ pa_hashmap_remove_and_free(u->clients, (void *) (size_t) pc->index);
1365++ pa_mutex_unlock(u->mutex);
1366++}
1367++
1368++static void check_result(pa_mainloop_api *a, pa_io_event *e, int fd, pa_io_event_flags_t flags, void *userdata) {
1369++ struct userdata *u = userdata;
1370++ struct per_client *pc;
1371++
1372++ pa_asyncq_read_after_poll(u->results);
1373++ while ((pc = pa_asyncq_pop(u->results, false)) != NULL) {
1374++ deliver_result(u, pc);
1375++ }
1376++ pa_asyncq_read_before_poll(u->results);
1377 +}
1378 +
1379 +int pa__init(pa_module *m) {
1380 + struct userdata *u;
1381-+ u = pa_xnew0(struct userdata, 1);
1382-+ u->core = m->core;
1383 +
1384++ u = pa_xnew0(struct userdata, 1);
1385 + m->userdata = u;
1386-+ u->connect_hook_slot = pa_hook_connect(&m->core->access[PA_ACCESS_HOOK_CONNECT_RECORD],
1387-+ PA_HOOK_NORMAL, (pa_hook_cb_t) connect_record_hook, u);
1388++ u->mutex = pa_mutex_new(false, false);
1389++ u->cond = pa_cond_new();
1390++
1391++ u->clients = pa_hashmap_new_full(pa_idxset_trivial_hash_func,
1392++ pa_idxset_trivial_compare_func,
1393++ NULL, (pa_free_cb_t) per_client_free);
1394++
1395++ u->results = pa_asyncq_new(0);
1396++ u->io_event = m->core->mainloop->io_new(
1397++ m->core->mainloop, pa_asyncq_read_fd(u->results), PA_IO_EVENT_INPUT,
1398++ check_result, u);
1399++ pa_asyncq_read_before_poll(u->results);
1400++
1401++ u->connect_hook_slot = pa_hook_connect(
1402++ &m->core->access[PA_ACCESS_HOOK_CONNECT_RECORD], PA_HOOK_NORMAL,
1403++ (pa_hook_cb_t) connect_record_hook, u);
1404++
1405++ /* Start glib thread and wait for it to finish initialising. */
1406++ pa_mutex_lock(u->mutex);
1407++ u->thread = pa_thread_new("snapd-glib", thread_main, u);
1408++ pa_cond_wait(u->cond, u->mutex);
1409++ pa_mutex_unlock(u->mutex);
1410 +
1411 + return 0;
1412 +}
1413 +
1414 +void pa__done(pa_module *m) {
1415 + struct userdata *u = m->userdata;
1416-+ if (u) {
1417-+ if (u->connect_hook_slot)
1418-+ pa_hook_slot_free(u->connect_hook_slot);
1419-+ pa_xfree(u);
1420-+ }
1421-+}
1422-Index: pulseaudio/configure.ac
1423-===================================================================
1424---- pulseaudio.orig/configure.ac
1425-+++ pulseaudio/configure.ac
1426-@@ -1446,6 +1446,19 @@ AS_IF([test "x$os_is_win32" != "x1"],
1427- AS_IF([test "x$ax_pthread_ok" = "xyes"],
1428- AC_DEFINE([_POSIX_PTHREAD_SEMANTICS], 1, [Needed on Solaris]))
1429-
1430-+# Snappy support
1431++ if (!u) return;
1432 +
1433-+AC_ARG_ENABLE([snappy],
1434-+ AS_HELP_STRING([--enable-snappy], [Enable snappy support]))
1435++ pa_hook_slot_free(u->connect_hook_slot);
1436++ m->core->mainloop->io_free(u->io_event);
1437 +
1438-+AS_IF([test "x$enable_snappy" != "xno"],
1439-+ [PKG_CHECK_MODULES(APPARMOR, [libapparmor], [HAVE_APPARMOR=1], [HAVE_APPARMOR=0])],
1440-+ [HAVE_APPARMOR=0])
1441++ /* Stop the glib thread and wait for it to exit */
1442++ g_main_context_invoke(u->main_context, thread_quit, u);
1443++ pa_thread_join(u->thread);
1444++ pa_thread_free(u->thread);
1445 +
1446-+AS_IF([test "x$enable_snappy" = "xyes" && test "x$HAVE_APPARMOR" = "x0"],
1447-+ [AC_MSG_ERROR([*** Apparmor library not found])])
1448++ pa_asyncq_free(u->results, NULL); /* items in queue owned by u->clients */
1449++ g_clear_pointer(&u->clients, pa_hashmap_free);
1450 +
1451-+AM_CONDITIONAL([HAVE_APPARMOR], [test "x$HAVE_APPARMOR" = "x1"])
1452-
1453- # Ubuntu touch trust store
1454-
1455-@@ -1641,6 +1654,8 @@ AS_IF([test "x$HAVE_ESOUND" = "x1" -a "x
1456- AS_IF([test "x$HAVE_GCOV" = "x1"], ENABLE_GCOV=yes, ENABLE_GCOV=no)
1457- AS_IF([test "x$HAVE_LIBCHECK" = "x1"], ENABLE_TESTS=yes, ENABLE_TESTS=no)
1458- AS_IF([test "x$enable_legacy_database_entry_format" != "xno"], ENABLE_LEGACY_DATABASE_ENTRY_FORMAT=yes, ENABLE_LEGACY_DATABASE_ENTRY_FORMAT=no)
1459-+AS_IF([test "x$enable_snappy" = "x1"], ENABLE_SNAPPY=yes, ENABLE_SNAPPY=no)
1460-+AS_IF([test "x$HAVE_APPARMOR" = "x1"], ENABLE_APPARMOR=yes, ENABLE_APPARMOR=no)
1461-
1462- echo "
1463- ---{ $PACKAGE_NAME $VERSION }---
1464-@@ -1698,6 +1713,8 @@ echo "
1465- Enable soxr (resampler): ${ENABLE_SOXR}
1466- Enable WebRTC echo canceller: ${ENABLE_WEBRTC}
1467- Enable Ubuntu trust store: ${ENABLE_TRUST_STORE}
1468-+ Enable Snappy support: ${ENABLE_SNAPPY}
1469-+ Enable Apparmor: ${ENABLE_APPARMOR}
1470- Enable gcov coverage: ${ENABLE_GCOV}
1471- Enable unit tests: ${ENABLE_TESTS}
1472- Database
1473++ g_clear_pointer(&u->cond, pa_cond_free);
1474++ g_clear_pointer(&u->mutex, pa_mutex_free);
1475++
1476++ pa_xfree(u);
1477++}
1478diff --git a/debian/patches/0701-enable-snap-policy-module.patch b/debian/patches/0701-enable-snap-policy-module.patch
1479new file mode 100644
1480index 0000000..233671b
1481--- /dev/null
1482+++ b/debian/patches/0701-enable-snap-policy-module.patch
1483@@ -0,0 +1,25 @@
1484+From: James Henstridge <james.henstridge@canonical.com>
1485+Date: Tue, 7 Aug 2018 16:54:00 +0800
1486+Subject: daemon: enable module-snap-policy module
1487+
1488+---
1489+ src/daemon/default.pa.in | 6 ++++++
1490+ 1 file changed, 6 insertions(+)
1491+
1492+diff --git a/src/daemon/default.pa.in b/src/daemon/default.pa.in
1493+index 78c42a1..633e0f0 100755
1494+--- a/src/daemon/default.pa.in
1495++++ b/src/daemon/default.pa.in
1496+@@ -171,6 +171,12 @@ load-module module-position-event-sounds
1497+ ### Cork music/video streams when a phone stream is active
1498+ load-module module-role-cork
1499+
1500++### Block audio recording for snap confined packages unless they have
1501++### the "pulseaudio" or "audio-record" interfaces plugged.
1502++.ifexists module-snap-policy@PA_SOEXT@
1503++load-module module-snap-policy
1504++.endif
1505++
1506+ ### Modules to allow autoloading of filters (such as echo cancellation)
1507+ ### on demand. module-filter-heuristics tries to determine what filters
1508+ ### make sense, and module-filter-apply does the heavy-lifting of
1509diff --git a/debian/patches/series b/debian/patches/series
1510index 52c106a..16de29a 100644
1511--- a/debian/patches/series
1512+++ b/debian/patches/series
1513@@ -7,13 +7,10 @@
1514 memfd-glibc2.27.patch
1515 0050-disable-volume-test.patch
1516
1517-# Ubuntu touch: support for trust-store
1518+# Ubuntu Snap policy support
1519 0406-tagstruct-add-copy-method.patch
1520 0407-access-Add-access-control-hooks.patch
1521 0408-protocol-native-add-access-checks.patch
1522-0409-Trust-store-patch.patch
1523-0410-Add-thread-to-activate-trust-store-interface.patch
1524-0417-increase-timeout-check-apparmor.patch
1525-
1526-# Ubuntu Snappy
1527+0409-pa-client-peer-credentials.patch
1528 0700-modules-add-snappy-policy-module.patch
1529+0701-enable-snap-policy-module.patch
1530diff --git a/debian/pulseaudio.install b/debian/pulseaudio.install
1531index 59419ae..0756e46 100755
1532--- a/debian/pulseaudio.install
1533+++ b/debian/pulseaudio.install
1534@@ -78,7 +78,7 @@ usr/lib/pulse-*/modules/module-virtual-sink.so
1535 usr/lib/pulse-*/modules/module-virtual-source.so
1536 usr/lib/pulse-*/modules/module-switch-on-port-available.so
1537 usr/lib/pulse-*/modules/module-virtual-surround-sink.so
1538-usr/lib/pulse-*/modules/module-snappy-policy.so
1539+usr/lib/pulse-*/modules/module-snap-policy.so
1540 usr/lib/pulse-*/modules/module-x11*.so
1541 usr/lib/pulse-*/modules/module-allow-passthrough.so
1542 [linux-any] usr/lib/pulse-*/modules/module-systemd-login.so
1543diff --git a/debian/rules b/debian/rules
1544index f92f0b2..697e3cc 100755
1545--- a/debian/rules
1546+++ b/debian/rules
1547@@ -22,7 +22,7 @@ DEB_CONFIGURE_EXTRA_FLAGS = --enable-x11 --disable-hal-compat \
1548 --with-zsh-completion-dir=\$${datadir}/zsh/vendor-completions \
1549 --with-bash-completion-dir=\$${datadir}/bash-completion/completions \
1550 --with-systemduserunitdir=\$${prefix}/lib/systemd/user \
1551- --enable-snappy \
1552+ --enable-snap \
1553 --disable-bluez4 \
1554 --enable-gsettings \
1555 --disable-gconf

Subscribers

People subscribed via source and target branches