From patchwork Sat Dec 9 00:26:56 2023 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Kui-Feng Lee X-Patchwork-Id: 13485902 X-Patchwork-Delegate: bpf@iogearbox.net Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=gmail.com header.i=@gmail.com header.b="M2mbwRUK" Received: from mail-yw1-x1131.google.com (mail-yw1-x1131.google.com [IPv6:2607:f8b0:4864:20::1131]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id D49E2171F for ; Fri, 8 Dec 2023 16:27:14 -0800 (PST) Received: by mail-yw1-x1131.google.com with SMTP id 00721157ae682-5d3758fdd2eso26366557b3.0 for ; Fri, 08 Dec 2023 16:27:14 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20230601; t=1702081633; x=1702686433; darn=vger.kernel.org; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:from:to:cc:subject:date :message-id:reply-to; bh=btc/MsJLI+X/urxNiZXzC+8XMLmtUZ3lzSYU9f3riGI=; b=M2mbwRUKZ407U6fHbUZStlVwdjwtQUfTHVQ++kK/L/2JjffaWy9dc5NG05IBkVLwHV B/mf8l/956rSQmVRVJHfYlqvIbZCZJtMPxtkV9JXOmHy65CCU+EMNe23EKv9tZUKmo4e XdEmifalfLQbFzCqKzFKAtq1C+onf2nqItTR1VntmZTMfeAbYgmjYnonsSjX0E8WxwWe OI+2kJRWXoVvxE3LpSVOiRSxmfaNgSwtndz3BqOznBG+szkAWypTHU0xSjH7LXIGaZHP y5bkBfUhP0QoHikl7KZfJLE6RjlqRM5/Rd6giW3/nkESTOc6vFksl0CL88lctUNTkJ7Y ucXw== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1702081633; x=1702686433; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:x-gm-message-state:from:to:cc :subject:date:message-id:reply-to; bh=btc/MsJLI+X/urxNiZXzC+8XMLmtUZ3lzSYU9f3riGI=; b=ij5FD3hC9QY7A/iwLL73gJkiu4Ip8pa7M3jvkK8FEByy05IjFkItnlPEw0GBSoIJSV g0arDa5jrNqz7I5nAhNbw3VCmSzEWjkDq2dheOuirh1rNy1I0otlZZHhePhYymNa71AP 9GVA16rfFiaDV9a8vRA3vZ1Yd4VKgr2oOWDz6tqdhQ+ocwQ+jkhmXCpHUkD6l/Qrk9id jfP1ipCnvczo64oJ+FvxzqiWYxlnBcLFAFo5GXvNg1RVrUkzCQgGrPhMo4731Q4FwRmb AtMgol4OWr/me5L6HBdRkqIJ+54+T3v+8dOICOWSnJ82fp/oWN5iFtYqRdR79Y++XYBI 128A== X-Gm-Message-State: AOJu0YzBXJGrBCZBtC9fxED1geKh2x+uvocT2RU6xWXb/HVygdg5qymX gdsv0ugGoPhfzkUPncMzd3+f/Y71lcoYIg== X-Google-Smtp-Source: AGHT+IGc0a7Wkd4pukicHFGI/ymJHCHYp1fm9KN4GG7Ej2qm2Xs4F9ZR5hzoInhJ+74+Vjx+aNh4JA== X-Received: by 2002:a0d:dd94:0:b0:5d7:1941:356a with SMTP id g142-20020a0ddd94000000b005d71941356amr756042ywe.81.1702081633635; Fri, 08 Dec 2023 16:27:13 -0800 (PST) Received: from kickker.attlocal.net ([2600:1700:6cf8:1240:65fe:fe26:c15:a05c]) by smtp.gmail.com with ESMTPSA id v4-20020a818504000000b005d9729068f5sm1057450ywf.42.2023.12.08.16.27.12 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Fri, 08 Dec 2023 16:27:13 -0800 (PST) From: thinker.li@gmail.com To: bpf@vger.kernel.org, ast@kernel.org, martin.lau@linux.dev, song@kernel.org, kernel-team@meta.com, andrii@kernel.org, drosen@google.com Cc: sinquersw@gmail.com, kuifeng@meta.com, Kui-Feng Lee Subject: [PATCH bpf-next v13 01/14] bpf: refactory struct_ops type initialization to a function. Date: Fri, 8 Dec 2023 16:26:56 -0800 Message-Id: <20231209002709.535966-2-thinker.li@gmail.com> X-Mailer: git-send-email 2.34.1 In-Reply-To: <20231209002709.535966-1-thinker.li@gmail.com> References: <20231209002709.535966-1-thinker.li@gmail.com> Precedence: bulk X-Mailing-List: bpf@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 X-Patchwork-Delegate: bpf@iogearbox.net From: Kui-Feng Lee Move the majority of the code to bpf_struct_ops_init_one(), which can then be utilized for the initialization of newly registered dynamically allocated struct_ops types in the following patches. Signed-off-by: Kui-Feng Lee --- include/linux/btf.h | 1 + kernel/bpf/bpf_struct_ops.c | 157 +++++++++++++++++++----------------- kernel/bpf/btf.c | 5 ++ 3 files changed, 89 insertions(+), 74 deletions(-) diff --git a/include/linux/btf.h b/include/linux/btf.h index 59d404e22814..1d852dad7473 100644 --- a/include/linux/btf.h +++ b/include/linux/btf.h @@ -137,6 +137,7 @@ struct btf_struct_metas { extern const struct file_operations btf_fops; +const char *btf_get_name(const struct btf *btf); void btf_get(struct btf *btf); void btf_put(struct btf *btf); int btf_new_fd(const union bpf_attr *attr, bpfptr_t uattr, u32 uattr_sz); diff --git a/kernel/bpf/bpf_struct_ops.c b/kernel/bpf/bpf_struct_ops.c index 4d53c53fc5aa..5714e7e54f9c 100644 --- a/kernel/bpf/bpf_struct_ops.c +++ b/kernel/bpf/bpf_struct_ops.c @@ -110,102 +110,111 @@ const struct bpf_prog_ops bpf_struct_ops_prog_ops = { static const struct btf_type *module_type; -void bpf_struct_ops_init(struct btf *btf, struct bpf_verifier_log *log) +static void bpf_struct_ops_init_one(struct bpf_struct_ops *st_ops, + struct btf *btf, + struct bpf_verifier_log *log) { - s32 type_id, value_id, module_id; const struct btf_member *member; - struct bpf_struct_ops *st_ops; const struct btf_type *t; + s32 type_id, value_id; char value_name[128]; const char *mname; - u32 i, j; + int i; - /* Ensure BTF type is emitted for "struct bpf_struct_ops_##_name" */ -#define BPF_STRUCT_OPS_TYPE(_name) BTF_TYPE_EMIT(struct bpf_struct_ops_##_name); -#include "bpf_struct_ops_types.h" -#undef BPF_STRUCT_OPS_TYPE + if (strlen(st_ops->name) + VALUE_PREFIX_LEN >= + sizeof(value_name)) { + pr_warn("struct_ops name %s is too long\n", + st_ops->name); + return; + } + sprintf(value_name, "%s%s", VALUE_PREFIX, st_ops->name); - module_id = btf_find_by_name_kind(btf, "module", BTF_KIND_STRUCT); - if (module_id < 0) { - pr_warn("Cannot find struct module in btf_vmlinux\n"); + value_id = btf_find_by_name_kind(btf, value_name, + BTF_KIND_STRUCT); + if (value_id < 0) { + pr_warn("Cannot find struct %s in %s\n", + value_name, btf_get_name(btf)); return; } - module_type = btf_type_by_id(btf, module_id); - for (i = 0; i < ARRAY_SIZE(bpf_struct_ops); i++) { - st_ops = bpf_struct_ops[i]; + type_id = btf_find_by_name_kind(btf, st_ops->name, + BTF_KIND_STRUCT); + if (type_id < 0) { + pr_warn("Cannot find struct %s in %s\n", + st_ops->name, btf_get_name(btf)); + return; + } + t = btf_type_by_id(btf, type_id); + if (btf_type_vlen(t) > BPF_STRUCT_OPS_MAX_NR_MEMBERS) { + pr_warn("Cannot support #%u members in struct %s\n", + btf_type_vlen(t), st_ops->name); + return; + } - if (strlen(st_ops->name) + VALUE_PREFIX_LEN >= - sizeof(value_name)) { - pr_warn("struct_ops name %s is too long\n", + for_each_member(i, t, member) { + const struct btf_type *func_proto; + + mname = btf_name_by_offset(btf, member->name_off); + if (!*mname) { + pr_warn("anon member in struct %s is not supported\n", st_ops->name); - continue; + break; } - sprintf(value_name, "%s%s", VALUE_PREFIX, st_ops->name); - value_id = btf_find_by_name_kind(btf, value_name, - BTF_KIND_STRUCT); - if (value_id < 0) { - pr_warn("Cannot find struct %s in btf_vmlinux\n", - value_name); - continue; + if (__btf_member_bitfield_size(t, member)) { + pr_warn("bit field member %s in struct %s is not supported\n", + mname, st_ops->name); + break; } - type_id = btf_find_by_name_kind(btf, st_ops->name, - BTF_KIND_STRUCT); - if (type_id < 0) { - pr_warn("Cannot find struct %s in btf_vmlinux\n", - st_ops->name); - continue; - } - t = btf_type_by_id(btf, type_id); - if (btf_type_vlen(t) > BPF_STRUCT_OPS_MAX_NR_MEMBERS) { - pr_warn("Cannot support #%u members in struct %s\n", - btf_type_vlen(t), st_ops->name); - continue; + func_proto = btf_type_resolve_func_ptr(btf, + member->type, + NULL); + if (func_proto && + btf_distill_func_proto(log, btf, + func_proto, mname, + &st_ops->func_models[i])) { + pr_warn("Error in parsing func ptr %s in struct %s\n", + mname, st_ops->name); + break; } + } - for_each_member(j, t, member) { - const struct btf_type *func_proto; + if (i == btf_type_vlen(t)) { + if (st_ops->init(btf)) { + pr_warn("Error in init bpf_struct_ops %s\n", + st_ops->name); + } else { + st_ops->type_id = type_id; + st_ops->type = t; + st_ops->value_id = value_id; + st_ops->value_type = btf_type_by_id(btf, + value_id); + } + } +} - mname = btf_name_by_offset(btf, member->name_off); - if (!*mname) { - pr_warn("anon member in struct %s is not supported\n", - st_ops->name); - break; - } +void bpf_struct_ops_init(struct btf *btf, struct bpf_verifier_log *log) +{ + struct bpf_struct_ops *st_ops; + s32 module_id; + u32 i; - if (__btf_member_bitfield_size(t, member)) { - pr_warn("bit field member %s in struct %s is not supported\n", - mname, st_ops->name); - break; - } + /* Ensure BTF type is emitted for "struct bpf_struct_ops_##_name" */ +#define BPF_STRUCT_OPS_TYPE(_name) BTF_TYPE_EMIT(struct bpf_struct_ops_##_name); +#include "bpf_struct_ops_types.h" +#undef BPF_STRUCT_OPS_TYPE - func_proto = btf_type_resolve_func_ptr(btf, - member->type, - NULL); - if (func_proto && - btf_distill_func_proto(log, btf, - func_proto, mname, - &st_ops->func_models[j])) { - pr_warn("Error in parsing func ptr %s in struct %s\n", - mname, st_ops->name); - break; - } - } + module_id = btf_find_by_name_kind(btf, "module", BTF_KIND_STRUCT); + if (module_id < 0) { + pr_warn("Cannot find struct module in %s\n", btf_get_name(btf)); + return; + } + module_type = btf_type_by_id(btf, module_id); - if (j == btf_type_vlen(t)) { - if (st_ops->init(btf)) { - pr_warn("Error in init bpf_struct_ops %s\n", - st_ops->name); - } else { - st_ops->type_id = type_id; - st_ops->type = t; - st_ops->value_id = value_id; - st_ops->value_type = btf_type_by_id(btf, - value_id); - } - } + for (i = 0; i < ARRAY_SIZE(bpf_struct_ops); i++) { + st_ops = bpf_struct_ops[i]; + bpf_struct_ops_init_one(st_ops, btf, log); } } diff --git a/kernel/bpf/btf.c b/kernel/bpf/btf.c index 63cf4128fc05..6935a88ed190 100644 --- a/kernel/bpf/btf.c +++ b/kernel/bpf/btf.c @@ -1707,6 +1707,11 @@ static void btf_free_rcu(struct rcu_head *rcu) btf_free(btf); } +const char *btf_get_name(const struct btf *btf) +{ + return btf->name; +} + void btf_get(struct btf *btf) { refcount_inc(&btf->refcnt); From patchwork Sat Dec 9 00:26:57 2023 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Kui-Feng Lee X-Patchwork-Id: 13485903 X-Patchwork-Delegate: bpf@iogearbox.net Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=gmail.com header.i=@gmail.com header.b="bNgMruqE" Received: from mail-yw1-x112b.google.com (mail-yw1-x112b.google.com [IPv6:2607:f8b0:4864:20::112b]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id D54881738 for ; Fri, 8 Dec 2023 16:27:15 -0800 (PST) Received: by mail-yw1-x112b.google.com with SMTP id 00721157ae682-5d77a1163faso20608437b3.0 for ; Fri, 08 Dec 2023 16:27:15 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20230601; t=1702081635; x=1702686435; darn=vger.kernel.org; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:from:to:cc:subject:date :message-id:reply-to; bh=jQ882GQwuYeEMKBt97e8U9tmg5pMnTPPfdQENCg/vVo=; b=bNgMruqE8qY4zpx94sMAeZFbFWt7Ju9ZJbTW+gMA/nx9H7X46Zojo4NBXuhAGKHQAk 1fJt7sbbLxZAuxpJob/SVP1l7msUehT9zDtG2YyHFg+ODWGnlYOClv0WiVYnQTTURVLU tPocGYoLaZmhccJrMXLOUXRyGa4JTaoktlPUgTRaajC1sOMGDe27z30ZU8gOgJnHHHlW bzsNCFOpScJwo/c3tgxs3ssa4BB+w7F6bhzoEle8u61o+P6so9Zz2O+ZBjLvG6uFS58f QrLdsub2qMT3Ljk1dtfdmmmYEeEyQaB59U7+4JthJWS2kc9X3uZSjHzVLoJl8koEQNOi Op5A== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1702081635; x=1702686435; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:x-gm-message-state:from:to:cc :subject:date:message-id:reply-to; bh=jQ882GQwuYeEMKBt97e8U9tmg5pMnTPPfdQENCg/vVo=; b=a6eA/EqHauTazOY7dr2/ELb0WxJn2fxXs6K2oK04DnmYHnb7c1e8sAAmf+fH6NY/a1 X4z8Pz8rRlrNYl9EOFRPSbvKk8VqE50TMMraK8ZBBXuiJ81PtWBhtjrvUucp9aDjX18C l0gZUnLie/dG4LD9RBSzZwHqIah9x1QHqp1J+XkZKyqmGKimjkiRARqtdnUr+GZ+Ys/C X44AAmYcD8bqVopKIJJmqU/TlCQTB0iZprJqIU8aF4wCG5z8vItY379AU7oJ8wZjZkh/ YS/Jng9tOENfKZ/L3+jrDwui5OTJNH+2SRqRckh1x7qo3FYxdKJ6k/ai38uMHoxsABv1 Yi6g== X-Gm-Message-State: AOJu0Ywn5CNuzcgfrTVeO9dEbVQy/3+XCpgYsAjLmfHjJ3J3v9nZ4SMf xM5GftOvCQPeenVROI6o8Ocx4xR459rbcA== X-Google-Smtp-Source: AGHT+IHg07SmBDSjabpvwe5D1cnfKjTUNoTOAD/jnQIsZMSw/KzHd2nQ8TM/5iqYahEp3rti/rdCOg== X-Received: by 2002:a0d:eac1:0:b0:5d3:f9b6:34ea with SMTP id t184-20020a0deac1000000b005d3f9b634eamr970135ywe.17.1702081634788; Fri, 08 Dec 2023 16:27:14 -0800 (PST) Received: from kickker.attlocal.net ([2600:1700:6cf8:1240:65fe:fe26:c15:a05c]) by smtp.gmail.com with ESMTPSA id v4-20020a818504000000b005d9729068f5sm1057450ywf.42.2023.12.08.16.27.13 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Fri, 08 Dec 2023 16:27:14 -0800 (PST) From: thinker.li@gmail.com To: bpf@vger.kernel.org, ast@kernel.org, martin.lau@linux.dev, song@kernel.org, kernel-team@meta.com, andrii@kernel.org, drosen@google.com Cc: sinquersw@gmail.com, kuifeng@meta.com, Kui-Feng Lee Subject: [PATCH bpf-next v13 02/14] bpf: get type information with BPF_ID_LIST Date: Fri, 8 Dec 2023 16:26:57 -0800 Message-Id: <20231209002709.535966-3-thinker.li@gmail.com> X-Mailer: git-send-email 2.34.1 In-Reply-To: <20231209002709.535966-1-thinker.li@gmail.com> References: <20231209002709.535966-1-thinker.li@gmail.com> Precedence: bulk X-Mailing-List: bpf@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 X-Patchwork-Delegate: bpf@iogearbox.net From: Kui-Feng Lee Get ready to remove bpf_struct_ops_init() in the future. By using BPF_ID_LIST, it is possible to gather type information while building instead of runtime. Signed-off-by: Kui-Feng Lee --- kernel/bpf/bpf_struct_ops.c | 17 ++++++++--------- 1 file changed, 8 insertions(+), 9 deletions(-) diff --git a/kernel/bpf/bpf_struct_ops.c b/kernel/bpf/bpf_struct_ops.c index 5714e7e54f9c..9f95e9fc00f3 100644 --- a/kernel/bpf/bpf_struct_ops.c +++ b/kernel/bpf/bpf_struct_ops.c @@ -108,7 +108,12 @@ const struct bpf_prog_ops bpf_struct_ops_prog_ops = { #endif }; -static const struct btf_type *module_type; +BTF_ID_LIST(st_ops_ids) +BTF_ID(struct, module) + +enum { + IDX_MODULE_ID, +}; static void bpf_struct_ops_init_one(struct bpf_struct_ops *st_ops, struct btf *btf, @@ -197,7 +202,6 @@ static void bpf_struct_ops_init_one(struct bpf_struct_ops *st_ops, void bpf_struct_ops_init(struct btf *btf, struct bpf_verifier_log *log) { struct bpf_struct_ops *st_ops; - s32 module_id; u32 i; /* Ensure BTF type is emitted for "struct bpf_struct_ops_##_name" */ @@ -205,13 +209,6 @@ void bpf_struct_ops_init(struct btf *btf, struct bpf_verifier_log *log) #include "bpf_struct_ops_types.h" #undef BPF_STRUCT_OPS_TYPE - module_id = btf_find_by_name_kind(btf, "module", BTF_KIND_STRUCT); - if (module_id < 0) { - pr_warn("Cannot find struct module in %s\n", btf_get_name(btf)); - return; - } - module_type = btf_type_by_id(btf, module_id); - for (i = 0; i < ARRAY_SIZE(bpf_struct_ops); i++) { st_ops = bpf_struct_ops[i]; bpf_struct_ops_init_one(st_ops, btf, log); @@ -388,6 +385,7 @@ static long bpf_struct_ops_map_update_elem(struct bpf_map *map, void *key, struct bpf_struct_ops_map *st_map = (struct bpf_struct_ops_map *)map; const struct bpf_struct_ops *st_ops = st_map->st_ops; struct bpf_struct_ops_value *uvalue, *kvalue; + const struct btf_type *module_type; const struct btf_member *member; const struct btf_type *t = st_ops->type; struct bpf_tramp_links *tlinks; @@ -435,6 +433,7 @@ static long bpf_struct_ops_map_update_elem(struct bpf_map *map, void *key, image = st_map->image; image_end = st_map->image + PAGE_SIZE; + module_type = btf_type_by_id(btf_vmlinux, st_ops_ids[IDX_MODULE_ID]); for_each_member(i, t, member) { const struct btf_type *mtype, *ptype; struct bpf_prog *prog; From patchwork Sat Dec 9 00:26:58 2023 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Kui-Feng Lee X-Patchwork-Id: 13485904 X-Patchwork-Delegate: bpf@iogearbox.net Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=gmail.com header.i=@gmail.com header.b="R10UQXKR" Received: from mail-yw1-x112f.google.com (mail-yw1-x112f.google.com [IPv6:2607:f8b0:4864:20::112f]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id 2F8521705; Fri, 8 Dec 2023 16:27:17 -0800 (PST) Received: by mail-yw1-x112f.google.com with SMTP id 00721157ae682-5cdc0b3526eso20486277b3.1; Fri, 08 Dec 2023 16:27:17 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20230601; t=1702081636; x=1702686436; darn=vger.kernel.org; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:from:to:cc:subject:date :message-id:reply-to; bh=5YxCJ2LpSDuh80VgjGDS3WPMLZzWL8C+83wbs3qkJn0=; b=R10UQXKRtTzAn9jwBeQPIk6ozKJPP0gfP+OEVkyj2a1iOmVYWx6SWlBc9m+Bk0L+F0 et1uIAOdXUUuamLfJXsU8/jR5sQlReC8qVzNVWJsF3uihon8wHiPLMVM/LOnDpmnjtUB Jg1+dIbLFjMlV+SyQxlo+SR68y25MKwYP/tiLhM9pGp6GKjK/+6ETQJbQglniv4dEHo3 GSxuOEBcj3Kb9yYZak2hA7m7Tz1NfnAJw7OV/whMKIvpb4ynF+xeFcT0iMUok29C6sLR wMRC4xn3zA/D82z0LVSLPsqF73YheLkwbQGVjcRezi8srnXWPwvQTss0vUGCyrl0v4lH ixWA== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1702081636; x=1702686436; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:x-gm-message-state:from:to:cc :subject:date:message-id:reply-to; bh=5YxCJ2LpSDuh80VgjGDS3WPMLZzWL8C+83wbs3qkJn0=; b=hF5nxI2yBRXXjwvF7MAM5qtrKrLdtRYgGvf26jdH9z6LqZgTbGpQXrZsuC9ryy96JR AkMsLrdIx7ljltFVB9oBadglzAc6RLByozdRgORuRRYmD1qSelnA5jt07CiTrHZ+sqDL iQ2ugrRWuKP2SKBXbctVoYJk4IViMdSRlSS00h8v1iHoI68Ux5PbyQ9UYXp75NU6sNF6 QtIUABYVxE1anrwgjfPbplwB9uVrm6ifAICgOIpIB5jry2W/fwaHg6C2uSi1Gp34kLZt BqUWbTSvtmCRubWe4IrcRL17XdUvTiQ+dPoOQRZ7AaZFdRHAIHl9VEDnmBCS+m332FIY FZ5g== X-Gm-Message-State: AOJu0YwWZqKSyC3WgsxhKVhkaSVzFVs4UImzpPVEoFHRGeS3qN8WmDOW FFTWC9HPHLQiWmdz/uKVr8wFsK9a8KQg2w== X-Google-Smtp-Source: AGHT+IHi5p//eDn+c+LKsUfgQRReYrGXf1a1IAC9hMyB6ngSPQVtupf4CRjBVNvHUIX6caIDYpXNdg== X-Received: by 2002:a0d:d909:0:b0:5d6:e87d:96c0 with SMTP id b9-20020a0dd909000000b005d6e87d96c0mr949228ywe.1.1702081635999; Fri, 08 Dec 2023 16:27:15 -0800 (PST) Received: from kickker.attlocal.net ([2600:1700:6cf8:1240:65fe:fe26:c15:a05c]) by smtp.gmail.com with ESMTPSA id v4-20020a818504000000b005d9729068f5sm1057450ywf.42.2023.12.08.16.27.14 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Fri, 08 Dec 2023 16:27:15 -0800 (PST) From: thinker.li@gmail.com To: bpf@vger.kernel.org, ast@kernel.org, martin.lau@linux.dev, song@kernel.org, kernel-team@meta.com, andrii@kernel.org, drosen@google.com Cc: sinquersw@gmail.com, kuifeng@meta.com, Kui-Feng Lee , netdev@vger.kernel.org Subject: [PATCH bpf-next v13 03/14] bpf, net: introduce bpf_struct_ops_desc. Date: Fri, 8 Dec 2023 16:26:58 -0800 Message-Id: <20231209002709.535966-4-thinker.li@gmail.com> X-Mailer: git-send-email 2.34.1 In-Reply-To: <20231209002709.535966-1-thinker.li@gmail.com> References: <20231209002709.535966-1-thinker.li@gmail.com> Precedence: bulk X-Mailing-List: bpf@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 X-Patchwork-Delegate: bpf@iogearbox.net From: Kui-Feng Lee Move some of members of bpf_struct_ops to bpf_struct_ops_desc. When we introduce the new API to register new bpf_struct_ops types from modules, bpf_struct_ops may destroyed when the module is unloaded. Moving these members to bpf_struct_ops_desc make these data available even when the module is unloaded. type_id is unavailabe in bpf_struct_ops anymore. Modules should get it from the btf received by kmod's init function. Cc: netdev@vger.kernel.org Signed-off-by: Kui-Feng Lee --- include/linux/bpf.h | 13 ++++-- kernel/bpf/bpf_struct_ops.c | 80 +++++++++++++++++----------------- kernel/bpf/verifier.c | 8 ++-- net/bpf/bpf_dummy_struct_ops.c | 9 +++- net/ipv4/bpf_tcp_ca.c | 8 +++- 5 files changed, 70 insertions(+), 48 deletions(-) diff --git a/include/linux/bpf.h b/include/linux/bpf.h index c1a06263a4f3..fa43255f59bc 100644 --- a/include/linux/bpf.h +++ b/include/linux/bpf.h @@ -1681,17 +1681,22 @@ struct bpf_struct_ops { void (*unreg)(void *kdata); int (*update)(void *kdata, void *old_kdata); int (*validate)(void *kdata); - const struct btf_type *type; - const struct btf_type *value_type; const char *name; struct btf_func_model func_models[BPF_STRUCT_OPS_MAX_NR_MEMBERS]; +}; + +struct bpf_struct_ops_desc { + struct bpf_struct_ops *st_ops; + + const struct btf_type *type; + const struct btf_type *value_type; u32 type_id; u32 value_id; }; #if defined(CONFIG_BPF_JIT) && defined(CONFIG_BPF_SYSCALL) #define BPF_MODULE_OWNER ((void *)((0xeB9FUL << 2) + POISON_POINTER_DELTA)) -const struct bpf_struct_ops *bpf_struct_ops_find(u32 type_id); +const struct bpf_struct_ops_desc *bpf_struct_ops_find(u32 type_id); void bpf_struct_ops_init(struct btf *btf, struct bpf_verifier_log *log); bool bpf_struct_ops_get(const void *kdata); void bpf_struct_ops_put(const void *kdata); @@ -1734,7 +1739,7 @@ int bpf_struct_ops_test_run(struct bpf_prog *prog, const union bpf_attr *kattr, union bpf_attr __user *uattr); #endif #else -static inline const struct bpf_struct_ops *bpf_struct_ops_find(u32 type_id) +static inline const struct bpf_struct_ops_desc *bpf_struct_ops_find(u32 type_id) { return NULL; } diff --git a/kernel/bpf/bpf_struct_ops.c b/kernel/bpf/bpf_struct_ops.c index 9f95e9fc00f3..5fbf88e6f4e5 100644 --- a/kernel/bpf/bpf_struct_ops.c +++ b/kernel/bpf/bpf_struct_ops.c @@ -32,7 +32,7 @@ struct bpf_struct_ops_value { struct bpf_struct_ops_map { struct bpf_map map; struct rcu_head rcu; - const struct bpf_struct_ops *st_ops; + const struct bpf_struct_ops_desc *st_ops_desc; /* protect map_update */ struct mutex lock; /* link has all the bpf_links that is populated @@ -92,9 +92,9 @@ enum { __NR_BPF_STRUCT_OPS_TYPE, }; -static struct bpf_struct_ops * const bpf_struct_ops[] = { +static struct bpf_struct_ops_desc bpf_struct_ops[] = { #define BPF_STRUCT_OPS_TYPE(_name) \ - [BPF_STRUCT_OPS_TYPE_##_name] = &bpf_##_name, + [BPF_STRUCT_OPS_TYPE_##_name] = { .st_ops = &bpf_##_name }, #include "bpf_struct_ops_types.h" #undef BPF_STRUCT_OPS_TYPE }; @@ -115,10 +115,11 @@ enum { IDX_MODULE_ID, }; -static void bpf_struct_ops_init_one(struct bpf_struct_ops *st_ops, - struct btf *btf, - struct bpf_verifier_log *log) +static void bpf_struct_ops_desc_init(struct bpf_struct_ops_desc *st_ops_desc, + struct btf *btf, + struct bpf_verifier_log *log) { + struct bpf_struct_ops *st_ops = st_ops_desc->st_ops; const struct btf_member *member; const struct btf_type *t; s32 type_id, value_id; @@ -190,18 +191,18 @@ static void bpf_struct_ops_init_one(struct bpf_struct_ops *st_ops, pr_warn("Error in init bpf_struct_ops %s\n", st_ops->name); } else { - st_ops->type_id = type_id; - st_ops->type = t; - st_ops->value_id = value_id; - st_ops->value_type = btf_type_by_id(btf, - value_id); + st_ops_desc->type_id = type_id; + st_ops_desc->type = t; + st_ops_desc->value_id = value_id; + st_ops_desc->value_type = btf_type_by_id(btf, + value_id); } } } void bpf_struct_ops_init(struct btf *btf, struct bpf_verifier_log *log) { - struct bpf_struct_ops *st_ops; + struct bpf_struct_ops_desc *st_ops_desc; u32 i; /* Ensure BTF type is emitted for "struct bpf_struct_ops_##_name" */ @@ -210,14 +211,14 @@ void bpf_struct_ops_init(struct btf *btf, struct bpf_verifier_log *log) #undef BPF_STRUCT_OPS_TYPE for (i = 0; i < ARRAY_SIZE(bpf_struct_ops); i++) { - st_ops = bpf_struct_ops[i]; - bpf_struct_ops_init_one(st_ops, btf, log); + st_ops_desc = &bpf_struct_ops[i]; + bpf_struct_ops_desc_init(st_ops_desc, btf, log); } } extern struct btf *btf_vmlinux; -static const struct bpf_struct_ops * +static const struct bpf_struct_ops_desc * bpf_struct_ops_find_value(u32 value_id) { unsigned int i; @@ -226,14 +227,14 @@ bpf_struct_ops_find_value(u32 value_id) return NULL; for (i = 0; i < ARRAY_SIZE(bpf_struct_ops); i++) { - if (bpf_struct_ops[i]->value_id == value_id) - return bpf_struct_ops[i]; + if (bpf_struct_ops[i].value_id == value_id) + return &bpf_struct_ops[i]; } return NULL; } -const struct bpf_struct_ops *bpf_struct_ops_find(u32 type_id) +const struct bpf_struct_ops_desc *bpf_struct_ops_find(u32 type_id) { unsigned int i; @@ -241,8 +242,8 @@ const struct bpf_struct_ops *bpf_struct_ops_find(u32 type_id) return NULL; for (i = 0; i < ARRAY_SIZE(bpf_struct_ops); i++) { - if (bpf_struct_ops[i]->type_id == type_id) - return bpf_struct_ops[i]; + if (bpf_struct_ops[i].type_id == type_id) + return &bpf_struct_ops[i]; } return NULL; @@ -302,7 +303,7 @@ static void *bpf_struct_ops_map_lookup_elem(struct bpf_map *map, void *key) static void bpf_struct_ops_map_put_progs(struct bpf_struct_ops_map *st_map) { - const struct btf_type *t = st_map->st_ops->type; + const struct btf_type *t = st_map->st_ops_desc->type; u32 i; for (i = 0; i < btf_type_vlen(t); i++) { @@ -383,11 +384,12 @@ static long bpf_struct_ops_map_update_elem(struct bpf_map *map, void *key, void *value, u64 flags) { struct bpf_struct_ops_map *st_map = (struct bpf_struct_ops_map *)map; - const struct bpf_struct_ops *st_ops = st_map->st_ops; + const struct bpf_struct_ops_desc *st_ops_desc = st_map->st_ops_desc; + const struct bpf_struct_ops *st_ops = st_ops_desc->st_ops; struct bpf_struct_ops_value *uvalue, *kvalue; const struct btf_type *module_type; const struct btf_member *member; - const struct btf_type *t = st_ops->type; + const struct btf_type *t = st_ops_desc->type; struct bpf_tramp_links *tlinks; void *udata, *kdata; int prog_fd, err; @@ -400,7 +402,7 @@ static long bpf_struct_ops_map_update_elem(struct bpf_map *map, void *key, if (*(u32 *)key != 0) return -E2BIG; - err = check_zero_holes(st_ops->value_type, value); + err = check_zero_holes(st_ops_desc->value_type, value); if (err) return err; @@ -493,7 +495,7 @@ static long bpf_struct_ops_map_update_elem(struct bpf_map *map, void *key, } if (prog->type != BPF_PROG_TYPE_STRUCT_OPS || - prog->aux->attach_btf_id != st_ops->type_id || + prog->aux->attach_btf_id != st_ops_desc->type_id || prog->expected_attach_type != i) { bpf_prog_put(prog); err = -EINVAL; @@ -588,7 +590,7 @@ static long bpf_struct_ops_map_delete_elem(struct bpf_map *map, void *key) BPF_STRUCT_OPS_STATE_TOBEFREE); switch (prev_state) { case BPF_STRUCT_OPS_STATE_INUSE: - st_map->st_ops->unreg(&st_map->kvalue.data); + st_map->st_ops_desc->st_ops->unreg(&st_map->kvalue.data); bpf_map_put(map); return 0; case BPF_STRUCT_OPS_STATE_TOBEFREE: @@ -669,22 +671,22 @@ static int bpf_struct_ops_map_alloc_check(union bpf_attr *attr) static struct bpf_map *bpf_struct_ops_map_alloc(union bpf_attr *attr) { - const struct bpf_struct_ops *st_ops; + const struct bpf_struct_ops_desc *st_ops_desc; size_t st_map_size; struct bpf_struct_ops_map *st_map; const struct btf_type *t, *vt; struct bpf_map *map; int ret; - st_ops = bpf_struct_ops_find_value(attr->btf_vmlinux_value_type_id); - if (!st_ops) + st_ops_desc = bpf_struct_ops_find_value(attr->btf_vmlinux_value_type_id); + if (!st_ops_desc) return ERR_PTR(-ENOTSUPP); - vt = st_ops->value_type; + vt = st_ops_desc->value_type; if (attr->value_size != vt->size) return ERR_PTR(-EINVAL); - t = st_ops->type; + t = st_ops_desc->type; st_map_size = sizeof(*st_map) + /* kvalue stores the @@ -696,7 +698,7 @@ static struct bpf_map *bpf_struct_ops_map_alloc(union bpf_attr *attr) if (!st_map) return ERR_PTR(-ENOMEM); - st_map->st_ops = st_ops; + st_map->st_ops_desc = st_ops_desc; map = &st_map->map; ret = bpf_jit_charge_modmem(PAGE_SIZE); @@ -733,8 +735,8 @@ static struct bpf_map *bpf_struct_ops_map_alloc(union bpf_attr *attr) static u64 bpf_struct_ops_map_mem_usage(const struct bpf_map *map) { struct bpf_struct_ops_map *st_map = (struct bpf_struct_ops_map *)map; - const struct bpf_struct_ops *st_ops = st_map->st_ops; - const struct btf_type *vt = st_ops->value_type; + const struct bpf_struct_ops_desc *st_ops_desc = st_map->st_ops_desc; + const struct btf_type *vt = st_ops_desc->value_type; u64 usage; usage = sizeof(*st_map) + @@ -808,7 +810,7 @@ static void bpf_struct_ops_map_link_dealloc(struct bpf_link *link) /* st_link->map can be NULL if * bpf_struct_ops_link_create() fails to register. */ - st_map->st_ops->unreg(&st_map->kvalue.data); + st_map->st_ops_desc->st_ops->unreg(&st_map->kvalue.data); bpf_map_put(&st_map->map); } kfree(st_link); @@ -855,7 +857,7 @@ static int bpf_struct_ops_map_link_update(struct bpf_link *link, struct bpf_map if (!bpf_struct_ops_valid_to_reg(new_map)) return -EINVAL; - if (!st_map->st_ops->update) + if (!st_map->st_ops_desc->st_ops->update) return -EOPNOTSUPP; mutex_lock(&update_mutex); @@ -868,12 +870,12 @@ static int bpf_struct_ops_map_link_update(struct bpf_link *link, struct bpf_map old_st_map = container_of(old_map, struct bpf_struct_ops_map, map); /* The new and old struct_ops must be the same type. */ - if (st_map->st_ops != old_st_map->st_ops) { + if (st_map->st_ops_desc != old_st_map->st_ops_desc) { err = -EINVAL; goto err_out; } - err = st_map->st_ops->update(st_map->kvalue.data, old_st_map->kvalue.data); + err = st_map->st_ops_desc->st_ops->update(st_map->kvalue.data, old_st_map->kvalue.data); if (err) goto err_out; @@ -924,7 +926,7 @@ int bpf_struct_ops_link_create(union bpf_attr *attr) if (err) goto err_out; - err = st_map->st_ops->reg(st_map->kvalue.data); + err = st_map->st_ops_desc->st_ops->reg(st_map->kvalue.data); if (err) { bpf_link_cleanup(&link_primer); link = NULL; diff --git a/kernel/bpf/verifier.c b/kernel/bpf/verifier.c index fb690539d5f6..ce41bc17ac10 100644 --- a/kernel/bpf/verifier.c +++ b/kernel/bpf/verifier.c @@ -20065,6 +20065,7 @@ static void print_verification_stats(struct bpf_verifier_env *env) static int check_struct_ops_btf_id(struct bpf_verifier_env *env) { const struct btf_type *t, *func_proto; + const struct bpf_struct_ops_desc *st_ops_desc; const struct bpf_struct_ops *st_ops; const struct btf_member *member; struct bpf_prog *prog = env->prog; @@ -20077,14 +20078,15 @@ static int check_struct_ops_btf_id(struct bpf_verifier_env *env) } btf_id = prog->aux->attach_btf_id; - st_ops = bpf_struct_ops_find(btf_id); - if (!st_ops) { + st_ops_desc = bpf_struct_ops_find(btf_id); + if (!st_ops_desc) { verbose(env, "attach_btf_id %u is not a supported struct\n", btf_id); return -ENOTSUPP; } + st_ops = st_ops_desc->st_ops; - t = st_ops->type; + t = st_ops_desc->type; member_idx = prog->expected_attach_type; if (member_idx >= btf_type_vlen(t)) { verbose(env, "attach to invalid member idx %u of struct %s\n", diff --git a/net/bpf/bpf_dummy_struct_ops.c b/net/bpf/bpf_dummy_struct_ops.c index 2748f9d77b18..bd753dbccaf6 100644 --- a/net/bpf/bpf_dummy_struct_ops.c +++ b/net/bpf/bpf_dummy_struct_ops.c @@ -17,6 +17,8 @@ struct bpf_dummy_ops_test_args { struct bpf_dummy_ops_state state; }; +static struct btf *bpf_dummy_ops_btf; + static struct bpf_dummy_ops_test_args * dummy_ops_init_args(const union bpf_attr *kattr, unsigned int nr) { @@ -85,9 +87,13 @@ int bpf_struct_ops_test_run(struct bpf_prog *prog, const union bpf_attr *kattr, void *image = NULL; unsigned int op_idx; int prog_ret; + u32 type_id; int err; - if (prog->aux->attach_btf_id != st_ops->type_id) + type_id = btf_find_by_name_kind(bpf_dummy_ops_btf, + bpf_bpf_dummy_ops.name, + BTF_KIND_STRUCT); + if (prog->aux->attach_btf_id != type_id) return -EOPNOTSUPP; func_proto = prog->aux->attach_func_proto; @@ -142,6 +148,7 @@ int bpf_struct_ops_test_run(struct bpf_prog *prog, const union bpf_attr *kattr, static int bpf_dummy_init(struct btf *btf) { + bpf_dummy_ops_btf = btf; return 0; } diff --git a/net/ipv4/bpf_tcp_ca.c b/net/ipv4/bpf_tcp_ca.c index c7bbd8f3c708..5bb56c9ad4e5 100644 --- a/net/ipv4/bpf_tcp_ca.c +++ b/net/ipv4/bpf_tcp_ca.c @@ -20,6 +20,7 @@ static u32 unsupported_ops[] = { static const struct btf_type *tcp_sock_type; static u32 tcp_sock_id, sock_id; +static const struct btf_type *tcp_congestion_ops_type; static int bpf_tcp_ca_init(struct btf *btf) { @@ -36,6 +37,11 @@ static int bpf_tcp_ca_init(struct btf *btf) tcp_sock_id = type_id; tcp_sock_type = btf_type_by_id(btf, tcp_sock_id); + type_id = btf_find_by_name_kind(btf, "tcp_congestion_ops", BTF_KIND_STRUCT); + if (type_id < 0) + return -EINVAL; + tcp_congestion_ops_type = btf_type_by_id(btf, type_id); + return 0; } @@ -149,7 +155,7 @@ static u32 prog_ops_moff(const struct bpf_prog *prog) u32 midx; midx = prog->expected_attach_type; - t = bpf_tcp_congestion_ops.type; + t = tcp_congestion_ops_type; m = &btf_type_member(t)[midx]; return __btf_member_bit_offset(t, m) / 8; From patchwork Sat Dec 9 00:26:59 2023 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Kui-Feng Lee X-Patchwork-Id: 13485905 X-Patchwork-Delegate: bpf@iogearbox.net Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=gmail.com header.i=@gmail.com header.b="aoApqesh" Received: from mail-yw1-x112f.google.com (mail-yw1-x112f.google.com [IPv6:2607:f8b0:4864:20::112f]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id 3BB571986 for ; Fri, 8 Dec 2023 16:27:18 -0800 (PST) Received: by mail-yw1-x112f.google.com with SMTP id 00721157ae682-5d400779f16so19673967b3.0 for ; Fri, 08 Dec 2023 16:27:18 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20230601; t=1702081637; x=1702686437; darn=vger.kernel.org; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:from:to:cc:subject:date :message-id:reply-to; bh=JmACXT60MQXvHQSw2TSPD/2h/eubxhIjthBeSg/9uI0=; b=aoApqeshkYMfzEgU/df6Ryv6AZ9Q2bKrrqOXb+4Z4qtCGxXD37AAOroadvY1ieY9Oh RULkyaY93gAyAToTBdXM0g2BA5i/MErK3SRjhMYOvw3PDCWlOa9aM8Dvf6Crvjf4YJps AmBD/R2S+1QyPGkvwZL8M2pdv7rpxX8g7TkSokYbCxe8jVYlWWh+D+AGar0LxJOF0UXp Ow7Un8qMqTUPYi/+ukss2BoRMHXZk1epB5KdWL1rKxd5YPMWpfbGNVPCS2bHeP+ti0yG qnGaL7vV18Apw2GCWPefoUd8RLHg0ElpkNbbWseU5RerUappIPHmJb3EHhZLMCU8lrtg D5lw== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1702081637; x=1702686437; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:x-gm-message-state:from:to:cc :subject:date:message-id:reply-to; bh=JmACXT60MQXvHQSw2TSPD/2h/eubxhIjthBeSg/9uI0=; b=ahdCBX72wfbnbbhjkIU7FxC1u2UgmQyzHoH5yq6kLTu2nugozrjGp3+LL56lQPejqE U4dPaTub6+8u/g9jrTpbgCIcqBD3j7gwWzyET7FAp7giWY9J3mXcTSfB9yYnDntFzUlI zn5r69qHupo1LUOKomlpDUKbxdSD8QSBJIXsgSq6O6j7dFUjWeOn7yxv8j+dPd/LYnpv EG7ZZ5u2JzZ2E7yVo/l8AbAYJqyrWACXp8ah2Fxk0NWZzUfyhBp3ycDHYJFaM0ebtvE1 Qv6v2Ad38ZQDbyiQINOZb9tv5iq4RQff8IlTD2GNXA6U4I0y7CB258qLWw2yFGIfZXex 9Bhg== X-Gm-Message-State: AOJu0YyAI6tPwdoxvKV4WGHl2D3T6IFtxScKrbOsRSuMbkQMa01XJjs1 PIkqiFMfEiiRlMmS76hR3xJ0ezUOsiy9nQ== X-Google-Smtp-Source: AGHT+IEn9A2hV7jbiR4E5EH/4wKcveeCwE/1udKMgePHYFwHCjvYQiWUTvIfC1jGwlU0OOuMuxz+tQ== X-Received: by 2002:a81:d50e:0:b0:5cd:ef57:ce3a with SMTP id i14-20020a81d50e000000b005cdef57ce3amr943023ywj.0.1702081637169; Fri, 08 Dec 2023 16:27:17 -0800 (PST) Received: from kickker.attlocal.net ([2600:1700:6cf8:1240:65fe:fe26:c15:a05c]) by smtp.gmail.com with ESMTPSA id v4-20020a818504000000b005d9729068f5sm1057450ywf.42.2023.12.08.16.27.16 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Fri, 08 Dec 2023 16:27:16 -0800 (PST) From: thinker.li@gmail.com To: bpf@vger.kernel.org, ast@kernel.org, martin.lau@linux.dev, song@kernel.org, kernel-team@meta.com, andrii@kernel.org, drosen@google.com Cc: sinquersw@gmail.com, kuifeng@meta.com, Kui-Feng Lee Subject: [PATCH bpf-next v13 04/14] bpf: add struct_ops_tab to btf. Date: Fri, 8 Dec 2023 16:26:59 -0800 Message-Id: <20231209002709.535966-5-thinker.li@gmail.com> X-Mailer: git-send-email 2.34.1 In-Reply-To: <20231209002709.535966-1-thinker.li@gmail.com> References: <20231209002709.535966-1-thinker.li@gmail.com> Precedence: bulk X-Mailing-List: bpf@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 X-Patchwork-Delegate: bpf@iogearbox.net From: Kui-Feng Lee Maintain a registry of registered struct_ops types in the per-btf (module) struct_ops_tab. This registry allows for easy lookup of struct_ops types that are registered by a specific module. It is a preparation work for supporting kernel module struct_ops in a latter patch. Each struct_ops will be registered under its own kernel module btf and will be stored in the newly added btf->struct_ops_tab. The bpf verifier and bpf syscall (e.g. prog and map cmd) can find the struct_ops and its btf type/size/id... information from btf->struct_ops_tab. Signed-off-by: Kui-Feng Lee --- include/linux/btf.h | 5 ++++ kernel/bpf/btf.c | 73 +++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 78 insertions(+) diff --git a/include/linux/btf.h b/include/linux/btf.h index 1d852dad7473..e2f4b85cf82a 100644 --- a/include/linux/btf.h +++ b/include/linux/btf.h @@ -584,4 +584,9 @@ static inline bool btf_type_is_struct_ptr(struct btf *btf, const struct btf_type return btf_type_is_struct(t); } +struct bpf_struct_ops_desc; + +const struct bpf_struct_ops_desc * +btf_get_struct_ops(struct btf *btf, u32 *ret_cnt); + #endif diff --git a/kernel/bpf/btf.c b/kernel/bpf/btf.c index 6935a88ed190..edbe3cbf2dcc 100644 --- a/kernel/bpf/btf.c +++ b/kernel/bpf/btf.c @@ -241,6 +241,12 @@ struct btf_id_dtor_kfunc_tab { struct btf_id_dtor_kfunc dtors[]; }; +struct btf_struct_ops_tab { + u32 cnt; + u32 capacity; + struct bpf_struct_ops_desc ops[]; +}; + struct btf { void *data; struct btf_type **types; @@ -258,6 +264,7 @@ struct btf { struct btf_kfunc_set_tab *kfunc_set_tab; struct btf_id_dtor_kfunc_tab *dtor_kfunc_tab; struct btf_struct_metas *struct_meta_tab; + struct btf_struct_ops_tab *struct_ops_tab; /* split BTF support */ struct btf *base_btf; @@ -1688,11 +1695,20 @@ static void btf_free_struct_meta_tab(struct btf *btf) btf->struct_meta_tab = NULL; } +static void btf_free_struct_ops_tab(struct btf *btf) +{ + struct btf_struct_ops_tab *tab = btf->struct_ops_tab; + + kfree(tab); + btf->struct_ops_tab = NULL; +} + static void btf_free(struct btf *btf) { btf_free_struct_meta_tab(btf); btf_free_dtor_kfunc_tab(btf); btf_free_kfunc_set_tab(btf); + btf_free_struct_ops_tab(btf); kvfree(btf->types); kvfree(btf->resolved_sizes); kvfree(btf->resolved_ids); @@ -8604,3 +8620,60 @@ bool btf_type_ids_nocast_alias(struct bpf_verifier_log *log, return !strncmp(reg_name, arg_name, cmp_len); } + +static int +btf_add_struct_ops(struct btf *btf, struct bpf_struct_ops *st_ops) +{ + struct btf_struct_ops_tab *tab, *new_tab; + int i; + + if (!btf) + return -ENOENT; + + /* Assume this function is called for a module when the module is + * loading. + */ + + tab = btf->struct_ops_tab; + if (!tab) { + tab = kzalloc(offsetof(struct btf_struct_ops_tab, ops[4]), + GFP_KERNEL); + if (!tab) + return -ENOMEM; + tab->capacity = 4; + btf->struct_ops_tab = tab; + } + + for (i = 0; i < tab->cnt; i++) + if (tab->ops[i].st_ops == st_ops) + return -EEXIST; + + if (tab->cnt == tab->capacity) { + new_tab = krealloc(tab, + offsetof(struct btf_struct_ops_tab, + ops[tab->capacity * 2]), + GFP_KERNEL); + if (!new_tab) + return -ENOMEM; + tab = new_tab; + tab->capacity *= 2; + btf->struct_ops_tab = tab; + } + + tab->ops[btf->struct_ops_tab->cnt].st_ops = st_ops; + + btf->struct_ops_tab->cnt++; + + return 0; +} + +const struct bpf_struct_ops_desc *btf_get_struct_ops(struct btf *btf, u32 *ret_cnt) +{ + if (!btf) + return NULL; + if (!btf->struct_ops_tab) + return NULL; + + *ret_cnt = btf->struct_ops_tab->cnt; + return (const struct bpf_struct_ops_desc *)btf->struct_ops_tab->ops; +} From patchwork Sat Dec 9 00:27:00 2023 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Kui-Feng Lee X-Patchwork-Id: 13485906 X-Patchwork-Delegate: bpf@iogearbox.net Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=gmail.com header.i=@gmail.com header.b="UPpCpVsO" Received: from mail-yw1-x112d.google.com (mail-yw1-x112d.google.com [IPv6:2607:f8b0:4864:20::112d]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id AB4F3172A for ; Fri, 8 Dec 2023 16:27:19 -0800 (PST) Received: by mail-yw1-x112d.google.com with SMTP id 00721157ae682-5d05ff42db0so24685117b3.2 for ; Fri, 08 Dec 2023 16:27:19 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20230601; t=1702081638; x=1702686438; darn=vger.kernel.org; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:from:to:cc:subject:date :message-id:reply-to; bh=WcijZ7zmEhMwBkAsr+58qnwQoyW4UBii1bAJMTXNQnA=; b=UPpCpVsO+EWDhVwP1KUWtuV7Zp2ARCB1Kxt0IkSGygRLS/NX4zhxlxPSomATDcpS7o RWP2A2luwPVIEXzshCJRmhAAH6Y9BjIevMX4biP9IBW0bGWZ74NPdUyUu20U56ccJuDZ phHrcps4zfdDPE9lLhJefDzMSCrxNjZO7BfWyPaf5iHLE71GfIoI86vMck5qX3Gx5G8w ETeM2sB1ZyO4Uvnv0j0HxhVAw7VZ/kpeMebNr3ksmowyN5YCoX3xzCsAiAzkdYMDfU6U DPS05ZnkWDytiUqzM4vUuIpe/aaAHNsd+Gzvjgs0g0X7ixL9cTDfgyAX2ePfv0kHhEBk crfg== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1702081638; x=1702686438; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:x-gm-message-state:from:to:cc :subject:date:message-id:reply-to; bh=WcijZ7zmEhMwBkAsr+58qnwQoyW4UBii1bAJMTXNQnA=; b=D+qXUh1hXZ3Nfy3npn8foZN0zMleqUwHlY6LL9UaS2UqmK1483kJL4z+iWDZ+nGJgs L1EcC/ByjO57AkcY8FJ/34/fCGj5UJ1sZL54Q/EKuRJNQJgVAGR7N3NnyVPUHyJP43I7 1fBMLbPoRTOmT/5YCerhWBJ6C1DCKZzjzpSos3ftUo2MVvZv1wEd1mmqGjkDfy2YDIh0 wgfdjTzOb+coBytdth+QNJLzs79gr4M0KXea0ha8PSp9gJQ65bFaOFygLqpd5QSH+/RO M7UrYe/Tqu+hRpEGObct0b25Q7pI7d47lxXIo3Rqv0sO2fSE++65xMwuCRawOYSzmRE1 zoYg== X-Gm-Message-State: AOJu0Yw8UlearuJYS6YOIRs3lZKCRd9nY7f3LqWHFLVVv+eQRfnfL1wq v5Uh/9TZky8v/weAWAd3Kx+HScvmVyFzrw== X-Google-Smtp-Source: AGHT+IGAC1GT/GNv0p1h/cadTeckcvzjbCGUiZu2ll8H2m+UJSSDHwn6lv9Z4A8e7QY4CflwFrqx0A== X-Received: by 2002:a0d:fe06:0:b0:5cd:3d82:1ac6 with SMTP id o6-20020a0dfe06000000b005cd3d821ac6mr829166ywf.42.1702081638547; Fri, 08 Dec 2023 16:27:18 -0800 (PST) Received: from kickker.attlocal.net ([2600:1700:6cf8:1240:65fe:fe26:c15:a05c]) by smtp.gmail.com with ESMTPSA id v4-20020a818504000000b005d9729068f5sm1057450ywf.42.2023.12.08.16.27.17 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Fri, 08 Dec 2023 16:27:18 -0800 (PST) From: thinker.li@gmail.com To: bpf@vger.kernel.org, ast@kernel.org, martin.lau@linux.dev, song@kernel.org, kernel-team@meta.com, andrii@kernel.org, drosen@google.com Cc: sinquersw@gmail.com, kuifeng@meta.com, Kui-Feng Lee Subject: [PATCH bpf-next v13 05/14] bpf: make struct_ops_map support btfs other than btf_vmlinux. Date: Fri, 8 Dec 2023 16:27:00 -0800 Message-Id: <20231209002709.535966-6-thinker.li@gmail.com> X-Mailer: git-send-email 2.34.1 In-Reply-To: <20231209002709.535966-1-thinker.li@gmail.com> References: <20231209002709.535966-1-thinker.li@gmail.com> Precedence: bulk X-Mailing-List: bpf@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 X-Patchwork-Delegate: bpf@iogearbox.net From: Kui-Feng Lee Once new struct_ops can be registered from modules, btf_vmlinux is no longer the only btf that struct_ops_map would face. st_map should remember what btf it should use to get type information. Signed-off-by: Kui-Feng Lee --- kernel/bpf/bpf_struct_ops.c | 24 +++++++++++++++--------- 1 file changed, 15 insertions(+), 9 deletions(-) diff --git a/kernel/bpf/bpf_struct_ops.c b/kernel/bpf/bpf_struct_ops.c index 5fbf88e6f4e5..2b0c402740cc 100644 --- a/kernel/bpf/bpf_struct_ops.c +++ b/kernel/bpf/bpf_struct_ops.c @@ -46,6 +46,8 @@ struct bpf_struct_ops_map { * "links[]". */ void *image; + /* The owner moduler's btf. */ + struct btf *btf; /* uvalue->data stores the kernel struct * (e.g. tcp_congestion_ops) that is more useful * to userspace than the kvalue. For example, @@ -314,7 +316,7 @@ static void bpf_struct_ops_map_put_progs(struct bpf_struct_ops_map *st_map) } } -static int check_zero_holes(const struct btf_type *t, void *data) +static int check_zero_holes(const struct btf *btf, const struct btf_type *t, void *data) { const struct btf_member *member; u32 i, moff, msize, prev_mend = 0; @@ -326,8 +328,8 @@ static int check_zero_holes(const struct btf_type *t, void *data) memchr_inv(data + prev_mend, 0, moff - prev_mend)) return -EINVAL; - mtype = btf_type_by_id(btf_vmlinux, member->type); - mtype = btf_resolve_size(btf_vmlinux, mtype, &msize); + mtype = btf_type_by_id(btf, member->type); + mtype = btf_resolve_size(btf, mtype, &msize); if (IS_ERR(mtype)) return PTR_ERR(mtype); prev_mend = moff + msize; @@ -402,12 +404,12 @@ static long bpf_struct_ops_map_update_elem(struct bpf_map *map, void *key, if (*(u32 *)key != 0) return -E2BIG; - err = check_zero_holes(st_ops_desc->value_type, value); + err = check_zero_holes(st_map->btf, st_ops_desc->value_type, value); if (err) return err; uvalue = value; - err = check_zero_holes(t, uvalue->data); + err = check_zero_holes(st_map->btf, t, uvalue->data); if (err) return err; @@ -443,7 +445,7 @@ static long bpf_struct_ops_map_update_elem(struct bpf_map *map, void *key, u32 moff; moff = __btf_member_bit_offset(t, member) / 8; - ptype = btf_type_resolve_ptr(btf_vmlinux, member->type, NULL); + ptype = btf_type_resolve_ptr(st_map->btf, member->type, NULL); if (ptype == module_type) { if (*(void **)(udata + moff)) goto reset_unlock; @@ -468,8 +470,8 @@ static long bpf_struct_ops_map_update_elem(struct bpf_map *map, void *key, if (!ptype || !btf_type_is_func_proto(ptype)) { u32 msize; - mtype = btf_type_by_id(btf_vmlinux, member->type); - mtype = btf_resolve_size(btf_vmlinux, mtype, &msize); + mtype = btf_type_by_id(st_map->btf, member->type); + mtype = btf_resolve_size(st_map->btf, mtype, &msize); if (IS_ERR(mtype)) { err = PTR_ERR(mtype); goto reset_unlock; @@ -607,6 +609,7 @@ static long bpf_struct_ops_map_delete_elem(struct bpf_map *map, void *key) static void bpf_struct_ops_map_seq_show_elem(struct bpf_map *map, void *key, struct seq_file *m) { + struct bpf_struct_ops_map *st_map = (struct bpf_struct_ops_map *)map; void *value; int err; @@ -616,7 +619,8 @@ static void bpf_struct_ops_map_seq_show_elem(struct bpf_map *map, void *key, err = bpf_struct_ops_map_sys_lookup_elem(map, key, value); if (!err) { - btf_type_seq_show(btf_vmlinux, map->btf_vmlinux_value_type_id, + btf_type_seq_show(st_map->btf, + map->btf_vmlinux_value_type_id, value, m); seq_puts(m, "\n"); } @@ -726,6 +730,8 @@ static struct bpf_map *bpf_struct_ops_map_alloc(union bpf_attr *attr) return ERR_PTR(-ENOMEM); } + st_map->btf = btf_vmlinux; + mutex_init(&st_map->lock); bpf_map_init_from_attr(map, attr); From patchwork Sat Dec 9 00:27:01 2023 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Kui-Feng Lee X-Patchwork-Id: 13485907 X-Patchwork-Delegate: bpf@iogearbox.net Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=gmail.com header.i=@gmail.com header.b="KVP9hbnY" Received: from mail-yw1-x112d.google.com (mail-yw1-x112d.google.com [IPv6:2607:f8b0:4864:20::112d]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id 1058E1723 for ; Fri, 8 Dec 2023 16:27:21 -0800 (PST) Received: by mail-yw1-x112d.google.com with SMTP id 00721157ae682-5d226f51f71so25651367b3.3 for ; Fri, 08 Dec 2023 16:27:21 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20230601; t=1702081640; x=1702686440; darn=vger.kernel.org; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:from:to:cc:subject:date :message-id:reply-to; bh=jdB5FWiEnCQxPfhzIAOeyjpBWMnnHt30kmPLXgz+oXU=; b=KVP9hbnY6yjHRx6VsbmwQGUuB0v9zDbcSKrsaRmM9D0h8U3loe5dioMkEghTuy4SbK Dh7oGiilavw0TDX+UpXURgw8aWmICaoWBOZjeIvZQYitUNLmyuKdGu8kv6iG7cFI3jxV rKaw4rR75EARz6ZwlQ3QKoryrtCYYXqo5/yoXaHLcYXbLh/W0FjeYdQEQzdK7FQNwsMp PNT6Ff/WfWKD6yg54lSeC9IOStSTixX6ZNMSpqm9vXxXucY5gB6N1H0JhcJHzz7zP7ba kfPzR5XpFf6fJXtfup67yyXwHd/gadmQ6y0KxnF6pRM+Fmfg1X1KVBXzwMFeaqfq7jCC z5Jg== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1702081640; x=1702686440; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:x-gm-message-state:from:to:cc :subject:date:message-id:reply-to; bh=jdB5FWiEnCQxPfhzIAOeyjpBWMnnHt30kmPLXgz+oXU=; b=NwTH4CFf1FhDDVo+ngAU80ZcyU7t2CHxBv0wIRZNf9glSJYOuKENKQ1VEKm6BjMCJt fp5DndR32At12qwjrqqoNpfwaKPF62mEihS5jhNba3s/nimWo84SaJ7kDQfyzmp1QqIu qCT1I2bU5DmSzIF1yINmdXa6wMmYXdkiV+rtjWAwkznUTKqkxlrGI+MNKW1/RwO31HEt oYEjPlwJZcRj4U17Qy8RC7EP4rwfwTLFj/o5Llxj+aPZ8++2McseXNVKQXtMDgD0MFZ9 k7J4X2MSgZtcvfR0srGzk20v9Yofk57D/GQ3jKJ9QUODEWhtR8nrvmnfzX+CZ7MtwUkm EO0w== X-Gm-Message-State: AOJu0Yy5eYJJx5HXJHDe2d20hUdpueHBB1kn+ZxRvIvAHbQBcXFyS15h oelyei6NeIwIlCmbmJKKEeYH3XPtSJs5Yw== X-Google-Smtp-Source: AGHT+IETfJVYs3sT56teuJlJIqD/Up+3BlAESPfLPZfWyheBLpDYah2abJvyH49bGxB0MUjr0xfEqQ== X-Received: by 2002:a81:488d:0:b0:5de:8c10:d17c with SMTP id v135-20020a81488d000000b005de8c10d17cmr796138ywa.66.1702081639849; Fri, 08 Dec 2023 16:27:19 -0800 (PST) Received: from kickker.attlocal.net ([2600:1700:6cf8:1240:65fe:fe26:c15:a05c]) by smtp.gmail.com with ESMTPSA id v4-20020a818504000000b005d9729068f5sm1057450ywf.42.2023.12.08.16.27.18 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Fri, 08 Dec 2023 16:27:19 -0800 (PST) From: thinker.li@gmail.com To: bpf@vger.kernel.org, ast@kernel.org, martin.lau@linux.dev, song@kernel.org, kernel-team@meta.com, andrii@kernel.org, drosen@google.com Cc: sinquersw@gmail.com, kuifeng@meta.com, Kui-Feng Lee Subject: [PATCH bpf-next v13 06/14] bpf: lookup struct_ops types from a given module BTF. Date: Fri, 8 Dec 2023 16:27:01 -0800 Message-Id: <20231209002709.535966-7-thinker.li@gmail.com> X-Mailer: git-send-email 2.34.1 In-Reply-To: <20231209002709.535966-1-thinker.li@gmail.com> References: <20231209002709.535966-1-thinker.li@gmail.com> Precedence: bulk X-Mailing-List: bpf@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 X-Patchwork-Delegate: bpf@iogearbox.net From: Kui-Feng Lee This is a preparation for searching for struct_ops types from a specified module. BTF is always btf_vmlinux now. This patch passes a pointer of BTF to bpf_struct_ops_find_value() and bpf_struct_ops_find(). Once the new registration API of struct_ops types is used, other BTFs besides btf_vmlinux can also be passed to them. Signed-off-by: Kui-Feng Lee --- include/linux/bpf.h | 4 ++-- kernel/bpf/bpf_struct_ops.c | 11 ++++++----- kernel/bpf/verifier.c | 2 +- 3 files changed, 9 insertions(+), 8 deletions(-) diff --git a/include/linux/bpf.h b/include/linux/bpf.h index fa43255f59bc..91bcd62d6fcf 100644 --- a/include/linux/bpf.h +++ b/include/linux/bpf.h @@ -1696,7 +1696,7 @@ struct bpf_struct_ops_desc { #if defined(CONFIG_BPF_JIT) && defined(CONFIG_BPF_SYSCALL) #define BPF_MODULE_OWNER ((void *)((0xeB9FUL << 2) + POISON_POINTER_DELTA)) -const struct bpf_struct_ops_desc *bpf_struct_ops_find(u32 type_id); +const struct bpf_struct_ops_desc *bpf_struct_ops_find(struct btf *btf, u32 type_id); void bpf_struct_ops_init(struct btf *btf, struct bpf_verifier_log *log); bool bpf_struct_ops_get(const void *kdata); void bpf_struct_ops_put(const void *kdata); @@ -1739,7 +1739,7 @@ int bpf_struct_ops_test_run(struct bpf_prog *prog, const union bpf_attr *kattr, union bpf_attr __user *uattr); #endif #else -static inline const struct bpf_struct_ops_desc *bpf_struct_ops_find(u32 type_id) +static inline const struct bpf_struct_ops_desc *bpf_struct_ops_find(struct btf *btf, u32 type_id) { return NULL; } diff --git a/kernel/bpf/bpf_struct_ops.c b/kernel/bpf/bpf_struct_ops.c index 2b0c402740cc..ed4d84a8437c 100644 --- a/kernel/bpf/bpf_struct_ops.c +++ b/kernel/bpf/bpf_struct_ops.c @@ -221,11 +221,11 @@ void bpf_struct_ops_init(struct btf *btf, struct bpf_verifier_log *log) extern struct btf *btf_vmlinux; static const struct bpf_struct_ops_desc * -bpf_struct_ops_find_value(u32 value_id) +bpf_struct_ops_find_value(struct btf *btf, u32 value_id) { unsigned int i; - if (!value_id || !btf_vmlinux) + if (!value_id || !btf) return NULL; for (i = 0; i < ARRAY_SIZE(bpf_struct_ops); i++) { @@ -236,11 +236,12 @@ bpf_struct_ops_find_value(u32 value_id) return NULL; } -const struct bpf_struct_ops_desc *bpf_struct_ops_find(u32 type_id) +const struct bpf_struct_ops_desc * +bpf_struct_ops_find(struct btf *btf, u32 type_id) { unsigned int i; - if (!type_id || !btf_vmlinux) + if (!type_id || !btf) return NULL; for (i = 0; i < ARRAY_SIZE(bpf_struct_ops); i++) { @@ -682,7 +683,7 @@ static struct bpf_map *bpf_struct_ops_map_alloc(union bpf_attr *attr) struct bpf_map *map; int ret; - st_ops_desc = bpf_struct_ops_find_value(attr->btf_vmlinux_value_type_id); + st_ops_desc = bpf_struct_ops_find_value(btf_vmlinux, attr->btf_vmlinux_value_type_id); if (!st_ops_desc) return ERR_PTR(-ENOTSUPP); diff --git a/kernel/bpf/verifier.c b/kernel/bpf/verifier.c index ce41bc17ac10..6b45f56f8d4c 100644 --- a/kernel/bpf/verifier.c +++ b/kernel/bpf/verifier.c @@ -20078,7 +20078,7 @@ static int check_struct_ops_btf_id(struct bpf_verifier_env *env) } btf_id = prog->aux->attach_btf_id; - st_ops_desc = bpf_struct_ops_find(btf_id); + st_ops_desc = bpf_struct_ops_find(btf_vmlinux, btf_id); if (!st_ops_desc) { verbose(env, "attach_btf_id %u is not a supported struct\n", btf_id); From patchwork Sat Dec 9 00:27:02 2023 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Kui-Feng Lee X-Patchwork-Id: 13485908 X-Patchwork-Delegate: bpf@iogearbox.net Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=gmail.com header.i=@gmail.com header.b="V7xacn01" Received: from mail-yw1-x112e.google.com (mail-yw1-x112e.google.com [IPv6:2607:f8b0:4864:20::112e]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id 21A9C1729 for ; Fri, 8 Dec 2023 16:27:22 -0800 (PST) Received: by mail-yw1-x112e.google.com with SMTP id 00721157ae682-5d05ff42db0so24685497b3.2 for ; Fri, 08 Dec 2023 16:27:22 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20230601; t=1702081641; x=1702686441; darn=vger.kernel.org; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:from:to:cc:subject:date :message-id:reply-to; bh=Ub9qoi3PTEGZNBq4TRs3aeMktswSheoGW49AGywpBTQ=; b=V7xacn01tLgZFAaTEc85s+ohGFiLaOjvvOkWbYgI/IzrM3rPkIoSx1LTP+aVwcbCHw rx0U905QilvIq+GelHsgcfJEqupncDh/YQ5fX8uuC3wQAgtCDFL2KZICjS4Ql8Hpixxc kKzwxHA2JhF4sto+wGsEGLNpA+A6XVhrtGcIjmuyFrAPJabKgKJRiYkLpkRfYRRlx4Hg d0o31jYSzbg+RESFROaLWUM80T6d5oetIRaUFWQCSlAtOuHpV6mScXAHQQclLWEUD5O4 lHobCJKZuviR27jWdy9yPctC+nn7ynyjP5vAJNWltH5v6642+VH16J+z4e7PeF3K8mM6 t8uQ== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1702081641; x=1702686441; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:x-gm-message-state:from:to:cc :subject:date:message-id:reply-to; bh=Ub9qoi3PTEGZNBq4TRs3aeMktswSheoGW49AGywpBTQ=; b=tSfq+WhgAj9e9KTcKy2pF014ZUyT87OKxw++94sekHM82sYB3C/xcqVVG99JCJcnWN 8LrBc7gBYjIB0vGSINI+I0ewZ8lrxbdTnOyjsnVDnetkB8AjFQqBusa0+6EI0uTKk0oq 3lGgaw8QzyhyZtVaVjRfdgUI0HxqJoEop8qBNac+8byH9OxxAu9hS1Nv6R+gYZQGo5LP 6lSLiqAsW3fPQnnwMVJGGgfB3zk3EBTyA+AZ2PKNCT+gaXSoc1gR3q1NiwlYdVDNGVd8 l2UuwMWH8DXVcZWIaAkFdQXaDnljESUekqBt2uEG1eR5T0Nijm8iv/Ft/20wyxoomnum 1SEA== X-Gm-Message-State: AOJu0YzybBhxgnvnvEV5nMy+/7QDsHuvtG7GkvQsBE+OtH9Lr6R044At Q/mD8JZCu1M2CKAhkg+igbJn1DEP7rvUgg== X-Google-Smtp-Source: AGHT+IGJKpJZfW1G1bRUXimEFHHbwnp8/DBBrrJ2f06Tj4VDXOvLxKse9cb1canzuAEbIOSD4MBeQg== X-Received: by 2002:a0d:d4d0:0:b0:5cc:dcf:47a4 with SMTP id w199-20020a0dd4d0000000b005cc0dcf47a4mr890301ywd.40.1702081641057; Fri, 08 Dec 2023 16:27:21 -0800 (PST) Received: from kickker.attlocal.net ([2600:1700:6cf8:1240:65fe:fe26:c15:a05c]) by smtp.gmail.com with ESMTPSA id v4-20020a818504000000b005d9729068f5sm1057450ywf.42.2023.12.08.16.27.19 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Fri, 08 Dec 2023 16:27:20 -0800 (PST) From: thinker.li@gmail.com To: bpf@vger.kernel.org, ast@kernel.org, martin.lau@linux.dev, song@kernel.org, kernel-team@meta.com, andrii@kernel.org, drosen@google.com Cc: sinquersw@gmail.com, kuifeng@meta.com, Kui-Feng Lee Subject: [PATCH bpf-next v13 07/14] bpf: pass attached BTF to the bpf_struct_ops subsystem Date: Fri, 8 Dec 2023 16:27:02 -0800 Message-Id: <20231209002709.535966-8-thinker.li@gmail.com> X-Mailer: git-send-email 2.34.1 In-Reply-To: <20231209002709.535966-1-thinker.li@gmail.com> References: <20231209002709.535966-1-thinker.li@gmail.com> Precedence: bulk X-Mailing-List: bpf@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 X-Patchwork-Delegate: bpf@iogearbox.net From: Kui-Feng Lee Pass the fd of a btf from the userspace to the bpf() syscall, and then convert the fd into a btf. The btf is generated from the module that defines the target BPF struct_ops type. In order to inform the kernel about the module that defines the target struct_ops type, the userspace program needs to provide a btf fd for the respective module's btf. This btf contains essential information on the types defined within the module, including the target struct_ops type. A btf fd must be provided to the kernel for struct_ops maps struct_ops and for the bpf programs attached to those maps. In the case of the bpf programs, the attach_btf_obj_fd parameter is passed as part of the bpf_attr and is converted into a btf. This btf is then stored in the prog->aux->attach_btf field. Here, it just let the verifier access attach_btf directly. In the case of struct_ops maps, a btf fd is passed as value_type_btf_obj_fd of bpf_attr. The bpf_struct_ops_map_alloc() function converts the fd to a btf and stores it as st_map->btf. Signed-off-by: Kui-Feng Lee --- include/uapi/linux/bpf.h | 5 +++ kernel/bpf/bpf_struct_ops.c | 56 +++++++++++++++++++++++----------- kernel/bpf/syscall.c | 2 +- kernel/bpf/verifier.c | 9 ++++-- tools/include/uapi/linux/bpf.h | 5 +++ 5 files changed, 56 insertions(+), 21 deletions(-) diff --git a/include/uapi/linux/bpf.h b/include/uapi/linux/bpf.h index e0545201b55f..5c3838a97554 100644 --- a/include/uapi/linux/bpf.h +++ b/include/uapi/linux/bpf.h @@ -1438,6 +1438,11 @@ union bpf_attr { */ __u64 map_extra; __u32 map_token_fd; + + __u32 value_type_btf_obj_fd; /* fd pointing to a BTF + * type data for + * btf_vmlinux_value_type_id. + */ }; struct { /* anonymous struct used by BPF_MAP_*_ELEM commands */ diff --git a/kernel/bpf/bpf_struct_ops.c b/kernel/bpf/bpf_struct_ops.c index ed4d84a8437c..f943f8378e76 100644 --- a/kernel/bpf/bpf_struct_ops.c +++ b/kernel/bpf/bpf_struct_ops.c @@ -641,6 +641,7 @@ static void __bpf_struct_ops_map_free(struct bpf_map *map) bpf_jit_uncharge_modmem(PAGE_SIZE); } bpf_map_area_free(st_map->uvalue); + btf_put(st_map->btf); bpf_map_area_free(st_map); } @@ -681,15 +682,30 @@ static struct bpf_map *bpf_struct_ops_map_alloc(union bpf_attr *attr) struct bpf_struct_ops_map *st_map; const struct btf_type *t, *vt; struct bpf_map *map; + struct btf *btf; int ret; - st_ops_desc = bpf_struct_ops_find_value(btf_vmlinux, attr->btf_vmlinux_value_type_id); - if (!st_ops_desc) - return ERR_PTR(-ENOTSUPP); + if (attr->value_type_btf_obj_fd) { + /* The map holds btf for its whole life time. */ + btf = btf_get_by_fd(attr->value_type_btf_obj_fd); + if (IS_ERR(btf)) + return ERR_PTR(PTR_ERR(btf)); + } else { + btf = btf_vmlinux; + btf_get(btf); + } + + st_ops_desc = bpf_struct_ops_find_value(btf, attr->btf_vmlinux_value_type_id); + if (!st_ops_desc) { + ret = -ENOTSUPP; + goto errout; + } vt = st_ops_desc->value_type; - if (attr->value_size != vt->size) - return ERR_PTR(-EINVAL); + if (attr->value_size != vt->size) { + ret = -EINVAL; + goto errout; + } t = st_ops_desc->type; @@ -700,17 +716,17 @@ static struct bpf_map *bpf_struct_ops_map_alloc(union bpf_attr *attr) (vt->size - sizeof(struct bpf_struct_ops_value)); st_map = bpf_map_area_alloc(st_map_size, NUMA_NO_NODE); - if (!st_map) - return ERR_PTR(-ENOMEM); + if (!st_map) { + ret = -ENOMEM; + goto errout; + } st_map->st_ops_desc = st_ops_desc; map = &st_map->map; ret = bpf_jit_charge_modmem(PAGE_SIZE); - if (ret) { - __bpf_struct_ops_map_free(map); - return ERR_PTR(ret); - } + if (ret) + goto errout_free; st_map->image = arch_alloc_bpf_trampoline(PAGE_SIZE); if (!st_map->image) { @@ -719,24 +735,30 @@ static struct bpf_map *bpf_struct_ops_map_alloc(union bpf_attr *attr) * here. */ bpf_jit_uncharge_modmem(PAGE_SIZE); - __bpf_struct_ops_map_free(map); - return ERR_PTR(-ENOMEM); + ret = -ENOMEM; + goto errout_free; } st_map->uvalue = bpf_map_area_alloc(vt->size, NUMA_NO_NODE); st_map->links = bpf_map_area_alloc(btf_type_vlen(t) * sizeof(struct bpf_links *), NUMA_NO_NODE); if (!st_map->uvalue || !st_map->links) { - __bpf_struct_ops_map_free(map); - return ERR_PTR(-ENOMEM); + ret = -ENOMEM; + goto errout_free; } - - st_map->btf = btf_vmlinux; + st_map->btf = btf; mutex_init(&st_map->lock); bpf_map_init_from_attr(map, attr); return map; + +errout_free: + __bpf_struct_ops_map_free(map); +errout: + btf_put(btf); + + return ERR_PTR(ret); } static u64 bpf_struct_ops_map_mem_usage(const struct bpf_map *map) diff --git a/kernel/bpf/syscall.c b/kernel/bpf/syscall.c index aff045eed375..4aced7e58904 100644 --- a/kernel/bpf/syscall.c +++ b/kernel/bpf/syscall.c @@ -1126,7 +1126,7 @@ static bool bpf_net_capable(void) return capable(CAP_NET_ADMIN) || capable(CAP_SYS_ADMIN); } -#define BPF_MAP_CREATE_LAST_FIELD map_token_fd +#define BPF_MAP_CREATE_LAST_FIELD value_type_btf_obj_fd /* called via syscall */ static int map_create(union bpf_attr *attr) { diff --git a/kernel/bpf/verifier.c b/kernel/bpf/verifier.c index 6b45f56f8d4c..795c16f9cf57 100644 --- a/kernel/bpf/verifier.c +++ b/kernel/bpf/verifier.c @@ -20070,6 +20070,7 @@ static int check_struct_ops_btf_id(struct bpf_verifier_env *env) const struct btf_member *member; struct bpf_prog *prog = env->prog; u32 btf_id, member_idx; + struct btf *btf; const char *mname; if (!prog->gpl_compatible) { @@ -20077,8 +20078,10 @@ static int check_struct_ops_btf_id(struct bpf_verifier_env *env) return -EINVAL; } + btf = prog->aux->attach_btf; + btf_id = prog->aux->attach_btf_id; - st_ops_desc = bpf_struct_ops_find(btf_vmlinux, btf_id); + st_ops_desc = bpf_struct_ops_find(btf, btf_id); if (!st_ops_desc) { verbose(env, "attach_btf_id %u is not a supported struct\n", btf_id); @@ -20095,8 +20098,8 @@ static int check_struct_ops_btf_id(struct bpf_verifier_env *env) } member = &btf_type_member(t)[member_idx]; - mname = btf_name_by_offset(btf_vmlinux, member->name_off); - func_proto = btf_type_resolve_func_ptr(btf_vmlinux, member->type, + mname = btf_name_by_offset(btf, member->name_off); + func_proto = btf_type_resolve_func_ptr(btf, member->type, NULL); if (!func_proto) { verbose(env, "attach to invalid member %s(@idx %u) of struct %s\n", diff --git a/tools/include/uapi/linux/bpf.h b/tools/include/uapi/linux/bpf.h index e0545201b55f..5c3838a97554 100644 --- a/tools/include/uapi/linux/bpf.h +++ b/tools/include/uapi/linux/bpf.h @@ -1438,6 +1438,11 @@ union bpf_attr { */ __u64 map_extra; __u32 map_token_fd; + + __u32 value_type_btf_obj_fd; /* fd pointing to a BTF + * type data for + * btf_vmlinux_value_type_id. + */ }; struct { /* anonymous struct used by BPF_MAP_*_ELEM commands */ From patchwork Sat Dec 9 00:27:03 2023 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Kui-Feng Lee X-Patchwork-Id: 13485909 X-Patchwork-Delegate: bpf@iogearbox.net Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=gmail.com header.i=@gmail.com header.b="gdB2v8xY" Received: from mail-yw1-x1133.google.com (mail-yw1-x1133.google.com [IPv6:2607:f8b0:4864:20::1133]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id 9C1BE173F for ; Fri, 8 Dec 2023 16:27:23 -0800 (PST) Received: by mail-yw1-x1133.google.com with SMTP id 00721157ae682-5cbcfdeaff3so25937927b3.0 for ; Fri, 08 Dec 2023 16:27:23 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20230601; t=1702081642; x=1702686442; darn=vger.kernel.org; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:from:to:cc:subject:date :message-id:reply-to; bh=tfhqBiCsXCASGYfkeUeDDTs+pOQh8dtlrhATgleG490=; b=gdB2v8xY/Rsfh65E75/1+btcjAf5/RV+MOiqmbGGp6GVdFNpDZjPc1DZhfIm7nElib 4Pup4whHlQDiIxyuaknuGOqdFJuYNKaIAsNPO7+jxG705uN86yLq7ImOEpqaHaBXsT8j UuzO/vnkoLGeCV8Gunhsv1qHjp43gXfXaBFDtpXSuafeEm1L5ylKNHVwVlYTWh4k+dL+ 9iUAuzN57Y3a7DUuTgO/MRKs0lBZp1l54pg88WskKYtjB4RttgvEkUL7COrK03JNYcbV gjjM0m609n8USj5AHiZJE9bDU0yVG1Za6ui1Hx+J8FUlPGiAnBtSeYTQCtHA0qsw6gRZ n2XA== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1702081642; x=1702686442; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:x-gm-message-state:from:to:cc :subject:date:message-id:reply-to; bh=tfhqBiCsXCASGYfkeUeDDTs+pOQh8dtlrhATgleG490=; b=Mn7XcS1kfUpPtJBcqbd1B4MogVWOjQOdP73WxPUJw2dvdLJI+kfrzVS4CXR4GhzQGu SOt5MO4VckiGvyPDtFThlIIYqTR6r/T0OBHzpUutYywzhayLM8IMtk7RwxZjyi+B82rA mO220f1RdunCI9PxQaIc5l84LJXEgjjK66qFmkTTrJO81mAQYtgG/fcIEfXkQJ4baL2B SLk2NtBGBdnXklFN4oXmY2kL9GXgC/lmOdh3Xs8z44TeOuyJu+VJxB6ocFwnMU72VZis kmFZ2TY+5aeKjPccNIQVvZPLOINRIuFInY+gUEsU1lOMcONrTb9TSwPb9uSOzmLRzboO UmhA== X-Gm-Message-State: AOJu0YxnhF1LG6yvg6uz9JoHn8PKrArxL4P0jiJ/2lGJFwlpmwvjP5Fc IS4j4ryHq1D+xQ/sdMXm1iOgCvv1wpBtdQ== X-Google-Smtp-Source: AGHT+IEj6OxKPpgobk0bAXSmNHUBDJw6GIiKKL/jcW+B5tlcwBeM4tdEWYnBsVRWiYre1I0UVoFsWA== X-Received: by 2002:a81:528f:0:b0:59b:dbb7:5c74 with SMTP id g137-20020a81528f000000b0059bdbb75c74mr856989ywb.32.1702081642287; Fri, 08 Dec 2023 16:27:22 -0800 (PST) Received: from kickker.attlocal.net ([2600:1700:6cf8:1240:65fe:fe26:c15:a05c]) by smtp.gmail.com with ESMTPSA id v4-20020a818504000000b005d9729068f5sm1057450ywf.42.2023.12.08.16.27.21 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Fri, 08 Dec 2023 16:27:22 -0800 (PST) From: thinker.li@gmail.com To: bpf@vger.kernel.org, ast@kernel.org, martin.lau@linux.dev, song@kernel.org, kernel-team@meta.com, andrii@kernel.org, drosen@google.com Cc: sinquersw@gmail.com, kuifeng@meta.com, Kui-Feng Lee Subject: [PATCH bpf-next v13 08/14] bpf: hold module for bpf_struct_ops_map. Date: Fri, 8 Dec 2023 16:27:03 -0800 Message-Id: <20231209002709.535966-9-thinker.li@gmail.com> X-Mailer: git-send-email 2.34.1 In-Reply-To: <20231209002709.535966-1-thinker.li@gmail.com> References: <20231209002709.535966-1-thinker.li@gmail.com> Precedence: bulk X-Mailing-List: bpf@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 X-Patchwork-Delegate: bpf@iogearbox.net From: Kui-Feng Lee To ensure that a module remains accessible whenever a struct_ops object of a struct_ops type provided by the module is still in use. struct bpf_strct_ops_map doesn't hold a refcnt to btf anymore sicne a module will hold a refcnt to it's btf already. But, struct_ops programs are different. They hold their associated btf, not the module since they need only btf to assure their types (signatures). Signed-off-by: Kui-Feng Lee --- include/linux/bpf.h | 1 + include/linux/bpf_verifier.h | 1 + kernel/bpf/bpf_struct_ops.c | 28 +++++++++++++++++++++++----- kernel/bpf/verifier.c | 10 ++++++++++ 4 files changed, 35 insertions(+), 5 deletions(-) diff --git a/include/linux/bpf.h b/include/linux/bpf.h index 91bcd62d6fcf..c5c7cc4552f5 100644 --- a/include/linux/bpf.h +++ b/include/linux/bpf.h @@ -1681,6 +1681,7 @@ struct bpf_struct_ops { void (*unreg)(void *kdata); int (*update)(void *kdata, void *old_kdata); int (*validate)(void *kdata); + struct module *owner; const char *name; struct btf_func_model func_models[BPF_STRUCT_OPS_MAX_NR_MEMBERS]; }; diff --git a/include/linux/bpf_verifier.h b/include/linux/bpf_verifier.h index 314b679fb494..01113bcdd479 100644 --- a/include/linux/bpf_verifier.h +++ b/include/linux/bpf_verifier.h @@ -651,6 +651,7 @@ struct bpf_verifier_env { u32 prev_insn_idx; struct bpf_prog *prog; /* eBPF program being verified */ const struct bpf_verifier_ops *ops; + struct module *attach_btf_mod; /* The owner module of prog->aux->attach_btf */ struct bpf_verifier_stack_elem *head; /* stack of verifier states to be processed */ int stack_size; /* number of states to be processed */ bool strict_alignment; /* perform strict pointer alignment checks */ diff --git a/kernel/bpf/bpf_struct_ops.c b/kernel/bpf/bpf_struct_ops.c index f943f8378e76..a838f7c7d583 100644 --- a/kernel/bpf/bpf_struct_ops.c +++ b/kernel/bpf/bpf_struct_ops.c @@ -641,12 +641,15 @@ static void __bpf_struct_ops_map_free(struct bpf_map *map) bpf_jit_uncharge_modmem(PAGE_SIZE); } bpf_map_area_free(st_map->uvalue); - btf_put(st_map->btf); bpf_map_area_free(st_map); } static void bpf_struct_ops_map_free(struct bpf_map *map) { + struct bpf_struct_ops_map *st_map = (struct bpf_struct_ops_map *)map; + + module_put(st_map->st_ops_desc->st_ops->owner); + /* The struct_ops's function may switch to another struct_ops. * * For example, bpf_tcp_cc_x->init() may switch to @@ -681,6 +684,7 @@ static struct bpf_map *bpf_struct_ops_map_alloc(union bpf_attr *attr) size_t st_map_size; struct bpf_struct_ops_map *st_map; const struct btf_type *t, *vt; + struct module *mod = NULL; struct bpf_map *map; struct btf *btf; int ret; @@ -690,10 +694,20 @@ static struct bpf_map *bpf_struct_ops_map_alloc(union bpf_attr *attr) btf = btf_get_by_fd(attr->value_type_btf_obj_fd); if (IS_ERR(btf)) return ERR_PTR(PTR_ERR(btf)); - } else { + + if (btf != btf_vmlinux) { + mod = btf_try_get_module(btf); + if (!mod) { + btf_put(btf); + return ERR_PTR(-EINVAL); + } + } + /* mod (NULL for btf_vmlinux) holds a refcnt to btf. We + * don't need an extra refcnt here. + */ + btf_put(btf); + } else btf = btf_vmlinux; - btf_get(btf); - } st_ops_desc = bpf_struct_ops_find_value(btf, attr->btf_vmlinux_value_type_id); if (!st_ops_desc) { @@ -756,7 +770,7 @@ static struct bpf_map *bpf_struct_ops_map_alloc(union bpf_attr *attr) errout_free: __bpf_struct_ops_map_free(map); errout: - btf_put(btf); + module_put(mod); return ERR_PTR(ret); } @@ -886,6 +900,10 @@ static int bpf_struct_ops_map_link_update(struct bpf_link *link, struct bpf_map if (!bpf_struct_ops_valid_to_reg(new_map)) return -EINVAL; + /* The old map is holding the refcount for the owner module. The + * ownership of the owner module refcount is going to be + * transferred from the old map to the new map. + */ if (!st_map->st_ops_desc->st_ops->update) return -EOPNOTSUPP; diff --git a/kernel/bpf/verifier.c b/kernel/bpf/verifier.c index 795c16f9cf57..c303cf2fb5ff 100644 --- a/kernel/bpf/verifier.c +++ b/kernel/bpf/verifier.c @@ -20079,6 +20079,14 @@ static int check_struct_ops_btf_id(struct bpf_verifier_env *env) } btf = prog->aux->attach_btf; + if (btf != btf_vmlinux) { + /* Make sure st_ops is valid through the lifetime of env */ + env->attach_btf_mod = btf_try_get_module(btf); + if (!env->attach_btf_mod) { + verbose(env, "owner module of btf is not found\n"); + return -ENOTSUPP; + } + } btf_id = prog->aux->attach_btf_id; st_ops_desc = bpf_struct_ops_find(btf, btf_id); @@ -20792,6 +20800,8 @@ int bpf_check(struct bpf_prog **prog, union bpf_attr *attr, bpfptr_t uattr, __u3 env->prog->expected_attach_type = 0; *prog = env->prog; + + module_put(env->attach_btf_mod); err_unlock: if (!is_priv) mutex_unlock(&bpf_verifier_lock); From patchwork Sat Dec 9 00:27:04 2023 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Kui-Feng Lee X-Patchwork-Id: 13485910 X-Patchwork-Delegate: bpf@iogearbox.net Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=gmail.com header.i=@gmail.com header.b="I7Mxz60B" Received: from mail-yw1-x112e.google.com (mail-yw1-x112e.google.com [IPv6:2607:f8b0:4864:20::112e]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id 179741724 for ; Fri, 8 Dec 2023 16:27:25 -0800 (PST) Received: by mail-yw1-x112e.google.com with SMTP id 00721157ae682-5d7346442d4so26164257b3.2 for ; Fri, 08 Dec 2023 16:27:25 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20230601; t=1702081644; x=1702686444; darn=vger.kernel.org; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:from:to:cc:subject:date :message-id:reply-to; bh=Bgf+ctWQ0pSKS0s8nWnhuS4dGiWOMUNFnJTO3cnAaik=; b=I7Mxz60BUhNEtbnx9rMcn16jAJsDrefATkNeRO7W+ARd5pC66o5okTAfdFcxzxAAiJ sxQ5FydT0Gv6sOLF3QILwLmt3ks+ZvwhhMPGYUjI19P++/1OMRaL8+2PQafNmu7eAVYR Tg/HT2DkbZamwOuWDTyKOy0za0MUYMx8BmLrEEp13W8mA4s10CBDH8Vma4h1Kvd7rw+M UI0nFnCIBvJ3DWdQDIIsBq/R3SZuppYa49OP1rNyejLoahV5ltKapEAonelGst+AnU+2 QqvImj7iYUZE6HmJbNUNL38mQtXJREqYGI6cHK9wV8wawWa7fVg/rFO1EErmYls9h/Xt lEpA== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1702081644; x=1702686444; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:x-gm-message-state:from:to:cc :subject:date:message-id:reply-to; bh=Bgf+ctWQ0pSKS0s8nWnhuS4dGiWOMUNFnJTO3cnAaik=; b=CFMh7OAqevfKSDCuAYQT57eqBob6Lr2e4vl9Wn56ycGu/HFbWqbtsR4JUQvyeIOIXh tzCNtlyn8U9rMd27eFM7jtVEhU1oAlQgxVVyKzA3o7WZ4E48divFQS4S0ZanUwuk6Jg6 f3csqt9229vecqDZbmkivu6ltO7RQdbk1969/VLsZVrvNU/DN9YFmx9Rwa/slauZeeae IPLrVQoPrK+iibYyKxRiVT9dIxVus0Jl+sAc+J71i+hz0/f1cU+nlRzwb9SwtYRZONHW rIzpqWs9vVDpj4uOMLJuRb1YQPZ2VJt0afTdRT0bJh6Fr6TD1tn7Yg/QYedD4ZmFtJD9 IK1Q== X-Gm-Message-State: AOJu0Yw3PLZS02FtGsM8TSluhl09btD17GHXhY2MV51unYwZ7vwIMgaQ 7xQS8cMoybGEI9lj4WCnDBZnB3GZlt9/lA== X-Google-Smtp-Source: AGHT+IExtvgEl+ANe70eRJdlCDBnc3Pewp6fUTxocLwfK0GB7l3wlreJWtOrzw2RL3vWt/8vc4FzNQ== X-Received: by 2002:a0d:e681:0:b0:5d7:1941:3552 with SMTP id p123-20020a0de681000000b005d719413552mr819596ywe.57.1702081644013; Fri, 08 Dec 2023 16:27:24 -0800 (PST) Received: from kickker.attlocal.net ([2600:1700:6cf8:1240:65fe:fe26:c15:a05c]) by smtp.gmail.com with ESMTPSA id v4-20020a818504000000b005d9729068f5sm1057450ywf.42.2023.12.08.16.27.22 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Fri, 08 Dec 2023 16:27:23 -0800 (PST) From: thinker.li@gmail.com To: bpf@vger.kernel.org, ast@kernel.org, martin.lau@linux.dev, song@kernel.org, kernel-team@meta.com, andrii@kernel.org, drosen@google.com Cc: sinquersw@gmail.com, kuifeng@meta.com, Kui-Feng Lee Subject: [PATCH bpf-next v13 09/14] bpf: validate value_type Date: Fri, 8 Dec 2023 16:27:04 -0800 Message-Id: <20231209002709.535966-10-thinker.li@gmail.com> X-Mailer: git-send-email 2.34.1 In-Reply-To: <20231209002709.535966-1-thinker.li@gmail.com> References: <20231209002709.535966-1-thinker.li@gmail.com> Precedence: bulk X-Mailing-List: bpf@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 X-Patchwork-Delegate: bpf@iogearbox.net From: Kui-Feng Lee A value_type should consist of three components: refcnt, state, and data. refcnt and state has been move to struct bpf_struct_ops_common_value to make it easier to check the value type. Signed-off-by: Kui-Feng Lee --- include/linux/bpf.h | 12 +++++ kernel/bpf/bpf_struct_ops.c | 93 ++++++++++++++++++++++++------------- 2 files changed, 72 insertions(+), 33 deletions(-) diff --git a/include/linux/bpf.h b/include/linux/bpf.h index c5c7cc4552f5..7384806ee74e 100644 --- a/include/linux/bpf.h +++ b/include/linux/bpf.h @@ -3321,4 +3321,16 @@ static inline bool bpf_is_subprog(const struct bpf_prog *prog) return prog->aux->func_idx != 0; } +enum bpf_struct_ops_state { + BPF_STRUCT_OPS_STATE_INIT, + BPF_STRUCT_OPS_STATE_INUSE, + BPF_STRUCT_OPS_STATE_TOBEFREE, + BPF_STRUCT_OPS_STATE_READY, +}; + +struct bpf_struct_ops_common_value { + refcount_t refcnt; + enum bpf_struct_ops_state state; +}; + #endif /* _LINUX_BPF_H */ diff --git a/kernel/bpf/bpf_struct_ops.c b/kernel/bpf/bpf_struct_ops.c index a838f7c7d583..a3d9ffbdba00 100644 --- a/kernel/bpf/bpf_struct_ops.c +++ b/kernel/bpf/bpf_struct_ops.c @@ -13,19 +13,8 @@ #include #include -enum bpf_struct_ops_state { - BPF_STRUCT_OPS_STATE_INIT, - BPF_STRUCT_OPS_STATE_INUSE, - BPF_STRUCT_OPS_STATE_TOBEFREE, - BPF_STRUCT_OPS_STATE_READY, -}; - -#define BPF_STRUCT_OPS_COMMON_VALUE \ - refcount_t refcnt; \ - enum bpf_struct_ops_state state - struct bpf_struct_ops_value { - BPF_STRUCT_OPS_COMMON_VALUE; + struct bpf_struct_ops_common_value common; char data[] ____cacheline_aligned_in_smp; }; @@ -80,8 +69,8 @@ static DEFINE_MUTEX(update_mutex); #define BPF_STRUCT_OPS_TYPE(_name) \ extern struct bpf_struct_ops bpf_##_name; \ \ -struct bpf_struct_ops_##_name { \ - BPF_STRUCT_OPS_COMMON_VALUE; \ +struct bpf_struct_ops_##_name { \ + struct bpf_struct_ops_common_value common; \ struct _name data ____cacheline_aligned_in_smp; \ }; #include "bpf_struct_ops_types.h" @@ -112,11 +101,49 @@ const struct bpf_prog_ops bpf_struct_ops_prog_ops = { BTF_ID_LIST(st_ops_ids) BTF_ID(struct, module) +BTF_ID(struct, bpf_struct_ops_common_value) enum { IDX_MODULE_ID, + IDX_ST_OPS_COMMON_VALUE_ID, }; +extern struct btf *btf_vmlinux; + +static bool is_valid_value_type(struct btf *btf, s32 value_id, + const struct btf_type *type, + const char *value_name) +{ + const struct btf_type *common_value_type; + const struct btf_member *member; + const struct btf_type *vt, *mt; + + vt = btf_type_by_id(btf, value_id); + if (btf_vlen(vt) != 2) { + pr_warn("The number of %s's members should be 2, but we get %d\n", + value_name, btf_vlen(vt)); + return false; + } + member = btf_type_member(vt); + mt = btf_type_by_id(btf, member->type); + common_value_type = btf_type_by_id(btf_vmlinux, + st_ops_ids[IDX_ST_OPS_COMMON_VALUE_ID]); + if (mt != common_value_type) { + pr_warn("The first member of %s should be bpf_struct_ops_common_value\n", + value_name); + return false; + } + member++; + mt = btf_type_by_id(btf, member->type); + if (mt != type) { + pr_warn("The second member of %s should be %s\n", + value_name, btf_name_by_offset(btf, type->name_off)); + return false; + } + + return true; +} + static void bpf_struct_ops_desc_init(struct bpf_struct_ops_desc *st_ops_desc, struct btf *btf, struct bpf_verifier_log *log) @@ -137,14 +164,6 @@ static void bpf_struct_ops_desc_init(struct bpf_struct_ops_desc *st_ops_desc, } sprintf(value_name, "%s%s", VALUE_PREFIX, st_ops->name); - value_id = btf_find_by_name_kind(btf, value_name, - BTF_KIND_STRUCT); - if (value_id < 0) { - pr_warn("Cannot find struct %s in %s\n", - value_name, btf_get_name(btf)); - return; - } - type_id = btf_find_by_name_kind(btf, st_ops->name, BTF_KIND_STRUCT); if (type_id < 0) { @@ -159,6 +178,16 @@ static void bpf_struct_ops_desc_init(struct bpf_struct_ops_desc *st_ops_desc, return; } + value_id = btf_find_by_name_kind(btf, value_name, + BTF_KIND_STRUCT); + if (value_id < 0) { + pr_warn("Cannot find struct %s in %s\n", + value_name, btf_get_name(btf)); + return; + } + if (!is_valid_value_type(btf, value_id, t, value_name)) + return; + for_each_member(i, t, member) { const struct btf_type *func_proto; @@ -218,8 +247,6 @@ void bpf_struct_ops_init(struct btf *btf, struct bpf_verifier_log *log) } } -extern struct btf *btf_vmlinux; - static const struct bpf_struct_ops_desc * bpf_struct_ops_find_value(struct btf *btf, u32 value_id) { @@ -275,7 +302,7 @@ int bpf_struct_ops_map_sys_lookup_elem(struct bpf_map *map, void *key, kvalue = &st_map->kvalue; /* Pair with smp_store_release() during map_update */ - state = smp_load_acquire(&kvalue->state); + state = smp_load_acquire(&kvalue->common.state); if (state == BPF_STRUCT_OPS_STATE_INIT) { memset(value, 0, map->value_size); return 0; @@ -286,7 +313,7 @@ int bpf_struct_ops_map_sys_lookup_elem(struct bpf_map *map, void *key, */ uvalue = value; memcpy(uvalue, st_map->uvalue, map->value_size); - uvalue->state = state; + uvalue->common.state = state; /* This value offers the user space a general estimate of how * many sockets are still utilizing this struct_ops for TCP @@ -294,7 +321,7 @@ int bpf_struct_ops_map_sys_lookup_elem(struct bpf_map *map, void *key, * should sufficiently meet our present goals. */ refcnt = atomic64_read(&map->refcnt) - atomic64_read(&map->usercnt); - refcount_set(&uvalue->refcnt, max_t(s64, refcnt, 0)); + refcount_set(&uvalue->common.refcnt, max_t(s64, refcnt, 0)); return 0; } @@ -414,7 +441,7 @@ static long bpf_struct_ops_map_update_elem(struct bpf_map *map, void *key, if (err) return err; - if (uvalue->state || refcount_read(&uvalue->refcnt)) + if (uvalue->common.state || refcount_read(&uvalue->common.refcnt)) return -EINVAL; tlinks = kcalloc(BPF_TRAMP_MAX, sizeof(*tlinks), GFP_KERNEL); @@ -426,7 +453,7 @@ static long bpf_struct_ops_map_update_elem(struct bpf_map *map, void *key, mutex_lock(&st_map->lock); - if (kvalue->state != BPF_STRUCT_OPS_STATE_INIT) { + if (kvalue->common.state != BPF_STRUCT_OPS_STATE_INIT) { err = -EBUSY; goto unlock; } @@ -540,7 +567,7 @@ static long bpf_struct_ops_map_update_elem(struct bpf_map *map, void *key, * * Pair with smp_load_acquire() during lookup_elem(). */ - smp_store_release(&kvalue->state, BPF_STRUCT_OPS_STATE_READY); + smp_store_release(&kvalue->common.state, BPF_STRUCT_OPS_STATE_READY); goto unlock; } @@ -558,7 +585,7 @@ static long bpf_struct_ops_map_update_elem(struct bpf_map *map, void *key, * It ensures the above udata updates (e.g. prog->aux->id) * can be seen once BPF_STRUCT_OPS_STATE_INUSE is set. */ - smp_store_release(&kvalue->state, BPF_STRUCT_OPS_STATE_INUSE); + smp_store_release(&kvalue->common.state, BPF_STRUCT_OPS_STATE_INUSE); goto unlock; } @@ -588,7 +615,7 @@ static long bpf_struct_ops_map_delete_elem(struct bpf_map *map, void *key) if (st_map->map.map_flags & BPF_F_LINK) return -EOPNOTSUPP; - prev_state = cmpxchg(&st_map->kvalue.state, + prev_state = cmpxchg(&st_map->kvalue.common.state, BPF_STRUCT_OPS_STATE_INUSE, BPF_STRUCT_OPS_STATE_TOBEFREE); switch (prev_state) { @@ -838,7 +865,7 @@ static bool bpf_struct_ops_valid_to_reg(struct bpf_map *map) return map->map_type == BPF_MAP_TYPE_STRUCT_OPS && map->map_flags & BPF_F_LINK && /* Pair with smp_store_release() during map_update */ - smp_load_acquire(&st_map->kvalue.state) == BPF_STRUCT_OPS_STATE_READY; + smp_load_acquire(&st_map->kvalue.common.state) == BPF_STRUCT_OPS_STATE_READY; } static void bpf_struct_ops_map_link_dealloc(struct bpf_link *link) From patchwork Sat Dec 9 00:27:05 2023 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Kui-Feng Lee X-Patchwork-Id: 13485911 X-Patchwork-Delegate: bpf@iogearbox.net Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=gmail.com header.i=@gmail.com header.b="GZsn4iEW" Received: from mail-yw1-x1134.google.com (mail-yw1-x1134.google.com [IPv6:2607:f8b0:4864:20::1134]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id 5047E1705; Fri, 8 Dec 2023 16:27:26 -0800 (PST) Received: by mail-yw1-x1134.google.com with SMTP id 00721157ae682-5d74186170fso23374447b3.3; Fri, 08 Dec 2023 16:27:26 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20230601; t=1702081645; x=1702686445; darn=vger.kernel.org; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:from:to:cc:subject:date :message-id:reply-to; bh=rAOnWn7+ElC6WLtSm+cP6o03Y5T9/6ZDP2/ecoBUnyM=; b=GZsn4iEWrp5zVC4rbDJTnxkIZcm3erKpyczlWSjIXi/62waJQBxlBPJzFcmN/HdvQR FKHs1lE4kQNP56sp1ZDIenXEMxOXMl6Q2P70rRRjv/Z3wYDI6ISwRQk4YQzGB2RnmL/U LyLRKeopMoizZdURR0LsZCMSeSZiQUtdnSEEpXdTA318Wf6VeVqhvL2QysTk9Cg0f5bR 4qeSiGZZGNtCVyEHVok9qyfEUUF8vlK4LjLRPwhw1ZiGB5L/1+SiS9IP5Io2hxk9WZVM j5+nVJvODDY3rl6HRdA9NtrpoFlxhMJsxpq8wff3RbEwD2aQnFnq5S2WC/5sRirABByg yNLA== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1702081645; x=1702686445; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:x-gm-message-state:from:to:cc :subject:date:message-id:reply-to; bh=rAOnWn7+ElC6WLtSm+cP6o03Y5T9/6ZDP2/ecoBUnyM=; b=hc/2o1lbVA24KAIA6dbq+SCgQYc7lEG+8Xc4iRRRXZ/Yws3xAosVITXteFI7LznPj+ JFhNJdglvnncoMs2sxtfTGqtYNNHHjWy+97mg+4UEp8icIxZ+kwRNUBflyIxl1sYAXpS bHrRsrzMiWc9ykrIpdw1WrmT9jiCKrDwjGFv0/ZOiiN7iJBBeSNxDFQjRPIDwae1tqis KEXv8GldalhQMvFXLyv+gAaIqEy5Bq6qpp/gvRrxndhPhuXIdp7K7YZu9kStLR6EAVzr /XNr3ZDNkUiQ+p9PRFdwIiH9CgysJ3sW57t8Z8LVxLs3jWJiyeJACDz1vTL2r7C8u/lP efeQ== X-Gm-Message-State: AOJu0YzqtKOEwKH8EvJ6huTOlMxYBvwdqu23nlrpEG5FqB51YQJlF8AD 3o1YZ3Jej4zmWTaNXFYHdzV3gk/6k4zmEg== X-Google-Smtp-Source: AGHT+IHhDIRvLjNVvmCt9SIo7ZFv2kZzd7avF2i9J9EajJ7sy2T5mYefqDlBPwjfhL5Eb/km+qaFAQ== X-Received: by 2002:a0d:dd04:0:b0:5d9:712e:2032 with SMTP id g4-20020a0ddd04000000b005d9712e2032mr768500ywe.2.1702081645202; Fri, 08 Dec 2023 16:27:25 -0800 (PST) Received: from kickker.attlocal.net ([2600:1700:6cf8:1240:65fe:fe26:c15:a05c]) by smtp.gmail.com with ESMTPSA id v4-20020a818504000000b005d9729068f5sm1057450ywf.42.2023.12.08.16.27.24 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Fri, 08 Dec 2023 16:27:24 -0800 (PST) From: thinker.li@gmail.com To: bpf@vger.kernel.org, ast@kernel.org, martin.lau@linux.dev, song@kernel.org, kernel-team@meta.com, andrii@kernel.org, drosen@google.com Cc: sinquersw@gmail.com, kuifeng@meta.com, Kui-Feng Lee , netdev@vger.kernel.org Subject: [PATCH bpf-next v13 10/14] bpf, net: switch to dynamic registration Date: Fri, 8 Dec 2023 16:27:05 -0800 Message-Id: <20231209002709.535966-11-thinker.li@gmail.com> X-Mailer: git-send-email 2.34.1 In-Reply-To: <20231209002709.535966-1-thinker.li@gmail.com> References: <20231209002709.535966-1-thinker.li@gmail.com> Precedence: bulk X-Mailing-List: bpf@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 X-Patchwork-Delegate: bpf@iogearbox.net From: Kui-Feng Lee Replace the static list of struct_ops types with per-btf struct_ops_tab to enable dynamic registration. Both bpf_dummy_ops and bpf_tcp_ca now utilize the registration function instead of being listed in bpf_struct_ops_types.h. Cc: netdev@vger.kernel.org Signed-off-by: Kui-Feng Lee --- include/linux/bpf.h | 28 ++++++++-- include/linux/btf.h | 2 + kernel/bpf/bpf_struct_ops.c | 90 ++++++++++--------------------- kernel/bpf/bpf_struct_ops_types.h | 12 ----- kernel/bpf/btf.c | 49 +++++++++++++++-- net/bpf/bpf_dummy_struct_ops.c | 13 ++++- net/ipv4/bpf_tcp_ca.c | 14 +++-- 7 files changed, 119 insertions(+), 89 deletions(-) delete mode 100644 kernel/bpf/bpf_struct_ops_types.h diff --git a/include/linux/bpf.h b/include/linux/bpf.h index 7384806ee74e..c881befa35f5 100644 --- a/include/linux/bpf.h +++ b/include/linux/bpf.h @@ -1698,7 +1698,6 @@ struct bpf_struct_ops_desc { #if defined(CONFIG_BPF_JIT) && defined(CONFIG_BPF_SYSCALL) #define BPF_MODULE_OWNER ((void *)((0xeB9FUL << 2) + POISON_POINTER_DELTA)) const struct bpf_struct_ops_desc *bpf_struct_ops_find(struct btf *btf, u32 type_id); -void bpf_struct_ops_init(struct btf *btf, struct bpf_verifier_log *log); bool bpf_struct_ops_get(const void *kdata); void bpf_struct_ops_put(const void *kdata); int bpf_struct_ops_map_sys_lookup_elem(struct bpf_map *map, void *key, @@ -1744,10 +1743,6 @@ static inline const struct bpf_struct_ops_desc *bpf_struct_ops_find(struct btf * { return NULL; } -static inline void bpf_struct_ops_init(struct btf *btf, - struct bpf_verifier_log *log) -{ -} static inline bool bpf_try_module_get(const void *data, struct module *owner) { return try_module_get(owner); @@ -3321,6 +3316,14 @@ static inline bool bpf_is_subprog(const struct bpf_prog *prog) return prog->aux->func_idx != 0; } +int register_bpf_struct_ops(struct bpf_struct_ops *st_ops); + +#define REGISTER_BPF_STRUCT_OPS(st_ops, type) \ +({ \ + BTF_STRUCT_OPS_TYPE_EMIT(type); \ + register_bpf_struct_ops(st_ops); \ +}) + enum bpf_struct_ops_state { BPF_STRUCT_OPS_STATE_INIT, BPF_STRUCT_OPS_STATE_INUSE, @@ -3333,4 +3336,19 @@ struct bpf_struct_ops_common_value { enum bpf_struct_ops_state state; }; +/* bpf_struct_ops_##_name (e.g. bpf_struct_ops_tcp_congestion_ops) is + * the map's value exposed to the userspace and its btf-type-id is + * stored at the map->btf_vmlinux_value_type_id. + * + */ +#define DEFINE_STRUCT_OPS_VALUE_TYPE(_name) \ +struct bpf_struct_ops_##_name { \ + struct bpf_struct_ops_common_value common; \ + struct _name data ____cacheline_aligned_in_smp; \ +} + +int bpf_struct_ops_desc_init(struct bpf_struct_ops_desc *st_ops_desc, + struct btf *btf, + struct bpf_verifier_log *log); + #endif /* _LINUX_BPF_H */ diff --git a/include/linux/btf.h b/include/linux/btf.h index e2f4b85cf82a..cabab3db5216 100644 --- a/include/linux/btf.h +++ b/include/linux/btf.h @@ -12,6 +12,8 @@ #include #define BTF_TYPE_EMIT(type) ((void)(type *)0) +#define BTF_STRUCT_OPS_TYPE_EMIT(type) \ + ((void)(struct bpf_struct_ops_##type *)0) #define BTF_TYPE_EMIT_ENUM(enum_val) ((void)enum_val) /* These need to be macros, as the expressions are used in assembler input */ diff --git a/kernel/bpf/bpf_struct_ops.c b/kernel/bpf/bpf_struct_ops.c index a3d9ffbdba00..fd26716fa0f9 100644 --- a/kernel/bpf/bpf_struct_ops.c +++ b/kernel/bpf/bpf_struct_ops.c @@ -61,35 +61,6 @@ static DEFINE_MUTEX(update_mutex); #define VALUE_PREFIX "bpf_struct_ops_" #define VALUE_PREFIX_LEN (sizeof(VALUE_PREFIX) - 1) -/* bpf_struct_ops_##_name (e.g. bpf_struct_ops_tcp_congestion_ops) is - * the map's value exposed to the userspace and its btf-type-id is - * stored at the map->btf_vmlinux_value_type_id. - * - */ -#define BPF_STRUCT_OPS_TYPE(_name) \ -extern struct bpf_struct_ops bpf_##_name; \ - \ -struct bpf_struct_ops_##_name { \ - struct bpf_struct_ops_common_value common; \ - struct _name data ____cacheline_aligned_in_smp; \ -}; -#include "bpf_struct_ops_types.h" -#undef BPF_STRUCT_OPS_TYPE - -enum { -#define BPF_STRUCT_OPS_TYPE(_name) BPF_STRUCT_OPS_TYPE_##_name, -#include "bpf_struct_ops_types.h" -#undef BPF_STRUCT_OPS_TYPE - __NR_BPF_STRUCT_OPS_TYPE, -}; - -static struct bpf_struct_ops_desc bpf_struct_ops[] = { -#define BPF_STRUCT_OPS_TYPE(_name) \ - [BPF_STRUCT_OPS_TYPE_##_name] = { .st_ops = &bpf_##_name }, -#include "bpf_struct_ops_types.h" -#undef BPF_STRUCT_OPS_TYPE -}; - const struct bpf_verifier_ops bpf_struct_ops_verifier_ops = { }; @@ -144,9 +115,9 @@ static bool is_valid_value_type(struct btf *btf, s32 value_id, return true; } -static void bpf_struct_ops_desc_init(struct bpf_struct_ops_desc *st_ops_desc, - struct btf *btf, - struct bpf_verifier_log *log) +int bpf_struct_ops_desc_init(struct bpf_struct_ops_desc *st_ops_desc, + struct btf *btf, + struct bpf_verifier_log *log) { struct bpf_struct_ops *st_ops = st_ops_desc->st_ops; const struct btf_member *member; @@ -160,7 +131,7 @@ static void bpf_struct_ops_desc_init(struct bpf_struct_ops_desc *st_ops_desc, sizeof(value_name)) { pr_warn("struct_ops name %s is too long\n", st_ops->name); - return; + return -EINVAL; } sprintf(value_name, "%s%s", VALUE_PREFIX, st_ops->name); @@ -169,13 +140,13 @@ static void bpf_struct_ops_desc_init(struct bpf_struct_ops_desc *st_ops_desc, if (type_id < 0) { pr_warn("Cannot find struct %s in %s\n", st_ops->name, btf_get_name(btf)); - return; + return -EINVAL; } t = btf_type_by_id(btf, type_id); if (btf_type_vlen(t) > BPF_STRUCT_OPS_MAX_NR_MEMBERS) { pr_warn("Cannot support #%u members in struct %s\n", btf_type_vlen(t), st_ops->name); - return; + return -EINVAL; } value_id = btf_find_by_name_kind(btf, value_name, @@ -183,10 +154,10 @@ static void bpf_struct_ops_desc_init(struct bpf_struct_ops_desc *st_ops_desc, if (value_id < 0) { pr_warn("Cannot find struct %s in %s\n", value_name, btf_get_name(btf)); - return; + return -EINVAL; } if (!is_valid_value_type(btf, value_id, t, value_name)) - return; + return -EINVAL; for_each_member(i, t, member) { const struct btf_type *func_proto; @@ -195,13 +166,13 @@ static void bpf_struct_ops_desc_init(struct bpf_struct_ops_desc *st_ops_desc, if (!*mname) { pr_warn("anon member in struct %s is not supported\n", st_ops->name); - break; + return -EOPNOTSUPP; } if (__btf_member_bitfield_size(t, member)) { pr_warn("bit field member %s in struct %s is not supported\n", mname, st_ops->name); - break; + return -EOPNOTSUPP; } func_proto = btf_type_resolve_func_ptr(btf, @@ -213,7 +184,7 @@ static void bpf_struct_ops_desc_init(struct bpf_struct_ops_desc *st_ops_desc, &st_ops->func_models[i])) { pr_warn("Error in parsing func ptr %s in struct %s\n", mname, st_ops->name); - break; + return -EINVAL; } } @@ -221,6 +192,7 @@ static void bpf_struct_ops_desc_init(struct bpf_struct_ops_desc *st_ops_desc, if (st_ops->init(btf)) { pr_warn("Error in init bpf_struct_ops %s\n", st_ops->name); + return -EINVAL; } else { st_ops_desc->type_id = type_id; st_ops_desc->type = t; @@ -229,35 +201,24 @@ static void bpf_struct_ops_desc_init(struct bpf_struct_ops_desc *st_ops_desc, value_id); } } -} -void bpf_struct_ops_init(struct btf *btf, struct bpf_verifier_log *log) -{ - struct bpf_struct_ops_desc *st_ops_desc; - u32 i; - - /* Ensure BTF type is emitted for "struct bpf_struct_ops_##_name" */ -#define BPF_STRUCT_OPS_TYPE(_name) BTF_TYPE_EMIT(struct bpf_struct_ops_##_name); -#include "bpf_struct_ops_types.h" -#undef BPF_STRUCT_OPS_TYPE - - for (i = 0; i < ARRAY_SIZE(bpf_struct_ops); i++) { - st_ops_desc = &bpf_struct_ops[i]; - bpf_struct_ops_desc_init(st_ops_desc, btf, log); - } + return 0; } static const struct bpf_struct_ops_desc * bpf_struct_ops_find_value(struct btf *btf, u32 value_id) { + const struct bpf_struct_ops_desc *st_ops_list; unsigned int i; + u32 cnt = 0; - if (!value_id || !btf) + if (!value_id) return NULL; - for (i = 0; i < ARRAY_SIZE(bpf_struct_ops); i++) { - if (bpf_struct_ops[i].value_id == value_id) - return &bpf_struct_ops[i]; + st_ops_list = btf_get_struct_ops(btf, &cnt); + for (i = 0; i < cnt; i++) { + if (st_ops_list[i].value_id == value_id) + return &st_ops_list[i]; } return NULL; @@ -266,14 +227,17 @@ bpf_struct_ops_find_value(struct btf *btf, u32 value_id) const struct bpf_struct_ops_desc * bpf_struct_ops_find(struct btf *btf, u32 type_id) { + const struct bpf_struct_ops_desc *st_ops_list; unsigned int i; + u32 cnt; - if (!type_id || !btf) + if (!type_id) return NULL; - for (i = 0; i < ARRAY_SIZE(bpf_struct_ops); i++) { - if (bpf_struct_ops[i].type_id == type_id) - return &bpf_struct_ops[i]; + st_ops_list = btf_get_struct_ops(btf, &cnt); + for (i = 0; i < cnt; i++) { + if (st_ops_list[i].type_id == type_id) + return &st_ops_list[i]; } return NULL; diff --git a/kernel/bpf/bpf_struct_ops_types.h b/kernel/bpf/bpf_struct_ops_types.h deleted file mode 100644 index 5678a9ddf817..000000000000 --- a/kernel/bpf/bpf_struct_ops_types.h +++ /dev/null @@ -1,12 +0,0 @@ -/* SPDX-License-Identifier: GPL-2.0 */ -/* internal file - do not include directly */ - -#ifdef CONFIG_BPF_JIT -#ifdef CONFIG_NET -BPF_STRUCT_OPS_TYPE(bpf_dummy_ops) -#endif -#ifdef CONFIG_INET -#include -BPF_STRUCT_OPS_TYPE(tcp_congestion_ops) -#endif -#endif diff --git a/kernel/bpf/btf.c b/kernel/bpf/btf.c index edbe3cbf2dcc..5545dee3ff54 100644 --- a/kernel/bpf/btf.c +++ b/kernel/bpf/btf.c @@ -19,6 +19,7 @@ #include #include #include +#include #include #include #include @@ -5792,8 +5793,6 @@ struct btf *btf_parse_vmlinux(void) /* btf_parse_vmlinux() runs under bpf_verifier_lock */ bpf_ctx_convert.t = btf_type_by_id(btf, bpf_ctx_convert_btf_id[0]); - bpf_struct_ops_init(btf, log); - refcount_set(&btf->refcnt, 1); err = btf_alloc_id(btf); @@ -8621,11 +8620,21 @@ bool btf_type_ids_nocast_alias(struct bpf_verifier_log *log, return !strncmp(reg_name, arg_name, cmp_len); } +#ifndef CONFIG_BPF_JIT +int bpf_struct_ops_desc_init(struct bpf_struct_ops_desc *st_ops_desc, + struct btf *btf, + struct bpf_verifier_log *log) +{ + return -ENOTSUPP; +} +#endif /* CONFIG_BPF_JIT */ + static int -btf_add_struct_ops(struct btf *btf, struct bpf_struct_ops *st_ops) +btf_add_struct_ops(struct btf *btf, struct bpf_struct_ops *st_ops, + struct bpf_verifier_log *log) { struct btf_struct_ops_tab *tab, *new_tab; - int i; + int i, err; if (!btf) return -ENOENT; @@ -8662,6 +8671,10 @@ btf_add_struct_ops(struct btf *btf, struct bpf_struct_ops *st_ops) tab->ops[btf->struct_ops_tab->cnt].st_ops = st_ops; + err = bpf_struct_ops_desc_init(&tab->ops[btf->struct_ops_tab->cnt], btf, log); + if (err) + return err; + btf->struct_ops_tab->cnt++; return 0; @@ -8677,3 +8690,31 @@ const struct bpf_struct_ops_desc *btf_get_struct_ops(struct btf *btf, u32 *ret_c *ret_cnt = btf->struct_ops_tab->cnt; return (const struct bpf_struct_ops_desc *)btf->struct_ops_tab->ops; } + +int register_bpf_struct_ops(struct bpf_struct_ops *st_ops) +{ + struct bpf_verifier_log *log; + struct btf *btf; + int err = 0; + + btf = btf_get_module_btf(st_ops->owner); + if (!btf) + return -EINVAL; + + log = kzalloc(sizeof(*log), GFP_KERNEL | __GFP_NOWARN); + if (!log) { + err = -ENOMEM; + goto errout; + } + + log->level = BPF_LOG_KERNEL; + + err = btf_add_struct_ops(btf, st_ops, log); + +errout: + kfree(log); + btf_put(btf); + + return err; +} +EXPORT_SYMBOL_GPL(register_bpf_struct_ops); diff --git a/net/bpf/bpf_dummy_struct_ops.c b/net/bpf/bpf_dummy_struct_ops.c index bd753dbccaf6..2bb2625ffbbf 100644 --- a/net/bpf/bpf_dummy_struct_ops.c +++ b/net/bpf/bpf_dummy_struct_ops.c @@ -7,7 +7,7 @@ #include #include -extern struct bpf_struct_ops bpf_bpf_dummy_ops; +static struct bpf_struct_ops bpf_bpf_dummy_ops; /* A common type for test_N with return value in bpf_dummy_ops */ typedef int (*dummy_ops_test_ret_fn)(struct bpf_dummy_ops_state *state, ...); @@ -222,11 +222,13 @@ static int bpf_dummy_reg(void *kdata) return -EOPNOTSUPP; } +DEFINE_STRUCT_OPS_VALUE_TYPE(bpf_dummy_ops); + static void bpf_dummy_unreg(void *kdata) { } -struct bpf_struct_ops bpf_bpf_dummy_ops = { +static struct bpf_struct_ops bpf_bpf_dummy_ops = { .verifier_ops = &bpf_dummy_verifier_ops, .init = bpf_dummy_init, .check_member = bpf_dummy_ops_check_member, @@ -234,4 +236,11 @@ struct bpf_struct_ops bpf_bpf_dummy_ops = { .reg = bpf_dummy_reg, .unreg = bpf_dummy_unreg, .name = "bpf_dummy_ops", + .owner = THIS_MODULE, }; + +static int __init bpf_dummy_struct_ops_init(void) +{ + return REGISTER_BPF_STRUCT_OPS(&bpf_bpf_dummy_ops, bpf_dummy_ops); +} +late_initcall(bpf_dummy_struct_ops_init); diff --git a/net/ipv4/bpf_tcp_ca.c b/net/ipv4/bpf_tcp_ca.c index 5bb56c9ad4e5..6d2728dc600e 100644 --- a/net/ipv4/bpf_tcp_ca.c +++ b/net/ipv4/bpf_tcp_ca.c @@ -12,7 +12,7 @@ #include /* "extern" is to avoid sparse warning. It is only used in bpf_struct_ops.c. */ -extern struct bpf_struct_ops bpf_tcp_congestion_ops; +static struct bpf_struct_ops bpf_tcp_congestion_ops; static u32 unsupported_ops[] = { offsetof(struct tcp_congestion_ops, get_info), @@ -277,7 +277,9 @@ static int bpf_tcp_ca_validate(void *kdata) return tcp_validate_congestion_control(kdata); } -struct bpf_struct_ops bpf_tcp_congestion_ops = { +DEFINE_STRUCT_OPS_VALUE_TYPE(tcp_congestion_ops); + +static struct bpf_struct_ops bpf_tcp_congestion_ops = { .verifier_ops = &bpf_tcp_ca_verifier_ops, .reg = bpf_tcp_ca_reg, .unreg = bpf_tcp_ca_unreg, @@ -287,10 +289,16 @@ struct bpf_struct_ops bpf_tcp_congestion_ops = { .init = bpf_tcp_ca_init, .validate = bpf_tcp_ca_validate, .name = "tcp_congestion_ops", + .owner = THIS_MODULE, }; static int __init bpf_tcp_ca_kfunc_init(void) { - return register_btf_kfunc_id_set(BPF_PROG_TYPE_STRUCT_OPS, &bpf_tcp_ca_kfunc_set); + int ret; + + ret = register_btf_kfunc_id_set(BPF_PROG_TYPE_STRUCT_OPS, &bpf_tcp_ca_kfunc_set); + ret = ret ?: REGISTER_BPF_STRUCT_OPS(&bpf_tcp_congestion_ops, tcp_congestion_ops); + + return ret; } late_initcall(bpf_tcp_ca_kfunc_init); From patchwork Sat Dec 9 00:27:06 2023 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Kui-Feng Lee X-Patchwork-Id: 13485913 X-Patchwork-Delegate: bpf@iogearbox.net Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=gmail.com header.i=@gmail.com header.b="Q6iOsWS8" Received: from mail-yw1-x1130.google.com (mail-yw1-x1130.google.com [IPv6:2607:f8b0:4864:20::1130]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id C88A11734 for ; Fri, 8 Dec 2023 16:27:27 -0800 (PST) Received: by mail-yw1-x1130.google.com with SMTP id 00721157ae682-5df49931b4eso2752947b3.0 for ; Fri, 08 Dec 2023 16:27:27 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20230601; t=1702081646; x=1702686446; darn=vger.kernel.org; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:from:to:cc:subject:date :message-id:reply-to; bh=dGhBORSemw2luLKPGGp6OlMXvBU3ZB32r1Pge1DFuOc=; b=Q6iOsWS8j9utscCz3p07nPghGo6Exg8x/uwlkxZ5pFOO5v46uTWi6n9uI4LDJGvVNJ 0vNB1ZRBvPxktdwHWb0rTKP1g3u1l7pmyTxXAnPxKzm98guhLYKhkD42m2QbhTLQ7VWT KA6hkRI/SS/y9ytggXX12YHF4xYIPjkIRTm42+kx3QA+G4ggKtt7hiTbo+4Tr8iWINfz 0roISBRgNeGABbMhL5goar5iQB0LTZdMshmV3B25aAWJwDdUgQA3gXVuHMMgBZl5lPBq fnQmpFCsIKWHAvOhj0p+gchGgR3ieCRG76EWDLXUhHTsETNgvb7Z476jivsXIFESM04j qDjg== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1702081646; x=1702686446; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:x-gm-message-state:from:to:cc :subject:date:message-id:reply-to; bh=dGhBORSemw2luLKPGGp6OlMXvBU3ZB32r1Pge1DFuOc=; b=AaEaW/b/v+1JRdAXARkC1nkVr9Xh7xSynoHwMgn5mCBp+qsh+op0nCSD4FhSdpWy/A vizzMY8r0seoxwUGkobaz38paZLNAr9UdHKaWEudNkUTXHtnyUVpdtCUAvE/vbVSFAXJ GVaYKHmEsAGOj1nHpjGEGkeEuntw2DsORQb+vkRiH5YAlUV0FDXgj3jZEu0OsM+m/8YX ryJPbrXUtPGweS/gu7RYxI1JlxzOWs9WbRWuc9wiskBSK1nut3VAtEBzVr8bKPp6REWD CBvLdtwpyvc1IXoyegd1sXNuW64nB2DktFC9FRFyVPyJl7TB7bRO6Msai5HOUOJTGNmY axmg== X-Gm-Message-State: AOJu0Yxm+yhjDVHiVPDM+FWHvatx4hBxUrgwmA6NydVp0vl/8vUKDQPl ET3ylrJgNXnP35CinitBolZ2gdvgzrSDEQ== X-Google-Smtp-Source: AGHT+IH44XWmELOPxPJvWU4ZGItF714I3KMPqXVKSsCcKZ+6BWuc6v3KLJkrNM8YK91rNmBsZW+NCw== X-Received: by 2002:a81:87c4:0:b0:5d7:1940:b396 with SMTP id x187-20020a8187c4000000b005d71940b396mr881169ywf.98.1702081646513; Fri, 08 Dec 2023 16:27:26 -0800 (PST) Received: from kickker.attlocal.net ([2600:1700:6cf8:1240:65fe:fe26:c15:a05c]) by smtp.gmail.com with ESMTPSA id v4-20020a818504000000b005d9729068f5sm1057450ywf.42.2023.12.08.16.27.25 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Fri, 08 Dec 2023 16:27:26 -0800 (PST) From: thinker.li@gmail.com To: bpf@vger.kernel.org, ast@kernel.org, martin.lau@linux.dev, song@kernel.org, kernel-team@meta.com, andrii@kernel.org, drosen@google.com Cc: sinquersw@gmail.com, kuifeng@meta.com, Kui-Feng Lee Subject: [PATCH bpf-next v13 11/14] libbpf: Find correct module BTFs for struct_ops maps and progs. Date: Fri, 8 Dec 2023 16:27:06 -0800 Message-Id: <20231209002709.535966-12-thinker.li@gmail.com> X-Mailer: git-send-email 2.34.1 In-Reply-To: <20231209002709.535966-1-thinker.li@gmail.com> References: <20231209002709.535966-1-thinker.li@gmail.com> Precedence: bulk X-Mailing-List: bpf@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 X-Patchwork-Delegate: bpf@iogearbox.net From: Kui-Feng Lee Locate the module BTFs for struct_ops maps and progs and pass them to the kernel. This ensures that the kernel correctly resolves type IDs from the appropriate module BTFs. For the map of a struct_ops object, the FD of the module BTF is set to bpf_map to keep a reference to the module BTF. The FD is passed to the kernel as value_type_btf_obj_fd when the struct_ops object is loaded. For a bpf_struct_ops prog, attach_btf_obj_fd of bpf_prog is the FD of a module BTF in the kernel. Signed-off-by: Kui-Feng Lee Acked-by: Andrii Nakryiko --- tools/lib/bpf/bpf.c | 4 +++- tools/lib/bpf/bpf.h | 5 +++-- tools/lib/bpf/libbpf.c | 38 ++++++++++++++++++++++++++++---------- 3 files changed, 34 insertions(+), 13 deletions(-) diff --git a/tools/lib/bpf/bpf.c b/tools/lib/bpf/bpf.c index f4e1da3c6d5f..14ed20b73b86 100644 --- a/tools/lib/bpf/bpf.c +++ b/tools/lib/bpf/bpf.c @@ -169,7 +169,8 @@ int bpf_map_create(enum bpf_map_type map_type, __u32 max_entries, const struct bpf_map_create_opts *opts) { - const size_t attr_sz = offsetofend(union bpf_attr, map_token_fd); + const size_t attr_sz = offsetofend(union bpf_attr, + value_type_btf_obj_fd); union bpf_attr attr; int fd; @@ -191,6 +192,7 @@ int bpf_map_create(enum bpf_map_type map_type, attr.btf_key_type_id = OPTS_GET(opts, btf_key_type_id, 0); attr.btf_value_type_id = OPTS_GET(opts, btf_value_type_id, 0); attr.btf_vmlinux_value_type_id = OPTS_GET(opts, btf_vmlinux_value_type_id, 0); + attr.value_type_btf_obj_fd = OPTS_GET(opts, value_type_btf_obj_fd, 0); attr.inner_map_fd = OPTS_GET(opts, inner_map_fd, 0); attr.map_flags = OPTS_GET(opts, map_flags, 0); diff --git a/tools/lib/bpf/bpf.h b/tools/lib/bpf/bpf.h index 991b86bfe7e4..1cecfde0c732 100644 --- a/tools/lib/bpf/bpf.h +++ b/tools/lib/bpf/bpf.h @@ -53,9 +53,10 @@ struct bpf_map_create_opts { __u32 map_ifindex; __u32 token_fd; - size_t :0; + __u32 value_type_btf_obj_fd; + size_t:0; }; -#define bpf_map_create_opts__last_field token_fd +#define bpf_map_create_opts__last_field value_type_btf_obj_fd LIBBPF_API int bpf_map_create(enum bpf_map_type map_type, const char *map_name, diff --git a/tools/lib/bpf/libbpf.c b/tools/lib/bpf/libbpf.c index ac54ebc0629f..d6709ebd1d8a 100644 --- a/tools/lib/bpf/libbpf.c +++ b/tools/lib/bpf/libbpf.c @@ -527,6 +527,7 @@ struct bpf_map { struct bpf_map_def def; __u32 numa_node; __u32 btf_var_idx; + int mod_btf_fd; __u32 btf_key_type_id; __u32 btf_value_type_id; __u32 btf_vmlinux_value_type_id; @@ -930,22 +931,29 @@ find_member_by_name(const struct btf *btf, const struct btf_type *t, return NULL; } +static int find_ksym_btf_id(struct bpf_object *obj, const char *ksym_name, + __u16 kind, struct btf **res_btf, + struct module_btf **res_mod_btf); + #define STRUCT_OPS_VALUE_PREFIX "bpf_struct_ops_" static int find_btf_by_prefix_kind(const struct btf *btf, const char *prefix, const char *name, __u32 kind); static int -find_struct_ops_kern_types(const struct btf *btf, const char *tname, +find_struct_ops_kern_types(struct bpf_object *obj, const char *tname, + struct module_btf **mod_btf, const struct btf_type **type, __u32 *type_id, const struct btf_type **vtype, __u32 *vtype_id, const struct btf_member **data_member) { const struct btf_type *kern_type, *kern_vtype; const struct btf_member *kern_data_member; + struct btf *btf; __s32 kern_vtype_id, kern_type_id; __u32 i; - kern_type_id = btf__find_by_name_kind(btf, tname, BTF_KIND_STRUCT); + kern_type_id = find_ksym_btf_id(obj, tname, BTF_KIND_STRUCT, + &btf, mod_btf); if (kern_type_id < 0) { pr_warn("struct_ops init_kern: struct %s is not found in kernel BTF\n", tname); @@ -999,14 +1007,16 @@ static bool bpf_map__is_struct_ops(const struct bpf_map *map) } /* Init the map's fields that depend on kern_btf */ -static int bpf_map__init_kern_struct_ops(struct bpf_map *map, - const struct btf *btf, - const struct btf *kern_btf) +static int bpf_map__init_kern_struct_ops(struct bpf_map *map) { const struct btf_member *member, *kern_member, *kern_data_member; const struct btf_type *type, *kern_type, *kern_vtype; __u32 i, kern_type_id, kern_vtype_id, kern_data_off; + struct bpf_object *obj = map->obj; + const struct btf *btf = obj->btf; struct bpf_struct_ops *st_ops; + const struct btf *kern_btf; + struct module_btf *mod_btf; void *data, *kern_data; const char *tname; int err; @@ -1014,16 +1024,19 @@ static int bpf_map__init_kern_struct_ops(struct bpf_map *map, st_ops = map->st_ops; type = st_ops->type; tname = st_ops->tname; - err = find_struct_ops_kern_types(kern_btf, tname, + err = find_struct_ops_kern_types(obj, tname, &mod_btf, &kern_type, &kern_type_id, &kern_vtype, &kern_vtype_id, &kern_data_member); if (err) return err; + kern_btf = mod_btf ? mod_btf->btf : obj->btf_vmlinux; + pr_debug("struct_ops init_kern %s: type_id:%u kern_type_id:%u kern_vtype_id:%u\n", map->name, st_ops->type_id, kern_type_id, kern_vtype_id); + map->mod_btf_fd = mod_btf ? mod_btf->fd : 0; map->def.value_size = kern_vtype->size; map->btf_vmlinux_value_type_id = kern_vtype_id; @@ -1099,6 +1112,8 @@ static int bpf_map__init_kern_struct_ops(struct bpf_map *map, return -ENOTSUP; } + if (mod_btf) + prog->attach_btf_obj_fd = mod_btf->fd; prog->attach_btf_id = kern_type_id; prog->expected_attach_type = kern_member_idx; @@ -1141,8 +1156,7 @@ static int bpf_object__init_kern_struct_ops_maps(struct bpf_object *obj) if (!bpf_map__is_struct_ops(map)) continue; - err = bpf_map__init_kern_struct_ops(map, obj->btf, - obj->btf_vmlinux); + err = bpf_map__init_kern_struct_ops(map); if (err) return err; } @@ -5212,8 +5226,10 @@ static int bpf_object__create_map(struct bpf_object *obj, struct bpf_map *map, b create_attr.numa_node = map->numa_node; create_attr.map_extra = map->map_extra; - if (bpf_map__is_struct_ops(map)) + if (bpf_map__is_struct_ops(map)) { create_attr.btf_vmlinux_value_type_id = map->btf_vmlinux_value_type_id; + create_attr.value_type_btf_obj_fd = map->mod_btf_fd; + } if (obj->btf && btf__fd(obj->btf) >= 0) { create_attr.btf_fd = btf__fd(obj->btf); @@ -9557,7 +9573,9 @@ static int libbpf_find_attach_btf_id(struct bpf_program *prog, const char *attac *btf_obj_fd = 0; *btf_type_id = 1; } else { - err = find_kernel_btf_id(prog->obj, attach_name, attach_type, btf_obj_fd, btf_type_id); + err = find_kernel_btf_id(prog->obj, attach_name, + attach_type, btf_obj_fd, + btf_type_id); } if (err) { pr_warn("prog '%s': failed to find kernel BTF type ID of '%s': %d\n", From patchwork Sat Dec 9 00:27:07 2023 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Kui-Feng Lee X-Patchwork-Id: 13485912 X-Patchwork-Delegate: bpf@iogearbox.net Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=gmail.com header.i=@gmail.com header.b="Nw0z1WU8" Received: from mail-yw1-x1135.google.com (mail-yw1-x1135.google.com [IPv6:2607:f8b0:4864:20::1135]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id 01281173F for ; Fri, 8 Dec 2023 16:27:29 -0800 (PST) Received: by mail-yw1-x1135.google.com with SMTP id 00721157ae682-5d852ac9bb2so25588817b3.2 for ; Fri, 08 Dec 2023 16:27:28 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20230601; t=1702081648; x=1702686448; darn=vger.kernel.org; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:from:to:cc:subject:date :message-id:reply-to; bh=4sjjYs0SoUIMGBIggG2RmbInOgfFHHKp5K529V1i6nE=; b=Nw0z1WU8SOvX7e1oZpBGoOEUVv5AOaZXP8Haj2/Jt6lr2YZoXbXHkYPAXKToh1M3r+ MmRdx6AND0A98ZA3Ix3e30/daH6iAjB8XjOuGPXM9FdaKHD7094DnqxnyuigS285pQtT E3YR1UEZHAolf6SmGbsPUbceH6U994y7hVry289Qvj4EwI3ypnD4EpASnmOLx0Fcw3+f ozhHndYqSzGnZZQ/MxAXLQrhF80hQF2yscek0WWHIDr5Eu2zW8s86sX1FFpJkXuEUBpE Ta92aF2yAbE5MVN0IXt3A29Leeofk/ky/0X++YR/NXTOTZuCY867c+s+R8nC/by55uX3 POiw== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1702081648; x=1702686448; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:x-gm-message-state:from:to:cc :subject:date:message-id:reply-to; bh=4sjjYs0SoUIMGBIggG2RmbInOgfFHHKp5K529V1i6nE=; b=sCGXZWDAbmsLr3pTZFogxZBSynVsi2Zx1y9qjTmNaEdA4f4VWbhEd/nh5ExK/u83p9 +QXBaQqeEBVfmUWH0ZNWqMf63zS0Px9CuQ9zpGvB08akaleLMgXlRpEBLpBEMH8AfAVQ fe7C0GvJ/5cN1hRowoxurRlbpsZHwVfv+rIHSuxoQNUcQo5c0nIaHM3k4ZWUUwaF4iTO hRoEP1pxVGqz2RY16rD3uBtd1KtH5PM6928hlti7UkbUa6WxAfVEDWJmk/OQ8PLiVXyz NI3AAog9wN7OS6hXYYcNP1CpKOg8UA5QYouBcpyf84qmSAShXHpYXpTmtb2D4aIM0QL/ ZoNQ== X-Gm-Message-State: AOJu0Yxk7eGBgekcyJ0zep6MO7iUARGVbCIPohdTdT1qDIO5JvRHItzQ 1IPSI9SNT4onQoWv6SkruYReqwffi7l12A== X-Google-Smtp-Source: AGHT+IGLR5e4xJAXyXo6WgR+bBmQi+NB/vxaOVPka11b6UQkVSFkWNcxCdrXYMXYoPA7GBO0N2XbGA== X-Received: by 2002:a0d:d007:0:b0:5d7:1940:53d9 with SMTP id s7-20020a0dd007000000b005d7194053d9mr871246ywd.81.1702081647963; Fri, 08 Dec 2023 16:27:27 -0800 (PST) Received: from kickker.attlocal.net ([2600:1700:6cf8:1240:65fe:fe26:c15:a05c]) by smtp.gmail.com with ESMTPSA id v4-20020a818504000000b005d9729068f5sm1057450ywf.42.2023.12.08.16.27.26 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Fri, 08 Dec 2023 16:27:27 -0800 (PST) From: thinker.li@gmail.com To: bpf@vger.kernel.org, ast@kernel.org, martin.lau@linux.dev, song@kernel.org, kernel-team@meta.com, andrii@kernel.org, drosen@google.com Cc: sinquersw@gmail.com, kuifeng@meta.com, Kui-Feng Lee Subject: [PATCH bpf-next v13 12/14] bpf: export btf_ctx_access to modules. Date: Fri, 8 Dec 2023 16:27:07 -0800 Message-Id: <20231209002709.535966-13-thinker.li@gmail.com> X-Mailer: git-send-email 2.34.1 In-Reply-To: <20231209002709.535966-1-thinker.li@gmail.com> References: <20231209002709.535966-1-thinker.li@gmail.com> Precedence: bulk X-Mailing-List: bpf@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 X-Patchwork-Delegate: bpf@iogearbox.net From: Kui-Feng Lee The module requires the use of btf_ctx_access() to invoke bpf_tracing_btf_ctx_access() from a module. This function is valuable for implementing validation functions that ensure proper access to ctx. Signed-off-by: Kui-Feng Lee --- kernel/bpf/btf.c | 1 + 1 file changed, 1 insertion(+) diff --git a/kernel/bpf/btf.c b/kernel/bpf/btf.c index 5545dee3ff54..d9cdf41e8f34 100644 --- a/kernel/bpf/btf.c +++ b/kernel/bpf/btf.c @@ -6142,6 +6142,7 @@ bool btf_ctx_access(int off, int size, enum bpf_access_type type, __btf_name_by_offset(btf, t->name_off)); return true; } +EXPORT_SYMBOL_GPL(btf_ctx_access); enum bpf_struct_walk_result { /* < 0 error */ From patchwork Sat Dec 9 00:27:08 2023 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Kui-Feng Lee X-Patchwork-Id: 13485914 X-Patchwork-Delegate: bpf@iogearbox.net Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=gmail.com header.i=@gmail.com header.b="iRwy4JIC" Received: from mail-yw1-x1129.google.com (mail-yw1-x1129.google.com [IPv6:2607:f8b0:4864:20::1129]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id 84D89171F for ; Fri, 8 Dec 2023 16:27:30 -0800 (PST) Received: by mail-yw1-x1129.google.com with SMTP id 00721157ae682-5d852ac9bb2so25589027b3.2 for ; Fri, 08 Dec 2023 16:27:30 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20230601; t=1702081649; x=1702686449; darn=vger.kernel.org; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:from:to:cc:subject:date :message-id:reply-to; bh=0acVKzFK0l5xHCXVGmgKp6gPcv7+cgFgaMCBNwj/ibY=; b=iRwy4JIC8LizVHwRRyuyswoMk9+YZ1zLDlzEnP0J6jVMELWFw1u95bn59ROaW1hqJl dvaJfiptlnzGXX7fLn9JKV0vVhU48NGeb1aNIpYnXjBgqQ/fCntUglMTgfIhzPPb8McH Z7HqajmkA9fl80wi8MefwYDNymcn39yiHHairovLnXzcdcazzNxrSFFBgaWHs750iqd8 CeEQ3P7KTpmPATNGba7awrNb/E1yfwvH/V+j+P4ImfaJfN2YA1rxY0hcFHednyu8+pxQ H2X7itsuNkY52Ryrk6JKgb/un5DcSP916zKCp6Q4G8l5WyJBXC1ST5hlv3LF3rPDtt5W 76sA== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1702081649; x=1702686449; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:x-gm-message-state:from:to:cc :subject:date:message-id:reply-to; bh=0acVKzFK0l5xHCXVGmgKp6gPcv7+cgFgaMCBNwj/ibY=; b=GnmaYtQxFnAT6pIjvjcYzx9LwF0aD9skobCMc2wclIVb8GbRfCdLDUel4BLv9z/Dtf HXbZHWL9Y9pIKYvQ9gOvY51MQiDnJmC7ZIVXq4oAiF9RwRKIE8XY1BGvWoJ3HYPCCIF4 P9ojYe8CRTKuGNnebIifZFmYFwSZJwcJwVHFz/I3Jyr17W1g41tYglGQ2roNnnldGQK9 ytDs7njfauPAQKIHNRci1C02WvEmid/DthVYnA9oqE2+8TVNpINv78bf+BvxCj+6aFcC 0NIct3y/PxqI/G4QzdUqKykAmjLAIk3aS+cryuIFHZH4iYNB+9TTBd5svFhZTCX7nRfM R1LA== X-Gm-Message-State: AOJu0YyO3BusqHuM0AyqFEK38cMexCiV7M3XnwhK2cjwio9fjMbeuQhJ R8GOYxmVhqXdkDpXehiU7+x683x1/3quCg== X-Google-Smtp-Source: AGHT+IEe+zAXYpIk4GONxK091xBrBsIlulNgCsV5cwsfZryIpKBRTx8ABFwUukRR299B13KiO9QdYA== X-Received: by 2002:a0d:cbd2:0:b0:5d4:1fbf:d08d with SMTP id n201-20020a0dcbd2000000b005d41fbfd08dmr756435ywd.14.1702081649437; Fri, 08 Dec 2023 16:27:29 -0800 (PST) Received: from kickker.attlocal.net ([2600:1700:6cf8:1240:65fe:fe26:c15:a05c]) by smtp.gmail.com with ESMTPSA id v4-20020a818504000000b005d9729068f5sm1057450ywf.42.2023.12.08.16.27.28 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Fri, 08 Dec 2023 16:27:28 -0800 (PST) From: thinker.li@gmail.com To: bpf@vger.kernel.org, ast@kernel.org, martin.lau@linux.dev, song@kernel.org, kernel-team@meta.com, andrii@kernel.org, drosen@google.com Cc: sinquersw@gmail.com, kuifeng@meta.com, Kui-Feng Lee Subject: [PATCH bpf-next v13 13/14] selftests/bpf: test case for register_bpf_struct_ops(). Date: Fri, 8 Dec 2023 16:27:08 -0800 Message-Id: <20231209002709.535966-14-thinker.li@gmail.com> X-Mailer: git-send-email 2.34.1 In-Reply-To: <20231209002709.535966-1-thinker.li@gmail.com> References: <20231209002709.535966-1-thinker.li@gmail.com> Precedence: bulk X-Mailing-List: bpf@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 X-Patchwork-Delegate: bpf@iogearbox.net From: Kui-Feng Lee Create a new struct_ops type called bpf_testmod_ops within the bpf_testmod module. When a struct_ops object is registered, the bpf_testmod module will invoke test_2 from the module. Signed-off-by: Kui-Feng Lee --- .../selftests/bpf/bpf_testmod/bpf_testmod.c | 52 +++++++++++ .../selftests/bpf/bpf_testmod/bpf_testmod.h | 5 + .../bpf/prog_tests/test_struct_ops_module.c | 92 +++++++++++++++++++ .../selftests/bpf/progs/struct_ops_module.c | 30 ++++++ .../selftests/bpf/progs/testmod_unload.c | 25 +++++ 5 files changed, 204 insertions(+) create mode 100644 tools/testing/selftests/bpf/prog_tests/test_struct_ops_module.c create mode 100644 tools/testing/selftests/bpf/progs/struct_ops_module.c create mode 100644 tools/testing/selftests/bpf/progs/testmod_unload.c diff --git a/tools/testing/selftests/bpf/bpf_testmod/bpf_testmod.c b/tools/testing/selftests/bpf/bpf_testmod/bpf_testmod.c index 91907b321f91..804a67bbb479 100644 --- a/tools/testing/selftests/bpf/bpf_testmod/bpf_testmod.c +++ b/tools/testing/selftests/bpf/bpf_testmod/bpf_testmod.c @@ -1,5 +1,6 @@ // SPDX-License-Identifier: GPL-2.0 /* Copyright (c) 2020 Facebook */ +#include #include #include #include @@ -520,11 +521,61 @@ BTF_ID_FLAGS(func, bpf_kfunc_call_test_static_unused_arg) BTF_ID_FLAGS(func, bpf_kfunc_call_test_offset) BTF_SET8_END(bpf_testmod_check_kfunc_ids) +DEFINE_STRUCT_OPS_VALUE_TYPE(bpf_testmod_ops); + +static int bpf_testmod_ops_init(struct btf *btf) +{ + return 0; +} + +static bool bpf_testmod_ops_is_valid_access(int off, int size, + enum bpf_access_type type, + const struct bpf_prog *prog, + struct bpf_insn_access_aux *info) +{ + return bpf_tracing_btf_ctx_access(off, size, type, prog, info); +} + +static int bpf_testmod_ops_init_member(const struct btf_type *t, + const struct btf_member *member, + void *kdata, const void *udata) +{ + return 0; +} + static const struct btf_kfunc_id_set bpf_testmod_kfunc_set = { .owner = THIS_MODULE, .set = &bpf_testmod_check_kfunc_ids, }; +static const struct bpf_verifier_ops bpf_testmod_verifier_ops = { + .is_valid_access = bpf_testmod_ops_is_valid_access, +}; + +static int bpf_dummy_reg(void *kdata) +{ + struct bpf_testmod_ops *ops = kdata; + int r; + + r = ops->test_2(4, 3); + + return 0; +} + +static void bpf_dummy_unreg(void *kdata) +{ +} + +struct bpf_struct_ops bpf_bpf_testmod_ops = { + .verifier_ops = &bpf_testmod_verifier_ops, + .init = bpf_testmod_ops_init, + .init_member = bpf_testmod_ops_init_member, + .reg = bpf_dummy_reg, + .unreg = bpf_dummy_unreg, + .name = "bpf_testmod_ops", + .owner = THIS_MODULE, +}; + extern int bpf_fentry_test1(int a); static int bpf_testmod_init(void) @@ -535,6 +586,7 @@ static int bpf_testmod_init(void) ret = ret ?: register_btf_kfunc_id_set(BPF_PROG_TYPE_SCHED_CLS, &bpf_testmod_kfunc_set); ret = ret ?: register_btf_kfunc_id_set(BPF_PROG_TYPE_TRACING, &bpf_testmod_kfunc_set); ret = ret ?: register_btf_kfunc_id_set(BPF_PROG_TYPE_SYSCALL, &bpf_testmod_kfunc_set); + ret = ret ?: REGISTER_BPF_STRUCT_OPS(&bpf_bpf_testmod_ops, bpf_testmod_ops); if (ret < 0) return ret; if (bpf_fentry_test1(0) < 0) diff --git a/tools/testing/selftests/bpf/bpf_testmod/bpf_testmod.h b/tools/testing/selftests/bpf/bpf_testmod/bpf_testmod.h index f32793efe095..ca5435751c79 100644 --- a/tools/testing/selftests/bpf/bpf_testmod/bpf_testmod.h +++ b/tools/testing/selftests/bpf/bpf_testmod/bpf_testmod.h @@ -28,4 +28,9 @@ struct bpf_iter_testmod_seq { int cnt; }; +struct bpf_testmod_ops { + int (*test_1)(void); + int (*test_2)(int a, int b); +}; + #endif /* _BPF_TESTMOD_H */ diff --git a/tools/testing/selftests/bpf/prog_tests/test_struct_ops_module.c b/tools/testing/selftests/bpf/prog_tests/test_struct_ops_module.c new file mode 100644 index 000000000000..55a4c6ed92aa --- /dev/null +++ b/tools/testing/selftests/bpf/prog_tests/test_struct_ops_module.c @@ -0,0 +1,92 @@ +// SPDX-License-Identifier: GPL-2.0 +/* Copyright (c) 2023 Meta Platforms, Inc. and affiliates. */ +#include +#include + +#include "struct_ops_module.skel.h" +#include "testmod_unload.skel.h" + +static void test_regular_load(void) +{ + DECLARE_LIBBPF_OPTS(bpf_object_open_opts, opts); + struct struct_ops_module *skel; + struct testmod_unload *skel_unload; + struct bpf_link *link_map_free = NULL; + struct bpf_link *link; + int err, i; + + skel = struct_ops_module__open_opts(&opts); + if (!ASSERT_OK_PTR(skel, "struct_ops_module_open")) + return; + + err = struct_ops_module__load(skel); + if (!ASSERT_OK(err, "struct_ops_module_load")) + goto cleanup; + + link = bpf_map__attach_struct_ops(skel->maps.testmod_1); + ASSERT_OK_PTR(link, "attach_test_mod_1"); + + /* test_2() will be called from bpf_dummy_reg() in bpf_testmod.c */ + ASSERT_EQ(skel->bss->test_2_result, 7, "test_2_result"); + + bpf_link__destroy(link); + +cleanup: + skel_unload = testmod_unload__open_and_load(); + + if (ASSERT_OK_PTR(skel_unload, "testmod_unload_open")) + link_map_free = bpf_program__attach(skel_unload->progs.trace_map_free); + struct_ops_module__destroy(skel); + + if (!ASSERT_OK_PTR(link_map_free, "create_link_map_free")) + return; + + /* Wait for the struct_ops map to be freed. Struct_ops maps hold a + * refcount to the module btf. And, this function unloads and then + * loads bpf_testmod. Without waiting the map to be freed, the next + * test may fail to unload the bpf_testmod module since the map is + * still holding a refcnt to the module. + */ + for (i = 0; i < 10; i++) { + if (skel_unload->bss->bpf_testmod_put) + break; + usleep(100000); + } + ASSERT_EQ(skel_unload->bss->bpf_testmod_put, 1, "map_free"); + + bpf_link__destroy(link_map_free); + testmod_unload__destroy(skel_unload); +} + +static void test_load_without_module(void) +{ + DECLARE_LIBBPF_OPTS(bpf_object_open_opts, opts); + struct struct_ops_module *skel; + int err; + + err = unload_bpf_testmod(false); + if (!ASSERT_OK(err, "unload_bpf_testmod")) + return; + + skel = struct_ops_module__open_opts(&opts); + if (!ASSERT_OK_PTR(skel, "struct_ops_module_open")) + goto cleanup; + err = struct_ops_module__load(skel); + ASSERT_ERR(err, "struct_ops_module_load"); + + struct_ops_module__destroy(skel); + +cleanup: + /* Without this, the next test may fail */ + load_bpf_testmod(false); +} + +void serial_test_struct_ops_module(void) +{ + if (test__start_subtest("regular_load")) + test_regular_load(); + + if (test__start_subtest("load_without_module")) + test_load_without_module(); +} + diff --git a/tools/testing/selftests/bpf/progs/struct_ops_module.c b/tools/testing/selftests/bpf/progs/struct_ops_module.c new file mode 100644 index 000000000000..cb305d04342f --- /dev/null +++ b/tools/testing/selftests/bpf/progs/struct_ops_module.c @@ -0,0 +1,30 @@ +// SPDX-License-Identifier: GPL-2.0 +/* Copyright (c) 2023 Meta Platforms, Inc. and affiliates. */ +#include +#include +#include +#include "../bpf_testmod/bpf_testmod.h" + +char _license[] SEC("license") = "GPL"; + +int test_2_result = 0; + +SEC("struct_ops/test_1") +int BPF_PROG(test_1) +{ + return 0xdeadbeef; +} + +SEC("struct_ops/test_2") +int BPF_PROG(test_2, int a, int b) +{ + test_2_result = a + b; + return a + b; +} + +SEC(".struct_ops.link") +struct bpf_testmod_ops testmod_1 = { + .test_1 = (void *)test_1, + .test_2 = (void *)test_2, +}; + diff --git a/tools/testing/selftests/bpf/progs/testmod_unload.c b/tools/testing/selftests/bpf/progs/testmod_unload.c new file mode 100644 index 000000000000..bb17914ecca3 --- /dev/null +++ b/tools/testing/selftests/bpf/progs/testmod_unload.c @@ -0,0 +1,25 @@ +// SPDX-License-Identifier: GPL-2.0 +/* Copyright (c) 2023 Meta Platforms, Inc. and affiliates. */ +#include +#include +#include + +char _license[] SEC("license") = "GPL"; + +int bpf_testmod_put = 0; + +SEC("fentry/__bpf_struct_ops_map_free") +int BPF_PROG(trace_map_free, struct bpf_map *map) +{ + static const char name[] = "testmod_1"; + int i; + + for (i = 0; i < sizeof(name); i++) { + if (map->name[i] != name[i]) + return 0; + } + + bpf_testmod_put = 1; + + return 0; +} From patchwork Sat Dec 9 00:27:09 2023 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Kui-Feng Lee X-Patchwork-Id: 13485915 X-Patchwork-Delegate: bpf@iogearbox.net Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=gmail.com header.i=@gmail.com header.b="FMED1TCw" Received: from mail-yw1-x1131.google.com (mail-yw1-x1131.google.com [IPv6:2607:f8b0:4864:20::1131]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id 0D2A91723 for ; Fri, 8 Dec 2023 16:27:32 -0800 (PST) Received: by mail-yw1-x1131.google.com with SMTP id 00721157ae682-5dd3affae03so26694987b3.1 for ; Fri, 08 Dec 2023 16:27:32 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20230601; t=1702081651; x=1702686451; darn=vger.kernel.org; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:from:to:cc:subject:date :message-id:reply-to; bh=VsG6FGyrNczTTIsApLKp8t0L6LgFXKoLzWdNL1M+7v4=; b=FMED1TCw8b+ng1oNoHh24dJxSco6WwrAAE5/sUr0fcIjltt6368gL0EqbdtJVlMchI qQqSZTPtuwEhuZrgdAEriI39tFplDYuo8qbQ5iqvuVI1TdpWLAjsBpi1FEJdweUySmO7 VFrZd947NIY6iFasjdAlsqG81RBGmRESuf30DjP8sluPob0H3EN8BAHEYncYyRe7A3Q8 66I0ECUJ9YEl74AkGGbp+ANnVmQbjyJWhp1o8s6sbptUflksiJ3Mdp/UeS/AOlB14wJ8 oTS2Qi7Dd2i8RGMqeTY+l1ANaWet+P6tk6B6Zddz2vgcTkK2fLVBskEqnTyw1FANWpA7 eLGA== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1702081651; x=1702686451; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:x-gm-message-state:from:to:cc :subject:date:message-id:reply-to; bh=VsG6FGyrNczTTIsApLKp8t0L6LgFXKoLzWdNL1M+7v4=; b=p/RMrUdGB1q1a7rRM6jn4BWlWgY5YciQRtC3Xvtyczu+Y7jhqeug3QwwrLDhQE0JBV d5HKlV2LPjPhNr2IUwx9w/flI5yZsPFleNFKVBkpIChb6kQi3b/vRHzoHLNVwaxtCAPD ErSSqO+uzi1/xhgMVPFhiygJLJN6r5wq0dmmSarD1lLajZJJT/gQQGNYqNMr6U1Gv2ws hC+8HYtW8Favc1awJpON+Ch0tCIANcuPxgp+Tp5Lm/0pNHtzrKraW2rhv0uuxWjL3FRz aV5M9KDReupqFIQkzEIWkQZsfKm/2FV5d5qo7USD9q1SshcKXD/yIE5QQVvWIu57tlql ZNEA== X-Gm-Message-State: AOJu0YwHJttMZU5AIiKLVsfUorrLyen1Vdu2if7+j21OAdxPqTsYj1UP S4G57kk9oOmKFICu+em+ExEILYE8IfUCHA== X-Google-Smtp-Source: AGHT+IFk18jPoI9B7RmsIMRiAR3BquIL9UsIxSJDJpKi2GMV8JSUpMwPwDuJkU8RH9cZhi+4aK3MKw== X-Received: by 2002:a0d:c6c5:0:b0:5d7:1940:b383 with SMTP id i188-20020a0dc6c5000000b005d71940b383mr758923ywd.79.1702081651012; Fri, 08 Dec 2023 16:27:31 -0800 (PST) Received: from kickker.attlocal.net ([2600:1700:6cf8:1240:65fe:fe26:c15:a05c]) by smtp.gmail.com with ESMTPSA id v4-20020a818504000000b005d9729068f5sm1057450ywf.42.2023.12.08.16.27.29 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Fri, 08 Dec 2023 16:27:30 -0800 (PST) From: thinker.li@gmail.com To: bpf@vger.kernel.org, ast@kernel.org, martin.lau@linux.dev, song@kernel.org, kernel-team@meta.com, andrii@kernel.org, drosen@google.com Cc: sinquersw@gmail.com, kuifeng@meta.com, Kui-Feng Lee Subject: [PATCH bpf-next v13 14/14] bpf: pass btf object id in bpf_map_info. Date: Fri, 8 Dec 2023 16:27:09 -0800 Message-Id: <20231209002709.535966-15-thinker.li@gmail.com> X-Mailer: git-send-email 2.34.1 In-Reply-To: <20231209002709.535966-1-thinker.li@gmail.com> References: <20231209002709.535966-1-thinker.li@gmail.com> Precedence: bulk X-Mailing-List: bpf@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 X-Patchwork-Delegate: bpf@iogearbox.net From: Kui-Feng Lee Include btf object id (btf_obj_id) in bpf_map_info so that tools (ex: bpftools struct_ops dump) know the correct btf from the kernel to look up type information of struct_ops types. Since struct_ops types can be defined and registered in a module. The type information of a struct_ops type are defined in the btf of the module defining it. The userspace tools need to know which btf is for the module defining a struct_ops type. Signed-off-by: Kui-Feng Lee --- include/linux/bpf.h | 1 + include/uapi/linux/bpf.h | 2 +- kernel/bpf/bpf_struct_ops.c | 7 +++++++ kernel/bpf/syscall.c | 2 ++ tools/include/uapi/linux/bpf.h | 2 +- 5 files changed, 12 insertions(+), 2 deletions(-) diff --git a/include/linux/bpf.h b/include/linux/bpf.h index c881befa35f5..26103d8a4374 100644 --- a/include/linux/bpf.h +++ b/include/linux/bpf.h @@ -3350,5 +3350,6 @@ struct bpf_struct_ops_##_name { \ int bpf_struct_ops_desc_init(struct bpf_struct_ops_desc *st_ops_desc, struct btf *btf, struct bpf_verifier_log *log); +void bpf_map_struct_ops_info_fill(struct bpf_map_info *info, struct bpf_map *map); #endif /* _LINUX_BPF_H */ diff --git a/include/uapi/linux/bpf.h b/include/uapi/linux/bpf.h index 5c3838a97554..716c6b28764d 100644 --- a/include/uapi/linux/bpf.h +++ b/include/uapi/linux/bpf.h @@ -6534,7 +6534,7 @@ struct bpf_map_info { __u32 btf_id; __u32 btf_key_type_id; __u32 btf_value_type_id; - __u32 :32; /* alignment pad */ + __u32 btf_obj_id; __u64 map_extra; } __attribute__((aligned(8))); diff --git a/kernel/bpf/bpf_struct_ops.c b/kernel/bpf/bpf_struct_ops.c index fd26716fa0f9..51c0de75aa85 100644 --- a/kernel/bpf/bpf_struct_ops.c +++ b/kernel/bpf/bpf_struct_ops.c @@ -979,3 +979,10 @@ int bpf_struct_ops_link_create(union bpf_attr *attr) kfree(link); return err; } + +void bpf_map_struct_ops_info_fill(struct bpf_map_info *info, struct bpf_map *map) +{ + struct bpf_struct_ops_map *st_map = (struct bpf_struct_ops_map *)map; + + info->btf_obj_id = btf_obj_id(st_map->btf); +} diff --git a/kernel/bpf/syscall.c b/kernel/bpf/syscall.c index 4aced7e58904..3cab56cd02ff 100644 --- a/kernel/bpf/syscall.c +++ b/kernel/bpf/syscall.c @@ -4715,6 +4715,8 @@ static int bpf_map_get_info_by_fd(struct file *file, info.btf_value_type_id = map->btf_value_type_id; } info.btf_vmlinux_value_type_id = map->btf_vmlinux_value_type_id; + if (map->map_type == BPF_MAP_TYPE_STRUCT_OPS) + bpf_map_struct_ops_info_fill(&info, map); if (bpf_map_is_offloaded(map)) { err = bpf_map_offload_info_fill(&info, map); diff --git a/tools/include/uapi/linux/bpf.h b/tools/include/uapi/linux/bpf.h index 5c3838a97554..716c6b28764d 100644 --- a/tools/include/uapi/linux/bpf.h +++ b/tools/include/uapi/linux/bpf.h @@ -6534,7 +6534,7 @@ struct bpf_map_info { __u32 btf_id; __u32 btf_key_type_id; __u32 btf_value_type_id; - __u32 :32; /* alignment pad */ + __u32 btf_obj_id; __u64 map_extra; } __attribute__((aligned(8)));