Last active
August 12, 2023 18:59
-
-
Save Freaky/2560975d3c94246b86f464b8be75c967 to your computer and use it in GitHub Desktop.
FreeBSD Zenbleed mitigation rc script
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#!/bin/sh | |
# | |
# PROVIDE: zenbleed_workaround | |
# REQUIRE: root mountcritlocal microcode_update | |
# BEFORE: SERVERS | |
# KEYWORD: nojail resume | |
# Source: https://gist.github.com/Freaky/2560975d3c94246b86f464b8be75c967 | |
# | |
# Copyright (c) 2023 Thomas Hurst <[email protected]> | |
# License: https://opensource.org/license/mit/ | |
. /etc/rc.subr | |
name="zenbleed_workaround" | |
desc="Zenbleed MSR chicken bit workaround" | |
rcvar="zenbleed_workaround_enable" | |
extra_commands="resume" | |
start_precmd="check_zen2" | |
resume_precmd="${start_precmd}" | |
stop_precmd="${start_precmd}" | |
start_cmd="workaround_zenbleed" | |
resume_cmd="${start_cmd}" | |
stop_cmd="restore_zenbleed" | |
load_rc_config "${name}" | |
: "${zenbleed_workaround_enable:=NO}" | |
CPUCTL="/usr/sbin/cpucontrol" | |
check_zen2() { | |
if ! kldstat -q -m cpuctl; then | |
if ! kldload cpuctl > /dev/null 2>&1; then | |
warn "Can't load cpuctl module." | |
return 1 | |
fi | |
fi | |
authenticamd="0x68747541 0x444d4163 0x69746e65" | |
if ! ${CPUCTL} -i 0x0 /dev/cpuctl0 | grep -q "$authenticamd"; then | |
warn "Not an AMD processor, ignoring" | |
return 1 | |
fi | |
cpuid=$(${CPUCTL} -i 0x1 /dev/cpuctl0 | awk '{ print $4 }') | |
family=$(( ((cpuid & 0xf00) >> 8) + ((cpuid & 0x0ff00000) >> 20) )) | |
model=$(( (cpuid & 0xf0) >> 4 | (cpuid & 0x000f0000) >> 12 )) | |
# Zen 2 is Family 23 Model 49 - 160 | |
if ! { [ $family -eq 23 ] && [ $model -ge 49 ] && [ $model -le 160 ]; } then | |
warn "Not a Zen 2 processor, ignoring" | |
return 1 | |
fi | |
hmicrocode=$(${CPUCTL} -m 0x8b /dev/cpuctl0 | awk '{ print $4 }') | |
microcode=$((hmicrocode)) | |
# Numbers sourced from Linux patch: | |
# https://freshbsd.org/linux/linux/commit/0a9266b79cacdd02b888aed1308c308ad6d4ee4e | |
if [ $model -ge $((0x30)) ] && [ $model -le $((0x3f)) ] && [ $microcode -ge $((0x0830107a)) ] || | |
[ $model -ge $((0x60)) ] && [ $model -le $((0x67)) ] && [ $microcode -ge $((0x0860010b)) ] || | |
[ $model -ge $((0x68)) ] && [ $model -le $((0x6f)) ] && [ $microcode -ge $((0x08608105)) ] || | |
[ $model -ge $((0x70)) ] && [ $model -le $((0x7f)) ] && [ $microcode -ge $((0x08701032)) ] || | |
[ $model -ge $((0xa0)) ] && [ $model -le $((0xaf)) ] && [ $microcode -ge $((0x08a00008)) ]; then | |
warn "Known-good microcode detected: ${hmicrocode}, ignoring" | |
return 1 | |
fi | |
} | |
check_date() { | |
# Start whinging mid-December | |
if [ "$(/bin/date +%s)" -ge 1702684800 ]; then | |
warn "Zenbleed should be resolved by updated AMD microcode, please check." | |
warn "Updated microcode is provided by sysutils/devcpu-data" | |
fi | |
} | |
workaround_zenbleed() { | |
check_date | |
check_startmsgs && echo "Applying Zenbleed MSR workaround" | |
for D in /dev/cpuctl* | |
do | |
${CPUCTL} -m "0xc0011029|=0x200" "$D" | |
done | |
} | |
restore_zenbleed() { | |
check_startmsgs && echo "Removing Zenbleed MSR workaround" | |
for D in /dev/cpuctl* | |
do | |
${CPUCTL} -m "0xc0011029&=~0x200" "$D" | |
done | |
} | |
run_rc_command "$1" | |
Thanks. I added a resume command (just pointing at start_cmd, no need to run restart or indirect it through a function I can see), and made it slightly less chatty.
Did you check that it will still check for the correct cpu ?
For me it seems like it will only check at start, not after resume.
So you can have a case where it will not initially start (like on an intel cpu), but after resume it will set the bit.
But maybe I don't really know how resume works, maybe it check if it succeed before resuming it.
Good point. I added a resume_precmd
.
I added known-good microcode checks (just EPYC "Rome" CPUs right now I believe), and a warning that appears if you use the script after mid December.
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Proof of concept BSD port: https://git.hardenedbsd.org/shawn.webb/zenbleed (be sure to co the
shawn.webb/bsd/main
branch)