Compare commits

..
Author SHA1 Message Date
Michal Kubecek 78c5443317 vmmon: avoid kernel writes to eventfd
Starting with mainline commit 4d03e3cc5982 ("fs: don't allow kernel reads
and writes without iter ops") in 5.10-rc1, kernel writes are only allowed
for files providing ->write_iter() callback which eventfd does not.

As an attempt to address this issue on kernel side by providing
->write_iter() callback to eventfd was met with a pushback and it's not
clear if there is a chance for it to be accepted, let's use a specific
eventfd interface eventfd_signal() instead. However, as the comments in
HostIF_SemaphoreSignal() indicate that the file descriptor may also be
a pipe (without telling when), let's keep kernel_write() as a fallback
in case the file descriptor is not eventfd.

Signed-off-by: Michal Kubecek <mkubecek@suse.cz>
2020-11-24 08:59:34 +01:00
Michal Kubecek 114301e71a vmmon: reflect rename of <linux/frame.h>
Header file <linux/frame.h> has been renamed to <linux/objtool.h> by
mainline commit 00089c048eb4 ("objtool: Rename frame.h -> objtool.h") in
5.10-rc1. Adjust the include directive accordingly.
2020-10-26 01:33:07 +01:00
Michal Kubecek bea0c1d1f4 vmnet: use new compat_csum_and_copy_to_user() calling convention
Part of bigger csum_and_copy rework, commit c693cc4676a0 ("saner calling
conventions for csum_and_copy_..._user()") in 5.10-rc1 drops last two
arguments and changes the way errors are reported.

Provide a compat wrapper with new calling convention and rewrite callers in
vmnet to use it. Unfortunately there doesn't seem to be a way to recognize
which calling convention kernel has so version check is used.
2020-10-26 01:31:07 +01:00
Michal Kubecek 714c0b283c vmmon: avoid set_fs() in HostIFFastClockThread()
The set_fs() function was dropped on x86_64 architecture by mainline commit
47058bb54b57 ("x86: remove address space overrides using set_fs()") in
5.10-rc1. It's not clear what purpose does set_fs(KERNEL_DS) serve in
HostIFFastClockThread(); it was certainly needed for the old code using
functions expecting user pointers to access /dev/rtc but that code has been
dropped between Workstation 12.5.7 and 14.0.0 in September 2017.

Drop the temporary set_fs(KERNEL_DS) trick as there doesn't seem to be
a need for it any more.
2020-10-26 01:29:56 +01:00
Michal Kubecek 05170767e2 vmmon: avoid set_fs() in isVAReadable()
The set_fs() function was dropped on x86_64 architecture by mainline commit
47058bb54b57 ("x86: remove address space overrides using set_fs()") in
5.10-rc1. In isVAReadable() it is used to check if a kernel address can be
read from without risking a pagefault if the answer is negative by using
set_fs() to pretend it's a userspace address and checking with
copy_from_user(). Starting with 5.8, copy_from_kernel_nofault() can be
used to copy from a kernel address with access check but without an actual
pagefault.
2020-10-26 01:19:55 +01:00
Michal Kubecek 2ea604e24c vmmon: include <asm/irq_vectors.h> explicitly
After mainline commit 13c01139b171 ("x86/headers: Remove APIC headers from
<asm/smp.h>") in 5.9-rc1, APIC headers are no longer included via
<asm/smp.h> so that linux/hostif.c will use incorrect fallback definitions
of SPURIOUS_APIC_VECTOR, POSTED_INTR_VECTOR and ERROR_APIC_VECTOR even if
built against kernel where these are defined.

Include <asm/irq_vectors.h> in linux/hostif.c explicitly to avoid that.
2020-09-15 21:59:56 +02:00
Michal Kubecek e6cc9071d2 vmmon: use standard definitions of MSR_TEST_CTRL and MSR_TEST_CTRL_SPLIT_LOCK_DETECT
The MSR_TEST_CTRL and MSR_TEST_CTRL_SPLIT_LOCK_DETECT macros are defined in
arch/x86/include/asm/msr-index.h since commit 6650cdd9a8cc
("x86/split_lock: Enable split lock detection by kernel") in v5.7-rc1.
2020-09-15 21:59:56 +02:00
Michal Kubecek 0dd333a403 vmmon: use standard definition of MSR_TSX_FORCE_ABORT if available
The MSR_TSX_FORCE_ABORT macro is defined in mainline since commit
52f64909409c ("x86: Add TSX Force Abort CPUID/MSR") in v5.1-rc1.
2020-09-15 21:59:56 +02:00
Michal Kubecek 9afa7df257 vmnet: convert VNetBridge debugging code to ktime_get_ns()
The do_gettimeofday() helper was removed by commit e4b92b108c6c
("timekeeping: remove obsolete time accessors") in v5.0-rc1 and since
commit c766d1472c70 ("y2038: hide timeval/timespec/itimerval/itimerspec
types") in v5.6-rc3, struct timeval should no longer be used in kernel
code.

Convert the do_gettimeofday() relics in VNetBridge (which are only compiled
with LOGLEVEL >= 4) completely to ktime based interface.
2020-09-15 21:59:56 +02:00
Michal Kubecek f92a0e9548 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.
2020-09-15 21:59:56 +02:00
Michal Kubecek ba86d4cec4 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.
2020-09-15 21:59:56 +02:00
Michal Kubecek 232baca602 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.
2020-09-15 21:59:56 +02:00
Theo Bertacchini ac21bb0259 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 was created by build since
kernel v4.15-rc1, commit 3298b690b21c ("kbuild: Add a cache for generated
variables") until the feature was removed in v4.18-rc1, commit e08d6de4e532
("kbuild: remove kbuild cache").
2020-09-15 21:59:56 +02:00
Michal Kubecek 6eef52adb8 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.
2020-09-15 21:59:56 +02:00
Michal Kubecek a15fafb33e 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.
2020-09-15 21:59:56 +02:00
Michal Kubecek fdab3451ac 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.
2020-09-15 21:59:56 +02:00
Michal Kubecek 2b7ad432a3 vmmon: rename GDT_SIZE macro to avoid collision
When building against kernel 4.12 and newer, macro name GDT_SIZE used in
(vmmon) include/segs.h collides with macro defined in (kernel source)
arch/x86/include/asm/segment.h, resulting in its redefinition.

To prevent potential problems, rename vmmon's GDT_SIZE to VMMON_GDT_SIZE
and GDT_LIMIT to VMMON_GDT_LIMIT. (There is no GDT_LIMIT in mainline kernel
source but let's be consistent.)
2020-09-15 21:59:56 +02:00
Michal Kubecek fb7cb68b3c 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.
2020-09-15 21:59:56 +02:00
Michal Kubecek 29cfea0504 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.
2020-09-15 21:59:56 +02:00
Michal Kubecek b4610316f5 vmmon: fix version check for <linux/frame.h> include
Both the version check for include of <linux/frame.h> in common/crosspage.c
and the comment explaining it are wrong for multiple reasons:

  1. <linux/frame.h> was introduced in v4.6-rc1, not v4.5-rc5
  2. ANNOTATE_INTRA_FUNCTION_CALL was introduced in v5.8-rc1, not v5.7
  3. Even if it were, the check should use ">=", not ">"
  4. Most important, the code in fact needs STACK_FRAME_NON_STANDARD

Without the definition of STACK_FRAME_NON_STANDARD, build against vanilla
5.7 kernel fails on objtool error (but succeeds against 5.7.1, because of
the mistake from point 3).

Change the check from "> 5.7" to ">= 4.6" to get STACK_FRAME_NON_STANDARD
whenever available and update the explaining comment.
2020-09-15 21:59:56 +02:00
3 changed files with 64 additions and 22 deletions

No files matched your search

+3 -1
View File
@@ -51,7 +51,9 @@
* linux/frame.h dates back to 4.6-rc1, we need the STACK_FRAME_NON_STANDARD
* definition from it which is there from the start.
*/
# if LINUX_VERSION_CODE >= KERNEL_VERSION(4, 6, 0)
# if LINUX_VERSION_CODE >= KERNEL_VERSION(5, 10, 0)
# include <linux/objtool.h>
# elif LINUX_VERSION_CODE >= KERNEL_VERSION(4, 6, 0)
# include <linux/frame.h>
# endif
#endif
+36 -11
View File
@@ -55,6 +55,7 @@
#include <linux/hrtimer.h>
#include <linux/signal.h>
#include <linux/taskstats_kern.h> // For linux/sched/signal.h without version check
#include <linux/eventfd.h>
#include "vmware.h"
#include "x86apic.h"
@@ -2330,6 +2331,27 @@ 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
/*
*----------------------------------------------------------------------
*
@@ -2349,15 +2371,11 @@ HostIF_VMLockIsHeld(VMDriver *vm) // IN
static Bool
isVAReadable(VA r) // IN:
{
mm_segment_t old_fs;
uint32 dummy;
int ret;
long ret;
old_fs = get_fs();
set_fs(KERNEL_DS);
r = APICR_TO_ADDR(r, APICR_VERSION);
ret = HostIF_CopyFromUser(&dummy, r, sizeof dummy);
set_fs(old_fs);
ret = compat_copy_from_kernel_nofault(&dummy, r, sizeof(dummy));
return ret == 0;
}
@@ -2670,6 +2688,7 @@ HostIF_SemaphoreForceWakeup(VMDriver *vm, // IN:
int
HostIF_SemaphoreSignal(uint64 *args) // IN:
{
struct eventfd_ctx *eventfd;
struct file *file;
int res;
int signalFD = args[1];
@@ -2680,6 +2699,17 @@ 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;
}
/*
* Always write sizeof(uint64) bytes. This works fine for eventfd and
* pipes. The data written is formatted to make an eventfd happy should
@@ -3243,12 +3273,9 @@ static int
HostIFFastClockThread(void *unused) // IN:
{
int res;
mm_segment_t oldFS;
unsigned int rate = 0;
unsigned int prevRate = 0;
oldFS = get_fs();
set_fs(KERNEL_DS);
allow_signal(SIGKILL);
while ((rate = linuxState.fastClockRate) > MIN_RATE) {
@@ -3271,8 +3298,6 @@ HostIFFastClockThread(void *unused) // IN:
}
out:
set_fs(oldFS);
/*
* Do not exit thread until we are told to do so.
*/
+25 -10
View File
@@ -87,6 +87,24 @@ extern unsigned int vnet_max_qlen;
# define skb_frag_off(frag) (frag)->page_offset
#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);
}
#endif
/*
*-----------------------------------------------------------------------------
*
@@ -548,7 +566,6 @@ 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;
@@ -561,10 +578,9 @@ VNetCsumCopyDatagram(const struct sk_buff *skb, // IN: skb to copy
return -EINVAL;
}
csum = csum_and_copy_to_user(skb->data + offset, curr, len, 0, &err);
if (err) {
return err;
}
csum = compat_csum_and_copy_to_user(skb->data + offset, curr, len);
if (!csum)
return -EFAULT;
curr += len;
for (frag = skb_shinfo(skb)->frags;
@@ -575,13 +591,12 @@ VNetCsumCopyDatagram(const struct sk_buff *skb, // IN: skb to copy
const void *vaddr;
vaddr = kmap(skb_frag_page(frag));
tmpCsum = csum_and_copy_to_user(vaddr + skb_frag_off(frag),
curr, skb_frag_size(frag), 0, &err);
tmpCsum = compat_csum_and_copy_to_user(vaddr + skb_frag_off(frag),
curr, skb_frag_size(frag));
kunmap(skb_frag_page(frag));
if (err) {
return err;
}
if (!tmpCsum)
return -EFAULT;
csum = csum_block_add(csum, tmpCsum, curr - buf);
curr += skb_frag_size(frag);
}