GPIO and permissions

We have a Revision C board running debian, and wish to use a couple of the GPIO channels from within the (C++) software we are developing. This requires writing to the “file” /sys/class/gpio/export, but this requires root permission. In bash I can just “sudo su”, but this is surely not going to work from C++?

Presumably if I logged in as root and ran my code, the permissions would be correct. However the board boots to the desktop with “debian” as the default user. Can this be changed to root and how?

You are not really asking the right question (its ok you are new to this). However the problem you have really has nothing to do with the Beaglebone Black - it is really a Linux issue and any solution to it would be common to any Linux system.

Try googling something like “linux auto run program on boot as root” and you will find a lot of help.

Or you can google the setuid bit. This would allow your application to run as root without having to be logged in as root.

Thanks Walker. I have looked at setuid and it appears to be the best way to go. I don’t quite get it though. My code is built by netbeans, so I have to chmod +s the exe, then call setuid( x ) in the code? What is x?

Why don’t you use libpruio to control the GPIOs? You’ll have no sysfs file access:

  • faster access,

  • better control over the configuration and

  • you can set the state as normal user.
    (And further features like PWM, QEP, ADC, …)

Interesting: looks a bit of a pain to install, mind!

I guess I should be more careful when posting off-the-cuff comments. :slight_smile: You need to be careful using the setuid bit because you can create a program that is exploitable. If you’re just hacking around on your own BBB then it’s fine for getting things to work. But if you want to distribute it to anyone then you probably need to think more about managing privileged access.

I don’t think you’ll need the setuid() call in the code providing you are okay with having your process always run as root.

If you are looking to access the gpio pins at the beginning of your program and then drop the root privileges then you can use setuid to become a non-privileged user. The parameter for setuid is the uid of the user you want to become. However, if you use setuid to drop root privileges then you cannot setuid back to root later.

If you want to periodically use admin privileges to access the gpio pins while reverting to a non-privileged user during normal runtime then look into the seteuid or setreuid calls.

TJF’s idea about using libpruio is a good one also.

Yeah, just send me your advanced installation instructions proposal.

Or ask RCN to implement libpruio in the next distros …

All of these suggestions are terrible. The right question to ask is “How do I give a non-root user permission to set GPIOs?” If this can’t be done, then this distribution of Linux is broken.

I can add my user to the “kmem” group, then change the group ownership of /sys/class/gpio/export to kmem, the chmod g+w, and then my user can export the GPIOs. But when they appear, “direction” is still owned root:root perms 644, so I can’t do anything with the GPIO I just created, even though, as a member of kmem, I could do the equivalent memory-mapped IO.

It is not acceptable to require a program to run as root. I not quite Linux-savvy enough to fix this.

The Linux way to fix this is with udev.

1) define a user group that should be able to access gpio, such as "gpio"
2) add a udev rule that runs a script on the necessary udev events. Here's my
   ubuntu rule (your distro might configure udev differently; good luck with that):

peter@black:~$ cat /etc/udev/rules.d/50-gpio.rules
ACTION!="add", GOTO="gpio_end"

KERNEL=="gpio[0-9]*", SUBSYSTEM=="gpio", ACTION=="add", PROGRAM="/lib/udev/gpio_pin %p"
ENV{OF_NAME}=="gpio", SUBSYSTEM=="platform", ACTION=="add", PROGRAM="/lib/udev/gpio_pin enable"

LABEL="gpio_end"

3) udev has the appropriate permissions to run the script (below) which
   changes the group/permissions:

peter@black:~$ cat /lib/udev/gpio_pin
#!/bin/sh

PATH='/sbin:/bin'
basedir="/sys/class/gpio"
devpath=$1

if [ "$1" = "enable" ] ; then
    for f in export unexport ; do
        chmod g+w $basedir/$f
        chown :gpio $basedir/$f
    done
else
    for f in active_low direction edge value ; do
        chmod g+w /sys${devpath}/$f
        chown :gpio /sys${devpath}/$f
    done
fi
exit 0

** NOTE **
Naturally there is a small delay between when the pin sysfs
inode is added and when the permissions have been changed, but
it's relatively simple to use a short timeout/delay loop when
opening a just-exported gpio pin.

** NOTE(2) **
When a user group is added, the user must re-login for the group
to become effective in their session.

** NOTE (3) **
udev can be triggered to re-play events after new rules are added
but it can be difficult to do that right, so it's easier just
to reboot.

Regards,
Peter Hurley