未验证 提交 a8f4a42f 编写于 作者: O openeuler-ci-bot 提交者: Gitee

!1443 backport sockmap feature patches from OLK-5.10

Merge Pull Request from: @kwb0523 
 
add gid field in sock;
add bpf_get_sockops_uid_gid and bpf_sk_original_addr helper function;
original issue:https://gitee.com/openeuler/kernel/issues/I545NW 
 
Link:https://gitee.com/openeuler/kernel/pulls/1443 

Reviewed-by: Wei Li <liwei391@huawei.com> 
Signed-off-by: Wei Li <liwei391@huawei.com> 
......@@ -381,4 +381,8 @@ int nf_ct_handle_fragments(struct net *net, struct sk_buff *skb,
#define MODULE_ALIAS_NFCT_HELPER(helper) \
MODULE_ALIAS("nfct-helper-" helper)
typedef int (*bpf_getorigdst_opt_func)(struct sock *sk, int optname,
void *optval, int *optlen, int dir);
extern bpf_getorigdst_opt_func bpf_getorigdst_opt;
#endif /* _NF_CONNTRACK_H */
......@@ -300,6 +300,7 @@ struct sk_filter;
* @sk_ack_backlog: current listen backlog
* @sk_max_ack_backlog: listen backlog set in listen()
* @sk_uid: user id of owner
* @sk_gid: group id of owner
* @sk_prefer_busy_poll: prefer busypolling over softirq processing
* @sk_busy_poll_budget: napi processing budget when busypolling
* @sk_priority: %SO_PRIORITY setting
......@@ -543,6 +544,10 @@ struct sock {
struct bpf_local_storage __rcu *sk_bpf_storage;
#endif
struct rcu_head sk_rcu;
union {
kgid_t sk_gid;
u64 sk_gid_padding;
};
netns_tracker ns_tracker;
struct hlist_node sk_bind2_node;
};
......@@ -2095,6 +2100,7 @@ static inline void sock_graft(struct sock *sk, struct socket *parent)
parent->sk = sk;
sk_set_socket(sk, parent);
sk->sk_uid = SOCK_INODE(parent)->i_uid;
sk->sk_gid = SOCK_INODE(parent)->i_gid;
security_sock_graft(sk, parent);
write_unlock_bh(&sk->sk_callback_lock);
}
......@@ -2107,6 +2113,11 @@ static inline kuid_t sock_net_uid(const struct net *net, const struct sock *sk)
return sk ? sk->sk_uid : make_kuid(net->user_ns, 0);
}
static inline kgid_t sock_net_gid(const struct net *net, const struct sock *sk)
{
return sk ? sk->sk_gid : make_kgid(net->user_ns, 0);
}
static inline u32 net_tx_rndhash(void)
{
u32 v = get_random_u32();
......
......@@ -5559,6 +5559,19 @@ union bpf_attr {
* 0 on success.
*
* **-ENOENT** if the bpf_local_storage cannot be found.
*
* u64 bpf_get_sockops_uid_gid(void *sockops)
* Description
* Get sock's uid and gid
* Return
* A 64-bit integer containing the current GID and UID, and
* created as such: *current_gid* **<< 32 \|** *current_uid*.
*
* int bpf_sk_original_addr(void *bpf_socket, int optname, char *optval, int optlen)
* Description
* Get Ipv4 origdst or replysrc. Works with IPv4.
* Return
* 0 on success, or a negative error in case of failure.
*/
#define ___BPF_FUNC_MAPPER(FN, ctx...) \
FN(unspec, 0, ##ctx) \
......@@ -5773,6 +5786,8 @@ union bpf_attr {
FN(user_ringbuf_drain, 209, ##ctx) \
FN(cgrp_storage_get, 210, ##ctx) \
FN(cgrp_storage_delete, 211, ##ctx) \
FN(get_sockops_uid_gid, 212, ##ctx) \
FN(sk_original_addr, 213, ##ctx) \
/* */
/* backwards-compatibility macros for users of __BPF_FUNC_MAPPER that don't
......
......@@ -50,6 +50,8 @@ enum nf_ip_hook_priorities {
/* 2.2 firewalling (+ masq) went from 64 through 76 */
/* 2.4 firewalling went 64 through 67. */
#define SO_ORIGINAL_DST 80
#define BPF_SO_ORIGINAL_DST 800
#define BPF_SO_REPLY_SRC 801
#endif /* _UAPI__LINUX_IP_NETFILTER_H */
......@@ -5487,6 +5487,76 @@ static const struct bpf_func_proto bpf_sock_addr_setsockopt_proto = {
.arg5_type = ARG_CONST_SIZE,
};
BPF_CALL_1(bpf_get_sockops_uid_gid, struct bpf_sock_ops_kern *, bpf_sock)
{
struct sock *sk = bpf_sock->sk;
kuid_t uid;
kgid_t gid;
if (!sk || !sk_fullsock(sk))
return -EINVAL;
uid = sock_net_uid(sock_net(sk), sk);
gid = sock_net_gid(sock_net(sk), sk);
return ((u64)from_kgid_munged(sock_net(sk)->user_ns, gid)) << 32 |
from_kuid_munged(sock_net(sk)->user_ns, uid);
}
static const struct bpf_func_proto bpf_get_sockops_uid_gid_proto = {
.func = bpf_get_sockops_uid_gid,
.gpl_only = false,
.ret_type = RET_INTEGER,
.arg1_type = ARG_PTR_TO_CTX,
};
#include <net/netfilter/nf_conntrack.h>
#include <linux/netfilter_ipv4.h>
bpf_getorigdst_opt_func bpf_getorigdst_opt;
EXPORT_SYMBOL(bpf_getorigdst_opt);
BPF_CALL_4(bpf_sk_original_addr, struct bpf_sock_ops_kern *, bpf_sock,
int, optname, char *, optval, int, optlen)
{
struct sock *sk = bpf_sock->sk;
int ret = -EINVAL;
if (!sk_fullsock(sk))
goto err_clear;
if (optname != BPF_SO_ORIGINAL_DST && optname != BPF_SO_REPLY_SRC)
goto err_clear;
if (!bpf_getorigdst_opt)
goto err_clear;
#if IS_ENABLED(CONFIG_NF_CONNTRACK)
if (optname == BPF_SO_ORIGINAL_DST)
ret = bpf_getorigdst_opt(sk, optname, optval, &optlen,
IP_CT_DIR_ORIGINAL);
else if (optname == BPF_SO_REPLY_SRC)
ret = bpf_getorigdst_opt(sk, optname, optval, &optlen,
IP_CT_DIR_REPLY);
if (ret < 0)
goto err_clear;
return 0;
#endif
err_clear:
memset(optval, 0, optlen);
return ret;
}
static const struct bpf_func_proto bpf_sk_original_addr_proto = {
.func = bpf_sk_original_addr,
.gpl_only = false,
.ret_type = RET_INTEGER,
.arg1_type = ARG_PTR_TO_CTX,
.arg2_type = ARG_ANYTHING,
.arg3_type = ARG_PTR_TO_UNINIT_MEM,
.arg4_type = ARG_CONST_SIZE,
};
BPF_CALL_5(bpf_sock_addr_getsockopt, struct bpf_sock_addr_kern *, ctx,
int, level, int, optname, char *, optval, int, optlen)
{
......@@ -8126,6 +8196,10 @@ sock_ops_func_proto(enum bpf_func_id func_id, const struct bpf_prog *prog)
return &bpf_sk_storage_delete_proto;
case BPF_FUNC_get_netns_cookie:
return &bpf_get_netns_cookie_sock_ops_proto;
case BPF_FUNC_get_sockops_uid_gid:
return &bpf_get_sockops_uid_gid_proto;
case BPF_FUNC_sk_original_addr:
return &bpf_sk_original_addr_proto;
#ifdef CONFIG_INET
case BPF_FUNC_load_hdr_opt:
return &bpf_sock_ops_load_hdr_opt_proto;
......
......@@ -3384,8 +3384,10 @@ void sock_init_data_uid(struct socket *sock, struct sock *sk, kuid_t uid)
sk->sk_type = sock->type;
RCU_INIT_POINTER(sk->sk_wq, &sock->wq);
sock->sk = sk;
sk->sk_gid = SOCK_INODE(sock)->i_gid;
} else {
RCU_INIT_POINTER(sk->sk_wq, NULL);
sk->sk_gid = make_kgid(sock_net(sk)->user_ns, 0);
}
sk->sk_uid = uid;
......
......@@ -311,6 +311,67 @@ getorigdst(struct sock *sk, int optval, void __user *user, int *len)
return -ENOENT;
}
static int
bpf_getorigdst_impl(struct sock *sk, int optval, void *user, int *len, int dir)
{
const struct inet_sock *inet = inet_sk(sk);
const struct nf_conntrack_tuple_hash *h;
struct nf_conntrack_tuple tuple;
memset(&tuple, 0, sizeof(tuple));
tuple.src.u3.ip = inet->inet_rcv_saddr;
tuple.src.u.tcp.port = inet->inet_sport;
tuple.dst.u3.ip = inet->inet_daddr;
tuple.dst.u.tcp.port = inet->inet_dport;
tuple.src.l3num = PF_INET;
tuple.dst.protonum = sk->sk_protocol;
/* We only do TCP and SCTP at the moment: is there a better way? */
if (tuple.dst.protonum != IPPROTO_TCP &&
tuple.dst.protonum != IPPROTO_SCTP) {
pr_debug("SO_ORIGINAL_DST: Not a TCP/SCTP socket\n");
return -ENOPROTOOPT;
}
if ((unsigned int)*len < sizeof(struct sockaddr_in)) {
pr_debug("SO_ORIGINAL_DST: len %d not %zu\n",
*len, sizeof(struct sockaddr_in));
return -EINVAL;
}
h = nf_conntrack_find_get(sock_net(sk), &nf_ct_zone_dflt, &tuple);
if (h) {
struct sockaddr_in sin;
struct nf_conn *ct = nf_ct_tuplehash_to_ctrack(h);
sin.sin_family = AF_INET;
if (dir == IP_CT_DIR_REPLY) {
sin.sin_port = ct->tuplehash[IP_CT_DIR_REPLY]
.tuple.src.u.tcp.port;
sin.sin_addr.s_addr = ct->tuplehash[IP_CT_DIR_REPLY]
.tuple.src.u3.ip;
} else {
sin.sin_port = ct->tuplehash[IP_CT_DIR_ORIGINAL]
.tuple.dst.u.tcp.port;
sin.sin_addr.s_addr = ct->tuplehash[IP_CT_DIR_ORIGINAL]
.tuple.dst.u3.ip;
}
memset(sin.sin_zero, 0, sizeof(sin.sin_zero));
pr_debug("SO_ORIGINAL_DST: %pI4 %u\n",
&sin.sin_addr.s_addr, ntohs(sin.sin_port));
nf_ct_put(ct);
memcpy(user, &sin, sizeof(sin));
return 0;
}
pr_debug("SO_ORIGINAL_DST: Can't find %pI4/%u-%pI4/%u.\n",
&tuple.src.u3.ip, ntohs(tuple.src.u.tcp.port),
&tuple.dst.u3.ip, ntohs(tuple.dst.u.tcp.port));
return -ENOENT;
}
static struct nf_sockopt_ops so_getorigdst = {
.pf = PF_INET,
.get_optmin = SO_ORIGINAL_DST,
......@@ -655,6 +716,8 @@ int nf_conntrack_proto_init(void)
goto cleanup_sockopt;
#endif
bpf_getorigdst_opt = bpf_getorigdst_impl;
return ret;
#if IS_ENABLED(CONFIG_IPV6)
......@@ -666,6 +729,8 @@ int nf_conntrack_proto_init(void)
void nf_conntrack_proto_fini(void)
{
bpf_getorigdst_opt = NULL;
nf_unregister_sockopt(&so_getorigdst);
#if IS_ENABLED(CONFIG_IPV6)
nf_unregister_sockopt(&so_getorigdst6);
......
......@@ -600,10 +600,12 @@ static int sockfs_setattr(struct mnt_idmap *idmap,
if (!err && (iattr->ia_valid & ATTR_UID)) {
struct socket *sock = SOCKET_I(d_inode(dentry));
if (sock->sk)
if (sock->sk) {
sock->sk->sk_uid = iattr->ia_uid;
else
sock->sk->sk_gid = iattr->ia_gid;
} else {
err = -ENOENT;
}
}
return err;
......
......@@ -5559,6 +5559,19 @@ union bpf_attr {
* 0 on success.
*
* **-ENOENT** if the bpf_local_storage cannot be found.
*
* u64 bpf_get_sockops_uid_gid(void *sockops)
* Description
* Get sock's uid and gid
* Return
* A 64-bit integer containing the current GID and UID, and
* created as such: *current_gid* **<< 32 \|** *current_uid*.
*
* int bpf_sk_original_addr(void *bpf_socket, int optname, char *optval, int optlen)
* Description
* Get Ipv4 origdst or replysrc. Works with IPv4.
* Return
* 0 on success, or a negative error in case of failure.
*/
#define ___BPF_FUNC_MAPPER(FN, ctx...) \
FN(unspec, 0, ##ctx) \
......@@ -5773,6 +5786,8 @@ union bpf_attr {
FN(user_ringbuf_drain, 209, ##ctx) \
FN(cgrp_storage_get, 210, ##ctx) \
FN(cgrp_storage_delete, 211, ##ctx) \
FN(get_sockops_uid_gid, 212, ##ctx) \
FN(sk_original_addr, 213, ##ctx) \
/* */
/* backwards-compatibility macros for users of __BPF_FUNC_MAPPER that don't
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册