[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index] Re: [PATCH v3 60/70] x86: Build check for embedded endbr64 instructions
On 23/02/2022 11:31, Jan Beulich wrote: > On 22.02.2022 16:26, Andrew Cooper wrote: >> up on a non-instruction boundary. Such embedded instructions mark legal >> indirect branch targets as far as the CPU is concerned, which aren't legal as >> far as the logic is concerned. > Thinking about it: Wouldn't it be yet slightly more reassuring to also > look for ENDBR32? I considered that, but it's awkward to do and doubles the length of this already ~0.7s (x2 for efi because this step isn't performed in parallel) delay to the build. We do not have __HYPERVISOR_CS32, so ENDBR32 will yield #CP[endbr] if encountered. If an attacker has managed to edit the GDT to insert a compatibility code segment, and hijacked a far transfer to use it, then the absence of ENDBR32's in the binary isn't going to be an impediment. > >> When CET-IBT is active, check for embedded byte sequences. Example failures >> look like: >> >> check-endbr.sh xen-syms Fail: Found 2 embedded endbr64 instructions >> 0xffff82d040325677: test_endbr64 at >> /local/xen.git/xen/arch/x86/x86_64/entry.S:28 >> 0xffff82d040352da6: init_done at /local/xen.git/xen/arch/x86/setup.c:675 >> >> Signed-off-by: Marek Marczykowski-Górecki <marmarek@xxxxxxxxxxxxxxxxxxxxxx> >> Signed-off-by: Andrew Cooper <andrew.cooper3@xxxxxxxxxx> > Reviewed-by: Jan Beulich <jbeulich@xxxxxxxx> Thanks. > >> --- a/README >> +++ b/README >> @@ -68,6 +68,7 @@ provided by your OS distributor: >> In addition to the above there are a number of optional build >> prerequisites. Omitting these will cause the related features to be >> disabled at compile time: >> + * Binary-search capable grep (if building Xen with CET support) > Nit: With this (maybe this was the case already earlier though) > s/will/may/ in the previous sentence? I'm planning a separate overhaul to README because bits of it are quite wrong, including lots of this section. This was the lead bad addition I could come up with that didn't involve a major rewrite. >> --- /dev/null >> +++ b/xen/tools/check-endbr.sh >> @@ -0,0 +1,85 @@ >> +#!/bin/sh >> +# >> +# Usage ./$0 xen-syms >> +# >> +set -e >> + >> +# Prettyprint parameters a little for message >> +MSG_PFX="${0##*/} ${1##*/}" >> + >> +OBJCOPY="${OBJCOPY:-objcopy} -j .text $1" >> +OBJDUMP="${OBJDUMP:-objdump} -j .text $1" > While embedding the arguments here shortens the lines where these are > used, the appearance especially of $OBJCOPY with a single file name > argument ... > >> +ADDR2LINE="${ADDR2LINE:-addr2line}" >> + >> +D=$(mktemp -d) >> +trap "rm -rf $D" EXIT >> + >> +TEXT_BIN=$D/xen-syms.text >> +VALID=$D/valid-addrs >> +ALL=$D/all-addrs >> +BAD=$D/bad-addrs >> + >> +# Check that grep can do binary searches. Some, e.g. busybox, can't. >> Leave a >> +# warning but don't fail the build. >> +echo "X" | grep -aob "X" -q 2>/dev/null || >> + { echo "$MSG_PFX Warning: grep can't do binary searches" >&2; exit 0; } >> + >> +# >> +# First, look for all the valid endbr64 instructions. >> +# A worst-case disassembly, viewed through cat -A, may look like: >> +# >> +# ffff82d040337bd4 <endbr64>:$ >> +# ffff82d040337bd4:^If3 0f 1e fa ^Iendbr64 $ >> +# ffff82d040337bd8:^Ieb fe ^Ijmp ffff82d040337bd8 >> <endbr64+0x4>$ >> +# ffff82d040337bda:^Ib8 f3 0f 1e fa ^Imov $0xfa1e0ff3,%eax$ >> +# >> +# Want to grab the address of endbr64 instructions only, ignoring function >> +# names/jump labels/etc, so look for 'endbr64' preceeded by a tab and with >> any >> +# number of trailing spaces before the end of the line. >> +# >> +${OBJDUMP} -d -w | grep ' endbr64 *$' | cut -f 1 -d ':' > $VALID & >> + >> +# >> +# Second, look for any endbr64 byte sequence >> +# This has a couple of complications: >> +# >> +# 1) Grep binary search isn't VMA aware. Copy .text out as binary, causing >> +# the grep offset to be from the start of .text. >> +# >> +# 2) dash's printf doesn't understand hex escapes, hence the use of octal. >> +# >> +# 3) AWK can't add 64bit integers, because internally all numbers are >> doubles. >> +# When the upper bits are set, the exponents worth of precision is lost >> in >> +# the lower bits, rounding integers to the nearest 4k. >> +# >> +# Instead, use the fact that Xen's .text is within a 1G aligned region, >> and >> +# split the VMA in half so AWK's numeric addition is only working on 32 >> bit >> +# numbers, which don't lose precision. >> +# >> +eval $(${OBJDUMP} -h | awk '$2 == ".text" {printf "vma_hi=%s\nvma_lo=%s\n", >> substr($4, 1, 8), substr($4, 9, 16)}') >> + >> +${OBJCOPY} -O binary $TEXT_BIN > ..., like here, is then somewhat misleading considering that the tool > can take one or two filenames as arguments. I can re-expand them if you'd prefer. This would be the delta: diff --git a/xen/tools/check-endbr.sh b/xen/tools/check-endbr.sh index 85878353112a..3019ca1c7db0 100755 --- a/xen/tools/check-endbr.sh +++ b/xen/tools/check-endbr.sh @@ -7,8 +7,8 @@ set -e # Prettyprint parameters a little for message MSG_PFX="${0##*/} ${1##*/}" -OBJCOPY="${OBJCOPY:-objcopy} -j .text $1" -OBJDUMP="${OBJDUMP:-objdump} -j .text $1" +OBJCOPY="${OBJCOPY:-objcopy}" +OBJDUMP="${OBJDUMP:-objdump}" ADDR2LINE="${ADDR2LINE:-addr2line}" D=$(mktemp -d) @@ -37,7 +37,7 @@ echo "X" | grep -aob "X" -q 2>/dev/null || # names/jump labels/etc, so look for 'endbr64' preceeded by a tab and with any # number of trailing spaces before the end of the line. # -${OBJDUMP} -d -w | grep ' endbr64 *$' | cut -f 1 -d ':' > $VALID & +${OBJDUMP} -j .text $1 -d -w | grep ' endbr64 *$' | cut -f 1 -d ':' > $VALID & # # Second, look for any endbr64 byte sequence @@ -56,9 +56,10 @@ ${OBJDUMP} -d -w | grep ' endbr64 *$' | cut -f 1 -d ':' > $VALID & # split the VMA in half so AWK's numeric addition is only working on 32 bit # numbers, which don't lose precision. # -eval $(${OBJDUMP} -h | awk '$2 == ".text" {printf "vma_hi=%s\nvma_lo=%s\n", substr($4, 1, 8), substr($4, 9, 16)}') +eval $(${OBJDUMP} -j .text $1 -h | + awk '$2 == ".text" {printf "vma_hi=%s\nvma_lo=%s\n", substr($4, 1, 8), substr($4, 9, 16)}') -${OBJCOPY} -O binary $TEXT_BIN +${OBJCOPY} -j .text $1 -O binary $TEXT_BIN grep -aob "$(printf '\363\17\36\372')" $TEXT_BIN | awk -F':' '{printf "%s%x\n", "'$vma_hi'", int(0x'$vma_lo') + $1}' > $ALL ~Andrew
|
![]() |
Lists.xenproject.org is hosted with RackSpace, monitoring our |