diff options
-rw-r--r-- | .SRCINFO | 20 | ||||
-rw-r--r-- | Makefile | 5 | ||||
-rw-r--r-- | PKGBUILD | 63 | ||||
-rw-r--r-- | dkms.conf.in | 15 | ||||
-rw-r--r-- | efi-patches.txt (renamed from efi-unlocker-patch-1.0.0.txt) | 0 | ||||
-rw-r--r-- | unlocker.py | 387 | ||||
-rw-r--r-- | vmmon.patch | 610 | ||||
-rw-r--r-- | vmnet.patch | 443 | ||||
-rw-r--r-- | vmware-networks.path | 8 | ||||
-rw-r--r-- | vmware-usbarbitrator.path | 8 | ||||
-rw-r--r-- | vmware-workstation.install | 21 |
11 files changed, 1490 insertions, 90 deletions
@@ -1,7 +1,7 @@ pkgbase = vmware-workstation14 pkgdesc = The industry standard for running multiple operating systems as virtual machines on a single Linux PC. pkgver = 14.1.7 - pkgrel = 6 + pkgrel = 25 url = https://www.vmware.com/products/workstation-for-linux.html install = vmware-workstation.install arch = x86_64 @@ -16,6 +16,10 @@ pkgbase = vmware-workstation14 depends = libaio depends = pcsclite depends = hicolor-icon-theme + depends = libxcrypt-compat + depends = fontconfig + depends = freetype2 + depends = harfbuzz depends = vmware-keymaps optdepends = linux-headers: build modules against Arch kernel provides = vmware-workstation=14.1.7 @@ -27,6 +31,7 @@ pkgbase = vmware-workstation14 conflicts = vmware-systemd-services options = !strip options = emptydirs + options = !debug backup = etc/vmware/config backup = etc/vmware/hostd/authorization.xml backup = etc/vmware/hostd/config.xml @@ -56,6 +61,8 @@ pkgbase = vmware-workstation14 source = vmware-networks-configuration.service source = vmware-networks.service source = vmware-usbarbitrator.service + source = vmware-networks.path + source = vmware-usbarbitrator.path source = dkms.conf.in source = Makefile source = vmmon.patch @@ -78,10 +85,11 @@ pkgbase = vmware-workstation14 sha256sums = 9b4fbe0ba83f761a2eb9ecd05d48428f8b0a5b3abd8404ccbd928408e682f02b sha256sums = c0a5aea785db06921fb350d36d5e0fd9a14f5eee0c835686ec6fea1af8c92245 sha256sums = d7a9fbf39a0345ae2f14f7f389f30b1110f605d187e0c241e99bbb18993c250d - sha256sums = 05e26d8b21d190ebabb7f693998114d9d5991d9dfb71acb4d990293a65b6b487 - sha256sums = 6ce902b1dab8fc69be253abd8e79017011985eca850ff7acc7282f9ab668e35d - sha256sums = 7bfbabd55c4c147538e96fa89e22827c6282d1231d6958391eebb59578e6188a - sha256sums = e712332335fde4e4846f18c3fa8c933f173336a44546f87ea02b1e1a53f15911 + sha256sums = 16a73931894a65d43da489ff25d07647c0ecddf60d443b103bceca63504910fe + sha256sums = fe1b1be8297f4170406f97dd1f8b385d911faf45afe19cbc0c26b8092b3ddf8d + sha256sums = 10562d11d50edab9abc2b29c8948714edcb9b084f99b3766d07ddd21259e372e + sha256sums = 273d4357599a3e54259c78cc49054fef8ecfd2c2eda35cbcde3a53a62777a5ac + sha256sums = 1789d14b184792db3fe0191aba0e4f733097dc058e73bf8c20a0a40cba74bfd8 + sha256sums = 42cd9eeca74db7ab9493ca8824b41d7aec837992ac273f1b32601a222d654388 pkgname = vmware-workstation14 - @@ -2,10 +2,7 @@ MODULES = \ vmmon \ - vmnet \ - #vmblock \ - #vmci \ - #vsock + vmnet all: $(foreach m, $(MODULES), $m.ko) @@ -16,7 +16,7 @@ pkgname=vmware-workstation14 pkgver=14.1.7 _buildver=12989993 _pkgver=${pkgver}_${_buildver} -pkgrel=6 +pkgrel=25 pkgdesc='The industry standard for running multiple operating systems as virtual machines on a single Linux PC.' arch=(x86_64) url='https://www.vmware.com/products/workstation-for-linux.html' @@ -43,6 +43,11 @@ depends=( libaio pcsclite hicolor-icon-theme + libxcrypt-compat # needed for ovftool + # needed to replace internal libs: + fontconfig + freetype2 + harfbuzz ) optdepends=( 'linux-headers: build modules against Arch kernel' @@ -85,6 +90,8 @@ source=( 'vmware-networks-configuration.service' 'vmware-networks.service' 'vmware-usbarbitrator.service' + 'vmware-networks.path' + 'vmware-usbarbitrator.path' 'dkms.conf.in' 'Makefile' @@ -113,13 +120,15 @@ sha256sums=( '9b4fbe0ba83f761a2eb9ecd05d48428f8b0a5b3abd8404ccbd928408e682f02b' 'c0a5aea785db06921fb350d36d5e0fd9a14f5eee0c835686ec6fea1af8c92245' 'd7a9fbf39a0345ae2f14f7f389f30b1110f605d187e0c241e99bbb18993c250d' + '16a73931894a65d43da489ff25d07647c0ecddf60d443b103bceca63504910fe' + 'fe1b1be8297f4170406f97dd1f8b385d911faf45afe19cbc0c26b8092b3ddf8d' - '05e26d8b21d190ebabb7f693998114d9d5991d9dfb71acb4d990293a65b6b487' - '6ce902b1dab8fc69be253abd8e79017011985eca850ff7acc7282f9ab668e35d' - '7bfbabd55c4c147538e96fa89e22827c6282d1231d6958391eebb59578e6188a' - 'e712332335fde4e4846f18c3fa8c933f173336a44546f87ea02b1e1a53f15911' + '10562d11d50edab9abc2b29c8948714edcb9b084f99b3766d07ddd21259e372e' + '273d4357599a3e54259c78cc49054fef8ecfd2c2eda35cbcde3a53a62777a5ac' + '1789d14b184792db3fe0191aba0e4f733097dc058e73bf8c20a0a40cba74bfd8' + '42cd9eeca74db7ab9493ca8824b41d7aec837992ac273f1b32601a222d654388' ) -options=(!strip emptydirs) +options=(!strip emptydirs !debug) if [ -z "$_remove_vmware_keymaps_dependency" ]; then depends+=( @@ -131,28 +140,27 @@ _isoimages=(freebsd linux linuxPreGlibc25 netware solaris windows winPre2k winPr if [ -n "$_enable_macOS_guests" ]; then -_vmware_fusion_ver=10.1.6_12989998 +_vmware_fusion_ver=10.1.6 +_vmware_fusion_buildver=12989998 +_vmware_fusion_ver_full=${_vmware_fusion_ver}_${_vmware_fusion_buildver} # List of VMware Fusion versions: https://softwareupdate.vmware.com/cds/vmw-desktop/fusion/ -_unlocker_ver=3.0.3 -_efi_unlocker_ver=1.0.0 - makedepends+=( python unzip - uefitool-git + uefitool ) source+=( - "darwinPre15-tools-${_vmware_fusion_ver}.zip.tar::https://softwareupdate.vmware.com/cds/vmw-desktop/fusion/${_vmware_fusion_ver/_//}/packages/com.vmware.fusion.tools.darwinPre15.zip.tar" - "darwin-tools-${_vmware_fusion_ver}.zip.tar::https://softwareupdate.vmware.com/cds/vmw-desktop/fusion/${_vmware_fusion_ver/_//}/packages/com.vmware.fusion.tools.darwin.zip.tar" - "unlocker-${_unlocker_ver}.py::https://raw.githubusercontent.com/paolo-projects/unlocker/${_unlocker_ver}/unlocker.py" - "efi-unlocker-patch-${_efi_unlocker_ver}.txt" + "darwinPre15-tools-${_vmware_fusion_ver_full}.zip.tar::https://softwareupdate.vmware.com/cds/vmw-desktop/fusion/${_vmware_fusion_ver_full/_//}/packages/com.vmware.fusion.tools.darwinPre15.zip.tar" + "darwin-tools-${_vmware_fusion_ver_full}.zip.tar::https://softwareupdate.vmware.com/cds/vmw-desktop/fusion/${_vmware_fusion_ver_full/_//}/packages/com.vmware.fusion.tools.darwin.zip.tar" + "unlocker.py" + "efi-patches.txt" ) sha256sums+=( '195313791f2c2cf880b0ba6c9d130e40ab6729335c0980fcc40df4209c1ed52b' 'e36fb99a56a65d2c4d82168c8adb1ed19a9a7aaf75807c667c79a79f4968740a' - '1c27547dcf6fb2f436c96ee62ae8c7f5cfd14b40d8bbd35dc385e247c4fb7e0f' + '8a61e03d0edbbf60c1c84a43aa87a6e950f82d2c71b968888f019345c2f684f3' '392c1effcdec516000e9f8ffc97f2586524d8953d3e7d6f2c5f93f2acd809d91' ) @@ -172,13 +180,13 @@ _create_database_file() { for isoimage in ${_isoimages[@]} do local version=$(cat "$srcdir/extracted/vmware-tools-$isoimage/manifest.xml" | grep -oPm1 "(?<=<version>)[^<]+") - sqlite3 "$database_filename" "INSERT INTO components(name,version,buildNumber,component_core_id,longName,description,type) VALUES(\"vmware-tools-$isoimage\",\"$version\",\"${_pkgver#*_}\",1,\"$isoimage\",\"$isoimage\",1);" + sqlite3 "$database_filename" "INSERT INTO components(name,version,buildNumber,component_core_id,longName,description,type) VALUES('vmware-tools-$isoimage','$version',${_pkgver#*_},1,'$isoimage','$isoimage',1);" done if [ -n "$_enable_macOS_guests" ]; then for isoimage in ${_fusion_isoimages[@]} do - sqlite3 "$database_filename" "INSERT INTO components(name,version,buildNumber,component_core_id,longName,description,type) VALUES(\"vmware-tools-$isoimage\",\"1\",\"${_vmware_fusion_ver#*_}\",1,\"$isoimage\",\"$isoimage\",1);" + sqlite3 "$database_filename" "INSERT INTO components(name,version,buildNumber,component_core_id,longName,description,type) VALUES('vmware-tools-$isoimage','1',${_vmware_fusion_ver_full#*_},1,'$isoimage','$isoimage',1);" done fi } @@ -200,7 +208,7 @@ if [ -n "$_enable_macOS_guests" ]; then rm -rf payload manifest.plist done - sed -i -e "s|/usr/lib/vmware/|${pkgdir}/usr/lib/vmware/|" "$srcdir/unlocker-${_unlocker_ver}.py" + sed -i -e "s|/usr/lib/vmware/|${pkgdir}/usr/lib/vmware/|" "$srcdir/unlocker.py" fi } @@ -210,7 +218,7 @@ package() { # Make directories and copy files. mkdir -p \ - "$pkgdir/etc"/{cups,pam.d,modprobe.d,profile.d,thnuclnt,vmware} \ + "$pkgdir/etc"/{cups,pam.d,modprobe.d,thnuclnt,vmware} \ "$pkgdir/usr"/{share,bin} \ "$pkgdir/usr/include/vmware-vix" \ "$pkgdir/usr/lib"/{vmware/{setup,lib/libvmware-vim-cmd.so},vmware-vix,vmware-ovftool,vmware-installer/"$vmware_installer_version",cups/filter,modules-load.d} \ @@ -330,7 +338,9 @@ fi vmware-authd.service \ vmware-networks-configuration.service \ vmware-networks.service \ - vmware-usbarbitrator.service + vmware-usbarbitrator.service \ + vmware-networks.path \ + vmware-usbarbitrator.path do install -Dm 644 \ "$srcdir/$service_file" \ @@ -428,7 +438,7 @@ fi -e "s/@PKGVER@/$_pkgver/g" \ -i "$dkms_dir/dkms.conf" - for module in vmmon vmnet; do # vmblock vmci vsock + for module in vmmon vmnet; do tar -xf "vmware-vmx/lib/modules/source/$module.tar" -C "$dkms_dir" msg "Patching $module module for DKMS" patch -p2 --read-only=ignore --directory="$dkms_dir/$module-only" < "$srcdir/$module.patch" @@ -438,7 +448,7 @@ fi if [ -n "$_enable_macOS_guests" ]; then msg "Patching VMware to enable macOS guest support" - python "$srcdir/unlocker-${_unlocker_ver}.py" > /dev/null + python3 "$srcdir/unlocker.py" > /dev/null for isoimage in ${_fusion_isoimages[@]} do @@ -447,10 +457,10 @@ if [ -n "$_enable_macOS_guests" ]; then done msg "Patching EFI firmwares to disable macOS server checking" - _efi_arch=(32 64) + _efi_arch=("32" "64") for arch in ${_efi_arch[@]} do - uefipatch "$pkgdir/usr/lib/vmware/roms/EFI${arch}.ROM" "$srcdir/efi-unlocker-patch-${_efi_unlocker_ver}.txt" -o "$pkgdir/usr/lib/vmware/roms/EFI${arch}.ROM" > /dev/null + uefipatch "$pkgdir/usr/lib/vmware/roms/EFI${arch}.ROM" "$srcdir/efi-patches.txt" -o "$pkgdir/usr/lib/vmware/roms/EFI${arch}.ROM" > /dev/null done fi @@ -472,4 +482,7 @@ fi # use system font rendering ln -sf /usr/lib/libfreetype.so.6 "$pkgdir/usr/lib/vmware/lib/libfreetype.so.6/" ln -sf /usr/lib/libfontconfig.so.1 "$pkgdir/usr/lib/vmware/lib/libfontconfig.so.1/" + + # to solve bugs with incompatibles library versions: + ln -sf /usr/lib/libharfbuzz.so.0 "$pkgdir/usr/lib/vmware/lib/libharfbuzz.so.0/" } diff --git a/dkms.conf.in b/dkms.conf.in index 64c93aa0c18c..5c7adc58ecde 100644 --- a/dkms.conf.in +++ b/dkms.conf.in @@ -13,18 +13,3 @@ DEST_MODULE_LOCATION[0]="/kernel/drivers/misc" BUILT_MODULE_NAME[1]="vmnet" BUILT_MODULE_LOCATION[1]='vmnet-only' DEST_MODULE_LOCATION[1]="/kernel/drivers/net" - -# seems that this module is never used -#BUILT_MODULE_NAME[2]="vmblock" -#BUILT_MODULE_LOCATION[2]='vmblock-only' -#DEST_MODULE_LOCATION[2]="/kernel/fs/vmblock" - -# vmci is already provided by the kernel with vmw_vmci -#BUILT_MODULE_NAME[3]="vmci" -#BUILT_MODULE_LOCATION[3]='vmci-only' -#DEST_MODULE_LOCATION[3]="/kernel/drivers/misc" - -# vsock is already provided by the kernel -#BUILT_MODULE_NAME[4]="vsock" -#BUILT_MODULE_LOCATION[4]='vsock-only' -#DEST_MODULE_LOCATION[4]="/kernel/net/vmw_vsock" diff --git a/efi-unlocker-patch-1.0.0.txt b/efi-patches.txt index 6451d1db0315..6451d1db0315 100644 --- a/efi-unlocker-patch-1.0.0.txt +++ b/efi-patches.txt diff --git a/unlocker.py b/unlocker.py new file mode 100644 index 000000000000..8ac86cb92951 --- /dev/null +++ b/unlocker.py @@ -0,0 +1,387 @@ +#!/usr/bin/env python3 +""" +vSMC Header Structure +Offset Length Struct Type Description +---------------------------------------- +0x00/00 0x08/08 Q ptr Offset to key table +0x08/08 0x04/4 I int Number of private keys +0x0C/12 0x04/4 I int Number of public keys + +vSMC Key Data Structure +Offset Length Struct Type Description +---------------------------------------- +0x00/00 0x04/04 4s int Key name (byte reversed e.g. #KEY is YEK#) +0x04/04 0x01/01 B byte Length of returned data +0x05/05 0x04/04 4s int Data type (byte reversed e.g. ui32 is 23iu) +0x09/09 0x01/01 B byte Flag R/W +0x0A/10 0x06/06 6x byte Padding +0x10/16 0x08/08 Q ptr Internal VMware routine +0x18/24 0x30/48 48B byte Data +""" + +import codecs +import os +import re +import struct +import sys + +if sys.version_info < (3, 6): + sys.stderr.write('You need Python 3.6 or later\n') + sys.exit(1) + +# Setup imports depending on whether IronPython or CPython +if sys.platform in ('cli', 'win32'): + # noinspection PyUnresolvedReferences + from winreg import * + + +def bytetohex(data): + return ''.join('{:02X} '.format(c) for c in data) + + +def joinpath(folder, filename): + return os.path.join(folder, filename) + + +def printkey(i, offset, smc_key, smc_data): + print(str(i + 1).zfill(3) + + ' ' + hex(offset) + + ' ' + smc_key[0][::-1].decode('UTF-8') + + ' ' + str(smc_key[1]).zfill(2) + + ' ' + smc_key[2][::-1].replace(b'\x00', b' ').decode('UTF-8') + + ' ' + '{0:#0{1}x}'.format(smc_key[3], 4) + + ' ' + hex(smc_key[4]) + + ' ' + bytetohex(smc_data)) + + +def set_bit(value, bit): + return value | (1 << bit) + + +def clear_bit(value, bit): + return value & ~(1 << bit) + + +def test_bit(value, bit): + return value & bit + + +E_CLASS64 = 2 +E_SHT_RELA = 4 + + +# noinspection PyUnusedLocal +def patchelf(f, oldoffset, newoffset): + f.seek(0) + magic = f.read(4) + if not magic == b'\x7fELF': + raise Exception('Magic number does not match') + + ei_class = struct.unpack('=B', f.read(1))[0] + if ei_class != E_CLASS64: + raise Exception('Not 64bit elf header: ' + ei_class) + + f.seek(40) + e_shoff = struct.unpack('=Q', f.read(8))[0] + f.seek(58) + e_shentsize = struct.unpack('=H', f.read(2))[0] + e_shnum = struct.unpack('=H', f.read(2))[0] + e_shstrndx = struct.unpack('=H', f.read(2))[0] + + print('e_shoff: 0x{:x} e_shentsize: 0x{:x} e_shnum:0x{:x} e_shstrndx:0x{:x}'.format(e_shoff, e_shentsize, + e_shnum, e_shstrndx)) + + for i in range(0, e_shnum): + f.seek(e_shoff + i * e_shentsize) + e_sh = struct.unpack('=LLQQQQLLQQ', f.read(e_shentsize)) + e_sh_name = e_sh[0] + e_sh_type = e_sh[1] + e_sh_offset = e_sh[4] + e_sh_size = e_sh[5] + e_sh_entsize = e_sh[9] + if e_sh_type == E_SHT_RELA: + e_sh_nument = int(e_sh_size / e_sh_entsize) + print('RELA at 0x{:x} with {:d} entries'.format(e_sh_offset, e_sh_nument)) + for j in range(0, e_sh_nument): + f.seek(e_sh_offset + e_sh_entsize * j) + rela = struct.unpack('=QQq', f.read(e_sh_entsize)) + r_offset = rela[0] + r_info = rela[1] + r_addend = rela[2] + if r_addend == oldoffset: + r_addend = newoffset + f.seek(e_sh_offset + e_sh_entsize * j) + f.write(struct.pack('=QQq', r_offset, r_info, r_addend)) + print('Relocation modified at: ' + hex(e_sh_offset + e_sh_entsize * j)) + + +def patchkeys(f, key): + # Setup struct pack string + key_pack = '=4sB4sB6xQ' + smc_old_memptr = 0 + smc_new_memptr = 0 + + # Do Until OSK1 read + i = 0 + while True: + + # Read key into struct str and data byte str + offset = key + (i * 72) + f.seek(offset) + smc_key = struct.unpack(key_pack, f.read(24)) + smc_data = f.read(smc_key[1]) + + # Reset pointer to beginning of key entry + f.seek(offset) + + if smc_key[0] == b'SKL+': + # Use the +LKS data routine for OSK0/1 + smc_new_memptr = smc_key[4] + print('+LKS Key: ') + printkey(i, offset, smc_key, smc_data) + + elif smc_key[0] == b'0KSO': + # Write new data routine pointer from +LKS + print('OSK0 Key Before:') + printkey(i, offset, smc_key, smc_data) + smc_old_memptr = smc_key[4] + f.seek(offset) + f.write(struct.pack(key_pack, smc_key[0], smc_key[1], smc_key[2], smc_key[3], smc_new_memptr)) + f.flush() + + # Write new data for key + f.seek(offset + 24) + smc_new_data = codecs.encode('bheuneqjbexolgurfrjbeqfthneqrqcy', 'rot_13') + f.write(smc_new_data.encode('UTF-8')) + f.flush() + + # Re-read and print key + f.seek(offset) + smc_key = struct.unpack(key_pack, f.read(24)) + smc_data = f.read(smc_key[1]) + print('OSK0 Key After:') + printkey(i, offset, smc_key, smc_data) + + elif smc_key[0] == b'1KSO': + # Write new data routine pointer from +LKS + print('OSK1 Key Before:') + printkey(i, offset, smc_key, smc_data) + smc_old_memptr = smc_key[4] + f.seek(offset) + f.write(struct.pack(key_pack, smc_key[0], smc_key[1], smc_key[2], smc_key[3], smc_new_memptr)) + f.flush() + + # Write new data for key + f.seek(offset + 24) + smc_new_data = codecs.encode('rnfrqbagfgrny(p)NccyrPbzchgreVap', 'rot_13') + f.write(smc_new_data.encode('UTF-8')) + f.flush() + + # Re-read and print key + f.seek(offset) + smc_key = struct.unpack(key_pack, f.read(24)) + smc_data = f.read(smc_key[1]) + print('OSK1 Key After:') + printkey(i, offset, smc_key, smc_data) + + # Finished so get out of loop + break + + # elif smc_key[0] == b'WPPK': + # # Set the old SMC password as an addtional marker that vmx has been patched + # # This has no functional value except for checking status + # print('KPPW Key Before:') + # printkey(i, offset, smc_key, smc_data) + # f.seek(offset + 24) + # f.write('SpecialisRevelio'.encode('UTF-8')) + # + # # Re-read and print key + # f.seek(offset) + # smc_key = struct.unpack(key_pack, f.read(24)) + # smc_data = f.read(smc_key[1]) + # print('KPPW Key After:') + # printkey(i, offset, smc_key, smc_data) + + else: + pass + + i += 1 + return smc_old_memptr, smc_new_memptr + + +def patchsmc(name, sharedobj): + with open(name, 'r+b') as f: + + smc_old_memptr = 0 + smc_new_memptr = 0 + + # Read file into string variable + vmx = f.read() + + print('File: ' + name + '\n') + + # Setup hex string for vSMC headers + # These are the private and public key counts + smc_header_v0 = b'\xF2\x00\x00\x00\xF0\x00\x00\x00' + smc_header_v1 = b'\xB4\x01\x00\x00\xB0\x01\x00\x00' + + # Setup hex string for #KEY key + key_key = b'\x59\x45\x4B\x23\x04\x32\x33\x69\x75' + + # Setup hex string for $Adr key + adr_key = b'\x72\x64\x41\x24\x04\x32\x33\x69\x75' + + # Find the vSMC headers + smc_header_v0_offset = vmx.find(smc_header_v0) - 8 + smc_header_v1_offset = vmx.find(smc_header_v1) - 8 + + # Find '#KEY' keys + smc_key0 = vmx.find(key_key) + smc_key1 = vmx.rfind(key_key) + + # Find '$Adr' key table + smc_adr = vmx.find(adr_key) + + # Print vSMC0 tables and keys + print('appleSMCTableV0 (smc.version = "0")') + print('appleSMCTableV0 Address : ' + hex(smc_header_v0_offset)) + print('appleSMCTableV0 Private Key #: 0xF2/242') + print('appleSMCTableV0 Public Key #: 0xF0/240') + + if (smc_adr - smc_key0) != 72: + print('appleSMCTableV0 Table : ' + hex(smc_key0)) + smc_old_memptr, smc_new_memptr = patchkeys(f, smc_key0) + elif (smc_adr - smc_key1) != 72: + print('appleSMCTableV0 Table : ' + hex(smc_key1)) + smc_old_memptr, smc_new_memptr = patchkeys(f, smc_key1) + + print() + + # Print vSMC1 tables and keys + print('appleSMCTableV1 (smc.version = "1")') + print('appleSMCTableV1 Address : ' + hex(smc_header_v1_offset)) + print('appleSMCTableV1 Private Key #: 0x01B4/436') + print('appleSMCTableV1 Public Key #: 0x01B0/432') + + if (smc_adr - smc_key0) == 72: + print('appleSMCTableV1 Table : ' + hex(smc_key0)) + smc_old_memptr, smc_new_memptr = patchkeys(f, smc_key0) + elif (smc_adr - smc_key1) == 72: + print('appleSMCTableV1 Table : ' + hex(smc_key1)) + smc_old_memptr, smc_new_memptr = patchkeys(f, smc_key1) + + print() + + # Find matching RELA record in .rela.dyn in ESXi ELF files + # This is temporary code until proper ELF parsing written + if sharedobj: + print('Modifying RELA records from: ' + hex(smc_old_memptr) + ' to ' + hex(smc_new_memptr)) + patchelf(f, smc_old_memptr, smc_new_memptr) + + # Tidy up + f.flush() + f.close() + + +def patchbase(name): + # Patch file + print('GOS Patching: ' + name) + f = open(name, 'r+b') + + # Entry to search for in GOS table + # Should work for Workstation 12-15... + darwin = re.compile( + b'\x10\x00\x00\x00[\x10|\x20]\x00\x00\x00[\x01|\x02]\x00\x00\x00\x00\x00\x00\x00' + b'\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00') + + # Read file into string variable + base = f.read() + + # Loop through each entry and set top bit + # 0xBE --> 0xBF (WKS 12/13) + # 0x3E --> 0x3F (WKS 14+) + for m in darwin.finditer(base): + offset = m.start() + f.seek(offset + 32) + flag = ord(f.read(1)) + flag = set_bit(flag, 0) + # flag = chr(flag) + f.seek(offset + 32) + f.write(bytes([flag])) + print('GOS Patched flag @: ' + hex(offset)) + + # Tidy up + f.flush() + f.close() + print('GOS Patched: ' + name) + + +def patchvmkctl(name): + # Patch file + print('smcPresent Patching: ' + name) + f = open(name, 'r+b') + + # Read file into string variable + vmkctl = f.read() + applesmc = vmkctl.find(b'applesmc') + f.seek(applesmc) + f.write(b'vmkernel') + + # Tidy up + f.flush() + f.close() + print('smcPresent Patched: ' + name) + + +# noinspection PyUnresolvedReferences +def main(): + # Work around absent Platform module on VMkernel + if os.name == 'nt' or os.name == 'cli': + osname = 'windows' + else: + osname = os.uname()[0].lower() + + # vmwarebase = '' + vmx_so = False + + # Setup default paths + if osname == 'linux': + # TODO: Dynamically find Linux installation + # Path the install is stored in /etc/vmware/config + # libdir = "/usr/lib/vmware" + vmx_path = '/usr/lib/vmware/bin/' + vmx = joinpath(vmx_path, 'vmware-vmx') + vmx_debug = joinpath(vmx_path, 'vmware-vmx-debug') + vmx_stats = joinpath(vmx_path, 'vmware-vmx-stats') + vmx_so = True + if os.path.isfile('/usr/lib/vmware/lib/libvmwarebase.so/libvmwarebase.so'): + vmwarebase = '/usr/lib/vmware/lib/libvmwarebase.so/libvmwarebase.so' + else: + vmwarebase = '/usr/lib/vmware/lib/libvmwarebase.so.0/libvmwarebase.so.0' + + elif osname == 'windows': + reg = ConnectRegistry(None, HKEY_LOCAL_MACHINE) + key = OpenKey(reg, r'SOFTWARE\Wow6432Node\VMware, Inc.\VMware Workstation') + vmwarebase_path = QueryValueEx(key, 'InstallPath')[0] + vmx_path = QueryValueEx(key, 'InstallPath64')[0] + vmx = joinpath(vmx_path, 'vmware-vmx.exe') + vmx_debug = joinpath(vmx_path, 'vmware-vmx-debug.exe') + vmx_stats = joinpath(vmx_path, 'vmware-vmx-stats.exe') + vmwarebase = joinpath(vmwarebase_path, 'vmwarebase.dll') + + else: + print('Unknown Operating System: ' + osname) + return + + # Patch the vmx executables skipping stats version for Player + patchsmc(vmx, vmx_so) + patchsmc(vmx_debug, vmx_so) + if os.path.isfile(vmx_stats): + patchsmc(vmx_stats, vmx_so) + + # Patch vmwarebase for Workstation and Player + patchbase(vmwarebase) + + +if __name__ == '__main__': + main() diff --git a/vmmon.patch b/vmmon.patch index 0d515e717502..98a264139759 100644 --- a/vmmon.patch +++ b/vmmon.patch @@ -1,6 +1,6 @@ --- a/vmmon/Makefile +++ b/vmmon/Makefile -@@ -43,7 +43,11 @@ INCLUDE += -I$(SRCROOT)/shared +@@ -43,7 +43,11 @@ endif @@ -12,7 +12,7 @@ # Header directory for the running kernel ifdef LINUXINCLUDE -@@ -98,6 +98,13 @@ auto-build: $(DRIVER_KO) +@@ -98,6 +102,13 @@ auto-build: $(DRIVER_KO) $(DRIVER): $(DRIVER_KO) if [ $< -nt $@ ] || [ ! -e $@ ] ; then cp -f $< $@; fi @@ -26,7 +26,7 @@ # # Define a setup target that gets built before the actual driver. # This target may not be used at all, but if it is then it will be defined -@@ -107,7 +114,7 @@ prebuild:: ; +@@ -107,7 +118,7 @@ prebuild:: ; postbuild:: ; $(DRIVER_KO): prebuild @@ -35,9 +35,23 @@ MODULEBUILDDIR=$(MODULEBUILDDIR) modules $(MAKE) -C $$PWD SRCROOT=$$PWD/$(SRCROOT) \ MODULEBUILDDIR=$(MODULEBUILDDIR) postbuild +--- a/vmmon/include/pgtbl.h ++++ b/vmmon/include/pgtbl.h +@@ -91,7 +91,11 @@ + } else { + pte_t *pte; + ++#if LINUX_VERSION_CODE >= KERNEL_VERSION(6,5,0) ++ pte = pte_offset_kernel(pmd, addr); ++#else + pte = pte_offset_map(pmd, addr); ++#endif + if (pte_present(*pte) == 0) { + pte_unmap(pte); + return INVALID_MPN; --- a/vmmon/linux/driver.c +++ b/vmmon/linux/driver.c -@@ -96,7 +95,9 @@ long LinuxDriver_Ioctl(struct file *filp, u_int iocmd, +@@ -96,7 +96,9 @@ long LinuxDriver_Ioctl(struct file *filp unsigned long ioarg); static int LinuxDriver_Close(struct inode *inode, struct file *filp); @@ -48,7 +62,43 @@ static int LinuxDriverFault(struct vm_fault *fault); #else static int LinuxDriverFault(struct vm_area_struct *vma, struct vm_fault *fault); -@@ -594,7 +596,12 @@ LinuxDriver_Close(struct inode *inode, // IN +@@ -259,7 +261,7 @@ + /* + *---------------------------------------------------------------------- + * +- * init_module -- ++ * LinuxDriverInit -- + * + * linux module entry point. Called by /sbin/insmod command + * +@@ -272,7 +274,7 @@ + */ + + int +-init_module(void) ++LinuxDriverInit(void) + { + int retval; + +@@ -351,7 +353,7 @@ + /* + *---------------------------------------------------------------------- + * +- * cleanup_module -- ++ * LinuxDriverExit -- + * + * Called by /sbin/rmmod + * +@@ -360,7 +362,7 @@ + */ + + void +-cleanup_module(void) ++LinuxDriverExit(void) + { + /* + * XXX smp race? +@@ -594,7 +596,12 @@ LinuxDriver_Close(struct inode *inode, / *----------------------------------------------------------------------------- */ @@ -62,9 +112,113 @@ #if LINUX_VERSION_CODE >= KERNEL_VERSION(4, 11, 0) LinuxDriverFault(struct vm_fault *fault) //IN/OUT #else +@@ -761,7 +768,11 @@ LinuxDriverMmap(struct file *filp, + return err; + } + /* Clear VM_IO, otherwise SuSE's kernels refuse to do get_user_pages */ ++#if COMPAT_LINUX_VERSION_CHECK_LT(6, 3, 0) + vma->vm_flags &= ~VM_IO; ++#else ++ vm_flags_clear(vma, VM_IO); ++#endif + + return 0; + } +@@ -1751,3 +1762,5 @@ + * by default (i.e., neither mkinitrd nor modprobe will accept it). + */ + MODULE_INFO(supported, "external"); ++module_init(LinuxDriverInit); ++module_exit(LinuxDriverExit); --- a/vmmon/linux/hostif.c +++ a/vmmon/linux/hostif.c -@@ -1499,9 +1499,13 @@ +@@ -47,6 +47,8 @@ + #include <asm/asm.h> + #include <asm/io.h> + #include <asm/page.h> ++#include <asm/tlbflush.h> ++#include <asm/irq_vectors.h> + #include <asm/uaccess.h> + #include <linux/capability.h> + #include <linux/kthread.h> +@@ -54,6 +56,7 @@ + #include <linux/hrtimer.h> + #include <linux/signal.h> + #include <linux/taskstats_kern.h> // For linux/sched/signal.h without version check ++#include <linux/eventfd.h> + + #include "vmware.h" + #include "x86apic.h" +@@ -79,6 +82,13 @@ + #error CONFIG_HIGH_RES_TIMERS required for acceptable performance + #endif + ++/* task's state is read-once rather than volatile from 5.14-rc2. */ ++#if LINUX_VERSION_CODE >= KERNEL_VERSION(5, 15, 0) || defined(get_current_state) ++#define get_task_state(task) READ_ONCE((task)->__state) ++#else ++#define get_task_state(task) ((task)->state) ++#endif ++ + /* + * Although this is not really related to kernel-compatibility, I put this + * helper macro here for now for a lack of better place --hpreg +@@ -442,7 +452,7 @@ + while ((vcpuid = VCPUSet_FindFirst(&req)) != VCPUID_INVALID) { + struct task_struct *t = vm->vmhost->vcpuSemaTask[vcpuid]; + VCPUSet_Remove(&req, vcpuid); +- if (t && (t->state & TASK_INTERRUPTIBLE)) { ++ if (t && (get_task_state(t) & TASK_INTERRUPTIBLE)) { + wake_up_process(t); + } + } +@@ -593,6 +596,15 @@ HostIF_FastClockUnlock(int callerID) // + MutexUnlock(&fastClockMutex, callerID); + } + ++#if LINUX_VERSION_CODE >= KERNEL_VERSION(5, 8, 0) ++static int crosspage_set_exec(pte_t *pte, unsigned long addr, void *data) ++{ ++ struct page *p = data; ++ ++ set_pte(pte, mk_pte(p, VM_PAGE_KERNEL_EXEC)); ++ return 0; ++} ++#endif + + /* + *---------------------------------------------------------------------- +@@ -613,7 +625,29 @@ HostIF_FastClockUnlock(int callerID) // + static void * + MapCrossPage(struct page *p) // IN: + { ++#if COMPAT_LINUX_VERSION_CHECK_LT(5, 8, 0) + return vmap(&p, 1, VM_MAP, VM_PAGE_KERNEL_EXEC); ++#else ++ void *addr; ++ ++ addr = vmap(&p, 1, VM_MAP, VM_PAGE_KERNEL_EXEC); ++ if (!addr) ++ return NULL; ++ ++ /* Starting with 5.8, vmap() always sets the NX bit, but the cross ++ * page needs to be executable. */ ++ if (apply_to_page_range(current->mm, (unsigned long)addr, PAGE_SIZE, ++ crosspage_set_exec, p)) { ++ vunmap(addr); ++ return NULL; ++ } ++ ++ preempt_disable(); ++ __flush_tlb_all(); ++ preempt_enable(); ++ ++ return addr; ++#endif + } + + +@@ -1499,9 +1533,13 @@ HostIF_EstimateLockedPageLimit(const VMD * since at least 2.6.0. */ @@ -78,7 +232,19 @@ /* * Use the memory information linux exports as of late for a more -@@ -1602,6 +1606,49 @@ +@@ -1527,7 +1565,10 @@ HostIF_EstimateLockedPageLimit(const VMD + lockedPages += global_page_state(NR_PAGETABLE); + #endif + /* NR_SLAB_* moved from zone to node in 4.13. */ +-#if LINUX_VERSION_CODE >= KERNEL_VERSION(4, 13, 0) ++ ++#if LINUX_VERSION_CODE >= KERNEL_VERSION(5, 9, 0) ++ lockedPages += global_node_page_state_pages(NR_SLAB_UNRECLAIMABLE_B); ++#elif LINUX_VERSION_CODE >= KERNEL_VERSION(4, 13, 0) + lockedPages += global_node_page_state(NR_SLAB_UNRECLAIMABLE); + #else + lockedPages += global_page_state(NR_SLAB_UNRECLAIMABLE); +@@ -1602,6 +1643,49 @@ HostIF_WaitForFreePages(unsigned int tim /* *---------------------------------------------------------------------- * @@ -128,7 +294,7 @@ * HostIFReadUptimeWork -- * * Reads the current uptime. The uptime is based on getimeofday, -@@ -1630,7 +1677,6 @@ +@@ -1630,7 +1714,6 @@ HostIF_WaitForFreePages(unsigned int tim static uint64 HostIFReadUptimeWork(unsigned long *j) // OUT: current jiffies { @@ -136,7 +302,7 @@ uint64 monotime, uptime, upBase, monoBase; int64 diff; uint32 version; -@@ -1645,13 +1691,12 @@ +@@ -1645,13 +1728,12 @@ HostIFReadUptimeWork(unsigned long *j) monoBase = uptimeState.monotimeBase; } while (!VersionedAtomic_EndTryRead(&uptimeState.version, version)); @@ -151,7 +317,7 @@ uptime += upBase; /* -@@ -1756,13 +1801,11 @@ +@@ -1756,13 +1838,11 @@ HostIFUptimeResyncMono(struct timer_list void HostIF_InitUptime(void) { @@ -168,16 +334,37 @@ #if LINUX_VERSION_CODE < KERNEL_VERSION(4, 15, 0) && !defined(timer_setup) init_timer(&uptimeState.timer); -@@ -2164,7 +2207,7 @@ isVAReadable(VA r) // IN: +@@ -2159,16 +2239,26 @@ HostIF_VMLockIsHeld(VMDriver *vm) // IN + static Bool + isVAReadable(VA r) // IN: + { +- mm_segment_t old_fs; + uint32 dummy; int ret; ++#if defined(HAVE_GET_KERNEL_NOFAULT) || LINUX_VERSION_CODE >= KERNEL_VERSION(5, 17, 0) ++ /* ++ * Exists from 5.10, first indicated by HAVE_GET_KERNEL_NOFAULT, ++ * and from post-5.17 just existing everywhere. ++ */ ++ ret = get_kernel_nofault(dummy, (void *)r); ++#else ++ { ++ mm_segment_t old_fs; ++ old_fs = get_fs(); - set_fs(get_ds()); + set_fs(KERNEL_DS); r = APICR_TO_ADDR(r, APICR_VERSION); ret = HostIF_CopyFromUser(&dummy, r, sizeof dummy); set_fs(old_fs); -@@ -2197,7 +2240,7 @@ +- ++ } ++#endif + return ret == 0; + } + +@@ -2197,7 +2283,7 @@ SetVMAPICAddr(VMDriver *vm, // IN/OUT: d volatile void *hostapic; ASSERT_ON_COMPILE(APICR_SIZE <= PAGE_SIZE); @@ -186,25 +373,146 @@ if (hostapic) { if ((APIC_VERSIONREG(hostapic) & 0xF0) == 0x10) { vm->hostAPIC.base = (volatile uint32 (*)[4]) hostapic; -@@ -2365,7 +2408,7 @@ HostIF_SemaphoreWait(VMDriver *vm, // IN: +@@ -2353,7 +2439,6 @@ HostIF_SemaphoreWait(VMDriver *vm, // + uint64 *args) // IN: + { + struct file *file; +- mm_segment_t old_fs; + int res; + int waitFD = args[0]; + int timeoutms = args[2]; +@@ -2364,22 +2449,19 @@ HostIF_SemaphoreWait(VMDriver *vm, // + return MX_WAITERROR; } - old_fs = get_fs(); +- old_fs = get_fs(); - set_fs(get_ds()); -+ set_fs(KERNEL_DS); - +- { struct poll_wqueues table; -@@ -2494,7 +2537,7 @@ HostIF_SemaphoreSignal(uint64 *args) // IN: + unsigned int mask; + + poll_initwait(&table); +- current->state = TASK_INTERRUPTIBLE; ++ __set_current_state(TASK_INTERRUPTIBLE); + mask = file->f_op->poll(file, &table.pt); + if (!(mask & (POLLIN | POLLERR | POLLHUP))) { + vm->vmhost->vcpuSemaTask[vcpuid] = current; + schedule_timeout(timeoutms * HZ / 1000); // convert to Hz + vm->vmhost->vcpuSemaTask[vcpuid] = NULL; + } +- current->state = TASK_RUNNING; ++ __set_current_state(TASK_RUNNING); + poll_freewait(&table); } - old_fs = get_fs(); +@@ -2388,9 +2470,11 @@ HostIF_SemaphoreWait(VMDriver *vm, // + * the code to happily deal with a pipe or an eventfd. We only care about + * reading no bytes (EAGAIN - non blocking fd) or sizeof(uint64). + */ +- +- res = file->f_op->read(file, (char *) &value, sizeof value, &file->f_pos); +- ++#if LINUX_VERSION_CODE < KERNEL_VERSION(4, 14, 0) ++ res = kernel_read(file, file->f_pos, (char *)&value, sizeof value); ++#else ++ res = kernel_read(file, &value, sizeof value, &file->f_pos); ++#endif + if (res == sizeof value) { + res = MX_WAITNORMAL; + } else { +@@ -2399,7 +2483,6 @@ HostIF_SemaphoreWait(VMDriver *vm, // + } + } + +- set_fs(old_fs); + fput(file); + + /* +@@ -2452,7 +2542,7 @@ + FOR_EACH_VCPU_IN_SET(vcs, vcpuid) { + struct task_struct *t = vm->vmhost->vcpuSemaTask[vcpuid]; + vm->vmhost->vcpuSemaTask[vcpuid] = NULL; +- if (t && (t->state & TASK_INTERRUPTIBLE)) { ++ if (t && (get_task_state(t) & TASK_INTERRUPTIBLE)) { + wake_up_process(t); + } + } ROF_EACH_VCPU_IN_SET(); +@@ -2482,8 +2565,8 @@ HostIF_SemaphoreForceWakeup(VMDriver *vm + int + HostIF_SemaphoreSignal(uint64 *args) // IN: + { ++ struct eventfd_ctx *eventfd; + struct file *file; +- mm_segment_t old_fs; + int res; + int signalFD = args[1]; + uint64 value = 1; // make an eventfd happy should it be there +@@ -2493,22 +2576,36 @@ HostIF_SemaphoreSignal(uint64 *args) // + return MX_WAITERROR; + } + +- old_fs = get_fs(); - set_fs(get_ds()); -+ set_fs(KERNEL_DS); ++ /* ++ * If it's eventfd, use specific eventfd interface as kernel writes ++ * to eventfd may not be allowed in kernel 5.10 and later. ++ */ ++ eventfd = eventfd_ctx_fileget(file); ++ if (!IS_ERR(eventfd)) { ++#if COMPAT_LINUX_VERSION_CHECK_LT(6, 8, 0) ++ eventfd_signal(eventfd, 1); ++#else ++ eventfd_signal(eventfd); ++#endif ++ fput(file); ++ return MX_WAITNORMAL; ++ } /* * Always write sizeof(uint64) bytes. This works fine for eventfd and -@@ -3154,7 +3202,6 @@ HostIF_SetFastClockRate(unsigned int rate) // IN: Frequency in Hz. + * pipes. The data written is formatted to make an eventfd happy should + * it be present. + */ +- +- res = file->f_op->write(file, (char *) &value, sizeof value, &file->f_pos); ++#if LINUX_VERSION_CODE < KERNEL_VERSION(4, 14, 0) ++ res = kernel_write(file, (char *)&value, sizeof value, file->f_pos); ++#else ++ res = kernel_write(file, &value, sizeof value, &file->f_pos); ++#endif + + if (res == sizeof value) { + res = MX_WAITNORMAL; + } + +- set_fs(old_fs); + fput(file); + + /* +@@ -3027,12 +3120,9 @@ static int + HostIFFastClockThread(void *unused) // IN: + { + int res; +- mm_segment_t oldFS; + unsigned int rate = 0; + unsigned int prevRate = 0; + +- oldFS = get_fs(); +- set_fs(KERNEL_DS); + allow_signal(SIGKILL); + + while ((rate = linuxState.fastClockRate) > MIN_RATE) { +@@ -3055,8 +3145,6 @@ HostIFFastClockThread(void *unused) // + } + + out: +- set_fs(oldFS); +- + /* + * Do not exit thread until we are told to do so. + */ +@@ -3154,7 +3242,6 @@ HostIF_SetFastClockRate(unsigned int rat } } else { if (linuxState.fastClockThread) { @@ -212,7 +520,7 @@ kthread_stop(linuxState.fastClockThread); linuxState.fastClockThread = NULL; -@@ -3200,7 +3243,12 @@ +@@ -3200,7 +3287,12 @@ HostIF_MapUserMem(VA addr, ASSERT(handle); @@ -226,3 +534,263 @@ printk(KERN_ERR "%s: Couldn't verify write to uva 0x%p with size %" FMTSZ"u\n", __func__, p, size); +From 4c2a103fd2d71f2084f1fe7ceacb816b9832ffa2 Mon Sep 17 00:00:00 2001 +From: Michal Kubecek <mkubecek@suse.cz> +Date: Sun, 22 Oct 2023 23:24:05 +0200 +Subject: [PATCH] vmmon: use get_user_pages to get page PFN + +As a side effect of mainline commit 0d940a9b270b ("mm/pgtable: allow +pte_offset_map[_lock]() to fail") in 6.5-rc1, __pte_offset_map(), called by +pte_offset_map(), is no longer exported. WMware developers decided to hack +around this by replacing pte_offset_map() by pte_offset_kernel() which does +not seem to be a good idea and apparently may trigger warn checks in RCU +code on some systems as mentioned in the discussion on issue #223. +Therefore let's use the same solution as we had for 17.0.2 and older +versions as it does not show these problems. + +Based on an upstream IRC discussion and the hva_to_pfn_*() family of +functions in KVM code, what PgtblVa2MPNLocked() does seems to be an +incomplete and partial open coded logic of get_user_pages() and as it is +only used to get PFN from a virtual address, it can be easily implemented +using get_user_pages() family. + +Without knowledge what exactly are the PFNs used for in VMware, it is hard +to guess the right flags, these seem to work and have been tested by +multiple users over last few weeks. + +We could likely use get_user_pages() also on older kernels and it might be +actually cleaner and more reliable as existing open coded implementation +does not seem to handle some corner cases but without knowledge of VMware +internals, it will be safer to stick to existing code where possible. +--- + vmmon-only/include/pgtbl.h | 25 +++++++++++++++++++++++++ + 1 file changed, 25 insertions(+) + +diff --git a/vmmon-only/include/pgtbl.h b/vmmon-only/include/pgtbl.h +index 3f43c62..7eaa49a 100644 +--- a/vmmon-only/include/pgtbl.h ++++ b/vmmon-only/include/pgtbl.h +@@ -25,6 +25,7 @@ + #include "compat_pgtable.h" + #include "compat_spinlock.h" + #include "compat_page.h" ++#include "compat_version.h" + + + /* +@@ -45,6 +46,7 @@ + *----------------------------------------------------------------------------- + */ + ++#if COMPAT_LINUX_VERSION_CHECK_LT(6, 5, 0) // only used by PgtblVa2MPN() below + static INLINE MPN + PgtblVa2MPNLocked(struct mm_struct *mm, // IN: Mm structure of a process + VA addr) // IN: Address in the virtual address +@@ -110,6 +112,7 @@ PgtblVa2MPNLocked(struct mm_struct *mm, // IN: Mm structure of a process + } + return mpn; + } ++#endif + + + /* +@@ -129,6 +132,8 @@ PgtblVa2MPNLocked(struct mm_struct *mm, // IN: Mm structure of a process + *----------------------------------------------------------------------------- + */ + ++#if COMPAT_LINUX_VERSION_CHECK_LT(6, 5, 0) ++ + static INLINE MPN + PgtblVa2MPN(VA addr) // IN + { +@@ -143,4 +148,24 @@ PgtblVa2MPN(VA addr) // IN + return mpn; + } + ++#else /* COMPAT_LINUX_VERSION_CHECK_LT(6, 5, 0) */ ++ ++static INLINE MPN ++PgtblVa2MPN(VA addr) // IN ++{ ++ struct page *page; ++ int npages; ++ MPN mpn; ++ ++ npages = get_user_pages_unlocked(addr, 1, &page, FOLL_HWPOISON); ++ if (npages != 1) ++ return INVALID_MPN; ++ mpn = page_to_pfn(page); ++ put_page(page); ++ ++ return mpn; ++} ++ ++#endif /* COMPAT_LINUX_VERSION_CHECK_LT(6, 5, 0) */ ++ + #endif /* __PGTBL_H__ */ +From add7a6d8b99565fdfa79098315b0a69fd244eda3 Mon Sep 17 00:00:00 2001 +From: Michal Kubecek <mkubecek@suse.cz> +Date: Fri, 12 Jan 2024 08:30:33 +0100 +Subject: [PATCH] modules: fix build with -Wmissing-prototypes + +Mainline commit 0fcb70851fbf ("Makefile.extrawarn: turn on +missing-prototypes globally") in 6.8-rc1 enables -Wmissing-prototypes +globally, revealing a lot of unclean code and also some actual problems. +This is also the case in vmmon and vmnet modules. + +Most of them are addressed by making functions used only within one file +static. A special case are Vmx86_MapPage() and Vmx86_UnmapPage() which were +defined since Workstation 14.0.0 but they are not actually used anywhere +until 15.0.0 so that dropping them seems to be the best option. + +The missing prototype of random_get_entropy_fallback() is handled by +including <linux/timex.h> rather than <asm/timex.h>. + +Finally, there are four functions in vmnet module which are actually used +in multiple files but instead of proper declarations, their prototype is +duplicated in vmnet-only/driver.c, risking that the two copies won't match +(which actually happened in one case). The cleanest solution would be +creating separate header files for them (bridge.h, netif.h, userif.h and +vnetUserListener.h) and including them in the respective source file and +driver.c. As the developers already handle similar cases by simply putting +the declarations into vnetInt.h, let us do the same to keep things simple. +--- + vmmon-only/bootstrap/monLoaderVmmon.c | 1 + + vmmon-only/common/vmx86.c | 50 +-------------------------- + vmmon-only/linux/driver.c | 4 +-- + vmmon-only/linux/hostif.c | 6 ++-- + vmnet-only/bridge.c | 2 +- + vmnet-only/driver.c | 16 ++------- + vmnet-only/vnetInt.h | 7 ++++ + 7 files changed, 17 insertions(+), 69 deletions(-) + +diff --git a/vmmon-only/bootstrap/monLoaderVmmon.c b/vmmon-only/bootstrap/monLoaderVmmon.c +index 6879e617..55bcd2c3 100644 +--- a/vmmon-only/bootstrap/monLoaderVmmon.c ++++ b/vmmon-only/bootstrap/monLoaderVmmon.c +@@ -37,6 +37,7 @@ + #include "x86paging_common.h" + #include "x86paging_64.h" + #include "vmx86.h" ++#include "monLoader.h" + #include "monLoaderLog.h" + + typedef struct MonLoaderEnvContext { +diff --git a/vmmon-only/common/vmx86.c b/vmmon-only/common/vmx86.c +index f6b0d6fc..69455206 100644 +--- a/vmmon-only/common/vmx86.c ++++ b/vmmon-only/common/vmx86.c +@@ -58,7 +58,7 @@ + #include "x86svm.h" + #include "x86cpuid_asm.h" + #if defined(linux) +-#include <asm/timex.h> ++#include <linux/timex.h> + #endif + #include "x86perfctr.h" + #include "x86vtinstr.h" +@@ -3066,51 +3066,3 @@ Vmx86_GetPageRoot(VMDriver *vm, // IN: + *mpn = vm->ptRootMpns[vcpuid]; + return TRUE; + } +- +- +-/* +- *---------------------------------------------------------------------- +- * +- * Vmx86_MapPage -- +- * +- * Maps the specified MPN into the host kernel address space. +- * returns the VPN of the mapping. +- * +- * Results: +- * The VPN in the kernel address space of the new mapping, or 0 if +- * the mapping failed. +- * +- * Side effects: +- * None. +- * +- *---------------------------------------------------------------------- +- */ +- +-VPN +-Vmx86_MapPage(MPN mpn) // IN: +-{ +- return HostIF_MapPage(mpn); +-} +- +- +-/* +- *---------------------------------------------------------------------- +- * +- * Vmx86_UnmapPage -- +- * +- * Unmaps the specified VPN from the host kernel address space. +- * +- * Results: +- * None. +- * +- * Side effects: +- * None. +- * +- *---------------------------------------------------------------------- +- */ +- +-void +-Vmx86_UnmapPage(VPN vpn) // IN: +-{ +- HostIF_UnmapPage(vpn); +-} +diff --git a/vmmon-only/linux/driver.c b/vmmon-only/linux/driver.c +index f015eb0b..337b1cf8 100644 +--- a/vmmon-only/linux/driver.c ++++ b/vmmon-only/linux/driver.c +@@ -273,7 +273,7 @@ LinuxDriverInitTSCkHz(void) + *---------------------------------------------------------------------- + */ + +-int ++static int + LinuxDriverInit(void) + { + int retval; +@@ -361,7 +361,7 @@ LinuxDriverInit(void) + *---------------------------------------------------------------------- + */ + +-void ++static void + LinuxDriverExit(void) + { + /* +diff --git a/vmmon-only/linux/hostif.c b/vmmon-only/linux/hostif.c +index cac16735..f33c442a 100644 +--- a/vmmon-only/linux/hostif.c ++++ b/vmmon-only/linux/hostif.c +@@ -2818,7 +2818,7 @@ HostIF_CallOnEachCPU(void (*func)(void*), // IN: function to call + *----------------------------------------------------------------------------- + */ + +-Bool ++static Bool + HostIFCheckTrackedMPN(VMDriver *vm, // IN: The VM instance + MPN mpn) // IN: The MPN + { +@@ -2946,7 +2946,7 @@ HostIF_ReadPhysical(VMDriver *vm, // IN: The VM instance + *---------------------------------------------------------------------- + */ + +-int ++static int + HostIFWritePhysicalWork(MA ma, // MA to be written to + VA64 addr, // src data to write + Bool kernelBuffer, // is the buffer in kernel space? +@@ -3085,7 +3085,7 @@ HostIF_GetCurrentPCPU(void) + *---------------------------------------------------------------------- + */ + +-int ++static int + HostIFStartTimer(Bool rateChanged, //IN: Did rate change? + unsigned int rate) //IN: current clock rate + { diff --git a/vmnet.patch b/vmnet.patch index 5f1159bc7121..04f8080b22d3 100644 --- a/vmnet.patch +++ b/vmnet.patch @@ -1,6 +1,6 @@ --- a/vmnet/Makefile +++ b/vmnet/Makefile -@@ -43,7 +43,11 @@ INCLUDE += -I$(SRCROOT)/shared +@@ -43,7 +43,11 @@ endif @@ -12,7 +12,7 @@ # Header directory for the running kernel ifdef LINUXINCLUDE -@@ -98,6 +98,13 @@ auto-build: $(DRIVER_KO) +@@ -98,6 +102,13 @@ auto-build: $(DRIVER_KO) $(DRIVER): $(DRIVER_KO) if [ $< -nt $@ ] || [ ! -e $@ ] ; then cp -f $< $@; fi @@ -26,7 +26,7 @@ # # Define a setup target that gets built before the actual driver. # This target may not be used at all, but if it is then it will be defined -@@ -107,7 +114,7 @@ prebuild:: ; +@@ -107,7 +118,7 @@ prebuild:: ; postbuild:: ; $(DRIVER_KO): prebuild @@ -35,9 +35,124 @@ MODULEBUILDDIR=$(MODULEBUILDDIR) modules $(MAKE) -C $$PWD SRCROOT=$$PWD/$(SRCROOT) \ MODULEBUILDDIR=$(MODULEBUILDDIR) postbuild +--- a/vmnet/bridge.c ++++ b/vmnet/bridge.c +@@ -26,6 +26,9 @@ + #include <linux/slab.h> + #include <linux/poll.h> + ++#if LINUX_VERSION_CODE >= KERNEL_VERSION(6, 4, 10) ++#include <net/gso.h> ++#endif + #include <linux/netdevice.h> + #include <linux/etherdevice.h> + #include <linux/mm.h> +@@ -684,14 +684,11 @@ + } + spin_unlock_irqrestore(&bridge->historyLock, flags); + +- /* +- * We used to cli() before calling netif_rx() here. It was probably +- * unneeded (as we never did it in netif.c, and the code worked). In +- * any case, now that we are using netif_rx_ni(), we should certainly +- * not do it, or netif_rx_ni() will deadlock on the cli() lock --hpreg +- */ +- +- netif_rx_ni(clone); ++#if LINUX_VERSION_CODE < KERNEL_VERSION(5, 18, 0) ++ netif_rx_ni(clone); ++#else ++ netif_rx(clone); ++#endif + # if LOGLEVEL >= 4 + do_gettimeofday(&vnetTime); + # endif +--- a/vmnet/driver.c ++++ b/vmnet/driver.c +@@ -279,7 +279,7 @@ + /* + *---------------------------------------------------------------------- + * +- * init_module -- ++ * LinuxDriverInit -- + * + * linux module entry point. Called by /sbin/insmod command. + * Initializes module and Registers this driver for a +@@ -296,7 +296,7 @@ + */ + + int +-init_module(void) ++LinuxDriverInit(void) + { + int retval; + +@@ -358,7 +358,7 @@ + /* + *---------------------------------------------------------------------- + * +- * cleanup_module -- ++ * LinuxDriverExit -- + * + * Called by /sbin/rmmod. Unregisters this driver for a + * vnet major #, and deinitializes the modules. The 64-bit +@@ -375,7 +375,7 @@ + */ + + void +-cleanup_module(void) ++LinuxDriverExit(void) + { + unregister_chrdev(VNET_MAJOR_NUMBER, "vmnet"); + VNetProtoUnregister(); +@@ -1701,3 +1701,5 @@ + * by default (i.e., neither mkinitrd nor modprobe will accept it). + */ + MODULE_INFO(supported, "external"); ++module_init(LinuxDriverInit); ++module_exit(LinuxDriverExit); +--- a/vmnet/netif.c ++++ b/vmnet/netif.c +@@ -219,7 +219,11 @@ + + memset(&netIf->stats, 0, sizeof netIf->stats); + ++#if LINUX_VERSION_CODE < KERNEL_VERSION(5, 15, 0) + memcpy(dev->dev_addr, netIf->port.paddr, sizeof netIf->port.paddr); ++#else ++ eth_hw_addr_set(dev, netIf->port.paddr); ++#endif + + if (register_netdev(dev) != 0) { + LOG(0, (KERN_NOTICE "%s: could not register network device\n", +@@ -311,7 +315,11 @@ + /* send to the host interface */ + skb->dev = netIf->dev; + skb->protocol = eth_type_trans(skb, netIf->dev); ++#if LINUX_VERSION_CODE < KERNEL_VERSION(5, 18, 0) + netif_rx_ni(skb); ++#else ++ netif_rx(skb); ++#endif + netIf->stats.rx_packets++; + + return; +@@ -498,7 +506,11 @@ + return -EINVAL; + } + memcpy(netIf->port.paddr, addr->sa_data, dev->addr_len); +- memcpy(dev->dev_addr, addr->sa_data, dev->addr_len); ++#if LINUX_VERSION_CODE < KERNEL_VERSION(5, 15, 0) ++ memcpy(dev->dev_addr, netIf->port.paddr, dev->addr_len); ++#else ++ eth_hw_addr_set(dev, netIf->port.paddr); ++#endif + return 0; + } + --- a/vmnet/procfs.c +++ a/vmnet/procfs.c -@@ -137,6 +137,7 @@ +@@ -137,6 +137,7 @@ VNetProcShow(struct seq_file *p, // IN: } @@ -45,7 +160,7 @@ /* *---------------------------------------------------------------------- * -@@ -168,6 +169,7 @@ +@@ -168,6 +169,7 @@ static struct file_operations fops = { .release = single_release, }; #endif @@ -53,7 +168,7 @@ /* -@@ -203,7 +205,12 @@ +@@ -203,7 +205,12 @@ VNetProcMakeEntryInt(VNetProcEntry *pa } else { ent->data = data; ent->fn = fn; @@ -66,9 +181,31 @@ } if (ent->pde != NULL) { *ret = ent; +--- a/vmnet/smac.c ++++ b/vmnet/smac.c +@@ -4118,7 +4118,7 @@ + + void SMACINT + SMAC_SetMac(SMACState *state, // IN: state to update +- uint8 *mac) // IN: pointer to host adapter's MAC ++ const uint8 *mac) // IN: pointer to host adapter's MAC + { + VNETKdPrintCall(("SMAC_SetMac")); + ASSERT(state); +--- a/vmnet/smac.h ++++ b/vmnet/smac.h +@@ -72,7 +72,7 @@ + void SMACINT + SMAC_InitState(struct SMACState **ptr); // IN: state to alloc/init + void SMACINT +-SMAC_SetMac(struct SMACState *state, uint8 *mac); // IN: state, and host MAC ++SMAC_SetMac(struct SMACState *state, const uint8 *mac); // IN: state, and host MAC + void SMACINT + SMAC_CleanupState(struct SMACState **ptr); // IN: state to cleanup/dealloc + --- a/vmnet/userif.c +++ b/vmnet/userif.c -@@ -78,11 +78,11 @@ +@@ -78,11 +78,11 @@ static int VNetUserIfSetUplinkState(VNe extern unsigned int vnet_max_qlen; #if COMPAT_LINUX_VERSION_CHECK_LT(3, 2, 0) @@ -85,7 +222,7 @@ #endif /* -@@ -137,16 +137,21 @@ +@@ -137,16 +137,21 @@ UserifLockPage(VA addr) // IN */ static INLINE int @@ -111,7 +248,7 @@ *p = UserifLockPage(uAddr); if (*p == NULL) { -@@ -158,7 +163,7 @@ +@@ -158,7 +163,7 @@ VNetUserIfMapPtr(VA uAddr, // IN: } static INLINE int @@ -120,7 +257,7 @@ struct page **p, // OUT: locked page uint32 **ptr) // OUT: kernel mapped pointer { -@@ -201,7 +206,7 @@ +@@ -201,7 +206,7 @@ VNetUserIfSetupNotify(VNetUserIF *userIf return -EBUSY; } @@ -129,7 +266,7 @@ &pollPtr)) < 0) { return retval; } -@@ -213,7 +218,7 @@ +@@ -213,7 +218,7 @@ VNetUserIfSetupNotify(VNetUserIF *userIf goto error_free; } @@ -138,7 +275,67 @@ &recvClusterPage, &recvClusterCount)) < 0) { goto error_free; -@@ -559,20 +564,20 @@ +@@ -511,6 +516,50 @@ + /* + *---------------------------------------------------------------------- + * ++ * VNetCsumAndCopyToUser -- ++ * ++ * Checksum data and copy them to userspace. ++ * ++ * Results: ++ * folded checksum (non-zero value) on success, ++ * err set to 0 on success, negative errno on failure. ++ * ++ * Side effects: ++ * Data copied to the buffer. ++ * ++ *---------------------------------------------------------------------- ++ */ ++ ++static unsigned int ++VNetCsumAndCopyToUser(const void *src, // IN: Source ++ void *dst, // IN: Destination ++ int len, // IN: Bytes to copy ++ int *err) // OUT: Error code ++{ ++ unsigned int csum; ++ ++#if COMPAT_LINUX_VERSION_CHECK_LT(5, 10, 0) ++ csum = csum_and_copy_to_user(src, dst, len, 0, err); ++#elif LINUX_VERSION_CODE < KERNEL_VERSION(5, 19, 0) ++ csum = csum_and_copy_to_user(src, dst, len); ++ *err = (csum == 0) ? -EFAULT : 0; ++#else ++ if (!user_access_begin(dst, len)) { ++ *err = -EFAULT; ++ csum = 0; ++ } else { ++ *err = 0; ++ csum = csum_partial_copy_nocheck(src, dst, len); ++ user_access_end(); ++ } ++#endif ++ return csum; ++} ++ ++ ++/* ++ *---------------------------------------------------------------------- ++ * + * VNetCsumCopyDatagram -- + * + * Copy part of datagram to userspace doing checksum at same time. +@@ -550,7 +555,7 @@ VNetCsumCopyDatagram(const struct sk_buf + return -EINVAL; + } + +- csum = csum_and_copy_to_user(skb->data + offset, curr, len, 0, &err); ++ csum = VNetCsumAndCopyToUser(skb->data + offset, curr, len, &err); + if (err) { + return err; + } +@@ -559,20 +569,20 @@ VNetCsumCopyDatagram(const struct sk_buf for (frag = skb_shinfo(skb)->frags; frag != skb_shinfo(skb)->frags + skb_shinfo(skb)->nr_frags; frag++) { @@ -152,8 +349,8 @@ - curr, frag->size, 0, &err); - compat_kunmap(frag->page); + vaddr = kmap(skb_frag_page(frag)); -+ tmpCsum = csum_and_copy_to_user(vaddr + skb_frag_off(frag), -+ curr, skb_frag_size(frag), 0, &err); ++ tmpCsum = VNetCsumAndCopyToUser(vaddr + skb_frag_off(frag), ++ curr, skb_frag_size(frag), &err); + kunmap(skb_frag_page(frag)); if (err) { @@ -165,3 +362,221 @@ } } +Fixing VMWare Player on Linux when using DHCP addresses: https://www.nikhef.nl/~janjust/vmnet/ +@@ -973,6 +989,9 @@ + userIf = (VNetUserIF *)port->jack.private; + hubJack = port->jack.peer; + ++ /* never send link down events */ ++ if (!linkUp) return 0; ++ + if (port->jack.state == FALSE || hubJack == NULL) { + return -EINVAL; + } +--- a/vmnet/vnetEvent.c ++++ b/vmnet/vnetEvent.c +@@ -60,10 +60,12 @@ + + struct VNetEvent_EventNode { + VNetEvent_EventNode *nextEvent; +- VNet_EventHeader event; ++ union { ++ VNet_EventHeader header; ++ VNet_LinkStateEvent lse; ++ } event; + }; + +-#define EVENT_NODE_HEADER_SIZE offsetof(struct VNetEvent_EventNode, event) + + struct VNetEvent_Mechanism { + VNetKernel_SpinLock lock; /* mechanism lock */ +@@ -369,6 +371,10 @@ + return VNetKernel_EINVAL; + } + ++ if (e->size > sizeof(p->event)) { ++ return VNetKernel_EINVAL; ++ } ++ + /* lock */ + VNetKernel_SpinLockAcquire(&m->lock); + m->handlerTask = VNetKernel_ThreadCurrent(); +@@ -378,22 +384,15 @@ + while (TRUE) { + p = *q; + if (p == NULL || +- (p->event.eventId == e->eventId && p->event.type == e->type)) { ++ (p->event.header.eventId == e->eventId && p->event.header.type == e->type)) { + break; + } + q = &p->nextEvent; + } + +- /* remove previously sent event */ +- if (p != NULL && p->event.size != e->size) { +- *q = p->nextEvent; +- VNetKernel_MemoryFree(p); +- p = NULL; +- } +- + /* insert new event into event list*/ + if (p == NULL) { +- p = VNetKernel_MemoryAllocate(EVENT_NODE_HEADER_SIZE + e->size); ++ p = VNetKernel_MemoryAllocate(sizeof(*p)); + if (p == NULL) { + m->handlerTask = NULL; + VNetKernel_SpinLockRelease(&m->lock); +@@ -485,8 +484,8 @@ + while (s != NULL) { + e = s->firstEvent; + while (e != NULL) { +- if ((e->event.classSet & classMask) != 0) { +- h(data, &e->event); ++ if ((e->event.header.classSet & classMask) != 0) { ++ h(data, &e->event.header); + } + e = e->nextEvent; + } +--- a/vmnet/vnetUserListener.c +--- b/vmnet/vnetUserListener.c +@@ -42,10 +42,12 @@ + + struct VNetUserListener_EventNode { + VNetUserListener_EventNode *nextEvent; +- VNet_EventHeader event; ++ union { ++ VNet_EventHeader header; ++ VNet_LinkStateEvent lse; ++ } event; + }; + +-#define EVENT_NODE_HEADER_SIZE offsetof(struct VNetUserListener_EventNode, event) + + typedef struct VNetUserListener { + VNetPort port; /* base port/jack */ +@@ -220,7 +222,7 @@ + VNetUserListener_EventNode *t; + + /* allocate and initialize event node */ +- t = kmalloc(EVENT_NODE_HEADER_SIZE + e->size, GFP_ATOMIC); ++ t = kmalloc(sizeof *t, GFP_ATOMIC); + if (t == NULL) { + LOG(0, (KERN_DEBUG "VNetUserListenerEventHandler, out of memory\n")); + return; +@@ -299,7 +301,7 @@ + spin_unlock(&userListener->lock); + + /* return data and free event */ +- n = t->event.size; ++ n = t->event.header.size; + if (count < n) { + n = count; + } +From add7a6d8b99565fdfa79098315b0a69fd244eda3 Mon Sep 17 00:00:00 2001 +From: Michal Kubecek <mkubecek@suse.cz> +Date: Fri, 12 Jan 2024 08:30:33 +0100 +Subject: [PATCH] modules: fix build with -Wmissing-prototypes + +Mainline commit 0fcb70851fbf ("Makefile.extrawarn: turn on +missing-prototypes globally") in 6.8-rc1 enables -Wmissing-prototypes +globally, revealing a lot of unclean code and also some actual problems. +This is also the case in vmmon and vmnet modules. + +Most of them are addressed by making functions used only within one file +static. A special case are Vmx86_MapPage() and Vmx86_UnmapPage() which were +defined since Workstation 14.0.0 but they are not actually used anywhere +until 15.0.0 so that dropping them seems to be the best option. + +The missing prototype of random_get_entropy_fallback() is handled by +including <linux/timex.h> rather than <asm/timex.h>. + +Finally, there are four functions in vmnet module which are actually used +in multiple files but instead of proper declarations, their prototype is +duplicated in vmnet-only/driver.c, risking that the two copies won't match +(which actually happened in one case). The cleanest solution would be +creating separate header files for them (bridge.h, netif.h, userif.h and +vnetUserListener.h) and including them in the respective source file and +driver.c. As the developers already handle similar cases by simply putting +the declarations into vnetInt.h, let us do the same to keep things simple. +--- + vmmon-only/bootstrap/monLoaderVmmon.c | 1 + + vmmon-only/common/vmx86.c | 50 +-------------------------- + vmmon-only/linux/driver.c | 4 +-- + vmmon-only/linux/hostif.c | 6 ++-- + vmnet-only/bridge.c | 2 +- + vmnet-only/driver.c | 16 ++------- + vmnet-only/vnetInt.h | 7 ++++ + 7 files changed, 17 insertions(+), 69 deletions(-) + +diff --git a/vmnet-only/bridge.c b/vmnet-only/bridge.c +index b144adab..b46df795 100644 +--- a/vmnet-only/bridge.c ++++ b/vmnet-only/bridge.c +@@ -1405,7 +1405,7 @@ VNetBridgeComputeHeaderPos(struct sk_buff *skb) // IN: buffer to examine + *---------------------------------------------------------------------- + */ + +-void ++static void + VNetBridgeSendLargePacket(struct sk_buff *skb, // IN: packet to split + VNetBridge *bridge) // IN: bridge + { +diff --git a/vmnet-only/driver.c b/vmnet-only/driver.c +index 602bbfa1..a6f6a7d9 100644 +--- a/vmnet-only/driver.c ++++ b/vmnet-only/driver.c +@@ -50,18 +50,6 @@ + + #include "vmnetInt.h" + +-/* +- * Initialization and creation routines from other files. +- * Putting them here reduces the need for so many header files. +- */ +- +-extern int VNetUserIf_Create(VNetPort **ret); +-extern int VNetNetIf_Create(char *devName, VNetPort **ret, int hubNum); +-extern int VNetBridge_Create(char *devName, uint32 flags, VNetJack *hubJack, +- VNetPort **ret); +-extern int VNetUserListener_Create(uint32 classMask, VNetJack *hubJack, VNetPort **ret); +- +- + /* + * Structure for cycle detection of host interfaces. This + * struct is only used by VNetCycleDetectIf(). +@@ -295,7 +283,7 @@ VNetRemovePortFromList(const VNetPort *port) // IN: port to remove from list + *---------------------------------------------------------------------- + */ + +-int ++static int + LinuxDriverInit(void) + { + int retval; +@@ -374,7 +362,7 @@ vmnet_init_module(void) + *---------------------------------------------------------------------- + */ + +-void ++static void + LinuxDriverExit(void) + { + unregister_chrdev(VNET_MAJOR_NUMBER, "vmnet"); +diff --git a/vmnet-only/vnetInt.h b/vmnet-only/vnetInt.h +index 5f41269d..cb25e3b8 100644 +--- a/vmnet-only/vnetInt.h ++++ b/vmnet-only/vnetInt.h +@@ -225,6 +225,13 @@ extern int VNetProc_Init(void); + + extern void VNetProc_Cleanup(void); + ++int VNetNetIf_Create(char *devName, VNetPort **ret, int hubNum); ++int VNetUserIf_Create(VNetPort **ret); ++int VNetBridge_Create(const char *devName, uint32 flags, VNetJack *hubJack, ++ VNetPort **ret); ++int VNetUserListener_Create(uint32 classMask, VNetJack *hubJack, ++ VNetPort **port); ++ + + /* + *---------------------------------------------------------------------- diff --git a/vmware-networks.path b/vmware-networks.path new file mode 100644 index 000000000000..fb53ff4ba642 --- /dev/null +++ b/vmware-networks.path @@ -0,0 +1,8 @@ +[Unit] +Description=Monitor to Load-On-Demand the VMware Networks service + +[Path] +PathExistsGlob=/var/run/vmware/*/* + +[Install] +WantedBy=paths.target diff --git a/vmware-usbarbitrator.path b/vmware-usbarbitrator.path new file mode 100644 index 000000000000..e56473635d8b --- /dev/null +++ b/vmware-usbarbitrator.path @@ -0,0 +1,8 @@ +[Unit] +Description=Monitor to Load-On-Demand the VMware USB Arbitrator + +[Path] +PathExistsGlob=/var/run/vmware/*/* + +[Install] +WantedBy=paths.target diff --git a/vmware-workstation.install b/vmware-workstation.install index 36f5a3505e48..22d527c8f00c 100644 --- a/vmware-workstation.install +++ b/vmware-workstation.install @@ -2,18 +2,29 @@ post_install() { cat << EOF ==> Before using VMware, you need to reboot or load vmw_vmci and vmmon kernel modules (in a terminal on root: modprobe -a vmw_vmci vmmon) -==> You may also need to enable some of these services: -- vmware-networks.service: to have network access inside VMs -- vmware-usbarbitrator.service: to connect USB devices inside VMs -- vmware-hostd.service: to share VMs on the network +==> You may also need to enable some of the following services: +- vmware-networks: to have network access inside VMs +- vmware-usbarbitrator: to connect USB devices inside VMs +- vmware-hostd: to share VMs on the network +These services can be activated during boot by enabling .service units or only when a VM is started by enabling .path units (except for vmware-hostd). EOF } +post_upgrade() { + if (( $(vercmp "$2" "14.1.7-11") < 0 )); then + cat << EOF + +Now vmware-networks and vmware-usbarbitrator services can be activated only when a VM is started by enabling .path units instead of .service units. + +EOF + fi +} + post_remove() { cat << EOF -==> To remove VMware settings, delete /etc/vmware and /etc/vmware-installer directories. +==> To completely clean VMware installation, you may have to manually delete /etc/vmware, /etc/vmware-installer and /usr/lib/vmware-installer directories if they still exist. EOF } |