My son is implementing a server on a raspberry pi that allows control of the gpio pins via a network connection. He has discovered a very strange bug.

First, the OS being used is raspbian, a version of Debian linux. He is using the standard system file to control the GPIO ports.

We start with a GPIO pin, e.g. pin 17, in a non-exported state. For example,

echo "17" > /sys/class/gpio/unexport

Now, if the server is asked to turn on pin 17, it does the following:

  1. opens the /sys/class/gpio/export, writes "17" to it, and closes the export file
  2. open the /sys/class/gpio/gpio17/direction file for read, examines it to see if it is set as input or output. closes the file. Then, if necessary, re-opens the file for write and writes "out" to the file, to set the pin as an output pin, and closes the direction file.

At this point, we should be able to open /sys/class/gpio/gpio17/value for write, and write a "1" to it.

However, the permissions on the /sys/class/gpio/gpio17/value file exists but the group permissions is read-only. If we put in a "sleep" in order to wait for a fraction of a second, the perms change so the group perm has write permissions.

I would have expected that the OS should not return from the write to the direction file until it had set the perms on the value file correctly.

Anyone know why this is happening? Seems like a bug. Anyone know where I should report this (with more detail...)?

  • Looking at the kernel driver source code (github.com/raspberrypi/linux/blob/rpi-3.12.y/drivers/gpio/…) I can only see the permissions on the value file being set to 0644. Are you sure they do change, or are you going by an error returned when trying to write? – harmic Sep 8 '14 at 6:05
  • I originally posted this question here: stackoverflow.com/questions/25695973/…. I have posted some source there. In the source, you see that we stat the files and print out the perms. 0644 that you give is user r/w, group read, and other read. That more or less matches what I remember, but this would not allow writing to ../direction or ../value. At some point (within 100ms), the group permissions (at the least) change and write perms are added. I will get the exact perm integer - I just don't have it here handy. – David I. McIntosh Sep 9 '14 at 20:51
  • For the files, user/owner is root, group is gpio. The process accessing them is a member of the gpio group, and so eventually gets write permissions by virtue of the group write bit being set, eventually. – David I. McIntosh Sep 10 '14 at 2:01
  • I can confirm this. I just posted this question: raspberrypi.stackexchange.com/questions/32237/… Adding a 'sleep(2);' strategically "solves" the problem. – nsayer Jun 5 '15 at 4:12

Note that a normal user by default on Raspbian cannot do this:

echo "17" > /sys/class/gpio/unexport

Or, conversely, use export, even if they are a member of the gpio group. This points to the fact that as the OP admits in another thread, there might have been some tweaks made, possibly by other software that was installed. However, it is probably still a common issue.

The answer to this question is in the cross-post on Stack Overflow. Note although it refers to the "systemd udev" service (applicable on pidora, Raspbian jessie, etc.) there is a parallel service on Raspbian wheezy (see /etc/init.d/udev):

[Direct cut n' paste from the above link.]

From a kernel perspective, the 'value' files for each GPIO pin that has been exported are created with mode 0644 and ownership root:root. The kernel does not do anything to change this when you write to the 'direction' file.

The behavior you are describing is due to the operation of the systemd udev service. This service listens for events from the kernel about changes in device state, and applies rules accordingly.

When I tested on my own Pi, I did not experience the behavior you described - the gpio files in /sys are all owned by root:root and have mode 0644, and did not change regardless of direction. However I am running Pidora, and I could not find any udev rules in my system relating to this. I am assuming that Raspbian (or maybe some package you have added to your system) has added such rules.

I did find this thread where some suggested rules are mentioned. In particular this rule which would have the effect you describe:

SUBSYSTEM=="gpio*", PROGRAM="/bin/sh -c 'chown -R root:gpio /sys/class/gpio; chmod -R 770 /sys/class/gpio; chown -R root:gpio /sys/devices/virtual/gpio; chmod -R 770 /sys/devices/virtual/gpio'"

You can search in /lib/udev/rules.d, /usr/lib/udev/rules.d and /etc/udev/rules.d for any files containing the text 'gpio' to confirm if you have such rules. By the way, I would be surprised if the change was triggered by changing direction on the pin, more likely by the action of exporting the pin to userspace.

The reason you need to sleep for a while after exporting the device is that until your process sleeps, the systemd service may not get a chance to run and action the rules.

The reason it is done like this, rather than just having the kernel take care of it, is to push policy implementation to userspace in order to provide maximum flexibility without overly complicating the kernel itself.

See: systemd-udevd.service man page and udev man page.

[End cut n' paste]

On the last Raspbian image I checked, the relevent udev rules can be found with:

grep gpio /lib/udev/rules.d/*

Again, this still doesn't affect restrictions on export or unexport. This is probably a good precaution -- it means it takes privileges to export a pin, but once done, anyone in the gpio group (which should include user pi) can use it.

  • Awesome answer and summary. I am just switching some of my c from legacy /dev/mem to sysfs and have been confused by the root:gpio export but root:root value permissions. Taking a look at my rules.d folder I had two files; 60-python-pifacecommon.rules and 60-python3-pifacecommon.rules that were changing permissions for the export. I must have installed piface at some point and forgotten about it. Now I can just produce my own rule and install it while elevated to allow my application run without root. – hoss Dec 10 '15 at 13:37

Not the answer you're looking for? Browse other questions tagged or ask your own question.