|
7 | 7 | #include <linux/fs.h>
|
8 | 8 | #include <linux/fdtable.h>
|
9 | 9 | #include <linux/filter.h>
|
| 10 | +#include <linux/bpf_mem_alloc.h> |
10 | 11 | #include <linux/btf_ids.h>
|
| 12 | +#include <linux/mm_types.h> |
11 | 13 | #include "mmap_unlock_work.h"
|
12 | 14 |
|
13 | 15 | static const char * const iter_task_type_names[] = {
|
@@ -803,6 +805,95 @@ const struct bpf_func_proto bpf_find_vma_proto = {
|
803 | 805 | .arg5_type = ARG_ANYTHING,
|
804 | 806 | };
|
805 | 807 |
|
| 808 | +struct bpf_iter_task_vma_kern_data { |
| 809 | + struct task_struct *task; |
| 810 | + struct mm_struct *mm; |
| 811 | + struct mmap_unlock_irq_work *work; |
| 812 | + struct vma_iterator vmi; |
| 813 | +}; |
| 814 | + |
| 815 | +struct bpf_iter_task_vma { |
| 816 | + /* opaque iterator state; having __u64 here allows to preserve correct |
| 817 | + * alignment requirements in vmlinux.h, generated from BTF |
| 818 | + */ |
| 819 | + __u64 __opaque[1]; |
| 820 | +} __attribute__((aligned(8))); |
| 821 | + |
| 822 | +/* Non-opaque version of bpf_iter_task_vma */ |
| 823 | +struct bpf_iter_task_vma_kern { |
| 824 | + struct bpf_iter_task_vma_kern_data *data; |
| 825 | +} __attribute__((aligned(8))); |
| 826 | + |
| 827 | +__diag_push(); |
| 828 | +__diag_ignore_all("-Wmissing-prototypes", |
| 829 | + "Global functions as their definitions will be in vmlinux BTF"); |
| 830 | + |
| 831 | +__bpf_kfunc int bpf_iter_task_vma_new(struct bpf_iter_task_vma *it, |
| 832 | + struct task_struct *task, u64 addr) |
| 833 | +{ |
| 834 | + struct bpf_iter_task_vma_kern *kit = (void *)it; |
| 835 | + bool irq_work_busy = false; |
| 836 | + int err; |
| 837 | + |
| 838 | + BUILD_BUG_ON(sizeof(struct bpf_iter_task_vma_kern) != sizeof(struct bpf_iter_task_vma)); |
| 839 | + BUILD_BUG_ON(__alignof__(struct bpf_iter_task_vma_kern) != __alignof__(struct bpf_iter_task_vma)); |
| 840 | + |
| 841 | + /* is_iter_reg_valid_uninit guarantees that kit hasn't been initialized |
| 842 | + * before, so non-NULL kit->data doesn't point to previously |
| 843 | + * bpf_mem_alloc'd bpf_iter_task_vma_kern_data |
| 844 | + */ |
| 845 | + kit->data = bpf_mem_alloc(&bpf_global_ma, sizeof(struct bpf_iter_task_vma_kern_data)); |
| 846 | + if (!kit->data) |
| 847 | + return -ENOMEM; |
| 848 | + |
| 849 | + kit->data->task = get_task_struct(task); |
| 850 | + kit->data->mm = task->mm; |
| 851 | + if (!kit->data->mm) { |
| 852 | + err = -ENOENT; |
| 853 | + goto err_cleanup_iter; |
| 854 | + } |
| 855 | + |
| 856 | + /* kit->data->work == NULL is valid after bpf_mmap_unlock_get_irq_work */ |
| 857 | + irq_work_busy = bpf_mmap_unlock_get_irq_work(&kit->data->work); |
| 858 | + if (irq_work_busy || !mmap_read_trylock(kit->data->mm)) { |
| 859 | + err = -EBUSY; |
| 860 | + goto err_cleanup_iter; |
| 861 | + } |
| 862 | + |
| 863 | + vma_iter_init(&kit->data->vmi, kit->data->mm, addr); |
| 864 | + return 0; |
| 865 | + |
| 866 | +err_cleanup_iter: |
| 867 | + if (kit->data->task) |
| 868 | + put_task_struct(kit->data->task); |
| 869 | + bpf_mem_free(&bpf_global_ma, kit->data); |
| 870 | + /* NULL kit->data signals failed bpf_iter_task_vma initialization */ |
| 871 | + kit->data = NULL; |
| 872 | + return err; |
| 873 | +} |
| 874 | + |
| 875 | +__bpf_kfunc struct vm_area_struct *bpf_iter_task_vma_next(struct bpf_iter_task_vma *it) |
| 876 | +{ |
| 877 | + struct bpf_iter_task_vma_kern *kit = (void *)it; |
| 878 | + |
| 879 | + if (!kit->data) /* bpf_iter_task_vma_new failed */ |
| 880 | + return NULL; |
| 881 | + return vma_next(&kit->data->vmi); |
| 882 | +} |
| 883 | + |
| 884 | +__bpf_kfunc void bpf_iter_task_vma_destroy(struct bpf_iter_task_vma *it) |
| 885 | +{ |
| 886 | + struct bpf_iter_task_vma_kern *kit = (void *)it; |
| 887 | + |
| 888 | + if (kit->data) { |
| 889 | + bpf_mmap_unlock_mm(kit->data->work, kit->data->mm); |
| 890 | + put_task_struct(kit->data->task); |
| 891 | + bpf_mem_free(&bpf_global_ma, kit->data); |
| 892 | + } |
| 893 | +} |
| 894 | + |
| 895 | +__diag_pop(); |
| 896 | + |
806 | 897 | DEFINE_PER_CPU(struct mmap_unlock_irq_work, mmap_unlock_work);
|
807 | 898 |
|
808 | 899 | static void do_mmap_read_unlock(struct irq_work *entry)
|
|
0 commit comments