Use GPIO as non-root user?

I noticed that the Raspberry Pi kernel adopted /dev/gpiomem to provide a way for non-root users to access GPIO:

Add /dev/gpiomem device for rootless user GPIO access:
https://github.com/raspberrypi/linux/pull/1112

Is there anything comparable for BeagleBone? Anyone have ideas/plans?

I started thinking about this after seeing this post on the Adafruit forum:

Trying to use Adafruit_BBIO library and run as non-root user

https://forums.adafruit.com/viewtopic.php?f=49&t=89338&p=450036#p450036

thanks,
drew

The poor man’s way is to make the executable file be owned by root, and then set the S bit so it takes execute permissions from the file owner.
You do this with :

sudo chown root:root filename
sudo chmod u+s filename

This requires a valid root user to be set up.

Jon

The “safest” way I can think of is put a very specific line in the sudoers file ( via visudo ). What this does, is allow you to issue a command, using sudo, potentially without using a passwd. So for example:

sudo sh -c "echo '1' > /sys/class/gpio/gpio67/value"

The above  can be made to run without using a passwd. So what this __*is*__ is a way to allow a very specific command to be run
as root, without using a passwd. What this __*is not*__ is a way to secure somethign similar on a multi user system. 

So this method does have it's perks, e.g. allowing a very specific command, say read a GPIO value, that is not really a security
risk, while the rest of the GPIO bank could represent an issue.

I do believe one can achieve something very similar to what I suggest above using udev rules, but I'm honestly not all that well 
versed with udev. . . 

This is why Unix/Linux has groups. Do the following:

ls -la /dev

You will see groups such as i2c, dialout, tty, etc. If you want to access these devices from a regular user account, add your user to those groups. If you need to use a device that has root:root, then change the group and add your user account to that group.

Regards,
John

So, here is an example of what I mean above. http://unix.stackexchange.com/questions/18830/how-to-run-a-specific-program-as-root-without-a-password-prompt

3rd post has a decent example.

This is why Unix/Linux has groups. Do the following:

Using groups is not necessarily the safest way to go about things John. But I do agree it is a possibility. The only real contention that I have with using groups. Is . . . my sudo example can be used on a very specific command, only allowing that very specific command, where all others, no matter how similar, if not exactly the same will not run. My example if not really a good illustration of this but imagine this:

echo '1' > /sys/class/gpio/gpio67/value /* allowed */
echo '0' > /sys/class/gpio/gpio67/value /* not allowed */

Obviously the above is very contrived, but there can be a need for something similar.

Also, when using groups, you do not really want to change groups, but add groups. e.g. you do not want to change group root to wheel ( or whatever group you want ) for a specific item. Since the system likely needs root to have access to given items for various reasons. You also want to be as specific as possible when creating / using groups. As using groups, wrongly, is a perfect way to add a huge gaping security hole into a system.

Drew, FYI, that is just a character device based on /dev/mem/ which could very easily be done for the Beaglebones as well. In fact, porting their code would be potentially as simple as redefining pin constants in code, plus adding an additional 60+ for beaglebones :wink:

Err, why?

Groups are frequently used to restrict access to resources. Android exploits groups for permissions and to sandbox applications. And the kernel enforces access.

Using sudo seems much less secure as it exposes the application to being exploited for security flaws. And since the application is running as root, it has access to everything.

But maybe I'm missing something?

ba

Using sudo seems much less secure as it exposes the application to being exploited for security flaws. And since the application is running as root, it has access to everything.

So, we have a device on a system that can potentially cause physical damage to external hardware when something like a wrong GPIO state is toggled, or such. How would sudo be less secure in this context? In fact under certain conditions it would be less safe using groups.

Also, “root has access to everything” is wrong. Reread what I’ve written above about running specific commands through sudo.

My comments are really to do with what I perceive as best practices on how one would approach building systems that are “security conscious”. Of course, “convenience” may direct us in different directions during development. I am not sure what you are trying to imply by “safe” as in protecting the GPIOs from misuse. I don’t actually see any way to accomplish that. What I do think one can do is to be aware of security considerations and not unnecessarily present an attack surface that can compromise the entire system.

Using sudo seems much less secure as it exposes the application to being exploited for security flaws. And since the application is running as root, it has access to everything.

So, we have a device on a system that can potentially cause physical damage to external hardware when something like a wrong GPIO state is toggled, or such. How would sudo be less secure in this context?

It wouldn’t. And that is not my point. I am not talking about how to protect the GPIOs from “bad behaved” programs that are “trusted” as implied by the fact that they are running as a normal user in the group that has access to those GPIOs. If an application is trusted (is a member of the appropriate group or for that matter can sudo), it is a hopeless task to protect the GPIOs from misuse. What I am trying to point out is that running an app as “root” (sudo, set uid, whatever) exposes a security attack vector…a vector that has access to all system resources. I would claim that it is an unnecessary exposure…from a security point of view. YMMV when it comes to “convenience”.

In fact under certain conditions it would be less safe using groups.

How would an application running at a non-root level using groups to access protected resources be less “safe” than an application running as root using sudo?

Also, “root has access to everything” is wrong. Reread what I’ve written above about running specific commands through sudo.

Errr, an application running as root, by definition, has access to all system resources. The fact that you are limiting just a single application/user to run sudo doesn’t limit the attack surface for that application. If your root application is compromised in some way, then the entire system can be compromised. Running as a normal user does not present the same attack surface…its much smaller and sandboxed by the kernel. Running as root affords no protection enforcement by the kernel.

ba

Brian, This is a great summation of the issue! Mike

Hi Drew!

This is John, the guy with the question Drew to above on the Adafruit board. (Thanks Drew for starting this conversation here.)

The problem is, this is part of a commercial application. My code will be reading and writing to the GPIOs and doing various things, communicating data to remote systems… I anticipate adding a fair bit of complexity. I’d hate to make a bug that blew something important away or something like that. I am generally leery of unnecessary privilege escalation.

So I could

  • sudo my entire application, which would be the same as running as root;
  • partition my application and have it invoke the code that interfaces directly to the GPIOs as sudo in some way (via shell?);
  • go by way of the PRUs;
  • change permissions;
  • some other way.

I did have partial success changing the permissions on relevant files, ala

https://github.com/cnobile2012/RobotControl/tree/master/contrib

which uses udev to set up permissions (not that I understand udev either.)

I call my success partial because I can get a test LED to turn on, but I can’t get it to flash using PWM.

Any ideas why that would be?

I call my success partial because I can get a test LED to turn on, but I can’t get it to flash using PWM.

Any ideas why that would be?

No . . . Because you’ve given no pertinent details. We’d need to know a few things, but kernel version used, method used for attempting to control said PWM, code, etc. All will help. So, if you want help, help us, help you.

(env) app@beaglebone:/opt/reactor_controller/src$ uname -a
Linux beaglebone 3.8.13-bone70 #1 SMP Fri Jan 23 02:15:42 UTC 2015 armv7l GNU/Linux
(env) app@beaglebone:/opt/reactor_controller/src$ cat /etc/dogtag
BeagleBoard.org Debian Image 2015-03-01

(env) app@beaglebone:/opt/reactor_controller/src$ python
Python 2.7.3 (default, Mar 14 2014, 17:55:54)
[GCC 4.6.3] on linux2
Type “help”, “copyright”, “credits” or “license” for more information.

import Adafruit_BBIO.PWM as PWM
PWM.start(‘P8_13’, 33, 4) # this turns the light on steady
PWM.stop(‘P8_13’) # this turns it off
PWM.cleanup()

I am using the latest Adafruit_BBIO library, source available at

https://github.com/adafruit/adafruit-beaglebone-io-python

Anything else you need?

and when I do the above as root it blinks as it should.

OK, so assuming your issue doing the above - only works as root, and you’d like it to work as a regular user too . . .

You need to figure out how the Adafruit_BBIO library accesses the pins, and go from there. Does it use sysfs, or /dev/mem/ ?

If the library uses sysfs. Then I would think you’d need to create a udev rule to add a group to your desired asset. In order for the pin path to have the appropriate permissions every time that asset is enabled through pinctrl. Which in your case I’d assume every reboot only.

A bit of advice however . . . if this library uses /dev/mem/ to access the pins . . . DO NOT adjust permissions on /dev/mem/. As that could give anyone in that group direct access to any physical address on the CPU. In short. they could pretty much do anything they’d want.

If you’re confident you can control access to the board, my concern above is less of a problem. As I tend to look at security issues of this nature as if one is already compromised at a regular user level. If the board is rooted . . . well then . . .heh it’s moot.

It seems as though their using sysfs: https://github.com/adafruit/adafruit-beaglebone-io-python/blob/master/source/c_pwm.c#L68-L77

Yes, they are. And I think my partially-successful solution is udev based. I copied this rule from the robot project I linked to before:

Install in: /etc/udev/rules.d/

from cnobile2012@ github

A bunch of code for a single GPIO pin (in order to get slow sysfs access). Keep in mind that you’ve to maintain all that code for each pin you use in your project.

For libpruio it is

`

chgrp pruio /dev/uio5
chmod g+rw /dev/uio5

`

and you’re done for all GPIO, CAP and PWM pins (and you’ll get much faster direct access).

BR