History

mm: Hold a file reference in madvise_remove

Otherwise the code races with munmap (causing a use-after-free of the vma) or with close (causing a use-after-free of the struct file). The bug was introduced by commit 90ed52ebe481 ("[PATCH] holepunch: fix mmap_sem i_mutex deadlock")

Andy Lutomirski committed 14 years ago

Commit 9ab42331 parent 1b7fa4c1 file · +14 −4Browse files

Unified · Split

mm/madvise.c+14−4
@@ -15,6 +15,7 @@ · 14 unmodified lines
1515 #include <linux/sched.h>
1616 #include <linux/ksm.h>
1717 #include <linux/fs.h>
18+#include <linux/file.h>
1819
1920 /*
2021 * Any behaviour which results in changes to the vma->vm_flags needs to
@@ -204,14 +205,16 @@ static long madvise_remove(struct vm_area_struct *vma, · 183 unmodified lines
204205 {
205206 loff_t offset;
206207 int error;
208+ struct file *f;
207209
208210 *prev = NULL; /* tell sys_madvise we drop mmap_sem */
209211
210212 if (vma->vm_flags & (VM_LOCKED|VM_NONLINEAR|VM_HUGETLB))
211213 return -EINVAL;
212214
213− if (!vma->vm_file || !vma->vm_file->f_mapping
214− || !vma->vm_file->f_mapping->host) {
215+ f = vma->vm_file;
216+
217+ if (!f || !f->f_mapping || !f->f_mapping->host) {
215218 return -EINVAL;
216219 }
217220
@@ -221,11 +224,18 @@ static long madvise_remove(struct vm_area_struct *vma, · 3 unmodified lines
221224 offset = (loff_t)(start - vma->vm_start)
222225 + ((loff_t)vma->vm_pgoff << PAGE_SHIFT);
223226
224− /* filesystem's fallocate may need to take i_mutex */
227+ /*
228+ * Filesystem's fallocate may need to take i_mutex. We need to
229+ * explicitly grab a reference because the vma (and hence the
230+ * vma's reference to the file) can go away as soon as we drop
231+ * mmap_sem.
232+ */
233+ get_file(f);
225234 up_read(&current->mm->mmap_sem);
226− error = do_fallocate(vma->vm_file,
235+ error = do_fallocate(f,
227236 FALLOC_FL_PUNCH_HOLE | FALLOC_FL_KEEP_SIZE,
228237 offset, end - start);
238+ fput(f);
229239 down_read(&current->mm->mmap_sem);
230240 return error;
231241 }