diff options
Diffstat (limited to 'fs/proc')
-rw-r--r-- | fs/proc/array.c | 4 | ||||
-rw-r--r-- | fs/proc/base.c | 266 | ||||
-rw-r--r-- | fs/proc/generic.c | 13 | ||||
-rw-r--r-- | fs/proc/inode.c | 14 | ||||
-rw-r--r-- | fs/proc/internal.h | 2 | ||||
-rw-r--r-- | fs/proc/proc_misc.c | 10 | ||||
-rw-r--r-- | fs/proc/proc_sysctl.c | 7 | ||||
-rw-r--r-- | fs/proc/proc_tty.c | 3 | ||||
-rw-r--r-- | fs/proc/task_mmu.c | 17 | ||||
-rw-r--r-- | fs/proc/task_nommu.c | 7 |
10 files changed, 228 insertions, 115 deletions
diff --git a/fs/proc/array.c b/fs/proc/array.c index 07c9cdbcdcac..74f30e0c0381 100644 --- a/fs/proc/array.c +++ b/fs/proc/array.c | |||
@@ -410,9 +410,9 @@ static int do_task_stat(struct task_struct *task, char * buffer, int whole) | |||
410 | /* convert nsec -> ticks */ | 410 | /* convert nsec -> ticks */ |
411 | start_time = nsec_to_clock_t(start_time); | 411 | start_time = nsec_to_clock_t(start_time); |
412 | 412 | ||
413 | res = sprintf(buffer,"%d (%s) %c %d %d %d %d %d %lu %lu \ | 413 | res = sprintf(buffer,"%d (%s) %c %d %d %d %d %d %u %lu \ |
414 | %lu %lu %lu %lu %lu %ld %ld %ld %ld %d 0 %llu %lu %ld %lu %lu %lu %lu %lu \ | 414 | %lu %lu %lu %lu %lu %ld %ld %ld %ld %d 0 %llu %lu %ld %lu %lu %lu %lu %lu \ |
415 | %lu %lu %lu %lu %lu %lu %lu %lu %d %d %lu %lu %llu\n", | 415 | %lu %lu %lu %lu %lu %lu %lu %lu %d %d %u %u %llu\n", |
416 | task->pid, | 416 | task->pid, |
417 | tcomm, | 417 | tcomm, |
418 | state, | 418 | state, |
diff --git a/fs/proc/base.c b/fs/proc/base.c index ec158dd02b3a..3c41149dea88 100644 --- a/fs/proc/base.c +++ b/fs/proc/base.c | |||
@@ -61,9 +61,9 @@ | |||
61 | #include <linux/namei.h> | 61 | #include <linux/namei.h> |
62 | #include <linux/mnt_namespace.h> | 62 | #include <linux/mnt_namespace.h> |
63 | #include <linux/mm.h> | 63 | #include <linux/mm.h> |
64 | #include <linux/smp_lock.h> | ||
65 | #include <linux/rcupdate.h> | 64 | #include <linux/rcupdate.h> |
66 | #include <linux/kallsyms.h> | 65 | #include <linux/kallsyms.h> |
66 | #include <linux/module.h> | ||
67 | #include <linux/mount.h> | 67 | #include <linux/mount.h> |
68 | #include <linux/security.h> | 68 | #include <linux/security.h> |
69 | #include <linux/ptrace.h> | 69 | #include <linux/ptrace.h> |
@@ -90,8 +90,8 @@ | |||
90 | #define PROC_NUMBUF 13 | 90 | #define PROC_NUMBUF 13 |
91 | 91 | ||
92 | struct pid_entry { | 92 | struct pid_entry { |
93 | int len; | ||
94 | char *name; | 93 | char *name; |
94 | int len; | ||
95 | mode_t mode; | 95 | mode_t mode; |
96 | const struct inode_operations *iop; | 96 | const struct inode_operations *iop; |
97 | const struct file_operations *fop; | 97 | const struct file_operations *fop; |
@@ -99,8 +99,8 @@ struct pid_entry { | |||
99 | }; | 99 | }; |
100 | 100 | ||
101 | #define NOD(NAME, MODE, IOP, FOP, OP) { \ | 101 | #define NOD(NAME, MODE, IOP, FOP, OP) { \ |
102 | .len = sizeof(NAME) - 1, \ | ||
103 | .name = (NAME), \ | 102 | .name = (NAME), \ |
103 | .len = sizeof(NAME) - 1, \ | ||
104 | .mode = MODE, \ | 104 | .mode = MODE, \ |
105 | .iop = IOP, \ | 105 | .iop = IOP, \ |
106 | .fop = FOP, \ | 106 | .fop = FOP, \ |
@@ -123,6 +123,9 @@ struct pid_entry { | |||
123 | NULL, &proc_info_file_operations, \ | 123 | NULL, &proc_info_file_operations, \ |
124 | { .proc_read = &proc_##OTYPE } ) | 124 | { .proc_read = &proc_##OTYPE } ) |
125 | 125 | ||
126 | int maps_protect; | ||
127 | EXPORT_SYMBOL(maps_protect); | ||
128 | |||
126 | static struct fs_struct *get_fs_struct(struct task_struct *task) | 129 | static struct fs_struct *get_fs_struct(struct task_struct *task) |
127 | { | 130 | { |
128 | struct fs_struct *fs; | 131 | struct fs_struct *fs; |
@@ -275,17 +278,15 @@ static int proc_pid_auxv(struct task_struct *task, char *buffer) | |||
275 | */ | 278 | */ |
276 | static int proc_pid_wchan(struct task_struct *task, char *buffer) | 279 | static int proc_pid_wchan(struct task_struct *task, char *buffer) |
277 | { | 280 | { |
278 | char *modname; | 281 | unsigned long wchan; |
279 | const char *sym_name; | 282 | char symname[KSYM_NAME_LEN+1]; |
280 | unsigned long wchan, size, offset; | ||
281 | char namebuf[KSYM_NAME_LEN+1]; | ||
282 | 283 | ||
283 | wchan = get_wchan(task); | 284 | wchan = get_wchan(task); |
284 | 285 | ||
285 | sym_name = kallsyms_lookup(wchan, &size, &offset, &modname, namebuf); | 286 | if (lookup_symbol_name(wchan, symname) < 0) |
286 | if (sym_name) | 287 | return sprintf(buffer, "%lu", wchan); |
287 | return sprintf(buffer, "%s", sym_name); | 288 | else |
288 | return sprintf(buffer, "%lu", wchan); | 289 | return sprintf(buffer, "%s", symname); |
289 | } | 290 | } |
290 | #endif /* CONFIG_KALLSYMS */ | 291 | #endif /* CONFIG_KALLSYMS */ |
291 | 292 | ||
@@ -310,7 +311,9 @@ static int proc_oom_score(struct task_struct *task, char *buffer) | |||
310 | struct timespec uptime; | 311 | struct timespec uptime; |
311 | 312 | ||
312 | do_posix_clock_monotonic_gettime(&uptime); | 313 | do_posix_clock_monotonic_gettime(&uptime); |
314 | read_lock(&tasklist_lock); | ||
313 | points = badness(task, uptime.tv_sec); | 315 | points = badness(task, uptime.tv_sec); |
316 | read_unlock(&tasklist_lock); | ||
314 | return sprintf(buffer, "%lu\n", points); | 317 | return sprintf(buffer, "%lu\n", points); |
315 | } | 318 | } |
316 | 319 | ||
@@ -344,11 +347,8 @@ static int proc_setattr(struct dentry *dentry, struct iattr *attr) | |||
344 | return -EPERM; | 347 | return -EPERM; |
345 | 348 | ||
346 | error = inode_change_ok(inode, attr); | 349 | error = inode_change_ok(inode, attr); |
347 | if (!error) { | 350 | if (!error) |
348 | error = security_inode_setattr(dentry, attr); | 351 | error = inode_setattr(inode, attr); |
349 | if (!error) | ||
350 | error = inode_setattr(inode, attr); | ||
351 | } | ||
352 | return error; | 352 | return error; |
353 | } | 353 | } |
354 | 354 | ||
@@ -660,7 +660,6 @@ static ssize_t oom_adjust_read(struct file *file, char __user *buf, | |||
660 | char buffer[PROC_NUMBUF]; | 660 | char buffer[PROC_NUMBUF]; |
661 | size_t len; | 661 | size_t len; |
662 | int oom_adjust; | 662 | int oom_adjust; |
663 | loff_t __ppos = *ppos; | ||
664 | 663 | ||
665 | if (!task) | 664 | if (!task) |
666 | return -ESRCH; | 665 | return -ESRCH; |
@@ -668,14 +667,8 @@ static ssize_t oom_adjust_read(struct file *file, char __user *buf, | |||
668 | put_task_struct(task); | 667 | put_task_struct(task); |
669 | 668 | ||
670 | len = snprintf(buffer, sizeof(buffer), "%i\n", oom_adjust); | 669 | len = snprintf(buffer, sizeof(buffer), "%i\n", oom_adjust); |
671 | if (__ppos >= len) | 670 | |
672 | return 0; | 671 | return simple_read_from_buffer(buf, count, ppos, buffer, len); |
673 | if (count > len-__ppos) | ||
674 | count = len-__ppos; | ||
675 | if (copy_to_user(buf, buffer + __ppos, count)) | ||
676 | return -EFAULT; | ||
677 | *ppos = __ppos + count; | ||
678 | return count; | ||
679 | } | 672 | } |
680 | 673 | ||
681 | static ssize_t oom_adjust_write(struct file *file, const char __user *buf, | 674 | static ssize_t oom_adjust_write(struct file *file, const char __user *buf, |
@@ -823,7 +816,6 @@ static ssize_t seccomp_read(struct file *file, char __user *buf, | |||
823 | { | 816 | { |
824 | struct task_struct *tsk = get_proc_task(file->f_dentry->d_inode); | 817 | struct task_struct *tsk = get_proc_task(file->f_dentry->d_inode); |
825 | char __buf[20]; | 818 | char __buf[20]; |
826 | loff_t __ppos = *ppos; | ||
827 | size_t len; | 819 | size_t len; |
828 | 820 | ||
829 | if (!tsk) | 821 | if (!tsk) |
@@ -831,14 +823,8 @@ static ssize_t seccomp_read(struct file *file, char __user *buf, | |||
831 | /* no need to print the trailing zero, so use only len */ | 823 | /* no need to print the trailing zero, so use only len */ |
832 | len = sprintf(__buf, "%u\n", tsk->seccomp.mode); | 824 | len = sprintf(__buf, "%u\n", tsk->seccomp.mode); |
833 | put_task_struct(tsk); | 825 | put_task_struct(tsk); |
834 | if (__ppos >= len) | 826 | |
835 | return 0; | 827 | return simple_read_from_buffer(buf, count, ppos, __buf, len); |
836 | if (count > len - __ppos) | ||
837 | count = len - __ppos; | ||
838 | if (copy_to_user(buf, __buf + __ppos, count)) | ||
839 | return -EFAULT; | ||
840 | *ppos = __ppos + count; | ||
841 | return count; | ||
842 | } | 828 | } |
843 | 829 | ||
844 | static ssize_t seccomp_write(struct file *file, const char __user *buf, | 830 | static ssize_t seccomp_write(struct file *file, const char __user *buf, |
@@ -897,7 +883,6 @@ static ssize_t proc_fault_inject_read(struct file * file, char __user * buf, | |||
897 | char buffer[PROC_NUMBUF]; | 883 | char buffer[PROC_NUMBUF]; |
898 | size_t len; | 884 | size_t len; |
899 | int make_it_fail; | 885 | int make_it_fail; |
900 | loff_t __ppos = *ppos; | ||
901 | 886 | ||
902 | if (!task) | 887 | if (!task) |
903 | return -ESRCH; | 888 | return -ESRCH; |
@@ -905,14 +890,8 @@ static ssize_t proc_fault_inject_read(struct file * file, char __user * buf, | |||
905 | put_task_struct(task); | 890 | put_task_struct(task); |
906 | 891 | ||
907 | len = snprintf(buffer, sizeof(buffer), "%i\n", make_it_fail); | 892 | len = snprintf(buffer, sizeof(buffer), "%i\n", make_it_fail); |
908 | if (__ppos >= len) | 893 | |
909 | return 0; | 894 | return simple_read_from_buffer(buf, count, ppos, buffer, len); |
910 | if (count > len-__ppos) | ||
911 | count = len-__ppos; | ||
912 | if (copy_to_user(buf, buffer + __ppos, count)) | ||
913 | return -EFAULT; | ||
914 | *ppos = __ppos + count; | ||
915 | return count; | ||
916 | } | 895 | } |
917 | 896 | ||
918 | static ssize_t proc_fault_inject_write(struct file * file, | 897 | static ssize_t proc_fault_inject_write(struct file * file, |
@@ -975,7 +954,7 @@ static int do_proc_readlink(struct dentry *dentry, struct vfsmount *mnt, | |||
975 | 954 | ||
976 | if (!tmp) | 955 | if (!tmp) |
977 | return -ENOMEM; | 956 | return -ENOMEM; |
978 | 957 | ||
979 | inode = dentry->d_inode; | 958 | inode = dentry->d_inode; |
980 | path = d_path(dentry, mnt, tmp, PAGE_SIZE); | 959 | path = d_path(dentry, mnt, tmp, PAGE_SIZE); |
981 | len = PTR_ERR(path); | 960 | len = PTR_ERR(path); |
@@ -1155,7 +1134,8 @@ static struct dentry_operations pid_dentry_operations = | |||
1155 | 1134 | ||
1156 | /* Lookups */ | 1135 | /* Lookups */ |
1157 | 1136 | ||
1158 | typedef struct dentry *instantiate_t(struct inode *, struct dentry *, struct task_struct *, void *); | 1137 | typedef struct dentry *instantiate_t(struct inode *, struct dentry *, |
1138 | struct task_struct *, const void *); | ||
1159 | 1139 | ||
1160 | /* | 1140 | /* |
1161 | * Fill a directory entry. | 1141 | * Fill a directory entry. |
@@ -1171,7 +1151,7 @@ typedef struct dentry *instantiate_t(struct inode *, struct dentry *, struct tas | |||
1171 | */ | 1151 | */ |
1172 | static int proc_fill_cache(struct file *filp, void *dirent, filldir_t filldir, | 1152 | static int proc_fill_cache(struct file *filp, void *dirent, filldir_t filldir, |
1173 | char *name, int len, | 1153 | char *name, int len, |
1174 | instantiate_t instantiate, struct task_struct *task, void *ptr) | 1154 | instantiate_t instantiate, struct task_struct *task, const void *ptr) |
1175 | { | 1155 | { |
1176 | struct dentry *child, *dir = filp->f_path.dentry; | 1156 | struct dentry *child, *dir = filp->f_path.dentry; |
1177 | struct inode *inode; | 1157 | struct inode *inode; |
@@ -1233,7 +1213,10 @@ out: | |||
1233 | return ~0U; | 1213 | return ~0U; |
1234 | } | 1214 | } |
1235 | 1215 | ||
1236 | static int proc_fd_link(struct inode *inode, struct dentry **dentry, struct vfsmount **mnt) | 1216 | #define PROC_FDINFO_MAX 64 |
1217 | |||
1218 | static int proc_fd_info(struct inode *inode, struct dentry **dentry, | ||
1219 | struct vfsmount **mnt, char *info) | ||
1237 | { | 1220 | { |
1238 | struct task_struct *task = get_proc_task(inode); | 1221 | struct task_struct *task = get_proc_task(inode); |
1239 | struct files_struct *files = NULL; | 1222 | struct files_struct *files = NULL; |
@@ -1252,8 +1235,16 @@ static int proc_fd_link(struct inode *inode, struct dentry **dentry, struct vfsm | |||
1252 | spin_lock(&files->file_lock); | 1235 | spin_lock(&files->file_lock); |
1253 | file = fcheck_files(files, fd); | 1236 | file = fcheck_files(files, fd); |
1254 | if (file) { | 1237 | if (file) { |
1255 | *mnt = mntget(file->f_path.mnt); | 1238 | if (mnt) |
1256 | *dentry = dget(file->f_path.dentry); | 1239 | *mnt = mntget(file->f_path.mnt); |
1240 | if (dentry) | ||
1241 | *dentry = dget(file->f_path.dentry); | ||
1242 | if (info) | ||
1243 | snprintf(info, PROC_FDINFO_MAX, | ||
1244 | "pos:\t%lli\n" | ||
1245 | "flags:\t0%o\n", | ||
1246 | (long long) file->f_pos, | ||
1247 | file->f_flags); | ||
1257 | spin_unlock(&files->file_lock); | 1248 | spin_unlock(&files->file_lock); |
1258 | put_files_struct(files); | 1249 | put_files_struct(files); |
1259 | return 0; | 1250 | return 0; |
@@ -1264,6 +1255,12 @@ static int proc_fd_link(struct inode *inode, struct dentry **dentry, struct vfsm | |||
1264 | return -ENOENT; | 1255 | return -ENOENT; |
1265 | } | 1256 | } |
1266 | 1257 | ||
1258 | static int proc_fd_link(struct inode *inode, struct dentry **dentry, | ||
1259 | struct vfsmount **mnt) | ||
1260 | { | ||
1261 | return proc_fd_info(inode, dentry, mnt, NULL); | ||
1262 | } | ||
1263 | |||
1267 | static int tid_fd_revalidate(struct dentry *dentry, struct nameidata *nd) | 1264 | static int tid_fd_revalidate(struct dentry *dentry, struct nameidata *nd) |
1268 | { | 1265 | { |
1269 | struct inode *inode = dentry->d_inode; | 1266 | struct inode *inode = dentry->d_inode; |
@@ -1306,9 +1303,9 @@ static struct dentry_operations tid_fd_dentry_operations = | |||
1306 | }; | 1303 | }; |
1307 | 1304 | ||
1308 | static struct dentry *proc_fd_instantiate(struct inode *dir, | 1305 | static struct dentry *proc_fd_instantiate(struct inode *dir, |
1309 | struct dentry *dentry, struct task_struct *task, void *ptr) | 1306 | struct dentry *dentry, struct task_struct *task, const void *ptr) |
1310 | { | 1307 | { |
1311 | unsigned fd = *(unsigned *)ptr; | 1308 | unsigned fd = *(const unsigned *)ptr; |
1312 | struct file *file; | 1309 | struct file *file; |
1313 | struct files_struct *files; | 1310 | struct files_struct *files; |
1314 | struct inode *inode; | 1311 | struct inode *inode; |
@@ -1359,7 +1356,9 @@ out_iput: | |||
1359 | goto out; | 1356 | goto out; |
1360 | } | 1357 | } |
1361 | 1358 | ||
1362 | static struct dentry *proc_lookupfd(struct inode * dir, struct dentry * dentry, struct nameidata *nd) | 1359 | static struct dentry *proc_lookupfd_common(struct inode *dir, |
1360 | struct dentry *dentry, | ||
1361 | instantiate_t instantiate) | ||
1363 | { | 1362 | { |
1364 | struct task_struct *task = get_proc_task(dir); | 1363 | struct task_struct *task = get_proc_task(dir); |
1365 | unsigned fd = name_to_int(dentry); | 1364 | unsigned fd = name_to_int(dentry); |
@@ -1370,23 +1369,15 @@ static struct dentry *proc_lookupfd(struct inode * dir, struct dentry * dentry, | |||
1370 | if (fd == ~0U) | 1369 | if (fd == ~0U) |
1371 | goto out; | 1370 | goto out; |
1372 | 1371 | ||
1373 | result = proc_fd_instantiate(dir, dentry, task, &fd); | 1372 | result = instantiate(dir, dentry, task, &fd); |
1374 | out: | 1373 | out: |
1375 | put_task_struct(task); | 1374 | put_task_struct(task); |
1376 | out_no_task: | 1375 | out_no_task: |
1377 | return result; | 1376 | return result; |
1378 | } | 1377 | } |
1379 | 1378 | ||
1380 | static int proc_fd_fill_cache(struct file *filp, void *dirent, filldir_t filldir, | 1379 | static int proc_readfd_common(struct file * filp, void * dirent, |
1381 | struct task_struct *task, int fd) | 1380 | filldir_t filldir, instantiate_t instantiate) |
1382 | { | ||
1383 | char name[PROC_NUMBUF]; | ||
1384 | int len = snprintf(name, sizeof(name), "%d", fd); | ||
1385 | return proc_fill_cache(filp, dirent, filldir, name, len, | ||
1386 | proc_fd_instantiate, task, &fd); | ||
1387 | } | ||
1388 | |||
1389 | static int proc_readfd(struct file * filp, void * dirent, filldir_t filldir) | ||
1390 | { | 1381 | { |
1391 | struct dentry *dentry = filp->f_path.dentry; | 1382 | struct dentry *dentry = filp->f_path.dentry; |
1392 | struct inode *inode = dentry->d_inode; | 1383 | struct inode *inode = dentry->d_inode; |
@@ -1422,12 +1413,17 @@ static int proc_readfd(struct file * filp, void * dirent, filldir_t filldir) | |||
1422 | for (fd = filp->f_pos-2; | 1413 | for (fd = filp->f_pos-2; |
1423 | fd < fdt->max_fds; | 1414 | fd < fdt->max_fds; |
1424 | fd++, filp->f_pos++) { | 1415 | fd++, filp->f_pos++) { |
1416 | char name[PROC_NUMBUF]; | ||
1417 | int len; | ||
1425 | 1418 | ||
1426 | if (!fcheck_files(files, fd)) | 1419 | if (!fcheck_files(files, fd)) |
1427 | continue; | 1420 | continue; |
1428 | rcu_read_unlock(); | 1421 | rcu_read_unlock(); |
1429 | 1422 | ||
1430 | if (proc_fd_fill_cache(filp, dirent, filldir, p, fd) < 0) { | 1423 | len = snprintf(name, sizeof(name), "%d", fd); |
1424 | if (proc_fill_cache(filp, dirent, filldir, | ||
1425 | name, len, instantiate, | ||
1426 | p, &fd) < 0) { | ||
1431 | rcu_read_lock(); | 1427 | rcu_read_lock(); |
1432 | break; | 1428 | break; |
1433 | } | 1429 | } |
@@ -1442,23 +1438,119 @@ out_no_task: | |||
1442 | return retval; | 1438 | return retval; |
1443 | } | 1439 | } |
1444 | 1440 | ||
1441 | static struct dentry *proc_lookupfd(struct inode *dir, struct dentry *dentry, | ||
1442 | struct nameidata *nd) | ||
1443 | { | ||
1444 | return proc_lookupfd_common(dir, dentry, proc_fd_instantiate); | ||
1445 | } | ||
1446 | |||
1447 | static int proc_readfd(struct file *filp, void *dirent, filldir_t filldir) | ||
1448 | { | ||
1449 | return proc_readfd_common(filp, dirent, filldir, proc_fd_instantiate); | ||
1450 | } | ||
1451 | |||
1452 | static ssize_t proc_fdinfo_read(struct file *file, char __user *buf, | ||
1453 | size_t len, loff_t *ppos) | ||
1454 | { | ||
1455 | char tmp[PROC_FDINFO_MAX]; | ||
1456 | int err = proc_fd_info(file->f_path.dentry->d_inode, NULL, NULL, tmp); | ||
1457 | if (!err) | ||
1458 | err = simple_read_from_buffer(buf, len, ppos, tmp, strlen(tmp)); | ||
1459 | return err; | ||
1460 | } | ||
1461 | |||
1462 | static const struct file_operations proc_fdinfo_file_operations = { | ||
1463 | .open = nonseekable_open, | ||
1464 | .read = proc_fdinfo_read, | ||
1465 | }; | ||
1466 | |||
1445 | static const struct file_operations proc_fd_operations = { | 1467 | static const struct file_operations proc_fd_operations = { |
1446 | .read = generic_read_dir, | 1468 | .read = generic_read_dir, |
1447 | .readdir = proc_readfd, | 1469 | .readdir = proc_readfd, |
1448 | }; | 1470 | }; |
1449 | 1471 | ||
1450 | /* | 1472 | /* |
1473 | * /proc/pid/fd needs a special permission handler so that a process can still | ||
1474 | * access /proc/self/fd after it has executed a setuid(). | ||
1475 | */ | ||
1476 | static int proc_fd_permission(struct inode *inode, int mask, | ||
1477 | struct nameidata *nd) | ||
1478 | { | ||
1479 | int rv; | ||
1480 | |||
1481 | rv = generic_permission(inode, mask, NULL); | ||
1482 | if (rv == 0) | ||
1483 | return 0; | ||
1484 | if (task_pid(current) == proc_pid(inode)) | ||
1485 | rv = 0; | ||
1486 | return rv; | ||
1487 | } | ||
1488 | |||
1489 | /* | ||
1451 | * proc directories can do almost nothing.. | 1490 | * proc directories can do almost nothing.. |
1452 | */ | 1491 | */ |
1453 | static const struct inode_operations proc_fd_inode_operations = { | 1492 | static const struct inode_operations proc_fd_inode_operations = { |
1454 | .lookup = proc_lookupfd, | 1493 | .lookup = proc_lookupfd, |
1494 | .permission = proc_fd_permission, | ||
1455 | .setattr = proc_setattr, | 1495 | .setattr = proc_setattr, |
1456 | }; | 1496 | }; |
1457 | 1497 | ||
1498 | static struct dentry *proc_fdinfo_instantiate(struct inode *dir, | ||
1499 | struct dentry *dentry, struct task_struct *task, const void *ptr) | ||
1500 | { | ||
1501 | unsigned fd = *(unsigned *)ptr; | ||
1502 | struct inode *inode; | ||
1503 | struct proc_inode *ei; | ||
1504 | struct dentry *error = ERR_PTR(-ENOENT); | ||
1505 | |||
1506 | inode = proc_pid_make_inode(dir->i_sb, task); | ||
1507 | if (!inode) | ||
1508 | goto out; | ||
1509 | ei = PROC_I(inode); | ||
1510 | ei->fd = fd; | ||
1511 | inode->i_mode = S_IFREG | S_IRUSR; | ||
1512 | inode->i_fop = &proc_fdinfo_file_operations; | ||
1513 | dentry->d_op = &tid_fd_dentry_operations; | ||
1514 | d_add(dentry, inode); | ||
1515 | /* Close the race of the process dying before we return the dentry */ | ||
1516 | if (tid_fd_revalidate(dentry, NULL)) | ||
1517 | error = NULL; | ||
1518 | |||
1519 | out: | ||
1520 | return error; | ||
1521 | } | ||
1522 | |||
1523 | static struct dentry *proc_lookupfdinfo(struct inode *dir, | ||
1524 | struct dentry *dentry, | ||
1525 | struct nameidata *nd) | ||
1526 | { | ||
1527 | return proc_lookupfd_common(dir, dentry, proc_fdinfo_instantiate); | ||
1528 | } | ||
1529 | |||
1530 | static int proc_readfdinfo(struct file *filp, void *dirent, filldir_t filldir) | ||
1531 | { | ||
1532 | return proc_readfd_common(filp, dirent, filldir, | ||
1533 | proc_fdinfo_instantiate); | ||
1534 | } | ||
1535 | |||
1536 | static const struct file_operations proc_fdinfo_operations = { | ||
1537 | .read = generic_read_dir, | ||
1538 | .readdir = proc_readfdinfo, | ||
1539 | }; | ||
1540 | |||
1541 | /* | ||
1542 | * proc directories can do almost nothing.. | ||
1543 | */ | ||
1544 | static const struct inode_operations proc_fdinfo_inode_operations = { | ||
1545 | .lookup = proc_lookupfdinfo, | ||
1546 | .setattr = proc_setattr, | ||
1547 | }; | ||
1548 | |||
1549 | |||
1458 | static struct dentry *proc_pident_instantiate(struct inode *dir, | 1550 | static struct dentry *proc_pident_instantiate(struct inode *dir, |
1459 | struct dentry *dentry, struct task_struct *task, void *ptr) | 1551 | struct dentry *dentry, struct task_struct *task, const void *ptr) |
1460 | { | 1552 | { |
1461 | struct pid_entry *p = ptr; | 1553 | const struct pid_entry *p = ptr; |
1462 | struct inode *inode; | 1554 | struct inode *inode; |
1463 | struct proc_inode *ei; | 1555 | struct proc_inode *ei; |
1464 | struct dentry *error = ERR_PTR(-EINVAL); | 1556 | struct dentry *error = ERR_PTR(-EINVAL); |
@@ -1487,13 +1579,13 @@ out: | |||
1487 | 1579 | ||
1488 | static struct dentry *proc_pident_lookup(struct inode *dir, | 1580 | static struct dentry *proc_pident_lookup(struct inode *dir, |
1489 | struct dentry *dentry, | 1581 | struct dentry *dentry, |
1490 | struct pid_entry *ents, | 1582 | const struct pid_entry *ents, |
1491 | unsigned int nents) | 1583 | unsigned int nents) |
1492 | { | 1584 | { |
1493 | struct inode *inode; | 1585 | struct inode *inode; |
1494 | struct dentry *error; | 1586 | struct dentry *error; |
1495 | struct task_struct *task = get_proc_task(dir); | 1587 | struct task_struct *task = get_proc_task(dir); |
1496 | struct pid_entry *p, *last; | 1588 | const struct pid_entry *p, *last; |
1497 | 1589 | ||
1498 | error = ERR_PTR(-ENOENT); | 1590 | error = ERR_PTR(-ENOENT); |
1499 | inode = NULL; | 1591 | inode = NULL; |
@@ -1522,8 +1614,8 @@ out_no_task: | |||
1522 | return error; | 1614 | return error; |
1523 | } | 1615 | } |
1524 | 1616 | ||
1525 | static int proc_pident_fill_cache(struct file *filp, void *dirent, filldir_t filldir, | 1617 | static int proc_pident_fill_cache(struct file *filp, void *dirent, |
1526 | struct task_struct *task, struct pid_entry *p) | 1618 | filldir_t filldir, struct task_struct *task, const struct pid_entry *p) |
1527 | { | 1619 | { |
1528 | return proc_fill_cache(filp, dirent, filldir, p->name, p->len, | 1620 | return proc_fill_cache(filp, dirent, filldir, p->name, p->len, |
1529 | proc_pident_instantiate, task, p); | 1621 | proc_pident_instantiate, task, p); |
@@ -1531,14 +1623,14 @@ static int proc_pident_fill_cache(struct file *filp, void *dirent, filldir_t fil | |||
1531 | 1623 | ||
1532 | static int proc_pident_readdir(struct file *filp, | 1624 | static int proc_pident_readdir(struct file *filp, |
1533 | void *dirent, filldir_t filldir, | 1625 | void *dirent, filldir_t filldir, |
1534 | struct pid_entry *ents, unsigned int nents) | 1626 | const struct pid_entry *ents, unsigned int nents) |
1535 | { | 1627 | { |
1536 | int i; | 1628 | int i; |
1537 | int pid; | 1629 | int pid; |
1538 | struct dentry *dentry = filp->f_path.dentry; | 1630 | struct dentry *dentry = filp->f_path.dentry; |
1539 | struct inode *inode = dentry->d_inode; | 1631 | struct inode *inode = dentry->d_inode; |
1540 | struct task_struct *task = get_proc_task(inode); | 1632 | struct task_struct *task = get_proc_task(inode); |
1541 | struct pid_entry *p, *last; | 1633 | const struct pid_entry *p, *last; |
1542 | ino_t ino; | 1634 | ino_t ino; |
1543 | int ret; | 1635 | int ret; |
1544 | 1636 | ||
@@ -1653,7 +1745,7 @@ static const struct file_operations proc_pid_attr_operations = { | |||
1653 | .write = proc_pid_attr_write, | 1745 | .write = proc_pid_attr_write, |
1654 | }; | 1746 | }; |
1655 | 1747 | ||
1656 | static struct pid_entry attr_dir_stuff[] = { | 1748 | static const struct pid_entry attr_dir_stuff[] = { |
1657 | REG("current", S_IRUGO|S_IWUGO, pid_attr), | 1749 | REG("current", S_IRUGO|S_IWUGO, pid_attr), |
1658 | REG("prev", S_IRUGO, pid_attr), | 1750 | REG("prev", S_IRUGO, pid_attr), |
1659 | REG("exec", S_IRUGO|S_IWUGO, pid_attr), | 1751 | REG("exec", S_IRUGO|S_IWUGO, pid_attr), |
@@ -1719,7 +1811,7 @@ static const struct inode_operations proc_self_inode_operations = { | |||
1719 | * that properly belong to the /proc filesystem, as they describe | 1811 | * that properly belong to the /proc filesystem, as they describe |
1720 | * describe something that is process related. | 1812 | * describe something that is process related. |
1721 | */ | 1813 | */ |
1722 | static struct pid_entry proc_base_stuff[] = { | 1814 | static const struct pid_entry proc_base_stuff[] = { |
1723 | NOD("self", S_IFLNK|S_IRWXUGO, | 1815 | NOD("self", S_IFLNK|S_IRWXUGO, |
1724 | &proc_self_inode_operations, NULL, {}), | 1816 | &proc_self_inode_operations, NULL, {}), |
1725 | }; | 1817 | }; |
@@ -1748,9 +1840,9 @@ static struct dentry_operations proc_base_dentry_operations = | |||
1748 | }; | 1840 | }; |
1749 | 1841 | ||
1750 | static struct dentry *proc_base_instantiate(struct inode *dir, | 1842 | static struct dentry *proc_base_instantiate(struct inode *dir, |
1751 | struct dentry *dentry, struct task_struct *task, void *ptr) | 1843 | struct dentry *dentry, struct task_struct *task, const void *ptr) |
1752 | { | 1844 | { |
1753 | struct pid_entry *p = ptr; | 1845 | const struct pid_entry *p = ptr; |
1754 | struct inode *inode; | 1846 | struct inode *inode; |
1755 | struct proc_inode *ei; | 1847 | struct proc_inode *ei; |
1756 | struct dentry *error = ERR_PTR(-EINVAL); | 1848 | struct dentry *error = ERR_PTR(-EINVAL); |
@@ -1798,7 +1890,7 @@ static struct dentry *proc_base_lookup(struct inode *dir, struct dentry *dentry) | |||
1798 | { | 1890 | { |
1799 | struct dentry *error; | 1891 | struct dentry *error; |
1800 | struct task_struct *task = get_proc_task(dir); | 1892 | struct task_struct *task = get_proc_task(dir); |
1801 | struct pid_entry *p, *last; | 1893 | const struct pid_entry *p, *last; |
1802 | 1894 | ||
1803 | error = ERR_PTR(-ENOENT); | 1895 | error = ERR_PTR(-ENOENT); |
1804 | 1896 | ||
@@ -1824,8 +1916,8 @@ out_no_task: | |||
1824 | return error; | 1916 | return error; |
1825 | } | 1917 | } |
1826 | 1918 | ||
1827 | static int proc_base_fill_cache(struct file *filp, void *dirent, filldir_t filldir, | 1919 | static int proc_base_fill_cache(struct file *filp, void *dirent, |
1828 | struct task_struct *task, struct pid_entry *p) | 1920 | filldir_t filldir, struct task_struct *task, const struct pid_entry *p) |
1829 | { | 1921 | { |
1830 | return proc_fill_cache(filp, dirent, filldir, p->name, p->len, | 1922 | return proc_fill_cache(filp, dirent, filldir, p->name, p->len, |
1831 | proc_base_instantiate, task, p); | 1923 | proc_base_instantiate, task, p); |
@@ -1862,9 +1954,10 @@ static int proc_pid_io_accounting(struct task_struct *task, char *buffer) | |||
1862 | static const struct file_operations proc_task_operations; | 1954 | static const struct file_operations proc_task_operations; |
1863 | static const struct inode_operations proc_task_inode_operations; | 1955 | static const struct inode_operations proc_task_inode_operations; |
1864 | 1956 | ||
1865 | static struct pid_entry tgid_base_stuff[] = { | 1957 | static const struct pid_entry tgid_base_stuff[] = { |
1866 | DIR("task", S_IRUGO|S_IXUGO, task), | 1958 | DIR("task", S_IRUGO|S_IXUGO, task), |
1867 | DIR("fd", S_IRUSR|S_IXUSR, fd), | 1959 | DIR("fd", S_IRUSR|S_IXUSR, fd), |
1960 | DIR("fdinfo", S_IRUSR|S_IXUSR, fdinfo), | ||
1868 | INF("environ", S_IRUSR, pid_environ), | 1961 | INF("environ", S_IRUSR, pid_environ), |
1869 | INF("auxv", S_IRUSR, pid_auxv), | 1962 | INF("auxv", S_IRUSR, pid_auxv), |
1870 | INF("status", S_IRUGO, pid_status), | 1963 | INF("status", S_IRUGO, pid_status), |
@@ -2005,7 +2098,7 @@ out: | |||
2005 | 2098 | ||
2006 | static struct dentry *proc_pid_instantiate(struct inode *dir, | 2099 | static struct dentry *proc_pid_instantiate(struct inode *dir, |
2007 | struct dentry * dentry, | 2100 | struct dentry * dentry, |
2008 | struct task_struct *task, void *ptr) | 2101 | struct task_struct *task, const void *ptr) |
2009 | { | 2102 | { |
2010 | struct dentry *error = ERR_PTR(-ENOENT); | 2103 | struct dentry *error = ERR_PTR(-ENOENT); |
2011 | struct inode *inode; | 2104 | struct inode *inode; |
@@ -2018,7 +2111,7 @@ static struct dentry *proc_pid_instantiate(struct inode *dir, | |||
2018 | inode->i_op = &proc_tgid_base_inode_operations; | 2111 | inode->i_op = &proc_tgid_base_inode_operations; |
2019 | inode->i_fop = &proc_tgid_base_operations; | 2112 | inode->i_fop = &proc_tgid_base_operations; |
2020 | inode->i_flags|=S_IMMUTABLE; | 2113 | inode->i_flags|=S_IMMUTABLE; |
2021 | inode->i_nlink = 4; | 2114 | inode->i_nlink = 5; |
2022 | #ifdef CONFIG_SECURITY | 2115 | #ifdef CONFIG_SECURITY |
2023 | inode->i_nlink += 1; | 2116 | inode->i_nlink += 1; |
2024 | #endif | 2117 | #endif |
@@ -2120,7 +2213,7 @@ int proc_pid_readdir(struct file * filp, void * dirent, filldir_t filldir) | |||
2120 | goto out_no_task; | 2213 | goto out_no_task; |
2121 | 2214 | ||
2122 | for (; nr < ARRAY_SIZE(proc_base_stuff); filp->f_pos++, nr++) { | 2215 | for (; nr < ARRAY_SIZE(proc_base_stuff); filp->f_pos++, nr++) { |
2123 | struct pid_entry *p = &proc_base_stuff[nr]; | 2216 | const struct pid_entry *p = &proc_base_stuff[nr]; |
2124 | if (proc_base_fill_cache(filp, dirent, filldir, reaper, p) < 0) | 2217 | if (proc_base_fill_cache(filp, dirent, filldir, reaper, p) < 0) |
2125 | goto out; | 2218 | goto out; |
2126 | } | 2219 | } |
@@ -2146,8 +2239,9 @@ out_no_task: | |||
2146 | /* | 2239 | /* |
2147 | * Tasks | 2240 | * Tasks |
2148 | */ | 2241 | */ |
2149 | static struct pid_entry tid_base_stuff[] = { | 2242 | static const struct pid_entry tid_base_stuff[] = { |
2150 | DIR("fd", S_IRUSR|S_IXUSR, fd), | 2243 | DIR("fd", S_IRUSR|S_IXUSR, fd), |
2244 | DIR("fdinfo", S_IRUSR|S_IXUSR, fdinfo), | ||
2151 | INF("environ", S_IRUSR, pid_environ), | 2245 | INF("environ", S_IRUSR, pid_environ), |
2152 | INF("auxv", S_IRUSR, pid_auxv), | 2246 | INF("auxv", S_IRUSR, pid_auxv), |
2153 | INF("status", S_IRUGO, pid_status), | 2247 | INF("status", S_IRUGO, pid_status), |
@@ -2216,7 +2310,7 @@ static const struct inode_operations proc_tid_base_inode_operations = { | |||
2216 | }; | 2310 | }; |
2217 | 2311 | ||
2218 | static struct dentry *proc_task_instantiate(struct inode *dir, | 2312 | static struct dentry *proc_task_instantiate(struct inode *dir, |
2219 | struct dentry *dentry, struct task_struct *task, void *ptr) | 2313 | struct dentry *dentry, struct task_struct *task, const void *ptr) |
2220 | { | 2314 | { |
2221 | struct dentry *error = ERR_PTR(-ENOENT); | 2315 | struct dentry *error = ERR_PTR(-ENOENT); |
2222 | struct inode *inode; | 2316 | struct inode *inode; |
@@ -2228,7 +2322,7 @@ static struct dentry *proc_task_instantiate(struct inode *dir, | |||
2228 | inode->i_op = &proc_tid_base_inode_operations; | 2322 | inode->i_op = &proc_tid_base_inode_operations; |
2229 | inode->i_fop = &proc_tid_base_operations; | 2323 | inode->i_fop = &proc_tid_base_operations; |
2230 | inode->i_flags|=S_IMMUTABLE; | 2324 | inode->i_flags|=S_IMMUTABLE; |
2231 | inode->i_nlink = 3; | 2325 | inode->i_nlink = 4; |
2232 | #ifdef CONFIG_SECURITY | 2326 | #ifdef CONFIG_SECURITY |
2233 | inode->i_nlink += 1; | 2327 | inode->i_nlink += 1; |
2234 | #endif | 2328 | #endif |
diff --git a/fs/proc/generic.c b/fs/proc/generic.c index 775fb21294d8..8a40e15f5ecb 100644 --- a/fs/proc/generic.c +++ b/fs/proc/generic.c | |||
@@ -398,6 +398,7 @@ struct dentry *proc_lookup(struct inode * dir, struct dentry *dentry, struct nam | |||
398 | if (!memcmp(dentry->d_name.name, de->name, de->namelen)) { | 398 | if (!memcmp(dentry->d_name.name, de->name, de->namelen)) { |
399 | unsigned int ino = de->low_ino; | 399 | unsigned int ino = de->low_ino; |
400 | 400 | ||
401 | de_get(de); | ||
401 | spin_unlock(&proc_subdir_lock); | 402 | spin_unlock(&proc_subdir_lock); |
402 | error = -EINVAL; | 403 | error = -EINVAL; |
403 | inode = proc_get_inode(dir->i_sb, ino, de); | 404 | inode = proc_get_inode(dir->i_sb, ino, de); |
@@ -414,6 +415,7 @@ struct dentry *proc_lookup(struct inode * dir, struct dentry *dentry, struct nam | |||
414 | d_add(dentry, inode); | 415 | d_add(dentry, inode); |
415 | return NULL; | 416 | return NULL; |
416 | } | 417 | } |
418 | de_put(de); | ||
417 | return ERR_PTR(error); | 419 | return ERR_PTR(error); |
418 | } | 420 | } |
419 | 421 | ||
@@ -476,14 +478,21 @@ int proc_readdir(struct file * filp, | |||
476 | } | 478 | } |
477 | 479 | ||
478 | do { | 480 | do { |
481 | struct proc_dir_entry *next; | ||
482 | |||
479 | /* filldir passes info to user space */ | 483 | /* filldir passes info to user space */ |
484 | de_get(de); | ||
480 | spin_unlock(&proc_subdir_lock); | 485 | spin_unlock(&proc_subdir_lock); |
481 | if (filldir(dirent, de->name, de->namelen, filp->f_pos, | 486 | if (filldir(dirent, de->name, de->namelen, filp->f_pos, |
482 | de->low_ino, de->mode >> 12) < 0) | 487 | de->low_ino, de->mode >> 12) < 0) { |
488 | de_put(de); | ||
483 | goto out; | 489 | goto out; |
490 | } | ||
484 | spin_lock(&proc_subdir_lock); | 491 | spin_lock(&proc_subdir_lock); |
485 | filp->f_pos++; | 492 | filp->f_pos++; |
486 | de = de->next; | 493 | next = de->next; |
494 | de_put(de); | ||
495 | de = next; | ||
487 | } while (de); | 496 | } while (de); |
488 | spin_unlock(&proc_subdir_lock); | 497 | spin_unlock(&proc_subdir_lock); |
489 | } | 498 | } |
diff --git a/fs/proc/inode.c b/fs/proc/inode.c index 22b1158389ae..b8171907c83b 100644 --- a/fs/proc/inode.c +++ b/fs/proc/inode.c | |||
@@ -21,7 +21,7 @@ | |||
21 | 21 | ||
22 | #include "internal.h" | 22 | #include "internal.h" |
23 | 23 | ||
24 | static inline struct proc_dir_entry * de_get(struct proc_dir_entry *de) | 24 | struct proc_dir_entry *de_get(struct proc_dir_entry *de) |
25 | { | 25 | { |
26 | if (de) | 26 | if (de) |
27 | atomic_inc(&de->count); | 27 | atomic_inc(&de->count); |
@@ -31,7 +31,7 @@ static inline struct proc_dir_entry * de_get(struct proc_dir_entry *de) | |||
31 | /* | 31 | /* |
32 | * Decrements the use count and checks for deferred deletion. | 32 | * Decrements the use count and checks for deferred deletion. |
33 | */ | 33 | */ |
34 | static void de_put(struct proc_dir_entry *de) | 34 | void de_put(struct proc_dir_entry *de) |
35 | { | 35 | { |
36 | if (de) { | 36 | if (de) { |
37 | lock_kernel(); | 37 | lock_kernel(); |
@@ -146,13 +146,6 @@ struct inode *proc_get_inode(struct super_block *sb, unsigned int ino, | |||
146 | { | 146 | { |
147 | struct inode * inode; | 147 | struct inode * inode; |
148 | 148 | ||
149 | /* | ||
150 | * Increment the use count so the dir entry can't disappear. | ||
151 | */ | ||
152 | de_get(de); | ||
153 | |||
154 | WARN_ON(de && de->deleted); | ||
155 | |||
156 | if (de != NULL && !try_module_get(de->owner)) | 149 | if (de != NULL && !try_module_get(de->owner)) |
157 | goto out_mod; | 150 | goto out_mod; |
158 | 151 | ||
@@ -184,7 +177,6 @@ out_ino: | |||
184 | if (de != NULL) | 177 | if (de != NULL) |
185 | module_put(de->owner); | 178 | module_put(de->owner); |
186 | out_mod: | 179 | out_mod: |
187 | de_put(de); | ||
188 | return NULL; | 180 | return NULL; |
189 | } | 181 | } |
190 | 182 | ||
@@ -199,6 +191,7 @@ int proc_fill_super(struct super_block *s, void *data, int silent) | |||
199 | s->s_op = &proc_sops; | 191 | s->s_op = &proc_sops; |
200 | s->s_time_gran = 1; | 192 | s->s_time_gran = 1; |
201 | 193 | ||
194 | de_get(&proc_root); | ||
202 | root_inode = proc_get_inode(s, PROC_ROOT_INO, &proc_root); | 195 | root_inode = proc_get_inode(s, PROC_ROOT_INO, &proc_root); |
203 | if (!root_inode) | 196 | if (!root_inode) |
204 | goto out_no_root; | 197 | goto out_no_root; |
@@ -212,6 +205,7 @@ int proc_fill_super(struct super_block *s, void *data, int silent) | |||
212 | out_no_root: | 205 | out_no_root: |
213 | printk("proc_read_super: get root inode failed\n"); | 206 | printk("proc_read_super: get root inode failed\n"); |
214 | iput(root_inode); | 207 | iput(root_inode); |
208 | de_put(&proc_root); | ||
215 | return -ENOMEM; | 209 | return -ENOMEM; |
216 | } | 210 | } |
217 | MODULE_LICENSE("GPL"); | 211 | MODULE_LICENSE("GPL"); |
diff --git a/fs/proc/internal.h b/fs/proc/internal.h index f771889183c3..b215c3524fa6 100644 --- a/fs/proc/internal.h +++ b/fs/proc/internal.h | |||
@@ -37,6 +37,8 @@ do { \ | |||
37 | extern int nommu_vma_show(struct seq_file *, struct vm_area_struct *); | 37 | extern int nommu_vma_show(struct seq_file *, struct vm_area_struct *); |
38 | #endif | 38 | #endif |
39 | 39 | ||
40 | extern int maps_protect; | ||
41 | |||
40 | extern void create_seq_entry(char *name, mode_t mode, const struct file_operations *f); | 42 | extern void create_seq_entry(char *name, mode_t mode, const struct file_operations *f); |
41 | extern int proc_exe_link(struct inode *, struct dentry **, struct vfsmount **); | 43 | extern int proc_exe_link(struct inode *, struct dentry **, struct vfsmount **); |
42 | extern int proc_tid_stat(struct task_struct *, char *); | 44 | extern int proc_tid_stat(struct task_struct *, char *); |
diff --git a/fs/proc/proc_misc.c b/fs/proc/proc_misc.c index 75ec6523d29a..5fd49e47f83a 100644 --- a/fs/proc/proc_misc.c +++ b/fs/proc/proc_misc.c | |||
@@ -35,7 +35,6 @@ | |||
35 | #include <linux/signal.h> | 35 | #include <linux/signal.h> |
36 | #include <linux/module.h> | 36 | #include <linux/module.h> |
37 | #include <linux/init.h> | 37 | #include <linux/init.h> |
38 | #include <linux/smp_lock.h> | ||
39 | #include <linux/seq_file.h> | 38 | #include <linux/seq_file.h> |
40 | #include <linux/times.h> | 39 | #include <linux/times.h> |
41 | #include <linux/profile.h> | 40 | #include <linux/profile.h> |
@@ -429,18 +428,11 @@ static int slabstats_open(struct inode *inode, struct file *file) | |||
429 | return ret; | 428 | return ret; |
430 | } | 429 | } |
431 | 430 | ||
432 | static int slabstats_release(struct inode *inode, struct file *file) | ||
433 | { | ||
434 | struct seq_file *m = file->private_data; | ||
435 | kfree(m->private); | ||
436 | return seq_release(inode, file); | ||
437 | } | ||
438 | |||
439 | static const struct file_operations proc_slabstats_operations = { | 431 | static const struct file_operations proc_slabstats_operations = { |
440 | .open = slabstats_open, | 432 | .open = slabstats_open, |
441 | .read = seq_read, | 433 | .read = seq_read, |
442 | .llseek = seq_lseek, | 434 | .llseek = seq_lseek, |
443 | .release = slabstats_release, | 435 | .release = seq_release_private, |
444 | }; | 436 | }; |
445 | #endif | 437 | #endif |
446 | #endif | 438 | #endif |
diff --git a/fs/proc/proc_sysctl.c b/fs/proc/proc_sysctl.c index 20e8cbb34364..680c429bfa22 100644 --- a/fs/proc/proc_sysctl.c +++ b/fs/proc/proc_sysctl.c | |||
@@ -429,11 +429,8 @@ static int proc_sys_setattr(struct dentry *dentry, struct iattr *attr) | |||
429 | return -EPERM; | 429 | return -EPERM; |
430 | 430 | ||
431 | error = inode_change_ok(inode, attr); | 431 | error = inode_change_ok(inode, attr); |
432 | if (!error) { | 432 | if (!error) |
433 | error = security_inode_setattr(dentry, attr); | 433 | error = inode_setattr(inode, attr); |
434 | if (!error) | ||
435 | error = inode_setattr(inode, attr); | ||
436 | } | ||
437 | 434 | ||
438 | return error; | 435 | return error; |
439 | } | 436 | } |
diff --git a/fs/proc/proc_tty.c b/fs/proc/proc_tty.c index c1bbfbeb035e..b3a473b0a191 100644 --- a/fs/proc/proc_tty.c +++ b/fs/proc/proc_tty.c | |||
@@ -108,6 +108,8 @@ static void *t_start(struct seq_file *m, loff_t *pos) | |||
108 | { | 108 | { |
109 | struct list_head *p; | 109 | struct list_head *p; |
110 | loff_t l = *pos; | 110 | loff_t l = *pos; |
111 | |||
112 | mutex_lock(&tty_mutex); | ||
111 | list_for_each(p, &tty_drivers) | 113 | list_for_each(p, &tty_drivers) |
112 | if (!l--) | 114 | if (!l--) |
113 | return list_entry(p, struct tty_driver, tty_drivers); | 115 | return list_entry(p, struct tty_driver, tty_drivers); |
@@ -124,6 +126,7 @@ static void *t_next(struct seq_file *m, void *v, loff_t *pos) | |||
124 | 126 | ||
125 | static void t_stop(struct seq_file *m, void *v) | 127 | static void t_stop(struct seq_file *m, void *v) |
126 | { | 128 | { |
129 | mutex_unlock(&tty_mutex); | ||
127 | } | 130 | } |
128 | 131 | ||
129 | static struct seq_operations tty_drivers_op = { | 132 | static struct seq_operations tty_drivers_op = { |
diff --git a/fs/proc/task_mmu.c b/fs/proc/task_mmu.c index 4008c060f7ef..c24d81a5a040 100644 --- a/fs/proc/task_mmu.c +++ b/fs/proc/task_mmu.c | |||
@@ -3,6 +3,7 @@ | |||
3 | #include <linux/mount.h> | 3 | #include <linux/mount.h> |
4 | #include <linux/seq_file.h> | 4 | #include <linux/seq_file.h> |
5 | #include <linux/highmem.h> | 5 | #include <linux/highmem.h> |
6 | #include <linux/ptrace.h> | ||
6 | #include <linux/pagemap.h> | 7 | #include <linux/pagemap.h> |
7 | #include <linux/mempolicy.h> | 8 | #include <linux/mempolicy.h> |
8 | 9 | ||
@@ -142,6 +143,9 @@ static int show_map_internal(struct seq_file *m, void *v, struct mem_size_stats | |||
142 | dev_t dev = 0; | 143 | dev_t dev = 0; |
143 | int len; | 144 | int len; |
144 | 145 | ||
146 | if (maps_protect && !ptrace_may_attach(task)) | ||
147 | return -EACCES; | ||
148 | |||
145 | if (file) { | 149 | if (file) { |
146 | struct inode *inode = vma->vm_file->f_path.dentry->d_inode; | 150 | struct inode *inode = vma->vm_file->f_path.dentry->d_inode; |
147 | dev = inode->i_sb->s_dev; | 151 | dev = inode->i_sb->s_dev; |
@@ -512,11 +516,22 @@ const struct file_operations proc_maps_operations = { | |||
512 | #ifdef CONFIG_NUMA | 516 | #ifdef CONFIG_NUMA |
513 | extern int show_numa_map(struct seq_file *m, void *v); | 517 | extern int show_numa_map(struct seq_file *m, void *v); |
514 | 518 | ||
519 | static int show_numa_map_checked(struct seq_file *m, void *v) | ||
520 | { | ||
521 | struct proc_maps_private *priv = m->private; | ||
522 | struct task_struct *task = priv->task; | ||
523 | |||
524 | if (maps_protect && !ptrace_may_attach(task)) | ||
525 | return -EACCES; | ||
526 | |||
527 | return show_numa_map(m, v); | ||
528 | } | ||
529 | |||
515 | static struct seq_operations proc_pid_numa_maps_op = { | 530 | static struct seq_operations proc_pid_numa_maps_op = { |
516 | .start = m_start, | 531 | .start = m_start, |
517 | .next = m_next, | 532 | .next = m_next, |
518 | .stop = m_stop, | 533 | .stop = m_stop, |
519 | .show = show_numa_map | 534 | .show = show_numa_map_checked |
520 | }; | 535 | }; |
521 | 536 | ||
522 | static int numa_maps_open(struct inode *inode, struct file *file) | 537 | static int numa_maps_open(struct inode *inode, struct file *file) |
diff --git a/fs/proc/task_nommu.c b/fs/proc/task_nommu.c index 7cddf6b8635a..d8b8c7183c24 100644 --- a/fs/proc/task_nommu.c +++ b/fs/proc/task_nommu.c | |||
@@ -2,6 +2,7 @@ | |||
2 | #include <linux/mm.h> | 2 | #include <linux/mm.h> |
3 | #include <linux/file.h> | 3 | #include <linux/file.h> |
4 | #include <linux/mount.h> | 4 | #include <linux/mount.h> |
5 | #include <linux/ptrace.h> | ||
5 | #include <linux/seq_file.h> | 6 | #include <linux/seq_file.h> |
6 | #include "internal.h" | 7 | #include "internal.h" |
7 | 8 | ||
@@ -143,6 +144,12 @@ out: | |||
143 | static int show_map(struct seq_file *m, void *_vml) | 144 | static int show_map(struct seq_file *m, void *_vml) |
144 | { | 145 | { |
145 | struct vm_list_struct *vml = _vml; | 146 | struct vm_list_struct *vml = _vml; |
147 | struct proc_maps_private *priv = m->private; | ||
148 | struct task_struct *task = priv->task; | ||
149 | |||
150 | if (maps_protect && !ptrace_may_attach(task)) | ||
151 | return -EACCES; | ||
152 | |||
146 | return nommu_vma_show(m, vml->vma); | 153 | return nommu_vma_show(m, vml->vma); |
147 | } | 154 | } |
148 | 155 | ||