History

bpf_lru_list: Read double-checked variable once without lock

For double-checked locking in bpf_common_lru_push_free(), node->type is read outside the critical section and then re-checked under the lock. However, concurrent writes to node->type result in data races. For example, the following concurrent access was observed by KCSAN: write to 0xffff88801521bc22 of 1 bytes by task 10038 on cpu 1: __bpf_lru_node_move_in kernel/bpf/bpf_lru_list.c:91 __local_list_flush kernel/bpf/bpf_lru_list.c:298 ... read to 0xffff88801521bc22 of 1 bytes by task 10043 on cpu 0: bpf_common_lru_push_free kernel/bpf/bpf_lru_list.c:507 bpf_lru_push_free kernel/bpf/bpf_lru_list.c:555 ... Fix the data races where node->type is read outside the critical section (for double-checked locking) by marking the access with READ_ONCE() as well as ensuring the variable is only accessed once.

Marco Elver committed 5 years ago

Commit 6df8fb81 parent bd2d4e61 file · +4 −3Browse files

Unified · Split

kernel/bpf/bpf_lru_list.c+4−3
@@ -502,13 +502,14 @@ struct bpf_lru_node *bpf_lru_pop_free(struct bpf_lru *lru, u32 hash) · 501 unmodified lines
502502 static void bpf_common_lru_push_free(struct bpf_lru *lru,
503503 struct bpf_lru_node *node)
504504 {
505+ u8 node_type = READ_ONCE(node->type);
505506 unsigned long flags;
506507
507− if (WARN_ON_ONCE(node->type == BPF_LRU_LIST_T_FREE) ||
508− WARN_ON_ONCE(node->type == BPF_LRU_LOCAL_LIST_T_FREE))
508+ if (WARN_ON_ONCE(node_type == BPF_LRU_LIST_T_FREE) ||
509+ WARN_ON_ONCE(node_type == BPF_LRU_LOCAL_LIST_T_FREE))
509510 return;
510511
511− if (node->type == BPF_LRU_LOCAL_LIST_T_PENDING) {
512+ if (node_type == BPF_LRU_LOCAL_LIST_T_PENDING) {
512513 struct bpf_lru_locallist *loc_l;
513514
514515 loc_l = per_cpu_ptr(lru->common_lru.local_list, node->cpu);

Keyboard shortcuts

General

Show keyboard shortcuts
?
Focus the current search
/

Issues and pull requests

Open filters
f

Issues, pull requests and Inbox

Select next item
j↓
Select previous item
k↑
Open selected item
Enter
Dismiss filters or clear selection
Esc

Repository code

Go to file
t