Blame view

fs/proc/base.c 72.3 KB
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1
2
3
4
5
6
7
8
9
10
11
12
13
  /*
   *  linux/fs/proc/base.c
   *
   *  Copyright (C) 1991, 1992 Linus Torvalds
   *
   *  proc base directory handling functions
   *
   *  1999, Al Viro. Rewritten. Now it covers the whole per-process part.
   *  Instead of using magical inumbers to determine the kind of object
   *  we allocate and fill in-core inodes upon lookup. They don't even
   *  go into icache. We cache the reference to task_struct upon lookup too.
   *  Eventually it should become a filesystem in its own. We don't use the
   *  rest of procfs anymore.
e070ad49f   Mauricio Lin   [PATCH] add /proc...
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
   *
   *
   *  Changelog:
   *  17-Jan-2005
   *  Allan Bezerra
   *  Bruna Moreira <bruna.moreira@indt.org.br>
   *  Edjard Mota <edjard.mota@indt.org.br>
   *  Ilias Biris <ilias.biris@indt.org.br>
   *  Mauricio Lin <mauricio.lin@indt.org.br>
   *
   *  Embedded Linux Lab - 10LE Instituto Nokia de Tecnologia - INdT
   *
   *  A new process specific entry (smaps) included in /proc. It shows the
   *  size of rss for each memory area. The maps entry lacks information
   *  about physical memory size (rss) for each mapped file, i.e.,
   *  rss information for executables and library files.
   *  This additional information is useful for any tools that need to know
   *  about physical memory consumption for a process specific library.
   *
   *  Changelog:
   *  21-Feb-2005
   *  Embedded Linux Lab - 10LE Instituto Nokia de Tecnologia - INdT
   *  Pud inclusion in the page table walking.
   *
   *  ChangeLog:
   *  10-Mar-2005
   *  10LE Instituto Nokia de Tecnologia - INdT:
   *  A better way to walks through the page table as suggested by Hugh Dickins.
   *
   *  Simo Piiroinen <simo.piiroinen@nokia.com>:
   *  Smaps information related to shared, private, clean and dirty pages.
   *
   *  Paul Mundt <paul.mundt@nokia.com>:
   *  Overall revision about smaps.
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
48
49
50
   */
  
  #include <asm/uaccess.h>
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
51
52
53
54
  #include <linux/errno.h>
  #include <linux/time.h>
  #include <linux/proc_fs.h>
  #include <linux/stat.h>
5995477ab   Andrea Righi   task IO accountin...
55
  #include <linux/task_io_accounting_ops.h>
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
56
  #include <linux/init.h>
16f7e0fe2   Randy Dunlap   [PATCH] capable/c...
57
  #include <linux/capability.h>
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
58
  #include <linux/file.h>
9f3acc314   Al Viro   [PATCH] split lin...
59
  #include <linux/fdtable.h>
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
60
61
62
  #include <linux/string.h>
  #include <linux/seq_file.h>
  #include <linux/namei.h>
6b3286ed1   Kirill Korotaev   [PATCH] rename st...
63
  #include <linux/mnt_namespace.h>
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
64
  #include <linux/mm.h>
b835996f6   Dipankar Sarma   [PATCH] files: lo...
65
  #include <linux/rcupdate.h>
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
66
  #include <linux/kallsyms.h>
d85f50d5e   Neil Horman   proc: export a pr...
67
  #include <linux/resource.h>
5096add84   Kees Cook   proc: maps protec...
68
  #include <linux/module.h>
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
69
70
71
  #include <linux/mount.h>
  #include <linux/security.h>
  #include <linux/ptrace.h>
0d094efeb   Roland McGrath   tracehook: traceh...
72
  #include <linux/tracehook.h>
a424316ca   Paul Menage   Task Control Grou...
73
  #include <linux/cgroup.h>
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
74
75
  #include <linux/cpuset.h>
  #include <linux/audit.h>
5addc5dd8   Al Viro   [PATCH] make /pro...
76
  #include <linux/poll.h>
1651e14e2   Serge E. Hallyn   [PATCH] namespace...
77
  #include <linux/nsproxy.h>
8ac773b4f   Alexey Dobriyan   [PATCH] OOM kille...
78
  #include <linux/oom.h>
3cb4a0bb1   Kawai, Hidehiro   coredump masking:...
79
  #include <linux/elf.h>
60347f671   Pavel Emelyanov   pid namespaces: p...
80
  #include <linux/pid_namespace.h>
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
81
  #include "internal.h"
0f2fe20f5   Eric W. Biederman   [PATCH] proc: Pro...
82
83
84
85
86
87
88
89
90
  /* NOTE:
   *	Implementing inode permission operations in /proc is almost
   *	certainly an error.  Permission checks need to happen during
   *	each system call not at open time.  The reason is that most of
   *	what we wish to check for permissions in /proc varies at runtime.
   *
   *	The classic example of a problem is opening file descriptors
   *	in /proc for a task before it execs a suid executable.
   */
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
91
  struct pid_entry {
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
92
  	char *name;
c5141e6d6   Eric Dumazet   procfs: reorder s...
93
  	int len;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
94
  	mode_t mode;
c5ef1c42c   Arjan van de Ven   [PATCH] mark stru...
95
  	const struct inode_operations *iop;
00977a59b   Arjan van de Ven   [PATCH] mark stru...
96
  	const struct file_operations *fop;
20cdc894c   Eric W. Biederman   [PATCH] proc: mod...
97
  	union proc_op op;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
98
  };
61a287840   Eric W. Biederman   [PATCH] proc: Rem...
99
  #define NOD(NAME, MODE, IOP, FOP, OP) {			\
20cdc894c   Eric W. Biederman   [PATCH] proc: mod...
100
  	.name = (NAME),					\
c5141e6d6   Eric Dumazet   procfs: reorder s...
101
  	.len  = sizeof(NAME) - 1,			\
20cdc894c   Eric W. Biederman   [PATCH] proc: mod...
102
103
104
105
106
  	.mode = MODE,					\
  	.iop  = IOP,					\
  	.fop  = FOP,					\
  	.op   = OP,					\
  }
61a287840   Eric W. Biederman   [PATCH] proc: Rem...
107
108
  #define DIR(NAME, MODE, OTYPE)							\
  	NOD(NAME, (S_IFDIR|(MODE)),						\
20cdc894c   Eric W. Biederman   [PATCH] proc: mod...
109
110
  		&proc_##OTYPE##_inode_operations, &proc_##OTYPE##_operations,	\
  		{} )
61a287840   Eric W. Biederman   [PATCH] proc: Rem...
111
112
  #define LNK(NAME, OTYPE)					\
  	NOD(NAME, (S_IFLNK|S_IRWXUGO),				\
20cdc894c   Eric W. Biederman   [PATCH] proc: mod...
113
114
  		&proc_pid_link_inode_operations, NULL,		\
  		{ .proc_get_link = &proc_##OTYPE##_link } )
61a287840   Eric W. Biederman   [PATCH] proc: Rem...
115
116
  #define REG(NAME, MODE, OTYPE)				\
  	NOD(NAME, (S_IFREG|(MODE)), NULL,		\
20cdc894c   Eric W. Biederman   [PATCH] proc: mod...
117
  		&proc_##OTYPE##_operations, {})
61a287840   Eric W. Biederman   [PATCH] proc: Rem...
118
119
  #define INF(NAME, MODE, OTYPE)				\
  	NOD(NAME, (S_IFREG|(MODE)), 			\
20cdc894c   Eric W. Biederman   [PATCH] proc: mod...
120
121
  		NULL, &proc_info_file_operations,	\
  		{ .proc_read = &proc_##OTYPE } )
be614086a   Eric W. Biederman   proc: implement p...
122
123
124
125
  #define ONE(NAME, MODE, OTYPE)				\
  	NOD(NAME, (S_IFREG|(MODE)), 			\
  		NULL, &proc_single_file_operations,	\
  		{ .proc_show = &proc_##OTYPE } )
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
126

aed541759   Vegard Nossum   proc: calculate t...
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
  /*
   * Count the number of hardlinks for the pid_entry table, excluding the .
   * and .. links.
   */
  static unsigned int pid_entry_count_dirs(const struct pid_entry *entries,
  	unsigned int n)
  {
  	unsigned int i;
  	unsigned int count;
  
  	count = 0;
  	for (i = 0; i < n; ++i) {
  		if (S_ISDIR(entries[i].mode))
  			++count;
  	}
  
  	return count;
  }
0494f6ec5   Miklos Szeredi   [PATCH] use get_f...
145
  static struct fs_struct *get_fs_struct(struct task_struct *task)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
146
147
  {
  	struct fs_struct *fs;
0494f6ec5   Miklos Szeredi   [PATCH] use get_f...
148
149
  	task_lock(task);
  	fs = task->fs;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
150
151
  	if(fs)
  		atomic_inc(&fs->count);
0494f6ec5   Miklos Szeredi   [PATCH] use get_f...
152
153
154
  	task_unlock(task);
  	return fs;
  }
99f895518   Eric W. Biederman   [PATCH] proc: don...
155
156
  static int get_nr_threads(struct task_struct *tsk)
  {
99f895518   Eric W. Biederman   [PATCH] proc: don...
157
158
159
160
161
162
163
164
165
  	unsigned long flags;
  	int count = 0;
  
  	if (lock_task_sighand(tsk, &flags)) {
  		count = atomic_read(&tsk->signal->count);
  		unlock_task_sighand(tsk, &flags);
  	}
  	return count;
  }
3dcd25f37   Jan Blunck   d_path: Make proc...
166
  static int proc_cwd_link(struct inode *inode, struct path *path)
0494f6ec5   Miklos Szeredi   [PATCH] use get_f...
167
  {
99f895518   Eric W. Biederman   [PATCH] proc: don...
168
169
  	struct task_struct *task = get_proc_task(inode);
  	struct fs_struct *fs = NULL;
0494f6ec5   Miklos Szeredi   [PATCH] use get_f...
170
  	int result = -ENOENT;
99f895518   Eric W. Biederman   [PATCH] proc: don...
171
172
173
174
175
  
  	if (task) {
  		fs = get_fs_struct(task);
  		put_task_struct(task);
  	}
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
176
177
  	if (fs) {
  		read_lock(&fs->lock);
3dcd25f37   Jan Blunck   d_path: Make proc...
178
179
  		*path = fs->pwd;
  		path_get(&fs->pwd);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
180
181
182
183
184
185
  		read_unlock(&fs->lock);
  		result = 0;
  		put_fs_struct(fs);
  	}
  	return result;
  }
3dcd25f37   Jan Blunck   d_path: Make proc...
186
  static int proc_root_link(struct inode *inode, struct path *path)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
187
  {
99f895518   Eric W. Biederman   [PATCH] proc: don...
188
189
  	struct task_struct *task = get_proc_task(inode);
  	struct fs_struct *fs = NULL;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
190
  	int result = -ENOENT;
99f895518   Eric W. Biederman   [PATCH] proc: don...
191
192
193
194
195
  
  	if (task) {
  		fs = get_fs_struct(task);
  		put_task_struct(task);
  	}
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
196
197
  	if (fs) {
  		read_lock(&fs->lock);
3dcd25f37   Jan Blunck   d_path: Make proc...
198
199
  		*path = fs->root;
  		path_get(&fs->root);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
200
201
202
203
204
205
  		read_unlock(&fs->lock);
  		result = 0;
  		put_fs_struct(fs);
  	}
  	return result;
  }
638fa202c   Roland McGrath   procfs: mem permi...
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
  /*
   * Return zero if current may access user memory in @task, -error if not.
   */
  static int check_mem_permission(struct task_struct *task)
  {
  	/*
  	 * A task can always look at itself, in case it chooses
  	 * to use system calls instead of load instructions.
  	 */
  	if (task == current)
  		return 0;
  
  	/*
  	 * If current is actively ptrace'ing, and would also be
  	 * permitted to freshly attach with ptrace now, permit it.
  	 */
0d094efeb   Roland McGrath   tracehook: traceh...
222
223
224
225
226
227
228
229
  	if (task_is_stopped_or_traced(task)) {
  		int match;
  		rcu_read_lock();
  		match = (tracehook_tracer_task(task) == current);
  		rcu_read_unlock();
  		if (match && ptrace_may_access(task, PTRACE_MODE_ATTACH))
  			return 0;
  	}
638fa202c   Roland McGrath   procfs: mem permi...
230
231
232
233
234
235
  
  	/*
  	 * Noone else is allowed.
  	 */
  	return -EPERM;
  }
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
236

831830b5a   Al Viro   restrict reading ...
237
238
239
240
241
242
243
244
245
  struct mm_struct *mm_for_maps(struct task_struct *task)
  {
  	struct mm_struct *mm = get_task_mm(task);
  	if (!mm)
  		return NULL;
  	down_read(&mm->mmap_sem);
  	task_lock(task);
  	if (task->mm != mm)
  		goto out;
006ebb40d   Stephen Smalley   Security: split p...
246
247
  	if (task->mm != current->mm &&
  	    __ptrace_may_access(task, PTRACE_MODE_READ) < 0)
831830b5a   Al Viro   restrict reading ...
248
249
250
251
252
253
254
255
256
  		goto out;
  	task_unlock(task);
  	return mm;
  out:
  	task_unlock(task);
  	up_read(&mm->mmap_sem);
  	mmput(mm);
  	return NULL;
  }
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
  static int proc_pid_cmdline(struct task_struct *task, char * buffer)
  {
  	int res = 0;
  	unsigned int len;
  	struct mm_struct *mm = get_task_mm(task);
  	if (!mm)
  		goto out;
  	if (!mm->arg_end)
  		goto out_mm;	/* Shh! No looking before we're done */
  
   	len = mm->arg_end - mm->arg_start;
   
  	if (len > PAGE_SIZE)
  		len = PAGE_SIZE;
   
  	res = access_process_vm(task, mm->arg_start, buffer, len, 0);
  
  	// If the nul at the end of args has been overwritten, then
  	// assume application is using setproctitle(3).
  	if (res > 0 && buffer[res-1] != '\0' && len < PAGE_SIZE) {
  		len = strnlen(buffer, res);
  		if (len < res) {
  		    res = len;
  		} else {
  			len = mm->env_end - mm->env_start;
  			if (len > PAGE_SIZE - res)
  				len = PAGE_SIZE - res;
  			res += access_process_vm(task, mm->env_start, buffer+res, len, 0);
  			res = strnlen(buffer, res);
  		}
  	}
  out_mm:
  	mmput(mm);
  out:
  	return res;
  }
  
  static int proc_pid_auxv(struct task_struct *task, char *buffer)
  {
  	int res = 0;
  	struct mm_struct *mm = get_task_mm(task);
  	if (mm) {
  		unsigned int nwords = 0;
  		do
  			nwords += 2;
  		while (mm->saved_auxv[nwords - 2] != 0); /* AT_NULL */
  		res = nwords * sizeof(mm->saved_auxv[0]);
  		if (res > PAGE_SIZE)
  			res = PAGE_SIZE;
  		memcpy(buffer, mm->saved_auxv, res);
  		mmput(mm);
  	}
  	return res;
  }
  
  
  #ifdef CONFIG_KALLSYMS
  /*
   * Provides a wchan file via kallsyms in a proper one-value-per-file format.
   * Returns the resolved symbol.  If that fails, simply return the address.
   */
  static int proc_pid_wchan(struct task_struct *task, char *buffer)
  {
ffb451227   Alexey Dobriyan   Simplify kallsyms...
320
  	unsigned long wchan;
9281acea6   Tejun Heo   kallsyms: make KS...
321
  	char symname[KSYM_NAME_LEN];
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
322
323
  
  	wchan = get_wchan(task);
9d65cb4a1   Alexey Dobriyan   Fix race between ...
324
325
326
327
  	if (lookup_symbol_name(wchan, symname) < 0)
  		return sprintf(buffer, "%lu", wchan);
  	else
  		return sprintf(buffer, "%s", symname);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
328
329
330
331
332
333
334
335
336
  }
  #endif /* CONFIG_KALLSYMS */
  
  #ifdef CONFIG_SCHEDSTATS
  /*
   * Provides /proc/PID/schedstat
   */
  static int proc_pid_schedstat(struct task_struct *task, char *buffer)
  {
172ba844a   Balbir Singh   sched: update del...
337
338
  	return sprintf(buffer, "%llu %llu %lu
  ",
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
339
340
  			task->sched_info.cpu_time,
  			task->sched_info.run_delay,
2d72376b3   Ingo Molnar   sched: clean up s...
341
  			task->sched_info.pcount);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
342
343
  }
  #endif
9745512ce   Arjan van de Ven   sched: latencytop...
344
345
346
347
  #ifdef CONFIG_LATENCYTOP
  static int lstats_show_proc(struct seq_file *m, void *v)
  {
  	int i;
13d77c37c   Hiroshi Shimamoto   latencytop: chang...
348
349
  	struct inode *inode = m->private;
  	struct task_struct *task = get_proc_task(inode);
9745512ce   Arjan van de Ven   sched: latencytop...
350

13d77c37c   Hiroshi Shimamoto   latencytop: chang...
351
352
353
354
  	if (!task)
  		return -ESRCH;
  	seq_puts(m, "Latency Top version : v0.1
  ");
9745512ce   Arjan van de Ven   sched: latencytop...
355
356
357
358
359
360
361
362
  	for (i = 0; i < 32; i++) {
  		if (task->latency_record[i].backtrace[0]) {
  			int q;
  			seq_printf(m, "%i %li %li ",
  				task->latency_record[i].count,
  				task->latency_record[i].time,
  				task->latency_record[i].max);
  			for (q = 0; q < LT_BACKTRACEDEPTH; q++) {
9c2462472   Hugh Dickins   KSYM_SYMBOL_LEN f...
363
  				char sym[KSYM_SYMBOL_LEN];
9745512ce   Arjan van de Ven   sched: latencytop...
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
  				char *c;
  				if (!task->latency_record[i].backtrace[q])
  					break;
  				if (task->latency_record[i].backtrace[q] == ULONG_MAX)
  					break;
  				sprint_symbol(sym, task->latency_record[i].backtrace[q]);
  				c = strchr(sym, '+');
  				if (c)
  					*c = 0;
  				seq_printf(m, "%s ", sym);
  			}
  			seq_printf(m, "
  ");
  		}
  
  	}
13d77c37c   Hiroshi Shimamoto   latencytop: chang...
380
  	put_task_struct(task);
9745512ce   Arjan van de Ven   sched: latencytop...
381
382
383
384
385
  	return 0;
  }
  
  static int lstats_open(struct inode *inode, struct file *file)
  {
13d77c37c   Hiroshi Shimamoto   latencytop: chang...
386
  	return single_open(file, lstats_show_proc, inode);
d6643d12c   Hiroshi Shimamoto   latencytop: fix m...
387
  }
9745512ce   Arjan van de Ven   sched: latencytop...
388
389
390
  static ssize_t lstats_write(struct file *file, const char __user *buf,
  			    size_t count, loff_t *offs)
  {
13d77c37c   Hiroshi Shimamoto   latencytop: chang...
391
  	struct task_struct *task = get_proc_task(file->f_dentry->d_inode);
9745512ce   Arjan van de Ven   sched: latencytop...
392

13d77c37c   Hiroshi Shimamoto   latencytop: chang...
393
394
  	if (!task)
  		return -ESRCH;
9745512ce   Arjan van de Ven   sched: latencytop...
395
  	clear_all_latency_tracing(task);
13d77c37c   Hiroshi Shimamoto   latencytop: chang...
396
  	put_task_struct(task);
9745512ce   Arjan van de Ven   sched: latencytop...
397
398
399
400
401
402
403
404
405
  
  	return count;
  }
  
  static const struct file_operations proc_lstats_operations = {
  	.open		= lstats_open,
  	.read		= seq_read,
  	.write		= lstats_write,
  	.llseek		= seq_lseek,
13d77c37c   Hiroshi Shimamoto   latencytop: chang...
406
  	.release	= single_release,
9745512ce   Arjan van de Ven   sched: latencytop...
407
408
409
  };
  
  #endif
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
410
411
412
413
414
415
416
417
  /* The badness from the OOM killer */
  unsigned long badness(struct task_struct *p, unsigned long uptime);
  static int proc_oom_score(struct task_struct *task, char *buffer)
  {
  	unsigned long points;
  	struct timespec uptime;
  
  	do_posix_clock_monotonic_gettime(&uptime);
19c5d45a0   Alexey Dobriyan   /proc/*/oom_score...
418
  	read_lock(&tasklist_lock);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
419
  	points = badness(task, uptime.tv_sec);
19c5d45a0   Alexey Dobriyan   /proc/*/oom_score...
420
  	read_unlock(&tasklist_lock);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
421
422
423
  	return sprintf(buffer, "%lu
  ", points);
  }
d85f50d5e   Neil Horman   proc: export a pr...
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
  struct limit_names {
  	char *name;
  	char *unit;
  };
  
  static const struct limit_names lnames[RLIM_NLIMITS] = {
  	[RLIMIT_CPU] = {"Max cpu time", "ms"},
  	[RLIMIT_FSIZE] = {"Max file size", "bytes"},
  	[RLIMIT_DATA] = {"Max data size", "bytes"},
  	[RLIMIT_STACK] = {"Max stack size", "bytes"},
  	[RLIMIT_CORE] = {"Max core file size", "bytes"},
  	[RLIMIT_RSS] = {"Max resident set", "bytes"},
  	[RLIMIT_NPROC] = {"Max processes", "processes"},
  	[RLIMIT_NOFILE] = {"Max open files", "files"},
  	[RLIMIT_MEMLOCK] = {"Max locked memory", "bytes"},
  	[RLIMIT_AS] = {"Max address space", "bytes"},
  	[RLIMIT_LOCKS] = {"Max file locks", "locks"},
  	[RLIMIT_SIGPENDING] = {"Max pending signals", "signals"},
  	[RLIMIT_MSGQUEUE] = {"Max msgqueue size", "bytes"},
  	[RLIMIT_NICE] = {"Max nice priority", NULL},
  	[RLIMIT_RTPRIO] = {"Max realtime priority", NULL},
8808117ca   Eugene Teo   proc: add RLIMIT_...
445
  	[RLIMIT_RTTIME] = {"Max realtime timeout", "us"},
d85f50d5e   Neil Horman   proc: export a pr...
446
447
448
449
450
451
452
453
454
455
456
  };
  
  /* Display limits for a process */
  static int proc_pid_limits(struct task_struct *task, char *buffer)
  {
  	unsigned int i;
  	int count = 0;
  	unsigned long flags;
  	char *bufptr = buffer;
  
  	struct rlimit rlim[RLIM_NLIMITS];
a6bebbc87   Lai Jiangshan   [PATCH] signal, p...
457
  	if (!lock_task_sighand(task, &flags))
d85f50d5e   Neil Horman   proc: export a pr...
458
  		return 0;
d85f50d5e   Neil Horman   proc: export a pr...
459
460
  	memcpy(rlim, task->signal->rlim, sizeof(struct rlimit) * RLIM_NLIMITS);
  	unlock_task_sighand(task, &flags);
d85f50d5e   Neil Horman   proc: export a pr...
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
  
  	/*
  	 * print the file header
  	 */
  	count += sprintf(&bufptr[count], "%-25s %-20s %-20s %-10s
  ",
  			"Limit", "Soft Limit", "Hard Limit", "Units");
  
  	for (i = 0; i < RLIM_NLIMITS; i++) {
  		if (rlim[i].rlim_cur == RLIM_INFINITY)
  			count += sprintf(&bufptr[count], "%-25s %-20s ",
  					 lnames[i].name, "unlimited");
  		else
  			count += sprintf(&bufptr[count], "%-25s %-20lu ",
  					 lnames[i].name, rlim[i].rlim_cur);
  
  		if (rlim[i].rlim_max == RLIM_INFINITY)
  			count += sprintf(&bufptr[count], "%-20s ", "unlimited");
  		else
  			count += sprintf(&bufptr[count], "%-20lu ",
  					 rlim[i].rlim_max);
  
  		if (lnames[i].unit)
  			count += sprintf(&bufptr[count], "%-10s
  ",
  					 lnames[i].unit);
  		else
  			count += sprintf(&bufptr[count], "
  ");
  	}
  
  	return count;
  }
ebcb67341   Roland McGrath   /proc/PID/syscall
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
  #ifdef CONFIG_HAVE_ARCH_TRACEHOOK
  static int proc_pid_syscall(struct task_struct *task, char *buffer)
  {
  	long nr;
  	unsigned long args[6], sp, pc;
  
  	if (task_current_syscall(task, &nr, args, 6, &sp, &pc))
  		return sprintf(buffer, "running
  ");
  
  	if (nr < 0)
  		return sprintf(buffer, "%ld 0x%lx 0x%lx
  ", nr, sp, pc);
  
  	return sprintf(buffer,
  		       "%ld 0x%lx 0x%lx 0x%lx 0x%lx 0x%lx 0x%lx 0x%lx 0x%lx
  ",
  		       nr,
  		       args[0], args[1], args[2], args[3], args[4], args[5],
  		       sp, pc);
  }
  #endif /* CONFIG_HAVE_ARCH_TRACEHOOK */
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
516
517
518
519
520
  /************************************************************************/
  /*                       Here the fs part begins                        */
  /************************************************************************/
  
  /* permission checks */
778c11447   Eric W. Biederman   [PATCH] proc: Use...
521
  static int proc_fd_access_allowed(struct inode *inode)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
522
  {
778c11447   Eric W. Biederman   [PATCH] proc: Use...
523
524
  	struct task_struct *task;
  	int allowed = 0;
df26c40e5   Eric W. Biederman   [PATCH] proc: Cle...
525
526
527
  	/* Allow access to a task's file descriptors if it is us or we
  	 * may use ptrace attach to the process and find out that
  	 * information.
778c11447   Eric W. Biederman   [PATCH] proc: Use...
528
529
  	 */
  	task = get_proc_task(inode);
df26c40e5   Eric W. Biederman   [PATCH] proc: Cle...
530
  	if (task) {
006ebb40d   Stephen Smalley   Security: split p...
531
  		allowed = ptrace_may_access(task, PTRACE_MODE_READ);
778c11447   Eric W. Biederman   [PATCH] proc: Use...
532
  		put_task_struct(task);
df26c40e5   Eric W. Biederman   [PATCH] proc: Cle...
533
  	}
778c11447   Eric W. Biederman   [PATCH] proc: Use...
534
  	return allowed;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
535
  }
6d76fa58b   Linus Torvalds   Don't allow chmod...
536
537
538
539
540
541
542
543
544
  static int proc_setattr(struct dentry *dentry, struct iattr *attr)
  {
  	int error;
  	struct inode *inode = dentry->d_inode;
  
  	if (attr->ia_valid & ATTR_MODE)
  		return -EPERM;
  
  	error = inode_change_ok(inode, attr);
1e8123fde   John Johansen   Remove redundant ...
545
546
  	if (!error)
  		error = inode_setattr(inode, attr);
6d76fa58b   Linus Torvalds   Don't allow chmod...
547
548
  	return error;
  }
c5ef1c42c   Arjan van de Ven   [PATCH] mark stru...
549
  static const struct inode_operations proc_def_inode_operations = {
6d76fa58b   Linus Torvalds   Don't allow chmod...
550
551
  	.setattr	= proc_setattr,
  };
a1a2c409b   Miklos Szeredi   [patch 5/7] vfs: ...
552
553
  static int mounts_open_common(struct inode *inode, struct file *file,
  			      const struct seq_operations *op)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
554
  {
99f895518   Eric W. Biederman   [PATCH] proc: don...
555
  	struct task_struct *task = get_proc_task(inode);
cf7b708c8   Pavel Emelyanov   Make access to ta...
556
  	struct nsproxy *nsp;
6b3286ed1   Kirill Korotaev   [PATCH] rename st...
557
  	struct mnt_namespace *ns = NULL;
a1a2c409b   Miklos Szeredi   [patch 5/7] vfs: ...
558
559
  	struct fs_struct *fs = NULL;
  	struct path root;
5addc5dd8   Al Viro   [PATCH] make /pro...
560
561
  	struct proc_mounts *p;
  	int ret = -EINVAL;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
562

99f895518   Eric W. Biederman   [PATCH] proc: don...
563
  	if (task) {
cf7b708c8   Pavel Emelyanov   Make access to ta...
564
565
566
567
  		rcu_read_lock();
  		nsp = task_nsproxy(task);
  		if (nsp) {
  			ns = nsp->mnt_ns;
863c47028   Alexey Dobriyan   [PATCH] Fix NULL ...
568
569
570
  			if (ns)
  				get_mnt_ns(ns);
  		}
cf7b708c8   Pavel Emelyanov   Make access to ta...
571
  		rcu_read_unlock();
a1a2c409b   Miklos Szeredi   [patch 5/7] vfs: ...
572
573
  		if (ns)
  			fs = get_fs_struct(task);
99f895518   Eric W. Biederman   [PATCH] proc: don...
574
575
  		put_task_struct(task);
  	}
5addc5dd8   Al Viro   [PATCH] make /pro...
576

a1a2c409b   Miklos Szeredi   [patch 5/7] vfs: ...
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
  	if (!ns)
  		goto err;
  	if (!fs)
  		goto err_put_ns;
  
  	read_lock(&fs->lock);
  	root = fs->root;
  	path_get(&root);
  	read_unlock(&fs->lock);
  	put_fs_struct(fs);
  
  	ret = -ENOMEM;
  	p = kmalloc(sizeof(struct proc_mounts), GFP_KERNEL);
  	if (!p)
  		goto err_put_path;
  
  	file->private_data = &p->m;
  	ret = seq_open(file, op);
  	if (ret)
  		goto err_free;
  
  	p->m.private = p;
  	p->ns = ns;
  	p->root = root;
  	p->event = ns->event;
  
  	return 0;
  
   err_free:
  	kfree(p);
   err_put_path:
  	path_put(&root);
   err_put_ns:
  	put_mnt_ns(ns);
   err:
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
612
613
614
615
616
  	return ret;
  }
  
  static int mounts_release(struct inode *inode, struct file *file)
  {
a1a2c409b   Miklos Szeredi   [patch 5/7] vfs: ...
617
618
619
  	struct proc_mounts *p = file->private_data;
  	path_put(&p->root);
  	put_mnt_ns(p->ns);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
620
621
  	return seq_release(inode, file);
  }
5addc5dd8   Al Viro   [PATCH] make /pro...
622
623
624
  static unsigned mounts_poll(struct file *file, poll_table *wait)
  {
  	struct proc_mounts *p = file->private_data;
a1a2c409b   Miklos Szeredi   [patch 5/7] vfs: ...
625
  	struct mnt_namespace *ns = p->ns;
5addc5dd8   Al Viro   [PATCH] make /pro...
626
627
628
629
630
631
632
633
634
635
636
637
638
  	unsigned res = 0;
  
  	poll_wait(file, &ns->poll, wait);
  
  	spin_lock(&vfsmount_lock);
  	if (p->event != ns->event) {
  		p->event = ns->event;
  		res = POLLERR;
  	}
  	spin_unlock(&vfsmount_lock);
  
  	return res;
  }
a1a2c409b   Miklos Szeredi   [patch 5/7] vfs: ...
639
640
641
642
  static int mounts_open(struct inode *inode, struct file *file)
  {
  	return mounts_open_common(inode, file, &mounts_op);
  }
00977a59b   Arjan van de Ven   [PATCH] mark stru...
643
  static const struct file_operations proc_mounts_operations = {
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
644
645
646
647
  	.open		= mounts_open,
  	.read		= seq_read,
  	.llseek		= seq_lseek,
  	.release	= mounts_release,
5addc5dd8   Al Viro   [PATCH] make /pro...
648
  	.poll		= mounts_poll,
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
649
  };
2d4d4864a   Ram Pai   [patch 6/7] vfs: ...
650
651
652
653
654
655
656
657
658
659
660
661
  static int mountinfo_open(struct inode *inode, struct file *file)
  {
  	return mounts_open_common(inode, file, &mountinfo_op);
  }
  
  static const struct file_operations proc_mountinfo_operations = {
  	.open		= mountinfo_open,
  	.read		= seq_read,
  	.llseek		= seq_lseek,
  	.release	= mounts_release,
  	.poll		= mounts_poll,
  };
b4629fe2f   Chuck Lever   VFS: New /proc fi...
662
663
  static int mountstats_open(struct inode *inode, struct file *file)
  {
a1a2c409b   Miklos Szeredi   [patch 5/7] vfs: ...
664
  	return mounts_open_common(inode, file, &mountstats_op);
b4629fe2f   Chuck Lever   VFS: New /proc fi...
665
  }
00977a59b   Arjan van de Ven   [PATCH] mark stru...
666
  static const struct file_operations proc_mountstats_operations = {
b4629fe2f   Chuck Lever   VFS: New /proc fi...
667
668
669
670
671
  	.open		= mountstats_open,
  	.read		= seq_read,
  	.llseek		= seq_lseek,
  	.release	= mounts_release,
  };
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
672
673
674
675
676
  #define PROC_BLOCK_SIZE	(3*1024)		/* 4K page size but our output routines use some slack for overruns */
  
  static ssize_t proc_info_read(struct file * file, char __user * buf,
  			  size_t count, loff_t *ppos)
  {
2fddfeefe   Josef "Jeff" Sipek   [PATCH] proc: cha...
677
  	struct inode * inode = file->f_path.dentry->d_inode;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
678
679
  	unsigned long page;
  	ssize_t length;
99f895518   Eric W. Biederman   [PATCH] proc: don...
680
681
682
683
684
  	struct task_struct *task = get_proc_task(inode);
  
  	length = -ESRCH;
  	if (!task)
  		goto out_no_task;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
685
686
687
  
  	if (count > PROC_BLOCK_SIZE)
  		count = PROC_BLOCK_SIZE;
99f895518   Eric W. Biederman   [PATCH] proc: don...
688
689
  
  	length = -ENOMEM;
e12ba74d8   Mel Gorman   Group short-lived...
690
  	if (!(page = __get_free_page(GFP_TEMPORARY)))
99f895518   Eric W. Biederman   [PATCH] proc: don...
691
  		goto out;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
692
693
694
695
696
697
  
  	length = PROC_I(inode)->op.proc_read(task, (char*)page);
  
  	if (length >= 0)
  		length = simple_read_from_buffer(buf, count, ppos, (char *)page, length);
  	free_page(page);
99f895518   Eric W. Biederman   [PATCH] proc: don...
698
699
700
  out:
  	put_task_struct(task);
  out_no_task:
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
701
702
  	return length;
  }
00977a59b   Arjan van de Ven   [PATCH] mark stru...
703
  static const struct file_operations proc_info_file_operations = {
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
704
705
  	.read		= proc_info_read,
  };
be614086a   Eric W. Biederman   proc: implement p...
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
  static int proc_single_show(struct seq_file *m, void *v)
  {
  	struct inode *inode = m->private;
  	struct pid_namespace *ns;
  	struct pid *pid;
  	struct task_struct *task;
  	int ret;
  
  	ns = inode->i_sb->s_fs_info;
  	pid = proc_pid(inode);
  	task = get_pid_task(pid, PIDTYPE_PID);
  	if (!task)
  		return -ESRCH;
  
  	ret = PROC_I(inode)->op.proc_show(m, ns, pid, task);
  
  	put_task_struct(task);
  	return ret;
  }
  
  static int proc_single_open(struct inode *inode, struct file *filp)
  {
  	int ret;
  	ret = single_open(filp, proc_single_show, NULL);
  	if (!ret) {
  		struct seq_file *m = filp->private_data;
  
  		m->private = inode;
  	}
  	return ret;
  }
  
  static const struct file_operations proc_single_file_operations = {
  	.open		= proc_single_open,
  	.read		= seq_read,
  	.llseek		= seq_lseek,
  	.release	= single_release,
  };
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
744
745
746
747
748
749
750
751
752
  static int mem_open(struct inode* inode, struct file* file)
  {
  	file->private_data = (void*)((long)current->self_exec_id);
  	return 0;
  }
  
  static ssize_t mem_read(struct file * file, char __user * buf,
  			size_t count, loff_t *ppos)
  {
2fddfeefe   Josef "Jeff" Sipek   [PATCH] proc: cha...
753
  	struct task_struct *task = get_proc_task(file->f_path.dentry->d_inode);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
754
755
756
757
  	char *page;
  	unsigned long src = *ppos;
  	int ret = -ESRCH;
  	struct mm_struct *mm;
99f895518   Eric W. Biederman   [PATCH] proc: don...
758
759
  	if (!task)
  		goto out_no_task;
638fa202c   Roland McGrath   procfs: mem permi...
760
  	if (check_mem_permission(task))
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
761
762
763
  		goto out;
  
  	ret = -ENOMEM;
e12ba74d8   Mel Gorman   Group short-lived...
764
  	page = (char *)__get_free_page(GFP_TEMPORARY);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
  	if (!page)
  		goto out;
  
  	ret = 0;
   
  	mm = get_task_mm(task);
  	if (!mm)
  		goto out_free;
  
  	ret = -EIO;
   
  	if (file->private_data != (void*)((long)current->self_exec_id))
  		goto out_put;
  
  	ret = 0;
   
  	while (count > 0) {
  		int this_len, retval;
  
  		this_len = (count > PAGE_SIZE) ? PAGE_SIZE : count;
  		retval = access_process_vm(task, src, page, this_len, 0);
638fa202c   Roland McGrath   procfs: mem permi...
786
  		if (!retval || check_mem_permission(task)) {
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
  			if (!ret)
  				ret = -EIO;
  			break;
  		}
  
  		if (copy_to_user(buf, page, retval)) {
  			ret = -EFAULT;
  			break;
  		}
   
  		ret += retval;
  		src += retval;
  		buf += retval;
  		count -= retval;
  	}
  	*ppos = src;
  
  out_put:
  	mmput(mm);
  out_free:
  	free_page((unsigned long) page);
  out:
99f895518   Eric W. Biederman   [PATCH] proc: don...
809
810
  	put_task_struct(task);
  out_no_task:
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
811
812
813
814
815
816
817
  	return ret;
  }
  
  #define mem_write NULL
  
  #ifndef mem_write
  /* This is a security hazard */
63967fa91   Glauber de Oliveira Costa   [PATCH] Missing _...
818
  static ssize_t mem_write(struct file * file, const char __user *buf,
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
819
820
  			 size_t count, loff_t *ppos)
  {
f7ca54f48   Frederik Deweerdt   [PATCH] fix mem_w...
821
  	int copied;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
822
  	char *page;
2fddfeefe   Josef "Jeff" Sipek   [PATCH] proc: cha...
823
  	struct task_struct *task = get_proc_task(file->f_path.dentry->d_inode);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
824
  	unsigned long dst = *ppos;
99f895518   Eric W. Biederman   [PATCH] proc: don...
825
826
827
  	copied = -ESRCH;
  	if (!task)
  		goto out_no_task;
638fa202c   Roland McGrath   procfs: mem permi...
828
  	if (check_mem_permission(task))
99f895518   Eric W. Biederman   [PATCH] proc: don...
829
  		goto out;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
830

99f895518   Eric W. Biederman   [PATCH] proc: don...
831
  	copied = -ENOMEM;
e12ba74d8   Mel Gorman   Group short-lived...
832
  	page = (char *)__get_free_page(GFP_TEMPORARY);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
833
  	if (!page)
99f895518   Eric W. Biederman   [PATCH] proc: don...
834
  		goto out;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
835

f7ca54f48   Frederik Deweerdt   [PATCH] fix mem_w...
836
  	copied = 0;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
854
855
856
857
  	while (count > 0) {
  		int this_len, retval;
  
  		this_len = (count > PAGE_SIZE) ? PAGE_SIZE : count;
  		if (copy_from_user(page, buf, this_len)) {
  			copied = -EFAULT;
  			break;
  		}
  		retval = access_process_vm(task, dst, page, this_len, 1);
  		if (!retval) {
  			if (!copied)
  				copied = -EIO;
  			break;
  		}
  		copied += retval;
  		buf += retval;
  		dst += retval;
  		count -= retval;			
  	}
  	*ppos = dst;
  	free_page((unsigned long) page);
99f895518   Eric W. Biederman   [PATCH] proc: don...
858
859
860
  out:
  	put_task_struct(task);
  out_no_task:
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
861
862
863
  	return copied;
  }
  #endif
85863e475   Matt Mackall   maps4: add /proc/...
864
  loff_t mem_lseek(struct file *file, loff_t offset, int orig)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
865
866
867
868
869
870
871
872
873
874
875
876
877
878
  {
  	switch (orig) {
  	case 0:
  		file->f_pos = offset;
  		break;
  	case 1:
  		file->f_pos += offset;
  		break;
  	default:
  		return -EINVAL;
  	}
  	force_successful_syscall_return();
  	return file->f_pos;
  }
00977a59b   Arjan van de Ven   [PATCH] mark stru...
879
  static const struct file_operations proc_mem_operations = {
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
880
881
882
883
884
  	.llseek		= mem_lseek,
  	.read		= mem_read,
  	.write		= mem_write,
  	.open		= mem_open,
  };
315e28c8d   James Pearson   Don't truncate /p...
885
886
887
888
889
890
891
892
893
894
895
  static ssize_t environ_read(struct file *file, char __user *buf,
  			size_t count, loff_t *ppos)
  {
  	struct task_struct *task = get_proc_task(file->f_dentry->d_inode);
  	char *page;
  	unsigned long src = *ppos;
  	int ret = -ESRCH;
  	struct mm_struct *mm;
  
  	if (!task)
  		goto out_no_task;
006ebb40d   Stephen Smalley   Security: split p...
896
  	if (!ptrace_may_access(task, PTRACE_MODE_READ))
315e28c8d   James Pearson   Don't truncate /p...
897
898
899
900
901
902
903
904
905
906
907
908
909
910
911
912
913
914
915
916
917
918
919
920
921
922
923
924
925
926
927
928
929
930
931
932
933
934
935
936
937
938
939
940
941
942
943
944
945
946
947
948
949
950
951
952
  		goto out;
  
  	ret = -ENOMEM;
  	page = (char *)__get_free_page(GFP_TEMPORARY);
  	if (!page)
  		goto out;
  
  	ret = 0;
  
  	mm = get_task_mm(task);
  	if (!mm)
  		goto out_free;
  
  	while (count > 0) {
  		int this_len, retval, max_len;
  
  		this_len = mm->env_end - (mm->env_start + src);
  
  		if (this_len <= 0)
  			break;
  
  		max_len = (count > PAGE_SIZE) ? PAGE_SIZE : count;
  		this_len = (this_len > max_len) ? max_len : this_len;
  
  		retval = access_process_vm(task, (mm->env_start + src),
  			page, this_len, 0);
  
  		if (retval <= 0) {
  			ret = retval;
  			break;
  		}
  
  		if (copy_to_user(buf, page, retval)) {
  			ret = -EFAULT;
  			break;
  		}
  
  		ret += retval;
  		src += retval;
  		buf += retval;
  		count -= retval;
  	}
  	*ppos = src;
  
  	mmput(mm);
  out_free:
  	free_page((unsigned long) page);
  out:
  	put_task_struct(task);
  out_no_task:
  	return ret;
  }
  
  static const struct file_operations proc_environ_operations = {
  	.read		= environ_read,
  };
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
953
954
955
  static ssize_t oom_adjust_read(struct file *file, char __user *buf,
  				size_t count, loff_t *ppos)
  {
2fddfeefe   Josef "Jeff" Sipek   [PATCH] proc: cha...
956
  	struct task_struct *task = get_proc_task(file->f_path.dentry->d_inode);
8578cea75   Eric W. Biederman   [PATCH] proc: mak...
957
  	char buffer[PROC_NUMBUF];
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
958
  	size_t len;
99f895518   Eric W. Biederman   [PATCH] proc: don...
959
  	int oom_adjust;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
960

99f895518   Eric W. Biederman   [PATCH] proc: don...
961
962
963
964
  	if (!task)
  		return -ESRCH;
  	oom_adjust = task->oomkilladj;
  	put_task_struct(task);
8578cea75   Eric W. Biederman   [PATCH] proc: mak...
965
966
  	len = snprintf(buffer, sizeof(buffer), "%i
  ", oom_adjust);
0c28f287a   Akinobu Mita   procfs: use simpl...
967
968
  
  	return simple_read_from_buffer(buf, count, ppos, buffer, len);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
969
970
971
972
973
  }
  
  static ssize_t oom_adjust_write(struct file *file, const char __user *buf,
  				size_t count, loff_t *ppos)
  {
99f895518   Eric W. Biederman   [PATCH] proc: don...
974
  	struct task_struct *task;
8578cea75   Eric W. Biederman   [PATCH] proc: mak...
975
  	char buffer[PROC_NUMBUF], *end;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
976
  	int oom_adjust;
8578cea75   Eric W. Biederman   [PATCH] proc: mak...
977
978
979
  	memset(buffer, 0, sizeof(buffer));
  	if (count > sizeof(buffer) - 1)
  		count = sizeof(buffer) - 1;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
980
981
982
  	if (copy_from_user(buffer, buf, count))
  		return -EFAULT;
  	oom_adjust = simple_strtol(buffer, &end, 0);
8ac773b4f   Alexey Dobriyan   [PATCH] OOM kille...
983
984
  	if ((oom_adjust < OOM_ADJUST_MIN || oom_adjust > OOM_ADJUST_MAX) &&
  	     oom_adjust != OOM_DISABLE)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
985
986
987
988
  		return -EINVAL;
  	if (*end == '
  ')
  		end++;
2fddfeefe   Josef "Jeff" Sipek   [PATCH] proc: cha...
989
  	task = get_proc_task(file->f_path.dentry->d_inode);
99f895518   Eric W. Biederman   [PATCH] proc: don...
990
991
  	if (!task)
  		return -ESRCH;
8fb4fc68c   Guillem Jover   [PATCH] Allow use...
992
993
994
995
  	if (oom_adjust < task->oomkilladj && !capable(CAP_SYS_RESOURCE)) {
  		put_task_struct(task);
  		return -EACCES;
  	}
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
996
  	task->oomkilladj = oom_adjust;
99f895518   Eric W. Biederman   [PATCH] proc: don...
997
  	put_task_struct(task);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
998
999
1000
1001
  	if (end - buffer == 0)
  		return -EIO;
  	return end - buffer;
  }
00977a59b   Arjan van de Ven   [PATCH] mark stru...
1002
  static const struct file_operations proc_oom_adjust_operations = {
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1003
1004
1005
  	.read		= oom_adjust_read,
  	.write		= oom_adjust_write,
  };
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1006
1007
1008
1009
1010
  #ifdef CONFIG_AUDITSYSCALL
  #define TMPBUFLEN 21
  static ssize_t proc_loginuid_read(struct file * file, char __user * buf,
  				  size_t count, loff_t *ppos)
  {
2fddfeefe   Josef "Jeff" Sipek   [PATCH] proc: cha...
1011
  	struct inode * inode = file->f_path.dentry->d_inode;
99f895518   Eric W. Biederman   [PATCH] proc: don...
1012
  	struct task_struct *task = get_proc_task(inode);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1013
1014
  	ssize_t length;
  	char tmpbuf[TMPBUFLEN];
99f895518   Eric W. Biederman   [PATCH] proc: don...
1015
1016
  	if (!task)
  		return -ESRCH;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1017
  	length = scnprintf(tmpbuf, TMPBUFLEN, "%u",
0c11b9428   Al Viro   [PATCH] switch au...
1018
  				audit_get_loginuid(task));
99f895518   Eric W. Biederman   [PATCH] proc: don...
1019
  	put_task_struct(task);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1020
1021
1022
1023
1024
1025
  	return simple_read_from_buffer(buf, count, ppos, tmpbuf, length);
  }
  
  static ssize_t proc_loginuid_write(struct file * file, const char __user * buf,
  				   size_t count, loff_t *ppos)
  {
2fddfeefe   Josef "Jeff" Sipek   [PATCH] proc: cha...
1026
  	struct inode * inode = file->f_path.dentry->d_inode;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1027
1028
  	char *page, *tmp;
  	ssize_t length;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1029
1030
1031
1032
  	uid_t loginuid;
  
  	if (!capable(CAP_AUDIT_CONTROL))
  		return -EPERM;
13b41b094   Eric W. Biederman   [PATCH] proc: Use...
1033
  	if (current != pid_task(proc_pid(inode), PIDTYPE_PID))
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1034
  		return -EPERM;
e01829092   Al Viro   [PATCH] proc_logi...
1035
1036
  	if (count >= PAGE_SIZE)
  		count = PAGE_SIZE - 1;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1037
1038
1039
1040
1041
  
  	if (*ppos != 0) {
  		/* No partial writes. */
  		return -EINVAL;
  	}
e12ba74d8   Mel Gorman   Group short-lived...
1042
  	page = (char*)__get_free_page(GFP_TEMPORARY);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1043
1044
1045
1046
1047
  	if (!page)
  		return -ENOMEM;
  	length = -EFAULT;
  	if (copy_from_user(page, buf, count))
  		goto out_free_page;
e01829092   Al Viro   [PATCH] proc_logi...
1048
  	page[count] = '\0';
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1049
1050
1051
1052
1053
1054
  	loginuid = simple_strtoul(page, &tmp, 10);
  	if (tmp == page) {
  		length = -EINVAL;
  		goto out_free_page;
  
  	}
99f895518   Eric W. Biederman   [PATCH] proc: don...
1055
  	length = audit_set_loginuid(current, loginuid);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1056
1057
1058
1059
1060
1061
1062
  	if (likely(length == 0))
  		length = count;
  
  out_free_page:
  	free_page((unsigned long) page);
  	return length;
  }
00977a59b   Arjan van de Ven   [PATCH] mark stru...
1063
  static const struct file_operations proc_loginuid_operations = {
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1064
1065
1066
  	.read		= proc_loginuid_read,
  	.write		= proc_loginuid_write,
  };
1e0bd7550   Eric Paris   [PATCH] export se...
1067
1068
1069
1070
1071
1072
1073
1074
1075
1076
1077
1078
1079
1080
1081
1082
1083
1084
1085
1086
  
  static ssize_t proc_sessionid_read(struct file * file, char __user * buf,
  				  size_t count, loff_t *ppos)
  {
  	struct inode * inode = file->f_path.dentry->d_inode;
  	struct task_struct *task = get_proc_task(inode);
  	ssize_t length;
  	char tmpbuf[TMPBUFLEN];
  
  	if (!task)
  		return -ESRCH;
  	length = scnprintf(tmpbuf, TMPBUFLEN, "%u",
  				audit_get_sessionid(task));
  	put_task_struct(task);
  	return simple_read_from_buffer(buf, count, ppos, tmpbuf, length);
  }
  
  static const struct file_operations proc_sessionid_operations = {
  	.read		= proc_sessionid_read,
  };
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1087
  #endif
f4f154fd9   Akinobu Mita   [PATCH] fault inj...
1088
1089
1090
1091
1092
1093
1094
1095
  #ifdef CONFIG_FAULT_INJECTION
  static ssize_t proc_fault_inject_read(struct file * file, char __user * buf,
  				      size_t count, loff_t *ppos)
  {
  	struct task_struct *task = get_proc_task(file->f_dentry->d_inode);
  	char buffer[PROC_NUMBUF];
  	size_t len;
  	int make_it_fail;
f4f154fd9   Akinobu Mita   [PATCH] fault inj...
1096
1097
1098
1099
1100
1101
1102
1103
  
  	if (!task)
  		return -ESRCH;
  	make_it_fail = task->make_it_fail;
  	put_task_struct(task);
  
  	len = snprintf(buffer, sizeof(buffer), "%i
  ", make_it_fail);
0c28f287a   Akinobu Mita   procfs: use simpl...
1104
1105
  
  	return simple_read_from_buffer(buf, count, ppos, buffer, len);
f4f154fd9   Akinobu Mita   [PATCH] fault inj...
1106
1107
1108
1109
1110
1111
1112
1113
1114
1115
1116
1117
1118
1119
1120
1121
1122
1123
1124
1125
1126
1127
1128
1129
1130
1131
1132
1133
1134
  }
  
  static ssize_t proc_fault_inject_write(struct file * file,
  			const char __user * buf, size_t count, loff_t *ppos)
  {
  	struct task_struct *task;
  	char buffer[PROC_NUMBUF], *end;
  	int make_it_fail;
  
  	if (!capable(CAP_SYS_RESOURCE))
  		return -EPERM;
  	memset(buffer, 0, sizeof(buffer));
  	if (count > sizeof(buffer) - 1)
  		count = sizeof(buffer) - 1;
  	if (copy_from_user(buffer, buf, count))
  		return -EFAULT;
  	make_it_fail = simple_strtol(buffer, &end, 0);
  	if (*end == '
  ')
  		end++;
  	task = get_proc_task(file->f_dentry->d_inode);
  	if (!task)
  		return -ESRCH;
  	task->make_it_fail = make_it_fail;
  	put_task_struct(task);
  	if (end - buffer == 0)
  		return -EIO;
  	return end - buffer;
  }
00977a59b   Arjan van de Ven   [PATCH] mark stru...
1135
  static const struct file_operations proc_fault_inject_operations = {
f4f154fd9   Akinobu Mita   [PATCH] fault inj...
1136
1137
1138
1139
  	.read		= proc_fault_inject_read,
  	.write		= proc_fault_inject_write,
  };
  #endif
9745512ce   Arjan van de Ven   sched: latencytop...
1140

43ae34cb4   Ingo Molnar   sched: scheduler ...
1141
1142
1143
1144
1145
1146
1147
1148
1149
1150
1151
1152
1153
1154
1155
1156
1157
1158
1159
1160
1161
1162
1163
1164
1165
1166
1167
1168
1169
1170
1171
1172
1173
1174
1175
1176
1177
1178
1179
1180
1181
1182
1183
1184
1185
1186
1187
1188
1189
1190
1191
1192
1193
1194
1195
1196
1197
1198
  #ifdef CONFIG_SCHED_DEBUG
  /*
   * Print out various scheduling related per-task fields:
   */
  static int sched_show(struct seq_file *m, void *v)
  {
  	struct inode *inode = m->private;
  	struct task_struct *p;
  
  	WARN_ON(!inode);
  
  	p = get_proc_task(inode);
  	if (!p)
  		return -ESRCH;
  	proc_sched_show_task(p, m);
  
  	put_task_struct(p);
  
  	return 0;
  }
  
  static ssize_t
  sched_write(struct file *file, const char __user *buf,
  	    size_t count, loff_t *offset)
  {
  	struct inode *inode = file->f_path.dentry->d_inode;
  	struct task_struct *p;
  
  	WARN_ON(!inode);
  
  	p = get_proc_task(inode);
  	if (!p)
  		return -ESRCH;
  	proc_sched_set_task(p);
  
  	put_task_struct(p);
  
  	return count;
  }
  
  static int sched_open(struct inode *inode, struct file *filp)
  {
  	int ret;
  
  	ret = single_open(filp, sched_show, NULL);
  	if (!ret) {
  		struct seq_file *m = filp->private_data;
  
  		m->private = inode;
  	}
  	return ret;
  }
  
  static const struct file_operations proc_pid_sched_operations = {
  	.open		= sched_open,
  	.read		= seq_read,
  	.write		= sched_write,
  	.llseek		= seq_lseek,
5ea473a1d   Alexey Dobriyan   Fix leaks on /pro...
1199
  	.release	= single_release,
43ae34cb4   Ingo Molnar   sched: scheduler ...
1200
1201
1202
  };
  
  #endif
925d1c401   Matt Helsley   procfs task exe s...
1203
1204
1205
1206
1207
1208
1209
1210
1211
1212
1213
1214
1215
1216
1217
1218
1219
1220
1221
1222
1223
1224
1225
1226
1227
1228
1229
1230
1231
1232
1233
1234
1235
1236
1237
1238
1239
1240
1241
1242
1243
1244
1245
1246
1247
1248
1249
1250
1251
1252
1253
1254
1255
1256
1257
1258
1259
1260
1261
1262
1263
1264
1265
1266
1267
1268
1269
1270
1271
1272
1273
1274
1275
1276
  /*
   * We added or removed a vma mapping the executable. The vmas are only mapped
   * during exec and are not mapped with the mmap system call.
   * Callers must hold down_write() on the mm's mmap_sem for these
   */
  void added_exe_file_vma(struct mm_struct *mm)
  {
  	mm->num_exe_file_vmas++;
  }
  
  void removed_exe_file_vma(struct mm_struct *mm)
  {
  	mm->num_exe_file_vmas--;
  	if ((mm->num_exe_file_vmas == 0) && mm->exe_file){
  		fput(mm->exe_file);
  		mm->exe_file = NULL;
  	}
  
  }
  
  void set_mm_exe_file(struct mm_struct *mm, struct file *new_exe_file)
  {
  	if (new_exe_file)
  		get_file(new_exe_file);
  	if (mm->exe_file)
  		fput(mm->exe_file);
  	mm->exe_file = new_exe_file;
  	mm->num_exe_file_vmas = 0;
  }
  
  struct file *get_mm_exe_file(struct mm_struct *mm)
  {
  	struct file *exe_file;
  
  	/* We need mmap_sem to protect against races with removal of
  	 * VM_EXECUTABLE vmas */
  	down_read(&mm->mmap_sem);
  	exe_file = mm->exe_file;
  	if (exe_file)
  		get_file(exe_file);
  	up_read(&mm->mmap_sem);
  	return exe_file;
  }
  
  void dup_mm_exe_file(struct mm_struct *oldmm, struct mm_struct *newmm)
  {
  	/* It's safe to write the exe_file pointer without exe_file_lock because
  	 * this is called during fork when the task is not yet in /proc */
  	newmm->exe_file = get_mm_exe_file(oldmm);
  }
  
  static int proc_exe_link(struct inode *inode, struct path *exe_path)
  {
  	struct task_struct *task;
  	struct mm_struct *mm;
  	struct file *exe_file;
  
  	task = get_proc_task(inode);
  	if (!task)
  		return -ENOENT;
  	mm = get_task_mm(task);
  	put_task_struct(task);
  	if (!mm)
  		return -ENOENT;
  	exe_file = get_mm_exe_file(mm);
  	mmput(mm);
  	if (exe_file) {
  		*exe_path = exe_file->f_path;
  		path_get(&exe_file->f_path);
  		fput(exe_file);
  		return 0;
  	} else
  		return -ENOENT;
  }
008b150a3   Al Viro   [PATCH] Fix up sy...
1277
  static void *proc_pid_follow_link(struct dentry *dentry, struct nameidata *nd)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1278
1279
1280
1281
1282
  {
  	struct inode *inode = dentry->d_inode;
  	int error = -EACCES;
  
  	/* We don't need a base pointer in the /proc filesystem */
1d957f9bf   Jan Blunck   Introduce path_put()
1283
  	path_put(&nd->path);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1284

778c11447   Eric W. Biederman   [PATCH] proc: Use...
1285
1286
  	/* Are we allowed to snoop on the tasks file descriptors? */
  	if (!proc_fd_access_allowed(inode))
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1287
  		goto out;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1288

3dcd25f37   Jan Blunck   d_path: Make proc...
1289
  	error = PROC_I(inode)->op.proc_get_link(inode, &nd->path);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1290
1291
  	nd->last_type = LAST_BIND;
  out:
008b150a3   Al Viro   [PATCH] Fix up sy...
1292
  	return ERR_PTR(error);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1293
  }
3dcd25f37   Jan Blunck   d_path: Make proc...
1294
  static int do_proc_readlink(struct path *path, char __user *buffer, int buflen)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1295
  {
e12ba74d8   Mel Gorman   Group short-lived...
1296
  	char *tmp = (char*)__get_free_page(GFP_TEMPORARY);
3dcd25f37   Jan Blunck   d_path: Make proc...
1297
  	char *pathname;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1298
1299
1300
1301
  	int len;
  
  	if (!tmp)
  		return -ENOMEM;
0c28f287a   Akinobu Mita   procfs: use simpl...
1302

cf28b4863   Jan Blunck   d_path: Make d_pa...
1303
  	pathname = d_path(path, tmp, PAGE_SIZE);
3dcd25f37   Jan Blunck   d_path: Make proc...
1304
1305
  	len = PTR_ERR(pathname);
  	if (IS_ERR(pathname))
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1306
  		goto out;
3dcd25f37   Jan Blunck   d_path: Make proc...
1307
  	len = tmp + PAGE_SIZE - 1 - pathname;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1308
1309
1310
  
  	if (len > buflen)
  		len = buflen;
3dcd25f37   Jan Blunck   d_path: Make proc...
1311
  	if (copy_to_user(buffer, pathname, len))
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1312
1313
1314
1315
1316
1317
1318
1319
1320
1321
  		len = -EFAULT;
   out:
  	free_page((unsigned long)tmp);
  	return len;
  }
  
  static int proc_pid_readlink(struct dentry * dentry, char __user * buffer, int buflen)
  {
  	int error = -EACCES;
  	struct inode *inode = dentry->d_inode;
3dcd25f37   Jan Blunck   d_path: Make proc...
1322
  	struct path path;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1323

778c11447   Eric W. Biederman   [PATCH] proc: Use...
1324
1325
  	/* Are we allowed to snoop on the tasks file descriptors? */
  	if (!proc_fd_access_allowed(inode))
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1326
  		goto out;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1327

3dcd25f37   Jan Blunck   d_path: Make proc...
1328
  	error = PROC_I(inode)->op.proc_get_link(inode, &path);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1329
1330
  	if (error)
  		goto out;
3dcd25f37   Jan Blunck   d_path: Make proc...
1331
1332
  	error = do_proc_readlink(&path, buffer, buflen);
  	path_put(&path);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1333
  out:
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1334
1335
  	return error;
  }
c5ef1c42c   Arjan van de Ven   [PATCH] mark stru...
1336
  static const struct inode_operations proc_pid_link_inode_operations = {
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1337
  	.readlink	= proc_pid_readlink,
6d76fa58b   Linus Torvalds   Don't allow chmod...
1338
1339
  	.follow_link	= proc_pid_follow_link,
  	.setattr	= proc_setattr,
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1340
  };
28a6d6717   Eric W. Biederman   [PATCH] proc: reo...
1341
1342
1343
1344
  
  /* building an inode */
  
  static int task_dumpable(struct task_struct *task)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1345
  {
28a6d6717   Eric W. Biederman   [PATCH] proc: reo...
1346
1347
  	int dumpable = 0;
  	struct mm_struct *mm;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1348

28a6d6717   Eric W. Biederman   [PATCH] proc: reo...
1349
1350
1351
  	task_lock(task);
  	mm = task->mm;
  	if (mm)
6c5d52382   Kawai, Hidehiro   coredump masking:...
1352
  		dumpable = get_dumpable(mm);
28a6d6717   Eric W. Biederman   [PATCH] proc: reo...
1353
1354
1355
1356
1357
  	task_unlock(task);
  	if(dumpable == 1)
  		return 1;
  	return 0;
  }
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1358

1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1359

61a287840   Eric W. Biederman   [PATCH] proc: Rem...
1360
  static struct inode *proc_pid_make_inode(struct super_block * sb, struct task_struct *task)
28a6d6717   Eric W. Biederman   [PATCH] proc: reo...
1361
1362
1363
  {
  	struct inode * inode;
  	struct proc_inode *ei;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1364

28a6d6717   Eric W. Biederman   [PATCH] proc: reo...
1365
  	/* We need a new inode */
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1366

28a6d6717   Eric W. Biederman   [PATCH] proc: reo...
1367
1368
1369
1370
1371
1372
1373
  	inode = new_inode(sb);
  	if (!inode)
  		goto out;
  
  	/* Common stuff */
  	ei = PROC_I(inode);
  	inode->i_mtime = inode->i_atime = inode->i_ctime = CURRENT_TIME;
28a6d6717   Eric W. Biederman   [PATCH] proc: reo...
1374
1375
1376
1377
1378
  	inode->i_op = &proc_def_inode_operations;
  
  	/*
  	 * grab the reference to task.
  	 */
1a657f78d   Oleg Nesterov   [PATCH] introduce...
1379
  	ei->pid = get_task_pid(task, PIDTYPE_PID);
28a6d6717   Eric W. Biederman   [PATCH] proc: reo...
1380
1381
1382
1383
1384
1385
1386
1387
  	if (!ei->pid)
  		goto out_unlock;
  
  	inode->i_uid = 0;
  	inode->i_gid = 0;
  	if (task_dumpable(task)) {
  		inode->i_uid = task->euid;
  		inode->i_gid = task->egid;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1388
  	}
28a6d6717   Eric W. Biederman   [PATCH] proc: reo...
1389
  	security_task_to_inode(task, inode);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1390
  out:
28a6d6717   Eric W. Biederman   [PATCH] proc: reo...
1391
1392
1393
1394
1395
  	return inode;
  
  out_unlock:
  	iput(inode);
  	return NULL;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1396
  }
28a6d6717   Eric W. Biederman   [PATCH] proc: reo...
1397
  static int pid_getattr(struct vfsmount *mnt, struct dentry *dentry, struct kstat *stat)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1398
  {
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1399
  	struct inode *inode = dentry->d_inode;
28a6d6717   Eric W. Biederman   [PATCH] proc: reo...
1400
1401
  	struct task_struct *task;
  	generic_fillattr(inode, stat);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1402

28a6d6717   Eric W. Biederman   [PATCH] proc: reo...
1403
1404
1405
1406
1407
1408
1409
1410
1411
  	rcu_read_lock();
  	stat->uid = 0;
  	stat->gid = 0;
  	task = pid_task(proc_pid(inode), PIDTYPE_PID);
  	if (task) {
  		if ((inode->i_mode == (S_IFDIR|S_IRUGO|S_IXUGO)) ||
  		    task_dumpable(task)) {
  			stat->uid = task->euid;
  			stat->gid = task->egid;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1412
1413
  		}
  	}
28a6d6717   Eric W. Biederman   [PATCH] proc: reo...
1414
  	rcu_read_unlock();
d6e711448   Alan Cox   [PATCH] setuid co...
1415
  	return 0;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1416
  }
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1417
1418
1419
1420
1421
1422
1423
1424
1425
  /* dentry stuff */
  
  /*
   *	Exceptional case: normally we are not allowed to unhash a busy
   * directory. In this case, however, we can do it - no aliasing problems
   * due to the way we treat inodes.
   *
   * Rewrite the inode's ownerships here because the owning task may have
   * performed a setuid(), etc.
99f895518   Eric W. Biederman   [PATCH] proc: don...
1426
1427
1428
1429
1430
1431
1432
   *
   * Before the /proc/pid/status file was created the only way to read
   * the effective uid of a /process was to stat /proc/pid.  Reading
   * /proc/pid/status is slow enough that procps and other packages
   * kept stating /proc/pid.  To keep the rules in /proc simple I have
   * made this apply to all per process world readable and executable
   * directories.
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1433
1434
1435
1436
   */
  static int pid_revalidate(struct dentry *dentry, struct nameidata *nd)
  {
  	struct inode *inode = dentry->d_inode;
99f895518   Eric W. Biederman   [PATCH] proc: don...
1437
1438
1439
1440
  	struct task_struct *task = get_proc_task(inode);
  	if (task) {
  		if ((inode->i_mode == (S_IFDIR|S_IRUGO|S_IXUGO)) ||
  		    task_dumpable(task)) {
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1441
1442
1443
1444
1445
1446
  			inode->i_uid = task->euid;
  			inode->i_gid = task->egid;
  		} else {
  			inode->i_uid = 0;
  			inode->i_gid = 0;
  		}
9ee8ab9fb   Linus Torvalds   Relax /proc fix a...
1447
  		inode->i_mode &= ~(S_ISUID | S_ISGID);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1448
  		security_task_to_inode(task, inode);
99f895518   Eric W. Biederman   [PATCH] proc: don...
1449
  		put_task_struct(task);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1450
1451
1452
1453
1454
  		return 1;
  	}
  	d_drop(dentry);
  	return 0;
  }
28a6d6717   Eric W. Biederman   [PATCH] proc: reo...
1455
  static int pid_delete_dentry(struct dentry * dentry)
99f895518   Eric W. Biederman   [PATCH] proc: don...
1456
  {
28a6d6717   Eric W. Biederman   [PATCH] proc: reo...
1457
1458
1459
1460
1461
1462
1463
1464
1465
1466
1467
1468
1469
1470
  	/* Is the task we represent dead?
  	 * If so, then don't put the dentry on the lru list,
  	 * kill it immediately.
  	 */
  	return !proc_pid(dentry->d_inode)->tasks[PIDTYPE_PID].first;
  }
  
  static struct dentry_operations pid_dentry_operations =
  {
  	.d_revalidate	= pid_revalidate,
  	.d_delete	= pid_delete_dentry,
  };
  
  /* Lookups */
c5141e6d6   Eric Dumazet   procfs: reorder s...
1471
1472
  typedef struct dentry *instantiate_t(struct inode *, struct dentry *,
  				struct task_struct *, const void *);
61a287840   Eric W. Biederman   [PATCH] proc: Rem...
1473

1c0d04c9e   Eric W. Biederman   [PATCH] proc: com...
1474
1475
1476
1477
1478
1479
1480
1481
1482
1483
1484
1485
  /*
   * Fill a directory entry.
   *
   * If possible create the dcache entry and derive our inode number and
   * file type from dcache entry.
   *
   * Since all of the proc inode numbers are dynamically generated, the inode
   * numbers do not exist until the inode is cache.  This means creating the
   * the dcache entry in readdir is necessary to keep the inode numbers
   * reported by readdir in sync with the inode numbers reported
   * by stat.
   */
61a287840   Eric W. Biederman   [PATCH] proc: Rem...
1486
1487
  static int proc_fill_cache(struct file *filp, void *dirent, filldir_t filldir,
  	char *name, int len,
c5141e6d6   Eric Dumazet   procfs: reorder s...
1488
  	instantiate_t instantiate, struct task_struct *task, const void *ptr)
61a287840   Eric W. Biederman   [PATCH] proc: Rem...
1489
  {
2fddfeefe   Josef "Jeff" Sipek   [PATCH] proc: cha...
1490
  	struct dentry *child, *dir = filp->f_path.dentry;
61a287840   Eric W. Biederman   [PATCH] proc: Rem...
1491
1492
1493
1494
1495
1496
1497
1498
1499
1500
1501
1502
1503
1504
1505
1506
1507
1508
1509
1510
1511
1512
1513
1514
1515
1516
1517
1518
1519
1520
1521
1522
1523
1524
1525
1526
  	struct inode *inode;
  	struct qstr qname;
  	ino_t ino = 0;
  	unsigned type = DT_UNKNOWN;
  
  	qname.name = name;
  	qname.len  = len;
  	qname.hash = full_name_hash(name, len);
  
  	child = d_lookup(dir, &qname);
  	if (!child) {
  		struct dentry *new;
  		new = d_alloc(dir, &qname);
  		if (new) {
  			child = instantiate(dir->d_inode, new, task, ptr);
  			if (child)
  				dput(new);
  			else
  				child = new;
  		}
  	}
  	if (!child || IS_ERR(child) || !child->d_inode)
  		goto end_instantiate;
  	inode = child->d_inode;
  	if (inode) {
  		ino = inode->i_ino;
  		type = inode->i_mode >> 12;
  	}
  	dput(child);
  end_instantiate:
  	if (!ino)
  		ino = find_inode_number(dir, &qname);
  	if (!ino)
  		ino = 1;
  	return filldir(dirent, name, len, filp->f_pos, ino, type);
  }
28a6d6717   Eric W. Biederman   [PATCH] proc: reo...
1527
1528
1529
1530
1531
1532
1533
1534
1535
1536
1537
1538
1539
1540
1541
1542
1543
1544
1545
1546
1547
  static unsigned name_to_int(struct dentry *dentry)
  {
  	const char *name = dentry->d_name.name;
  	int len = dentry->d_name.len;
  	unsigned n = 0;
  
  	if (len > 1 && *name == '0')
  		goto out;
  	while (len-- > 0) {
  		unsigned c = *name++ - '0';
  		if (c > 9)
  			goto out;
  		if (n >= (~0U-9)/10)
  			goto out;
  		n *= 10;
  		n += c;
  	}
  	return n;
  out:
  	return ~0U;
  }
279327429   Miklos Szeredi   add file position...
1548
  #define PROC_FDINFO_MAX 64
3dcd25f37   Jan Blunck   d_path: Make proc...
1549
  static int proc_fd_info(struct inode *inode, struct path *path, char *info)
28a6d6717   Eric W. Biederman   [PATCH] proc: reo...
1550
1551
1552
1553
1554
  {
  	struct task_struct *task = get_proc_task(inode);
  	struct files_struct *files = NULL;
  	struct file *file;
  	int fd = proc_fd(inode);
99f895518   Eric W. Biederman   [PATCH] proc: don...
1555

99f895518   Eric W. Biederman   [PATCH] proc: don...
1556
  	if (task) {
28a6d6717   Eric W. Biederman   [PATCH] proc: reo...
1557
1558
1559
1560
1561
1562
1563
1564
1565
1566
1567
  		files = get_files_struct(task);
  		put_task_struct(task);
  	}
  	if (files) {
  		/*
  		 * We are not taking a ref to the file structure, so we must
  		 * hold ->file_lock.
  		 */
  		spin_lock(&files->file_lock);
  		file = fcheck_files(files, fd);
  		if (file) {
3dcd25f37   Jan Blunck   d_path: Make proc...
1568
1569
1570
1571
  			if (path) {
  				*path = file->f_path;
  				path_get(&file->f_path);
  			}
279327429   Miklos Szeredi   add file position...
1572
1573
1574
1575
1576
1577
1578
1579
  			if (info)
  				snprintf(info, PROC_FDINFO_MAX,
  					 "pos:\t%lli
  "
  					 "flags:\t0%o
  ",
  					 (long long) file->f_pos,
  					 file->f_flags);
28a6d6717   Eric W. Biederman   [PATCH] proc: reo...
1580
1581
1582
  			spin_unlock(&files->file_lock);
  			put_files_struct(files);
  			return 0;
99f895518   Eric W. Biederman   [PATCH] proc: don...
1583
  		}
28a6d6717   Eric W. Biederman   [PATCH] proc: reo...
1584
1585
  		spin_unlock(&files->file_lock);
  		put_files_struct(files);
99f895518   Eric W. Biederman   [PATCH] proc: don...
1586
  	}
28a6d6717   Eric W. Biederman   [PATCH] proc: reo...
1587
  	return -ENOENT;
99f895518   Eric W. Biederman   [PATCH] proc: don...
1588
  }
3dcd25f37   Jan Blunck   d_path: Make proc...
1589
  static int proc_fd_link(struct inode *inode, struct path *path)
279327429   Miklos Szeredi   add file position...
1590
  {
3dcd25f37   Jan Blunck   d_path: Make proc...
1591
  	return proc_fd_info(inode, path, NULL);
279327429   Miklos Szeredi   add file position...
1592
  }
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1593
1594
1595
  static int tid_fd_revalidate(struct dentry *dentry, struct nameidata *nd)
  {
  	struct inode *inode = dentry->d_inode;
99f895518   Eric W. Biederman   [PATCH] proc: don...
1596
  	struct task_struct *task = get_proc_task(inode);
aed7a6c47   Eric W. Biederman   [PATCH] proc: Rep...
1597
  	int fd = proc_fd(inode);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1598
  	struct files_struct *files;
99f895518   Eric W. Biederman   [PATCH] proc: don...
1599
1600
1601
1602
1603
1604
1605
1606
1607
1608
1609
1610
1611
1612
  	if (task) {
  		files = get_files_struct(task);
  		if (files) {
  			rcu_read_lock();
  			if (fcheck_files(files, fd)) {
  				rcu_read_unlock();
  				put_files_struct(files);
  				if (task_dumpable(task)) {
  					inode->i_uid = task->euid;
  					inode->i_gid = task->egid;
  				} else {
  					inode->i_uid = 0;
  					inode->i_gid = 0;
  				}
9ee8ab9fb   Linus Torvalds   Relax /proc fix a...
1613
  				inode->i_mode &= ~(S_ISUID | S_ISGID);
99f895518   Eric W. Biederman   [PATCH] proc: don...
1614
1615
1616
1617
  				security_task_to_inode(task, inode);
  				put_task_struct(task);
  				return 1;
  			}
b835996f6   Dipankar Sarma   [PATCH] files: lo...
1618
  			rcu_read_unlock();
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1619
  			put_files_struct(files);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1620
  		}
99f895518   Eric W. Biederman   [PATCH] proc: don...
1621
  		put_task_struct(task);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1622
1623
1624
1625
  	}
  	d_drop(dentry);
  	return 0;
  }
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1626
1627
1628
1629
1630
  static struct dentry_operations tid_fd_dentry_operations =
  {
  	.d_revalidate	= tid_fd_revalidate,
  	.d_delete	= pid_delete_dentry,
  };
444ceed8d   Eric W. Biederman   [PATCH] proc: Fac...
1631
  static struct dentry *proc_fd_instantiate(struct inode *dir,
c5141e6d6   Eric Dumazet   procfs: reorder s...
1632
  	struct dentry *dentry, struct task_struct *task, const void *ptr)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1633
  {
c5141e6d6   Eric Dumazet   procfs: reorder s...
1634
  	unsigned fd = *(const unsigned *)ptr;
444ceed8d   Eric W. Biederman   [PATCH] proc: Fac...
1635
1636
1637
1638
1639
  	struct file *file;
  	struct files_struct *files;
   	struct inode *inode;
   	struct proc_inode *ei;
  	struct dentry *error = ERR_PTR(-ENOENT);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1640

61a287840   Eric W. Biederman   [PATCH] proc: Rem...
1641
  	inode = proc_pid_make_inode(dir->i_sb, task);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1642
1643
1644
  	if (!inode)
  		goto out;
  	ei = PROC_I(inode);
aed7a6c47   Eric W. Biederman   [PATCH] proc: Rep...
1645
  	ei->fd = fd;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1646
1647
  	files = get_files_struct(task);
  	if (!files)
444ceed8d   Eric W. Biederman   [PATCH] proc: Fac...
1648
  		goto out_iput;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1649
  	inode->i_mode = S_IFLNK;
ca99c1da0   Dipankar Sarma   [PATCH] Fix file ...
1650
1651
1652
1653
1654
1655
  
  	/*
  	 * We are not taking a ref to the file structure, so we must
  	 * hold ->file_lock.
  	 */
  	spin_lock(&files->file_lock);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1656
1657
  	file = fcheck_files(files, fd);
  	if (!file)
444ceed8d   Eric W. Biederman   [PATCH] proc: Fac...
1658
  		goto out_unlock;
aeb5d7270   Al Viro   [PATCH] introduce...
1659
  	if (file->f_mode & FMODE_READ)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1660
  		inode->i_mode |= S_IRUSR | S_IXUSR;
aeb5d7270   Al Viro   [PATCH] introduce...
1661
  	if (file->f_mode & FMODE_WRITE)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1662
  		inode->i_mode |= S_IWUSR | S_IXUSR;
ca99c1da0   Dipankar Sarma   [PATCH] Fix file ...
1663
  	spin_unlock(&files->file_lock);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1664
  	put_files_struct(files);
444ceed8d   Eric W. Biederman   [PATCH] proc: Fac...
1665

1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1666
1667
1668
1669
1670
  	inode->i_op = &proc_pid_link_inode_operations;
  	inode->i_size = 64;
  	ei->op.proc_get_link = proc_fd_link;
  	dentry->d_op = &tid_fd_dentry_operations;
  	d_add(dentry, inode);
cd6a3ce9e   Eric W. Biederman   [PATCH] proc: Clo...
1671
1672
  	/* Close the race of the process dying before we return the dentry */
  	if (tid_fd_revalidate(dentry, NULL))
444ceed8d   Eric W. Biederman   [PATCH] proc: Fac...
1673
  		error = NULL;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1674

444ceed8d   Eric W. Biederman   [PATCH] proc: Fac...
1675
1676
1677
   out:
  	return error;
  out_unlock:
ca99c1da0   Dipankar Sarma   [PATCH] Fix file ...
1678
  	spin_unlock(&files->file_lock);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1679
  	put_files_struct(files);
444ceed8d   Eric W. Biederman   [PATCH] proc: Fac...
1680
  out_iput:
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1681
  	iput(inode);
cd6a3ce9e   Eric W. Biederman   [PATCH] proc: Clo...
1682
  	goto out;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1683
  }
279327429   Miklos Szeredi   add file position...
1684
1685
1686
  static struct dentry *proc_lookupfd_common(struct inode *dir,
  					   struct dentry *dentry,
  					   instantiate_t instantiate)
444ceed8d   Eric W. Biederman   [PATCH] proc: Fac...
1687
1688
1689
1690
1691
1692
1693
1694
1695
  {
  	struct task_struct *task = get_proc_task(dir);
  	unsigned fd = name_to_int(dentry);
  	struct dentry *result = ERR_PTR(-ENOENT);
  
  	if (!task)
  		goto out_no_task;
  	if (fd == ~0U)
  		goto out;
279327429   Miklos Szeredi   add file position...
1696
  	result = instantiate(dir, dentry, task, &fd);
444ceed8d   Eric W. Biederman   [PATCH] proc: Fac...
1697
1698
1699
1700
1701
  out:
  	put_task_struct(task);
  out_no_task:
  	return result;
  }
279327429   Miklos Szeredi   add file position...
1702
1703
  static int proc_readfd_common(struct file * filp, void * dirent,
  			      filldir_t filldir, instantiate_t instantiate)
28a6d6717   Eric W. Biederman   [PATCH] proc: reo...
1704
  {
2fddfeefe   Josef "Jeff" Sipek   [PATCH] proc: cha...
1705
  	struct dentry *dentry = filp->f_path.dentry;
28a6d6717   Eric W. Biederman   [PATCH] proc: reo...
1706
1707
  	struct inode *inode = dentry->d_inode;
  	struct task_struct *p = get_proc_task(inode);
457c25107   Pavel Emelyanov   Remove unused var...
1708
  	unsigned int fd, ino;
28a6d6717   Eric W. Biederman   [PATCH] proc: reo...
1709
  	int retval;
28a6d6717   Eric W. Biederman   [PATCH] proc: reo...
1710
  	struct files_struct * files;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1711

28a6d6717   Eric W. Biederman   [PATCH] proc: reo...
1712
1713
1714
1715
  	retval = -ENOENT;
  	if (!p)
  		goto out_no_task;
  	retval = 0;
28a6d6717   Eric W. Biederman   [PATCH] proc: reo...
1716
1717
1718
1719
1720
1721
1722
1723
1724
1725
1726
1727
1728
1729
1730
1731
1732
  
  	fd = filp->f_pos;
  	switch (fd) {
  		case 0:
  			if (filldir(dirent, ".", 1, 0, inode->i_ino, DT_DIR) < 0)
  				goto out;
  			filp->f_pos++;
  		case 1:
  			ino = parent_ino(dentry);
  			if (filldir(dirent, "..", 2, 1, ino, DT_DIR) < 0)
  				goto out;
  			filp->f_pos++;
  		default:
  			files = get_files_struct(p);
  			if (!files)
  				goto out;
  			rcu_read_lock();
28a6d6717   Eric W. Biederman   [PATCH] proc: reo...
1733
  			for (fd = filp->f_pos-2;
9b4f526cd   Al Viro   [PATCH] proc_read...
1734
  			     fd < files_fdtable(files)->max_fds;
28a6d6717   Eric W. Biederman   [PATCH] proc: reo...
1735
  			     fd++, filp->f_pos++) {
279327429   Miklos Szeredi   add file position...
1736
1737
  				char name[PROC_NUMBUF];
  				int len;
28a6d6717   Eric W. Biederman   [PATCH] proc: reo...
1738
1739
1740
1741
  
  				if (!fcheck_files(files, fd))
  					continue;
  				rcu_read_unlock();
279327429   Miklos Szeredi   add file position...
1742
1743
1744
1745
  				len = snprintf(name, sizeof(name), "%d", fd);
  				if (proc_fill_cache(filp, dirent, filldir,
  						    name, len, instantiate,
  						    p, &fd) < 0) {
28a6d6717   Eric W. Biederman   [PATCH] proc: reo...
1746
1747
1748
1749
1750
1751
1752
1753
1754
1755
1756
1757
1758
  					rcu_read_lock();
  					break;
  				}
  				rcu_read_lock();
  			}
  			rcu_read_unlock();
  			put_files_struct(files);
  	}
  out:
  	put_task_struct(p);
  out_no_task:
  	return retval;
  }
279327429   Miklos Szeredi   add file position...
1759
1760
1761
1762
1763
1764
1765
1766
1767
1768
1769
1770
1771
1772
1773
  static struct dentry *proc_lookupfd(struct inode *dir, struct dentry *dentry,
  				    struct nameidata *nd)
  {
  	return proc_lookupfd_common(dir, dentry, proc_fd_instantiate);
  }
  
  static int proc_readfd(struct file *filp, void *dirent, filldir_t filldir)
  {
  	return proc_readfd_common(filp, dirent, filldir, proc_fd_instantiate);
  }
  
  static ssize_t proc_fdinfo_read(struct file *file, char __user *buf,
  				      size_t len, loff_t *ppos)
  {
  	char tmp[PROC_FDINFO_MAX];
3dcd25f37   Jan Blunck   d_path: Make proc...
1774
  	int err = proc_fd_info(file->f_path.dentry->d_inode, NULL, tmp);
279327429   Miklos Szeredi   add file position...
1775
1776
1777
1778
1779
1780
1781
1782
1783
  	if (!err)
  		err = simple_read_from_buffer(buf, len, ppos, tmp, strlen(tmp));
  	return err;
  }
  
  static const struct file_operations proc_fdinfo_file_operations = {
  	.open		= nonseekable_open,
  	.read		= proc_fdinfo_read,
  };
00977a59b   Arjan van de Ven   [PATCH] mark stru...
1784
  static const struct file_operations proc_fd_operations = {
28a6d6717   Eric W. Biederman   [PATCH] proc: reo...
1785
1786
  	.read		= generic_read_dir,
  	.readdir	= proc_readfd,
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1787
1788
1789
  };
  
  /*
8948e11f4   Alexey Dobriyan   Allow access to /...
1790
1791
1792
   * /proc/pid/fd needs a special permission handler so that a process can still
   * access /proc/self/fd after it has executed a setuid().
   */
e6305c43e   Al Viro   [PATCH] sanitize ...
1793
  static int proc_fd_permission(struct inode *inode, int mask)
8948e11f4   Alexey Dobriyan   Allow access to /...
1794
1795
1796
1797
1798
1799
1800
1801
1802
1803
1804
1805
  {
  	int rv;
  
  	rv = generic_permission(inode, mask, NULL);
  	if (rv == 0)
  		return 0;
  	if (task_pid(current) == proc_pid(inode))
  		rv = 0;
  	return rv;
  }
  
  /*
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1806
1807
   * proc directories can do almost nothing..
   */
c5ef1c42c   Arjan van de Ven   [PATCH] mark stru...
1808
  static const struct inode_operations proc_fd_inode_operations = {
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1809
  	.lookup		= proc_lookupfd,
8948e11f4   Alexey Dobriyan   Allow access to /...
1810
  	.permission	= proc_fd_permission,
6d76fa58b   Linus Torvalds   Don't allow chmod...
1811
  	.setattr	= proc_setattr,
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1812
  };
279327429   Miklos Szeredi   add file position...
1813
1814
1815
1816
1817
1818
1819
1820
1821
1822
1823
1824
1825
1826
1827
1828
1829
1830
1831
1832
1833
1834
1835
1836
1837
1838
1839
1840
1841
1842
1843
1844
1845
1846
1847
1848
1849
1850
1851
1852
1853
1854
1855
1856
1857
1858
1859
1860
1861
1862
  static struct dentry *proc_fdinfo_instantiate(struct inode *dir,
  	struct dentry *dentry, struct task_struct *task, const void *ptr)
  {
  	unsigned fd = *(unsigned *)ptr;
   	struct inode *inode;
   	struct proc_inode *ei;
  	struct dentry *error = ERR_PTR(-ENOENT);
  
  	inode = proc_pid_make_inode(dir->i_sb, task);
  	if (!inode)
  		goto out;
  	ei = PROC_I(inode);
  	ei->fd = fd;
  	inode->i_mode = S_IFREG | S_IRUSR;
  	inode->i_fop = &proc_fdinfo_file_operations;
  	dentry->d_op = &tid_fd_dentry_operations;
  	d_add(dentry, inode);
  	/* Close the race of the process dying before we return the dentry */
  	if (tid_fd_revalidate(dentry, NULL))
  		error = NULL;
  
   out:
  	return error;
  }
  
  static struct dentry *proc_lookupfdinfo(struct inode *dir,
  					struct dentry *dentry,
  					struct nameidata *nd)
  {
  	return proc_lookupfd_common(dir, dentry, proc_fdinfo_instantiate);
  }
  
  static int proc_readfdinfo(struct file *filp, void *dirent, filldir_t filldir)
  {
  	return proc_readfd_common(filp, dirent, filldir,
  				  proc_fdinfo_instantiate);
  }
  
  static const struct file_operations proc_fdinfo_operations = {
  	.read		= generic_read_dir,
  	.readdir	= proc_readfdinfo,
  };
  
  /*
   * proc directories can do almost nothing..
   */
  static const struct inode_operations proc_fdinfo_inode_operations = {
  	.lookup		= proc_lookupfdinfo,
  	.setattr	= proc_setattr,
  };
444ceed8d   Eric W. Biederman   [PATCH] proc: Fac...
1863
  static struct dentry *proc_pident_instantiate(struct inode *dir,
c5141e6d6   Eric Dumazet   procfs: reorder s...
1864
  	struct dentry *dentry, struct task_struct *task, const void *ptr)
444ceed8d   Eric W. Biederman   [PATCH] proc: Fac...
1865
  {
c5141e6d6   Eric Dumazet   procfs: reorder s...
1866
  	const struct pid_entry *p = ptr;
444ceed8d   Eric W. Biederman   [PATCH] proc: Fac...
1867
1868
1869
  	struct inode *inode;
  	struct proc_inode *ei;
  	struct dentry *error = ERR_PTR(-EINVAL);
61a287840   Eric W. Biederman   [PATCH] proc: Rem...
1870
  	inode = proc_pid_make_inode(dir->i_sb, task);
444ceed8d   Eric W. Biederman   [PATCH] proc: Fac...
1871
1872
1873
1874
1875
1876
1877
1878
1879
1880
1881
1882
1883
1884
1885
1886
1887
1888
1889
1890
  	if (!inode)
  		goto out;
  
  	ei = PROC_I(inode);
  	inode->i_mode = p->mode;
  	if (S_ISDIR(inode->i_mode))
  		inode->i_nlink = 2;	/* Use getattr to fix if necessary */
  	if (p->iop)
  		inode->i_op = p->iop;
  	if (p->fop)
  		inode->i_fop = p->fop;
  	ei->op = p->op;
  	dentry->d_op = &pid_dentry_operations;
  	d_add(dentry, inode);
  	/* Close the race of the process dying before we return the dentry */
  	if (pid_revalidate(dentry, NULL))
  		error = NULL;
  out:
  	return error;
  }
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1891
1892
  static struct dentry *proc_pident_lookup(struct inode *dir, 
  					 struct dentry *dentry,
c5141e6d6   Eric Dumazet   procfs: reorder s...
1893
  					 const struct pid_entry *ents,
7bcd6b0ef   Eric W. Biederman   [PATCH] proc: rem...
1894
  					 unsigned int nents)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1895
1896
  {
  	struct inode *inode;
cd6a3ce9e   Eric W. Biederman   [PATCH] proc: Clo...
1897
  	struct dentry *error;
99f895518   Eric W. Biederman   [PATCH] proc: don...
1898
  	struct task_struct *task = get_proc_task(dir);
c5141e6d6   Eric Dumazet   procfs: reorder s...
1899
  	const struct pid_entry *p, *last;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1900

cd6a3ce9e   Eric W. Biederman   [PATCH] proc: Clo...
1901
  	error = ERR_PTR(-ENOENT);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1902
  	inode = NULL;
99f895518   Eric W. Biederman   [PATCH] proc: don...
1903
1904
  	if (!task)
  		goto out_no_task;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1905

20cdc894c   Eric W. Biederman   [PATCH] proc: mod...
1906
1907
1908
1909
  	/*
  	 * Yes, it does not scale. And it should not. Don't add
  	 * new entries into /proc/<tgid>/ without very good reasons.
  	 */
7bcd6b0ef   Eric W. Biederman   [PATCH] proc: rem...
1910
1911
  	last = &ents[nents - 1];
  	for (p = ents; p <= last; p++) {
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1912
1913
1914
1915
1916
  		if (p->len != dentry->d_name.len)
  			continue;
  		if (!memcmp(dentry->d_name.name, p->name, p->len))
  			break;
  	}
7bcd6b0ef   Eric W. Biederman   [PATCH] proc: rem...
1917
  	if (p > last)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1918
  		goto out;
444ceed8d   Eric W. Biederman   [PATCH] proc: Fac...
1919
  	error = proc_pident_instantiate(dir, dentry, task, p);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1920
  out:
99f895518   Eric W. Biederman   [PATCH] proc: don...
1921
1922
  	put_task_struct(task);
  out_no_task:
cd6a3ce9e   Eric W. Biederman   [PATCH] proc: Clo...
1923
  	return error;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1924
  }
c5141e6d6   Eric Dumazet   procfs: reorder s...
1925
1926
  static int proc_pident_fill_cache(struct file *filp, void *dirent,
  	filldir_t filldir, struct task_struct *task, const struct pid_entry *p)
61a287840   Eric W. Biederman   [PATCH] proc: Rem...
1927
1928
1929
1930
  {
  	return proc_fill_cache(filp, dirent, filldir, p->name, p->len,
  				proc_pident_instantiate, task, p);
  }
28a6d6717   Eric W. Biederman   [PATCH] proc: reo...
1931
1932
  static int proc_pident_readdir(struct file *filp,
  		void *dirent, filldir_t filldir,
c5141e6d6   Eric Dumazet   procfs: reorder s...
1933
  		const struct pid_entry *ents, unsigned int nents)
28a6d6717   Eric W. Biederman   [PATCH] proc: reo...
1934
1935
  {
  	int i;
2fddfeefe   Josef "Jeff" Sipek   [PATCH] proc: cha...
1936
  	struct dentry *dentry = filp->f_path.dentry;
28a6d6717   Eric W. Biederman   [PATCH] proc: reo...
1937
1938
  	struct inode *inode = dentry->d_inode;
  	struct task_struct *task = get_proc_task(inode);
c5141e6d6   Eric Dumazet   procfs: reorder s...
1939
  	const struct pid_entry *p, *last;
28a6d6717   Eric W. Biederman   [PATCH] proc: reo...
1940
1941
1942
1943
1944
  	ino_t ino;
  	int ret;
  
  	ret = -ENOENT;
  	if (!task)
61a287840   Eric W. Biederman   [PATCH] proc: Rem...
1945
  		goto out_no_task;
28a6d6717   Eric W. Biederman   [PATCH] proc: reo...
1946
1947
  
  	ret = 0;
28a6d6717   Eric W. Biederman   [PATCH] proc: reo...
1948
1949
1950
1951
1952
1953
1954
1955
1956
1957
1958
1959
1960
1961
1962
1963
1964
1965
1966
1967
1968
1969
1970
  	i = filp->f_pos;
  	switch (i) {
  	case 0:
  		ino = inode->i_ino;
  		if (filldir(dirent, ".", 1, i, ino, DT_DIR) < 0)
  			goto out;
  		i++;
  		filp->f_pos++;
  		/* fall through */
  	case 1:
  		ino = parent_ino(dentry);
  		if (filldir(dirent, "..", 2, i, ino, DT_DIR) < 0)
  			goto out;
  		i++;
  		filp->f_pos++;
  		/* fall through */
  	default:
  		i -= 2;
  		if (i >= nents) {
  			ret = 1;
  			goto out;
  		}
  		p = ents + i;
7bcd6b0ef   Eric W. Biederman   [PATCH] proc: rem...
1971
1972
  		last = &ents[nents - 1];
  		while (p <= last) {
61a287840   Eric W. Biederman   [PATCH] proc: Rem...
1973
  			if (proc_pident_fill_cache(filp, dirent, filldir, task, p) < 0)
28a6d6717   Eric W. Biederman   [PATCH] proc: reo...
1974
1975
1976
1977
1978
1979
1980
1981
  				goto out;
  			filp->f_pos++;
  			p++;
  		}
  	}
  
  	ret = 1;
  out:
61a287840   Eric W. Biederman   [PATCH] proc: Rem...
1982
1983
  	put_task_struct(task);
  out_no_task:
28a6d6717   Eric W. Biederman   [PATCH] proc: reo...
1984
  	return ret;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1985
  }
28a6d6717   Eric W. Biederman   [PATCH] proc: reo...
1986
1987
1988
1989
  #ifdef CONFIG_SECURITY
  static ssize_t proc_pid_attr_read(struct file * file, char __user * buf,
  				  size_t count, loff_t *ppos)
  {
2fddfeefe   Josef "Jeff" Sipek   [PATCH] proc: cha...
1990
  	struct inode * inode = file->f_path.dentry->d_inode;
04ff97086   Al Viro   [PATCH] sanitize ...
1991
  	char *p = NULL;
28a6d6717   Eric W. Biederman   [PATCH] proc: reo...
1992
1993
  	ssize_t length;
  	struct task_struct *task = get_proc_task(inode);
28a6d6717   Eric W. Biederman   [PATCH] proc: reo...
1994
  	if (!task)
04ff97086   Al Viro   [PATCH] sanitize ...
1995
  		return -ESRCH;
28a6d6717   Eric W. Biederman   [PATCH] proc: reo...
1996
1997
  
  	length = security_getprocattr(task,
2fddfeefe   Josef "Jeff" Sipek   [PATCH] proc: cha...
1998
  				      (char*)file->f_path.dentry->d_name.name,
04ff97086   Al Viro   [PATCH] sanitize ...
1999
  				      &p);
28a6d6717   Eric W. Biederman   [PATCH] proc: reo...
2000
  	put_task_struct(task);
04ff97086   Al Viro   [PATCH] sanitize ...
2001
2002
2003
  	if (length > 0)
  		length = simple_read_from_buffer(buf, count, ppos, p, length);
  	kfree(p);
28a6d6717   Eric W. Biederman   [PATCH] proc: reo...
2004
  	return length;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2005
  }
28a6d6717   Eric W. Biederman   [PATCH] proc: reo...
2006
2007
2008
  static ssize_t proc_pid_attr_write(struct file * file, const char __user * buf,
  				   size_t count, loff_t *ppos)
  {
2fddfeefe   Josef "Jeff" Sipek   [PATCH] proc: cha...
2009
  	struct inode * inode = file->f_path.dentry->d_inode;
28a6d6717   Eric W. Biederman   [PATCH] proc: reo...
2010
2011
2012
2013
2014
2015
2016
2017
2018
2019
2020
2021
2022
2023
2024
2025
  	char *page;
  	ssize_t length;
  	struct task_struct *task = get_proc_task(inode);
  
  	length = -ESRCH;
  	if (!task)
  		goto out_no_task;
  	if (count > PAGE_SIZE)
  		count = PAGE_SIZE;
  
  	/* No partial writes. */
  	length = -EINVAL;
  	if (*ppos != 0)
  		goto out;
  
  	length = -ENOMEM;
e12ba74d8   Mel Gorman   Group short-lived...
2026
  	page = (char*)__get_free_page(GFP_TEMPORARY);
28a6d6717   Eric W. Biederman   [PATCH] proc: reo...
2027
2028
2029
2030
2031
2032
2033
2034
  	if (!page)
  		goto out;
  
  	length = -EFAULT;
  	if (copy_from_user(page, buf, count))
  		goto out_free;
  
  	length = security_setprocattr(task,
2fddfeefe   Josef "Jeff" Sipek   [PATCH] proc: cha...
2035
  				      (char*)file->f_path.dentry->d_name.name,
28a6d6717   Eric W. Biederman   [PATCH] proc: reo...
2036
2037
2038
2039
2040
2041
2042
2043
  				      (void*)page, count);
  out_free:
  	free_page((unsigned long) page);
  out:
  	put_task_struct(task);
  out_no_task:
  	return length;
  }
00977a59b   Arjan van de Ven   [PATCH] mark stru...
2044
  static const struct file_operations proc_pid_attr_operations = {
28a6d6717   Eric W. Biederman   [PATCH] proc: reo...
2045
2046
2047
  	.read		= proc_pid_attr_read,
  	.write		= proc_pid_attr_write,
  };
c5141e6d6   Eric Dumazet   procfs: reorder s...
2048
  static const struct pid_entry attr_dir_stuff[] = {
61a287840   Eric W. Biederman   [PATCH] proc: Rem...
2049
2050
2051
2052
2053
2054
  	REG("current",    S_IRUGO|S_IWUGO, pid_attr),
  	REG("prev",       S_IRUGO,	   pid_attr),
  	REG("exec",       S_IRUGO|S_IWUGO, pid_attr),
  	REG("fscreate",   S_IRUGO|S_IWUGO, pid_attr),
  	REG("keycreate",  S_IRUGO|S_IWUGO, pid_attr),
  	REG("sockcreate", S_IRUGO|S_IWUGO, pid_attr),
28a6d6717   Eric W. Biederman   [PATCH] proc: reo...
2055
  };
72d9dcfc7   Eric W. Biederman   [PATCH] proc: Mer...
2056
  static int proc_attr_dir_readdir(struct file * filp,
28a6d6717   Eric W. Biederman   [PATCH] proc: reo...
2057
2058
2059
  			     void * dirent, filldir_t filldir)
  {
  	return proc_pident_readdir(filp,dirent,filldir,
72d9dcfc7   Eric W. Biederman   [PATCH] proc: Mer...
2060
  				   attr_dir_stuff,ARRAY_SIZE(attr_dir_stuff));
28a6d6717   Eric W. Biederman   [PATCH] proc: reo...
2061
  }
00977a59b   Arjan van de Ven   [PATCH] mark stru...
2062
  static const struct file_operations proc_attr_dir_operations = {
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2063
  	.read		= generic_read_dir,
72d9dcfc7   Eric W. Biederman   [PATCH] proc: Mer...
2064
  	.readdir	= proc_attr_dir_readdir,
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2065
  };
72d9dcfc7   Eric W. Biederman   [PATCH] proc: Mer...
2066
  static struct dentry *proc_attr_dir_lookup(struct inode *dir,
28a6d6717   Eric W. Biederman   [PATCH] proc: reo...
2067
2068
  				struct dentry *dentry, struct nameidata *nd)
  {
7bcd6b0ef   Eric W. Biederman   [PATCH] proc: rem...
2069
2070
  	return proc_pident_lookup(dir, dentry,
  				  attr_dir_stuff, ARRAY_SIZE(attr_dir_stuff));
28a6d6717   Eric W. Biederman   [PATCH] proc: reo...
2071
  }
c5ef1c42c   Arjan van de Ven   [PATCH] mark stru...
2072
  static const struct inode_operations proc_attr_dir_inode_operations = {
72d9dcfc7   Eric W. Biederman   [PATCH] proc: Mer...
2073
  	.lookup		= proc_attr_dir_lookup,
99f895518   Eric W. Biederman   [PATCH] proc: don...
2074
  	.getattr	= pid_getattr,
6d76fa58b   Linus Torvalds   Don't allow chmod...
2075
  	.setattr	= proc_setattr,
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2076
  };
28a6d6717   Eric W. Biederman   [PATCH] proc: reo...
2077
  #endif
3cb4a0bb1   Kawai, Hidehiro   coredump masking:...
2078
2079
2080
2081
2082
2083
2084
2085
2086
2087
2088
2089
2090
2091
2092
2093
2094
2095
2096
2097
2098
2099
2100
2101
2102
2103
2104
2105
2106
2107
2108
2109
2110
2111
2112
2113
2114
2115
2116
2117
2118
2119
2120
2121
2122
2123
2124
2125
2126
2127
2128
2129
2130
2131
2132
2133
2134
2135
2136
2137
2138
2139
2140
2141
2142
2143
2144
2145
2146
2147
2148
2149
2150
2151
2152
2153
2154
2155
2156
2157
2158
2159
2160
2161
2162
2163
  #if defined(USE_ELF_CORE_DUMP) && defined(CONFIG_ELF_CORE)
  static ssize_t proc_coredump_filter_read(struct file *file, char __user *buf,
  					 size_t count, loff_t *ppos)
  {
  	struct task_struct *task = get_proc_task(file->f_dentry->d_inode);
  	struct mm_struct *mm;
  	char buffer[PROC_NUMBUF];
  	size_t len;
  	int ret;
  
  	if (!task)
  		return -ESRCH;
  
  	ret = 0;
  	mm = get_task_mm(task);
  	if (mm) {
  		len = snprintf(buffer, sizeof(buffer), "%08lx
  ",
  			       ((mm->flags & MMF_DUMP_FILTER_MASK) >>
  				MMF_DUMP_FILTER_SHIFT));
  		mmput(mm);
  		ret = simple_read_from_buffer(buf, count, ppos, buffer, len);
  	}
  
  	put_task_struct(task);
  
  	return ret;
  }
  
  static ssize_t proc_coredump_filter_write(struct file *file,
  					  const char __user *buf,
  					  size_t count,
  					  loff_t *ppos)
  {
  	struct task_struct *task;
  	struct mm_struct *mm;
  	char buffer[PROC_NUMBUF], *end;
  	unsigned int val;
  	int ret;
  	int i;
  	unsigned long mask;
  
  	ret = -EFAULT;
  	memset(buffer, 0, sizeof(buffer));
  	if (count > sizeof(buffer) - 1)
  		count = sizeof(buffer) - 1;
  	if (copy_from_user(buffer, buf, count))
  		goto out_no_task;
  
  	ret = -EINVAL;
  	val = (unsigned int)simple_strtoul(buffer, &end, 0);
  	if (*end == '
  ')
  		end++;
  	if (end - buffer == 0)
  		goto out_no_task;
  
  	ret = -ESRCH;
  	task = get_proc_task(file->f_dentry->d_inode);
  	if (!task)
  		goto out_no_task;
  
  	ret = end - buffer;
  	mm = get_task_mm(task);
  	if (!mm)
  		goto out_no_mm;
  
  	for (i = 0, mask = 1; i < MMF_DUMP_FILTER_BITS; i++, mask <<= 1) {
  		if (val & mask)
  			set_bit(i + MMF_DUMP_FILTER_SHIFT, &mm->flags);
  		else
  			clear_bit(i + MMF_DUMP_FILTER_SHIFT, &mm->flags);
  	}
  
  	mmput(mm);
   out_no_mm:
  	put_task_struct(task);
   out_no_task:
  	return ret;
  }
  
  static const struct file_operations proc_coredump_filter_operations = {
  	.read		= proc_coredump_filter_read,
  	.write		= proc_coredump_filter_write,
  };
  #endif
28a6d6717   Eric W. Biederman   [PATCH] proc: reo...
2164
2165
2166
2167
2168
2169
  /*
   * /proc/self:
   */
  static int proc_self_readlink(struct dentry *dentry, char __user *buffer,
  			      int buflen)
  {
488e5bc45   Eric W. Biederman   proc: proper pidn...
2170
  	struct pid_namespace *ns = dentry->d_sb->s_fs_info;
b55fcb22d   Andrew Morton   revert "proc: fix...
2171
  	pid_t tgid = task_tgid_nr_ns(current, ns);
28a6d6717   Eric W. Biederman   [PATCH] proc: reo...
2172
  	char tmp[PROC_NUMBUF];
b55fcb22d   Andrew Morton   revert "proc: fix...
2173
  	if (!tgid)
488e5bc45   Eric W. Biederman   proc: proper pidn...
2174
  		return -ENOENT;
b55fcb22d   Andrew Morton   revert "proc: fix...
2175
  	sprintf(tmp, "%d", tgid);
28a6d6717   Eric W. Biederman   [PATCH] proc: reo...
2176
2177
2178
2179
2180
  	return vfs_readlink(dentry,buffer,buflen,tmp);
  }
  
  static void *proc_self_follow_link(struct dentry *dentry, struct nameidata *nd)
  {
488e5bc45   Eric W. Biederman   proc: proper pidn...
2181
  	struct pid_namespace *ns = dentry->d_sb->s_fs_info;
b55fcb22d   Andrew Morton   revert "proc: fix...
2182
  	pid_t tgid = task_tgid_nr_ns(current, ns);
28a6d6717   Eric W. Biederman   [PATCH] proc: reo...
2183
  	char tmp[PROC_NUMBUF];
b55fcb22d   Andrew Morton   revert "proc: fix...
2184
  	if (!tgid)
488e5bc45   Eric W. Biederman   proc: proper pidn...
2185
  		return ERR_PTR(-ENOENT);
b55fcb22d   Andrew Morton   revert "proc: fix...
2186
  	sprintf(tmp, "%d", task_tgid_nr_ns(current, ns));
28a6d6717   Eric W. Biederman   [PATCH] proc: reo...
2187
2188
  	return ERR_PTR(vfs_follow_link(nd,tmp));
  }
c5ef1c42c   Arjan van de Ven   [PATCH] mark stru...
2189
  static const struct inode_operations proc_self_inode_operations = {
28a6d6717   Eric W. Biederman   [PATCH] proc: reo...
2190
2191
2192
2193
2194
  	.readlink	= proc_self_readlink,
  	.follow_link	= proc_self_follow_link,
  };
  
  /*
801199ce8   Eric W. Biederman   [PATCH] proc: Mak...
2195
2196
2197
2198
2199
2200
   * proc base
   *
   * These are the directory entries in the root directory of /proc
   * that properly belong to the /proc filesystem, as they describe
   * describe something that is process related.
   */
c5141e6d6   Eric Dumazet   procfs: reorder s...
2201
  static const struct pid_entry proc_base_stuff[] = {
61a287840   Eric W. Biederman   [PATCH] proc: Rem...
2202
  	NOD("self", S_IFLNK|S_IRWXUGO,
801199ce8   Eric W. Biederman   [PATCH] proc: Mak...
2203
  		&proc_self_inode_operations, NULL, {}),
801199ce8   Eric W. Biederman   [PATCH] proc: Mak...
2204
2205
2206
2207
2208
2209
2210
2211
2212
2213
2214
2215
2216
2217
2218
2219
2220
2221
2222
2223
2224
2225
2226
2227
  };
  
  /*
   *	Exceptional case: normally we are not allowed to unhash a busy
   * directory. In this case, however, we can do it - no aliasing problems
   * due to the way we treat inodes.
   */
  static int proc_base_revalidate(struct dentry *dentry, struct nameidata *nd)
  {
  	struct inode *inode = dentry->d_inode;
  	struct task_struct *task = get_proc_task(inode);
  	if (task) {
  		put_task_struct(task);
  		return 1;
  	}
  	d_drop(dentry);
  	return 0;
  }
  
  static struct dentry_operations proc_base_dentry_operations =
  {
  	.d_revalidate	= proc_base_revalidate,
  	.d_delete	= pid_delete_dentry,
  };
444ceed8d   Eric W. Biederman   [PATCH] proc: Fac...
2228
  static struct dentry *proc_base_instantiate(struct inode *dir,
c5141e6d6   Eric Dumazet   procfs: reorder s...
2229
  	struct dentry *dentry, struct task_struct *task, const void *ptr)
801199ce8   Eric W. Biederman   [PATCH] proc: Mak...
2230
  {
c5141e6d6   Eric Dumazet   procfs: reorder s...
2231
  	const struct pid_entry *p = ptr;
801199ce8   Eric W. Biederman   [PATCH] proc: Mak...
2232
  	struct inode *inode;
801199ce8   Eric W. Biederman   [PATCH] proc: Mak...
2233
  	struct proc_inode *ei;
444ceed8d   Eric W. Biederman   [PATCH] proc: Fac...
2234
  	struct dentry *error = ERR_PTR(-EINVAL);
801199ce8   Eric W. Biederman   [PATCH] proc: Mak...
2235
2236
2237
2238
2239
2240
2241
2242
2243
2244
  
  	/* Allocate the inode */
  	error = ERR_PTR(-ENOMEM);
  	inode = new_inode(dir->i_sb);
  	if (!inode)
  		goto out;
  
  	/* Initialize the inode */
  	ei = PROC_I(inode);
  	inode->i_mtime = inode->i_atime = inode->i_ctime = CURRENT_TIME;
801199ce8   Eric W. Biederman   [PATCH] proc: Mak...
2245
2246
2247
2248
  
  	/*
  	 * grab the reference to the task.
  	 */
1a657f78d   Oleg Nesterov   [PATCH] introduce...
2249
  	ei->pid = get_task_pid(task, PIDTYPE_PID);
801199ce8   Eric W. Biederman   [PATCH] proc: Mak...
2250
2251
2252
2253
2254
2255
2256
2257
2258
2259
2260
2261
2262
2263
2264
2265
2266
2267
2268
  	if (!ei->pid)
  		goto out_iput;
  
  	inode->i_uid = 0;
  	inode->i_gid = 0;
  	inode->i_mode = p->mode;
  	if (S_ISDIR(inode->i_mode))
  		inode->i_nlink = 2;
  	if (S_ISLNK(inode->i_mode))
  		inode->i_size = 64;
  	if (p->iop)
  		inode->i_op = p->iop;
  	if (p->fop)
  		inode->i_fop = p->fop;
  	ei->op = p->op;
  	dentry->d_op = &proc_base_dentry_operations;
  	d_add(dentry, inode);
  	error = NULL;
  out:
801199ce8   Eric W. Biederman   [PATCH] proc: Mak...
2269
2270
2271
2272
2273
  	return error;
  out_iput:
  	iput(inode);
  	goto out;
  }
444ceed8d   Eric W. Biederman   [PATCH] proc: Fac...
2274
2275
2276
2277
  static struct dentry *proc_base_lookup(struct inode *dir, struct dentry *dentry)
  {
  	struct dentry *error;
  	struct task_struct *task = get_proc_task(dir);
c5141e6d6   Eric Dumazet   procfs: reorder s...
2278
  	const struct pid_entry *p, *last;
444ceed8d   Eric W. Biederman   [PATCH] proc: Fac...
2279
2280
2281
2282
2283
2284
2285
  
  	error = ERR_PTR(-ENOENT);
  
  	if (!task)
  		goto out_no_task;
  
  	/* Lookup the directory entry */
7bcd6b0ef   Eric W. Biederman   [PATCH] proc: rem...
2286
2287
  	last = &proc_base_stuff[ARRAY_SIZE(proc_base_stuff) - 1];
  	for (p = proc_base_stuff; p <= last; p++) {
444ceed8d   Eric W. Biederman   [PATCH] proc: Fac...
2288
2289
2290
2291
2292
  		if (p->len != dentry->d_name.len)
  			continue;
  		if (!memcmp(dentry->d_name.name, p->name, p->len))
  			break;
  	}
7bcd6b0ef   Eric W. Biederman   [PATCH] proc: rem...
2293
  	if (p > last)
444ceed8d   Eric W. Biederman   [PATCH] proc: Fac...
2294
2295
2296
2297
2298
2299
2300
2301
2302
  		goto out;
  
  	error = proc_base_instantiate(dir, dentry, task, p);
  
  out:
  	put_task_struct(task);
  out_no_task:
  	return error;
  }
c5141e6d6   Eric Dumazet   procfs: reorder s...
2303
2304
  static int proc_base_fill_cache(struct file *filp, void *dirent,
  	filldir_t filldir, struct task_struct *task, const struct pid_entry *p)
61a287840   Eric W. Biederman   [PATCH] proc: Rem...
2305
2306
2307
2308
  {
  	return proc_fill_cache(filp, dirent, filldir, p->name, p->len,
  				proc_base_instantiate, task, p);
  }
aba76fdb8   Andrew Morton   [PATCH] io-accoun...
2309
  #ifdef CONFIG_TASK_IO_ACCOUNTING
297c5d926   Andrea Righi   task IO accountin...
2310
2311
  static int do_io_accounting(struct task_struct *task, char *buffer, int whole)
  {
940389b8a   Andrea Righi   task IO accountin...
2312
  	struct task_io_accounting acct = task->ioac;
5995477ab   Andrea Righi   task IO accountin...
2313
2314
2315
2316
2317
2318
2319
2320
2321
2322
  	unsigned long flags;
  
  	if (whole && lock_task_sighand(task, &flags)) {
  		struct task_struct *t = task;
  
  		task_io_accounting_add(&acct, &task->signal->ioac);
  		while_each_thread(task, t)
  			task_io_accounting_add(&acct, &t->ioac);
  
  		unlock_task_sighand(task, &flags);
297c5d926   Andrea Righi   task IO accountin...
2323
  	}
aba76fdb8   Andrew Morton   [PATCH] io-accoun...
2324
2325
2326
2327
2328
2329
2330
2331
2332
2333
2334
2335
2336
2337
2338
  	return sprintf(buffer,
  			"rchar: %llu
  "
  			"wchar: %llu
  "
  			"syscr: %llu
  "
  			"syscw: %llu
  "
  			"read_bytes: %llu
  "
  			"write_bytes: %llu
  "
  			"cancelled_write_bytes: %llu
  ",
7c44319dc   Alexander Beregalov   proc: fix warnings
2339
2340
2341
2342
2343
2344
2345
  			(unsigned long long)acct.rchar,
  			(unsigned long long)acct.wchar,
  			(unsigned long long)acct.syscr,
  			(unsigned long long)acct.syscw,
  			(unsigned long long)acct.read_bytes,
  			(unsigned long long)acct.write_bytes,
  			(unsigned long long)acct.cancelled_write_bytes);
297c5d926   Andrea Righi   task IO accountin...
2346
2347
2348
2349
2350
  }
  
  static int proc_tid_io_accounting(struct task_struct *task, char *buffer)
  {
  	return do_io_accounting(task, buffer, 0);
aba76fdb8   Andrew Morton   [PATCH] io-accoun...
2351
  }
297c5d926   Andrea Righi   task IO accountin...
2352
2353
2354
2355
2356
2357
  
  static int proc_tgid_io_accounting(struct task_struct *task, char *buffer)
  {
  	return do_io_accounting(task, buffer, 1);
  }
  #endif /* CONFIG_TASK_IO_ACCOUNTING */
aba76fdb8   Andrew Morton   [PATCH] io-accoun...
2358

478307230   Kees Cook   [PATCH] proc: sho...
2359
2360
2361
2362
2363
2364
2365
  static int proc_pid_personality(struct seq_file *m, struct pid_namespace *ns,
  				struct pid *pid, struct task_struct *task)
  {
  	seq_printf(m, "%08x
  ", task->personality);
  	return 0;
  }
801199ce8   Eric W. Biederman   [PATCH] proc: Mak...
2366
  /*
28a6d6717   Eric W. Biederman   [PATCH] proc: reo...
2367
2368
   * Thread groups
   */
00977a59b   Arjan van de Ven   [PATCH] mark stru...
2369
  static const struct file_operations proc_task_operations;
c5ef1c42c   Arjan van de Ven   [PATCH] mark stru...
2370
  static const struct inode_operations proc_task_inode_operations;
20cdc894c   Eric W. Biederman   [PATCH] proc: mod...
2371

c5141e6d6   Eric Dumazet   procfs: reorder s...
2372
  static const struct pid_entry tgid_base_stuff[] = {
61a287840   Eric W. Biederman   [PATCH] proc: Rem...
2373
2374
  	DIR("task",       S_IRUGO|S_IXUGO, task),
  	DIR("fd",         S_IRUSR|S_IXUSR, fd),
279327429   Miklos Szeredi   add file position...
2375
  	DIR("fdinfo",     S_IRUSR|S_IXUSR, fdinfo),
b2211a361   Andrew Morton   net: fix build wi...
2376
  #ifdef CONFIG_NET
4f42c288e   Andre Noll   [NET]: Fix permis...
2377
  	DIR("net",        S_IRUGO|S_IXUGO, net),
b2211a361   Andrew Morton   net: fix build wi...
2378
  #endif
315e28c8d   James Pearson   Don't truncate /p...
2379
  	REG("environ",    S_IRUSR, environ),
61a287840   Eric W. Biederman   [PATCH] proc: Rem...
2380
  	INF("auxv",       S_IRUSR, pid_auxv),
df5f8314c   Eric W. Biederman   proc: seqfile con...
2381
  	ONE("status",     S_IRUGO, pid_status),
478307230   Kees Cook   [PATCH] proc: sho...
2382
  	ONE("personality", S_IRUSR, pid_personality),
d85f50d5e   Neil Horman   proc: export a pr...
2383
  	INF("limits",	  S_IRUSR, pid_limits),
43ae34cb4   Ingo Molnar   sched: scheduler ...
2384
2385
2386
  #ifdef CONFIG_SCHED_DEBUG
  	REG("sched",      S_IRUGO|S_IWUSR, pid_sched),
  #endif
ebcb67341   Roland McGrath   /proc/PID/syscall
2387
2388
2389
  #ifdef CONFIG_HAVE_ARCH_TRACEHOOK
  	INF("syscall",    S_IRUSR, pid_syscall),
  #endif
61a287840   Eric W. Biederman   [PATCH] proc: Rem...
2390
  	INF("cmdline",    S_IRUGO, pid_cmdline),
ee992744e   Eric W. Biederman   proc: rewrite do_...
2391
  	ONE("stat",       S_IRUGO, tgid_stat),
a56d3fc74   Eric W. Biederman   seqfile convert p...
2392
  	ONE("statm",      S_IRUGO, pid_statm),
61a287840   Eric W. Biederman   [PATCH] proc: Rem...
2393
  	REG("maps",       S_IRUGO, maps),
28a6d6717   Eric W. Biederman   [PATCH] proc: reo...
2394
  #ifdef CONFIG_NUMA
61a287840   Eric W. Biederman   [PATCH] proc: Rem...
2395
  	REG("numa_maps",  S_IRUGO, numa_maps),
28a6d6717   Eric W. Biederman   [PATCH] proc: reo...
2396
  #endif
61a287840   Eric W. Biederman   [PATCH] proc: Rem...
2397
  	REG("mem",        S_IRUSR|S_IWUSR, mem),
61a287840   Eric W. Biederman   [PATCH] proc: Rem...
2398
2399
2400
2401
  	LNK("cwd",        cwd),
  	LNK("root",       root),
  	LNK("exe",        exe),
  	REG("mounts",     S_IRUGO, mounts),
2d4d4864a   Ram Pai   [patch 6/7] vfs: ...
2402
  	REG("mountinfo",  S_IRUGO, mountinfo),
61a287840   Eric W. Biederman   [PATCH] proc: Rem...
2403
  	REG("mountstats", S_IRUSR, mountstats),
1e8832811   Matt Mackall   maps4: make page ...
2404
  #ifdef CONFIG_PROC_PAGE_MONITOR
b813e931b   David Rientjes   smaps: add clear_...
2405
  	REG("clear_refs", S_IWUSR, clear_refs),
61a287840   Eric W. Biederman   [PATCH] proc: Rem...
2406
  	REG("smaps",      S_IRUGO, smaps),
85863e475   Matt Mackall   maps4: add /proc/...
2407
  	REG("pagemap",    S_IRUSR, pagemap),
28a6d6717   Eric W. Biederman   [PATCH] proc: reo...
2408
2409
  #endif
  #ifdef CONFIG_SECURITY
72d9dcfc7   Eric W. Biederman   [PATCH] proc: Mer...
2410
  	DIR("attr",       S_IRUGO|S_IXUGO, attr_dir),
28a6d6717   Eric W. Biederman   [PATCH] proc: reo...
2411
2412
  #endif
  #ifdef CONFIG_KALLSYMS
61a287840   Eric W. Biederman   [PATCH] proc: Rem...
2413
  	INF("wchan",      S_IRUGO, pid_wchan),
28a6d6717   Eric W. Biederman   [PATCH] proc: reo...
2414
2415
  #endif
  #ifdef CONFIG_SCHEDSTATS
61a287840   Eric W. Biederman   [PATCH] proc: Rem...
2416
  	INF("schedstat",  S_IRUGO, pid_schedstat),
28a6d6717   Eric W. Biederman   [PATCH] proc: reo...
2417
  #endif
9745512ce   Arjan van de Ven   sched: latencytop...
2418
2419
2420
  #ifdef CONFIG_LATENCYTOP
  	REG("latency",  S_IRUGO, lstats),
  #endif
8793d854e   Paul Menage   Task Control Grou...
2421
  #ifdef CONFIG_PROC_PID_CPUSET
61a287840   Eric W. Biederman   [PATCH] proc: Rem...
2422
  	REG("cpuset",     S_IRUGO, cpuset),
28a6d6717   Eric W. Biederman   [PATCH] proc: reo...
2423
  #endif
a424316ca   Paul Menage   Task Control Grou...
2424
2425
2426
  #ifdef CONFIG_CGROUPS
  	REG("cgroup",  S_IRUGO, cgroup),
  #endif
61a287840   Eric W. Biederman   [PATCH] proc: Rem...
2427
2428
  	INF("oom_score",  S_IRUGO, oom_score),
  	REG("oom_adj",    S_IRUGO|S_IWUSR, oom_adjust),
28a6d6717   Eric W. Biederman   [PATCH] proc: reo...
2429
  #ifdef CONFIG_AUDITSYSCALL
61a287840   Eric W. Biederman   [PATCH] proc: Rem...
2430
  	REG("loginuid",   S_IWUSR|S_IRUGO, loginuid),
6ee650467   Steve Grubb   [PATCH] open sess...
2431
  	REG("sessionid",  S_IRUGO, sessionid),
28a6d6717   Eric W. Biederman   [PATCH] proc: reo...
2432
  #endif
f4f154fd9   Akinobu Mita   [PATCH] fault inj...
2433
2434
2435
  #ifdef CONFIG_FAULT_INJECTION
  	REG("make-it-fail", S_IRUGO|S_IWUSR, fault_inject),
  #endif
3cb4a0bb1   Kawai, Hidehiro   coredump masking:...
2436
2437
2438
  #if defined(USE_ELF_CORE_DUMP) && defined(CONFIG_ELF_CORE)
  	REG("coredump_filter", S_IRUGO|S_IWUSR, coredump_filter),
  #endif
aba76fdb8   Andrew Morton   [PATCH] io-accoun...
2439
  #ifdef CONFIG_TASK_IO_ACCOUNTING
297c5d926   Andrea Righi   task IO accountin...
2440
  	INF("io",	S_IRUGO, tgid_io_accounting),
aba76fdb8   Andrew Morton   [PATCH] io-accoun...
2441
  #endif
28a6d6717   Eric W. Biederman   [PATCH] proc: reo...
2442
  };
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2443

28a6d6717   Eric W. Biederman   [PATCH] proc: reo...
2444
  static int proc_tgid_base_readdir(struct file * filp,
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2445
2446
2447
  			     void * dirent, filldir_t filldir)
  {
  	return proc_pident_readdir(filp,dirent,filldir,
28a6d6717   Eric W. Biederman   [PATCH] proc: reo...
2448
  				   tgid_base_stuff,ARRAY_SIZE(tgid_base_stuff));
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2449
  }
00977a59b   Arjan van de Ven   [PATCH] mark stru...
2450
  static const struct file_operations proc_tgid_base_operations = {
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2451
  	.read		= generic_read_dir,
28a6d6717   Eric W. Biederman   [PATCH] proc: reo...
2452
  	.readdir	= proc_tgid_base_readdir,
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2453
  };
28a6d6717   Eric W. Biederman   [PATCH] proc: reo...
2454
  static struct dentry *proc_tgid_base_lookup(struct inode *dir, struct dentry *dentry, struct nameidata *nd){
7bcd6b0ef   Eric W. Biederman   [PATCH] proc: rem...
2455
2456
  	return proc_pident_lookup(dir, dentry,
  				  tgid_base_stuff, ARRAY_SIZE(tgid_base_stuff));
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2457
  }
c5ef1c42c   Arjan van de Ven   [PATCH] mark stru...
2458
  static const struct inode_operations proc_tgid_base_inode_operations = {
28a6d6717   Eric W. Biederman   [PATCH] proc: reo...
2459
  	.lookup		= proc_tgid_base_lookup,
99f895518   Eric W. Biederman   [PATCH] proc: don...
2460
  	.getattr	= pid_getattr,
6d76fa58b   Linus Torvalds   Don't allow chmod...
2461
  	.setattr	= proc_setattr,
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2462
  };
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2463

60347f671   Pavel Emelyanov   pid namespaces: p...
2464
  static void proc_flush_task_mnt(struct vfsmount *mnt, pid_t pid, pid_t tgid)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2465
  {
48e6484d4   Eric W. Biederman   [PATCH] proc: Rew...
2466
  	struct dentry *dentry, *leader, *dir;
8578cea75   Eric W. Biederman   [PATCH] proc: mak...
2467
  	char buf[PROC_NUMBUF];
48e6484d4   Eric W. Biederman   [PATCH] proc: Rew...
2468
2469
2470
  	struct qstr name;
  
  	name.name = buf;
60347f671   Pavel Emelyanov   pid namespaces: p...
2471
2472
  	name.len = snprintf(buf, sizeof(buf), "%d", pid);
  	dentry = d_hash_and_lookup(mnt->mnt_root, &name);
48e6484d4   Eric W. Biederman   [PATCH] proc: Rew...
2473
  	if (dentry) {
7766755a2   Andrea Arcangeli   Fix /proc dcache ...
2474
2475
  		if (!(current->flags & PF_EXITING))
  			shrink_dcache_parent(dentry);
48e6484d4   Eric W. Biederman   [PATCH] proc: Rew...
2476
2477
2478
  		d_drop(dentry);
  		dput(dentry);
  	}
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2479

60347f671   Pavel Emelyanov   pid namespaces: p...
2480
  	if (tgid == 0)
48e6484d4   Eric W. Biederman   [PATCH] proc: Rew...
2481
  		goto out;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2482

48e6484d4   Eric W. Biederman   [PATCH] proc: Rew...
2483
  	name.name = buf;
60347f671   Pavel Emelyanov   pid namespaces: p...
2484
2485
  	name.len = snprintf(buf, sizeof(buf), "%d", tgid);
  	leader = d_hash_and_lookup(mnt->mnt_root, &name);
48e6484d4   Eric W. Biederman   [PATCH] proc: Rew...
2486
2487
  	if (!leader)
  		goto out;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2488

48e6484d4   Eric W. Biederman   [PATCH] proc: Rew...
2489
2490
2491
2492
2493
2494
2495
  	name.name = "task";
  	name.len = strlen(name.name);
  	dir = d_hash_and_lookup(leader, &name);
  	if (!dir)
  		goto out_put_leader;
  
  	name.name = buf;
60347f671   Pavel Emelyanov   pid namespaces: p...
2496
  	name.len = snprintf(buf, sizeof(buf), "%d", pid);
48e6484d4   Eric W. Biederman   [PATCH] proc: Rew...
2497
2498
2499
2500
2501
  	dentry = d_hash_and_lookup(dir, &name);
  	if (dentry) {
  		shrink_dcache_parent(dentry);
  		d_drop(dentry);
  		dput(dentry);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2502
  	}
48e6484d4   Eric W. Biederman   [PATCH] proc: Rew...
2503
2504
2505
2506
2507
2508
  
  	dput(dir);
  out_put_leader:
  	dput(leader);
  out:
  	return;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2509
  }
0895e91d6   Randy Dunlap   procfs: fix kerne...
2510
2511
2512
2513
2514
  /**
   * proc_flush_task -  Remove dcache entries for @task from the /proc dcache.
   * @task: task that should be flushed.
   *
   * When flushing dentries from proc, one needs to flush them from global
60347f671   Pavel Emelyanov   pid namespaces: p...
2515
   * proc (proc_mnt) and from all the namespaces' procs this task was seen
0895e91d6   Randy Dunlap   procfs: fix kerne...
2516
2517
2518
2519
2520
2521
2522
2523
2524
2525
2526
2527
2528
2529
2530
2531
2532
   * in. This call is supposed to do all of this job.
   *
   * Looks in the dcache for
   * /proc/@pid
   * /proc/@tgid/task/@pid
   * if either directory is present flushes it and all of it'ts children
   * from the dcache.
   *
   * It is safe and reasonable to cache /proc entries for a task until
   * that task exits.  After that they just clog up the dcache with
   * useless entries, possibly causing useful dcache entries to be
   * flushed instead.  This routine is proved to flush those useless
   * dcache entries at process exit time.
   *
   * NOTE: This routine is just an optimization so it does not guarantee
   *       that no dcache entries will exist at process exit time it
   *       just makes it very unlikely that any will persist.
60347f671   Pavel Emelyanov   pid namespaces: p...
2533
2534
2535
2536
   */
  
  void proc_flush_task(struct task_struct *task)
  {
9fcc2d15b   Eric W. Biederman   proc: simplify an...
2537
2538
  	int i;
  	struct pid *pid, *tgid = NULL;
130f77ecb   Pavel Emelyanov   pid namespaces: m...
2539
  	struct upid *upid;
130f77ecb   Pavel Emelyanov   pid namespaces: m...
2540
  	pid = task_pid(task);
9fcc2d15b   Eric W. Biederman   proc: simplify an...
2541
2542
  	if (thread_group_leader(task))
  		tgid = task_tgid(task);
130f77ecb   Pavel Emelyanov   pid namespaces: m...
2543

9fcc2d15b   Eric W. Biederman   proc: simplify an...
2544
  	for (i = 0; i <= pid->level; i++) {
130f77ecb   Pavel Emelyanov   pid namespaces: m...
2545
2546
  		upid = &pid->numbers[i];
  		proc_flush_task_mnt(upid->ns->proc_mnt, upid->nr,
9fcc2d15b   Eric W. Biederman   proc: simplify an...
2547
  			tgid ? tgid->numbers[i].nr : 0);
130f77ecb   Pavel Emelyanov   pid namespaces: m...
2548
  	}
6f4e64335   Pavel Emelyanov   pid namespaces: i...
2549
2550
2551
2552
  
  	upid = &pid->numbers[pid->level];
  	if (upid->nr == 1)
  		pid_ns_release_proc(upid->ns);
60347f671   Pavel Emelyanov   pid namespaces: p...
2553
  }
9711ef994   Adrian Bunk   [PATCH] make fs/p...
2554
2555
  static struct dentry *proc_pid_instantiate(struct inode *dir,
  					   struct dentry * dentry,
c5141e6d6   Eric Dumazet   procfs: reorder s...
2556
  					   struct task_struct *task, const void *ptr)
444ceed8d   Eric W. Biederman   [PATCH] proc: Fac...
2557
2558
2559
  {
  	struct dentry *error = ERR_PTR(-ENOENT);
  	struct inode *inode;
61a287840   Eric W. Biederman   [PATCH] proc: Rem...
2560
  	inode = proc_pid_make_inode(dir->i_sb, task);
444ceed8d   Eric W. Biederman   [PATCH] proc: Fac...
2561
2562
2563
2564
2565
2566
2567
  	if (!inode)
  		goto out;
  
  	inode->i_mode = S_IFDIR|S_IRUGO|S_IXUGO;
  	inode->i_op = &proc_tgid_base_inode_operations;
  	inode->i_fop = &proc_tgid_base_operations;
  	inode->i_flags|=S_IMMUTABLE;
aed541759   Vegard Nossum   proc: calculate t...
2568
2569
2570
  
  	inode->i_nlink = 2 + pid_entry_count_dirs(tgid_base_stuff,
  		ARRAY_SIZE(tgid_base_stuff));
444ceed8d   Eric W. Biederman   [PATCH] proc: Fac...
2571
2572
2573
2574
2575
2576
2577
2578
2579
2580
  
  	dentry->d_op = &pid_dentry_operations;
  
  	d_add(dentry, inode);
  	/* Close the race of the process dying before we return the dentry */
  	if (pid_revalidate(dentry, NULL))
  		error = NULL;
  out:
  	return error;
  }
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2581
2582
  struct dentry *proc_pid_lookup(struct inode *dir, struct dentry * dentry, struct nameidata *nd)
  {
cd6a3ce9e   Eric W. Biederman   [PATCH] proc: Clo...
2583
  	struct dentry *result = ERR_PTR(-ENOENT);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2584
  	struct task_struct *task;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2585
  	unsigned tgid;
b488893a3   Pavel Emelyanov   pid namespaces: c...
2586
  	struct pid_namespace *ns;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2587

801199ce8   Eric W. Biederman   [PATCH] proc: Mak...
2588
2589
2590
  	result = proc_base_lookup(dir, dentry);
  	if (!IS_ERR(result) || PTR_ERR(result) != -ENOENT)
  		goto out;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2591
2592
2593
  	tgid = name_to_int(dentry);
  	if (tgid == ~0U)
  		goto out;
b488893a3   Pavel Emelyanov   pid namespaces: c...
2594
  	ns = dentry->d_sb->s_fs_info;
de7587343   Eric W. Biederman   [PATCH] proc: Rem...
2595
  	rcu_read_lock();
b488893a3   Pavel Emelyanov   pid namespaces: c...
2596
  	task = find_task_by_pid_ns(tgid, ns);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2597
2598
  	if (task)
  		get_task_struct(task);
de7587343   Eric W. Biederman   [PATCH] proc: Rem...
2599
  	rcu_read_unlock();
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2600
2601
  	if (!task)
  		goto out;
444ceed8d   Eric W. Biederman   [PATCH] proc: Fac...
2602
  	result = proc_pid_instantiate(dir, dentry, task, NULL);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2603
  	put_task_struct(task);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2604
  out:
cd6a3ce9e   Eric W. Biederman   [PATCH] proc: Clo...
2605
  	return result;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2606
  }
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2607
  /*
0804ef4b0   Eric W. Biederman   [PATCH] proc: rea...
2608
   * Find the first task with tgid >= tgid
0bc58a910   Eric W. Biederman   [PATCH] proc: ref...
2609
   *
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2610
   */
19fd4bb2a   Eric W. Biederman   proc: remove race...
2611
2612
  struct tgid_iter {
  	unsigned int tgid;
0804ef4b0   Eric W. Biederman   [PATCH] proc: rea...
2613
  	struct task_struct *task;
19fd4bb2a   Eric W. Biederman   proc: remove race...
2614
2615
2616
  };
  static struct tgid_iter next_tgid(struct pid_namespace *ns, struct tgid_iter iter)
  {
0804ef4b0   Eric W. Biederman   [PATCH] proc: rea...
2617
  	struct pid *pid;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2618

19fd4bb2a   Eric W. Biederman   proc: remove race...
2619
2620
  	if (iter.task)
  		put_task_struct(iter.task);
454cc105e   Eric W. Biederman   [PATCH] proc: Rem...
2621
  	rcu_read_lock();
0804ef4b0   Eric W. Biederman   [PATCH] proc: rea...
2622
  retry:
19fd4bb2a   Eric W. Biederman   proc: remove race...
2623
2624
  	iter.task = NULL;
  	pid = find_ge_pid(iter.tgid, ns);
0804ef4b0   Eric W. Biederman   [PATCH] proc: rea...
2625
  	if (pid) {
19fd4bb2a   Eric W. Biederman   proc: remove race...
2626
2627
  		iter.tgid = pid_nr_ns(pid, ns);
  		iter.task = pid_task(pid, PIDTYPE_PID);
0804ef4b0   Eric W. Biederman   [PATCH] proc: rea...
2628
2629
2630
2631
2632
2633
2634
2635
2636
2637
2638
2639
  		/* What we to know is if the pid we have find is the
  		 * pid of a thread_group_leader.  Testing for task
  		 * being a thread_group_leader is the obvious thing
  		 * todo but there is a window when it fails, due to
  		 * the pid transfer logic in de_thread.
  		 *
  		 * So we perform the straight forward test of seeing
  		 * if the pid we have found is the pid of a thread
  		 * group leader, and don't worry if the task we have
  		 * found doesn't happen to be a thread group leader.
  		 * As we don't care in the case of readdir.
  		 */
19fd4bb2a   Eric W. Biederman   proc: remove race...
2640
2641
  		if (!iter.task || !has_group_leader_pid(iter.task)) {
  			iter.tgid += 1;
0804ef4b0   Eric W. Biederman   [PATCH] proc: rea...
2642
  			goto retry;
19fd4bb2a   Eric W. Biederman   proc: remove race...
2643
2644
  		}
  		get_task_struct(iter.task);
0bc58a910   Eric W. Biederman   [PATCH] proc: ref...
2645
  	}
454cc105e   Eric W. Biederman   [PATCH] proc: Rem...
2646
  	rcu_read_unlock();
19fd4bb2a   Eric W. Biederman   proc: remove race...
2647
  	return iter;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2648
  }
7bcd6b0ef   Eric W. Biederman   [PATCH] proc: rem...
2649
  #define TGID_OFFSET (FIRST_PROCESS_ENTRY + ARRAY_SIZE(proc_base_stuff))
0804ef4b0   Eric W. Biederman   [PATCH] proc: rea...
2650

61a287840   Eric W. Biederman   [PATCH] proc: Rem...
2651
  static int proc_pid_fill_cache(struct file *filp, void *dirent, filldir_t filldir,
19fd4bb2a   Eric W. Biederman   proc: remove race...
2652
  	struct tgid_iter iter)
61a287840   Eric W. Biederman   [PATCH] proc: Rem...
2653
2654
  {
  	char name[PROC_NUMBUF];
19fd4bb2a   Eric W. Biederman   proc: remove race...
2655
  	int len = snprintf(name, sizeof(name), "%d", iter.tgid);
61a287840   Eric W. Biederman   [PATCH] proc: Rem...
2656
  	return proc_fill_cache(filp, dirent, filldir, name, len,
19fd4bb2a   Eric W. Biederman   proc: remove race...
2657
  				proc_pid_instantiate, iter.task, NULL);
61a287840   Eric W. Biederman   [PATCH] proc: Rem...
2658
  }
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2659
2660
2661
  /* for the /proc/ directory itself, after non-process stuff has been done */
  int proc_pid_readdir(struct file * filp, void * dirent, filldir_t filldir)
  {
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2662
  	unsigned int nr = filp->f_pos - FIRST_PROCESS_ENTRY;
2fddfeefe   Josef "Jeff" Sipek   [PATCH] proc: cha...
2663
  	struct task_struct *reaper = get_proc_task(filp->f_path.dentry->d_inode);
19fd4bb2a   Eric W. Biederman   proc: remove race...
2664
  	struct tgid_iter iter;
b488893a3   Pavel Emelyanov   pid namespaces: c...
2665
  	struct pid_namespace *ns;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2666

61a287840   Eric W. Biederman   [PATCH] proc: Rem...
2667
2668
  	if (!reaper)
  		goto out_no_task;
7bcd6b0ef   Eric W. Biederman   [PATCH] proc: rem...
2669
  	for (; nr < ARRAY_SIZE(proc_base_stuff); filp->f_pos++, nr++) {
c5141e6d6   Eric Dumazet   procfs: reorder s...
2670
  		const struct pid_entry *p = &proc_base_stuff[nr];
61a287840   Eric W. Biederman   [PATCH] proc: Rem...
2671
  		if (proc_base_fill_cache(filp, dirent, filldir, reaper, p) < 0)
801199ce8   Eric W. Biederman   [PATCH] proc: Mak...
2672
  			goto out;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2673
  	}
b488893a3   Pavel Emelyanov   pid namespaces: c...
2674
  	ns = filp->f_dentry->d_sb->s_fs_info;
19fd4bb2a   Eric W. Biederman   proc: remove race...
2675
2676
2677
2678
2679
2680
2681
2682
  	iter.task = NULL;
  	iter.tgid = filp->f_pos - TGID_OFFSET;
  	for (iter = next_tgid(ns, iter);
  	     iter.task;
  	     iter.tgid += 1, iter = next_tgid(ns, iter)) {
  		filp->f_pos = iter.tgid + TGID_OFFSET;
  		if (proc_pid_fill_cache(filp, dirent, filldir, iter) < 0) {
  			put_task_struct(iter.task);
0804ef4b0   Eric W. Biederman   [PATCH] proc: rea...
2683
  			goto out;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2684
  		}
0bc58a910   Eric W. Biederman   [PATCH] proc: ref...
2685
  	}
0804ef4b0   Eric W. Biederman   [PATCH] proc: rea...
2686
2687
  	filp->f_pos = PID_MAX_LIMIT + TGID_OFFSET;
  out:
61a287840   Eric W. Biederman   [PATCH] proc: Rem...
2688
2689
  	put_task_struct(reaper);
  out_no_task:
0bc58a910   Eric W. Biederman   [PATCH] proc: ref...
2690
2691
  	return 0;
  }
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2692

0bc58a910   Eric W. Biederman   [PATCH] proc: ref...
2693
  /*
28a6d6717   Eric W. Biederman   [PATCH] proc: reo...
2694
2695
   * Tasks
   */
c5141e6d6   Eric Dumazet   procfs: reorder s...
2696
  static const struct pid_entry tid_base_stuff[] = {
61a287840   Eric W. Biederman   [PATCH] proc: Rem...
2697
  	DIR("fd",        S_IRUSR|S_IXUSR, fd),
279327429   Miklos Szeredi   add file position...
2698
  	DIR("fdinfo",    S_IRUSR|S_IXUSR, fdinfo),
315e28c8d   James Pearson   Don't truncate /p...
2699
  	REG("environ",   S_IRUSR, environ),
61a287840   Eric W. Biederman   [PATCH] proc: Rem...
2700
  	INF("auxv",      S_IRUSR, pid_auxv),
df5f8314c   Eric W. Biederman   proc: seqfile con...
2701
  	ONE("status",    S_IRUGO, pid_status),
478307230   Kees Cook   [PATCH] proc: sho...
2702
  	ONE("personality", S_IRUSR, pid_personality),
d85f50d5e   Neil Horman   proc: export a pr...
2703
  	INF("limits",	 S_IRUSR, pid_limits),
43ae34cb4   Ingo Molnar   sched: scheduler ...
2704
2705
2706
  #ifdef CONFIG_SCHED_DEBUG
  	REG("sched",     S_IRUGO|S_IWUSR, pid_sched),
  #endif
ebcb67341   Roland McGrath   /proc/PID/syscall
2707
2708
2709
  #ifdef CONFIG_HAVE_ARCH_TRACEHOOK
  	INF("syscall",   S_IRUSR, pid_syscall),
  #endif
61a287840   Eric W. Biederman   [PATCH] proc: Rem...
2710
  	INF("cmdline",   S_IRUGO, pid_cmdline),
ee992744e   Eric W. Biederman   proc: rewrite do_...
2711
  	ONE("stat",      S_IRUGO, tid_stat),
a56d3fc74   Eric W. Biederman   seqfile convert p...
2712
  	ONE("statm",     S_IRUGO, pid_statm),
61a287840   Eric W. Biederman   [PATCH] proc: Rem...
2713
  	REG("maps",      S_IRUGO, maps),
28a6d6717   Eric W. Biederman   [PATCH] proc: reo...
2714
  #ifdef CONFIG_NUMA
61a287840   Eric W. Biederman   [PATCH] proc: Rem...
2715
  	REG("numa_maps", S_IRUGO, numa_maps),
28a6d6717   Eric W. Biederman   [PATCH] proc: reo...
2716
  #endif
61a287840   Eric W. Biederman   [PATCH] proc: Rem...
2717
  	REG("mem",       S_IRUSR|S_IWUSR, mem),
61a287840   Eric W. Biederman   [PATCH] proc: Rem...
2718
2719
2720
2721
  	LNK("cwd",       cwd),
  	LNK("root",      root),
  	LNK("exe",       exe),
  	REG("mounts",    S_IRUGO, mounts),
2d4d4864a   Ram Pai   [patch 6/7] vfs: ...
2722
  	REG("mountinfo",  S_IRUGO, mountinfo),
1e8832811   Matt Mackall   maps4: make page ...
2723
  #ifdef CONFIG_PROC_PAGE_MONITOR
b813e931b   David Rientjes   smaps: add clear_...
2724
  	REG("clear_refs", S_IWUSR, clear_refs),
61a287840   Eric W. Biederman   [PATCH] proc: Rem...
2725
  	REG("smaps",     S_IRUGO, smaps),
85863e475   Matt Mackall   maps4: add /proc/...
2726
  	REG("pagemap",    S_IRUSR, pagemap),
28a6d6717   Eric W. Biederman   [PATCH] proc: reo...
2727
2728
  #endif
  #ifdef CONFIG_SECURITY
72d9dcfc7   Eric W. Biederman   [PATCH] proc: Mer...
2729
  	DIR("attr",      S_IRUGO|S_IXUGO, attr_dir),
28a6d6717   Eric W. Biederman   [PATCH] proc: reo...
2730
2731
  #endif
  #ifdef CONFIG_KALLSYMS
61a287840   Eric W. Biederman   [PATCH] proc: Rem...
2732
  	INF("wchan",     S_IRUGO, pid_wchan),
28a6d6717   Eric W. Biederman   [PATCH] proc: reo...
2733
2734
  #endif
  #ifdef CONFIG_SCHEDSTATS
61a287840   Eric W. Biederman   [PATCH] proc: Rem...
2735
  	INF("schedstat", S_IRUGO, pid_schedstat),
28a6d6717   Eric W. Biederman   [PATCH] proc: reo...
2736
  #endif
9745512ce   Arjan van de Ven   sched: latencytop...
2737
2738
2739
  #ifdef CONFIG_LATENCYTOP
  	REG("latency",  S_IRUGO, lstats),
  #endif
8793d854e   Paul Menage   Task Control Grou...
2740
  #ifdef CONFIG_PROC_PID_CPUSET
61a287840   Eric W. Biederman   [PATCH] proc: Rem...
2741
  	REG("cpuset",    S_IRUGO, cpuset),
28a6d6717   Eric W. Biederman   [PATCH] proc: reo...
2742
  #endif
a424316ca   Paul Menage   Task Control Grou...
2743
2744
2745
  #ifdef CONFIG_CGROUPS
  	REG("cgroup",  S_IRUGO, cgroup),
  #endif
61a287840   Eric W. Biederman   [PATCH] proc: Rem...
2746
2747
  	INF("oom_score", S_IRUGO, oom_score),
  	REG("oom_adj",   S_IRUGO|S_IWUSR, oom_adjust),
28a6d6717   Eric W. Biederman   [PATCH] proc: reo...
2748
  #ifdef CONFIG_AUDITSYSCALL
61a287840   Eric W. Biederman   [PATCH] proc: Rem...
2749
  	REG("loginuid",  S_IWUSR|S_IRUGO, loginuid),
1e0bd7550   Eric Paris   [PATCH] export se...
2750
  	REG("sessionid",  S_IRUSR, sessionid),
28a6d6717   Eric W. Biederman   [PATCH] proc: reo...
2751
  #endif
f4f154fd9   Akinobu Mita   [PATCH] fault inj...
2752
2753
2754
  #ifdef CONFIG_FAULT_INJECTION
  	REG("make-it-fail", S_IRUGO|S_IWUSR, fault_inject),
  #endif
297c5d926   Andrea Righi   task IO accountin...
2755
2756
2757
  #ifdef CONFIG_TASK_IO_ACCOUNTING
  	INF("io",	S_IRUGO, tid_io_accounting),
  #endif
28a6d6717   Eric W. Biederman   [PATCH] proc: reo...
2758
2759
2760
2761
2762
2763
2764
2765
2766
2767
  };
  
  static int proc_tid_base_readdir(struct file * filp,
  			     void * dirent, filldir_t filldir)
  {
  	return proc_pident_readdir(filp,dirent,filldir,
  				   tid_base_stuff,ARRAY_SIZE(tid_base_stuff));
  }
  
  static struct dentry *proc_tid_base_lookup(struct inode *dir, struct dentry *dentry, struct nameidata *nd){
7bcd6b0ef   Eric W. Biederman   [PATCH] proc: rem...
2768
2769
  	return proc_pident_lookup(dir, dentry,
  				  tid_base_stuff, ARRAY_SIZE(tid_base_stuff));
28a6d6717   Eric W. Biederman   [PATCH] proc: reo...
2770
  }
00977a59b   Arjan van de Ven   [PATCH] mark stru...
2771
  static const struct file_operations proc_tid_base_operations = {
28a6d6717   Eric W. Biederman   [PATCH] proc: reo...
2772
2773
2774
  	.read		= generic_read_dir,
  	.readdir	= proc_tid_base_readdir,
  };
c5ef1c42c   Arjan van de Ven   [PATCH] mark stru...
2775
  static const struct inode_operations proc_tid_base_inode_operations = {
28a6d6717   Eric W. Biederman   [PATCH] proc: reo...
2776
2777
2778
2779
  	.lookup		= proc_tid_base_lookup,
  	.getattr	= pid_getattr,
  	.setattr	= proc_setattr,
  };
444ceed8d   Eric W. Biederman   [PATCH] proc: Fac...
2780
  static struct dentry *proc_task_instantiate(struct inode *dir,
c5141e6d6   Eric Dumazet   procfs: reorder s...
2781
  	struct dentry *dentry, struct task_struct *task, const void *ptr)
444ceed8d   Eric W. Biederman   [PATCH] proc: Fac...
2782
2783
2784
  {
  	struct dentry *error = ERR_PTR(-ENOENT);
  	struct inode *inode;
61a287840   Eric W. Biederman   [PATCH] proc: Rem...
2785
  	inode = proc_pid_make_inode(dir->i_sb, task);
444ceed8d   Eric W. Biederman   [PATCH] proc: Fac...
2786
2787
2788
2789
2790
2791
2792
  
  	if (!inode)
  		goto out;
  	inode->i_mode = S_IFDIR|S_IRUGO|S_IXUGO;
  	inode->i_op = &proc_tid_base_inode_operations;
  	inode->i_fop = &proc_tid_base_operations;
  	inode->i_flags|=S_IMMUTABLE;
aed541759   Vegard Nossum   proc: calculate t...
2793
2794
2795
  
  	inode->i_nlink = 2 + pid_entry_count_dirs(tid_base_stuff,
  		ARRAY_SIZE(tid_base_stuff));
444ceed8d   Eric W. Biederman   [PATCH] proc: Fac...
2796
2797
2798
2799
2800
2801
2802
2803
2804
2805
  
  	dentry->d_op = &pid_dentry_operations;
  
  	d_add(dentry, inode);
  	/* Close the race of the process dying before we return the dentry */
  	if (pid_revalidate(dentry, NULL))
  		error = NULL;
  out:
  	return error;
  }
28a6d6717   Eric W. Biederman   [PATCH] proc: reo...
2806
2807
2808
2809
2810
  static struct dentry *proc_task_lookup(struct inode *dir, struct dentry * dentry, struct nameidata *nd)
  {
  	struct dentry *result = ERR_PTR(-ENOENT);
  	struct task_struct *task;
  	struct task_struct *leader = get_proc_task(dir);
28a6d6717   Eric W. Biederman   [PATCH] proc: reo...
2811
  	unsigned tid;
b488893a3   Pavel Emelyanov   pid namespaces: c...
2812
  	struct pid_namespace *ns;
28a6d6717   Eric W. Biederman   [PATCH] proc: reo...
2813
2814
2815
2816
2817
2818
2819
  
  	if (!leader)
  		goto out_no_task;
  
  	tid = name_to_int(dentry);
  	if (tid == ~0U)
  		goto out;
b488893a3   Pavel Emelyanov   pid namespaces: c...
2820
  	ns = dentry->d_sb->s_fs_info;
28a6d6717   Eric W. Biederman   [PATCH] proc: reo...
2821
  	rcu_read_lock();
b488893a3   Pavel Emelyanov   pid namespaces: c...
2822
  	task = find_task_by_pid_ns(tid, ns);
28a6d6717   Eric W. Biederman   [PATCH] proc: reo...
2823
2824
2825
2826
2827
  	if (task)
  		get_task_struct(task);
  	rcu_read_unlock();
  	if (!task)
  		goto out;
bac0abd61   Pavel Emelyanov   Isolate some expl...
2828
  	if (!same_thread_group(leader, task))
28a6d6717   Eric W. Biederman   [PATCH] proc: reo...
2829
  		goto out_drop_task;
444ceed8d   Eric W. Biederman   [PATCH] proc: Fac...
2830
  	result = proc_task_instantiate(dir, dentry, task, NULL);
28a6d6717   Eric W. Biederman   [PATCH] proc: reo...
2831
2832
2833
2834
2835
2836
2837
2838
2839
  out_drop_task:
  	put_task_struct(task);
  out:
  	put_task_struct(leader);
  out_no_task:
  	return result;
  }
  
  /*
0bc58a910   Eric W. Biederman   [PATCH] proc: ref...
2840
2841
2842
2843
2844
2845
2846
2847
2848
2849
2850
   * Find the first tid of a thread group to return to user space.
   *
   * Usually this is just the thread group leader, but if the users
   * buffer was too small or there was a seek into the middle of the
   * directory we have more work todo.
   *
   * In the case of a short read we start with find_task_by_pid.
   *
   * In the case of a seek we start with the leader and walk nr
   * threads past it.
   */
cc288738c   Eric W. Biederman   [PATCH] proc: Rem...
2851
  static struct task_struct *first_tid(struct task_struct *leader,
b488893a3   Pavel Emelyanov   pid namespaces: c...
2852
  		int tid, int nr, struct pid_namespace *ns)
0bc58a910   Eric W. Biederman   [PATCH] proc: ref...
2853
  {
a872ff0cb   Oleg Nesterov   [PATCH] simplify/...
2854
  	struct task_struct *pos;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2855

cc288738c   Eric W. Biederman   [PATCH] proc: Rem...
2856
  	rcu_read_lock();
0bc58a910   Eric W. Biederman   [PATCH] proc: ref...
2857
2858
  	/* Attempt to start with the pid of a thread */
  	if (tid && (nr > 0)) {
b488893a3   Pavel Emelyanov   pid namespaces: c...
2859
  		pos = find_task_by_pid_ns(tid, ns);
a872ff0cb   Oleg Nesterov   [PATCH] simplify/...
2860
2861
  		if (pos && (pos->group_leader == leader))
  			goto found;
0bc58a910   Eric W. Biederman   [PATCH] proc: ref...
2862
  	}
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2863

0bc58a910   Eric W. Biederman   [PATCH] proc: ref...
2864
  	/* If nr exceeds the number of threads there is nothing todo */
a872ff0cb   Oleg Nesterov   [PATCH] simplify/...
2865
2866
2867
  	pos = NULL;
  	if (nr && nr >= get_nr_threads(leader))
  		goto out;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2868

a872ff0cb   Oleg Nesterov   [PATCH] simplify/...
2869
2870
  	/* If we haven't found our starting place yet start
  	 * with the leader and walk nr threads forward.
0bc58a910   Eric W. Biederman   [PATCH] proc: ref...
2871
  	 */
a872ff0cb   Oleg Nesterov   [PATCH] simplify/...
2872
2873
2874
2875
2876
2877
  	for (pos = leader; nr > 0; --nr) {
  		pos = next_thread(pos);
  		if (pos == leader) {
  			pos = NULL;
  			goto out;
  		}
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2878
  	}
a872ff0cb   Oleg Nesterov   [PATCH] simplify/...
2879
2880
2881
  found:
  	get_task_struct(pos);
  out:
cc288738c   Eric W. Biederman   [PATCH] proc: Rem...
2882
  	rcu_read_unlock();
0bc58a910   Eric W. Biederman   [PATCH] proc: ref...
2883
2884
2885
2886
2887
2888
2889
2890
2891
2892
2893
  	return pos;
  }
  
  /*
   * Find the next thread in the thread list.
   * Return NULL if there is an error or no next thread.
   *
   * The reference to the input task_struct is released.
   */
  static struct task_struct *next_tid(struct task_struct *start)
  {
c1df7fb88   Oleg Nesterov   [PATCH] cleanup n...
2894
  	struct task_struct *pos = NULL;
cc288738c   Eric W. Biederman   [PATCH] proc: Rem...
2895
  	rcu_read_lock();
c1df7fb88   Oleg Nesterov   [PATCH] cleanup n...
2896
  	if (pid_alive(start)) {
0bc58a910   Eric W. Biederman   [PATCH] proc: ref...
2897
  		pos = next_thread(start);
c1df7fb88   Oleg Nesterov   [PATCH] cleanup n...
2898
2899
2900
2901
2902
  		if (thread_group_leader(pos))
  			pos = NULL;
  		else
  			get_task_struct(pos);
  	}
cc288738c   Eric W. Biederman   [PATCH] proc: Rem...
2903
  	rcu_read_unlock();
0bc58a910   Eric W. Biederman   [PATCH] proc: ref...
2904
2905
  	put_task_struct(start);
  	return pos;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2906
  }
61a287840   Eric W. Biederman   [PATCH] proc: Rem...
2907
2908
2909
2910
2911
2912
2913
2914
  static int proc_task_fill_cache(struct file *filp, void *dirent, filldir_t filldir,
  	struct task_struct *task, int tid)
  {
  	char name[PROC_NUMBUF];
  	int len = snprintf(name, sizeof(name), "%d", tid);
  	return proc_fill_cache(filp, dirent, filldir, name, len,
  				proc_task_instantiate, task, NULL);
  }
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2915
2916
2917
  /* for the /proc/TGID/task/ directories */
  static int proc_task_readdir(struct file * filp, void * dirent, filldir_t filldir)
  {
2fddfeefe   Josef "Jeff" Sipek   [PATCH] proc: cha...
2918
  	struct dentry *dentry = filp->f_path.dentry;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2919
  	struct inode *inode = dentry->d_inode;
7d8952440   Guillaume Chazarain   [PATCH] procfs: F...
2920
  	struct task_struct *leader = NULL;
0bc58a910   Eric W. Biederman   [PATCH] proc: ref...
2921
  	struct task_struct *task;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2922
2923
  	int retval = -ENOENT;
  	ino_t ino;
0bc58a910   Eric W. Biederman   [PATCH] proc: ref...
2924
  	int tid;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2925
  	unsigned long pos = filp->f_pos;  /* avoiding "long long" filp->f_pos */
b488893a3   Pavel Emelyanov   pid namespaces: c...
2926
  	struct pid_namespace *ns;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2927

7d8952440   Guillaume Chazarain   [PATCH] procfs: F...
2928
2929
2930
2931
2932
2933
2934
2935
2936
2937
  	task = get_proc_task(inode);
  	if (!task)
  		goto out_no_task;
  	rcu_read_lock();
  	if (pid_alive(task)) {
  		leader = task->group_leader;
  		get_task_struct(leader);
  	}
  	rcu_read_unlock();
  	put_task_struct(task);
99f895518   Eric W. Biederman   [PATCH] proc: don...
2938
2939
  	if (!leader)
  		goto out_no_task;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2940
2941
2942
2943
2944
2945
2946
2947
2948
2949
2950
2951
2952
2953
2954
2955
  	retval = 0;
  
  	switch (pos) {
  	case 0:
  		ino = inode->i_ino;
  		if (filldir(dirent, ".", 1, pos, ino, DT_DIR) < 0)
  			goto out;
  		pos++;
  		/* fall through */
  	case 1:
  		ino = parent_ino(dentry);
  		if (filldir(dirent, "..", 2, pos, ino, DT_DIR) < 0)
  			goto out;
  		pos++;
  		/* fall through */
  	}
0bc58a910   Eric W. Biederman   [PATCH] proc: ref...
2956
2957
2958
  	/* f_version caches the tgid value that the last readdir call couldn't
  	 * return. lseek aka telldir automagically resets f_version to 0.
  	 */
b488893a3   Pavel Emelyanov   pid namespaces: c...
2959
  	ns = filp->f_dentry->d_sb->s_fs_info;
2b47c3611   Mathieu Desnoyers   Fix f_version typ...
2960
  	tid = (int)filp->f_version;
0bc58a910   Eric W. Biederman   [PATCH] proc: ref...
2961
  	filp->f_version = 0;
b488893a3   Pavel Emelyanov   pid namespaces: c...
2962
  	for (task = first_tid(leader, tid, pos - 2, ns);
0bc58a910   Eric W. Biederman   [PATCH] proc: ref...
2963
2964
  	     task;
  	     task = next_tid(task), pos++) {
b488893a3   Pavel Emelyanov   pid namespaces: c...
2965
  		tid = task_pid_nr_ns(task, ns);
61a287840   Eric W. Biederman   [PATCH] proc: Rem...
2966
  		if (proc_task_fill_cache(filp, dirent, filldir, task, tid) < 0) {
0bc58a910   Eric W. Biederman   [PATCH] proc: ref...
2967
2968
  			/* returning this tgid failed, save it as the first
  			 * pid for the next readir call */
2b47c3611   Mathieu Desnoyers   Fix f_version typ...
2969
  			filp->f_version = (u64)tid;
0bc58a910   Eric W. Biederman   [PATCH] proc: ref...
2970
  			put_task_struct(task);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2971
  			break;
0bc58a910   Eric W. Biederman   [PATCH] proc: ref...
2972
  		}
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2973
2974
2975
  	}
  out:
  	filp->f_pos = pos;
99f895518   Eric W. Biederman   [PATCH] proc: don...
2976
2977
  	put_task_struct(leader);
  out_no_task:
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2978
2979
  	return retval;
  }
6e66b52bf   Eric W. Biederman   [PATCH] proc: Fix...
2980
2981
2982
2983
  
  static int proc_task_getattr(struct vfsmount *mnt, struct dentry *dentry, struct kstat *stat)
  {
  	struct inode *inode = dentry->d_inode;
99f895518   Eric W. Biederman   [PATCH] proc: don...
2984
  	struct task_struct *p = get_proc_task(inode);
6e66b52bf   Eric W. Biederman   [PATCH] proc: Fix...
2985
  	generic_fillattr(inode, stat);
99f895518   Eric W. Biederman   [PATCH] proc: don...
2986
  	if (p) {
99f895518   Eric W. Biederman   [PATCH] proc: don...
2987
  		stat->nlink += get_nr_threads(p);
99f895518   Eric W. Biederman   [PATCH] proc: don...
2988
  		put_task_struct(p);
6e66b52bf   Eric W. Biederman   [PATCH] proc: Fix...
2989
2990
2991
2992
  	}
  
  	return 0;
  }
28a6d6717   Eric W. Biederman   [PATCH] proc: reo...
2993

c5ef1c42c   Arjan van de Ven   [PATCH] mark stru...
2994
  static const struct inode_operations proc_task_inode_operations = {
28a6d6717   Eric W. Biederman   [PATCH] proc: reo...
2995
2996
2997
2998
  	.lookup		= proc_task_lookup,
  	.getattr	= proc_task_getattr,
  	.setattr	= proc_setattr,
  };
00977a59b   Arjan van de Ven   [PATCH] mark stru...
2999
  static const struct file_operations proc_task_operations = {
28a6d6717   Eric W. Biederman   [PATCH] proc: reo...
3000
3001
3002
  	.read		= generic_read_dir,
  	.readdir	= proc_task_readdir,
  };