xref: /openbmc/linux/fs/proc/base.c (revision 1da177e4c3f41524e886b7f1b8a0c1fc7321cac2)
1*1da177e4SLinus Torvalds /*
2*1da177e4SLinus Torvalds  *  linux/fs/proc/base.c
3*1da177e4SLinus Torvalds  *
4*1da177e4SLinus Torvalds  *  Copyright (C) 1991, 1992 Linus Torvalds
5*1da177e4SLinus Torvalds  *
6*1da177e4SLinus Torvalds  *  proc base directory handling functions
7*1da177e4SLinus Torvalds  *
8*1da177e4SLinus Torvalds  *  1999, Al Viro. Rewritten. Now it covers the whole per-process part.
9*1da177e4SLinus Torvalds  *  Instead of using magical inumbers to determine the kind of object
10*1da177e4SLinus Torvalds  *  we allocate and fill in-core inodes upon lookup. They don't even
11*1da177e4SLinus Torvalds  *  go into icache. We cache the reference to task_struct upon lookup too.
12*1da177e4SLinus Torvalds  *  Eventually it should become a filesystem in its own. We don't use the
13*1da177e4SLinus Torvalds  *  rest of procfs anymore.
14*1da177e4SLinus Torvalds  */
15*1da177e4SLinus Torvalds 
16*1da177e4SLinus Torvalds #include <asm/uaccess.h>
17*1da177e4SLinus Torvalds 
18*1da177e4SLinus Torvalds #include <linux/config.h>
19*1da177e4SLinus Torvalds #include <linux/errno.h>
20*1da177e4SLinus Torvalds #include <linux/time.h>
21*1da177e4SLinus Torvalds #include <linux/proc_fs.h>
22*1da177e4SLinus Torvalds #include <linux/stat.h>
23*1da177e4SLinus Torvalds #include <linux/init.h>
24*1da177e4SLinus Torvalds #include <linux/file.h>
25*1da177e4SLinus Torvalds #include <linux/string.h>
26*1da177e4SLinus Torvalds #include <linux/seq_file.h>
27*1da177e4SLinus Torvalds #include <linux/namei.h>
28*1da177e4SLinus Torvalds #include <linux/namespace.h>
29*1da177e4SLinus Torvalds #include <linux/mm.h>
30*1da177e4SLinus Torvalds #include <linux/smp_lock.h>
31*1da177e4SLinus Torvalds #include <linux/kallsyms.h>
32*1da177e4SLinus Torvalds #include <linux/mount.h>
33*1da177e4SLinus Torvalds #include <linux/security.h>
34*1da177e4SLinus Torvalds #include <linux/ptrace.h>
35*1da177e4SLinus Torvalds #include <linux/seccomp.h>
36*1da177e4SLinus Torvalds #include <linux/cpuset.h>
37*1da177e4SLinus Torvalds #include <linux/audit.h>
38*1da177e4SLinus Torvalds #include "internal.h"
39*1da177e4SLinus Torvalds 
40*1da177e4SLinus Torvalds /*
41*1da177e4SLinus Torvalds  * For hysterical raisins we keep the same inumbers as in the old procfs.
42*1da177e4SLinus Torvalds  * Feel free to change the macro below - just keep the range distinct from
43*1da177e4SLinus Torvalds  * inumbers of the rest of procfs (currently those are in 0x0000--0xffff).
44*1da177e4SLinus Torvalds  * As soon as we'll get a separate superblock we will be able to forget
45*1da177e4SLinus Torvalds  * about magical ranges too.
46*1da177e4SLinus Torvalds  */
47*1da177e4SLinus Torvalds 
48*1da177e4SLinus Torvalds #define fake_ino(pid,ino) (((pid)<<16)|(ino))
49*1da177e4SLinus Torvalds 
50*1da177e4SLinus Torvalds enum pid_directory_inos {
51*1da177e4SLinus Torvalds 	PROC_TGID_INO = 2,
52*1da177e4SLinus Torvalds 	PROC_TGID_TASK,
53*1da177e4SLinus Torvalds 	PROC_TGID_STATUS,
54*1da177e4SLinus Torvalds 	PROC_TGID_MEM,
55*1da177e4SLinus Torvalds #ifdef CONFIG_SECCOMP
56*1da177e4SLinus Torvalds 	PROC_TGID_SECCOMP,
57*1da177e4SLinus Torvalds #endif
58*1da177e4SLinus Torvalds 	PROC_TGID_CWD,
59*1da177e4SLinus Torvalds 	PROC_TGID_ROOT,
60*1da177e4SLinus Torvalds 	PROC_TGID_EXE,
61*1da177e4SLinus Torvalds 	PROC_TGID_FD,
62*1da177e4SLinus Torvalds 	PROC_TGID_ENVIRON,
63*1da177e4SLinus Torvalds 	PROC_TGID_AUXV,
64*1da177e4SLinus Torvalds 	PROC_TGID_CMDLINE,
65*1da177e4SLinus Torvalds 	PROC_TGID_STAT,
66*1da177e4SLinus Torvalds 	PROC_TGID_STATM,
67*1da177e4SLinus Torvalds 	PROC_TGID_MAPS,
68*1da177e4SLinus Torvalds 	PROC_TGID_MOUNTS,
69*1da177e4SLinus Torvalds 	PROC_TGID_WCHAN,
70*1da177e4SLinus Torvalds #ifdef CONFIG_SCHEDSTATS
71*1da177e4SLinus Torvalds 	PROC_TGID_SCHEDSTAT,
72*1da177e4SLinus Torvalds #endif
73*1da177e4SLinus Torvalds #ifdef CONFIG_CPUSETS
74*1da177e4SLinus Torvalds 	PROC_TGID_CPUSET,
75*1da177e4SLinus Torvalds #endif
76*1da177e4SLinus Torvalds #ifdef CONFIG_SECURITY
77*1da177e4SLinus Torvalds 	PROC_TGID_ATTR,
78*1da177e4SLinus Torvalds 	PROC_TGID_ATTR_CURRENT,
79*1da177e4SLinus Torvalds 	PROC_TGID_ATTR_PREV,
80*1da177e4SLinus Torvalds 	PROC_TGID_ATTR_EXEC,
81*1da177e4SLinus Torvalds 	PROC_TGID_ATTR_FSCREATE,
82*1da177e4SLinus Torvalds #endif
83*1da177e4SLinus Torvalds #ifdef CONFIG_AUDITSYSCALL
84*1da177e4SLinus Torvalds 	PROC_TGID_LOGINUID,
85*1da177e4SLinus Torvalds #endif
86*1da177e4SLinus Torvalds 	PROC_TGID_FD_DIR,
87*1da177e4SLinus Torvalds 	PROC_TGID_OOM_SCORE,
88*1da177e4SLinus Torvalds 	PROC_TGID_OOM_ADJUST,
89*1da177e4SLinus Torvalds 	PROC_TID_INO,
90*1da177e4SLinus Torvalds 	PROC_TID_STATUS,
91*1da177e4SLinus Torvalds 	PROC_TID_MEM,
92*1da177e4SLinus Torvalds #ifdef CONFIG_SECCOMP
93*1da177e4SLinus Torvalds 	PROC_TID_SECCOMP,
94*1da177e4SLinus Torvalds #endif
95*1da177e4SLinus Torvalds 	PROC_TID_CWD,
96*1da177e4SLinus Torvalds 	PROC_TID_ROOT,
97*1da177e4SLinus Torvalds 	PROC_TID_EXE,
98*1da177e4SLinus Torvalds 	PROC_TID_FD,
99*1da177e4SLinus Torvalds 	PROC_TID_ENVIRON,
100*1da177e4SLinus Torvalds 	PROC_TID_AUXV,
101*1da177e4SLinus Torvalds 	PROC_TID_CMDLINE,
102*1da177e4SLinus Torvalds 	PROC_TID_STAT,
103*1da177e4SLinus Torvalds 	PROC_TID_STATM,
104*1da177e4SLinus Torvalds 	PROC_TID_MAPS,
105*1da177e4SLinus Torvalds 	PROC_TID_MOUNTS,
106*1da177e4SLinus Torvalds 	PROC_TID_WCHAN,
107*1da177e4SLinus Torvalds #ifdef CONFIG_SCHEDSTATS
108*1da177e4SLinus Torvalds 	PROC_TID_SCHEDSTAT,
109*1da177e4SLinus Torvalds #endif
110*1da177e4SLinus Torvalds #ifdef CONFIG_CPUSETS
111*1da177e4SLinus Torvalds 	PROC_TID_CPUSET,
112*1da177e4SLinus Torvalds #endif
113*1da177e4SLinus Torvalds #ifdef CONFIG_SECURITY
114*1da177e4SLinus Torvalds 	PROC_TID_ATTR,
115*1da177e4SLinus Torvalds 	PROC_TID_ATTR_CURRENT,
116*1da177e4SLinus Torvalds 	PROC_TID_ATTR_PREV,
117*1da177e4SLinus Torvalds 	PROC_TID_ATTR_EXEC,
118*1da177e4SLinus Torvalds 	PROC_TID_ATTR_FSCREATE,
119*1da177e4SLinus Torvalds #endif
120*1da177e4SLinus Torvalds #ifdef CONFIG_AUDITSYSCALL
121*1da177e4SLinus Torvalds 	PROC_TID_LOGINUID,
122*1da177e4SLinus Torvalds #endif
123*1da177e4SLinus Torvalds 	PROC_TID_FD_DIR = 0x8000,	/* 0x8000-0xffff */
124*1da177e4SLinus Torvalds 	PROC_TID_OOM_SCORE,
125*1da177e4SLinus Torvalds 	PROC_TID_OOM_ADJUST,
126*1da177e4SLinus Torvalds };
127*1da177e4SLinus Torvalds 
128*1da177e4SLinus Torvalds struct pid_entry {
129*1da177e4SLinus Torvalds 	int type;
130*1da177e4SLinus Torvalds 	int len;
131*1da177e4SLinus Torvalds 	char *name;
132*1da177e4SLinus Torvalds 	mode_t mode;
133*1da177e4SLinus Torvalds };
134*1da177e4SLinus Torvalds 
135*1da177e4SLinus Torvalds #define E(type,name,mode) {(type),sizeof(name)-1,(name),(mode)}
136*1da177e4SLinus Torvalds 
137*1da177e4SLinus Torvalds static struct pid_entry tgid_base_stuff[] = {
138*1da177e4SLinus Torvalds 	E(PROC_TGID_TASK,      "task",    S_IFDIR|S_IRUGO|S_IXUGO),
139*1da177e4SLinus Torvalds 	E(PROC_TGID_FD,        "fd",      S_IFDIR|S_IRUSR|S_IXUSR),
140*1da177e4SLinus Torvalds 	E(PROC_TGID_ENVIRON,   "environ", S_IFREG|S_IRUSR),
141*1da177e4SLinus Torvalds 	E(PROC_TGID_AUXV,      "auxv",	  S_IFREG|S_IRUSR),
142*1da177e4SLinus Torvalds 	E(PROC_TGID_STATUS,    "status",  S_IFREG|S_IRUGO),
143*1da177e4SLinus Torvalds 	E(PROC_TGID_CMDLINE,   "cmdline", S_IFREG|S_IRUGO),
144*1da177e4SLinus Torvalds 	E(PROC_TGID_STAT,      "stat",    S_IFREG|S_IRUGO),
145*1da177e4SLinus Torvalds 	E(PROC_TGID_STATM,     "statm",   S_IFREG|S_IRUGO),
146*1da177e4SLinus Torvalds 	E(PROC_TGID_MAPS,      "maps",    S_IFREG|S_IRUGO),
147*1da177e4SLinus Torvalds 	E(PROC_TGID_MEM,       "mem",     S_IFREG|S_IRUSR|S_IWUSR),
148*1da177e4SLinus Torvalds #ifdef CONFIG_SECCOMP
149*1da177e4SLinus Torvalds 	E(PROC_TGID_SECCOMP,   "seccomp", S_IFREG|S_IRUSR|S_IWUSR),
150*1da177e4SLinus Torvalds #endif
151*1da177e4SLinus Torvalds 	E(PROC_TGID_CWD,       "cwd",     S_IFLNK|S_IRWXUGO),
152*1da177e4SLinus Torvalds 	E(PROC_TGID_ROOT,      "root",    S_IFLNK|S_IRWXUGO),
153*1da177e4SLinus Torvalds 	E(PROC_TGID_EXE,       "exe",     S_IFLNK|S_IRWXUGO),
154*1da177e4SLinus Torvalds 	E(PROC_TGID_MOUNTS,    "mounts",  S_IFREG|S_IRUGO),
155*1da177e4SLinus Torvalds #ifdef CONFIG_SECURITY
156*1da177e4SLinus Torvalds 	E(PROC_TGID_ATTR,      "attr",    S_IFDIR|S_IRUGO|S_IXUGO),
157*1da177e4SLinus Torvalds #endif
158*1da177e4SLinus Torvalds #ifdef CONFIG_KALLSYMS
159*1da177e4SLinus Torvalds 	E(PROC_TGID_WCHAN,     "wchan",   S_IFREG|S_IRUGO),
160*1da177e4SLinus Torvalds #endif
161*1da177e4SLinus Torvalds #ifdef CONFIG_SCHEDSTATS
162*1da177e4SLinus Torvalds 	E(PROC_TGID_SCHEDSTAT, "schedstat", S_IFREG|S_IRUGO),
163*1da177e4SLinus Torvalds #endif
164*1da177e4SLinus Torvalds #ifdef CONFIG_CPUSETS
165*1da177e4SLinus Torvalds 	E(PROC_TGID_CPUSET,    "cpuset",  S_IFREG|S_IRUGO),
166*1da177e4SLinus Torvalds #endif
167*1da177e4SLinus Torvalds 	E(PROC_TGID_OOM_SCORE, "oom_score",S_IFREG|S_IRUGO),
168*1da177e4SLinus Torvalds 	E(PROC_TGID_OOM_ADJUST,"oom_adj", S_IFREG|S_IRUGO|S_IWUSR),
169*1da177e4SLinus Torvalds #ifdef CONFIG_AUDITSYSCALL
170*1da177e4SLinus Torvalds 	E(PROC_TGID_LOGINUID, "loginuid", S_IFREG|S_IWUSR|S_IRUGO),
171*1da177e4SLinus Torvalds #endif
172*1da177e4SLinus Torvalds 	{0,0,NULL,0}
173*1da177e4SLinus Torvalds };
174*1da177e4SLinus Torvalds static struct pid_entry tid_base_stuff[] = {
175*1da177e4SLinus Torvalds 	E(PROC_TID_FD,         "fd",      S_IFDIR|S_IRUSR|S_IXUSR),
176*1da177e4SLinus Torvalds 	E(PROC_TID_ENVIRON,    "environ", S_IFREG|S_IRUSR),
177*1da177e4SLinus Torvalds 	E(PROC_TID_AUXV,       "auxv",	  S_IFREG|S_IRUSR),
178*1da177e4SLinus Torvalds 	E(PROC_TID_STATUS,     "status",  S_IFREG|S_IRUGO),
179*1da177e4SLinus Torvalds 	E(PROC_TID_CMDLINE,    "cmdline", S_IFREG|S_IRUGO),
180*1da177e4SLinus Torvalds 	E(PROC_TID_STAT,       "stat",    S_IFREG|S_IRUGO),
181*1da177e4SLinus Torvalds 	E(PROC_TID_STATM,      "statm",   S_IFREG|S_IRUGO),
182*1da177e4SLinus Torvalds 	E(PROC_TID_MAPS,       "maps",    S_IFREG|S_IRUGO),
183*1da177e4SLinus Torvalds 	E(PROC_TID_MEM,        "mem",     S_IFREG|S_IRUSR|S_IWUSR),
184*1da177e4SLinus Torvalds #ifdef CONFIG_SECCOMP
185*1da177e4SLinus Torvalds 	E(PROC_TID_SECCOMP,    "seccomp", S_IFREG|S_IRUSR|S_IWUSR),
186*1da177e4SLinus Torvalds #endif
187*1da177e4SLinus Torvalds 	E(PROC_TID_CWD,        "cwd",     S_IFLNK|S_IRWXUGO),
188*1da177e4SLinus Torvalds 	E(PROC_TID_ROOT,       "root",    S_IFLNK|S_IRWXUGO),
189*1da177e4SLinus Torvalds 	E(PROC_TID_EXE,        "exe",     S_IFLNK|S_IRWXUGO),
190*1da177e4SLinus Torvalds 	E(PROC_TID_MOUNTS,     "mounts",  S_IFREG|S_IRUGO),
191*1da177e4SLinus Torvalds #ifdef CONFIG_SECURITY
192*1da177e4SLinus Torvalds 	E(PROC_TID_ATTR,       "attr",    S_IFDIR|S_IRUGO|S_IXUGO),
193*1da177e4SLinus Torvalds #endif
194*1da177e4SLinus Torvalds #ifdef CONFIG_KALLSYMS
195*1da177e4SLinus Torvalds 	E(PROC_TID_WCHAN,      "wchan",   S_IFREG|S_IRUGO),
196*1da177e4SLinus Torvalds #endif
197*1da177e4SLinus Torvalds #ifdef CONFIG_SCHEDSTATS
198*1da177e4SLinus Torvalds 	E(PROC_TID_SCHEDSTAT, "schedstat",S_IFREG|S_IRUGO),
199*1da177e4SLinus Torvalds #endif
200*1da177e4SLinus Torvalds #ifdef CONFIG_CPUSETS
201*1da177e4SLinus Torvalds 	E(PROC_TID_CPUSET,     "cpuset",  S_IFREG|S_IRUGO),
202*1da177e4SLinus Torvalds #endif
203*1da177e4SLinus Torvalds 	E(PROC_TID_OOM_SCORE,  "oom_score",S_IFREG|S_IRUGO),
204*1da177e4SLinus Torvalds 	E(PROC_TID_OOM_ADJUST, "oom_adj", S_IFREG|S_IRUGO|S_IWUSR),
205*1da177e4SLinus Torvalds #ifdef CONFIG_AUDITSYSCALL
206*1da177e4SLinus Torvalds 	E(PROC_TID_LOGINUID, "loginuid", S_IFREG|S_IWUSR|S_IRUGO),
207*1da177e4SLinus Torvalds #endif
208*1da177e4SLinus Torvalds 	{0,0,NULL,0}
209*1da177e4SLinus Torvalds };
210*1da177e4SLinus Torvalds 
211*1da177e4SLinus Torvalds #ifdef CONFIG_SECURITY
212*1da177e4SLinus Torvalds static struct pid_entry tgid_attr_stuff[] = {
213*1da177e4SLinus Torvalds 	E(PROC_TGID_ATTR_CURRENT,  "current",  S_IFREG|S_IRUGO|S_IWUGO),
214*1da177e4SLinus Torvalds 	E(PROC_TGID_ATTR_PREV,     "prev",     S_IFREG|S_IRUGO),
215*1da177e4SLinus Torvalds 	E(PROC_TGID_ATTR_EXEC,     "exec",     S_IFREG|S_IRUGO|S_IWUGO),
216*1da177e4SLinus Torvalds 	E(PROC_TGID_ATTR_FSCREATE, "fscreate", S_IFREG|S_IRUGO|S_IWUGO),
217*1da177e4SLinus Torvalds 	{0,0,NULL,0}
218*1da177e4SLinus Torvalds };
219*1da177e4SLinus Torvalds static struct pid_entry tid_attr_stuff[] = {
220*1da177e4SLinus Torvalds 	E(PROC_TID_ATTR_CURRENT,   "current",  S_IFREG|S_IRUGO|S_IWUGO),
221*1da177e4SLinus Torvalds 	E(PROC_TID_ATTR_PREV,      "prev",     S_IFREG|S_IRUGO),
222*1da177e4SLinus Torvalds 	E(PROC_TID_ATTR_EXEC,      "exec",     S_IFREG|S_IRUGO|S_IWUGO),
223*1da177e4SLinus Torvalds 	E(PROC_TID_ATTR_FSCREATE,  "fscreate", S_IFREG|S_IRUGO|S_IWUGO),
224*1da177e4SLinus Torvalds 	{0,0,NULL,0}
225*1da177e4SLinus Torvalds };
226*1da177e4SLinus Torvalds #endif
227*1da177e4SLinus Torvalds 
228*1da177e4SLinus Torvalds #undef E
229*1da177e4SLinus Torvalds 
230*1da177e4SLinus Torvalds static int proc_fd_link(struct inode *inode, struct dentry **dentry, struct vfsmount **mnt)
231*1da177e4SLinus Torvalds {
232*1da177e4SLinus Torvalds 	struct task_struct *task = proc_task(inode);
233*1da177e4SLinus Torvalds 	struct files_struct *files;
234*1da177e4SLinus Torvalds 	struct file *file;
235*1da177e4SLinus Torvalds 	int fd = proc_type(inode) - PROC_TID_FD_DIR;
236*1da177e4SLinus Torvalds 
237*1da177e4SLinus Torvalds 	files = get_files_struct(task);
238*1da177e4SLinus Torvalds 	if (files) {
239*1da177e4SLinus Torvalds 		spin_lock(&files->file_lock);
240*1da177e4SLinus Torvalds 		file = fcheck_files(files, fd);
241*1da177e4SLinus Torvalds 		if (file) {
242*1da177e4SLinus Torvalds 			*mnt = mntget(file->f_vfsmnt);
243*1da177e4SLinus Torvalds 			*dentry = dget(file->f_dentry);
244*1da177e4SLinus Torvalds 			spin_unlock(&files->file_lock);
245*1da177e4SLinus Torvalds 			put_files_struct(files);
246*1da177e4SLinus Torvalds 			return 0;
247*1da177e4SLinus Torvalds 		}
248*1da177e4SLinus Torvalds 		spin_unlock(&files->file_lock);
249*1da177e4SLinus Torvalds 		put_files_struct(files);
250*1da177e4SLinus Torvalds 	}
251*1da177e4SLinus Torvalds 	return -ENOENT;
252*1da177e4SLinus Torvalds }
253*1da177e4SLinus Torvalds 
254*1da177e4SLinus Torvalds static int proc_cwd_link(struct inode *inode, struct dentry **dentry, struct vfsmount **mnt)
255*1da177e4SLinus Torvalds {
256*1da177e4SLinus Torvalds 	struct fs_struct *fs;
257*1da177e4SLinus Torvalds 	int result = -ENOENT;
258*1da177e4SLinus Torvalds 	task_lock(proc_task(inode));
259*1da177e4SLinus Torvalds 	fs = proc_task(inode)->fs;
260*1da177e4SLinus Torvalds 	if(fs)
261*1da177e4SLinus Torvalds 		atomic_inc(&fs->count);
262*1da177e4SLinus Torvalds 	task_unlock(proc_task(inode));
263*1da177e4SLinus Torvalds 	if (fs) {
264*1da177e4SLinus Torvalds 		read_lock(&fs->lock);
265*1da177e4SLinus Torvalds 		*mnt = mntget(fs->pwdmnt);
266*1da177e4SLinus Torvalds 		*dentry = dget(fs->pwd);
267*1da177e4SLinus Torvalds 		read_unlock(&fs->lock);
268*1da177e4SLinus Torvalds 		result = 0;
269*1da177e4SLinus Torvalds 		put_fs_struct(fs);
270*1da177e4SLinus Torvalds 	}
271*1da177e4SLinus Torvalds 	return result;
272*1da177e4SLinus Torvalds }
273*1da177e4SLinus Torvalds 
274*1da177e4SLinus Torvalds static int proc_root_link(struct inode *inode, struct dentry **dentry, struct vfsmount **mnt)
275*1da177e4SLinus Torvalds {
276*1da177e4SLinus Torvalds 	struct fs_struct *fs;
277*1da177e4SLinus Torvalds 	int result = -ENOENT;
278*1da177e4SLinus Torvalds 	task_lock(proc_task(inode));
279*1da177e4SLinus Torvalds 	fs = proc_task(inode)->fs;
280*1da177e4SLinus Torvalds 	if(fs)
281*1da177e4SLinus Torvalds 		atomic_inc(&fs->count);
282*1da177e4SLinus Torvalds 	task_unlock(proc_task(inode));
283*1da177e4SLinus Torvalds 	if (fs) {
284*1da177e4SLinus Torvalds 		read_lock(&fs->lock);
285*1da177e4SLinus Torvalds 		*mnt = mntget(fs->rootmnt);
286*1da177e4SLinus Torvalds 		*dentry = dget(fs->root);
287*1da177e4SLinus Torvalds 		read_unlock(&fs->lock);
288*1da177e4SLinus Torvalds 		result = 0;
289*1da177e4SLinus Torvalds 		put_fs_struct(fs);
290*1da177e4SLinus Torvalds 	}
291*1da177e4SLinus Torvalds 	return result;
292*1da177e4SLinus Torvalds }
293*1da177e4SLinus Torvalds 
294*1da177e4SLinus Torvalds #define MAY_PTRACE(task) \
295*1da177e4SLinus Torvalds 	(task == current || \
296*1da177e4SLinus Torvalds 	(task->parent == current && \
297*1da177e4SLinus Torvalds 	(task->ptrace & PT_PTRACED) && \
298*1da177e4SLinus Torvalds 	 (task->state == TASK_STOPPED || task->state == TASK_TRACED) && \
299*1da177e4SLinus Torvalds 	 security_ptrace(current,task) == 0))
300*1da177e4SLinus Torvalds 
301*1da177e4SLinus Torvalds static int may_ptrace_attach(struct task_struct *task)
302*1da177e4SLinus Torvalds {
303*1da177e4SLinus Torvalds 	int retval = 0;
304*1da177e4SLinus Torvalds 
305*1da177e4SLinus Torvalds 	task_lock(task);
306*1da177e4SLinus Torvalds 
307*1da177e4SLinus Torvalds 	if (!task->mm)
308*1da177e4SLinus Torvalds 		goto out;
309*1da177e4SLinus Torvalds 	if (((current->uid != task->euid) ||
310*1da177e4SLinus Torvalds 	     (current->uid != task->suid) ||
311*1da177e4SLinus Torvalds 	     (current->uid != task->uid) ||
312*1da177e4SLinus Torvalds 	     (current->gid != task->egid) ||
313*1da177e4SLinus Torvalds 	     (current->gid != task->sgid) ||
314*1da177e4SLinus Torvalds 	     (current->gid != task->gid)) && !capable(CAP_SYS_PTRACE))
315*1da177e4SLinus Torvalds 		goto out;
316*1da177e4SLinus Torvalds 	rmb();
317*1da177e4SLinus Torvalds 	if (!task->mm->dumpable && !capable(CAP_SYS_PTRACE))
318*1da177e4SLinus Torvalds 		goto out;
319*1da177e4SLinus Torvalds 	if (security_ptrace(current, task))
320*1da177e4SLinus Torvalds 		goto out;
321*1da177e4SLinus Torvalds 
322*1da177e4SLinus Torvalds 	retval = 1;
323*1da177e4SLinus Torvalds out:
324*1da177e4SLinus Torvalds 	task_unlock(task);
325*1da177e4SLinus Torvalds 	return retval;
326*1da177e4SLinus Torvalds }
327*1da177e4SLinus Torvalds 
328*1da177e4SLinus Torvalds static int proc_pid_environ(struct task_struct *task, char * buffer)
329*1da177e4SLinus Torvalds {
330*1da177e4SLinus Torvalds 	int res = 0;
331*1da177e4SLinus Torvalds 	struct mm_struct *mm = get_task_mm(task);
332*1da177e4SLinus Torvalds 	if (mm) {
333*1da177e4SLinus Torvalds 		unsigned int len = mm->env_end - mm->env_start;
334*1da177e4SLinus Torvalds 		if (len > PAGE_SIZE)
335*1da177e4SLinus Torvalds 			len = PAGE_SIZE;
336*1da177e4SLinus Torvalds 		res = access_process_vm(task, mm->env_start, buffer, len, 0);
337*1da177e4SLinus Torvalds 		if (!may_ptrace_attach(task))
338*1da177e4SLinus Torvalds 			res = -ESRCH;
339*1da177e4SLinus Torvalds 		mmput(mm);
340*1da177e4SLinus Torvalds 	}
341*1da177e4SLinus Torvalds 	return res;
342*1da177e4SLinus Torvalds }
343*1da177e4SLinus Torvalds 
344*1da177e4SLinus Torvalds static int proc_pid_cmdline(struct task_struct *task, char * buffer)
345*1da177e4SLinus Torvalds {
346*1da177e4SLinus Torvalds 	int res = 0;
347*1da177e4SLinus Torvalds 	unsigned int len;
348*1da177e4SLinus Torvalds 	struct mm_struct *mm = get_task_mm(task);
349*1da177e4SLinus Torvalds 	if (!mm)
350*1da177e4SLinus Torvalds 		goto out;
351*1da177e4SLinus Torvalds 	if (!mm->arg_end)
352*1da177e4SLinus Torvalds 		goto out_mm;	/* Shh! No looking before we're done */
353*1da177e4SLinus Torvalds 
354*1da177e4SLinus Torvalds  	len = mm->arg_end - mm->arg_start;
355*1da177e4SLinus Torvalds 
356*1da177e4SLinus Torvalds 	if (len > PAGE_SIZE)
357*1da177e4SLinus Torvalds 		len = PAGE_SIZE;
358*1da177e4SLinus Torvalds 
359*1da177e4SLinus Torvalds 	res = access_process_vm(task, mm->arg_start, buffer, len, 0);
360*1da177e4SLinus Torvalds 
361*1da177e4SLinus Torvalds 	// If the nul at the end of args has been overwritten, then
362*1da177e4SLinus Torvalds 	// assume application is using setproctitle(3).
363*1da177e4SLinus Torvalds 	if (res > 0 && buffer[res-1] != '\0' && len < PAGE_SIZE) {
364*1da177e4SLinus Torvalds 		len = strnlen(buffer, res);
365*1da177e4SLinus Torvalds 		if (len < res) {
366*1da177e4SLinus Torvalds 		    res = len;
367*1da177e4SLinus Torvalds 		} else {
368*1da177e4SLinus Torvalds 			len = mm->env_end - mm->env_start;
369*1da177e4SLinus Torvalds 			if (len > PAGE_SIZE - res)
370*1da177e4SLinus Torvalds 				len = PAGE_SIZE - res;
371*1da177e4SLinus Torvalds 			res += access_process_vm(task, mm->env_start, buffer+res, len, 0);
372*1da177e4SLinus Torvalds 			res = strnlen(buffer, res);
373*1da177e4SLinus Torvalds 		}
374*1da177e4SLinus Torvalds 	}
375*1da177e4SLinus Torvalds out_mm:
376*1da177e4SLinus Torvalds 	mmput(mm);
377*1da177e4SLinus Torvalds out:
378*1da177e4SLinus Torvalds 	return res;
379*1da177e4SLinus Torvalds }
380*1da177e4SLinus Torvalds 
381*1da177e4SLinus Torvalds static int proc_pid_auxv(struct task_struct *task, char *buffer)
382*1da177e4SLinus Torvalds {
383*1da177e4SLinus Torvalds 	int res = 0;
384*1da177e4SLinus Torvalds 	struct mm_struct *mm = get_task_mm(task);
385*1da177e4SLinus Torvalds 	if (mm) {
386*1da177e4SLinus Torvalds 		unsigned int nwords = 0;
387*1da177e4SLinus Torvalds 		do
388*1da177e4SLinus Torvalds 			nwords += 2;
389*1da177e4SLinus Torvalds 		while (mm->saved_auxv[nwords - 2] != 0); /* AT_NULL */
390*1da177e4SLinus Torvalds 		res = nwords * sizeof(mm->saved_auxv[0]);
391*1da177e4SLinus Torvalds 		if (res > PAGE_SIZE)
392*1da177e4SLinus Torvalds 			res = PAGE_SIZE;
393*1da177e4SLinus Torvalds 		memcpy(buffer, mm->saved_auxv, res);
394*1da177e4SLinus Torvalds 		mmput(mm);
395*1da177e4SLinus Torvalds 	}
396*1da177e4SLinus Torvalds 	return res;
397*1da177e4SLinus Torvalds }
398*1da177e4SLinus Torvalds 
399*1da177e4SLinus Torvalds 
400*1da177e4SLinus Torvalds #ifdef CONFIG_KALLSYMS
401*1da177e4SLinus Torvalds /*
402*1da177e4SLinus Torvalds  * Provides a wchan file via kallsyms in a proper one-value-per-file format.
403*1da177e4SLinus Torvalds  * Returns the resolved symbol.  If that fails, simply return the address.
404*1da177e4SLinus Torvalds  */
405*1da177e4SLinus Torvalds static int proc_pid_wchan(struct task_struct *task, char *buffer)
406*1da177e4SLinus Torvalds {
407*1da177e4SLinus Torvalds 	char *modname;
408*1da177e4SLinus Torvalds 	const char *sym_name;
409*1da177e4SLinus Torvalds 	unsigned long wchan, size, offset;
410*1da177e4SLinus Torvalds 	char namebuf[KSYM_NAME_LEN+1];
411*1da177e4SLinus Torvalds 
412*1da177e4SLinus Torvalds 	wchan = get_wchan(task);
413*1da177e4SLinus Torvalds 
414*1da177e4SLinus Torvalds 	sym_name = kallsyms_lookup(wchan, &size, &offset, &modname, namebuf);
415*1da177e4SLinus Torvalds 	if (sym_name)
416*1da177e4SLinus Torvalds 		return sprintf(buffer, "%s", sym_name);
417*1da177e4SLinus Torvalds 	return sprintf(buffer, "%lu", wchan);
418*1da177e4SLinus Torvalds }
419*1da177e4SLinus Torvalds #endif /* CONFIG_KALLSYMS */
420*1da177e4SLinus Torvalds 
421*1da177e4SLinus Torvalds #ifdef CONFIG_SCHEDSTATS
422*1da177e4SLinus Torvalds /*
423*1da177e4SLinus Torvalds  * Provides /proc/PID/schedstat
424*1da177e4SLinus Torvalds  */
425*1da177e4SLinus Torvalds static int proc_pid_schedstat(struct task_struct *task, char *buffer)
426*1da177e4SLinus Torvalds {
427*1da177e4SLinus Torvalds 	return sprintf(buffer, "%lu %lu %lu\n",
428*1da177e4SLinus Torvalds 			task->sched_info.cpu_time,
429*1da177e4SLinus Torvalds 			task->sched_info.run_delay,
430*1da177e4SLinus Torvalds 			task->sched_info.pcnt);
431*1da177e4SLinus Torvalds }
432*1da177e4SLinus Torvalds #endif
433*1da177e4SLinus Torvalds 
434*1da177e4SLinus Torvalds /* The badness from the OOM killer */
435*1da177e4SLinus Torvalds unsigned long badness(struct task_struct *p, unsigned long uptime);
436*1da177e4SLinus Torvalds static int proc_oom_score(struct task_struct *task, char *buffer)
437*1da177e4SLinus Torvalds {
438*1da177e4SLinus Torvalds 	unsigned long points;
439*1da177e4SLinus Torvalds 	struct timespec uptime;
440*1da177e4SLinus Torvalds 
441*1da177e4SLinus Torvalds 	do_posix_clock_monotonic_gettime(&uptime);
442*1da177e4SLinus Torvalds 	points = badness(task, uptime.tv_sec);
443*1da177e4SLinus Torvalds 	return sprintf(buffer, "%lu\n", points);
444*1da177e4SLinus Torvalds }
445*1da177e4SLinus Torvalds 
446*1da177e4SLinus Torvalds /************************************************************************/
447*1da177e4SLinus Torvalds /*                       Here the fs part begins                        */
448*1da177e4SLinus Torvalds /************************************************************************/
449*1da177e4SLinus Torvalds 
450*1da177e4SLinus Torvalds /* permission checks */
451*1da177e4SLinus Torvalds 
452*1da177e4SLinus Torvalds static int proc_check_root(struct inode *inode)
453*1da177e4SLinus Torvalds {
454*1da177e4SLinus Torvalds 	struct dentry *de, *base, *root;
455*1da177e4SLinus Torvalds 	struct vfsmount *our_vfsmnt, *vfsmnt, *mnt;
456*1da177e4SLinus Torvalds 	int res = 0;
457*1da177e4SLinus Torvalds 
458*1da177e4SLinus Torvalds 	if (proc_root_link(inode, &root, &vfsmnt)) /* Ewww... */
459*1da177e4SLinus Torvalds 		return -ENOENT;
460*1da177e4SLinus Torvalds 	read_lock(&current->fs->lock);
461*1da177e4SLinus Torvalds 	our_vfsmnt = mntget(current->fs->rootmnt);
462*1da177e4SLinus Torvalds 	base = dget(current->fs->root);
463*1da177e4SLinus Torvalds 	read_unlock(&current->fs->lock);
464*1da177e4SLinus Torvalds 
465*1da177e4SLinus Torvalds 	spin_lock(&vfsmount_lock);
466*1da177e4SLinus Torvalds 	de = root;
467*1da177e4SLinus Torvalds 	mnt = vfsmnt;
468*1da177e4SLinus Torvalds 
469*1da177e4SLinus Torvalds 	while (vfsmnt != our_vfsmnt) {
470*1da177e4SLinus Torvalds 		if (vfsmnt == vfsmnt->mnt_parent)
471*1da177e4SLinus Torvalds 			goto out;
472*1da177e4SLinus Torvalds 		de = vfsmnt->mnt_mountpoint;
473*1da177e4SLinus Torvalds 		vfsmnt = vfsmnt->mnt_parent;
474*1da177e4SLinus Torvalds 	}
475*1da177e4SLinus Torvalds 
476*1da177e4SLinus Torvalds 	if (!is_subdir(de, base))
477*1da177e4SLinus Torvalds 		goto out;
478*1da177e4SLinus Torvalds 	spin_unlock(&vfsmount_lock);
479*1da177e4SLinus Torvalds 
480*1da177e4SLinus Torvalds exit:
481*1da177e4SLinus Torvalds 	dput(base);
482*1da177e4SLinus Torvalds 	mntput(our_vfsmnt);
483*1da177e4SLinus Torvalds 	dput(root);
484*1da177e4SLinus Torvalds 	mntput(mnt);
485*1da177e4SLinus Torvalds 	return res;
486*1da177e4SLinus Torvalds out:
487*1da177e4SLinus Torvalds 	spin_unlock(&vfsmount_lock);
488*1da177e4SLinus Torvalds 	res = -EACCES;
489*1da177e4SLinus Torvalds 	goto exit;
490*1da177e4SLinus Torvalds }
491*1da177e4SLinus Torvalds 
492*1da177e4SLinus Torvalds static int proc_permission(struct inode *inode, int mask, struct nameidata *nd)
493*1da177e4SLinus Torvalds {
494*1da177e4SLinus Torvalds 	if (generic_permission(inode, mask, NULL) != 0)
495*1da177e4SLinus Torvalds 		return -EACCES;
496*1da177e4SLinus Torvalds 	return proc_check_root(inode);
497*1da177e4SLinus Torvalds }
498*1da177e4SLinus Torvalds 
499*1da177e4SLinus Torvalds extern struct seq_operations proc_pid_maps_op;
500*1da177e4SLinus Torvalds static int maps_open(struct inode *inode, struct file *file)
501*1da177e4SLinus Torvalds {
502*1da177e4SLinus Torvalds 	struct task_struct *task = proc_task(inode);
503*1da177e4SLinus Torvalds 	int ret = seq_open(file, &proc_pid_maps_op);
504*1da177e4SLinus Torvalds 	if (!ret) {
505*1da177e4SLinus Torvalds 		struct seq_file *m = file->private_data;
506*1da177e4SLinus Torvalds 		m->private = task;
507*1da177e4SLinus Torvalds 	}
508*1da177e4SLinus Torvalds 	return ret;
509*1da177e4SLinus Torvalds }
510*1da177e4SLinus Torvalds 
511*1da177e4SLinus Torvalds static struct file_operations proc_maps_operations = {
512*1da177e4SLinus Torvalds 	.open		= maps_open,
513*1da177e4SLinus Torvalds 	.read		= seq_read,
514*1da177e4SLinus Torvalds 	.llseek		= seq_lseek,
515*1da177e4SLinus Torvalds 	.release	= seq_release,
516*1da177e4SLinus Torvalds };
517*1da177e4SLinus Torvalds 
518*1da177e4SLinus Torvalds extern struct seq_operations mounts_op;
519*1da177e4SLinus Torvalds static int mounts_open(struct inode *inode, struct file *file)
520*1da177e4SLinus Torvalds {
521*1da177e4SLinus Torvalds 	struct task_struct *task = proc_task(inode);
522*1da177e4SLinus Torvalds 	int ret = seq_open(file, &mounts_op);
523*1da177e4SLinus Torvalds 
524*1da177e4SLinus Torvalds 	if (!ret) {
525*1da177e4SLinus Torvalds 		struct seq_file *m = file->private_data;
526*1da177e4SLinus Torvalds 		struct namespace *namespace;
527*1da177e4SLinus Torvalds 		task_lock(task);
528*1da177e4SLinus Torvalds 		namespace = task->namespace;
529*1da177e4SLinus Torvalds 		if (namespace)
530*1da177e4SLinus Torvalds 			get_namespace(namespace);
531*1da177e4SLinus Torvalds 		task_unlock(task);
532*1da177e4SLinus Torvalds 
533*1da177e4SLinus Torvalds 		if (namespace)
534*1da177e4SLinus Torvalds 			m->private = namespace;
535*1da177e4SLinus Torvalds 		else {
536*1da177e4SLinus Torvalds 			seq_release(inode, file);
537*1da177e4SLinus Torvalds 			ret = -EINVAL;
538*1da177e4SLinus Torvalds 		}
539*1da177e4SLinus Torvalds 	}
540*1da177e4SLinus Torvalds 	return ret;
541*1da177e4SLinus Torvalds }
542*1da177e4SLinus Torvalds 
543*1da177e4SLinus Torvalds static int mounts_release(struct inode *inode, struct file *file)
544*1da177e4SLinus Torvalds {
545*1da177e4SLinus Torvalds 	struct seq_file *m = file->private_data;
546*1da177e4SLinus Torvalds 	struct namespace *namespace = m->private;
547*1da177e4SLinus Torvalds 	put_namespace(namespace);
548*1da177e4SLinus Torvalds 	return seq_release(inode, file);
549*1da177e4SLinus Torvalds }
550*1da177e4SLinus Torvalds 
551*1da177e4SLinus Torvalds static struct file_operations proc_mounts_operations = {
552*1da177e4SLinus Torvalds 	.open		= mounts_open,
553*1da177e4SLinus Torvalds 	.read		= seq_read,
554*1da177e4SLinus Torvalds 	.llseek		= seq_lseek,
555*1da177e4SLinus Torvalds 	.release	= mounts_release,
556*1da177e4SLinus Torvalds };
557*1da177e4SLinus Torvalds 
558*1da177e4SLinus Torvalds #define PROC_BLOCK_SIZE	(3*1024)		/* 4K page size but our output routines use some slack for overruns */
559*1da177e4SLinus Torvalds 
560*1da177e4SLinus Torvalds static ssize_t proc_info_read(struct file * file, char __user * buf,
561*1da177e4SLinus Torvalds 			  size_t count, loff_t *ppos)
562*1da177e4SLinus Torvalds {
563*1da177e4SLinus Torvalds 	struct inode * inode = file->f_dentry->d_inode;
564*1da177e4SLinus Torvalds 	unsigned long page;
565*1da177e4SLinus Torvalds 	ssize_t length;
566*1da177e4SLinus Torvalds 	struct task_struct *task = proc_task(inode);
567*1da177e4SLinus Torvalds 
568*1da177e4SLinus Torvalds 	if (count > PROC_BLOCK_SIZE)
569*1da177e4SLinus Torvalds 		count = PROC_BLOCK_SIZE;
570*1da177e4SLinus Torvalds 	if (!(page = __get_free_page(GFP_KERNEL)))
571*1da177e4SLinus Torvalds 		return -ENOMEM;
572*1da177e4SLinus Torvalds 
573*1da177e4SLinus Torvalds 	length = PROC_I(inode)->op.proc_read(task, (char*)page);
574*1da177e4SLinus Torvalds 
575*1da177e4SLinus Torvalds 	if (length >= 0)
576*1da177e4SLinus Torvalds 		length = simple_read_from_buffer(buf, count, ppos, (char *)page, length);
577*1da177e4SLinus Torvalds 	free_page(page);
578*1da177e4SLinus Torvalds 	return length;
579*1da177e4SLinus Torvalds }
580*1da177e4SLinus Torvalds 
581*1da177e4SLinus Torvalds static struct file_operations proc_info_file_operations = {
582*1da177e4SLinus Torvalds 	.read		= proc_info_read,
583*1da177e4SLinus Torvalds };
584*1da177e4SLinus Torvalds 
585*1da177e4SLinus Torvalds static int mem_open(struct inode* inode, struct file* file)
586*1da177e4SLinus Torvalds {
587*1da177e4SLinus Torvalds 	file->private_data = (void*)((long)current->self_exec_id);
588*1da177e4SLinus Torvalds 	return 0;
589*1da177e4SLinus Torvalds }
590*1da177e4SLinus Torvalds 
591*1da177e4SLinus Torvalds static ssize_t mem_read(struct file * file, char __user * buf,
592*1da177e4SLinus Torvalds 			size_t count, loff_t *ppos)
593*1da177e4SLinus Torvalds {
594*1da177e4SLinus Torvalds 	struct task_struct *task = proc_task(file->f_dentry->d_inode);
595*1da177e4SLinus Torvalds 	char *page;
596*1da177e4SLinus Torvalds 	unsigned long src = *ppos;
597*1da177e4SLinus Torvalds 	int ret = -ESRCH;
598*1da177e4SLinus Torvalds 	struct mm_struct *mm;
599*1da177e4SLinus Torvalds 
600*1da177e4SLinus Torvalds 	if (!MAY_PTRACE(task) || !may_ptrace_attach(task))
601*1da177e4SLinus Torvalds 		goto out;
602*1da177e4SLinus Torvalds 
603*1da177e4SLinus Torvalds 	ret = -ENOMEM;
604*1da177e4SLinus Torvalds 	page = (char *)__get_free_page(GFP_USER);
605*1da177e4SLinus Torvalds 	if (!page)
606*1da177e4SLinus Torvalds 		goto out;
607*1da177e4SLinus Torvalds 
608*1da177e4SLinus Torvalds 	ret = 0;
609*1da177e4SLinus Torvalds 
610*1da177e4SLinus Torvalds 	mm = get_task_mm(task);
611*1da177e4SLinus Torvalds 	if (!mm)
612*1da177e4SLinus Torvalds 		goto out_free;
613*1da177e4SLinus Torvalds 
614*1da177e4SLinus Torvalds 	ret = -EIO;
615*1da177e4SLinus Torvalds 
616*1da177e4SLinus Torvalds 	if (file->private_data != (void*)((long)current->self_exec_id))
617*1da177e4SLinus Torvalds 		goto out_put;
618*1da177e4SLinus Torvalds 
619*1da177e4SLinus Torvalds 	ret = 0;
620*1da177e4SLinus Torvalds 
621*1da177e4SLinus Torvalds 	while (count > 0) {
622*1da177e4SLinus Torvalds 		int this_len, retval;
623*1da177e4SLinus Torvalds 
624*1da177e4SLinus Torvalds 		this_len = (count > PAGE_SIZE) ? PAGE_SIZE : count;
625*1da177e4SLinus Torvalds 		retval = access_process_vm(task, src, page, this_len, 0);
626*1da177e4SLinus Torvalds 		if (!retval || !MAY_PTRACE(task) || !may_ptrace_attach(task)) {
627*1da177e4SLinus Torvalds 			if (!ret)
628*1da177e4SLinus Torvalds 				ret = -EIO;
629*1da177e4SLinus Torvalds 			break;
630*1da177e4SLinus Torvalds 		}
631*1da177e4SLinus Torvalds 
632*1da177e4SLinus Torvalds 		if (copy_to_user(buf, page, retval)) {
633*1da177e4SLinus Torvalds 			ret = -EFAULT;
634*1da177e4SLinus Torvalds 			break;
635*1da177e4SLinus Torvalds 		}
636*1da177e4SLinus Torvalds 
637*1da177e4SLinus Torvalds 		ret += retval;
638*1da177e4SLinus Torvalds 		src += retval;
639*1da177e4SLinus Torvalds 		buf += retval;
640*1da177e4SLinus Torvalds 		count -= retval;
641*1da177e4SLinus Torvalds 	}
642*1da177e4SLinus Torvalds 	*ppos = src;
643*1da177e4SLinus Torvalds 
644*1da177e4SLinus Torvalds out_put:
645*1da177e4SLinus Torvalds 	mmput(mm);
646*1da177e4SLinus Torvalds out_free:
647*1da177e4SLinus Torvalds 	free_page((unsigned long) page);
648*1da177e4SLinus Torvalds out:
649*1da177e4SLinus Torvalds 	return ret;
650*1da177e4SLinus Torvalds }
651*1da177e4SLinus Torvalds 
652*1da177e4SLinus Torvalds #define mem_write NULL
653*1da177e4SLinus Torvalds 
654*1da177e4SLinus Torvalds #ifndef mem_write
655*1da177e4SLinus Torvalds /* This is a security hazard */
656*1da177e4SLinus Torvalds static ssize_t mem_write(struct file * file, const char * buf,
657*1da177e4SLinus Torvalds 			 size_t count, loff_t *ppos)
658*1da177e4SLinus Torvalds {
659*1da177e4SLinus Torvalds 	int copied = 0;
660*1da177e4SLinus Torvalds 	char *page;
661*1da177e4SLinus Torvalds 	struct task_struct *task = proc_task(file->f_dentry->d_inode);
662*1da177e4SLinus Torvalds 	unsigned long dst = *ppos;
663*1da177e4SLinus Torvalds 
664*1da177e4SLinus Torvalds 	if (!MAY_PTRACE(task) || !may_ptrace_attach(task))
665*1da177e4SLinus Torvalds 		return -ESRCH;
666*1da177e4SLinus Torvalds 
667*1da177e4SLinus Torvalds 	page = (char *)__get_free_page(GFP_USER);
668*1da177e4SLinus Torvalds 	if (!page)
669*1da177e4SLinus Torvalds 		return -ENOMEM;
670*1da177e4SLinus Torvalds 
671*1da177e4SLinus Torvalds 	while (count > 0) {
672*1da177e4SLinus Torvalds 		int this_len, retval;
673*1da177e4SLinus Torvalds 
674*1da177e4SLinus Torvalds 		this_len = (count > PAGE_SIZE) ? PAGE_SIZE : count;
675*1da177e4SLinus Torvalds 		if (copy_from_user(page, buf, this_len)) {
676*1da177e4SLinus Torvalds 			copied = -EFAULT;
677*1da177e4SLinus Torvalds 			break;
678*1da177e4SLinus Torvalds 		}
679*1da177e4SLinus Torvalds 		retval = access_process_vm(task, dst, page, this_len, 1);
680*1da177e4SLinus Torvalds 		if (!retval) {
681*1da177e4SLinus Torvalds 			if (!copied)
682*1da177e4SLinus Torvalds 				copied = -EIO;
683*1da177e4SLinus Torvalds 			break;
684*1da177e4SLinus Torvalds 		}
685*1da177e4SLinus Torvalds 		copied += retval;
686*1da177e4SLinus Torvalds 		buf += retval;
687*1da177e4SLinus Torvalds 		dst += retval;
688*1da177e4SLinus Torvalds 		count -= retval;
689*1da177e4SLinus Torvalds 	}
690*1da177e4SLinus Torvalds 	*ppos = dst;
691*1da177e4SLinus Torvalds 	free_page((unsigned long) page);
692*1da177e4SLinus Torvalds 	return copied;
693*1da177e4SLinus Torvalds }
694*1da177e4SLinus Torvalds #endif
695*1da177e4SLinus Torvalds 
696*1da177e4SLinus Torvalds static loff_t mem_lseek(struct file * file, loff_t offset, int orig)
697*1da177e4SLinus Torvalds {
698*1da177e4SLinus Torvalds 	switch (orig) {
699*1da177e4SLinus Torvalds 	case 0:
700*1da177e4SLinus Torvalds 		file->f_pos = offset;
701*1da177e4SLinus Torvalds 		break;
702*1da177e4SLinus Torvalds 	case 1:
703*1da177e4SLinus Torvalds 		file->f_pos += offset;
704*1da177e4SLinus Torvalds 		break;
705*1da177e4SLinus Torvalds 	default:
706*1da177e4SLinus Torvalds 		return -EINVAL;
707*1da177e4SLinus Torvalds 	}
708*1da177e4SLinus Torvalds 	force_successful_syscall_return();
709*1da177e4SLinus Torvalds 	return file->f_pos;
710*1da177e4SLinus Torvalds }
711*1da177e4SLinus Torvalds 
712*1da177e4SLinus Torvalds static struct file_operations proc_mem_operations = {
713*1da177e4SLinus Torvalds 	.llseek		= mem_lseek,
714*1da177e4SLinus Torvalds 	.read		= mem_read,
715*1da177e4SLinus Torvalds 	.write		= mem_write,
716*1da177e4SLinus Torvalds 	.open		= mem_open,
717*1da177e4SLinus Torvalds };
718*1da177e4SLinus Torvalds 
719*1da177e4SLinus Torvalds static ssize_t oom_adjust_read(struct file *file, char __user *buf,
720*1da177e4SLinus Torvalds 				size_t count, loff_t *ppos)
721*1da177e4SLinus Torvalds {
722*1da177e4SLinus Torvalds 	struct task_struct *task = proc_task(file->f_dentry->d_inode);
723*1da177e4SLinus Torvalds 	char buffer[8];
724*1da177e4SLinus Torvalds 	size_t len;
725*1da177e4SLinus Torvalds 	int oom_adjust = task->oomkilladj;
726*1da177e4SLinus Torvalds 	loff_t __ppos = *ppos;
727*1da177e4SLinus Torvalds 
728*1da177e4SLinus Torvalds 	len = sprintf(buffer, "%i\n", oom_adjust);
729*1da177e4SLinus Torvalds 	if (__ppos >= len)
730*1da177e4SLinus Torvalds 		return 0;
731*1da177e4SLinus Torvalds 	if (count > len-__ppos)
732*1da177e4SLinus Torvalds 		count = len-__ppos;
733*1da177e4SLinus Torvalds 	if (copy_to_user(buf, buffer + __ppos, count))
734*1da177e4SLinus Torvalds 		return -EFAULT;
735*1da177e4SLinus Torvalds 	*ppos = __ppos + count;
736*1da177e4SLinus Torvalds 	return count;
737*1da177e4SLinus Torvalds }
738*1da177e4SLinus Torvalds 
739*1da177e4SLinus Torvalds static ssize_t oom_adjust_write(struct file *file, const char __user *buf,
740*1da177e4SLinus Torvalds 				size_t count, loff_t *ppos)
741*1da177e4SLinus Torvalds {
742*1da177e4SLinus Torvalds 	struct task_struct *task = proc_task(file->f_dentry->d_inode);
743*1da177e4SLinus Torvalds 	char buffer[8], *end;
744*1da177e4SLinus Torvalds 	int oom_adjust;
745*1da177e4SLinus Torvalds 
746*1da177e4SLinus Torvalds 	if (!capable(CAP_SYS_RESOURCE))
747*1da177e4SLinus Torvalds 		return -EPERM;
748*1da177e4SLinus Torvalds 	memset(buffer, 0, 8);
749*1da177e4SLinus Torvalds 	if (count > 6)
750*1da177e4SLinus Torvalds 		count = 6;
751*1da177e4SLinus Torvalds 	if (copy_from_user(buffer, buf, count))
752*1da177e4SLinus Torvalds 		return -EFAULT;
753*1da177e4SLinus Torvalds 	oom_adjust = simple_strtol(buffer, &end, 0);
754*1da177e4SLinus Torvalds 	if (oom_adjust < -16 || oom_adjust > 15)
755*1da177e4SLinus Torvalds 		return -EINVAL;
756*1da177e4SLinus Torvalds 	if (*end == '\n')
757*1da177e4SLinus Torvalds 		end++;
758*1da177e4SLinus Torvalds 	task->oomkilladj = oom_adjust;
759*1da177e4SLinus Torvalds 	if (end - buffer == 0)
760*1da177e4SLinus Torvalds 		return -EIO;
761*1da177e4SLinus Torvalds 	return end - buffer;
762*1da177e4SLinus Torvalds }
763*1da177e4SLinus Torvalds 
764*1da177e4SLinus Torvalds static struct file_operations proc_oom_adjust_operations = {
765*1da177e4SLinus Torvalds 	.read		= oom_adjust_read,
766*1da177e4SLinus Torvalds 	.write		= oom_adjust_write,
767*1da177e4SLinus Torvalds };
768*1da177e4SLinus Torvalds 
769*1da177e4SLinus Torvalds static struct inode_operations proc_mem_inode_operations = {
770*1da177e4SLinus Torvalds 	.permission	= proc_permission,
771*1da177e4SLinus Torvalds };
772*1da177e4SLinus Torvalds 
773*1da177e4SLinus Torvalds #ifdef CONFIG_AUDITSYSCALL
774*1da177e4SLinus Torvalds #define TMPBUFLEN 21
775*1da177e4SLinus Torvalds static ssize_t proc_loginuid_read(struct file * file, char __user * buf,
776*1da177e4SLinus Torvalds 				  size_t count, loff_t *ppos)
777*1da177e4SLinus Torvalds {
778*1da177e4SLinus Torvalds 	struct inode * inode = file->f_dentry->d_inode;
779*1da177e4SLinus Torvalds 	struct task_struct *task = proc_task(inode);
780*1da177e4SLinus Torvalds 	ssize_t length;
781*1da177e4SLinus Torvalds 	char tmpbuf[TMPBUFLEN];
782*1da177e4SLinus Torvalds 
783*1da177e4SLinus Torvalds 	length = scnprintf(tmpbuf, TMPBUFLEN, "%u",
784*1da177e4SLinus Torvalds 				audit_get_loginuid(task->audit_context));
785*1da177e4SLinus Torvalds 	return simple_read_from_buffer(buf, count, ppos, tmpbuf, length);
786*1da177e4SLinus Torvalds }
787*1da177e4SLinus Torvalds 
788*1da177e4SLinus Torvalds static ssize_t proc_loginuid_write(struct file * file, const char __user * buf,
789*1da177e4SLinus Torvalds 				   size_t count, loff_t *ppos)
790*1da177e4SLinus Torvalds {
791*1da177e4SLinus Torvalds 	struct inode * inode = file->f_dentry->d_inode;
792*1da177e4SLinus Torvalds 	char *page, *tmp;
793*1da177e4SLinus Torvalds 	ssize_t length;
794*1da177e4SLinus Torvalds 	struct task_struct *task = proc_task(inode);
795*1da177e4SLinus Torvalds 	uid_t loginuid;
796*1da177e4SLinus Torvalds 
797*1da177e4SLinus Torvalds 	if (!capable(CAP_AUDIT_CONTROL))
798*1da177e4SLinus Torvalds 		return -EPERM;
799*1da177e4SLinus Torvalds 
800*1da177e4SLinus Torvalds 	if (current != task)
801*1da177e4SLinus Torvalds 		return -EPERM;
802*1da177e4SLinus Torvalds 
803*1da177e4SLinus Torvalds 	if (count > PAGE_SIZE)
804*1da177e4SLinus Torvalds 		count = PAGE_SIZE;
805*1da177e4SLinus Torvalds 
806*1da177e4SLinus Torvalds 	if (*ppos != 0) {
807*1da177e4SLinus Torvalds 		/* No partial writes. */
808*1da177e4SLinus Torvalds 		return -EINVAL;
809*1da177e4SLinus Torvalds 	}
810*1da177e4SLinus Torvalds 	page = (char*)__get_free_page(GFP_USER);
811*1da177e4SLinus Torvalds 	if (!page)
812*1da177e4SLinus Torvalds 		return -ENOMEM;
813*1da177e4SLinus Torvalds 	length = -EFAULT;
814*1da177e4SLinus Torvalds 	if (copy_from_user(page, buf, count))
815*1da177e4SLinus Torvalds 		goto out_free_page;
816*1da177e4SLinus Torvalds 
817*1da177e4SLinus Torvalds 	loginuid = simple_strtoul(page, &tmp, 10);
818*1da177e4SLinus Torvalds 	if (tmp == page) {
819*1da177e4SLinus Torvalds 		length = -EINVAL;
820*1da177e4SLinus Torvalds 		goto out_free_page;
821*1da177e4SLinus Torvalds 
822*1da177e4SLinus Torvalds 	}
823*1da177e4SLinus Torvalds 	length = audit_set_loginuid(task->audit_context, loginuid);
824*1da177e4SLinus Torvalds 	if (likely(length == 0))
825*1da177e4SLinus Torvalds 		length = count;
826*1da177e4SLinus Torvalds 
827*1da177e4SLinus Torvalds out_free_page:
828*1da177e4SLinus Torvalds 	free_page((unsigned long) page);
829*1da177e4SLinus Torvalds 	return length;
830*1da177e4SLinus Torvalds }
831*1da177e4SLinus Torvalds 
832*1da177e4SLinus Torvalds static struct file_operations proc_loginuid_operations = {
833*1da177e4SLinus Torvalds 	.read		= proc_loginuid_read,
834*1da177e4SLinus Torvalds 	.write		= proc_loginuid_write,
835*1da177e4SLinus Torvalds };
836*1da177e4SLinus Torvalds #endif
837*1da177e4SLinus Torvalds 
838*1da177e4SLinus Torvalds #ifdef CONFIG_SECCOMP
839*1da177e4SLinus Torvalds static ssize_t seccomp_read(struct file *file, char __user *buf,
840*1da177e4SLinus Torvalds 			    size_t count, loff_t *ppos)
841*1da177e4SLinus Torvalds {
842*1da177e4SLinus Torvalds 	struct task_struct *tsk = proc_task(file->f_dentry->d_inode);
843*1da177e4SLinus Torvalds 	char __buf[20];
844*1da177e4SLinus Torvalds 	loff_t __ppos = *ppos;
845*1da177e4SLinus Torvalds 	size_t len;
846*1da177e4SLinus Torvalds 
847*1da177e4SLinus Torvalds 	/* no need to print the trailing zero, so use only len */
848*1da177e4SLinus Torvalds 	len = sprintf(__buf, "%u\n", tsk->seccomp.mode);
849*1da177e4SLinus Torvalds 	if (__ppos >= len)
850*1da177e4SLinus Torvalds 		return 0;
851*1da177e4SLinus Torvalds 	if (count > len - __ppos)
852*1da177e4SLinus Torvalds 		count = len - __ppos;
853*1da177e4SLinus Torvalds 	if (copy_to_user(buf, __buf + __ppos, count))
854*1da177e4SLinus Torvalds 		return -EFAULT;
855*1da177e4SLinus Torvalds 	*ppos = __ppos + count;
856*1da177e4SLinus Torvalds 	return count;
857*1da177e4SLinus Torvalds }
858*1da177e4SLinus Torvalds 
859*1da177e4SLinus Torvalds static ssize_t seccomp_write(struct file *file, const char __user *buf,
860*1da177e4SLinus Torvalds 			     size_t count, loff_t *ppos)
861*1da177e4SLinus Torvalds {
862*1da177e4SLinus Torvalds 	struct task_struct *tsk = proc_task(file->f_dentry->d_inode);
863*1da177e4SLinus Torvalds 	char __buf[20], *end;
864*1da177e4SLinus Torvalds 	unsigned int seccomp_mode;
865*1da177e4SLinus Torvalds 
866*1da177e4SLinus Torvalds 	/* can set it only once to be even more secure */
867*1da177e4SLinus Torvalds 	if (unlikely(tsk->seccomp.mode))
868*1da177e4SLinus Torvalds 		return -EPERM;
869*1da177e4SLinus Torvalds 
870*1da177e4SLinus Torvalds 	memset(__buf, 0, sizeof(__buf));
871*1da177e4SLinus Torvalds 	count = min(count, sizeof(__buf) - 1);
872*1da177e4SLinus Torvalds 	if (copy_from_user(__buf, buf, count))
873*1da177e4SLinus Torvalds 		return -EFAULT;
874*1da177e4SLinus Torvalds 	seccomp_mode = simple_strtoul(__buf, &end, 0);
875*1da177e4SLinus Torvalds 	if (*end == '\n')
876*1da177e4SLinus Torvalds 		end++;
877*1da177e4SLinus Torvalds 	if (seccomp_mode && seccomp_mode <= NR_SECCOMP_MODES) {
878*1da177e4SLinus Torvalds 		tsk->seccomp.mode = seccomp_mode;
879*1da177e4SLinus Torvalds 		set_tsk_thread_flag(tsk, TIF_SECCOMP);
880*1da177e4SLinus Torvalds 	} else
881*1da177e4SLinus Torvalds 		return -EINVAL;
882*1da177e4SLinus Torvalds 	if (unlikely(!(end - __buf)))
883*1da177e4SLinus Torvalds 		return -EIO;
884*1da177e4SLinus Torvalds 	return end - __buf;
885*1da177e4SLinus Torvalds }
886*1da177e4SLinus Torvalds 
887*1da177e4SLinus Torvalds static struct file_operations proc_seccomp_operations = {
888*1da177e4SLinus Torvalds 	.read		= seccomp_read,
889*1da177e4SLinus Torvalds 	.write		= seccomp_write,
890*1da177e4SLinus Torvalds };
891*1da177e4SLinus Torvalds #endif /* CONFIG_SECCOMP */
892*1da177e4SLinus Torvalds 
893*1da177e4SLinus Torvalds static int proc_pid_follow_link(struct dentry *dentry, struct nameidata *nd)
894*1da177e4SLinus Torvalds {
895*1da177e4SLinus Torvalds 	struct inode *inode = dentry->d_inode;
896*1da177e4SLinus Torvalds 	int error = -EACCES;
897*1da177e4SLinus Torvalds 
898*1da177e4SLinus Torvalds 	/* We don't need a base pointer in the /proc filesystem */
899*1da177e4SLinus Torvalds 	path_release(nd);
900*1da177e4SLinus Torvalds 
901*1da177e4SLinus Torvalds 	if (current->fsuid != inode->i_uid && !capable(CAP_DAC_OVERRIDE))
902*1da177e4SLinus Torvalds 		goto out;
903*1da177e4SLinus Torvalds 	error = proc_check_root(inode);
904*1da177e4SLinus Torvalds 	if (error)
905*1da177e4SLinus Torvalds 		goto out;
906*1da177e4SLinus Torvalds 
907*1da177e4SLinus Torvalds 	error = PROC_I(inode)->op.proc_get_link(inode, &nd->dentry, &nd->mnt);
908*1da177e4SLinus Torvalds 	nd->last_type = LAST_BIND;
909*1da177e4SLinus Torvalds out:
910*1da177e4SLinus Torvalds 	return error;
911*1da177e4SLinus Torvalds }
912*1da177e4SLinus Torvalds 
913*1da177e4SLinus Torvalds static int do_proc_readlink(struct dentry *dentry, struct vfsmount *mnt,
914*1da177e4SLinus Torvalds 			    char __user *buffer, int buflen)
915*1da177e4SLinus Torvalds {
916*1da177e4SLinus Torvalds 	struct inode * inode;
917*1da177e4SLinus Torvalds 	char *tmp = (char*)__get_free_page(GFP_KERNEL), *path;
918*1da177e4SLinus Torvalds 	int len;
919*1da177e4SLinus Torvalds 
920*1da177e4SLinus Torvalds 	if (!tmp)
921*1da177e4SLinus Torvalds 		return -ENOMEM;
922*1da177e4SLinus Torvalds 
923*1da177e4SLinus Torvalds 	inode = dentry->d_inode;
924*1da177e4SLinus Torvalds 	path = d_path(dentry, mnt, tmp, PAGE_SIZE);
925*1da177e4SLinus Torvalds 	len = PTR_ERR(path);
926*1da177e4SLinus Torvalds 	if (IS_ERR(path))
927*1da177e4SLinus Torvalds 		goto out;
928*1da177e4SLinus Torvalds 	len = tmp + PAGE_SIZE - 1 - path;
929*1da177e4SLinus Torvalds 
930*1da177e4SLinus Torvalds 	if (len > buflen)
931*1da177e4SLinus Torvalds 		len = buflen;
932*1da177e4SLinus Torvalds 	if (copy_to_user(buffer, path, len))
933*1da177e4SLinus Torvalds 		len = -EFAULT;
934*1da177e4SLinus Torvalds  out:
935*1da177e4SLinus Torvalds 	free_page((unsigned long)tmp);
936*1da177e4SLinus Torvalds 	return len;
937*1da177e4SLinus Torvalds }
938*1da177e4SLinus Torvalds 
939*1da177e4SLinus Torvalds static int proc_pid_readlink(struct dentry * dentry, char __user * buffer, int buflen)
940*1da177e4SLinus Torvalds {
941*1da177e4SLinus Torvalds 	int error = -EACCES;
942*1da177e4SLinus Torvalds 	struct inode *inode = dentry->d_inode;
943*1da177e4SLinus Torvalds 	struct dentry *de;
944*1da177e4SLinus Torvalds 	struct vfsmount *mnt = NULL;
945*1da177e4SLinus Torvalds 
946*1da177e4SLinus Torvalds 	lock_kernel();
947*1da177e4SLinus Torvalds 
948*1da177e4SLinus Torvalds 	if (current->fsuid != inode->i_uid && !capable(CAP_DAC_OVERRIDE))
949*1da177e4SLinus Torvalds 		goto out;
950*1da177e4SLinus Torvalds 	error = proc_check_root(inode);
951*1da177e4SLinus Torvalds 	if (error)
952*1da177e4SLinus Torvalds 		goto out;
953*1da177e4SLinus Torvalds 
954*1da177e4SLinus Torvalds 	error = PROC_I(inode)->op.proc_get_link(inode, &de, &mnt);
955*1da177e4SLinus Torvalds 	if (error)
956*1da177e4SLinus Torvalds 		goto out;
957*1da177e4SLinus Torvalds 
958*1da177e4SLinus Torvalds 	error = do_proc_readlink(de, mnt, buffer, buflen);
959*1da177e4SLinus Torvalds 	dput(de);
960*1da177e4SLinus Torvalds 	mntput(mnt);
961*1da177e4SLinus Torvalds out:
962*1da177e4SLinus Torvalds 	unlock_kernel();
963*1da177e4SLinus Torvalds 	return error;
964*1da177e4SLinus Torvalds }
965*1da177e4SLinus Torvalds 
966*1da177e4SLinus Torvalds static struct inode_operations proc_pid_link_inode_operations = {
967*1da177e4SLinus Torvalds 	.readlink	= proc_pid_readlink,
968*1da177e4SLinus Torvalds 	.follow_link	= proc_pid_follow_link
969*1da177e4SLinus Torvalds };
970*1da177e4SLinus Torvalds 
971*1da177e4SLinus Torvalds #define NUMBUF 10
972*1da177e4SLinus Torvalds 
973*1da177e4SLinus Torvalds static int proc_readfd(struct file * filp, void * dirent, filldir_t filldir)
974*1da177e4SLinus Torvalds {
975*1da177e4SLinus Torvalds 	struct inode *inode = filp->f_dentry->d_inode;
976*1da177e4SLinus Torvalds 	struct task_struct *p = proc_task(inode);
977*1da177e4SLinus Torvalds 	unsigned int fd, tid, ino;
978*1da177e4SLinus Torvalds 	int retval;
979*1da177e4SLinus Torvalds 	char buf[NUMBUF];
980*1da177e4SLinus Torvalds 	struct files_struct * files;
981*1da177e4SLinus Torvalds 
982*1da177e4SLinus Torvalds 	retval = -ENOENT;
983*1da177e4SLinus Torvalds 	if (!pid_alive(p))
984*1da177e4SLinus Torvalds 		goto out;
985*1da177e4SLinus Torvalds 	retval = 0;
986*1da177e4SLinus Torvalds 	tid = p->pid;
987*1da177e4SLinus Torvalds 
988*1da177e4SLinus Torvalds 	fd = filp->f_pos;
989*1da177e4SLinus Torvalds 	switch (fd) {
990*1da177e4SLinus Torvalds 		case 0:
991*1da177e4SLinus Torvalds 			if (filldir(dirent, ".", 1, 0, inode->i_ino, DT_DIR) < 0)
992*1da177e4SLinus Torvalds 				goto out;
993*1da177e4SLinus Torvalds 			filp->f_pos++;
994*1da177e4SLinus Torvalds 		case 1:
995*1da177e4SLinus Torvalds 			ino = fake_ino(tid, PROC_TID_INO);
996*1da177e4SLinus Torvalds 			if (filldir(dirent, "..", 2, 1, ino, DT_DIR) < 0)
997*1da177e4SLinus Torvalds 				goto out;
998*1da177e4SLinus Torvalds 			filp->f_pos++;
999*1da177e4SLinus Torvalds 		default:
1000*1da177e4SLinus Torvalds 			files = get_files_struct(p);
1001*1da177e4SLinus Torvalds 			if (!files)
1002*1da177e4SLinus Torvalds 				goto out;
1003*1da177e4SLinus Torvalds 			spin_lock(&files->file_lock);
1004*1da177e4SLinus Torvalds 			for (fd = filp->f_pos-2;
1005*1da177e4SLinus Torvalds 			     fd < files->max_fds;
1006*1da177e4SLinus Torvalds 			     fd++, filp->f_pos++) {
1007*1da177e4SLinus Torvalds 				unsigned int i,j;
1008*1da177e4SLinus Torvalds 
1009*1da177e4SLinus Torvalds 				if (!fcheck_files(files, fd))
1010*1da177e4SLinus Torvalds 					continue;
1011*1da177e4SLinus Torvalds 				spin_unlock(&files->file_lock);
1012*1da177e4SLinus Torvalds 
1013*1da177e4SLinus Torvalds 				j = NUMBUF;
1014*1da177e4SLinus Torvalds 				i = fd;
1015*1da177e4SLinus Torvalds 				do {
1016*1da177e4SLinus Torvalds 					j--;
1017*1da177e4SLinus Torvalds 					buf[j] = '0' + (i % 10);
1018*1da177e4SLinus Torvalds 					i /= 10;
1019*1da177e4SLinus Torvalds 				} while (i);
1020*1da177e4SLinus Torvalds 
1021*1da177e4SLinus Torvalds 				ino = fake_ino(tid, PROC_TID_FD_DIR + fd);
1022*1da177e4SLinus Torvalds 				if (filldir(dirent, buf+j, NUMBUF-j, fd+2, ino, DT_LNK) < 0) {
1023*1da177e4SLinus Torvalds 					spin_lock(&files->file_lock);
1024*1da177e4SLinus Torvalds 					break;
1025*1da177e4SLinus Torvalds 				}
1026*1da177e4SLinus Torvalds 				spin_lock(&files->file_lock);
1027*1da177e4SLinus Torvalds 			}
1028*1da177e4SLinus Torvalds 			spin_unlock(&files->file_lock);
1029*1da177e4SLinus Torvalds 			put_files_struct(files);
1030*1da177e4SLinus Torvalds 	}
1031*1da177e4SLinus Torvalds out:
1032*1da177e4SLinus Torvalds 	return retval;
1033*1da177e4SLinus Torvalds }
1034*1da177e4SLinus Torvalds 
1035*1da177e4SLinus Torvalds static int proc_pident_readdir(struct file *filp,
1036*1da177e4SLinus Torvalds 		void *dirent, filldir_t filldir,
1037*1da177e4SLinus Torvalds 		struct pid_entry *ents, unsigned int nents)
1038*1da177e4SLinus Torvalds {
1039*1da177e4SLinus Torvalds 	int i;
1040*1da177e4SLinus Torvalds 	int pid;
1041*1da177e4SLinus Torvalds 	struct dentry *dentry = filp->f_dentry;
1042*1da177e4SLinus Torvalds 	struct inode *inode = dentry->d_inode;
1043*1da177e4SLinus Torvalds 	struct pid_entry *p;
1044*1da177e4SLinus Torvalds 	ino_t ino;
1045*1da177e4SLinus Torvalds 	int ret;
1046*1da177e4SLinus Torvalds 
1047*1da177e4SLinus Torvalds 	ret = -ENOENT;
1048*1da177e4SLinus Torvalds 	if (!pid_alive(proc_task(inode)))
1049*1da177e4SLinus Torvalds 		goto out;
1050*1da177e4SLinus Torvalds 
1051*1da177e4SLinus Torvalds 	ret = 0;
1052*1da177e4SLinus Torvalds 	pid = proc_task(inode)->pid;
1053*1da177e4SLinus Torvalds 	i = filp->f_pos;
1054*1da177e4SLinus Torvalds 	switch (i) {
1055*1da177e4SLinus Torvalds 	case 0:
1056*1da177e4SLinus Torvalds 		ino = inode->i_ino;
1057*1da177e4SLinus Torvalds 		if (filldir(dirent, ".", 1, i, ino, DT_DIR) < 0)
1058*1da177e4SLinus Torvalds 			goto out;
1059*1da177e4SLinus Torvalds 		i++;
1060*1da177e4SLinus Torvalds 		filp->f_pos++;
1061*1da177e4SLinus Torvalds 		/* fall through */
1062*1da177e4SLinus Torvalds 	case 1:
1063*1da177e4SLinus Torvalds 		ino = parent_ino(dentry);
1064*1da177e4SLinus Torvalds 		if (filldir(dirent, "..", 2, i, ino, DT_DIR) < 0)
1065*1da177e4SLinus Torvalds 			goto out;
1066*1da177e4SLinus Torvalds 		i++;
1067*1da177e4SLinus Torvalds 		filp->f_pos++;
1068*1da177e4SLinus Torvalds 		/* fall through */
1069*1da177e4SLinus Torvalds 	default:
1070*1da177e4SLinus Torvalds 		i -= 2;
1071*1da177e4SLinus Torvalds 		if (i >= nents) {
1072*1da177e4SLinus Torvalds 			ret = 1;
1073*1da177e4SLinus Torvalds 			goto out;
1074*1da177e4SLinus Torvalds 		}
1075*1da177e4SLinus Torvalds 		p = ents + i;
1076*1da177e4SLinus Torvalds 		while (p->name) {
1077*1da177e4SLinus Torvalds 			if (filldir(dirent, p->name, p->len, filp->f_pos,
1078*1da177e4SLinus Torvalds 				    fake_ino(pid, p->type), p->mode >> 12) < 0)
1079*1da177e4SLinus Torvalds 				goto out;
1080*1da177e4SLinus Torvalds 			filp->f_pos++;
1081*1da177e4SLinus Torvalds 			p++;
1082*1da177e4SLinus Torvalds 		}
1083*1da177e4SLinus Torvalds 	}
1084*1da177e4SLinus Torvalds 
1085*1da177e4SLinus Torvalds 	ret = 1;
1086*1da177e4SLinus Torvalds out:
1087*1da177e4SLinus Torvalds 	return ret;
1088*1da177e4SLinus Torvalds }
1089*1da177e4SLinus Torvalds 
1090*1da177e4SLinus Torvalds static int proc_tgid_base_readdir(struct file * filp,
1091*1da177e4SLinus Torvalds 			     void * dirent, filldir_t filldir)
1092*1da177e4SLinus Torvalds {
1093*1da177e4SLinus Torvalds 	return proc_pident_readdir(filp,dirent,filldir,
1094*1da177e4SLinus Torvalds 				   tgid_base_stuff,ARRAY_SIZE(tgid_base_stuff));
1095*1da177e4SLinus Torvalds }
1096*1da177e4SLinus Torvalds 
1097*1da177e4SLinus Torvalds static int proc_tid_base_readdir(struct file * filp,
1098*1da177e4SLinus Torvalds 			     void * dirent, filldir_t filldir)
1099*1da177e4SLinus Torvalds {
1100*1da177e4SLinus Torvalds 	return proc_pident_readdir(filp,dirent,filldir,
1101*1da177e4SLinus Torvalds 				   tid_base_stuff,ARRAY_SIZE(tid_base_stuff));
1102*1da177e4SLinus Torvalds }
1103*1da177e4SLinus Torvalds 
1104*1da177e4SLinus Torvalds /* building an inode */
1105*1da177e4SLinus Torvalds 
1106*1da177e4SLinus Torvalds static int task_dumpable(struct task_struct *task)
1107*1da177e4SLinus Torvalds {
1108*1da177e4SLinus Torvalds 	int dumpable = 0;
1109*1da177e4SLinus Torvalds 	struct mm_struct *mm;
1110*1da177e4SLinus Torvalds 
1111*1da177e4SLinus Torvalds 	task_lock(task);
1112*1da177e4SLinus Torvalds 	mm = task->mm;
1113*1da177e4SLinus Torvalds 	if (mm)
1114*1da177e4SLinus Torvalds 		dumpable = mm->dumpable;
1115*1da177e4SLinus Torvalds 	task_unlock(task);
1116*1da177e4SLinus Torvalds 	return dumpable;
1117*1da177e4SLinus Torvalds }
1118*1da177e4SLinus Torvalds 
1119*1da177e4SLinus Torvalds 
1120*1da177e4SLinus Torvalds static struct inode *proc_pid_make_inode(struct super_block * sb, struct task_struct *task, int ino)
1121*1da177e4SLinus Torvalds {
1122*1da177e4SLinus Torvalds 	struct inode * inode;
1123*1da177e4SLinus Torvalds 	struct proc_inode *ei;
1124*1da177e4SLinus Torvalds 
1125*1da177e4SLinus Torvalds 	/* We need a new inode */
1126*1da177e4SLinus Torvalds 
1127*1da177e4SLinus Torvalds 	inode = new_inode(sb);
1128*1da177e4SLinus Torvalds 	if (!inode)
1129*1da177e4SLinus Torvalds 		goto out;
1130*1da177e4SLinus Torvalds 
1131*1da177e4SLinus Torvalds 	/* Common stuff */
1132*1da177e4SLinus Torvalds 	ei = PROC_I(inode);
1133*1da177e4SLinus Torvalds 	ei->task = NULL;
1134*1da177e4SLinus Torvalds 	inode->i_mtime = inode->i_atime = inode->i_ctime = CURRENT_TIME;
1135*1da177e4SLinus Torvalds 	inode->i_ino = fake_ino(task->pid, ino);
1136*1da177e4SLinus Torvalds 
1137*1da177e4SLinus Torvalds 	if (!pid_alive(task))
1138*1da177e4SLinus Torvalds 		goto out_unlock;
1139*1da177e4SLinus Torvalds 
1140*1da177e4SLinus Torvalds 	/*
1141*1da177e4SLinus Torvalds 	 * grab the reference to task.
1142*1da177e4SLinus Torvalds 	 */
1143*1da177e4SLinus Torvalds 	get_task_struct(task);
1144*1da177e4SLinus Torvalds 	ei->task = task;
1145*1da177e4SLinus Torvalds 	ei->type = ino;
1146*1da177e4SLinus Torvalds 	inode->i_uid = 0;
1147*1da177e4SLinus Torvalds 	inode->i_gid = 0;
1148*1da177e4SLinus Torvalds 	if (ino == PROC_TGID_INO || ino == PROC_TID_INO || task_dumpable(task)) {
1149*1da177e4SLinus Torvalds 		inode->i_uid = task->euid;
1150*1da177e4SLinus Torvalds 		inode->i_gid = task->egid;
1151*1da177e4SLinus Torvalds 	}
1152*1da177e4SLinus Torvalds 	security_task_to_inode(task, inode);
1153*1da177e4SLinus Torvalds 
1154*1da177e4SLinus Torvalds out:
1155*1da177e4SLinus Torvalds 	return inode;
1156*1da177e4SLinus Torvalds 
1157*1da177e4SLinus Torvalds out_unlock:
1158*1da177e4SLinus Torvalds 	ei->pde = NULL;
1159*1da177e4SLinus Torvalds 	iput(inode);
1160*1da177e4SLinus Torvalds 	return NULL;
1161*1da177e4SLinus Torvalds }
1162*1da177e4SLinus Torvalds 
1163*1da177e4SLinus Torvalds /* dentry stuff */
1164*1da177e4SLinus Torvalds 
1165*1da177e4SLinus Torvalds /*
1166*1da177e4SLinus Torvalds  *	Exceptional case: normally we are not allowed to unhash a busy
1167*1da177e4SLinus Torvalds  * directory. In this case, however, we can do it - no aliasing problems
1168*1da177e4SLinus Torvalds  * due to the way we treat inodes.
1169*1da177e4SLinus Torvalds  *
1170*1da177e4SLinus Torvalds  * Rewrite the inode's ownerships here because the owning task may have
1171*1da177e4SLinus Torvalds  * performed a setuid(), etc.
1172*1da177e4SLinus Torvalds  */
1173*1da177e4SLinus Torvalds static int pid_revalidate(struct dentry *dentry, struct nameidata *nd)
1174*1da177e4SLinus Torvalds {
1175*1da177e4SLinus Torvalds 	struct inode *inode = dentry->d_inode;
1176*1da177e4SLinus Torvalds 	struct task_struct *task = proc_task(inode);
1177*1da177e4SLinus Torvalds 	if (pid_alive(task)) {
1178*1da177e4SLinus Torvalds 		if (proc_type(inode) == PROC_TGID_INO || proc_type(inode) == PROC_TID_INO || task_dumpable(task)) {
1179*1da177e4SLinus Torvalds 			inode->i_uid = task->euid;
1180*1da177e4SLinus Torvalds 			inode->i_gid = task->egid;
1181*1da177e4SLinus Torvalds 		} else {
1182*1da177e4SLinus Torvalds 			inode->i_uid = 0;
1183*1da177e4SLinus Torvalds 			inode->i_gid = 0;
1184*1da177e4SLinus Torvalds 		}
1185*1da177e4SLinus Torvalds 		security_task_to_inode(task, inode);
1186*1da177e4SLinus Torvalds 		return 1;
1187*1da177e4SLinus Torvalds 	}
1188*1da177e4SLinus Torvalds 	d_drop(dentry);
1189*1da177e4SLinus Torvalds 	return 0;
1190*1da177e4SLinus Torvalds }
1191*1da177e4SLinus Torvalds 
1192*1da177e4SLinus Torvalds static int tid_fd_revalidate(struct dentry *dentry, struct nameidata *nd)
1193*1da177e4SLinus Torvalds {
1194*1da177e4SLinus Torvalds 	struct inode *inode = dentry->d_inode;
1195*1da177e4SLinus Torvalds 	struct task_struct *task = proc_task(inode);
1196*1da177e4SLinus Torvalds 	int fd = proc_type(inode) - PROC_TID_FD_DIR;
1197*1da177e4SLinus Torvalds 	struct files_struct *files;
1198*1da177e4SLinus Torvalds 
1199*1da177e4SLinus Torvalds 	files = get_files_struct(task);
1200*1da177e4SLinus Torvalds 	if (files) {
1201*1da177e4SLinus Torvalds 		spin_lock(&files->file_lock);
1202*1da177e4SLinus Torvalds 		if (fcheck_files(files, fd)) {
1203*1da177e4SLinus Torvalds 			spin_unlock(&files->file_lock);
1204*1da177e4SLinus Torvalds 			put_files_struct(files);
1205*1da177e4SLinus Torvalds 			if (task_dumpable(task)) {
1206*1da177e4SLinus Torvalds 				inode->i_uid = task->euid;
1207*1da177e4SLinus Torvalds 				inode->i_gid = task->egid;
1208*1da177e4SLinus Torvalds 			} else {
1209*1da177e4SLinus Torvalds 				inode->i_uid = 0;
1210*1da177e4SLinus Torvalds 				inode->i_gid = 0;
1211*1da177e4SLinus Torvalds 			}
1212*1da177e4SLinus Torvalds 			security_task_to_inode(task, inode);
1213*1da177e4SLinus Torvalds 			return 1;
1214*1da177e4SLinus Torvalds 		}
1215*1da177e4SLinus Torvalds 		spin_unlock(&files->file_lock);
1216*1da177e4SLinus Torvalds 		put_files_struct(files);
1217*1da177e4SLinus Torvalds 	}
1218*1da177e4SLinus Torvalds 	d_drop(dentry);
1219*1da177e4SLinus Torvalds 	return 0;
1220*1da177e4SLinus Torvalds }
1221*1da177e4SLinus Torvalds 
1222*1da177e4SLinus Torvalds static void pid_base_iput(struct dentry *dentry, struct inode *inode)
1223*1da177e4SLinus Torvalds {
1224*1da177e4SLinus Torvalds 	struct task_struct *task = proc_task(inode);
1225*1da177e4SLinus Torvalds 	spin_lock(&task->proc_lock);
1226*1da177e4SLinus Torvalds 	if (task->proc_dentry == dentry)
1227*1da177e4SLinus Torvalds 		task->proc_dentry = NULL;
1228*1da177e4SLinus Torvalds 	spin_unlock(&task->proc_lock);
1229*1da177e4SLinus Torvalds 	iput(inode);
1230*1da177e4SLinus Torvalds }
1231*1da177e4SLinus Torvalds 
1232*1da177e4SLinus Torvalds static int pid_delete_dentry(struct dentry * dentry)
1233*1da177e4SLinus Torvalds {
1234*1da177e4SLinus Torvalds 	/* Is the task we represent dead?
1235*1da177e4SLinus Torvalds 	 * If so, then don't put the dentry on the lru list,
1236*1da177e4SLinus Torvalds 	 * kill it immediately.
1237*1da177e4SLinus Torvalds 	 */
1238*1da177e4SLinus Torvalds 	return !pid_alive(proc_task(dentry->d_inode));
1239*1da177e4SLinus Torvalds }
1240*1da177e4SLinus Torvalds 
1241*1da177e4SLinus Torvalds static struct dentry_operations tid_fd_dentry_operations =
1242*1da177e4SLinus Torvalds {
1243*1da177e4SLinus Torvalds 	.d_revalidate	= tid_fd_revalidate,
1244*1da177e4SLinus Torvalds 	.d_delete	= pid_delete_dentry,
1245*1da177e4SLinus Torvalds };
1246*1da177e4SLinus Torvalds 
1247*1da177e4SLinus Torvalds static struct dentry_operations pid_dentry_operations =
1248*1da177e4SLinus Torvalds {
1249*1da177e4SLinus Torvalds 	.d_revalidate	= pid_revalidate,
1250*1da177e4SLinus Torvalds 	.d_delete	= pid_delete_dentry,
1251*1da177e4SLinus Torvalds };
1252*1da177e4SLinus Torvalds 
1253*1da177e4SLinus Torvalds static struct dentry_operations pid_base_dentry_operations =
1254*1da177e4SLinus Torvalds {
1255*1da177e4SLinus Torvalds 	.d_revalidate	= pid_revalidate,
1256*1da177e4SLinus Torvalds 	.d_iput		= pid_base_iput,
1257*1da177e4SLinus Torvalds 	.d_delete	= pid_delete_dentry,
1258*1da177e4SLinus Torvalds };
1259*1da177e4SLinus Torvalds 
1260*1da177e4SLinus Torvalds /* Lookups */
1261*1da177e4SLinus Torvalds 
1262*1da177e4SLinus Torvalds static unsigned name_to_int(struct dentry *dentry)
1263*1da177e4SLinus Torvalds {
1264*1da177e4SLinus Torvalds 	const char *name = dentry->d_name.name;
1265*1da177e4SLinus Torvalds 	int len = dentry->d_name.len;
1266*1da177e4SLinus Torvalds 	unsigned n = 0;
1267*1da177e4SLinus Torvalds 
1268*1da177e4SLinus Torvalds 	if (len > 1 && *name == '0')
1269*1da177e4SLinus Torvalds 		goto out;
1270*1da177e4SLinus Torvalds 	while (len-- > 0) {
1271*1da177e4SLinus Torvalds 		unsigned c = *name++ - '0';
1272*1da177e4SLinus Torvalds 		if (c > 9)
1273*1da177e4SLinus Torvalds 			goto out;
1274*1da177e4SLinus Torvalds 		if (n >= (~0U-9)/10)
1275*1da177e4SLinus Torvalds 			goto out;
1276*1da177e4SLinus Torvalds 		n *= 10;
1277*1da177e4SLinus Torvalds 		n += c;
1278*1da177e4SLinus Torvalds 	}
1279*1da177e4SLinus Torvalds 	return n;
1280*1da177e4SLinus Torvalds out:
1281*1da177e4SLinus Torvalds 	return ~0U;
1282*1da177e4SLinus Torvalds }
1283*1da177e4SLinus Torvalds 
1284*1da177e4SLinus Torvalds /* SMP-safe */
1285*1da177e4SLinus Torvalds static struct dentry *proc_lookupfd(struct inode * dir, struct dentry * dentry, struct nameidata *nd)
1286*1da177e4SLinus Torvalds {
1287*1da177e4SLinus Torvalds 	struct task_struct *task = proc_task(dir);
1288*1da177e4SLinus Torvalds 	unsigned fd = name_to_int(dentry);
1289*1da177e4SLinus Torvalds 	struct file * file;
1290*1da177e4SLinus Torvalds 	struct files_struct * files;
1291*1da177e4SLinus Torvalds 	struct inode *inode;
1292*1da177e4SLinus Torvalds 	struct proc_inode *ei;
1293*1da177e4SLinus Torvalds 
1294*1da177e4SLinus Torvalds 	if (fd == ~0U)
1295*1da177e4SLinus Torvalds 		goto out;
1296*1da177e4SLinus Torvalds 	if (!pid_alive(task))
1297*1da177e4SLinus Torvalds 		goto out;
1298*1da177e4SLinus Torvalds 
1299*1da177e4SLinus Torvalds 	inode = proc_pid_make_inode(dir->i_sb, task, PROC_TID_FD_DIR+fd);
1300*1da177e4SLinus Torvalds 	if (!inode)
1301*1da177e4SLinus Torvalds 		goto out;
1302*1da177e4SLinus Torvalds 	ei = PROC_I(inode);
1303*1da177e4SLinus Torvalds 	files = get_files_struct(task);
1304*1da177e4SLinus Torvalds 	if (!files)
1305*1da177e4SLinus Torvalds 		goto out_unlock;
1306*1da177e4SLinus Torvalds 	inode->i_mode = S_IFLNK;
1307*1da177e4SLinus Torvalds 	spin_lock(&files->file_lock);
1308*1da177e4SLinus Torvalds 	file = fcheck_files(files, fd);
1309*1da177e4SLinus Torvalds 	if (!file)
1310*1da177e4SLinus Torvalds 		goto out_unlock2;
1311*1da177e4SLinus Torvalds 	if (file->f_mode & 1)
1312*1da177e4SLinus Torvalds 		inode->i_mode |= S_IRUSR | S_IXUSR;
1313*1da177e4SLinus Torvalds 	if (file->f_mode & 2)
1314*1da177e4SLinus Torvalds 		inode->i_mode |= S_IWUSR | S_IXUSR;
1315*1da177e4SLinus Torvalds 	spin_unlock(&files->file_lock);
1316*1da177e4SLinus Torvalds 	put_files_struct(files);
1317*1da177e4SLinus Torvalds 	inode->i_op = &proc_pid_link_inode_operations;
1318*1da177e4SLinus Torvalds 	inode->i_size = 64;
1319*1da177e4SLinus Torvalds 	ei->op.proc_get_link = proc_fd_link;
1320*1da177e4SLinus Torvalds 	dentry->d_op = &tid_fd_dentry_operations;
1321*1da177e4SLinus Torvalds 	d_add(dentry, inode);
1322*1da177e4SLinus Torvalds 	return NULL;
1323*1da177e4SLinus Torvalds 
1324*1da177e4SLinus Torvalds out_unlock2:
1325*1da177e4SLinus Torvalds 	spin_unlock(&files->file_lock);
1326*1da177e4SLinus Torvalds 	put_files_struct(files);
1327*1da177e4SLinus Torvalds out_unlock:
1328*1da177e4SLinus Torvalds 	iput(inode);
1329*1da177e4SLinus Torvalds out:
1330*1da177e4SLinus Torvalds 	return ERR_PTR(-ENOENT);
1331*1da177e4SLinus Torvalds }
1332*1da177e4SLinus Torvalds 
1333*1da177e4SLinus Torvalds static int proc_task_readdir(struct file * filp, void * dirent, filldir_t filldir);
1334*1da177e4SLinus Torvalds static struct dentry *proc_task_lookup(struct inode *dir, struct dentry * dentry, struct nameidata *nd);
1335*1da177e4SLinus Torvalds 
1336*1da177e4SLinus Torvalds static struct file_operations proc_fd_operations = {
1337*1da177e4SLinus Torvalds 	.read		= generic_read_dir,
1338*1da177e4SLinus Torvalds 	.readdir	= proc_readfd,
1339*1da177e4SLinus Torvalds };
1340*1da177e4SLinus Torvalds 
1341*1da177e4SLinus Torvalds static struct file_operations proc_task_operations = {
1342*1da177e4SLinus Torvalds 	.read		= generic_read_dir,
1343*1da177e4SLinus Torvalds 	.readdir	= proc_task_readdir,
1344*1da177e4SLinus Torvalds };
1345*1da177e4SLinus Torvalds 
1346*1da177e4SLinus Torvalds /*
1347*1da177e4SLinus Torvalds  * proc directories can do almost nothing..
1348*1da177e4SLinus Torvalds  */
1349*1da177e4SLinus Torvalds static struct inode_operations proc_fd_inode_operations = {
1350*1da177e4SLinus Torvalds 	.lookup		= proc_lookupfd,
1351*1da177e4SLinus Torvalds 	.permission	= proc_permission,
1352*1da177e4SLinus Torvalds };
1353*1da177e4SLinus Torvalds 
1354*1da177e4SLinus Torvalds static struct inode_operations proc_task_inode_operations = {
1355*1da177e4SLinus Torvalds 	.lookup		= proc_task_lookup,
1356*1da177e4SLinus Torvalds 	.permission	= proc_permission,
1357*1da177e4SLinus Torvalds };
1358*1da177e4SLinus Torvalds 
1359*1da177e4SLinus Torvalds #ifdef CONFIG_SECURITY
1360*1da177e4SLinus Torvalds static ssize_t proc_pid_attr_read(struct file * file, char __user * buf,
1361*1da177e4SLinus Torvalds 				  size_t count, loff_t *ppos)
1362*1da177e4SLinus Torvalds {
1363*1da177e4SLinus Torvalds 	struct inode * inode = file->f_dentry->d_inode;
1364*1da177e4SLinus Torvalds 	unsigned long page;
1365*1da177e4SLinus Torvalds 	ssize_t length;
1366*1da177e4SLinus Torvalds 	struct task_struct *task = proc_task(inode);
1367*1da177e4SLinus Torvalds 
1368*1da177e4SLinus Torvalds 	if (count > PAGE_SIZE)
1369*1da177e4SLinus Torvalds 		count = PAGE_SIZE;
1370*1da177e4SLinus Torvalds 	if (!(page = __get_free_page(GFP_KERNEL)))
1371*1da177e4SLinus Torvalds 		return -ENOMEM;
1372*1da177e4SLinus Torvalds 
1373*1da177e4SLinus Torvalds 	length = security_getprocattr(task,
1374*1da177e4SLinus Torvalds 				      (char*)file->f_dentry->d_name.name,
1375*1da177e4SLinus Torvalds 				      (void*)page, count);
1376*1da177e4SLinus Torvalds 	if (length >= 0)
1377*1da177e4SLinus Torvalds 		length = simple_read_from_buffer(buf, count, ppos, (char *)page, length);
1378*1da177e4SLinus Torvalds 	free_page(page);
1379*1da177e4SLinus Torvalds 	return length;
1380*1da177e4SLinus Torvalds }
1381*1da177e4SLinus Torvalds 
1382*1da177e4SLinus Torvalds static ssize_t proc_pid_attr_write(struct file * file, const char __user * buf,
1383*1da177e4SLinus Torvalds 				   size_t count, loff_t *ppos)
1384*1da177e4SLinus Torvalds {
1385*1da177e4SLinus Torvalds 	struct inode * inode = file->f_dentry->d_inode;
1386*1da177e4SLinus Torvalds 	char *page;
1387*1da177e4SLinus Torvalds 	ssize_t length;
1388*1da177e4SLinus Torvalds 	struct task_struct *task = proc_task(inode);
1389*1da177e4SLinus Torvalds 
1390*1da177e4SLinus Torvalds 	if (count > PAGE_SIZE)
1391*1da177e4SLinus Torvalds 		count = PAGE_SIZE;
1392*1da177e4SLinus Torvalds 	if (*ppos != 0) {
1393*1da177e4SLinus Torvalds 		/* No partial writes. */
1394*1da177e4SLinus Torvalds 		return -EINVAL;
1395*1da177e4SLinus Torvalds 	}
1396*1da177e4SLinus Torvalds 	page = (char*)__get_free_page(GFP_USER);
1397*1da177e4SLinus Torvalds 	if (!page)
1398*1da177e4SLinus Torvalds 		return -ENOMEM;
1399*1da177e4SLinus Torvalds 	length = -EFAULT;
1400*1da177e4SLinus Torvalds 	if (copy_from_user(page, buf, count))
1401*1da177e4SLinus Torvalds 		goto out;
1402*1da177e4SLinus Torvalds 
1403*1da177e4SLinus Torvalds 	length = security_setprocattr(task,
1404*1da177e4SLinus Torvalds 				      (char*)file->f_dentry->d_name.name,
1405*1da177e4SLinus Torvalds 				      (void*)page, count);
1406*1da177e4SLinus Torvalds out:
1407*1da177e4SLinus Torvalds 	free_page((unsigned long) page);
1408*1da177e4SLinus Torvalds 	return length;
1409*1da177e4SLinus Torvalds }
1410*1da177e4SLinus Torvalds 
1411*1da177e4SLinus Torvalds static struct file_operations proc_pid_attr_operations = {
1412*1da177e4SLinus Torvalds 	.read		= proc_pid_attr_read,
1413*1da177e4SLinus Torvalds 	.write		= proc_pid_attr_write,
1414*1da177e4SLinus Torvalds };
1415*1da177e4SLinus Torvalds 
1416*1da177e4SLinus Torvalds static struct file_operations proc_tid_attr_operations;
1417*1da177e4SLinus Torvalds static struct inode_operations proc_tid_attr_inode_operations;
1418*1da177e4SLinus Torvalds static struct file_operations proc_tgid_attr_operations;
1419*1da177e4SLinus Torvalds static struct inode_operations proc_tgid_attr_inode_operations;
1420*1da177e4SLinus Torvalds #endif
1421*1da177e4SLinus Torvalds 
1422*1da177e4SLinus Torvalds /* SMP-safe */
1423*1da177e4SLinus Torvalds static struct dentry *proc_pident_lookup(struct inode *dir,
1424*1da177e4SLinus Torvalds 					 struct dentry *dentry,
1425*1da177e4SLinus Torvalds 					 struct pid_entry *ents)
1426*1da177e4SLinus Torvalds {
1427*1da177e4SLinus Torvalds 	struct inode *inode;
1428*1da177e4SLinus Torvalds 	int error;
1429*1da177e4SLinus Torvalds 	struct task_struct *task = proc_task(dir);
1430*1da177e4SLinus Torvalds 	struct pid_entry *p;
1431*1da177e4SLinus Torvalds 	struct proc_inode *ei;
1432*1da177e4SLinus Torvalds 
1433*1da177e4SLinus Torvalds 	error = -ENOENT;
1434*1da177e4SLinus Torvalds 	inode = NULL;
1435*1da177e4SLinus Torvalds 
1436*1da177e4SLinus Torvalds 	if (!pid_alive(task))
1437*1da177e4SLinus Torvalds 		goto out;
1438*1da177e4SLinus Torvalds 
1439*1da177e4SLinus Torvalds 	for (p = ents; p->name; p++) {
1440*1da177e4SLinus Torvalds 		if (p->len != dentry->d_name.len)
1441*1da177e4SLinus Torvalds 			continue;
1442*1da177e4SLinus Torvalds 		if (!memcmp(dentry->d_name.name, p->name, p->len))
1443*1da177e4SLinus Torvalds 			break;
1444*1da177e4SLinus Torvalds 	}
1445*1da177e4SLinus Torvalds 	if (!p->name)
1446*1da177e4SLinus Torvalds 		goto out;
1447*1da177e4SLinus Torvalds 
1448*1da177e4SLinus Torvalds 	error = -EINVAL;
1449*1da177e4SLinus Torvalds 	inode = proc_pid_make_inode(dir->i_sb, task, p->type);
1450*1da177e4SLinus Torvalds 	if (!inode)
1451*1da177e4SLinus Torvalds 		goto out;
1452*1da177e4SLinus Torvalds 
1453*1da177e4SLinus Torvalds 	ei = PROC_I(inode);
1454*1da177e4SLinus Torvalds 	inode->i_mode = p->mode;
1455*1da177e4SLinus Torvalds 	/*
1456*1da177e4SLinus Torvalds 	 * Yes, it does not scale. And it should not. Don't add
1457*1da177e4SLinus Torvalds 	 * new entries into /proc/<tgid>/ without very good reasons.
1458*1da177e4SLinus Torvalds 	 */
1459*1da177e4SLinus Torvalds 	switch(p->type) {
1460*1da177e4SLinus Torvalds 		case PROC_TGID_TASK:
1461*1da177e4SLinus Torvalds 			inode->i_nlink = 3;
1462*1da177e4SLinus Torvalds 			inode->i_op = &proc_task_inode_operations;
1463*1da177e4SLinus Torvalds 			inode->i_fop = &proc_task_operations;
1464*1da177e4SLinus Torvalds 			break;
1465*1da177e4SLinus Torvalds 		case PROC_TID_FD:
1466*1da177e4SLinus Torvalds 		case PROC_TGID_FD:
1467*1da177e4SLinus Torvalds 			inode->i_nlink = 2;
1468*1da177e4SLinus Torvalds 			inode->i_op = &proc_fd_inode_operations;
1469*1da177e4SLinus Torvalds 			inode->i_fop = &proc_fd_operations;
1470*1da177e4SLinus Torvalds 			break;
1471*1da177e4SLinus Torvalds 		case PROC_TID_EXE:
1472*1da177e4SLinus Torvalds 		case PROC_TGID_EXE:
1473*1da177e4SLinus Torvalds 			inode->i_op = &proc_pid_link_inode_operations;
1474*1da177e4SLinus Torvalds 			ei->op.proc_get_link = proc_exe_link;
1475*1da177e4SLinus Torvalds 			break;
1476*1da177e4SLinus Torvalds 		case PROC_TID_CWD:
1477*1da177e4SLinus Torvalds 		case PROC_TGID_CWD:
1478*1da177e4SLinus Torvalds 			inode->i_op = &proc_pid_link_inode_operations;
1479*1da177e4SLinus Torvalds 			ei->op.proc_get_link = proc_cwd_link;
1480*1da177e4SLinus Torvalds 			break;
1481*1da177e4SLinus Torvalds 		case PROC_TID_ROOT:
1482*1da177e4SLinus Torvalds 		case PROC_TGID_ROOT:
1483*1da177e4SLinus Torvalds 			inode->i_op = &proc_pid_link_inode_operations;
1484*1da177e4SLinus Torvalds 			ei->op.proc_get_link = proc_root_link;
1485*1da177e4SLinus Torvalds 			break;
1486*1da177e4SLinus Torvalds 		case PROC_TID_ENVIRON:
1487*1da177e4SLinus Torvalds 		case PROC_TGID_ENVIRON:
1488*1da177e4SLinus Torvalds 			inode->i_fop = &proc_info_file_operations;
1489*1da177e4SLinus Torvalds 			ei->op.proc_read = proc_pid_environ;
1490*1da177e4SLinus Torvalds 			break;
1491*1da177e4SLinus Torvalds 		case PROC_TID_AUXV:
1492*1da177e4SLinus Torvalds 		case PROC_TGID_AUXV:
1493*1da177e4SLinus Torvalds 			inode->i_fop = &proc_info_file_operations;
1494*1da177e4SLinus Torvalds 			ei->op.proc_read = proc_pid_auxv;
1495*1da177e4SLinus Torvalds 			break;
1496*1da177e4SLinus Torvalds 		case PROC_TID_STATUS:
1497*1da177e4SLinus Torvalds 		case PROC_TGID_STATUS:
1498*1da177e4SLinus Torvalds 			inode->i_fop = &proc_info_file_operations;
1499*1da177e4SLinus Torvalds 			ei->op.proc_read = proc_pid_status;
1500*1da177e4SLinus Torvalds 			break;
1501*1da177e4SLinus Torvalds 		case PROC_TID_STAT:
1502*1da177e4SLinus Torvalds 			inode->i_fop = &proc_info_file_operations;
1503*1da177e4SLinus Torvalds 			ei->op.proc_read = proc_tid_stat;
1504*1da177e4SLinus Torvalds 			break;
1505*1da177e4SLinus Torvalds 		case PROC_TGID_STAT:
1506*1da177e4SLinus Torvalds 			inode->i_fop = &proc_info_file_operations;
1507*1da177e4SLinus Torvalds 			ei->op.proc_read = proc_tgid_stat;
1508*1da177e4SLinus Torvalds 			break;
1509*1da177e4SLinus Torvalds 		case PROC_TID_CMDLINE:
1510*1da177e4SLinus Torvalds 		case PROC_TGID_CMDLINE:
1511*1da177e4SLinus Torvalds 			inode->i_fop = &proc_info_file_operations;
1512*1da177e4SLinus Torvalds 			ei->op.proc_read = proc_pid_cmdline;
1513*1da177e4SLinus Torvalds 			break;
1514*1da177e4SLinus Torvalds 		case PROC_TID_STATM:
1515*1da177e4SLinus Torvalds 		case PROC_TGID_STATM:
1516*1da177e4SLinus Torvalds 			inode->i_fop = &proc_info_file_operations;
1517*1da177e4SLinus Torvalds 			ei->op.proc_read = proc_pid_statm;
1518*1da177e4SLinus Torvalds 			break;
1519*1da177e4SLinus Torvalds 		case PROC_TID_MAPS:
1520*1da177e4SLinus Torvalds 		case PROC_TGID_MAPS:
1521*1da177e4SLinus Torvalds 			inode->i_fop = &proc_maps_operations;
1522*1da177e4SLinus Torvalds 			break;
1523*1da177e4SLinus Torvalds 		case PROC_TID_MEM:
1524*1da177e4SLinus Torvalds 		case PROC_TGID_MEM:
1525*1da177e4SLinus Torvalds 			inode->i_op = &proc_mem_inode_operations;
1526*1da177e4SLinus Torvalds 			inode->i_fop = &proc_mem_operations;
1527*1da177e4SLinus Torvalds 			break;
1528*1da177e4SLinus Torvalds #ifdef CONFIG_SECCOMP
1529*1da177e4SLinus Torvalds 		case PROC_TID_SECCOMP:
1530*1da177e4SLinus Torvalds 		case PROC_TGID_SECCOMP:
1531*1da177e4SLinus Torvalds 			inode->i_fop = &proc_seccomp_operations;
1532*1da177e4SLinus Torvalds 			break;
1533*1da177e4SLinus Torvalds #endif /* CONFIG_SECCOMP */
1534*1da177e4SLinus Torvalds 		case PROC_TID_MOUNTS:
1535*1da177e4SLinus Torvalds 		case PROC_TGID_MOUNTS:
1536*1da177e4SLinus Torvalds 			inode->i_fop = &proc_mounts_operations;
1537*1da177e4SLinus Torvalds 			break;
1538*1da177e4SLinus Torvalds #ifdef CONFIG_SECURITY
1539*1da177e4SLinus Torvalds 		case PROC_TID_ATTR:
1540*1da177e4SLinus Torvalds 			inode->i_nlink = 2;
1541*1da177e4SLinus Torvalds 			inode->i_op = &proc_tid_attr_inode_operations;
1542*1da177e4SLinus Torvalds 			inode->i_fop = &proc_tid_attr_operations;
1543*1da177e4SLinus Torvalds 			break;
1544*1da177e4SLinus Torvalds 		case PROC_TGID_ATTR:
1545*1da177e4SLinus Torvalds 			inode->i_nlink = 2;
1546*1da177e4SLinus Torvalds 			inode->i_op = &proc_tgid_attr_inode_operations;
1547*1da177e4SLinus Torvalds 			inode->i_fop = &proc_tgid_attr_operations;
1548*1da177e4SLinus Torvalds 			break;
1549*1da177e4SLinus Torvalds 		case PROC_TID_ATTR_CURRENT:
1550*1da177e4SLinus Torvalds 		case PROC_TGID_ATTR_CURRENT:
1551*1da177e4SLinus Torvalds 		case PROC_TID_ATTR_PREV:
1552*1da177e4SLinus Torvalds 		case PROC_TGID_ATTR_PREV:
1553*1da177e4SLinus Torvalds 		case PROC_TID_ATTR_EXEC:
1554*1da177e4SLinus Torvalds 		case PROC_TGID_ATTR_EXEC:
1555*1da177e4SLinus Torvalds 		case PROC_TID_ATTR_FSCREATE:
1556*1da177e4SLinus Torvalds 		case PROC_TGID_ATTR_FSCREATE:
1557*1da177e4SLinus Torvalds 			inode->i_fop = &proc_pid_attr_operations;
1558*1da177e4SLinus Torvalds 			break;
1559*1da177e4SLinus Torvalds #endif
1560*1da177e4SLinus Torvalds #ifdef CONFIG_KALLSYMS
1561*1da177e4SLinus Torvalds 		case PROC_TID_WCHAN:
1562*1da177e4SLinus Torvalds 		case PROC_TGID_WCHAN:
1563*1da177e4SLinus Torvalds 			inode->i_fop = &proc_info_file_operations;
1564*1da177e4SLinus Torvalds 			ei->op.proc_read = proc_pid_wchan;
1565*1da177e4SLinus Torvalds 			break;
1566*1da177e4SLinus Torvalds #endif
1567*1da177e4SLinus Torvalds #ifdef CONFIG_SCHEDSTATS
1568*1da177e4SLinus Torvalds 		case PROC_TID_SCHEDSTAT:
1569*1da177e4SLinus Torvalds 		case PROC_TGID_SCHEDSTAT:
1570*1da177e4SLinus Torvalds 			inode->i_fop = &proc_info_file_operations;
1571*1da177e4SLinus Torvalds 			ei->op.proc_read = proc_pid_schedstat;
1572*1da177e4SLinus Torvalds 			break;
1573*1da177e4SLinus Torvalds #endif
1574*1da177e4SLinus Torvalds #ifdef CONFIG_CPUSETS
1575*1da177e4SLinus Torvalds 		case PROC_TID_CPUSET:
1576*1da177e4SLinus Torvalds 		case PROC_TGID_CPUSET:
1577*1da177e4SLinus Torvalds 			inode->i_fop = &proc_cpuset_operations;
1578*1da177e4SLinus Torvalds 			break;
1579*1da177e4SLinus Torvalds #endif
1580*1da177e4SLinus Torvalds 		case PROC_TID_OOM_SCORE:
1581*1da177e4SLinus Torvalds 		case PROC_TGID_OOM_SCORE:
1582*1da177e4SLinus Torvalds 			inode->i_fop = &proc_info_file_operations;
1583*1da177e4SLinus Torvalds 			ei->op.proc_read = proc_oom_score;
1584*1da177e4SLinus Torvalds 			break;
1585*1da177e4SLinus Torvalds 		case PROC_TID_OOM_ADJUST:
1586*1da177e4SLinus Torvalds 		case PROC_TGID_OOM_ADJUST:
1587*1da177e4SLinus Torvalds 			inode->i_fop = &proc_oom_adjust_operations;
1588*1da177e4SLinus Torvalds 			break;
1589*1da177e4SLinus Torvalds #ifdef CONFIG_AUDITSYSCALL
1590*1da177e4SLinus Torvalds 		case PROC_TID_LOGINUID:
1591*1da177e4SLinus Torvalds 		case PROC_TGID_LOGINUID:
1592*1da177e4SLinus Torvalds 			inode->i_fop = &proc_loginuid_operations;
1593*1da177e4SLinus Torvalds 			break;
1594*1da177e4SLinus Torvalds #endif
1595*1da177e4SLinus Torvalds 		default:
1596*1da177e4SLinus Torvalds 			printk("procfs: impossible type (%d)",p->type);
1597*1da177e4SLinus Torvalds 			iput(inode);
1598*1da177e4SLinus Torvalds 			return ERR_PTR(-EINVAL);
1599*1da177e4SLinus Torvalds 	}
1600*1da177e4SLinus Torvalds 	dentry->d_op = &pid_dentry_operations;
1601*1da177e4SLinus Torvalds 	d_add(dentry, inode);
1602*1da177e4SLinus Torvalds 	return NULL;
1603*1da177e4SLinus Torvalds 
1604*1da177e4SLinus Torvalds out:
1605*1da177e4SLinus Torvalds 	return ERR_PTR(error);
1606*1da177e4SLinus Torvalds }
1607*1da177e4SLinus Torvalds 
1608*1da177e4SLinus Torvalds static struct dentry *proc_tgid_base_lookup(struct inode *dir, struct dentry *dentry, struct nameidata *nd){
1609*1da177e4SLinus Torvalds 	return proc_pident_lookup(dir, dentry, tgid_base_stuff);
1610*1da177e4SLinus Torvalds }
1611*1da177e4SLinus Torvalds 
1612*1da177e4SLinus Torvalds static struct dentry *proc_tid_base_lookup(struct inode *dir, struct dentry *dentry, struct nameidata *nd){
1613*1da177e4SLinus Torvalds 	return proc_pident_lookup(dir, dentry, tid_base_stuff);
1614*1da177e4SLinus Torvalds }
1615*1da177e4SLinus Torvalds 
1616*1da177e4SLinus Torvalds static struct file_operations proc_tgid_base_operations = {
1617*1da177e4SLinus Torvalds 	.read		= generic_read_dir,
1618*1da177e4SLinus Torvalds 	.readdir	= proc_tgid_base_readdir,
1619*1da177e4SLinus Torvalds };
1620*1da177e4SLinus Torvalds 
1621*1da177e4SLinus Torvalds static struct file_operations proc_tid_base_operations = {
1622*1da177e4SLinus Torvalds 	.read		= generic_read_dir,
1623*1da177e4SLinus Torvalds 	.readdir	= proc_tid_base_readdir,
1624*1da177e4SLinus Torvalds };
1625*1da177e4SLinus Torvalds 
1626*1da177e4SLinus Torvalds static struct inode_operations proc_tgid_base_inode_operations = {
1627*1da177e4SLinus Torvalds 	.lookup		= proc_tgid_base_lookup,
1628*1da177e4SLinus Torvalds };
1629*1da177e4SLinus Torvalds 
1630*1da177e4SLinus Torvalds static struct inode_operations proc_tid_base_inode_operations = {
1631*1da177e4SLinus Torvalds 	.lookup		= proc_tid_base_lookup,
1632*1da177e4SLinus Torvalds };
1633*1da177e4SLinus Torvalds 
1634*1da177e4SLinus Torvalds #ifdef CONFIG_SECURITY
1635*1da177e4SLinus Torvalds static int proc_tgid_attr_readdir(struct file * filp,
1636*1da177e4SLinus Torvalds 			     void * dirent, filldir_t filldir)
1637*1da177e4SLinus Torvalds {
1638*1da177e4SLinus Torvalds 	return proc_pident_readdir(filp,dirent,filldir,
1639*1da177e4SLinus Torvalds 				   tgid_attr_stuff,ARRAY_SIZE(tgid_attr_stuff));
1640*1da177e4SLinus Torvalds }
1641*1da177e4SLinus Torvalds 
1642*1da177e4SLinus Torvalds static int proc_tid_attr_readdir(struct file * filp,
1643*1da177e4SLinus Torvalds 			     void * dirent, filldir_t filldir)
1644*1da177e4SLinus Torvalds {
1645*1da177e4SLinus Torvalds 	return proc_pident_readdir(filp,dirent,filldir,
1646*1da177e4SLinus Torvalds 				   tid_attr_stuff,ARRAY_SIZE(tid_attr_stuff));
1647*1da177e4SLinus Torvalds }
1648*1da177e4SLinus Torvalds 
1649*1da177e4SLinus Torvalds static struct file_operations proc_tgid_attr_operations = {
1650*1da177e4SLinus Torvalds 	.read		= generic_read_dir,
1651*1da177e4SLinus Torvalds 	.readdir	= proc_tgid_attr_readdir,
1652*1da177e4SLinus Torvalds };
1653*1da177e4SLinus Torvalds 
1654*1da177e4SLinus Torvalds static struct file_operations proc_tid_attr_operations = {
1655*1da177e4SLinus Torvalds 	.read		= generic_read_dir,
1656*1da177e4SLinus Torvalds 	.readdir	= proc_tid_attr_readdir,
1657*1da177e4SLinus Torvalds };
1658*1da177e4SLinus Torvalds 
1659*1da177e4SLinus Torvalds static struct dentry *proc_tgid_attr_lookup(struct inode *dir,
1660*1da177e4SLinus Torvalds 				struct dentry *dentry, struct nameidata *nd)
1661*1da177e4SLinus Torvalds {
1662*1da177e4SLinus Torvalds 	return proc_pident_lookup(dir, dentry, tgid_attr_stuff);
1663*1da177e4SLinus Torvalds }
1664*1da177e4SLinus Torvalds 
1665*1da177e4SLinus Torvalds static struct dentry *proc_tid_attr_lookup(struct inode *dir,
1666*1da177e4SLinus Torvalds 				struct dentry *dentry, struct nameidata *nd)
1667*1da177e4SLinus Torvalds {
1668*1da177e4SLinus Torvalds 	return proc_pident_lookup(dir, dentry, tid_attr_stuff);
1669*1da177e4SLinus Torvalds }
1670*1da177e4SLinus Torvalds 
1671*1da177e4SLinus Torvalds static struct inode_operations proc_tgid_attr_inode_operations = {
1672*1da177e4SLinus Torvalds 	.lookup		= proc_tgid_attr_lookup,
1673*1da177e4SLinus Torvalds };
1674*1da177e4SLinus Torvalds 
1675*1da177e4SLinus Torvalds static struct inode_operations proc_tid_attr_inode_operations = {
1676*1da177e4SLinus Torvalds 	.lookup		= proc_tid_attr_lookup,
1677*1da177e4SLinus Torvalds };
1678*1da177e4SLinus Torvalds #endif
1679*1da177e4SLinus Torvalds 
1680*1da177e4SLinus Torvalds /*
1681*1da177e4SLinus Torvalds  * /proc/self:
1682*1da177e4SLinus Torvalds  */
1683*1da177e4SLinus Torvalds static int proc_self_readlink(struct dentry *dentry, char __user *buffer,
1684*1da177e4SLinus Torvalds 			      int buflen)
1685*1da177e4SLinus Torvalds {
1686*1da177e4SLinus Torvalds 	char tmp[30];
1687*1da177e4SLinus Torvalds 	sprintf(tmp, "%d", current->tgid);
1688*1da177e4SLinus Torvalds 	return vfs_readlink(dentry,buffer,buflen,tmp);
1689*1da177e4SLinus Torvalds }
1690*1da177e4SLinus Torvalds 
1691*1da177e4SLinus Torvalds static int proc_self_follow_link(struct dentry *dentry, struct nameidata *nd)
1692*1da177e4SLinus Torvalds {
1693*1da177e4SLinus Torvalds 	char tmp[30];
1694*1da177e4SLinus Torvalds 	sprintf(tmp, "%d", current->tgid);
1695*1da177e4SLinus Torvalds 	return vfs_follow_link(nd,tmp);
1696*1da177e4SLinus Torvalds }
1697*1da177e4SLinus Torvalds 
1698*1da177e4SLinus Torvalds static struct inode_operations proc_self_inode_operations = {
1699*1da177e4SLinus Torvalds 	.readlink	= proc_self_readlink,
1700*1da177e4SLinus Torvalds 	.follow_link	= proc_self_follow_link,
1701*1da177e4SLinus Torvalds };
1702*1da177e4SLinus Torvalds 
1703*1da177e4SLinus Torvalds /**
1704*1da177e4SLinus Torvalds  * proc_pid_unhash -  Unhash /proc/<pid> entry from the dcache.
1705*1da177e4SLinus Torvalds  * @p: task that should be flushed.
1706*1da177e4SLinus Torvalds  *
1707*1da177e4SLinus Torvalds  * Drops the /proc/<pid> dcache entry from the hash chains.
1708*1da177e4SLinus Torvalds  *
1709*1da177e4SLinus Torvalds  * Dropping /proc/<pid> entries and detach_pid must be synchroneous,
1710*1da177e4SLinus Torvalds  * otherwise e.g. /proc/<pid>/exe might point to the wrong executable,
1711*1da177e4SLinus Torvalds  * if the pid value is immediately reused. This is enforced by
1712*1da177e4SLinus Torvalds  * - caller must acquire spin_lock(p->proc_lock)
1713*1da177e4SLinus Torvalds  * - must be called before detach_pid()
1714*1da177e4SLinus Torvalds  * - proc_pid_lookup acquires proc_lock, and checks that
1715*1da177e4SLinus Torvalds  *   the target is not dead by looking at the attach count
1716*1da177e4SLinus Torvalds  *   of PIDTYPE_PID.
1717*1da177e4SLinus Torvalds  */
1718*1da177e4SLinus Torvalds 
1719*1da177e4SLinus Torvalds struct dentry *proc_pid_unhash(struct task_struct *p)
1720*1da177e4SLinus Torvalds {
1721*1da177e4SLinus Torvalds 	struct dentry *proc_dentry;
1722*1da177e4SLinus Torvalds 
1723*1da177e4SLinus Torvalds 	proc_dentry = p->proc_dentry;
1724*1da177e4SLinus Torvalds 	if (proc_dentry != NULL) {
1725*1da177e4SLinus Torvalds 
1726*1da177e4SLinus Torvalds 		spin_lock(&dcache_lock);
1727*1da177e4SLinus Torvalds 		spin_lock(&proc_dentry->d_lock);
1728*1da177e4SLinus Torvalds 		if (!d_unhashed(proc_dentry)) {
1729*1da177e4SLinus Torvalds 			dget_locked(proc_dentry);
1730*1da177e4SLinus Torvalds 			__d_drop(proc_dentry);
1731*1da177e4SLinus Torvalds 			spin_unlock(&proc_dentry->d_lock);
1732*1da177e4SLinus Torvalds 		} else {
1733*1da177e4SLinus Torvalds 			spin_unlock(&proc_dentry->d_lock);
1734*1da177e4SLinus Torvalds 			proc_dentry = NULL;
1735*1da177e4SLinus Torvalds 		}
1736*1da177e4SLinus Torvalds 		spin_unlock(&dcache_lock);
1737*1da177e4SLinus Torvalds 	}
1738*1da177e4SLinus Torvalds 	return proc_dentry;
1739*1da177e4SLinus Torvalds }
1740*1da177e4SLinus Torvalds 
1741*1da177e4SLinus Torvalds /**
1742*1da177e4SLinus Torvalds  * proc_pid_flush - recover memory used by stale /proc/<pid>/x entries
1743*1da177e4SLinus Torvalds  * @proc_entry: directoy to prune.
1744*1da177e4SLinus Torvalds  *
1745*1da177e4SLinus Torvalds  * Shrink the /proc directory that was used by the just killed thread.
1746*1da177e4SLinus Torvalds  */
1747*1da177e4SLinus Torvalds 
1748*1da177e4SLinus Torvalds void proc_pid_flush(struct dentry *proc_dentry)
1749*1da177e4SLinus Torvalds {
1750*1da177e4SLinus Torvalds 	might_sleep();
1751*1da177e4SLinus Torvalds 	if(proc_dentry != NULL) {
1752*1da177e4SLinus Torvalds 		shrink_dcache_parent(proc_dentry);
1753*1da177e4SLinus Torvalds 		dput(proc_dentry);
1754*1da177e4SLinus Torvalds 	}
1755*1da177e4SLinus Torvalds }
1756*1da177e4SLinus Torvalds 
1757*1da177e4SLinus Torvalds /* SMP-safe */
1758*1da177e4SLinus Torvalds struct dentry *proc_pid_lookup(struct inode *dir, struct dentry * dentry, struct nameidata *nd)
1759*1da177e4SLinus Torvalds {
1760*1da177e4SLinus Torvalds 	struct task_struct *task;
1761*1da177e4SLinus Torvalds 	struct inode *inode;
1762*1da177e4SLinus Torvalds 	struct proc_inode *ei;
1763*1da177e4SLinus Torvalds 	unsigned tgid;
1764*1da177e4SLinus Torvalds 	int died;
1765*1da177e4SLinus Torvalds 
1766*1da177e4SLinus Torvalds 	if (dentry->d_name.len == 4 && !memcmp(dentry->d_name.name,"self",4)) {
1767*1da177e4SLinus Torvalds 		inode = new_inode(dir->i_sb);
1768*1da177e4SLinus Torvalds 		if (!inode)
1769*1da177e4SLinus Torvalds 			return ERR_PTR(-ENOMEM);
1770*1da177e4SLinus Torvalds 		ei = PROC_I(inode);
1771*1da177e4SLinus Torvalds 		inode->i_mtime = inode->i_atime = inode->i_ctime = CURRENT_TIME;
1772*1da177e4SLinus Torvalds 		inode->i_ino = fake_ino(0, PROC_TGID_INO);
1773*1da177e4SLinus Torvalds 		ei->pde = NULL;
1774*1da177e4SLinus Torvalds 		inode->i_mode = S_IFLNK|S_IRWXUGO;
1775*1da177e4SLinus Torvalds 		inode->i_uid = inode->i_gid = 0;
1776*1da177e4SLinus Torvalds 		inode->i_size = 64;
1777*1da177e4SLinus Torvalds 		inode->i_op = &proc_self_inode_operations;
1778*1da177e4SLinus Torvalds 		d_add(dentry, inode);
1779*1da177e4SLinus Torvalds 		return NULL;
1780*1da177e4SLinus Torvalds 	}
1781*1da177e4SLinus Torvalds 	tgid = name_to_int(dentry);
1782*1da177e4SLinus Torvalds 	if (tgid == ~0U)
1783*1da177e4SLinus Torvalds 		goto out;
1784*1da177e4SLinus Torvalds 
1785*1da177e4SLinus Torvalds 	read_lock(&tasklist_lock);
1786*1da177e4SLinus Torvalds 	task = find_task_by_pid(tgid);
1787*1da177e4SLinus Torvalds 	if (task)
1788*1da177e4SLinus Torvalds 		get_task_struct(task);
1789*1da177e4SLinus Torvalds 	read_unlock(&tasklist_lock);
1790*1da177e4SLinus Torvalds 	if (!task)
1791*1da177e4SLinus Torvalds 		goto out;
1792*1da177e4SLinus Torvalds 
1793*1da177e4SLinus Torvalds 	inode = proc_pid_make_inode(dir->i_sb, task, PROC_TGID_INO);
1794*1da177e4SLinus Torvalds 
1795*1da177e4SLinus Torvalds 
1796*1da177e4SLinus Torvalds 	if (!inode) {
1797*1da177e4SLinus Torvalds 		put_task_struct(task);
1798*1da177e4SLinus Torvalds 		goto out;
1799*1da177e4SLinus Torvalds 	}
1800*1da177e4SLinus Torvalds 	inode->i_mode = S_IFDIR|S_IRUGO|S_IXUGO;
1801*1da177e4SLinus Torvalds 	inode->i_op = &proc_tgid_base_inode_operations;
1802*1da177e4SLinus Torvalds 	inode->i_fop = &proc_tgid_base_operations;
1803*1da177e4SLinus Torvalds 	inode->i_nlink = 3;
1804*1da177e4SLinus Torvalds 	inode->i_flags|=S_IMMUTABLE;
1805*1da177e4SLinus Torvalds 
1806*1da177e4SLinus Torvalds 	dentry->d_op = &pid_base_dentry_operations;
1807*1da177e4SLinus Torvalds 
1808*1da177e4SLinus Torvalds 	died = 0;
1809*1da177e4SLinus Torvalds 	d_add(dentry, inode);
1810*1da177e4SLinus Torvalds 	spin_lock(&task->proc_lock);
1811*1da177e4SLinus Torvalds 	task->proc_dentry = dentry;
1812*1da177e4SLinus Torvalds 	if (!pid_alive(task)) {
1813*1da177e4SLinus Torvalds 		dentry = proc_pid_unhash(task);
1814*1da177e4SLinus Torvalds 		died = 1;
1815*1da177e4SLinus Torvalds 	}
1816*1da177e4SLinus Torvalds 	spin_unlock(&task->proc_lock);
1817*1da177e4SLinus Torvalds 
1818*1da177e4SLinus Torvalds 	put_task_struct(task);
1819*1da177e4SLinus Torvalds 	if (died) {
1820*1da177e4SLinus Torvalds 		proc_pid_flush(dentry);
1821*1da177e4SLinus Torvalds 		goto out;
1822*1da177e4SLinus Torvalds 	}
1823*1da177e4SLinus Torvalds 	return NULL;
1824*1da177e4SLinus Torvalds out:
1825*1da177e4SLinus Torvalds 	return ERR_PTR(-ENOENT);
1826*1da177e4SLinus Torvalds }
1827*1da177e4SLinus Torvalds 
1828*1da177e4SLinus Torvalds /* SMP-safe */
1829*1da177e4SLinus Torvalds static struct dentry *proc_task_lookup(struct inode *dir, struct dentry * dentry, struct nameidata *nd)
1830*1da177e4SLinus Torvalds {
1831*1da177e4SLinus Torvalds 	struct task_struct *task;
1832*1da177e4SLinus Torvalds 	struct task_struct *leader = proc_task(dir);
1833*1da177e4SLinus Torvalds 	struct inode *inode;
1834*1da177e4SLinus Torvalds 	unsigned tid;
1835*1da177e4SLinus Torvalds 
1836*1da177e4SLinus Torvalds 	tid = name_to_int(dentry);
1837*1da177e4SLinus Torvalds 	if (tid == ~0U)
1838*1da177e4SLinus Torvalds 		goto out;
1839*1da177e4SLinus Torvalds 
1840*1da177e4SLinus Torvalds 	read_lock(&tasklist_lock);
1841*1da177e4SLinus Torvalds 	task = find_task_by_pid(tid);
1842*1da177e4SLinus Torvalds 	if (task)
1843*1da177e4SLinus Torvalds 		get_task_struct(task);
1844*1da177e4SLinus Torvalds 	read_unlock(&tasklist_lock);
1845*1da177e4SLinus Torvalds 	if (!task)
1846*1da177e4SLinus Torvalds 		goto out;
1847*1da177e4SLinus Torvalds 	if (leader->tgid != task->tgid)
1848*1da177e4SLinus Torvalds 		goto out_drop_task;
1849*1da177e4SLinus Torvalds 
1850*1da177e4SLinus Torvalds 	inode = proc_pid_make_inode(dir->i_sb, task, PROC_TID_INO);
1851*1da177e4SLinus Torvalds 
1852*1da177e4SLinus Torvalds 
1853*1da177e4SLinus Torvalds 	if (!inode)
1854*1da177e4SLinus Torvalds 		goto out_drop_task;
1855*1da177e4SLinus Torvalds 	inode->i_mode = S_IFDIR|S_IRUGO|S_IXUGO;
1856*1da177e4SLinus Torvalds 	inode->i_op = &proc_tid_base_inode_operations;
1857*1da177e4SLinus Torvalds 	inode->i_fop = &proc_tid_base_operations;
1858*1da177e4SLinus Torvalds 	inode->i_nlink = 3;
1859*1da177e4SLinus Torvalds 	inode->i_flags|=S_IMMUTABLE;
1860*1da177e4SLinus Torvalds 
1861*1da177e4SLinus Torvalds 	dentry->d_op = &pid_base_dentry_operations;
1862*1da177e4SLinus Torvalds 
1863*1da177e4SLinus Torvalds 	d_add(dentry, inode);
1864*1da177e4SLinus Torvalds 
1865*1da177e4SLinus Torvalds 	put_task_struct(task);
1866*1da177e4SLinus Torvalds 	return NULL;
1867*1da177e4SLinus Torvalds out_drop_task:
1868*1da177e4SLinus Torvalds 	put_task_struct(task);
1869*1da177e4SLinus Torvalds out:
1870*1da177e4SLinus Torvalds 	return ERR_PTR(-ENOENT);
1871*1da177e4SLinus Torvalds }
1872*1da177e4SLinus Torvalds 
1873*1da177e4SLinus Torvalds #define PROC_NUMBUF 10
1874*1da177e4SLinus Torvalds #define PROC_MAXPIDS 20
1875*1da177e4SLinus Torvalds 
1876*1da177e4SLinus Torvalds /*
1877*1da177e4SLinus Torvalds  * Get a few tgid's to return for filldir - we need to hold the
1878*1da177e4SLinus Torvalds  * tasklist lock while doing this, and we must release it before
1879*1da177e4SLinus Torvalds  * we actually do the filldir itself, so we use a temp buffer..
1880*1da177e4SLinus Torvalds  */
1881*1da177e4SLinus Torvalds static int get_tgid_list(int index, unsigned long version, unsigned int *tgids)
1882*1da177e4SLinus Torvalds {
1883*1da177e4SLinus Torvalds 	struct task_struct *p;
1884*1da177e4SLinus Torvalds 	int nr_tgids = 0;
1885*1da177e4SLinus Torvalds 
1886*1da177e4SLinus Torvalds 	index--;
1887*1da177e4SLinus Torvalds 	read_lock(&tasklist_lock);
1888*1da177e4SLinus Torvalds 	p = NULL;
1889*1da177e4SLinus Torvalds 	if (version) {
1890*1da177e4SLinus Torvalds 		p = find_task_by_pid(version);
1891*1da177e4SLinus Torvalds 		if (p && !thread_group_leader(p))
1892*1da177e4SLinus Torvalds 			p = NULL;
1893*1da177e4SLinus Torvalds 	}
1894*1da177e4SLinus Torvalds 
1895*1da177e4SLinus Torvalds 	if (p)
1896*1da177e4SLinus Torvalds 		index = 0;
1897*1da177e4SLinus Torvalds 	else
1898*1da177e4SLinus Torvalds 		p = next_task(&init_task);
1899*1da177e4SLinus Torvalds 
1900*1da177e4SLinus Torvalds 	for ( ; p != &init_task; p = next_task(p)) {
1901*1da177e4SLinus Torvalds 		int tgid = p->pid;
1902*1da177e4SLinus Torvalds 		if (!pid_alive(p))
1903*1da177e4SLinus Torvalds 			continue;
1904*1da177e4SLinus Torvalds 		if (--index >= 0)
1905*1da177e4SLinus Torvalds 			continue;
1906*1da177e4SLinus Torvalds 		tgids[nr_tgids] = tgid;
1907*1da177e4SLinus Torvalds 		nr_tgids++;
1908*1da177e4SLinus Torvalds 		if (nr_tgids >= PROC_MAXPIDS)
1909*1da177e4SLinus Torvalds 			break;
1910*1da177e4SLinus Torvalds 	}
1911*1da177e4SLinus Torvalds 	read_unlock(&tasklist_lock);
1912*1da177e4SLinus Torvalds 	return nr_tgids;
1913*1da177e4SLinus Torvalds }
1914*1da177e4SLinus Torvalds 
1915*1da177e4SLinus Torvalds /*
1916*1da177e4SLinus Torvalds  * Get a few tid's to return for filldir - we need to hold the
1917*1da177e4SLinus Torvalds  * tasklist lock while doing this, and we must release it before
1918*1da177e4SLinus Torvalds  * we actually do the filldir itself, so we use a temp buffer..
1919*1da177e4SLinus Torvalds  */
1920*1da177e4SLinus Torvalds static int get_tid_list(int index, unsigned int *tids, struct inode *dir)
1921*1da177e4SLinus Torvalds {
1922*1da177e4SLinus Torvalds 	struct task_struct *leader_task = proc_task(dir);
1923*1da177e4SLinus Torvalds 	struct task_struct *task = leader_task;
1924*1da177e4SLinus Torvalds 	int nr_tids = 0;
1925*1da177e4SLinus Torvalds 
1926*1da177e4SLinus Torvalds 	index -= 2;
1927*1da177e4SLinus Torvalds 	read_lock(&tasklist_lock);
1928*1da177e4SLinus Torvalds 	/*
1929*1da177e4SLinus Torvalds 	 * The starting point task (leader_task) might be an already
1930*1da177e4SLinus Torvalds 	 * unlinked task, which cannot be used to access the task-list
1931*1da177e4SLinus Torvalds 	 * via next_thread().
1932*1da177e4SLinus Torvalds 	 */
1933*1da177e4SLinus Torvalds 	if (pid_alive(task)) do {
1934*1da177e4SLinus Torvalds 		int tid = task->pid;
1935*1da177e4SLinus Torvalds 
1936*1da177e4SLinus Torvalds 		if (--index >= 0)
1937*1da177e4SLinus Torvalds 			continue;
1938*1da177e4SLinus Torvalds 		tids[nr_tids] = tid;
1939*1da177e4SLinus Torvalds 		nr_tids++;
1940*1da177e4SLinus Torvalds 		if (nr_tids >= PROC_MAXPIDS)
1941*1da177e4SLinus Torvalds 			break;
1942*1da177e4SLinus Torvalds 	} while ((task = next_thread(task)) != leader_task);
1943*1da177e4SLinus Torvalds 	read_unlock(&tasklist_lock);
1944*1da177e4SLinus Torvalds 	return nr_tids;
1945*1da177e4SLinus Torvalds }
1946*1da177e4SLinus Torvalds 
1947*1da177e4SLinus Torvalds /* for the /proc/ directory itself, after non-process stuff has been done */
1948*1da177e4SLinus Torvalds int proc_pid_readdir(struct file * filp, void * dirent, filldir_t filldir)
1949*1da177e4SLinus Torvalds {
1950*1da177e4SLinus Torvalds 	unsigned int tgid_array[PROC_MAXPIDS];
1951*1da177e4SLinus Torvalds 	char buf[PROC_NUMBUF];
1952*1da177e4SLinus Torvalds 	unsigned int nr = filp->f_pos - FIRST_PROCESS_ENTRY;
1953*1da177e4SLinus Torvalds 	unsigned int nr_tgids, i;
1954*1da177e4SLinus Torvalds 	int next_tgid;
1955*1da177e4SLinus Torvalds 
1956*1da177e4SLinus Torvalds 	if (!nr) {
1957*1da177e4SLinus Torvalds 		ino_t ino = fake_ino(0,PROC_TGID_INO);
1958*1da177e4SLinus Torvalds 		if (filldir(dirent, "self", 4, filp->f_pos, ino, DT_LNK) < 0)
1959*1da177e4SLinus Torvalds 			return 0;
1960*1da177e4SLinus Torvalds 		filp->f_pos++;
1961*1da177e4SLinus Torvalds 		nr++;
1962*1da177e4SLinus Torvalds 	}
1963*1da177e4SLinus Torvalds 
1964*1da177e4SLinus Torvalds 	/* f_version caches the tgid value that the last readdir call couldn't
1965*1da177e4SLinus Torvalds 	 * return. lseek aka telldir automagically resets f_version to 0.
1966*1da177e4SLinus Torvalds 	 */
1967*1da177e4SLinus Torvalds 	next_tgid = filp->f_version;
1968*1da177e4SLinus Torvalds 	filp->f_version = 0;
1969*1da177e4SLinus Torvalds 	for (;;) {
1970*1da177e4SLinus Torvalds 		nr_tgids = get_tgid_list(nr, next_tgid, tgid_array);
1971*1da177e4SLinus Torvalds 		if (!nr_tgids) {
1972*1da177e4SLinus Torvalds 			/* no more entries ! */
1973*1da177e4SLinus Torvalds 			break;
1974*1da177e4SLinus Torvalds 		}
1975*1da177e4SLinus Torvalds 		next_tgid = 0;
1976*1da177e4SLinus Torvalds 
1977*1da177e4SLinus Torvalds 		/* do not use the last found pid, reserve it for next_tgid */
1978*1da177e4SLinus Torvalds 		if (nr_tgids == PROC_MAXPIDS) {
1979*1da177e4SLinus Torvalds 			nr_tgids--;
1980*1da177e4SLinus Torvalds 			next_tgid = tgid_array[nr_tgids];
1981*1da177e4SLinus Torvalds 		}
1982*1da177e4SLinus Torvalds 
1983*1da177e4SLinus Torvalds 		for (i=0;i<nr_tgids;i++) {
1984*1da177e4SLinus Torvalds 			int tgid = tgid_array[i];
1985*1da177e4SLinus Torvalds 			ino_t ino = fake_ino(tgid,PROC_TGID_INO);
1986*1da177e4SLinus Torvalds 			unsigned long j = PROC_NUMBUF;
1987*1da177e4SLinus Torvalds 
1988*1da177e4SLinus Torvalds 			do
1989*1da177e4SLinus Torvalds 				buf[--j] = '0' + (tgid % 10);
1990*1da177e4SLinus Torvalds 			while ((tgid /= 10) != 0);
1991*1da177e4SLinus Torvalds 
1992*1da177e4SLinus Torvalds 			if (filldir(dirent, buf+j, PROC_NUMBUF-j, filp->f_pos, ino, DT_DIR) < 0) {
1993*1da177e4SLinus Torvalds 				/* returning this tgid failed, save it as the first
1994*1da177e4SLinus Torvalds 				 * pid for the next readir call */
1995*1da177e4SLinus Torvalds 				filp->f_version = tgid_array[i];
1996*1da177e4SLinus Torvalds 				goto out;
1997*1da177e4SLinus Torvalds 			}
1998*1da177e4SLinus Torvalds 			filp->f_pos++;
1999*1da177e4SLinus Torvalds 			nr++;
2000*1da177e4SLinus Torvalds 		}
2001*1da177e4SLinus Torvalds 	}
2002*1da177e4SLinus Torvalds out:
2003*1da177e4SLinus Torvalds 	return 0;
2004*1da177e4SLinus Torvalds }
2005*1da177e4SLinus Torvalds 
2006*1da177e4SLinus Torvalds /* for the /proc/TGID/task/ directories */
2007*1da177e4SLinus Torvalds static int proc_task_readdir(struct file * filp, void * dirent, filldir_t filldir)
2008*1da177e4SLinus Torvalds {
2009*1da177e4SLinus Torvalds 	unsigned int tid_array[PROC_MAXPIDS];
2010*1da177e4SLinus Torvalds 	char buf[PROC_NUMBUF];
2011*1da177e4SLinus Torvalds 	unsigned int nr_tids, i;
2012*1da177e4SLinus Torvalds 	struct dentry *dentry = filp->f_dentry;
2013*1da177e4SLinus Torvalds 	struct inode *inode = dentry->d_inode;
2014*1da177e4SLinus Torvalds 	int retval = -ENOENT;
2015*1da177e4SLinus Torvalds 	ino_t ino;
2016*1da177e4SLinus Torvalds 	unsigned long pos = filp->f_pos;  /* avoiding "long long" filp->f_pos */
2017*1da177e4SLinus Torvalds 
2018*1da177e4SLinus Torvalds 	if (!pid_alive(proc_task(inode)))
2019*1da177e4SLinus Torvalds 		goto out;
2020*1da177e4SLinus Torvalds 	retval = 0;
2021*1da177e4SLinus Torvalds 
2022*1da177e4SLinus Torvalds 	switch (pos) {
2023*1da177e4SLinus Torvalds 	case 0:
2024*1da177e4SLinus Torvalds 		ino = inode->i_ino;
2025*1da177e4SLinus Torvalds 		if (filldir(dirent, ".", 1, pos, ino, DT_DIR) < 0)
2026*1da177e4SLinus Torvalds 			goto out;
2027*1da177e4SLinus Torvalds 		pos++;
2028*1da177e4SLinus Torvalds 		/* fall through */
2029*1da177e4SLinus Torvalds 	case 1:
2030*1da177e4SLinus Torvalds 		ino = parent_ino(dentry);
2031*1da177e4SLinus Torvalds 		if (filldir(dirent, "..", 2, pos, ino, DT_DIR) < 0)
2032*1da177e4SLinus Torvalds 			goto out;
2033*1da177e4SLinus Torvalds 		pos++;
2034*1da177e4SLinus Torvalds 		/* fall through */
2035*1da177e4SLinus Torvalds 	}
2036*1da177e4SLinus Torvalds 
2037*1da177e4SLinus Torvalds 	nr_tids = get_tid_list(pos, tid_array, inode);
2038*1da177e4SLinus Torvalds 
2039*1da177e4SLinus Torvalds 	for (i = 0; i < nr_tids; i++) {
2040*1da177e4SLinus Torvalds 		unsigned long j = PROC_NUMBUF;
2041*1da177e4SLinus Torvalds 		int tid = tid_array[i];
2042*1da177e4SLinus Torvalds 
2043*1da177e4SLinus Torvalds 		ino = fake_ino(tid,PROC_TID_INO);
2044*1da177e4SLinus Torvalds 
2045*1da177e4SLinus Torvalds 		do
2046*1da177e4SLinus Torvalds 			buf[--j] = '0' + (tid % 10);
2047*1da177e4SLinus Torvalds 		while ((tid /= 10) != 0);
2048*1da177e4SLinus Torvalds 
2049*1da177e4SLinus Torvalds 		if (filldir(dirent, buf+j, PROC_NUMBUF-j, pos, ino, DT_DIR) < 0)
2050*1da177e4SLinus Torvalds 			break;
2051*1da177e4SLinus Torvalds 		pos++;
2052*1da177e4SLinus Torvalds 	}
2053*1da177e4SLinus Torvalds out:
2054*1da177e4SLinus Torvalds 	filp->f_pos = pos;
2055*1da177e4SLinus Torvalds 	return retval;
2056*1da177e4SLinus Torvalds }
2057