diff options
| -rw-r--r-- | fs/binfmt_flat.c | 3 | ||||
| -rw-r--r-- | fs/exec.c | 2 | ||||
| -rw-r--r-- | fs/proc/base.c | 75 | ||||
| -rw-r--r-- | fs/proc/internal.h | 1 | ||||
| -rw-r--r-- | fs/proc/task_mmu.c | 34 | ||||
| -rw-r--r-- | fs/proc/task_nommu.c | 34 | ||||
| -rw-r--r-- | include/linux/mm.h | 13 | ||||
| -rw-r--r-- | include/linux/mm_types.h | 6 | ||||
| -rw-r--r-- | include/linux/proc_fs.h | 20 | ||||
| -rw-r--r-- | kernel/fork.c | 3 | ||||
| -rw-r--r-- | mm/mmap.c | 24 | ||||
| -rw-r--r-- | mm/nommu.c | 23 |
12 files changed, 157 insertions, 81 deletions
diff --git a/fs/binfmt_flat.c b/fs/binfmt_flat.c index c12cc362fd3b..3b40d45a3a16 100644 --- a/fs/binfmt_flat.c +++ b/fs/binfmt_flat.c | |||
| @@ -531,7 +531,8 @@ static int load_flat_file(struct linux_binprm * bprm, | |||
| 531 | DBG_FLT("BINFMT_FLAT: ROM mapping of file (we hope)\n"); | 531 | DBG_FLT("BINFMT_FLAT: ROM mapping of file (we hope)\n"); |
| 532 | 532 | ||
| 533 | down_write(¤t->mm->mmap_sem); | 533 | down_write(¤t->mm->mmap_sem); |
| 534 | textpos = do_mmap(bprm->file, 0, text_len, PROT_READ|PROT_EXEC, MAP_PRIVATE, 0); | 534 | textpos = do_mmap(bprm->file, 0, text_len, PROT_READ|PROT_EXEC, |
| 535 | MAP_PRIVATE|MAP_EXECUTABLE, 0); | ||
| 535 | up_write(¤t->mm->mmap_sem); | 536 | up_write(¤t->mm->mmap_sem); |
| 536 | if (!textpos || textpos >= (unsigned long) -4096) { | 537 | if (!textpos || textpos >= (unsigned long) -4096) { |
| 537 | if (!textpos) | 538 | if (!textpos) |
| @@ -964,6 +964,8 @@ int flush_old_exec(struct linux_binprm * bprm) | |||
| 964 | if (retval) | 964 | if (retval) |
| 965 | goto out; | 965 | goto out; |
| 966 | 966 | ||
| 967 | set_mm_exe_file(bprm->mm, bprm->file); | ||
| 968 | |||
| 967 | /* | 969 | /* |
| 968 | * Release all of the old mmap stuff | 970 | * Release all of the old mmap stuff |
| 969 | */ | 971 | */ |
diff --git a/fs/proc/base.c b/fs/proc/base.c index c5e412a00b17..b48ddb119945 100644 --- a/fs/proc/base.c +++ b/fs/proc/base.c | |||
| @@ -1181,6 +1181,81 @@ static const struct file_operations proc_pid_sched_operations = { | |||
| 1181 | 1181 | ||
| 1182 | #endif | 1182 | #endif |
| 1183 | 1183 | ||
| 1184 | /* | ||
| 1185 | * We added or removed a vma mapping the executable. The vmas are only mapped | ||
| 1186 | * during exec and are not mapped with the mmap system call. | ||
| 1187 | * Callers must hold down_write() on the mm's mmap_sem for these | ||
| 1188 | */ | ||
| 1189 | void added_exe_file_vma(struct mm_struct *mm) | ||
| 1190 | { | ||
| 1191 | mm->num_exe_file_vmas++; | ||
| 1192 | } | ||
| 1193 | |||
| 1194 | void removed_exe_file_vma(struct mm_struct *mm) | ||
| 1195 | { | ||
| 1196 | mm->num_exe_file_vmas--; | ||
| 1197 | if ((mm->num_exe_file_vmas == 0) && mm->exe_file){ | ||
| 1198 | fput(mm->exe_file); | ||
| 1199 | mm->exe_file = NULL; | ||
| 1200 | } | ||
| 1201 | |||
| 1202 | } | ||
| 1203 | |||
| 1204 | void set_mm_exe_file(struct mm_struct *mm, struct file *new_exe_file) | ||
| 1205 | { | ||
| 1206 | if (new_exe_file) | ||
| 1207 | get_file(new_exe_file); | ||
| 1208 | if (mm->exe_file) | ||
| 1209 | fput(mm->exe_file); | ||
| 1210 | mm->exe_file = new_exe_file; | ||
| 1211 | mm->num_exe_file_vmas = 0; | ||
| 1212 | } | ||
| 1213 | |||
| 1214 | struct file *get_mm_exe_file(struct mm_struct *mm) | ||
| 1215 | { | ||
| 1216 | struct file *exe_file; | ||
| 1217 | |||
| 1218 | /* We need mmap_sem to protect against races with removal of | ||
| 1219 | * VM_EXECUTABLE vmas */ | ||
| 1220 | down_read(&mm->mmap_sem); | ||
| 1221 | exe_file = mm->exe_file; | ||
| 1222 | if (exe_file) | ||
| 1223 | get_file(exe_file); | ||
| 1224 | up_read(&mm->mmap_sem); | ||
| 1225 | return exe_file; | ||
| 1226 | } | ||
| 1227 | |||
| 1228 | void dup_mm_exe_file(struct mm_struct *oldmm, struct mm_struct *newmm) | ||
| 1229 | { | ||
| 1230 | /* It's safe to write the exe_file pointer without exe_file_lock because | ||
| 1231 | * this is called during fork when the task is not yet in /proc */ | ||
| 1232 | newmm->exe_file = get_mm_exe_file(oldmm); | ||
| 1233 | } | ||
| 1234 | |||
| 1235 | static int proc_exe_link(struct inode *inode, struct path *exe_path) | ||
| 1236 | { | ||
| 1237 | struct task_struct *task; | ||
| 1238 | struct mm_struct *mm; | ||
| 1239 | struct file *exe_file; | ||
| 1240 | |||
| 1241 | task = get_proc_task(inode); | ||
| 1242 | if (!task) | ||
| 1243 | return -ENOENT; | ||
| 1244 | mm = get_task_mm(task); | ||
| 1245 | put_task_struct(task); | ||
| 1246 | if (!mm) | ||
| 1247 | return -ENOENT; | ||
| 1248 | exe_file = get_mm_exe_file(mm); | ||
| 1249 | mmput(mm); | ||
| 1250 | if (exe_file) { | ||
| 1251 | *exe_path = exe_file->f_path; | ||
| 1252 | path_get(&exe_file->f_path); | ||
| 1253 | fput(exe_file); | ||
| 1254 | return 0; | ||
| 1255 | } else | ||
| 1256 | return -ENOENT; | ||
| 1257 | } | ||
| 1258 | |||
| 1184 | static void *proc_pid_follow_link(struct dentry *dentry, struct nameidata *nd) | 1259 | static void *proc_pid_follow_link(struct dentry *dentry, struct nameidata *nd) |
| 1185 | { | 1260 | { |
| 1186 | struct inode *inode = dentry->d_inode; | 1261 | struct inode *inode = dentry->d_inode; |
diff --git a/fs/proc/internal.h b/fs/proc/internal.h index bc72f5c8c47d..45abb9803988 100644 --- a/fs/proc/internal.h +++ b/fs/proc/internal.h | |||
| @@ -48,7 +48,6 @@ extern int maps_protect; | |||
| 48 | 48 | ||
| 49 | extern void create_seq_entry(char *name, mode_t mode, | 49 | extern void create_seq_entry(char *name, mode_t mode, |
| 50 | const struct file_operations *f); | 50 | const struct file_operations *f); |
| 51 | extern int proc_exe_link(struct inode *, struct path *); | ||
| 52 | extern int proc_tid_stat(struct seq_file *m, struct pid_namespace *ns, | 51 | extern int proc_tid_stat(struct seq_file *m, struct pid_namespace *ns, |
| 53 | struct pid *pid, struct task_struct *task); | 52 | struct pid *pid, struct task_struct *task); |
| 54 | extern int proc_tgid_stat(struct seq_file *m, struct pid_namespace *ns, | 53 | extern int proc_tgid_stat(struct seq_file *m, struct pid_namespace *ns, |
diff --git a/fs/proc/task_mmu.c b/fs/proc/task_mmu.c index 7415eeb7cc3a..e2b8e769f510 100644 --- a/fs/proc/task_mmu.c +++ b/fs/proc/task_mmu.c | |||
| @@ -75,40 +75,6 @@ int task_statm(struct mm_struct *mm, int *shared, int *text, | |||
| 75 | return mm->total_vm; | 75 | return mm->total_vm; |
| 76 | } | 76 | } |
| 77 | 77 | ||
| 78 | int proc_exe_link(struct inode *inode, struct path *path) | ||
| 79 | { | ||
| 80 | struct vm_area_struct * vma; | ||
| 81 | int result = -ENOENT; | ||
| 82 | struct task_struct *task = get_proc_task(inode); | ||
| 83 | struct mm_struct * mm = NULL; | ||
| 84 | |||
| 85 | if (task) { | ||
| 86 | mm = get_task_mm(task); | ||
| 87 | put_task_struct(task); | ||
| 88 | } | ||
| 89 | if (!mm) | ||
| 90 | goto out; | ||
| 91 | down_read(&mm->mmap_sem); | ||
| 92 | |||
| 93 | vma = mm->mmap; | ||
| 94 | while (vma) { | ||
| 95 | if ((vma->vm_flags & VM_EXECUTABLE) && vma->vm_file) | ||
| 96 | break; | ||
| 97 | vma = vma->vm_next; | ||
| 98 | } | ||
| 99 | |||
| 100 | if (vma) { | ||
| 101 | *path = vma->vm_file->f_path; | ||
| 102 | path_get(&vma->vm_file->f_path); | ||
| 103 | result = 0; | ||
| 104 | } | ||
| 105 | |||
| 106 | up_read(&mm->mmap_sem); | ||
| 107 | mmput(mm); | ||
| 108 | out: | ||
| 109 | return result; | ||
| 110 | } | ||
| 111 | |||
| 112 | static void pad_len_spaces(struct seq_file *m, int len) | 78 | static void pad_len_spaces(struct seq_file *m, int len) |
| 113 | { | 79 | { |
| 114 | len = 25 + sizeof(void*) * 6 - len; | 80 | len = 25 + sizeof(void*) * 6 - len; |
diff --git a/fs/proc/task_nommu.c b/fs/proc/task_nommu.c index 8011528518bd..4b733f108455 100644 --- a/fs/proc/task_nommu.c +++ b/fs/proc/task_nommu.c | |||
| @@ -103,40 +103,6 @@ int task_statm(struct mm_struct *mm, int *shared, int *text, | |||
| 103 | return size; | 103 | return size; |
| 104 | } | 104 | } |
| 105 | 105 | ||
| 106 | int proc_exe_link(struct inode *inode, struct path *path) | ||
| 107 | { | ||
| 108 | struct vm_list_struct *vml; | ||
| 109 | struct vm_area_struct *vma; | ||
| 110 | struct task_struct *task = get_proc_task(inode); | ||
| 111 | struct mm_struct *mm = get_task_mm(task); | ||
| 112 | int result = -ENOENT; | ||
| 113 | |||
| 114 | if (!mm) | ||
| 115 | goto out; | ||
| 116 | down_read(&mm->mmap_sem); | ||
| 117 | |||
| 118 | vml = mm->context.vmlist; | ||
| 119 | vma = NULL; | ||
| 120 | while (vml) { | ||
| 121 | if ((vml->vma->vm_flags & VM_EXECUTABLE) && vml->vma->vm_file) { | ||
| 122 | vma = vml->vma; | ||
| 123 | break; | ||
| 124 | } | ||
| 125 | vml = vml->next; | ||
| 126 | } | ||
| 127 | |||
| 128 | if (vma) { | ||
| 129 | *path = vma->vm_file->f_path; | ||
| 130 | path_get(&vma->vm_file->f_path); | ||
| 131 | result = 0; | ||
| 132 | } | ||
| 133 | |||
| 134 | up_read(&mm->mmap_sem); | ||
| 135 | mmput(mm); | ||
| 136 | out: | ||
| 137 | return result; | ||
| 138 | } | ||
| 139 | |||
| 140 | /* | 106 | /* |
| 141 | * display mapping lines for a particular process's /proc/pid/maps | 107 | * display mapping lines for a particular process's /proc/pid/maps |
| 142 | */ | 108 | */ |
diff --git a/include/linux/mm.h b/include/linux/mm.h index fef602d82722..c31a9cd2a30e 100644 --- a/include/linux/mm.h +++ b/include/linux/mm.h | |||
| @@ -1066,6 +1066,19 @@ extern void unlink_file_vma(struct vm_area_struct *); | |||
| 1066 | extern struct vm_area_struct *copy_vma(struct vm_area_struct **, | 1066 | extern struct vm_area_struct *copy_vma(struct vm_area_struct **, |
| 1067 | unsigned long addr, unsigned long len, pgoff_t pgoff); | 1067 | unsigned long addr, unsigned long len, pgoff_t pgoff); |
| 1068 | extern void exit_mmap(struct mm_struct *); | 1068 | extern void exit_mmap(struct mm_struct *); |
| 1069 | |||
| 1070 | #ifdef CONFIG_PROC_FS | ||
| 1071 | /* From fs/proc/base.c. callers must _not_ hold the mm's exe_file_lock */ | ||
| 1072 | extern void added_exe_file_vma(struct mm_struct *mm); | ||
| 1073 | extern void removed_exe_file_vma(struct mm_struct *mm); | ||
| 1074 | #else | ||
| 1075 | static inline void added_exe_file_vma(struct mm_struct *mm) | ||
| 1076 | {} | ||
| 1077 | |||
| 1078 | static inline void removed_exe_file_vma(struct mm_struct *mm) | ||
| 1079 | {} | ||
| 1080 | #endif /* CONFIG_PROC_FS */ | ||
| 1081 | |||
| 1069 | extern int may_expand_vm(struct mm_struct *mm, unsigned long npages); | 1082 | extern int may_expand_vm(struct mm_struct *mm, unsigned long npages); |
| 1070 | extern int install_special_mapping(struct mm_struct *mm, | 1083 | extern int install_special_mapping(struct mm_struct *mm, |
| 1071 | unsigned long addr, unsigned long len, | 1084 | unsigned long addr, unsigned long len, |
diff --git a/include/linux/mm_types.h b/include/linux/mm_types.h index bc97bd54f606..eb7c16cc9559 100644 --- a/include/linux/mm_types.h +++ b/include/linux/mm_types.h | |||
| @@ -229,6 +229,12 @@ struct mm_struct { | |||
| 229 | struct task_struct *owner; /* The thread group leader that */ | 229 | struct task_struct *owner; /* The thread group leader that */ |
| 230 | /* owns the mm_struct. */ | 230 | /* owns the mm_struct. */ |
| 231 | #endif | 231 | #endif |
| 232 | |||
| 233 | #ifdef CONFIG_PROC_FS | ||
| 234 | /* store ref to file /proc/<pid>/exe symlink points to */ | ||
| 235 | struct file *exe_file; | ||
| 236 | unsigned long num_exe_file_vmas; | ||
| 237 | #endif | ||
| 232 | }; | 238 | }; |
| 233 | 239 | ||
| 234 | #endif /* _LINUX_MM_TYPES_H */ | 240 | #endif /* _LINUX_MM_TYPES_H */ |
diff --git a/include/linux/proc_fs.h b/include/linux/proc_fs.h index 9b6c935f69cf..65f2299b772b 100644 --- a/include/linux/proc_fs.h +++ b/include/linux/proc_fs.h | |||
| @@ -9,7 +9,6 @@ | |||
| 9 | 9 | ||
| 10 | struct net; | 10 | struct net; |
| 11 | struct completion; | 11 | struct completion; |
| 12 | |||
| 13 | /* | 12 | /* |
| 14 | * The proc filesystem constants/structures | 13 | * The proc filesystem constants/structures |
| 15 | */ | 14 | */ |
| @@ -206,6 +205,12 @@ extern void proc_net_remove(struct net *net, const char *name); | |||
| 206 | extern struct proc_dir_entry *proc_net_mkdir(struct net *net, const char *name, | 205 | extern struct proc_dir_entry *proc_net_mkdir(struct net *net, const char *name, |
| 207 | struct proc_dir_entry *parent); | 206 | struct proc_dir_entry *parent); |
| 208 | 207 | ||
| 208 | /* While the {get|set|dup}_mm_exe_file functions are for mm_structs, they are | ||
| 209 | * only needed to implement /proc/<pid>|self/exe so we define them here. */ | ||
| 210 | extern void set_mm_exe_file(struct mm_struct *mm, struct file *new_exe_file); | ||
| 211 | extern struct file *get_mm_exe_file(struct mm_struct *mm); | ||
| 212 | extern void dup_mm_exe_file(struct mm_struct *oldmm, struct mm_struct *newmm); | ||
| 213 | |||
| 209 | #else | 214 | #else |
| 210 | 215 | ||
| 211 | #define proc_root_driver NULL | 216 | #define proc_root_driver NULL |
| @@ -255,6 +260,19 @@ static inline void pid_ns_release_proc(struct pid_namespace *ns) | |||
| 255 | { | 260 | { |
| 256 | } | 261 | } |
| 257 | 262 | ||
| 263 | static inline void set_mm_exe_file(struct mm_struct *mm, | ||
| 264 | struct file *new_exe_file) | ||
| 265 | {} | ||
| 266 | |||
| 267 | static inline struct file *get_mm_exe_file(struct mm_struct *mm) | ||
| 268 | { | ||
| 269 | return NULL; | ||
| 270 | } | ||
| 271 | |||
| 272 | static inline void dup_mm_exe_file(struct mm_struct *oldmm, | ||
| 273 | struct mm_struct *newmm) | ||
| 274 | {} | ||
| 275 | |||
| 258 | #endif /* CONFIG_PROC_FS */ | 276 | #endif /* CONFIG_PROC_FS */ |
| 259 | 277 | ||
| 260 | #if !defined(CONFIG_PROC_KCORE) | 278 | #if !defined(CONFIG_PROC_KCORE) |
diff --git a/kernel/fork.c b/kernel/fork.c index de5c16c6b6ec..068ffe007529 100644 --- a/kernel/fork.c +++ b/kernel/fork.c | |||
| @@ -431,6 +431,7 @@ void mmput(struct mm_struct *mm) | |||
| 431 | if (atomic_dec_and_test(&mm->mm_users)) { | 431 | if (atomic_dec_and_test(&mm->mm_users)) { |
| 432 | exit_aio(mm); | 432 | exit_aio(mm); |
| 433 | exit_mmap(mm); | 433 | exit_mmap(mm); |
| 434 | set_mm_exe_file(mm, NULL); | ||
| 434 | if (!list_empty(&mm->mmlist)) { | 435 | if (!list_empty(&mm->mmlist)) { |
| 435 | spin_lock(&mmlist_lock); | 436 | spin_lock(&mmlist_lock); |
| 436 | list_del(&mm->mmlist); | 437 | list_del(&mm->mmlist); |
| @@ -543,6 +544,8 @@ struct mm_struct *dup_mm(struct task_struct *tsk) | |||
| 543 | if (init_new_context(tsk, mm)) | 544 | if (init_new_context(tsk, mm)) |
| 544 | goto fail_nocontext; | 545 | goto fail_nocontext; |
| 545 | 546 | ||
| 547 | dup_mm_exe_file(oldmm, mm); | ||
| 548 | |||
| 546 | err = dup_mmap(mm, oldmm); | 549 | err = dup_mmap(mm, oldmm); |
| 547 | if (err) | 550 | if (err) |
| 548 | goto free_pt; | 551 | goto free_pt; |
| @@ -230,8 +230,11 @@ static struct vm_area_struct *remove_vma(struct vm_area_struct *vma) | |||
| 230 | might_sleep(); | 230 | might_sleep(); |
| 231 | if (vma->vm_ops && vma->vm_ops->close) | 231 | if (vma->vm_ops && vma->vm_ops->close) |
| 232 | vma->vm_ops->close(vma); | 232 | vma->vm_ops->close(vma); |
| 233 | if (vma->vm_file) | 233 | if (vma->vm_file) { |
| 234 | fput(vma->vm_file); | 234 | fput(vma->vm_file); |
| 235 | if (vma->vm_flags & VM_EXECUTABLE) | ||
| 236 | removed_exe_file_vma(vma->vm_mm); | ||
| 237 | } | ||
| 235 | mpol_put(vma_policy(vma)); | 238 | mpol_put(vma_policy(vma)); |
| 236 | kmem_cache_free(vm_area_cachep, vma); | 239 | kmem_cache_free(vm_area_cachep, vma); |
| 237 | return next; | 240 | return next; |
| @@ -623,8 +626,11 @@ again: remove_next = 1 + (end > next->vm_end); | |||
| 623 | spin_unlock(&mapping->i_mmap_lock); | 626 | spin_unlock(&mapping->i_mmap_lock); |
| 624 | 627 | ||
| 625 | if (remove_next) { | 628 | if (remove_next) { |
| 626 | if (file) | 629 | if (file) { |
| 627 | fput(file); | 630 | fput(file); |
| 631 | if (next->vm_flags & VM_EXECUTABLE) | ||
| 632 | removed_exe_file_vma(mm); | ||
| 633 | } | ||
| 628 | mm->map_count--; | 634 | mm->map_count--; |
| 629 | mpol_put(vma_policy(next)); | 635 | mpol_put(vma_policy(next)); |
| 630 | kmem_cache_free(vm_area_cachep, next); | 636 | kmem_cache_free(vm_area_cachep, next); |
| @@ -1154,6 +1160,8 @@ munmap_back: | |||
| 1154 | error = file->f_op->mmap(file, vma); | 1160 | error = file->f_op->mmap(file, vma); |
| 1155 | if (error) | 1161 | if (error) |
| 1156 | goto unmap_and_free_vma; | 1162 | goto unmap_and_free_vma; |
| 1163 | if (vm_flags & VM_EXECUTABLE) | ||
| 1164 | added_exe_file_vma(mm); | ||
| 1157 | } else if (vm_flags & VM_SHARED) { | 1165 | } else if (vm_flags & VM_SHARED) { |
| 1158 | error = shmem_zero_setup(vma); | 1166 | error = shmem_zero_setup(vma); |
| 1159 | if (error) | 1167 | if (error) |
| @@ -1185,6 +1193,8 @@ munmap_back: | |||
| 1185 | mpol_put(vma_policy(vma)); | 1193 | mpol_put(vma_policy(vma)); |
| 1186 | kmem_cache_free(vm_area_cachep, vma); | 1194 | kmem_cache_free(vm_area_cachep, vma); |
| 1187 | fput(file); | 1195 | fput(file); |
| 1196 | if (vm_flags & VM_EXECUTABLE) | ||
| 1197 | removed_exe_file_vma(mm); | ||
| 1188 | } else { | 1198 | } else { |
| 1189 | vma_link(mm, vma, prev, rb_link, rb_parent); | 1199 | vma_link(mm, vma, prev, rb_link, rb_parent); |
| 1190 | file = vma->vm_file; | 1200 | file = vma->vm_file; |
| @@ -1817,8 +1827,11 @@ int split_vma(struct mm_struct * mm, struct vm_area_struct * vma, | |||
| 1817 | } | 1827 | } |
| 1818 | vma_set_policy(new, pol); | 1828 | vma_set_policy(new, pol); |
| 1819 | 1829 | ||
| 1820 | if (new->vm_file) | 1830 | if (new->vm_file) { |
| 1821 | get_file(new->vm_file); | 1831 | get_file(new->vm_file); |
| 1832 | if (vma->vm_flags & VM_EXECUTABLE) | ||
| 1833 | added_exe_file_vma(mm); | ||
| 1834 | } | ||
| 1822 | 1835 | ||
| 1823 | if (new->vm_ops && new->vm_ops->open) | 1836 | if (new->vm_ops && new->vm_ops->open) |
| 1824 | new->vm_ops->open(new); | 1837 | new->vm_ops->open(new); |
| @@ -2135,8 +2148,11 @@ struct vm_area_struct *copy_vma(struct vm_area_struct **vmap, | |||
| 2135 | new_vma->vm_start = addr; | 2148 | new_vma->vm_start = addr; |
| 2136 | new_vma->vm_end = addr + len; | 2149 | new_vma->vm_end = addr + len; |
| 2137 | new_vma->vm_pgoff = pgoff; | 2150 | new_vma->vm_pgoff = pgoff; |
| 2138 | if (new_vma->vm_file) | 2151 | if (new_vma->vm_file) { |
| 2139 | get_file(new_vma->vm_file); | 2152 | get_file(new_vma->vm_file); |
| 2153 | if (vma->vm_flags & VM_EXECUTABLE) | ||
| 2154 | added_exe_file_vma(mm); | ||
| 2155 | } | ||
| 2140 | if (new_vma->vm_ops && new_vma->vm_ops->open) | 2156 | if (new_vma->vm_ops && new_vma->vm_ops->open) |
| 2141 | new_vma->vm_ops->open(new_vma); | 2157 | new_vma->vm_ops->open(new_vma); |
| 2142 | vma_link(mm, new_vma, prev, rb_link, rb_parent); | 2158 | vma_link(mm, new_vma, prev, rb_link, rb_parent); |
diff --git a/mm/nommu.c b/mm/nommu.c index 1d32fe89d57b..ef8c62cec697 100644 --- a/mm/nommu.c +++ b/mm/nommu.c | |||
| @@ -966,8 +966,13 @@ unsigned long do_mmap_pgoff(struct file *file, | |||
| 966 | 966 | ||
| 967 | INIT_LIST_HEAD(&vma->anon_vma_node); | 967 | INIT_LIST_HEAD(&vma->anon_vma_node); |
| 968 | atomic_set(&vma->vm_usage, 1); | 968 | atomic_set(&vma->vm_usage, 1); |
| 969 | if (file) | 969 | if (file) { |
| 970 | get_file(file); | 970 | get_file(file); |
| 971 | if (vm_flags & VM_EXECUTABLE) { | ||
| 972 | added_exe_file_vma(current->mm); | ||
| 973 | vma->vm_mm = current->mm; | ||
| 974 | } | ||
| 975 | } | ||
| 971 | vma->vm_file = file; | 976 | vma->vm_file = file; |
| 972 | vma->vm_flags = vm_flags; | 977 | vma->vm_flags = vm_flags; |
| 973 | vma->vm_start = addr; | 978 | vma->vm_start = addr; |
| @@ -1022,8 +1027,11 @@ unsigned long do_mmap_pgoff(struct file *file, | |||
| 1022 | up_write(&nommu_vma_sem); | 1027 | up_write(&nommu_vma_sem); |
| 1023 | kfree(vml); | 1028 | kfree(vml); |
| 1024 | if (vma) { | 1029 | if (vma) { |
| 1025 | if (vma->vm_file) | 1030 | if (vma->vm_file) { |
| 1026 | fput(vma->vm_file); | 1031 | fput(vma->vm_file); |
| 1032 | if (vma->vm_flags & VM_EXECUTABLE) | ||
| 1033 | removed_exe_file_vma(vma->vm_mm); | ||
| 1034 | } | ||
| 1027 | kfree(vma); | 1035 | kfree(vma); |
| 1028 | } | 1036 | } |
| 1029 | return ret; | 1037 | return ret; |
| @@ -1053,7 +1061,7 @@ EXPORT_SYMBOL(do_mmap_pgoff); | |||
| 1053 | /* | 1061 | /* |
| 1054 | * handle mapping disposal for uClinux | 1062 | * handle mapping disposal for uClinux |
| 1055 | */ | 1063 | */ |
| 1056 | static void put_vma(struct vm_area_struct *vma) | 1064 | static void put_vma(struct mm_struct *mm, struct vm_area_struct *vma) |
| 1057 | { | 1065 | { |
| 1058 | if (vma) { | 1066 | if (vma) { |
| 1059 | down_write(&nommu_vma_sem); | 1067 | down_write(&nommu_vma_sem); |
| @@ -1075,8 +1083,11 @@ static void put_vma(struct vm_area_struct *vma) | |||
| 1075 | realalloc -= kobjsize(vma); | 1083 | realalloc -= kobjsize(vma); |
| 1076 | askedalloc -= sizeof(*vma); | 1084 | askedalloc -= sizeof(*vma); |
| 1077 | 1085 | ||
| 1078 | if (vma->vm_file) | 1086 | if (vma->vm_file) { |
| 1079 | fput(vma->vm_file); | 1087 | fput(vma->vm_file); |
| 1088 | if (vma->vm_flags & VM_EXECUTABLE) | ||
| 1089 | removed_exe_file_vma(mm); | ||
| 1090 | } | ||
| 1080 | kfree(vma); | 1091 | kfree(vma); |
| 1081 | } | 1092 | } |
| 1082 | 1093 | ||
| @@ -1113,7 +1124,7 @@ int do_munmap(struct mm_struct *mm, unsigned long addr, size_t len) | |||
| 1113 | found: | 1124 | found: |
| 1114 | vml = *parent; | 1125 | vml = *parent; |
| 1115 | 1126 | ||
| 1116 | put_vma(vml->vma); | 1127 | put_vma(mm, vml->vma); |
| 1117 | 1128 | ||
| 1118 | *parent = vml->next; | 1129 | *parent = vml->next; |
| 1119 | realalloc -= kobjsize(vml); | 1130 | realalloc -= kobjsize(vml); |
| @@ -1158,7 +1169,7 @@ void exit_mmap(struct mm_struct * mm) | |||
| 1158 | 1169 | ||
| 1159 | while ((tmp = mm->context.vmlist)) { | 1170 | while ((tmp = mm->context.vmlist)) { |
| 1160 | mm->context.vmlist = tmp->next; | 1171 | mm->context.vmlist = tmp->next; |
| 1161 | put_vma(tmp->vma); | 1172 | put_vma(mm, tmp->vma); |
| 1162 | 1173 | ||
| 1163 | realalloc -= kobjsize(tmp); | 1174 | realalloc -= kobjsize(tmp); |
| 1164 | askedalloc -= sizeof(*tmp); | 1175 | askedalloc -= sizeof(*tmp); |
