^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1) // SPDX-License-Identifier: GPL-2.0
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3) #include <linux/bpf.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4) #include <linux/filter.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5) #include <net/net_namespace.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8) * Functions to manage BPF programs attached to netns
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11) struct bpf_netns_link {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12) struct bpf_link link;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13) enum bpf_attach_type type;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14) enum netns_bpf_attach_type netns_type;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 15)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 16) /* We don't hold a ref to net in order to auto-detach the link
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 17) * when netns is going away. Instead we rely on pernet
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 18) * pre_exit callback to clear this pointer. Must be accessed
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 19) * with netns_bpf_mutex held.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 20) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 21) struct net *net;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 22) struct list_head node; /* node in list of links attached to net */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 23) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 24)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 25) /* Protects updates to netns_bpf */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 26) DEFINE_MUTEX(netns_bpf_mutex);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 27)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 28) static void netns_bpf_attach_type_unneed(enum netns_bpf_attach_type type)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 29) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 30) switch (type) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 31) #ifdef CONFIG_INET
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 32) case NETNS_BPF_SK_LOOKUP:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 33) static_branch_dec(&bpf_sk_lookup_enabled);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 34) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 35) #endif
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 36) default:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 37) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 38) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 39) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 40)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 41) static void netns_bpf_attach_type_need(enum netns_bpf_attach_type type)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 42) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 43) switch (type) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 44) #ifdef CONFIG_INET
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 45) case NETNS_BPF_SK_LOOKUP:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 46) static_branch_inc(&bpf_sk_lookup_enabled);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 47) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 48) #endif
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 49) default:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 50) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 51) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 52) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 53)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 54) /* Must be called with netns_bpf_mutex held. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 55) static void netns_bpf_run_array_detach(struct net *net,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 56) enum netns_bpf_attach_type type)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 57) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 58) struct bpf_prog_array *run_array;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 59)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 60) run_array = rcu_replace_pointer(net->bpf.run_array[type], NULL,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 61) lockdep_is_held(&netns_bpf_mutex));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 62) bpf_prog_array_free(run_array);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 63) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 64)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 65) static int link_index(struct net *net, enum netns_bpf_attach_type type,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 66) struct bpf_netns_link *link)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 67) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 68) struct bpf_netns_link *pos;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 69) int i = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 70)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 71) list_for_each_entry(pos, &net->bpf.links[type], node) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 72) if (pos == link)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 73) return i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 74) i++;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 75) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 76) return -ENOENT;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 77) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 78)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 79) static int link_count(struct net *net, enum netns_bpf_attach_type type)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 80) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 81) struct list_head *pos;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 82) int i = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 83)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 84) list_for_each(pos, &net->bpf.links[type])
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 85) i++;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 86) return i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 87) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 88)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 89) static void fill_prog_array(struct net *net, enum netns_bpf_attach_type type,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 90) struct bpf_prog_array *prog_array)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 91) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 92) struct bpf_netns_link *pos;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 93) unsigned int i = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 94)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 95) list_for_each_entry(pos, &net->bpf.links[type], node) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 96) prog_array->items[i].prog = pos->link.prog;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 97) i++;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 98) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 99) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 100)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 101) static void bpf_netns_link_release(struct bpf_link *link)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 102) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 103) struct bpf_netns_link *net_link =
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 104) container_of(link, struct bpf_netns_link, link);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 105) enum netns_bpf_attach_type type = net_link->netns_type;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 106) struct bpf_prog_array *old_array, *new_array;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 107) struct net *net;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 108) int cnt, idx;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 109)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 110) mutex_lock(&netns_bpf_mutex);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 111)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 112) /* We can race with cleanup_net, but if we see a non-NULL
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 113) * struct net pointer, pre_exit has not run yet and wait for
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 114) * netns_bpf_mutex.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 115) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 116) net = net_link->net;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 117) if (!net)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 118) goto out_unlock;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 119)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 120) /* Mark attach point as unused */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 121) netns_bpf_attach_type_unneed(type);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 122)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 123) /* Remember link position in case of safe delete */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 124) idx = link_index(net, type, net_link);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 125) list_del(&net_link->node);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 126)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 127) cnt = link_count(net, type);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 128) if (!cnt) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 129) netns_bpf_run_array_detach(net, type);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 130) goto out_unlock;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 131) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 132)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 133) old_array = rcu_dereference_protected(net->bpf.run_array[type],
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 134) lockdep_is_held(&netns_bpf_mutex));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 135) new_array = bpf_prog_array_alloc(cnt, GFP_KERNEL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 136) if (!new_array) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 137) WARN_ON(bpf_prog_array_delete_safe_at(old_array, idx));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 138) goto out_unlock;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 139) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 140) fill_prog_array(net, type, new_array);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 141) rcu_assign_pointer(net->bpf.run_array[type], new_array);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 142) bpf_prog_array_free(old_array);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 143)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 144) out_unlock:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 145) net_link->net = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 146) mutex_unlock(&netns_bpf_mutex);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 147) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 148)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 149) static int bpf_netns_link_detach(struct bpf_link *link)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 150) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 151) bpf_netns_link_release(link);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 152) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 153) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 154)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 155) static void bpf_netns_link_dealloc(struct bpf_link *link)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 156) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 157) struct bpf_netns_link *net_link =
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 158) container_of(link, struct bpf_netns_link, link);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 159)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 160) kfree(net_link);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 161) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 162)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 163) static int bpf_netns_link_update_prog(struct bpf_link *link,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 164) struct bpf_prog *new_prog,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 165) struct bpf_prog *old_prog)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 166) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 167) struct bpf_netns_link *net_link =
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 168) container_of(link, struct bpf_netns_link, link);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 169) enum netns_bpf_attach_type type = net_link->netns_type;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 170) struct bpf_prog_array *run_array;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 171) struct net *net;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 172) int idx, ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 173)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 174) if (old_prog && old_prog != link->prog)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 175) return -EPERM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 176) if (new_prog->type != link->prog->type)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 177) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 178)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 179) mutex_lock(&netns_bpf_mutex);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 180)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 181) net = net_link->net;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 182) if (!net || !check_net(net)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 183) /* Link auto-detached or netns dying */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 184) ret = -ENOLINK;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 185) goto out_unlock;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 186) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 187)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 188) run_array = rcu_dereference_protected(net->bpf.run_array[type],
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 189) lockdep_is_held(&netns_bpf_mutex));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 190) idx = link_index(net, type, net_link);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 191) ret = bpf_prog_array_update_at(run_array, idx, new_prog);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 192) if (ret)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 193) goto out_unlock;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 194)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 195) old_prog = xchg(&link->prog, new_prog);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 196) bpf_prog_put(old_prog);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 197)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 198) out_unlock:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 199) mutex_unlock(&netns_bpf_mutex);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 200) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 201) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 202)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 203) static int bpf_netns_link_fill_info(const struct bpf_link *link,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 204) struct bpf_link_info *info)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 205) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 206) const struct bpf_netns_link *net_link =
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 207) container_of(link, struct bpf_netns_link, link);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 208) unsigned int inum = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 209) struct net *net;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 210)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 211) mutex_lock(&netns_bpf_mutex);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 212) net = net_link->net;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 213) if (net && check_net(net))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 214) inum = net->ns.inum;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 215) mutex_unlock(&netns_bpf_mutex);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 216)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 217) info->netns.netns_ino = inum;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 218) info->netns.attach_type = net_link->type;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 219) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 220) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 221)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 222) static void bpf_netns_link_show_fdinfo(const struct bpf_link *link,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 223) struct seq_file *seq)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 224) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 225) struct bpf_link_info info = {};
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 226)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 227) bpf_netns_link_fill_info(link, &info);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 228) seq_printf(seq,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 229) "netns_ino:\t%u\n"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 230) "attach_type:\t%u\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 231) info.netns.netns_ino,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 232) info.netns.attach_type);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 233) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 234)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 235) static const struct bpf_link_ops bpf_netns_link_ops = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 236) .release = bpf_netns_link_release,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 237) .dealloc = bpf_netns_link_dealloc,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 238) .detach = bpf_netns_link_detach,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 239) .update_prog = bpf_netns_link_update_prog,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 240) .fill_link_info = bpf_netns_link_fill_info,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 241) .show_fdinfo = bpf_netns_link_show_fdinfo,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 242) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 243)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 244) /* Must be called with netns_bpf_mutex held. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 245) static int __netns_bpf_prog_query(const union bpf_attr *attr,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 246) union bpf_attr __user *uattr,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 247) struct net *net,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 248) enum netns_bpf_attach_type type)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 249) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 250) __u32 __user *prog_ids = u64_to_user_ptr(attr->query.prog_ids);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 251) struct bpf_prog_array *run_array;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 252) u32 prog_cnt = 0, flags = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 253)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 254) run_array = rcu_dereference_protected(net->bpf.run_array[type],
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 255) lockdep_is_held(&netns_bpf_mutex));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 256) if (run_array)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 257) prog_cnt = bpf_prog_array_length(run_array);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 258)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 259) if (copy_to_user(&uattr->query.attach_flags, &flags, sizeof(flags)))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 260) return -EFAULT;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 261) if (copy_to_user(&uattr->query.prog_cnt, &prog_cnt, sizeof(prog_cnt)))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 262) return -EFAULT;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 263) if (!attr->query.prog_cnt || !prog_ids || !prog_cnt)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 264) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 265)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 266) return bpf_prog_array_copy_to_user(run_array, prog_ids,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 267) attr->query.prog_cnt);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 268) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 269)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 270) int netns_bpf_prog_query(const union bpf_attr *attr,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 271) union bpf_attr __user *uattr)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 272) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 273) enum netns_bpf_attach_type type;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 274) struct net *net;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 275) int ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 276)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 277) if (attr->query.query_flags)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 278) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 279)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 280) type = to_netns_bpf_attach_type(attr->query.attach_type);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 281) if (type < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 282) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 283)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 284) net = get_net_ns_by_fd(attr->query.target_fd);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 285) if (IS_ERR(net))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 286) return PTR_ERR(net);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 287)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 288) mutex_lock(&netns_bpf_mutex);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 289) ret = __netns_bpf_prog_query(attr, uattr, net, type);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 290) mutex_unlock(&netns_bpf_mutex);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 291)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 292) put_net(net);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 293) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 294) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 295)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 296) int netns_bpf_prog_attach(const union bpf_attr *attr, struct bpf_prog *prog)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 297) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 298) struct bpf_prog_array *run_array;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 299) enum netns_bpf_attach_type type;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 300) struct bpf_prog *attached;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 301) struct net *net;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 302) int ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 303)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 304) if (attr->target_fd || attr->attach_flags || attr->replace_bpf_fd)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 305) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 306)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 307) type = to_netns_bpf_attach_type(attr->attach_type);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 308) if (type < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 309) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 310)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 311) net = current->nsproxy->net_ns;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 312) mutex_lock(&netns_bpf_mutex);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 313)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 314) /* Attaching prog directly is not compatible with links */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 315) if (!list_empty(&net->bpf.links[type])) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 316) ret = -EEXIST;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 317) goto out_unlock;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 318) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 319)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 320) switch (type) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 321) case NETNS_BPF_FLOW_DISSECTOR:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 322) ret = flow_dissector_bpf_prog_attach_check(net, prog);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 323) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 324) default:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 325) ret = -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 326) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 327) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 328) if (ret)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 329) goto out_unlock;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 330)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 331) attached = net->bpf.progs[type];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 332) if (attached == prog) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 333) /* The same program cannot be attached twice */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 334) ret = -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 335) goto out_unlock;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 336) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 337)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 338) run_array = rcu_dereference_protected(net->bpf.run_array[type],
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 339) lockdep_is_held(&netns_bpf_mutex));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 340) if (run_array) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 341) WRITE_ONCE(run_array->items[0].prog, prog);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 342) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 343) run_array = bpf_prog_array_alloc(1, GFP_KERNEL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 344) if (!run_array) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 345) ret = -ENOMEM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 346) goto out_unlock;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 347) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 348) run_array->items[0].prog = prog;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 349) rcu_assign_pointer(net->bpf.run_array[type], run_array);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 350) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 351)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 352) net->bpf.progs[type] = prog;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 353) if (attached)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 354) bpf_prog_put(attached);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 355)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 356) out_unlock:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 357) mutex_unlock(&netns_bpf_mutex);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 358)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 359) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 360) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 361)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 362) /* Must be called with netns_bpf_mutex held. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 363) static int __netns_bpf_prog_detach(struct net *net,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 364) enum netns_bpf_attach_type type,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 365) struct bpf_prog *old)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 366) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 367) struct bpf_prog *attached;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 368)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 369) /* Progs attached via links cannot be detached */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 370) if (!list_empty(&net->bpf.links[type]))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 371) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 372)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 373) attached = net->bpf.progs[type];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 374) if (!attached || attached != old)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 375) return -ENOENT;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 376) netns_bpf_run_array_detach(net, type);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 377) net->bpf.progs[type] = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 378) bpf_prog_put(attached);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 379) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 380) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 381)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 382) int netns_bpf_prog_detach(const union bpf_attr *attr, enum bpf_prog_type ptype)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 383) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 384) enum netns_bpf_attach_type type;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 385) struct bpf_prog *prog;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 386) int ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 387)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 388) if (attr->target_fd)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 389) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 390)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 391) type = to_netns_bpf_attach_type(attr->attach_type);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 392) if (type < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 393) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 394)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 395) prog = bpf_prog_get_type(attr->attach_bpf_fd, ptype);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 396) if (IS_ERR(prog))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 397) return PTR_ERR(prog);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 398)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 399) mutex_lock(&netns_bpf_mutex);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 400) ret = __netns_bpf_prog_detach(current->nsproxy->net_ns, type, prog);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 401) mutex_unlock(&netns_bpf_mutex);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 402)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 403) bpf_prog_put(prog);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 404)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 405) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 406) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 407)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 408) static int netns_bpf_max_progs(enum netns_bpf_attach_type type)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 409) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 410) switch (type) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 411) case NETNS_BPF_FLOW_DISSECTOR:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 412) return 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 413) case NETNS_BPF_SK_LOOKUP:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 414) return 64;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 415) default:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 416) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 417) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 418) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 419)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 420) static int netns_bpf_link_attach(struct net *net, struct bpf_link *link,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 421) enum netns_bpf_attach_type type)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 422) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 423) struct bpf_netns_link *net_link =
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 424) container_of(link, struct bpf_netns_link, link);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 425) struct bpf_prog_array *run_array;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 426) int cnt, err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 427)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 428) mutex_lock(&netns_bpf_mutex);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 429)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 430) cnt = link_count(net, type);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 431) if (cnt >= netns_bpf_max_progs(type)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 432) err = -E2BIG;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 433) goto out_unlock;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 434) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 435) /* Links are not compatible with attaching prog directly */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 436) if (net->bpf.progs[type]) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 437) err = -EEXIST;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 438) goto out_unlock;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 439) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 440)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 441) switch (type) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 442) case NETNS_BPF_FLOW_DISSECTOR:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 443) err = flow_dissector_bpf_prog_attach_check(net, link->prog);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 444) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 445) case NETNS_BPF_SK_LOOKUP:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 446) err = 0; /* nothing to check */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 447) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 448) default:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 449) err = -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 450) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 451) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 452) if (err)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 453) goto out_unlock;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 454)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 455) run_array = bpf_prog_array_alloc(cnt + 1, GFP_KERNEL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 456) if (!run_array) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 457) err = -ENOMEM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 458) goto out_unlock;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 459) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 460)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 461) list_add_tail(&net_link->node, &net->bpf.links[type]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 462)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 463) fill_prog_array(net, type, run_array);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 464) run_array = rcu_replace_pointer(net->bpf.run_array[type], run_array,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 465) lockdep_is_held(&netns_bpf_mutex));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 466) bpf_prog_array_free(run_array);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 467)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 468) /* Mark attach point as used */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 469) netns_bpf_attach_type_need(type);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 470)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 471) out_unlock:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 472) mutex_unlock(&netns_bpf_mutex);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 473) return err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 474) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 475)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 476) int netns_bpf_link_create(const union bpf_attr *attr, struct bpf_prog *prog)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 477) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 478) enum netns_bpf_attach_type netns_type;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 479) struct bpf_link_primer link_primer;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 480) struct bpf_netns_link *net_link;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 481) enum bpf_attach_type type;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 482) struct net *net;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 483) int err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 484)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 485) if (attr->link_create.flags)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 486) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 487)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 488) type = attr->link_create.attach_type;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 489) netns_type = to_netns_bpf_attach_type(type);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 490) if (netns_type < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 491) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 492)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 493) net = get_net_ns_by_fd(attr->link_create.target_fd);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 494) if (IS_ERR(net))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 495) return PTR_ERR(net);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 496)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 497) net_link = kzalloc(sizeof(*net_link), GFP_USER);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 498) if (!net_link) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 499) err = -ENOMEM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 500) goto out_put_net;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 501) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 502) bpf_link_init(&net_link->link, BPF_LINK_TYPE_NETNS,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 503) &bpf_netns_link_ops, prog);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 504) net_link->net = net;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 505) net_link->type = type;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 506) net_link->netns_type = netns_type;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 507)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 508) err = bpf_link_prime(&net_link->link, &link_primer);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 509) if (err) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 510) kfree(net_link);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 511) goto out_put_net;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 512) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 513)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 514) err = netns_bpf_link_attach(net, &net_link->link, netns_type);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 515) if (err) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 516) bpf_link_cleanup(&link_primer);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 517) goto out_put_net;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 518) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 519)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 520) put_net(net);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 521) return bpf_link_settle(&link_primer);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 522)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 523) out_put_net:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 524) put_net(net);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 525) return err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 526) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 527)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 528) static int __net_init netns_bpf_pernet_init(struct net *net)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 529) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 530) int type;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 531)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 532) for (type = 0; type < MAX_NETNS_BPF_ATTACH_TYPE; type++)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 533) INIT_LIST_HEAD(&net->bpf.links[type]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 534)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 535) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 536) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 537)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 538) static void __net_exit netns_bpf_pernet_pre_exit(struct net *net)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 539) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 540) enum netns_bpf_attach_type type;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 541) struct bpf_netns_link *net_link;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 542)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 543) mutex_lock(&netns_bpf_mutex);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 544) for (type = 0; type < MAX_NETNS_BPF_ATTACH_TYPE; type++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 545) netns_bpf_run_array_detach(net, type);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 546) list_for_each_entry(net_link, &net->bpf.links[type], node) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 547) net_link->net = NULL; /* auto-detach link */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 548) netns_bpf_attach_type_unneed(type);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 549) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 550) if (net->bpf.progs[type])
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 551) bpf_prog_put(net->bpf.progs[type]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 552) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 553) mutex_unlock(&netns_bpf_mutex);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 554) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 555)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 556) static struct pernet_operations netns_bpf_pernet_ops __net_initdata = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 557) .init = netns_bpf_pernet_init,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 558) .pre_exit = netns_bpf_pernet_pre_exit,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 559) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 560)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 561) static int __init netns_bpf_init(void)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 562) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 563) return register_pernet_subsys(&netns_bpf_pernet_ops);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 564) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 565)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 566) subsys_initcall(netns_bpf_init);