Compare commits

..
Author SHA1 Message Date
Michal Kubecek fac2c93374 vmmon: check presence of file_operations::poll()
Commit 11c5ad0ec441 ("eventpoll: switch to ->poll_mask") in v4.18-rc1, made
eventpoll switch from ->poll() to ->poll_mask(), resulting in a null
pointer dereference as vmmon calls the callback directly without checking
its availability.

Rather than calling the callback directly (which would result in null
pointer dereference), use vfs_poll() wrapper. As this wrapper is only
available since 4.18-rc1 cycle as well, provide a copy to use when building
against older kernels.

Note: even if the commit revealing the problem was reverted in 4.18-rc3
(and is unlikely to go back in the same form) so that vmmon no longer
crashes with 4.18 kernel, calling the callback without a check is a bad
practice so let's keep the patch in place.
2018-08-20 07:46:13 +02:00
Michal Kubecek e6804c4f5b vmmon: fix indirect call with retpoline build
Build against kernel with retpoline support issues warning

  objtool: Task_Switch()+0x425: indirect call found in RETPOLINE build

This is because an indirect call in TaskSwitchToMonitor() is encoded using
inline assembler so that it bypasses retpoline generation. For this
purpose, macro CALL_NOSPEC exists since v4.15-rc8 (and has been backported
into some distribution kernels with the rest of retpoline support). Use the
macro if available and fallback to the original code if not.
2018-08-20 07:37:40 +02:00
Michal Kubecek d620eaf4e4 vmmon: fix always_inline attribute usage
Function declared with __attribute__((always_inline)) should also be
declared as inline, otherwise gcc issues a warning "always_inline function
might not be inlinable". It's just cosmetic but getting rid of known
harmless warnings makes it easier to spot actual problems. Use the
__always_inline macro for LinuxDriverSyncReadTSCs() as this is how always
inline functions should be declared in kernel code.
2018-08-20 07:37:33 +02:00
Michal Kubecek 173a605d6f vmmon: use standard definition of MSR_K7_HWCR_SMMLOCK if available
The MSR_K7_HWCR_SMMLOCK macro is defined in mainline since commit
18c71ce9c882 ("x86/CPU/AMD: Add the Secure Encrypted Virtualization CPU
feature") in v4.16-rc1.
2018-08-20 07:37:29 +02:00
Theo Bertacchini 6747202f86 modules: remove .cache.mk on make clean
Remove .cache.mk inside vmmon-only and vmnet-only when executing
"make clean". This file can cause issues when upgrading gcc as make will
still look for includes inside older gcc includes directory.

File .cache.mk with cache of generated variables is created by build since
kernel v4.15-rc1, commit 3298b690b21c ("kbuild: Add a cache for generated
variables").
2018-08-20 07:36:26 +02:00
Michal Kubecek b73189148b vmmon: quick workaround for objtool warnings
As discussed in

  https://bugzilla.suse.com/show_bug.cgi?id=1059674

the reason for multiple objtool warnings is the fact that vmmon module
defines its own Panic() function which never returns. While it is marked as
such which is used by the compiler for optimization, there is no way to
find this from object file.

While this seems innocuous, it might result in problems with unwinder
later. The quickest way around is to replace vmmon's own Panic() with
standard kernel panic() until a cleaner solution is found.
2018-08-20 07:34:04 +02:00
Michal Kubecek 5c38f36d20 vmmon: use standard definition of CR3_PCID_MASK if available
The CR3_PCID_MASK is defined in mainline asm/processor-flags.h since
commit 6c690ee1039b ("x86/mm: Split read_cr3() into read_cr3_pa() and
__read_cr3()") in v4.13-rc1.
2018-08-20 07:33:44 +02:00
Michal Kubecek 6a61649088 vmmon: use standard definition of MSR_MISC_FEATURES_ENABLES if available
The MSR_MISC_FEATURES_ENABLES macro is defined in mainline since commit
ab6d9468631a ("x86/msr: Rename MISC_FEATURE_ENABLES to
MISC_FEATURES_ENABLES") in v4.12-rc1.

The MSR_MISC_FEATURES_ENABLES_CPUID_FAULT macro is defined in mainline
since commit e9ea1e7f53b8 ("x86/arch_prctl: Add ARCH_[GET|SET]_CPUID") in
v4.12-rc1.
2018-08-20 07:33:31 +02:00
Michal Kubecek 9cf4254e55 vmnet: use standard definition of PCI_VENDOR_ID_VMWARE_VMXNET3 if available
The PCI_DEVICE_ID_VMWARE_VMXNET3 macro is defined in mainline pci_ids.h
since commit b1226c7db1d9 ("vmxnet3: Move PCI Id to pci_ids.h") in
v4.10-rc1.
2018-08-20 07:33:11 +02:00
Michal Kubecek 5435177e9c vmnet: use standard definition of PCI_VENDOR_ID_VMWARE if available
The PCI_VENDOR_ID_VMWARE macro is defined in mainline pci_ids.h since
commit 94e57fea6202 ("PCI: Move PCI_VENDOR_ID_VMWARE to pci_ids.h")
in v3.18-rc1.
2018-08-20 07:32:34 +02:00
Michal Kubecek 56b2ba7686 import Player 14.1.3 module sources 2018-08-20 07:28:17 +02:00
Michal Kubecek 7c61516e73 Merge branch 'master' into player 2018-05-27 16:13:48 +02:00
Michal Kubecek 7ee6cd4520 import Player 14.1.2 module sources 2018-05-23 18:14:05 +02:00
Michal Kubecek 5791987f56 Merge branch 'master' into player 2018-04-02 15:37:18 +02:00
Michal Kubecek 0b2713797e Merge branch 'master' into player 2018-02-04 21:50:37 +01:00
Michal Kubecek 3e445144a1 import Player 14.1.1 module sources 2018-01-12 13:51:34 +01:00
Michal Kubecek 82f569a212 import Player 14.1.0 module sources 2017-12-25 09:47:38 +01:00
Michal Kubecek 455d4d9368 import Player 14.0.0 module sources 2017-09-30 20:31:15 +02:00
Michal Kubecek 027dd56418 import Player 12.5.7 module sources 2017-06-30 19:11:22 +02:00
Michal Kubecek 0e634ffbf1 import Player 12.5.6 module sources 2017-05-31 10:06:51 +02:00
Michal Kubecek c62c78e908 import Player 12.5.5 module sources 2017-05-31 09:20:00 +02:00
Michal Kubecek 4f648692e4 import Player 12.5.2 module sources 2017-05-31 09:19:26 +02:00
9 changed files with 250 additions and 209 deletions

No files matched your search

+1 -1
View File
@@ -150,7 +150,7 @@ test build).
When using a downloaded tarball, simply run
tar -cf vmmon.tar vmmon-only
tar -cf vmnet.tar vmnet-only
tar -cf vmnet.tar vmmon-only
to create the tarballs. In this case, there is no protection against
unwanted local changes.
+1 -1
View File
@@ -107,7 +107,7 @@ prebuild:: ;
postbuild:: ;
$(DRIVER_KO): prebuild
$(MAKE) -C $(BUILD_DIR) M=$$PWD SRCROOT=$$PWD/$(SRCROOT) \
$(MAKE) -C $(BUILD_DIR) SUBDIRS=$$PWD SRCROOT=$$PWD/$(SRCROOT) \
MODULEBUILDDIR=$(MODULEBUILDDIR) modules
$(MAKE) -C $$PWD SRCROOT=$$PWD/$(SRCROOT) \
MODULEBUILDDIR=$(MODULEBUILDDIR) postbuild
-1
View File
@@ -251,7 +251,6 @@ static INLINE ub8 hash2(register const ub8 *k, /* the key */
{
/* c is reserved for the length */
case 2: b+=k[1];
/* fall through */
case 1: a+=k[0];
/* case 0: nothing left to add */
}
+3 -6
View File
@@ -73,9 +73,6 @@ static Bool LinuxDriverCheckPadding(void);
struct VMXLinuxState linuxState;
#if LINUX_VERSION_CODE < KERNEL_VERSION(4, 17, 0)
typedef int vm_fault_t;
#endif
/*
*----------------------------------------------------------------------
@@ -100,9 +97,9 @@ long LinuxDriver_Ioctl(struct file *filp, u_int iocmd,
static int LinuxDriver_Close(struct inode *inode, struct file *filp);
#if LINUX_VERSION_CODE >= KERNEL_VERSION(4, 11, 0)
static vm_fault_t LinuxDriverFault(struct vm_fault *fault);
static int LinuxDriverFault(struct vm_fault *fault);
#else
static vm_fault_t LinuxDriverFault(struct vm_area_struct *vma, struct vm_fault *fault);
static int LinuxDriverFault(struct vm_area_struct *vma, struct vm_fault *fault);
#endif
static int LinuxDriverMmap(struct file *filp, struct vm_area_struct *vma);
@@ -597,7 +594,7 @@ LinuxDriver_Close(struct inode *inode, // IN
*-----------------------------------------------------------------------------
*/
static vm_fault_t
static int
#if LINUX_VERSION_CODE >= KERNEL_VERSION(4, 11, 0)
LinuxDriverFault(struct vm_fault *fault) //IN/OUT
#else
+218 -124
View File
@@ -47,16 +47,13 @@
#include <asm/asm.h>
#include <asm/io.h>
#include <asm/page.h>
#include <asm/tlbflush.h>
#include <asm/uaccess.h>
#include <asm/irq_vectors.h>
#include <linux/capability.h>
#include <linux/kthread.h>
#include <linux/wait.h>
#include <linux/hrtimer.h>
#include <linux/signal.h>
#include <linux/taskstats_kern.h> // For linux/sched/signal.h without version check
#include <linux/eventfd.h>
#include "vmware.h"
#include "x86apic.h"
@@ -119,7 +116,13 @@
*/
#define LOCKED_PAGE_SLACK 10000
u64 uptime_base;
static struct {
Atomic_uint64 uptimeBase;
VersionedAtomic version;
uint64 monotimeBase;
unsigned long jiffiesBase;
struct timer_list timer;
} uptimeState;
/*
* First Page Locking strategy
@@ -178,21 +181,6 @@ u64 uptime_base;
uint8 monitorIPIVector;
uint8 hvIPIVector;
static unsigned long compat_totalram_pages(void)
{
#if LINUX_VERSION_CODE < KERNEL_VERSION(5, 0, 0)
return totalram_pages;
#else
return totalram_pages();
#endif
}
#if LINUX_VERSION_CODE < KERNEL_VERSION(5, 0, 0) && defined(VERIFY_WRITE)
#define write_access_ok(addr, size) access_ok(VERIFY_WRITE, addr, size)
#else
#define write_access_ok(addr, size) access_ok(addr, size)
#endif
/*
*-----------------------------------------------------------------------------
*
@@ -606,15 +594,6 @@ HostIF_FastClockUnlock(int callerID) // IN
MutexUnlock(&fastClockMutex, callerID);
}
#if LINUX_VERSION_CODE >= KERNEL_VERSION(5, 8, 0)
static int crosspage_set_exec(pte_t *pte, unsigned long addr, void *data)
{
struct page *p = data;
set_pte(pte, mk_pte(p, VM_PAGE_KERNEL_EXEC));
return 0;
}
#endif
/*
*----------------------------------------------------------------------
@@ -635,29 +614,7 @@ static int crosspage_set_exec(pte_t *pte, unsigned long addr, void *data)
static void *
MapCrossPage(struct page *p) // IN:
{
#if COMPAT_LINUX_VERSION_CHECK_LT(5, 8, 0)
return vmap(&p, 1, VM_MAP, VM_PAGE_KERNEL_EXEC);
#else
void *addr;
addr = vmap(&p, 1, VM_MAP, VM_PAGE_KERNEL_EXEC);
if (!addr)
return NULL;
/* Starting with 5.8, vmap() always sets the NX bit, but the cross
* page needs to be executable. */
if (apply_to_page_range(current->mm, (unsigned long)addr, PAGE_SIZE,
crosspage_set_exec, p)) {
vunmap(addr);
return NULL;
}
preempt_disable();
__flush_tlb_all();
preempt_enable();
return addr;
#endif
}
@@ -1538,7 +1495,14 @@ unsigned int
HostIF_EstimateLockedPageLimit(const VMDriver* vm, // IN
unsigned int currentlyLockedPages) // IN
{
unsigned int totalPhysicalPages = compat_totalram_pages();
/*
* This variable is available and exported to modules,
* since at least 2.6.0.
*/
extern unsigned long totalram_pages;
unsigned int totalPhysicalPages = totalram_pages;
/*
* Use the memory information linux exports as of late for a more
@@ -1563,11 +1527,8 @@ HostIF_EstimateLockedPageLimit(const VMDriver* vm, // IN
#else
lockedPages += global_page_state(NR_PAGETABLE);
#endif
#if LINUX_VERSION_CODE >= KERNEL_VERSION(5, 9, 0)
/* NR_SLAB_* converted to byte counters in 5.9 */
lockedPages += global_node_page_state_pages(NR_SLAB_UNRECLAIMABLE_B);
#elif LINUX_VERSION_CODE >= KERNEL_VERSION(4, 13, 0)
/* NR_SLAB_* moved from zone to node in 4.13. */
#if LINUX_VERSION_CODE >= KERNEL_VERSION(4, 13, 0)
lockedPages += global_node_page_state(NR_SLAB_UNRECLAIMABLE);
#else
lockedPages += global_page_state(NR_SLAB_UNRECLAIMABLE);
@@ -1639,6 +1600,143 @@ HostIF_WaitForFreePages(unsigned int timeoutMs) // IN:
}
/*
*----------------------------------------------------------------------
*
* HostIFReadUptimeWork --
*
* Reads the current uptime. The uptime is based on getimeofday,
* which provides the needed high resolution. However, we don't
* want uptime to be warped by e.g. calls to settimeofday. So, we
* use a jiffies based monotonic clock to sanity check the uptime.
* If the uptime is more than one second from the monotonic time,
* we assume that the time of day has been set, and recalculate the
* uptime base to get uptime back on track with monotonic time. On
* the other hand, we do expect jiffies based monotonic time and
* timeofday to have small drift (due to NTP rate correction, etc).
* We handle this by rebasing the jiffies based monotonic clock
* every second (see HostIFUptimeResyncMono).
*
* Results:
* The uptime, in units of UPTIME_FREQ. Also returns the jiffies
* value that was used in the monotonic time calculation.
*
* Side effects:
* May reset the uptime base in the case gettimeofday warp was
* detected.
*
*----------------------------------------------------------------------
*/
static uint64
HostIFReadUptimeWork(unsigned long *j) // OUT: current jiffies
{
struct timeval tv;
uint64 monotime, uptime, upBase, monoBase;
int64 diff;
uint32 version;
unsigned long jifs, jifBase;
unsigned int attempts = 0;
retry:
do {
version = VersionedAtomic_BeginTryRead(&uptimeState.version);
jifs = jiffies;
jifBase = uptimeState.jiffiesBase;
monoBase = uptimeState.monotimeBase;
} while (!VersionedAtomic_EndTryRead(&uptimeState.version, version));
do_gettimeofday(&tv);
upBase = Atomic_Read64(&uptimeState.uptimeBase);
monotime = (uint64)(jifs - jifBase) * (UPTIME_FREQ / HZ);
monotime += monoBase;
uptime = tv.tv_usec * (UPTIME_FREQ / 1000000) + tv.tv_sec * UPTIME_FREQ;
uptime += upBase;
/*
* Use the jiffies based monotonic time to sanity check gettimeofday.
* If they differ by more than one second, assume the time of day has
* been warped, and use the jiffies time to undo (most of) the warp.
*/
diff = uptime - monotime;
if (UNLIKELY(diff < -UPTIME_FREQ || diff > UPTIME_FREQ)) {
/* Compute a new uptimeBase to get uptime back on track. */
uint64 newUpBase = monotime - (uptime - upBase);
attempts++;
if (!Atomic_CMPXCHG64(&uptimeState.uptimeBase, upBase, newUpBase) &&
attempts < 5) {
/* Another thread updated uptimeBase. Recalculate uptime. */
goto retry;
}
uptime = monotime;
Log("%s: detected settimeofday: fixed uptimeBase old %"FMT64"u "
"new %"FMT64"u attempts %u\n", __func__,
upBase, newUpBase, attempts);
}
*j = jifs;
return uptime;
}
/*
*----------------------------------------------------------------------
*
* HostIFUptimeResyncMono --
*
* Timer that fires ever second to resynchronize the jiffies based
* monotonic time with the uptime.
*
* Results:
* None
*
* Side effects:
* Resets the monotonic time bases so that jiffies based monotonic
* time does not drift from gettimeofday over the long term.
*
*----------------------------------------------------------------------
*/
static void
HostIFUptimeResyncMono(struct timer_list *timer) // IN: ignored
{
unsigned long jifs;
uintptr_t flags;
/*
* Read the uptime and the corresponding jiffies value. This will
* also correct the uptime (which is based on time of day) if needed
* before we rebase monotonic time (which is based on jiffies).
*/
uint64 uptime = HostIFReadUptimeWork(&jifs);
/*
* Every second, recalculate monoBase and jiffiesBase to squash small
* drift between gettimeofday and jiffies. Also, this prevents
* (jiffies - jiffiesBase) wrap on 32-bits.
*/
SAVE_FLAGS(flags);
CLEAR_INTERRUPTS();
VersionedAtomic_BeginWrite(&uptimeState.version);
uptimeState.monotimeBase = uptime;
uptimeState.jiffiesBase = jifs;
VersionedAtomic_EndWrite(&uptimeState.version);
RESTORE_FLAGS(flags);
/* Reschedule this timer to expire in one second. */
mod_timer(&uptimeState.timer, jifs + HZ);
}
/*
*----------------------------------------------------------------------
*
@@ -1650,7 +1748,8 @@ HostIF_WaitForFreePages(unsigned int timeoutMs) // IN:
* None
*
* Side effects:
* Sets the initial value for the uptime base.
* Sets the initial values for the uptime state, and schedules
* the uptime timer.
*
*----------------------------------------------------------------------
*/
@@ -1658,7 +1757,22 @@ HostIF_WaitForFreePages(unsigned int timeoutMs) // IN:
void
HostIF_InitUptime(void)
{
uptime_base = ktime_get_ns();
struct timeval tv;
uptimeState.jiffiesBase = jiffies;
do_gettimeofday(&tv);
Atomic_Write64(&uptimeState.uptimeBase,
-(tv.tv_usec * (UPTIME_FREQ / 1000000) +
tv.tv_sec * UPTIME_FREQ));
#if LINUX_VERSION_CODE < KERNEL_VERSION(4, 15, 0) && !defined(timer_setup)
init_timer(&uptimeState.timer);
uptimeState.timer.function = (void *)HostIFUptimeResyncMono;
uptimeState.timer.data = (unsigned long)&uptimeState.timer;
#else
timer_setup(&uptimeState.timer, HostIFUptimeResyncMono, 0);
#endif
mod_timer(&uptimeState.timer, jiffies + HZ);
}
@@ -1667,13 +1781,13 @@ HostIF_InitUptime(void)
*
* HostIF_CleanupUptime --
*
* No-op, left for backward compatibility.
* Cleanup uptime state, called at module unloading time.
*
* Results:
* None
*
* Side effects:
* None
* Deschedule the uptime timer.
*
*----------------------------------------------------------------------
*/
@@ -1681,6 +1795,7 @@ HostIF_InitUptime(void)
void
HostIF_CleanupUptime(void)
{
del_timer_sync(&uptimeState.timer);
}
@@ -1704,10 +1819,9 @@ HostIF_CleanupUptime(void)
uint64
HostIF_ReadUptime(void)
{
u64 tm;
unsigned long jifs;
tm = ktime_get_ns();
return (tm - uptime_base) / (NSEC_PER_SEC / UPTIME_FREQ);
return HostIFReadUptimeWork(&jifs);
}
@@ -2027,27 +2141,6 @@ HostIF_VMLockIsHeld(VMDriver *vm) // IN
#if defined(CONFIG_SMP) || defined(CONFIG_X86_UP_IOAPIC) || \
defined(CONFIG_X86_UP_APIC) || defined(CONFIG_X86_LOCAL_APIC)
#if COMPAT_LINUX_VERSION_CHECK_LT(5, 8, 0)
static long compat_copy_from_kernel_nofault(void *dst, VA src, size_t size)
{
mm_segment_t old_fs;
long ret;
old_fs = get_fs();
set_fs(KERNEL_DS);
ret = HostIF_CopyFromUser(dst, src, size);
set_fs(old_fs);
return ret;
}
#else
static long compat_copy_from_kernel_nofault(void *dst, VA src, size_t size)
{
return copy_from_kernel_nofault(dst, (const void *)src, size);
}
#endif
/*
*----------------------------------------------------------------------
*
@@ -2067,11 +2160,15 @@ static long compat_copy_from_kernel_nofault(void *dst, VA src, size_t size)
static Bool
isVAReadable(VA r) // IN:
{
mm_segment_t old_fs;
uint32 dummy;
long ret;
int ret;
old_fs = get_fs();
set_fs(get_ds());
r = APICR_TO_ADDR(r, APICR_VERSION);
ret = compat_copy_from_kernel_nofault(&dummy, r, sizeof(dummy));
ret = HostIF_CopyFromUser(&dummy, r, sizeof dummy);
set_fs(old_fs);
return ret == 0;
}
@@ -2101,7 +2198,7 @@ SetVMAPICAddr(VMDriver *vm, // IN/OUT: driver state
volatile void *hostapic;
ASSERT_ON_COMPILE(APICR_SIZE <= PAGE_SIZE);
hostapic = (volatile void *) ioremap(ma, PAGE_SIZE);
hostapic = (volatile void *) ioremap_nocache(ma, PAGE_SIZE);
if (hostapic) {
if ((APIC_VERSIONREG(hostapic) & 0xF0) == 0x10) {
vm->hostAPIC.base = (volatile uint32 (*)[4]) hostapic;
@@ -2257,41 +2354,44 @@ HostIF_SemaphoreWait(VMDriver *vm, // IN:
uint64 *args) // IN:
{
struct file *file;
mm_segment_t old_fs;
int res;
int waitFD = args[0];
int timeoutms = args[2];
uint64 value;
struct poll_wqueues table;
unsigned int mask;
file = vmware_fget(waitFD);
if (file == NULL) {
return MX_WAITERROR;
}
poll_initwait(&table);
current->state = TASK_INTERRUPTIBLE;
mask = compat_vfs_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;
old_fs = get_fs();
set_fs(get_ds());
{
struct poll_wqueues table;
unsigned int mask;
poll_initwait(&table);
current->state = TASK_INTERRUPTIBLE;
mask = compat_vfs_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;
poll_freewait(&table);
}
current->state = TASK_RUNNING;
poll_freewait(&table);
/*
* Userland only writes in multiples of sizeof(uint64). This will allow
* 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).
*
* Upstream Linux changed the function parameter types/ordering in 4.14.0.
*/
#if LINUX_VERSION_CODE < KERNEL_VERSION(4, 14, 0)
res = kernel_read(file, file->f_pos, (char *)&value, sizeof value);
#else
res = kernel_read(file, &value, sizeof value, &file->f_pos);
#endif
res = file->f_op->read(file, (char *) &value, sizeof value, &file->f_pos);
if (res == sizeof value) {
res = MX_WAITNORMAL;
} else {
@@ -2300,6 +2400,7 @@ HostIF_SemaphoreWait(VMDriver *vm, // IN:
}
}
set_fs(old_fs);
fput(file);
/*
@@ -2382,8 +2483,8 @@ HostIF_SemaphoreForceWakeup(VMDriver *vm, // IN:
int
HostIF_SemaphoreSignal(uint64 *args) // IN:
{
struct eventfd_ctx *eventfd;
struct file *file;
mm_segment_t old_fs;
int res;
int signalFD = args[1];
uint64 value = 1; // make an eventfd happy should it be there
@@ -2393,34 +2494,22 @@ HostIF_SemaphoreSignal(uint64 *args) // IN:
return MX_WAITERROR;
}
/*
* If it's eventfd, use specific eventfd interface as kernel writes
* to eventfd may not be allowed in kernel 5.10 and later.
*/
eventfd = eventfd_ctx_fileget(file);
if (!IS_ERR(eventfd)) {
eventfd_signal(eventfd, 1);
fput(file);
return MX_WAITNORMAL;
}
old_fs = get_fs();
set_fs(get_ds());
/*
* Always write sizeof(uint64) bytes. This works fine for eventfd and
* pipes. The data written is formatted to make an eventfd happy should
* it be present.
*
* Upstream Linux changed the function parameter types/ordering in 4.14.0.
*/
#if LINUX_VERSION_CODE < KERNEL_VERSION(4, 14, 0)
res = kernel_write(file, (char *)&value, sizeof value, file->f_pos);
#else
res = kernel_write(file, &value, sizeof value, &file->f_pos);
#endif
res = file->f_op->write(file, (char *) &value, sizeof value, &file->f_pos);
if (res == sizeof value) {
res = MX_WAITNORMAL;
}
set_fs(old_fs);
fput(file);
/*
@@ -2939,9 +3028,12 @@ static int
HostIFFastClockThread(void *unused) // IN:
{
int res;
mm_segment_t oldFS;
unsigned int rate = 0;
unsigned int prevRate = 0;
oldFS = get_fs();
set_fs(KERNEL_DS);
allow_signal(SIGKILL);
while ((rate = linuxState.fastClockRate) > MIN_RATE) {
@@ -2964,6 +3056,8 @@ HostIFFastClockThread(void *unused) // IN:
}
out:
set_fs(oldFS);
/*
* Do not exit thread until we are told to do so.
*/
@@ -3061,7 +3155,7 @@ HostIF_SetFastClockRate(unsigned int rate) // IN: Frequency in Hz.
}
} else {
if (linuxState.fastClockThread) {
send_sig(SIGKILL, linuxState.fastClockThread, 1);
force_sig(SIGKILL, linuxState.fastClockThread);
kthread_stop(linuxState.fastClockThread);
linuxState.fastClockThread = NULL;
@@ -3107,7 +3201,7 @@ HostIF_MapUserMem(VA addr, // IN: User memory virtual address
ASSERT(handle);
if (!write_access_ok(p, size)) {
if (!access_ok(VERIFY_WRITE, p, size)) {
printk(KERN_ERR "%s: Couldn't verify write to uva 0x%p with size %"
FMTSZ"u\n", __func__, p, size);
+1 -1
View File
@@ -107,7 +107,7 @@ prebuild:: ;
postbuild:: ;
$(DRIVER_KO): prebuild
$(MAKE) -C $(BUILD_DIR) M=$$PWD SRCROOT=$$PWD/$(SRCROOT) \
$(MAKE) -C $(BUILD_DIR) SUBDIRS=$$PWD SRCROOT=$$PWD/$(SRCROOT) \
MODULEBUILDDIR=$(MODULEBUILDDIR) modules
$(MAKE) -C $$PWD SRCROOT=$$PWD/$(SRCROOT) \
MODULEBUILDDIR=$(MODULEBUILDDIR) postbuild
+7 -6
View File
@@ -66,7 +66,7 @@
#endif
#if LOGLEVEL >= 4
static u64 vnetTime;
static struct timeval vnetTime;
#endif
typedef struct VNetBridge VNetBridge;
@@ -693,7 +693,7 @@ VNetBridgeReceiveFromVNet(VNetJack *this, // IN: jack
netif_rx_ni(clone);
# if LOGLEVEL >= 4
vnetTime = ktime_get_ns();
do_gettimeofday(&vnetTime);
# endif
}
}
@@ -1490,11 +1490,12 @@ VNetBridgeReceiveFromDev(struct sk_buff *skb, // IN: packet to receive
# if LOGLEVEL >= 4
{
u64 now;
now = ktime_get_ns();
struct timeval now;
do_gettimeofday(&now);
LOG(3, (KERN_DEBUG "bridge-%s: time %d\n",
bridge->name, (int)((now - vnetTime) / NSEC_PER_USEC)));
bridge->name,
(int)((now.tv_sec * 1000000 + now.tv_usec)
- (vnetTime.tv_sec * 1000000 + vnetTime.tv_usec))));
}
# endif
-9
View File
@@ -161,14 +161,6 @@ VNetProcOpen(struct inode *inode, // IN:
}
/* Our procfs callbacks. We only need to specialize open. */
#ifdef DEFINE_PROC_SHOW_ATTRIBUTE
static const struct proc_ops fops = {
.proc_open = VNetProcOpen,
.proc_read = seq_read,
.proc_lseek = seq_lseek,
.proc_release = single_release,
};
#else
static struct file_operations fops = {
.open = VNetProcOpen,
.read = seq_read,
@@ -176,7 +168,6 @@ static struct file_operations fops = {
.release = single_release,
};
#endif
#endif
/*
+19 -60
View File
@@ -78,55 +78,11 @@ static int VNetUserIfSetUplinkState(VNetPort *port, uint8 linkUp);
extern unsigned int vnet_max_qlen;
#if COMPAT_LINUX_VERSION_CHECK_LT(3, 2, 0)
# define compat_kmap_frag(frag) kmap((frag)->page)
# define compat_kunmap_frag(page) kunmap((frag)->page)
# define compat_kmap(page) kmap(page)
# define compat_kunmap(page) kunmap(page)
#else
# define compat_kmap_frag(frag) kmap(skb_frag_page(frag))
# define compat_kunmap_frag(frag) kunmap(skb_frag_page(frag))
#endif
static unsigned int compat_skb_frag_size(const skb_frag_t *frag)
{
#if COMPAT_LINUX_VERSION_CHECK_LT(3, 2, 0)
return frag->size;
#else
return skb_frag_size(frag);
#endif
}
static unsigned int compat_skb_frag_off(const skb_frag_t *frag)
{
#if COMPAT_LINUX_VERSION_CHECK_LT(5, 4, 0) && \
!(defined(CONFIG_SUSE_VERSION) && CONFIG_SUSE_VERSION == 15 && \
defined(CONFIG_SUSE_PATCHLEVEL) && CONFIG_SUSE_PATCHLEVEL >= 2)
return frag->page_offset;
#else
return skb_frag_off(frag);
#endif
}
#if LINUX_VERSION_CODE < KERNEL_VERSION(5, 0, 0) && defined(VERIFY_WRITE)
#define write_access_ok(addr, size) access_ok(VERIFY_WRITE, addr, size)
#else
#define write_access_ok(addr, size) access_ok(addr, size)
#endif
#if COMPAT_LINUX_VERSION_CHECK_LT(5, 10, 0)
static inline
__wsum compat_csum_and_copy_to_user(const void *src, void __user *dst, int len)
{
int err;
__wsum ret;
ret = csum_and_copy_to_user(src, dst, len, 0, &err);
return err ? 0 : ret;
}
#else
static inline
__wsum compat_csum_and_copy_to_user(const void *src, void __user *dst, int len)
{
return csum_and_copy_to_user(src, dst, len);
}
# define compat_kmap(page) kmap((page).p)
# define compat_kunmap(page) kunmap((page).p)
#endif
/*
@@ -186,7 +142,7 @@ VNetUserIfMapPtr(VA uAddr, // IN: pointer to user memory
struct page **p, // OUT: locked page
void **ptr) // OUT: kernel mapped pointer
{
if (!write_access_ok((void *)uAddr, size) ||
if (!access_ok(VERIFY_WRITE, (void *)uAddr, size) ||
(((uAddr + size - 1) & ~(PAGE_SIZE - 1)) !=
(uAddr & ~(PAGE_SIZE - 1)))) {
return -EINVAL;
@@ -581,6 +537,7 @@ VNetCsumCopyDatagram(const struct sk_buff *skb, // IN: skb to copy
char *buf) // OUT: where to copy data
{
unsigned int csum;
int err = 0;
int len = skb_headlen(skb) - offset;
char *curr = buf;
const skb_frag_t *frag;
@@ -593,27 +550,29 @@ VNetCsumCopyDatagram(const struct sk_buff *skb, // IN: skb to copy
return -EINVAL;
}
csum = compat_csum_and_copy_to_user(skb->data + offset, curr, len);
if (!csum)
return -EFAULT;
csum = csum_and_copy_to_user(skb->data + offset, curr, len, 0, &err);
if (err) {
return err;
}
curr += len;
for (frag = skb_shinfo(skb)->frags;
frag != skb_shinfo(skb)->frags + skb_shinfo(skb)->nr_frags;
frag++) {
if (compat_skb_frag_size(frag) > 0) {
if (frag->size > 0) {
unsigned int tmpCsum;
const void *vaddr;
vaddr = compat_kmap_frag(frag);
tmpCsum = compat_csum_and_copy_to_user(vaddr + compat_skb_frag_off(frag),
curr, compat_skb_frag_size(frag));
compat_kunmap_frag(frag);
vaddr = compat_kmap(frag->page);
tmpCsum = csum_and_copy_to_user(vaddr + frag->page_offset,
curr, frag->size, 0, &err);
compat_kunmap(frag->page);
if (!tmpCsum)
return -EFAULT;
if (err) {
return err;
}
csum = csum_block_add(csum, tmpCsum, curr - buf);
curr += compat_skb_frag_size(frag);
curr += frag->size;
}
}