Public bug reported:

SUMMARY
=========
When running a snap in classic confinement, that needs access to 
PA_COMMAND_LOAD_MODULE and PA_COMMAND_UNLOAD_MODULE. These sometimes succeed 
and sometimes fail with "Access denied".

After running "pacmd unload-module module-snap-policy" and unloading the
snap policy module, these work reliably.

I have verified this in a fresh install of Ubuntu 20.04 in a VM.

STEPS TO REPRODUCE
=========
a) Either build a snap with classic confinement that sends these commands on 
the pulseaudio native protocol socket. (This is how I found the bug)
b) Or, what I did here to easier reproduce, abuse the sandbox of a random 
classic snap:

Download the attached bug.tgz with a minimal reproducer. It contains the
source code for a program that sends load and unload commands to pulse.
Unfortunately `pacmd` has a pid-file check that fails inside the sandbox
and doesn't work. The reproducer does essentially the same as "pacmd
load/unload-module" though.

(a pre-compiled x64 binary is also included in case you don't have a go
compiler and dare to run an untrusted binary in a VM)

Unpack the tgz, build it, if necessary with "go mod download && go
build"

Grab a random classic mode snap to use its sandbox as a test bed:

    $ sudo snap install atom --classic
    atom 1.48.0 from Snapcrafters installed

Open a shell in its sandbox:

    snap run --shell atom
    
Navigate to the compiled binary and execute it a few times:

    user@user-Standard-PC-Q35-ICH9-2009:~/bug$ ./bug 
    2020/07/08 18:46:10 PulseAudio connection created successfully
    2020/07/08 18:46:10 Couldn't load module, error message: PulseAudio error: 
commandLoadModule -> Access denied
    user@user-Standard-PC-Q35-ICH9-2009:~/bug$ ./bug 
    2020/07/08 18:46:11 PulseAudio connection created successfully
    Loaded Module sucessfully at index: 40
    user@user-Standard-PC-Q35-ICH9-2009:~/bug$ ./bug 
    2020/07/08 18:46:12 PulseAudio connection created successfully
    Loaded Module sucessfully at index: 41
    user@user-Standard-PC-Q35-ICH9-2009:~/bug$ ./bug 
    2020/07/08 18:46:12 PulseAudio connection created successfully
    2020/07/08 18:46:12 Couldn't load module, error message: PulseAudio error: 
commandLoadModule -> Access denied
    user@user-Standard-PC-Q35-ICH9-2009:~/bug$ ./bug 
    2020/07/08 18:46:14 PulseAudio connection created successfully
    2020/07/08 18:46:14 Couldn't load module, error message: PulseAudio error: 
commandLoadModule -> Access denied
    user@user-Standard-PC-Q35-ICH9-2009:~/bug$ ./bug 
    2020/07/08 18:46:14 PulseAudio connection created successfully
    2020/07/08 18:46:14 Couldn't load module, error message: PulseAudio error: 
commandLoadModule -> Access denied
    user@user-Standard-PC-Q35-ICH9-2009:~/bug$ ./bug 
    2020/07/08 18:46:15 PulseAudio connection created successfully
    2020/07/08 18:46:15 Couldn't load module, error message: PulseAudio error: 
commandLoadModule -> Access denied

Succeeds and fails apparently at random.

Now from a non-sandboxed shell, run

    pacmd unload-module module-snap-policy

to unload the snap-policy module from pulseaudio, now run ./bug a few
more times. It now succeeds reliably, every time.

Side note, with the real program on my actual machine, the race seems to
behave slightly differently. It seems not to work the first time an
application is started, but closing it and reopening it seems to make it
work pretty reliably afterwards. Restarting "snapd", causes the
following run the snap to fail again.

EXPECTED BEHAVIOUR
==================

The pulseaudio snap policy module should correctly determine and enforce
it's policy.

ACTUAL BEHAVIOUR
================

The pulseaudio snap policy module seemingly at random denies access when
the snap has the permissions to do an operation.

ADDITIONAL INFORMATION
======================

$ lsb_release -rd
Description:    Ubuntu 20.04 LTS
Release:        20.04

$ apt-cache policy pulseaudio
pulseaudio:
  Installed: 1:13.99.1-1ubuntu3.3
  Candidate: 1:13.99.1-1ubuntu3.3
  Version table:
 *** 1:13.99.1-1ubuntu3.3 500
        500 http://ch.archive.ubuntu.com/ubuntu focal-updates/main amd64 
Packages
        100 /var/lib/dpkg/status
     1:13.99.1-1ubuntu3.2 500
        500 http://security.ubuntu.com/ubuntu focal-security/main amd64 Packages
     1:13.99.1-1ubuntu3 500
        500 http://ch.archive.ubuntu.com/ubuntu focal/main amd64 Packages

** Affects: pulseaudio (Ubuntu)
     Importance: Undecided
         Status: New

** Attachment added: "Code/binary to reproduce"
   https://bugs.launchpad.net/bugs/1886854/+attachment/5390823/+files/bug.tgz

-- 
You received this bug notification because you are a member of Ubuntu
Touch seeded packages, which is subscribed to pulseaudio in Ubuntu.
https://bugs.launchpad.net/bugs/1886854

Title:
  Race in load-module snap policy check in classic confinement

Status in pulseaudio package in Ubuntu:
  New

Bug description:
  SUMMARY
  =========
  When running a snap in classic confinement, that needs access to 
PA_COMMAND_LOAD_MODULE and PA_COMMAND_UNLOAD_MODULE. These sometimes succeed 
and sometimes fail with "Access denied".

  After running "pacmd unload-module module-snap-policy" and unloading
  the snap policy module, these work reliably.

  I have verified this in a fresh install of Ubuntu 20.04 in a VM.

  STEPS TO REPRODUCE
  =========
  a) Either build a snap with classic confinement that sends these commands on 
the pulseaudio native protocol socket. (This is how I found the bug)
  b) Or, what I did here to easier reproduce, abuse the sandbox of a random 
classic snap:

  Download the attached bug.tgz with a minimal reproducer. It contains
  the source code for a program that sends load and unload commands to
  pulse. Unfortunately `pacmd` has a pid-file check that fails inside
  the sandbox and doesn't work. The reproducer does essentially the same
  as "pacmd load/unload-module" though.

  (a pre-compiled x64 binary is also included in case you don't have a
  go compiler and dare to run an untrusted binary in a VM)

  Unpack the tgz, build it, if necessary with "go mod download && go
  build"

  Grab a random classic mode snap to use its sandbox as a test bed:

      $ sudo snap install atom --classic
      atom 1.48.0 from Snapcrafters installed

  Open a shell in its sandbox:

      snap run --shell atom
      
  Navigate to the compiled binary and execute it a few times:

      user@user-Standard-PC-Q35-ICH9-2009:~/bug$ ./bug 
      2020/07/08 18:46:10 PulseAudio connection created successfully
      2020/07/08 18:46:10 Couldn't load module, error message: PulseAudio 
error: commandLoadModule -> Access denied
      user@user-Standard-PC-Q35-ICH9-2009:~/bug$ ./bug 
      2020/07/08 18:46:11 PulseAudio connection created successfully
      Loaded Module sucessfully at index: 40
      user@user-Standard-PC-Q35-ICH9-2009:~/bug$ ./bug 
      2020/07/08 18:46:12 PulseAudio connection created successfully
      Loaded Module sucessfully at index: 41
      user@user-Standard-PC-Q35-ICH9-2009:~/bug$ ./bug 
      2020/07/08 18:46:12 PulseAudio connection created successfully
      2020/07/08 18:46:12 Couldn't load module, error message: PulseAudio 
error: commandLoadModule -> Access denied
      user@user-Standard-PC-Q35-ICH9-2009:~/bug$ ./bug 
      2020/07/08 18:46:14 PulseAudio connection created successfully
      2020/07/08 18:46:14 Couldn't load module, error message: PulseAudio 
error: commandLoadModule -> Access denied
      user@user-Standard-PC-Q35-ICH9-2009:~/bug$ ./bug 
      2020/07/08 18:46:14 PulseAudio connection created successfully
      2020/07/08 18:46:14 Couldn't load module, error message: PulseAudio 
error: commandLoadModule -> Access denied
      user@user-Standard-PC-Q35-ICH9-2009:~/bug$ ./bug 
      2020/07/08 18:46:15 PulseAudio connection created successfully
      2020/07/08 18:46:15 Couldn't load module, error message: PulseAudio 
error: commandLoadModule -> Access denied

  Succeeds and fails apparently at random.

  Now from a non-sandboxed shell, run

      pacmd unload-module module-snap-policy

  to unload the snap-policy module from pulseaudio, now run ./bug a few
  more times. It now succeeds reliably, every time.

  Side note, with the real program on my actual machine, the race seems
  to behave slightly differently. It seems not to work the first time an
  application is started, but closing it and reopening it seems to make
  it work pretty reliably afterwards. Restarting "snapd", causes the
  following run the snap to fail again.

  EXPECTED BEHAVIOUR
  ==================

  The pulseaudio snap policy module should correctly determine and
  enforce it's policy.

  ACTUAL BEHAVIOUR
  ================

  The pulseaudio snap policy module seemingly at random denies access
  when the snap has the permissions to do an operation.

  ADDITIONAL INFORMATION
  ======================

  $ lsb_release -rd
  Description:  Ubuntu 20.04 LTS
  Release:      20.04

  $ apt-cache policy pulseaudio
  pulseaudio:
    Installed: 1:13.99.1-1ubuntu3.3
    Candidate: 1:13.99.1-1ubuntu3.3
    Version table:
   *** 1:13.99.1-1ubuntu3.3 500
          500 http://ch.archive.ubuntu.com/ubuntu focal-updates/main amd64 
Packages
          100 /var/lib/dpkg/status
       1:13.99.1-1ubuntu3.2 500
          500 http://security.ubuntu.com/ubuntu focal-security/main amd64 
Packages
       1:13.99.1-1ubuntu3 500
          500 http://ch.archive.ubuntu.com/ubuntu focal/main amd64 Packages

To manage notifications about this bug go to:
https://bugs.launchpad.net/ubuntu/+source/pulseaudio/+bug/1886854/+subscriptions

-- 
Mailing list: https://launchpad.net/~touch-packages
Post to     : touch-packages@lists.launchpad.net
Unsubscribe : https://launchpad.net/~touch-packages
More help   : https://help.launchpad.net/ListHelp

Reply via email to