summarylogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--.SRCINFO13
-rw-r--r--PKGBUILD53
-rw-r--r--efi-patches.txt (renamed from efi-unlocker-patch-1.0.0.txt)0
-rw-r--r--unlocker.py387
-rw-r--r--vmmon.patch424
-rw-r--r--vmnet.patch438
-rw-r--r--vmware-networks.path8
-rw-r--r--vmware-usbarbitrator.path8
-rw-r--r--vmware-workstation.install21
9 files changed, 1221 insertions, 131 deletions
diff --git a/.SRCINFO b/.SRCINFO
index 4c3235ec4192..260d47a4f846 100644
--- a/.SRCINFO
+++ b/.SRCINFO
@@ -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
diff --git a/PKGBUILD b/PKGBUILD
index 329e6c351d1e..ab952e0caebf 100644
--- a/PKGBUILD
+++ b/PKGBUILD
@@ -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
}