Access Linux char driver from snap app

Hi,

I have integrated custom char driver with kernel snap and able to load driver using insmod. Now I am trying access char driver from snap application.

My snap app has below code.

int fd = open("/dev/test_driver0", O_RDONLY);
read(fd,buf,sizeof(buf)); close(fd);

This code works fine in devmode. But in strict mode, open function fails with EPERM (Operation not permitted). Tried system-files interface to allow read access to /dev/test_driver0. But error still exists.
Which snap interface to be used to solve this error?

Thanks and Regards,

I further did debugging of this issue.

  • Checked with snappy-debug: snappy debug is not giving any violation.
  • Added “/dev/ r,**” in apparmor profile policy file. But still snap application not able to access /dev/test_driver. fails with errno EPERM.
  • Used cat command within snap to access /dev/test_driver0 (cat /dev/test_driver0). This also fails with same error (EPERM).
  • Switched to sudo user mode and tried. Still same error exists.
  • Access(read and write) permission (0666) provided to /dev/test_driver0. Still same error exists.

Do I need to define device node details in gadget snap to allow access within snap?

Tried with uio (https://snapcraft.io/docs/the-uio-interface) snap interface.

  • Updated char driver implementation to create the device node as /dev/uio0.
  • Added uio slot information in gadget snap and added plug in snap application.

But still app fails with EPERM (Operation not permitted) error during open function call.

Hi All,

I observed that kernel-module-control(used for allowing insmod, rmmod within snap) has some influence on uio snap interface. If same application uses both interfaces, then application fails with EPERM error while trying to access uio interface.

If I eliminate the kernel-module-control dependency, then application is able to access /dev/uio0 interface.
For allowing access to device node of custom char driver from snap application, I did following changes.

  • Updated char driver implementation to create the device node as /dev/uio0.
  • Added uio slot information in gadget snap and added plug in snap application
  • Used different snap application to load char driver using kernel-module-control interface and creating the symbolic link file (ln -s /dev/ui0 /dev/test_driver0). system-file interface to allow creation of symbolic link file in /dev directory.

With these changes, snap application is able to access character driver device node.

Another simple alternative method I found is make use of greengrass-support interface.
I have gone through Allowing interfaces to disable device cgroup/udev.

Is it okay to use greengrass-support interface for my requirement?

When you use the uio interface, you are in effect enabling snapd to enforce the device cgroup for your snap, which is what is causing the EPERM message you see. You need to have your device added to the snap’s device cgroup.

We are in the process of developing an interface like system-files but meant for specifically device nodes in /dev which will also have the necessary backend code inside snapd to setup the device cgroup to access the device in addition to the AppArmor rules. system-files by itself is insufficient because it does not know anything about the device cgroup, and so the device cgroup is not setup to allow access to the device hence your EPERM message.

No, the greengrass-support interface is meant for the greengrass snap specifically.

@ijohnson,

Thanks for your detailed reply.

I hope this is difficult without snapd customization. If I use uio interface, uio supports udev tagging so that device nodes are available to snap application when device cgroup is in effect.

As greengrass-support interface usage is not recommended, I will continue with uio and system-files interfaces.

As I stated before, there is a conflict when I add both kernel-module-control and uio interface plugs to same snap command. Below udev tagging in udev rule added by kernel-module-control is causing the conflict.

KERNEL==mem TAG+=“snap.test-app.test-app”

Is your device a uio device? If so then perhaps we just need to expand the uio interface to handle your new device node in the AppArmor

Driver not using UIO standard framework; User-space application controls the device node for read and write operation. character device driver exposes read and write functions to user-space and owns the responsibility to communicate with secured non-volatile storage.

Hmm okay, yeah I think our plan for a custom-device interface will fit your needs here, I will provide an update here for you when there is something to test hopefully in the next few weeks we will have that work done, it is high on our priority list for other reasons

1 Like

@ijohnson,

Updated to custom-device interface and feature (write and read to char driver from snap) was working as expected till snapd 2.55.3.
But not working since I updated the snapd version to 2.55.5. Getting EPERM error.

I see some modification in custom-device plug in snapd 2.55.4 release (i/b/custom_device: fix generation of udev rules). Do I need to perform any modification in slot/plug declaration?

Gadget snap slot declaration:

slots:
  dev-node:
interface: custom-device  
     devices:
          - /dev/test/test_driver[0-2]

Plugs declaration

plugs:
- custom-device

Hi,

Below are current observation -

Current custom-device plug adding below udev rule which is not working since snapd 2.55.4. KERNEL==“test/test_driver0”, TAG+=“snap_ test-app.test-app”

Below udev rules allows dev node access from snap -

KERNEL=="test_driver0", TAG+="snap_ test-app.test-app"
KERNEL=="test_driver0", SUBSYSTEM="test" TAG+="snap_ test-app.test-app"

Option to achieve updated udev rule using custom-device plug with required apparmor permission.

Option 1: Works. But does not looks like perfect solution.

slots:
  dev-node:
     interface: custom-device  
     devices:
          - /dev/test/test_driver[0-2]
          - /dev/test_driver[0-2]

Option 2:

slots:
  dev-node:
     interface: custom-device  
     devices:
          - /dev/test/test_driver[0-2]
     udev-tagging:
         - kernel: test_driver[0-2]
           subsystem: test
          

Not working. Section of code in validateUDevTaggingRule function of custom_device.go (https://github.com/snapcore/snapd/blob/master/interfaces/builtin/custom_device.go#L160) throws below error.

if !strutil.ListContains(devices, "/dev/"+deviceName) {
err = fmt.Errorf(`%q does not match a specified device`, deviceName)
 }

What is usage this check added in validate function?