diff options
author | Eric W. Biederman <ebiederm@aristanetworks.com> | 2010-09-20 03:57:03 -0400 |
---|---|---|
committer | Greg Kroah-Hartman <gregkh@suse.de> | 2010-10-22 13:16:43 -0400 |
commit | 38f49a5132f24d29236820eb5c7dd956e47f94a3 (patch) | |
tree | eb2d3184996d01babcf3689dd20d626f731d340a /fs | |
parent | a6849fa1f7d7d7adbeb6a696beeabfa078acf173 (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')
-rw-r--r-- | fs/sysfs/bin.c | 42 |
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; |