diff options
Diffstat (limited to 'kernel/bpf/arraymap.c')
-rw-r--r-- | kernel/bpf/arraymap.c | 18 |
1 files changed, 8 insertions, 10 deletions
diff --git a/kernel/bpf/arraymap.c b/kernel/bpf/arraymap.c index 584636c9e2eb..0349cbf23cdb 100644 --- a/kernel/bpf/arraymap.c +++ b/kernel/bpf/arraymap.c | |||
@@ -83,6 +83,7 @@ static struct bpf_map *array_map_alloc(union bpf_attr *attr) | |||
83 | u32 elem_size, index_mask, max_entries; | 83 | u32 elem_size, index_mask, max_entries; |
84 | bool unpriv = !capable(CAP_SYS_ADMIN); | 84 | bool unpriv = !capable(CAP_SYS_ADMIN); |
85 | u64 cost, array_size, mask64; | 85 | u64 cost, array_size, mask64; |
86 | struct bpf_map_memory mem; | ||
86 | struct bpf_array *array; | 87 | struct bpf_array *array; |
87 | 88 | ||
88 | elem_size = round_up(attr->value_size, 8); | 89 | elem_size = round_up(attr->value_size, 8); |
@@ -116,32 +117,29 @@ static struct bpf_map *array_map_alloc(union bpf_attr *attr) | |||
116 | 117 | ||
117 | /* make sure there is no u32 overflow later in round_up() */ | 118 | /* make sure there is no u32 overflow later in round_up() */ |
118 | cost = array_size; | 119 | cost = array_size; |
119 | if (cost >= U32_MAX - PAGE_SIZE) | 120 | if (percpu) |
120 | return ERR_PTR(-ENOMEM); | ||
121 | if (percpu) { | ||
122 | cost += (u64)attr->max_entries * elem_size * num_possible_cpus(); | 121 | cost += (u64)attr->max_entries * elem_size * num_possible_cpus(); |
123 | if (cost >= U32_MAX - PAGE_SIZE) | ||
124 | return ERR_PTR(-ENOMEM); | ||
125 | } | ||
126 | cost = round_up(cost, PAGE_SIZE) >> PAGE_SHIFT; | ||
127 | 122 | ||
128 | ret = bpf_map_precharge_memlock(cost); | 123 | ret = bpf_map_charge_init(&mem, cost); |
129 | if (ret < 0) | 124 | if (ret < 0) |
130 | return ERR_PTR(ret); | 125 | return ERR_PTR(ret); |
131 | 126 | ||
132 | /* allocate all map elements and zero-initialize them */ | 127 | /* allocate all map elements and zero-initialize them */ |
133 | array = bpf_map_area_alloc(array_size, numa_node); | 128 | array = bpf_map_area_alloc(array_size, numa_node); |
134 | if (!array) | 129 | if (!array) { |
130 | bpf_map_charge_finish(&mem); | ||
135 | return ERR_PTR(-ENOMEM); | 131 | return ERR_PTR(-ENOMEM); |
132 | } | ||
136 | array->index_mask = index_mask; | 133 | array->index_mask = index_mask; |
137 | array->map.unpriv_array = unpriv; | 134 | array->map.unpriv_array = unpriv; |
138 | 135 | ||
139 | /* copy mandatory map attributes */ | 136 | /* copy mandatory map attributes */ |
140 | bpf_map_init_from_attr(&array->map, attr); | 137 | bpf_map_init_from_attr(&array->map, attr); |
141 | array->map.pages = cost; | 138 | bpf_map_charge_move(&array->map.memory, &mem); |
142 | array->elem_size = elem_size; | 139 | array->elem_size = elem_size; |
143 | 140 | ||
144 | if (percpu && bpf_array_alloc_percpu(array)) { | 141 | if (percpu && bpf_array_alloc_percpu(array)) { |
142 | bpf_map_charge_finish(&array->map.memory); | ||
145 | bpf_map_area_free(array); | 143 | bpf_map_area_free(array); |
146 | return ERR_PTR(-ENOMEM); | 144 | return ERR_PTR(-ENOMEM); |
147 | } | 145 | } |