From patchwork Thu Jan 4 14:01:15 2018 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Seth Forshee X-Patchwork-Id: 855601 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Authentication-Results: ozlabs.org; spf=none (mailfrom) smtp.mailfrom=lists.ubuntu.com (client-ip=91.189.94.19; helo=huckleberry.canonical.com; envelope-from=kernel-team-bounces@lists.ubuntu.com; receiver=) Received: from huckleberry.canonical.com (huckleberry.canonical.com [91.189.94.19]) by ozlabs.org (Postfix) with ESMTP id 3zC8c45rsBz9t3Z; Fri, 5 Jan 2018 01:01:38 +1100 (AEDT) Received: from localhost ([127.0.0.1] helo=huckleberry.canonical.com) by huckleberry.canonical.com with esmtp (Exim 4.86_2) (envelope-from ) id 1eX65L-0004rx-IR; Thu, 04 Jan 2018 14:01:31 +0000 Received: from youngberry.canonical.com ([91.189.89.112]) by huckleberry.canonical.com with esmtps (TLS1.0:DHE_RSA_AES_128_CBC_SHA1:128) (Exim 4.86_2) (envelope-from ) id 1eX65J-0004rG-9s for kernel-team@lists.ubuntu.com; Thu, 04 Jan 2018 14:01:29 +0000 Received: from mail-io0-f198.google.com ([209.85.223.198]) by youngberry.canonical.com with esmtps (TLS1.0:RSA_AES_128_CBC_SHA1:16) (Exim 4.76) (envelope-from ) id 1eX65I-0002A2-W3 for kernel-team@lists.ubuntu.com; Thu, 04 Jan 2018 14:01:29 +0000 Received: by mail-io0-f198.google.com with SMTP id 79so1847608iou.19 for ; Thu, 04 Jan 2018 06:01:28 -0800 (PST) X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:from:to:subject:date:message-id:in-reply-to :references; bh=ekShnpzqzNy63znnikHuiEQbc4zbhcY+0Kv15YbD5JQ=; b=WbedVReh77U1RXKeW+6ekYQn+ptljLF497fVP+b16oohVBNATgetJ2sbL9ORxAkwJ/ tYGt2yJy/HPmIx+NhTHjE7teE76OnpOZBP1gBlh1/L/sUe+8oNi7Snji7LAJWMBBW8Fn lw4tV51J9qhGpfSVisWZ0jo7WFVGSGUkpfEXOIEDBB/qg/SknAjeyInLdus3b667djni o/aEiTtZS7DfBhH8rIYr23fIX2hDlqQaZRyMBpBfneUpBy3cpsUXksf5D0QSK6mHsW7Z TJn8b4NzTuCx7NhrZS7MSTCMF4wjzxSHwIY0WWRBoSIibjlGYQvxI1/NnH/4jZi3jTSh Xnuw== X-Gm-Message-State: AKGB3mKvJHZUP7IWSUmh/RDzaDVwhXxptfxaDx6A7ogaU4G1T1Pi4rlU tibJg6SYjaAtRimUSitoqFjjftv1EcHK4VPNfrNRkeVpC+DCAOmZ3BoOOeuAdJkd0NRi6EJxNa1 YtJ5pK+mDgYZ+Lw0p8dYEqmRSZOrr9lYbvhsI5yrC0Q== X-Received: by 10.107.97.3 with SMTP id v3mr5653018iob.283.1515074487664; Thu, 04 Jan 2018 06:01:27 -0800 (PST) X-Google-Smtp-Source: ACJfBovVpTHN6W14d2V+cowAYEBDm79FdFntD3UTVSkdwFdqO9NEpMhbYlvY1XnUfsE6gyNrdCYPtA== X-Received: by 10.107.97.3 with SMTP id v3mr5652980iob.283.1515074487316; Thu, 04 Jan 2018 06:01:27 -0800 (PST) Received: from localhost ([2605:a601:aae:1b20:6cc2:cccd:da95:a96c]) by smtp.gmail.com with ESMTPSA id z188sm2168320itb.28.2018.01.04.06.01.26 for (version=TLS1_2 cipher=ECDHE-RSA-CHACHA20-POLY1305 bits=256/256); Thu, 04 Jan 2018 06:01:26 -0800 (PST) From: Seth Forshee To: kernel-team@lists.ubuntu.com Subject: [PATCH 1/2][X] bpf: fix incorrect sign extension in check_alu_op() Date: Thu, 4 Jan 2018 08:01:15 -0600 Message-Id: <20180104140124.2515-2-seth.forshee@canonical.com> X-Mailer: git-send-email 2.14.1 In-Reply-To: <20180104140124.2515-1-seth.forshee@canonical.com> References: <20180104140124.2515-1-seth.forshee@canonical.com> X-BeenThere: kernel-team@lists.ubuntu.com X-Mailman-Version: 2.1.20 Precedence: list List-Id: Kernel team discussions List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , MIME-Version: 1.0 Errors-To: kernel-team-bounces@lists.ubuntu.com Sender: "kernel-team" From: Jann Horn [ Upstream commit 95a762e2c8c942780948091f8f2a4f32fce1ac6f ] Distinguish between BPF_ALU64|BPF_MOV|BPF_K (load 32-bit immediate, sign-extended to 64-bit) and BPF_ALU|BPF_MOV|BPF_K (load 32-bit immediate, zero-padded to 64-bit); only perform sign extension in the first case. Starting with v4.14, this is exploitable by unprivileged users as long as the unprivileged_bpf_disabled sysctl isn't set. Debian assigned CVE-2017-16995 for this issue. v3: - add CVE number (Ben Hutchings) Fixes: 484611357c19 ("bpf: allow access into map value arrays") Signed-off-by: Jann Horn Acked-by: Edward Cree Signed-off-by: Alexei Starovoitov Signed-off-by: Daniel Borkmann CVE-2017-16995 [ saf: Backport to 4.4. Include partial backports of 4923ec0b10d9 ("bpf: simplify verifier register state assignments") and 969bf05eb3ce ("bpf: direct packet access") to extend reg_state.imm to 64-bit. ] Signed-off-by: Seth Forshee --- kernel/bpf/verifier.c | 24 +++++++++++++++++++----- 1 file changed, 19 insertions(+), 5 deletions(-) diff --git a/kernel/bpf/verifier.c b/kernel/bpf/verifier.c index eb759f5008b8..74ff7218caa0 100644 --- a/kernel/bpf/verifier.c +++ b/kernel/bpf/verifier.c @@ -142,7 +142,7 @@ struct reg_state { enum bpf_reg_type type; union { /* valid when type == CONST_IMM | PTR_TO_STACK */ - int imm; + s64 imm; /* valid when type == CONST_PTR_TO_MAP | PTR_TO_MAP_VALUE | * PTR_TO_MAP_VALUE_OR_NULL @@ -250,7 +250,7 @@ static void print_verifier_state(struct verifier_env *env) continue; verbose(" R%d=%s", i, reg_type_str[t]); if (t == CONST_IMM || t == PTR_TO_STACK) - verbose("%d", env->cur_state.regs[i].imm); + verbose("%lld", env->cur_state.regs[i].imm); else if (t == CONST_PTR_TO_MAP || t == PTR_TO_MAP_VALUE || t == PTR_TO_MAP_VALUE_OR_NULL) verbose("(ks=%d,vs=%d)", @@ -478,7 +478,6 @@ static void init_reg_state(struct reg_state *regs) for (i = 0; i < MAX_BPF_REG; i++) { regs[i].type = NOT_INIT; regs[i].imm = 0; - regs[i].map_ptr = NULL; } /* frame pointer */ @@ -493,7 +492,6 @@ static void mark_reg_unknown_value(struct reg_state *regs, u32 regno) BUG_ON(regno >= MAX_BPF_REG); regs[regno].type = UNKNOWN_VALUE; regs[regno].imm = 0; - regs[regno].map_ptr = NULL; } enum reg_arg_type { @@ -741,6 +739,15 @@ static int check_mem_access(struct verifier_env *env, u32 regno, int off, regno, reg_type_str[state->regs[regno].type]); return -EACCES; } + + if (!err && size <= 2 && value_regno >= 0 && env->allow_ptr_leaks && + state->regs[value_regno].type == UNKNOWN_VALUE) { + /* 1 or 2 byte load zero-extends, determine the number of + * zero upper bits. Not doing it fo 4 byte load, since + * such values cannot be added to ptr_to_packet anyway. + */ + state->regs[value_regno].imm = 64 - size * 8; + } return err; } @@ -1110,8 +1117,15 @@ static int check_alu_op(struct verifier_env *env, struct bpf_insn *insn) /* case: R = imm * remember the value we stored into this reg */ + u64 imm; + + if (BPF_CLASS(insn->code) == BPF_ALU64) + imm = insn->imm; + else + imm = (u32)insn->imm; + regs[insn->dst_reg].type = CONST_IMM; - regs[insn->dst_reg].imm = insn->imm; + regs[insn->dst_reg].imm = imm; } } else if (opcode > BPF_END) {