aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorMatt Helsley <matthltc@us.ibm.com>2008-04-29 04:01:36 -0400
committerLinus Torvalds <torvalds@linux-foundation.org>2008-04-29 11:06:17 -0400
commit925d1c401fa6cfd0df5d2e37da8981494ccdec07 (patch)
tree4f3b7a09311cd99783b822350628125e44f9902d
parente93b4ea20adb20f1f1f07f10ba5d7dd739d2843e (diff)
procfs task exe symlink
The kernel implements readlink of /proc/pid/exe by getting the file from the first executable VMA. Then the path to the file is reconstructed and reported as the result. Because of the VMA walk the code is slightly different on nommu systems. This patch avoids separate /proc/pid/exe code on nommu systems. Instead of walking the VMAs to find the first executable file-backed VMA we store a reference to the exec'd file in the mm_struct. That reference would prevent the filesystem holding the executable file from being unmounted even after unmapping the VMAs. So we track the number of VM_EXECUTABLE VMAs and drop the new reference when the last one is unmapped. This avoids pinning the mounted filesystem. [akpm@linux-foundation.org: improve comments] [yamamoto@valinux.co.jp: fix dup_mmap] Signed-off-by: Matt Helsley <matthltc@us.ibm.com> Cc: Oleg Nesterov <oleg@tv-sign.ru> Cc: David Howells <dhowells@redhat.com> Cc:"Eric W. Biederman" <ebiederm@xmission.com> Cc: Christoph Hellwig <hch@lst.de> Cc: Al Viro <viro@zeniv.linux.org.uk> Cc: Hugh Dickins <hugh@veritas.com> Signed-off-by: YAMAMOTO Takashi <yamamoto@valinux.co.jp> Signed-off-by: Andrew Morton <akpm@linux-foundation.org> Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
-rw-r--r--fs/binfmt_flat.c3
-rw-r--r--fs/exec.c2
-rw-r--r--fs/proc/base.c75
-rw-r--r--fs/proc/internal.h1
-rw-r--r--fs/proc/task_mmu.c34
-rw-r--r--fs/proc/task_nommu.c34
-rw-r--r--include/linux/mm.h13
-rw-r--r--include/linux/mm_types.h6
-rw-r--r--include/linux/proc_fs.h20
-rw-r--r--kernel/fork.c3
-rw-r--r--mm/mmap.c24
-rw-r--r--mm/nommu.c23
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(&current->mm->mmap_sem); 533 down_write(&current->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(&current->mm->mmap_sem); 536 up_write(&current->mm->mmap_sem);
536 if (!textpos || textpos >= (unsigned long) -4096) { 537 if (!textpos || textpos >= (unsigned long) -4096) {
537 if (!textpos) 538 if (!textpos)
diff --git a/fs/exec.c b/fs/exec.c
index 711bc45d789c..a13883903ee9 100644
--- a/fs/exec.c
+++ b/fs/exec.c
@@ -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 */
1189void added_exe_file_vma(struct mm_struct *mm)
1190{
1191 mm->num_exe_file_vmas++;
1192}
1193
1194void 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
1204void 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
1214struct 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
1228void 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
1235static 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
1184static void *proc_pid_follow_link(struct dentry *dentry, struct nameidata *nd) 1259static 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
49extern void create_seq_entry(char *name, mode_t mode, 49extern void create_seq_entry(char *name, mode_t mode,
50 const struct file_operations *f); 50 const struct file_operations *f);
51extern int proc_exe_link(struct inode *, struct path *);
52extern int proc_tid_stat(struct seq_file *m, struct pid_namespace *ns, 51extern 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);
54extern int proc_tgid_stat(struct seq_file *m, struct pid_namespace *ns, 53extern 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
78int 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);
108out:
109 return result;
110}
111
112static void pad_len_spaces(struct seq_file *m, int len) 78static 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
106int 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);
136out:
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 *);
1066extern struct vm_area_struct *copy_vma(struct vm_area_struct **, 1066extern 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);
1068extern void exit_mmap(struct mm_struct *); 1068extern 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 */
1072extern void added_exe_file_vma(struct mm_struct *mm);
1073extern void removed_exe_file_vma(struct mm_struct *mm);
1074#else
1075static inline void added_exe_file_vma(struct mm_struct *mm)
1076{}
1077
1078static inline void removed_exe_file_vma(struct mm_struct *mm)
1079{}
1080#endif /* CONFIG_PROC_FS */
1081
1069extern int may_expand_vm(struct mm_struct *mm, unsigned long npages); 1082extern int may_expand_vm(struct mm_struct *mm, unsigned long npages);
1070extern int install_special_mapping(struct mm_struct *mm, 1083extern 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
10struct net; 10struct net;
11struct completion; 11struct 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);
206extern struct proc_dir_entry *proc_net_mkdir(struct net *net, const char *name, 205extern 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. */
210extern void set_mm_exe_file(struct mm_struct *mm, struct file *new_exe_file);
211extern struct file *get_mm_exe_file(struct mm_struct *mm);
212extern 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
263static inline void set_mm_exe_file(struct mm_struct *mm,
264 struct file *new_exe_file)
265{}
266
267static inline struct file *get_mm_exe_file(struct mm_struct *mm)
268{
269 return NULL;
270}
271
272static 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;
diff --git a/mm/mmap.c b/mm/mmap.c
index 677d184b0d42..fac66337da2a 100644
--- a/mm/mmap.c
+++ b/mm/mmap.c
@@ -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 */
1056static void put_vma(struct vm_area_struct *vma) 1064static 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);