Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

bpf: Use kvmalloc for map values in syscall

Use kvmalloc/kvfree for temporary value when manipulating a map via
syscall. kmalloc might not be sufficient for percpu maps where the value
is big (and further multiplied by hundreds of CPUs).

Can be reproduced with netcnt test on qemu with "-smp 255".

Signed-off-by: Stanislav Fomichev <sdf@google.com>
Signed-off-by: Daniel Borkmann <daniel@iogearbox.net>
Acked-by: Song Liu <songliubraving@fb.com>
Link: https://lore.kernel.org/bpf/20210818235216.1159202-1-sdf@google.com

authored by

Stanislav Fomichev and committed by
Daniel Borkmann
f0dce1d9 3666b167

+11 -17
+11 -17
kernel/bpf/syscall.c
··· 1076 1076 value_size = bpf_map_value_size(map); 1077 1077 1078 1078 err = -ENOMEM; 1079 - value = kmalloc(value_size, GFP_USER | __GFP_NOWARN); 1079 + value = kvmalloc(value_size, GFP_USER | __GFP_NOWARN); 1080 1080 if (!value) 1081 1081 goto free_key; 1082 1082 ··· 1091 1091 err = 0; 1092 1092 1093 1093 free_value: 1094 - kfree(value); 1094 + kvfree(value); 1095 1095 free_key: 1096 1096 kfree(key); 1097 1097 err_put: ··· 1137 1137 goto err_put; 1138 1138 } 1139 1139 1140 - if (map->map_type == BPF_MAP_TYPE_PERCPU_HASH || 1141 - map->map_type == BPF_MAP_TYPE_LRU_PERCPU_HASH || 1142 - map->map_type == BPF_MAP_TYPE_PERCPU_ARRAY || 1143 - map->map_type == BPF_MAP_TYPE_PERCPU_CGROUP_STORAGE) 1144 - value_size = round_up(map->value_size, 8) * num_possible_cpus(); 1145 - else 1146 - value_size = map->value_size; 1140 + value_size = bpf_map_value_size(map); 1147 1141 1148 1142 err = -ENOMEM; 1149 - value = kmalloc(value_size, GFP_USER | __GFP_NOWARN); 1143 + value = kvmalloc(value_size, GFP_USER | __GFP_NOWARN); 1150 1144 if (!value) 1151 1145 goto free_key; 1152 1146 ··· 1151 1157 err = bpf_map_update_value(map, f, key, value, attr->flags); 1152 1158 1153 1159 free_value: 1154 - kfree(value); 1160 + kvfree(value); 1155 1161 free_key: 1156 1162 kfree(key); 1157 1163 err_put: ··· 1361 1367 if (!key) 1362 1368 return -ENOMEM; 1363 1369 1364 - value = kmalloc(value_size, GFP_USER | __GFP_NOWARN); 1370 + value = kvmalloc(value_size, GFP_USER | __GFP_NOWARN); 1365 1371 if (!value) { 1366 1372 kfree(key); 1367 1373 return -ENOMEM; ··· 1384 1390 if (copy_to_user(&uattr->batch.count, &cp, sizeof(cp))) 1385 1391 err = -EFAULT; 1386 1392 1387 - kfree(value); 1393 + kvfree(value); 1388 1394 kfree(key); 1389 1395 return err; 1390 1396 } ··· 1423 1429 if (!buf_prevkey) 1424 1430 return -ENOMEM; 1425 1431 1426 - buf = kmalloc(map->key_size + value_size, GFP_USER | __GFP_NOWARN); 1432 + buf = kvmalloc(map->key_size + value_size, GFP_USER | __GFP_NOWARN); 1427 1433 if (!buf) { 1428 1434 kfree(buf_prevkey); 1429 1435 return -ENOMEM; ··· 1486 1492 1487 1493 free_buf: 1488 1494 kfree(buf_prevkey); 1489 - kfree(buf); 1495 + kvfree(buf); 1490 1496 return err; 1491 1497 } 1492 1498 ··· 1541 1547 value_size = bpf_map_value_size(map); 1542 1548 1543 1549 err = -ENOMEM; 1544 - value = kmalloc(value_size, GFP_USER | __GFP_NOWARN); 1550 + value = kvmalloc(value_size, GFP_USER | __GFP_NOWARN); 1545 1551 if (!value) 1546 1552 goto free_key; 1547 1553 ··· 1573 1579 err = 0; 1574 1580 1575 1581 free_value: 1576 - kfree(value); 1582 + kvfree(value); 1577 1583 free_key: 1578 1584 kfree(key); 1579 1585 err_put: