Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

cmd/snap-confine: handle device cgroup before pivot #7049

Merged
merged 4 commits into from
Jul 2, 2019

Conversation

zyga
Copy link
Contributor

@zyga zyga commented Jun 28, 2019

Since the dawn of snapd, snap-confine would populate and join the device
cgroup nearly just before executing the target application. This is done
by interrogating udev for devices with appropriate tags and adding them
to the control group. They way they are added to the control group,
however, is pretty inefficient, as it involves executing a shell script
that writes to /sys/fs/cgroup/devices/devices.allow. The shells script
uses the interpreter #!/bin/sh forcing all base snaps to ship shell
along with the minimal set of support libraries.

Normally that was "okay" with the exception that we recently started
adding new base snaps that are otherwise empty, raising the pressure on
the need to host the spurious shell.

While a better solution would be to write to the device cgroup directly,
from snap-confine, ignoring the script, that work is somewhat larger.
As a simple alternative, just run the script before we setup and switch
to the mount namespace of the snap application.

Signed-off-by: Zygmunt Krynicki me@zygoon.pl

Since the dawn of snapd, snap-confine would populate and join the device
cgroup nearly just before executing the target application. This is done
by interrogating udev for devices with appropriate tags and adding them
to the control group. They way they are added to the control group,
however, is pretty inefficient, as it involves executing a shell script
that writes to /sys/fs/cgroup/devices/devices.allow. The shells script
uses the interpreter #!/bin/sh forcing all base snaps to ship shell
along with the minimal set of support libraries.

Normally that was "okay" with the exception that we recently started
adding new base snaps that are otherwise empty, raising the pressure on
the need to host the spurious shell.

While a better solution would be to write to the device cgroup directly,
from snap-confine, ignoring the script, that work is somewhat larger.
As a simple alternative, just run the script before we setup and switch
to the mount namespace of the snap application.

Signed-off-by: Zygmunt Krynicki <me@zygoon.pl>
@zyga zyga requested a review from jdstrand June 28, 2019 15:11
Copy link

@jdstrand jdstrand left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This should be fine and the risk should only be that we can die() in more places after we setup the cgroup, but we could die() in places prior to this PR and new snap-confine invocations set this up anew anyway. LGTM so long as tests pass.

@jdstrand jdstrand changed the title cmd/snap-confine: handle device group before pivot cmd/snap-confine: handle device cgroup before pivot Jun 28, 2019
Copy link
Contributor

@bboozzoo bboozzoo left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM

@bboozzoo
Copy link
Contributor

bboozzoo commented Jul 1, 2019

Looks like this is going to be fun:

2019-06-28 16:16:12 Failed tasks: 29
    - google:amazon-linux-2-64:tests/main/interfaces-device-buttons
    - google:amazon-linux-2-64:tests/main/interfaces-joystick
    - google:amazon-linux-2-64:tests/main/interfaces-kvm
    - google:amazon-linux-2-64:tests/main/interfaces-time-control
    - google:amazon-linux-2-64:tests/main/security-device-cgroups:kmsg
    - google:amazon-linux-2-64:tests/main/security-device-cgroups:uinput
    - google:amazon-linux-2-64:tests/main/security-devpts
    - google:amazon-linux-2-64:tests/main/security-udev-input-subsystem
    - google:centos-7-64:tests/main/interfaces-device-buttons
    - google:centos-7-64:tests/main/interfaces-joystick
    - google:centos-7-64:tests/main/interfaces-kvm
    - google:centos-7-64:tests/main/interfaces-time-control
    - google:centos-7-64:tests/main/security-device-cgroups:kmsg
    - google:centos-7-64:tests/main/security-device-cgroups:uinput
    - google:centos-7-64:tests/main/security-devpts
    - google:centos-7-64:tests/main/security-udev-input-subsystem
    - google:fedora-30-64:tests/main/interfaces-device-buttons
    - google:fedora-30-64:tests/main/interfaces-joystick
    - google:fedora-30-64:tests/main/interfaces-kvm
    - google:fedora-30-64:tests/main/security-devpts
    - google:fedora-30-64:tests/main/security-udev-input-subsystem
    - google:opensuse-tumbleweed-64:tests/main/interfaces-device-buttons
    - google:opensuse-tumbleweed-64:tests/main/interfaces-framebuffer
    - google:opensuse-tumbleweed-64:tests/main/interfaces-fuse_support:parallel
    - google:opensuse-tumbleweed-64:tests/main/interfaces-fuse_support:regular
    - google:opensuse-tumbleweed-64:tests/main/interfaces-joystick
    - google:opensuse-tumbleweed-64:tests/main/interfaces-kvm
    - google:opensuse-tumbleweed-64:tests/main/security-devpts
    - google:opensuse-tumbleweed-64:tests/main/security-udev-input-subsystem

@zyga
Copy link
Contributor Author

zyga commented Jul 1, 2019

Well, it was worth a try. I'll see if this is something obviously silly or more complex.

@zyga
Copy link
Contributor Author

zyga commented Jul 1, 2019

Interestingly this only failed on fedora, debian, etc but not on any ubuntu system, perhaps it is just a interpreter problem in the script (that now executes on the host). I'll check.

zyga added 2 commits July 1, 2019 08:40
Since the snap-device-helper script now executes on the host we should
not rewrite its interpreter path.

Signed-off-by: Zygmunt Krynicki <me@zygoon.pl>
When snap-confine executes snap-device-helper it does not have a
prefix-derived path for it, instead it looks for several fixed
locations. Adding /usr/libexec/snapd/snap-device-helper to it allows the
code to work correctly on libexec-like systems, like Fedora.

Signed-off-by: Zygmunt Krynicki <me@zygoon.pl>
@bboozzoo
Copy link
Contributor

bboozzoo commented Jul 1, 2019

Still fails on opensuse:

2019-07-01 07:26:34 Error executing google:opensuse-tumbleweed-64:tests/main/interfaces-framebuffer : 
-----
+ echo 'The plug is not connected by default'
The plug is not connected by default
+ MATCH '^- +test-snapd-framebuffer:framebuffer'
+ snap interfaces -i framebuffer

'snap interfaces' is deprecated; use 'snap connections'.
+ '[' '!' -e /dev/fb0 ']'
+ echo 'When the interface is connected'
When the interface is connected
+ snap connect test-snapd-framebuffer:framebuffer
+ echo 'Then the snap is able to write in the framebuffer'
Then the snap is able to write in the framebuffer
+ test-snapd-framebuffer.write 123
/bin/sh: error while loading shared libraries: libtinfo.so.6: cannot open shared object file: No such file or directory
child exited with status 127

Bit confusing. IIRC up to the point where the code is executed, there's no changes to the mount ns yet?

@zyga
Copy link
Contributor Author

zyga commented Jul 1, 2019

After fixing Fedora packaging we have only those errors left:

    - google:opensuse-tumbleweed-64:tests/main/interfaces-device-buttons
    - google:opensuse-tumbleweed-64:tests/main/interfaces-framebuffer
    - google:opensuse-tumbleweed-64:tests/main/interfaces-fuse_support:parallel
    - google:opensuse-tumbleweed-64:tests/main/interfaces-fuse_support:regular
    - google:opensuse-tumbleweed-64:tests/main/interfaces-joystick
    - google:opensuse-tumbleweed-64:tests/main/interfaces-kvm
    - google:opensuse-tumbleweed-64:tests/main/security-devpts
    - google:opensuse-tumbleweed-64:tests/main/security-udev-input-subsystem

... and all of them fail on /bin/sh: error while loading shared libraries: libtinfo.so.6: cannot open shared object file: No such file or directory.

@zyga
Copy link
Contributor Author

zyga commented Jul 1, 2019

The reason it failed on Tumbleweed (than god) is because we have apparmor there:

type=AVC msg=audit(1561974565.075:360): apparmor="DENIED" operation="open" profile="/usr/lib/snapd/snap-confine" name="/lib64/libtinfo.so.6.1" pid=7732 comm="snap-device-hel" requested_mask="r" denied_mask="r" fsuid=0 ouid=0

We either need to run the helper script unconfined or allow this to be used in the snap-confine template.

When snap-confine runs snap-device-helper it now does so in the initial
host mount namespace. On openSUSE the shell is linked with libtinfo and
we get a denial, like this:

    type=AVC msg=audit(1561974565.075:360): apparmor="DENIED"
    operation="open" profile="/usr/lib/snapd/snap-confine"
    name="/lib64/libtinfo.so.6.1" pid=7732 comm="snap-device-hel"
    requested_mask="r" denied_mask="r" fsuid=0 ouid=0

This patch fixes that by allowing this library to be loaded. As an
alternative that was considered but discarded, udev could run before
apparmor is loaded. I think we will re-visit this once cgroup v2 work
forces changes to snap-device-helper and associated code.

Signed-off-by: Zygmunt Krynicki <me@zygoon.pl>
Copy link
Contributor

@bboozzoo bboozzoo left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM

Copy link

@jdstrand jdstrand left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Still LGTM. Thanks for tracking down the packaging issues.

@@ -38,6 +38,8 @@
/{,usr/}lib{,32,64,x32}/{,@{multiarch}/}libudev.so* mr,
/{,usr/}lib{,32,64,x32}/{,@{multiarch}/}libseccomp.so* mr,
/{,usr/}lib{,32,64,x32}/{,@{multiarch}/}libcap.so* mr,
# Needed to run /usr/bin/sh for snap-device-helper.
/{,usr/}lib{,32,64,x32}/{,@{multiarch}/}libtinfo.so* mr,
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This rule is fine from a security POV, but I wouldn't normally be super excited about it from a maintenance POV, but we know that snap-confine is going to be adjusted to not shell out to snap-device-helper, so this is ok for now (at such time, we should remove the access that only the shell needs, like this one, but I suspect there are more).

@mvo5 mvo5 merged commit 62bd1cd into canonical:master Jul 2, 2019
@zyga zyga deleted the tweak/udev-before-pivot branch July 2, 2019 13:04
bboozzoo added a commit to bboozzoo/snapd that referenced this pull request Nov 27, 2019
Drop the workaround for rpmbuild rewriting /bin/sh to /usr/bin/sh.

The snap-confine device cgroup setup would call snap-device-helper after
pivoting to the snap mount namespace. This used to fail on Fedora because of the
mangling done by rpm packaging that changes /bin/sh to /usr/bin/sh. In which,
case we would try to run snap-device-helper using an interpreter at /usr/bin/sh
that does not exist within the snap mount ns. The downstream packaging defined
macros that prevented this scenario.

Since canonical#7049, snap-confine calls snap-device-helper before pivoting to the snap
mount namespace, thus the host interpreter is still visible at the correct path.

Signed-off-by: Maciej Borzecki <maciej.zenon.borzecki@canonical.com>
bboozzoo added a commit to bboozzoo/snapd that referenced this pull request Nov 28, 2019
Drop the workaround for rpmbuild rewriting /bin/sh to /usr/bin/sh.

The snap-confine device cgroup setup would call snap-device-helper after
pivoting to the snap mount namespace. This used to fail on Fedora because of the
mangling done by rpm packaging that changes /bin/sh to /usr/bin/sh. In which,
case we would try to run snap-device-helper using an interpreter at /usr/bin/sh
that does not exist within the snap mount ns. The downstream packaging defined
macros that prevented this scenario.

Since canonical#7049, snap-confine calls snap-device-helper before pivoting to the snap
mount namespace, thus the host interpreter is still visible at the correct path.

Signed-off-by: Maciej Borzecki <maciej.zenon.borzecki@canonical.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

4 participants