WARNING - OLD ARCHIVES

This is an archived copy of the Xen.org mailing list, which we have preserved to ensure that existing links to archives are not broken. The live archive, which contains the latest emails, can be found at http://lists.xen.org/
   
 
 
Xen 
 
Home Products Support Community News
 
   
 

xen-devel

[Xen-devel] [PATCH 2/3] xenoprof fixes: active_domains races

To: xen-devel@xxxxxxxxxxxxxxxxxxx
Subject: [Xen-devel] [PATCH 2/3] xenoprof fixes: active_domains races
From: Markus Armbruster <armbru@xxxxxxxxxx>
Date: Mon, 15 May 2006 18:32:40 +0200
Delivery-date: Mon, 15 May 2006 09:33:11 -0700
Envelope-to: www-data@xxxxxxxxxxxxxxxxxx
In-reply-to: <87hd3r2qst.fsf@xxxxxxxxxxxxxxxxx> (Markus Armbruster's message of "Mon, 15 May 2006 18:31:14 +0200")
List-help: <mailto:xen-devel-request@lists.xensource.com?subject=help>
List-id: Xen developer discussion <xen-devel.lists.xensource.com>
List-post: <mailto:xen-devel@lists.xensource.com>
List-subscribe: <http://lists.xensource.com/cgi-bin/mailman/listinfo/xen-devel>, <mailto:xen-devel-request@lists.xensource.com?subject=subscribe>
List-unsubscribe: <http://lists.xensource.com/cgi-bin/mailman/listinfo/xen-devel>, <mailto:xen-devel-request@lists.xensource.com?subject=unsubscribe>
References: <87hd3r2qst.fsf@xxxxxxxxxxxxxxxxx>
Sender: xen-devel-bounces@xxxxxxxxxxxxxxxxxxx
User-agent: Gnus/5.1008 (Gnus v5.10.8) Emacs/21.4 (gnu/linux)
The active_domains code has race conditions:

* oprofile_set_active() calls set_active() method without holding
  start_sem.  This is clearly wrong, as xenoprof_set_active() makes
  several hypercalls.  oprofile_start(), for instance, could run in
  the middle of xenoprof_set_active().

* adomain_write(), adomain_read() and xenoprof_set_active() access
  global active_domains[] and adomains without synchronization.  I
  went for a simple, obvious fix and created another mutex.  Instead,
  one could move the shared data into oprof.c and protect it with
  start_sem, but that's more invasive.


diff -rup linux-2.6.16.13-xen.patched-1/drivers/oprofile/oprof.c 
linux-2.6.16.13-xen.patched-2/drivers/oprofile/oprof.c
--- linux-2.6.16.13-xen.patched-1/drivers/oprofile/oprof.c      2006-05-15 
10:28:11.000000000 +0200
+++ linux-2.6.16.13-xen.patched-2/drivers/oprofile/oprof.c      2006-05-15 
10:31:11.000000000 +0200
@@ -42,10 +42,15 @@ extern int active_domains[MAX_OPROF_DOMA
 
 int oprofile_set_active(void)
 {
-       if (oprofile_ops.set_active)
-               return oprofile_ops.set_active(active_domains, adomains);
+       int err;
+
+       if (!oprofile_ops.set_active)
+               return -EINVAL;
 
-       return -EINVAL;
+       down(&start_sem);
+       err = oprofile_ops.set_active(active_domains, adomains);
+       up(&start_sem);
+       return err;
 }
 
 int oprofile_setup(void)
diff -rup linux-2.6.16.13-xen.patched-1/drivers/oprofile/oprofile_files.c 
linux-2.6.16.13-xen.patched-2/drivers/oprofile/oprofile_files.c
--- linux-2.6.16.13-xen.patched-1/drivers/oprofile/oprofile_files.c     
2006-05-15 10:28:11.000000000 +0200
+++ linux-2.6.16.13-xen.patched-2/drivers/oprofile/oprofile_files.c     
2006-05-15 10:31:11.000000000 +0200
@@ -128,6 +128,7 @@ static struct file_operations dump_fops 
 
 unsigned int adomains = 0;
 long active_domains[MAX_OPROF_DOMAINS];
+static DECLARE_MUTEX(adom_sem);
 
 static ssize_t adomain_write(struct file * file, char const __user * buf, 
                             size_t count, loff_t * offset)
@@ -137,6 +138,7 @@ static ssize_t adomain_write(struct file
        char * endp = tmpbuf;
        int i;
        unsigned long val;
+       ssize_t retval = count;
        
        if (*offset)
                return -EINVAL; 
@@ -150,6 +152,8 @@ static ssize_t adomain_write(struct file
        if (copy_from_user(tmpbuf, buf, count))
                return -EFAULT;
        
+       down(&adom_sem);
+
        for (i = 0; i < MAX_OPROF_DOMAINS; i++)
                active_domains[i] = -1;
        adomains = 0;
@@ -165,9 +169,12 @@ static ssize_t adomain_write(struct file
                        break;
                startp = endp;
        }
+
        if (oprofile_set_active())
-               return -EINVAL; 
-       return count;
+               retval = -EINVAL;
+
+       up(&adom_sem);
+       return retval;
 }
 
 static ssize_t adomain_read(struct file * file, char __user * buf, 
@@ -176,11 +183,17 @@ static ssize_t adomain_read(struct file 
        char tmpbuf[TMPBUFSIZE];
        size_t len = 0;
        int i;
+
+       down(&adom_sem);
+
        /* This is all screwed up if we run out of space */
        for (i = 0; i < adomains; i++) 
                len += snprintf(tmpbuf + len, TMPBUFSIZE - len, 
                                "%u ", (unsigned int)active_domains[i]);
        len += snprintf(tmpbuf + len, TMPBUFSIZE - len, "\n");
+
+       up(&adom_sem);
+
        return simple_read_from_buffer((void __user *)buf, count, 
                                       offset, tmpbuf, len);
 }

_______________________________________________
Xen-devel mailing list
Xen-devel@xxxxxxxxxxxxxxxxxxx
http://lists.xensource.com/xen-devel