interfaces: fix udev tagging for hooks #4144

Merged
merged 21 commits into from Nov 10, 2017

Conversation

Projects
None yet
6 participants
Contributor

zyga commented Nov 3, 2017

This branch aims to fix udev tagging to support hooks in addition to apps that
were added earlier.

There are three main patches here:

  • add spec.TagDevice method to udev.Specification, this automatically tags
    both apps and hooks
  • switch non-common interfaces to TagDevice, with exception of some special
    uses of AddSnippet
  • switch common interfaces to TagDevice, with some trivial changes to how
    that is defined.

The only remaining uses of spec.AddSnippet are special-cases that add large
chunk of arbitrary udev code that is not specifically aiming to tag a device.

This passes local unit testing, no testing was done on any hardware.

Base on initial feedback I also included changes to format udev rules
differently. They are now preceded by the snapd interface name (as a comment).
The order of entries is also different, now being sorted by TAG += if one
exists (this allows us to see everything affecting particular command easily)

Signed-off-by: Zygmunt Krynicki zygmunt.krynicki@canonical.com

zyga added some commits Nov 3, 2017

interfaces/udev: refactor acquisition of test data
This will just allow us to add apps/hooks easily later.

Signed-off-by: Zygmunt Krynicki <zygmunt.krynicki@canonical.com>
interfaces/udev: add a way to udev-tag devices for all apps/hooks
This patch introduces functionality similar to what other specification
types allow: the snippet is automatically added to all the apps and hooks
that affect the given plug or slot.

Udev is a bit special in that it allows arbitrary udev programs to be
injected (for instance, the network manager interface requires this)
but most interfaces don't need that generic functionality and instead
just want to tag a device so that all the apps associated with the
plug or slot have acess to it.

When we added hooks the udev backend was never updated to handle them
so we now noticed that hooks don't have any udev tagging at all.

With this new method we can use a much simpler API to do the right thing
while still retain the ability to add arbitrary free-form snippets
everywhere.

Signed-off-by: Zygmunt Krynicki <zygmunt.krynicki@canonical.com>
interfaces/builtin: use TagDevice instead of AddSnippet if possible
This automatically handles both apps and hooks, leading to simpler and
more correct code. The only cases that still use AddSnippet are
injecting non-tagging expressions (udisks, modem-manager, etc).

Signed-off-by: Zygmunt Krynicki <zygmunt.krynicki@canonical.com>
interfaces/builtin: convert common interfaces to new udev
The "new" udev is where the TAG += ... part is handled automatically by
the common interface and now contains support for both apps and hooks.

Signed-off-by: Zygmunt Krynicki <zygmunt.krynicki@canonical.com>

@zyga zyga requested review from pedronis, stolowski and mvo5 Nov 3, 2017

codecov-io commented Nov 3, 2017

Codecov Report

❗️ No coverage uploaded for pull request base (master@7273bc2). Click here to learn what that means.
The diff coverage is 92.64%.

Impacted file tree graph

@@            Coverage Diff            @@
##             master    #4144   +/-   ##
=========================================
  Coverage          ?   75.71%           
=========================================
  Files             ?      437           
  Lines             ?    37856           
  Branches          ?        0           
=========================================
  Hits              ?    28663           
  Misses            ?     7192           
  Partials          ?     2001
Impacted Files Coverage Δ
interfaces/builtin/utils.go 100% <ø> (ø)
interfaces/builtin/ofono.go 75.51% <ø> (ø)
interfaces/udev/spec.go 95.18% <100%> (ø)
interfaces/builtin/serial_port.go 67.17% <80%> (ø)
interfaces/builtin/hidraw.go 65.21% <87.5%> (ø)

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 7273bc2...f714b95. Read the comment docs.

Looks good, much better than the old code. Just two minor comments.

interfaces/builtin/common.go
- spec.AddSnippet(snippet)
- }
+ for _, rule := range iface.connectedPlugUDev {
+ spec.TagDevice(rule)
@stolowski

stolowski Nov 6, 2017

Contributor

Nice.

interfaces/builtin/hidraw.go
+ spec.TagDevice(fmt.Sprintf(`SUBSYSTEM=="hidraw", KERNEL=="%s"`, strings.TrimPrefix(path, "/dev/")))
+ } else {
+ spec.TagDevice(fmt.Sprintf(`IMPORT{builtin}="usb_id"
+SUBSYSTEM=="hidraw", SUBSYSTEMS=="usb", ATTRS{idVendor}=="%04x", ATTRS{idProduct}=="%04x"`, usbVendor, usbProduct))
@stolowski

stolowski Nov 6, 2017

Contributor

I'm not totally sure it's more readable than calling udevUsbDeviceSnippet helper here to be honest. Anyway, not biggie but if you decide not to use udevUsbDeviceSnippet, then perhaps udevUsbDeviceSnippet can be removed from utils?

@jdstrand

jdstrand Nov 7, 2017

Contributor

I agree, either use udevUsbDeviceSnippet where you can or remove it from utils.go.

@zyga

zyga Nov 8, 2017

Contributor

I dropped it entirely now. I think the result is much more readable.

interfaces/udev/spec_test.go
+ iface := &ifacetest.TestInterface{
+ InterfaceName: "test",
+ UDevConnectedPlugCallback: func(spec *udev.Specification, plug *interfaces.Plug, plugAttrs map[string]interface{}, slot *interfaces.Slot, slotAttrs map[string]interface{}) error {
+ spec.TagDevice(`kernel="voodoo"`)
@stolowski

stolowski Nov 6, 2017

Contributor

Could you please extend this test to have call spec.TagDevice twice?

I blackbox tested this by connecting all the (non-gadget) interfaces and found that the udev tagging rules are fine. On the one hand, the sorting of the rules is nice since the left hand side (non-TAG) part is sorted, but on the other hand, the TAGs are not grouped by command. I think it would be good to group by snap command and then by rule (eg, each command is in a stanza with stanzas separated by new lines). While this sounds cosmetic, it helps with debugging and for making policy audits easier.

interfaces/builtin/hidraw.go
+ spec.TagDevice(fmt.Sprintf(`SUBSYSTEM=="hidraw", KERNEL=="%s"`, strings.TrimPrefix(path, "/dev/")))
+ } else {
+ spec.TagDevice(fmt.Sprintf(`IMPORT{builtin}="usb_id"
+SUBSYSTEM=="hidraw", SUBSYSTEMS=="usb", ATTRS{idVendor}=="%04x", ATTRS{idProduct}=="%04x"`, usbVendor, usbProduct))
@stolowski

stolowski Nov 6, 2017

Contributor

I'm not totally sure it's more readable than calling udevUsbDeviceSnippet helper here to be honest. Anyway, not biggie but if you decide not to use udevUsbDeviceSnippet, then perhaps udevUsbDeviceSnippet can be removed from utils?

@jdstrand

jdstrand Nov 7, 2017

Contributor

I agree, either use udevUsbDeviceSnippet where you can or remove it from utils.go.

@zyga

zyga Nov 8, 2017

Contributor

I dropped it entirely now. I think the result is much more readable.

interfaces/builtin/ofono.go
+ */
+ spec.TagDevice(`KERNEL=="tty[A-Z]*[0-9]*|cdc-wdm[0-9]*"`)
+ spec.TagDevice(`KERNEL=="tun"`)
+ spec.TagDevice(`KERNEL=="tun[0-9]*"`)
@jdstrand

jdstrand Nov 7, 2017

Contributor

Oh, this tun[0-9]* tag is actually an error. I realize this PR didn't introduce this, but we should fix it. See #4031

@zyga

zyga Nov 8, 2017

Contributor

Dropped

zyga added some commits Nov 8, 2017

interfaces: tweak sorting and rendering of udev device tagging
This patch changes how the udev specification is handling sorting and
rendering of udev tagging rules. Rules are now sorted by tag and only
then by the actual command. This tends to group rules affecting a given
program into one lump. In addition each rule is now followed by a
comment describing the snapd interface that added the rule. This
improves ability to debug rules and reason about their origin quickly.

All of the interface tests are adjusted for the additional "# interface"
comment.

Some minor cleanups are done to certain tests (drop of legacy
DeepEquals + Commentf, from the days when those were []byte).
Some unused udev helper functions are dropped.

Signed-off-by: Zygmunt Krynicki <zygmunt.krynicki@canonical.com>
Contributor

zyga commented Nov 8, 2017

The udev rules cannot contain trailing comments:

foo # comment

This is not allowed. I'll update the PR after lunch.

zyga added some commits Nov 8, 2017

interfaces: drop the tun[0-9]* tag as requested by jdstrand
Signed-off-by: Zygmunt Krynicki <zygmunt.krynicki@canonical.com>
interfaces: put udev comments on preceding lines
Udev parser cannot handle commands like:

    foo # comment

Those need to be formatted as follows:

    # comment
    foo

Signed-off-by: Zygmunt Krynicki <zygmunt.krynicki@canonical.com>

Since you fixed the ofono issue and added the comment commit, I'm going to mark this as approved. I do think that it would be nice to group by command, but we didn't have that before so I don't think it should be a blocker for this PR.

Looking good.

Contributor

zyga commented Nov 10, 2017

Just for the record, this does contain the formatting changes that were requested. Jamie just didn't see it when he made that comment above. We discussed this on IRC yesterday.

Contributor

pedronis commented Nov 10, 2017

@zyga are the comments in #4146 (review) addressed here?

zyga and others added some commits Nov 10, 2017

interfaces/builtin: test extra snippets for mir
Signed-off-by: Zygmunt Krynicki <zygmunt.krynicki@canonical.com>
interfaces/builtin: test snippets more carefully for network-manager
Signed-off-by: Zygmunt Krynicki <zygmunt.krynicki@canonical.com>
interfaces/builtin: test more snippets for ofono
Signed-off-by: Zygmunt Krynicki <zygmunt.krynicki@canonical.com>
interfaces/builtin: test more snippets for pulseaudio
Signed-off-by: Zygmunt Krynicki <zygmunt.krynicki@canonical.com>
interfaces/builtin: tweak test for spi
Signed-off-by: Zygmunt Krynicki <zygmunt.krynicki@canonical.com>
interfaces/builtin: test more snippets for udisks2
Signed-off-by: Zygmunt Krynicki <zygmunt.krynicki@canonical.com>
Contributor

zyga commented Nov 10, 2017

@pedronis yes (now)

@zyga zyga merged commit 0dbad11 into snapcore:master Nov 10, 2017

1 check passed

continuous-integration/travis-ci/pr The Travis CI build passed
Details

@zyga zyga deleted the zyga:fix/udev-hooks branch Nov 10, 2017

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment