diff options
Diffstat (limited to 'fs/proc/base.c')
-rw-r--r-- | fs/proc/base.c | 75 |
1 files changed, 75 insertions, 0 deletions
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; |