interfaces/builtin: use udev tagging more broadly #3617

Merged
merged 45 commits into from Aug 29, 2017

Conversation

Projects
None yet
7 participants
Contributor

adglkh commented Jul 25, 2017

It's a long-standing bug in snapd.
https://bugs.launchpad.net/snapd/+bug/1675738

We have some interfaces using udev tagging, but quite a few interfaces are still without udev tagging. So when people create a snap which has a combination of udev tagging plugs and none udev tagging plugs, an issue occurs due to device access denied since snap-confine only loads udev rules and creates a device cgroup for the tagged devices, excluding untagged ones.

adglkh added some commits Jul 12, 2017

Use udev tagging for framebuffer interface and adjust test cases.
Use udev tagging for framebuffer interface and adjust test cases.
Simplify sanitizeSlot for most interfaces.
Avoid to generate duplicate udev rule entries in modem manager interface.
Use udev tagging for ofono interface and adjust test cases.
Use udev tagging for ofono interface and adjust test cases.
Fix udev rule for modem manager interface.
Use udev tagging for docker support interface and adjust test cases.
dmsetup tool is required to apply the following udev rule. However it
looks like we don't have dmsetup pre-installed on core.
Use udev tagging for udisks2 interface and adjust test cases.
some changes with a consistent code style for some existing interfaces.
Fix a bunch of unit tests.
some minor changes on code style.
interfaces/builtin/alsa.go
func init() {
- registerIface(&commonInterface{
@mvo5

mvo5 Jul 27, 2017

Collaborator

A bit of a meta-question - would it make sense to add an optional connectedPlugUdev to commonInterface so that not all the interfaces that use commonInterface need to be exapnded ?

@adglkh

adglkh Jul 27, 2017

Contributor

Yes, it makes sense for some interfaces.
I'll fix it in the next commit.
Thanks.

adglkh added some commits Jul 27, 2017

Add a connectedPlugUdev function to commonInterface.
Add a connectedPlugUdev function to commonInterface and modify the
registerInterface call with less intervention to support udev tagging.
Contributor

jdstrand commented Jul 27, 2017

@adglkh - there are a lot of conflicts now. Can you clean these up? Perhaps this has something to do with @zyga's most recent commits?

codecov-io commented Jul 28, 2017

Codecov Report

Merging #3617 into master will increase coverage by 0.06%.
The diff coverage is 100%.

Impacted file tree graph

@@            Coverage Diff            @@
##           master   #3617      +/-   ##
=========================================
+ Coverage   75.63%   75.7%   +0.06%     
=========================================
  Files         407     407              
  Lines       35034   35093      +59     
=========================================
+ Hits        26499   26566      +67     
+ Misses       6654    6648       -6     
+ Partials     1881    1879       -2
Impacted Files Coverage Δ
interfaces/builtin/time_control.go 100% <ø> (ø) ⬆️
interfaces/builtin/uhid.go 100% <ø> (ø) ⬆️
interfaces/builtin/kvm.go 100% <ø> (ø) ⬆️
interfaces/builtin/hardware_random_observe.go 100% <ø> (ø) ⬆️
interfaces/builtin/broadcom_asic_control.go 100% <ø> (ø) ⬆️
interfaces/builtin/physical_memory_observe.go 100% <ø> (ø) ⬆️
interfaces/builtin/physical_memory_control.go 100% <ø> (ø) ⬆️
interfaces/builtin/hardware_random_control.go 100% <ø> (ø) ⬆️
interfaces/builtin/io_ports_control.go 100% <ø> (ø) ⬆️
interfaces/builtin/udisks2.go 100% <100%> (ø) ⬆️
... and 26 more

Continue to review full report at Codecov.

Legend - Click here to learn more
Δ = absolute <relative> (impact), ø = not affected, ? = missing data
Powered by Codecov. Last update 55c86cb...4dc3c47. Read the comment docs.

Contributor

jdstrand commented Aug 1, 2017

@adglkh - unfortunately there are more conflicts. Can you clean these up (again)?

adglkh added some commits Aug 2, 2017

interfaces/builtin/alsa_test.go
@@ -1,7 +1,7 @@
// -*- Mode: Go; indent-tabs-mode: t -*-
/*
- * Copyright (C) 2016 Canonical Ltd
+ * Copyright (C) 2017 Canonical Ltd
@morphis

morphis Aug 2, 2017

Contributor

Should be 2016-2017

@adglkh

adglkh Aug 3, 2017

Contributor

Thanks.
I'll fix it accordingly in each *_test.go I modified.

This is very much on the right track, thanks! Please make the requested changes.

Curious on the testing performed-- I know you updated the testsuite but did you blackbox test by connecting these plugs and seeing if you could access the devices?

interfaces/builtin/alsa.go
+KERNEL=="pcm[CD0-9cp]*", NAME="snd/%%k", TAG+="%[1]s"
+KERNEL=="midiC[D0-9]*", NAME="snd/%%k", TAG+="%[1]s"
+KERNEL=="timer", NAME="snd/%%k", TAG+="%[1]s"
+KERNEL=="seq", NAME="snd/%%k", TAG+="%[1]s"
@jdstrand

jdstrand Aug 2, 2017

Contributor

Where did you get this list? I don't think it is quite right be looking at my system and reading http://www.reactivated.net/writing_udev_rules.html#strmatch. Also, I don't think we need 'NAME' here since we are only tagging kernel devices and not trying to rename them (this is true everywhere you use NAME)-- did you add NAME for a specific reason?

I think you want this instead:

KERNEL=="controlC[0-9]*",        TAG+="%[1]s"
KERNEL=="hwC[0-9]*D[0-9]*",      TAG+="%[1]s"
KERNEL=="pcmC[0-9]*D[0-9]*[cp]", TAG+="%[1]s"
KERNEL=="midiC[0-9]*D[0-9]*",    TAG+="%[1]s"
KERNEL=="timer",                 TAG+="%[1]s"
KERNEL=="seq",                   TAG+="%[1]s"
@jdstrand

jdstrand Aug 2, 2017

Contributor

Not to mention, I feel like the list may be incomplete. I see in /lib/udev/rules.d references to card*. I think at least this should be added:

SUBSYSTEM=="sound", KERNEL=="card[0-9]*", TAG+="%[1]s"
@adglkh

adglkh Aug 3, 2017

Contributor

Adding the name here ensures that the sound device node appears exclusively in the /dev/snd directory where they are created in my system and also it meant to be consistent with /dev/snd/* in apparmor policy for alsa interface. Removing the name results in sound devices are created under /dev directory by default. But I couldn't find them there(/dev) in my system.

Basically, it's harmless to have 'NAME' here for each device. I need to confirm this at this point before I proceed.

SUBSYSTEM=="sound", KERNEL=="card[0-9]*", TAG+="%[1]s"
Yes, I saw it. Thanks for the mention.

@jdstrand

jdstrand Aug 3, 2017

Contributor

Well, the system should already have rules for putting devices in /dev/snd. Your rules are only about tagging the devices. AIUI the NAME field, it does affect where things are put so I didn't want to override what the system is already providing so suggested that NAME be removed.

Are you saying that if you omit NAME, when you connect the interface you now see /dev/pcm..., etc? If that is the case, we should look at why that is happening-- we only want to add a tag, not change existing rules.

@adglkh

adglkh Aug 4, 2017

Contributor

Okay, got your point.
Let's remove NAME key for each rule of the interfaces.
I'll also give it a try on snap to check if it works for me with the fine-tuned udev rules.
Thanks.

interfaces/builtin/alsa_test.go
+KERNEL=="midiC[D0-9]*", NAME="snd/%k", TAG+="snap_other_app"
+KERNEL=="timer", NAME="snd/%k", TAG+="snap_other_app"
+KERNEL=="seq", NAME="snd/%k", TAG+="snap_other_app"
+`
@jdstrand

jdstrand Aug 2, 2017

Contributor

It's a little weird that the expectedSnippet declaration is so far from its use. Can you move it after the apparmor tests and before the udev tests? This is true for other _test.go files as well.

@adglkh

adglkh Aug 3, 2017

Contributor

Sure.

interfaces/builtin/bluetooth_control.go
+#
+# Do not edit this file, it will be overwritten on updates
+
+SUBSYSTEM=="bluetooth", KERNEL=="hci[0-9]*", TAG+="%s"
@jdstrand

jdstrand Aug 2, 2017

Contributor

hci* are virtual devices-- do virtual devices need to be added to the device cgroup?. Also, bluetooth-control does have an apparmor access for /dev/vhci but there is no udev rule for it.

+#
+# Do not edit this file, it will be overwritten on updates
+
+SUBSYSTEM=="net", KERNEL=="bdev", TAG+="%[1]s"
@jdstrand

jdstrand Aug 2, 2017

Contributor

I thought this was going to be (to match the apparmor /dev access):

SUBSYSTEM=="net", KERNEL=="linux-user-bde", TAG+="%[1]s"
SUBSYSTEM=="net", KERNEL=="linux-kernel-bde", TAG+="%[1]s"
SUBSYSTEM=="net", KERNEL=="linux-bcm-knet", TAG+="%[1]s"

where did you get your rule?

@adglkh

adglkh Aug 3, 2017

Contributor

Here is the udev rule from upstream,
https://git.openswitch.net/cgit/openswitch/ops-build/commit/?id=c0e324d0e76e9464f115434cce74301b5794ff61

I'm afraid it doesn't work that way if we use kernel module name rather than the 'bdev' (bcm device) in this case.

@jdstrand

jdstrand Aug 3, 2017

Contributor

So long as we are using base_dev_name=bdev in the module loading, I guess what you had before would work. Where do we guarantee that is happening?

If using 'bdev' instead, can you add a comment above your rule?

@adglkh

adglkh Aug 4, 2017

Contributor

Yes, basically, this interface was added since it's needed by a customer project.
I compared the rule with what was being added into upstream and found the difference here.
I'll do a further investigation on these two rules and confirm the final behavior on real device and will add the upstream link above the rule if it's the one we needed.

@adglkh

adglkh Aug 7, 2017

Contributor

@jdstrand, I took a closer look today on a machine a kernel built for openswitch.

A udev rule(/etc/udev/rules.d/60-bcm-driver.rules) executes external comment to creates three character device files(via mknod) by using loadable kernel modules, However, I am not able to query the information for all three character devices on the machine.
http://paste.ubuntu.com/25262959/

I found some hints after exporting the content of the udev database (keyword: "linux-kernel-bde" and "bcm0")
http://paste.ubuntu.com/25262850/
Then query all information for the first matched device
http://paste.ubuntu.com/25262846/
Meanwhile, there's another 'bcm0' device can be found in sysfs (the second matched device)
http://paste.ubuntu.com/25262841/

Based on these findings, the udev tagging rule for this interface would be

SUBSYSTEM=="pci", DRIVER=="linux-kernel-bde", TAG+="%[1]s"
SUBSYSTEM=="net", KERNEL=="bcm[0-9]*", TAG+="%[1]s"

Also apparmor policy is needed to update somehow by adding a few lines, here are what I have in mind.

  /sys/devices/pci[0-9]*/**/config r,
  /sys/devices/pci[0-9]*/**/{,subsystem_}device r,
  /sys/devices/pci[0-9]*/**/{,subsystem_}vendor r,

  /sys/bus/pci/devices/** r,
  /run/udev/data/+pci:[0-9]* r,

@jdstrand

jdstrand Aug 7, 2017

Contributor

+1 on the udev changes. The apparmor policy is too broad. Can you give the specific denials the prompted each rule?

interfaces/builtin/docker_support.go
+# /dev/mapper/docker* rw,
+#
+# dmsetup tool is required to apply the following udev rule. However it looks like we don't have dmsetup pre-installed on core.
+KERNEL=="dm-[0-9]*", PROGRAM="/sbin/dmsetup info -c --noopencount --noheadings -o name -j %%M -m %%m", NAME="%%k", SYMLINK+="mapper/%%c", TAG+="%[1]s"
@jdstrand

jdstrand Aug 2, 2017

Contributor

I don't think we want to have udev rules for docker-supprort since docker can be used to add devices to a container. If we add udev rules, the only devices it could add would be those here. Perhaps it makes sense to document in the interface that we are intentionally not creating udev rules.

@adglkh

adglkh Aug 3, 2017

Contributor

Yes, docker supports to add a rule to the cgroup allowed devices list.
I'll drop udev rules for docker-support interface in this case and document the reason.
Thanks for the mention.

interfaces/builtin/mir.go
+#
+# Do not edit this file, it will be overwritten on updates
+
+KERNEL=="tty", TAG+="%[1]s"
@jdstrand

jdstrand Aug 2, 2017

Contributor

/dev/tty is already added by defaults (see cmd/snap-confine/udev-support.c)

@adglkh

adglkh Aug 3, 2017

Contributor

I will remove it in the next commit.

interfaces/builtin/mir.go
+KERNEL=="mice", NAME="input/%%k", TAG+="%[1]s"
+KERNEL=="mouse*", NAME="input/%%k", TAG+="%[1]s"
+KERNEL=="event*", NAME="input/%%k", TAG+="%[1]s"
+KERNEL=="js*", NAME="input/%%k", TAG+="%[1]s"
@jdstrand

jdstrand Aug 2, 2017

Contributor

We have a joystick interface. I wonder if we should omit js here?

@adglkh

adglkh Aug 3, 2017

Contributor

Yes, I should remove it to avoid overlapping each other.
Same for /dev/ttyS* in modem_manager.go

interfaces/builtin/mir.go
+KERNEL=="mouse*", NAME="input/%%k", TAG+="%[1]s"
+KERNEL=="event*", NAME="input/%%k", TAG+="%[1]s"
+KERNEL=="js*", NAME="input/%%k", TAG+="%[1]s"
+KERNEL=="ts*", NAME="input/%%k", TAG+="%[1]s"
@jdstrand

jdstrand Aug 2, 2017

Contributor

Where did you see /dev/input/ts*? Also, instead of mouse*, event* and ts*, I think we want mouse[0-9]*, event[0-9]* and ts[0-9]*. Also, you should drop 'NAME=' (see above).

@jdstrand

jdstrand Aug 4, 2017

Contributor

Ah, thanks! :)

+ spec.AddSnippet(fmt.Sprintf(mirPermanentSlotUdev, tag))
+ }
+ return nil
+}
@jdstrand

jdstrand Aug 2, 2017

Contributor

Would it make sense to move this to common.go like you did UDevConnectedPlug?

@adglkh

adglkh Aug 4, 2017

Contributor

Yes, it makes sense.

interfaces/builtin/modem_manager.go
@@ -200,6 +201,8 @@ const modemManagerPermanentSlotUDev = `
# Concatenation of all ModemManager udev rules
# do not edit this file, it will be overwritten on update
+KERNEL=="tty[A-Z]*[0-9]|cdc-wdm[0-9]*" TAG+="%s"
@jdstrand

jdstrand Aug 2, 2017

Contributor

I think you meant to remove this since you are adding per-command lines via modemManagerPermanentSlotUDevTag.

interfaces/builtin/modem_manager.go
+#
+# Do not edit this file, it will be overwritten on updates
+
+KERNEL=="tty[A-Z]*[0-9]|cdc-wdm[0-9]*", TAG+="%s"
@jdstrand

jdstrand Aug 2, 2017

Contributor

This includes /dev/ttyS* which might be what you want. Can you comment? If not, this should work:

# omit ttyS* since that is covered by the serial-port interface
KERNEL=="tty[A-RT-Z]*[0-9]|cdc-wdm[0-9]*" TAG+="%s"
@adglkh

adglkh Aug 3, 2017

Contributor

Aha, I didn't notice we already have /dev/ttyS* in serial-port interface.

interfaces/builtin/network_control.go
+# Do not edit this file, it will be overwritten on updates
+
+KERNEL=="rfkill", TAG+="%[1]s"
+KERNEL=="tap*", TAG+="%[1]s"
@jdstrand

jdstrand Aug 2, 2017

Contributor

According to https://github.com/torvalds/linux/blob/master/Documentation/admin-guide/devices.txt, I think we should use:

KERNEL=="tap[0-9]*",   TAG+="%[1]s"
interfaces/builtin/network_control.go
+
+KERNEL=="rfkill", TAG+="%[1]s"
+KERNEL=="tap*", TAG+="%[1]s"
+KERNEL=="tun[0-9]*", NAME="net/%%k", TAG+="%[1]s"
@jdstrand

jdstrand Aug 2, 2017

Contributor

We need this here (use of /dev/net/tun creates /dev/tun* devices):

KERNEL=="tun", TAG+="%[1]s"
KERNEL=="tun[0-9]*", TAG+="%[1]s"
interfaces/builtin/ofono.go
+#
+# Do not edit this file, it will be overwritten on updates
+
+KERNEL=="tty[A-Z]*[0-9]|cdc-wdm[0-9]*", TAG+="%[1]s"
@jdstrand

jdstrand Aug 2, 2017

Contributor

Same comment here wrt ttyS*.

interfaces/builtin/ofono.go
+# Do not edit this file, it will be overwritten on updates
+
+KERNEL=="tty[A-Z]*[0-9]|cdc-wdm[0-9]*", TAG+="%[1]s"
+KERNEL=="tun[0-9]*", NAME="net/%%k", TAG+="%[1]s"
@jdstrand

jdstrand Aug 2, 2017

Contributor

and here wrt to tun devices.

interfaces/builtin/ofono.go
+KERNEL=="tun[0-9]*", NAME="net/%%k", TAG+="%[1]s"
+KERNEL=="dsp", TAG+="%[1]s"
+KERNEL=="ttyLTM[0-9]", SYMLINK+="modem%%e", TAG+="%[1]s"
+KERNEL=="ttyUSB[0-9]", SYMLINK+="modem%%e", TAG+="%[1]s"
@jdstrand

jdstrand Aug 2, 2017

Contributor

We don't need SYMLINK here. We are just tagging.

interfaces/builtin/opengl.go
+# Do not edit this file, it will be overwritten on updates
+
+KERNEL=="card[0-9]*", NAME="dri/card%%n", TAG+="%[1]s"
+KERNEL=="nvidia*|nvidiactl*", NAME="%%k", TAG+="%[1]s"
@jdstrand

jdstrand Aug 2, 2017

Contributor

Drop 'NAME=' here and you missed /dev/vchiq.This should be:

SUBSYSTEM="drm", KERNEL=="card[0-9]*", TAG+="%[1]s"
KERNEL=="nvidia*", TAG+="%[1]s"
KERNEL=="vchiq", TAG+="%[1]s"

Since the apparmor policy has a redundancy too, can you update it to remove /dev/nvidiactl rw, and /dev/nvidia-modeset rw, since /dev/nvidia* rw, covers all of them?

@adglkh

adglkh Aug 3, 2017

Contributor

Sure.
One quick question: Is vchiq kept for bcm device(GPU) on PI?
Thanks.

interfaces/builtin/optical_drive.go
+#
+# Do not edit this file, it will be overwritten on updates
+
+KERNEL=="sr[0-9]*", NAME="%%k", SYMLINK+="scd%%n", TAG+="%s"
@jdstrand

jdstrand Aug 2, 2017

Contributor

We can drop NAME and SYMLINK. /dev/scd* aren't always symlinks, so adjust to be:

KERNEL=="sr[0-9]*",  TAG+="%[1]s"
KERNEL=="scd[0-9]*", TAG+="%[1]s"
interfaces/builtin/optical_drive_test.go
+
+func (s *OpticalDriveInterfaceSuite) TestInterfaces(c *C) {
+ c.Check(builtin.Interfaces(), testutil.DeepContains, s.iface)
+}
@jdstrand

jdstrand Aug 2, 2017

Contributor

Thank you for adding these missing tests.

interfaces/builtin/ppp.go
- return true
-}
+KERNEL=="ppp", TAG+="%[1]s"
+KERNEL=="tty[0-9]*", TAG+="%[1]s"
@jdstrand

jdstrand Aug 2, 2017

Contributor

The apparmor rule was /dev/tty[^0-9]* rw,, so this should be:

KERNEL=="tty[A-Z]*", TAG+="%[1]s"
@adglkh

adglkh Aug 4, 2017

Contributor

My stupid mistake.

interfaces/builtin/pulseaudio.go
+# Do not edit this file, it will be overwritten on updates
+KERNEL=="pcm[CD0-9cp]*", NAME="snd/%%k", TAG+="%[1]s"
+KERNEL=="controlC[0-9]*", NAME="snd/%%k", TAG+="%[1]s"
+KERNEL=="timer", NAME="snd/%%k", TAG+="%[1]s"
@jdstrand

jdstrand Aug 2, 2017

Contributor

Like above, drop NAME and update the globs to be:

KERNEL=="controlC[0-9]*",        TAG+="%[1]s"
KERNEL=="pcmC[0-9]*D[0-9]*[cp]", TAG+="%[1]s"
KERNEL=="timer",                 TAG+="%[1]s"
interfaces/builtin/time_control.go
- // Allow what is allowed in the declarations
- return true
-}
+KERNEL=="/dev/rtc0", TAG+="%s"
@jdstrand

jdstrand Aug 2, 2017

Contributor

This should be:

SUBSYSTEM=="rtc", TAG+="%s"
interfaces/builtin/tpm.go
+#
+# Do not edit this file, it will be overwritten on updates
+
+KERNEL=="tpm*", TAG+="%s"
@jdstrand

jdstrand Aug 2, 2017

Contributor

This should be:

KERNEL=="tpm[0-9]*", TAG+="%s"
interfaces/builtin/udisks2.go
+# Do not edit this file, it will be overwritten on updates
+
+KERNEL=="sr*|md*|fd*|sd*|mmcblk[0-9]|mspblk[0-9]", TAG+="%[1]s"
+SUBSYSTEMS=="usb", TAG+="%[1]s"
@jdstrand

jdstrand Aug 2, 2017

Contributor

I know we're missing vd*. I think perhaps change this to:

SUBSYSTEM=="block", TAG+="%[1]s"
KERNEL=="fd[0-9]*, TAG+="%[1]s"
# This tags all USB devices, so we'll use AppArmor to mediate specific access (eg, /dev/sd* and /dev/mmcblk*)
SUBSYSTEM=="usb", TAG+="%[1]s"

Can you update the apparmor policy to have this:

/dev/vd* r,
@adglkh

adglkh Aug 3, 2017

Contributor

My concerns on this line were that it probably opens unnecessary holes in the confinement system since we grant people permission accessing all USB devices. However I forget, on the other hand, we could enforce AppArmor profile constraints for the confinement escape. I guess this strategy applies to raw_usb, broadcom_asic_control too. Thanks for your comments above

@adglkh

adglkh Aug 4, 2017

Contributor

@jdstrand I double-checked here
fd[0-9]* would be covered by SUBSYSTEM=="block", do we really need to keep fd[0-9]* in the udev rule for udisk2 interface?

@jdstrand

jdstrand Aug 4, 2017

Contributor

I would be fine to remove the fd lines-- I was looking at the udev rules and saw it handled floppy a little differently, so put it. Really, it doesn't matter-- the apparmor policy currently only allows /dev/sd* and /dev/mmcblk* (and if you added it, /dev/vd*). I think you are right to just use block and usb subsystems and then we'll use apparmor globbing for which to allow.

interfaces/builtin/camera_test.go
+
+func (s *CameraInterfaceSuite) TestInterfaces(c *C) {
+ c.Check(builtin.Interfaces(), testutil.DeepContains, s.iface)
+}
@jdstrand

jdstrand Aug 2, 2017

Contributor

Thank you for adding this to the testsuite.

Contributor

jdstrand commented Aug 2, 2017

@adglkh - note #3609 which is on the verge of landing. If it lands, it might be nice (though not required for merging) to update it to use UDevConnectedPlug.

Contributor

adglkh commented Aug 3, 2017

Thanks for a detailed review.

I have a bunch of simple apps with individual and multiple interfaces combinations declared in its yaml file for black-box testing(udev tagging verification). I was also thinking if it's good timing to update spread test of snap-confine. We moved snap-confine into snapd, but it looks like we didn't update the doc and scripts accordingly(I encountered the folder&file path issue during running spread-test ). Also in order to run spread test of snap-confine, we're still relying on https://git.launchpad.net/snap-confine to build the package. It failed since one dependency(xfslibs-dev) we recently added is missing in control file of snap-confine repo on lp.

Probably we need a separated PR to fix it.

@jdstrand jdstrand deleted a comment from adglkh Aug 3, 2017

Contributor

jdstrand commented Aug 3, 2017

@zyga - could you comment on @adglkh's comments regarding spread tests?

Contributor

zyga commented Aug 4, 2017

This branch is on my TODO list but it's somewhat pushed back given how huge it is. I'll try to review it today though.

This is a pretty big PR and I'd like to de-compose it somewhat. Here's what I propose:

  • create a new PR with the new common udev function and (perhaps separate) simplification of existing interfaces to let them become common
  • tweaks and updates to tests (I'm trying to unify how those are done lately)
  • per-interface PRs that do udev tagging. This seems painful but I think it is much saner than iterating on one huge PR that touches a thousand lines in half of the interface files.

If you don't disagree I'll start chopping this into pieces and iterating on all the elements.

interfaces/builtin/common.go
@@ -142,3 +145,13 @@ func (iface *commonInterface) SecCompConnectedPlug(spec *seccomp.Specification,
}
return nil
}
+
+func (iface *commonInterface) UDevConnectedPlug(spec *udev.Specification, plug *interfaces.Plug, plugAttrs map[string]interface{}, slot *interfaces.Slot, slotAttrs map[string]interface{}) error {
@zyga

zyga Aug 4, 2017

Contributor

Thank you for doing this. I wanted to add something like this for a long time lately

adglkh and others added some commits Aug 4, 2017

Contributor

zyga commented Aug 7, 2017

Yay, the PR shrank by a few lines. I'll iterate on the remaining changes and try to get them merged to master separately so that this PR can focus just on actual udev changes.

Contributor

adglkh commented Aug 15, 2017

Ooops, Looks like sth went wrong with the merging.
Will fix it soon.

adglkh added some commits Aug 15, 2017

Merge https://github.com/snapcore/snapd into udev_tagging
* Improve test for time_control interface
* Simplify uhid interface
Contributor

adglkh commented Aug 15, 2017

This branch now has halved diff size after merging master into it and resolving lots of conflicts as well.
I think we're good to go.
@zyga Could you help review it?
@jdstrand Could you take another look at this PR?
Thanks.

I made a few remarks. I don't mind merging this if @jdstrand agrees. I highlighted some parts that could land immediately in separate PRs and one thing that is not related to udev.

interfaces/builtin/framebuffer.go
-// TODO: we are not doing this due to the bug and we'll be reintroducing
-// the udev tagging soon.
-// const framebufferUDevConnectedPlug = `KERNEL=="fb[0-9]*", TAG+="###SLOT_SECURITY_TAGS###"`
+const framebufferConnectedPlugUDev = `KERNEL=="fb[0-9]*", TAG+="###SLOT_SECURITY_TAGS###"`
@zyga

zyga Aug 16, 2017

Contributor

Thanks!

@jdstrand

jdstrand Aug 17, 2017

Contributor

s/###SLOT_SECURITY_TAGS###/###CONNECTED_SECURITY_TAGS###/

@@ -157,25 +157,18 @@ func (s *I2cInterfaceSuite) TestSanitizeBadGadgetSnapSlot(c *C) {
c.Assert(s.testUDevBadValue7.Sanitize(s.iface), ErrorMatches, "i2c slot must have a path attribute")
}
-func (s *I2cInterfaceSuite) TestConnectedPlugUDevSnippets(c *C) {
@zyga

zyga Aug 16, 2017

Contributor

Thanks!

}
-func (s *I2cInterfaceSuite) TestConnectedPlugAppArmorSnippets(c *C) {
@zyga

zyga Aug 16, 2017

Contributor

Thanks!

@@ -154,13 +154,10 @@ func (s *IioInterfaceSuite) TestSanitizeBadGadgetSnapSlot(c *C) {
}
func (s *IioInterfaceSuite) TestConnectedPlugUDevSnippets(c *C) {
@zyga

zyga Aug 16, 2017

Contributor

Thanks!

@@ -38,7 +38,7 @@ const joystickConnectedPlugAppArmor = `
/run/udev/data/c13:{[0-9],[12][0-9],3[01]} r,
`
-//const joystickConnectedPlugUDev = `KERNEL=="js[0-9]*", TAG+="###SLOT_SECURITY_TAGS###"`
@zyga

zyga Aug 16, 2017

Contributor

Nice, finally :-)

@@ -76,7 +77,7 @@ func (s *KernelModuleControlInterfaceSuite) TestSanitizePlug(c *C) {
c.Assert(s.plug.Sanitize(s.iface), IsNil)
}
-func (s *KernelModuleControlInterfaceSuite) TestUsedSecuritySystems(c *C) {
+func (s *KernelModuleControlInterfaceSuite) TestAppArmorSpec(c *C) {
@zyga

zyga Aug 16, 2017

Contributor

Thanks!

interfaces/builtin/modem_manager.go
+ udevRule := modemManagerPermanentSlotUDev
+ for appName := range slot.Apps {
+ tag := udevSnapSecurityName(slot.Snap.Name(), appName)
+ udevRule += fmt.Sprintf(modemManagerPermanentSlotUDevTag, tag)
@zyga

zyga Aug 16, 2017

Contributor

Let's please use strings.Replace

interfaces/builtin/network_manager.go
+func (iface *networkManagerInterface) UDevPermanentSlot(spec *udev.Specification, slot *interfaces.Slot) error {
+ for appName := range slot.Apps {
+ tag := udevSnapSecurityName(slot.Snap.Name(), appName)
+ spec.AddSnippet(fmt.Sprintf(networkManagerPermanentSlotUdev, tag))
@zyga

zyga Aug 16, 2017

Contributor

Let's please use strings.Replace

interfaces/builtin/ofono.go
+ udevRule := ofonoPermanentSlotUDev
+ for appName := range slot.Apps {
+ tag := udevSnapSecurityName(slot.Snap.Name(), appName)
+ udevRule += fmt.Sprintf(ofonoPermanentSlotUDevTag, tag)
@zyga

zyga Aug 16, 2017

Contributor

I'd love the same replacement logic that we use elsewhere simply because this will lessen the friction to unify everything at some point in the future.

interfaces/builtin/opengl_test.go
@@ -79,40 +80,14 @@ func (s *OpenglInterfaceSuite) TestAppArmorSpec(c *C) {
spec := &apparmor.Specification{}
c.Assert(spec.AddConnectedPlug(s.iface, s.plug, nil, s.slot, nil), IsNil)
c.Assert(spec.SecurityTags(), DeepEquals, []string{"snap.consumer.app"})
- c.Assert(spec.SnippetForTag("snap.consumer.app"), Equals, `
@zyga

zyga Aug 16, 2017

Contributor

This could be a separate PR (just this part) if you feel like it.

interfaces/builtin/pulseaudio.go
+func (iface *pulseAudioInterface) UDevPermanentSlot(spec *udev.Specification, slot *interfaces.Slot) error {
+ for appName := range slot.Apps {
+ tag := udevSnapSecurityName(slot.Snap.Name(), appName)
+ spec.AddSnippet(fmt.Sprintf(pulseaudioPermanentSlotUdev, tag))
@zyga

zyga Aug 16, 2017

Contributor

Let's please use strings.Replace here

interfaces/builtin/time_control_test.go
@@ -1,7 +1,7 @@
// -*- Mode: Go; indent-tabs-mode: t -*-
/*
- * Copyright (C) 2016 Canonical Ltd
@zyga

zyga Aug 16, 2017

Contributor

This could be a separate PR that lands very quickly.

interfaces/builtin/udisks2.go
@@ -102,6 +102,7 @@ umount /{,run/}media/**,
# give raw read access to the system disks and therefore the entire system.
/dev/sd* r,
/dev/mmcblk* r,
+/dev/vd* r,
@zyga

zyga Aug 16, 2017

Contributor

This is not related to the change (not that I dislike it but it confuses the premise of the PR)

interfaces/builtin/uhid.go
@@ -45,44 +37,17 @@ const uhidConnectedPlugAppArmor = `
/dev/uhid rw,
`
-type uhidInterface struct{}
@zyga

zyga Aug 16, 2017

Contributor

This could be a separate PR that lands very quickly.

Contributor

adglkh commented Aug 16, 2017

I just wanna keep the same code patterns in test cases for all interfaces I worked on and squeeze something unrelated to udev tagging changes in this PR.
I should submit a separated PR to do that since it makes more sense. Keeping diff sizes smaller is nice. That'd be helpful for code review as well.
Sorry about that. I'll do it now.

adglkh added a commit to adglkh/snapd that referenced this pull request Aug 16, 2017

Improve test case for time control interface.
Note: we have udev rule tagged for time control since earlier version
of snapd and try to fine-tune the rules in a seperated PR(#3617). We
just imporve the test case in this commit.

adglkh added some commits Aug 16, 2017

Contributor

zyga commented Aug 17, 2017

@jdstrand can you please re-review this PR? Garry worked on making the diff nice and small by merging other branches into master.

@zyga zyga added this to the 2.28 milestone Aug 17, 2017

Contributor

jdstrand commented Aug 17, 2017

Yes. I would've done it sooner but @adglkh said he had more to do. I see new commits since then, so I'll take a look today.

This is really close; thanks for all your hard work on this. In addition to the other inline comments, please adjust TAG+="###SLOT_SECURITY_TAGS###" to be TAG+="###CONNECTED_SECURITY_TAGS###". It seems these crept in some previous commits, but lets make sure at least the things we are changing in this PR are correct. You'll want to also change interfaces/builtin/common.go

@@ -1,7 +1,7 @@
// -*- Mode: Go; indent-tabs-mode: t -*-
/*
- * Copyright (C) 2016 Canonical Ltd
+ * Copyright (C) 2016-2017 Canonical Ltd
@jdstrand

jdstrand Aug 17, 2017

Contributor

You changed the copyright in bluetooth_control_test.go, but forgot to update it and bluetooth_control.go for /dev/vhci, which is included in the apparmor policy. Can you add that?

@adglkh

adglkh Aug 18, 2017

Contributor

/dev/vhci is just a node that vhci driver created. I am not able to find it in udev database even if it exists. http://paste.ubuntu.com/25336192/
If we add udev rules, the devices we want to tag are the virtual devices.
`SUBSYSTEM=="bluetooth", KERNEL=="hci[0-9]*", TAG+="%s"

Yes, "%s" will be changed to ###CONNECTED_SECURITY_TAGS###

@jdstrand

jdstrand Aug 18, 2017

Contributor

Oh that is interesting, but I really like your idea of SUBSYSTEM bluetooth. How about just treat this like raw-usb and do:

SUBSYSTEM=="bluetooth", TAG+="%s

The 'hci' devices are virtual devices and not yet mediated by AppArmor or devices that need to be added to the device cgroup. However, tagging all bluetooth devices helps future-proof a bit in case /dev/vhci ends up showing up in udev or other bluetooth devices show up in /dev.

@adglkh

adglkh Aug 18, 2017

Contributor

Yeah, that's exactly what we're looking for.
Thanks.

interfaces/builtin/bluez.go
@@ -192,6 +193,8 @@ const bluezPermanentSlotDBus = `
</policy>
`
+const bluezConnectedPlugUDev = `KERNEL=="rfkill", TAG+="###SLOT_SECURITY_TAGS###"`
@jdstrand

jdstrand Aug 17, 2017

Contributor

The variable name is bluezConnectedPlugUDev but the TAG is ###SLOT_SECURITY_TAGS###, which is not quite right. With apparmor policy there is plug side and slot side policy, but with udev tagging, there is only the tag of what is being connected. I suggest changing to ###CONNECTED_SECURITY_TAGS###

@jdstrand

jdstrand Aug 18, 2017

Contributor

Thanks for fixing all these! :)

+/sys/devices/pci[0-9]*/0000:00:1c.0/{,subsystem_}vendor r,
+
+/sys/bus/pci/devices/0000:00:1c.0/** r,
+/run/udev/data/+pci:0000:00:1c.0 r,
@jdstrand

jdstrand Aug 17, 2017

Contributor

This doesn't seem right since I suspect that the devices might show up in other places than /sys/devices/pci0000:00/0000:00:1c.0. For example, I don't have these modules loaded on my laptop, but I do have these paths.

Until https://bugs.launchpad.net/ubuntu/+source/snapd/+bug/1570860/comments/1 is implemented, we probably need to use broader glob rules like:

/sys/devices/pci[0-9]*/**/config r,
/sys/devices/pci[0-9]*/**/{,subsystem_}device r,
/sys/devices/pci[0-9]*/**/{,subsystem_}vendor r,

/sys/bus/pci/devices/ r,
/run/udev/data/+pci:[0-9]* r,

Note, I changed the /sys/bus/pci/devices rule because it should be filled with symlinks, not actual files, and apparmor resolves symlinks.

@adglkh

adglkh Aug 17, 2017

Contributor

Ah, right. There was another common detail I didn't take into account.
Using broader glob rules is a good fit, at least for now.
I take a note here.
RE: /sys/bus/pci/devices rule
I'd expect we need the same change for opengl interface.

Thanks for your explanation!

+# The second rule for matched device http://paste.ubuntu.com/25262841/
+
+KERNEL=="0000:01:00.0", SUBSYSTEM=="pci", DRIVER=="linux-kernel-bde", TAG+="###SLOT_SECURITY_TAGS###"
+SUBSYSTEM=="net", KERNEL=="bcm[0-9]*", TAG+="###SLOT_SECURITY_TAGS###"
@jdstrand

jdstrand Aug 17, 2017

Contributor

I'm surprised you can use KERNEL=="0000:01:00.0" here, but if it works, +1.

Note, I don't think we should have pastebins in the comments since I think they go away after awhile. Perhaps just mention the importants bits from the pastes (possibly with examples entries instead of all of them).

@adglkh

adglkh Aug 17, 2017

Contributor

I'll remove the comments here to keep it simple.

interfaces/builtin/camera.go
@@ -42,6 +42,8 @@ const cameraConnectedPlugAppArmor = `
/sys/devices/pci**/usb*/**/video4linux/** r,
`
+const cameraConnectedPlugUDev = `KERNEL=="video[0-9]*", TAG+="###SLOT_SECURITY_TAGS###"`
@jdstrand

jdstrand Aug 17, 2017

Contributor

s/###SLOT_SECURITY_TAGS###/###CONNECTED_SECURITY_TAGS###/

interfaces/builtin/framebuffer.go
-// TODO: we are not doing this due to the bug and we'll be reintroducing
-// the udev tagging soon.
-// const framebufferUDevConnectedPlug = `KERNEL=="fb[0-9]*", TAG+="###SLOT_SECURITY_TAGS###"`
+const framebufferConnectedPlugUDev = `KERNEL=="fb[0-9]*", TAG+="###SLOT_SECURITY_TAGS###"`
@zyga

zyga Aug 16, 2017

Contributor

Thanks!

@jdstrand

jdstrand Aug 17, 2017

Contributor

s/###SLOT_SECURITY_TAGS###/###CONNECTED_SECURITY_TAGS###/

interfaces/builtin/fuse_support.go
@@ -83,8 +83,9 @@ deny /etc/fuse.conf r,
#/{,usr/}bin/fusermount ixr,
`
+const fuseSupportConnectedPlugUDev = `KERNEL=="fuse", TAG+="###SLOT_SECURITY_TAGS###"`
@jdstrand

jdstrand Aug 17, 2017

Contributor

s/###SLOT_SECURITY_TAGS###/###CONNECTED_SECURITY_TAGS###/

interfaces/builtin/joystick.go
@@ -38,7 +38,7 @@ const joystickConnectedPlugAppArmor = `
/run/udev/data/c13:{[0-9],[12][0-9],3[01]} r,
`
-//const joystickConnectedPlugUDev = `KERNEL=="js[0-9]*", TAG+="###SLOT_SECURITY_TAGS###"`
+const joystickConnectedPlugUDev = `KERNEL=="js[0-9]*", TAG+="###SLOT_SECURITY_TAGS###"`
@jdstrand

jdstrand Aug 17, 2017

Contributor

s/###SLOT_SECURITY_TAGS###/###CONNECTED_SECURITY_TAGS###/

interfaces/builtin/modem_manager.go
@@ -1187,6 +1188,11 @@ KERNEL=="cdc-wdm*", SUBSYSTEM=="usbmisc", ENV{ID_MM_CANDIDATE}="1"
LABEL="mm_candidate_end"
`
+const modemManagerPermanentSlotUDevTag = `
+# omit ttyS* since that is covered by the serial-port interface
+KERNEL=="tty[A-RT-Z]*[0-9]|cdc-wdm[0-9]*", TAG+="%s"
@jdstrand

jdstrand Aug 17, 2017

Contributor

I think this should be:

KERNEL=="tty[A-RT-Z]*[0-9]*|cdc-wdm[0-9]*", TAG+="%s"

(note the '*' after tty[A-RT-Z]*[0-9]).

That said, in thinking about this more, the modem-manager interface apparmor policy currently allows /dev/ttyS[0-9]* so in retrospect, I think we should use this so as not to break existing snaps that don't plugs serial-port (not to mention, serial-port only shows up with configured gadgets so there would be no way to have modem-manager use /dev/ttyS*, which would be a regression):

KERNEL=="tty[A-Z]*[0-9]*|cdc-wdm[0-9]*", TAG+="%s"
interfaces/builtin/network_control.go
+KERNEL=="rfkill", TAG+="###SLOT_SECURITY_TAGS###"
+KERNEL=="tap[0-9]*", TAG+="###SLOT_SECURITY_TAGS###"
+KERNEL=="tun", TAG+="###SLOT_SECURITY_TAGS###",
+KERNEL=="tun[0-9]*", TAG+="###SLOT_SECURITY_TAGS###"
@jdstrand

jdstrand Aug 17, 2017

Contributor

s/###SLOT_SECURITY_TAGS###/###CONNECTED_SECURITY_TAGS###/

interfaces/builtin/network_manager.go
@@ -407,6 +408,8 @@ const networkManagerPermanentSlotDBus = `
<limit name="max_match_rules_per_connection">2048</limit>
`
+const networkManagerPermanentSlotUdev = `KERNEL=="rfkill", TAG+="###SLOT_SECURITY_TAGS###"`
@jdstrand

jdstrand Aug 17, 2017

Contributor

s/###SLOT_SECURITY_TAGS###/###CONNECTED_SECURITY_TAGS###/

interfaces/builtin/ofono.go
@@ -288,6 +288,15 @@ ATTRS{idVendor}=="1c9e", ATTRS{idProduct}=="9605", ENV{ID_USB_INTERFACE_NUM}=="0
LABEL="ofono_speedup_end"
`
+const ofonoPermanentSlotUDevTag = `
+KERNEL=="tty[A-RT-Z]*[0-9]|cdc-wdm[0-9]*", TAG+="###SLOT_SECURITY_TAGS###"
@jdstrand

jdstrand Aug 17, 2017

Contributor

Same here as with modem-manager:

KERNEL=="tty[A-Z]*[0-9]*|cdc-wdm[0-9]*", TAG+="###SLOT_SECURITY_TAGS###"
interfaces/builtin/ofono.go
+KERNEL=="tun[0-9]*", TAG+="###SLOT_SECURITY_TAGS###"
+KERNEL=="dsp", TAG+="###SLOT_SECURITY_TAGS###"
+KERNEL=="ttyLTM[0-9]", TAG+="###SLOT_SECURITY_TAGS###"
+KERNEL=="ttyUSB[0-9]", TAG+="###SLOT_SECURITY_TAGS###"
@jdstrand

jdstrand Aug 17, 2017

Contributor

These two ttys are covered by the first rule.

Also, I think we need (for other apparmor accesses):

KERNEL=="modem[0-9]*",       TAG+="###SLOT_SECURITY_TAGS###"
KERNEL=="chnlat[0-9]*",      TAG+="###SLOT_SECURITY_TAGS###"
KERNEL=="rild[0-9]*",        TAG+="###SLOT_SECURITY_TAGS###"

Also, s/###SLOT_SECURITY_TAGS###/###CONNECTED_SECURITY_TAGS###/'

@adglkh

adglkh Aug 17, 2017

Contributor

I didn't find above three udev rules after digging around.
RE: KERNEL=="modem[0-9]*"

Basically, Linux modem drivers set up the modem device /dev/modem as a symbolic link to the actual device to /dev/ttyS*. So first entry would cover this case.
And /dev/socket/rild is just a socket created by rild daemon when it runs during system boot up. See here
https://stackoverflow.com/questions/11111067/how-does-modem-code-talk-to-android-code/11111953#11111953

I suspect if it's an actual device node we can find in udev database. Same for chnlat.

So I doubt if they're really needed putting here to tag device node which does not actually exist in system.

@jdstrand

jdstrand Aug 17, 2017

Contributor

If modem is always a symlink, then that's fine (we could remove the apparmor rule then too since apparmor resolves symlinks).

@jdstrand

jdstrand Aug 17, 2017

Contributor

If rild and chnlat are actually a sockets, then we don't need a udev rule. Can you add a comment above ofonoPermanentSlotUDevTag that we intetionally skipped modem, rild and chnlat, and why?

@adglkh

adglkh Aug 18, 2017

Contributor

Okay, no problem.
I'll add my comments there.

interfaces/builtin/opengl.go
+const openglConnectedPlugUDev = `
+SUBSYSTEM="drm", KERNEL=="card[0-9]*", TAG+="###SLOT_SECURITY_TAGS###"
+KERNEL=="nvidia*", TAG+="###SLOT_SECURITY_TAGS###"
+KERNEL=="vchiq", TAG+="###SLOT_SECURITY_TAGS###"
@jdstrand

jdstrand Aug 17, 2017

Contributor

s/###SLOT_SECURITY_TAGS###/###CONNECTED_SECURITY_TAGS###/

interfaces/builtin/optical_drive.go
@@ -36,13 +36,19 @@ const opticalDriveConnectedPlugAppArmor = `
/run/udev/data/b11:[0-9]* r,
`
+const opticalDriveConnectedPlugUDev = `
+KERNEL=="sr[0-9]*", TAG+="###SLOT_SECURITY_TAGS###"
+KERNEL=="scd[0-9]*", TAG+="###SLOT_SECURITY_TAGS###"
@jdstrand

jdstrand Aug 17, 2017

Contributor

s/###SLOT_SECURITY_TAGS###/###CONNECTED_SECURITY_TAGS###/

interfaces/builtin/ppp.go
@@ -55,6 +55,11 @@ var pppConnectedPlugKmod = []string{
"ppp_generic",
}
+const pppConnectedPlugUDev = `
+KERNEL=="ppp", TAG+="###SLOT_SECURITY_TAGS###"
+KERNEL=="tty[A-Z]*", TAG+="###SLOT_SECURITY_TAGS###"
@jdstrand

jdstrand Aug 17, 2017

Contributor

We're using this elsewhere:

KERNEL=="tty[A-Z]*[0-9]*", TAG+="###SLOT_SECURITY_TAGS###"

Also, s/###SLOT_SECURITY_TAGS###/###CONNECTED_SECURITY_TAGS###/

interfaces/builtin/pulseaudio.go
+const pulseaudioPermanentSlotUdev = `
+KERNEL=="controlC[0-9]*", TAG+="###SLOT_SECURITY_TAGS###"
+KERNEL=="pcmC[0-9]*D[0-9]*[cp]", TAG+="###SLOT_SECURITY_TAGS###"
+KERNEL=="timer", TAG+="###SLOT_SECURITY_TAGS###"
@jdstrand

jdstrand Aug 17, 2017

Contributor

s/###SLOT_SECURITY_TAGS###/###CONNECTED_SECURITY_TAGS###/

interfaces/builtin/raw_usb.go
@@ -45,6 +45,8 @@ const rawusbConnectedPlugAppArmor = `
/run/udev/data/+usb:* r,
`
+const rawusbConnectedPlugUDev = `SUBSYSTEMS=="usb", TAG+="###SLOT_SECURITY_TAGS###"`
@jdstrand

jdstrand Aug 17, 2017

Contributor

s/###SLOT_SECURITY_TAGS###/###CONNECTED_SECURITY_TAGS###/

interfaces/builtin/time_control.go
@@ -92,7 +92,7 @@ capability sys_time,
/sbin/hwclock ixr,
`
-const timeControlConnectedPlugUDev = `KERNEL=="/dev/rtc0", TAG+="###SLOT_SECURITY_TAGS###"`
+const timeControlConnectedPlugUDev = `SUBSYSTEM=="rtc", TAG+="###SLOT_SECURITY_TAGS###"`
@jdstrand

jdstrand Aug 17, 2017

Contributor

s/###SLOT_SECURITY_TAGS###/###CONNECTED_SECURITY_TAGS###/

interfaces/builtin/tpm.go
@@ -35,6 +35,8 @@ const tpmConnectedPlugAppArmor = `
/dev/tpm0 rw,
`
+const tpmConnectedPlugUDev = `KERNEL=="tpm[0-9]*", TAG+="###SLOT_SECURITY_TAGS###"`
@jdstrand

jdstrand Aug 17, 2017

Contributor

s/###SLOT_SECURITY_TAGS###/###CONNECTED_SECURITY_TAGS###/

interfaces/builtin/udisks2.go
+const udisks2PermanentSlotUDevTag = `
+SUBSYSTEM=="block", TAG+="###SLOT_SECURITY_TAGS###"
+# This tags all USB devices, so we'll use AppArmor to mediate specific access (eg, /dev/sd* and /dev/mmcblk*)
+SUBSYSTEM=="usb", TAG+="###SLOT_SECURITY_TAGS###"
@jdstrand

jdstrand Aug 17, 2017

Contributor

s/###SLOT_SECURITY_TAGS###/###CONNECTED_SECURITY_TAGS###/

+1. Thanks for working through this large task! This is going to really help people.

Just a request to add one comment and then one question that I'll leave to your discretion to fix.

@@ -38,12 +38,18 @@ const broadcomAsicControlConnectedPlugAppArmor = `
/dev/linux-user-bde rw,
/dev/linux-kernel-bde rw,
/dev/linux-bcm-knet rw,
+
+/sys/devices/pci[0-9]*/**/config r,
@jdstrand

jdstrand Aug 18, 2017

Contributor

Can you add a comment here:

# These are broader than they needs to be, but until we query udev
# for specific devices, use a broader glob
@adglkh

adglkh Aug 18, 2017

Contributor

Sure. :)

-KERNEL=="linux-user-bde", TAG+="###SLOT_SECURITY_TAGS###"
-KERNEL=="linux-kernel-bde", TAG+="###SLOT_SECURITY_TAGS###"
-KERNEL=="linux-bcm-knet", TAG+="###SLOT_SECURITY_TAGS###"
+KERNEL=="0000:01:00.0", SUBSYSTEM=="pci", DRIVER=="linux-kernel-bde", TAG+="###CONNECTED_SECURITY_TAGS###"
@jdstrand

jdstrand Aug 18, 2017

Contributor

Is KERNEL=="0000:01:00.0" correct (ie, is it too narrow?). If so, perhaps just:

SUBSYSTEM=="pci", DRIVER=="linux-kernel-bde", TAG+="###CONNECTED_SECURITY_TAGS###"
@adglkh

adglkh Aug 18, 2017

Contributor

The above rules address my concerns as well.
To some extent, IMHO, The following rule is probably good enough in this case
DRIVER=="linux-kernel-bde", TAG+="###CONNECTED_SECURITY_TAGS###"
Let's finalise with yours proposal
SUBSYSTEM=="pci", DRIVER=="linux-kernel-bde", TAG+="###CONNECTED_SECURITY_TAGS###"

Contributor

adglkh commented Aug 18, 2017

Without your guys' guidance and assistance, it could not happen.
@jdstrand @zyga
Could you help take another look at this PR?
Thanks again.

@niemeyer niemeyer changed the title from Using udev tagging for snap interfaces to interfaces/builtin: use udev tagging more broadly Aug 23, 2017

A couple of questions:

@@ -38,12 +38,20 @@ const broadcomAsicControlConnectedPlugAppArmor = `
/dev/linux-user-bde rw,
/dev/linux-kernel-bde rw,
/dev/linux-bcm-knet rw,
+
+# These are broader than they needs to be, but until we query udev
+# for specific devices, use a broader glob
@niemeyer

niemeyer Aug 23, 2017

Contributor

Indeed, that looks way too broad. In fact, a bit too broad to be right. Not sure it makes sense to turn the "broadcoam-asic" interface in a sort of "read about every single PCI device in the system".

@jdstrand Note that we won't be able to change that in the future without the potential of breaking clients unknowingly.

What's the plan here?

@adglkh

adglkh Aug 24, 2017

Contributor

I think it's related to hardware assignment. We have a bug on launchpad tracking on this. Not sure where are we with that.
@jdstrand Could you share the updates and plan here?
Thanks

@jdstrand

jdstrand Aug 24, 2017

Contributor

@niemeyer, @adglkh - they are necessarily broad because in PR review it was found there was nothing in the /sys/devices path alone that made it 'broadcom-asic'. I believe it is technically possible for snapd to interrogate the system via udev to get the precise /sys/devices and /run/udev/data paths for the device (see #1226 (comment) for back of the napkin idea), but this work is neither prioritized nor assigned. As a result, this interface along with existing opengl and camera interfaces use rules that are broader than they should be (but we comment in the policy in camera and opengl about the leak). While the accesses in question do constitute an information leak, they are not terribly significant (which is why the work is not prioritized/assigned) and in the 'future work' bucket.

I think the plan should be:

  • continue with the access as written since without it, things break
  • add a comment that this is an information leak (see opengl.go)
  • at some future time, implement the udev querying in snapd and have new interfaces in series 16 use this
  • in some future iteration of snappy which is generating different policy (eg, something not 'series 16'), migrate existing interfaces that use the broad globs to using only the outputs of udev querying
interfaces/builtin/opengl.go
@@ -51,7 +51,7 @@ const openglConnectedPlugAppArmor = `
# FIXME: this is an information leak and snapd should instead query udev for
# the specific accesses associated with the above devices.
- /sys/bus/pci/devices/** r,
+ /sys/bus/pci/devices/ r,
@niemeyer

niemeyer Aug 23, 2017

Contributor

Has this change been tested? Why was the prior case necessary and why is it not needed anymore now?

This also seems unrelated to device tagging.

@adglkh

adglkh Aug 24, 2017

Contributor

We changed this rule because /sys/bus/pci/devices/ should be filled with symlinks, not actual files, and apparmor resolves symlinks. Also see here
https://github.com/adglkh/snapd/blob/1f4a0fe9c464e805afc9ccfe241b96b14d13248b/interfaces/builtin/opengl.go#L48-L50
The prior case matches any file or directory in or under /sys/bus/pci/devices/. It seems to be not needed anymore now

The same for broadcom_asic_control interface.
https://github.com/snapcore/snapd/pull/3617/files/1f4a0fe9c464e805afc9ccfe241b96b14d13248b#diff-5ef61751d67fe46b2e4b8167e20330c8R48

Yes, it's unrelated to udev tagging rule. It makes more sense to fix it in a separated PR.
Sorry about that.

@mvo5

mvo5 Aug 29, 2017

Collaborator

I reverted this change now - please open a new PR with this particular change. We are keen to land this one this is why I did the change :)

@adglkh

adglkh Aug 29, 2017

Contributor

Sure, no problem.:)

LGTM assuming we drop the unrelated opengl change from this PR (okay for another, but let's please test the change in real-world use first). For the other point, LGTM given comments from @jdstrand.

Thanks for the PR, by the way!

mvo5 added some commits Aug 29, 2017

Collaborator

mvo5 commented Aug 29, 2017

I changed the opengl.go as suggested by Gustavo and de-conflicted.

Collaborator

mvo5 commented Aug 29, 2017

This is failing currently in linode:ubuntu-core-16-64:tests/main/install-store:reexec0 which is a new test in master. I suspect this is because this is racy, I'm working on a fix for the race in https://github.com/snapcore/snapd/compare/master...mvo5:nmcli-regression-test?expand=1

mvo5 added some commits Aug 29, 2017

@@ -37,9 +37,5 @@ execute: |
actual=$(snap install --channel beta --devmode $DEVMODE_SNAP)
echo "$actual" | grep -Pzq "$expected"
- echo "Install network-manager and do basic smoke test"
@mvo5

mvo5 Aug 29, 2017

Collaborator

I removed this as it is racy in this PR at least. #3825 is a better test

Contributor

jdstrand commented Aug 29, 2017

The changes since my last review approval look fine. +1

@mvo5 mvo5 merged commit e58930f into snapcore:master Aug 29, 2017

7 checks passed

artful-amd64 autopkgtest finished (success)
Details
continuous-integration/travis-ci/pr The Travis CI build passed
Details
xenial-amd64 autopkgtest finished (success)
Details
xenial-i386 autopkgtest finished (success)
Details
xenial-ppc64el autopkgtest finished (success)
Details
yakkety-amd64 autopkgtest finished (success)
Details
zesty-amd64 autopkgtest finished (success)
Details
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment