BPF程序类型
BPF没有明确的分类,可以将其分为两类:
跟踪
提供系统行为及系统硬件的直接信息。也可以访问特定程序的内存区域,从运行进程中提取执行跟踪信息,还可以访问进程分配的特定资源,文件描述符、cpu、内存。
网络
检测和控制系统的网络流量。可以对网络接口数据包进行过滤,甚至可以完全拒绝数据包。
BPF程序可以附加到网络驱动程序接收数据包的网络事件中,也可以附加到数据包传递给用户空间的网络事件。
man bpf 获得更多知识:
各种类型添加到内核的时间顺序来进行介绍:
参考:https://github.com/DavadDi/bpf_study/blob/5d30702c6c1eb884326d933c401c162163d85936/bpf-prog-type.md#bpf-程序类型支持-helper-函数列表
- 套接字过滤器程序
BPF_PROG_TYPE_SOCKET_FILTER类型用于访问所有套接字处理的数据包,只能用于观测,不能修改数据包的内容或者更改目的地。
BPF_PROG_TYPE_SOCKET_FILTER:
BPF_FUNC_skb_load_bytes()
BPF_FUNC_skb_load_bytes_relative()
BPF_FUNC_get_socket_cookie()
BPF_FUNC_get_socket_uid()
BPF_FUNC_perf_event_output()
Base functions
- kprobe程序
kprobe是动态附加到内核调用点的函数。bpf虚拟机总是确kprobe能够安全的运行,但是内核kprobe被认为是不稳定的入口点,需要确定程序是否与内核相兼容。
BPF_PROG_TYPE_KPROBE:
BPF_FUNC_perf_event_output()
BPF_FUNC_get_stackid()
BPF_FUNC_get_stack()
BPF_FUNC_perf_event_read_value()
BPF_FUNC_override_return()
Tracing functions
如果需要检查exec系统调用的返回值,需要BPF程序设置sec头部,SEC("kretprobe/sys_exec")
- 跟踪点程序
跟踪点程序会俯角到内核提供的跟踪点处理程序上。是内核代码的静态标记,允许注入跟踪和调试相关的任意代码。可以编写一个BPF程序来检查其他BPF程序的行为。
BPF_PROG_TYPE_TRACEPOINT:
BPF_FUNC_perf_event_output()
BPF_FUNC_get_stackid()
BPF_FUNC_get_stack()
Tracing functions
- XDP程序
当网络包到达内核时,xdp程序会在早起被执行, 此时,内核还没有对数据包本身进行太多的处理,所以数据包的信息展示有限,但是具有更高级别的控制。
BPF_PROG_TYPE_XDP:
BPF_FUNC_perf_event_output()
BPF_FUNC_get_smp_processor_id()
BPF_FUNC_csum_diff()
BPF_FUNC_xdp_adjust_head()
BPF_FUNC_xdp_adjust_meta()
BPF_FUNC_redirect()
BPF_FUNC_redirect_map()
BPF_FUNC_xdp_adjust_tail()
BPF_FUNC_fib_lookup()
Base functions
- perf 事件程序
将bpf代码附加到perf事件上,使用perf事件程序监控很多系统信息。
BPF_PROG_TYPE_PERF_EVENT:
BPF_FUNC_perf_event_output()
BPF_FUNC_get_stackid()
BPF_FUNC_get_stack()
BPF_FUNC_perf_prog_read_value()
Tracing functions
- cgroup套接字程序
该程序允许cgroup在其包含的进程中控制网络流量。在传入cgroup控制之前,通过cgroup套接字程序,可以决定如何处理这些数据包。cilium使用cgroup套接字程序将策略应用进程组上,而不是在隔离的容器上。
BPF_PROG_TYPE_CGROUP_SKB:
BPF_FUNC_skb_load_bytes()
BPF_FUNC_skb_load_bytes_relative()
BPF_FUNC_get_socket_cookie()
BPF_FUNC_get_socket_uid()
Base functions
- cgroup 打开套接字程序
允许cgroup内的任何进程打开网络套接字时执行代码。可以对打开套接字程序组提供安全性和访问控制,而不必单独限制每个进程的功能。
BPF_PROG_TYPE_CGROUP_SOCK :
BPF_FUNC_get_current_uid_gid()
Base functions
- 套接字选项程序
允许运行时修改套接字链接选项,可以访网络IP地址和链接端口之类的数据,并且还可以修改链接选项,设置超时,以及更改给定数据包往返延迟时间。
BPF_PROG_TYPE_SOCK_OPS :
BPF_FUNC_setsockopt()
BPF_FUNC_getsockopt()
BPF_FUNC_sock_ops_cb_flags_set()
BPF_FUNC_sock_map_update()
BPF_FUNC_sock_hash_update()
BPF_FUNC_get_socket_cookie()
Base functions
- 套接字映射程序
套接字映射可以保留对一些套接字的引用。使用这些引用和特性的帮助函数将套接字的数据包重定向到其他的套接字。以下两个项目是使用此功能,实现负载均衡等。
https://github.com/cilium/cilium.git
https://github.com/facebookincubator/katran.git
BPF_PROG_TYPE_SK_SKB :
BPF_FUNC_skb_store_bytes()
BPF_FUNC_skb_load_bytes()
BPF_FUNC_skb_pull_data()
BPF_FUNC_skb_change_tail()
BPF_FUNC_skb_change_head()
BPF_FUNC_get_socket_cookie()
BPF_FUNC_get_socket_uid()
BPF_FUNC_sk_redirect_map()
BPF_FUNC_sk_redirect_hash()
BPF_FUNC_sk_lookup_tcp()
BPF_FUNC_sk_lookup_udp()
BPF_FUNC_sk_release()
Base functions
- cgroup 设备程序
决定是否能够给定设备上执行cgroup中的操作。cgroups(v1)的第一个实现允许为特定设备设置权限。但是第二个迭代中缺少了这个功能。
BPF_PROG_TYPE_CGROUP_DEVICE :
BPF_FUNC_map_lookup_elem()
BPF_FUNC_map_update_elem()
BPF_FUNC_map_delete_elem()
BPF_FUNC_get_current_uid_gid()
BPF_FUNC_trace_printk()
- 套接字消息传递程序
控制是否将消息发送到套接字。
BPF_PROG_TYPE_SK_MSG :
BPF_FUNC_msg_redirect_map()
BPF_FUNC_msg_redirect_hash()
BPF_FUNC_msg_apply_bytes()
BPF_FUNC_msg_cork_bytes()
BPF_FUNC_msg_pull_data()
BPF_FUNC_msg_push_data()
BPF_FUNC_msg_pop_data()
Base functions
- 原始跟踪点程序
程序能够提供内核执行任务的更多信息,但是会有少许性能开销。
BPF_PROG_TYPE_RAW_TRACEPOINT :
BPF_FUNC_perf_event_output()
BPF_FUNC_get_stackid()
BPF_FUNC_get_stack()
BPF_FUNC_skb_output()
Tracing functions
- cgroup套接字地址程序
允许cgroup控制的用户控件程序的IP地址和端口号。当系统使用多个IP时,可以确保一组特定的用户控件程序使用相同的IP地址和端口。
BPF_PROG_TYPE_CGROUP_SOCK_ADDR :
BPF_FUNC_get_current_uid_gid()
BPF_FUNC_bind()
BPF_FUNC_get_socket_cookie()
Base functions
- 套接字重用端口程序
允许相同的主机上多个进程绑定相同的端口。在高并发情况下,我们可以使用多个线程处理负载。
BPF_PROG_TYPE_SK_REUSEPORT :
BPF_FUNC_sk_select_reuseport()
BPF_FUNC_skb_load_bytes()
BPF_FUNC_load_bytes_relative()
Base functions
- 流量解析程序
跟踪网络数据包经过不同的层,从网络数据包到达系统再到数据包发送给用户空间程序。将程序裸机挂钩到流量解析器的路径上,提供了内置解析器没有的安全保证。
BPF_PROG_TYPE_FLOW_DISSECTOR :
BPF_FUNC_skb_load_bytes()
Base functions
- 其他
BPF_PROG_TYPE_LWT_SEG6LOCAL :
BPF_FUNC_lwt_seg6_store_bytes()
BPF_FUNC_lwt_seg6_action()
BPF_FUNC_lwt_seg6_adjust_srh()
LWT functions
BPF_PROG_TYPE_LIRC_MODE2 :
BPF_FUNC_rc_repeat()
BPF_FUNC_rc_keydown()
BPF_FUNC_rc_pointer_rel()
BPF_FUNC_map_lookup_elem()
BPF_FUNC_map_update_elem()
BPF_FUNC_map_delete_elem()
BPF_FUNC_ktime_get_ns()
BPF_FUNC_tail_call()
BPF_FUNC_get_prandom_u32()
BPF_FUNC_trace_printk()
BPF_PROG_TYPE_LWT_IN :
BPF_FUNC_lwt_push_encap()
LWT functions
Base functions
BPF_PROG_TYPE_LWT_OUT :
LWT functions
Base functions
BPF_PROG_TYPE_LWT_XMIT :
BPF_FUNC_skb_get_tunnel_key()
BPF_FUNC_skb_set_tunnel_key()
BPF_FUNC_skb_get_tunnel_opt()
BPF_FUNC_skb_set_tunnel_opt()
BPF_FUNC_redirect()
BPF_FUNC_clone_redirect()
BPF_FUNC_skb_change_tail()
BPF_FUNC_skb_change_head()
BPF_FUNC_skb_store_bytes()
BPF_FUNC_csum_update()
BPF_FUNC_l3_csum_replace()
BPF_FUNC_l4_csum_replace()
BPF_FUNC_set_hash_invalid()
LWT functions
BPF_PROG_TYPE_SCHED_CLS 、 BPF_PROG_TYPE_SCHED_ACT :
BPF_FUNC_skb_store_bytes()
BPF_FUNC_skb_load_bytes()
BPF_FUNC_skb_load_bytes_relative()
BPF_FUNC_skb_pull_data()
BPF_FUNC_csum_diff()
BPF_FUNC_csum_update()
BPF_FUNC_l3_csum_replace()
BPF_FUNC_l4_csum_replace()
BPF_FUNC_clone_redirect()
BPF_FUNC_get_cgroup_classid()
BPF_FUNC_skb_vlan_push()
BPF_FUNC_skb_vlan_pop()
BPF_FUNC_skb_change_proto()
BPF_FUNC_skb_change_type()
BPF_FUNC_skb_adjust_room()
BPF_FUNC_skb_change_tail()
BPF_FUNC_skb_get_tunnel_key()
BPF_FUNC_skb_set_tunnel_key()
BPF_FUNC_skb_get_tunnel_opt()
BPF_FUNC_skb_set_tunnel_opt()
BPF_FUNC_redirect()
BPF_FUNC_get_route_realm()
BPF_FUNC_get_hash_recalc()
BPF_FUNC_set_hash_invalid()
BPF_FUNC_set_hash()
BPF_FUNC_perf_event_output()
BPF_FUNC_get_smp_processor_id()
BPF_FUNC_skb_under_cgroup()
BPF_FUNC_get_socket_cookie()
BPF_FUNC_get_socket_uid()
BPF_FUNC_fib_lookup()
BPF_FUNC_skb_get_xfrm_state()
BPF_FUNC_skb_cgroup_id()
Base functions
BPF能够允许任何人在linux内核中执行任意代码,那么安全性怎么保证呢?
CVE-2017-16995 https://cve.mitre.org/cgi-bin/cvename.cgi?name=CVE-2017-16995