aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorAl Viro <viro@zeniv.linux.org.uk>2008-02-23 06:46:49 -0500
committerAl Viro <viro@zeniv.linux.org.uk>2008-05-01 13:08:50 -0400
commit2030a42cecd4dd1985a2ab03e25f3cd6106a5ca8 (patch)
tree7cb4710c3f7a4e034a20890f0df99bc42f9bbcee
parent9f3acc3140444a900ab280de942291959f0f615d (diff)
[PATCH] sanitize anon_inode_getfd()
a) none of the callers even looks at inode or file returned by anon_inode_getfd() b) any caller that would try to look at those would be racy, since by the time it returns we might have raced with close() from another thread and that file would be pining for fjords. Signed-off-by: Al Viro <viro@zeniv.linux.org.uk>
-rw-r--r--fs/anon_inodes.c13
-rw-r--r--fs/eventfd.c15
-rw-r--r--fs/eventpoll.c23
-rw-r--r--fs/signalfd.c17
-rw-r--r--fs/timerfd.c11
-rw-r--r--include/linux/anon_inodes.h3
-rw-r--r--virt/kvm/kvm_main.c21
7 files changed, 29 insertions, 74 deletions
diff --git a/fs/anon_inodes.c b/fs/anon_inodes.c
index f42be069e085..977ef208c051 100644
--- a/fs/anon_inodes.c
+++ b/fs/anon_inodes.c
@@ -57,9 +57,6 @@ static struct dentry_operations anon_inodefs_dentry_operations = {
57 * anonymous inode, and a dentry that describe the "class" 57 * anonymous inode, and a dentry that describe the "class"
58 * of the file 58 * of the file
59 * 59 *
60 * @pfd: [out] pointer to the file descriptor
61 * @dpinode: [out] pointer to the inode
62 * @pfile: [out] pointer to the file struct
63 * @name: [in] name of the "class" of the new file 60 * @name: [in] name of the "class" of the new file
64 * @fops [in] file operations for the new file 61 * @fops [in] file operations for the new file
65 * @priv [in] private data for the new file (will be file's private_data) 62 * @priv [in] private data for the new file (will be file's private_data)
@@ -68,10 +65,9 @@ static struct dentry_operations anon_inodefs_dentry_operations = {
68 * that do not need to have a full-fledged inode in order to operate correctly. 65 * that do not need to have a full-fledged inode in order to operate correctly.
69 * All the files created with anon_inode_getfd() will share a single inode, 66 * All the files created with anon_inode_getfd() will share a single inode,
70 * hence saving memory and avoiding code duplication for the file/inode/dentry 67 * hence saving memory and avoiding code duplication for the file/inode/dentry
71 * setup. 68 * setup. Returns new descriptor or -error.
72 */ 69 */
73int anon_inode_getfd(int *pfd, struct inode **pinode, struct file **pfile, 70int anon_inode_getfd(const char *name, const struct file_operations *fops,
74 const char *name, const struct file_operations *fops,
75 void *priv) 71 void *priv)
76{ 72{
77 struct qstr this; 73 struct qstr this;
@@ -125,10 +121,7 @@ int anon_inode_getfd(int *pfd, struct inode **pinode, struct file **pfile,
125 121
126 fd_install(fd, file); 122 fd_install(fd, file);
127 123
128 *pfd = fd; 124 return fd;
129 *pinode = anon_inode_inode;
130 *pfile = file;
131 return 0;
132 125
133err_dput: 126err_dput:
134 dput(dentry); 127 dput(dentry);
diff --git a/fs/eventfd.c b/fs/eventfd.c
index a9f130cd50ac..343942deeec1 100644
--- a/fs/eventfd.c
+++ b/fs/eventfd.c
@@ -200,10 +200,8 @@ struct file *eventfd_fget(int fd)
200 200
201asmlinkage long sys_eventfd(unsigned int count) 201asmlinkage long sys_eventfd(unsigned int count)
202{ 202{
203 int error, fd; 203 int fd;
204 struct eventfd_ctx *ctx; 204 struct eventfd_ctx *ctx;
205 struct file *file;
206 struct inode *inode;
207 205
208 ctx = kmalloc(sizeof(*ctx), GFP_KERNEL); 206 ctx = kmalloc(sizeof(*ctx), GFP_KERNEL);
209 if (!ctx) 207 if (!ctx)
@@ -216,12 +214,9 @@ asmlinkage long sys_eventfd(unsigned int count)
216 * When we call this, the initialization must be complete, since 214 * When we call this, the initialization must be complete, since
217 * anon_inode_getfd() will install the fd. 215 * anon_inode_getfd() will install the fd.
218 */ 216 */
219 error = anon_inode_getfd(&fd, &inode, &file, "[eventfd]", 217 fd = anon_inode_getfd("[eventfd]", &eventfd_fops, ctx);
220 &eventfd_fops, ctx); 218 if (fd < 0)
221 if (!error) 219 kfree(ctx);
222 return fd; 220 return fd;
223
224 kfree(ctx);
225 return error;
226} 221}
227 222
diff --git a/fs/eventpoll.c b/fs/eventpoll.c
index 221086fef174..990c01d2d66b 100644
--- a/fs/eventpoll.c
+++ b/fs/eventpoll.c
@@ -1050,8 +1050,6 @@ asmlinkage long sys_epoll_create(int size)
1050{ 1050{
1051 int error, fd = -1; 1051 int error, fd = -1;
1052 struct eventpoll *ep; 1052 struct eventpoll *ep;
1053 struct inode *inode;
1054 struct file *file;
1055 1053
1056 DNPRINTK(3, (KERN_INFO "[%p] eventpoll: sys_epoll_create(%d)\n", 1054 DNPRINTK(3, (KERN_INFO "[%p] eventpoll: sys_epoll_create(%d)\n",
1057 current, size)); 1055 current, size));
@@ -1061,29 +1059,24 @@ asmlinkage long sys_epoll_create(int size)
1061 * structure ( "struct eventpoll" ). 1059 * structure ( "struct eventpoll" ).
1062 */ 1060 */
1063 error = -EINVAL; 1061 error = -EINVAL;
1064 if (size <= 0 || (error = ep_alloc(&ep)) != 0) 1062 if (size <= 0 || (error = ep_alloc(&ep)) < 0) {
1063 fd = error;
1065 goto error_return; 1064 goto error_return;
1065 }
1066 1066
1067 /* 1067 /*
1068 * Creates all the items needed to setup an eventpoll file. That is, 1068 * Creates all the items needed to setup an eventpoll file. That is,
1069 * a file structure, and inode and a free file descriptor. 1069 * a file structure and a free file descriptor.
1070 */ 1070 */
1071 error = anon_inode_getfd(&fd, &inode, &file, "[eventpoll]", 1071 fd = anon_inode_getfd("[eventpoll]", &eventpoll_fops, ep);
1072 &eventpoll_fops, ep); 1072 if (fd < 0)
1073 if (error) 1073 ep_free(ep);
1074 goto error_free;
1075 1074
1075error_return:
1076 DNPRINTK(3, (KERN_INFO "[%p] eventpoll: sys_epoll_create(%d) = %d\n", 1076 DNPRINTK(3, (KERN_INFO "[%p] eventpoll: sys_epoll_create(%d) = %d\n",
1077 current, size, fd)); 1077 current, size, fd));
1078 1078
1079 return fd; 1079 return fd;
1080
1081error_free:
1082 ep_free(ep);
1083error_return:
1084 DNPRINTK(3, (KERN_INFO "[%p] eventpoll: sys_epoll_create(%d) = %d\n",
1085 current, size, error));
1086 return error;
1087} 1080}
1088 1081
1089/* 1082/*
diff --git a/fs/signalfd.c b/fs/signalfd.c
index 8ead0db35933..619725644c75 100644
--- a/fs/signalfd.c
+++ b/fs/signalfd.c
@@ -207,11 +207,8 @@ static const struct file_operations signalfd_fops = {
207 207
208asmlinkage long sys_signalfd(int ufd, sigset_t __user *user_mask, size_t sizemask) 208asmlinkage long sys_signalfd(int ufd, sigset_t __user *user_mask, size_t sizemask)
209{ 209{
210 int error;
211 sigset_t sigmask; 210 sigset_t sigmask;
212 struct signalfd_ctx *ctx; 211 struct signalfd_ctx *ctx;
213 struct file *file;
214 struct inode *inode;
215 212
216 if (sizemask != sizeof(sigset_t) || 213 if (sizemask != sizeof(sigset_t) ||
217 copy_from_user(&sigmask, user_mask, sizeof(sigmask))) 214 copy_from_user(&sigmask, user_mask, sizeof(sigmask)))
@@ -230,12 +227,11 @@ asmlinkage long sys_signalfd(int ufd, sigset_t __user *user_mask, size_t sizemas
230 * When we call this, the initialization must be complete, since 227 * When we call this, the initialization must be complete, since
231 * anon_inode_getfd() will install the fd. 228 * anon_inode_getfd() will install the fd.
232 */ 229 */
233 error = anon_inode_getfd(&ufd, &inode, &file, "[signalfd]", 230 ufd = anon_inode_getfd("[signalfd]", &signalfd_fops, ctx);
234 &signalfd_fops, ctx); 231 if (ufd < 0)
235 if (error) 232 kfree(ctx);
236 goto err_fdalloc;
237 } else { 233 } else {
238 file = fget(ufd); 234 struct file *file = fget(ufd);
239 if (!file) 235 if (!file)
240 return -EBADF; 236 return -EBADF;
241 ctx = file->private_data; 237 ctx = file->private_data;
@@ -252,9 +248,4 @@ asmlinkage long sys_signalfd(int ufd, sigset_t __user *user_mask, size_t sizemas
252 } 248 }
253 249
254 return ufd; 250 return ufd;
255
256err_fdalloc:
257 kfree(ctx);
258 return error;
259} 251}
260
diff --git a/fs/timerfd.c b/fs/timerfd.c
index 5400524e9cb1..d87d354ec424 100644
--- a/fs/timerfd.c
+++ b/fs/timerfd.c
@@ -181,10 +181,8 @@ static struct file *timerfd_fget(int fd)
181 181
182asmlinkage long sys_timerfd_create(int clockid, int flags) 182asmlinkage long sys_timerfd_create(int clockid, int flags)
183{ 183{
184 int error, ufd; 184 int ufd;
185 struct timerfd_ctx *ctx; 185 struct timerfd_ctx *ctx;
186 struct file *file;
187 struct inode *inode;
188 186
189 if (flags) 187 if (flags)
190 return -EINVAL; 188 return -EINVAL;
@@ -200,12 +198,9 @@ asmlinkage long sys_timerfd_create(int clockid, int flags)
200 ctx->clockid = clockid; 198 ctx->clockid = clockid;
201 hrtimer_init(&ctx->tmr, clockid, HRTIMER_MODE_ABS); 199 hrtimer_init(&ctx->tmr, clockid, HRTIMER_MODE_ABS);
202 200
203 error = anon_inode_getfd(&ufd, &inode, &file, "[timerfd]", 201 ufd = anon_inode_getfd("[timerfd]", &timerfd_fops, ctx);
204 &timerfd_fops, ctx); 202 if (ufd < 0)
205 if (error) {
206 kfree(ctx); 203 kfree(ctx);
207 return error;
208 }
209 204
210 return ufd; 205 return ufd;
211} 206}
diff --git a/include/linux/anon_inodes.h b/include/linux/anon_inodes.h
index b2e1ba325b9a..6129e58ca7c9 100644
--- a/include/linux/anon_inodes.h
+++ b/include/linux/anon_inodes.h
@@ -8,8 +8,7 @@
8#ifndef _LINUX_ANON_INODES_H 8#ifndef _LINUX_ANON_INODES_H
9#define _LINUX_ANON_INODES_H 9#define _LINUX_ANON_INODES_H
10 10
11int anon_inode_getfd(int *pfd, struct inode **pinode, struct file **pfile, 11int anon_inode_getfd(const char *name, const struct file_operations *fops,
12 const char *name, const struct file_operations *fops,
13 void *priv); 12 void *priv);
14 13
15#endif /* _LINUX_ANON_INODES_H */ 14#endif /* _LINUX_ANON_INODES_H */
diff --git a/virt/kvm/kvm_main.c b/virt/kvm/kvm_main.c
index c82cf15730a1..e89338e2b043 100644
--- a/virt/kvm/kvm_main.c
+++ b/virt/kvm/kvm_main.c
@@ -834,16 +834,9 @@ static const struct file_operations kvm_vcpu_fops = {
834 */ 834 */
835static int create_vcpu_fd(struct kvm_vcpu *vcpu) 835static int create_vcpu_fd(struct kvm_vcpu *vcpu)
836{ 836{
837 int fd, r; 837 int fd = anon_inode_getfd("kvm-vcpu", &kvm_vcpu_fops, vcpu);
838 struct inode *inode; 838 if (fd < 0)
839 struct file *file;
840
841 r = anon_inode_getfd(&fd, &inode, &file,
842 "kvm-vcpu", &kvm_vcpu_fops, vcpu);
843 if (r) {
844 kvm_put_kvm(vcpu->kvm); 839 kvm_put_kvm(vcpu->kvm);
845 return r;
846 }
847 return fd; 840 return fd;
848} 841}
849 842
@@ -1168,19 +1161,15 @@ static const struct file_operations kvm_vm_fops = {
1168 1161
1169static int kvm_dev_ioctl_create_vm(void) 1162static int kvm_dev_ioctl_create_vm(void)
1170{ 1163{
1171 int fd, r; 1164 int fd;
1172 struct inode *inode;
1173 struct file *file;
1174 struct kvm *kvm; 1165 struct kvm *kvm;
1175 1166
1176 kvm = kvm_create_vm(); 1167 kvm = kvm_create_vm();
1177 if (IS_ERR(kvm)) 1168 if (IS_ERR(kvm))
1178 return PTR_ERR(kvm); 1169 return PTR_ERR(kvm);
1179 r = anon_inode_getfd(&fd, &inode, &file, "kvm-vm", &kvm_vm_fops, kvm); 1170 fd = anon_inode_getfd("kvm-vm", &kvm_vm_fops, kvm);
1180 if (r) { 1171 if (fd < 0)
1181 kvm_put_kvm(kvm); 1172 kvm_put_kvm(kvm);
1182 return r;
1183 }
1184 1173
1185 return fd; 1174 return fd;
1186} 1175}