xref: /linux-6.15/kernel/bpf/devmap.c (revision 97f91a7c)
1546ac1ffSJohn Fastabend /* Copyright (c) 2017 Covalent IO, Inc. http://covalent.io
2546ac1ffSJohn Fastabend  *
3546ac1ffSJohn Fastabend  * This program is free software; you can redistribute it and/or
4546ac1ffSJohn Fastabend  * modify it under the terms of version 2 of the GNU General Public
5546ac1ffSJohn Fastabend  * License as published by the Free Software Foundation.
6546ac1ffSJohn Fastabend  *
7546ac1ffSJohn Fastabend  * This program is distributed in the hope that it will be useful, but
8546ac1ffSJohn Fastabend  * WITHOUT ANY WARRANTY; without even the implied warranty of
9546ac1ffSJohn Fastabend  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
10546ac1ffSJohn Fastabend  * General Public License for more details.
11546ac1ffSJohn Fastabend  */
12546ac1ffSJohn Fastabend 
13546ac1ffSJohn Fastabend /* Devmaps primary use is as a backend map for XDP BPF helper call
14546ac1ffSJohn Fastabend  * bpf_redirect_map(). Because XDP is mostly concerned with performance we
15546ac1ffSJohn Fastabend  * spent some effort to ensure the datapath with redirect maps does not use
16546ac1ffSJohn Fastabend  * any locking. This is a quick note on the details.
17546ac1ffSJohn Fastabend  *
18546ac1ffSJohn Fastabend  * We have three possible paths to get into the devmap control plane bpf
19546ac1ffSJohn Fastabend  * syscalls, bpf programs, and driver side xmit/flush operations. A bpf syscall
20546ac1ffSJohn Fastabend  * will invoke an update, delete, or lookup operation. To ensure updates and
21546ac1ffSJohn Fastabend  * deletes appear atomic from the datapath side xchg() is used to modify the
22546ac1ffSJohn Fastabend  * netdev_map array. Then because the datapath does a lookup into the netdev_map
23546ac1ffSJohn Fastabend  * array (read-only) from an RCU critical section we use call_rcu() to wait for
24546ac1ffSJohn Fastabend  * an rcu grace period before free'ing the old data structures. This ensures the
25546ac1ffSJohn Fastabend  * datapath always has a valid copy. However, the datapath does a "flush"
26546ac1ffSJohn Fastabend  * operation that pushes any pending packets in the driver outside the RCU
27546ac1ffSJohn Fastabend  * critical section. Each bpf_dtab_netdev tracks these pending operations using
28546ac1ffSJohn Fastabend  * an atomic per-cpu bitmap. The bpf_dtab_netdev object will not be destroyed
29546ac1ffSJohn Fastabend  * until all bits are cleared indicating outstanding flush operations have
30546ac1ffSJohn Fastabend  * completed.
31546ac1ffSJohn Fastabend  *
32546ac1ffSJohn Fastabend  * BPF syscalls may race with BPF program calls on any of the update, delete
33546ac1ffSJohn Fastabend  * or lookup operations. As noted above the xchg() operation also keep the
34546ac1ffSJohn Fastabend  * netdev_map consistent in this case. From the devmap side BPF programs
35546ac1ffSJohn Fastabend  * calling into these operations are the same as multiple user space threads
36546ac1ffSJohn Fastabend  * making system calls.
37546ac1ffSJohn Fastabend  */
38546ac1ffSJohn Fastabend #include <linux/bpf.h>
39546ac1ffSJohn Fastabend #include <linux/jhash.h>
40546ac1ffSJohn Fastabend #include <linux/filter.h>
41546ac1ffSJohn Fastabend #include <linux/rculist_nulls.h>
42546ac1ffSJohn Fastabend #include "percpu_freelist.h"
43546ac1ffSJohn Fastabend #include "bpf_lru_list.h"
44546ac1ffSJohn Fastabend #include "map_in_map.h"
45546ac1ffSJohn Fastabend 
46546ac1ffSJohn Fastabend struct bpf_dtab_netdev {
47546ac1ffSJohn Fastabend 	struct net_device *dev;
48546ac1ffSJohn Fastabend 	int key;
49546ac1ffSJohn Fastabend 	struct rcu_head rcu;
50546ac1ffSJohn Fastabend 	struct bpf_dtab *dtab;
51546ac1ffSJohn Fastabend };
52546ac1ffSJohn Fastabend 
53546ac1ffSJohn Fastabend struct bpf_dtab {
54546ac1ffSJohn Fastabend 	struct bpf_map map;
55546ac1ffSJohn Fastabend 	struct bpf_dtab_netdev **netdev_map;
56546ac1ffSJohn Fastabend };
57546ac1ffSJohn Fastabend 
58546ac1ffSJohn Fastabend static struct bpf_map *dev_map_alloc(union bpf_attr *attr)
59546ac1ffSJohn Fastabend {
60546ac1ffSJohn Fastabend 	struct bpf_dtab *dtab;
61546ac1ffSJohn Fastabend 	u64 cost;
62546ac1ffSJohn Fastabend 	int err;
63546ac1ffSJohn Fastabend 
64546ac1ffSJohn Fastabend 	/* check sanity of attributes */
65546ac1ffSJohn Fastabend 	if (attr->max_entries == 0 || attr->key_size != 4 ||
66546ac1ffSJohn Fastabend 	    attr->value_size != 4 || attr->map_flags)
67546ac1ffSJohn Fastabend 		return ERR_PTR(-EINVAL);
68546ac1ffSJohn Fastabend 
69546ac1ffSJohn Fastabend 	/* if value_size is bigger, the user space won't be able to
70546ac1ffSJohn Fastabend 	 * access the elements.
71546ac1ffSJohn Fastabend 	 */
72546ac1ffSJohn Fastabend 	if (attr->value_size > KMALLOC_MAX_SIZE)
73546ac1ffSJohn Fastabend 		return ERR_PTR(-E2BIG);
74546ac1ffSJohn Fastabend 
75546ac1ffSJohn Fastabend 	dtab = kzalloc(sizeof(*dtab), GFP_USER);
76546ac1ffSJohn Fastabend 	if (!dtab)
77546ac1ffSJohn Fastabend 		return ERR_PTR(-ENOMEM);
78546ac1ffSJohn Fastabend 
79546ac1ffSJohn Fastabend 	/* mandatory map attributes */
80546ac1ffSJohn Fastabend 	dtab->map.map_type = attr->map_type;
81546ac1ffSJohn Fastabend 	dtab->map.key_size = attr->key_size;
82546ac1ffSJohn Fastabend 	dtab->map.value_size = attr->value_size;
83546ac1ffSJohn Fastabend 	dtab->map.max_entries = attr->max_entries;
84546ac1ffSJohn Fastabend 	dtab->map.map_flags = attr->map_flags;
85546ac1ffSJohn Fastabend 
86546ac1ffSJohn Fastabend 	err = -ENOMEM;
87546ac1ffSJohn Fastabend 
88546ac1ffSJohn Fastabend 	/* make sure page count doesn't overflow */
89546ac1ffSJohn Fastabend 	cost = (u64) dtab->map.max_entries * sizeof(struct bpf_dtab_netdev *);
90546ac1ffSJohn Fastabend 	if (cost >= U32_MAX - PAGE_SIZE)
91546ac1ffSJohn Fastabend 		goto free_dtab;
92546ac1ffSJohn Fastabend 
93546ac1ffSJohn Fastabend 	dtab->map.pages = round_up(cost, PAGE_SIZE) >> PAGE_SHIFT;
94546ac1ffSJohn Fastabend 
95546ac1ffSJohn Fastabend 	/* if map size is larger than memlock limit, reject it early */
96546ac1ffSJohn Fastabend 	err = bpf_map_precharge_memlock(dtab->map.pages);
97546ac1ffSJohn Fastabend 	if (err)
98546ac1ffSJohn Fastabend 		goto free_dtab;
99546ac1ffSJohn Fastabend 
100546ac1ffSJohn Fastabend 	dtab->netdev_map = bpf_map_area_alloc(dtab->map.max_entries *
101546ac1ffSJohn Fastabend 					      sizeof(struct bpf_dtab_netdev *));
102546ac1ffSJohn Fastabend 	if (!dtab->netdev_map)
103546ac1ffSJohn Fastabend 		goto free_dtab;
104546ac1ffSJohn Fastabend 
105546ac1ffSJohn Fastabend 	return &dtab->map;
106546ac1ffSJohn Fastabend 
107546ac1ffSJohn Fastabend free_dtab:
108546ac1ffSJohn Fastabend 	kfree(dtab);
109546ac1ffSJohn Fastabend 	return ERR_PTR(err);
110546ac1ffSJohn Fastabend }
111546ac1ffSJohn Fastabend 
112546ac1ffSJohn Fastabend static void dev_map_free(struct bpf_map *map)
113546ac1ffSJohn Fastabend {
114546ac1ffSJohn Fastabend 	struct bpf_dtab *dtab = container_of(map, struct bpf_dtab, map);
115546ac1ffSJohn Fastabend 	int i;
116546ac1ffSJohn Fastabend 
117546ac1ffSJohn Fastabend 	/* At this point bpf_prog->aux->refcnt == 0 and this map->refcnt == 0,
118546ac1ffSJohn Fastabend 	 * so the programs (can be more than one that used this map) were
119546ac1ffSJohn Fastabend 	 * disconnected from events. Wait for outstanding critical sections in
120546ac1ffSJohn Fastabend 	 * these programs to complete. The rcu critical section only guarantees
121546ac1ffSJohn Fastabend 	 * no further reads against netdev_map. It does __not__ ensure pending
122546ac1ffSJohn Fastabend 	 * flush operations (if any) are complete.
123546ac1ffSJohn Fastabend 	 */
124546ac1ffSJohn Fastabend 	synchronize_rcu();
125546ac1ffSJohn Fastabend 
126546ac1ffSJohn Fastabend 	for (i = 0; i < dtab->map.max_entries; i++) {
127546ac1ffSJohn Fastabend 		struct bpf_dtab_netdev *dev;
128546ac1ffSJohn Fastabend 
129546ac1ffSJohn Fastabend 		dev = dtab->netdev_map[i];
130546ac1ffSJohn Fastabend 		if (!dev)
131546ac1ffSJohn Fastabend 			continue;
132546ac1ffSJohn Fastabend 
133546ac1ffSJohn Fastabend 		dev_put(dev->dev);
134546ac1ffSJohn Fastabend 		kfree(dev);
135546ac1ffSJohn Fastabend 	}
136546ac1ffSJohn Fastabend 
137546ac1ffSJohn Fastabend 	/* At this point bpf program is detached and all pending operations
138546ac1ffSJohn Fastabend 	 * _must_ be complete
139546ac1ffSJohn Fastabend 	 */
140546ac1ffSJohn Fastabend 	bpf_map_area_free(dtab->netdev_map);
141546ac1ffSJohn Fastabend 	kfree(dtab);
142546ac1ffSJohn Fastabend }
143546ac1ffSJohn Fastabend 
144546ac1ffSJohn Fastabend static int dev_map_get_next_key(struct bpf_map *map, void *key, void *next_key)
145546ac1ffSJohn Fastabend {
146546ac1ffSJohn Fastabend 	struct bpf_dtab *dtab = container_of(map, struct bpf_dtab, map);
147546ac1ffSJohn Fastabend 	u32 index = key ? *(u32 *)key : U32_MAX;
148546ac1ffSJohn Fastabend 	u32 *next = (u32 *)next_key;
149546ac1ffSJohn Fastabend 
150546ac1ffSJohn Fastabend 	if (index >= dtab->map.max_entries) {
151546ac1ffSJohn Fastabend 		*next = 0;
152546ac1ffSJohn Fastabend 		return 0;
153546ac1ffSJohn Fastabend 	}
154546ac1ffSJohn Fastabend 
155546ac1ffSJohn Fastabend 	if (index == dtab->map.max_entries - 1)
156546ac1ffSJohn Fastabend 		return -ENOENT;
157546ac1ffSJohn Fastabend 
158546ac1ffSJohn Fastabend 	*next = index + 1;
159546ac1ffSJohn Fastabend 	return 0;
160546ac1ffSJohn Fastabend }
161546ac1ffSJohn Fastabend 
162*97f91a7cSJohn Fastabend struct net_device  *__dev_map_lookup_elem(struct bpf_map *map, u32 key)
163*97f91a7cSJohn Fastabend {
164*97f91a7cSJohn Fastabend 	struct bpf_dtab *dtab = container_of(map, struct bpf_dtab, map);
165*97f91a7cSJohn Fastabend 	struct bpf_dtab_netdev *dev;
166*97f91a7cSJohn Fastabend 
167*97f91a7cSJohn Fastabend 	if (key >= map->max_entries)
168*97f91a7cSJohn Fastabend 		return NULL;
169*97f91a7cSJohn Fastabend 
170*97f91a7cSJohn Fastabend 	dev = READ_ONCE(dtab->netdev_map[key]);
171*97f91a7cSJohn Fastabend 	return dev ? dev->dev : NULL;
172*97f91a7cSJohn Fastabend }
173*97f91a7cSJohn Fastabend 
174546ac1ffSJohn Fastabend /* rcu_read_lock (from syscall and BPF contexts) ensures that if a delete and/or
175546ac1ffSJohn Fastabend  * update happens in parallel here a dev_put wont happen until after reading the
176546ac1ffSJohn Fastabend  * ifindex.
177546ac1ffSJohn Fastabend  */
178546ac1ffSJohn Fastabend static void *dev_map_lookup_elem(struct bpf_map *map, void *key)
179546ac1ffSJohn Fastabend {
180546ac1ffSJohn Fastabend 	struct bpf_dtab *dtab = container_of(map, struct bpf_dtab, map);
181546ac1ffSJohn Fastabend 	struct bpf_dtab_netdev *dev;
182546ac1ffSJohn Fastabend 	u32 i = *(u32 *)key;
183546ac1ffSJohn Fastabend 
184546ac1ffSJohn Fastabend 	if (i >= map->max_entries)
185546ac1ffSJohn Fastabend 		return NULL;
186546ac1ffSJohn Fastabend 
187546ac1ffSJohn Fastabend 	dev = READ_ONCE(dtab->netdev_map[i]);
188546ac1ffSJohn Fastabend 	return dev ? &dev->dev->ifindex : NULL;
189546ac1ffSJohn Fastabend }
190546ac1ffSJohn Fastabend 
191546ac1ffSJohn Fastabend static void __dev_map_entry_free(struct rcu_head *rcu)
192546ac1ffSJohn Fastabend {
193546ac1ffSJohn Fastabend 	struct bpf_dtab_netdev *old_dev;
194546ac1ffSJohn Fastabend 
195546ac1ffSJohn Fastabend 	old_dev = container_of(rcu, struct bpf_dtab_netdev, rcu);
196546ac1ffSJohn Fastabend 	dev_put(old_dev->dev);
197546ac1ffSJohn Fastabend 	kfree(old_dev);
198546ac1ffSJohn Fastabend }
199546ac1ffSJohn Fastabend 
200546ac1ffSJohn Fastabend static int dev_map_delete_elem(struct bpf_map *map, void *key)
201546ac1ffSJohn Fastabend {
202546ac1ffSJohn Fastabend 	struct bpf_dtab *dtab = container_of(map, struct bpf_dtab, map);
203546ac1ffSJohn Fastabend 	struct bpf_dtab_netdev *old_dev;
204546ac1ffSJohn Fastabend 	int k = *(u32 *)key;
205546ac1ffSJohn Fastabend 
206546ac1ffSJohn Fastabend 	if (k >= map->max_entries)
207546ac1ffSJohn Fastabend 		return -EINVAL;
208546ac1ffSJohn Fastabend 
209546ac1ffSJohn Fastabend 	/* Use synchronize_rcu() here to ensure any rcu critical sections
210546ac1ffSJohn Fastabend 	 * have completed, but this does not guarantee a flush has happened
211546ac1ffSJohn Fastabend 	 * yet. Because driver side rcu_read_lock/unlock only protects the
212546ac1ffSJohn Fastabend 	 * running XDP program. However, for pending flush operations the
213546ac1ffSJohn Fastabend 	 * dev and ctx are stored in another per cpu map. And additionally,
214546ac1ffSJohn Fastabend 	 * the driver tear down ensures all soft irqs are complete before
215546ac1ffSJohn Fastabend 	 * removing the net device in the case of dev_put equals zero.
216546ac1ffSJohn Fastabend 	 */
217546ac1ffSJohn Fastabend 	old_dev = xchg(&dtab->netdev_map[k], NULL);
218546ac1ffSJohn Fastabend 	if (old_dev)
219546ac1ffSJohn Fastabend 		call_rcu(&old_dev->rcu, __dev_map_entry_free);
220546ac1ffSJohn Fastabend 	return 0;
221546ac1ffSJohn Fastabend }
222546ac1ffSJohn Fastabend 
223546ac1ffSJohn Fastabend static int dev_map_update_elem(struct bpf_map *map, void *key, void *value,
224546ac1ffSJohn Fastabend 				u64 map_flags)
225546ac1ffSJohn Fastabend {
226546ac1ffSJohn Fastabend 	struct bpf_dtab *dtab = container_of(map, struct bpf_dtab, map);
227546ac1ffSJohn Fastabend 	struct net *net = current->nsproxy->net_ns;
228546ac1ffSJohn Fastabend 	struct bpf_dtab_netdev *dev, *old_dev;
229546ac1ffSJohn Fastabend 	u32 i = *(u32 *)key;
230546ac1ffSJohn Fastabend 	u32 ifindex = *(u32 *)value;
231546ac1ffSJohn Fastabend 
232546ac1ffSJohn Fastabend 	if (unlikely(map_flags > BPF_EXIST))
233546ac1ffSJohn Fastabend 		return -EINVAL;
234546ac1ffSJohn Fastabend 
235546ac1ffSJohn Fastabend 	if (unlikely(i >= dtab->map.max_entries))
236546ac1ffSJohn Fastabend 		return -E2BIG;
237546ac1ffSJohn Fastabend 
238546ac1ffSJohn Fastabend 	if (unlikely(map_flags == BPF_NOEXIST))
239546ac1ffSJohn Fastabend 		return -EEXIST;
240546ac1ffSJohn Fastabend 
241546ac1ffSJohn Fastabend 	if (!ifindex) {
242546ac1ffSJohn Fastabend 		dev = NULL;
243546ac1ffSJohn Fastabend 	} else {
244546ac1ffSJohn Fastabend 		dev = kmalloc(sizeof(*dev), GFP_ATOMIC | __GFP_NOWARN);
245546ac1ffSJohn Fastabend 		if (!dev)
246546ac1ffSJohn Fastabend 			return -ENOMEM;
247546ac1ffSJohn Fastabend 
248546ac1ffSJohn Fastabend 		dev->dev = dev_get_by_index(net, ifindex);
249546ac1ffSJohn Fastabend 		if (!dev->dev) {
250546ac1ffSJohn Fastabend 			kfree(dev);
251546ac1ffSJohn Fastabend 			return -EINVAL;
252546ac1ffSJohn Fastabend 		}
253546ac1ffSJohn Fastabend 
254546ac1ffSJohn Fastabend 		dev->key = i;
255546ac1ffSJohn Fastabend 		dev->dtab = dtab;
256546ac1ffSJohn Fastabend 	}
257546ac1ffSJohn Fastabend 
258546ac1ffSJohn Fastabend 	/* Use call_rcu() here to ensure rcu critical sections have completed
259546ac1ffSJohn Fastabend 	 * Remembering the driver side flush operation will happen before the
260546ac1ffSJohn Fastabend 	 * net device is removed.
261546ac1ffSJohn Fastabend 	 */
262546ac1ffSJohn Fastabend 	old_dev = xchg(&dtab->netdev_map[i], dev);
263546ac1ffSJohn Fastabend 	if (old_dev)
264546ac1ffSJohn Fastabend 		call_rcu(&old_dev->rcu, __dev_map_entry_free);
265546ac1ffSJohn Fastabend 
266546ac1ffSJohn Fastabend 	return 0;
267546ac1ffSJohn Fastabend }
268546ac1ffSJohn Fastabend 
269546ac1ffSJohn Fastabend const struct bpf_map_ops dev_map_ops = {
270546ac1ffSJohn Fastabend 	.map_alloc = dev_map_alloc,
271546ac1ffSJohn Fastabend 	.map_free = dev_map_free,
272546ac1ffSJohn Fastabend 	.map_get_next_key = dev_map_get_next_key,
273546ac1ffSJohn Fastabend 	.map_lookup_elem = dev_map_lookup_elem,
274546ac1ffSJohn Fastabend 	.map_update_elem = dev_map_update_elem,
275546ac1ffSJohn Fastabend 	.map_delete_elem = dev_map_delete_elem,
276546ac1ffSJohn Fastabend };
277