Unverified Commit 3dc0cdc2 authored by openeuler-ci-bot's avatar openeuler-ci-bot Committed by Gitee
Browse files

!10658 CVE-2024-35860

Merge Pull Request from: @ci-robot 
 
PR sync from: Pu Lehui <pulehui@huawei.com>
https://mailweb.openeuler.org/hyperkitty/list/kernel@openeuler.org/message/AWAZ6CYXS46HSZ44C7QDSDBPQHUHRPYW/ 
Andrii Nakryiko (1):
  bpf: support deferring bpf_link dealloc to after RCU grace period

Cong Wang (1):
  bpf: Fix a potential use-after-free in bpf_link_free()

Tengda Wu (1):
  Fix kabi breakage in struct bpf_link and bpf_link_ops


-- 
2.34.1
 
https://gitee.com/src-openeuler/kernel/issues/I9QG81 
 
Link:https://gitee.com/openeuler/kernel/pulls/10658

 

Reviewed-by: default avatarXu Kuohai <xukuohai@huawei.com>
Reviewed-by: default avatarYe Weihua <yeweihua4@huawei.com>
Signed-off-by: default avatarZhang Peng <zhangpeng362@huawei.com>
parents 7df35986 4e8b651a
Loading
Loading
Loading
Loading
+15 −2
Original line number Diff line number Diff line
@@ -1582,7 +1582,13 @@ struct bpf_link {
	enum bpf_link_type type;
	const struct bpf_link_ops *ops;
	struct bpf_prog *prog;
	/* rcu is used before freeing, work can be used to schedule that
	 * RCU-based freeing before that, so they never overlap
	 */
	KABI_REPLACE(struct work_struct work, union {
		struct rcu_head rcu;
		struct work_struct work;
	})

	KABI_RESERVE(1)
	KABI_RESERVE(2)
@@ -1592,6 +1598,9 @@ struct bpf_link {

struct bpf_link_ops {
	void (*release)(struct bpf_link *link);
	/* deallocate link resources callback, called without RCU grace period
	 * waiting
	 */
	void (*dealloc)(struct bpf_link *link);
	int (*detach)(struct bpf_link *link);
	int (*update_prog)(struct bpf_link *link, struct bpf_prog *new_prog,
@@ -1602,7 +1611,11 @@ struct bpf_link_ops {
	int (*update_map)(struct bpf_link *link, struct bpf_map *new_map,
			  struct bpf_map *old_map);

	KABI_RESERVE(1)
	/* deallocate link resources callback, called after RCU grace period;
	 * if underlying BPF program is sleepable we go through tasks trace
	 * RCU GP and then "classic" RCU GP
	 */
	KABI_USE(1, void (*dealloc_deferred)(struct bpf_link *link))
	KABI_RESERVE(2)
	KABI_RESERVE(3)
	KABI_RESERVE(4)
+34 −4
Original line number Diff line number Diff line
@@ -2834,6 +2834,7 @@ static int bpf_obj_get(const union bpf_attr *attr)
void bpf_link_init(struct bpf_link *link, enum bpf_link_type type,
		   const struct bpf_link_ops *ops, struct bpf_prog *prog)
{
	WARN_ON(ops->dealloc && ops->dealloc_deferred);
	atomic64_set(&link->refcnt, 1);
	link->type = type;
	link->id = 0;
@@ -2873,17 +2874,46 @@ void bpf_link_inc(struct bpf_link *link)
	atomic64_inc(&link->refcnt);
}

static void bpf_link_defer_dealloc_rcu_gp(struct rcu_head *rcu)
{
	struct bpf_link *link = container_of(rcu, struct bpf_link, rcu);

	/* free bpf_link and its containing memory */
	link->ops->dealloc_deferred(link);
}

static void bpf_link_defer_dealloc_mult_rcu_gp(struct rcu_head *rcu)
{
	if (rcu_trace_implies_rcu_gp())
		bpf_link_defer_dealloc_rcu_gp(rcu);
	else
		call_rcu(rcu, bpf_link_defer_dealloc_rcu_gp);
}

/* bpf_link_free is guaranteed to be called from process context */
static void bpf_link_free(struct bpf_link *link)
{
	const struct bpf_link_ops *ops = link->ops;
	bool sleepable = false;

	bpf_link_free_id(link->id);
	if (link->prog) {
		sleepable = link->prog->aux->sleepable;
		/* detach BPF program, clean up used resources */
		link->ops->release(link);
		ops->release(link);
		bpf_prog_put(link->prog);
	}
	/* free bpf_link and its containing memory */
	link->ops->dealloc(link);
	if (ops->dealloc_deferred) {
		/* schedule BPF link deallocation; if underlying BPF program
		 * is sleepable, we need to first wait for RCU tasks trace
		 * sync, then go through "classic" RCU grace period
		 */
		if (sleepable)
			call_rcu_tasks_trace(&link->rcu, bpf_link_defer_dealloc_mult_rcu_gp);
		else
			call_rcu(&link->rcu, bpf_link_defer_dealloc_rcu_gp);
	} else if (ops->dealloc)
		ops->dealloc(link);
}

static void bpf_link_put_deferred(struct work_struct *work)
@@ -3406,7 +3436,7 @@ static int bpf_raw_tp_link_fill_link_info(const struct bpf_link *link,

static const struct bpf_link_ops bpf_raw_tp_link_lops = {
	.release = bpf_raw_tp_link_release,
	.dealloc = bpf_raw_tp_link_dealloc,
	.dealloc_deferred = bpf_raw_tp_link_dealloc,
	.show_fdinfo = bpf_raw_tp_link_show_fdinfo,
	.fill_link_info = bpf_raw_tp_link_fill_link_info,
};
+2 −2
Original line number Diff line number Diff line
@@ -2639,7 +2639,7 @@ static int bpf_kprobe_multi_link_fill_link_info(const struct bpf_link *link,

static const struct bpf_link_ops bpf_kprobe_multi_link_lops = {
	.release = bpf_kprobe_multi_link_release,
	.dealloc = bpf_kprobe_multi_link_dealloc,
	.dealloc_deferred = bpf_kprobe_multi_link_dealloc,
	.fill_link_info = bpf_kprobe_multi_link_fill_link_info,
};

@@ -3082,7 +3082,7 @@ static void bpf_uprobe_multi_link_dealloc(struct bpf_link *link)

static const struct bpf_link_ops bpf_uprobe_multi_link_lops = {
	.release = bpf_uprobe_multi_link_release,
	.dealloc = bpf_uprobe_multi_link_dealloc,
	.dealloc_deferred = bpf_uprobe_multi_link_dealloc,
};

static int uprobe_prog_run(struct bpf_uprobe *uprobe,