From patchwork Fri Oct 5 16:17:59 2018 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Jann Horn X-Patchwork-Id: 979573 X-Patchwork-Delegate: bpf@iogearbox.net Return-Path: X-Original-To: patchwork-incoming-netdev@ozlabs.org Delivered-To: patchwork-incoming-netdev@ozlabs.org Authentication-Results: ozlabs.org; spf=none (mailfrom) smtp.mailfrom=vger.kernel.org (client-ip=209.132.180.67; helo=vger.kernel.org; envelope-from=netdev-owner@vger.kernel.org; receiver=) Authentication-Results: ozlabs.org; dmarc=pass (p=reject dis=none) header.from=google.com Authentication-Results: ozlabs.org; dkim=pass (2048-bit key; unprotected) header.d=google.com header.i=@google.com header.b="uYs0sVZ6"; dkim-atps=neutral Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by ozlabs.org (Postfix) with ESMTP id 42RZgj2JcLzB4MW for ; Sat, 6 Oct 2018 02:18:41 +1000 (AEST) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1730425AbeJEXR6 (ORCPT ); Fri, 5 Oct 2018 19:17:58 -0400 Received: from mail-qk1-f201.google.com ([209.85.222.201]:42204 "EHLO mail-qk1-f201.google.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1729536AbeJEXR5 (ORCPT ); Fri, 5 Oct 2018 19:17:57 -0400 Received: by mail-qk1-f201.google.com with SMTP id m63-v6so8798145qkb.9 for ; Fri, 05 Oct 2018 09:18:34 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=20161025; h=date:message-id:mime-version:subject:from:to:cc; bh=cQ9JSSsF2O+YiukHbjWxYbVnwmc9rU5fCIU4mPWxpJI=; b=uYs0sVZ69R9D36DrZ452Zp7wC9xXDCQoIJnzTvqQ8SbsniUC/XqmpyNT0l/m+nQWKC rqi0Ol+kot/wyv/qE6jgxDEVXYSnatnP+X4aArvqiU+mnG1KqEcSbiHw7O/Po0tI3BST WQYpr3BAFG9+FdJlETUbtMMEoqsY+kll5fNL5bw1cB+gI4lWiYHuRFqlMHa6Cv/1gz6c BD76B0I5Fwi2tLmfP6dzYyVo8ohwmCjRRx44NJic6ZeEZExGz0KWAWEn2rMb3unPr++j 4Whh8pa1+ybAAQL9JdzRG7e9V3LvWxZfuZb6OKLopxCJYZb7vCo9yrdvLBLq1ouExcyf bXmg== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:date:message-id:mime-version:subject:from:to:cc; bh=cQ9JSSsF2O+YiukHbjWxYbVnwmc9rU5fCIU4mPWxpJI=; b=RavdFs/FSap5x9kplbApu7qbhmHLzKb+ffPNBgO1wY2I6Gv95TCLabQ/Grv9nazSLe XIhbGTumeLOhtAQSJFlrUJujJcT2n5d9bKQ7mQuxpS3gDQQD+18Fd5TgLdSVRTylXot2 Vuyr3IP/LKI0uu9HBzo149Hr80eFRGzxDG0SZBRc6EOgk1rcKu/zvJh4vqWEgrxeX7Aa bmwUxNs73XxqAIubrB4isGhi55V05kx0VFrlgyHV6zny+2LgUa1GrEFonTXjX/K6b45f 0/Zs22xE/9sVX50ZrXf0NW4tXSYEyfwY2Cm3qmjgH9sGOMIx++rrJeOuWVDiHsPERpWo zYtQ== X-Gm-Message-State: ABuFfoiSyQ4sosOhwSzw3r6+xWfkkGJE15TPPeltjljcCekhNBTwQ7t2 6CxpLvtiKdYZGOvDiG9XLxAQFrhtMA== X-Google-Smtp-Source: ACcGV62q5xA+TqpstgQh+c9L2NoGHvYLPQZVXo4Wb+VVjARN65KyqgBk92+OKsahAFN0S6s2UdwS8pYFRA== X-Received: by 2002:a0c:be06:: with SMTP id k6-v6mr8970698qvg.4.1538756313719; Fri, 05 Oct 2018 09:18:33 -0700 (PDT) Date: Fri, 5 Oct 2018 18:17:59 +0200 Message-Id: <20181005161759.177992-1-jannh@google.com> Mime-Version: 1.0 X-Mailer: git-send-email 2.19.0.605.g01d371f741-goog Subject: [PATCH] bpf: 32-bit RSH verification must truncate input before the ALU op From: Jann Horn To: Daniel Borkmann , Alexei Starovoitov , netdev@vger.kernel.org, jannh@google.com Cc: "David S. Miller" , linux-kernel@vger.kernel.org Sender: netdev-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: netdev@vger.kernel.org When I wrote commit 468f6eafa6c4 ("bpf: fix 32-bit ALU op verification"), I assumed that, in order to emulate 64-bit arithmetic with 32-bit logic, it is sufficient to just truncate the output to 32 bits; and so I just moved the register size coercion that used to be at the start of the function to the end of the function. That assumption is true for almost every op, but not for 32-bit right shifts, because those can propagate information towards the least significant bit. Fix it by always truncating inputs for 32-bit ops to 32 bits. Also get rid of the coerce_reg_to_size() after the ALU op, since that has no effect. Fixes: 468f6eafa6c4 ("bpf: fix 32-bit ALU op verification") Acked-by: Daniel Borkmann Signed-off-by: Jann Horn Acked-by: Edward Cree --- kernel/bpf/verifier.c | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/kernel/bpf/verifier.c b/kernel/bpf/verifier.c index bb07e74b34a2..465952a8e465 100644 --- a/kernel/bpf/verifier.c +++ b/kernel/bpf/verifier.c @@ -2896,6 +2896,15 @@ static int adjust_scalar_min_max_vals(struct bpf_verifier_env *env, u64 umin_val, umax_val; u64 insn_bitness = (BPF_CLASS(insn->code) == BPF_ALU64) ? 64 : 32; + if (insn_bitness == 32) { + /* Relevant for 32-bit RSH: Information can propagate towards + * LSB, so it isn't sufficient to only truncate the output to + * 32 bits. + */ + coerce_reg_to_size(dst_reg, 4); + coerce_reg_to_size(&src_reg, 4); + } + smin_val = src_reg.smin_value; smax_val = src_reg.smax_value; umin_val = src_reg.umin_value; @@ -3131,7 +3140,6 @@ static int adjust_scalar_min_max_vals(struct bpf_verifier_env *env, if (BPF_CLASS(insn->code) != BPF_ALU64) { /* 32-bit ALU ops are (32,32)->32 */ coerce_reg_to_size(dst_reg, 4); - coerce_reg_to_size(&src_reg, 4); } __reg_deduce_bounds(dst_reg);