Commit 7b9e74c5 authored by Linus Torvalds's avatar Linus Torvalds
Browse files
Pull bpf fixes from Alexei Starovoitov:

 - Fix register equivalence for pointers to packet (Alexei Starovoitov)

 - Fix incorrect pruning due to atomic fetch precision tracking (Daniel
   Borkmann)

 - Fix grace period wait for bpf_link-ed tracepoints (Kumar Kartikeya
   Dwivedi)

 - Fix use-after-free of sockmap's sk->sk_socket (Kuniyuki Iwashima)

 - Reject direct access to nullable PTR_TO_BUF pointers (Qi Tang)

 - Reject sleepable kprobe_multi programs at attach time (Varun R
   Mallya)

* tag 'bpf-fixes' of git://git.kernel.org/pub/scm/linux/kernel/git/bpf/bpf:
  selftests/bpf: Add more precision tracking tests for atomics
  bpf: Fix incorrect pruning due to atomic fetch precision tracking
  bpf: Reject sleepable kprobe_multi programs at attach time
  bpf: reject direct access to nullable PTR_TO_BUF pointers
  bpf: sockmap: Fix use-after-free of sk->sk_socket in sk_psock_verdict_data_ready().
  bpf: Fix grace period wait for tracepoint bpf_link
  bpf: Fix regsafe() for pointers to packet
parents 5a9617dd e1b5687a
Loading
Loading
Loading
Loading
+4 −0
Original line number Diff line number Diff line
@@ -1854,6 +1854,10 @@ struct bpf_link_ops {
	 * target hook is sleepable, we'll go through tasks trace RCU GP and
	 * then "classic" RCU GP; this need for chaining tasks trace and
	 * classic RCU GPs is designated by setting bpf_link->sleepable flag
	 *
	 * For non-sleepable tracepoint links we go through SRCU gp instead,
	 * since RCU is not used in that case. Sleepable tracepoints still
	 * follow the scheme above.
	 */
	void (*dealloc_deferred)(struct bpf_link *link);
	int (*detach)(struct bpf_link *link);
+20 −0
Original line number Diff line number Diff line
@@ -122,6 +122,22 @@ static inline bool tracepoint_is_faultable(struct tracepoint *tp)
{
	return tp->ext && tp->ext->faultable;
}
/*
 * Run RCU callback with the appropriate grace period wait for non-faultable
 * tracepoints, e.g., those used in atomic context.
 */
static inline void call_tracepoint_unregister_atomic(struct rcu_head *rcu, rcu_callback_t func)
{
	call_srcu(&tracepoint_srcu, rcu, func);
}
/*
 * Run RCU callback with the appropriate grace period wait for faultable
 * tracepoints, e.g., those used in syscall context.
 */
static inline void call_tracepoint_unregister_syscall(struct rcu_head *rcu, rcu_callback_t func)
{
	call_rcu_tasks_trace(rcu, func);
}
#else
static inline void tracepoint_synchronize_unregister(void)
{ }
@@ -129,6 +145,10 @@ static inline bool tracepoint_is_faultable(struct tracepoint *tp)
{
	return false;
}
static inline void call_tracepoint_unregister_atomic(struct rcu_head *rcu, rcu_callback_t func)
{  }
static inline void call_tracepoint_unregister_syscall(struct rcu_head *rcu, rcu_callback_t func)
{  }
#endif

#ifdef CONFIG_HAVE_SYSCALL_TRACEPOINTS
+23 −2
Original line number Diff line number Diff line
@@ -3261,6 +3261,18 @@ static void bpf_link_defer_dealloc_rcu_gp(struct rcu_head *rcu)
	bpf_link_dealloc(link);
}

static bool bpf_link_is_tracepoint(struct bpf_link *link)
{
	/*
	 * Only these combinations support a tracepoint bpf_link.
	 * BPF_LINK_TYPE_TRACING raw_tp progs are hardcoded to use
	 * bpf_raw_tp_link_lops and thus dealloc_deferred(), see
	 * bpf_raw_tp_link_attach().
	 */
	return link->type == BPF_LINK_TYPE_RAW_TRACEPOINT ||
	       (link->type == BPF_LINK_TYPE_TRACING && link->attach_type == BPF_TRACE_RAW_TP);
}

static void bpf_link_defer_dealloc_mult_rcu_gp(struct rcu_head *rcu)
{
	if (rcu_trace_implies_rcu_gp())
@@ -3279,16 +3291,25 @@ static void bpf_link_free(struct bpf_link *link)
	if (link->prog)
		ops->release(link);
	if (ops->dealloc_deferred) {
		/* Schedule BPF link deallocation, which will only then
		/*
		 * Schedule BPF link deallocation, which will only then
		 * trigger putting BPF program refcount.
		 * If underlying BPF program is sleepable or BPF link's target
		 * attach hookpoint is sleepable or otherwise requires RCU GPs
		 * to ensure link and its underlying BPF program is not
		 * reachable anymore, we need to first wait for RCU tasks
		 * trace sync, and then go through "classic" RCU grace period
		 * trace sync, and then go through "classic" RCU grace period.
		 *
		 * For tracepoint BPF links, we need to go through SRCU grace
		 * period wait instead when non-faultable tracepoint is used. We
		 * don't need to chain SRCU grace period waits, however, for the
		 * faultable case, since it exclusively uses RCU Tasks Trace.
		 */
		if (link->sleepable || (link->prog && link->prog->sleepable))
			call_rcu_tasks_trace(&link->rcu, bpf_link_defer_dealloc_mult_rcu_gp);
		/* We need to do a SRCU grace period wait for non-faultable tracepoint BPF links. */
		else if (bpf_link_is_tracepoint(link))
			call_tracepoint_unregister_atomic(&link->rcu, bpf_link_defer_dealloc_rcu_gp);
		else
			call_rcu(&link->rcu, bpf_link_defer_dealloc_rcu_gp);
	} else if (ops->dealloc) {
+32 −5
Original line number Diff line number Diff line
@@ -617,6 +617,13 @@ static bool is_atomic_load_insn(const struct bpf_insn *insn)
	       insn->imm == BPF_LOAD_ACQ;
}
static bool is_atomic_fetch_insn(const struct bpf_insn *insn)
{
	return BPF_CLASS(insn->code) == BPF_STX &&
	       BPF_MODE(insn->code) == BPF_ATOMIC &&
	       (insn->imm & BPF_FETCH);
}
static int __get_spi(s32 off)
{
	return (-off - 1) / BPF_REG_SIZE;
@@ -4447,10 +4454,24 @@ static int backtrack_insn(struct bpf_verifier_env *env, int idx, int subseq_idx,
			   * dreg still needs precision before this insn
			   */
		}
	} else if (class == BPF_LDX || is_atomic_load_insn(insn)) {
		if (!bt_is_reg_set(bt, dreg))
	} else if (class == BPF_LDX ||
		   is_atomic_load_insn(insn) ||
		   is_atomic_fetch_insn(insn)) {
		u32 load_reg = dreg;
		/*
		 * Atomic fetch operation writes the old value into
		 * a register (sreg or r0) and if it was tracked for
		 * precision, propagate to the stack slot like we do
		 * in regular ldx.
		 */
		if (is_atomic_fetch_insn(insn))
			load_reg = insn->imm == BPF_CMPXCHG ?
				   BPF_REG_0 : sreg;
		if (!bt_is_reg_set(bt, load_reg))
			return 0;
		bt_clear_reg(bt, dreg);
		bt_clear_reg(bt, load_reg);
		/* scalars can only be spilled into stack w/o losing precision.
		 * Load from any other memory can be zero extended.
@@ -7905,7 +7926,8 @@ static int check_mem_access(struct bpf_verifier_env *env, int insn_idx, u32 regn
	} else if (reg->type == CONST_PTR_TO_MAP) {
		err = check_ptr_to_map_access(env, regs, regno, off, size, t,
					      value_regno);
	} else if (base_type(reg->type) == PTR_TO_BUF) {
	} else if (base_type(reg->type) == PTR_TO_BUF &&
		   !type_may_be_null(reg->type)) {
		bool rdonly_mem = type_is_rdonly_mem(reg->type);
		u32 *max_access;
@@ -19915,8 +19937,13 @@ static bool regsafe(struct bpf_verifier_env *env, struct bpf_reg_state *rold,
		 * since someone could have accessed through (ptr - k), or
		 * even done ptr -= k in a register, to get a safe access.
		 */
		if (rold->range > rcur->range)
		if (rold->range < 0 || rcur->range < 0) {
			/* special case for [BEYOND|AT]_PKT_END */
			if (rold->range != rcur->range)
				return false;
		} else if (rold->range > rcur->range) {
			return false;
		}
		/* If the offsets don't match, we can't trust our alignment;
		 * nor can we be sure that we won't fall out of range.
		 */
+4 −0
Original line number Diff line number Diff line
@@ -2752,6 +2752,10 @@ int bpf_kprobe_multi_link_attach(const union bpf_attr *attr, struct bpf_prog *pr
	if (!is_kprobe_multi(prog))
		return -EINVAL;

	/* kprobe_multi is not allowed to be sleepable. */
	if (prog->sleepable)
		return -EINVAL;

	/* Writing to context is not allowed for kprobes. */
	if (prog->aux->kprobe_write_ctx)
		return -EINVAL;
Loading