History

Merge tag 'bpf-fixes' of git://git.kernel.org/pub/scm/linux/kernel/git/bpf/bpf

Pull BPF fixes from Daniel Borkmann: - Fix BPF verifier to preserve full pointer state for commuted scalar += pointer arithmetic (Yiyang Chen, Eduard Zingerman) - Fix a use-after-free of request sockets in the BPF TCP iterator batching (Jose Fernandez) - Fix a use-after-free of sk_redir in the BPF sockmap send verdict path (Chengfeng Ye) - Fix a netns reference imbalance in the BPF conntrack kfuncs (Chengfeng Ye) - Fix bpf_get_fsverity_digest() dynptr assumptions and silent digest truncation (Eric Biggers) - Fix bpf_tcp_{gen,check}_syncookie to check sk_state before sk_protocol to make sure it is a full socket (Luxiao Xu) - Fix rqspinlock to reset the tail when preserving the queue on deadlock (Kumar Kartikeya Dwivedi) * tag 'bpf-fixes' of git://git.kernel.org/pub/scm/linux/kernel/git/bpf/bpf: rqspinlock: Reset tail when preserving queue on deadlock bpf: Check sk_state before sk_protocol in bpf_tcp_*_syncookie fsverity: Fix silent truncation in bpf_get_fsverity_digest() fsverity: Fix bpf_get_fsverity_digest() dynptr assumptions bpf: tcp: Fix use-after-free in bpf_iter_tcp_established_batch() bpf: Fix netns reference imbalance in conntrack kfuncs bpf, sockmap: Fix sk_redir use-after-free in send verdict selftests/bpf: Cover commuted pointer state propagation bpf: Propagate untrusted pointer state in commuted arithmetic bpf: Preserve pointer state for commuted arithmetic bpf: Simplify sanitize_err() signature

Linus Torvalds committed 3 months ago

Commit a13307e2 parents 0150da6 7a3c02810 files · +198 −76Browse files

Showing the changes to kernel (2 of 10 files). Show all

Unified · Split

2 files
  1. kernel/bpf/rqspinlock.c +3 −2
  2. kernel/bpf/verifier.c +22 −23
kernel/bpf/rqspinlock.c+3−2
@@ -572,9 +572,10 @@ queue: · 571 unmodified lines
572572
573573 /* Disable queue destruction when we detect deadlocks. */
574574 if (ret == -EDEADLK) {
575− if (!next)
575+ if (!try_cmpxchg_tail(lock, tail, 0)) {
576576 next = smp_cond_load_relaxed(&node->next, (VAL));
577− arch_mcs_spin_unlock_contended(&next->locked);
577+ arch_mcs_spin_unlock_contended(&next->locked);
578+ }
578579 goto err_release_node;
579580 }
580581
kernel/bpf/verifier.c+22−23
@@ -13557,23 +13557,21 @@ static void sanitize_mark_insn_seen(struct bpf_verifier_env *env) · 13556 unmodified lines
1355713557 env->insn_aux_data[env->insn_idx].seen = env->pass_cnt;
1355813558 }
1355913559
13560−static int sanitize_err(struct bpf_verifier_env *env,
13561− const struct bpf_insn *insn, int reason,
13562− const struct bpf_reg_state *off_reg,
13563− const struct bpf_reg_state *dst_reg)
13560+static int sanitize_err(struct bpf_verifier_env *env, const struct bpf_insn *insn, int reason)
1356413561 {
1356513562 static const char *err = "pointer arithmetic with it prohibited for !root";
1356613563 const char *op = BPF_OP(insn->code) == BPF_ADD ? "add" : "sub";
1356713564 u32 dst = insn->dst_reg, src = insn->src_reg;
13565+ struct bpf_reg_state *regs = cur_regs(env);
1356813566
1356913567 switch (reason) {
1357013568 case REASON_BOUNDS:
1357113569 verbose(env, "R%d has unknown scalar with mixed signed bounds, %s\n",
13572− off_reg == dst_reg ? dst : src, err);
13570+ regs[src].type == SCALAR_VALUE ? src : dst, err);
1357313571 break;
1357413572 case REASON_TYPE:
1357513573 verbose(env, "R%d has pointer with unsupported alu operation, %s\n",
13576− off_reg == dst_reg ? src : dst, err);
13574+ regs[src].type == SCALAR_VALUE ? dst : src, err);
1357713575 break;
1357813576 case REASON_PATHS:
1357913577 verbose(env, "R%d tried to %s from different maps, paths or scalars, %s\n",
@@ -13709,13 +13707,6 @@ static int adjust_ptr_min_max_vals(struct bpf_verifier_env *env, · 129 unmodified lines
1370913707 return -EACCES;
1371013708 }
1371113709
13712− /*
13713− * Accesses to untrusted PTR_TO_MEM are done through probe
13714− * instructions, hence no need to track offsets.
13715− */
13716− if (base_type(ptr_reg->type) == PTR_TO_MEM && (ptr_reg->type & PTR_UNTRUSTED))
13717− return 0;
13718−
1371913710 switch (base_type(ptr_reg->type)) {
1372013711 case PTR_TO_CTX:
1372113712 case PTR_TO_MAP_VALUE:
@@ -13745,11 +13736,19 @@ static int adjust_ptr_min_max_vals(struct bpf_verifier_env *env, · 23 unmodified lines
1374513736 return -EACCES;
1374613737 }
1374713738
13748− /* In case of 'scalar += pointer', dst_reg inherits pointer type and id.
13749− * The id may be overwritten later if we create a new variable offset.
13739+ /* For 'scalar += pointer', dst_reg inherits the complete pointer
13740+ * register state. Individual fields may be adjusted later by pointer
13741+ * arithmetic. Callers guarantee that below does not overwrite off_reg.
1375013742 */
13751− dst_reg->type = ptr_reg->type;
13752− dst_reg->id = ptr_reg->id;
13743+ if (dst_reg != ptr_reg)
13744+ *dst_reg = *ptr_reg;
13745+
13746+ /*
13747+ * Accesses to untrusted PTR_TO_MEM are done through probe
13748+ * instructions, hence no need to track offsets.
13749+ */
13750+ if (base_type(ptr_reg->type) == PTR_TO_MEM && (ptr_reg->type & PTR_UNTRUSTED))
13751+ return 0;
1375313752
1375413753 if (!check_reg_sane_offset_scalar(env, off_reg, ptr_reg->type) ||
1375513754 !check_reg_sane_offset_ptr(env, ptr_reg, ptr_reg->type))
@@ -13762,7 +13761,7 @@ static int adjust_ptr_min_max_vals(struct bpf_verifier_env *env, · 6 unmodified lines
1376213761 ret = sanitize_ptr_alu(env, insn, ptr_reg, off_reg, dst_reg,
1376313762 &info, false);
1376413763 if (ret < 0)
13765− return sanitize_err(env, insn, ret, off_reg, dst_reg);
13764+ return sanitize_err(env, insn, ret);
1376613765 }
1376713766
1376813767 switch (opcode) {
@@ -13792,7 +13791,7 @@ static int adjust_ptr_min_max_vals(struct bpf_verifier_env *env, · 23 unmodified lines
1379213791 }
1379313792 break;
1379413793 case BPF_SUB:
13795− if (dst_reg == off_reg) {
13794+ if (dst_reg != ptr_reg) {
1379613795 /* scalar -= pointer. Creates an unknown scalar */
1379713796 verbose(env, "R%d tried to subtract pointer from scalar\n",
1379813797 dst);
@@ -13855,7 +13854,7 @@ static int adjust_ptr_min_max_vals(struct bpf_verifier_env *env, · 56 unmodified lines
1385513854 return -EFAULT;
1385613855 }
1385713856 if (ret < 0)
13858− return sanitize_err(env, insn, ret, off_reg, dst_reg);
13857+ return sanitize_err(env, insn, ret);
1385913858 }
1386013859
1386113860 return 0;
@@ -14607,7 +14606,7 @@ static int adjust_scalar_min_max_vals(struct bpf_verifier_env *env, · 745 unmodified lines
1460714606 if (sanitize_needed(opcode)) {
1460814607 ret = sanitize_val_alu(env, insn);
1460914608 if (ret < 0)
14610− return sanitize_err(env, insn, ret, NULL, NULL);
14609+ return sanitize_err(env, insn, ret);
1461114610 }
1461214611
1461314612 /* Calculate sign/unsigned bounds and tnum for alu32 and alu64 bit ops.
@@ -14810,8 +14809,8 @@ static int adjust_reg_min_max_vals(struct bpf_verifier_env *env, · 196 unmodified lines
1481014809 err = mark_chain_precision(env, insn->dst_reg);
1481114810 if (err)
1481214811 return err;
14813− return adjust_ptr_min_max_vals(env, insn,
14814− src_reg, dst_reg);
14812+ off_reg = *dst_reg;
14813+ return adjust_ptr_min_max_vals(env, insn, src_reg, &off_reg);
1481514814 }
1481614815 } else if (ptr_reg) {
1481714816 /* pointer += scalar */