From 2cef39d7d18db1d2c6bc7d9e0c49b996387198a4 Mon Sep 17 00:00:00 2001 From: "Anand H. Krishnan" Date: Thu, 24 Mar 2016 21:06:04 +0530 Subject: [PATCH] Fix memory corruption at the time of unloading Every alloc and free of memory in vRouter is accounted for by the memory statistics subsystem of vRouter. While unloading the module, we are freeing malloc statistics memory before packet drop statstics memory is freed. While we do update the memory statistics only if the memory statistics block pointer is not null, we do not seem to be zeroing the pointer that holds the address of the memory block post release. Hence, reverse the order of release and NULL-ify the memory statistics pointer. Also, unregister the net device notifier before going ahead and freeing the memory that the vhost driver keeps. If the notifier is not unregistered first, it can potentially access freed memory that vhost driver maintains. Change-Id: I79c4cdec4f0501e61abf38698e44e461a90c370b Closes-BUG: #1561589 --- dp-core/vr_stats.c | 3 ++- linux/vhost_dev.c | 6 ++++-- linux/vr_host_interface.c | 2 +- 3 files changed, 7 insertions(+), 4 deletions(-) diff --git a/dp-core/vr_stats.c b/dp-core/vr_stats.c index 07f7e3a39..f0ced3845 100644 --- a/dp-core/vr_stats.c +++ b/dp-core/vr_stats.c @@ -331,6 +331,7 @@ vr_malloc_stats_exit(struct vrouter *router) } vr_free(router->vr_malloc_stats, VR_MALLOC_OBJECT); + router->vr_malloc_stats = NULL; return; } @@ -451,8 +452,8 @@ vr_stats_exit(struct vrouter *router, bool soft_reset) return; } - vr_malloc_stats_exit(router); vr_pkt_drop_stats_exit(router); + vr_malloc_stats_exit(router); return; } diff --git a/linux/vhost_dev.c b/linux/vhost_dev.c index e473cc96c..686cf1b0d 100644 --- a/linux/vhost_dev.c +++ b/linux/vhost_dev.c @@ -494,7 +494,7 @@ vhost_dellink(struct net_device *dev, struct list_head *head) vp = netdev_priv(dev); if (vp) { - if (vp->vp_db_index >= 0) + if (vhost_priv_db && vp->vp_db_index >= 0) vhost_priv_db[vp->vp_db_index] = NULL; vp->vp_db_index = -1; @@ -566,8 +566,10 @@ void vhost_exit(void) { vhost_netlink_exit(); - if (vhost_priv_db) + if (vhost_priv_db) { kfree(vhost_priv_db); + vhost_priv_db = NULL; + } return; } diff --git a/linux/vr_host_interface.c b/linux/vr_host_interface.c index 149f89f5d..f8cf857d9 100644 --- a/linux/vr_host_interface.c +++ b/linux/vr_host_interface.c @@ -2334,8 +2334,8 @@ vr_host_vif_init(struct vrouter *router) void vr_host_interface_exit(void) { - vhost_exit(); unregister_netdevice_notifier(&host_if_nb); + vhost_exit(); linux_pkt_dev_free(); #if (LINUX_VERSION_CODE < KERNEL_VERSION(2,6,39))