From patchwork Tue Jan 23 10:32:40 2024 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Pu Lehui X-Patchwork-Id: 13527172 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from bombadil.infradead.org (bombadil.infradead.org [198.137.202.133]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.lore.kernel.org (Postfix) with ESMTPS id B7927C47E49 for ; Tue, 23 Jan 2024 10:32:30 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; q=dns/txt; c=relaxed/relaxed; d=lists.infradead.org; s=bombadil.20210309; h=Sender: Content-Transfer-Encoding:Content-Type:List-Subscribe:List-Help:List-Post: List-Archive:List-Unsubscribe:List-Id:MIME-Version:References:In-Reply-To: Message-Id:Date:Subject:Cc:To:From:Reply-To:Content-ID:Content-Description: Resent-Date:Resent-From:Resent-Sender:Resent-To:Resent-Cc:Resent-Message-ID: List-Owner; bh=+WpsA920Jbq/9BC4mord+C8yO7DoqGlutTqD1APq2O0=; b=18v2UjNqz1JQpx ZXQaA7e+NnLNOq/Ncv1gdl2wQng78ivoaNK6TX8OeMpQUlqONkCQMQvomTkxdjYCjB0to6y9XwZ3B sGn7wMDsZ+NFxIu5mZ6JILWlRrALwP4gbcy3UV+AEoQKuRbiHRdEhP3YgpVgO9qBsvfTaWNvvyYKy h4FlXO7BshTpUr5Rh0z8OY3nYe8+qbgM+TuOkhj3xkdtjL6dJ5zHSQYzYsOX/imxF2VqQndxRieeJ BPS+zNOfLU9hZHAn90COxiMmpBWbwitvwbt00r21k1TSdgpitJm1phG++1aDvH+t3JCKGZkTXgEd0 hO8FfSHSzQ9KdNe1ReOw==; Received: from localhost ([::1] helo=bombadil.infradead.org) by bombadil.infradead.org with esmtp (Exim 4.96 #2 (Red Hat Linux)) id 1rSE4t-00FwmK-1b; Tue, 23 Jan 2024 10:32:23 +0000 Received: from [45.249.212.51] (helo=dggsgout11.his.huawei.com) by bombadil.infradead.org with esmtps (Exim 4.96 #2 (Red Hat Linux)) id 1rSE4m-00FwgQ-0T for linux-riscv@lists.infradead.org; Tue, 23 Jan 2024 10:32:20 +0000 Received: from mail.maildlp.com (unknown [172.19.163.216]) by dggsgout11.his.huawei.com (SkyGuard) with ESMTP id 4TK3L61VMXz4f3m74 for ; Tue, 23 Jan 2024 18:31:58 +0800 (CST) Received: from mail02.huawei.com (unknown [10.116.40.75]) by mail.maildlp.com (Postfix) with ESMTP id 7A0EB1A01E9 for ; Tue, 23 Jan 2024 18:32:04 +0800 (CST) Received: from ultra.huawei.com (unknown [10.90.53.71]) by APP2 (Coremail) with SMTP id Syh0CgBHaQyfla9ldy79Bg--.53064S4; Tue, 23 Jan 2024 18:32:04 +0800 (CST) From: Pu Lehui To: bpf@vger.kernel.org, linux-riscv@lists.infradead.org, netdev@vger.kernel.org Cc: =?utf-8?b?QmrDtnJuIFTDtnBlbA==?= , Song Liu , Puranjay Mohan , Alexei Starovoitov , Daniel Borkmann , Andrii Nakryiko , Martin KaFai Lau , Yonghong Song , John Fastabend , KP Singh , Stanislav Fomichev , Hao Luo , Jiri Olsa , Palmer Dabbelt , Luke Nelson , Pu Lehui , Pu Lehui Subject: [PATCH bpf-next 2/3] bpf: Keep im address consistent between dry run and real patching Date: Tue, 23 Jan 2024 10:32:40 +0000 Message-Id: <20240123103241.2282122-3-pulehui@huaweicloud.com> X-Mailer: git-send-email 2.34.1 In-Reply-To: <20240123103241.2282122-1-pulehui@huaweicloud.com> References: <20240123103241.2282122-1-pulehui@huaweicloud.com> MIME-Version: 1.0 X-CM-TRANSID: Syh0CgBHaQyfla9ldy79Bg--.53064S4 X-Coremail-Antispam: 1UD129KBjvJXoW3Ww15ZrWDKr4DGFW3tw4rAFb_yoWftw1kpF 1UAF13AF48XrWDXa4kJw48ZF4ava4kX3y7CFWUGrWFka90qr95JF1rK34SvrWFyrZ09F13 AFs09rn0yF18u3DanT9S1TB71UUUUU7qnTZGkaVYY2UrUUUUjbIjqfuFe4nvWSU5nxnvy2 9KBjDU0xBIdaVrnRJUUUmF14x267AKxVWrJVCq3wAFc2x0x2IEx4CE42xK8VAvwI8IcIk0 rVWrJVCq3wAFIxvE14AKwVWUJVWUGwA2048vs2IY020E87I2jVAFwI0_Jryl82xGYIkIc2 x26xkF7I0E14v26ryj6s0DM28lY4IEw2IIxxk0rwA2F7IY1VAKz4vEj48ve4kI8wA2z4x0 Y4vE2Ix0cI8IcVAFwI0_Ar0_tr1l84ACjcxK6xIIjxv20xvEc7CjxVAFwI0_Gr1j6F4UJw A2z4x0Y4vEx4A2jsIE14v26rxl6s0DM28EF7xvwVC2z280aVCY1x0267AKxVW0oVCq3wAS 0I0E0xvYzxvE52x082IY62kv0487Mc02F40EFcxC0VAKzVAqx4xG6I80ewAv7VC0I7IYx2 IY67AKxVWUJVWUGwAv7VC2z280aVAFwI0_Jr0_Gr1lOx8S6xCaFVCjc4AY6r1j6r4UM4x0 Y48IcxkI7VAKI48JM4x0x7Aq67IIx4CEVc8vx2IErcIFxwACI402YVCY1x02628vn2kIc2 xKxwCY1x0262kKe7AKxVWUtVW8ZwCF04k20xvY0x0EwIxGrwCFx2IqxVCFs4IE7xkEbVWU JVW8JwC20s026c02F40E14v26r1j6r18MI8I3I0E7480Y4vE14v26r106r1rMI8E67AF67 kF1VAFwI0_GFv_WrylIxkGc2Ij64vIr41lIxAIcVC0I7IYx2IY67AKxVWUJVWUCwCI42IY 6xIIjxv20xvEc7CjxVAFwI0_Cr0_Gr1UMIIF0xvE42xK8VAvwI8IcIk0rVWUJVWUCwCI42 IY6I8E87Iv67AKxVW8JVWxJwCI42IY6I8E87Iv6xkF7I0E14v26r4UJVWxJrUvcSsGvfC2 KfnxnUUI43ZEXa7VUbH5lUUUUUU== X-CM-SenderInfo: psxovxtxl6x35dzhxuhorxvhhfrp/ X-CRM114-Version: 20100106-BlameMichelson ( TRE 0.8.0 (BSD) ) MR-646709E3 X-CRM114-CacheID: sfid-20240123_023216_558021_D15F0F3D X-CRM114-Status: GOOD ( 17.49 ) X-BeenThere: linux-riscv@lists.infradead.org X-Mailman-Version: 2.1.34 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Sender: "linux-riscv" Errors-To: linux-riscv-bounces+linux-riscv=archiver.kernel.org@lists.infradead.org From: Pu Lehui In __arch_prepare_bpf_trampoline, we emit instructions to store the address of im to register and then pass it to __bpf_tramp_enter and __bpf_tramp_exit functions. Currently we use fake im in arch_bpf_trampoline_size for the dry run, and then allocate new im for the real patching. This is fine for architectures that use fixed instructions to generate addresses. However, for architectures that use dynamic instructions to generate addresses, this may make the front and rear images inconsistent, leading to patching overflow. We can extract the im allocation ahead of the dry run and pass the allocated im to arch_bpf_trampoline_size, so that we can ensure that im is consistent in dry run and real patching. Signed-off-by: Pu Lehui --- arch/arm64/net/bpf_jit_comp.c | 7 +++--- arch/riscv/net/bpf_jit_comp64.c | 7 +++--- arch/s390/net/bpf_jit_comp.c | 7 +++--- arch/x86/net/bpf_jit_comp.c | 7 +++--- include/linux/bpf.h | 4 +-- kernel/bpf/bpf_struct_ops.c | 2 +- kernel/bpf/trampoline.c | 43 ++++++++++++++++----------------- 7 files changed, 36 insertions(+), 41 deletions(-) diff --git a/arch/arm64/net/bpf_jit_comp.c b/arch/arm64/net/bpf_jit_comp.c index 8955da5c47cf..fad760f14a96 100644 --- a/arch/arm64/net/bpf_jit_comp.c +++ b/arch/arm64/net/bpf_jit_comp.c @@ -2041,14 +2041,13 @@ static int btf_func_model_nregs(const struct btf_func_model *m) return nregs; } -int arch_bpf_trampoline_size(const struct btf_func_model *m, u32 flags, - struct bpf_tramp_links *tlinks, void *func_addr) +int arch_bpf_trampoline_size(struct bpf_tramp_image *im, const struct btf_func_model *m, + u32 flags, struct bpf_tramp_links *tlinks, void *func_addr) { struct jit_ctx ctx = { .image = NULL, .idx = 0, }; - struct bpf_tramp_image im; int nregs, ret; nregs = btf_func_model_nregs(m); @@ -2056,7 +2055,7 @@ int arch_bpf_trampoline_size(const struct btf_func_model *m, u32 flags, if (nregs > 8) return -ENOTSUPP; - ret = prepare_trampoline(&ctx, &im, tlinks, func_addr, nregs, flags); + ret = prepare_trampoline(&ctx, im, tlinks, func_addr, nregs, flags); if (ret < 0) return ret; diff --git a/arch/riscv/net/bpf_jit_comp64.c b/arch/riscv/net/bpf_jit_comp64.c index 719a97e7edb2..5c4e0ac389d0 100644 --- a/arch/riscv/net/bpf_jit_comp64.c +++ b/arch/riscv/net/bpf_jit_comp64.c @@ -1030,17 +1030,16 @@ static int __arch_prepare_bpf_trampoline(struct bpf_tramp_image *im, return ret; } -int arch_bpf_trampoline_size(const struct btf_func_model *m, u32 flags, - struct bpf_tramp_links *tlinks, void *func_addr) +int arch_bpf_trampoline_size(struct bpf_tramp_image *im, const struct btf_func_model *m, + u32 flags, struct bpf_tramp_links *tlinks, void *func_addr) { - struct bpf_tramp_image im; struct rv_jit_context ctx; int ret; ctx.ninsns = 0; ctx.insns = NULL; ctx.ro_insns = NULL; - ret = __arch_prepare_bpf_trampoline(&im, m, tlinks, func_addr, flags, &ctx); + ret = __arch_prepare_bpf_trampoline(im, m, tlinks, func_addr, flags, &ctx); return ret < 0 ? ret : ninsns_rvoff(ctx.ninsns); } diff --git a/arch/s390/net/bpf_jit_comp.c b/arch/s390/net/bpf_jit_comp.c index b418333bb086..adf289eee6cd 100644 --- a/arch/s390/net/bpf_jit_comp.c +++ b/arch/s390/net/bpf_jit_comp.c @@ -2638,16 +2638,15 @@ static int __arch_prepare_bpf_trampoline(struct bpf_tramp_image *im, return 0; } -int arch_bpf_trampoline_size(const struct btf_func_model *m, u32 flags, - struct bpf_tramp_links *tlinks, void *orig_call) +int arch_bpf_trampoline_size(struct bpf_tramp_image *im, const struct btf_func_model *m, + u32 flags, struct bpf_tramp_links *tlinks, void *orig_call) { - struct bpf_tramp_image im; struct bpf_tramp_jit tjit; int ret; memset(&tjit, 0, sizeof(tjit)); - ret = __arch_prepare_bpf_trampoline(&im, &tjit, m, flags, + ret = __arch_prepare_bpf_trampoline(im, &tjit, m, flags, tlinks, orig_call); return ret < 0 ? ret : tjit.common.prg; diff --git a/arch/x86/net/bpf_jit_comp.c b/arch/x86/net/bpf_jit_comp.c index e1390d1e331b..fdef44913643 100644 --- a/arch/x86/net/bpf_jit_comp.c +++ b/arch/x86/net/bpf_jit_comp.c @@ -2817,10 +2817,9 @@ int arch_prepare_bpf_trampoline(struct bpf_tramp_image *im, void *image, void *i return ret; } -int arch_bpf_trampoline_size(const struct btf_func_model *m, u32 flags, - struct bpf_tramp_links *tlinks, void *func_addr) +int arch_bpf_trampoline_size(struct bpf_tramp_image *im, const struct btf_func_model *m, + u32 flags, struct bpf_tramp_links *tlinks, void *func_addr) { - struct bpf_tramp_image im; void *image; int ret; @@ -2835,7 +2834,7 @@ int arch_bpf_trampoline_size(const struct btf_func_model *m, u32 flags, if (!image) return -ENOMEM; - ret = __arch_prepare_bpf_trampoline(&im, image, image + PAGE_SIZE, image, + ret = __arch_prepare_bpf_trampoline(im, image, image + PAGE_SIZE, image, m, flags, tlinks, func_addr); bpf_jit_free_exec(image); return ret; diff --git a/include/linux/bpf.h b/include/linux/bpf.h index 377857b232c6..d3a486e12b17 100644 --- a/include/linux/bpf.h +++ b/include/linux/bpf.h @@ -1114,8 +1114,8 @@ void *arch_alloc_bpf_trampoline(unsigned int size); void arch_free_bpf_trampoline(void *image, unsigned int size); void arch_protect_bpf_trampoline(void *image, unsigned int size); void arch_unprotect_bpf_trampoline(void *image, unsigned int size); -int arch_bpf_trampoline_size(const struct btf_func_model *m, u32 flags, - struct bpf_tramp_links *tlinks, void *func_addr); +int arch_bpf_trampoline_size(struct bpf_tramp_image *im, const struct btf_func_model *m, + u32 flags, struct bpf_tramp_links *tlinks, void *func_addr); u64 notrace __bpf_prog_enter_sleepable_recur(struct bpf_prog *prog, struct bpf_tramp_run_ctx *run_ctx); diff --git a/kernel/bpf/bpf_struct_ops.c b/kernel/bpf/bpf_struct_ops.c index e2e1bf3c69a3..8b3c6cc7ea94 100644 --- a/kernel/bpf/bpf_struct_ops.c +++ b/kernel/bpf/bpf_struct_ops.c @@ -363,7 +363,7 @@ int bpf_struct_ops_prepare_trampoline(struct bpf_tramp_links *tlinks, if (model->ret_size > 0) flags |= BPF_TRAMP_F_RET_FENTRY_RET; - size = arch_bpf_trampoline_size(model, flags, tlinks, NULL); + size = arch_bpf_trampoline_size(NULL, model, flags, tlinks, NULL); if (size < 0) return size; if (size > (unsigned long)image_end - (unsigned long)image) diff --git a/kernel/bpf/trampoline.c b/kernel/bpf/trampoline.c index d382f5ebe06c..25621d97f3ca 100644 --- a/kernel/bpf/trampoline.c +++ b/kernel/bpf/trampoline.c @@ -349,20 +349,15 @@ static void bpf_tramp_image_put(struct bpf_tramp_image *im) call_rcu_tasks_trace(&im->rcu, __bpf_tramp_image_put_rcu_tasks); } -static struct bpf_tramp_image *bpf_tramp_image_alloc(u64 key, int size) +static int bpf_tramp_image_alloc(struct bpf_tramp_image *im, u64 key, int size) { - struct bpf_tramp_image *im; struct bpf_ksym *ksym; void *image; - int err = -ENOMEM; - - im = kzalloc(sizeof(*im), GFP_KERNEL); - if (!im) - goto out; + int err; err = bpf_jit_charge_modmem(size); if (err) - goto out_free_im; + goto out; im->size = size; err = -ENOMEM; @@ -378,16 +373,14 @@ static struct bpf_tramp_image *bpf_tramp_image_alloc(u64 key, int size) INIT_LIST_HEAD_RCU(&ksym->lnode); snprintf(ksym->name, KSYM_NAME_LEN, "bpf_trampoline_%llu", key); bpf_image_ksym_add(image, size, ksym); - return im; + return 0; out_free_image: arch_free_bpf_trampoline(im->image, im->size); out_uncharge: bpf_jit_uncharge_modmem(size); -out_free_im: - kfree(im); out: - return ERR_PTR(err); + return err; } static int bpf_trampoline_update(struct bpf_trampoline *tr, bool lock_direct_mutex) @@ -432,23 +425,27 @@ static int bpf_trampoline_update(struct bpf_trampoline *tr, bool lock_direct_mut tr->flags |= BPF_TRAMP_F_ORIG_STACK; #endif - size = arch_bpf_trampoline_size(&tr->func.model, tr->flags, + im = kzalloc(sizeof(*im), GFP_KERNEL); + if (!im) { + err = -ENOMEM; + goto out; + } + + size = arch_bpf_trampoline_size(im, &tr->func.model, tr->flags, tlinks, tr->func.addr); if (size < 0) { err = size; - goto out; + goto out_free_im; } if (size > PAGE_SIZE) { err = -E2BIG; - goto out; + goto out_free_im; } - im = bpf_tramp_image_alloc(tr->key, size); - if (IS_ERR(im)) { - err = PTR_ERR(im); - goto out; - } + err = bpf_tramp_image_alloc(im, tr->key, size); + if (err < 0) + goto out_free_im; err = arch_prepare_bpf_trampoline(im, im->image, im->image + size, &tr->func.model, tr->flags, tlinks, @@ -496,6 +493,8 @@ static int bpf_trampoline_update(struct bpf_trampoline *tr, bool lock_direct_mut out_free: bpf_tramp_image_free(im); +out_free_im: + kfree_rcu(im, rcu); goto out; } @@ -1085,8 +1084,8 @@ void __weak arch_unprotect_bpf_trampoline(void *image, unsigned int size) set_memory_rw((long)image, 1); } -int __weak arch_bpf_trampoline_size(const struct btf_func_model *m, u32 flags, - struct bpf_tramp_links *tlinks, void *func_addr) +int __weak arch_bpf_trampoline_size(struct bpf_tramp_image *im, const struct btf_func_model *m, + u32 flags, struct bpf_tramp_links *tlinks, void *func_addr) { return -ENOTSUPP; }