All of lore.kernel.org
 help / color / mirror / Atom feed
From: Mykyta Yatsenko <mykyta.yatsenko5@gmail.com>
To: chenyuan_fl@163.com, bpf@vger.kernel.org
Cc: linux-kernel@vger.kernel.org, linux-kselftest@vger.kernel.org,
	Alexei Starovoitov <ast@kernel.org>,
	Daniel Borkmann <daniel@iogearbox.net>,
	Andrii Nakryiko <andrii@kernel.org>,
	Eduard Zingerman <eddyz87@gmail.com>,
	Kumar Kartikeya Dwivedi <memxor@gmail.com>,
	Martin KaFai Lau <martin.lau@linux.dev>,
	Emil Tsalapatis <emil@etsalapatis.com>,
	Ihor Solodrai <ihor.solodrai@linux.dev>,
	Shuah Khan <shuah@kernel.org>,
	Nuoqi Gui <gnq25@mails.tsinghua.edu.cn>,
	Yuan Chen <chenyuan@kylinos.cn>
Subject: Re: [PATCH bpf-next v3 2/4] bpf: Fix use-after-free of program BTF in mem-alloc destructor
Date: Tue, 1 Sep 2026 18:10:30 +0100	[thread overview]
Message-ID: <ff4637bd-4919-4532-a416-fd98e2abf747@gmail.com> (raw)
In-Reply-To: <20260901062845.1379760-3-chenyuan_fl@163.com>



On 9/1/26 7:28 AM, chenyuan_fl@163.com wrote:
> From: Yuan Chen <chenyuan@kylinos.cn>
> 
> bpf_ma_set_dtor() duplicates the map's btf_record for the bpf_mem_alloc
> destructor. btf_record_dup() only borrows the BTF references held by
> the fields: kptrs and list_head/rb_root fields point at the program
> BTF, whose lifetime is independent of the map. The duplicated record is
> used from the deferred mem-alloc destructor workqueue, which can run
> after the program BTF is gone (bpf_map_free() drops the map's
> reference, and the RCU callback may run first). Reading the borrowed
> descriptors there is a use-after-free, detected by KASAN as
> "slab-use-after-free in btf_is_kernel".
> 
> Keep a reference on the borrowed program BTFs for the lifetime of the
> duplicated record. The record is freed from a preemptible worker, so
> the last btf_put() (which only schedules RCU destruction) does not make
> the field descriptors safe to read; snapshot the borrowed BTFs, free
> the record, then drop the references.
> 
> The rhtab kptr selftests exercise this path on every map teardown and
> triggered the bug under KASAN; with this fix they pass cleanly.

Does htab trigger the same kasan?

> 
> Fixes: 1df97a7453ee ("bpf: Register dtor for freeing special fields")
> Signed-off-by: Yuan Chen <chenyuan@kylinos.cn>
> ---
>  kernel/bpf/hashtab.c | 66 ++++++++++++++++++++++++++++++++++++++++++++
>  1 file changed, 66 insertions(+)
> 
> diff --git a/kernel/bpf/hashtab.c b/kernel/bpf/hashtab.c
> index aaedda3730f3..30bcc573772e 100644
> --- a/kernel/bpf/hashtab.c
> +++ b/kernel/bpf/hashtab.c
> @@ -493,11 +493,76 @@ static void htab_pcpu_mem_dtor(void *obj, void *ctx)
>  		bpf_obj_free_fields(hrec->record, per_cpu_ptr(pptr, cpu));
>  }
>  
> +/*
> + * The duplicated record borrows program BTFs, but is freed from a deferred
> + * workqueue that may run after the program BTF is gone. Hold a reference for
> + * the record's lifetime and snapshot the borrowed BTFs, since
> + * btf_record_free() frees the record.
> + */
> +
> +/* Program BTF borrowed by the field, or NULL. */
> +static struct btf *htab_field_borrowed_btf(const struct btf_field *field)
> +{
> +	struct btf *btf = NULL;
> +
> +	switch (field->type) {
> +	case BPF_KPTR_UNREF:
> +	case BPF_KPTR_REF:
> +	case BPF_KPTR_PERCPU:
> +	case BPF_UPTR:
> +		btf = field->kptr.btf;
> +		break;
> +	case BPF_LIST_HEAD:
> +	case BPF_RB_ROOT:
> +		btf = field->graph_root.btf;
> +		break;
> +	default:
> +		break;
> +	}
> +
> +	if (btf && !btf_is_kernel(btf))
> +		return btf;
> +	return NULL;
> +}
> +
> +/* Snapshot the program BTFs @rec borrows into @btfs; returns their count. */
> +static int htab_record_prog_btfs_snapshot(struct btf_record *rec,
> +					  struct btf **btfs)
> +{
> +	int i, n = 0;
> +
> +	if (IS_ERR_OR_NULL(rec))
> +		return 0;
> +
> +	for (i = 0; i < rec->cnt; i++) {
> +		struct btf *btf = htab_field_borrowed_btf(&rec->fields[i]);
> +
> +		if (btf)
> +			btfs[n++] = btf;
> +	}
> +	return n;
> +}
> +
> +static void htab_record_prog_btf_get(struct btf_record *rec)
> +{
> +	struct btf *btfs[BTF_FIELDS_MAX];

it looks like temporary array and htab_record_prog_btfs_snapshot()
are unnecessary:

for (i = 0; i < rec->cnt; i++) {
        struct btf *btf = htab_field_borrowed_btf(&rec->fields[i]);

        if (btf)
	        btf_get(btf);
}

> +	int i, n;
> +
> +	n = htab_record_prog_btfs_snapshot(rec, btfs);
> +	for (i = 0; i < n; i++)
> +		btf_get(btfs[i]);
> +}
> +
>  static void htab_dtor_ctx_free(void *ctx)
>  {
>  	struct htab_btf_record *hrec = ctx;
> +	struct btf *btfs[BTF_FIELDS_MAX];
> +	int i, n;
>  
> +	n = htab_record_prog_btfs_snapshot(hrec->record, btfs);
>  	btf_record_free(hrec->record);
> +	for (i = 0; i < n; i++)
> +		btf_put(btfs[i]);
>  	kfree(ctx);
>  }
>  
> @@ -521,6 +586,7 @@ static int bpf_ma_set_dtor(struct bpf_map *map, struct bpf_mem_alloc *ma,
>  		kfree(hrec);
>  		return err;
>  	}
> +	htab_record_prog_btf_get(hrec->record);
>  	bpf_mem_alloc_set_dtor(ma, dtor, htab_dtor_ctx_free, hrec);
>  	return 0;
>  }


  reply	other threads:[~2026-09-01 17:10 UTC|newest]

Thread overview: 34+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2026-08-11  9:55 [PATCH bpf-next 0/2] bpf: Cancel special fields in resizable hashtab on recycle chenyuan_fl
2026-08-11  9:55 ` [PATCH bpf-next 1/2] " chenyuan_fl
2026-08-11 10:50   ` bot+bpf-ci
2026-08-11  9:55 ` [PATCH bpf-next 2/2] selftests/bpf: Test rhtab kptr recycle from NMI context chenyuan_fl
2026-08-11 11:08   ` bot+bpf-ci
2026-08-11 14:22 ` [PATCH bpf-next 0/2] bpf: Cancel special fields in resizable hashtab on recycle Kumar Kartikeya Dwivedi
2026-08-24 14:36   ` [PATCH bpf-next v2 0/4] " chenyuan_fl
2026-08-24 14:36     ` [PATCH 1/4] " chenyuan_fl
2026-08-24 15:00       ` sashiko-bot
2026-08-24 15:42       ` bot+bpf-ci
2026-08-24 16:15       ` Mykyta Yatsenko
2026-09-01  6:28         ` [PATCH bpf-next v3 0/4] " chenyuan_fl
2026-09-01  6:28           ` [PATCH bpf-next v3 1/4] " chenyuan_fl
2026-09-01  6:49             ` sashiko-bot
2026-09-01  7:37             ` bot+bpf-ci
2026-09-01 16:57             ` Mykyta Yatsenko
2026-09-01  6:28           ` [PATCH bpf-next v3 2/4] bpf: Fix use-after-free of program BTF in mem-alloc destructor chenyuan_fl
2026-09-01 17:10             ` Mykyta Yatsenko [this message]
2026-09-01  6:28           ` [PATCH bpf-next v3 3/4] selftests/bpf: Test rhtab kptr recycle from NMI context chenyuan_fl
2026-09-01  6:40             ` sashiko-bot
2026-09-01  7:37             ` bot+bpf-ci
2026-09-01  6:28           ` [PATCH bpf-next v3 4/4] selftests/bpf: Test rhtab special-field combinations chenyuan_fl
2026-09-01  6:41             ` sashiko-bot
2026-09-01  7:37             ` bot+bpf-ci
2026-09-04 10:49           ` [PATCH bpf-next v3 0/4] bpf: Cancel special fields in resizable hashtab on recycle Kumar Kartikeya Dwivedi
2026-08-24 14:36     ` [PATCH 2/4] bpf: Fix use-after-free of program BTF in mem-alloc destructor chenyuan_fl
2026-08-24 15:17       ` sashiko-bot
2026-08-24 15:42       ` bot+bpf-ci
2026-08-24 14:36     ` [PATCH 3/4] selftests/bpf: Test rhtab kptr recycle from NMI context chenyuan_fl
2026-08-24 15:28       ` sashiko-bot
2026-08-24 15:42       ` bot+bpf-ci
2026-08-24 14:36     ` [PATCH 4/4] selftests/bpf: Test rhtab special-field combinations chenyuan_fl
2026-08-24 15:40       ` sashiko-bot
2026-08-24 15:42       ` bot+bpf-ci

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=ff4637bd-4919-4532-a416-fd98e2abf747@gmail.com \
    --to=mykyta.yatsenko5@gmail.com \
    --cc=andrii@kernel.org \
    --cc=ast@kernel.org \
    --cc=bpf@vger.kernel.org \
    --cc=chenyuan@kylinos.cn \
    --cc=chenyuan_fl@163.com \
    --cc=daniel@iogearbox.net \
    --cc=eddyz87@gmail.com \
    --cc=emil@etsalapatis.com \
    --cc=gnq25@mails.tsinghua.edu.cn \
    --cc=ihor.solodrai@linux.dev \
    --cc=linux-kernel@vger.kernel.org \
    --cc=linux-kselftest@vger.kernel.org \
    --cc=martin.lau@linux.dev \
    --cc=memxor@gmail.com \
    --cc=shuah@kernel.org \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.