Received: by 2002:a05:6a10:c7c6:0:0:0:0 with SMTP id h6csp1650254pxy; Mon, 2 Aug 2021 07:05:24 -0700 (PDT) X-Google-Smtp-Source: ABdhPJz+KOuvFwM4HR0UkAzk4aTAN+D6lN4643kAhEOKSN6seC9b50m0UJtaPjn4E7C6xAFP8bdF X-Received: by 2002:a05:6638:34aa:: with SMTP id t42mr14839178jal.128.1627913124781; Mon, 02 Aug 2021 07:05:24 -0700 (PDT) ARC-Seal: i=1; a=rsa-sha256; t=1627913124; cv=none; d=google.com; s=arc-20160816; b=n2DI07fxDTaHp/pFtZnl/8B7adkpV7skyCSA8nteve1birxfH06YIE8iqn/5iICs1x k5KHg0rNzlFokOkcOUrtk/cTcEhe9ixWY89MhcJXs8ICQdjK0I0uEVG86DaYLyaxia83 kD+n7Ck1agTx20MK8+ut8jm9CQTTZYGFmuHnNsD5ELLURD/vn6sVCTiHEv2H8rCammh2 ztDStP/MogTyGyZ9myV0ZZc2Wib4vKbCKdo1Agdznndp0Hl+7yKE8EXYGd4jOeSNIdDG 4B++MfqdOqrb3DlVsOT17qUYx6iQIp6/PtqGpm6idhIP/lPx0XYn2m0tdy0HQwEyblxM tRIw== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20160816; h=list-id:precedence:content-transfer-encoding:mime-version :user-agent:references:in-reply-to:message-id:date:subject:cc:to :from:dkim-signature; bh=dhqHzd0yN9NlaX+7YawpAfLBCtIV8WO/QSuWjUm0730=; b=Enh4KxPzq2iHDreEGPfdWf9T/gD5cDW74198kPMHrUoB/g4Em1KAxv9LZ5u0F7l2yo C3o0v1lAbLzBFW2CxuN9K77icNvy61O+KiHW/OQpii6zE+49pvzYZ8SxVU+b0ON1/Y4P S6ZR5hMvAfRQQKlN7lv6+oWXwTktkZRvtyc+W51hwTddfM/Get8ayewS4gIbVBaUdaBx r03HhTod3JoXEMCVhXXvOq+da901l6n5C2MsqubIotq01ukrGC12WmNDt2vxl9t+2j9K PJLo21Vt/xzH6Q2tauHZAe40JNEtPP5AQWOzgnhuRGGcg+EJdTBhgZc3ghRiA5xv8O4z f02w== ARC-Authentication-Results: i=1; mx.google.com; dkim=pass header.i=@linuxfoundation.org header.s=korg header.b=uXwbG9ep; spf=pass (google.com: domain of linux-kernel-owner@vger.kernel.org designates 23.128.96.18 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org; dmarc=pass (p=NONE sp=NONE dis=NONE) header.from=linuxfoundation.org Return-Path: Received: from vger.kernel.org (vger.kernel.org. [23.128.96.18]) by mx.google.com with ESMTP id n3si13644681ioh.98.2021.08.02.07.05.13; Mon, 02 Aug 2021 07:05:24 -0700 (PDT) Received-SPF: pass (google.com: domain of linux-kernel-owner@vger.kernel.org designates 23.128.96.18 as permitted sender) client-ip=23.128.96.18; Authentication-Results: mx.google.com; dkim=pass header.i=@linuxfoundation.org header.s=korg header.b=uXwbG9ep; spf=pass (google.com: domain of linux-kernel-owner@vger.kernel.org designates 23.128.96.18 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org; dmarc=pass (p=NONE sp=NONE dis=NONE) header.from=linuxfoundation.org Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S234834AbhHBOEA (ORCPT + 99 others); Mon, 2 Aug 2021 10:04:00 -0400 Received: from mail.kernel.org ([198.145.29.99]:42416 "EHLO mail.kernel.org" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S235537AbhHBNzx (ORCPT ); Mon, 2 Aug 2021 09:55:53 -0400 Received: by mail.kernel.org (Postfix) with ESMTPSA id B0E3660FC2; Mon, 2 Aug 2021 13:54:18 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=linuxfoundation.org; s=korg; t=1627912459; bh=NyW7d6PIyiREgntorEgZ1iDhDJXoM/9cWj6Lj94d4eM=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=uXwbG9epJ5e3+uoaie4B4i6RB1bLB4RR5QsWfzTP64YOD4Pk541RoNnzB8X+yUVJN NmteW9JEwYkCL3XsQLpZ5FTBQCSX9dSJdlWAv/E+OXOhbnKgTjA5ABzmMact+igxVn KGkYjdWbaWcFOYXK/tqOZ+0ooFXbmxNn5x0HMDsA= From: Greg Kroah-Hartman To: linux-kernel@vger.kernel.org Cc: Greg Kroah-Hartman , stable@vger.kernel.org, Lorenz Bauer , Alexei Starovoitov , Edward Cree Subject: [PATCH 5.10 61/67] bpf: verifier: Allocate idmap scratch in verifier env Date: Mon, 2 Aug 2021 15:45:24 +0200 Message-Id: <20210802134341.134023420@linuxfoundation.org> X-Mailer: git-send-email 2.32.0 In-Reply-To: <20210802134339.023067817@linuxfoundation.org> References: <20210802134339.023067817@linuxfoundation.org> User-Agent: quilt/0.66 MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Precedence: bulk List-ID: X-Mailing-List: linux-kernel@vger.kernel.org From: Lorenz Bauer commit c9e73e3d2b1eb1ea7ff068e05007eec3bd8ef1c9 upstream. func_states_equal makes a very short lived allocation for idmap, probably because it's too large to fit on the stack. However the function is called quite often, leading to a lot of alloc / free churn. Replace the temporary allocation with dedicated scratch space in struct bpf_verifier_env. Signed-off-by: Lorenz Bauer Signed-off-by: Alexei Starovoitov Acked-by: Edward Cree Link: https://lore.kernel.org/bpf/20210429134656.122225-4-lmb@cloudflare.com Signed-off-by: Greg Kroah-Hartman --- include/linux/bpf_verifier.h | 8 +++++++ kernel/bpf/verifier.c | 46 ++++++++++++++----------------------------- 2 files changed, 23 insertions(+), 31 deletions(-) --- a/include/linux/bpf_verifier.h +++ b/include/linux/bpf_verifier.h @@ -204,6 +204,13 @@ struct bpf_idx_pair { u32 idx; }; +struct bpf_id_pair { + u32 old; + u32 cur; +}; + +/* Maximum number of register states that can exist at once */ +#define BPF_ID_MAP_SIZE (MAX_BPF_REG + MAX_BPF_STACK / BPF_REG_SIZE) #define MAX_CALL_FRAMES 8 struct bpf_verifier_state { /* call stack tracking */ @@ -401,6 +408,7 @@ struct bpf_verifier_env { const struct bpf_line_info *prev_linfo; struct bpf_verifier_log log; struct bpf_subprog_info subprog_info[BPF_MAX_SUBPROGS + 1]; + struct bpf_id_pair idmap_scratch[BPF_ID_MAP_SIZE]; struct { int *insn_state; int *insn_stack; --- a/kernel/bpf/verifier.c +++ b/kernel/bpf/verifier.c @@ -8962,13 +8962,6 @@ static bool range_within(struct bpf_reg_ old->s32_max_value >= cur->s32_max_value; } -/* Maximum number of register states that can exist at once */ -#define ID_MAP_SIZE (MAX_BPF_REG + MAX_BPF_STACK / BPF_REG_SIZE) -struct idpair { - u32 old; - u32 cur; -}; - /* If in the old state two registers had the same id, then they need to have * the same id in the new state as well. But that id could be different from * the old state, so we need to track the mapping from old to new ids. @@ -8979,11 +8972,11 @@ struct idpair { * So we look through our idmap to see if this old id has been seen before. If * so, we require the new id to match; otherwise, we add the id pair to the map. */ -static bool check_ids(u32 old_id, u32 cur_id, struct idpair *idmap) +static bool check_ids(u32 old_id, u32 cur_id, struct bpf_id_pair *idmap) { unsigned int i; - for (i = 0; i < ID_MAP_SIZE; i++) { + for (i = 0; i < BPF_ID_MAP_SIZE; i++) { if (!idmap[i].old) { /* Reached an empty slot; haven't seen this id before */ idmap[i].old = old_id; @@ -9096,7 +9089,7 @@ next: /* Returns true if (rold safe implies rcur safe) */ static bool regsafe(struct bpf_reg_state *rold, struct bpf_reg_state *rcur, - struct idpair *idmap) + struct bpf_id_pair *idmap) { bool equal; @@ -9213,7 +9206,7 @@ static bool regsafe(struct bpf_reg_state static bool stacksafe(struct bpf_func_state *old, struct bpf_func_state *cur, - struct idpair *idmap) + struct bpf_id_pair *idmap) { int i, spi; @@ -9310,32 +9303,23 @@ static bool refsafe(struct bpf_func_stat * whereas register type in current state is meaningful, it means that * the current state will reach 'bpf_exit' instruction safely */ -static bool func_states_equal(struct bpf_func_state *old, +static bool func_states_equal(struct bpf_verifier_env *env, struct bpf_func_state *old, struct bpf_func_state *cur) { - struct idpair *idmap; - bool ret = false; int i; - idmap = kcalloc(ID_MAP_SIZE, sizeof(struct idpair), GFP_KERNEL); - /* If we failed to allocate the idmap, just say it's not safe */ - if (!idmap) - return false; - - for (i = 0; i < MAX_BPF_REG; i++) { - if (!regsafe(&old->regs[i], &cur->regs[i], idmap)) - goto out_free; - } + memset(env->idmap_scratch, 0, sizeof(env->idmap_scratch)); + for (i = 0; i < MAX_BPF_REG; i++) + if (!regsafe(&old->regs[i], &cur->regs[i], env->idmap_scratch)) + return false; - if (!stacksafe(old, cur, idmap)) - goto out_free; + if (!stacksafe(old, cur, env->idmap_scratch)) + return false; if (!refsafe(old, cur)) - goto out_free; - ret = true; -out_free: - kfree(idmap); - return ret; + return false; + + return true; } static bool states_equal(struct bpf_verifier_env *env, @@ -9362,7 +9346,7 @@ static bool states_equal(struct bpf_veri for (i = 0; i <= old->curframe; i++) { if (old->frame[i]->callsite != cur->frame[i]->callsite) return false; - if (!func_states_equal(old->frame[i], cur->frame[i])) + if (!func_states_equal(env, old->frame[i], cur->frame[i])) return false; } return true;