Make sure gpio exported before apparmor setup #2

Closed
wants to merge 1 commit into
from
Jump to file or symbol
Failed to load files and symbols.
+8 −9
Split
@@ -104,21 +104,21 @@ func (iface *GpioInterface) ConnectedPlugSnippet(plug *interfaces.Plug, slot *in
// PermanentSlotSnippet - no slot snippets provided
func (iface *GpioInterface) PermanentSlotSnippet(slot *interfaces.Slot, securitySystem interfaces.SecuritySystem) ([]byte, error) {
- return nil, nil
-}
-
-// ConnectedSlotSnippet - no slot snippets provided
-func (iface *GpioInterface) ConnectedSlotSnippet(plug *interfaces.Plug, slot *interfaces.Slot, securitySystem interfaces.SecuritySystem) ([]byte, error) {
switch securitySystem {
@jdstrand

jdstrand Oct 5, 2016

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.

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"])
@jdstrand

jdstrand Oct 5, 2016

Why was ACTION=="add" removed?

@jocave

jocave Oct 6, 2016

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.

return []byte(snippet), nil
}
return nil, nil
}
+// ConnectedSlotSnippet - no slot snippets provided
+func (iface *GpioInterface) ConnectedSlotSnippet(plug *interfaces.Plug, slot *interfaces.Slot, securitySystem interfaces.SecuritySystem) ([]byte, error) {
+ return nil, nil
+}
+
// AutoConnect returns whether interface should be auto-connected by default
func (iface *GpioInterface) AutoConnect() bool {
return false
@@ -135,9 +135,8 @@ func (s *GpioInterfaceSuite) TestSanitizePlug(c *C) {
func (s *GpioInterfaceSuite) TestUsedSnippet(c *C) {
slot := s.gadgetGpioSlot
- plug := s.gadgetPlug
- content, err := s.iface.ConnectedSlotSnippet(plug, slot, interfaces.SecurityUDev)
+ content, err := s.iface.PermanentSlotSnippet(slot, interfaces.SecurityUDev)
c.Assert(err, IsNil)
- expected := `ACTION=="add", SUBSYSTEM=="gpio", RUN+="/bin/echo 100 > /syc/class/gpio/export"`
+ expected := `SUBSYSTEM=="gpio", RUN+="/bin/sh -c '/bin/echo 100 > /sys/class/gpio/export'"`
c.Assert(string(content), Equals, expected)
}