hypervisor kernel integrity enforcement via EPT/NPT write interception for Xen/HVM guests
1#!/bin/bash
2set -e
3
4XEN_VERSION="4.18.0"
5XEN_URL="https://downloads.xenproject.org/release/xen/${XEN_VERSION}/xen-${XEN_VERSION}.tar.gz"
6BUILD_DIR="/tmp/xen-turnstile-build"
7TURNSTILE_DIR="$(cd "$(dirname "$0")" && pwd)"
8
9echo "=== Turnstile Xen Build Script ==="
10echo "Xen version: ${XEN_VERSION}"
11echo "Turnstile source: ${TURNSTILE_DIR}"
12echo "Build directory: ${BUILD_DIR}"
13echo ""
14
15install_deps_arch() {
16 echo "Installing build dependencies for Arch Linux..."
17 sudo pacman -Sy --needed --noconfirm \
18 base-devel git wget python python-setuptools \
19 iasl acpica yajl pixman bridge-utils \
20 iproute2 libaio glib2 libpng sdl2 ncurses \
21 libnl openssl zlib lzo libseccomp systemd \
22 e2fsprogs nasm flex bison ninja meson
23
24 if ! command -v bcc &> /dev/null; then
25 echo ""
26 echo "dev86 not found. Installing from AUR..."
27 if command -v yay &> /dev/null; then
28 yay -S --needed --noconfirm dev86
29 elif command -v paru &> /dev/null; then
30 paru -S --needed --noconfirm dev86
31 else
32 echo "No AUR helper found. Installing dev86 manually..."
33 cd /tmp
34 rm -rf dev86
35 git clone https://aur.archlinux.org/dev86.git
36 cd dev86
37 makepkg -si --noconfirm
38 cd "${TURNSTILE_DIR}"
39 fi
40 fi
41}
42
43install_deps_debian() {
44 echo "Installing build dependencies for Debian/Ubuntu..."
45 sudo apt-get update
46 sudo apt-get install -y \
47 build-essential git wget python3 python3-dev \
48 uuid-dev libncurses-dev libglib2.0-dev libyajl-dev \
49 libaio-dev libpixman-1-dev libssl-dev libsdl2-dev \
50 liblzo2-dev libseccomp-dev bison flex iasl \
51 bridge-utils iproute2 e2fsprogs ninja-build meson
52}
53
54install_deps() {
55 if [ -f /etc/arch-release ]; then
56 install_deps_arch
57 elif [ -f /etc/debian_version ]; then
58 install_deps_debian
59 else
60 echo "Unknown distribution. Please install Xen build dependencies manually."
61 echo "Required: build tools, python, uuid, ncurses, glib2, yajl, aio, pixman, ssl, sdl2, lzo, seccomp, iasl, ninja"
62 exit 1
63 fi
64}
65
66download_xen() {
67 echo ""
68 echo "=== Downloading Xen ${XEN_VERSION} ==="
69 mkdir -p "${BUILD_DIR}"
70 cd "${BUILD_DIR}"
71
72 if [ ! -f "xen-${XEN_VERSION}.tar.gz" ]; then
73 wget "${XEN_URL}"
74 fi
75
76 if [ ! -d "xen-${XEN_VERSION}" ]; then
77 tar xzf "xen-${XEN_VERSION}.tar.gz"
78 fi
79}
80
81copy_turnstile_sources() {
82 echo ""
83 echo "=== Copying turnstile sources ==="
84 cd "${BUILD_DIR}/xen-${XEN_VERSION}"
85
86 cp "${TURNSTILE_DIR}/xen-patch/turnstile.c" xen/arch/x86/
87 cp "${TURNSTILE_DIR}/xen-patch/turnstile.h" xen/arch/x86/include/asm/
88
89 echo "Copied turnstile.c to xen/arch/x86/"
90 echo "Copied turnstile.h to xen/arch/x86/include/asm/"
91}
92
93apply_patches() {
94 echo ""
95 echo "=== Applying turnstile patches ==="
96 cd "${BUILD_DIR}/xen-${XEN_VERSION}"
97
98 DOMAIN_H="xen/arch/x86/include/asm/domain.h"
99 DOMAIN_C="xen/arch/x86/domain.c"
100 VMX_C="xen/arch/x86/hvm/vmx/vmx.c"
101 SVM_C="xen/arch/x86/hvm/svm/svm.c"
102 MAKEFILE="xen/arch/x86/Makefile"
103
104 echo "Adding turnstile pointer to arch_domain..."
105 if ! grep -q "struct turnstile_domain_state" "${DOMAIN_H}"; then
106 sed -i '/^struct arch_domain$/i struct turnstile_domain_state;' "${DOMAIN_H}"
107 sed -i '/^struct arch_domain$/,/^{$/ { /^{$/a\ struct turnstile_domain_state *turnstile;
108 }' "${DOMAIN_H}"
109 fi
110
111 echo "Adding turnstile include and cleanup to domain.c..."
112 if ! grep -q "asm/turnstile.h" "${DOMAIN_C}"; then
113 sed -i '/#include <asm\/pv\/mm.h>/a #include <asm/turnstile.h>' "${DOMAIN_C}"
114 fi
115 if ! grep -q "turnstile_domain_destroy" "${DOMAIN_C}"; then
116 sed -i '/^void arch_domain_destroy(struct domain \*d)/,/^{/ { /^{$/a\ turnstile_domain_destroy(d);
117 }' "${DOMAIN_C}"
118 fi
119
120 echo "Adding turnstile EPT hook to vmx.c..."
121 if ! grep -q "asm/turnstile.h" "${VMX_C}"; then
122 sed -i '/#include <asm\/monitor.h>/a #include <asm/turnstile.h>' "${VMX_C}"
123 fi
124 if ! grep -q "turnstile_check_violation" "${VMX_C}"; then
125 sed -i '/case EXIT_REASON_EPT_VIOLATION:/,/ept_handle_violation/ {
126 /paddr_t gpa;/a\ uint8_t insn_bytes[16];
127 }' "${VMX_C}"
128 sed -i 's/ ept_handle_violation(exit_qualification, gpa);/ if ( (exit_qualification \& (1u << 1)) \&\& currd->arch.turnstile )\n {\n unsigned long rip, cr3;\n int block;\n\n __vmread(GUEST_RIP, \&rip);\n __vmread(GUEST_CR3, \&cr3);\n\n memset(insn_bytes, 0, sizeof(insn_bytes));\n hvm_copy_from_guest_phys(insn_bytes, rip, sizeof(insn_bytes));\n\n block = turnstile_check_violation(currd, gpa, rip, cr3,\n exit_qualification,\n insn_bytes);\n if ( block )\n {\n hvm_inject_page_fault(PFEC_write_access | PFEC_page_present, gpa);\n break;\n }\n }\n\n ept_handle_violation(exit_qualification, gpa);/' "${VMX_C}"
129 fi
130
131 echo "Adding turnstile NPT hook to svm.c..."
132 if ! grep -q "asm/turnstile.h" "${SVM_C}"; then
133 sed -i '/#include <asm\/apic.h>/a #include <asm/turnstile.h>' "${SVM_C}"
134 fi
135 if ! grep -q "turnstile_check_violation" "${SVM_C}"; then
136 sed -i '/case VMEXIT_NPF:/,/v->arch.hvm.svm.cached_insn_len = 0;/ {
137 /if ( cpu_has_svm_decode )/i\ if ( (vmcb->ei.npf.ec \& PFEC_write_access) \&\& v->domain->arch.turnstile )\n {\n uint8_t insn_bytes[16];\n unsigned long rip = vmcb->rip;\n unsigned long cr3 = vmcb_get_cr3(vmcb);\n int block;\n\n memset(insn_bytes, 0, sizeof(insn_bytes));\n hvm_copy_from_guest_phys(insn_bytes, rip, sizeof(insn_bytes));\n\n block = turnstile_check_violation(v->domain, vmcb->ei.npf.gpa, rip, cr3,\n vmcb->ei.npf.ec,\n insn_bytes);\n if ( block )\n {\n hvm_inject_page_fault(PFEC_write_access | PFEC_page_present,\n vmcb->ei.npf.gpa);\n break;\n }\n }\n
138 }' "${SVM_C}"
139 fi
140
141 echo "Adding turnstile.o to Makefile..."
142 if ! grep -q "turnstile.o" "${MAKEFILE}"; then
143 sed -i '/^obj-y += usercopy.o/i obj-y += turnstile.o' "${MAKEFILE}"
144 fi
145
146 echo "Patches applied."
147}
148
149configure_xen() {
150 echo ""
151 echo "=== Configuring Xen ==="
152 cd "${BUILD_DIR}/xen-${XEN_VERSION}"
153
154 ./configure --prefix=/usr --sysconfdir=/etc --localstatedir=/var \
155 --enable-systemd --disable-stubdom --disable-docs
156}
157
158build_xen() {
159 echo ""
160 echo "=== Building Xen hypervisor ==="
161 cd "${BUILD_DIR}/xen-${XEN_VERSION}"
162
163 make -j$(nproc) xen
164}
165
166build_tools() {
167 echo ""
168 echo "=== Building Xen tools ==="
169 cd "${BUILD_DIR}/xen-${XEN_VERSION}"
170
171 make -j$(nproc) tools
172}
173
174install_xen() {
175 echo ""
176 echo "=== Installing Xen hypervisor ==="
177 cd "${BUILD_DIR}/xen-${XEN_VERSION}"
178
179 sudo make install-xen
180
181 echo ""
182 echo "=== Updating boot configuration ==="
183 if [ -f /etc/arch-release ]; then
184 sudo grub-mkconfig -o /boot/grub/grub.cfg
185 elif [ -f /etc/debian_version ]; then
186 sudo update-grub
187 fi
188}
189
190install_tools() {
191 echo ""
192 echo "=== Installing Xen tools ==="
193 cd "${BUILD_DIR}/xen-${XEN_VERSION}"
194
195 sudo make install-tools
196}
197
198print_usage() {
199 echo "Usage: $0 [command]"
200 echo ""
201 echo "Commands:"
202 echo " deps - Install build dependencies only"
203 echo " download - Download Xen source only"
204 echo " patch - Copy sources and apply patches only"
205 echo " configure - Configure Xen build"
206 echo " build - Build Xen hypervisor (assumes patched)"
207 echo " build-tools - Build Xen tools"
208 echo " install - Install built Xen hypervisor"
209 echo " install-tools - Install Xen tools"
210 echo " hypervisor - Build and install hypervisor only (no tools)"
211 echo " all - Do everything (default)"
212 echo ""
213}
214
215case "${1:-all}" in
216 deps)
217 install_deps
218 ;;
219 download)
220 download_xen
221 ;;
222 patch)
223 download_xen
224 copy_turnstile_sources
225 apply_patches
226 ;;
227 configure)
228 configure_xen
229 ;;
230 build)
231 build_xen
232 ;;
233 build-tools)
234 build_tools
235 ;;
236 install)
237 install_xen
238 ;;
239 install-tools)
240 install_tools
241 ;;
242 hypervisor)
243 install_deps
244 download_xen
245 copy_turnstile_sources
246 apply_patches
247 configure_xen
248 build_xen
249 install_xen
250 echo ""
251 echo "=== Turnstile-patched Xen ${XEN_VERSION} hypervisor installed ==="
252 echo ""
253 echo "Next steps:"
254 echo "1. Reboot and select Xen from the bootloader"
255 echo "2. Build turnstile-ctl: cd ${TURNSTILE_DIR}/turnstile-ctl && cargo build --release"
256 echo "3. Start a guest domain and run: turnstile-ctl protect <domid> /path/to/vmlinux"
257 ;;
258 all)
259 install_deps
260 download_xen
261 copy_turnstile_sources
262 apply_patches
263 configure_xen
264 build_xen
265 build_tools
266 install_xen
267 install_tools
268 echo ""
269 echo "=== Turnstile-patched Xen ${XEN_VERSION} installed ==="
270 echo ""
271 echo "Next steps:"
272 echo "1. Reboot and select Xen from the bootloader"
273 echo "2. Build turnstile-ctl: cd ${TURNSTILE_DIR}/turnstile-ctl && cargo build --release"
274 echo "3. Start a guest domain and run: turnstile-ctl protect <domid> /path/to/vmlinux"
275 ;;
276 *)
277 print_usage
278 exit 1
279 ;;
280esac