Skip to content

Commit 1682d8d

Browse files
committed
Merge git://git.kernel.org/pub/scm/linux/kernel/git/bpf/bpf
Daniel Borkmann says: ==================== pull-request: bpf 2021-05-04 The following pull-request contains BPF updates for your *net* tree. We've added 5 non-merge commits during the last 4 day(s) which contain a total of 6 files changed, 52 insertions(+), 30 deletions(-). The main changes are: 1) Fix libbpf overflow when processing BPF ring buffer in case of extreme application behavior, from Brendan Jackman. 2) Fix potential data leakage of uninitialized BPF stack under speculative execution, from Daniel Borkmann. 3) Fix off-by-one when validating xsk pool chunks, from Xuan Zhuo. 4) Fix snprintf BPF selftest with a pid filter to avoid racing its output test buffer, from Florent Revest. ==================== Signed-off-by: David S. Miller <[email protected]>
2 parents bd1af6b + ac31565 commit 1682d8d

File tree

6 files changed

+52
-30
lines changed

6 files changed

+52
-30
lines changed

include/linux/bpf_verifier.h

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -302,10 +302,11 @@ struct bpf_verifier_state_list {
302302
};
303303

304304
/* Possible states for alu_state member. */
305-
#define BPF_ALU_SANITIZE_SRC 1U
306-
#define BPF_ALU_SANITIZE_DST 2U
305+
#define BPF_ALU_SANITIZE_SRC (1U << 0)
306+
#define BPF_ALU_SANITIZE_DST (1U << 1)
307307
#define BPF_ALU_NEG_VALUE (1U << 2)
308308
#define BPF_ALU_NON_POINTER (1U << 3)
309+
#define BPF_ALU_IMMEDIATE (1U << 4)
309310
#define BPF_ALU_SANITIZE (BPF_ALU_SANITIZE_SRC | \
310311
BPF_ALU_SANITIZE_DST)
311312

kernel/bpf/verifier.c

Lines changed: 18 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -6496,6 +6496,7 @@ static int sanitize_ptr_alu(struct bpf_verifier_env *env,
64966496
{
64976497
struct bpf_insn_aux_data *aux = commit_window ? cur_aux(env) : tmp_aux;
64986498
struct bpf_verifier_state *vstate = env->cur_state;
6499+
bool off_is_imm = tnum_is_const(off_reg->var_off);
64996500
bool off_is_neg = off_reg->smin_value < 0;
65006501
bool ptr_is_dst_reg = ptr_reg == dst_reg;
65016502
u8 opcode = BPF_OP(insn->code);
@@ -6526,6 +6527,7 @@ static int sanitize_ptr_alu(struct bpf_verifier_env *env,
65266527
alu_limit = abs(tmp_aux->alu_limit - alu_limit);
65276528
} else {
65286529
alu_state = off_is_neg ? BPF_ALU_NEG_VALUE : 0;
6530+
alu_state |= off_is_imm ? BPF_ALU_IMMEDIATE : 0;
65296531
alu_state |= ptr_is_dst_reg ?
65306532
BPF_ALU_SANITIZE_SRC : BPF_ALU_SANITIZE_DST;
65316533
}
@@ -12371,7 +12373,7 @@ static int do_misc_fixups(struct bpf_verifier_env *env)
1237112373
const u8 code_add = BPF_ALU64 | BPF_ADD | BPF_X;
1237212374
const u8 code_sub = BPF_ALU64 | BPF_SUB | BPF_X;
1237312375
struct bpf_insn *patch = &insn_buf[0];
12374-
bool issrc, isneg;
12376+
bool issrc, isneg, isimm;
1237512377
u32 off_reg;
1237612378

1237712379
aux = &env->insn_aux_data[i + delta];
@@ -12382,28 +12384,29 @@ static int do_misc_fixups(struct bpf_verifier_env *env)
1238212384
isneg = aux->alu_state & BPF_ALU_NEG_VALUE;
1238312385
issrc = (aux->alu_state & BPF_ALU_SANITIZE) ==
1238412386
BPF_ALU_SANITIZE_SRC;
12387+
isimm = aux->alu_state & BPF_ALU_IMMEDIATE;
1238512388

1238612389
off_reg = issrc ? insn->src_reg : insn->dst_reg;
12387-
if (isneg)
12388-
*patch++ = BPF_ALU64_IMM(BPF_MUL, off_reg, -1);
12389-
*patch++ = BPF_MOV32_IMM(BPF_REG_AX, aux->alu_limit);
12390-
*patch++ = BPF_ALU64_REG(BPF_SUB, BPF_REG_AX, off_reg);
12391-
*patch++ = BPF_ALU64_REG(BPF_OR, BPF_REG_AX, off_reg);
12392-
*patch++ = BPF_ALU64_IMM(BPF_NEG, BPF_REG_AX, 0);
12393-
*patch++ = BPF_ALU64_IMM(BPF_ARSH, BPF_REG_AX, 63);
12394-
if (issrc) {
12395-
*patch++ = BPF_ALU64_REG(BPF_AND, BPF_REG_AX,
12396-
off_reg);
12397-
insn->src_reg = BPF_REG_AX;
12390+
if (isimm) {
12391+
*patch++ = BPF_MOV32_IMM(BPF_REG_AX, aux->alu_limit);
1239812392
} else {
12399-
*patch++ = BPF_ALU64_REG(BPF_AND, off_reg,
12400-
BPF_REG_AX);
12393+
if (isneg)
12394+
*patch++ = BPF_ALU64_IMM(BPF_MUL, off_reg, -1);
12395+
*patch++ = BPF_MOV32_IMM(BPF_REG_AX, aux->alu_limit);
12396+
*patch++ = BPF_ALU64_REG(BPF_SUB, BPF_REG_AX, off_reg);
12397+
*patch++ = BPF_ALU64_REG(BPF_OR, BPF_REG_AX, off_reg);
12398+
*patch++ = BPF_ALU64_IMM(BPF_NEG, BPF_REG_AX, 0);
12399+
*patch++ = BPF_ALU64_IMM(BPF_ARSH, BPF_REG_AX, 63);
12400+
*patch++ = BPF_ALU64_REG(BPF_AND, BPF_REG_AX, off_reg);
1240112401
}
12402+
if (!issrc)
12403+
*patch++ = BPF_MOV64_REG(insn->dst_reg, insn->src_reg);
12404+
insn->src_reg = BPF_REG_AX;
1240212405
if (isneg)
1240312406
insn->code = insn->code == code_add ?
1240412407
code_sub : code_add;
1240512408
*patch++ = *insn;
12406-
if (issrc && isneg)
12409+
if (issrc && isneg && !isimm)
1240712410
*patch++ = BPF_ALU64_IMM(BPF_MUL, off_reg, -1);
1240812411
cnt = patch - insn_buf;
1240912412

net/xdp/xsk_queue.h

Lines changed: 3 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -128,13 +128,12 @@ static inline bool xskq_cons_read_addr_unchecked(struct xsk_queue *q, u64 *addr)
128128
static inline bool xp_aligned_validate_desc(struct xsk_buff_pool *pool,
129129
struct xdp_desc *desc)
130130
{
131-
u64 chunk, chunk_end;
131+
u64 chunk;
132132

133-
chunk = xp_aligned_extract_addr(pool, desc->addr);
134-
chunk_end = xp_aligned_extract_addr(pool, desc->addr + desc->len);
135-
if (chunk != chunk_end)
133+
if (desc->len > pool->chunk_size)
136134
return false;
137135

136+
chunk = xp_aligned_extract_addr(pool, desc->addr);
138137
if (chunk >= pool->addrs_cnt)
139138
return false;
140139

tools/lib/bpf/ringbuf.c

Lines changed: 21 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -202,9 +202,11 @@ static inline int roundup_len(__u32 len)
202202
return (len + 7) / 8 * 8;
203203
}
204204

205-
static int ringbuf_process_ring(struct ring* r)
205+
static int64_t ringbuf_process_ring(struct ring* r)
206206
{
207-
int *len_ptr, len, err, cnt = 0;
207+
int *len_ptr, len, err;
208+
/* 64-bit to avoid overflow in case of extreme application behavior */
209+
int64_t cnt = 0;
208210
unsigned long cons_pos, prod_pos;
209211
bool got_new_data;
210212
void *sample;
@@ -244,12 +246,14 @@ static int ringbuf_process_ring(struct ring* r)
244246
}
245247

246248
/* Consume available ring buffer(s) data without event polling.
247-
* Returns number of records consumed across all registered ring buffers, or
248-
* negative number if any of the callbacks return error.
249+
* Returns number of records consumed across all registered ring buffers (or
250+
* INT_MAX, whichever is less), or negative number if any of the callbacks
251+
* return error.
249252
*/
250253
int ring_buffer__consume(struct ring_buffer *rb)
251254
{
252-
int i, err, res = 0;
255+
int64_t err, res = 0;
256+
int i;
253257

254258
for (i = 0; i < rb->ring_cnt; i++) {
255259
struct ring *ring = &rb->rings[i];
@@ -259,18 +263,24 @@ int ring_buffer__consume(struct ring_buffer *rb)
259263
return err;
260264
res += err;
261265
}
266+
if (res > INT_MAX)
267+
return INT_MAX;
262268
return res;
263269
}
264270

265271
/* Poll for available data and consume records, if any are available.
266-
* Returns number of records consumed, or negative number, if any of the
267-
* registered callbacks returned error.
272+
* Returns number of records consumed (or INT_MAX, whichever is less), or
273+
* negative number, if any of the registered callbacks returned error.
268274
*/
269275
int ring_buffer__poll(struct ring_buffer *rb, int timeout_ms)
270276
{
271-
int i, cnt, err, res = 0;
277+
int i, cnt;
278+
int64_t err, res = 0;
272279

273280
cnt = epoll_wait(rb->epoll_fd, rb->events, rb->ring_cnt, timeout_ms);
281+
if (cnt < 0)
282+
return -errno;
283+
274284
for (i = 0; i < cnt; i++) {
275285
__u32 ring_id = rb->events[i].data.fd;
276286
struct ring *ring = &rb->rings[ring_id];
@@ -280,7 +290,9 @@ int ring_buffer__poll(struct ring_buffer *rb, int timeout_ms)
280290
return err;
281291
res += err;
282292
}
283-
return cnt < 0 ? -errno : res;
293+
if (res > INT_MAX)
294+
return INT_MAX;
295+
return res;
284296
}
285297

286298
/* Get an fd that can be used to sleep until data is available in the ring(s) */

tools/testing/selftests/bpf/prog_tests/snprintf.c

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -43,6 +43,8 @@ void test_snprintf_positive(void)
4343
if (!ASSERT_OK_PTR(skel, "skel_open"))
4444
return;
4545

46+
skel->bss->pid = getpid();
47+
4648
if (!ASSERT_OK(test_snprintf__attach(skel), "skel_attach"))
4749
goto cleanup;
4850

tools/testing/selftests/bpf/progs/test_snprintf.c

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,8 @@
55
#include <bpf/bpf_helpers.h>
66
#include <bpf/bpf_tracing.h>
77

8+
__u32 pid = 0;
9+
810
char num_out[64] = {};
911
long num_ret = 0;
1012

@@ -42,6 +44,9 @@ int handler(const void *ctx)
4244
static const char str1[] = "str1";
4345
static const char longstr[] = "longstr";
4446

47+
if ((int)bpf_get_current_pid_tgid() != pid)
48+
return 0;
49+
4550
/* Integer types */
4651
num_ret = BPF_SNPRINTF(num_out, sizeof(num_out),
4752
"%d %u %x %li %llu %lX",

0 commit comments

Comments
 (0)