diff --git a/private/bpfloader.te b/private/bpfloader.te
new file mode 100644
index 0000000000000000000000000000000000000000..1caf95268a43da30f52235b50f517e0193910068
--- /dev/null
+++ b/private/bpfloader.te
@@ -0,0 +1,28 @@
+# bpf program loader
+type bpfloader, domain;
+type bpfloader_exec, exec_type, file_type;
+typeattribute bpfloader coredomain;
+
+# Process need CAP_NET_ADMIN to run bpf programs as cgroup filter
+allow bpfloader self:global_capability_class_set net_admin;
+
+r_dir_file(bpfloader, cgroup_bpf)
+
+# These permission is required for pin bpf program for netd.
+allow bpfloader fs_bpf:dir  create_dir_perms;
+allow bpfloader fs_bpf:file create_file_perms;
+allow bpfloader devpts:chr_file { read write };
+
+# TODO: unknown fd pass denials, need further investigation.
+dontaudit bpfloader netd:fd use;
+
+# Use pinned bpf map files from netd.
+allow bpfloader netd:bpf { map_read map_write };
+allow bpfloader self:bpf { prog_load prog_run };
+
+# Neverallow rules
+neverallow { domain -bpfloader } *:bpf { prog_load prog_run };
+neverallow { domain -netd -bpfloader } bpfloader_exec:file { execute execute_no_trans };
+neverallow bpfloader domain:{ tcp_socket udp_socket rawip_socket } *;
+# only system_server, netd and bpfloader can read/write the bpf maps
+neverallow { domain -system_server -netd -bpfloader} netd:bpf { map_read map_write };
diff --git a/private/compat/26.0/26.0.ignore.cil b/private/compat/26.0/26.0.ignore.cil
index 34db6fa14bc525db5ef4dd156ccdf425da272fc8..56b0cf5a0b8a99e281d4271d02c1610f8728f763 100644
--- a/private/compat/26.0/26.0.ignore.cil
+++ b/private/compat/26.0/26.0.ignore.cil
@@ -5,6 +5,8 @@
 (typeattributeset new_objects
   ( adbd_exec
     bootloader_boot_reason_prop
+    bpfloader
+    bpfloader_exec
     broadcastradio_service
     cgroup_bpf
     crossprofileapps_service
diff --git a/private/file_contexts b/private/file_contexts
index 52003d6b752d301049cd69cb47c0b511057abe91..bebced685e57104e7feb82f3ccc9b3117f780715 100644
--- a/private/file_contexts
+++ b/private/file_contexts
@@ -283,6 +283,7 @@
 /system/bin/vold_prepare_subdirs u:object_r:vold_prepare_subdirs_exec:s0
 /system/bin/stats                u:object_r:stats_exec:s0
 /system/bin/statsd               u:object_r:statsd_exec:s0
+/system/bin/bpfloader            u:object_r:bpfloader_exec:s0
 
 #############################
 # Vendor files
diff --git a/private/netd.te b/private/netd.te
index f501f25e9f56361cb38813acec88f440a1ad7ee1..461d59b34c1c8fd29edb5f5e1d7b2a97ff4e5230 100644
--- a/private/netd.te
+++ b/private/netd.te
@@ -7,3 +7,6 @@ domain_auto_trans(netd, dnsmasq_exec, dnsmasq)
 
 # Allow netd to start clatd in its own domain
 domain_auto_trans(netd, clatd_exec, clatd)
+
+# Allow netd to start bpfloader_exec in its own domain
+domain_auto_trans(netd, bpfloader_exec, bpfloader)
diff --git a/public/netd.te b/public/netd.te
index d5d90a7df729b7fb201dee38479f480d1d1f03c9..0e9e08ca7f0772f62d97d17a0a87b9e8d7ecb082 100644
--- a/public/netd.te
+++ b/public/netd.te
@@ -7,7 +7,7 @@ net_domain(netd)
 allowxperm netd self:udp_socket ioctl priv_sock_ioctls;
 
 r_dir_file(netd, cgroup)
-r_dir_file(netd, cgroup_bpf)
+
 allow netd system_server:fd use;
 
 allow netd self:global_capability_class_set { net_admin net_raw kill };
@@ -105,7 +105,7 @@ allow netd netdomain:fd use;
 allow netd self:netlink_xfrm_socket { create_socket_perms_no_ioctl nlmsg_write nlmsg_read };
 
 # give netd permission to use eBPF functionalities
-allow netd self:bpf { map_create map_read map_write prog_load prog_run };
+allow netd self:bpf { map_create map_read map_write };
 
 # Allow netd to register as hal server.
 add_hwservice(netd, system_net_netd_hwservice)
@@ -132,6 +132,9 @@ neverallow netd { app_data_file system_data_file }:dir_file_class_set write;
 # only system_server and dumpstate may find netd service
 neverallow { domain -system_server -dumpstate -netd } netd_service:service_manager find;
 
+# only netd can create the bpf maps
+neverallow { domain -netd } netd:bpf { map_create };
+
 # apps may not interact with netd over binder.
 neverallow appdomain netd:binder call;
 neverallow netd { appdomain userdebug_or_eng(`-su') }:binder call;