Join GitHub today
GitHub is home to over 20 million developers working together to host and review code, manage projects, and build software together.
interface: add usb device support to serial-port #1669
Conversation
morphis
reviewed
Aug 12, 2016
| panic(fmt.Sprintf("plug is not of interface %q", iface)) | ||
| } | ||
| - // NOTE: currently we don't check anything on the plug side. | ||
| + |
morphis
Aug 12, 2016
Contributor
We should verify here too for the case that we have a path specified that we're only allowed to connect when the plug as the path attribute with the same value specified.
To improve the user experience for this we may should add attribtes to the output of snap interfaces
|
Mostly LGMT, one comment inline. |
|
Last commit makes it necessary for the path attribute to be on both plug & slot. I also raised a bug for the comment about the |
|
Needs de-conflicting |
|
LGTM, @jdstrand can you have a look? |
|
@morphis - yes, after I look at a high priority bug. |
jocave
referenced this pull request
Aug 18, 2016
Closed
interfaces: add hidraw-device interface #1696
|
Please consider reviewing the PR at the same time - they are essentially the same code but for different device types: |
jdstrand
reviewed
Aug 19, 2016
| +var udevVidPidFormat = regexp.MustCompile(`^[\da-fA-F]{4}$`) | ||
| +var udevHeader = `IMPORT{builtin}="usb_id"` | ||
| +var udevEntryPattern = `SUBSYSTEM=="tty", SUBSYSTEMS=="usb", ATTRS{idVendor}=="%s", ATTRS{idProduct}=="%s"` | ||
| +var udevEntryTagPattern = `, TAG+="%s"` |
jdstrand
Aug 19, 2016
Contributor
Gustavo asked me to request that people use const string (and do a []byte(<string>) when needed) for security backend variables that hold policy. There are plenty of examples in the interfaces where this isn't happening, and they will be cleaned up.
jdstrand
reviewed
Aug 19, 2016
| } | ||
| - return fmt.Errorf("serial-port path attribute must be a valid device node") | ||
| + | ||
| + return nil |
|
Can you update docs/interfaces.md for the new attributes, etc? |
jdstrand
reviewed
Aug 19, 2016
| +// Strings used to build up udev snippet for VID+PID identified devices. The TAG | ||
| +// attribute of the udev rule is used to indicate that devices with these | ||
| +// parameters should be added to the apps device cgroup | ||
| +var udevVidPidFormat = regexp.MustCompile(`^[\da-fA-F]{4}$`) |
jdstrand
Aug 19, 2016
•
Contributor
udevVidPidFormat is hard to read (for me). Would udevVendorIdFormat be better?
UPDATE: actually, since this regex is used for Product Id too, how about udevVendorProductIdFormat?
jdstrand
reviewed
Aug 19, 2016
| + switch len(plug.Attrs) { | ||
| + case 1: | ||
| + // In the case of one attribute it should be valid path attribute | ||
| + // Check slot has a path attribute identify serial device |
jdstrand
Aug 19, 2016
•
Contributor
Ok, now that we are on the plugs side...
This comment has a grammatical error. I think it is supposed to say "Check slot has a path attribute to identify serial device".
That said, the code doesn't do that-- it is verifying if the plug side has a valid path attribute.
The PR description says: "1. A fixed "path: /dev/tty.." attribute defined on the slot with no attributes expected on the plug", but you are validating the path attribute on the plugs side.
It seems to me that the case 1 code needs to:
- remove the path check-- it is already in SanitizePlug
- if has vendor attribute, verify the pattern
- if has product attribute, verify the pattern
jdstrand
reviewed
Aug 19, 2016
| + } else { | ||
| + // use path attribute to generate specific device apparmor snippet | ||
| + // no udev required for this | ||
| + plugPath, plugOk := plug.Attrs["path"].(string) |
jdstrand
Aug 19, 2016
Contributor
This is wrong based on "1. A fixed "path: /dev/tty.." attribute defined on the slot with no attributes expected on the plug". Shouldn't this be slotPath, slotOk := slot.Attrs["path"].(string) and then you add the apparmor rule?
jdstrand
reviewed
Aug 19, 2016
| @@ -109,23 +164,63 @@ func (iface *SerialPortInterface) PermanentPlugSnippet(plug *interfaces.Plug, se | ||
| // ConnectedPlugSnippet returns security snippet specific to the plug | ||
| func (iface *SerialPortInterface) ConnectedPlugSnippet(plug *interfaces.Plug, slot *interfaces.Slot, securitySystem interfaces.SecuritySystem) ([]byte, error) { | ||
| + | ||
| + slotPath, slotOk := slot.Attrs["path"].(string) | ||
| + if !slotOk || slotPath == "" { |
jdstrand
Aug 19, 2016
Contributor
I think the logic would be clearer if you did:
if slotOk && slotPath != "" {
...
return []byte(fmt.Sprintf("%s rwk,\n", cleanedPath)), nil
} else {
...
return []byte("/dev/tty* rw,\n"), nil
...
return udevSnippet.Bytes(), nil
}
jdstrand
reviewed
Aug 19, 2016
| + case interfaces.SecurityAppArmor: | ||
| + // Wildcarded apparmor snippet as the cgroup will restrict down to the | ||
| + // specific device | ||
| + return []byte("/dev/tty* rw,\n"), nil |
jdstrand
Aug 19, 2016
•
Contributor
Thank you for using this instead of /dev/** rw,. There is a bug in snap-confine that I need to fix wrt no matched tags and these finer-grained apparmor rules help limit the impact of such bugs.
jdstrand
reviewed
Aug 19, 2016
| + udevSnippet.WriteString(fmt.Sprintf(udevEntryPattern, idVendor, idProduct)) | ||
| + tag := fmt.Sprintf("snap_%s_%s", plug.Snap.Name(), appName) | ||
| + udevSnippet.WriteString(fmt.Sprintf(udevEntryTagPattern, tag) + "\n") | ||
| + } |
jdstrand
Aug 19, 2016
Contributor
If we are going to support vendor, product or vendor+product (which I thought we would), then this needs to be reworked.
morphis
Aug 22, 2016
Contributor
We shouldn't. We can add support for this easily later without breaking anything but for now I don't see any need to assign access to all devices from the same vendor or product type.
|
Ok, excepting the questions regarding attributes, whether product id and vendor id can be specified separately, I want to discuss this PR direction to make sure we all (eg, you, @zyga, @niemeyer and myself) all agree with the approach. As per the PR description:
I'll try to summarize plans AIUI: '1' is intended to support future work where snapd from the core snap detects serial ports and exposes them as implicit slots. This detection would include detecting unpluggable serial ports like /dev/ttyS0 on boot as well as processing udev notifications of hotplug/hotunplug events that match the '2' is intended to support the need today for assigning a particular device with a specific vendor and product id to a snap. The snap author does specify the vendor and product id but does not need to express the device path in the yaml and the user does not have to express the device path (or vendor and product id) with 'snap connect'. Neither '1' nor '2' addresses how gadget snaps are supposed to weigh in. I'm trying to understand where we are going to make sure that we implement this interface in a manner that is consistent with the final design. I suspect that might be difficult since this is not all fleshed out yet but let me propose a straw man that I think unblocks the immediate requirement (what prompted this PR) that is consistent with the future. = Straw man =
Assuming a gadget with /dev/ttyS0, /dev/ttyS1, hard-wired /dev/ttyUSB0 (vendor=abcd, product=0123) and hotpluggable /dev/ttyUSB1 (vendor=edff, product=4567) that is unplugged, we have implicit dynamic slots from core that on boot (but before the gadget aliases are applied) that are the equivalent of:
Such that:
Then the gadget snap applies its aliases and the merged core+gadget implicit dynamic slots are the equivalent of:
Such that:
Then at some later point, the user plugs in the addon usb serial port and the new merged dynamic slot equivalent yaml is (omitting snap interfaces output):
Finally, apps can plugs like so:
Now, understanding that dynamic detection is not here yet, how can we meet the requirements of '2' while being forward thinking? Rather than add vendor and product attributes, simply Several issues with the above:
@zyga and @niemeyer - I hope you don't mind the long comment. I tried to tie together various pieces based on my understanding. If you have already worked all this out before, please show me the specification so I might understand how this PR fits in, otherwise, this comment can be a springboard for discussion. :) |
|
@jdstrand We had a a very long discussion on this already and agreed that this is for now the way forward and wouldn't break a future design where snapd would expose dynamic slots. In detail what we want to allow for now and agreed on:
This can easily stay for future design changes as we rely on the implicit If all agree I would like to offload the discussion for the whole dynamic slot thing and finish the implementation to archive the requirements listed above. We have a very tight timeline and I would us to get the first version described above done. As outlined there shouldn't be any problems with a future extension of the interface to handle dynamic slots. |
|
Made the policy strings constants and fixed the comment with errors in it. @jdstrand - Quite a few of your comments are based on the premise the path attribute should only be slot side. That is how I initially developed the interface, but after the first review from @morphis, I modified the code to require a matching path attribute on both plug and slot for connection to be made. I'm happy to wait for the thoughts of the others tagged in the last review and can changed if required. However, I think that the implementation as is meets what we set out to achieve for the next iteration of this interface given forthcoming milestones. |
|
@jocave Right that was my idea there, as that way we could also specify a slot for now on the gadget snap rather than using the |
jocave
added some commits
Aug 10, 2016
niemeyer
added
Blocked
Critical
labels
Aug 24, 2016
For the record, I was part of the initial conversation a couple of months back, when we still had hardcoded paths, but wasn't part of those follow up discussions and agreements. A lot here is completely new to snapd and to me, and some of those ideas are problematic as we discussed online last week.
How can we possibly have a path on the plug side? We'd be asking people developing snaps that require a serial port to know where the serial port will live on the target device! The idea of hardcoding vendor-id and product-id on a serial port is also twisting my mind a little bit. There are many providers of generic serial port chips. Using such a hardcoded id pair while purporting it to be hot-pluggable seems counter-intuitive. It means although one may hot-plug, it needs to be that one serial port chip or it won't work. Finally, as an implementation detail, the trick of counting the number of attributes to see if a specific attribute is present or not is an approach that breaks forwards compatibility badly. Imagine what happens with old devices when we extend the declaration with one more attribute. That said, this is just a hint for future cases. I think we want to review those descriptions anyway. We need a call to figure those details out. |
|
We need a new approach here. I'll close this and other PRs that are using the same methodology. Let's please discuss the right approach and recreate a clean PR when ready for review. |
jocave commentedAug 11, 2016
Now allow serial-ports to be used in two ways: