/dev/mem access denied on raspberry pi

2019-07-05 08:25发布

问题:

I am working with my Raspberry Pi and I am writing a cgi python script that creates a webpage to control my gpio out pins. My script crashes when I try to import RPi.GPIO as GPIO. This is the error that I am getting:

File "./coffee.py", line 7, in <module>
    import RPi.GPIO as GPIO
RuntimeError: No access to /dev/mem.  Try running as root!

My code works perfectly when I use sudo to run my script, but when I am running from a URL from my apache2 server it says that I do not have access to /dev/mem. I have already tried editing visudo and that did not work. This is what my visudo file looks like:

#includedir /etc/sudoers.d
pi ALL=(ALL) NOPASSWD: ALL
www-data ALL=(root) NOPASSWD: /usr/bin/python3 /usr/lib/cgi-bin/coffee.py *
apache2 ALL = (root) NOPASSWD: /usr/lib/cgi-bin/coffee.py

There any way that I can run my script as root from a URL call? Can anyone tell me what I am doing wrong?

回答1:

I found that adding www-data to the gpio user group worked fine:

sudo usermod -aG gpio www-data

You can also add www-data to the memory user group:

sudo usermod -aG kmem www-data

As mentioned, it is a bad idea, but for me it was necessary.



回答2:

Your problem is that the script is not executed as root. It is executed as the user that apache runs as.

Your apache process runs as a specific user, probably www-data. You could change the user that apache runs as. You should be able to find this in /etc/apache2/envvars:

# Since there is no sane way to get the parsed apache2 config in scripts, some
# settings are defined via environment variables and then used in apache2ctl,
# /etc/init.d/apache2, /etc/logrotate.d/apache2, etc.
export APACHE_RUN_USER=www-data
export APACHE_RUN_GROUP=www-data

If you change that to root you should have access. Normally this would be a terrible security hole, but you are doing direct memory access already. Be very careful!

If you are uncomfortable with this then you need to update your command so it is executed as root (this is a good way, but it requires you understand what you are doing!). You can do this by altering the way you call it, or by wrapping the call in a script which itself changes the user, or by using setuid (this is very similar to the suEXEC approach mentioned earlier). Wrapping it in a script seems the best way to me, as that should allow your entry in sudoers to correctly apply the privilieges for only that command, and it doesn't require you to understand the full implications of setuid approaches.