Skip to content

Commit e002434

Browse files
committed
Merge git://git.kernel.org/pub/scm/linux/kernel/git/bpf/bpf
Daniel Borkmann says: ==================== pull-request: bpf 2018-05-03 The following pull-request contains BPF updates for your *net* tree. The main changes are: 1) Several BPF sockmap fixes mostly related to bugs in error path handling, that is, a bug in updating the scatterlist length / offset accounting, a missing sk_mem_uncharge() in redirect error handling, and a bug where the outstanding bytes counter sg_size was not zeroed, from John. 2) Fix two memory leaks in the x86-64 BPF JIT, one in an error path where we still don't converge after image was allocated and another one where BPF calls are used and JIT passes don't converge, from Daniel. 3) Minor fix in BPF selftests where in test_stacktrace_build_id() we drop useless args in urandom_read and we need to add a missing newline in a CHECK() error message, from Song. ==================== Signed-off-by: David S. Miller <[email protected]>
2 parents 7df40c2 + b5b6ff7 commit e002434

File tree

4 files changed

+36
-29
lines changed

4 files changed

+36
-29
lines changed

arch/x86/net/bpf_jit_comp.c

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1236,6 +1236,7 @@ struct bpf_prog *bpf_int_jit_compile(struct bpf_prog *prog)
12361236
for (pass = 0; pass < 20 || image; pass++) {
12371237
proglen = do_jit(prog, addrs, image, oldproglen, &ctx);
12381238
if (proglen <= 0) {
1239+
out_image:
12391240
image = NULL;
12401241
if (header)
12411242
bpf_jit_binary_free(header);
@@ -1246,8 +1247,7 @@ struct bpf_prog *bpf_int_jit_compile(struct bpf_prog *prog)
12461247
if (proglen != oldproglen) {
12471248
pr_err("bpf_jit: proglen=%d != oldproglen=%d\n",
12481249
proglen, oldproglen);
1249-
prog = orig_prog;
1250-
goto out_addrs;
1250+
goto out_image;
12511251
}
12521252
break;
12531253
}
@@ -1283,7 +1283,7 @@ struct bpf_prog *bpf_int_jit_compile(struct bpf_prog *prog)
12831283
prog = orig_prog;
12841284
}
12851285

1286-
if (!prog->is_func || extra_pass) {
1286+
if (!image || !prog->is_func || extra_pass) {
12871287
out_addrs:
12881288
kfree(addrs);
12891289
kfree(jit_data);

kernel/bpf/sockmap.c

Lines changed: 26 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -326,15 +326,16 @@ static int bpf_tcp_push(struct sock *sk, int apply_bytes,
326326
if (ret > 0) {
327327
if (apply)
328328
apply_bytes -= ret;
329+
330+
sg->offset += ret;
331+
sg->length -= ret;
329332
size -= ret;
330333
offset += ret;
331334
if (uncharge)
332335
sk_mem_uncharge(sk, ret);
333336
goto retry;
334337
}
335338

336-
sg->length = size;
337-
sg->offset = offset;
338339
return ret;
339340
}
340341

@@ -392,7 +393,8 @@ static void return_mem_sg(struct sock *sk, int bytes, struct sk_msg_buff *md)
392393
} while (i != md->sg_end);
393394
}
394395

395-
static void free_bytes_sg(struct sock *sk, int bytes, struct sk_msg_buff *md)
396+
static void free_bytes_sg(struct sock *sk, int bytes,
397+
struct sk_msg_buff *md, bool charge)
396398
{
397399
struct scatterlist *sg = md->sg_data;
398400
int i = md->sg_start, free;
@@ -402,11 +404,13 @@ static void free_bytes_sg(struct sock *sk, int bytes, struct sk_msg_buff *md)
402404
if (bytes < free) {
403405
sg[i].length -= bytes;
404406
sg[i].offset += bytes;
405-
sk_mem_uncharge(sk, bytes);
407+
if (charge)
408+
sk_mem_uncharge(sk, bytes);
406409
break;
407410
}
408411

409-
sk_mem_uncharge(sk, sg[i].length);
412+
if (charge)
413+
sk_mem_uncharge(sk, sg[i].length);
410414
put_page(sg_page(&sg[i]));
411415
bytes -= sg[i].length;
412416
sg[i].length = 0;
@@ -417,6 +421,7 @@ static void free_bytes_sg(struct sock *sk, int bytes, struct sk_msg_buff *md)
417421
if (i == MAX_SKB_FRAGS)
418422
i = 0;
419423
}
424+
md->sg_start = i;
420425
}
421426

422427
static int free_sg(struct sock *sk, int start, struct sk_msg_buff *md)
@@ -575,10 +580,10 @@ static int bpf_tcp_sendmsg_do_redirect(struct sock *sk, int send,
575580
struct sk_msg_buff *md,
576581
int flags)
577582
{
583+
bool ingress = !!(md->flags & BPF_F_INGRESS);
578584
struct smap_psock *psock;
579585
struct scatterlist *sg;
580-
int i, err, free = 0;
581-
bool ingress = !!(md->flags & BPF_F_INGRESS);
586+
int err = 0;
582587

583588
sg = md->sg_data;
584589

@@ -606,16 +611,8 @@ static int bpf_tcp_sendmsg_do_redirect(struct sock *sk, int send,
606611
out_rcu:
607612
rcu_read_unlock();
608613
out:
609-
i = md->sg_start;
610-
while (sg[i].length) {
611-
free += sg[i].length;
612-
put_page(sg_page(&sg[i]));
613-
sg[i].length = 0;
614-
i++;
615-
if (i == MAX_SKB_FRAGS)
616-
i = 0;
617-
}
618-
return free;
614+
free_bytes_sg(NULL, send, md, false);
615+
return err;
619616
}
620617

621618
static inline void bpf_md_init(struct smap_psock *psock)
@@ -700,19 +697,26 @@ static int bpf_exec_tx_verdict(struct smap_psock *psock,
700697
err = bpf_tcp_sendmsg_do_redirect(redir, send, m, flags);
701698
lock_sock(sk);
702699

700+
if (unlikely(err < 0)) {
701+
free_start_sg(sk, m);
702+
psock->sg_size = 0;
703+
if (!cork)
704+
*copied -= send;
705+
} else {
706+
psock->sg_size -= send;
707+
}
708+
703709
if (cork) {
704710
free_start_sg(sk, m);
711+
psock->sg_size = 0;
705712
kfree(m);
706713
m = NULL;
714+
err = 0;
707715
}
708-
if (unlikely(err))
709-
*copied -= err;
710-
else
711-
psock->sg_size -= send;
712716
break;
713717
case __SK_DROP:
714718
default:
715-
free_bytes_sg(sk, send, m);
719+
free_bytes_sg(sk, send, m, true);
716720
apply_bytes_dec(psock, send);
717721
*copied -= send;
718722
psock->sg_size -= send;

tools/bpf/bpf_dbg.c

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1063,7 +1063,7 @@ static int cmd_load_pcap(char *file)
10631063

10641064
static int cmd_load(char *arg)
10651065
{
1066-
char *subcmd, *cont, *tmp = strdup(arg);
1066+
char *subcmd, *cont = NULL, *tmp = strdup(arg);
10671067
int ret = CMD_OK;
10681068

10691069
subcmd = strtok_r(tmp, " ", &cont);
@@ -1073,7 +1073,10 @@ static int cmd_load(char *arg)
10731073
bpf_reset();
10741074
bpf_reset_breakpoints();
10751075

1076-
ret = cmd_load_bpf(cont);
1076+
if (!cont)
1077+
ret = CMD_ERR;
1078+
else
1079+
ret = cmd_load_bpf(cont);
10771080
} else if (matches(subcmd, "pcap") == 0) {
10781081
ret = cmd_load_pcap(cont);
10791082
} else {

tools/testing/selftests/bpf/test_progs.c

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1108,7 +1108,7 @@ static void test_stacktrace_build_id(void)
11081108

11091109
assert(system("dd if=/dev/urandom of=/dev/zero count=4 2> /dev/null")
11101110
== 0);
1111-
assert(system("./urandom_read if=/dev/urandom of=/dev/zero count=4 2> /dev/null") == 0);
1111+
assert(system("./urandom_read") == 0);
11121112
/* disable stack trace collection */
11131113
key = 0;
11141114
val = 1;
@@ -1158,7 +1158,7 @@ static void test_stacktrace_build_id(void)
11581158
} while (bpf_map_get_next_key(stackmap_fd, &previous_key, &key) == 0);
11591159

11601160
CHECK(build_id_matches < 1, "build id match",
1161-
"Didn't find expected build ID from the map");
1161+
"Didn't find expected build ID from the map\n");
11621162

11631163
disable_pmu:
11641164
ioctl(pmu_fd, PERF_EVENT_IOC_DISABLE);

0 commit comments

Comments
 (0)