Received: by 2002:a05:6a10:c7c6:0:0:0:0 with SMTP id h6csp1650246pxy; Mon, 2 Aug 2021 07:05:24 -0700 (PDT) X-Google-Smtp-Source: ABdhPJyOxsZFhygINWEBCSmBGt9gSLljujEpfqyH/J826dfhB4+7Tpx/6hTlPuURIIVyxbNn90Q8 X-Received: by 2002:a05:6e02:54c:: with SMTP id i12mr1425717ils.103.1627913124437; 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=cBZ0OwPy7zYmuLI37B3j5b/MTdKzdIJDpMFPylxPuFXQMye53LSoBNEdWhJsJmn39/ 2yQc1JG1oo9orL7kZJmcJxfJIJOvHUki7v7dctsUtYRX71PhsoqvXxila/EACEr+uCjp old5YDaeY6fSUxaBUcgSMPRMQxoCLMjUPOQ7QRu7kNSDITBNRHBNzBLd1h/4q04Fw5K2 tbMhpaekkfSRgrvT8a/aeR9cLvh6IH99bJWIpy8CxVwGiyXFMVl6HqNPNMaBvM+oqds0 wjqJkx0XJcLR4Ady84Mxdle7l8CTbl4/CGZ7JCQsRQ0zSz8Gs+RKMQY9f9vMn6uwl0wn oOWQ== 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=7wd2he1dxSIE/LalXbsB30ZJCGzjb6eESvBSp2lj2Xo=; b=VwBHBNBQVqkDqpPoRcwPe7cnsTo55pfCeuh/QABNOjfWBO6R5AZL4cHwEfVIg2Yttb joKyISE57BrAnkJPLmCHYdL2cAEfublX3zztguZqCc/NHpSdj2DxspLjCQmzwt3TLW4Y Po5hijm6t4QKdLVgim40DT9gNBEAuakInxy3zktEByVijeC45znFVosmgxISqJfFhFtk sxUhdOFF+RdJzvlOVu8n+6dvVVPol5i1rJU0bG5L30BgKNVPHyJGq1O5OA1fm1fLz82b 6b3216Nk/cZVLP499RAHQCImqdRsjtl8mgDLPcc5sXUJ1olBGSrEds6VpVIh8hWpVf5U 8V/A== ARC-Authentication-Results: i=1; mx.google.com; dkim=pass header.i=@linuxfoundation.org header.s=korg header.b=LFqslmpn; 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 t15si11961077ilg.47.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=LFqslmpn; 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 S234047AbhHBODv (ORCPT + 99 others); Mon, 2 Aug 2021 10:03:51 -0400 Received: from mail.kernel.org ([198.145.29.99]:40874 "EHLO mail.kernel.org" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S235536AbhHBNzx (ORCPT ); Mon, 2 Aug 2021 09:55:53 -0400 Received: by mail.kernel.org (Postfix) with ESMTPSA id E13FC6112E; Mon, 2 Aug 2021 13:54:20 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=linuxfoundation.org; s=korg; t=1627912461; bh=aGHkqmSGxXrbhtwRUFt4vEQlw1xCA2kFYBUK5GRyUn8=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=LFqslmpn9DOzypyLcYzOizwbhu+vEENwuuriwK/vg+67ORAf+gcd25Heex+4u1v4D iXoQ3r5rCRFnR0Ui7GonUTLJp8HL+dYIB1x1E/DWyFv0N6O+NcnLu0yevaIrU/PimU 6LFhBvldF1Dz9rf/6fj2EWOC6iU81ePw0DnAZeMQ= From: Greg Kroah-Hartman To: linux-kernel@vger.kernel.org Cc: Greg Kroah-Hartman , stable@vger.kernel.org, Daniel Borkmann , Alexei Starovoitov Subject: [PATCH 5.10 62/67] bpf: Fix pointer arithmetic mask tightening under state pruning Date: Mon, 2 Aug 2021 15:45:25 +0200 Message-Id: <20210802134341.172647088@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: Daniel Borkmann commit e042aa532c84d18ff13291d00620502ce7a38dda upstream. In 7fedb63a8307 ("bpf: Tighten speculative pointer arithmetic mask") we narrowed the offset mask for unprivileged pointer arithmetic in order to mitigate a corner case where in the speculative domain it is possible to advance, for example, the map value pointer by up to value_size-1 out-of- bounds in order to leak kernel memory via side-channel to user space. The verifier's state pruning for scalars leaves one corner case open where in the first verification path R_x holds an unknown scalar with an aux->alu_limit of e.g. 7, and in a second verification path that same register R_x, here denoted as R_x', holds an unknown scalar which has tighter bounds and would thus satisfy range_within(R_x, R_x') as well as tnum_in(R_x, R_x') for state pruning, yielding an aux->alu_limit of 3: Given the second path fits the register constraints for pruning, the final generated mask from aux->alu_limit will remain at 7. While technically not wrong for the non-speculative domain, it would however be possible to craft similar cases where the mask would be too wide as in 7fedb63a8307. One way to fix it is to detect the presence of unknown scalar map pointer arithmetic and force a deeper search on unknown scalars to ensure that we do not run into a masking mismatch. Signed-off-by: Daniel Borkmann Acked-by: Alexei Starovoitov Signed-off-by: Greg Kroah-Hartman --- include/linux/bpf_verifier.h | 1 + kernel/bpf/verifier.c | 27 +++++++++++++++++---------- 2 files changed, 18 insertions(+), 10 deletions(-) --- a/include/linux/bpf_verifier.h +++ b/include/linux/bpf_verifier.h @@ -397,6 +397,7 @@ struct bpf_verifier_env { struct bpf_map *used_maps[MAX_USED_MAPS]; /* array of map's used by eBPF program */ u32 used_map_cnt; /* number of used maps */ u32 id_gen; /* used to generate unique reg IDs */ + bool explore_alu_limits; bool allow_ptr_leaks; bool allow_uninit_stack; bool allow_ptr_to_map_access; --- a/kernel/bpf/verifier.c +++ b/kernel/bpf/verifier.c @@ -5792,6 +5792,12 @@ static int sanitize_ptr_alu(struct bpf_v alu_state |= off_is_imm ? BPF_ALU_IMMEDIATE : 0; alu_state |= ptr_is_dst_reg ? BPF_ALU_SANITIZE_SRC : BPF_ALU_SANITIZE_DST; + + /* Limit pruning on unknown scalars to enable deep search for + * potential masking differences from other program paths. + */ + if (!off_is_imm) + env->explore_alu_limits = true; } err = update_alu_sanitation_state(aux, alu_state, alu_limit); @@ -9088,8 +9094,8 @@ next: } /* Returns true if (rold safe implies rcur safe) */ -static bool regsafe(struct bpf_reg_state *rold, struct bpf_reg_state *rcur, - struct bpf_id_pair *idmap) +static bool regsafe(struct bpf_verifier_env *env, struct bpf_reg_state *rold, + struct bpf_reg_state *rcur, struct bpf_id_pair *idmap) { bool equal; @@ -9115,6 +9121,8 @@ static bool regsafe(struct bpf_reg_state return false; switch (rold->type) { case SCALAR_VALUE: + if (env->explore_alu_limits) + return false; if (rcur->type == SCALAR_VALUE) { if (!rold->precise && !rcur->precise) return true; @@ -9204,9 +9212,8 @@ static bool regsafe(struct bpf_reg_state return false; } -static bool stacksafe(struct bpf_func_state *old, - struct bpf_func_state *cur, - struct bpf_id_pair *idmap) +static bool stacksafe(struct bpf_verifier_env *env, struct bpf_func_state *old, + struct bpf_func_state *cur, struct bpf_id_pair *idmap) { int i, spi; @@ -9251,9 +9258,8 @@ static bool stacksafe(struct bpf_func_st continue; if (old->stack[spi].slot_type[0] != STACK_SPILL) continue; - if (!regsafe(&old->stack[spi].spilled_ptr, - &cur->stack[spi].spilled_ptr, - idmap)) + if (!regsafe(env, &old->stack[spi].spilled_ptr, + &cur->stack[spi].spilled_ptr, idmap)) /* when explored and current stack slot are both storing * spilled registers, check that stored pointers types * are the same as well. @@ -9310,10 +9316,11 @@ static bool func_states_equal(struct bpf 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)) + if (!regsafe(env, &old->regs[i], &cur->regs[i], + env->idmap_scratch)) return false; - if (!stacksafe(old, cur, env->idmap_scratch)) + if (!stacksafe(env, old, cur, env->idmap_scratch)) return false; if (!refsafe(old, cur))