diff options
-rw-r--r-- | .SRCINFO | 13 | ||||
-rw-r--r-- | PKGBUILD | 53 | ||||
-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 | 424 | ||||
-rw-r--r-- | vmnet.patch | 438 | ||||
-rw-r--r-- | vmware-networks.path | 8 | ||||
-rw-r--r-- | vmware-usbarbitrator.path | 8 | ||||
-rw-r--r-- | vmware-workstation.install | 21 |
9 files changed, 1221 insertions, 131 deletions
@@ -1,7 +1,7 @@ pkgbase = vmware-workstation15 pkgdesc = The industry standard for running multiple operating systems as virtual machines on a single Linux PC. pkgver = 15.5.7 - pkgrel = 4 + pkgrel = 18 url = https://www.vmware.com/products/workstation-for-linux.html install = vmware-workstation.install arch = x86_64 @@ -14,8 +14,10 @@ pkgbase = vmware-workstation15 depends = libaio depends = pcsclite depends = hicolor-icon-theme + depends = libxcrypt-compat depends = gtk3 depends = gcr + depends = libpng12 depends = vmware-keymaps optdepends = linux-headers: build modules against Arch kernel provides = vmware-workstation=15.5.7 @@ -27,6 +29,7 @@ pkgbase = vmware-workstation15 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 +59,8 @@ pkgbase = vmware-workstation15 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,9 +83,11 @@ pkgbase = vmware-workstation15 sha256sums = 9b4fbe0ba83f761a2eb9ecd05d48428f8b0a5b3abd8404ccbd928408e682f02b sha256sums = c0a5aea785db06921fb350d36d5e0fd9a14f5eee0c835686ec6fea1af8c92245 sha256sums = d7a9fbf39a0345ae2f14f7f389f30b1110f605d187e0c241e99bbb18993c250d + sha256sums = 16a73931894a65d43da489ff25d07647c0ecddf60d443b103bceca63504910fe + sha256sums = fe1b1be8297f4170406f97dd1f8b385d911faf45afe19cbc0c26b8092b3ddf8d sha256sums = 10562d11d50edab9abc2b29c8948714edcb9b084f99b3766d07ddd21259e372e sha256sums = 273d4357599a3e54259c78cc49054fef8ecfd2c2eda35cbcde3a53a62777a5ac - sha256sums = c6192797745e19e6361e005adb98383f8877f0118e1db5c018c67cc88c7cb6e1 - sha256sums = 361a3abf195098a90cbf2a4ce16dbcfcfc224c78284269b6d980972bc3647796 + sha256sums = ff327a4de16d705b4337adf66eb48435c045e9aa51862112dab5c42fab542459 + sha256sums = 6e455d89f6209aa3f5dfa3dbaed8bef8314c331aa48e4d69012ec8aaab140407 pkgname = vmware-workstation15 @@ -16,7 +16,7 @@ pkgname=vmware-workstation15 pkgver=15.5.7 _buildver=17171714 _pkgver=${pkgver}_${_buildver} -pkgrel=4 +pkgrel=18 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' @@ -41,9 +41,11 @@ depends=( libaio pcsclite hicolor-icon-theme + libxcrypt-compat # needed for ovftool # needed to use Arch GTK3 library (for theme integration) gtk3 gcr + libpng12 ) optdepends=( 'linux-headers: build modules against Arch kernel' @@ -86,6 +88,8 @@ source=( 'vmware-networks-configuration.service' 'vmware-networks.service' 'vmware-usbarbitrator.service' + 'vmware-networks.path' + 'vmware-usbarbitrator.path' 'dkms.conf.in' 'Makefile' @@ -114,13 +118,15 @@ sha256sums=( '9b4fbe0ba83f761a2eb9ecd05d48428f8b0a5b3abd8404ccbd928408e682f02b' 'c0a5aea785db06921fb350d36d5e0fd9a14f5eee0c835686ec6fea1af8c92245' 'd7a9fbf39a0345ae2f14f7f389f30b1110f605d187e0c241e99bbb18993c250d' + '16a73931894a65d43da489ff25d07647c0ecddf60d443b103bceca63504910fe' + 'fe1b1be8297f4170406f97dd1f8b385d911faf45afe19cbc0c26b8092b3ddf8d' '10562d11d50edab9abc2b29c8948714edcb9b084f99b3766d07ddd21259e372e' '273d4357599a3e54259c78cc49054fef8ecfd2c2eda35cbcde3a53a62777a5ac' - 'c6192797745e19e6361e005adb98383f8877f0118e1db5c018c67cc88c7cb6e1' - '361a3abf195098a90cbf2a4ce16dbcfcfc224c78284269b6d980972bc3647796' + 'ff327a4de16d705b4337adf66eb48435c045e9aa51862112dab5c42fab542459' + '6e455d89f6209aa3f5dfa3dbaed8bef8314c331aa48e4d69012ec8aaab140407' ) -options=(!strip emptydirs) +options=(!strip emptydirs !debug) if [ -z "$_remove_vmware_keymaps_dependency" ]; then depends+=( @@ -134,27 +140,26 @@ _isovirtualprinterimages=(Linux Windows) if [ -n "$_enable_macOS_guests" ]; then -_vmware_fusion_ver=11.5.7_17130923 +_vmware_fusion_ver=11.5.7 +_vmware_fusion_buildver=17130923 +_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 dmg2img p7zip - uefitool-git + uefitool ) source+=( - "https://download3.vmware.com/software/fusion/file/VMware-Fusion-${_vmware_fusion_ver/_/-}.dmg" - "unlocker-${_unlocker_ver}.py::https://raw.githubusercontent.com/paolo-projects/unlocker/${_unlocker_ver}/unlocker.py" - "efi-unlocker-patch-${_efi_unlocker_ver}.txt" + "https://download3.vmware.com/software/fusion/file/VMware-Fusion-${_vmware_fusion_ver_full/_/-}.dmg" + "unlocker.py" + "efi-patches.txt" ) sha256sums+=( 'c7d58ca44510de6c1ddffe86129ed19982114e742d71e7d81e4a5882036e06e3' - '1c27547dcf6fb2f436c96ee62ae8c7f5cfd14b40d8bbd35dc385e247c4fb7e0f' + '8a61e03d0edbbf60c1c84a43aa87a6e950f82d2c71b968888f019345c2f684f3' '392c1effcdec516000e9f8ffc97f2586524d8953d3e7d6f2c5f93f2acd809d91' ) @@ -171,18 +176,18 @@ _create_database_file() { sqlite3 "$database_filename" "INSERT INTO settings(key,value,component_name) VALUES('db.schemaVersion','2','vmware-installer');" sqlite3 "$database_filename" "CREATE TABLE components(id INTEGER PRIMARY KEY, name VARCHAR NOT NULL, version VARCHAR NOT NULL, buildNumber INTEGER NOT NULL, component_core_id INTEGER NOT NULL, longName VARCHAR NOT NULL, description VARCHAR, type INTEGER NOT NULL);" - sqlite3 "$database_filename" "INSERT INTO components(name,version,buildNumber,component_core_id,longName,description,type) VALUES(\"vmware-player\",\"$pkgver\",\"${_pkgver#*_}\",1,\"VMware Player\",\"VMware Player for Linux\",0);" + sqlite3 "$database_filename" "INSERT INTO components(name,version,buildNumber,component_core_id,longName,description,type) VALUES('vmware-player','$pkgver',${_pkgver#*_},1,'VMware Player','VMware Player for Linux',0);" 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 } @@ -196,10 +201,10 @@ prepare() { --extract "$extracted_dir" if [ -n "$_enable_macOS_guests" ]; then - dmg2img VMware-Fusion-${_vmware_fusion_ver/_/-}.dmg VMware-Fusion-${_vmware_fusion_ver/_/-}.iso > /dev/null - 7z e -y VMware-Fusion-${_vmware_fusion_ver/_/-}.iso VMware\ Fusion/VMware\ Fusion.app/Contents/Library/isoimages/\* -o"fusion-isoimages" > /dev/null 2>&1 || true + dmg2img -s VMware-Fusion-${_vmware_fusion_ver_full/_/-}.dmg VMware-Fusion-${_vmware_fusion_ver_full/_/-}.iso + 7z e -y VMware-Fusion-${_vmware_fusion_ver_full/_/-}.iso VMware\ Fusion/VMware\ Fusion.app/Contents/Library/isoimages/\* -o"fusion-isoimages" > /dev/null 2>&1 || true - 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 } @@ -331,7 +336,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" \ @@ -448,7 +455,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 @@ -456,10 +463,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 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 19ba25431813..1ec443375812 100644 --- a/vmmon.patch +++ b/vmmon.patch @@ -20,6 +20,78 @@ include $(SRCROOT)/Makefile.kernel +--- 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/include/vm_basic_defs.h ++++ b/vmmon/include/vm_basic_defs.h +@@ -50,7 +50,10 @@ + * References: + * C90 7.17, C99 7.19, C11 7.19 + */ +-#if !defined(VMKERNEL) ++/* Use linux/stddef.h when building Linux kernel modules. */ ++#ifdef KBUILD_MODNAME ++# include <linux/stddef.h> ++#elif !defined(VMKERNEL) + # include <stddef.h> + #else + /* +--- a/vmmon/linux/driver.c ++++ b/vmmon/linux/driver.c +@@ -246,7 +246,7 @@ + /* + *---------------------------------------------------------------------- + * +- * init_module -- ++ * LinuxDriverInit -- + * + * linux module entry point. Called by /sbin/insmod command + * +@@ -259,7 +259,7 @@ + */ + + int +-init_module(void) ++LinuxDriverInit(void) + { + int retval; + +@@ -340,7 +340,7 @@ + /* + *---------------------------------------------------------------------- + * +- * cleanup_module -- ++ * LinuxDriverExit -- + * + * Called by /sbin/rmmod + * +@@ -349,7 +349,7 @@ + */ + + void +-cleanup_module(void) ++LinuxDriverExit(void) + { + /* + * XXX smp race? +@@ -1448,3 +1448,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 +++ b/vmmon/linux/hostif.c @@ -47,6 +47,8 @@ @@ -39,6 +111,29 @@ #include "vmware.h" #include "x86apic.h" +@@ -80,6 +83,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 +@@ -463,7 +473,7 @@ + ASSERT(vcpuid < vm->numVCPUs); + 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); + } + } @@ -614,6 +617,15 @@ MutexUnlock(&fastClockMutex, callerID); } @@ -97,7 +192,7 @@ lockedPages += global_node_page_state(NR_SLAB_UNRECLAIMABLE); #else lockedPages += global_page_state(NR_SLAB_UNRECLAIMABLE); -@@ -2389,16 +2426,22 @@ +@@ -2389,16 +2426,26 @@ static Bool isVAReadable(VA r) // IN: { @@ -105,7 +200,11 @@ uint32 dummy; int ret; -+#ifdef HAVE_GET_KERNEL_NOFAULT ++#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 + { @@ -130,7 +229,7 @@ int res; int waitFD = args[0]; int timeoutms = args[2]; -@@ -2566,9 +2610,6 @@ +@@ -2566,22 +2610,19 @@ return MX_WAITERROR; } @@ -140,6 +239,21 @@ { struct poll_wqueues table; 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); + } + @@ -2590,9 +2631,11 @@ * 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). @@ -163,6 +277,15 @@ fput(file); /* +@@ -2658,7 +2705,7 @@ + */ + struct task_struct *t = + (struct task_struct *)xchg(&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_WITH_MAX(); @@ -2688,8 +2730,8 @@ int HostIF_SemaphoreSignal(uint64 *args) // IN: @@ -173,7 +296,7 @@ int res; int signalFD = args[1]; uint64 value = 1; // make an eventfd happy should it be there -@@ -2699,22 +2741,32 @@ +@@ -2699,22 +2741,36 @@ return MX_WAITERROR; } @@ -185,7 +308,11 @@ + */ + 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; + } @@ -233,99 +360,226 @@ /* * Do not exit thread until we are told to do so. */ -From 9fda02bce13527ce94a95df1a98fb6188dea22b8 Mon Sep 17 00:00:00 2001 +From 4c2a103fd2d71f2084f1fe7ceacb816b9832ffa2 Mon Sep 17 00:00:00 2001 From: Michal Kubecek <mkubecek@suse.cz> -Date: Wed, 30 Jun 2021 11:05:16 +0200 -Subject: [PATCH] vmmon: fix task_struct::state access patterns +Date: Sun, 22 Oct 2023 23:24:05 +0200 +Subject: [PATCH] vmmon: use get_user_pages to get page PFN -Mainline commit 2f064a59a11f ("sched: Change task_struct::state") in -5.14-rc1 finishes a series fixing racy access patterns to task state and -renames task_struct::state to __state so that code old code acessing it -directly fails to build. +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. -Two of these in HostIF_SemaphoreWait() can be rewritten into calls to -set_current_state() unconditionally (second one may do with -__set_current_state() but I don't feel confident enough about that). -There are also two places where vmmon code reads task_struct::state; -provide a compat accessor using READ_ONCE() and use it instead of -a direct read. To avoid kernel version check, check presence of -get_current_state() macro introduced in the same commit as state member -rename. +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/compat_sched.h | 15 +++++++++++++++ - vmmon-only/linux/hostif.c | 10 ++++++---- - 2 files changed, 21 insertions(+), 4 deletions(-) + vmmon-only/include/pgtbl.h | 25 +++++++++++++++++++++++++ + 1 file changed, 25 insertions(+) -diff --git a/vmmon-only/include/compat_sched.h b/vmmon-only/include/compat_sched.h -index 3f3304b..72078e0 100644 ---- a/vmmon-only/include/compat_sched.h -+++ b/vmmon-only/include/compat_sched.h -@@ -289,5 +289,20 @@ typedef struct pid * compat_pid; - #define compat_kill_pid(pid, sig, flag) kill_pid(pid, sig, flag) - #endif +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" -+/* -+ * Since v5.14-rc1, task_struct::state hase been renamed to __state and is -+ * is longer supposed to be accessed without READ_ONCE/WRITE_ONCE. -+ */ -+#ifdef get_current_state -+static inline int compat_get_task_state(const struct task_struct *t) -+{ -+ return READ_ONCE(t->__state); -+} -+#else -+static inline int compat_get_task_state(const struct task_struct *t) + + /* +@@ -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 +{ -+ return READ_ONCE(t->state); ++ 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 ++ ++#endif /* COMPAT_LINUX_VERSION_CHECK_LT(6, 5, 0) */ ++ + #endif /* __PGTBL_H__ */ +From 2c6d66f3f1947384038b765c897b102ecdb18298 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. 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/common/task.c | 2 +- + vmmon-only/common/vmx86.c | 6 +++--- + 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, 19 insertions(+), 24 deletions(-) + +diff --git a/vmmon-only/common/task.c b/vmmon-only/common/task.c +index 5d34cf4d..f3752069 100644 +--- a/vmmon-only/common/task.c ++++ b/vmmon-only/common/task.c +@@ -542,7 +542,7 @@ Task_Terminate(void) + *----------------------------------------------------------------------------- + */ + +-Selector ++static Selector + TaskGetFlatWriteableDataSegment(void) + { + DTR hostGDTR; +diff --git a/vmmon-only/common/vmx86.c b/vmmon-only/common/vmx86.c +index 86e52fb4..cf64b123 100644 +--- a/vmmon-only/common/vmx86.c ++++ b/vmmon-only/common/vmx86.c +@@ -56,7 +56,7 @@ + #include "x86svm.h" + #include "x86cpuid_asm.h" + #if defined(__linux__) +-#include <asm/timex.h> ++#include <linux/timex.h> + #endif + #include "perfctr.h" + #include "x86vtinstr.h" +@@ -583,7 +583,7 @@ Vmx86FreeCrossPages(VMDriver *vm) + *----------------------------------------------------------------------------- + */ + +-void ++static void + Vmx86FreeVMDriver(VMDriver *vm) + { + Vmx86_Free(vm->ptRootMpns); +@@ -616,7 +616,7 @@ Vmx86FreeVMDriver(VMDriver *vm) + *----------------------------------------------------------------------------- + */ - #endif /* __COMPAT_SCHED_H__ */ +-VMDriver * ++static VMDriver * + Vmx86AllocVMDriver(uint32 numVCPUs) + { + VMDriver *vm = Vmx86_Calloc(1, sizeof *vm, TRUE); +diff --git a/vmmon-only/linux/driver.c b/vmmon-only/linux/driver.c +index 3d8b7228..ab8e2dc4 100644 +--- a/vmmon-only/linux/driver.c ++++ b/vmmon-only/linux/driver.c +@@ -258,7 +258,7 @@ LinuxDriverInitTSCkHz(void) + *---------------------------------------------------------------------- + */ + +-int ++static int + LinuxDriverInit(void) + { + int retval; +@@ -348,7 +348,7 @@ LinuxDriverInit(void) + *---------------------------------------------------------------------- + */ + +-void ++static void + LinuxDriverExit(void) + { + /* diff --git a/vmmon-only/linux/hostif.c b/vmmon-only/linux/hostif.c -index 137062c..6910f69 100644 +index 5d08f33a..c1e6c671 100644 --- a/vmmon-only/linux/hostif.c +++ b/vmmon-only/linux/hostif.c -@@ -79,6 +79,8 @@ - #include "pgtbl.h" - #include "versioned_atomic.h" +@@ -2997,7 +2997,7 @@ HostIF_CallOnEachCPU(void (*func)(void*), // IN: function to call + *----------------------------------------------------------------------------- + */ -+#include "compat_sched.h" -+ - #if !defined(CONFIG_HIGH_RES_TIMERS) - #error CONFIG_HIGH_RES_TIMERS required for acceptable performance - #endif -@@ -466,7 +468,7 @@ HostIF_WakeUpYielders(VMDriver *vm, // IN: - ASSERT(vcpuid < vm->numVCPUs); - t = vm->vmhost->vcpuSemaTask[vcpuid]; - VCPUSet_Remove(&req, vcpuid); -- if (t && (t->state & TASK_INTERRUPTIBLE)) { -+ if (t && (compat_get_task_state(t) & TASK_INTERRUPTIBLE)) { - wake_up_process(t); - } - } -@@ -2613,14 +2615,14 @@ HostIF_SemaphoreWait(VMDriver *vm, // IN: - unsigned int mask; +-Bool ++static Bool + HostIFCheckTrackedMPN(VMDriver *vm, // IN: The VM instance + MPN mpn) // IN: The MPN + { +@@ -3117,7 +3117,7 @@ HostIF_ReadPhysical(VMDriver *vm, // IN: The VM instance + *---------------------------------------------------------------------- + */ - 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); - } +-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? +@@ -3276,7 +3276,7 @@ HostIF_GetCurrentPCPU(void) + *---------------------------------------------------------------------- + */ -@@ -2698,7 +2700,7 @@ HostIF_SemaphoreForceWakeup(VMDriver *vm, // IN: - */ - struct task_struct *t = - (struct task_struct *)xchg(&vm->vmhost->vcpuSemaTask[vcpuid], NULL); -- if (t && (t->state & TASK_INTERRUPTIBLE)) { -+ if (t && (compat_get_task_state(t) & TASK_INTERRUPTIBLE)) { - wake_up_process(t); - } - } ROF_EACH_VCPU_IN_SET_WITH_MAX(); +-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 daa16401676f..3e28898e9749 100644 --- a/vmnet.patch +++ b/vmnet.patch @@ -20,33 +20,441 @@ include $(SRCROOT)/Makefile.kernel ---- a/vmnet/userif.c -+++ b/vmnet/userif.c -@@ -559,7 +559,12 @@ +--- 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 +@@ -253,7 +253,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", +@@ -345,7 +349,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; +@@ -532,7 +540,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/smac.c ++++ b/vmnet/smac.c +@@ -4116,7 +4116,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 +@@ -520,6 +520,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(skb->data + offset, curr, len, 0, &err); ++ 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 -+ csum = csum_and_copy_to_user(skb->data + offset, curr, len); -+ err = (csum == 0) ? -EFAULT : 0; ++ 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. +@@ -559,7 +559,7 @@ + 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; } -@@ -573,8 +578,14 @@ +@@ -573,8 +578,8 @@ const void *vaddr; vaddr = kmap(skb_frag_page(frag)); -+#if COMPAT_LINUX_VERSION_CHECK_LT(5, 10, 0) - tmpCsum = csum_and_copy_to_user(vaddr + skb_frag_off(frag), - curr, skb_frag_size(frag), 0, &err); -+#else -+ tmpCsum = csum_and_copy_to_user(vaddr + skb_frag_off(frag), -+ curr, skb_frag_size(frag)); -+ err = (tmpCsum == 0) ? -EFAULT : 0; -+#endif +- 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) { +Fixing VMWare Player on Linux when using DHCP addresses: https://www.nikhef.nl/~janjust/vmnet/ +@@ -985,6 +996,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/vm_basic_defs.h ++++ b/vmnet/vm_basic_defs.h +@@ -50,7 +50,10 @@ + * References: + * C90 7.17, C99 7.19, C11 7.19 + */ +-#if !defined(VMKERNEL) ++/* Use linux/stddef.h when building Linux kernel modules. */ ++#ifdef KBUILD_MODNAME ++# include <linux/stddef.h> ++#elif !defined(VMKERNEL) + # include <stddef.h> + #else + /* +--- 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 2c6d66f3f1947384038b765c897b102ecdb18298 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. 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/common/task.c | 2 +- + vmmon-only/common/vmx86.c | 6 +++--- + 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, 19 insertions(+), 24 deletions(-) + +diff --git a/vmnet-only/bridge.c b/vmnet-only/bridge.c +index b604a25d..4c139570 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 f314ff2e..fe5923d8 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 f6a90a13..e76dcf5c 100644 +--- a/vmnet-only/vnetInt.h ++++ b/vmnet-only/vnetInt.h +@@ -218,6 +218,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..2de40c8bc07d 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" "15.5.7-4") < 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 } |