Linux-ARM-Kernel Archive on lore.kernel.org
 help / color / mirror / Atom feed
From: Dave.Martin@arm.com (Dave Martin)
To: linux-arm-kernel@lists.infradead.org
Subject: [PATCH v3] arm64: fault: Don't leak data in ESR context for user fault on kernel VA
Date: Wed, 23 May 2018 11:31:31 +0100	[thread overview]
Message-ID: <20180523103131.GI13470@e103592.cambridge.arm.com> (raw)
In-Reply-To: <20180522161120.12798-1-peter.maydell@linaro.org>

On Tue, May 22, 2018 at 05:11:20PM +0100, Peter Maydell wrote:
> If userspace faults on a kernel address, handing them the raw ESR
> value on the sigframe as part of the delivered signal can leak data

Nit: on -> in
(not worth it unless you respin the patch though).

> useful to attackers who are using information about the underlying hardware
> fault type (e.g. translation vs permission) as a mechanism to defeat KASLR.
> 
> However there are also legitimate uses for the information provided
> in the ESR -- notably the GCC and LLVM sanitizers use this to report
> whether wild pointer accesses by the application are reads or writes
> (since a wild write is a more serious bug than a wild read), so we
> don't want to drop the ESR information entirely.
> 
> For faulting addresses in the kernel, sanitize the ESR. We choose
> to present userspace with the illusion that there is nothing mapped
> in the kernel's part of the address space at all, by reporting all
> faults as level 0 translation faults taken to EL1.

Did the discussion about faultin on user addresses go anywhere?

i.e., we tell userspace which page table level a fault occurred
at, and other things that are really none of userspace's business to
know.

This is not obviously a problem, but still a bit odd.  It could be
addressed separately.

> These fields are safe to pass through to userspace as they depend
> only on the instruction that userspace used to provoke the fault:
>  EC IL (always)
>  ISV CM WNR (for all data aborts)
> All the other fields in ESR except DFSC are architecturally RES0
> for an L0 translation fault taken to EL1, so can be zeroed out
> without confusing userspace.
> 
> The illusion is not entirely perfect, as there is a tiny wrinkle
> where we will report an alignment fault that was not due to the memory
> type (for instance a LDREX to an unaligned address) as a translation
> fault, whereas if you do this on real unmapped memory the alignment
> fault takes precedence. This is not likely to trip anybody up in
> practice, as the only users we know of for the ESR information who
> care about the behaviour for kernel addresses only really want to
> know about the WnR bit.
> 
> Signed-off-by: Peter Maydell <peter.maydell@linaro.org>

Modulo the above (which may be out of scope anyway)

Reviewed-by: Dave Martin <Dave.Martin@arm.com>

Cheers
---Dave

> ---
> This patch is an alternative proposal to Will's patch
> https://patchwork.kernel.org/patch/10258781/
> which simply removed the ESR record entirely for kernel addresses.
> 
> Changes v1->v2:
>  * rebased on master
>  * commit message tweak
>  * DABT_CUR and IABT_CUR moved to "can't happen" default case
>  * explicitly clear the bits which are RES0 if ISV == 0
>  * comment text tweaks
> Changes v2->v3:
>  * remove the support for reporting ESRs with ISV == 1 (this
>    can't happen, and we probably don't want to tell userspace
>    that the exception was taken to EL2 if in some hypothetical
>    future that becomes possible)
>  * rebased on 4.17-rc6
> ---
>  arch/arm64/mm/fault.c | 51 +++++++++++++++++++++++++++++++++++++++++++
>  1 file changed, 51 insertions(+)
> 
> diff --git a/arch/arm64/mm/fault.c b/arch/arm64/mm/fault.c
> index 4165485e8b6e..2af3dd89bcdb 100644
> --- a/arch/arm64/mm/fault.c
> +++ b/arch/arm64/mm/fault.c
> @@ -293,6 +293,57 @@ static void __do_kernel_fault(unsigned long addr, unsigned int esr,
>  static void __do_user_fault(struct siginfo *info, unsigned int esr)
>  {
>  	current->thread.fault_address = (unsigned long)info->si_addr;
> +
> +	/*
> +	 * If the faulting address is in the kernel, we must sanitize the ESR.
> +	 * From userspace's point of view, kernel-only mappings don't exist
> +	 * at all, so we report them as level 0 translation faults.
> +	 * (This is not quite the way that "no mapping there at all" behaves:
> +	 * an alignment fault not caused by the memory type would take
> +	 * precedence over translation fault for a real access to empty
> +	 * space. Unfortunately we can't easily distinguish "alignment fault
> +	 * not caused by memory type" from "alignment fault caused by memory
> +	 * type", so we ignore this wrinkle and just return the translation
> +	 * fault.)
> +	 */
> +	if (current->thread.fault_address >= TASK_SIZE) {
> +		switch (ESR_ELx_EC(esr)) {
> +		case ESR_ELx_EC_DABT_LOW:
> +			/*
> +			 * These bits provide only information about the
> +			 * faulting instruction, which userspace knows already.
> +			 * We explicitly clear bits which are architecturally
> +			 * RES0 in case they are given meanings in future.
> +			 * We always report the ESR as if the fault was taken
> +			 * to EL1 and so ISV and the bits in ISS[23:14] are
> +			 * clear. (In fact it always will be a fault to EL1.)
> +			 */
> +			esr &= ESR_ELx_EC_MASK | ESR_ELx_IL |
> +				ESR_ELx_CM | ESR_ELx_WNR;
> +			esr |= ESR_ELx_FSC_FAULT;
> +			break;
> +		case ESR_ELx_EC_IABT_LOW:
> +			/*
> +			 * Claim a level 0 translation fault.
> +			 * All other bits are architecturally RES0 for faults
> +			 * reported with that DFSC value, so we clear them.
> +			 */
> +			esr &= ESR_ELx_EC_MASK | ESR_ELx_IL;
> +			esr |= ESR_ELx_FSC_FAULT;
> +			break;
> +		default:
> +			/*
> +			 * This should never happen (entry.S only brings us
> +			 * into this code for insn and data aborts from a lower
> +			 * exception level). Fail safe by not providing an ESR
> +			 * context record at all.
> +			 */
> +			WARN(1, "ESR 0x%x is not DABT or IABT from EL0\n", esr);
> +			esr = 0;
> +			break;
> +		}
> +	}
> +
>  	current->thread.fault_code = esr;
>  	arm64_force_sig_info(info, esr_to_fault_info(esr)->name, current);
>  }
> -- 
> 2.17.0
> 
> 
> _______________________________________________
> linux-arm-kernel mailing list
> linux-arm-kernel at lists.infradead.org
> http://lists.infradead.org/mailman/listinfo/linux-arm-kernel

      reply	other threads:[~2018-05-23 10:31 UTC|newest]

Thread overview: 2+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2018-05-22 16:11 [PATCH v3] arm64: fault: Don't leak data in ESR context for user fault on kernel VA Peter Maydell
2018-05-23 10:31 ` Dave Martin [this message]

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=20180523103131.GI13470@e103592.cambridge.arm.com \
    --to=dave.martin@arm.com \
    --cc=linux-arm-kernel@lists.infradead.org \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox