diff options
Diffstat (limited to 'fs')
-rw-r--r-- | fs/proc/base.c | 384 |
1 files changed, 174 insertions, 210 deletions
diff --git a/fs/proc/base.c b/fs/proc/base.c index e8084eb037e3..7bf28c3af70c 100644 --- a/fs/proc/base.c +++ b/fs/proc/base.c | |||
@@ -84,114 +84,11 @@ | |||
84 | * in /proc for a task before it execs a suid executable. | 84 | * in /proc for a task before it execs a suid executable. |
85 | */ | 85 | */ |
86 | 86 | ||
87 | /* | ||
88 | * For hysterical raisins we keep the same inumbers as in the old procfs. | ||
89 | * Feel free to change the macro below - just keep the range distinct from | ||
90 | * inumbers of the rest of procfs (currently those are in 0x0000--0xffff). | ||
91 | * As soon as we'll get a separate superblock we will be able to forget | ||
92 | * about magical ranges too. | ||
93 | */ | ||
94 | |||
95 | #define fake_ino(pid,ino) (((pid)<<16)|(ino)) | ||
96 | |||
97 | enum pid_directory_inos { | ||
98 | PROC_TGID_INO = 2, | ||
99 | PROC_TGID_TASK, | ||
100 | PROC_TGID_STATUS, | ||
101 | PROC_TGID_MEM, | ||
102 | #ifdef CONFIG_SECCOMP | ||
103 | PROC_TGID_SECCOMP, | ||
104 | #endif | ||
105 | PROC_TGID_CWD, | ||
106 | PROC_TGID_ROOT, | ||
107 | PROC_TGID_EXE, | ||
108 | PROC_TGID_FD, | ||
109 | PROC_TGID_ENVIRON, | ||
110 | PROC_TGID_AUXV, | ||
111 | PROC_TGID_CMDLINE, | ||
112 | PROC_TGID_STAT, | ||
113 | PROC_TGID_STATM, | ||
114 | PROC_TGID_MAPS, | ||
115 | PROC_TGID_NUMA_MAPS, | ||
116 | PROC_TGID_MOUNTS, | ||
117 | PROC_TGID_MOUNTSTATS, | ||
118 | PROC_TGID_WCHAN, | ||
119 | #ifdef CONFIG_MMU | ||
120 | PROC_TGID_SMAPS, | ||
121 | #endif | ||
122 | #ifdef CONFIG_SCHEDSTATS | ||
123 | PROC_TGID_SCHEDSTAT, | ||
124 | #endif | ||
125 | #ifdef CONFIG_CPUSETS | ||
126 | PROC_TGID_CPUSET, | ||
127 | #endif | ||
128 | #ifdef CONFIG_SECURITY | ||
129 | PROC_TGID_ATTR, | ||
130 | PROC_TGID_ATTR_CURRENT, | ||
131 | PROC_TGID_ATTR_PREV, | ||
132 | PROC_TGID_ATTR_EXEC, | ||
133 | PROC_TGID_ATTR_FSCREATE, | ||
134 | PROC_TGID_ATTR_KEYCREATE, | ||
135 | PROC_TGID_ATTR_SOCKCREATE, | ||
136 | #endif | ||
137 | #ifdef CONFIG_AUDITSYSCALL | ||
138 | PROC_TGID_LOGINUID, | ||
139 | #endif | ||
140 | PROC_TGID_OOM_SCORE, | ||
141 | PROC_TGID_OOM_ADJUST, | ||
142 | PROC_TID_INO, | ||
143 | PROC_TID_STATUS, | ||
144 | PROC_TID_MEM, | ||
145 | #ifdef CONFIG_SECCOMP | ||
146 | PROC_TID_SECCOMP, | ||
147 | #endif | ||
148 | PROC_TID_CWD, | ||
149 | PROC_TID_ROOT, | ||
150 | PROC_TID_EXE, | ||
151 | PROC_TID_FD, | ||
152 | PROC_TID_ENVIRON, | ||
153 | PROC_TID_AUXV, | ||
154 | PROC_TID_CMDLINE, | ||
155 | PROC_TID_STAT, | ||
156 | PROC_TID_STATM, | ||
157 | PROC_TID_MAPS, | ||
158 | PROC_TID_NUMA_MAPS, | ||
159 | PROC_TID_MOUNTS, | ||
160 | PROC_TID_MOUNTSTATS, | ||
161 | PROC_TID_WCHAN, | ||
162 | #ifdef CONFIG_MMU | ||
163 | PROC_TID_SMAPS, | ||
164 | #endif | ||
165 | #ifdef CONFIG_SCHEDSTATS | ||
166 | PROC_TID_SCHEDSTAT, | ||
167 | #endif | ||
168 | #ifdef CONFIG_CPUSETS | ||
169 | PROC_TID_CPUSET, | ||
170 | #endif | ||
171 | #ifdef CONFIG_SECURITY | ||
172 | PROC_TID_ATTR, | ||
173 | PROC_TID_ATTR_CURRENT, | ||
174 | PROC_TID_ATTR_PREV, | ||
175 | PROC_TID_ATTR_EXEC, | ||
176 | PROC_TID_ATTR_FSCREATE, | ||
177 | PROC_TID_ATTR_KEYCREATE, | ||
178 | PROC_TID_ATTR_SOCKCREATE, | ||
179 | #endif | ||
180 | #ifdef CONFIG_AUDITSYSCALL | ||
181 | PROC_TID_LOGINUID, | ||
182 | #endif | ||
183 | PROC_TID_OOM_SCORE, | ||
184 | PROC_TID_OOM_ADJUST, | ||
185 | |||
186 | /* Add new entries before this */ | ||
187 | PROC_TID_FD_DIR = 0x8000, /* 0x8000-0xffff */ | ||
188 | }; | ||
189 | 87 | ||
190 | /* Worst case buffer size needed for holding an integer. */ | 88 | /* Worst case buffer size needed for holding an integer. */ |
191 | #define PROC_NUMBUF 10 | 89 | #define PROC_NUMBUF 10 |
192 | 90 | ||
193 | struct pid_entry { | 91 | struct pid_entry { |
194 | int type; | ||
195 | int len; | 92 | int len; |
196 | char *name; | 93 | char *name; |
197 | mode_t mode; | 94 | mode_t mode; |
@@ -200,8 +97,7 @@ struct pid_entry { | |||
200 | union proc_op op; | 97 | union proc_op op; |
201 | }; | 98 | }; |
202 | 99 | ||
203 | #define NOD(TYPE, NAME, MODE, IOP, FOP, OP) { \ | 100 | #define NOD(NAME, MODE, IOP, FOP, OP) { \ |
204 | .type = (TYPE), \ | ||
205 | .len = sizeof(NAME) - 1, \ | 101 | .len = sizeof(NAME) - 1, \ |
206 | .name = (NAME), \ | 102 | .name = (NAME), \ |
207 | .mode = MODE, \ | 103 | .mode = MODE, \ |
@@ -210,19 +106,19 @@ struct pid_entry { | |||
210 | .op = OP, \ | 106 | .op = OP, \ |
211 | } | 107 | } |
212 | 108 | ||
213 | #define DIR(TYPE, NAME, MODE, OTYPE) \ | 109 | #define DIR(NAME, MODE, OTYPE) \ |
214 | NOD(TYPE, NAME, (S_IFDIR|(MODE)), \ | 110 | NOD(NAME, (S_IFDIR|(MODE)), \ |
215 | &proc_##OTYPE##_inode_operations, &proc_##OTYPE##_operations, \ | 111 | &proc_##OTYPE##_inode_operations, &proc_##OTYPE##_operations, \ |
216 | {} ) | 112 | {} ) |
217 | #define LNK(TYPE, NAME, OTYPE) \ | 113 | #define LNK(NAME, OTYPE) \ |
218 | NOD(TYPE, NAME, (S_IFLNK|S_IRWXUGO), \ | 114 | NOD(NAME, (S_IFLNK|S_IRWXUGO), \ |
219 | &proc_pid_link_inode_operations, NULL, \ | 115 | &proc_pid_link_inode_operations, NULL, \ |
220 | { .proc_get_link = &proc_##OTYPE##_link } ) | 116 | { .proc_get_link = &proc_##OTYPE##_link } ) |
221 | #define REG(TYPE, NAME, MODE, OTYPE) \ | 117 | #define REG(NAME, MODE, OTYPE) \ |
222 | NOD(TYPE, NAME, (S_IFREG|(MODE)), NULL, \ | 118 | NOD(NAME, (S_IFREG|(MODE)), NULL, \ |
223 | &proc_##OTYPE##_operations, {}) | 119 | &proc_##OTYPE##_operations, {}) |
224 | #define INF(TYPE, NAME, MODE, OTYPE) \ | 120 | #define INF(NAME, MODE, OTYPE) \ |
225 | NOD(TYPE, NAME, (S_IFREG|(MODE)), \ | 121 | NOD(NAME, (S_IFREG|(MODE)), \ |
226 | NULL, &proc_info_file_operations, \ | 122 | NULL, &proc_info_file_operations, \ |
227 | { .proc_read = &proc_##OTYPE } ) | 123 | { .proc_read = &proc_##OTYPE } ) |
228 | 124 | ||
@@ -1043,7 +939,7 @@ static int task_dumpable(struct task_struct *task) | |||
1043 | } | 939 | } |
1044 | 940 | ||
1045 | 941 | ||
1046 | static struct inode *proc_pid_make_inode(struct super_block * sb, struct task_struct *task, int ino) | 942 | static struct inode *proc_pid_make_inode(struct super_block * sb, struct task_struct *task) |
1047 | { | 943 | { |
1048 | struct inode * inode; | 944 | struct inode * inode; |
1049 | struct proc_inode *ei; | 945 | struct proc_inode *ei; |
@@ -1057,7 +953,6 @@ static struct inode *proc_pid_make_inode(struct super_block * sb, struct task_st | |||
1057 | /* Common stuff */ | 953 | /* Common stuff */ |
1058 | ei = PROC_I(inode); | 954 | ei = PROC_I(inode); |
1059 | inode->i_mtime = inode->i_atime = inode->i_ctime = CURRENT_TIME; | 955 | inode->i_mtime = inode->i_atime = inode->i_ctime = CURRENT_TIME; |
1060 | inode->i_ino = fake_ino(task->pid, ino); | ||
1061 | inode->i_op = &proc_def_inode_operations; | 956 | inode->i_op = &proc_def_inode_operations; |
1062 | 957 | ||
1063 | /* | 958 | /* |
@@ -1160,6 +1055,50 @@ static struct dentry_operations pid_dentry_operations = | |||
1160 | 1055 | ||
1161 | /* Lookups */ | 1056 | /* Lookups */ |
1162 | 1057 | ||
1058 | typedef struct dentry *instantiate_t(struct inode *, struct dentry *, struct task_struct *, void *); | ||
1059 | |||
1060 | static int proc_fill_cache(struct file *filp, void *dirent, filldir_t filldir, | ||
1061 | char *name, int len, | ||
1062 | instantiate_t instantiate, struct task_struct *task, void *ptr) | ||
1063 | { | ||
1064 | struct dentry *child, *dir = filp->f_dentry; | ||
1065 | struct inode *inode; | ||
1066 | struct qstr qname; | ||
1067 | ino_t ino = 0; | ||
1068 | unsigned type = DT_UNKNOWN; | ||
1069 | |||
1070 | qname.name = name; | ||
1071 | qname.len = len; | ||
1072 | qname.hash = full_name_hash(name, len); | ||
1073 | |||
1074 | child = d_lookup(dir, &qname); | ||
1075 | if (!child) { | ||
1076 | struct dentry *new; | ||
1077 | new = d_alloc(dir, &qname); | ||
1078 | if (new) { | ||
1079 | child = instantiate(dir->d_inode, new, task, ptr); | ||
1080 | if (child) | ||
1081 | dput(new); | ||
1082 | else | ||
1083 | child = new; | ||
1084 | } | ||
1085 | } | ||
1086 | if (!child || IS_ERR(child) || !child->d_inode) | ||
1087 | goto end_instantiate; | ||
1088 | inode = child->d_inode; | ||
1089 | if (inode) { | ||
1090 | ino = inode->i_ino; | ||
1091 | type = inode->i_mode >> 12; | ||
1092 | } | ||
1093 | dput(child); | ||
1094 | end_instantiate: | ||
1095 | if (!ino) | ||
1096 | ino = find_inode_number(dir, &qname); | ||
1097 | if (!ino) | ||
1098 | ino = 1; | ||
1099 | return filldir(dirent, name, len, filp->f_pos, ino, type); | ||
1100 | } | ||
1101 | |||
1163 | static unsigned name_to_int(struct dentry *dentry) | 1102 | static unsigned name_to_int(struct dentry *dentry) |
1164 | { | 1103 | { |
1165 | const char *name = dentry->d_name.name; | 1104 | const char *name = dentry->d_name.name; |
@@ -1264,7 +1203,7 @@ static struct dentry *proc_fd_instantiate(struct inode *dir, | |||
1264 | struct proc_inode *ei; | 1203 | struct proc_inode *ei; |
1265 | struct dentry *error = ERR_PTR(-ENOENT); | 1204 | struct dentry *error = ERR_PTR(-ENOENT); |
1266 | 1205 | ||
1267 | inode = proc_pid_make_inode(dir->i_sb, task, PROC_TID_FD_DIR+fd); | 1206 | inode = proc_pid_make_inode(dir->i_sb, task); |
1268 | if (!inode) | 1207 | if (!inode) |
1269 | goto out; | 1208 | goto out; |
1270 | ei = PROC_I(inode); | 1209 | ei = PROC_I(inode); |
@@ -1327,6 +1266,15 @@ out_no_task: | |||
1327 | return result; | 1266 | return result; |
1328 | } | 1267 | } |
1329 | 1268 | ||
1269 | static int proc_fd_fill_cache(struct file *filp, void *dirent, filldir_t filldir, | ||
1270 | struct task_struct *task, int fd) | ||
1271 | { | ||
1272 | char name[PROC_NUMBUF]; | ||
1273 | int len = snprintf(name, sizeof(name), "%d", fd); | ||
1274 | return proc_fill_cache(filp, dirent, filldir, name, len, | ||
1275 | proc_fd_instantiate, task, &fd); | ||
1276 | } | ||
1277 | |||
1330 | static int proc_readfd(struct file * filp, void * dirent, filldir_t filldir) | 1278 | static int proc_readfd(struct file * filp, void * dirent, filldir_t filldir) |
1331 | { | 1279 | { |
1332 | struct dentry *dentry = filp->f_dentry; | 1280 | struct dentry *dentry = filp->f_dentry; |
@@ -1334,7 +1282,6 @@ static int proc_readfd(struct file * filp, void * dirent, filldir_t filldir) | |||
1334 | struct task_struct *p = get_proc_task(inode); | 1282 | struct task_struct *p = get_proc_task(inode); |
1335 | unsigned int fd, tid, ino; | 1283 | unsigned int fd, tid, ino; |
1336 | int retval; | 1284 | int retval; |
1337 | char buf[PROC_NUMBUF]; | ||
1338 | struct files_struct * files; | 1285 | struct files_struct * files; |
1339 | struct fdtable *fdt; | 1286 | struct fdtable *fdt; |
1340 | 1287 | ||
@@ -1364,22 +1311,12 @@ static int proc_readfd(struct file * filp, void * dirent, filldir_t filldir) | |||
1364 | for (fd = filp->f_pos-2; | 1311 | for (fd = filp->f_pos-2; |
1365 | fd < fdt->max_fds; | 1312 | fd < fdt->max_fds; |
1366 | fd++, filp->f_pos++) { | 1313 | fd++, filp->f_pos++) { |
1367 | unsigned int i,j; | ||
1368 | 1314 | ||
1369 | if (!fcheck_files(files, fd)) | 1315 | if (!fcheck_files(files, fd)) |
1370 | continue; | 1316 | continue; |
1371 | rcu_read_unlock(); | 1317 | rcu_read_unlock(); |
1372 | 1318 | ||
1373 | j = PROC_NUMBUF; | 1319 | if (proc_fd_fill_cache(filp, dirent, filldir, p, fd) < 0) { |
1374 | i = fd; | ||
1375 | do { | ||
1376 | j--; | ||
1377 | buf[j] = '0' + (i % 10); | ||
1378 | i /= 10; | ||
1379 | } while (i); | ||
1380 | |||
1381 | ino = fake_ino(tid, PROC_TID_FD_DIR + fd); | ||
1382 | if (filldir(dirent, buf+j, PROC_NUMBUF-j, fd+2, ino, DT_LNK) < 0) { | ||
1383 | rcu_read_lock(); | 1320 | rcu_read_lock(); |
1384 | break; | 1321 | break; |
1385 | } | 1322 | } |
@@ -1415,7 +1352,7 @@ static struct dentry *proc_pident_instantiate(struct inode *dir, | |||
1415 | struct proc_inode *ei; | 1352 | struct proc_inode *ei; |
1416 | struct dentry *error = ERR_PTR(-EINVAL); | 1353 | struct dentry *error = ERR_PTR(-EINVAL); |
1417 | 1354 | ||
1418 | inode = proc_pid_make_inode(dir->i_sb, task, p->type); | 1355 | inode = proc_pid_make_inode(dir->i_sb, task); |
1419 | if (!inode) | 1356 | if (!inode) |
1420 | goto out; | 1357 | goto out; |
1421 | 1358 | ||
@@ -1473,6 +1410,13 @@ out_no_task: | |||
1473 | return error; | 1410 | return error; |
1474 | } | 1411 | } |
1475 | 1412 | ||
1413 | static int proc_pident_fill_cache(struct file *filp, void *dirent, filldir_t filldir, | ||
1414 | struct task_struct *task, struct pid_entry *p) | ||
1415 | { | ||
1416 | return proc_fill_cache(filp, dirent, filldir, p->name, p->len, | ||
1417 | proc_pident_instantiate, task, p); | ||
1418 | } | ||
1419 | |||
1476 | static int proc_pident_readdir(struct file *filp, | 1420 | static int proc_pident_readdir(struct file *filp, |
1477 | void *dirent, filldir_t filldir, | 1421 | void *dirent, filldir_t filldir, |
1478 | struct pid_entry *ents, unsigned int nents) | 1422 | struct pid_entry *ents, unsigned int nents) |
@@ -1488,11 +1432,10 @@ static int proc_pident_readdir(struct file *filp, | |||
1488 | 1432 | ||
1489 | ret = -ENOENT; | 1433 | ret = -ENOENT; |
1490 | if (!task) | 1434 | if (!task) |
1491 | goto out; | 1435 | goto out_no_task; |
1492 | 1436 | ||
1493 | ret = 0; | 1437 | ret = 0; |
1494 | pid = task->pid; | 1438 | pid = task->pid; |
1495 | put_task_struct(task); | ||
1496 | i = filp->f_pos; | 1439 | i = filp->f_pos; |
1497 | switch (i) { | 1440 | switch (i) { |
1498 | case 0: | 1441 | case 0: |
@@ -1517,8 +1460,7 @@ static int proc_pident_readdir(struct file *filp, | |||
1517 | } | 1460 | } |
1518 | p = ents + i; | 1461 | p = ents + i; |
1519 | while (p->name) { | 1462 | while (p->name) { |
1520 | if (filldir(dirent, p->name, p->len, filp->f_pos, | 1463 | if (proc_pident_fill_cache(filp, dirent, filldir, task, p) < 0) |
1521 | fake_ino(pid, p->type), p->mode >> 12) < 0) | ||
1522 | goto out; | 1464 | goto out; |
1523 | filp->f_pos++; | 1465 | filp->f_pos++; |
1524 | p++; | 1466 | p++; |
@@ -1527,6 +1469,8 @@ static int proc_pident_readdir(struct file *filp, | |||
1527 | 1469 | ||
1528 | ret = 1; | 1470 | ret = 1; |
1529 | out: | 1471 | out: |
1472 | put_task_struct(task); | ||
1473 | out_no_task: | ||
1530 | return ret; | 1474 | return ret; |
1531 | } | 1475 | } |
1532 | 1476 | ||
@@ -1606,21 +1550,21 @@ static struct file_operations proc_pid_attr_operations = { | |||
1606 | }; | 1550 | }; |
1607 | 1551 | ||
1608 | static struct pid_entry tgid_attr_stuff[] = { | 1552 | static struct pid_entry tgid_attr_stuff[] = { |
1609 | REG(PROC_TGID_ATTR_CURRENT, "current", S_IRUGO|S_IWUGO, pid_attr), | 1553 | REG("current", S_IRUGO|S_IWUGO, pid_attr), |
1610 | REG(PROC_TGID_ATTR_PREV, "prev", S_IRUGO, pid_attr), | 1554 | REG("prev", S_IRUGO, pid_attr), |
1611 | REG(PROC_TGID_ATTR_EXEC, "exec", S_IRUGO|S_IWUGO, pid_attr), | 1555 | REG("exec", S_IRUGO|S_IWUGO, pid_attr), |
1612 | REG(PROC_TGID_ATTR_FSCREATE, "fscreate", S_IRUGO|S_IWUGO, pid_attr), | 1556 | REG("fscreate", S_IRUGO|S_IWUGO, pid_attr), |
1613 | REG(PROC_TGID_ATTR_KEYCREATE, "keycreate", S_IRUGO|S_IWUGO, pid_attr), | 1557 | REG("keycreate", S_IRUGO|S_IWUGO, pid_attr), |
1614 | REG(PROC_TGID_ATTR_SOCKCREATE, "sockcreate", S_IRUGO|S_IWUGO, pid_attr), | 1558 | REG("sockcreate", S_IRUGO|S_IWUGO, pid_attr), |
1615 | {} | 1559 | {} |
1616 | }; | 1560 | }; |
1617 | static struct pid_entry tid_attr_stuff[] = { | 1561 | static struct pid_entry tid_attr_stuff[] = { |
1618 | REG(PROC_TID_ATTR_CURRENT, "current", S_IRUGO|S_IWUGO, pid_attr), | 1562 | REG("current", S_IRUGO|S_IWUGO, pid_attr), |
1619 | REG(PROC_TID_ATTR_PREV, "prev", S_IRUGO, pid_attr), | 1563 | REG("prev", S_IRUGO, pid_attr), |
1620 | REG(PROC_TID_ATTR_EXEC, "exec", S_IRUGO|S_IWUGO, pid_attr), | 1564 | REG("exec", S_IRUGO|S_IWUGO, pid_attr), |
1621 | REG(PROC_TID_ATTR_FSCREATE, "fscreate", S_IRUGO|S_IWUGO, pid_attr), | 1565 | REG("fscreate", S_IRUGO|S_IWUGO, pid_attr), |
1622 | REG(PROC_TID_ATTR_KEYCREATE, "keycreate", S_IRUGO|S_IWUGO, pid_attr), | 1566 | REG("keycreate", S_IRUGO|S_IWUGO, pid_attr), |
1623 | REG(PROC_TID_ATTR_SOCKCREATE, "sockcreate", S_IRUGO|S_IWUGO, pid_attr), | 1567 | REG("sockcreate", S_IRUGO|S_IWUGO, pid_attr), |
1624 | {} | 1568 | {} |
1625 | }; | 1569 | }; |
1626 | 1570 | ||
@@ -1704,7 +1648,7 @@ static struct inode_operations proc_self_inode_operations = { | |||
1704 | * describe something that is process related. | 1648 | * describe something that is process related. |
1705 | */ | 1649 | */ |
1706 | static struct pid_entry proc_base_stuff[] = { | 1650 | static struct pid_entry proc_base_stuff[] = { |
1707 | NOD(PROC_TGID_INO, "self", S_IFLNK|S_IRWXUGO, | 1651 | NOD("self", S_IFLNK|S_IRWXUGO, |
1708 | &proc_self_inode_operations, NULL, {}), | 1652 | &proc_self_inode_operations, NULL, {}), |
1709 | {} | 1653 | {} |
1710 | }; | 1654 | }; |
@@ -1749,7 +1693,6 @@ static struct dentry *proc_base_instantiate(struct inode *dir, | |||
1749 | /* Initialize the inode */ | 1693 | /* Initialize the inode */ |
1750 | ei = PROC_I(inode); | 1694 | ei = PROC_I(inode); |
1751 | inode->i_mtime = inode->i_atime = inode->i_ctime = CURRENT_TIME; | 1695 | inode->i_mtime = inode->i_atime = inode->i_ctime = CURRENT_TIME; |
1752 | inode->i_ino = fake_ino(0, p->type); | ||
1753 | 1696 | ||
1754 | /* | 1697 | /* |
1755 | * grab the reference to the task. | 1698 | * grab the reference to the task. |
@@ -1809,6 +1752,13 @@ out_no_task: | |||
1809 | return error; | 1752 | return error; |
1810 | } | 1753 | } |
1811 | 1754 | ||
1755 | static int proc_base_fill_cache(struct file *filp, void *dirent, filldir_t filldir, | ||
1756 | struct task_struct *task, struct pid_entry *p) | ||
1757 | { | ||
1758 | return proc_fill_cache(filp, dirent, filldir, p->name, p->len, | ||
1759 | proc_base_instantiate, task, p); | ||
1760 | } | ||
1761 | |||
1812 | /* | 1762 | /* |
1813 | * Thread groups | 1763 | * Thread groups |
1814 | */ | 1764 | */ |
@@ -1816,46 +1766,46 @@ static struct file_operations proc_task_operations; | |||
1816 | static struct inode_operations proc_task_inode_operations; | 1766 | static struct inode_operations proc_task_inode_operations; |
1817 | 1767 | ||
1818 | static struct pid_entry tgid_base_stuff[] = { | 1768 | static struct pid_entry tgid_base_stuff[] = { |
1819 | DIR(PROC_TGID_TASK, "task", S_IRUGO|S_IXUGO, task), | 1769 | DIR("task", S_IRUGO|S_IXUGO, task), |
1820 | DIR(PROC_TGID_FD, "fd", S_IRUSR|S_IXUSR, fd), | 1770 | DIR("fd", S_IRUSR|S_IXUSR, fd), |
1821 | INF(PROC_TGID_ENVIRON, "environ", S_IRUSR, pid_environ), | 1771 | INF("environ", S_IRUSR, pid_environ), |
1822 | INF(PROC_TGID_AUXV, "auxv", S_IRUSR, pid_auxv), | 1772 | INF("auxv", S_IRUSR, pid_auxv), |
1823 | INF(PROC_TGID_STATUS, "status", S_IRUGO, pid_status), | 1773 | INF("status", S_IRUGO, pid_status), |
1824 | INF(PROC_TGID_CMDLINE, "cmdline", S_IRUGO, pid_cmdline), | 1774 | INF("cmdline", S_IRUGO, pid_cmdline), |
1825 | INF(PROC_TGID_STAT, "stat", S_IRUGO, tgid_stat), | 1775 | INF("stat", S_IRUGO, tgid_stat), |
1826 | INF(PROC_TGID_STATM, "statm", S_IRUGO, pid_statm), | 1776 | INF("statm", S_IRUGO, pid_statm), |
1827 | REG(PROC_TGID_MAPS, "maps", S_IRUGO, maps), | 1777 | REG("maps", S_IRUGO, maps), |
1828 | #ifdef CONFIG_NUMA | 1778 | #ifdef CONFIG_NUMA |
1829 | REG(PROC_TGID_NUMA_MAPS, "numa_maps", S_IRUGO, numa_maps), | 1779 | REG("numa_maps", S_IRUGO, numa_maps), |
1830 | #endif | 1780 | #endif |
1831 | REG(PROC_TGID_MEM, "mem", S_IRUSR|S_IWUSR, mem), | 1781 | REG("mem", S_IRUSR|S_IWUSR, mem), |
1832 | #ifdef CONFIG_SECCOMP | 1782 | #ifdef CONFIG_SECCOMP |
1833 | REG(PROC_TGID_SECCOMP, "seccomp", S_IRUSR|S_IWUSR, seccomp), | 1783 | REG("seccomp", S_IRUSR|S_IWUSR, seccomp), |
1834 | #endif | 1784 | #endif |
1835 | LNK(PROC_TGID_CWD, "cwd", cwd), | 1785 | LNK("cwd", cwd), |
1836 | LNK(PROC_TGID_ROOT, "root", root), | 1786 | LNK("root", root), |
1837 | LNK(PROC_TGID_EXE, "exe", exe), | 1787 | LNK("exe", exe), |
1838 | REG(PROC_TGID_MOUNTS, "mounts", S_IRUGO, mounts), | 1788 | REG("mounts", S_IRUGO, mounts), |
1839 | REG(PROC_TGID_MOUNTSTATS, "mountstats", S_IRUSR, mountstats), | 1789 | REG("mountstats", S_IRUSR, mountstats), |
1840 | #ifdef CONFIG_MMU | 1790 | #ifdef CONFIG_MMU |
1841 | REG(PROC_TGID_SMAPS, "smaps", S_IRUGO, smaps), | 1791 | REG("smaps", S_IRUGO, smaps), |
1842 | #endif | 1792 | #endif |
1843 | #ifdef CONFIG_SECURITY | 1793 | #ifdef CONFIG_SECURITY |
1844 | DIR(PROC_TGID_ATTR, "attr", S_IRUGO|S_IXUGO, tgid_attr), | 1794 | DIR("attr", S_IRUGO|S_IXUGO, tgid_attr), |
1845 | #endif | 1795 | #endif |
1846 | #ifdef CONFIG_KALLSYMS | 1796 | #ifdef CONFIG_KALLSYMS |
1847 | INF(PROC_TGID_WCHAN, "wchan", S_IRUGO, pid_wchan), | 1797 | INF("wchan", S_IRUGO, pid_wchan), |
1848 | #endif | 1798 | #endif |
1849 | #ifdef CONFIG_SCHEDSTATS | 1799 | #ifdef CONFIG_SCHEDSTATS |
1850 | INF(PROC_TGID_SCHEDSTAT, "schedstat", S_IRUGO, pid_schedstat), | 1800 | INF("schedstat", S_IRUGO, pid_schedstat), |
1851 | #endif | 1801 | #endif |
1852 | #ifdef CONFIG_CPUSETS | 1802 | #ifdef CONFIG_CPUSETS |
1853 | REG(PROC_TGID_CPUSET, "cpuset", S_IRUGO, cpuset), | 1803 | REG("cpuset", S_IRUGO, cpuset), |
1854 | #endif | 1804 | #endif |
1855 | INF(PROC_TGID_OOM_SCORE, "oom_score", S_IRUGO, oom_score), | 1805 | INF("oom_score", S_IRUGO, oom_score), |
1856 | REG(PROC_TGID_OOM_ADJUST, "oom_adj", S_IRUGO|S_IWUSR, oom_adjust), | 1806 | REG("oom_adj", S_IRUGO|S_IWUSR, oom_adjust), |
1857 | #ifdef CONFIG_AUDITSYSCALL | 1807 | #ifdef CONFIG_AUDITSYSCALL |
1858 | REG(PROC_TGID_LOGINUID, "loginuid", S_IWUSR|S_IRUGO, loginuid), | 1808 | REG("loginuid", S_IWUSR|S_IRUGO, loginuid), |
1859 | #endif | 1809 | #endif |
1860 | {} | 1810 | {} |
1861 | }; | 1811 | }; |
@@ -1955,7 +1905,7 @@ struct dentry *proc_pid_instantiate(struct inode *dir, | |||
1955 | struct dentry *error = ERR_PTR(-ENOENT); | 1905 | struct dentry *error = ERR_PTR(-ENOENT); |
1956 | struct inode *inode; | 1906 | struct inode *inode; |
1957 | 1907 | ||
1958 | inode = proc_pid_make_inode(dir->i_sb, task, PROC_TGID_INO); | 1908 | inode = proc_pid_make_inode(dir->i_sb, task); |
1959 | if (!inode) | 1909 | if (!inode) |
1960 | goto out; | 1910 | goto out; |
1961 | 1911 | ||
@@ -2045,18 +1995,29 @@ retry: | |||
2045 | 1995 | ||
2046 | #define TGID_OFFSET (FIRST_PROCESS_ENTRY + (1 /* /proc/self */)) | 1996 | #define TGID_OFFSET (FIRST_PROCESS_ENTRY + (1 /* /proc/self */)) |
2047 | 1997 | ||
1998 | static int proc_pid_fill_cache(struct file *filp, void *dirent, filldir_t filldir, | ||
1999 | struct task_struct *task, int tgid) | ||
2000 | { | ||
2001 | char name[PROC_NUMBUF]; | ||
2002 | int len = snprintf(name, sizeof(name), "%d", tgid); | ||
2003 | return proc_fill_cache(filp, dirent, filldir, name, len, | ||
2004 | proc_pid_instantiate, task, NULL); | ||
2005 | } | ||
2006 | |||
2048 | /* for the /proc/ directory itself, after non-process stuff has been done */ | 2007 | /* for the /proc/ directory itself, after non-process stuff has been done */ |
2049 | int proc_pid_readdir(struct file * filp, void * dirent, filldir_t filldir) | 2008 | int proc_pid_readdir(struct file * filp, void * dirent, filldir_t filldir) |
2050 | { | 2009 | { |
2051 | char buf[PROC_NUMBUF]; | ||
2052 | unsigned int nr = filp->f_pos - FIRST_PROCESS_ENTRY; | 2010 | unsigned int nr = filp->f_pos - FIRST_PROCESS_ENTRY; |
2011 | struct task_struct *reaper = get_proc_task(filp->f_dentry->d_inode); | ||
2053 | struct task_struct *task; | 2012 | struct task_struct *task; |
2054 | int tgid; | 2013 | int tgid; |
2055 | 2014 | ||
2015 | if (!reaper) | ||
2016 | goto out_no_task; | ||
2017 | |||
2056 | for (; nr < (ARRAY_SIZE(proc_base_stuff) - 1); filp->f_pos++, nr++) { | 2018 | for (; nr < (ARRAY_SIZE(proc_base_stuff) - 1); filp->f_pos++, nr++) { |
2057 | struct pid_entry *p = &proc_base_stuff[nr]; | 2019 | struct pid_entry *p = &proc_base_stuff[nr]; |
2058 | if (filldir(dirent, p->name, p->len, filp->f_pos, | 2020 | if (proc_base_fill_cache(filp, dirent, filldir, reaper, p) < 0) |
2059 | fake_ino(0, p->type), p->mode >> 12) < 0) | ||
2060 | goto out; | 2021 | goto out; |
2061 | } | 2022 | } |
2062 | 2023 | ||
@@ -2064,19 +2025,17 @@ int proc_pid_readdir(struct file * filp, void * dirent, filldir_t filldir) | |||
2064 | for (task = next_tgid(tgid); | 2025 | for (task = next_tgid(tgid); |
2065 | task; | 2026 | task; |
2066 | put_task_struct(task), task = next_tgid(tgid + 1)) { | 2027 | put_task_struct(task), task = next_tgid(tgid + 1)) { |
2067 | int len; | ||
2068 | ino_t ino; | ||
2069 | tgid = task->pid; | 2028 | tgid = task->pid; |
2070 | filp->f_pos = tgid + TGID_OFFSET; | 2029 | filp->f_pos = tgid + TGID_OFFSET; |
2071 | len = snprintf(buf, sizeof(buf), "%d", tgid); | 2030 | if (proc_pid_fill_cache(filp, dirent, filldir, task, tgid) < 0) { |
2072 | ino = fake_ino(tgid, PROC_TGID_INO); | ||
2073 | if (filldir(dirent, buf, len, filp->f_pos, ino, DT_DIR) < 0) { | ||
2074 | put_task_struct(task); | 2031 | put_task_struct(task); |
2075 | goto out; | 2032 | goto out; |
2076 | } | 2033 | } |
2077 | } | 2034 | } |
2078 | filp->f_pos = PID_MAX_LIMIT + TGID_OFFSET; | 2035 | filp->f_pos = PID_MAX_LIMIT + TGID_OFFSET; |
2079 | out: | 2036 | out: |
2037 | put_task_struct(reaper); | ||
2038 | out_no_task: | ||
2080 | return 0; | 2039 | return 0; |
2081 | } | 2040 | } |
2082 | 2041 | ||
@@ -2084,44 +2043,44 @@ out: | |||
2084 | * Tasks | 2043 | * Tasks |
2085 | */ | 2044 | */ |
2086 | static struct pid_entry tid_base_stuff[] = { | 2045 | static struct pid_entry tid_base_stuff[] = { |
2087 | DIR(PROC_TID_FD, "fd", S_IRUSR|S_IXUSR, fd), | 2046 | DIR("fd", S_IRUSR|S_IXUSR, fd), |
2088 | INF(PROC_TID_ENVIRON, "environ", S_IRUSR, pid_environ), | 2047 | INF("environ", S_IRUSR, pid_environ), |
2089 | INF(PROC_TID_AUXV, "auxv", S_IRUSR, pid_auxv), | 2048 | INF("auxv", S_IRUSR, pid_auxv), |
2090 | INF(PROC_TID_STATUS, "status", S_IRUGO, pid_status), | 2049 | INF("status", S_IRUGO, pid_status), |
2091 | INF(PROC_TID_CMDLINE, "cmdline", S_IRUGO, pid_cmdline), | 2050 | INF("cmdline", S_IRUGO, pid_cmdline), |
2092 | INF(PROC_TID_STAT, "stat", S_IRUGO, tid_stat), | 2051 | INF("stat", S_IRUGO, tid_stat), |
2093 | INF(PROC_TID_STATM, "statm", S_IRUGO, pid_statm), | 2052 | INF("statm", S_IRUGO, pid_statm), |
2094 | REG(PROC_TID_MAPS, "maps", S_IRUGO, maps), | 2053 | REG("maps", S_IRUGO, maps), |
2095 | #ifdef CONFIG_NUMA | 2054 | #ifdef CONFIG_NUMA |
2096 | REG(PROC_TID_NUMA_MAPS, "numa_maps", S_IRUGO, numa_maps), | 2055 | REG("numa_maps", S_IRUGO, numa_maps), |
2097 | #endif | 2056 | #endif |
2098 | REG(PROC_TID_MEM, "mem", S_IRUSR|S_IWUSR, mem), | 2057 | REG("mem", S_IRUSR|S_IWUSR, mem), |
2099 | #ifdef CONFIG_SECCOMP | 2058 | #ifdef CONFIG_SECCOMP |
2100 | REG(PROC_TID_SECCOMP, "seccomp", S_IRUSR|S_IWUSR, seccomp), | 2059 | REG("seccomp", S_IRUSR|S_IWUSR, seccomp), |
2101 | #endif | 2060 | #endif |
2102 | LNK(PROC_TID_CWD, "cwd", cwd), | 2061 | LNK("cwd", cwd), |
2103 | LNK(PROC_TID_ROOT, "root", root), | 2062 | LNK("root", root), |
2104 | LNK(PROC_TID_EXE, "exe", exe), | 2063 | LNK("exe", exe), |
2105 | REG(PROC_TID_MOUNTS, "mounts", S_IRUGO, mounts), | 2064 | REG("mounts", S_IRUGO, mounts), |
2106 | #ifdef CONFIG_MMU | 2065 | #ifdef CONFIG_MMU |
2107 | REG(PROC_TID_SMAPS, "smaps", S_IRUGO, smaps), | 2066 | REG("smaps", S_IRUGO, smaps), |
2108 | #endif | 2067 | #endif |
2109 | #ifdef CONFIG_SECURITY | 2068 | #ifdef CONFIG_SECURITY |
2110 | DIR(PROC_TID_ATTR, "attr", S_IRUGO|S_IXUGO, tid_attr), | 2069 | DIR("attr", S_IRUGO|S_IXUGO, tid_attr), |
2111 | #endif | 2070 | #endif |
2112 | #ifdef CONFIG_KALLSYMS | 2071 | #ifdef CONFIG_KALLSYMS |
2113 | INF(PROC_TID_WCHAN, "wchan", S_IRUGO, pid_wchan), | 2072 | INF("wchan", S_IRUGO, pid_wchan), |
2114 | #endif | 2073 | #endif |
2115 | #ifdef CONFIG_SCHEDSTATS | 2074 | #ifdef CONFIG_SCHEDSTATS |
2116 | INF(PROC_TID_SCHEDSTAT, "schedstat", S_IRUGO, pid_schedstat), | 2075 | INF("schedstat", S_IRUGO, pid_schedstat), |
2117 | #endif | 2076 | #endif |
2118 | #ifdef CONFIG_CPUSETS | 2077 | #ifdef CONFIG_CPUSETS |
2119 | REG(PROC_TID_CPUSET, "cpuset", S_IRUGO, cpuset), | 2078 | REG("cpuset", S_IRUGO, cpuset), |
2120 | #endif | 2079 | #endif |
2121 | INF(PROC_TID_OOM_SCORE, "oom_score", S_IRUGO, oom_score), | 2080 | INF("oom_score", S_IRUGO, oom_score), |
2122 | REG(PROC_TID_OOM_ADJUST, "oom_adj", S_IRUGO|S_IWUSR, oom_adjust), | 2081 | REG("oom_adj", S_IRUGO|S_IWUSR, oom_adjust), |
2123 | #ifdef CONFIG_AUDITSYSCALL | 2082 | #ifdef CONFIG_AUDITSYSCALL |
2124 | REG(PROC_TID_LOGINUID, "loginuid", S_IWUSR|S_IRUGO, loginuid), | 2083 | REG("loginuid", S_IWUSR|S_IRUGO, loginuid), |
2125 | #endif | 2084 | #endif |
2126 | {} | 2085 | {} |
2127 | }; | 2086 | }; |
@@ -2153,7 +2112,7 @@ static struct dentry *proc_task_instantiate(struct inode *dir, | |||
2153 | { | 2112 | { |
2154 | struct dentry *error = ERR_PTR(-ENOENT); | 2113 | struct dentry *error = ERR_PTR(-ENOENT); |
2155 | struct inode *inode; | 2114 | struct inode *inode; |
2156 | inode = proc_pid_make_inode(dir->i_sb, task, PROC_TID_INO); | 2115 | inode = proc_pid_make_inode(dir->i_sb, task); |
2157 | 2116 | ||
2158 | if (!inode) | 2117 | if (!inode) |
2159 | goto out; | 2118 | goto out; |
@@ -2279,10 +2238,18 @@ static struct task_struct *next_tid(struct task_struct *start) | |||
2279 | return pos; | 2238 | return pos; |
2280 | } | 2239 | } |
2281 | 2240 | ||
2241 | static int proc_task_fill_cache(struct file *filp, void *dirent, filldir_t filldir, | ||
2242 | struct task_struct *task, int tid) | ||
2243 | { | ||
2244 | char name[PROC_NUMBUF]; | ||
2245 | int len = snprintf(name, sizeof(name), "%d", tid); | ||
2246 | return proc_fill_cache(filp, dirent, filldir, name, len, | ||
2247 | proc_task_instantiate, task, NULL); | ||
2248 | } | ||
2249 | |||
2282 | /* for the /proc/TGID/task/ directories */ | 2250 | /* for the /proc/TGID/task/ directories */ |
2283 | static int proc_task_readdir(struct file * filp, void * dirent, filldir_t filldir) | 2251 | static int proc_task_readdir(struct file * filp, void * dirent, filldir_t filldir) |
2284 | { | 2252 | { |
2285 | char buf[PROC_NUMBUF]; | ||
2286 | struct dentry *dentry = filp->f_dentry; | 2253 | struct dentry *dentry = filp->f_dentry; |
2287 | struct inode *inode = dentry->d_inode; | 2254 | struct inode *inode = dentry->d_inode; |
2288 | struct task_struct *leader = get_proc_task(inode); | 2255 | struct task_struct *leader = get_proc_task(inode); |
@@ -2319,11 +2286,8 @@ static int proc_task_readdir(struct file * filp, void * dirent, filldir_t filldi | |||
2319 | for (task = first_tid(leader, tid, pos - 2); | 2286 | for (task = first_tid(leader, tid, pos - 2); |
2320 | task; | 2287 | task; |
2321 | task = next_tid(task), pos++) { | 2288 | task = next_tid(task), pos++) { |
2322 | int len; | ||
2323 | tid = task->pid; | 2289 | tid = task->pid; |
2324 | len = snprintf(buf, sizeof(buf), "%d", tid); | 2290 | if (proc_task_fill_cache(filp, dirent, filldir, task, tid) < 0) { |
2325 | ino = fake_ino(tid, PROC_TID_INO); | ||
2326 | if (filldir(dirent, buf, len, pos, ino, DT_DIR < 0)) { | ||
2327 | /* returning this tgid failed, save it as the first | 2291 | /* returning this tgid failed, save it as the first |
2328 | * pid for the next readir call */ | 2292 | * pid for the next readir call */ |
2329 | filp->f_version = tid; | 2293 | filp->f_version = tid; |