@@ -7,12 +7,95 @@ use anyhow::Result;
77use log:: { debug, warn} ;
88use std:: env;
99use std:: fs;
10+ use std:: os:: unix:: fs:: PermissionsExt ;
1011use std:: path:: PathBuf ;
1112use std:: process:: Command ;
1213
1314const GROUP_IDENTIFIER : & str = "ScriptedChecks" ;
1415const 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