--- a/vmnet/Makefile +++ b/vmnet/Makefile @@ -43,7 +43,11 @@ endif +ifdef KVERSION +VM_UNAME = $(KVERSION) +else VM_UNAME = $(shell uname -r) +endif # Header directory for the running kernel ifdef LINUXINCLUDE @@ -137,7 +141,6 @@ endif # Add Spectre options when available -CC_OPTS += $(call vm_check_gcc,-mindirect-branch=thunk -mindirect-branch-register,) include $(SRCROOT)/Makefile.kernel --- a/vmnet/bridge.c +++ b/vmnet/bridge.c @@ -26,6 +26,9 @@ #include #include +#if LINUX_VERSION_CODE >= KERNEL_VERSION(6, 4, 10) +#include +#endif #include #include #include @@ -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 @@ VNetRemovePortFromList(const VNetPort *port) // IN: port to remove from list /* *---------------------------------------------------------------------- * - * init_module -- + * LinuxDriverInit -- * * linux module entry point. Called by /sbin/insmod command. * Initializes module and Registers this driver for a @@ -296,7 +296,7 @@ VNetRemovePortFromList(const VNetPort *port) // IN: port to remove from list */ int -init_module(void) +LinuxDriverInit(void) { int retval; @@ -358,7 +358,7 @@ init_module(void) /* *---------------------------------------------------------------------- * - * 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 @@ init_module(void) */ void -cleanup_module(void) +LinuxDriverExit(void) { unregister_chrdev(VNET_MAJOR_NUMBER, "vmnet"); VNetProtoUnregister(); @@ -1701,3 +1701,5 @@ MODULE_LICENSE("GPL v2"); * 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(src, dst, len, 0, err); +#elif LINUX_VERSION_CODE < KERNEL_VERSION(5, 19, 0) + csum = csum_and_copy_to_user(src, dst, len); + *err = (csum == 0) ? -EFAULT : 0; +#else + if (!user_access_begin(dst, len)) { + *err = -EFAULT; + csum = 0; + } else { + *err = 0; + csum = csum_partial_copy_nocheck(src, dst, len); + user_access_end(); + } +#endif + return csum; +} + + +/* + *---------------------------------------------------------------------- + * * VNetCsumCopyDatagram -- * * Copy part of datagram to userspace doing checksum at same time. @@ -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,8 @@ 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 = 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 +#elif !defined(VMKERNEL) # include #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; }