diff options
author | Chenbo Feng <fengc@google.com> | 2017-03-22 17:27:35 -0700 |
---|---|---|
committer | David S. Miller <davem@davemloft.net> | 2017-03-23 17:01:02 -0700 |
commit | 6acc5c2910689fc6ee181bf63085c5efff6a42bd (patch) | |
tree | 049fec629362ea0f3017381bc96f4e117ed3e903 | |
parent | 91b8270f2a4d1d9b268de90451cdca63a70052d6 (diff) |
Add a eBPF helper function to retrieve socket uid
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 <fengc@google.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
-rw-r--r-- | include/uapi/linux/bpf.h | 9 | ||||
-rw-r--r-- | net/core/filter.c | 22 | ||||
-rw-r--r-- | tools/include/uapi/linux/bpf.h | 3 |
3 files changed, 32 insertions, 2 deletions
diff --git a/include/uapi/linux/bpf.h b/include/uapi/linux/bpf.h index cdfc5595fbc1..28317a04c34d 100644 --- a/include/uapi/linux/bpf.h +++ b/include/uapi/linux/bpf.h @@ -465,6 +465,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), \ @@ -513,7 +519,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 diff --git a/net/core/filter.c b/net/core/filter.c index 35b0f97c3fdf..dfb9f61a2fd5 100644 --- a/net/core/filter.c +++ b/net/core/filter.c @@ -2619,6 +2619,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) +{ + struct sock *sk = sk_to_full_sk(skb->sk); + kuid_t kuid; + + if (!sk || !sk_fullsock(sk)) + return overflowuid; + kuid = sock_net_uid(sock_net(sk), sk); + return from_kuid_munged(sock_net(sk)->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) { @@ -2655,6 +2673,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); } @@ -2716,6 +2736,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); } diff --git a/tools/include/uapi/linux/bpf.h b/tools/include/uapi/linux/bpf.h index a3851859e5f3..1ea08ce35567 100644 --- a/tools/include/uapi/linux/bpf.h +++ b/tools/include/uapi/linux/bpf.h @@ -507,7 +507,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 |