Skip to content

Commit eb9c522

Browse files
committed
chore: move pvh script to builtin
Signed-off-by: James Petersen <jpetersenames@gmail.com>
1 parent 7917c54 commit eb9c522

2 files changed

Lines changed: 101 additions & 79 deletions

File tree

scripts/pvh.sh

Lines changed: 0 additions & 78 deletions
This file was deleted.

src/script.rs

Lines changed: 101 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,12 +7,95 @@ use anyhow::Result;
77
use log::{debug, warn};
88
use std::env;
99
use std::fs;
10+
use std::os::unix::fs::PermissionsExt;
1011
use std::path::PathBuf;
1112
use std::process::Command;
1213

1314
const GROUP_IDENTIFIER: &str = "ScriptedChecks";
1415
const NAME: &str = "Scripted Checks";
1516

17+
// TODO(found-it): encoding this here for the time being. Need a better way to handle builtin
18+
// scripts, but would like to get customer feedback first.
19+
const PVH_SCRIPT: &str = r#"#!/bin/sh
20+
set -eu
21+
22+
echo "EDERA_PREFLIGHT_CHECK_NAME=Can PVH Be Enabled"
23+
24+
# prerequisites: msr-tools (rdmsr), and the msr kernel module
25+
modprobe msr 2>/dev/null || true
26+
27+
err() {
28+
echo "$@" >&2
29+
}
30+
31+
do_rdmsr() {
32+
MSR="$1"
33+
if [ ! -e /dev/cpu/0/msr ]; then
34+
err "rdmsr ${MSR}: /dev/cpu/0/msr doesn't exist, load 'msr' kernel module"
35+
return 1
36+
fi
37+
38+
if command -v rdmsr >/dev/null; then
39+
rdmsr -p0 -d "$MSR" 2>/dev/null || echo 0
40+
elif command -v dd >/dev/null && command -v od >/dev/null; then
41+
(dd if=/dev/cpu/0/msr bs=1 skip=$(($MSR)) count=8 status=none 2>/dev/null | od -An -tu8 -N8) || echo 0
42+
else
43+
err "rdmsr ${MSR}: need either 'rdmsr' or 'dd' and 'od' commands and none were found"
44+
return 1
45+
fi
46+
}
47+
48+
cpu_vendor=$(awk -F: '/vendor_id/{print $2; exit}' /proc/cpuinfo | xargs)
49+
flags=$(awk -F: '/^flags/{print $2; exit}' /proc/cpuinfo)
50+
51+
case "$cpu_vendor" in
52+
"GenuineIntel")
53+
echo "$flags" | grep -qw vmx && cap=yes || cap=no
54+
55+
if do_rdmsr "0x3a" >/dev/null; then
56+
val=$(do_rdmsr 0x3a 2>/dev/null || echo 0)
57+
lock=$(((val >> 0) & 1))
58+
vmx_outside_smx=$(((val >> 2) & 1))
59+
bios_enabled=no
60+
if [ $lock -eq 1 ] && [ $vmx_outside_smx -eq 1 ]; then
61+
bios_enabled=yes
62+
fi
63+
printf "Intel VT-x capability: %s\n" "$cap"
64+
printf "IA32_FEATURE_CONTROL (0x3A): 0x%x (lock=%d, vmx_outside_smx=%d)\n" "$val" "$lock" "$vmx_outside_smx"
65+
printf "BIOS permits VT-x: %s\n" "$bios_enabled"
66+
else
67+
printf "Intel VT-x capability: %s (install msr-tools to verify MSR 0x3A)\n" "$cap"
68+
fi
69+
;;
70+
71+
"AuthenticAMD")
72+
echo "$flags" | grep -qw svm && cap=yes || cap=no
73+
if do_rdmsr "0xC0010114" >/dev/null; then
74+
vmcr=$(do_rdmsr 0xC0010114 2>/dev/null || echo 0)
75+
lock=$(((vmcr >> 3) & 1)) # VM_CR.LOCK
76+
svmdis=$(((vmcr >> 4) & 1)) # VM_CR.SVMDIS (1 = disabled by BIOS/firmware)
77+
bios_enabled=$([ $svmdis -eq 0 ] && echo yes || echo no)
78+
79+
efer=$(do_rdmsr 0xC0000080 2>/dev/null || echo 0)
80+
svme=$(((efer >> 12) & 1)) # EFER.SVME (runtime: 1 if OS/hypervisor enabled SVM)
81+
82+
printf "AMD SVM capability: %s\n" "$cap"
83+
printf "VM_CR (0xC0010114): 0x%x (lock=%d, svmdis=%d)\n" "$vmcr" "$lock" "$svmdis"
84+
printf "BIOS permits SVM: %s\n" "$bios_enabled"
85+
printf "EFER (0xC0000080): 0x%x (SVME=%d)\n" "$efer" "$svme"
86+
else
87+
printf "AMD SVM capability: %s (install msr-tools to verify VM_CR/EFER)\n" "$cap"
88+
fi
89+
;;
90+
91+
*)
92+
echo "Unknown CPU vendor: $cpu_vendor"
93+
;;
94+
esac
95+
96+
# vim: set ts=2 sts=2 sw=2 et:
97+
"#;
98+
1699
/// ScriptChecks is a special type of check that is intended to run a series of
17100
/// small shell scripts. The intent here is to make a pluggable interface for to
18101
/// quickly implement checks. Ideally all checks end up in their own CheckGroup.
@@ -31,7 +114,24 @@ impl ScriptChecks {
31114
results: vec![],
32115
};
33116
}
34-
let script_list = script_list.unwrap();
117+
let mut script_list = script_list.unwrap();
118+
119+
// TODO(found-it): Handle builtin scripts better. This is a temporary workaround while we
120+
// get folks to test. If they want to copy the binary out of the container then everything
121+
// will be self contained.
122+
let script_path = env::temp_dir().join("edera_preflight_pvh.sh");
123+
let r = fs::write(&script_path, PVH_SCRIPT);
124+
if r.is_ok() {
125+
if let Ok(metadata) = fs::metadata(&script_path) {
126+
let mut permissions = metadata.permissions();
127+
128+
// Set permissions to read, write, and execute for owner (0o700)
129+
// The `0o` prefix indicates an octal literal.
130+
permissions.set_mode(0o700);
131+
let _ = fs::set_permissions(&script_path, permissions);
132+
script_list.push(script_path);
133+
}
134+
}
35135

36136
let mut group_result = Passed;
37137

0 commit comments

Comments
 (0)