net: core: Two Helper function about socket information
Subsystems (5)
v5 cover net: core: Two Helper function about socket information
From: Chenbo Feng <[email protected]>
Introduce two eBpf helper function to get the socket cookie and socket uid for each packet. The helper function is useful when the *sk field inside sk_buff is not empty. These helper functions can be used on socket and uid based traffic monitoring programs.
Change since V4:
* Using current user namespace to get uid instead of using init_ns.
* Add compiling setup of example program in to Makefile.
* Change the name style of the example program binaries.
Change since V3:
* Fixed some typos and incorrect comments in sample program
* replaced raw insns with BPF_STX_XADD and add it to libbpf.h
* Use a temp dir as mount point instead and added a check for the user input string.
* Make the get uid helper function returns the user namespace uid instead of kuid.
* Return a overflowuid instead of 0 when no uid information is found.
Change since V2:
* Add a sample program to demostrate the usage of the helper function.
* Moved the helper function proto invoking place.
* Add function header into tools/include
* Apply sk_to_full_sk() before getting uid.
Change since V1:
* Removed the unnecessary declarations and export command
* resolved conflict with master branch.
* Examine if the socket is a full socket before getting the uid.
Chenbo Feng (3):
Add a helper function to get socket cookie in eBPF Add a eBPF helper function to retrieve socket uid
A Sample of using socket cookie and uid for traffic monitoring
include/linux/sock_diag.h | 1 + include/uapi/linux/bpf.h | 16 +- net/core/filter.c | 39 +++++ net/core/sock_diag.c | 2 +- samples/bpf/Makefile | 3 + samples/bpf/cookie_uid_helper_example.c | 223 +++++++++++++++++++++++++++ samples/bpf/libbpf.h | 10 ++ samples/bpf/run_cookie_uid_helper_example.sh | 14 ++ tools/include/uapi/linux/bpf.h | 4 +- 9 files changed, 309 insertions(+), 3 deletions(-) create mode 100644 samples/bpf/cookie_uid_helper_example.c create mode 100755 samples/bpf/run_cookie_uid_helper_example.sh
Signature · 1 line
2.7.4
PATCH v5 1/3 Add a helper function to get socket cookie in eBPF
From: Chenbo Feng <[email protected]>
Retrieve the socket cookie generated by sock_gen_cookie() from a sk_buff with a known socket. Generates a new cookie if one was not yet set.If the socket pointer inside sk_buff is NULL, 0 is returned. The helper function coud be useful in monitoring per socket networking traffic statistics and provide a unique socket identifier per namespace.
--- include/linux/sock_diag.h | 1 + include/uapi/linux/bpf.h | 9 ++++++++- net/core/filter.c | 17 +++++++++++++++++ net/core/sock_diag.c | 2 +- tools/include/uapi/linux/bpf.h | 3 ++- 5 files changed, 29 insertions(+), 3 deletions(-)
include/linux/sock_diag.h +1 -0
@@ -24,6 +24,7 @@ void sock_diag_unregister(const struct sock_diag_handler *h);void sock_diag_register_inet_compat (int (*fn)(struct sk_buff *skb,struct nlmsghdr *nlh));void sock_diag_unregister_inet_compat (int (*fn)(struct sk_buff *skb,struct nlmsghdr *nlh)); +u64 sock_gen_cookie (struct sock *sk);int sock_diag_check_cookie (struct sock *sk,const __u32 *cookie);void sock_diag_save_cookie (struct sock *sk,__u32 *cookie);
include/uapi/linux/bpf.h +8 -1
@@ -456,6 +456,12 @@ union bpf_attr {* Return: * > 0 length of the string including the trailing NUL on success * < 0 error +* +* u64 bpf_bpf_get_socket_cookie(skb) +* Get the cookie for the socket stored inside sk_buff. +* @skb: pointer to skb +* Return: 8 Bytes non-decreasing number on success or 0 if the socket +* field is missing inside sk_buff */ #define __BPF_FUNC_MAPPER (FN ) \ FN(unspec), \
@@ -503,7 +509,8 @@ union bpf_attr {FN (get_numa_node_id), \FN (skb_change_head), \FN (xdp_adjust_head), \ -FN (probe_read_str), +FN (probe_read_str), \ +FN (get_socket_cookie),/* integer value in 'imm' field of BPF_CALL instruction selects which helper * function eBPF program intends to call
net/core/filter.c +17 -0
@@ -26,6 +26,7 @@#include <linux/mm.h> #include <linux/fcntl.h> #include <linux/socket.h> +#include <linux/sock_diag.h> #include <linux/in.h> #include <linux/inet.h> #include <linux/netdevice.h>
@@ -2599,6 +2600,18 @@ static const struct bpf_func_proto bpf_xdp_event_output_proto = { .arg5_type = ARG_CONST_SIZE, }; +BPF_CALL_1(bpf_get_socket_cookie, struct sk_buff *, skb) +{ +return skb->sk ?sock_gen_cookie (skb->sk) :0 ; +} + +static const struct bpf_func_proto bpf_get_socket_cookie_proto = { + .func = bpf_get_socket_cookie, + .gpl_only = false, + .ret_type =RET_INTEGER , + .arg1_type =ARG_PTR_TO_CTX , +}; +static const struct bpf_func_proto *bpf_base_func_proto (enum bpf_func_id func_id) {
@@ -2633,6 +2646,8 @@ sk_filter_func_proto(enum bpf_func_id func_id)switch (func_id) {case BPF_FUNC_skb_load_bytes:return &bpf_skb_load_bytes_proto; +case BPF_FUNC_get_socket_cookie: +return &bpf_get_socket_cookie_proto;default :return bpf_base_func_proto (func_id); }
@@ -2692,6 +2707,8 @@ tc_cls_act_func_proto(enum bpf_func_id func_id)return &bpf_get_smp_processor_id_proto;case BPF_FUNC_skb_under_cgroup:return &bpf_skb_under_cgroup_proto; +case BPF_FUNC_get_socket_cookie: +return &bpf_get_socket_cookie_proto;default :return bpf_base_func_proto (func_id); }
net/core/sock_diag.c +1 -1
@@ -19,7 +19,7 @@ static int (*inet_rcv_compat)(struct sk_buff *skb, struct nlmsghdr *nlh);static DEFINE_MUTEX (sock_diag_table_mutex);static struct workqueue_struct *broadcast_wq; -static u64 sock_gen_cookie (struct sock *sk) +u64 sock_gen_cookie (struct sock *sk) {while (1 ) {u64 res =atomic64_read (&sk->sk_cookie);
tools/include/uapi/linux/bpf.h +2 -1
@@ -503,7 +503,8 @@ union bpf_attr {FN (get_numa_node_id), \FN (skb_change_head), \FN (xdp_adjust_head), \ -FN (probe_read_str), +FN (probe_read_str), \ +FN (get_socket_cookie),/* integer value in 'imm' field of BPF_CALL instruction selects which helper * function eBPF program intends to call
Signature · 1 line
2.7.4
Re: [PATCH net-next v5 1/3] Add a helper function to get socket cookie in eBPF
Quoted 9 lines · Chenbo Feng
From: Chenbo Feng <[email protected]>
Retrieve the socket cookie generated by
sock_gen_cookie()from ask_buffwith a known socket. Generates a new cookie if one was not yet set.If the socket pointer insidesk_buffis NULL, 0 is returned. The helper function coud be useful in monitoring per socket networking traffic statistics and provide a unique socket identifier per namespace.Signed-off-by Chenbo Feng <[email protected]>
PATCH v5 2/3 Add a eBPF helper function to retrieve socket uid
In reply to Chenbo FengFrom: Chenbo Feng <[email protected]>
Returns the owner uid of the socket inside a sk_buff. This is useful to perform per-UID accounting of network traffic or per-UID packet filtering. The socket need to be a fullsock otherwise overflowuid is returned.
--- include/uapi/linux/bpf.h | 9 ++++++++- net/core/filter.c | 22 ++++++++++++++++++++++ tools/include/uapi/linux/bpf.h | 3 ++- 3 files changed, 32 insertions(+), 2 deletions(-)
include/uapi/linux/bpf.h +8 -1
@@ -462,6 +462,12 @@ union bpf_attr {* @skb: pointer to skb * Return: 8 Bytes non-decreasing number on success or 0 if the socket * field is missing inside sk_buff +* +* u32 bpf_get_socket_uid(skb) +* Get the owner uid of the socket stored inside sk_buff. +* @skb: pointer to skb +* Return: uid of the socket owner on success or 0 if the socket pointer +* inside sk_buff is NULL */ #define __BPF_FUNC_MAPPER (FN ) \ FN(unspec), \
@@ -510,7 +516,8 @@ union bpf_attr {FN (skb_change_head), \FN (xdp_adjust_head), \FN (probe_read_str), \ -FN (get_socket_cookie), +FN (get_socket_cookie), \ +FN (get_socket_uid),/* integer value in 'imm' field of BPF_CALL instruction selects which helper * function eBPF program intends to call
net/core/filter.c +22 -0
@@ -2612,6 +2612,24 @@ static const struct bpf_func_proto bpf_get_socket_cookie_proto = { .arg1_type = ARG_PTR_TO_CTX, }; +BPF_CALL_1(bpf_get_socket_uid, struct sk_buff *, skb) +{ +kuid_t kuid; +struct sock *sk =sk_to_full_sk (skb->sk); + +if (!sk || !sk_fullsock (sk)) +return overflowuid; + kuid =sock_net_uid (sock_net (sk), sk); +return from_kuid_munged (current_user_ns (), kuid); +} + +static const struct bpf_func_proto bpf_get_socket_uid_proto = { + .func = bpf_get_socket_uid, + .gpl_only = false, + .ret_type =RET_INTEGER , + .arg1_type =ARG_PTR_TO_CTX , +}; +static const struct bpf_func_proto *bpf_base_func_proto (enum bpf_func_id func_id) {
@@ -2648,6 +2666,8 @@ sk_filter_func_proto(enum bpf_func_id func_id)return &bpf_skb_load_bytes_proto;case BPF_FUNC_get_socket_cookie:return &bpf_get_socket_cookie_proto; +case BPF_FUNC_get_socket_uid: +return &bpf_get_socket_uid_proto;default :return bpf_base_func_proto (func_id); }
@@ -2709,6 +2729,8 @@ tc_cls_act_func_proto(enum bpf_func_id func_id)return &bpf_skb_under_cgroup_proto;case BPF_FUNC_get_socket_cookie:return &bpf_get_socket_cookie_proto; +case BPF_FUNC_get_socket_uid: +return &bpf_get_socket_uid_proto;default :return bpf_base_func_proto (func_id); }
tools/include/uapi/linux/bpf.h +2 -1
@@ -504,7 +504,8 @@ union bpf_attr {FN (skb_change_head), \FN (xdp_adjust_head), \FN (probe_read_str), \ -FN (get_socket_cookie), +FN (get_socket_cookie), \ +FN (get_socket_uid),/* integer value in 'imm' field of BPF_CALL instruction selects which helper * function eBPF program intends to call
Signature · 1 line
2.7.4
Re: [PATCH net-next v5 2/3] Add a eBPF helper function to retrieve socket uid
Quoted 46 lines · Chenbo Feng
From: Chenbo Feng <[email protected]>
Returns the owner uid of the socket inside a
sk_buff. This is useful to perform per-UID accounting of network traffic or per-UID packet filtering. The socket need to be a fullsock otherwise overflowuid is returned.Signed-off-by Chenbo Feng <[email protected]>--- include/uapi/linux/bpf.h | 9 ++++++++- net/core/filter.c | 22 ++++++++++++++++++++++ tools/include/uapi/linux/bpf.h | 3 ++- 3 files changed, 32 insertions(+), 2 deletions(-)include/uapi/linux/bpf.h +8
-1@@ -462,6 +462,12 @@ union bpf_attr {* @skb: pointer to skb * Return: 8 Bytes non-decreasing number on success or 0 if the socket * field is missing inside sk_buff +* +* u32 bpf_get_socket_uid(skb) +* Get the owner uid of the socket stored inside sk_buff. +* @skb: pointer to skb +* Return: uid of the socket owner on success or 0 if the socket pointer +* inside sk_buff is NULL */ #define __BPF_FUNC_MAPPER (FN ) \ FN(unspec), \@@ -510,7 +516,8 @@ union bpf_attr {FN (skb_change_head), \FN (xdp_adjust_head), \FN (probe_read_str), \ -FN (get_socket_cookie), +FN (get_socket_cookie), \ +FN (get_socket_uid),/* integer value in 'imm' field of BPF_CALL instruction selects which helper * function eBPF program intends to call net/core/filter.c +0
-0
net/core/filter.c static const struct bpf_func_proto bpf_get_socket_cookie_proto = { · line 2618
Quoted 7 lines
net/core/filter.c +4
-0@@ -2612,6 +2612,24 @@ static const struct bpf_func_proto bpf_get_socket_cookie_proto = { .arg1_type = ARG_PTR_TO_CTX, }; +BPF_CALL_1(bpf_get_socket_uid, struct sk_buff *, skb) +{ +kuid_t kuid; +struct sock *sk =sk_to_full_sk (skb->sk);
Minor nit, please change the order into:
struct sock *sk = sk_to_full_sk(skb->sk); kuid_t kuid;
net/core/filter.c static const struct bpf_func_proto bpf_get_socket_cookie_proto = { · line 2632
Quoted 13 lines
net/core/filter.c +13
-0+if (!sk || !sk_fullsock (sk)) +return overflowuid; + kuid =sock_net_uid (sock_net (sk), sk); +return from_kuid_munged (current_user_ns (), kuid); +} + +static const struct bpf_func_proto bpf_get_socket_uid_proto = { + .func = bpf_get_socket_uid, + .gpl_only = false, + .ret_type =RET_INTEGER , + .arg1_type =ARG_PTR_TO_CTX , +}; +
Rest looks good, thanks.
PATCH v5 3/3 A Sample of using socket cookie and uid for traffic monitoring
In reply to Chenbo FengFrom: Chenbo Feng <[email protected]>
Add a sample program to demostrate the possible usage of get_socket_cookie and get_socket_uid helper function. The program will store bytes and packets counting of in/out traffic monitored by iptables and store the stats in a bpf map in per socket base. The owner uid of the socket will be stored as part of the data entry. A shell script for running the program is also included.
--- samples/bpf/Makefile | 3 + samples/bpf/cookie_uid_helper_example.c | 223 +++++++++++++++++++++++++++ samples/bpf/libbpf.h | 10 ++ samples/bpf/run_cookie_uid_helper_example.sh | 14 ++ 4 files changed, 250 insertions(+) create mode 100644 samples/bpf/cookie_uid_helper_example.c create mode 100755 samples/bpf/run_cookie_uid_helper_example.sh
samples/bpf/Makefile +3 -0
@@ -34,6 +34,7 @@ hostprogs-y += sampleip hostprogs-y += tc_l2_redirect hostprogs-y += lwt_len_hist hostprogs-y += xdp_tx_iptunnel +hostprogs-y += per_socket_stats_example # Libbpf dependencies LIBBPF := ../../tools/lib/bpf/bpf.o
@@ -72,6 +73,7 @@ sampleip-objs := bpf_load.o $(LIBBPF) sampleip_user.o tc_l2_redirect-objs := bpf_load.o $(LIBBPF) tc_l2_redirect_user.o lwt_len_hist-objs := bpf_load.o $(LIBBPF) lwt_len_hist_user.o xdp_tx_iptunnel-objs := bpf_load.o $(LIBBPF) xdp_tx_iptunnel_user.o +per_socket_stats_example-objs := $(LIBBPF) cookie_uid_helper_example.o # Tell kbuild to always build the programs always := $(hostprogs-y)
@@ -105,6 +107,7 @@ always += trace_event_kern.o always += sampleip_kern.o always += lwt_len_hist_kern.o always += xdp_tx_iptunnel_kern.o +always += cookie_uid_helper_example.o HOSTCFLAGS += -I$(objtree)/usr/include HOSTCFLAGS += -I$(srctree)/tools/lib/
samples/bpf/cookie_uid_helper_example.c new file +223 -0
223 lines not on this page · raw message
samples/bpf/libbpf.h +10 -0
@@ -135,6 +135,16 @@ struct bpf_insn; .off = OFF, \ .imm = 0 }) +/* Atomic memory add, *(uint *)(dst_reg + off16) += src_reg */ + +#define BPF_STX_XADD (SIZE ,DST ,SRC ,OFF ) \ + ((struct bpf_insn) { \ + .code = BPF_STX | BPF_SIZE(SIZE) | BPF_XADD, \ + .dst_reg = DST, \ + .src_reg = SRC, \ + .off = OFF, \ + .imm = 0 }) +/* Memory store, *(uint *) (dst_reg + off16) = imm32 */ #define BPF_ST_MEM (SIZE ,DST ,OFF ,IMM ) \
samples/bpf/run_cookie_uid_helper_example.sh new file +14 -0
@@ -0,0 +1,14 @@ +#!/bin/bash +local_dir="$(pwd)" +root_dir=$local_dir/../.. +mnt_dir=$(mktemp -d --tmp) + +on_exit() { + iptables -D INPUT -m bpf --object-pinned ${mnt_dir}/bpf_prog -j ACCEPT + umount ${mnt_dir} + rm -r ${mnt_dir} +} + +trap on_exit EXIT +mount -t bpf bpf ${mnt_dir} +./per_socket_stats_example ${mnt_dir}/bpf_prog
Signature · 1 line
2.7.4
Daniel Borkmann
maintainerRe: [PATCH net-next v5 3/3] A Sample of using socket cookie and uid for traffic monitoring
Quoted 10 lines · Chenbo Feng
From: Chenbo Feng <[email protected]>
Add a sample program to demostrate the possible usage of
get_socket_cookieandget_socket_uidhelper function. The program will store bytes and packets counting of in/out traffic monitored by iptables and store the stats in a bpf map in per socket base. The owner uid of the socket will be stored as part of the data entry. A shell script for running the program is also included.Signed-off-by Chenbo Feng <[email protected]>
[...]
Quoted 5 lines
samples/bpf/cookie_uid_helper_example.c new file +5
-0+int main (int argc,char *argv[]) +{ +if (argc >2 ) { +printf ("Too many argument provided\n" ); +return 1 ;
[...]
samples/bpf/cookie_uid_helper_example.c line 223
Quoted 9 lines
samples/bpf/cookie_uid_helper_example.c new file +9
-0+ +return 0 ; +} + + + + + +
Did these bits slip in accidentally?
Quoted 8 lines
samples/bpf/libbpf.h +0
-0@@ -135,6 +135,16 @@ struct bpf_insn; .off = OFF, \ .imm = 0 })
[...]