Received: by 2002:ab2:6991:0:b0:1f7:f6c3:9cb1 with SMTP id v17csp169743lqo; Tue, 7 May 2024 16:28:02 -0700 (PDT) X-Forwarded-Encrypted: i=3; AJvYcCVGhcaK7jtofSxBf9A0pfNFDzrJotc8lUfMSeyihQvNJ31eqifTuloJx6oS8BL2cq4Rp6N+Xassx3It+QfDVj/+yJURWBEqHhXQGbbb6w== X-Google-Smtp-Source: AGHT+IHzwVacLANqYzD8M1G+YNxuyhNSFrC5pXHq42tDra3Ftc0bIzWBgnV1UqyryuOVukMjQV3f X-Received: by 2002:a05:6358:9494:b0:183:a0ac:b638 with SMTP id e5c5f4694b2df-192d2a26c01mr143550855d.11.1715124482549; Tue, 07 May 2024 16:28:02 -0700 (PDT) ARC-Seal: i=2; a=rsa-sha256; t=1715124482; cv=pass; d=google.com; s=arc-20160816; b=JqGOrLJCrdz0NZoT8SUzoyT14SrPwGPQIrym7rQy3DQIpNMG1P95lnOl9fBm7z+g6z mUuD9A2zXV+fF8LfSjCqkoGV/lhWGgExfL7NcZwGFGat/ou8+LKhhdgS6BOtvrq5WLa1 io+VHmU61VdIucEDVYDoO9DOuP03Y9ldX7EgQ5iqa9Ye8IpDfm8DBCE1UHK+u/nUSyYH dWfSYPUtLCER0wX+Zq9H0nm5KmyTaUmjAUw2eqG7RnrPaHRVXa9i4/fhaEjwCKa7EnGy FN6rNzvyz0EjKt/VPgb12GIx3bUGyBCnCbv5aWIbeY3nOJkhMZRSpSgY964WIJvbwa60 bTwg== ARC-Message-Signature: i=2; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20160816; h=content-transfer-encoding:mime-version:list-unsubscribe :list-subscribe:list-id:precedence:references:in-reply-to:message-id :date:subject:cc:to:from:dkim-signature; bh=l57Xw+x1GfzcMxmOklKhL+oFbiiBt+95pnHSObxga0o=; fh=Nyw2xfBoT2OZ7DzWvNHYXBDD+l9QG0/LQtGDn7qUWzA=; b=ZoTyP6bepUrajWHtfMIglMnoYdpv06gBDB3135NmpxtW8W01V6B3vaAJIlmaFDt7nU Jsx9gJcNzMsEm42nHoarTAEBfDJhkUsZIwFIsfJ3NeV0sUV5f0Jb6yQ0tYP4dM6XPNRF QiUsPO5yUebgZ5MT7e/b8Nh2gtwIRveiGMzOGc1JozTyol5toUMGkqIMrFKvLukZK4wo vTAxQnZlte73iNSI5qrDBdOCa9v9Qg/LAoZTj/4wwI1zsZOhIYOuDCYar3h8Tm+q1mxd vLv0pmI+qZmH9Jo+F5/DBL26bruF+hfC8J0nQDJCsdleA+EUObQeCBPCn60y6V2ESlpK nq6w==; dara=google.com ARC-Authentication-Results: i=2; mx.google.com; dkim=pass header.i=@kernel.org header.s=k20201202 header.b=ERYejF+P; arc=pass (i=1 dkim=pass dkdomain=kernel.org); spf=pass (google.com: domain of linux-kernel+bounces-172365-linux.lists.archive=gmail.com@vger.kernel.org designates 2604:1380:45e3:2400::1 as permitted sender) smtp.mailfrom="linux-kernel+bounces-172365-linux.lists.archive=gmail.com@vger.kernel.org"; dmarc=pass (p=NONE sp=NONE dis=NONE) header.from=kernel.org Return-Path: Received: from sv.mirrors.kernel.org (sv.mirrors.kernel.org. [2604:1380:45e3:2400::1]) by mx.google.com with ESMTPS id p29-20020a631e5d000000b005dc36761adcsi11708949pgm.175.2024.05.07.16.28.02 for (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Tue, 07 May 2024 16:28:02 -0700 (PDT) Received-SPF: pass (google.com: domain of linux-kernel+bounces-172365-linux.lists.archive=gmail.com@vger.kernel.org designates 2604:1380:45e3:2400::1 as permitted sender) client-ip=2604:1380:45e3:2400::1; Authentication-Results: mx.google.com; dkim=pass header.i=@kernel.org header.s=k20201202 header.b=ERYejF+P; arc=pass (i=1 dkim=pass dkdomain=kernel.org); spf=pass (google.com: domain of linux-kernel+bounces-172365-linux.lists.archive=gmail.com@vger.kernel.org designates 2604:1380:45e3:2400::1 as permitted sender) smtp.mailfrom="linux-kernel+bounces-172365-linux.lists.archive=gmail.com@vger.kernel.org"; dmarc=pass (p=NONE sp=NONE dis=NONE) header.from=kernel.org Received: from smtp.subspace.kernel.org (wormhole.subspace.kernel.org [52.25.139.140]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by sv.mirrors.kernel.org (Postfix) with ESMTPS id A00BB281D80 for ; Tue, 7 May 2024 23:27:41 +0000 (UTC) Received: from localhost.localdomain (localhost.localdomain [127.0.0.1]) by smtp.subspace.kernel.org (Postfix) with ESMTP id 5158713E3F9; Tue, 7 May 2024 23:08:45 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b="ERYejF+P" Received: from smtp.kernel.org (aws-us-west-2-korg-mail-1.web.codeaurora.org [10.30.226.201]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 4B22A13E054; Tue, 7 May 2024 23:08:44 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=10.30.226.201 ARC-Seal:i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1715123324; cv=none; b=GAXv2oy7yo7MzXOQDgOI6jOgSrVZb/NFfGeBJg4K+2jiKxj4ZOmFP7hPShny3zpBJpvPPWTm2XOwqXR7WNdkxN7HRqnPBjycAX6P4bJaHzgAK2W0tyfuZ+I/kUrug9crdJjQAxtCmP4+Xt8GvcqAdpsoPNodSCuwRc51/a4/Kks= ARC-Message-Signature:i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1715123324; c=relaxed/simple; bh=94NJJLJqQOWhkUetOC3eDu9jUS6rglVC4ci4xw4oJRo=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=hAESezqxNfsBqkuTImV1pIazHZBfCqgK6FIH9tIKGVxrlXUf778g8q7qOX+rnuikZ4CGoE+Mb6KIKlfwxv3CiEUykaUrqDRH0kB2yPSbO8bqRc7/XQT3h2sen2uGRsx0uN/swaARfMeA9PcGSnISYxFuOowzpvtk0va7dF0dTKU= ARC-Authentication-Results:i=1; smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b=ERYejF+P; arc=none smtp.client-ip=10.30.226.201 Received: by smtp.kernel.org (Postfix) with ESMTPSA id 47F18C4AF67; Tue, 7 May 2024 23:08:42 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1715123324; bh=94NJJLJqQOWhkUetOC3eDu9jUS6rglVC4ci4xw4oJRo=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=ERYejF+PuzXC6k3axBPQpTt5HS4KqufOQqq8hkaoAGSfUPTihhkW6EvHvXN66uWxV oM0aV4WeBDOeYqbMj0gphyWw5FYyXJ1PUmifiCTTDkpS9f048JQIN4aABN8YTUs6tu e/sYkAuUyfi7SEf/7R1bCeFYz+9Znon7q6/VUZIQJP1H+GpiNThactdWzjKonCC0Ic Hy6wS1fRVSAACQBma/BLKJMeP6ULAvpXRXRa/bTFNu26V/ZmivzHqIYG9Ovf1BeCO+ V3DoWL3yEYOyvmwrVhXBl9dN83NVu6TrM0GH2vc6jtnEPteKWpUg8a7a6eZgOM7q89 XizA2bJ5c8PXw== From: Sasha Levin To: linux-kernel@vger.kernel.org, stable@vger.kernel.org Cc: Puranjay Mohan , Alexei Starovoitov , Sasha Levin , daniel@iogearbox.net, andrii@kernel.org, davem@davemloft.net, dsahern@kernel.org, tglx@linutronix.de, mingo@redhat.com, bp@alien8.de, dave.hansen@linux.intel.com, x86@kernel.org, bpf@vger.kernel.org, netdev@vger.kernel.org Subject: [PATCH AUTOSEL 6.8 23/52] bpf, x86: Fix PROBE_MEM runtime load check Date: Tue, 7 May 2024 19:06:49 -0400 Message-ID: <20240507230800.392128-23-sashal@kernel.org> X-Mailer: git-send-email 2.43.0 In-Reply-To: <20240507230800.392128-1-sashal@kernel.org> References: <20240507230800.392128-1-sashal@kernel.org> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 X-stable: review X-Patchwork-Hint: Ignore X-stable-base: Linux 6.8.9 Content-Transfer-Encoding: 8bit From: Puranjay Mohan [ Upstream commit b599d7d26d6ad1fc9975218574bc2ca6d0293cfd ] When a load is marked PROBE_MEM - e.g. due to PTR_UNTRUSTED access - the address being loaded from is not necessarily valid. The BPF jit sets up exception handlers for each such load which catch page faults and 0 out the destination register. If the address for the load is outside kernel address space, the load will escape the exception handling and crash the kernel. To prevent this from happening, the emits some instruction to verify that addr is > end of userspace addresses. x86 has a legacy vsyscall ABI where a page at address 0xffffffffff600000 is mapped with user accessible permissions. The addresses in this page are considered userspace addresses by the fault handler. Therefore, a BPF program accessing this page will crash the kernel. This patch fixes the runtime checks to also check that the PROBE_MEM address is below VSYSCALL_ADDR. Example BPF program: SEC("fentry/tcp_v4_connect") int BPF_PROG(fentry_tcp_v4_connect, struct sock *sk) { *(volatile unsigned long *)&sk->sk_tsq_flags; return 0; } BPF Assembly: 0: (79) r1 = *(u64 *)(r1 +0) 1: (79) r1 = *(u64 *)(r1 +344) 2: (b7) r0 = 0 3: (95) exit x86-64 JIT ========== BEFORE AFTER ------ ----- 0: nopl 0x0(%rax,%rax,1) 0: nopl 0x0(%rax,%rax,1) 5: xchg %ax,%ax 5: xchg %ax,%ax 7: push %rbp 7: push %rbp 8: mov %rsp,%rbp 8: mov %rsp,%rbp b: mov 0x0(%rdi),%rdi b: mov 0x0(%rdi),%rdi ------------------------------------------------------------------------------- f: movabs $0x100000000000000,%r11 f: movabs $0xffffffffff600000,%r10 19: add $0x2a0,%rdi 19: mov %rdi,%r11 20: cmp %r11,%rdi 1c: add $0x2a0,%r11 23: jae 0x0000000000000029 23: sub %r10,%r11 25: xor %edi,%edi 26: movabs $0x100000000a00000,%r10 27: jmp 0x000000000000002d 30: cmp %r10,%r11 29: mov 0x0(%rdi),%rdi 33: ja 0x0000000000000039 --------------------------------\ 35: xor %edi,%edi 2d: xor %eax,%eax \ 37: jmp 0x0000000000000040 2f: leave \ 39: mov 0x2a0(%rdi),%rdi 30: ret \-------------------------------------------- 40: xor %eax,%eax 42: leave 43: ret Signed-off-by: Puranjay Mohan Link: https://lore.kernel.org/r/20240424100210.11982-3-puranjay@kernel.org Signed-off-by: Alexei Starovoitov Signed-off-by: Sasha Levin --- arch/x86/net/bpf_jit_comp.c | 57 ++++++++++++++++--------------------- 1 file changed, 25 insertions(+), 32 deletions(-) diff --git a/arch/x86/net/bpf_jit_comp.c b/arch/x86/net/bpf_jit_comp.c index df484885ccd4a..f415c2cf53582 100644 --- a/arch/x86/net/bpf_jit_comp.c +++ b/arch/x86/net/bpf_jit_comp.c @@ -1585,36 +1585,41 @@ st: if (is_imm8(insn->off)) if (BPF_MODE(insn->code) == BPF_PROBE_MEM || BPF_MODE(insn->code) == BPF_PROBE_MEMSX) { /* Conservatively check that src_reg + insn->off is a kernel address: - * src_reg + insn->off >= TASK_SIZE_MAX + PAGE_SIZE - * src_reg is used as scratch for src_reg += insn->off and restored - * after emit_ldx if necessary + * src_reg + insn->off > TASK_SIZE_MAX + PAGE_SIZE + * and + * src_reg + insn->off < VSYSCALL_ADDR */ - u64 limit = TASK_SIZE_MAX + PAGE_SIZE; + u64 limit = TASK_SIZE_MAX + PAGE_SIZE - VSYSCALL_ADDR; u8 *end_of_jmp; - /* At end of these emitted checks, insn->off will have been added - * to src_reg, so no need to do relative load with insn->off offset - */ - insn_off = 0; + /* movabsq r10, VSYSCALL_ADDR */ + emit_mov_imm64(&prog, BPF_REG_AX, (long)VSYSCALL_ADDR >> 32, + (u32)(long)VSYSCALL_ADDR); - /* movabsq r11, limit */ - EMIT2(add_1mod(0x48, AUX_REG), add_1reg(0xB8, AUX_REG)); - EMIT((u32)limit, 4); - EMIT(limit >> 32, 4); + /* mov src_reg, r11 */ + EMIT_mov(AUX_REG, src_reg); if (insn->off) { - /* add src_reg, insn->off */ - maybe_emit_1mod(&prog, src_reg, true); - EMIT2_off32(0x81, add_1reg(0xC0, src_reg), insn->off); + /* add r11, insn->off */ + maybe_emit_1mod(&prog, AUX_REG, true); + EMIT2_off32(0x81, add_1reg(0xC0, AUX_REG), insn->off); } - /* cmp src_reg, r11 */ - maybe_emit_mod(&prog, src_reg, AUX_REG, true); - EMIT2(0x39, add_2reg(0xC0, src_reg, AUX_REG)); + /* sub r11, r10 */ + maybe_emit_mod(&prog, AUX_REG, BPF_REG_AX, true); + EMIT2(0x29, add_2reg(0xC0, AUX_REG, BPF_REG_AX)); + + /* movabsq r10, limit */ + emit_mov_imm64(&prog, BPF_REG_AX, (long)limit >> 32, + (u32)(long)limit); + + /* cmp r10, r11 */ + maybe_emit_mod(&prog, AUX_REG, BPF_REG_AX, true); + EMIT2(0x39, add_2reg(0xC0, AUX_REG, BPF_REG_AX)); - /* if unsigned '>=', goto load */ - EMIT2(X86_JAE, 0); + /* if unsigned '>', goto load */ + EMIT2(X86_JA, 0); end_of_jmp = prog; /* xor dst_reg, dst_reg */ @@ -1640,18 +1645,6 @@ st: if (is_imm8(insn->off)) /* populate jmp_offset for JMP above */ start_of_ldx[-1] = prog - start_of_ldx; - if (insn->off && src_reg != dst_reg) { - /* sub src_reg, insn->off - * Restore src_reg after "add src_reg, insn->off" in prev - * if statement. But if src_reg == dst_reg, emit_ldx - * above already clobbered src_reg, so no need to restore. - * If add src_reg, insn->off was unnecessary, no need to - * restore either. - */ - maybe_emit_1mod(&prog, src_reg, true); - EMIT2_off32(0x81, add_1reg(0xE8, src_reg), insn->off); - } - if (!bpf_prog->aux->extable) break; -- 2.43.0