diff options
| -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; |
