Automation Phat - permissions problem?


#1

Hi.

I have an automation Phat which is working well. When I click a button on a simple php webpage - hosted on a local Apache 2 server, I am trying to get 2 things to happen:

  1. A Prowl notification is sent to my phone (this works fine)
  2. The Automation Phat relay to be toggled (this doesn’t work and causes an entry in the apache error.log below)

How I set it up:

This php code fragment calls a shell script

<?php
        if(isset($_GET['trigger']) && $_GET['trigger'] == 1) {
                error_reporting(E_ALL);
                $command = escapeshellcmd('/var/www/html/GDRelayToggle.sh');
                $output = shell_exec($command);
                echo $output;
        }
?>

GDRelayToggle.sh consists very simply of:

#!/bin/bash
python  /var/www/html/GDRelayToggle.py > /dev/null

GDRelayToggle.py is a simple sequence:

#!/usr/bin/env python
import time
import automationhat
from subprocess import call
call('/home/pi/prowl.pl -apikeyfile=/home/pi/prowl_key.txt -event="G DOOR ALERT" -notification="GD Motor" -priority=2', shell=True)
automationhat.relay.one.toggle()
time.sleep(0.3)
automationhat.relay.one.toggle()

In /var/log/apache2/error.log

Traceback (most recent call last):
  File "/var/www/html/GDRelayToggle.py", line 6, in <module>
    automationhat.relay.one.toggle()
  File "/usr/lib/python2.7/dist-packages/automationhat/__init__.py", line 238, in toggle
    self.write(not self.read())
  File "/usr/lib/python2.7/dist-packages/automationhat/__init__.py", line 143, in read
    self.setup()
  File "/usr/lib/python2.7/dist-packages/automationhat/__init__.py", line 259, in setup
    setup()
  File "/usr/lib/python2.7/dist-packages/automationhat/__init__.py", line 354, in setup
    _ads1015 = ads1015(smbus.SMBus(1))
IOError: [Errno 13] Permission denied

I tried chmod and chown the 2 scripts as follows…

-rwxr-xr-x 1 root root   297 Jun 11 21:18 GDRelayToggle.py
-rwxr-xr-x 1 root root    64 Jul 14 17:47 GDRelayToggle.sh

Run on their own - the shell script or the python code run correctly (phone alert and relay toggles on/off).

Any idea why activating these from the apache web server are causing the IOError: [Errno 13] Permission denied?

Suggestions would be most welcome - hope my first post to this forum makes sense.

Thanks,

Rob


#2

Apache and other web servers usually run under the context of the wwwdata user and group to avoid granting any code exposed to the web more permissions than it should have.

Since smbus.SMBus(1) is attempting to open /dev/i2c-1 and failing due to a lack of permissions (and not being very good at communicating this in the error message) you need to look at that node and see what user/group it’s assigned to:

$ ls -hal /dev/i2c-1
crw-rw---- 1 root i2c 89, 1 Jun 15 12:04 /dev/i2c-1

On my system the user is root and the group is i2c. Aha! That means we need to grant wwwdata the i2c group:

sudo adduser wwwdata i2c

(Note: there’s another command for adding groups to a user, but I prefer the one above since it’s one not one typo away from deleting all but the added group!)

And this should - hopefully - get you up and running.

For posterity one good approach this problem would be to run the Python code in a separate process, under a separate user which has access to the i2c device nodes, and then have the web interface communicate with that process in order to control devices. This would mean even if the web server were compromised, the wwwdata user wouldn’t have access to communicate with sensors/devices connected via i2c.


#3

Thanks for the response! Indeed, we’re on the right track here…

pi@pi3:~ $ ls -hal /dev/i2c-1
crw-rw---- 1 root i2c 89, 1 May 28 22:34 /dev/i2c-1

I then added…

$ sudo adduser www-data i2c

Did a reboot.

Then tried the web click again… but, interestingly, a new error pops up…

Traceback (most recent call last):
  File "/var/www/html/GDRelayToggle.py", line 6, in <module>
    automationhat.relay.one.toggle()
  File "/usr/lib/python2.7/dist-packages/automationhat/__init__.py", line 238, in toggle
    self.write(not self.read())
  File "/usr/lib/python2.7/dist-packages/automationhat/__init__.py", line 143, in read
    self.setup()
  File "/usr/lib/python2.7/dist-packages/automationhat/__init__.py", line 264, in setup
    GPIO.setup(self.pin, GPIO.OUT, initial=0)
RuntimeError: No access to /dev/mem.  Try running as root!

Am I onto the correct track by looking at access to /dev/gpiomem or even /dev/mem ?

$ ls -l /dev/gpiomem
crw-rw---- 1 root gpio 248, 0 Jul 17 21:38 /dev/gpiomem
$ ls -l /dev/mem
crw-r----- 1 root kmem 1, 1 Jul 17 21:38 /dev/mem

Probably a bad idea to give it unrestricted write access to /dev/mem ! But does www-data need to be able to write to gpio I wonder?

thus…

$ sudo adduser www-data gpio

Bingo! Relay now cycles when web page button is clicked!

Thanks for the info on the permissions and group settings (and for speedy response!).

Agreed - I should consider the security angle now. For the moment, the apache server will not be open to the internet (I vpn in to another pi on the local network). Next steps to learn some inter process communication.
Brilliant fun these Pis!

Thanks again!