Granting capabilities CAP_NET_ADMIN and CAP_NET_RAW allows running
hostapd and wpa_supplicant without root priviledges.
Add ubus acl allowing the necessary ubus interactions for the 'network'
user running hostapd/wpa_supplicant.
To still allow netifd to acquire the PID of wpa_supplicant and hostapd
introduce a new ubus method 'getpid' for both of them and make use of
that instead of querying procd (which will not work, as procd will
return the PID of ujail)

Signed-off-by: Daniel Golle <dan...@makrotopia.org>
---
 package/network/services/hostapd/Makefile     |  9 ++++++--
 .../network/services/hostapd/files/hostapd.sh |  2 +-
 .../network/services/hostapd/files/wpad.init  | 16 ++++++++++++++
 .../network/services/hostapd/files/wpad.json  | 22 +++++++++++++++++++
 .../services/hostapd/files/wpad_acl.json      | 10 +++++++++
 .../services/hostapd/src/src/ap/ubus.c        | 16 ++++++++++++++
 .../hostapd/src/wpa_supplicant/ubus.c         | 16 ++++++++++++++
 7 files changed, 88 insertions(+), 3 deletions(-)
 create mode 100644 package/network/services/hostapd/files/wpad.json
 create mode 100644 package/network/services/hostapd/files/wpad_acl.json

diff --git a/package/network/services/hostapd/Makefile 
b/package/network/services/hostapd/Makefile
index 61b2a548ef..386c17f99d 100644
--- a/package/network/services/hostapd/Makefile
+++ b/package/network/services/hostapd/Makefile
@@ -7,7 +7,7 @@
 include $(TOPDIR)/rules.mk
 
 PKG_NAME:=hostapd
-PKG_RELEASE:=18
+PKG_RELEASE:=19
 
 PKG_SOURCE_URL:=http://w1.fi/hostap.git
 PKG_SOURCE_PROTO:=git
@@ -149,6 +149,7 @@ define Package/hostapd/Default
   TITLE:=IEEE 802.1x Authenticator
   URL:=http://hostap.epitest.fi/
   DEPENDS:=$(DRV_DEPENDS) +hostapd-common +libubus
+  USERID:=network=101:network=101
   PROVIDES:=hostapd
   CONFLICTS:=$(HOSTAPD_PROVIDERS)
   HOSTAPD_PROVIDERS+=$(1)
@@ -232,6 +233,7 @@ define Package/wpad/Default
   SUBMENU:=WirelessAPD
   TITLE:=IEEE 802.1x Auth/Supplicant
   DEPENDS:=$(DRV_DEPENDS) +hostapd-common +libubus
+  USERID:=network=101:network=101
   URL:=http://hostap.epitest.fi/
   PROVIDES:=hostapd wpa-supplicant
   CONFLICTS:=$(HOSTAPD_PROVIDERS) $(SUPPLICANT_PROVIDERS)
@@ -346,6 +348,7 @@ define Package/wpa-supplicant/Default
   TITLE:=WPA Supplicant
   URL:=http://hostap.epitest.fi/wpa_supplicant/
   DEPENDS:=$(DRV_DEPENDS) +hostapd-common +libubus
+  USERID:=network=101:network=101
   PROVIDES:=wpa-supplicant
   CONFLICTS:=$(SUPPLICANT_PROVIDERS)
   SUPPLICANT_PROVIDERS+=$(1)
@@ -597,10 +600,12 @@ define Install/supplicant
 endef
 
 define Package/hostapd-common/install
-       $(INSTALL_DIR) $(1)/lib/netifd $(1)/etc/rc.button 
$(1)/etc/hotplug.d/ieee80211 $(1)/etc/init.d
+       $(INSTALL_DIR) $(1)/etc/capabilities $(1)/etc/rc.button 
$(1)/etc/hotplug.d/ieee80211 $(1)/etc/init.d $(1)/lib/netifd  
$(1)/usr/share/acl.d
        $(INSTALL_DATA) ./files/hostapd.sh $(1)/lib/netifd/hostapd.sh
        $(INSTALL_BIN) ./files/wpad.init $(1)/etc/init.d/wpad
        $(INSTALL_BIN) ./files/wps-hotplug.sh $(1)/etc/rc.button/wps
+       $(INSTALL_DATA) ./files/wpad_acl.json $(1)/usr/share/acl.d
+       $(INSTALL_DATA) ./files/wpad.json $(1)/etc/capabilities
 endef
 
 define Package/hostapd/install
diff --git a/package/network/services/hostapd/files/hostapd.sh 
b/package/network/services/hostapd/files/hostapd.sh
index 41b04e6029..781a34028a 100644
--- a/package/network/services/hostapd/files/hostapd.sh
+++ b/package/network/services/hostapd/files/hostapd.sh
@@ -1365,6 +1365,7 @@ wpa_supplicant_run() {
        _wpa_supplicant_common "$ifname"
 
        ubus wait_for wpa_supplicant
+       local supplicant_pid=$(ubus call wpa_supplicant getpid | jsonfilter -l 
1 -e @.pid)
        ubus call wpa_supplicant config_add "{ \
                \"driver\": \"${_w_driver:-wext}\", \"ctrl\": \"$_rpath\", \
                \"iface\": \"$ifname\", \"config\": \"$_config\" \
@@ -1376,7 +1377,6 @@ wpa_supplicant_run() {
 
        [ "$ret" != 0 ] && wireless_setup_vif_failed WPA_SUPPLICANT_FAILED
 
-       local supplicant_pid=$(ubus call service list '{"name": "wpad"}' | 
jsonfilter -l 1 -e "@['wpad'].instances['supplicant'].pid")
        wireless_add_process "$supplicant_pid" "/usr/sbin/wpa_supplicant" 1
 
        return $ret
diff --git a/package/network/services/hostapd/files/wpad.init 
b/package/network/services/hostapd/files/wpad.init
index 3198e9801f..6c60d539a2 100644
--- a/package/network/services/hostapd/files/wpad.init
+++ b/package/network/services/hostapd/files/wpad.init
@@ -9,17 +9,33 @@ NAME=wpad
 start_service() {
        if [ -x "/usr/sbin/hostapd" ]; then
                mkdir -p /var/run/hostapd
+               chown network:network /var/run/hostapd
                procd_open_instance hostapd
                procd_set_param command /usr/sbin/hostapd -s -g 
/var/run/hostapd/global
                procd_set_param respawn
+               [ -x /sbin/ujail -a -e /etc/capabilities/wpad.json ] && {
+                       procd_add_jail netifd
+                       procd_set_param capabilities /etc/capabilities/wpad.json
+                       procd_set_param user network
+                       procd_set_param group network
+                       procd_set_param no_new_privs 1
+               }
                procd_close_instance
        fi
 
        if [ -x "/usr/sbin/wpa_supplicant" ]; then
                mkdir -p /var/run/wpa_supplicant
+               chown network:network /var/run/wpa_supplicant
                procd_open_instance supplicant
                procd_set_param command /usr/sbin/wpa_supplicant -n -s -g 
/var/run/wpa_supplicant/global
                procd_set_param respawn
+               [ -x /sbin/ujail -a -e /etc/capabilities/wpad.json ] && {
+                       procd_add_jail netifd
+                       procd_set_param capabilities /etc/capabilities/wpad.json
+                       procd_set_param user network
+                       procd_set_param group network
+                       procd_set_param no_new_privs 1
+               }
                procd_close_instance
        fi
 }
diff --git a/package/network/services/hostapd/files/wpad.json 
b/package/network/services/hostapd/files/wpad.json
new file mode 100644
index 0000000000..ae3edd4fea
--- /dev/null
+++ b/package/network/services/hostapd/files/wpad.json
@@ -0,0 +1,22 @@
+{
+       "bounding": [
+               "CAP_NET_RAW",
+               "CAP_NET_ADMIN"
+       ],
+       "effective": [
+               "CAP_NET_RAW",
+               "CAP_NET_ADMIN"
+       ],
+       "ambient": [
+               "CAP_NET_RAW",
+               "CAP_NET_ADMIN"
+       ],
+       "permitted": [
+               "CAP_NET_RAW",
+               "CAP_NET_ADMIN"
+       ],
+       "inheritable": [
+               "CAP_NET_RAW",
+               "CAP_NET_ADMIN"
+       ]
+}
diff --git a/package/network/services/hostapd/files/wpad_acl.json 
b/package/network/services/hostapd/files/wpad_acl.json
new file mode 100644
index 0000000000..c77ccd8ea0
--- /dev/null
+++ b/package/network/services/hostapd/files/wpad_acl.json
@@ -0,0 +1,10 @@
+{
+       "user": "network",
+       "access": {
+               "service": {
+                       "methods": [ "event" ]
+               }
+       },
+       "publish": [ "hostapd", "hostapd.*", "wpa_supplicant", 
"wpa_supplicant.*" ],
+       "send": [ "bss.*", "wps_credentials" ]
+}
diff --git a/package/network/services/hostapd/src/src/ap/ubus.c 
b/package/network/services/hostapd/src/src/ap/ubus.c
index 8546d2ce69..e59db00bd3 100644
--- a/package/network/services/hostapd/src/src/ap/ubus.c
+++ b/package/network/services/hostapd/src/src/ap/ubus.c
@@ -690,6 +690,21 @@ hostapd_config_remove(struct ubus_context *ctx, struct 
ubus_object *obj,
        return UBUS_STATUS_OK;
 }
 
+static int
+hostapd_getpid(struct ubus_context *ctx, struct ubus_object *obj,
+              struct ubus_request_data *req, const char *method,
+              struct blob_attr *msg)
+{
+
+       blob_buf_init(&b, 0);
+
+       blobmsg_add_u32(&b, "pid", getpid());
+
+       ubus_send_reply(ctx, req, b.head);
+
+       return UBUS_STATUS_OK;
+}
+
 enum {
        CSA_FREQ,
        CSA_BCN_COUNT,
@@ -1363,6 +1378,7 @@ void hostapd_ubus_free_bss(struct hostapd_data *hapd)
 static const struct ubus_method daemon_methods[] = {
        UBUS_METHOD("config_add", hostapd_config_add, config_add_policy),
        UBUS_METHOD("config_remove", hostapd_config_remove, 
config_remove_policy),
+       UBUS_METHOD_NOARG("getpid", hostapd_getpid),
 };
 
 static struct ubus_object_type daemon_object_type =
diff --git a/package/network/services/hostapd/src/wpa_supplicant/ubus.c 
b/package/network/services/hostapd/src/wpa_supplicant/ubus.c
index 4bb92a7b66..f9fa1645d7 100644
--- a/package/network/services/hostapd/src/wpa_supplicant/ubus.c
+++ b/package/network/services/hostapd/src/wpa_supplicant/ubus.c
@@ -311,9 +311,25 @@ wpas_config_remove(struct ubus_context *ctx, struct 
ubus_object *obj,
        return UBUS_STATUS_OK;
 }
 
+static int
+wpas_getpid(struct ubus_context *ctx, struct ubus_object *obj,
+           struct ubus_request_data *req, const char *method,
+           struct blob_attr *msg)
+{
+
+       blob_buf_init(&b, 0);
+
+       blobmsg_add_u32(&b, "pid", getpid());
+
+       ubus_send_reply(ctx, req, b.head);
+
+       return UBUS_STATUS_OK;
+}
+
 static const struct ubus_method wpas_daemon_methods[] = {
        UBUS_METHOD("config_add", wpas_config_add, wpas_config_add_policy),
        UBUS_METHOD("config_remove", wpas_config_remove, 
wpas_config_remove_policy),
+       UBUS_METHOD_NOARG("getpid", wpas_getpid),
 };
 
 static struct ubus_object_type wpas_daemon_object_type =
-- 
2.29.2


_______________________________________________
openwrt-devel mailing list
openwrt-devel@lists.openwrt.org
https://lists.openwrt.org/mailman/listinfo/openwrt-devel

Reply via email to