Merge git://git.kernel.org/pub/scm/linux/kernel/git/bpf/bpf-next
Signed-off-by: David S. Miller <davem@davemloft.net>
This commit is contained in:
@@ -8655,15 +8655,17 @@ static void dev_xdp_uninstall(struct net_device *dev)
|
||||
* @dev: device
|
||||
* @extack: netlink extended ack
|
||||
* @fd: new program fd or negative value to clear
|
||||
* @expected_fd: old program fd that userspace expects to replace or clear
|
||||
* @flags: xdp-related flags
|
||||
*
|
||||
* Set or clear a bpf program for a device
|
||||
*/
|
||||
int dev_change_xdp_fd(struct net_device *dev, struct netlink_ext_ack *extack,
|
||||
int fd, u32 flags)
|
||||
int fd, int expected_fd, u32 flags)
|
||||
{
|
||||
const struct net_device_ops *ops = dev->netdev_ops;
|
||||
enum bpf_netdev_command query;
|
||||
u32 prog_id, expected_id = 0;
|
||||
struct bpf_prog *prog = NULL;
|
||||
bpf_op_t bpf_op, bpf_chk;
|
||||
bool offload;
|
||||
@@ -8684,15 +8686,29 @@ int dev_change_xdp_fd(struct net_device *dev, struct netlink_ext_ack *extack,
|
||||
if (bpf_op == bpf_chk)
|
||||
bpf_chk = generic_xdp_install;
|
||||
|
||||
if (fd >= 0) {
|
||||
u32 prog_id;
|
||||
prog_id = __dev_xdp_query(dev, bpf_op, query);
|
||||
if (flags & XDP_FLAGS_REPLACE) {
|
||||
if (expected_fd >= 0) {
|
||||
prog = bpf_prog_get_type_dev(expected_fd,
|
||||
BPF_PROG_TYPE_XDP,
|
||||
bpf_op == ops->ndo_bpf);
|
||||
if (IS_ERR(prog))
|
||||
return PTR_ERR(prog);
|
||||
expected_id = prog->aux->id;
|
||||
bpf_prog_put(prog);
|
||||
}
|
||||
|
||||
if (prog_id != expected_id) {
|
||||
NL_SET_ERR_MSG(extack, "Active program does not match expected");
|
||||
return -EEXIST;
|
||||
}
|
||||
}
|
||||
if (fd >= 0) {
|
||||
if (!offload && __dev_xdp_query(dev, bpf_chk, XDP_QUERY_PROG)) {
|
||||
NL_SET_ERR_MSG(extack, "native and generic XDP can't be active at the same time");
|
||||
return -EEXIST;
|
||||
}
|
||||
|
||||
prog_id = __dev_xdp_query(dev, bpf_op, query);
|
||||
if ((flags & XDP_FLAGS_UPDATE_IF_NOEXIST) && prog_id) {
|
||||
NL_SET_ERR_MSG(extack, "XDP program already attached");
|
||||
return -EBUSY;
|
||||
@@ -8715,7 +8731,7 @@ int dev_change_xdp_fd(struct net_device *dev, struct netlink_ext_ack *extack,
|
||||
return 0;
|
||||
}
|
||||
} else {
|
||||
if (!__dev_xdp_query(dev, bpf_op, query))
|
||||
if (!prog_id)
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@@ -2642,6 +2642,19 @@ static const struct bpf_func_proto bpf_msg_pop_data_proto = {
|
||||
.arg4_type = ARG_ANYTHING,
|
||||
};
|
||||
|
||||
#ifdef CONFIG_CGROUP_NET_CLASSID
|
||||
BPF_CALL_0(bpf_get_cgroup_classid_curr)
|
||||
{
|
||||
return __task_get_classid(current);
|
||||
}
|
||||
|
||||
static const struct bpf_func_proto bpf_get_cgroup_classid_curr_proto = {
|
||||
.func = bpf_get_cgroup_classid_curr,
|
||||
.gpl_only = false,
|
||||
.ret_type = RET_INTEGER,
|
||||
};
|
||||
#endif
|
||||
|
||||
BPF_CALL_1(bpf_get_cgroup_classid, const struct sk_buff *, skb)
|
||||
{
|
||||
return task_get_classid(skb);
|
||||
@@ -4117,6 +4130,18 @@ static const struct bpf_func_proto bpf_get_socket_cookie_sock_addr_proto = {
|
||||
.arg1_type = ARG_PTR_TO_CTX,
|
||||
};
|
||||
|
||||
BPF_CALL_1(bpf_get_socket_cookie_sock, struct sock *, ctx)
|
||||
{
|
||||
return sock_gen_cookie(ctx);
|
||||
}
|
||||
|
||||
static const struct bpf_func_proto bpf_get_socket_cookie_sock_proto = {
|
||||
.func = bpf_get_socket_cookie_sock,
|
||||
.gpl_only = false,
|
||||
.ret_type = RET_INTEGER,
|
||||
.arg1_type = ARG_PTR_TO_CTX,
|
||||
};
|
||||
|
||||
BPF_CALL_1(bpf_get_socket_cookie_sock_ops, struct bpf_sock_ops_kern *, ctx)
|
||||
{
|
||||
return sock_gen_cookie(ctx->sk);
|
||||
@@ -4129,6 +4154,39 @@ static const struct bpf_func_proto bpf_get_socket_cookie_sock_ops_proto = {
|
||||
.arg1_type = ARG_PTR_TO_CTX,
|
||||
};
|
||||
|
||||
static u64 __bpf_get_netns_cookie(struct sock *sk)
|
||||
{
|
||||
#ifdef CONFIG_NET_NS
|
||||
return net_gen_cookie(sk ? sk->sk_net.net : &init_net);
|
||||
#else
|
||||
return 0;
|
||||
#endif
|
||||
}
|
||||
|
||||
BPF_CALL_1(bpf_get_netns_cookie_sock, struct sock *, ctx)
|
||||
{
|
||||
return __bpf_get_netns_cookie(ctx);
|
||||
}
|
||||
|
||||
static const struct bpf_func_proto bpf_get_netns_cookie_sock_proto = {
|
||||
.func = bpf_get_netns_cookie_sock,
|
||||
.gpl_only = false,
|
||||
.ret_type = RET_INTEGER,
|
||||
.arg1_type = ARG_PTR_TO_CTX_OR_NULL,
|
||||
};
|
||||
|
||||
BPF_CALL_1(bpf_get_netns_cookie_sock_addr, struct bpf_sock_addr_kern *, ctx)
|
||||
{
|
||||
return __bpf_get_netns_cookie(ctx ? ctx->sk : NULL);
|
||||
}
|
||||
|
||||
static const struct bpf_func_proto bpf_get_netns_cookie_sock_addr_proto = {
|
||||
.func = bpf_get_netns_cookie_sock_addr,
|
||||
.gpl_only = false,
|
||||
.ret_type = RET_INTEGER,
|
||||
.arg1_type = ARG_PTR_TO_CTX_OR_NULL,
|
||||
};
|
||||
|
||||
BPF_CALL_1(bpf_get_socket_uid, struct sk_buff *, skb)
|
||||
{
|
||||
struct sock *sk = sk_to_full_sk(skb->sk);
|
||||
@@ -4147,8 +4205,8 @@ static const struct bpf_func_proto bpf_get_socket_uid_proto = {
|
||||
.arg1_type = ARG_PTR_TO_CTX,
|
||||
};
|
||||
|
||||
BPF_CALL_5(bpf_sockopt_event_output, struct bpf_sock_ops_kern *, bpf_sock,
|
||||
struct bpf_map *, map, u64, flags, void *, data, u64, size)
|
||||
BPF_CALL_5(bpf_event_output_data, void *, ctx, struct bpf_map *, map, u64, flags,
|
||||
void *, data, u64, size)
|
||||
{
|
||||
if (unlikely(flags & ~(BPF_F_INDEX_MASK)))
|
||||
return -EINVAL;
|
||||
@@ -4156,8 +4214,8 @@ BPF_CALL_5(bpf_sockopt_event_output, struct bpf_sock_ops_kern *, bpf_sock,
|
||||
return bpf_event_output(map, flags, data, size, NULL, 0, NULL);
|
||||
}
|
||||
|
||||
static const struct bpf_func_proto bpf_sockopt_event_output_proto = {
|
||||
.func = bpf_sockopt_event_output,
|
||||
static const struct bpf_func_proto bpf_event_output_data_proto = {
|
||||
.func = bpf_event_output_data,
|
||||
.gpl_only = true,
|
||||
.ret_type = RET_INTEGER,
|
||||
.arg1_type = ARG_PTR_TO_CTX,
|
||||
@@ -5343,8 +5401,7 @@ static const struct bpf_func_proto bpf_sk_lookup_udp_proto = {
|
||||
|
||||
BPF_CALL_1(bpf_sk_release, struct sock *, sk)
|
||||
{
|
||||
/* Only full sockets have sk->sk_flags. */
|
||||
if (!sk_fullsock(sk) || !sock_flag(sk, SOCK_RCU_FREE))
|
||||
if (sk_is_refcounted(sk))
|
||||
sock_gen_put(sk);
|
||||
return 0;
|
||||
}
|
||||
@@ -5860,6 +5917,36 @@ static const struct bpf_func_proto bpf_tcp_gen_syncookie_proto = {
|
||||
.arg5_type = ARG_CONST_SIZE,
|
||||
};
|
||||
|
||||
BPF_CALL_3(bpf_sk_assign, struct sk_buff *, skb, struct sock *, sk, u64, flags)
|
||||
{
|
||||
if (flags != 0)
|
||||
return -EINVAL;
|
||||
if (!skb_at_tc_ingress(skb))
|
||||
return -EOPNOTSUPP;
|
||||
if (unlikely(dev_net(skb->dev) != sock_net(sk)))
|
||||
return -ENETUNREACH;
|
||||
if (unlikely(sk->sk_reuseport))
|
||||
return -ESOCKTNOSUPPORT;
|
||||
if (sk_is_refcounted(sk) &&
|
||||
unlikely(!refcount_inc_not_zero(&sk->sk_refcnt)))
|
||||
return -ENOENT;
|
||||
|
||||
skb_orphan(skb);
|
||||
skb->sk = sk;
|
||||
skb->destructor = sock_pfree;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static const struct bpf_func_proto bpf_sk_assign_proto = {
|
||||
.func = bpf_sk_assign,
|
||||
.gpl_only = false,
|
||||
.ret_type = RET_INTEGER,
|
||||
.arg1_type = ARG_PTR_TO_CTX,
|
||||
.arg2_type = ARG_PTR_TO_SOCK_COMMON,
|
||||
.arg3_type = ARG_ANYTHING,
|
||||
};
|
||||
|
||||
#endif /* CONFIG_INET */
|
||||
|
||||
bool bpf_helper_changes_pkt_data(void *func)
|
||||
@@ -5954,6 +6041,26 @@ sock_filter_func_proto(enum bpf_func_id func_id, const struct bpf_prog *prog)
|
||||
return &bpf_get_current_uid_gid_proto;
|
||||
case BPF_FUNC_get_local_storage:
|
||||
return &bpf_get_local_storage_proto;
|
||||
case BPF_FUNC_get_socket_cookie:
|
||||
return &bpf_get_socket_cookie_sock_proto;
|
||||
case BPF_FUNC_get_netns_cookie:
|
||||
return &bpf_get_netns_cookie_sock_proto;
|
||||
case BPF_FUNC_perf_event_output:
|
||||
return &bpf_event_output_data_proto;
|
||||
case BPF_FUNC_get_current_pid_tgid:
|
||||
return &bpf_get_current_pid_tgid_proto;
|
||||
case BPF_FUNC_get_current_comm:
|
||||
return &bpf_get_current_comm_proto;
|
||||
#ifdef CONFIG_CGROUPS
|
||||
case BPF_FUNC_get_current_cgroup_id:
|
||||
return &bpf_get_current_cgroup_id_proto;
|
||||
case BPF_FUNC_get_current_ancestor_cgroup_id:
|
||||
return &bpf_get_current_ancestor_cgroup_id_proto;
|
||||
#endif
|
||||
#ifdef CONFIG_CGROUP_NET_CLASSID
|
||||
case BPF_FUNC_get_cgroup_classid:
|
||||
return &bpf_get_cgroup_classid_curr_proto;
|
||||
#endif
|
||||
default:
|
||||
return bpf_base_func_proto(func_id);
|
||||
}
|
||||
@@ -5978,8 +6085,26 @@ sock_addr_func_proto(enum bpf_func_id func_id, const struct bpf_prog *prog)
|
||||
}
|
||||
case BPF_FUNC_get_socket_cookie:
|
||||
return &bpf_get_socket_cookie_sock_addr_proto;
|
||||
case BPF_FUNC_get_netns_cookie:
|
||||
return &bpf_get_netns_cookie_sock_addr_proto;
|
||||
case BPF_FUNC_get_local_storage:
|
||||
return &bpf_get_local_storage_proto;
|
||||
case BPF_FUNC_perf_event_output:
|
||||
return &bpf_event_output_data_proto;
|
||||
case BPF_FUNC_get_current_pid_tgid:
|
||||
return &bpf_get_current_pid_tgid_proto;
|
||||
case BPF_FUNC_get_current_comm:
|
||||
return &bpf_get_current_comm_proto;
|
||||
#ifdef CONFIG_CGROUPS
|
||||
case BPF_FUNC_get_current_cgroup_id:
|
||||
return &bpf_get_current_cgroup_id_proto;
|
||||
case BPF_FUNC_get_current_ancestor_cgroup_id:
|
||||
return &bpf_get_current_ancestor_cgroup_id_proto;
|
||||
#endif
|
||||
#ifdef CONFIG_CGROUP_NET_CLASSID
|
||||
case BPF_FUNC_get_cgroup_classid:
|
||||
return &bpf_get_cgroup_classid_curr_proto;
|
||||
#endif
|
||||
#ifdef CONFIG_INET
|
||||
case BPF_FUNC_sk_lookup_tcp:
|
||||
return &bpf_sock_addr_sk_lookup_tcp_proto;
|
||||
@@ -6153,6 +6278,8 @@ tc_cls_act_func_proto(enum bpf_func_id func_id, const struct bpf_prog *prog)
|
||||
return &bpf_skb_ecn_set_ce_proto;
|
||||
case BPF_FUNC_tcp_gen_syncookie:
|
||||
return &bpf_tcp_gen_syncookie_proto;
|
||||
case BPF_FUNC_sk_assign:
|
||||
return &bpf_sk_assign_proto;
|
||||
#endif
|
||||
default:
|
||||
return bpf_base_func_proto(func_id);
|
||||
@@ -6222,7 +6349,7 @@ sock_ops_func_proto(enum bpf_func_id func_id, const struct bpf_prog *prog)
|
||||
case BPF_FUNC_get_local_storage:
|
||||
return &bpf_get_local_storage_proto;
|
||||
case BPF_FUNC_perf_event_output:
|
||||
return &bpf_sockopt_event_output_proto;
|
||||
return &bpf_event_output_data_proto;
|
||||
case BPF_FUNC_sk_storage_get:
|
||||
return &bpf_sk_storage_get_proto;
|
||||
case BPF_FUNC_sk_storage_delete:
|
||||
|
@@ -69,6 +69,20 @@ EXPORT_SYMBOL_GPL(pernet_ops_rwsem);
|
||||
|
||||
static unsigned int max_gen_ptrs = INITIAL_NET_GEN_PTRS;
|
||||
|
||||
static atomic64_t cookie_gen;
|
||||
|
||||
u64 net_gen_cookie(struct net *net)
|
||||
{
|
||||
while (1) {
|
||||
u64 res = atomic64_read(&net->net_cookie);
|
||||
|
||||
if (res)
|
||||
return res;
|
||||
res = atomic64_inc_return(&cookie_gen);
|
||||
atomic64_cmpxchg(&net->net_cookie, 0, res);
|
||||
}
|
||||
}
|
||||
|
||||
static struct net_generic *net_alloc_generic(void)
|
||||
{
|
||||
struct net_generic *ng;
|
||||
@@ -1087,6 +1101,7 @@ static int __init net_ns_init(void)
|
||||
panic("Could not allocate generic netns");
|
||||
|
||||
rcu_assign_pointer(init_net.gen, ng);
|
||||
net_gen_cookie(&init_net);
|
||||
|
||||
down_write(&pernet_ops_rwsem);
|
||||
if (setup_net(&init_net, &init_user_ns))
|
||||
|
@@ -1872,7 +1872,9 @@ static const struct nla_policy ifla_port_policy[IFLA_PORT_MAX+1] = {
|
||||
};
|
||||
|
||||
static const struct nla_policy ifla_xdp_policy[IFLA_XDP_MAX + 1] = {
|
||||
[IFLA_XDP_UNSPEC] = { .strict_start_type = IFLA_XDP_EXPECTED_FD },
|
||||
[IFLA_XDP_FD] = { .type = NLA_S32 },
|
||||
[IFLA_XDP_EXPECTED_FD] = { .type = NLA_S32 },
|
||||
[IFLA_XDP_ATTACHED] = { .type = NLA_U8 },
|
||||
[IFLA_XDP_FLAGS] = { .type = NLA_U32 },
|
||||
[IFLA_XDP_PROG_ID] = { .type = NLA_U32 },
|
||||
@@ -2799,8 +2801,20 @@ static int do_setlink(const struct sk_buff *skb,
|
||||
}
|
||||
|
||||
if (xdp[IFLA_XDP_FD]) {
|
||||
int expected_fd = -1;
|
||||
|
||||
if (xdp_flags & XDP_FLAGS_REPLACE) {
|
||||
if (!xdp[IFLA_XDP_EXPECTED_FD]) {
|
||||
err = -EINVAL;
|
||||
goto errout;
|
||||
}
|
||||
expected_fd =
|
||||
nla_get_s32(xdp[IFLA_XDP_EXPECTED_FD]);
|
||||
}
|
||||
|
||||
err = dev_change_xdp_fd(dev, extack,
|
||||
nla_get_s32(xdp[IFLA_XDP_FD]),
|
||||
expected_fd,
|
||||
xdp_flags);
|
||||
if (err)
|
||||
goto errout;
|
||||
|
@@ -2071,6 +2071,18 @@ void sock_efree(struct sk_buff *skb)
|
||||
}
|
||||
EXPORT_SYMBOL(sock_efree);
|
||||
|
||||
/* Buffer destructor for prefetch/receive path where reference count may
|
||||
* not be held, e.g. for listen sockets.
|
||||
*/
|
||||
#ifdef CONFIG_INET
|
||||
void sock_pfree(struct sk_buff *skb)
|
||||
{
|
||||
if (sk_is_refcounted(skb->sk))
|
||||
sock_gen_put(skb->sk);
|
||||
}
|
||||
EXPORT_SYMBOL(sock_pfree);
|
||||
#endif /* CONFIG_INET */
|
||||
|
||||
kuid_t sock_i_uid(struct sock *sk)
|
||||
{
|
||||
kuid_t uid;
|
||||
|
Reference in New Issue
Block a user