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
572 572
573 /* Disable queue destruction when we detect deadlocks. */573 /* Disable queue destruction when we detect deadlocks. */
574 if (ret == -EDEADLK) {574 if (ret == -EDEADLK) {
575 if (!next)575 if (!try_cmpxchg_tail(lock, tail, 0)) {
576 next = smp_cond_load_relaxed(&node->next, (VAL));576 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 }
578 goto err_release_node;579 goto err_release_node;
579 }580 }
580 581
kernel/bpf/verifier.c+22−23
@@ -13557,23 +13557,21 @@ static void sanitize_mark_insn_seen(struct bpf_verifier_env *env) · 13556 unmodified lines
13557 env->insn_aux_data[env->insn_idx].seen = env->pass_cnt;13557 env->insn_aux_data[env->insn_idx].seen = env->pass_cnt;
13558}13558}
13559 13559
13560static int sanitize_err(struct bpf_verifier_env *env,13560static int sanitize_err(struct bpf_verifier_env *env, const struct bpf_insn *insn, int reason)
13561 const struct bpf_insn *insn, int reason,
13562 const struct bpf_reg_state *off_reg,
13563 const struct bpf_reg_state *dst_reg)
13564{13561{
13565 static const char *err = "pointer arithmetic with it prohibited for !root";13562 static const char *err = "pointer arithmetic with it prohibited for !root";
13566 const char *op = BPF_OP(insn->code) == BPF_ADD ? "add" : "sub";13563 const char *op = BPF_OP(insn->code) == BPF_ADD ? "add" : "sub";
13567 u32 dst = insn->dst_reg, src = insn->src_reg;13564 u32 dst = insn->dst_reg, src = insn->src_reg;
13565 struct bpf_reg_state *regs = cur_regs(env);
13568 13566
13569 switch (reason) {13567 switch (reason) {
13570 case REASON_BOUNDS:13568 case REASON_BOUNDS:
13571 verbose(env, "R%d has unknown scalar with mixed signed bounds, %s\n",13569 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);
13573 break;13571 break;
13574 case REASON_TYPE:13572 case REASON_TYPE:
13575 verbose(env, "R%d has pointer with unsupported alu operation, %s\n",13573 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);
13577 break;13575 break;
13578 case REASON_PATHS:13576 case REASON_PATHS:
13579 verbose(env, "R%d tried to %s from different maps, paths or scalars, %s\n",13577 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
13709 return -EACCES;13707 return -EACCES;
13710 }13708 }
13711 13709
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
13719 switch (base_type(ptr_reg->type)) {13710 switch (base_type(ptr_reg->type)) {
13720 case PTR_TO_CTX:13711 case PTR_TO_CTX:
13721 case PTR_TO_MAP_VALUE:13712 case PTR_TO_MAP_VALUE:
@@ -13745,11 +13736,19 @@ static int adjust_ptr_min_max_vals(struct bpf_verifier_env *env, · 23 unmodified lines
13745 return -EACCES;13736 return -EACCES;
13746 }13737 }
13747 13738
13748 /* In case of 'scalar += pointer', dst_reg inherits pointer type and id.13739 /* For 'scalar += pointer', dst_reg inherits the complete pointer
13749 * The id may be overwritten later if we create a new variable offset.13740 * register state. Individual fields may be adjusted later by pointer
13741 * arithmetic. Callers guarantee that below does not overwrite off_reg.
13750 */13742 */
13751 dst_reg->type = ptr_reg->type;13743 if (dst_reg != ptr_reg)
13752 dst_reg->id = ptr_reg->id;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;
13753 13752
13754 if (!check_reg_sane_offset_scalar(env, off_reg, ptr_reg->type) ||13753 if (!check_reg_sane_offset_scalar(env, off_reg, ptr_reg->type) ||
13755 !check_reg_sane_offset_ptr(env, ptr_reg, ptr_reg->type))13754 !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
13762 ret = sanitize_ptr_alu(env, insn, ptr_reg, off_reg, dst_reg,13761 ret = sanitize_ptr_alu(env, insn, ptr_reg, off_reg, dst_reg,
13763 &info, false);13762 &info, false);
13764 if (ret < 0)13763 if (ret < 0)
13765 return sanitize_err(env, insn, ret, off_reg, dst_reg);13764 return sanitize_err(env, insn, ret);
13766 }13765 }
13767 13766
13768 switch (opcode) {13767 switch (opcode) {
@@ -13792,7 +13791,7 @@ static int adjust_ptr_min_max_vals(struct bpf_verifier_env *env, · 23 unmodified lines
13792 }13791 }
13793 break;13792 break;
13794 case BPF_SUB:13793 case BPF_SUB:
13795 if (dst_reg == off_reg) {13794 if (dst_reg != ptr_reg) {
13796 /* scalar -= pointer. Creates an unknown scalar */13795 /* scalar -= pointer. Creates an unknown scalar */
13797 verbose(env, "R%d tried to subtract pointer from scalar\n",13796 verbose(env, "R%d tried to subtract pointer from scalar\n",
13798 dst);13797 dst);
@@ -13855,7 +13854,7 @@ static int adjust_ptr_min_max_vals(struct bpf_verifier_env *env, · 56 unmodified lines
13855 return -EFAULT;13854 return -EFAULT;
13856 }13855 }
13857 if (ret < 0)13856 if (ret < 0)
13858 return sanitize_err(env, insn, ret, off_reg, dst_reg);13857 return sanitize_err(env, insn, ret);
13859 }13858 }
13860 13859
13861 return 0;13860 return 0;
@@ -14607,7 +14606,7 @@ static int adjust_scalar_min_max_vals(struct bpf_verifier_env *env, · 745 unmodified lines
14607 if (sanitize_needed(opcode)) {14606 if (sanitize_needed(opcode)) {
14608 ret = sanitize_val_alu(env, insn);14607 ret = sanitize_val_alu(env, insn);
14609 if (ret < 0)14608 if (ret < 0)
14610 return sanitize_err(env, insn, ret, NULL, NULL);14609 return sanitize_err(env, insn, ret);
14611 }14610 }
14612 14611
14613 /* Calculate sign/unsigned bounds and tnum for alu32 and alu64 bit ops.14612 /* 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
14810 err = mark_chain_precision(env, insn->dst_reg);14809 err = mark_chain_precision(env, insn->dst_reg);
14811 if (err)14810 if (err)
14812 return err;14811 return err;
14813 return adjust_ptr_min_max_vals(env, insn,14812 off_reg = *dst_reg;
14814 src_reg, dst_reg);14813 return adjust_ptr_min_max_vals(env, insn, src_reg, &off_reg);
14815 }14814 }
14816 } else if (ptr_reg) {14815 } else if (ptr_reg) {
14817 /* pointer += scalar */14816 /* pointer += scalar */