From: Pekka Enberg <[EMAIL PROTECTED]> We need to break COW for private mappings to make sure a process cannot read new data after an inode has been revoked.
Signed-off-by: Pekka Enberg <[EMAIL PROTECTED]> --- fs/revoke.c | 85 +++++++++++++++++++++++++++++++++++++++++++++++++++--------- 1 file changed, 73 insertions(+), 12 deletions(-) Index: uml-2.6/fs/revoke.c =================================================================== --- uml-2.6.orig/fs/revoke.c 2007-03-26 18:10:24.000000000 +0300 +++ uml-2.6/fs/revoke.c 2007-03-26 18:27:25.000000000 +0300 @@ -174,12 +174,58 @@ static inline bool need_revoke(struct vm if (file->f_path.dentry->d_inode != inode) return false; - if (!(vma->vm_flags & VM_SHARED)) - return false; - return file != to_exclude; } +static int __revoke_break_cow(struct task_struct *tsk, struct inode *inode, + struct file *to_exclude) +{ + struct mm_struct *mm = tsk->mm; + struct vm_area_struct *vma; + int err = 0; + + down_write(&mm->mmap_sem); + for (vma = mm->mmap; vma != NULL; vma = vma->vm_next) { + int ret; + + if (vma->vm_flags & VM_SHARED) + continue; + + if (!need_revoke(vma, inode, to_exclude)) + continue; + + ret = get_user_pages(tsk, tsk->mm, vma->vm_start, + vma->vm_end-vma->vm_start, 1, 1, NULL, + NULL); + if (ret < 0) { + err = ret; + break; + } + } + up_write(&mm->mmap_sem); + return err; +} + +static int revoke_break_cow(struct revoke_table *table, struct inode *inode, + struct file *to_exclude) +{ + unsigned long i; + int err = 0; + + for (i = 0; i < table->end; i++) { + struct revokefs_inode_info *info; + struct file *this; + + this = table->files[i]; + info = revokefs_i(this->f_dentry->d_inode); + + err = __revoke_break_cow(info->owner, inode, to_exclude); + if (err) + break; + } + return err; +} + /* * LOCKING: down_write(&mm->mmap_sem) * -> spin_lock(&mapping->i_mmap_lock) @@ -235,6 +281,9 @@ int err = 0; goto out; } for (vma = mm->mmap; vma != NULL; vma = vma->vm_next) { + if (!(vma->vm_flags & VM_SHARED)) + continue; + if (!need_revoke(vma, mapping->host, to_exclude)) continue; @@ -261,6 +310,9 @@ int try_again = 0; vma_prio_tree_foreach(vma, &iter, &mapping->i_mmap, 0, ULONG_MAX) { int err; + if (!(vma->vm_flags & VM_SHARED)) + continue; + if (likely(!need_revoke(vma, mapping->host, to_exclude))) continue; @@ -380,12 +432,9 @@ for (i = 0; i < table->end; i++) { put_task_struct(info->owner); info->owner = NULL; /* To avoid restoring closed file. */ if (err) - goto failed; + goto out; } - return 0; - - failed: - restore_files(table); + out: return err; } @@ -527,10 +576,8 @@ int err = 0; exit_loop: read_unlock(&tasklist_lock); - if (err) { - restore_files(table); - goto out_free_table; - } + if (err) + goto out_restore; /* * Take down shared memory mappings. @@ -538,13 +585,27 @@ int err = 0; revoke_mapping(inode->i_mapping, to_exclude); /* + * Break COW for private mappings. + */ + err = revoke_break_cow(table, inode, to_exclude); + if (err) + goto out_restore; + + /* * Now, revoke the files for good. */ err = revoke_files(table); + if (err) + goto out_restore; + out_free_table: free_revoke_table(table); out: return err; + + out_restore: + restore_files(table); + goto out_free_table; } asmlinkage long sys_revokeat(int dfd, const char __user * filename) - To unsubscribe from this list: send the line "unsubscribe linux-kernel" in the body of a message to [EMAIL PROTECTED] More majordomo info at http://vger.kernel.org/majordomo-info.html Please read the FAQ at http://www.tux.org/lkml/