]> git.ipfire.org Git - ipfire-2.x.git/blobdiff - src/patches/suse-2.6.27.31/patches.fixes/dlm-fix-plock-use-after-free.patch
Reenabled linux-xen, added patches for Xen Kernel Version 2.6.27.31,
[ipfire-2.x.git] / src / patches / suse-2.6.27.31 / patches.fixes / dlm-fix-plock-use-after-free.patch
diff --git a/src/patches/suse-2.6.27.31/patches.fixes/dlm-fix-plock-use-after-free.patch b/src/patches/suse-2.6.27.31/patches.fixes/dlm-fix-plock-use-after-free.patch
new file mode 100644 (file)
index 0000000..6cc707a
--- /dev/null
@@ -0,0 +1,67 @@
+From c78a87d0a1fc885dfdbe21fd5e07787691dfb068 Mon Sep 17 00:00:00 2001
+From: David Teigland <teigland@redhat.com>
+Date: Thu, 18 Jun 2009 13:20:24 -0500
+Subject: [PATCH] dlm: fix plock use-after-free
+
+Fix a regression from the original addition of nfs lock support
+586759f03e2e9031ac5589912a51a909ed53c30a.  When a synchronous
+(non-nfs) plock completes, the waiting thread will wake up and
+free the op struct.  This races with the user thread in
+dev_write() which goes on to read the op's callback field to
+check if the lock is async and needs a callback.  This check
+can happen on the freed op.  The fix is to note the callback
+value before the op can be freed.
+
+Signed-off-by: David Teigland <teigland@redhat.com>
+Signed-off-by: Coly Li <coly.li@suse.de>
+---
+ fs/dlm/plock.c |   17 ++++++++++-------
+ 1 files changed, 10 insertions(+), 7 deletions(-)
+
+diff --git a/fs/dlm/plock.c b/fs/dlm/plock.c
+index 894a32d..16f682e 100644
+--- a/fs/dlm/plock.c
++++ b/fs/dlm/plock.c
+@@ -353,7 +353,7 @@ static ssize_t dev_write(struct file *file, const char __user *u, size_t count,
+ {
+       struct dlm_plock_info info;
+       struct plock_op *op;
+-      int found = 0;
++      int found = 0, do_callback = 0;
+       if (count != sizeof(info))
+               return -EINVAL;
+@@ -366,21 +366,24 @@ static ssize_t dev_write(struct file *file, const char __user *u, size_t count,
+       spin_lock(&ops_lock);
+       list_for_each_entry(op, &recv_list, list) {
+-              if (op->info.fsid == info.fsid && op->info.number == info.number &&
++              if (op->info.fsid == info.fsid &&
++                  op->info.number == info.number &&
+                   op->info.owner == info.owner) {
++                      struct plock_xop *xop = (struct plock_xop *)op;
+                       list_del_init(&op->list);
+-                      found = 1;
+-                      op->done = 1;
+                       memcpy(&op->info, &info, sizeof(info));
++                      if (xop->callback)
++                              do_callback = 1;
++                      else
++                              op->done = 1;
++                      found = 1;
+                       break;
+               }
+       }
+       spin_unlock(&ops_lock);
+       if (found) {
+-              struct plock_xop *xop;
+-              xop = (struct plock_xop *)op;
+-              if (xop->callback)
++              if (do_callback)
+                       dlm_plock_callback(op);
+               else
+                       wake_up(&recv_wq);
+-- 
+1.6.0.2
+