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); |