aboutsummaryrefslogtreecommitdiffstats
path: root/kernel
diff options
context:
space:
mode:
Diffstat (limited to 'kernel')
-rw-r--r--kernel/bpf/helpers.c8
-rw-r--r--kernel/bpf/local_storage.c150
-rw-r--r--kernel/bpf/syscall.c11
-rw-r--r--kernel/bpf/verifier.c15
4 files changed, 157 insertions, 27 deletions
diff --git a/kernel/bpf/helpers.c b/kernel/bpf/helpers.c
index e42f8789b7ea..6502115e8f55 100644
--- a/kernel/bpf/helpers.c
+++ b/kernel/bpf/helpers.c
@@ -206,10 +206,16 @@ BPF_CALL_2(bpf_get_local_storage, struct bpf_map *, map, u64, flags)
206 */ 206 */
207 enum bpf_cgroup_storage_type stype = cgroup_storage_type(map); 207 enum bpf_cgroup_storage_type stype = cgroup_storage_type(map);
208 struct bpf_cgroup_storage *storage; 208 struct bpf_cgroup_storage *storage;
209 void *ptr;
209 210
210 storage = this_cpu_read(bpf_cgroup_storage[stype]); 211 storage = this_cpu_read(bpf_cgroup_storage[stype]);
211 212
212 return (unsigned long)&READ_ONCE(storage->buf)->data[0]; 213 if (stype == BPF_CGROUP_STORAGE_SHARED)
214 ptr = &READ_ONCE(storage->buf)->data[0];
215 else
216 ptr = this_cpu_ptr(storage->percpu_buf);
217
218 return (unsigned long)ptr;
213} 219}
214 220
215const struct bpf_func_proto bpf_get_local_storage_proto = { 221const struct bpf_func_proto bpf_get_local_storage_proto = {
diff --git a/kernel/bpf/local_storage.c b/kernel/bpf/local_storage.c
index 6742292fb39e..944eb297465f 100644
--- a/kernel/bpf/local_storage.c
+++ b/kernel/bpf/local_storage.c
@@ -152,6 +152,71 @@ static int cgroup_storage_update_elem(struct bpf_map *map, void *_key,
152 return 0; 152 return 0;
153} 153}
154 154
155int bpf_percpu_cgroup_storage_copy(struct bpf_map *_map, void *_key,
156 void *value)
157{
158 struct bpf_cgroup_storage_map *map = map_to_storage(_map);
159 struct bpf_cgroup_storage_key *key = _key;
160 struct bpf_cgroup_storage *storage;
161 int cpu, off = 0;
162 u32 size;
163
164 rcu_read_lock();
165 storage = cgroup_storage_lookup(map, key, false);
166 if (!storage) {
167 rcu_read_unlock();
168 return -ENOENT;
169 }
170
171 /* per_cpu areas are zero-filled and bpf programs can only
172 * access 'value_size' of them, so copying rounded areas
173 * will not leak any kernel data
174 */
175 size = round_up(_map->value_size, 8);
176 for_each_possible_cpu(cpu) {
177 bpf_long_memcpy(value + off,
178 per_cpu_ptr(storage->percpu_buf, cpu), size);
179 off += size;
180 }
181 rcu_read_unlock();
182 return 0;
183}
184
185int bpf_percpu_cgroup_storage_update(struct bpf_map *_map, void *_key,
186 void *value, u64 map_flags)
187{
188 struct bpf_cgroup_storage_map *map = map_to_storage(_map);
189 struct bpf_cgroup_storage_key *key = _key;
190 struct bpf_cgroup_storage *storage;
191 int cpu, off = 0;
192 u32 size;
193
194 if (map_flags != BPF_ANY && map_flags != BPF_EXIST)
195 return -EINVAL;
196
197 rcu_read_lock();
198 storage = cgroup_storage_lookup(map, key, false);
199 if (!storage) {
200 rcu_read_unlock();
201 return -ENOENT;
202 }
203
204 /* the user space will provide round_up(value_size, 8) bytes that
205 * will be copied into per-cpu area. bpf programs can only access
206 * value_size of it. During lookup the same extra bytes will be
207 * returned or zeros which were zero-filled by percpu_alloc,
208 * so no kernel data leaks possible
209 */
210 size = round_up(_map->value_size, 8);
211 for_each_possible_cpu(cpu) {
212 bpf_long_memcpy(per_cpu_ptr(storage->percpu_buf, cpu),
213 value + off, size);
214 off += size;
215 }
216 rcu_read_unlock();
217 return 0;
218}
219
155static int cgroup_storage_get_next_key(struct bpf_map *_map, void *_key, 220static int cgroup_storage_get_next_key(struct bpf_map *_map, void *_key,
156 void *_next_key) 221 void *_next_key)
157{ 222{
@@ -287,60 +352,105 @@ void bpf_cgroup_storage_release(struct bpf_prog *prog, struct bpf_map *_map)
287 spin_unlock_bh(&map->lock); 352 spin_unlock_bh(&map->lock);
288} 353}
289 354
355static size_t bpf_cgroup_storage_calculate_size(struct bpf_map *map, u32 *pages)
356{
357 size_t size;
358
359 if (cgroup_storage_type(map) == BPF_CGROUP_STORAGE_SHARED) {
360 size = sizeof(struct bpf_storage_buffer) + map->value_size;
361 *pages = round_up(sizeof(struct bpf_cgroup_storage) + size,
362 PAGE_SIZE) >> PAGE_SHIFT;
363 } else {
364 size = map->value_size;
365 *pages = round_up(round_up(size, 8) * num_possible_cpus(),
366 PAGE_SIZE) >> PAGE_SHIFT;
367 }
368
369 return size;
370}
371
290struct bpf_cgroup_storage *bpf_cgroup_storage_alloc(struct bpf_prog *prog, 372struct bpf_cgroup_storage *bpf_cgroup_storage_alloc(struct bpf_prog *prog,
291 enum bpf_cgroup_storage_type stype) 373 enum bpf_cgroup_storage_type stype)
292{ 374{
293 struct bpf_cgroup_storage *storage; 375 struct bpf_cgroup_storage *storage;
294 struct bpf_map *map; 376 struct bpf_map *map;
377 gfp_t flags;
378 size_t size;
295 u32 pages; 379 u32 pages;
296 380
297 map = prog->aux->cgroup_storage[stype]; 381 map = prog->aux->cgroup_storage[stype];
298 if (!map) 382 if (!map)
299 return NULL; 383 return NULL;
300 384
301 pages = round_up(sizeof(struct bpf_cgroup_storage) + 385 size = bpf_cgroup_storage_calculate_size(map, &pages);
302 sizeof(struct bpf_storage_buffer) + 386
303 map->value_size, PAGE_SIZE) >> PAGE_SHIFT;
304 if (bpf_map_charge_memlock(map, pages)) 387 if (bpf_map_charge_memlock(map, pages))
305 return ERR_PTR(-EPERM); 388 return ERR_PTR(-EPERM);
306 389
307 storage = kmalloc_node(sizeof(struct bpf_cgroup_storage), 390 storage = kmalloc_node(sizeof(struct bpf_cgroup_storage),
308 __GFP_ZERO | GFP_USER, map->numa_node); 391 __GFP_ZERO | GFP_USER, map->numa_node);
309 if (!storage) { 392 if (!storage)
310 bpf_map_uncharge_memlock(map, pages); 393 goto enomem;
311 return ERR_PTR(-ENOMEM);
312 }
313 394
314 storage->buf = kmalloc_node(sizeof(struct bpf_storage_buffer) + 395 flags = __GFP_ZERO | GFP_USER;
315 map->value_size, __GFP_ZERO | GFP_USER, 396
316 map->numa_node); 397 if (stype == BPF_CGROUP_STORAGE_SHARED) {
317 if (!storage->buf) { 398 storage->buf = kmalloc_node(size, flags, map->numa_node);
318 bpf_map_uncharge_memlock(map, pages); 399 if (!storage->buf)
319 kfree(storage); 400 goto enomem;
320 return ERR_PTR(-ENOMEM); 401 } else {
402 storage->percpu_buf = __alloc_percpu_gfp(size, 8, flags);
403 if (!storage->percpu_buf)
404 goto enomem;
321 } 405 }
322 406
323 storage->map = (struct bpf_cgroup_storage_map *)map; 407 storage->map = (struct bpf_cgroup_storage_map *)map;
324 408
325 return storage; 409 return storage;
410
411enomem:
412 bpf_map_uncharge_memlock(map, pages);
413 kfree(storage);
414 return ERR_PTR(-ENOMEM);
415}
416
417static void free_shared_cgroup_storage_rcu(struct rcu_head *rcu)
418{
419 struct bpf_cgroup_storage *storage =
420 container_of(rcu, struct bpf_cgroup_storage, rcu);
421
422 kfree(storage->buf);
423 kfree(storage);
424}
425
426static void free_percpu_cgroup_storage_rcu(struct rcu_head *rcu)
427{
428 struct bpf_cgroup_storage *storage =
429 container_of(rcu, struct bpf_cgroup_storage, rcu);
430
431 free_percpu(storage->percpu_buf);
432 kfree(storage);
326} 433}
327 434
328void bpf_cgroup_storage_free(struct bpf_cgroup_storage *storage) 435void bpf_cgroup_storage_free(struct bpf_cgroup_storage *storage)
329{ 436{
330 u32 pages; 437 enum bpf_cgroup_storage_type stype;
331 struct bpf_map *map; 438 struct bpf_map *map;
439 u32 pages;
332 440
333 if (!storage) 441 if (!storage)
334 return; 442 return;
335 443
336 map = &storage->map->map; 444 map = &storage->map->map;
337 pages = round_up(sizeof(struct bpf_cgroup_storage) + 445
338 sizeof(struct bpf_storage_buffer) + 446 bpf_cgroup_storage_calculate_size(map, &pages);
339 map->value_size, PAGE_SIZE) >> PAGE_SHIFT;
340 bpf_map_uncharge_memlock(map, pages); 447 bpf_map_uncharge_memlock(map, pages);
341 448
342 kfree_rcu(storage->buf, rcu); 449 stype = cgroup_storage_type(map);
343 kfree_rcu(storage, rcu); 450 if (stype == BPF_CGROUP_STORAGE_SHARED)
451 call_rcu(&storage->rcu, free_shared_cgroup_storage_rcu);
452 else
453 call_rcu(&storage->rcu, free_percpu_cgroup_storage_rcu);
344} 454}
345 455
346void bpf_cgroup_storage_link(struct bpf_cgroup_storage *storage, 456void bpf_cgroup_storage_link(struct bpf_cgroup_storage *storage,
diff --git a/kernel/bpf/syscall.c b/kernel/bpf/syscall.c
index 8c91d2b41b1e..5742df21598c 100644
--- a/kernel/bpf/syscall.c
+++ b/kernel/bpf/syscall.c
@@ -686,7 +686,8 @@ static int map_lookup_elem(union bpf_attr *attr)
686 686
687 if (map->map_type == BPF_MAP_TYPE_PERCPU_HASH || 687 if (map->map_type == BPF_MAP_TYPE_PERCPU_HASH ||
688 map->map_type == BPF_MAP_TYPE_LRU_PERCPU_HASH || 688 map->map_type == BPF_MAP_TYPE_LRU_PERCPU_HASH ||
689 map->map_type == BPF_MAP_TYPE_PERCPU_ARRAY) 689 map->map_type == BPF_MAP_TYPE_PERCPU_ARRAY ||
690 map->map_type == BPF_MAP_TYPE_PERCPU_CGROUP_STORAGE)
690 value_size = round_up(map->value_size, 8) * num_possible_cpus(); 691 value_size = round_up(map->value_size, 8) * num_possible_cpus();
691 else if (IS_FD_MAP(map)) 692 else if (IS_FD_MAP(map))
692 value_size = sizeof(u32); 693 value_size = sizeof(u32);
@@ -705,6 +706,8 @@ static int map_lookup_elem(union bpf_attr *attr)
705 err = bpf_percpu_hash_copy(map, key, value); 706 err = bpf_percpu_hash_copy(map, key, value);
706 } else if (map->map_type == BPF_MAP_TYPE_PERCPU_ARRAY) { 707 } else if (map->map_type == BPF_MAP_TYPE_PERCPU_ARRAY) {
707 err = bpf_percpu_array_copy(map, key, value); 708 err = bpf_percpu_array_copy(map, key, value);
709 } else if (map->map_type == BPF_MAP_TYPE_PERCPU_CGROUP_STORAGE) {
710 err = bpf_percpu_cgroup_storage_copy(map, key, value);
708 } else if (map->map_type == BPF_MAP_TYPE_STACK_TRACE) { 711 } else if (map->map_type == BPF_MAP_TYPE_STACK_TRACE) {
709 err = bpf_stackmap_copy(map, key, value); 712 err = bpf_stackmap_copy(map, key, value);
710 } else if (IS_FD_ARRAY(map)) { 713 } else if (IS_FD_ARRAY(map)) {
@@ -774,7 +777,8 @@ static int map_update_elem(union bpf_attr *attr)
774 777
775 if (map->map_type == BPF_MAP_TYPE_PERCPU_HASH || 778 if (map->map_type == BPF_MAP_TYPE_PERCPU_HASH ||
776 map->map_type == BPF_MAP_TYPE_LRU_PERCPU_HASH || 779 map->map_type == BPF_MAP_TYPE_LRU_PERCPU_HASH ||
777 map->map_type == BPF_MAP_TYPE_PERCPU_ARRAY) 780 map->map_type == BPF_MAP_TYPE_PERCPU_ARRAY ||
781 map->map_type == BPF_MAP_TYPE_PERCPU_CGROUP_STORAGE)
778 value_size = round_up(map->value_size, 8) * num_possible_cpus(); 782 value_size = round_up(map->value_size, 8) * num_possible_cpus();
779 else 783 else
780 value_size = map->value_size; 784 value_size = map->value_size;
@@ -809,6 +813,9 @@ static int map_update_elem(union bpf_attr *attr)
809 err = bpf_percpu_hash_update(map, key, value, attr->flags); 813 err = bpf_percpu_hash_update(map, key, value, attr->flags);
810 } else if (map->map_type == BPF_MAP_TYPE_PERCPU_ARRAY) { 814 } else if (map->map_type == BPF_MAP_TYPE_PERCPU_ARRAY) {
811 err = bpf_percpu_array_update(map, key, value, attr->flags); 815 err = bpf_percpu_array_update(map, key, value, attr->flags);
816 } else if (map->map_type == BPF_MAP_TYPE_PERCPU_CGROUP_STORAGE) {
817 err = bpf_percpu_cgroup_storage_update(map, key, value,
818 attr->flags);
812 } else if (IS_FD_ARRAY(map)) { 819 } else if (IS_FD_ARRAY(map)) {
813 rcu_read_lock(); 820 rcu_read_lock();
814 err = bpf_fd_array_map_update_elem(map, f.file, key, value, 821 err = bpf_fd_array_map_update_elem(map, f.file, key, value,
diff --git a/kernel/bpf/verifier.c b/kernel/bpf/verifier.c
index e90899df585d..a8cc83a970d1 100644
--- a/kernel/bpf/verifier.c
+++ b/kernel/bpf/verifier.c
@@ -2074,6 +2074,7 @@ static int check_map_func_compatibility(struct bpf_verifier_env *env,
2074 goto error; 2074 goto error;
2075 break; 2075 break;
2076 case BPF_MAP_TYPE_CGROUP_STORAGE: 2076 case BPF_MAP_TYPE_CGROUP_STORAGE:
2077 case BPF_MAP_TYPE_PERCPU_CGROUP_STORAGE:
2077 if (func_id != BPF_FUNC_get_local_storage) 2078 if (func_id != BPF_FUNC_get_local_storage)
2078 goto error; 2079 goto error;
2079 break; 2080 break;
@@ -2164,7 +2165,8 @@ static int check_map_func_compatibility(struct bpf_verifier_env *env,
2164 goto error; 2165 goto error;
2165 break; 2166 break;
2166 case BPF_FUNC_get_local_storage: 2167 case BPF_FUNC_get_local_storage:
2167 if (map->map_type != BPF_MAP_TYPE_CGROUP_STORAGE) 2168 if (map->map_type != BPF_MAP_TYPE_CGROUP_STORAGE &&
2169 map->map_type != BPF_MAP_TYPE_PERCPU_CGROUP_STORAGE)
2168 goto error; 2170 goto error;
2169 break; 2171 break;
2170 case BPF_FUNC_sk_select_reuseport: 2172 case BPF_FUNC_sk_select_reuseport:
@@ -5049,6 +5051,12 @@ static int check_map_prog_compatibility(struct bpf_verifier_env *env,
5049 return 0; 5051 return 0;
5050} 5052}
5051 5053
5054static bool bpf_map_is_cgroup_storage(struct bpf_map *map)
5055{
5056 return (map->map_type == BPF_MAP_TYPE_CGROUP_STORAGE ||
5057 map->map_type == BPF_MAP_TYPE_PERCPU_CGROUP_STORAGE);
5058}
5059
5052/* look for pseudo eBPF instructions that access map FDs and 5060/* look for pseudo eBPF instructions that access map FDs and
5053 * replace them with actual map pointers 5061 * replace them with actual map pointers
5054 */ 5062 */
@@ -5139,10 +5147,9 @@ static int replace_map_fd_with_map_ptr(struct bpf_verifier_env *env)
5139 } 5147 }
5140 env->used_maps[env->used_map_cnt++] = map; 5148 env->used_maps[env->used_map_cnt++] = map;
5141 5149
5142 if (map->map_type == BPF_MAP_TYPE_CGROUP_STORAGE && 5150 if (bpf_map_is_cgroup_storage(map) &&
5143 bpf_cgroup_storage_assign(env->prog, map)) { 5151 bpf_cgroup_storage_assign(env->prog, map)) {
5144 verbose(env, 5152 verbose(env, "only one cgroup storage of each type is allowed\n");
5145 "only one cgroup storage is allowed\n");
5146 fdput(f); 5153 fdput(f);
5147 return -EBUSY; 5154 return -EBUSY;
5148 } 5155 }