Skip to content

Commit b9d37bb

Browse files
committed
Merge git://git.kernel.org/pub/scm/linux/kernel/git/bpf/bpf
Alexei Starovoitov says: ==================== pull-request: bpf 2020-06-17 The following pull-request contains BPF updates for your *net* tree. We've added 10 non-merge commits during the last 2 day(s) which contain a total of 14 files changed, 158 insertions(+), 59 deletions(-). The main changes are: 1) Important fix for bpf_probe_read_kernel_str() return value, from Andrii. 2) [gs]etsockopt fix for large optlen, from Stanislav. 3) devmap allocation fix, from Toke. ==================== Signed-off-by: David S. Miller <[email protected]>
2 parents 6911967 + 8030e25 commit b9d37bb

File tree

14 files changed

+158
-59
lines changed

14 files changed

+158
-59
lines changed

Documentation/bpf/prog_cgroup_sockopt.rst

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -86,6 +86,20 @@ then the next program in the chain (A) will see those changes,
8686
*not* the original input ``setsockopt`` arguments. The potentially
8787
modified values will be then passed down to the kernel.
8888

89+
Large optval
90+
============
91+
When the ``optval`` is greater than the ``PAGE_SIZE``, the BPF program
92+
can access only the first ``PAGE_SIZE`` of that data. So it has to options:
93+
94+
* Set ``optlen`` to zero, which indicates that the kernel should
95+
use the original buffer from the userspace. Any modifications
96+
done by the BPF program to the ``optval`` are ignored.
97+
* Set ``optlen`` to the value less than ``PAGE_SIZE``, which
98+
indicates that the kernel should use BPF's trimmed ``optval``.
99+
100+
When the BPF program returns with the ``optlen`` greater than
101+
``PAGE_SIZE``, the userspace will receive ``EFAULT`` errno.
102+
89103
Example
90104
=======
91105

include/uapi/linux/bpf.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3168,7 +3168,7 @@ union bpf_attr {
31683168
* Return
31693169
* The id is returned or 0 in case the id could not be retrieved.
31703170
*
3171-
* void *bpf_ringbuf_output(void *ringbuf, void *data, u64 size, u64 flags)
3171+
* int bpf_ringbuf_output(void *ringbuf, void *data, u64 size, u64 flags)
31723172
* Description
31733173
* Copy *size* bytes from *data* into a ring buffer *ringbuf*.
31743174
* If BPF_RB_NO_WAKEUP is specified in *flags*, no notification of

kernel/bpf/cgroup.c

Lines changed: 33 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -1276,16 +1276,23 @@ static bool __cgroup_bpf_prog_array_is_empty(struct cgroup *cgrp,
12761276

12771277
static int sockopt_alloc_buf(struct bpf_sockopt_kern *ctx, int max_optlen)
12781278
{
1279-
if (unlikely(max_optlen > PAGE_SIZE) || max_optlen < 0)
1279+
if (unlikely(max_optlen < 0))
12801280
return -EINVAL;
12811281

1282+
if (unlikely(max_optlen > PAGE_SIZE)) {
1283+
/* We don't expose optvals that are greater than PAGE_SIZE
1284+
* to the BPF program.
1285+
*/
1286+
max_optlen = PAGE_SIZE;
1287+
}
1288+
12821289
ctx->optval = kzalloc(max_optlen, GFP_USER);
12831290
if (!ctx->optval)
12841291
return -ENOMEM;
12851292

12861293
ctx->optval_end = ctx->optval + max_optlen;
12871294

1288-
return 0;
1295+
return max_optlen;
12891296
}
12901297

12911298
static void sockopt_free_buf(struct bpf_sockopt_kern *ctx)
@@ -1319,13 +1326,13 @@ int __cgroup_bpf_run_filter_setsockopt(struct sock *sk, int *level,
13191326
*/
13201327
max_optlen = max_t(int, 16, *optlen);
13211328

1322-
ret = sockopt_alloc_buf(&ctx, max_optlen);
1323-
if (ret)
1324-
return ret;
1329+
max_optlen = sockopt_alloc_buf(&ctx, max_optlen);
1330+
if (max_optlen < 0)
1331+
return max_optlen;
13251332

13261333
ctx.optlen = *optlen;
13271334

1328-
if (copy_from_user(ctx.optval, optval, *optlen) != 0) {
1335+
if (copy_from_user(ctx.optval, optval, min(*optlen, max_optlen)) != 0) {
13291336
ret = -EFAULT;
13301337
goto out;
13311338
}
@@ -1353,8 +1360,14 @@ int __cgroup_bpf_run_filter_setsockopt(struct sock *sk, int *level,
13531360
/* export any potential modifications */
13541361
*level = ctx.level;
13551362
*optname = ctx.optname;
1356-
*optlen = ctx.optlen;
1357-
*kernel_optval = ctx.optval;
1363+
1364+
/* optlen == 0 from BPF indicates that we should
1365+
* use original userspace data.
1366+
*/
1367+
if (ctx.optlen != 0) {
1368+
*optlen = ctx.optlen;
1369+
*kernel_optval = ctx.optval;
1370+
}
13581371
}
13591372

13601373
out:
@@ -1385,12 +1398,12 @@ int __cgroup_bpf_run_filter_getsockopt(struct sock *sk, int level,
13851398
__cgroup_bpf_prog_array_is_empty(cgrp, BPF_CGROUP_GETSOCKOPT))
13861399
return retval;
13871400

1388-
ret = sockopt_alloc_buf(&ctx, max_optlen);
1389-
if (ret)
1390-
return ret;
1391-
13921401
ctx.optlen = max_optlen;
13931402

1403+
max_optlen = sockopt_alloc_buf(&ctx, max_optlen);
1404+
if (max_optlen < 0)
1405+
return max_optlen;
1406+
13941407
if (!retval) {
13951408
/* If kernel getsockopt finished successfully,
13961409
* copy whatever was returned to the user back
@@ -1404,10 +1417,8 @@ int __cgroup_bpf_run_filter_getsockopt(struct sock *sk, int level,
14041417
goto out;
14051418
}
14061419

1407-
if (ctx.optlen > max_optlen)
1408-
ctx.optlen = max_optlen;
1409-
1410-
if (copy_from_user(ctx.optval, optval, ctx.optlen) != 0) {
1420+
if (copy_from_user(ctx.optval, optval,
1421+
min(ctx.optlen, max_optlen)) != 0) {
14111422
ret = -EFAULT;
14121423
goto out;
14131424
}
@@ -1436,10 +1447,12 @@ int __cgroup_bpf_run_filter_getsockopt(struct sock *sk, int level,
14361447
goto out;
14371448
}
14381449

1439-
if (copy_to_user(optval, ctx.optval, ctx.optlen) ||
1440-
put_user(ctx.optlen, optlen)) {
1441-
ret = -EFAULT;
1442-
goto out;
1450+
if (ctx.optlen != 0) {
1451+
if (copy_to_user(optval, ctx.optval, ctx.optlen) ||
1452+
put_user(ctx.optlen, optlen)) {
1453+
ret = -EFAULT;
1454+
goto out;
1455+
}
14431456
}
14441457

14451458
ret = ctx.retval;

kernel/bpf/devmap.c

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -86,12 +86,13 @@ static DEFINE_PER_CPU(struct list_head, dev_flush_list);
8686
static DEFINE_SPINLOCK(dev_map_lock);
8787
static LIST_HEAD(dev_map_list);
8888

89-
static struct hlist_head *dev_map_create_hash(unsigned int entries)
89+
static struct hlist_head *dev_map_create_hash(unsigned int entries,
90+
int numa_node)
9091
{
9192
int i;
9293
struct hlist_head *hash;
9394

94-
hash = kmalloc_array(entries, sizeof(*hash), GFP_KERNEL);
95+
hash = bpf_map_area_alloc(entries * sizeof(*hash), numa_node);
9596
if (hash != NULL)
9697
for (i = 0; i < entries; i++)
9798
INIT_HLIST_HEAD(&hash[i]);
@@ -145,7 +146,8 @@ static int dev_map_init_map(struct bpf_dtab *dtab, union bpf_attr *attr)
145146
return -EINVAL;
146147

147148
if (attr->map_type == BPF_MAP_TYPE_DEVMAP_HASH) {
148-
dtab->dev_index_head = dev_map_create_hash(dtab->n_buckets);
149+
dtab->dev_index_head = dev_map_create_hash(dtab->n_buckets,
150+
dtab->map.numa_node);
149151
if (!dtab->dev_index_head)
150152
goto free_charge;
151153

@@ -232,7 +234,7 @@ static void dev_map_free(struct bpf_map *map)
232234
}
233235
}
234236

235-
kfree(dtab->dev_index_head);
237+
bpf_map_area_free(dtab->dev_index_head);
236238
} else {
237239
for (i = 0; i < dtab->map.max_entries; i++) {
238240
struct bpf_dtab_netdev *dev;

kernel/trace/bpf_trace.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -241,7 +241,7 @@ bpf_probe_read_kernel_str_common(void *dst, u32 size, const void *unsafe_ptr)
241241
if (unlikely(ret < 0))
242242
goto fail;
243243

244-
return 0;
244+
return ret;
245245
fail:
246246
memset(dst, 0, size);
247247
return ret;

net/core/xdp.c

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -462,6 +462,7 @@ struct xdp_frame *xdp_convert_zc_to_xdp_frame(struct xdp_buff *xdp)
462462
xdpf->len = totsize - metasize;
463463
xdpf->headroom = 0;
464464
xdpf->metasize = metasize;
465+
xdpf->frame_sz = PAGE_SIZE;
465466
xdpf->mem.type = MEM_TYPE_PAGE_ORDER0;
466467

467468
xsk_buff_free(xdp);

samples/bpf/xdp_monitor_user.c

Lines changed: 2 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -509,11 +509,8 @@ static void *alloc_rec_per_cpu(int record_size)
509509
{
510510
unsigned int nr_cpus = bpf_num_possible_cpus();
511511
void *array;
512-
size_t size;
513512

514-
size = record_size * nr_cpus;
515-
array = malloc(size);
516-
memset(array, 0, size);
513+
array = calloc(nr_cpus, record_size);
517514
if (!array) {
518515
fprintf(stderr, "Mem alloc error (nr_cpus:%u)\n", nr_cpus);
519516
exit(EXIT_FAIL_MEM);
@@ -528,8 +525,7 @@ static struct stats_record *alloc_stats_record(void)
528525
int i;
529526

530527
/* Alloc main stats_record structure */
531-
rec = malloc(sizeof(*rec));
532-
memset(rec, 0, sizeof(*rec));
528+
rec = calloc(1, sizeof(*rec));
533529
if (!rec) {
534530
fprintf(stderr, "Mem alloc error\n");
535531
exit(EXIT_FAIL_MEM);

samples/bpf/xdp_redirect_cpu_user.c

Lines changed: 2 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -207,11 +207,8 @@ static struct datarec *alloc_record_per_cpu(void)
207207
{
208208
unsigned int nr_cpus = bpf_num_possible_cpus();
209209
struct datarec *array;
210-
size_t size;
211210

212-
size = sizeof(struct datarec) * nr_cpus;
213-
array = malloc(size);
214-
memset(array, 0, size);
211+
array = calloc(nr_cpus, sizeof(struct datarec));
215212
if (!array) {
216213
fprintf(stderr, "Mem alloc error (nr_cpus:%u)\n", nr_cpus);
217214
exit(EXIT_FAIL_MEM);
@@ -226,11 +223,11 @@ static struct stats_record *alloc_stats_record(void)
226223

227224
size = sizeof(*rec) + n_cpus * sizeof(struct record);
228225
rec = malloc(size);
229-
memset(rec, 0, size);
230226
if (!rec) {
231227
fprintf(stderr, "Mem alloc error\n");
232228
exit(EXIT_FAIL_MEM);
233229
}
230+
memset(rec, 0, size);
234231
rec->rx_cnt.cpu = alloc_record_per_cpu();
235232
rec->redir_err.cpu = alloc_record_per_cpu();
236233
rec->kthread.cpu = alloc_record_per_cpu();

samples/bpf/xdp_rxq_info_user.c

Lines changed: 3 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -198,11 +198,8 @@ static struct datarec *alloc_record_per_cpu(void)
198198
{
199199
unsigned int nr_cpus = bpf_num_possible_cpus();
200200
struct datarec *array;
201-
size_t size;
202201

203-
size = sizeof(struct datarec) * nr_cpus;
204-
array = malloc(size);
205-
memset(array, 0, size);
202+
array = calloc(nr_cpus, sizeof(struct datarec));
206203
if (!array) {
207204
fprintf(stderr, "Mem alloc error (nr_cpus:%u)\n", nr_cpus);
208205
exit(EXIT_FAIL_MEM);
@@ -214,11 +211,8 @@ static struct record *alloc_record_per_rxq(void)
214211
{
215212
unsigned int nr_rxqs = bpf_map__def(rx_queue_index_map)->max_entries;
216213
struct record *array;
217-
size_t size;
218214

219-
size = sizeof(struct record) * nr_rxqs;
220-
array = malloc(size);
221-
memset(array, 0, size);
215+
array = calloc(nr_rxqs, sizeof(struct record));
222216
if (!array) {
223217
fprintf(stderr, "Mem alloc error (nr_rxqs:%u)\n", nr_rxqs);
224218
exit(EXIT_FAIL_MEM);
@@ -232,8 +226,7 @@ static struct stats_record *alloc_stats_record(void)
232226
struct stats_record *rec;
233227
int i;
234228

235-
rec = malloc(sizeof(*rec));
236-
memset(rec, 0, sizeof(*rec));
229+
rec = calloc(1, sizeof(struct stats_record));
237230
if (!rec) {
238231
fprintf(stderr, "Mem alloc error\n");
239232
exit(EXIT_FAIL_MEM);

tools/bpf/bpftool/Documentation/bpftool-map.rst

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -49,7 +49,7 @@ MAP COMMANDS
4949
| | **lru_percpu_hash** | **lpm_trie** | **array_of_maps** | **hash_of_maps**
5050
| | **devmap** | **devmap_hash** | **sockmap** | **cpumap** | **xskmap** | **sockhash**
5151
| | **cgroup_storage** | **reuseport_sockarray** | **percpu_cgroup_storage**
52-
| | **queue** | **stack** | **sk_storage** | **struct_ops** }
52+
| | **queue** | **stack** | **sk_storage** | **struct_ops** | **ringbuf** }
5353
5454
DESCRIPTION
5555
===========

0 commit comments

Comments
 (0)