From: Don Dutile <ddutile@redhat.com> Date: Wed, 5 Nov 2008 10:42:15 -0500 Subject: [xen] uninitialized watch structure can lead to crashes Message-id: 4911BED7.2060309@redhat.com O-Subject: [RHEL5.3 PATCH] uninitialized xen watch structure can lead to kernel crashes, xen guest installation panics Bugzilla: 465849 RH-Acked-by: Chris Lalancette <clalance@redhat.com> RH-Acked-by: Bill Burns <bburns@redhat.com> RH-Acked-by: Rik van Riel <riel@redhat.com> BZ 435273 & BZ 465849 There are a couple of places in the -xen kernel where a struct xenbus_watch is allocated but not all fields are initialized. This can result in ->flags spuriously containing the XBWF_new_thread flag. A crash can result due to a race between this unexpected thread and deregistration and freeing of the watch structure. This problem is present in the /proc/xen/xenbus code and in pcifront. BZ 435273 was reported by XenSource but with no deterministic way to reproduce, albeit the solutions were simple (kmalloc() -> kzalloc()) & the errors obvious. BZ 465849 provided a reproducible scenario -- installing over 100 guests (now that's a patient admin!) -- and the reporter was able to test a kernel-xen with the patch to prove it resolved that issue (although it showed another LVM issue that requires a new BZ). The brew build which was tested by the customer was/is: https://brewweb.devel.redhat.com/taskinfo?taskID=1542520 -- an x86_64-only build, but the only change is kmalloc() -> kzalloc() ... fairly architecture indep. change. -- the customer only (effectively) tested the xenbus-dev fix; the customer didn't use the pci-passthrough functionality which would exercise the kzalloc(), but it's fairly obvious that a zero'd pci_dev structure is better than an uninit'd structure I combined the 2 upstream patches into one for the rhel5 patch below. The upstream patches are: linux-2.6.18-xen, cset 440: http://xenbits.xensource.com/linux-2.6.18-xen.hg?rev/43de9d7c3c63 -- this is the one that was built into a -120 kernel & tested by the reporter linux-2.6.18-xen, cset 442: http://xenbits.xensource.com/staging/linux-2.6.18-xen.hg?rev/7c04748ed275 -- this is the second patch I combined into the single patch below. Please review & ACK. - Don NOTE: This patch should probably be put into 5.2.z; can the appropriate/capable flag setters set the z-flag for one or both BZ's ? (I don't have that privilege... thanks.) ps -- the first upstream patch, cset 440, needs to be backported to 4.8 (& probably 4.7.z). diff --git a/drivers/xen/pcifront/xenbus.c b/drivers/xen/pcifront/xenbus.c index c5fca76..6231c81 100644 --- a/drivers/xen/pcifront/xenbus.c +++ b/drivers/xen/pcifront/xenbus.c @@ -17,7 +17,7 @@ static struct pcifront_device *alloc_pdev(struct xenbus_device *xdev) { struct pcifront_device *pdev; - pdev = kmalloc(sizeof(struct pcifront_device), GFP_KERNEL); + pdev = kzalloc(sizeof(struct pcifront_device), GFP_KERNEL); if (pdev == NULL) goto out; diff --git a/drivers/xen/xenbus/xenbus_dev.c b/drivers/xen/xenbus/xenbus_dev.c index b1b1548..c630557 100644 --- a/drivers/xen/xenbus/xenbus_dev.c +++ b/drivers/xen/xenbus/xenbus_dev.c @@ -238,7 +238,7 @@ static ssize_t xenbus_dev_write(struct file *filp, static const char * XS_WATCH_RESP = "OK"; struct xsd_sockmsg hdr; - watch = kmalloc(sizeof(*watch), GFP_KERNEL); + watch = kzalloc(sizeof(*watch), GFP_KERNEL); watch->watch.node = kmalloc(strlen(path)+1, GFP_KERNEL); strcpy((char *)watch->watch.node, path);