Hi all, I've been experimenting with adding access control to pulseaudio and I would like to start the discussion and propose some ideas with the attached patch set. With the current pulseaudio policy, once the app has made a connection with the daemon, it can perform any action it wants. This includes inspecting the state of the various objects but more problematically, the client is allowed to change the volume of any stream or sink/source or even kill any stream in the daemon. Any client is also allowed to start capturing from any of the sources or even the monitor sources of other streams. This is not something we want to allow in all cases without explicitly asking the user first. The primary use case for access control is sandboxed apps where we want to restrict the actions that the sandboxed app can perform on pulseaudio. We currently bind mount the pulseaudio socket in the sandbox and let the clients use that to communicate over the native protocol with the pulseaudio daemon [1]. This is the only way to communicate with pulseaudio, so the cli protocol and other protocols are disabled and excluded from this discussion. Pulseaudio was not designed and built with access control in mind from the start. Adding full control at the lowest level is probably not feasable at this stage, and I believe it is not really needed. Instead, I've experimented with blocking access at the protocol-native level [2]. With the native protocol, there are about 39 interesting actions that a client can perform. These roughly map to the pa_context, introspection, sample cache and pa_stream API. The idea is to fire a hook for each of these commands to check if the object being operated on can be seen/modified by the requesting client. The implementation of these checks happens in modules that can implement whatever policy is needed by connecting to the various hooks. This makes for some simple extra additions in protocol-native.c For the subscribed events, we need to be carefull that we don't send events to clients about objects that the client is not allowed to see, like an input_stream of some other client, if the policy does not allow that. It's a little tricky because with the REMOVE event, we can't get to the original object anymore (to check who the owner was, for example). This can be solved by keeping a list of all the events sent to a client about what objects, as is implemented in [2]. There are more actions in the pa_stream object but I believe it is not very useful to control access to those. Those actions are about configuring the stream attributes and get status information about the streams. I believe it is sufficient to allow or deny the creation of the pa_stream and after that, you are free to use all pa_stream actions on that stream. again, moving the stream to another sink is something that can be blocked, if needed because it is not an action on the pa_stream. What we eventually might want to do is ask the user for permission before a potentially dangerous action is done (record from a source, switch sinks/source,...). The idea is to let the access module call into a dbus api that will handle the user interaction and tells us what to do next. We would then also need to store those results in a database so that we don't have to ask for permission every time. I'm not sure we can block those protocol-native calls while waiting for the user or if we have to make them async on the server. [2] contains a simple example access module that has some hardcoded checks on input/output sink/source to see if the streams belong to the client that created them. This essentially makes each client only see its own streams and disallows any action on a stream that's not from the client. The idea is to do different checks based on the user/cgroup/... a process is executed under, possibly configured with a config file somehow. What do you think? I would love to hear your ideas. [1] https://wiki.gnome.org/action/info/Projects/SandboxedApps/Sandbox [2] http://cgit.freedesktop.org/~wtay/pulseaudio/log/?h=access-hooks Wim Taymans (2): access: add access control hooks module-access: make policy object containing rules src/Makefile.am | 8 + src/modules/module-access.c | 354 ++++++++++++++++++++++++++++++++++++++++ src/pulsecore/access.h | 98 +++++++++++ src/pulsecore/core-subscribe.c | 2 +- src/pulsecore/core.c | 5 + src/pulsecore/core.h | 3 + src/pulsecore/protocol-native.c | 152 +++++++++++++++++ 7 files changed, 621 insertions(+), 1 deletion(-) create mode 100644 src/modules/module-access.c create mode 100644 src/pulsecore/access.h -- 2.1.0