Received: by 10.223.185.116 with SMTP id b49csp1287348wrg; Wed, 21 Feb 2018 15:55:37 -0800 (PST) X-Google-Smtp-Source: AH8x226XGho4D+x5RuxqhtJy8zZtSoNhGy8OWPf/sh8BDSZC4SHrZy66YK83L9Hg340/2LTkG6/A X-Received: by 10.99.173.73 with SMTP id y9mr4008162pgo.432.1519257337769; Wed, 21 Feb 2018 15:55:37 -0800 (PST) ARC-Seal: i=1; a=rsa-sha256; t=1519257337; cv=none; d=google.com; s=arc-20160816; b=iIc+3VCRkLzCL/2MoZh9uSDBJIbzZluL1/ywAUnfsDclrY5/19/4Te2R14nM9oJ07k qDCn+vf5uuacD8O9E7JdNwkhGryH9G74j2fv8C8PGxoPLpgtg/BaRI/7Jf6xSPamNRk+ IyelUMFVMOXk2cYCCoNTsju3OEzcpVUhyvyqFK44okloAogyLlbdWcrjZqzSVLHB1C1U +RS0MEEElKo2wKAhAE8yWGO5B0R9nWk640GcOLhzBFXsr7obokLenGpE8USvtslz9rck rLRwYCoCocUVSgVqKvJlPRF0nc27zsvC5Y0eboCGXfKnMGJhJ98w7emyxY9a6PLY6hjK L2MQ== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20160816; h=list-id:precedence:sender:content-transfer-encoding :content-language:in-reply-to:mime-version:user-agent:date :message-id:from:references:cc:to:subject:arc-authentication-results; bh=0WlztGgbQii/9TgilIMvLLbvNEk7PCw4zc49qg8p8Xo=; b=Q9upQ3uFxlsvYaYolgPsWFLgaj9+MEhbLNBoZtkLa4wT7Zsh2SZRED4VOp38f+LoKw Ap2aqsf0X1AoLqnA/yt8h7KkkWXFuJHor8YOji7q3rLkEXw00qeT818Cxbq/CNx0POHg vVZrIbpfaPvryd6D/n7HRGSTcztzVkgIJSUA1+51SOQNx4ICilzubNnNUuCYzlArhsCu 97ikMK1jh4zwnEd+FZaOYWs9b/bqKPnP9ooVO/t6Co0XxFFHRkCdbNykn7+oFKPqVKRi bR2WL8kMfJdWPhg4FUQ1FHdAB2jgQ6qeCvvHD4/RlYhT/JpOHqGk5Asj3iw9q/RtG/rg 95dA== ARC-Authentication-Results: i=1; mx.google.com; spf=pass (google.com: best guess record for domain of linux-kernel-owner@vger.kernel.org designates 209.132.180.67 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org; dmarc=fail (p=NONE sp=NONE dis=NONE) header.from=redhat.com Return-Path: Received: from vger.kernel.org (vger.kernel.org. [209.132.180.67]) by mx.google.com with ESMTP id i125si3477405pfb.74.2018.02.21.15.55.23; Wed, 21 Feb 2018 15:55:37 -0800 (PST) Received-SPF: pass (google.com: best guess record for domain of linux-kernel-owner@vger.kernel.org designates 209.132.180.67 as permitted sender) client-ip=209.132.180.67; Authentication-Results: mx.google.com; spf=pass (google.com: best guess record for domain of linux-kernel-owner@vger.kernel.org designates 209.132.180.67 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org; dmarc=fail (p=NONE sp=NONE dis=NONE) header.from=redhat.com Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1751448AbeBUXxx (ORCPT + 99 others); Wed, 21 Feb 2018 18:53:53 -0500 Received: from mail-ot0-f195.google.com ([74.125.82.195]:33169 "EHLO mail-ot0-f195.google.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1750752AbeBUXxu (ORCPT ); Wed, 21 Feb 2018 18:53:50 -0500 Received: by mail-ot0-f195.google.com with SMTP id k7so2392104otj.0 for ; Wed, 21 Feb 2018 15:53:50 -0800 (PST) X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:subject:to:cc:references:from:message-id:date :user-agent:mime-version:in-reply-to:content-language :content-transfer-encoding; bh=0WlztGgbQii/9TgilIMvLLbvNEk7PCw4zc49qg8p8Xo=; b=IeNNPJEdzbt9vypmjQsg/bKt66/pfksuidWma94Rq4PvDA+tsQ6oN94XIADMbV4F7l CQ/CDqXZIVCnY5B/C1xaCRujop+i1amRSVXRWFoKbX4VuEUZOmrHXj9PVfVit2OaJmm0 hzqiOPhmzAgi1YhUA4EsmQWutlMjHXl6Nupz8Hb2pTetZBLE71kMMJbT4apN4SFaJP/O OXVVFZRRnQCes8CSCIOs2OyMLZ1bu2w/3itm2GJg6hgHSW0ZKEvgQs3u7TebevlFhWM3 qs9t9yUIVeUHSfJGs5oZsF0npqBM6+PlpOMfwFlP6lf/6IeRrKmqHlqb1b1DCyYf2yo6 tP7g== X-Gm-Message-State: APf1xPAqV087mp+MK540I8LwROUOIwhNKXH4hmfREauo38F7YzZDPXyo h8mIgkUIiILLXc/Kia+PGP85u/EoYIA= X-Received: by 10.157.22.242 with SMTP id s47mr3666872ots.317.1519257229349; Wed, 21 Feb 2018 15:53:49 -0800 (PST) Received: from ?IPv6:2601:602:9802:a8dc::f21a? ([2601:602:9802:a8dc::f21a]) by smtp.gmail.com with ESMTPSA id h12sm16252161ote.23.2018.02.21.15.53.46 (version=TLS1_2 cipher=ECDHE-RSA-AES128-GCM-SHA256 bits=128/128); Wed, 21 Feb 2018 15:53:48 -0800 (PST) Subject: Re: [PATCH 2/2] arm64: Clear the stack To: Mark Rutland Cc: Alexander Popov , Kees Cook , Ard Biesheuvel , kernel-hardening@lists.openwall.com, linux-arm-kernel@lists.infradead.org, linux-kernel@vger.kernel.org References: <20180221011303.20392-1-labbott@redhat.com> <20180221011303.20392-3-labbott@redhat.com> <20180221153850.ywpzsigfnz3etoun@salmiak> From: Laura Abbott Message-ID: <3b76d238-e10a-9abf-c9cb-6d3738eb7896@redhat.com> Date: Wed, 21 Feb 2018 15:53:35 -0800 User-Agent: Mozilla/5.0 (X11; Linux x86_64; rv:52.0) Gecko/20100101 Thunderbird/52.5.2 MIME-Version: 1.0 In-Reply-To: <20180221153850.ywpzsigfnz3etoun@salmiak> Content-Type: text/plain; charset=utf-8; format=flowed Content-Language: en-US Content-Transfer-Encoding: 7bit Sender: linux-kernel-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-kernel@vger.kernel.org On 02/21/2018 07:38 AM, Mark Rutland wrote: > Hi Laura, > > On Tue, Feb 20, 2018 at 05:13:03PM -0800, Laura Abbott wrote: >> Implementation of stackleak based heavily on the x86 version > > Neat! > >> diff --git a/arch/arm64/kernel/entry.S b/arch/arm64/kernel/entry.S >> index ec2ee720e33e..b909b436293a 100644 >> --- a/arch/arm64/kernel/entry.S >> +++ b/arch/arm64/kernel/entry.S >> @@ -401,6 +401,11 @@ tsk .req x28 // current thread_info >> >> .text >> >> + .macro erase_kstack >> +#ifdef CONFIG_GCC_PLUGIN_STACKLEAK >> + bl __erase_kstack >> +#endif >> + .endm >> /* >> * Exception vectors. >> */ >> @@ -901,6 +906,7 @@ work_pending: >> */ >> ret_to_user: >> disable_daif >> + erase_kstack > > I *think* this should happen in finish_ret_to_user a few lines down, since we > can call C code if we branch to work_pending, dirtying the stack. > I think you're right but this didn't immediately work when I tried it. I'll have to dig into this some more. >> ldr x1, [tsk, #TSK_TI_FLAGS] >> and x2, x1, #_TIF_WORK_MASK >> cbnz x2, work_pending >> @@ -1337,3 +1343,105 @@ alternative_else_nop_endif >> ENDPROC(__sdei_asm_handler) >> NOKPROBE(__sdei_asm_handler) >> #endif /* CONFIG_ARM_SDE_INTERFACE */ >> + >> +/* >> + * This is what the stack looks like >> + * >> + * +---+ <- task_stack_page(p) + THREAD_SIZE >> + * | | >> + * +---+ <- task_stack_page(p) + THREAD_START_SP >> + * | | >> + * | | >> + * +---+ <- task_pt_regs(p) > > THREAD_START_SP got killed off in commit 34be98f4944f9907 as part of the > VMAP_STACK rework, so this can be: > > +---+ <- task_stack_page(p) + THREAD_SIZE > | | > | | > +---+ <- task_pt_regs(p) > ... > Good point. >> + * | | >> + * | | >> + * | | <- current_sp >> + * ~~~~~ >> + * >> + * ~~~~~ >> + * | | <- lowest_stack >> + * | | >> + * | | >> + * +---+ <- task_stack_page(p) >> + * >> + * This function is desgned to poison the memory between the lowest_stack >> + * and the current stack pointer. After clearing the stack, the lowest >> + * stack is reset. >> + */ >> + >> +#ifdef CONFIG_GCC_PLUGIN_STACKLEAK >> +ENTRY(__erase_kstack) >> + mov x10, x0 // save x0 for the fast path > > AFAICT, we only call this from ret_to_user, where x0 doesn't need to be > preserved. > > Is that for ret_fast_syscall? In some cases, ret_fast_syscall can bypass > ret_to_user and calls kernel_exit directly, so we might need a call there. > This was a hold over when I was experimenting with calling erase_kstack more places, one of which came through ret_fast_syscall. I realized later that the erase was unnecessary but accidentally kept the saving in. I'll see about removing it assuming we don't decide later to put a call on the fast path. >> + >> + get_thread_info x0 >> + ldr x1, [x0, #TSK_TI_LOWEST_STACK] >> + >> + /* get the number of bytes to check for lowest stack */ >> + mov x3, x1 >> + and x3, x3, #THREAD_SIZE - 1 >> + lsr x3, x3, #3 >> + >> + /* generate addresses from the bottom of the stack */ >> + mov x4, sp >> + movn x2, #THREAD_SIZE - 1 >> + and x1, x4, x2 > > Can we replace the MOVN;AND with a single instruction to clear the low bits? > e.g. > > mov x4, sp > bic x1, x4, #THREAD_SIZE - 1 > > ... IIUC BIC is an alias for the bitfield instructions, though I can't recall > exactly which one(s). > Good suggestion. >> + >> + mov x2, #STACKLEAK_POISON >> + >> + mov x5, #0 >> +1: >> + /* >> + * As borrowed from the x86 logic, start from the lowest_stack >> + * and go to the bottom to find the poison value. >> + * The check of 16 is to hopefully avoid false positives. >> + */ >> + cbz x3, 4f >> + ldr x4, [x1, x3, lsl #3] >> + cmp x4, x2 >> + csinc x5, xzr, x5, ne >> + tbnz x5, #STACKLEAK_POISON_CHECK_DEPTH/4, 4f // found 16 poisons? >> + sub x3, x3, #1 >> + b 1b >> + >> +4: >> + /* total number of bytes to poison */ >> + add x5, x1, x3, lsl #3 >> + mov x4, sp >> + sub x8, x4, x5 >> + >> + cmp x8, #THREAD_SIZE // sanity check the range >> + b.lo 5f >> + ASM_BUG() >> + >> +5: >> + /* >> + * We may have hit a path where the stack did not get used, >> + * no need to do anything here >> + */ >> + cbz x8, 7f >> + >> + sub x8, x8, #1 // don't poison the current stack pointer >> + >> + lsr x8, x8, #3 >> + add x3, x3, x8 >> + >> + /* >> + * The logic of this loop ensures the last stack word isn't >> + * ovewritten. >> + */ > > Is that to ensure that we don't clobber the word at the current sp value? > Correct. >> +6: >> + cbz x8, 7f >> + str x2, [x1, x3, lsl #3] >> + sub x3, x3, #1 >> + sub x8, x8, #1 >> + b 6b >> + >> + /* Reset the lowest stack to the top of the stack */ >> +7: >> + mov x1, sp >> + str x1, [x0, #TSK_TI_LOWEST_STACK] >> + >> + mov x0, x10 >> + ret >> +ENDPROC(__erase_kstack) >> +#endif > > [...] > >> diff --git a/drivers/firmware/efi/libstub/Makefile b/drivers/firmware/efi/libstub/Makefile >> index 7b3ba40f0745..35ebbc1b17ff 100644 >> --- a/drivers/firmware/efi/libstub/Makefile >> +++ b/drivers/firmware/efi/libstub/Makefile >> @@ -20,7 +20,8 @@ cflags-$(CONFIG_EFI_ARMSTUB) += -I$(srctree)/scripts/dtc/libfdt >> KBUILD_CFLAGS := $(cflags-y) -DDISABLE_BRANCH_PROFILING \ >> -D__NO_FORTIFY \ >> $(call cc-option,-ffreestanding) \ >> - $(call cc-option,-fno-stack-protector) >> + $(call cc-option,-fno-stack-protector) \ >> + $(DISABLE_STACKLEAK_PLUGIN) > > I believe the KVM hyp code will also need to opt-out of this. > I'll double check that. > Thanks, > Mark. > Thanks, Laura