--- a/vmnet/Makefile +++ b/vmnet/Makefile @@ -43,7 +43,11 @@ INCLUDE += -I$(SRCROOT)/shared endif +ifdef KVERSION +VM_UNAME = $(KVERSION) +else VM_UNAME = $(shell uname -r) +endif # Header directory for the running kernel ifdef LINUXINCLUDE @@ -100,6 +104,13 @@ auto-build: $(DRIVER_KO) $(DRIVER): $(DRIVER_KO) if [ $< -nt $@ ] || [ ! -e $@ ] ; then cp -f $< $@; fi +# Use SUBDIRS on 2.x, 3.x, 4.x. Use M on newer kernels. +ifeq ($(filter-out 2 3 4,$(firstword $(subst ., ,$(VM_UNAME)))),) +DIRVAR := SUBDIRS +else +DIRVAR := M +endif + # Pass gcc version down the chain, so we can detect if kernel attempts to use unapproved compiler VM_CCVER := $(VMCCVER) export VM_CCVER @@ -117,7 +128,7 @@ prebuild:: ; postbuild:: ; $(DRIVER_KO): prebuild - $(MAKE) -C $(BUILD_DIR) SUBDIRS=$$PWD SRCROOT=$$PWD/$(SRCROOT) \ + $(MAKE) -C $(BUILD_DIR) $(DIRVAR)=$$PWD SRCROOT=$$PWD/$(SRCROOT) \ MODULEBUILDDIR=$(MODULEBUILDDIR) modules $(MAKE) -C $$PWD SRCROOT=$$PWD/$(SRCROOT) \ MODULEBUILDDIR=$(MODULEBUILDDIR) postbuild --- a/vmnet/bridge.c +++ b/vmnet/bridge.c @@ -65,7 +65,7 @@ #endif #if LOGLEVEL >= 4 -static struct timeval vnetTime; +static u64 vnetTime; #endif typedef struct VNetBridge VNetBridge; @@ -636,7 +636,7 @@ VNetBridgeReceiveFromVNet(VNetJack unsigned long flags; int i; - atomic_inc(&clone->users); + clone = skb_get(clone); clone->dev = dev; clone->protocol = eth_type_trans(clone, dev); @@ -696,7 +696,7 @@ VNetBridgeReceiveFromVNet(VNetJack netif_rx_ni(clone); # if LOGLEVEL >= 4 - do_gettimeofday(&vnetTime); + vnetTime = ktime_get_ns(); # endif } } @@ -1143,11 +1143,16 @@ VNetBridgeNotifyLogBridgeUpError(int err static int VNetBridgeNotify(struct notifier_block *this, // IN: callback data (bridge) u_long msg, // IN: type of event - void *data) // IN: device pertaining to event + void *data) // IN: net_device or notifier info { VNetBridge *bridge = list_entry(this, VNetBridge, notifier); - struct net_device *dev = (struct net_device *) data; + struct net_device *dev; +#if LINUX_VERSION_CODE >= KERNEL_VERSION(3, 11, 0) + dev = netdev_notifier_info_to_dev(data); +#else + dev = (struct net_device *)data; +#endif switch (msg) { case NETDEV_UNREGISTER: LOG(2, (KERN_DEBUG "bridge-%s: interface %s is unregistering\n", @@ -1656,12 +1661,11 @@ VNetBridgeReceiveFromDev(struct sk_buff # if LOGLEVEL >= 4 { - struct timeval now; - do_gettimeofday(&now); + u64 now; + + now = ktime_get_ns(); LOG(3, (KERN_DEBUG "bridge-%s: time %d\n", - bridge->name, - (int)((now.tv_sec * 1000000 + now.tv_usec) - - (vnetTime.tv_sec * 1000000 + vnetTime.tv_usec)))); + bridge->name, (int)((now - vnetTime) / NSEC_PER_USEC))); } # endif --- a/vmnet/compat_netdevice.h +++ b/vmnet/compat_netdevice.h @@ -337,4 +337,11 @@ typedef netdev_features_t compat_netdev_ typedef u32 compat_netdev_features_t; #endif +#if LINUX_VERSION_CODE >= KERNEL_VERSION(4, 7, 0) || \ + (defined(RHEL_RELEASE_CODE) && RHEL_RELEASE_CODE >= 0x0704) +#define compat_netif_trans_update(d) netif_trans_update(d) +#else +#define compat_netif_trans_update(d) do { (d)->trans_start = jiffies; } while (0) +#endif + #endif /* __COMPAT_NETDEVICE_H__ */ --- a/vmnet/netif.c +++ b/vmnet/netif.c @@ -149,7 +149,7 @@ VNetNetIf_Create(char *devName, // IN: memcpy(deviceName, devName, sizeof deviceName); NULL_TERMINATE_STRING(deviceName); -#if LINUX_VERSION_CODE >= KERNEL_VERSION(3, 18, 0) || defined(NET_NAME_USER) +#if LINUX_VERSION_CODE >= KERNEL_VERSION(3, 18, 0) dev = alloc_netdev(sizeof *netIf, deviceName, NET_NAME_USER, VNetNetIfSetup); #else dev = alloc_netdev(sizeof *netIf, deviceName, VNetNetIfSetup); @@ -465,7 +465,7 @@ VNetNetifStartXmit(struct sk_buff *sk VNetSend(&netIf->port.jack, skb); netIf->stats.tx_packets++; - dev->trans_start = jiffies; + compat_netif_trans_update(dev); return 0; } --- a/vmnet/procfs.c +++ a/vmnet/procfs.c @@ -137,6 +137,7 @@ VNetProcShow(struct seq_file *p, // IN: } +#if LINUX_VERSION_CODE < KERNEL_VERSION(4, 18, 0) /* *---------------------------------------------------------------------- * @@ -168,6 +169,7 @@ static struct file_operations fops = { .release = single_release, }; #endif +#endif /* @@ -203,7 +205,12 @@ VNetProcMakeEntryInt(VNetProcEntry *pa } else { ent->data = data; ent->fn = fn; +#if LINUX_VERSION_CODE >= KERNEL_VERSION(4, 18, 0) + ent->pde = proc_create_single_data(name, mode, parent->pde, + VNetProcShow, ent); +#else ent->pde = proc_create_data(name, mode, parent->pde, &fops, ent); +#endif } if (ent->pde != NULL) { *ret = ent; --- a/vmnet/userif.c +++ b/vmnet/userif.c @@ -36,6 +36,9 @@ #include #include #include +#if LINUX_VERSION_CODE >= KERNEL_VERSION(4, 11, 0) +#include // For without version dependency +#endif #include #include @@ -81,11 +84,11 @@ static int VNetUserIfSetUplinkState(VNe extern unsigned int vnet_max_qlen; #if COMPAT_LINUX_VERSION_CHECK_LT(3, 2, 0) -# define compat_kmap(page) kmap(page) -# define compat_kunmap(page) kunmap(page) -#else -# define compat_kmap(page) kmap((page).p) -# define compat_kunmap(page) kunmap((page).p) +# define skb_frag_page(frag) (frag)->page +# define skb_frag_size(frag) (frag)->size +#endif +#if COMPAT_LINUX_VERSION_CHECK_LT(5, 4, 0) +# define skb_frag_off(frag) (frag)->page_offset #endif /* @@ -112,10 +115,7 @@ UserifLockPage(VA addr) // IN struct page *page = NULL; int retval; - down_read(¤t->mm->mmap_sem); - retval = get_user_pages(current, current->mm, addr, - 1, 1, 0, &page, NULL); - up_read(¤t->mm->mmap_sem); + retval = get_user_pages_fast(addr, 1, FOLL_WRITE, &page); if (retval != 1) { return NULL; @@ -143,16 +143,21 @@ UserifLockPage(VA addr) // IN */ static INLINE int -VNetUserIfMapPtr(VA uAddr, // IN: pointer to user memory +VNetUserIfMapPtr(VA64 uAddr, // IN: pointer to user memory size_t size, // IN: size of data struct page **p, // OUT: locked page void **ptr) // OUT: kernel mapped pointer { - if (!access_ok(VERIFY_WRITE, (void *)uAddr, size) || - (((uAddr + size - 1) & ~(PAGE_SIZE - 1)) != - (uAddr & ~(PAGE_SIZE - 1)))) { + uint8 v; + + /* Check area does not straddle two pages. */ + if ((uAddr & (PAGE_SIZE - 1)) + size > PAGE_SIZE) { return -EINVAL; } + /* Check if it is user's area. UserifLockPage() checks writability. */ + if (copy_from_user(&v, (void *)(unsigned long)uAddr, sizeof v) != 0) { + return -EFAULT; + } *p = UserifLockPage(uAddr); if (*p == NULL) { @@ -164,7 +169,7 @@ VNetUserIfMapPtr(VA uAddr, // IN: } static INLINE int -VNetUserIfMapUint32Ptr(VA uAddr, // IN: pointer to user memory +VNetUserIfMapUint32Ptr(VA64 uAddr, // IN: pointer to user memory struct page **p, // OUT: locked page uint32 **ptr) // OUT: kernel mapped pointer { @@ -209,7 +214,7 @@ VNetUserIfSetupNotify(VNetUserIF *userIf return -EBUSY; } - if ((retval = VNetUserIfMapUint32Ptr((VA)vn->pollPtr, &pollPage, + if ((retval = VNetUserIfMapUint32Ptr(vn->pollPtr, &pollPage, &pollPtr)) < 0) { return retval; } @@ -227,7 +232,7 @@ VNetUserIfSetupNotify(VNetUserIF *userIf goto error_free; } - if ((retval = VNetUserIfMapUint32Ptr((VA)vn->recvClusterPtr, + if ((retval = VNetUserIfMapUint32Ptr(vn->recvClusterPtr, &recvClusterPage, &recvClusterCount)) < 0) { goto error_free; @@ -576,7 +581,12 @@ VNetCsumCopyDatagram(const struct sk_buf return -EINVAL; } +#if COMPAT_LINUX_VERSION_CHECK_LT(5, 10, 0) csum = csum_and_copy_to_user(skb->data + offset, curr, len, 0, &err); +#else + csum = csum_and_copy_to_user(skb->data + offset, curr, len); + err = (csum == 0) ? -EFAULT : 0; +#endif if (err) { return err; } @@ -585,20 +595,26 @@ VNetCsumCopyDatagram(const struct sk_buf for (frag = skb_shinfo(skb)->frags; frag != skb_shinfo(skb)->frags + skb_shinfo(skb)->nr_frags; frag++) { - if (frag->size > 0) { + if (skb_frag_size(frag) > 0) { unsigned int tmpCsum; const void *vaddr; - vaddr = compat_kmap(frag->page); - tmpCsum = csum_and_copy_to_user(vaddr + frag->page_offset, - curr, frag->size, 0, &err); - compat_kunmap(frag->page); + 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 + kunmap(skb_frag_page(frag)); if (err) { return err; } csum = csum_block_add(csum, tmpCsum, curr - buf); - curr += frag->size; + curr += skb_frag_size(frag); } } --- a/vmnet/vmnetInt.h +++ b/vmnet/vmnetInt.h @@ -77,7 +77,7 @@ extern struct proto vmnet_proto; -#if LINUX_VERSION_CODE >= KERNEL_VERSION(4, 2, 0) +#if LINUX_VERSION_CODE >= KERNEL_VERSION(4, 2, 0) || defined(sk_net_refcnt) # define compat_sk_alloc(_bri, _pri) sk_alloc(&init_net, \ PF_NETLINK, _pri, &vmnet_proto, 1) #elif defined(VMW_NETDEV_HAS_NET)