diff --git a/file.te b/file.te
index 722ccac0dab2b92575eb9178949fe1fe98289012..9102679acf0389605ccf1cdefa559ee4cf58b5f8 100644
--- a/file.te
+++ b/file.te
@@ -228,6 +228,8 @@ type system_ndebug_socket, file_type;
 type uncrypt_socket, file_type;
 type vold_socket, file_type;
 type wpa_socket, file_type;
+# hostapd control interface.
+type hostapd_socket, file_type;
 type zygote_socket, file_type;
 type sap_uim_socket, file_type;
 # UART (for GPS) control proc file
diff --git a/file_contexts b/file_contexts
index 4d5eea91123fc067ad8aff80f3ecd0b12cfb75d9..3655d3784863badc00bc85c8797c2397955f8512 100644
--- a/file_contexts
+++ b/file_contexts
@@ -287,7 +287,7 @@
 /data/misc/wifi(/.*)?           u:object_r:wifi_data_file:s0
 /data/misc/wifi/sockets(/.*)?   u:object_r:wpa_socket:s0
 /data/misc/wifi/sockets/wpa_ctrl.*   u:object_r:system_wpa_socket:s0
-/data/misc/wifi/hostapd(/.*)?   u:object_r:wpa_socket:s0
+/data/misc/wifi/hostapd(/.*)?   u:object_r:hostapd_socket:s0
 /data/misc/zoneinfo(/.*)?       u:object_r:zoneinfo_data_file:s0
 /data/misc/vold(/.*)?           u:object_r:vold_data_file:s0
 /data/misc/perfprofd(/.*)?      u:object_r:perfprofd_data_file:s0
diff --git a/hostapd.te b/hostapd.te
index e552c2b25994b883289e4de94a9061fd02e80e75..8f8cd6522e0ec63cf72a41fc72f7c77ae7bac3c2 100644
--- a/hostapd.te
+++ b/hostapd.te
@@ -1,28 +1,33 @@
 # userspace wifi access points
-type hostapd, domain, domain_deprecated;
+type hostapd, domain;
 type hostapd_exec, exec_type, file_type;
 
+init_daemon_domain(hostapd)
 net_domain(hostapd)
-allowxperm hostapd self:udp_socket ioctl priv_sock_ioctls;
+allow hostapd self:capability { net_admin net_raw };
+
+# hostapd learns about its network interface via sysfs.
+allow hostapd sysfs:file r_file_perms;
+# hostapd follows the /sys/class/net/wlan0 link to the PCI device.
+allow hostapd sysfs:lnk_file r_file_perms;
+
+# Allow hostapd to access /proc/net/psched
+allow hostapd proc_net:file { getattr open read };
 
-allow hostapd self:capability { net_admin net_raw setuid setgid };
+# Various socket permissions.
+allowxperm hostapd self:udp_socket ioctl priv_sock_ioctls;
 allow hostapd self:netlink_socket create_socket_perms_no_ioctl;
 allow hostapd self:netlink_generic_socket create_socket_perms_no_ioctl;
 allow hostapd self:packet_socket create_socket_perms_no_ioctl;
 allow hostapd self:netlink_route_socket nlmsg_write;
 
+# hostapd can read and write WiFi related data and configuration.
+# For example, the entropy file is periodically updated.
 allow hostapd wifi_data_file:file rw_file_perms;
-allow hostapd wifi_data_file:dir create_dir_perms;
-type_transition hostapd wifi_data_file:dir wpa_socket "sockets";
-type_transition hostapd wifi_data_file:dir wpa_socket "hostapd";
-allow hostapd wpa_socket:dir create_dir_perms;
-allow hostapd wpa_socket:sock_file create_file_perms;
-allow hostapd netd:fd use;
-allow hostapd netd:udp_socket { read write };
-allow hostapd netd:fifo_file { read write };
-# TODO: Investigate whether these inherited sockets should be closed on exec.
-allow hostapd netd:netlink_kobject_uevent_socket { read write };
-allow hostapd netd:netlink_nflog_socket { read write };
-allow hostapd netd:netlink_route_socket { read write };
-allow hostapd netd:unix_stream_socket { read write };
-allow hostapd netd:unix_dgram_socket { read write };
+r_dir_file(hostapd, wifi_data_file)
+
+# hostapd needs to bind to (and possibly create) its control interface socket.
+allow hostapd hostapd_socket:dir rw_dir_perms;
+# hostapd likes to chmod its socket directory.
+allow hostapd hostapd_socket:dir setattr;
+allow hostapd hostapd_socket:sock_file create_file_perms;
diff --git a/netd.te b/netd.te
index 7b9201c55a5a9ab7e284390383af46d30a3c8524..ff06ac9868f8a04d0b714a12612bdc7b07994f51 100644
--- a/netd.te
+++ b/netd.te
@@ -55,10 +55,6 @@ allow netd wifi_data_file:dir rw_dir_perms;
 allow netd net_data_file:file create_file_perms;
 allow netd net_data_file:dir rw_dir_perms;
 
-# Allow netd to spawn hostapd in it's own domain
-domain_auto_trans(netd, hostapd_exec, hostapd)
-allow netd hostapd:process signal;
-
 # Allow netd to spawn dnsmasq in it's own domain
 domain_auto_trans(netd, dnsmasq_exec, dnsmasq)
 allow netd dnsmasq:process signal;
@@ -85,6 +81,8 @@ allow netd dns_listener_service:service_manager find;
 allow netd netdomain:{tcp_socket udp_socket rawip_socket dccp_socket tun_socket} {read write getattr setattr getopt setopt};
 allow netd netdomain:fd use;
 
+# Allow netd to start and stop hostapd via ctl.start/stop
+set_prop(netd, ctl_default_prop)
 
 ###
 ### Neverallow rules