eBPF kernel code is tightly coupled with the regular linux kernel code i.e., it operates with the same priviledges and address space as the kernel. This means eBPF kernel code needs to adhere to the licensing restrictions of the kernel components whichever are applicable. For ebpf these kernel components are helper functions.
eBPF helper functions allows one to invoke kernel functions. These helper functions can either be GPLed or not and they have to explicitly define their license. For e.g.,:
static const struct bpf_func_proto bpf_probe_read_proto = { .func = bpf_probe_read, .gpl_only = true, .ret_type = RET_INTEGER, .arg1_type = ARG_PTR_TO_UNINIT_MEM, .arg2_type = ARG_CONST_SIZE_OR_ZERO, .arg3_type = ARG_ANYTHING, };
Notice the gpl_only
flag which is set to true in the above helper function,
which means that any eBPF code using bpf_probe_read
needs to be declared as
GPL too using:
char __license[] __attribute__((section("license"), used)) = "GPL";
In-kernel verifier will spit out the bytecode with an error, for e.g.,:
Verifier analysis: 0: (bf) r6 = r1 1: (61) r8 = *(u32 *)(r6 +80) 2: (61) r7 = *(u32 *)(r6 +76) 3: (b7) r1 = 686200 4: (63) *(u32 *)(r10 -12) = r1 5: (bf) r1 = r10 6: (07) r1 += -12 7: (b7) r2 = 4 8: (85) call bpf_trace_printk#6 cannot call GPL-restricted function from non-GPL compatible program processed 9 insns (limit 1000000) max_states_per_insn 0 total_states 0 peak_states 0 mark_read 0
In this case I used bpf_trace_printk
without declaring the "GPL" license
for ebpf kernel code.
This is tricky! GPL license says that if the userspace app is tightly coupled with the kernel space app using for e.g, shared memory or dependent APIs then the userspace app must be made available as GPL code. Since the userspace ebpf components interact with the kernel space component using maps and syscalls, doesn't this require userspace ebpf apps to be GPLed too?
There is a twist here! Kernel license makes an exception that any user-space component which interacts with kernel using system calls need not be called a "derived work". Userspace ebpf code interacts or accesses the kernel space bpf maps using system calls and thus may not be tied with GPL licensing.:
NOTE! This copyright does *not* cover user programs that use kernel services by normal system calls - this is merely considered normal use of the kernel, and does *not* fall under the heading of "derived work".
Most of the ebpf user-space code I have seen is not licensed as GPL (for e.g., from Cilium which is licensed as Apache 2.0).
<Assuming Kernel v5.3.0>
GPLed:
bpf_override_return bpf_probe_read bpf_probe_write_user bpf_trace_printk bpf_perf_event_read bpf_perf_event_read_value bpf_perf_event_output bpf_get_current_task bpf_probe_read_str bpf_perf_event_output_tp bpf_get_stackid_tp bpf_get_stack_tp bpf_perf_prog_read_value bpf_perf_event_output_raw_tp bpf_get_stackid_raw_tp bpf_get_stack_raw_tp bpf_rc_repeat bpf_rc_keydown bpf_rc_pointer_rel bpf_skb_event_output bpf_xdp_event_output bpf_sockopt_event_output bpf_xdp_fib_lookup bpf_skb_fib_lookup bpf_tcp_check_syncookie
Non-GPLed:
bpf_current_task_under_cgroup bpf_send_signal bpf_sysctl_get_name bpf_sysctl_get_current_value bpf_sysctl_get_new_value bpf_sysctl_set_new_value bpf_get_raw_cpu_id bpf_skb_store_bytes bpf_skb_load_bytes bpf_flow_dissector_load_bytes bpf_skb_load_bytes_relative bpf_skb_pull_data bpf_sk_fullsock sk_skb_pull_data bpf_l3_csum_replace bpf_l4_csum_replace bpf_csum_diff bpf_csum_update bpf_clone_redirect bpf_redirect bpf_msg_apply_bytes bpf_msg_cork_bytes bpf_msg_pull_data bpf_msg_push_data bpf_msg_pop_data bpf_get_cgroup_classid bpf_get_route_realm bpf_get_hash_recalc bpf_set_hash_invalid bpf_set_hash bpf_skb_vlan_push bpf_skb_vlan_pop bpf_skb_change_proto bpf_skb_change_type bpf_skb_adjust_room bpf_skb_change_tail sk_skb_change_tail bpf_skb_change_head sk_skb_change_head bpf_xdp_adjust_head bpf_xdp_adjust_tail bpf_xdp_adjust_meta bpf_xdp_redirect bpf_xdp_redirect_map bpf_skb_get_tunnel_key bpf_skb_get_tunnel_opt bpf_skb_set_tunnel_key bpf_skb_set_tunnel_opt bpf_skb_under_cgroup bpf_skb_cgroup_id bpf_skb_ancestor_cgroup_id bpf_get_socket_cookie bpf_get_socket_cookie_sock_addr bpf_get_socket_cookie_sock_ops bpf_get_socket_uid bpf_setsockopt bpf_getsockopt bpf_sock_ops_cb_flags_set bpf_bind bpf_skb_get_xfrm_state bpf_lwt_in_push_encap bpf_lwt_xmit_push_encap bpf_lwt_seg6_store_bytes bpf_lwt_seg6_action bpf_lwt_seg6_adjust_srh bpf_skc_lookup_tcp bpf_sk_lookup_tcp bpf_sk_lookup_udp bpf_sk_release bpf_xdp_sk_lookup_udp bpf_xdp_skc_lookup_tcp bpf_xdp_sk_lookup_tcp bpf_sock_addr_skc_lookup_tcp bpf_sock_addr_sk_lookup_tcp bpf_sock_addr_sk_lookup_udp bpf_get_listener_sock bpf_skb_ecn_set_ce sk_select_reuseport sk_reuseport_load_bytes sk_reuseport_load_bytes_relative