Use GPIO as non-root user?

2,127 views
Skip to first unread message

Drew Fustini

unread,
Feb 5, 2016, 5:13:34 PM2/5/16
to BeagleBoard
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:

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


thanks,
drew

jmelson

unread,
Feb 5, 2016, 5:35:12 PM2/5/16
to BeagleBoard


On Friday, February 5, 2016 at 4:13:34 PM UTC-6, Drew Fustini wrote:
I noticed that the Raspberry Pi kernel adopted /dev/gpiomem to provide a way for non-root users to access GPIO:


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

William Hermans

unread,
Feb 5, 2016, 6:26:31 PM2/5/16
to beagl...@googlegroups.com
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. . .

--
For more options, visit http://beagleboard.org/discuss
---
You received this message because you are subscribed to the Google Groups "BeagleBoard" group.
To unsubscribe from this group and stop receiving emails from it, send an email to beagleboard...@googlegroups.com.
For more options, visit https://groups.google.com/d/optout.

John Syne

unread,
Feb 5, 2016, 6:34:35 PM2/5/16
to beagl...@googlegroups.com
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




William Hermans

unread,
Feb 5, 2016, 6:34:51 PM2/5/16
to beagl...@googlegroups.com
3rd post has a decent example.

William Hermans

unread,
Feb 5, 2016, 6:48:04 PM2/5/16
to beagl...@googlegroups.com
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.

William Hermans

unread,
Feb 5, 2016, 7:28:30 PM2/5/16
to beagl...@googlegroups.com
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 ;)

Brian Anderson

unread,
Feb 5, 2016, 8:05:38 PM2/5/16
to BeagleBoard
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

William Hermans

unread,
Feb 5, 2016, 8:22:18 PM2/5/16
to beagl...@googlegroups.com
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.

Brian Anderson

unread,
Feb 6, 2016, 12:51:14 AM2/6/16
to BeagleBoard

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
 

Mike

unread,
Feb 7, 2016, 11:00:01 AM2/7/16
to beagl...@googlegroups.com
On 02/06/2016 12:51 AM, Brian Anderson wrote:

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
 

On Fri, Feb 5, 2016 at 6:05 PM, Brian Anderson <b...@nwlink.com> wrote:
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

Brian,

This is a great summation of the issue!

Mike

TJF

unread,
Feb 8, 2016, 12:44:17 PM2/8/16
to BeagleBoard
Hi Drew!

Am Freitag, 5. Februar 2016 23:13:34 UTC+1 schrieb Drew Fustini:
... to provide a way for non-root users to access GPIO:
...
Anyone have ideas/plans?

You could use libpruio to access GPIO (and ADC, CAP, PWM). It provides much faster access than sysfs. Root privileges are only necessary to configure pins (ie. pullup / pulldown), but not to set their state.

BR

jo...@forelight.com

unread,
Feb 8, 2016, 3:06:07 PM2/8/16
to BeagleBoard, belly...@gmail.com
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


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?

William Hermans

unread,
Feb 8, 2016, 5:39:48 PM2/8/16
to beagl...@googlegroups.com
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.

--

John Stoner

unread,
Feb 8, 2016, 8:06:17 PM2/8/16
to beagl...@googlegroups.com
(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 


Anything else you need?

You received this message because you are subscribed to a topic in the Google Groups "BeagleBoard" group.
To unsubscribe from this topic, visit https://groups.google.com/d/topic/beagleboard/Ca7QDUwv72g/unsubscribe.
To unsubscribe from this group and all its topics, send an email to beagleboard...@googlegroups.com.

John Stoner

unread,
Feb 8, 2016, 8:06:21 PM2/8/16
to beagl...@googlegroups.com
and when I do the above as root it blinks as it should.

William Hermans

unread,
Feb 8, 2016, 8:24:12 PM2/8/16
to beagl...@googlegroups.com
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.

William Hermans

unread,
Feb 8, 2016, 8:45:23 PM2/8/16
to beagl...@googlegroups.com

John Stoner

unread,
Feb 9, 2016, 11:47:25 AM2/9/16
to beagl...@googlegroups.com
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

KERNEL=="gpio*", SUBSYSTEM=="gpio", ACTION=="add", PROGRAM="/bin/fix_udev_gpio.sh"

and this script, with modifications (marked with  '# added this line')

#!/bin/bash
#
# This file will change the user, group and permissions in both the
# /sys/devices/virtual/gpio and /sys/class/gpio path directories.
#
# DO NOT change the order of the commands below, they are optimized so that
# commonly created files and directories are changed first.
#

chown -R debian:gpio /sys/devices/virtual/gpio
chown -R debian:gpio /sys/class/gpio
chown -R debian:gpio /sys/devices/bone_capemgr.* # added this line
chown -R debian:gpio /sys/devices/ocp.* # added this line

find /sys/devices/virtual/gpio -type d -exec chmod 2775 {} \;
find /sys/devices/virtual/gpio -name "direction" -exec chmod 0660 {} \;
find /sys/devices/virtual/gpio -name "edge" -exec chmod 0660 {} \;
find /sys/devices/virtual/gpio -name "value" -exec chmod 0660 {} \;

find /sys/devices/virtual/gpio -name "active_low" -exec chmod 0660 {} \;
chmod 0220 /sys/class/gpio/export
chmod 0220 /sys/class/gpio/unexport
chmod 0664 /sys/devices/bone_capemgr.*/slots # added this line
chmod -R 0770 /sys/devices/ocp.* # added this line
find /sys/devices/virtual/gpio -name "uevent" -exec chmod 0660 {} \;
find /sys/devices/virtual/gpio -name "autosuspend_delay_ms" -exec chmod 0660 {} \;
find /sys/devices/virtual/gpio -name "control" -exec chmod 0660 {} \;
 
Still seeing just a steady light, not PWM. Should be seeing four flashes a second with a 33% duty cycle.

TJF

unread,
Feb 9, 2016, 12:05:20 PM2/9/16
to BeagleBoard, jo...@forelight.com
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

John Stoner

unread,
Feb 9, 2016, 1:52:34 PM2/9/16
to TJF, BeagleBoard
So libpruio looks like it wraps calls to interface with the GPIOs via the PRU with Freebasic or C calls, yes? 

We are committed to building this application in a language that is

1. High level and
2. Prevalent in the job market--we need to be able to find people who know it reasonably well.

(also, developer cycles are a lot more expensive to us than processor cycles. Actually, performance is not a  high priority for us.)

Python fits pretty well. Freebasic does not. C does not either, but I guess I could use SWIG to generate an API for myself to use. That sounds doable, but it doesn't sound like less trouble to me, more like exchanging one difficulty for another.

You could add a SWIG interface file to libpruio so people could talk to it in whatever language they wanted. That would make it a lot more attractive to a lot more developers, myself included...

http://www.swig.org/

TJF

unread,
Feb 9, 2016, 4:51:17 PM2/9/16
to BeagleBoard, jeli.f...@gmail.com, jo...@forelight.com
libpruio is PRUSS assembler code to control the subsystems GPIO, ADC, PWM/CAP. An API is available to control that assembler part from host CPU (ARM), written in FreeBASIC. Also a C wrapper is shipped in the package.

When you say Python fits well, why do you think FreeBASIC doesn't? It combines a steep learning curve (like Python) with the advantages of a real compiler.

Some years ago I tried to use SWIG. From my point of view it's not flexible, not really well documented and much too complicated to use. Finally I wrote a similar tool (h_2_bi) from scratch, in order to meet my needs.

In April 2015 Benoit Clouet and me made a libpruio Python binding based on ctypes for his browser controlled tank project. Find the source code and additional information in this post.

Anyway, I just tried to share experiences from other libpruio users and myself in order to minimize your development costs. If you feel like replacing one difficulty by another, then I need not spend my time in posting here.

BR

ybea...@rehut.com

unread,
Feb 10, 2016, 6:02:56 PM2/10/16
to beagl...@googlegroups.com
You might want think more about this then the peep hole approach.

Rather then running things in userland and relying on user id isolation; a
better way is to write a kernel driver that exposes a very specific and
limited interface. GPIOs are directly toggling hardware which means there are
more then thing simple "privileges" -
- Can the pins be reconfigured to conflict (i.e. BBB is an Output and the
thing connected is an output) and is the hardware tolerant of that or will
things die?

- Is there anything bad that will happen if the pin floats (i.e. a normally
output pin is switched to an input)? Will it pickup noise and let things go
crazy?

Just merely changing permissions can leave a dangling problem.
> > *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.*
--
Hunyue Yau
http://www.hy-research.com/

William Hermans

unread,
Feb 10, 2016, 6:32:36 PM2/10/16
to beagl...@googlegroups.com
I've often given thought to running two processes in this context, and using inter process communications( shared memory seemed the most attractive to me ). How I envisioned this though, is that you have one process running as root, that is the main "supervisor" part of the application. Then a regular user application that makes requests via whatever shared memory mechanism that get used.

I think the main benefit of an application of this sort is that there is kind of a partition between privileged commands, and non privileged users. With the ability of having very fine grained control.

Anyway, I only bring this up because the last post kind of reminds me of what I mention above, and actually could be made to work as a "userland" driver. 

John Stoner

unread,
Feb 11, 2016, 1:49:49 PM2/11/16
to TJF, BeagleBoard
Thanks, I appreciate your efforts. Please read that with zero sarcasm. I've been there too, thinking I knew what would save someone time and effort and not realizing I was in a different situation.

I have a large application to build. I'm not sure how much of the complexity is going to be running on the BBBs I will use. I will probably have to hire a small-to-medium sized team over the next few years. I have to consider the technologies I will start with carefully. Python isn't perfect, but it's easy to find developers who have mastered it and can be productive quickly, and that's important.

peters...@googlemail.com

unread,
Aug 21, 2016, 2:03:30 PM8/21/16
to BeagleBoard
I tried that ls -la /dev and could not find anything like a GPIO group - my Nanopi M1 does not have a GPIO group and right now the only way I can run the MATRIX programs that come with the NanoPi - is by root- and every recommendation I have ever seen for Node-Red says NOT to run it as root - and Node-Red's EXEC function cannot accesss SUDO which suggests there is no way for Node-Red to access the GPIO on the M1. Ideas anyone?
Reply all
Reply to author
Forward
0 new messages