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
Make sure gpio exported before apparmor setup #2
Conversation
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
+1 overall, but have a question that needs answering.
} | ||
|
||
// ConnectedSlotSnippet - no slot snippets provided | ||
func (iface *GpioInterface) ConnectedSlotSnippet(plug *interfaces.Plug, slot *interfaces.Slot, securitySystem interfaces.SecuritySystem) ([]byte, error) { | ||
switch securitySystem { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Moving to PermanentSlotSnippet is fine. It'll be the core or gadget snap that is the providing side, so no big deal moving the exports IMO.
switch securitySystem { | ||
case interfaces.SecurityUDev: | ||
// NOTE: nothing unexports this GPIO when the slot is disconnected but | ||
// AFAIK this doesn't hurt. | ||
snippet := fmt.Sprintf(`ACTION=="add", SUBSYSTEM=="gpio", RUN+="/bin/echo %v > /syc/class/gpio/export"`, slot.Attrs["number"]) | ||
snippet := fmt.Sprintf(`SUBSYSTEM=="gpio", RUN+="/bin/sh -c '/bin/echo %v > /sys/class/gpio/export'"`, slot.Attrs["number"]) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Why was ACTION=="add"
removed?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I removed ACTION==add because:
- the udev backend uses the command "udevadm trigger" (Note: no flags) to reload udev rules
- the default ACTION sent by the trigger command is "change" so the command in the original rule would not be matched on install of the snap
- we need to ensure the gpio is exported before any connection is made so the apparmor snippet can be created
By not specifying an action at all I think the rule is processed immediately as it only requires the device to be present. The guarantees that the gpio will be exported. The cost is that I don't believe it is actually possible to unexport a gpio with a rule like this in place. This may be a reasonable trade-off to guarantee the apparmor snippet can be created.
@jdstrand Could you also comment on whether you think it is acceptable for the gpio to be exported even when there is no plug connected to the slot, which implies the resource is not in use. I think this is not ideal, but unfortunately required if we want to guarantee it is exported before ConnectedPlugSnippet is processed. |
@jocave - in terms of security policy-- I think exported by snapd anywhere is pretty much ok since the plugging snap just needs the gpio to be there and the security policy will block access to an exported gpio to gpio-disconnected plugged snaps. As for whether it is a problem for the kernel or the system to have it exported even if unused, I have no opinion. It doesn't seem like it would be a big issue, but I'll defer a definitive answer to a gpio expert. |
small tweaks for the store branch
Closing as I don't think we need this anymore, |
Make sure that we pick up nvidia TLS libs otherwise applications using libGLX will fail in most mysterious ways. The problem was debugged in detail in this forum topic [1]. A simple test case using glxinfo would segfault both inside the snap mount namespace and in chroot, the backtrace pointing back to pthread_mutex_lock(): (gdb) bt #0 0x00007ffff7559fb4 in pthread_mutex_lock () from target:/lib/x86_64-linux-gnu/libc.so.6 #1 0x00007ffff6f5eddb in mt_mutex_lock (mutex=0x7ffff71e5180 <dispatchLock>) at glvnd_pthread.c:317 #2 0x00007ffff6f23f77 in LockDispatch () at GLdispatch.c:144 #3 0x00007ffff6f24115 in __glDispatchNewVendorID () at GLdispatch.c:198 #4 0x00007ffff7212607 in __glXLookupVendorByName (vendorName=0x60d160 "nvidia") at libglxmapping.c:442 #5 0x00007ffff7213811 in __glXLookupVendorByScreen (dpy=0x60aab0, screen=0) at libglxmapping.c:574 #6 0x00007ffff7213966 in __glXGetDynDispatch (dpy=0x60aab0, screen=0) at libglxmapping.c:608 #7 0x00007ffff7209563 in glXChooseVisual (dpy=0x60aab0, screen=0, attrib_list=0x609200) at libglx.c:215 snapcore#8 0x00007ffff7b89d58 in glXChooseVisual (dpy=0x60aab0, screen=0, attribList=0x609200) at g_libglglxwrapper.c:183 snapcore#9 0x0000000000401741 in ?? () snapcore#10 0x00007ffff7465830 in __libc_start_main () from target:/lib/x86_64-linux-gnu/libc.so.6 snapcore#11 0x0000000000401ea9 in ?? () Further debugging revealed that this may be related to libc/pthread & TLS handling. [1]. https://forum.snapcraft.io/t/nvidia-acceleration-on-chrome-and-firefox/4532/ Signed-off-by: Maciej Borzecki <maciej.zenon.borzecki@canonical.com>
Make sure that we pick up nvidia TLS libs otherwise applications using libGLX will fail in most mysterious ways. The problem was debugged in detail in this forum topic [1]. A simple test case using glxinfo would segfault both inside the snap mount namespace and in chroot, the backtrace pointing back to pthread_mutex_lock(): (gdb) bt #0 0x00007ffff7559fb4 in pthread_mutex_lock () from target:/lib/x86_64-linux-gnu/libc.so.6 #1 0x00007ffff6f5eddb in mt_mutex_lock (mutex=0x7ffff71e5180 <dispatchLock>) at glvnd_pthread.c:317 #2 0x00007ffff6f23f77 in LockDispatch () at GLdispatch.c:144 #3 0x00007ffff6f24115 in __glDispatchNewVendorID () at GLdispatch.c:198 #4 0x00007ffff7212607 in __glXLookupVendorByName (vendorName=0x60d160 "nvidia") at libglxmapping.c:442 #5 0x00007ffff7213811 in __glXLookupVendorByScreen (dpy=0x60aab0, screen=0) at libglxmapping.c:574 #6 0x00007ffff7213966 in __glXGetDynDispatch (dpy=0x60aab0, screen=0) at libglxmapping.c:608 #7 0x00007ffff7209563 in glXChooseVisual (dpy=0x60aab0, screen=0, attrib_list=0x609200) at libglx.c:215 snapcore#8 0x00007ffff7b89d58 in glXChooseVisual (dpy=0x60aab0, screen=0, attribList=0x609200) at g_libglglxwrapper.c:183 snapcore#9 0x0000000000401741 in ?? () snapcore#10 0x00007ffff7465830 in __libc_start_main () from target:/lib/x86_64-linux-gnu/libc.so.6 snapcore#11 0x0000000000401ea9 in ?? () Further debugging revealed that this may be related to libc/pthread & TLS handling. [1]. https://forum.snapcraft.io/t/nvidia-acceleration-on-chrome-and-firefox/4532/ Signed-off-by: Maciej Borzecki <maciej.zenon.borzecki@canonical.com>
Thank you for your contribution, the implemetnation is valid and have no negative impact on the existing code, go merge ! Cheers Fixes #1
* o/devicestate: add ensureCloudInitRestricted to DeviceManager This function will disable or restrict cloud-init after seeding is complete on an Ubuntu Core system. This is the full implementation of the mitigation of CVE-2020-11933 and https://bugs.launchpad.net/snapd/+bug/1879530. We want to allow some uses of cloud-init to continue to work, but we don't want cloud-init to be able to trigged arbitrarily after first boot because at that point the device should be considered "locked down". Signed-off-by: Ian Johnson <ian.johnson@canonical.com> * o/devicestate/devicemgr: set cloudInitAlreadyRestricted bool, use to skip early If we already restricted cloud-init we can set a manager bool to prevent unnecessary checking again for the duration of the manager. If snapd is restarted for example, it will ping cloud-init again to check the status and re-set the variable. Also add tests around this, including a full call to devicemgr.Ensure() to test that Ensure() calls ensureCloudInitRestricted(). Signed-off-by: Ian Johnson <ian.johnson@canonical.com> * o/devicestate/devicemgr, tests: adjust error msg, test names Signed-off-by: Ian Johnson <ian.johnson@canonical.com> * tests/o/devicestate: disable device registration in cloud-init Ensure() test Signed-off-by: Ian Johnson <ian.johnson@canonical.com> * tests/o/devicestate/cloudinit: simplify tests * Move duplicated setup to the SetUpTest preamble * Use a shared mockLogger instead of creating individual ones * Fix import ordering * Add missing MockCommand restores Signed-off-by: Ian Johnson <ian.johnson@canonical.com> * o/devicestate/devicemgr: adjust EnsureBefore logic to use time instead of count Previously, we were using the number of times we were called with a counter to determine if a specific time had elapsed, but this is fragile since EnsureBefore does not guarantee that we run in the specified time exactly, it ensures only that we will get re-run at some point before the specified time. This means that we could get scheduled to re-run very soon in time and incorrectly conclude that a significant amount of time had elapsed when in fact it had not. As a matter of fact, this bug was actually being relied upon (unknowingly in my defense) in the unit tests, where a call to settle() would just call Ensure repeatedly and cause the logic to assume that the specific time had elapsed. The solution to all of this is to keep track of time instead of count. Here, we save the first time we encounter cloud-init in one of the states we track it in, and check in all future instances if the time has actually elapsed before continuing. This does require significant mocking of time in the unit tests, but otherwise is a good solution. Signed-off-by: Ian Johnson <ian.johnson@canonical.com> * o/devicestate/devicemgr: while waiting in error state, only output msg once This previously would output a message every time EnsureCloudInitRestricted was called before hitting the timeout, but really we should only output it on the first time we find cloud-init in this state. Also add a test for this scenario, with Ensure getting scheduled before the 3 minute timeout has elapsed, so that we also have some test coverage of the timeout logic for error, previously we only had this logic covered for the CloudInitEnabled state. Signed-off-by: Ian Johnson <ian.johnson@canonical.com>
* o/devicestate: add ensureCloudInitRestricted to DeviceManager This function will disable or restrict cloud-init after seeding is complete on an Ubuntu Core system. This is the full implementation of the mitigation of CVE-2020-11933 and https://bugs.launchpad.net/snapd/+bug/1879530. We want to allow some uses of cloud-init to continue to work, but we don't want cloud-init to be able to trigged arbitrarily after first boot because at that point the device should be considered "locked down". Signed-off-by: Ian Johnson <ian.johnson@canonical.com> * o/devicestate/devicemgr: set cloudInitAlreadyRestricted bool, use to skip early If we already restricted cloud-init we can set a manager bool to prevent unnecessary checking again for the duration of the manager. If snapd is restarted for example, it will ping cloud-init again to check the status and re-set the variable. Also add tests around this, including a full call to devicemgr.Ensure() to test that Ensure() calls ensureCloudInitRestricted(). Signed-off-by: Ian Johnson <ian.johnson@canonical.com> * o/devicestate/devicemgr, tests: adjust error msg, test names Signed-off-by: Ian Johnson <ian.johnson@canonical.com> * tests/o/devicestate: disable device registration in cloud-init Ensure() test Signed-off-by: Ian Johnson <ian.johnson@canonical.com> * tests/o/devicestate/cloudinit: simplify tests * Move duplicated setup to the SetUpTest preamble * Use a shared mockLogger instead of creating individual ones * Fix import ordering * Add missing MockCommand restores Signed-off-by: Ian Johnson <ian.johnson@canonical.com> * o/devicestate/devicemgr: adjust EnsureBefore logic to use time instead of count Previously, we were using the number of times we were called with a counter to determine if a specific time had elapsed, but this is fragile since EnsureBefore does not guarantee that we run in the specified time exactly, it ensures only that we will get re-run at some point before the specified time. This means that we could get scheduled to re-run very soon in time and incorrectly conclude that a significant amount of time had elapsed when in fact it had not. As a matter of fact, this bug was actually being relied upon (unknowingly in my defense) in the unit tests, where a call to settle() would just call Ensure repeatedly and cause the logic to assume that the specific time had elapsed. The solution to all of this is to keep track of time instead of count. Here, we save the first time we encounter cloud-init in one of the states we track it in, and check in all future instances if the time has actually elapsed before continuing. This does require significant mocking of time in the unit tests, but otherwise is a good solution. Signed-off-by: Ian Johnson <ian.johnson@canonical.com> * o/devicestate/devicemgr: while waiting in error state, only output msg once This previously would output a message every time EnsureCloudInitRestricted was called before hitting the timeout, but really we should only output it on the first time we find cloud-init in this state. Also add a test for this scenario, with Ensure getting scheduled before the 3 minute timeout has elapsed, so that we also have some test coverage of the timeout logic for error, previously we only had this logic covered for the CloudInitEnabled state. Signed-off-by: Ian Johnson <ian.johnson@canonical.com>
Merge pull request snapcore#9025 from mvo5/feature/cloud-init-disable This is #2 from the snapd-private repo used to address the cloud-init fix. Built on top of snapcore#9024.
This change adds a new line in the /etc/sudoers file to prevent an error which is happening in debian and fedora after latest updates: # syntax error, unexpected WORD, expecting END or ':' or '\n' The error: Error: 2020-09-28 21:54:59 Error executing google:debian-sid-64:tests/main/sudo-env (sep282050-048295) : ----- ... + tests.session -u test exec sudo sh -c 'echo :$PATH:' /etc/sudoers:28: syntax error, unexpected WORD, expecting END or ':' or '\n' test ALL=(ALL) NOPASSWD:ALL ^~~~ We trust you have received the usual lecture from the local System Administrator. It usually boils down to these three things: #1) Respect the privacy of others. #2) Think before you type. #3) With great power comes great responsibility. sudo: a terminal is required to read the password; either use the -S option to read from standard input or configure an askpass helper
No description provided.