Orange Pi5 kernel

Deprecated Linux kernel 5.10.110 for OrangePi 5/5B/5+ boards

3 Commits   0 Branches   0 Tags
^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);