]> git.ipfire.org Git - people/teissler/ipfire-2.x.git/blob - src/patches/suse-2.6.27.31/patches.fixes/dlm-fix-plock-use-after-free.patch
Merge branch 'master' of git://git.ipfire.org/ipfire-2.x
[people/teissler/ipfire-2.x.git] / src / patches / suse-2.6.27.31 / patches.fixes / dlm-fix-plock-use-after-free.patch
1 From c78a87d0a1fc885dfdbe21fd5e07787691dfb068 Mon Sep 17 00:00:00 2001
2 From: David Teigland <teigland@redhat.com>
3 Date: Thu, 18 Jun 2009 13:20:24 -0500
4 Subject: [PATCH] dlm: fix plock use-after-free
5
6 Fix a regression from the original addition of nfs lock support
7 586759f03e2e9031ac5589912a51a909ed53c30a. When a synchronous
8 (non-nfs) plock completes, the waiting thread will wake up and
9 free the op struct. This races with the user thread in
10 dev_write() which goes on to read the op's callback field to
11 check if the lock is async and needs a callback. This check
12 can happen on the freed op. The fix is to note the callback
13 value before the op can be freed.
14
15 Signed-off-by: David Teigland <teigland@redhat.com>
16 Signed-off-by: Coly Li <coly.li@suse.de>
17 ---
18 fs/dlm/plock.c | 17 ++++++++++-------
19 1 files changed, 10 insertions(+), 7 deletions(-)
20
21 diff --git a/fs/dlm/plock.c b/fs/dlm/plock.c
22 index 894a32d..16f682e 100644
23 --- a/fs/dlm/plock.c
24 +++ b/fs/dlm/plock.c
25 @@ -353,7 +353,7 @@ static ssize_t dev_write(struct file *file, const char __user *u, size_t count,
26 {
27 struct dlm_plock_info info;
28 struct plock_op *op;
29 - int found = 0;
30 + int found = 0, do_callback = 0;
31
32 if (count != sizeof(info))
33 return -EINVAL;
34 @@ -366,21 +366,24 @@ static ssize_t dev_write(struct file *file, const char __user *u, size_t count,
35
36 spin_lock(&ops_lock);
37 list_for_each_entry(op, &recv_list, list) {
38 - if (op->info.fsid == info.fsid && op->info.number == info.number &&
39 + if (op->info.fsid == info.fsid &&
40 + op->info.number == info.number &&
41 op->info.owner == info.owner) {
42 + struct plock_xop *xop = (struct plock_xop *)op;
43 list_del_init(&op->list);
44 - found = 1;
45 - op->done = 1;
46 memcpy(&op->info, &info, sizeof(info));
47 + if (xop->callback)
48 + do_callback = 1;
49 + else
50 + op->done = 1;
51 + found = 1;
52 break;
53 }
54 }
55 spin_unlock(&ops_lock);
56
57 if (found) {
58 - struct plock_xop *xop;
59 - xop = (struct plock_xop *)op;
60 - if (xop->callback)
61 + if (do_callback)
62 dlm_plock_callback(op);
63 else
64 wake_up(&recv_wq);
65 --
66 1.6.0.2
67