Diskussion/Fragen: Anleitung zum schalten von GPIO

  • Diskussion/Fragen: Anleitung zum schalten von GPIO? Schau mal ob du hier fündig wirst!

  • Hm ich muss gerade feststellen das die Berechtigungen für /sys/class/gpio/ ab Kernel Version 4.1.6 geändert wurden... Beziehungsweise sind die GPIO Dateien in /sys/class/gpio/ nur noch Verknüpfungen nach /sys/devices/platform/soc/*.gpio/gpio/ aber dort gehören die Dateien der Gruppe "root", also fällt die 1.Möglichkeit mit der Systemgruppe "gpio" flach :denker:

    Das gleiche Problem besteht auch mit Raspbian Jessie.. Es gibt zwar einen dirty Hack, aber das bedeutet mehr Aufwand als es früher nötig war... Angeblich soll es bald ein "raspberrypi-sys-mods" Paket geben um dieses "Problem" wieder zum alten Schema zu bringen, aber ob und wann können die verantwortlichen Entwickler zZt. nicht sagen.

    Irgend wie hängt die Rechtevergabe mit dem DeviceTree zusammen...
    Wenn man diesen durch einfügen von " device_tree= " zur /boot/config.txt deaktiviert gibt es nämlich kein/sys/devices/platform/soc/*.gpio/gpio/ mehr!


    Ein angeblicher Fix sieht wie folgt aus:

    sudo nano /lib/udev/rules.d/60-python-pifacecommon.rules

    Code
    KERNEL=="spidev*", GROUP="spi", MODE="0660"
    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; chown -R root:gpio /sys/devices/platform/soc/*.gpio/gpio && chmod -R 770 /sys/devices/platform/soc/*.gpio/gpio'"


    sudo cp /lib/udev/rules.d/60-python-pifacecommon.rules /lib/udev/rules.d/60-python3-pifacecommon.rules

    Quellen:
    https://github.com/raspberrypi/linux/issues/1117
    http://raspberrypi.znix.com/hipidocs/topic_gpiodev.htm

    Ein alternativer Hack wäre:
    sudo nano /etc/udev/rules.d/80-gpio-noroot.rules

    Code
    # /etc/udev/rules.d/80-gpio-noroot.rules
    # Zugriff auf GPIO ohne root-Rechte ermoeglichen
    #
    # Gruppe aendern
    SUBSYSTEM=="gpio", RUN+="/bin/chown -R root.gpio /sys/devices/platform/soc/3f200000.gpio/gpio"
    # SGID setzen
    SUBSYSTEM=="gpio", RUN+="/bin/chmod g+s /sys/devices/platform/soc/3f200000.gpio/gpio"
    # Zugriffsrechte setzen
    SUBSYSTEM=="gpio", RUN+="/bin/chmod -R ug+rw /sys/devices/platform/soc/3f200000.gpio/gpio/"


    sudo service udev restart
    sudo udevadm trigger --subsystem-match=gpio


    Leider funktionieren diese Workarounds bei mir nicht! Kann das jemand verifizieren?


    //EDIT: Folgendes funktioniert für alle RaspberryPi's:

    Code
    sudo nano /etc/udev/rules.d/80-gpio-noroot.rules
    Code
    # /etc/udev/rules.d/80-gpio-noroot.rules
    # Zugriff auf GPIO ohne root-Rechte ermoeglichen
    #
    # Gruppe aendern
    SUBSYSTEM=="gpio", PROGRAM="/bin/sh -c '/bin/chown -R root:gpio /sys/devices/platform/soc/*.gpio/gpio'"
    # Zugriffsrechte setzen
    SUBSYSTEM=="gpio", PROGRAM="/bin/sh -c '/bin/chmod -R ug+rw /sys/devices/platform/soc/*.gpio/gpio'"
  • Moin,
    ich habe nur den alternativen Hack getestet.

    Code
    pi@webradio ~ $ uname -a
    Linux webradio.site 4.1.7+ #817 PREEMPT Sat Sep 19 15:25:36 BST 2015 armv6l GNU/Linux

    Ich habe zuerst deine Kommandos benutzt. Da hat es auch nicht gegriffen.
    Dann habe ich die Datei wie folgt geändert.

    Code
    sudo cat /etc/udev/rules.d/80-gpio-noroot.rules
    #test
    SUBSYSTEM=="gpio", RUN+="/bin/chown -R root:gpio /sys/devices/platform/soc/20200000.gpio/gpio"
    # Sticky-Bit setzen
    SUBSYSTEM=="gpio", RUN+="/bin/chmod g+s /sys/devices/platform/soc/20200000.gpio/gpio"
    # Zugriffsrechte setzen
    SUBSYSTEM=="gpio", RUN+="/bin/chmod -R ug+rw /sys/devices/platform/soc/20200000.gpio/gpio/"

    Wie du siehst habe ich statt dem "*" den genauen Pfad genommen. Nun sieht es so aus:

    Code
    drwxrwsr-x  6 root root    0 Okt 13 00:26 gpio

    Ich hoffe ich konnte weiterhelfen.
    Gruss Bernd

    Ich habe KEINE Ahnung und davon GANZ VIEL!!
    Bei einer Lösung freue ich mich über ein ":thumbup:"
    Vielleicht trifft man sich in der RPi-Plauderecke.
    Linux ist zum Lernen da, je mehr man lernt um so besser versteht man es.

  • morob65: Ich hab in der Anleitung beschrieben das ich nicht auf alle Eventualitäten eingehen möchte und nur das anspreche was aus meiner Sicht sinnvoll wäre.

    $_REQUEST hab ich dort auch aufgeführt, betrachte ich aber als nicht Sinnvoll dies zu verwenden. $_REQUEST zu nutzen ist zwar einfach aber sehr unsicher da es von einem Angreifer leichter manipuliert werden kann als es bei $_POST der Fall ist. Das ist quasi das selbe als würde man www-data volle und uneingeschränkte sudo Rechte geben -> blöde Idee.
    Desweiteren würden gleichnamige Übergaben überschrieben werden weil $_REQUEST nicht unterscheidet ob ein Schlüssel von GET oder POST übergeben wurde.

    Wenn du nach "php $_REQUEST" googlest, findest du auch einige genauere Begründungen..

    Es gibt zwar diese Variable, sie zu verwenden bedarf aber weit aus mehr Aufwand auch Sicher zu nutzen. Ich möchte aber keine 100 Seitige Anleitung zusammen texten nur damit jeder von allem ein bisschen darin findet und zufrieden ist - Anfänger aber überfordert sind und nichts davon beachten...

    Davon abgesehen bin ich mit der Anleitung auch noch nicht fertig... Es ist bereits jetzt sehr umfangreich und wie hier auch steht gibt es zudem Probleme mit diesem Device-Tree...

  • Code
    sudo cat /etc/udev/rules.d/80-gpio-noroot.rules
    #test
    SUBSYSTEM=="gpio", RUN+="/bin/chown -R root:gpio /sys/devices/platform/soc/20200000.gpio/gpio"
    # SGID setzen
    SUBSYSTEM=="gpio", RUN+="/bin/chmod g+s /sys/devices/platform/soc/20200000.gpio/gpio"
    # Zugriffsrechte setzen
    SUBSYSTEM=="gpio", RUN+="/bin/chmod -R ug+rw /sys/devices/platform/soc/20200000.gpio/gpio/"

    :denker: In der Tat funktioniert das nur wenn man das *.gpio mit der tatsächlichen Zahl ersetzt. Du hast aber anscheint noch einen älteren RaspberryPi, B+ oder B oder so...
    Bei dir ist die Zahl anders: 20200000.gpio
    Beim 2B lautet die Zahl: 3f200000.gpio

    Ich muss nun also ein gängigen Workaround basteln der einfach einzurichten und universal funktioniert. Schöner wärs natürlich gewesen wenn " *.gpio " funktionieren würde aber nunja :-/

    Mal gucken wie ich das löse :denker:

    //EDIT: Folgendes sollte universal funktionieren:

    Code
    # /etc/udev/rules.d/80-gpio-noroot.rules
    # Zugriff auf GPIO ohne root-Rechte ermoeglichen
    #
    # Gruppe aendern
    SUBSYSTEM=="gpio", PROGRAM="/bin/sh -c '/bin/chown -R root.gpio /sys/devices/platform/soc/*.gpio/gpio'"
    # SGID setzen
    SUBSYSTEM=="gpio", PROGRAM="/bin/sh -c '/bin/chmod g+s /sys/devices/platform/soc/*.gpio/gpio'"
    # Zugriffsrechte setzen
    SUBSYSTEM=="gpio", PROGRAM="/bin/sh -c '/bin/chmod -R ug+rw /sys/devices/platform/soc/*.gpio/gpio'"
  • Danke für die Vorarbeit ...
    btw: ich weiss nicht, wo wer das her hat, aber der Kommentar

    Code
    # Sticky-Bit setzen


    ist, gelinde gesagt, Quatsch, denn mit

    Code
    SUBSYSTEM=="gpio", RUN+="/bin/chmod g+s /sys/devices/platform/soc/20200000.gpio/gpio"


    wird das [b]s-Bit[/s] für die Gruppe gesetzt (set group-id on execution) ...
    Das sticky-bit (oder auch text-bit) ist, wenn ich mich noch recht erinnere, ein Relikt aus der Zeit, als Speicher noch ziemlich wertvoll war und CPUs als auch Datentransfers noch recht langsam waren. Es diente dazu, dass ein Programm nach seiner Beendigung nicht aus dem Speicher entfernt sondern dort behalten wurde, um die folgenden Aufrufe desselben zu beschleunigen.
    Wobei ich mich gerade frage, ob die Zeile mit dem s-Bit nicht überhaupt überflüssig ist. Ohne sie sollte der Zugriff auf Mitglieder der Gruppe gpio beschränkt bleiben. Setzt man das Bit, sollte der Zugriff mit jeder beliebigen User-Id funktionieren ...

    cu,
    -ds-

  • Sticky-Bit ist in der Unix/Linux-Welt immer noch ein gültiger Begriff: https://de.wikipedia.org/wiki/Sticky_Bit

    Aber du hast insofern Recht das es hierfür nicht zwingend notwendig ist und vermutlich eher 'setgid' entspricht.. Da diese Zeilen aber nicht von mir stammen kann ich zu den genauen Hintergründen nichts sagen ;)

  • Naja ... ich sagte ja auch nur, dass es Relikt ist ... was aber nichts daran ändert, dass der Kommentar nicht stimmt ....

    Aber zurück zum Thema:
    Auf meinem Pi2 mit kernel 4.1 sieht das übrigens so aus:

    Nachtrag:
    Bei mir klappt das mit dem udev-Eintrag:

    Code
    pi@raspi2 ~ $ sudo udevadm trigger --subsystem-match=gpio
    pi@raspi2 ~ $ echo "27" > /sys/class/gpio/export 
    pi@raspi2 ~ $ echo "out" > /sys/class/gpio/gpio27/direction
    pi@raspi2 ~ $ echo 1 > /sys/class/gpio/gpio27/value
    pi@raspi2 ~ $ cat /sys/class/gpio/gpio27/value
    1
    pi@raspi2 ~ $


    Das war, wie gesagt, auf einem Pi2 mit 4.1.7 ... ich habe allerdings die Zeile mit dem s-Bit weggelassen ...

    cu,
    -ds-

  • Spoiler anzeigen

    Nein das Sticky-Bit wird auch heute noch verwendet, nur mit einem anderen Hintergrund als "damals" ;)
    ...Ich hab das falsche Kommentar aus meinen Beiträgen gestrichen damit das keinem mehr sauer aufstößt - mir ging es eh nur um die Funktion nicht um die Kommentare einer mir fremden Person :fies:

    Das übergeordnete Verzeichnis " /sys/devices/platform/soc/ " gehört weiterhin "root:root", was aber auch nicht schlimm ist. Das hierfür wichtige ist das Unterverzeichnis " 3f200000.gpio " erst der dadrin befindliche Ordner " gpio " sollte 'root:gpio' gehören damit das hier angesprochene Funktioniert.

    Und wie erwähnt besteht dieses Problem auch nur wenn man deviceTree aktiviert hat.

  • Ach ja, noch was:
    wenn man die Zeile mit dem s-Bit weglässt, funktioniert auch der Mechanismus mit der Gruppe gpio wieder:

    Code
    dreamshader@raspi2 ~ $ echo "27" > /sys/class/gpio/export
    -su: /sys/class/gpio/export: Keine Berechtigung
    dreamshader@raspi2 ~ $ groups
    dreamshader

    Brauchst Du noch was an Daten (für Pi2, 4.1.7)?
    Dateiliste oder so?

    //EDIT:
    Einen hab' ich noch:
    Das Verzeichnis /sys/devices/platform/soc

    Code
    pi@rpi-lcurr ~ $ uname -a
    Linux rpi-lcurr 3.18.5+ #1 PREEMPT Fri Feb 6 23:35:59 CET 2015 armv6l GNU/Linux
    pi@rpi-lcurr ~ $ ls -l /sys/devices/platform/soc
    ls: Zugriff auf /sys/devices/platform/soc nicht möglich: Datei oder Verzeichnis nicht gefunden
    pi@rpi-lcurr ~ $


    gibts scheinbar vor Kernel 4.1 gar nicht.

    cu,
    -ds-

  • Hm ... ich müsste mich schon schwer täuschen, aber auf dem Pi2 habe ich meines Wissen alles ganz normal mit apt-get update/upgrade installiert - also auch den Kernel 4.1.7 ...
    Damit wäre der Kernel, für den Pi2 zumindest, offiziell ...
    Vielleicht kann das ja noch jemand anderes bestätigen?

    //Nachtrag:
    Ich hab' jetzt mal den hold-status des Kernels auf meinem B zurückgesetzt (den hatte ich, glaube ich, mal wegen einer Framebuffer-Geschichte gesperrt) und dann einen apt-get update/upgrade gemacht,
    Nache einem reboot, siehe da:

    Code
    pi@rpi-lcurr ~ $ uname -a
    Linux rpi-lcurr 4.1.7+ #817 PREEMPT Sat Sep 19 15:25:36 BST 2015 armv6l GNU/Linux
    pi@rpi-lcurr ~

    Mit anderen Worten: der Kernel 4.1.7 ist mittlerweile wohl als stable eingestuft und auch freigegeben :) ...

    Der Vollständigkeit halber:


    Wie gesagt, das ist jetzt ein "alter" B Rev.2 (512MB) auf dem über den ganz offiziellen Weg mit apt-get update/upgrade jetzt auf 4.1.7 installiert ist.


    cu,
    -ds-

  • Mal was ganz anderes:

    Warum verwendet man nicht einfach WiringPi?

    Das braucht kein sudo-Recht zum Ausführen und lässt sich somit viel weniger umständlich in einem Webinterface realisieren.

    Einfach mal Google-Suche "wiring pi"
    oder
    Website des Entwicklers: wiringpi.com

    Gruß

  • Weil wiringPi ein Konsolen Programm ist und somit suboptimal wäre dies in PHP via exec(); einzubinden. Das ist auch noch weitaus langsamer als es nativ in der jeweiligen Sprache (php) zu realisieren. Man schreibt sich ja auch kein C++ Programm nur weil man damit bash Scripte ausführen will...
    Das erklär ich aber auch in der Anleitung, die du also vermutlich nicht mals gelesen hast? :s

    Meiner Anleitung kannst du aber auch entnehmen das 'sudo' nicht zwangsweise benötigt wird, der Trick ist schlicht den www-data Benutzer des WebServers der Systemgruppe 'gpio' hinzuzufügen.


    Mittlerweile empfehle ich aber: FAQ => Nützliche Links / Linksammlung => [Python] Webserver, Websocket und ein bisschen AJAX


  • Weil wiringPi ein Konsolen Programm ist und somit suboptimal wäre dies in PHP via exec(); einzubinden. Das ist auch noch weitaus langsamer als es nativ in der jeweiligen Sprache (php) zu realisieren. Man schreibt sich ja auch kein C++ Programm nur weil man damit bash Scripte ausführen will...
    Das erklär ich aber auch in der Anleitung, die du also vermutlich nicht mals gelesen hast? :s

    Meiner Anleitung kannst du aber auch entnehmen das 'sudo' nicht zwangsweise benötigt wird, der Trick ist schlicht den www-data Benutzer des WebServers der Systemgruppe 'gpio' hinzuzufügen.


    Mittlerweile empfehle ich aber: FAQ => Nützliche Links / Linksammlung => [Python] Webserver, Websocket und ein bisschen AJAX

    Hmmm... ok versteh ich. Also ist es einfach doch umständlicher WiringPi in PHP zu nutzen. Aber nochmal bezüglich Sicherheit, da gibt es kein Problem, wenn der "WWW-data"-user auf die GPIO's direkt Zugriff hat. Also ich meine, bei wiring pi hat er das auch. Aber ist da überhaupt ein Unterschied zwischen Hinzufügen in Gruppe "gpio" und Benutzung von Wiring Pi (bezüglich der Sicherheit)?

    Ansonsten vielen Dank für die Antwort, ich hatte deine Anleitung schon gelesen, in der du erklärt hattest, dass man eben den WWW-data einfach in die Gruppe "gpio" reinstecken kann, aber ich hatte da eben noch so Zweifel...

  • Bezüglich der Sicherheit gibt es da zunächst keinen Unterschied.
    Ob ein PHP Script den Konsolen Befehl 'gpio' verwendet oder eben direkten Zugriff auf die GPIO Dateien im sysfs hat. Die Systemgruppe "gpio" bezieht sich eben nur auf die sysfs Dateien in /sys/class/gpio/ , ermöglicht also kein Zugriff auf andere sysfs Dateien.
    Allerdings könnte ein PHP-wiringPi-Script schlecht geschrieben sein wodurch ein Angreifer noch weitere Konsolen Befehle ausführen könnte... Dieses Problem hätte man übers sysfs nicht.

    [code=php]
    if (!file_exists("/sys/class/gpio/gpio17")) {
    file_put_contents("/sys/class/gpio/export", "17");
    usleep(200000); //Programm-Verzoegerung in Mikrosekunden: 0.2s
    file_put_contents("/sys/class/gpio/gpio17/direction", "out");
    }

    if (isset($_POST["17an"]) AND !empty($_POST["17an"])) {
    file_put_contents("/sys/class/gpio/gpio17/value", "1");
    } elseif (isset($_POST["17aus"]) AND !empty($_POST["17aus"])) {
    file_put_contents("/sys/class/gpio/gpio17/value", "0");
    }
    [/php]
    Wie soll da ein Angreifer weiteren Code einschleusen?

  • Ok also das war eben mein Zweifel mit dem Zugriff auf das sysfs hat. Aber wenn das wirklich nur für die GPIO-Dateien gilt.
    Ich habe in meinem PHP-Script für GPIO WiringPi benutzt, aber mein Raspi ist auch nicht von außen erreichbar.
    Auf jeden Fall danke für das Script und die hilfreichen schnellen Antworten!

    Schönen Sonntag!

  • Hallo zusammen.

    Hab alles wie in der Anleitung beschrieben gemacht und es hat super funktionert. Aber leider nur für 3 Wochen.
    Seitdem startet apache einfach nicht mehr. Google mich jetzt schon seit einer Woche durch die Gegend und komme nicht vorran.

    Nach "sudo service apache2 start" kommt das hier:

    Job for apache2.service failed. See 'systemctl status apache2.service' and 'journalctl -xn' for details.

    systemctl status apache2.service sagt:

    ● apache2.service - LSB: Apache2 web server
    Loaded: loaded (/etc/init.d/apache2)
    Drop-In: /lib/systemd/system/apache2.service.d
    └─forking.conf
    Active: failed (Result: exit-code) since Fri 2017-05-19 18:11:36 UTC; 20s ago
    Process: 1867 ExecStart=/etc/init.d/apache2 start (code=exited, status=1/FAILURE)

    und journalctl -xn findet keine files.
    Ich habe absolut keine Ahnung wie ich weitermachen soll. Kann mir jemand helfen?

  • Dein Problem/Anliegen hat nicht wirklich etwas mit der hier behandelten Anleitung zum schalten von GPIO's zu tun, sondern bezieht sich offensichtlich auf ein Problem mit deinem Webserver. Daher wäre es denk ich besser du erstellst einen eigenen Thread um dort dein Problem/Anliegen ausführlich zu behandeln.
    Danke.


    PS: Einfach so, plötzlich, ohne zu tun oder dergleichen passiert sowas nicht. Es kann schon ein unsachgemäßer "power off" des Computers reichen um etwas zu beschädigen.... Aber wie gesagt, bitte nicht weiter hier behandeln da das nichts mit "[PHP] Anleitung zum schalten von GPIO" zu tun hat.

Jetzt mitmachen!

Du hast noch kein Benutzerkonto auf unserer Seite? Registriere dich kostenlos und nimm an unserer Community teil!