As discussed in [0], it's dangerous to allow mapping BPF map, that's meant to be frozen and is read-only on BPF program side, because that allows user-space to actually store a writable view to the page even after it is frozen. This is exacerbated by BPF verifier making a strong assumption that contents of such frozen map will remain unchanged. To prevent this, disallow mapping BPF_F_RDONLY_PROG mmap()'able BPF maps as writable, ever. [0] https://lore.kernel.org/bpf/CAEf4BzYGWYhXdp6BJ7_=9OQPJxQpgug080MMjdSB72i9R+5c6g@mail.gmail.com/
Showing the changes to kernel (1 of 3 files). Show all
Unified · Split
| @@ -623,9 +623,20 @@ static int bpf_map_mmap(struct file *filp, struct vm_area_struct *vma) · 622 unmodified lines | ||
| 623 | 623 | |
| 624 | 624 | mutex_lock(&map->freeze_mutex); |
| 625 | 625 | |
| 626 | − if ((vma->vm_flags & VM_WRITE) && map->frozen) { | |
| 627 | − err = -EPERM; | |
| 628 | − goto out; | |
| 626 | + if (vma->vm_flags & VM_WRITE) { | |
| 627 | + if (map->frozen) { | |
| 628 | + err = -EPERM; | |
| 629 | + goto out; | |
| 630 | + } | |
| 631 | + /* map is meant to be read-only, so do not allow mapping as | |
| 632 | + * writable, because it's possible to leak a writable page | |
| 633 | + * reference and allows user-space to still modify it after | |
| 634 | + * freezing, while verifier will assume contents do not change | |
| 635 | + */ | |
| 636 | + if (map->map_flags & BPF_F_RDONLY_PROG) { | |
| 637 | + err = -EACCES; | |
| 638 | + goto out; | |
| 639 | + } | |
| 629 | 640 | } |
| 630 | 641 | |
| 631 | 642 | /* set default open/close callbacks */ |