Skip to content

Commit 274043c

Browse files
borkmanndavem330
authored andcommitted
bpf: fix double free from dev_map_notification()
In the current code, dev_map_free() can still race with dev_map_notification(). In dev_map_free(), we remove dtab from the list of dtabs after we purged all entries from it. However, we don't do xchg() with NULL or the like, so the entry at that point is still pointing to the device. If a unregister notification comes in at the same time, we therefore risk a double-free, since the pointer is still present in the map, and then pushed again to __dev_map_entry_free(). All this is completely unnecessary. Just remove the dtab from the list right before the synchronize_rcu(), so all outstanding readers from the notifier list have finished by then, thus we don't need to deal with this corner case anymore and also wouldn't need to nullify dev entires. This is fine because we iterate over the map releasing all entries and therefore dev references anyway. Fixes: 4cc7b95 ("bpf: devmap fix mutex in rcu critical section") Signed-off-by: Daniel Borkmann <[email protected]> Acked-by: Alexei Starovoitov <[email protected]> Signed-off-by: David S. Miller <[email protected]>
1 parent 63bfc50 commit 274043c

File tree

1 file changed

+5
-7
lines changed

1 file changed

+5
-7
lines changed

kernel/bpf/devmap.c

Lines changed: 5 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -148,6 +148,11 @@ static void dev_map_free(struct bpf_map *map)
148148
* no further reads against netdev_map. It does __not__ ensure pending
149149
* flush operations (if any) are complete.
150150
*/
151+
152+
spin_lock(&dev_map_lock);
153+
list_del_rcu(&dtab->list);
154+
spin_unlock(&dev_map_lock);
155+
151156
synchronize_rcu();
152157

153158
/* To ensure all pending flush operations have completed wait for flush
@@ -162,10 +167,6 @@ static void dev_map_free(struct bpf_map *map)
162167
cpu_relax();
163168
}
164169

165-
/* Although we should no longer have datapath or bpf syscall operations
166-
* at this point we we can still race with netdev notifier, hence the
167-
* lock.
168-
*/
169170
for (i = 0; i < dtab->map.max_entries; i++) {
170171
struct bpf_dtab_netdev *dev;
171172

@@ -180,9 +181,6 @@ static void dev_map_free(struct bpf_map *map)
180181
/* At this point bpf program is detached and all pending operations
181182
* _must_ be complete
182183
*/
183-
spin_lock(&dev_map_lock);
184-
list_del_rcu(&dtab->list);
185-
spin_unlock(&dev_map_lock);
186184
free_percpu(dtab->flush_needed);
187185
bpf_map_area_free(dtab->netdev_map);
188186
kfree(dtab);

0 commit comments

Comments
 (0)