/[linux-patches]/genpatches-2.6/trunk/2.6.14/1413_15.2_mqueue-double-decrement.patch
Gentoo

Contents of /genpatches-2.6/trunk/2.6.14/1413_15.2_mqueue-double-decrement.patch

Parent Directory Parent Directory | Revision Log Revision Log


Revision 328 - (show annotations) (download) (as text)
Tue Mar 14 13:34:17 2006 UTC (14 years, 8 months ago) by johnm
File MIME type: text/x-diff
File size: 3946 byte(s)
2.6.14-11, rebase against local tree
1 From nobody Mon Sep 17 00:00:00 2001
2 Subject: [PATCH] Fix double decrement of mqueue_mnt->mnt_count in sys_mq_open (CVE-2005-3356)
3 From: Alexander Viro <aviro@redhat.com>
4 Date: 1137270595 -0500
5
6 Fixed the refcounting on failure exits in sys_mq_open() and
7 cleaned the logics up. Rules are actually pretty simple - dentry_open()
8 expects vfsmount and dentry to be pinned down and it either transfers
9 them into created struct file or drops them. Old code had been very
10 confused in that area - if dentry_open() had failed either in do_open()
11 or do_create(), we ended up dentry and mqueue_mnt dropped twice, once
12 by dentry_open() cleanup and then by sys_mq_open().
13
14 Fix consists of making the rules for do_create() and do_open()
15 same as for dentry_open() and updating the sys_mq_open() accordingly;
16 that actually leads to more straightforward code and less work on
17 normal path.
18
19 Signed-off-by: Al Viro <aviro@redhat.com>
20 Signed-off-by: Linus Torvalds <torvalds@osdl.org>
21 Signed-off-by: Chris Wright <chrisw@sous-sol.org>
22 ---
23 ipc/mqueue.c | 59 +++++++++++++++++++++++++++++++++--------------------------
24 1 files changed, 33 insertions(+), 26 deletions(-)
25
26 --- linux-2.6.15.1.orig/ipc/mqueue.c
27 +++ linux-2.6.15.1/ipc/mqueue.c
28 @@ -598,15 +598,16 @@ static int mq_attr_ok(struct mq_attr *at
29 static struct file *do_create(struct dentry *dir, struct dentry *dentry,
30 int oflag, mode_t mode, struct mq_attr __user *u_attr)
31 {
32 - struct file *filp;
33 struct mq_attr attr;
34 int ret;
35
36 - if (u_attr != NULL) {
37 + if (u_attr) {
38 + ret = -EFAULT;
39 if (copy_from_user(&attr, u_attr, sizeof(attr)))
40 - return ERR_PTR(-EFAULT);
41 + goto out;
42 + ret = -EINVAL;
43 if (!mq_attr_ok(&attr))
44 - return ERR_PTR(-EINVAL);
45 + goto out;
46 /* store for use during create */
47 dentry->d_fsdata = &attr;
48 }
49 @@ -615,13 +616,14 @@ static struct file *do_create(struct den
50 ret = vfs_create(dir->d_inode, dentry, mode, NULL);
51 dentry->d_fsdata = NULL;
52 if (ret)
53 - return ERR_PTR(ret);
54 + goto out;
55
56 - filp = dentry_open(dentry, mqueue_mnt, oflag);
57 - if (!IS_ERR(filp))
58 - dget(dentry);
59 + return dentry_open(dentry, mqueue_mnt, oflag);
60
61 - return filp;
62 +out:
63 + dput(dentry);
64 + mntput(mqueue_mnt);
65 + return ERR_PTR(ret);
66 }
67
68 /* Opens existing queue */
69 @@ -629,20 +631,20 @@ static struct file *do_open(struct dentr
70 {
71 static int oflag2acc[O_ACCMODE] = { MAY_READ, MAY_WRITE,
72 MAY_READ | MAY_WRITE };
73 - struct file *filp;
74
75 - if ((oflag & O_ACCMODE) == (O_RDWR | O_WRONLY))
76 + if ((oflag & O_ACCMODE) == (O_RDWR | O_WRONLY)) {
77 + dput(dentry);
78 + mntput(mqueue_mnt);
79 return ERR_PTR(-EINVAL);
80 + }
81
82 - if (permission(dentry->d_inode, oflag2acc[oflag & O_ACCMODE], NULL))
83 + if (permission(dentry->d_inode, oflag2acc[oflag & O_ACCMODE], NULL)) {
84 + dput(dentry);
85 + mntput(mqueue_mnt);
86 return ERR_PTR(-EACCES);
87 + }
88
89 - filp = dentry_open(dentry, mqueue_mnt, oflag);
90 -
91 - if (!IS_ERR(filp))
92 - dget(dentry);
93 -
94 - return filp;
95 + return dentry_open(dentry, mqueue_mnt, oflag);
96 }
97
98 asmlinkage long sys_mq_open(const char __user *u_name, int oflag, mode_t mode,
99 @@ -670,17 +672,20 @@ asmlinkage long sys_mq_open(const char _
100
101 if (oflag & O_CREAT) {
102 if (dentry->d_inode) { /* entry already exists */
103 - filp = (oflag & O_EXCL) ? ERR_PTR(-EEXIST) :
104 - do_open(dentry, oflag);
105 + error = -EEXIST;
106 + if (oflag & O_EXCL)
107 + goto out;
108 + filp = do_open(dentry, oflag);
109 } else {
110 filp = do_create(mqueue_mnt->mnt_root, dentry,
111 oflag, mode, u_attr);
112 }
113 - } else
114 - filp = (dentry->d_inode) ? do_open(dentry, oflag) :
115 - ERR_PTR(-ENOENT);
116 -
117 - dput(dentry);
118 + } else {
119 + error = -ENOENT;
120 + if (!dentry->d_inode)
121 + goto out;
122 + filp = do_open(dentry, oflag);
123 + }
124
125 if (IS_ERR(filp)) {
126 error = PTR_ERR(filp);
127 @@ -691,8 +696,10 @@ asmlinkage long sys_mq_open(const char _
128 fd_install(fd, filp);
129 goto out_upsem;
130
131 -out_putfd:
132 +out:
133 + dput(dentry);
134 mntput(mqueue_mnt);
135 +out_putfd:
136 put_unused_fd(fd);
137 out_err:
138 fd = error;

  ViewVC Help
Powered by ViewVC 1.1.20