diff options
| author | Rob Herring <robh@kernel.org> | 2018-03-08 10:21:07 -0500 |
|---|---|---|
| committer | Rob Herring <robh@kernel.org> | 2018-03-08 10:21:07 -0500 |
| commit | c679fa6e3aaa5c58fc514b5b88cfa82774b8d390 (patch) | |
| tree | 0c10b339368bd1795152a66a4e245e6f654fb3ec /kernel/bpf | |
| parent | bdb7013df910681f84eff27b07791d4c160cb76f (diff) | |
| parent | 4fd98e374fd377ae0458a9dc44aa779cf9631ddd (diff) | |
Merge branch 'dtc-update' into dt/next
Diffstat (limited to 'kernel/bpf')
| -rw-r--r-- | kernel/bpf/arraymap.c | 33 | ||||
| -rw-r--r-- | kernel/bpf/core.c | 2 | ||||
| -rw-r--r-- | kernel/bpf/cpumap.c | 2 | ||||
| -rw-r--r-- | kernel/bpf/lpm_trie.c | 14 | ||||
| -rw-r--r-- | kernel/bpf/sockmap.c | 3 |
5 files changed, 32 insertions, 22 deletions
diff --git a/kernel/bpf/arraymap.c b/kernel/bpf/arraymap.c index b1f66480135b..14750e7c5ee4 100644 --- a/kernel/bpf/arraymap.c +++ b/kernel/bpf/arraymap.c | |||
| @@ -26,8 +26,10 @@ static void bpf_array_free_percpu(struct bpf_array *array) | |||
| 26 | { | 26 | { |
| 27 | int i; | 27 | int i; |
| 28 | 28 | ||
| 29 | for (i = 0; i < array->map.max_entries; i++) | 29 | for (i = 0; i < array->map.max_entries; i++) { |
| 30 | free_percpu(array->pptrs[i]); | 30 | free_percpu(array->pptrs[i]); |
| 31 | cond_resched(); | ||
| 32 | } | ||
| 31 | } | 33 | } |
| 32 | 34 | ||
| 33 | static int bpf_array_alloc_percpu(struct bpf_array *array) | 35 | static int bpf_array_alloc_percpu(struct bpf_array *array) |
| @@ -43,6 +45,7 @@ static int bpf_array_alloc_percpu(struct bpf_array *array) | |||
| 43 | return -ENOMEM; | 45 | return -ENOMEM; |
| 44 | } | 46 | } |
| 45 | array->pptrs[i] = ptr; | 47 | array->pptrs[i] = ptr; |
| 48 | cond_resched(); | ||
| 46 | } | 49 | } |
| 47 | 50 | ||
| 48 | return 0; | 51 | return 0; |
| @@ -73,11 +76,11 @@ static int array_map_alloc_check(union bpf_attr *attr) | |||
| 73 | static struct bpf_map *array_map_alloc(union bpf_attr *attr) | 76 | static struct bpf_map *array_map_alloc(union bpf_attr *attr) |
| 74 | { | 77 | { |
| 75 | bool percpu = attr->map_type == BPF_MAP_TYPE_PERCPU_ARRAY; | 78 | bool percpu = attr->map_type == BPF_MAP_TYPE_PERCPU_ARRAY; |
| 76 | int numa_node = bpf_map_attr_numa_node(attr); | 79 | int ret, numa_node = bpf_map_attr_numa_node(attr); |
| 77 | u32 elem_size, index_mask, max_entries; | 80 | u32 elem_size, index_mask, max_entries; |
| 78 | bool unpriv = !capable(CAP_SYS_ADMIN); | 81 | bool unpriv = !capable(CAP_SYS_ADMIN); |
| 82 | u64 cost, array_size, mask64; | ||
| 79 | struct bpf_array *array; | 83 | struct bpf_array *array; |
| 80 | u64 array_size, mask64; | ||
| 81 | 84 | ||
| 82 | elem_size = round_up(attr->value_size, 8); | 85 | elem_size = round_up(attr->value_size, 8); |
| 83 | 86 | ||
| @@ -109,8 +112,19 @@ static struct bpf_map *array_map_alloc(union bpf_attr *attr) | |||
| 109 | array_size += (u64) max_entries * elem_size; | 112 | array_size += (u64) max_entries * elem_size; |
| 110 | 113 | ||
| 111 | /* make sure there is no u32 overflow later in round_up() */ | 114 | /* make sure there is no u32 overflow later in round_up() */ |
| 112 | if (array_size >= U32_MAX - PAGE_SIZE) | 115 | cost = array_size; |
| 116 | if (cost >= U32_MAX - PAGE_SIZE) | ||
| 113 | return ERR_PTR(-ENOMEM); | 117 | return ERR_PTR(-ENOMEM); |
| 118 | if (percpu) { | ||
| 119 | cost += (u64)attr->max_entries * elem_size * num_possible_cpus(); | ||
| 120 | if (cost >= U32_MAX - PAGE_SIZE) | ||
| 121 | return ERR_PTR(-ENOMEM); | ||
| 122 | } | ||
| 123 | cost = round_up(cost, PAGE_SIZE) >> PAGE_SHIFT; | ||
| 124 | |||
| 125 | ret = bpf_map_precharge_memlock(cost); | ||
| 126 | if (ret < 0) | ||
| 127 | return ERR_PTR(ret); | ||
| 114 | 128 | ||
| 115 | /* allocate all map elements and zero-initialize them */ | 129 | /* allocate all map elements and zero-initialize them */ |
| 116 | array = bpf_map_area_alloc(array_size, numa_node); | 130 | array = bpf_map_area_alloc(array_size, numa_node); |
| @@ -121,20 +135,13 @@ static struct bpf_map *array_map_alloc(union bpf_attr *attr) | |||
| 121 | 135 | ||
| 122 | /* copy mandatory map attributes */ | 136 | /* copy mandatory map attributes */ |
| 123 | bpf_map_init_from_attr(&array->map, attr); | 137 | bpf_map_init_from_attr(&array->map, attr); |
| 138 | array->map.pages = cost; | ||
| 124 | array->elem_size = elem_size; | 139 | array->elem_size = elem_size; |
| 125 | 140 | ||
| 126 | if (!percpu) | 141 | if (percpu && bpf_array_alloc_percpu(array)) { |
| 127 | goto out; | ||
| 128 | |||
| 129 | array_size += (u64) attr->max_entries * elem_size * num_possible_cpus(); | ||
| 130 | |||
| 131 | if (array_size >= U32_MAX - PAGE_SIZE || | ||
| 132 | bpf_array_alloc_percpu(array)) { | ||
| 133 | bpf_map_area_free(array); | 142 | bpf_map_area_free(array); |
| 134 | return ERR_PTR(-ENOMEM); | 143 | return ERR_PTR(-ENOMEM); |
| 135 | } | 144 | } |
| 136 | out: | ||
| 137 | array->map.pages = round_up(array_size, PAGE_SIZE) >> PAGE_SHIFT; | ||
| 138 | 145 | ||
| 139 | return &array->map; | 146 | return &array->map; |
| 140 | } | 147 | } |
diff --git a/kernel/bpf/core.c b/kernel/bpf/core.c index 29ca9208dcfa..d315b393abdd 100644 --- a/kernel/bpf/core.c +++ b/kernel/bpf/core.c | |||
| @@ -1590,7 +1590,7 @@ int bpf_prog_array_copy_to_user(struct bpf_prog_array __rcu *progs, | |||
| 1590 | * so always copy 'cnt' prog_ids to the user. | 1590 | * so always copy 'cnt' prog_ids to the user. |
| 1591 | * In a rare race the user will see zero prog_ids | 1591 | * In a rare race the user will see zero prog_ids |
| 1592 | */ | 1592 | */ |
| 1593 | ids = kcalloc(cnt, sizeof(u32), GFP_USER); | 1593 | ids = kcalloc(cnt, sizeof(u32), GFP_USER | __GFP_NOWARN); |
| 1594 | if (!ids) | 1594 | if (!ids) |
| 1595 | return -ENOMEM; | 1595 | return -ENOMEM; |
| 1596 | rcu_read_lock(); | 1596 | rcu_read_lock(); |
diff --git a/kernel/bpf/cpumap.c b/kernel/bpf/cpumap.c index fbfdada6caee..a4bb0b34375a 100644 --- a/kernel/bpf/cpumap.c +++ b/kernel/bpf/cpumap.c | |||
| @@ -334,7 +334,7 @@ static int cpu_map_kthread_run(void *data) | |||
| 334 | static struct bpf_cpu_map_entry *__cpu_map_entry_alloc(u32 qsize, u32 cpu, | 334 | static struct bpf_cpu_map_entry *__cpu_map_entry_alloc(u32 qsize, u32 cpu, |
| 335 | int map_id) | 335 | int map_id) |
| 336 | { | 336 | { |
| 337 | gfp_t gfp = GFP_ATOMIC|__GFP_NOWARN; | 337 | gfp_t gfp = GFP_KERNEL | __GFP_NOWARN; |
| 338 | struct bpf_cpu_map_entry *rcpu; | 338 | struct bpf_cpu_map_entry *rcpu; |
| 339 | int numa, err; | 339 | int numa, err; |
| 340 | 340 | ||
diff --git a/kernel/bpf/lpm_trie.c b/kernel/bpf/lpm_trie.c index 7b469d10d0e9..b4b5b81e7251 100644 --- a/kernel/bpf/lpm_trie.c +++ b/kernel/bpf/lpm_trie.c | |||
| @@ -555,7 +555,10 @@ static void trie_free(struct bpf_map *map) | |||
| 555 | struct lpm_trie_node __rcu **slot; | 555 | struct lpm_trie_node __rcu **slot; |
| 556 | struct lpm_trie_node *node; | 556 | struct lpm_trie_node *node; |
| 557 | 557 | ||
| 558 | raw_spin_lock(&trie->lock); | 558 | /* Wait for outstanding programs to complete |
| 559 | * update/lookup/delete/get_next_key and free the trie. | ||
| 560 | */ | ||
| 561 | synchronize_rcu(); | ||
| 559 | 562 | ||
| 560 | /* Always start at the root and walk down to a node that has no | 563 | /* Always start at the root and walk down to a node that has no |
| 561 | * children. Then free that node, nullify its reference in the parent | 564 | * children. Then free that node, nullify its reference in the parent |
| @@ -566,10 +569,9 @@ static void trie_free(struct bpf_map *map) | |||
| 566 | slot = &trie->root; | 569 | slot = &trie->root; |
| 567 | 570 | ||
| 568 | for (;;) { | 571 | for (;;) { |
| 569 | node = rcu_dereference_protected(*slot, | 572 | node = rcu_dereference_protected(*slot, 1); |
| 570 | lockdep_is_held(&trie->lock)); | ||
| 571 | if (!node) | 573 | if (!node) |
| 572 | goto unlock; | 574 | goto out; |
| 573 | 575 | ||
| 574 | if (rcu_access_pointer(node->child[0])) { | 576 | if (rcu_access_pointer(node->child[0])) { |
| 575 | slot = &node->child[0]; | 577 | slot = &node->child[0]; |
| @@ -587,8 +589,8 @@ static void trie_free(struct bpf_map *map) | |||
| 587 | } | 589 | } |
| 588 | } | 590 | } |
| 589 | 591 | ||
| 590 | unlock: | 592 | out: |
| 591 | raw_spin_unlock(&trie->lock); | 593 | kfree(trie); |
| 592 | } | 594 | } |
| 593 | 595 | ||
| 594 | static int trie_get_next_key(struct bpf_map *map, void *_key, void *_next_key) | 596 | static int trie_get_next_key(struct bpf_map *map, void *_key, void *_next_key) |
diff --git a/kernel/bpf/sockmap.c b/kernel/bpf/sockmap.c index 48c33417d13c..a927e89dad6e 100644 --- a/kernel/bpf/sockmap.c +++ b/kernel/bpf/sockmap.c | |||
| @@ -521,8 +521,8 @@ static struct smap_psock *smap_init_psock(struct sock *sock, | |||
| 521 | static struct bpf_map *sock_map_alloc(union bpf_attr *attr) | 521 | static struct bpf_map *sock_map_alloc(union bpf_attr *attr) |
| 522 | { | 522 | { |
| 523 | struct bpf_stab *stab; | 523 | struct bpf_stab *stab; |
| 524 | int err = -EINVAL; | ||
| 525 | u64 cost; | 524 | u64 cost; |
| 525 | int err; | ||
| 526 | 526 | ||
| 527 | if (!capable(CAP_NET_ADMIN)) | 527 | if (!capable(CAP_NET_ADMIN)) |
| 528 | return ERR_PTR(-EPERM); | 528 | return ERR_PTR(-EPERM); |
| @@ -547,6 +547,7 @@ static struct bpf_map *sock_map_alloc(union bpf_attr *attr) | |||
| 547 | 547 | ||
| 548 | /* make sure page count doesn't overflow */ | 548 | /* make sure page count doesn't overflow */ |
| 549 | cost = (u64) stab->map.max_entries * sizeof(struct sock *); | 549 | cost = (u64) stab->map.max_entries * sizeof(struct sock *); |
| 550 | err = -EINVAL; | ||
| 550 | if (cost >= U32_MAX - PAGE_SIZE) | 551 | if (cost >= U32_MAX - PAGE_SIZE) |
| 551 | goto free_stab; | 552 | goto free_stab; |
| 552 | 553 | ||
