Received: by 2002:a05:6520:1682:b0:147:d1a0:b502 with SMTP id ck2csp5597312lkb; Mon, 11 Oct 2021 09:39:54 -0700 (PDT) X-Google-Smtp-Source: ABdhPJxichpS1YkY1i/OOFkoUoKTwlhUCkJ0X/Cdbawnt1GIXCgw+kxokPJoDaUk2dbqFRJ4L9RQ X-Received: by 2002:a17:906:5e17:: with SMTP id n23mr26456599eju.258.1633970394154; Mon, 11 Oct 2021 09:39:54 -0700 (PDT) ARC-Seal: i=1; a=rsa-sha256; t=1633970394; cv=none; d=google.com; s=arc-20160816; b=Ox9wFreeT9HwqXd2Zu/fkZcpI4yVIkMWG9O7Goow59Aivm3b9QqkEJkWICAA905lRr bJ2BQzy0O6DF7NZesDQpb9T1ZwRMDobcaH/bHGQdOk1qjXr+v5miJpoLulrvueU2ocvG 8rn0CrgPFPsERFmlZZU5N5qFuyLU7gD5QHb54OScq9/VyrZN5rY9LH3zVVk4Xet7/tN2 oV1y6qzgOt8oPFVvpbl2Z20Q4yhMhrTviVQGsmtYuqMWqBBLMT5o9g8mb7ng8nLoYgoz uVPM5xnHPKYF179gv/IYycRDss1fV1kMGJPeAUO1OBnMETiZ7dadSvjV9g2pOxCDIO0h U7BQ== 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=SsRfZfShRcXZyAgVQJ0AT3/dgKfAowBV0ci2cxEC9+c=; b=Yb2AcbjygkNMqJ/AcrxAOZxYFoNMkAwQSHbjYPgE8sSLUwZMuGIxhJeHFr8lNAVP1T aFPhiZln8+p+OaNnZlu1fbhkXiprG4QPUwO2TzszegOoktUCpzmPPWkbjH+h7DRHooNx NJn41KI9zPOvIqHDb6auyAXj3uSwN4gGWpJaFfcI+eyX16hdrYPAL9/D5znrL9/WYuT+ StgiNm8oe+73SwHtXSBluykR3cfCGbgpoaQGyn/0SwkUFVz/GjFVx3IeRoyd23f6+qtL 0ySsyWSd5icQRBupf/U3JAuD6DLcbU90VaSmGPAMXECjXVTdAK1p8sN+VhbVrQpjhswM v7Cw== ARC-Authentication-Results: i=1; mx.google.com; dkim=pass header.i=@linuxfoundation.org header.s=korg header.b=umcXZu3y; 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 i15si11466336ejy.479.2021.10.11.09.39.30; Mon, 11 Oct 2021 09:39:54 -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=umcXZu3y; 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 S242932AbhJKOTD (ORCPT + 99 others); Mon, 11 Oct 2021 10:19:03 -0400 Received: from mail.kernel.org ([198.145.29.99]:39036 "EHLO mail.kernel.org" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S243060AbhJKOPy (ORCPT ); Mon, 11 Oct 2021 10:15:54 -0400 Received: by mail.kernel.org (Postfix) with ESMTPSA id 248D560F6E; Mon, 11 Oct 2021 14:05:46 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=linuxfoundation.org; s=korg; t=1633961146; bh=IPGid/75yXg+7JRb6pRPQpFWWSlSgrLrtMJn72uwovM=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=umcXZu3yDsznqUuUrzlOXb06VquHSnJ9wm/vJCxM4k9zlgBpErzFOuSCRzgfR1oAZ vJx3knVmAxraQApb2gJJZD7HDMJRszMCofMMOPFdHVdpUU5pTrd22MAU5pBkKm+yp2 daU0u2BvIPAdqMuuAoT243XPTC5qChCapKzvT8UQ= From: Greg Kroah-Hartman To: linux-kernel@vger.kernel.org Cc: Greg Kroah-Hartman , stable@vger.kernel.org, Johan Almbladh , Daniel Borkmann , Sasha Levin Subject: [PATCH 4.19 12/28] bpf, arm: Fix register clobbering in div/mod implementation Date: Mon, 11 Oct 2021 15:47:02 +0200 Message-Id: <20211011134641.114041074@linuxfoundation.org> X-Mailer: git-send-email 2.33.0 In-Reply-To: <20211011134640.711218469@linuxfoundation.org> References: <20211011134640.711218469@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: Johan Almbladh [ Upstream commit 79e3445b38e0cab94264a3894c0c3d57c930b97e ] On ARM CPUs that lack div/mod instructions, ALU32 BPF_DIV and BPF_MOD are implemented using a call to a helper function. Before, the emitted code for those function calls failed to preserve caller-saved ARM registers. Since some of those registers happen to be mapped to BPF registers, it resulted in eBPF register values being overwritten. This patch emits code to push and pop the remaining caller-saved ARM registers r2-r3 into the stack during the div/mod function call. ARM registers r0-r1 are used as arguments and return value, and those were already saved and restored correctly. Fixes: 39c13c204bb1 ("arm: eBPF JIT compiler") Signed-off-by: Johan Almbladh Signed-off-by: Daniel Borkmann Signed-off-by: Sasha Levin --- arch/arm/net/bpf_jit_32.c | 19 +++++++++++++++++++ 1 file changed, 19 insertions(+) diff --git a/arch/arm/net/bpf_jit_32.c b/arch/arm/net/bpf_jit_32.c index 79b12e744537..dade3a3ba666 100644 --- a/arch/arm/net/bpf_jit_32.c +++ b/arch/arm/net/bpf_jit_32.c @@ -39,6 +39,10 @@ * +-----+ * |RSVD | JIT scratchpad * current ARM_SP => +-----+ <= (BPF_FP - STACK_SIZE + SCRATCH_SIZE) + * | ... | caller-saved registers + * +-----+ + * | ... | arguments passed on stack + * ARM_SP during call => +-----| * | | * | ... | Function call stack * | | @@ -66,6 +70,12 @@ * * When popping registers off the stack at the end of a BPF function, we * reference them via the current ARM_FP register. + * + * Some eBPF operations are implemented via a call to a helper function. + * Such calls are "invisible" in the eBPF code, so it is up to the calling + * program to preserve any caller-saved ARM registers during the call. The + * JIT emits code to push and pop those registers onto the stack, immediately + * above the callee stack frame. */ #define CALLEE_MASK (1 << ARM_R4 | 1 << ARM_R5 | 1 << ARM_R6 | \ 1 << ARM_R7 | 1 << ARM_R8 | 1 << ARM_R9 | \ @@ -73,6 +83,8 @@ #define CALLEE_PUSH_MASK (CALLEE_MASK | 1 << ARM_LR) #define CALLEE_POP_MASK (CALLEE_MASK | 1 << ARM_PC) +#define CALLER_MASK (1 << ARM_R0 | 1 << ARM_R1 | 1 << ARM_R2 | 1 << ARM_R3) + enum { /* Stack layout - these are offsets from (top of stack - 4) */ BPF_R2_HI, @@ -467,6 +479,7 @@ static inline int epilogue_offset(const struct jit_ctx *ctx) static inline void emit_udivmod(u8 rd, u8 rm, u8 rn, struct jit_ctx *ctx, u8 op) { + const int exclude_mask = BIT(ARM_R0) | BIT(ARM_R1); const s8 *tmp = bpf2a32[TMP_REG_1]; #if __LINUX_ARM_ARCH__ == 7 @@ -498,11 +511,17 @@ static inline void emit_udivmod(u8 rd, u8 rm, u8 rn, struct jit_ctx *ctx, u8 op) emit(ARM_MOV_R(ARM_R0, rm), ctx); } + /* Push caller-saved registers on stack */ + emit(ARM_PUSH(CALLER_MASK & ~exclude_mask), ctx); + /* Call appropriate function */ emit_mov_i(ARM_IP, op == BPF_DIV ? (u32)jit_udiv32 : (u32)jit_mod32, ctx); emit_blx_r(ARM_IP, ctx); + /* Restore caller-saved registers from stack */ + emit(ARM_POP(CALLER_MASK & ~exclude_mask), ctx); + /* Save return value */ if (rd != ARM_R0) emit(ARM_MOV_R(rd, ARM_R0), ctx); -- 2.33.0