aboutsummaryrefslogtreecommitdiffstats
path: root/fs/sysfs/bin.c
diff options
context:
space:
mode:
authorEric W. Biederman <ebiederm@aristanetworks.com>2010-09-20 03:57:03 -0400
committerGreg Kroah-Hartman <gregkh@suse.de>2010-10-22 13:16:43 -0400
commit38f49a5132f24d29236820eb5c7dd956e47f94a3 (patch)
treeeb2d3184996d01babcf3689dd20d626f731d340a /fs/sysfs/bin.c
parenta6849fa1f7d7d7adbeb6a696beeabfa078acf173 (diff)
sysfs: only access bin file vm_ops with the active lock
bb->vm_ops is a cached copy of the vm_ops of the underlying sysfs bin file, which means that after sysfs_bin_remove_file completes it is only longer valid to deference bb->vm_ops. So move all of the tests of bb->vm_ops inside of where we hold the sysfs active lock. Signed-off-by: Eric W. Biederman <ebiederm@aristanetworks.com> Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
Diffstat (limited to 'fs/sysfs/bin.c')
-rw-r--r--fs/sysfs/bin.c42
1 files changed, 26 insertions, 16 deletions
diff --git a/fs/sysfs/bin.c b/fs/sysfs/bin.c
index d31d7b7d5426..a4759833d62d 100644
--- a/fs/sysfs/bin.c
+++ b/fs/sysfs/bin.c
@@ -179,13 +179,14 @@ static void bin_vma_open(struct vm_area_struct *vma)
179 struct bin_buffer *bb = file->private_data; 179 struct bin_buffer *bb = file->private_data;
180 struct sysfs_dirent *attr_sd = file->f_path.dentry->d_fsdata; 180 struct sysfs_dirent *attr_sd = file->f_path.dentry->d_fsdata;
181 181
182 if (!bb->vm_ops || !bb->vm_ops->open) 182 if (!bb->vm_ops)
183 return; 183 return;
184 184
185 if (!sysfs_get_active(attr_sd)) 185 if (!sysfs_get_active(attr_sd))
186 return; 186 return;
187 187
188 bb->vm_ops->open(vma); 188 if (bb->vm_ops->open)
189 bb->vm_ops->open(vma);
189 190
190 sysfs_put_active(attr_sd); 191 sysfs_put_active(attr_sd);
191} 192}
@@ -197,13 +198,15 @@ static int bin_fault(struct vm_area_struct *vma, struct vm_fault *vmf)
197 struct sysfs_dirent *attr_sd = file->f_path.dentry->d_fsdata; 198 struct sysfs_dirent *attr_sd = file->f_path.dentry->d_fsdata;
198 int ret; 199 int ret;
199 200
200 if (!bb->vm_ops || !bb->vm_ops->fault) 201 if (!bb->vm_ops)
201 return VM_FAULT_SIGBUS; 202 return VM_FAULT_SIGBUS;
202 203
203 if (!sysfs_get_active(attr_sd)) 204 if (!sysfs_get_active(attr_sd))
204 return VM_FAULT_SIGBUS; 205 return VM_FAULT_SIGBUS;
205 206
206 ret = bb->vm_ops->fault(vma, vmf); 207 ret = VM_FAULT_SIGBUS;
208 if (bb->vm_ops->fault)
209 ret = bb->vm_ops->fault(vma, vmf);
207 210
208 sysfs_put_active(attr_sd); 211 sysfs_put_active(attr_sd);
209 return ret; 212 return ret;
@@ -219,13 +222,12 @@ static int bin_page_mkwrite(struct vm_area_struct *vma, struct vm_fault *vmf)
219 if (!bb->vm_ops) 222 if (!bb->vm_ops)
220 return VM_FAULT_SIGBUS; 223 return VM_FAULT_SIGBUS;
221 224
222 if (!bb->vm_ops->page_mkwrite)
223 return 0;
224
225 if (!sysfs_get_active(attr_sd)) 225 if (!sysfs_get_active(attr_sd))
226 return VM_FAULT_SIGBUS; 226 return VM_FAULT_SIGBUS;
227 227
228 ret = bb->vm_ops->page_mkwrite(vma, vmf); 228 ret = 0;
229 if (bb->vm_ops->page_mkwrite)
230 ret = bb->vm_ops->page_mkwrite(vma, vmf);
229 231
230 sysfs_put_active(attr_sd); 232 sysfs_put_active(attr_sd);
231 return ret; 233 return ret;
@@ -239,13 +241,15 @@ static int bin_access(struct vm_area_struct *vma, unsigned long addr,
239 struct sysfs_dirent *attr_sd = file->f_path.dentry->d_fsdata; 241 struct sysfs_dirent *attr_sd = file->f_path.dentry->d_fsdata;
240 int ret; 242 int ret;
241 243
242 if (!bb->vm_ops || !bb->vm_ops->access) 244 if (!bb->vm_ops)
243 return -EINVAL; 245 return -EINVAL;
244 246
245 if (!sysfs_get_active(attr_sd)) 247 if (!sysfs_get_active(attr_sd))
246 return -EINVAL; 248 return -EINVAL;
247 249
248 ret = bb->vm_ops->access(vma, addr, buf, len, write); 250 ret = -EINVAL;
251 if (bb->vm_ops->access)
252 ret = bb->vm_ops->access(vma, addr, buf, len, write);
249 253
250 sysfs_put_active(attr_sd); 254 sysfs_put_active(attr_sd);
251 return ret; 255 return ret;
@@ -259,13 +263,15 @@ static int bin_set_policy(struct vm_area_struct *vma, struct mempolicy *new)
259 struct sysfs_dirent *attr_sd = file->f_path.dentry->d_fsdata; 263 struct sysfs_dirent *attr_sd = file->f_path.dentry->d_fsdata;
260 int ret; 264 int ret;
261 265
262 if (!bb->vm_ops || !bb->vm_ops->set_policy) 266 if (!bb->vm_ops)
263 return 0; 267 return 0;
264 268
265 if (!sysfs_get_active(attr_sd)) 269 if (!sysfs_get_active(attr_sd))
266 return -EINVAL; 270 return -EINVAL;
267 271
268 ret = bb->vm_ops->set_policy(vma, new); 272 ret = 0;
273 if (bb->vm_ops->set_policy)
274 ret = bb->vm_ops->set_policy(vma, new);
269 275
270 sysfs_put_active(attr_sd); 276 sysfs_put_active(attr_sd);
271 return ret; 277 return ret;
@@ -279,13 +285,15 @@ static struct mempolicy *bin_get_policy(struct vm_area_struct *vma,
279 struct sysfs_dirent *attr_sd = file->f_path.dentry->d_fsdata; 285 struct sysfs_dirent *attr_sd = file->f_path.dentry->d_fsdata;
280 struct mempolicy *pol; 286 struct mempolicy *pol;
281 287
282 if (!bb->vm_ops || !bb->vm_ops->get_policy) 288 if (!bb->vm_ops)
283 return vma->vm_policy; 289 return vma->vm_policy;
284 290
285 if (!sysfs_get_active(attr_sd)) 291 if (!sysfs_get_active(attr_sd))
286 return vma->vm_policy; 292 return vma->vm_policy;
287 293
288 pol = bb->vm_ops->get_policy(vma, addr); 294 pol = vma->vm_policy;
295 if (bb->vm_ops->get_policy)
296 pol = bb->vm_ops->get_policy(vma, addr);
289 297
290 sysfs_put_active(attr_sd); 298 sysfs_put_active(attr_sd);
291 return pol; 299 return pol;
@@ -299,13 +307,15 @@ static int bin_migrate(struct vm_area_struct *vma, const nodemask_t *from,
299 struct sysfs_dirent *attr_sd = file->f_path.dentry->d_fsdata; 307 struct sysfs_dirent *attr_sd = file->f_path.dentry->d_fsdata;
300 int ret; 308 int ret;
301 309
302 if (!bb->vm_ops || !bb->vm_ops->migrate) 310 if (!bb->vm_ops)
303 return 0; 311 return 0;
304 312
305 if (!sysfs_get_active(attr_sd)) 313 if (!sysfs_get_active(attr_sd))
306 return 0; 314 return 0;
307 315
308 ret = bb->vm_ops->migrate(vma, from, to, flags); 316 ret = 0;
317 if (bb->vm_ops->migrate)
318 ret = bb->vm_ops->migrate(vma, from, to, flags);
309 319
310 sysfs_put_active(attr_sd); 320 sysfs_put_active(attr_sd);
311 return ret; 321 return ret;