Add udev rules and tmpfiles for gpio sysfs node 77/137577/4
authorHyeongsik Min <hyeongsik.min@samsung.com>
Thu, 6 Jul 2017 11:01:24 +0000 (20:01 +0900)
committerHyeongsik Min <hyeongsik.min@samsung.com>
Mon, 10 Jul 2017 06:40:21 +0000 (15:40 +0900)
In order to change UID/GID of peripheral-bus, we need to change
permission of gpio sysfs node from root to system_fw and set smack label to
them.

Change-Id: I84640cc8aa858a6cc00d9a38a89bd4d1aee3b478
Signed-off-by: Hyeongsik Min <hyeongsik.min@samsung.com>
CMakeLists.txt
packaging/90-gpio.rules [new file with mode: 0644]
packaging/peripheral-bus.service
packaging/peripheral-bus.spec
packaging/peripheral-bus.tmpfiles.conf [new file with mode: 0644]
src/daemon/peripheral_bus_gpio.c
src/interface/include/gpio.h

index 9462957..0027411 100644 (file)
@@ -4,7 +4,7 @@ PROJECT(peripheral-bus C)
 SET(PREFIX ${CMAKE_INSTALL_PREFIX})
 SET(VERSION 0.0.1)
 
-SET(dependents "dlog glib-2.0 gio-2.0 gio-unix-2.0 iniparser")
+SET(dependents "dlog glib-2.0 gio-2.0 gio-unix-2.0 iniparser libudev")
 
 FIND_PROGRAM(GDBUS_CODEGEN NAMES gdbus-codegen)
 EXEC_PROGRAM(${GDBUS_CODEGEN} ARGS
diff --git a/packaging/90-gpio.rules b/packaging/90-gpio.rules
new file mode 100644 (file)
index 0000000..a1dcd59
--- /dev/null
@@ -0,0 +1,12 @@
+SUBSYSTEM=="gpio", KERNEL=="gpio*", ACTION=="add",\
+ RUN+="/bin/chown root:system_fw /sys%p/value",\
+ RUN+="/bin/chmod g+rw /sys%p/value",\
+ RUN+="/bin/chsmack -a System /sys%p/value"
+SUBSYSTEM=="gpio", KERNEL=="gpio*", ACTION=="add",\
+ RUN+="/bin/chown root:system_fw /sys%p/direction",\
+ RUN+="/bin/chmod g+rw /sys%p/direction",\
+ RUN+="/bin/chsmack -a System /sys%p/direction"
+SUBSYSTEM=="gpio", KERNEL=="gpio*", ACTION=="add",\
+ RUN+="/bin/chown root:system_fw /sys%p/edge",\
+ RUN+="/bin/chmod g+rw /sys%p/edge",\
+ RUN+="/bin/chsmack -a System /sys%p/edge"
index c3d8841..9fbf27d 100644 (file)
@@ -1,6 +1,7 @@
 [Unit]
 Description=Peripheral Service Daemon
 Requires=dbus.service
+After=systemd-tmpfiles-setup.service
 
 [Service]
 SmackProcessLabel=System
index 3e0d858..d5013e8 100644 (file)
@@ -7,12 +7,16 @@ License:    Apache-2.0
 Source0:    %{name}-%{version}.tar.gz
 Source1:    %{name}.manifest
 Source2:    %{name}.service
+Source3:    %{name}.tmpfiles.conf
+Source4:    90-gpio.rules
 BuildRequires:  cmake
 BuildRequires:  pkgconfig(glib-2.0)
 BuildRequires:  pkgconfig(gio-2.0)
 BuildRequires:  pkgconfig(dlog)
+BuildRequires:  pkgconfig(libsystemd)
 BuildRequires:  pkgconfig(capi-system-peripheral-io)
 BuildRequires:  pkgconfig(iniparser)
+BuildRequires:  pkgconfig(libudev)
 
 Requires(post): /sbin/ldconfig
 Requires(postun): /sbin/ldconfig
@@ -35,6 +39,10 @@ MAJORVER=`echo %{version} | awk 'BEGIN {FS="."}{print $1}'`
 %make_install
 mkdir -p %{buildroot}%{_unitdir}/multi-user.target.wants
 install -m 0644 %SOURCE2 %{buildroot}%{_unitdir}/peripheral-bus.service
+mkdir -p %{buildroot}%{_tmpfilesdir}
+install -m 0644 %SOURCE3 %{buildroot}%{_tmpfilesdir}/%{name}.conf
+mkdir -p %{buildroot}%{_udevrulesdir}
+install -m 0644 %SOURCE4 %{buildroot}%{_udevrulesdir}
 %install_service multi-user.target.wants peripheral-bus.service
 
 mkdir -p %{buildroot}/etc/peripheral-bus
@@ -63,7 +71,9 @@ systemctl daemon-reload
 %manifest %{name}.manifest
 %defattr(-,root,root,-)
 %license LICENSE.APLv2
-%{_bindir}/peripheral-bus
-%{_unitdir}/peripheral-bus.service
-%{_unitdir}/multi-user.target.wants/peripheral-bus.service
+%{_bindir}/%{name}
+%{_unitdir}/%{name}.service
+%{_tmpfilesdir}/%{name}.conf
+/usr/lib/udev/rules.d/90-gpio.rules
+%{_unitdir}/multi-user.target.wants/%{name}.service
 /etc/peripheral-bus/*.ini
diff --git a/packaging/peripheral-bus.tmpfiles.conf b/packaging/peripheral-bus.tmpfiles.conf
new file mode 100644 (file)
index 0000000..d0d787e
--- /dev/null
@@ -0,0 +1,7 @@
+#Type Path        Mode UID  GID  Age Argument
+z      /sys/class/gpio/export  0220 root system_fw     -
+t      /sys/class/gpio/export  -       -       -       -       security.SMACK64="System"
+z      /sys/class/gpio/unexport        0220 root system_fw     -
+t      /sys/class/gpio/unexport        -       -       -       -       security.SMACK64="System"
+z      /sys/devices/platform/soc/*.gpio/gpiochip*      0775 root system_fw     -
+t      /sys/devices/platform/soc/*.gpio/gpiochip*      -       -       -       -       security.SMACK64="System"
index c36275e..c0d89e4 100644 (file)
@@ -17,6 +17,9 @@
 #include <stdio.h>
 #include <stdlib.h>
 #include <gio/gio.h>
+#include <poll.h>
+#include <sys/time.h>
+#include <libudev.h>
 
 #include <peripheral_io.h>
 
@@ -53,6 +56,71 @@ static bool peripheral_bus_gpio_is_available(int pin, peripheral_bus_s *pb_data)
        return true;
 }
 
+static int gpio_wait_for_udev(int gpiopin)
+{
+       #define GPIO_NAME_LEN 8
+       struct udev *udev;
+       struct udev_monitor *monitor;
+       struct udev_device *dev;
+       struct pollfd pfd;
+       char gpio_name[GPIO_NAME_LEN];
+       int ret = -EIO;
+
+       udev = udev_new();
+       if (!udev) {
+               _E("Cannot create udev");
+               return ret;
+       }
+
+       monitor = udev_monitor_new_from_netlink(udev, "udev");
+       if (!monitor) {
+               _E("Cannot create udev monitor");
+               udev_unref(udev);
+               return ret;
+       }
+
+       ret = udev_monitor_filter_add_match_subsystem_devtype(monitor, "gpio", NULL);
+       if (ret < 0) {
+               _E("Failed to add monitor filter");
+               goto out;
+       }
+
+       ret = udev_monitor_enable_receiving(monitor);
+       if (ret < 0) {
+               _E("Failed to enable udev receiving");
+               goto out;
+       }
+
+       pfd.fd = udev_monitor_get_fd(monitor);
+       pfd.events = POLLIN;
+
+       snprintf(gpio_name, GPIO_NAME_LEN, "gpio%d", gpiopin);
+
+       for (int cnt = 0; cnt < 10; cnt++) {
+               if (poll(&pfd, 1, 100) < 0) {
+                       _E("Failed to watch udev monitor");
+                       goto out;
+               }
+
+               dev = udev_monitor_receive_device(monitor);
+               if (dev) {
+                       if (strcmp(udev_device_get_sysname(dev), gpio_name) == 0) {
+                               _D("udev for %s is initialized", gpio_name);
+                               ret = 0;
+                               goto out;
+                       }
+               }
+       }
+       _E("Time out");
+
+out:
+       udev_monitor_unref(monitor);
+       udev_unref(udev);
+
+       return ret;
+}
+
+
 int peripheral_bus_gpio_open(gint pin, pb_data_h *handle, gpointer user_data)
 {
        peripheral_bus_s *pb_data = (peripheral_bus_s*)user_data;
@@ -87,6 +155,12 @@ int peripheral_bus_gpio_open(gint pin, pb_data_h *handle, gpointer user_data)
                goto err;
        }
 
+       if (gpio_wait_for_udev(pin) < 0) {
+               _E("device nodes are not writable");
+               ret = PERIPHERAL_ERROR_UNKNOWN;
+               goto err;
+       }
+
        gpio_handle->type = PERIPHERAL_BUS_TYPE_GPIO;
        gpio_handle->list = &pb_data->gpio_list;
        gpio_handle->dev.gpio.pin = pin;
index a7cb530..9d7743b 100644 (file)
@@ -33,17 +33,16 @@ typedef enum {
        GPIO_EDGE_BOTH = 3,
 } gpio_edge_e;
 
-int gpio_get_edge_mode(int gpiopin, gpio_edge_e *edge);
-int gpio_get_direction(int gpiopin, gpio_direction_e *dir);
-int gpio_read(int gpiopin, int *value);
 int gpio_open(int gpiopin);
 int gpio_close(int gpiopin);
 int gpio_set_edge_mode(int gpiopin, gpio_edge_e edge);
+int gpio_get_edge_mode(int gpiopin, gpio_edge_e *edge);
 int gpio_set_direction(int gpiopin, gpio_direction_e dir);
+int gpio_get_direction(int gpiopin, gpio_direction_e *dir);
 int gpio_write(int gpiopin, int value);
+int gpio_read(int gpiopin, int *value);
 
 int gpio_open_isr(int gpiopin);
 int gpio_close_isr(int file_hndl);
 int gpio_read_isr(void *fdset, char *rev_buf, int length);
-//int gpio_read_isr(void *fdset, char *rev_buf, int length);
 #endif/*__GPIO_H__*/